Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/Files.App.Controls/Sidebar/FlatSidebarItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

namespace Files.App.Controls
{
/// <summary>
/// Per-row wrapper used by the sidebar's virtualized ItemsRepeater. Carries the row's tree depth and section-gap flags so the underlying data items don't have to.
/// </summary>
public sealed class FlatSidebarItem : INotifyPropertyChanged
{
public ISidebarItemModel Item { get; }

public int Depth { get; }

// Caller-supplied at construction; hidden filesystem items are dimmed to match the file list's dimming convention.
public double RowOpacity { get; }

private static readonly PropertyChangedEventArgs SectionGapMarginChangedArgs = new(nameof(SectionGapMargin));

private bool _hasExpandedPredecessor;
public bool HasExpandedPredecessor
{
get => _hasExpandedPredecessor;
set
{
if (_hasExpandedPredecessor == value)
return;
_hasExpandedPredecessor = value;
PropertyChanged?.Invoke(this, SectionGapMarginChangedArgs);
}
}

public Thickness SectionGapMargin => _hasExpandedPredecessor
? new Thickness(0, 12, 0, 0)
: new Thickness(0);

public event PropertyChangedEventHandler? PropertyChanged;

public FlatSidebarItem(ISidebarItemModel item, int depth, double rowOpacity = 1.0)
{
Item = item;
Depth = depth;
RowOpacity = rowOpacity;
}
}
}
13 changes: 9 additions & 4 deletions src/Files.App.Controls/Sidebar/ISidebarItemModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ public interface ISidebarItemModel : INotifyPropertyChanged
bool IsExpanded { get; set; }

/// <summary>
/// Indicates whether the children should have an indentation or not.
/// Optional path associated with this sidebar item for drag/drop scenarios.
/// </summary>
bool PaddedItem { get; }
string? Path { get; }

/// <summary>
/// Optional path associated with this sidebar item for drag/drop scenarios.
/// Renders as expandable even when Children is empty (children load lazily on first expansion).
/// </summary>
string? Path { get; }
bool HasUnrealizedChildren => false;

/// <summary>
/// Expansion participant that keeps the regular row appearance (icon + normal text) instead of the section-header style.
/// </summary>
bool IsLeafWithChildren => false;
Comment thread
yair100 marked this conversation as resolved.
}
}
60 changes: 39 additions & 21 deletions src/Files.App.Controls/Sidebar/SidebarItem.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ public SidebarView? Owner
set { SetValue(OwnerProperty, value); }
}
public static readonly DependencyProperty OwnerProperty =
DependencyProperty.Register(nameof(Owner), typeof(SidebarView), typeof(SidebarItem), new PropertyMetadata(null));
DependencyProperty.Register(nameof(Owner), typeof(SidebarView), typeof(SidebarItem), new PropertyMetadata(null, OnOwnerChanged));

// Owner is assigned by the hosting ItemsRepeater's ElementPrepared (top-level rows) or by the parent row (flyout children) — recycled containers can carry a stale Owner across realizations, so the chevron-column visual state must re-apply whenever Owner flips.
private static void OnOwnerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is SidebarItem item && item.Owner is { } owner)
VisualStateManager.GoToState(item, owner.SupportsExpansion ? "OwnerSupportsExpansion" : "OwnerDoesNotSupportExpansion", false);
}

public bool IsSelected
{
Expand All @@ -31,6 +38,37 @@ public bool IsExpanded
public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.Register(nameof(IsExpanded), typeof(bool), typeof(SidebarItem), new PropertyMetadata(true, OnPropertyChanged));

public int NestingLevel
{
get { return (int)GetValue(NestingLevelProperty); }
set { SetValue(NestingLevelProperty, value); }
}
public static readonly DependencyProperty NestingLevelProperty =
DependencyProperty.Register(nameof(NestingLevel), typeof(int), typeof(SidebarItem), new PropertyMetadata(0, OnNestingLevelChanged));

public double IndentWidth
{
get { return (double)GetValue(IndentWidthProperty); }
set { SetValue(IndentWidthProperty, value); }
}
public static readonly DependencyProperty IndentWidthProperty =
DependencyProperty.Register(nameof(IndentWidth), typeof(double), typeof(SidebarItem), new PropertyMetadata(0d));

private static void OnNestingLevelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is SidebarItem item && e.NewValue is int level)
item.IndentWidth = level * 16d;
}

// Dims icon + text + chevron + decorator only; the selection indicator and pointer-over fill stay at full opacity so a selected hidden row still reads as selected.
public double ContentOpacity
{
get { return (double)GetValue(ContentOpacityProperty); }
set { SetValue(ContentOpacityProperty, value); }
}
public static readonly DependencyProperty ContentOpacityProperty =
DependencyProperty.Register(nameof(ContentOpacity), typeof(double), typeof(SidebarItem), new PropertyMetadata(1.0));

public bool IsInFlyout
{
get { return (bool)GetValue(IsInFlyoutProperty); }
Expand All @@ -39,15 +77,6 @@ public bool IsInFlyout
public static readonly DependencyProperty IsInFlyoutProperty =
DependencyProperty.Register(nameof(IsInFlyout), typeof(bool), typeof(SidebarItem), new PropertyMetadata(false));

public double ChildrenPresenterHeight
{
get { return (double)GetValue(ChildrenPresenterHeightProperty); }
set { SetValue(ChildrenPresenterHeightProperty, value); }
}
// Using 30 as a default in case something goes wrong
public static readonly DependencyProperty ChildrenPresenterHeightProperty =
DependencyProperty.Register(nameof(ChildrenPresenterHeight), typeof(double), typeof(SidebarItem), new PropertyMetadata(30d));

public ISidebarItemModel? Item
{
get { return (ISidebarItemModel)GetValue(ItemProperty); }
Expand Down Expand Up @@ -94,17 +123,6 @@ public SidebarDisplayMode DisplayMode
[GeneratedDependencyProperty]
public partial object? ToolTip { get; set; }

public static void SetTemplateRoot(DependencyObject target, FrameworkElement value)
{
target.SetValue(TemplateRootProperty, value);
}
public static FrameworkElement GetTemplateRoot(DependencyObject target)
{
return (FrameworkElement)target.GetValue(TemplateRootProperty);
}
public static readonly DependencyProperty TemplateRootProperty =
DependencyProperty.Register("TemplateRoot", typeof(FrameworkElement), typeof(SidebarItem), new PropertyMetadata(null));

public static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (sender is not SidebarItem item) return;
Expand Down
Loading
Loading