Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2009-04

Dragging documented

11 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Hans-Peter Diettrich

I've started documentation about dragging, with the first part (drag-drop) here:
<http://wiki.lazarus.freepascal.org/LCL_Drag_Drop>

This page shall explain general principles behind dragging, one or more pages about docking will follow.

My research started in Delphi 2.0, where only drag-drop is supported. So far the Delphi model is fine, but the extensions for drag-dock support are both poorly designed *and* implemented. Obviously nobody at Borland or CodeGear ever dared to touch that crap, the same bugs persist in the RAD Studio versions - and also in the LCL, of course :-(

So I couldn't resist to add some criticism about the current LCL implementation. Any comments are welcome :-)

DoDi

Felipe Monteiro de Carvalho
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
So I couldn't resist to add some criticism about the current LCL implementation. Any comments are welcome :-)

I think you should be more specific if you want to do a criticism. In the way you put it one can have no idea what exactly you are taking about.

Felipe Monteiro de Carvalho
Hans-Peter Diettrich
to Felipe Monteiro de Carvalho
Show quoted text 6 lines
> So I couldn't resist to add some criticism about the current LCL > implementation. Any comments are welcome :-) I think you should be more specific if you want to do a criticism. In the way you put it one can have no idea what exactly you are taking about.

[ ] You have read section 3: LCL Implementation

DoDi

Felipe Monteiro de Carvalho
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
[ ] You have read section 3: LCL Implementation

I had just assumed you would never write the critics to the wiki. The Wiki is the wrong place for criticism. It is a documentation and not a discussion forum or a blog. Could you modify the page to make it more professional looking? thanks

Please post criticism in the mailling list instead.

thanks,

Felipe Monteiro de Carvalho
Tom Verhoeff
to Hans-Peter Diettrich: I've started documentation about dragging, with the first part (drag-drop) here:…
Hans-Peter Diettrich wrote
I've started documentation about dragging, with the first part (drag-drop) here: <http://wiki.lazarus.freepascal.org/LCL_Drag_Drop>

It would be helpful to include a Message Sequence Chart or UML Sequence Diagram, visualizing which objects and methods are involved in what order.

Something along the lines (this is for Delphi; view with monospaced font):

Main Drag (Optional) Drag User Event Source Drag Target (Mouse) Loop Control Object Control = = = = | | | | 1|--MouseDown--->| | | | 2#--OnMouseDown->| | | | 3# | | 4#<-BeginDrag()--# | | # # | | | | | | 5#--OnStartDrag->| | | # 6#----Create---->= | | | # | | 7|--MouseMove--->| | | | | 8#-----------------------------------OnDragOver->| | # | | 9# | # | | # | | | | | 10|---MouseUp---->| | | | | 11#-----------------------------------OnDragDrop->| | # | | 12# | # | | # | #---OnEndDrag-->| | | | | 13#----Destroy--->= | | | | |

The DragObject is optional. There could be multiple candidate targets. The Main Event Loop determines which event to send to which object, depending on the user action, the cursor location, and the current state of the GUI.

4 somehow triggers 5 (there is a delay depending on the Boolean parameter Immediate to BeginDrag).

6 determines the location of the MouseDown and may use this to decide on what gets dragged (through GetCursorPos, ScreenToClient, MouseToCell). It can call SetDragImage to visualize a thing being dragged.

The chain 7, 8, 9 can occur repeatedly; 9 indicates acceptability of a drop at this target via the Boolean var parameter Accepted.

12 is called only if the immediately preceding OnDragOver of this target returned Accepted = True; i.e. Accepted is a precondition of 12.

13 receives the parameter Target to know where the drop was accepted; if Target = nil, then the drop was cancelled by the user (MouseUp at an unacceptable location), and OnDragDrop was not performed; if Target nil, then OnDragDrop was already performed at the Target. The work associated with an actual drop is thus divided over the OnDragDrop (for actions at the target) and OnEndDrag (for actions at the source). Since a Drag Object needs to be destroyed, independent of whether the drop was successful or canceled, it is best to call Free (or Destroy) only in the OnEndDrag handler.

Only one drag can be active at any moment; it either ends in a drop or is canceled.

There are various other things to be included, but this is the fundamental part. (Maybe also see <http://www.delphi-central.com/drag.aspx> or <http://www.podgoretsky.com/ftp/Docs/Delphi/D5/dg/controls.html>.)

I hope this is helpful.

Tom

E-MAIL: T.Verhoeff @ TUE.NL | Dept. of Math. & Comp. Science PHONE: +31 40 247 41 25 | Technische Universiteit Eindhoven FAX: +31 40 247 54 04 | PO Box 513, NL-5600 MB Eindhoven http://www.win.tue.nl/~wstomv/ | The Netherlands
Mattias Gaertner
to Tom Verhoeff
Show quoted text 13 lines
On Sat, Apr 18, 2009 at 01:56:54AM +0200, Hans-Peter Diettrich wrote: > I've started documentation about dragging, with the first part > (drag-drop) here: > <http://wiki.lazarus.freepascal.org/LCL_Drag_Drop> It would be helpful to include a Message Sequence Chart or UML Sequence Diagram, visualizing which objects and methods are involved in what order. Something along the lines (this is for Delphi; view with monospaced font): [...] I hope this is helpful.

Good idea. Can you add this to the wiki:
http://wiki.lazarus.freepascal.org/LCL_Drag_Drop
?

Mattias

Tom Verhoeff
to Mattias Gaertner
Mattias Gaertner wrote 13 lines
On Tue, 19 May 2009 10:34:40 +0200 Tom Verhoeff wrote: > It would be helpful to include a Message Sequence Chart or UML > Sequence Diagram, visualizing which objects and methods are involved > in what order. > > Something along the lines (this is for Delphi; view with monospaced > font): >[...] Good idea. Can you add this to the wiki: http://wiki.lazarus.freepascal.org/LCL_Drag_Drop

I was hoping that Hans-Peter Diettrich could incorporate it.

Unfortunately, I have a number of serious deadlines coming up, and it would be necessary to redraw the diagram using some (graphical or UML) tool, which I am not using so often.

Thanks for the heads up,

Tom

E-MAIL: T.Verhoeff @ TUE.NL | Dept. of Math. & Comp. Science PHONE: +31 40 247 41 25 | Technische Universiteit Eindhoven FAX: +31 40 247 54 04 | PO Box 513, NL-5600 MB Eindhoven http://www.win.tue.nl/~wstomv/ | The Netherlands
Hans-Peter Diettrich
to Tom Verhoeff: It would be helpful to include a Message Sequence Chart or UML Sequence Diagram,…
Show quoted text 6 lines
> I've started documentation about dragging, with the first part > (drag-drop) here: > <http://wiki.lazarus.freepascal.org/LCL_Drag_Drop> It would be helpful to include a Message Sequence Chart or UML Sequence Diagram, visualizing which objects and methods are involved in what order.

Thanks for your chart :-)
[...]
Do you want to add it to the wiki?

Unfortunately the actual order is more complicated, and more objects are involved, especially in drag-dock. I've already tried to create an graph with the called methods, but it doesn't scale nicely :-(

The DragObject is optional.

It's not optional, but a default object is created unless one is provided by the application in OnDragStart. In Delphi the DragObject handles the input messages, what in Lazarus is the task of the DragManager. The Delphi approach is more flexible, but not very useful without access to the many protected TControl methods and properties.

Show quoted text 7 lines
There could be multiple candidate targets. The Main Event Loop determines which event to send to which object, depending on the user action, the cursor location, and the current state of the GUI. 4 somehow triggers 5 (there is a delay depending on the Boolean parameter Immediate to BeginDrag).

In Delphi the DragObject has to be created immediately, because it handles the further input (message loop). In Lazarus the creation could be postponed, until a not-immediate drag really starts.

6 determines the location of the MouseDown and may use this to decide on what gets dragged (through GetCursorPos, ScreenToClient, MouseToCell). It can call SetDragImage to visualize a thing being dragged.

The visualization allows for many implementations, like dragging a connection from one component to another one, in a graph or flowchart construction or (electronic...) CAD application.

The chain 7, 8, 9 can occur repeatedly; 9 indicates acceptability of a drop at this target via the Boolean var parameter Accepted.

OnDragOver can occur for enter, leave and move. Usually only the result of a dsDragMove is processed further, but in a manual drag operation only the outcome of dsDragLeave is the important one, invoked from DragStop prior to 11. IMO this convention is one more design flaw.

12 is called only if the immediately preceding OnDragOver of this target returned Accepted = True; i.e. Accepted is a precondition of 12.

When a dock manager is used, OnDockOver can be omitted. Otherwise Accepted is set to True before the call to the handler.

13 receives the parameter Target to know where the drop was accepted; if Target = nil, then the drop was cancelled by the user (MouseUp at an unacceptable location), and OnDragDrop was not performed; if Target nil, then OnDragDrop was already performed at the Target.

In drag-dock there can exist 4 possible outcomes: a valid drop (dock), a valid drop on no target (float), an invalid drop (cancel), and the abort of a not yet started drag. In addition the entire operation can be aborted from the OnUnDock handler - I wonder why in this case the drag did start at all :-(

Show quoted text 5 lines
The work associated with an actual drop is thus divided over the OnDragDrop (for actions at the target) and OnEndDrag (for actions at the source). Since a Drag Object needs to be destroyed, independent of whether the drop was successful or canceled, it is best to call Free (or Destroy) only in the OnEndDrag handler.

DragObjects can be destroyed automatically, what is done for the default objects and the TDrag...ObjectEx classes. The other classes are designed for re-use, and should be created and destroyed only once for the lifetime of the application.

Show quoted text 8 lines
Only one drag can be active at any moment; it either ends in a drop or is canceled. There are various other things to be included, but this is the fundamental part. (Maybe also see <http://www.delphi-central.com/drag.aspx> or <http://www.podgoretsky.com/ftp/Docs/Delphi/D5/dg/controls.html>.) I hope this is helpful.

Of course :-)

Do you have already or want to implement some sample applications, for e.g. the demonstration of the OnDragMove visualization?

DoDi

Tom Verhoeff
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 12 lines
Tom Verhoeff schrieb: >> I've started documentation about dragging, with the first part >> (drag-drop) here: >> <http://wiki.lazarus.freepascal.org/LCL_Drag_Drop> > > It would be helpful to include a Message Sequence Chart or UML Sequence > Diagram, visualizing which objects and methods are involved in what order. Thanks for your chart :-) [...] Do you want to add it to the wiki?

I answered this in my reply to Mattias :-). In short: no time at the moment.

I know little about the way Drag&Drop is done in Lazarus, because I never used it there (only in Delphi 7).

Furthermore, it seems that you (Hans-Peter) know a lot more about it.

Do you have already or want to implement some sample applications, for e.g. the demonstration of the OnDragMove visualization?

Given my current agenda, that is unfortunately out of the question.

It would be immensely useful to have accessible documentation.

Keep It Simple, S...... Don't try to cover all possibilities at once, but break it down by what is minimally relevant, and document variants separately.

Cheers,

Tom

E-MAIL: T.Verhoeff @ TUE.NL | Dept. of Math. & Comp. Science PHONE: +31 40 247 41 25 | Technische Universiteit Eindhoven FAX: +31 40 247 54 04 | PO Box 513, NL-5600 MB Eindhoven http://www.win.tue.nl/~wstomv/ | The Netherlands