Browse Source

Implemented context menu for vertices.

Implemented operations for removing vertices (eg. by what use what)
Implemented an option to save graph to an image.
Implemented an option to reset graphs.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6058 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Tomáš Linhart 15 years ago
parent
commit
d210702061
  1. 218
      src/AddIns/Analysis/CodeQuality/Src/Controls/DependencyGraphLayout.cs
  2. 4
      src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml
  3. 70
      src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs

218
src/AddIns/Analysis/CodeQuality/Src/Controls/DependencyGraphLayout.cs

@ -3,7 +3,9 @@ using System.Collections.Generic; @@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using GraphSharp.Controls;
using QuickGraph;
@ -12,6 +14,7 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -12,6 +14,7 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
public class DependencyGraphLayout : GraphLayout<DependencyVertex, DependencyEdge, DependencyGraph>
{
public event MouseButtonEventHandler VertexClick;
public event MouseButtonEventHandler VertexRightClick;
public void ChangeGraph(DependencyGraph graph)
{
@ -19,25 +22,214 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -19,25 +22,214 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
{
if (graph != null && graph.VertexCount > 0)
{
this.Graph = graph;
Graph = graph;
}
}
catch
{
} // ignore it if it fails
AttachEvents();
}
private void AttachEvents()
{
foreach (UIElement element in this.Children)
{
var vertex = element as VertexControl;
if (vertex != null)
{
// Preview because otherwise is LeftButtonDown blocked
vertex.PreviewMouseLeftButtonDown += vertex_MouseLeftButtonDown;
vertex.MouseRightButtonDown += vertex_MouseRightButtonDown;
vertex.MouseDoubleClick += vertex_MouseDoubleClick;
}
}
}
void vertex_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
if (VertexRightClick != null)
VertexRightClick(sender, e);
var vertexControl = sender as VertexControl;
if (vertexControl != null)
CreateContextMenu(vertexControl);
}
private void CreateContextMenu(VertexControl vertexControl)
{
var menu = new ContextMenu();
// internal dependencies
var iternalDependency = new MenuItem { Header = "View internal dependencies on graph" };
iternalDependency.Click += (sender, e) =>
{
var vc =
((ContextMenu) ((MenuItem) sender).Parent).PlacementTarget as
VertexControl;
if (vc != null)
{
var vertex = vertexControl.Vertex as DependencyVertex;
if (vertex != null && vertex.Node.Dependency != null)
{
ChangeGraph(vertex.Node.Dependency.BuildDependencyGraph());
}
}
};
menu.Items.Add(iternalDependency);
menu.Items.Add(new Separator());
// remove
var remove = new MenuItem { Header = "Remove" };
remove.Click += (sender, e) =>
{
// no nested menus for now so this is ok
var vc =
((ContextMenu)((MenuItem)sender).Parent).PlacementTarget as
VertexControl;
if (vc != null)
{
var vertex = vertexControl.Vertex as DependencyVertex;
if (vertex != null)
{
RemoveVertexWithEdges(vertex);
}
}
};
menu.Items.Add(remove);
// keep only nodes that use this
var useThis = new MenuItem { Header = "Keep only nodes that use this" };
useThis.Click += (sender, e) =>
{
// no nested menus for now so this is ok
var vc =
((ContextMenu)((MenuItem)sender).Parent).PlacementTarget as
VertexControl;
if (vc != null)
{
var vertex = vertexControl.Vertex as DependencyVertex;
if (vertex != null)
{
ISet<DependencyVertex> vertices = new HashSet<DependencyVertex>();
vertices.Add(vertex); // original vertex shouldnt be removed
foreach (KeyValuePair<DependencyEdge,EdgeControl> pair in _edgeControls)
{
if (pair.Key.Target.Equals(vertex))
{
vertices.Add(pair.Key.Source);
}
}
foreach (var v in _vertexControls.Keys.Except(vertices).ToList())
{
RemoveVertexWithEdges(v);
}
}
}
};
menu.Items.Add(useThis);
var thisUse = new MenuItem { Header = "Keep only nodes that this use" };
thisUse.Click += (sender, e) =>
{
// no nested menus for now so this is ok
var vc =
((ContextMenu)((MenuItem)sender).Parent).PlacementTarget as
VertexControl;
if (vc != null)
{
var vertex = vertexControl.Vertex as DependencyVertex;
if (vertex != null)
{
ISet<DependencyVertex> vertices = new HashSet<DependencyVertex>();
vertices.Add(vertex); // original vertex shouldnt be removed
foreach (KeyValuePair<DependencyEdge, EdgeControl> pair in _edgeControls)
{
if (pair.Key.Source.Equals(vertex))
{
vertices.Add(pair.Key.Target);
}
}
foreach (var v in _vertexControls.Keys.Except(vertices).ToList())
{
RemoveVertexWithEdges(v);
}
}
}
};
menu.Items.Add(thisUse);
// keep only nodes users and used
var usersUsed = new MenuItem { Header = "Keep only nodes users and used" };
usersUsed.Click += (sender, e) =>
{
// no nested menus for now so this is ok
var vc =
((ContextMenu)((MenuItem)sender).Parent).PlacementTarget as
VertexControl;
if (vc != null)
{
var vertex = vertexControl.Vertex as DependencyVertex;
if (vertex != null)
{
ISet<DependencyVertex> vertices = new HashSet<DependencyVertex>();
vertices.Add(vertex); // original vertex shouldnt be removed
foreach (KeyValuePair<DependencyEdge, EdgeControl> pair in _edgeControls)
{
if (pair.Key.Source.Equals(vertex))
{
vertices.Add(pair.Key.Target);
}
if (pair.Key.Target.Equals(vertex))
{
vertices.Add(pair.Key.Source);
}
}
foreach (var v in _vertexControls.Keys.Except(vertices).ToList())
{
RemoveVertexWithEdges(v);
}
}
}
};
menu.Items.Add(usersUsed);
vertexControl.ContextMenu = menu;
vertexControl.ContextMenu.PlacementTarget = this;
}
private void RemoveVertexWithEdges(DependencyVertex vertex)
{
IList<DependencyEdge> edges = new List<DependencyEdge>();
foreach (KeyValuePair<DependencyEdge,EdgeControl> pair in _edgeControls)
{
if (pair.Key.Source.Equals(vertex) || pair.Key.Target.Equals(vertex))
edges.Add(pair.Key);
}
foreach (DependencyEdge edge in edges)
{
RemoveEdgeControl(edge);
}
RemoveVertexControl(vertex);
}
private void vertex_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var vertexControl = sender as VertexControl;
@ -46,16 +238,36 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -46,16 +238,36 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
var vertex = vertexControl.Vertex as DependencyVertex;
if (vertex != null && vertex.Node.Dependency != null)
{
this.ChangeGraph(vertex.Node.Dependency.BuildDependencyGraph());
ChangeGraph(vertex.Node.Dependency.BuildDependencyGraph());
}
}
}
private void vertex_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
VertexClick(sender, e);
if (VertexClick != null)
VertexClick(sender, e);
// TODO: Implement SelectedVertex and change its color
}
public void ResetGraph()
{
RecreateGraphElements(false);
Relayout();
AttachEvents();
}
public override void Relayout()
{
if (_vertexControls.Count > 0)
base.Relayout();
}
public override void ContinueLayout()
{
if (_vertexControls.Count > 0)
base.ContinueLayout();
}
}
}

4
src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml

@ -30,7 +30,9 @@ @@ -30,7 +30,9 @@
<ToolBar>
<Button Name="btnOpenAssembly" Click="btnOpenAssembly_Click" Margin="0 0 5 0">Open Assembly</Button>
<Button Name="btnRelayout" Click="btnRelayout_Click" Margin="0 0 5 0">Relayout</Button>
<Button Name="btnContinueLayout" Click="btnContinueLayout_Click">Continue Layout</Button>
<Button Name="btnContinueLayout" Click="btnContinueLayout_Click" Margin="0 0 5 0">Continue Layout</Button>
<Button Name="btnResetGraph" Click="btnResetGraph_Click" Margin="0 0 5 0">Reset Graph</Button>
<Button Name="btnSaveImageGraph" Click="btnSaveImageGraph_Click">Save an Image of Graph</Button>
</ToolBar>
</ToolBarTray>

70
src/AddIns/Analysis/CodeQuality/Src/MainWindow.xaml.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
@ -152,6 +153,51 @@ namespace ICSharpCode.CodeQualityAnalysis @@ -152,6 +153,51 @@ namespace ICSharpCode.CodeQualityAnalysis
}
}
private void btnResetGraph_Click(object sender, RoutedEventArgs e)
{
graphLayout.ResetGraph();
}
private void btnSaveImageGraph_Click(object sender, RoutedEventArgs e)
{
var fileDialog = new SaveFileDialog()
{
Filter = "PNG Image (*.png)|*.png"
};
fileDialog.ShowDialog();
if (String.IsNullOrEmpty(fileDialog.FileName))
return;
var transform = graphLayout.LayoutTransform;
graphLayout.LayoutTransform = null;
// calculate size
var size = new Size(graphLayout.ActualWidth, graphLayout.ActualHeight);
graphLayout.Measure(size);
graphLayout.Arrange(new Rect(size));
// render it
var renderBitmap = new RenderTargetBitmap((int) size.Width,
(int) size.Height,
96d,
96d,
PixelFormats.Pbgra32);
renderBitmap.Render(graphLayout);
using (var outStream = new FileStream(fileDialog.FileName, FileMode.Create))
{
// for now only PNG
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
graphLayout.LayoutTransform = transform;
}
private class MetricTreeViewItem : TreeViewItem
{
private readonly Image _iconControl;
@ -167,7 +213,7 @@ namespace ICSharpCode.CodeQualityAnalysis @@ -167,7 +213,7 @@ namespace ICSharpCode.CodeQualityAnalysis
{
get
{
return _textControl.Text;
return _textControl.Text;
}
set
{
@ -183,31 +229,31 @@ namespace ICSharpCode.CodeQualityAnalysis @@ -183,31 +229,31 @@ namespace ICSharpCode.CodeQualityAnalysis
get
{
return _bitmap;
}
}
set
{
_iconControl.Source = _bitmap = value;
}
}
public MetricTreeViewItem()
{
var stack = new StackPanel
{
Orientation = Orientation.Horizontal
};
{
Orientation = Orientation.Horizontal
};
Header = stack;
_iconControl = new Image
{
Margin = new Thickness(0, 0, 5, 0)
};
{
Margin = new Thickness(0, 0, 5, 0)
};
_textControl = new TextBlock()
{
VerticalAlignment = VerticalAlignment.Center
};
{
VerticalAlignment = VerticalAlignment.Center
};
stack.Children.Add(_iconControl);
stack.Children.Add(_textControl);

Loading…
Cancel
Save