/// <summary> /// Looks the through adjacent panel for overlap. /// </summary> /// <param name="panel">The panel.</param> /// <param name="comparisonPanel">The comparison panel.</param> /// <param name="offset">The offset.</param> private static new void LookThroughAdjacentPanelForOverlap(PanelWrapper panel, PanelWrapper comparisonPanel, double offset) { // all we need to do is determine if the items on the edge of the panels overlap. // so, really we are talking about a datamarker symbol wide on either edge. // the seamedelementcolelction gives us the elements that are plotted // outside the bounds of our panel. foreach (FrameworkElement element in panel.SeamedElementCollection) { double elementLeft = Canvas.GetLeft(element); double elementWidth = element.Width; Collision collision; foreach (FrameworkElement comparisonElement in comparisonPanel.SeamedElementCollection) { GraphPoint elementDataContext = element.DataContext as GraphPoint; GraphPoint comparisionElementDataContext = comparisonElement.DataContext as GraphPoint; if (elementDataContext != null && comparisionElementDataContext != null) { bool areDataContextsSame = false; areDataContextsSame = elementDataContext.X1 == comparisionElementDataContext.X1; if (elementDataContext.X2.HasValue && comparisionElementDataContext.X2.HasValue) { areDataContextsSame = elementDataContext.X2.Value == comparisionElementDataContext.X2.Value; } else if ((elementDataContext.X2.HasValue && !comparisionElementDataContext.X2.HasValue) || (!elementDataContext.X2.HasValue && comparisionElementDataContext.X2.HasValue)) { areDataContextsSame = false; } if (null != element && null != comparisonElement && !areDataContextsSame) { double comparisonLeft = Canvas.GetLeft(comparisonElement) + offset; bool flag = false; if (elementLeft < comparisonLeft && (elementLeft + elementWidth) > comparisonLeft) { // the elements collide // the element is to the left of the comparison and overlaps. flag = true; } else if (elementLeft > comparisonLeft && elementLeft < (comparisonLeft + elementWidth)) { // the elements collide // the element is to the right of the comparison and overlaps. flag = true; } if (true == flag) { collision = new Collision(element, element, true); panel.CollisionCollection.Add(collision); } } } } } }
/// <summary> /// Looks the through adjacent panel for overlap. /// </summary> /// <param name="panel">The panel.</param> /// <param name="comparisonPanel">The comparison panel.</param> /// <param name="offset">The offset.</param> internal static void LookThroughAdjacentPanelForOverlap(PanelWrapper panel, PanelWrapper comparisonPanel, double offset) { // all we need to do is determine if the items on the edge of the panels overlap. // so, really we are talking about a datamarker synmbol wide on either edge. // the seamedelementcolelction gives us the elements that are plotted // outside the bounds of our panel. foreach (FrameworkElement element in panel.SeamedElementCollection) { double elementLeft = Canvas.GetLeft(element); double elementWidth = element.Width; Collision collision; foreach (FrameworkElement comparisonElement in comparisonPanel.SeamedElementCollection) { FrameworkElement elementLabel = GraphBase.GetDataPointLabel(element); FrameworkElement comparisonElementLabel = GraphBase.GetDataPointLabel(comparisonElement); if (null != elementLabel && null != comparisonElementLabel) { GraphPoint elementGraphPoint = elementLabel.DataContext as GraphPoint; GraphPoint comparisonElementGraphPoint = comparisonElementLabel.DataContext as GraphPoint; if (null != elementGraphPoint && null != comparisonElementGraphPoint && elementGraphPoint.DataContext != comparisonElementGraphPoint.DataContext) { double comparisonLeft = Canvas.GetLeft(comparisonElement) + offset; bool flag = false; if (elementLeft < comparisonLeft && (elementLeft + elementWidth) > comparisonLeft) { // the elements collide // the element is to the left of the comparison and overlaps. flag = true; } else if (elementLeft > comparisonLeft && elementLeft < (comparisonLeft + elementWidth)) { // the elements collide // the element is to the right of the comparison and overlaps. flag = true; } if (true == flag) { collision = new Collision(element, element, true); panel.CollisionCollection.Add(collision); GraphBase.SetDataPointOverlapProperty(element, true); GraphBase.SetDataPointOverlapProperty(elementLabel, true); elementLabel.Visibility = Visibility.Collapsed; GraphBase.SetDataPointOverlapProperty(comparisonElement, true); GraphBase.SetDataPointOverlapProperty(comparisonElementLabel, true); comparisonElementLabel.Visibility = Visibility.Collapsed; } } } } } }
/// <summary> /// Virtual. Plots a time graph with a filtered set of data. /// </summary> /// <param name="subSet">Filtered set of data.</param> /// <param name="panel">The panel.</param> protected override void DrawFilteredTimeGraph(IEnumerable subSet, PanelWrapper panel) { base.DrawFilteredTimeGraph(subSet, panel); // Maintain the previous and current point plotted for the virtual method call GraphPoint prevPoint = new GraphPoint(); GraphPoint currPoint = new GraphPoint(); System.Collections.Generic.Stack<FrameworkElement> dataPointStack = new System.Collections.Generic.Stack<FrameworkElement>(); System.Collections.Generic.Stack<FrameworkElement> dataPointLabelStack = new System.Collections.Generic.Stack<FrameworkElement>(); CollisionDetectionManager collisionManager = GraphBase.GetCollisionDetectionManager(this.DynamicPlotLayer); foreach (object o in subSet) { if (panel.AbortLayout) { break; } GraphPoint gp = this.GetBoundGraphPoint(o); if (null == gp) { return; } gp.X1Pixel = this.GetXForDate(gp.X1); gp.Y1Pixel = this.GetYForValue(gp.Y1); if (!Double.IsNaN(gp.Y2)) { gp.Y2Pixel = this.GetYForValue(gp.Y2); } currPoint = gp; // process the plotted data marker this.ProcessPlottedDataMarker(prevPoint, currPoint); if (!this.Minimized) { if (!double.IsNaN(gp.Y1) && currPoint.X1Pixel >= 0 && currPoint.X1Pixel < this.DynamicMainLayerViewport.ActualWidth) { FrameworkElement marker = this.GetPlottedDataMarker(gp); double left = Canvas.GetLeft(marker); #if !SILVERLIGHT // For WPF should snap to grid if requested bool snap = GraphBase.GetSnapToPixels(marker); if (marker.SnapsToDevicePixels != snap) { marker.SnapsToDevicePixels = snap; } #endif if (left < 0 || (left + marker.Width) > this.DynamicMainLayerViewport.ActualWidth) { this.CurrentWorkingPanel.SeamedElementCollection.Add(marker); } this.DynamicPlotLayer.Children.Add(marker); dataPointStack.Push(marker); FrameworkElement labelElement = null; if (null != this.LabelTemplate) { labelElement = this.LabelTemplate.LoadContent() as FrameworkElement; labelElement.DataContext = gp; dataPointLabelStack.Push(labelElement); } if (null != labelElement) { double offsetValueX = GraphBase.GetXOffset(labelElement); double offsetValueY = GraphBase.GetYOffset(labelElement); // define the label position double labelY = currPoint.Y1Pixel; if (!double.IsNaN(gp.Y2) && gp.Y1 < gp.Y2) { labelY = currPoint.Y2Pixel; } double markerOffset = Math.Abs(GraphBase.GetYOffset(marker)) + 2; Canvas.SetTop(labelElement, (labelY - markerOffset) + offsetValueY); Canvas.SetLeft(labelElement, currPoint.X1Pixel + offsetValueX); labelElement.Visibility = this.ShowDataPointLabels; this.DynamicPlotLayer.Children.Add(labelElement); GraphBase.SetDataPointLabel(marker, labelElement); panel.LabelElements.Add(labelElement); marker.MouseEnter += new MouseEventHandler(this.DataPointMarker_MouseEnter); marker.MouseLeave += new MouseEventHandler(this.DataPointMarker_MouseLeave); } } } prevPoint = currPoint; } if (!panel.AbortLayout && this.DetectCollisions) { Collision previousCollision = null; // get the last items in the collection for the data context object[] lastItems = this.GetLastDataPoints(); object lastObject = lastItems[1]; object secondLastObject = lastItems[0]; byte lastItemsCheck = 0; while (dataPointStack.Count > 0) { FrameworkElement ele = dataPointStack.Pop(); FrameworkElement labelEle = GraphBase.GetDataPointLabel(ele); if (lastItemsCheck < 2 && null != labelEle && null != labelEle.DataContext) { // this is the last item on the page. // we plot back to front to check if things overlap. ++lastItemsCheck; object gp = ((GraphPoint)labelEle.DataContext).DataContext; if (lastObject == gp) { // this is the last item in the series. GraphBase.SetLastItem(ele, true); labelEle.Visibility = Visibility.Visible; labelEle.RenderTransform = this.LabelTransform; } if (secondLastObject == gp) { // this is the second last item in the series. GraphBase.SetSecondToLast(ele, true); labelEle.Visibility = Visibility.Visible; } } FrameworkElement clashElement = collisionManager.RegisterAndTestIfMarkerOverlaps(ele); if (null != clashElement) { previousCollision = new Collision(clashElement, ele, true); this.CurrentWorkingPanel.CollisionCollection.Add(previousCollision); GraphBase.SetDataPointOverlapProperty(ele, true); GraphBase.SetDataPointOverlapProperty(labelEle, true); labelEle.Visibility = Visibility.Collapsed; GraphBase.SetDataPointOverlapProperty(clashElement, true); FrameworkElement clashElementLabel = GraphBase.GetDataPointLabel(clashElement); GraphBase.SetDataPointOverlapProperty(clashElementLabel, true); clashElementLabel.Visibility = Visibility.Collapsed; } else { // this marker does not overlap previousCollision = null; } } while (dataPointLabelStack.Count > 0) { FrameworkElement ele2 = dataPointLabelStack.Pop(); if (collisionManager.RegisterAndTestIfLabelOverlaps(ele2)) { GraphBase.SetDataPointOverlapProperty(ele2, true); ele2.Visibility = Visibility.Collapsed; } } PanelWrapper otherPanel = null; // we get panel 2 then panel 1 when getting both panels. double markerOffsetToUse = 0; // perform seam detection // panel1 is to the left of panel2 if (this.CurrentWorkingPanel == this.Panel1) { // panel2 markers must be incremented by the width of the layer. otherPanel = this.Panel2; markerOffsetToUse = this.Panel1.Width; } else { // panel1 markers must be decremented by the width of the plot layer. // if we are renewing both panels, then do not do collisions detections on seams for if (true != this.RenewingBothPanels) { otherPanel = this.Panel1; markerOffsetToUse = this.Panel2.Width * -1; } } // this gets run if we are renewing a panel, but if renewing both, only for panel 1 if (null != otherPanel) { LookThroughAdjacentPanelForOverlap(this.CurrentWorkingPanel, otherPanel, markerOffsetToUse); } double lastCollisionPosition = -1; foreach (Collision collision in this.CurrentWorkingPanel.CollisionCollection) { if (null != this.CollisionTemplate) { FrameworkElement collisionIcon = this.CollisionTemplate.LoadContent() as FrameworkElement; double theXOffset = GraphBase.GetXOffset(collisionIcon); double theYOffset = GraphBase.GetYOffset(collisionIcon); if (null != collisionIcon) { double localxPosition = Canvas.GetLeft(collision.ClusterStartElement) + theXOffset; double localyPosition = Canvas.GetTop(collision.ClusterStartElement) + theYOffset; if (lastCollisionPosition == -1 || localxPosition < lastCollisionPosition - 46) { lastCollisionPosition = localxPosition; Canvas.SetLeft(collisionIcon, localxPosition); Canvas.SetTop(collisionIcon, localyPosition); if (true == collision.ClusterShowingIcon) { this.DynamicPlotLayer.Children.Add(collisionIcon); } } } } } } }