Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 0 additions & 41 deletions src/MainDemo.Wpf/Domain/PickersViewModel.cs

This file was deleted.

255 changes: 108 additions & 147 deletions src/MainDemo.Wpf/Pickers.xaml

Large diffs are not rendered by default.

41 changes: 0 additions & 41 deletions src/MaterialDesign3.Demo.Wpf/Domain/PickersViewModel.cs

This file was deleted.

34 changes: 28 additions & 6 deletions src/MaterialDesign3.Demo.Wpf/Pickers.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,11 @@
</Grid.Resources>
<Calendar materialDesign:CalendarAssist.HeaderBackground="{DynamicResource MaterialDesign.Brush.Primary.Dark}"
materialDesign:CalendarAssist.HeaderForeground="{DynamicResource MaterialDesign.Brush.Primary.Dark.Foreground}"
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Background="{DynamicResource MaterialDesign.Brush.Primary.Light}"
CalendarButtonStyle="{StaticResource SecondaryCalendarButton}"
CalendarDayButtonStyle="{StaticResource SecondaryCalendarDayButton}"
Foreground="{DynamicResource MaterialDesign.Brush.Primary.Light.Foreground}" />
Foreground="{DynamicResource MaterialDesign.Brush.Primary.Light.Foreground}"
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" />
</Grid>
</smtx:XamlDisplay>
</GroupBox>
Expand Down Expand Up @@ -439,11 +439,11 @@
</Grid.Resources>
<Calendar materialDesign:CalendarAssist.HeaderBackground="#A2E9FF"
materialDesign:CalendarAssist.HeaderForeground="Black"
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Background="#343C3F"
CalendarButtonStyle="{StaticResource CustomCalendarButton}"
CalendarDayButtonStyle="{StaticResource CustomCalendarDayButton}"
Foreground="White" />
Foreground="White"
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" />
</Grid>
</smtx:XamlDisplay>
</GroupBox>
Expand All @@ -468,8 +468,8 @@
Style="{StaticResource MaterialDesignCardGroupBox}">
<smtx:XamlDisplay UniqueKey="calendar_5">
<Calendar materialDesign:ElevationAssist.Elevation="Dp8"
Style="{StaticResource MaterialDesignCalendarPortraitForeground}"
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" />
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Style="{StaticResource MaterialDesignCalendarPortraitForeground}" />
</smtx:XamlDisplay>
</GroupBox>

Expand Down Expand Up @@ -559,6 +559,26 @@
</smtx:XamlDisplay>
</GroupBox>

<GroupBox Margin="10"
materialDesign:ColorZoneAssist.Mode="SecondaryMid"
materialDesign:ElevationAssist.Elevation="Dp8"
Header="MinuteSelectionStep"
Style="{StaticResource MaterialDesignCardGroupBox}">
<StackPanel Margin="0,0,16,16">
<TextBlock Margin="0,0,0,8" Text="You can change the granularity of selectable times with the MinuteSelectionStep property." />
<ComboBox materialDesign:HintAssist.Hint="MinuteSelectionStep"
ItemsSource="{Binding AvailableMinuteSelectionSteps}"
SelectedItem="{Binding SelectedMinuteSelectionStep}"
Style="{StaticResource MaterialDesignFilledComboBox}" />
<smtx:XamlDisplay UniqueKey="clock_13">
<materialDesign:Clock Width="auto"
Is24Hours="True"
MinuteSelectionStep="{Binding SelectedMinuteSelectionStep}"
Style="{StaticResource MaterialDesignClock}" />
</smtx:XamlDisplay>
</StackPanel>
</GroupBox>

</WrapPanel>
</Expander>

Expand Down Expand Up @@ -650,6 +670,8 @@
</GroupBox>




</WrapPanel>
</Expander>
</Grid>
Expand Down
2 changes: 1 addition & 1 deletion src/MaterialDesign3.Demo.Wpf/Pickers.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Diagnostics;
using System.Globalization;
using MaterialDesign3Demo.Domain;
using MaterialDesignDemo.Domain;
using MaterialDesignThemes.Wpf;

namespace MaterialDesign3Demo;
Expand Down
29 changes: 29 additions & 0 deletions src/MaterialDesignDemo.Shared/Domain/PickersViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using CommunityToolkit.Mvvm.ComponentModel;

namespace MaterialDesignDemo.Domain;

public partial class PickersViewModel : ObservableObject
{
[ObservableProperty]
private DateTime _date;
[ObservableProperty]
private DateTime _time;
[ObservableProperty]
private string? _validatingTime;
[ObservableProperty]
private DateTime? _futureValidatingDate;

public IReadOnlyList<int> AvailableMinuteSelectionSteps { get; }

[ObservableProperty]
private int _selectedMinuteSelectionStep;

public PickersViewModel()
{
Date = DateTime.Now;
Time = DateTime.Now;

AvailableMinuteSelectionSteps = [ 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 ];
SelectedMinuteSelectionStep = 15;
}
}
62 changes: 52 additions & 10 deletions src/MaterialDesignThemes.Wpf/Clock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,29 @@ public CornerRadius CornerRadius
set => SetValue(CornerRadiusProperty, value);
}

public static readonly DependencyProperty MinuteSelectionStepProperty = DependencyProperty.Register(
nameof(MinuteSelectionStep), typeof(int),typeof(Clock), new PropertyMetadata(1, MinuteSelectionStepPropertyChangedCallback));

private static void MinuteSelectionStepPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var clock = (Clock)d;

int step = (int)e.NewValue;

if (step < 1 || step > 60 || 60 % step != 0)
throw new ArgumentOutOfRangeException(
nameof(MinuteSelectionStep),
$"{nameof(MinuteSelectionStep)} must be a divisor of 60 and between 1 and 60.");

clock.GenerateButtons();
}

public int MinuteSelectionStep
{
get => (int)GetValue(MinuteSelectionStepProperty);
set => SetValue(MinuteSelectionStepProperty, value);
}

public static readonly RoutedEvent ClockChoiceMadeEvent =
EventManager.RegisterRoutedEvent(
"ClockChoiceMade",
Expand Down Expand Up @@ -300,15 +323,15 @@ private void GenerateButtons()

if (Is24Hours)
{
GenerateButtons(hoursCanvas, Enumerable.Range(13, 12).ToList(), ButtonRadiusRatio,
GenerateButtons(hoursCanvas, [.. Enumerable.Range(13, 12)], ButtonRadiusRatio,
new ClockItemIsCheckedConverter(() => Time, ClockDisplayMode.Hours, Is24Hours), i => "ButtonStyle", "00",
ClockDisplayMode.Hours);
GenerateButtons(hoursCanvas, Enumerable.Range(1, 12).ToList(), ButtonRadiusInnerRatio,
GenerateButtons(hoursCanvas, [.. Enumerable.Range(1, 12)], ButtonRadiusInnerRatio,
new ClockItemIsCheckedConverter(() => Time, ClockDisplayMode.Hours, Is24Hours), i => "ButtonStyle", "#",
ClockDisplayMode.Hours);
}
else
GenerateButtons(hoursCanvas, Enumerable.Range(1, 12).ToList(), ButtonRadiusRatio,
GenerateButtons(hoursCanvas, [.. Enumerable.Range(1, 12)], ButtonRadiusRatio,
new ClockItemIsCheckedConverter(() => Time, ClockDisplayMode.Hours, Is24Hours), i => "ButtonStyle", "0",
ClockDisplayMode.Hours);
}
Expand All @@ -317,17 +340,24 @@ private void GenerateButtons()
{
RemoveExistingButtons(minutesCanvas);

GenerateButtons(minutesCanvas, Enumerable.Range(1, 60).ToList(), ButtonRadiusRatio,
GenerateButtons(
minutesCanvas,
[.. Enumerable.Range(1, 60)],
ButtonRadiusRatio,
new ClockItemIsCheckedConverter(() => Time, ClockDisplayMode.Minutes, Is24Hours),
i => ((i / 5.0) % 1) == 0.0 ? "ButtonStyle" : "LesserButtonStyle", "0",
ClockDisplayMode.Minutes);
i => ((i / 5.0) % 1) == 0.0
? "ButtonStyle"
: "LesserButtonStyle",
"0",
ClockDisplayMode.Minutes,
i => (i % 60) % MinuteSelectionStep == 0);
}

if (GetTemplateChild(SecondsCanvasPartName) is Canvas secondsCanvas)
{
RemoveExistingButtons(secondsCanvas);

GenerateButtons(secondsCanvas, Enumerable.Range(1, 60).ToList(), ButtonRadiusRatio,
GenerateButtons(secondsCanvas, [.. Enumerable.Range(1, 60)], ButtonRadiusRatio,
new ClockItemIsCheckedConverter(() => Time, ClockDisplayMode.Seconds, Is24Hours),
i => ((i / 5.0) % 1) == 0.0 ? "ButtonStyle" : "LesserButtonStyle", "0",
ClockDisplayMode.Seconds);
Expand Down Expand Up @@ -356,12 +386,13 @@ private void HourReadOutPartNameOnPreviewMouseLeftButtonDown(object sender, Mous

private void GenerateButtons(
Panel canvas,
ICollection<int> range,
List<int> range,
double radiusRatio,
IValueConverter isCheckedConverter,
Func<int, string> stylePropertySelector,
string format,
ClockDisplayMode clockDisplayMode)
ClockDisplayMode clockDisplayMode,
Func<int, bool>? isEnabledSelector = null)
{
var anglePerItem = 360.0 / range.Count;
var radiansPerItem = anglePerItem * (Math.PI / 180);
Expand All @@ -388,6 +419,12 @@ private void GenerateButtons(
button.SetBinding(Canvas.TopProperty, GetBinding("Y", button));

button.Content = (i == 60 ? 0 : (i == 24 && clockDisplayMode == ClockDisplayMode.Hours ? 0 : i)).ToString(format);

if (isEnabledSelector is not null)
{
bool isEnabled = isEnabledSelector.Invoke(i);
button.IsEnabled = isEnabled;
}
canvas.Children.Add(button);
}

Expand Down Expand Up @@ -476,7 +513,12 @@ private void ClockItemDragDeltaHandler(object sender, DragDeltaEventArgs dragDel
}
else
{
var value = (int)Math.Round(30 * angle / Math.PI, MidpointRounding.AwayFromZero) % 60;
int rawValue = (int)Math.Round(30 * angle / Math.PI, MidpointRounding.AwayFromZero) % 60;

int value = DisplayMode == ClockDisplayMode.Minutes
? ((int)Math.Round(rawValue / (double)MinuteSelectionStep, MidpointRounding.AwayFromZero)
* MinuteSelectionStep) % 60
: rawValue;
if (DisplayMode == ClockDisplayMode.Minutes)
time = new DateTime(Time.Year, Time.Month, Time.Day, Time.Hour, value, Time.Second);
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@
<Setter Property="Background" Value="{DynamicResource MaterialDesign.Brush.Primary}" />
<Setter Property="Foreground" Value="{DynamicResource MaterialDesign.Brush.Primary.Foreground}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.38" />
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
Expand Down
24 changes: 24 additions & 0 deletions tests/MaterialDesignThemes.Wpf.Tests/ClockTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,28 @@ void OnTimeChanged(object? sender, TimeChangedEventArgs e)
await Assert.That(invocations[1].OldTime).IsEqualTo(now);
await Assert.That(invocations[1].NewTime).IsEqualTo(now + TimeSpan.FromMinutes(-2));
}

[Test]
public async Task MinuteSelectionStep_DefaultValue_IsOne()
{
var clock = new Clock();

await Assert.That(clock.MinuteSelectionStep).IsEqualTo(1);
}

[Test]
[Arguments(0)]
[Arguments(-1)]
[Arguments(61)]
[Arguments(7)]
[Arguments(13)]
[Arguments(59)]
public async Task MinuteSelectionStep_InvalidValues_Throws(int value)
{
var clock = new Clock();

var ex = Assert.Throws<ArgumentOutOfRangeException>(() => clock.MinuteSelectionStep = value);

await Assert.That(ex.Message).IsEqualTo($"{nameof(Clock.MinuteSelectionStep)} must be a divisor of 60 and between 1 and 60. (Parameter '{nameof(Clock.MinuteSelectionStep)}')");
}
}
Loading