public static void PrintToFit(GraphAreaBase visual, string description, int margin = 0) { var pd = new PrintDialog(); if (pd.ShowDialog() == true) { visual.SetPrintMode(true, true, margin); //store original scale var originalScale = visual.LayoutTransform; //get selected printer capabilities var capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket); //get scale of the print wrt to screen of WPF visual var scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / visual.ActualWidth, capabilities.PageImageableArea.ExtentHeight / visual.ActualHeight); //Transform the Visual to scale var group = new TransformGroup(); group.Children.Add(new ScaleTransform(scale, scale)); visual.LayoutTransform = group; visual.InvalidateArrange(); visual.UpdateLayout(); //now print the visual to printer to fit on the one page. pd.PrintVisual(visual, description); //apply the original transform. visual.LayoutTransform = originalScale; visual.SetPrintMode(false, true, margin); } }
private static void UpdateCoordinates(GraphAreaBase area, DependencyObject obj, double horizontalChange, double verticalChange, SnapModifierFunc xSnapModifier, SnapModifierFunc ySnapModifier) { if (double.IsNaN(GraphAreaBase.GetX(obj))) { GraphAreaBase.SetX(obj, 0, true); } if (double.IsNaN(GraphAreaBase.GetY(obj))) { GraphAreaBase.SetY(obj, 0, true); } //move the object var x = GetOriginalX(obj) + horizontalChange; if (xSnapModifier != null) { x = xSnapModifier(area, obj, x); } GraphAreaBase.SetX(obj, x, true); var y = GetOriginalY(obj) + verticalChange; if (ySnapModifier != null) { y = ySnapModifier(area, obj, y); } GraphAreaBase.SetY(obj, y, true); if (GetUpdateEdgesOnMove(obj)) { UpdateVertexEdges(obj as VertexControl); } //Debug.WriteLine("({0:##0.00000}, {1:##0.00000})", x, y); }
public static void PrintWithDPI(GraphAreaBase visual, string description, double dpi, int margin = 0) { var pd = new PrintDialog(); if (pd.ShowDialog() == true) { visual.SetPrintMode(true, true, margin); //store original scale var originalScale = visual.LayoutTransform; //get scale from DPI var scale = dpi / DEFAULT_DPI; //Transform the Visual to scale var group = new TransformGroup(); group.Children.Add(new ScaleTransform(scale, scale)); visual.LayoutTransform = group; //update visual visual.InvalidateArrange(); visual.UpdateLayout(); //now print the visual to printer to fit on the one page. pd.PrintVisual(visual, description); //apply the original transform. visual.LayoutTransform = originalScale; visual.SetPrintMode(false, true, margin); } }
private static void OnDragStarted(object sender, PointerRoutedEventArgs e) #endif { var obj = sender as DependencyObject; //we are starting the drag SetIsDragging(obj, true); // Save the position of the mouse to the start position var area = GetAreaFromObject(obj); var pos = GetPositionInArea(area, e); SetOriginalMouseX(obj, pos.X); SetOriginalMouseY(obj, pos.Y); // Save the position of the dragged object to its starting position SetOriginalX(obj, GraphAreaBase.GetFinalX(obj)); SetOriginalY(obj, GraphAreaBase.GetFinalY(obj)); // Save starting position of all tagged elements if (GetIsTagged(obj)) { foreach (var item in area.GetAllVertexControls()) { if (GetIsTagged(item)) { SetOriginalX(item, GraphAreaBase.GetFinalX(item)); SetOriginalY(item, GraphAreaBase.GetFinalY(item)); } } } //capture the mouse #if WPF var element = obj as IInputElement; if (element != null) { element.CaptureMouse(); element.MouseMove -= OnDragging; element.MouseMove += OnDragging; } //else throw new GX_InvalidDataException("The control must be a descendent of the FrameworkElement or FrameworkContentElement!"); e.Handled = false; #elif METRO var element = obj as FrameworkElement; if (element != null) { element.CapturePointer(e.Pointer); element.PointerMoved += OnDragging; } e.Handled = true; #endif }
//Set pixelformat of image. /////!!! private static PixelFormat pixelFormat = PixelFormats.Pbgra32; /// <summary> /// Method exports the GraphArea to an png image. /// </summary> /// <param name="surface">GraphArea control</param> /// <param name="path">Image destination path</param> /// <param name="imgdpi">Optional image DPI parameter</param> /// <param name="imgQuality">Optional image quality parameter (for some formats like JPEG)</param> public static void ExportToImage(GraphAreaBase surface, Uri path, ImageType itype, bool useZoomControlSurface = false, double imgdpi = DEFAULT_DPI, int imgQuality = 100) { //TODO //Create a render bitmap and push the surface to it /*Visual vis = surface; * if (useZoomControlSurface) * { * if (surface.Parent != null && surface.Parent is IZoomControl) * vis = (surface.Parent as IZoomControl).PresenterVisual; * else if(surface.Parent!=null && surface.Parent is FrameworkElement && (surface.Parent as FrameworkElement).Parent is IZoomControl) * vis = ((surface.Parent as FrameworkElement).Parent as IZoomControl).PresenterVisual; * } * var renderBitmap = * new RenderTargetBitmap( * //(int)surface.ActualWidth, * //(int)surface.ActualHeight, * (int)((vis as UIElement).DesiredSize.Width * (imgdpi / DefaultDPI) + 100), * (int)((vis as UIElement).DesiredSize.Height * (imgdpi / DefaultDPI) + 100), * imgdpi, * imgdpi, * pixelFormat); * * //Render the graphlayout onto the bitmap. * renderBitmap.Render(vis); * * * //Create a file stream for saving image * using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create)) * { * //Use png encoder for our data * BitmapEncoder encoder; * switch (itype) * { * case ImageType.PNG: encoder = new PngBitmapEncoder(); * break; * case ImageType.JPEG: encoder = new JpegBitmapEncoder() { QualityLevel = imgQuality }; * break; * case ImageType.BMP: encoder = new BmpBitmapEncoder(); * break; * case ImageType.GIF: encoder = new GifBitmapEncoder(); * break; * case ImageType.TIFF: encoder = new TiffBitmapEncoder(); * break; * default: throw new GX_InvalidDataException("ExportToImage() -> Unknown output image format specified!"); * } * * //Push the rendered bitmap to it * encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); * //Save the data to the stream * encoder.Save(outStream); * }*/ }
private static Windows.Foundation.Point GetPositionInArea(GraphAreaBase area, PointerRoutedEventArgs e) #endif { if (area != null) { #if WPF var pos = e.GetPosition(area); #elif METRO var pos = e.GetCurrentPoint(area as UIElement).Position; #endif return(pos); } throw new GX_InvalidDataException("DragBehavior.GetPositionInArea() - The input element must be a child of a GraphAreaBase."); }
private static void OnEdgeDragFinished(object sender, System.Windows.Input.MouseButtonEventArgs e) { EdgeControl edgeControl = sender as EdgeControl; if (edgeControl == null) { return; } GraphAreaBase graphAreaBase = edgeControl.RootArea; VertexControl vertexControl = graphAreaBase.GetVertexControlAt(e.GetPosition(graphAreaBase)); if (vertexControl != null) { edgeControl.Target = vertexControl; if (vertexControl.VertexConnectionPointsList.Count > 0) { IVertexConnectionPoint vertexConnectionPoint = vertexControl.GetConnectionPointAt(e.GetPosition(graphAreaBase)); var edge = edgeControl.Edge as IGraphXCommonEdge; if (vertexConnectionPoint != null) { edge.TargetConnectionPointId = vertexConnectionPoint.Id; } else { edge.TargetConnectionPointId = null; } } edgeControl.UpdateEdge(); var obj = (DependencyObject)sender; SetIsDragging(obj, false); //obj.ClearValue(OriginalMouseXProperty); //obj.ClearValue(OriginalMouseYProperty); //obj.ClearValue(OriginalXProperty); //obj.ClearValue(OriginalYProperty); var element = sender as IInputElement; if (element != null) { element.MouseMove -= OnVertexDragging; element.ReleaseMouseCapture(); } } }
public static void ShowPrintPreview(GraphAreaBase surface, string description = "") { try { var printDialog = new PrintDialog(); if (printDialog.ShowDialog() == true) { printDialog.PrintVisual(surface, description); } } catch (Exception) { MessageBox.Show("Unexpected exception occured while trying to access default printer. Please ensure that default printer is installed in your OS!"); } }
public static void ShowPrintPreview(GraphAreaBase surface, string description = "") { //TODO /* try * { * var printDialog = new PrintDialog(); * if (printDialog.ShowDialog() == true) * { * printDialog.PrintVisual(surface, description); * } * } * catch (Exception ex) * { * new MessageDialog("Unexpected exception occured while trying to acces default printer. Please ensure that default printer is installed in your OS!").Show(); * }*/ }
private static GraphAreaBase GetAreaFromObject(object obj) { GraphAreaBase area = null; if (obj is VertexControl) { area = ((VertexControl)obj).RootArea; } else if (obj is EdgeControl) { area = ((EdgeControl)obj).RootArea; } else if (obj is DependencyObject) { area = VisualTreeHelperEx.FindAncestorByType((DependencyObject)obj, typeof(GraphAreaBase), false) as GraphAreaBase; } return(area); }
/// <summary> /// Helper method which calculates estimated image DPI based on the input criterias /// </summary> /// <param name="vis">GraphArea object</param> /// <param name="imgdpi">Desired DPI</param> /// <param name="dpiStep">DPI decrease step while estimating</param> /// <param name="estPixelCount">Pixel quantity threshold</param> public static double CalculateEstimatedDPI(GraphAreaBase vis, double imgdpi, double dpiStep, int estPixelCount) { bool result = false; double currentDPI = imgdpi; while (!result) { if (CalulateSize(vis.ContentSize.Size, currentDPI) <= estPixelCount) { result = true; } else { currentDPI -= dpiStep; } if (currentDPI < 0) { return(0); } } return(currentDPI); }
private static void UpdateCoordinates(DependencyObject obj, double horizontalChange, double verticalChange) { if (double.IsNaN(GraphAreaBase.GetX(obj))) { GraphAreaBase.SetX(obj, 0, true); } if (double.IsNaN(GraphAreaBase.GetY(obj))) { GraphAreaBase.SetY(obj, 0, true); } //move the object var x = GraphAreaBase.GetX(obj) + horizontalChange; GraphAreaBase.SetX(obj, x, true); var y = GraphAreaBase.GetY(obj) + verticalChange; GraphAreaBase.SetY(obj, y, true); if (GetUpdateEdgesOnMove(obj)) { UpdateVertexEdges(obj as VertexControl); } }
private static RenderTargetBitmap RenderTargetBitmap(GraphAreaBase surface, bool useZoomControlSurface, double imgdpi) { UIElement vis = surface; if (useZoomControlSurface) { var zoomControl = surface.Parent as IZoomControl; if (zoomControl != null) { vis = zoomControl.PresenterVisual; } else { var frameworkElement = surface.Parent as FrameworkElement; if (frameworkElement != null && frameworkElement.Parent is IZoomControl) { vis = ((IZoomControl)frameworkElement.Parent).PresenterVisual; } } } var renderBitmap = new RenderTargetBitmap( //(int)surface.ActualWidth, //(int)surface.ActualHeight, (int)(vis.DesiredSize.Width * (imgdpi / 96) + 100), (int)(vis.DesiredSize.Height * (imgdpi / 96) + 100), imgdpi, imgdpi, PixelFormat); vis.SetValue(Panel.BackgroundProperty, Brushes.White); //Render the graphlayout onto the bitmap. renderBitmap.Render(vis); return(renderBitmap); }
/// <summary> /// Get control position on the GraphArea panel in attached coords X and Y (GraphX type version) /// </summary> /// <param name="final"></param> /// <param name="round"></param> internal Measure.Point GetPositionGraphX(bool final = false, bool round = false) { return(round ? new Measure.Point(final ? (int)GraphAreaBase.GetFinalX(this) : (int)GraphAreaBase.GetX(this), final ? (int)GraphAreaBase.GetFinalY(this) : (int)GraphAreaBase.GetY(this)) : new Measure.Point(final ? GraphAreaBase.GetFinalX(this) : GraphAreaBase.GetX(this), final ? GraphAreaBase.GetFinalY(this) : GraphAreaBase.GetY(this))); }
/// <summary> /// Get control position on the GraphArea panel in attached coords X and Y /// </summary> /// <param name="final"></param> /// <param name="round"></param> public Point GetPosition(bool final = false, bool round = false) { return(round ? new Point(final ? (int)GraphAreaBase.GetFinalX(this) : (int)GraphAreaBase.GetX(this), final ? (int)GraphAreaBase.GetFinalY(this) : (int)GraphAreaBase.GetY(this)) : new Point(final ? GraphAreaBase.GetFinalX(this) : GraphAreaBase.GetX(this), final ? GraphAreaBase.GetFinalY(this) : GraphAreaBase.GetY(this))); }
public void SetPosition(double x, double y, bool alsoFinal = true) { GraphAreaBase.SetX(this, x, alsoFinal); GraphAreaBase.SetY(this, y, alsoFinal); }
/// <summary> /// Set attached coordinates X and Y /// </summary> /// <param name="pt"></param> /// <param name="alsoFinal"></param> public void SetPosition(Point pt, bool alsoFinal = true) { GraphAreaBase.SetX(this, pt.X, alsoFinal); GraphAreaBase.SetY(this, pt.Y, alsoFinal); }
/// <summary> /// Method exports the GraphArea to an png image. /// </summary> /// <param name="surface">GraphArea control</param> /// <param name="path">Image destination path</param> /// <param name="useZoomControlSurface"></param> /// <param name="imgdpi">Optional image DPI parameter</param> /// <param name="imgQuality">Optional image quality parameter (for some formats like JPEG)</param> /// <param name="itype"></param> public static void ExportToImage(GraphAreaBase surface, Uri path, ImageType itype, bool useZoomControlSurface = false, double imgdpi = DEFAULT_DPI, int imgQuality = 100) { if (!useZoomControlSurface) { surface.SetPrintMode(true, true, 100); } //Create a render bitmap and push the surface to it UIElement vis = surface; if (useZoomControlSurface) { var zoomControl = surface.Parent as IZoomControl; if (zoomControl != null) { vis = zoomControl.PresenterVisual; } else { var frameworkElement = surface.Parent as FrameworkElement; if (frameworkElement != null && frameworkElement.Parent is IZoomControl) { vis = ((IZoomControl)frameworkElement.Parent).PresenterVisual; } } } var renderBitmap = new RenderTargetBitmap( (int)(vis.DesiredSize.Width * (imgdpi / DEFAULT_DPI) + 100), (int)(vis.DesiredSize.Height * (imgdpi / DEFAULT_DPI) + 100), imgdpi, imgdpi, PixelFormat); //Render the graphlayout onto the bitmap. renderBitmap.Render(vis); //Create a file stream for saving image using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create)) { //Use png encoder for our data BitmapEncoder encoder; switch (itype) { case ImageType.PNG: encoder = new PngBitmapEncoder(); break; case ImageType.JPEG: encoder = new JpegBitmapEncoder() { QualityLevel = imgQuality }; break; case ImageType.BMP: encoder = new BmpBitmapEncoder(); break; case ImageType.GIF: encoder = new GifBitmapEncoder(); break; case ImageType.TIFF: encoder = new TiffBitmapEncoder(); break; default: throw new GX_InvalidDataException("ExportToImage() -> Unknown output image format specified!"); } //Push the rendered bitmap to it encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); //Save the data to the stream encoder.Save(outStream); } renderBitmap.Clear(); renderBitmap = null; //due to mem leak in wpf :( GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); if (!useZoomControlSurface) { surface.SetPrintMode(false, true, 100); } }
private static void OnDragging(object sender, PointerRoutedEventArgs e) #endif { var obj = sender as DependencyObject; if (!GetIsDragging(obj)) { return; } var area = GetAreaFromObject(obj); var pos = GetPositionInArea(area, e); double horizontalChange = pos.X - GetOriginalMouseX(obj); double verticalChange = pos.Y - GetOriginalMouseY(obj); // Determine whether to use snapping bool snap = GetIsSnappingPredicate(obj)(obj); bool individualSnap = false; // Snap modifier functions to apply to the primary dragged object SnapModifierFunc snapXMod = null; SnapModifierFunc snapYMod = null; // Snap modifier functions to apply to other dragged objects if they snap individually instead of moving // the same amounts as the primary object. SnapModifierFunc individualSnapXMod = null; SnapModifierFunc individualSnapYMod = null; if (snap) { snapXMod = GetXSnapModifier(obj); snapYMod = GetYSnapModifier(obj); // If objects snap to grid individually instead of moving the same amount as the primary dragged object, // use the same snap modifier on each individual object. individualSnap = GetIsIndividualSnappingPredicate(obj)(obj); if (individualSnap) { individualSnapXMod = snapXMod; individualSnapYMod = snapYMod; } } if (GetIsTagged(obj)) { // When the dragged item is a tagged item, we could be dragging a group of objects. If the dragged object is a vertex, it's // automatically the primary object of the drag. If the dragged object is an edge, prefer the source vertex, but accept the // target vertex as the primary object of the drag and start with that. var primaryDragVertex = obj as VertexControl; if (primaryDragVertex == null) { var ec = obj as EdgeControl; if (ec != null) { primaryDragVertex = ec.Source ?? ec.Target; } if (primaryDragVertex == null) { Debug.WriteLine("OnDragging() -> Tagged and dragged the wrong object?"); return; } } UpdateCoordinates(area, primaryDragVertex, horizontalChange, verticalChange, snapXMod, snapYMod); if (!individualSnap) { // When dragging groups of objects that all move the same amount (not snapping individually, but tracking with // the movement of the primary dragged object), deterrmine how much offset the primary dragged object experienced // and use that offset for the rest. horizontalChange = GraphAreaBase.GetFinalX(primaryDragVertex) - GetOriginalX(primaryDragVertex); verticalChange = GraphAreaBase.GetFinalY(primaryDragVertex) - GetOriginalY(primaryDragVertex); } foreach (var item in area.GetAllVertexControls()) { if (!ReferenceEquals(item, primaryDragVertex) && GetIsTagged(item)) { UpdateCoordinates(area, item, horizontalChange, verticalChange, individualSnapXMod, individualSnapYMod); } } } else { UpdateCoordinates(area, obj, horizontalChange, verticalChange, snapXMod, snapYMod); } e.Handled = true; }
private static Point GetPositionInArea(GraphAreaBase area, System.Windows.Input.MouseEventArgs e)
/// <summary> /// Create and apply edge path using calculated ER parameters stored in edge /// </summary> /// <param name="useCurrentCoords">Use current vertices coordinates or final coorfinates (for.ex if move animation is active final coords will be its destination)</param> /// <param name="externalRoutingPoints">Provided custom routing points will be used instead of stored ones.</param> /// <param name="updateLabel">Should edge label be updated in this pass</param> public virtual void PrepareEdgePath(bool useCurrentCoords = false, Measure.Point[] externalRoutingPoints = null, bool updateLabel = true) { //do not calculate invisible edges if ((Visibility != Visibility.Visible && !IsHiddenEdgesUpdated) && Source == null || Target == null || ManualDrawing || !IsTemplateLoaded) { return; } #region Get the inputs //get the size of the source var sourceSize = new Size { Width = Source.ActualWidth, Height = Source.ActualHeight }; if (CustomHelper.IsInDesignMode(this)) { sourceSize = new Size(80, 20); } //get the position center of the source var sourcePos = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Source) : GraphAreaBase.GetFinalX(Source)) + sourceSize.Width * .5, Y = (useCurrentCoords ? GraphAreaBase.GetY(Source) : GraphAreaBase.GetFinalY(Source)) + sourceSize.Height * .5 }; //get the size of the target var targetSize = new Size { Width = Target.ActualWidth, Height = Target.ActualHeight }; if (CustomHelper.IsInDesignMode(this)) { targetSize = new Size(80, 20); } //get the position center of the target var targetPos = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Target) : GraphAreaBase.GetFinalX(Target)) + targetSize.Width * .5, Y = (useCurrentCoords ? GraphAreaBase.GetY(Target) : GraphAreaBase.GetFinalY(Target)) + targetSize.Height * .5 }; var routedEdge = Edge as IRoutingInfo; if (routedEdge == null) { throw new GX_InvalidDataException("Edge must implement IRoutingInfo interface"); } //get the route informations var routeInformation = externalRoutingPoints ?? routedEdge.RoutingPoints; // Get the TopLeft position of the Source Vertex. var sourcePos1 = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Source) : GraphAreaBase.GetFinalX(Source)), Y = (useCurrentCoords ? GraphAreaBase.GetY(Source) : GraphAreaBase.GetFinalY(Source)) }; // Get the TopLeft position of the Target Vertex. var targetPos1 = new Point { X = (useCurrentCoords ? GraphAreaBase.GetX(Target) : GraphAreaBase.GetFinalX(Target)), Y = (useCurrentCoords ? GraphAreaBase.GetY(Target) : GraphAreaBase.GetFinalY(Target)) }; var hasEpSource = _edgePointerForSource != null; var hasEpTarget = _edgePointerForTarget != null; #endregion //if self looped edge if (IsSelfLooped) { PrepareSelfLoopedEdge(sourcePos1); return; } //check if we have some edge route data var hasRouteInfo = routeInformation != null && routeInformation.Length > 1; //calculate source and target edge attach points if (RootArea != null && !hasRouteInfo && RootArea.EnableParallelEdges && ParallelEdgeOffset != 0) { sourcePos = GetParallelOffset(Source, Target, ParallelEdgeOffset); targetPos = GetParallelOffset(Target, Source, -ParallelEdgeOffset); } /* Rectangular shapes implementation by bleibold */ var gEdge = Edge as IGraphXCommonEdge; Point p1; Point p2; //calculate edge source (p1) and target (p2) endpoints based on different settings if (gEdge != null && gEdge.SourceConnectionPointId.HasValue) { var sourceCp = Source.GetConnectionPointById(gEdge.SourceConnectionPointId.Value, true); if (sourceCp == null) { throw new GX_ObjectNotFoundException(string.Format("Can't find source vertex VCP by edge source connection point Id({1}) : {0}", Source, gEdge.SourceConnectionPointId)); } if (sourceCp.Shape == VertexShape.None) { p1 = sourceCp.RectangularSize.Center(); } else { var targetCpPos = gEdge.TargetConnectionPointId.HasValue ? Target.GetConnectionPointById(gEdge.TargetConnectionPointId.Value, true).RectangularSize.Center() : (hasRouteInfo ? routeInformation[1].ToWindows() : (targetPos)); p1 = GeometryHelper.GetEdgeEndpoint(sourceCp.RectangularSize.Center(), sourceCp.RectangularSize, targetCpPos, sourceCp.Shape); } } else { p1 = GeometryHelper.GetEdgeEndpoint(sourcePos, new SysRect(sourcePos1, sourceSize), (hasRouteInfo ? routeInformation[1].ToWindows() : (targetPos)), Source.VertexShape); } if (gEdge != null && gEdge.TargetConnectionPointId.HasValue) { var targetCp = Target.GetConnectionPointById(gEdge.TargetConnectionPointId.Value, true); if (targetCp == null) { throw new GX_ObjectNotFoundException(string.Format("Can't find target vertex VCP by edge target connection point Id({1}) : {0}", Target, gEdge.TargetConnectionPointId)); } if (targetCp.Shape == VertexShape.None) { p2 = targetCp.RectangularSize.Center(); } else { var sourceCpPos = gEdge.SourceConnectionPointId.HasValue ? Source.GetConnectionPointById(gEdge.SourceConnectionPointId.Value, true).RectangularSize.Center() : hasRouteInfo ? routeInformation[routeInformation.Length - 2].ToWindows() : (sourcePos); p2 = GeometryHelper.GetEdgeEndpoint(targetCp.RectangularSize.Center(), targetCp.RectangularSize, sourceCpPos, targetCp.Shape); } } else { p2 = GeometryHelper.GetEdgeEndpoint(targetPos, new SysRect(targetPos1, targetSize), hasRouteInfo ? routeInformation[routeInformation.Length - 2].ToWindows() : (sourcePos), Target.VertexShape); } SourceConnectionPoint = p1; TargetConnectionPoint = p2; _linegeometry = new PathGeometry(); PathFigure lineFigure; //if we have route and route consist of 2 or more points if (RootArea != null && hasRouteInfo) { //replace start and end points with accurate ones var routePoints = routeInformation.ToWindows().ToList(); routePoints.Remove(routePoints.First()); routePoints.Remove(routePoints.Last()); routePoints.Insert(0, p1); routePoints.Add(p2); if (RootArea.EdgeCurvingEnabled) { var oPolyLineSegment = GeometryHelper.GetCurveThroughPoints(routePoints.ToArray(), 0.5, RootArea.EdgeCurvingTolerance); if (hasEpTarget) { UpdateTargetEpData(oPolyLineSegment.Points[oPolyLineSegment.Points.Count - 1], oPolyLineSegment.Points[oPolyLineSegment.Points.Count - 2]); oPolyLineSegment.Points.RemoveAt(oPolyLineSegment.Points.Count - 1); } if (hasEpSource) { UpdateSourceEpData(oPolyLineSegment.Points.First(), oPolyLineSegment.Points[1]); } lineFigure = GeometryHelper.GetPathFigureFromPathSegments(routePoints[0], true, true, oPolyLineSegment); #if WPF //freeze and create resulting geometry GeometryHelper.TryFreeze(oPolyLineSegment); #endif } else { if (hasEpSource) { UpdateSourceEpData(routePoints.First(), routePoints[1]); } if (hasEpTarget) { routePoints[routePoints.Count - 1] = routePoints[routePoints.Count - 1].Subtract(UpdateTargetEpData(p2, routePoints[routePoints.Count - 2])); } var pcol = new PointCollection(); foreach (var item in routePoints) { pcol.Add(item); } lineFigure = new PathFigure { StartPoint = p1, Segments = new PathSegmentCollection { new PolyLineSegment { Points = pcol } }, IsClosed = false }; } } else // no route defined { if (hasEpSource) { UpdateSourceEpData(p1, p2); } if (hasEpTarget) { p2 = p2.Subtract(UpdateTargetEpData(p2, p1)); } lineFigure = new PathFigure { StartPoint = p1, Segments = new PathSegmentCollection { new LineSegment() { Point = p2 } }, IsClosed = false }; } ((PathGeometry)_linegeometry).Figures.Add(lineFigure); #if WPF GeometryHelper.TryFreeze(lineFigure); GeometryHelper.TryFreeze(_linegeometry); #endif if (ShowLabel && _edgeLabelControl != null && _updateLabelPosition && updateLabel) { _edgeLabelControl.UpdatePosition(); } }
/// <summary> /// Automaticaly update edge label position /// </summary> public virtual void UpdatePosition() { if (double.IsNaN(DesiredSize.Width) || DesiredSize.Width == 0) { return; } if (EdgeControl == null) { return; } if (EdgeControl.Source == null || EdgeControl.Target == null) { Debug.WriteLine("EdgeLabelControl_LayoutUpdated() -> Got empty edgecontrol!"); return; } //if hidden if (Visibility != Visibility.Visible) { return; } if (EdgeControl.IsSelfLooped) { var idesiredSize = DesiredSize; var pt = EdgeControl.Source.GetCenterPosition(); SetSelfLoopedSize(pt, idesiredSize); Arrange(LastKnownRectSize); return; } var p1 = EdgeControl.SourceConnectionPoint.GetValueOrDefault(); var p2 = EdgeControl.TargetConnectionPoint.GetValueOrDefault(); double edgeLength = 0; var routingInfo = EdgeControl.Edge as IRoutingInfo; if (routingInfo != null) { var routePoints = routingInfo.RoutingPoints == null ? null : routingInfo.RoutingPoints.ToWindows(); if (routePoints == null || routePoints.Length == 0) { // the edge is a single segment (p1,p2) edgeLength = GetLabelDistance(MathHelper.GetDistanceBetweenPoints(p1, p2)); } else { // the edge has one or more segments // compute the total length of all the segments edgeLength = 0; var rplen = routePoints.Length; for (var i = 0; i <= rplen; ++i) { if (i == 0) { edgeLength += MathHelper.GetDistanceBetweenPoints(p1, routePoints[0]); } else if (i == rplen) { edgeLength += MathHelper.GetDistanceBetweenPoints(routePoints[rplen - 1], p2); } else { edgeLength += MathHelper.GetDistanceBetweenPoints(routePoints[i - 1], routePoints[i]); } } // find the line segment where the half distance is located edgeLength = GetLabelDistance(edgeLength); var newp1 = p1; var newp2 = p2; for (var i = 0; i <= rplen; ++i) { double lengthOfSegment; if (i == 0) { lengthOfSegment = MathHelper.GetDistanceBetweenPoints(newp1 = p1, newp2 = routePoints[0]); } else if (i == rplen) { lengthOfSegment = MathHelper.GetDistanceBetweenPoints(newp1 = routePoints[rplen - 1], newp2 = p2); } else { lengthOfSegment = MathHelper.GetDistanceBetweenPoints(newp1 = routePoints[i - 1], newp2 = routePoints[i]); } if (lengthOfSegment >= edgeLength) { break; } edgeLength -= lengthOfSegment; } // redefine our edge points p1 = newp1; p2 = newp2; } } // The label control should be laid out on a rectangle, in the middle of the edge var angleBetweenPoints = MathHelper.GetAngleBetweenPoints(p1, p2); var desiredSize = DesiredSize; bool flipAxis = p1.X > p2.X; // Flip axis if source is "after" target ApplyLabelHorizontalOffset(edgeLength, LabelHorizontalOffset); // Calculate the center point of the edge var centerPoint = new Point(p1.X + edgeLength * Math.Cos(angleBetweenPoints), p1.Y - edgeLength * Math.Sin(angleBetweenPoints)); if (AlignToEdge) { // If we're aligning labels to the edges make sure add the label vertical offset var yEdgeOffset = LabelVerticalOffset; if (FlipOnRotation && flipAxis && !EdgeControl.IsParallel) // If we've flipped axis, move the offset to the other side of the edge { yEdgeOffset = -yEdgeOffset; } // Adjust offset for rotation. Remember, the offset is perpendicular from the edge tangent. // Slap on 90 degrees to the angle between the points, to get the direction of the offset. centerPoint.Y -= yEdgeOffset * Math.Sin(angleBetweenPoints + Math.PI / 2); centerPoint.X += yEdgeOffset * Math.Cos(angleBetweenPoints + Math.PI / 2); // Angle is in degrees Angle = -angleBetweenPoints * 180 / Math.PI; if (flipAxis) { Angle += 180; // Reorient the label so that it's always "pointing north" } } UpdateFinalPosition(centerPoint, desiredSize); #if METRO GraphAreaBase.SetX(this, LastKnownRectSize.X, true); GraphAreaBase.SetY(this, LastKnownRectSize.Y, true); #else Arrange(LastKnownRectSize); #endif }