Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Minimap control to Nodify #124

Merged
merged 11 commits into from
Jul 23, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

> - Breaking Changes:
> - Features:
> - Added a Minimap control and EditorGestures.Minimap to Nodify
> - Added ContentContainerStyle, HeaderContainerStyle and FooterContainerStyle dependency properties to Node
> - Added BringIntoView that takes a Rect parameter to NodifyEditor
> - Added the NodifyEditor's DataContext as the parameter of the ItemsSelectStartedCommand, ItemsSelectCompletedCommand, ItemsDragStartedCommand and ItemsDragCompletedCommand commands
Expand Down
31 changes: 31 additions & 0 deletions Examples/Nodify.Playground/Editor/NodifyEditorView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,37 @@
<Grid Background="{StaticResource LargeGridLinesDrawingBrush}"
Visibility="{Binding ShowGridLines, Source={x:Static local:PlaygroundSettings.Instance}, Converter={shared:BooleanToVisibilityConverter}}"
Panel.ZIndex="-2" />

<nodify:Minimap ItemsSource="{Binding ItemsSource, ElementName=Editor}"
ViewportSize="{Binding ViewportSize, ElementName=Editor}"
ViewportLocation="{Binding ViewportLocation, ElementName=Editor}"
Visibility="{Binding ShowMinimap, Source={x:Static local:PlaygroundSettings.Instance}, Converter={shared:BooleanToVisibilityConverter}}"
IsReadOnly="{Binding DisableMinimapControls, Source={x:Static local:PlaygroundSettings.Instance}}"
ResizeToViewport="{Binding ResizeToViewport, Source={x:Static local:PlaygroundSettings.Instance}}"
MaxViewportOffset="{Binding MinimapMaxViewportOffset.Size, Source={x:Static local:PlaygroundSettings.Instance}}"
Zoom="Minimap_Zoom"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Width="300"
Height="200"
Margin="5 40">
<nodify:Minimap.ItemTemplate>
<DataTemplate DataType="{x:Type local:NodeViewModel}">
<Grid />
</DataTemplate>
</nodify:Minimap.ItemTemplate>
<nodify:Minimap.ItemContainerStyle>
<Style TargetType="{x:Type nodify:MinimapItem}"
BasedOn="{StaticResource {x:Type nodify:MinimapItem}}">
<Setter Property="Location"
Value="{Binding Location}" />
<Setter Property="Width"
Value="150" />
<Setter Property="Height"
Value="130" />
</Style>
</nodify:Minimap.ItemContainerStyle>
</nodify:Minimap>
</Grid>

</UserControl>
5 changes: 5 additions & 0 deletions Examples/Nodify.Playground/Editor/NodifyEditorView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ public NodifyEditorView()
{
InitializeComponent();
}

private void Minimap_Zoom(object sender, ZoomEventArgs e)
{
EditorInstance.ZoomAtPosition(e.Zoom, e.Location);
}
}
}
7 changes: 4 additions & 3 deletions Examples/Nodify.Playground/EditorSettings.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace Nodify.Playground
{
Expand Down Expand Up @@ -398,14 +399,14 @@ public ArrowHeadShape ArrowHeadShape
set => SetProperty(ref _arrowHeadShape, value);
}

private PointEditor _connectionSourceOffset = new PointEditor { X = 14, Y = 0 };
private PointEditor _connectionSourceOffset = new Size(14, 0);
public PointEditor ConnectionSourceOffset
{
get => _connectionSourceOffset;
set => SetProperty(ref _connectionSourceOffset, value);
}

private PointEditor _connectionTargetOffset = new PointEditor { X = 14, Y = 0 };
private PointEditor _connectionTargetOffset = new Size(14, 0);
public PointEditor ConnectionTargetOffset
{
get => _connectionTargetOffset;
Expand All @@ -426,7 +427,7 @@ public double DirectionalArrowsOffset
set => SetProperty(ref _directionalArrowsOffset, value);
}

private PointEditor _connectionArrowSize = new PointEditor { X = 8, Y = 8 };
private PointEditor _connectionArrowSize = new Size(8, 8);
public PointEditor ConnectionArrowSize
{
get => _connectionArrowSize;
Expand Down
49 changes: 49 additions & 0 deletions Examples/Nodify.Playground/PlaygroundSettings.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace Nodify.Playground
{
Expand All @@ -19,6 +20,26 @@ private PlaygroundSettings()
() => Instance.EditorInputMode,
val => Instance.EditorInputMode = val,
"Editor input mode"),
new ProxySettingViewModel<bool>(
() => Instance.ShowMinimap,
val => Instance.ShowMinimap = val,
"Show minimap",
"Set Enable nodes dragging optimization to false for realtime updates"),
new ProxySettingViewModel<bool>(
() => Instance.DisableMinimapControls,
val => Instance.DisableMinimapControls = val,
"Disable minimap controls",
"Whether the minimap can move and zoom the viewport"),
new ProxySettingViewModel<bool>(
() => Instance.ResizeToViewport,
val => Instance.ResizeToViewport = val,
"Minimap resize to viewport",
"Whether the minimap should resized to also display the viewport"),
new ProxySettingViewModel<PointEditor>(
() => Instance.MinimapMaxViewportOffset,
val => Instance.MinimapMaxViewportOffset = val,
"Minimap max viewport offset",
"The max position from the items extent that the viewport can move to"),
new ProxySettingViewModel<bool>(
() => Instance.ShowGridLines,
val => Instance.ShowGridLines = val,
Expand Down Expand Up @@ -76,6 +97,34 @@ public EditorInputMode EditorInputMode
.Then(() => EditorGestures.Mappings.Apply(value));
}

private bool _showMinimap = true;
public bool ShowMinimap
{
get => _showMinimap;
set => SetProperty(ref _showMinimap, value);
}

private bool _disableMinimapControls = false;
public bool DisableMinimapControls
{
get => _disableMinimapControls;
set => SetProperty(ref _disableMinimapControls, value);
}

private bool _resizeToViewport = false;
public bool ResizeToViewport
{
get => _resizeToViewport;
set => SetProperty(ref _resizeToViewport, value);
}

private PointEditor _minimapViewportOffset = new Size(2000, 2000);
public PointEditor MinimapMaxViewportOffset
{
get => _minimapViewportOffset;
set => SetProperty(ref _minimapViewportOffset, value);
}

private bool _shouldConnectNodes = true;
public bool ShouldConnectNodes
{
Expand Down
7 changes: 6 additions & 1 deletion Examples/Nodify.Playground/PointEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public Size Size
});
}

public string XLabel { get; set; } = "x";
public string YLabel { get; set; } = "y";

public static implicit operator PointEditor(Point point)
{
return new PointEditor
Expand All @@ -68,7 +71,9 @@ public static implicit operator PointEditor(Size size)
return new PointEditor
{
X = size.Width,
Y = size.Height
Y = size.Height,
XLabel = "w",
YLabel = "h"
};
}
}
Expand Down
16 changes: 10 additions & 6 deletions Examples/Nodify.Playground/PointEditorView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<TextBlock Text="X:"
TextAlignment="Center"
VerticalAlignment="Center" />
<TextBlock TextAlignment="Center"
VerticalAlignment="Center">
<Run Text="{Binding XLabel}" />
<Run Text=":" />
</TextBlock>
<TextBox Text="{Binding X, Mode=TwoWay}"
Grid.Column="1" />

<TextBlock Text="Y:"
TextAlignment="Center"
<TextBlock TextAlignment="Center"
VerticalAlignment="Center"
Grid.Row="1"
Margin="0 5 0 0" />
Margin="0 5 0 0">
<Run Text="{Binding YLabel}" />
<Run Text=":" />
</TextBlock>
<TextBox Text="{Binding Y, Mode=TwoWay}"
Margin="0 5 0 0"
Grid.Row="1"
Expand Down
102 changes: 102 additions & 0 deletions Examples/Nodify.Shapes/Canvas/CanvasView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,108 @@
</nodify:NodifyEditor.ItemContainerStyle>
</nodify:NodifyEditor>

<!--MINIMAP-->
<shared:ResizablePanel Directions="BottomLeft"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Width="300"
Height="200"
MinWidth="250"
MinHeight="150"
BorderBrush="{x:Null}"
Margin="20">
<shared:ResizablePanel.Resources>
<Style TargetType="{x:Type shared:Resizer}">
<Setter Property="Cursor"
Value="SizeNESW" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type shared:Resizer}">
<Grid Margin="-3 -6 -6 -3" Background="Transparent">
<Rectangle Height="12"
Width="3"
Fill="#d2d4d7"
HorizontalAlignment="Left"
VerticalAlignment="Bottom" />
<Rectangle Height="3"
Width="12"
Fill="#d2d4d7"
VerticalAlignment="Bottom"
HorizontalAlignment="Left" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</shared:ResizablePanel.Resources>
<Border CornerRadius="3"
BorderBrush="#1e293b"
BorderThickness="3">
<Border.Effect>
<DropShadowEffect ShadowDepth="1" />
</Border.Effect>

<nodify:Minimap ItemsSource="{Binding ItemsSource, ElementName=Editor}"
ViewportLocation="{Binding ViewportLocation, ElementName=Editor}"
ViewportSize="{Binding ViewportSize, ElementName=Editor}"
ResizeToViewport="True"
Zoom="Minimap_Zoom">
<nodify:Minimap.Resources>
<DataTemplate DataType="{x:Type local:EllipseViewModel}">
<Ellipse Stretch="Fill"
Fill="{Binding Color, Converter={StaticResource ColorToSolidColorBrushConverter}}"
Stroke="{Binding BorderColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"
StrokeThickness="2"
Opacity="0.8" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:RectangleViewModel}">
<Rectangle Stretch="Fill"
Fill="{Binding Color, Converter={StaticResource ColorToSolidColorBrushConverter}}"
Stroke="{Binding BorderColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"
StrokeThickness="2"
Opacity="0.8" />
</DataTemplate>

<DataTemplate DataType="{x:Type local:TriangleViewModel}">
<Polygon Points="0,100 50,0 100,100"
Stretch="Fill"
Fill="{Binding Color, Converter={StaticResource ColorToSolidColorBrushConverter}}"
Stroke="{Binding BorderColor, Converter={StaticResource ColorToSolidColorBrushConverter}}"
StrokeThickness="2"
Opacity="0.8" />
</DataTemplate>
</nodify:Minimap.Resources>
<nodify:Minimap.Background>
<SolidColorBrush Color="#111a2d"
Opacity="0.5" />
</nodify:Minimap.Background>
<nodify:Minimap.ItemContainerStyle>
<Style TargetType="{x:Type nodify:MinimapItem}">
<Setter Property="Location"
Value="{Binding Location}" />
<Setter Property="Width"
Value="{Binding Width}" />
<Setter Property="Height"
Value="{Binding Height}" />
</Style>
</nodify:Minimap.ItemContainerStyle>
<nodify:Minimap.ViewportStyle>
<Style TargetType="Rectangle">
<Setter Property="StrokeThickness"
Value="3" />
<Setter Property="Fill">
<Setter.Value>
<SolidColorBrush Color="#445e87"
Opacity="0.3" />
</Setter.Value>
</Setter>
</Style>
</nodify:Minimap.ViewportStyle>
</nodify:Minimap>
</Border>
</shared:ResizablePanel>

<!--TOOLBARS-->

<Border VerticalAlignment="Bottom"
Expand Down
5 changes: 5 additions & 0 deletions Examples/Nodify.Shapes/Canvas/CanvasView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,10 @@ private void Toolbar_MouseDown(object sender, MouseButtonEventArgs e)
}

#endregion

private void Minimap_Zoom(object sender, ZoomEventArgs e)
{
Editor.ZoomAtPosition(e.Zoom, e.Location);
}
}
}
2 changes: 2 additions & 0 deletions Examples/Nodify.Shapes/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();

NodifyEditor.EnableDraggingContainersOptimizations = false;
}
}
}
8 changes: 4 additions & 4 deletions Nodify/Connections/BaseConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ public Size ArrowSize
}

/// <summary>
/// Splits the connection. Triggered by <see cref="EditorGestures.Connection.Split"/> gesture.
/// Splits the connection. Triggered by <see cref="EditorGestures.ConnectionGestures.Split"/> gesture.
/// Parameter is the location where the splitting ocurred.
/// </summary>
public ICommand? SplitCommand
Expand All @@ -282,7 +282,7 @@ public ICommand? SplitCommand
}

/// <summary>
/// Removes this connection. Triggered by <see cref="EditorGestures.Connection.Disconnect"/> gesture.
/// Removes this connection. Triggered by <see cref="EditorGestures.ConnectionGestures.Disconnect"/> gesture.
/// Parameter is the location where the disconnect ocurred.
/// </summary>
public ICommand? DisconnectCommand
Expand Down Expand Up @@ -352,14 +352,14 @@ public FontStretch FontStretch
public static readonly RoutedEvent DisconnectEvent = EventManager.RegisterRoutedEvent(nameof(Disconnect), RoutingStrategy.Bubble, typeof(ConnectionEventHandler), typeof(BaseConnection));
public static readonly RoutedEvent SplitEvent = EventManager.RegisterRoutedEvent(nameof(Split), RoutingStrategy.Bubble, typeof(ConnectionEventHandler), typeof(BaseConnection));

/// <summary>Triggered by the <see cref="EditorGestures.Connection.Disconnect"/> gesture.</summary>
/// <summary>Triggered by the <see cref="EditorGestures.ConnectionGestures.Disconnect"/> gesture.</summary>
public event ConnectionEventHandler Disconnect
{
add => AddHandler(DisconnectEvent, value);
remove => RemoveHandler(DisconnectEvent, value);
}

/// <summary>Triggered by the <see cref="EditorGestures.Connection.Split"/> gesture.</summary>
/// <summary>Triggered by the <see cref="EditorGestures.ConnectionGestures.Split"/> gesture.</summary>
public event ConnectionEventHandler Split
{
add => AddHandler(SplitEvent, value);
Expand Down
6 changes: 3 additions & 3 deletions Nodify/Connections/Connector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ public class Connector : Control
public static readonly RoutedEvent PendingConnectionDragEvent = EventManager.RegisterRoutedEvent(nameof(PendingConnectionDrag), RoutingStrategy.Bubble, typeof(PendingConnectionEventHandler), typeof(Connector));
public static readonly RoutedEvent DisconnectEvent = EventManager.RegisterRoutedEvent(nameof(Disconnect), RoutingStrategy.Bubble, typeof(ConnectorEventHandler), typeof(Connector));

/// <summary>Triggered by the <see cref="EditorGestures.Connector.Connect"/> gesture.</summary>
/// <summary>Triggered by the <see cref="EditorGestures.ConnectorGestures.Connect"/> gesture.</summary>
public event PendingConnectionEventHandler PendingConnectionStarted
{
add => AddHandler(PendingConnectionStartedEvent, value);
remove => RemoveHandler(PendingConnectionStartedEvent, value);
}

/// <summary>Triggered by the <see cref="EditorGestures.Connector.Connect"/> gesture.</summary>
/// <summary>Triggered by the <see cref="EditorGestures.ConnectorGestures.Connect"/> gesture.</summary>
public event PendingConnectionEventHandler PendingConnectionCompleted
{
add => AddHandler(PendingConnectionCompletedEvent, value);
Expand All @@ -43,7 +43,7 @@ public event PendingConnectionEventHandler PendingConnectionDrag
remove => RemoveHandler(PendingConnectionDragEvent, value);
}

/// <summary>Triggered by the <see cref="EditorGestures.Connector.Disconnect"/> gesture.</summary>
/// <summary>Triggered by the <see cref="EditorGestures.ConnectorGestures.Disconnect"/> gesture.</summary>
public event ConnectorEventHandler Disconnect
{
add => AddHandler(DisconnectEvent, value);
Expand Down
Loading
Loading