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