Ejemplo n.º 1
0
		/// <summary>
		/// allocates larger grid arrays if necessary
		/// </summary>
		internal void allocate(int cols, int rows, RectangleF bounds, Arrow arrow)
		{
			int curCols = 0;
			int curRows = 0;

			if (costGrid != null)
			{
				curCols = costGrid.GetLength(0);
				curRows = costGrid.GetLength(1);
			}

			// allocate new arrays if needed
			if (costGrid == null || curCols < cols || curRows < rows)
			{
				int newCols = Math.Max(curCols, cols);
				int newRows = Math.Max(curRows, rows);

				costGrid = new byte[newCols, newRows];
				closedGrid = new PathNode[newCols, newRows];
				openGrid = new PathNode[newCols, newRows];
			}
			//or reuse the existing ones
			else
			{
				Array.Clear(costGrid, 0, costGrid.Length);
				Array.Clear(closedGrid, 0, closedGrid.Length);
				Array.Clear(openGrid, 0, openGrid.Length);
			}

			// mark border lines as obstacles
			for (int c = 0; c < cols; c++)
			{
				costGrid[c, 0] = 255;
				costGrid[c, rows - 1] = 255;
			}
			for (int r = 1; r < rows - 1; r++)
			{
				costGrid[0, r] = 255;
				costGrid[cols - 1, r] = 255;
			}

			// mark node locations
			markObstacles(bounds, arrow, cols, rows);
		}
Ejemplo n.º 2
0
		internal virtual PointF getAnchor(PointF pt,
			Arrow arrow, bool incm, ref int idx)
		{
			return getNode().getAnchor(pt, arrow, incm, ref idx);
		}
Ejemplo n.º 3
0
		// invoked when an arrow is drawn from / to a table.
		// finds the anchor point nearest to arrow's end point.
		// tables need special handling to combine row's and table's anchor patterns
		internal override PointF getNearestAnchor(PointF pt,
			Arrow arrow, bool incoming, ref int anchorIdx)
		{
			PointF nearestPt = pt;
			anchorIdx = -1;

			// check if at that position, an arrow would link to a row
			lastAnchorForTable = false;
			int row = rowFromPt(pt);
			if(row == -1)
			{
				// it seems not, so use Table's anchor pattern, not Row's one
				PointF result = base.getNearestAnchor(pt, arrow, incoming, ref anchorIdx);
				lastAnchorForTable = true;
				lastFoundAnchor = result;
				return result;
			}

			// link to a row, get the relevant anchor pattern for this row
			AnchorPattern rowap = getRowAnchorPattern(row);
			bool foundAp = false;

			// get row extents
			RectangleF rowRect = getRowRect(row);
			float nearestDist = 100 * Math.Max(rowRect.Width, rowRect.Height);

			if (rowap != null)
			{			
				// look for appropriate anchor points, in or out
				for (int i = 0; i < rowap.Points.Count; i++)
				{
					AnchorPoint ap = rowap.Points[i];
					if (incoming && !ap.AllowIncoming) continue;
					if (!incoming && !ap.AllowOutgoing) continue;
					if (!flowChart.validateAnchor(arrow, !incoming, this, i)) continue;
					foundAp = true;

					// how close an anchor point is to the point passed as parameter
					RectangleF testRect =
						ap.Column == -1 ? rowRect : getSpannedCellRect(row, ap.Column);
					PointF pos = ap.getPos(testRect);
					float dx = pos.X - pt.X;
					float dy = pos.Y - pt.Y;
					float ptDist = (float)Math.Sqrt(dx*dx + dy*dy);
					if (ptDist < nearestDist)
					{
						// dis closer than the others
						nearestDist = ptDist;
						nearestPt = pos;
						anchorIdx = i;
					}
				}

				if (foundAp) return nearestPt;
			}

			// haven't found suitable anchor point for this row
			if (anchorPattern != null && linkStyle != TableLinkStyle.Rows)
			{
				PointF result = base.getNearestAnchor(pt, arrow, incoming, ref anchorIdx);
				lastAnchorForTable = true;
				lastFoundAnchor = result;
				return result;
			}

			if (!foundAp)
			{
				nearestDist = float.MaxValue;

				for (int r = 0; r < RowCount; ++r)
				{
					if (r == row) continue;
					rowap = getRowAnchorPattern(r);
					if (rowap == null) continue;

					// get row extents
					rowRect = getRowRect(r);

					// look for anchor points
					for (int i = 0; i < rowap.Points.Count; i++)
					{
						AnchorPoint ap = rowap.Points[i];
						if (incoming && !ap.AllowIncoming) continue;
						if (!incoming && !ap.AllowOutgoing) continue;
						if (!flowChart.validateAnchor(arrow, !incoming, this, i)) continue;

						RectangleF testRect =
							ap.Column == -1 ? rowRect : getSpannedCellRect(r, ap.Column);
						PointF pos = ap.getPos(testRect);
						float dx = pos.X - pt.X;
						float dy = pos.Y - pt.Y;
						float ptDist = (float)Math.Sqrt(dx*dx + dy*dy);
						if (ptDist < nearestDist)
						{
							nearestDist = ptDist;
							nearestPt = pos;
							anchorIdx = i;
						}
					}

				}
			}

			return nearestPt;
		}
Ejemplo n.º 4
0
		internal void addOutgoingArrow(int row, Arrow arrow)
		{
			if (rowsList == null || row >= rowsCount) return;

			ArrowCollection arrows = ((Row)rowsList[row]).OutgoingArrows;
			if (!arrows.Contains(arrow))
				arrows.Add(arrow);
		}
Ejemplo n.º 5
0
		internal override Link createLink(Arrow arrow, PointF pt, bool incoming)
		{
			return new TableLink(this, arrow, incoming, rowFromPt(pt));
		}
Ejemplo n.º 6
0
		public void Remove(Arrow a)
		{
			List.Remove(a);
		}
Ejemplo n.º 7
0
		public void Add(Arrow a)
		{
			List.Add(a);
		}
Ejemplo n.º 8
0
		internal void fireArrowRoutedEvent(Arrow arrow)
		{
			if (ArrowRouted != null)
				ArrowRouted(this, new ArrowEventArgs(arrow));
		}
Ejemplo n.º 9
0
		private ItemsAndGroups copySelection(
			FlowChart doc, bool unconnectedArrows, bool copyGroups)
		{
			if (doc.Selection.Objects.Count == 0)
				return null;

			// determine which items and groups to copy
			ChartObjectCollection items = new ChartObjectCollection();
			GroupCollection groups = new GroupCollection();
			Hashtable indexMap = new Hashtable();
			for (int i = 0; i < doc.Selection.Objects.Count; ++i)
			{
				ChartObject item = doc.Selection.Objects[i];

				// do not copy unconncted arrows if specified
				if (!unconnectedArrows && item is Arrow)
				{
					Arrow arrow = item as Arrow;
					if (!arrow.IsConnected) continue;
				}

				indexMap[item] = items.Count;
				items.Add(item);
				
				if (copyGroups && item.SubordinateGroup != null)
					groups.Add(item.SubordinateGroup);
			}

			// add subordinated group items
			foreach (Group group in groups)
			{
				foreach (ChartObject item in group.AttachedObjects)
				{
					if (!items.Contains(item))
					{
						indexMap[item] = items.Count;
						items.Add(item);
					}
				}
			}

			// copy nodes
			for (int i = 0; i < items.Count; ++i)
			{
				ChartObject item = items[i];

				if (item is Box) items[i] = new Box((Box)item);
				if (item is ControlHost) items[i] = new ControlHost((ControlHost)item);
				if (item is Table) items[i] = new Table((Table)item);
			}

			// copy arrows, linking them to node clones
			for (int i = 0; i <  items.Count; ++i)
			{
				if (items[i] is Arrow)
				{
					Arrow arrow = items[i] as Arrow;

					int srcIndex = indexMap.Contains(arrow.Origin) ?
						(int)indexMap[arrow.Origin] : -1;
					int dstIndex = indexMap.Contains(arrow.Destination) ?
						(int)indexMap[arrow.Destination] : -1;

					items[i] = new Arrow(arrow,
						srcIndex == -1 ? Dummy : items[srcIndex] as Node,
						dstIndex == -1 ? Dummy : items[dstIndex] as Node);
				}
			}

			// copy groups
			for (int i = 0; i < groups.Count; ++i)
			{
				Group group = new Group(groups[i]);
				groups[i] = group;
				group.setMainObject(items[(int)indexMap[group.MainObject]]);

				foreach (Attachment atc in group.Attachments)
				{
					atc.node = items[(int)indexMap[atc.node]] as Node;
					atc.node.putInGroup(group);
				}
				group.updateObjCol();
			}

			return new ItemsAndGroups(items, groups);
		}
Ejemplo n.º 10
0
		internal void drawArrow(Graphics g, Arrow arrow, bool shadow, PointCollection points)
		{
			if (DrawArrow != null)
				DrawArrow(this, new ArrowDrawArgs(g, arrow, shadow, points));
		}
Ejemplo n.º 11
0
		/// <summary>
		/// Determines whether a link must be rerouted.
		/// </summary>
		internal bool rerouteArrow(Arrow arrow)
		{
			if ((routingOptions.TriggerRerouting & RerouteArrows.WhenModified) != 0)
				return true;

			if ((routingOptions.TriggerRerouting & RerouteArrows.WhenIntersectNode) != 0)
			{
				RectangleF arrowRect = arrow.BoundingRect;
				for (int j = 0; j < zOrder.Count; ++j)
				{
					if (zOrder[j] is Node)
					{
						Node node = zOrder[j] as Node;
						if (node == arrow.Origin || node == arrow.Destination)
							continue;
						RectangleF rect = node.getRotatedBounds();
						if (arrowRect.IntersectsWith(rect))
						{
							if (arrow.Intersects(node))
								return true;

						}	// if (arrowRect.IntersectsWith(rect))

					}	// if (zOrder[j] is Node)

				}	// for (int j = 0; j < zOrder.Count; ++j)
			}

			return false;
		}
Ejemplo n.º 12
0
		/// <summary>
		/// Creates a new Arrow instance and adds it to the flowchart.
		/// </summary>
		/// <param name="src">Specifies the origin point.</param>
		/// <param name="dest">Specifies the destination point.</param>
		/// <returns>A reference to the new arrow.</returns>
		public Arrow CreateArrow(PointF src, PointF dest)
		{
			// create the arrow instance and add it to the chart
			Arrow newArrow = new Arrow(this, src, dest);
			Add(newArrow, SelectAfterCreate);
			return newArrow;
		}
Ejemplo n.º 13
0
		/// <summary>
		/// Creates a new Arrow instance and adds it to the flowchart.
		/// </summary>
		/// <param name="src">Specifies the origin point.</param>
		/// <param name="dest">Specifies the destination node.</param>
		/// <returns>A reference to the new arrow.</returns>
		public Arrow CreateArrow(PointF src, Node dest)
		{
			if (dest == null) return null;

			// create the arrow instance and add it to the chart
			Arrow newArrow = new Arrow(this, src, dest);
			Add(newArrow, SelectAfterCreate);
			return newArrow;
		}
Ejemplo n.º 14
0
		/// <summary>
		/// Creates a new Arrow instance and adds it to the flowchart.
		/// </summary>
		/// <param name="srcTable">Specifies the origin table.</param>
		/// <param name="srcRow">Specifies the origin row.</param>
		/// <param name="dstNode">Specifies the destination node.</param>
		/// <returns>A reference to the new arrow.</returns>
		public Arrow CreateArrow(Table srcTable, int srcRow, Node dstNode)
		{
			if (srcTable == null || dstNode == null) return null;

			if (!srcTable.canHaveArrows(true) && srcRow != -1) return null;

			if (srcRow < -1 || srcRow >= srcTable.RowCount) return null;

			// create the arrow object and store it in the item array
			Arrow newArrow = new Arrow(this);
			newArrow.setOrgAndDest(
				srcTable.createLink(newArrow, false, srcRow),
				dstNode.createLink(newArrow, dstNode.getCenter(), true));

			Add(newArrow, SelectAfterCreate);

			return newArrow;
		}
Ejemplo n.º 15
0
		internal bool requestAttach(Arrow arrow, bool changingOrg, Node node)
		{
			if (ArrowAttaching != null)
			{
				PointF endPt = changingOrg ? arrow.Points[0] : arrow.Points[arrow.Points.Count - 1];
				int id = 0;
				int row = -1;
				node.getAnchor(endPt, arrow, !changingOrg, ref id);

				// get the row if attaching to table
				Table table = node as Table;
				if (table != null)
					row = table.rowFromPt(endPt);

				AttachConfirmArgs args = new AttachConfirmArgs(arrow,
					node, changingOrg, id, row);
				ArrowAttaching(this, args);

				return args.Confirm;
			}

			return true;
		}
Ejemplo n.º 16
0
		internal virtual void removeOutgoingArrow(Arrow arrow)
		{
			outgoingArrows.Remove(arrow);
		}
Ejemplo n.º 17
0
		internal bool validateAnchor(Arrow arrow, bool outgoing, Node node, int pointIndex)
		{
			if (ValidateAnchorPoint != null)
			{
				AttachConfirmArgs args = new AttachConfirmArgs(arrow,
					node, outgoing, pointIndex, 0);
				ValidateAnchorPoint(this, args);

				return args.Confirm;
			}

			return true;
		}
Ejemplo n.º 18
0
		/// <summary>
		/// mark obstacles and costs in the routing grid.
		/// </summary>
		private void markObstacles(RectangleF bounds,
			Arrow arrow, int cols, int rows)
		{
			RoutingOptions rop = flowChart.RoutingOptions;
			float gridSize = rop.GridSize;
			byte ccost = rop.CrossingCost;

			foreach (ChartObject obj in flowChart.Objects)
			{
				// if there is a crossing cost assigned, mark arrows in the route grid
				if (obj is Arrow && ccost > 0)
				{
					if (obj == arrow) continue;
					Arrow link = obj as Arrow;

					// at this time we handle only asPerpendicular links
					if (link.Style == ArrowStyle.Cascading)
					{
						PointF cp1 = link.ControlPoints[0];
						Point gp1 = new Point(
							(int)((cp1.X - bounds.Left) / gridSize),
							(int)((cp1.Y - bounds.Top) / gridSize));

						// iterate over all segments
						for (int i = 0; i < link.ControlPoints.Count - 1; ++i)
						{
							PointF cp2 = link.ControlPoints[i + 1];
							Point gp2 = new Point(
								(int)((cp2.X - bounds.Left) / gridSize),
								(int)((cp2.Y - bounds.Top) / gridSize));

							if (!gp1.Equals(gp2))
							{
								if (gp1.X == gp2.X)
								{
									// vertical segment
									if (gp1.X >= 0 && gp1.X < cols)
									{
										int miny = Math.Min(gp1.Y, gp2.Y);
										miny = Math.Max(0, miny);
										int maxy = Math.Max(gp1.Y, gp2.Y);
										maxy = Math.Min(rows - 1, maxy);
										for (int y = miny; y <= maxy; ++y)
											if (costGrid[gp1.X, y] < ccost) costGrid[gp1.X, y] = ccost;
									}
								}
								else
								{
									// horizontal segment
									if (gp1.Y >= 0 && gp1.Y < rows)
									{
										int minx = Math.Min(gp1.X, gp2.X);
										minx = Math.Max(0, minx);
										int maxx = Math.Max(gp1.X, gp2.X);
										maxx = Math.Min(cols - 1, maxx);
										for (int x = minx; x <= maxx; ++x)
											if (costGrid[x, gp1.Y] < ccost) costGrid[x, gp1.Y] = ccost;
									}
								}
							}

							gp1 = gp2;
						}
					}
					continue;
				}

				if (!(obj is Node))
					continue;

				Node node = obj as Node;
				if (!node.Obstacle)
					continue;
				if (node.MasterGroup != null && node.MasterGroup.MainObject == arrow)
					continue;

				RectangleF nodeRect = node.getRotatedBounds();

				if (bounds.IntersectsWith(nodeRect))
				{
					RectangleF intrRect = bounds;
					intrRect.Intersect(nodeRect);

					Point ptStart = new Point(
						(int)((intrRect.Left - bounds.Left) / gridSize),
						(int)((intrRect.Top - bounds.Top) / gridSize));
					Point ptEnd = new Point(
						(int)((intrRect.Right - bounds.Left) / gridSize),
						(int)((intrRect.Bottom - bounds.Top) / gridSize));

					if (ptStart.X < 0) ptStart.X = 0;
					if (ptStart.Y < 0) ptStart.Y = 0;
					if (ptEnd.X >= cols) ptEnd.X = cols - 1;
					if (ptEnd.Y >= rows) ptEnd.Y = rows - 1;

					// mark node interior as obstacle
					for (int c = ptStart.X; c <= ptEnd.X; ++c)
						for (int r = ptStart.Y; r <= ptEnd.Y; ++r)
							costGrid[c, r] = 255;

					// mark surrounding area with any cost assigned
					// going lineary down to the outside directions
					if (rop.NodeVicinityCost == 0) continue;
					for (int i = 1; i <= rop.NodeVicinitySize / gridSize; ++i)
					{
						byte cost = (byte)(rop.NodeVicinityCost / i);

						int minc = Math.Max(0, ptStart.X - i);
						int maxc = Math.Min(cols - 1, ptEnd.X + i);
						int minr = Math.Max(0, ptStart.Y - i);
						int maxr = Math.Min(rows - 1, ptEnd.Y + i);

						// top side
						int r = ptStart.Y - i;
						if (r >= 0)
						{
							for (int c = minc; c <= maxc; ++c)
								if (costGrid[c, r] < cost) costGrid[c, r] = cost;
						}

						// bottom side
						r = ptEnd.Y + i;
						if (r <= maxr)
						{
							for (int c = minc; c <= maxc; ++c)
								if (costGrid[c, r] < cost) costGrid[c, r] = cost;
						}

						// left side
						int cc = ptStart.X - i;
						if (cc >= 0)
						{
							for (r = minr; r <= maxr; ++r)
								if (costGrid[cc, r] < cost) costGrid[cc, r] = cost;
						}

						// right side
						cc = ptEnd.X + i;
						if (cc <= maxc)
						{
							for (r = minr; r <= maxr; ++r)
								if (costGrid[cc, r] < cost) costGrid[cc, r] = cost;
						}
					}
				}
			}
		}
Ejemplo n.º 19
0
		internal virtual PointF getNearestAnchor(PointF pt,
			Arrow arrow, bool incoming, ref int anchorIdx)
		{
			anchorIdx = -1;
			if (anchorPattern == null) return pt;

			if (rotation() != 0)
				pt = Utilities.rotatePointAt(pt, getCenter(), -rotation());
			PointF nearestPt = pt;

			RectangleF nodeRect = getBoundingRect();
			float nearestDist = 2 * Math.Max(nodeRect.Width, nodeRect.Height);

			for (int i = 0; i < anchorPattern.Points.Count; i++)
			{
				AnchorPoint ap = anchorPattern.Points[i];
				if (incoming && !ap.AllowIncoming) continue;
				if (!incoming && !ap.AllowOutgoing) continue;
				if (!flowChart.validateAnchor(arrow, !incoming, this, i)) continue;

				PointF pos = ap.getPos(nodeRect);
				float dx = pos.X - pt.X;
				float dy = pos.Y - pt.Y;
				float ptDist = (float)Math.Sqrt(dx*dx + dy*dy);
				if (ptDist < nearestDist)
				{
					nearestDist = ptDist;
					nearestPt = pos;
					anchorIdx = i;
				}
			}

			if (rotation() != 0)
				nearestPt = Utilities.rotatePointAt(nearestPt, getCenter(), rotation());

			return nearestPt;
		}
Ejemplo n.º 20
0
		public void Insert(int i, Arrow a)
		{
			List.Insert(i, a);
		}
Ejemplo n.º 21
0
		internal abstract Link createLink(Arrow arrow, PointF pt, bool incoming);
Ejemplo n.º 22
0
		public bool Contains(Arrow obj)
		{
			return List.Contains(obj);
		}
Ejemplo n.º 23
0
		public void AttachTo(Arrow arrow,
			AttachToArrow attType, int index)
		{
			// that returns the active composite if somebody has already created one
			CompositeCmd composite = flowChart.UndoManager.StartComposite("_fcnet_");

			Detach();
			Group masterGroup = getSubordinateGroup(arrow);

			switch (attType)
			{
				case AttachToArrow.Point:
					masterGroup.AttachToArrowPoint(this, index);
					break;
				case AttachToArrow.Segment:
					masterGroup.AttachToArrowSegment(this, index);
					break;
				case AttachToArrow.LongestHSegment:
					masterGroup.AttachToLongestHSegment(this);
					break;
			}

			if (composite != null && composite.Title == "_fcnet_")
			{
				// this is our own composite cmd
				composite.Title = "Attach";
				composite.Execute();
			}
		}
Ejemplo n.º 24
0
		internal Link createLink(Arrow arrow, bool incm, int row)
		{
			return new TableLink(this, arrow, incm, row);
		}
Ejemplo n.º 25
0
		internal void addIncomingArrow(Arrow arrow)
		{
			if (!incomingArrows.Contains(arrow))
				incomingArrows.Add(arrow);
		}
Ejemplo n.º 26
0
		internal void removeOutgoingArrow(int row, Arrow arrow)
		{
			if (rowsList == null || row >= rowsCount) return;

			foreach(Arrow a in ((Row)rowsList[row]).OutgoingArrows)
				if(a == arrow)
				{
					((Row)rowsList[row]).OutgoingArrows.Remove(a);
					return;
				}
		}
Ejemplo n.º 27
0
		internal void addOutgoingArrow(Arrow arrow)
		{
			if (!outgoingArrows.Contains(arrow))
				outgoingArrows.Add(arrow);
		}
Ejemplo n.º 28
0
		internal PointF getNearestAnchor(int row,
			PointF pt, Arrow arrow, bool incoming, ref int anchorIdx)
		{
			lastAnchorForTable = false;
			PointF nearestPt = pt;
			anchorIdx = -1;

			if (row == -1)
				return base.getNearestAnchor(pt, arrow, incoming, ref anchorIdx);

			// link to a row, get the relevant anchor pattern for this row
			AnchorPattern rowap = getRowAnchorPattern(row);

			// get row extents
			RectangleF rowRect = getRowRect(row);
			float nearestDist = 100 * Math.Max(rowRect.Width, rowRect.Height);

			if (rowap != null)
			{			
				// look for appropriate anchor points, in or out
				for (int i = 0; i < rowap.Points.Count; i++)
				{
					AnchorPoint ap = rowap.Points[i];
					if (incoming && !ap.AllowIncoming) continue;
					if (!incoming && !ap.AllowOutgoing) continue;
					if (!flowChart.validateAnchor(arrow, !incoming, this, i)) continue;

					// how close an anchor point is to the point passed as parameter
					RectangleF testRect =
						ap.Column == -1 ? rowRect : getSpannedCellRect(row, ap.Column);
					PointF pos = ap.getPos(testRect);
					float dx = pos.X - pt.X;
					float dy = pos.Y - pt.Y;
					float ptDist = (float)Math.Sqrt(dx*dx + dy*dy);
					if (ptDist < nearestDist)
					{
						// dis closer than the others
						nearestDist = ptDist;
						nearestPt = pos;
						anchorIdx = i;
					}
				}
			}

			return nearestPt;
		}
Ejemplo n.º 29
0
		internal virtual void removeIncomingArrow(Arrow arrow)
		{
			incomingArrows.Remove(arrow);
		}
Ejemplo n.º 30
0
		/// <summary>
		/// Initializes a new instance of the Link class.
		/// </summary>
		/// <param name="arrow">The arrow whose connection to a node is managed by this Link.</param>
		/// <param name="incoming">Specifies which end of the arrow is represented by this Link.</param>
		public Link(Arrow arrow, bool incoming)
		{
			this.arrow = arrow;
			this.incoming = incoming;
			this.relativePosition = new PointF(0, 0);
		}
Ejemplo n.º 31
0
        /// <summary>
        /// Converts Flowchart.NET arrow into SVG
        /// </summary>
        /// <param name="newArrow">Arrow reference</param>
        /// <returns>TRUE if successfull otherwise FALSE</returns>
        private bool CreateArrow(MindFusion.FlowChartX.Arrow newArrow)
        {
            bool   bOk = false;
            string sPath = "", sPathPart = "";
            int    iCount = 0;


            try
            {
                if (newArrow.Origin != null)
                {
                    if ((!newArrow.Origin.Visible) && (!InvisibleItems))
                    {
                        return(true);
                    }
                }

                if (newArrow.Destination != null)
                {
                    if ((!newArrow.Destination.Visible) && (!InvisibleItems))
                    {
                        return(true);
                    }
                }

                if (newArrow.Style == ArrowStyle.Bezier)
                {
                    sPath = String.Format("M{0},{1} C{2},{3} {4},{5} {6},{7} ",
                                          Unit2Pix(newArrow.ControlPoints[0].X),
                                          Unit2Pix(newArrow.ControlPoints[0].Y),
                                          Unit2Pix(newArrow.ControlPoints[1].X),
                                          Unit2Pix(newArrow.ControlPoints[1].Y),
                                          Unit2Pix(newArrow.ControlPoints[newArrow.ControlPoints.Count - 2].X),
                                          Unit2Pix(newArrow.ControlPoints[newArrow.ControlPoints.Count - 2].Y),
                                          Unit2Pix(newArrow.ControlPoints[newArrow.ControlPoints.Count - 1].X),
                                          Unit2Pix(newArrow.ControlPoints[newArrow.ControlPoints.Count - 1].Y));
                }
                else
                {
                    sPath = String.Format("M{0},{1} ", Unit2Pix(newArrow.ControlPoints[0].X), Unit2Pix(newArrow.ControlPoints[0].Y));

                    for (iCount = 1; iCount < newArrow.ControlPoints.Count; iCount++)
                    {
                        sPathPart = String.Format("L{0},{1} ", Unit2Pix(newArrow.ControlPoints[iCount].X), Unit2Pix(newArrow.ControlPoints[iCount].Y));
                        sPath    += sPathPart;
                    }
                }
                if (sPath == "")
                {
                    return(false);
                }

                sPath = sPath.TrimEnd();
                string sWidth = "1px";
                if (newArrow.Pen.Width != 0)
                {
                    String.Format("{0}px", Unit2Pix(newArrow.Pen.Width));
                }

                sMan.AddPath(sPath, sWidth, newArrow.PenColor, Color.Transparent);


                sPath = "";
                sPath = sMan.GetArrowHead(newArrow.HeadShape);
                XmlNode last_node = sMan.AddPath(sPath, sWidth, newArrow.PenColor, newArrow.PenColor);

                sPath     = "";
                sPath     = sMan.GetArrowHead(newArrow.BaseShape);
                last_node = sMan.AddPath(sPath, sWidth, newArrow.PenColor, newArrow.PenColor);

                RectangleF rect  = RectangleF.Empty;
                float      angle = 0;

                rect = getTextRect(System.Drawing.Graphics.FromHwnd(SvgManager.GetActiveWindow()), newArrow.Style, newArrow.TextStyle,
                                   newArrow.ControlPoints, newArrow.TextColor, newArrow.SegmentCount, newArrow.Text, newArrow.Font,
                                   RectangleF.Empty, ref angle);

                if (!rect.Equals(RectangleF.Empty))
                {
                    StringFormat sf = new StringFormat();
                    sf.Alignment = StringAlignment.Center;

                    XmlNode text_added = sMan.AddText(null, newArrow.Text,
                                                      newArrow.Font,
                                                      rect,
                                                      newArrow.TextColor, sf, false, angle);
                }
                bOk = true;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(String.Format("{0} error {1}\n", "CreateArrow", ex.Message));
                bOk = false;
            }

            return(bOk);
        }