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