home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 4 / AUCD4.iso / acorn / documents / appnotes / 231-245 / 241c.arc / Text
Encoding:
Text File  |  1993-11-12  |  14.8 KB  |  350 lines

  1. -----------------------------------------------------------------------------
  2. 8th October,   The RISC OS Drag-and-Drop System
  3. -----------------------------------------------------------------------------
  4. Support Group Application Note 
  5. Number:  241
  6. Issue:   1.00
  7. Author:  SH/JB
  8. -----------------------------------------------------------------------------
  9.  
  10. Developer's Notes: 
  11.  
  12.  This application note describes how drag-and-drop data transfer within and
  13. between applications could be implemented, and how to make sure that your
  14. applications co-operate with others to promote consistent data transfer
  15. facilities.
  16.  
  17. This application note is based on a protocol designed by Iota Software Ltd.
  18.  
  19. -----------------------------------------------------------------------------
  20. Applicable Hardware: All Acorn RISC OS based computers
  21.  
  22. Related Application Notes: The RISC OS Selection Model and Clipboard
  23.  
  24.  
  25. -----------------------------------------------------------------------------
  26. Copyright (C) Acorn Computers Limited 1992
  27.  
  28. Every effort has been made to ensure that the information in this leaflet is 
  29. true and correct at the time of printing. However, the products described in
  30. this leaflet are subject to continuous development and improvements and
  31. Acorn Computers Limited reserves the right to change its specifications at
  32. any time. Acorn Computers Limited cannot accept liability for any loss or
  33. damage arising from the use of any information or particulars in this
  34. leaflet. ACORN, ECONET and ARCHIMEDES are trademarks of Acorn Computers
  35. Limited.
  36. -----------------------------------------------------------------------------
  37. Support Group
  38. Acorn Computers Limited
  39. Acorn House
  40. Vision Park
  41. Histon
  42. Cambridge
  43. CB4 4AE                                                  
  44. -----------------------------------------------------------------------------
  45.  
  46.  
  47. Drag and Drop
  48.  
  49.  
  50.  The goal of this protocol is to allow the user to copy and move data, both
  51. within and between applications,  by direct manipulation.  This means that
  52. the user should be able to make a selection in a document, pick the selected
  53. objects up with the mouse, drag them to their destination and release the
  54. mouse button.  To facilitate precise positioning of the dragged objects,
  55. provision is made for the receiving task to display a ghost caret, which
  56. tracks the mouse pointer in the target window and indicates exactly where
  57. the data will be inserted.  For text, the ghost caret should look similar to
  58. the normal Wimp caret, and as its follows the mouse pointer it should "snap"
  59. to the nearest inter-character gap.  The appearance of a ghost caret for
  60. non-textual selections will vary, but might typically be the bounding box of
  61. the dragged data, scaled according to the destination window's zoom factors.
  62.  
  63.  This document assumes that you have implemented the selection system
  64. described in the application note The RISC OS Selection Model and Clipboard.
  65.  
  66.  
  67. User Interface
  68.  
  69.  The following mouse controls exist on a text area.  Non-textual documents
  70. will work similarly, but the details of the selection model and visual
  71. feedback may differ according to the nature of the data being manipulated.
  72.  
  73.  Clicking Select where there is no selection sets the caret position
  74.  
  75.  Clicking Adjust when there is a caret creates a selection between  the old
  76. caret position and the mouse position.
  77.  
  78.  Dragging with Select where there is no selection starts a new selection,
  79. and subsequent dragging moves the other end.
  80.  
  81. Dragging with Adjust alters the ‘nearest’ end of the selection.
  82.  
  83.  Clicking Select over the selection has no effect (to allow the drag to
  84. occur properly - see below).
  85.  
  86.  Dragging with Select over the selection causes a box the size of the
  87. selection to be dragged.  While the box is being dragged over a potential
  88. destination, a ghost caret may be displayed by the application that owns the
  89. destination window.
  90.  
  91.  While a drag is in progress, placing the mouse pointer close to (but
  92. inside) an edge of the window should cause the window to scroll
  93. automatically in the appropriate direction.   Scrolling is the
  94. responsibility of the application that owns the destination window.
  95.  
  96.  Releasing Select at the destination causes the selection to be copied or
  97. moved to the destination.  If the destination is within the same window,
  98. then the data should be moved, unless SHIFT is held down, when the data
  99. should be copied instead.  However, if the destination is a different
  100. window, the sense of the SHIFT key should be reversed so that the default
  101. action is a copy.
  102.  
  103.  
  104.  
  105.  
  106.  While the selection is being dragged, the following message protocol is
  107. used to implement automatic scrolling  and ‘ghost caret’ positioning:
  108.  
  109.         Message_Dragging (17)
  110.  
  111.                 0       message size
  112.                 4       task handle of task performing the drag
  113.                 8       message id
  114.                 12      your_ref (0)
  115.                 16      Message_Dragging
  116.                 20      window handle
  117.                 24      icon handle
  118.                 28      x
  119.                 32      y
  120.                 36      flags:
  121.                                 bit 1 set => sending data from selection
  122.                                 bit 2 set => sending data from clipboard
  123.                                 bit 3 set => source data will be deleted
  124.                                 bit 4 set => do NOT claim this message
  125.                                 all other bits reserved (must be 0)               
  126.                                 40    x0, y0, x1, y1:  bounding box of data
  127.                                 relative to the pointer,                      
  128.                                 in 1/72000“ (not scaled according to the
  129.                                 zoom factors of the source window)
  130.                                 x0 > x1 => source data size unknown
  131.                 56      list of filetypes in sender’s order of preference,
  132.                           terminated by -1
  133.                         Message_DragClaim (18)
  134.                 0       message size
  135.                 4       task handle of task replying to Message_Dragging
  136.                 8       message id
  137.                 12      your_ref (message id of the Message_Dragging received)
  138.                 16      Message_DragClaim
  139.                 20      flags:
  140.                                 bit 0 set => pointer shape has been changed
  141.                                 bit 1 set => remove wimp dragbox
  142.                                 bit 3 set => source data should be deleted
  143.                                 all other bits reserved (must be 0)
  144.                 24      list of filetypes in receiver’s order of preference,
  145.                           terminated by -1
  146.  
  147.  All messages are sent using type 18 (reply required), and the 'your_ref'
  148. field of each message is set to the message id of that to which it is
  149. replying, unless otherwise stated.
  150.  
  151.  During the drag, the dragging task enables null events using Wimp_PollIdle
  152. with a minimum return time of about 0.25 second.  On each null event, it
  153. finds the current mouse position using Wimp_GetPointerInfo.  It then
  154. constructs the message block for Message_Dragging using the information
  155. gleaned.
  156.  
  157.  If no task has claimed control of the pointer (as none has at the start),
  158. the message is sent to the owner of the window/icon pair returned by
  159. Wimp_GetPointerInfo.
  160.  
  161.  If the dragging task receives a Message_DragClaim in reply, it stores the
  162. task / your_ref / flags of the message to indicate that the given task has
  163. claimed the drag process.
  164.  
  165.  On the next null event, if the drag has been claimed, the Message_Dragging
  166. is sent to the claimant (with your_ref set as appropriate), otherwise it is
  167. sent to the window/icon pair returned by Wimp_GetPointerInfo as before.
  168.  
  169.  If the Message_Dragging bounces (note that a DragClaim reply is required
  170. for each Message_Dragging that is sent), and the drag was being claimed, the
  171. record of the claimant is reset and the Message_Dragging is resent, this
  172. time to the window/icon pair (with a your_ref of 0).
  173.  
  174.  The claimant will normally only claim the drag again if the pointer is
  175. still within its window, but it may continue if it has started
  176. auto-scrolling.  If bit 4 of the flags in the Message_Dragging is set, the
  177. claimant MUST relinquish the drag, since this indicates that the sender is
  178. terminating the drag process.
  179.  
  180.  When the drag terminates, the dragging task sets a flag and calls the null
  181. event code once more (to ensure that the mouse position is up-to-date). 
  182. This results in a Message_Dragging being sent, either to the claimant or to
  183. the window/icon pair under the pointer.
  184.  
  185.  This will result in a DragClaim being returned, or the message bouncing. 
  186. If the message bounces, and there was a claimant, the Message_Dragging is
  187. resent, as for a null event.
  188.  
  189.  However, if a DragClaim is received, or the Message_Dragging bounces and
  190. there is no claimant, then the ‘drag terminated’ flag is inspected, and if
  191. set, the data can finally be saved to the destination.
  192.  
  193.  The sender is also responsible for detecting the user aborting the drag
  194. using Escape - in this case it should set an internal ‘Aborted’ flag, call
  195. Wimp_DragBox with -1 to terminate the drag, and then proceed as for drag
  196. finished, terminating the process just before the DataSave would have been
  197. sent.
  198.  
  199.  The sender should keep a record of whether the pointer shape has been
  200. changed (ie. keep a copy of the last set of DragClaim flags received), and
  201. reset the pointer shape whenever the ‘pointer altered’ bit changes from a 1
  202. to a 0.  Thus if the other application first changes the pointer shape,
  203. sending a DragClaim with flags bit 0 set, then next time does not wish to
  204. change the pointer shape, but nevertheless wants to keep the drag, it will
  205. send a DragClaim with flags bit 0 clear, so the sender should reset the
  206. pointer shape.
  207.  
  208.  The ‘remove wimp dragbox’ flag works slightly differently - since the
  209. receiver is not allowed to alter the wimp dragbox, it should instead ask the
  210. sender to do this by setting bit 1 of the DragClaim message.  If at some
  211. later time a DragClaim is sent without this bit set, or the Message_Dragging
  212. bounces, the sender should restore the wimp dragbox.  It should do this by
  213. calling Wimp_DragBox again with the appropriate drag type.
  214.  
  215.  The bounding box in internal units allows the receiver to display the exact
  216. position of where the data will be placed if the mouse button is released,
  217. and is an exact analogy of the ghost caret for text.  The receiver should
  218. display the box exactly where the data would go, i.e. corrected for grid
  219. alignment, snap to frames etc.
  220.  
  221.  Note that sometimes the sender does not know the bounding box of the data,
  222. or sometimes the concept may be meaningless (e.g. for text transfer).  In
  223. this case the bounding box in the Message_Dragging should be set so that x0
  224. > x1, and the receiver should check for this and not use a box to display
  225. the position of the data (although it may still use a ghost caret if
  226. appropriate). The Wimp drag box should be used if the receiver has no way to
  227. display the destination position.
  228.  
  229.  Bit 3 of the DragClaim message can be set to indicate that the sender
  230. should delete the source data even if the user did not press the Shift key. 
  231. This option could be used by a trashcan application, so that objects dragged
  232. to it are simply deleted.
  233.  
  234.  When the sender finally comes to save the data, it should send in its own
  235. preferred format, unless a DragClaim is in force and the sender can do one
  236. of the the filetypes in the list returned.  If so, it must do the first one
  237. in the list that it can.
  238.  
  239.  Before sending the data, the sender should now reset the pointer shape to
  240. the default if the claimant’s last DragClaim had the ‘pointer shape altered‘
  241. flag set.
  242.  
  243.  The normal Message_DataSave protocol is used, except that the your_ref of
  244. the Message_DataSave is set to 0 if there was no claimant, and to the stored
  245. claimant’s last DragClaim message id otherwise.
  246.  
  247.  Thus the receiver of the Message_DataSave knows whether to alter the
  248. insertion point according to the x,y position indicated, and whether the
  249. ‘ghost caret’ needs to be removed from view.
  250.  
  251. In summary, the two tasks should behave as follows:
  252.  
  253. Sender:
  254.     start:
  255.         call Wimp_DragBox to start the drag, and enable null events every 0.25s
  256.         set claimant to ‘none’
  257.         set drag_finished to ‘false’
  258.         set drag_aborted to ‘false’
  259.         set lastref to 'none'
  260.  
  261.     null event:
  262.         read mouse position and construct Message_Dragging
  263.         if claimant
  264.           send message (18) to claimant (your_ref = lastref)
  265.         else
  266.           send message (17/18) to window/icon pair (your_ref = 0)
  267.         endif
  268.  
  269.     escape pressed:
  270.         set drag_aborted to ‘true’
  271.         call Wimp_DragBox with -1 to terminate the drag
  272.         proceed as for drag finished
  273.  
  274.     drag finished:
  275.         set drag_finished to ‘true’, then call null event code
  276.  
  277.     Message_DragClaim received:
  278.         if drag_finished
  279.           reset pointer shape if claimant altered it
  280.           unless drag_aborted send data to claimant (your_ref = my_ref of DragClaim)
  281.         else
  282.           reset pointer shape if (old_flags and not new_flags) has bit 0 set
  283.           set claimant to task handle of DragClaim message
  284.           set lastref to my_ref of DragClaim message
  285.         endif
  286.  
  287.  
  288.  
  289.     Message_Dragging bounced:
  290.         if claimant is not 'none'
  291.           reset pointer shape if claimant altered it
  292.           set claimant to ‘none’
  293.           resend message to window/icon pair (type 17/18)
  294.         else
  295.           if drag_finished
  296.             unless drag_aborted send data to window/icon pair (your_ref = 0)
  297.           endif
  298.         endif
  299.  
  300.         ‘17/18’ means ‘if drag_finished, send as type 18, else as type 17’.
  301.         bit 4 of any Message_Dragging sent is set if drag_aborted is true.
  302.  
  303. Receiver:
  304.     start:
  305.         set claiming to ‘false’
  306.         set pointer_altered to ‘false’
  307.  
  308.     Message_Dragging received:
  309.         if claiming,
  310.           if flags bit 4 clear, and we’re auto-scrolling or in a text area
  311.             reply with Message_DragClaim (type 17)
  312.             perform auto-scroll if required
  313.             update ghost caret if required
  314.          else
  315.             set claiming to 'false'
  316.             undraw ghost caret if necessary
  317.             don’t reply to message
  318.           endif
  319.         else
  320.           if flags bit 4 clear
  321.             if we’re in the auto-scroll area
  322.               change pointer shape to indicate auto-scroll
  323.               set timer for auto-scroll
  324.               set pointer_altered to ‘true’
  325.               reply with Message_DragClaim (type 17)
  326.             elseif we’re in a text area
  327.               draw ghost caret in correct place
  328.               set pointer_altered to ‘false’
  329.               reply with Message_DragClaim (type 17)
  330.             endif
  331.           endif
  332.         endif
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.    Message_DataSave received:
  341.         if your_ref indicates we’re claiming:
  342.           if ghost caret is set up
  343.             set insertion point to ghost caret
  344.             undraw ghost caret
  345.           endif
  346.         endif
  347.         import data to insertion point
  348.  
  349.  All Message_DragClaim messages are sent with bit 0 of the flags indicating
  350. the current value of the ‘pointer_altered’ flag.