Difference between revisions of "EasyDockingManager"

From Free Pascal wiki
Jump to navigationJump to search
Line 27: Line 27:
 
But how does the DockMaster know whether a docked form already exists, or whether a new instance has to be created?
 
But how does the DockMaster know whether a docked form already exists, or whether a new instance has to be created?
 
This requires that all dockable forms have the same Owner (TComponent), which includes a list of all already created dockable form or component instances. In default GUI applications the Application object is the Owner of all Forms, the Lazarus IDE instead uses a dedicated OwningComponent for this purpose.
 
This requires that all dockable forms have the same Owner (TComponent), which includes a list of all already created dockable form or component instances. In default GUI applications the Application object is the Owner of all Forms, the Lazarus IDE instead uses a dedicated OwningComponent for this purpose.
 +
 +
==== Further Options ====
 +
Above issues currently are reflected in $DEFINEs in uMakeSite, and in a DockMaster.Factory field. These and some more issues deserve further consideration (discussion). I'd like to remove the Defines and to replace them by meaningful conventions, suitable for all application cases.
 +
 +
When restored forms deserve further parameters, like editor components should reload the previously edited file, then the Delphi-inherited TWinControl.ReloadDockedControl(CtrlName) is insufficient. We could add an inverse method SaveDockedControl, that returns an string containing '''all''' information about a docked control, not only its name. This method can be added to TWinControl, or to a new TDockingFactory class used for DockMaster.Factory. When SaveDockedControl is implemented to return an string with more than only the control name, then of course that string must be handled in ReloadDockedControl, because the DockMaster has no idea how to extract the control name and class from such an string.
 +
 +
Another issue is notebook docking. The Delphi docking model offers no special means to restore DockBooks, neither by nesting DockSites nor by integration into an extended DockManager. The EasyDockTree manager already abuses alCustom for notebook docking, and could be extended to handle notebook contents (tabs), and eventually recursively the layout of notebook pages as further DockSites. Any opinions?
 +
 +
My docking notebooks differ from the IDE SourceEditor notebooks, at least in the handling of the docked pages. Since it depends on the platforms, which components can be made dockable how, I use the notebook tabs as docking grips. The pages of a DockBook are not related to each other, every dockable control can be docked as a notebook page, and can be undocked independently as well. Thus notebooks also can be docked into notebooks, what would allow e.g. to hold the included files of a source unit in a dedicated (nested) notebook, together with the unit source itself. OTOH the IDE SourceNotebook seems to be a specialized form class, handling only docked SourceEditor pages, what does not integrate well into the general layout Save/Load procedures. As long as the SourceNotebook form has no other components apart from the notebook itself, I'd suggest to refactor the SourceEditors into independent components (forms, frames...), that can be docked in whatever way the user likes.
  
 
=== The EasyDockTree Manager ===
 
=== The EasyDockTree Manager ===

Revision as of 08:06, 2 December 2009

Easy Docking Manager Package

The examples/EasyDockMgr package offers several helpers for docking support. This entry is organized in multiple levels, which cover different views on the docking topics.

Please note: All mentioned names may change in a final release!

Adding Docking Support to an entire Application

In the most simple case you make one or more forms of your application DockSites, to which other forms can be docked. Then make selected or all other forms dockable, and everything else will be done for you :-)

Prerequisites

The uMakeSite unit defines a DockMaster class and variable (singleton), that manages all docking issues.

Making a Form a DockSite

Use DockMaster.AddElasticSites() to make a form a DockSite. Currently docking regions (panels) can be added to the left, right and bottom of a form. "Elastic" here means that the docking regions are almost invisible, as long as nothing is docked into them. When a first component is docked into such a region, the panel extends either within the form, reducing the form's client area, or it expands the form, depending on where exactly the component is dropped. The DockRect frame indicates which kind of expansion will occur on a drop. The size of every docking region can be adjusted later by moving its associated splitter.

Making a Form dockable

Use DockMaster.MakeDockable() to make any of your forms dockable. This includes setting the related properties (DragKind...), and a pin-shaped dock grip is added to the form. This grip is needed on platforms that do not (yet) support for dragging entire forms, its exact appearance and placement may be changed.

When a form doesn't deserve special initialization, DockMaster.CreateDockable() can be used to also create the dockable form, given a form name. Here the form name must correspond to a registered form class name, and it can include an instance number. E.g. "Form3" will create a form of class "TForm3" when fMultiInst is False. When fMultiInst is True, e.g. "DockForm2" will create a form of class "TDockForm", named "DockForm2".

Saving and Restoring a Layout

If you want your application to restore the previous docked layout on the next start, DockMaster.SaveToStream() stores all required layout information in the given stream. It's your responsibility to provide an according TFileStream. You can store different layouts in different files, if you like.

DockMaster.LoadFromStream() restores the previously stored layout. This means that the elastic and floating dock sites are created, and the previously docked forms are searched or created, and then are docked into their previous places.

But how does the DockMaster know whether a docked form already exists, or whether a new instance has to be created? This requires that all dockable forms have the same Owner (TComponent), which includes a list of all already created dockable form or component instances. In default GUI applications the Application object is the Owner of all Forms, the Lazarus IDE instead uses a dedicated OwningComponent for this purpose.

Further Options

Above issues currently are reflected in $DEFINEs in uMakeSite, and in a DockMaster.Factory field. These and some more issues deserve further consideration (discussion). I'd like to remove the Defines and to replace them by meaningful conventions, suitable for all application cases.

When restored forms deserve further parameters, like editor components should reload the previously edited file, then the Delphi-inherited TWinControl.ReloadDockedControl(CtrlName) is insufficient. We could add an inverse method SaveDockedControl, that returns an string containing all information about a docked control, not only its name. This method can be added to TWinControl, or to a new TDockingFactory class used for DockMaster.Factory. When SaveDockedControl is implemented to return an string with more than only the control name, then of course that string must be handled in ReloadDockedControl, because the DockMaster has no idea how to extract the control name and class from such an string.

Another issue is notebook docking. The Delphi docking model offers no special means to restore DockBooks, neither by nesting DockSites nor by integration into an extended DockManager. The EasyDockTree manager already abuses alCustom for notebook docking, and could be extended to handle notebook contents (tabs), and eventually recursively the layout of notebook pages as further DockSites. Any opinions?

My docking notebooks differ from the IDE SourceEditor notebooks, at least in the handling of the docked pages. Since it depends on the platforms, which components can be made dockable how, I use the notebook tabs as docking grips. The pages of a DockBook are not related to each other, every dockable control can be docked as a notebook page, and can be undocked independently as well. Thus notebooks also can be docked into notebooks, what would allow e.g. to hold the included files of a source unit in a dedicated (nested) notebook, together with the unit source itself. OTOH the IDE SourceNotebook seems to be a specialized form class, handling only docked SourceEditor pages, what does not integrate well into the general layout Save/Load procedures. As long as the SourceNotebook form has no other components apart from the notebook itself, I'd suggest to refactor the SourceEditors into independent components (forms, frames...), that can be docked in whatever way the user likes.

The EasyDockTree Manager

Almost every DockSite needs an DockManager. The EasyDockTree manager allows to build an dock tree, that grows by docking other components to any side (top/bottom, left/right) of an already docked component. Dropping a component into the middle of another component creates a tabbed notebook, to which more components can be docked as notebook pages.

Docking Helper Classes

A FloatingSite is a container form for other components, that possibly cannot exist without a parent form (TControl). It also acts as an entire docking site (form), to which other components can be docked.

A DockBook also is a container form for other components, that keeps docked components in distinct notebook pages, while a FloatingSite shows the docked components beneath each other.