Skip to content

Commit 0da897f

Browse files
committed
Add grid transpose functionality to UI and view models
Introduces a transpose feature for the grid, including a new command and UI button. Updates view models and rendering logic to support transposed state, adapts header sizing, and corrects hover behavior. Removes unused Splat.NLog dependency and related code.
1 parent bc08e6e commit 0da897f

9 files changed

Lines changed: 128 additions & 77 deletions

File tree

src/Demo.AvaloniaApplication/ViewModels/MainViewModel.cs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class MainViewModel : ViewModelBase
2727
public ReactiveCommand<Unit, Unit> SwitchTestTheme { get; }
2828
public ReactiveCommand<Unit, Unit> CycleRowHeights { get; }
2929
public ReactiveCommand<Unit, Unit> CycleFontSizes { get; }
30+
public ReactiveCommand<Unit, Unit> TransposeGrid { get; }
3031

3132
public MainViewModel()
3233
{
@@ -36,6 +37,11 @@ public MainViewModel()
3637
return dg.GenerateSample();
3738
});
3839

40+
TransposeGrid = ReactiveCommand.Create(() =>
41+
{
42+
DemoViewModel.IsTransposed = !DemoViewModel.IsTransposed;
43+
});
44+
3945
BuildTestDefinitions = ReactiveCommand.CreateRunInBackground(
4046
() => new HierarchyDefinitions(BuildRows(), BuildColumns())
4147
);
@@ -178,18 +184,21 @@ var child in Enumerable
178184
int.TryParse(o.ToString(), out var i)
179185
? i switch
180186
{
181-
17 => (
182-
new ThemeColor(150, 100, 120, 0),
183-
new ThemeColor(255, 0, 0, 0)
184-
),
185-
18 => (
186-
new ThemeColor(150, 0, 100, 120),
187-
new ThemeColor(255, 255, 0, 0)
188-
),
189-
_ => (
190-
new ThemeColor(0, 0, 0, 0),
191-
new ThemeColor(0, 255, 0, 0)
192-
),
187+
17
188+
=> (
189+
new ThemeColor(150, 100, 120, 0),
190+
new ThemeColor(255, 0, 0, 0)
191+
),
192+
18
193+
=> (
194+
new ThemeColor(150, 0, 100, 120),
195+
new ThemeColor(255, 255, 0, 0)
196+
),
197+
_
198+
=> (
199+
new ThemeColor(0, 0, 0, 0),
200+
new ThemeColor(0, 255, 0, 0)
201+
),
193202
}
194203
: (
195204
new ThemeColor(0, 0, 0, 0),
@@ -203,9 +212,10 @@ var child in Enumerable
203212
cdef.RightDecor = (_, o) =>
204213
o switch
205214
{
206-
int i => i % 2 == 0
207-
? "Resources/comment.svg"
208-
: string.Empty,
215+
int i
216+
=> i % 2 == 0
217+
? "Resources/comment.svg"
218+
: string.Empty,
209219
_ => string.Empty,
210220
};
211221
cdef.Editor = (p, c, s) =>

src/Demo.AvaloniaApplication/Views/MainView.axaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
Content="Fill"
2525
HorizontalAlignment="Stretch"
2626
HorizontalContentAlignment="Center"/>
27+
<Button x:Name="ButtonTranspose"
28+
Content="Transpose"
29+
HorizontalAlignment="Stretch"
30+
HorizontalContentAlignment="Center"/>
2731
</UniformGrid>
2832
<hierarchyGrid:Grid x:Name="HierarchyGrid"
2933
DefaultColumnWidth="250"

src/Demo.AvaloniaApplication/Views/MainView.axaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,8 @@ CompositeDisposable disposables
5151

5252
view.BindCommand(viewModel, vm => vm.CycleFontSizes, v => v.ButtonCycleFontSize)
5353
.DisposeWith(disposables);
54+
55+
view.BindCommand(viewModel, vm => vm.TransposeGrid, v => v.ButtonTranspose)
56+
.DisposeWith(disposables);
5457
}
5558
}

src/Demo/App.xaml.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System.Windows;
88
using NLog.Targets;
99
using Splat;
10-
using Splat.NLog;
1110

1211
namespace Demo
1312
{
@@ -19,28 +18,28 @@ public partial class App : Application
1918
public App()
2019
{
2120
ConfigureLogs();
22-
Locator.CurrentMutable.UseNLogWithWrappingFullLogger();
21+
// Locator.CurrentMutable.UseNLogWithWrappingFullLogger();
2322
}
2423

2524
private void ConfigureLogs()
2625
{
2726
var config = new NLog.Config.LoggingConfiguration();
2827

2928
// Targets where to log to: File and Console
30-
var logfile = new NLog.Targets.FileTarget( "logfile" )
29+
var logfile = new NLog.Targets.FileTarget("logfile")
3130
{
32-
FileName = "hierarchygrid.log" ,
33-
AutoFlush = true ,
31+
FileName = "hierarchygrid.log",
32+
AutoFlush = true,
3433
DeleteOldFileOnStartup = true
3534
};
36-
var logconsole = new NLog.Targets.ConsoleTarget( "logconsole" );
35+
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
3736

3837
// Rules for mapping loggers to targets
39-
config.AddRule( NLog.LogLevel.Info , NLog.LogLevel.Fatal , logconsole );
40-
config.AddRule( NLog.LogLevel.Debug , NLog.LogLevel.Fatal , logfile );
38+
config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, logconsole);
39+
config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);
4140

4241
// Apply config
4342
NLog.LogManager.Configuration = config;
4443
}
4544
}
46-
}
45+
}

src/Demo/Demo.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
<ItemGroup>
2020
<PackageReference Include="Bogus" Version="35.6.5" />
2121
<PackageReference Include="NLog" Version="6.0.7" />
22-
<PackageReference Include="Splat.NLog" Version="19.1.1" />
2322
</ItemGroup>
2423

2524
<ItemGroup>

src/HierarchyGrid.Avalonia/Grid.axaml.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,14 @@ double screenScale
487487
CommandParameter = false,
488488
}
489489
);
490+
contextMenu.Items.Add(
491+
new MenuItem
492+
{
493+
Header = "Transpose",
494+
IsChecked = viewModel.IsTransposed,
495+
Command = viewModel.ToggleTransposeCommand
496+
}
497+
);
490498

491499
contextMenu.Items.Add(new Separator());
492500

src/HierarchyGrid.Definitions/HierarchyGridViewModel.cs

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,13 @@ private void TriggerGridDrawing(CompositeDisposable disposables)
509509
// Events starting a grid redraw
510510
Observable
511511
.Merge(
512-
this.WhenAnyValue(x => x.IsTransposed).Select(_ => false),
512+
this.WhenAnyValue(x => x.IsTransposed)
513+
.Do(isTransposed =>
514+
{
515+
/* Need to adapt headers size on transpose */
516+
SetHeadersDimension(isTransposed);
517+
})
518+
.Select(_ => false),
513519
this.WhenAnyValue(x => x.Theme).WhereNotNull().Select(_ => false),
514520
SelectionChanged.DistinctUntilChanged().Select(_ => false),
515521
gridLayoutEventsObservable.Select(_ => false),
@@ -523,6 +529,42 @@ private void TriggerGridDrawing(CompositeDisposable disposables)
523529
.DisposeWith(disposables);
524530
}
525531

532+
private void SetHeadersDimension(bool isTransposed, bool preserveSizes = false)
533+
{
534+
var rowDefinitions = !isTransposed
535+
? Producers.Cast<HierarchyDefinition>()
536+
: Consumers.Cast<HierarchyDefinition>();
537+
var columnDefinitions = !isTransposed
538+
? Consumers.Cast<HierarchyDefinition>()
539+
: Producers.Cast<HierarchyDefinition>();
540+
541+
RowsHeadersWidth =
542+
[
543+
.. Enumerable.Range(0, rowDefinitions.TotalDepth()).Select(_ => DefaultHeaderWidth),
544+
];
545+
546+
ColumnsHeadersHeight =
547+
[
548+
.. Enumerable.Range(0, columnDefinitions.TotalDepth()).Select(_ => DefaultHeaderHeight),
549+
];
550+
551+
var columnsCount = columnDefinitions.TotalCount(true);
552+
if (!preserveSizes || columnsCount != ColumnsWidths.Count)
553+
{
554+
ColumnsWidths.Clear();
555+
for (int x = 0; x <= columnsCount; x++)
556+
ColumnsWidths.Add(x, DefaultColumnWidth);
557+
}
558+
559+
var rowsCount = rowDefinitions.TotalCount(true);
560+
if (!preserveSizes || rowsCount != RowsHeights.Count)
561+
{
562+
RowsHeights.Clear();
563+
for (int x = 0; x <= rowsCount; x++)
564+
RowsHeights.Add(x, DefaultRowHeight);
565+
}
566+
}
567+
526568
/// <summary>
527569
/// Registers default interaction handlers for the specified <see cref="HierarchyGridViewModel"/> instance.
528570
/// Those interactions do nothing but prevent exceptions if called without real implementation.
@@ -623,36 +665,7 @@ public void Set(HierarchyDefinitions hierarchyDefinitions, bool preserveSizes =
623665
Producers = hierarchyDefinitions.Producers;
624666
Consumers = hierarchyDefinitions.Consumers;
625667

626-
// TODO: change if transposed is implemented
627-
var rowDefinitions = Producers;
628-
var columnDefinitions = Consumers;
629-
630-
RowsHeadersWidth =
631-
[
632-
.. Enumerable.Range(0, rowDefinitions.TotalDepth()).Select(_ => DefaultHeaderWidth),
633-
];
634-
635-
ColumnsHeadersHeight =
636-
[
637-
.. Enumerable.Range(0, columnDefinitions.TotalDepth()).Select(_ => DefaultHeaderHeight),
638-
];
639-
640-
var columnsCount = columnDefinitions.TotalCount(true);
641-
if (!preserveSizes || columnsCount != ColumnsWidths.Count)
642-
{
643-
ColumnsWidths.Clear();
644-
for (int x = 0; x <= columnsCount; x++)
645-
ColumnsWidths.Add(x, DefaultColumnWidth);
646-
}
647-
648-
var rowsCount = rowDefinitions.TotalCount(true);
649-
if (!preserveSizes || rowsCount != RowsHeights.Count)
650-
{
651-
RowsHeights.Clear();
652-
for (int x = 0; x <= rowsCount; x++)
653-
RowsHeights.Add(x, DefaultRowHeight);
654-
}
655-
668+
SetHeadersDimension(IsTransposed, preserveSizes);
656669
Observable.Return(true).InvokeCommand(DrawGridCommand);
657670
}
658671

@@ -1095,19 +1108,33 @@ private void HoverHeader(Option<PositionedDefinition> definition, double x, doub
10951108
s =>
10961109
{
10971110
HoveredElementId = s.Definition.DefinitionId;
1111+
1112+
// Reset first
1113+
HoveredRow = -1;
1114+
HoveredColumn = -1;
1115+
10981116
switch (s.Definition)
10991117
{
11001118
case ConsumerDefinition consumer when consumer.Count() == 1:
1101-
HoveredColumn = ColumnsDefinitions.GetPosition(consumer);
1102-
HoveredRow = -1;
1119+
{
1120+
if (IsTransposed)
1121+
HoveredRow = RowsDefinitions.GetPosition(consumer);
1122+
else
1123+
HoveredColumn = ColumnsDefinitions.GetPosition(consumer);
11031124
break;
1125+
}
1126+
11041127
case ProducerDefinition producer when producer.Count() == 1:
1105-
HoveredRow = RowsDefinitions.GetPosition(producer);
1106-
HoveredColumn = -1;
1128+
{
1129+
if (IsTransposed)
1130+
HoveredColumn = ColumnsDefinitions.GetPosition(producer);
1131+
else
1132+
HoveredRow = RowsDefinitions.GetPosition(producer);
11071133
break;
1134+
}
1135+
11081136
default:
1109-
HoveredColumn = -1;
1110-
HoveredRow = -1;
1137+
// Already reset above; nothing to do
11111138
break;
11121139
}
11131140
},

src/HierarchyGrid.Skia/RenderInfo.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,13 @@ HierarchyDefinition hdef
190190

191191
private static bool IsHovered(HierarchyGridViewModel viewModel, HierarchyDefinition hdef)
192192
{
193-
var isColumn = hdef is ConsumerDefinition && !viewModel.IsTransposed;
194-
var position = isColumn
195-
? viewModel.ColumnsDefinitions.GetPosition(hdef)
196-
: viewModel.RowsDefinitions.GetPosition(hdef);
197-
var isHovered = isColumn
198-
? viewModel.HoveredColumn == position
199-
: viewModel.HoveredRow == position;
200-
return isHovered;
193+
return hdef is ConsumerDefinition
194+
? viewModel.IsTransposed
195+
? viewModel.HoveredRow == viewModel.RowsDefinitions.GetPosition(hdef)
196+
: viewModel.HoveredColumn == viewModel.ColumnsDefinitions.GetPosition(hdef)
197+
: viewModel.IsTransposed
198+
? viewModel.HoveredColumn == viewModel.ColumnsDefinitions.GetPosition(hdef)
199+
: viewModel.HoveredRow == viewModel.RowsDefinitions.GetPosition(hdef);
201200
}
202201
}
203202
}

src/HierarchyGrid/Grid.xaml.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,15 @@ double screenScale
437437
CommandParameter = false,
438438
}
439439
);
440-
//contextMenu.Items.Add( new MenuItem
441-
//{
442-
// Header = "Transposed" ,
443-
// IsChecked = viewModel.IsTransposed ,
444-
// IsCheckable = true ,
445-
// Command = viewModel.ToggleTransposeCommand
446-
//} );
440+
contextMenu.Items.Add(
441+
new MenuItem
442+
{
443+
Header = "Transpose",
444+
IsChecked = viewModel.IsTransposed,
445+
IsCheckable = true,
446+
Command = viewModel.ToggleTransposeCommand
447+
}
448+
);
447449

448450
contextMenu.Items.Add(new Separator());
449451

0 commit comments

Comments
 (0)