Sign in Join

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

Mailing lists / lazarus / 2008-12

Some docking theory

4 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

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

Hans-Peter Diettrich

Thanks to Paul for his engagement in the improvement of docking :-)

Here are some thoughts about the organization and management of dock zones, which should be helpful in the further development. Keys: determination of the drop zone, and how to keep the dock tree balanced.

A dock zone can have several layouts (states):
- empty: the site may be entirely invisible, or may be shrinked to a minimum size.
- single client: the client covers the entire client area of the zone, the zone has no orientation.
- notebook: the notebook covers the entire client area of the zone, and can contain any number of pages.
- horizontal or vertical stack: multiple clients reside side by side in the site's client area, separated by splitters.
- custom: any other layout, like anchor docking.

Drop zones are highlighted when a dockable client is dragged over a dock zone. Two distinct areas should be treated differently: An outer area, possibly exceeding the boundaries of the dock zone, will allow to dock new clients to the sides of the zone itself. An inner area will allow to dock new clients relative to already docked clients. This separation is missing from the current LCL implementation.

Hint: assume a row of docked clients: A-B-C. Now it should be possible to insert another client to the left or right of A,B or C A - d - B - C
looks easy ;-)

But when a new client shall reside below B
A - B - C
A - d - C
or entirely below A-B-C
A - B - C
ddddddddd
things becomes tricky!

According to above classification, the dock zones should behave somewhat differently:

An empty dock zone will signal one unique drop zone (frame), entirely covering or possibly exceeding it's current extent (in case of elastic dock zones, initially being almost invisible parts of a form). The first docked client will cover the entire zone.

A dock zone containing an single client will signal orthogonal drop zones at all four borders, for it's outer zone, and a notebook area in it's inner zone. When another client is dropped, the layout of the zone will change accordingly, into horizontal, vertical or notebook layout, or into some custom (anchored) layout.

A notebook zone can have a single inner zone, for automatically appending an added client as a new page. It also can allow for docking an dropped client relative to the existing pages, when the mouse hovers over the notebook tabs - problem: the tabs reside in the outer zone of the zone, so that some disambiguation is required. Else it should be possible to move the new client into the desired position later, by dragging the tabs.

A horizontal or vertical zone will have an outer zone only at it's orthogonal sides, the management of the remaining inner zone is delegated to it's existing clients. When a client receives an "outer" drop, it should delegate the handling to it's parent, which has to keep the tree balanced. On an drop in the direction of the host zone, that client is shrinked to make room, for the client to be added to the parent(!) zone. Otherwise the layout of the affected client's zone is adjusted, and the dropped client is inserted into it, according to the signaled orientation.

That's all, so far, but it took me many hours to distill all the observed woes of the current [L]DockTree implementation into these few principles.

One more hint: re-docking an already docked client deserves further considerations:
- When exactly will the client be removed from the tree?
- What about the node becoming free/empty, possibly turning the zone layout from horz/vert into single-client?
- What if the client is dropped into its old place?

It looks like a useful implementation to me, when the dragged client control is immediately removed from its zone, but the zone itself stays unchanged in the tree, as a now empty but not resized zone. When the client finally is dropped into his old zone, nothing has to be done at all. Otherwise the client should be docked in it's new place, *before* removing his old zone from the tree. This sequence will allow to dock the client exactly as determined and indicated (by the frame) before. [If the empty zone were removed before, the tree/site layout might change, with a possible mismatch in the intended and final drop location] The removal of the now empty zone then can be handled in exactly the way, as if the client had been undocked entirely from the tree/site. When the layout changes due to that removal, the client already sits in it's new place, so that the layout can be changed in any required way.

DoDi

Reply by email

Paul Ishenin
to Hans-Peter Diettrich

Hans-Peter Diettrich wrote:
...

That's all, so far, but it took me many hours to distill all the observed woes of the current [L]DockTree implementation into these few principles.

Will you implement this principles also?

Best regards,
Paul Ishenin.

Reply by email

Hans-Peter Diettrich
to Paul Ishenin
Will you implement this principles also?

No problem, if you provide a base class with everything else, so that the rest can be implemented in a derived class. I'm just trying to figure out the current implemention(s) of the various classes, but have no idea yet where to start.

DoDi

Reply by email

Hans-Peter Diettrich
to Paul Ishenin: ... Will you implement this principles also? Paul Ishenin.
Show quoted text 5 lines
> That's all, so far, but it took me many hours to distill all the > observed woes of the current [L]DockTree implementation into these few > principles. > Will you implement this principles also?

I've just implemented TDockTree.PositionDockRect (see appended diff). Before testing with the docking example, remove the Form1.OnDockOver handler, which replaces the DockRect again.

There is one problem with getting the dock zone extent, as you can see in the comment on dzone.FBounds, which seems to be invalid for most docking zones. The workaround with dzone.Top etc. works better, but it excludes the zone header - behaves like DropCtl.Bounds. Using the workaround makes the DockRect behave almost as in Delphi.

There exist more problems with the current implementation, apart from the bugs in the dock zone management. One problem is inherited from the Delphi interface IDockManager, which allows the docking manager to modify the DockRect, but doesn't allow to also modify the DropAlign. It wouldn't break compatibility to make DropAlign an "var" parameter in PositionDockRect, like DockRect already is. Without this or a similar patch it will be impossible to obtain values other than the top/bottom/left/right alignment, as determined by the dragged control. When the zone and alignment is only determined by the dragged control, without a chance for adjustments by the dock manager, it will be almost impossible to e.g. dock a control to the top or bottom of a horizontal row of already docked controls.

Another problem is the determination of the DropCtl, which cannot work properly when the mouse is over an dock header, not over a docked control - then DropCtl is Nil. Then the dock manager has no idea about the affected dock zone. Using the current mouse position and iterating through the dock zones doesn't work just now, because the dock zones currently do not have a valid Bounds rectangle (including the zone header). This also may be one of the reason for further errors in the handling of docked controls and docking zones.

The Delphi implementation reveals further problems, e.g. undocking a control can result in undocking an entire dock zone with more than only the intended control. A bug or a feature?

Now I wish everybody a Merry Christmas or, to be more political correct, seasonal greetings :-)

DoDi
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed... Name: PositionDockRect.diff
Url: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20081223/7c003d13/attachment.pl

Reply by email