Skip to content

Commit cd5d5e7

Browse files
feat: expand and collapse all buttons
1 parent 12efd85 commit cd5d5e7

File tree

9 files changed

+286
-29
lines changed

9 files changed

+286
-29
lines changed

src/Resources/Locales/en_US.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,12 +708,14 @@
708708
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `git gc` command for this repository.</x:String>
709709
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
710710
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Clear</x:String>
711+
<x:String x:Key="Text.Repository.CollapseAll" xml:space="preserve">Collapse All</x:String>
711712
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
712713
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
713714
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Custom Actions</x:String>
714715
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No Custom Actions</x:String>
715716
<x:String x:Key="Text.Repository.Dashboard" xml:space="preserve">Dashboard</x:String>
716717
<x:String x:Key="Text.Repository.DiscardAll" xml:space="preserve">Discard all changes</x:String>
718+
<x:String x:Key="Text.Repository.ExpandAll" xml:space="preserve">Expand All</x:String>
717719
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open in File Browser</x:String>
718720
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>
719721
<x:String x:Key="Text.Repository.FilterCommits" xml:space="preserve">Visibility in Graph</x:String>

src/Resources/Locales/es_ES.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,12 +703,14 @@
703703
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Ejecutar comando `git gc` para este repositorio.</x:String>
704704
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Limpiar todo</x:String>
705705
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Limpiar</x:String>
706+
<x:String x:Key="Text.Repository.CollapseAll" xml:space="preserve">Contraer Todo</x:String>
706707
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configurar este repositorio</x:String>
707708
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUAR</x:String>
708709
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Acciones Personalizadas</x:String>
709710
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No hay ninguna Acción Personalizada</x:String>
710711
<x:String x:Key="Text.Repository.Dashboard" xml:space="preserve">Dashboard</x:String>
711712
<x:String x:Key="Text.Repository.DiscardAll" xml:space="preserve">Descartar todos los cambios</x:String>
713+
<x:String x:Key="Text.Repository.ExpandAll" xml:space="preserve">Expandir Todo</x:String>
712714
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Abrir en el Explorador</x:String>
713715
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Buscar Ramas/Etiquetas/Submódulos</x:String>
714716
<x:String x:Key="Text.Repository.FilterCommits" xml:space="preserve">Visibilidad en el Gráfico</x:String>

src/Resources/Locales/fr_FR.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,12 +688,14 @@
688688
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Lancer `git gc` pour ce repository.</x:String>
689689
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Tout effacer</x:String>
690690
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Nettoyer</x:String>
691+
<x:String x:Key="Text.Repository.CollapseAll" xml:space="preserve">Tout Réduire</x:String>
691692
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configurer ce repository</x:String>
692693
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUER</x:String>
693694
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Actions personnalisées</x:String>
694695
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">Pas d'actions personnalisées</x:String>
695696
<x:String x:Key="Text.Repository.Dashboard" xml:space="preserve">Tableau de bord</x:String>
696697
<x:String x:Key="Text.Repository.DiscardAll" xml:space="preserve">Rejeter tous les changements</x:String>
698+
<x:String x:Key="Text.Repository.ExpandAll" xml:space="preserve">Tout Développer</x:String>
697699
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Ouvrir dans l'explorateur de fichiers</x:String>
698700
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Rechercher Branches/Tags/Submodules</x:String>
699701
<x:String x:Key="Text.Repository.FilterCommits" xml:space="preserve">Visibilité dans le graphique</x:String>

src/Resources/Locales/it_IT.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,12 +642,14 @@
642642
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Esegui il comando `git gc` per questo repository.</x:String>
643643
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Cancella tutto</x:String>
644644
<x:String x:Key="Text.Repository.ClearStashes" xml:space="preserve">Cancella</x:String>
645+
<x:String x:Key="Text.Repository.CollapseAll" xml:space="preserve">Comprimi Tutto</x:String>
645646
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configura questo repository</x:String>
646647
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUA</x:String>
647648
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">Azioni Personalizzate</x:String>
648649
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">Nessuna Azione Personalizzata</x:String>
649650
<x:String x:Key="Text.Repository.Dashboard" xml:space="preserve">Dashboard</x:String>
650651
<x:String x:Key="Text.Repository.DiscardAll" xml:space="preserve">Scarta tutte le modifiche</x:String>
652+
<x:String x:Key="Text.Repository.ExpandAll" xml:space="preserve">Espandi Tutto</x:String>
651653
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Apri nell'Esplora File</x:String>
652654
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Cerca Branch/Tag/Sottomodulo</x:String>
653655
<x:String x:Key="Text.Repository.FilterCommits" xml:space="preserve">Visibilità nel grafico</x:String>

src/Views/BranchTree.axaml.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,84 @@ public void ToggleNodeIsExpanded(ViewModels.BranchTreeNode node)
387387
_disableSelectionChangingEvent = false;
388388
}
389389

390+
public void ExpandAll()
391+
{
392+
if (Nodes == null || Nodes.Count == 0)
393+
return;
394+
395+
_disableSelectionChangingEvent = true;
396+
397+
// Set IsExpanded = true on all folder nodes recursively
398+
SetExpandedRecursive(Nodes, true);
399+
400+
// Rebuild rows
401+
var rows = Rows;
402+
rows.Clear();
403+
var newRows = new List<ViewModels.BranchTreeNode>();
404+
MakeRows(newRows, Nodes, 0);
405+
rows.AddRange(newRows);
406+
407+
// Persist state for all nodes
408+
var repo = DataContext as ViewModels.Repository;
409+
if (repo != null)
410+
PersistExpandedState(Nodes, repo);
411+
412+
RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
413+
_disableSelectionChangingEvent = false;
414+
}
415+
416+
public void CollapseAll()
417+
{
418+
if (Nodes == null || Nodes.Count == 0)
419+
return;
420+
421+
_disableSelectionChangingEvent = true;
422+
423+
// Set IsExpanded = false on all folder nodes recursively
424+
SetExpandedRecursive(Nodes, false);
425+
426+
// Rebuild rows (only root nodes visible)
427+
var rows = Rows;
428+
rows.Clear();
429+
var newRows = new List<ViewModels.BranchTreeNode>();
430+
MakeRows(newRows, Nodes, 0);
431+
rows.AddRange(newRows);
432+
433+
// Persist state for all nodes
434+
var repo = DataContext as ViewModels.Repository;
435+
if (repo != null)
436+
PersistExpandedState(Nodes, repo);
437+
438+
RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
439+
_disableSelectionChangingEvent = false;
440+
}
441+
442+
private void SetExpandedRecursive(List<ViewModels.BranchTreeNode> nodes, bool expanded)
443+
{
444+
foreach (var node in nodes)
445+
{
446+
// Only set IsExpanded for folder nodes (not branch leaves)
447+
if (node.Backend is not Models.Branch)
448+
node.IsExpanded = expanded;
449+
450+
// Recurse into children
451+
if (node.Children != null && node.Children.Count > 0)
452+
SetExpandedRecursive(node.Children, expanded);
453+
}
454+
}
455+
456+
private void PersistExpandedState(List<ViewModels.BranchTreeNode> nodes, ViewModels.Repository repo)
457+
{
458+
foreach (var node in nodes)
459+
{
460+
if (node.Backend is not Models.Branch)
461+
repo.UpdateBranchNodeIsExpanded(node);
462+
463+
if (node.Children != null && node.Children.Count > 0)
464+
PersistExpandedState(node.Children, repo);
465+
}
466+
}
467+
390468
protected override void OnSizeChanged(SizeChangedEventArgs e)
391469
{
392470
base.OnSizeChanged(e);

src/Views/Repository.axaml

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -192,36 +192,60 @@
192192
</Border>
193193

194194
<!-- Filter Branches/Tags/Submodules -->
195-
<TextBox Grid.Row="1"
196-
Height="26"
197-
Margin="8,6,4,0"
198-
BorderThickness="1"
199-
CornerRadius="4"
200-
BorderBrush="{DynamicResource Brush.Border2}"
201-
Watermark="{DynamicResource Text.Repository.Filter}"
202-
Text="{Binding Filter, Mode=TwoWay}"
203-
VerticalContentAlignment="Center">
204-
<TextBox.InnerLeftContent>
205-
<Path Width="14" Height="14"
206-
Margin="6,0,0,0"
207-
Fill="{DynamicResource Brush.FG2}"
208-
Data="{StaticResource Icons.Search}"/>
209-
</TextBox.InnerLeftContent>
210-
211-
<TextBox.InnerRightContent>
212-
<Button Classes="icon_button"
213-
Width="16"
214-
Margin="0,0,6,0"
215-
Command="{Binding ClearFilter}"
216-
IsVisible="{Binding Filter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
217-
HorizontalAlignment="Right">
195+
<Grid Grid.Row="1" Height="26" Margin="8,6,4,0" ColumnDefinitions="*,Auto,Auto">
196+
<TextBox Grid.Column="0"
197+
BorderThickness="1"
198+
CornerRadius="4"
199+
BorderBrush="{DynamicResource Brush.Border2}"
200+
Watermark="{DynamicResource Text.Repository.Filter}"
201+
Text="{Binding Filter, Mode=TwoWay}"
202+
VerticalContentAlignment="Center">
203+
<TextBox.InnerLeftContent>
218204
<Path Width="14" Height="14"
219-
Margin="0,1,0,0"
220-
Fill="{DynamicResource Brush.FG1}"
221-
Data="{StaticResource Icons.Clear}"/>
222-
</Button>
223-
</TextBox.InnerRightContent>
224-
</TextBox>
205+
Margin="6,0,0,0"
206+
Fill="{DynamicResource Brush.FG2}"
207+
Data="{StaticResource Icons.Search}"/>
208+
</TextBox.InnerLeftContent>
209+
210+
<TextBox.InnerRightContent>
211+
<Button Classes="icon_button"
212+
Width="16"
213+
Margin="0,0,6,0"
214+
Command="{Binding ClearFilter}"
215+
IsVisible="{Binding Filter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
216+
HorizontalAlignment="Right">
217+
<Path Width="14" Height="14"
218+
Margin="0,1,0,0"
219+
Fill="{DynamicResource Brush.FG1}"
220+
Data="{StaticResource Icons.Clear}"/>
221+
</Button>
222+
</TextBox.InnerRightContent>
223+
</TextBox>
224+
225+
<!-- Expand All Button -->
226+
<Button Grid.Column="1"
227+
Classes="icon_button"
228+
Width="14"
229+
Margin="4,0,0,0"
230+
Click="OnExpandAllNodes"
231+
ToolTip.Tip="{DynamicResource Text.Repository.ExpandAll}">
232+
<Path Width="12" Height="12"
233+
Fill="{DynamicResource Brush.FG1}"
234+
Data="{StaticResource Icons.DoubleDown}"/>
235+
</Button>
236+
237+
<!-- Collapse All Button -->
238+
<Button Grid.Column="2"
239+
Classes="icon_button"
240+
Width="14"
241+
Margin="4,0,0,0"
242+
Click="OnCollapseAllNodes"
243+
ToolTip.Tip="{DynamicResource Text.Repository.CollapseAll}">
244+
<Path Width="12" Height="12"
245+
Fill="{DynamicResource Brush.FG1}"
246+
Data="{StaticResource Icons.DoubleUp}"/>
247+
</Button>
248+
</Grid>
225249

226250
<Grid Grid.Row="2" x:Name="LeftSidebarGroups" Margin="0,4,0,0" RowDefinitions="28,Auto,28,Auto,28,Auto,28,Auto,28,Auto" SizeChanged="OnLeftSidebarSizeChanged">
227251
<!-- Local Branches -->

src/Views/Repository.axaml.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,5 +598,41 @@ private async void OnBisectCommand(object sender, RoutedEventArgs e)
598598

599599
e.Handled = true;
600600
}
601+
602+
private void OnExpandAllNodes(object sender, RoutedEventArgs e)
603+
{
604+
if (DataContext is ViewModels.Repository repo)
605+
{
606+
repo.IsLocalBranchGroupExpanded = true;
607+
repo.IsRemoteGroupExpanded = true;
608+
repo.IsTagGroupExpanded = true;
609+
repo.IsSubmoduleGroupExpanded = true;
610+
repo.IsWorktreeGroupExpanded = true;
611+
}
612+
613+
LocalBranchTree?.ExpandAll();
614+
RemoteBranchTree?.ExpandAll();
615+
TagsList?.ExpandAll();
616+
SubmoduleList?.ExpandAll();
617+
e.Handled = true;
618+
}
619+
620+
private void OnCollapseAllNodes(object sender, RoutedEventArgs e)
621+
{
622+
if (DataContext is ViewModels.Repository repo)
623+
{
624+
repo.IsLocalBranchGroupExpanded = false;
625+
repo.IsRemoteGroupExpanded = false;
626+
repo.IsTagGroupExpanded = false;
627+
repo.IsSubmoduleGroupExpanded = false;
628+
repo.IsWorktreeGroupExpanded = false;
629+
}
630+
631+
LocalBranchTree?.CollapseAll();
632+
RemoteBranchTree?.CollapseAll();
633+
TagsList?.CollapseAll();
634+
SubmoduleList?.CollapseAll();
635+
e.Handled = true;
636+
}
601637
}
602638
}

src/Views/SubmodulesView.axaml.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23

34
using Avalonia;
45
using Avalonia.Controls;
@@ -118,6 +119,61 @@ public void ToggleNodeIsExpanded(ViewModels.SubmoduleTreeNode node)
118119
}
119120
}
120121

122+
public void ExpandAll()
123+
{
124+
if (Content is ViewModels.SubmoduleCollectionAsTree tree)
125+
{
126+
SetExpandedRecursive(tree.Tree, true);
127+
128+
// Rebuild rows manually
129+
tree.Rows.Clear();
130+
MakeTreeRows(tree.Rows, tree.Tree);
131+
132+
Rows = tree.Rows.Count;
133+
RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
134+
}
135+
}
136+
137+
public void CollapseAll()
138+
{
139+
if (Content is ViewModels.SubmoduleCollectionAsTree tree)
140+
{
141+
SetExpandedRecursive(tree.Tree, false);
142+
143+
// Rebuild rows manually
144+
tree.Rows.Clear();
145+
MakeTreeRows(tree.Rows, tree.Tree);
146+
147+
Rows = tree.Rows.Count;
148+
RaiseEvent(new RoutedEventArgs(RowsChangedEvent));
149+
}
150+
}
151+
152+
private void MakeTreeRows(Avalonia.Collections.AvaloniaList<ViewModels.SubmoduleTreeNode> rows, List<ViewModels.SubmoduleTreeNode> nodes)
153+
{
154+
foreach (var node in nodes)
155+
{
156+
rows.Add(node);
157+
158+
if (!node.IsExpanded || !node.IsFolder)
159+
continue;
160+
161+
MakeTreeRows(rows, node.Children);
162+
}
163+
}
164+
165+
private void SetExpandedRecursive(List<ViewModels.SubmoduleTreeNode> nodes, bool expanded)
166+
{
167+
foreach (var node in nodes)
168+
{
169+
if (node.IsFolder)
170+
node.IsExpanded = expanded;
171+
172+
if (node.Children != null && node.Children.Count > 0)
173+
SetExpandedRecursive(node.Children, expanded);
174+
}
175+
}
176+
121177
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
122178
{
123179
base.OnPropertyChanged(change);

0 commit comments

Comments
 (0)