home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWPart / Sources / FWDrCmd.cpp < prev    next >
Encoding:
Text File  |  1996-08-16  |  20.3 KB  |  688 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWDrCmd.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWDRCMD_H
  13. #include "FWDrCmd.h"
  14. #endif
  15.  
  16. #ifndef FWINTER_H
  17. #include "FWInter.h"
  18. #endif
  19.  
  20. // ----- Framework Includes -----
  21.  
  22. #ifndef FWPART_H
  23. #include "FWPart.h"
  24. #endif
  25.  
  26. #ifndef FWFRAME_H
  27. #include "FWFrame.h"
  28. #endif
  29.  
  30. #ifndef FWDRGDRP_H
  31. #include "FWDrgDrp.h"
  32. #endif
  33.  
  34. #ifndef FWSELECT_H
  35. #include "FWSelect.h"
  36. #endif
  37.  
  38. #ifndef FWEVENT_H
  39. #include "FWEvent.h"
  40. #endif
  41.  
  42. #ifndef FWUTIL_H
  43. #include "FWUtil.h"
  44. #endif
  45.  
  46. #ifndef FWPRESEN_H
  47. #include "FWPresen.h"
  48. #endif
  49.  
  50. #ifndef FWLNKMGR_H
  51. #include "FWLnkMgr.h"
  52. #endif
  53.  
  54. #ifndef FWCONTXT_H
  55. #include "FWContxt.h"
  56. #endif
  57.  
  58. // ----- OS Layer -----
  59.  
  60. #ifndef FWMENU_K
  61. #include "FWMenu.k"
  62. #endif
  63.  
  64. #ifndef FWODGEOM_H
  65. #include "FWODGeom.h"
  66. #endif
  67.  
  68. #ifndef FWREGION_H
  69. #include "FWRegion.h"
  70. #endif
  71.  
  72. #ifndef FWBARRAY_H
  73. #include "FWBArray.h"
  74. #endif
  75.  
  76. #ifndef SLODFSTR_K
  77. #include "SLODFStr.k"
  78. #endif
  79.  
  80. #ifndef SLODFSTR_H
  81. #include "SLODFStr.h"
  82. #endif
  83.  
  84. // ----- OpenDoc Includes -----
  85.  
  86. #ifndef SOM_Module_OpenDoc_Commands_defined
  87. #include <CmdDefs.xh>
  88. #endif
  89.  
  90. #ifndef SOM_ODSession_xh
  91. #include <ODSessn.xh>
  92. #endif
  93.  
  94. #ifndef SOM_ODClipboard_xh
  95. #include <Clipbd.xh>
  96. #endif
  97.  
  98. #ifndef SOM_Module_OpenDoc_StdProps_defined
  99. #include <StdProps.xh>
  100. #endif
  101.  
  102. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  103. #include <StdTypes.xh>
  104. #endif
  105.  
  106. #ifndef SOM_ODStorageUnit_xh
  107. #include <StorageU.xh>
  108. #endif
  109.  
  110. #ifndef SOM_ODFacet_xh
  111. #include <Facet.xh>
  112. #endif
  113.  
  114. #ifndef SOM_ODDragAndDrop_xh
  115. #include <DragDrp.xh>
  116. #endif
  117.  
  118. #ifndef SOM_ODDragItemIterator_xh
  119. #include <DgItmIt.xh>
  120. #endif
  121.  
  122. #ifndef _TRANSFORM_
  123. #include <Trnsform.xh>
  124. #endif
  125.  
  126. #ifndef SOM_ODLinkSpec_xh
  127. #include <LinkSpec.xh>
  128. #endif
  129.  
  130. // ----- Macintosh Includes -----
  131.  
  132. #if defined(FW_BUILD_MAC) && !defined(__DRAG__)
  133. #include <Drag.h>
  134. #endif
  135.  
  136. //========================================================================================
  137. //    Runtime Info
  138. //========================================================================================
  139.  
  140. #ifdef FW_BUILD_MAC
  141. #pragma segment odfcommands
  142. #endif
  143.  
  144. FW_DEFINE_AUTO(FW_CDragCommand)
  145. FW_DEFINE_AUTO(FW_CDropCommand)
  146.  
  147. //========================================================================================
  148. // FW_CDragCommand class
  149. //========================================================================================
  150.  
  151. //----------------------------------------------------------------------------------------
  152. // FW_CDragCommand constructor
  153. //----------------------------------------------------------------------------------------
  154.  
  155. FW_CDragCommand::FW_CDragCommand(Environment* ev,
  156.                                  FW_CFrame* frame,
  157.                                  FW_Boolean canUndo) :
  158.     FW_CCommand(ev, FW_kDragCommand, frame, canUndo),
  159.     fDragMoveToAnotherPart(FALSE),
  160.     fSelection(NULL)
  161. {
  162.     fBeganTransaction = FALSE;
  163.     fDragResult = kODDropFail;
  164.  
  165.     if (GetCanUndo(ev))
  166.     {
  167.         FW_CString undoString;
  168.         FW_CString redoString;
  169.         
  170.         ::FW_PrivLoadUndoStrings(ev, FW_kUndoDropMsg, undoString, redoString);
  171.         SetMenuStrings(ev, undoString, redoString);
  172.         
  173.         SetActionType(ev, kODEndAction);
  174.     }
  175.  
  176.     fSelection = frame->GetPresentation(ev)->GetSelection(ev);
  177.     FW_ASSERT(fSelection != NULL);    // Must have a selection object for drag
  178.     FW_END_CONSTRUCTOR
  179. }
  180.  
  181. //----------------------------------------------------------------------------------------
  182. // FW_CDragCommand destructor
  183. //----------------------------------------------------------------------------------------
  184.  
  185. FW_CDragCommand::~FW_CDragCommand()
  186. {
  187.     FW_START_DESTRUCTOR
  188. }
  189.  
  190. //----------------------------------------------------------------------------------------
  191. // FW_CDragCommand::DoIt
  192. //----------------------------------------------------------------------------------------
  193.  
  194. void FW_CDragCommand::DoIt(Environment* ev)    // Override
  195. {
  196.     if (fDragMoveToAnotherPart)            // it's a move to another part
  197.     {
  198.         if (GetCanUndo(ev))
  199.         {
  200.             SaveUndoState(ev);            
  201.         }
  202.         fSelection->ClearSelection(ev);
  203.     }
  204.     
  205.     // ----- Check for failure, and if so clean up
  206.     if (fDragResult == kODDropFail)                // Drag&Drop operation failed somewhere along the line
  207.     {
  208.         SetCausesChange(ev, FALSE);                // Don't call part->Changed()
  209.         SetCanUndo(ev, FALSE);                    // cancel the Undo!
  210.  
  211.         if (fBeganTransaction)                    // we've already added a Begin action
  212.         {
  213.             AbortTransaction(ev);            // clear unfinished transactions from Undo stack
  214.             fBeganTransaction = FALSE;
  215.         }
  216.     }
  217.     else if (fBeganTransaction && !GetCanUndo(ev))    // fCanUndo was turned off after BeginAction was added
  218.     {
  219.         // ----- add an EndAction to finish the transaction, since PerformCommand won't
  220.         AddAction(ev, kODEndAction, NULL, 0, GetUndoString(ev), GetRedoString(ev));
  221.         fBeganTransaction = FALSE;
  222.     }
  223.  
  224.     // ----- Finally if can undo save the redo state
  225.     if (GetCanUndo(ev))
  226.         SaveRedoState(ev);
  227. }
  228.  
  229. //----------------------------------------------------------------------------------------
  230. // FW_CDragCommand::CommitDone
  231. //----------------------------------------------------------------------------------------
  232.  
  233. void FW_CDragCommand::CommitDone(Environment* ev)
  234. {
  235.     if (GetCanUndo(ev) && HasAddedAction(ev) && fDragMoveToAnotherPart)
  236.             FreeUndoState(ev);
  237. }
  238.  
  239. //----------------------------------------------------------------------------------------
  240. // FW_CDragCommand::BeginDrag
  241. //----------------------------------------------------------------------------------------
  242.  
  243. void FW_CDragCommand::BeginDrag(Environment* ev, const FW_CMouseEvent& theMouseEvent)
  244. {
  245.     ODPart* destPart;
  246.     ODDragAndDrop*    drag;
  247.     ODStorageUnit*    dragSU;
  248.  
  249.     // ----- Ask the command to save the dragged content and the undo state-----
  250.     ODFacet* facet = theMouseEvent.GetFacet(ev);
  251.     
  252.     ODRgnHandle dragRegion = NULL;
  253.     
  254.     // ----- In the following block we focus on the window -----
  255.     {
  256.         FW_CWindowContext wc(ev, facet);
  257.     
  258.         FW_CRect selectionBounds;    // selectionBounds is in content coordinate
  259.  
  260.         // ----- Scope for aqDragShape and aqWindowContentTransform -----
  261.         {
  262.             FW_CAcquiredODShape    aqDragShape(CreateDragShape(ev, facet));
  263.             selectionBounds = FW_GetShapeBoundingBox(ev, aqDragShape);
  264.  
  265.             FW_ContentToWindow(ev, facet, aqDragShape);
  266.  
  267.             dragRegion = ::FW_CopyRegion(::FW_GetShapeRegion(ev, aqDragShape));
  268.         }
  269.         
  270. #ifdef FW_BUILD_MAC
  271.         // ----- dragRegion must be in screen coordinate on the Mac
  272.         Point localToGlobal = {FW_QDGlobals.thePort->portRect.top, FW_QDGlobals.thePort->portRect.left};
  273.         ::LocalToGlobal(&localToGlobal);
  274.         FW_CPoint offset(localToGlobal);
  275.         ::FW_OffsetRegion(dragRegion, offset.x, offset.y);
  276. #endif        
  277.  
  278.         //  ----- Fill Drag and Drop SU with Props n' Vals
  279.         drag = GetPart(ev)->GetSession(ev)->GetDragAndDrop(ev);
  280.         drag->Clear(ev);
  281.         dragSU = drag->GetContentStorageUnit(ev);
  282.         
  283.         // ----- write out the contents of the drag
  284.         GetPart(ev)->GetDataInterchange(ev)->ExternalizeData(ev, fSelection->GetSelectedContent(ev), GetFrame(ev), dragSU, FW_kDragAndDropStorage, kODCloneCut);
  285.         
  286.         // ----- save offset between mousedown pt and topLeft pt of selection
  287.         // (must convert to Content coordinates first)
  288.         FW_CPoint mouseDownOffset = theMouseEvent.GetMousePosition(ev, FW_CMouseEvent::kFrame);
  289.         FW_CFrame* frame = FW_CFrame::ODtoFWFrame(ev, facet->GetFrame(ev));
  290.         frame->GetContentView(ev)->FrameToViewContent(ev, mouseDownOffset);
  291.         
  292.         mouseDownOffset -= selectionBounds.TopLeft();
  293.         
  294.         dragSU->AddProperty(ev, kODPropMouseDownOffset)->AddValue(ev, kODPoint);
  295.  
  296.         FW_CByteArray byteArray(&mouseDownOffset, sizeof(FW_CPoint));
  297.         dragSU->SetValue(ev, byteArray);
  298.  
  299.         // ----- Write out Link Spec if possible -----
  300.         if (theMouseEvent.IsItemModifier(ev) && !GetPart(ev)->IsReadOnly(ev))    // command key is down
  301.         {
  302.             FW_CLinkManager* linkMgr = GetPart(ev)->GetLinkManager(ev);
  303.             if (linkMgr && fSelection->IsSelectionLinkable(ev))
  304.             {
  305.                 ODLinkSpec* linkSpec = NULL;
  306.                 FW_VOLATILE(linkSpec);
  307.                 ODUpdateID updateID = GetPart(ev)->GetSession(ev)->UniqueUpdateID(ev); // need data to put in the link spec
  308.                 FW_CByteArray data(&updateID, sizeof(updateID));
  309.         
  310.                 FW_TRY
  311.                 {
  312.                     linkSpec = GetPart(ev)->GetDraft(ev)->CreateLinkSpec(ev, GetPart(ev)->GetODPart(ev), data);
  313.                     dragSU->AddProperty(ev, kODPropLinkSpec);
  314.                     linkSpec->WriteLinkSpec(ev, dragSU);
  315.                 }
  316.                 FW_CATCH_BEGIN
  317.                 FW_CATCH_EVERYTHING()
  318.                 {
  319.                     // exception occurred - just continue without the link spec
  320.                     if (linkSpec)
  321.                     {
  322.                         delete linkSpec;
  323.                         linkSpec = NULL;
  324.                     }
  325.                     // FW_THROW_SAME();
  326.                 }
  327.                 FW_CATCH_END
  328.         
  329.                 if (linkSpec)
  330.                 {
  331.                     // Create a link
  332.                     FW_CLinkSource* link = linkMgr->NewLinkSource(ev, updateID, GetPresentation(ev));
  333.                     linkMgr->SetPendingDropLink(ev, link);
  334.                     delete linkSpec;
  335.                 }
  336.             }
  337.         }
  338.  
  339.         GetFrame(ev)->PrivDragging(ev, TRUE);
  340.         if (GetCanUndo(ev))                        // post an empty Begin action
  341.         {
  342.             ODUndo* undo = GetPart(ev)->GetSession(ev)->GetUndo(ev);
  343.             AddAction(ev, kODBeginAction, NULL, 0, GetUndoString(ev), GetRedoString(ev));
  344.             fBeganTransaction = TRUE;
  345.         }
  346.  
  347.         FW_CMouseEvent dragEvent(ev, theMouseEvent);
  348.         ODEventData* eventData = dragEvent.GetPlatformEvent();
  349.         FW_CByteArray dragRegionBArray(&dragRegion, sizeof(dragRegion));        
  350.         FW_CByteArray dragEventBArray(&eventData, sizeof(ODEventData*));
  351.  
  352.         fDragResult = drag->StartDrag(ev, GetFrame(ev)->GetODFrame(ev), kODDragImageRegionHandle, dragRegionBArray, &destPart, dragEventBArray);
  353.         
  354.         GetPart(ev)->GetDataInterchange(ev)->PrivDeletePromises(ev, FW_kDragAndDropStorage); // [HLX] ??? delete any drag and drop promises because we wan't need them
  355.  
  356.         // ----- Done Dragging -----
  357.         GetFrame(ev)->PrivDragging(ev, FALSE);
  358.  
  359.         // ----- Dispose the Drag region ----- [HLX] need a try block
  360.         ::FW_DisposeRegion(dragRegion);
  361.         dragRegion = NULL;
  362.  
  363.         // ----- Determine if it was a dragmove to another part
  364.         fDragMoveToAnotherPart = (fDragResult == kODDropMove) && (destPart != GetPart(ev)->GetODPart(ev));
  365.         
  366.         // ----- Release the destination part -----
  367.         if (destPart)
  368.             destPart->Release(ev);
  369.  
  370.         // ----- If was not a DragMove to another part 
  371.         if (!fDragMoveToAnotherPart)    // can only Undo drag-move to another part
  372.             SetCanUndo(ev, FALSE);
  373.     }
  374. }
  375.  
  376. //----------------------------------------------------------------------------------------
  377. // FW_CDragCommand::CreateDragShape
  378. //----------------------------------------------------------------------------------------
  379.  
  380. ODShape* FW_CDragCommand::CreateDragShape(Environment* ev, ODFacet* facet)
  381. {
  382.     FW_ASSERT(facet);
  383.     return fSelection->CreateSelectionOutline(ev, facet, GetFrame(ev));
  384. }
  385.  
  386. //----------------------------------------------------------------------------------------
  387. // FW_CDragCommand::AbortTransaction
  388. //----------------------------------------------------------------------------------------
  389.  
  390. void FW_CDragCommand::AbortTransaction(Environment* ev)
  391. {
  392.     ODUndo* undo = GetPart(ev)->GetSession(ev)->GetUndo(ev);
  393.     undo->AbortCurrentTransaction(ev);
  394. }
  395.  
  396. //========================================================================================
  397. // FW_CDropCommand
  398. //========================================================================================
  399.  
  400. //----------------------------------------------------------------------------------------
  401. // FW_CDropCommand constructor
  402. //----------------------------------------------------------------------------------------
  403.  
  404. FW_CDropCommand::FW_CDropCommand(Environment* ev,
  405.                                  FW_CFrame* frame, 
  406.                                  ODDragItemIterator* dropInfo, 
  407.                                  ODFacet* facet, 
  408.                                  const FW_CPoint& dropPoint,
  409.                                  FW_Boolean canUndo) :
  410.     FW_CCommand(ev, FW_kDropCommand, frame, canUndo),
  411.     FW_MPasteAsHandler(ev, frame),
  412.     fDropItemIterator(dropInfo),
  413.     fFacet(facet),
  414.     fDropPoint(dropPoint),
  415.     fSelection(NULL)
  416. {
  417.     fDroppedInSameFrame = FALSE;
  418.     fDropResult = kODDropFail;
  419.     fSelection = frame->GetPresentation(ev)->GetSelection(ev);
  420.     
  421.     if (GetCanUndo(ev))
  422.     {
  423.         FW_CString undoString;
  424.         FW_CString redoString;
  425.         
  426.         ::FW_PrivLoadUndoStrings(ev, FW_kUndoDropMsg, undoString, redoString);
  427.         SetMenuStrings(ev, undoString, redoString);
  428.     }
  429.  
  430.     FW_ASSERT(fSelection != NULL);    // Must have a selection object for drag
  431.     FW_END_CONSTRUCTOR
  432. }
  433.  
  434. //----------------------------------------------------------------------------------------
  435. // FW_CDropCommand destructor
  436. //----------------------------------------------------------------------------------------
  437.  
  438. FW_CDropCommand::~FW_CDropCommand()
  439. {
  440.     FW_START_DESTRUCTOR
  441. }
  442.  
  443. //----------------------------------------------------------------------------------------
  444. // FW_CDropCommand::DoIt
  445. //----------------------------------------------------------------------------------------
  446.  
  447. FW_DECLARE_THROW_POINT(FW_CDropCommand_DoIt_BeforeHandleDrop)
  448. FW_DECLARE_THROW_POINT(FW_CDropCommand_DoIt_AfterHandleDrop)
  449.  
  450. void FW_CDropCommand::DoIt(Environment* ev)
  451. {
  452.     FW_MDroppableFrame* droppable = GetFrame(ev)->GetDroppable(ev);
  453.     FW_ASSERT(droppable != NULL);
  454.     
  455.     if (!droppable->GetCanAcceptDrop(ev))
  456.         fDropResult = kODDropFail;
  457.     else
  458.     {
  459.         if (GetCanUndo(ev))
  460.             SaveUndoState(ev);
  461.             
  462.         FW_TRY 
  463.         {
  464.             FW_CHECK_THROW_POINT (FW_CDropCommand_DoIt_BeforeHandleDrop);
  465.             fDropResult = PrivHandleDrop(ev);
  466.         }
  467.         FW_CATCH_BEGIN
  468.         FW_CATCH_EVERYTHING () 
  469.         {
  470.             if (GetCanUndo(ev))
  471.                 FreeUndoState (ev);
  472.             FW_THROW_SAME ();
  473.         }
  474.         FW_CATCH_END
  475.     }
  476.     FW_CHECK_THROW_POINT (FW_CDropCommand_DoIt_AfterHandleDrop);
  477.  
  478.     if (fDropResult == kODDropFail)            // Drop failed--can't Undo
  479.     {
  480.         if (GetCanUndo(ev))
  481.             FreeUndoState(ev);                // Discard any data saved for Undo
  482.         SetCanUndo(ev, FALSE);                // Don't call AddActionToHistory
  483.         SetCausesChange(ev, FALSE);            // Don't call GetPart(ev)->Changed()
  484.     }
  485.     
  486.     // Now that we've successfully dropped, "protect" it by supressing any subsequent
  487.     // failures. We *don't* rethrow now because undo is less important.
  488.     
  489.     if (GetCanUndo(ev)) 
  490.     {
  491.         FW_TRY 
  492.         {
  493.             SaveRedoState(ev);
  494.         }
  495.         FW_CATCH_BEGIN
  496.         FW_CATCH_EVERYTHING () 
  497.         {
  498.             // Having already called PrivHandleDrop and performed the major work of this
  499.             // command we *really* want to avoid passing exceptions up. It would be nice
  500.             // if we could put up an alert saying that Redo won't be supported, though.
  501.         }
  502.         FW_CATCH_END
  503.     }
  504. }
  505.  
  506. //----------------------------------------------------------------------------------------
  507. // FW_CDropCommand::CommitUndone
  508. //----------------------------------------------------------------------------------------
  509.  
  510. void FW_CDropCommand::CommitUndone(Environment* ev)
  511. {
  512.     if (GetCanUndo(ev) && !IsDragMoveInSameFrame(ev))
  513.             FreeRedoState(ev);
  514. }
  515.  
  516. //----------------------------------------------------------------------------------------
  517. // FW_CDropCommand::DoDrop
  518. //----------------------------------------------------------------------------------------
  519.  
  520. FW_Boolean FW_CDropCommand::DoDrop(    Environment* ev,
  521.                                     ODStorageUnit* dropSU,
  522.                                     const FW_CPoint& mouseDownOffset, 
  523.                                     const FW_CPoint& dropPoint,
  524.                                     FW_Boolean isDropMove,
  525.                                     short itemNumber)
  526. {
  527.     FW_UNUSED(mouseDownOffset);
  528.     FW_UNUSED(dropPoint);
  529.     FW_UNUSED(itemNumber);
  530.     
  531.     return GetPart(ev)->GetDataInterchange(ev)->InternalizeData(ev, 
  532.                                                                 GetPresentation(ev)->GetSelection(ev)->GetSelectedContent(ev), 
  533.                                                                 GetFrame(ev), 
  534.                                                                 dropSU, 
  535.                                                                 FW_kDragAndDropStorage, 
  536.                                                                 (isDropMove ? kODCloneDropMove : kODCloneDropCopy), 
  537.                                                                 GetEmbedInfoPtr(ev)) != FW_kInternalizeFailed;
  538. }
  539.  
  540. //----------------------------------------------------------------------------------------
  541. // FW_CDropCommand::DoDroppedInSameFrame
  542. //----------------------------------------------------------------------------------------
  543.  
  544. FW_Boolean FW_CDropCommand::DoDroppedInSameFrame(Environment* ev,
  545.                                                  ODStorageUnit* dropSU,
  546.                                                  const FW_CPoint& mouseDownOffset, 
  547.                                                  const FW_CPoint& dropPoint)
  548. {
  549.     FW_UNUSED(ev);
  550.     FW_UNUSED(dropSU);
  551.     FW_UNUSED(mouseDownOffset);
  552.     FW_UNUSED(dropPoint);
  553.     
  554.     return FALSE;
  555. }
  556.  
  557. //----------------------------------------------------------------------------------------
  558. // FW_CDropCommand::PrivReadMouseDownOffset
  559. //----------------------------------------------------------------------------------------
  560.  
  561. FW_CPoint FW_CDropCommand::PrivReadMouseDownOffset(Environment* ev, ODStorageUnit *dropSU) const
  562. {
  563.     FW_CPoint mouseDownOffset;
  564.     
  565.     if (dropSU->Exists(ev, kODPropMouseDownOffset, kODPoint, 0))
  566.     {
  567.         dropSU->Focus(ev, kODPropMouseDownOffset, kODPosUndefined, kODPoint, 0, kODPosFirstSib);
  568.         FW_CByteArray byteArray;
  569.         dropSU->GetValue(ev, sizeof(FW_CPoint), byteArray);
  570.         byteArray.CopyBuffer(&mouseDownOffset, sizeof(FW_CPoint));
  571.     }
  572.     
  573.     return mouseDownOffset;
  574. }
  575.  
  576. //----------------------------------------------------------------------------------------
  577. // FW_CDropCommand::PrivHandleDrop
  578. //----------------------------------------------------------------------------------------
  579.  
  580. FW_DECLARE_THROW_POINT (FW_CDropCommand_PrivHandleDrop_AfterFirstDrop);
  581.  
  582. ODDropResult FW_CDropCommand::PrivHandleDrop(Environment* ev)
  583. {
  584.     ODStorageUnit* dropSU;
  585.     ODDropResult dropResult = kODDropFail;        // assume the worst
  586.     FW_Boolean acceptedDrop = true;
  587.     FW_Boolean handledDrop = false;
  588.  
  589.     ODDragAndDrop* drag = GetPart(ev)->GetSession(ev)->GetDragAndDrop(ev);
  590.     
  591.     unsigned long attributes = drag->GetDragAttributes(ev);
  592.     FW_Boolean isDropMove = (attributes & kODDropIsMove);
  593.     FW_Boolean isDropInSameFrame = (attributes & kODDropIsInSourceFrame);
  594.     FW_Boolean isDropInSamePart = (attributes & kODDropIsInSourcePart);
  595.     
  596.     if (attributes & kODDropIsPasteAs)            // user wants Paste As dialog
  597.     {
  598.         dropSU = fDropItemIterator->First(ev);
  599.         
  600.         acceptedDrop = HandleDropPasteAsDialog(ev, dropSU, handledDrop);
  601.         if (handledDrop && acceptedDrop)
  602.         {
  603.             // ----- Get the Mouse Offset -----
  604.             FW_CPoint mouseDownOffset = PrivReadMouseDownOffset(ev, dropSU);
  605.             
  606.             SetCommandID(ev, kODCommandPasteAs);
  607.             DoDroppedPasteAs(ev, mouseDownOffset, fDropPoint);
  608.  
  609.             if (GetNewLink(ev) != NULL)    // If the drop created a link, return kODDropCopy regardless of the drop attributes.
  610.                 return kODDropCopy;
  611.         }
  612.         // If the user chose to Merge with Contents without a Link, handledDrop is FALSE
  613.         // and the dropped data will be handled below.
  614.     }
  615.     
  616.     if (!handledDrop)
  617.     {
  618.     /*    Regarding exception handling...
  619.         What happens if we are dropping several items and the first goes OK but a later
  620.         one causes an exception to be thrown? Should we try to undo the previous drops
  621.         or just exit (not having fully cleaned up)? We are not going to clean up, on
  622.         the theory that you probably want dropped objects to stick around. If whoever
  623.         called us assumes that we are going to either completely succeed or completely
  624.         fail (i.e. not exit with a partial state change) then there may be a problem.
  625.         This situation comes up every time we have a loop with a state change in it.
  626.     */
  627.         short itemNumber = 0;
  628.     
  629.         // ----- Iterate thru dropped items
  630.         for (dropSU = fDropItemIterator->First(ev); 
  631.             dropSU && acceptedDrop;
  632.             dropSU = fDropItemIterator->Next(ev))
  633.         {        
  634.             itemNumber++;
  635.  
  636.             // ----- Get the Mouse Offset -----
  637.             FW_CPoint mouseDownOffset = PrivReadMouseDownOffset(ev, dropSU);
  638.             
  639.             // ----- Just make sure we are dealing with the same frame -----
  640.             FW_ASSERT(GetFrame(ev) == FW_CFrame::ODtoFWFrame(ev, fFacet->GetFrame(ev)));
  641.             
  642.             // ----- Check if we were dragging in the same presentation. In this case
  643.             // ----- even if we were dragging accross frames I still want to just call 
  644.             // ----- DoDroppedInSameFrame.
  645.             FW_Boolean samePresentation = (isDropInSamePart) && GetPresentation(ev)->PrivIsDragPending();
  646.             
  647.             if ((samePresentation || isDropInSameFrame) && isDropMove)
  648.             {
  649.                 acceptedDrop = DoDroppedInSameFrame(ev, dropSU, mouseDownOffset, fDropPoint);
  650.                 fDroppedInSameFrame = true;
  651.             }
  652.             else
  653.             {
  654.                 ODWindow* window = fFacet->GetWindow(ev);
  655.                 if (!window->IsActive(ev))
  656.                     window->Select(ev);
  657.                     
  658.                 GetFrame(ev)->PrivActivateFrame(ev, fFacet);
  659.                 
  660.                 acceptedDrop = DoDrop(ev, dropSU, mouseDownOffset, fDropPoint, isDropMove, itemNumber);
  661.             }
  662.             FW_CHECK_THROW_POINT (FW_CDropCommand_PrivHandleDrop_AfterFirstDrop);
  663.         }
  664.     }
  665.  
  666.     // ----- Return drop result
  667.     if (acceptedDrop)
  668.         dropResult = (isDropMove ? kODDropMove : kODDropCopy);
  669.         
  670.     return dropResult;
  671. }
  672.  
  673. //----------------------------------------------------------------------------------------
  674. // FW_CDropCommand::DoDroppedPasteAs
  675. //----------------------------------------------------------------------------------------
  676.  
  677. void FW_CDropCommand::DoDroppedPasteAs(Environment* ev, 
  678.                                        const FW_CPoint& mouseDownOffset, 
  679.                                        const FW_CPoint& dropPoint)
  680. {
  681.     FW_UNUSED(ev);
  682.     FW_UNUSED(mouseDownOffset);
  683.     FW_UNUSED(dropPoint);
  684.  
  685.     // Override to perform post-Drop positioning on the items that were dropped
  686. }
  687.  
  688.