Refactor how data context is handled
This commit is contained in:
Родитель
d15749f724
Коммит
16bfdd230d
|
@ -201,10 +201,12 @@ public partial class MainViewViewModel : ViewModelBase
|
|||
{
|
||||
var control = new DrawingNode
|
||||
{
|
||||
DataContext = Editor.Drawing
|
||||
DrawingSource = Editor.Drawing,
|
||||
Width = Editor.Drawing.Width,
|
||||
Height = Editor.Drawing.Height,
|
||||
};
|
||||
|
||||
var root = new ExportRoot()
|
||||
var root = new ExportRoot
|
||||
{
|
||||
Width = Editor.Drawing.Width,
|
||||
Height = Editor.Drawing.Height,
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
</UserControl.KeyBindings>
|
||||
<DockPanel>
|
||||
<views:MenuView ZoomControl="{Binding #EditorControl.ZoomControl}"
|
||||
DrawingNode="{Binding #EditorControl.DrawingNode}"
|
||||
x:CompileBindings="False"
|
||||
DockPanel.Dock="Top" />
|
||||
<Separator IsVisible="False" Classes="horizontal" DockPanel.Dock="Top" />
|
||||
|
@ -92,23 +91,12 @@
|
|||
IsVisible="{Binding IsToolboxVisible}">
|
||||
<Separator Classes="vertical" DockPanel.Dock="Right" />
|
||||
<editor:Toolbox TemplatesSource="{Binding Editor.Templates}"
|
||||
Drawing="{Binding Editor.Drawing}"
|
||||
Name="ToolboxView" />
|
||||
</DockPanel>
|
||||
<ThemeVariantScope RequestedThemeVariant="Light"
|
||||
Grid.Column="1" Grid.ColumnSpan="2">
|
||||
<editor:Editor Name="EditorControl"
|
||||
DataContext="{Binding Editor.Drawing, FallbackValue={x:Null}}"
|
||||
DrawingWidth="{Binding Width}"
|
||||
DrawingHeight="{Binding Height}"
|
||||
NodesSource="{Binding Nodes}"
|
||||
ConnectorsSource="{Binding Connectors}"
|
||||
EnableSnap="{Binding Settings.EnableSnap}"
|
||||
SnapX="{Binding Settings.SnapX}"
|
||||
SnapY="{Binding Settings.SnapY}"
|
||||
EnableGrid="{Binding Settings.EnableGrid}"
|
||||
GridCellWidth="{Binding Settings.GridCellWidth}"
|
||||
GridCellHeight="{Binding Settings.GridCellHeight}"/>
|
||||
DrawingSource="{Binding Editor.Drawing, FallbackValue={x:Null}}" />
|
||||
</ThemeVariantScope>
|
||||
<GridSplitter Grid.Column="1" Background="Transparent" />
|
||||
</Grid>
|
||||
|
|
|
@ -8,10 +8,7 @@ public partial class MenuView : UserControl
|
|||
{
|
||||
public static readonly StyledProperty<NodeZoomBorder?> ZoomControlProperty =
|
||||
AvaloniaProperty.Register<MenuView, NodeZoomBorder?>(nameof(ZoomControl));
|
||||
|
||||
public static readonly StyledProperty<DrawingNode?> DrawingNodeProperty =
|
||||
AvaloniaProperty.Register<MenuView, DrawingNode?>(nameof(DrawingNode));
|
||||
|
||||
|
||||
public MenuView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -22,10 +19,4 @@ public partial class MenuView : UserControl
|
|||
get => GetValue(ZoomControlProperty);
|
||||
set => SetValue(ZoomControlProperty, value);
|
||||
}
|
||||
|
||||
public DrawingNode? DrawingNode
|
||||
{
|
||||
get => GetValue(DrawingNodeProperty);
|
||||
set => SetValue(DrawingNodeProperty, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,15 @@ namespace NodeEditor.Behaviors;
|
|||
|
||||
public class ConnectorsSelectedBehavior : Behavior<ItemsControl>
|
||||
{
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<ConnectorsSelectedBehavior, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
private IDisposable? _dataContextDisposable;
|
||||
private IDrawingNode? _drawingNode;
|
||||
|
||||
|
@ -66,7 +75,7 @@ public class ConnectorsSelectedBehavior : Behavior<ItemsControl>
|
|||
|
||||
private void DrawingNode_SelectionChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (AssociatedObject?.DataContext is not IDrawingNode)
|
||||
if (DrawingSource is not IDrawingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,18 @@ namespace NodeEditor.Behaviors;
|
|||
|
||||
public class DrawingDropHandler : DefaultDropHandler
|
||||
{
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingDropHandler, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public static readonly StyledProperty<Control?> RelativeToProperty =
|
||||
AvaloniaProperty.Register<DrawingDropHandler, Control?>(nameof(RelativeTo));
|
||||
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
public Control? RelativeTo
|
||||
{
|
||||
get => GetValue(RelativeToProperty);
|
||||
|
@ -27,9 +36,9 @@ public class DrawingDropHandler : DefaultDropHandler
|
|||
}
|
||||
var point = GetPosition(relativeTo, e);
|
||||
|
||||
if (relativeTo is DrawingNode drawingNode)
|
||||
if (relativeTo is DrawingNode { DrawingSource: not null } drawingNode)
|
||||
{
|
||||
point = SnapHelper.Snap(point, drawingNode.SnapX, drawingNode.SnapY, drawingNode.EnableSnap);
|
||||
point = SnapHelper.Snap(point, drawingNode.DrawingSource.Settings.SnapX, drawingNode.DrawingSource.Settings.SnapY, drawingNode.DrawingSource.Settings.EnableSnap);
|
||||
}
|
||||
|
||||
if (e.Data.Contains(DataFormats.Text))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Xaml.Interactivity;
|
||||
|
@ -8,6 +9,15 @@ namespace NodeEditor.Behaviors;
|
|||
|
||||
public class DrawingMovedBehavior : Behavior<ItemsControl>
|
||||
{
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingMovedBehavior, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
@ -30,7 +40,7 @@ public class DrawingMovedBehavior : Behavior<ItemsControl>
|
|||
|
||||
private void Moved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
if (AssociatedObject?.DataContext is not IDrawingNode drawingNode)
|
||||
if (DrawingSource is not IDrawingNode drawingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Xaml.Interactivity;
|
||||
|
@ -8,6 +9,15 @@ namespace NodeEditor.Behaviors;
|
|||
|
||||
public class DrawingPressedBehavior : Behavior<ItemsControl>
|
||||
{
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingPressedBehavior, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
@ -35,7 +45,7 @@ public class DrawingPressedBehavior : Behavior<ItemsControl>
|
|||
return;
|
||||
}
|
||||
|
||||
if (AssociatedObject?.DataContext is not IDrawingNode drawingNode)
|
||||
if (DrawingSource is not IDrawingNode drawingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -12,21 +12,15 @@ namespace NodeEditor.Behaviors;
|
|||
|
||||
public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
||||
{
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingSelectionBehavior, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public static readonly StyledProperty<Control?> InputSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingSelectionBehavior, Control?>(nameof(InputSource));
|
||||
|
||||
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
|
||||
AvaloniaProperty.Register<DrawingSelectionBehavior, Canvas?>(nameof(AdornerCanvas));
|
||||
|
||||
public static readonly StyledProperty<bool> EnableSnapProperty =
|
||||
AvaloniaProperty.Register<DrawingSelectionBehavior, bool>(nameof(EnableSnap));
|
||||
|
||||
public static readonly StyledProperty<double> SnapXProperty =
|
||||
AvaloniaProperty.Register<DrawingSelectionBehavior, double>(nameof(SnapX), 1.0);
|
||||
|
||||
public static readonly StyledProperty<double> SnapYProperty =
|
||||
AvaloniaProperty.Register<DrawingSelectionBehavior, double>(nameof(SnapY), 1.0);
|
||||
|
||||
private IDisposable? _dataContextDisposable;
|
||||
private IDrawingNode? _drawingNode;
|
||||
private SelectionAdorner? _selectionAdorner;
|
||||
|
@ -36,6 +30,12 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
private Rect _selectedRect;
|
||||
private Control? _inputSource;
|
||||
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
public Control? InputSource
|
||||
{
|
||||
get => GetValue(InputSourceProperty);
|
||||
|
@ -48,24 +48,6 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
set => SetValue(AdornerCanvasProperty, value);
|
||||
}
|
||||
|
||||
public bool EnableSnap
|
||||
{
|
||||
get => GetValue(EnableSnapProperty);
|
||||
set => SetValue(EnableSnapProperty, value);
|
||||
}
|
||||
|
||||
public double SnapX
|
||||
{
|
||||
get => GetValue(SnapXProperty);
|
||||
set => SetValue(SnapXProperty, value);
|
||||
}
|
||||
|
||||
public double SnapY
|
||||
{
|
||||
get => GetValue(SnapYProperty);
|
||||
set => SetValue(SnapYProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
@ -95,12 +77,12 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
_inputSource.AddHandler(InputElement.PointerCaptureLostEvent, CaptureLost, RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
||||
_inputSource.AddHandler(InputElement.PointerMovedEvent, Moved, RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
||||
|
||||
_dataContextDisposable = AssociatedObject
|
||||
.GetObservable(StyledElement.DataContextProperty)
|
||||
.Subscribe(new AnonymousObserver<object?>(
|
||||
_dataContextDisposable = this
|
||||
.GetObservable(DrawingSourceProperty)
|
||||
.Subscribe(new AnonymousObserver<IDrawingNode?>(
|
||||
x =>
|
||||
{
|
||||
if (x is IDrawingNode drawingNode)
|
||||
if (x is { } drawingNode)
|
||||
{
|
||||
if (_drawingNode == drawingNode)
|
||||
{
|
||||
|
@ -163,7 +145,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
|
||||
private void DrawingNode_SelectionChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (AssociatedObject?.DataContext is not IDrawingNode)
|
||||
if (DrawingSource is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -175,7 +157,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
|
||||
if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 })
|
||||
{
|
||||
_selectedRect = HitTestHelper.CalculateSelectedRect(AssociatedObject);
|
||||
_selectedRect = HitTestHelper.CalculateSelectedRect(_drawingNode, AssociatedObject);
|
||||
|
||||
if (_selectedAdorner is not null)
|
||||
{
|
||||
|
@ -203,7 +185,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
|
||||
var info = e.GetCurrentPoint(_inputSource);
|
||||
|
||||
if (AssociatedObject?.DataContext is not IDrawingNode drawingNode)
|
||||
if (DrawingSource is not { } drawingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -236,11 +218,11 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
if (_selectedRect.Contains(position))
|
||||
{
|
||||
_dragSelectedItems = true;
|
||||
_start = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap);
|
||||
_start = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
|
||||
}
|
||||
else
|
||||
{
|
||||
HitTestHelper.FindSelectedNodes(AssociatedObject, pointerHitTestRect);
|
||||
HitTestHelper.FindSelectedNodes(drawingNode, AssociatedObject, pointerHitTestRect);
|
||||
|
||||
selectedNodes = drawingNode.GetSelectedNodes();
|
||||
selectedConnectors = drawingNode.GetSelectedConnectors();
|
||||
|
@ -248,7 +230,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 })
|
||||
{
|
||||
_dragSelectedItems = true;
|
||||
_start = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap);
|
||||
_start = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -264,7 +246,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
}
|
||||
else
|
||||
{
|
||||
HitTestHelper.FindSelectedNodes(AssociatedObject, pointerHitTestRect);
|
||||
HitTestHelper.FindSelectedNodes(drawingNode, AssociatedObject, pointerHitTestRect);
|
||||
|
||||
selectedNodes = drawingNode.GetSelectedNodes();
|
||||
selectedConnectors = drawingNode.GetSelectedConnectors();
|
||||
|
@ -272,7 +254,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
if (selectedNodes is { Count: > 0 } || selectedConnectors is { Count: > 0 })
|
||||
{
|
||||
_dragSelectedItems = true;
|
||||
_start = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap);
|
||||
_start = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +266,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
|
||||
RemoveSelected();
|
||||
|
||||
if (e.Source is not Control { DataContext: not IDrawingNode })
|
||||
// TODO: if (e.Source is not Control { DataContext: not IDrawingNode })
|
||||
{
|
||||
AddSelection(position.X, position.Y);
|
||||
}
|
||||
|
@ -298,15 +280,15 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
{
|
||||
if (Equals(e.Pointer.Captured, _inputSource))
|
||||
{
|
||||
if (e.InitialPressMouseButton == MouseButton.Left && AssociatedObject?.DataContext is IDrawingNode)
|
||||
if (e.InitialPressMouseButton == MouseButton.Left && DrawingSource is IDrawingNode drawingNode)
|
||||
{
|
||||
_dragSelectedItems = false;
|
||||
|
||||
if (e.Source is not Control { DataContext: not IDrawingNode })
|
||||
// TODO: if (e.Source is not Control { DataContext: not IDrawingNode })
|
||||
{
|
||||
if (_selectionAdorner is not null)
|
||||
{
|
||||
HitTestHelper.FindSelectedNodes(AssociatedObject, _selectionAdorner.GetRect());
|
||||
HitTestHelper.FindSelectedNodes(drawingNode, AssociatedObject, _selectionAdorner.GetRect());
|
||||
}
|
||||
|
||||
RemoveSelection();
|
||||
|
@ -326,19 +308,19 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
{
|
||||
var info = e.GetCurrentPoint(_inputSource);
|
||||
|
||||
if (Equals(e.Pointer.Captured, _inputSource) && info.Properties.IsLeftButtonPressed && AssociatedObject?.DataContext is IDrawingNode)
|
||||
if (Equals(e.Pointer.Captured, _inputSource) && info.Properties.IsLeftButtonPressed && DrawingSource is IDrawingNode)
|
||||
{
|
||||
var position = e.GetPosition(AssociatedObject);
|
||||
|
||||
if (_dragSelectedItems)
|
||||
{
|
||||
if (AssociatedObject?.DataContext is IDrawingNode drawingNode)
|
||||
if (DrawingSource is IDrawingNode drawingNode)
|
||||
{
|
||||
var selectedNodes = drawingNode.GetSelectedNodes();
|
||||
|
||||
if (selectedNodes is { Count: > 0 } && drawingNode.Nodes is { Count: > 0 })
|
||||
{
|
||||
position = SnapHelper.Snap(position, SnapX, SnapY, EnableSnap);
|
||||
position = SnapHelper.Snap(position, drawingNode.Settings.SnapX, drawingNode.Settings.SnapY, drawingNode.Settings.EnableSnap);
|
||||
|
||||
var deltaX = position.X - _start.X;
|
||||
var deltaY = position.Y - _start.Y;
|
||||
|
@ -353,7 +335,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
}
|
||||
}
|
||||
|
||||
var selectedRect = HitTestHelper.CalculateSelectedRect(AssociatedObject);
|
||||
var selectedRect = HitTestHelper.CalculateSelectedRect(drawingNode, AssociatedObject);
|
||||
|
||||
_selectedRect = selectedRect;
|
||||
|
||||
|
@ -365,7 +347,7 @@ public class DrawingSelectionBehavior : Behavior<ItemsControl>
|
|||
}
|
||||
else
|
||||
{
|
||||
if (e.Source is not Control { DataContext: not IDrawingNode })
|
||||
// TODO: if (e.Source is not Control { DataContext: not IDrawingNode })
|
||||
{
|
||||
UpdateSelection(position.X, position.Y);
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ namespace NodeEditor.Behaviors;
|
|||
|
||||
public class InsertTemplateOnDoubleTappedBehavior : Behavior<ListBoxItem>
|
||||
{
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingProperty =
|
||||
AvaloniaProperty.Register<InsertTemplateOnDoubleTappedBehavior, IDrawingNode?>(nameof(Drawing));
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<InsertTemplateOnDoubleTappedBehavior, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public IDrawingNode? Drawing
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(DrawingProperty);
|
||||
set => SetValue(DrawingProperty, value);
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
|
@ -37,7 +37,7 @@ public class InsertTemplateOnDoubleTappedBehavior : Behavior<ListBoxItem>
|
|||
|
||||
private void DoubleTapped(object? sender, RoutedEventArgs args)
|
||||
{
|
||||
if (AssociatedObject is { DataContext: INodeTemplate template } && Drawing is { } drawing)
|
||||
if (AssociatedObject is { DataContext: INodeTemplate template } && DrawingSource is { } drawing)
|
||||
{
|
||||
var node = drawing.Clone(template.Template);
|
||||
if (node is not null)
|
||||
|
|
|
@ -11,6 +11,15 @@ namespace NodeEditor.Behaviors;
|
|||
|
||||
public class NodesSelectedBehavior : Behavior<ItemsControl>
|
||||
{
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<NodesSelectedBehavior, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
private IDisposable? _dataContextDisposable;
|
||||
private IDrawingNode? _drawingNode;
|
||||
|
||||
|
@ -66,7 +75,7 @@ public class NodesSelectedBehavior : Behavior<ItemsControl>
|
|||
|
||||
private void DrawingNode_SelectionChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (AssociatedObject?.DataContext is not IDrawingNode)
|
||||
if (DrawingSource is not IDrawingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Xaml.Interactivity;
|
||||
using NodeEditor.Controls;
|
||||
using NodeEditor.Model;
|
||||
|
||||
namespace NodeEditor.Behaviors;
|
||||
|
||||
public class PinPressedBehavior : Behavior<ContentPresenter>
|
||||
{
|
||||
public static readonly StyledProperty<IPin?> PinSourceProperty =
|
||||
AvaloniaProperty.Register<PinPressedBehavior, IPin?>(nameof(PinSource));
|
||||
|
||||
public IPin? PinSource
|
||||
{
|
||||
get => GetValue(PinSourceProperty);
|
||||
set => SetValue(PinSourceProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace NodeEditor.Controls;
|
|||
[PseudoClasses(":selected")]
|
||||
public class Connector : Shape
|
||||
{
|
||||
public static readonly StyledProperty<IConnector?> ConnectorSourceProperty =
|
||||
AvaloniaProperty.Register<Connector, IConnector?>(nameof(ConnectorSource));
|
||||
|
||||
public static readonly StyledProperty<Point> StartPointProperty =
|
||||
AvaloniaProperty.Register<Connector, Point>(nameof(StartPoint));
|
||||
|
||||
|
@ -31,6 +34,12 @@ public class Connector : Shape
|
|||
OrientationProperty);
|
||||
}
|
||||
|
||||
public IConnector? ConnectorSource
|
||||
{
|
||||
get => GetValue(ConnectorSourceProperty);
|
||||
set => SetValue(ConnectorSourceProperty, value);
|
||||
}
|
||||
|
||||
public Point StartPoint
|
||||
{
|
||||
get => GetValue(StartPointProperty);
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
using System.Collections;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using NodeEditor.Model;
|
||||
|
||||
namespace NodeEditor.Controls;
|
||||
|
||||
public class Connectors : TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable?> ConnectorsSourceProperty =
|
||||
AvaloniaProperty.Register<Connectors, IEnumerable?>(nameof(ConnectorsSource));
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<Connectors, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public IEnumerable? ConnectorsSource
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(ConnectorsSourceProperty);
|
||||
set => SetValue(ConnectorsSourceProperty, value);
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
using System.Collections;
|
||||
using Avalonia;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using NodeEditor.Model;
|
||||
|
||||
namespace NodeEditor.Controls;
|
||||
|
||||
public class DrawingNode : TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable?> NodesSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, IEnumerable?>(nameof(NodesSource));
|
||||
|
||||
public static readonly StyledProperty<IEnumerable?> ConnectorsSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, IEnumerable?>(nameof(ConnectorsSource));
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public static readonly StyledProperty<Control?> InputSourceProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, Control?>(nameof(InputSource));
|
||||
|
@ -19,34 +16,10 @@ public class DrawingNode : TemplatedControl
|
|||
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, Canvas?>(nameof(AdornerCanvas));
|
||||
|
||||
public static readonly StyledProperty<bool> EnableSnapProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, bool>(nameof(EnableSnap));
|
||||
|
||||
public static readonly StyledProperty<double> SnapXProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, double>(nameof(SnapX), 1.0);
|
||||
|
||||
public static readonly StyledProperty<double> SnapYProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, double>(nameof(SnapY), 1.0);
|
||||
|
||||
public static readonly StyledProperty<bool> EnableGridProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, bool>(nameof(EnableGrid));
|
||||
|
||||
public static readonly StyledProperty<double> GridCellWidthProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, double>(nameof(GridCellWidth));
|
||||
|
||||
public static readonly StyledProperty<double> GridCellHeightProperty =
|
||||
AvaloniaProperty.Register<DrawingNode, double>(nameof(GridCellHeight));
|
||||
|
||||
public IEnumerable? NodesSource
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(NodesSourceProperty);
|
||||
set => SetValue(NodesSourceProperty, value);
|
||||
}
|
||||
|
||||
public IEnumerable? ConnectorsSource
|
||||
{
|
||||
get => GetValue(ConnectorsSourceProperty);
|
||||
set => SetValue(ConnectorsSourceProperty, value);
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
public Control? InputSource
|
||||
|
@ -60,40 +33,4 @@ public class DrawingNode : TemplatedControl
|
|||
get => GetValue(AdornerCanvasProperty);
|
||||
set => SetValue(AdornerCanvasProperty, value);
|
||||
}
|
||||
|
||||
public bool EnableSnap
|
||||
{
|
||||
get => GetValue(EnableSnapProperty);
|
||||
set => SetValue(EnableSnapProperty, value);
|
||||
}
|
||||
|
||||
public double SnapX
|
||||
{
|
||||
get => GetValue(SnapXProperty);
|
||||
set => SetValue(SnapXProperty, value);
|
||||
}
|
||||
|
||||
public double SnapY
|
||||
{
|
||||
get => GetValue(SnapYProperty);
|
||||
set => SetValue(SnapYProperty, value);
|
||||
}
|
||||
|
||||
public bool EnableGrid
|
||||
{
|
||||
get => GetValue(EnableGridProperty);
|
||||
set => SetValue(EnableGridProperty, value);
|
||||
}
|
||||
|
||||
public double GridCellWidth
|
||||
{
|
||||
get => GetValue(GridCellWidthProperty);
|
||||
set => SetValue(GridCellWidthProperty, value);
|
||||
}
|
||||
|
||||
public double GridCellHeight
|
||||
{
|
||||
get => GetValue(GridCellHeightProperty);
|
||||
set => SetValue(GridCellHeightProperty, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,66 +4,30 @@ using Avalonia.Controls;
|
|||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using NodeEditor.Model;
|
||||
|
||||
namespace NodeEditor.Controls;
|
||||
|
||||
[TemplatePart("PART_ZoomBorder", typeof(NodeZoomBorder))]
|
||||
[TemplatePart("PART_Drawing", typeof(DrawingNode))]
|
||||
[TemplatePart("PART_AdornerCanvas", typeof(Canvas))]
|
||||
public class Editor : TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable?> NodesSourceProperty =
|
||||
AvaloniaProperty.Register<Editor, IEnumerable?>(nameof(NodesSource));
|
||||
|
||||
public static readonly StyledProperty<IEnumerable?> ConnectorsSourceProperty =
|
||||
AvaloniaProperty.Register<Editor, IEnumerable?>(nameof(ConnectorsSource));
|
||||
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<Editor, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public static readonly StyledProperty<Control?> InputSourceProperty =
|
||||
AvaloniaProperty.Register<Editor, Control?>(nameof(InputSource));
|
||||
|
||||
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
|
||||
AvaloniaProperty.Register<Editor, Canvas?>(nameof(AdornerCanvas));
|
||||
|
||||
public static readonly StyledProperty<bool> EnableSnapProperty =
|
||||
AvaloniaProperty.Register<Editor, bool>(nameof(EnableSnap), false, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<double> SnapXProperty =
|
||||
AvaloniaProperty.Register<Editor, double>(nameof(SnapX), 1.0, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<double> SnapYProperty =
|
||||
AvaloniaProperty.Register<Editor, double>(nameof(SnapY), 1.0, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<bool> EnableGridProperty =
|
||||
AvaloniaProperty.Register<Editor, bool>(nameof(EnableGrid), false, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<double> GridCellWidthProperty =
|
||||
AvaloniaProperty.Register<Editor, double>(nameof(GridCellWidth), 15.0, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<double> GridCellHeightProperty =
|
||||
AvaloniaProperty.Register<Editor, double>(nameof(GridCellHeight), 15.0, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<double> DrawingWidthProperty =
|
||||
AvaloniaProperty.Register<Editor, double>(nameof(DrawingWidth), 0.0, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<double> DrawingHeightProperty =
|
||||
AvaloniaProperty.Register<Editor, double>(nameof(DrawingHeight), 0.0, false, BindingMode.TwoWay);
|
||||
|
||||
public static readonly StyledProperty<NodeZoomBorder?> ZoomControlProperty =
|
||||
AvaloniaProperty.Register<Editor, NodeZoomBorder?>(nameof(ZoomControl));
|
||||
|
||||
public static readonly StyledProperty<DrawingNode?> DrawingNodeProperty =
|
||||
AvaloniaProperty.Register<Editor, DrawingNode?>(nameof(DrawingNode));
|
||||
|
||||
public IEnumerable? NodesSource
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(NodesSourceProperty);
|
||||
set => SetValue(NodesSourceProperty, value);
|
||||
}
|
||||
|
||||
public IEnumerable? ConnectorsSource
|
||||
{
|
||||
get => GetValue(ConnectorsSourceProperty);
|
||||
set => SetValue(ConnectorsSourceProperty, value);
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
public Control? InputSource
|
||||
|
@ -78,72 +42,17 @@ public class Editor : TemplatedControl
|
|||
set => SetValue(AdornerCanvasProperty, value);
|
||||
}
|
||||
|
||||
public bool EnableSnap
|
||||
{
|
||||
get => GetValue(EnableSnapProperty);
|
||||
set => SetValue(EnableSnapProperty, value);
|
||||
}
|
||||
|
||||
public double SnapX
|
||||
{
|
||||
get => GetValue(SnapXProperty);
|
||||
set => SetValue(SnapXProperty, value);
|
||||
}
|
||||
|
||||
public double SnapY
|
||||
{
|
||||
get => GetValue(SnapYProperty);
|
||||
set => SetValue(SnapYProperty, value);
|
||||
}
|
||||
|
||||
public bool EnableGrid
|
||||
{
|
||||
get => GetValue(EnableGridProperty);
|
||||
set => SetValue(EnableGridProperty, value);
|
||||
}
|
||||
|
||||
public double GridCellWidth
|
||||
{
|
||||
get => GetValue(GridCellWidthProperty);
|
||||
set => SetValue(GridCellWidthProperty, value);
|
||||
}
|
||||
|
||||
public double GridCellHeight
|
||||
{
|
||||
get => GetValue(GridCellHeightProperty);
|
||||
set => SetValue(GridCellHeightProperty, value);
|
||||
}
|
||||
|
||||
public double DrawingWidth
|
||||
{
|
||||
get => GetValue(DrawingWidthProperty);
|
||||
set => SetValue(DrawingWidthProperty, value);
|
||||
}
|
||||
|
||||
public double DrawingHeight
|
||||
{
|
||||
get => GetValue(DrawingHeightProperty);
|
||||
set => SetValue(DrawingHeightProperty, value);
|
||||
}
|
||||
|
||||
public NodeZoomBorder? ZoomControl
|
||||
{
|
||||
get => GetValue(ZoomControlProperty);
|
||||
set => SetValue(ZoomControlProperty, value);
|
||||
}
|
||||
|
||||
public DrawingNode? DrawingNode
|
||||
{
|
||||
get => GetValue(DrawingNodeProperty);
|
||||
set => SetValue(DrawingNodeProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
ZoomControl = e.NameScope.Find<NodeZoomBorder>("PART_ZoomBorder");
|
||||
DrawingNode = e.NameScope.Find<DrawingNode>("PART_DrawingNode");
|
||||
AdornerCanvas = e.NameScope.Find<Canvas>("PART_AdornerCanvas");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,19 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using NodeEditor.Model;
|
||||
|
||||
namespace NodeEditor.Controls;
|
||||
|
||||
[PseudoClasses(":selected")]
|
||||
public class Node : ContentControl
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable?> PinsSourceProperty =
|
||||
AvaloniaProperty.Register<Node, IEnumerable?>(nameof(PinsSource));
|
||||
|
||||
public IEnumerable? PinsSource
|
||||
public static readonly StyledProperty<INode?> NodeSourceProperty =
|
||||
AvaloniaProperty.Register<Node, INode?>(nameof(NodeSource));
|
||||
|
||||
public INode? NodeSource
|
||||
{
|
||||
get => GetValue(PinsSourceProperty);
|
||||
set => SetValue(PinsSourceProperty, value);
|
||||
get => GetValue(NodeSourceProperty);
|
||||
set => SetValue(NodeSourceProperty, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,37 @@
|
|||
using System.Collections;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using NodeEditor.Model;
|
||||
|
||||
namespace NodeEditor.Controls;
|
||||
|
||||
public class Nodes : TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable?> NodesSourceProperty =
|
||||
AvaloniaProperty.Register<Nodes, IEnumerable?>(nameof(NodesSource));
|
||||
|
||||
public IEnumerable? NodesSource
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingSourceProperty =
|
||||
AvaloniaProperty.Register<Nodes, IDrawingNode?>(nameof(DrawingSource));
|
||||
|
||||
public static readonly StyledProperty<Control?> InputSourceProperty =
|
||||
AvaloniaProperty.Register<Nodes, Control?>(nameof(InputSource));
|
||||
|
||||
public static readonly StyledProperty<Canvas?> AdornerCanvasProperty =
|
||||
AvaloniaProperty.Register<Nodes, Canvas?>(nameof(AdornerCanvas));
|
||||
|
||||
public IDrawingNode? DrawingSource
|
||||
{
|
||||
get => GetValue(NodesSourceProperty);
|
||||
set => SetValue(NodesSourceProperty, value);
|
||||
get => GetValue(DrawingSourceProperty);
|
||||
set => SetValue(DrawingSourceProperty, value);
|
||||
}
|
||||
|
||||
public Control? InputSource
|
||||
{
|
||||
get => GetValue(InputSourceProperty);
|
||||
set => SetValue(InputSourceProperty, value);
|
||||
}
|
||||
|
||||
public Canvas? AdornerCanvas
|
||||
{
|
||||
get => GetValue(AdornerCanvasProperty);
|
||||
set => SetValue(AdornerCanvasProperty, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,21 @@ namespace NodeEditor.Controls;
|
|||
|
||||
public class Pin : TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<IPin?> PinSourceProperty =
|
||||
AvaloniaProperty.Register<Pin, IPin?>(nameof(PinSource));
|
||||
|
||||
public static readonly StyledProperty<PinAlignment> AlignmentProperty =
|
||||
AvaloniaProperty.Register<Pin, PinAlignment>(nameof(Alignment));
|
||||
|
||||
public static readonly StyledProperty<string?> IdProperty =
|
||||
AvaloniaProperty.Register<Pin, string?>(nameof(Id));
|
||||
|
||||
public IPin? PinSource
|
||||
{
|
||||
get => GetValue(PinSourceProperty);
|
||||
set => SetValue(PinSourceProperty, value);
|
||||
}
|
||||
|
||||
public PinAlignment Alignment
|
||||
{
|
||||
get => GetValue(AlignmentProperty);
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
using System.Collections;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using NodeEditor.Model;
|
||||
|
||||
namespace NodeEditor.Controls;
|
||||
|
||||
public class Pins : TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable?> PinsSourceProperty =
|
||||
AvaloniaProperty.Register<Pins, IEnumerable?>(nameof(PinsSource));
|
||||
|
||||
public IEnumerable? PinsSource
|
||||
public static readonly StyledProperty<INode?> NodeSourceProperty =
|
||||
AvaloniaProperty.Register<Pins, INode?>(nameof(NodeSource));
|
||||
|
||||
public INode? NodeSource
|
||||
{
|
||||
get => GetValue(PinsSourceProperty);
|
||||
set => SetValue(PinsSourceProperty, value);
|
||||
get => GetValue(NodeSourceProperty);
|
||||
set => SetValue(NodeSourceProperty, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using NodeEditor.Model;
|
||||
|
@ -6,22 +7,13 @@ using NodeEditor.Model;
|
|||
namespace NodeEditor.Controls;
|
||||
|
||||
public class Toolbox : TemplatedControl
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable?> TemplatesSourceProperty =
|
||||
AvaloniaProperty.Register<Toolbox, IEnumerable?>(nameof(TemplatesSource));
|
||||
|
||||
public static readonly StyledProperty<IDrawingNode?> DrawingProperty =
|
||||
AvaloniaProperty.Register<Toolbox, IDrawingNode?>(nameof(Drawing));
|
||||
{
|
||||
public static readonly StyledProperty<IEnumerable<INodeTemplate>?> TemplatesSourceProperty =
|
||||
AvaloniaProperty.Register<Toolbox, IEnumerable<INodeTemplate>?>(nameof(TemplatesSource));
|
||||
|
||||
public IEnumerable? TemplatesSource
|
||||
public IEnumerable<INodeTemplate>? TemplatesSource
|
||||
{
|
||||
get => GetValue(TemplatesSourceProperty);
|
||||
set => SetValue(TemplatesSourceProperty, value);
|
||||
}
|
||||
|
||||
public IDrawingNode? Drawing
|
||||
{
|
||||
get => GetValue(DrawingProperty);
|
||||
set => SetValue(DrawingProperty, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,13 +167,8 @@ internal static class HitTestHelper
|
|||
new Point(bottomRightX, bottomRightY));
|
||||
}
|
||||
|
||||
public static void FindSelectedNodes(ItemsControl? itemsControl, Rect rect)
|
||||
public static void FindSelectedNodes(IDrawingNode drawingNode, ItemsControl? itemsControl, Rect rect)
|
||||
{
|
||||
if (itemsControl?.DataContext is not IDrawingNode drawingNode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
drawingNode.NotifyDeselectedNodes();
|
||||
drawingNode.NotifyDeselectedConnectors();
|
||||
drawingNode.SetSelectedNodes(null);
|
||||
|
@ -245,13 +240,8 @@ internal static class HitTestHelper
|
|||
}
|
||||
}
|
||||
|
||||
public static Rect CalculateSelectedRect(ItemsControl? itemsControl)
|
||||
public static Rect CalculateSelectedRect(IDrawingNode drawingNode, ItemsControl? itemsControl)
|
||||
{
|
||||
if (itemsControl?.DataContext is not IDrawingNode drawingNode)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var selectedRect = new Rect();
|
||||
|
||||
itemsControl.UpdateLayout();
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<Setter Property="StrokeThickness" Value="2" />
|
||||
<Setter Property="ClipToBounds" Value="False" />
|
||||
|
||||
<Setter Property="ContextFlyout">
|
||||
<Setter Property="ContextFlyout" x:DataType="controls:Connector">
|
||||
<Setter.Value>
|
||||
<Flyout>
|
||||
<DockPanel>
|
||||
|
@ -19,19 +19,19 @@
|
|||
<Label Content="Orientation:" DockPanel.Dock="Top" />
|
||||
<RadioButton Content="Auto"
|
||||
GroupName="Orientation"
|
||||
IsChecked="{Binding $parent[controls:Connector].Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Auto}}"
|
||||
IsChecked="{Binding Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Auto}}"
|
||||
DockPanel.Dock="Top" />
|
||||
<RadioButton Content="Horizontal"
|
||||
GroupName="Orientation"
|
||||
IsChecked="{Binding $parent[controls:Connector].Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Horizontal}}"
|
||||
IsChecked="{Binding Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Horizontal}}"
|
||||
DockPanel.Dock="Top" />
|
||||
<RadioButton Content="Vertical"
|
||||
GroupName="Orientation"
|
||||
IsChecked="{Binding $parent[controls:Connector].Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Vertical}}"
|
||||
IsChecked="{Binding Orientation, Converter={x:Static converters:EnumToCheckedConverter.Instance}, ConverterParameter={x:Static m:ConnectorOrientation.Vertical}}"
|
||||
DockPanel.Dock="Top" />
|
||||
</DockPanel>
|
||||
<Label Content="Offset:" DockPanel.Dock="Top" />
|
||||
<TextBox Text="{Binding $parent[controls:Connector].Offset}" DockPanel.Dock="Top" />
|
||||
<TextBox Text="{Binding Offset}" DockPanel.Dock="Top" />
|
||||
</DockPanel>
|
||||
</Flyout>
|
||||
</Setter.Value>
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ItemsControl x:Name="PART_ConnectorsItemsControl"
|
||||
ItemsSource="{TemplateBinding ConnectorsSource}"
|
||||
Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}"
|
||||
ItemsSource="{Binding DrawingSource.Connectors, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Width="{Binding Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Background="Transparent"
|
||||
IsHitTestVisible="False"
|
||||
ClipToBounds="False">
|
||||
|
@ -29,7 +29,8 @@
|
|||
StartPoint="{Binding Start, Converter={x:Static converters:PinToPointConverter.Instance}}"
|
||||
EndPoint="{Binding End, Converter={x:Static converters:PinToPointConverter.Instance}}"
|
||||
Offset="{Binding Offset}"
|
||||
Orientation="{Binding Orientation}" />
|
||||
Orientation="{Binding Orientation}"
|
||||
ConnectorSource="{Binding .}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
|
|
@ -12,17 +12,19 @@
|
|||
<ControlTemplate>
|
||||
<Panel x:Name="PART_Panel"
|
||||
Background="{TemplateBinding Background}">
|
||||
<controls:GridDecorator EnableGrid="{TemplateBinding EnableGrid}"
|
||||
GridCellWidth="{TemplateBinding GridCellWidth}"
|
||||
GridCellHeight="{TemplateBinding GridCellHeight}" />
|
||||
<controls:GridDecorator EnableGrid="{Binding DrawingSource.Settings.EnableGrid, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
GridCellWidth="{Binding DrawingSource.Settings.GridCellWidth, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
GridCellHeight="{Binding DrawingSource.Settings.GridCellHeight, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<controls:Connectors x:Name="PART_Connectors"
|
||||
Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}"
|
||||
ConnectorsSource="{TemplateBinding ConnectorsSource}" />
|
||||
Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<controls:Nodes x:Name="PART_Nodes"
|
||||
Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}"
|
||||
NodesSource="{TemplateBinding NodesSource}" />
|
||||
Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputSource="{Binding InputSource, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
AdornerCanvas="{Binding AdornerCanvas, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<DockPanel>
|
||||
<!-- Snap -->
|
||||
<DockPanel DockPanel.Dock="Bottom">
|
||||
<ToggleSwitch IsChecked="{TemplateBinding EnableSnap}"
|
||||
<ToggleSwitch IsChecked="{Binding EnableSnap, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
OnContent="Snap On"
|
||||
OffContent="Snap Off"
|
||||
HorizontalAlignment="Left"
|
||||
|
@ -30,7 +30,7 @@
|
|||
Margin="4,4,2,4"
|
||||
Padding="6"
|
||||
TextAlignment="Left"
|
||||
Text="{TemplateBinding SnapX}" />
|
||||
Text="{Binding SnapX, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<Label Grid.Column="2"
|
||||
Content="SY"
|
||||
Margin="6,0,6,0"
|
||||
|
@ -41,12 +41,12 @@
|
|||
Margin="2,4,4,4"
|
||||
Padding="6"
|
||||
TextAlignment="Left"
|
||||
Text="{TemplateBinding SnapY}" />
|
||||
Text="{Binding SnapY, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
<!-- Grid -->
|
||||
<DockPanel DockPanel.Dock="Bottom">
|
||||
<ToggleSwitch IsChecked="{TemplateBinding EnableGrid}"
|
||||
<ToggleSwitch IsChecked="{Binding EnableGrid, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
OnContent="Grid On"
|
||||
OffContent="Grid Off"
|
||||
HorizontalAlignment="Left"
|
||||
|
@ -64,7 +64,7 @@
|
|||
Margin="4,4,2,4"
|
||||
Padding="6"
|
||||
TextAlignment="Left"
|
||||
Text="{TemplateBinding GridCellWidth}" />
|
||||
Text="{Binding GridCellWidth, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<Label Grid.Column="2"
|
||||
Content="CH"
|
||||
Margin="6,0,6,0"
|
||||
|
@ -75,7 +75,7 @@
|
|||
Margin="2,4,4,4"
|
||||
Padding="6"
|
||||
TextAlignment="Left"
|
||||
Text="{TemplateBinding GridCellHeight}" />
|
||||
Text="{Binding GridCellHeight, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
<!-- Width/Height -->
|
||||
|
@ -90,7 +90,7 @@
|
|||
Margin="4,4,2,4"
|
||||
Padding="6"
|
||||
TextAlignment="Left"
|
||||
Text="{TemplateBinding DrawingWidth}" />
|
||||
Text="{Binding DrawingWidth, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<Label Grid.Column="2"
|
||||
Content="H"
|
||||
Margin="6,0,6,0"
|
||||
|
@ -101,7 +101,7 @@
|
|||
Margin="2,4,4,4"
|
||||
Padding="6"
|
||||
TextAlignment="Left"
|
||||
Text="{TemplateBinding DrawingHeight}" />
|
||||
Text="{Binding DrawingHeight, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</ControlTemplate>
|
||||
|
|
|
@ -32,20 +32,21 @@
|
|||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch">
|
||||
<i:Interaction.Behaviors>
|
||||
<idd:ContextDropBehavior Context="{TemplateBinding DataContext}">
|
||||
<idd:ContextDropBehavior Context="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<idd:ContextDropBehavior.Handler>
|
||||
<behaviors:DrawingDropHandler RelativeTo="{Binding #PART_DrawingNode}" />
|
||||
<behaviors:DrawingDropHandler DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
RelativeTo="{Binding #PART_DrawingNode}" />
|
||||
</idd:ContextDropBehavior.Handler>
|
||||
</idd:ContextDropBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
<Border Background="Transparent"
|
||||
Width="{TemplateBinding DrawingWidth}"
|
||||
Height="{TemplateBinding DrawingHeight}"
|
||||
Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
BoxShadow="4 11 30 1 #3F000000"
|
||||
ZIndex="-1">
|
||||
<Panel Background="Transparent"
|
||||
Width="{TemplateBinding DrawingWidth}"
|
||||
Height="{TemplateBinding DrawingHeight}">
|
||||
Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<Panel.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.1" />
|
||||
|
@ -53,56 +54,48 @@
|
|||
</Panel.Transitions>
|
||||
<controls:DrawingNode x:Name="PART_DrawingNode"
|
||||
Background="{DynamicResource DrawingBackground}"
|
||||
Width="{TemplateBinding DrawingWidth}"
|
||||
Height="{TemplateBinding DrawingHeight}"
|
||||
NodesSource="{TemplateBinding NodesSource}"
|
||||
ConnectorsSource="{TemplateBinding ConnectorsSource}"
|
||||
InputSource="{TemplateBinding ZoomControl}"
|
||||
AdornerCanvas="{TemplateBinding AdornerCanvas}"
|
||||
EnableSnap="{TemplateBinding EnableSnap}"
|
||||
SnapX="{TemplateBinding SnapX}"
|
||||
SnapY="{TemplateBinding SnapY}"
|
||||
EnableGrid="{TemplateBinding EnableGrid}"
|
||||
GridCellWidth="{TemplateBinding GridCellWidth}"
|
||||
GridCellHeight="{TemplateBinding GridCellHeight}"
|
||||
DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputSource="{Binding ZoomControl, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
AdornerCanvas="{Binding AdornerCanvas, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
ClipToBounds="False">
|
||||
<!-- TODO:
|
||||
<controls:DrawingNode.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem Header="Cu_t"
|
||||
Command="{Binding CutNodesCommand}"
|
||||
Command="{Binding DrawingSource.CutNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputGesture="{OnPlatform macOS=CMD+X, iOS=CMD+X, Default=Ctrl+X}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon Width="16" Height="16" Data="{DynamicResource EditorCutIcon}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Copy"
|
||||
Command="{Binding CopyNodesCommand}"
|
||||
Command="{Binding DrawingSource.CopyNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputGesture="{OnPlatform macOS=CMD+C, iOS=CMD+C, Default=Ctrl+C}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon Width="16" Height="16" Data="{DynamicResource EditorCopyIcon}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Paste"
|
||||
Command="{Binding PasteNodesCommand}"
|
||||
Command="{Binding DrawingSource.PasteNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputGesture="{OnPlatform macOS=CMD+V, iOS=CMD+V, Default=Ctrl+V}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon Width="16" Height="16" Data="{DynamicResource EditorPasteIcon}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="D_uplicate"
|
||||
Command="{Binding DuplicateNodesCommand}"
|
||||
Command="{Binding DrawingSource.DuplicateNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputGesture="{OnPlatform macOS=CMD+D, iOS=CMD+D, Default=Ctrl+D}" />
|
||||
<MenuItem Header="-" />
|
||||
<MenuItem Header="Select _All"
|
||||
Command="{Binding SelectAllNodesCommand, FallbackValue={x:Null}}"
|
||||
Command="{Binding DrawingSource.SelectAllNodesCommand, RelativeSource={RelativeSource TemplatedParent}, FallbackValue={x:Null}}"
|
||||
InputGesture="{OnPlatform macOS=CMD+A, iOS=CMD+A, Default=Ctrl+A}" />
|
||||
<MenuItem Header="De_select All"
|
||||
Command="{Binding DeselectAllNodesCommand, FallbackValue={x:Null}}"
|
||||
Command="{Binding DrawingSource.DeselectAllNodesCommand, RelativeSource={RelativeSource TemplatedParent}, FallbackValue={x:Null}}"
|
||||
InputGesture="Escape" />
|
||||
<MenuItem Header="-" />
|
||||
<MenuItem Header="_Delete"
|
||||
Command="{Binding DeleteNodesCommand}"
|
||||
Command="{Binding DrawingSource.DeleteNodesCommand, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputGesture="Delete">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon Width="16" Height="16" Data="{DynamicResource DeleteIcon}" />
|
||||
|
@ -110,12 +103,11 @@
|
|||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</controls:DrawingNode.ContextFlyout>
|
||||
-->
|
||||
</controls:DrawingNode>
|
||||
<Canvas x:Name="PART_AdornerCanvas"
|
||||
Background="Transparent"
|
||||
Width="{TemplateBinding DrawingWidth}"
|
||||
Height="{TemplateBinding DrawingHeight}"
|
||||
Width="{Binding DrawingSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding DrawingSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsHitTestVisible="False"/>
|
||||
</Panel>
|
||||
</Border>
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Panel Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}">
|
||||
<Panel Width="{Binding NodeSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding NodeSource.Height, RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<ContentPresenter x:Name="PART_ContentPresenter"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
|
@ -23,9 +23,9 @@
|
|||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
|
||||
<controls:Pins x:Name="PART_Pins"
|
||||
Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}"
|
||||
PinsSource="{TemplateBinding PinsSource}"/>
|
||||
Width="{Binding NodeSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding NodeSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
NodeSource="{Binding NodeSource, RelativeSource={RelativeSource TemplatedParent}}"/>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
|
|
@ -13,22 +13,18 @@
|
|||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ItemsControl x:Name="PART_NodesItemsControl"
|
||||
ItemsSource="{TemplateBinding NodesSource}"
|
||||
Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}"
|
||||
ItemsSource="{Binding DrawingSource.Nodes, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Width="{Binding Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Background="Transparent"
|
||||
ClipToBounds="False">
|
||||
<i:Interaction.Behaviors>
|
||||
<behaviors:NodesSelectedBehavior />
|
||||
<!-- TODO: Fix using $parent[controls:DrawingNode] -->
|
||||
<behaviors:DrawingSelectionBehavior InputSource="{Binding $parent[controls:DrawingNode].InputSource}"
|
||||
AdornerCanvas="{Binding $parent[controls:DrawingNode].AdornerCanvas}"
|
||||
EnableSnap="{Binding $parent[controls:DrawingNode].EnableSnap}"
|
||||
SnapX="{Binding $parent[controls:DrawingNode].SnapX}"
|
||||
SnapY="{Binding $parent[controls:DrawingNode].SnapY}"
|
||||
x:CompileBindings="False" />
|
||||
<behaviors:DrawingPressedBehavior />
|
||||
<behaviors:DrawingMovedBehavior />
|
||||
<behaviors:NodesSelectedBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<behaviors:DrawingSelectionBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
InputSource="{Binding InputSource, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
AdornerCanvas="{Binding AdornerCanvas, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<behaviors:DrawingPressedBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
<behaviors:DrawingMovedBehavior DrawingSource="{Binding DrawingSource, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</i:Interaction.Behaviors>
|
||||
<ItemsControl.Styles>
|
||||
<Style Selector="ItemsControl > ContentPresenter" x:DataType="m:INode">
|
||||
|
@ -47,7 +43,7 @@
|
|||
Content="{Binding Content}"
|
||||
Width="{Binding Width}"
|
||||
Height="{Binding Height}"
|
||||
PinsSource="{Binding Pins}" />
|
||||
NodeSource="{Binding .}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Ellipse x:Name="PART_Pin"
|
||||
Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}" />
|
||||
Width="{Binding Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ItemsControl x:Name="PART_PinsItemsControl"
|
||||
ItemsSource="{TemplateBinding PinsSource}"
|
||||
Width="{TemplateBinding Width}"
|
||||
Height="{TemplateBinding Height}"
|
||||
ItemsSource="{Binding NodeSource.Pins, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Width="{Binding NodeSource.Width, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Height="{Binding NodeSource.Height, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
ClipToBounds="False">
|
||||
<ItemsControl.Styles>
|
||||
<Style Selector="ItemsControl > ContentPresenter" x:DataType="m:IPin">
|
||||
|
@ -44,7 +44,8 @@
|
|||
Width="{Binding Width}"
|
||||
Height="{Binding Height}"
|
||||
Alignment="{Binding Alignment}"
|
||||
Id="{Binding Name}" />
|
||||
Id="{Binding Name}"
|
||||
PinSource="{Binding .}"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
|
||||
<ListBox ItemsSource="{TemplateBinding TemplatesSource}"
|
||||
<ListBox ItemsSource="{Binding TemplatesSource, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Background="Transparent">
|
||||
<ListBox.Resources>
|
||||
<behaviors:TemplatesListBoxDropHandler x:Key="TemplatesListBoxDropHandler" />
|
||||
|
@ -28,7 +28,7 @@
|
|||
<i:BehaviorCollectionTemplate>
|
||||
<i:BehaviorCollection>
|
||||
<idd:ContextDragBehavior />
|
||||
<behaviors:InsertTemplateOnDoubleTappedBehavior Drawing="{Binding $parent[Toolbox].Drawing}" />
|
||||
<behaviors:InsertTemplateOnDoubleTappedBehavior />
|
||||
</i:BehaviorCollection>
|
||||
</i:BehaviorCollectionTemplate>
|
||||
</Setter>
|
||||
|
@ -42,7 +42,7 @@
|
|||
Content="{Binding Content}"
|
||||
Width="{Binding Width}"
|
||||
Height="{Binding Width}"
|
||||
PinsSource="{Binding Pins}">
|
||||
NodeSource="{Binding .}">
|
||||
<controls:Node.Styles>
|
||||
<Style Selector="controls|Pins /template/ ItemsControl#PART_PinsItemsControl">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче