Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow better SegmentedButton theming #2450

Merged
merged 1 commit into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion src/Eto.Wpf/Forms/Controls/ButtonHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public int ImageLabelSpacing
protected override void Initialize()
{
Control.Click += (sender, e) => Callback.OnClick(Widget, EventArgs.Empty);
Control.Padding = new sw.Thickness(2);
LabelPart = new WpfLabel
{
IsHitTestVisible = false,
Expand Down
27 changes: 19 additions & 8 deletions src/Eto.Wpf/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
using Eto.Shared.Forms;
using System.Linq;
using System.Diagnostics;

namespace Eto.Wpf
{
public class Platform : Eto.Platform
Expand All @@ -38,16 +37,28 @@ static Platform()

Style.Add<ThemedSegmentedButtonHandler>(null, h =>
{
h.Control.Styles.Add<ToggleButtonHandler>(null, tb =>
h.Widget.Items.CollectionChanged += (sender, e) =>
{
if (tb.Widget.Parent is TableLayout tl && tl.Rows.Count > 0 && tl.Spacing.Width == 0)
for (int i = 0; i < h.Widget.Items.Count; i++)
{
var isFirst = ReferenceEquals(tl.Rows[0].Cells[0].Control, tb.Widget);
var thickness = tb.Control.BorderThickness;
thickness.Left = isFirst ? thickness.Right : 0;
tb.Control.BorderThickness = thickness;
SegmentedItem item = h.Widget.Items[i];
if (item.ControlObject is Control control)
{
var native = control.ToNative();
if (native != null)
{
WpfProperties.SetEtoStyle(native, "SegmentedButton");
if (i == 0)
WpfProperties.SetEtoModifier(native, "first");
else if (i == h.Widget.Items.Count - 1)
WpfProperties.SetEtoModifier(native, "last");
else
native.ClearValue(WpfProperties.EtoModifierProperty);
}
}

}
});
};
});
}

Expand Down
25 changes: 25 additions & 0 deletions src/Eto.Wpf/WpfProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using sw = System.Windows;

namespace Eto.Wpf
{
public static class WpfProperties
{
public static string GetEtoStyle(sw.DependencyObject obj) => (string)obj.GetValue(EtoStyleProperty);
public static void SetEtoStyle(sw.DependencyObject obj, string value) => obj.SetValue(EtoStyleProperty, value);

public static readonly sw.DependencyProperty EtoStyleProperty =
sw.DependencyProperty.RegisterAttached("EtoStyle", typeof(string), typeof(WpfProperties), new sw.UIPropertyMetadata(string.Empty));



public static string GetEtoModifier(sw.DependencyObject obj) => (string)obj.GetValue(EtoModifierProperty);
public static void SetEtoModifier(sw.DependencyObject obj, string value) => obj.SetValue(EtoModifierProperty, value);

public static readonly sw.DependencyProperty EtoModifierProperty =
sw.DependencyProperty.RegisterAttached("EtoModifier", typeof(string), typeof(WpfProperties), new sw.UIPropertyMetadata(string.Empty));

}
}
51 changes: 51 additions & 0 deletions src/Eto.Wpf/themes/generic.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:r="clr-namespace:Eto.Wpf.CustomControls.TreeGridView"
xmlns:efc="clr-namespace:Eto.Wpf.Forms.Controls"
xmlns:e="clr-namespace:Eto.Wpf"
xmlns:s="clr-namespace:System;assembly=mscorlib">

<ResourceDictionary.MergedDictionaries>
Expand Down Expand Up @@ -94,5 +95,55 @@
</Setter>
</Style.Setters>
</Style>

<Style TargetType="efc:EtoButton">
<Setter Property="Padding" Value="2" />
</Style>

<Style TargetType="efc:EtoToggleButton">
<Setter Property="Padding" Value="2" />
<Style.Resources>
<Style TargetType="Border">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(e:WpfProperties.EtoStyle), RelativeSource={RelativeSource AncestorType={x:Type efc:EtoToggleButton}}}" Value="SegmentedButton" />
<Condition Binding="{Binding Path=(e:WpfProperties.EtoModifier), RelativeSource={RelativeSource AncestorType={x:Type efc:EtoToggleButton}}}" Value="first" />
</MultiDataTrigger.Conditions>
<Setter Property="CornerRadius" Value="4,0,0,4" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(e:WpfProperties.EtoStyle), RelativeSource={RelativeSource AncestorType={x:Type efc:EtoToggleButton}}}" Value="SegmentedButton" />
<Condition Binding="{Binding Path=(e:WpfProperties.EtoModifier), RelativeSource={RelativeSource AncestorType={x:Type efc:EtoToggleButton}}}" Value="last" />
</MultiDataTrigger.Conditions>
<Setter Property="CornerRadius" Value="0,4,4,0" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
<Style.Triggers>
<Trigger Property="e:WpfProperties.EtoStyle" Value="SegmentedButton">
<Setter Property="BorderThickness" Value=".5,1" />
<Setter Property="Padding" Value="4,2" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="e:WpfProperties.EtoStyle" Value="SegmentedButton"/>
<Condition Property="e:WpfProperties.EtoModifier" Value="first"/>
</MultiTrigger.Conditions>
<Setter Property="BorderThickness" Value="1,1,.5,1" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="e:WpfProperties.EtoStyle" Value="SegmentedButton"/>
<Condition Property="e:WpfProperties.EtoModifier" Value="last"/>
</MultiTrigger.Conditions>
<Setter Property="BorderThickness" Value=".5,1,1,1" />
</MultiTrigger>

</Style.Triggers>
</Style>


</ResourceDictionary>
2 changes: 2 additions & 0 deletions src/Eto/Forms/SegmentedButton/SegmentedButton.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ static SegmentedButton()
public SegmentedButton()
{
Items = new SegmentedItemCollection(this);
Initialize();
}

/// <inheritdoc />
Expand Down Expand Up @@ -328,6 +329,7 @@ public new interface ICallback : Control.ICallback
/// <summary>
/// Handler interface for <see cref="SegmentedButton"/>.
/// </summary>
[AutoInitialize(false)]
public new interface IHandler : Control.IHandler
{
/// <summary>
Expand Down
8 changes: 5 additions & 3 deletions src/Eto/Forms/SegmentedButton/SegmentedItemCollection.cs
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace Eto.Forms;

/// <summary>
/// Collection of <see cref="SegmentedItem"/> objects for the <see cref="SegmentedButton"/>.
/// </summary>
public class SegmentedItemCollection : Collection<SegmentedItem>
public class SegmentedItemCollection : ObservableCollection<SegmentedItem>
{
SegmentedButton Parent { get; }
SegmentedButton.IHandler Handler => Parent.Handler as SegmentedButton.IHandler;
Expand Down Expand Up @@ -64,7 +65,8 @@ protected override void RemoveItem(int index)
/// <param name="item">Item to replace with.</param>
protected override void SetItem(int index, SegmentedItem item)
{
this[index].Parent = null;
var oldItem = this[index];
oldItem.Parent = null;
base.SetItem(index, item);
Handler.SetItem(index, item);
item.Parent = Parent;
Expand Down
40 changes: 20 additions & 20 deletions src/Eto/Forms/ThemedControls/ThemedSegmentedButtonHandler.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ public class ThemedMenuSegmentedItemHandler : ThemedSegmentedItemHandler<MenuSeg
/// <summary>
/// Delay for the menu to show when the mouse is down and <see cref="CanSelect"/> is <c>true</c>.
/// </summary>
public TimeSpan MenuDelay { get; set; } = TimeSpan.FromSeconds(0.5);
public virtual TimeSpan MenuDelay { get; set; } = TimeSpan.FromSeconds(0.5);

/// <summary>
/// Gets or sets the indicator to show to the right of the text.
/// </summary>
/// <value>The menu indicator.</value>
public string MenuIndicator
public virtual string MenuIndicator
{
get => menuIndicator;
set
Expand All @@ -36,10 +36,10 @@ public string MenuIndicator
}

/// <inheritdoc/>
public ContextMenu Menu { get; set; }
public virtual ContextMenu Menu { get; set; }

/// <inheritdoc/>
public bool CanSelect { get; set; }
public virtual bool CanSelect { get; set; }

/// <inheritdoc/>
public override string Text
Expand Down Expand Up @@ -125,13 +125,13 @@ public abstract class ThemedSegmentedItemHandler<TWidget, TCallback> : WidgetHan
protected ThemedSegmentedButtonHandler ParentHandler => Widget.Parent?.Handler as ThemedSegmentedButtonHandler;

/// <inheritdoc/>
public bool Enabled { get => Control.Enabled; set => Control.Enabled = value; }
public virtual bool Enabled { get => Control.Enabled; set => Control.Enabled = value; }
/// <inheritdoc/>
public bool Visible { get => Control.Visible; set => Control.Visible = value; }
public virtual bool Visible { get => Control.Visible; set => Control.Visible = value; }
/// <inheritdoc/>
public string ToolTip { get => Control.ToolTip; set => Control.ToolTip = value; }
public virtual string ToolTip { get => Control.ToolTip; set => Control.ToolTip = value; }
/// <inheritdoc/>
public int Width { get => Control.Width; set => Control.Width = value; }
public virtual int Width { get => Control.Width; set => Control.Width = value; }
/// <inheritdoc/>
public virtual string Text
{
Expand All @@ -143,9 +143,9 @@ public virtual string Text
}
}
/// <inheritdoc/>
public Image Image { get => Control.Image; set => Control.Image = value; }
public virtual Image Image { get => Control.Image; set => Control.Image = value; }
/// <inheritdoc/>
public bool Selected
public virtual bool Selected
{
get => Control.Checked;
set
Expand Down Expand Up @@ -224,7 +224,7 @@ public class ThemedSegmentedButtonHandler : ThemedControlHandler<Panel, Segmente
protected override Panel CreateControl() => new Panel();

/// <inheritdoc/>
public SegmentedSelectionMode SelectionMode
public virtual SegmentedSelectionMode SelectionMode
{
get => selectionMode;
set
Expand All @@ -247,10 +247,10 @@ public SegmentedSelectionMode SelectionMode
/// Gets or sets the spacing between the buttons
/// </summary>
/// <value>The spacing between the buttons.</value>
public int Spacing { get; set; }
public virtual int Spacing { get; set; }

/// <inheritdoc/>
public int SelectedIndex
public virtual int SelectedIndex
{
get
{
Expand All @@ -273,7 +273,7 @@ public int SelectedIndex
}

/// <inheritdoc/>
public IEnumerable<int> SelectedIndexes
public virtual IEnumerable<int> SelectedIndexes
{
get
{
Expand Down Expand Up @@ -309,7 +309,7 @@ public IEnumerable<int> SelectedIndexes
}

/// <inheritdoc/>
public void ClearItems()
public virtual void ClearItems()
{
var hasSelected = SelectedIndex != -1;
CreateTable(false);
Expand All @@ -322,7 +322,7 @@ public void ClearItems()
TableCell GetCell(SegmentedItem item) => new TableCell(GetControl(item));

/// <inheritdoc/>
public void ClearSelection()
public virtual void ClearSelection()
{
suppressSelectionChanged++;
var wasSelected = false;
Expand All @@ -338,7 +338,7 @@ public void ClearSelection()
}

/// <inheritdoc/>
public void InsertItem(int index, SegmentedItem item)
public virtual void InsertItem(int index, SegmentedItem item)
{
var isSelected = item.Selected;
CreateTable(false);
Expand All @@ -354,7 +354,7 @@ public void InsertItem(int index, SegmentedItem item)
}

/// <inheritdoc/>
public void RemoveItem(int index, SegmentedItem item)
public virtual void RemoveItem(int index, SegmentedItem item)
{
var wasSelected = item.Selected;
CreateTable(false);
Expand All @@ -363,7 +363,7 @@ public void RemoveItem(int index, SegmentedItem item)
}

/// <inheritdoc/>
public void SelectAll()
public virtual void SelectAll()
{
suppressSelectionChanged++;
bool wasChanged = false;
Expand All @@ -378,7 +378,7 @@ public void SelectAll()
}

/// <inheritdoc/>
public void SetItem(int index, SegmentedItem item)
public virtual void SetItem(int index, SegmentedItem item)
{
var wasSelected = Widget.Items[index].Selected;
var isSelected = item.Selected;
Expand Down