mirror of
https://github.com/egmont11/NetworkDiagram.git
synced 2026-07-24 07:09:43 +02:00
Inverting ifs, using switchcases etc. The things the IDE likes more.
This commit is contained in:
@@ -1,6 +1,4 @@
|
|||||||
using System.Configuration;
|
using System.Windows;
|
||||||
using System.Data;
|
|
||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace NetworkDiagram;
|
namespace NetworkDiagram;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using NetworkDiagram.Models;
|
using NetworkDiagram.Models;
|
||||||
|
|
||||||
namespace NetworkDiagram
|
namespace NetworkDiagram
|
||||||
{
|
{
|
||||||
public partial class EditDeviceWindow : Window
|
public partial class EditDeviceWindow
|
||||||
{
|
{
|
||||||
private PlacedDevice _device;
|
private readonly PlacedDevice _device;
|
||||||
|
|
||||||
public EditDeviceWindow(PlacedDevice device)
|
public EditDeviceWindow(PlacedDevice device)
|
||||||
{
|
{
|
||||||
@@ -20,7 +18,7 @@ namespace NetworkDiagram
|
|||||||
private void Save_Click(object sender, RoutedEventArgs e)
|
private void Save_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_device.Name = NameBox.Text;
|
_device.Name = NameBox.Text;
|
||||||
_device.IpAddresses = IpBox.Text.Split(new[] { Environment.NewLine, "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
_device.IpAddresses = IpBox.Text.Split([Environment.NewLine, "\n", "\r"], StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||||
DialogResult = true;
|
DialogResult = true;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
+198
-184
@@ -1,9 +1,5 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@@ -16,13 +12,13 @@ using Path = System.IO.Path;
|
|||||||
|
|
||||||
namespace NetworkDiagram
|
namespace NetworkDiagram
|
||||||
{
|
{
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow
|
||||||
{
|
{
|
||||||
private List<DeviceTemplate> _deviceTemplates = new List<DeviceTemplate>();
|
private List<DeviceTemplate> _deviceTemplates = [];
|
||||||
private Diagram _currentDiagram = new Diagram();
|
private Diagram _currentDiagram = new();
|
||||||
|
|
||||||
// Selection & Dragging
|
// Selection & Dragging
|
||||||
private HashSet<FrameworkElement> _selectedElements = new HashSet<FrameworkElement>();
|
private readonly HashSet<FrameworkElement> _selectedElements = [];
|
||||||
private Point _dragStartPoint;
|
private Point _dragStartPoint;
|
||||||
private bool _isDraggingDevices;
|
private bool _isDraggingDevices;
|
||||||
private bool _isSelectingArea;
|
private bool _isSelectingArea;
|
||||||
@@ -31,8 +27,8 @@ namespace NetworkDiagram
|
|||||||
private ConnectionType? _activeTool;
|
private ConnectionType? _activeTool;
|
||||||
private PlacedDevice? _firstDeviceForConnection;
|
private PlacedDevice? _firstDeviceForConnection;
|
||||||
|
|
||||||
private Dictionary<Connection, Line> _connectionLines = new Dictionary<Connection, Line>();
|
private readonly Dictionary<Connection, Line> _connectionLines = new();
|
||||||
private Dictionary<PlacedDevice, FrameworkElement> _deviceElements = new Dictionary<PlacedDevice, FrameworkElement>();
|
private readonly Dictionary<PlacedDevice, FrameworkElement> _deviceElements = new();
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
@@ -44,40 +40,42 @@ namespace NetworkDiagram
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (File.Exists("devices.json"))
|
if (!File.Exists("devices.json")) return;
|
||||||
|
|
||||||
|
var json = File.ReadAllText("devices.json");
|
||||||
|
_deviceTemplates = JsonSerializer.Deserialize<List<DeviceTemplate>>(json) ?? [];
|
||||||
|
|
||||||
|
foreach (var t in _deviceTemplates.Where(t => !string.IsNullOrEmpty(t.IconPath)))
|
||||||
{
|
{
|
||||||
string json = File.ReadAllText("devices.json");
|
t.IconPath = Path.GetFullPath(t.IconPath);
|
||||||
_deviceTemplates = JsonSerializer.Deserialize<List<DeviceTemplate>>(json) ?? new List<DeviceTemplate>();
|
|
||||||
foreach(var t in _deviceTemplates)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(t.IconPath)) t.IconPath = Path.GetFullPath(t.IconPath);
|
|
||||||
}
|
|
||||||
ToolboxList.ItemsSource = _deviceTemplates;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToolboxList.ItemsSource = _deviceTemplates;
|
||||||
}
|
}
|
||||||
catch (Exception ex) { MessageBox.Show($"Error loading templates: {ex.Message}"); }
|
catch (Exception ex) { MessageBox.Show($"Error loading templates: {ex.Message}"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetLocalizedString(string key) => Application.Current.Resources[key] as string ?? key;
|
private static string GetLocalizedString(string key) => Application.Current.Resources[key] as string ?? key;
|
||||||
|
|
||||||
private void LangCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
private void LangCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (LangCombo.SelectedItem is ComboBoxItem item && item.Tag is string lang)
|
if (LangCombo.SelectedItem is not ComboBoxItem { Tag: string lang }) return;
|
||||||
|
|
||||||
|
var dict = new ResourceDictionary
|
||||||
{
|
{
|
||||||
var dict = new ResourceDictionary();
|
Source = new Uri($"Localization/Strings.{lang}.xaml", UriKind.Relative)
|
||||||
dict.Source = new Uri($"Localization/Strings.{lang}.xaml", UriKind.Relative);
|
};
|
||||||
|
|
||||||
// Replace the existing localization dictionary
|
// Replace the existing localization dictionary
|
||||||
var oldDict = Application.Current.Resources.MergedDictionaries.FirstOrDefault(d => d.Source != null && d.Source.OriginalString.Contains("Localization/Strings."));
|
var oldDict = Application.Current.Resources.MergedDictionaries.FirstOrDefault(d => d.Source != null && d.Source.OriginalString.Contains("Localization/Strings."));
|
||||||
if (oldDict != null) Application.Current.Resources.MergedDictionaries.Remove(oldDict);
|
if (oldDict != null) Application.Current.Resources.MergedDictionaries.Remove(oldDict);
|
||||||
Application.Current.Resources.MergedDictionaries.Add(dict);
|
Application.Current.Resources.MergedDictionaries.Add(dict);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Drag and Drop (Toolbox to Canvas)
|
#region Drag and Drop (Toolbox to Canvas)
|
||||||
private void Toolbox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
|
private void Toolbox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is ListBox listBox && listBox.SelectedItem is DeviceTemplate template)
|
if (sender is ListBox { SelectedItem: DeviceTemplate template } listBox)
|
||||||
DragDrop.DoDragDrop(listBox, template, DragDropEffects.Copy);
|
DragDrop.DoDragDrop(listBox, template, DragDropEffects.Copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,12 +87,11 @@ namespace NetworkDiagram
|
|||||||
|
|
||||||
private void DiagramCanvas_Drop(object sender, DragEventArgs e)
|
private void DiagramCanvas_Drop(object sender, DragEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Data.GetDataPresent(typeof(DeviceTemplate)))
|
if (!e.Data.GetDataPresent(typeof(DeviceTemplate))) return;
|
||||||
{
|
|
||||||
var template = (DeviceTemplate)e.Data.GetData(typeof(DeviceTemplate));
|
var template = (DeviceTemplate)e.Data.GetData(typeof(DeviceTemplate));
|
||||||
Point dropPoint = e.GetPosition(DiagramCanvas);
|
var dropPoint = e.GetPosition(DiagramCanvas);
|
||||||
AddDeviceToCanvas(template, dropPoint.X, dropPoint.Y);
|
AddDeviceToCanvas(template, dropPoint.X, dropPoint.Y);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -118,18 +115,26 @@ namespace NetworkDiagram
|
|||||||
Canvas.SetLeft(container, device.X);
|
Canvas.SetLeft(container, device.X);
|
||||||
Canvas.SetTop(container, device.Y);
|
Canvas.SetTop(container, device.Y);
|
||||||
|
|
||||||
device.PropertyChanged += (s, e) => {
|
device.PropertyChanged += (s, e) =>
|
||||||
if (e.PropertyName == nameof(PlacedDevice.X)) Canvas.SetLeft(container, device.X);
|
{
|
||||||
if (e.PropertyName == nameof(PlacedDevice.Y)) Canvas.SetTop(container, device.Y);
|
switch (e.PropertyName)
|
||||||
|
{
|
||||||
|
case nameof(PlacedDevice.X):
|
||||||
|
Canvas.SetLeft(container, device.X);
|
||||||
|
break;
|
||||||
|
case nameof(PlacedDevice.Y):
|
||||||
|
Canvas.SetTop(container, device.Y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
container.MouseDown += Device_MouseDown;
|
container.MouseDown += Device_MouseDown;
|
||||||
container.MouseLeftButtonDown += (s, e) => {
|
container.MouseLeftButtonDown += (s, e) =>
|
||||||
if (e.ClickCount == 2) {
|
{
|
||||||
StopDragging();
|
if (e.ClickCount != 2) return;
|
||||||
EditDevice(device);
|
StopDragging();
|
||||||
e.Handled = true;
|
EditDevice(device);
|
||||||
}
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
_deviceElements[device] = container;
|
_deviceElements[device] = container;
|
||||||
@@ -146,36 +151,35 @@ namespace NetworkDiagram
|
|||||||
|
|
||||||
private void Device_MouseDown(object sender, MouseButtonEventArgs e)
|
private void Device_MouseDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is FrameworkElement element && element.Tag is PlacedDevice device)
|
if (sender is not FrameworkElement { Tag: PlacedDevice device } element) return;
|
||||||
|
|
||||||
|
if (_activeTool != null)
|
||||||
{
|
{
|
||||||
if (_activeTool != null)
|
HandleConnectionTool(device, element);
|
||||||
{
|
|
||||||
HandleConnectionTool(device, element);
|
|
||||||
e.Handled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Selection
|
|
||||||
if (!Keyboard.IsKeyDown(Key.LeftCtrl) && !Keyboard.IsKeyDown(Key.RightCtrl))
|
|
||||||
{
|
|
||||||
if (!_selectedElements.Contains(element))
|
|
||||||
{
|
|
||||||
ClearSelection();
|
|
||||||
SelectElement(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_selectedElements.Contains(element)) DeselectElement(element);
|
|
||||||
else SelectElement(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start Dragging
|
|
||||||
_isDraggingDevices = true;
|
|
||||||
_dragStartPoint = e.GetPosition(DiagramCanvas);
|
|
||||||
DiagramCanvas.CaptureMouse();
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle Selection
|
||||||
|
if (!Keyboard.IsKeyDown(Key.LeftCtrl) && !Keyboard.IsKeyDown(Key.RightCtrl))
|
||||||
|
{
|
||||||
|
if (!_selectedElements.Contains(element))
|
||||||
|
{
|
||||||
|
ClearSelection();
|
||||||
|
SelectElement(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_selectedElements.Contains(element)) DeselectElement(element);
|
||||||
|
else SelectElement(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Dragging
|
||||||
|
_isDraggingDevices = true;
|
||||||
|
_dragStartPoint = e.GetPosition(DiagramCanvas);
|
||||||
|
DiagramCanvas.CaptureMouse();
|
||||||
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectElement(FrameworkElement element)
|
private void SelectElement(FrameworkElement element)
|
||||||
@@ -196,15 +200,16 @@ namespace NetworkDiagram
|
|||||||
private void DeselectElement(FrameworkElement element)
|
private void DeselectElement(FrameworkElement element)
|
||||||
{
|
{
|
||||||
_selectedElements.Remove(element);
|
_selectedElements.Remove(element);
|
||||||
if (element is Border b)
|
switch (element)
|
||||||
{
|
{
|
||||||
b.BorderBrush = Brushes.Transparent;
|
case Border b:
|
||||||
b.Background = Brushes.Transparent;
|
b.BorderBrush = Brushes.Transparent;
|
||||||
}
|
b.Background = Brushes.Transparent;
|
||||||
else if (element is Line l)
|
break;
|
||||||
{
|
case Line l:
|
||||||
l.StrokeThickness = 3;
|
l.StrokeThickness = 3;
|
||||||
l.Opacity = 1.0;
|
l.Opacity = 1.0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,14 +238,14 @@ namespace NetworkDiagram
|
|||||||
|
|
||||||
private void DiagramCanvas_MouseMove(object sender, MouseEventArgs e)
|
private void DiagramCanvas_MouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
Point currentPoint = e.GetPosition(DiagramCanvas);
|
var currentPoint = e.GetPosition(DiagramCanvas);
|
||||||
|
|
||||||
if (_isSelectingArea)
|
if (_isSelectingArea)
|
||||||
{
|
{
|
||||||
double x = Math.Min(_selectionStartPoint.X, currentPoint.X);
|
var x = Math.Min(_selectionStartPoint.X, currentPoint.X);
|
||||||
double y = Math.Min(_selectionStartPoint.Y, currentPoint.Y);
|
var y = Math.Min(_selectionStartPoint.Y, currentPoint.Y);
|
||||||
double w = Math.Abs(_selectionStartPoint.X - currentPoint.X);
|
var w = Math.Abs(_selectionStartPoint.X - currentPoint.X);
|
||||||
double h = Math.Abs(_selectionStartPoint.Y - currentPoint.Y);
|
var h = Math.Abs(_selectionStartPoint.Y - currentPoint.Y);
|
||||||
|
|
||||||
Canvas.SetLeft(SelectionRect, x);
|
Canvas.SetLeft(SelectionRect, x);
|
||||||
Canvas.SetTop(SelectionRect, y);
|
Canvas.SetTop(SelectionRect, y);
|
||||||
@@ -248,10 +253,10 @@ namespace NetworkDiagram
|
|||||||
SelectionRect.Height = h;
|
SelectionRect.Height = h;
|
||||||
|
|
||||||
// Real-time selection preview
|
// Real-time selection preview
|
||||||
Rect selectionBounds = new Rect(x, y, w, h);
|
var selectionBounds = new Rect(x, y, w, h);
|
||||||
foreach (var border in _deviceElements.Values)
|
foreach (var border in _deviceElements.Values)
|
||||||
{
|
{
|
||||||
Rect elementBounds = new Rect(Canvas.GetLeft(border), Canvas.GetTop(border), border.ActualWidth, border.ActualHeight);
|
var elementBounds = new Rect(Canvas.GetLeft(border), Canvas.GetTop(border), border.ActualWidth, border.ActualHeight);
|
||||||
if (selectionBounds.IntersectsWith(elementBounds))
|
if (selectionBounds.IntersectsWith(elementBounds))
|
||||||
{
|
{
|
||||||
if (!_selectedElements.Contains(border)) SelectElement(border);
|
if (!_selectedElements.Contains(border)) SelectElement(border);
|
||||||
@@ -266,7 +271,7 @@ namespace NetworkDiagram
|
|||||||
// Also preview for lines
|
// Also preview for lines
|
||||||
foreach (var line in _connectionLines.Values)
|
foreach (var line in _connectionLines.Values)
|
||||||
{
|
{
|
||||||
Rect lineBounds = new Rect(
|
var lineBounds = new Rect(
|
||||||
Math.Min(line.X1, line.X2),
|
Math.Min(line.X1, line.X2),
|
||||||
Math.Min(line.Y1, line.Y2),
|
Math.Min(line.Y1, line.Y2),
|
||||||
Math.Abs(line.X1 - line.X2),
|
Math.Abs(line.X1 - line.X2),
|
||||||
@@ -284,8 +289,8 @@ namespace NetworkDiagram
|
|||||||
}
|
}
|
||||||
else if (_isDraggingDevices && e.LeftButton == MouseButtonState.Pressed)
|
else if (_isDraggingDevices && e.LeftButton == MouseButtonState.Pressed)
|
||||||
{
|
{
|
||||||
double deltaX = currentPoint.X - _dragStartPoint.X;
|
var deltaX = currentPoint.X - _dragStartPoint.X;
|
||||||
double deltaY = currentPoint.Y - _dragStartPoint.Y;
|
var deltaY = currentPoint.Y - _dragStartPoint.Y;
|
||||||
|
|
||||||
foreach (var element in _selectedElements)
|
foreach (var element in _selectedElements)
|
||||||
{
|
{
|
||||||
@@ -303,7 +308,7 @@ namespace NetworkDiagram
|
|||||||
{
|
{
|
||||||
if (_isSelectingArea)
|
if (_isSelectingArea)
|
||||||
{
|
{
|
||||||
Rect selectionBounds = new Rect(
|
var selectionBounds = new Rect(
|
||||||
Canvas.GetLeft(SelectionRect),
|
Canvas.GetLeft(SelectionRect),
|
||||||
Canvas.GetTop(SelectionRect),
|
Canvas.GetTop(SelectionRect),
|
||||||
SelectionRect.Width,
|
SelectionRect.Width,
|
||||||
@@ -311,7 +316,7 @@ namespace NetworkDiagram
|
|||||||
|
|
||||||
foreach (var border in _deviceElements.Values)
|
foreach (var border in _deviceElements.Values)
|
||||||
{
|
{
|
||||||
Rect elementBounds = new Rect(Canvas.GetLeft(border), Canvas.GetTop(border), border.ActualWidth, border.ActualHeight);
|
var elementBounds = new Rect(Canvas.GetLeft(border), Canvas.GetTop(border), border.ActualWidth, border.ActualHeight);
|
||||||
if (selectionBounds.IntersectsWith(elementBounds)) SelectElement(border);
|
if (selectionBounds.IntersectsWith(elementBounds)) SelectElement(border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,7 +358,7 @@ namespace NetworkDiagram
|
|||||||
StrokeThickness = 3,
|
StrokeThickness = 3,
|
||||||
Tag = conn
|
Tag = conn
|
||||||
};
|
};
|
||||||
if (conn.Type == ConnectionType.Wifi) line.StrokeDashArray = new DoubleCollection { 2, 2 };
|
if (conn.Type == ConnectionType.Wifi) line.StrokeDashArray = [2, 2];
|
||||||
|
|
||||||
UpdateLinePosition(conn, line);
|
UpdateLinePosition(conn, line);
|
||||||
|
|
||||||
@@ -372,60 +377,68 @@ namespace NetworkDiagram
|
|||||||
|
|
||||||
private void UpdateLinePosition(Connection conn, Line line)
|
private void UpdateLinePosition(Connection conn, Line line)
|
||||||
{
|
{
|
||||||
if (_deviceElements.TryGetValue(conn.StartDevice, out var startElem) &&
|
if (!_deviceElements.TryGetValue(conn.StartDevice, out var startElem) ||
|
||||||
_deviceElements.TryGetValue(conn.EndDevice, out var endElem))
|
!_deviceElements.TryGetValue(conn.EndDevice, out var endElem)) return;
|
||||||
{
|
|
||||||
if (startElem.ActualWidth == 0) startElem.UpdateLayout();
|
if (startElem.ActualWidth == 0) startElem.UpdateLayout();
|
||||||
if (endElem.ActualWidth == 0) endElem.UpdateLayout();
|
if (endElem.ActualWidth == 0) endElem.UpdateLayout();
|
||||||
|
|
||||||
line.X1 = conn.StartDevice.X + (startElem.ActualWidth / 2);
|
line.X1 = conn.StartDevice.X + (startElem.ActualWidth / 2);
|
||||||
line.Y1 = conn.StartDevice.Y + 24;
|
line.Y1 = conn.StartDevice.Y + 24;
|
||||||
line.X2 = conn.EndDevice.X + (endElem.ActualWidth / 2);
|
line.X2 = conn.EndDevice.X + (endElem.ActualWidth / 2);
|
||||||
line.Y2 = conn.EndDevice.Y + 24;
|
line.Y2 = conn.EndDevice.Y + 24;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_KeyDown(object sender, KeyEventArgs e)
|
private void Window_KeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.Delete && _selectedElements.Count > 0)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
foreach (var el in _selectedElements.ToList())
|
case Key.Delete when _selectedElements.Count > 0:
|
||||||
{
|
{
|
||||||
if (el is Line line && el.Tag is Connection conn)
|
foreach (var el in _selectedElements.ToList())
|
||||||
{
|
{
|
||||||
_currentDiagram.Connections.Remove(conn);
|
switch (el)
|
||||||
_connectionLines.Remove(conn);
|
|
||||||
DiagramCanvas.Children.Remove(line);
|
|
||||||
}
|
|
||||||
else if (el is Border border && border.Tag is PlacedDevice device)
|
|
||||||
{
|
|
||||||
_currentDiagram.Devices.Remove(device);
|
|
||||||
_deviceElements.Remove(device);
|
|
||||||
var toRemove = _currentDiagram.Connections.Where(c => c.StartDevice == device || c.EndDevice == device).ToList();
|
|
||||||
foreach (var c in toRemove)
|
|
||||||
{
|
{
|
||||||
if (_connectionLines.TryGetValue(c, out var l)) DiagramCanvas.Children.Remove(l);
|
case Line line when el.Tag is Connection conn:
|
||||||
_currentDiagram.Connections.Remove(c);
|
_currentDiagram.Connections.Remove(conn);
|
||||||
_connectionLines.Remove(c);
|
_connectionLines.Remove(conn);
|
||||||
|
DiagramCanvas.Children.Remove(line);
|
||||||
|
break;
|
||||||
|
case Border { Tag: PlacedDevice device } border:
|
||||||
|
{
|
||||||
|
_currentDiagram.Devices.Remove(device);
|
||||||
|
_deviceElements.Remove(device);
|
||||||
|
var toRemove = _currentDiagram.Connections.Where(c => c.StartDevice == device || c.EndDevice == device).ToList();
|
||||||
|
foreach (var c in toRemove)
|
||||||
|
{
|
||||||
|
if (_connectionLines.TryGetValue(c, out var l)) DiagramCanvas.Children.Remove(l);
|
||||||
|
_currentDiagram.Connections.Remove(c);
|
||||||
|
_connectionLines.Remove(c);
|
||||||
|
}
|
||||||
|
DiagramCanvas.Children.Remove(border);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DiagramCanvas.Children.Remove(border);
|
|
||||||
}
|
}
|
||||||
|
_selectedElements.Clear();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
_selectedElements.Clear();
|
case Key.Escape:
|
||||||
|
ResetConnectionTool(); StopDragging(); ClearSelection();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (e.Key == Key.Escape) { ResetConnectionTool(); StopDragging(); ClearSelection(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EditDevice(PlacedDevice device)
|
private void EditDevice(PlacedDevice device)
|
||||||
{
|
{
|
||||||
var dialog = new EditDeviceWindow(device);
|
var dialog = new EditDeviceWindow(device);
|
||||||
dialog.ShowDialog();
|
dialog.ShowDialog();
|
||||||
if (_deviceElements.TryGetValue(device, out var elem))
|
|
||||||
{
|
if (!_deviceElements.TryGetValue(device, out var elem)) return;
|
||||||
elem.UpdateLayout();
|
|
||||||
var attached = _currentDiagram.Connections.Where(c => c.StartDevice == device || c.EndDevice == device).ToList();
|
elem.UpdateLayout();
|
||||||
foreach(var c in attached) if (_connectionLines.TryGetValue(c, out var l)) UpdateLinePosition(c, l);
|
var attached = _currentDiagram.Connections.Where(c => c.StartDevice == device || c.EndDevice == device).ToList();
|
||||||
}
|
foreach(var c in attached) if (_connectionLines.TryGetValue(c, out var l)) UpdateLinePosition(c, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Toolbar Events
|
#region Toolbar Events
|
||||||
@@ -441,48 +454,46 @@ namespace NetworkDiagram
|
|||||||
private void SaveDiagram_Click(object sender, RoutedEventArgs e)
|
private void SaveDiagram_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var sfd = new SaveFileDialog { Filter = "Network Diagram (*.ndjson)|*.ndjson" };
|
var sfd = new SaveFileDialog { Filter = "Network Diagram (*.ndjson)|*.ndjson" };
|
||||||
if (sfd.ShowDialog() == true)
|
if (sfd.ShowDialog() != true) return;
|
||||||
{
|
|
||||||
var model = new DiagramSaveModel {
|
var model = new DiagramSaveModel {
|
||||||
Devices = _currentDiagram.Devices,
|
Devices = _currentDiagram.Devices,
|
||||||
Connections = _currentDiagram.Connections.Select(c => new ConnectionSaveModel {
|
Connections = _currentDiagram.Connections.Select(c => new ConnectionSaveModel {
|
||||||
StartIndex = _currentDiagram.Devices.IndexOf(c.StartDevice),
|
StartIndex = _currentDiagram.Devices.IndexOf(c.StartDevice),
|
||||||
EndIndex = _currentDiagram.Devices.IndexOf(c.EndDevice),
|
EndIndex = _currentDiagram.Devices.IndexOf(c.EndDevice),
|
||||||
Type = c.Type
|
Type = c.Type
|
||||||
}).ToList()
|
}).ToList()
|
||||||
};
|
};
|
||||||
string json = JsonSerializer.Serialize(model, new JsonSerializerOptions { WriteIndented = true });
|
|
||||||
File.WriteAllText(sfd.FileName, json);
|
var json = JsonSerializer.Serialize(model, new JsonSerializerOptions { WriteIndented = true });
|
||||||
}
|
File.WriteAllText(sfd.FileName, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadDiagram_Click(object sender, RoutedEventArgs e)
|
private void LoadDiagram_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var ofd = new OpenFileDialog { Filter = "Network Diagram (*.ndjson)|*.ndjson" };
|
var ofd = new OpenFileDialog { Filter = "Network Diagram (*.ndjson)|*.ndjson" };
|
||||||
if (ofd.ShowDialog() == true)
|
if (ofd.ShowDialog() != true) return;
|
||||||
|
|
||||||
|
var json = File.ReadAllText(ofd.FileName);
|
||||||
|
var model = JsonSerializer.Deserialize<DiagramSaveModel>(json);
|
||||||
|
if (model == null) return;
|
||||||
|
_currentDiagram = new Diagram { Devices = model.Devices };
|
||||||
|
|
||||||
|
foreach (var device in _currentDiagram.Devices)
|
||||||
{
|
{
|
||||||
string json = File.ReadAllText(ofd.FileName);
|
var template = _deviceTemplates.FirstOrDefault(t => t.Name == device.TemplateName);
|
||||||
var model = JsonSerializer.Deserialize<DiagramSaveModel>(json);
|
if (template != null) device.IconPath = template.IconPath;
|
||||||
if (model == null) return;
|
}
|
||||||
_currentDiagram = new Diagram { Devices = model.Devices };
|
|
||||||
|
|
||||||
foreach (var device in _currentDiagram.Devices)
|
DiagramCanvas.Children.Clear();
|
||||||
{
|
_connectionLines.Clear();
|
||||||
var template = _deviceTemplates.FirstOrDefault(t => t.Name == device.TemplateName);
|
_deviceElements.Clear();
|
||||||
if (template != null) device.IconPath = template.IconPath;
|
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 }))
|
||||||
DiagramCanvas.Children.Clear();
|
{
|
||||||
_connectionLines.Clear();
|
_currentDiagram.Connections.Add(conn);
|
||||||
_deviceElements.Clear();
|
RenderConnection(conn);
|
||||||
ClearSelection();
|
|
||||||
foreach (var device in _currentDiagram.Devices) RenderDevice(device);
|
|
||||||
foreach (var cModel in model.Connections)
|
|
||||||
{
|
|
||||||
var conn = new Connection { StartDevice = _currentDiagram.Devices[cModel.StartIndex], EndDevice = _currentDiagram.Devices[cModel.EndIndex], Type = cModel.Type };
|
|
||||||
_currentDiagram.Connections.Add(conn);
|
|
||||||
RenderConnection(conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,14 +515,14 @@ namespace NetworkDiagram
|
|||||||
var result = MessageBox.Show(GetLocalizedString("ExportWhiteBgMsg"), GetLocalizedString("ExportOptionsTitle"), MessageBoxButton.YesNoCancel);
|
var result = MessageBox.Show(GetLocalizedString("ExportWhiteBgMsg"), GetLocalizedString("ExportOptionsTitle"), MessageBoxButton.YesNoCancel);
|
||||||
if (result == MessageBoxResult.Cancel) return;
|
if (result == MessageBoxResult.Cancel) return;
|
||||||
|
|
||||||
bool whiteBg = result == MessageBoxResult.Yes;
|
var whiteBg = result == MessageBoxResult.Yes;
|
||||||
|
|
||||||
// 1. Find content bounds
|
// 1. Find content bounds
|
||||||
double minX = double.MaxValue, minY = double.MaxValue, maxX = double.MinValue, maxY = double.MinValue;
|
double minX = double.MaxValue, minY = double.MaxValue, maxX = double.MinValue, maxY = double.MinValue;
|
||||||
foreach (var border in _deviceElements.Values)
|
foreach (var border in _deviceElements.Values)
|
||||||
{
|
{
|
||||||
double x = Canvas.GetLeft(border);
|
var x = Canvas.GetLeft(border);
|
||||||
double y = Canvas.GetTop(border);
|
var y = Canvas.GetTop(border);
|
||||||
minX = Math.Min(minX, x);
|
minX = Math.Min(minX, x);
|
||||||
minY = Math.Min(minY, y);
|
minY = Math.Min(minY, y);
|
||||||
maxX = Math.Max(maxX, x + border.ActualWidth);
|
maxX = Math.Max(maxX, x + border.ActualWidth);
|
||||||
@@ -525,16 +536,16 @@ namespace NetworkDiagram
|
|||||||
maxY = Math.Max(maxY, Math.Max(line.Y1, line.Y2));
|
maxY = Math.Max(maxY, Math.Max(line.Y1, line.Y2));
|
||||||
}
|
}
|
||||||
|
|
||||||
double margin = 20;
|
const double margin = 20;
|
||||||
minX -= margin; minY -= margin; maxX += margin; maxY += margin;
|
minX -= margin; minY -= margin; maxX += margin; maxY += margin;
|
||||||
double width = Math.Max(1, maxX - minX);
|
var width = Math.Max(1, maxX - minX);
|
||||||
double height = Math.Max(1, maxY - minY);
|
var height = Math.Max(1, maxY - minY);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RenderTargetBitmap rtb = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
|
var rtb = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
|
||||||
DrawingVisual dv = new DrawingVisual();
|
var dv = new DrawingVisual();
|
||||||
using (DrawingContext dc = dv.RenderOpen())
|
using (var dc = dv.RenderOpen())
|
||||||
{
|
{
|
||||||
if (whiteBg) dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, width, height));
|
if (whiteBg) dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, width, height));
|
||||||
dc.PushTransform(new TranslateTransform(-minX, -minY));
|
dc.PushTransform(new TranslateTransform(-minX, -minY));
|
||||||
@@ -543,23 +554,26 @@ namespace NetworkDiagram
|
|||||||
{
|
{
|
||||||
if (child == SelectionRect || !(child is Visual v) || ((UIElement)child).Visibility != Visibility.Visible) continue;
|
if (child == SelectionRect || !(child is Visual v) || ((UIElement)child).Visibility != Visibility.Visible) continue;
|
||||||
|
|
||||||
double left = Canvas.GetLeft((UIElement)child);
|
var left = Canvas.GetLeft((UIElement)child);
|
||||||
double top = Canvas.GetTop((UIElement)child);
|
var top = Canvas.GetTop((UIElement)child);
|
||||||
|
|
||||||
if (child is Line line)
|
switch (child)
|
||||||
{
|
{
|
||||||
dc.DrawLine(new Pen(line.Stroke, line.StrokeThickness) { DashStyle = new DashStyle(line.StrokeDashArray, 0) },
|
case Line line:
|
||||||
new Point(line.X1, line.Y1), new Point(line.X2, line.Y2));
|
dc.DrawLine(new Pen(line.Stroke, line.StrokeThickness) { DashStyle = new DashStyle(line.StrokeDashArray, 0) },
|
||||||
}
|
new Point(line.X1, line.Y1), new Point(line.X2, line.Y2));
|
||||||
else if (child is FrameworkElement fe)
|
break;
|
||||||
{
|
case FrameworkElement fe:
|
||||||
VisualBrush vb = new VisualBrush(fe) { Stretch = Stretch.None };
|
{
|
||||||
dc.DrawRectangle(vb, null, new Rect(left, top, fe.ActualWidth, fe.ActualHeight));
|
var vb = new VisualBrush(fe) { Stretch = Stretch.None };
|
||||||
|
dc.DrawRectangle(vb, null, new Rect(left, top, fe.ActualWidth, fe.ActualHeight));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rtb.Render(dv);
|
rtb.Render(dv);
|
||||||
PngBitmapEncoder encoder = new PngBitmapEncoder();
|
var encoder = new PngBitmapEncoder();
|
||||||
encoder.Frames.Add(BitmapFrame.Create(rtb));
|
encoder.Frames.Add(BitmapFrame.Create(rtb));
|
||||||
using (var stream = File.Create(sfd.FileName)) encoder.Save(stream);
|
using (var stream = File.Create(sfd.FileName)) encoder.Save(stream);
|
||||||
MessageBox.Show(GetLocalizedString("ExportSuccess"));
|
MessageBox.Show(GetLocalizedString("ExportSuccess"));
|
||||||
@@ -570,11 +584,11 @@ namespace NetworkDiagram
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class DiagramSaveModel {
|
public class DiagramSaveModel {
|
||||||
public List<PlacedDevice> Devices { get; set; } = new();
|
public List<PlacedDevice> Devices { get; set; } = [];
|
||||||
public List<ConnectionSaveModel> Connections { get; set; } = new();
|
public List<ConnectionSaveModel> Connections { get; set; } = [];
|
||||||
}
|
}
|
||||||
public class ConnectionSaveModel {
|
public class ConnectionSaveModel {
|
||||||
public int StartIndex { get; set; }
|
public int StartIndex { get; init; }
|
||||||
public int EndIndex { get; set; }
|
public int EndIndex { get; set; }
|
||||||
public ConnectionType Type { get; set; }
|
public ConnectionType Type { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
@@ -13,58 +12,65 @@ namespace NetworkDiagram.Models
|
|||||||
|
|
||||||
public class DeviceTemplate
|
public class DeviceTemplate
|
||||||
{
|
{
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; init; } = string.Empty;
|
||||||
public string IconPath { get; set; } = string.Empty;
|
public string IconPath { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlacedDevice : INotifyPropertyChanged
|
public class PlacedDevice : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
private string _name = string.Empty;
|
public string Name
|
||||||
private List<string> _ipAddresses = new List<string>();
|
{
|
||||||
private string _annotation = string.Empty;
|
get;
|
||||||
private double _x;
|
set
|
||||||
private double _y;
|
{
|
||||||
|
field = value;
|
||||||
public string Name
|
OnPropertyChanged();
|
||||||
{
|
}
|
||||||
get => _name;
|
} = string.Empty;
|
||||||
set { _name = value; OnPropertyChanged(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string TemplateName { get; set; } = string.Empty;
|
public string TemplateName { get; set; } = string.Empty;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string IconPath { get; set; } = string.Empty;
|
public string IconPath { get; set; } = string.Empty;
|
||||||
|
|
||||||
public double X
|
public double X
|
||||||
{
|
{
|
||||||
get => _x;
|
get;
|
||||||
set { _x = value; OnPropertyChanged(); OnPropertyChanged(nameof(CenterX)); }
|
set
|
||||||
|
{
|
||||||
|
field = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(CenterX));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Y
|
public double Y
|
||||||
{
|
{
|
||||||
get => _y;
|
get;
|
||||||
set { _y = value; OnPropertyChanged(); OnPropertyChanged(nameof(CenterY)); }
|
set
|
||||||
|
{
|
||||||
|
field = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(CenterY));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> IpAddresses
|
public List<string> IpAddresses
|
||||||
{
|
{
|
||||||
get => _ipAddresses;
|
get;
|
||||||
set { _ipAddresses = value; OnPropertyChanged(); }
|
set
|
||||||
}
|
{
|
||||||
|
field = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
} = [];
|
||||||
|
|
||||||
public string Annotation
|
|
||||||
{
|
|
||||||
get => _annotation;
|
|
||||||
set { _annotation = value; OnPropertyChanged(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public double CenterX => X + 50;
|
public double CenterX => X + 50;
|
||||||
public double CenterY => Y + 40;
|
public double CenterY => Y + 40;
|
||||||
|
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
protected void OnPropertyChanged([CallerMemberName] string? name = null)
|
|
||||||
|
private void OnPropertyChanged([CallerMemberName] string? name = null)
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
|
||||||
}
|
}
|
||||||
@@ -79,7 +85,7 @@ namespace NetworkDiagram.Models
|
|||||||
|
|
||||||
public class Diagram
|
public class Diagram
|
||||||
{
|
{
|
||||||
public List<PlacedDevice> Devices { get; set; } = new List<PlacedDevice>();
|
public List<PlacedDevice> Devices { get; set; } = [];
|
||||||
public List<Connection> Connections { get; set; } = new List<Connection>();
|
public List<Connection> Connections { get; set; } = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user