Многопанельный интерфейс (Docking framework).

Многопанельный интерфейс состоит из панелей.

Пользователь может менять расположение панелей с помощью мышки, перетаскивая их из одного оконного компонента в другой (Drag and Drop).

Панели также можно извлекать из основного окна в новые вспомогательные окна, которые создаются автоматически при вытаскивании панели из ее текущего расположения.

Основной компонент-панель для организации многопанельного интерфейса Frame. Его можно создать с помощью метода CreateFrame.

Пользователь может перетаскивать панели между:

При этом при помещении в многостраничный компонент, TabControl или PageControl, для панели создается отдельная страница-закладка.

При помещении в Frame или Form доступны два варианта:

Если перемещаемый компонент помещается относительно целевого компонента слева, права, сверху, снизу (AL_LEFT, AL_RIGHT, AL_TOP, AL_BOTTOM, соответственно), то в качестве родительского компонента создается Frame. При этом дочерние компоненты автоматически разделяются разделителем, с помощью которого можно менять их размеры.

Если перемещаемый компонент помещается на целевой компонент (аналогично AL_CLIENT), то в качестве общего родительского компонента создается многостраничный компонент TabControl или PageControl.

Свойства AlwaysDockTab и AlwaysDockPage

Если AlwaysDockTab = "TRUE", то для Frame автоматически создается родительский TabControl.

Следующий пример создает обычный Frame. Можно заметить, что значение свойства 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"

f.Show()

o.Run()

Frame.jpg

Следующий пример создает Frame с AlwaysDockTab = "TRUE". Значение свойства 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

Для перетаскивания контрола пользователь нажимает левую кнопку мышки на заголовок закладки и, удерживая кнопку мышки нажатой, перемещает ее. Frame извлекается из закладки и помещается в создаваемую Form. Текущая закладка будет удалена. TabControl также удаляется, если в нем больше не остается закладок.

Родительский TabControl создается автоматически при изменении свойства, а также при перемещении панели в другой компонент, если целевой компонент не является многостраничным компонентом, например, при перемещении панели в новый Frame.

Если AlwaysDockPage = "TRUE", то для Frame автоматически создается родительский PageControl. Работа с PageControl осуществляется аналогично TabControl, т. е. используется заголовок закладки.

Перемещение формы с компонентом

Когда перемещаемая форма оказывается поверх целевого компонента отображаются кнопки, которые определяют, каким образом компонент будет располагаться относительно целевого компонента.

Целевой компонент должен иметь DropTarget = "TRUE".

Указатель мышки должен быть помещен на одну из появляющихся кнопок.

Когда пользователь отпустит клавишу мышки, перетаскиваемый компонент будет перемещен в целевой компонент.

Пример 1:

На следующем изображении показаны возможные кнопки, когда некоторый компонент помещается на другой компонент:

При выборе кнопки в центре перемещаемый и целевой компоненты будет помещены в качестве закладок на многостраничном компоненте. При выборе кнопок по краям перемещаемый компонент будет помещен рядом с целевым компонентом.

DockingFramework1.jpg

Пример 2:

На следующем изображении показаны возможные кнопки, когда

Добавляются дополнительные кнопки, которые соответствуют помещению перемещаемого компонента как дочернего компонента в целевой компонент.

DockingFramework2.jpg

Пример 3:

На следующем изображении показаны возможные кнопки, когда:

Добавляются дополнительные кнопки. Эти кнопки означают, что перемещаемый компонент будет помещен рядом с целевым компонентом, но его тип многостраничного компонента будет преобразован в тип многостраничного компонента целевого компонента.

DockingFramework3.jpg

Пример 4:

На следующем изображении показаны возможные кнопки, когда:

Доступны только кнопки для помещения компонента как дочернего в целевой компонент.

DockingFramework4.jpg

Заметки:
Если целевой компонент имеет AllowDockAsChild = "TRUE", то при нажатии на центральную кнопку перемещаемый компонент будет помещен внутрь целевого компонента, с Align = AL_CLIENT. В ином случае при нажатии на центральную кнопку перемещаемый компонент будет помещен как соседний компонент на целевой компонент, т. е. оба они будут помещены на закладки общего многостраничного контейнера, TabControl или PageControl .
Целевой компонент должен иметь DropTarget = "TRUE".

Начиная с:
1.1.15.
См. также:
Demo\JScript\Docking\Docking.js.
Пример:

//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

Заметки:
В дополнение к Docking::AlwaysDockPage и Docking::AlwaysDockTab свойство Docking::PageControlTag позволяет ввести разные виды многостраничных компонентов одинакового типа.
См. также:
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. Последние изменения:Wed Aug 12 18:10:22 2015. (C) Веретенников А. Б. 2004-2015