Browse Source

MatrixControl now implements IScrollInfo and supports UI virtualization.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6428 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Tomáš Linhart 15 years ago
parent
commit
89ffbd64b7
  1. 16
      src/AddIns/Analysis/CodeQuality/CodeQualityAnalysis.csproj
  2. 312
      src/AddIns/Analysis/CodeQuality/Src/Controls/MatrixControl.cs
  3. 13
      src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml

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

@ -113,16 +113,12 @@ @@ -113,16 +113,12 @@
<Compile Include="Src\Controls\DependencyEdge.cs" />
<Compile Include="Src\Controls\DependencyGraph.cs" />
<Compile Include="Src\Controls\DependencyGraphLayout.cs" />
<Compile Include="Src\Controls\DependencyMatrixControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Src\Controls\DependencyMatrixControl.cs" />
<Compile Include="Src\Controls\DependencyMatrix.cs" />
<Compile Include="Src\Controls\DependencyVertex.cs" />
<Compile Include="Src\Controls\DependencyIconVertexConverter.cs" />
<Compile Include="Src\Controls\Matrix.cs" />
<Compile Include="Src\Controls\MatrixControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Src\Controls\MatrixControl.cs" />
<Compile Include="Src\Controls\TreeMatrixControl.xaml.cs">
<DependentUpon>TreeMatrixControl.xaml</DependentUpon>
<SubType>Code</SubType>
@ -220,12 +216,12 @@ @@ -220,12 +216,12 @@
<ProjectReference Include="..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj">
<Project>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</Project>
<Name>ICSharpCode.Core.Presentation</Name>
<Private>False</Private>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj">
<Project>{8035765F-D51F-4A0C-A746-2FD100E19419}</Project>
<Name>ICSharpCode.SharpDevelop.Widgets</Name>
<Private>False</Private>
<Private>True</Private>
<EmbedInteropTypes>False</EmbedInteropTypes>
</ProjectReference>
<ProjectReference Include="..\..\DisplayBindings\WpfDesign\WpfDesign.Designer\Project\WpfDesign.Designer.csproj">
@ -240,9 +236,7 @@ @@ -240,9 +236,7 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Themes" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

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

@ -1,27 +1,43 @@ @@ -1,27 +1,43 @@
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace ICSharpCode.CodeQualityAnalysis.Controls
{
public class MatrixControl<TValue> : FrameworkElement // TODO: Virtualization
public class MatrixControl<TValue> : FrameworkElement, IScrollInfo
{
Dictionary<string, ImageSource> imgs = new Dictionary<string, ImageSource>();
Point currentPoint = new Point(-1, -1);
string font;
private Dictionary<string, ImageSource> imgs = new Dictionary<string, ImageSource>();
private Coords currentCell = new Coords(-1, -1);
private string font;
private bool canHorizontalScroll = true;
private bool canVerticalScroll = true;
private Size extent = new Size(0, 0);
private Size viewport = new Size(0, 0);
private Point offset;
// will be loaded from Matrix
int cellsVertically = 25;
int cellsHorizontally = 25;
private int matrixWidth = 0;
private int matrixHeight = 0;
private Matrix<TValue> matrix;
public Matrix<TValue> Matrix { get; set; }
public Matrix<TValue> Matrix
{
get { return matrix; }
set
{
matrix = value;
matrixHeight = Matrix.HeaderRows.Count;
matrixWidth = Matrix.HeaderColumns.Count;
}
}
public int CellHeight { get; set; }
@ -30,6 +46,8 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -30,6 +46,8 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
public MatrixControl()
{
CellHeight = CellWidth = 36;
matrixWidth = 20;
matrixHeight = 20;
font = "Verdana";
}
@ -38,10 +56,12 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -38,10 +56,12 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
base.OnMouseMove(e);
var point = e.GetPosition(this);
if (point.X < cellsHorizontally * CellWidth && point.Y < cellsVertically * CellHeight)
currentPoint = point;
if (point.X < matrixWidth * CellWidth && point.Y < matrixHeight * CellHeight)
currentCell = new Coords(
(int)((point.X + offset.X) / CellWidth),
(int)((point.Y + offset.Y) / CellHeight));
else
currentPoint = new Point(-1, -1);
currentCell = new Coords(-1, -1);
InvalidateVisual();
}
@ -49,15 +69,36 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -49,15 +69,36 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
// how much space we got for cells
var maxWidth = ((int) viewport.Width / CellWidth) + 1;
var maxHeight = ((int) viewport.Height / CellHeight) + 1;
// how many cells we will draw
var cellsHorizontally = maxWidth > matrixWidth ? matrixWidth : maxWidth;
var cellsVertically = maxHeight > matrixHeight ? matrixHeight : maxHeight;
// number of cell which will be drawn
var scaledOffsetX = (int)offset.X / CellWidth;
var scaledOffsetY = (int)offset.Y / CellHeight;
// sets how much of cell on border should be drawn
var offsetDiffX = offset.X - scaledOffsetX * CellWidth;
var offsetDiffY = offset.Y - scaledOffsetY * CellHeight;
// background
var background = new Rect(0, 0, cellsHorizontally * CellWidth, cellsVertically * CellHeight);
var backgroundColor = new SolidColorBrush(Colors.Yellow);
drawingContext.DrawRectangle(backgroundColor, null, background);
// hover cell
if (currentPoint.X > 0 || currentPoint.Y > 0) {
var rect = new Rect(currentPoint.X - currentPoint.X % CellWidth, currentPoint.Y - currentPoint.Y % CellHeight, CellWidth, CellHeight);
if (currentCell.X >= 0 || currentCell.Y >= 0) {
var rect = new Rect(
(currentCell.X - scaledOffsetX) * CellWidth - offsetDiffX,
(currentCell.Y - scaledOffsetY) * CellHeight - offsetDiffY,
CellWidth,
CellHeight);
var brush = new SolidColorBrush(Colors.Red);
drawingContext.DrawRectangle(brush, null, rect);
}
@ -65,33 +106,37 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -65,33 +106,37 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
// grid
var pen = new Pen(Brushes.Black, 1);
for (int i = 0; i <= cellsHorizontally; i++) {
// grid x
for (int i = 0; i <= cellsHorizontally; i++)
drawingContext.DrawLine(pen,
new Point(i * CellWidth, 0),
new Point(i * CellWidth,
cellsHorizontally * CellWidth));
}
for (int i = 0; i <= cellsVertically; i++) {
new Point(i * CellWidth - offsetDiffX, 0),
new Point(i * CellWidth - offsetDiffX,
cellsVertically * CellWidth));
// grid y
for (int i = 0; i <= cellsVertically; i++)
drawingContext.DrawLine(pen,
new Point(0, i * CellHeight),
new Point(cellsVertically * CellHeight,
i * CellHeight));
}
new Point(0, i * CellHeight - offsetDiffY),
new Point(cellsHorizontally * CellHeight,
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++) {
drawingContext.DrawImage(CreateText(i * j), new Rect(i * CellWidth, j * CellHeight, CellWidth, CellHeight));
}
}
for (int i = 0; i < cellsHorizontally; i++)
for (int j = 0; j < cellsVertically; j++)
drawingContext.DrawImage(
CreateText((i + scaledOffsetX) * (j + scaledOffsetY)),
new Rect(i * CellWidth - offsetDiffX, j * CellHeight - offsetDiffY, CellWidth, CellHeight));
}
public ImageSource CreateText(int number)
{
return CreateText(number.ToString());
}
public ImageSource CreateText(string text)
{
if (imgs.ContainsKey(text))
@ -106,19 +151,206 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls @@ -106,19 +151,206 @@ namespace ICSharpCode.CodeQualityAnalysis.Controls
var size = g.MeasureString(text, fontOjb);
float spanWidth = CellWidth / 2 - size.Width / 2;
float spanHeight = CellHeight / 2 - size.Height / 2;
var spanWidth = (CellWidth - size.Width) / 2;
var spanHeight = (CellHeight - size.Height) / 2;
g.DrawString(text, fontOjb, System.Drawing.Brushes.Black, new System.Drawing.PointF(spanWidth, spanHeight));
g.Dispose();
var img = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(),
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
var img = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromWidthAndHeight(bmp.Width, bmp.Height));
imgs.Add(text, img);
return img;
}
public bool CanVerticallyScroll
{
get { return canVerticalScroll; }
set { canVerticalScroll = value; }
}
public bool CanHorizontallyScroll
{
get { return canHorizontalScroll; }
set { canHorizontalScroll = value; }
}
/// <summary>
/// Width of entire component
/// </summary>
public double ExtentWidth
{
get { return extent.Width; }
}
/// <summary>
/// Height of entire component
/// </summary>
public double ExtentHeight
{
get { return extent.Height; }
}
/// <summary>
/// Width of available area
/// </summary>
public double ViewportWidth
{
get { return viewport.Width; }
}
/// <summary>
/// Height of available area
/// </summary>
public double ViewportHeight
{
get { return viewport.Height; }
}
/// <summary>
/// Where is scrollbar located on X
/// </summary>
public double HorizontalOffset
{
get { return offset.X; }
}
/// <summary>
/// Where is scrollbar located on Y
/// </summary>
public double VerticalOffset
{
get { return offset.Y; }
}
public ScrollViewer ScrollOwner { get; set; }
public void LineUp()
{
SetVerticalOffset(VerticalOffset - 1);
}
public void LineDown()
{
SetVerticalOffset(VerticalOffset + 1);
}
public void LineLeft()
{
SetHorizontalOffset(HorizontalOffset - 1);
}
public void LineRight()
{
SetHorizontalOffset(HorizontalOffset + 1);
}
public void PageUp()
{
SetVerticalOffset(VerticalOffset - CellHeight);
}
public void PageDown()
{
SetVerticalOffset(VerticalOffset + CellHeight);
}
public void PageLeft()
{
SetHorizontalOffset(HorizontalOffset - CellWidth);
}
public void PageRight()
{
SetHorizontalOffset(HorizontalOffset + CellWidth);
}
public void MouseWheelUp()
{
SetVerticalOffset(VerticalOffset - 4);
}
public void MouseWheelDown()
{
SetVerticalOffset(VerticalOffset + 4);
}
public void MouseWheelLeft()
{
SetVerticalOffset(HorizontalOffset + 4);
}
public void MouseWheelRight()
{
SetVerticalOffset(HorizontalOffset + 4);
}
public void SetHorizontalOffset(double offset)
{
if (offset == this.offset.X) return;
this.offset.X = offset;
InvalidateVisual();
}
public void SetVerticalOffset(double offset)
{
if (offset == this.offset.Y) return;
this.offset.Y = offset;
InvalidateVisual();
}
public Rect MakeVisible(Visual visual, Rect rectangle)
{
throw new NotImplementedException();
}
protected override Size MeasureOverride(Size availableSize)
{
VerifyScrollData(availableSize, new Size(matrixWidth * CellWidth, matrixHeight * CellHeight));
return viewport;
}
protected override Size ArrangeOverride(Size finalSize)
{
VerifyScrollData(finalSize, new Size(matrixWidth * CellWidth, matrixHeight * CellHeight));
return finalSize;
}
protected void VerifyScrollData(Size viewport, Size extent)
{
if (double.IsInfinity(viewport.Width))
viewport.Width = extent.Width;
if (double.IsInfinity(viewport.Height))
viewport.Height = extent.Height;
// if viewport changes so recalculates offsets
offset.X = Math.Max(0, Math.Min(offset.X, ExtentWidth - ViewportWidth));
offset.Y = Math.Max(0, Math.Min(offset.Y, ExtentHeight - ViewportHeight));
ScrollOwner.InvalidateScrollInfo();
this.extent = extent;
this.viewport = viewport;
if (ScrollOwner != null)
ScrollOwner.InvalidateScrollInfo();
}
private struct Coords
{
public int Y { get; private set; }
public int X { get; private set; }
public Coords(int x, int y) : this()
{
X = x;
Y = y;
}
}
}
}

13
src/AddIns/Analysis/CodeQuality/Src/Controls/TreeMatrixControl.xaml

@ -11,12 +11,12 @@ @@ -11,12 +11,12 @@
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TreeView Name="leftTree" Grid.Row="1" Grid.Column="0">
@ -31,11 +31,8 @@ @@ -31,11 +31,8 @@
</TreeView.LayoutTransform>
</TreeView>
<Controls:DependencyMatrixControl Grid.Column="1" Grid.Row="1"
x:Name="matrixControl"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
</Controls:DependencyMatrixControl>
<ScrollViewer Grid.Column="1" Grid.Row="1" CanContentScroll="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<Controls:DependencyMatrixControl x:Name="matrixControl" />
</ScrollViewer>
</Grid>
</UserControl>
Loading…
Cancel
Save