Skip to content

Commit

Permalink
Support sub data sources
Browse files Browse the repository at this point in the history
  • Loading branch information
ReMinoer committed May 15, 2022
1 parent ecadfbb commit a3ee0de
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 19 deletions.
3 changes: 3 additions & 0 deletions Calame.Icons/Descriptors/FallbackIconDescriptor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.ComponentModel.Composition;
using System.Windows.Media;
using MahApps.Metro.IconPacks;
Expand All @@ -19,6 +20,8 @@ private IconDescription GetIcon(object model)
{
if (model == null)
return new IconDescription(PackIconMaterialKind.Null, DefaultBrush);
if (model is IEnumerable)
return new IconDescription(PackIconMaterialKind.Menu, DefaultBrush);

return new IconDescription(PackIconMaterialKind.RhombusOutline, DefaultBrush);
}
Expand Down
11 changes: 9 additions & 2 deletions Calame/UserControls/CalameTreeView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,17 @@
</TreeView.ItemsPanel>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Focusable" Value="{Binding IsEnabled}" />
<Setter Property="Focusable" Value="True" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
<Setter Property="Focusable" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding IsHeader}" Value="True">
<Setter Property="Focusable" Value="False" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
</DataTrigger>
<DataTrigger Binding="{Binding VisibleForFilter}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
Expand Down Expand Up @@ -105,7 +112,7 @@
IconSize="14"
IconProvider="{Binding IconProvider, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type userControls:CalameTreeView}}}"
VerticalAlignment="Center" />
<TextBlock Text="{Binding DisplayName}" Background="Transparent">
<TextBlock Text="{Binding DisplayName}" FontWeight="{Binding FontWeight}" Background="Transparent">
<b:Interaction.Behaviors>
<behaviors:TextBlockHighlightFilteredBehavior ItemText="{Binding DisplayName}"
FilterText="{Binding FilterText, ElementName=This}"
Expand Down
19 changes: 19 additions & 0 deletions Calame/Utils/TreeViewItemModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using Calame.Icons;
using Diese;
using Diese.Collections;
Expand All @@ -14,12 +16,15 @@ namespace Calame.Utils
public interface ITreeViewItemModel : IParentable<ITreeViewItemModel>, IEquatable<ITreeViewItemModel>, IDisposable
{
object Data { get; }

string DisplayName { get; }
FontWeight FontWeight { get; }
IconDescription IconDescription { get; }

new ITreeViewItemModel Parent { get; set; }
IObservableList<ITreeViewItemModel> Children { get; }

bool IsHeader { get; set; }
bool IsEnabled { get; set; }
bool IsDisabledByParent { get; set; }

Expand Down Expand Up @@ -53,13 +58,27 @@ public string DisplayName
set => Set(ref _displayName, value);
}

private FontWeight _fontWeight;
public FontWeight FontWeight
{
get => _fontWeight;
set => Set(ref _fontWeight, value);
}

private IconDescription _iconDescription;
public IconDescription IconDescription
{
get => _iconDescription;
set => Set(ref _iconDescription, value);
}

private bool _isHeader;
public bool IsHeader
{
get => _isHeader;
set => Set(ref _isHeader, value);
}

private bool _isEnabled = true;
public bool IsEnabled
{
Expand Down
18 changes: 18 additions & 0 deletions Calame/Utils/TreeViewItemModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Calame.Icons;
using Diese.Collections.Observables;
using Diese.Collections.Observables.ReadOnly;
Expand All @@ -17,12 +19,16 @@ public class TreeViewItemModelBuilder<T>

public TreeViewItemModelBuilder<T> DisplayName(Func<T, string> getter, string propertyName, Func<T, INotifyPropertyChanged> notifier = null)
=> DisplayName(getter, x => OnPropertyChanged(x, propertyName, notifier));
public TreeViewItemModelBuilder<T> FontWeight(Func<T, FontWeight> getter, string propertyName, Func<T, INotifyPropertyChanged> notifier = null)
=> FontWeight(getter, x => OnPropertyChanged(x, propertyName, notifier));
public TreeViewItemModelBuilder<T> IconDescription(Func<T, IconDescription> getter, string propertyName, Func<T, INotifyPropertyChanged> notifier = null)
=> IconDescription(getter, x => OnPropertyChanged(x, propertyName, notifier));
public TreeViewItemModelBuilder<T> ChildrenSource(Func<T, IReadOnlyObservableList<object>> getter, string propertyName, Func<T, INotifyPropertyChanged> notifier = null)
=> ChildrenSource(getter, x => OnPropertyChanged(x, propertyName, notifier));
public TreeViewItemModelBuilder<T> IsEnabled(Func<T, bool> getter, string propertyName, Func<T, INotifyPropertyChanged> notifier = null)
=> IsEnabled(getter, x => OnPropertyChanged(x, propertyName, notifier));
public TreeViewItemModelBuilder<T> IsHeader(Func<T, bool> getter, string propertyName, Func<T, INotifyPropertyChanged> notifier = null)
=> IsHeader(getter, x => OnPropertyChanged(x, propertyName, notifier));
public TreeViewItemModelBuilder<T> IsTriggered(Func<T, bool> getter, string propertyName, Func<T, INotifyPropertyChanged> notifier = null)
=> IsTriggered(getter, x => OnPropertyChanged(x, propertyName, notifier));

Expand Down Expand Up @@ -57,6 +63,12 @@ public TreeViewItemModelBuilder<T> DisplayName(Func<T, string> getter, Func<T, I
return this;
}

public TreeViewItemModelBuilder<T> FontWeight(Func<T, FontWeight> getter, Func<T, IObservable<object>> observableFunc = null)
{
AddBinding(getter, observableFunc, (v, x) => v.FontWeight = x);
return this;
}

public TreeViewItemModelBuilder<T> IconDescription(Func<T, IconDescription> getter, Func<T, IObservable<object>> observableFunc = null)
{
AddBinding(getter, observableFunc, (v, x) => v.IconDescription = x);
Expand All @@ -75,6 +87,12 @@ public TreeViewItemModelBuilder<T> IsEnabled(Func<T, bool> getter, Func<T, IObse
return this;
}

public TreeViewItemModelBuilder<T> IsHeader(Func<T, bool> getter, Func<T, IObservable<object>> observableFunc = null)
{
AddBinding(getter, observableFunc, (v, x) => v.IsHeader = x);
return this;
}

public TreeViewItemModelBuilder<T> IsTriggered(Func<T, bool> getter, Func<T, IObservable<object>> observableFunc = null)
{
AddBinding(getter, observableFunc, (v, x) => v.IsTriggered = x);
Expand Down
26 changes: 22 additions & 4 deletions Modules/Calame.BrushPanel/ViewModels/BrushPanelViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Calame.DocumentContexts;
using Calame.Icons;
Expand Down Expand Up @@ -35,6 +37,7 @@ public sealed class BrushPanelViewModel : CalameTool<IDocumentContext<ViewerView
private ISelectionContext _selectionContext;

private readonly TreeViewItemModelBuilder<IGlyphData> _dataTreeItemBuilder;
private readonly TreeViewItemModelBuilder<IReadOnlyObservableCollection<IGlyphData>> _childrenSourceItemBuilder;
private readonly TreeViewItemModelBuilder<IGlyphComponent> _componentTreeItemBuilder;

public bool DisableChildrenIfParentDisabled => true;
Expand Down Expand Up @@ -106,17 +109,30 @@ public BrushPanelViewModel(IShell shell, IEventAggregator eventAggregator, IIcon
IconDescriptorManager = iconDescriptorManager;
IconDescriptor = iconDescriptorManager.GetDescriptor();

IIconDescriptor<IGlyphComponent> iconDescriptor = iconDescriptorManager.GetDescriptor<IGlyphComponent>();
IIconDescriptor defaultIconDescriptor = iconDescriptorManager.GetDescriptor();
IIconDescriptor<IGlyphData> dataIconDescriptor = iconDescriptorManager.GetDescriptor<IGlyphData>();
IIconDescriptor<IGlyphComponent> componentIconDescriptor = iconDescriptorManager.GetDescriptor<IGlyphComponent>();

_dataTreeItemBuilder = new TreeViewItemModelBuilder<IGlyphData>()
.DisplayName(x => x.DisplayName, nameof(IGlyphData.DisplayName))
.ChildrenSource(x => new EnumerableReadOnlyObservableList<object>(x.Children), nameof(IGlyphData.Children))
.IconDescription(x => iconDescriptor.GetIcon(x.BindedObject));
.ChildrenSource(x => new CompositeReadOnlyObservableList<object>
(
new EnumerableReadOnlyObservableList<object>(x.Children),
new EnumerableReadOnlyObservableList<object>(x.ChildrenSources)
), x => ObservableHelpers.OnPropertyChanged(x as INotifyPropertyChanged, nameof(IGlyphData.Children), nameof(IGlyphData.ChildrenSources)))
.IconDescription(dataIconDescriptor.GetIcon);

_childrenSourceItemBuilder = new TreeViewItemModelBuilder<IReadOnlyObservableCollection<IGlyphData>>()
.DisplayName(x => x.ToString())
.FontWeight(_ => FontWeights.Bold)
.ChildrenSource(x => new EnumerableReadOnlyObservableList<object>(x))
.IconDescription(defaultIconDescriptor.GetIcon)
.IsHeader(_ => true);

_componentTreeItemBuilder = new TreeViewItemModelBuilder<IGlyphComponent>()
.DisplayName(x => x.Name, nameof(IGlyphComponent.Name))
.ChildrenSource(x => new EnumerableReadOnlyObservableList<object>(x.Components), nameof(IGlyphComponent.Components))
.IconDescription(x => iconDescriptor.GetIcon(x));
.IconDescription(componentIconDescriptor.GetIcon);

SelectBrushCommand = new RelayCommand(OnSelectBrush);
SelectPaintCommand = new RelayCommand(OnSelectPaint);
Expand Down Expand Up @@ -180,6 +196,8 @@ ITreeViewItemModel ITreeContext.CreateTreeItemModel(object model, ICollectionSyn
{
case IGlyphData data:
return _dataTreeItemBuilder.Build(data, synchronizerConfiguration);
case IReadOnlyObservableCollection<IGlyphData> childrenSource:
return _childrenSourceItemBuilder.Build(childrenSource, synchronizerConfiguration);
case IGlyphComponent component:
return _componentTreeItemBuilder.Build(component, synchronizerConfiguration);
default:
Expand Down
48 changes: 36 additions & 12 deletions Modules/Calame.DataModelTree/ViewModels/DataModelTreeViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using Calame.DocumentContexts;
using Calame.Icons;
using Calame.UserControls;
Expand All @@ -23,7 +26,8 @@ public sealed class DataModelTreeViewModel : CalameTool<IDocumentContext<IRootDa
public IIconDescriptor IconDescriptor { get; }

private ISelectionContext<IGlyphData> _selectionContext;
private readonly TreeViewItemModelBuilder<IGlyphCreator> _treeItemBuilder;
private readonly TreeViewItemModelBuilder<IGlyphData> _dataItemBuilder;
private readonly TreeViewItemModelBuilder<IReadOnlyObservableCollection<IGlyphData>> _childrenSourceItemBuilder;

private IRootDataContext _rootDataContext;
public IRootDataContext RootDataContext
Expand All @@ -32,17 +36,17 @@ public IRootDataContext RootDataContext
private set => SetValue(ref _rootDataContext, value);
}

private IGlyphData _selection;
public IGlyphData Selection
private object _selection;
public object Selection
{
get => _selection;
set
{
if (!SetValue(ref _selection, value))
return;

if (_selection != null)
_selectionContext.SelectAsync(_selection).Wait();
if (_selection is IGlyphData data)
_selectionContext.SelectAsync(data).Wait();
}
}

Expand All @@ -57,12 +61,24 @@ public DataModelTreeViewModel(IShell shell, IEventAggregator eventAggregator, II
IconProvider = iconProvider;
IconDescriptor = iconDescriptorManager.GetDescriptor();

IIconDescriptor<IGlyphData> iconDescriptor = iconDescriptorManager.GetDescriptor<IGlyphData>();

_treeItemBuilder = new TreeViewItemModelBuilder<IGlyphCreator>()
.DisplayName(x => x.DisplayName, nameof(IGlyphCreator.DisplayName))
.ChildrenSource(x => new EnumerableReadOnlyObservableList<object>(x.Children), nameof(IGlyphCreator.Children))
.IconDescription(x => iconDescriptor.GetIcon(x));
IIconDescriptor defaultIconDescriptor = iconDescriptorManager.GetDescriptor();
IIconDescriptor<IGlyphData> dataIconDescriptor = iconDescriptorManager.GetDescriptor<IGlyphData>();

_dataItemBuilder = new TreeViewItemModelBuilder<IGlyphData>()
.DisplayName(x => x.DisplayName, nameof(IGlyphData.DisplayName))
.ChildrenSource(x => new CompositeReadOnlyObservableList<object>
(
new EnumerableReadOnlyObservableList<object>(x.Children),
new EnumerableReadOnlyObservableList<object>(x.ChildrenSources)
), x => ObservableHelpers.OnPropertyChanged(x as INotifyPropertyChanged, nameof(IGlyphData.Children), nameof(IGlyphData.ChildrenSources)))
.IconDescription(x => dataIconDescriptor.GetIcon(x));

_childrenSourceItemBuilder = new TreeViewItemModelBuilder<IReadOnlyObservableCollection<IGlyphData>>()
.DisplayName(x => x.ToString())
.FontWeight(_ => FontWeights.Bold)
.ChildrenSource(x => new EnumerableReadOnlyObservableList<object>(x))
.IconDescription(x => defaultIconDescriptor.GetIcon(x))
.IsHeader(_ => true);
}

protected override Task OnDocumentActivated(IDocumentContext<IRootDataContext> activeDocument)
Expand Down Expand Up @@ -93,7 +109,15 @@ Task IHandle<ISelectionSpread<IGlyphData>>.HandleAsync(ISelectionSpread<IGlyphDa

ITreeViewItemModel ITreeContext.CreateTreeItemModel(object data, ICollectionSynchronizerConfiguration<object, ITreeViewItemModel> synchronizerConfiguration)
{
return _treeItemBuilder.Build((IGlyphCreator)data, synchronizerConfiguration);
switch (data)
{
case IGlyphData glyphData:
return _dataItemBuilder.Build(glyphData, synchronizerConfiguration);
case IReadOnlyObservableCollection<IGlyphData> childrenSource:
return _childrenSourceItemBuilder.Build(childrenSource, synchronizerConfiguration);
default:
throw new NotSupportedException();
}
}

public bool DisableChildrenIfParentDisabled => false;
Expand Down

0 comments on commit a3ee0de

Please sign in to comment.