Browse Source

Improvements to Matrix Control.

pull/19/head
Tomas Linhart 14 years ago
parent
commit
6061837e06
  1. 2
      src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj
  2. 68
      src/AddIns/Analysis/CodeQuality/Src/Controls/DependencyColorizer.cs
  3. 11
      src/AddIns/Analysis/CodeQuality/Src/Controls/DependencyMatrix.cs
  4. 95
      src/AddIns/Analysis/CodeQuality/Src/Controls/MatrixControl.cs
  5. 7
      src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml.cs
  6. 37
      src/AddIns/Analysis/CodeQuality/Src/Helper.cs
  7. 2
      src/AddIns/Analysis/CodeQuality/Src/Relationship.cs
  8. 72
      src/AddIns/Analysis/CodeQuality/Src/Type.cs
  9. 18
      src/AddIns/Analysis/CodeQuality/Src/Utility/IColorizer.cs
  10. 4
      src/AddIns/Analysis/CodeQuality/Src/Utility/Matrix.cs

2
src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj

@ -113,6 +113,7 @@
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs"> <Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link> <Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="Src\Controls\DependencyColorizer.cs" />
<Compile Include="Src\Controls\DependencyEdge.cs" /> <Compile Include="Src\Controls\DependencyEdge.cs" />
<Compile Include="Src\Controls\DependencyGraph.cs" /> <Compile Include="Src\Controls\DependencyGraph.cs" />
<Compile Include="Src\Controls\DependencyGraphLayout.cs" /> <Compile Include="Src\Controls\DependencyGraphLayout.cs" />
@ -143,6 +144,7 @@
<Compile Include="Src\RelationshipType.cs" /> <Compile Include="Src\RelationshipType.cs" />
<Compile Include="Src\Type.cs" /> <Compile Include="Src\Type.cs" />
<Compile Include="Src\Utility\DoubleKeyDictionary.cs" /> <Compile Include="Src\Utility\DoubleKeyDictionary.cs" />
<Compile Include="Src\Utility\IColorizer.cs" />
<Compile Include="Src\Utility\Matrix.cs" /> <Compile Include="Src\Utility\Matrix.cs" />
<Compile Include="Src\Utility\RelayCommand.cs" /> <Compile Include="Src\Utility\RelayCommand.cs" />
<Compile Include="Src\Utility\ViewModelBase.cs" /> <Compile Include="Src\Utility\ViewModelBase.cs" />

68
src/AddIns/Analysis/CodeQuality/Src/Controls/DependencyColorizer.cs

@ -0,0 +1,68 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Linq;
using System.Collections.Generic;
using System.Windows.Media;
using ICSharpCode.CodeQualityAnalysis.Utility;
namespace ICSharpCode.CodeQualityAnalysis.Controls
{
/// <summary>
/// Description of DependencyColorizer.
/// </summary>
public class DependencyColorizer : IColorizer<Relationship>
{
private Dictionary<Color, SolidColorBrush> cache;
public DependencyColorizer()
{
cache = new Dictionary<Color, SolidColorBrush>();
}
public SolidColorBrush GetColorBrush(Relationship relationship)
{
var color = GetColor(relationship);
if (cache.ContainsKey(color))
return cache[color];
var brush = new SolidColorBrush(color);
brush.Freeze();
cache[color] = brush;
return brush;
}
public Color GetColor(Relationship relationship)
{
if (relationship.Relationships.Any(r => r == RelationshipType.UseThis))
return Colors.Azure;
if (relationship.Relationships.Any(r => r == RelationshipType.UsedBy))
return Colors.Beige;
if (relationship.Relationships.Any(r => r == RelationshipType.Same))
return Colors.Gray;
return Colors.Transparent;
}
public SolidColorBrush GetColorBrushMixedWith(Color color, Relationship relationship)
{
var mixedColor = GetColor(relationship);
mixedColor = mixedColor.MixedWith(color);
if (cache.ContainsKey(mixedColor))
return cache[mixedColor];
var brush = new SolidColorBrush(mixedColor);
brush.Freeze();
cache[mixedColor] = brush;
return brush;
}
}
}

11
src/AddIns/Analysis/CodeQuality/Src/Controls/DependencyMatrix.cs

@ -13,7 +13,16 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
{ {
protected override Relationship GetCellValue(int rowIndex, int columnIndex) protected override Relationship GetCellValue(int rowIndex, int columnIndex)
{ {
return HeaderRows[rowIndex].Value.GetRelationship(HeaderColumns[columnIndex].Value); var toRelationship = HeaderRows[rowIndex].Value.GetRelationship(HeaderColumns[columnIndex].Value);
var fromRelationship = HeaderColumns[columnIndex].Value.GetRelationship(HeaderRows[rowIndex].Value);
// add other way
foreach (var relationship in fromRelationship.Relationships) {
if (relationship == RelationshipType.UseThis)
toRelationship.AddRelationship(RelationshipType.UsedBy);
}
return toRelationship;
} }
} }
} }

95
src/AddIns/Analysis/CodeQuality/Src/Controls/MatrixControl.cs

@ -31,6 +31,9 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
// will be loaded from Matrix // will be loaded from Matrix
private int matrixWidth = 0; private int matrixWidth = 0;
private int matrixHeight = 0; private int matrixHeight = 0;
private int fontSize = 0;
private int penSize = 0;
private Matrix<TItem, TValue> matrix; private Matrix<TItem, TValue> matrix;
@ -54,11 +57,15 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
public bool RenderZeroes { get; set; } public bool RenderZeroes { get; set; }
public IColorizer<TValue> Colorizer { get; set; }
public MatrixControl() public MatrixControl()
{ {
CellHeight = CellWidth = 36; CellHeight = CellWidth = 18;
matrixWidth = 20; matrixWidth = 20;
matrixHeight = 20; matrixHeight = 20;
fontSize = CellHeight / 3;
penSize = 1;
font = "Verdana"; font = "Verdana";
HoveredCell = new HoveredCell<TValue>(); HoveredCell = new HoveredCell<TValue>();
@ -69,12 +76,13 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
base.OnMouseMove(e); base.OnMouseMove(e);
var point = e.GetPosition(this); var point = e.GetPosition(this);
if (point.X < matrixWidth * CellWidth && point.Y < matrixHeight * CellHeight) if (point.X < matrixWidth * CellWidth
&& point.Y < matrixHeight * CellHeight)
currentCell = new Coords( currentCell = new Coords(
(int)((point.X + offset.X) / CellWidth), (int)((point.X + offset.X) / CellWidth),
(int)((point.Y + offset.Y) / CellHeight)); (int)((point.Y + offset.Y) / CellHeight));
else // else // if we are out of matrix just use last cell
currentCell = new Coords(-1, -1); // currentCell = new Coords(-1, -1);
if (currentCell.X != HoveredCell.RowIndex || if (currentCell.X != HoveredCell.RowIndex ||
currentCell.Y != HoveredCell.ColumnIndex) currentCell.Y != HoveredCell.ColumnIndex)
@ -112,27 +120,38 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
// background // background
var background = new Rect(0, 0, cellsHorizontally * CellWidth, cellsVertically * CellHeight); var background = new Rect(0, 0, cellsHorizontally * CellWidth, cellsVertically * CellHeight);
var backgroundColor = new SolidColorBrush(Colors.Yellow); var backgroundColor = new SolidColorBrush(Colors.Yellow);
backgroundColor.Freeze();
drawingContext.DrawRectangle(backgroundColor, null, background); drawingContext.DrawRectangle(backgroundColor, null, background);
// sometimes happens when half of cell is hidden in scroll so text isnt drawn
// so lets drawn one more cell
cellsHorizontally = maxWidth > matrixWidth ? matrixWidth : maxWidth + 1;
cellsVertically = maxHeight > matrixHeight ? matrixHeight : maxHeight + 1;
var currentXLine = (currentCell.X - scaledOffsetX) * CellWidth - offsetDiffX;
var currentYLine = (currentCell.Y - scaledOffsetY) * CellHeight - offsetDiffY;
// hovering // hovering
if (currentCell.X >= 0 || currentCell.Y >= 0) { if (currentCell.X >= 0 || currentCell.Y >= 0) {
// hover x line // hover y line
var rect = new Rect(0, var rect = new Rect(0,
(currentCell.Y - scaledOffsetY) * CellHeight - offsetDiffY, currentYLine,
CellWidth * cellsHorizontally, CellWidth * cellsHorizontally,
CellHeight); CellHeight);
var brush = new SolidColorBrush(Colors.GreenYellow); var brush = new SolidColorBrush(Colors.GreenYellow);
brush.Freeze();
drawingContext.DrawRectangle(brush, null, rect); drawingContext.DrawRectangle(brush, null, rect);
// hover y line // hover x line
rect = new Rect((currentCell.X - scaledOffsetX) * CellWidth - offsetDiffX, rect = new Rect(currentXLine,
0, 0,
CellWidth, CellWidth,
CellHeight * cellsVertically); CellHeight * cellsVertically);
brush = new SolidColorBrush(Colors.GreenYellow); brush = new SolidColorBrush(Colors.GreenYellow);
brush.Freeze();
drawingContext.DrawRectangle(brush, null, rect); drawingContext.DrawRectangle(brush, null, rect);
// hover cell // hover cell
@ -143,11 +162,44 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
CellHeight); CellHeight);
brush = new SolidColorBrush(Colors.Red); brush = new SolidColorBrush(Colors.Red);
brush.Freeze();
drawingContext.DrawRectangle(brush, null, rect); drawingContext.DrawRectangle(brush, null, rect);
} }
// text
for (int i = 0; i < cellsHorizontally; i++) {
for (int j = 0; j < cellsVertically; j++) { // dont draw text in unavailables places
int rowIndex = i + scaledOffsetX;
int columnIndex = j + scaledOffsetY;
var value = matrix[rowIndex, columnIndex];
if (Colorizer != null) {
var rect = new Rect(
i * CellWidth - offsetDiffX,
j * CellHeight - offsetDiffY,
CellWidth,
CellHeight);
SolidColorBrush brush = null;
if ((i * CellWidth - offsetDiffX) == currentXLine ||
((i * CellWidth - offsetDiffX) == currentXLine))
brush = Colorizer.GetColorBrushMixedWith(Colors.GreenYellow, value);
else
brush = Colorizer.GetColorBrush(value);
drawingContext.DrawRectangle(brush, null, rect);
}
if (!RenderZeroes && value.Text != "0") // rendering zeroes would be distracting
drawingContext.DrawImage(
CreateText(value.Text),
new Rect(i * CellWidth - offsetDiffX, j * CellHeight - offsetDiffY, CellWidth, CellHeight));
}
}
// grid // grid
var pen = new Pen(Brushes.Black, 1); var pen = new Pen(Brushes.Black, penSize);
pen.Freeze();
// grid x // grid x
for (int i = 0; i <= cellsHorizontally; i++) for (int i = 0; i <= cellsHorizontally; i++)
@ -161,30 +213,10 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
new Point(0, i * CellHeight - offsetDiffY), new Point(0, i * CellHeight - offsetDiffY),
new Point(cellsHorizontally * CellHeight, new Point(cellsHorizontally * CellHeight,
i * CellHeight - offsetDiffY)); i * CellHeight - offsetDiffY));
// sometimes happens when half of cell is hidden in scroll so text isnt drawn
// so lets drawn one more cell
cellsHorizontally = maxWidth > matrixWidth ? matrixWidth : maxWidth + 1;
cellsVertically = maxHeight > matrixHeight ? matrixHeight : maxHeight + 1;
// text
for (int i = 0; i < cellsHorizontally; i++) {
for (int j = 0; j < cellsVertically; j++) {
int rowIndex = i + scaledOffsetX;
int columnIndex = j + scaledOffsetY;
var value = matrix[rowIndex, columnIndex];
drawingContext.DrawImage(
CreateText(value.Text),
new Rect(i * CellWidth - offsetDiffX, j * CellHeight - offsetDiffY, CellWidth, CellHeight));
}
}
} }
public ImageSource CreateText(string text) public ImageSource CreateText(string text)
{ {
if (!RenderZeroes && text == "0") // rendering zeroes would be distracting
text = string.Empty;
if (imgs.ContainsKey(text)) if (imgs.ContainsKey(text))
return imgs[text]; return imgs[text];
@ -193,7 +225,7 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
g.SmoothingMode = SmoothingMode.AntiAlias; g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
var fontOjb = new System.Drawing.Font(font, 12); var fontOjb = new System.Drawing.Font(font, fontSize);
var size = g.MeasureString(text, fontOjb); var size = g.MeasureString(text, fontOjb);
@ -207,6 +239,7 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
IntPtr.Zero, IntPtr.Zero,
Int32Rect.Empty, Int32Rect.Empty,
BitmapSizeOptions.FromWidthAndHeight(bmp.Width, bmp.Height)); BitmapSizeOptions.FromWidthAndHeight(bmp.Width, bmp.Height));
img.Freeze();
imgs.Add(text, img); imgs.Add(text, img);
return img; return img;

7
src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml.cs

@ -38,13 +38,14 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
public TreeMatrixControl() public TreeMatrixControl()
{ {
InitializeComponent(); InitializeComponent();
matrixControl.Colorizer = new DependencyColorizer();
} }
public void DrawTree(Module module) public void DrawTree(Module module)
{ {
Helper.FillTree (leftTree,module); Helper.FillTree(leftTree,module);
Helper.FillTree (topTree,module); Helper.FillTree(topTree,module);
} }
} }
} }

37
src/AddIns/Analysis/CodeQuality/Src/Helper.cs

@ -1,25 +1,21 @@
/* // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
* Created by SharpDevelop. // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
* User: Peter Forstmeier
* Date: 02.09.2011
* Time: 23:10
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System; using System;
using System.Windows.Media;
namespace ICSharpCode.CodeQualityAnalysis namespace ICSharpCode.CodeQualityAnalysis
{ {
/// <summary> /// <summary>
/// Description of Helper. /// Description of Helper.
/// </summary> /// </summary>
public class Helper public static class Helper
{ {
public static void FillTree (ICSharpCode.TreeView.SharpTreeView tree,Module module) public static void FillTree(ICSharpCode.TreeView.SharpTreeView tree,Module module)
{ {
tree.ShowRoot = false;
var root = CreateTreeItem(module); var root = CreateTreeItem(module);
tree.Root = root; tree.Root = root;
tree.ShowRoot = false;
foreach (var ns in module.Namespaces) foreach (var ns in module.Namespaces)
{ {
@ -34,23 +30,36 @@ namespace ICSharpCode.CodeQualityAnalysis
foreach (var method in type.Methods) foreach (var method in type.Methods)
{ {
var methodName = CreateTreeItem(method); var methodName = CreateTreeItem(method);
namespaceNode.Children.Add(methodName); typeNode.Children.Add(methodName);
} }
foreach (var field in type.Fields) foreach (var field in type.Fields)
{ {
var fieldNode = CreateTreeItem(field); var fieldNode = CreateTreeItem(field);
namespaceNode.Children.Add(fieldNode); typeNode.Children.Add(fieldNode);
} }
} }
} }
} }
private static DependecyTreeNode CreateTreeItem (INode node) private static DependecyTreeNode CreateTreeItem (INode node)
{ {
DependecyTreeNode dtn = new DependecyTreeNode(node); DependecyTreeNode dtn = new DependecyTreeNode(node);
return dtn; return dtn;
} }
public static Color MixedWith(this Color c1, Color c2)
{
int r = Math.Min((c1.R + c2.R), 255);
int g = Math.Min((c1.G + c2.G), 255);
int b = Math.Min((c1.B + c2.B), 255);
return new Color
{
R = Convert.ToByte(r),
G = Convert.ToByte(g),
B = Convert.ToByte(b)
};
}
} }
} }

2
src/AddIns/Analysis/CodeQuality/Src/Relationship.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.CodeQualityAnalysis
public void AddRelationship(RelationshipType type) public void AddRelationship(RelationshipType type)
{ {
if (type == RelationshipType.UseThis) if (type == RelationshipType.UseThis || type == RelationshipType.UsedBy)
OccurrenceCount++; OccurrenceCount++;
Relationships.Add(type); Relationships.Add(type);

72
src/AddIns/Analysis/CodeQuality/Src/Type.cs

@ -255,13 +255,71 @@ namespace ICSharpCode.CodeQualityAnalysis
public Relationship GetRelationship(INode node) public Relationship GetRelationship(INode node)
{ {
// if (node is Namespace) { Relationship relationship = new Relationship();
// Namespace ns = (Namespace)node;
// if (ns.Types.Contains(this) if (node == this) {
// return RelationshipType.Contains; relationship.Relationships.Add(RelationshipType.Same);
// } return relationship;
}
return new Relationship();
if (node is Namespace) {
Namespace ns = (Namespace)node;
if (this.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
if (this.BaseType != null && this.BaseType.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
foreach (var type in this.GenericBaseTypes) {
if (type.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
}
foreach (var type in this.GenericImplementedInterfacesTypes) {
if (type.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
}
foreach (var type in this.ImplementedInterfaces) {
if (type.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
}
foreach (var field in this.Fields) {
if (field.DeclaringType.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
if (field.FieldType != null && field.FieldType.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
if (field.GenericTypes.Any(type => type.Namespace.Name == ns.Name)) {
relationship.AddRelationship(RelationshipType.UseThis);
}
}
foreach (var method in this.Methods) {
if (method.TypeUses.Any(type => type.Namespace.Name == ns.Name)) {
relationship.AddRelationship(RelationshipType.UseThis);
}
if (method.GenericReturnTypes.Any(type => type.Namespace.Name == ns.Name)) {
relationship.AddRelationship(RelationshipType.UseThis);
}
if (method.DeclaringType != null && method.DeclaringType.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
if (method.ReturnType != null && method.ReturnType.Namespace.Name == ns.Name) {
relationship.AddRelationship(RelationshipType.UseThis);
}
}
}
return relationship;
} }
public override string ToString() public override string ToString()

18
src/AddIns/Analysis/CodeQuality/Src/Utility/IColorizer.cs

@ -0,0 +1,18 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Windows.Media;
namespace ICSharpCode.CodeQualityAnalysis.Utility
{
/// <summary>
/// Description of IColorizer.
/// </summary>
public interface IColorizer<TValue>
{
SolidColorBrush GetColorBrush(TValue value);
SolidColorBrush GetColorBrushMixedWith(Color color, TValue value);
Color GetColor(TValue value);
}
}

4
src/AddIns/Analysis/CodeQuality/Src/Utility/Matrix.cs

@ -36,6 +36,10 @@ namespace ICSharpCode.CodeQualityAnalysis.Utility
{ {
get get
{ {
if (rowIndex > HeaderRows.Count || rowIndex < 0 ||
columnIndex > HeaderColumns.Count || columnIndex < 0)
return default(TValue);
var cacheResult = GetFromCache(rowIndex, columnIndex); var cacheResult = GetFromCache(rowIndex, columnIndex);
if (cacheResult != null) if (cacheResult != null)
return cacheResult; return cacheResult;

Loading…
Cancel
Save