Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
        {
            if (hotChunk != null)
            {
                hotChunk       = null;
                toolTip.IsOpen = false;
                InvalidateVisual();
            }

            base.OnMouseLeave(e);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
 public SelectionEventArgs(IEventDataNode node)
 {
     SelectedEvent = node;
 }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
 void SelectChunk(IEventDataNode chunk)
 {
     dataSource.OnSelectionChangedInternal(chunk);
     this.Focus();
 }
        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);
        }
 public SelectionEventArgs(IEventDataNode node)
 {
     SelectedEvent = node;
 }
        protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
        {
            if (hotChunk != null)
            {
                hotChunk = null;
                toolTip.IsOpen = false;
                InvalidateVisual();
            }

            base.OnMouseLeave(e);
        }
        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);
        }
        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;
        }
        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;
        }
 void SelectChunk(IEventDataNode chunk)
 {
     dataSource.OnSelectionChangedInternal(chunk);
     this.Focus();
 }