]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/gizmos/dynamicsash.cpp
use default position, not 0, 0
[wxWidgets.git] / contrib / src / gizmos / dynamicsash.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dynamicsash.cpp
3 // Purpose: A window which can be dynamically split to an arbitrary depth
4 // and later reunified through the user interface
5 // Author: Matt Kimball
6 // Modified by:
7 // Created: 7/15/2001
8 // RCS-ID: $Id$
9 // Copyright: (c) 2001 Matt Kimball
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 #ifdef __GNUG__
14 #pragma implementation "splittree.h"
15 #endif
16
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 // for all others, include the necessary headers (this file is usually all you
25 // need because it includes almost all "standard" wxWidgets headers)
26 #ifndef WX_PRECOMP
27 #include "wx/wx.h"
28 #endif
29
30 #ifdef __WXMSW__
31 #include "wx/mdi.h"
32 #endif
33
34 #include "wx/gizmos/dynamicsash.h"
35
36
37 const wxChar* wxDynamicSashWindowNameStr = wxT("dynamicSashWindow");
38
39
40 /*
41 wxDynamicSashWindow works by internally storing a tree of Implementation
42 objects (wxDynamicSsahWindowImpl) and Leaf objects
43 (wxDynamicSashWindowLeaf). The wxDynamicSashWindow has a pointer to one
44 implementation, and each implementation either has a pointer to a one
45 leaf (m_leaf) or a pointer to two children implementation objects
46 (m_child). The leaves each are responsible for drawing the frame and
47 decorations around one user-provided views and for responding to mouse
48 and scrollbar events.
49
50 A resulting tree might look something like this:
51
52 wxDynamicSashWindow
53 |
54 +- wxDynamicSashWindowImpl
55 |
56 +- wxDynamicSashWindowLeaf
57 | |
58 | +- user view window
59 |
60 +- wxDynamicSashWindowImpl
61 |
62 +- wxDynamicSashWindowLeaf
63 | |
64 | +- user view window
65 |
66 +- wxDynamicSashWindowLeaf
67 |
68 +- user view window
69
70 Each time a split occurs, one of the implementation objects removes its
71 leaf, generates two new implementation object children, each with a new
72 leaf, and reparents the user view which was connected to its old leaf
73 to be one of the new leaf's user view, and sends a Split event to the
74 user view in the hopes that it will generate a new user view for the
75 other new leaf.
76
77 When a unification ocurrs, an implementation object is replaced by one
78 of its children, and the tree of its other child is pruned.
79
80 One quirk is that the top-level implementation object (m_top) always
81 keeps a pointer to the implementation object where a new child is needed.
82 (m_add_child_target). This is so that when a new uesr view is added
83 to the hierarchy, AddChild() is able to reparent the new user view to
84 the correct implementation object's leaf.
85
86 */
87
88 #include <wx/dcmemory.h>
89 #include <wx/dcscreen.h>
90 #include <wx/layout.h>
91 #include <wx/scrolbar.h>
92 #include <wx/settings.h>
93
94
95 #define wxEVT_DYNAMIC_SASH_PRIVATE (wxEVT_DYNAMIC_SASH_BASE + 8)
96 #define wxEVT_DYNAMIC_SASH_REPARENT (wxEVT_DYNAMIC_SASH_PRIVATE + 1)
97
98
99 /*
100 wxDynamicSashReparentEvent is generated by the AddChild() method of
101 wxDynamicSashWindow when it wants a Leaf to reparent a user view window
102 to its viewport at some time in the future. We can't reparent the window
103 immediately, because switching parents in AddChild() confuses the wxWindow
104 class. Instead, we queue up this event, and the window is actually
105 reparented the next time we process events in the idle loop.
106 */
107 class wxDynamicSashReparentEvent : public wxEvent {
108 public:
109 wxDynamicSashReparentEvent();
110 wxDynamicSashReparentEvent(wxObject *object);
111 wxDynamicSashReparentEvent(const wxDynamicSashReparentEvent& evt);
112
113 virtual wxEvent* Clone() const { return new wxDynamicSashReparentEvent(*this); }
114
115 DECLARE_DYNAMIC_CLASS(wxDynamicSashReparentEvent)
116 };
117
118
119 enum DynamicSashRegion {
120 DSR_NONE,
121 DSR_VERTICAL_TAB,
122 DSR_HORIZONTAL_TAB,
123 DSR_CORNER,
124 DSR_LEFT_EDGE,
125 DSR_TOP_EDGE,
126 DSR_RIGHT_EDGE,
127 DSR_BOTTOM_EDGE
128 };
129
130
131 class wxDynamicSashWindowImpl : public wxEvtHandler {
132 public:
133 wxDynamicSashWindowImpl(wxDynamicSashWindow *window);
134 ~wxDynamicSashWindowImpl();
135
136 bool Create();
137 void AddChild(wxWindow *window);
138 void DrawSash(int x, int y) const;
139 void ConstrainChildren(int px, int py);
140 void Split(int x, int y);
141 void Unify(int panel);
142 void Resize(int x, int y);
143 wxDynamicSashWindowImpl *FindParent(DynamicSashRegion side) const;
144 wxDynamicSashWindowImpl *FindUpperParent(wxDynamicSashWindowImpl *sash_a,
145 wxDynamicSashWindowImpl *sash_b) const;
146 wxWindow *FindFrame() const;
147 wxScrollBar *FindScrollBar(const wxWindow *child, int vert) const;
148
149 void OnSize(wxSizeEvent &event);
150 void OnPaint(wxPaintEvent &event);
151 void OnMouseMove(wxMouseEvent &event);
152 void OnLeave(wxMouseEvent &event);
153 void OnPress(wxMouseEvent &event);
154 void OnRelease(wxMouseEvent &event);
155
156 wxDynamicSashWindow *m_window;
157 wxDynamicSashWindowImpl *m_add_child_target;
158
159 /* This is the window we are responsible for managing. Either of
160 leaf or our children are in this window. For the top level
161 implementation object, this is the same as m_window.
162 Otherwise it is a window we've created an will destroy when we
163 are deleted. */
164 wxWindow *m_container;
165
166 wxDynamicSashWindowImpl *m_parent;
167 wxDynamicSashWindowImpl *m_top;
168 wxDynamicSashWindowImpl *m_child[2];
169
170 class wxDynamicSashWindowLeaf *m_leaf;
171
172 /* If the implementation is split horizontally or vertically, m_split
173 is set to DSR_HORIZONTAL_TAB or DSR_VERTICAL_TAB, respectively.
174 Otherwise it is set to DSR_NONE. */
175 DynamicSashRegion m_split;
176
177 /* These are used to keep track of a sash as it is being dragged, for
178 drawing the user interface correctly. */
179 DynamicSashRegion m_dragging;
180 int m_drag_x, m_drag_y;
181 };
182
183 class wxDynamicSashWindowLeaf : public wxEvtHandler {
184 public:
185 wxDynamicSashWindowLeaf(wxDynamicSashWindowImpl *impl);
186 ~wxDynamicSashWindowLeaf();
187
188 bool Create();
189 void AddChild(wxWindow *window);
190 DynamicSashRegion GetRegion(int x, int y);
191 void ResizeChild(wxSize size);
192 wxScrollBar *FindScrollBar(const wxWindow *child, int vert) const;
193
194 void OnSize(wxSizeEvent &event);
195 void OnPaint(wxPaintEvent &event);
196 void OnScroll(wxScrollEvent &event);
197 void OnFocus(wxFocusEvent &event);
198 void OnMouseMove(wxMouseEvent &event);
199 void OnLeave(wxMouseEvent &event);
200 void OnPress(wxMouseEvent &event);
201 void OnRelease(wxMouseEvent &event);
202 void OnReparent(wxEvent &event);
203
204 wxDynamicSashWindowImpl *m_impl;
205
206 wxScrollBar *m_vscroll, *m_hscroll;
207
208 /* m_child is the window provided to us by the application developer.
209 m_viewport is a window we've created, and it is the immediately
210 parent of m_child. We scroll m_child by moving it around within
211 m_viewport. */
212 wxWindow *m_viewport, *m_child;
213 };
214
215 // wxDynamicSashWindow //////////////////////////////////////////////////////
216
217 wxDynamicSashWindow::wxDynamicSashWindow() {
218 m_impl = NULL;
219 }
220
221 wxDynamicSashWindow::wxDynamicSashWindow(wxWindow *parent, wxWindowID id,
222 const wxPoint& pos, const wxSize& size,
223 long style, const wxString& name) {
224 m_impl = NULL;
225 Create(parent, id, pos, size, style, name);
226 }
227
228 wxDynamicSashWindow::~wxDynamicSashWindow() {
229 SetEventHandler(this);
230 delete m_impl;
231 }
232
233 bool wxDynamicSashWindow::Create(wxWindow *parent, wxWindowID id,
234 const wxPoint& pos, const wxSize& size,
235 long style, const wxString& name) {
236 if (m_impl)
237 return false;
238
239 if (!wxWindow::Create(parent, id, pos, size, style, name))
240 return false;
241
242 m_impl = new wxDynamicSashWindowImpl(this);
243 if (!m_impl)
244 return false;
245
246 if (!m_impl->Create()) {
247 delete m_impl;
248 m_impl = NULL;
249 return false;
250 }
251
252 return true;
253 }
254
255 void wxDynamicSashWindow::AddChild(wxWindowBase *child) {
256 wxWindow::AddChild(child);
257
258 m_impl->AddChild(wxDynamicCast(child, wxWindow));
259 }
260
261 wxScrollBar *wxDynamicSashWindow::GetHScrollBar(const wxWindow *child) const {
262 return m_impl->FindScrollBar(child, 0);
263 }
264
265 wxScrollBar *wxDynamicSashWindow::GetVScrollBar(const wxWindow *child) const {
266 return m_impl->FindScrollBar(child, 1);
267 }
268
269 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashWindow, wxWindow)
270
271 // wxDynamicSashWindowImpl //////////////////////////////////////////////////
272
273 wxDynamicSashWindowImpl::wxDynamicSashWindowImpl(wxDynamicSashWindow *window) {
274 m_window = window;
275 m_add_child_target = this;
276
277 m_container = NULL;
278 m_parent = NULL;
279 m_top = this;
280 m_child[0] = m_child[1] = NULL;
281 m_leaf = NULL;
282 m_dragging = DSR_NONE;
283 m_split = DSR_NONE;
284 }
285
286 wxDynamicSashWindowImpl::~wxDynamicSashWindowImpl() {
287 delete m_leaf;
288 delete m_child[0];
289 m_child[0] = NULL;
290 delete m_child[1];
291 m_child[1] = NULL;
292 m_leaf = NULL;
293
294 if (m_container != m_window && m_container) {
295 m_container->SetEventHandler(m_container);
296 m_container->Destroy();
297 }
298 }
299
300 bool wxDynamicSashWindowImpl::Create() {
301 if (!m_container) {
302 m_container = m_window;
303 }
304
305 wxCursor cursor(wxCURSOR_ARROW);
306 m_container->SetCursor(cursor);
307
308 m_leaf = new wxDynamicSashWindowLeaf(this);
309 if (!m_leaf)
310 return false;
311
312 if (!m_leaf->Create()) {
313 delete m_leaf;
314 m_leaf = NULL;
315 return false;
316 }
317
318 m_container->SetEventHandler(this);
319
320 Connect(wxID_ANY, wxEVT_SIZE, (wxObjectEventFunction)
321 (wxEventFunction)
322 (wxSizeEventFunction)&wxDynamicSashWindowImpl::OnSize);
323 Connect(wxID_ANY, wxEVT_PAINT, (wxObjectEventFunction)
324 (wxEventFunction)
325 (wxPaintEventFunction)&wxDynamicSashWindowImpl::OnPaint);
326 Connect(wxID_ANY, wxEVT_MOTION, (wxObjectEventFunction)
327 (wxEventFunction)
328 (wxMouseEventFunction)&wxDynamicSashWindowImpl::OnMouseMove);
329 Connect(wxID_ANY, wxEVT_ENTER_WINDOW, (wxObjectEventFunction)
330 (wxEventFunction)
331 (wxMouseEventFunction)&wxDynamicSashWindowImpl::OnMouseMove);
332 Connect(wxID_ANY, wxEVT_LEAVE_WINDOW, (wxObjectEventFunction)
333 (wxEventFunction)
334 (wxMouseEventFunction)&wxDynamicSashWindowImpl::OnLeave);
335 Connect(wxID_ANY, wxEVT_LEFT_DOWN, (wxObjectEventFunction)
336 (wxEventFunction)
337 (wxMouseEventFunction)&wxDynamicSashWindowImpl::OnPress);
338 Connect(wxID_ANY, wxEVT_LEFT_UP, (wxObjectEventFunction)
339 (wxEventFunction)
340 (wxMouseEventFunction)&wxDynamicSashWindowImpl::OnRelease);
341
342 return true;
343 }
344
345 void wxDynamicSashWindowImpl::AddChild(wxWindow *window) {
346 if (m_add_child_target && m_add_child_target->m_leaf) {
347 m_add_child_target->m_leaf->AddChild(window);
348 }
349 }
350
351 void wxDynamicSashWindowImpl::DrawSash(int x, int y) const {
352 int i, j;
353
354 wxScreenDC dc;
355 dc.StartDrawingOnTop(m_container);
356
357 wxBitmap bmp(8, 8);
358 wxMemoryDC bdc;
359 bdc.SelectObject(bmp);
360 bdc.DrawRectangle(-1, -1, 10, 10);
361 for (i = 0; i < 8; i++) {
362 for (j = 0; j < 8; j++) {
363 if ((i + j) & 1) {
364 bdc.DrawPoint(i, j);
365 }
366 }
367 }
368
369 wxBrush brush(bmp);
370 dc.SetBrush(brush);
371 dc.SetLogicalFunction(wxXOR);
372
373 if ((m_dragging == DSR_CORNER) &&
374 (m_window->GetWindowStyle() & wxDS_DRAG_CORNER) != 0) {
375 int cx = 0;
376 int cy = 0;
377
378 m_container->ClientToScreen(&cx, &cy);
379 m_container->ClientToScreen(&x, &y);
380
381 if (cx < x && cy < y) {
382 dc.DrawRectangle(cx - 2, cy - 2, x - cx + 4, 4);
383 dc.DrawRectangle(x - 2, cy + 2, 4, y - cy);
384 dc.DrawRectangle(cx - 2, cy + 2, 4, y - cy);
385 dc.DrawRectangle(cx + 2, y - 2, x - cx - 4, 4);
386 }
387 } else {
388 int body_w, body_h;
389 m_container->GetClientSize(&body_w, &body_h);
390
391 if (y < 0)
392 y = 0;
393 if (y > body_h)
394 y = body_h;
395 if (x < 0)
396 x = 0;
397 if (x > body_w)
398 x = body_w;
399
400 if (m_dragging == DSR_HORIZONTAL_TAB)
401 x = 0;
402 else
403 y = 0;
404
405 m_container->ClientToScreen(&x, &y);
406
407 int w, h;
408 w = body_w; h = body_h;
409
410 if (m_dragging == DSR_HORIZONTAL_TAB)
411 dc.DrawRectangle(x, y - 2, w, 4);
412 else
413 dc.DrawRectangle(x - 2, y, 4, h);
414 }
415
416 dc.EndDrawingOnTop();
417 }
418
419 wxDynamicSashWindowImpl *wxDynamicSashWindowImpl::FindParent(DynamicSashRegion side) const {
420 if (m_parent == NULL) {
421 return NULL;
422 }
423
424 if (m_parent->m_split == DSR_HORIZONTAL_TAB) {
425 if (side == DSR_TOP_EDGE && m_parent->m_child[1] == this)
426 return m_parent;
427 if (side == DSR_BOTTOM_EDGE && m_parent->m_child[0] == this)
428 return m_parent;
429 } else if (m_parent->m_split == DSR_VERTICAL_TAB) {
430 if (side == DSR_LEFT_EDGE && m_parent->m_child[1] == this)
431 return m_parent;
432 if (side == DSR_RIGHT_EDGE && m_parent->m_child[0] == this)
433 return m_parent;
434 }
435
436 return m_parent->FindParent(side);
437 }
438
439 wxDynamicSashWindowImpl *wxDynamicSashWindowImpl::FindUpperParent(wxDynamicSashWindowImpl *sash_a,
440 wxDynamicSashWindowImpl *sash_b) const {
441 wxWindow *win;
442 win = sash_a->m_container->GetParent();
443 while (win && !win->IsTopLevel()) {
444 if (win == sash_b->m_container) {
445 return sash_b;
446 }
447
448 win = win->GetParent();
449 }
450
451 return sash_a;
452 }
453
454
455 wxWindow *wxDynamicSashWindowImpl::FindFrame() const {
456 wxWindow *win;
457
458 win = m_window->GetParent();
459 while (win && !win->IsTopLevel()
460 #ifdef __WXMSW__
461 && ! wxIsKindOf(win, wxMDIChildFrame) // not top-level but still a frame
462 #endif
463 ) {
464 win = win->GetParent();
465 }
466
467 return win;
468 }
469
470 wxScrollBar *wxDynamicSashWindowImpl::FindScrollBar(const wxWindow *child, int vert) const {
471 if (m_child[0] == NULL && m_leaf == NULL) {
472 return NULL;
473 }
474
475 if (!m_child[0]) {
476 return m_leaf->FindScrollBar(child, vert);
477 } else {
478 wxScrollBar *ret = m_child[0]->FindScrollBar(child, vert);
479 if (!ret) {
480 ret = m_child[1]->FindScrollBar(child, vert);
481 }
482
483 return ret;
484 }
485 }
486
487 void wxDynamicSashWindowImpl::ConstrainChildren(int px, int py) {
488 wxLayoutConstraints *layout = new wxLayoutConstraints();
489 layout->left.SameAs(m_container, wxLeft);
490 layout->top.SameAs(m_container, wxTop);
491 if (m_split == DSR_HORIZONTAL_TAB) {
492 layout->right.SameAs(m_container, wxRight);
493 layout->height.PercentOf(m_container, wxHeight, py);
494 } else {
495 layout->bottom.SameAs(m_container, wxBottom);
496 layout->width.PercentOf(m_container, wxWidth, px);
497 }
498 m_child[0]->m_container->SetConstraints(layout);
499
500 layout = new wxLayoutConstraints();
501 layout->right.SameAs(m_container, wxRight);
502 layout->bottom.SameAs(m_container, wxBottom);
503 if (m_split == DSR_HORIZONTAL_TAB) {
504 layout->top.Below(m_child[0]->m_container, 1);
505 layout->left.SameAs(m_container, wxLeft);
506 } else {
507 layout->left.RightOf(m_child[0]->m_container, 1);
508 layout->top.SameAs(m_container, wxTop);
509 }
510 m_child[1]->m_container->SetConstraints(layout);
511 }
512
513 void wxDynamicSashWindowImpl::Unify(int panel) {
514 int other = 0;
515 if (panel == 0) {
516 other = 1;
517 }
518
519 if (m_child[panel]->m_leaf) {
520 wxDynamicSashWindowImpl *child[2];
521
522 child[0] = m_child[0];
523 child[1] = m_child[1];
524
525 m_child[0] = m_child[1] = NULL;
526
527 m_leaf = new wxDynamicSashWindowLeaf(this);
528 m_leaf->Create();
529 m_leaf->m_child = child[panel]->m_leaf->m_child;
530
531 m_leaf->m_vscroll->SetScrollbar(child[panel]->m_leaf->m_vscroll->GetThumbPosition(),
532 child[panel]->m_leaf->m_vscroll->GetThumbSize(),
533 child[panel]->m_leaf->m_vscroll->GetRange(),
534 child[panel]->m_leaf->m_vscroll->GetPageSize());
535 m_leaf->m_hscroll->SetScrollbar(child[panel]->m_leaf->m_hscroll->GetThumbPosition(),
536 child[panel]->m_leaf->m_hscroll->GetThumbSize(),
537 child[panel]->m_leaf->m_hscroll->GetRange(),
538 child[panel]->m_leaf->m_hscroll->GetPageSize());
539 m_add_child_target = NULL;
540 wxDynamicSashReparentEvent event(m_leaf);
541 m_leaf->ProcessEvent(event);
542
543 delete child[0];
544 delete child[1];
545
546 m_split = DSR_NONE;
547
548 wxDynamicSashUnifyEvent unify(m_leaf->m_child);
549 m_leaf->m_child->ProcessEvent(unify);
550 } else {
551 m_split = m_child[panel]->m_split;
552
553 delete m_child[other];
554
555 wxDynamicSashWindowImpl *child_panel = m_child[panel];
556 m_child[0] = child_panel->m_child[0];
557 m_child[1] = child_panel->m_child[1];
558
559 m_child[0]->m_parent = this;
560 m_child[1]->m_parent = this;
561
562 m_add_child_target = NULL;
563 m_child[0]->m_container->Reparent(m_container);
564 m_child[1]->m_container->Reparent(m_container);
565
566 child_panel->m_child[0] = child_panel->m_child[1] = NULL;
567 delete child_panel;
568
569 wxSize size = m_container->GetSize();
570 wxSize child_size = m_child[0]->m_container->GetSize();
571
572 ConstrainChildren(child_size.GetWidth() * 100 / size.GetWidth(),
573 child_size.GetHeight() * 100 / size.GetHeight());
574
575 m_container->Layout();
576 }
577 }
578
579 void wxDynamicSashWindowImpl::Split(int px, int py) {
580
581 m_add_child_target = NULL;
582
583 m_child[0] = new wxDynamicSashWindowImpl(m_window);
584 m_child[0]->m_container = new wxWindow(m_container, wxID_ANY);
585 m_child[0]->m_parent = this;
586 m_child[0]->m_top = m_top;
587 m_child[0]->Create();
588 if (m_leaf->m_child) {
589 m_leaf->m_child->Reparent(m_container);
590 m_child[0]->AddChild(m_leaf->m_child);
591 }
592
593 m_child[1] = new wxDynamicSashWindowImpl(m_window);
594 m_child[1]->m_container = new wxWindow(m_container, wxID_ANY);
595 m_child[1]->m_parent = this;
596 m_child[1]->m_top = m_top;
597 m_child[1]->Create();
598
599 m_split = m_dragging;
600 ConstrainChildren(px, py);
601
602 m_top->m_add_child_target = m_child[1];
603 wxDynamicSashSplitEvent split(m_child[0]->m_leaf->m_child);
604 m_child[0]->m_leaf->m_child->ProcessEvent(split);
605
606 m_child[0]->m_leaf->m_vscroll->SetScrollbar(m_leaf->m_vscroll->GetThumbPosition(),
607 m_leaf->m_vscroll->GetThumbSize(),
608 m_leaf->m_vscroll->GetRange(),
609 m_leaf->m_vscroll->GetPageSize());
610 m_child[0]->m_leaf->m_hscroll->SetScrollbar(m_leaf->m_hscroll->GetThumbPosition(),
611 m_leaf->m_hscroll->GetThumbSize(),
612 m_leaf->m_hscroll->GetRange(),
613 m_leaf->m_hscroll->GetPageSize());
614 m_child[1]->m_leaf->m_vscroll->SetScrollbar(m_leaf->m_vscroll->GetThumbPosition(),
615 m_leaf->m_vscroll->GetThumbSize(),
616 m_leaf->m_vscroll->GetRange(),
617 m_leaf->m_vscroll->GetPageSize());
618 m_child[1]->m_leaf->m_hscroll->SetScrollbar(m_leaf->m_hscroll->GetThumbPosition(),
619 m_leaf->m_hscroll->GetThumbSize(),
620 m_leaf->m_hscroll->GetRange(),
621 m_leaf->m_hscroll->GetPageSize());
622 delete m_leaf;
623 m_leaf = NULL;
624
625 m_container->Layout();
626 }
627
628
629 /* This code is called when you finish resizing a view by dragging the
630 corner tab, but I think this implementation is lousy and will surprise
631 the user more often than it will do what they are trying to do. What
632 I really need to be doing here is do a rewrite such that *no* sashes
633 move except the ones immediately to the bottom and right of this window,
634 and handle the case where you resize a window larger than it's neighbors
635 by destroying the neighbors.
636
637 But this will do for now. */
638 void wxDynamicSashWindowImpl::Resize(int x, int y) {
639 wxDynamicSashWindowImpl *h_parent = FindParent(DSR_BOTTOM_EDGE);
640 wxDynamicSashWindowImpl *v_parent = FindParent(DSR_RIGHT_EDGE);
641 int h_unify = -1;
642 int v_unify = -1;
643 wxWindow *frame = FindFrame();
644
645 if (x < 0) {
646 x = 0;
647 }
648 if (y < 0) {
649 y = 0;
650 }
651
652 if (h_parent) {
653 m_container->ClientToScreen(NULL, &y);
654 h_parent->m_container->ScreenToClient(NULL, &y);
655
656 int py = (int)((y * 100) / h_parent->m_container->GetSize().GetHeight() + 0.5);
657
658 if (py < 10) {
659 wxDynamicSashWindowImpl *ho_parent = FindParent(DSR_TOP_EDGE);
660
661 if (ho_parent) {
662 if (FindUpperParent(h_parent, ho_parent) == ho_parent) {
663 h_unify = 1;
664 } else {
665 py = (int)((ho_parent->m_child[0]->m_container->GetSize().GetHeight() * 100)
666 / h_parent->m_container->GetSize().GetHeight() + 0.5);
667 h_parent->m_child[0]->m_container->GetConstraints()->height.PercentOf(
668 h_parent->m_container, wxHeight, py);
669
670 h_parent = ho_parent;
671 h_unify = 0;
672 }
673 } else {
674 h_unify = 1;
675 }
676 } else if (py > 90) {
677 h_unify = 0;
678 } else {
679 h_parent->m_child[0]->m_container->GetConstraints()->height.PercentOf(
680 h_parent->m_container, wxHeight, py);
681 h_parent->m_container->Layout();
682 }
683 } else {
684 int do_resize = 1;
685 h_parent = FindParent(DSR_TOP_EDGE);
686
687 if (h_parent) {
688 int py = (int)((y * 100) /
689 (h_parent->m_container->GetSize().GetHeight() +
690 y - m_container->GetSize().GetHeight()) + 0.5);
691
692 if (py < 10) {
693 h_unify = 0;
694 }
695 } else if (y < 64) {
696 do_resize = 0;
697 }
698
699 if (do_resize) {
700 wxSize size = frame->GetSize();
701 frame->SetSize(size.GetWidth(), size.GetHeight() + y - m_container->GetSize().GetHeight());
702 }
703 }
704
705 if (v_parent) {
706 m_container->ClientToScreen(&x, NULL);
707 v_parent->m_container->ScreenToClient(&x, NULL);
708
709 int px = (int)((x * 100) / v_parent->m_container->GetSize().GetWidth() + 0.5);
710
711 if (px < 10) {
712 wxDynamicSashWindowImpl *vo_parent = FindParent(DSR_LEFT_EDGE);
713
714 if (vo_parent) {
715 if (FindUpperParent(v_parent, vo_parent) == vo_parent) {
716 v_unify = 1;
717 } else {
718 px = (int)((vo_parent->m_child[0]->m_container->GetSize().GetWidth() * 100)
719 / v_parent->m_container->GetSize().GetWidth() + 0.5);
720 v_parent->m_child[0]->m_container->GetConstraints()->width.PercentOf(
721 v_parent->m_container, wxWidth, px);
722
723 v_parent = vo_parent;
724 v_unify = 0;
725 }
726 } else {
727 v_unify = 1;
728 }
729 } else if (px > 90) {
730 v_unify = 0;
731 } else {
732 v_parent->m_child[0]->m_container->GetConstraints()->width.PercentOf(
733 v_parent->m_container, wxWidth, px);
734 v_parent->m_container->Layout();
735 }
736 } else {
737 int do_resize = 1;
738 v_parent = FindParent(DSR_LEFT_EDGE);
739
740 if (v_parent) {
741 int px = (int)((x * 100) /
742 (v_parent->m_container->GetSize().GetWidth() +
743 x - m_container->GetSize().GetWidth()) + 0.5);
744
745 if (px < 10) {
746 v_unify = 0;
747 }
748 } else if (x < 64) {
749 do_resize = 0;
750 }
751
752 if (do_resize) {
753 wxSize size = frame->GetSize();
754 frame->SetSize(size.GetWidth() + x - m_container->GetSize().GetWidth(), size.GetHeight());
755 }
756 }
757
758 if (h_unify != -1 && v_unify != -1) {
759 wxDynamicSashWindowImpl *parent = FindUpperParent(h_parent, v_parent);
760
761 if (parent == h_parent) {
762 h_parent->Unify(h_unify);
763 } else {
764 v_parent->Unify(v_unify);
765 }
766 } else if (h_unify != -1) {
767 h_parent->Unify(h_unify);
768 } else if (v_unify != -1) {
769 v_parent->Unify(v_unify);
770 }
771 }
772
773
774 void wxDynamicSashWindowImpl::OnSize(wxSizeEvent &event) {
775 m_container->Layout();
776
777 if (m_leaf)
778 m_leaf->OnSize(event);
779 }
780
781 void wxDynamicSashWindowImpl::OnPaint(wxPaintEvent &event) {
782 if (m_leaf)
783 m_leaf->OnPaint(event);
784 else {
785 wxPaintDC dc(m_container);
786 dc.SetBackground(wxBrush(m_container->GetBackgroundColour(), wxSOLID));
787 dc.Clear();
788 }
789 }
790
791 void wxDynamicSashWindowImpl::OnMouseMove(wxMouseEvent &event) {
792 if (m_dragging) {
793 DrawSash(m_drag_x, m_drag_y);
794 m_drag_x = event.m_x; m_drag_y = event.m_y;
795 DrawSash(m_drag_x, m_drag_y);
796 } else if (m_leaf) {
797 m_leaf->OnMouseMove(event);
798 }
799 }
800
801 void wxDynamicSashWindowImpl::OnLeave(wxMouseEvent &event) {
802 if (m_leaf) {
803 m_leaf->OnLeave(event);
804 }
805 }
806
807 void wxDynamicSashWindowImpl::OnPress(wxMouseEvent &event) {
808 if (m_leaf) {
809 m_leaf->OnPress(event);
810 } else {
811 m_dragging = m_split;
812 m_drag_x = event.m_x;
813 m_drag_y = event.m_y;
814 DrawSash(m_drag_x, m_drag_y);
815 m_container->CaptureMouse();
816 }
817 }
818
819 void wxDynamicSashWindowImpl::OnRelease(wxMouseEvent &event) {
820 if ((m_dragging == DSR_CORNER) &&
821 (m_window->GetWindowStyle() & wxDS_DRAG_CORNER) != 0) {
822 DrawSash(m_drag_x, m_drag_y);
823 m_container->ReleaseMouse();
824
825 Resize(event.m_x, event.m_y);
826
827 m_dragging = DSR_NONE;
828 } else if (m_dragging) {
829 DrawSash(m_drag_x, m_drag_y);
830 m_container->ReleaseMouse();
831
832 wxSize size = m_container->GetSize();
833 int px = (int)((event.m_x * 100) / size.GetWidth() + 0.5);
834 int py = (int)((event.m_y * 100) / size.GetHeight() + 0.5);
835
836 if ((m_dragging == DSR_HORIZONTAL_TAB && py >= 10 && py <= 90)
837 || (m_dragging == DSR_VERTICAL_TAB && px >= 10 && px <= 90)) {
838 if (m_child[0] == NULL) {
839 Split(px, py);
840 } else {
841 /* It would be nice if moving *this* sash didn't implicitly move
842 the sashes of our children (if any). But this will do. */
843 wxLayoutConstraints *layout = m_child[0]->m_container->GetConstraints();
844 if (m_split == DSR_HORIZONTAL_TAB) {
845 layout->height.PercentOf(m_container, wxHeight, py);
846 } else {
847 layout->width.PercentOf(m_container, wxWidth, px);
848 }
849 m_container->Layout();
850 }
851 } else {
852 if (m_child[0] != NULL) {
853 if ((m_dragging == DSR_HORIZONTAL_TAB && py <= 10)
854 || (m_dragging == DSR_VERTICAL_TAB && px <= 10)) {
855 Unify(1);
856 } else {
857 Unify(0);
858 }
859 }
860 }
861
862 wxCursor cursor(wxCURSOR_ARROW);
863 if (m_split == DSR_HORIZONTAL_TAB) {
864 cursor = wxCursor(wxCURSOR_SIZENS);
865 } else if (m_split == DSR_VERTICAL_TAB) {
866 cursor = wxCursor(wxCURSOR_SIZEWE);
867 }
868 m_container->SetCursor(cursor);
869
870 m_dragging = DSR_NONE;
871 } else if (m_leaf) {
872 m_leaf->OnRelease(event);
873 }
874 }
875
876 // wxDynamicSashWindowLeaf //////////////////////////////////////////////////
877
878 wxDynamicSashWindowLeaf::wxDynamicSashWindowLeaf(wxDynamicSashWindowImpl *impl) {
879 m_impl = impl;
880
881 m_hscroll = m_vscroll = NULL;
882 m_child = NULL;
883 }
884
885 wxDynamicSashWindowLeaf::~wxDynamicSashWindowLeaf() {
886 m_hscroll->SetEventHandler(m_hscroll);
887 m_vscroll->SetEventHandler(m_vscroll);
888 m_viewport->SetEventHandler(m_viewport);
889
890 m_hscroll->Destroy();
891 m_vscroll->Destroy();
892 m_viewport->Destroy();
893 }
894
895 bool wxDynamicSashWindowLeaf::Create() {
896 bool success;
897
898 m_hscroll = new wxScrollBar();
899 m_vscroll = new wxScrollBar();
900 m_viewport = new wxWindow();
901
902 if (!m_hscroll || !m_vscroll || !m_viewport) {
903 return false;
904 }
905
906 wxDynamicSashWindowImpl *add_child_target = m_impl->m_add_child_target;
907 m_impl->m_add_child_target = NULL;
908 success = m_hscroll->Create(m_impl->m_container, wxID_ANY, wxDefaultPosition, wxDefaultSize,
909 wxSB_HORIZONTAL);
910 success = success && m_vscroll->Create(m_impl->m_container, wxID_ANY, wxDefaultPosition, wxDefaultSize,
911 wxSB_VERTICAL);
912 success = success && m_viewport->Create(m_impl->m_container, wxID_ANY);
913 m_impl->m_add_child_target = add_child_target;
914
915 wxCursor cursor(wxCURSOR_ARROW);
916 m_hscroll->SetCursor(cursor);
917 m_vscroll->SetCursor(cursor);
918 m_viewport->SetCursor(cursor);
919
920 m_viewport->SetEventHandler(this);
921 Connect(wxID_ANY, wxEVT_DYNAMIC_SASH_REPARENT, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnReparent);
922
923 if (m_impl->m_window->GetWindowStyle() & wxDS_MANAGE_SCROLLBARS) {
924 m_hscroll->SetEventHandler(this);
925 m_vscroll->SetEventHandler(this);
926
927 Connect(wxID_ANY, wxEVT_SET_FOCUS, (wxObjectEventFunction)
928 (wxEventFunction)
929 (wxFocusEventFunction)&wxDynamicSashWindowLeaf::OnFocus);
930 Connect(wxID_ANY, wxEVT_SCROLL_TOP, (wxObjectEventFunction)
931 (wxEventFunction)
932 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
933 Connect(wxID_ANY, wxEVT_SCROLL_BOTTOM, (wxObjectEventFunction)
934 (wxEventFunction)
935 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
936 Connect(wxID_ANY, wxEVT_SCROLL_LINEUP, (wxObjectEventFunction)
937 (wxEventFunction)
938 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
939 Connect(wxID_ANY, wxEVT_SCROLL_LINEDOWN, (wxObjectEventFunction)
940 (wxEventFunction)
941 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
942 Connect(wxID_ANY, wxEVT_SCROLL_PAGEUP, (wxObjectEventFunction)
943 (wxEventFunction)
944 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
945 Connect(wxID_ANY, wxEVT_SCROLL_PAGEDOWN, (wxObjectEventFunction)
946 (wxEventFunction)
947 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
948 Connect(wxID_ANY, wxEVT_SCROLL_THUMBTRACK, (wxObjectEventFunction)
949 (wxEventFunction)
950 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
951 Connect(wxID_ANY, wxEVT_SCROLL_THUMBRELEASE, (wxObjectEventFunction)
952 (wxEventFunction)
953 (wxScrollEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
954 }
955
956 wxLayoutConstraints *layout = new wxLayoutConstraints();
957 if (!layout)
958 return false;
959 wxSize size = m_hscroll->GetBestSize();
960 #ifdef __WXMSW__
961 size = m_hscroll->GetSize();
962 #endif
963
964 layout->left.SameAs(m_impl->m_container, wxLeft, 10);
965 layout->right.LeftOf(m_vscroll);
966 layout->bottom.SameAs(m_impl->m_container, wxBottom, 3);
967 layout->height.Absolute(size.GetHeight());
968 m_hscroll->SetConstraints(layout);
969
970 layout = new wxLayoutConstraints();
971 if (!layout)
972 return false;
973 size = size = m_vscroll->GetBestSize();
974 #ifdef __WXMSW__
975 size = m_vscroll->GetSize();
976 #endif
977
978 layout->top.SameAs(m_impl->m_container, wxTop, 10);
979 layout->bottom.Above(m_hscroll);
980 layout->right.SameAs(m_impl->m_container, wxRight, 3);
981 layout->width.Absolute(size.GetWidth());
982 m_vscroll->SetConstraints(layout);
983
984 layout = new wxLayoutConstraints();
985 if (!layout)
986 return false;
987 layout->left.SameAs(m_impl->m_container, wxLeft, 3);
988 layout->right.LeftOf(m_vscroll);
989 layout->top.SameAs(m_impl->m_container, wxTop, 3);
990 layout->bottom.Above(m_hscroll);
991 m_viewport->SetConstraints(layout);
992
993 m_impl->m_container->Layout();
994
995 return success;
996 }
997
998 void wxDynamicSashWindowLeaf::AddChild(wxWindow *window) {
999 if (m_child) {
1000 m_child->Destroy();
1001 }
1002
1003 m_child = window;
1004
1005 wxDynamicSashReparentEvent event(this);
1006 AddPendingEvent(event);
1007 }
1008
1009 DynamicSashRegion wxDynamicSashWindowLeaf::GetRegion(int x, int y) {
1010 wxSize size = m_impl->m_container->GetSize();
1011 int w = size.GetWidth();
1012 int h = size.GetHeight();
1013 size = m_hscroll->GetSize();
1014 int sh = size.GetHeight();
1015 size = m_vscroll->GetSize();
1016 int sw = size.GetWidth();
1017
1018 if (x >= w - sw - 3 && x < w && y >= h - sh - 3 && y < h)
1019 return DSR_CORNER;
1020 if (x >= 3 && x < 10 && y >= h - sh - 3 && y < h - 2)
1021 return DSR_VERTICAL_TAB;
1022 if (x >= w - sw - 3 && x < w - 2 && y >= 3 && y < 10)
1023 return DSR_HORIZONTAL_TAB;
1024 if (x < 3)
1025 return DSR_LEFT_EDGE;
1026 if (y < 3)
1027 return DSR_TOP_EDGE;
1028 if (x >= w - 2)
1029 return DSR_RIGHT_EDGE;
1030 if (y >= h - 2)
1031 return DSR_BOTTOM_EDGE;
1032
1033 return DSR_NONE;
1034 }
1035
1036 void wxDynamicSashWindowLeaf::ResizeChild(wxSize size) {
1037 if (m_child) {
1038 if (m_impl->m_window->GetWindowStyle() & wxDS_MANAGE_SCROLLBARS) {
1039 m_child->SetSize(size);
1040 wxSize best_size = m_child->GetBestSize();
1041 if (best_size.GetWidth() < size.GetWidth()) {
1042 best_size.SetWidth(size.GetWidth());
1043 }
1044 if (best_size.GetHeight() < size.GetHeight()) {
1045 best_size.SetHeight(size.GetHeight());
1046 }
1047 m_child->SetSize(best_size);
1048
1049 int hpos = m_hscroll->GetThumbPosition();
1050 int vpos = m_vscroll->GetThumbPosition();
1051
1052 if (hpos < 0) {
1053 hpos = 0;
1054 }
1055 if (vpos < 0) {
1056 vpos = 0;
1057 }
1058 if (hpos > best_size.GetWidth() - size.GetWidth()) {
1059 hpos = best_size.GetWidth() - size.GetWidth();
1060 }
1061 if (vpos > best_size.GetHeight() - size.GetHeight()) {
1062 vpos = best_size.GetHeight() - size.GetHeight();
1063 }
1064
1065 m_hscroll->SetScrollbar(hpos, size.GetWidth(),
1066 best_size.GetWidth(), size.GetWidth());
1067 m_vscroll->SetScrollbar(vpos, size.GetHeight(),
1068 best_size.GetHeight(), size.GetHeight());
1069
1070 // Umm, the scrollbars are doing something insane under GTK+ and subtracting
1071 // one from the position I pass in. This works around that.
1072 m_hscroll->SetThumbPosition(hpos + hpos - m_hscroll->GetThumbPosition());
1073 m_vscroll->SetThumbPosition(vpos + vpos - m_vscroll->GetThumbPosition());
1074
1075 wxPoint pos = m_child->GetPosition();
1076 m_viewport->ScrollWindow(-hpos - pos.x, -vpos - pos.y);
1077 } else {
1078 m_child->SetSize(size);
1079 }
1080 }
1081 }
1082
1083 wxScrollBar *wxDynamicSashWindowLeaf::FindScrollBar(const wxWindow *child, int vert) const {
1084 if (m_child == child) {
1085 if (vert) {
1086 return m_vscroll;
1087 } else {
1088 return m_hscroll;
1089 }
1090 }
1091
1092 return NULL;
1093 }
1094
1095 void wxDynamicSashWindowLeaf::OnSize(wxSizeEvent &WXUNUSED(event)) {
1096 m_impl->m_container->Refresh();
1097 ResizeChild(m_viewport->GetSize());
1098 }
1099
1100 void wxDynamicSashWindowLeaf::OnPaint(wxPaintEvent &WXUNUSED(event)) {
1101 wxPaintDC dc(m_impl->m_container);
1102 dc.SetBackground(wxBrush(m_impl->m_container->GetBackgroundColour(), wxSOLID));
1103 dc.Clear();
1104
1105 wxPen highlight(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT), 1, wxSOLID);
1106 wxPen shadow(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW), 1, wxSOLID);
1107 wxPen black(*wxBLACK, 1, wxSOLID);
1108
1109 wxSize size = m_impl->m_container->GetSize();
1110 int w = size.GetWidth();
1111 int h = size.GetHeight();
1112 size = m_hscroll->GetSize();
1113 int sh = size.GetHeight();
1114 size = m_vscroll->GetSize();
1115 int sw = size.GetWidth();
1116
1117 dc.SetPen(shadow);
1118 dc.DrawLine(1, 1, 1, h - 2);
1119 dc.DrawLine(1, 1, w - 2, 1);
1120 dc.SetPen(black);
1121 dc.DrawLine(2, 2, 2, h - 3);
1122 dc.DrawLine(2, 2, w - 3, 2);
1123 dc.SetPen(highlight);
1124 dc.DrawLine(w - 2, 2, w - 2, h - sh - 2);
1125 dc.DrawLine(w - 2, h - sh - 2, w - sw - 2, h - sh - 2);
1126 dc.DrawLine(w - sw - 2, h - sh - 2, w - sw - 2, h - 2);
1127 dc.DrawLine(w - sw - 2, h - 2, 2, h - 2);
1128
1129 dc.SetPen(highlight);
1130 dc.DrawLine(w - sw - 2, 8, w - sw - 2, 4);
1131 dc.DrawLine(w - sw - 2, 4, w - 5, 4);
1132 dc.SetPen(shadow);
1133 dc.DrawLine(w - 5, 4, w - 5, 8);
1134 dc.DrawLine(w - 5, 8, w - sw - 2, 8);
1135 dc.SetPen(black);
1136 dc.DrawLine(w - 4, 3, w - 4, 9);
1137 dc.DrawLine(w - 4, 9, w - sw - 3, 9);
1138
1139 dc.SetPen(highlight);
1140 dc.DrawLine(4, h - 5, 4, h - sh - 2);
1141 dc.DrawLine(4, h - sh - 2, 8, h - sh - 2);
1142 dc.SetPen(shadow);
1143 dc.DrawLine(8, h - sh - 2, 8, h - 5);
1144 dc.DrawLine(8, h - 5, 4, h - 5);
1145 dc.SetPen(black);
1146 dc.DrawLine(9, h - sh - 3, 9, h - 4);
1147 dc.DrawLine(9, h - 4, 3, h - 4);
1148
1149 int cy = (h - sh + h - 6) / 2 + 1;
1150 int cx = (w - sw + w - 6) / 2 + 1;
1151 int sy = cy;
1152 while (sy > h - sh)
1153 sy -= 4;
1154 int sx = cx;
1155 while (sx > w - sw)
1156 sx -= 4;
1157
1158 int x, y;
1159 for (y = sy; y < h - 2; y += 4) {
1160 for (x = sx; x < w - 2; x += 4) {
1161 if (x - cx >= -(y - cy)) {
1162 dc.SetPen(highlight);
1163 dc.DrawPoint(x, y);
1164 dc.SetPen(shadow);
1165 dc.DrawPoint(x + 1, y + 1);
1166 }
1167 }
1168 }
1169 }
1170
1171 void wxDynamicSashWindowLeaf::OnScroll(wxScrollEvent &WXUNUSED(event)) {
1172 int nx = -m_hscroll->GetThumbPosition();
1173 int ny = -m_vscroll->GetThumbPosition();
1174
1175 if (m_child) {
1176 wxPoint pos = m_child->GetPosition();
1177
1178 m_viewport->ScrollWindow(nx - pos.x, ny - pos.y);
1179 }
1180 }
1181
1182 void wxDynamicSashWindowLeaf::OnFocus(wxFocusEvent &event) {
1183 if (event.GetEventObject() == m_hscroll || event.GetEventObject() == m_vscroll) {
1184 m_child->SetFocus();
1185 }
1186 }
1187
1188
1189 void wxDynamicSashWindowLeaf::OnMouseMove(wxMouseEvent &event) {
1190 if (m_impl->m_dragging) {
1191 return;
1192 }
1193
1194 DynamicSashRegion region = GetRegion(event.m_x, event.m_y);
1195
1196 wxCursor cursor(wxCURSOR_ARROW);
1197 if (region == DSR_HORIZONTAL_TAB) {
1198 cursor = wxCursor(wxCURSOR_SIZENS);
1199 } else if (region == DSR_VERTICAL_TAB) {
1200 cursor = wxCursor(wxCURSOR_SIZEWE);
1201 } else if ((region == DSR_CORNER) &&
1202 (m_impl->m_window->GetWindowStyle() & wxDS_DRAG_CORNER) != 0) {
1203 cursor = wxCursor(wxCURSOR_SIZENWSE);
1204 } else if (region == DSR_LEFT_EDGE || region == DSR_TOP_EDGE
1205 || region == DSR_RIGHT_EDGE || region == DSR_BOTTOM_EDGE) {
1206 if (m_impl->FindParent(region)) {
1207 if (region == DSR_LEFT_EDGE || region == DSR_RIGHT_EDGE) {
1208 cursor = wxCursor(wxCURSOR_SIZEWE);
1209 } else {
1210 cursor = wxCursor(wxCURSOR_SIZENS);
1211 }
1212 }
1213 }
1214
1215 m_impl->m_container->SetCursor(cursor);
1216 }
1217
1218 void wxDynamicSashWindowLeaf::OnLeave(wxMouseEvent &WXUNUSED(event)) {
1219 wxCursor cursor(wxCURSOR_ARROW);
1220 m_impl->m_container->SetCursor(cursor);
1221 }
1222
1223
1224 void wxDynamicSashWindowLeaf::OnPress(wxMouseEvent &event) {
1225 DynamicSashRegion region = GetRegion(event.m_x, event.m_y);
1226
1227 if ((region == DSR_CORNER) && (m_impl->m_window->GetWindowStyle() & wxDS_DRAG_CORNER) == 0)
1228 return;
1229
1230 if (region == DSR_HORIZONTAL_TAB || region == DSR_VERTICAL_TAB || region == DSR_CORNER) {
1231 m_impl->m_dragging = region;
1232 m_impl->m_drag_x = event.m_x;
1233 m_impl->m_drag_y = event.m_y;
1234 m_impl->DrawSash(event.m_x, event.m_y);
1235 m_impl->m_container->CaptureMouse();
1236 } else if (region == DSR_LEFT_EDGE || region == DSR_TOP_EDGE
1237 || region == DSR_RIGHT_EDGE || region == DSR_BOTTOM_EDGE) {
1238 wxDynamicSashWindowImpl *parent = m_impl->FindParent(region);
1239
1240 if (parent) {
1241 int x = event.m_x;
1242 int y = event.m_y;
1243
1244 m_impl->m_container->ClientToScreen(&x, &y);
1245 parent->m_container->ScreenToClient(&x, &y);
1246
1247 parent->m_dragging = parent->m_split;
1248 parent->m_drag_x = x;
1249 parent->m_drag_y = y;
1250 parent->DrawSash(x, y);
1251 parent->m_container->CaptureMouse();
1252 }
1253 }
1254 }
1255
1256 void wxDynamicSashWindowLeaf::OnRelease(wxMouseEvent &WXUNUSED(event)) {
1257 }
1258
1259 void wxDynamicSashWindowLeaf::OnReparent(wxEvent &WXUNUSED(event)) {
1260 if (m_child) {
1261 m_child->Reparent(m_viewport);
1262 }
1263
1264 ResizeChild(m_viewport->GetSize());
1265 }
1266
1267 // wxDynamicSashSplitEvent //////////////////////////////////////////////////
1268
1269 wxDynamicSashSplitEvent::wxDynamicSashSplitEvent() {
1270 m_eventObject = NULL;
1271 m_eventType = wxEVT_DYNAMIC_SASH_SPLIT;
1272 }
1273
1274 wxDynamicSashSplitEvent::wxDynamicSashSplitEvent(wxObject *object) {
1275 m_eventObject = object;
1276 m_eventType = wxEVT_DYNAMIC_SASH_SPLIT;
1277 }
1278
1279 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashSplitEvent, wxCommandEvent)
1280
1281 // wxDynamicSashUnifyEvent //////////////////////////////////////////////////
1282
1283 wxDynamicSashUnifyEvent::wxDynamicSashUnifyEvent() {
1284 m_eventObject = NULL;
1285 m_eventType = wxEVT_DYNAMIC_SASH_UNIFY;
1286 }
1287
1288 wxDynamicSashUnifyEvent::wxDynamicSashUnifyEvent(wxObject *object) {
1289 m_eventObject = object;
1290 m_eventType = wxEVT_DYNAMIC_SASH_UNIFY;
1291 }
1292
1293 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashUnifyEvent, wxCommandEvent)
1294
1295 // wxDynamicSsahReparentEvent ///////////////////////////////////////////////
1296
1297 wxDynamicSashReparentEvent::wxDynamicSashReparentEvent() {
1298 m_eventObject = NULL;
1299 m_eventType = wxEVT_DYNAMIC_SASH_REPARENT;
1300 }
1301
1302 wxDynamicSashReparentEvent::wxDynamicSashReparentEvent(wxObject *object) {
1303 m_eventObject = object;
1304 m_eventType = wxEVT_DYNAMIC_SASH_REPARENT;
1305 }
1306
1307 wxDynamicSashReparentEvent::wxDynamicSashReparentEvent(const wxDynamicSashReparentEvent& evt)
1308 : wxEvent(evt)
1309 {
1310 }
1311
1312 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashReparentEvent, wxEvent)
1313
1314 /////////////////////////////////////////////////////////////////////////////