void SetElementExpanded(ILiveElement element, bool expand) { var expandState = _expandMap.GetOrCreateValue(element); expandState.IsExpanded = expand; _expandToggled.OnNext(Unit.Default); }
public static IEnumerable <ILiveElement> DescendantsAndSelf(this ILiveElement element) { yield return(element); foreach (var descendant in element.Children.Value.SelectMany(DescendantsAndSelf)) { yield return(descendant); } }
bool GetElementExpanded(ILiveElement element, bool fallback) { ElementExpandState expandState; if (_expandMap.TryGetValue(element, out expandState)) { return(expandState.IsExpanded); } return(fallback); }
public void Update( ILiveElement element, int depth, int rowOffset, int expandedDescendantCount, bool expandToggleEnabled, bool isExpanded, bool isSelected, bool isAncestorSelected, bool isDescendantSelected) { _element.OnNextDistinct(Optional.Some(element)); _rowOffset.OnNextDistinct(rowOffset); _expandedDescendantCount.OnNextDistinct(expandedDescendantCount); _depth.OnNextDistinct(depth); _isExpanded.OnNextDistinct(isExpanded); _expandToggleEnabled.OnNextDistinct(expandToggleEnabled); _isSelected.OnNextDistinct(isSelected); _isAncestorSelected.OnNextDistinct(isAncestorSelected); _isDescendantSelected = isDescendantSelected; }
static ILiveElement[] GetSelectionPath(ILiveElement root, Optional <ILiveElement> selectedElement) { if (!selectedElement.HasValue) { return new ILiveElement[] { } } ; // First we count depth and see if selection is descendant of our root var selected = selectedElement.Value; var current = selected; int depth = 0; while (current != root) { var liveParent = current.Parent as ILiveElement; if (liveParent == null) { return(new ILiveElement[] { }); } depth++; current = liveParent; } // Then we walk down again and build the selection array var selectionPath = new ILiveElement[depth + 1]; current = selected; do { selectionPath[depth] = current; current = current.Parent as ILiveElement; } while (depth-- > 0); return(selectionPath); } }
State ScanElementTree( ILiveElement root, int visibleRowCount, int visibleRowOffset, Optional <ILiveElement> selectedElement, Optional <ILiveElement> previewElement) { // Update visible rows ake sure we have enough var updates = new Dictionary <ILiveElement, Action <RowModel> >(); var allExpandedElements = new List <ILiveElement>(_allExpandedElements.Count * 2); var selectedElementRowOffset = Optional.None <int>(); var previewElementRowOffset = Optional.None <int>(); ScanElementTree( treeModel: this._tree, element: root, updates: updates, allExpandedElements: allExpandedElements, visibleRowCount: visibleRowCount, visibleRowOffset: visibleRowOffset, depth: 0, selectionPath: GetSelectionPath(root, selectedElement), previewElement: previewElement, isAncestorSelected: false, selectedElementRowOffset: ref selectedElementRowOffset, previewElementRowOffset: ref previewElementRowOffset); return(new State( _tree, VisibleRows, allExpandedElements.Count, visibleRows => UpdateRows(visibleRows, updates), selectedElementRowOffset, visibleRowOffset, visibleRowCount, allExpandedElements)); }
Optional <Action> GetDropAction(ILiveElement thisElement, DropPosition position, object dragged) { var draggedElement = dragged as ILiveElement; var sourceFragment = dragged as SourceFragment; var bytes = dragged as byte[]; Func <SourceFragment> cut; if (draggedElement != null) { var node = thisElement; while (node != null) { if (node.Equals(draggedElement)) { return(Optional.None()); } node = node.Parent as ILiveElement; } cut = () => draggedElement.Cut().Result; } else if (bytes != null) { cut = () => SourceFragment.FromBytes(bytes); } else if (sourceFragment != null) { cut = () => sourceFragment; } else { return(Optional.None()); } switch (position) { case DropPosition.Inside: if (!_isExpanded.Value) { return((Action)( () => { var src = cut(); var element = thisElement.Paste(src); _tree._context.Select(element); })); } break; case DropPosition.After: case DropPosition.Before: if (_depth.Value > 0) { return((Action)(() => { var src = cut(); var element = position == DropPosition.Before ? thisElement.PasteBefore(src) : thisElement.PasteAfter(src); _tree._context.Select(element); })); } break; } return(Optional.None()); }
static bool CanExpand(ILiveElement element, int depth) { return(element.Children.Value.Any() && (depth == 0 || !element.UxClass().Value.HasValue)); }
/// <summary> /// Walks through all expanded elements of tree, adding actions to updates for pending row updates. /// Returns index of selected element /// </summary> static void ScanElementTree( TreeViewModel treeModel, ILiveElement element, Dictionary <ILiveElement, Action <RowModel> > updates, List <ILiveElement> allExpandedElements, int visibleRowCount, int visibleRowOffset, int depth, ILiveElement[] selectionPath, Optional <ILiveElement> previewElement, bool isAncestorSelected, ref Optional <int> selectedElementRowOffset, ref Optional <int> previewElementRowOffset) { var rowOffset = allExpandedElements.Count; allExpandedElements.Add(element); // A node with children can expand, unless it has a "ux:Class" attribute var canExpand = CanExpand(element, depth); // We expand up to 2 levels by default var expandByDefault = depth < 2; // Check if this element is an ancestor of selection var isDescendantSelected = depth < (selectionPath.Length - 1) && selectionPath[depth].Equals(element); // This is the selected element when we're at the end of the selection path var isSelected = depth == (selectionPath.Length - 1) && selectionPath[depth].Equals(element); var isExpanded = canExpand && (isDescendantSelected || treeModel.GetElementExpanded(element, expandByDefault)); if (previewElement.Select(pe => pe == element).Or(false)) { previewElementRowOffset = rowOffset; } if (isSelected) { selectedElementRowOffset = rowOffset; } var children = element.Children.Value; if (isExpanded) { foreach (var child in children) { ScanElementTree( treeModel: treeModel, element: child, updates: updates, allExpandedElements: allExpandedElements, visibleRowCount: visibleRowCount, visibleRowOffset: visibleRowOffset, depth: depth + 1, selectionPath: selectionPath, previewElement: previewElement, isAncestorSelected: isSelected | isAncestorSelected, selectedElementRowOffset: ref selectedElementRowOffset, previewElementRowOffset: ref previewElementRowOffset); } } var lastDescendantRowOffset = allExpandedElements.Count - 1; if ((rowOffset >= visibleRowOffset && rowOffset < visibleRowOffset + visibleRowCount) || (rowOffset < visibleRowOffset && lastDescendantRowOffset >= visibleRowOffset)) { updates[element] = rowModel => rowModel.Update( element: element, depth: depth, rowOffset: rowOffset, expandedDescendantCount: lastDescendantRowOffset - rowOffset, expandToggleEnabled: depth > 0 && canExpand, // Don't allow collapse of root isExpanded: isExpanded, isSelected: isSelected, isAncestorSelected: isAncestorSelected, isDescendantSelected: isDescendantSelected); } }
public static IBehaviorProperty <Optional <string> > UxClass(this ILiveElement element) { return(element["ux:Class"]); }