+ Fixed ZoomControl::Zoom property bug on empty content window resize [WPF, METRO]
+ Added new showcase example: Templates/Graph editor [WPF] + Optimized showcase app media files
|
@ -1,12 +1,16 @@
|
|||
RELEASE 2.1.8
|
||||
+ Added support method GraphArea::GetVertexControlAt(Point position) to get VC by coordinates [METRO, WPF]
|
||||
+ Added VertexControl::GetCenterPosition() method to get vertex center position instead the default top-left
|
||||
+ Added VertexControl::GetCenterPosition() method to get vertex center position instead the default top-left [WPF, METRO]
|
||||
+ Added new showcase example: Templates/Graph editor [WPF]
|
||||
+ Fixed annoying data binding error in ZoomControl slider binding [METRO, WPF]
|
||||
+ Fixed ZoomControl unresponsivness after startup (prev needed to change zoom/translation first to work fine) [WPF,METRO]
|
||||
+ Fixed dynamic graph showcase example first vertex auto zooming onto
|
||||
+ Fixed ZoomControl::Zoom property bug on empty content window resize [WPF, METRO]
|
||||
+ Fixed dynamic graph showcase example first vertex auto zooming onto [WPF]
|
||||
+ Optimized showcase app media files
|
||||
|
||||
!Breaking changes
|
||||
+ Renamed and changed to Enum - ZoomControl::UseAbsoluteZoomOnMouseWheel to MouseWheelZoomingMode [METRO, WPF]
|
||||
+ Expanded EdgeControl event args with mouse and keyboard modifiers [WPF]
|
||||
|
||||
RELEASE 2.1.7
|
||||
+ Added new ShowcaseApp.WPF with mostly the same functionality as before but in a new nutshell and with refactored code. Expect new showcases soon.
|
||||
|
|
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/GraphPaperBackground.png
До Ширина: | Высота: | Размер: 44 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/background.snowflakes.jpg
До Ширина: | Высота: | Размер: 203 KiB После Ширина: | Высота: | Размер: 34 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/board_hd.png
До Ширина: | Высота: | Размер: 229 KiB После Ширина: | Высота: | Размер: 97 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/brick_16.png
До Ширина: | Высота: | Размер: 132 KiB После Ширина: | Высота: | Размер: 58 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/carpet.png
До Ширина: | Высота: | Размер: 147 KiB После Ширина: | Высота: | Размер: 58 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/circle_blue.png
До Ширина: | Высота: | Размер: 101 KiB После Ширина: | Высота: | Размер: 18 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/circle_green.png
До Ширина: | Высота: | Размер: 101 KiB После Ширина: | Высота: | Размер: 19 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/circle_red.png
До Ширина: | Высота: | Размер: 116 KiB После Ширина: | Высота: | Размер: 18 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/female.png
До Ширина: | Высота: | Размер: 32 KiB После Ширина: | Высота: | Размер: 45 KiB |
После Ширина: | Высота: | Размер: 6.5 KiB |
После Ширина: | Высота: | Размер: 12 KiB |
После Ширина: | Высота: | Размер: 9.3 KiB |
После Ширина: | Высота: | Размер: 12 KiB |
Двоичные данные
Examples/ShowcaseApp.WPF/Assets/male.png
До Ширина: | Высота: | Размер: 52 KiB После Ширина: | Высота: | Размер: 66 KiB |
|
@ -26,6 +26,7 @@
|
|||
<mui:LinkGroup DisplayName="Templates">
|
||||
<mui:LinkGroup.Links>
|
||||
<mui:Link DisplayName="General" Source="/Pages/ThemedGraph.xaml" />
|
||||
<mui:Link DisplayName="Editor" Source="/Pages/EditorGraph.xaml" />
|
||||
</mui:LinkGroup.Links>
|
||||
</mui:LinkGroup>
|
||||
<mui:LinkGroup DisplayName="Edge routing">
|
||||
|
|
|
@ -136,17 +136,26 @@ namespace ShowcaseApp.WPF.Models
|
|||
"Oren Kesten",
|
||||
};
|
||||
|
||||
private static List<BitmapImage> Images = new List<BitmapImage>();
|
||||
public static readonly List<BitmapImage> Images = new List<BitmapImage>();
|
||||
public static readonly List<BitmapImage> EditorImages = new List<BitmapImage>();
|
||||
|
||||
static ThemedDataStorage()
|
||||
{
|
||||
Images.Add(new BitmapImage(new Uri(@"pack://application:,,,/ShowcaseApp.WPF;component/Assets/female.png", UriKind.Absolute)) { CacheOption = BitmapCacheOption.OnLoad });
|
||||
Images.Add(new BitmapImage(new Uri(@"pack://application:,,,/ShowcaseApp.WPF;component/Assets/male.png", UriKind.Absolute)) { CacheOption = BitmapCacheOption.OnLoad });
|
||||
EditorImages.Add(new BitmapImage(new Uri(@"pack://application:,,,/ShowcaseApp.WPF;component/Assets/hand_comp.png", UriKind.Absolute)) { CacheOption = BitmapCacheOption.OnLoad });
|
||||
EditorImages.Add(new BitmapImage(new Uri(@"pack://application:,,,/ShowcaseApp.WPF;component/Assets/hand_comp2.png", UriKind.Absolute)) { CacheOption = BitmapCacheOption.OnLoad });
|
||||
EditorImages.Add(new BitmapImage(new Uri(@"pack://application:,,,/ShowcaseApp.WPF;component/Assets/hand_comp3.png", UriKind.Absolute)) { CacheOption = BitmapCacheOption.OnLoad });
|
||||
}
|
||||
|
||||
public static BitmapImage GetImageById(int imageId)
|
||||
{
|
||||
return Images[imageId > 1 ? 1 : 0];
|
||||
return Images[imageId >= 1 ? 1 : 0];
|
||||
}
|
||||
|
||||
public static BitmapImage GetEditorImageById(int imageId)
|
||||
{
|
||||
return EditorImages[imageId >= 1 ? 1 : 0];
|
||||
}
|
||||
|
||||
public static void FillDataVertex(DataVertex item)
|
||||
|
|
|
@ -40,5 +40,25 @@ namespace ShowcaseApp.WPF
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
public sealed class ValueToEditorImageConverter : IValueConverter
|
||||
{
|
||||
#region IValueConverter Members
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (!(value is int)) return null;
|
||||
return ThemedDataStorage.GetEditorImageById((int)value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException("Image to Id conversion is not supported!");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,15 @@
|
|||
<TextBlock Margin="1" TextWrapping="Wrap" TextAlignment="Center" Text="Create vertices and connect them with edges! Read tooltips for buttons info."/>
|
||||
</Border>
|
||||
|
||||
|
||||
<Border Grid.Row="1" Grid.Column="0" BorderBrush="{DynamicResource ButtonBorder}" BorderThickness="1" Margin="2" >
|
||||
<Border.Background>
|
||||
<VisualBrush TileMode="Tile" Viewport="0,0,0.09,0.095">
|
||||
<VisualBrush.Visual>
|
||||
<Image Source="/Assets/grid_paper.png" Stretch="Uniform" UseLayoutRounding="True" SnapsToDevicePixels="True"></Image>
|
||||
</VisualBrush.Visual>
|
||||
</VisualBrush>
|
||||
</Border.Background>
|
||||
<controls:ZoomControl x:Name="zoomCtrl" Background="Transparent" VerticalContentAlignment="Center" VerticalAlignment="Center">
|
||||
<wpf:GraphAreaExample x:Name="graphArea"/>
|
||||
</controls:ZoomControl>
|
||||
|
@ -46,7 +54,7 @@
|
|||
<Setter Property="Height" Value="45"/>
|
||||
</Style>
|
||||
</StackPanel.Resources>
|
||||
<ToggleButton Name="butSelect" ToolTip="Selection mode: drag vertices" x:FieldModifier="private">
|
||||
<ToggleButton Name="butSelect" ToolTip="Selection mode: drag vertices, Ctrl+Click to group them" x:FieldModifier="private">
|
||||
<Path Stretch="Uniform" Fill="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToggleButton}}, Path=Foreground}" Data="F1 M 29,18L 52.25,41.1667L 43.0865,42.6585L 50.817,56.6949L 43.827,60.4115L 36,46.25L 29,53.25L 29,18 Z "/>
|
||||
</ToggleButton>
|
||||
<ToggleButton Name="butEdit" ToolTip="Edit mode: click to place vertices, click vertices to add edges" x:FieldModifier="private">
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
@ -26,9 +27,12 @@ namespace ShowcaseApp.WPF.Pages
|
|||
public EditorGraph()
|
||||
{
|
||||
InitializeComponent();
|
||||
_editorManager = new EditorObjectManager(graphArea, zoomCtrl);
|
||||
var dgLogic = new LogicCoreExample();
|
||||
graphArea.LogicCore = dgLogic;
|
||||
graphArea.VertexSelected += graphArea_VertexSelected;
|
||||
graphArea.EdgeSelected += graphArea_EdgeSelected;
|
||||
graphArea.SetVerticesMathShape(VertexShape.Circle);
|
||||
// addVertexButton.Click += addVertexButton_Click;
|
||||
// addEdgeButton.Click += addEdgeButton_Click;
|
||||
|
||||
|
@ -46,18 +50,13 @@ namespace ShowcaseApp.WPF.Pages
|
|||
|
||||
zoomCtrl.IsAnimationDisabled = true;
|
||||
ZoomControl.SetViewFinderVisibility(zoomCtrl, Visibility.Visible);
|
||||
zoomCtrl.Zoom = 3;
|
||||
zoomCtrl.Zoom = 2;
|
||||
zoomCtrl.MinZoom = .5;
|
||||
zoomCtrl.MaxZoom = 50;
|
||||
zoomCtrl.ZoomDeltaMultiplier = 25;
|
||||
zoomCtrl.MouseDown += zoomCtrl_MouseDown;
|
||||
var tb = new TextBlock() {Text = "AAAA"};
|
||||
graphArea.AddCustomChildControl(tb);
|
||||
GraphAreaBase.SetX(tb, 0);
|
||||
GraphAreaBase.SetY(tb, 0, true);
|
||||
graphArea.UpdateLayout();
|
||||
zoomCtrl.ZoomToFill();
|
||||
graphArea.RemoveCustomChildControl(tb);
|
||||
|
||||
|
||||
//zoomCtrl.ZoomToContent(new System.Windows.Rect(0,0, 500, 500));
|
||||
|
||||
|
@ -67,27 +66,62 @@ namespace ShowcaseApp.WPF.Pages
|
|||
|
||||
butSelect.IsChecked = true;
|
||||
|
||||
_editorManager = new EditorObjectManager(graphArea, zoomCtrl);
|
||||
}
|
||||
|
||||
void graphArea_EdgeSelected(object sender, GraphX.Models.EdgeSelectedEventArgs args)
|
||||
{
|
||||
if (args.MouseArgs.LeftButton == MouseButtonState.Pressed && _opMode == EditorOperationMode.Delete)
|
||||
{
|
||||
graphArea.LogicCore.Graph.RemoveEdge(args.EdgeControl.Edge as DataEdge);
|
||||
graphArea.RemoveEdge(args.EdgeControl.Edge as DataEdge);
|
||||
}
|
||||
}
|
||||
|
||||
void graphArea_VertexSelected(object sender, GraphX.Models.VertexSelectedEventArgs args)
|
||||
{
|
||||
if(args.MouseArgs.LeftButton == MouseButtonState.Pressed && _opMode == EditorOperationMode.Edit)
|
||||
if(args.MouseArgs.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
CreateEdgeControl(args.VertexControl);
|
||||
return;
|
||||
if (_opMode == EditorOperationMode.Edit)
|
||||
CreateEdgeControl(args.VertexControl);
|
||||
else if(_opMode == EditorOperationMode.Delete)
|
||||
SafeRemoveVertex(args.VertexControl);
|
||||
else if (_opMode == EditorOperationMode.Select && args.Modifiers == ModifierKeys.Control)
|
||||
SelectVertex(args.VertexControl);
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectVertex(VertexControl vc)
|
||||
{
|
||||
if (_selectedVertices.Contains(vc))
|
||||
{
|
||||
_selectedVertices.Remove(vc);
|
||||
HighlightBehaviour.SetHighlighted(vc, false);
|
||||
DragBehaviour.SetIsTagged(vc, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedVertices.Add(vc);
|
||||
HighlightBehaviour.SetHighlighted(vc, true);
|
||||
DragBehaviour.SetIsTagged(vc, true);
|
||||
}
|
||||
}
|
||||
|
||||
void zoomCtrl_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
//create vertices and edges only in Edit mode
|
||||
if(_opMode != EditorOperationMode.Edit) return;
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
var vc = CreateVertexControl(zoomCtrl.TranslatePoint(e.GetPosition(zoomCtrl), graphArea));
|
||||
if(_ecFrom != null)
|
||||
CreateEdgeControl(vc);
|
||||
if (_opMode == EditorOperationMode.Edit)
|
||||
{
|
||||
var pos = zoomCtrl.TranslatePoint(e.GetPosition(zoomCtrl), graphArea);
|
||||
pos.Offset(-22.5,-22.5);
|
||||
var vc = CreateVertexControl(pos);
|
||||
if (_ecFrom != null)
|
||||
CreateEdgeControl(vc);
|
||||
}else if(_opMode == EditorOperationMode.Select)
|
||||
{
|
||||
ClearSelectMode(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +134,8 @@ namespace ShowcaseApp.WPF.Pages
|
|||
butSelect.IsChecked = false;
|
||||
zoomCtrl.Cursor = Cursors.Help;
|
||||
_opMode = EditorOperationMode.Delete;
|
||||
graphArea.SetVerticesDrag(false);
|
||||
ClearEditMode();
|
||||
ClearSelectMode();
|
||||
return;
|
||||
}
|
||||
if (butEdit.IsChecked == true && sender == butEdit)
|
||||
|
@ -109,7 +144,7 @@ namespace ShowcaseApp.WPF.Pages
|
|||
butSelect.IsChecked = false;
|
||||
zoomCtrl.Cursor = Cursors.Pen;
|
||||
_opMode = EditorOperationMode.Edit;
|
||||
graphArea.SetVerticesDrag(false);
|
||||
ClearSelectMode();
|
||||
return;
|
||||
}
|
||||
if (butSelect.IsChecked == true && sender == butSelect)
|
||||
|
@ -118,14 +153,39 @@ namespace ShowcaseApp.WPF.Pages
|
|||
butDelete.IsChecked = false;
|
||||
zoomCtrl.Cursor = Cursors.Hand;
|
||||
_opMode = EditorOperationMode.Select;
|
||||
ClearEditMode();
|
||||
graphArea.SetVerticesDrag(true, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearSelectMode(bool soft = false)
|
||||
{
|
||||
if (_selectedVertices != null && _selectedVertices.Any())
|
||||
{
|
||||
_selectedVertices.ForEach(a =>
|
||||
{
|
||||
HighlightBehaviour.SetHighlighted(a, false);
|
||||
DragBehaviour.SetIsTagged(a, false);
|
||||
});
|
||||
_selectedVertices.Clear();
|
||||
}
|
||||
if (!soft)
|
||||
{
|
||||
graphArea.SetVerticesDrag(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearEditMode()
|
||||
{
|
||||
if (_ecFrom != null) HighlightBehaviour.SetHighlighted(_ecFrom, false);
|
||||
_editorManager.DestroyVirtualEdge();
|
||||
_ecFrom = null;
|
||||
}
|
||||
|
||||
private VertexControl CreateVertexControl(Point position)
|
||||
{
|
||||
var data = new DataVertex("Vertex " + (graphArea.VertexList.Count + 1));
|
||||
var data = new DataVertex("Vertex " + (graphArea.VertexList.Count + 1)) { ImageId = ShowcaseHelper.Rand.Next(0, ThemedDataStorage.EditorImages.Count) };
|
||||
graphArea.LogicCore.Graph.AddVertex(data);
|
||||
var vc = new VertexControl(data);
|
||||
graphArea.AddVertex(data, vc);
|
||||
|
@ -155,249 +215,20 @@ namespace ShowcaseApp.WPF.Pages
|
|||
_editorManager.DestroyVirtualEdge();
|
||||
}
|
||||
|
||||
/* #region Manual edge drawing
|
||||
|
||||
private bool _isInEdMode;
|
||||
private PathGeometry _edGeo;
|
||||
private VertexControl _edVertex;
|
||||
private EdgeControl _edEdge;
|
||||
private DataVertex _edFakeDv;
|
||||
|
||||
void dg_zoomctrl_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (!_isInEdMode || _edGeo == null || _edEdge == null || _edVertex == null || e.LeftButton != MouseButtonState.Pressed) return;
|
||||
//place point
|
||||
var pos = dg_zoomctrl.TranslatePoint(e.GetPosition(dg_zoomctrl), dg_Area);
|
||||
var lastseg = _edGeo.Figures[0].Segments[_edGeo.Figures[0].Segments.Count - 1] as PolyLineSegment;
|
||||
if (lastseg != null) lastseg.Points.Add(pos);
|
||||
_edEdge.SetEdgePathManually(_edGeo);
|
||||
}
|
||||
|
||||
void dg_Area_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!_isInEdMode || _edGeo == null || _edEdge == null || _edVertex == null) return;
|
||||
var pos = dg_zoomctrl.TranslatePoint(e.GetPosition(dg_zoomctrl), dg_Area);
|
||||
var lastseg = _edGeo.Figures[0].Segments[_edGeo.Figures[0].Segments.Count - 1] as PolyLineSegment;
|
||||
if (lastseg != null) lastseg.Points[lastseg.Points.Count - 1] = pos;
|
||||
_edEdge.SetEdgePathManually(_edGeo);
|
||||
}
|
||||
|
||||
void dg_Area_VertexSelectedForED(object sender, VertexSelectedEventArgs args)
|
||||
{
|
||||
if (!_isInEdMode) return;
|
||||
if (_edVertex == null) //select starting vertex
|
||||
{
|
||||
_edVertex = args.VertexControl;
|
||||
_edFakeDv = new DataVertex { ID = -666 };
|
||||
_edGeo = new PathGeometry(new PathFigureCollection { new PathFigure { IsClosed = false, StartPoint = _edVertex.GetPosition(), Segments = new PathSegmentCollection { new PolyLineSegment(new List<Point> { new Point() }, true) } } });
|
||||
var dedge = new DataEdge(_edVertex.Vertex as DataVertex, _edFakeDv);
|
||||
_edEdge = new EdgeControl(_edVertex, null, dedge) { ManualDrawing = true };
|
||||
dg_Area.AddEdge(dedge, _edEdge);
|
||||
dg_Area.LogicCore.Graph.AddVertex(_edFakeDv);
|
||||
dg_Area.LogicCore.Graph.AddEdge(dedge);
|
||||
_edEdge.SetEdgePathManually(_edGeo);
|
||||
}
|
||||
else if (!Equals(_edVertex, args.VertexControl)) //finish draw
|
||||
{
|
||||
_edEdge.Target = args.VertexControl;
|
||||
var dedge = _edEdge.Edge as DataEdge;
|
||||
if (dedge != null) dedge.Target = args.VertexControl.Vertex as DataVertex;
|
||||
var fig = _edGeo.Figures[0];
|
||||
var seg = fig.Segments[_edGeo.Figures[0].Segments.Count - 1] as PolyLineSegment;
|
||||
|
||||
if (seg != null && seg.Points.Count > 0)
|
||||
{
|
||||
var targetPos = _edEdge.Target.GetPosition();
|
||||
var sourcePos = _edEdge.Source.GetPosition();
|
||||
//get the size of the source
|
||||
var sourceSize = new Size
|
||||
{
|
||||
Width = _edEdge.Source.ActualWidth,
|
||||
Height = _edEdge.Source.ActualHeight
|
||||
};
|
||||
var targetSize = new Size
|
||||
{
|
||||
Width = _edEdge.Target.ActualWidth,
|
||||
Height = _edEdge.Target.ActualHeight
|
||||
};
|
||||
|
||||
var srcStart = seg.Points.Count == 0 ? fig.StartPoint : seg.Points[0];
|
||||
var srcEnd = seg.Points.Count > 1 ? (seg.Points[seg.Points.Count - 1] == targetPos ? seg.Points[seg.Points.Count - 2] : seg.Points[seg.Points.Count - 1]) : fig.StartPoint;
|
||||
var p1 = GeometryHelper.GetEdgeEndpoint(sourcePos, new Rect(sourceSize), srcStart, _edEdge.Source.VertexShape);
|
||||
var p2 = GeometryHelper.GetEdgeEndpoint(targetPos, new Rect(targetSize), srcEnd, _edEdge.Target.VertexShape);
|
||||
|
||||
|
||||
fig.StartPoint = p1;
|
||||
if (seg.Points.Count > 1)
|
||||
seg.Points[seg.Points.Count - 1] = p2;
|
||||
}
|
||||
GeometryHelper.TryFreeze(_edGeo);
|
||||
_edEdge.SetEdgePathManually(new PathGeometry(_edGeo.Figures));
|
||||
_isInEdMode = false;
|
||||
ClearEdgeDrawing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ClearEdgeDrawing()
|
||||
{
|
||||
_edGeo = null;
|
||||
if (_edFakeDv != null)
|
||||
dg_Area.LogicCore.Graph.RemoveVertex(_edFakeDv);
|
||||
_edFakeDv = null;
|
||||
_edVertex = null;
|
||||
_edEdge = null;
|
||||
}
|
||||
|
||||
private void dg_butdraw_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isInEdMode)
|
||||
{
|
||||
if (dg_Area.VertexList.Count() < 2)
|
||||
{
|
||||
MessageBox.Show("Please add more vertices before proceed with this action!", "Starting to draw custom edge...", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
MessageBox.Show("Please select any vertex to define edge starting point!", "Starting to draw custom edge...", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Edge drawing mode has been canceled!");
|
||||
if (_edEdge != null)
|
||||
_edEdge.SetEdgePathManually(null);
|
||||
ClearEdgeDrawing();
|
||||
}
|
||||
_isInEdMode = !_isInEdMode;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dragging example
|
||||
void dg_dragsource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var data = new DataObject(typeof(object), new object());
|
||||
DragDrop.DoDragDrop(dg_dragsource, data, DragDropEffects.Link);
|
||||
}
|
||||
|
||||
static void dg_Area_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
//don't show drag effect if we are on drag source or don't have any item of needed type dragged
|
||||
if (!e.Data.GetDataPresent(typeof(object)) || sender == e.Source)
|
||||
{
|
||||
e.Effects = DragDropEffects.None;
|
||||
}
|
||||
}
|
||||
|
||||
void dg_Area_Drop(object sender, DragEventArgs e)
|
||||
{
|
||||
if (!e.Data.GetDataPresent(typeof (object))) return;
|
||||
//how to get dragged data by its type
|
||||
var pos = dg_zoomctrl.TranslatePoint(e.GetPosition(dg_zoomctrl), dg_Area);
|
||||
var data = new DataVertex("Vertex " + (dg_Area.VertexList.Count() + 1));
|
||||
dg_Area.LogicCore.Graph.AddVertex(data);
|
||||
var vc = new VertexControl(data);
|
||||
dg_Area.AddVertex(data, vc);
|
||||
GraphAreaBase.SetX(vc, pos.X);
|
||||
GraphAreaBase.SetY(vc, pos.Y, true);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void SelectVertex(VertexControl vc)
|
||||
{
|
||||
if (_selectedVertices.Contains(vc))
|
||||
{
|
||||
_selectedVertices.Remove(vc);
|
||||
HighlightBehaviour.SetHighlighted(vc, false);
|
||||
DragBehaviour.SetIsTagged(vc, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedVertices.Add(vc);
|
||||
HighlightBehaviour.SetHighlighted(vc, true);
|
||||
DragBehaviour.SetIsTagged(vc, true);
|
||||
}
|
||||
}
|
||||
|
||||
void graphArea_VertexSelected(object sender, VertexSelectedEventArgs args)
|
||||
{
|
||||
if (args.MouseArgs.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
if (Keyboard.IsKeyDown(Key.LeftCtrl))
|
||||
SelectVertex(args.VertexControl);
|
||||
}
|
||||
else if (args.MouseArgs.RightButton == MouseButtonState.Pressed)
|
||||
{
|
||||
args.VertexControl.ContextMenu = new ContextMenu();
|
||||
var mi = new MenuItem { Header = "Delete item", Tag = args.VertexControl };
|
||||
mi.Click += mi_Click;
|
||||
args.VertexControl.ContextMenu.Items.Add(mi);
|
||||
}
|
||||
}
|
||||
|
||||
void mi_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var menuItem = sender as MenuItem;
|
||||
if (menuItem == null) return;
|
||||
var vc = menuItem.Tag as VertexControl;
|
||||
if (vc != null) SafeRemoveVertex(vc, true);
|
||||
}
|
||||
|
||||
void dg_remedge_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!dg_Area.EdgesList.Any()) return;
|
||||
dg_Area.LogicCore.Graph.RemoveEdge(dg_Area.EdgesList.Last().Key);
|
||||
dg_Area.RemoveEdge(dg_Area.EdgesList.Last().Key);
|
||||
}
|
||||
|
||||
private EditorMode EditorMode;
|
||||
void addEdgeButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if(EditorMode == EditorMode.AddEdge)
|
||||
{
|
||||
EditorMode = EditorMode.None;
|
||||
_selectedVertices.ForEach(SelectVertex);
|
||||
return;
|
||||
}
|
||||
EditorMode = EditorMode.AddEdge;
|
||||
|
||||
}
|
||||
|
||||
private void SafeRemoveVertex(VertexControl vc, bool removeFromSelected = false)
|
||||
{
|
||||
//remove all adjacent edges
|
||||
foreach (var ec in dg_Area.GetRelatedControls(vc, GraphControlType.Edge, EdgesType.All).OfType<EdgeControl>()) {
|
||||
dg_Area.LogicCore.Graph.RemoveEdge(ec.Edge as DataEdge);
|
||||
dg_Area.RemoveEdge(ec.Edge as DataEdge);
|
||||
foreach (var ec in graphArea.GetRelatedControls(vc, GraphControlType.Edge, EdgesType.All).OfType<EdgeControl>())
|
||||
{
|
||||
graphArea.LogicCore.Graph.RemoveEdge(ec.Edge as DataEdge);
|
||||
graphArea.RemoveEdge(ec.Edge as DataEdge);
|
||||
}
|
||||
dg_Area.LogicCore.Graph.RemoveVertex(vc.Vertex as DataVertex);
|
||||
dg_Area.RemoveVertex(vc.Vertex as DataVertex);
|
||||
graphArea.LogicCore.Graph.RemoveVertex(vc.Vertex as DataVertex);
|
||||
graphArea.RemoveVertex(vc.Vertex as DataVertex);
|
||||
if (removeFromSelected && _selectedVertices.Contains(vc))
|
||||
_selectedVertices.Remove(vc);
|
||||
dg_zoomctrl.ZoomToFill();
|
||||
|
||||
}
|
||||
|
||||
void addVertexButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var data = new DataVertex();
|
||||
ThemedDataStorage.FillDataVertex(data);
|
||||
|
||||
dg_Area.LogicCore.Graph.AddVertex(data);
|
||||
dg_Area.AddVertex(data, new VertexControl(data));
|
||||
|
||||
//we have to check if there is only one vertex and set coordinates manulay
|
||||
//because layout algorithms skip all logic if there are less than two vertices
|
||||
if (dg_Area.VertexList.Count() == 1)
|
||||
dg_Area.VertexList.First().Value.SetPosition(0, 0);
|
||||
else dg_Area.RelayoutGraph(true);
|
||||
dg_zoomctrl.ZoomToFill();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if(_editorManager != null)
|
||||
|
@ -408,10 +239,5 @@ namespace ShowcaseApp.WPF.Pages
|
|||
}
|
||||
}
|
||||
|
||||
public enum EditorMode
|
||||
{
|
||||
None = 0,
|
||||
AddEdge,
|
||||
AddVertex
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -276,9 +276,6 @@
|
|||
<ItemGroup>
|
||||
<Resource Include="Assets\SplashScreen.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\GraphPaperBackground.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\board_hd.png" />
|
||||
</ItemGroup>
|
||||
|
@ -302,6 +299,18 @@
|
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\hand_comp.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\hand_comp2.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\grid_paper.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\hand_comp3.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
|
|
|
@ -62,8 +62,7 @@
|
|||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Source="{Binding PersonImage}" Margin="3" Width="60" Stretch="UniformToFill" Grid.RowSpan="2"/>
|
||||
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" FontWeight="Bold" Foreground="Black" Grid.Column="1" Grid.Row="0" Margin="3" MinWidth="120"/>
|
||||
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" TextAlignment="Center" HorizontalAlignment="Center" FontWeight="Bold" Foreground="Black" Grid.Column="1" Grid.Row="0" Margin="3" MinWidth="120"/>
|
||||
<TextBlock Text="{Binding Profession}" TextAlignment="Center" FontStyle="Italic" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" Grid.Column="1" Grid.Row="1" Margin="3"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
|
||||
xmlns:gxl="clr-namespace:GraphX;assembly=GraphX.WPF.Controls"
|
||||
xmlns:local="clr-namespace:ShowcaseApp.WPF"
|
||||
|
||||
xmlns:conv="clr-namespace:GraphX.Converters;assembly=GraphX.WPF.Controls">
|
||||
|
||||
<LinearGradientBrush x:Key="NormalBrush" EndPoint="0.5,1" StartPoint="0.5,0" po:Freeze="true">
|
||||
|
@ -20,53 +22,29 @@
|
|||
|
||||
<LinearGradientBrush x:Key="EdgeBrush" EndPoint="0.5,0" StartPoint="0.5,1" po:Freeze="true">
|
||||
<GradientStop Color="#FF000000"/>
|
||||
<GradientStop Color="#FFBF931E" Offset="1"/>
|
||||
<GradientStop Color="#FF95EAE2" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
|
||||
<SolidColorBrush x:Key="EdgeArrowBrush" Color="Black" po:Freeze="true" />
|
||||
|
||||
<local:ValueToEditorImageConverter x:Key="ImageConverter"/>
|
||||
|
||||
<!-- VERTEX CONTROL -->
|
||||
<Style TargetType="{x:Type gxl:VertexControl}">
|
||||
<!-- Set background color through attached property -->
|
||||
<Setter Property="Background" Value="{StaticResource NormalBrush}"/>
|
||||
<Setter Property="Padding" Value="10,5,10,5"/>
|
||||
<Setter Property="BorderBrush" Value="{StaticResource NormalBorderBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="ShowLabel" Value="True"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type gxl:VertexControl}">
|
||||
<ControlTemplate.Resources>
|
||||
<Storyboard x:Key="HoverOn">
|
||||
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="BackgroundOver" Storyboard.TargetProperty="Opacity" To="1" />
|
||||
<DoubleAnimation Duration="00:00:00.1000000" Storyboard.TargetName="BackgroundOver_Highlight" Storyboard.TargetProperty="Opacity" To="0.65" />
|
||||
</Storyboard>
|
||||
<Storyboard x:Key="HoverOff">
|
||||
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="BackgroundOver" Storyboard.TargetProperty="Opacity" To="0" />
|
||||
<DoubleAnimation Duration="00:00:00.4000000" Storyboard.TargetName="BackgroundOver_Highlight" Storyboard.TargetProperty="Opacity" To="0" />
|
||||
</Storyboard>
|
||||
</ControlTemplate.Resources>
|
||||
|
||||
<Grid>
|
||||
<Border x:Name="BackgroundNorm" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"/>
|
||||
<Border x:Name="BackgroundNorm_highlight" Margin="1" BorderBrush="{DynamicResource NormalHighlightBrush}" BorderThickness="1,0,1,1" CornerRadius="5" Opacity="0.65" />
|
||||
<Border x:Name="BackgroundOver" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5" Opacity="0" Background="{DynamicResource MouseOverBrush}" BorderBrush="{DynamicResource MouseOverBorderBrush}"/>
|
||||
<Border x:Name="BackgroundOver_Highlight" Margin="1" BorderThickness="1,0,1,1" CornerRadius="5" Opacity="0" BorderBrush="{DynamicResource MouseOverHighlightBrush}"/>
|
||||
<Border CornerRadius="50" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Name="hlBorder">
|
||||
<Image Source="{Binding ImageId, Converter={StaticResource ImageConverter}}" Width="45" Stretch="Uniform" Margin="2" />
|
||||
</Border>
|
||||
|
||||
<gxl:VertexLabelControl x:Name="PART_vertexLabel" Content="{Binding Vertex.Text, RelativeSource={RelativeSource TemplatedParent}}" LabelPositionSide="Bottom" FontFamily="Comic Sans MS" />
|
||||
|
||||
<Grid UseLayoutRounding="True" SnapsToDevicePixels="True">
|
||||
<TextBlock Text="{Binding Text}" TextAlignment="Center" FontStyle="Italic" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" Grid.Column="1" Grid.Row="1" Margin="3"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Trigger.ExitActions>
|
||||
<BeginStoryboard Storyboard="{StaticResource HoverOff}" x:Name="HoverOff_BeginStoryboard" />
|
||||
</Trigger.ExitActions>
|
||||
<Trigger.EnterActions>
|
||||
<BeginStoryboard Storyboard="{StaticResource HoverOn}" />
|
||||
</Trigger.EnterActions>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
|
||||
|
@ -82,7 +60,7 @@
|
|||
<Style.Triggers>
|
||||
<Trigger Property="gxl:HighlightBehaviour.Highlighted" Value="True">
|
||||
<Setter Property="BorderBrush" Value="Gold"/>
|
||||
<Setter Property="BorderThickness" Value="2"/>
|
||||
<Setter Property="BorderThickness" Value="3"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
|
||||
|
|
|
@ -479,35 +479,35 @@ namespace GraphX
|
|||
void EdgeControl_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (RootArea != null && Visibility == Visibility.Visible)
|
||||
RootArea.OnEdgeMouseLeave(this);
|
||||
RootArea.OnEdgeMouseLeave(this, null, Keyboard.Modifiers);
|
||||
// e.Handled = true;
|
||||
}
|
||||
|
||||
void EdgeControl_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (RootArea != null && Visibility == Visibility.Visible)
|
||||
RootArea.OnEdgeMouseEnter(this);
|
||||
RootArea.OnEdgeMouseEnter(this, null, Keyboard.Modifiers);
|
||||
// e.Handled = true;
|
||||
}
|
||||
|
||||
void EdgeControl_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (RootArea != null && Visibility == Visibility.Visible)
|
||||
RootArea.OnEdgeMouseMove(this);
|
||||
RootArea.OnEdgeMouseMove(this, null, Keyboard.Modifiers);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
void EdgeControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (RootArea != null && Visibility == Visibility.Visible)
|
||||
RootArea.OnEdgeDoubleClick(this);
|
||||
RootArea.OnEdgeDoubleClick(this, e, Keyboard.Modifiers);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
void GraphEdge_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (RootArea != null && Visibility == Visibility.Visible)
|
||||
RootArea.OnEdgeSelected(this);
|
||||
RootArea.OnEdgeSelected(this, e, Keyboard.Modifiers);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,10 +97,10 @@ namespace GraphX
|
|||
/// </summary>
|
||||
public virtual event EdgeSelectedEventHandler EdgeSelected;
|
||||
|
||||
internal virtual void OnEdgeSelected(EdgeControl ec)
|
||||
internal virtual void OnEdgeSelected(EdgeControl ec, MouseButtonEventArgs e, ModifierKeys keys)
|
||||
{
|
||||
if (EdgeSelected != null)
|
||||
EdgeSelected(this, new EdgeSelectedEventArgs(ec));
|
||||
EdgeSelected(this, new EdgeSelectedEventArgs(ec, e, keys));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -239,33 +239,33 @@ namespace GraphX
|
|||
}
|
||||
|
||||
public virtual event EdgeSelectedEventHandler EdgeDoubleClick;
|
||||
internal void OnEdgeDoubleClick(EdgeControl edgeControl)
|
||||
internal void OnEdgeDoubleClick(EdgeControl edgeControl, MouseButtonEventArgs e, ModifierKeys keys)
|
||||
{
|
||||
if (EdgeDoubleClick != null)
|
||||
EdgeDoubleClick(this, new EdgeSelectedEventArgs(edgeControl));
|
||||
EdgeDoubleClick(this, new EdgeSelectedEventArgs(edgeControl, e, keys));
|
||||
}
|
||||
|
||||
public virtual event EdgeSelectedEventHandler EdgeMouseMove;
|
||||
internal void OnEdgeMouseMove(EdgeControl edgeControl)
|
||||
internal void OnEdgeMouseMove(EdgeControl edgeControl, MouseButtonEventArgs e, ModifierKeys keys)
|
||||
{
|
||||
if (EdgeMouseMove != null)
|
||||
EdgeMouseMove(this, new EdgeSelectedEventArgs(edgeControl));
|
||||
EdgeMouseMove(this, new EdgeSelectedEventArgs(edgeControl, e, keys));
|
||||
}
|
||||
|
||||
public virtual event EdgeSelectedEventHandler EdgeMouseEnter;
|
||||
internal void OnEdgeMouseEnter(EdgeControl edgeControl)
|
||||
internal void OnEdgeMouseEnter(EdgeControl edgeControl, MouseButtonEventArgs e, ModifierKeys keys)
|
||||
{
|
||||
if (EdgeMouseEnter != null)
|
||||
EdgeMouseEnter(this, new EdgeSelectedEventArgs(edgeControl));
|
||||
EdgeMouseEnter(this, new EdgeSelectedEventArgs(edgeControl, e, keys));
|
||||
if (MouseOverAnimation != null)
|
||||
MouseOverAnimation.AnimateEdgeForward(edgeControl);
|
||||
}
|
||||
|
||||
public virtual event EdgeSelectedEventHandler EdgeMouseLeave;
|
||||
internal void OnEdgeMouseLeave(EdgeControl edgeControl)
|
||||
internal void OnEdgeMouseLeave(EdgeControl edgeControl, MouseButtonEventArgs e, ModifierKeys keys)
|
||||
{
|
||||
if (EdgeMouseLeave != null)
|
||||
EdgeMouseLeave(this, new EdgeSelectedEventArgs(edgeControl));
|
||||
EdgeMouseLeave(this, new EdgeSelectedEventArgs(edgeControl, e, keys));
|
||||
if (MouseOverAnimation != null)
|
||||
MouseOverAnimation.AnimateEdgeBackward(edgeControl);
|
||||
}
|
||||
|
|
|
@ -1090,10 +1090,7 @@ namespace GraphX.Controls
|
|||
|
||||
void ZoomControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var zoom = Zoom;
|
||||
BeginAnimation(ZoomProperty, null);
|
||||
SetValue(ZoomProperty,zoom);
|
||||
SetValue(ZoomDeltaMultiplierProperty, ZoomDeltaMultiplier);
|
||||
FakeZoom();
|
||||
}
|
||||
|
||||
#region ContentChanged
|
||||
|
@ -1288,6 +1285,7 @@ namespace GraphX.Controls
|
|||
|
||||
private void DoZoomAnimation(double targetZoom, double transformX, double transformY, bool isZooming = true)
|
||||
{
|
||||
if (targetZoom == 0d && double.IsNaN(transformX) && double.IsNaN(transformY)) return;
|
||||
_isZooming = isZooming;
|
||||
var duration = !IsAnimationDisabled ? new Duration(AnimationLength) : new Duration(new TimeSpan(0,0,0,0,100));
|
||||
var value = (double)GetValue(TranslateXProperty);
|
||||
|
@ -1495,6 +1493,26 @@ namespace GraphX.Controls
|
|||
Mode = ZoomControlModes.Custom;
|
||||
}
|
||||
|
||||
private void FakeZoom()
|
||||
{
|
||||
var startZoom = Zoom;
|
||||
var currentZoom = startZoom;
|
||||
currentZoom = Math.Max(MinZoom, Math.Min(MaxZoom, currentZoom));
|
||||
|
||||
var startTranslate = new Vector(TranslateX, TranslateY);
|
||||
|
||||
var v = (OrigoPosition - OrigoPosition);
|
||||
var vTarget = (OrigoPosition - OrigoPosition);
|
||||
|
||||
var targetPoint = (v - startTranslate) / startZoom;
|
||||
var zoomedTargetPointPos = targetPoint * currentZoom + startTranslate;
|
||||
var endTranslate = vTarget - zoomedTargetPointPos;
|
||||
|
||||
var transformX = GetCoercedTranslateX(TranslateX + endTranslate.X, currentZoom);
|
||||
var transformY = GetCoercedTranslateY(TranslateY + endTranslate.Y, currentZoom);
|
||||
DoZoomAnimation(currentZoom, transformX, transformY);
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
using System.Windows.Input;
|
||||
|
||||
namespace GraphX.Models
|
||||
{
|
||||
public sealed class EdgeSelectedEventArgs : System.EventArgs
|
||||
{
|
||||
public EdgeControl EdgeControl { get; set; }
|
||||
public ModifierKeys Modifiers { get; set; }
|
||||
public MouseButtonEventArgs MouseArgs { get; set; }
|
||||
|
||||
public EdgeSelectedEventArgs(EdgeControl ec)
|
||||
public EdgeSelectedEventArgs(EdgeControl ec, MouseButtonEventArgs e, ModifierKeys keys)
|
||||
: base()
|
||||
{
|
||||
EdgeControl = ec;
|
||||
EdgeControl = ec;
|
||||
Modifiers = keys;
|
||||
MouseArgs = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -321,7 +321,14 @@ namespace GraphX.Controls
|
|||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get vertex center position
|
||||
/// </summary>
|
||||
public Point GetCenterPosition(bool final = false)
|
||||
{
|
||||
var pos = GetPosition();
|
||||
return new Point(pos.X + ActualWidth * .5, pos.Y + ActualHeight * .5);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -660,6 +660,7 @@ namespace GraphX.Controls
|
|||
|
||||
private void DoZoomAnimation(double targetZoom, double transformX, double transformY, bool isZooming = true)
|
||||
{
|
||||
if (targetZoom == 0d && double.IsNaN(transformX) && double.IsNaN(transformY)) return;
|
||||
_isZooming = isZooming;
|
||||
var duration = !IsAnimationDisabled ? new Duration(AnimationLength) : new Duration(new TimeSpan(0,0,0,0,100));
|
||||
var value = (double)GetValue(TranslateXProperty);
|
||||
|
|