Skip to content

Commit

Permalink
feat: WinUI TimePicker
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/Uno.UI/Generated/3.0.0.0/Microsoft.UI.Xaml.Controls/TimePickerFlyout.cs
#	src/Uno.UI/Generated/3.0.0.0/Windows.UI.Xaml.Controls/TimePicker.cs
#	src/Uno.UI/Microsoft/UI/Input/InputKeyboardSource.cs
#	src/Uno.UI/UI/Xaml/Automation/Peers/TimePickerAutomationPeer.cs
#	src/Uno.UI/UI/Xaml/Controls/PlatformHelpers.cs
#	src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePickedEventArgs.cs
#	src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePicker.cs
#	src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePickerFlyout.cs
#	src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePickerFlyoutPresenter.cs
#	src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePickerSelectedValueChangedEventArgs.cs
#	src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePickerValueChangedEventArgs.cs
  • Loading branch information
MartinZikmund committed Jan 18, 2024
1 parent 279747e commit 2810779
Show file tree
Hide file tree
Showing 27 changed files with 4,428 additions and 577 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
#pragma warning disable 114 // new keyword hiding
namespace Microsoft.UI.Xaml.Automation.Peers
{
#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented]
#endif
public partial class TimePickerFlyoutPresenterAutomationPeer : global::Microsoft.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer
{
#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
internal TimePickerFlyoutPresenterAutomationPeer()
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
#pragma warning disable 114 // new keyword hiding
namespace Microsoft.UI.Xaml.Controls
{
#if false || false || IS_UNIT_TESTS || false || false || false || false
#if false || false || false || false || false || false || false
[global::Uno.NotImplemented("IS_UNIT_TESTS")]
#endif
public partial class TimePickerFlyoutPresenter
public partial class TimePickerFlyoutPresenter
{
#if false || false || IS_UNIT_TESTS || false || false || false || false
#if false || false || false || false || false || false || false
internal TimePickerFlyoutPresenter()
{
}
#endif
#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public bool IsDefaultShadowEnabled
{
Expand All @@ -27,7 +27,7 @@ public bool IsDefaultShadowEnabled
}
}
#endif
#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public static global::Microsoft.UI.Xaml.DependencyProperty IsDefaultShadowEnabledProperty { get; } =
Microsoft.UI.Xaml.DependencyProperty.Register(
Expand Down
10 changes: 5 additions & 5 deletions src/Uno.UI/Microsoft/UI/Input/InputKeyboardSource.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace Microsoft.UI.Input;
using Uno.UI.Core;

namespace Microsoft.UI.Input;

public partial class InputKeyboardSource
{
#if HAS_UNO_WINUI
public
public
#else
internal
internal
#endif
static Windows.UI.Core.CoreVirtualKeyStates GetKeyStateForCurrentThread(Windows.System.VirtualKey virtualKey)
=> Microsoft.UI.Xaml.Window.Current.CoreWindow.GetKeyState(virtualKey);
Expand Down
6 changes: 0 additions & 6 deletions src/Uno.UI/Mixins/DependencyPropertyMixins.tt
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,10 @@
.Property("DayVisible", "bool", "true")
.Property("MonthVisible", "bool", "true")
.Property("YearVisible", "bool", "true")
.Class("TimePickerFlyout")
.Property("Time", "TimeSpan", "DateTime.Now.TimeOfDay")
.Property("MinuteIncrement", "int", "1")
.Property("ClockIdentifier", "string", "Windows.Globalization.ClockIdentifiers.TwelveHour")
.Class("TimePickerSelector")
.Property("Time", "TimeSpan", "DateTime.Now.TimeOfDay")
.Property("MinuteIncrement", "int", "1")
.Property("ClockIdentifier", "string", "Windows.Globalization.ClockIdentifiers.TwelveHour")
.Class("TimePicker")
.Property("ClockIdentifier", "string", "Windows.Globalization.ClockIdentifiers.TwelveHour")

.Namespace("Microsoft.UI.Xaml.Controls.Primitives")
.Class("SelectorItem")
Expand Down
6 changes: 6 additions & 0 deletions src/Uno.UI/UI/Xaml/Automation/AutomationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,11 @@ public static string GetPlainText(DependencyObject obj)

return null;
}

public static void SetElementAutomationName(DependencyObject pDO, string name) =>
AutomationProperties.SetName(pDO, name);

public static void SetElementAutomationId(DependencyObject pDO, string id) =>
AutomationProperties.SetAutomationId(pDO, id);
}
}
43 changes: 31 additions & 12 deletions src/Uno.UI/UI/Xaml/Automation/Peers/TimePickerAutomationPeer.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
using Microsoft.UI.Xaml.Controls;
using Uno.UI.Helpers.WinUI;
using Windows.UI.Xaml.Controls;

namespace Microsoft.UI.Xaml.Automation.Peers
namespace Microsoft.UI.Xaml.Automation.Peers;

public partial class TimePickerAutomationPeer : FrameworkElementAutomationPeer
{
public partial class TimePickerAutomationPeer : FrameworkElementAutomationPeer
private string UIA_AP_TIMEPICKER = nameof(UIA_AP_TIMEPICKER);

public TimePickerAutomationPeer(TimePicker owner) : base(owner)
{
public TimePickerAutomationPeer(TimePicker owner) : base(owner)
{
}
}

protected override string GetClassNameCore()
{
return "TimePicker";
}
protected override string GetClassNameCore() => nameof(TimePicker);

protected override AutomationControlType GetAutomationControlTypeCore()
protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Group;

protected override string GetNameCore()
{
var returnValue = base.GetNameCore();

if (string.IsNullOrEmpty(returnValue))
{
return AutomationControlType.Group;
var owner = (TimePicker)Owner;

var spHeaderAsInspectable = owner.Header;
if (spHeaderAsInspectable is not null)
{
returnValue = FrameworkElement.GetStringFromObject(spHeaderAsInspectable);
}

if (string.IsNullOrEmpty(returnValue))
{
returnValue = ResourceAccessor.GetLocalizedStringResource(UIA_AP_TIMEPICKER);
}
}

return returnValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Uno.UI.Helpers.WinUI;
using Windows.UI.Xaml.Controls;

namespace Windows.UI.Xaml.Automation.Peers;

/// <summary>
/// Exposes TimePickerFlyoutPresenter types to Microsoft UI Automation.
/// </summary>
public sealed partial class TimePickerFlyoutPresenterAutomationPeer : FrameworkElementAutomationPeer
{
private string UIA_AP_TIMEPICKER_NAME = nameof(UIA_AP_TIMEPICKER_NAME);

internal TimePickerFlyoutPresenterAutomationPeer(TimePickerFlyoutPresenter owner) : base(owner)
{
}

protected override AutomationControlType GetAutomationControlTypeCore() => AutomationControlType.Pane;

protected override string GetClassNameCore() => nameof(TimePickerFlyoutPresenter);

protected override string GetNameCore() => ResourceAccessor.GetLocalizedStringResource(UIA_AP_TIMEPICKER_NAME);
}
50 changes: 42 additions & 8 deletions src/Uno.UI/UI/Xaml/Controls/PlatformHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,49 @@
using Uno;
using Microsoft.UI.Input;
using Uno;
using Windows.System;
using Windows.UI.Core;

namespace Microsoft.UI.Xaml.Controls
namespace Microsoft.UI.Xaml.Controls;

internal static class PlatformHelpers
{
internal static class PlatformHelpers
public static VirtualKeyModifiers GetKeyboardModifiers()
{
//TODO Uno: Should be implemented for proper keyboard handling.
[NotImplemented]
public static VirtualKeyModifiers GetKeyboardModifiers() => VirtualKeyModifiers.None;
var pnKeyboardModifiers = VirtualKeyModifiers.None;

var keyState = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Menu);
if (keyState.HasFlag(CoreVirtualKeyStates.Down))
{
pnKeyboardModifiers |= VirtualKeyModifiers.Menu;
}

keyState = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control);
if (keyState.HasFlag(CoreVirtualKeyStates.Down))
{
pnKeyboardModifiers |= VirtualKeyModifiers.Control;
}

keyState = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Shift);
if (keyState.HasFlag(CoreVirtualKeyStates.Down))
{
pnKeyboardModifiers |= VirtualKeyModifiers.Shift;
}

public static void RequestInteractionSoundForElement(ElementSoundKind soundToPlay, DependencyObject element) =>
ElementSoundPlayer.RequestInteractionSoundForElement(soundToPlay, element);
keyState = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.RightWindows);
if (keyState.HasFlag(CoreVirtualKeyStates.Down))
{
pnKeyboardModifiers |= VirtualKeyModifiers.Windows;
}

keyState = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.LeftWindows);
if (keyState.HasFlag(CoreVirtualKeyStates.Down))
{
pnKeyboardModifiers |= VirtualKeyModifiers.Windows;
}

return pnKeyboardModifiers;
}

public static void RequestInteractionSoundForElement(ElementSoundKind soundToPlay, DependencyObject element) =>
ElementSoundPlayer.RequestInteractionSoundForElement(soundToPlay, element);
}
38 changes: 25 additions & 13 deletions src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePickedEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
using System;

namespace Microsoft.UI.Xaml.Controls
namespace Microsoft.UI.Xaml.Controls;

/// <summary>
/// Provides data for the TimePicked event.
/// </summary>
public sealed partial class TimePickedEventArgs : DependencyObject
{
public partial class TimePickedEventArgs
/// <summary>
/// Initializes a new instance of the TimePickedEventArgs class.
/// </summary>
public TimePickedEventArgs()
{
public TimePickedEventArgs()
{
}

public TimePickedEventArgs(TimeSpan oldTime, TimeSpan newTime)
{
OldTime = oldTime;
NewTime = newTime;
}
}

public TimeSpan OldTime { get; }
public TimeSpan NewTime { get; }
internal TimePickedEventArgs(TimeSpan oldTime, TimeSpan newTime)
{
OldTime = oldTime;
NewTime = newTime;
}

/// <summary>
/// Gets the old time value.
/// </summary>
public TimeSpan OldTime { get; }

/// <summary>
/// Gets the time that was selected by the user.
/// </summary>
public TimeSpan NewTime { get; }
}
118 changes: 118 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/TimePicker/TimePicker.Flyout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System;
using Uno;
using Uno.UI;

namespace Windows.UI.Xaml.Controls;

partial class TimePicker
{
#if __IOS__ || __ANDROID__
private const bool DEFAULT_NATIVE_STYLE = true;
#else
private const bool DEFAULT_NATIVE_STYLE = false;
#endif

[UnoOnly]
public static DependencyProperty UseNativeStyleProperty { get; } = DependencyProperty.Register(
"UseNativeStyle",
typeof(bool),
typeof(TimePicker),
new FrameworkPropertyMetadata(DEFAULT_NATIVE_STYLE));

/// <summary>
/// [UnoOnly] If we should use the native picker for the platform.
/// IMPORTANT: must be set before the first time the picker is opened.
/// </summary>
[UnoOnly]
public bool UseNativeStyle
{
get => (bool)GetValue(UseNativeStyleProperty);
set => SetValue(UseNativeStyleProperty, value);
}

[UnoOnly]
public static DependencyProperty UseNativeMinMaxDatesProperty { get; } = DependencyProperty.Register(
"UseNativeMinMaxDates",
typeof(bool),
typeof(TimePicker),
new FrameworkPropertyMetadata(false));

/// <summary>
/// [UnoOnly] When using native pickers (through the UseNativeStyle property),
/// setting this to true will interpret MinYear/MaxYear as MinDate and MaxDate.
/// </summary>
/// <remarks>
/// This property has no effect when not using native pickers.
/// </remarks>
[UnoOnly]
public bool UseNativeMinMaxDates
{
get => (bool)GetValue(UseNativeMinMaxDatesProperty);
set => SetValue(UseNativeMinMaxDatesProperty, value);
}

/// <summary>
/// FlyoutPresenterStyle is an Uno-only property to allow the styling of the TimePicker's FlyoutPresenter.
/// </summary>
[UnoOnly]
public Style FlyoutPresenterStyle
{
get => (Style)this.GetValue(FlyoutPresenterStyleProperty);
set => this.SetValue(FlyoutPresenterStyleProperty, value);
}

[UnoOnly]
public static DependencyProperty FlyoutPresenterStyleProperty { get; } =
DependencyProperty.Register(
nameof(FlyoutPresenterStyle),
typeof(Style),
typeof(TimePicker),
new FrameworkPropertyMetadata(
default(Style),
FrameworkPropertyMetadataOptions.ValueDoesNotInheritDataContext));


private Lazy<TimePickerFlyout> _lazyFlyout;

private TimePickerFlyout _flyout => _lazyFlyout.Value;


private void InitPartial()
{
#if __IOS__ || __ANDROID__
TimePickerFlyout CreateFlyout()
{
var f = UseNativeStyle
? new NativeTimePickerFlyout()
: CreateManagedTimePickerFlyout();

f.DatePicked += OnPicked;

return f;
}

_lazyFlyout = new Lazy<TimePickerFlyout>(CreateFlyout);
#else
_lazyFlyout = new Lazy<TimePickerFlyout>(CreateManagedTimePickerFlyout);
#endif

void OnPicked(TimePickerFlyout snd, TimePickedEventArgs evt)
{
SelectedTime = evt.NewTime;
Time = evt.NewTime;

if (evt.NewTime != evt.OldTime)
{
TimeChanged?.Invoke(this, new TimePickerValueChangedEventArgs(evt.NewTime, evt.OldTime));
}
}

TimePickerFlyout CreateManagedTimePickerFlyout()
{
var flyout = new TimePickerFlyout(); //TODO:MZ: { TimePickerFlyoutPresenterStyle = FlyoutPresenterStyle };
flyout.TimePicked += OnPicked;

return flyout;
}
}
}
Loading

0 comments on commit 2810779

Please sign in to comment.