예제 #1
0
        void IView.SetViewModel(IViewModel viewModel)
        {
            this.viewModel = viewModel;

            var itemsUpdater = Updaters.Create(
                () => viewModel.Items,
                items =>
            {
                using (new ScopedGuard(
                           () => {
                    dropDownPanel.SuspendLayout();
                    updateLock = true;
                },
                           () => {
                    dropDownPanel.ResumeLayout();
                    updateLock = false;
                }
                           ))
                {
                    UpdateToolStripControls(mainToolStripControls, items.FirstOrDefault());

                    var existingControls = dropDownPanel.Controls.OfType <ExtendedToolStrip>().ToList();

                    int idx = 0;
                    foreach (var item in items)
                    {
                        var row = existingControls.LastOrDefault();
                        if (row != null)
                        {
                            existingControls.RemoveAt(existingControls.Count - 1);
                        }
                        else
                        {
                            row = new ExtendedToolStrip()
                            {
                                GripStyle        = ToolStripGripStyle.Hidden,
                                ImageScalingSize = mainToolStrip.ImageScalingSize,
                                Font             = mainToolStrip.Font,
                                TabStop          = true,
                            };
                            row.Tag = AddToolStripControls(row);
                            dropDownPanel.Controls.Add(row);
                            dropDownPanel.Controls.SetChildIndex(row, 0);
                        }

                        var ctrls = (ToolStripControls)row.Tag;
                        ctrls.dropdownBtnShowsList = (idx == 0) ? false : new bool?();
                        UpdateToolStripControls(ctrls, item);

                        ++idx;
                    }

                    existingControls.ForEach(c => c.Dispose());

                    UpdateToolStripTextSizes();
                }
            }
                );

            viewModel.ChangeNotification.CreateSubscription(() =>
            {
                itemsUpdater();
            });
        }
예제 #2
0
        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);
        }
예제 #3
0
        void IView.SetViewModel(IViewModel viewModel)
        {
            this.viewModel = viewModel;

            var prototypeStringFormat = (StringFormat)StringFormat.GenericDefault.Clone();

            prototypeStringFormat.SetTabStops(0, new float[] { 20 });
            prototypeStringFormat.FormatFlags |=
                StringFormatFlags.MeasureTrailingSpaces |
                StringFormatFlags.NoFontFallback;                 // this is to treat \0002 and \0003 as regular characters

            graphicsResources = new GraphicsResources(viewModel,
                                                      fontData => new LJD.Font(GetFontFamily(fontData.Name).Name, ToFontEmSize(fontData.Size)),
                                                      textFormat: new LJD.StringFormat(prototypeStringFormat),
                                                      (error: new LJD.Image(Properties.Resources.ErrorLogSeverity),
                                                       warn: new LJD.Image(Properties.Resources.WarnLogSeverity),
                                                       bookmark: new LJD.Image(Properties.Resources.Bookmark),
                                                       focusedMark: new LJD.Image(Properties.Resources.FocusedMsg)),
                                                      () => new LJD.Graphics(this.CreateGraphics(), ownsGraphics: true)
                                                      );

            viewDrawing = new ViewDrawing(
                viewModel,
                graphicsResources,
                dpiScale: UIUtils.Dpi.Scale(1f),
                scrollPosXSelector: () => scrollPosXCache,
                viewWidthSelector: () => viewWidthCache
                );

            viewWidthCache = this.ClientRectangle.Width;

            var viewUpdater = Updaters.Create(
                () => viewModel.ViewLines,
                () => viewModel.FocusedMessageMark,
                (_1, _2) =>
            {
                Invalidate();
            }
                );
            var vScrollerUpdater = Updaters.Create(
                () => viewModel.VerticalScrollerPosition,
                value =>
            {
                scrollBarsInfo.scrollSize.Height = value != null ? ScrollBarsInfo.virtualVScrollSize : 0;
                SetScrollPos(posY: (int)(value.GetValueOrDefault() * (double)(ScrollBarsInfo.virtualVScrollSize - ClientRectangle.Height + 1)));
            }
                );
            var emptyViewMessageUpdater = Updaters.Create(
                () => viewModel.EmptyViewMessage,
                value =>
            {
                if (emptyMessagesCollectionMessage == null)
                {
                    Controls.Add(emptyMessagesCollectionMessage = new EmptyMessagesCollectionMessage {
                        Dock = DockStyle.Fill
                    });
                }
                emptyMessagesCollectionMessage.Visible = value != null;
                emptyMessagesCollectionMessage.SetMessage(value ?? "");
            }
                );

            viewModel.ChangeNotification.CreateSubscription(() =>
            {
                viewUpdater();
                vScrollerUpdater();
                emptyViewMessageUpdater();
            });
        }
        void IView.SetViewModel(IViewModel viewModel)
        {
            this.viewModel = viewModel;

            this.Window.EnsureCreated();

            treeViewController.OnExpand     = viewModel.OnExpandNode;
            treeViewController.OnCollapse   = viewModel.OnCollapseNode;
            treeViewController.OnSelect     = viewModel.OnSelect;
            treeViewController.OnCreateView = (col, node) => {
                TreeNodeView view = (TreeNodeView)treeView.MakeView("view", this);
                if (view == null)
                {
                    view = new TreeNodeView {
                        owner      = this,
                        Identifier = "view",
                        Menu       = new NSMenu {
                            Delegate = GetContextMenuDelegate()
                        }
                    }
                }
                ;
                view.Update(node);
                return(view);
            };
            treeViewController.OnCreateRowView = (node) => {
                TreeRowView view = (TreeRowView)treeView.MakeView("row", this);
                if (view == null)
                {
                    view = new TreeRowView {
                        owner      = this,
                        Identifier = "row"
                    }
                }
                ;
                view.Update(node);
                return(view);
            };
            treeViewController.OnUpdateRowView = (rowView, node) => {
                ((TreeRowView)rowView).Update(node);
            };


            stateHistoryController.OnSelect     = items => viewModel.OnChangeHistoryChangeSelection(items);
            stateHistoryController.OnCreateView = (historyItem, tableColumn) => {
                NSTextField MakeTextField(string viewId)
                {
                    NSTextField view = (NSTextField)stateHistoryView.MakeView(viewId, this);

                    if (view == null)
                    {
                        view = new NSTextField()
                        {
                            Identifier      = viewId,
                            Editable        = false,
                            Selectable      = false,
                            Bordered        = false,
                            BackgroundColor = NSColor.Clear
                        };
                        view.Cell.LineBreakMode = NSLineBreakMode.TruncatingTail;
                    }
                    return(view);
                }

                if (tableColumn == HistoryItemTimeColumn)
                {
                    var view = MakeTextField("timeView");
                    view.StringValue = historyItem.Time;
                    return(view);
                }
                else if (tableColumn == HistoryItemTextColumn)
                {
                    var view = MakeTextField("messageView");
                    view.StringValue = historyItem.Message;
                    return(view);
                }

                return(null);
            };
            stateHistoryController.OnUpdateView = (item, tableColumn, view, oldItem) => {
                if (tableColumn == HistoryItemTimeColumn)
                {
                    ((NSTextField)view).StringValue = item.Time;
                }
                else if (tableColumn == HistoryItemTextColumn)
                {
                    ((NSTextField)view).StringValue = item.Message;
                }
            };

            stateHistoryController.OnCreateRowView = (item, rowIndex) =>
            {
                return(new StateHistoryTableRowView {
                    owner = this, row = rowIndex, items = viewModel.ChangeHistoryItems
                });
            };


            var updateTree = Updaters.Create(
                () => viewModel.ObjectsTreeRoot,
                treeViewController.Update
                );

            var invalidateTree = Updaters.Create(
                () => viewModel.PaintNode,
                () => viewModel.ColorTheme,
                (_1, _2) => InvalidateTree()
                );

            var updateStateHistory = Updaters.Create(
                () => viewModel.ChangeHistoryItems,
                items =>
            {
                stateHistoryController.Update(items);
                UpdateStateHistoryTimeColumn(items);
            }
                );

            var invalidateStateHistory = Updaters.Create(
                () => viewModel.IsChangeHistoryItemBookmarked,
                () => viewModel.FocusedMessagePositionInChangeHistory,
                (_1, _2) => InvalidateStateHistoryTableView()
                );

            var updateProperties = Updaters.Create(
                () => viewModel.ObjectsProperties,
                properties => {
                propsDataSource.data = properties;
                propertiesView.ReloadData();
            }
                );

            var updateCurrentTime = Updaters.Create(
                () => viewModel.CurrentTimeLabelText,
                timeValue => currentTimeLabel.StringValue = timeValue
                );

            viewModel.ChangeNotification.CreateSubscription(() => {
                updateTree();
                invalidateTree();
                updateStateHistory();
                invalidateStateHistory();
                updateProperties();
                updateCurrentTime();
            });
        }

        void IView.Show()
        {
            ShowInternal();
        }

        void IView.ScrollStateHistoryItemIntoView(int itemIndex)
        {
            var items = viewModel.ChangeHistoryItems;

            if (items.Count == 0)
            {
                return;
            }
            stateHistoryView.ScrollRowToVisible(RangeUtils.PutInRange(0, items.Count - 1, itemIndex));
        }

        void InvalidateTree()
        {
            treeView.NeedsDisplay = true;
            var rows = treeView.RowsInRect(treeView.VisibleRect());

            for (var r = 0; r < rows.Length; ++r)
            {
                var rv = treeView.GetRowView(r + rows.Location, false);
                if (rv != null)
                {
                    rv.NeedsDisplay = true;
                }
                var nv = treeView.GetView(0, r + rows.Location, false);
                if (nv != null)
                {
                    nv.NeedsDisplay = true;
                }
            }
        }

        void UpdateStateHistoryTimeColumn(IReadOnlyList <IStateHistoryItem> items)
        {
            var widestCell = items.Select(
                (item, idx) => (item, idx)
                ).MaxByKey(
                i => i.item.Time.Length
                );

            if (widestCell.item != null)
            {
                var cellView = (NSTextField)stateHistoryView.GetView(1, widestCell.idx, makeIfNecessary: true);
                cellView.SizeToFit();
                historyItemTimeColumn.Width = cellView.Frame.Width + 10;
            }
            else
            {
                historyItemTimeColumn.Width = 0;
            }
        }

        void Presenters.Postprocessing.IPostprocessorVisualizerPresenter.Show()
        {
            ShowInternal();
        }
        void IView.SetViewModel(IViewModel viewModel)
        {
            this.EnsureCreated();

            this.viewModel = viewModel;

            var fontSz = (NSFont.SystemFontSize + NSFont.SmallSystemFontSize) / 2f;

            this.resources = new Resources(
                viewModel,
                NSFont.SystemFontOfSize(NSFont.SystemFontSize).FamilyName,
                (float)fontSz)
            {
                BookmarkImage       = new LJD.Image(NSImage.ImageNamed("Bookmark.png")),
                FocusedMessageImage = new LJD.Image(NSImage.ImageNamed("FocusedMsgSlave.png")),
                FocusedMsgSlaveVert = new LJD.Image(NSImage.ImageNamed("FocusedMsgSlaveVert.png"))
            };

            this.drawingUtils = new DrawingUtils(viewModel, resources);

            var notificationsIconUpdater = Updaters.Create(
                () => viewModel.IsNotificationsIconVisibile,
                value => activeNotificationsButton.Hidden = !value
                );

            var updateCurrentArrowControls = Updaters.Create(
                () => viewModel.CurrentArrowInfo,
                value => {
                arrowNameTextField.StringValue = value.Caption;
                arrowDetailsLink.StringValue   = value.DescriptionText;
                arrowDetailsLink.Links         = (value.DescriptionLinks ?? Enumerable.Empty <Tuple <object, int, int> >())
                                                 .Select(l => new NSLinkLabel.Link(l.Item2, l.Item3, l.Item1)).ToArray();
            }
                );

            var updateCollapseResponsesCheckbox = Updaters.Create(
                () => viewModel.IsCollapseResponsesChecked,
                value => collapseResponsesCheckbox.State = value ? NSCellStateValue.On : NSCellStateValue.Off
                );

            var updateCollapseRoleInstancesCheckbox = Updaters.Create(
                () => viewModel.IsCollapseRoleInstancesChecked,
                value => collapseRoleInstancesCheckbox.State = value ? NSCellStateValue.On : NSCellStateValue.Off);

            var scrollBarsUpdater = Updaters.Create(
                () => viewModel.ScrollInfo,
                value => UpdateScrollBars(value.vMax, value.vChange, value.vValue,
                                          value.hMax, value.hChange, value.hValue)
                );

            var invalidateViews = Updaters.Create(
                () => viewModel.RolesDrawInfo,
                () => viewModel.ArrowsDrawInfo,
                (_1, _2) => {
                rolesCaptionsView.NeedsDisplay = true;
                arrowsView.NeedsDisplay        = true;
                leftPanelView.NeedsDisplay     = true;
            }
                );

            viewModel.ChangeNotification.CreateSubscription(() => {
                notificationsIconUpdater();
                updateCurrentArrowControls();
                updateCollapseResponsesCheckbox();
                updateCollapseRoleInstancesCheckbox();
                scrollBarsUpdater();
                invalidateViews();
            });
        }
예제 #6
0
        public override void AwakeFromNib()
        {
            base.AwakeFromNib();

            Window.owner = this;

            var sysFont = NSFont.SystemFontOfSize(NSFont.SystemFontSize);

            res = new Lazy <GraphicsResources> (() => new GraphicsResources(
                                                    model,
                                                    sysFont.FamilyName,
                                                    (float)NSFont.SystemFontSize,
                                                    (float)NSFont.SmallSystemFontSize,
                                                    (float)NSFont.SmallSystemFontSize,
                                                    new LJD.Image(NSImage.ImageNamed("UserAction.png")),
                                                    new LJD.Image(NSImage.ImageNamed("APICall.png")),
                                                    new LJD.Image(NSImage.ImageNamed("TimelineBookmark.png")),
                                                    new LJD.Image(NSImage.ImageNamed("FocusedMsgSlaveVert.png")),
                                                    1f,
                                                    new LJD.Brush(Color.FromArgb(235, 235, 235))
                                                    ));
            drawing = new Lazy <ControlDrawing> (() => new ControlDrawing(res.Value));

            activitiesView.PostsFrameChangedNotifications = true;
            captionsView.PostsFrameChangedNotifications   = true;
            NSNotificationCenter.DefaultCenter.AddObserver(NSView.FrameChangedNotification,
                                                           ns => { UpdateVertScroller(); }, activitiesView);

            PlaceToastNotificationsView(toastNotifications.View, activitiesView);

            activitiesView.BackgroundColor     = NSColor.TextBackground;
            activitiesView.CanBeFirstResponder = true;
            activitiesView.OnPaint             = DrawActivitiesView;
            activitiesView.OnScrollWheel       = ActivitiesViewScrollWheel;
            activitiesView.OnMagnify           = ActivitiesViewMagnify;
            activitiesView.OnMouseDown         =
                e => model.OnMouseDown(new HitTestToken(activitiesView, e), GetModifiers(e), e.ClickCount == 2);
            activitiesView.OnMouseUp =
                e => model.OnMouseUp(new HitTestToken(activitiesView, e));
            activitiesView.OnMouseMove = e => {
                SetActivitiesCursor(e);
                SetActivitiesToolTip(e);
                model.OnMouseMove(new HitTestToken(activitiesView, e), GetModifiers(e));
            };
            activitiesView.OnMouseLeave   = e => NSCursor.ArrowCursor.Set();
            activitiesView.OnMouseDragged = activitiesView.OnMouseMove;

            captionsView.BackgroundColor     = NSColor.TextBackground;
            captionsView.CanBeFirstResponder = true;
            captionsView.OnPaint             = DrawCaptionsView;
            captionsView.OnMouseDown         =
                e => model.OnMouseDown(new HitTestToken(captionsView, e), GetModifiers(e), e.ClickCount == 2);
            captionsView.OnMouseUp =
                e => model.OnMouseUp(new HitTestToken(captionsView, e));

            activityDetailsLabel.BackgroundColor   = NSColor.TextBackground;
            activityDetailsLabel.LinkClicked       = (s, e) => model.OnActivityTriggerClicked(e.Link.Tag);
            activityLogSourceLabel.BackgroundColor = NSColor.TextBackground;
            activityLogSourceLabel.LinkClicked     = (s, e) => model.OnActivitySourceLinkClicked(e.Link.Tag);

            navigatorView.OnPaint     = DrawNavigationPanel;
            navigatorView.OnMouseDown =
                e => model.OnMouseDown(new HitTestToken(navigatorView, e), GetModifiers(e), e.ClickCount == 2);
            navigatorView.OnMouseUp =
                e => model.OnMouseUp(new HitTestToken(navigatorView, e));
            navigatorView.OnMouseMove = (e) => {
                SetNavigationCursor(e);
                model.OnMouseMove(new HitTestToken(navigatorView, e), GetModifiers(e));
            };
            navigatorView.OnMouseDragged = navigatorView.OnMouseMove;
            navigatorView.OnMouseLeave   = e => NSCursor.ArrowCursor.Set();

            vertScroller.Action = new Selector("OnVertScrollChanged");
            vertScroller.Target = this;

            tagsListController.View.MoveToPlaceholder(tagsSelectorPlacefolder);
            quickSearchTextBox.View.MoveToPlaceholder(searchTextBoxPlaceholder);

            Window.InitialFirstResponder = activitiesView;

            var updateNotificationsButton = Updaters.Create(() => model.NotificationsIconVisibile, v => activeNotificationsButton.Hidden = !v);
            var updateNoContentMessage    = Updaters.Create(() => model.NoContentMessageVisibile, SetNoContentMessageVisibility);
            var updateVertScroller        = Updaters.Create(() => model.ActivitiesCount, _ => UpdateVertScroller());
            var updateCurrentActivityInfo = Updaters.Create(() => model.CurrentActivity, UpdateCurrentActivityControls);

            changeNotification.CreateSubscription(() => {
                updateNotificationsButton();
                updateNoContentMessage();
                updateVertScroller();
                updateCurrentActivityInfo();
            });

            Window.WillClose += (s, e) => model.OnWindowHidden();
        }