Add project files.
This commit is contained in:
19
Examples/Nodify.Shared/BindingProxy.cs
Normal file
19
Examples/Nodify.Shared/BindingProxy.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class BindingProxy : Freezable
|
||||
{
|
||||
public static readonly DependencyProperty DataContextProperty =
|
||||
DependencyProperty.Register(nameof(DataContext), typeof(object), typeof(BindingProxy), new UIPropertyMetadata(default(object)));
|
||||
|
||||
public object DataContext
|
||||
{
|
||||
get => GetValue(DataContextProperty);
|
||||
set => SetValue(DataContextProperty, value);
|
||||
}
|
||||
|
||||
protected override Freezable CreateInstanceCore()
|
||||
=> new BindingProxy();
|
||||
}
|
||||
}
|
||||
19
Examples/Nodify.Shared/BoxValue.cs
Normal file
19
Examples/Nodify.Shared/BoxValue.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace Nodify.Shared
|
||||
{
|
||||
public static class BoxValue
|
||||
{
|
||||
public static readonly object Point = default(Point);
|
||||
public static readonly object Size = default(Size);
|
||||
public static readonly object Rect = default(Rect);
|
||||
public static readonly object False = false;
|
||||
public static readonly object True = true;
|
||||
public static readonly object DoubleHalf = 0.5d;
|
||||
public static readonly object Double0 = 0d;
|
||||
public static readonly object Double1 = 1d;
|
||||
public static readonly object Double2 = 2d;
|
||||
public static readonly object Int0 = 0;
|
||||
public static readonly object Int1 = 1;
|
||||
}
|
||||
}
|
||||
179
Examples/Nodify.Shared/Controls/EditableTextBlock.cs
Normal file
179
Examples/Nodify.Shared/Controls/EditableTextBlock.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
using Nodify.Shared;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
[TemplatePart(Name = ElementTextBox, Type = typeof(TextBox))]
|
||||
public class EditableTextBlock : Control
|
||||
{
|
||||
private const string ElementTextBox = "PART_TextBox";
|
||||
|
||||
public static readonly DependencyProperty IsEditingProperty = DependencyProperty.Register(nameof(IsEditing), typeof(bool), typeof(EditableTextBlock), new FrameworkPropertyMetadata(BoxValue.False, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsEditingChanged, CoerceIsEditing));
|
||||
public static readonly DependencyProperty IsEditableProperty = DependencyProperty.Register(nameof(IsEditable), typeof(bool), typeof(EditableTextBlock), new FrameworkPropertyMetadata(BoxValue.True));
|
||||
public static readonly DependencyProperty TextProperty = TextBlock.TextProperty.AddOwner(typeof(EditableTextBlock), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
||||
public static readonly DependencyProperty AcceptsReturnProperty = TextBoxBase.AcceptsReturnProperty.AddOwner(typeof(EditableTextBlock), new FrameworkPropertyMetadata(BoxValue.False));
|
||||
public static readonly DependencyProperty TextWrappingProperty = TextBlock.TextWrappingProperty.AddOwner(typeof(EditableTextBlock), new FrameworkPropertyMetadata(TextWrapping.Wrap));
|
||||
public static readonly DependencyProperty TextTrimmingProperty = TextBlock.TextTrimmingProperty.AddOwner(typeof(EditableTextBlock), new FrameworkPropertyMetadata(TextTrimming.CharacterEllipsis));
|
||||
public static readonly DependencyProperty MinLinesProperty = TextBox.MinLinesProperty.AddOwner(typeof(EditableTextBlock));
|
||||
public static readonly DependencyProperty MaxLinesProperty = TextBox.MaxLinesProperty.AddOwner(typeof(EditableTextBlock));
|
||||
public static readonly DependencyProperty MaxLengthProperty = TextBox.MaxLengthProperty.AddOwner(typeof(EditableTextBlock));
|
||||
|
||||
private static void OnIsEditingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { }
|
||||
|
||||
private static object CoerceIsEditing(DependencyObject d, object value)
|
||||
{
|
||||
if (!((EditableTextBlock)d).IsEditable)
|
||||
{
|
||||
return BoxValue.False;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public bool IsEditing
|
||||
{
|
||||
get => (bool)GetValue(IsEditingProperty);
|
||||
set => SetValue(IsEditingProperty, value);
|
||||
}
|
||||
|
||||
public bool IsEditable
|
||||
{
|
||||
get => (bool)GetValue(IsEditableProperty);
|
||||
set => SetValue(IsEditableProperty, value);
|
||||
}
|
||||
|
||||
public bool AcceptsReturn
|
||||
{
|
||||
get => (bool)GetValue(AcceptsReturnProperty);
|
||||
set => SetValue(AcceptsReturnProperty, value);
|
||||
}
|
||||
|
||||
public int MaxLength
|
||||
{
|
||||
get => (int)GetValue(MaxLengthProperty);
|
||||
set => SetValue(MaxLengthProperty, value);
|
||||
}
|
||||
|
||||
public int MinLines
|
||||
{
|
||||
get => (int)GetValue(MinLinesProperty);
|
||||
set => SetValue(MaxLinesProperty, value);
|
||||
}
|
||||
|
||||
public int MaxLines
|
||||
{
|
||||
get => (int)GetValue(MaxLinesProperty);
|
||||
set => SetValue(MaxLinesProperty, value);
|
||||
}
|
||||
|
||||
public TextWrapping TextWrapping
|
||||
{
|
||||
get => (TextWrapping)GetValue(TextWrappingProperty);
|
||||
set => SetValue(TextWrappingProperty, value);
|
||||
}
|
||||
|
||||
public TextTrimming TextTrimming
|
||||
{
|
||||
get => (TextTrimming)GetValue(TextTrimmingProperty);
|
||||
set => SetValue(TextTrimmingProperty, value);
|
||||
}
|
||||
|
||||
protected TextBox? TextBox { get; private set; }
|
||||
|
||||
static EditableTextBlock()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(EditableTextBlock), new FrameworkPropertyMetadata(typeof(EditableTextBlock)));
|
||||
FocusableProperty.OverrideMetadata(typeof(EditableTextBlock), new FrameworkPropertyMetadata(BoxValue.True));
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
if (TextBox != null)
|
||||
{
|
||||
TextBox.LostFocus -= OnLostFocus;
|
||||
TextBox.LostKeyboardFocus -= OnLostFocus;
|
||||
TextBox.IsVisibleChanged -= OnTextBoxVisiblityChanged;
|
||||
}
|
||||
|
||||
TextBox = GetTemplateChild(ElementTextBox) as TextBox;
|
||||
|
||||
if (TextBox != null)
|
||||
{
|
||||
TextBox.LostFocus += OnLostFocus;
|
||||
TextBox.LostKeyboardFocus += OnLostFocus;
|
||||
TextBox.IsVisibleChanged += OnTextBoxVisiblityChanged;
|
||||
|
||||
if (IsEditing)
|
||||
{
|
||||
TextBox.Focus();
|
||||
TextBox.SelectAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextBoxVisiblityChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (IsEditing && TextBox != null)
|
||||
{
|
||||
if (TextBox.Focus())
|
||||
{
|
||||
TextBox.SelectAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
IsEditing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
if (IsEditing)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (IsEditable && e.ChangedButton == MouseButton.Left && e.ClickCount == 2)
|
||||
{
|
||||
IsEditing = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseButtonEventArgs e)
|
||||
{
|
||||
if (IsEditing)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsEditing = false;
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
if (IsEditing && e.Key == Key.Escape || !AcceptsReturn && e.Key == Key.Enter)
|
||||
{
|
||||
IsEditing = false;
|
||||
}
|
||||
|
||||
if (e.Key == Key.Enter && IsFocused && !IsEditing)
|
||||
{
|
||||
IsEditing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
196
Examples/Nodify.Shared/Controls/ResizablePanel.cs
Normal file
196
Examples/Nodify.Shared/Controls/ResizablePanel.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class ResizablePanel : ContentControl
|
||||
{
|
||||
internal static readonly object BoxedResizeDirection = ResizeDirections.All;
|
||||
|
||||
public static readonly DependencyProperty DirectionsProperty
|
||||
= DependencyProperty.Register(nameof(Directions), typeof(ResizeDirections), typeof(ResizablePanel), new FrameworkPropertyMetadata(BoxedResizeDirection));
|
||||
|
||||
public static readonly DependencyProperty ResizeStartedCommandProperty = DependencyProperty.Register(nameof(ResizeStartedCommand), typeof(ICommand), typeof(ResizablePanel));
|
||||
|
||||
public static readonly DependencyProperty ResizeCompletedCommandProperty = DependencyProperty.Register(nameof(ResizeCompletedCommand), typeof(ICommand), typeof(ResizablePanel));
|
||||
|
||||
public ResizeDirections Directions
|
||||
{
|
||||
get => (ResizeDirections)GetValue(DirectionsProperty);
|
||||
set => SetValue(DirectionsProperty, value);
|
||||
}
|
||||
|
||||
public ICommand? ResizeStartedCommand
|
||||
{
|
||||
get => (ICommand)GetValue(ResizeStartedCommandProperty);
|
||||
set => SetValue(ResizeStartedCommandProperty, value);
|
||||
}
|
||||
|
||||
public ICommand? ResizeCompletedCommand
|
||||
{
|
||||
get => (ICommand)GetValue(ResizeCompletedCommandProperty);
|
||||
set => SetValue(ResizeCompletedCommandProperty, value);
|
||||
}
|
||||
|
||||
static ResizablePanel()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(ResizablePanel), new FrameworkPropertyMetadata(typeof(ResizablePanel)));
|
||||
}
|
||||
|
||||
public ResizablePanel()
|
||||
{
|
||||
AddHandler(Thumb.DragDeltaEvent, new DragDeltaEventHandler(OnResize));
|
||||
AddHandler(Thumb.DragStartedEvent, new DragStartedEventHandler(OnDragStarted));
|
||||
AddHandler(Thumb.DragCompletedEvent, new DragCompletedEventHandler(OnDragCompleted));
|
||||
}
|
||||
|
||||
private void OnDragStarted(object sender, DragStartedEventArgs e)
|
||||
{
|
||||
if (ResizeStartedCommand?.CanExecute(null) ?? false)
|
||||
{
|
||||
ResizeStartedCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDragCompleted(object sender, DragCompletedEventArgs e)
|
||||
{
|
||||
if (ResizeCompletedCommand?.CanExecute(null) ?? false)
|
||||
{
|
||||
ResizeCompletedCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnResize(object sender, DragDeltaEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is Resizer resizer)
|
||||
{
|
||||
double resizeX = 0;
|
||||
double resizeY = 0;
|
||||
|
||||
double moveX = 0;
|
||||
double moveY = 0;
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.Top))
|
||||
{
|
||||
moveY = resizeY = ResizeTop(e);
|
||||
}
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.Bottom))
|
||||
{
|
||||
resizeY = ResizeBottom(e);
|
||||
}
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.Left))
|
||||
{
|
||||
moveX = resizeX = ResizeLeft(e);
|
||||
}
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.Right))
|
||||
{
|
||||
resizeX = ResizeRight(e);
|
||||
}
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.TopLeft))
|
||||
{
|
||||
moveY = resizeY = ResizeTop(e);
|
||||
moveX = resizeX = ResizeLeft(e);
|
||||
}
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.TopRight))
|
||||
{
|
||||
moveY = resizeY = ResizeTop(e);
|
||||
resizeX = ResizeRight(e);
|
||||
}
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.BottomLeft))
|
||||
{
|
||||
resizeY = ResizeBottom(e);
|
||||
moveX = resizeX = ResizeLeft(e);
|
||||
}
|
||||
|
||||
if (resizer.Direction.HasFlag(ResizeDirections.BottomRight))
|
||||
{
|
||||
resizeY = ResizeBottom(e);
|
||||
resizeX = ResizeRight(e);
|
||||
}
|
||||
|
||||
OnProcessDelta(ref resizeX, ref resizeY);
|
||||
OnProcessDelta(ref moveX, ref moveY);
|
||||
|
||||
OnMove(moveX, moveY);
|
||||
|
||||
Width -= resizeX;
|
||||
Height -= resizeY;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private double ResizeBottom(DragDeltaEventArgs e)
|
||||
{
|
||||
return Math.Min(-e.VerticalChange, ActualHeight - MinHeight);
|
||||
}
|
||||
|
||||
private double ResizeTop(DragDeltaEventArgs e)
|
||||
{
|
||||
return Math.Min(e.VerticalChange, ActualHeight - MinHeight);
|
||||
}
|
||||
|
||||
private double ResizeRight(DragDeltaEventArgs e)
|
||||
{
|
||||
return Math.Min(-e.HorizontalChange, ActualWidth - MinWidth);
|
||||
}
|
||||
|
||||
private double ResizeLeft(DragDeltaEventArgs e)
|
||||
{
|
||||
return Math.Min(e.HorizontalChange, ActualWidth - MinWidth);
|
||||
}
|
||||
|
||||
protected virtual void OnMove(double x, double y)
|
||||
{
|
||||
Canvas.SetTop(this, Canvas.GetTop(this) + y);
|
||||
Canvas.SetLeft(this, Canvas.GetLeft(this) + x);
|
||||
}
|
||||
|
||||
protected virtual void OnProcessDelta(ref double dx, ref double dy)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Resizer : Thumb
|
||||
{
|
||||
public static readonly DependencyProperty DirectionProperty
|
||||
= DependencyProperty.Register(nameof(Direction), typeof(ResizeDirections), typeof(Resizer), new FrameworkPropertyMetadata(ResizablePanel.BoxedResizeDirection));
|
||||
|
||||
public ResizeDirections Direction
|
||||
{
|
||||
get => (ResizeDirections)GetValue(DirectionProperty);
|
||||
set => SetValue(DirectionProperty, value);
|
||||
}
|
||||
|
||||
static Resizer()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(Resizer), new FrameworkPropertyMetadata(typeof(Resizer)));
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ResizeDirections
|
||||
{
|
||||
Top = 1,
|
||||
Left = 2,
|
||||
Bottom = 4,
|
||||
Right = 8,
|
||||
TopLeft = 16,
|
||||
TopRight = 32,
|
||||
BottomLeft = 64,
|
||||
BottomRight = 128,
|
||||
|
||||
Edges = Top | Left | Bottom | Right,
|
||||
Corners = TopLeft | TopRight | BottomLeft | BottomRight,
|
||||
All = Edges | Corners
|
||||
}
|
||||
}
|
||||
48
Examples/Nodify.Shared/Controls/Swatches.xaml.cs
Normal file
48
Examples/Nodify.Shared/Controls/Swatches.xaml.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Nodify.Shared;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public partial class Swatches : Control
|
||||
{
|
||||
public static readonly DependencyProperty SelectedColorProperty
|
||||
= DependencyProperty.Register(nameof(SelectedColor), typeof(Color), typeof(Swatches), new FrameworkPropertyMetadata(default(Color), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
|
||||
|
||||
public static readonly DependencyProperty ColorsProperty
|
||||
= DependencyProperty.Register(nameof(Colors), typeof(IEnumerable<Color>), typeof(Swatches), new PropertyMetadata(Array.Empty<Color>()));
|
||||
|
||||
public Color SelectedColor
|
||||
{
|
||||
get => (Color)GetValue(SelectedColorProperty);
|
||||
set => SetValue(SelectedColorProperty, value);
|
||||
}
|
||||
|
||||
public IEnumerable<Color> Colors
|
||||
{
|
||||
get => (IEnumerable<Color>)GetValue(ColorsProperty);
|
||||
set => SetValue(ColorsProperty, value);
|
||||
}
|
||||
|
||||
static Swatches()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(Swatches), new FrameworkPropertyMetadata(typeof(Swatches)));
|
||||
FocusableProperty.OverrideMetadata(typeof(Swatches), new FrameworkPropertyMetadata(BoxValue.True));
|
||||
}
|
||||
|
||||
protected override void OnMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
var color = e.OriginalSource is FrameworkElement fe && fe.DataContext is Color c ? c : (Color?)null;
|
||||
if (color.HasValue)
|
||||
{
|
||||
SelectedColor = color.Value;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Examples/Nodify.Shared/Controls/TabControlEx.cs
Normal file
57
Examples/Nodify.Shared/Controls/TabControlEx.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
[TemplatePart(Name = ElementScrollViewer, Type = typeof(ScrollViewer))]
|
||||
public class TabControlEx : TabControl
|
||||
{
|
||||
private const string ElementScrollViewer = "PART_ScrollViewer";
|
||||
|
||||
public static readonly DependencyProperty AddTabCommandProperty = DependencyProperty.Register(nameof(AddTabCommand), typeof(ICommand), typeof(TabControlEx), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty AutoScrollToEndProperty = DependencyProperty.Register(nameof(AutoScrollToEnd), typeof(bool), typeof(TabControlEx), new PropertyMetadata(false));
|
||||
|
||||
public ICommand AddTabCommand
|
||||
{
|
||||
get { return (ICommand)GetValue(AddTabCommandProperty); }
|
||||
set { SetValue(AddTabCommandProperty, value); }
|
||||
}
|
||||
public bool AutoScrollToEnd
|
||||
{
|
||||
get { return (bool)GetValue(AutoScrollToEndProperty); }
|
||||
set { SetValue(AutoScrollToEndProperty, value); }
|
||||
}
|
||||
|
||||
protected ScrollViewer? ScrollViewer { get; private set; }
|
||||
|
||||
static TabControlEx()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(TabControlEx), new FrameworkPropertyMetadata(typeof(TabControlEx)));
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
ScrollViewer = GetTemplateChild(ElementScrollViewer) as ScrollViewer;
|
||||
if(ScrollViewer != null)
|
||||
{
|
||||
ScrollViewer.ScrollChanged += OnScrollChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
if(e.ExtentWidthChange > 0 && e.ViewportWidth < e.ExtentWidth && AutoScrollToEnd)
|
||||
{
|
||||
ScrollViewer?.ScrollToRightEnd();
|
||||
}
|
||||
}
|
||||
|
||||
protected override DependencyObject GetContainerForItemOverride()
|
||||
{
|
||||
return new TabItemEx();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Examples/Nodify.Shared/Controls/TabItemEx.cs
Normal file
29
Examples/Nodify.Shared/Controls/TabItemEx.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class TabItemEx : TabItem
|
||||
{
|
||||
public static readonly DependencyProperty CloseTabCommandProperty = DependencyProperty.Register(nameof(CloseTabCommand), typeof(ICommand), typeof(TabItemEx), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty CloseTabCommandParameterProperty = DependencyProperty.Register(nameof(CloseTabCommandParameter), typeof(object), typeof(TabItemEx), new PropertyMetadata(null));
|
||||
|
||||
public ICommand CloseTabCommand
|
||||
{
|
||||
get { return (ICommand)GetValue(CloseTabCommandProperty); }
|
||||
set { SetValue(CloseTabCommandProperty, value); }
|
||||
}
|
||||
|
||||
public object CloseTabCommandParameter
|
||||
{
|
||||
get { return (object)GetValue(CloseTabCommandParameterProperty); }
|
||||
set { SetValue(CloseTabCommandParameterProperty, value); }
|
||||
}
|
||||
|
||||
static TabItemEx()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(TabItemEx), new FrameworkPropertyMetadata(typeof(TabItemEx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class BooleanToVisibilityConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
public Visibility FalseVisibility { get; set; } = Visibility.Collapsed;
|
||||
public bool Negate { get; set; }
|
||||
|
||||
public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
string? stringValue = value?.ToString();
|
||||
if (bool.TryParse(stringValue, out var b))
|
||||
{
|
||||
return (Negate ? !b : b) ? Visibility.Visible : FalseVisibility;
|
||||
}
|
||||
else if (double.TryParse(stringValue, out var d))
|
||||
{
|
||||
return (Negate ? !(d > 0) : (d > 0)) ? Visibility.Visible : FalseVisibility;
|
||||
}
|
||||
|
||||
bool result = value != null;
|
||||
return (Negate ? !result : result) ? Visibility.Visible : FalseVisibility;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> value is Visibility v && v == Visibility.Visible;
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) => this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class ColorToSolidColorBrushConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Color color)
|
||||
{
|
||||
var brush = new SolidColorBrush(color);
|
||||
|
||||
if(double.TryParse(parameter?.ToString(), out double opacity))
|
||||
brush.Opacity = opacity;
|
||||
|
||||
return brush;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is SolidColorBrush brush)
|
||||
return brush.Color;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Examples/Nodify.Shared/Converters/DebugConverter.cs
Normal file
24
Examples/Nodify.Shared/Converters/DebugConverter.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class DebugConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
Console.WriteLine($"Value: {value} :: Parameter: {parameter}");
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
Console.WriteLine($"Value: {value} :: Parameter: {parameter}");
|
||||
return value;
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) => this;
|
||||
}
|
||||
}
|
||||
49
Examples/Nodify.Shared/Converters/EnumValuesConverter.cs
Normal file
49
Examples/Nodify.Shared/Converters/EnumValuesConverter.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public readonly struct EnumValue
|
||||
{
|
||||
public EnumValue(string name, object? value)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public object? Value { get; }
|
||||
}
|
||||
|
||||
public class EnumValuesConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Enum enumValue)
|
||||
{
|
||||
var type = enumValue.GetType();
|
||||
var values = Enum.GetValues(type);
|
||||
var names = Enum.GetNames(type);
|
||||
|
||||
EnumValue[] result = new EnumValue[values.Length];
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
result[i] = new EnumValue(names[i], values.GetValue(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) => this;
|
||||
}
|
||||
}
|
||||
25
Examples/Nodify.Shared/Converters/InverseBooleanConverter.cs
Normal file
25
Examples/Nodify.Shared/Converters/InverseBooleanConverter.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class InverseBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (targetType != typeof(bool))
|
||||
throw new InvalidOperationException("The value must be of type bool.");
|
||||
|
||||
return !(bool)value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (targetType != typeof(bool))
|
||||
throw new InvalidOperationException("The value must be of type bool.");
|
||||
|
||||
return !(bool)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class MultiValueEqualityConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return AllElementsEqual(values) || AllElementsNull(values);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static bool AllElementsEqual(IEnumerable<object> values)
|
||||
{
|
||||
object? firstElement = values.FirstOrDefault();
|
||||
return values.All(o => o?.Equals(firstElement) == true);
|
||||
}
|
||||
|
||||
private static bool AllElementsNull(IEnumerable<object> values)
|
||||
{
|
||||
return values.All(o => o == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Examples/Nodify.Shared/Converters/RandomBrushConverter.cs
Normal file
30
Examples/Nodify.Shared/Converters/RandomBrushConverter.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class RandomBrushConverter : IValueConverter
|
||||
{
|
||||
private readonly Random _rand = new Random();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (double.TryParse(parameter?.ToString(), out double alpha))
|
||||
{
|
||||
return new SolidColorBrush(Color.FromRgb((byte)_rand.Next(256), (byte)_rand.Next(256), (byte)_rand.Next(256)))
|
||||
{
|
||||
Opacity = alpha
|
||||
};
|
||||
}
|
||||
|
||||
return new SolidColorBrush(Color.FromRgb((byte)_rand.Next(256), (byte)_rand.Next(256), (byte)_rand.Next(256)));
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
internal class ResizeDirectionToVisiblityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (!(value is ResizeDirections resizeDirections))
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
if (Enum.TryParse(parameter.ToString(), out ResizeDirections direction))
|
||||
{
|
||||
return resizeDirections.HasFlag(direction) ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class StringToVisibilityConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
public Visibility NullVisibility { get; set; } = Visibility.Collapsed;
|
||||
|
||||
public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> string.IsNullOrEmpty(value as string) ? NullVisibility : Visibility.Visible;
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) => this;
|
||||
}
|
||||
}
|
||||
35
Examples/Nodify.Shared/Converters/ToStringConverter.cs
Normal file
35
Examples/Nodify.Shared/Converters/ToStringConverter.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class ToStringConverter : IValueConverter
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Point p)
|
||||
{
|
||||
return $"{p.X:0.0}, {p.Y:0.0}";
|
||||
}
|
||||
|
||||
if (value is Size s)
|
||||
{
|
||||
return $"{s.Width:0.0}, {s.Height:0.0}";
|
||||
}
|
||||
|
||||
if(value is double d)
|
||||
{
|
||||
return d.ToString("0.00");
|
||||
}
|
||||
|
||||
return value?.ToString();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
72
Examples/Nodify.Shared/DelegateCommand.cs
Normal file
72
Examples/Nodify.Shared/DelegateCommand.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public interface INodifyCommand : ICommand
|
||||
{
|
||||
void RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
public class DelegateCommand : INodifyCommand
|
||||
{
|
||||
private readonly Action _action;
|
||||
private readonly Func<bool>? _condition;
|
||||
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
public DelegateCommand(Action action, Func<bool>? executeCondition = default)
|
||||
{
|
||||
_action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
_condition = executeCondition;
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter)
|
||||
=> _condition?.Invoke() ?? true;
|
||||
|
||||
public void Execute(object? parameter)
|
||||
=> _action();
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
=> CanExecuteChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
|
||||
public class DelegateCommand<T> : INodifyCommand
|
||||
{
|
||||
private readonly Action<T> _action;
|
||||
private readonly Func<T, bool>? _condition;
|
||||
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
public DelegateCommand(Action<T> action, Func<T, bool>? executeCondition = default)
|
||||
{
|
||||
_action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
_condition = executeCondition;
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
if (parameter is T value)
|
||||
{
|
||||
return _condition?.Invoke(value) ?? true;
|
||||
}
|
||||
|
||||
return _condition?.Invoke(default!) ?? true;
|
||||
}
|
||||
|
||||
public void Execute(object? parameter)
|
||||
{
|
||||
if (parameter is T value)
|
||||
{
|
||||
_action(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_action(default!);
|
||||
}
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
=> CanExecuteChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
74
Examples/Nodify.Shared/FluentSyntax.cs
Normal file
74
Examples/Nodify.Shared/FluentSyntax.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public static class FluentSyntax
|
||||
{
|
||||
public static void Then<T>(this T caller, Action<T> action)
|
||||
=> action?.Invoke(caller);
|
||||
|
||||
public static bool Then(this bool condition, Action action)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
public static bool Else(this bool condition, Action action)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
action();
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> collection, Action<T> action)
|
||||
{
|
||||
if (collection is IList<T> list)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
action(list[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in collection)
|
||||
{
|
||||
action(item);
|
||||
}
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static ICollection<T> AddRange<T>(this ICollection<T> collection, IEnumerable<T> values)
|
||||
{
|
||||
values.ForEach(collection.Add);
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static ICollection<T> RemoveRange<T>(this ICollection<T> collection, IEnumerable<T> values)
|
||||
{
|
||||
values.ForEach(v => collection.Remove(v));
|
||||
return collection;
|
||||
}
|
||||
|
||||
public static ICollection<T> RemoveOne<T>(this ICollection<T> collection, Func<T, bool> search)
|
||||
{
|
||||
if (collection.FirstOrDefault(search) is { } x)
|
||||
{
|
||||
collection.Remove(x);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Examples/Nodify.Shared/Nodify.Shared.csproj
Normal file
24
Examples/Nodify.Shared/Nodify.Shared.csproj
Normal file
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<UseWPF>true</UseWPF>
|
||||
<TargetFrameworks>net9-windows;net8-windows;net6-windows;net5-windows;netcoreapp3.1;net48;net472</TargetFrameworks>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(TargetFramework)'=='net472' OR '$(TargetFramework)'=='net48'">
|
||||
<LangVersion>8.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="Themes\Controls.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Themes\Generic.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Themes\Icons.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
193
Examples/Nodify.Shared/NodifyObservableCollection.cs
Normal file
193
Examples/Nodify.Shared/NodifyObservableCollection.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public interface INodifyObservableCollection<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when a new item is added
|
||||
/// </summary>
|
||||
/// <param name="added">The callback to execute when an item is added</param>
|
||||
/// <returns>Returns self</returns>
|
||||
INodifyObservableCollection<T> WhenAdded(Action<T> added);
|
||||
|
||||
/// <summary>
|
||||
/// Called when an existing item is removed
|
||||
/// Note: It is not called when items are cleared if <see cref="WhenCleared(Action{IList{T}})"/> is used
|
||||
/// </summary>
|
||||
/// <param name="added">The callback to execute when an item is removed</param>
|
||||
/// <returns>Returns self</returns>
|
||||
INodifyObservableCollection<T> WhenRemoved(Action<T> removed);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the collection is cleared
|
||||
/// NOTE: It does not call <see cref="WhenRemoved(Action{T})"/> on each item
|
||||
/// </summary>
|
||||
/// <param name="added">The callback to execute when the collection is cleared</param>
|
||||
/// <returns>Returns self</returns>
|
||||
INodifyObservableCollection<T> WhenCleared(Action<IList<T>> cleared);
|
||||
}
|
||||
|
||||
public class NodifyObservableCollection<T> : Collection<T>, INodifyObservableCollection<T>, INotifyPropertyChanged, INotifyCollectionChanged
|
||||
{
|
||||
protected static readonly PropertyChangedEventArgs IndexerPropertyChanged = new PropertyChangedEventArgs("Item[]");
|
||||
protected static readonly PropertyChangedEventArgs CountPropertyChanged = new PropertyChangedEventArgs("Count");
|
||||
protected static readonly NotifyCollectionChangedEventArgs ResetCollectionChanged = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
|
||||
|
||||
private readonly List<Action<T>> _added = new List<Action<T>>();
|
||||
private readonly List<Action<T>> _removed = new List<Action<T>>();
|
||||
private readonly List<Action<IList<T>>> _cleared = new List<Action<IList<T>>>();
|
||||
|
||||
public event NotifyCollectionChangedEventHandler? CollectionChanged;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
public NodifyObservableCollection()
|
||||
{
|
||||
}
|
||||
|
||||
public NodifyObservableCollection(IEnumerable<T> collection)
|
||||
: base(new List<T>(collection))
|
||||
{
|
||||
}
|
||||
|
||||
#region Collection Events
|
||||
|
||||
public INodifyObservableCollection<T> WhenAdded(Action<T> added)
|
||||
{
|
||||
if (added != null)
|
||||
{
|
||||
_added.Add(added);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public INodifyObservableCollection<T> WhenRemoved(Action<T> removed)
|
||||
{
|
||||
if (removed != null)
|
||||
{
|
||||
_removed.Add(removed);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public INodifyObservableCollection<T> WhenCleared(Action<IList<T>> cleared)
|
||||
{
|
||||
if (cleared != null)
|
||||
{
|
||||
_cleared.Add(cleared);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected virtual void NotifyOnItemAdded(T item)
|
||||
{
|
||||
for (int i = 0; i < _added.Count; i++)
|
||||
{
|
||||
_added[i](item);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void NotifyOnItemRemoved(T item)
|
||||
{
|
||||
for (int i = 0; i < _removed.Count; i++)
|
||||
{
|
||||
_removed[i](item);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void NotifyOnItemsCleared(IList<T> items)
|
||||
{
|
||||
for (int i = 0; i < _cleared.Count; i++)
|
||||
{
|
||||
_cleared[i](items);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Collection Handlers
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
var items = _cleared.Count > 0 || _removed.Count > 0 ? new List<T>(this) : new List<T>();
|
||||
base.ClearItems();
|
||||
|
||||
if (_cleared.Count > 0)
|
||||
{
|
||||
NotifyOnItemsCleared(items);
|
||||
}
|
||||
else if (_removed.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
NotifyOnItemRemoved(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
OnPropertyChanged(CountPropertyChanged);
|
||||
OnPropertyChanged(IndexerPropertyChanged);
|
||||
OnCollectionChanged(ResetCollectionChanged);
|
||||
}
|
||||
|
||||
protected override void InsertItem(int index, T item)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
|
||||
OnPropertyChanged(CountPropertyChanged);
|
||||
OnPropertyChanged(IndexerPropertyChanged);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
|
||||
NotifyOnItemAdded(item);
|
||||
}
|
||||
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
var item = base[index];
|
||||
base.RemoveItem(index);
|
||||
|
||||
OnPropertyChanged(CountPropertyChanged);
|
||||
OnPropertyChanged(IndexerPropertyChanged);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index);
|
||||
NotifyOnItemRemoved(item);
|
||||
}
|
||||
|
||||
protected override void SetItem(int index, T item)
|
||||
{
|
||||
T prev = base[index];
|
||||
base.SetItem(index, item);
|
||||
OnPropertyChanged(IndexerPropertyChanged);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Replace, prev, item, index);
|
||||
NotifyOnItemRemoved(prev);
|
||||
NotifyOnItemAdded(item);
|
||||
}
|
||||
|
||||
public void Move(int oldIndex, int newIndex)
|
||||
{
|
||||
T prev = base[oldIndex];
|
||||
base.RemoveItem(oldIndex);
|
||||
base.InsertItem(newIndex, prev);
|
||||
OnPropertyChanged(IndexerPropertyChanged);
|
||||
OnCollectionChanged(NotifyCollectionChangedAction.Move, prev, newIndex, oldIndex);
|
||||
}
|
||||
|
||||
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
=> CollectionChanged?.Invoke(this, e);
|
||||
|
||||
protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
|
||||
=> PropertyChanged?.Invoke(this, args);
|
||||
|
||||
private void OnCollectionChanged(NotifyCollectionChangedAction action, object? item, int index)
|
||||
=> OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
|
||||
|
||||
private void OnCollectionChanged(NotifyCollectionChangedAction action, object? item, int index, int oldIndex)
|
||||
=> OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
|
||||
|
||||
private void OnCollectionChanged(NotifyCollectionChangedAction action, object? oldItem, object? newItem, int index)
|
||||
=> OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
51
Examples/Nodify.Shared/ObservableObject.cs
Normal file
51
Examples/Nodify.Shared/ObservableObject.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class ObservableObject : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the dispatcher to use to dispatch PropertyChanged events. Defaults to UI thread.
|
||||
/// </summary>
|
||||
public virtual Action<Action> PropertyChangedDispatcher { get; set; } = Application.Current.Dispatcher.Invoke;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Fires the PropertyChanged notification.
|
||||
/// </summary>
|
||||
/// <remarks>Specially named so that Fody.PropertyChanged calls it</remarks>
|
||||
/// <param name="propertyName">Name of the property to raise the notification for</param>
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
|
||||
{
|
||||
PropertyChangedDispatcher(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Takes, by reference, a field, and its new value. If field != value, will set field = value and raise a PropertyChanged notification
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of field being set and notified</typeparam>
|
||||
/// <param name="field">Field to assign</param>
|
||||
/// <param name="value">Value to assign to the field, if it differs</param>
|
||||
/// <param name="propertyName">Name of the property to notify for. Defaults to the calling property</param>
|
||||
/// <returns>True if field != value and a notification was raised; false otherwise</returns>
|
||||
protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
|
||||
{
|
||||
if (!EqualityComparer<T>.Default.Equals(field, value))
|
||||
{
|
||||
field = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Examples/Nodify.Shared/Properties/AssemblyInfo.cs
Normal file
10
Examples/Nodify.Shared/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
73
Examples/Nodify.Shared/RequeryCommand.cs
Normal file
73
Examples/Nodify.Shared/RequeryCommand.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public class RequeryCommand : INodifyCommand
|
||||
{
|
||||
private readonly Action _action;
|
||||
private readonly Func<bool>? _condition;
|
||||
|
||||
public event EventHandler? CanExecuteChanged
|
||||
{
|
||||
add => CommandManager.RequerySuggested += value;
|
||||
remove => CommandManager.RequerySuggested -= value;
|
||||
}
|
||||
|
||||
public RequeryCommand(Action action, Func<bool>? executeCondition = default)
|
||||
{
|
||||
_action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
_condition = executeCondition;
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter)
|
||||
=> _condition?.Invoke() ?? true;
|
||||
|
||||
public void Execute(object? parameter)
|
||||
=> _action();
|
||||
|
||||
public void RaiseCanExecuteChanged() { }
|
||||
}
|
||||
|
||||
public class RequeryCommand<T> : INodifyCommand
|
||||
{
|
||||
private readonly Action<T> _action;
|
||||
private readonly Func<T, bool>? _condition;
|
||||
|
||||
public event EventHandler? CanExecuteChanged
|
||||
{
|
||||
add => CommandManager.RequerySuggested += value;
|
||||
remove => CommandManager.RequerySuggested -= value;
|
||||
}
|
||||
|
||||
public RequeryCommand(Action<T> action, Func<T, bool>? executeCondition = default)
|
||||
{
|
||||
_action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
_condition = executeCondition;
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
if (parameter is T value)
|
||||
{
|
||||
return _condition?.Invoke(value) ?? true;
|
||||
}
|
||||
|
||||
return _condition?.Invoke(default!) ?? true;
|
||||
}
|
||||
|
||||
public void Execute(object? parameter)
|
||||
{
|
||||
if (parameter is T value)
|
||||
{
|
||||
_action(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_action(default!);
|
||||
}
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged() { }
|
||||
}
|
||||
}
|
||||
21
Examples/Nodify.Shared/StringExtensions.cs
Normal file
21
Examples/Nodify.Shared/StringExtensions.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static string GetUnique(this ICollection<string> values, in string baseValue)
|
||||
{
|
||||
int counter = 1;
|
||||
string result = baseValue;
|
||||
|
||||
while (values.Contains(result))
|
||||
{
|
||||
result = $"{baseValue}{counter}";
|
||||
counter++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
Examples/Nodify.Shared/ThemeManager.cs
Normal file
134
Examples/Nodify.Shared/ThemeManager.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Nodify
|
||||
{
|
||||
public static class ThemeManager
|
||||
{
|
||||
private static readonly string? _assemblyName = Assembly.GetEntryAssembly()?.GetName().Name;
|
||||
|
||||
private static readonly Dictionary<string, List<Uri>> _themesUris = new Dictionary<string, List<Uri>>();
|
||||
private static readonly Dictionary<string, List<ResourceDictionary>> _themesResources = new Dictionary<string, List<ResourceDictionary>>();
|
||||
|
||||
public static string? ActiveTheme { get; private set; }
|
||||
|
||||
private static readonly List<string> _availableThemes = new List<string>();
|
||||
public static IReadOnlyCollection<string> AvailableThemes => _availableThemes;
|
||||
|
||||
public static ICommand SetNextThemeCommand { get; }
|
||||
|
||||
static ThemeManager()
|
||||
{
|
||||
PreloadTheme("Dark");
|
||||
PreloadTheme("Light");
|
||||
PreloadTheme("Nodify");
|
||||
|
||||
SetNextThemeCommand = new DelegateCommand(SetNextTheme);
|
||||
}
|
||||
|
||||
private static List<ResourceDictionary> FindExistingResources(List<Uri> uris)
|
||||
{
|
||||
var result = new List<ResourceDictionary>();
|
||||
foreach (var d in Application.Current.Resources.MergedDictionaries)
|
||||
{
|
||||
if (d.Source != null && uris.Contains(d.Source))
|
||||
{
|
||||
result.Add(d);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void PreloadTheme(string themeName)
|
||||
{
|
||||
if (!_themesUris.TryGetValue(themeName, out var preload))
|
||||
{
|
||||
preload = new List<Uri>(3)
|
||||
{
|
||||
new Uri($"pack://application:,,,/Nodify;component/Themes/{themeName}.xaml"),
|
||||
new Uri($"pack://application:,,,/Nodify.Shared;component/Themes/{themeName}.xaml")
|
||||
};
|
||||
|
||||
if (_assemblyName != null)
|
||||
{
|
||||
preload.Add(new Uri($"pack://application:,,,/{_assemblyName};component/Themes/{themeName}.xaml"));
|
||||
}
|
||||
|
||||
_themesUris.Add(themeName, preload);
|
||||
}
|
||||
|
||||
var resources = FindExistingResources(preload);
|
||||
if (resources.Count == 0)
|
||||
{
|
||||
for (int i = 0; i < preload.Count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
resources.Add(new ResourceDictionary
|
||||
{
|
||||
Source = preload[i]
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ActiveTheme == null)
|
||||
{
|
||||
ActiveTheme = themeName;
|
||||
}
|
||||
|
||||
_themesResources.Add(themeName, resources);
|
||||
_availableThemes.Add(themeName);
|
||||
}
|
||||
|
||||
public static void SetNextTheme()
|
||||
{
|
||||
if (ActiveTheme != null)
|
||||
{
|
||||
var i = _availableThemes.IndexOf(ActiveTheme);
|
||||
var next = i + 1 == _availableThemes.Count ? 0 : i + 1;
|
||||
|
||||
SetTheme(_availableThemes[next]);
|
||||
}
|
||||
else if (_availableThemes.Count > 0)
|
||||
{
|
||||
SetTheme(_availableThemes[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetTheme(string themeName)
|
||||
{
|
||||
if (!_themesResources.ContainsKey(themeName))
|
||||
{
|
||||
PreloadTheme(themeName);
|
||||
}
|
||||
|
||||
// Load new theme if it is valid
|
||||
if (_themesResources.TryGetValue(themeName, out var resources))
|
||||
{
|
||||
foreach (var res in resources)
|
||||
{
|
||||
Application.Current.Resources.MergedDictionaries.Insert(0, res);
|
||||
}
|
||||
|
||||
// Unload current theme
|
||||
if (ActiveTheme != null)
|
||||
{
|
||||
foreach (var res in _themesResources[ActiveTheme])
|
||||
{
|
||||
Application.Current.Resources.MergedDictionaries.Remove(res);
|
||||
}
|
||||
}
|
||||
|
||||
ActiveTheme = themeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Examples/Nodify.Shared/Themes/Brushes.xaml
Normal file
45
Examples/Nodify.Shared/Themes/Brushes.xaml
Normal file
@@ -0,0 +1,45 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:o="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options">
|
||||
|
||||
<SolidColorBrush x:Key="ForegroundBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource ForegroundColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="DisabledForegroundBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource DisabledForegroundColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="BackgroundBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource BackgroundColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="ContrastBackgroundBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource ContrastBackgroundColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="HighlightedBackgroundBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource HighlightedBackgroundColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="BorderBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource BorderColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="DisabledBorderBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource DisabledBorderColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="HighlightedBorderBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource HighlightedBorderColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="FocusedBorderBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource FocusedBorderColor}" />
|
||||
|
||||
<SolidColorBrush x:Key="GridLinesBrush"
|
||||
o:Freeze="True"
|
||||
Color="{DynamicResource GridLinesColor}" />
|
||||
|
||||
</ResourceDictionary>
|
||||
857
Examples/Nodify.Shared/Themes/Controls.xaml
Normal file
857
Examples/Nodify.Shared/Themes/Controls.xaml
Normal file
@@ -0,0 +1,857 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<Style TargetType="{x:Type CheckBox}"
|
||||
BasedOn="{StaticResource {x:Type CheckBox}}">
|
||||
<Setter Property="SnapsToDevicePixels"
|
||||
Value="False" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="IsThreeState"
|
||||
Value="False" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="CheckBox">
|
||||
<BulletDecorator Background="Transparent">
|
||||
<BulletDecorator.Bullet>
|
||||
<Border x:Name="Border"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
ClipToBounds="True">
|
||||
<Path x:Name="PART_CheckMark"
|
||||
Stroke="{TemplateBinding Foreground}"
|
||||
Width="7"
|
||||
Height="7"
|
||||
Stretch="Fill"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
SnapsToDevicePixels="False"
|
||||
StrokeThickness="2"
|
||||
StrokeEndLineCap="Round"
|
||||
StrokeStartLineCap="Round"
|
||||
Data="M 30,100 L 80,140 L 160,60" />
|
||||
</Border>
|
||||
</BulletDecorator.Bullet>
|
||||
<ContentPresenter Margin="4,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
RecognizesAccessKey="True" />
|
||||
</BulletDecorator>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource HighlightedBorderBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed"
|
||||
Value="True">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource FocusedBorderBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked"
|
||||
Value="False">
|
||||
<Setter TargetName="PART_CheckMark"
|
||||
Property="Visibility"
|
||||
Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource DisabledBorderBrush}" />
|
||||
<Setter TargetName="PART_CheckMark"
|
||||
Property="Stroke"
|
||||
Value="{DynamicResource DisabledBorderBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type TextBox}"
|
||||
BasedOn="{StaticResource {x:Type TextBox}}">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="Padding"
|
||||
Value="4 2" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ToggleButton}"
|
||||
BasedOn="{StaticResource {x:Type ToggleButton}}">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="20" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border x:Name="PART_Border"
|
||||
Grid.ColumnSpan="2"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}" />
|
||||
|
||||
<Path Grid.Column="1"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z" />
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter TargetName="PART_Border"
|
||||
Property="Background"
|
||||
Value="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
TargetName="PART_Border"
|
||||
Value="{DynamicResource HighlightedBorderBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked"
|
||||
Value="True">
|
||||
<Setter Property="BorderBrush"
|
||||
TargetName="PART_Border"
|
||||
Value="{DynamicResource FocusedBorderBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ComboBox}"
|
||||
BasedOn="{StaticResource {x:Type ComboBox}}">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ComboBox}">
|
||||
<Grid>
|
||||
<ToggleButton Focusable="False"
|
||||
IsThreeState="False"
|
||||
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsEnabled="{TemplateBinding IsEnabled}"
|
||||
ClickMode="Press" />
|
||||
|
||||
<ContentPresenter x:Name="PART_Content"
|
||||
IsHitTestVisible="False"
|
||||
Content="{TemplateBinding SelectionBoxItem}"
|
||||
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
|
||||
Margin="4 2 24 2"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBox x:Name="PART_EditableTextBox"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Margin="4 2 24 2"
|
||||
Focusable="True"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
IsReadOnly="{TemplateBinding IsReadOnly}"
|
||||
Visibility="Hidden" />
|
||||
|
||||
<Popup Placement="Bottom"
|
||||
IsOpen="{TemplateBinding IsDropDownOpen}"
|
||||
Focusable="False"
|
||||
AllowsTransparency="True"
|
||||
PopupAnimation="Slide">
|
||||
<Grid SnapsToDevicePixels="True"
|
||||
MinWidth="{TemplateBinding ActualWidth}"
|
||||
MaxHeight="{TemplateBinding MaxDropDownHeight}">
|
||||
<Border x:Name="PART_DropDown"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
MinHeight="15"
|
||||
Margin="0 2 0 0" />
|
||||
<ScrollViewer Margin="2 3"
|
||||
SnapsToDevicePixels="True">
|
||||
<StackPanel IsItemsHost="True"
|
||||
KeyboardNavigation.DirectionalNavigation="Contained" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Popup>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource DisabledForegroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEditable"
|
||||
Value="True">
|
||||
<Setter Property="IsTabStop"
|
||||
Value="False" />
|
||||
<Setter TargetName="PART_EditableTextBox"
|
||||
Property="Visibility"
|
||||
Value="Visible" />
|
||||
<Setter TargetName="PART_Content"
|
||||
Property="Visibility"
|
||||
Value="Hidden" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ComboBoxItem}"
|
||||
BasedOn="{StaticResource {x:Type ComboBoxItem}}">
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
|
||||
<Border Name="Border"
|
||||
Padding="4 2"
|
||||
SnapsToDevicePixels="True">
|
||||
<ContentPresenter />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsHighlighted"
|
||||
Value="True">
|
||||
<Setter TargetName="Border"
|
||||
Property="Background"
|
||||
Value="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource DisabledForegroundBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ScrollViewer}"
|
||||
BasedOn="{StaticResource {x:Type ScrollViewer}}">
|
||||
<Setter Property="VerticalScrollBarVisibility"
|
||||
Value="Auto" />
|
||||
<Setter Property="HorizontalScrollBarVisibility"
|
||||
Value="Auto" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollViewer}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollContentPresenter CanContentScroll="{TemplateBinding CanContentScroll}"
|
||||
ContentSource="Content" />
|
||||
<ScrollBar x:Name="PART_VerticalScrollBar"
|
||||
Value="{TemplateBinding VerticalOffset}"
|
||||
Maximum="{TemplateBinding ScrollableHeight}"
|
||||
ViewportSize="{TemplateBinding ViewportHeight}"
|
||||
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
|
||||
Orientation="Vertical"
|
||||
Width="7"
|
||||
Grid.Column="1"
|
||||
Grid.Row="0" />
|
||||
<ScrollBar x:Name="PART_HorizontalScrollBar"
|
||||
Value="{TemplateBinding HorizontalOffset}"
|
||||
Maximum="{TemplateBinding ScrollableWidth}"
|
||||
ViewportSize="{TemplateBinding ViewportWidth}"
|
||||
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
|
||||
Orientation="Horizontal"
|
||||
Height="7"
|
||||
Grid.Column="0"
|
||||
Grid.Row="1" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ScrollBar}"
|
||||
BasedOn="{StaticResource {x:Type ScrollBar}}">
|
||||
<Style.Resources>
|
||||
<Style TargetType="{x:Type Thumb}"
|
||||
BasedOn="{StaticResource {x:Type Thumb}}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Thumb}">
|
||||
<Rectangle SnapsToDevicePixels="True"
|
||||
Height="{TemplateBinding Height}"
|
||||
Width="{TemplateBinding Width}"
|
||||
Fill="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Style.Resources>
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollBar}">
|
||||
<Grid x:Name="PART_Content"
|
||||
SnapsToDevicePixels="True"
|
||||
Height="{TemplateBinding Height}"
|
||||
Width="{TemplateBinding Width}"
|
||||
Margin="0 5 0 5">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}" />
|
||||
<Track x:Name="PART_Track"
|
||||
IsEnabled="{TemplateBinding IsMouseOver}"
|
||||
IsDirectionReversed="True">
|
||||
<Track.Thumb>
|
||||
<Thumb />
|
||||
</Track.Thumb>
|
||||
</Track>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Orientation"
|
||||
Value="Horizontal">
|
||||
<Setter Property="Width"
|
||||
Value="Auto" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ScrollBar}">
|
||||
<Grid x:Name="PART_Content"
|
||||
SnapsToDevicePixels="True"
|
||||
Height="{TemplateBinding Height}"
|
||||
Width="{TemplateBinding Width}"
|
||||
Margin="5 0 5 0">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}" />
|
||||
<Track x:Name="PART_Track"
|
||||
IsEnabled="{TemplateBinding IsMouseOver}">
|
||||
<Track.Thumb>
|
||||
<Thumb />
|
||||
</Track.Thumb>
|
||||
</Track>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type Separator}"
|
||||
BasedOn="{StaticResource {x:Type Separator}}">
|
||||
<Setter Property="Focusable"
|
||||
Value="False" />
|
||||
<Setter Property="VerticalAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="HorizontalAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="Height"
|
||||
Value="1" />
|
||||
<Setter Property="Width"
|
||||
Value="2" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Separator}">
|
||||
<Border BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Height="{TemplateBinding Height}"
|
||||
Width="{TemplateBinding Width}" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="IconCheckBox"
|
||||
TargetType="{x:Type CheckBox}"
|
||||
BasedOn="{StaticResource {x:Type CheckBox}}">
|
||||
<Setter Property="Padding"
|
||||
Value="1 2" />
|
||||
<Setter Property="HorizontalAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="VerticalAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type CheckBox}">
|
||||
<Border x:Name="PART_Border"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
SnapsToDevicePixels="True">
|
||||
<ContentPresenter HorizontalAlignment="Left"
|
||||
SnapsToDevicePixels="True"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter TargetName="PART_Border"
|
||||
Property="Background"
|
||||
Value="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed"
|
||||
Value="True">
|
||||
<Setter TargetName="PART_Border"
|
||||
Property="Background"
|
||||
Value="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource DisabledForegroundBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="IconButton"
|
||||
TargetType="{x:Type Button}"
|
||||
BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Padding"
|
||||
Value="1 2" />
|
||||
<Setter Property="HorizontalAlignment"
|
||||
Value="Left" />
|
||||
<Setter Property="VerticalAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="PART_Border"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
SnapsToDevicePixels="True">
|
||||
<ContentPresenter x:Name="contentPresenter"
|
||||
Focusable="False"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter TargetName="PART_Border"
|
||||
Property="Background"
|
||||
Value="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed"
|
||||
Value="True">
|
||||
<Setter TargetName="PART_Border"
|
||||
Property="Background"
|
||||
Value="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource DisabledForegroundBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="HollowButton"
|
||||
TargetType="{x:Type Button}"
|
||||
BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Margin"
|
||||
Value="0,0,5,0" />
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Setter Property="Padding"
|
||||
Value="7" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="OrangeRed" />
|
||||
<Setter Property="Cursor"
|
||||
Value="Hand" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="FocusVisualStyle"
|
||||
Value="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="3"
|
||||
Margin="{TemplateBinding Margin}">
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type MenuItem}">
|
||||
<Setter Property="OverridesDefaultStyle"
|
||||
Value="True" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
|
||||
<Setter Property="Background"
|
||||
Value="{Binding Path=Background, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="Padding"
|
||||
Value="3 0 0 0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type MenuItem}">
|
||||
<Border x:Name="PART_Border"
|
||||
Margin="{TemplateBinding Margin}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Padding="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition MinWidth="17"
|
||||
Width="Auto"
|
||||
SharedSizeGroup="MenuItemIcon" />
|
||||
<ColumnDefinition Width="Auto"
|
||||
SharedSizeGroup="MenuItemText" />
|
||||
<ColumnDefinition Width="Auto"
|
||||
SharedSizeGroup="MenuItemGesture" />
|
||||
<ColumnDefinition Width="14" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ContentPresenter x:Name="Icon"
|
||||
Margin="4 0 6 0"
|
||||
VerticalAlignment="Center"
|
||||
ContentSource="Icon"
|
||||
Visibility="Visible" />
|
||||
|
||||
<ContentPresenter Grid.Column="1"
|
||||
x:Name="Header"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
RecognizesAccessKey="True"
|
||||
ContentSource="Header"
|
||||
Visibility="Visible" />
|
||||
|
||||
<ContentPresenter Grid.Column="2"
|
||||
x:Name="InputGestureText"
|
||||
Margin="32 1 8 1"
|
||||
ContentSource="InputGestureText"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="Visible" />
|
||||
|
||||
<Grid Grid.Column="3"
|
||||
Margin="4 0 6 0"
|
||||
x:Name="ArrowPanel"
|
||||
VerticalAlignment="Center">
|
||||
<Path x:Name="ArrowPanelPath"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
Data="M0,0 L0,8 L4,4 z" />
|
||||
</Grid>
|
||||
|
||||
<Popup AllowsTransparency="True"
|
||||
IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Placement="Right"
|
||||
x:Name="PART_Popup"
|
||||
Focusable="False"
|
||||
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
|
||||
<Border Background="{Binding Path=Background, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"
|
||||
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"
|
||||
BorderThickness="{Binding Path=BorderThickness, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"
|
||||
Margin="0 0 5 5">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="5"
|
||||
Opacity="0.5" />
|
||||
</Border.Effect>
|
||||
<Grid Grid.IsSharedSizeScope="True">
|
||||
<ItemsPresenter x:Name="ItemsPresenter"
|
||||
KeyboardNavigation.DirectionalNavigation="Cycle"
|
||||
Grid.IsSharedSizeScope="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
KeyboardNavigation.TabNavigation="Cycle" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsSuspendingPopupAnimation"
|
||||
Value="True">
|
||||
<Setter Property="PopupAnimation"
|
||||
TargetName="PART_Popup"
|
||||
Value="None" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Role"
|
||||
Value="SubmenuItem">
|
||||
<Setter Property="DockPanel.Dock"
|
||||
Value="Top" />
|
||||
<Setter Property="Visibility"
|
||||
Value="Collapsed"
|
||||
TargetName="ArrowPanel" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Icon"
|
||||
Value="{x:Null}">
|
||||
<Setter Property="Visibility"
|
||||
Value="Collapsed"
|
||||
TargetName="Icon" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="InputGestureText"
|
||||
Value="{x:Null}">
|
||||
<Setter Property="Visibility"
|
||||
Value="Collapsed"
|
||||
TargetName="InputGestureText" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsHighlighted"
|
||||
Value="True">
|
||||
<Setter Property="BorderBrush"
|
||||
TargetName="PART_Border"
|
||||
Value="{DynamicResource HighlightedBorderBrush}" />
|
||||
<Setter Property="Background">
|
||||
<Setter.Value>
|
||||
<SolidColorBrush Opacity="0.2"
|
||||
Color="{DynamicResource FocusedBorderColor}" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="BorderThickness"
|
||||
TargetName="PART_Border"
|
||||
Value="1" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource DisabledForegroundBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ContextMenu}"
|
||||
BasedOn="{StaticResource {x:Type ContextMenu}}">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource ContrastBackgroundBrush}" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="{DynamicResource BorderBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ContextMenu}">
|
||||
<Border SnapsToDevicePixels="True"
|
||||
Margin="0 0 5 5"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Background="{TemplateBinding Background}">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="5"
|
||||
Opacity="0.5" />
|
||||
</Border.Effect>
|
||||
<ItemsPresenter SnapsToDevicePixels="True" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type Expander}"
|
||||
BasedOn="{StaticResource {x:Type Expander}}">
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="Transparent" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Expander}">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
SnapsToDevicePixels="True">
|
||||
<DockPanel LastChildFill="True">
|
||||
<CheckBox ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
|
||||
Content="{TemplateBinding Header}"
|
||||
FontStyle="{TemplateBinding FontStyle}"
|
||||
FontStretch="{TemplateBinding FontStretch}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Tag="{TemplateBinding Tag}"
|
||||
IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
FocusVisualStyle="{StaticResource {x:Static SystemParameters.FocusVisualStyleKey}}"
|
||||
Cursor="Hand"
|
||||
x:Name="PART_Header">
|
||||
<CheckBox.Template>
|
||||
<ControlTemplate TargetType="{x:Type CheckBox}">
|
||||
<Border Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ContentPresenter Content="{TemplateBinding Tag}" />
|
||||
<ContentPresenter SnapsToDevicePixels="True"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</CheckBox.Template>
|
||||
</CheckBox>
|
||||
<ContentPresenter x:Name="PART_Content"
|
||||
Focusable="False"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
Visibility="Collapsed" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsExpanded"
|
||||
Value="True">
|
||||
<Setter Property="Visibility"
|
||||
TargetName="PART_Content"
|
||||
Value="Visible" />
|
||||
<Setter TargetName="PART_Header"
|
||||
Property="Background"
|
||||
Value="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource DisabledForegroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="ExpandDirection"
|
||||
Value="Right">
|
||||
<Setter TargetName="PART_Header"
|
||||
Property="LayoutTransform">
|
||||
<Setter.Value>
|
||||
<RotateTransform Angle="90" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter TargetName="PART_Header"
|
||||
Property="DockPanel.Dock"
|
||||
Value="Left" />
|
||||
<Setter TargetName="PART_Content"
|
||||
Property="DockPanel.Dock"
|
||||
Value="Right" />
|
||||
</Trigger>
|
||||
<Trigger Property="ExpandDirection"
|
||||
Value="Down">
|
||||
<Setter TargetName="PART_Header"
|
||||
Property="DockPanel.Dock"
|
||||
Value="Top" />
|
||||
<Setter TargetName="PART_Content"
|
||||
Property="DockPanel.Dock"
|
||||
Value="Bottom" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
23
Examples/Nodify.Shared/Themes/Dark.xaml
Normal file
23
Examples/Nodify.Shared/Themes/Dark.xaml
Normal file
@@ -0,0 +1,23 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Brushes.xaml" />
|
||||
<ResourceDictionary Source="Controls.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Color x:Key="ForegroundColor">White</Color>
|
||||
<Color x:Key="DisabledForegroundColor">Gray</Color>
|
||||
|
||||
<Color x:Key="BackgroundColor">#333337</Color>
|
||||
<Color x:Key="ContrastBackgroundColor">#1B1B1C</Color>
|
||||
<Color x:Key="HighlightedBackgroundColor">#3F3F46</Color>
|
||||
|
||||
<Color x:Key="BorderColor">#3F3F3F</Color>
|
||||
<Color x:Key="DisabledBorderColor">Gray</Color>
|
||||
<Color x:Key="HighlightedBorderColor">#7EB4EA</Color>
|
||||
<Color x:Key="FocusedBorderColor">#569DE5</Color>
|
||||
|
||||
<Color x:Key="GridLinesColor">#333337</Color>
|
||||
|
||||
</ResourceDictionary>
|
||||
454
Examples/Nodify.Shared/Themes/Generic.xaml
Normal file
454
Examples/Nodify.Shared/Themes/Generic.xaml
Normal file
@@ -0,0 +1,454 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Nodify">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Nodify.Shared;component/Themes/Controls.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/Nodify.Shared;component/Themes/Icons.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<local:ResizeDirectionToVisiblityConverter x:Key="ResizeDirectionToVisiblityConverter" />
|
||||
|
||||
<Style x:Key="EditableTextBlockBaseStyle"
|
||||
TargetType="{x:Type local:EditableTextBlock}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="BorderBrush"
|
||||
Value="DodgerBlue" />
|
||||
<Setter Property="MinHeight"
|
||||
Value="{Binding FontSize, RelativeSource={RelativeSource Self}}" />
|
||||
<Setter Property="Padding"
|
||||
Value="0" />
|
||||
<Setter Property="Foreground"
|
||||
Value="White" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="Cursor"
|
||||
Value="IBeam" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type local:EditableTextBlock}">
|
||||
<Grid VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
|
||||
<TextBlock Text="{Binding Text, ElementName=PART_TextBox}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
TextWrapping="{TemplateBinding TextWrapping}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
TextTrimming="{TemplateBinding TextTrimming}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
x:Name="PART_Text" />
|
||||
|
||||
<TextBox Text="{Binding Text, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
TextWrapping="{TemplateBinding TextWrapping}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
AcceptsReturn="{TemplateBinding AcceptsReturn}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
MaxLength="{TemplateBinding MaxLength}"
|
||||
MinLines="{TemplateBinding MinLines}"
|
||||
MaxLines="{TemplateBinding MinLines}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
AcceptsTab="True"
|
||||
Visibility="Collapsed"
|
||||
Margin="-1"
|
||||
x:Name="PART_TextBox" />
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEditing"
|
||||
Value="True">
|
||||
<Setter TargetName="PART_TextBox"
|
||||
Property="Visibility"
|
||||
Value="Visible" />
|
||||
<Setter TargetName="PART_Text"
|
||||
Property="Visibility"
|
||||
Value="Collapsed" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type local:EditableTextBlock}"
|
||||
BasedOn="{StaticResource EditableTextBlockBaseStyle}" />
|
||||
|
||||
<Style TargetType="{x:Type local:TabControlEx}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type local:TabControlEx}">
|
||||
<Grid KeyboardNavigation.TabNavigation="Local"
|
||||
SnapsToDevicePixels="true"
|
||||
ClipToBounds="true">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Panel.ZIndex="1"
|
||||
Margin="2,2,2,0"
|
||||
Background="{TemplateBinding Background}"
|
||||
KeyboardNavigation.TabIndex="1">
|
||||
<ScrollViewer x:Name="PART_ScrollViewer"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
IsItemsHost="True" />
|
||||
<Button Style="{StaticResource IconButton}"
|
||||
Command="{TemplateBinding AddTabCommand}"
|
||||
Height="34"
|
||||
VerticalAlignment="Bottom"
|
||||
BorderBrush="{DynamicResource HighlightedBackgroundBrush}"
|
||||
Grid.Column="1"
|
||||
ToolTip="Add new tab">
|
||||
<Path Width="25"
|
||||
Height="15"
|
||||
Data="{StaticResource AddGeometry}"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
Stretch="Uniform" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
<Border x:Name="ContentPanel"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
KeyboardNavigation.TabNavigation="Local"
|
||||
KeyboardNavigation.DirectionalNavigation="Contained"
|
||||
KeyboardNavigation.TabIndex="2"
|
||||
Grid.Row="1">
|
||||
<ContentPresenter x:Name="PART_SelectedContentHost"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
ContentSource="SelectedContent" />
|
||||
</Border>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="false">
|
||||
<Setter Property="Opacity"
|
||||
Value=".5" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type local:TabItemEx}">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource BackgroundBrush}" />
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource ForegroundBrush}" />
|
||||
<Setter Property="RenderTransform">
|
||||
<Setter.Value>
|
||||
<ScaleTransform ScaleY="0" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="RenderTransformOrigin"
|
||||
Value="1 1" />
|
||||
<Setter Property="VerticalAlignment"
|
||||
Value="Bottom" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="Padding"
|
||||
Value="7" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type local:TabItemEx}">
|
||||
<Border x:Name="mBorder"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5 5 0 0"
|
||||
Background="{TemplateBinding Background}"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<Grid>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<local:EditableTextBlock Text="{TemplateBinding Header}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<Button x:Name="mCloseBtn"
|
||||
Command="{TemplateBinding CloseTabCommand}"
|
||||
CommandParameter="{TemplateBinding CloseTabCommandParameter}"
|
||||
Visibility="Hidden"
|
||||
Margin="5 0 0 0"
|
||||
Background="{DynamicResource HighlightedBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource BackgroundBrush}"
|
||||
Style="{StaticResource IconButton}"
|
||||
ToolTip="Close Tab">
|
||||
<Path Width="16"
|
||||
Height="8"
|
||||
Data="{StaticResource CloseGeometry}"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
Stretch="Uniform" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver"
|
||||
Value="True">
|
||||
<Setter Property="Visibility"
|
||||
Value="Visible"
|
||||
TargetName="mCloseBtn" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected"
|
||||
Value="True">
|
||||
<Setter Property="TextElement.FontWeight"
|
||||
Value="Bold" />
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource HighlightedBackgroundBrush}" />
|
||||
<Setter Property="Padding"
|
||||
Value="8" />
|
||||
<Setter Property="Visibility"
|
||||
Value="Visible"
|
||||
TargetName="mCloseBtn" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<EventTrigger RoutedEvent="Loaded">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Duration="0:0:.5"
|
||||
From="0"
|
||||
To="1"
|
||||
Storyboard.TargetProperty="(RenderTransform).(ScaleTransform.ScaleY)">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ElasticEase Oscillations="1"
|
||||
Springiness="3"
|
||||
EasingMode="EaseOut" />
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type local:Swatches}">
|
||||
<Style.Resources>
|
||||
<local:MultiValueEqualityConverter x:Key="MultiValueEqualityConverter" />
|
||||
<local:ColorToSolidColorBrushConverter x:Key="ColorToSolidColorBrushConverter" />
|
||||
</Style.Resources>
|
||||
<Setter Property="Background"
|
||||
Value="#1e293b" />
|
||||
<Setter Property="Padding"
|
||||
Value="6" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:Swatches">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
CornerRadius="8">
|
||||
<ItemsControl ItemsSource="{TemplateBinding Colors}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border CornerRadius="50"
|
||||
Padding="1"
|
||||
Margin="3">
|
||||
<Border.Style>
|
||||
<Style TargetType="{x:Type Border}">
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Value="True">
|
||||
<DataTrigger.Binding>
|
||||
<MultiBinding Converter="{StaticResource MultiValueEqualityConverter}">
|
||||
<Binding RelativeSource="{RelativeSource AncestorType=local:Swatches}"
|
||||
Path="SelectedColor"
|
||||
Mode="OneWay" />
|
||||
<Binding Mode="OneWay" />
|
||||
</MultiBinding>
|
||||
</DataTrigger.Binding>
|
||||
<Setter Property="Background"
|
||||
Value="White" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Ellipse Width="24"
|
||||
Height="24"
|
||||
Stroke="#1e293b"
|
||||
Fill="{Binding ., Converter={StaticResource ColorToSolidColorBrushConverter}}"
|
||||
Cursor="Hand" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsEnabled"
|
||||
Value="False">
|
||||
<Setter Property="Opacity"
|
||||
Value="0.7" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type local:ResizablePanel}">
|
||||
<Setter Property="BorderBrush"
|
||||
Value="#1e293b" />
|
||||
<Setter Property="BorderThickness"
|
||||
Value="1" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:ResizablePanel">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<Grid>
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}" />
|
||||
|
||||
<local:Resizer Direction="TopLeft"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=TopLeft}" />
|
||||
|
||||
<local:Resizer Direction="TopRight"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=TopRight}" />
|
||||
|
||||
<local:Resizer Direction="BottomLeft"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Bottom"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=BottomLeft}" />
|
||||
|
||||
<local:Resizer Direction="BottomRight"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=BottomRight}" />
|
||||
|
||||
<local:Resizer Direction="Left"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=Left}" />
|
||||
|
||||
<local:Resizer Direction="Right"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=Right}" />
|
||||
|
||||
<local:Resizer Direction="Top"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=Top}" />
|
||||
|
||||
<local:Resizer Direction="Bottom"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Visibility="{TemplateBinding Directions, Converter={StaticResource ResizeDirectionToVisiblityConverter}, ConverterParameter=Bottom}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type local:Resizer}">
|
||||
<Setter Property="Background"
|
||||
Value="#1e293b" />
|
||||
<Setter Property="Width"
|
||||
Value="6" />
|
||||
<Setter Property="Height"
|
||||
Value="6" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:Resizer">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}" />
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="Direction"
|
||||
Value="TopLeft">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeNWSE" />
|
||||
<Setter Property="Margin"
|
||||
Value="-4 -4 0 0" />
|
||||
</Trigger>
|
||||
<Trigger Property="Direction"
|
||||
Value="TopRight">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeNESW" />
|
||||
<Setter Property="Margin"
|
||||
Value="0 -4 -4 0" />
|
||||
</Trigger>
|
||||
<Trigger Property="Direction"
|
||||
Value="BottomLeft">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeNESW" />
|
||||
<Setter Property="Margin"
|
||||
Value="-4 0 0 -4" />
|
||||
</Trigger>
|
||||
<Trigger Property="Direction"
|
||||
Value="BottomRight">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeNWSE" />
|
||||
<Setter Property="Margin"
|
||||
Value="0 0 -4 -4" />
|
||||
</Trigger>
|
||||
<Trigger Property="Direction"
|
||||
Value="Left">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeWE" />
|
||||
<Setter Property="Margin"
|
||||
Value="-4 0 0 0" />
|
||||
</Trigger>
|
||||
<Trigger Property="Direction"
|
||||
Value="Right">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeWE" />
|
||||
<Setter Property="Margin"
|
||||
Value="0 0 -4 0" />
|
||||
</Trigger>
|
||||
<Trigger Property="Direction"
|
||||
Value="Top">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeNS" />
|
||||
<Setter Property="Margin"
|
||||
Value="0 -4 0 0" />
|
||||
</Trigger>
|
||||
<Trigger Property="Direction"
|
||||
Value="Bottom">
|
||||
<Setter Property="Cursor"
|
||||
Value="SizeNS" />
|
||||
<Setter Property="Margin"
|
||||
Value="0 0 0 -4" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
773
Examples/Nodify.Shared/Themes/Icons.xaml
Normal file
773
Examples/Nodify.Shared/Themes/Icons.xaml
Normal file
@@ -0,0 +1,773 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<Rectangle x:Key="AlignCenterIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M6.0003,-0.000199999999999534L6.0003,3.0008 1.0003,3.0008 1.0003,6.9998 6.0003,6.9998 6.0003,8.9998 1.9993,8.9998 1.9993,13.0008 6.0003,13.0008 6.0003,15.9998 9.0003,15.9998 9.0003,13.0008 12.9993,13.0008 12.9993,8.9998 9.0003,8.9998 9.0003,6.9998 14.0003,6.9998 14.0003,3.0008 9.0003,3.0008 9.0003,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M8,6L8,10 12,10 12,12 8,12 8,15 7,15 7,12 3,12 3,10 7,10 7,6 2,6 2,4 7,4 7,1 8,1 8,4 13,4 13,6z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="AlignMiddleIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M2.9997,1.9996L2.9997,6.9996 -0.000300000000000189,6.9996 -0.000300000000000189,9.9996 2.9997,9.9996 2.9997,15.0006 7.0007,15.0006 7.0007,9.9996 8.9997,9.9996 8.9997,14.0006 12.9997,14.0006 12.9997,9.9996 16.0007,9.9996 16.0007,6.9996 12.9997,6.9996 12.9997,3.0006 8.9997,3.0006 8.9997,6.9996 7.0007,6.9996 7.0007,1.9996z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M6,8L10,8 10,4 12,4 12,8 15,8 15,9 12,9 12,13 10,13 10,9 6,9 6,14 4,14 4,9 1,9 1,8 4,8 4,3 6,3z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="AlignRightIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M12.9996,-0.000199999999999534L12.9996,3.0008 -0.000400000000000844,3.0008 -0.000400000000000844,6.9998 12.9996,6.9998 12.9996,8.9998 2.9996,8.9998 2.9996,13.0008 12.9996,13.0008 12.9996,15.9998 16.0006,15.9998 16.0006,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M13,10L4,10 4,12 13,12z M13,4L1,4 1,6 13,6z M14,1L15,1 15,15 14,15z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="AlignBottomIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M2.9997,-0.000199999999999534L2.9997,13.0008 -0.000300000000000189,13.0008 -0.000300000000000189,15.9998 16.0007,15.9998 16.0007,13.0008 12.9997,13.0008 12.9997,3.0008 8.9997,3.0008 8.9997,13.0008 7.0007,13.0008 7.0007,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M12,4L10,4 10,13 12,13z M6,1L4,1 4,13 6,13z M15,15L1,15 1,14 15,14z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="AlignLeftIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M0,-0.000199999999999534L0,15.9998 3,15.9998 3,13.0008 13,13.0008 13,8.9998 3,8.9998 3,6.9998 16,6.9998 16,3.0008 3,3.0008 3,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M12,10L3,10 3,12 12,12z M15,4L3,4 3,6 15,6z M1,1L2,1 2,15 1,15z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="AlignTopIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M0,-0.000199999999999534L0,4.0008 3,4.0008 3,15.9998 7,15.9998 7,4.0008 9,4.0008 9,12.0008 13,12.0008 13,4.0008 16,4.0008 16,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M10,11L12,11 12,4 10,4z M4,15L6,15 6,4 4,4z M15,3L1,3 1,1 15,1z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="ThemeIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M16,8C16,12.418 12.418,16 8,16 3.582,16 0,12.418 0,8 0,3.582 3.582,0 8,0 12.418,0 16,3.582 16,8" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M7.999,14C7.657,14 7.325,13.965 6.999,13.91 9.836,13.434 12,10.973 12,8 12,5.027 9.836,2.567 6.999,2.09 7.325,2.035 7.657,2 7.999,2 11.312,2 13.999,4.687 13.999,8 13.999,11.313 11.312,14 7.999,14 M7.999,1C4.133,1 0.999,4.134 0.999,8 0.999,11.866 4.133,15 7.999,15 11.865,15 14.999,11.866 14.999,8 14.999,4.134 11.865,1 7.999,1" />
|
||||
<GeometryDrawing Brush="#FFF0EFF1"
|
||||
Geometry="F1M7.999,2C7.657,2 7.325,2.035 6.999,2.09 9.836,2.567 12,5.027 12,8 12,10.973 9.836,13.434 6.999,13.91 7.325,13.965 7.657,14 7.999,14 11.312,14 13.999,11.313 13.999,8 13.999,4.687 11.312,2 7.999,2" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="DiamondFillIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M1.5859,8L7.9999,1.586 14.4139,8 7.9999,14.414z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M4.4141,8L8.0001,4.414 11.5861,8 8.0001,11.586z M8.0001,3L3.0001,8 8.0001,13 13.0001,8z" />
|
||||
<GeometryDrawing Brush="#FFFFCC00"
|
||||
Geometry="F1M8,4.4141L11.586,8.0001 8,11.5861 4.414,8.0001z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="DiamondIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M1.5859,8L7.9999,1.586 14.4139,8 7.9999,14.414z" />
|
||||
<GeometryDrawing Brush="#FFEFEFF0"
|
||||
Geometry="F1M8,4.4141L11.586,8.0001 8,11.5861 4.414,8.0001z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M4.4141,8L8.0001,4.414 11.5861,8 8.0001,11.586z M8.0001,3L3.0001,8 8.0001,13 13.0001,8z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="PlusIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M6.0003,-0.000199999999999534L6.0003,5.9998 0.000300000000000189,5.9998 0.000300000000000189,9.9998 6.0003,9.9998 6.0003,15.9998 10.0003,15.9998 10.0003,9.9998 16.0003,9.9998 16.0003,5.9998 10.0003,5.9998 10.0003,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M15,9L9,9 9,15 7,15 7,9 1,9 1,7 7,7 7,1 9,1 9,7 15,7z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="RemoveKeyIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M13,10L4,10 4,6 13,6z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M12,9L5,9 5,7 12,7z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="AddKeyIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M16,8.4629C16,10.9239 13.997,12.9259 11.537,12.9259 11.118,12.9259 10.704,12.8669 10.3,12.7479L7.704,15.3439C7.595,15.4529 7.003,16.0019 6.147,16.0019 5.767,16.0019 5.2,15.8869 4.657,15.3439 3.538,14.2249 4.043,12.9079 4.657,12.2959L7.252,9.6989C7.133,9.2959 7.073,8.8819 7.073,8.4629 7.073,7.5529 7.35,6.7069 7.82,5.9999L6,5.9999 6,7.9999 2.019,7.9999 2.019,5.9999 0,5.9999 0,2.0179 2.019,2.0179 2.019,-9.99999999979906E-05 6,-9.99999999979906E-05 6,2.0179 8,2.0179 8,5.7719C8.816,4.7019 10.091,3.9999 11.537,3.9999 12.165,3.9999 13.132,4.2889 13.368,4.3999 13.605,4.5099 14.987,5.1659 15.601,6.6309 15.688,6.8399 16,7.8359 16,8.4629" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M14.9873,8.5049C14.9873,10.4339 13.4233,11.9969 11.4953,11.9969 10.9823,11.9969 10.4323,11.9349 9.9953,11.7359L7.1303,14.6149C7.1303,14.6149 6.2573,15.4879 5.3843,14.6149 4.5103,13.7419 5.3843,12.8689 5.3843,12.8689L8.3233,10.0179C8.1263,9.5779 8.0033,9.0169 8.0033,8.5049 8.0033,6.5769 9.5663,5.0139 11.4953,5.0139 12.0063,5.0139 12.5553,5.0849 12.9953,5.2829L10.6223,7.6329 12.3683,9.3789 14.7143,7.0179C14.9113,7.4549,14.9873,7.9939,14.9873,8.5049" />
|
||||
<GeometryDrawing Brush="#FF388A34"
|
||||
Geometry="F1M7,3.0176L5,3.0176 5,0.9996 3.019,0.9996 3.019,3.0176 1,3.0176 1,4.9996 3.019,4.9996 3.019,6.9996 5,6.9996 5,4.9996 7,4.9996z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="ExpandRightIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="F1M6.3906,13.6943L3.9156,11.2193 7.1356,8.0003 3.9156,4.7803 6.3906,2.3053 12.0836,8.0003z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="F1M6.3901,12.2803L5.3291,11.2193 8.5491,8.0003 5.3291,4.7803 6.3901,3.7193 10.6701,8.0003z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="ExpandLeftIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.LayoutTransform>
|
||||
<RotateTransform Angle="180" />
|
||||
</Rectangle.LayoutTransform>
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="F1M6.3906,13.6943L3.9156,11.2193 7.1356,8.0003 3.9156,4.7803 6.3906,2.3053 12.0836,8.0003z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="F1M6.3901,12.2803L5.3291,11.2193 8.5491,8.0003 5.3291,4.7803 6.3901,3.7193 10.6701,8.0003z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="ExpandDownIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M0,0L16,0 16,16 0,16z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="F1M2.3057,6.3906L4.7807,3.9156 7.9997,7.1356 11.2197,3.9156 13.6947,6.3906 7.9997,12.0836z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="F1M3.7197,6.3901L4.7807,5.3291 7.9997,8.5491 11.2197,5.3291 12.2807,6.3901 7.9997,10.6701z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="EditIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M2.5857,-0.000199999999999534L-0.000299999999999745,2.5858 -0.000299999999999745,3.4148 1.0867,4.4998 -0.000299999999999745,5.5858 -0.000299999999999745,12.4148 2.5857,14.9998 13.4147,14.9998 16.0007,12.4148 16.0007,5.5858 13.4147,3.0008 6.4147,3.0008 3.4137,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M13,4L7.414,4 8.414,5 12.586,5 14,6.414 14,11.586 12.586,13 3.414,13 2,11.586 2,6.414 2.358,6.057 2.5,5.914 1.793,5.207 1.624,5.376 1,6 1,12 3,14 13,14 15,12 15,6z" />
|
||||
<GeometryDrawing Brush="#FFF0EFF1"
|
||||
Geometry="F1M12.5858,5L8.4138,5 10.9998,7.586 10.9998,11 7.5858,11 2.4998,5.914 2.3578,6.057 1.9998,6.414 1.9998,11.586 3.4138,13 7.5858,13 12.5858,13 13.4998,12.086 13.6428,11.943 13.9998,11.586 13.9998,6.414z" />
|
||||
<GeometryDrawing Brush="#FF00539C"
|
||||
Geometry="F1M5,3L3,5 7,8.999 9,6.999z" />
|
||||
<GeometryDrawing Brush="#FF00539C"
|
||||
Geometry="F1M4,2L2,4 1,3 3,1z" />
|
||||
<GeometryDrawing Brush="#FF00539C"
|
||||
Geometry="F1M8,10L10,9.999 10,8z" />
|
||||
<GeometryDrawing Brush="#FF00539C"
|
||||
Geometry="F1M5,3L3,5 7,8.999 9,6.999z" />
|
||||
<GeometryDrawing Brush="#FF00539C"
|
||||
Geometry="F1M4,2L2,4 1,3 3,1z" />
|
||||
<GeometryDrawing Brush="#FF00539C"
|
||||
Geometry="F1M8,10L10,9.999 10,8z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="UnpauseIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="F1M4,2L4,14 12,8z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="PauseIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00f6f6f6"
|
||||
Geometry="M16,0V16H0V0Z" />
|
||||
<GeometryDrawing Brush="Transparent"
|
||||
Geometry="M13,2V13H3V2Z" />
|
||||
<GeometryDrawing Brush="#FF0081E4"
|
||||
Geometry="M4,3H7v9H4ZM9,3v9h3V3Z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="ZoomOutIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V16 H16 V0 H0 Z">
|
||||
<GeometryDrawing Geometry="F1 M16,16z M0,0z M16,16L0,16 0,0 16,0 16,16z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FFF6F6F6"
|
||||
Opacity="0" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FF252526"
|
||||
Geometry="F1 M16,16z M0,0z M8.654,11.548C7.969,11.846 7.237,12 6.5,12 3.467,12 1,9.532 1,6.5 1,3.467 3.467,1 6.5,1 9.532,1 12,3.467 12,6.5 12,7.225 11.849,7.948 11.559,8.625L16,13.066 16,13.433 13.437,16 13.107,16 8.654,11.548z" />
|
||||
<GeometryDrawing Brush="#FFC5C5C5"
|
||||
Geometry="F1 M16,16z M0,0z M14.769,13.25L10.338,8.819C10.75,8.14 11,7.352 11,6.5 11,4.015 8.985,2 6.5,2 4.015,2 2,4.015 2,6.5 2,8.985 4.015,11 6.5,11 7.362,11 8.16,10.745 8.844,10.325L13.271,14.75 14.769,13.25z M3,6.5C3,4.567 4.567,3 6.5,3 8.433,3 10,4.567 10,6.5 10,8.433 8.433,10 6.5,10 4.567,10 3,8.433 3,6.5z" />
|
||||
<GeometryDrawing Brush="#FF2A292C"
|
||||
Geometry="F1 M16,16z M0,0z M6.5,3C4.567,3 3,4.567 3,6.5 3,8.433 4.567,10 6.5,10 8.433,10 10,8.433 10,6.5 10,4.567 8.433,3 6.5,3z M4,7L4,6 9,6 9,7 4,7z" />
|
||||
<GeometryDrawing Brush="#FF75BEFF"
|
||||
Geometry="F1 M16,16z M0,0z M9,7L4,7 4,6 9,6 9,7z" />
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="ZoomInIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V16 H16 V0 H0 Z">
|
||||
<GeometryDrawing Geometry="F1 M16,16z M0,0z M16,16L0,16 0,0 16,0 16,16z">
|
||||
<GeometryDrawing.Brush>
|
||||
<SolidColorBrush Color="#FFF6F6F6"
|
||||
Opacity="0" />
|
||||
</GeometryDrawing.Brush>
|
||||
</GeometryDrawing>
|
||||
<GeometryDrawing Brush="#FF252526"
|
||||
Geometry="F1 M16,16z M0,0z M8.654,11.548C7.969,11.846 7.237,12 6.5,12 3.467,12 1,9.532 1,6.5 1,3.467 3.467,1 6.5,1 9.532,1 12,3.467 12,6.5 12,7.225 11.849,7.948 11.559,8.625L16,13.066 16,13.433 13.437,16 13.107,16 8.654,11.548z" />
|
||||
<GeometryDrawing Brush="#FFC5C5C5"
|
||||
Geometry="F1 M16,16z M0,0z M14.769,13.25L10.338,8.819C10.75,8.14 11,7.352 11,6.5 11,4.015 8.985,2 6.5,2 4.015,2 2,4.015 2,6.5 2,8.985 4.015,11 6.5,11 7.362,11 8.16,10.745 8.844,10.325L13.271,14.75 14.769,13.25z M3,6.5C3,4.567 4.567,3 6.5,3 8.433,3 10,4.567 10,6.5 10,8.433 8.433,10 6.5,10 4.567,10 3,8.433 3,6.5z" />
|
||||
<GeometryDrawing Brush="#FF2A292C"
|
||||
Geometry="F1 M16,16z M0,0z M6.5,3C4.567,3 3,4.567 3,6.5 3,8.433 4.567,10 6.5,10 8.433,10 10,8.433 10,6.5 10,4.567 8.433,3 6.5,3z M7,7L7,9 6,9 6,7 4,7 4,6 6,6 6,4 7,4 7,6 9,6 9,7 7,7z" />
|
||||
<GeometryDrawing Brush="#FF75BEFF"
|
||||
Geometry="F1 M16,16z M0,0z M9,6L9,7 7,7 7,9 6,9 6,7 4,7 4,6 6,6 6,4 7,4 7,6 9,6z" />
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="StopIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#F38B76"
|
||||
Geometry="F1M13,13L3,13 3,3 13,3z" />
|
||||
<GeometryDrawing Brush="#F38B76"
|
||||
Geometry="F1M12,12L4,12 4,4 12,4z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="RunIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#8DD28A"
|
||||
Geometry="F1M4,2L4,14 12,8z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="AddStateIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M1.9998,-0.000199999999999534L1.9998,1.9998 -0.000199999999999978,1.9998 -0.000199999999999978,5.9998 1.9998,5.9998 1.9998,13.4148 3.5858,14.9998 5.4148,14.9998 6.9998,13.4148 6.9998,12.0008 14.4148,12.0008 15.9998,10.4138 15.9998,6.5858 14.4148,4.9998 7.9998,4.9998 7.9998,1.9998 6.0008,1.9998 6.0008,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M15,7L15,10 14,11 6,11 6,13 5,14 4,14 3,13 3,8 4,8 4,13 5,13 5,10 14,10 14,7 6,7 6,6 14,6z" />
|
||||
<GeometryDrawing Brush="#FFF0EFF1"
|
||||
Geometry="F1M14,7L14,10 5,10 5,13 4,13 4,8 6,8 6,7z" />
|
||||
<GeometryDrawing Brush="#FF388A34"
|
||||
Geometry="F1M3,5L1,5 1,3 3,3 3,1 5,1 5,3 7,3 7,5 5,5 5,7 3,7z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="RenameIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M0,0.999700000000001L0,14.0007 8,14.0007 8,13.0007 16,13.0007 16,4.0007 8,4.0007 8,0.999700000000001z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,13L3,13 3,11 1,11z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M3,11L5,11 5,4 3,4z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M7,11L5,11 5,13 7,13z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,4L3,4 3,2 1,2z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,6L2,6 2,5 1,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,8L2,8 2,7 1,7z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M6,6L7,6 7,5 6,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M5,4L7,4 7,2 5,2z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,10L2,10 2,9 1,9z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M8,6L9,6 9,5 8,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M14,10L15,10 15,9 14,9z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M14,8L15,8 15,7 14,7z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M14,12L15,12 15,10.999 14,10.999z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M14,6L15,6 15,5 14,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M12,12L13,12 13,10.999 12,10.999z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M12,6L13,6 13,5 12,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M10,12L11,12 11,10.999 10,10.999z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M10,6L11,6 11,5 10,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M8,12L9,12 9,10.999 8,10.999z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="DeleteIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V511.992 H511.992 V0 H0 Z">
|
||||
<DrawingGroup.Transform>
|
||||
<TranslateTransform X="3.5762786865234375E-07"
|
||||
Y="3.5762786865234375E-07" />
|
||||
</DrawingGroup.Transform>
|
||||
<GeometryDrawing Brush="#FFE76E54"
|
||||
Geometry="F1 M511.992,511.992z M0,0z M415.402344,495.421875L255.996094,336.011719 96.589844,495.421875C74.492188,517.515625 38.667969,517.515625 16.570312,495.421875 -5.52343799999997,473.324219 -5.52343799999997,437.5 16.570312,415.402344L175.980469,255.996094 16.570312,96.589844C-5.52343799999997,74.492188 -5.52343799999997,38.667969 16.570312,16.570312 38.667969,-5.52343800000003 74.492188,-5.52343800000003 96.589844,16.570312L255.996094,175.980469 415.402344,16.570312C437.5,-5.52343800000003 473.324219,-5.52343800000003 495.421875,16.570312 517.515625,38.667969 517.515625,74.492188 495.421875,96.589844L336.011719,255.996094 495.421875,415.402344C517.515625,437.5 517.515625,473.324219 495.421875,495.421875 473.324219,517.515625 437.5,517.515625 415.402344,495.421875z M415.402344,495.421875" />
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="DisconnectIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M7.0002,-0.000199999999999534L7.0002,0.6468 6.3532,-0.000199999999999534 5.5252,-0.000199999999999534 3.9702,1.5558 2.4142,-0.000199999999999534 1.5862,-0.000199999999999534 0.000200000000000422,1.5858 0.000200000000000422,2.5348 1.4952,4.0298 0.000200000000000422,5.5258 0.000200000000000422,6.4748 1.5252,7.9998 1.0002,7.9998 1.0002,15.9998 10.0002,15.9998 10.0002,13.9998 14.0002,13.9998 14.0002,7.9998 16.0002,7.9998 16.0002,-0.000199999999999534z M6.4442,4.0298L7.0002,3.4748 7.0002,4.5858z M3.9702,6.5048L5.4652,7.9998 2.4752,7.9998z M7.0002,7.4138L7.0002,7.9998 6.4142,7.9998z M10.0002,7.9998L11.0002,7.9998 11.0002,10.9998 10.0002,10.9998z" />
|
||||
<GeometryDrawing Brush="#FF424242"
|
||||
Geometry="F1M14,6L9,6 9,3 14,3z M8,14L3,14 3,11 8,11z M8,1L8,7 12,7 12,12 9,12 9,9 2,9 2,15 9,15 9,13 13,13 13,7 15,7 15,1z" />
|
||||
<GeometryDrawing Brush="#FFEFEFF0"
|
||||
Geometry="F1M9,6L14,6 14,3 9,3z M3,11L8,11 8,14 3,14z" />
|
||||
<GeometryDrawing Brush="#FFA1260D"
|
||||
Geometry="F1M3.9699,2.9698L1.9999,0.999799999999999 0.9399,2.0608 2.9089,4.0298 0.9399,5.9998 1.9999,7.0598 3.9699,5.0908 5.9389,7.0598 6.9999,5.9998 5.0299,4.0298 6.9999,2.0608 5.9389,0.999799999999999z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="SelectAllIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="F1M16,16L0,16 0,0 16,0z" />
|
||||
<GeometryDrawing Brush="#FFF6F6F6"
|
||||
Geometry="F1M0,-0.000199999999999534L0,13.0008 6,13.0008 6,14.9998 7.649,14.9998 8.337,14.2448 9.115,15.9998 9.983,15.9998 12.269,14.9598 11.406,13.0008 15,13.0008 15,-0.000199999999999534z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M8.4141,7L9.4141,8 11.0001,8 11.0001,7z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,12L2,12 2,10.999 1,10.999z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,2L2,2 2,1 1,1z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,10L2,10 2,9 1,9z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,6L2,6 2,5 1,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,4L2,4 2,3 1,3z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M1,8L2,8 2,7 1,7z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M9,2L10,2 10,1 9,1z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M7,2L8,2 8,1 7,1z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M5,2L6,2 6,1 5,1z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M3,2L4,2 4,1 3,1z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M3,6L10,6 10,5 3,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M13,4L14.001,4 14.001,3 13,3z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M13,10L14.001,10 14.001,9 13,9z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M3,12L4,12 4,10.999 3,10.999z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M12.9996,10.9996L12.9996,11.5856 13.4146,12.0006 14.0006,12.0006 14.0006,10.9996z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M13,6L14.001,6 14.001,5 13,5z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M13,2L14.001,2 14.001,1 13,1z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M13,8L14.001,8 14.001,7 13,7z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M11,2L12,2 12,1 11,1z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M3,8L6.001,8 6.001,7 3,7z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M5,12L6,12 6,10.999 5,10.999z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M3,4L12,4 12,3 3,3z" />
|
||||
<GeometryDrawing Brush="#FF414141"
|
||||
Geometry="F1M10.9551,14.459L9.8691,11.994 12.3871,11.994 7.0001,6.996 7.0001,14.228 8.6291,12.438 9.7661,15z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="LockIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="M16,16H0V0H16Z" />
|
||||
<GeometryDrawing Brush="#0A212121"
|
||||
Geometry="M2.5,14.5h10v-8H2.5Z" />
|
||||
<GeometryDrawing Brush="#FF212121"
|
||||
Geometry="M8,12H7V9H8Z" />
|
||||
<GeometryDrawing Brush="#FF212121"
|
||||
Geometry="M12.5,6H11V4.536a3.5,3.5,0,0,0-7,0V6H2.5L2,6.5v8l.5.5h10l.5-.5v-8ZM5,4.536a2.5,2.5,0,0,1,5,0V6H5ZM12,14H3V7h9Z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Rectangle x:Key="UnlockIcon"
|
||||
x:Shared="False"
|
||||
Width="16"
|
||||
Height="16">
|
||||
<Rectangle.Fill>
|
||||
<DrawingBrush>
|
||||
<DrawingBrush.Drawing>
|
||||
<DrawingGroup>
|
||||
<DrawingGroup.Children>
|
||||
<GeometryDrawing Brush="#00FFFFFF"
|
||||
Geometry="M16,16H0V0H16Z" />
|
||||
<GeometryDrawing Brush="#0A212121"
|
||||
Geometry="M1.5,14.5h10v-8H1.5Z" />
|
||||
<GeometryDrawing Brush="#FF212121"
|
||||
Geometry="M7,12H6V9H7Z" />
|
||||
<GeometryDrawing Brush="#FF212121"
|
||||
Geometry="M12.5,1.036A3.5,3.5,0,0,0,9,4.536V6H1.5L1,6.5v8l.5.5h10l.5-.5v-8L11.5,6H10V4.536a2.5,2.5,0,0,1,5,0V5h1V4.536A3.5,3.5,0,0,0,12.5,1.036ZM11,7v7H2V7Z" />
|
||||
</DrawingGroup.Children>
|
||||
</DrawingGroup>
|
||||
</DrawingBrush.Drawing>
|
||||
</DrawingBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<PathGeometry x:Key="CloseGeometry"
|
||||
x:Shared="False"
|
||||
Figures="M9.15625 6.3125L6.3125 9.15625L22.15625 25L6.21875 40.96875L9.03125 43.78125L25 27.84375L40.9375 43.78125L43.78125 40.9375L27.84375 25L43.6875 9.15625L40.84375 6.3125L25 22.15625Z" />
|
||||
|
||||
<PathGeometry x:Key="AddGeometry"
|
||||
x:Shared="False"
|
||||
Figures="M15 5L15 15L5 15L5 17L15 17L15 27L17 27L17 17L27 17L27 15L17 15L17 5Z" />
|
||||
|
||||
</ResourceDictionary>
|
||||
23
Examples/Nodify.Shared/Themes/Light.xaml
Normal file
23
Examples/Nodify.Shared/Themes/Light.xaml
Normal file
@@ -0,0 +1,23 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Brushes.xaml" />
|
||||
<ResourceDictionary Source="Controls.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Color x:Key="ForegroundColor">Black</Color>
|
||||
<Color x:Key="DisabledForegroundColor">Gray</Color>
|
||||
|
||||
<Color x:Key="BackgroundColor">#D4DCF2</Color>
|
||||
<Color x:Key="ContrastBackgroundColor">#CCD6ED</Color>
|
||||
<Color x:Key="HighlightedBackgroundColor">#B1C5FF</Color>
|
||||
|
||||
<Color x:Key="BorderColor">#CBCCDF</Color>
|
||||
<Color x:Key="DisabledBorderColor">Gray</Color>
|
||||
<Color x:Key="HighlightedBorderColor">#7EB4EA</Color>
|
||||
<Color x:Key="FocusedBorderColor">#569DE5</Color>
|
||||
|
||||
<Color x:Key="GridLinesColor">#7EB4EA</Color>
|
||||
|
||||
</ResourceDictionary>
|
||||
23
Examples/Nodify.Shared/Themes/Nodify.xaml
Normal file
23
Examples/Nodify.Shared/Themes/Nodify.xaml
Normal file
@@ -0,0 +1,23 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Brushes.xaml" />
|
||||
<ResourceDictionary Source="Controls.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Color x:Key="ForegroundColor">White</Color>
|
||||
<Color x:Key="DisabledForegroundColor">Gray</Color>
|
||||
|
||||
<Color x:Key="BackgroundColor">#4C3180</Color>
|
||||
<Color x:Key="ContrastBackgroundColor">#451E63</Color>
|
||||
<Color x:Key="HighlightedBackgroundColor">#662D91</Color>
|
||||
|
||||
<Color x:Key="BorderColor">#662D91</Color>
|
||||
<Color x:Key="DisabledBorderColor">Gray</Color>
|
||||
<Color x:Key="HighlightedBorderColor">#7EB4EA</Color>
|
||||
<Color x:Key="FocusedBorderColor">#569DE5</Color>
|
||||
|
||||
<Color x:Key="GridLinesColor">#4C3180</Color>
|
||||
|
||||
</ResourceDictionary>
|
||||
215
Examples/Nodify.Shared/UndoRedo/ActionsHistory.cs
Normal file
215
Examples/Nodify.Shared/UndoRedo/ActionsHistory.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Nodify.UndoRedo
|
||||
{
|
||||
public interface IActionsHistory : INotifyPropertyChanged
|
||||
{
|
||||
int MaxSize { get; set; }
|
||||
bool CanUndo { get; }
|
||||
bool CanRedo { get; }
|
||||
bool IsEnabled { get; set; }
|
||||
IAction? Current { get; }
|
||||
|
||||
void Undo();
|
||||
void Redo();
|
||||
|
||||
void Clear();
|
||||
|
||||
/// <summary>
|
||||
/// All future modifications will be merged together to create a single history item until batch is disposed.
|
||||
/// </summary>
|
||||
IDisposable Batch(string? label = default);
|
||||
|
||||
void Record(IAction action);
|
||||
|
||||
/// <summary>
|
||||
/// All future modifications will be merged together to create a single history item until history is resumed.
|
||||
/// </summary>
|
||||
void Pause(string? label = default);
|
||||
|
||||
/// <summary>Each future modifications will create a new history item.</summary>
|
||||
void Resume();
|
||||
}
|
||||
|
||||
public interface IAction
|
||||
{
|
||||
string? Label { get; }
|
||||
|
||||
void Execute();
|
||||
void Undo();
|
||||
}
|
||||
|
||||
public static class ActionsHistoryExtensions
|
||||
{
|
||||
public static void Record(this IActionsHistory history, Action execute, Action unexecute, string? label = default)
|
||||
=> history.Record(new DelegateAction(execute, unexecute, label));
|
||||
|
||||
public static void ExecuteAction(this IActionsHistory history, IAction action)
|
||||
{
|
||||
history.Record(action);
|
||||
action.Execute();
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionsHistory : IActionsHistory
|
||||
{
|
||||
private readonly List<IAction> _history = new List<IAction>();
|
||||
private readonly List<IAction> _batchHistory = new List<IAction>();
|
||||
private int _position = -1;
|
||||
private bool _isApplyingOperation = false;
|
||||
private string? _batchLabel;
|
||||
private int _batchDepth;
|
||||
|
||||
private static readonly PropertyChangedEventArgs _canRedoArgs = new PropertyChangedEventArgs(nameof(CanRedo));
|
||||
private static readonly PropertyChangedEventArgs _canUndoArgs = new PropertyChangedEventArgs(nameof(CanUndo));
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
public static readonly ActionsHistory Global = new ActionsHistory();
|
||||
|
||||
public bool IsBatching { get; private set; }
|
||||
|
||||
public int MaxSize { get; set; } = 50;
|
||||
|
||||
public bool CanRedo => _history.Count > 0 && _position < _history.Count - 1;
|
||||
|
||||
public bool CanUndo => _position > -1;
|
||||
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
|
||||
public IAction? Current => CanUndo ? _history[_position] : null;
|
||||
|
||||
public IDisposable Batch(string? label = default)
|
||||
=> new BatchOperation(label, this);
|
||||
|
||||
public void Record(IAction op)
|
||||
{
|
||||
// Prevent recording the undo or redo operation
|
||||
if (_isApplyingOperation || !IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsBatching)
|
||||
{
|
||||
_batchHistory.Add(op);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddToUndoStack(op);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddToUndoStack(IAction op)
|
||||
{
|
||||
if (_position < _history.Count - 1)
|
||||
{
|
||||
_history.RemoveRange(_position + 1, _history.Count - _position - 1);
|
||||
}
|
||||
|
||||
if (_history.Count >= MaxSize)
|
||||
{
|
||||
_history.RemoveAt(0);
|
||||
_position--;
|
||||
}
|
||||
|
||||
_history.Add(op);
|
||||
_position++;
|
||||
|
||||
PropertyChanged?.Invoke(this, _canRedoArgs);
|
||||
PropertyChanged?.Invoke(this, _canUndoArgs);
|
||||
}
|
||||
|
||||
public void Undo()
|
||||
{
|
||||
if (IsBatching)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(Undo)} is not allowed during a batch.");
|
||||
}
|
||||
|
||||
if (CanUndo)
|
||||
{
|
||||
var op = _history[_position];
|
||||
_isApplyingOperation = true;
|
||||
op.Undo();
|
||||
_isApplyingOperation = false;
|
||||
_position--;
|
||||
}
|
||||
}
|
||||
|
||||
public void Redo()
|
||||
{
|
||||
if (IsBatching)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(Redo)} is not allowed during a batch.");
|
||||
}
|
||||
|
||||
if (CanRedo)
|
||||
{
|
||||
_position++;
|
||||
var op = _history[_position];
|
||||
_isApplyingOperation = true;
|
||||
op.Execute();
|
||||
_isApplyingOperation = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_history.Clear();
|
||||
_batchHistory.Clear();
|
||||
}
|
||||
|
||||
public void Pause(string? label = default)
|
||||
{
|
||||
if (_batchDepth > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_batchLabel = label;
|
||||
IsBatching = true;
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
if (_batchDepth > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_batchHistory.Count > 0)
|
||||
{
|
||||
AddToUndoStack(new BatchAction(_batchLabel, _batchHistory));
|
||||
_batchHistory.Clear();
|
||||
}
|
||||
|
||||
_batchLabel = null;
|
||||
IsBatching = false;
|
||||
}
|
||||
|
||||
private class BatchOperation : IDisposable
|
||||
{
|
||||
private readonly ActionsHistory _history;
|
||||
private bool _disposed;
|
||||
|
||||
public BatchOperation(string? label, ActionsHistory history)
|
||||
{
|
||||
_history = history;
|
||||
_history.Pause(label);
|
||||
_history._batchDepth++;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
_history._batchDepth--;
|
||||
_history.Resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Examples/Nodify.Shared/UndoRedo/BatchAction.cs
Normal file
37
Examples/Nodify.Shared/UndoRedo/BatchAction.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Nodify.UndoRedo
|
||||
{
|
||||
public class BatchAction : IAction
|
||||
{
|
||||
public BatchAction(string? label, IEnumerable<IAction> history)
|
||||
{
|
||||
History = history.Reverse().ToList();
|
||||
Label = label;
|
||||
}
|
||||
|
||||
public IReadOnlyList<IAction> History { get; }
|
||||
|
||||
public string? Label { get; }
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
for (int i = History.Count - 1; i >= 0; i--)
|
||||
{
|
||||
History[i].Execute();
|
||||
}
|
||||
}
|
||||
|
||||
public void Undo()
|
||||
{
|
||||
for (int i = 0; i < History.Count; i++)
|
||||
{
|
||||
History[i].Undo();
|
||||
}
|
||||
}
|
||||
|
||||
public override string? ToString()
|
||||
=> Label;
|
||||
}
|
||||
}
|
||||
25
Examples/Nodify.Shared/UndoRedo/DelegateAction.cs
Normal file
25
Examples/Nodify.Shared/UndoRedo/DelegateAction.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace Nodify.UndoRedo
|
||||
{
|
||||
public class DelegateAction : IAction
|
||||
{
|
||||
private readonly Action _execute;
|
||||
private readonly Action _undo;
|
||||
|
||||
public string? Label { get; }
|
||||
|
||||
public DelegateAction(Action apply, Action unapply, string? label)
|
||||
{
|
||||
_execute = apply;
|
||||
_undo = unapply;
|
||||
Label = label;
|
||||
}
|
||||
|
||||
public void Execute() => _execute();
|
||||
public void Undo() => _undo();
|
||||
|
||||
public override string? ToString()
|
||||
=> Label;
|
||||
}
|
||||
}
|
||||
84
Examples/Nodify.Shared/UndoRedo/PropertyCache.cs
Normal file
84
Examples/Nodify.Shared/UndoRedo/PropertyCache.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Nodify.UndoRedo
|
||||
{
|
||||
public interface IPropertyAccessor
|
||||
{
|
||||
object? GetValue(object instance);
|
||||
void SetValue(object instance, object? value);
|
||||
bool CanRead { get; }
|
||||
bool CanWrite { get; }
|
||||
}
|
||||
|
||||
public sealed class PropertyAccessor<TInstanceType, TPropertyType> : IPropertyAccessor where TInstanceType : class
|
||||
{
|
||||
private readonly Func<TInstanceType, TPropertyType> _getter;
|
||||
private readonly Action<TInstanceType, TPropertyType> _setter;
|
||||
|
||||
public bool CanRead { get; }
|
||||
public bool CanWrite { get; }
|
||||
|
||||
public PropertyAccessor(Func<TInstanceType, TPropertyType> getter, Action<TInstanceType, TPropertyType> setter)
|
||||
{
|
||||
_getter = getter;
|
||||
_setter = setter;
|
||||
|
||||
CanRead = getter != null;
|
||||
CanWrite = setter != null;
|
||||
}
|
||||
|
||||
public object? GetValue(object instance)
|
||||
=> _getter((TInstanceType)instance);
|
||||
|
||||
public void SetValue(object instance, object? value)
|
||||
=> _setter((TInstanceType)instance, (TPropertyType)value!);
|
||||
}
|
||||
|
||||
public class PropertyCache
|
||||
{
|
||||
private static readonly Dictionary<string, IPropertyAccessor> _properties = new Dictionary<string, IPropertyAccessor>();
|
||||
|
||||
public static IPropertyAccessor Get(Type type, string name)
|
||||
{
|
||||
string propKey = $"{type.FullName}.{name}";
|
||||
if (!_properties.TryGetValue(propKey, out var result))
|
||||
{
|
||||
var prop = type.GetProperty(name);
|
||||
result = Create(type, prop!);
|
||||
|
||||
_properties.Add(propKey, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IPropertyAccessor Get<T>(string name)
|
||||
=> Get(typeof(T), name);
|
||||
|
||||
private static IPropertyAccessor Create(Type type, PropertyInfo property)
|
||||
{
|
||||
Delegate? getterInvocation = default;
|
||||
Delegate? setterInvocation = default;
|
||||
|
||||
if (property.CanRead)
|
||||
{
|
||||
MethodInfo getMethod = property.GetGetMethod(true)!;
|
||||
Type getterType = typeof(Func<,>).MakeGenericType(type, property.PropertyType);
|
||||
getterInvocation = Delegate.CreateDelegate(getterType, getMethod);
|
||||
}
|
||||
|
||||
if (property.CanWrite)
|
||||
{
|
||||
MethodInfo setMethod = property.GetSetMethod(true)!;
|
||||
Type setterType = typeof(Action<,>).MakeGenericType(type, property.PropertyType);
|
||||
setterInvocation = Delegate.CreateDelegate(setterType, setMethod);
|
||||
}
|
||||
|
||||
Type adapterType = typeof(PropertyAccessor<,>).MakeGenericType(type, property.PropertyType);
|
||||
|
||||
return (IPropertyAccessor)Activator.CreateInstance(adapterType, getterInvocation, setterInvocation)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
80
Examples/Nodify.Shared/UndoRedo/Undoable.cs
Normal file
80
Examples/Nodify.Shared/UndoRedo/Undoable.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Expression = System.Linq.Expressions.Expression;
|
||||
|
||||
namespace Nodify.UndoRedo
|
||||
{
|
||||
[Flags]
|
||||
public enum PropertyFlags
|
||||
{
|
||||
Disable = 0,
|
||||
Enable = 1
|
||||
}
|
||||
|
||||
public abstract class Undoable : ObservableObject
|
||||
{
|
||||
private readonly HashSet<string> _trackedProperties = new HashSet<string>();
|
||||
|
||||
public IActionsHistory History { get; }
|
||||
|
||||
private void RecordHistory<TPropType>(string propName, TPropType previous, TPropType current)
|
||||
{
|
||||
if (_trackedProperties.Contains(propName))
|
||||
{
|
||||
var prop = PropertyCache.Get(GetType(), propName);
|
||||
History.Record(() => prop.SetValue(this, current), () => prop.SetValue(this, previous), propName);
|
||||
}
|
||||
}
|
||||
|
||||
protected void RecordProperty(string propName, PropertyFlags flags = PropertyFlags.Enable)
|
||||
{
|
||||
if (flags == PropertyFlags.Disable)
|
||||
{
|
||||
_trackedProperties.Remove(propName);
|
||||
}
|
||||
else if (flags.HasFlag(PropertyFlags.Enable))
|
||||
{
|
||||
_trackedProperties.Add(propName);
|
||||
}
|
||||
}
|
||||
|
||||
protected void RecordProperty<TType>(Expression<Func<TType, object?>> selector, PropertyFlags flags = PropertyFlags.Enable)
|
||||
{
|
||||
string name = GetPropertyName(selector);
|
||||
RecordProperty(name, flags);
|
||||
}
|
||||
|
||||
private static string GetPropertyName(Expression memberAccess)
|
||||
=> memberAccess switch
|
||||
{
|
||||
LambdaExpression lambda => GetPropertyName(lambda.Body),
|
||||
MemberExpression mbr => mbr.Member.Name,
|
||||
UnaryExpression unary => GetPropertyName(unary.Operand),
|
||||
_ => throw new Exception($"Member name could not be extracted from {memberAccess}.")
|
||||
};
|
||||
|
||||
protected override bool SetProperty<TPropType>(ref TPropType field, TPropType value, [CallerMemberName] string propertyName = "")
|
||||
{
|
||||
TPropType prev = field;
|
||||
if (base.SetProperty(ref field, value, propertyName))
|
||||
{
|
||||
RecordHistory(propertyName, prev, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Undoable()
|
||||
{
|
||||
History = ActionsHistory.Global;
|
||||
}
|
||||
|
||||
public Undoable(IActionsHistory history)
|
||||
{
|
||||
History = history;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user