I'm reimplementing the drag-output-record, dragging-output to be more
closer to CLIM specification. This work is almost done. However, a
behaviour of drag-output-record is underspecified in some places.
My questions are about `feedback' argument of drag-output-record. The
following is what the CLIM specification says about feedback function
and that's all what we have:
------------------------------------------------------------------------
`feedback' allows the programmer to identify a "feedback" function of
seven arguments: the output record, the stream, the initial x and y
position of the pointer, the current x and y position of the pointer,
and a drawing argument (either :erase or :draw). It has dynamic
extent. The default is nil, meaning that the feedback behavior will be
for the output record to track the pointer. (The feedback argument is
used when the programmer desires more complex feedback behavior, such as
drawing a "rubber band" line as the user moves the mouse.) Note that if
feedback is supplied, erase is ignored.
------------------------------------------------------------------------
My current solution. Notes: (i) the numbers with star means that the
action is performed by user in the `feedback' function; (ii) (INITIAL-X
INITIAL-Y) is the pointer coordinate when the user initially clicks the
button on the desired record; (iii) (X-OLD Y-OLD) is remembered previous
pointer coordinate.
The user calls drag-output-record. In drag-output-record:
1* Call (feedback RECORD STREAM INITIAL-X INITIAL-Y INITIAL-X INITIAL-Y :DRAW)
2. Set X-OLD := INITIAL-X; Y-OLD := INITIAL-Y
3. User moves the pointer. Now X Y is a new pointer position.
4* Call (feedback RECORD STREAM INITIAL-X INITIAL-Y X-OLD Y-OLD
:ERASE). Erase previous feedback effect and output record.
5. Change output-record-position of the RECORD to a new location.
6* Call (feedback RECORD STREAM INITIAL-X INITIAL-Y X Y :DRAW) where
the user draws the record at it's new position and draws feedback
effect. Note, that RECORD already has the new coordinates in
output-record-position.
7. X-OLD := X; Y-OLD := Y
8. Repeat from 4
...
9. User clicks a pointer button
10* Call (feedback RECORD STREAM INITIAL-X INITIAL-Y X Y :ERASE). Erase
last feedback effect and the output record.
11. Replay the output record without feedback effect at it's final
position.
12. Exit
---
Qusetion about my solution.
===========================
Q: Where the dragged output record should be erased and redrawn
(i. e. replayed) when the `feedback' is supplied: in the `feedback'
function by user or inside the drag-output-record function?
My solution: I've delegated the erasing and redrawing the dragged record
to the user. The situation with erasing is more clear. CLIM
specification states that if `feedback' argument is supplied, the
`erase' argument is ignored. As far as user already had the possibility
to provide the `erase' argument with custom function
(`erase-output-record' by default), then this possibility only migrates
to the :ERASE part of `feedback' function. A situation with `feedback
:DRAW' is unclear. The redrawing of dragged output record can be
accomplished either (i) in the drag-output-record before `feedback
:DRAW' or (ii) by user in `feedback :DRAW', manually replaying the
record and the desired feedback effect.
In other words, there are two algorithms, which are almost equivalent in
the sense of visible effect, but not equivalent with respect to the
user.
(I) My current solution. Erasing/redrawing of output record and feedback
effect is accompishing by user.
1. Call `feedback :ERASE' where user erases the dragged output record
and additional feedback effect from their previous position (with
possible replaying).
2. Change output-record-position to a new position inside
drag-output-record.
3. Call 'feedback :DRAW' where user draws the dragged output record and
then the additional feedback effect at the new position.
(II) Alternative solution. The output record is redrawing in the
drag-output-record.
1. Call `feedback :ERASE' where user erases the dragged output record
and additional feedback effect from previous position (with possible
replaying).
2. Change output-record-position to a new position inside
drag-output-record
3. Draw the dragged output record at it's new position inside the
drag-output-record by replaying required region that contains the
output record.
4. Call 'feedback :DRAW' where user draws only the additional feedback
effect.
What to prefer? The former provides more flexibility to control output
record appearence as it's dragged. For example, I could implement
dragging that is snapped to a grid by erasing/redrawing output record
and additional feedback effect only when the pointer occures in the next
grid cell area. This is not possible with (II), bacause we cannot
control the redrawing of output record. How it was implemented in
original CLIM? Does anyone have any legacy code or examples that use the
drag-output-record with `feedback'?
---
Q: When the `feedback' is called with :DRAW, does the RECORD already
have a new position on STREAM, i. e. the coordinates where it will be
drawn?
My solution: See item 5. I'm changing output-record-position in the
drag-output-record just before calling `feedback :DRAW'. Only the
original CLIM implementation could clear how this was implemented.
---
Q: Am I right when passing the X-OLD Y-OLD to the `feedback :ERASE'?
My solution: If we are using the current pointer coordinates to draw
feedback effect in `feedback :DRAW' (for example, to draw line with
flipping ink from 0,0 to current pointer location), then to erase this
feedback effect in subsequent :ERASE the previous pointer coordinates
are required, not the current. However, CLIM spec says, that only
current pointer coordinates are passed to feedback
:ERASE/:DRAW. Alternative solution: user somewhere remembers coordinates
that are passed to `feedback :DRAW' and use them when it's required to
erase previous feedback.