diff --git a/src/FEntwumS.Common/Builders/GenericGraphElementBuilder.cs b/src/FEntwumS.Common/Builders/GenericGraphElementBuilder.cs index 9b3c779..1cc39f1 100644 --- a/src/FEntwumS.Common/Builders/GenericGraphElementBuilder.cs +++ b/src/FEntwumS.Common/Builders/GenericGraphElementBuilder.cs @@ -70,8 +70,8 @@ public T Build() { X = this._x, Y = this._y, - Width = this._width, - Height = this._height, + ElementWidth = this._width, + ElementHeight = this._height, srcLocation = this._srclocation, ZIndex = _zIndex, ClipToBounds = false diff --git a/src/FEntwumS.Common/Builders/GraphNodeBuilder.cs b/src/FEntwumS.Common/Builders/GraphNodeBuilder.cs index 2f8f74a..6f8e9f9 100644 --- a/src/FEntwumS.Common/Builders/GraphNodeBuilder.cs +++ b/src/FEntwumS.Common/Builders/GraphNodeBuilder.cs @@ -386,18 +386,18 @@ public GraphNodeBuilder WithExpandCollapseInteractionControl( (expandCollapseButton.Content as PathIcon)?.Data = AppIcons.MINUS; } - directAncestorNode.PropertyChanged += (o, eventArgs) => - { - if (eventArgs.Property == PositionableSubControl.ScaleProperty && - expandCollapseButton.Content is PathIcon buttonContent) - { - double newScale = (double)eventArgs.NewValue!; - double oldScale = (double)eventArgs.OldValue!; - double scaleDifference = newScale / oldScale; - - expandCollapseButton.GetVisualParent()?.RenderTransform = new ScaleTransform(newScale, newScale); - } - }; + // directAncestorNode.PropertyChanged += (o, eventArgs) => + // { + // if (eventArgs.Property == PositionableSubControl.ScaleProperty && + // expandCollapseButton.Content is PathIcon buttonContent) + // { + // double newScale = (double)eventArgs.NewValue!; + // double oldScale = (double)eventArgs.OldValue!; + // double scaleDifference = newScale / oldScale; + // + // expandCollapseButton.GetVisualParent()?.RenderTransform = new ScaleTransform(newScale, newScale); + // } + // }; } }; @@ -514,7 +514,7 @@ await Dispatcher.UIThread.InvokeAsync(() => } sendingPanningNetlist.ZoomBounds = new Rect(new Point(absoluteX, absoluteY), - new Size(clickedNode.Width, clickedNode.Height)); + new Size(clickedNode.ElementWidth, clickedNode.ElementHeight)); } else { diff --git a/src/FEntwumS.Common/Controls/GenericGraphElementControl.cs b/src/FEntwumS.Common/Controls/GenericGraphElementControl.cs index 773d4a2..c3549cd 100644 --- a/src/FEntwumS.Common/Controls/GenericGraphElementControl.cs +++ b/src/FEntwumS.Common/Controls/GenericGraphElementControl.cs @@ -32,37 +32,21 @@ public string srcLocation AvaloniaProperty.Register(nameof(srcLocation), defaultBindingMode: BindingMode.TwoWay, defaultValue: ""); + + public double cullingOriginX = 0.0d; + public double cullingOriginY = 0.0d; #endregion #region Event Handling - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e) - { - if (e.Property == ParentProperty) - { - var newParent = e.NewValue; - - if (newParent is PanningControl { Child: GenericGraphElementControl childControl }) - childControl.PropertyChanged += (sender, args) => - { - if (args.Property == ScaleProperty && args.NewValue is double newScale) - { - childControl.NetlistTheme.RegenerateBrushesAndPens(newScale); - } - }; - } - - base.OnPropertyChanged(e); - } - #endregion #region Rendering protected override Size MeasureCore(Size availableSize) { - return Double.IsNaN(Width) || Double.IsNaN(Height) ? new Size(100, 100) : new Size(Width, Height); + return Double.IsNaN(ElementWidth) || Double.IsNaN(ElementHeight) ? new Size(100, 100) : new Size(ElementWidth, ElementHeight); } protected override void ArrangeCore(Rect finalRect) diff --git a/src/FEntwumS.Common/Controls/GraphEdgeControl.cs b/src/FEntwumS.Common/Controls/GraphEdgeControl.cs index eac023e..9fbc704 100644 --- a/src/FEntwumS.Common/Controls/GraphEdgeControl.cs +++ b/src/FEntwumS.Common/Controls/GraphEdgeControl.cs @@ -58,9 +58,30 @@ public override void Render(DrawingContext context) context.DrawGeometry(null, linePen, _contentGeometry); } - protected override void RegenerateDrawnElements() + protected override void UpdateScale(double newScale) { - _contentGeometry.Transform = new ScaleTransform(Scale, Scale); + double scaleDifference = newScale / Scale; + + base.UpdateScale(newScale); + + cullingOriginX *= scaleDifference; + cullingOriginY *= scaleDifference; + ElementWidth *= scaleDifference; + ElementHeight *= scaleDifference; + } + + protected override void RegenerateDrawnElements(double newScale) + { + if (!this.IsVisible) + { + return; + } + + _contentGeometry.Transform = new ScaleTransform(newScale, newScale); + Rect newBounds = _contentGeometry.Bounds; + + ElementWidth = newBounds.Width; + ElementHeight = newBounds.Height; } #endregion diff --git a/src/FEntwumS.Common/Controls/GraphEntityNodeControl.cs b/src/FEntwumS.Common/Controls/GraphEntityNodeControl.cs index 0d4aa21..dc60b36 100644 --- a/src/FEntwumS.Common/Controls/GraphEntityNodeControl.cs +++ b/src/FEntwumS.Common/Controls/GraphEntityNodeControl.cs @@ -1,14 +1,17 @@ using Avalonia; using Avalonia.Data; +using Avalonia.Interactivity; +using FEntwumS.Common.Services; +using OneWare.Essentials.Services; namespace FEntwumS.Common.Controls; public class GraphEntityNodeControl : GraphNodeControl { #region Properties - + private Rect _currentViewPort= new Rect(0, 0, 3840, 2160); - + public Rect CurrentViewPort { @@ -16,15 +19,7 @@ public Rect CurrentViewPort set { _currentViewPort = value; - CheckChildVisibility(); - - if (_hasEntityChildren) - { - foreach (GraphEntityNodeControl childEntity in _childEntities) - { - childEntity.CurrentViewPort = new Rect(_currentViewPort.X - childEntity.X, _currentViewPort.Y - childEntity.Y, _currentViewPort.Width, _currentViewPort.Height); - } - } + OnViewPortChanged(); } } @@ -34,37 +29,80 @@ public Rect CurrentViewPort private List _childEntities = new List(); private bool _hasEntityChildren = true; + + private List _childElements = new List(); + private bool _hasChildElements = true; #endregion #region Event handling - protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + protected override void OnLoaded(RoutedEventArgs e) { _childEntities.Clear(); _childEntities.AddRange(this.VisualChildren.OfType()); _hasEntityChildren = _childEntities.Count > 0; - base.OnAttachedToVisualTree(e); + _childElements.Clear(); + _childElements.AddRange(this.VisualChildren.OfType()); + + _hasChildElements = _childElements.Count > 0; + + base.OnLoaded(e); } - protected void CheckChildVisibility() + protected virtual void OnViewPortChanged() { - if (!_hasEntityChildren) + if (!this.IsVisible) { return; } - foreach (GraphEntityNodeControl childEntity in _childEntities) + CheckChildVisibility(); + + if (_hasEntityChildren) { - Rect childArea = new Rect(childEntity.X, childEntity.Y, - childEntity.Width, childEntity.Height); + foreach (GraphEntityNodeControl childEntity in _childEntities) + { + childEntity.CurrentViewPort = new Rect(CurrentViewPort.X - childEntity.X, CurrentViewPort.Y - childEntity.Y, CurrentViewPort.Width, CurrentViewPort.Height); + } + } + } + + protected virtual void CheckChildVisibility() + { +#if DEBUG + if (ServiceManager.GetService().GetSettingValue("NetlistViewer_FreezeGUIState")) + { + return; + } +#endif + + if (!_hasChildElements) + { + return; + } + + foreach (GenericGraphElementControl childElement in _childElements) + { + Rect childArea = new Rect(childElement.cullingOriginX, childElement.cullingOriginY, + childElement.ElementWidth, childElement.ElementHeight); bool isVisible = CurrentViewPort.Contains(childArea) - || childArea.Intersects(CurrentViewPort) - || childArea.Contains(CurrentViewPort); - - childEntity.IsVisible = isVisible; + || childArea.Intersects(CurrentViewPort) + || childArea.Contains(CurrentViewPort); + if (!childElement.IsVisible && isVisible) + { + childElement.IsVisible = true; + + childElement.Scale = this.Scale; + + childElement.InvalidateMeasure(); + } + else + { + childElement.IsVisible = isVisible; + } } } diff --git a/src/FEntwumS.Common/Controls/GraphJunctionControl.cs b/src/FEntwumS.Common/Controls/GraphJunctionControl.cs index 6df795a..4a16748 100644 --- a/src/FEntwumS.Common/Controls/GraphJunctionControl.cs +++ b/src/FEntwumS.Common/Controls/GraphJunctionControl.cs @@ -36,11 +36,11 @@ public JunctionShape _junctionShape protected override void OnInitialized() { - double rh = Width / 2.0d, - rv = Height / 2.0d; + double rh = ElementWidth / 2.0d, + rv = ElementHeight / 2.0d; - double ow = Width * 1.4d, - oh = Height * 1.4d; + double ow = ElementWidth * 1.4d, + oh = ElementHeight * 1.4d; double orh = ow / 2.0d, orv = oh / 2.0d; @@ -56,8 +56,8 @@ protected override void OnInitialized() oby = orv; _contentGeometry = _junctionShape switch { - JunctionShape.Circle => new EllipseGeometry(new Rect(ilx, ity, Width, Height)), - JunctionShape.Square => new RectangleGeometry(new Rect(ilx, ity, Width, Height)), + JunctionShape.Circle => new EllipseGeometry(new Rect(ilx, ity, ElementWidth, ElementHeight)), + JunctionShape.Square => new RectangleGeometry(new Rect(ilx, ity, ElementWidth, ElementHeight)), JunctionShape.Diamond => new PolylineGeometry([ new Point(0.0d, oty), new Point(orx, 0.0d), @@ -83,15 +83,28 @@ protected override void OnInitialized() public override void Render(DrawingContext context) { - if (_contentGeometry.Bounds.Height >= 2.0d) + if (ElementHeight >= 2.0d) { context.DrawGeometry(NetlistTheme.EdgeBrush, null, _contentGeometry); } } - protected override void RegenerateDrawnElements() + protected override void UpdateScale(double newScale) { - _contentGeometry.Transform = new ScaleTransform(Scale, Scale); + base.UpdateScale(newScale); + + cullingOriginX = X; + cullingOriginY = Y; + } + + protected override void RegenerateDrawnElements(double newScale) + { + if (!this.IsVisible) + { + return; + } + + _contentGeometry.Transform = new ScaleTransform(newScale, newScale); } #endregion diff --git a/src/FEntwumS.Common/Controls/GraphLabelControl.cs b/src/FEntwumS.Common/Controls/GraphLabelControl.cs index 364143e..3083530 100644 --- a/src/FEntwumS.Common/Controls/GraphLabelControl.cs +++ b/src/FEntwumS.Common/Controls/GraphLabelControl.cs @@ -2,6 +2,7 @@ using Avalonia; using Avalonia.Data; using Avalonia.Media; +using Avalonia.VisualTree; namespace FEntwumS.Common.Controls; @@ -53,19 +54,37 @@ public double Fontsize public override void Render(DrawingContext context) { + if (!this.GetVisualParent().IsVisible || !this.IsVisible) + { + return; + } + if (Scale >= 0.2d) { context.DrawText(_formattedContent, new Point(0, 0)); } } - protected override void RegenerateDrawnElements() + protected override void UpdateScale(double newScale) { + base.UpdateScale(newScale); + + cullingOriginX = X; + cullingOriginY = Y; + } + + protected override void RegenerateDrawnElements(double newScale) + { + if (!this.GetVisualParent().IsVisible || !this.IsVisible) + { + return; + } + _formattedContent = new FormattedText(Content ?? "", CultureInfo.InvariantCulture, FlowDirection.LeftToRight, NetlistTheme.Typeface, - Fontsize * Scale, + Fontsize * newScale, NetlistTheme.TextBrush); } diff --git a/src/FEntwumS.Common/Controls/GraphNodeControl.cs b/src/FEntwumS.Common/Controls/GraphNodeControl.cs index 8c68c47..1e211f9 100644 --- a/src/FEntwumS.Common/Controls/GraphNodeControl.cs +++ b/src/FEntwumS.Common/Controls/GraphNodeControl.cs @@ -3,9 +3,12 @@ using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Data; +using Avalonia.Interactivity; using Avalonia.Layout; using Avalonia.Media; using Avalonia.Rendering; +using FEntwumS.Common.Services; +using OneWare.Essentials.Services; namespace FEntwumS.Common.Controls; @@ -67,6 +70,7 @@ public string? LocationPath public static readonly StyledProperty LocationPathProperty = AvaloniaProperty.Register(nameof(LocationPath), defaultBindingMode: BindingMode.TwoWay); + #endregion @@ -83,7 +87,7 @@ public string? LocationPath protected override void OnInitialized() { - var contentRect = new Rect(0.0d, 0.0d, Width, Height); + var contentRect = new Rect(0.0d, 0.0d, ElementWidth, ElementHeight); // double l = ((NetlistTheme.BorderThickness + NetlistTheme.DropShadowThickness) / 2) * Scale; // double r = l + Width; @@ -132,11 +136,42 @@ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) base.OnAttachedToVisualTree(e); } + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + if (this is not GraphEntityNodeControl && change.Property == IsVisibleProperty) + { + foreach (PositionableSubControl childControl in Items) + { + childControl.InvalidateMeasure(); + } + } + + base.OnPropertyChanged(change); + } + private void ItemsChanged(object? sender, NotifyCollectionChangedEventArgs e) { AddChildrenToVisualTree(); } + protected override void UpdateScale(double newScale) + { + foreach (Control v in _interactionControls) + { + v.RenderTransform = new ScaleTransform(newScale, newScale); + } + + foreach (PositionableSubControl child in Items) + { + child.Scale = newScale; + } + + base.UpdateScale(newScale); + + cullingOriginX = X; + cullingOriginY = Y; + } + #endregion #region Rendering @@ -152,7 +187,7 @@ protected override Size MeasureCore(Size availableSize) protected override Size MeasureOverride(Size availableSize) { - availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity); + availableSize = new Size(ElementWidth, ElementHeight); foreach (PositionableSubControl child in Items) { @@ -190,15 +225,15 @@ private void ArrangeInteractionControl(Control interactionControl, Size availabl double offset = (NetlistTheme.BorderThickness + 2.0d) * Scale; double x = interactionControl.HorizontalAlignment switch { - HorizontalAlignment.Center => availableSize.Width / 2.0d - (interactionControl.DesiredSize.Width / 2.0d) - offset, - HorizontalAlignment.Right => availableSize.Width - interactionControl.DesiredSize.Width, + HorizontalAlignment.Center => ElementWidth / 2.0d - (interactionControl.DesiredSize.Width / 2.0d) - offset, + HorizontalAlignment.Right => ElementWidth - interactionControl.DesiredSize.Width, _ => offset }; double y = interactionControl.VerticalAlignment switch { - VerticalAlignment.Center => availableSize.Height / 2.0d - (interactionControl.DesiredSize.Height / 2.0d) - offset, - VerticalAlignment.Bottom => availableSize.Height - interactionControl.DesiredSize.Height, + VerticalAlignment.Center => ElementHeight / 2.0d - (interactionControl.DesiredSize.Height / 2.0d) - offset, + VerticalAlignment.Bottom => ElementHeight - interactionControl.DesiredSize.Height, _ => offset }; @@ -243,9 +278,14 @@ public override void Render(DrawingContext context) } } - protected override void RegenerateDrawnElements() + protected override void RegenerateDrawnElements(double newScale) { - _contentGeometry.Transform = new ScaleTransform(Scale, Scale); + if (!this.IsVisible) + { + return; + } + + _contentGeometry.Transform = new ScaleTransform(newScale, newScale); } #endregion diff --git a/src/FEntwumS.Common/Controls/GraphPortControl.cs b/src/FEntwumS.Common/Controls/GraphPortControl.cs index 8db3653..c671165 100644 --- a/src/FEntwumS.Common/Controls/GraphPortControl.cs +++ b/src/FEntwumS.Common/Controls/GraphPortControl.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Data; using Avalonia.Media; +using Avalonia.VisualTree; using FEntwumS.Common.Types; namespace FEntwumS.Common.Controls; @@ -33,12 +34,12 @@ public PortShape _portShape protected override void OnInitialized() { double lx = 0.0d, - rx = 0.0d + Width, + rx = 0.0d + ElementWidth, rox = rx - 5.0d, - mx = rx - (Width / 2.0d), + mx = rx - (ElementWidth / 2.0d), ty = 0.0d, - by = 0.0d + Height, - my = by - (Height / 2.0d); + by = 0.0d + ElementHeight, + my = by - (ElementHeight / 2.0d); _contentGeometry = _portShape switch { @@ -59,15 +60,15 @@ protected override void OnInitialized() PortShape.SquareCircle => new GeometryGroup() { Children = [ - new RectangleGeometry(new Rect(lx, ty, Width / 2.0d, Height)), - new EllipseGeometry(new Rect(mx + 1.0d, ty + 1.0d, (Width / 2.0d) - 2.0d, Height - 2.0d)) + new RectangleGeometry(new Rect(lx, ty, ElementWidth / 2.0d, ElementHeight)), + new EllipseGeometry(new Rect(mx + 1.0d, ty + 1.0d, (ElementWidth / 2.0d) - 2.0d, ElementHeight - 2.0d)) ] }, PortShape.CircleSquare => new GeometryGroup() { Children = [ - new EllipseGeometry(new Rect(lx + 1.0d, ty + 1.0d, (Width / 2.0d) - 2.0d, Height - 2.0d)), - new RectangleGeometry(new Rect(mx, ty, Width / 2.0d, Height)) + new EllipseGeometry(new Rect(lx + 1.0d, ty + 1.0d, (ElementWidth / 2.0d) - 2.0d, ElementHeight - 2.0d)), + new RectangleGeometry(new Rect(mx, ty, ElementWidth / 2.0d, ElementHeight)) ] }, _ => throw new ArgumentOutOfRangeException() @@ -88,9 +89,22 @@ public override void Render(DrawingContext context) } } - protected override void RegenerateDrawnElements() + protected override void UpdateScale(double newScale) { - _contentGeometry.Transform = new ScaleTransform(Scale, Scale); + base.UpdateScale(newScale); + + cullingOriginX = X; + cullingOriginY = Y; + } + + protected override void RegenerateDrawnElements(double newScale) + { + if (!this.IsVisible) + { + return; + } + + _contentGeometry.Transform = new ScaleTransform(newScale, newScale); } #endregion diff --git a/src/FEntwumS.Common/Controls/GraphRootNodeControl.cs b/src/FEntwumS.Common/Controls/GraphRootNodeControl.cs index e234cc6..a9c5220 100644 --- a/src/FEntwumS.Common/Controls/GraphRootNodeControl.cs +++ b/src/FEntwumS.Common/Controls/GraphRootNodeControl.cs @@ -12,4 +12,11 @@ public override void Render(DrawingContext context) } #endregion + + protected override void UpdateScale(double newScale) + { + NetlistTheme.RegenerateBrushesAndPens(newScale); + + base.UpdateScale(newScale); + } } \ No newline at end of file diff --git a/src/FEntwumS.Common/Controls/PanningControl.cs b/src/FEntwumS.Common/Controls/PanningControl.cs index fa8bbe0..9875bf1 100644 --- a/src/FEntwumS.Common/Controls/PanningControl.cs +++ b/src/FEntwumS.Common/Controls/PanningControl.cs @@ -93,7 +93,8 @@ protected override Size MeasureOverride(Size availableSize) { if (Child is not null) { - Child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); + //Child.InvalidateMeasure(); + Child.Measure(new Size(Child.ElementWidth, Child.ElementHeight)); } return new Size(); @@ -161,7 +162,7 @@ private void OnPointerWheelChanged(object? sender, PointerWheelEventArgs e) ScaleChangedCommand?.Execute(newScale); - InvalidateArrange(); + InvalidateMeasure(); Child?.IsHitTestVisible = true; } @@ -265,13 +266,13 @@ public void ZoomToFit() var invariantBounds = new Rect(Child.X * invariantScaleFactor, Child.Y * invariantScaleFactor, - Child.Width * invariantScaleFactor, - Child.Height * invariantScaleFactor); + Child.ElementWidth * invariantScaleFactor, + Child.ElementHeight * invariantScaleFactor); ZoomToRect(invariantBounds); } } - private void ZoomToRect(Rect shownBounds) + protected virtual void ZoomToRect(Rect shownBounds) { if (Child is null) { @@ -303,7 +304,7 @@ private void ZoomToRect(Rect shownBounds) OffsetY = shownBounds.Y * -scaleY; } - InvalidateArrange(); + InvalidateMeasure(); } #endregion diff --git a/src/FEntwumS.Common/Controls/PanningNetlistControl.cs b/src/FEntwumS.Common/Controls/PanningNetlistControl.cs index 3fcc12f..3cc488a 100644 --- a/src/FEntwumS.Common/Controls/PanningNetlistControl.cs +++ b/src/FEntwumS.Common/Controls/PanningNetlistControl.cs @@ -32,6 +32,12 @@ public string ProjectRootFolder #endregion + #region Variables + + private bool hasBeenLoadedBefore = false; + + #endregion + #region Event Handling protected override void OnLoaded(RoutedEventArgs e) @@ -43,8 +49,10 @@ protected override void OnLoaded(RoutedEventArgs e) Child = null; } - if (Child is not null) + if (!hasBeenLoadedBefore && Child is not null) { + hasBeenLoadedBefore = true; + ZoomToFit(); } } @@ -66,6 +74,14 @@ protected override void OnPointerMoved(PointerEventArgs e) } } + protected override void ZoomToRect(Rect shownBounds) + { + base.ZoomToRect(shownBounds); + + UpdateViewPort(); + InvalidateMeasure(); + } + private void UpdateViewPort() { if (Child is GraphRootNodeControl graphRootNodeControl) diff --git a/src/FEntwumS.Common/Controls/PositionableSubControl.cs b/src/FEntwumS.Common/Controls/PositionableSubControl.cs index cbaba90..914094d 100644 --- a/src/FEntwumS.Common/Controls/PositionableSubControl.cs +++ b/src/FEntwumS.Common/Controls/PositionableSubControl.cs @@ -24,20 +24,33 @@ public double Y set => _y = value; } - public double Scale + private double _elementWidth = 1.0d; + + public double ElementWidth + { + get => _elementWidth; + set => _elementWidth = value; + } + + private double _elementHeight = 1.0d; + + public double ElementHeight { - get => GetValue(ScaleProperty); - set => SetValue(ScaleProperty, value); + get => _elementHeight; + set => _elementHeight = value; } - /// - /// The scale of the element. Since the scale is inherited, it only needs to be set on the root element - /// - public static readonly StyledProperty ScaleProperty = - AvaloniaProperty.Register(nameof(Scale), - defaultBindingMode: BindingMode.TwoWay, - defaultValue: 1.0d, - inherits: true); + private double _scale = 1.0d; + + public double Scale + { + get => _scale; + set + { + UpdateScale(value); + _scale = value; + } + } #endregion @@ -49,26 +62,19 @@ public double Scale #region Event handling - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e) + protected virtual void UpdateScale(double newScale) { - if (e.Property == ScaleProperty) - { - double scaleDifference = ((double)e.NewValue!) / ((double)e.OldValue!); + double scaleDifference = newScale / _scale; - this.Width *= scaleDifference; - this.Height *= scaleDifference; - this.X *= scaleDifference; - this.Y *= scaleDifference; + this.ElementWidth *= scaleDifference; + this.ElementHeight *= scaleDifference; + this.X *= scaleDifference; + this.Y *= scaleDifference; - RegenerateDrawnElements(); - - return; - } - - base.OnPropertyChanged(e); + RegenerateDrawnElements(newScale); } - protected abstract void RegenerateDrawnElements(); + protected abstract void RegenerateDrawnElements(double newScale); #endregion } \ No newline at end of file diff --git a/src/FEntwumS.Common/Interfaces/IJsonLoader.cs b/src/FEntwumS.Common/Interfaces/IJsonLoader.cs index 8b5889b..be764b4 100644 --- a/src/FEntwumS.Common/Interfaces/IJsonLoader.cs +++ b/src/FEntwumS.Common/Interfaces/IJsonLoader.cs @@ -16,7 +16,7 @@ public interface IJsonLoader public void CreateLabels(JsonArray labels, GraphNodeControl parent, double xRef, double yRef, ushort depth); - public void CreatePorts(JsonArray ports, GraphNodeControl parent, double xRef, + public void CreatePorts(JsonArray ports, GraphNodeControl parent, GraphNodeControl attachedTo, double xRef, double yRef, ushort depth); public void CreateEdges(JsonArray edges, GraphNodeControl parent, double xRef, diff --git a/src/FEntwumS.Common/ViewModels/NetlistViewModel.cs b/src/FEntwumS.Common/ViewModels/NetlistViewModel.cs index 70a5392..3d8a848 100644 --- a/src/FEntwumS.Common/ViewModels/NetlistViewModel.cs +++ b/src/FEntwumS.Common/ViewModels/NetlistViewModel.cs @@ -1,6 +1,7 @@  using System.Runtime.Serialization; using System.Windows.Input; +using Avalonia; using Avalonia.Data; using CommunityToolkit.Mvvm.Input; using FEntwumS.Common.Controls; @@ -62,6 +63,18 @@ public string ProjectRootFolder } [DataMember] private string _projectRootFolder { get; set; } + + private Rect? _zoomBounds; + + public Rect? ZoomBounds + { + get => _zoomBounds; + set + { + _zoomBounds = value; + OnPropertyChanged(nameof(ZoomBounds)); + } + } private ICommand _scaleChangedCommand; diff --git a/src/FEntwumS.Common/Views/NetlistView.axaml b/src/FEntwumS.Common/Views/NetlistView.axaml index 50332ab..f1ec0d0 100644 --- a/src/FEntwumS.Common/Views/NetlistView.axaml +++ b/src/FEntwumS.Common/Views/NetlistView.axaml @@ -36,6 +36,7 @@ Child="{Binding RootNode}" ScaleChangedCommand="{Binding ScaleChangedCommand}" ProjectRootFolder="{Binding ProjectRootFolder}" + ZoomBounds="{Binding ZoomBounds}" > diff --git a/src/FEntwumS.NetlistViewer/FEntwumSNetlistReaderFrontendModule.cs b/src/FEntwumS.NetlistViewer/FEntwumSNetlistReaderFrontendModule.cs index e679a4a..4942b01 100644 --- a/src/FEntwumS.NetlistViewer/FEntwumSNetlistReaderFrontendModule.cs +++ b/src/FEntwumS.NetlistViewer/FEntwumSNetlistReaderFrontendModule.cs @@ -948,6 +948,11 @@ private void RegisterSettings() // These settings are not displayed to the user; They store internal extension state ServiceManager.GetService().Register(FentwumSNetlistViewerSettingsHelper.FentwumsSettingVersionKey, -1); ServiceManager.GetService().Register(FentwumSNetlistViewerSettingsHelper.NetlistGenerationSettingsChangedKey, ""); + + #if DEBUG + ServiceManager.GetService().RegisterSetting("Netlist Viewer", "Experimental", + FentwumSNetlistViewerSettingsHelper.FreezeGUIStateKey, new CheckBoxSetting("Freeze GUI state", false)); + #endif ServiceManager.GetService().Log("Registered custom settings"); } diff --git a/src/FEntwumS.NetlistViewer/Helpers/FentwumSNetlistViewerSettingsHelper.cs b/src/FEntwumS.NetlistViewer/Helpers/FentwumSNetlistViewerSettingsHelper.cs index 9bb2883..d684b98 100644 --- a/src/FEntwumS.NetlistViewer/Helpers/FentwumSNetlistViewerSettingsHelper.cs +++ b/src/FEntwumS.NetlistViewer/Helpers/FentwumSNetlistViewerSettingsHelper.cs @@ -55,6 +55,10 @@ PlatformHelper.Platform is PlatformId.OsxArm64 || PlatformHelper.Platform is Pla public static readonly string LayoutEffortKey = "NetlistViewer_LayoutEffort"; public static readonly string ShowUnconnectedPortsKey = "NetlistViewer_ShowUnconnectedPorts"; public static readonly string OnlyShowUserGeneratedSignalNamesKey = "NetlistViewer_OnlyShowUserGeneratedSignalNames"; + + #if DEBUG + public static readonly string FreezeGUIStateKey = "NetlistViewer_FreezeGUIState"; + #endif public static readonly string AutomaticNetlistGenerationIntervalKey = "NetlistViewer_AutomaticNetlistGenerationInterval"; diff --git a/src/FEntwumS.NetlistViewer/Services/FrontendService.cs b/src/FEntwumS.NetlistViewer/Services/FrontendService.cs index 7c3255a..db63e07 100644 --- a/src/FEntwumS.NetlistViewer/Services/FrontendService.cs +++ b/src/FEntwumS.NetlistViewer/Services/FrontendService.cs @@ -3,6 +3,7 @@ using System.Text; using System.Text.RegularExpressions; using Asmichi.ProcessManagement; +using Avalonia; using Avalonia.Collections; using Avalonia.Media; using FEntwumS.Common.Controls; diff --git a/src/FEntwumS.NetlistViewer/Services/JsonLoader.cs b/src/FEntwumS.NetlistViewer/Services/JsonLoader.cs index 0255731..4aefe75 100644 --- a/src/FEntwumS.NetlistViewer/Services/JsonLoader.cs +++ b/src/FEntwumS.NetlistViewer/Services/JsonLoader.cs @@ -319,14 +319,14 @@ public JsonLoader() if (labels != null) { - CreateLabels(labels, parent, 0, 0, newDepth); + CreateLabels(labels, prevParent, xRef + x, yRef + y, newDepth); } JsonArray? ports = node["ports"] as JsonArray; if (ports != null) { - CreatePorts(ports, prevParent, x, y, newDepth); + CreatePorts(ports, prevParent, parent, x, y, newDepth); } JsonArray? edges = node["edges"] as JsonArray; @@ -443,7 +443,7 @@ public void CreateLabels(JsonArray labels, GraphNodeControl parent, double xRef, } } - public void CreatePorts(JsonArray ports, GraphNodeControl parent, double xRef, + public void CreatePorts(JsonArray ports, GraphNodeControl parent, GraphNodeControl attachedTo, double xRef, double yRef, ushort depth) { double x = 0; @@ -491,7 +491,7 @@ public void CreatePorts(JsonArray ports, GraphNodeControl parent, double xRef, if (labels is not null) { - CreateLabels(labels, parent, xRef + x, yRef + y, (ushort)(depth + 1)); + CreateLabels(labels, attachedTo, x, y, (ushort)(depth + 1)); } if (layoutOptions is not null)