diff --git a/DsmSuite.DsmViewer.View/Matrix/MatrixCellsView.cs b/DsmSuite.DsmViewer.View/Matrix/MatrixCellsView.cs index eea1bd6..80e0b0e 100644 --- a/DsmSuite.DsmViewer.View/Matrix/MatrixCellsView.cs +++ b/DsmSuite.DsmViewer.View/Matrix/MatrixCellsView.cs @@ -5,16 +5,19 @@ namespace DsmSuite.DsmViewer.View.Matrix { + /// + /// The view for the square block of cells in a matrix. + /// public class MatrixCellsView : MatrixFrameworkElement { private MatrixViewModel _viewModel; private readonly MatrixTheme _theme; - private Rect _rect; + private Rect _rect; // Area of the cell that is being rendered (reused) private int? _hoveredRow; private int? _hoveredColumn; - private readonly double _pitch; - private readonly double _offset; - private readonly double _verticalTextOffset = 16.0; + private readonly double _pitch; // Distance between the same points in neighbouring cells + private readonly double _offset; // Distance between header and first cell (hor/ver) + private readonly double _verticalTextOffset = 11.0; // Distance between top of cell and baseline of text public MatrixCellsView() { @@ -86,6 +89,9 @@ protected override void OnRender(DrawingContext dc) { if (_viewModel != null) { + SolidColorBrush weightBrush = _theme.CellWeightColor; + Rect weightRect = new Rect(0, 0, _theme.MatrixCellSize, 0.5 * _theme.MatrixCellSize); + int matrixSize = _viewModel.MatrixSize; for (int row = 0; row < matrixSize; row++) { @@ -106,6 +112,13 @@ protected override void OnRender(DrawingContext dc) int weight = _viewModel.CellWeights[row][column]; if (weight > 0) { + //---- Weight as a filled block + weightRect.X = _rect.X; + weightRect.Y = _rect.Y + 0.5 * _rect.Height; + weightRect.Width = _theme.MatrixCellSize * _viewModel.WeightPercentiles[row][column]; + dc.DrawRectangle(weightBrush, null, weightRect); + + //---- Weight as a number char infinity = '\u221E'; string content = weight > 9999 ? infinity.ToString() : weight.ToString(); @@ -116,7 +129,7 @@ protected override void OnRender(DrawingContext dc) X = (column * _pitch) + (_pitch - textWidth) / 2, Y = (row * _pitch) + _verticalTextOffset }; - DrawText(dc, content, location, _theme.TextColor,_rect.Width - _theme.SpacingWidth); + DrawText(dc, content, location, _theme.TextColor, _rect.Width - _theme.SpacingWidth); } } } diff --git a/DsmSuite.DsmViewer.View/Matrix/MatrixTheme.cs b/DsmSuite.DsmViewer.View/Matrix/MatrixTheme.cs index c7d55d5..732b588 100644 --- a/DsmSuite.DsmViewer.View/Matrix/MatrixTheme.cs +++ b/DsmSuite.DsmViewer.View/Matrix/MatrixTheme.cs @@ -18,6 +18,7 @@ public MatrixTheme(FrameworkElement frameworkElement) MatrixHeaderHeight = (double)_frameworkElement.FindResource("MatrixHeaderHeight"); MatrixMetricsViewWidth = (double)_frameworkElement.FindResource("MatrixMetricsViewWidth"); TextColor = (SolidColorBrush)_frameworkElement.FindResource("TextColor"); + CellWeightColor = (SolidColorBrush)_frameworkElement.FindResource("CellWeightColor"); MatrixColorConsumer = (SolidColorBrush)_frameworkElement.FindResource("MatrixColorConsumer"); MatrixColorProvider = (SolidColorBrush)_frameworkElement.FindResource("MatrixColorProvider"); MatrixColorMatch = (SolidColorBrush)_frameworkElement.FindResource("MatrixColorMatch"); @@ -51,6 +52,7 @@ public MatrixTheme(FrameworkElement frameworkElement) public double MatrixHeaderHeight { get; } public double MatrixMetricsViewWidth { get; } public SolidColorBrush TextColor { get; } + public SolidColorBrush CellWeightColor { get; } public SolidColorBrush MatrixColorConsumer { get; } public SolidColorBrush MatrixColorProvider { get; } public SolidColorBrush MatrixColorMatch { get; } diff --git a/DsmSuite.DsmViewer.View/Resources/Themes/DarkTheme.xaml b/DsmSuite.DsmViewer.View/Resources/Themes/DarkTheme.xaml index 455d92e..92668c5 100644 --- a/DsmSuite.DsmViewer.View/Resources/Themes/DarkTheme.xaml +++ b/DsmSuite.DsmViewer.View/Resources/Themes/DarkTheme.xaml @@ -28,6 +28,8 @@ #ff0000 #00ff00 + #FFFFFF + 1.1 1.2 \ No newline at end of file diff --git a/DsmSuite.DsmViewer.View/Resources/Themes/LightTheme.xaml b/DsmSuite.DsmViewer.View/Resources/Themes/LightTheme.xaml index d9b664d..6a48396 100644 --- a/DsmSuite.DsmViewer.View/Resources/Themes/LightTheme.xaml +++ b/DsmSuite.DsmViewer.View/Resources/Themes/LightTheme.xaml @@ -28,6 +28,8 @@ #ff0000 #00ff00 + #606060 + 1.1 1.2 \ No newline at end of file diff --git a/DsmSuite.DsmViewer.View/Resources/Themes/PastelTheme.xaml b/DsmSuite.DsmViewer.View/Resources/Themes/PastelTheme.xaml index 59dbb3e..d105dd5 100644 --- a/DsmSuite.DsmViewer.View/Resources/Themes/PastelTheme.xaml +++ b/DsmSuite.DsmViewer.View/Resources/Themes/PastelTheme.xaml @@ -28,6 +28,8 @@ #ff0000 #00ff00 + #606060 + 1.1 1.2 \ No newline at end of file diff --git a/DsmSuite.DsmViewer.ViewModel/Matrix/MatrixViewModel.cs b/DsmSuite.DsmViewer.ViewModel/Matrix/MatrixViewModel.cs index 98a44c6..044cd99 100644 --- a/DsmSuite.DsmViewer.ViewModel/Matrix/MatrixViewModel.cs +++ b/DsmSuite.DsmViewer.ViewModel/Matrix/MatrixViewModel.cs @@ -7,6 +7,7 @@ using DsmSuite.DsmViewer.Model.Interfaces; using DsmSuite.DsmViewer.ViewModel.Main; using DsmSuite.DsmViewer.ViewModel.Lists; +using System.Security.RightsManagement; namespace DsmSuite.DsmViewer.ViewModel.Matrix { @@ -35,6 +36,9 @@ public class MatrixViewModel : ViewModelBase, IMatrixViewModel private int? _selectedConsumerId; private int? _selectedProviderId; + private const int _nrWeightBuckets = 10; // Number of buckets (quantiles) for grouping cell weights. + private List> _weightPercentiles; // The weight bucket for every cell as a percentile + private ElementToolTipViewModel _columnHeaderTooltipViewModel; private CellToolTipViewModel _cellTooltipViewModel; @@ -187,6 +191,13 @@ public ObservableCollection ElementViewModelTree public IReadOnlyList ColumnElementIds => _columnElementIds; public IReadOnlyList> CellColors => _cellColors; public IReadOnlyList> CellWeights => _cellWeights; + /// + /// The weight percentile for every cell as a number between 0 and 1. + /// These are not actual percentiles, but quantiles with _nrWeightBuckets" buckets, + /// where bucket 0 is reserved for cells with weight 0. + /// + public IReadOnlyList> WeightPercentiles => _weightPercentiles; + public IReadOnlyList Metrics => _metrics; public double ZoomLevel @@ -540,11 +551,18 @@ private void DefineColumnContent() } } + /// + /// For every cell, set its weight and its weight bucket. + /// private void DefineCellContent() { - _cellWeights = new List>(); + List sortedWeights = new List(); + List buckets = new List(_nrWeightBuckets); + int matrixSize = _elementViewModelLeafs.Count; + //---- Set weight for every cell + _cellWeights = new List>(); for (int row = 0; row < matrixSize; row++) { _cellWeights.Add(new List()); @@ -554,10 +572,41 @@ private void DefineCellContent() IDsmElement provider = _elementViewModelLeafs[row].Element; int weight = _application.GetDependencyWeight(consumer, provider); _cellWeights[row].Add(weight); + if (weight > 0) + sortedWeights.Add(weight); + } + } + + //---- Set up weight buckets + buckets.Add(0); + if (sortedWeights.Count > 0) + { + sortedWeights.Sort(); + int stepSize = sortedWeights.Count / _nrWeightBuckets; + for (int i = 1; i < _nrWeightBuckets; i++) + { + buckets.Add(sortedWeights[i * stepSize]); + } + } + + //---- Assign every cell its weight percentile + _weightPercentiles = new List>(); + for (int row = 0; row < matrixSize; row++) + { + _weightPercentiles.Add(new List()); + for (int column = 0; column < matrixSize; column++) + { + int i = buckets.Count-1; + while (_cellWeights[row][column] < buckets[i]) + i--; + if (i == 0) // Bucket 0 is for weight 0 exclusively + i = 1; + _weightPercentiles[row].Add(i / (double) _nrWeightBuckets); } } } + private void DefineMetrics() { _metrics = new List();