diff --git a/Perspex/Controls/ContentPresenter.cs b/Perspex/Controls/ContentPresenter.cs index b2156ef452..0f8dc7d3c9 100644 --- a/Perspex/Controls/ContentPresenter.cs +++ b/Perspex/Controls/ContentPresenter.cs @@ -82,7 +82,7 @@ namespace Perspex.Controls if (this.visualChild != null) { - ((IVisual)this.visualChild).VisualParent = this; + this.visualChild.VisualParent = this; ((Control)this.visualChild).TemplatedParent = null; } } diff --git a/Perspex/Controls/Control.cs b/Perspex/Controls/Control.cs index 6cad776216..74e1c85f73 100644 --- a/Perspex/Controls/Control.cs +++ b/Perspex/Controls/Control.cs @@ -218,7 +218,7 @@ namespace Perspex.Controls if (visual != null) { - return new DataTemplate(_ => true, x => visual); + return new DataTemplate(x => visual); } ILogical node = this; diff --git a/Perspex/Controls/DataTemplate.cs b/Perspex/Controls/DataTemplate.cs index 1a3cb139a7..03905d438a 100644 --- a/Perspex/Controls/DataTemplate.cs +++ b/Perspex/Controls/DataTemplate.cs @@ -14,6 +14,11 @@ namespace Perspex.Controls public static readonly DataTemplate Default = new DataTemplate(typeof(object), o => new TextBlock { Text = o.ToString() }); + public DataTemplate(Func build) + : this(o => true, build) + { + } + public DataTemplate(Type type, Func build) : this(o => type.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo()), build) { diff --git a/Perspex/Controls/ItemsControl.cs b/Perspex/Controls/ItemsControl.cs index a9b9dcad6b..4ac836e6f2 100644 --- a/Perspex/Controls/ItemsControl.cs +++ b/Perspex/Controls/ItemsControl.cs @@ -10,18 +10,17 @@ namespace Perspex.Controls public class ItemsControl : TemplatedControl { - private static readonly ItemsPanelTemplate defaultPanel = + private static readonly ItemsPanelTemplate DefaultPanel = new ItemsPanelTemplate(() => new StackPanel { Orientation = Orientation.Vertical }); public static readonly PerspexProperty ItemsProperty = PerspexProperty.Register("Items"); public static readonly PerspexProperty ItemsPanelProperty = - PerspexProperty.Register("ItemsPanel", defaultValue: defaultPanel); + PerspexProperty.Register("ItemsPanel", defaultValue: DefaultPanel); - public ItemsControl() - { - } + public static readonly PerspexProperty ItemTemplateProperty = + PerspexProperty.Register("ItemTemplate"); public IEnumerable Items { @@ -34,5 +33,11 @@ namespace Perspex.Controls get { return this.GetValue(ItemsPanelProperty); } set { this.SetValue(ItemsPanelProperty, value); } } + + public DataTemplate ItemTemplate + { + get { return this.GetValue(ItemTemplateProperty); } + set { this.SetValue(ItemTemplateProperty, value); } + } } } diff --git a/Perspex/Controls/ItemsPresenter.cs b/Perspex/Controls/ItemsPresenter.cs index 9ba460c2af..9278b3282e 100644 --- a/Perspex/Controls/ItemsPresenter.cs +++ b/Perspex/Controls/ItemsPresenter.cs @@ -15,10 +15,13 @@ namespace Perspex.Controls public class ItemsPresenter : Control, IVisual { public static readonly PerspexProperty ItemsProperty = - PerspexProperty.Register("Items"); + ItemsControl.ItemsProperty.AddOwner(); public static readonly PerspexProperty ItemsPanelProperty = - PerspexProperty.Register("ItemsPanel"); + ItemsControl.ItemsPanelProperty.AddOwner(); + + public static readonly PerspexProperty ItemTemplateProperty = + ItemsControl.ItemTemplateProperty.AddOwner(); private Panel panel; @@ -39,6 +42,12 @@ namespace Perspex.Controls set { this.SetValue(ItemsPanelProperty, value); } } + public DataTemplate ItemTemplate + { + get { return this.GetValue(ItemTemplateProperty); } + set { this.SetValue(ItemTemplateProperty, value); } + } + IEnumerable IVisual.ExistingVisualChildren { get { return Enumerable.Repeat(this.panel, this.panel != null ? 1 : 0); } @@ -62,6 +71,20 @@ namespace Perspex.Controls return finalSize; } + protected override DataTemplate FindDataTemplate(object content) + { + TabItem tabItem = content as TabItem; + + if (tabItem != null) + { + return new DataTemplate(_ => tabItem); + } + else + { + return this.ItemTemplate ?? base.FindDataTemplate(content); + } + } + private IEnumerable CreateItems(IEnumerable items) { if (items != null) @@ -82,6 +105,7 @@ namespace Perspex.Controls if (this.panel == null && this.ItemsPanel != null) { this.panel = this.ItemsPanel.Build(); + ((IVisual)this.panel).VisualParent = this; this.ItemsChanged(this.Items); } @@ -93,6 +117,11 @@ namespace Perspex.Controls if (this.panel != null) { this.panel.Children = new PerspexList(this.CreateItems(items)); + + if (this.panel.Children.Count > 0) + { + ((TabItem)this.panel.Children[0]).Classes.Add(":selected"); + } } } } diff --git a/Perspex/Controls/Tab.cs b/Perspex/Controls/Tab.cs deleted file mode 100644 index 537b5874be..0000000000 --- a/Perspex/Controls/Tab.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Perspex.Controls -{ - public class Tab : ContentControl - { - } -} diff --git a/Perspex/Controls/TabItem.cs b/Perspex/Controls/TabItem.cs new file mode 100644 index 0000000000..dc64b8d78b --- /dev/null +++ b/Perspex/Controls/TabItem.cs @@ -0,0 +1,15 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2013 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Controls +{ + public class TabItem : HeaderedContentControl + { + public TabItem() + { + } + } +} diff --git a/Perspex/Controls/TabStrip.cs b/Perspex/Controls/TabStrip.cs index 4041b384a8..cd5b691c19 100644 --- a/Perspex/Controls/TabStrip.cs +++ b/Perspex/Controls/TabStrip.cs @@ -12,16 +12,16 @@ namespace Perspex.Controls public class TabStrip : ItemsControl { - private static readonly DataTemplate TabTemplate = new DataTemplate(_ => true, CreateTab); + private static readonly ItemsPanelTemplate PanelTemplate = new ItemsPanelTemplate( + () => new StackPanel()); - protected override DataTemplate FindDataTemplate(object content) - { - return TabTemplate; - } + private static readonly DataTemplate TabTemplate = new DataTemplate( + o => new TabItem { Content = o }); - private static IVisual CreateTab(object o) + static TabStrip() { - return new Tab { Content = o }; + ItemsPanelProperty.OverrideDefaultValue(typeof(TabStrip), PanelTemplate); + ItemTemplateProperty.OverrideDefaultValue(typeof(TabStrip), TabTemplate); } } } diff --git a/Perspex/Diagnostics/Debug.cs b/Perspex/Diagnostics/Debug.cs index 33942f9137..cd9a08e2e2 100644 --- a/Perspex/Diagnostics/Debug.cs +++ b/Perspex/Diagnostics/Debug.cs @@ -36,10 +36,10 @@ namespace Perspex.Diagnostics builder.Append(" | "); builder.Append(value.Item1.Name); builder.Append(" = "); - builder.Append(value.Item2); - builder.Append(" ("); + builder.Append(value.Item2 ?? "(null)"); + builder.Append(" ["); builder.Append(value.Item3); - builder.AppendLine(")"); + builder.AppendLine("]"); } } diff --git a/Perspex/Layout/Layoutable.cs b/Perspex/Layout/Layoutable.cs index 8b510cde3b..9d2a0a86e5 100644 --- a/Perspex/Layout/Layoutable.cs +++ b/Perspex/Layout/Layoutable.cs @@ -217,7 +217,7 @@ namespace Perspex.Layout { if (this.IsVisible) { - Size measuredSize = this.MeasureOverride(availableSize.Deflate(this.Margin)); + Size measuredSize = this.MeasureOverride(availableSize.Deflate(this.Margin)).Inflate(this.Margin); double width = (this.Width > 0) ? this.Width : measuredSize.Width; double height = (this.Height > 0) ? this.Height : measuredSize.Height; diff --git a/Perspex/Media/Brushes.cs b/Perspex/Media/Brushes.cs index 261fcc98ca..fbe57a9909 100644 --- a/Perspex/Media/Brushes.cs +++ b/Perspex/Media/Brushes.cs @@ -14,6 +14,7 @@ namespace Perspex.Media static Brushes() { Black = new SolidColorBrush(0xff000000); + Gray = new SolidColorBrush(0xff808080); Red = new SolidColorBrush(0xffff0000); } @@ -23,6 +24,12 @@ namespace Perspex.Media private set; } + public static SolidColorBrush Gray + { + get; + private set; + } + public static SolidColorBrush Red { get; diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj index 402e7e426b..80e46c870a 100644 --- a/Perspex/Perspex.csproj +++ b/Perspex/Perspex.csproj @@ -71,7 +71,7 @@ - + @@ -133,7 +133,7 @@ - + diff --git a/Perspex/Styling/Selector.cs b/Perspex/Styling/Selector.cs index 729fa78287..43d5b8da0e 100644 --- a/Perspex/Styling/Selector.cs +++ b/Perspex/Styling/Selector.cs @@ -82,8 +82,7 @@ namespace Perspex.Styling while (selector != null) { - if ((selector.InTemplate && control.TemplatedParent == null) || - (!selector.InTemplate && control.TemplatedParent != null)) + if (selector.InTemplate && control.TemplatedParent == null) { inputs.Add(Observable.Return(false)); } diff --git a/Perspex/Styling/Style.cs b/Perspex/Styling/Style.cs index 8d2d603926..f8b9fc1546 100644 --- a/Perspex/Styling/Style.cs +++ b/Perspex/Styling/Style.cs @@ -52,5 +52,10 @@ namespace Perspex.Styling } } } + + public override string ToString() + { + return "Style: " + this.Selector.ToString(); + } } } diff --git a/Perspex/Themes/Default/ContentControlStyle.cs b/Perspex/Themes/Default/ContentControlStyle.cs index 81aff1e0c6..00feac460b 100644 --- a/Perspex/Themes/Default/ContentControlStyle.cs +++ b/Perspex/Themes/Default/ContentControlStyle.cs @@ -21,7 +21,7 @@ namespace Perspex.Themes.Default { Setters = new[] { - new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), + new Setter(ContentControl.TemplateProperty, ControlTemplate.Create(this.Template)), }, }, }); diff --git a/Perspex/Themes/Default/DefaultTheme.cs b/Perspex/Themes/Default/DefaultTheme.cs index 256d8acdee..2364704493 100644 --- a/Perspex/Themes/Default/DefaultTheme.cs +++ b/Perspex/Themes/Default/DefaultTheme.cs @@ -17,7 +17,7 @@ namespace Perspex.Themes.Default this.Add(new ContentControlStyle()); this.Add(new ItemsControlStyle()); this.Add(new TextBoxStyle()); - this.Add(new TabStyle()); + this.Add(new TabItemStyle()); this.Add(new TabStripStyle()); } } diff --git a/Perspex/Themes/Default/ItemsControlStyle.cs b/Perspex/Themes/Default/ItemsControlStyle.cs index 396c6f7802..7cdb01140a 100644 --- a/Perspex/Themes/Default/ItemsControlStyle.cs +++ b/Perspex/Themes/Default/ItemsControlStyle.cs @@ -32,6 +32,7 @@ namespace Perspex.Themes.Default { [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty], [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty], + [~ItemsPresenter.ItemTemplateProperty] = control[~ItemsControl.ItemTemplateProperty], }; } } diff --git a/Perspex/Themes/Default/TabItemStyle.cs b/Perspex/Themes/Default/TabItemStyle.cs new file mode 100644 index 0000000000..dd0976d6a0 --- /dev/null +++ b/Perspex/Themes/Default/TabItemStyle.cs @@ -0,0 +1,48 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Themes.Default +{ + using System.Linq; + using Perspex.Controls; + using Perspex.Media; + using Perspex.Styling; + + public class TabItemStyle : Styles + { + public TabItemStyle() + { + this.AddRange(new[] + { + new Style(x => x.OfType()) + { + Setters = new[] + { + new Setter(TextBox.FontSizeProperty, 28.7), + new Setter(Control.ForegroundProperty, Brushes.Gray), + new Setter(Control.MarginProperty, new Thickness(8, 0)), + new Setter(TabItem.TemplateProperty, ControlTemplate.Create(this.Template)), + }, + }, + new Style(x => x.OfType().Class(":selected")) + { + Setters = new[] + { + new Setter(Control.ForegroundProperty, Brushes.Black), + }, + }, + }); + } + + private Control Template(TabItem control) + { + return new ContentPresenter + { + [~ContentPresenter.ContentProperty] = control[~TabItem.HeaderProperty], + }; + } + } +} diff --git a/Perspex/Themes/Default/TabStripStyle.cs b/Perspex/Themes/Default/TabStripStyle.cs index e7ed4176fe..fde473c714 100644 --- a/Perspex/Themes/Default/TabStripStyle.cs +++ b/Perspex/Themes/Default/TabStripStyle.cs @@ -8,7 +8,6 @@ namespace Perspex.Themes.Default { using System.Linq; using Perspex.Controls; - using Perspex.Media; using Perspex.Styling; public class TabStripStyle : Styles @@ -21,7 +20,14 @@ namespace Perspex.Themes.Default { Setters = new[] { - new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), + new Setter(TabStrip.TemplateProperty, ControlTemplate.Create(this.Template)), + }, + }, + new Style(x => x.OfType().Template().OfType()) + { + Setters = new[] + { + new Setter(StackPanel.OrientationProperty, Orientation.Horizontal), }, }, }); @@ -31,8 +37,9 @@ namespace Perspex.Themes.Default { return new ItemsPresenter { - ItemsPanel = new ItemsPanelTemplate(() => new StackPanel()), [~ItemsPresenter.ItemsProperty] = control[~ItemsControl.ItemsProperty], + [~ItemsPresenter.ItemsPanelProperty] = control[~ItemsControl.ItemsPanelProperty], + [~ItemsPresenter.ItemTemplateProperty] = control[~ItemsControl.ItemTemplateProperty], }; } } diff --git a/Perspex/Themes/Default/TabStyle.cs b/Perspex/Themes/Default/TabStyle.cs deleted file mode 100644 index f0a6be8e96..0000000000 --- a/Perspex/Themes/Default/TabStyle.cs +++ /dev/null @@ -1,42 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright 2014 MIT Licence. See licence.md for more information. -// -// ----------------------------------------------------------------------- - -namespace Perspex.Themes.Default -{ - using System.Linq; - using Perspex.Controls; - using Perspex.Media; - using Perspex.Styling; - - public class TabStyle : Styles - { - public TabStyle() - { - this.AddRange(new[] - { - new Style(x => x.OfType()) - { - Setters = new[] - { - new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), - }, - }, - }); - } - - private Control Template(Tab control) - { - return new Border - { - Background = Brushes.Red, - Content = new ContentPresenter - { - [~ContentPresenter.ContentProperty] = control[~Tab.ContentProperty], - } - }; - } - } -} diff --git a/Perspex/Themes/Default/TextBoxStyle.cs b/Perspex/Themes/Default/TextBoxStyle.cs index 574eae6261..1ff135089e 100644 --- a/Perspex/Themes/Default/TextBoxStyle.cs +++ b/Perspex/Themes/Default/TextBoxStyle.cs @@ -23,7 +23,7 @@ namespace Perspex.Themes.Default { Setters = new[] { - new Setter(Button.TemplateProperty, ControlTemplate.Create(this.Template)), + new Setter(TextBox.TemplateProperty, ControlTemplate.Create(this.Template)), new Setter(TextBox.BorderBrushProperty, new SolidColorBrush(0xff707070)), new Setter(TextBox.BorderThicknessProperty, 2.0), }, diff --git a/TestApplication/Program.cs b/TestApplication/Program.cs index 3f2cf9a9e0..f1eca4227c 100644 --- a/TestApplication/Program.cs +++ b/TestApplication/Program.cs @@ -74,8 +74,14 @@ namespace TestApplication { Items = new[] { - "Foo", - "Bar", + new TabItem + { + Header = "Tab 1", + }, + new TabItem + { + Header = "Tab 2", + }, } } }