Bugfix : Zooming works correct, no more errors on screen.
[xara-cairo.git] / wxOil / sgldrag.cpp
bloba92293e73b53f3b27939018a6d1012e3cb211089
1 // $Id: sgldrag.cpp 1282 2006-06-09 09:46:49Z alex $
2 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
3 ================================XARAHEADERSTART===========================
5 Xara LX, a vector drawing and manipulation program.
6 Copyright (C) 1993-2006 Xara Group Ltd.
7 Copyright on certain contributions may be held in joint with their
8 respective authors. See AUTHORS file for details.
10 LICENSE TO USE AND MODIFY SOFTWARE
11 ----------------------------------
13 This file is part of Xara LX.
15 Xara LX is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License version 2 as published
17 by the Free Software Foundation.
19 Xara LX and its component source files are distributed in the hope
20 that it will be useful, but WITHOUT ANY WARRANTY; without even the
21 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License along
25 with Xara LX (see the file GPL in the root directory of the
26 distribution); if not, write to the Free Software Foundation, Inc., 51
27 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 ADDITIONAL RIGHTS
31 -----------------
33 Conditional upon your continuing compliance with the GNU General Public
34 License described above, Xara Group Ltd grants to you certain additional
35 rights.
37 The additional rights are to use, modify, and distribute the software
38 together with the wxWidgets library, the wxXtra library, and the "CDraw"
39 library and any other such library that any version of Xara LX relased
40 by Xara Group Ltd requires in order to compile and execute, including
41 the static linking of that library to XaraLX. In the case of the
42 "CDraw" library, you may satisfy obligation under the GNU General Public
43 License to provide source code by providing a binary copy of the library
44 concerned and a copy of the license accompanying it.
46 Nothing in this section restricts any of the rights you have under
47 the GNU General Public License.
50 SCOPE OF LICENSE
51 ----------------
53 This license applies to this program (XaraLX) and its constituent source
54 files only, and does not necessarily apply to other Xara products which may
55 in part share the same code base, and are subject to their own licensing
56 terms.
58 This license does not apply to files in the wxXtra directory, which
59 are built into a separate library, and are subject to the wxWindows
60 license contained within that directory in the file "WXXTRA-LICENSE".
62 This license does not apply to the binary libraries (if any) within
63 the "libs" directory, which are subject to a separate license contained
64 within that directory in the file "LIBS-LICENSE".
67 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
68 ----------------------------------------------
70 Subject to the terms of the GNU Public License (see above), you are
71 free to do whatever you like with your modifications. However, you may
72 (at your option) wish contribute them to Xara's source tree. You can
73 find details of how to do this at:
74 http://www.xaraxtreme.org/developers/
76 Prior to contributing your modifications, you will need to complete our
77 contributor agreement. This can be found at:
78 http://www.xaraxtreme.org/developers/contribute/
80 Please note that Xara will not accept modifications which modify any of
81 the text between the start and end of this header (marked
82 XARAHEADERSTART and XARAHEADEREND).
85 MARKS
86 -----
88 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
89 designs are registered or unregistered trademarks, design-marks, and/or
90 service marks of Xara Group Ltd. All rights in these marks are reserved.
93 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
94 http://www.xara.com/
96 =================================XARAHEADEREND============================
98 // sgldrag.cpp - Line gallery item dragging
100 #include "camtypes.h"
102 #include "sgldrag.h"
103 #include "dragmgr.h"
104 #include "dragbmp.h"
105 //#include "viewrc.h"
106 //#include "resource.h"
107 #include "camview.h"
108 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
109 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
110 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
111 #include "grndbmp.h"
112 #include "nodepath.h"
113 #include "lineattr.h"
114 #include "sgline.h"
115 #include "osrndrgn.h"
117 //#include "richard2.h" // string resources
119 // Implement the dynamic class bits...
120 CC_IMPLEMENT_DYNCREATE(GalleryLineDragInfo, BitmapDragInformation)
121 CC_IMPLEMENT_DYNAMIC(SGLineDragTarget, SGListDragTarget);
123 // This line mustn't go before any CC_IMPLEMENT_... macros
124 #define new CAM_DEBUG_NEW
126 // This determines where, if at all, the text description of a dragged line gallery item
127 // will be displayed.
128 const LineAttrItem::TextPosition c_eLineAttrDragTextPos = LineAttrItem::NO_LABEL;
131 /********************************************************************************************
133 > SGLineDragTarget::SGLineDragTarget(DialogOp *TheDialog, CGadgetID TheGadget = NULL)
135 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
136 Created: 10/4/95
137 Inputs: TheDialog - The kernel dialog in which the target exists
138 TheGadget - The gadget within that dialogue which is the target
140 Purpose: Constructor
142 ********************************************************************************************/
144 SGLineDragTarget::SGLineDragTarget(DialogOp *TheDialog, CGadgetID TheGadget)
145 : SGListDragTarget(TheDialog, TheGadget)
147 ERROR3IF(!TheDialog->IsKindOf(CC_RUNTIME_CLASS(LineGallery)),
148 "You can only use SGLineDragTargets with LineGallery dialogues!");
153 /********************************************************************************************
155 BOOL SGLineDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo,
156 OilCoord *pMousePos, KeyPress* pKeyPress)
158 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
159 Created: 10/4/95
160 Inputs: Event - Indicates what has happened
161 pDragInfo - points to drag information describing this drag. This
162 should be a BitmapDragInformation or derivation thereof
163 pMousePos - points to information on the current mouse position, in OIL coords
164 pKeyPress - NULL, or if for a keypress event, keypress information
166 Returns: TRUE to claim the event, FALSE to let it through to other targets
168 Purpose: Event Handler for SuperGallery listitem drag events. Overrides the
169 base class handler to enable it to sort out the node being dragged
170 for Line drags.
172 ********************************************************************************************/
174 BOOL SGLineDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo,
175 OilCoord *pMousePos, KeyPress* pKeyPress)
177 if (!pDragInfo->IsKindOf(CC_RUNTIME_CLASS(GalleryLineDragInfo)))
178 return(FALSE);
180 SGDisplayNode *DraggedNode = NULL;
181 BOOL IsSimpleBitmapDrag = TRUE;
183 if (IS_A(pDragInfo, GalleryLineDragInfo))
185 DraggedNode = ((GalleryLineDragInfo *)pDragInfo)->GetDraggedLineAttr();
188 if (DraggedNode != NULL)
190 switch(Event)
192 case DRAGEVENT_COMPLETED:
193 HandleDragCompleted((SuperGallery *) TargetDialog,
194 DraggedNode, pMousePos, IsSimpleBitmapDrag);
195 return(TRUE);
198 case DRAGEVENT_MOUSESTOPPED:
199 case DRAGEVENT_MOUSEMOVED:
200 case DRAGEVENT_MOUSEIDLE:
201 // Call a subroutine to work out and set our current cursor shape
202 return(DetermineCursorShape((SuperGallery *) TargetDialog,
203 DraggedNode, pMousePos));
204 default:
205 break;
209 // Otherwise, we aren't interested in the event, so we don't claim it
210 return(FALSE);
213 /********************************************************************************************
215 > void GalleryLineDragInfo::GalleryLineDragInfo()
217 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
218 Created: 10/4/95
220 Purpose: Default constructor - do not call this constructor
222 ********************************************************************************************/
224 GalleryLineDragInfo::GalleryLineDragInfo()
226 ERROR3("Default GalleryLineDragInfo constructor called");
231 /********************************************************************************************
233 > GalleryLineDragInfo::GalleryLineDragInfo(LineAttrItem *pSourceItem,
234 SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
235 BOOL IsAdjust = FALSE)
237 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
238 Created: 10/4/95
240 Inputs: pSourceItem - The gallery item from which the drag originated
241 pMouseInfo - The mouse info which made the item start the drag
242 pMiscInfo - The MiscInfo which accompanied the mouse event
243 IsAdjust - TRUE if this is an adjust (line-Bitmap) drag
245 Purpose: Constructor
247 ********************************************************************************************/
249 GalleryLineDragInfo::GalleryLineDragInfo(LineAttrItem *pSourceItem,
250 SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
251 BOOL IsAdjust)
252 : BitmapDragInformation(NULL, 100,50,0,0,
253 IsAdjust)
255 SourceItem = pSourceItem; // Copy the source item pointer
257 pAttr = SourceItem->CreateNewAttribute(IsAdjust);
259 MouseInfo = *pMouseInfo; // Duplicate the structures (they may cease to exist
260 MiscInfo = *pMiscInfo; // soon after the drag is started)
263 /********************************************************************************************
265 > GalleryLineDragInfo::~GalleryLineDragInfo()
267 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
268 Created: 10/4/95
270 Purpose: Destructor. Deletes the dragged bitmap.
272 ********************************************************************************************/
274 GalleryLineDragInfo::~GalleryLineDragInfo()
276 if (TheBitmap != NULL)
278 delete TheBitmap;
279 TheBitmap = NULL;
282 if (pAttr != NULL)
283 delete pAttr;
286 /********************************************************************************************
288 > void GalleryLineDragInfo::OnClick(INT32 Flags,POINT Point)
290 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
291 Created: 10/4/95
292 Inputs: -
293 Outputs: -
294 Returns: -
295 Purpose: This is called if a drag was attempted but never started because it was a
296 click all along. It calls back the SourceItem SGDisplayLine, to get it
297 to handle the click.
298 Errors: -
299 SeeAlso: -
301 ********************************************************************************************/
303 void GalleryLineDragInfo::OnClick(INT32 Flags ,POINT Point)
305 if (SourceItem != NULL)
306 SourceItem->DragWasReallyAClick(&MouseInfo, &MiscInfo);
309 /********************************************************************************************
311 > void GalleryLineDragInfo::GetCursorID(DragTarget* pDragTarget)
313 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
314 Created: 10/4/95
315 Purpose: Set cursor over this target
318 ********************************************************************************************/
320 UINT32 GalleryLineDragInfo::GetCursorID(DragTarget* pDragTarget)
322 if (pDragTarget && pDragTarget->IS_KIND_OF(ViewDragTarget))
324 PageDropInfo PageDropInfo;
325 ((ViewDragTarget*)pDragTarget)->GetDropInfo(&PageDropInfo);
327 NodeRenderableInk* pObjectHit = PageDropInfo.pObjectHit;
328 ObjectDragTarget TargetHit = PageDropInfo.TargetHit;
330 if (IS_A(pAttr, AttrStartArrow) || IS_A(pAttr, AttrEndArrow))
332 if (pObjectHit && pObjectHit->IS_KIND_OF(NodePath))
334 Path* pPath = &((NodePath*)pObjectHit)->InkPath;
335 BOOL IsStart;
336 if (DropStartOrEndArrow(pPath, PageDropInfo.DropPos, &IsStart))
338 TargetHit = IsStart ? STARTCOL_TARGET : ENDCOL_TARGET;
343 ClickModifiers ClickMods = ClickModifiers::GetClickModifiers();
344 BOOL IsInside = ClickMods.Constrain;
346 if (!IsInside && pObjectHit && pObjectHit->IsCompound())
348 TargetHit = MANY_TARGET;
351 switch (TargetHit)
353 case FILL_TARGET:
354 return IsInside ? _R(IDC_DROPINSIDEONLINE) : _R(IDC_CANDROPONLINE);
355 case LINE_TARGET:
356 return IsInside ? _R(IDC_DROPINSIDEONLINE) : _R(IDC_CANDROPONLINE);
357 case STARTCOL_TARGET:
358 return IsInside ? _R(IDC_DROPINSIDEONFILLSTART) : _R(IDC_CANDROPONFILLSTART);
359 case ENDCOL_TARGET:
360 return IsInside ? _R(IDC_DROPINSIDEONFILLEND) : _R(IDC_CANDROPONFILLEND);
361 case MANY_TARGET:
362 return IsInside ? _R(IDC_DROPINSIDEONLINE) : _R(IDC_CANDROPONLINE);
364 case NO_TARGET:
365 return _R(IDC_CANDROPONPAGE);
366 default:
367 break;
370 return _R(IDC_CANDROPONPAGE);
373 return _R(IDC_CANTDROP);
376 /********************************************************************************************
378 > virtual BOOL GalleryLineDragInfo::GetStatusLineText(String_256 * TheText, DragTarget* pDragTarget)
380 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
381 Created: 10/4/95
382 Returns: Whether String is valid
383 Purpose: provide status line text for this target
385 ********************************************************************************************/
387 BOOL GalleryLineDragInfo::GetStatusLineText(String_256 * TheText, DragTarget* pDragTarget)
389 ERROR2IF(TheText==NULL,FALSE,"NULL string in GetStatusLineText()");
391 if (TheBitmap == NULL || TheBitmap->ActualBitmap == NULL)
392 return FALSE;
394 String_256 DragString(_R(IDS_SGLDRAG_DRAG_LINE_ATTR)); // "Dragging line attribute"
395 DragString += String_8(_R(IDS_SGDFONTS_STAT_COLON_SEP)); //" : ";
397 if (pDragTarget && pDragTarget->IS_KIND_OF(ViewDragTarget))
399 PageDropInfo PageDropInfo;
400 ((ViewDragTarget*)pDragTarget)->GetDropInfo(&PageDropInfo);
402 NodeRenderableInk* pObjectHit = PageDropInfo.pObjectHit;
403 ObjectDragTarget TargetHit = PageDropInfo.TargetHit;
405 String_256 ObjectDesc = _R(IDS_SGLDRAG_THIS_OBJECT); // " this object";
407 if (pObjectHit)
409 ObjectDesc = pObjectHit->Describe(FALSE);
412 ClickModifiers ClickMods = ClickModifiers::GetClickModifiers();
413 BOOL IsInside = ClickMods.Constrain;
415 if (!IsInside && pObjectHit && pObjectHit->IsCompound())
417 TargetHit = MANY_TARGET;
420 switch (TargetHit)
422 case FILL_TARGET:
423 case LINE_TARGET:
424 case STARTCOL_TARGET:
425 case ENDCOL_TARGET:
426 DragString += String_64(_R(IDS_SGLDRAG_DROP_TO_APPLY)); // "Drop to apply this attribute to this ";
427 DragString += ObjectDesc;
428 if (IsInside)
429 DragString += String_64(_R(IDS_SGLDRAG_SPACE_ALONE)); // " alone";
430 break;
432 case MANY_TARGET:
433 DragString += String_64(_R(IDS_SGLDRAG_DROP_TO_APPLY)); // "Drop to apply this attribute to this ";
434 DragString += ObjectDesc;
435 DragString += String_64(_R(IDS_SGLDRAG_CONTROL_DROP_INSIDE)); // "; Press 'Control' to drop 'Inside'";
436 break;
438 case NO_TARGET:
439 DragString += String_64(_R(IDS_SGLDRAG_DROP_CURRENT_ATTRIBUTE)); // "Drop to set the Current Attribute";
440 break;
441 default:
442 break;
445 *TheText = DragString;
446 return TRUE;
449 return FALSE;
452 /********************************************************************************************
454 > BOOL GalleryBitmapDragInfo::OnPageDrop(ViewDragTarget* pDragTarget)
456 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
457 Created: 10/4/95
458 Inputs: -
459 Outputs: -
460 Returns: -
461 Purpose: Called when a Line Attr is dropped onto the page.
462 Errors: -
463 SeeAlso: -
465 ********************************************************************************************/
467 BOOL GalleryLineDragInfo::OnPageDrop(ViewDragTarget* pDragTarget)
469 PageDropInfo PageDropInfo;
470 ((ViewDragTarget*)pDragTarget)->GetDropInfo(&PageDropInfo);
471 NodeRenderableInk* pObjectHit = PageDropInfo.pObjectHit;
473 NodeAttribute* Attrib = SourceItem->CreateNewAttribute(IsAnAdjustDrag());
475 if (Attrib == NULL)
476 return FALSE;
478 if (pObjectHit && (IS_A(Attrib, AttrStartArrow) || IS_A(Attrib, AttrEndArrow)))
480 if (!pObjectHit->IS_KIND_OF(NodePath))
482 delete Attrib;
483 return FALSE;
486 Path* pPath = &((NodePath*)pObjectHit)->InkPath;
487 BOOL IsStart;
489 if (!DropStartOrEndArrow(pPath, PageDropInfo.DropPos, &IsStart))
491 delete Attrib;
492 return FALSE;
495 Attrib = MakeStartOrEndArrow(Attrib, IsStart);
498 if (pObjectHit)
500 // Hit a Line Object, so apply attribute to it
501 AttributeManager::ApplyAttribToNode(pObjectHit, Attrib);
503 else
505 // Didn't hit anything, so just set the current attribute
506 AttributeManager::AttributeSelected(Attrib);
509 return TRUE;
513 /********************************************************************************************
515 > INT32 GalleryLineDragInfo::GetDragTransparency()
517 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
518 Created: 10/4/95
519 Returns: -
520 Purpose: Specifies how transparent a drag should be.
521 A value of 0, will cause a normal solid blit.
522 Any other value (between 0 and 100), will cause a masked blit.
523 SeeAlso: -
525 ********************************************************************************************/
527 INT32 GalleryLineDragInfo::GetDragTransparency()
529 // if (IS_A(pAttr, AttrStartArrow) || IS_A(pAttr, AttrEndArrow))
530 // return 50;
532 return 50;
535 /********************************************************************************************
537 > KernelBitmap* GalleryLineDragInfo::GetSolidDragMask()
539 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
540 Created: 10/4/95
541 Returns: -
542 Purpose: Makes a 1bpp KernelBitmap mask for the solid drag.
543 SeeAlso: -
545 ********************************************************************************************/
547 KernelBitmap* GalleryLineDragInfo::GetSolidDragMask()
549 // Note we abuse this call (like our base class abuses this call) to create the bitmap
550 // itself. We don't use DragMask itself anymore (i.e. it stays NULL)
551 if (!DragMask && !TheBitmap)
553 DocView *View = DocView::GetCurrent();
554 if (View == NULL)
556 return NULL;
559 Spread *pSpread = View->FindEnclosingSpread(OilCoord(0,0));
560 if (pSpread == NULL)
562 return NULL;
565 // Find the size of the rendered item.
566 DocRect ClipRegion(0,0, 750*100, 750*50);
567 // ClipRegion.lo.x = ClipRegion.lo.y = 0;
568 // SourceItem->GetSize(c_eLineAttrDragTextPos, &ClipRegion.hi.x, &ClipRegion.hi.y);
569 Matrix ConvertMatrix;
570 FIXED16 ViewScale = 1;
572 wxScreenDC DisplayDC;
573 double dpi = (double) OSRenderRegion::GetFixedDCPPI(DisplayDC).GetWidth();
575 GRenderBitmap* pMaskRegion = new GRenderBitmap(ClipRegion, ConvertMatrix, ViewScale,
576 32, dpi);
578 pMaskRegion->SetDoCompression(TRUE); // misnamed call to indicate we want transparency
579 pMaskRegion->AttachDevice(View, &DisplayDC, pSpread);
581 // Make a Mask Bitmap
582 pMaskRegion->StartRender();
583 SourceItem->Render(pMaskRegion, ClipRegion, c_eLineAttrDragTextPos);
584 pMaskRegion->StopRender();
586 OILBitmap* pOilMaskBmp = pMaskRegion->ExtractBitmap();
587 TheBitmap = new KernelBitmap(pOilMaskBmp, TRUE);
589 delete pMaskRegion;
592 return BitmapDragInformation::GetSolidDragMask();
595 /********************************************************************************************
597 > BOOL GalleryLineDragInfo::DropStartOrEndArrow(Path* pPathHit, DocCoord DropPos,
598 BOOL* IsStart)
600 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
601 Created: 10/4/95
602 Returns: -
603 Purpose: Checks to see whether the arrow was dropped nearer to the start or end of
604 a path.
605 SeeAlso: -
607 ********************************************************************************************/
609 BOOL GalleryLineDragInfo::DropStartOrEndArrow(Path* pPathHit, DocCoord DropPos,
610 BOOL* IsStart)
612 double NearestDist = -1;
613 BOOL GotNearest = FALSE;
614 BOOL NearestIsStart = FALSE;
616 DocCoord* Coords = pPathHit->GetCoordArray();
617 PathVerb* Verbs = pPathHit->GetVerbArray();
618 INT32 NumCoords = pPathHit->GetNumCoords();
620 DocCoord ArrowCentre;
621 DocCoord ArrowDirection;
623 INT32 PathIndex = 0;
625 // Find the first position of an ArrowHead
626 BOOL GotPos = ArrowRec::GetFirstArrowPos(TRUE,
627 Coords, Verbs, NumCoords,
628 &PathIndex, &ArrowCentre, &ArrowDirection);
629 while (GotPos)
631 double Dist = ArrowCentre.Distance(DropPos);
633 if (NearestDist == -1 || Dist < NearestDist)
635 NearestDist = Dist;
636 GotNearest = TRUE;
637 NearestIsStart = TRUE;
640 // Find the next Arrow position (if there are any more subpaths)
641 GotPos = ArrowRec::GetNextArrowPos(TRUE,
642 Coords, Verbs, NumCoords,
643 &PathIndex, &ArrowCentre, &ArrowDirection);
646 // Now test all the end positions
647 PathIndex = 0;
649 // Find the first position of an ArrowHead
650 GotPos = ArrowRec::GetFirstArrowPos(FALSE,
651 Coords, Verbs, NumCoords,
652 &PathIndex, &ArrowCentre, &ArrowDirection);
653 while (GotPos)
655 double Dist = ArrowCentre.Distance(DropPos);
657 if (NearestDist == -1 || Dist < NearestDist)
659 NearestDist = Dist;
660 GotNearest = TRUE;
661 NearestIsStart = FALSE;
664 // Find the next Arrow position (if there are any more subpaths)
665 GotPos = ArrowRec::GetNextArrowPos(FALSE,
666 Coords, Verbs, NumCoords,
667 &PathIndex, &ArrowCentre, &ArrowDirection);
670 if (GotNearest)
671 *IsStart = NearestIsStart;
673 return GotNearest;
676 /********************************************************************************************
678 > NodeAttribute* GalleryLineDragInfo::MakeStartOrEndArrow(NodeAttribute* pArrowAttr, BOOL Start)
680 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
681 Created: 10/4/95
682 Returns: -
683 Purpose: Makes a Start or End arrow depending on where the arrow was dropped.
684 SeeAlso: -
686 ********************************************************************************************/
688 NodeAttribute* GalleryLineDragInfo::MakeStartOrEndArrow(NodeAttribute* pArrowAttr, BOOL Start)
690 ArrowRec Arrow;
691 NodeAttribute* NewAttr;
693 if (IS_A(pArrowAttr, AttrStartArrow))
695 Arrow = ((AttrStartArrow*)pArrowAttr)->Value.StartArrow;
697 else
699 Arrow = ((AttrEndArrow*)pArrowAttr)->Value.EndArrow;
702 if (Start)
704 NewAttr = new AttrStartArrow();
705 ((AttrStartArrow*)NewAttr)->Value.StartArrow = Arrow;
707 else
709 NewAttr = new AttrEndArrow();
710 ((AttrEndArrow*)NewAttr)->Value.EndArrow = Arrow;
713 delete pArrowAttr;
714 return NewAttr;