+ 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
This commit is contained in:
Alexander Smirnov 2015-01-26 23:07:50 +03:00
Родитель 911a38c57a
Коммит ec4418e43f
29 изменённых файлов: 212 добавлений и 326 удалений

Просмотреть файл

@ -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.

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 44 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 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

Двоичные данные
Examples/ShowcaseApp.WPF/Assets/grid_paper.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.5 KiB

Двоичные данные
Examples/ShowcaseApp.WPF/Assets/hand_comp.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
Examples/ShowcaseApp.WPF/Assets/hand_comp2.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.3 KiB

Двоичные данные
Examples/ShowcaseApp.WPF/Assets/hand_comp3.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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);