home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / gui / CIconTextDragTask.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  11.6 KB  |  467 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. //
  20. // Implementation for class that handles dragging an outline of an icon and descriptive text.
  21. // Will do translucent dragging if available (which it almost always should be). It makes
  22. // use of a helper class (CIconTextSuite) to handle building an icon suite and text caption.
  23. // I broke this out to allow more flexibility in how the suite is created (from a resource
  24. // file, from RDF backend, etc).
  25. //
  26. // Hopefully, this (or a derrivative) should be able to meet the needs of any drag and drop
  27. // behavior in the toolbars or the nav center instead of having us reinvent the wheel over
  28. // and over again.
  29. //
  30. // This rather poor first stab is enough functionality to get its first client (the personal
  31. // toolbar) working. It provides a caption to the right of the icon. Translucent
  32. // dragging is broken and commented out. Future versions will also support the ability to
  33. // drag multiple items.
  34. //
  35.  
  36.  
  37. #include "CIconTextDragTask.h"
  38. #include "CEnvironment.h"
  39. #include "macutil.h"
  40. #include "CGWorld.h"
  41. #include "StRegionHandle.h"
  42. #include "StCaptureView.h"
  43. #include "LDragTask.h"
  44. #include "LArray.h"
  45. #include "resgui.h"
  46.  
  47.  
  48. //
  49. // Constructor
  50. //
  51. // Takes a pre-built list of CIconTextSuite's
  52. //
  53. CIconTextDragTask :: CIconTextDragTask( const EventRecord& inEventRecord, 
  54.                                         const LArray & inDragItems, 
  55.                                         const Rect& inLocalFrame )
  56.     :    mFrame(inLocalFrame), mDragItems(inDragItems),
  57.         super(inEventRecord)
  58. {
  59.     // do nothing
  60. }
  61.  
  62.  
  63. //
  64. // Constructor
  65. //
  66. // Takes a single CIconTextSuite and adds it to our internal list automatically
  67. //
  68. CIconTextDragTask :: CIconTextDragTask ( const EventRecord& inEventRecord, 
  69.                                             const CIconTextSuite * inItem, 
  70.                                             const Rect& inLocalFrame )
  71.     : mFrame(inLocalFrame), super(inEventRecord)
  72. {
  73.     AddDragItem ( inItem );
  74. }
  75.  
  76.  
  77. //
  78. // Constructor
  79. //
  80. // Provided so user doesn't have to supply a list when the drag task is created, but
  81. // can use AddDragItem() later
  82. //
  83. CIconTextDragTask :: CIconTextDragTask ( const EventRecord& inEventRecord, 
  84.                                             const Rect& inLocalFrame )
  85.     : mFrame(inLocalFrame), super(inEventRecord)
  86. {
  87.  
  88.  
  89. }
  90.  
  91.  
  92. //
  93. // Destructor
  94. //
  95. CIconTextDragTask :: ~CIconTextDragTask ( )
  96. {
  97.     // do nothing
  98. }
  99.  
  100.  
  101. //
  102. // AddDragItem
  103. //
  104. // Add the item to our internal list
  105. //
  106. void
  107. CIconTextDragTask :: AddDragItem ( const CIconTextSuite * inItem )
  108. {
  109.     mDragItems.InsertItemsAt ( 1, LArray::index_Last, &inItem );
  110.  
  111. } // AddDragItem
  112.  
  113.  
  114. //
  115. // MakeDragRegion
  116. //
  117. // Compute the outline of the region the user sees when they drag. We use the 
  118. // CIconTextSuite to do all the work, since it knows how (and where) it wants to draw.
  119. // Multiple drag items are handled by iterating over the item list and adding each
  120. // item's rectangles to the overall region.
  121. //
  122. void
  123. CIconTextDragTask :: MakeDragRegion( DragReference /*inDragRef*/, RgnHandle inDragRegion)
  124. {
  125.     CIconTextSuite* curr = NULL;
  126.     LArrayIterator it ( mDragItems );
  127.     while ( it.Next(&curr) ) {
  128.  
  129.         Rect iconRect = curr->IconRectGlobal();
  130.         AddRectDragItem(static_cast<ItemReference>(1), iconRect);
  131.         RgnHandle iconRectRgn = ::NewRgn();
  132.         ::RectRgn ( iconRectRgn, &iconRect );
  133.         ::UnionRgn ( inDragRegion, iconRectRgn, inDragRegion );
  134.         DisposeRgn ( iconRectRgn );
  135.         
  136.         Rect textRect = curr->TextRectGlobal();
  137.         AddRectDragItem(static_cast<ItemReference>(1), textRect);
  138.         RgnHandle textRectRgn = ::NewRgn();
  139.         ::RectRgn ( textRectRgn, &textRect );
  140.         ::UnionRgn ( inDragRegion, textRectRgn, inDragRegion );
  141.         DisposeRgn ( textRectRgn );
  142.  
  143.     } // for each item to be dragged
  144.  
  145. } // MakeDragRegion
  146.  
  147.  
  148. //
  149. // AddFlavors
  150. //
  151. // Overloaded to allow for multiple items being dragged and to assign them each
  152. // a different item reference number. 
  153. //
  154. void 
  155. CIconTextDragTask :: AddFlavors ( DragReference inDragRef )
  156. {
  157.     Uint32 itemRef = 1;
  158.     CIconTextSuite* curr = NULL;
  159.     LArrayIterator it ( mDragItems );
  160.     while ( it.Next(&curr) ) {
  161.         AddFlavorForItem ( inDragRef, itemRef, curr );        
  162.         itemRef++;
  163.     } // for each item
  164.     
  165. } // AddFlavors
  166.  
  167.  
  168. //
  169. // AddFlavorForItem
  170. //
  171. // Register the flavors for the given item. Overload this (as opposed to AddFlavors()) to
  172. // do something out of the ordinary for each item or do register different
  173. // drag flavors from the standard bookmark flavors.
  174. //
  175. void
  176. CIconTextDragTask :: AddFlavorForItem ( DragReference inDragRef, ItemReference inItemRef,
  177.                                             const CIconTextSuite* inItem )
  178. {
  179.     #pragma unused (inDragRef)
  180.     
  181.     // ...register standard bookmark flavors
  182.     AddFlavorBookmarkFile(inItemRef);
  183.     AddFlavorURL(inItemRef);
  184.     AddFlavorHTNode(inItemRef, inItem->GetHTNodeData());
  185.  
  186. } // AddFlavorForItem
  187.  
  188.  
  189. //
  190. // AddFlavorHTNode
  191. //
  192. // This flavor contains the RDF information for a node in a hypertree. It only has 
  193. // meaning internally to Navigator.
  194. //
  195. void
  196. CIconTextDragTask :: AddFlavorHTNode ( ItemReference inItemRef, const HT_Resource inNode )
  197. {
  198.     OSErr theErr = ::AddDragItemFlavor(
  199.                                     mDragRef,
  200.                                     inItemRef,
  201.                                     emHTNodeDrag,
  202.                                     &inNode,            
  203.                                     sizeof(HT_Resource),
  204.                                     flavorSenderOnly);
  205.     ThrowIfOSErr_(theErr);
  206.     
  207.  
  208. } // AddFlavorHTNode
  209.  
  210.  
  211. //
  212. // DoDrag
  213. //
  214. // Register the normal url flavors then dispatch to handle either translucent or
  215. // normal dragging
  216. //
  217. OSErr
  218. CIconTextDragTask :: DoDrag ( )
  219. {
  220.     MakeDragRegion(mDragRef, mDragRegion);
  221.     AddFlavors(mDragRef);
  222.     
  223.     if (UEnvironment::HasFeature(env_HasDragMgrImageSupport)) {
  224.         try {
  225.             DoTranslucentDrag();
  226.         }
  227.         catch (...) {
  228.             DoNormalDrag();
  229.         }
  230.     }
  231.     else
  232.         DoNormalDrag();
  233.     
  234.     return noErr;
  235.     
  236. } // DoDrag
  237.  
  238.  
  239. //
  240. // DoNormalDrag
  241. //
  242. // Just tracks the drag displaying the outline of the region created from MakeDragRegion()
  243. //
  244. void
  245. CIconTextDragTask :: DoNormalDrag ( )
  246. {
  247.     ::TrackDrag(mDragRef, &mEventRecord, mDragRegion);
  248.     
  249. } // DoNormalDrag
  250.  
  251.  
  252. //
  253. // DoTranslucentDrag
  254. //
  255. // Tracks the drag but also draws the icon and caption translucently.
  256. //
  257. void
  258. CIconTextDragTask :: DoTranslucentDrag ( )
  259. {
  260.     ::TrackDrag(mDragRef, &mEventRecord, mDragRegion);
  261.     
  262. #if THIS_WOULD_EVER_WORK
  263.     Rect theFrame;
  264.     StColorPortState theColorPortState(mSuite.Parent()->GetMacPort());
  265.  
  266.     // Normalize the color state (to make CopyBits happy)
  267.     StColorState::Normalize();
  268.     
  269.     // Build a GWorld
  270.     Rect gworldSize = mSuite.BoundingRect();
  271.     CGWorld theGWorld(gworldSize, 0, useTempMem);
  272.     theGWorld.BeginDrawing();
  273. //    StCaptureView theCaptureView( *mSuite.Parent() );
  274.  
  275.     try
  276.     {
  277. //        theCaptureView.Capture(theGWorld);
  278.  
  279.         mSuite.Parent()->FocusDraw();
  280.     
  281.         mSuite.mDisplayText->Show();
  282. //        mSuite.DrawIcon();
  283.  
  284.            Point theOffsetPoint = topLeft(PortToGlobalRect(mSuite.Parent(),
  285.                                        LocalToPortRect(mSuite.Parent(), mFrame)));
  286.         
  287.         // Set the drag image
  288.  
  289.         StRegionHandle theTrackMask;
  290.  
  291. //        mProxyPane.CalcLocalFrameRect(theFrame);
  292. //        ThrowIfOSErr_(::IconSuiteToRgn(theTrackMask, &theFrame, kAlignAbsoluteCenter, mIconSuite));
  293.         
  294.         mSuite.mDisplayText->CalcLocalFrameRect(theFrame); // Use frame which bounds the actual text, not the frame bounds
  295.         theTrackMask += theFrame;
  296.         
  297.         theGWorld.EndDrawing();
  298.         
  299.         PixMapHandle theMap = ::GetGWorldPixMap(theGWorld.GetMacGWorld());
  300.         OSErr theErr = ::SetDragImage(mDragRef, theMap, theTrackMask, theOffsetPoint, dragDarkerImage);
  301.         ThrowIfOSErr_(theErr);
  302.         
  303.         // Track the drag
  304.         
  305.         ::TrackDrag(mDragRef, &mEventRecord, mDragRegion);
  306.     }
  307.     catch (...)
  308.     {
  309.     }
  310.     
  311.     mSuite.mDisplayText->Hide();
  312. #endif
  313.  
  314. } // DoTranslucentDrag
  315.  
  316.  
  317. #pragma mark -
  318.  
  319. CIconTextSuite :: CIconTextSuite ( )
  320.     : mIconSuite(nil), mIconText(""), mDisplayText(nil), mParent(nil), mHTNodeData(nil)
  321. {
  322.  
  323. } // constructor
  324.  
  325.  
  326. //
  327. // Constructor
  328. //
  329. // Creates a icon suite that is loaded in from an icon in a resource file. |inBounds| must
  330. // be in local coordinates, and is only used as a guideline for giving a top/left to
  331. // draw the icon and caption relative to. It is NOT used as a clipping rectangle.
  332. //
  333. CIconTextSuite :: CIconTextSuite ( LView* inParent, const Rect & inBounds, ResIDT inIconId, 
  334.                                     const cstring & inIconText, const HT_Resource inHTNodeData )
  335.     : mIconText(inIconText), mBounds(inBounds), mParent(inParent), mHTNodeData(inHTNodeData)
  336. {
  337.     IconSelectorValue selector = svAllAvailableData;
  338.     ::GetIconSuite ( &mIconSuite, inIconId, selector );
  339.     ThrowIfNil_ ( mIconSuite );
  340.     
  341.     // build a caption for the icon's title relative to the bounding rect we're given.
  342.     // The top and left offsets are from the LSmallIconTable's drawing routine.
  343.     SPaneInfo paneInfo;
  344.     paneInfo.width = ::TextWidth(inIconText, 0, inIconText.length());
  345.     paneInfo.height = 16;
  346.     paneInfo.visible = false;
  347.     paneInfo.left = inBounds.left + 22;
  348.     paneInfo.top = inBounds.top + 2;
  349.     paneInfo.superView = inParent;
  350.     mDisplayText = new LCaption ( paneInfo, LStr255(mIconText), 130 );
  351.     ThrowIfNil_(mDisplayText);
  352.     
  353. } // constructor
  354.  
  355.  
  356. //
  357. // Copy Constructor
  358. //
  359. CIconTextSuite :: CIconTextSuite ( const CIconTextSuite & other )
  360.     : mHTNodeData(other.mHTNodeData)
  361. {
  362.     mIconSuite = other.mIconSuite;
  363.     mBounds = other.mBounds;
  364.     mIconText = other.mIconText;
  365.     mDisplayText = other.mDisplayText;
  366.     mParent = other.mParent;
  367.  
  368. } // copy constructor
  369.  
  370.  
  371. //
  372. // Destructor
  373. //
  374. // Clean up our mess
  375. //
  376. CIconTextSuite :: ~CIconTextSuite ( ) 
  377. {
  378.     ::DisposeIconSuite ( mIconSuite, true );
  379.     delete mDisplayText;
  380.     
  381. } // destructor
  382.  
  383.  
  384. //
  385. // IconRectLocal
  386. //
  387. // Returns the rectangle (in local coordinates) of the icon, relative to the |mBounds|
  388. // rectangle. The offsets are from LSmallIconTable's draw routine.
  389. //
  390. Rect
  391. CIconTextSuite :: IconRectLocal ( ) const
  392. {
  393.     Rect iconRect;
  394.     
  395.     // Add the icon region
  396.     iconRect.left = mBounds.left + 3;
  397.     iconRect.right = iconRect.left + 16;
  398.     iconRect.bottom = mBounds.bottom - 2;
  399.     iconRect.top = iconRect.bottom - 16;
  400.     return iconRect;
  401.     
  402. } // IconRectLocal
  403.  
  404.  
  405. //
  406. // IconRectGlobal
  407. //
  408. // Takes the local icon bounds and makes them global
  409. //
  410. Rect
  411. CIconTextSuite :: IconRectGlobal ( ) const
  412. {
  413.     return ( PortToGlobalRect(mParent, LocalToPortRect(mParent, IconRectLocal())) );
  414.  
  415. } // IconRectGlobal
  416.  
  417.  
  418. //
  419. // TextRectLocal
  420. //
  421. // Returns the rectangle (in local coordinates) of the text caption, relative to the |mBounds|
  422. // rectangle. Since we've already positioned the caption when we started up, this is
  423. // pretty easy.
  424. //
  425. Rect
  426. CIconTextSuite :: TextRectLocal ( ) const
  427. {
  428.     Rect theFrame;
  429.  
  430.     mDisplayText->CalcLocalFrameRect(theFrame);
  431.     return theFrame;
  432.  
  433. } // TextRectLocal
  434.  
  435.  
  436. //
  437. // TextRectGlobal
  438. //
  439. // Takes the local text bounds and makes them global
  440. //
  441. Rect
  442. CIconTextSuite :: TextRectGlobal ( ) const
  443. {
  444.     return ( PortToGlobalRect(mParent, LocalToPortRect(mParent, TextRectLocal())) );
  445.  
  446. } // TextRectGlobal
  447.  
  448.  
  449. //
  450. // BoundingRect
  451. //
  452. // Compute the rect that can contain the icon and caption entirely.
  453. //
  454. Rect
  455. CIconTextSuite :: BoundingRect ( ) const
  456. {
  457.     Rect bounds = { 0, 0, 0, 0 };
  458.     
  459.     mParent->FocusDraw();
  460.     Rect textRect = TextRectLocal();
  461.     
  462.     bounds.right = textRect.right;
  463.     bounds.bottom = textRect.bottom;
  464.     return bounds;
  465.     
  466. } // BoundingRect
  467.