mirror of
https://github.com/egmont11/NetworkDiagram.git
synced 2026-07-24 07:09:43 +02:00
"Infinite" workspace for diagrams
This commit is contained in:
@@ -73,12 +73,23 @@
|
||||
</Border>
|
||||
|
||||
<!-- Canvas Area -->
|
||||
<ScrollViewer Grid.Row="1" Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="Transparent">
|
||||
<Canvas x:Name="DiagramCanvas" Width="2000" Height="2000" AllowDrop="True"
|
||||
<Grid Grid.Row="1" Grid.Column="1" x:Name="CanvasViewport" ClipToBounds="True" Background="Transparent"
|
||||
MouseDown="Viewport_MouseDown"
|
||||
MouseMove="Viewport_MouseMove"
|
||||
MouseUp="Viewport_MouseUp"
|
||||
MouseWheel="Viewport_MouseWheel">
|
||||
<!-- Increased size to 40k to provide plenty of space in all directions -->
|
||||
<Canvas x:Name="DiagramCanvas" Width="40000" Height="40000" AllowDrop="True"
|
||||
Drop="DiagramCanvas_Drop" DragOver="DiagramCanvas_DragOver"
|
||||
MouseDown="DiagramCanvas_MouseDown"
|
||||
MouseMove="DiagramCanvas_MouseMove"
|
||||
MouseUp="DiagramCanvas_MouseUp">
|
||||
<Canvas.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform x:Name="CanvasScale" ScaleX="1" ScaleY="1"/>
|
||||
<TranslateTransform x:Name="CanvasTranslate" X="-20000" Y="-20000"/>
|
||||
</TransformGroup>
|
||||
</Canvas.RenderTransform>
|
||||
<Canvas.Background>
|
||||
<VisualBrush TileMode="Tile" Viewport="0,0,40,40" ViewportUnits="Absolute">
|
||||
<VisualBrush.Visual>
|
||||
@@ -122,6 +133,6 @@
|
||||
<Rectangle x:Name="SelectionRect" Stroke="{StaticResource AccentBlue}" StrokeThickness="1.5" StrokeDashArray="3,3"
|
||||
Fill="#220078D7" Visibility="Collapsed" Panel.ZIndex="9999" RadiusX="2" RadiusY="2" IsHitTestVisible="False"/>
|
||||
</Canvas>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -30,12 +30,85 @@ namespace NetworkDiagram
|
||||
private readonly Dictionary<Connection, Line> _connectionLines = new();
|
||||
private readonly Dictionary<PlacedDevice, FrameworkElement> _deviceElements = new();
|
||||
|
||||
// Panning and Zooming
|
||||
private Point _lastPanPoint;
|
||||
private bool _isPanning;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
LoadTemplates();
|
||||
this.Loaded += MainWindow_Loaded;
|
||||
}
|
||||
|
||||
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CenterView();
|
||||
}
|
||||
|
||||
private void CenterView()
|
||||
{
|
||||
// Center logically on (20000, 20000) minus half the viewport size to put 0,0 in the middle
|
||||
CanvasTranslate.X = -20000 + (CanvasViewport.ActualWidth / 2);
|
||||
CanvasTranslate.Y = -20000 + (CanvasViewport.ActualHeight / 2);
|
||||
CanvasScale.ScaleX = 1.0;
|
||||
CanvasScale.ScaleY = 1.0;
|
||||
}
|
||||
|
||||
#region Panning and Zooming
|
||||
private void Viewport_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Middle)
|
||||
{
|
||||
_isPanning = true;
|
||||
_lastPanPoint = e.GetPosition(CanvasViewport);
|
||||
CanvasViewport.CaptureMouse();
|
||||
}
|
||||
}
|
||||
|
||||
private void Viewport_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_isPanning)
|
||||
{
|
||||
Point currentPoint = e.GetPosition(CanvasViewport);
|
||||
double deltaX = currentPoint.X - _lastPanPoint.X;
|
||||
double deltaY = currentPoint.Y - _lastPanPoint.Y;
|
||||
|
||||
CanvasTranslate.X += deltaX;
|
||||
CanvasTranslate.Y += deltaY;
|
||||
|
||||
_lastPanPoint = currentPoint;
|
||||
}
|
||||
}
|
||||
|
||||
private void Viewport_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton == MouseButton.Middle)
|
||||
{
|
||||
_isPanning = false;
|
||||
CanvasViewport.ReleaseMouseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
private void Viewport_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
double zoom = e.Delta > 0 ? 1.1 : 0.9;
|
||||
|
||||
double newScale = CanvasScale.ScaleX * zoom;
|
||||
if (newScale < 0.1 || newScale > 5) return;
|
||||
|
||||
Point mousePos = e.GetPosition(DiagramCanvas);
|
||||
|
||||
// Zoom centered on mouse
|
||||
CanvasScale.ScaleX = newScale;
|
||||
CanvasScale.ScaleY = newScale;
|
||||
|
||||
Point newMousePos = e.GetPosition(DiagramCanvas);
|
||||
CanvasTranslate.X += (newMousePos.X - mousePos.X) * CanvasScale.ScaleX;
|
||||
CanvasTranslate.Y += (newMousePos.Y - mousePos.Y) * CanvasScale.ScaleY;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void LoadTemplates()
|
||||
{
|
||||
try
|
||||
@@ -457,9 +530,13 @@ namespace NetworkDiagram
|
||||
{
|
||||
_currentDiagram = new Diagram();
|
||||
DiagramCanvas.Children.Clear();
|
||||
// Re-add selection rectangle after clearing
|
||||
if (SelectionRect != null) DiagramCanvas.Children.Add(SelectionRect);
|
||||
|
||||
_connectionLines.Clear();
|
||||
_deviceElements.Clear();
|
||||
ClearSelection();
|
||||
CenterView();
|
||||
}
|
||||
|
||||
private void SaveDiagram_Click(object sender, RoutedEventArgs e)
|
||||
@@ -497,15 +574,35 @@ namespace NetworkDiagram
|
||||
}
|
||||
|
||||
DiagramCanvas.Children.Clear();
|
||||
// Re-add selection rectangle after clearing
|
||||
if (SelectionRect != null) DiagramCanvas.Children.Add(SelectionRect);
|
||||
|
||||
_connectionLines.Clear();
|
||||
_deviceElements.Clear();
|
||||
ClearSelection();
|
||||
|
||||
foreach (var device in _currentDiagram.Devices) RenderDevice(device);
|
||||
foreach (var conn in model.Connections.Select(cModel => new Connection { StartDevice = _currentDiagram.Devices[cModel.StartIndex], EndDevice = _currentDiagram.Devices[cModel.EndIndex], Type = cModel.Type }))
|
||||
{
|
||||
_currentDiagram.Connections.Add(conn);
|
||||
RenderConnection(conn);
|
||||
}
|
||||
|
||||
// Center on loaded content
|
||||
if (_currentDiagram.Devices.Count > 0)
|
||||
{
|
||||
double minX = _currentDiagram.Devices.Min(d => d.X);
|
||||
double minY = _currentDiagram.Devices.Min(d => d.Y);
|
||||
double maxX = _currentDiagram.Devices.Max(d => d.X);
|
||||
double maxY = _currentDiagram.Devices.Max(d => d.Y);
|
||||
|
||||
CanvasTranslate.X = -((minX + maxX) / 2) * CanvasScale.ScaleX + (CanvasViewport.ActualWidth / 2);
|
||||
CanvasTranslate.Y = -((minY + maxY) / 2) * CanvasScale.ScaleY + (CanvasViewport.ActualHeight / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
CenterView();
|
||||
}
|
||||
}
|
||||
|
||||
private void WireTool_Click(object sender, RoutedEventArgs e) => _activeTool = ConnectionType.Wire;
|
||||
|
||||
Reference in New Issue
Block a user