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; }
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)); } } }
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); }
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]; }
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); }
public OnlineMode(TimeAxis timeAxis) { _timeAxis = timeAxis; _onlineTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1), IsEnabled = false }; _onlineTimer.Tick += (s, e) => UpdateOnlineTime(); }
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); }
public void Remove() { if (mName != null) { TimeMgr.single.mMap.Remove(mName); } if (mParent == null) { return; } mParent.mChilds.Remove(this); mParent = null; }
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); }
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; } }
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(); }
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])); } }
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); }
public TimeAxis AssignTo(User user, TimeAxis line, AuthorityType type) { var auth = new TimeAxisAuthority(user, type); return(AssignTo(user, line, auth)); }