Browse Source

Merge branch 'fixes/textProcessingBugs' of https://github.com/Gillibald/Avalonia into fixes/textProcessingBugs

pull/7746/head
Benedikt Stebner 4 years ago
parent
commit
05836c4bea
  1. 4
      src/Avalonia.Controls/AutoCompleteBox.cs
  2. 2
      src/Avalonia.Controls/ButtonSpinner.cs
  3. 21
      src/Avalonia.Controls/Calendar/Calendar.cs
  4. 5
      src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
  5. 5
      src/Avalonia.Controls/Calendar/CalendarItem.cs
  6. 4
      src/Avalonia.Controls/Chrome/CaptionButtons.cs
  7. 1
      src/Avalonia.Controls/Chrome/TitleBar.cs
  8. 2
      src/Avalonia.Controls/ComboBox.cs
  9. 2
      src/Avalonia.Controls/ContentControl.cs
  10. 9
      src/Avalonia.Controls/DateTimePickers/DatePicker.cs
  11. 20
      src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
  12. 12
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  13. 17
      src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
  14. 2
      src/Avalonia.Controls/ListBox.cs
  15. 1
      src/Avalonia.Controls/MenuItem.cs
  16. 1
      src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
  17. 3
      src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
  18. 4
      src/Avalonia.Controls/Primitives/ScrollBar.cs
  19. 1
      src/Avalonia.Controls/ProgressBar.cs
  20. 3
      src/Avalonia.Controls/ScrollViewer.cs
  21. 3
      src/Avalonia.Controls/Slider.cs
  22. 2
      src/Avalonia.Controls/SplitButton/SplitButton.cs
  23. 1
      src/Avalonia.Controls/SplitView.cs
  24. 2
      src/Avalonia.Controls/TabControl.cs
  25. 1
      src/Avalonia.Controls/TextBox.cs
  26. 2
      src/Avalonia.Controls/ToggleSwitch.cs
  27. 2
      src/Avalonia.Controls/TopLevel.cs
  28. 1
      src/Avalonia.Controls/TreeViewItem.cs
  29. 3
      src/Avalonia.Dialogs/ManagedFileChooser.cs
  30. 2
      src/Avalonia.Visuals/Media/Color.cs
  31. 141
      src/Avalonia.Visuals/Media/HsvColor.cs
  32. 28
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs

4
src/Avalonia.Controls/AutoCompleteBox.cs

@ -252,6 +252,10 @@ namespace Avalonia.Controls
/// drop-down that contains possible matches based on the input in the text
/// box.
/// </summary>
[TemplatePart(ElementPopup, typeof(Popup))]
[TemplatePart(ElementSelector, typeof(SelectingItemsControl))]
[TemplatePart(ElementSelectionAdapter, typeof(ISelectionAdapter))]
[TemplatePart(ElementTextBox, typeof(TextBox))]
[PseudoClasses(":dropdownopen")]
public class AutoCompleteBox : TemplatedControl
{

2
src/Avalonia.Controls/ButtonSpinner.cs

@ -16,6 +16,8 @@ namespace Avalonia.Controls
/// <summary>
/// Represents a spinner control that includes two Buttons.
/// </summary>
[TemplatePart("PART_DecreaseButton", typeof(Button))]
[TemplatePart("PART_IncreaseButton", typeof(Button))]
[PseudoClasses(":left", ":right")]
public class ButtonSpinner : Spinner
{

21
src/Avalonia.Controls/Calendar/Calendar.cs

@ -6,6 +6,7 @@
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Input;
@ -222,6 +223,8 @@ namespace Avalonia.Controls
/// element in XAML.
/// </para>
/// </remarks>
[TemplatePart(PART_ElementMonth, typeof(CalendarItem))]
[TemplatePart(PART_ElementRoot, typeof(Panel))]
public class Calendar : TemplatedControl
{
internal const int RowsPerMonth = 7;
@ -261,6 +264,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register<Calendar, DayOfWeek>(
nameof(FirstDayOfWeek),
defaultValue: DateTimeHelper.GetCurrentDateFormat().FirstDayOfWeek);
/// <summary>
/// Gets or sets the day that is considered the beginning of the week.
/// </summary>
@ -273,6 +277,7 @@ namespace Avalonia.Controls
get { return GetValue(FirstDayOfWeekProperty); }
set { SetValue(FirstDayOfWeekProperty, value); }
}
/// <summary>
/// FirstDayOfWeekProperty property changed handler.
/// </summary>
@ -289,6 +294,7 @@ namespace Avalonia.Controls
throw new ArgumentOutOfRangeException("d", "Invalid DayOfWeek");
}
}
/// <summary>
/// Inherited code: Requires comment.
/// </summary>
@ -311,6 +317,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register<Calendar, bool>(
nameof(IsTodayHighlighted),
defaultValue: true);
/// <summary>
/// Gets or sets a value indicating whether the current date is
/// highlighted.
@ -324,6 +331,7 @@ namespace Avalonia.Controls
get { return GetValue(IsTodayHighlightedProperty); }
set { SetValue(IsTodayHighlightedProperty, value); }
}
/// <summary>
/// IsTodayHighlightedProperty property changed handler.
/// </summary>
@ -343,6 +351,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty<IBrush> HeaderBackgroundProperty =
AvaloniaProperty.Register<Calendar, IBrush>(nameof(HeaderBackground));
public IBrush HeaderBackground
{
get { return GetValue(HeaderBackgroundProperty); }
@ -367,6 +376,7 @@ namespace Avalonia.Controls
get { return GetValue(DisplayModeProperty); }
set { SetValue(DisplayModeProperty, value); }
}
/// <summary>
/// DisplayModeProperty property changed handler.
/// </summary>
@ -424,6 +434,7 @@ namespace Avalonia.Controls
|| mode == CalendarMode.Year
|| mode == CalendarMode.Decade;
}
private void OnDisplayModeChanged(CalendarModeChangedEventArgs args)
{
DisplayModeChanged?.Invoke(this, args);
@ -433,6 +444,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register<Calendar, CalendarSelectionMode>(
nameof(SelectionMode),
defaultValue: CalendarSelectionMode.SingleDate);
/// <summary>
/// Gets or sets a value that indicates what kind of selections are
/// allowed.
@ -457,6 +469,7 @@ namespace Avalonia.Controls
get { return GetValue(SelectionModeProperty); }
set { SetValue(SelectionModeProperty, value); }
}
private void OnSelectionModeChanged(AvaloniaPropertyChangedEventArgs e)
{
if (IsValidSelectionMode(e.NewValue!))
@ -471,6 +484,7 @@ namespace Avalonia.Controls
throw new ArgumentOutOfRangeException("d", "Invalid SelectionMode");
}
}
/// <summary>
/// Inherited code: Requires comment.
/// </summary>
@ -492,6 +506,7 @@ namespace Avalonia.Controls
o => o.SelectedDate,
(o, v) => o.SelectedDate = v,
defaultBindingMode: BindingMode.TwoWay);
/// <summary>
/// Gets or sets the currently selected date.
/// </summary>
@ -720,6 +735,7 @@ namespace Avalonia.Controls
o => o.DisplayDate,
(o, v) => o.DisplayDate = v,
defaultBindingMode: BindingMode.TwoWay);
/// <summary>
/// Gets or sets the date to display.
/// </summary>
@ -1973,6 +1989,7 @@ namespace Avalonia.Controls
}
}
}
private void Calendar_KeyUp(KeyEventArgs e)
{
if (!e.Handled && (e.Key == Key.LeftShift || e.Key == Key.RightShift))
@ -1980,6 +1997,7 @@ namespace Avalonia.Controls
ProcessShiftKeyUp();
}
}
internal void ProcessShiftKeyUp()
{
if (_isShiftPressed && (SelectionMode == CalendarSelectionMode.SingleRange || SelectionMode == CalendarSelectionMode.MultipleRange))
@ -2028,6 +2046,7 @@ namespace Avalonia.Controls
}
}
}
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
@ -2054,6 +2073,7 @@ namespace Avalonia.Controls
}
}
}
/// <summary>
/// Called when the IsEnabled property changes.
/// </summary>
@ -2098,6 +2118,7 @@ namespace Avalonia.Controls
private const string PART_ElementRoot = "Root";
private const string PART_ElementMonth = "CalendarItem";
/// <summary>
/// Builds the visual tree for the
/// <see cref="T:System.Windows.Controls.Calendar" /> when a new

5
src/Avalonia.Controls/Calendar/CalendarDatePicker.cs

@ -7,6 +7,7 @@ using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Input;
@ -116,6 +117,10 @@ namespace Avalonia.Controls
Custom = 2
}
[TemplatePart(ElementButton, typeof(Button))]
[TemplatePart(ElementCalendar, typeof(Calendar))]
[TemplatePart(ElementPopup, typeof(Popup))]
[TemplatePart(ElementTextBox, typeof(TextBox))]
public class CalendarDatePicker : TemplatedControl
{
private const string ElementTextBox = "PART_TextBox";

5
src/Avalonia.Controls/Calendar/CalendarItem.cs

@ -19,6 +19,11 @@ namespace Avalonia.Controls.Primitives
/// Represents the currently displayed month or year on a
/// <see cref="T:Avalonia.Controls.Calendar" />.
/// </summary>
[TemplatePart(PART_ElementHeaderButton, typeof(Button))]
[TemplatePart(PART_ElementMonthView, typeof(Grid))]
[TemplatePart(PART_ElementNextButton, typeof(Button))]
[TemplatePart(PART_ElementPreviousButton, typeof(Button))]
[TemplatePart(PART_ElementYearView, typeof(Grid))]
[PseudoClasses(":calendardisabled")]
public sealed class CalendarItem : TemplatedControl
{

4
src/Avalonia.Controls/Chrome/CaptionButtons.cs

@ -8,6 +8,10 @@ namespace Avalonia.Controls.Chrome
/// <summary>
/// Draws window minimize / maximize / close buttons in a <see cref="TitleBar"/> when managed client decorations are enabled.
/// </summary>
[TemplatePart("PART_CloseButton", typeof(Panel))]
[TemplatePart("PART_RestoreButton", typeof(Panel))]
[TemplatePart("PART_MinimiseButton", typeof(Panel))]
[TemplatePart("PART_FullScreenButton", typeof(Panel))]
[PseudoClasses(":minimized", ":normal", ":maximized", ":fullscreen")]
public class CaptionButtons : TemplatedControl
{

1
src/Avalonia.Controls/Chrome/TitleBar.cs

@ -8,6 +8,7 @@ namespace Avalonia.Controls.Chrome
/// <summary>
/// Draws a titlebar when managed client decorations are enabled.
/// </summary>
[TemplatePart("PART_CaptionButtons", typeof(CaptionButtons))]
[PseudoClasses(":minimized", ":normal", ":maximized", ":fullscreen")]
public class TitleBar : TemplatedControl
{

2
src/Avalonia.Controls/ComboBox.cs

@ -13,12 +13,14 @@ using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.VisualTree;
using Avalonia.Controls.Metadata;
namespace Avalonia.Controls
{
/// <summary>
/// A drop-down list control.
/// </summary>
[TemplatePart("PART_Popup", typeof(Popup))]
public class ComboBox : SelectingItemsControl
{
/// <summary>

2
src/Avalonia.Controls/ContentControl.cs

@ -1,4 +1,5 @@
using Avalonia.Collections;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Mixins;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
@ -12,6 +13,7 @@ namespace Avalonia.Controls
/// <summary>
/// Displays <see cref="Content"/> according to a <see cref="FuncDataTemplate"/>.
/// </summary>
[TemplatePart("PART_ContentPresenter", typeof(IContentPresenter))]
public class ContentControl : TemplatedControl, IContentControl, IContentPresenterHost
{
/// <summary>

9
src/Avalonia.Controls/DateTimePickers/DatePicker.cs

@ -14,6 +14,15 @@ namespace Avalonia.Controls
/// <summary>
/// A control to allow the user to select a date
/// </summary>
[TemplatePart("ButtonContentGrid", typeof(Grid))]
[TemplatePart("DayText", typeof(TextBlock))]
[TemplatePart("FirstSpacer", typeof(Rectangle))]
[TemplatePart("FlyoutButton", typeof(Button))]
[TemplatePart("MonthText", typeof(TextBlock))]
[TemplatePart("PickerPresenter", typeof(DatePickerPresenter))]
[TemplatePart("Popup", typeof(Popup))]
[TemplatePart("SecondSpacer", typeof(Rectangle))]
[TemplatePart("YearText", typeof(TextBlock))]
[PseudoClasses(":hasnodate")]
public class DatePicker : TemplatedControl
{

20
src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs

@ -1,4 +1,5 @@
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Interactivity;
@ -12,6 +13,23 @@ namespace Avalonia.Controls
/// Defines the presenter used for selecting a date for a
/// <see cref="DatePicker"/>
/// </summary>
[TemplatePart("AcceptButton", typeof(Button))]
[TemplatePart("DayDownButton", typeof(RepeatButton))]
[TemplatePart("DayHost", typeof(Panel))]
[TemplatePart("DaySelector", typeof(DateTimePickerPanel))]
[TemplatePart("DayUpButton", typeof(RepeatButton))]
[TemplatePart("DismissButton", typeof(Button))]
[TemplatePart("FirstSpacer", typeof(Rectangle))]
[TemplatePart("MonthDownButton", typeof(RepeatButton))]
[TemplatePart("MonthHost", typeof(Panel))]
[TemplatePart("MonthSelector", typeof(DateTimePickerPanel))]
[TemplatePart("MonthUpButton", typeof(RepeatButton))]
[TemplatePart("PickerContainer", typeof(Grid))]
[TemplatePart("SecondSpacer", typeof(Rectangle))]
[TemplatePart("YearDownButton", typeof(RepeatButton))]
[TemplatePart("YearHost", typeof(Panel))]
[TemplatePart("YearSelector", typeof(DateTimePickerPanel))]
[TemplatePart("YearUpButton", typeof(RepeatButton))]
public class DatePickerPresenter : PickerPresenterBase
{
/// <summary>

12
src/Avalonia.Controls/DateTimePickers/TimePicker.cs

@ -12,6 +12,18 @@ namespace Avalonia.Controls
/// <summary>
/// A control to allow the user to select a time.
/// </summary>
[TemplatePart("FirstColumnDivider", typeof(Rectangle))]
[TemplatePart("FirstPickerHost", typeof(Border))]
[TemplatePart("FlyoutButton", typeof(Button))]
[TemplatePart("FlyoutButtonContentGrid", typeof(Grid))]
[TemplatePart("HourTextBlock", typeof(TextBlock))]
[TemplatePart("MinuteTextBlock", typeof(TextBlock))]
[TemplatePart("PeriodTextBlock", typeof(TextBlock))]
[TemplatePart("PickerPresenter", typeof(TimePickerPresenter))]
[TemplatePart("Popup", typeof(Popup))]
[TemplatePart("SecondColumnDivider", typeof(Rectangle))]
[TemplatePart("SecondPickerHost", typeof(Border))]
[TemplatePart("ThirdPickerHost", typeof(Border))]
[PseudoClasses(":hasnotime")]
public class TimePicker : TemplatedControl
{

17
src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs

@ -1,4 +1,5 @@
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Interactivity;
@ -10,6 +11,20 @@ namespace Avalonia.Controls
/// Defines the presenter used for selecting a time. Intended for use with
/// <see cref="TimePicker"/> but can be used independently
/// </summary>
[TemplatePart("AcceptButton", typeof(Button))]
[TemplatePart("DismissButton", typeof(Button))]
[TemplatePart("HourDownButton", typeof(RepeatButton))]
[TemplatePart("HourSelector", typeof(DateTimePickerPanel))]
[TemplatePart("HourUpButton", typeof(RepeatButton))]
[TemplatePart("MinuteDownButton", typeof(RepeatButton))]
[TemplatePart("MinuteSelector", typeof(DateTimePickerPanel))]
[TemplatePart("MinuteUpButton", typeof(RepeatButton))]
[TemplatePart("PeriodDownButton", typeof(RepeatButton))]
[TemplatePart("PeriodHost", typeof(Panel))]
[TemplatePart("PeriodSelector", typeof(DateTimePickerPanel))]
[TemplatePart("PeriodUpButton", typeof(RepeatButton))]
[TemplatePart("PickerContainer", typeof(Grid))]
[TemplatePart("SecondSpacer", typeof(Rectangle))]
public class TimePickerPresenter : PickerPresenterBase
{
/// <summary>

2
src/Avalonia.Controls/ListBox.cs

@ -1,5 +1,6 @@
using System.Collections;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Selection;
@ -12,6 +13,7 @@ namespace Avalonia.Controls
/// <summary>
/// An <see cref="ItemsControl"/> in which individual items can be selected.
/// </summary>
[TemplatePart("PART_ScrollViewer", typeof(IScrollable))]
public class ListBox : SelectingItemsControl
{
/// <summary>

1
src/Avalonia.Controls/MenuItem.cs

@ -20,6 +20,7 @@ namespace Avalonia.Controls
/// <summary>
/// A menu item control.
/// </summary>
[TemplatePart("PART_Popup", typeof(Popup))]
[PseudoClasses(":separator", ":icon", ":open", ":pressed", ":selected")]
public class MenuItem : HeaderedSelectingItemsControl, IMenuItem, ISelectable, ICommandSource
{

1
src/Avalonia.Controls/Notifications/WindowNotificationManager.cs

@ -14,6 +14,7 @@ namespace Avalonia.Controls.Notifications
/// <summary>
/// An <see cref="INotificationManager"/> that displays notifications in a <see cref="Window"/>.
/// </summary>
[TemplatePart("PART_Items", typeof(Panel))]
[PseudoClasses(":topleft", ":topright", ":bottomleft", ":bottomright")]
public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager, ICustomSimpleHitTest
{

3
src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs

@ -2,6 +2,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Input;
@ -15,6 +16,8 @@ namespace Avalonia.Controls
/// <summary>
/// Control that represents a TextBox with button spinners that allow incrementing and decrementing numeric values.
/// </summary>
[TemplatePart("PART_Spinner", typeof(Spinner))]
[TemplatePart("PART_TextBox", typeof(TextBox))]
public class NumericUpDown : TemplatedControl
{
/// <summary>

4
src/Avalonia.Controls/Primitives/ScrollBar.cs

@ -22,6 +22,10 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// A scrollbar control.
/// </summary>
[TemplatePart("PART_LineDownButton", typeof(Button))]
[TemplatePart("PART_LineUpButton", typeof(Button))]
[TemplatePart("PART_PageDownButton", typeof(Button))]
[TemplatePart("PART_PageUpButton", typeof(Button))]
[PseudoClasses(":vertical", ":horizontal")]
public class ScrollBar : RangeBase
{

1
src/Avalonia.Controls/ProgressBar.cs

@ -10,6 +10,7 @@ namespace Avalonia.Controls
/// <summary>
/// A control used to indicate the progress of an operation.
/// </summary>
[TemplatePart("PART_Indicator", typeof(Border))]
[PseudoClasses(":vertical", ":horizontal", ":indeterminate")]
public class ProgressBar : RangeBase
{

3
src/Avalonia.Controls/ScrollViewer.cs

@ -1,6 +1,7 @@
using System;
using System.Reactive.Linq;
using Avalonia.Automation.Peers;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
@ -11,6 +12,8 @@ namespace Avalonia.Controls
/// <summary>
/// A control which scrolls its content if the content is bigger than the space available.
/// </summary>
[TemplatePart("PART_HorizontalScrollBar", typeof(ScrollBar))]
[TemplatePart("PART_VerticalScrollBar", typeof(ScrollBar))]
public class ScrollViewer : ContentControl, IScrollable, IScrollAnchorProvider
{
/// <summary>

3
src/Avalonia.Controls/Slider.cs

@ -42,6 +42,9 @@ namespace Avalonia.Controls
/// <summary>
/// A control that lets the user select from a range of values by moving a Thumb control along a Track.
/// </summary>
[TemplatePart("PART_DecreaseButton", typeof(Button))]
[TemplatePart("PART_IncreaseButton", typeof(Button))]
[TemplatePart("PART_Track", typeof(Track))]
[PseudoClasses(":vertical", ":horizontal", ":pressed")]
public class Slider : RangeBase
{

2
src/Avalonia.Controls/SplitButton/SplitButton.cs

@ -13,6 +13,8 @@ namespace Avalonia.Controls
/// A button with primary and secondary parts that can each be pressed separately.
/// The primary part behaves like a <see cref="Button"/> and the secondary part opens a flyout.
/// </summary>
[TemplatePart("PART_PrimaryButton", typeof(Button))]
[TemplatePart("PART_SecondaryButton", typeof(Button))]
[PseudoClasses(pcFlyoutOpen, pcPressed)]
public class SplitButton : ContentControl, ICommandSource
{

1
src/Avalonia.Controls/SplitView.cs

@ -77,6 +77,7 @@ namespace Avalonia.Controls
/// <summary>
/// A control with two views: A collapsible pane and an area for content
/// </summary>
[TemplatePart("PART_PaneRoot", typeof(Panel))]
[PseudoClasses(":open", ":closed")]
[PseudoClasses(":compactoverlay", ":compactinline", ":overlay", ":inline")]
[PseudoClasses(":left", ":right")]

2
src/Avalonia.Controls/TabControl.cs

@ -11,12 +11,14 @@ using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.VisualTree;
using Avalonia.Automation;
using Avalonia.Controls.Metadata;
namespace Avalonia.Controls
{
/// <summary>
/// A tab control that displays a tab strip along with the content of the selected tab.
/// </summary>
[TemplatePart("PART_ItemsPresenter", typeof(ItemsPresenter))]
public class TabControl : SelectingItemsControl, IContentPresenterHost
{
/// <summary>

1
src/Avalonia.Controls/TextBox.cs

@ -23,6 +23,7 @@ namespace Avalonia.Controls
/// <summary>
/// Represents a control that can be used to display or edit unformatted text.
/// </summary>
[TemplatePart("PART_TextPresenter", typeof(TextPresenter))]
[PseudoClasses(":empty")]
public class TextBox : TemplatedControl, UndoRedoHelper<TextBox.UndoRedoState>.IUndoRedoHost
{

2
src/Avalonia.Controls/ToggleSwitch.cs

@ -9,6 +9,8 @@ namespace Avalonia.Controls
/// <summary>
/// A Toggle Switch control.
/// </summary>
[TemplatePart("MovingKnobs", typeof(Panel))]
[TemplatePart("SwitchKnob", typeof(Panel))]
[PseudoClasses(":dragging")]
public class ToggleSwitch : ToggleButton
{

2
src/Avalonia.Controls/TopLevel.cs

@ -1,5 +1,6 @@
using System;
using System.Reactive.Linq;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
@ -26,6 +27,7 @@ namespace Avalonia.Controls
/// It handles scheduling layout, styling and rendering as well as
/// tracking the widget's <see cref="ClientSize"/>.
/// </remarks>
[TemplatePart("PART_TransparencyFallback", typeof(Border))]
public abstract class TopLevel : ContentControl,
IInputRoot,
ILayoutRoot,

1
src/Avalonia.Controls/TreeViewItem.cs

@ -12,6 +12,7 @@ namespace Avalonia.Controls
/// <summary>
/// An item in a <see cref="TreeView"/>.
/// </summary>
[TemplatePart("PART_Header", typeof(IControl))]
[PseudoClasses(":pressed", ":selected")]
public class TreeViewItem : HeaderedItemsControl, ISelectable
{

3
src/Avalonia.Dialogs/ManagedFileChooser.cs

@ -2,6 +2,7 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
@ -9,6 +10,8 @@ using Avalonia.LogicalTree;
namespace Avalonia.Dialogs
{
[TemplatePart("QuickLinks", typeof(Control))]
[TemplatePart("Files", typeof(ListBox))]
public class ManagedFileChooser : TemplatedControl
{
private Control _quickLinksRoot;

2
src/Avalonia.Visuals/Media/Color.cs

@ -258,7 +258,7 @@ namespace Avalonia.Media
public override string ToString()
{
uint rgb = ToUint32();
return KnownColors.GetKnownColorName(rgb) ?? $"#{rgb:x8}";
return KnownColors.GetKnownColorName(rgb) ?? $"#{rgb.ToString("x8", CultureInfo.InvariantCulture)}";
}
/// <summary>

141
src/Avalonia.Visuals/Media/HsvColor.cs

@ -4,6 +4,8 @@
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
using System;
using System.Globalization;
using System.Text;
using Avalonia.Utilities;
namespace Avalonia.Media
@ -20,7 +22,8 @@ namespace Avalonia.Media
/// Initializes a new instance of the <see cref="HsvColor"/> struct.
/// </summary>
/// <param name="alpha">The Alpha (transparency) channel value in the range from 0..1.</param>
/// <param name="hue">The Hue channel value in the range from 0..360.</param>
/// <param name="hue">The Hue channel value in the range from 0..360.
/// Note that 360 is equivalent to 0 and will be adjusted automatically.</param>
/// <param name="saturation">The Saturation channel value in the range from 0..1.</param>
/// <param name="value">The Value channel value in the range from 0..1.</param>
public HsvColor(
@ -33,6 +36,12 @@ namespace Avalonia.Media
H = MathUtilities.Clamp(hue, 0.0, 360.0);
S = MathUtilities.Clamp(saturation, 0.0, 1.0);
V = MathUtilities.Clamp(value, 0.0, 1.0);
// The maximum value of Hue is technically 360 minus epsilon (just below 360).
// This is because, in a color circle, 360 degrees is equivalent to 0 degrees.
// However, that is too tricky to work with in code and isn't as intuitive.
// Therefore, since 360 == 0, just wrap 360 if needed back to 0.
H = (H == 360.0 ? 0 : H);
}
/// <summary>
@ -43,7 +52,8 @@ namespace Avalonia.Media
/// Whether or not the channel values are in the correct ranges must be known.
/// </remarks>
/// <param name="alpha">The Alpha (transparency) channel value in the range from 0..1.</param>
/// <param name="hue">The Hue channel value in the range from 0..360.</param>
/// <param name="hue">The Hue channel value in the range from 0..360.
/// Note that 360 is equivalent to 0 and will be adjusted automatically.</param>
/// <param name="saturation">The Saturation channel value in the range from 0..1.</param>
/// <param name="value">The Value channel value in the range from 0..1.</param>
/// <param name="clampValues">Whether to clamp channel values to their required ranges.</param>
@ -60,6 +70,9 @@ namespace Avalonia.Media
H = MathUtilities.Clamp(hue, 0.0, 360.0);
S = MathUtilities.Clamp(saturation, 0.0, 1.0);
V = MathUtilities.Clamp(value, 0.0, 1.0);
// See comments in constructor above
H = (H == 360.0 ? 0 : H);
}
else
{
@ -91,6 +104,7 @@ namespace Avalonia.Media
/// <summary>
/// Gets the Hue channel value in the range from 0..360.
/// Note that 360 is equivalent to 0 and will be adjusted automatically.
/// </summary>
public double H { get; }
@ -155,6 +169,129 @@ namespace Avalonia.Media
return HsvColor.ToRgb(H, S, V, A);
}
/// <inheritdoc/>
public override string ToString()
{
var sb = new StringBuilder();
// Use a format similar to HSL in HTML/CSS "hsla(0, 100%, 50%, 0.5)"
//
// However:
// - To ensure precision is never lost, allow decimal places
// - To maintain numerical consistency do not use percent
//
// Example:
//
// hsva(hue, saturation, value, alpha)
// hsva(230, 1.0, 0.5, 1.0)
//
// Where:
//
// hue : double from 0 to 360
// saturation : double from 0 to 1
// (HTML uses a percentage)
// value : double from 0 to 1
// (HTML uses a percentage)
// alpha : double from 0 to 1
// (HTML does not use a percentage for alpha)
sb.Append("hsva(");
sb.Append(H.ToString(CultureInfo.InvariantCulture));
sb.Append(", ");
sb.Append(S.ToString(CultureInfo.InvariantCulture));
sb.Append(", ");
sb.Append(V.ToString(CultureInfo.InvariantCulture));
sb.Append(", ");
sb.Append(A.ToString(CultureInfo.InvariantCulture));
sb.Append(')');
return sb.ToString();
}
/// <summary>
/// Parses an HSV color string.
/// </summary>
/// <param name="s">The HSV color string to parse.</param>
/// <returns>The parsed <see cref="HsvColor"/>.</returns>
public static HsvColor Parse(string s)
{
if (s is null)
{
throw new ArgumentNullException(nameof(s));
}
if (TryParse(s, out HsvColor hsvColor))
{
return hsvColor;
}
throw new FormatException($"Invalid HSV color string: '{s}'.");
}
/// <summary>
/// Parses an HSV color string.
/// </summary>
/// <param name="s">The HSV color string to parse.</param>
/// <param name="hsvColor">The parsed <see cref="HsvColor"/>.</param>
/// <returns>True if parsing was successful; otherwise, false.</returns>
public static bool TryParse(string s, out HsvColor hsvColor)
{
hsvColor = default;
if (s is null)
{
return false;
}
string workingString = s.Trim();
if (workingString.Length == 0 ||
workingString.IndexOf(",", StringComparison.Ordinal) < 0)
{
return false;
}
if (workingString.Length > 6 &&
workingString.StartsWith("hsva(", StringComparison.OrdinalIgnoreCase) &&
workingString.EndsWith(")", StringComparison.Ordinal))
{
workingString = workingString.Substring(5, workingString.Length - 6);
}
if (workingString.Length > 5 &&
workingString.StartsWith("hsv(", StringComparison.OrdinalIgnoreCase) &&
workingString.EndsWith(")", StringComparison.Ordinal))
{
workingString = workingString.Substring(4, workingString.Length - 5);
}
string[] components = workingString.Split(',');
if (components.Length == 3) // HSV
{
if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
double.TryParse(components[1], NumberStyles.Number, CultureInfo.InvariantCulture, out double saturation) &&
double.TryParse(components[2], NumberStyles.Number, CultureInfo.InvariantCulture, out double value))
{
hsvColor = new HsvColor(1.0, hue, saturation, value);
return true;
}
}
else if (components.Length == 4) // HSVA
{
if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
double.TryParse(components[1], NumberStyles.Number, CultureInfo.InvariantCulture, out double saturation) &&
double.TryParse(components[2], NumberStyles.Number, CultureInfo.InvariantCulture, out double value) &&
double.TryParse(components[3], NumberStyles.Number, CultureInfo.InvariantCulture, out double alpha))
{
hsvColor = new HsvColor(alpha, hue, saturation, value);
return true;
}
}
return false;
}
/// <summary>
/// Creates a new <see cref="HsvColor"/> from individual color channel values.
/// </summary>

28
src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs

@ -1,7 +1,9 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using static Avalonia.LinuxFramebuffer.NativeUnsafeMethods;
using static Avalonia.LinuxFramebuffer.Output.LibDrm;
@ -142,10 +144,28 @@ namespace Avalonia.LinuxFramebuffer.Output
public int Fd { get; private set; }
public DrmCard(string path = null)
{
path = path ?? "/dev/dri/card0";
Fd = open(path, 2, 0);
if (Fd == -1)
throw new Win32Exception("Couldn't open " + path);
if(path == null)
{
var files = Directory.GetFiles("/dev/dri/");
foreach(var file in files)
{
var match = Regex.Match(file, "card[0-9]+");
if(match.Success)
{
Fd = open(file, 2, 0);
if(Fd != -1) break;
}
}
if(Fd == -1) throw new Win32Exception("Couldn't open /dev/dri/card[0-9]+");
}
else
{
Fd = open(path, 2, 0);
if(Fd != -1) throw new Win32Exception($"Couldn't open {path}");
}
}
public DrmResources GetResources() => new DrmResources(Fd);

Loading…
Cancel
Save