diff --git a/src/AtomUI.Controls/Calendar/CalendarButton.cs b/src/AtomUI.Controls/Calendar/CalendarButton.cs
index 57cf27513..18834664a 100644
--- a/src/AtomUI.Controls/Calendar/CalendarButton.cs
+++ b/src/AtomUI.Controls/Calendar/CalendarButton.cs
@@ -1,4 +1,8 @@
-using Avalonia.Controls;
+using AtomUI.Media;
+using AtomUI.Theme.Styling;
+using AtomUI.Theme.Utils;
+using Avalonia.Animation;
+using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
@@ -10,9 +14,10 @@ namespace AtomUI.Controls;
/// Represents a button on a
/// .
///
-[PseudoClasses(":selected", ":inactive", ":btnfocused")]
+[PseudoClasses(StdPseudoClass.Selected, StdPseudoClass.InActive, BtnFocusedPC)]
internal sealed class CalendarButton : AvaloniaButton
{
+ private const string BtnFocusedPC = ":btnfocused";
///
/// A value indicating whether the button is focused.
///
@@ -34,7 +39,6 @@ internal sealed class CalendarButton : AvaloniaButton
/// class.
///
public CalendarButton()
- : base()
{
SetCurrentValue(ContentProperty, DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]);
}
@@ -97,6 +101,12 @@ internal sealed class CalendarButton : AvaloniaButton
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
SetPseudoClasses();
+ if (Transitions is null) {
+ Transitions = new Transitions()
+ {
+ AnimationUtils.CreateTransition(BackgroundProperty, GlobalTokenResourceKey.MotionDurationFast)
+ };
+ }
}
///
@@ -104,9 +114,9 @@ internal sealed class CalendarButton : AvaloniaButton
///
private void SetPseudoClasses()
{
- PseudoClasses.Set(":selected", IsSelected);
- PseudoClasses.Set(":inactive", IsInactive);
- PseudoClasses.Set(":btnfocused", IsCalendarButtonFocused && IsEnabled);
+ PseudoClasses.Set(StdPseudoClass.Selected, IsSelected);
+ PseudoClasses.Set(StdPseudoClass.InActive, IsInactive);
+ PseudoClasses.Set(BtnFocusedPC, IsCalendarButtonFocused && IsEnabled);
}
///
diff --git a/src/AtomUI.Controls/Calendar/CalendarButtonTheme.cs b/src/AtomUI.Controls/Calendar/CalendarButtonTheme.cs
new file mode 100644
index 000000000..f0aa89da1
--- /dev/null
+++ b/src/AtomUI.Controls/Calendar/CalendarButtonTheme.cs
@@ -0,0 +1,88 @@
+using AtomUI.Theme;
+using AtomUI.Theme.Styling;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Presenters;
+using Avalonia.Controls.Templates;
+using Avalonia.Input;
+using Avalonia.Layout;
+using Avalonia.Styling;
+
+namespace AtomUI.Controls;
+
+[ControlThemeProvider]
+internal class CalendarButtonTheme : BaseControlTheme
+{
+ private const string ContentPart = "PART_Content";
+
+ public CalendarButtonTheme()
+ : base(typeof(CalendarButton))
+ {
+ }
+
+ protected override IControlTemplate BuildControlTemplate()
+ {
+ return new FuncControlTemplate((calendarButton, scope) =>
+ {
+ var contentPresenter = new ContentPresenter()
+ {
+ Name = ContentPart,
+ };
+
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.PaddingProperty, CalendarButton.PaddingProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.ForegroundProperty, CalendarButton.ForegroundProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.BackgroundProperty, CalendarButton.BackgroundProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.CornerRadiusProperty, CalendarButton.CornerRadiusProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderBrushProperty, CalendarButton.BorderBrushProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderThicknessProperty, CalendarButton.BorderThicknessProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.FontSizeProperty, CalendarButton.FontSizeProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, CalendarButton.ContentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty, CalendarButton.ContentTemplateProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.HorizontalAlignmentProperty, CalendarButton.HorizontalAlignmentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.VerticalAlignmentProperty, CalendarButton.VerticalAlignmentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.HorizontalContentAlignmentProperty, CalendarButton.HorizontalContentAlignmentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.VerticalContentAlignmentProperty, CalendarButton.VerticalContentAlignmentProperty);
+
+ return contentPresenter;
+ });
+ }
+
+ protected override void BuildStyles()
+ {
+ var commonStyle = new Style(selector => selector.Nesting());
+
+ commonStyle.Add(CalendarButton.ClickModeProperty, ClickMode.Release);
+ commonStyle.Add(CalendarButton.CursorProperty, new Cursor(StandardCursorType.Hand));
+ commonStyle.Add(CalendarButton.BackgroundProperty, GlobalTokenResourceKey.ColorTransparent);
+ commonStyle.Add(CalendarButton.ForegroundProperty, GlobalTokenResourceKey.ColorTextLabel);
+ commonStyle.Add(CalendarButton.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadiusSM);
+ commonStyle.Add(CalendarButton.BorderBrushProperty, GlobalTokenResourceKey.ColorTransparent);
+ commonStyle.Add(CalendarButton.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
+ commonStyle.Add(CalendarButton.VerticalAlignmentProperty, VerticalAlignment.Stretch);
+ commonStyle.Add(CalendarButton.HorizontalContentAlignmentProperty, HorizontalAlignment.Center);
+ commonStyle.Add(CalendarButton.VerticalContentAlignmentProperty, VerticalAlignment.Center);
+ commonStyle.Add(CalendarButton.FontSizeProperty, GlobalTokenResourceKey.FontSize);
+ commonStyle.Add(CalendarButton.HeightProperty, CalendarTokenResourceKey.CellHeight);
+ commonStyle.Add(CalendarButton.MarginProperty, CalendarTokenResourceKey.CellMargin);
+
+ var contentStyle = new Style(selector => selector.Nesting().Template().Name(ContentPart));
+ contentStyle.Add(ContentPresenter.LineHeightProperty, CalendarTokenResourceKey.CellLineHeight);
+ commonStyle.Add(contentStyle);
+
+ var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
+ hoverStyle.Add(CalendarButton.BackgroundProperty, CalendarTokenResourceKey.CellHoverBg);
+ commonStyle.Add(hoverStyle);
+
+ var inactiveStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.InActive));
+ inactiveStyle.Add(CalendarButton.ForegroundProperty, GlobalTokenResourceKey.ColorTextDisabled);
+ commonStyle.Add(inactiveStyle);
+
+ var selectedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Selected));
+ selectedStyle.Add(CalendarButton.BackgroundProperty, GlobalTokenResourceKey.ColorPrimary);
+ selectedStyle.Add(CalendarButton.ForegroundProperty, GlobalTokenResourceKey.ColorWhite);
+ selectedStyle.Add(CalendarButton.BorderThicknessProperty, new Thickness(0));
+ commonStyle.Add(selectedStyle);
+
+ Add(commonStyle);
+ }
+}
\ No newline at end of file
diff --git a/src/AtomUI.Controls/Calendar/CalendarDayButton.cs b/src/AtomUI.Controls/Calendar/CalendarDayButton.cs
index 5d5caf288..fa9bb998a 100644
--- a/src/AtomUI.Controls/Calendar/CalendarDayButton.cs
+++ b/src/AtomUI.Controls/Calendar/CalendarDayButton.cs
@@ -1,20 +1,28 @@
using System.Globalization;
+using AtomUI.Media;
+using AtomUI.Theme.Data;
+using AtomUI.Theme.Styling;
+using AtomUI.Theme.Utils;
+using AtomUI.Utils;
+using Avalonia;
+using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
+using Avalonia.Data;
using Avalonia.Input;
using AvaloniaButton = Avalonia.Controls.Button;
namespace AtomUI.Controls;
-[PseudoClasses(StdPseudoClass.Pressed, StdPseudoClass.Disabled, StdPseudoClass.Selected, InactivePC, TodayPC, BlackoutPC, DayfocusedPC)]
+[PseudoClasses(StdPseudoClass.Pressed, StdPseudoClass.Disabled, StdPseudoClass.Selected, StdPseudoClass.InActive,
+ TodayPC, BlackoutPC, DayfocusedPC)]
internal sealed class CalendarDayButton : AvaloniaButton
{
- private const string InactivePC = ":inactive";
- private const string TodayPC = ":today";
- private const string BlackoutPC = ":blackout";
- private const string DayfocusedPC = ":dayfocused";
-
+ internal const string TodayPC = ":today";
+ internal const string BlackoutPC = ":blackout";
+ internal const string DayfocusedPC = ":dayfocused";
+
///
/// Default content for the CalendarDayButton.
///
@@ -152,6 +160,12 @@ internal sealed class CalendarDayButton : AvaloniaButton
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
SetPseudoClasses();
+ if (Transitions is null) {
+ Transitions = new Transitions()
+ {
+ AnimationUtils.CreateTransition(BackgroundProperty, GlobalTokenResourceKey.MotionDurationFast)
+ };
+ }
}
private void SetPseudoClasses()
@@ -162,7 +176,7 @@ internal sealed class CalendarDayButton : AvaloniaButton
}
PseudoClasses.Set(StdPseudoClass.Selected, IsSelected);
- PseudoClasses.Set(InactivePC, IsInactive);
+ PseudoClasses.Set(StdPseudoClass.InActive, IsInactive);
PseudoClasses.Set(TodayPC, IsToday);
PseudoClasses.Set(BlackoutPC, IsBlackout);
PseudoClasses.Set(DayfocusedPC, IsCurrent && IsEnabled);
@@ -230,4 +244,11 @@ internal sealed class CalendarDayButton : AvaloniaButton
if (e.InitialPressMouseButton == MouseButton.Left) CalendarDayButtonMouseUp?.Invoke(this, e);
}
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+ TokenResourceBinder.CreateGlobalTokenBinding(this, BorderThicknessProperty, GlobalTokenResourceKey.BorderThickness, BindingPriority.Template,
+ new RenderScaleAwareThicknessConfigure(this));
+ }
}
\ No newline at end of file
diff --git a/src/AtomUI.Controls/Calendar/CalendarDayButtonTheme.cs b/src/AtomUI.Controls/Calendar/CalendarDayButtonTheme.cs
new file mode 100644
index 000000000..9aa3b8cc0
--- /dev/null
+++ b/src/AtomUI.Controls/Calendar/CalendarDayButtonTheme.cs
@@ -0,0 +1,93 @@
+using AtomUI.Theme;
+using AtomUI.Theme.Styling;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Presenters;
+using Avalonia.Controls.Templates;
+using Avalonia.Input;
+using Avalonia.Layout;
+using Avalonia.Styling;
+
+namespace AtomUI.Controls;
+
+[ControlThemeProvider]
+internal class CalendarDayButtonTheme : BaseControlTheme
+{
+ private const string ContentPart = "PART_Content";
+
+ public CalendarDayButtonTheme()
+ : base(typeof(CalendarDayButton))
+ {
+ }
+
+ protected override IControlTemplate BuildControlTemplate()
+ {
+ return new FuncControlTemplate((calendarDayButton, scope) =>
+ {
+ var contentPresenter = new ContentPresenter()
+ {
+ Name = ContentPart,
+ };
+
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.PaddingProperty, CalendarDayButton.PaddingProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.ForegroundProperty, CalendarDayButton.ForegroundProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.BackgroundProperty, CalendarDayButton.BackgroundProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.CornerRadiusProperty, CalendarDayButton.CornerRadiusProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderBrushProperty, CalendarDayButton.BorderBrushProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderThicknessProperty, CalendarDayButton.BorderThicknessProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.FontSizeProperty, CalendarDayButton.FontSizeProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, CalendarDayButton.ContentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty, CalendarDayButton.ContentTemplateProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.HorizontalAlignmentProperty, CalendarDayButton.HorizontalAlignmentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.VerticalAlignmentProperty, CalendarDayButton.VerticalAlignmentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.HorizontalContentAlignmentProperty, CalendarDayButton.HorizontalContentAlignmentProperty);
+ CreateTemplateParentBinding(contentPresenter, ContentPresenter.VerticalContentAlignmentProperty, CalendarDayButton.VerticalContentAlignmentProperty);
+
+ return contentPresenter;
+ });
+ }
+
+ protected override void BuildStyles()
+ {
+ var commonStyle = new Style(selector => selector.Nesting());
+
+ commonStyle.Add(CalendarDayButton.ClickModeProperty, ClickMode.Release);
+ commonStyle.Add(CalendarDayButton.CursorProperty, new Cursor(StandardCursorType.Hand));
+ commonStyle.Add(CalendarDayButton.BackgroundProperty, GlobalTokenResourceKey.ColorTransparent);
+ commonStyle.Add(CalendarDayButton.ForegroundProperty, GlobalTokenResourceKey.ColorTextLabel);
+ commonStyle.Add(CalendarDayButton.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadiusSM);
+ commonStyle.Add(CalendarDayButton.BorderBrushProperty, GlobalTokenResourceKey.ColorTransparent);
+ commonStyle.Add(CalendarDayButton.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
+ commonStyle.Add(CalendarDayButton.VerticalAlignmentProperty, VerticalAlignment.Stretch);
+ commonStyle.Add(CalendarDayButton.HorizontalContentAlignmentProperty, HorizontalAlignment.Center);
+ commonStyle.Add(CalendarDayButton.VerticalContentAlignmentProperty, VerticalAlignment.Center);
+ commonStyle.Add(CalendarDayButton.FontSizeProperty, GlobalTokenResourceKey.FontSize);
+ commonStyle.Add(CalendarDayButton.WidthProperty, CalendarTokenResourceKey.CellWidth);
+ commonStyle.Add(CalendarDayButton.HeightProperty, CalendarTokenResourceKey.CellHeight);
+ commonStyle.Add(CalendarDayButton.MarginProperty, CalendarTokenResourceKey.CellMargin);
+
+ var contentStyle = new Style(selector => selector.Nesting().Template().Name(ContentPart));
+ contentStyle.Add(ContentPresenter.LineHeightProperty, CalendarTokenResourceKey.CellLineHeight);
+ commonStyle.Add(contentStyle);
+
+ var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
+ hoverStyle.Add(CalendarDayButton.BackgroundProperty, CalendarTokenResourceKey.CellHoverBg);
+ commonStyle.Add(hoverStyle);
+
+ var inactiveStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.InActive));
+ inactiveStyle.Add(CalendarDayButton.ForegroundProperty, GlobalTokenResourceKey.ColorTextDisabled);
+ commonStyle.Add(inactiveStyle);
+
+ var todayStyle = new Style(selector => selector.Nesting().Class(CalendarDayButton.TodayPC));
+ todayStyle.Add(CalendarDayButton.BorderBrushProperty, GlobalTokenResourceKey.ColorPrimary);
+ commonStyle.Add(todayStyle);
+
+ var selectedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Selected));
+ selectedStyle.Add(CalendarDayButton.BackgroundProperty, GlobalTokenResourceKey.ColorPrimary);
+ selectedStyle.Add(CalendarDayButton.ForegroundProperty, GlobalTokenResourceKey.ColorWhite);
+ selectedStyle.Add(CalendarDayButton.BorderThicknessProperty, new Thickness(0));
+ commonStyle.Add(selectedStyle);
+
+ Add(commonStyle);
+ }
+}
\ No newline at end of file
diff --git a/src/AtomUI.Controls/Calendar/CalendarItem.cs b/src/AtomUI.Controls/Calendar/CalendarItem.cs
index ad5f45477..8ed8c0690 100644
--- a/src/AtomUI.Controls/Calendar/CalendarItem.cs
+++ b/src/AtomUI.Controls/Calendar/CalendarItem.cs
@@ -31,9 +31,9 @@ internal sealed class CalendarItem : TemplatedControl
///
private const int NumberOfDaysPerWeek = 7;
- private AvaloniaButton? _headerButton;
- private AvaloniaButton? _nextButton;
- private AvaloniaButton? _previousButton;
+ private HeadTextButton? _headerButton;
+ private IconButton? _nextButton;
+ private IconButton? _previousButton;
private DateTime _currentMonth;
private bool _isMouseLeftButtonDown;
@@ -69,7 +69,7 @@ internal sealed class CalendarItem : TemplatedControl
/// Gets the button that allows switching between month mode, year mode,
/// and decade mode.
///
- internal AvaloniaButton? HeaderButton
+ internal HeadTextButton? HeaderButton
{
get => _headerButton;
private set
@@ -89,7 +89,7 @@ internal sealed class CalendarItem : TemplatedControl
/// Gets the button that displays the next page of the calendar when it
/// is clicked.
///
- internal AvaloniaButton? NextButton
+ internal IconButton? NextButton
{
get => _nextButton;
private set
@@ -118,7 +118,7 @@ internal sealed class CalendarItem : TemplatedControl
/// Gets the button that displays the previous page of the calendar when
/// it is clicked.
///
- internal AvaloniaButton? PreviousButton
+ internal IconButton? PreviousButton
{
get => _previousButton;
private set
@@ -230,9 +230,9 @@ internal sealed class CalendarItem : TemplatedControl
///
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
- HeaderButton = e.NameScope.Find(CalendarItemTheme.HeaderButtonPart);
- PreviousButton = e.NameScope.Find(CalendarItemTheme.PreviousButtonPart);
- NextButton = e.NameScope.Find(CalendarItemTheme.NextButtonPart);
+ HeaderButton = e.NameScope.Find(CalendarItemTheme.HeaderButtonPart);
+ PreviousButton = e.NameScope.Find(CalendarItemTheme.PreviousButtonPart);
+ NextButton = e.NameScope.Find(CalendarItemTheme.NextButtonPart);
MonthView = e.NameScope.Find(CalendarItemTheme.MonthViewPart);
YearView = e.NameScope.Find(CalendarItemTheme.YearViewPart);
diff --git a/src/AtomUI.Controls/Calendar/CalendarItemTheme.cs b/src/AtomUI.Controls/Calendar/CalendarItemTheme.cs
index 6345cf944..6d94c497b 100644
--- a/src/AtomUI.Controls/Calendar/CalendarItemTheme.cs
+++ b/src/AtomUI.Controls/Calendar/CalendarItemTheme.cs
@@ -1,10 +1,11 @@
using AtomUI.Theme;
using AtomUI.Theme.Styling;
+using AtomUI.Utils;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
+using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Styling;
-using AvaloniaButton = Avalonia.Controls.Button;
namespace AtomUI.Controls;
@@ -15,6 +16,7 @@ internal class CalendarItemTheme : BaseControlTheme
public const string ItemRootLayoutPart = "PART_ItemRootLayout";
public const string MonthViewPart = "PART_MonthView";
public const string YearViewPart = "PART_YearView";
+ public const string HeaderLayoutPart = "PART_HeaderLayout";
public const string PreviousButtonPart = "PART_PreviousButton";
public const string HeaderButtonPart = "PART_HeaderButton";
@@ -33,11 +35,6 @@ internal class CalendarItemTheme : BaseControlTheme
{
Name = ItemFramePart
};
-
- CreateTemplateParentBinding(frame, Border.BorderBrushProperty, CalendarItem.BorderBrushProperty);
- CreateTemplateParentBinding(frame, Border.BorderThicknessProperty, CalendarItem.BorderThicknessProperty);
- CreateTemplateParentBinding(frame, Border.CornerRadiusProperty, CalendarItem.CornerRadiusProperty);
- CreateTemplateParentBinding(frame, Border.BackgroundProperty, CalendarItem.BackgroundProperty);
var rootLayout = new DockPanel()
{
@@ -63,6 +60,7 @@ internal class CalendarItemTheme : BaseControlTheme
{
var headerLayout = new Grid()
{
+ Name = HeaderLayoutPart,
ColumnDefinitions = new ColumnDefinitions()
{
new ColumnDefinition(GridLength.Auto),
@@ -70,15 +68,29 @@ internal class CalendarItemTheme : BaseControlTheme
new ColumnDefinition(GridLength.Auto),
}
};
- var previousButton = new AvaloniaButton()
+
+ var previousButtonIcon = new PathIcon()
{
- Name = PreviousButtonPart
+ Kind = "LeftOutlined"
};
+ TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorTextDescription);
+ TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.ActiveFilledBrushProperty, GlobalTokenResourceKey.ColorText);
+ TokenResourceBinder.CreateGlobalTokenBinding(previousButtonIcon, PathIcon.SelectedFilledBrushProperty, GlobalTokenResourceKey.ColorText);
+
+ var previousButton = new IconButton()
+ {
+ Name = PreviousButtonPart,
+ Icon = previousButtonIcon
+ };
+
+ TokenResourceBinder.CreateGlobalTokenBinding(previousButton, IconButton.IconWidthProperty, GlobalTokenResourceKey.IconSize);
+ TokenResourceBinder.CreateGlobalTokenBinding(previousButton, IconButton.IconHeightProperty, GlobalTokenResourceKey.IconSize);
+
previousButton.RegisterInNameScope(scope);
Grid.SetColumn(previousButton, 0);
headerLayout.Children.Add(previousButton);
- var headerButton = new AvaloniaButton()
+ var headerButton = new HeadTextButton()
{
Name = HeaderButtonPart
};
@@ -86,10 +98,22 @@ internal class CalendarItemTheme : BaseControlTheme
headerButton.RegisterInNameScope(scope);
headerLayout.Children.Add(headerButton);
- var nextButton = new AvaloniaButton()
+ var nextButtonIcon = new PathIcon()
{
- Name = NextButtonPart
+ Kind = "RightOutlined"
};
+ TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorTextDescription);
+ TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.ActiveFilledBrushProperty, GlobalTokenResourceKey.ColorText);
+ TokenResourceBinder.CreateGlobalTokenBinding(nextButtonIcon, PathIcon.SelectedFilledBrushProperty, GlobalTokenResourceKey.ColorText);
+
+ var nextButton = new IconButton()
+ {
+ Name = NextButtonPart,
+ Icon = nextButtonIcon
+ };
+ TokenResourceBinder.CreateGlobalTokenBinding(nextButton, IconButton.IconWidthProperty, GlobalTokenResourceKey.IconSize);
+ TokenResourceBinder.CreateGlobalTokenBinding(nextButton, IconButton.IconHeightProperty, GlobalTokenResourceKey.IconSize);
+
Grid.SetColumn(nextButton, 2);
nextButton.RegisterInNameScope(scope);
headerLayout.Children.Add(nextButton);
@@ -99,6 +123,9 @@ internal class CalendarItemTheme : BaseControlTheme
private void BuildContentView(DockPanel layout, INameScope scope)
{
+ var dayTitleRowDef = new RowDefinition();
+ TokenResourceBinder.CreateTokenBinding(dayTitleRowDef, RowDefinition.HeightProperty, CalendarTokenResourceKey.DayTitleHeight);
+
var monthView = new Grid()
{
Name = MonthViewPart,
@@ -106,7 +133,7 @@ internal class CalendarItemTheme : BaseControlTheme
IsVisible = false,
RowDefinitions = new RowDefinitions()
{
- new RowDefinition(30, GridUnitType.Pixel),
+ dayTitleRowDef,
new RowDefinition(GridLength.Star),
new RowDefinition(GridLength.Star),
new RowDefinition(GridLength.Star),
@@ -153,9 +180,15 @@ internal class CalendarItemTheme : BaseControlTheme
protected override void BuildStyles()
{
var commonStyle = new Style(selector => selector.Nesting());
- commonStyle.Add(CalendarItem.BorderBrushProperty, GlobalTokenResourceKey.ColorBorder);
- commonStyle.Add(CalendarItem.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadius);
- commonStyle.Add(CalendarItem.BackgroundProperty, GlobalTokenResourceKey.ColorBgContainer);
+
+ commonStyle.Add(CalendarItem.MinWidthProperty, CalendarTokenResourceKey.ItemPanelMinWidth);
+ commonStyle.Add(CalendarItem.MinHeightProperty, CalendarTokenResourceKey.ItemPanelMinHeight);
+
+ var headerLayoutStyle = new Style(selector => selector.Nesting().Template().Name(HeaderLayoutPart));
+ headerLayoutStyle.Add(Grid.MarginProperty, CalendarTokenResourceKey.HeaderMargin);
+
+ commonStyle.Add(headerLayoutStyle);
+
Add(commonStyle);
}
}
@@ -164,7 +197,13 @@ internal class DayTitleTemplate : ITemplate
{
public Control Build()
{
- return new TextBlock();
+ var textBlock = new TextBlock()
+ {
+ HorizontalAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center
+ };
+ textBlock.Bind(TextBlock.TextProperty, new Binding());
+ return textBlock;
}
object? ITemplate.Build()
diff --git a/src/AtomUI.Controls/Calendar/CalendarTheme.cs b/src/AtomUI.Controls/Calendar/CalendarTheme.cs
index ce7c7d4bc..352f5b7de 100644
--- a/src/AtomUI.Controls/Calendar/CalendarTheme.cs
+++ b/src/AtomUI.Controls/Calendar/CalendarTheme.cs
@@ -2,6 +2,7 @@
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
+using Avalonia.Layout;
using Avalonia.Styling;
namespace AtomUI.Controls;
@@ -11,6 +12,7 @@ internal class CalendarTheme : BaseControlTheme
{
public const string RootPart = "PART_Root";
public const string CalendarItemPart = "PART_CalendarItem";
+ public const string FramePart = "PART_Frame";
public CalendarTheme()
: base(typeof(Calendar))
@@ -22,6 +24,17 @@ internal class CalendarTheme : BaseControlTheme
{
return new FuncControlTemplate((calendar, scope) =>
{
+ var frame = new Border()
+ {
+ Name = FramePart
+ };
+
+ CreateTemplateParentBinding(frame, Border.BorderBrushProperty, Calendar.BorderBrushProperty);
+ CreateTemplateParentBinding(frame, Border.BorderThicknessProperty, Calendar.BorderThicknessProperty);
+ CreateTemplateParentBinding(frame, Border.CornerRadiusProperty, Calendar.CornerRadiusProperty);
+ CreateTemplateParentBinding(frame, Border.BackgroundProperty, Calendar.BackgroundProperty);
+ CreateTemplateParentBinding(frame, Border.PaddingProperty, Calendar.PaddingProperty);
+
var rootLayout = new StackPanel()
{
Name = RootPart,
@@ -31,16 +44,16 @@ internal class CalendarTheme : BaseControlTheme
var calendarItem = new CalendarItem()
{
- Name = CalendarItemPart
+ Name = CalendarItemPart,
+ HorizontalAlignment = HorizontalAlignment.Center
};
- calendarItem.RegisterInNameScope(scope);
- CreateTemplateParentBinding(calendarItem, CalendarItem.BorderBrushProperty, Calendar.BorderBrushProperty);
- CreateTemplateParentBinding(calendarItem, CalendarItem.BorderThicknessProperty, Calendar.BorderThicknessProperty);
- CreateTemplateParentBinding(calendarItem, CalendarItem.CornerRadiusProperty, Calendar.CornerRadiusProperty);
- CreateTemplateParentBinding(calendarItem, CalendarItem.BackgroundProperty, Calendar.BackgroundProperty);
- rootLayout.Children.Add(calendarItem);
- return rootLayout;
+ calendarItem.RegisterInNameScope(scope);
+
+ rootLayout.Children.Add(calendarItem);
+ frame.Child = rootLayout;
+
+ return frame;
});
}
@@ -50,6 +63,7 @@ internal class CalendarTheme : BaseControlTheme
commonStyle.Add(Calendar.BorderBrushProperty, GlobalTokenResourceKey.ColorBorder);
commonStyle.Add(Calendar.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadius);
commonStyle.Add(Calendar.BackgroundProperty, GlobalTokenResourceKey.ColorBgContainer);
+ commonStyle.Add(Calendar.PaddingProperty, CalendarTokenResourceKey.PanelContentPadding);
Add(commonStyle);
}
}
\ No newline at end of file
diff --git a/src/AtomUI.Controls/Calendar/CalendarToken.cs b/src/AtomUI.Controls/Calendar/CalendarToken.cs
index d8a13d510..e63effa31 100644
--- a/src/AtomUI.Controls/Calendar/CalendarToken.cs
+++ b/src/AtomUI.Controls/Calendar/CalendarToken.cs
@@ -1,5 +1,7 @@
using AtomUI.Media;
using AtomUI.Theme.TokenSystem;
+using Avalonia;
+using Avalonia.Controls;
using Avalonia.Media;
namespace AtomUI.Controls;
@@ -49,16 +51,51 @@ internal class CalendarToken : AbstractControlDesignToken
///
public double CellWidth { get; set; }
+ ///
+ /// 单元格行高
+ ///
+ public double CellLineHeight { get; set; }
+
+ ///
+ /// 单元格外边距
+ ///
+ public Thickness CellMargin { get; set; }
+
+ ///
+ /// 日历项最小宽度
+ ///
+ public double ItemPanelMinWidth { get; set; }
+
+ ///
+ /// 日历项最小高度
+ ///
+ public double ItemPanelMinHeight { get; set; }
+
///
/// 单元格文本高度
///
public double TextHeight { get; set; }
+ ///
+ /// 面板内容内边距
+ ///
+ public Thickness PanelContentPadding { get; set; }
+
///
/// 十年/年/季/月/周单元格高度
///
public double WithoutTimeCellHeight { get; set; }
+ ///
+ /// 星期的高度
+ ///
+ public GridLength DayTitleHeight { get; set; }
+
+ ///
+ /// Header 头外边距
+ ///
+ public Thickness HeaderMargin { get; set; }
+
internal override void CalculateFromAlias()
{
base.CalculateFromAlias();
@@ -70,9 +107,16 @@ internal class CalendarToken : AbstractControlDesignToken
CellHoverWithRangeBg = colorPrimary.Lighten(35);
CellRangeBorderColor = colorPrimary.Lighten(20);
CellBgDisabled = _globalToken.ColorBgContainerDisabled;
- CellWidth = _globalToken.HeightToken.ControlHeightSM * 1.5;
+ CellWidth = _globalToken.HeightToken.ControlHeightSM;
CellHeight = _globalToken.HeightToken.ControlHeightSM;
TextHeight = _globalToken.HeightToken.ControlHeightLG;
WithoutTimeCellHeight = _globalToken.HeightToken.ControlHeightLG * 1.65;
+ CellMargin = new Thickness(_globalToken.MarginXXS);
+ PanelContentPadding = new Thickness(_globalToken.PaddingSM);
+ ItemPanelMinWidth = 230;
+ ItemPanelMinHeight = 260;
+ DayTitleHeight = new GridLength(40, GridUnitType.Pixel);
+ HeaderMargin = new Thickness(0, 0, 0, _globalToken.MarginXS);
+ CellLineHeight = CellHeight - 2; // 不知道为啥设置成一样,或者不设置文字有些靠下
}
}
\ No newline at end of file
diff --git a/src/AtomUI.Controls/Calendar/DateTimeHelper.cs b/src/AtomUI.Controls/Calendar/DateTimeHelper.cs
index 80ca7823e..217b40c4c 100644
--- a/src/AtomUI.Controls/Calendar/DateTimeHelper.cs
+++ b/src/AtomUI.Controls/Calendar/DateTimeHelper.cs
@@ -1,5 +1,6 @@
using System.Diagnostics;
using System.Globalization;
+using AtomUI.Theme;
namespace AtomUI.Controls;
@@ -67,14 +68,15 @@ internal static class DateTimeHelper
public static DateTimeFormatInfo GetCurrentDateFormat()
{
- if (CultureInfo.CurrentCulture.Calendar is GregorianCalendar) {
- return CultureInfo.CurrentCulture.DateTimeFormat;
+ var culture = ThemeManager.Current.CultureInfo ?? CultureInfo.CurrentCulture;
+ if (culture.Calendar is GregorianCalendar) {
+ return culture.DateTimeFormat;
} else {
- foreach (System.Globalization.Calendar cal in CultureInfo.CurrentCulture.OptionalCalendars) {
+ foreach (System.Globalization.Calendar cal in culture.OptionalCalendars) {
if (cal is GregorianCalendar) {
// if the default calendar is not Gregorian, return the
// first supported GregorianCalendar dtfi
- DateTimeFormatInfo dtfi = new CultureInfo(CultureInfo.CurrentCulture.Name).DateTimeFormat;
+ DateTimeFormatInfo dtfi = new CultureInfo(culture.Name).DateTimeFormat;
dtfi.Calendar = cal;
return dtfi;
}
diff --git a/src/AtomUI.Controls/Calendar/HeadTextButton.cs b/src/AtomUI.Controls/Calendar/HeadTextButton.cs
new file mode 100644
index 000000000..ad162b5a4
--- /dev/null
+++ b/src/AtomUI.Controls/Calendar/HeadTextButton.cs
@@ -0,0 +1,24 @@
+using AtomUI.Media;
+using AtomUI.Theme.Styling;
+using AtomUI.Theme.Utils;
+using Avalonia.Animation;
+using Avalonia.Controls.Primitives;
+
+namespace AtomUI.Controls;
+
+using AvaloniaButton = Avalonia.Controls.Button;
+
+internal class HeadTextButton : AvaloniaButton
+{
+ protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
+ {
+ base.OnApplyTemplate(e);
+ if (Transitions is null) {
+ Transitions = new Transitions()
+ {
+ AnimationUtils.CreateTransition(ForegroundProperty, GlobalTokenResourceKey.MotionDurationFast)
+ };
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/AtomUI.Controls/Calendar/HeadTextButtonTheme.cs b/src/AtomUI.Controls/Calendar/HeadTextButtonTheme.cs
new file mode 100644
index 000000000..6049a103e
--- /dev/null
+++ b/src/AtomUI.Controls/Calendar/HeadTextButtonTheme.cs
@@ -0,0 +1,51 @@
+using AtomUI.Theme;
+using AtomUI.Theme.Styling;
+using Avalonia.Controls.Presenters;
+using Avalonia.Controls.Templates;
+using Avalonia.Input;
+using Avalonia.Layout;
+using Avalonia.Media;
+using Avalonia.Styling;
+
+namespace AtomUI.Controls;
+
+[ControlThemeProvider]
+internal class HeadTextButtonTheme : BaseControlTheme
+{
+ private const string ContentPart = "PART_Content";
+
+ public HeadTextButtonTheme() : base(typeof(HeadTextButton)) {}
+
+ protected override IControlTemplate BuildControlTemplate()
+ {
+ return new FuncControlTemplate((headTextButton, scope) =>
+ {
+ var content = new ContentPresenter()
+ {
+ Name = ContentPart,
+ HorizontalContentAlignment = HorizontalAlignment.Center,
+ VerticalContentAlignment = VerticalAlignment.Center
+ };
+ CreateTemplateParentBinding(content, ContentPresenter.ContentProperty, HeadTextButton.ContentProperty);
+ CreateTemplateParentBinding(content, ContentPresenter.ContentTemplateProperty, HeadTextButton.ContentTemplateProperty);
+ CreateTemplateParentBinding(content, ContentPresenter.BackgroundProperty, HeadTextButton.BackgroundProperty);
+ return content;
+ });
+ }
+
+ protected override void BuildStyles()
+ {
+ var commonStyle = new Style(selector => selector.Nesting());
+ commonStyle.Add(HeadTextButton.HorizontalAlignmentProperty, HorizontalAlignment.Center);
+ commonStyle.Add(HeadTextButton.BackgroundProperty, GlobalTokenResourceKey.ColorTransparent);
+ commonStyle.Add(HeadTextButton.FontWeightProperty, FontWeight.SemiBold);
+ commonStyle.Add(HeadTextButton.FontSizeProperty, GlobalTokenResourceKey.FontSize);
+ commonStyle.Add(HeadTextButton.CursorProperty, new Cursor(StandardCursorType.Hand));
+
+ var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
+ hoverStyle.Add(HeadTextButton.ForegroundProperty, GlobalTokenResourceKey.ColorPrimary);
+ commonStyle.Add(hoverStyle);
+
+ Add(commonStyle);
+ }
+}
\ No newline at end of file
diff --git a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs
index 44ee95c92..ca07e8f1d 100644
--- a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs
+++ b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs
@@ -18,8 +18,11 @@
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SplitButtonTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TextButtonTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ToggleIconButtonTheme());
+ ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CalendarButtonTheme());
+ ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CalendarDayButtonTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CalendarItemTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CalendarTheme());
+ ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.HeadTextButtonTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CheckBoxTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CollapseItemTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CollapseTheme());
diff --git a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs
index 01d649c64..fcfc969c5 100644
--- a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs
+++ b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs
@@ -137,8 +137,15 @@ namespace AtomUI.Theme.Styling
public static readonly TokenResourceKey CellRangeBorderColor = new TokenResourceKey("Calendar.CellRangeBorderColor", "AtomUI.Token");
public static readonly TokenResourceKey CellHeight = new TokenResourceKey("Calendar.CellHeight", "AtomUI.Token");
public static readonly TokenResourceKey CellWidth = new TokenResourceKey("Calendar.CellWidth", "AtomUI.Token");
+ public static readonly TokenResourceKey CellLineHeight = new TokenResourceKey("Calendar.CellLineHeight", "AtomUI.Token");
+ public static readonly TokenResourceKey CellMargin = new TokenResourceKey("Calendar.CellMargin", "AtomUI.Token");
+ public static readonly TokenResourceKey ItemPanelMinWidth = new TokenResourceKey("Calendar.ItemPanelMinWidth", "AtomUI.Token");
+ public static readonly TokenResourceKey ItemPanelMinHeight = new TokenResourceKey("Calendar.ItemPanelMinHeight", "AtomUI.Token");
public static readonly TokenResourceKey TextHeight = new TokenResourceKey("Calendar.TextHeight", "AtomUI.Token");
+ public static readonly TokenResourceKey PanelContentPadding = new TokenResourceKey("Calendar.PanelContentPadding", "AtomUI.Token");
public static readonly TokenResourceKey WithoutTimeCellHeight = new TokenResourceKey("Calendar.WithoutTimeCellHeight", "AtomUI.Token");
+ public static readonly TokenResourceKey DayTitleHeight = new TokenResourceKey("Calendar.DayTitleHeight", "AtomUI.Token");
+ public static readonly TokenResourceKey HeaderMargin = new TokenResourceKey("Calendar.HeaderMargin", "AtomUI.Token");
}
public static class CheckBoxTokenResourceKey
diff --git a/src/AtomUI.Controls/StdPseudoClass.cs b/src/AtomUI.Controls/StdPseudoClass.cs
index 5b4444776..ad56960cc 100644
--- a/src/AtomUI.Controls/StdPseudoClass.cs
+++ b/src/AtomUI.Controls/StdPseudoClass.cs
@@ -2,20 +2,21 @@
public static class StdPseudoClass
{
- public const string Disabled = ":disabled";
- public const string Focus = ":focus";
- public const string FocusWithIn = ":focus-within";
- public const string PointerOver = ":pointerover";
- public const string Checked = ":checked";
- public const string UnChecked = ":unchecked";
- public const string Pressed = ":pressed";
- public const string Selected = ":selected";
- public const string Indeterminate = ":indeterminate";
- public const string Dragging = ":dragging";
- public const string Empty = ":empty";
- public const string FlyoutOpen = ":flyout-open";
- public const string Expanded = ":expanded";
- public const string Open = ":open";
- public const string Horizontal = ":horizontal";
- public const string Vertical = ":vertical";
+ public const string Disabled = ":disabled";
+ public const string Focus = ":focus";
+ public const string FocusWithIn = ":focus-within";
+ public const string PointerOver = ":pointerover";
+ public const string Checked = ":checked";
+ public const string UnChecked = ":unchecked";
+ public const string Pressed = ":pressed";
+ public const string Selected = ":selected";
+ public const string Indeterminate = ":indeterminate";
+ public const string Dragging = ":dragging";
+ public const string Empty = ":empty";
+ public const string FlyoutOpen = ":flyout-open";
+ public const string Expanded = ":expanded";
+ public const string Open = ":open";
+ public const string Horizontal = ":horizontal";
+ public const string Vertical = ":vertical";
+ public const string InActive = ":inactive";
}
\ No newline at end of file