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