1 #include "Docking.h"
2
3 namespace Upp {
4
5 #define HIGHLIGHT_DURATION 1000
6
DockConfigDlg(DockWindow & dockwindow)7 DockConfigDlg::DockConfigDlg(DockWindow& dockwindow)
8 : dock(dockwindow),
9 dockers(dockwindow.GetDockableCtrls()),
10 menu(&dockwindow),
11 highlight(NULL)
12 {
13 CtrlLayoutOKCancel(*this, t_("Dockable Window Manager"));
14 Sizeable().Zoomable();
15
16 // Make backup of layout
17 StringStream s;
18 dock.SerializeLayout(s, true);
19 backup = s;
20
21 // Setup groups
22 RefreshTree(true);
23
24 // Setup layout list
25 const ArrayMap<String, String>& l = dock.GetLayouts();
26 for (int i = 0; i < l.GetCount(); i++)
27 list.Add(l.GetKey(i));
28
29 tree.MultiSelect(true);
30 tree.WhenCursor = THISBACK(OnTreeCursor);
31 tree.WhenBar = THISBACK(OnTreeContext);
32 tree.WhenDropInsert = THISBACK(OnTreeDrop);
33 tree.WhenDrag = THISBACK(OnTreeDrag);
34
35 list.MultiSelect(false);
36 list.WhenSel = THISBACK(OnListCursor);
37 list.WhenSel = THISBACK(OnListCursor);
38
39 savelayout <<= THISBACK(OnSaveLayout);
40 loadlayout <<= THISBACK(OnLoadLayout);
41 deletelayout <<= THISBACK(OnDeleteLayout);
42 newgroup <<= THISBACK(OnNewGroup);
43 deletegroup <<= THISBACK(OnDeleteGroup);
44 ok <<= THISBACK(OnOK);
45 cancel <<= THISBACK(OnCancel);
46 WhenClose = THISBACK(OnCancel);
47 locked <<= THISBACK(OnLock);
48
49 animatehighlight <<= dock.IsAnimatedHighlight();
50 animateframes <<= dock.IsAnimatedFrames();
51 animatewindows <<= dock.IsAnimatedWindows();
52 locked <<= dock.IsLocked();
53 tabbing <<= dock.IsTabbing();
54 tabnesting <<= dock.IsNestedTabs();
55 autohide <<= dock.IsAutoHide();
56 grouping <<= dock.IsGrouping();
57
58 closebtn <<= dock.HasCloseButtons();
59 autohidebtn <<= dock.HasHideButtons();
60 menubtn <<= dock.HasMenuButtons();
61
62 OnTreeCursor();
63 OnListCursor();
64 }
65
RefreshTree(bool dogroups)66 void DockConfigDlg::RefreshTree(bool dogroups)
67 {
68 TreeCtrl::Node n;
69
70 if (dogroups) {
71 tree.NoRoot(true).Clear();
72 groups.Clear();
73 n.Set(-1, t_("All")).CanSelect(false).CanOpen(true);
74 all = tree.Add(0, n);
75 for (int i = 0; i < dockers.GetCount(); i++) {
76 String s = dockers[i]->GetGroup();
77 int group = s.IsEmpty() ? -1 : groups.Find(s);
78 if (!s.IsEmpty() && group < 0) {
79 n.Set(groups.GetCount(), s);
80 group = tree.Add(0, n);
81 tree.Open(group);
82 groups.Add(s, group);
83 }
84 }
85 if (!groups.GetCount()) tree.Open(all);
86 }
87 else {
88 for (int i = 0; i < tree.GetChildCount(0); i++)
89 tree.RemoveChildren(tree.GetChild(0, i));
90 }
91 n.CanSelect(true).CanOpen(false);
92 for (int i = 0; i < dockers.GetCount(); i++) {
93 String s = dockers[i]->GetGroup();
94 int group = s.IsEmpty() ? -1 : groups.Find(s);
95 s = DockerString(dockers[i]);
96 n.SetImage(dockers[i]->GetIcon()).Set(i, s);
97 if (group >= 0)
98 tree.Add(groups[group], n);
99 tree.Add(all, n);
100 }
101 }
102
OnTreeContext(Bar & bar)103 void DockConfigDlg::OnTreeContext(Bar& bar)
104 {
105 int id = tree.GetCursor();
106 if (id >= 0) {
107 int p = tree.GetParent(id);
108 if (p != 0) {
109 menu.WindowMenu(bar, dockers[(int)tree.Get(id)]);
110 bar.Separator();
111 }
112 menu.GroupMenu(bar, (String)tree.GetValue((p==0) ? id : p));
113 if (p == 0 && id != all) {
114 bar.Separator();
115 bar.Add(t_("Delete Group"), THISBACK1(DeleteGroup, id));
116 }
117 }
118 }
119
OnSaveLayout()120 void DockConfigDlg::OnSaveLayout()
121 {
122 int ix = ListIndex();
123 String s = (ix >= 0) ? (String)list.Get(ix) : Null;
124 if (EditText(s, t_("New Layout"), t_("Layout name:"), 25)) {
125 if (!s.IsEmpty()) {
126 ix = dock.GetLayouts().Find(s);
127 if (ix < 0 || PromptOKCancel(Format(t_("Overwrite layout '%s'?"), s))) {
128 dock.SaveLayout(s);
129 if (ix < 0) {
130 list.Add(s);
131 list.SetCursor(list.GetCount()-1);
132 OnListCursor();
133 }
134 }
135 }
136 }
137 }
138
OnLoadLayout()139 void DockConfigDlg::OnLoadLayout()
140 {
141 Ctrl *focus = GetFocusCtrl();
142 int ix = ListIndex();
143 ASSERT(ix >= 0);
144 dock.LoadLayout((String)list.Get(ix));
145 dock.DisableFloating();
146 if (focus) focus->SetFocus();
147 RefreshTree(true);
148 }
149
OnDeleteLayout()150 void DockConfigDlg::OnDeleteLayout()
151 {
152 int ix = ListIndex();
153 if (!PromptOKCancel(Format(t_("Delete layout '%s'?"), (String)list.Get(ix)))) return;
154 dock.DeleteLayout((String)list.Get(ix));
155 list.Remove(ix);
156 }
157
OnTreeCursor()158 void DockConfigDlg::OnTreeCursor()
159 {
160 int id = tree.GetCursor();
161 if (id <= 0) { deletegroup.Disable(); return; }
162 int p = tree.GetParent(id);
163 if (p == 0)
164 deletegroup.Enable();
165 else
166 Highlight(dockers[(int)tree.Get(id)]);
167 }
168
169
OnListCursor()170 void DockConfigDlg::OnListCursor()
171 {
172 loadlayout.Enable(list.GetCursor() >= 0);
173 deletelayout.Enable(list.GetCursor() >= 0);
174 }
175
OnNewGroup()176 void DockConfigDlg::OnNewGroup()
177 {
178 String s;
179 if (EditText(s, t_("New Group"), t_("Group name:"), 25)) {
180 if (!s.IsEmpty()) {
181 if (groups.Find(s) < 0) {
182 int id = tree.Add(0, Image(), Value(-1), Value(s));
183 groups.Add(s, id);
184 tree.SetCursor(list.GetCount()-1);
185 OnTreeCursor();
186 }
187 else {
188 PromptOK(t_("Group '%s' already exists."));
189 OnNewGroup();
190 }
191 }
192 }
193 }
194
OnDeleteGroup()195 void DockConfigDlg::OnDeleteGroup()
196 {
197 int id = tree.GetCursor();
198 if (id < 0) return;
199 int p = tree.GetParent(id);
200 if (p != 0) id = p;
201 if (id == all) return;
202 DeleteGroup(id);
203 }
204
DeleteGroup(int id)205 void DockConfigDlg::DeleteGroup(int id)
206 {
207 String s = (String)tree.GetValue(id);
208 if (!PromptOKCancel(Format(t_("Delete group '%s'?"), s))) return;
209 int ix = groups.Find(s);
210 if (ix >= 0) {
211 String g = Null;
212 String name = groups.GetKey(ix);
213 for (int i = 0; i < dockers.GetCount(); i++)
214 if (dockers[i]->GetGroup() == name)
215 dockers[i]->SetGroup(g);
216 tree.RemoveChildren(id);
217 tree.Remove(id);
218 }
219 }
220
OnOK()221 void DockConfigDlg::OnOK()
222 {
223 dock.Animate(~animatehighlight, ~animateframes, ~animatewindows);
224 dock.Tabbing(~tabbing);
225 dock.NestedTabs(~tabnesting);
226 dock.AutoHide(~autohide);
227 dock.Grouping(~grouping);
228 dock.WindowButtons(~menubtn, ~autohidebtn, ~closebtn);
229 Close();
230 dock.EnableFloating();
231 }
232
OnCancel()233 void DockConfigDlg::OnCancel()
234 {
235 // Restore layout
236 StringStream s(backup);
237 dock.SerializeLayout(s, true);
238 Close();
239 }
240
OnLock()241 void DockConfigDlg::OnLock()
242 {
243 dock.LockLayout(locked);
244 }
245
OnTreeDrag()246 void DockConfigDlg::OnTreeDrag()
247 {
248 if (tree.GetCursor() >= 0 && tree.GetParent(tree.GetCursor()) == 0)
249 return;
250 tree.DoDragAndDrop(InternalClip(tree, "dockwindowdrag"), tree.GetDragSample(), DND_MOVE);
251 }
252
OnTreeDrop(int parent,int ii,PasteClip & d)253 void DockConfigDlg::OnTreeDrop(int parent, int ii, PasteClip& d)
254 {
255 if (parent == 0)
256 return d.Reject();
257 int p = tree.GetParent(parent);
258 if (p != 0)
259 parent = p;
260
261 if(AcceptInternal<TreeCtrl>(d, "dockwindowdrag")) {
262 Vector<int> sel = tree.GetSel();
263 for (int i = 0; i < sel.GetCount(); i++) {
264 int ix = tree.Get(sel[i]);
265 ASSERT(ix >= 0);
266 dockers[ix]->SetGroup((parent == all) ? Null : (String)tree.GetValue(parent));
267 }
268 if (tree.GetCursor()) {
269 int ix = tree.Get(tree.GetCursor());
270 ASSERT(ix >= 0);
271 dockers[ix]->SetGroup((parent == all) ? Null : (String)tree.GetValue(parent));
272 }
273 tree.SetFocus();
274 RefreshTree();
275 return;
276 }
277 }
278
Highlight(DockableCtrl * dc)279 void DockConfigDlg::Highlight(DockableCtrl *dc)
280 {
281 if (dc != highlight) {
282 if (DockCont *cont = dynamic_cast<DockCont *>(dc->GetParent())) {
283 if (!highlight || cont != highlight->GetParent()) {
284 StopHighlight();
285 cont->Highlight();
286 }
287 }
288 else {
289 StopHighlight();
290 dc->Highlight();
291 }
292 highlight = dc;
293 }
294 KillSetTimeCallback(HIGHLIGHT_DURATION, THISBACK(StopHighlight), 0);
295 }
296
StopHighlight()297 void DockConfigDlg::StopHighlight()
298 {
299 if (highlight) {
300 if (DockCont *dc = dynamic_cast<DockCont *>(highlight->GetParent()))
301 dc->Refresh();
302 else
303 highlight->Refresh();
304 }
305 highlight = NULL;
306 }
307
ListIndex() const308 int DockConfigDlg::ListIndex() const
309 {
310 if (!list.IsSelection()) {
311 if (list.IsCursor())
312 return list.GetCursor();
313 else
314 return -1;
315 }
316 for (int i = 0; i < list.GetCount(); i++)
317 if (list.IsSelected(i))
318 return i;
319 return -1;
320 }
321
322
DockerString(DockableCtrl * dc) const323 String DockConfigDlg::DockerString(DockableCtrl *dc) const
324 {
325 return Format("%20<s %s", dc->GetTitle(), PositionString(dc));
326 }
327
PositionString(DockableCtrl * dc) const328 String DockConfigDlg::PositionString(DockableCtrl *dc) const
329 {
330 if (dc->IsFloating())
331 return t_("Floating");
332 else if (dc->IsTabbed())
333 return t_("Tabbed");
334 else if (dc->IsDocked()) {
335 int align = dc->GetDockAlign();
336 switch (align) {
337 case DockWindow::DOCK_LEFT:
338 return Format(t_("Docked(%s)"), t_("Left"));
339 case DockWindow::DOCK_TOP:
340 return Format(t_("Docked(%s)"), t_("Top"));
341 case DockWindow::DOCK_RIGHT:
342 return Format(t_("Docked(%s)"), t_("Right"));
343 case DockWindow::DOCK_BOTTOM:
344 return Format(t_("Docked(%s)"), t_("Bottom"));
345 default:
346 return t_("Docked");
347 }
348 }
349 else if (dc->IsAutoHide())
350 return t_("Auto-Hide");
351 else
352 return t_("Hidden");
353 }
354
355 }
356