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
33 Conditional upon your continuing compliance with the GNU General Public
34 License described above, Xara Group Ltd grants to you certain additional
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.
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
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).
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.
96 =================================XARAHEADEREND============================
98 // sgldrag.cpp - Line gallery item dragging
100 #include "camtypes.h"
105 //#include "viewrc.h"
106 //#include "resource.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]
112 #include "nodepath.h"
113 #include "lineattr.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>
137 Inputs: TheDialog - The kernel dialog in which the target exists
138 TheGadget - The gadget within that dialogue which is the target
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>
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
172 ********************************************************************************************/
174 BOOL
SGLineDragTarget::ProcessEvent(DragEventType Event
, DragInformation
*pDragInfo
,
175 OilCoord
*pMousePos
, KeyPress
* pKeyPress
)
177 if (!pDragInfo
->IsKindOf(CC_RUNTIME_CLASS(GalleryLineDragInfo
)))
180 SGDisplayNode
*DraggedNode
= NULL
;
181 BOOL IsSimpleBitmapDrag
= TRUE
;
183 if (IS_A(pDragInfo
, GalleryLineDragInfo
))
185 DraggedNode
= ((GalleryLineDragInfo
*)pDragInfo
)->GetDraggedLineAttr();
188 if (DraggedNode
!= NULL
)
192 case DRAGEVENT_COMPLETED
:
193 HandleDragCompleted((SuperGallery
*) TargetDialog
,
194 DraggedNode
, pMousePos
, IsSimpleBitmapDrag
);
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
));
209 // Otherwise, we aren't interested in the event, so we don't claim it
213 /********************************************************************************************
215 > void GalleryLineDragInfo::GalleryLineDragInfo()
217 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
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>
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
247 ********************************************************************************************/
249 GalleryLineDragInfo::GalleryLineDragInfo(LineAttrItem
*pSourceItem
,
250 SGMouseInfo
*pMouseInfo
, SGMiscInfo
*pMiscInfo
,
252 : BitmapDragInformation(NULL
, 100,50,0,0,
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>
270 Purpose: Destructor. Deletes the dragged bitmap.
272 ********************************************************************************************/
274 GalleryLineDragInfo::~GalleryLineDragInfo()
276 if (TheBitmap
!= NULL
)
286 /********************************************************************************************
288 > void GalleryLineDragInfo::OnClick(INT32 Flags,POINT Point)
290 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
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
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>
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
;
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
;
354 return IsInside
? _R(IDC_DROPINSIDEONLINE
) : _R(IDC_CANDROPONLINE
);
356 return IsInside
? _R(IDC_DROPINSIDEONLINE
) : _R(IDC_CANDROPONLINE
);
357 case STARTCOL_TARGET
:
358 return IsInside
? _R(IDC_DROPINSIDEONFILLSTART
) : _R(IDC_CANDROPONFILLSTART
);
360 return IsInside
? _R(IDC_DROPINSIDEONFILLEND
) : _R(IDC_CANDROPONFILLEND
);
362 return IsInside
? _R(IDC_DROPINSIDEONLINE
) : _R(IDC_CANDROPONLINE
);
365 return _R(IDC_CANDROPONPAGE
);
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>
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
)
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";
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
;
424 case STARTCOL_TARGET
:
426 DragString
+= String_64(_R(IDS_SGLDRAG_DROP_TO_APPLY
)); // "Drop to apply this attribute to this ";
427 DragString
+= ObjectDesc
;
429 DragString
+= String_64(_R(IDS_SGLDRAG_SPACE_ALONE
)); // " alone";
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'";
439 DragString
+= String_64(_R(IDS_SGLDRAG_DROP_CURRENT_ATTRIBUTE
)); // "Drop to set the Current Attribute";
445 *TheText
= DragString
;
452 /********************************************************************************************
454 > BOOL GalleryBitmapDragInfo::OnPageDrop(ViewDragTarget* pDragTarget)
456 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
461 Purpose: Called when a Line Attr is dropped onto the page.
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());
478 if (pObjectHit
&& (IS_A(Attrib
, AttrStartArrow
) || IS_A(Attrib
, AttrEndArrow
)))
480 if (!pObjectHit
->IS_KIND_OF(NodePath
))
486 Path
* pPath
= &((NodePath
*)pObjectHit
)->InkPath
;
489 if (!DropStartOrEndArrow(pPath
, PageDropInfo
.DropPos
, &IsStart
))
495 Attrib
= MakeStartOrEndArrow(Attrib
, IsStart
);
500 // Hit a Line Object, so apply attribute to it
501 AttributeManager::ApplyAttribToNode(pObjectHit
, Attrib
);
505 // Didn't hit anything, so just set the current attribute
506 AttributeManager::AttributeSelected(Attrib
);
513 /********************************************************************************************
515 > INT32 GalleryLineDragInfo::GetDragTransparency()
517 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
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.
525 ********************************************************************************************/
527 INT32
GalleryLineDragInfo::GetDragTransparency()
529 // if (IS_A(pAttr, AttrStartArrow) || IS_A(pAttr, AttrEndArrow))
535 /********************************************************************************************
537 > KernelBitmap* GalleryLineDragInfo::GetSolidDragMask()
539 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
542 Purpose: Makes a 1bpp KernelBitmap mask for the solid drag.
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();
559 Spread
*pSpread
= View
->FindEnclosingSpread(OilCoord(0,0));
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
,
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
);
592 return BitmapDragInformation::GetSolidDragMask();
595 /********************************************************************************************
597 > BOOL GalleryLineDragInfo::DropStartOrEndArrow(Path* pPathHit, DocCoord DropPos,
600 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
603 Purpose: Checks to see whether the arrow was dropped nearer to the start or end of
607 ********************************************************************************************/
609 BOOL
GalleryLineDragInfo::DropStartOrEndArrow(Path
* pPathHit
, DocCoord DropPos
,
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
;
625 // Find the first position of an ArrowHead
626 BOOL GotPos
= ArrowRec::GetFirstArrowPos(TRUE
,
627 Coords
, Verbs
, NumCoords
,
628 &PathIndex
, &ArrowCentre
, &ArrowDirection
);
631 double Dist
= ArrowCentre
.Distance(DropPos
);
633 if (NearestDist
== -1 || Dist
< NearestDist
)
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
649 // Find the first position of an ArrowHead
650 GotPos
= ArrowRec::GetFirstArrowPos(FALSE
,
651 Coords
, Verbs
, NumCoords
,
652 &PathIndex
, &ArrowCentre
, &ArrowDirection
);
655 double Dist
= ArrowCentre
.Distance(DropPos
);
657 if (NearestDist
== -1 || Dist
< NearestDist
)
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
);
671 *IsStart
= NearestIsStart
;
676 /********************************************************************************************
678 > NodeAttribute* GalleryLineDragInfo::MakeStartOrEndArrow(NodeAttribute* pArrowAttr, BOOL Start)
680 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
683 Purpose: Makes a Start or End arrow depending on where the arrow was dropped.
686 ********************************************************************************************/
688 NodeAttribute
* GalleryLineDragInfo::MakeStartOrEndArrow(NodeAttribute
* pArrowAttr
, BOOL Start
)
691 NodeAttribute
* NewAttr
;
693 if (IS_A(pArrowAttr
, AttrStartArrow
))
695 Arrow
= ((AttrStartArrow
*)pArrowAttr
)->Value
.StartArrow
;
699 Arrow
= ((AttrEndArrow
*)pArrowAttr
)->Value
.EndArrow
;
704 NewAttr
= new AttrStartArrow();
705 ((AttrStartArrow
*)NewAttr
)->Value
.StartArrow
= Arrow
;
709 NewAttr
= new AttrEndArrow();
710 ((AttrEndArrow
*)NewAttr
)->Value
.EndArrow
= Arrow
;