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