feat: WIP.
This commit is contained in:
@@ -6,8 +6,6 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Ursa.Demo.Pages.DatePickerDemo">
|
||||
<StackPanel Margin="20" HorizontalAlignment="Left">
|
||||
<u:CalendarMonthView />
|
||||
<u:CalendarYearView />
|
||||
<u:CalendarView/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<Design.PreviewWith>
|
||||
<StackPanel Margin="20" Spacing="5">
|
||||
<u:CalendarMonthView />
|
||||
<u:CalendarView />
|
||||
</StackPanel>
|
||||
</Design.PreviewWith>
|
||||
@@ -119,144 +118,6 @@
|
||||
<Setter Property="Cursor" Value="No" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:CalendarView}" TargetType="u:CalendarView">
|
||||
<Setter Property="MinHeight" Value="300" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:CalendarView">
|
||||
<Panel>
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, Auto,*, Auto, Auto">
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_PreviousYearButton}"
|
||||
Grid.Column="0"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemPreviousIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_PreviousButton}"
|
||||
Grid.Column="1"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemPreviousIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
|
||||
<Grid Grid.Column="2" ColumnDefinitions="*, *">
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_YearButton}"
|
||||
Grid.Column="0"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="2024"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsVisible="{TemplateBinding IsMonthMode}"
|
||||
Theme="{DynamicResource BorderlessButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_MonthButton}"
|
||||
Grid.Column="1"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="Apr"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsVisible="{TemplateBinding IsMonthMode}"
|
||||
Theme="{DynamicResource BorderlessButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_HeaderButton}"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
IsVisible="{TemplateBinding IsMonthMode, Converter={x:Static BoolConverters.Not}}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="2020-2030" />
|
||||
</Grid>
|
||||
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_NextButton}"
|
||||
Grid.Column="3"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemNextIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_NextYearButton}"
|
||||
Grid.Column="4"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemNextIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<u:CalendarMonthView
|
||||
Name="{x:Static u:CalendarView.PART_MonthView}"
|
||||
Grid.Row="1"
|
||||
VerticalAlignment="Top"
|
||||
IsVisible="{TemplateBinding IsMonthMode}" />
|
||||
<u:CalendarYearView
|
||||
Name="{x:Static u:CalendarView.PART_YearView}"
|
||||
Grid.Row="1"
|
||||
Width="{Binding #PART_MonthView.Bounds.Width}"
|
||||
Height="{Binding #PART_MonthView.Bounds.Height}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
IsVisible="{TemplateBinding IsMonthMode,
|
||||
Converter={x:Static BoolConverters.Not}}" />
|
||||
</Grid>
|
||||
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:CalendarMonthView}" TargetType="u:CalendarMonthView">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid
|
||||
Name="{x:Static u:CalendarMonthView.PART_Grid}"
|
||||
ColumnDefinitions="*, *, *, *, *, *, *"
|
||||
RowDefinitions="*, Auto, *, *, *, *, *, *">
|
||||
<Rectangle
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="7"
|
||||
Height="1"
|
||||
Margin="8,8,8,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{DynamicResource SemiGrey2}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:CalendarYearView}" TargetType="u:CalendarYearView">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid
|
||||
Name="{x:Static u:CalendarYearView.PART_Grid}"
|
||||
ColumnDefinitions="*, *, *"
|
||||
RowDefinitions="*, *, *, *" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:CalendarYearButton}" TargetType="u:CalendarYearButton">
|
||||
<Setter Property="MinWidth" Value="32" />
|
||||
<Setter Property="MinHeight" Value="32" />
|
||||
@@ -298,4 +159,119 @@
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
<ControlTheme x:Key="{x:Type u:CalendarView}" TargetType="u:CalendarView">
|
||||
<Setter Property="MinHeight" Value="300" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:CalendarView">
|
||||
<Panel>
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, Auto,*, Auto, Auto">
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_PreviousYearButton}"
|
||||
Grid.Column="0"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemPreviousIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_PreviousButton}"
|
||||
Grid.Column="1"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemPreviousIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
|
||||
<Grid Grid.Column="2" ColumnDefinitions="*, *">
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_YearButton}"
|
||||
Grid.Column="0"
|
||||
HorizontalContentAlignment="Center"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_MonthButton}"
|
||||
Grid.Column="1"
|
||||
HorizontalContentAlignment="Center"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}" />
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_HeaderButton}"
|
||||
Grid.Column="0"
|
||||
IsVisible="True"
|
||||
Grid.ColumnSpan="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center" />
|
||||
</Grid>
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_NextButton}"
|
||||
Grid.Column="3"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemNextIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
<Button
|
||||
Name="{x:Static u:CalendarView.PART_NextYearButton}"
|
||||
Grid.Column="4"
|
||||
HorizontalContentAlignment="Left"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<PathIcon
|
||||
Width="12"
|
||||
Height="12"
|
||||
Data="{DynamicResource CalendarItemNextIconGlyph}"
|
||||
Foreground="{DynamicResource CalendarItemIconForeground}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid
|
||||
Name="{x:Static u:CalendarView.PART_MonthGrid}"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ColumnDefinitions="*, *, *, *, *, *, *"
|
||||
RowDefinitions="*, Auto, *, *, *, *, *, *" />
|
||||
<Grid
|
||||
Name="{x:Static u:CalendarView.PART_YearGrid}"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ColumnDefinitions="*, *, *"
|
||||
RowDefinitions="*, *, *, *" />
|
||||
</Grid>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:month">
|
||||
<Style Selector="^ /template/ Button#PART_YearButton, ^ /template/ Button#PART_MonthButton,^ /template/ Grid#PART_MonthGrid">
|
||||
<Setter Property="Control.IsVisible" Value="True" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_HeaderButton, ^ /template/ Grid#PART_YearGrid">
|
||||
<Setter Property="Control.IsVisible" Value="False" />
|
||||
</Style>
|
||||
</Style>
|
||||
<Style Selector="^:not(:month)">
|
||||
<Style Selector="^ /template/ Button#PART_YearButton, ^ /template/ Button#PART_MonthButton,^ /template/ Grid#PART_MonthGrid">
|
||||
<Setter Property="Control.IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_HeaderButton, ^ /template/ Grid#PART_YearGrid">
|
||||
<Setter Property="Control.IsVisible" Value="True" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -8,6 +8,7 @@ using Avalonia.Layout;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Show days in a month. CalendarMonthView itself doesn't handle any date range selection logic.
|
||||
/// it provides a method to mark preview range and selection range. The range limit may out of current displayed month.
|
||||
@@ -226,4 +227,6 @@ public class CalendarMonthView : TemplatedControl
|
||||
button.IsInRange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -1,14 +1,13 @@
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media.TextFormatting;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Calendar = System.Globalization.Calendar;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
@@ -19,11 +18,10 @@ namespace Ursa.Controls;
|
||||
[TemplatePart(PART_YearButton, typeof(Button))]
|
||||
[TemplatePart(PART_MonthButton, typeof(Button))]
|
||||
[TemplatePart(PART_HeaderButton, typeof(Button))]
|
||||
[TemplatePart(PART_MonthView, typeof(CalendarMonthView))]
|
||||
[TemplatePart(PART_YearView, typeof(CalendarYearView))]
|
||||
[TemplatePart(PART_MonthGrid, typeof(Grid))]
|
||||
[TemplatePart(PART_YearGrid, typeof(Grid))]
|
||||
public class CalendarView: TemplatedControl
|
||||
[PseudoClasses(PC_Month)]
|
||||
public class CalendarView : TemplatedControl
|
||||
{
|
||||
public const string PART_NextYearButton = "PART_NextYearButton";
|
||||
public const string PART_PreviousYearButton = "PART_PreviousYearButton";
|
||||
@@ -31,51 +29,79 @@ public class CalendarView: TemplatedControl
|
||||
public const string PART_PreviousButton = "PART_PreviousButton";
|
||||
public const string PART_YearButton = "PART_YearButton";
|
||||
public const string PART_MonthButton = "PART_MonthButton";
|
||||
public const string PART_MonthView = "PART_MonthView";
|
||||
public const string PART_YearView = "PART_YearView";
|
||||
public const string PART_HeaderButton = "PART_HeaderButton";
|
||||
public const string PART_MonthGrid = "PART_MonthGrid";
|
||||
public const string PART_YearGrid = "PART_YearGried";
|
||||
|
||||
public const string PART_YearGrid = "PART_YearGrid";
|
||||
public const string PC_Month = ":month";
|
||||
|
||||
private const string ShortestDayName = "ShortestDayName";
|
||||
|
||||
private readonly System.Globalization.Calendar _calendar = new GregorianCalendar();
|
||||
|
||||
internal CalendarViewMode Mode;
|
||||
|
||||
//private CalendarMonthView? _monthView;
|
||||
//private CalendarYearView? _yearView;
|
||||
private Grid? _monthGrid;
|
||||
private Grid? _yearGrid;
|
||||
// Year button only shows the year in month mode.
|
||||
private Button? _yearButton;
|
||||
// Month button only shows the month in month mode.
|
||||
private Button? _monthButton;
|
||||
// Header button shows year in year mode, and year range in higher mode.
|
||||
private Button? _headerButton;
|
||||
|
||||
public DateContext ContextDate { get; set; } = new DateContext();
|
||||
|
||||
public event EventHandler<CalendarDayButtonEventArgs>? OnDateSelected;
|
||||
public event EventHandler<CalendarDayButtonEventArgs>? OnDatePreviewed;
|
||||
internal static readonly DirectProperty<CalendarView, CalendarViewMode> ModeProperty =
|
||||
AvaloniaProperty.RegisterDirect<CalendarView, CalendarViewMode>(
|
||||
nameof(Mode), o => o.Mode, (o, v) => o.Mode = v, unsetValue: CalendarViewMode.Month);
|
||||
|
||||
public static readonly StyledProperty<bool> IsTodayHighlightedProperty =
|
||||
DatePickerBase.IsTodayHighlightedProperty.AddOwner<CalendarView>();
|
||||
|
||||
public static readonly StyledProperty<DayOfWeek> FirstDayOfWeekProperty =
|
||||
DatePickerBase.FirstDayOfWeekProperty.AddOwner<CalendarView>();
|
||||
|
||||
private readonly Calendar _calendar = new GregorianCalendar();
|
||||
|
||||
// Header button shows year in year mode, and year range in higher mode.
|
||||
private Button? _headerButton;
|
||||
|
||||
private CalendarViewMode _mode;
|
||||
|
||||
// Month button only shows the month in month mode.
|
||||
private Button? _monthButton;
|
||||
|
||||
private Grid? _monthGrid;
|
||||
|
||||
// Year button only shows the year in month mode.
|
||||
private Button? _yearButton;
|
||||
private Grid? _yearGrid;
|
||||
|
||||
static CalendarView()
|
||||
{
|
||||
FirstDayOfWeekProperty.Changed.AddClassHandler<CalendarView, DayOfWeek>((view, args) =>
|
||||
view.OnFirstDayOfWeekChanged(args));
|
||||
ModeProperty.Changed.AddClassHandler<CalendarView, CalendarViewMode>((view, args) =>
|
||||
{
|
||||
view.PseudoClasses.Set(PC_Month, args.NewValue.Value == CalendarViewMode.Month);
|
||||
Debug.WriteLine(args.NewValue.Value);
|
||||
});
|
||||
}
|
||||
|
||||
internal CalendarViewMode Mode
|
||||
{
|
||||
get => _mode;
|
||||
set => SetAndRaise(ModeProperty, ref _mode, value);
|
||||
}
|
||||
|
||||
public DateContext ContextDate { get; set; } = new();
|
||||
|
||||
public bool IsTodayHighlighted
|
||||
{
|
||||
get => GetValue(IsTodayHighlightedProperty);
|
||||
set => SetValue(IsTodayHighlightedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DayOfWeek> FirstDayOfWeekProperty =
|
||||
DatePickerBase.FirstDayOfWeekProperty.AddOwner<CalendarView>();
|
||||
|
||||
public DayOfWeek FirstDayOfWeek
|
||||
{
|
||||
get => GetValue(FirstDayOfWeekProperty);
|
||||
set => SetValue(FirstDayOfWeekProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public event EventHandler<CalendarDayButtonEventArgs>? OnDateSelected;
|
||||
public event EventHandler<CalendarDayButtonEventArgs>? OnDatePreviewed;
|
||||
|
||||
private void OnFirstDayOfWeekChanged(AvaloniaPropertyChangedEventArgs<DayOfWeek> args)
|
||||
{
|
||||
UpdateMonthViewHeader(args.NewValue.Value);
|
||||
RefreshDayButtons();
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
@@ -83,7 +109,7 @@ public class CalendarView: TemplatedControl
|
||||
Button.ClickEvent.RemoveHandler(OnHeaderYearButtonClick, _yearButton);
|
||||
Button.ClickEvent.RemoveHandler(OnHeaderMonthButtonClick, _monthButton);
|
||||
Button.ClickEvent.RemoveHandler(OnHeaderButtonClick, _headerButton);
|
||||
|
||||
|
||||
_monthGrid = e.NameScope.Find<Grid>(PART_MonthGrid);
|
||||
_yearGrid = e.NameScope.Find<Grid>(PART_YearGrid);
|
||||
_yearButton = e.NameScope.Find<Button>(PART_YearButton);
|
||||
@@ -94,30 +120,40 @@ public class CalendarView: TemplatedControl
|
||||
Button.ClickEvent.AddHandler(OnHeaderMonthButtonClick, _monthButton);
|
||||
Button.ClickEvent.AddHandler(OnHeaderButtonClick, _headerButton);
|
||||
|
||||
ContextDate = new DateContext(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day);
|
||||
PseudoClasses.Set(PC_Month, Mode == CalendarViewMode.Month);
|
||||
GenerateGridElements();
|
||||
RefreshDayButtons();
|
||||
RefreshYearButtons();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rule:
|
||||
/// Rule:
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OnHeaderButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Mode == CalendarViewMode.Month)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// Header button should be hidden in Month mode.
|
||||
if (Mode == CalendarViewMode.Month) return;
|
||||
if (Mode == CalendarViewMode.Year)
|
||||
{
|
||||
|
||||
Mode = CalendarViewMode.Decade;
|
||||
RefreshYearButtons();
|
||||
return;
|
||||
}
|
||||
if(Mode == CalendarViewMode.Decade)
|
||||
{
|
||||
Mode = CalendarViewMode.Century;
|
||||
RefreshYearButtons();
|
||||
return;
|
||||
}
|
||||
if (Mode == CalendarViewMode.Century) return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate Buttons and labels for MonthView.
|
||||
/// Generate Buttons for YearView.
|
||||
/// Generate Buttons and labels for MonthView.
|
||||
/// Generate Buttons for YearView.
|
||||
/// </summary>
|
||||
private void GenerateGridElements()
|
||||
{
|
||||
@@ -147,8 +183,9 @@ public class CalendarView: TemplatedControl
|
||||
cell.AddHandler(CalendarDayButton.DatePreviewedEvent, OnCellDatePreviewed);
|
||||
children.Add(cell);
|
||||
}
|
||||
|
||||
_monthGrid?.Children.AddRange(children);
|
||||
|
||||
|
||||
// Generate month/year buttons.
|
||||
for (var i = 0; i < 12; i++)
|
||||
{
|
||||
@@ -160,14 +197,16 @@ public class CalendarView: TemplatedControl
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshButtons(DateTime date)
|
||||
private void RefreshDayButtons()
|
||||
{
|
||||
if (_monthGrid is null) return;
|
||||
var children = _monthGrid.Children;
|
||||
var info = DateTimeHelper.GetCurrentDateTimeFormatInfo();
|
||||
var dayBefore = PreviousMonthDays(date);
|
||||
var date = new DateTime(ContextDate.Year.Value, ContextDate.Month.Value, ContextDate.Day.Value);
|
||||
var dayBefore =
|
||||
PreviousMonthDays(date);
|
||||
var dateToSet = date.GetFirstDayOfMonth().AddDays(-dayBefore);
|
||||
for (var i = 8; i < children.Count; i++)
|
||||
for (var i = 7; i < children.Count; i++)
|
||||
{
|
||||
var day = dateToSet;
|
||||
var cell = children[i] as CalendarDayButton;
|
||||
@@ -180,16 +219,58 @@ public class CalendarView: TemplatedControl
|
||||
|
||||
FadeOutDayButtons();
|
||||
}
|
||||
|
||||
|
||||
private void RefreshYearButtons()
|
||||
{
|
||||
if (_yearGrid is null) return;
|
||||
var mode = Mode;
|
||||
var contextDate = ContextDate;
|
||||
for (var i = 0; i < 12; i++)
|
||||
{
|
||||
var child = _yearGrid.Children[i] as CalendarYearButton;
|
||||
if (child is null) continue;
|
||||
switch (mode)
|
||||
{
|
||||
case CalendarViewMode.Month:
|
||||
child.SetValues(CalendarViewMode.Year, i);
|
||||
break;
|
||||
case CalendarViewMode.Year:
|
||||
child.SetValues(CalendarViewMode.Decade, year: ContextDate.Year / 10 * 10 + i - 1);
|
||||
break;
|
||||
case CalendarViewMode.Decade:
|
||||
var startYear = (ContextDate.Year / 10 + i - 1) * 10;
|
||||
var endYear = (ContextDate.Year / 10 + i - 1) * 10 + 10;
|
||||
child.SetValues(CalendarViewMode.Century, startYear: startYear, endYear: endYear);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FadeOutDayButtons()
|
||||
{
|
||||
if (_monthGrid is null) return;
|
||||
var children = _monthGrid.Children;
|
||||
for (var i = 8; i < children.Count; i++)
|
||||
for (var i = 7; i < children.Count; i++)
|
||||
if (children[i] is CalendarDayButton { DataContext: DateTime d } button && d.Month != ContextDate.Month)
|
||||
button.IsNotCurrentMonth = true;
|
||||
}
|
||||
|
||||
|
||||
private void UpdateMonthViewHeader(DayOfWeek day)
|
||||
{
|
||||
var dayOfWeek = (int)day;
|
||||
var info = DateTimeHelper.GetCurrentDateTimeFormatInfo();
|
||||
var texts = _monthGrid?.Children.Where(a => a is TextBlock { Tag: ShortestDayName }).ToList();
|
||||
if (texts is not null)
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
var d = (dayOfWeek + i) % DateTimeHelper.NumberOfDaysPerWeek;
|
||||
texts[i].SetValue(TextBlock.TextProperty, info.ShortestDayNames[d]);
|
||||
texts[i].SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
|
||||
texts[i].SetValue(Grid.RowProperty, 0);
|
||||
texts[i].SetValue(Grid.ColumnProperty, i);
|
||||
}
|
||||
}
|
||||
|
||||
private int PreviousMonthDays(DateTime date)
|
||||
{
|
||||
var firstDay = date.GetFirstDayOfMonth();
|
||||
@@ -198,7 +279,7 @@ public class CalendarView: TemplatedControl
|
||||
var i = (dayOfWeek - firstDayOfWeek + DateTimeHelper.NumberOfDaysPerWeek) % DateTimeHelper.NumberOfDaysPerWeek;
|
||||
return i == 0 ? DateTimeHelper.NumberOfDaysPerWeek : i;
|
||||
}
|
||||
|
||||
|
||||
private void OnCellDatePreviewed(object sender, CalendarDayButtonEventArgs e)
|
||||
{
|
||||
OnDatePreviewed?.Invoke(sender, e);
|
||||
@@ -210,66 +291,68 @@ public class CalendarView: TemplatedControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Click on Month Header button. Calendar switch from month mode to year mode.
|
||||
/// Click on Month Header button. Calendar switch from month mode to year mode.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OnHeaderMonthButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_headerButton?.SetValue(ContentControl.ContentProperty, ContextDate.Year);
|
||||
Mode = CalendarViewMode.Year;
|
||||
IsVisibleProperty.SetValue(true, _yearGrid);
|
||||
IsVisibleProperty.SetValue(false, _monthGrid);
|
||||
SetCurrentValue(ModeProperty, CalendarViewMode.Year);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Click on Year Header button. Calendar switch from month mode to decade mode.
|
||||
/// Click on Year Header button. Calendar switch from month mode to decade mode.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OnHeaderYearButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_yearGrid is null) return;
|
||||
int? decadeStart = ContextDate.Year / 10 * 10;
|
||||
_headerButton?.SetValue(ContentControl.ContentProperty,
|
||||
decadeStart + "-" + (decadeStart + 10));
|
||||
Mode = CalendarViewMode.Decade;
|
||||
IsVisibleProperty.SetValue(true, _yearGrid);
|
||||
IsVisibleProperty.SetValue(false, _monthGrid);
|
||||
var decadeStart = ContextDate.Year / 10 * 10;
|
||||
_headerButton?.SetValue(ContentControl.ContentProperty, decadeStart + "-" + (decadeStart + 10));
|
||||
SetCurrentValue(ModeProperty, CalendarViewMode.Decade);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Click on CalendarYearButton in YearView.
|
||||
/// Mode switch rules are:
|
||||
/// 1. Month -> Not supported, buttons are hidden.
|
||||
/// 2. Year -> Month: Set the date to the selected year and switch to Month mode.
|
||||
/// 3. Decade -> Year: Set the date to the selected year and switch to Year mode.
|
||||
/// 4. Century -> Decade: Set the date to the selected year and switch to Decade mode.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void OnYearItemSelected(object sender, CalendarYearButtonEventArgs e)
|
||||
{
|
||||
if (_yearGrid is null) return;
|
||||
var buttons = _yearGrid.Children.OfType<CalendarYearButton>().ToList();
|
||||
if (e.Mode == CalendarViewMode.Year)
|
||||
if (Mode == CalendarViewMode.Year)
|
||||
{
|
||||
Mode = CalendarViewMode.Month;
|
||||
if (e.Month is null) return;
|
||||
var day = MathHelpers.SafeClamp(e.Month.Value, 0,
|
||||
DateTime.DaysInMonth(ContextDate.Year!.Value, e.Month.Value + 1));
|
||||
ContextDate = new DateContext { Year = ContextDate.Year, Month = e.Month + 1, Day = day };
|
||||
Mode = CalendarViewMode.Month;
|
||||
}
|
||||
else if (e.Mode == CalendarViewMode.Decade)
|
||||
else if (Mode == CalendarViewMode.Decade)
|
||||
{
|
||||
// Set CalendarYearView to Month mode
|
||||
for (var i = 0; i < 12; i++)
|
||||
{
|
||||
buttons[i].SetValues(CalendarViewMode.Month, month: i);
|
||||
}
|
||||
ContextDate = new DateContext() { Year = e.Year!.Value, Month = ContextDate.Month, Day = null };
|
||||
Mode = CalendarViewMode.Month;
|
||||
Mode = CalendarViewMode.Year;
|
||||
for (var i = 0; i < 12; i++) buttons[i].SetValues(CalendarViewMode.Year, i);
|
||||
ContextDate = new DateContext { Year = e.Year!.Value, Month = null, Day = null };
|
||||
}
|
||||
else if (e.Mode == CalendarViewMode.Century)
|
||||
else if (Mode == CalendarViewMode.Century)
|
||||
{
|
||||
// Set CalendarYearView to Year mode
|
||||
Mode = CalendarViewMode.Decade;
|
||||
for (var i = 0; i < 12; i++)
|
||||
{
|
||||
if (e.StartYear is null || e.EndYear is null) continue;
|
||||
var year = e.StartYear.Value - 1 + i;
|
||||
buttons[i].SetValues(CalendarViewMode.Year, year: year);
|
||||
buttons[i].SetValues(CalendarViewMode.Decade, year: year);
|
||||
}
|
||||
Mode = CalendarViewMode.Year;
|
||||
}
|
||||
|
||||
RefreshYearButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using Irihi.Avalonia.Shared.Helpers;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Three modes:
|
||||
/// 1. show 12 months in a year
|
||||
@@ -116,4 +117,5 @@ public class CalendarYearView: TemplatedControl
|
||||
Mode = mode;
|
||||
RefreshButtons();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
Reference in New Issue
Block a user