#include "DockCtrl/DockCtrl.h" #define IMAGEFILE #define IMAGECLASS DockCtrlImages #include //=============================================== // DockCtrl class: // Actual Framework. //=============================================== DockCtrl::DockCtrl() : DockBase() { ctrlinit = false; AllowAll(); } DockCtrl::~DockCtrl() { ctrlinit = false; } void DockCtrl::State(int reason) { if(reason == Ctrl::OPEN) { if(!ctrlinit) { InitFrameWork(); InitDockCtrl (); InitDefaultLayout(); InitCustomLayouts(); InitFrameWorkSettings(); ctrlinit = true; } } } //=============================================== // DockBase class: // A dockable widget framework base ctrl. //=============================================== Ctrl& DockBase::Dock(DockableCtrl& ctrl) { int alignment = ctrl.Alignment(); // Register ctrl. ctrl.SetBase(this); AddCtrlRecord(ctrl); // Dock... switch(alignment) { case DockableCtrl::DOCK_LEFT: GetPaneFrame(alignment).Attach(ctrl).Vert(); break; case DockableCtrl::DOCK_TOP: GetPaneFrame(alignment).Attach(ctrl).Horz(); break; case DockableCtrl::DOCK_RIGHT: GetPaneFrame(alignment).Attach(ctrl).Vert(); break; case DockableCtrl::DOCK_BOTTOM: GetPaneFrame(alignment).Attach(ctrl).Horz(); break; default: if(ctrl.IsFloating()) { ctrl.CenterOwner(); ctrl.SetSize(panesize); ctrl.FloatEx(Rect(0, 0, panesize.cx / 4, panesize.cy / 3)); ctrl.NoCenter(); } break; } RefreshPanel(); return *this; } DockableCtrl& DockBase::Tabify(DockableCtrl& ctrl1, DockableCtrl& ctrl2) { // Register Ctrls. AddCtrlRecord(ctrl1); AddCtrlRecord(ctrl2); // By default (if not stated otherwise) create tabwindows from Left PaneFrame. TabWindow* tabwindow = GetPaneFrame(0).AddTabWindow(); ASSERT(tabwindow); tabwindow->Attach(ctrl1); tabwindow->Attach(ctrl2); return (DockableCtrl&) *tabwindow; } DockableCtrl& DockBase::Tabify(String groupname, DockableCtrl& ctrl1, DockableCtrl& ctrl2) { return (DockableCtrl&) dynamic_cast(Tabify(ctrl1, ctrl2)).SetGroup(groupname); } DockableCtrl& DockBase::Tabify(DockableCtrl& ctrl1, DockableCtrl& ctrl2, DockableCtrl& ctrl3, DockableCtrl& ctrl4) { return Tabify(Tabify(ctrl1, ctrl2), Tabify(ctrl3, ctrl4)); } DockableCtrl& DockBase::Tabify(String groupname, DockableCtrl& ctrl1, DockableCtrl& ctrl2, DockableCtrl& ctrl3, DockableCtrl& ctrl4) { return (DockableCtrl&) dynamic_cast(Tabify(ctrl1, ctrl2, ctrl3, ctrl4)).SetGroup(groupname); } void DockBase::TabifyGroupAndDock(String groupname, int alignment) { Dock(TabifyGroup(groupname).DockingStyle(alignment, DockableCtrl::STATE_SHOW)); } void DockBase::TabifyGroupAndAutoHide(String groupname, int alignment) { Dock(TabifyGroup(groupname).DockingStyle(alignment, DockableCtrl::STATE_AUTO)); } void DockBase::TabifyGroupAndFloat(String groupname) { Dock(TabifyGroup(groupname).DockFloat()); } DockableCtrl& DockBase::TabifyGroup(String name) { DockableCtrl* ctrl = NULL; Vector& ids = groups.Get(name); int ncount = ids.GetCount(); ASSERT(ncount); TabWindow* tabwindow = GetPaneFrame(0).AddTabWindow(); ASSERT(tabwindow); for(int i = 0; i < ncount; i++) tabwindow->Attach(*GetCtrlRecordFromId(ids[i])->ctrl); tabwindow->SetGroup(name); return (DockableCtrl&) *tabwindow; } DockBase& DockBase::WidgetGroup(String name) { NewWidgetGroup(predefinedgroup = name); return *this; } DockBase& DockBase::operator%(DockableCtrl& ctrl) { int id = GetCtrlRecord(ctrl)->id; if(!FindWidgetinGroup(predefinedgroup, id)) AddWidgettoGroup(predefinedgroup, id); return *this; } DockBase& DockBase::WidgetLayout(String name) { NewWidgetLayout(predefinedgroup = name); return *this; } DockBase& DockBase::operator/(DockableCtrl& ctrl) { return *this; } void DockBase::DoDragAndDrop(DockableCtrl& ctrl, Point p, Size sz) { for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { if(i != j) { if(!GetPaneFrame(j).HasCtrlInRange(ctrl, p)) { GetPaneFrame(j).DnDSourceoutofRange(); GetPaneFrame(j).DnDAnimate(); } } } if(GetPaneFrame(i).HasCtrlInRange(ctrl, p)) { ctrl.SetDropTarget(i, ctrl.GetDropState()); break; } } } void DockBase::Attach(DockableCtrl& ctrl) { GetPaneFrame(ctrl.Alignment()).Attach(ctrl); } void DockBase::Attach(DockableCtrl* ctrl) { Attach(*ctrl); } void DockBase::Detach(DockableCtrl& ctrl) { GetPaneFrame(ctrl.Alignment()).Detach(ctrl); } void DockBase::Detach(DockableCtrl* ctrl) { Detach(*ctrl); } void DockBase::ShowLeftPane(bool b) { if(b) GetPaneFrame(PaneFrame::LEFT).ShowFrame(); else GetPaneFrame(PaneFrame::LEFT).HideFrame(); } void DockBase::ShowTopPane(bool b) { if(b) GetPaneFrame(PaneFrame::TOP).ShowFrame(); else GetPaneFrame(PaneFrame::TOP).HideFrame(); } void DockBase::ShowRightPane(bool b) { if(b) GetPaneFrame(PaneFrame::RIGHT).ShowFrame(); else GetPaneFrame(PaneFrame::RIGHT).HideFrame(); } void DockBase::ShowBottomPane(bool b) { if(b) GetPaneFrame(PaneFrame::BOTTOM).ShowFrame(); else GetPaneFrame(PaneFrame::BOTTOM).HideFrame(); } void DockBase::AllowAll() { AllowedSides[0] = true; AllowedSides[1] = true; AllowedSides[2] = true; AllowedSides[3] = true; } void DockBase::AllowLeft() { AllowedSides[0] = true; AllowedSides[1] = false; AllowedSides[2] = false; AllowedSides[3] = false; } void DockBase::AllowTop() { AllowedSides[1] = true; AllowedSides[0] = false; AllowedSides[2] = false; AllowedSides[3] = false; } void DockBase::AllowRight() { AllowedSides[2] = true; AllowedSides[0] = false; AllowedSides[1] = false; AllowedSides[3] = false; } void DockBase::AllowBottom() { AllowedSides[3] = true; AllowedSides[0] = false; AllowedSides[1] = false; AllowedSides[2] = false; } void DockBase::AllowLeftRight() { AllowedSides[0] = true; AllowedSides[2] = true; AllowedSides[1] = false; AllowedSides[3] = false; } void DockBase::AllowTopBottom() { AllowedSides[1] = true; AllowedSides[3] = true; AllowedSides[0] = false; AllowedSides[2] = false; } void DockBase::AllowLeftTop() { AllowedSides[0] = true; AllowedSides[1] = true; AllowedSides[2] = false; AllowedSides[3] = false; } void DockBase::AllowRightBottom() { AllowedSides[2] = true; AllowedSides[3] = true; AllowedSides[0] = false; AllowedSides[1] = false; } void DockBase::AllowLeftBottom() { AllowedSides[0] = true; AllowedSides[3] = true; AllowedSides[1] = false; AllowedSides[2] = false; } void DockBase::AllowTopRight() { AllowedSides[1] = true; AllowedSides[2] = true; AllowedSides[0] = false; AllowedSides[3] = false; } void DockBase::AllowNestedTabbing(bool b) { tabsnested = b; controlpanel.TabOptionNest <<= tabsnested; } void DockBase::ControlPanel() { if(controlpanel.IsOpen()) return; controlpanel.Open(GetTopWindow()); RefreshGroups(); RefreshPanel(); } void DockBase::OnPanelAction() { CtrlRecord* ctrlrecord = GetCtrlRecordFromIndex(listtab.list.GetClickRow()); if(ctrlrecord) ctrlrecord->ctrl->Menu(); } void DockBase::RefreshPanel() { if(!controlpanel.IsOpen() || !controlpanel.IsVisible()) return; listtab.list.Clear(); for(int i = 0; i < GetCtrlRecords().GetCount(); i++) { int alignment = 0; bool tabbed = false; bool floating = false; DockableCtrl* ctrl = GetCtrlRecordFromIndex(i)->ctrl; if(ctrl->IsTabbed()) { TabWindow* tabwindow = dynamic_cast(ctrl)->GetOwnerTab(); if(tabwindow) { alignment = tabwindow->GetBaseTab()->Alignment(); floating = tabwindow->GetBaseTab()->IsAutoHidden(); tabbed = true; } } else alignment = ctrl->Alignment(); String a, s; switch(alignment) { case DockableCtrl::DOCK_LEFT: a = t_("LEFT"); break; case DockableCtrl::DOCK_TOP: a = t_("TOP"); break; case DockableCtrl::DOCK_RIGHT: a = t_("RIGHT"); break; case DockableCtrl::DOCK_BOTTOM: a = t_("BOTTOM"); break; case DockableCtrl::DOCK_NONE: if(ctrl->IsFloating() || tabbed) a = t_("FLOATING"); else a = t_("NONE"); break; } switch(ctrl->State()) { case DockableCtrl::STATE_SHOW: s = t_("SHOWN"); break; case DockableCtrl::STATE_HIDE: s = t_("HIDDEN"); break; case DockableCtrl::STATE_AUTO: s = t_("AUTO HIDDEN"); break; case DockableCtrl::STATE_SHUT: s = t_("SHUT"); break; case DockableCtrl::STATE_TABBED: floating ? s = t_("AUTO HIDDEN") : s = t_("TABBED"); break; } listtab.list.Add(0, Format("%s",ctrl->GetLabel()), a, s, ctrl->Position()); listtab.list.SetCtrl(i, 0, (panelicons.At(i))->SetImage(ctrl->GetIcon().IsNullInstance() ? DockCtrlImages::DefaultImage : ctrl->GetIcon())); } controlpanel.Refresh(); } void DockBase::Serialize(Stream& s) { String layout = "CTRLSLAYOUTS"; String group = "CTRLGROUPS"; String settings = "DOCKCTRLSETTINGS"; int version = 1; int n = 0; s.Magic(1234765); if(s.IsStoring()) { s / version; SerializePlacement(s); s / settings; s % tabsicons; s % tabsclose; s % tabsautoalign; s % tabsnested; s % autohideicons; s % autohideclose; s / layoutindex; s / skinindex; s / hotkey; s / layout; // Write Layouts. n = layouts.GetCount(); s / n; for(int i = 0; i < n; i++) { String key = layouts.GetKey(i); String lay = layouts.Get(key); s / key; s / lay; } // Write Layout List. n = controlpanel.layoutlist.GetCount(); s / n; for(int i = 0; i < n; i++) { String lname = controlpanel.layoutlist.GetKey(i); s / lname; } s / group; // Write Groups. //int j = predefinedgroups + 1; n = groups.GetCount(); s / n; for(int i = 0; i < n; i++) { String key = groups.GetKey(i); Vector& ids = groups.Get(key); s / key; ids.Serialize(s); } } else { n = 0; s / version; SerializePlacement(s); s / settings; s % tabsicons; s % tabsclose; s % tabsautoalign; s % tabsnested; s % autohideicons; s % autohideclose; s / layoutindex; s / skinindex; s / hotkey; s / layout; // Read Layouts. s / n; for(int i = 0; i < n; i++) { String key, lay; s / key; s / lay; layouts.FindAdd(key, lay); } // Read Layout List. s / n; for(int i = 0; i < n; i++) { String lname; s / lname; controlpanel.layoutlist.Add(lname); } s / group; // Read Groups. s / n; for(int i = 0; i < n; i++) { String key; Vector ids; ids.Clear(); s / key; ids.Serialize(s); groups.FindAdd(key, ids); } // Write Ctrl values. controlpanel.TabOptionIcon <<= tabsicons; controlpanel.TabOptionClose <<= tabsclose; controlpanel.TabOptionNest <<= tabsnested; controlpanel.TabOptionAlignment <<= tabsautoalign; controlpanel.AutoOptionIcon <<= autohideicons; controlpanel.AutoOptionClose <<= autohideclose; controlpanel.layoutlist.SetIndex(layoutindex); controlpanel.skinlist.SetIndex(skinindex); } s.Magic(); } void DockBase::InitFrameWorkSettings() { RefreshWidgetLayout(); SetSkin(skinindex); SetWidgetLayout(layoutindex); } void DockBase::InitDefaultLayout() { String name = t_("Default"); if(layouts.Find(name) < 0) NewWidgetLayout(name); NewWidgetGroup(name); } void DockBase::SetSkin(int index) { switch(index) { case 0: style = &(DockCtrlChStyle::StyleDefault()); break; case 1: style = &(DockCtrlChStyle::StyleClassic()); break; case 2: style = &(DockCtrlChStyle::StyleEnhanced()); break; default: break; } for(int i = 0; i < GetCtrlRecords().GetCount(); i++) dynamic_cast(GetCtrlRecordFromIndex(i)->ctrl)->SetStyle(*style); for(int i = 0; i < GetTabWindowCount(); i++) GetTabWindowFromIndex(i)->SetStyle(*style); } DockBase& DockBase::SetStyle(const DockCtrlChStyle::Style& s) { style = &s; Refresh(); return *this; } void DockBase::OnSelectSkin() { int newindex = controlpanel.skinlist.GetIndex(); if(skinindex == newindex) return; SetSkin(skinindex = newindex); } void DockBase::OnSelectLayout() { int newindex = controlpanel.layoutlist.GetIndex(); if(layoutindex == newindex) return; SetWidgetLayout(layoutindex = newindex); } void DockBase::InitFrameWork() { panesize = GetSize(); int cx = panesize.cx / 4; int cy = panesize.cy / 3; AddFrame(hide[0]); AddFrame(hide[1]); AddFrame(hide[2]); AddFrame(hide[3]); hide[0].SetLayout(DockCtrlCustomFrame::LAYOUT_LEFT); hide[2].SetLayout(DockCtrlCustomFrame::LAYOUT_RIGHT); hide[1].SetLayout(DockCtrlCustomFrame::LAYOUT_TOP); hide[3].SetLayout(DockCtrlCustomFrame::LAYOUT_BOTTOM); AddFrame(pane[0]); AddFrame(pane[2]); AddFrame(pane[1]); AddFrame(pane[3]); pane[0].SetLayout(this, PaneFrame::LEFT, cx); pane[2].SetLayout(this, PaneFrame::RIGHT, cx); pane[1].SetLayout(this, PaneFrame::TOP, cy); pane[3].SetLayout(this, PaneFrame::BOTTOM, cy); } DockBase::DockBase() { skinindex = layoutindex = 0; tabsicons = tabsclose = tabsautoalign = true; tabsnested = false; autohideicons = autohideclose = true; isready = false; panesize.Clear(); LeftPos(0, 0).TopPos(0,0); CtrlLayout(listtab); CtrlLayout(grouptab); CtrlLayout(controlpanel); controlpanel.CenterScreen().Sizeable().Zoomable().Title(t_("Settings")); listtab.list.AddColumn(); listtab.list.AddColumn(t_("Window Title")); listtab.list.AddColumn(t_("Alignment")); listtab.list.AddColumn(t_("State")); listtab.list.AddColumn(t_("Position")); listtab.list.EvenRowColor(); listtab.list.SetLineCy(16); grouptab.grouptree.MultiSelect(); controlpanel.panel.Add(listtab.SizePos(), t_("Status")); controlpanel.panel.Add(grouptab.SizePos(), t_("Group Manager")); controlpanel.skinlist.Add(0, String(t_("Default"))).Add(1, String(t_("Classic"))).Add(2, String(t_("Enhanced"))).SetIndex(skinindex); controlpanel.skinlist.WhenAction = THISBACK(OnSelectSkin); controlpanel.layoutlist.WhenAction = THISBACK(OnSelectLayout); listtab.list.WhenLeftClick = THISBACK(OnPanelAction); grouptab.grouptree.WhenDropInsert = THISBACK(GroupDrop); grouptab.grouptree.WhenDrag = THISBACK(GroupDrag); grouptab.grouptree.WhenBar = THISBACK(GroupMenu); grouptab.grouptree.WhenCursor = THISBACK(GroupSelect); grouptab.groupadd <<= THISBACK(OnAddNewGroup); grouptab.groupdelete <<= THISBACK(OnDeleteGroup); controlpanel.layoutbutton <<= THISBACK(ResetWidgetLayout); controlpanel.layoutadd <<= THISBACK(OnAddNewLayout); controlpanel.layoutdelete <<= THISBACK(OnDeleteLayout); controlpanel.TabOptionAlignment <<= THISBACK(RefreshWidgetLayout); controlpanel.TabOptionIcon <<= THISBACK(RefreshWidgetLayout); controlpanel.TabOptionClose <<= THISBACK(RefreshWidgetLayout); controlpanel.AutoOptionClose <<= THISBACK(RefreshWidgetLayout); controlpanel.AutoOptionIcon <<= THISBACK(RefreshWidgetLayout); controlpanel.TabOptionIcon <<= tabsicons; controlpanel.TabOptionClose <<= tabsclose; controlpanel.TabOptionNest <<= tabsnested; controlpanel.TabOptionAlignment <<= tabsautoalign; controlpanel.AutoOptionIcon <<= autohideicons; controlpanel.AutoOptionClose <<= autohideclose; grouptab.groupdelete.Disable(); SetKey(K_CTRL_HOME); } DockBase::~DockBase() { CleanUp(); panesize.Clear(); } void DockBase::CleanUp() { for(int i = 0; i < panelicons.GetCount(); i++) delete panelicons.At(i); for(int i = 0; i < layouts.GetCount(); i++) layouts.Remove(i); for(int i = 0; i < groups.GetCount(); i++) groups.Remove(i); RemoveTabWindows(); DeleteCtrlRecords(); } void DockBase::RefreshWidgetLayout() { TabWindow* tabwindow = NULL; tabsicons = (bool) controlpanel.TabOptionIcon.Get(); tabsclose = (bool) controlpanel.TabOptionClose.Get(); tabsnested = (bool) controlpanel.TabOptionNest.Get(); tabsautoalign = (bool) controlpanel.TabOptionAlignment.Get(); autohideicons = (bool) controlpanel.AutoOptionIcon.Get(); autohideclose = (bool) controlpanel.AutoOptionClose.Get(); int n = GetTabWindowCount(); for(int i = 0; i < n; i++) { tabwindow = GetTabWindowFromIndex(i); if(tabsautoalign) { switch(tabwindow->GetBaseTab()->Alignment()) { case DockableCtrl::DOCK_LEFT: tabwindow->SetLayout(DockCtrlCustomFrame::LAYOUT_RIGHT); break; case DockableCtrl::DOCK_TOP: tabwindow->SetLayout(DockCtrlCustomFrame::LAYOUT_BOTTOM); break; case DockableCtrl::DOCK_RIGHT: tabwindow->SetLayout(DockCtrlCustomFrame::LAYOUT_LEFT); break; case DockableCtrl::DOCK_BOTTOM: tabwindow->SetLayout(DockCtrlCustomFrame::LAYOUT_TOP); break; } } else tabwindow->SetLayout(DockCtrlCustomFrame::LAYOUT_BOTTOM); tabwindow->GetTabs().HasIcons(tabsicons); tabwindow->GetTabs().HasButtons(tabsclose); } for(int i = 0; i < 4; i++) GetHideBar(i).HasButtons(autohideclose).HasIcons(autohideicons); } void DockBase::OnAddNewLayout() { String name; if(EditText(name, t_("Add new layout"), t_("Layout name:"), 32)) { if(IsNull(name)) { Exclamation(t_("You must enter a name for the new layout")); return; } else if(layouts.Find(name) >= 0) { if(!PromptOKCancel(Format(t_("Layout '%s' adready exists. Do you want to overwrite it?"), name))) return; } NewWidgetLayout(name); RefreshPanel(); } } void DockBase::OnDeleteLayout() { DelWidgetLayout(layouts.GetKey(layoutindex)); } void DockBase::AddCtrlRecord(DockableCtrl& ctrl) { CtrlRecord* record = NULL; if(GetCtrlRecord(ctrl) || ctrl.IsTabWindow()) return; ctrls.Add((record = new CtrlRecord())); if(record) { record->ctrl = &ctrl; record->id = ctrls.GetCount(); ImageCtrl* imagectrl = new ImageCtrl(); panelicons.Add(imagectrl); } } void DockBase::RemoveCtrlRecord(DockableCtrl& ctrl) { CtrlRecord* record = GetCtrlRecord(ctrl); if(record) delete record; } void DockBase::DeleteCtrlRecords() { for(int i = 0; i < ctrls.GetCount(); i++) delete ctrls.At(i); } DockBase::CtrlRecord* DockBase::GetCtrlRecord(DockableCtrl& ctrl) { for(int i = 0; i < ctrls.GetCount(); i++) { CtrlRecord* record = ctrls.At(i); if(record->ctrl == &ctrl) return record; } return NULL; } DockBase::CtrlRecord* DockBase::GetCtrlRecordFromIndex(int index) { if(index >= 0 && index < ctrls.GetCount()) return ctrls.At(index); return NULL; } DockBase::CtrlRecord* DockBase::GetCtrlRecordFromId(int id) { for(int i = 0; i < ctrls.GetCount(); i++) { CtrlRecord* record = ctrls.At(i); if(record->id == id) return record; } return NULL; } DockBase::CtrlRecord* DockBase::GetCtrlRecordFromGroup(String group) { return NULL; } DockableCtrl* DockBase::GetDockedWindowFromIndex(int index) { Vector docks; docks.Clear(); for(int i = 0; i < 8; i++) { if(i < 4) { int n = GetPaneFrame(i).GetCount(); if(n) for(int j = 0; j < n; j++) docks.Add(GetPaneFrame(i).GetChild(j + 1)); } else { int n = GetHideBar(i - 4).GetCount(); if(n) for(int j = 0; j < n; j++) docks.Add(GetHideBar(i - 4).GetChild(j)); } } return docks.GetCount() ? docks.At(index) : NULL; } TabWindow* DockBase::GetTabWindowFromIndex(int index) { TabWindow* tabwindow = tabwindows.At(index); ASSERT(tabwindow); return tabwindow; } int DockBase::GetTabWindowCount() { return tabwindows.GetCount(); } int DockBase::GetDockedWindowCount() { int dockcount = 0; for(int i = 0; i < 8; i++) if(i < 4) dockcount += GetPaneFrame(i).GetCount(); else dockcount += GetHideBar(i - 4).GetCount(); return dockcount; } void DockBase::RemoveTabWindows() { for(int i = 0 ; i < tabwindows.GetCount(); i++) if(tabwindows.At(i)) delete tabwindows.At(i); } void DockBase::RefreshTabWindowList() { for(int i = 0; i < tabwindows.GetCount(); i++) if(tabwindows.At(i)->IsDestroyed()) { TabWindow *t = tabwindows.At(i); tabwindows.Remove(i); delete t; } } Vector& DockBase::GetTabWindows() { return tabwindows; } void DockBase::NewWidgetLayout(String name) { StringStream s; SerializeLayout(s); int id = AddWidgetLayout(name); layouts[id] = (String) s; } int DockBase::AddWidgetLayout(String name) { int id = layouts.Find(name); if(id < 0) { id = layouts.FindAdd(name, String()); controlpanel.layoutlist.Add(name); int index = controlpanel.layoutlist.GetCount() - 1; controlpanel.layoutlist.SetIndex(layoutindex = index); } return id; } void DockBase::AddWidgetLayout(String name, DockableCtrl& ctrl, int alignment, int state, int position) { } void DockBase::DelWidgetLayout(String name) { int id = layouts.Find(name); if(id < 0) return; if(PromptOKCancel(Format(t_("Do you really want to delete layout '%s'"), name))) { layouts.RemoveKey(name); controlpanel.layoutlist.Remove(id); id--; controlpanel.layoutlist.SetIndex(layoutindex = id); } } void DockBase::SetWidgetLayout(String name) { int id = layouts.Find(name); if(id < 0) return; SetWidgetLayout(id); } void DockBase::SetWidgetLayout(int index) { if(layoutindex != index) controlpanel.layoutlist.SetIndex(layoutindex = index); if(index == 0) controlpanel.layoutdelete.Disable(); else controlpanel.layoutdelete.Enable(); String key = layouts.GetKey(index); String& layout = layouts.Get(key); StringStream s(layout); s.SetLoading(); SerializeLayout(s); } void DockBase::SerializeLayout(Stream& s, bool deflay) { CtrlRecord* record = NULL; DockableCtrl* ctrl = NULL; TreeCtrl& tree = grouptab.grouptree; String name; int panesize = 0; int type = 0; int alignment = 0; int state = 0; int position = 0; int id = 0; int childcount = 0; Size childsize; if(s.IsStoring()) { // Remove unused TabWindows (BugFix). RefreshTabWindowList(); // Write Tabbing mode. s % tabsnested; // Write Widgets. // Write Docked (shown or hidden) and AutoHidden widgets. childcount = GetDockedWindowCount(); s / childcount; if(childcount) for(int i = 0; i < childcount; i++) { ctrl = GetDockedWindowFromIndex(i); ASSERT(ctrl); ctrl->Serialize(s); } // Write PaneFrame sizes. for(int i = 0; i < 4; i++) { panesize = GetPaneFrame(i).GetSize(); s / panesize; } childcount = 0; int ctrlscount = ctrls.GetCount(); // Write Floating Dockwindows. for(int i = 0; i < ctrlscount * 2; i++) { if(i < ctrlscount) childcount += GetCtrlRecordFromIndex(i)->ctrl->IsFloating() ? 1 : 0; if(i >= ctrlscount) { if(i == ctrlscount) s / childcount; ctrl = GetCtrlRecordFromIndex(i - ctrlscount)->ctrl; ASSERT(ctrl); if(ctrl->IsFloating()) ctrl->Serialize(s); } } childcount = 0; // Write Floating TabWindows. int tabwindowcount = GetTabWindowCount(); if(tabwindowcount) for(int i = 0; i < tabwindowcount * 2; i++) { if(i < tabwindowcount) childcount += GetTabWindowFromIndex(i)->IsFloating() ? 1 : 0; if(i >= tabwindowcount) { if(i == tabwindowcount) s / childcount; TabWindow* tabwindow = GetTabWindowFromIndex(i - tabwindowcount); ASSERT(tabwindow); if(tabwindow->IsFloating()) tabwindow->Serialize(s); } } } if(s.IsLoading()) { childcount = 0; // Close All widgets. for(int i = 0; i < GetTabWindowCount(); i++) GetTabWindowFromIndex(i)->DetachAll(); for(int i = 0; i < ctrls.GetCount(); i++) GetCtrlRecordFromIndex(i)->ctrl->Shut(); // Remove unused TabWindows (BugFix). RefreshTabWindowList(); // Read Tabbing Mode s % tabsnested; controlpanel.TabOptionNest <<= tabsnested; // Read Docked (shown or hidden) and AutoHidden widgets. s / childcount; if(childcount) for(int i = 0; i < childcount; i++) { s / type / id; if(type == DockableCtrl::TYPE_DOCKWINDOW) GetCtrlRecordFromId(id)->ctrl->Serialize(s); if(type == DockableCtrl::TYPE_TABWINDOW) GetPaneFrame(0).AddTabWindow()->Serialize(s); } // Read PaneFrame sizes. for(int i = 0; i < 4; i++) { s / panesize; GetPaneFrame(i).SetSize(panesize); } childcount = 0; s / childcount; if(childcount) for(int i = 0; i < childcount; i++) { s / type / id; GetCtrlRecordFromId(id)->ctrl->Serialize(s); } childcount = 0; s / childcount; if(childcount) for(int j = 0; j < childcount; j++) { s / type / id; TabWindow* tabwindow = GetPaneFrame(0).AddTabWindow(); tabwindow->Serialize(s); } } s.Close(); } void DockBase::ResetWidgetLayout() { controlpanel.layoutlist.SetIndex(layoutindex = 0); SetWidgetLayout(layoutindex); RefreshPanel(); } void DockBase::NewWidgetGroup(String name, bool predefined) { predefined = true; TreeCtrl& tree = grouptab.grouptree; Vector ids; ids.Clear(); int group = groups.FindAdd(name, ids); if(tree.Find(name) < 0) tree.Add(0, DockCtrlImages::DefaultImage(), Value(name)); if(name != t_("Default")) return; for(int i = 0; i < ctrls.GetCount(); i++) { DockableCtrl * ctrl = ctrls[i]->ctrl; int id = ctrls[i]->id; ids.Add(ctrls[i]->id); tree.Add(tree.Find(name), ctrl->GetIcon(), Value(id), Value(ctrl->GetLabel())); } groups[group] = ids; } bool DockBase::AddWidgettoGroup(String name, DockableCtrl& ctrl) { CtrlRecord* record = GetCtrlRecord(ctrl); if(!record || name == t_("Default")) return false; NewWidgetGroup(name); Vector& ids = groups.Get(name); for(int i = 0; i < ids.GetCount(); i++) if(ids[i] == record->id) { Exclamation(Format(t_("Error: Widget (%s) is already in the group '%s'"), ctrl.GetLabel(), name)); return false; } ids.Add(record->id); grouptab.grouptree.Add(grouptab.grouptree.Find(name), ctrl.GetIcon(), Value(record->id), Value(ctrl.GetLabel())); return true; } bool DockBase::AddWidgettoGroup(String name, int id) { CtrlRecord* record = GetCtrlRecordFromId(id); if(!record) return false; return AddWidgettoGroup(name, *record->ctrl); } bool DockBase::DeleteWidgetfromGroup(String name, DockableCtrl& ctrl) { CtrlRecord* record = GetCtrlRecord(ctrl); if(groups.Find(name) < 0 || name == t_("Default") || !record) return false; Vector& ids = groups.Get(name); for(int i = 0; i < ids.GetCount(); i++) if(record->id == ids[i]) ids.Remove(i); return true; } bool DockBase::DeleteWidgetfromGroup(String name, int id) { CtrlRecord* record = GetCtrlRecordFromId(id); if(!record) return false; return DeleteWidgetfromGroup(name, *record->ctrl); } int DockBase::AddWidgetGroup(String name) { return 1; } void DockBase::DeleteWidgetGroup(String name) { TreeCtrl& tree = grouptab.grouptree; if(name == t_("Default")) return; if(PromptOKCancel(Format(t_("Do you really want to delete group '%s'"), name))) { groups.RemoveKey(name); int id = tree.Find(name); if(id >= 0) { tree.RemoveChildren(id); tree.Remove(id); } tree.Refresh(); } } Vector& DockBase::FindWidgetGroup(String name) { return groups.Get(name); } bool DockBase::FindWidgetinGroup(String name, int id) { Vector& ids = FindWidgetGroup(name); for(int i = 0; i < ids.GetCount(); i++) if(ids[i] == id) return true; return false; } void DockBase::OnAddNewGroup() { String name; if(EditText(name, t_("Add new group"), t_("Group name:"), 32)) { if(IsNull(name)) { Exclamation(t_("You must enter a name for the new group")); return; } else if(groups.Find(name) >= 0) { if(!PromptOKCancel(Format(t_("Group '%s' adready exists. Do you want to overwrite it?"), name))) return; } NewWidgetGroup(name); RefreshPanel(); } } void DockBase::OnDeleteGroup() { TreeCtrl& tree = grouptab.grouptree; int id = tree.GetCursor(); if(id == 0) return; DeleteWidgetGroup(tree.GetValue(tree.GetCursor())); } void DockBase::GroupDrop(int parent, int ii, PasteClip& d) { if (parent == 0) return d.Reject(); TreeCtrl& tree = grouptab.grouptree; int p = tree.GetParent(parent); if (p != 0) parent = p; if(AcceptInternal(d, "DockCtrlGroupTreeDrag")) { Vector sel = tree.GetSel(); for (int i = 0; i < sel.GetCount(); i++) { int id = tree.Get(sel[i]); String group = (String) tree.GetValue(parent); if(group == t_("Default") || FindWidgetinGroup(group, id)) return d.Reject(); AddWidgettoGroup(group, id); tree.Open(parent); } return; } tree.SetFocus(); } void DockBase::GroupDrag() { TreeCtrl& tree = grouptab.grouptree; int idc = -1; if (tree.GetCursor() >= 0 && tree.GetParent(tree.GetCursor()) <= 0) return; if(tree.DoDragAndDrop(InternalClip(tree, "DockCtrlGroupTreeDrag"), tree.GetDragSample()) == DND_MOVE) { int parent = tree.GetParent(tree.GetCursor()); idc = tree.GetCursor(); String name = tree.GetValue(idc); String group = (String) tree.GetValue(parent); int id = tree.Get(idc); if(DeleteWidgetfromGroup(group, id)) tree.Remove(idc); } tree.Refresh(); } void DockBase::GroupSelect() { TreeCtrl& tree = grouptab.grouptree; int root = tree.GetCursor(); if(root < 0) return; int id = tree.GetParent(root); String group = (String) tree.GetValue(root); grouptab.groupdelete.Enable(id == 0 && group != t_("Default")); } void DockBase::RefreshGroups() { TreeCtrl& tree = grouptab.grouptree; tree.Clear(); tree.SetRoot(DockCtrlImages::DefaultImage(), t_("Available Widget Groups")); tree.Open(0); for(int i = 0; i < groups.GetCount(); i++) { String group = groups.GetKey(i); Vector& ids = groups.Get(group); tree.Add(0, DockCtrlImages::DefaultImage(), group); for(int j = 0; j < ids.GetCount(); j++) { CtrlRecord* record = GetCtrlRecordFromId(ids[j]); ASSERT(record); tree.Add(tree.Find(group), record->ctrl->GetIcon(), Value(record->id), Value(record->ctrl->GetLabel())); } } } void DockBase::GroupMenu(Bar& bar) { TreeCtrl& tree = grouptab.grouptree; int id = tree.GetCursor(); if(id < 0) return; id = tree.GetParent(id); activegroup = (String) tree.GetValue(tree.GetCursor()); if(id >= 0) { if(id == 0 && tree.GetChildCount(id)) { bar.Add(Format(t_("Dock Group '%s'"), activegroup), THISBACK1(GroupDockMenu, 0)); bar.Add(Format(t_("AutoHide Group '%s'"), activegroup), THISBACK1(GroupDockMenu, 1)); bar.Add(Format(t_("Float Group '%s'"), activegroup), THISBACK3(GroupMenuAction, activegroup, 2, -1)); bar.Separator(); bar.Add(tree.GetChildCount(tree.GetCursor()) > 1, Format(t_("Tabify Group '%s' and..."), activegroup), THISBACK1(GroupTabifyMenu, 3)); bar.Separator(); bar.Add(activegroup != t_("Default"), Format(t_("Delete Group '%s'"), activegroup), THISBACK1(DeleteWidgetGroup, activegroup)); bar.Separator(); bar.Add(Format(t_("Close Group '%s'"), activegroup), DockCtrlImages::CClose(), THISBACK3(GroupMenuAction, activegroup, -1, -1)); } if(id > 0) { Vector sel = tree.GetSel(); for(int i = 0; i < sel.GetCount(); i++) id = tree.Get(sel[i]); CtrlRecord* record = GetCtrlRecordFromId(id); ASSERT(record); record->ctrl->Menu(); } } else bar.Add(t_("Add New Group..."), THISBACK(OnAddNewGroup)); } void DockBase::GroupDockMenu(Bar& bar, int command) { if(IsSideAllowed(DockableCtrl::DOCK_TOP)) bar.Add(t_("Top"), THISBACK3(GroupMenuAction, activegroup, (int) command, (int)DockableCtrl::DOCK_TOP)); if(IsSideAllowed(DockableCtrl::DOCK_LEFT)) bar.Add(t_("Left"), THISBACK3(GroupMenuAction, activegroup, (int) command, (int)DockableCtrl::DOCK_LEFT)); if(IsSideAllowed(DockableCtrl::DOCK_RIGHT)) bar.Add(t_("Right"), THISBACK3(GroupMenuAction, activegroup, (int) command, (int)DockableCtrl::DOCK_RIGHT)); if(IsSideAllowed(DockableCtrl::DOCK_BOTTOM)) bar.Add(t_("Bottom"), THISBACK3(GroupMenuAction, activegroup, (int) command, (int)DockableCtrl::DOCK_BOTTOM)); } void DockBase::GroupTabifyMenu(Bar& bar, int command) { bar.Add(t_("Dock"), THISBACK1(GroupDockMenu, 3)); bar.Add(t_("Auto Hide"), THISBACK1(GroupDockMenu, 4)); bar.Add(t_("Float"), THISBACK3(GroupMenuAction, activegroup, 5, -1)); } void DockBase::GroupMenuAction(String name, int command, int alignment) { DockableCtrl* ctrl = NULL; Vector& ids = groups.Get(name); int ncount = ids.GetCount(); bool aligned = (alignment >= DockableCtrl::DOCK_LEFT && alignment <= DockableCtrl::DOCK_BOTTOM); for(int i = 0; i < ncount * 2; i++) { if(i < ncount) { ctrl = GetCtrlRecordFromId(ids[i])->ctrl; ASSERT(ctrl); ctrl->Shut(); } else { if(i == ncount) RefreshTabWindowList(); ctrl = GetCtrlRecordFromId(ids[i - ncount])->ctrl; ASSERT(ctrl); switch(command) { case 0: Dock(ctrl->DockingStyle(alignment, DockableCtrl::STATE_SHOW)); break; case 1: Dock(ctrl->SetSizeHint(Size(0,0)).DockingStyle(alignment, DockableCtrl::STATE_AUTO)); break; case 2: Dock(ctrl->DockFloat()); break; case 3: if (i - ncount == 0) TabifyGroupAndDock(name, alignment); break; case 4: if (i - ncount == 0) TabifyGroupAndAutoHide(name, alignment); break; case 5: if (i - ncount == 0) TabifyGroupAndFloat(name); break; } } } } bool DockBase::Key(dword key, int count) { if(key == hotkey) ControlPanel(); return TopWindow::Key(key, count); } CH_STYLE(DockCtrlChStyle, Style, StyleClassic) { font = StdFont(); barmargins = Rect(2,2,2,2); barheight = font.Info().GetHeight() + 8; tabheight = font.Info().GetHeight() + 8; tabmargin = 2; tabsel = Rect(2, 2, 2, 2); tabedge = Rect(6, 6, 6, 6); tabextendleft = 0; DockCtrlImgsLook(barbackground, DockCtrlImages::I_CBarBackground, 1); DockCtrlImgsLook(barshut, DockCtrlImages::I_CClose, 3); DockCtrlImgsLook(barhide, DockCtrlImages::I_CHide, 3); DockCtrlImgsLook(barmenu, DockCtrlImages::I_CMenu, 3); CtrlsImageLook(tabnormal, ClassicCtrlsImg::I_TAB, 4); CtrlsImageLook(tabfirst, ClassicCtrlsImg::I_FTAB, 4); CtrlsImageLook(tablast, ClassicCtrlsImg::I_LTAB, 4); CtrlsImageLook(tabboth, ClassicCtrlsImg::I_BTAB, 4); } CH_STYLE(DockCtrlChStyle, Style, StyleEnhanced) { font = StdFont(); barmargins = Rect(2,2,2,2); barheight = font.Info().GetHeight() + 8; tabheight = font.Info().GetHeight() + 8; tabmargin = 2; tabsel = Rect(2, 2, 2, 2); tabedge = Rect(6, 6, 6, 6); tabextendleft = 0; const ToolBar::Style* defguistyle = &ToolBar::StyleDefault(); barbackground[0] = defguistyle->arealook; DockCtrlImgsLook(barshut, DockCtrlImages::I_CClose, 3); DockCtrlImgsLook(barhide, DockCtrlImages::I_CHide, 3); DockCtrlImgsLook(barmenu, DockCtrlImages::I_CMenu, 3); CtrlsImageLook(tabnormal, CtrlsImg::I_TAB, 4); CtrlsImageLook(tabfirst, CtrlsImg::I_FTAB, 4); CtrlsImageLook(tablast, CtrlsImg::I_LTAB, 4); CtrlsImageLook(tabboth, CtrlsImg::I_BTAB, 4); stdhighlight = StandardHighlight(Blend(SColorHighlight, SColorPaper, 90), SColorHighlight); tabhighlight = AlphaHighlight(stdhighlight, 80); } CH_STYLE(DockCtrlChStyle, Style, StyleDefault) { font = StdFont(); barmargins = Rect(2,2,2,2); barheight = font.Info().GetHeight() + 8; tabheight = font.Info().GetHeight() + 8; tabmargin = 2; tabsel = Rect(2, 2, 2, 2); tabedge = Rect(6, 6, 6, 6); tabextendleft = 0; const TabCtrl::Style* defguistyle = &TabCtrl::StyleDefault(); barbackground[0] = defguistyle->normal[0]; DockCtrlImgsLook(barshut, DockCtrlImages::I_DClose, 3); DockCtrlImgsLook(barhide, DockCtrlImages::I_DHide, 3); DockCtrlImgsLook(barmenu, DockCtrlImages::I_DMenu, 3); CtrlsImageLook(tabnormal, CtrlsImg::I_TAB, 4); CtrlsImageLook(tabfirst, CtrlsImg::I_FTAB, 4); CtrlsImageLook(tablast, CtrlsImg::I_LTAB, 4); CtrlsImageLook(tabboth, CtrlsImg::I_BTAB, 4); stdhighlight = StandardHighlight(Blend(SColorHighlight, SColorPaper, 90), SColorHighlight); tabhighlight = AlphaHighlight(stdhighlight, 80); }