Wednesday, May 27, 2009

Compatibility

Okay, FreePascal and Lazarus have to be compatible with Delphi, so that existing Delphi code can be used immediately. But what about new applications?

The Delphi VCL is dedicated to Windows, and for multi-platform applications the CLX was derived. So I wonder why Lazarus should try to cover all widgetsets with a model, that obviously is not suited for widgetsets other than Win32.

What would really change, when a LCX were added to the LCL? Not really much, I think. The LCL could stay compatible by emulating controls, that are not immediately available in a Win32 compatible form on other widgetsets, as mono does, or fpGUI. The multi-platform LCX instead could change the component model, in a way that allows to use existing components of other widgetsets almost immediately.

A different model were required e.g. for drag&drop support, where easy integration into other widgetsets could be achieved, and at the same time we could get rid of the flaws in the VCL model.

Layout management is another candidate for a different model. The Delphi docking managers are layout managers in the first place, with only an added interface to the drag manager. I cannot imagine any reason, why a layout manager has to be built into TWinControl, instead of making it linkable like an docking manager. Then we could have dedicated layout mangers for e.g. toolbars and dock trees, without a need to squeeze all layout features into one basic (anchored) layout model, that has no counterpart in the VCL.

Thursday, May 21, 2009

A Great Day

This morning I could make Paul fix some bugs, related to docking, and then I could make work a notebook for docking! A milestone, worth to remember :-)

We had a discussion about mouse messages and events, and we disagreed, as usual . Here my thoughts about this topic:

Pressing an mouse button (in detail the left one) can mean many things. Most obvious is the begin of a sequence of clicks, where Lazarus for some reason supports up to quadruple clicks. If only one event shall be signaled, then the handling of the mouse up and down messages must be delayed, until the timeout or maximum sequence number is reached. When a mouse down also can start dragging, processing can be inlined into that delayed handling. As the word says, "drag" means *moving* something, so that an automatic dragging operation always should start only after an significant move of the mouse. When the dragging threshold was not reached on mouse up, no dragging actions or messages should have occured, and the click processing should continue.

Such processing would eliminate the long standing note on WM_MOUSEDOWN in TControl.WndProc, where Delphi stops further processing after starting the dragmanager, and the LCL continues to process the message. IMO it would be much more transparent to stop handling of the message, and to leave it to the drag manager to delay further processing, until it's clear whether a drag should start, or normal click handling should occur. Or the drag manager could be invoked only in that place, where a mouse move would break a sequence of clicks. This latter solution would concentrate all decisions in one place, so that conflicts with already started dragging operations can no more occur. The TControl.IsDragging method could be based on a flag in the control's state, that steers the handling of all mouse messages. The control states then become:


IDLE <down ---> DOWN /move ---> DRAGGING <up ---> DROPPED
\ up ---> 1CLICK - - - > 4CLICK


Then also the dragging threshold could reflect the system threshold, not an application specific (and consequently unexpected) value.

Tuesday, May 19, 2009

Messages from the Mouse

The handling of mouse button messages is a mess :-(

An attempt to start dragging of a control, from a click on the zone header, seems to block proper processing of further messages. We should re-think the handling of WM_LBUTTONDOWN, with regards to multiple widgetsets and dragging.

When the left button is pressed over a control with DragMode=dmAutomatic, the drag manager should handle this and further messages. It seems not to be a problem to capture input, but the drag manager is responsible for the distinction of immedately started dragging, delayed started dragging (using threshold), and simple clicks on mouse up before dragging starts (threshold not reached). When dragging starts, the dragged control should either not have processed the button down message, or must be reset into unpressed state (CancelMode). When no drag really starts, the drag manager can send both an down and up message to the control, so that it can react on an click in the usual way.

Effectively a mouse button down message should be processed either by the drag manager or by the control, but not by both at the same time!

BTW, dragging from the zone header now works on Linux/gtk2, but no more on Windows/win32 widgetset.

Monday, May 18, 2009

Back to the Roots

Now I've tried to get the best out of three worlds, and could make docking work again. The dock helpers moved into the dock site unit, and multiple or configurable dock headers will come soon. Unfortunately some features got lost, for sometimes obscure reasons. At least the layout still works more stable than LDockTree, when multiple zones come into play.

Friday, May 15, 2009

How fragile a simple model can be...

In the last updates of the EasyTree I "only" changed the zone orientation meaning, and moved the splitter from the zone header to the opposite side of the zone - and now the layout seems to be broken :-(

While everything looked fine at the first glance, when docking and undocking components, some zones refused to resize properly. The more I tried to find the reason for that strange behaviour, the less I understood what really was going on. When I finally tried to redesign the entire handling of the zone bounds, I learned more about the subtle design of my tree model, and that it was not a good idea to change it at all.

Now I have to revert to the last working state, long before the addition of the notebook zones, and must verify that in this state all zones resize properly. Then I can introduce the notebooks again, and hope that then they will resize properly.

Wednesday, May 13, 2009

What will happen on the end of a drag?

When a drag-drop operation ends, the target control is notified of the drop. The entire operation can be canceled by pressing the ESC button.

But when a docking operation ends, we should have more options. The "normal" end will dock the dragged component into the target host site, or the component will become (or stay) floating on the screen, or the entire operation will be aborted. The user should get enough visible feedback, so that he can know what will happen when he releases the mouse button. The following changes to the LCL are suggested:

A NoDrop cursor should be used, when nothing will happen on a drop. This kind of feedback is essential when the dragged component would be dropped onto itself, whereupon nothing should happen at all. This feature is not part of the Delphi/Lazarus drag-drop implementation, where the default docking object does not support state specific cursors, and the drag object has no property for an NoDrop state at all.

The Lazarus implementation also doesn't handle the CTRL key, for making a component float even if it moves over a dock site.

Now I hope that the according patches are added to the LCL soon...

Fundamentals

Dragging GUI elements is a widely used technique, available on most platforms. Delphi has rudimentary support for both drag-drop (copy contents) and drag-dock (move forms or components), but the support for docking is a mess :-(

Lazarus already has slightly improved support for docking, but still lacks some features, and the support is platform dependent. While the platform specific support will be improved over time, by the famous Lazarus team, I feel a need to discuss the general implementation of dragging (DragManager etc.), and the available or missing features.

For some documentation on dragging visit the Lazarus wiki, and for a live example run the Lazarus\examples\dockmanager\easydocking project. More example projects are in preparation.