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