Skip to content

Commit

Permalink
Finish TreeView V1 and demos for it
Browse files Browse the repository at this point in the history
  • Loading branch information
fgilde committed Jun 27, 2024
1 parent 1bbcc0c commit 437c983
Show file tree
Hide file tree
Showing 24 changed files with 843 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

namespace MudBlazor.Extensions.Components;

/// <summary>
/// TreeView component that renders a tree structure of items.
/// </summary>
/// <typeparam name="T"></typeparam>
public partial class MudExTreeView<T>
where T : IHierarchical<T>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public TreeViewItemContext(T item,
/// <summary>
/// The string that was used to search for this item.
/// </summary>
public string Search { get; }
public string Search { get; }

/// <summary>
/// The recommended string to highlight in the item.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Microsoft.AspNetCore.Components;
using MudBlazor.Extensions.Attribute;
using MudBlazor.Extensions.Components.Base;
using MudBlazor.Extensions.Components.ObjectEdit;
using MudBlazor.Extensions.Core;
using MudBlazor.Extensions.Core.Css;
using MudBlazor.Extensions.Core.Enums;
using MudBlazor.Extensions.Helper;
using MudBlazor.Extensions.Helper.Internal;
using Nextended.Core.Extensions;
Expand Down Expand Up @@ -94,9 +96,9 @@ public abstract partial class MudExTreeViewBase<TItem> : MudExBaseComponent<MudE
[Parameter] public bool FilterMultiple { get; set; } = true;

/// <summary>
/// If true the expand button will be on the other right side of the item content
/// Controls if the expand button is at the start or end
/// </summary>
[Parameter] public bool ReverseExpandButton { get; set; }
[Parameter] public LeftOrRight? ExpandButtonDirection { get; set; }

/// <summary>
/// Dense mode for the treeview
Expand Down Expand Up @@ -132,6 +134,7 @@ public abstract partial class MudExTreeViewBase<TItem> : MudExBaseComponent<MudE
/// Items to display in the treeview
/// </summary>
[Parameter]
[IgnoreOnObjectEdit]
public HashSet<TItem> Items
{
get => FilterManager.Items;
Expand All @@ -148,6 +151,16 @@ public Func<TItem, string> TextFunc
set => FilterManager.TextFunc = value;
}

/// <summary>
/// This function controls how a separator will be detected. Default is if the item ToString() equals '-'
/// </summary>
[Parameter] public Func<TItem, bool> IsSeparatorDetectFunc { get; set; } = n => n?.ToString() == "-";

/// <summary>
/// Here you can specify a function to determine if a node is allowed to be selected
/// </summary>
[Parameter] public Func<TItem, bool> AllowedToSelectFunc { get; set; }

/// <summary>
/// Behaviour for the filtering
/// </summary>
Expand All @@ -169,11 +182,6 @@ public HierarchicalFilterBehaviour FilterBehaviour
/// </summary>
[Parameter] public RenderFragment<TreeViewItemContext<TItem>> ItemContentTemplate { get; set; }

/// <summary>
/// This function controls how a separator will be detected. Default is if the item ToString() equals '-'
/// </summary>
[Parameter] public Func<TItem, bool> IsSeparatorDetectFunc { get; set; } = n => n?.ToString() == "-";

/// <summary>
/// The expand/collapse icon.
/// </summary>
Expand All @@ -200,13 +208,14 @@ public HierarchicalFilterBehaviour FilterBehaviour
/// Selected node
/// </summary>
[Parameter]
[IgnoreOnObjectEdit]
public TItem SelectedNode
{
get => _selectedNode;
set => Set(ref _selectedNode, LastSelectedNode = value, _ =>
{
SelectedNodeChanged.InvokeAsync(value).AndForget();
if(AutoExpand)
if(ExpandOnClick)
ExpandTo(value);
});
}
Expand Down Expand Up @@ -315,22 +324,18 @@ protected virtual TreeViewItemContext<TItem> CreateContext(TItem item, string se
/// <summary>
/// Set to true to automatically expand the node when clicked and is not expanded
/// </summary>
[Parameter] public bool AutoExpand { get; set; } = true;
[Parameter] public bool ExpandOnClick { get; set; } = true;

/// <summary>
/// Set to true to automatically collapse the node when clicked and is already expanded
/// </summary>
[Parameter] public bool AutoCollapse { get; set; } = true;
[Parameter] public bool CollapseOnClick { get; set; } = true;

/// <summary>
/// Set to true to allow selection of nodes with children
/// </summary>
[Parameter] public bool AllowSelectionOfNonEmptyNodes { get; set; } = false;

/// <summary>
/// Here you can specify a function to determine if a node is allowed to be selected
/// </summary>
[Parameter] public Func<TItem, bool> AllowedToSelectFunc { get; set; }

/// <summary>
/// On node click
Expand Down Expand Up @@ -358,12 +363,12 @@ public virtual bool IsAllowedToSelect(TItem node)

private void ExecuteAutoExpand(TItem node)
{
if (node != null && (AutoExpand || AutoCollapse))
if (node != null && (ExpandOnClick || CollapseOnClick))
{
var isExpanded = IsExpanded(node);
if (isExpanded && AutoCollapse)
if (isExpanded && CollapseOnClick)
SetExpanded(node, false);
else if (!isExpanded && AutoExpand)
else if (!isExpanded && ExpandOnClick)
SetExpanded(node, true);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@typeparam T
@inherits MudExTreeViewBase<T>
@namespace MudBlazor.Extensions.Components
@using MudBlazor.Extensions.Options
@using Nextended.Core.Types

<MudToolBar Class="@Class" Style="@StyleStr()" Dense="@Dense" WrapContent="true">
Expand All @@ -21,9 +22,9 @@
return
@<RenderChild Condition="@(hierarchical?.Any(i => FilterManager.GetMatchedSearch(i).Found) == true)">
<MudMenu ActivationEvent="@(isSubMenu ? MouseEvent.MouseOver : MouseEvent.LeftClick)"
AnchorOrigin="Origin.TopRight"
TransformOrigin="Origin.TopLeft"
MaxHeight="500"
AnchorOrigin="@MenuAnchorOrigin"
TransformOrigin="@MenuTransformOrigin"
MaxHeight="@MenuMaxHeight"
Dense="@Dense"
EndIcon="@ExpandedIcon"
Icon="@(isSubMenu ? null : ExpandedIcon)">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
using MudBlazor.Extensions.Components.ObjectEdit;
using Microsoft.AspNetCore.Components;
using MudBlazor.Extensions.Components.ObjectEdit;
using Nextended.Core.Types;

namespace MudBlazor.Extensions.Components;

public partial class MudExTreeViewBreadcrumb<T>
where T : IHierarchical<T>
{

/// <summary>
/// Set the anchor origin point to determine where the popover will open from.
/// </summary>
[Parameter] public Origin MenuAnchorOrigin { get; set; } = Origin.BottomRight;

/// <summary>
/// Sets the transform origin point for the popover.
/// </summary>
[Parameter] public Origin MenuTransformOrigin { get; set; } = Origin.TopLeft;

/// <summary>
/// Max height of the menu when this is reached overflow will be scrollable
/// </summary>
[Parameter] public int MenuMaxHeight { get; set; } = 500;

/// <summary>
/// Class for use in the filter box
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
{
return
@<MudTreeViewItem Expanded="@context.IsExpanded"
OnClick="@(() => NodeClick(context.Item))"
Items="@(context.Item?.Children?.ToHashSet())">
Style="@ItemStyleStr(context)"
Class="@ItemClassStr(context)"
OnClick="@(() => NodeClick(context.Item))"
Items="@(context.Item?.Children?.ToHashSet())">
<Content>
<div style="@ItemStyleStr(context)" class="@ItemClassStr(context)">
<div style="@ContentFlexStyleStr()">
@if (ExpandBehaviour != Core.Enums.TreeViewExpandBehaviour.None)
{
<MudTreeViewItemToggleButton ExpandedIcon="@ExpandedIcon" ExpandedChanged="@(expanded => SetExpanded(context.Item, expanded))" Expanded="@context.IsExpanded" Visible="@(context.Item?.Children?.Any() == true)"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using MudBlazor.Extensions.Core;
using MudBlazor.Extensions.Core.Css;
using MudBlazor.Extensions.Core.Enums;
using MudBlazor.Extensions.Helper;
Expand Down Expand Up @@ -45,16 +46,17 @@ public override void SetExpanded(T context, bool expanded)
}
}

/// <inheritdoc />
protected override string ItemStyleStr(TreeViewItemContext<T> context, string mergeWith = "")
private string ContentFlexStyleStr()
{
return MudExStyleBuilder.FromStyle(base.ItemStyleStr(context, mergeWith))
return MudExStyleBuilder.Default
.WithWidth(100, CssUnit.Percentage)
.WithDisplay(Display.Flex)
.WithAlignItems(Core.Css.AlignItems.Center)
.WithFlexFlow(FlexFlow.RowReverse, ReverseExpandButton)
.WithJustifyContent(JustifyContent.SpaceBetween, ReverseExpandButton)
.WithFlexFlow(FlexFlow.RowReverse, ExpandButtonDirection == LeftOrRight.Right)
.WithJustifyContent(JustifyContent.SpaceBetween, ExpandButtonDirection == LeftOrRight.Right)
.Style;
}


}

Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@


<div id="@_treeId"
@onkeydown="KeyDown"
@onkeydown:stopPropagation="true"
@onkeydown:preventDefault="true"
@onwheel="OnWheel"
@onwheel:stopPropagation="true"
@onwheel:preventDefault="true"
tabindex="0"
class="mud-ex-horizontal-tree-wrapper">
@RenderSearchBar()
<div class="mud-ex-horizontal-tree" style="@StyleStr()">
<div @onkeydown="KeyDown"
@onkeydown:stopPropagation="@KeyDownHandled"
@onkeydown:preventDefault="@KeyDownHandled"
@onwheel="OnWheel"
@onwheel:stopPropagation="true"
@onwheel:preventDefault="true"
tabindex="0"
class="mud-ex-horizontal-tree"
style="@StyleStr()">
<div style="@ScrollHorizontalTree(LastSelectedNode)" class="mud-ex-horizontal-tree-scroll-wrapper">
@{
var items = FilterManager.FilteredItems()?.Where(n => FilterManager.GetMatchedSearch(n).Found).ToList() ?? new List<T>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using MudBlazor.Extensions.Core;
using MudBlazor.Extensions.Core.Enums;
using MudBlazor.Extensions.Helper;
using Nextended.Core.Extensions;
using Nextended.Core.Types;
Expand Down Expand Up @@ -55,10 +56,10 @@ protected override void OnInitialized()
{
if (!IsOverwritten(nameof(SelectedItemBorderColor)))
SelectedItemBorderColor = SelectedItemColor;
if (!IsOverwritten(nameof(AutoCollapse)))
AutoCollapse = false;
if (!IsOverwritten(nameof(AutoExpand)))
AutoExpand = true;
if (!IsOverwritten(nameof(CollapseOnClick)))
CollapseOnClick = false;
if (!IsOverwritten(nameof(ExpandOnClick)))
ExpandOnClick = true;
if (!IsOverwritten(nameof(AllowSelectionOfNonEmptyNodes)))
AllowSelectionOfNonEmptyNodes = true;
base.OnInitialized();
Expand All @@ -83,9 +84,11 @@ private void OnWheel(WheelEventArgs e)
NodeClick(siblings[newIndex]);
}

protected bool KeyDownHandled { get; set; }

private void KeyDown(KeyboardEventArgs args)
{
KeyDownHandled = false;
if (!new[] { "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "PageDown", "PageUp", "End", "Home" }.Contains(args.Code))
return;

Expand All @@ -99,34 +102,40 @@ private void KeyDown(KeyboardEventArgs args)
{
parent = parent.Parent;
}
if (!AutoExpand || AutoCollapse)
if (!ExpandOnClick || CollapseOnClick)
CollapseAll();
KeyDownHandled = true;
NodeClick(parent ?? toSelect);
}
else if (args.Code == "End" && selectedNode?.HasChildren() == true)
{
var lastOrDefault = selectedNode.Children.Recursive(n => n.Children ?? Enumerable.Empty<T>()).ToList();
var node = lastOrDefault.FirstOrDefault(n => !n.HasChildren());
ExpandTo(node);
KeyDownHandled = true;
NodeClick(node);
}
else if (args.Code == "PageDown" && siblings.Any())
{
KeyDownHandled = true;
NodeClick(siblings.LastOrDefault());
}
else if (args.Code == "PageUp" && siblings.Any())
{
KeyDownHandled = true;
NodeClick(siblings.FirstOrDefault());
}
else if (args.Code == "ArrowLeft" && selectedNode != null && selectedNode.Parent != null && FilterManager.GetMatchedSearch(selectedNode.Parent).Found)
{
if(!AutoExpand || AutoCollapse)
if(!ExpandOnClick || CollapseOnClick)
SetExpanded(selectedNode.Parent, false);
KeyDownHandled = true;
NodeClick(selectedNode.Parent);
}
else if (args.Code == "ArrowRight" && selectedNode?.HasChildren() == true)
{
SetExpanded(selectedNode, true);
KeyDownHandled = true;
NodeClick(selectedNode.Children.FirstOrDefault(n => FilterManager.GetMatchedSearch(n).Found));
}
else if (new[] { "ArrowUp", "ArrowDown" }.Contains(args.Code) && siblings.Any())
Expand All @@ -141,6 +150,7 @@ private void KeyDown(KeyboardEventArgs args)

if (newIndex >= 0 && newIndex < siblings.Length)
{
KeyDownHandled = true;
NodeClick(siblings[newIndex]);
}
}
Expand Down Expand Up @@ -201,7 +211,7 @@ private string InnerItemClassStr()
{
return MudExCssBuilder.Default.
AddClass("mud-ex-simple-flex")
.AddClass("mud-ex-flex-reverse-end", ReverseExpandButton)
.AddClass("mud-ex-flex-reverse-end", ExpandButtonDirection == LeftOrRight.Left)
.ToString();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using MudBlazor.Extensions.Core.Enums;
using MudBlazor.Extensions.Helper;
using MudBlazor.Extensions.Options;
using Nextended.Core.Types;
Expand Down Expand Up @@ -107,7 +108,7 @@ private string ListItemClassStr()
{
return MudExCssBuilder.Default.
AddClass("mud-ex-simple-flex")
.AddClass("mud-ex-flex-reverse-end", ReverseExpandButton)
.AddClass("mud-ex-flex-reverse-end", ExpandButtonDirection == LeftOrRight.Left)
.ToString();
}

Expand Down
7 changes: 7 additions & 0 deletions MudBlazor.Extensions/Core/Enums/LeftOrRight.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace MudBlazor.Extensions.Core.Enums;

public enum LeftOrRight
{
Left,
Right
}
Loading

0 comments on commit 437c983

Please sign in to comment.