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