public Timeline()
        {
            this.ContextMenuItems = new ObservableCollection <object>();
            this.ContextMenuItems.Add(ZoomInCommand);
            this.ContextMenuItems.Add(ZoomOutCommand);
            this.ContextMenuItems.Add(ZoomToAllCommand);
            this.ContextMenuItems.Add(ZoomToSelectionCommand);
            this.CommandBindings.Add(new CommandBinding(ZoomInCommand, OnZoomInExecuted, OnZoomInCanExecute));
            this.CommandBindings.Add(new CommandBinding(ZoomOutCommand, OnZoomOutExecuted, OnZoomOutCanExecute));
            this.CommandBindings.Add(new CommandBinding(ZoomToAllCommand, OnZoomToAllExecuted));
            this.CommandBindings.Add(new CommandBinding(ZoomToSelectionCommand, OnZoomToSelectionExecuted, OnZoomToSelectionCanExecute));
            this.CommandBindings.Add(new CommandBinding(ToggleScrollingCommand, OnToggleScrollingExecuted));
            this.swimlanes = new ObservableCollection <SwimlanePanel.SwimlaneDefinition>();
            this.swimlanes.CollectionChanged += OnSwimLaneCollectionChanged;
            this.timeAxis = new TimeAxis()
            {
                HorizontalAlignment = HorizontalAlignment.Stretch, MouseOverElement = this
            };
            this.timeAxis.SetBinding(TimeAxis.IsLiveProperty, new Binding {
                Source = this, Path = new PropertyPath(IsLiveProperty)
            });
            this.timeAxis.SetBinding(TimeAxis.ForegroundProperty, new Binding {
                Source = this, Path = new PropertyPath(ForegroundProperty)
            });
            this.timeAxis.SetBinding(TimeAxis.BackgroundProperty, new Binding {
                Source = this, Path = new PropertyPath(BackgroundProperty)
            });
            this.TimeAxis = this.timeAxis;

            this.MouseWheel           += OnMouseWheel;
            this.MouseLeftButtonDown  += OnMouseLeftButtonDown;
            this.MouseRightButtonDown += OnMouseRightButtonDown;
        }
        public SectionZoomManager(
			InputReference inputReference,
			TimeAxis timeAxis,
			IDoubleAxesGroupPool axesGroupPool,
			IDrawingAreaInfo drawingAreaInfo,
			IOnlineMode onlineMode)
        {
            _timeAxis = timeAxis;
            _axesGroupPool = axesGroupPool;
            _drawingAreaInfo = drawingAreaInfo;

            _onlineMode = onlineMode;
            // TODO: abhängen
            _onlineMode.IsOnlineChanged += (s, e) =>
                {
                    if (_onlineMode.IsOnline)
                        IsActive = false;
                };

            InitializeComponent();

            // Preview-Event ist wichtig, damit alle anderen Elemente nicht informiert werden
            inputReference.InputElement.PreviewMouseLeftButtonDown += InputElement_PreviewMouseLeftButtonDown;
            MouseMove += this_MouseMove;
            MouseLeftButtonUp += this_MouseLeftButtonUp;
        }
Exemple #3
0
        public IEnumerable <TimeAxisItem> FilterTimeAxisItems(TimeAxis line, TimeAxisFilter filter)
        {
            if (filter == null || !filter.HasAnyFilters())
            {
                return(new List <TimeAxisItem>());
            }

            var items = line.GetItems();

            if (filter.MaxDate != null)
            {
                items = items.Where(x => x.EndTime <= filter.MaxDate);
            }
            if (filter.MinDate != null)
            {
                items = items.Where(x => x.StartTime >= filter.MinDate);
            }
            if (filter.MaxPage != null)
            {
                items = items.Where(x => x.MaxPage <= filter.MaxPage);
            }
            if (filter.MinPage != null)
            {
                items = items.Where(x => x.MinPage >= filter.MinPage);
            }

            return(items);
        }
        private void DrawGrid(DrawingContext drawingContext)
        {
            double bottom = this.ActualHeight;
            Rect   r      = new Rect(0, 0, this.ActualWidth, bottom);
            ulong  firstVisibleTick;
            ulong  lastVisibleTick;
            ulong  tickInterval;

            this.TimeAxis.GetTickInfo(out firstVisibleTick, out lastVisibleTick, out tickInterval);

            if (tickInterval == 0)
            {
                return;
            }

            double yFirstTic    = 0;
            double yTicInterval = 1;
            double yMax         = 100;

            if (this.SideBar != null)
            {
                this.SideBar.GetTickInfo(out yFirstTic, out yTicInterval, out yMax);
            }

            // Draw all tween grid lines before major grid lines
            if (xShowTween)
            {
                for (ulong x = firstVisibleTick + tickInterval / 2; x <= lastVisibleTick; x += tickInterval)
                {
                    double tx = Math.Floor(TimeAxis.TimeToScreen(x)) + 0.5;
                    drawingContext.DrawLine(gridPen, new Point(tx, r.Top), new Point(tx, r.Bottom));
                }
            }

            if (yShowTween)
            {
                for (double y = yFirstTic + yTicInterval / 2; y < yMax; y += yTicInterval)
                {
                    double ty = Math.Floor((bottom - 1) - SideBar.YToPixels(y)) + 0.5;
                    drawingContext.DrawLine(gridPen, new Point(0, ty), new Point(this.ActualWidth, ty));
                }
            }

            // Draw major grid lines
            for (ulong x = firstVisibleTick; x <= lastVisibleTick; x += tickInterval)
            {
                double tx = Math.Floor(TimeAxis.TimeToScreen(x)) + 0.5;
                drawingContext.DrawLine(gridPen, new Point(tx, r.Top), new Point(tx, r.Bottom));
            }

            if (this.SideBar != null)
            {
                for (double y = yFirstTic; y < yMax; y += yTicInterval)
                {
                    double ty = Math.Floor((bottom - 1) - SideBar.YToPixels(y)) + 0.5;
                    drawingContext.DrawLine(gridPen, new Point(0, ty), new Point(this.ActualWidth, ty));
                }
            }
        }
Exemple #5
0
        public TimeAxis CreateTimeAxis(User user, string title)
        {
            var entity = new TimeAxis(title);

            _authorityManager.AssignAllTo(user, entity);

            return(entity);
        }
        protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
        {
            IEventDataNode curHotChunk = null;
            double         mouseX      = e.GetPosition(this).X;
            ulong          tick        = TimeAxis.ScreenToTime(mouseX);

            // Look through the slicing markers first
            for (int i = 0; i < this.slicingMarkers.Length; i++)
            {
                var chunk = this.slicingMarkers[i];

                // Slicing markers are only a pixel wide, so make them selectable w/ padding
                if (chunk.Visible)
                {
                    var x = TimeAxis.TimeToScreen(chunk.StartTime);
                    if (mouseX > (x - 3) && mouseX < (x + 3))
                    {
                        curHotChunk = chunk;
                        break;
                    }
                }
            }

            if (curHotChunk == null)
            {
                for (int i = this.sortedNodes.Length - 1; i >= 0; i--)
                {
                    var chunk = this.sortedNodes[i];

                    if (chunk.Visible && (tick >= chunk.StartTime) && (tick < chunk.StartTime + chunk.Duration))
                    {
                        curHotChunk = chunk;
                        break;
                    }

                    // Marker events are drawn at special minimum width, so make them selectable w/ padding
                    if (chunk.Visible && chunk.Style == EventRenderStyle.ParentedMarker)
                    {
                        var x = TimeAxis.TimeToScreen(chunk.StartTime);
                        if (mouseX > (x - 3) && mouseX < (x + 3))
                        {
                            curHotChunk = chunk;
                            break;
                        }
                    }
                }
            }

            if (curHotChunk != hotChunk)
            {
                // Hot chunk has changed
                hotChunk = curHotChunk;
                UpdateToolTip();
                InvalidateVisual();
            }

            base.OnMouseMove(e);
        }
Exemple #7
0
        public bool HasAuthority(User user, TimeAxis line, params AuthorityType[] types)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            return(HasAuthority(user.Id, line, types));
        }
        public RippleLineChartText()
        {
            _chartConfig   = CreateNewChartConfig();
            _showOnlyGraph = false;

            _xAxis  = (TimeAxis)_chartConfig.Options.Scales.XAxes.First();
            _yAxis1 = (LinearCartesianAxis)_chartConfig.Options.Scales.YAxes[0];
            _yAxis2 = (LinearCartesianAxis)_chartConfig.Options.Scales.YAxes[1];
        }
Exemple #9
0
        public TimeAxis AssignAllTo(User user, TimeAxis line)
        {
            AssignTo(user, line, AuthorityType.View);
            AssignTo(user, line, AuthorityType.AddItem);
            AssignTo(user, line, AuthorityType.AuditItem);
            AssignTo(user, line, AuthorityType.DeleteItem);
            AssignTo(user, line, AuthorityType.EditItem);

            return(line);
        }
Exemple #10
0
        public OnlineMode(TimeAxis timeAxis)
        {
            _timeAxis = timeAxis;

            _onlineTimer = new DispatcherTimer
            {
                Interval = TimeSpan.FromSeconds(1),
                IsEnabled = false
            };
            _onlineTimer.Tick += (s, e) => UpdateOnlineTime();
        }
Exemple #11
0
        public TimeAxis AssignNo(User user, TimeAxis line, AuthorityType auth)
        {
            if (user == null || line == null)
            {
                throw new ArgumentNullException();
            }

            line.RemoveAuth(auth, user);
            user.RemoveAuth(auth);

            return(line);
        }
Exemple #12
0
 public void Remove()
 {
     if (mName != null)
     {
         TimeMgr.single.mMap.Remove(mName);
     }
     if (mParent == null)
     {
         return;
     }
     mParent.mChilds.Remove(this);
     mParent = null;
 }
Exemple #13
0
 public void SetParent(TimeAxis parent, float relativeTime = 0)
 {
     if (mParent != null)
     {
         mParent.mChilds.Remove(this);
     }
     mRelativeTime = relativeTime;
     mParent       = parent;
     if (mParent != null)
     {
         mParent.mChilds.Add(this);
     }
     Reset();
 }
        public TileLegendItemViewModel(
			TimeDoubleCurve curve,
			TimeAxis timeAxis)
        {
            _timeAxis = timeAxis;
            Curve = curve;
            //Curve.PropertyChanged += Curve_PropertyChanged;
            _curvePropChgObservable = Observable
                .FromEventPattern(Curve, "PropertyChanged")
                .Sample(TimeSpan.FromMilliseconds(100))
                .ObserveOn(SynchronizationContext.Current)
                .Subscribe(o => RefreshView());
            Curve.IsSelectedChanged += Curve_IsSelectedChanged;
        }
        public RulerViewModel(
			TimeAxis timeAxis,
			IStaticRulerManager rulerManager,
			int rulerIndex)
        {
            _timeAxis = timeAxis;
            _timeAxis.BoundsChanged += _timeAxis_BoundsChanged;
            _rulerIndex = rulerIndex;

            _rulerManager = rulerManager;
            _rulerManager.ReferenceRulerChanged += _rulerManager_ReferenceRulerChanged;

            DeleteCommand = new RelayCommand(Delete);
            GotoCommand = new RelayCommand(Goto);
        }
        double?DrawSlicingMarker(DrawingContext drawingContext, IEventDataNode slicingMarker, double?lastDrawnSlicingMarkerX)
        {
            var x = TimeAxis.TimeToScreen(slicingMarker.StartTime);

            if (x >= 0 && x <= this.ActualWidth)
            {
                if (!lastDrawnSlicingMarkerX.HasValue || (x > lastDrawnSlicingMarkerX.Value + 3))
                {
                    drawingContext.DrawLine(this.slicingMarkerPen, new Point(x, verticalMargin / 3), new Point(x, this.ActualHeight - verticalMargin + 2));
                    return(x);
                }
            }

            return(lastDrawnSlicingMarkerX);
        }
Exemple #17
0
        public TimeAxis GetTimeAxis(string name, bool create = false)
        {
            if (name == null)
            {
                return(null);
            }
            TimeAxis a = null;

            mMap.TryGetValue(name, out a);
            if (a == null && create)
            {
                a           = new TimeAxis(name);
                mMap [name] = a;
            }
            return(a);
        }
 void UpdateToolTip()
 {
     if (hotChunk == null)
     {
         toolTip.IsOpen = false;
     }
     else
     {
         var x1 = Math.Max(0, TimeAxis.TimeToScreen(hotChunk.StartTime));
         var x2 = Math.Min(TimeAxis.ActualWidth, TimeAxis.TimeToScreen(hotChunk.StartTime + hotChunk.Duration));
         var r  = new Rect(new Point(x1, 0), new Point(x2, this.ActualHeight - verticalMargin));
         toolTip.PlacementRectangle = r;
         toolTip.Placement          = PlacementMode.Bottom;
         toolTip.Content            = string.Format(dataSource.ToolTipFormat, hotChunk.StartTime, hotChunk.Duration, hotChunk.Name);
         toolTip.IsOpen             = true;
     }
 }
Exemple #19
0
        public TimeAxis AssignTo(User user, TimeAxis line, TimeAxisAuthority auth)
        {
            if (user == null || line == null || auth == null)
            {
                throw new ArgumentNullException();
            }

            if (HasAuthority(user, line, auth.AuthorityType))
            {
                return(line);
            }

            line.AddAuth(auth);
            user.AddAuth(auth);

            return(line);
        }
        public TimeScale(
			TimeAxis timeAxis,
			IHDynamicRulerEventBroker dynamicRulerEventBroker,
			HStepHelper hStepHelper,
			IOnlineMode onlineMode)
        {
            _timeAxis = timeAxis;
            _timeAxis.BoundsChanged += (s, e) => UpdateSectionLabels();
            _timeAxis.BoundsChanged += (s, e) => UpdateDynamicRulerLabel();

            _hStepHelper = hStepHelper;
            _hStepHelper.StepsChanged += (s, e) =>
            {
                CreateSectionLabels();
                UpdateSectionLabels();
            };

            _onlineMode = onlineMode;
            _onlineMode.IsOnlineChanged += (s, e) => OnPropertyChanged("IsInOfflineMode");

            IntervalLeftCommand = new RelayCommand(IntervalLeft);
            IntervalRightCommand = new RelayCommand(IntervalRight);

            InitializeComponent();

            MouseEnter += (s, e) => UpdateVisualStates();
            MouseLeave += (s, e) => UpdateVisualStates();

            var uiMoveHelper = new UiMoveHelper(MoveScaleSurface, Cursors.ScrollWE, onlineMode);
            uiMoveHelper.Moved += uiMoveHelper_Moved;

            var scaleZoomHelper = new ScaleZoomHelper(MoveScaleSurface, true);
            scaleZoomHelper.Scrolled += scaleZoomHelper_Scrolled;

            dynamicRulerEventBroker.ShowRuler += ShowDynamicRulerLabel;
            dynamicRulerEventBroker.HideRuler += HideDynamicRulerLabel;

            _updateRulerObservable = Observable
                .FromEventPattern<DynamicRulerChangedEventArgs>(dynamicRulerEventBroker, "UpdateRuler")
                .ObserveOn(SynchronizationContext.Current)
                .Subscribe(evt => UpdateDynamicRuler(evt.EventArgs));

            CreateSectionLabels();
            UpdateSectionLabels();
        }
Exemple #21
0
        private void Bind()
        {
            List <ScatterPoint[]> returnsCache = new List <ScatterPoint[]>();

            using (var file = new StreamReader(@"C:\Source\Repos\LeanOptimization_RobotLittleJiggleRemix\Optimization\bin\Release\optimizer.txt"))
            {
                var    rand = new Random();
                string line;
                while ((line = file.ReadLine()) != null)
                {
                    if (rand.Next(0, 6) != 0)
                    {
                        continue;
                    }



                    try
                    {
                        var split = line.Split(' ');
                        var time  = DateTime.Parse(split[0] + " " + split[1]);
                        if (time > TimeAxis.LastOrDefault())
                        {
                            TimeAxis.Add(time);
                            returnsCache.Add(new[]
                            {
                                new ScatterPoint(time.Ticks, double.Parse(split[split.Count() - 2]), 1),
                                new ScatterPoint(time.Ticks, double.Parse(split[5].Trim(',')) / 100, 1),
                                new ScatterPoint(time.Ticks, double.Parse(split[7].Trim(',')) / 2, 1)
                            });
                        }
                    }
                    catch (Exception)
                    {
                    }
                }

                ReturnSeries.AddRange(returnsCache.Select(r => r[0]));
                AversionSeries.AddRange(returnsCache.Select(r => r[1]));
                UnrealizedSeries.AddRange(returnsCache.Select(r => r[2]));
            }
        }
Exemple #22
0
        public bool HasAuthority(long id, TimeAxis line, params AuthorityType[] types)
        {
            if (line == null)
            {
                throw new ArgumentNullException(nameof(line));
            }
            if (types == null || types.Count() == 0)
            {
                return(true);
            }

            var hasAuth = line.GetAuthorities(id);

            var _t = types.Except(hasAuth);

            //若为开放状态则不验证查看权限
            if (line.IsPublic)
            {
                _t = _t.Where(x => x != AuthorityType.View);
            }

            return(_t.Count() == 0);
        }
        void OnSelectedNodesChanged(object sender, EventArgs e)
        {
            ulong startTime = ulong.MaxValue;
            ulong endTime   = 0;

            this.selectedChunks.Clear();
            foreach (var chunk in this.dataSelection.SelectedNodes)
            {
                this.selectedChunks.Add(chunk);
                startTime = Math.Min(chunk.StartTime, startTime);
                endTime   = Math.Max(chunk.StartTime + chunk.Duration, endTime);
            }

            if (startTime < endTime)
            {
                ulong visibleTimeStart = this.TimeAxis.VisibleTimeStart;
                ulong visibleTimeEnd   = this.TimeAxis.VisibleTimeEnd;

                // If the selection doesn't fit, zoom.  Otherwise, pan it into view as needed.
                if ((visibleTimeEnd - visibleTimeStart) < (endTime - startTime))
                {
                    TimeAxis.ZoomToHere(startTime, endTime);
                }
                else if (startTime > visibleTimeEnd)
                {
                    long deltaTicks = (long)endTime - (long)visibleTimeEnd;
                    TimeAxis.PanByTime(deltaTicks);
                }
                else if (endTime < visibleTimeStart)
                {
                    long deltaTicks = (long)startTime - (long)visibleTimeStart;
                    TimeAxis.PanByTime(deltaTicks);
                }
            }

            InvalidateVisual();
        }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            bool right = (e.Key == Key.Right);
            bool left  = (e.Key == Key.Left);
            bool up    = (e.Key == Key.Up);
            bool down  = (e.Key == Key.Down);

            // There might be a better nav model for keyboard multi-select...
            var selectedChunk = this.selectedChunks.FirstOrDefault();

            if (right || left)
            {
                if (e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Control))
                {
                    // Ctrl + L/R arrows: pan left and right
                    int panScreen = (int)(this.ActualWidth / 8.0);
                    if (right)
                    {
                        panScreen = -panScreen;
                    }
                    TimeAxis.PanByScreenDelta(panScreen);

                    hotChunk = null;
                    UpdateToolTip();
                }
                else if (selectedChunk != null)
                {
                    IEventDataNode newSelectedChunk = null;

                    if (right)
                    {
                        newSelectedChunk = dataSource.NextNode(selectedChunk);
                    }
                    else if (left)
                    {
                        newSelectedChunk = dataSource.PreviousNode(selectedChunk);
                    }
                    // L/R arrows: select next/prev chunk
                    if (newSelectedChunk != selectedChunk && newSelectedChunk != null)
                    {
                        SelectChunk(newSelectedChunk);
                    }
                }
            }
            else if (up || down)
            {
                if (e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Control))
                {
                    // Ctrl + U/D arrows: zoom in and out
                    if (up)
                    {
                        TimeAxis.ZoomIn();
                    }
                    else
                    {
                        TimeAxis.ZoomOut();
                    }
                }

                e.Handled = true;
            }

            base.OnKeyDown(e);
        }
        protected override void OnLayoutBuild()
        {
            {
//                int index = 0;
//                foreach (GUIStyle VARIABLE in GUI.skin)
//                {
//                    Button b = EuiCore.CreateElement<Button>();
//                    b.Style = VARIABLE;
//                    b.SetAnchor(AnchorType.LeftTop);
//                    b.Pivot = new Vector2(0, 0);
//                    b.Size = new Vector2(30, 30);
//                    b.AnchoredPosition = new Vector2(index % 30 * 35, index / 30 * 35);
//                    b.OnClickEvt += () =>
//                    {
//                        Debug.Log(VARIABLE);
//                        Selection.activeObject = GUI.skin;
//                    };
//
//                    index++;
//                }
                TimeAxis ta = EuiCore.CreateElement <TimeAxis>();

                //return;
                VerticalScrollRect verticalScrollRect = EuiCore.CreateElement <VerticalScrollRect>();
                verticalScrollRect.AnchoredPosition = new Vector2(0, 0);
                verticalScrollRect.Size             = new Vector2(400, 500);


                StackLayout sl = EuiCore.CreateElement <StackLayout>();
                verticalScrollRect.SetContent(sl);

                ta.SetParent(sl);

                Button btn = EuiCore.CreateElement <Button>();
                btn.Text        = "测试按钮";
                btn.Size        = new Vector2(60, 20);
                btn.OnClickEvt += () => { Debug.Log("点击"); };
                btn.SetParent(sl);

                btn             = EuiCore.CreateElement <Button>();
                btn.Text        = "测试按钮";
                btn.Size        = new Vector2(60, 180);
                btn.OnClickEvt += () => { Debug.Log("点击"); };
                btn.SetParent(sl);


                Label lab = EuiCore.CreateElement <Label>();
                lab.Text             = " 测试";
                lab.AnchoredPosition = new Vector2(100, 100);
                lab.Size             = new Vector2(60, 20);
                lab.SetParent(sl);


                Toggle toggle = EuiCore.CreateElement <Toggle>();
                toggle.Text             = "测试";
                toggle.AnchoredPosition = new Vector2(0, 100);
                toggle.Size             = new Vector2(60, 20);
                toggle.SetParent(sl);
                InputField ifd = EuiCore.CreateElement <InputField>();
                ifd.SetParent(sl);


                ifd.Text = "测试";
//                ifd.SetAnchor(AnchorType.LeftTop);
                ifd.AnchoredPosition = new Vector2(0, 0);
//                ifd.Pivot = new Vector2(0,0);
                ifd.Size = new Vector2(100, 20);


                Image im = EuiCore.CreateElement <Image>();
                im.MainTexture = AssetDatabase.LoadAssetAtPath <Texture2D>("Assets/demo.aseprite");
//                im.AnchordPosition = new Vector2(-200, 0);
                //设置裁剪
                im.SetActiveClip(true);

                //设置父对象
                ifd.SetParent(im);

                VerticalScrollbar sr = EuiCore.CreateElement <VerticalScrollbar>();
                sr.SetAnchor(AnchorType.RightStretch);
                sr.Pivot           = new Vector2(1, 0.5f);
                sr.OnValueChanged += (x) => { Debug.Log(x); };
                sr.SetSliderHeightRelative(0.5f);
                //sr.SetParent(im);
                sr.SetValue(1);
            }
        }
        public HStaticRulerControl(
			HStaticRuler staticRuler,
			IStaticRulerManager staticRulerManager,
			IHStaticRulerSurface rulerSurface,
			TimeAxis timeAxis,
			ICurvePool curvePool,
			IOnlineMode onlineMode,
			IDrawingAreaInfo drawingAreaInfo)
        {
            _timeAxis = timeAxis;
            _timeAxis.BoundsChanged += (s, e) =>
                {
                    UpdatePosition();
                    UpdateDiffs();
                };

            _drawingAreaInfo = drawingAreaInfo;
            _drawingAreaInfo.DrawingSizeChanged += (s, e) =>
                {
                    UpdatePosition();
                    UpdateDiffs();
                };

            _staticRuler = staticRuler;
            _staticRuler.PositionUpdated += (s, e) => UpdatePosition();

            _staticRulerManager = staticRulerManager;
            _staticRulerManager.ReferenceRulerChanged += () =>
                {
                    OnPropertyChanged("IsReference");
                    UpdateDiffs();
                };

            _rulerSurface = rulerSurface;

            RemoveCommand = new RelayCommand(Remove);
            SetAsReferenceCommand = new RelayCommand(_staticRuler.ToggleReference);

            _onlineMode = onlineMode;

            _curvePool = curvePool;
            _curvePool.SelectedCurveChanged += (s, e) => UpdateDiffs();

            InitializeComponent();

            _moveHelper = new UiMoveHelper(backgroundGrid, Cursors.ScrollWE, _onlineMode);
            _moveHelper.Moved += moveHelper_Moved;
            _moveHelper.IsCapturedChanged += MenuStateChanged;

            MouseEnter += (s, e) =>
                {
                    MenuStateChanged();
                    UpdateZIndex();
                };
            MouseLeave += (s, e) =>
                {
                    MenuStateChanged();
                    UpdateZIndex();
                };
            menuPopup.MouseEnter += (s, e) => MenuStateChanged();
            menuPopup.MouseLeave += (s, e) => MenuStateChanged();

            UpdatePosition();
            UpdateDiffs();
        }
        public override void Draw(DrawingContext drawingContext, ulong tickMinVis, ulong tickMaxVis)
        {
            Rect r = new Rect(new Point(0, 0), new Size(this.ActualWidth, this.ActualHeight));

            // Use a slightly oversize clip region.  Otherwise the user wouldn't see the left edge
            // of the outline on an event starting right at zero.
            Rect r2 = new Rect(new Point(-2, 0), new Size(this.ActualWidth + 4, this.ActualHeight));
            RectangleGeometry rg = new RectangleGeometry(r2);

            drawingContext.PushClip(rg);

            drawingContext.DrawRectangle(Brushes.Transparent, null, r);

            drawingContext.DrawLine(axisPen, new Point(0, this.ActualHeight / 2), new Point(this.ActualWidth, this.ActualHeight / 2));

            bool doOptimizedBorders = false;

            // Chunks are ordered by z-index, then by start time.  For each z-index, chunks should be in left-to-right order
            // and not overlap.  Track the maximum drawn X pixel for each z-index pass, so we can draw very small events
            // without drawing a crazy number of rectangles.  See DrawChunk() for the comparisons against maximumDrawnX.
            int                   currentZIndex     = -1;
            ChunkDrawData         previousChunkData = null;
            List <IEventDataNode> forceDrawChunks   = new List <IEventDataNode>();

            foreach (var chunk in this.sortedNodes)
            {
                if (chunk.ZIndex > currentZIndex)
                {
                    currentZIndex = chunk.ZIndex;

                    // Draw the previous chunk data (if any) and the forced-drawn (selected/hot) chunks at the previous level
                    DrawLastDelayedAndForcedDrawChunks(drawingContext, previousChunkData, forceDrawChunks);
                    previousChunkData = null;
                    forceDrawChunks.Clear();

                    // If dataSource.ContiguousEvents is true, then we are guaranteed that the events are
                    // always right next to each other -- but only at level 0.  At higher levels, they may
                    // not be contiguous due to the tree expansion state.  The "doOptimizedBorders" mode is to
                    // fill the entire region with the outline color, then draw the chunks with no borders
                    // (if they are big enough to be visible).
                    doOptimizedBorders = (dataSource.ContiguousEvents && currentZIndex == 0);

                    if (doOptimizedBorders)
                    {
                        // Draw the full bar in the standard pen brush color, as if it were full of 1-px wide chunks.
                        r = new Rect(new Point(0, verticalMargin), new Size(this.ActualWidth, this.ActualHeight - (verticalMargin * 2)));
                        if (currentZIndex > 0)
                        {
                            double delta = chunk.ZIndex * 2;
                            r.Inflate(0, -delta);
                        }
                        drawingContext.DrawRectangle(this.Stroke, null, r);
                    }
                }

                if (chunk.Visible)
                {
                    Brush brush;
                    Pen   pen;

                    if (chunk == hotChunk || this.selectedChunks.Contains(chunk))
                    {
                        // We need to draw these a second time.  If we skip them, it causes different
                        // merging behavior and you get visual artifacts as you select/hover over events.
                        forceDrawChunks.Add(chunk);
                    }

                    pen = doOptimizedBorders ? null : standardPen;

                    if (UseEventColor)
                    {
                        uint nodeColor = chunk.Color;
                        if (!customBrushes.TryGetValue(nodeColor, out brush))
                        {
                            brush = new SolidColorBrush(new EventColor(nodeColor));
                            customBrushes.Add(nodeColor, brush);
                        }
                    }
                    else
                    {
                        brush = this.Fill;
                    }

                    previousChunkData = DrawChunk(drawingContext, chunk, brush, pen, previousChunkData, forceDraw: false);
                }
            }

            DrawLastDelayedAndForcedDrawChunks(drawingContext, previousChunkData, forceDrawChunks);

            double?lastDrawnSlicingMarkerX = null;

            foreach (var marker in this.slicingMarkers)
            {
                lastDrawnSlicingMarkerX = DrawSlicingMarker(drawingContext, marker, lastDrawnSlicingMarkerX);
            }

            List <Rect>   labelRects = new List <Rect>();
            FormattedText ftLabel    = null;

            // Draw selected chunk arrows, and calculate label rect requirements
            foreach (var selectedChunk in this.selectedChunks)
            {
                if (selectedChunk != hotChunk)
                {
                    var    brush        = IsFocused ? this.SelectedFill : this.InactiveSelectedFill;
                    var    middle       = TimeAxis.TimeToScreen(selectedChunk.StartTime + (selectedChunk.Duration / 2));
                    double heightAdjust = 0.5;

                    if (selectedChunk.Style == EventRenderStyle.SlicingMarker)
                    {
                        heightAdjust = verticalMargin - 6;
                    }

                    var geom = selectionArrowGeometry.Clone();
                    geom.Transform = new TranslateTransform(middle, verticalMargin - heightAdjust);
                    drawingContext.DrawGeometry(brush, selectedPen, geom);

                    var x1 = TimeAxis.TimeToScreen(selectedChunk.StartTime);
                    var x2 = TimeAxis.TimeToScreen(selectedChunk.StartTime + selectedChunk.Duration);
                    if (x1 < this.ActualWidth && x2 > 0)
                    {
                        // Draw label, if selected chunk is visible
                        if (ftLabel == null)
                        {
                            // NOTE:  It is assumed that all selected chunks have the same name...
                            ftLabel = new FormattedText(selectedChunk.Name, CultureInfo.CurrentCulture,
                                                        FlowDirection.LeftToRight, labelTypeface, labelFontSize, Brushes.Black);
                        }

                        // Try to center the label under the event.  But adjust its position if it
                        // is clipped by the left or right edge of the timeline.
                        var left = middle - ftLabel.Width / 2;
                        if (left < 0)
                        {
                            left = 0;
                        }
                        else if (left + ftLabel.Width > this.ActualWidth)
                        {
                            left = this.ActualWidth - ftLabel.Width;
                        }

                        // Create a rect (top/height insignificant) for this label and remember it
                        labelRects.Add(new Rect(left, 0, ftLabel.Width, 10));
                    }
                }
            }

            if (ftLabel != null)
            {
                List <Rect> mergedRects = new List <Rect>(labelRects.Count);

                // Merge the overlapping label rects together
                while (labelRects.Count > 0)
                {
                    Rect rect = labelRects[0];

                    labelRects.RemoveAt(0);

                    for (int i = 0; i < labelRects.Count;)
                    {
                        if (rect.IntersectsWith(labelRects[i]))
                        {
                            rect.Union(labelRects[i]);
                            labelRects.RemoveAt(i);
                        }
                        else
                        {
                            i++;
                        }
                    }

                    mergedRects.Add(rect);
                }

                // Draw the text centered in each of the remaining label rects
                foreach (var rect in mergedRects)
                {
                    double centerX = rect.Left + (rect.Width / 2) - (ftLabel.Width / 2);
                    drawingContext.DrawText(ftLabel, new Point(centerX, this.ActualHeight - verticalMargin));
                }
            }

            // Draw hot chunk arrow
            if (hotChunk != null)
            {
                var    middle       = TimeAxis.TimeToScreen(hotChunk.StartTime + (hotChunk.Duration / 2));
                double heightAdjust = 0.5;

                if (hotChunk.Style == EventRenderStyle.SlicingMarker)
                {
                    heightAdjust = verticalMargin - 6;
                }

                hotArrowGeometry.Transform = new TranslateTransform(middle, verticalMargin - heightAdjust);
                drawingContext.DrawGeometry(this.HighlightedFill, this.highlightedPen, hotArrowGeometry);
            }

            drawingContext.Pop(); // pop clip

            UpdateToolTip();
        }
        ChunkDrawData DrawChunk(DrawingContext drawingContext, IEventDataNode chunk, Brush brush, Pen pen, ChunkDrawData previousChunkData, bool forceDraw)
        {
            var x1 = TimeAxis.TimeToScreen(chunk.StartTime);
            var x2 = Math.Max(x1, TimeAxis.TimeToScreen(chunk.StartTime + chunk.Duration));  // Max in case the duration is bogus

            if (x2 < 0 || x1 > this.ActualWidth)
            {
                if (previousChunkData != null)
                {
                    drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect);
                }

                return(null);
            }

            var r = new Rect(new Point(x1, verticalMargin), new Size(x2 - x1, this.ActualHeight - (verticalMargin * 2)));
            var halfHeightRect = new Rect(new Point(x1, (this.ActualHeight - halfHeight) / 2), new Size(x2 - x1, halfHeight));
            var style          = chunk.Style;

            if (pen == null)
            {
                // Since there is no stroke (pen == null), this is a "normal" chunk with no border
                // (the bar has already been filled w/ border color) so deflate 1/2 pixel to simulate
                // a border stroke.
                r.Inflate(-0.5, -0.5);
            }
            else
            {
                r.Inflate(0, -0.5);
            }

            const int minWidth = 3;

            // Points-in-time (markers) are always 3px wide
            if (style == EventRenderStyle.ParentedMarker)
            {
                r = new Rect(x1 - Math.Floor((double)minWidth / 2), verticalMargin, minWidth, this.ActualHeight - (verticalMargin * 2));
            }

            // Adjust rect height based on chunk nesting depth
            if (chunk.ZIndex > 0 && !r.IsEmpty && style != EventRenderStyle.HalfHeight)
            {
                double delta = chunk.ZIndex * 2;
                r.Inflate(0, -delta);
            }

            if (forceDraw)
            {
                // This is a special (hot or selected) chunk, so enforce a minimum width and always draw it.
                if (style == EventRenderStyle.HalfHeight)
                {
                    r = halfHeightRect;
                }

                var width = r.Width;
                if (width < minWidth)
                {
                    var halfGap = (minWidth - width) / 2;
                    r = new Rect(new Point(r.Left - halfGap, r.Top), new Point(r.Right + halfGap, r.Bottom));
                }
                drawingContext.DrawRectangle(brush, pen, r);
                return(null);
            }

            const double minDistance = 16;

            if (style == EventRenderStyle.HalfHeight)
            {
                r = halfHeightRect;
            }

            // Draw the chunk.  We may need to merge it with the previous rect if there is one.
            if (previousChunkData != null)
            {
                // We have a previous rect.  If it's far enough away from this one, then draw it.
                // OR, if this one is big enough BY ITSELF to be drawn, draw the previous one.
                // Otherwise, merge it with this one, and draw the result if it's wide enough.
                if (previousChunkData.Rect.Right < (r.Left - (minDistance / 4)) || (r.Width >= minDistance))
                {
                    drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect);
                }
                else
                {
                    previousChunkData.Rect = Rect.Union(previousChunkData.Rect, r);
                    previousChunkData.Fill = Brushes.Gray;

                    if (previousChunkData.Rect.Width >= minDistance)
                    {
                        drawingContext.DrawRectangle(previousChunkData.Fill, previousChunkData.Pen, previousChunkData.Rect);
                        previousChunkData = null;
                    }

                    return(previousChunkData);
                }
            }

            if (r.Width >= minDistance)
            {
                drawingContext.DrawRectangle(brush, pen, r);
                previousChunkData = null;
            }
            else
            {
                previousChunkData = new ChunkDrawData {
                    Fill = brush, Rect = r, Pen = pen
                };
            }

            return(previousChunkData);
        }
Exemple #29
0
        public TimeAxis AssignTo(User user, TimeAxis line, AuthorityType type)
        {
            var auth = new TimeAxisAuthority(user, type);

            return(AssignTo(user, line, auth));
        }