FocusedMessageEventsRange GetFocusedMessageEqualRange(IStateInspectorOutputsGroup forGroup) { FocusedMessageEventsRange ret; if (focusedMessagePositionsCache.TryGetValue(forGroup, out ret)) { return(ret); } var equalRange = forGroup.Events.CalcFocusedMessageEqualRange(GetFocusedMessageInfo()); ret = new FocusedMessageEventsRange(GetFocusedMessageInfo(), equalRange); focusedMessagePositionsCache.Add(forGroup, ret); return(ret); }
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); }