committed by
GitHub
202 changed files with 8657 additions and 1101 deletions
@ -1,7 +1,6 @@ |
|||
<ProjectConfiguration> |
|||
<Settings> |
|||
<DefaultTestTimeout>1000</DefaultTestTimeout> |
|||
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely> |
|||
<DefaultTestTimeout>3000</DefaultTestTimeout> |
|||
<PreviouslyBuiltSuccessfully>True</PreviouslyBuiltSuccessfully> |
|||
</Settings> |
|||
</ProjectConfiguration> |
|||
@ -1,5 +1,5 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="MonoMac.NetStandard" Version="0.0.3" /> |
|||
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -1,5 +0,0 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="Serilog.Sinks.Trace" Version="2.1.0" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -1,5 +1,7 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="Serilog" Version="2.4.0" /> |
|||
<PackageReference Include="Serilog" Version="2.5.0" /> |
|||
<PackageReference Include="Serilog.Sinks.Trace" Version="2.1.0" /> |
|||
<PackageReference Include="Serilog.Sinks.Debug" Version="1.0.0" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -0,0 +1,47 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
|||
<StackPanel Orientation="Vertical" Gap="4"> |
|||
<TextBlock Classes="h1">Calendar</TextBlock> |
|||
<TextBlock Classes="h2">A calendar control for selecting dates</TextBlock> |
|||
|
|||
<StackPanel Orientation="Horizontal" |
|||
Margin="0,16,0,0" |
|||
HorizontalAlignment="Center" |
|||
Gap="16"> |
|||
<StackPanel Orientation="Vertical"> |
|||
<TextBlock Text="SelectionMode: None"/> |
|||
<Calendar SelectionMode="None" |
|||
Margin="0,0,0,8"/> |
|||
|
|||
<TextBlock Text="SelectionMode: SingleDate"/> |
|||
<Calendar SelectionMode="SingleDate" |
|||
Margin="0,0,0,8"/> |
|||
|
|||
<TextBlock Text="Disabled"/> |
|||
<Calendar IsEnabled="False" |
|||
SelectionMode="SingleDate"/> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Orientation="Vertical"> |
|||
<TextBlock Text="SelectionMode: SingleRange"/> |
|||
<Calendar SelectionMode="SingleRange" |
|||
Margin="0,0,0,8"/> |
|||
|
|||
<TextBlock Text="SelectionMode: MultipleRange"/> |
|||
<Calendar SelectionMode="MultipleRange"/> |
|||
</StackPanel> |
|||
|
|||
<StackPanel Orientation="Vertical"> |
|||
<TextBlock Text="DisplayDates"/> |
|||
<Calendar Name="DisplayDatesCalendar" |
|||
SelectionMode="SingleDate" |
|||
Margin="0,0,0,8"/> |
|||
|
|||
<TextBlock Text="BlackoutDates"/> |
|||
<Calendar Name="BlackoutDatesCalendar" |
|||
SelectionMode="SingleDate" /> |
|||
</StackPanel> |
|||
|
|||
</StackPanel> |
|||
</StackPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,28 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Markup.Xaml; |
|||
using System; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public class CalendarPage : UserControl |
|||
{ |
|||
public CalendarPage() |
|||
{ |
|||
this.InitializeComponent(); |
|||
|
|||
var today = DateTime.Today; |
|||
var cal1 = this.FindControl<Calendar>("DisplayDatesCalendar"); |
|||
cal1.DisplayDateStart = today.AddDays(-25); |
|||
cal1.DisplayDateEnd = today.AddDays(25); |
|||
|
|||
var cal2 = this.FindControl<Calendar>("BlackoutDatesCalendar"); |
|||
cal2.BlackoutDates.AddDatesInPast(); |
|||
cal2.BlackoutDates.Add(new CalendarDateRange(today.AddDays(6))); |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
} |
|||
} |
|||
@ -1,15 +1,28 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui"> |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
|||
<StackPanel Orientation="Vertical" Gap="4"> |
|||
<TextBlock Classes="h1">CheckBox</TextBlock> |
|||
<TextBlock Classes="h2">A check box control</TextBlock> |
|||
|
|||
<StackPanel Orientation="Vertical" |
|||
<StackPanel Orientation="Horizontal" |
|||
Margin="0,16,0,0" |
|||
HorizontalAlignment="Center" |
|||
Gap="16"> |
|||
<CheckBox>Unchecked</CheckBox> |
|||
<CheckBox IsChecked="True">Checked</CheckBox> |
|||
<CheckBox IsChecked="True" IsEnabled="False">Disabled</CheckBox> |
|||
</StackPanel> |
|||
<StackPanel Orientation="Vertical" |
|||
Gap="16"> |
|||
<CheckBox>Unchecked</CheckBox> |
|||
<CheckBox IsChecked="True">Checked</CheckBox> |
|||
<CheckBox IsChecked="{x:Null}">Indeterminate</CheckBox> |
|||
<CheckBox IsChecked="True" IsEnabled="False">Disabled</CheckBox> |
|||
</StackPanel> |
|||
<StackPanel Orientation="Vertical" |
|||
HorizontalAlignment="Center" |
|||
Gap="16"> |
|||
<CheckBox IsChecked="False" IsThreeState="True">Three State: Unchecked</CheckBox> |
|||
<CheckBox IsChecked="True" IsThreeState="True">Three State: Checked</CheckBox> |
|||
<CheckBox IsChecked="{x:Null}" IsThreeState="True">Three State: Indeterminate</CheckBox> |
|||
<CheckBox IsChecked="{x:Null}" IsThreeState="True" IsEnabled="False">Three State: Disabled</CheckBox> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</UserControl> |
|||
@ -1,15 +1,27 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui"> |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
|||
<StackPanel Orientation="Vertical" Gap="4"> |
|||
<TextBlock Classes="h1">RadioButton</TextBlock> |
|||
<TextBlock Classes="h2">Allows the selection of a single option of many</TextBlock> |
|||
|
|||
<StackPanel Orientation="Vertical" |
|||
<StackPanel Orientation="Horizontal" |
|||
Margin="0,16,0,0" |
|||
HorizontalAlignment="Center" |
|||
Gap="16"> |
|||
<RadioButton IsChecked="True">Option 1</RadioButton> |
|||
<RadioButton>Option 2</RadioButton> |
|||
<RadioButton IsEnabled="False">Disabled</RadioButton> |
|||
</StackPanel> |
|||
<StackPanel Orientation="Vertical" |
|||
Gap="16"> |
|||
<RadioButton IsChecked="True">Option 1</RadioButton> |
|||
<RadioButton>Option 2</RadioButton> |
|||
<RadioButton IsChecked="{x:Null}">Option 3</RadioButton> |
|||
<RadioButton IsEnabled="False">Disabled</RadioButton> |
|||
</StackPanel> |
|||
<StackPanel Orientation="Vertical" |
|||
Gap="16"> |
|||
<RadioButton IsChecked="True" IsThreeState="True">Three States: Option 1</RadioButton> |
|||
<RadioButton IsChecked="False" IsThreeState="True">Three States: Option 2</RadioButton> |
|||
<RadioButton IsChecked="{x:Null}" IsThreeState="True">Three States: Option 3</RadioButton> |
|||
<RadioButton IsChecked="{x:Null}" IsThreeState="True" IsEnabled="False">Disabled</RadioButton> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</UserControl> |
|||
@ -1,4 +1,5 @@ |
|||
copy ..\samples\ControlCatalog.NetCore\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netcoreapp2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.gtk3\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.win32\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.win32\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.skia\$args\lib\netstandard2.0\ |
|||
@ -1,16 +0,0 @@ |
|||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Avalonia.Reactive |
|||
{ |
|||
public class AnonymousSubject<T> : AnonymousSubject<T, T>, ISubject<T> |
|||
{ |
|||
public AnonymousSubject(IObserver<T> observer, IObservable<T> observable) |
|||
: base(observer, observable) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,49 +0,0 @@ |
|||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Avalonia.Reactive |
|||
{ |
|||
public class AnonymousSubject<T, U> : ISubject<T, U> |
|||
{ |
|||
private readonly IObserver<T> _observer; |
|||
private readonly IObservable<U> _observable; |
|||
|
|||
public AnonymousSubject(IObserver<T> observer, IObservable<U> observable) |
|||
{ |
|||
_observer = observer; |
|||
_observable = observable; |
|||
} |
|||
|
|||
public void OnCompleted() |
|||
{ |
|||
_observer.OnCompleted(); |
|||
} |
|||
|
|||
public void OnError(Exception error) |
|||
{ |
|||
if (error == null) |
|||
throw new ArgumentNullException("error"); |
|||
|
|||
_observer.OnError(error); |
|||
} |
|||
|
|||
public void OnNext(T value) |
|||
{ |
|||
_observer.OnNext(value); |
|||
} |
|||
|
|||
public IDisposable Subscribe(IObserver<U> observer) |
|||
{ |
|||
if (observer == null) |
|||
throw new ArgumentNullException("observer"); |
|||
|
|||
//
|
|||
// [OK] Use of unsafe Subscribe: non-pretentious wrapping of an observable sequence.
|
|||
//
|
|||
return _observable.Subscribe/*Unsafe*/(observer); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reactive.Disposables; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Text; |
|||
|
|||
namespace Avalonia.Utilities |
|||
{ |
|||
/// <summary>
|
|||
/// A utility class to enable deferring assignment until after property-changed notifications are sent.
|
|||
/// </summary>
|
|||
/// <typeparam name="TProperty">The type of the object that represents the property.</typeparam>
|
|||
/// <typeparam name="TSetRecord">The type of value with which to track the delayed assignment.</typeparam>
|
|||
class DeferredSetter<TProperty, TSetRecord> |
|||
where TProperty: class |
|||
{ |
|||
private struct NotifyDisposable : IDisposable |
|||
{ |
|||
private readonly SettingStatus status; |
|||
|
|||
internal NotifyDisposable(SettingStatus status) |
|||
{ |
|||
this.status = status; |
|||
status.Notifying = true; |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
status.Notifying = false; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Information on current setting/notification status of a property.
|
|||
/// </summary>
|
|||
private class SettingStatus |
|||
{ |
|||
public bool Notifying { get; set; } |
|||
|
|||
private Queue<TSetRecord> pendingValues; |
|||
|
|||
public Queue<TSetRecord> PendingValues |
|||
{ |
|||
get |
|||
{ |
|||
return pendingValues ?? (pendingValues = new Queue<TSetRecord>()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private readonly ConditionalWeakTable<TProperty, SettingStatus> setRecords = new ConditionalWeakTable<TProperty, SettingStatus>(); |
|||
|
|||
/// <summary>
|
|||
/// Mark the property as currently notifying.
|
|||
/// </summary>
|
|||
/// <param name="property">The property to mark as notifying.</param>
|
|||
/// <returns>Returns a disposable that when disposed, marks the property as done notifying.</returns>
|
|||
private NotifyDisposable MarkNotifying(TProperty property) |
|||
{ |
|||
Contract.Requires<InvalidOperationException>(!IsNotifying(property)); |
|||
|
|||
return new NotifyDisposable(setRecords.GetOrCreateValue(property)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if the property is currently notifying listeners.
|
|||
/// </summary>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <returns>If the property is currently notifying listeners.</returns>
|
|||
private bool IsNotifying(TProperty property) |
|||
=> setRecords.TryGetValue(property, out var value) && value.Notifying; |
|||
|
|||
/// <summary>
|
|||
/// Add a pending assignment for the property.
|
|||
/// </summary>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <param name="value">The value to assign.</param>
|
|||
private void AddPendingSet(TProperty property, TSetRecord value) |
|||
{ |
|||
Contract.Requires<InvalidOperationException>(IsNotifying(property)); |
|||
|
|||
setRecords.GetOrCreateValue(property).PendingValues.Enqueue(value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Checks if there are any pending assignments for the property.
|
|||
/// </summary>
|
|||
/// <param name="property">The property to check.</param>
|
|||
/// <returns>If the property has any pending assignments.</returns>
|
|||
private bool HasPendingSet(TProperty property) |
|||
{ |
|||
return setRecords.TryGetValue(property, out var status) && status.PendingValues.Count != 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the first pending assignment for the property.
|
|||
/// </summary>
|
|||
/// <param name="property">The property to check.</param>
|
|||
/// <returns>The first pending assignment for the property.</returns>
|
|||
private TSetRecord GetFirstPendingSet(TProperty property) |
|||
{ |
|||
return setRecords.GetOrCreateValue(property).PendingValues.Dequeue(); |
|||
} |
|||
|
|||
public delegate bool SetterDelegate<TValue>(TSetRecord record, ref TValue backing, Action<Action> notifyCallback); |
|||
|
|||
/// <summary>
|
|||
/// Set the property and notify listeners while ensuring we don't get into a stack overflow as happens with #855 and #824
|
|||
/// </summary>
|
|||
/// <param name="property">The property to set.</param>
|
|||
/// <param name="backing">The backing field for the property</param>
|
|||
/// <param name="setterCallback">
|
|||
/// A callback that actually sets the property.
|
|||
/// The first parameter is the value to set, and the second is a wrapper that takes a callback that sends the property-changed notification.
|
|||
/// </param>
|
|||
/// <param name="value">The value to try to set.</param>
|
|||
public bool SetAndNotify<TValue>( |
|||
TProperty property, |
|||
ref TValue backing, |
|||
SetterDelegate<TValue> setterCallback, |
|||
TSetRecord value) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(setterCallback != null); |
|||
if (!IsNotifying(property)) |
|||
{ |
|||
bool updated = false; |
|||
if (!object.Equals(value, backing)) |
|||
{ |
|||
updated = setterCallback(value, ref backing, notification => |
|||
{ |
|||
using (MarkNotifying(property)) |
|||
{ |
|||
notification(); |
|||
} |
|||
}); |
|||
} |
|||
while (HasPendingSet(property)) |
|||
{ |
|||
updated |= setterCallback(GetFirstPendingSet(property), ref backing, notification => |
|||
{ |
|||
using (MarkNotifying(property)) |
|||
{ |
|||
notification(); |
|||
} |
|||
}); |
|||
} |
|||
return updated; |
|||
} |
|||
else if(!object.Equals(value, backing)) |
|||
{ |
|||
AddPendingSet(property, value); |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,215 @@ |
|||
// (c) Copyright Microsoft Corporation.
|
|||
// This source is subject to the Microsoft Public License (Ms-PL).
|
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|||
// All other rights reserved.
|
|||
|
|||
using Avalonia.Threading; |
|||
using System; |
|||
using System.Collections.ObjectModel; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
|
|||
namespace Avalonia.Controls.Primitives |
|||
{ |
|||
public sealed class CalendarBlackoutDatesCollection : ObservableCollection<CalendarDateRange> |
|||
{ |
|||
/// <summary>
|
|||
/// The Calendar whose dates this object represents.
|
|||
/// </summary>
|
|||
private Calendar _owner; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the
|
|||
/// <see cref="T:Avalonia.Controls.Primitives.CalendarBlackoutDatesCollection" />
|
|||
/// class.
|
|||
/// </summary>
|
|||
/// <param name="owner">
|
|||
/// The <see cref="T:Avalonia.Controls.Calendar" /> whose dates
|
|||
/// this object represents.
|
|||
/// </param>
|
|||
public CalendarBlackoutDatesCollection(Calendar owner) |
|||
{ |
|||
_owner = owner ?? throw new ArgumentNullException(nameof(owner)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds all dates before <see cref="P:System.DateTime.Today" /> to the
|
|||
/// collection.
|
|||
/// </summary>
|
|||
public void AddDatesInPast() |
|||
{ |
|||
Add(new CalendarDateRange(DateTime.MinValue, DateTime.Today.AddDays(-1))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a value that represents whether this collection contains the
|
|||
/// specified date.
|
|||
/// </summary>
|
|||
/// <param name="date">The date to search for.</param>
|
|||
/// <returns>
|
|||
/// True if the collection contains the specified date; otherwise,
|
|||
/// false.
|
|||
/// </returns>
|
|||
public bool Contains(DateTime date) |
|||
{ |
|||
int count = Count; |
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
if (DateTimeHelper.InRange(date, this[i])) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a value that represents whether this collection contains the
|
|||
/// specified range of dates.
|
|||
/// </summary>
|
|||
/// <param name="start">The start of the date range.</param>
|
|||
/// <param name="end">The end of the date range.</param>
|
|||
/// <returns>
|
|||
/// True if all dates in the range are contained in the collection;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public bool Contains(DateTime start, DateTime end) |
|||
{ |
|||
DateTime rangeStart; |
|||
DateTime rangeEnd; |
|||
|
|||
if (DateTime.Compare(end, start) > -1) |
|||
{ |
|||
rangeStart = DateTimeHelper.DiscardTime(start).Value; |
|||
rangeEnd = DateTimeHelper.DiscardTime(end).Value; |
|||
} |
|||
else |
|||
{ |
|||
rangeStart = DateTimeHelper.DiscardTime(end).Value; |
|||
rangeEnd = DateTimeHelper.DiscardTime(start).Value; |
|||
} |
|||
|
|||
int count = Count; |
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
CalendarDateRange range = this[i]; |
|||
if (DateTime.Compare(range.Start, rangeStart) == 0 && DateTime.Compare(range.End, rangeEnd) == 0) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a value that represents whether this collection contains any
|
|||
/// date in the specified range.
|
|||
/// </summary>
|
|||
/// <param name="range">The range of dates to search for.</param>
|
|||
/// <returns>
|
|||
/// True if any date in the range is contained in the collection;
|
|||
/// otherwise, false.
|
|||
/// </returns>
|
|||
public bool ContainsAny(CalendarDateRange range) |
|||
{ |
|||
return this.Any(r => r.ContainsAny(range)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes all items from the collection.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void ClearItems() |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
base.ClearItems(); |
|||
_owner.UpdateMonths(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Inserts an item into the collection at the specified index.
|
|||
/// </summary>
|
|||
/// <param name="index">
|
|||
/// The zero-based index at which item should be inserted.
|
|||
/// </param>
|
|||
/// <param name="item">The object to insert.</param>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void InsertItem(int index, CalendarDateRange item) |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
if (!IsValid(item)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException("Value is not valid."); |
|||
} |
|||
|
|||
base.InsertItem(index, item); |
|||
_owner.UpdateMonths(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the item at the specified index of the collection.
|
|||
/// </summary>
|
|||
/// <param name="index">
|
|||
/// The zero-based index of the element to remove.
|
|||
/// </param>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void RemoveItem(int index) |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
base.RemoveItem(index); |
|||
_owner.UpdateMonths(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Replaces the element at the specified index.
|
|||
/// </summary>
|
|||
/// <param name="index">
|
|||
/// The zero-based index of the element to replace.
|
|||
/// </param>
|
|||
/// <param name="item">
|
|||
/// The new value for the element at the specified index.
|
|||
/// </param>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void SetItem(int index, CalendarDateRange item) |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
if (!IsValid(item)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException("Value is not valid."); |
|||
} |
|||
|
|||
base.SetItem(index, item); |
|||
_owner.UpdateMonths(); |
|||
} |
|||
|
|||
private bool IsValid(CalendarDateRange item) |
|||
{ |
|||
foreach (DateTime day in _owner.SelectedDates) |
|||
{ |
|||
if (DateTimeHelper.InRange(day, item)) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
private void EnsureValidThread() |
|||
{ |
|||
Dispatcher.UIThread.VerifyAccess(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
// (c) Copyright Microsoft Corporation.
|
|||
// This source is subject to the Microsoft Public License (Ms-PL).
|
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|||
// All other rights reserved.
|
|||
|
|||
using Avalonia.Input; |
|||
using System; |
|||
|
|||
namespace Avalonia.Controls.Primitives |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a button on a
|
|||
/// <see cref="T:Avalonia.Controls.Calendar" />.
|
|||
/// </summary>
|
|||
public sealed class CalendarButton : Button |
|||
{ |
|||
/// <summary>
|
|||
/// A value indicating whether the button is focused.
|
|||
/// </summary>
|
|||
private bool _isCalendarButtonFocused; |
|||
|
|||
/// <summary>
|
|||
/// A value indicating whether the button is inactive.
|
|||
/// </summary>
|
|||
private bool _isInactive; |
|||
|
|||
/// <summary>
|
|||
/// A value indicating whether the button is selected.
|
|||
/// </summary>
|
|||
private bool _isSelected; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the
|
|||
/// <see cref="T:Avalonia.Controls.Primitives.CalendarButton" />
|
|||
/// class.
|
|||
/// </summary>
|
|||
public CalendarButton() |
|||
: base() |
|||
{ |
|||
Content = DateTimeHelper.GetCurrentDateFormat().AbbreviatedMonthNames[0]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the Calendar associated with this button.
|
|||
/// </summary>
|
|||
internal Calendar Owner { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the button is focused.
|
|||
/// </summary>
|
|||
internal bool IsCalendarButtonFocused |
|||
{ |
|||
get { return _isCalendarButtonFocused; } |
|||
set |
|||
{ |
|||
if (_isCalendarButtonFocused != value) |
|||
{ |
|||
_isCalendarButtonFocused = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the button is inactive.
|
|||
/// </summary>
|
|||
internal bool IsInactive |
|||
{ |
|||
get { return _isInactive; } |
|||
set |
|||
{ |
|||
if (_isInactive != value) |
|||
{ |
|||
_isInactive = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the button is selected.
|
|||
/// </summary>
|
|||
internal bool IsSelected |
|||
{ |
|||
get { return _isSelected; } |
|||
set |
|||
{ |
|||
if (_isSelected != value) |
|||
{ |
|||
_isSelected = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Builds the visual tree for the
|
|||
/// <see cref="T:System.Windows.Controls.Primitives.CalendarButton" />
|
|||
/// when a new template is applied.
|
|||
/// </summary>
|
|||
protected override void OnTemplateApplied(TemplateAppliedEventArgs e) |
|||
{ |
|||
base.OnTemplateApplied(e); |
|||
SetPseudoClasses(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets PseudoClasses based on current state.
|
|||
/// </summary>
|
|||
private void SetPseudoClasses() |
|||
{ |
|||
PseudoClasses.Set(":selected", IsSelected); |
|||
PseudoClasses.Set(":inactive", IsInactive); |
|||
PseudoClasses.Set(":btnfocused", IsCalendarButtonFocused && IsEnabled); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Occurs when the left mouse button is pressed (or when the tip of the
|
|||
/// stylus touches the tablet PC) while the mouse pointer is over a
|
|||
/// UIElement.
|
|||
/// </summary>
|
|||
public event EventHandler<PointerPressedEventArgs> CalendarLeftMouseButtonDown; |
|||
|
|||
/// <summary>
|
|||
/// Occurs when the left mouse button is released (or the tip of the
|
|||
/// stylus is removed from the tablet PC) while the mouse (or the
|
|||
/// stylus) is over a UIElement (or while a UIElement holds mouse
|
|||
/// capture).
|
|||
/// </summary>
|
|||
public event EventHandler<PointerReleasedEventArgs> CalendarLeftMouseButtonUp; |
|||
|
|||
/// <summary>
|
|||
/// Provides class handling for the MouseLeftButtonDown event that
|
|||
/// occurs when the left mouse button is pressed while the mouse pointer
|
|||
/// is over this control.
|
|||
/// </summary>
|
|||
/// <param name="e">The event data. </param>
|
|||
/// <exception cref="System.ArgumentNullException">
|
|||
/// e is a null reference (Nothing in Visual Basic).
|
|||
/// </exception>
|
|||
/// <remarks>
|
|||
/// This method marks the MouseLeftButtonDown event as handled by
|
|||
/// setting the MouseButtonEventArgs.Handled property of the event data
|
|||
/// to true when the button is enabled and its ClickMode is not set to
|
|||
/// Hover. Since this method marks the MouseLeftButtonDown event as
|
|||
/// handled in some situations, you should use the Click event instead
|
|||
/// to detect a button click.
|
|||
/// </remarks>
|
|||
protected override void OnPointerPressed(PointerPressedEventArgs e) |
|||
{ |
|||
base.OnPointerPressed(e); |
|||
if (e.MouseButton == MouseButton.Left) |
|||
CalendarLeftMouseButtonDown?.Invoke(this, e); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Provides handling for the MouseLeftButtonUp event that occurs when
|
|||
/// the left mouse button is released while the mouse pointer is over
|
|||
/// this control.
|
|||
/// </summary>
|
|||
/// <param name="e">The event data.</param>
|
|||
/// <exception cref="System.ArgumentNullException">
|
|||
/// e is a null reference (Nothing in Visual Basic).
|
|||
/// </exception>
|
|||
/// <remarks>
|
|||
/// This method marks the MouseLeftButtonUp event as handled by setting
|
|||
/// the MouseButtonEventArgs.Handled property of the event data to true
|
|||
/// when the button is enabled and its ClickMode is not set to Hover.
|
|||
/// Since this method marks the MouseLeftButtonUp event as handled in
|
|||
/// some situations, you should use the Click event instead to detect a
|
|||
/// button click.
|
|||
/// </remarks>
|
|||
protected override void OnPointerReleased(PointerReleasedEventArgs e) |
|||
{ |
|||
base.OnPointerReleased(e); |
|||
if (e.MouseButton == MouseButton.Left) |
|||
CalendarLeftMouseButtonUp?.Invoke(this, e); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// We need to simulate the MouseLeftButtonUp event for the
|
|||
/// CalendarButton that stays in Pressed state after MouseCapture is
|
|||
/// released since there is no actual MouseLeftButtonUp event for the
|
|||
/// release.
|
|||
/// </summary>
|
|||
/// <param name="e">Event arguments.</param>
|
|||
internal void SendMouseLeftButtonUp(PointerReleasedEventArgs e) |
|||
{ |
|||
e.Handled = false; |
|||
base.OnPointerReleased(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
// (c) Copyright Microsoft Corporation.
|
|||
// This source is subject to the Microsoft Public License (Ms-PL).
|
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|||
// All other rights reserved.
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
public sealed class CalendarDateRange |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the first date in the represented range.
|
|||
/// </summary>
|
|||
/// <value>The first date in the represented range.</value>
|
|||
public DateTime Start { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the last date in the represented range.
|
|||
/// </summary>
|
|||
/// <value>The last date in the represented range.</value>
|
|||
public DateTime End { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the
|
|||
/// <see cref="T:System.Windows.Controls.CalendarDateRange" /> class
|
|||
/// with a single date.
|
|||
/// </summary>
|
|||
/// <param name="day">The date to be represented by the range.</param>
|
|||
public CalendarDateRange(DateTime day) |
|||
{ |
|||
Start = day; |
|||
End = day; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the
|
|||
/// <see cref="T:System.Windows.Controls.CalendarDateRange" /> class
|
|||
/// with a range of dates.
|
|||
/// </summary>
|
|||
/// <param name="start">
|
|||
/// The start of the range to be represented.
|
|||
/// </param>
|
|||
/// <param name="end">The end of the range to be represented.</param>
|
|||
public CalendarDateRange(DateTime start, DateTime end) |
|||
{ |
|||
if (DateTime.Compare(end, start) >= 0) |
|||
{ |
|||
Start = start; |
|||
End = end; |
|||
} |
|||
else |
|||
{ |
|||
// Always use the start for ranges on the same day
|
|||
Start = start; |
|||
End = start; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns true if any day in the given DateTime range is contained in
|
|||
/// the current CalendarDateRange.
|
|||
/// </summary>
|
|||
/// <param name="range">Inherited code: Requires comment 1.</param>
|
|||
/// <returns>Inherited code: Requires comment 2.</returns>
|
|||
internal bool ContainsAny(CalendarDateRange range) |
|||
{ |
|||
Debug.Assert(range != null, "range should not be null!"); |
|||
|
|||
int start = DateTime.Compare(Start, range.Start); |
|||
|
|||
// Check if any part of the supplied range is contained by this
|
|||
// range or if the supplied range completely covers this range.
|
|||
return (start <= 0 && DateTime.Compare(End, range.Start) >= 0) || |
|||
(start >= 0 && DateTime.Compare(Start, range.End) <= 0); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,253 @@ |
|||
// (c) Copyright Microsoft Corporation.
|
|||
// This source is subject to the Microsoft Public License (Ms-PL).
|
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|||
// All other rights reserved.
|
|||
|
|||
using Avalonia.Input; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.Text; |
|||
|
|||
namespace Avalonia.Controls.Primitives |
|||
{ |
|||
public sealed class CalendarDayButton : Button |
|||
{ |
|||
/// <summary>
|
|||
/// Default content for the CalendarDayButton.
|
|||
/// </summary>
|
|||
private const int DefaultContent = 1; |
|||
|
|||
private bool _isCurrent; |
|||
private bool _ignoringMouseOverState; |
|||
private bool _isBlackout; |
|||
private bool _isToday; |
|||
private bool _isInactive; |
|||
private bool _isSelected; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the
|
|||
/// <see cref="T:Avalonia.Controls.Primitives.CalendarDayButton" />
|
|||
/// class.
|
|||
/// </summary>
|
|||
public CalendarDayButton() |
|||
: base() |
|||
{ |
|||
//Focusable = false;
|
|||
Content = DefaultContent.ToString(CultureInfo.CurrentCulture); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the Calendar associated with this button.
|
|||
/// </summary>
|
|||
internal Calendar Owner { get; set; } |
|||
internal int Index { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the button is the focused
|
|||
/// element on the Calendar control.
|
|||
/// </summary>
|
|||
internal bool IsCurrent |
|||
{ |
|||
get { return _isCurrent; } |
|||
set |
|||
{ |
|||
if (_isCurrent != value) |
|||
{ |
|||
_isCurrent = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ensure the button is not in the MouseOver state.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// If a button is in the MouseOver state when a Popup is closed (as is
|
|||
/// the case when you select a date in the DatePicker control), it will
|
|||
/// continue to think it's in the mouse over state even when the Popup
|
|||
/// opens again and it's not. This method is used to forcibly clear the
|
|||
/// state by changing the CommonStates state group.
|
|||
/// </remarks>
|
|||
internal void IgnoreMouseOverState() |
|||
{ |
|||
// TODO: Investigate whether this needs to be done by changing the
|
|||
// state everytime we change any state, or if it can be done once
|
|||
// to properly reset the control.
|
|||
|
|||
_ignoringMouseOverState = false; |
|||
|
|||
// If the button thinks it's in the MouseOver state (which can
|
|||
// happen when a Popup is closed before the button can change state)
|
|||
// we will override the state so it shows up as normal.
|
|||
if (IsPointerOver) |
|||
{ |
|||
_ignoringMouseOverState = true; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether this is a blackout date.
|
|||
/// </summary>
|
|||
internal bool IsBlackout |
|||
{ |
|||
get { return _isBlackout; } |
|||
set |
|||
{ |
|||
if (_isBlackout != value) |
|||
{ |
|||
_isBlackout = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether this button represents
|
|||
/// today.
|
|||
/// </summary>
|
|||
internal bool IsToday |
|||
{ |
|||
get { return _isToday; } |
|||
set |
|||
{ |
|||
if (_isToday != value) |
|||
{ |
|||
_isToday = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the button is inactive.
|
|||
/// </summary>
|
|||
internal bool IsInactive |
|||
{ |
|||
get { return _isInactive; } |
|||
set |
|||
{ |
|||
if (_isInactive != value) |
|||
{ |
|||
_isInactive = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets a value indicating whether the button is selected.
|
|||
/// </summary>
|
|||
internal bool IsSelected |
|||
{ |
|||
get { return _isSelected; } |
|||
set |
|||
{ |
|||
if (_isSelected != value) |
|||
{ |
|||
_isSelected = value; |
|||
SetPseudoClasses(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected override void OnTemplateApplied(TemplateAppliedEventArgs e) |
|||
{ |
|||
base.OnTemplateApplied(e); |
|||
SetPseudoClasses(); |
|||
} |
|||
private void SetPseudoClasses() |
|||
{ |
|||
if (_ignoringMouseOverState) |
|||
{ |
|||
PseudoClasses.Set(":pressed", IsPressed); |
|||
PseudoClasses.Set(":disabled", !IsEnabled); |
|||
} |
|||
|
|||
PseudoClasses.Set(":selected", IsSelected); |
|||
PseudoClasses.Set(":inactive", IsInactive); |
|||
PseudoClasses.Set(":today", IsToday); |
|||
PseudoClasses.Set(":blackout", IsBlackout); |
|||
PseudoClasses.Set(":dayfocused", IsCurrent && IsEnabled); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Occurs when the left mouse button is pressed (or when the tip of the
|
|||
/// stylus touches the tablet PC) while the mouse pointer is over a
|
|||
/// UIElement.
|
|||
/// </summary>
|
|||
public event EventHandler<PointerPressedEventArgs> CalendarDayButtonMouseDown; |
|||
|
|||
/// <summary>
|
|||
/// Occurs when the left mouse button is released (or the tip of the
|
|||
/// stylus is removed from the tablet PC) while the mouse (or the
|
|||
/// stylus) is over a UIElement (or while a UIElement holds mouse
|
|||
/// capture).
|
|||
/// </summary>
|
|||
public event EventHandler<PointerReleasedEventArgs> CalendarDayButtonMouseUp; |
|||
|
|||
/// <summary>
|
|||
/// Provides class handling for the MouseLeftButtonDown event that
|
|||
/// occurs when the left mouse button is pressed while the mouse pointer
|
|||
/// is over this control.
|
|||
/// </summary>
|
|||
/// <param name="e">The event data. </param>
|
|||
/// <exception cref="System.ArgumentNullException">
|
|||
/// e is a null reference (Nothing in Visual Basic).
|
|||
/// </exception>
|
|||
/// <remarks>
|
|||
/// This method marks the MouseLeftButtonDown event as handled by
|
|||
/// setting the MouseButtonEventArgs.Handled property of the event data
|
|||
/// to true when the button is enabled and its ClickMode is not set to
|
|||
/// Hover. Since this method marks the MouseLeftButtonDown event as
|
|||
/// handled in some situations, you should use the Click event instead
|
|||
/// to detect a button click.
|
|||
/// </remarks>
|
|||
protected override void OnPointerPressed(PointerPressedEventArgs e) |
|||
{ |
|||
base.OnPointerPressed(e); |
|||
|
|||
if (e.MouseButton == MouseButton.Left) |
|||
CalendarDayButtonMouseDown?.Invoke(this, e); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Provides handling for the MouseLeftButtonUp event that occurs when
|
|||
/// the left mouse button is released while the mouse pointer is over
|
|||
/// this control.
|
|||
/// </summary>
|
|||
/// <param name="e">The event data.</param>
|
|||
/// <exception cref="System.ArgumentNullException">
|
|||
/// e is a null reference (Nothing in Visual Basic).
|
|||
/// </exception>
|
|||
/// <remarks>
|
|||
/// This method marks the MouseLeftButtonUp event as handled by setting
|
|||
/// the MouseButtonEventArgs.Handled property of the event data to true
|
|||
/// when the button is enabled and its ClickMode is not set to Hover.
|
|||
/// Since this method marks the MouseLeftButtonUp event as handled in
|
|||
/// some situations, you should use the Click event instead to detect a
|
|||
/// button click.
|
|||
/// </remarks>
|
|||
protected override void OnPointerReleased(PointerReleasedEventArgs e) |
|||
{ |
|||
base.OnPointerReleased(e); |
|||
|
|||
if (e.MouseButton == MouseButton.Left) |
|||
CalendarDayButtonMouseUp?.Invoke(this, e); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// We need to simulate the MouseLeftButtonUp event for the
|
|||
/// CalendarDayButton that stays in Pressed state after MouseCapture is
|
|||
/// released since there is no actual MouseLeftButtonUp event for the
|
|||
/// release.
|
|||
/// </summary>
|
|||
/// <param name="e">Event arguments.</param>
|
|||
internal void SendMouseLeftButtonUp(PointerReleasedEventArgs e) |
|||
{ |
|||
e.Handled = false; |
|||
base.OnPointerReleased(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// (c) Copyright Microsoft Corporation.
|
|||
// This source is subject to the Microsoft Public License (Ms-PL).
|
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|||
// All other rights reserved.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Input; |
|||
using System.Diagnostics; |
|||
|
|||
namespace Avalonia.Controls.Primitives |
|||
{ |
|||
internal static class CalendarExtensions |
|||
{ |
|||
public static void GetMetaKeyState(InputModifiers modifiers, out bool ctrl, out bool shift) |
|||
{ |
|||
ctrl = (modifiers & InputModifiers.Control) == InputModifiers.Control; |
|||
shift = (modifiers & InputModifiers.Shift) == InputModifiers.Shift; |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,155 @@ |
|||
// (c) Copyright Microsoft Corporation.
|
|||
// This source is subject to the Microsoft Public License (Ms-PL).
|
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|||
// All other rights reserved.
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Globalization; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
internal static class DateTimeHelper |
|||
{ |
|||
public static DateTime? AddDays(DateTime time, int days) |
|||
{ |
|||
System.Globalization.Calendar cal = new GregorianCalendar(); |
|||
try |
|||
{ |
|||
return cal.AddDays(time, days); |
|||
} |
|||
catch (ArgumentException) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public static DateTime? AddMonths(DateTime time, int months) |
|||
{ |
|||
System.Globalization.Calendar cal = new GregorianCalendar(); |
|||
try |
|||
{ |
|||
return cal.AddMonths(time, months); |
|||
} |
|||
catch (ArgumentException) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public static DateTime? AddYears(DateTime time, int years) |
|||
{ |
|||
System.Globalization.Calendar cal = new GregorianCalendar(); |
|||
try |
|||
{ |
|||
return cal.AddYears(time, years); |
|||
} |
|||
catch (ArgumentException) |
|||
{ |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public static int CompareDays(DateTime dt1, DateTime dt2) |
|||
{ |
|||
return DateTime.Compare(DiscardTime(dt1).Value, DiscardTime(dt2).Value); |
|||
} |
|||
|
|||
public static int CompareYearMonth(DateTime dt1, DateTime dt2) |
|||
{ |
|||
return (dt1.Year - dt2.Year) * 12 + (dt1.Month - dt2.Month); |
|||
} |
|||
|
|||
public static int DecadeOfDate(DateTime date) |
|||
{ |
|||
return date.Year - (date.Year % 10); |
|||
} |
|||
|
|||
public static DateTime DiscardDayTime(DateTime d) |
|||
{ |
|||
int year = d.Year; |
|||
int month = d.Month; |
|||
DateTime newD = new DateTime(year, month, 1, 0, 0, 0); |
|||
return newD; |
|||
} |
|||
|
|||
public static DateTime? DiscardTime(DateTime? d) |
|||
{ |
|||
if (d == null) |
|||
{ |
|||
return null; |
|||
} |
|||
return d.Value.Date; |
|||
} |
|||
|
|||
public static int EndOfDecade(DateTime date) |
|||
{ |
|||
return DecadeOfDate(date) + 9; |
|||
} |
|||
|
|||
public static DateTimeFormatInfo GetCurrentDateFormat() |
|||
{ |
|||
if (CultureInfo.CurrentCulture.Calendar is GregorianCalendar) |
|||
{ |
|||
return CultureInfo.CurrentCulture.DateTimeFormat; |
|||
} |
|||
else |
|||
{ |
|||
foreach (System.Globalization.Calendar cal in CultureInfo.CurrentCulture.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; |
|||
dtfi.Calendar = cal; |
|||
return dtfi; |
|||
} |
|||
} |
|||
|
|||
// if there are no GregorianCalendars in the OptionalCalendars
|
|||
// list, use the invariant dtfi
|
|||
DateTimeFormatInfo dt = new CultureInfo(CultureInfo.InvariantCulture.Name).DateTimeFormat; |
|||
dt.Calendar = new GregorianCalendar(); |
|||
return dt; |
|||
} |
|||
} |
|||
public static bool InRange(DateTime date, CalendarDateRange range) |
|||
{ |
|||
Debug.Assert(DateTime.Compare(range.Start, range.End) < 1, "The range should start before it ends!"); |
|||
|
|||
if (CompareDays(date, range.Start) > -1 && CompareDays(date, range.End) < 1) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public static string ToYearMonthPatternString(DateTime date) |
|||
{ |
|||
string result = string.Empty; |
|||
DateTimeFormatInfo format = GetCurrentDateFormat(); |
|||
|
|||
if (format != null) |
|||
{ |
|||
result = date.ToString(format.YearMonthPattern, format); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static string ToYearString(DateTime date) |
|||
{ |
|||
string result = string.Empty; |
|||
DateTimeFormatInfo format = GetCurrentDateFormat(); |
|||
|
|||
if (format != null) |
|||
{ |
|||
result = date.Year.ToString(format); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,361 @@ |
|||
// (c) Copyright Microsoft Corporation.
|
|||
// This source is subject to the Microsoft Public License (Ms-PL).
|
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
|
|||
// All other rights reserved.
|
|||
|
|||
using Avalonia.Threading; |
|||
using System; |
|||
using System.Collections.ObjectModel; |
|||
using System.Threading; |
|||
|
|||
namespace Avalonia.Controls.Primitives |
|||
{ |
|||
public sealed class SelectedDatesCollection : ObservableCollection<DateTime> |
|||
{ |
|||
/// <summary>
|
|||
/// Inherited code: Requires comment.
|
|||
/// </summary>
|
|||
private Collection<DateTime> _addedItems; |
|||
|
|||
/// <summary>
|
|||
/// Inherited code: Requires comment.
|
|||
/// </summary>
|
|||
private bool _isCleared; |
|||
|
|||
/// <summary>
|
|||
/// Inherited code: Requires comment.
|
|||
/// </summary>
|
|||
private bool _isRangeAdded; |
|||
|
|||
/// <summary>
|
|||
/// Inherited code: Requires comment.
|
|||
/// </summary>
|
|||
private Calendar _owner; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the
|
|||
/// <see cref="T:Avalonia.Controls.Primitives.SelectedDatesCollection" />
|
|||
/// class.
|
|||
/// </summary>
|
|||
/// <param name="owner">
|
|||
/// The <see cref="T:Avalonia.Controls.Calendar" /> associated
|
|||
/// with this object.
|
|||
/// </param>
|
|||
public SelectedDatesCollection(Calendar owner) |
|||
{ |
|||
_owner = owner; |
|||
_addedItems = new Collection<DateTime>(); |
|||
} |
|||
|
|||
private void InvokeCollectionChanged(System.Collections.IList removedItems, System.Collections.IList addedItems) |
|||
{ |
|||
_owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(null, addedItems, removedItems)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds all the dates in the specified range, which includes the first
|
|||
/// and last dates, to the collection.
|
|||
/// </summary>
|
|||
/// <param name="start">The first date to add to the collection.</param>
|
|||
/// <param name="end">The last date to add to the collection.</param>
|
|||
public void AddRange(DateTime start, DateTime end) |
|||
{ |
|||
DateTime? rangeStart; |
|||
|
|||
// increment parameter specifies if the Days were selected in
|
|||
// Descending order or Ascending order based on this value, we add
|
|||
// the days in the range either in Ascending order or in Descending
|
|||
// order
|
|||
int increment = (DateTime.Compare(end, start) >= 0) ? 1 : -1; |
|||
|
|||
_addedItems.Clear(); |
|||
|
|||
rangeStart = start; |
|||
_isRangeAdded = true; |
|||
|
|||
if (_owner.IsMouseSelection) |
|||
{ |
|||
// In Mouse Selection we allow the user to be able to add
|
|||
// multiple ranges in one action in MultipleRange Mode. In
|
|||
// SingleRange Mode, we only add the first selected range.
|
|||
while (rangeStart.HasValue && DateTime.Compare(end, rangeStart.Value) != -increment) |
|||
{ |
|||
if (Calendar.IsValidDateSelection(_owner, rangeStart)) |
|||
{ |
|||
Add(rangeStart.Value); |
|||
} |
|||
else |
|||
{ |
|||
if (_owner.SelectionMode == CalendarSelectionMode.SingleRange) |
|||
{ |
|||
_owner.HoverEnd = rangeStart.Value.AddDays(-increment); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
rangeStart = DateTimeHelper.AddDays(rangeStart.Value, increment); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// If CalendarSelectionMode.SingleRange and a user
|
|||
// programmatically tries to add multiple ranges, we will throw
|
|||
// away the old range and replace it with the new one. In order
|
|||
// to provide the removed items without an additional event, we
|
|||
// are calling ClearInternal
|
|||
if (_owner.SelectionMode == CalendarSelectionMode.SingleRange && Count > 0) |
|||
{ |
|||
foreach (DateTime item in this) |
|||
{ |
|||
_owner.RemovedItems.Add(item); |
|||
} |
|||
ClearInternal(); |
|||
} |
|||
|
|||
while (rangeStart.HasValue && DateTime.Compare(end, rangeStart.Value) != -increment) |
|||
{ |
|||
Add(rangeStart.Value); |
|||
rangeStart = DateTimeHelper.AddDays(rangeStart.Value, increment); |
|||
} |
|||
} |
|||
|
|||
_owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(null, _addedItems, _owner.RemovedItems)); |
|||
_owner.RemovedItems.Clear(); |
|||
_owner.UpdateMonths(); |
|||
_isRangeAdded = false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes all items from the collection.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void ClearItems() |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
Collection<DateTime> addedItems = new Collection<DateTime>(); |
|||
Collection<DateTime> removedItems = new Collection<DateTime>(); |
|||
|
|||
foreach (DateTime item in this) |
|||
{ |
|||
removedItems.Add(item); |
|||
} |
|||
|
|||
base.ClearItems(); |
|||
|
|||
// The event fires after SelectedDate changes
|
|||
if (_owner.SelectionMode != CalendarSelectionMode.None && _owner.SelectedDate != null) |
|||
{ |
|||
_owner.SelectedDate = null; |
|||
} |
|||
|
|||
if (removedItems.Count != 0) |
|||
{ |
|||
InvokeCollectionChanged(removedItems, addedItems); |
|||
} |
|||
_owner.UpdateMonths(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Inserts an item into the collection at the specified index.
|
|||
/// </summary>
|
|||
/// <param name="index">
|
|||
/// The zero-based index at which item should be inserted.
|
|||
/// </param>
|
|||
/// <param name="item">The object to insert.</param>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void InsertItem(int index, DateTime item) |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
if (!Contains(item)) |
|||
{ |
|||
Collection<DateTime> addedItems = new Collection<DateTime>(); |
|||
|
|||
if (CheckSelectionMode()) |
|||
{ |
|||
if (Calendar.IsValidDateSelection(_owner, item)) |
|||
{ |
|||
// If the Collection is cleared since it is SingleRange
|
|||
// and it had another range set the index to 0
|
|||
if (_isCleared) |
|||
{ |
|||
index = 0; |
|||
_isCleared = false; |
|||
} |
|||
|
|||
base.InsertItem(index, item); |
|||
|
|||
// The event fires after SelectedDate changes
|
|||
if (index == 0 && !(_owner.SelectedDate.HasValue && DateTime.Compare(_owner.SelectedDate.Value, item) == 0)) |
|||
{ |
|||
_owner.SelectedDate = item; |
|||
} |
|||
|
|||
if (!_isRangeAdded) |
|||
{ |
|||
addedItems.Add(item); |
|||
|
|||
InvokeCollectionChanged(_owner.RemovedItems, addedItems); |
|||
_owner.RemovedItems.Clear(); |
|||
int monthDifference = DateTimeHelper.CompareYearMonth(item, _owner.DisplayDateInternal); |
|||
|
|||
if (monthDifference < 2 && monthDifference > -2) |
|||
{ |
|||
_owner.UpdateMonths(); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
_addedItems.Add(item); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
throw new ArgumentOutOfRangeException("SelectedDate value is not valid."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the item at the specified index of the collection.
|
|||
/// </summary>
|
|||
/// <param name="index">
|
|||
/// The zero-based index of the element to remove.
|
|||
/// </param>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void RemoveItem(int index) |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
if (index >= Count) |
|||
{ |
|||
base.RemoveItem(index); |
|||
} |
|||
else |
|||
{ |
|||
Collection<DateTime> addedItems = new Collection<DateTime>(); |
|||
Collection<DateTime> removedItems = new Collection<DateTime>(); |
|||
int monthDifference = DateTimeHelper.CompareYearMonth(this[index], _owner.DisplayDateInternal); |
|||
|
|||
removedItems.Add(this[index]); |
|||
base.RemoveItem(index); |
|||
|
|||
// The event fires after SelectedDate changes
|
|||
if (index == 0) |
|||
{ |
|||
if (Count > 0) |
|||
{ |
|||
_owner.SelectedDate = this[0]; |
|||
} |
|||
else |
|||
{ |
|||
_owner.SelectedDate = null; |
|||
} |
|||
} |
|||
|
|||
InvokeCollectionChanged(removedItems, addedItems); |
|||
|
|||
if (monthDifference < 2 && monthDifference > -2) |
|||
{ |
|||
_owner.UpdateMonths(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Replaces the element at the specified index.
|
|||
/// </summary>
|
|||
/// <param name="index">
|
|||
/// The zero-based index of the element to replace.
|
|||
/// </param>
|
|||
/// <param name="item">
|
|||
/// The new value for the element at the specified index.
|
|||
/// </param>
|
|||
/// <remarks>
|
|||
/// This implementation raises the CollectionChanged event.
|
|||
/// </remarks>
|
|||
protected override void SetItem(int index, DateTime item) |
|||
{ |
|||
EnsureValidThread(); |
|||
|
|||
if (!Contains(item)) |
|||
{ |
|||
Collection<DateTime> addedItems = new Collection<DateTime>(); |
|||
Collection<DateTime> removedItems = new Collection<DateTime>(); |
|||
|
|||
if (index >= Count) |
|||
{ |
|||
base.SetItem(index, item); |
|||
} |
|||
else |
|||
{ |
|||
if (item != null && DateTime.Compare(this[index], item) != 0 && Calendar.IsValidDateSelection(_owner, item)) |
|||
{ |
|||
removedItems.Add(this[index]); |
|||
base.SetItem(index, item); |
|||
addedItems.Add(item); |
|||
|
|||
// The event fires after SelectedDate changes
|
|||
if (index == 0 && !(_owner.SelectedDate.HasValue && DateTime.Compare(_owner.SelectedDate.Value, item) == 0)) |
|||
{ |
|||
_owner.SelectedDate = item; |
|||
} |
|||
InvokeCollectionChanged(removedItems, addedItems); |
|||
|
|||
int monthDifference = DateTimeHelper.CompareYearMonth(item, _owner.DisplayDateInternal); |
|||
|
|||
if (monthDifference < 2 && monthDifference > -2) |
|||
{ |
|||
_owner.UpdateMonths(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
internal void ClearInternal() |
|||
{ |
|||
base.ClearItems(); |
|||
} |
|||
|
|||
private bool CheckSelectionMode() |
|||
{ |
|||
if (_owner.SelectionMode == CalendarSelectionMode.None) |
|||
{ |
|||
throw new InvalidOperationException("The SelectedDate property cannot be set when the selection mode is None."); |
|||
} |
|||
if (_owner.SelectionMode == CalendarSelectionMode.SingleDate && Count > 0) |
|||
{ |
|||
throw new InvalidOperationException("The SelectedDates collection can be changed only in a multiple selection mode. Use the SelectedDate in a single selection mode."); |
|||
} |
|||
|
|||
// if user tries to add an item into the SelectedDates in
|
|||
// SingleRange mode, we throw away the old range and replace it with
|
|||
// the new one in order to provide the removed items without an
|
|||
// additional event, we are calling ClearInternal
|
|||
if (_owner.SelectionMode == CalendarSelectionMode.SingleRange && !_isRangeAdded && Count > 0) |
|||
{ |
|||
foreach (DateTime item in this) |
|||
{ |
|||
_owner.RemovedItems.Add(item); |
|||
} |
|||
ClearInternal(); |
|||
_isCleared = true; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
private void EnsureValidThread() |
|||
{ |
|||
Dispatcher.UIThread.VerifyAccess(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
using System; |
|||
using Avalonia.Controls; |
|||
using Serilog; |
|||
using SerilogLevel = Serilog.Events.LogEventLevel; |
|||
|
|||
namespace Avalonia.Logging.Serilog |
|||
{ |
|||
/// <summary>
|
|||
/// Extension methods for Serilog logging.
|
|||
/// </summary>
|
|||
public static class SerilogExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Logs Avalonia events to the <see cref="System.Diagnostics.Debug"/> sink.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The application class type.</typeparam>
|
|||
/// <param name="builder">The app builder instance.</param>
|
|||
/// <param name="level">The minimum level to log.</param>
|
|||
/// <returns>The app builder instance.</returns>
|
|||
public static T LogToDebug<T>( |
|||
this T builder, |
|||
LogEventLevel level = LogEventLevel.Warning) |
|||
where T : AppBuilderBase<T>, new() |
|||
{ |
|||
SerilogLogger.Initialize(new LoggerConfiguration() |
|||
.MinimumLevel.Is((SerilogLevel)level) |
|||
.WriteTo.Debug(outputTemplate: "{Area}: {Message}") |
|||
.CreateLogger()); |
|||
return builder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Logs Avalonia events to the <see cref="System.Diagnostics.Trace"/> sink.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The application class type.</typeparam>
|
|||
/// <param name="builder">The app builder instance.</param>
|
|||
/// <param name="level">The minimum level to log.</param>
|
|||
/// <returns>The app builder instance.</returns>
|
|||
public static T LogToTrace<T>( |
|||
this T builder, |
|||
LogEventLevel level = LogEventLevel.Warning) |
|||
where T : AppBuilderBase<T>, new() |
|||
{ |
|||
SerilogLogger.Initialize(new LoggerConfiguration() |
|||
.MinimumLevel.Is((SerilogLevel)level) |
|||
.WriteTo.Trace(outputTemplate: "{Area}: {Message}") |
|||
.CreateLogger()); |
|||
return builder; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
<!-- |
|||
// (c) Copyright Microsoft Corporation. |
|||
// This source is subject to the Microsoft Public License (Ms-PL). |
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. |
|||
// All other rights reserved. |
|||
--> |
|||
|
|||
<Styles xmlns="https://github.com/avaloniaui"> |
|||
<Style Selector="Calendar"> |
|||
<!--<Setter Property="Focusable" Value="False" />--> |
|||
<Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}" /> |
|||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderDarkBrush}" /> |
|||
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" /> |
|||
<Setter Property="HeaderBackground" Value="{DynamicResource ThemeAccentBrush2}" /> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<StackPanel Name="Root" |
|||
HorizontalAlignment="Center"> |
|||
|
|||
<CalendarItem Name="CalendarItem" |
|||
Background="{TemplateBinding Background}" |
|||
BorderBrush="{TemplateBinding BorderBrush}" |
|||
BorderThickness="{TemplateBinding BorderThickness}" |
|||
HeaderBackground="{TemplateBinding HeaderBackground}"/> |
|||
|
|||
</StackPanel> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
</Styles> |
|||
@ -0,0 +1,80 @@ |
|||
<!-- |
|||
// (c) Copyright Microsoft Corporation. |
|||
// This source is subject to the Microsoft Public License (Ms-PL). |
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. |
|||
// All other rights reserved. |
|||
--> |
|||
|
|||
<Styles xmlns="https://github.com/avaloniaui"> |
|||
<Style Selector="CalendarButton"> |
|||
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush2}" /> |
|||
<Setter Property="FontSize" Value="{DynamicResource FontSizeSmall}" /> |
|||
<Setter Property="HorizontalContentAlignment" Value="Center" /> |
|||
<Setter Property="VerticalContentAlignment" Value="Center" /> |
|||
<Setter Property="MinWidth" Value="37" /> |
|||
<Setter Property="MinHeight" Value="38" /> |
|||
<Setter Property="Focusable" Value="False"/> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Grid> |
|||
|
|||
<Rectangle Name="SelectedBackground" |
|||
Opacity="0.75" |
|||
Fill="{TemplateBinding Background}"/> |
|||
|
|||
<Rectangle Name="Background" |
|||
Opacity="0.5" |
|||
Fill="{TemplateBinding Background}"/> |
|||
|
|||
<!--Focusable="False"--> |
|||
<ContentControl Name="Content" |
|||
Foreground="#FF333333" |
|||
ContentTemplate="{TemplateBinding ContentTemplate}" |
|||
Content="{TemplateBinding Content}" |
|||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" |
|||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" |
|||
FontSize="{TemplateBinding FontSize}" |
|||
Margin="1,0,1,1"/> |
|||
|
|||
<Rectangle Name="FocusVisual" |
|||
StrokeThickness="1" |
|||
Stroke="{DynamicResource HighlightBrush}" |
|||
IsHitTestVisible="False"/> |
|||
|
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarButton /template/ Rectangle#Background"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarButton:pointerover /template/ Rectangle#Background"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
<Style Selector="CalendarButton:pressed /template/ Rectangle#Background"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarButton /template/ Rectangle#SelectedBackground"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarButton:selected /template/ Rectangle#SelectedBackground"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarButton /template/ ContentControl#Content"> |
|||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}"/> |
|||
</Style> |
|||
<Style Selector="CalendarButton:inactive /template/ ContentControl#Content"> |
|||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLightBrush}"/> |
|||
</Style> |
|||
|
|||
|
|||
<Style Selector="CalendarButton /template/ Rectangle#FocusVisual"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarButton:btnfocused /template/ Rectangle#FocusVisual"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
</Styles> |
|||
@ -0,0 +1,116 @@ |
|||
<!-- |
|||
// (c) Copyright Microsoft Corporation. |
|||
// This source is subject to the Microsoft Public License (Ms-PL). |
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. |
|||
// All other rights reserved. |
|||
--> |
|||
|
|||
<Styles xmlns="https://github.com/avaloniaui"> |
|||
<Style Selector="CalendarDayButton"> |
|||
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush2}" /> |
|||
<Setter Property="FontSize" Value="{DynamicResource FontSizeSmall}" /> |
|||
<Setter Property="HorizontalContentAlignment" Value="Center" /> |
|||
<Setter Property="VerticalContentAlignment" Value="Center" /> |
|||
<Setter Property="MinWidth" Value="5" /> |
|||
<Setter Property="MinHeight" Value="5" /> |
|||
<Setter Property="Focusable" Value="False"/> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Panel Background="Transparent"> |
|||
|
|||
<Rectangle Name="TodayBackground" |
|||
Fill="{DynamicResource HighlightBrush}"/> |
|||
|
|||
<Rectangle Name="SelectedBackground" |
|||
Opacity="0.75" |
|||
Fill="{TemplateBinding Background}"/> |
|||
|
|||
<Rectangle Name="Background" |
|||
Opacity="0.5" |
|||
Fill="{TemplateBinding Background}"/> |
|||
|
|||
<ContentControl Name="Content" |
|||
ContentTemplate="{TemplateBinding ContentTemplate}" |
|||
Content="{TemplateBinding Content}" |
|||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" |
|||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" |
|||
FontSize="{TemplateBinding FontSize}" |
|||
Margin="5,1,5,1"/> |
|||
|
|||
<Path Name="BlackoutVisual" |
|||
Margin="3" |
|||
HorizontalAlignment="Stretch" |
|||
VerticalAlignment="Stretch" |
|||
RenderTransformOrigin="0.5,0.5" |
|||
Fill="#FF000000" |
|||
Stretch="Fill" |
|||
Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z" /> |
|||
|
|||
<Rectangle Name="FocusVisual" |
|||
StrokeThickness="1" |
|||
Stroke="{DynamicResource HighlightBrush}" |
|||
IsHitTestVisible="False"/> |
|||
|
|||
</Panel> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarDayButton /template/ Rectangle#Background"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:pointerover /template/ Rectangle#Background"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:pressed /template/ Rectangle#Background"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarDayButton /template/ Rectangle#SelectedBackground"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:selected /template/ Rectangle#SelectedBackground"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarDayButton /template/ ContentControl#Content"> |
|||
<Setter Property="Opacity" Value="1"/> |
|||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:disabled /template/ Rectangle#Background"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:disabled /template/ ContentControl#Content"> |
|||
<Setter Property="Opacity" Value="0.3"/> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarDayButton /template/ Rectangle#FocusVisual"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:dayfocused /template/ Rectangle#FocusVisual"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarDayButton /template/ Rectangle#TodayBackground"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:today /template/ Rectangle#TodayBackground"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
|
|||
|
|||
<Style Selector="CalendarDayButton:inactive /template/ ContentControl#Content"> |
|||
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLightBrush}"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:today /template/ ContentControl#Content"> |
|||
<Setter Property="Foreground" Value="#FFFFFFFF"/> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarDayButton /template/ Path#BlackoutVisual"> |
|||
<Setter Property="Opacity" Value="0"/> |
|||
</Style> |
|||
<Style Selector="CalendarDayButton:blackout /template/ Path#BlackoutVisual"> |
|||
<Setter Property="Opacity" Value="0.3"/> |
|||
</Style> |
|||
|
|||
</Styles> |
|||
@ -0,0 +1,183 @@ |
|||
<!-- |
|||
// (c) Copyright Microsoft Corporation. |
|||
// This source is subject to the Microsoft Public License (Ms-PL). |
|||
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. |
|||
// All other rights reserved. |
|||
--> |
|||
|
|||
<Styles xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
|||
<Style Selector="CalendarItem"> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Panel> |
|||
<Border BorderThickness="{TemplateBinding BorderThickness}" |
|||
BorderBrush="{TemplateBinding BorderBrush}" |
|||
Background="{TemplateBinding Background}" |
|||
Margin="0,2,0,2" |
|||
CornerRadius="1"> |
|||
|
|||
<Border CornerRadius="1" |
|||
BorderBrush="{DynamicResource ThemeBackgroundBrush}" |
|||
BorderThickness="2"> |
|||
<Grid> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="*" /> |
|||
</Grid.RowDefinitions> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
</Grid.ColumnDefinitions> |
|||
|
|||
<Grid.Styles> |
|||
<Style Selector="Button.CalendarHeader"> |
|||
<Setter Property="Cursor" Value="Hand"/> |
|||
<Setter Property="Background" Value="Transparent"/> |
|||
<Setter Property="BorderThickness" Value="0"/> |
|||
</Style> |
|||
<Style Selector="Button.CalendarHeader:pressed /template/ ContentPresenter"> |
|||
<Setter Property="Background" Value="Transparent"/> |
|||
</Style> |
|||
|
|||
<Style Selector="Button.CalendarNavigation"> |
|||
<Setter Property="Height" Value="20"/> |
|||
<Setter Property="Width" Value="28"/> |
|||
</Style> |
|||
<Style Selector="Button.CalendarNavigation > Path"> |
|||
<Setter Property="Fill" Value="{DynamicResource ThemeForegroundBrush}"/> |
|||
</Style> |
|||
<Style Selector="Button.CalendarNavigation:pointerover > Path"> |
|||
<Setter Property="Fill" Value="{DynamicResource HighlightBrush}"/> |
|||
</Style> |
|||
|
|||
<Style Selector="Button#HeaderButton:pointerover"> |
|||
<Setter Property="Foreground" Value="{DynamicResource HighlightBrush}"/> |
|||
</Style> |
|||
</Grid.Styles> |
|||
|
|||
<Rectangle Grid.ColumnSpan="3" |
|||
Fill="{TemplateBinding HeaderBackground}" |
|||
Stretch="Fill" |
|||
VerticalAlignment="Top" |
|||
Height="22"/> |
|||
|
|||
<Button Name="PreviousButton" |
|||
Classes="CalendarHeader CalendarNavigation" |
|||
IsVisible="False" |
|||
HorizontalAlignment="Left"> |
|||
|
|||
<Path Margin="14,-6,0,0" |
|||
Height="10" |
|||
Width="6" |
|||
VerticalAlignment="Center" |
|||
HorizontalAlignment="Left" |
|||
Stretch="Fill" |
|||
Data="M288.75,232.25 L288.75,240.625 L283,236.625 z" /> |
|||
|
|||
</Button> |
|||
|
|||
<Button Name="HeaderButton" |
|||
Classes="CalendarHeader" |
|||
Grid.Column="1" |
|||
FontWeight="Bold" |
|||
FontSize="10.5" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" |
|||
Padding="1,5,1,9"/> |
|||
|
|||
<Button Name="NextButton" |
|||
Classes="CalendarHeader CalendarNavigation" |
|||
Grid.Column="2" |
|||
IsVisible="False" |
|||
HorizontalAlignment="Right" > |
|||
|
|||
<Path Margin="0,-6,14,0" |
|||
Height="10" |
|||
Width="6" |
|||
Stretch="Fill" |
|||
VerticalAlignment="Center" |
|||
HorizontalAlignment="Right" |
|||
Data="M282.875,231.875 L282.875,240.375 L288.625,236 z" /> |
|||
|
|||
</Button> |
|||
|
|||
<Grid Name="MonthView" |
|||
Grid.Row="1" |
|||
Grid.ColumnSpan="3" |
|||
IsVisible="False" |
|||
Margin="6,-1,6,6"> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
</Grid.RowDefinitions> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
</Grid.ColumnDefinitions> |
|||
</Grid> |
|||
|
|||
<Grid Name="YearView" |
|||
Grid.Row="1" |
|||
Grid.ColumnSpan="3" |
|||
IsVisible="False" |
|||
Margin="6,-3,7,6"> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="Auto" /> |
|||
</Grid.RowDefinitions> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto" /> |
|||
</Grid.ColumnDefinitions> |
|||
</Grid> |
|||
|
|||
</Grid> |
|||
</Border> |
|||
</Border> |
|||
|
|||
|
|||
<Rectangle Name="DisabledVisual" |
|||
Stretch="Fill" |
|||
Fill="#FFFFFFFF" |
|||
Opacity="{DynamicResource ThemeDisabledOpacity}" |
|||
Margin="0,2,0,2" /> |
|||
|
|||
</Panel> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
<Setter Property="DayTitleTemplate"> |
|||
<Template> |
|||
<TextBlock FontWeight="Bold" |
|||
FontSize="9.5" |
|||
Margin="0,4,0,4" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" |
|||
Text="{Binding}" /> |
|||
</Template> |
|||
|
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style Selector="CalendarItem /template/ Rectangle#DisabledVisual"> |
|||
<Setter Property="IsVisible" Value="False"/> |
|||
</Style> |
|||
<Style Selector="CalendarItem:calendardisabled /template/ Rectangle#DisabledVisual"> |
|||
<Setter Property="IsVisible" Value="True"/> |
|||
</Style> |
|||
|
|||
</Styles> |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue