home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / documentation / documents / a252drop < prev    next >
Internet Message Format  |  1999-04-27  |  13KB

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