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