feat: Add TimePicker and Clock components, styles, demos.
This commit is contained in:
1 parent
d32f4b66c0
commit
7198c9c2ae
15 files changed
+2028
-4
No files matched your search
@@ -8,7 +8,7 @@
|
||||
[ "Button", "ButtonDemo", "Brush.ButtonClick", "", "" ],
|
||||
[ "RepeatButton", "RepeatButtonDemo", "Brush.RepeatButton", "", "" ],
|
||||
[ "ToggleButton", "ToggleButtonDemo", "Brush.Toggle", "", "" ],
|
||||
[ "ToggleSwitch", "ToggleSwitchDemo", "Brush.Toggle", "1", "" ],
|
||||
[ "ToggleSwitch", "ToggleSwitchDemo", "Brush.Toggle", "", "" ],
|
||||
[ "RadioButton", "RadioButtonDemo", "Brush.RadioButton", "", "" ],
|
||||
[ "HyperlinkButton", "HyperlinkButtonDemo", "Brush.Hyperlink", "", "" ],
|
||||
[ "CheckBox", "CheckBoxDemo", "Brush.CheckBoxChecked", "", "" ],
|
||||
@@ -22,6 +22,8 @@
|
||||
[ "Expander", "ExpanderDemo", "Brush.Expander", "", "" ],
|
||||
[ "ProgressBar", "NativeProgressBarDemo", "Brush.ProgressBar", "", "" ],
|
||||
[ "Calendar", "CalendarDemo", "Brush.Calendar", "", "" ],
|
||||
[ "DatePicker", "DatePickerDemo", "Brush.Calendar", "", "" ],
|
||||
[ "TimePicker", "TimePickerDemo", "Brush.Calendar", "", "" ],
|
||||
[ "TabControl", "NativeTabControlDemo", "Brush.TabPage", "", "" ],
|
||||
[ "TreeView", "TreeViewDemo", "Brush.TreeView", "", "" ],
|
||||
[ "ListBox", "ListBoxDemo", "Brush.ListBox", "", "" ],
|
||||
@@ -39,13 +41,13 @@
|
||||
[ "Gravatar", "GravatarDemo", "Brush.User", "", "DataDisplay" ],
|
||||
[ "ButtonGroup", "ButtonGroupDemo", "Brush.ButtonGroup", "", "Button" ],
|
||||
[ "Card", "CardDemo", "Brush.ContactCard", "", "DataDisplay" ],
|
||||
[ "ElementGroup", "ElementGroupDemo", "Brush.ButtonGroup", "1", "Layout" ],
|
||||
[ "ElementGroup", "ElementGroupDemo", "Brush.ButtonGroup", "", "Layout" ],
|
||||
[ "CirclePanel", "CirclePanelDemo", "Brush.ColorWheel", "", "Layout" ],
|
||||
[ "Grid", "GridDemo", "Brush.GridPane", "", "Layout" ],
|
||||
[ "FlexPanel", "FlexPanelDemo", "Brush.FlowLayoutPanel", "1", "Layout" ],
|
||||
[ "FlexPanel", "FlexPanelDemo", "Brush.FlowLayoutPanel", "", "Layout" ],
|
||||
[ "WaterfallPanel", "WaterfallPanelDemo", "Brush.Panel", "", "Layout" ],
|
||||
[ "HoneycombPanel", "HoneycombPanelDemo", "Brush.PolygonHexagon", "", "Layout" ],
|
||||
[ "UniformSpacingPanel", "UniformSpacingPanelDemo", "Brush.IncreaseHorizontalSpacing", "1", "Layout" ]
|
||||
[ "UniformSpacingPanel", "UniformSpacingPanelDemo", "Brush.IncreaseHorizontalSpacing", "", "Layout" ]
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,89 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
x:Class="HandyControlDemo.UserControl.DatePickerDemo"
|
||||
Background="{DynamicResource RegionBrush}">
|
||||
<TransitioningContentControl>
|
||||
<ScrollViewer>
|
||||
<hc:UniformSpacingPanel Spacing="32"
|
||||
Margin="32"
|
||||
ChildWrapping="Wrap">
|
||||
<StackPanel>
|
||||
<CalendarDatePicker hc:InfoElement.ShowClearButton="True"
|
||||
SelectedDate="{x:Static system:DateTime.Now}" />
|
||||
<CalendarDatePicker Margin="0,16,0,0"
|
||||
IsEnabled="False"
|
||||
SelectedDate="{x:Static system:DateTime.Now}" />
|
||||
|
||||
<CalendarDatePicker hc:InfoElement.ShowClearButton="True"
|
||||
SelectedDate="{x:Static system:DateTime.Now}"
|
||||
hc:TitleElement.Title="This is the title"
|
||||
Theme="{StaticResource CalendarDatePickerExtend}"
|
||||
Margin="0,32,0,0" />
|
||||
<CalendarDatePicker SelectedDate="{x:Static system:DateTime.Now}"
|
||||
Watermark="Please enter content"
|
||||
hc:TitleElement.Title="This item must be filled in"
|
||||
Theme="{StaticResource CalendarDatePickerExtend}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0" />
|
||||
|
||||
<CalendarDatePicker hc:InfoElement.ShowClearButton="True"
|
||||
SelectedDate="{x:Static system:DateTime.Now}"
|
||||
Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
hc:TitleElement.Title="The title is on the left"
|
||||
Theme="{StaticResource CalendarDatePickerExtend}"
|
||||
Margin="0,32,0,0" />
|
||||
<CalendarDatePicker Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Watermark="Please enter content"
|
||||
hc:TitleElement.Title="The title is on the left"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Theme="{StaticResource CalendarDatePickerExtend}"
|
||||
Margin="0,16,0,0" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<CalendarDatePicker hc:InfoElement.ShowClearButton="True"
|
||||
SelectedDate="{x:Static system:DateTime.Now}"
|
||||
Theme="{StaticResource CalendarDatePicker.Small}" />
|
||||
<CalendarDatePicker Margin="0,16,0,0"
|
||||
IsEnabled="False"
|
||||
SelectedDate="{x:Static system:DateTime.Now}"
|
||||
Theme="{StaticResource CalendarDatePicker.Small}" />
|
||||
|
||||
<CalendarDatePicker hc:InfoElement.ShowClearButton="True"
|
||||
SelectedDate="{x:Static system:DateTime.Now}"
|
||||
hc:TitleElement.Title="This is the title"
|
||||
Theme="{StaticResource CalendarDatePickerExtend.Small}"
|
||||
Margin="0,32,0,0" />
|
||||
<CalendarDatePicker SelectedDate="{x:Static system:DateTime.Now}"
|
||||
Watermark="Please enter content"
|
||||
hc:TitleElement.Title="This item must be filled in"
|
||||
Theme="{StaticResource CalendarDatePickerExtend.Small}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0" />
|
||||
|
||||
<CalendarDatePicker hc:InfoElement.ShowClearButton="True"
|
||||
SelectedDate="{x:Static system:DateTime.Now}"
|
||||
Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
hc:TitleElement.Title="The title is on the left"
|
||||
Theme="{StaticResource CalendarDatePickerExtend.Small}"
|
||||
Margin="0,32,0,0" />
|
||||
<CalendarDatePicker Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Watermark="Please enter content"
|
||||
hc:TitleElement.Title="The title is on the left"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Theme="{StaticResource CalendarDatePickerExtend.Small}"
|
||||
Margin="0,16,0,0" />
|
||||
</StackPanel>
|
||||
</hc:UniformSpacingPanel>
|
||||
</ScrollViewer>
|
||||
</TransitioningContentControl>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace HandyControlDemo.UserControl;
|
||||
|
||||
public partial class DatePickerDemo : Avalonia.Controls.UserControl
|
||||
{
|
||||
public DatePickerDemo()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
|
||||
x:Class="HandyControlDemo.UserControl.TimePickerDemo"
|
||||
Background="{DynamicResource RegionBrush}">
|
||||
<TransitioningContentControl>
|
||||
<ScrollViewer>
|
||||
<hc:UniformSpacingPanel Spacing="32"
|
||||
Margin="32"
|
||||
ChildWrapping="Wrap">
|
||||
<StackPanel>
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True" />
|
||||
<hc:TimePicker Margin="0,16,0,0"
|
||||
IsEnabled="False" />
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Theme="{StaticResource TimePickerExtend}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr1}"
|
||||
Margin="0,32,0,0" />
|
||||
<hc:TimePicker Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr2}"
|
||||
Theme="{StaticResource TimePickerExtend}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0" />
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Theme="{StaticResource TimePickerExtend}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Margin="0,32,0,0" />
|
||||
<hc:TimePicker Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Theme="{StaticResource TimePickerExtend}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Theme="{StaticResource TimePickerPlus}">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
<hc:TimePicker Margin="0,16,0,0"
|
||||
IsEnabled="False"
|
||||
Theme="{StaticResource TimePickerPlus}" />
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Theme="{StaticResource TimePickerPlus}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr1}"
|
||||
Margin="0,32,0,0" />
|
||||
<hc:TimePicker Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr2}"
|
||||
Theme="{StaticResource TimePickerPlus}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0" />
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Theme="{StaticResource TimePickerPlus}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Margin="0,32,0,0" />
|
||||
<hc:TimePicker Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Theme="{StaticResource TimePickerPlus}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0" />
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Theme="{StaticResource TimePicker.Small}">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
<hc:TimePicker Margin="0,16,0,0"
|
||||
IsEnabled="False"
|
||||
Theme="{StaticResource TimePicker.Small}">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Theme="{StaticResource TimePickerExtend.Small}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr1}"
|
||||
Margin="0,32,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
<hc:TimePicker Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr2}"
|
||||
Theme="{StaticResource TimePickerExtend.Small}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Theme="{StaticResource TimePickerExtend.Small}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Margin="0,32,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
<hc:TimePicker Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Theme="{StaticResource TimePickerExtend.Small}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Theme="{StaticResource TimePickerPlus.Small}">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Margin="0,16,0,0"
|
||||
Theme="{StaticResource TimePickerPlus.Small}">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Theme="{StaticResource TimePickerPlus.Small}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr1}"
|
||||
Margin="0,32,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
<hc:TimePicker Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr2}"
|
||||
Theme="{StaticResource TimePickerPlus.Small}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
|
||||
<hc:TimePicker hc:InfoElement.ShowClearButton="True"
|
||||
Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Theme="{StaticResource TimePickerPlus.Small}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Margin="0,32,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
<hc:TimePicker Width="380"
|
||||
hc:TitleElement.TitleWidth="140"
|
||||
hc:TitleElement.TitlePlacement="Left"
|
||||
Watermark="{x:Static langs:Lang.PlsEnterContent}"
|
||||
hc:TitleElement.Title="{x:Static langs:Lang.TitleDemoStr3}"
|
||||
Theme="{StaticResource TimePickerPlus.Small}"
|
||||
hc:InfoElement.Necessary="True"
|
||||
Margin="0,16,0,0">
|
||||
<hc:TimePicker.Clock>
|
||||
<hc:ListClock />
|
||||
</hc:TimePicker.Clock>
|
||||
</hc:TimePicker>
|
||||
</StackPanel>
|
||||
</hc:UniformSpacingPanel>
|
||||
</ScrollViewer>
|
||||
</TransitioningContentControl>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace HandyControlDemo.UserControl;
|
||||
|
||||
public partial class TimePickerDemo : Avalonia.Controls.UserControl
|
||||
{
|
||||
public TimePickerDemo()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,403 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[TemplatePart(ElementRoot, typeof(Grid))]
|
||||
[TemplatePart(ElementTextBox, typeof(TextBox))]
|
||||
[TemplatePart(ElementButton, typeof(Button))]
|
||||
[TemplatePart(ElementPopup, typeof(Popup))]
|
||||
[PseudoClasses(":dropdownopen")]
|
||||
public class TimePicker : TemplatedControl
|
||||
{
|
||||
private const string ElementRoot = "PART_Root";
|
||||
private const string ElementTextBox = "PART_TextBox";
|
||||
private const string ElementButton = "PART_Button";
|
||||
private const string ElementPopup = "PART_Popup";
|
||||
|
||||
private string? _defaultText;
|
||||
private Button? _dropDownButton;
|
||||
private Popup? _popup;
|
||||
private TextBox? _textBox;
|
||||
private DateTime? _originalSelectedTime;
|
||||
private bool _isHandlerSuspendedText;
|
||||
|
||||
public event EventHandler<DateTime?>? SelectedTimeChanged;
|
||||
public event EventHandler? ClockClosed;
|
||||
public event EventHandler? ClockOpened;
|
||||
|
||||
public static readonly StyledProperty<string> TimeFormatProperty =
|
||||
AvaloniaProperty.Register<TimePicker, string>(nameof(TimeFormat), "HH:mm:ss");
|
||||
|
||||
public string TimeFormat
|
||||
{
|
||||
get => GetValue(TimeFormatProperty);
|
||||
set => SetValue(TimeFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DateTime> DisplayTimeProperty =
|
||||
AvaloniaProperty.Register<TimePicker, DateTime>(nameof(DisplayTime), DateTime.Now,
|
||||
defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
public DateTime DisplayTime
|
||||
{
|
||||
get => GetValue(DisplayTimeProperty);
|
||||
set => SetValue(DisplayTimeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsDropDownOpenProperty =
|
||||
AvaloniaProperty.Register<TimePicker, bool>(nameof(IsDropDownOpen),
|
||||
defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
public bool IsDropDownOpen
|
||||
{
|
||||
get => GetValue(IsDropDownOpenProperty);
|
||||
set => SetValue(IsDropDownOpenProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DateTime?> SelectedTimeProperty =
|
||||
AvaloniaProperty.Register<TimePicker, DateTime?>(nameof(SelectedTime),
|
||||
defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
public DateTime? SelectedTime
|
||||
{
|
||||
get => GetValue(SelectedTimeProperty);
|
||||
set => SetValue(SelectedTimeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string> TextProperty =
|
||||
AvaloniaProperty.Register<TimePicker, string>(nameof(Text), string.Empty);
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string?> WatermarkProperty =
|
||||
AvaloniaProperty.Register<TimePicker, string?>(nameof(Watermark));
|
||||
|
||||
public string? Watermark
|
||||
{
|
||||
get => GetValue(WatermarkProperty);
|
||||
set => SetValue(WatermarkProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ClockBase?> ClockProperty =
|
||||
AvaloniaProperty.Register<TimePicker, ClockBase?>(nameof(Clock));
|
||||
|
||||
public ClockBase? Clock
|
||||
{
|
||||
get => GetValue(ClockProperty);
|
||||
set => SetValue(ClockProperty, value);
|
||||
}
|
||||
|
||||
static TimePicker()
|
||||
{
|
||||
IsDropDownOpenProperty.Changed.AddClassHandler<TimePicker>((o, e) => o.OnIsDropDownOpenChanged(e));
|
||||
SelectedTimeProperty.Changed.AddClassHandler<TimePicker>((o, e) => o.OnSelectedTimePropertyChanged(e));
|
||||
TextProperty.Changed.AddClassHandler<TimePicker>((o, e) => o.OnTextPropertyChanged(e));
|
||||
ClockProperty.Changed.AddClassHandler<TimePicker>((o, e) => o.OnClockChanged(e));
|
||||
DisplayTimeProperty.Changed.AddClassHandler<TimePicker>((o, e) => o.OnDisplayTimePropertyChanged(e));
|
||||
}
|
||||
|
||||
public TimePicker()
|
||||
{
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
|
||||
private void OnIsDropDownOpenChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
var newValue = (bool) (e.NewValue ?? false);
|
||||
if (!IsEnabled) newValue = false;
|
||||
|
||||
if (_popup != null && _popup.IsOpen != newValue)
|
||||
{
|
||||
_popup.IsOpen = newValue;
|
||||
if (newValue)
|
||||
{
|
||||
_originalSelectedTime = SelectedTime;
|
||||
Clock?.Focus();
|
||||
}
|
||||
}
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
|
||||
private void OnSelectedTimePropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
var v = (DateTime?) e.NewValue;
|
||||
if (Clock != null) Clock.SelectedTime = v;
|
||||
if (v.HasValue)
|
||||
{
|
||||
SetTextInternal(DateTimeToString(v.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTextInternal(string.Empty);
|
||||
}
|
||||
SelectedTimeChanged?.Invoke(this, v);
|
||||
}
|
||||
|
||||
private void OnDisplayTimePropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (Clock != null && e.NewValue is DateTime dt)
|
||||
{
|
||||
Clock.DisplayTime = dt;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (_isHandlerSuspendedText) return;
|
||||
if (e.NewValue is string newValue)
|
||||
{
|
||||
if (_textBox != null)
|
||||
{
|
||||
_textBox.Text = newValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_defaultText = newValue;
|
||||
}
|
||||
SetSelectedTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValueNoCallback(SelectedTimeProperty, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClockChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.OldValue is ClockBase oldClock)
|
||||
{
|
||||
oldClock.SelectedTimeChanged -= Clock_SelectedTimeChanged;
|
||||
oldClock.Confirmed -= Clock_Confirmed;
|
||||
SetPopupChild(null);
|
||||
}
|
||||
|
||||
if (e.NewValue is ClockBase newClock)
|
||||
{
|
||||
newClock.ShowConfirmButton = true;
|
||||
newClock.SelectedTimeChanged += Clock_SelectedTimeChanged;
|
||||
newClock.Confirmed += Clock_Confirmed;
|
||||
SetPopupChild(newClock);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
if (_popup != null)
|
||||
{
|
||||
_popup.Opened -= PopupOpened;
|
||||
_popup.Closed -= PopupClosed;
|
||||
_popup.Child = null;
|
||||
}
|
||||
if (_dropDownButton != null)
|
||||
{
|
||||
_dropDownButton.Click -= DropDownButton_Click;
|
||||
}
|
||||
if (_textBox != null)
|
||||
{
|
||||
_textBox.KeyDown -= TextBox_KeyDown;
|
||||
_textBox.TextChanged -= TextBox_TextChanged;
|
||||
_textBox.LostFocus -= TextBox_LostFocus;
|
||||
}
|
||||
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
_popup = e.NameScope.Find<Popup>(ElementPopup);
|
||||
_dropDownButton = e.NameScope.Find<Button>(ElementButton);
|
||||
_textBox = e.NameScope.Find<TextBox>(ElementTextBox);
|
||||
|
||||
if (_popup != null)
|
||||
{
|
||||
_popup.Opened += PopupOpened;
|
||||
_popup.Closed += PopupClosed;
|
||||
if (Clock != null) _popup.Child = Clock;
|
||||
}
|
||||
if (_dropDownButton != null)
|
||||
{
|
||||
_dropDownButton.Click += DropDownButton_Click;
|
||||
}
|
||||
if (_textBox != null)
|
||||
{
|
||||
_textBox.KeyDown += TextBox_KeyDown;
|
||||
_textBox.TextChanged += TextBox_TextChanged;
|
||||
_textBox.LostFocus += TextBox_LostFocus;
|
||||
|
||||
var selectedTime = SelectedTime;
|
||||
if (selectedTime == null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_defaultText))
|
||||
{
|
||||
_textBox.Text = _defaultText;
|
||||
SetSelectedTime();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_textBox.Text = DateTimeToString(selectedTime.Value);
|
||||
}
|
||||
}
|
||||
|
||||
EnsureClock();
|
||||
|
||||
var sel = SelectedTime;
|
||||
if (sel is null)
|
||||
{
|
||||
_originalSelectedTime ??= DateTime.Now;
|
||||
SetCurrentValue(DisplayTimeProperty, _originalSelectedTime.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCurrentValue(DisplayTimeProperty, sel.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTextInternal(string value) => SetCurrentValue(TextProperty, value);
|
||||
|
||||
private void SetValueNoCallback(AvaloniaProperty property, object? value)
|
||||
{
|
||||
_isHandlerSuspendedText = true;
|
||||
try { SetCurrentValue(property, value); }
|
||||
finally { _isHandlerSuspendedText = false; }
|
||||
}
|
||||
|
||||
private void TextBox_LostFocus(object? sender, RoutedEventArgs e) => SetSelectedTime();
|
||||
|
||||
private void TextBox_TextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (_textBox == null) return;
|
||||
SetValueNoCallback(TextProperty, _textBox.Text ?? string.Empty);
|
||||
}
|
||||
|
||||
private void TextBox_KeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
SetSelectedTime();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Clock_SelectedTimeChanged(object? sender, DateTime? e) => SelectedTime = e;
|
||||
|
||||
private void Clock_Confirmed() => TogglePopup();
|
||||
|
||||
private void PopupOpened(object? sender, EventArgs e)
|
||||
{
|
||||
if (!IsDropDownOpen) SetCurrentValue(IsDropDownOpenProperty, true);
|
||||
Clock?.OnClockOpened();
|
||||
ClockOpened?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void PopupClosed(object? sender, EventArgs e)
|
||||
{
|
||||
if (IsDropDownOpen) SetCurrentValue(IsDropDownOpenProperty, false);
|
||||
Clock?.OnClockClosed();
|
||||
ClockClosed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void DropDownButton_Click(object? sender, RoutedEventArgs e) => TogglePopup();
|
||||
|
||||
private void TogglePopup()
|
||||
{
|
||||
if (IsDropDownOpen)
|
||||
{
|
||||
SetCurrentValue(IsDropDownOpenProperty, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSelectedTime();
|
||||
SetCurrentValue(IsDropDownOpenProperty, true);
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime? ParseText(string text)
|
||||
{
|
||||
if (DateTime.TryParse(text, CultureInfo.CurrentCulture, DateTimeStyles.None, out var d))
|
||||
return d;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void SetSelectedTime()
|
||||
{
|
||||
var s = _textBox?.Text ?? _defaultText ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(s))
|
||||
{
|
||||
if (SelectedTime != null)
|
||||
{
|
||||
var existing = DateTimeToString(SelectedTime.Value);
|
||||
if (string.Equals(existing, s, StringComparison.Ordinal)) return;
|
||||
}
|
||||
|
||||
var d = ParseText(s);
|
||||
if (d != null)
|
||||
{
|
||||
SetCurrentValue(TextProperty, DateTimeToString(d.Value));
|
||||
if (!Equals(SelectedTime, d))
|
||||
{
|
||||
SetCurrentValue(SelectedTimeProperty, d);
|
||||
SetCurrentValue(DisplayTimeProperty, d.Value);
|
||||
}
|
||||
}
|
||||
else if (SelectedTime != null)
|
||||
{
|
||||
SetCurrentValue(TextProperty, DateTimeToString(SelectedTime.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCurrentValue(TextProperty, DateTimeToString(DisplayTime));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SelectedTime.HasValue)
|
||||
{
|
||||
SetCurrentValue(SelectedTimeProperty, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTextInternal(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string DateTimeToString(DateTime d) => d.ToString(TimeFormat, CultureInfo.CurrentCulture);
|
||||
|
||||
private void EnsureClock()
|
||||
{
|
||||
if (Clock is not null) return;
|
||||
SetCurrentValue(ClockProperty, new Clock());
|
||||
}
|
||||
|
||||
private void SetPopupChild(Control? element)
|
||||
{
|
||||
if (_popup is not null)
|
||||
{
|
||||
_popup.Child = element ?? Clock;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePseudoClasses()
|
||||
{
|
||||
PseudoClasses.Set(":dropdownopen", IsDropDownOpen);
|
||||
}
|
||||
|
||||
public override string ToString() => SelectedTime?.ToString(TimeFormat) ?? string.Empty;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
SetCurrentValue(SelectedTimeProperty, null);
|
||||
SetCurrentValue(TextProperty, string.Empty);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[TemplatePart(ElementButtonAm, typeof(RadioButton))]
|
||||
[TemplatePart(ElementButtonPm, typeof(RadioButton))]
|
||||
[TemplatePart(ElementCanvas, typeof(Canvas))]
|
||||
[TemplatePart(ElementBorderTitle, typeof(Border))]
|
||||
[TemplatePart(ElementBorderClock, typeof(Border))]
|
||||
[TemplatePart(ElementPanelNum, typeof(CirclePanel))]
|
||||
[TemplatePart(ElementTimeStr, typeof(TextBlock))]
|
||||
public class Clock : ClockBase
|
||||
{
|
||||
private const string ElementButtonAm = "PART_ButtonAm";
|
||||
private const string ElementButtonPm = "PART_ButtonPm";
|
||||
private const string ElementCanvas = "PART_Canvas";
|
||||
private const string ElementBorderTitle = "PART_BorderTitle";
|
||||
private const string ElementBorderClock = "PART_BorderClock";
|
||||
private const string ElementPanelNum = "PART_PanelNum";
|
||||
private const string ElementTimeStr = "PART_TimeStr";
|
||||
|
||||
private RadioButton? _buttonAm;
|
||||
private RadioButton? _buttonPm;
|
||||
private Canvas? _canvas;
|
||||
private Border? _borderTitle;
|
||||
private Border? _borderClock;
|
||||
private ClockRadioButton? _currentButton;
|
||||
private RotateTransform? _rotateTransformClock;
|
||||
private CirclePanel? _circlePanel;
|
||||
private List<ClockRadioButton>? _radioButtonList;
|
||||
private TextBlock? _blockTime;
|
||||
private int _secValue;
|
||||
|
||||
public static readonly StyledProperty<ControlTheme?> ClockRadioButtonThemeProperty =
|
||||
AvaloniaProperty.Register<Clock, ControlTheme?>(nameof(ClockRadioButtonTheme));
|
||||
|
||||
public ControlTheme? ClockRadioButtonTheme
|
||||
{
|
||||
get => GetValue(ClockRadioButtonThemeProperty);
|
||||
set => SetValue(ClockRadioButtonThemeProperty, value);
|
||||
}
|
||||
|
||||
private int SecValue
|
||||
{
|
||||
get => _secValue;
|
||||
set
|
||||
{
|
||||
if (value < 0) _secValue = 59;
|
||||
else if (value > 59) _secValue = 0;
|
||||
else _secValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
AppliedTemplate = false;
|
||||
if (_buttonAm != null) _buttonAm.Click -= ButtonAm_OnClick;
|
||||
if (_buttonPm != null) _buttonPm.Click -= ButtonPm_OnClick;
|
||||
if (ButtonConfirm != null) ButtonConfirm.Click -= ButtonConfirm_OnClick;
|
||||
if (_borderTitle != null) _borderTitle.PointerWheelChanged -= BorderTitle_OnPointerWheelChanged;
|
||||
if (_canvas != null)
|
||||
{
|
||||
_canvas.PointerWheelChanged -= Canvas_OnPointerWheelChanged;
|
||||
_canvas.RemoveHandler(Button.ClickEvent, Canvas_OnClick);
|
||||
_canvas.PointerMoved -= Canvas_OnPointerMoved;
|
||||
}
|
||||
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
_buttonAm = e.NameScope.Find<RadioButton>(ElementButtonAm);
|
||||
_buttonPm = e.NameScope.Find<RadioButton>(ElementButtonPm);
|
||||
ButtonConfirm = e.NameScope.Find<Button>(ElementButtonConfirm);
|
||||
_borderTitle = e.NameScope.Find<Border>(ElementBorderTitle);
|
||||
_canvas = e.NameScope.Find<Canvas>(ElementCanvas);
|
||||
_borderClock = e.NameScope.Find<Border>(ElementBorderClock);
|
||||
_circlePanel = e.NameScope.Find<CirclePanel>(ElementPanelNum);
|
||||
_blockTime = e.NameScope.Find<TextBlock>(ElementTimeStr);
|
||||
|
||||
if (!CheckNull()) return;
|
||||
|
||||
_buttonAm!.Click += ButtonAm_OnClick;
|
||||
_buttonPm!.Click += ButtonPm_OnClick;
|
||||
ButtonConfirm!.Click += ButtonConfirm_OnClick;
|
||||
_borderTitle!.PointerWheelChanged += BorderTitle_OnPointerWheelChanged;
|
||||
|
||||
_canvas!.PointerWheelChanged += Canvas_OnPointerWheelChanged;
|
||||
_canvas.AddHandler(Button.ClickEvent, Canvas_OnClick);
|
||||
_canvas.PointerMoved += Canvas_OnPointerMoved;
|
||||
|
||||
_rotateTransformClock = new RotateTransform();
|
||||
_borderClock!.RenderTransform = _rotateTransformClock;
|
||||
_borderClock.RenderTransformOrigin = new RelativePoint(0.5, 1, RelativeUnit.Relative);
|
||||
|
||||
_radioButtonList = new List<ClockRadioButton>();
|
||||
_circlePanel!.Children.Clear();
|
||||
for (var i = 0; i < 12; i++)
|
||||
{
|
||||
var num = i + 1;
|
||||
var button = new ClockRadioButton
|
||||
{
|
||||
Num = num,
|
||||
Content = num
|
||||
};
|
||||
if (ClockRadioButtonTheme != null)
|
||||
{
|
||||
button.Theme = ClockRadioButtonTheme;
|
||||
}
|
||||
_radioButtonList.Add(button);
|
||||
_circlePanel.Children.Add(button);
|
||||
}
|
||||
|
||||
AppliedTemplate = true;
|
||||
if (SelectedTime.HasValue)
|
||||
{
|
||||
Update(SelectedTime.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayTime = DateTime.Now;
|
||||
Update(DisplayTime);
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckNull() =>
|
||||
_buttonAm != null && _buttonPm != null && ButtonConfirm != null && _canvas != null &&
|
||||
_borderTitle != null && _borderClock != null && _circlePanel != null && _blockTime != null;
|
||||
|
||||
private void BorderTitle_OnPointerWheelChanged(object? sender, PointerWheelEventArgs e)
|
||||
{
|
||||
if (e.Delta.Y < 0) SecValue--;
|
||||
else SecValue++;
|
||||
UpdateInternal();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void Canvas_OnPointerWheelChanged(object? sender, PointerWheelEventArgs e)
|
||||
{
|
||||
if (_rotateTransformClock == null) return;
|
||||
var value = (int) _rotateTransformClock.Angle;
|
||||
if (e.Delta.Y < 0) value += 6;
|
||||
else value -= 6;
|
||||
if (value < 0) value += 360;
|
||||
_rotateTransformClock.Angle = value;
|
||||
UpdateInternal();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void Canvas_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (e.Source is ClockRadioButton crb)
|
||||
{
|
||||
_currentButton = crb;
|
||||
UpdateInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private void Canvas_OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (_canvas == null || _rotateTransformClock == null) return;
|
||||
var props = e.GetCurrentPoint(_canvas).Properties;
|
||||
if (!props.IsLeftButtonPressed) return;
|
||||
|
||||
var p = e.GetPosition(_canvas);
|
||||
var dx = p.X - 85;
|
||||
var dy = p.Y - 85;
|
||||
var angle = Math.Atan2(dy, dx) * 180.0 / Math.PI + 90;
|
||||
if (angle < 0) angle += 360;
|
||||
angle -= angle % 6;
|
||||
_rotateTransformClock.Angle = angle;
|
||||
UpdateInternal();
|
||||
}
|
||||
|
||||
private void UpdateInternal()
|
||||
{
|
||||
if (!AppliedTemplate || _currentButton == null || _buttonAm == null || _buttonPm == null) return;
|
||||
var hValue = _currentButton.Num;
|
||||
if (_buttonPm.IsChecked == true)
|
||||
{
|
||||
hValue += 12;
|
||||
if (hValue == 24) hValue = 12;
|
||||
}
|
||||
else if (hValue == 12)
|
||||
{
|
||||
hValue = 0;
|
||||
}
|
||||
if (hValue == 12 && _buttonAm.IsChecked == true)
|
||||
{
|
||||
_buttonPm.IsChecked = true;
|
||||
_buttonAm.IsChecked = false;
|
||||
}
|
||||
|
||||
if (_blockTime != null)
|
||||
{
|
||||
DisplayTime = GetDisplayTime();
|
||||
_blockTime.Text = DisplayTime.ToString(TimeFormat);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Update(DateTime time)
|
||||
{
|
||||
if (!AppliedTemplate || _buttonAm == null || _buttonPm == null ||
|
||||
_rotateTransformClock == null || _radioButtonList == null) return;
|
||||
|
||||
var h = time.Hour;
|
||||
var m = time.Minute;
|
||||
|
||||
if (h >= 12)
|
||||
{
|
||||
_buttonPm.IsChecked = true;
|
||||
_buttonAm.IsChecked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_buttonPm.IsChecked = false;
|
||||
_buttonAm.IsChecked = true;
|
||||
}
|
||||
|
||||
_rotateTransformClock.Angle = m * 6;
|
||||
|
||||
var hRest = h % 12;
|
||||
if (hRest == 0) hRest = 12;
|
||||
var ctl = _radioButtonList[hRest - 1];
|
||||
ctl.IsChecked = true;
|
||||
_currentButton = ctl;
|
||||
|
||||
_secValue = time.Second;
|
||||
UpdateInternal();
|
||||
}
|
||||
|
||||
private DateTime GetDisplayTime()
|
||||
{
|
||||
if (_currentButton == null || _buttonAm == null || _buttonPm == null || _rotateTransformClock == null)
|
||||
return DateTime.Now;
|
||||
|
||||
var hValue = _currentButton.Num;
|
||||
if (_buttonPm.IsChecked == true)
|
||||
{
|
||||
hValue += 12;
|
||||
if (hValue == 24) hValue = 12;
|
||||
}
|
||||
else if (hValue == 12)
|
||||
{
|
||||
hValue = 0;
|
||||
}
|
||||
var now = DateTime.Now;
|
||||
return new DateTime(now.Year, now.Month, now.Day, hValue,
|
||||
(int) Math.Abs(_rotateTransformClock.Angle) % 360 / 6, _secValue);
|
||||
}
|
||||
|
||||
private void ButtonAm_OnClick(object? sender, RoutedEventArgs e) => UpdateInternal();
|
||||
private void ButtonPm_OnClick(object? sender, RoutedEventArgs e) => UpdateInternal();
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[TemplatePart(ElementButtonConfirm, typeof(Button))]
|
||||
public abstract class ClockBase : TemplatedControl
|
||||
{
|
||||
protected const string ElementButtonConfirm = "PART_ButtonConfirm";
|
||||
|
||||
protected Button? ButtonConfirm;
|
||||
|
||||
protected bool AppliedTemplate;
|
||||
|
||||
public event Action? Confirmed;
|
||||
|
||||
public event EventHandler<DateTime>? DisplayTimeChanged;
|
||||
|
||||
public event EventHandler<DateTime?>? SelectedTimeChanged;
|
||||
|
||||
public static readonly StyledProperty<string> TimeFormatProperty =
|
||||
AvaloniaProperty.Register<ClockBase, string>(nameof(TimeFormat), "HH:mm:ss");
|
||||
|
||||
public string TimeFormat
|
||||
{
|
||||
get => GetValue(TimeFormatProperty);
|
||||
set => SetValue(TimeFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DateTime?> SelectedTimeProperty =
|
||||
AvaloniaProperty.Register<ClockBase, DateTime?>(nameof(SelectedTime),
|
||||
defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
public DateTime? SelectedTime
|
||||
{
|
||||
get => GetValue(SelectedTimeProperty);
|
||||
set => SetValue(SelectedTimeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DateTime> DisplayTimeProperty =
|
||||
AvaloniaProperty.Register<ClockBase, DateTime>(nameof(DisplayTime), DateTime.Now,
|
||||
defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
public DateTime DisplayTime
|
||||
{
|
||||
get => GetValue(DisplayTimeProperty);
|
||||
set => SetValue(DisplayTimeProperty, value);
|
||||
}
|
||||
|
||||
internal static readonly StyledProperty<bool> ShowConfirmButtonProperty =
|
||||
AvaloniaProperty.Register<ClockBase, bool>(nameof(ShowConfirmButton));
|
||||
|
||||
internal bool ShowConfirmButton
|
||||
{
|
||||
get => GetValue(ShowConfirmButtonProperty);
|
||||
set => SetValue(ShowConfirmButtonProperty, value);
|
||||
}
|
||||
|
||||
static ClockBase()
|
||||
{
|
||||
SelectedTimeProperty.Changed.AddClassHandler<ClockBase>((o, e) => o.OnSelectedTimePropertyChanged(e));
|
||||
DisplayTimeProperty.Changed.AddClassHandler<ClockBase>((o, e) => o.OnDisplayTimePropertyChanged(e));
|
||||
}
|
||||
|
||||
private void OnSelectedTimePropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
var v = (DateTime?) e.NewValue;
|
||||
DisplayTime = v ?? DateTime.Now;
|
||||
SelectedTimeChanged?.Invoke(this, v);
|
||||
}
|
||||
|
||||
private void OnDisplayTimePropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
var v = (DateTime) (e.NewValue ?? DateTime.Now);
|
||||
Update(v);
|
||||
DisplayTimeChanged?.Invoke(this, v);
|
||||
}
|
||||
|
||||
protected void ButtonConfirm_OnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
SelectedTime = DisplayTime;
|
||||
Confirmed?.Invoke();
|
||||
}
|
||||
|
||||
internal abstract void Update(DateTime time);
|
||||
|
||||
public virtual void OnClockClosed()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnClockOpened()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class ClockRadioButton : RadioButton
|
||||
{
|
||||
public static readonly StyledProperty<int> NumProperty =
|
||||
AvaloniaProperty.Register<ClockRadioButton, int>(nameof(Num));
|
||||
|
||||
public int Num
|
||||
{
|
||||
get => GetValue(NumProperty);
|
||||
set => SetValue(NumProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[TemplatePart(ElementHourList, typeof(ListBox))]
|
||||
[TemplatePart(ElementMinuteList, typeof(ListBox))]
|
||||
[TemplatePart(ElementSecondList, typeof(ListBox))]
|
||||
public class ListClock : ClockBase
|
||||
{
|
||||
private const string ElementHourList = "PART_HourList";
|
||||
private const string ElementMinuteList = "PART_MinuteList";
|
||||
private const string ElementSecondList = "PART_SecondList";
|
||||
|
||||
private ListBox? _hourList;
|
||||
private ListBox? _minuteList;
|
||||
private ListBox? _secondList;
|
||||
|
||||
public override void OnClockOpened() => ScrollIntoView();
|
||||
|
||||
protected override void OnApplyTemplate(Avalonia.Controls.Primitives.TemplateAppliedEventArgs e)
|
||||
{
|
||||
AppliedTemplate = false;
|
||||
if (ButtonConfirm != null)
|
||||
{
|
||||
ButtonConfirm.Click -= ButtonConfirm_OnClick;
|
||||
}
|
||||
if (_hourList != null) _hourList.SelectionChanged -= HourList_SelectionChanged;
|
||||
if (_minuteList != null) _minuteList.SelectionChanged -= MinuteList_SelectionChanged;
|
||||
if (_secondList != null) _secondList.SelectionChanged -= SecondList_SelectionChanged;
|
||||
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
_hourList = e.NameScope.Find<ListBox>(ElementHourList);
|
||||
if (_hourList != null)
|
||||
{
|
||||
CreateItemsSource(_hourList, 24);
|
||||
_hourList.SelectionChanged += HourList_SelectionChanged;
|
||||
}
|
||||
|
||||
_minuteList = e.NameScope.Find<ListBox>(ElementMinuteList);
|
||||
if (_minuteList != null)
|
||||
{
|
||||
CreateItemsSource(_minuteList, 60);
|
||||
_minuteList.SelectionChanged += MinuteList_SelectionChanged;
|
||||
}
|
||||
|
||||
_secondList = e.NameScope.Find<ListBox>(ElementSecondList);
|
||||
if (_secondList != null)
|
||||
{
|
||||
CreateItemsSource(_secondList, 60);
|
||||
_secondList.SelectionChanged += SecondList_SelectionChanged;
|
||||
}
|
||||
|
||||
ButtonConfirm = e.NameScope.Find<Button>(ElementButtonConfirm);
|
||||
if (ButtonConfirm != null)
|
||||
{
|
||||
ButtonConfirm.Click += ButtonConfirm_OnClick;
|
||||
}
|
||||
|
||||
AppliedTemplate = true;
|
||||
if (SelectedTime.HasValue)
|
||||
{
|
||||
Update(SelectedTime.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayTime = DateTime.Now;
|
||||
Update(DisplayTime);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Update(DateTime time)
|
||||
{
|
||||
if (!AppliedTemplate || _hourList == null || _minuteList == null || _secondList == null) return;
|
||||
|
||||
_hourList.SelectedIndex = time.Hour;
|
||||
_minuteList.SelectedIndex = time.Minute;
|
||||
_secondList.SelectedIndex = time.Second;
|
||||
|
||||
ScrollIntoView();
|
||||
|
||||
DisplayTime = time;
|
||||
}
|
||||
|
||||
private void HourList_SelectionChanged(object? sender, SelectionChangedEventArgs e) => UpdateFromSelection();
|
||||
private void MinuteList_SelectionChanged(object? sender, SelectionChangedEventArgs e) => UpdateFromSelection();
|
||||
private void SecondList_SelectionChanged(object? sender, SelectionChangedEventArgs e) => UpdateFromSelection();
|
||||
|
||||
private static void CreateItemsSource(ItemsControl selector, int count)
|
||||
{
|
||||
var list = new List<string>(count);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
list.Add(i.ToString("00"));
|
||||
}
|
||||
selector.ItemsSource = list;
|
||||
}
|
||||
|
||||
private void UpdateFromSelection()
|
||||
{
|
||||
if (_hourList == null || _minuteList == null || _secondList == null) return;
|
||||
if (_hourList.SelectedIndex >= 0 && _hourList.SelectedIndex < 24 &&
|
||||
_minuteList.SelectedIndex >= 0 && _minuteList.SelectedIndex < 60 &&
|
||||
_secondList.SelectedIndex >= 0 && _secondList.SelectedIndex < 60)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
DisplayTime = new DateTime(now.Year, now.Month, now.Day,
|
||||
_hourList.SelectedIndex, _minuteList.SelectedIndex, _secondList.SelectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void ScrollIntoView()
|
||||
{
|
||||
if (_hourList?.SelectedItem != null) _hourList.ScrollIntoView(_hourList.SelectedItem);
|
||||
if (_minuteList?.SelectedItem != null) _minuteList.ScrollIntoView(_minuteList.SelectedItem);
|
||||
if (_secondList?.SelectedItem != null) _secondList.ScrollIntoView(_secondList.SelectedItem);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:ClassModifier="internal"
|
||||
xmlns:hc="clr-namespace:HandyControl.Controls"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<ControlTheme x:Key="CalendarDatePickerBaseStyle"
|
||||
TargetType="CalendarDatePicker">
|
||||
<Setter Property="hc:TitleElement.MarginOnTheLeft"
|
||||
Value="0,7,6,0" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheTop"
|
||||
Value="8,0,0,5" />
|
||||
<Setter Property="hc:TitleElement.HorizontalAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="hc:BorderElement.CornerRadius"
|
||||
Value="{StaticResource DefaultCornerRadius}" />
|
||||
<Setter Property="CornerRadius"
|
||||
Value="{Binding $self.(hc:BorderElement.CornerRadius)}" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="{StaticResource DefaultControlHeight}" />
|
||||
<Setter Property="MinWidth"
|
||||
Value="120" />
|
||||
<Setter Property="Padding"
|
||||
Value="{StaticResource DefaultInputPadding}" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource RegionBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource PrimaryTextBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="IsTodayHighlighted"
|
||||
Value="True" />
|
||||
<Setter Property="SelectedDateFormat"
|
||||
Value="Short" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<DataValidationErrors>
|
||||
<Grid x:Name="PART_Root"
|
||||
ColumnDefinitions="*,Auto">
|
||||
<Border x:Name="border"
|
||||
Grid.ColumnSpan="2"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}" />
|
||||
<TextBox x:Name="PART_TextBox"
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Watermark="{TemplateBinding Watermark}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<Button x:Name="PART_Button"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Theme="{StaticResource ButtonIcon}"
|
||||
hc:IconElement.Width="14"
|
||||
hc:IconElement.Geometry="{StaticResource CalendarGeometry}"
|
||||
Padding="{TemplateBinding Padding, Converter={StaticResource ThicknessSplitConverter}, ConverterParameter='0,0,1,0'}"
|
||||
Foreground="{Binding BorderBrush, ElementName=border}"
|
||||
Focusable="False" />
|
||||
<Popup x:Name="PART_Popup"
|
||||
WindowManagerAddShadowHint="False"
|
||||
PlacementTarget="border"
|
||||
Placement="BottomEdgeAlignedLeft"
|
||||
IsLightDismissEnabled="True"
|
||||
InheritsTransform="True">
|
||||
<Calendar x:Name="PART_Calendar" />
|
||||
</Popup>
|
||||
</Grid>
|
||||
</DataValidationErrors>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="Opacity"
|
||||
Value="0.4" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pointerover /template/ Border#border">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource SecondaryBorderBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:focus-within /template/ Border#border">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource PrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:dropdownopen /template/ Border#border">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource PrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:error /template/ Border#border">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource DangerBrush}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type CalendarDatePicker}"
|
||||
BasedOn="{StaticResource CalendarDatePickerBaseStyle}"
|
||||
TargetType="CalendarDatePicker" />
|
||||
|
||||
<ControlTheme x:Key="CalendarDatePicker.Small"
|
||||
BasedOn="{StaticResource CalendarDatePickerBaseStyle}"
|
||||
TargetType="CalendarDatePicker">
|
||||
<Setter Property="MinHeight"
|
||||
Value="20" />
|
||||
<Setter Property="Padding"
|
||||
Value="6,0" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="CalendarDatePickerExtend"
|
||||
BasedOn="{StaticResource CalendarDatePickerBaseStyle}"
|
||||
TargetType="CalendarDatePicker">
|
||||
<Setter Property="hc:InfoElement.Symbol"
|
||||
Value="●" />
|
||||
<Setter Property="hc:InfoElement.ContentHeight"
|
||||
Value="{x:Static system:Double.NaN}" />
|
||||
<Setter Property="hc:InfoElement.MinContentHeight"
|
||||
Value="{StaticResource DefaultControlHeight}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<HeaderedContentControl Header="{Binding $parent.(hc:TitleElement.Title)}">
|
||||
<Grid x:Name="PART_Root"
|
||||
ColumnDefinitions="*,Auto,Auto">
|
||||
<Border x:Name="border"
|
||||
Grid.ColumnSpan="3"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}" />
|
||||
<TextBox x:Name="PART_TextBox"
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Watermark="{TemplateBinding Watermark}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<Button x:Name="ButtonClear"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
hc:IconElement.Width="14"
|
||||
Command="{Binding $parent[CalendarDatePicker].Clear}"
|
||||
Focusable="False"
|
||||
Theme="{StaticResource ButtonIcon}"
|
||||
Padding="0,0,2,0"
|
||||
hc:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}"
|
||||
Foreground="{Binding BorderBrush, ElementName=border}">
|
||||
<Button.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding RelativeSource="{RelativeSource TemplatedParent}"
|
||||
Path="IsPointerOver" />
|
||||
<Binding RelativeSource="{RelativeSource TemplatedParent}"
|
||||
Path="(hc:InfoElement.ShowClearButton)" />
|
||||
</MultiBinding>
|
||||
</Button.IsVisible>
|
||||
</Button>
|
||||
<Button x:Name="PART_Button"
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Theme="{StaticResource ButtonIcon}"
|
||||
hc:IconElement.Width="14"
|
||||
hc:IconElement.Geometry="{StaticResource CalendarGeometry}"
|
||||
Padding="{TemplateBinding Padding, Converter={StaticResource ThicknessSplitConverter}, ConverterParameter='0,0,1,0'}"
|
||||
Foreground="{Binding BorderBrush, ElementName=border}"
|
||||
Focusable="False" />
|
||||
<Popup x:Name="PART_Popup"
|
||||
WindowManagerAddShadowHint="False"
|
||||
PlacementTarget="border"
|
||||
Placement="BottomEdgeAlignedLeft"
|
||||
IsLightDismissEnabled="True"
|
||||
InheritsTransform="True">
|
||||
<Calendar x:Name="PART_Calendar" />
|
||||
</Popup>
|
||||
</Grid>
|
||||
</HeaderedContentControl>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="CalendarDatePickerExtend.Small"
|
||||
BasedOn="{StaticResource CalendarDatePickerExtend}"
|
||||
TargetType="CalendarDatePicker">
|
||||
<Setter Property="hc:InfoElement.MinContentHeight"
|
||||
Value="20" />
|
||||
<Setter Property="hc:InfoElement.ContentHeight"
|
||||
Value="20" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheLeft"
|
||||
Value="0,3,6,0" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheTop"
|
||||
Value="6,0,0,1" />
|
||||
<Setter Property="Padding"
|
||||
Value="6,0" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="20" />
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,338 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:ClassModifier="internal"
|
||||
xmlns:hc="clr-namespace:HandyControl.Controls"
|
||||
xmlns:langs="clr-namespace:HandyControl.Properties.Langs">
|
||||
|
||||
<ControlTheme x:Key="ClockRadioButtonTheme"
|
||||
TargetType="hc:ClockRadioButton">
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource PrimaryTextBrush}" />
|
||||
<Setter Property="Focusable"
|
||||
Value="False" />
|
||||
<Setter Property="Width"
|
||||
Value="28" />
|
||||
<Setter Property="Height"
|
||||
Value="28" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource DangerBrush}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Panel Name="templateRoot"
|
||||
Background="Transparent">
|
||||
<Ellipse Name="optionMark"
|
||||
Fill="{TemplateBinding Background}"
|
||||
MinWidth="6"
|
||||
MinHeight="6"
|
||||
Opacity="0">
|
||||
<Ellipse.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity"
|
||||
Duration="0:0:0.2" />
|
||||
</Transitions>
|
||||
</Ellipse.Transitions>
|
||||
</Ellipse>
|
||||
<ContentPresenter Name="contentPresenter"
|
||||
Focusable="False"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:checked /template/ Ellipse#optionMark">
|
||||
<Setter Property="Opacity"
|
||||
Value="1" />
|
||||
</Style>
|
||||
<Style Selector="^:checked">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource TextIconBrush}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="ClockBaseStyle"
|
||||
TargetType="hc:Clock">
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0" />
|
||||
<Setter Property="Margin"
|
||||
Value="8,0" />
|
||||
<Setter Property="Focusable"
|
||||
Value="False" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource RegionBrush}" />
|
||||
<Setter Property="ClockRadioButtonTheme"
|
||||
Value="{StaticResource ClockRadioButtonTheme}" />
|
||||
<Setter Property="hc:TitleElement.Background"
|
||||
Value="{DynamicResource TitleBrush}" />
|
||||
<Setter Property="hc:BorderElement.CornerRadius"
|
||||
Value="{StaticResource DefaultCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Panel Margin="8,4,8,8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<Border CornerRadius="{TemplateBinding hc:BorderElement.CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Effect="{StaticResource EffectShadow2}" />
|
||||
<Grid RowDefinitions="50,*"
|
||||
ColumnDefinitions="*,*,*">
|
||||
<Border Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="4"
|
||||
CornerRadius="{TemplateBinding hc:BorderElement.CornerRadius}"
|
||||
Background="{TemplateBinding hc:TitleElement.Background}"
|
||||
Name="PART_BorderTitle">
|
||||
<TextBlock Name="PART_TimeStr"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="20"
|
||||
Foreground="{DynamicResource TextIconBrush}" />
|
||||
</Border>
|
||||
<Canvas Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="16,16,16,62"
|
||||
VerticalAlignment="Top"
|
||||
Name="PART_Canvas"
|
||||
Width="178"
|
||||
Height="178">
|
||||
<Border Background="{DynamicResource SecondaryRegionBrush}"
|
||||
Width="178"
|
||||
Height="178"
|
||||
CornerRadius="89" />
|
||||
<hc:CirclePanel Diameter="130"
|
||||
Name="PART_PanelNum"
|
||||
KeepVertical="True"
|
||||
Margin="24,24,0,0"
|
||||
OffsetAngle="-60" />
|
||||
<Border Focusable="False"
|
||||
Name="PART_BorderClock"
|
||||
Background="{DynamicResource PrimaryBrush}"
|
||||
Height="63"
|
||||
Width="2"
|
||||
Canvas.Left="88"
|
||||
Canvas.Top="26" />
|
||||
<Ellipse Fill="White"
|
||||
Width="8"
|
||||
Height="8"
|
||||
StrokeThickness="2"
|
||||
Stroke="{DynamicResource PrimaryBrush}"
|
||||
Canvas.Top="85"
|
||||
Canvas.Left="85" />
|
||||
</Canvas>
|
||||
<hc:ClockRadioButton Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Background="{DynamicResource PrimaryBrush}"
|
||||
Name="PART_ButtonAm"
|
||||
IsChecked="True"
|
||||
Height="30"
|
||||
Width="30"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="16,0,0,16"
|
||||
Content="{x:Static langs:Lang.Am}"
|
||||
Theme="{StaticResource ClockRadioButtonTheme}" />
|
||||
<hc:ClockRadioButton Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Background="{DynamicResource PrimaryBrush}"
|
||||
Name="PART_ButtonPm"
|
||||
Height="30"
|
||||
Width="30"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="0,0,16,16"
|
||||
Content="{x:Static langs:Lang.Pm}"
|
||||
Theme="{StaticResource ClockRadioButtonTheme}" />
|
||||
<Button Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
IsVisible="{TemplateBinding ShowConfirmButton}"
|
||||
Name="PART_ButtonConfirm"
|
||||
Content="{x:Static langs:Lang.Confirm}"
|
||||
Foreground="{DynamicResource PrimaryBrush}"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,19"
|
||||
Height="24"
|
||||
Width="60"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="Transparent"
|
||||
Theme="{StaticResource ButtonCustom}" />
|
||||
</Grid>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type hc:Clock}"
|
||||
BasedOn="{StaticResource ClockBaseStyle}"
|
||||
TargetType="hc:Clock" />
|
||||
|
||||
<ControlTheme x:Key="{x:Type hc:ClockRadioButton}"
|
||||
BasedOn="{StaticResource ClockRadioButtonTheme}"
|
||||
TargetType="hc:ClockRadioButton" />
|
||||
|
||||
<ControlTheme x:Key="ClockListBoxItemStyle"
|
||||
TargetType="ListBoxItem">
|
||||
<Setter Property="Padding"
|
||||
Value="0" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="{StaticResource DefaultControlHeight}" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource RegionBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource PrimaryTextBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="Transparent" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0" />
|
||||
<Setter Property="Margin"
|
||||
Value="0" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ContentPresenter Name="PART_ContentPresenter"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:pointerover /template/ ContentPresenter">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource SecondaryRegionBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:selected /template/ ContentPresenter">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource PrimaryBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource TextIconBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="Opacity"
|
||||
Value="0.4" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="ClockListBoxStyle"
|
||||
TargetType="ListBox">
|
||||
<Setter Property="MaxHeight"
|
||||
Value="180" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource RegionBrush}" />
|
||||
<Setter Property="Padding"
|
||||
Value="0" />
|
||||
<Setter Property="ItemContainerTheme"
|
||||
Value="{StaticResource ClockListBoxItemStyle}" />
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility"
|
||||
Value="Hidden" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}">
|
||||
<ScrollViewer Name="PART_ScrollViewer"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Hidden">
|
||||
<ItemsPresenter Name="PART_ItemsPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="ListClockBaseStyle"
|
||||
TargetType="hc:ListClock">
|
||||
<Setter Property="BorderThickness"
|
||||
Value="0" />
|
||||
<Setter Property="Margin"
|
||||
Value="8,0" />
|
||||
<Setter Property="Focusable"
|
||||
Value="False" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource RegionBrush}" />
|
||||
<Setter Property="hc:BorderElement.CornerRadius"
|
||||
Value="{StaticResource DefaultCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Panel Margin="8,4,8,8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<Border CornerRadius="{TemplateBinding hc:BorderElement.CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Effect="{StaticResource EffectShadow2}" />
|
||||
<Grid Margin="0,4"
|
||||
Width="210"
|
||||
ColumnDefinitions="*,*,*"
|
||||
RowDefinitions="*,Auto">
|
||||
<ListBox Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Name="PART_HourList"
|
||||
Theme="{StaticResource ClockListBoxStyle}" />
|
||||
<ListBox Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Name="PART_MinuteList"
|
||||
BorderThickness="1,0"
|
||||
Theme="{StaticResource ClockListBoxStyle}" />
|
||||
<ListBox Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Name="PART_SecondList"
|
||||
Theme="{StaticResource ClockListBoxStyle}" />
|
||||
<Border Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
VerticalAlignment="Bottom"
|
||||
IsVisible="{TemplateBinding ShowConfirmButton}"
|
||||
Height="1"
|
||||
Background="{DynamicResource BorderBrush}" />
|
||||
<Button Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="0,10"
|
||||
Name="PART_ButtonConfirm"
|
||||
IsVisible="{TemplateBinding ShowConfirmButton}"
|
||||
Content="{x:Static langs:Lang.Confirm}"
|
||||
Foreground="{DynamicResource PrimaryBrush}"
|
||||
HorizontalAlignment="Center"
|
||||
Background="Transparent"
|
||||
Theme="{StaticResource ButtonCustom}" />
|
||||
</Grid>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type hc:ListClock}"
|
||||
BasedOn="{StaticResource ListClockBaseStyle}"
|
||||
TargetType="hc:ListClock" />
|
||||
</ResourceDictionary>
|
||||
@@ -16,6 +16,10 @@
|
||||
Value="0" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="{StaticResource DefaultControlHeight}" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="CornerRadius"
|
||||
Value="{Binding $self.(hc:BorderElement.CornerRadius)}" />
|
||||
<Setter Property="Template">
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Expander.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/ProgressBar.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Calendar.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/CalendarDatePicker.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Clock.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/TimePicker.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/TextBox.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/AutoCompleteBox.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/ButtonSpinner.axaml" />
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:ClassModifier="internal"
|
||||
xmlns:hc="clr-namespace:HandyControl.Controls"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime">
|
||||
|
||||
<ControlTheme x:Key="TimePickerBaseStyle"
|
||||
TargetType="hc:TimePicker">
|
||||
<Setter Property="hc:TitleElement.MarginOnTheLeft"
|
||||
Value="0,7,6,0" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheTop"
|
||||
Value="8,0,0,5" />
|
||||
<Setter Property="hc:TitleElement.HorizontalAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="hc:BorderElement.CornerRadius"
|
||||
Value="{StaticResource DefaultCornerRadius}" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="{StaticResource DefaultControlHeight}" />
|
||||
<Setter Property="MinWidth"
|
||||
Value="120" />
|
||||
<Setter Property="Padding"
|
||||
Value="{StaticResource DefaultInputPadding}" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource RegionBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource PrimaryTextBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid x:Name="PART_Root"
|
||||
ColumnDefinitions="*,Auto">
|
||||
<Border x:Name="border"
|
||||
Grid.ColumnSpan="2"
|
||||
CornerRadius="{TemplateBinding hc:BorderElement.CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}" />
|
||||
<TextBox x:Name="PART_TextBox"
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Watermark="{TemplateBinding Watermark}"
|
||||
Text="{Binding $parent[hc:TimePicker].Text, Mode=TwoWay}"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<Button x:Name="PART_Button"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Theme="{StaticResource ButtonIcon}"
|
||||
hc:IconElement.Width="14"
|
||||
hc:IconElement.Geometry="{StaticResource ClockGeometry}"
|
||||
Padding="{TemplateBinding Padding, Converter={StaticResource ThicknessSplitConverter}, ConverterParameter='0,0,1,0'}"
|
||||
Foreground="{Binding BorderBrush, ElementName=border}"
|
||||
Focusable="False" />
|
||||
<Popup x:Name="PART_Popup"
|
||||
WindowManagerAddShadowHint="False"
|
||||
PlacementTarget="border"
|
||||
Placement="BottomEdgeAlignedLeft"
|
||||
IsLightDismissEnabled="True"
|
||||
InheritsTransform="True" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:disabled">
|
||||
<Setter Property="Opacity"
|
||||
Value="0.4" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:pointerover /template/ Border#border">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource SecondaryBorderBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:focus-within /template/ Border#border">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource PrimaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:dropdownopen /template/ Border#border">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource PrimaryBrush}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type hc:TimePicker}"
|
||||
BasedOn="{StaticResource TimePickerBaseStyle}"
|
||||
TargetType="hc:TimePicker" />
|
||||
|
||||
<ControlTheme x:Key="TimePicker.Small"
|
||||
BasedOn="{StaticResource TimePickerBaseStyle}"
|
||||
TargetType="hc:TimePicker">
|
||||
<Setter Property="MinHeight"
|
||||
Value="20" />
|
||||
<Setter Property="Padding"
|
||||
Value="6,0" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="TimePickerExtend"
|
||||
BasedOn="{StaticResource TimePickerBaseStyle}"
|
||||
TargetType="hc:TimePicker">
|
||||
<Setter Property="hc:InfoElement.Symbol"
|
||||
Value="●" />
|
||||
<Setter Property="hc:InfoElement.ContentHeight"
|
||||
Value="{x:Static system:Double.NaN}" />
|
||||
<Setter Property="hc:InfoElement.MinContentHeight"
|
||||
Value="{StaticResource DefaultControlHeight}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<HeaderedContentControl Header="{Binding $parent[hc:TimePicker].(hc:TitleElement.Title)}">
|
||||
<Grid x:Name="PART_Root"
|
||||
ColumnDefinitions="*,Auto">
|
||||
<Border x:Name="border"
|
||||
Grid.ColumnSpan="2"
|
||||
CornerRadius="{TemplateBinding hc:BorderElement.CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}" />
|
||||
<TextBox x:Name="PART_TextBox"
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Watermark="{TemplateBinding Watermark}"
|
||||
Text="{Binding $parent[hc:TimePicker].Text, Mode=TwoWay}"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<Button x:Name="PART_Button"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Theme="{StaticResource ButtonIcon}"
|
||||
hc:IconElement.Width="14"
|
||||
hc:IconElement.Geometry="{StaticResource ClockGeometry}"
|
||||
Padding="{TemplateBinding Padding, Converter={StaticResource ThicknessSplitConverter}, ConverterParameter='0,0,1,0'}"
|
||||
Foreground="{Binding BorderBrush, ElementName=border}"
|
||||
Focusable="False" />
|
||||
<Popup x:Name="PART_Popup"
|
||||
WindowManagerAddShadowHint="False"
|
||||
PlacementTarget="border"
|
||||
Placement="BottomEdgeAlignedLeft"
|
||||
IsLightDismissEnabled="True"
|
||||
InheritsTransform="True" />
|
||||
</Grid>
|
||||
</HeaderedContentControl>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="TimePickerExtend.Small"
|
||||
BasedOn="{StaticResource TimePickerExtend}"
|
||||
TargetType="hc:TimePicker">
|
||||
<Setter Property="hc:InfoElement.MinContentHeight"
|
||||
Value="20" />
|
||||
<Setter Property="hc:InfoElement.ContentHeight"
|
||||
Value="20" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheLeft"
|
||||
Value="0,3,6,0" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheTop"
|
||||
Value="6,0,0,1" />
|
||||
<Setter Property="Padding"
|
||||
Value="6,0" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="20" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="TimePickerPlus"
|
||||
BasedOn="{StaticResource TimePickerExtend}"
|
||||
TargetType="hc:TimePicker">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<HeaderedContentControl Header="{Binding $parent[hc:TimePicker].(hc:TitleElement.Title)}">
|
||||
<Grid x:Name="PART_Root"
|
||||
ColumnDefinitions="*,Auto,Auto">
|
||||
<Border x:Name="border"
|
||||
Grid.ColumnSpan="3"
|
||||
CornerRadius="{TemplateBinding hc:BorderElement.CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}" />
|
||||
<TextBox x:Name="PART_TextBox"
|
||||
Grid.Column="0"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Watermark="{TemplateBinding Watermark}"
|
||||
Text="{Binding $parent[hc:TimePicker].Text, Mode=TwoWay}"
|
||||
VerticalContentAlignment="Center"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<Button x:Name="ButtonClear"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
hc:IconElement.Width="14"
|
||||
Command="{Binding $parent[hc:TimePicker].Clear}"
|
||||
Focusable="False"
|
||||
Theme="{StaticResource ButtonIcon}"
|
||||
Padding="0,0,2,0"
|
||||
hc:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}"
|
||||
Foreground="{Binding BorderBrush, ElementName=border}">
|
||||
<Button.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding RelativeSource="{RelativeSource TemplatedParent}"
|
||||
Path="IsPointerOver" />
|
||||
<Binding RelativeSource="{RelativeSource TemplatedParent}"
|
||||
Path="(hc:InfoElement.ShowClearButton)" />
|
||||
</MultiBinding>
|
||||
</Button.IsVisible>
|
||||
</Button>
|
||||
<Button x:Name="PART_Button"
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Theme="{StaticResource ButtonIcon}"
|
||||
hc:IconElement.Width="14"
|
||||
hc:IconElement.Geometry="{StaticResource ClockGeometry}"
|
||||
Padding="{TemplateBinding Padding, Converter={StaticResource ThicknessSplitConverter}, ConverterParameter='0,0,1,0'}"
|
||||
Foreground="{Binding BorderBrush, ElementName=border}"
|
||||
Focusable="False" />
|
||||
<Popup x:Name="PART_Popup"
|
||||
WindowManagerAddShadowHint="False"
|
||||
PlacementTarget="border"
|
||||
Placement="BottomEdgeAlignedLeft"
|
||||
IsLightDismissEnabled="True"
|
||||
InheritsTransform="True" />
|
||||
</Grid>
|
||||
</HeaderedContentControl>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="TimePickerPlus.Small"
|
||||
BasedOn="{StaticResource TimePickerPlus}"
|
||||
TargetType="hc:TimePicker">
|
||||
<Setter Property="hc:InfoElement.MinContentHeight"
|
||||
Value="20" />
|
||||
<Setter Property="hc:InfoElement.ContentHeight"
|
||||
Value="20" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheLeft"
|
||||
Value="0,3,6,0" />
|
||||
<Setter Property="hc:TitleElement.MarginOnTheTop"
|
||||
Value="6,0,0,1" />
|
||||
<Setter Property="Padding"
|
||||
Value="6,0" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="20" />
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
Reference in new issue
Block a user