diff --git a/demo/Ursa.Demo/Pages/TimePickerDemo.axaml b/demo/Ursa.Demo/Pages/TimePickerDemo.axaml
new file mode 100644
index 0000000..d5324f6
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/TimePickerDemo.axaml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/demo/Ursa.Demo/Pages/TimePickerDemo.axaml.cs b/demo/Ursa.Demo/Pages/TimePickerDemo.axaml.cs
new file mode 100644
index 0000000..330eb98
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/TimePickerDemo.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Ursa.Demo.Pages;
+
+public partial class TimePickerDemo : UserControl
+{
+ public TimePickerDemo()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
index 80b9f6a..f981fa6 100644
--- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
@@ -55,6 +55,7 @@ public class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeySelectionList => new SelectionListDemoViewModel(),
MenuKeys.MenuKeySkeleton => new SkeletonDemoViewModel(),
MenuKeys.MenuKeyTagInput => new TagInputDemoViewModel(),
+ MenuKeys.MenuKeyTimePicker => new TimePickerDemoViewModel(),
MenuKeys.MenuKeyTimeline => new TimelineDemoViewModel(),
MenuKeys.MenuKeyTreeComboBox => new TreeComboBoxDemoViewModel(),
MenuKeys.MenuKeyTwoTonePathIcon => new TwoTonePathIconDemoViewModel(),
diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
index a1fcdb7..32066e6 100644
--- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
@@ -43,6 +43,7 @@ public class MenuViewModel: ViewModelBase
new() { MenuHeader = "Skeleton", Key = MenuKeys.MenuKeySkeleton },
new() { MenuHeader = "TagInput", Key = MenuKeys.MenuKeyTagInput },
new() { MenuHeader = "Theme Toggler", Key = MenuKeys.MenuKeyThemeToggler },
+ new() { MenuHeader = "TimePicker", Key = MenuKeys.MenuKeyTimePicker },
new() { MenuHeader = "Timeline", Key = MenuKeys.MenuKeyTimeline },
new() { MenuHeader = "TreeComboBox", Key = MenuKeys.MenuKeyTreeComboBox },
new() { MenuHeader = "TwoTonePathIcon", Key = MenuKeys.MenuKeyTwoTonePathIcon},
@@ -86,6 +87,7 @@ public static class MenuKeys
public const string MenuKeySelectionList = "SelectionList";
public const string MenuKeyTagInput = "TagInput";
public const string MenuKeySkeleton = "Skeleton";
+ public const string MenuKeyTimePicker = "TimePicker";
public const string MenuKeyTimeline = "Timeline";
public const string MenuKeyTwoTonePathIcon = "TwoTonePathIcon";
public const string MenuKeyThemeToggler = "ThemeToggler";
diff --git a/demo/Ursa.Demo/ViewModels/TimePickerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/TimePickerDemoViewModel.cs
new file mode 100644
index 0000000..f115429
--- /dev/null
+++ b/demo/Ursa.Demo/ViewModels/TimePickerDemoViewModel.cs
@@ -0,0 +1,8 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace Ursa.Demo.ViewModels;
+
+public class TimePickerDemoViewModel: ObservableObject
+{
+
+}
\ No newline at end of file
diff --git a/src/Ursa.Themes.Semi/Controls/TimePicker.axaml b/src/Ursa.Themes.Semi/Controls/TimePicker.axaml
new file mode 100644
index 0000000..3f0d93d
--- /dev/null
+++ b/src/Ursa.Themes.Semi/Controls/TimePicker.axaml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ursa.Themes.Semi/Controls/_index.axaml b/src/Ursa.Themes.Semi/Controls/_index.axaml
index 6e25af2..0ceb9e3 100644
--- a/src/Ursa.Themes.Semi/Controls/_index.axaml
+++ b/src/Ursa.Themes.Semi/Controls/_index.axaml
@@ -32,6 +32,7 @@
+
diff --git a/src/Ursa/Controls/DateTimePicker/TimePicker.cs b/src/Ursa/Controls/DateTimePicker/TimePicker.cs
index 6650a24..9cacca4 100644
--- a/src/Ursa/Controls/DateTimePicker/TimePicker.cs
+++ b/src/Ursa/Controls/DateTimePicker/TimePicker.cs
@@ -4,14 +4,33 @@ using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Irihi.Avalonia.Shared.Contracts;
-namespace Ursa.Controls.TimePicker;
+namespace Ursa.Controls;
-public class TimePicker: TemplatedControl, IClearControl
+public class TimePicker : TemplatedControl, IClearControl
{
- private TimeSpan? _selectedTimeHolder;
-
public static readonly StyledProperty DisplayFormatProperty = AvaloniaProperty.Register(
- nameof(DisplayFormat), defaultValue: "HH:mm:ss");
+ nameof(DisplayFormat), "HH:mm:ss");
+
+ public static readonly StyledProperty PanelFormatProperty = AvaloniaProperty.Register(
+ nameof(PanelFormat), "HH mm ss");
+
+ public static readonly StyledProperty SelectedTimeProperty =
+ AvaloniaProperty.Register(
+ nameof(SelectedTime));
+
+ public static readonly StyledProperty NeedConfirmationProperty = AvaloniaProperty.Register(
+ nameof(NeedConfirmation));
+
+ public static readonly StyledProperty IsLoopingProperty = AvaloniaProperty.Register(
+ nameof(IsLooping));
+
+ private TimeSpan? _selectedTimeHolder;
+
+ static TimePicker()
+ {
+ PanelFormatProperty.Changed.AddClassHandler((picker, args) =>
+ picker.OnPanelFormatChanged(args));
+ }
public string DisplayFormat
{
@@ -19,26 +38,17 @@ public class TimePicker: TemplatedControl, IClearControl
set => SetValue(DisplayFormatProperty, value);
}
- public static readonly StyledProperty PanelFormatProperty = AvaloniaProperty.Register(
- nameof(PanelFormat), defaultValue: "HH mm ss");
-
public string PanelFormat
{
get => GetValue(PanelFormatProperty);
set => SetValue(PanelFormatProperty, value);
}
- public static readonly StyledProperty SelectedTimeProperty = AvaloniaProperty.Register(
- nameof(SelectedTime));
-
public TimeSpan? SelectedTime
{
get => GetValue(SelectedTimeProperty);
set => SetValue(SelectedTimeProperty, value);
}
-
- public static readonly StyledProperty NeedConfirmationProperty = AvaloniaProperty.Register(
- nameof(NeedConfirmation));
public bool NeedConfirmation
{
@@ -46,65 +56,47 @@ public class TimePicker: TemplatedControl, IClearControl
set => SetValue(NeedConfirmationProperty, value);
}
- public static readonly StyledProperty IsLoopingProperty = AvaloniaProperty.Register(
- nameof(IsLooping));
-
public bool IsLooping
{
get => GetValue(IsLoopingProperty);
set => SetValue(IsLoopingProperty, value);
}
- static TimePicker()
+ public void Clear()
{
- PanelFormatProperty.Changed.AddClassHandler((picker, args)=> picker.OnPanelFormatChanged(args));
+ SetCurrentValue(SelectedTimeProperty, null);
}
private void OnPanelFormatChanged(AvaloniaPropertyChangedEventArgs args)
{
var format = args.NewValue.Value;
- string[] parts = format.Split(new char[] { ' ', '-', ':' });
+ var parts = format.Split(' ', '-', ':');
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
-
}
private void OnSelectionChanged()
{
if (NeedConfirmation)
- {
_selectedTimeHolder = new TimeSpan();
- }
else
- {
SelectedTime = new TimeSpan();
- }
}
- public void Clear()
- {
- SetCurrentValue(SelectedTimeProperty, null);
- }
-
public void Confirm()
{
if (NeedConfirmation)
- {
// TODO: close popup.
SetCurrentValue(SelectedTimeProperty, _selectedTimeHolder);
- }
}
protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error)
{
base.UpdateDataValidation(property, state, error);
- if (property == SelectedTimeProperty)
- {
- DataValidationErrors.SetError(this, error);
- }
+ if (property == SelectedTimeProperty) DataValidationErrors.SetError(this, error);
}
}
\ No newline at end of file
diff --git a/src/Ursa/Controls/DateTimePicker/TimePickerPresenter.cs b/src/Ursa/Controls/DateTimePicker/TimePickerPresenter.cs
new file mode 100644
index 0000000..ac27c1f
--- /dev/null
+++ b/src/Ursa/Controls/DateTimePicker/TimePickerPresenter.cs
@@ -0,0 +1,129 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Metadata;
+using Avalonia.Controls.Primitives;
+
+namespace Ursa.Controls;
+
+[TemplatePart(PART_PickerContainer, typeof(Grid))]
+[TemplatePart(PART_HourSelector, typeof(DateTimePickerPanel))]
+[TemplatePart(PART_MinuteSelector, typeof(DateTimePickerPanel))]
+[TemplatePart(PART_SecondSelector, typeof(DateTimePickerPanel))]
+[TemplatePart(PART_AmPmSelector, typeof(DateTimePickerPanel))]
+public class TimePickerPresenter: TemplatedControl
+{
+ public const string PART_HourSelector = "PART_HourSelector";
+ public const string PART_MinuteSelector = "PART_MinuteSelector";
+ public const string PART_SecondSelector = "PART_SecondSelector";
+ public const string PART_AmPmSelector = "PART_AmPmSelector";
+ public const string PART_PickerContainer = "PART_PickerContainer";
+
+ private DateTimePickerPanel? _hourSelector;
+ private DateTimePickerPanel? _minuteSelector;
+ private DateTimePickerPanel? _secondSelector;
+ private DateTimePickerPanel? _ampmSelector;
+ private Grid? _pickerContainer;
+
+ public static readonly StyledProperty NeedsConfirmationProperty = AvaloniaProperty.Register(
+ nameof(NeedsConfirmation));
+
+ public bool NeedsConfirmation
+ {
+ get => GetValue(NeedsConfirmationProperty);
+ set => SetValue(NeedsConfirmationProperty, value);
+ }
+
+ public static readonly StyledProperty MinuteIncrementProperty = AvaloniaProperty.Register(
+ nameof(MinuteIncrement));
+
+ public int MinuteIncrement
+ {
+ get => GetValue(MinuteIncrementProperty);
+ set => SetValue(MinuteIncrementProperty, value);
+ }
+
+ public static readonly StyledProperty TimeProperty = AvaloniaProperty.Register(
+ nameof(Time));
+
+ public TimeSpan? Time
+ {
+ get => GetValue(TimeProperty);
+ set => SetValue(TimeProperty, value);
+ }
+
+ public static readonly StyledProperty Use12HoursProperty = AvaloniaProperty.Register(
+ nameof(Use12Hours));
+
+ public bool Use12Hours
+ {
+ get => GetValue(Use12HoursProperty);
+ set => SetValue(Use12HoursProperty, value);
+ }
+
+ public static readonly StyledProperty PanelFormatProperty = AvaloniaProperty.Register(
+ nameof(PanelFormat));
+
+ public string PanelFormat
+ {
+ get => GetValue(PanelFormatProperty);
+ set => SetValue(PanelFormatProperty, value);
+ }
+
+ public TimePickerPresenter()
+ {
+ SetCurrentValue(TimeProperty, DateTime.Now.TimeOfDay);
+ }
+
+ protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
+ {
+ base.OnApplyTemplate(e);
+ _hourSelector = e.NameScope.Find(PART_HourSelector);
+ _minuteSelector = e.NameScope.Find(PART_MinuteSelector);
+ _secondSelector = e.NameScope.Find(PART_SecondSelector);
+ _ampmSelector = e.NameScope.Find(PART_AmPmSelector);
+ _pickerContainer = e.NameScope.Find(PART_PickerContainer);
+ Initialize();
+ }
+
+ private void Initialize()
+ {
+ if (_pickerContainer is null) return;
+ var use12Clock = Use12Hours;
+ if (_hourSelector is not null)
+ {
+ _hourSelector.MaximumValue = use12Clock ? 12 : 23;
+ _hourSelector.MinimumValue = use12Clock ? 1 : 0;
+ _hourSelector.ItemFormat = "%h";
+ var hour = Time?.Hours;
+ _hourSelector.SelectedValue = hour ?? 0;
+ }
+ if(_minuteSelector is not null)
+ {
+ _minuteSelector.MaximumValue = 59;
+ _minuteSelector.MinimumValue = 0;
+ _minuteSelector.ItemFormat = "mm";
+ var minute = Time?.Minutes;
+ _minuteSelector.SelectedValue = minute ?? 0;
+ }
+ if(_secondSelector is not null)
+ {
+ _secondSelector.MaximumValue = 59;
+ _secondSelector.MinimumValue = 0;
+ _secondSelector.ItemFormat = "mm";
+ var second = Time?.Seconds;
+ _secondSelector.SelectedValue = second ?? 0;
+ }
+ if(_ampmSelector is not null)
+ {
+ _ampmSelector.MaximumValue = 1;
+ _ampmSelector.MinimumValue = 0;
+ _ampmSelector.ItemFormat = "%t";
+ var ampm = Time?.Hours switch
+ {
+ >= 12 => 1,
+ _ => 0
+ };
+ _ampmSelector.SelectedValue = ampm;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ursa/Controls/DateTimePicker/UrsaTimePickerPanel.cs b/src/Ursa/Controls/DateTimePicker/UrsaDateTimeScrollPanel.cs
similarity index 57%
rename from src/Ursa/Controls/DateTimePicker/UrsaTimePickerPanel.cs
rename to src/Ursa/Controls/DateTimePicker/UrsaDateTimeScrollPanel.cs
index e38d549..36a8893 100644
--- a/src/Ursa/Controls/DateTimePicker/UrsaTimePickerPanel.cs
+++ b/src/Ursa/Controls/DateTimePicker/UrsaDateTimeScrollPanel.cs
@@ -9,59 +9,75 @@ using Avalonia.VisualTree;
namespace Ursa.Controls.Panels;
-public enum TimePickerPanelType
+public enum UrsaDateTimeScrollPanelType
{
+ Year,
+ Month,
+ Day,
Hour,
Minute,
Second,
TimePeriod // AM/PM
}
+
///
-/// The panel to display items for time selection
+/// The panel to display items for time selection
///
-public class UrsaTimePickerPanel: Panel, ILogicalScrollable
+public class UrsaDateTimeScrollPanel : Panel, ILogicalScrollable
{
- private ScrollContentPresenter? _parentScroller;
- private double _extendOne;
- private Vector _offset;
- private bool _initialized;
- private int _countItemAboveBelowSelected;
-
- public Vector Offset
- {
- get => _offset;
- set => SetOffset(value);
- }
-
- private int _increment;
-
- public int Increment
- {
- get => _increment;
- set => _increment = value;
- }
-
- private int _selectedIndex;
- public int SelectedIndex
- {
- get => _selectedIndex;
- set
- {
- _selectedIndex = value;
- }
- }
-
- private int _selectedValue;
-
- public int SelectedValue
- {
- get => _selectedValue;
- set => _selectedValue = value;
- }
-
public static readonly StyledProperty ItemHeightProperty =
- AvaloniaProperty.Register(
- nameof(ItemHeight), defaultValue: 32);
+ AvaloniaProperty.Register(
+ nameof(ItemHeight), 32);
+
+ public static readonly StyledProperty ShouldLoopProperty =
+ AvaloniaProperty.Register(
+ nameof(ShouldLoop));
+
+ public static readonly StyledProperty PanelTypeProperty = AvaloniaProperty.Register(
+ nameof(PanelType));
+
+ public UrsaDateTimeScrollPanelType PanelType
+ {
+ get => GetValue(PanelTypeProperty);
+ set => SetValue(PanelTypeProperty, value);
+ }
+
+ public static readonly StyledProperty ItemFormatProperty = AvaloniaProperty.Register(
+ nameof(ItemFormat));
+
+ public string ItemFormat
+ {
+ get => GetValue(ItemFormatProperty);
+ set => SetValue(ItemFormatProperty, value);
+ }
+
+
+ private int _countItemAboveBelowSelected;
+ private double _extendOne;
+
+ private bool _initialized;
+ private int _maximumValue;
+ private int _minimumValue;
+ private Vector _offset;
+ private ScrollContentPresenter? _parentScroller;
+
+ private int _range;
+
+ private int _totalItems;
+
+ static UrsaDateTimeScrollPanel()
+ {
+ ItemHeightProperty.Changed.AddClassHandler((panel, args) =>
+ panel.OnItemHeightChanged(args));
+ AffectsArrange(ItemHeightProperty);
+ AffectsMeasure(ItemHeightProperty);
+ }
+
+ public int Increment { get; set; }
+
+ public int SelectedIndex { get; set; }
+
+ public int SelectedValue { get; set; }
public double ItemHeight
{
@@ -69,29 +85,61 @@ public class UrsaTimePickerPanel: Panel, ILogicalScrollable
set => SetValue(ItemHeightProperty, value);
}
- public static readonly StyledProperty ShouldLoopProperty = AvaloniaProperty.Register(
- nameof(ShouldLoop));
-
public bool ShouldLoop
{
get => GetValue(ShouldLoopProperty);
set => SetValue(ShouldLoopProperty, value);
}
-
- static UrsaTimePickerPanel()
+
+ public Vector Offset
{
- ItemHeightProperty.Changed.AddClassHandler((panel, args) => panel.OnItemHeightChanged(args));
- AffectsArrange(ItemHeightProperty);
- AffectsMeasure(ItemHeightProperty);
+ get => _offset;
+ set => SetOffset(value);
}
- private Size _scrollSize;
- private Size _pageScrollSize;
+ public Size Extent { get; private set; }
+
+ public Size Viewport => Bounds.Size;
+
+ public bool BringIntoView(Control target, Rect targetRect)
+ {
+ return false;
+ }
+
+ public Control? GetControlInDirection(NavigationDirection direction, Control? from)
+ {
+ return null;
+ }
+
+ public void RaiseScrollInvalidated(System.EventArgs e)
+ {
+ ScrollInvalidated?.Invoke(this, e);
+ }
+
+ public bool CanHorizontallyScroll
+ {
+ get => false;
+ set { }
+ }
+
+ public bool CanVerticallyScroll
+ {
+ get => false;
+ set { }
+ }
+
+ public bool IsLogicalScrollEnabled => true;
+ public Size ScrollSize { get; private set; }
+
+ public Size PageScrollSize { get; private set; }
+
+ public event EventHandler? ScrollInvalidated;
+
private void OnItemHeightChanged(AvaloniaPropertyChangedEventArgs args)
{
var newValue = args.NewValue.Value;
- _scrollSize = new Size(0, newValue);
- _pageScrollSize = new Size(0, newValue * 3);
+ ScrollSize = new Size(0, newValue);
+ PageScrollSize = new Size(0, newValue * 3);
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
@@ -127,10 +175,7 @@ public class UrsaTimePickerPanel: Panel, ILogicalScrollable
private ListBoxItem? GetItemFromSource(Visual source)
{
var item = source;
- while (item != null && !(item is ListBoxItem))
- {
- item = item.GetVisualParent();
- }
+ while (item != null && !(item is ListBoxItem)) item = item.GetVisualParent();
return item as ListBoxItem;
}
@@ -138,18 +183,15 @@ public class UrsaTimePickerPanel: Panel, ILogicalScrollable
{
if (double.IsInfinity(availableSize.Width) || double.IsInfinity(availableSize.Height))
throw new InvalidOperationException("Panel must have finite height");
- if(_initialized) UpdateHelperInfo();
- double initY = availableSize.Height / 2.0 - ItemHeight / 2.0;
+ if (_initialized) UpdateHelperInfo();
+ var initY = availableSize.Height / 2.0 - ItemHeight / 2.0;
_countItemAboveBelowSelected = (int)Math.Ceiling(initY / ItemHeight);
-
+
var children = Children;
-
+
CreateOrDestroyItems(children);
-
- for(int i = 0; i< children.Count; i++)
- {
- children[i].Measure(availableSize);
- }
+
+ for (var i = 0; i < children.Count; i++) children[i].Measure(availableSize);
if (!_initialized)
{
@@ -163,72 +205,63 @@ public class UrsaTimePickerPanel: Panel, ILogicalScrollable
protected override Size ArrangeOverride(Size finalSize)
{
- if (Children.Count == 0)
- {
- return base.ArrangeOverride(finalSize);
- }
+ if (Children.Count == 0) return base.ArrangeOverride(finalSize);
var itemHeight = ItemHeight;
var children = Children;
Rect rc;
- double initY = finalSize.Height / 2.0 - itemHeight / 2.0;
+ var initY = finalSize.Height / 2.0 - itemHeight / 2.0;
if (ShouldLoop)
{
var currentSet = Math.Truncate(Offset.Y / _extendOne);
- initY += _extendOne * currentSet + (_selectedIndex - _countItemAboveBelowSelected) * ItemHeight;
+ initY += _extendOne * currentSet + (SelectedIndex - _countItemAboveBelowSelected) * ItemHeight;
foreach (var child in children)
{
- rc = new Rect(0, initY-Offset.Y, finalSize.Width, itemHeight);
+ rc = new Rect(0, initY - Offset.Y, finalSize.Width, itemHeight);
child.Arrange(rc);
initY += itemHeight;
}
}
else
{
- var first = Math.Max(0, _selectedIndex - _countItemAboveBelowSelected);
+ var first = Math.Max(0, SelectedIndex - _countItemAboveBelowSelected);
foreach (var child in children)
{
- rc = new Rect(0, initY+first+itemHeight-Offset.Y, finalSize.Width, itemHeight);
+ rc = new Rect(0, initY + first + itemHeight - Offset.Y, finalSize.Width, itemHeight);
child.Arrange(rc);
initY += itemHeight;
}
}
+
return finalSize;
}
private void OnScrollGestureEnded(object sender, ScrollGestureEndedEventArgs e)
{
var snapY = Math.Round(Offset.Y / ItemHeight) * ItemHeight;
- if(!snapY.Equals(Offset.Y))
- {
- Offset = Offset.WithY(snapY);
- }
+ if (!snapY.Equals(Offset.Y)) Offset = Offset.WithY(snapY);
}
-
+
private void SetOffset(Vector value)
{
var oldValue = _offset;
_offset = value;
var dy = _offset.Y - oldValue.Y;
- var children = this.Children;
+ var children = Children;
// TODO
}
- private int _range;
- private int _maximumValue;
- private int _minimumValue;
- private int _totalItems;
private void UpdateHelperInfo()
{
_range = _maximumValue - _minimumValue + 1;
- _totalItems = (int)Math.Ceiling((double)_range / _increment);
+ _totalItems = (int)Math.Ceiling((double)_range / Increment);
var itemHeight = ItemHeight;
- _extent = new Size(0, ShouldLoop ? _totalItems * itemHeight * 100 : _totalItems * itemHeight);
+ Extent = new Size(0, ShouldLoop ? _totalItems * itemHeight * 100 : _totalItems * itemHeight);
_extendOne = _totalItems * itemHeight;
_offset = new Vector(0,
- ShouldLoop ? _extendOne * 50 + _selectedIndex * itemHeight : _selectedIndex * itemHeight);
+ ShouldLoop ? _extendOne * 50 + SelectedIndex * itemHeight : SelectedIndex * itemHeight);
}
private void UpdateItems()
@@ -241,94 +274,63 @@ public class UrsaTimePickerPanel: Panel, ILogicalScrollable
int first;
if (ShouldLoop)
{
- first = (_selectedIndex - _countItemAboveBelowSelected) % _totalItems;
+ first = (SelectedIndex - _countItemAboveBelowSelected) % _totalItems;
first = first < 0 ? min + (first + _totalItems) * Increment : min + first * Increment;
}
else
{
- first = min + Math.Max(0, _selectedIndex - _countItemAboveBelowSelected) * Increment;
+ first = min + Math.Max(0, SelectedIndex - _countItemAboveBelowSelected) * Increment;
}
- for (int i = 0; i < children.Count; i++)
+ for (var i = 0; i < children.Count; i++)
{
- ListBoxItem item = (ListBoxItem)children[i];
+ var item = (ListBoxItem)children[i];
item.Content = first + i * Increment; // TODO
item.Tag = first;
item.IsSelected = first == selected;
first += Increment;
- if(first > max)
- {
- first = min;
- }
+ if (first > max) first = min;
}
-
}
private void CreateOrDestroyItems(Avalonia.Controls.Controls children)
{
- int totalItemsInViewport = _countItemAboveBelowSelected * 2 + 1;
+ var totalItemsInViewport = _countItemAboveBelowSelected * 2 + 1;
if (!ShouldLoop)
{
- int numItemAboveSelect = _countItemAboveBelowSelected;
- if (_selectedIndex - _countItemAboveBelowSelected < 0)
- {
- numItemAboveSelect = _selectedIndex;
- }
- int numItemBelowSelect = _countItemAboveBelowSelected;
- if (_selectedIndex + _countItemAboveBelowSelected >= _totalItems)
- {
- numItemBelowSelect = _totalItems - _selectedIndex - 1;
- }
+ var numItemAboveSelect = _countItemAboveBelowSelected;
+ if (SelectedIndex - _countItemAboveBelowSelected < 0) numItemAboveSelect = SelectedIndex;
+ var numItemBelowSelect = _countItemAboveBelowSelected;
+ if (SelectedIndex + _countItemAboveBelowSelected >= _totalItems)
+ numItemBelowSelect = _totalItems - SelectedIndex - 1;
totalItemsInViewport = numItemAboveSelect + numItemBelowSelect + 1;
}
- while (children.Count totalItemsInViewport)
{
var countToRemove = children.Count - totalItemsInViewport;
- children.RemoveRange(children.Count-countToRemove, countToRemove);
+ children.RemoveRange(children.Count - countToRemove, countToRemove);
}
}
private int CoerceSelected(int newValue)
{
- if(newValue < _minimumValue)
- {
- return _minimumValue;
- }
- if(newValue > _maximumValue)
- {
- return _maximumValue;
- }
- if (newValue % _increment == 0) return newValue;
- var items = Enumerable.Range(_minimumValue, _range).Where(x => x % _increment == 0).ToList();
+ if (newValue < _minimumValue) return _minimumValue;
+ if (newValue > _maximumValue) return _maximumValue;
+ if (newValue % Increment == 0) return newValue;
+ var items = Enumerable.Range(_minimumValue, _range).Where(x => x % Increment == 0).ToList();
var nearest = items.Aggregate((x, y) => Math.Abs(x - newValue) > Math.Abs(y - newValue) ? y : x);
return items.IndexOf(nearest) * Increment;
}
+
public event EventHandler? OnSelectionChanged;
- private Size _extent;
- public Size Extent {
- get => _extent;
- private set => _extent = value;
- }
- public Size Viewport => Bounds.Size;
- public bool BringIntoView(Control target, Rect targetRect) => false;
- public Control? GetControlInDirection(NavigationDirection direction, Control? from) => null;
- public void RaiseScrollInvalidated(System.EventArgs e) => ScrollInvalidated?.Invoke(this, e);
- public bool CanHorizontallyScroll { get => false; set { } }
- public bool CanVerticallyScroll { get => false; set {} }
- public bool IsLogicalScrollEnabled => true;
- public Size ScrollSize => _scrollSize;
- public Size PageScrollSize => _pageScrollSize;
- public event EventHandler? ScrollInvalidated;
public event EventHandler? SelectionChanged;
}
\ No newline at end of file