LMD DockingPack Guide
The TLMDDockManager component can be used to save/load docking layout. Because the user can undock any number of panels and make them “floating” the saving/loading process has been designed as global process, not the process related to some concrete site.
The SaveToFile and SaveToStream methods can be used to save application docking layout. While saving the TLMDDockManager iterates through all existing in application dock sites (e.g. TLMDDockSite instances), including all floating window sites. It fires the OnSaveSite event before saving each site. The OnSaveSite event can be used as a site filter to prevent saving some particular site.
Saving is performed in XML format. Saved XML basically reflect zone structure, and can look like this:
<?xml version="1.0" encoding="utf-8"?>
<sitelist>
<site id="frmMain.Site">
<zone kind="HORZ">
<zone kind="TABS" autohide="1" activetab="0" size="209">
<zone kind="PANEL" id="frmMain.pnlCalendar" visible="1" hiddenwidth="209" hiddenheight="517"/>
<zone kind="PANEL" id="frmMain.pnlTealPanel" visible="1" hiddenwidth="209" hiddenheight="534"/>
</zone>
<zone kind="VERT" size="741" dsize="1">
<zone kind="HORZ" size="309" dsize="0.741007194244604">
<zone kind="PANEL" id="frmMain.pnlCentral" visible="1" size="521" dsize="0.708843537414966" isspace="1"/>
<zone kind="TABS" activetab="0" size="214" dsize="0.291156462585034">
<zone kind="PANEL" id="frmMain.pnlSiteStructure" visible="1"/>
<zone kind="PANEL" id="frmMain.pnlBluePanel" visible="1"/>
<zone kind="PANEL" id="frmMain.pnlGreenPanel" visible="1"/>
</zone>
</zone>
<zone kind="TABS" activetab="0" size="108" dsize="0.258992805755396">
<zone kind="PANEL" id="frmMain.pnlOutput" visible="1"/>
<zone kind="PANEL" id="frmMain.pnlCallStack" visible="1"/>
<zone kind="PANEL" id="frmMain.pnlWatches" visible="1"/>
</zone>
</zone>
</zone>
</site>
</sitelist>
Usually, document panels, including floating ones, are transient and are not considered as part of application layout. The user opens and closes documents from time to time, so the set of documents differs between application usage sessions.
Docking layout can be saved skipping space zone content (tabbed documents) as well as floating documents. The layout can be loaded back while preserving current space zone content (tabbed documents) and floating documents. New save and load method overloads include additional flags parameter to control this behavior:
DockManager.SaveToFile('layout.xml', [sfExcludeSpace, sfExcludeFloatDocs]);
DockManager.LoadFromFile('layout.xml', [lfPreserveSpace]);
During saving sfExcludeSpace flag excludes all panels, resided inside space zone, from being saved into layout XML. All tabbed documents will be excluded. As well, if some tool panels has been docked into space zone, they also will not be saved. sfExcludeFloatDocs flag excludes all floating document forms.
During loading lfPreserveSpace flag allows to preserve current space zone layout without re-loading it from layout XML. Internally, this flag forces loading algorithm do the following steps for each loading site:
•Save current space zone state into temporary memory stream. Each tabbed document should have a proper ID.
•Load site's layout from specified XML, ignoring space zone content.
•Restore space zone content by loading it from temporary memory stream.
Existing floating documents will not be affected by loading algorithm, if they are not present in loading layout XML (if sfExcludeFloatDocs was used during saving).
OnWriteAppInfo event can be used to write some additional application depended info into XML. This can be, for example, the main application form bounds. The LoadFromFile and LoadFromStream methods can be used to load back previously saved layout. The OnReadAppInfo event handler can be used to read back and apply additional application depended info from the XML:
procedure MainForm.DockManagerWriteAppInfo(Sender: TObject;
const Xml: ILMDXmlDocument);
var
elem: ILMDXmlElement;
i: Integer;
begin
elem := Xml.DocumentElement.AppendElement('application');
elem.SetIntAttr('left', MainForm.Left);
elem.SetIntAttr('top', MainForm.Top);
elem.SetIntAttr('width', MainForm.Width);
elem.SetIntAttr('height', MainForm.Height);
end;
procedure MainForm.DockManagerReadAppInfo(Sender: TObject;
const Xml: ILMDXmlDocument);
var
i: Integer;
elem: ILMDXmlElement;
comp: TComponent;
begin
elem := Xml.DocumentElement.FindElement('application', '', Null);
if elem <> nil then
begin
SetBounds(elem.GetIntAttr('left', MainForm.Left),
elem.GetIntAttr('top', MainForm.Top),
elem.GetIntAttr('width', MainForm.Width),
elem.GetIntAttr('height', MainForm.Height));
end;
end;
The OnWriteAppInfo event handler shown above will produce the following XML:
<?xml version="1.0" encoding="utf-8"?>
<sitelist>
...
<application left="411" top="264" width="790" height="493"/>
</sitelist>
Assigning False value to the LoadDesignLayout property of the site at design-time prevents the site to apply the design-time layout at the application start (e.g. while form components loading). So, the empty site will be shown after application start. This can prevent visual flickers while loading previously saved layout.
At the application start the application can check whether the layout has been previously saved (e.g. for example, whether the file exists), and load saved layout directly, skipping applying design-time layout. However, if layout has not been saved, then the design-time layout can be safely applied by calling ApplyDesignLayout method of the TLMDDockManager component. This method also iterates through all existing sites and applies the design-time layout, if required.