1 #ifndef _Docking_Docking_h_
2 #define _Docking_Docking_h_
3
4 #include <CtrlLib/CtrlLib.h>
5 #include <TabBar/TabBar.h>
6
7 namespace Upp {
8
9 class DockWindow;
10
11 #include "ToolWin.h"
12 #include "DockableCtrl.h"
13 #include "DockMenu.h"
14 #include "DockTabBar.h"
15 #include "DockCont.h"
16 #include "DockPane.h"
17
18 class DockWindow : public TopWindow {
19 public:
20 typedef DockWindow CLASSNAME;
21
22 enum {
23 DOCK_NONE = -1,
24 DOCK_LEFT = SplitterFrame::LEFT,
25 DOCK_TOP = SplitterFrame::TOP,
26 DOCK_RIGHT = SplitterFrame::RIGHT,
27 DOCK_BOTTOM = SplitterFrame::BOTTOM,
28 };
29
30 virtual void State(int reason);
31 virtual bool Key(dword key, int count);
32 protected:
33 enum { TIMEID_ACTION_CHECK = Ctrl::TIMEID_COUNT,
34 TIMEID_ANIMATE,
35 TIMEID_ANIMATE_DELAY,
36 TIMEID_COUNT };
37 // DnD interface
38 struct HighlightCtrl : public DockableCtrl {
HighlightCtrlHighlightCtrl39 HighlightCtrl() { BackPaint(); }
ClearHighlightHighlightCtrl40 void ClearHighlight() { img.Clear(); buffer.Clear(); }
41 void SetHighlight(const Value& hl, bool _isnested, bool cannest, Image bg = Image());
42 void SetNested(bool _isnested);
43 void CreateBuffer();
44 virtual void Paint(Draw& w);
45 int oldframesize;
46 Rect bounds;
47 private:
48 Image img;
49 Image buffer;
50 bool isnested;
51 bool cannest;
52 const Value *highlight;
53 };
54
55 struct PosInfo : public Moveable<PosInfo> {
PosInfoPosInfo56 PosInfo() : state(DockCont::STATE_NONE) {}
57 DockCont::DockState state; // State info
58 Ptr<DockCont> tabcont;// Only valid when ctrl was tabbed
59 String data; // Serialized context info dependent on state
60 };
61 protected:
62 // Highlight control
GetHighlightCtrl()63 virtual HighlightCtrl& GetHighlightCtrl() { return hlc; }
64 void StartHighlight(DockCont *dcptr);
65 void Highlight(int align, DockCont& cont, DockCont *target);
66 void StopHighlight(bool do_animatehl);
67 virtual bool NeedFrameReorder(int align);
IsReorderingFrames()68 bool IsReorderingFrames() { return prehighlightframepos >= 0; }
69 // Called by containers to signal drag-drop events
70 virtual void ContainerDragStart(DockCont& dc);
71 virtual void ContainerDragMove(DockCont& dc);
72 virtual void ContainerDragEnd(DockCont& dc);
73 // Container docking/undocking
74 void DockContainer(int align, DockCont& c, int pos = -1);
75 void DockAsTab(DockCont& target, DockableCtrl& dc);
76 void DockContainerAsTab(DockCont& target, DockCont& c, bool do_nested);
77 void FloatContainer(DockCont& c, Point p = Null, bool move = true);
FloatFromTab(DockCont & c,DockableCtrl & tab)78 void FloatFromTab(DockCont& c, DockableCtrl& tab) { FloatFromTab(c, *CreateContainer(tab)); }
79 void FloatFromTab(DockCont& c, DockCont& tab);
80 void AutoHideContainer(int align, DockCont& c);
81 void CloseContainer(DockCont& c);
82 DockCont *TabifyGroup(String group);
83 void Undock(DockCont& c);
84 void Unfloat(DockCont& c);
Detach(DockCont & c)85 void Detach(DockCont& c) { Undock(c); Unfloat(c); }
86 // For finding drag-drop targets and computing boundary rect
87 DockCont *GetMouseDockTarget();
88 DockCont *FindDockTarget(DockCont& dc, int& al);
89 int FindDocker(const Ctrl *dc);
90 Rect GetAlignBounds(int al, Rect r, bool center, bool allow_lr = true, bool allow_tb = true);
91 int GetPointAlign(const Point p, Rect r, bool center, bool allow_lr = true, bool allow_tb = true);
92 int GetQuad(Point p, Rect r);
93 Rect GetFinalAnimRect(int align, Ctrl& c);
94 // Helpers
IsTL(int align)95 bool IsTL(int align) const { return align < 2; } //ie (align == DOCK_LEFT || align == DOCK_TOP)
IsTB(int align)96 bool IsTB(int align) const { return align & 1; } //ie (align == DOCK_TOP || align == DOCK_BOTTOM)
97 int GetDockAlign(const Ctrl& c) const;
98 int GetDockAlign(const Point& p) const;
99 int GetAutoHideAlign(const DockCont& c) const;
IsFrameAnimating(int align)100 bool IsFrameAnimating(int align) const { return frameanim[align].inc; }
IsPaneAnimating(int align)101 bool IsPaneAnimating(int align) const { return dockpane[align].IsAnimating(); }
CheckNesting()102 bool CheckNesting() const { return (GetMouseFlags() & nesttoggle) ? !nestedtabs : nestedtabs; }
103
104 void DoHotKeys(dword key);
105
106 void SaveDockerPos(DockableCtrl& dc, PosInfo& pi);
107 void SetDockerPosInfo(DockableCtrl& dc, const PosInfo& pi);
108
109 friend class DockCont;
110 private:
111 bool init;
112 bool tabbing;
113 bool autohide;
114 bool animatehl;
115 bool animatefrm;
116 bool animatewnd;
117 bool nestedtabs;
118 bool grouping;
119 bool menubtn;
120 bool closebtn;
121 bool hidebtn;
122 bool dockable[4];
123 bool locked;
124 bool tabtext;
125 bool tabalign;
126 bool frameorder;
127 bool showlockedhandles;
128 bool childtoolwindows;
129 dword nesttoggle;
130 String layoutbackup;
131 int dockframepos;
132 int prehighlightframepos;
133
134 Array<DockCont> conts;
135 Vector<DockableCtrl *> dockers;
136 ArrayMap<String, String> layouts;
137 Array<DockableCtrl> ctrls;
138
139 HighlightCtrl hlc;
140 DockPane dockpane[4];
141 SplitterFrame dockframe[4];
142 AutoHideBar hideframe[4];
143 DockMenu menu;
144 Vector<PosInfo> dockerpos;
145
146 struct FrameAnim {
FrameAnimFrameAnim147 FrameAnim() : target(0), inc(0) {}
148 int target;
149 int inc;
150 };
151 FrameAnim frameanim[4];
152 int animdelay;
153 public:
154 // If you are attaching DockableCtrls programmatically it must be done in an overloaded DockInit.
155 // It is called after Ctrl::OPEN in order so that docking can be done with the correct window size.
DockInit()156 virtual void DockInit() { }
157 // Attaches all the required frames to the DockWindow.
158 // It is called internally on Ctrl::Open so should not usually be needed
159 void DockLayout(bool tb_precedence = true);
160
161 // Functions for registering/deregistering externally owned DockableCtrls
162 // NOTE: Registering is automatically done when using Dock/Float etc functions, but Register
163 // also be called before DockInit (eg in constructor), and are prefered if you are only going
164 // to be serializing the DockWindow layout
165 DockableCtrl& Register(DockableCtrl& dc);
166 void Deregister(const DockableCtrl& dc);
167
168 // Creates an internal DockableCtrl for you to allow simple wrapping of GUI elements
169 DockableCtrl& Dockable(Ctrl& ctrl, WString title);
170 DockableCtrl& Dockable(Ctrl& ctrl, const char *title = 0) { return Dockable(ctrl, (WString)title); }
171 // More flexible methods for creating internally stored DockableCtrl derived classes
172 template<class T>
173 T& CreateDockable(WString title);
174 template<class T>
175 T& CreateDockable(const char *title = 0) { return CreateDockable<T>((WString)title); }
176
177 // Get a list of all registered DockableCtrls (including externally owned ones
GetDockableCtrls()178 const Vector<DockableCtrl *>& GetDockableCtrls() const { return dockers; }
179
180 // Simple docking control
181 void DockLeft(DockableCtrl& dc, int pos = -1) { Dock(DOCK_LEFT, dc, pos); }
182 void DockTop(DockableCtrl& dc, int pos = -1) { Dock(DOCK_TOP, dc, pos); }
183 void DockRight(DockableCtrl& dc, int pos = -1) { Dock(DOCK_RIGHT, dc, pos); }
184 void DockBottom(DockableCtrl& dc, int pos = -1) { Dock(DOCK_BOTTOM, dc, pos); }
185 void Dock(int align, DockableCtrl& dc, int pos = -1);
186 // Attaches 'dc' as a tab to 'target', wherever it may be
187 void Tabify(DockableCtrl& target, DockableCtrl& dc);
188 // Detaches the passed ctrl as a floating window
189 void Float(DockableCtrl& dc, Point p = Null);
190 void Float(DockableCtrl& dc, const char *title, Point p = Null);
191 // Attaches the passed ctrl to the autohide frames on the window edges
192 // If no alignment is given the ctrl will be autohidden where it is docked or to the top bar if not docked
193 void AutoHide(DockableCtrl& dc);
194 void AutoHide(int align, DockableCtrl& dc);
195 // Closes the window, detaching it from and docking panes or autohide frames.
196 // This just 'hides' the window, it can be opened again at any time.
197 void Close(DockableCtrl& dc);
198
199 // Activate the passed ctrl. If open this will make sure it's the active tab, if
200 // closed the ctrls last known position will be restored (see RestoreDockerPos)
201 void ActivateDockable(Ctrl& c);
202 // As above, but you can pass any child ctrl of the DockableCtrl (useful with the Dockable functions)
203 void ActivateDockableChild(Ctrl& c);
204
205 // When DockableCtrls change state a record of their last position is stored internally.
206 // These functions can restore the previous DockableCtrl's postion of force a save of the current one
207 void SaveDockerPos(DockableCtrl& dc);
208 void RestoreDockerPos(DockableCtrl& dc, bool savefirst = false);
209 // Toggle window visibility. If the window is open it is hidden, if it is hidden it is restored
210 void HideRestoreDocker(DockableCtrl& dc);
211
212 // Group docking ctrl. These work the same way as for single DockableCtrls but apply to the passed group
213 // TabDockGroup and DockGroup will respect the DockAllowed settings for DockableCtrls
214 void DockGroup(int align, String group, int pos = -1);
215 void FloatGroup(String group);
216 void AutoHideGroup(int align, String group);
217 void AutoHideGroup(String group);
218 void TabFloatGroup(String group);
219 void CloseGroup(String group);
220 void TabDockGroup(int align, String group, int pos = -1);
221 // These variants of DockGroup and DockTabGroup ignore the DockAllowed settings
222 void ForceDockGroup(int align, String group, int pos = -1);
223 void ForceTabDockGroup(int align, String group, int pos = -1);
224
225 // Check docking frame visibility. If there are no docked ctrls it will be invisibly
IsDockVisible(int align)226 bool IsDockVisible(int align) const { ASSERT(align >= 0 && align <= 4); return dockpane[align].IsVisible(); }
227 // Manually sets the size of a docking frame
228 void SetFrameSize(int align, int size);
229
230 // Animation settings. Disabling various forms of animation can improve performance when
231 // you have complex displays/GUIs in either DockableCtrls of the DockWindow client area
AnimateDelay(int ms)232 DockWindow& AnimateDelay(int ms) { animdelay = max(ms, 0); return *this; }
233 DockWindow& Animate(bool highlight = true, bool frames = true, bool windows = true, int ticks = 10, int interval = 20);
NoAnimate()234 DockWindow& NoAnimate() { return Animate(false, false); }
IsAnimated()235 bool IsAnimated() const { return animatehl || animatewnd; }
IsAnimatedHighlight()236 bool IsAnimatedHighlight() const { return animatehl; }
IsAnimatedFrames()237 bool IsAnimatedFrames() const { return animatefrm; }
IsAnimatedWindows()238 bool IsAnimatedWindows() const { return animatewnd; }
239
240 // Lock control. When the layout is locked the user cannot use the drag-drop functionality, the
241 // title bar buttons or the titlebar context menus. ShowLockedHandles determines whether the
242 // title bar is shown on docked ctrls when the layout is locked.
243 void LockLayout(bool lock = true);
UnlockLayout()244 void UnlockLayout() { LockLayout(true); }
IsLocked()245 bool IsLocked() const { return locked; }
246 DockWindow& ShowLockedHandles(bool show = true) { showlockedhandles = show; SyncAll(); return *this; }
IsShowingLockedHandles()247 bool IsShowingLockedHandles() const { return showlockedhandles; }
248
249 // Enableing TabAutoAlign will move docked tab bars depending on where their contained is docked.
250 // For instance, a collection of controls docked one the left edge will have it's tab bar moved
251 // to its ;left hand side
252 DockWindow& TabAutoAlign(bool al = true);
253 // If this is disabled only icons will be shown when windows are tabbed (in containers of autohidden)
254 DockWindow& TabShowText(bool text = true);
255
256 // Enable/Disable tabbing support
257 DockWindow& Tabbing(bool _tabbing = true) { tabbing = _tabbing; return *this; }
NoTabbing()258 DockWindow& NoTabbing() { return Tabbing(false); }
IsTabbing()259 bool IsTabbing() const { return tabbing; }
260 // Enable/Disable multi-layer tab support (groups of tabs stored as a tab in another group)
261 // When enabled the user can use this function by holding NestedToggleKey during a drag-drop
262 DockWindow& NestedTabs(bool _nestedtabs = true) { nestedtabs = _nestedtabs; return *this; }
NoNestedTabs()263 DockWindow& NoNestedTabs() { return NestedTabs(false); }
IsNestedTabs()264 bool IsNestedTabs() const { return nestedtabs; }
NestedToggleKey()265 dword NestedToggleKey() { return nesttoggle; }
SetNestedToggleKey(dword key)266 DockWindow& SetNestedToggleKey(dword key) { nesttoggle = key; return *this; }
267 // Enable/Disable grouping support
268 DockWindow& Grouping(bool grouping = true);
NoGrouping()269 DockWindow& NoGrouping() { return Grouping(false); }
IsGrouping()270 bool IsGrouping() const { return grouping; }
271 // Allows the user to change docking frame precedence/ordering. By default the left and right
272 // frames take precedence over the top/bottom frames (meaning they occupy the entire height of the window)
273 // When this option is enabled the user chan change this by dragging to the appropriate corner of the frame
274 DockWindow& FrameReordering(bool reorder = true){ frameorder = reorder; return *this;}
NoFrameReordering()275 DockWindow& NoFrameReordering() { return FrameReordering(false); }
IsFrameReordering()276 bool IsFrameReordering() const { return frameorder; }
277 DockWindow& SetFrameOrder(int first, int second = DOCK_NONE, int third = DOCK_NONE, int fourth = DOCK_NONE);
278 // Allow/Block docking to particular sides of the DockWindow. This works in conjunction with
279 // the settings in the DockableCtrl class.
280 DockWindow& AllowDockAll();
281 DockWindow& AllowDockNone();
282 DockWindow& AllowDockLeft(bool v = true) { dockable[DOCK_LEFT] = v; return *this; }
283 DockWindow& AllowDockTop(bool v = true) { dockable[DOCK_TOP] = v; return *this; }
284 DockWindow& AllowDockRight(bool v = true) { dockable[DOCK_RIGHT] = v; return *this; }
285 DockWindow& AllowDockBottom(bool v = true) { dockable[DOCK_BOTTOM] = v; return *this; }
286 DockWindow& AllowDock(int a, bool v = true) { ASSERT(a >= 0 && a < 4); dockable[a] = v; return *this; }
IsDockAllowed(int align)287 bool IsDockAllowed(int align) const { ASSERT(align >= 0 && align < 4); return dockable[align]; }
288 bool IsDockAllowed(int align, DockableCtrl& dc) const;
IsDockAllowedLeft()289 bool IsDockAllowedLeft() const { return dockable[DOCK_LEFT]; }
IsDockAllowedTop()290 bool IsDockAllowedTop() const { return dockable[DOCK_TOP]; }
IsDockAllowedRight()291 bool IsDockAllowedRight() const { return dockable[DOCK_RIGHT]; }
IsDockAllowedBottom()292 bool IsDockAllowedBottom() const { return dockable[DOCK_BOTTOM]; }
IsDockAllowedAny()293 bool IsDockAllowedAny() const { return dockable[DOCK_LEFT] || dockable[DOCK_TOP]
294 || dockable[DOCK_RIGHT] || dockable[DOCK_BOTTOM]; }
IsDockAllowedNone()295 bool IsDockAllowedNone() const { return !IsDockAllowedAny(); }
296 // Enable/Disable the AutoHide functions
297 DockWindow& AutoHide(bool v = true);
IsAutoHide()298 bool IsAutoHide() { return autohide; }
299 // Determines which buttons are visible on docked/autohidden DockableCtrl title bars
300 DockWindow& WindowButtons(bool menu, bool hide, bool close);
HasMenuButtons()301 bool HasMenuButtons() const { return menubtn; }
HasHideButtons()302 bool HasHideButtons() const { return hidebtn; }
HasCloseButtons()303 bool HasCloseButtons() const { return closebtn; }
304 // When enabled (default) floating DockableCtrl windows are set to be tool windows
305 // (exactly what this means varies between OSs)
306 void ChildToolWindows(bool v = true) { childtoolwindows = v; SyncAll(); }
HasToolWindows()307 bool HasToolWindows() const { return childtoolwindows; }
308
309 // Opens the standard Docking Configuration dialog (see DockConfig)
310 void DockManager();
311 // Returns the standard Docking menu so that an application can add it to it's main menu bar
312 void DockWindowMenu(Bar& bar);
313
314 // SerializeWindow serialized both the DockWindow layout and the window position/state (using TopWindow::SerializePlacement)
315 void SerializeWindow(Stream& s);
316 // SerializeLayout only serializes the DockQWindow layout
317 void SerializeLayout(Stream& s, bool withsavedlayouts = true);
318 // Saves/Load/Manage dockwindow layouts. Theese are handy for saving different
319 // GUI configurations for different application states (like editing/debugging)
320 int SaveLayout(String name);
321 void LoadLayout(int ix);
322 void LoadLayout(String name);
DeleteLayout(String name)323 void DeleteLayout(String name) { layouts.RemoveKey(name); }
GetLayoutName(int ix)324 String GetLayoutName(int ix) const { return layouts.GetKey(ix); }
LayoutCount()325 int LayoutCount() const { return layouts.GetCount(); }
GetLayouts()326 const ArrayMap<String, String>& GetLayouts() const { return layouts; }
327 // Serializes/Loads layout to/from an internal buffer (used for cancelling changes in the DockConfig window)
328 // The difference between this and Save/LoadLayout is that it also backs-up the saved layouts
329 void BackupLayout();
330 void RestoreLayout();
331 // This enables/disables all floating windows. This can be used to prevent the user
332 // moving windows when a dialog is visible (like DockConfig)
DisableFloating()333 void DisableFloating() { EnableFloating(false); }
334 void EnableFloating(bool enable = true);
335 // Changes the Chameleon style for the highlight ctrl
SetHighlightStyle(DockableCtrl::Style & s)336 void SetHighlightStyle(DockableCtrl::Style& s) { GetHighlightCtrl().SetStyle(s); }
337 // Constructer
338 DockWindow();
339 private:
340 // Container management
GetContainer(Ctrl & dc)341 DockCont *GetContainer(Ctrl& dc) { return dynamic_cast<DockCont *>(dc.GetParent()); }
342 DockCont *CreateContainer();
343 DockCont *CreateContainer(DockableCtrl& dc);
344 void DestroyContainer(DockCont& c);
345 DockCont *GetReleasedContainer(DockableCtrl& dc);
346
347 void SyncContainer(DockCont& c);
348 void SyncAll();
349
350 // Helpers
351 void Dock0(int align, Ctrl& c, int pos, bool do_animatehl = false, bool ishighlight = false);
352 void Dock0(int align, Ctrl& c, int pos, Size sz, bool do_animatehl = false, bool ishighlight = false);
353 void Undock0(Ctrl& c, bool do_animatehl = false, int fsz = -1, bool ishighlight = false);
354 void Activate(DockableCtrl& dc);
355
356 void DoFrameSize(bool animate, int align, int targetsize);
357 void FrameAnimateTick();
358 void DoFrameReorder(int align);
359 void UndoFrameReorder();
360
361 Size CtrlBestSize(const Ctrl& c, int align, bool restrict = true) const;
362
363 void ClearLayout();
364 };
365
366 class PopUpDockWindow : public DockWindow {
367 public:
368 struct Style : ChStyle<Style> {
369 Value inner[5];
370 Value outer[4];
371 Value hide[4];
372 Value highlight;
373 int innersize;
374 int outersize;
375 };
376 static const Style& StyleDefault();
377 protected:
378 virtual void ContainerDragStart(DockCont& dc);
379 virtual void ContainerDragMove(DockCont& dc);
380 virtual void ContainerDragEnd(DockCont& dc);
381
382 private:
383 struct PopUpButton : public Ctrl {
384 const Value *icon;
385 const Value *hlight;
PaintPopUpButton386 virtual void Paint(Draw& w) { Rect r = GetSize(); ChPaint(w, r, *icon); if (hlight) ChPaint(w, r, *hlight); }
PopUpButtonPopUpButton387 PopUpButton() { hlight = NULL; }
388 };
389
390 const Style *style;
391 DockCont *last_target;
392 PopUpButton *last_popup;
393 PopUpButton inner[5];
394 PopUpButton outer[4];
395 PopUpButton hide[4];
396 bool showhide;
397
398 int PopUpHighlight(PopUpButton *pb, int cnt);
399 void ShowOuterPopUps(DockCont& dc);
400 void ShowInnerPopUps(DockCont& dc, DockCont *target);
401 void ShowPopUp(PopUpButton& pb, const Rect& r);
402 void HidePopUps(bool _inner, bool _outer);
403 public:
404 PopUpDockWindow& SetStyle(const Style& s);
405 PopUpDockWindow();
406
407 PopUpDockWindow& AutoHidePopUps(bool v = true) { showhide = v; return *this; }
408
409 };
410
411 #define LAYOUTFILE <Docking/Docking.lay>
412 #include <CtrlCore/lay.h>
413
414 class DockConfigDlg : public WithDockConfigLayout<TopWindow>
415 {
416 public:
417 typedef DockConfigDlg CLASSNAME;
418
419 DockConfigDlg(DockWindow& dockwindow);
420 private:
421 DockWindow & dock;
422 const Vector<DockableCtrl *>& dockers;
423 VectorMap<String, int> groups;
424 DockMenu menu;
425 String backup;
426 int all;
427 DockableCtrl *highlight;
428
429 void RefreshTree(bool dogroups = false);
430
431 void OnTreeContext(Bar& bar);
432 void OnSaveLayout();
433 void OnLoadLayout();
434 void OnDeleteLayout();
435 void OnTreeCursor();
436 void OnListCursor();
437 void OnNewGroup();
438 void OnDeleteGroup();
439 void OnOK();
440 void OnCancel();
441 void OnLock();
442
443 void OnTreeDrag();
444 void OnTreeDrop(int parent, int ii, PasteClip& d);
445
446 void Highlight(DockableCtrl *dc);
447 void StopHighlight();
448
449 void DeleteGroup(int id);
450
451 String DockerString(DockableCtrl *dc) const;
452 String PositionString(DockableCtrl *dc) const;
453 int ListIndex() const;
454 void DupePrompt(String type);
455 };
456
457 template <class T>
CreateDockable(WString title)458 T& DockWindow::CreateDockable(WString title)
459 {
460 T &q = ctrls.Create<T>();
461 Register(q.Title(title));
462 return q;
463 }
464
465 }
466
467 #endif
468