public VisualizerNode ReplaceChild(VisualizerNode old, VisualizerNode newChild, bool ensureExpanded) { var copy = new VisualizerNode(obj, ImmutableList.CreateRange(children.Select(c => c == old ? newChild : c)), ensureExpanded ? true : expanded, selected, level, annotationsMap); old.parent = null; return(parent == null ? copy : parent.ReplaceChild(this, copy, ensureExpanded)); }
NodeInfo CreateViewNode(IView view, NodesCollectionInfo collectionToAddViewNode, IInspectedObject modelNode, int level, List <NodeInfo> nodesToCollapse) { string nodeText = modelNode.DisplayName; if (modelNode.Comment != "") { nodeText += " (" + modelNode.Comment + ")"; } bool createCollapsed = false; bool createLazilyLoaded = false; if (level < 5) { if (OnNodeCreated != null) { var args = new NodeCreatedEventArgs() { NodeObject = VisualizerNode.FromObject(modelNode) }; OnNodeCreated(this, args); createCollapsed = args.CreateCollapsed.GetValueOrDefault(createCollapsed); createLazilyLoaded = args.CreateLazilyLoaded.GetValueOrDefault(createLazilyLoaded); } if (createLazilyLoaded && !view.TreeSupportsLoadingOnExpansion) { createLazilyLoaded = false; } } var viewNode = view.CreateNode(nodeText, modelNode, collectionToAddViewNode); if (createLazilyLoaded) { view.CreateNode(lazyLoadTag, lazyLoadTag, viewNode.ChildrenNodesCollection); } else { foreach (var child in modelNode.Children) { CreateViewNode(view, viewNode.ChildrenNodesCollection, child, level + 1, nodesToCollapse); } } if (createCollapsed) { nodesToCollapse.Add(viewNode); } return(viewNode); }
static MessageTimestamp GetNodeTimestamp(VisualizerNode node) { var obj = (node as VisualizerNode)?.InspectedObject; StateInspectorEvent referenceEvt = null; if (obj != null) { referenceEvt = obj.StateChangeHistory.FirstOrDefault(); } if (referenceEvt != null) { return(referenceEvt.Trigger.Timestamp.Adjust(referenceEvt.Output.LogSource.TimeOffsets)); } return(MessageTimestamp.MaxValue); }
public VisualizerNode Follow(VisualizerNode rootNode) { VisualizerNode ret = null; bool inspectingRoots = true; foreach (var segment in path) { VisualizerNode found = ( from n in inspectingRoots ? rootNode.Children : ret.Children let obj = n.InspectedObject where obj != null where inspectingRoots ? (obj == segment && obj.Owner.Key == outputsGroupKey) : (obj == segment) select n ).FirstOrDefault(); if (found == null) { return(null); } ret = found; inspectingRoots = false; } return(ret); }
static VisualizerNode MakeRootNode( IReadOnlyList <IStateInspectorOutputsGroup> groups, EventHandler <NodeCreatedEventArgs> nodeCreationHandler, ImmutableDictionary <ILogSource, string> annotationsMap, VisualizerNode existingRoot ) { var existingRoots = existingRoot.Children.ToLookup(c => c.InspectedObject); var children = ImmutableList.CreateRange( groups.SelectMany( group => group.Roots.Select(rootObj => { var existingNode = existingRoots[rootObj].FirstOrDefault(); if (existingNode != null) { return(existingNode.SetAnnotationsMap(annotationsMap)); } var newNode = MakeVisualizerNode(rootObj, 1, annotationsMap); newNode.SetInitialProps(nodeCreationHandler); // call handler on second phase when all children and parents are initiated return(newNode); }) ) ); children = children.Sort((n1, n2) => MessageTimestamp.Compare(GetNodeTimestamp(n1), GetNodeTimestamp(n2))); var result = new VisualizerNode(null, children, true, false, 0, annotationsMap); if (!result.HasSelectedNodes && result.Children.Count > 0) { result = result.Children[0].Select(true); } return(result); }
bool IPresenter.TrySelectObject(ILogSource source, TextLogEventTrigger creationTrigger, Func <IVisualizerNode, int> disambiguationFunction) { EnsureTreeView(); Func <IInspectedObject, bool> predecate = obj => { return(obj.Owner.Outputs.Any(o => o.LogSource == source) && obj.StateChangeHistory.Any(change => change.Trigger.CompareTo(creationTrigger) == 0)); }; var candidates = EnumRoots().SelectMany(EnumTree).Where(predecate).ToList(); if (candidates.Count > 0) { IInspectedObject obj; if (candidates.Count == 1 || disambiguationFunction == null) { obj = candidates[0]; } else { obj = candidates .Select(c => new { Obj = c, Rating = disambiguationFunction(VisualizerNode.FromObject(c)) }) .OrderByDescending(x => x.Rating) .First().Obj; } var n = FindOrCreateNode(obj); if (n != null) { view.SelectedNodes = new[] { n.Value }; view.ScrollSelectedNodesInView(); return(true); } } return(false); }
public InspectedObjectPath(VisualizerNode node) : this(node?.InspectedObject) { }
public StateInspectorPresenter( IView view, IStateInspectorVisualizerModel model, IUserNamesProvider shortNames, ILogSourcesManager logSources, LoadedMessages.IPresenter loadedMessagesPresenter, IBookmarks bookmarks, IModelThreads threads, IPresentersFacade presentersFacade, IClipboardAccess clipboardAccess, SourcesManager.IPresenter sourcesManagerPresenter, IColorTheme theme, IChangeNotification changeNotification ) { this.view = view; this.model = model; this.shortNames = shortNames; this.threads = threads; this.presentersFacade = presentersFacade; this.bookmarks = bookmarks; this.clipboardAccess = clipboardAccess; this.sourcesManagerPresenter = sourcesManagerPresenter; this.loadedMessagesPresenter = loadedMessagesPresenter; this.theme = theme; this.changeNotification = changeNotification.CreateChainedChangeNotification(initiallyActive: false); var annotationsVersion = 0; logSources.OnLogSourceAnnotationChanged += (sender, e) => { annotationsVersion++; changeNotification.Post(); }; var getAnnotationsMap = Selectors.Create( () => logSources.Items, () => annotationsVersion, (sources, _) => sources .Where(s => !s.IsDisposed && !string.IsNullOrEmpty(s.Annotation)) .ToImmutableDictionary(s => s, s => s.Annotation) ); VisualizerNode rootNode = new VisualizerNode(null, ImmutableList <VisualizerNode> .Empty, true, false, 0, ImmutableDictionary <ILogSource, string> .Empty); var updateRoot = Updaters.Create( () => model.Groups, getAnnotationsMap, (groups, annotationsMap) => rootNode = MakeRootNode(groups, OnNodeCreated, annotationsMap, rootNode) ); this.getRootNode = () => { updateRoot(); return(rootNode); }; this.updateRootNode = reducer => { var oldRoot = getRootNode(); var newRoot = reducer(oldRoot); if (oldRoot != newRoot) { rootNode = newRoot; changeNotification.Post(); } }; this.getSelectedNodes = Selectors.Create( getRootNode, (root) => { var result = ImmutableArray.CreateBuilder <VisualizerNode>(); void traverse(VisualizerNode n) { if (!n.HasSelectedNodes) { return; } if (n.IsSelected) { result.Add(n); } foreach (var c in n.Children) { traverse(c); } } traverse(root); return(result.ToImmutable()); } ); this.getSelectedInspectedObjects = Selectors.Create( getSelectedNodes, nodes => ImmutableArray.CreateRange(nodes.Select(n => n.InspectedObject)) ); this.getStateHistoryItems = Selectors.Create( getSelectedInspectedObjects, () => selectedHistoryEvents, MakeSelectedObjectHistory ); this.getIsHistoryItemBookmarked = Selectors.Create( () => bookmarks.Items, boormarksItems => { Predicate <IStateHistoryItem> result = (item) => { var change = (item as StateHistoryItem)?.Event; if (change == null || change.Output.LogSource.IsDisposed) { return(false); } var bmk = bookmarks.Factory.CreateBookmark( change.Trigger.Timestamp.Adjust(change.Output.LogSource.TimeOffsets), change.Output.LogSource.GetSafeConnectionId(), change.Trigger.StreamPosition, 0); var pos = boormarksItems.FindBookmark(bmk); return(pos.Item2 > pos.Item1); }; return(result); } ); this.getFocusedMessageInfo = () => loadedMessagesPresenter.LogViewerPresenter.FocusedMessage; this.getFocusedMessageEqualRange = Selectors.Create( getFocusedMessageInfo, focusedMessageInfo => { var cache = new Dictionary <IStateInspectorOutputsGroup, FocusedMessageEventsRange>(); Func <IStateInspectorOutputsGroup, FocusedMessageEventsRange> result = forGroup => { if (!cache.TryGetValue(forGroup, out FocusedMessageEventsRange eventsRange)) { eventsRange = new FocusedMessageEventsRange(focusedMessageInfo, forGroup.Events.CalcFocusedMessageEqualRange(focusedMessageInfo)); cache.Add(forGroup, eventsRange); } return(eventsRange); }; return(result); } ); this.getPaintNode = Selectors.Create( getFocusedMessageEqualRange, MakePaintNodeDelegate ); this.getFocusedMessagePositionInHistory = Selectors.Create( getStateHistoryItems, getFocusedMessageInfo, (changes, focusedMessage) => { return (focusedMessage == null ? null : new ListUtils.VirtualList <StateInspectorEvent>(changes.Length, i => changes[i].Event).CalcFocusedMessageEqualRange(focusedMessage)); } ); this.getCurrentTimeLabelText = Selectors.Create( getFocusedMessageInfo, focusedMsg => focusedMsg != null ? $"at {focusedMsg.Time}" : "" ); this.getCurrentProperties = Selectors.Create( getSelectedInspectedObjects, getFocusedMessageEqualRange, () => selectedProperty, MakeCurrentProperties ); this.getPropertyItems = Selectors.Create( getCurrentProperties, props => (IReadOnlyList <IPropertyListItem>)props.Cast <IPropertyListItem>().ToImmutableArray() ); this.getObjectsProperties = Selectors.Create( getCurrentProperties, props => (IReadOnlyList <KeyValuePair <string, object> >)props.Select(p => p.ToDataSourceItem()).ToImmutableArray() ); view.SetViewModel(this); }
public VisualizerNode Select(bool value) { var copy = new VisualizerNode(obj, children, expanded, value, level, annotationsMap); return(parent.ReplaceChild(this, copy, true)); }
public VisualizerNode Expand(bool value) { var copy = new VisualizerNode(obj, children, value, selected, level, annotationsMap); return(parent.ReplaceChild(this, copy, false)); }