Status & Roadmap
Authors & License
Funding Ultimate++
Search on this site

SourceForge.net Logo



Docking example showing advanced features inc. Serialization.





#include <Docking/Docking.h>

using namespace Upp;


** This is an advanced example designed to show most of the available Docking features, and how

**  might be used in a real world application.


** Features used:

**    Serailization

**  Including a default layout as binary data in the exe.

**  Layout templates with DockableCtrls

**    Dock Manager (Group/layout management)

**  Standard Docking Menu

**  Permitted/denied docking alignments per window



#define LAYOUTFILE <DockingExample2/DockingExample.lay>

#include <CtrlCore/lay.h>


#define TOPICFILE <DockingExample2/app.tpp/all.i>

#include <Core/topic_group.h>


// This sets up our backup serialization data (see Upp documentation for how .brc files work)

#include <DockingExample2/DefaultLayout.brc>



** Class declaration. Notice that we inherit from DockWindow (not TopWindow)


class DockingExample : public DockWindow {


    typedef DockingExample CLASSNAME;



    virtual void Close();    


    // Some DockableCtrls using Layout template

    WithDockingToolsLayout<DockableCtrl>     toolwindow;

    WithDockingOptionsLayout<DockableCtrl>     optionswindow;

    // Some data ctrls (will be added with Dockable())

    ArrayCtrl     arrayctrl1, arrayctrl2;

    TreeCtrl     treectrl1,     treectrl2;

    Button        button;

    // A menu bar to hold our windows

    MenuBar menu;



    // Our initialization function

    virtual void DockInit();


    // MenuBar callback function

    void MainMenu(Bar &bar);

    // Option callback handler

    void OnDockAllow(int align, Option *ctrl);

    // Button callback handler

    void OnUserGuide();


    // Functions to put data in our ctrls (fluff)

    void FillArray(ArrayCtrl &array);

    void FillTree(TreeCtrl &tree);




** Source




    Title("DockingExample2 : Advanced Docking").Sizeable(true).Zoomable(true);


    // Layout out windows

    CtrlLayout(toolwindow,         "Tools");

    CtrlLayout(optionswindow,     "Options");


    // Add our MenuBar using the standard Docking menu

    AddFrame(menu); // menu must be added before Set or it thinks it's a context menu



    // Set Option callbacks. The option ctrls will permit/deny docking in different directions

    //  for optionswindow only. The (int) is for the benefit of GCC

    // You can also do this for the whole window (see DockWindow::AllowDockLeft() etc)

    optionswindow.dockleft         <<= THISBACK2(OnDockAllow,     (int)DOCK_LEFT,     &optionswindow.dockleft);        

    optionswindow.docktop         <<= THISBACK2(OnDockAllow,     (int)DOCK_TOP,         &optionswindow.docktop);        

    optionswindow.dockright     <<= THISBACK2(OnDockAllow,     (int)DOCK_RIGHT,     &optionswindow.dockright);        

    optionswindow.dockbottom     <<= THISBACK2(OnDockAllow,     (int)DOCK_BOTTOM,    &optionswindow.dockbottom);    


    // Now we put some bogus data in our controls





    // And add the User-Guide button

    Add(button.SetLabel("User Guide").LeftPosZ(4, 100).TopPosZ(4, 23));

    button <<= THISBACK(OnUserGuide);    



void DockingExample::DockInit()

/* This is the docking initialisation function. It gets called after the window is opened,

**  and it's here you should do your docking/serialization, if you do it in the contructor

**  you get various problems (incorrect layout, floating windows not opening).



    // Because we are going to use Serialization and will always have a Layout available we

    //    don't need to Dock/Float windows manually. Instead we just Register them.

    // First our windows. These don't need size hints as they were set already by CtrlLayout



    // And now our data ctrls

    Register(Dockable(arrayctrl1, "ArrayCtrl 1").SizeHint(Size(300, 200)));

    Register(Dockable(treectrl1,  "TreeCtrl 1").SizeHint(Size(300, 200)));

    Register(Dockable(arrayctrl2, "ArrayCtrl 2").SizeHint(Size(300, 200)));

    Register(Dockable(treectrl2,  "TreeCtrl 2").SizeHint(Size(300, 200)));

    // Now we're ready to Serialize. The first time you run this example there won't be a data

    //  file, but I have included serialized copy in the .EXE to use as Default

    // Note that we use SerializeWindow, not Serialize.

    FileIn in(GetDataFile("docklayout.dat"));

    bool badfile = !in.IsOpen();

    if (!badfile) {


        badfile = in.IsError();


    // If the file didn't open or was corrupt, use default layout

    if (badfile) {

        MemStream in(default_layout_bin, default_layout_bin_length);





void DockingExample::Close()


    // Save our current layout & settings

    FileOut out(GetDataFile("docklayout.dat"));

    if (out.IsOpen())





void DockingExample::MainMenu(Bar &bar)


    // Add a Windows menu.

    // We're using a the standard DockWindow menu, though you can also roll your own.

    bar.Add("Windows", Image(), THISBACK(DockWindowMenu));    



void DockingExample::OnDockAllow(int align, Option *ctrl)

// Permit/deny docking in different directions

//  for optionswindow only.

// You can also do this for the whole window (see DockWindow::AllowDockLeft() etc)


    optionswindow.AllowDock(align, !(bool)~(*ctrl));







** Everything after here is fluff


void DockingExample::OnUserGuide()


    HelpWindow help;





void DockingExample::FillArray(ArrayCtrl &array)



    array.AddColumn("Roman numbers");


    for(int i = 0; i < 200; i++)

        array.Add(i, FormatIntRoman(i, true));



void DockingExample::FillTree(TreeCtrl &tree)


    Vector<int> parent, parent2;


    tree.SetRoot(Image(), "The Tree");

    for(int i = 1; i < 10000; i++) {

        parent.Add(tree.Add(parent[rand() % parent.GetCount()], Image(),

                    FormatIntRoman(i, true)));

        if((rand() & 3) == 0)
















LAYOUT(DockingToolsLayout, 164, 264)

    ITEM(SliderCtrl, dv___0, HSizePosZ(52, 4).BottomPosZ(32, 24))

    ITEM(EditInt, dv___1, HSizePosZ(76, 2).TopPosZ(28, 19))

    ITEM(Label, dv___2, SetLabel(t_("Slider 2:")).LeftPosZ(4, 45).BottomPosZ(9, 19))

    ITEM(Label, dv___3, SetLabel(t_("Slider 1:")).LeftPosZ(4, 45).BottomPosZ(33, 19))

    ITEM(Label, dv___4, SetLabel(t_("LineEdit:")).LeftPosZ(4, 69).TopPosZ(48, 19))

    ITEM(Label, dv___5, SetLabel(t_("EditInt:")).LeftPosZ(4, 69).TopPosZ(28, 19))

    ITEM(DropDate, dv___6, HSizePosZ(76, 2).TopPosZ(4, 19))

    ITEM(Label, dv___7, SetLabel(t_("DropDate:")).LeftPosZ(4, 69).TopPosZ(4, 19))

    ITEM(SliderCtrl, dv___8, HSizePosZ(52, 4).BottomPosZ(4, 24))

    ITEM(LineEdit, dv___9, HSizePosZ(4, 4).VSizePosZ(68, 56))



LAYOUT(DockingOptionsLayout, 124, 100)

    ITEM(Label, dv___0, SetLabel(t_(" Allow Docking:")).HSizePosZ(0, 20).TopPosZ(0, 19))

    ITEM(Option, dockright, SetLabel(t_("Right")).HSizePosZ(16, 4).TopPosZ(60, 16))

    ITEM(Option, dockbottom, SetLabel(t_("Bottom")).HSizePosZ(16, 4).TopPosZ(80, 16))

    ITEM(Option, dockleft, SetLabel(t_("Left")).HSizePosZ(16, 4).TopPosZ(20, 16))

    ITEM(Option, docktop, SetLabel(t_("Top")).HSizePosZ(16, 4).TopPosZ(40, 16))








BINARY(default_layout_bin, "defaultlayout.dat")






Do you want to contribute?