Docking framework

An user interface usually consists of some panels.

The docking framework provides a way to change layout.

The user can move panels by using drag and drop from one place to another and can change panels size.

The basic docking framework component is the Frame. A frame can be created by CreateFrame method.

The user can move a panel-frame between:

A new tab or page created when the user moves a panel into a multi-page component, TabControl or PageControl, respectively.

Two options available when the user moves a panel into a Frame or Form :

If the panel is moving on the left, right, top or bottom side of the target frame (AL_LEFT, AL_RIGHT, AL_TOP, AL_BOTTOM, respectively), then the new mutial parent will be a new Frame.

The panel and the target frame will be divided by a splitter. The user can change size of the panel and the target frame with the splitter.

If the panel is moving onto the target frame (as AL_CLIENT) then the new mutial parent will be a multi-page component, TabControl or PageControl.

AlwaysDockTab and AlwaysDockPage properties

If a frame's AlwaysDockTab = "TRUE" then a new parent TabControl will be created automatically for the frame.

In the first example a usual Frame is created. The value of the Text property is not visible.

o = new ActiveXObject("Scripting.WindowSystemObject")

o.EnableVisualStyles = true

f = o.CreateForm(0,0,0,0)

f.Text = "WSO"
f.ClientWidth = 200
f.ClientHeight = 100
f.CenterControl()

Frame = f.CreateFrame(10,10,180,80)
Frame.BevelOuter = o.Translate("BS_RAISED")
Frame.TextOut(10,10,"Test")
Frame.Text = "Frame"

f.Show()

o.Run()

Frame.jpg

In the second example a Frame with AlwaysDockTab = "TRUE" is created. The value of the Text property used for the tab's text.

o = new ActiveXObject("Scripting.WindowSystemObject")

o.EnableVisualStyles = true

f = o.CreateForm(0,0,0,0)

f.Text = "WSO"
f.ClientWidth = 200
f.ClientHeight = 100
f.CenterControl()

Frame = f.CreateFrame(10,10,180,80)
Frame.BevelOuter = o.Translate("BS_RAISED")
Frame.TextOut(10,10,"Test")
Frame.Text = "Frame"
Frame.Docking.AlwaysDockTab = true

f.Show()

o.Run()

Frame_AlwaysDockTab.jpg

The user can press down the left mouse button on the panel's tab header and, keeping the button down, move mouse. The Frame will be moved out the tab control and placed info a new docking Form. The previous panel's parent - tab will be deleted. If the tab is the last tab in the tab control then the tab control will be deleted also.

If a frame's AlwaysDockPage = "TRUE" then a new parent PageControl will be created automatically for the frame. It works similar the previous case.

Moving the docking form

The docking buttons will be shown when the docking form will be above a target component.

The target component must have DropTarget = "TRUE".

A docking button specifies a required control layout relatively the target component.

The mouse cursor must be moved above some docking button. The moving panel will be placed onto target component when the user releases the mouse button.

Example 1:

The moving panel will be placed into a new tab of target's TabControl when the user uses the center button.

The moving panel will be placed as a neighbour of target when the user uses the left, top, right or button button.

DockingFramework1.jpg

Example 2:

Additional buttons allows the user to place the panel as a child of the target.

DockingFramework2.jpg

Example 3:

Additional buttons allows the user to place the panel as a neighbour of the target with conversion of multi-page container type from the panel's type to the target's type.

DockingFramework3.jpg

Example 4:

Only buttons for moving the panel as a child of the target allowed.

Note:
If the target have AllowDockAsChild = "TRUE" then the center button moves the panel as a child with Align = AL_CLIENT. Otherwise the center button moves the panel as a neighbour onto target and the panel and the target will be placed into mutial parent multi-page container, TabControl or PageControl .
DockingFramework4.jpg

The target component must have DropTarget = "TRUE".

Since:
1.1.15.
See also:
Demo\JScript\Docking\Docking.js.
Example:

//WindowSystemObject (WSO) sample
//Copyright (C) Veretennikov A. B. 2004-2015

o = new ActiveXObject("Scripting.WindowSystemObject")

o.EnableVisualStyles = true

f = o.CreateForm(0,0,0,0)

f.ClientWidth = 600
f.ClientHeight = 400
f.CenterControl()
f.Text = "Docking framework example"
var Panels = new Array()
f.Docking.UniqueId = "Form1"
f.Docking.DropTarget = true
f.AutoSplit = true

function CreateDocument(Name)
{
        var Doc = f.CreateFrame(10,10,100,100)
        Doc.Text = Name
        var Edit = Doc.CreateEdit(0,0,0,0,o.translate("ES_MULTILINE"))
        Edit.Align = o.Translate("AL_CLIENT")
        Doc.Align = o.Translate("AL_CLIENT")
        Doc.Docking.AlwaysDockTab = true
        Doc.Docking.DropTarget = true
        Doc.Docking.UniqueId = Name
        Edit.Text = "Some text where"
        Panels[Name]=Doc
        return Doc      
}

function CreatePanel(Name)
{
        var Panel = f.CreateFrame(10,10,150,100)
        Panel.Text = Name
        Panel.Align = o.Translate("AL_LEFT")
        Panel.Docking.AlwaysDockPage = true
        Panel.Docking.DropTarget = true
        Panel.Docking.UniqueId = Name
        Panels[Name]=Panel
        return Panel
}

function CreateBottomPanel(Name)
{
        var Panel = f.CreateFrame(10,10,100,100)
        Panel.Text = Name
        Panel.Align = o.Translate("AL_BOTTOM")
        Panel.Docking.AlwaysDockPage = true
        Panel.Docking.DropTarget = true
        Panel.Docking.UniqueId = Name
        Panels[Name]=Panel
        return Panel
}

Doc1 = CreateDocument("Doc1")

for (i = 2; i<4; i++)
{
        Doc = CreateDocument("Doc"+i)
        Doc1.Docking.DockAsNeighbour(Doc,o.Translate("AL_CLIENT"))
}
Doc1.Parent.Visible = true

SearchPanel = CreateBottomPanel("Search")
ConsolePanel = CreateBottomPanel("Console")
with (ConsolePanel)
{
        with (CreateEdit(0,0,0,0,o.Translate("ES_MULTILINE | ES_READONLY")))
        {
                Align = o.Translate("AL_CLIENT")        
                Add("Line 1")
                Add("Line 2")
                Add("Line 3")
        }
}
with (SearchPanel)
{
        with (CreateEdit(0,0,0,0,o.Translate("ES_MULTILINE | ES_READONLY")))
        {
                Align = o.Translate("AL_CLIENT")        
                Add("Search result 1")
                Add("Search result 2")
                Add("Search result 3")
        }
}


SearchPanel.Docking.DockAsNeighbour(ConsolePanel,o.Translate("AL_CLIENT"))


ContextPanel = CreatePanel("Context")
var TreeView = ContextPanel.CreateTreeView(0,0,0,0)
TreeView.Align = o.Translate("AL_CLIENT")
var Root = TreeView.Items.Add("Item 1")
for (i = 1; i<5; i++)
{
        Root.Add("Item 1."+i)
}
Root.Expand()


IndexPanel = CreatePanel("Index")
var ListBox = IndexPanel.CreateListBox(0,0,0,0)
ListBox.Align = o.Translate("AL_CLIENT")
for (i = 1; i<5; i++)
{
        ListBox.Add("Item 1."+i)
}

ContextPanel.Docking.DockAsNeighbour(IndexPanel,o.Translate("AL_CLIENT"))
HelpPanel = CreatePanel("Help")
ContextPanel.Docking.DockAsNeighbour(HelpPanel,o.Translate("AL_CLIENT"))
ContextPanel.Parent.Visible = true
HelpPanel.TextOut(10,10,"Some Help can be there")

File = f.Menu.Add("File")
File.Add("Exit").OnExecute = CloseFormHandler

Windows = f.Menu.Add("Windows")
for (Name in Panels)
{
        Item = Windows.Add(Name)
        Item.OnExecute = ShowPanel
}

function ShowPanel(Sender)
{
        Panel = Panels[Sender.Text]
        while (true)
        {
                Panel.Visible = true
                if (Panel.Type == "Form")
                        break
                Panel = Panel.Parent
        }
}

Layout = f.Menu.Add("Layout")
Layout.Add("Save").OnExecute = SaveLayout
Layout.Add("Load").OnExecute = LoadLayout

f.Show()

o.Run()

function CloseFormHandler(Sender)
{
        Sender.Form.Close()
}



function SaveLayout()
{
        Text = o.SaveLayout()
        FSO = new ActiveXObject("Scripting.FileSystemObject")
        var File = FSO.CreateTextFile(LayoutFile())
        File.WriteLine(Text)
        File.Close()
}


function LoadLayout()
{
        var File = LayoutFile()
        FSO = new ActiveXObject("Scripting.FileSystemObject")
        if (!FSO.FileExists(File))
        {
                f.MessageBox("File "+File+" does not exists")
                return
        }
        var File = FSO.OpenTextFile(File)
        Text = File.ReadAll()
        File.Close()
        o.LoadLayout(Text)
}



function CurrentDir() 
{
        var s = WScript.ScriptFullName; 
        s = s.substring(0,s.lastIndexOf("\\") + 1); 
        return s; 
};

function LayoutFile()
{
        return ConfigurationFolder() + "Docking.txt"
}

function ConfigurationFolder()
{
        FSO = new ActiveXObject("Scripting.FileSystemObject")
        var Path = FSO.GetSpecialFolder(TemporaryFolder = 2)+"\\WSOExamples"
        if (!FSO.FolderExists(Path))
                FSO.CreateFolder(Path)
        return Path+"\\"
}

Docking.jpg

Docking2.jpg

Note:
In addition to Docking::AlwaysDockPage and Docking::AlwaysDockTab the Docking::PageControlTag property specifies different kinds of multi-page components of same type. For example, different kinds of the PageControl.
See also:
Demo\JScript\Docking\DockingEx.js.
Example:

//WindowSystemObject (WSO) sample
//Copyright (C) Veretennikov A. B. 2004-2015

o = new ActiveXObject("Scripting.WindowSystemObject")

o.EnableVisualStyles = true

f = o.CreateForm(0,0,0,0)

f.ClientWidth = 600
f.ClientHeight = 400
f.CenterControl()
f.Text = "Docking framework example"
var Panels = new Array()
f.Docking.UniqueId = "Form1"
f.Docking.DropTarget = true
f.AutoSplit = true
f.Color = 0x00BEAE9E

f.BorderWidth = 5

function CreateDocument(Name)
{
        var Doc = f.CreateFrame(10,10,100,100)
        Doc.Docking.PageControlTag = 1

        Doc.OnDockControlCreate = DocOnDockControlCreate
        Doc.OnBeginDock = DocOnBeginDock

        Doc.Text = Name
        var Edit = Doc.CreateEdit(0,0,0,0,o.translate("ES_MULTILINE"))
        Edit.Align = o.Translate("AL_CLIENT")
        Doc.Align = o.Translate("AL_CLIENT")
        Doc.Docking.AlwaysDockPage = true
        Doc.Docking.DropTarget = true
        Doc.Docking.UniqueId = Name
        Edit.Text = "Some text where - " + Name
        Panels[Name]=Doc

        return Doc      
}

function DocOnDockControlCreate(Sender,Control,DockTarget,Context)
{
        if (Control.Type == "Frame")
        {
                Control.Color = 0x00BEAE9E
                Control.ParentBackground = false
        }
        if (Control.Type == "PageControl")
        {
                if (Control.Docking.PageControlTag == 1)
                {
                        Control.HeaderVisible = false
                        Control.TabsAlign = o.Translate("AL_TOP")
                        Control.FlatButtons = false
                        Control.ShowSingleTab = true
                        Control.TabCloseButton = true
                        Control.HideClippedTabs = true
                        
                }
        }
}

function DocOnBeginDock(Sender,DockTarget,Context)
{

}

function CreatePanel(Name)
{
        var Panel = f.CreateFrame(10, 10, 150, 100)

        Panel.OnDockControlCreate = DocOnDockControlCreate
        Panel.OnBeginDock = DocOnBeginDock      
    
        Panel.Text = Name
        Panel.Align = o.Translate("AL_LEFT")
        Panel.Docking.AlwaysDockPage = true
        Panel.Docking.DropTarget = true
        Panel.Docking.UniqueId = Name
        Panels[Name]=Panel
        return Panel
}

function CreateBottomPanel(Name)
{
        var Panel = f.CreateFrame(10, 10, 100, 100)

        Panel.OnDockControlCreate = DocOnDockControlCreate
        Panel.OnBeginDock = DocOnBeginDock      
        
        Panel.Text = Name
        Panel.Align = o.Translate("AL_BOTTOM")
        Panel.Docking.AlwaysDockPage = true
        Panel.Docking.DropTarget = true
        Panel.Docking.UniqueId = Name
        Panels[Name]=Panel
        return Panel
}

Doc1 = CreateDocument("Doc1")

for (i = 2; i<4; i++)
{
        Doc = CreateDocument("Doc"+i)
        Doc1.Docking.DockAsNeighbour(Doc,o.Translate("AL_CLIENT"))
}
Doc1.Parent.Visible = true

SearchPanel = CreateBottomPanel("Search")
ConsolePanel = CreateBottomPanel("Console")
with (ConsolePanel)
{
        with (CreateEdit(0,0,0,0,o.Translate("ES_MULTILINE | ES_READONLY")))
        {
                Align = o.Translate("AL_CLIENT")        
                Add("Line 1")
                Add("Line 2")
                Add("Line 3")
        }
}
with (SearchPanel)
{
        with (CreateEdit(0,0,0,0,o.Translate("ES_MULTILINE | ES_READONLY")))
        {
                Align = o.Translate("AL_CLIENT")        
                Add("Search result 1")
                Add("Search result 2")
                Add("Search result 3")
        }
}


SearchPanel.Docking.DockAsNeighbour(ConsolePanel,o.Translate("AL_CLIENT"))


ContextPanel = CreatePanel("Context")
var TreeView = ContextPanel.CreateTreeView(0,0,0,0)
TreeView.Align = o.Translate("AL_CLIENT")
var Root = TreeView.Items.Add("Item 1")
for (i = 1; i<5; i++)
{
        Root.Add("Item 1."+i)
}
Root.Expand()


IndexPanel = CreatePanel("Index")
var ListBox = IndexPanel.CreateListBox(0,0,0,0)
ListBox.Align = o.Translate("AL_CLIENT")
for (i = 1; i<5; i++)
{
        ListBox.Add("Item 1."+i)
}

ContextPanel.Docking.DockAsNeighbour(IndexPanel,o.Translate("AL_CLIENT"))
HelpPanel = CreatePanel("Help")
ContextPanel.Docking.DockAsNeighbour(HelpPanel,o.Translate("AL_CLIENT"))
ContextPanel.Parent.Visible = true
HelpPanel.TextOut(10,10,"Some Help can be there")

File = f.Menu.Add("File")
File.Add("Exit").OnExecute = CloseFormHandler

Windows = f.Menu.Add("Windows")
for (Name in Panels)
{
        Item = Windows.Add(Name)
        Item.OnExecute = ShowPanel
}

function ShowPanel(Sender)
{
        Panel = Panels[Sender.Text]
        while (true)
        {
                Panel.Visible = true
                if (Panel.Type == "Form")
                        break
                Panel = Panel.Parent
        }
}

Layout = f.Menu.Add("Layout")
Layout.Add("Save").OnExecute = SaveLayout
Layout.Add("Load").OnExecute = LoadLayout

f.Show()

o.Run()

function CloseFormHandler(Sender)
{
        Sender.Form.Close()
}



function SaveLayout()
{
        Text = o.SaveLayout()
        FSO = new ActiveXObject("Scripting.FileSystemObject")
        var File = FSO.CreateTextFile(LayoutFile())
        File.WriteLine(Text)
        File.Close()
}


function LoadLayout()
{
        var File = LayoutFile()
        FSO = new ActiveXObject("Scripting.FileSystemObject")
        if (!FSO.FileExists(File))
        {
                f.MessageBox("File "+File+" does not exists")
                return
        }
        var File = FSO.OpenTextFile(File)
        Text = File.ReadAll()
        File.Close()
        o.LoadLayout(Text)
}



function CurrentDir() 
{
        var s = WScript.ScriptFullName; 
        s = s.substring(0,s.lastIndexOf("\\") + 1); 
        return s; 
};

function LayoutFile()
{
        return ConfigurationFolder() + "DockingEx.txt"
}

function ConfigurationFolder()
{
        FSO = new ActiveXObject("Scripting.FileSystemObject")
        var Path = FSO.GetSpecialFolder(TemporaryFolder = 2)+"\\WSOExamples"
        if (!FSO.FolderExists(Path))
                FSO.CreateFolder(Path)
        return Path+"\\"
}

DockingEx.jpg

WSO 1.1 Documentation. Date modified:Wed Aug 12 18:12:13 2015. (C) Veretennikov A. B. 2004-2015