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