OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
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#include <unordered_map>
28
29using namespace std;
30
31namespace owl {
32
33//
34// Fillin missing defines for some configurations
35//
36#if !defined(WM_SIZING)
37# define WM_SIZING 0x0214
38#endif
39#if !defined(DS_SETFOREGROUND)
40# define DS_SETFOREGROUND 0x200L // not in win3.1
41#endif
42
43//
44// Diagnostic group for docking
45//
48
49
51
52//----------------------------------------------------------------------------
53
54//
55/// This constructor creates a dockable gadget window and sets the appropriate
56/// styles for the window.
57//
60 TFont* font,
61 TModule* module)
62:
63 TGadgetWindow(parent, direction, font, module),
64 TDockable(),
65 Cursor(nullptr)
66{
67#if 0
68 Attr.Style |= WS_BORDER; // Add in border for boundries between dockables
69#else
70 Attr.Style &= ~WS_BORDER; // Normally no borders
71#endif
72 Attr.Style |= WS_CLIPSIBLINGS;
73
74 // Always shrink wrapped when dockable since slip fills out docking area
75 //
76 SetShrinkWrap(true, true);
77}
78
79//
80//
81//
86
87
93
94//
95//
96//
102
103
104/// Inserts/deletes FlatBar Grip.
105void
107{
110 if(dir == Rectangular){
111 delete Cursor;
112 Cursor = 0;
113 }
114 else if(!GadgetWithId(IDG_FLATHANDLE)){
116 if(gadget)
118
119 // set cursor
120 if(dir == Horizontal)
121 Cursor = new TCursor(0, IDC_SIZEWE);
122 else
123 Cursor = new TCursor(0, IDC_SIZENS);
124
126 }
127 else{
128 if(GetDirection() != dir){
129 delete Cursor;
130 if(dir == Horizontal)
131 Cursor = new TCursor(0, IDC_SIZEWE);
132 else
133 Cursor = new TCursor(0, IDC_SIZENS);
134 }
136 }
137 }
138 // if exist GridGadget
140 // set cursor
141 if(dir == Horizontal)
142 Cursor = new TCursor(0, IDC_SIZEWE);
143 else
144 Cursor = new TCursor(0, IDC_SIZENS);
145
147 }
148}
149
150//
151//
152//
153bool
155{
163 boundsRect.right = boundsRect.left+8;
165 }
166 else{
167 boundsRect.bottom = boundsRect.top+7;
169 }
170 if(boundsRect.Contains(point)){
172 return true;
173 }
174 }
176}
177
178//
179/// Finds out how big this dockable would be in a given location, and with a given
180/// optional size hint.
181//
182TSize
184{
186
187 // Save current settings to restore when done, since this is a info-request
188 // only function
189 //
191 int oldWidth = RowWidth;
192
193 // If rectangular, calcuate adjust size for surrounding parent frame window
194 //
195 TSize delta(0,0);
196 if (dir == Rectangular) {
197 // If we currently are in a floating slip, use that window to calc frame delta
198 //
199 TWindow* parent = GetParentO();
200 if (oldDir == Rectangular && parent && parent->GetHandle()) {
201 delta = parent->GetWindowRect().Size() - parent->GetClientRect().Size();
202 // In Win95, the bottom margin and the bottom sizing border are the
203 // same color and not separated by a hard border, so we 'kern' them
204 // together to match the size of the top margin.
205 //
207 int topM, leftM, bottomM, rightM;
209 delta.cy -= std::min(yt, bottomM);
210 }
211 // No floating parent yet. Calculate the delta based on assumed frame
212 // styles. (This rect is only used to size the drag frame anyway.)
213 //
214 else {
215 TRect winRect(0, 0, 0, 0);
219 delta = winRect.Size();
220 }
221 }
222
223 TSize sz(0, 0);
224 Direction = dir;
225
226 // Seek a vertical size if just a non-zero cy is given
227 //
228 if (dim && dim->cx == 0 && dim->cy != 0) {
229
230 int seekCy = dim->cy - delta.cy; // This is the height to shoot for
231
234
235 // Seek the row whose height is less than seekCy
236 ///CH: I really would like to have a better, non-iterative algorithm for
237 ///CH: this, but for now this works.
238 //
239 if (testSz.cy < seekCy) {
240 // Seek a taller row by successivly shrinking the width
241 //
242 while (1) {
243 int prevW = RowWidth;
244 sz = testSz;
245 RowWidth -= 5;
246 if (RowWidth <= 0) { // Limit reached. Give up
247 RowWidth = testSz.cx;
248 sz = testSz;
249 break;
250 }
252 if (seekCy < testSz.cy) { // Shrunk too far: use previous size
253 RowWidth = prevW;
254 break;
255 }
256 }
257 }
258 else if (testSz.cy > seekCy) {
259 // Seek a shorter row by successivly growing the width
260 //
261 while (1) {
262 int prevW = RowWidth;
263 sz = testSz;
264 RowWidth += 5;
265 if (RowWidth > 1000) { // CHNOTE: Limit reached. Give up
266 RowWidth = testSz.cx;
267 sz = testSz;
268 break;
269 }
271 if (seekCy > testSz.cy) {
272 RowWidth = prevW;
273 break;
274 }
275 }
276 }
277 else // seekCy == testSz.cy
278 sz = testSz;
279 }
280 // Change to a given horizontal size, or just the natural size for the
281 // direction
282 //
283 else {
284 if (dim) // Change the row width here because we are changing size.
285 RowWidth = dim->cx - delta.cx;
287 }
288
289 Direction = oldDir;
290 RowWidth = oldWidth;
291 sz += delta;
292
293 return sz;
294}
295
296//
297/// Gets this dockable's screen rectangle.
298//
299void
304
305//
306/// Returns a gadget window tile direction code, given a docking absolute location
307/// code.
308//
311{
312 switch(loc) {
313 case alTop:
314 case alBottom:
315 return Horizontal;
316 case alLeft:
317 case alRight:
318 return Vertical;
319 case alNone:
320 default:
321 return Rectangular;
322 }
323}
324
325//
326/// Causes this dockable to lay itself out vertically, horizontally, or
327/// rectangularly.
328//
329void
331{
333 if (GetDirection() != dir || dim) {
334 if (dim)
335 SetRectangularDimensions(dim->cx, dim->cy); // Sets RowWidth mostly
336
337 // Set the layout direction, which ends up invoking LayoutSession &
338 // SetWindowPos
339 //
341 }
342}
343
344//
345/// Returns true if the mouse click point is in a spot that should move this
346/// dockable around.
347//
348bool
350{
352 if (g)
353 // !CQ should also allow non-clickables to drag, like text!
354#if 1
355 return !g->IsVisible(); // Allow hidden gadgets to begin a drag; separators are hidden
356#else
357 return !g->GetEnabled(); // Allow disabled gadgets to begin a drag
358#endif
359
360 return true;
361}
362
363//
364/// Returns the TWindow part of this dockable object. In this case, it is just this
365/// window.
366//
367TWindow*
369{
370 return this;
371}
372
373//
374/// If the gadget window changes size when laying out a dockable gadget window, this
375/// function tells the dock about it so the dock can resize too.
376//
377void
379{
380 TSize sz;
381 GetDesiredSize(sz); // Find out how big we'd like to be
382
383 Attr.W = sz.cx; // This will allow LayoutSession to work as if
384 Attr.H = sz.cy; // we were the right size.
385
387
388 // If we are in a slip that has been created properly, then tell it to adjust
389 // to our new layout
390 //
391 if (GetParentO()) {
393 if (slip) {
394 // If this is a null-sized gadget window, hide our floating frame.
395 //
396 bool hideSlip = Attr.W == 0 || Attr.H == 0;
398
399 // Make sure the slip will adjust to our new size
400 //
402 if (!stc)
404 SetWindowPos(nullptr, 0, 0, Attr.W, Attr.H, SWP_NOACTIVATE | SWP_NOMOVE);
405 if (!stc)
407 }
408 // If we aren't in a slip (because we haven't been inserted yet) resize
409 // anyway.
410 //
411 else {
412 SetWindowPos(nullptr, 0, 0, Attr.W, Attr.H, SWP_NOACTIVATE | SWP_NOMOVE);
413 }
414 }
415}
416
417//
418/// Returns the harbor containing the dockable object.
419//
420THarbor*
422{
423 // If parent is a slip, return its harbor.
424 // If parent is the harbor (because the dockable is hidden), return the harbor.
425 //
426 if (!Parent)
427 return nullptr;
429 if (slip)
430 return slip->GetHarbor();
432 return harbor;
433}
434
435//
436/// Forwards event to slip to allow movement of gadget within the slip.
437//
438void
440{
441 TPoint pt = point;
443
444 // Forward the message to the parent, this is for the docking areas. To
445 // allow moving of the controlbars within the docking areas.
446 // !CQ Use OWL parent??? Or old hwnd parent?
447 //
448 TWindow* w = GetParentO();
449
450 // Check that we're parented to the right window. In OLE server situation,
451 // the toolbar could have been reparented to another HWND [i.e. container's
452 // window]
453 //
454 if (w && ::GetParent(*this) != w->GetHandle())
455 return;
456
457 // Forward to parent [which is a slip]
458 //
459 if (w && w->GetHandle()) {
460 TPoint p = MapWindowPoints(*w, point); // Transform to parent's coordinate system.
461 w->HandleMessage(WM_LBUTTONDOWN, modKeys, MkParam2(int16(p.x), int16(p.y)));
462 }
463
464 // At this point, our window may be in drag mode [i.e. being docked or
465 // undocked]. This means that the harbor has invoked 'SetCapture' which in
466 // turn implies that we won't see subsequent WM_MOUSEMOVE/WM_LBUTTONDOWN
467 // messages. This will leave the tooltip the impression [strong impression
468 // if I may add] that the mouse button never came up. The net side-effect
469 // will be that the tooltip will not activate until it sees an LBUTTONUP
470 // message. So to avoid this side-effect we fake an LBUTTONUP message here.
471 //
473 if (harbor && GetCapture() == *harbor)
474 {
476 if (tooltip && tooltip->IsWindow())
477 {
478 MSG msg;
479 msg.hwnd = *this;
480 msg.message = WM_LBUTTONUP;
481 msg.wParam = modKeys;
482 msg.lParam = MkUint32(int16(pt.x), int16(pt.y));
483 tooltip->RelayEvent(msg);
484 }
485 }
486}
487//----------------------------------------------------------------------------
488
492
493//
494/// Constructs a dockable control bar.
495//
498 TFont* font,
499 TModule* module)
500:
501 TDockableGadgetWindow(parent, direction, font, module)
502{
504 WantTooltip = true;
505
507}
508
509//
510//
511//
512void
514{
515 // !CQ Conrad's IDEOWL uses 6*Border,3*border & vice versa
516 if (GetDirection() == Horizontal) {
517 Margins.Left = Margins.Right = TUIMetric::CxSizeFrame + TUIMetric::CxFixedFrame;
518 Margins.Top = Margins.Bottom = TUIMetric::CySizeFrame;
519 }
520 else if(Direction == Vertical){
521 Margins.Left = Margins.Right = TUIMetric::CxSizeFrame;
522 Margins.Top = Margins.Bottom = TUIMetric::CySizeFrame + TUIMetric::CyFixedFrame;
523 }
524 else{
525 Margins.Left = Margins.Right = TUIMetric::CxSizeFrame;
526 Margins.Top = Margins.Bottom = TUIMetric::CySizeFrame;
527 }
528}
529
530//
531//
532//
533void
539
540
545 EV_WM_SIZING, // Win 4.0 message only.
551
552//
553/// Constructs a floating slip and sets the appropriate style for the window.
554//
556 int x, int y,
558 bool shrinkToClient,
559 int captionHeight,
560 bool popupPalette,
561 TModule* module)
562:
563 TFloatingFrame(parent, clientWnd->GetCaption(), nullptr/*clientWnd*/, shrinkToClient,
565
566{
567 SetDragFrame(false);
568
570 Attr.Style &= ~(WS_VISIBLE); // Create initially hidden, show later
571 Attr.Style |= WS_CLIPCHILDREN; // Dont womp on children
572 Attr.Style |= WS_BORDER | WS_THICKFRAME; // Sizeable frame to allow reshaping
573
574 // Let tiny caption recalc margin & border dimensions using new styles. Tiny
575 // caption will adjust these some more as needed.
576 //
577 EnableTinyCaption(TFloatingFrame::DefaultCaptionHeight, true);
578
579 // Calculate a real initial position, & an estimated size. May resize later
580 // when client has reshaped.
581 //
582 TRect winRect(x, y, x+clientWnd->GetWindowAttr().W, y+clientWnd->GetWindowAttr().H);
583 AdjustWindowRectEx(winRect, Attr.Style, false, Attr.ExStyle);
584
585#if 1
586 Attr.X = x; // Places this frame at given screen x,y
587 Attr.Y = y;
588#else
589 Attr.X = winRect.left; // Places client rect at given screen x,y
590 Attr.Y = winRect.top;
591#endif
592 Attr.W = winRect.Width();
593 Attr.H = winRect.Height();
594}
595
596//
597/// Handles lbutton down bubbled up from the client to begin a dockable drag
598/// operation.
599//
600void
602{
603 if (hitTest == HTCAPTION) {
604 // Call the dockable dragging setup function in Harbor, passing this
605 // window as the dragged dockable and as the docking slip too
606 //
607 if (Harbor && Harbor->DockDraggingBegin(*this, point, alNone, this))
608 return;
609 }
611}
612
613//
614/// Handles lbutton down bubbled up from the client to begin a dockable drag
615/// operation.
616//
617void
619{
620 // Is the mouseDown in a area where we can move the docked window?
621 //
624
625 TPoint childPt = MapWindowPoints(*cw, point); // Transform to client window's coordinate system.
626
627 if (d && d->ShouldBeginDrag(childPt)) {
629 if (Harbor && Harbor->DockDraggingBegin(*this, p, alNone, this))
630 return; // Successfully started
631 }
633}
634
635//
636/// When closing the floating slip, removes any dockable first so that it is not
637/// destroyed. Dockables are owned by the harbor, not the slip, and must not be
638/// destroyed when the slip is destroyed.
639//
640void
642{
644 if (dd)
645 Harbor->Remove(*dd); // Will cause a close in DockableRemoved()
646 else
648}
649
650//
651/// Handles the Windows 4.0 message for the best resize user feedback.
652//
653bool
655{
656
657 // Look for size changes & make them track the dockable
658 //
660 if (w) {
662 if (dockable) {
663 TSize trackSize(rect.Size());
664 switch (side) {
665 case WMSZ_BOTTOM:
666 case WMSZ_TOP:
667 trackSize.cx = 0;
668 break;
669 case WMSZ_LEFT:
670 case WMSZ_RIGHT:
671 trackSize.cy = 0;
672 break;
673 }
674 TSize dsz = dockable->ComputeSize(alNone, &trackSize);
675
676 // Center the fixed axis
677 //
678 switch (side) {
679 case WMSZ_BOTTOM:
680 case WMSZ_TOP:
681 rect.left = rect.left + (rect.Width() - dsz.cx)/2;
682 break;
683 case WMSZ_LEFT:
684 case WMSZ_RIGHT:
685 rect.top = rect.top + (rect.Height() - dsz.cy)/2;
686 break;
687 }
688
689 // Change the window size, keeping it pinned on the opposite corner
690 //
691 switch (side) {
692 case WMSZ_TOP:
693 case WMSZ_TOPRIGHT:
694 rect.top = rect.bottom - dsz.cy;
695 rect.right = rect.left + dsz.cx;
696 break;
697 case WMSZ_TOPLEFT:
698 rect.left = rect.right - dsz.cx;
699 rect.top = rect.bottom - dsz.cy;
700 break;
701 case WMSZ_BOTTOMLEFT:
702 case WMSZ_LEFT:
703 rect.left = rect.right - dsz.cx;
704 rect.bottom = rect.top + dsz.cy;
705 break;
706 case WMSZ_BOTTOM:
707 case WMSZ_BOTTOMRIGHT:
708 case WMSZ_RIGHT:
709 rect.right = rect.left + dsz.cx;
710 rect.bottom = rect.top + dsz.cy;
711 break;
712 }
713 }
714 }
715
716 return true;
717}
718
719//
720/// Handles WM_WINDOWPOSCHANGING to make sure that the frame is properly constrained
721/// by the dimensions of the dockable client.
722//
723bool
725{
727
728 // Look for size changes & make them track the dockable
729 //
730 if (!(windowPos.flags&SWP_NOSIZE)) {
732 if (w) {
734 if (dockable) {
735// !CQ Shouldn't we adjust .cx by our frame thickness to get client width?
736// !CQ Maybe keep Delta around for these client<->frame size calculations...
737/// TRect cr(0,0,0,0);
738/// AdjustWindowRectEx(cr, Attr.Style, false, Attr.ExStyle);
739 TSize ts(windowPos.cx, 0);
740 TSize dsz = dockable->ComputeSize(alNone, &ts);
741
742 // Center the non-sizing axis
743 //
744 if (!(windowPos.flags&SWP_NOMOVE)) {
745/// if (sizing horizontally)
746 windowPos.y = windowPos.y + (windowPos.cy - dsz.cy)/2;
747/// else
748/// windowPos.x = windowPos.x + (windowpos.cx - dsz.cx)/2;
749 }
750 windowPos.cx = dsz.cx;
751 windowPos.cy = dsz.cy;
752 }
753 }
754 }
755 windowPos.flags |= SWP_NOACTIVATE; // Not very effective, but worth a try
756 return false;
757}
758
759//
760/// Handles WM_WINDOWPOSCHANGED to make sure that the dockable client gets a chance
761/// to do final layout.
762//
763void
765{
767
768 if (!(windowPos.flags&SWP_NOSIZE)) {
770 if (w) {
772 if (dockable) {
773/// TRect cr(0,0,0,0);
774/// AdjustWindowRectEx(cr, Attr.Style, false, Attr.ExStyle);
775 TSize ts(windowPos.cx, 0);
776 TSize dsz = dockable->ComputeSize(alNone, &ts);
777
778 dockable->Layout(alNone, &dsz);
779 }
780 }
781 }
782}
783//
784/// Event handler for the .INI file changed message. The window may have resized
785/// because the user has changed the caption size.
786//
787void
789
790{
792
793 // Resize, since our sizing borders may have changed size
794 //
795 if (w) {
796 TRect newWinRect = w->GetWindowRect();
797 AdjustWindowRectEx(newWinRect, Attr.Style, false, Attr.ExStyle);
798
800
801 if (winRect.Height() != newWinRect.Height() ||
802 winRect.Width() != newWinRect.Width()) {
804 }
805 }
806}
807
808//
809// Respond to WM_GETMINMAXINFO messages to ensure that the minTrackSize
810// used by Windows is not greater than the size would be for a vertical
811// floating control bar.
812//
813void
815{
816 TSize sz(0,0);
817 ComputeSize( alLeft, &sz );
818 info.ptMinTrackSize.x = sz.cx;
819 info.ptMinTrackSize.y = sz.cy;
820}
821
822//
823/// Overriden TDockingSlip virtual. Called by mouseup handler after a dockable is
824/// dropped into this docking window.
825//
826void
828 const TPoint* /*topLeft*/,
829 TRelPosition /*position*/, TDockable* /*relDockable*/)
830
831{
832 dockable.Layout(alNone); // No specific dimensions suggested
833 SetClientWindow(dockable.GetWindow()); // Set dockable as client & resize
834
835 // Retrieve window object of dockable
836 //
837 TWindow* dockableWindow = dockable.GetWindow();
839
840 // Let window know it was docked [well, undocked]
841 //
842#ifdef UNIX
843 if (dockableWindow->IsWindow()) //?????????????????????
845 TParam2((TDockingSlip*)this));
846#else
848 TParam2((TDockingSlip*)this));
849#endif
850}
851
852//
853/// Overriden TDockingSlip virtual. Called by lbutton up handler after a drag within
854/// this docking window. This floating slip only moves itself.
855//
856void
858 TRelPosition /*position*/, TDockable* /*relDockable*/)
859{
860 if (topLeft)
861 SetWindowPos(nullptr, topLeft->x, topLeft->y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE);
862}
863
864//
865/// Overriden TDockingSlip virtual. Called by lbutton up handler after a dockable
866/// has been removed from this docking slip.
867//
868void
870{
871 // Clear client window
872 //
873 SetClientWindow(nullptr);
874
875// !BB CloseWindow has the side-effect of leaving things around - i.e.
876// !BB window object is not condemned... Can be expensive after a few
877// !BB floating slips.
878// !BB
879// !BB CloseWindow();
881}
882
883//
884/// Forward the first four TDockable virtuals to the client dockable.
885//
886TSize
888{
890 if (w) {
892 if (dockable)
893 return dockable->ComputeSize(loc, dim);
894 }
895 return TSize(0, 0);
896}
897
898//
899/// Gets this dockable's screen rect.
900//
901void
906
907//
908/// Forwards the layout message over to the dockable object.
909//
910void
912{
914 if (w) {
916 if (dockable)
917 dockable->Layout(loc, dim); // !CQ adjust dim by our frame thickness?
918 }
919 CHECK(w);
920}
921
922//
923/// A given mouse down should never begin a drag for this dockable.
924//
925bool
927{
928 return false;
929}
930
931//
932/// Returns the TWindow part of this dockable object. In this case it is actually
933/// the client window.
934//
935TWindow*
941
942//
943/// Returns the associated harbor.
944//
945THarbor*
947{
948 return Harbor;
949}
950
951//
952/// Returns the location of the object.
953//
956{
957 return alNone;
958}
959
960
970
971//
972/// Constructs an edge slip, and sets the approriate styles for the window.
973//
975:
976 TWindow(&parent, _T("EdgeSlip"), module),
977 Location(location),
978 GridType(Location == alTop || Location == alBottom ? YCoord : XCoord)
979{
980#if defined(__TRACE) || defined(__WARN)
981 // Make slip dark blue for debugging purposes in diagnostic build
982 //
983 TProfile iniFile(_T("Diagnostics"), _T(OWL_INI));
984
985 bool useDiagColor = iniFile.GetInt(_T("DiagToolbarBorders")) != 0;
986
987 if (useDiagColor)
988 SetBkgndColor(TColor(0, 0, 128));
989 else
990#endif
991
993
995}
996
997//
998// Type of decoration
999//
1000struct TEachDecoration {
1001 TWindow* Window;
1002 int Top; // or Left if XCoord
1003 int Bottom; // or Right if XCoord
1004
1005 TEachDecoration(TWindow*, TGridType);
1006 TEachDecoration(int Top, int Bottom, TWindow* w);
1007
1008 bool operator <(const TEachDecoration& other) const
1009 {return Top < other.Top;}
1010};
1011
1012//
1013// Create a decoration from the grid.
1014//
1015TEachDecoration::TEachDecoration(TWindow* w, TGridType gridType)
1016:
1017 Window(w)
1018{
1019 TRect rect = w->GetWindowRect();
1020 if (gridType == YCoord) {
1021 Top = rect.top;
1022 Bottom = rect.bottom;
1023 }
1024 else {
1025 Top = rect.left;
1026 Bottom = rect.right;
1027 }
1028}
1029
1030//
1031// Create the decoration from a specific location.
1032//
1033TEachDecoration::TEachDecoration(int top, int bottom, TWindow* w)
1034:
1035 Window(w),
1036 Top(top),
1037 Bottom(bottom)
1038{
1039}
1040
1041namespace
1042{
1043
1044template <class TDecoration>
1046{
1048 for (TWindow* w = s.GetFirstChild(); w; w = (w == s.GetLastChild()) ? nullptr : w->Next())
1050 sort(v.begin(), v.end());
1051 return v;
1052}
1053
1054} // namespace
1055
1056//
1057/// Ensures that all decorations in the docking window are abutted against each
1058/// other (both horizontally and vertically); there should be no gaping holes.
1059//
1060void
1062{
1063 TWindow::SetupWindow(); // Create all children.
1064
1066
1067 // Look for any gaping holes between the dockable windows and collapse them.
1068 // Normally, this doesn't occur unless the to be created size is different
1069 // from the actual created size of a gadget. This, currently, only occurs
1070 // for TControlGadgets where the gadget is a combobox the created size
1071 // specifies the editclass area and the drop-down area, however, the window
1072 // rect (when the GetHandle() is valid) is just the editclass area.
1073 //
1074 int diff = 0;
1075 int startWindowChange = -1;
1076 int rowHeight = 0;
1077 for (size_t i = 1; i < decoList.size(); ++i) {
1078 // Are the two decorations we're going to look at on the same vertical?
1079 //
1080 if (decoList[i-1].Top != decoList[i].Top) {
1081 // No, so compute possible difference.
1082 //
1083 if (decoList[i-1].Bottom+diff != decoList[i].Top+diff) {
1084 // Remember the first window which is adjusted, we'll want to delay the
1085 // SetWindowPos until all windows from this point to the end have been
1086 // completely adjusted.
1087 //
1088 if (startWindowChange == -1)
1089 startWindowChange = static_cast<int>(i);
1090
1091 // Found a spot. Compute the offset.
1092 //
1093 diff += decoList[i-1].Top + rowHeight - decoList[i].Top;
1094 }
1095 rowHeight = decoList[i].Bottom - decoList[i].Top;
1096 }
1097 else {
1098 rowHeight = std::max(rowHeight, decoList[i].Bottom - decoList[i].Top);
1099 }
1100 if (diff) {
1101 TEachDecoration& decoItem = decoList[i];
1102 decoItem.Top += diff;
1103 decoItem.Bottom += diff;
1104 }
1105 }
1106
1107 // Re-adjust all windows which have changed location.
1108 //
1109 if (startWindowChange != -1) {
1110 for (size_t i = startWindowChange; i < decoList.size(); ++i) {
1111 TEachDecoration& decoItem = decoList[i];
1112 TRect r;
1113 decoItem.Window->GetWindowRect(r);
1114
1115 TPoint pt(r.left, r.top);
1116 if (GridType == YCoord)
1117 pt.y = decoItem.Top;
1118 else
1119 pt.x = decoItem.Top;
1120
1121 // Map from global to local coord (the parent's coordinate space).
1122 //
1123 ::MapWindowPoints(nullptr, *this, (TPoint*)&pt, 1);
1124 decoItem.Window->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1126 i++;
1127 }
1128 }
1129
1130 // Make sure that our size is updated
1131 //
1132 ReLayout(true);
1133}
1134
1135//
1136/// Changes the reciever to be the framewindow, not the docking window. The receiver
1137/// window is normally set up in Activate upon the creation of TButtonGadgetEnabler.
1138//
1139void
1141{
1142 if (GetParentO()) {
1143 // Already being processed?
1144 //
1145 if (!commandEnabler.IsReceiver(GetParentO()->GetHandle())) {
1146 // No, so forward it up to our parent
1147 //
1148 commandEnabler.SetReceiver(GetParentO()->GetHandle());
1150 }
1151 }
1152}
1153
1154//
1155/// Forward command messages to the parent.
1156//
1157/// Changes the receiver to be the framewindow, not the docking window. The receiver
1158/// window is normally set up in Activate upon the creation of TButtonGadgetEnabler.
1159//
1160TResult
1162{
1163 TRACEX(OwlCmd, 1, "TEdgeSlip::EvCommand - id(" << id << "), ctl(" <<\
1164 static_cast<void*>(hWndCtl) << "), code(" << notifyCode << ")");
1165
1166 if (notifyCode == 0 && GetParentO())
1167 return GetParentO()->EvCommand(id, hWndCtl, notifyCode);
1168
1170}
1171
1172//
1173/// Forwards the left button down message to the dockable object.
1174//
1175void
1177{
1179
1180 // Only allow immediate children of the docking window to be clicked on.
1181 //
1182 if (cw && cw->GetParentO() == this) {
1183 // Is the mouseDown in a area where we can move the docked window?
1184 //
1187 if (d && d->ShouldBeginDrag(childPt)) {
1189 if (Harbor && Harbor->DockDraggingBegin(*d, p, Location, this)) {
1190 return; // Successfully started
1191 }
1192 }
1193 }
1195}
1196
1197//
1198/// Handles WM_LBUTONDBLCLICK to tell the frame to edit a toolbar.
1199//
1200void
1205
1206//
1207/// Returns the size of the client area, leaving room for the etched separators.
1208//
1209uint
1211{
1213 if (IsIconic())
1214 return ret;
1215
1216 // Only add in space if this slip is not shrunk to nothing
1217 //
1218 if (calcSize.rgrc[0].bottom - calcSize.rgrc[0].top > 0) {
1219 if (!(Attr.Style & WS_BORDER)) {
1220 if (Location != alBottom)
1221 calcSize.rgrc[0].top += 2;
1222 if (Location != alTop)
1223 calcSize.rgrc[0].bottom -= 2;
1224 }
1225 }
1226 return 0;
1227}
1228
1229//
1230/// Erases the background and draws in etched 'borders' within the client area.
1231//
1233{
1234 // Non-3d style
1235 // !CQ Always do 3d etch here?
1236 //
1237 if (Attr.Style & WS_BORDER) {
1239 }
1240 // Use 3-d style
1241 //
1242 else {
1243 TWindowDC dc(*this);
1244
1245 // Paint etched line along the top for left, top & right slips, and along
1246 // the bottom for bottom, left & right slips to separate from the menubar,
1247 // statusbar & eachother.
1248 //
1249 int height(GetWindowRect().Height());
1250 if (Location != alBottom){
1251 TRect tr(0,0,9999,2);
1253 }
1254 if (Location != alTop){
1255 TRect tr(0,height-2,9999,height);
1257 }
1258 }
1259}
1260
1261//
1262/// Erases the background and draws in etched 'borders' within the client area.
1263//
1264bool
1266{
1267 TWindow::EvEraseBkgnd(hDC); // Let TWindow erase everything
1268
1269 // !CQ Paint etched lines for docked children?
1270
1271 return true;
1272}
1273
1274//
1275/// Makes sure that the slip size is updated when a child changes size.
1276//
1277void
1279{
1280 if (n.Event == WM_SIZE)
1281 ReLayout(false);
1282 else
1284}
1285
1286//
1287//
1288//
1289class TDecorationSpan {
1290public:
1291 int Left;
1292 int Right;
1293 int Top;
1294 int Bottom;
1295 TWindow* Window;
1296 bool Moved;
1297
1298 TDecorationSpan(TWindow* w, TGridType);
1299
1300 bool operator <(const TDecorationSpan& other) const
1301 {return Top < other.Top || (Top == other.Top && Left < other.Left);}
1302};
1303
1304//
1305// Create the decoration span from the grid.
1306//
1307TDecorationSpan::TDecorationSpan(TWindow* w, TGridType gridType)
1308 : Moved(false)
1309{
1310 TRect rect = w->GetWindowRect();
1311 ::MapWindowPoints(nullptr, w->GetParentH(), reinterpret_cast<TPoint*>(&rect), 2); // map to slip coordinates
1312
1313 Window = w;
1314 if (gridType == YCoord) {
1315 Top = rect.top;
1316 Left = rect.left;
1317 Right = rect.right;
1318 Bottom = rect.bottom;
1319 }
1320 else {
1321 Top = rect.left;
1322 Left = rect.top;
1323 Right = rect.bottom;
1324 Bottom = rect.right;
1325 }
1326}
1327
1328//
1329/// When the slip shrinks, this function adjusts dockables where needed.
1330//
1331bool
1339
1340//
1341/// Compresses or expands dockables perpendicular to the grid line.
1342//
1343void
1345{
1347
1348 // Tile dockables perpendicular to grid lines
1349 //
1350 if (!decoList.empty()) {
1351 int gridLine = decoList[0].Top;
1352 int lastTop = gridLine - 1;
1353 int delta = 0;
1354 for (size_t i = 0; i < decoList.size(); ++i) {
1355 decoList[i].Moved = false;
1356 int t = decoList[i].Top;
1357 if (t != lastTop) {
1358 delta = gridLine-t;
1359 gridLine = t;
1360 lastTop = t;
1361 }
1362 if (delta != 0) {
1363 decoList[i].Top += delta;
1364 decoList[i].Bottom += delta;
1365 decoList[i].Moved = true;
1366 }
1367 gridLine = std::max(gridLine,decoList[i].Bottom);
1368 }
1369
1370 // Move all dockables that have changed location.
1371 //
1372 for (size_t j = 0; j < decoList.size(); ++j) {
1373 TPoint pt;
1374 TDecorationSpan& decoItem = decoList[j];
1375 if (decoItem.Moved) {
1376 if (GridType == YCoord) {
1377 pt.x = decoItem.Left;
1378 pt.y = decoItem.Top;
1379 }
1380 else {
1381 pt.x = decoItem.Top;
1382 pt.y = decoItem.Left;
1383 }
1384 decoItem.Window->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1386 }
1387 }
1388 }
1389
1390 ReLayout(false);
1391}
1392
1393//
1394/// Compresses empty space along grid line if any dockables hang out past the end.
1395//
1396void
1398{
1399 // Scan each row looking for a decoration that hangs off the end.
1400 // If possible, pull that decoration in by collapsing empty space between
1401 // decorations on that row.
1402 //
1404 size_t firstOnRow = 0;
1405 size_t lastOnRow = 0;
1406 while (firstOnRow < decoList.size()) {
1407 int spaceOnRow = decoList[firstOnRow].Left;
1408 int rowTop = decoList[firstOnRow].Top;
1409 while (lastOnRow + 1 < decoList.size() && decoList[lastOnRow + 1].Top == rowTop) {
1410 spaceOnRow += decoList[lastOnRow+1].Left-(decoList[lastOnRow].Right+1);
1411 lastOnRow ++;
1412 }
1413
1414 int delta = decoList[lastOnRow].Right - width;
1415 if (delta > 0 && spaceOnRow > 0) {
1416 if (spaceOnRow > delta) {
1417 // if there is extra empty space, collapse from the right
1418 //
1419 int r = width;
1420 size_t i = lastOnRow;
1421 while (i >= firstOnRow && (decoList[i].Right+1) > r) {
1422 int dx = (decoList[i].Right+1) - r;
1423 decoList[i].Left -= dx;
1424 decoList[i].Right -= dx;
1425 decoList[i].Moved = true;
1426 r = decoList[i].Left;
1427 if (i == 0) break;
1428 i--;
1429 }
1430 }
1431 else {
1432 // if there is not extra empty space, just collapse the space
1433 //
1434 int r = 0;
1435 for (size_t i = firstOnRow; i <= lastOnRow; ++i) {
1436 if (decoList[i].Left > r) {
1437 int dx = decoList[i].Left - r;
1438 decoList[i].Left -= dx;
1439 decoList[i].Right -= dx;
1440 decoList[i].Moved = true;
1441 r = decoList[i].Right+1;
1442 }
1443 else
1444 break;
1445 }
1446 }
1447 }
1449 }
1450
1451 // Move all dockables that have changed location.
1452 //
1453 for (size_t i = 0; i < decoList.size(); ++i) {
1454 TPoint pt;
1455 TDecorationSpan& decoItem = decoList[i];
1456 if (decoItem.Moved) {
1457 if (GridType == YCoord) {
1458 pt.x = decoItem.Left;
1459 pt.y = decoItem.Top;
1460 }
1461 else {
1462 pt.x = decoItem.Top;
1463 pt.y = decoItem.Left;
1464 }
1465 decoItem.Window->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1467 }
1468 }
1469}
1470
1471//
1472/// Changes the child metrics of this docking window within its decorated frame.
1473/// Calls when the rectangle area of the docking area is different from the computed
1474/// area of the dockable windows within the docking area.
1475//
1476void
1478{
1479 // Has the docking area changed in size?
1480 //
1482
1483 bool sizeChanged;
1484 if (Location == alTop || Location == alBottom) {
1485 sizeChanged = Attr.H != area.cy;
1486 Attr.H = area.cy;
1487 }
1488 else {
1489 sizeChanged = Attr.W != area.cx;
1490 Attr.W = area.cx;
1491 }
1492
1493 // If the size has change or we need to force a layout, then do so
1494 //
1495 if (sizeChanged || forcedLayout) {
1497 CHECK(df);
1498
1499 // Set the same metrics just to dirty the layout plan & force a rebuild
1500 //
1502 df->GetChildLayoutMetrics(*this, metrics);
1503 df->SetChildLayoutMetrics(*this, metrics);
1504
1505 df->Layout();
1506 }
1507}
1508
1509//
1510/// This function overrides TDockingSlip::DockableInsert to insert a new dockable
1511/// object into this TEdgeSlip. Called by mouseup handler after a dockable object is
1512/// dropped into this slip.
1513//
1514void
1517{
1518 // Get dockable's window & hide it in case we have to toss it around a bit
1519 // Reparent the window to the edge slip
1520 //
1521 TWindow* dockableWindow = dockable.GetWindow();
1523 dockableWindow->ShowWindow(SW_HIDE);
1524 dockableWindow->SetParent(this);
1525
1526 // Let window know it was docked...
1527 //
1528#ifdef UNIX
1529 if (dockableWindow->IsWindow()) //???????????????????????
1530 dockableWindow->HandleMessage(WM_OWLWINDOWDOCKED, TParam1(GridType == YCoord ? alTop : alLeft), TParam2( (TDockingSlip*)this) );
1531#else
1532 dockableWindow->DispatchMsg(WM_OWLWINDOWDOCKED, 0, TParam1(GridType == YCoord ? alTop : alLeft),
1533 TParam2(static_cast<TDockingSlip*>(this)));
1534#endif
1535
1536 // Slam dockable over to 0,0 since Move assumes we own it already
1537 //
1538 dockableWindow->SetWindowPos(nullptr, 0, 0, 0, 0,
1540
1541 // Make sure that the dockable is oriented the right way--horizontal layout
1542 // for Y-gridded slips
1543 //
1544 dockable.Layout(GridType == YCoord ? alTop : alLeft);
1545
1546/// dockableWindow->Create(); // just in case? but only if we are?
1548 dockableWindow->ShowWindow(SW_SHOWNA);
1549}
1550
1551//
1552/// Overriden TDockingSlip virtual. Called by mouseup handler after a drag within
1553/// this docking window.
1554//
1555void
1558{
1559 TWindow* dockableWindow = dockable.GetWindow();
1561
1562 // If no dockable topleft given, calculate based on relative dockable &
1563 // location
1564 //
1565 if (topLeft) {
1566 dockPos = *topLeft;
1567 }
1568 else {
1569 // Figure out the best relative position if none given
1570 //
1571 if (position == rpNone) switch (Location) {
1572 case alNone:
1573 break;
1574 case alTop:
1575 position = rpBelow;
1576 break;
1577 case alBottom:
1578 position = rpAbove;
1579 break;
1580 case alLeft:
1582 break;
1583 case alRight:
1585 break;
1586 default: //JJH added empty default construct
1587 break;
1588 }
1589
1590 // Get the last child inserted into this docking window and use it as the
1591 // relative window if none was given
1592 //
1593 TWindow* relWindow = 0;
1594 if (relDockable)
1595 relWindow = relDockable->GetWindow();
1596 if (!relWindow)
1598
1599 // Get its rect if it exists, or the screen coord of this slip's client area
1600 //
1601 TRect relWindowRect(0,0,0,0);
1602 if (relWindow)
1603 relWindowRect = relWindow->GetWindowRect();
1604 else
1605 ::MapWindowPoints(nullptr, *this, reinterpret_cast<TPoint*>(&relWindowRect), 2);
1606
1607 TSize dockableSize = dockableWindow->GetWindowRect().Size();
1608 switch (position) {
1609 case rpNone:
1610 break;
1611 case rpAbove:
1613 break;
1614 case rpBelow:
1615 dockPos = TPoint(relWindowRect.left, relWindowRect.bottom);
1616 break;
1617 case rpLeftOf:
1619 break;
1620 case rpRightOf:
1622 break;
1623 default: //JJH added default construct
1624 break;
1625 }
1626 }
1627
1628 // Find a gridline on which to put the dockable
1629 //
1630 int dockableEdge;
1632 CHECK(!GridList.empty());
1633 int bottomEdge = GridList[0].Top;
1634 if (Location == alTop || Location == alBottom)
1636 else
1638
1639 for (size_t i = 0; i < GridList.size(); ++i) {
1640 if (dockableEdge <= (GridList[i].Top+GridList[i].Bottom)/2)
1641 break;
1642 if (GridList[i].Window != dockableWindow)
1643 bottomEdge = std::max(bottomEdge,GridList[i].Bottom);
1644 }
1645
1646 // Adjust perpendicular coord to newly found spot
1647 //
1649 if (Location == alTop || Location == alBottom) {
1650 newPos.y = bottomEdge;
1651 }
1652 else {
1653 newPos.x = bottomEdge;
1654 }
1655
1656 // Adjust from screen coords, but make sure rect topleft is > 0
1657 //
1658 ::MapWindowPoints(nullptr, *this, &newPos, 1);
1659 if (newPos.x < 0)
1660 newPos.x = 0;
1661 if (newPos.y < 0)
1662 newPos.y = 0;
1663
1664 // Position & show the dockable window
1665 //
1666 dockableWindow->SetWindowPos(nullptr, newPos.x, newPos.y, 0, 0,
1668 dockableWindow->ShowWindow(SW_SHOWNA);
1669
1670 // Adjust all windows on the grid line
1671 //
1673
1674 // Squash down dockable's previous area if needed
1675 //
1677}
1678
1679//
1680/// Overriden TDockingSlip virtual. Called by mouseup handler after a dockable has
1681/// been removed from this docking slip.
1682//
1683void
1685{
1687}
1688
1689//
1690/// All terminology in this function is referenced to the following two windows
1691/// Drag and LeftEdge. The LeftEdge window is only valid if the Drag windows's
1692/// left side is intersecting the LeftEdge window's right side.
1693/// \code
1694/// ======================
1695/// ------------------- Drag Window |
1696/// | LeftEdge Window |================
1697/// -------------------
1698/// \endcode
1699//1 The goal of this function is to anchor down the Drag window's left side.
1700/// This is accomplished by one of three ways:
1701/// - 1. Leave the Drag window where it is; if the Drag window's left side does
1702/// not intersect with any other windows (no LeftEdge window).
1703/// - 2. Slide the Drag window to the right of the LeftEdge window being
1704/// intersected. This is only done if the intersection is not beyond the
1705/// midpoint (less than 50% of the LeftEdge window) of the LeftEdge window.
1706/// - 3. Slide the Drag window to the left side position of the LeftEdge window
1707/// (the Drag window's left side is equal to the LeftEdge window's left
1708/// side). The LeftEdge window is then slid to the right side of the Drag
1709/// window; if the intersection is beyond the mid point of the left edge
1710/// window (more than 50% of the LeftEdge window).
1711//
1712TWindow*
1714{
1715 // Do we want to move the draggedWindow, if so do that.
1716 //
1717 TRect draggedRect = draggedWindow->GetWindowRect();
1718
1720 if (first) {
1721 TWindow* w = first;
1722 do {
1723 if (w != draggedWindow) {
1724 TRect currRect = w->GetWindowRect();
1725 TPoint pt;
1726
1727 if (Location == alTop || Location == alBottom) {
1728 if (draggedRect.left >= currRect.left && draggedRect.left <= currRect.right &&
1729 currRect.top == draggedRect.top) {
1730
1731 int midPt = (currRect.right - currRect.left) / 2;
1732
1733 // If the dragged window is obscuring the window underneath by more
1734 // than 50% then the dragged window will keep its position and the
1735 // underneath window must moved. Otherwise, the dragged window
1736 // will move and the window underneath will move.
1737 //
1738 if (currRect.left + midPt > draggedRect.left) {
1739 // Move the draggedWindow to the same left as the window
1740 // underneath.
1741 //
1742 pt.x = currRect.left;
1743 pt.y = draggedRect.top;
1744 ::MapWindowPoints(nullptr, *this, &pt, 1);
1745 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1747
1748 // Move the current window to the right of the dragged window.
1749 //
1750 draggedRect = draggedWindow->GetWindowRect();
1751 pt.x = draggedRect.right;
1752 pt.y = currRect.top;
1753 ::MapWindowPoints(nullptr, *this, &pt, 1);
1754 w->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1756 return w;
1757 }
1758 else {
1759 // Move the dragged window to the right of the current window (w).
1760 //
1761 pt.x = currRect.right;
1762 pt.y = draggedRect.top;
1763 ::MapWindowPoints(nullptr, *this, &pt, 1);
1764 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1766 return draggedWindow;
1767 }
1768 }
1769 }
1770 else {
1771 // Left and right docking area.
1772 //
1773 if (draggedRect.top >= currRect.top && draggedRect.top <= currRect.bottom &&
1774 currRect.left == draggedRect.left) {
1775
1776 int midPt = (currRect.bottom - currRect.top) / 2;
1777
1778 // If the dragged window is obscuring the window underneath by more
1779 // than 50% then the dragged window will keep its position and the
1780 // underneath window must moved. Otherwise, the dragged window will
1781 // move and the window underneath will move.
1782 //
1783 if (currRect.top+midPt > draggedRect.top) {
1784 // Move the draggedWindow to the same left as the window underneath.
1785 //
1786 pt.x = currRect.left;
1787 pt.y = draggedRect.top;
1788 ::MapWindowPoints(nullptr, *this, &pt, 1);
1789 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1791
1792 // Move the current window to the right of the dragged window.
1793 //
1794 draggedRect = draggedWindow->GetWindowRect();
1795 pt.x = draggedRect.right;
1796 pt.y = currRect.top;
1797 ::MapWindowPoints(nullptr, *this, &pt, 1);
1798 w->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1800 return w;
1801 }
1802 else {
1803 // Move the dragged window to the right of the current window (w).
1804 //
1805 pt.x = currRect.right;
1806 pt.y = draggedRect.top;
1807 ::MapWindowPoints(nullptr, *this, &pt, 1);
1808 draggedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1810 return draggedWindow;
1811 }
1812 }
1813 }
1814 }
1815
1816 w = w->Next();
1817 } while (w != first);
1818 }
1819
1820 return draggedWindow;
1821}
1822
1823//
1824// Structure to manage the list of windows to slide.
1825//
1826struct TWindowItem {
1827 TWindow* DockedWindow;
1828 int LeftSide;
1829
1830 TWindowItem(TWindow* dockedW = 0, int left = 0) : DockedWindow(dockedW),
1831 LeftSide(left)
1832 {}
1833
1834 // operator to satisfy TIArrayAsVector
1835 //
1836 bool operator == (const TWindowItem& other) {
1837 return (other.DockedWindow == DockedWindow) &&
1838 (other.LeftSide == LeftSide);
1839 }
1840};
1841
1842//
1843/// Builds a list (sorted by left coordinate) of windows on the same horizontal
1844/// (top/bottom docking) or vertical (left/right docking) of windows to the right of
1845/// or below the dragged window. The function then slides all windows from the first
1846/// one intersecting the dragged window to the last one in the list.
1847//
1848void
1850{
1851
1853
1854 // Include the (upto) two windows which were anchored in MoveDraggedWindow.
1855 //
1856 TRect draggedRect = draggedWindow->GetWindowRect() | movedWindow->GetWindowRect();
1858 if (first) {
1859 TWindow* w = first;
1860 do {
1861 // If the current window is the moved window or the draggedWindow then
1862 // grab another window.
1863 //
1864 if (w != draggedWindow) {
1865 TRect currRect = w->GetWindowRect();
1866
1867 // Build a list of windows on the same horizontal or vertical after
1868 // the dragged window.
1869 // !CQ assumes top/bottom slip -- flip axis for left/right
1870 //
1871 if (currRect.top == draggedRect.top && currRect.left >= draggedRect.left) {
1872 uint i = 0;
1873
1874 while (i < windowList.Size()) {
1875 if (currRect.left <= windowList[i].LeftSide)
1876 break;
1877 i++;
1878 }
1879
1880 TWindowItem wItem(w, currRect.left); // !CQ leave to debug
1881 windowList.AddAt(wItem, i);
1882 }
1883 }
1884
1885 w = w->Next();
1886 } while (w != first);
1887 }
1888
1889
1890 // Are there windows after the dragged window to adjust?
1891 //
1892
1893 if(windowList.Size()) {
1894 uint i = 0;
1895
1896 // Find the first one, all subsequent ones (plus this one) will be slid.
1897 //
1898 while (i < windowList.Size()) {
1899 if (windowList[i].LeftSide >= draggedRect.left &&
1900 windowList[i].LeftSide < draggedRect.right)
1901 break;
1902 i++;
1903 }
1904
1905 // Slide all windows after the dragged window.
1906 //
1907
1908 if (i == 0 || i != windowList.Size()) {
1910 TPoint pt;
1911
1912 while (i < windowList.Size()) {
1913 int offset = w1->GetWindowRect().right - windowList[i].LeftSide;
1914
1915 pt.x = windowList[i].LeftSide + offset;
1916 pt.y = windowList[i].DockedWindow->GetWindowRect().top;
1917 ::MapWindowPoints(nullptr, *this, &pt, 1);
1918 windowList[i].DockedWindow->SetWindowPos(nullptr, pt.x, pt.y, 0, 0,
1920 w1 = windowList[i++].DockedWindow;
1921 }
1922 }
1923 }
1924
1925// Iterators cannot be used when modifying the underlying container
1926//
1927// TWindowItemArrayIter iter(windowList);
1928// while (iter) {
1929// TWindowItem* item = iter.Current();
1930// windowList.Detach(item);
1931// delete item;
1932// iter++;
1933// }
1934}
1935
1936#if 0
1937//
1938// Pull every child beyond a given coord in by a given delta (positive),
1939// or push out every child beyond the given coord by the given delta (negative)
1940//
1941void
1942TEdgeSlip::Collapse(int topCoord, int delta)
1943{
1945 if (first) {
1946 TWindow* w = first;
1947 do {
1948 TRect rect = w->GetWindowRect();
1949 if (Location == alTop || Location == alBottom) {
1950 if (rect.top > topCoord) {
1951 rect.Offset(0, -delta);
1952 ::MapWindowPoints(0, *this, (LPPOINT)&rect, 1);
1953 w->SetWindowPos(0, rect.left, rect.top, 0, 0,
1955 }
1956 }
1957 else {
1958 if (rect.left > topCoord) {
1959 rect.Offset(-delta, 0);
1960 ::MapWindowPoints(0, *this, (LPPOINT)&rect, 1);
1961 w->SetWindowPos(0, rect.left, rect.top, 0, 0,
1963 }
1964 }
1965 w = w->Next();
1966 } while (w != first);
1967 }
1968}
1969#endif
1970
1971//
1972/// Computes the docking area size based on the dockables inside (total height if
1973/// top/bottom docking area or total width if left/right docking area). Includes the
1974/// non-client area etched borders or real window borders. Will return misleading
1975/// Size() if dockables not 0 justified.
1976//
1977TSize
1979{
1980 TRect rect(0, 0, 0, 0);
1981
1983 if (first) {
1984 TWindow* w = first;
1985 do {
1986 // Union of all visible areas.
1987 //
1988 if (w->GetWindowAttr().Style & WS_VISIBLE)
1989 rect |= w->GetWindowRect();
1990 w = w->Next();
1991 } while (w != first);
1992 }
1993
1994 // Only add in space if this slip is not shrunk to nothing
1995 //
1996 if (rect.bottom > rect.top && rect.right > rect.left) {
1997 if (!(Attr.Style & WS_BORDER)) { // if 3d style, add space for the etchings
1998 if (Location != alBottom)
1999 rect.bottom += 2;
2000 if (Location != alTop)
2001 rect.bottom += 2;
2002 }
2003 else {
2004 AdjustWindowRectEx(rect, Attr.Style, false, Attr.ExStyle);
2005 }
2006 }
2007
2008 return rect.Size(); // !CQ or could return rect.BottomRight()
2009}
2010
2011//
2012/// Returns the perpendicular size of the grid line with the given base coordinates.
2013/// Returns 0 if there are no dockables on the given grid line.
2014//
2015int
2017{
2019 int h = 0;
2020 if (first) {
2021 TWindow* w = first;
2022 do {
2023 if (w->GetWindowAttr().Style & WS_VISIBLE) {
2024 TRect r = w->GetWindowRect();
2025
2026 if (GridType == YCoord) {
2027 if (baseCoord == r.top) {
2028 h = std::max(h, r.Height());
2029 }
2030 }
2031 else {
2032 if (baseCoord == r.left){
2033 h = std::max(h, r.Width());
2034 }
2035 }
2036 }
2037 w = w->Next();
2038 } while (w != first);
2039 }
2040 return h;
2041}
2042
2043
2044//
2045/// Retrieves the location of the slip.
2046//
2049{
2050 return Location;
2051}
2052
2053
2059
2060//
2061/// Creates the harbor. The harbor is where the slips can go dock.
2062//
2064:
2065 TWindow(&df, _T("Harbor")),
2066 DecFrame(df)
2067{
2068 Attr.W = 0;
2069 Attr.H = 0;
2070 Attr.Style = WS_CHILD; // not visible
2071
2072 SlipTop = nullptr;
2073 SlipLeft = nullptr;
2074 SlipBottom = nullptr;
2075 SlipRight = nullptr;
2076
2077 DragDC = nullptr;
2078 DragDockable = nullptr;
2079}
2080
2081//
2082/// Destructor.
2083/// Currently does nothing.
2084//
2086{
2087}
2088
2089
2090//
2091/// Creates an edge slip at a location.
2092//
2093TEdgeSlip*
2098
2099//
2100/// Constructs a floating slip with a particular window at a location.
2101//
2107
2108//
2109/// Returns the slip at the location.
2110//
2111TEdgeSlip*
2113{
2114 switch (location) {
2115 case alNone:
2116 return nullptr;
2117 case alTop:
2118 return SlipTop;
2119 case alBottom:
2120 return SlipBottom;
2121 case alLeft:
2122 return SlipLeft;
2123 case alRight:
2124 return SlipRight;
2125 default: //JJH added empty default construct
2126 break;
2127 }
2128 return nullptr;
2129}
2130
2131//
2132/// Sets a new edge slip for a given location. Also lets the edge slip know who we
2133/// are.
2134//
2135void
2137{
2138 slip->SetHarbor(this);
2139
2140 switch (location) {
2141 case alNone:
2142 break;
2143 case alTop:
2144 SlipTop = slip;
2145 break;
2146 case alBottom:
2147 SlipBottom = slip;
2148 break;
2149 case alLeft:
2150 SlipLeft = slip;
2151 break;
2152 case alRight:
2153 SlipRight = slip;
2154 break;
2155 default: //JJH added empty default construct
2156 break;
2157 }
2158}
2159
2160//
2161/// Returns the default docking relative position for a given slip location.
2162/// \todo !CQ make a TDockingSlip virtual!
2163//
2166{
2167 switch (location) {
2168 case alNone:
2169 return rpNone;
2170 case alTop:
2171 return rpBelow;
2172 case alBottom:
2173 return rpAbove;
2174 case alLeft:
2175 return rpRightOf;
2176 case alRight:
2177 return rpLeftOf;
2178 default: //JJH added empty default construct
2179 break;
2180 }
2181 return rpNone;
2182}
2183
2184namespace {
2185
2186//
2187// Layered-window drag guide (replaces PatBlt/PATINVERT, which is invisible under DWM)
2188//
2189
2190const TCHAR DragGuideClassName[] = _T("OWLNext.DragGuideWindow.1");
2191const COLORREF DragGuideColor = RGB(100, 100, 100);
2192const BYTE DragGuideAlpha = 128; // 50% transparent
2193
2195{
2197 WNDCLASSEX wc = {};
2198 wc.cbSize = sizeof(wc);
2199 wc.lpfnWndProc = ::DefWindowProc;
2200 wc.hInstance = ::GetModuleHandle(nullptr);
2201 wc.hbrBackground = brush;
2202 wc.lpszClassName = DragGuideClassName;
2203 return ::RegisterClassEx(&wc);
2204}
2205
2206// Apply a hollow frame region to the guide window (punch out the interior).
2207//
2208static void SetDragGuideRegion(HWND hwnd, int cx, int cy, int thickness)
2209{
2210 HRGN outer = ::CreateRectRgn(0, 0, cx, cy);
2214 ::SetWindowRgn(hwnd, outer, FALSE); // OS takes ownership of outer
2215}
2216
2217// Create and show the drag guide window.
2218//
2219static HWND CreateDragGuide(const TRect& r, bool thick)
2220{
2221 static ATOM cls = RegisterDragGuideClass();
2223 const int cx = r.Width();
2224 const int cy = r.Height();
2227 reinterpret_cast<LPCTSTR>(cls),
2228 nullptr,
2229 WS_POPUP,
2230 r.left, r.top, cx, cy,
2231 nullptr, nullptr, ::GetModuleHandle(nullptr), nullptr);
2234 ::ShowWindow(hwnd, SW_SHOWNA);
2235 return hwnd;
2236}
2237
2238// Move and resize the drag guide window.
2239//
2240static void MoveDragGuide(HWND hwnd, const TRect& r, bool thick)
2241{
2243 const int cx = r.Width();
2244 const int cy = r.Height();
2245 ::SetWindowPos(hwnd, nullptr, r.left, r.top, cx, cy,
2248}
2249
2250// Destroy the drag guide window.
2251//
2252static void DestroyDragGuide(HWND hwnd)
2253{
2255}
2256
2257// Per-harbor drag guide HWND map (avoids ABI change to THarbor).
2258//
2259static std::unordered_map<THarbor*, HWND> s_dragGuideHwnds;
2260
2261} // namespace
2262
2263//
2264/// Begins a dockable window tracking session. Returns true if started
2265/// satisfactorily.
2266//
2267bool
2270{
2271 // Get dockable to drag, its frame rectangle & the mouse anchor point
2272 // Compute relative position of mouse from top/left corner of window.
2273 //
2277
2278 // Remember the docking area & original docking area too. Also remember which
2279 // docking slip to notify when drag is done.
2280 //
2283
2284 // Find out the sizes of the dockable in the three orientations:
2285 // Vertical, Horizontal & Natural
2286 //
2290
2291 // Calculate the screen relative rectangles for the four docking areas based
2292 // on the dec frame's client area.
2293 //
2294 TRect frameR = DecFrame.GetClientWindow()->GetWindowRect();
2295/// DecFrame.MapWindowPoints(0, frameR, 2);
2296
2297 if (SlipTop)
2299 else
2300 SlipTR.Set(frameR.left, frameR.top, frameR.right, frameR.top);
2301
2302 if (SlipBottom)
2304 else
2305 SlipBR.Set(frameR.left, frameR.bottom, frameR.right, frameR.bottom);
2306
2307 if (SlipLeft)
2309 else
2310 SlipLR.Set(frameR.left, frameR.top, frameR.left, frameR.bottom);
2311
2312 if (SlipRight)
2314 else
2315 SlipRR.Set(frameR.right, frameR.top, frameR.right, frameR.bottom);
2316
2317 // Capture the mouse & show the drag guide window.
2318 //
2319 SetCapture();
2320 DragDC = new TScreenDC; // non-null sentinel for EvMouseMove/EvLButtonUp guards
2321
2322 // Update dragged window here to avoid asynchronous repaint uglies when
2323 // exposed by click. Then show the guide.
2324 //
2325 DragDockable->GetWindow()->UpdateWindow();
2327
2328 return true;
2329}
2330
2331//
2332/// Handles MouseMove to perform dockable dragging if a drag is in progress.
2333//
2334void
2336{
2337 if (DragDockable && DragDC) {
2339
2340 // Compute the new horz, vert & natural frames to test for touching of
2341 // edge slips & to eventualy update DragRect. Make sure that horz & vert
2342 // rects surround mouse, shift as needed.
2343 //
2344 DragFrame.MoveTo(p.x - DragAnchor.x, p.y - DragAnchor.y);
2345
2347 if (!hFrame.Contains(p))
2348 hFrame.MoveTo(hFrame.left, p.y - DragHSize.cy/2);
2349
2351 if (!vFrame.Contains(p))
2352 vFrame.MoveTo(p.x - DragVSize.cx/2, vFrame.top);
2353
2355 if (!nFrame.Contains(p))
2356 nFrame.Offset(p.x - DragNSize.cx/2 - nFrame.left,
2357 p.y - DragNSize.cy/2 - nFrame.top);
2358
2359 if (hFrame.Touches(SlipTR))
2361 else if (hFrame.Touches(SlipBR))
2363 else if (vFrame.Touches(SlipLR))
2365 else if (vFrame.Touches(SlipRR))
2367 else
2369
2370 // If over a docking area and it is not the same as the last one, then
2371 // re-compute the frame rectangle
2372 //
2373 if (DragSlipLoc == alNone)
2374 DragFrame = nFrame;
2375 else if (DragSlipLoc == alTop || DragSlipLoc == alBottom)
2376 DragFrame = hFrame;
2377 else
2378 DragFrame = vFrame;
2379
2380 /// Adjust if needed to put frame around mouse? Check each rect? At least
2381 /// horz & vert?
2382 ///
2383/// if (!DragFrame.Contains(p))
2384/// DragFrame.Offset(p.x - DragFrame.left - 15, p.y - DragFrame.top - 15);
2385
2386 // Move the guide window to the new frame position.
2387 //
2389 }
2390 else
2392}
2393
2394//
2395/// Handles mouse up to drop a dockable window being dragged.
2396//
2397void
2399{
2400 if (DragDockable && DragDC) {
2401
2402 // Destroy the guide window (no explicit un-paint needed).
2403 //
2405 s_dragGuideHwnds.erase(this);
2406
2408
2411
2413 DragDockable = nullptr;
2414
2415 delete DragDC;
2416 DragDC = nullptr;
2417
2418 // We're docking into a new slip--call the Move function to do the
2419 // work.
2420 //
2421 if (DragOrgSlipLoc != DragSlipLoc) {
2422 // Get the real dockable interface for the actual dockable window--
2423 // working dockable may have been a helper.
2424 //
2426 CHECK(dd);
2428 }
2429 // Notifiy docking slip that the dragging resulted in a dockable move.
2430 //
2431 else {
2432 if (DragNotificatee)
2434 }
2435 }
2436 else
2438}
2439
2440//
2441/// Handles the left button double click and forwards the message to the dockable
2442/// window.
2443//
2444void
2446{
2447 // We get this message when a slip is in drag mode, and mouse clicks are
2448 // captured by the harbor.
2449 //
2450 if (DragDockable) {
2451 // If dragging, stop dragging and pass the message to the dragged window.
2452 //
2453 TWindow* win = DragDockable->GetWindow();
2456 }
2457 else {
2459 }
2460}
2461
2462//
2463/// Inserts a dockable into the appropriate docking area indicated by the given
2464/// location and either a point or a relative dockable and position.
2465//
2468 const TPoint* where,
2470{
2471 // Get the actual window associated with the dockable
2472 //
2473 TWindow* dw = dockable.GetWindow();
2474
2475 // Making the dockable Floating.
2476 //
2477 if (location == alNone) {
2478 // The 'where' is relative to the decframe's client. Make absolute when
2479 // the floatFrame is a popup
2480 //
2482 if (where) {
2483 floatWhere = *where;
2484 }
2485 else {
2486 // Don't know where to put the floating palette, use CW_USEDEFAULT
2487 //
2489 }
2490
2491 // Call out to the virtual to contruct a hidden floating slip
2492 //
2495 dw);
2496 // Give slip pointer to harbor
2497 //
2498 slip->SetHarbor(this);
2499
2500 // If decorated frame is already created, the create floating slip
2501 //
2502 if (DecFrame.GetHandle()) {
2503 slip->Create();
2504 slip->DockableInsert(dockable, where, rpNone, nullptr);
2505 slip->ShowWindow(SW_SHOWNA);
2506
2507 } else {
2508
2509 // Slip will be created latter (auto-creation) - make sure it's visible
2510 //
2511 slip->GetWindowAttr().Style |= WS_VISIBLE;
2512 slip->DockableInsert(dockable, where, rpNone, nullptr);
2513 }
2514
2515 // Return floating slip
2516 //
2517 return slip;
2518 }
2519 else {
2521 if (!slip) {
2522 // Make an edge slip if not one already for the given edge
2523 //
2527
2528 // If frame is created, go ahead and create slip
2529 //
2530 if (DecFrame.GetHandle())
2531 slip->Create();
2532 }
2533
2534 // Insert the dockable into the slip, based on args given
2535 //
2536 slip->DockableInsert(dockable, where, position, relDockable);
2537
2538 // Return edge slip
2539 //
2540 return slip;
2541 }
2542}
2543
2544//
2545/// Moves a dockable from one slip to another.
2546//
2547void
2550{
2551 // Get current slip, assuming it is the parent of the dockable's window
2552 //
2554 TWindow* dockableWindow = dockable.GetWindow();
2555 if (dockableWindow) {
2557 }
2558
2559 // If the location hasn't changes, just tweak the position within the slip,
2560 // otherwise insert into new & remove from old.
2561 //
2562 if (previousSlip && previousSlip->GetLocation() == location) {
2563 if (where)
2564 previousSlip->DockableMove(dockable, where);
2565 else
2566 ;// !CQ call DockableMove when it takes position & relDockable
2567 }
2568 else {
2570 dockable.GetRect(previousRect);
2571
2572 // Remove from the previous slip
2573 //
2575
2576 // Insert into the new slip
2577 //
2579 }
2580}
2581
2582//
2583/// Removes a dockable from the harbor.
2584//
2585void
2587{
2588 // Get the actual window associated with the dockable
2589 //
2590 TWindow* dockableWindow = dockable.GetWindow();
2591
2592 if (dockableWindow) {
2594 dockable.GetRect(previousRect);
2595
2596 // Find the slip containing the dockable
2597 //
2599 TDockingSlip);
2600
2601 // Remove the dockable from the slip and reparent it to the harbor
2602 //
2603 dockableWindow->ShowWindow(SW_HIDE);
2604 dockableWindow->SetParent(this);
2605
2606 // Notify original docking slip that its dockable was removed.
2607 //
2608 if (previousSlip)
2609 previousSlip->DockableRemoved(previousRect);
2610 }
2611}
2612
2613} // OWL namespace
2614
#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:496
void EvOwlWindowDocked(uint pos, const TDockingSlip &slip)
Definition docking.cpp:534
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:330
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:310
auto GetWindow() -> TWindow *override
Returns the TWindow part of this dockable object.
Definition docking.cpp:368
void EvOwlWindowDocked(uint pos, const TDockingSlip &slip)
Inserts/deletes FlatBar Grip.
Definition docking.cpp:106
void EvLButtonDown(uint modKeys, const TPoint &point)
Forwards event to slip to allow movement of gadget within the slip.
Definition docking.cpp:439
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:349
~TDockableGadgetWindow() override
Definition docking.cpp:82
virtual TGadget * GetGripGadget()
Definition docking.cpp:89
void GetRect(TRect &) override
Gets this dockable's screen rectangle.
Definition docking.cpp:300
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:183
void LayoutSession() override
If the gadget window changes size when laying out a dockable gadget window, this function tells the d...
Definition docking.cpp:378
auto GetHarbor() -> THarbor *override
Returns the harbor containing the dockable object.
Definition docking.cpp:421
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:58
bool EvSetCursor(HWND hWndCursor, uint codeHitTest, TMsgId mouseMsg)
Definition docking.cpp:154
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:1713
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:1515
void EvParentNotify(const TParentNotify &)
Makes sure that the slip size is updated when a child changes size.
Definition docking.cpp:1278
uint EvNCCalcSize(bool calcValidRects, NCCALCSIZE_PARAMS &calcSize)
Returns the size of the client area, leaving room for the etched separators.
Definition docking.cpp:1210
TEdgeSlip(TDecoratedFrame &parent, TAbsLocation location, TModule *module=0)
Constructs an edge slip, and sets the approriate styles for the window.
Definition docking.cpp:974
void EvLButtonDown(uint modKeys, const TPoint &point)
Forwards the left button down message to the dockable object.
Definition docking.cpp:1176
bool EvWindowPosChanging(WINDOWPOS &windowPos)
When the slip shrinks, this function adjusts dockables where needed.
Definition docking.cpp:1332
void DockableRemoved(const TRect &orgRect) override
Overriden TDockingSlip virtual.
Definition docking.cpp:1684
void SetupWindow() override
Ensures that all decorations in the docking window are abutted against each other (both horizontally ...
Definition docking.cpp:1061
void CompressGridLines()
Compresses or expands dockables perpendicular to the grid line.
Definition docking.cpp:1344
void DockableMove(TDockable &dockable, const TPoint *topLeft, TRelPosition position, TDockable *relDockable) override
Overriden TDockingSlip virtual.
Definition docking.cpp:1556
auto EvCommand(uint id, THandle hWndCtl, uint notifyCode) -> TResult override
Forward command messages to the parent.
Definition docking.cpp:1161
int GridSize(int baseCoord)
Returns the perpendicular size of the grid line with the given base coordinates.
Definition docking.cpp:2016
void EvLButtonDblClk(uint modKeys, const TPoint &point)
Handles WM_LBUTONDBLCLICK to tell the frame to edit a toolbar.
Definition docking.cpp:1201
void EvCommandEnable(TCommandEnabler &commandEnabler) override
Changes the reciever to be the framewindow, not the docking window.
Definition docking.cpp:1140
void CompressParallel(int width)
Compresses empty space along grid line if any dockables hang out past the end.
Definition docking.cpp:1397
auto GetLocation() const -> TAbsLocation override
Retrieves the location of the slip.
Definition docking.cpp:2048
void EvNCPaint(HRGN)
Erases the background and draws in etched 'borders' within the client area.
Definition docking.cpp:1232
TSize ComputeDockingArea()
Computes the docking area size based on the dockables inside (total height if top/bottom docking area...
Definition docking.cpp:1978
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:1849
void ReLayout(bool forcedLayout)
Called by Harbor when creating this docking window on a drop.
Definition docking.cpp:1477
bool EvEraseBkgnd(HDC)
Erases the background and draws in etched 'borders' within the client area.
Definition docking.cpp:1265
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:724
auto ComputeSize(TAbsLocation, TSize *) -> TSize override
Forward the first four TDockable virtuals to the client dockable.
Definition docking.cpp:887
void EvSettingChange(uint, LPCTSTR)
Event handler for the .INI file changed message.
Definition docking.cpp:788
void EvNCLButtonDown(uint hitTest, const TPoint &point)
Handles lbutton down bubbled up from the client to begin a dockable drag operation.
Definition docking.cpp:601
auto GetHarbor() -> THarbor *override
Returns the associated harbor.
Definition docking.cpp:946
auto ShouldBeginDrag(TPoint &) -> bool override
A given mouse down should never begin a drag for this dockable.
Definition docking.cpp:926
void DockableInsert(TDockable &, const TPoint *topLeft, TRelPosition, TDockable *relDockable) override
Overriden TDockingSlip virtual.
Definition docking.cpp:827
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:764
void GetRect(TRect &) override
Gets this dockable's screen rect.
Definition docking.cpp:902
void EvGetMinMaxInfo(MINMAXINFO &info)
Definition docking.cpp:814
void Layout(TAbsLocation, TSize *=nullptr) override
Forwards the layout message over to the dockable object.
Definition docking.cpp:911
void DockableMove(TDockable &, const TPoint *topLeft, TRelPosition, TDockable *relDockable) override
Overriden TDockingSlip virtual.
Definition docking.cpp:857
void EvClose()
When closing the floating slip, removes any dockable first so that it is not destroyed.
Definition docking.cpp:641
bool EvSizing(uint side, TRect &rect)
Handles the Windows 4.0 message for the best resize user feedback.
Definition docking.cpp:654
void DockableRemoved(const TRect &) override
Overriden TDockingSlip virtual.
Definition docking.cpp:869
void EvLButtonDown(uint hitTest, const TPoint &point)
Handles lbutton down bubbled up from the client to begin a dockable drag operation.
Definition docking.cpp:618
auto GetWindow() -> TWindow *override
Returns the TWindow part of this dockable object.
Definition docking.cpp:936
auto GetLocation() const -> TAbsLocation override
Returns the location of the object.
Definition docking.cpp:955
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:2586
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:2165
void EvLButtonDblClk(uint modKeys, const TPoint &point)
Handles the left button double click and forwards the message to the dockable window.
Definition docking.cpp:2445
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:2467
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:2548
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:2398
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:2335
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:2094
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:2103
TDockingSlip * DragNotificatee
Slip notified on drag operations.
Definition docking.h:370
~THarbor() override
Destructor.
Definition docking.cpp:2085
TEdgeSlip * SlipTop
Definition docking.h:354
void SetEdgeSlip(TAbsLocation location, TEdgeSlip *slip)
Sets a new edge slip for a given location.
Definition docking.cpp:2136
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:2268
TEdgeSlip * GetEdgeSlip(TAbsLocation location)
Returns the slip at the location.
Definition docking.cpp:2112
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:78
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:964
EV_WM_OWLWINDOWDOCKED
Definition docking.cpp:99
EV_WM_LBUTTONUP
Definition docking.cpp:2057
EV_WM_SETCURSOR
Definition docking.cpp:100
UINT TMsgId
Message ID type.
Definition dispatch.h:53
EV_WM_GETMINMAXINFO
Definition docking.cpp:549
EV_WM_SETTINGCHANGE
Definition docking.cpp:548
EV_WM_LBUTTONDBLCLK
Definition docking.cpp:963
EV_WM_MOUSEMOVE
Definition docking.cpp:2055
uint32 MkUint32(uint16 lo, uint16 hi)
Definition defs.h:261
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:967
EV_WM_NCPAINT
Definition docking.cpp:965
EV_WM_WINDOWPOSCHANGING
Definition docking.cpp:546
END_RESPONSE_TABLE
Definition button.cpp:26
EV_WM_NCLBUTTONDOWN
Definition docking.cpp:542
LRESULT TResult
Result type.
Definition dispatch.h:52
EV_WM_WINDOWPOSCHANGED
Definition docking.cpp:547
unsigned int uint
Definition number.h:25
EV_WM_LBUTTONDOWN
Definition checklst.cpp:195
EV_WM_SIZING
Definition docking.cpp:545
EV_WM_ERASEBKGND
Definition docking.cpp:966
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