OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
docking.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1995, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of docking window classes
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9
10#include <owl/docking.h>
11#include <owl/controlb.h>
12#include <owl/tooltip.h>
13#include <owl/uihelper.h> // for TUIBorder edge painting
14#include <owl/uimetric.h>
15#include <owl/template.h>
16
17#if defined(BI_MULTI_THREAD_RTL)
18#include <owl/thread.h>
19#endif
20
21#if defined(__TRACE) || defined(__WARN)
22# include <owl/profile.h>
23#endif
24
25#include <vector>
26#include <algorithm>
27
28using namespace std;
29
30namespace owl {
31
32//
33// Fillin missing defines for some configurations
34//
35#if !defined(WM_SIZING)
36# define WM_SIZING 0x0214
37#endif
38#if !defined(DS_SETFOREGROUND)
39# define DS_SETFOREGROUND 0x200L // not in win3.1
40#endif
41
42//
43// Diagnostic group for docking
44//
47
48
50
51//----------------------------------------------------------------------------
52
53//
54/// This constructor creates a dockable gadget window and sets the appropriate
55/// styles for the window.
56//
59 TFont* font,
60 TModule* module)
61:
62 TGadgetWindow(parent, direction, font, module),
63 TDockable(),
64 Cursor(nullptr)
65{
66#if 0
67 Attr.Style |= WS_BORDER; // Add in border for boundries between dockables
68#else
69 Attr.Style &= ~WS_BORDER; // Normally no borders
70#endif
71 Attr.Style |= WS_CLIPSIBLINGS;
72
73 // Always shrink wrapped when dockable since slip fills out docking area
74 //
75 SetShrinkWrap(true, true);
76}
77
78//
79//
80//
85
86
92
93//
94//
95//
101
102
103/// Inserts/deletes FlatBar Grip.
104void
106{
109 if(dir == Rectangular){
110 delete Cursor;
111 Cursor = 0;
112 }
113 else if(!GadgetWithId(IDG_FLATHANDLE)){
115 if(gadget)
117
118 // set cursor
119 if(dir == Horizontal)
120 Cursor = new TCursor(0, IDC_SIZEWE);
121 else
122 Cursor = new TCursor(0, IDC_SIZENS);
123
125 }
126 else{
127 if(GetDirection() != dir){
128 delete Cursor;
129 if(dir == Horizontal)
130 Cursor = new TCursor(0, IDC_SIZEWE);
131 else
132 Cursor = new TCursor(0, IDC_SIZENS);
133 }
135 }
136 }
137 // if exist GridGadget
139 // set cursor
140 if(dir == Horizontal)
141 Cursor = new TCursor(0, IDC_SIZEWE);
142 else
143 Cursor = new TCursor(0, IDC_SIZENS);
144
146 }
147}
148
149//
150//
151//
152bool
154{
162 boundsRect.right = boundsRect.left+8;
164 }
165 else{
166 boundsRect.bottom = boundsRect.top+7;
168 }
169 if(boundsRect.Contains(point)){
171 return true;
172 }
173 }
175}
176
177//
178/// Finds out how big this dockable would be in a given location, and with a given
179/// optional size hint.
180//
181TSize
183{
185
186 // Save current settings to restore when done, since this is a info-request
187 // only function
188 //
190 int oldWidth = RowWidth;
191
192 // If rectangular, calcuate adjust size for surrounding parent frame window
193 //
194 TSize delta(0,0);
195 if (dir == Rectangular) {
196 // If we currently are in a floating slip, use that window to calc frame delta
197 //
198 TWindow* parent = GetParentO();
199 if (oldDir == Rectangular && parent && parent->GetHandle()) {
200 delta = parent->GetWindowRect().Size() - parent->GetClientRect().Size();
201 // In Win95, the bottom margin and the bottom sizing border are the
202 // same color and not separated by a hard border, so we 'kern' them
203 // together to match the size of the top margin.
204 //
206 int topM, leftM, bottomM, rightM;
208 delta.cy -= std::min(yt, bottomM);
209 }
210 // No floating parent yet. Calculate the delta based on assumed frame
211 // styles. (This rect is only used to size the drag frame anyway.)
212 //
213 else {
214 TRect winRect(0, 0, 0, 0);
218 delta = winRect.Size();
219 }
220 }
221
222 TSize sz(0, 0);
223 Direction = dir;
224
225 // Seek a vertical size if just a non-zero cy is given
226 //
227 if (dim && dim->cx == 0 && dim->cy != 0) {
228
229 int seekCy = dim->cy - delta.cy; // This is the height to shoot for
230
233
234 // Seek the row whose height is less than seekCy
235 ///CH: I really would like to have a better, non-iterative algorithm for
236 ///CH: this, but for now this works.
237 //
238 if (testSz.cy < seekCy) {
239 // Seek a taller row by successivly shrinking the width
240 //
241 while (1) {
242 int prevW = RowWidth;
243 sz = testSz;
244 RowWidth -= 5;
245 if (RowWidth <= 0) { // Limit reached. Give up
246 RowWidth = testSz.cx;
247 sz = testSz;
248 break;
249 }
251 if (seekCy < testSz.cy) { // Shrunk too far: use previous size
252 RowWidth = prevW;
253 break;
254 }
255 }
256 }
257 else if (testSz.cy > seekCy) {
258 // Seek a shorter row by successivly growing the width
259 //
260 while (1) {
261 int prevW = RowWidth;
262 sz = testSz;
263 RowWidth += 5;
264 if (RowWidth > 1000) { // CHNOTE: Limit reached. Give up
265 RowWidth = testSz.cx;
266 sz = testSz;
267 break;
268 }
270 if (seekCy > testSz.cy) {
271 RowWidth = prevW;
272 break;
273 }
274 }
275 }
276 else // seekCy == testSz.cy
277 sz = testSz;
278 }
279 // Change to a given horizontal size, or just the natural size for the
280 // direction
281 //
282 else {
283 if (dim) // Change the row width here because we are changing size.
284 RowWidth = dim->cx - delta.cx;
286 }
287
288 Direction = oldDir;
289 RowWidth = oldWidth;
290 sz += delta;
291
292 return sz;
293}
294
295//
296/// Gets this dockable's screen rectangle.
297//
298void
303
304//
305/// Returns a gadget window tile direction code, given a docking absolute location
306/// code.
307//
310{
311 switch(loc) {
312 case alTop:
313 case alBottom:
314 return Horizontal;
315 case alLeft:
316 case alRight:
317 return Vertical;
318 case alNone:
319 default:
320 return Rectangular;
321 }
322}
323
324//
325/// Causes this dockable to lay itself out vertically, horizontally, or
326/// rectangularly.
327//
328void
330{
332 if (GetDirection() != dir || dim) {
333 if (dim)
334 SetRectangularDimensions(dim->cx, dim->cy); // Sets RowWidth mostly
335
336 // Set the layout direction, which ends up invoking LayoutSession &
337 // SetWindowPos
338 //
340 }
341}
342
343//
344/// Returns true if the mouse click point is in a spot that should move this
345/// dockable around.
346//
347bool
349{
351 if (g)
352 // !CQ should also allow non-clickables to drag, like text!
353#if 1
354 return !g->IsVisible(); // Allow hidden gadgets to begin a drag; separators are hidden
355#else
356 return !g->GetEnabled(); // Allow disabled gadgets to begin a drag
357#endif
358
359 return true;
360}
361
362//
363/// Returns the TWindow part of this dockable object. In this case, it is just this
364/// window.
365//
366TWindow*
368{
369 return this;
370}
371
372//
373/// If the gadget window changes size when laying out a dockable gadget window, this
374/// function tells the dock about it so the dock can resize too.
375//
376void
378{
379 TSize sz;
380 GetDesiredSize(sz); // Find out how big we'd like to be
381
382 Attr.W = sz.cx; // This will allow LayoutSession to work as if
383 Attr.H = sz.cy; // we were the right size.
384
386
387 // If we are in a slip that has been created properly, then tell it to adjust
388 // to our new layout
389 //
390 if (GetParentO()) {
392 if (slip) {
393 // If this is a null-sized gadget window, hide our floating frame.
394 //
395 bool hideSlip = Attr.W == 0 || Attr.H == 0;
397
398 // Make sure the slip will adjust to our new size
399 //
401 if (!stc)
403 SetWindowPos(nullptr, 0, 0, Attr.W, Attr.H, SWP_NOACTIVATE | SWP_NOMOVE);
404 if (!stc)
406 }
407 // If we aren't in a slip (because we haven't been inserted yet) resize
408 // anyway.
409 //
410 else {
411 SetWindowPos(nullptr, 0, 0, Attr.W, Attr.H, SWP_NOACTIVATE | SWP_NOMOVE);
412 }
413 }
414}
415
416//
417/// Returns the harbor containing the dockable object.
418//
419THarbor*
421{
422 // If parent is a slip, return its harbor.
423 // If parent is the harbor (because the dockable is hidden), return the harbor.
424 //
425 if (!Parent)
426 return nullptr;
428 if (slip)
429 return slip->GetHarbor();
431 return harbor;
432}
433
434//
435/// Forwards event to slip to allow movement of gadget within the slip.
436//
437void
439{
440 TPoint pt = point;
442
443 // Forward the message to the parent, this is for the docking areas. To
444 // allow moving of the controlbars within the docking areas.
445 // !CQ Use OWL parent??? Or old hwnd parent?
446 //
447 TWindow* w = GetParentO();
448
449 // Check that we're parented to the right window. In OLE server situation,
450 // the toolbar could have been reparented to another HWND [i.e. container's
451 // window]
452 //
453 if (w && ::GetParent(*this) != w->GetHandle())
454 return;
455
456 // Forward to parent [which is a slip]
457 //
458 if (w && w->GetHandle()) {
459 TPoint p = MapWindowPoints(*w, point); // Transform to parent's coordinate system.
460 w->HandleMessage(WM_LBUTTONDOWN, modKeys, MkParam2(int16(p.x), int16(p.y)));
461 }
462
463 // At this point, our window may be in drag mode [i.e. being docked or
464 // undocked]. This means that the harbor has invoked 'SetCapture' which in
465 // turn implies that we won't see subsequent WM_MOUSEMOVE/WM_LBUTTONDOWN
466 // messages. This will leave the tooltip the impression [strong impression
467 // if I may add] that the mouse button never came up. The net side-effect
468 // will be that the tooltip will not activate until it sees an LBUTTONUP
469 // message. So to avoid this side-effect we fake an LBUTTONUP message here.
470 //
472 if (harbor && GetCapture() == *harbor)
473 {
475 if (tooltip && tooltip->IsWindow())
476 {
477 MSG msg;
478 msg.hwnd = *this;
479 msg.message = WM_LBUTTONUP;
480 msg.wParam = modKeys;
481 msg.lParam = MkUint32(int16(pt.x), int16(pt.y));
482 tooltip->RelayEvent(msg);
483 }
484 }
485}
486//----------------------------------------------------------------------------
487
491
492//
493/// Constructs a dockable control bar.
494//
497 TFont* font,
498 TModule* module)
499:
500 TDockableGadgetWindow(parent, direction, font, module)
501{
503 WantTooltip = true;
504
506}
507
508//
509//
510//
511void
513{
514 // !CQ Conrad's IDEOWL uses 6*Border,3*border & vice versa
515 if (GetDirection() == Horizontal) {
516 Margins.Left = Margins.Right = TUIMetric::CxSizeFrame + TUIMetric::CxFixedFrame;
517 Margins.Top = Margins.Bottom = TUIMetric::CySizeFrame;
518 }
519 else if(Direction == Vertical){
520 Margins.Left = Margins.Right = TUIMetric::CxSizeFrame;
521 Margins.Top = Margins.Bottom = TUIMetric::CySizeFrame + TUIMetric::CyFixedFrame;
522 }
523 else{
524 Margins.Left = Margins.Right = TUIMetric::CxSizeFrame;
525 Margins.Top = Margins.Bottom = TUIMetric::CySizeFrame;
526 }
527}
528
529//
530//
531//
532void
538
539
544 EV_WM_SIZING, // Win 4.0 message only.
550
551//
552/// Constructs a floating slip and sets the appropriate style for the window.
553//
555 int x, int y,
557 bool shrinkToClient,
558 int captionHeight,
559 bool popupPalette,
560 TModule* module)
561:
562 TFloatingFrame(parent, clientWnd->GetCaption(), nullptr/*clientWnd*/, shrinkToClient,
564
565{
566 SetDragFrame(false);
567
569 Attr.Style &= ~(WS_VISIBLE); // Create initially hidden, show later
570 Attr.Style |= WS_CLIPCHILDREN; // Dont womp on children
571 Attr.Style |= WS_BORDER | WS_THICKFRAME; // Sizeable frame to allow reshaping
572
573 // Let tiny caption recalc margin & border dimensions using new styles. Tiny
574 // caption will adjust these some more as needed.
575 //
576 EnableTinyCaption(TFloatingFrame::DefaultCaptionHeight, true);
577
578 // Calculate a real initial position, & an estimated size. May resize later
579 // when client has reshaped.
580 //
581 TRect winRect(x, y, x+clientWnd->GetWindowAttr().W, y+clientWnd->GetWindowAttr().H);
582 AdjustWindowRectEx(winRect, Attr.Style, false, Attr.ExStyle);
583
584#if 1
585 Attr.X = x; // Places this frame at given screen x,y
586 Attr.Y = y;
587#else
588 Attr.X = winRect.left; // Places client rect at given screen x,y
589 Attr.Y = winRect.top;
590#endif
591 Attr.W = winRect.Width();
592 Attr.H = winRect.Height();
593}
594
595//
596/// Handles lbutton down bubbled up from the client to begin a dockable drag
597/// operation.
598//
599void
601{
602 if (hitTest == HTCAPTION) {
603 // Call the dockable dragging setup function in Harbor, passing this
604 // window as the dragged dockable and as the docking slip too
605 //
606 if (Harbor && Harbor->DockDraggingBegin(*this, point, alNone, this))
607 return;
608 }
610}
611
612//
613/// Handles lbutton down bubbled up from the client to begin a dockable drag
614/// operation.
615//
616void
618{
619 // Is the mouseDown in a area where we can move the docked window?
620 //
623
624 TPoint childPt = MapWindowPoints(*cw, point); // Transform to client window's coordinate system.
625
626 if (d && d->ShouldBeginDrag(childPt)) {
628 if (Harbor && Harbor->DockDraggingBegin(*this, p, alNone, this))
629 return; // Successfully started
630 }
632}
633
634//
635/// When closing the floating slip, removes any dockable first so that it is not
636/// destroyed. Dockables are owned by the harbor, not the slip, and must not be
637/// destroyed when the slip is destroyed.
638//
639void
641{
643 if (dd)
644 Harbor->Remove(*dd); // Will cause a close in DockableRemoved()
645 else
647}
648
649//
650/// Handles the Windows 4.0 message for the best resize user feedback.
651//
652bool
654{
655
656 // Look for size changes & make them track the dockable
657 //
659 if (w) {
661 if (dockable) {
662 TSize trackSize(rect.Size());
663 switch (side) {
664 case WMSZ_BOTTOM:
665 case WMSZ_TOP:
666 trackSize.cx = 0;
667 break;
668 case WMSZ_LEFT:
669 case WMSZ_RIGHT:
670 trackSize.cy = 0;
671 break;
672 }
673 TSize dsz = dockable->ComputeSize(alNone, &trackSize);
674
675 // Center the fixed axis
676 //
677 switch (side) {
678 case WMSZ_BOTTOM:
679 case WMSZ_TOP:
680 rect.left = rect.left + (rect.Width() - dsz.cx)/2;
681 break;
682 case WMSZ_LEFT:
683 case WMSZ_RIGHT:
684 rect.top = rect.top + (rect.Height() - dsz.cy)/2;
685 break;
686 }
687
688 // Change the window size, keeping it pinned on the opposite corner
689 //
690 switch (side) {
691 case WMSZ_TOP:
692 case WMSZ_TOPRIGHT:
693 rect.top = rect.bottom - dsz.cy;
694 rect.right = rect.left + dsz.cx;
695 break;
696 case WMSZ_TOPLEFT:
697 rect.left = rect.right - dsz.cx;
698 rect.top = rect.bottom - dsz.cy;
699 break;
700 case WMSZ_BOTTOMLEFT:
701 case WMSZ_LEFT:
702 rect.left = rect.right - dsz.cx;
703 rect.bottom = rect.top + dsz.cy;
704 break;
705 case WMSZ_BOTTOM:
706 case WMSZ_BOTTOMRIGHT:
707 case WMSZ_RIGHT:
708 rect.right = rect.left + dsz.cx;
709 rect.bottom = rect.top + dsz.cy;
710 break;
711 }
712 }
713 }
714
715 return true;
716}
717
718//
719/// Handles WM_WINDOWPOSCHANGING to make sure that the frame is properly constrained
720/// by the dimensions of the dockable client.
721//
722bool
724{
726
727 // Look for size changes & make them track the dockable
728 //
729 if (!(windowPos.flags&SWP_NOSIZE)) {
731 if (w) {
733 if (dockable) {
734// !CQ Shouldn't we adjust .cx by our frame thickness to get client width?
735// !CQ Maybe keep Delta around for these client<->frame size calculations...
736/// TRect cr(0,0,0,0);
737/// AdjustWindowRectEx(cr, Attr.Style, false, Attr.ExStyle);
738 TSize ts(windowPos.cx, 0);
739 TSize dsz = dockable->ComputeSize(alNone, &ts);
740
741 // Center the non-sizing axis
742 //
743 if (!(windowPos.flags&SWP_NOMOVE)) {
744/// if (sizing horizontally)
745 windowPos.y = windowPos.y + (windowPos.cy - dsz.cy)/2;
746/// else
747/// windowPos.x = windowPos.x + (windowpos.cx - dsz.cx)/2;
748 }
749 windowPos.cx = dsz.cx;
750 windowPos.cy = dsz.cy;
751 }
752 }
753 }
754 windowPos.flags |= SWP_NOACTIVATE; // Not very effective, but worth a try
755 return false;
756}
757
758//
759/// Handles WM_WINDOWPOSCHANGED to make sure that the dockable client gets a chance
760/// to do final layout.
761//
762void
764{
766
767 if (!(windowPos.flags&SWP_NOSIZE)) {
769 if (w) {
771 if (dockable) {
772/// TRect cr(0,0,0,0);
773/// AdjustWindowRectEx(cr, Attr.Style, false, Attr.ExStyle);
774 TSize ts(windowPos.cx, 0);
775 TSize dsz = dockable->ComputeSize(alNone, &ts);
776
777 dockable->Layout(alNone, &dsz);
778 }
779 }
780 }
781}
782//
783/// Event handler for the .INI file changed message. The window may have resized
784/// because the user has changed the caption size.
785//
786void
788
789{
791
792 // Resize, since our sizing borders may have changed size
793 //
794 if (w) {
795 TRect newWinRect = w->GetWindowRect();
796 AdjustWindowRectEx(newWinRect, Attr.Style, false, Attr.ExStyle);
797
799
800 if (winRect.Height() != newWinRect.Height() ||
801 winRect.Width() != newWinRect.Width()) {
803 }
804 }
805}
806
807//
808// Respond to WM_GETMINMAXINFO messages to ensure that the minTrackSize
809// used by Windows is not greater than the size would be for a vertical
810// floating control bar.
811//
812void
814{
815 TSize sz(0,0);
816 ComputeSize( alLeft, &sz );
817 info.ptMinTrackSize.x = sz.cx;
818 info.ptMinTrackSize.y = sz.cy;
819}
820
821//
822/// Overriden TDockingSlip virtual. Called by mouseup handler after a dockable is
823/// dropped into this docking window.
824//
825void
827 const TPoint* /*topLeft*/,
828 TRelPosition /*position*/, TDockable* /*relDockable*/)
829
830{
831 dockable.Layout(alNone); // No specific dimensions suggested
832 SetClientWindow(dockable.GetWindow()); // Set dockable as client & resize
833
834 // Retrieve window object of dockable
835 //
836 TWindow* dockableWindow = dockable.GetWindow();
838
839 // Let window know it was docked [well, undocked]
840 //
841#ifdef UNIX
842 if (dockableWindow->IsWindow()) //?????????????????????
844 TParam2((TDockingSlip*)this));
845#else
847 TParam2((TDockingSlip*)this));
848#endif
849}
850
851//
852/// Overriden TDockingSlip virtual. Called by lbutton up handler after a drag within
853/// this docking window. This floating slip only moves itself.
854//
855void
857 TRelPosition /*position*/, TDockable* /*relDockable*/)
858{
859 if (topLeft)
860 SetWindowPos(nullptr, topLeft->x, topLeft->y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE);
861}
862
863//
864/// Overriden TDockingSlip virtual. Called by lbutton up handler after a dockable
865/// has been removed from this docking slip.
866//
867void
869{
870 // Clear client window
871 //
872 SetClientWindow(nullptr);
873
874// !BB CloseWindow has the side-effect of leaving things around - i.e.
875// !BB window object is not condemned... Can be expensive after a few
876// !BB floating slips.
877// !BB
878// !BB CloseWindow();
880}
881
882//
883/// Forward the first four TDockable virtuals to the client dockable.
884//
885TSize
887{
889 if (w) {
891 if (dockable)
892 return dockable->ComputeSize(loc, dim);
893 }
894 return TSize(0, 0);
895}
896
897//
898/// Gets this dockable's screen rect.
899//
900void
905
906//
907/// Forwards the layout message over to the dockable object.
908//
909void
911{
913 if (w) {
915 if (dockable)
916 dockable->Layout(loc, dim); // !CQ adjust dim by our frame thickness?
917 }
918 CHECK(w);
919}
920
921//
922/// A given mouse down should never begin a drag for this dockable.
923//
924bool
926{
927 return false;
928}
929
930//
931/// Returns the TWindow part of this dockable object. In this case it is actually
932/// the client window.
933//
934TWindow*
940
941//
942/// Returns the associated harbor.
943//
944THarbor*
946{
947 return Harbor;
948}
949
950//
951/// Returns the location of the object.
952//
955{
956 return alNone;
957}
958
959
969
970//
971/// Constructs an edge slip, and sets the approriate styles for the window.
972//
974:
975 TWindow(&parent, _T("EdgeSlip"), module),
976 Location(location),
977 GridType(Location == alTop || Location == alBottom ? YCoord : XCoord)
978{
979#if defined(__TRACE) || defined(__WARN)
980 // Make slip dark blue for debugging purposes in diagnostic build
981 //
982 TProfile iniFile(_T("Diagnostics"), _T(OWL_INI));
983
984 bool useDiagColor = iniFile.GetInt(_T("DiagToolbarBorders")) != 0;
985
986 if (useDiagColor)
987 SetBkgndColor(TColor(0, 0, 128));
988 else
989#endif
990
992
994}
995
996//
997// Type of decoration
998//
999struct TEachDecoration {
1000 TWindow* Window;
1001 int Top; // or Left if XCoord
1002 int Bottom; // or Right if XCoord
1003
1004 TEachDecoration(TWindow*, TGridType);
1005 TEachDecoration(int Top, int Bottom, TWindow* w);
1006
1007 bool operator <(const TEachDecoration& other) const
1008 {return Top < other.Top;}
1009};
1010
1011//
1012// Create a decoration from the grid.
1013//
1014TEachDecoration::TEachDecoration(TWindow* w, TGridType gridType)
1015:
1016 Window(w)
1017{
1018 TRect rect = w->GetWindowRect();
1019 if (gridType == YCoord) {
1020 Top = rect.top;
1021 Bottom = rect.bottom;
1022 }
1023 else {
1024 Top = rect.left;
1025 Bottom = rect.right;
1026 }
1027}
1028
1029//
1030// Create the decoration from a specific location.
1031//
1032TEachDecoration::TEachDecoration(int top, int bottom, TWindow* w)
1033:
1034 Window(w),
1035 Top(top),
1036 Bottom(bottom)
1037{
1038}
1039
1040namespace
1041{
1042
1043template <class TDecoration>
1045{
1047 for (TWindow* w = s.GetFirstChild(); w; w = (w == s.GetLastChild()) ? nullptr : w->Next())
1049 sort(v.begin(), v.end());
1050 return v;
1051}
1052
1053} // namespace
1054
1055//
1056/// Ensures that all decorations in the docking window are abutted against each
1057/// other (both horizontally and vertically); there should be no gaping holes.
1058//
1059void
1061{
1062 TWindow::SetupWindow(); // Create all children.
1063
1065
1066 // Look for any gaping holes between the dockable windows and collapse them.
1067 // Normally, this doesn't occur unless the to be created size is different
1068 // from the actual created size of a gadget. This, currently, only occurs
1069 // for TControlGadgets where the gadget is a combobox the created size
1070 // specifies the editclass area and the drop-down area, however, the window
1071 // rect (when the GetHandle() is valid) is just the editclass area.
1072 //
1073 int diff = 0;
1074 int startWindowChange = -1;
1075 int rowHeight = 0;
1076 for (size_t i = 1; i < decoList.size(); ++i) {
1077 // Are the two decorations we're going to look at on the same vertical?
1078 //
1079 if (decoList[i-1].Top != decoList[i].Top) {
1080 // No, so compute possible difference.
1081 //
1082 if (decoList[i-1].Bottom+diff != decoList[i].Top+diff) {
1083 // Remember the first window which is adjusted, we'll want to delay the
1084 // SetWindowPos until all windows from this point to the end have been
1085 // completely adjusted.
1086 //
1087 if (startWindowChange == -1)
1088 startWindowChange = static_cast<int>(i);
1089
1090 // Found a spot. Compute the offset.
1091 //
1092 diff += decoList[i-1].Top + rowHeight - decoList[i].Top;
1093 }
1094 rowHeight = decoList[i].Bottom - decoList[i].Top;
1095 }
1096 else {
1097 rowHeight = std::max(rowHeight, decoList[i].Bottom - decoList[i].Top);
1098 }
1099 if (diff) {
1100 TEachDecoration& decoItem = decoList[i];
1101 decoItem.Top += diff;
1102 decoItem.Bottom += diff;
1103 }
1104 }
1105
1106 // Re-adjust all windows which have changed location.
1107 //
1108 if (startWindowChange != -1) {
1109 for (size_t i = startWindowChange; i < decoList.size(); ++i) {
1110 TEachDecoration& decoItem = decoList[i];
1111 TRect r;
1112 decoItem.Window->GetWindowRect(r);
1113
1114 TPoint pt(r.left, r.top);
1115 if (GridType == YCoord)
1116 pt.y = decoItem.Top;
1117 else
1118 pt.x = decoItem.Top;
1119
1120 // Map from global to local coord (the parent's coordinate space).
1121 //
1122 ::MapWindowPoints(nullptr, *this, (TPoint*)&pt, 1);
1123 decoItem.Window->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1125 i++;
1126 }
1127 }
1128
1129 // Make sure that our size is updated
1130 //
1131 ReLayout(true);
1132}
1133
1134//
1135/// Changes the reciever to be the framewindow, not the docking window. The receiver
1136/// window is normally set up in Activate upon the creation of TButtonGadgetEnabler.
1137//
1138void
1140{
1141 if (GetParentO()) {
1142 // Already being processed?
1143 //
1144 if (!commandEnabler.IsReceiver(GetParentO()->GetHandle())) {
1145 // No, so forward it up to our parent
1146 //
1147 commandEnabler.SetReceiver(GetParentO()->GetHandle());
1149 }
1150 }
1151}
1152
1153//
1154/// Forward command messages to the parent.
1155//
1156/// Changes the receiver to be the framewindow, not the docking window. The receiver
1157/// window is normally set up in Activate upon the creation of TButtonGadgetEnabler.
1158//
1159TResult
1161{
1162 TRACEX(OwlCmd, 1, "TEdgeSlip::EvCommand - id(" << id << "), ctl(" <<\
1163 static_cast<void*>(hWndCtl) << "), code(" << notifyCode << ")");
1164
1165 if (notifyCode == 0 && GetParentO())
1166 return GetParentO()->EvCommand(id, hWndCtl, notifyCode);
1167
1169}
1170
1171//
1172/// Forwards the left button down message to the dockable object.
1173//
1174void
1176{
1178
1179 // Only allow immediate children of the docking window to be clicked on.
1180 //
1181 if (cw && cw->GetParentO() == this) {
1182 // Is the mouseDown in a area where we can move the docked window?
1183 //
1186 if (d && d->ShouldBeginDrag(childPt)) {
1188 if (Harbor && Harbor->DockDraggingBegin(*d, p, Location, this)) {
1189 return; // Successfully started
1190 }
1191 }
1192 }
1194}
1195
1196//
1197/// Handles WM_LBUTONDBLCLICK to tell the frame to edit a toolbar.
1198//
1199void
1204
1205//
1206/// Returns the size of the client area, leaving room for the etched separators.
1207//
1208uint
1210{
1212 if (IsIconic())
1213 return ret;
1214
1215 // Only add in space if this slip is not shrunk to nothing
1216 //
1217 if (calcSize.rgrc[0].bottom - calcSize.rgrc[0].top > 0) {
1218 if (!(Attr.Style & WS_BORDER)) {
1219 if (Location != alBottom)
1220 calcSize.rgrc[0].top += 2;
1221 if (Location != alTop)
1222 calcSize.rgrc[0].bottom -= 2;
1223 }
1224 }
1225 return 0;
1226}
1227
1228//
1229/// Erases the background and draws in etched 'borders' within the client area.
1230//
1232{
1233 // Non-3d style
1234 // !CQ Always do 3d etch here?
1235 //
1236 if (Attr.Style & WS_BORDER) {
1238 }
1239 // Use 3-d style
1240 //
1241 else {
1242 TWindowDC dc(*this);
1243
1244 // Paint etched line along the top for left, top & right slips, and along
1245 // the bottom for bottom, left & right slips to separate from the menubar,
1246 // statusbar & eachother.
1247 //
1248 int height(GetWindowRect().Height());
1249 if (Location != alBottom){
1250 TRect tr(0,0,9999,2);
1252 }
1253 if (Location != alTop){
1254 TRect tr(0,height-2,9999,height);
1256 }
1257 }
1258}
1259
1260//
1261/// Erases the background and draws in etched 'borders' within the client area.
1262//
1263bool
1265{
1266 TWindow::EvEraseBkgnd(hDC); // Let TWindow erase everything
1267
1268 // !CQ Paint etched lines for docked children?
1269
1270 return true;
1271}
1272
1273//
1274/// Makes sure that the slip size is updated when a child changes size.
1275//
1276void
1278{
1279 if (n.Event == WM_SIZE)
1280 ReLayout(false);
1281 else
1283}
1284
1285//
1286//
1287//
1288class TDecorationSpan {
1289public:
1290 int Left;
1291 int Right;
1292 int Top;
1293 int Bottom;
1294 TWindow* Window;
1295 bool Moved;
1296
1297 TDecorationSpan(TWindow* w, TGridType);
1298
1299 bool operator <(const TDecorationSpan& other) const
1300 {return Top < other.Top || (Top == other.Top && Left < other.Left);}
1301};
1302
1303//
1304// Create the decoration span from the grid.
1305//
1306TDecorationSpan::TDecorationSpan(TWindow* w, TGridType gridType)
1307 : Moved(false)
1308{
1309 TRect rect = w->GetWindowRect();
1310 ::MapWindowPoints(nullptr, w->GetParentH(), reinterpret_cast<TPoint*>(&rect), 2); // map to slip coordinates
1311
1312 Window = w;
1313 if (gridType == YCoord) {
1314 Top = rect.top;
1315 Left = rect.left;
1316 Right = rect.right;
1317 Bottom = rect.bottom;
1318 }
1319 else {
1320 Top = rect.left;
1321 Left = rect.top;
1322 Right = rect.bottom;
1323 Bottom = rect.right;
1324 }
1325}
1326
1327//
1328/// When the slip shrinks, this function adjusts dockables where needed.
1329//
1330bool
1338
1339//
1340/// Compresses or expands dockables perpendicular to the grid line.
1341//
1342void
1344{
1346
1347 // Tile dockables perpendicular to grid lines
1348 //
1349 if (!decoList.empty()) {
1350 int gridLine = decoList[0].Top;
1351 int lastTop = gridLine - 1;
1352 int delta = 0;
1353 for (size_t i = 0; i < decoList.size(); ++i) {
1354 decoList[i].Moved = false;
1355 int t = decoList[i].Top;
1356 if (t != lastTop) {
1357 delta = gridLine-t;
1358 gridLine = t;
1359 lastTop = t;
1360 }
1361 if (delta != 0) {
1362 decoList[i].Top += delta;
1363 decoList[i].Bottom += delta;
1364 decoList[i].Moved = true;
1365 }
1366 gridLine = std::max(gridLine,decoList[i].Bottom);
1367 }
1368
1369 // Move all dockables that have changed location.
1370 //
1371 for (size_t j = 0; j < decoList.size(); ++j) {
1372 TPoint pt;
1373 TDecorationSpan& decoItem = decoList[j];
1374 if (decoItem.Moved) {
1375 if (GridType == YCoord) {
1376 pt.x = decoItem.Left;
1377 pt.y = decoItem.Top;
1378 }
1379 else {
1380 pt.x = decoItem.Top;
1381 pt.y = decoItem.Left;
1382 }
1383 decoItem.Window->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1385 }
1386 }
1387 }
1388
1389 ReLayout(false);
1390}
1391
1392//
1393/// Compresses empty space along grid line if any dockables hang out past the end.
1394//
1395void
1397{
1398 // Scan each row looking for a decoration that hangs off the end.
1399 // If possible, pull that decoration in by collapsing empty space between
1400 // decorations on that row.
1401 //
1403 size_t firstOnRow = 0;
1404 size_t lastOnRow = 0;
1405 while (firstOnRow < decoList.size()) {
1406 int spaceOnRow = decoList[firstOnRow].Left;
1407 int rowTop = decoList[firstOnRow].Top;
1408 while (lastOnRow + 1 < decoList.size() && decoList[lastOnRow + 1].Top == rowTop) {
1409 spaceOnRow += decoList[lastOnRow+1].Left-(decoList[lastOnRow].Right+1);
1410 lastOnRow ++;
1411 }
1412
1413 int delta = decoList[lastOnRow].Right - width;
1414 if (delta > 0 && spaceOnRow > 0) {
1415 if (spaceOnRow > delta) {
1416 // if there is extra empty space, collapse from the right
1417 //
1418 int r = width;
1419 size_t i = lastOnRow;
1420 while (i >= firstOnRow && (decoList[i].Right+1) > r) {
1421 int dx = (decoList[i].Right+1) - r;
1422 decoList[i].Left -= dx;
1423 decoList[i].Right -= dx;
1424 decoList[i].Moved = true;
1425 r = decoList[i].Left;
1426 if (i == 0) break;
1427 i--;
1428 }
1429 }
1430 else {
1431 // if there is not extra empty space, just collapse the space
1432 //
1433 int r = 0;
1434 for (size_t i = firstOnRow; i <= lastOnRow; ++i) {
1435 if (decoList[i].Left > r) {
1436 int dx = decoList[i].Left - r;
1437 decoList[i].Left -= dx;
1438 decoList[i].Right -= dx;
1439 decoList[i].Moved = true;
1440 r = decoList[i].Right+1;
1441 }
1442 else
1443 break;
1444 }
1445 }
1446 }
1448 }
1449
1450 // Move all dockables that have changed location.
1451 //
1452 for (size_t i = 0; i < decoList.size(); ++i) {
1453 TPoint pt;
1454 TDecorationSpan& decoItem = decoList[i];
1455 if (decoItem.Moved) {
1456 if (GridType == YCoord) {
1457 pt.x = decoItem.Left;
1458 pt.y = decoItem.Top;
1459 }
1460 else {
1461 pt.x = decoItem.Top;
1462 pt.y = decoItem.Left;
1463 }
1464 decoItem.Window->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1466 }
1467 }
1468}
1469
1470//
1471/// Changes the child metrics of this docking window within its decorated frame.
1472/// Calls when the rectangle area of the docking area is different from the computed
1473/// area of the dockable windows within the docking area.
1474//
1475void
1477{
1478 // Has the docking area changed in size?
1479 //
1481
1482 bool sizeChanged;
1483 if (Location == alTop || Location == alBottom) {
1484 sizeChanged = Attr.H != area.cy;
1485 Attr.H = area.cy;
1486 }
1487 else {
1488 sizeChanged = Attr.W != area.cx;
1489 Attr.W = area.cx;
1490 }
1491
1492 // If the size has change or we need to force a layout, then do so
1493 //
1494 if (sizeChanged || forcedLayout) {
1496 CHECK(df);
1497
1498 // Set the same metrics just to dirty the layout plan & force a rebuild
1499 //
1501 df->GetChildLayoutMetrics(*this, metrics);
1502 df->SetChildLayoutMetrics(*this, metrics);
1503
1504 df->Layout();
1505 }
1506}
1507
1508//
1509/// This function overrides TDockingSlip::DockableInsert to insert a new dockable
1510/// object into this TEdgeSlip. Called by mouseup handler after a dockable object is
1511/// dropped into this slip.
1512//
1513void
1516{
1517 // Get dockable's window & hide it in case we have to toss it around a bit
1518 // Reparent the window to the edge slip
1519 //
1520 TWindow* dockableWindow = dockable.GetWindow();
1522 dockableWindow->ShowWindow(SW_HIDE);
1523 dockableWindow->SetParent(this);
1524
1525 // Let window know it was docked...
1526 //
1527#ifdef UNIX
1528 if (dockableWindow->IsWindow()) //???????????????????????
1529 dockableWindow->HandleMessage(WM_OWLWINDOWDOCKED, TParam1(GridType == YCoord ? alTop : alLeft), TParam2( (TDockingSlip*)this) );
1530#else
1531 dockableWindow->DispatchMsg(WM_OWLWINDOWDOCKED, 0, TParam1(GridType == YCoord ? alTop : alLeft),
1532 TParam2(static_cast<TDockingSlip*>(this)));
1533#endif
1534
1535 // Slam dockable over to 0,0 since Move assumes we own it already
1536 //
1537 dockableWindow->SetWindowPos(nullptr, 0, 0, 0, 0,
1539
1540 // Make sure that the dockable is oriented the right way--horizontal layout
1541 // for Y-gridded slips
1542 //
1543 dockable.Layout(GridType == YCoord ? alTop : alLeft);
1544
1545/// dockableWindow->Create(); // just in case? but only if we are?
1547 dockableWindow->ShowWindow(SW_SHOWNA);
1548}
1549
1550//
1551/// Overriden TDockingSlip virtual. Called by mouseup handler after a drag within
1552/// this docking window.
1553//
1554void
1557{
1558 TWindow* dockableWindow = dockable.GetWindow();
1560
1561 // If no dockable topleft given, calculate based on relative dockable &
1562 // location
1563 //
1564 if (topLeft) {
1565 dockPos = *topLeft;
1566 }
1567 else {
1568 // Figure out the best relative position if none given
1569 //
1570 if (position == rpNone) switch (Location) {
1571 case alNone:
1572 break;
1573 case alTop:
1574 position = rpBelow;
1575 break;
1576 case alBottom:
1577 position = rpAbove;
1578 break;
1579 case alLeft:
1581 break;
1582 case alRight:
1584 break;
1585 default: //JJH added empty default construct
1586 break;
1587 }
1588
1589 // Get the last child inserted into this docking window and use it as the
1590 // relative window if none was given
1591 //
1592 TWindow* relWindow = 0;
1593 if (relDockable)
1594 relWindow = relDockable->GetWindow();
1595 if (!relWindow)
1597
1598 // Get its rect if it exists, or the screen coord of this slip's client area
1599 //
1600 TRect relWindowRect(0,0,0,0);
1601 if (relWindow)
1602 relWindowRect = relWindow->GetWindowRect();
1603 else
1604 ::MapWindowPoints(nullptr, *this, reinterpret_cast<TPoint*>(&relWindowRect), 2);
1605
1606 TSize dockableSize = dockableWindow->GetWindowRect().Size();
1607 switch (position) {
1608 case rpNone:
1609 break;
1610 case rpAbove:
1612 break;
1613 case rpBelow:
1614 dockPos = TPoint(relWindowRect.left, relWindowRect.bottom);
1615 break;
1616 case rpLeftOf:
1618 break;
1619 case rpRightOf:
1621 break;
1622 default: //JJH added default construct
1623 break;
1624 }
1625 }
1626
1627 // Find a gridline on which to put the dockable
1628 //
1629 int dockableEdge;
1631 CHECK(!GridList.empty());
1632 int bottomEdge = GridList[0].Top;
1633 if (Location == alTop || Location == alBottom)
1635 else
1637
1638 for (size_t i = 0; i < GridList.size(); ++i) {
1639 if (dockableEdge <= (GridList[i].Top+GridList[i].Bottom)/2)
1640 break;
1641 if (GridList[i].Window != dockableWindow)
1642 bottomEdge = std::max(bottomEdge,GridList[i].Bottom);
1643 }
1644
1645 // Adjust perpendicular coord to newly found spot
1646 //
1648 if (Location == alTop || Location == alBottom) {
1649 newPos.y = bottomEdge;
1650 }
1651 else {
1652 newPos.x = bottomEdge;
1653 }
1654
1655 // Adjust from screen coords, but make sure rect topleft is > 0
1656 //
1657 ::MapWindowPoints(nullptr, *this, &newPos, 1);
1658 if (newPos.x < 0)
1659 newPos.x = 0;
1660 if (newPos.y < 0)
1661 newPos.y = 0;
1662
1663 // Position & show the dockable window
1664 //
1665 dockableWindow->SetWindowPos(nullptr, newPos.x, newPos.y, 0, 0,
1667 dockableWindow->ShowWindow(SW_SHOWNA);
1668
1669 // Adjust all windows on the grid line
1670 //
1672
1673 // Squash down dockable's previous area if needed
1674 //
1676}
1677
1678//
1679/// Overriden TDockingSlip virtual. Called by mouseup handler after a dockable has
1680/// been removed from this docking slip.
1681//
1682void
1684{
1686}
1687
1688//
1689/// All terminology in this function is referenced to the following two windows
1690/// Drag and LeftEdge. The LeftEdge window is only valid if the Drag windows's
1691/// left side is intersecting the LeftEdge window's right side.
1692/// \code
1693/// ======================
1694/// ------------------- Drag Window |
1695/// | LeftEdge Window |================
1696/// -------------------
1697/// \endcode
1698//1 The goal of this function is to anchor down the Drag window's left side.
1699/// This is accomplished by one of three ways:
1700/// - 1. Leave the Drag window where it is; if the Drag window's left side does
1701/// not intersect with any other windows (no LeftEdge window).
1702/// - 2. Slide the Drag window to the right of the LeftEdge window being
1703/// intersected. This is only done if the intersection is not beyond the
1704/// midpoint (less than 50% of the LeftEdge window) of the LeftEdge window.
1705/// - 3. Slide the Drag window to the left side position of the LeftEdge window
1706/// (the Drag window's left side is equal to the LeftEdge window's left
1707/// side). The LeftEdge window is then slid to the right side of the Drag
1708/// window; if the intersection is beyond the mid point of the left edge
1709/// window (more than 50% of the LeftEdge window).
1710//
1711TWindow*
1713{
1714 // Do we want to move the draggedWindow, if so do that.
1715 //
1716 TRect draggedRect = draggedWindow->GetWindowRect();
1717
1719 if (first) {
1720 TWindow* w = first;
1721 do {
1722 if (w != draggedWindow) {
1723 TRect currRect = w->GetWindowRect();
1724 TPoint pt;
1725
1726 if (Location == alTop || Location == alBottom) {
1727 if (draggedRect.left >= currRect.left && draggedRect.left <= currRect.right &&
1728 currRect.top == draggedRect.top) {
1729
1730 int midPt = (currRect.right - currRect.left) / 2;
1731
1732 // If the dragged window is obscuring the window underneath by more
1733 // than 50% then the dragged window will keep its position and the
1734 // underneath window must moved. Otherwise, the dragged window
1735 // will move and the window underneath will move.
1736 //
1737 if (currRect.left + midPt > draggedRect.left) {
1738 // Move the draggedWindow to the same left as the window
1739 // underneath.
1740 //
1741 pt.x = currRect.left;
1742 pt.y = draggedRect.top;
1743 ::MapWindowPoints(nullptr, *this, &pt, 1);
1744 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1746
1747 // Move the current window to the right of the dragged window.
1748 //
1749 draggedRect = draggedWindow->GetWindowRect();
1750 pt.x = draggedRect.right;
1751 pt.y = currRect.top;
1752 ::MapWindowPoints(nullptr, *this, &pt, 1);
1753 w->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1755 return w;
1756 }
1757 else {
1758 // Move the dragged window to the right of the current window (w).
1759 //
1760 pt.x = currRect.right;
1761 pt.y = draggedRect.top;
1762 ::MapWindowPoints(nullptr, *this, &pt, 1);
1763 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1765 return draggedWindow;
1766 }
1767 }
1768 }
1769 else {
1770 // Left and right docking area.
1771 //
1772 if (draggedRect.top >= currRect.top && draggedRect.top <= currRect.bottom &&
1773 currRect.left == draggedRect.left) {
1774
1775 int midPt = (currRect.bottom - currRect.top) / 2;
1776
1777 // If the dragged window is obscuring the window underneath by more
1778 // than 50% then the dragged window will keep its position and the
1779 // underneath window must moved. Otherwise, the dragged window will
1780 // move and the window underneath will move.
1781 //
1782 if (currRect.top+midPt > draggedRect.top) {
1783 // Move the draggedWindow to the same left as the window underneath.
1784 //
1785 pt.x = currRect.left;
1786 pt.y = draggedRect.top;
1787 ::MapWindowPoints(nullptr, *this, &pt, 1);
1788 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1790
1791 // Move the current window to the right of the dragged window.
1792 //
1793 draggedRect = draggedWindow->GetWindowRect();
1794 pt.x = draggedRect.right;
1795 pt.y = currRect.top;
1796 ::MapWindowPoints(nullptr, *this, &pt, 1);
1797 w->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1799 return w;
1800 }
1801 else {
1802 // Move the dragged window to the right of the current window (w).
1803 //
1804 pt.x = currRect.right;
1805 pt.y = draggedRect.top;
1806 ::MapWindowPoints(nullptr, *this, &pt, 1);
1807 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1809 return draggedWindow;
1810 }
1811 }
1812 }
1813 }
1814
1815 w = w->Next();
1816 } while (w != first);
1817 }
1818
1819 return draggedWindow;
1820}
1821
1822//
1823// Structure to manage the list of windows to slide.
1824//
1825struct TWindowItem {
1826 TWindow* DockedWindow;
1827 int LeftSide;
1828
1829 TWindowItem(TWindow* dockedW = 0, int left = 0) : DockedWindow(dockedW),
1830 LeftSide(left)
1831 {}
1832
1833 // operator to satisfy TIArrayAsVector
1834 //
1835 bool operator == (const TWindowItem& other) {
1836 return (other.DockedWindow == DockedWindow) &&
1837 (other.LeftSide == LeftSide);
1838 }
1839};
1840
1841//
1842/// Builds a list (sorted by left coordinate) of windows on the same horizontal
1843/// (top/bottom docking) or vertical (left/right docking) of windows to the right of
1844/// or below the dragged window. The function then slides all windows from the first
1845/// one intersecting the dragged window to the last one in the list.
1846//
1847void
1849{
1850
1852
1853 // Include the (upto) two windows which were anchored in MoveDraggedWindow.
1854 //
1855 TRect draggedRect = draggedWindow->GetWindowRect() | movedWindow->GetWindowRect();
1857 if (first) {
1858 TWindow* w = first;
1859 do {
1860 // If the current window is the moved window or the draggedWindow then
1861 // grab another window.
1862 //
1863 if (w != draggedWindow) {
1864 TRect currRect = w->GetWindowRect();
1865
1866 // Build a list of windows on the same horizontal or vertical after
1867 // the dragged window.
1868 // !CQ assumes top/bottom slip -- flip axis for left/right
1869 //
1870 if (currRect.top == draggedRect.top && currRect.left >= draggedRect.left) {
1871 uint i = 0;
1872
1873 while (i < windowList.Size()) {
1874 if (currRect.left <= windowList[i].LeftSide)
1875 break;
1876 i++;
1877 }
1878
1879 TWindowItem wItem(w, currRect.left); // !CQ leave to debug
1880 windowList.AddAt(wItem, i);
1881 }
1882 }
1883
1884 w = w->Next();
1885 } while (w != first);
1886 }
1887
1888
1889 // Are there windows after the dragged window to adjust?
1890 //
1891
1892 if(windowList.Size()) {
1893 uint i = 0;
1894
1895 // Find the first one, all subsequent ones (plus this one) will be slid.
1896 //
1897 while (i < windowList.Size()) {
1898 if (windowList[i].LeftSide >= draggedRect.left &&
1899 windowList[i].LeftSide < draggedRect.right)
1900 break;
1901 i++;
1902 }
1903
1904 // Slide all windows after the dragged window.
1905 //
1906
1907 if (i == 0 || i != windowList.Size()) {
1909 TPoint pt;
1910
1911 while (i < windowList.Size()) {
1912 int offset = w1->GetWindowRect().right - windowList[i].LeftSide;
1913
1914 pt.x = windowList[i].LeftSide + offset;
1915 pt.y = windowList[i].DockedWindow->GetWindowRect().top;
1916 ::MapWindowPoints(nullptr, *this, &pt, 1);
1917 windowList[i].DockedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1919 w1 = windowList[i++].DockedWindow;
1920 }
1921 }
1922 }
1923
1924// Iterators cannot be used when modifying the underlying container
1925//
1926// TWindowItemArrayIter iter(windowList);
1927// while (iter) {
1928// TWindowItem* item = iter.Current();
1929// windowList.Detach(item);
1930// delete item;
1931// iter++;
1932// }
1933}
1934
1935#if 0
1936//
1937// Pull every child beyond a given coord in by a given delta (positive),
1938// or push out every child beyond the given coord by the given delta (negative)
1939//
1940void
1941TEdgeSlip::Collapse(int topCoord, int delta)
1942{
1944 if (first) {
1945 TWindow* w = first;
1946 do {
1947 TRect rect = w->GetWindowRect();
1948 if (Location == alTop || Location == alBottom) {
1949 if (rect.top > topCoord) {
1950 rect.Offset(0, -delta);
1951 ::MapWindowPoints(0, *this, (LPPOINT)&rect, 1);
1952 w->SetWindowPos(0, rect.left, rect.top, 0, 0,
1954 }
1955 }
1956 else {
1957 if (rect.left > topCoord) {
1958 rect.Offset(-delta, 0);
1959 ::MapWindowPoints(0, *this, (LPPOINT)&rect, 1);
1960 w->SetWindowPos(0, rect.left, rect.top, 0, 0,
1962 }
1963 }
1964 w = w->Next();
1965 } while (w != first);
1966 }
1967}
1968#endif
1969
1970//
1971/// Computes the docking area size based on the dockables inside (total height if
1972/// top/bottom docking area or total width if left/right docking area). Includes the
1973/// non-client area etched borders or real window borders. Will return misleading
1974/// Size() if dockables not 0 justified.
1975//
1976TSize
1978{
1979 TRect rect(0, 0, 0, 0);
1980
1982 if (first) {
1983 TWindow* w = first;
1984 do {
1985 // Union of all visible areas.
1986 //
1987 if (w->GetWindowAttr().Style & WS_VISIBLE)
1988 rect |= w->GetWindowRect();
1989 w = w->Next();
1990 } while (w != first);
1991 }
1992
1993 // Only add in space if this slip is not shrunk to nothing
1994 //
1995 if (rect.bottom > rect.top && rect.right > rect.left) {
1996 if (!(Attr.Style & WS_BORDER)) { // if 3d style, add space for the etchings
1997 if (Location != alBottom)
1998 rect.bottom += 2;
1999 if (Location != alTop)
2000 rect.bottom += 2;
2001 }
2002 else {
2003 AdjustWindowRectEx(rect, Attr.Style, false, Attr.ExStyle);
2004 }
2005 }
2006
2007 return rect.Size(); // !CQ or could return rect.BottomRight()
2008}
2009
2010//
2011/// Returns the perpendicular size of the grid line with the given base coordinates.
2012/// Returns 0 if there are no dockables on the given grid line.
2013//
2014int
2016{
2018 int h = 0;
2019 if (first) {
2020 TWindow* w = first;
2021 do {
2022 if (w->GetWindowAttr().Style & WS_VISIBLE) {
2023 TRect r = w->GetWindowRect();
2024
2025 if (GridType == YCoord) {
2026 if (baseCoord == r.top) {
2027 h = std::max(h, r.Height());
2028 }
2029 }
2030 else {
2031 if (baseCoord == r.left){
2032 h = std::max(h, r.Width());
2033 }
2034 }
2035 }
2036 w = w->Next();
2037 } while (w != first);
2038 }
2039 return h;
2040}
2041
2042
2043//
2044/// Retrieves the location of the slip.
2045//
2048{
2049 return Location;
2050}
2051
2052
2058
2059//
2060/// Creates the harbor. The harbor is where the slips can go dock.
2061//
2063:
2064 TWindow(&df, _T("Harbor")),
2065 DecFrame(df)
2066{
2067 Attr.W = 0;
2068 Attr.H = 0;
2069 Attr.Style = WS_CHILD; // not visible
2070
2071 SlipTop = nullptr;
2072 SlipLeft = nullptr;
2073 SlipBottom = nullptr;
2074 SlipRight = nullptr;
2075
2076 DragDC = nullptr;
2077 DragDockable = nullptr;
2078}
2079
2080//
2081/// Destructor.
2082/// Currently does nothing.
2083//
2085{
2086}
2087
2088
2089//
2090/// Creates an edge slip at a location.
2091//
2092TEdgeSlip*
2097
2098//
2099/// Constructs a floating slip with a particular window at a location.
2100//
2106
2107//
2108/// Returns the slip at the location.
2109//
2110TEdgeSlip*
2112{
2113 switch (location) {
2114 case alNone:
2115 return nullptr;
2116 case alTop:
2117 return SlipTop;
2118 case alBottom:
2119 return SlipBottom;
2120 case alLeft:
2121 return SlipLeft;
2122 case alRight:
2123 return SlipRight;
2124 default: //JJH added empty default construct
2125 break;
2126 }
2127 return nullptr;
2128}
2129
2130//
2131/// Sets a new edge slip for a given location. Also lets the edge slip know who we
2132/// are.
2133//
2134void
2136{
2137 slip->SetHarbor(this);
2138
2139 switch (location) {
2140 case alNone:
2141 break;
2142 case alTop:
2143 SlipTop = slip;
2144 break;
2145 case alBottom:
2146 SlipBottom = slip;
2147 break;
2148 case alLeft:
2149 SlipLeft = slip;
2150 break;
2151 case alRight:
2152 SlipRight = slip;
2153 break;
2154 default: //JJH added empty default construct
2155 break;
2156 }
2157}
2158
2159//
2160/// Returns the default docking relative position for a given slip location.
2161/// \todo !CQ make a TDockingSlip virtual!
2162//
2165{
2166 switch (location) {
2167 case alNone:
2168 return rpNone;
2169 case alTop:
2170 return rpBelow;
2171 case alBottom:
2172 return rpAbove;
2173 case alLeft:
2174 return rpRightOf;
2175 case alRight:
2176 return rpLeftOf;
2177 default: //JJH added empty default construct
2178 break;
2179 }
2180 return rpNone;
2181}
2182
2183struct TDitherBrush
2185 : public TLocalObject
2186#endif
2187{
2188 TDitherBrush():Brush(THatch8x8Brush::Hatch11F1)
2189 {
2190 }
2191 ~TDitherBrush()
2192 {
2193 }
2194
2195 THatch8x8Brush Brush;
2196
2197#if defined(BI_MULTI_THREAD_RTL)
2198// TMRSWSection Lock;
2199#endif
2200};
2201
2202//
2203// Static instance of the colors
2204//
2205static TDitherBrush& GetDitherBrush()
2206{
2207#if defined(BI_MULTI_THREAD_RTL)
2209 return ditherBrush.Get();
2210#else
2211 static TDitherBrush ditherBrush;
2212 return ditherBrush;
2213#endif
2214};
2215
2216//
2217// Draw a fast window-type frame rect
2218//
2219static int fastWindowFrame(TDC& dc, const TRect& r, bool thick, uint32 rop)
2220{
2221 int thickness = thick ? TUIMetric::CxSizeFrame // a thick
2222 : TUIMetric::CxBorder; // or a thin frame
2223
2224 int x = r.left;
2225 int y = r.top;
2226 int cx = r.right - x - thickness;
2227 int cy = r.bottom - y - thickness;
2228
2229 if (thick)
2230 dc.SelectObject(GetDitherBrush().Brush);
2231 else
2232 dc.SelectStockObject(WHITE_BRUSH);
2233
2234 dc.PatBlt(x, y, thickness, cy, rop); // Left
2235 dc.PatBlt(x + thickness, y, cx, thickness, rop); // Top
2236 dc.PatBlt(x, y + cy, cx, thickness, rop); // Bottom
2237 dc.PatBlt(x + cx, y + thickness, thickness, cy, rop); // Right
2238
2239 return true;
2240}
2241
2242//
2243/// Begins a dockable window tracking session. Returns true if started
2244/// satisfactorily.
2245//
2246bool
2249{
2250 // Get dockable to drag, its frame rectangle & the mouse anchor point
2251 // Compute relative position of mouse from top/left corner of window.
2252 //
2256
2257 // Remember the docking area & original docking area too. Also remember which
2258 // docking slip to notify when drag is done.
2259 //
2262
2263 // Find out the sizes of the dockable in the three orientations:
2264 // Vertical, Horizontal & Natural
2265 //
2269
2270 // Calculate the screen relative rectangles for the four docking areas based
2271 // on the dec frame's client area.
2272 //
2273 TRect frameR = DecFrame.GetClientWindow()->GetWindowRect();
2274/// DecFrame.MapWindowPoints(0, frameR, 2);
2275
2276 if (SlipTop)
2278 else
2279 SlipTR.Set(frameR.left, frameR.top, frameR.right, frameR.top);
2280
2281 if (SlipBottom)
2283 else
2284 SlipBR.Set(frameR.left, frameR.bottom, frameR.right, frameR.bottom);
2285
2286 if (SlipLeft)
2288 else
2289 SlipLR.Set(frameR.left, frameR.top, frameR.left, frameR.bottom);
2290
2291 if (SlipRight)
2293 else
2294 SlipRR.Set(frameR.right, frameR.top, frameR.right, frameR.bottom);
2295
2296 // Capture the mouse & create a screen DC to use while dragging
2297 //
2298 SetCapture();
2299 DragDC = new TScreenDC;
2300
2301 // Update dragged window here to avoid asynchronous repaint uglies when
2302 // exposed by click. Then paint frame.
2303 //
2304 DragDockable->GetWindow()->UpdateWindow();
2305 fastWindowFrame(*DragDC, DragFrame, DragSlipLoc == alNone, PATINVERT);
2306
2307 return true;
2308}
2309
2310//
2311/// Handles MouseMove to perform dockable dragging if a drag is in progress.
2312//
2313void
2315{
2316 if (DragDockable && DragDC) {
2318
2319 // Save un-painting the frame until the end to reduce flicker
2320 //
2323
2324 // Compute the new horz, vert & natural frames to test for touching of
2325 // edge slips & to eventualy update DragRect. Make sure that horz & vert
2326 // rects surround mouse, shift as needed.
2327 //
2328 DragFrame.MoveTo(p.x - DragAnchor.x, p.y - DragAnchor.y);
2329
2331 if (!hFrame.Contains(p))
2332 hFrame.MoveTo(hFrame.left, p.y - DragHSize.cy/2);
2333
2335 if (!vFrame.Contains(p))
2336 vFrame.MoveTo(p.x - DragVSize.cx/2, vFrame.top);
2337
2339 if (!nFrame.Contains(p))
2340 nFrame.Offset(p.x - DragNSize.cx/2 - nFrame.left,
2341 p.y - DragNSize.cy/2 - nFrame.top);
2342
2343 if (hFrame.Touches(SlipTR))
2345 else if (hFrame.Touches(SlipBR))
2347 else if (vFrame.Touches(SlipLR))
2349 else if (vFrame.Touches(SlipRR))
2351 else
2353
2354 // If over a docking area and it is not the same as the last one, then
2355 // re-compute the frame rectangle
2356 //
2357 if (DragSlipLoc == alNone)
2358 DragFrame = nFrame;
2359 else if (DragSlipLoc == alTop || DragSlipLoc == alBottom)
2360 DragFrame = hFrame;
2361 else
2362 DragFrame = vFrame;
2363
2364 /// Adjust if needed to put frame around mouse? Check each rect? At least
2365 /// horz & vert?
2366 ///
2367/// if (!DragFrame.Contains(p))
2368/// DragFrame.Offset(p.x - DragFrame.left - 15, p.y - DragFrame.top - 15);
2369
2370 // Unpaint old frame, & paint new frame
2371 //
2372 fastWindowFrame(*DragDC, oldDragFrame, oldDragSlipLoc == alNone, PATINVERT);
2373 fastWindowFrame(*DragDC, DragFrame, DragSlipLoc == alNone, PATINVERT);
2374 }
2375 else
2377}
2378
2379//
2380/// Handles mouse up to drop a dockable window being dragged.
2381//
2382void
2384{
2385 if (DragDockable && DragDC) {
2386
2387 // Unpaint frame.
2388 //
2389 fastWindowFrame(*DragDC, DragFrame, DragSlipLoc == alNone, PATINVERT);
2390
2392
2395
2397 DragDockable = nullptr;
2398
2399 delete DragDC;
2400 DragDC = nullptr;
2401
2402 // We're docking into a new slip--call the Move function to do the
2403 // work.
2404 //
2405 if (DragOrgSlipLoc != DragSlipLoc) {
2406 // Get the real dockable interface for the actual dockable window--
2407 // working dockable may have been a helper.
2408 //
2410 CHECK(dd);
2412 }
2413 // Notifiy docking slip that the dragging resulted in a dockable move.
2414 //
2415 else {
2416 if (DragNotificatee)
2418 }
2419 }
2420 else
2422}
2423
2424//
2425/// Handles the left button double click and forwards the message to the dockable
2426/// window.
2427//
2428void
2430{
2431 // We get this message when a slip is in drag mode, and mouse clicks are
2432 // captured by the harbor.
2433 //
2434 if (DragDockable) {
2435 // If dragging, stop dragging and pass the message to the dragged window.
2436 //
2437 TWindow* win = DragDockable->GetWindow();
2440 }
2441 else {
2443 }
2444}
2445
2446//
2447/// Inserts a dockable into the appropriate docking area indicated by the given
2448/// location and either a point or a relative dockable and position.
2449//
2452 const TPoint* where,
2454{
2455 // Get the actual window associated with the dockable
2456 //
2457 TWindow* dw = dockable.GetWindow();
2458
2459 // Making the dockable Floating.
2460 //
2461 if (location == alNone) {
2462 // The 'where' is relative to the decframe's client. Make absolute when
2463 // the floatFrame is a popup
2464 //
2466 if (where) {
2467 floatWhere = *where;
2468 }
2469 else {
2470 // Don't know where to put the floating palette, use CW_USEDEFAULT
2471 //
2473 }
2474
2475 // Call out to the virtual to contruct a hidden floating slip
2476 //
2479 dw);
2480 // Give slip pointer to harbor
2481 //
2482 slip->SetHarbor(this);
2483
2484 // If decorated frame is already created, the create floating slip
2485 //
2486 if (DecFrame.GetHandle()) {
2487 slip->Create();
2488 slip->DockableInsert(dockable, where, rpNone, nullptr);
2489 slip->ShowWindow(SW_SHOWNA);
2490
2491 } else {
2492
2493 // Slip will be created latter (auto-creation) - make sure it's visible
2494 //
2495 slip->GetWindowAttr().Style |= WS_VISIBLE;
2496 slip->DockableInsert(dockable, where, rpNone, nullptr);
2497 }
2498
2499 // Return floating slip
2500 //
2501 return slip;
2502 }
2503 else {
2505 if (!slip) {
2506 // Make an edge slip if not one already for the given edge
2507 //
2511
2512 // If frame is created, go ahead and create slip
2513 //
2514 if (DecFrame.GetHandle())
2515 slip->Create();
2516 }
2517
2518 // Insert the dockable into the slip, based on args given
2519 //
2520 slip->DockableInsert(dockable, where, position, relDockable);
2521
2522 // Return edge slip
2523 //
2524 return slip;
2525 }
2526}
2527
2528//
2529/// Moves a dockable from one slip to another.
2530//
2531void
2534{
2535 // Get current slip, assuming it is the parent of the dockable's window
2536 //
2538 TWindow* dockableWindow = dockable.GetWindow();
2539 if (dockableWindow) {
2541 }
2542
2543 // If the location hasn't changes, just tweak the position within the slip,
2544 // otherwise insert into new & remove from old.
2545 //
2546 if (previousSlip && previousSlip->GetLocation() == location) {
2547 if (where)
2548 previousSlip->DockableMove(dockable, where);
2549 else
2550 ;// !CQ call DockableMove when it takes position & relDockable
2551 }
2552 else {
2554 dockable.GetRect(previousRect);
2555
2556 // Remove from the previous slip
2557 //
2559
2560 // Insert into the new slip
2561 //
2563 }
2564}
2565
2566//
2567/// Removes a dockable from the harbor.
2568//
2569void
2571{
2572 // Get the actual window associated with the dockable
2573 //
2574 TWindow* dockableWindow = dockable.GetWindow();
2575
2576 if (dockableWindow) {
2578 dockable.GetRect(previousRect);
2579
2580 // Find the slip containing the dockable
2581 //
2583 TDockingSlip);
2584
2585 // Remove the dockable from the slip and reparent it to the harbor
2586 //
2587 dockableWindow->ShowWindow(SW_HIDE);
2588 dockableWindow->SetParent(this);
2589
2590 // Notify original docking slip that its dockable was removed.
2591 //
2592 if (previousSlip)
2593 previousSlip->DockableRemoved(previousRect);
2594 }
2595}
2596
2597} // OWL namespace
2598
#define CHECK(condition)
Definition checks.h:239
#define DIAG_DECLARE_GROUP(group)
Definition checks.h:404
#define TRACEX(group, level, message)
Definition checks.h:263
#define DIAG_DEFINE_GROUP_INIT(f, g, e, l)
Definition checks.h:429
Class wrapper for management of color values.
Definition color.h:245
static const TColor Sys3dFace
The symbolic system color value for the face color of 3-dimensional display elements.
Definition color.h:339
Base class for an extensible interface for auto enabling/disabling of commands (menu items,...
Definition window.h:209
TCursor, derived from TGdiBase, represents the GDI cursor object class.
Definition gdiobjec.h:730
TDecoratedFrame automatically positions its client window (you must supply a client window) so that i...
Definition decframe.h:74
TLocation
Enumeration describing the possible locations of a Gadgetwindow [Used mainly for location of Toolbar ...
Definition decframe.h:88
virtual void Insert(TWindow &decoration, TLocation location=Top)
Insert a decoration window into position at one of the four edges.
Definition decframe.cpp:899
A control bar class that is dockable.
Definition docking.h:133
TDockableControlBar(TWindow *parent=0, TTileDirection direction=Horizontal, TFont *font=0, TModule *module=0)
Constructs a dockable control bar.
Definition docking.cpp:495
void EvOwlWindowDocked(uint pos, const TDockingSlip &slip)
Definition docking.cpp:533
A version of TGadgetWindow which is dockable.
Definition docking.h:92
void Layout(TAbsLocation, TSize *=nullptr) override
Causes this dockable to lay itself out vertically, horizontally, or rectangularly.
Definition docking.cpp:329
virtual TTileDirection GetDirectionForLocation(TAbsLocation loc)
Returns the layout direction to use when placed in a slip This can be overridden to provide different...
Definition docking.cpp:309
auto GetWindow() -> TWindow *override
Returns the TWindow part of this dockable object.
Definition docking.cpp:367
void EvOwlWindowDocked(uint pos, const TDockingSlip &slip)
Inserts/deletes FlatBar Grip.
Definition docking.cpp:105
void EvLButtonDown(uint modKeys, const TPoint &point)
Forwards event to slip to allow movement of gadget within the slip.
Definition docking.cpp:438
auto ShouldBeginDrag(TPoint &) -> bool override
Returns true if the mouse click point is in a spot that should move this dockable around.
Definition docking.cpp:348
~TDockableGadgetWindow() override
Definition docking.cpp:81
virtual TGadget * GetGripGadget()
Definition docking.cpp:88
void GetRect(TRect &) override
Gets this dockable's screen rectangle.
Definition docking.cpp:299
auto ComputeSize(TAbsLocation, TSize *) -> TSize override
Finds out how big this dockable would be in a given location, and with a given optional size hint.
Definition docking.cpp:182
void LayoutSession() override
If the gadget window changes size when laying out a dockable gadget window, this function tells the d...
Definition docking.cpp:377
auto GetHarbor() -> THarbor *override
Returns the harbor containing the dockable object.
Definition docking.cpp:420
TDockableGadgetWindow(TWindow *parent=0, TTileDirection direction=Horizontal, TFont *font=0, TModule *module=0)
This constructor creates a dockable gadget window and sets the appropriate styles for the window.
Definition docking.cpp:57
bool EvSetCursor(HWND hWndCursor, uint codeHitTest, TMsgId mouseMsg)
Definition docking.cpp:153
TDockable is an abstract base class for fixed or floating docking windows that want to be dockable in...
Definition docking.h:57
virtual TWindow * GetWindow()=0
Gets dockable's window and hides it, in case we have to toss it around a bit.
virtual TSize ComputeSize(TAbsLocation loc, TSize *dim)=0
Returns the rectangle of the dockable window in the given location.
virtual void GetRect(TRect &rect)=0
Return the rectangle of the dockable window in the given location.
TDockingSlip is an abstract base class for windows which accepts and holds dockable windows.
Definition docking.h:154
virtual void DockableMove(TDockable &dockable, const TPoint *topLeft=0, TRelPosition position=rpNone, TDockable *relDockable=0)=0
THarbor * Harbor
Definition docking.h:176
TEdgeSlip is the class of windows used by THarbor as the actual docking slips along the decorated fra...
Definition docking.h:238
TWindow * MoveDraggedWindow(TWindow *draggedWindow)
All terminology in this function is referenced to the following two windows Drag and LeftEdge.
Definition docking.cpp:1712
void DockableInsert(TDockable &dockable, const TPoint *topLeft, TRelPosition position, TDockable *relDockable) override
This function overrides TDockingSlip::DockableInsert to insert a new dockable object into this TEdgeS...
Definition docking.cpp:1514
void EvParentNotify(const TParentNotify &)
Makes sure that the slip size is updated when a child changes size.
Definition docking.cpp:1277
uint EvNCCalcSize(bool calcValidRects, NCCALCSIZE_PARAMS &calcSize)
Returns the size of the client area, leaving room for the etched separators.
Definition docking.cpp:1209
TEdgeSlip(TDecoratedFrame &parent, TAbsLocation location, TModule *module=0)
Constructs an edge slip, and sets the approriate styles for the window.
Definition docking.cpp:973
void EvLButtonDown(uint modKeys, const TPoint &point)
Forwards the left button down message to the dockable object.
Definition docking.cpp:1175
bool EvWindowPosChanging(WINDOWPOS &windowPos)
When the slip shrinks, this function adjusts dockables where needed.
Definition docking.cpp:1331
void DockableRemoved(const TRect &orgRect) override
Overriden TDockingSlip virtual.
Definition docking.cpp:1683
void SetupWindow() override
Ensures that all decorations in the docking window are abutted against each other (both horizontally ...
Definition docking.cpp:1060
void CompressGridLines()
Compresses or expands dockables perpendicular to the grid line.
Definition docking.cpp:1343
void DockableMove(TDockable &dockable, const TPoint *topLeft, TRelPosition position, TDockable *relDockable) override
Overriden TDockingSlip virtual.
Definition docking.cpp:1555
auto EvCommand(uint id, THandle hWndCtl, uint notifyCode) -> TResult override
Forward command messages to the parent.
Definition docking.cpp:1160
int GridSize(int baseCoord)
Returns the perpendicular size of the grid line with the given base coordinates.
Definition docking.cpp:2015
void EvLButtonDblClk(uint modKeys, const TPoint &point)
Handles WM_LBUTONDBLCLICK to tell the frame to edit a toolbar.
Definition docking.cpp:1200
void EvCommandEnable(TCommandEnabler &commandEnabler) override
Changes the reciever to be the framewindow, not the docking window.
Definition docking.cpp:1139
void CompressParallel(int width)
Compresses empty space along grid line if any dockables hang out past the end.
Definition docking.cpp:1396
auto GetLocation() const -> TAbsLocation override
Retrieves the location of the slip.
Definition docking.cpp:2047
void EvNCPaint(HRGN)
Erases the background and draws in etched 'borders' within the client area.
Definition docking.cpp:1231
TSize ComputeDockingArea()
Computes the docking area size based on the dockables inside (total height if top/bottom docking area...
Definition docking.cpp:1977
void MoveAllOthers(TWindow *draggedWindow, TWindow *movedWindow)
Builds a list (sorted by left coordinate) of windows on the same horizontal (top/bottom docking) or v...
Definition docking.cpp:1848
void ReLayout(bool forcedLayout)
Called by Harbor when creating this docking window on a drop.
Definition docking.cpp:1476
bool EvEraseBkgnd(HDC)
Erases the background and draws in etched 'borders' within the client area.
Definition docking.cpp:1264
A gadget that is used on the far right of a status bar to provide re-sizing grip for the host window.
Definition gadget.h:375
Derived from TFrameWindow and TTinyCaption, TFloatingFrame implements a floating frame that can be po...
Definition floatfra.h:52
TFloatingSlip is a floating frame which can hold a dockable window.
Definition docking.h:187
bool EvWindowPosChanging(WINDOWPOS &windowPos)
Handles WM_WINDOWPOSCHANGING to make sure that the frame is properly constrained by the dimensions of...
Definition docking.cpp:723
auto ComputeSize(TAbsLocation, TSize *) -> TSize override
Forward the first four TDockable virtuals to the client dockable.
Definition docking.cpp:886
void EvSettingChange(uint, LPCTSTR)
Event handler for the .INI file changed message.
Definition docking.cpp:787
void EvNCLButtonDown(uint hitTest, const TPoint &point)
Handles lbutton down bubbled up from the client to begin a dockable drag operation.
Definition docking.cpp:600
auto GetHarbor() -> THarbor *override
Returns the associated harbor.
Definition docking.cpp:945
auto ShouldBeginDrag(TPoint &) -> bool override
A given mouse down should never begin a drag for this dockable.
Definition docking.cpp:925
void DockableInsert(TDockable &, const TPoint *topLeft, TRelPosition, TDockable *relDockable) override
Overriden TDockingSlip virtual.
Definition docking.cpp:826
void EvWindowPosChanged(const WINDOWPOS &windowPos)
Handles WM_WINDOWPOSCHANGED to make sure that the dockable client gets a chance to do final layout.
Definition docking.cpp:763
void GetRect(TRect &) override
Gets this dockable's screen rect.
Definition docking.cpp:901
void EvGetMinMaxInfo(MINMAXINFO &info)
Definition docking.cpp:813
void Layout(TAbsLocation, TSize *=nullptr) override
Forwards the layout message over to the dockable object.
Definition docking.cpp:910
void DockableMove(TDockable &, const TPoint *topLeft, TRelPosition, TDockable *relDockable) override
Overriden TDockingSlip virtual.
Definition docking.cpp:856
void EvClose()
When closing the floating slip, removes any dockable first so that it is not destroyed.
Definition docking.cpp:640
bool EvSizing(uint side, TRect &rect)
Handles the Windows 4.0 message for the best resize user feedback.
Definition docking.cpp:653
void DockableRemoved(const TRect &) override
Overriden TDockingSlip virtual.
Definition docking.cpp:868
void EvLButtonDown(uint hitTest, const TPoint &point)
Handles lbutton down bubbled up from the client to begin a dockable drag operation.
Definition docking.cpp:617
auto GetWindow() -> TWindow *override
Returns the TWindow part of this dockable object.
Definition docking.cpp:935
auto GetLocation() const -> TAbsLocation override
Returns the location of the object.
Definition docking.cpp:954
TFont derived from TGdiObject provides constructors for creating font objects from explicit informati...
Definition gdiobjec.h:296
virtual TWindow * GetClientWindow()
Returns a pointer to the client window.
Definition framewin.cpp:591
virtual TWindow * SetClientWindow(TWindow *clientWnd)
Sets the client window to the specified window.
Definition framewin.cpp:603
TGadget is the base class for the following derived gadget classes:
Definition gadget.h:120
TGadget * GadgetFromPoint(const TPoint &point) const
Returns the gadget that a given window-relative point is in, or 0 if none is found.
Definition gadgetli.cpp:42
TGadget * GadgetWithId(int id) const
Returns the gadget with a given ID, or 0 if none is found.
Definition gadgetli.cpp:56
TGadget * FirstGadget() const
Returns the first gadget of the list.
Definition gadgetwi.h:400
Derived from TWindow, TGadgetWindow maintains a list of tiled gadgets for a window and lets you dynam...
Definition gadgetwi.h:122
void Insert(TGadget &, TPlacement=After, TGadget *sibling=nullptr) override
Inserts a gadget before or after a sibling gadget (TPlacement).
static uint GetFlatStyle()
Returns the flat style.
Definition gadgetwi.h:459
@ FlatStandard
Flat style IE 3.0 - base style.
Definition gadgetwi.h:194
void EvLButtonDown(uint modKeys, const TPoint &point)
Responds to a left button-down mouse message by forwarding the event to the gadget (if it is enabled)...
TMargins & GetMargins()
Definition gadgetwi.h:481
virtual void GetDesiredSize(TSize &size)
Get the desired size for this gadget window by performing a trial layout of the gadgets without touch...
Definition gadgetwi.cpp:380
auto GetTooltip() const -> TTooltip *override
Returns Tooltip.
Definition gadgetwi.h:430
void SetRectangularDimensions(int width, int height, int rowMargin=-1)
Sets the maximum width for each row used for rectangular layout.
Definition gadgetwi.cpp:542
void SetShrinkWrap(bool shrinkWrapWidth, bool shrinkWrapHeight)
Sets the width and height of the data members.
Definition gadgetwi.cpp:250
virtual void SetDirection(TTileDirection direction)
Sets the horizontal or vertical orientation of the gadgets.
Definition gadgetwi.cpp:449
virtual void LayoutSession()
LayoutSession is typically called when a change occurs in the size of the margins or gadgets,...
Definition gadgetwi.cpp:357
TTileDirection
Enumeration describing how gadgets should be laid out within the gadget window.
Definition gadgetwi.h:130
@ Vertical
Arrange gadgets in a column.
Definition gadgetwi.h:132
@ Rectangular
Arrange gadgets in rows and columns (2-D grid)
Definition gadgetwi.h:133
@ Horizontal
Arrange gadgets in a row.
Definition gadgetwi.h:131
TTileDirection GetDirection() const
Returns the direction of tiling for this gadget window.
Definition gadgetwi.h:416
THarbor is the object that holds all the docking slips.
Definition docking.h:298
TDockable * DragDockable
Definition docking.h:361
void Remove(TDockable &dockable)
Remove a dockable from the harbor.
Definition docking.cpp:2570
TEdgeSlip * SlipLeft
Definition docking.h:355
TRect SlipRR
Definition docking.h:375
TRelPosition GetSlipPosition(TAbsLocation location)
Returns the default docking relative position for a given slip location.
Definition docking.cpp:2164
void EvLButtonDblClk(uint modKeys, const TPoint &point)
Handles the left button double click and forwards the message to the dockable window.
Definition docking.cpp:2429
TWindowDC * DragDC
Definition docking.h:362
TDockingSlip * Insert(TDockable &dockable, TAbsLocation location, const TPoint *where=0, TRelPosition position=rpNone, TDockable *relativeTo=0)
Dockable window insertion.
Definition docking.cpp:2451
TEdgeSlip * SlipRight
Definition docking.h:357
TSize DragNSize
Size of dockable when a natural shape.
Definition docking.h:368
TDecoratedFrame & DecFrame
Definition docking.h:350
TRect DragFrame
Definition docking.h:365
void Move(TDockable &dockable, TAbsLocation location, const TPoint *where=0, TRelPosition position=rpNone, TDockable *relativeTo=0)
Move a dockable from one slip to another, programatically.
Definition docking.cpp:2532
TRect SlipBR
Definition docking.h:373
TAbsLocation DragSlipLoc
Definition docking.h:364
TEdgeSlip * SlipBottom
Definition docking.h:356
void EvLButtonUp(uint modKeys, const TPoint &point)
Handles mouse up to drop a dockable window being dragged.
Definition docking.cpp:2383
TSize DragVSize
Size of dockable when vertical.
Definition docking.h:366
void EvMouseMove(uint modKeys, const TPoint &point)
Handles MouseMove to perform dockable dragging if a drag is in progress.
Definition docking.cpp:2314
TPoint DragAnchor
Definition docking.h:369
TSize DragHSize
Size of dockable when horizontal.
Definition docking.h:367
TRect SlipTR
Definition docking.h:372
TRect SlipLR
Definition docking.h:374
virtual TEdgeSlip * ConstructEdgeSlip(TDecoratedFrame &df, TAbsLocation location)
Creates an edge slip at a location.
Definition docking.cpp:2093
virtual TFloatingSlip * ConstructFloatingSlip(TDecoratedFrame &df, int x, int y, TWindow *dockableWindow)
Constructs a floating slip with a particular window at a location.
Definition docking.cpp:2102
TDockingSlip * DragNotificatee
Slip notified on drag operations.
Definition docking.h:370
~THarbor() override
Destructor.
Definition docking.cpp:2084
TEdgeSlip * SlipTop
Definition docking.h:354
void SetEdgeSlip(TAbsLocation location, TEdgeSlip *slip)
Sets a new edge slip for a given location.
Definition docking.cpp:2135
TAbsLocation DragOrgSlipLoc
Original slip location on mouseDown.
Definition docking.h:363
bool DockDraggingBegin(TDockable &dockable, const TPoint &pt, TAbsLocation location, TDockingSlip *dockingNotify=0)
Called by docking slips.
Definition docking.cpp:2247
TEdgeSlip * GetEdgeSlip(TAbsLocation location)
Returns the slip at the location.
Definition docking.cpp:2111
Derived from TBrush, THatch8x8Brush defines a small, 8x8, monochrome, configurable hatch brush.
Definition gdiobjec.h:250
When specifying the layout metrics for a window, four layout constraints are needed.
Definition layoutwi.h:54
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:75
TPoint is a support class, derived from tagPOINT.
Definition geometry.h:87
An instance of TProfile encapsulates a setting within a system file, often referred to as a profile o...
Definition profile.h:44
TRect is a mathematical class derived from tagRect.
Definition geometry.h:308
void Set(int _left, int _top, int _right, int _bottom)
Repositions and resizes this rectangle to the given values.
Definition geometry.h:1087
const TPoint & TopLeft() const
Returns the upperleft point.
Definition geometry.h:983
TRect & MoveTo(int x, int y)
Moves the upper left corner of the rectangle to a new location and maintains the current dimension.
Definition geometry.h:1371
Derived from TWindowDC, TScreenDC is a DC class that provides direct access to the screen bitmap.
Definition dc.h:610
The tagSIZE struct is defined as.
Definition geometry.h:234
TTooltip encapsulates a tooltip window - i.e.
Definition tooltip.h:175
Assists in drawing borders of many styles.
Definition uihelper.h:270
@ EdgeEtched
Outer sunken, inner raised.
Definition uihelper.h:324
void Paint(TDC &dc) const
Paints this UIBorder object onto a given device context.
Definition uiborder.cpp:112
static const TUIMetric CyFixedFrame
Definition uimetric.h:42
static const TUIMetric CxBorder
Definition uimetric.h:39
static const TUIMetric CySizeFrame
Definition uimetric.h:67
static const TUIMetric CxFixedFrame
Definition uimetric.h:41
static const TUIMetric CxSizeFrame
Definition uimetric.h:66
Derived from TDC, TWindowDC is a device context (DC) class that provides access to the entire area ow...
Definition dc.h:588
TWindow, derived from TEventHandler and TStreamableBase, provides window-specific behavior and encaps...
Definition window.h:414
bool EvEraseBkgnd(HDC)
Handler for WM_ERASEBKGND.
Definition window.cpp:1924
static TPoint GetCursorPos()
Definition window.h:1212
static void AdjustWindowRectEx(TRect &rect, uint32 style, bool menu, uint32 exStyle)
Calculates the size of a window rectangle that has an extended style.
Definition window.h:2296
bool SetCursor(TModule *module, TResId resId)
Sets the mouse cursor for the window, loading the given resId from the given module.
Definition window.cpp:3766
HWND SetCapture()
Sets the mouse capture to the current window.
Definition window.h:2121
HWND ChildWindowFromPoint(const TPoint &point) const
Determines which of the child windows contains the point specified in TPoint.
Definition window.h:2238
void EvNCLButtonDown(uint codeHitTest, const TPoint &)
The default message handler for WM_NCLBUTTONDOWN.
Definition window.h:3883
void EvLButtonUp(uint modKeys, const TPoint &point)
The default message handler for WM_LBUTTONUP.
Definition window.h:3792
static HWND GetCapture()
Returns the handle of the window that has captured the mouse.
Definition window.h:2112
bool EvWindowPosChanging(WINDOWPOS &)
The default message handler for WM_WINDOWPOSCHANGING.
Definition window.h:4212
void SetBkgndColor(TColor color, bool shouldUpdate=true)
Sets the background color for the window.
Definition window.h:1925
TWindow * GetLastChild()
Returns a pointer to the last child window in the interface object's child list.
Definition window.h:1776
void EvClose()
The default response to a WM_CLOSE message is to call CloseWindow() and then have the window deleted ...
Definition window.cpp:2828
bool SetWindowPos(HWND hWndInsertAfter, const TRect &rect, uint flags)
Changes the size of the window pointed to by rect.
Definition window.h:2809
virtual void EvCommandEnable(TCommandEnabler &ce)
Called by WindowProc to handle WM_COMMAND_ENABLE messages, EvCommandEnable calls the CmXxxx command-h...
Definition window.cpp:1135
TWindow * GetParent() const
Retrieves the OWL object of the parent window. If none exists, returns 0.
Definition window.h:2013
TWindow * GetWindowPtr(HWND hWnd) const
Calls TApplication:GetWindowPtr on the application associated with this window.
Definition window.h:3567
TRect GetWindowRect() const
Gets the screen coordinates of the window's rectangle.
Definition window.h:2257
TPoint MapClientToScreen(const TPoint &p) const
Function-style version of ClientToScreen.
Definition window.h:838
void SetFlag(uint mask)
Sets the specified TWindow wfXxxx constant flags (for example wfAlias, wfTransfer,...
Definition window.h:1783
TWindow * GetParentO() const
Return the OWL's parent for this window.
Definition window.h:2006
static void ReleaseCapture()
Releases the mouse capture from this window.
Definition window.h:2130
void MapWindowPoints(HWND hWndTo, TPoint *pts, int count) const
Maps a set of points in one window to a relative set of points in another window.
Definition window.h:2206
bool IsIconic() const
Returns true if window is iconic or minimized.
Definition window.h:2628
void GetWindowRect(TRect &rect) const
Gets the screen coordinates of the window's rectangle and copies them into rect.
Definition window.cpp:3609
TResult HandleMessage(TMsgId, TParam1=0, TParam2=0)
Dispatches the given message using the response table.
Definition window.cpp:1392
void EvLButtonDown(uint modKeys, const TPoint &point)
Response method for an incoming WM_LBUTTONDOWN message.
Definition window.cpp:2101
void EvWindowPosChanged(const WINDOWPOS &windowPos)
The default message handler for WM_WINDOWPOSCHANGED.
Definition window.h:4205
TResult DefaultProcessing()
Handles default processing of events, which includes continued processing of menu/accelerators comman...
Definition window.cpp:852
TRect GetClientRect() const
Gets the coordinates of the window's client area (the area in a window you can use for drawing).
Definition window.h:2217
virtual TResult EvCommand(uint id, HWND hWndCtl, uint notifyCode)
WindowProc calls EvCommand to handle WM_COMMAND messages.
Definition window.cpp:999
void ClearFlag(uint mask)
Clears the specified TWindow wfXxxx constant flags (for example wfAlias, wfTransfer,...
Definition window.h:1790
void ScreenToClient(TPoint &point) const
Uses the screen coordinates specified in point to calculate the client window's coordinates and then ...
Definition window.h:2192
void EvMouseMove(uint modKeys, const TPoint &point)
The default message handler for WM_MOUSEMOVE.
Definition window.h:3841
virtual bool ShowWindow(int cmdShow)
Displays this TWindow in a given state.
Definition window.cpp:3713
TResult SendMessage(TMsgId, TParam1=0, TParam2=0) const
Sends a message (msg) to a specified window or windows.
Definition window.cpp:3288
virtual void SetupWindow()
Performs setup following creation of an associated MS-Windows window.
Definition window.cpp:2575
void EvLButtonDblClk(uint modKeys, const TPoint &point)
The default message handler for WM_LBUTTONDBLCLK.
Definition window.h:3785
bool IsFlagSet(uint mask)
Returns the state of the bit flag in Attr.Flags whose mask is supplied.
Definition window.h:1797
uint EvNCCalcSize(bool calcValidRects, NCCALCSIZE_PARAMS &)
The default message handler for WM_NCCALCSIZE.
Definition window.h:3855
bool EvSetCursor(HWND hWndCursor, uint codeHitTest, TMsgId mouseMsg)
Response method for an incoming WM_SETCURSOR message.
Definition window.cpp:2081
void GetClientRect(TRect &rect) const
Gets the coordinates of the window's client area and then copies them into the object referred to by ...
Definition window.cpp:3624
TWindow * GetFirstChild()
Returns a pointer to the first child window, which is the first window created in the interface objec...
Definition window.h:1770
HWND THandle
TWindow encapsulates an HWND.
Definition window.h:418
HWND GetHandle() const
Returns the handle of the window.
Definition window.h:2020
Definition of class TControlBar.
#define _T(x)
Definition cygwin.h:51
#define WM_OWLWINDOWDOCKED
Notify window it was [un]docked/reparented.
Definition dispatch.h:4116
#define WM_OWLSLIPDBLCLK
Notify parent of user dblclick of edge slip.
Definition dispatch.h:4115
TDockable classes: TDockableGadgetWindow & TDockableControlBar TDockingSlip classes: TFloatingSlip & ...
#define DEFINE_RESPONSE_TABLE1(cls, base)
Macro to define a response table for a class with one base.
Definition eventhan.h:492
#define IDG_FLATHANDLE
The ID for a flat bar handle.
Definition gadget.h:37
TRelPosition
General use 2-D rectangular relative position enum.
Definition docking.h:43
TGridType
Definition docking.h:227
@ rpNone
No location specified.
Definition docking.h:44
@ rpAbove
Refers to top edge of frame.
Definition docking.h:45
@ rpBelow
Refers to bottom edge of frame.
Definition docking.h:46
@ rpRightOf
Refers to left edge of frame.
Definition docking.h:47
@ rpLeftOf
Refers to right edge of frame.
Definition docking.h:48
@ XCoord
Left & right edge have X coords parallel vertically.
Definition docking.h:229
@ YCoord
Grid type corresponds with Location:
Definition docking.h:228
TAbsLocation
General use absolute 2-D rectangular location enum.
Definition geometry.h:62
@ alTop
Refers to top edge of frame.
Definition geometry.h:64
@ alRight
Refers to right edge of frame.
Definition geometry.h:67
@ alBottom
Refers to bottom edge of frame.
Definition geometry.h:65
@ alLeft
Refers to left edge of frame.
Definition geometry.h:66
@ alNone
No location specified.
Definition geometry.h:63
@ wfShrinkToClient
Shrink a frame window to its client's size.
Definition window.h:62
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
EV_WM_NCCALCSIZE
Definition docking.cpp:963
EV_WM_OWLWINDOWDOCKED
Definition docking.cpp:98
EV_WM_LBUTTONUP
Definition docking.cpp:2056
EV_WM_SETCURSOR
Definition docking.cpp:99
UINT TMsgId
Message ID type.
Definition dispatch.h:53
EV_WM_GETMINMAXINFO
Definition docking.cpp:548
EV_WM_SETTINGCHANGE
Definition docking.cpp:547
EV_WM_LBUTTONDBLCLK
Definition docking.cpp:962
EV_WM_MOUSEMOVE
Definition docking.cpp:2054
uint32 MkUint32(uint16 lo, uint16 hi)
Definition defs.h:261
unsigned long uint32
Definition number.h:34
LPARAM TParam2
Second parameter type.
Definition dispatch.h:55
signed short int16
Definition number.h:29
WPARAM TParam1
First parameter type.
Definition dispatch.h:54
TDispatch< WM_PARENTNOTIFY >::TArgs TParentNotify
Alias for convenience.
Definition dispatch.h:2894
TParam2 MkParam2(const T1 &lo, const T2 &hi)
Definition dispatch.h:65
OWL_DIAGINFO
Definition animctrl.cpp:14
EV_WM_PARENTNOTIFY
Definition docking.cpp:966
EV_WM_NCPAINT
Definition docking.cpp:964
EV_WM_WINDOWPOSCHANGING
Definition docking.cpp:545
END_RESPONSE_TABLE
Definition button.cpp:26
EV_WM_NCLBUTTONDOWN
Definition docking.cpp:541
LRESULT TResult
Result type.
Definition dispatch.h:52
EV_WM_WINDOWPOSCHANGED
Definition docking.cpp:546
unsigned int uint
Definition number.h:25
EV_WM_LBUTTONDOWN
Definition checklst.cpp:195
EV_WM_SIZING
Definition docking.cpp:544
EV_WM_ERASEBKGND
Definition docking.cpp:965
EV_WM_CLOSE
Definition commdial.cpp:23
#define OWL_INI
Definition defs.h:170
#define TYPESAFE_DOWNCAST(object, toClass)
Definition defs.h:269
Definition of TProfile class.
TUnits Units
Definition gadget.h:57
Definition of container classes used and made available by OWL.
Definition of the TTooltip class and helper objects.
Definition of the UI Helper Classes: TUIHandle, TUIBorder, TUIFace, TUIPart.
Definition of TUIMetric, a UI metrics provider class.
#define WS_EX_TOOLWINDOW
Definition wsysinc.h:27
#define WS_EX_WINDOWEDGE
Definition wsysinc.h:30