]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/gizmos/dynamicsash.cpp
98bc41207e84d78b311334ddf1f9d0f30671e9dd
[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 wxDynamicSashReparentEvent(const wxDynamicSashReparentEvent& evt);
87
88 virtual wxEvent* Clone() const { return new wxDynamicSashReparentEvent(*this); }
89
90 DECLARE_DYNAMIC_CLASS(wxDynamicSashReparentEvent);
91 };
92
93
94 enum DynamicSashRegion {
95 DSR_NONE,
96 DSR_VERTICAL_TAB,
97 DSR_HORIZONTAL_TAB,
98 DSR_CORNER,
99 DSR_LEFT_EDGE,
100 DSR_TOP_EDGE,
101 DSR_RIGHT_EDGE,
102 DSR_BOTTOM_EDGE
103 };
104
105
106 class wxDynamicSashWindowImpl : public wxEvtHandler {
107 public:
108 wxDynamicSashWindowImpl(wxDynamicSashWindow *window);
109 ~wxDynamicSashWindowImpl();
110
111 bool Create();
112 void AddChild(wxWindow *window);
113 void DrawSash(int x, int y) const;
114 void ConstrainChildren(int px, int py);
115 void Split(int x, int y);
116 void Unify(int panel);
117 void Resize(int x, int y);
118 wxDynamicSashWindowImpl *FindParent(DynamicSashRegion side) const;
119 wxDynamicSashWindowImpl *FindUpperParent(wxDynamicSashWindowImpl *sash_a,
120 wxDynamicSashWindowImpl *sash_b) const;
121 wxWindow *FindFrame() const;
122 wxScrollBar *FindScrollBar(const wxWindow *child, int vert) const;
123
124 void OnSize(wxSizeEvent &event);
125 void OnPaint(wxPaintEvent &event);
126 void OnMouseMove(wxMouseEvent &event);
127 void OnLeave(wxMouseEvent &event);
128 void OnPress(wxMouseEvent &event);
129 void OnRelease(wxMouseEvent &event);
130
131 wxDynamicSashWindow *m_window;
132 wxDynamicSashWindowImpl *m_add_child_target;
133
134 /* This is the window we are responsible for managing. Either of
135 leaf or our children are in this window. For the top level
136 implementation object, this is the same as m_window.
137 Otherwise it is a window we've created an will destroy when we
138 are deleted. */
139 wxWindow *m_container;
140
141 wxDynamicSashWindowImpl *m_parent;
142 wxDynamicSashWindowImpl *m_top;
143 wxDynamicSashWindowImpl *m_child[2];
144
145 class wxDynamicSashWindowLeaf *m_leaf;
146
147 /* If the implementation is split horizontally or vertically, m_split
148 is set to DSR_HORIZONTAL_TAB or DSR_VERTICAL_TAB, respectively.
149 Otherwise it is set to DSR_NONE. */
150 DynamicSashRegion m_split;
151
152 /* These are used to keep track of a sash as it is being dragged, for
153 drawing the user interface correctly. */
154 DynamicSashRegion m_dragging;
155 int m_drag_x, m_drag_y;
156 };
157
158 class wxDynamicSashWindowLeaf : public wxEvtHandler {
159 public:
160 wxDynamicSashWindowLeaf(wxDynamicSashWindowImpl *impl);
161 ~wxDynamicSashWindowLeaf();
162
163 bool Create();
164 void AddChild(wxWindow *window);
165 DynamicSashRegion GetRegion(int x, int y);
166 void ResizeChild(wxSize size);
167 wxScrollBar *FindScrollBar(const wxWindow *child, int vert) const;
168
169 void OnSize(wxSizeEvent &event);
170 void OnPaint(wxPaintEvent &event);
171 void OnScroll(wxScrollEvent &event);
172 void OnFocus(wxFocusEvent &event);
173 void OnMouseMove(wxMouseEvent &event);
174 void OnLeave(wxMouseEvent &event);
175 void OnPress(wxMouseEvent &event);
176 void OnRelease(wxMouseEvent &event);
177 void OnReparent(wxEvent &event);
178
179 wxDynamicSashWindowImpl *m_impl;
180
181 wxScrollBar *m_vscroll, *m_hscroll;
182
183 /* m_child is the window provided to us by the application developer.
184 m_viewport is a window we've created, and it is the immediately
185 parent of m_child. We scroll m_child by moving it around within
186 m_viewport. */
187 wxWindow *m_viewport, *m_child;
188 };
189
190 // wxDynamicSashWindow //////////////////////////////////////////////////////
191
192 wxDynamicSashWindow::wxDynamicSashWindow() {
193 m_impl = NULL;
194 }
195
196 wxDynamicSashWindow::wxDynamicSashWindow(wxWindow *parent, wxWindowID id,
197 const wxPoint& pos, const wxSize& size,
198 long style, const wxString& name) {
199 m_impl = NULL;
200 Create(parent, id, pos, size, style, name);
201 }
202
203 wxDynamicSashWindow::~wxDynamicSashWindow() {
204 SetEventHandler(this);
205 delete m_impl;
206 }
207
208 bool wxDynamicSashWindow::Create(wxWindow *parent, wxWindowID id,
209 const wxPoint& pos, const wxSize& size,
210 long style, const wxString& name) {
211 if (m_impl)
212 return FALSE;
213
214 if (!wxWindow::Create(parent, id, pos, size, style, name))
215 return FALSE;
216
217 m_impl = new wxDynamicSashWindowImpl(this);
218 if (!m_impl)
219 return FALSE;
220
221 if (!m_impl->Create()) {
222 delete m_impl;
223 m_impl = NULL;
224 return FALSE;
225 }
226
227 return TRUE;
228 }
229
230 void wxDynamicSashWindow::AddChild(wxWindowBase *child) {
231 wxWindow::AddChild(child);
232
233 m_impl->AddChild(wxDynamicCast(child, wxWindow));
234 }
235
236 wxScrollBar *wxDynamicSashWindow::GetHScrollBar(const wxWindow *child) const {
237 return m_impl->FindScrollBar(child, 0);
238 }
239
240 wxScrollBar *wxDynamicSashWindow::GetVScrollBar(const wxWindow *child) const {
241 return m_impl->FindScrollBar(child, 1);
242 }
243
244 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashWindow, wxWindow)
245
246 // wxDynamicSashWindowImpl //////////////////////////////////////////////////
247
248 wxDynamicSashWindowImpl::wxDynamicSashWindowImpl(wxDynamicSashWindow *window) {
249 m_window = window;
250 m_add_child_target = this;
251
252 m_container = NULL;
253 m_parent = NULL;
254 m_top = this;
255 m_child[0] = m_child[1] = NULL;
256 m_leaf = NULL;
257 m_dragging = DSR_NONE;
258 m_split = DSR_NONE;
259 }
260
261 wxDynamicSashWindowImpl::~wxDynamicSashWindowImpl() {
262 delete m_leaf;
263 delete m_child[0];
264 m_child[0] = NULL;
265 delete m_child[1];
266 m_child[1] = NULL;
267 m_leaf = NULL;
268
269 if (m_container != m_window && m_container) {
270 m_container->SetEventHandler(m_container);
271 m_container->Destroy();
272 }
273 }
274
275 bool wxDynamicSashWindowImpl::Create() {
276 if (!m_container) {
277 m_container = m_window;
278 }
279
280 wxCursor cursor(wxCURSOR_ARROW);
281 m_container->SetCursor(cursor);
282
283 m_leaf = new wxDynamicSashWindowLeaf(this);
284 if (!m_leaf)
285 return FALSE;
286
287 if (!m_leaf->Create()) {
288 delete m_leaf;
289 m_leaf = NULL;
290 return FALSE;
291 }
292
293 m_container->SetEventHandler(this);
294
295 Connect(-1, wxEVT_SIZE, (wxObjectEventFunction)&wxDynamicSashWindowImpl::OnSize);
296 Connect(-1, wxEVT_PAINT, (wxObjectEventFunction)&wxDynamicSashWindowImpl::OnPaint);
297 Connect(-1, wxEVT_MOTION, (wxObjectEventFunction)&wxDynamicSashWindowImpl::OnMouseMove);
298 Connect(-1, wxEVT_ENTER_WINDOW, (wxObjectEventFunction)&wxDynamicSashWindowImpl::OnMouseMove);
299 Connect(-1, wxEVT_LEAVE_WINDOW, (wxObjectEventFunction)&wxDynamicSashWindowImpl::OnLeave);
300 Connect(-1, wxEVT_LEFT_DOWN, (wxObjectEventFunction)&wxDynamicSashWindowImpl::OnPress);
301 Connect(-1, wxEVT_LEFT_UP, (wxObjectEventFunction)&wxDynamicSashWindowImpl::OnRelease);
302
303 return TRUE;
304 }
305
306 void wxDynamicSashWindowImpl::AddChild(wxWindow *window) {
307 if (m_add_child_target && m_add_child_target->m_leaf) {
308 m_add_child_target->m_leaf->AddChild(window);
309 }
310 }
311
312 void wxDynamicSashWindowImpl::DrawSash(int x, int y) const {
313 int i, j;
314
315 wxScreenDC dc;
316 dc.StartDrawingOnTop(m_container);
317
318 wxBitmap bmp(8, 8);
319 wxMemoryDC bdc;
320 bdc.SelectObject(bmp);
321 bdc.DrawRectangle(-1, -1, 10, 10);
322 for (i = 0; i < 8; i++) {
323 for (j = 0; j < 8; j++) {
324 if ((i + j) & 1) {
325 bdc.DrawPoint(i, j);
326 }
327 }
328 }
329
330 wxBrush brush(bmp);
331 dc.SetBrush(brush);
332 dc.SetLogicalFunction(wxXOR);
333
334 if ((m_dragging == DSR_CORNER) &&
335 (m_window->GetWindowStyle() & wxDS_DRAG_CORNER) != 0) {
336 int cx = 0;
337 int cy = 0;
338
339 m_container->ClientToScreen(&cx, &cy);
340 m_container->ClientToScreen(&x, &y);
341
342 if (cx < x && cy < y) {
343 dc.DrawRectangle(cx - 2, cy - 2, x - cx + 4, 4);
344 dc.DrawRectangle(x - 2, cy + 2, 4, y - cy);
345 dc.DrawRectangle(cx - 2, cy + 2, 4, y - cy);
346 dc.DrawRectangle(cx + 2, y - 2, x - cx - 4, 4);
347 }
348 } else {
349 int body_w, body_h;
350 m_container->GetClientSize(&body_w, &body_h);
351
352 if (y < 0)
353 y = 0;
354 if (y > body_h)
355 y = body_h;
356 if (x < 0)
357 x = 0;
358 if (x > body_w)
359 x = body_w;
360
361 if (m_dragging == DSR_HORIZONTAL_TAB)
362 x = 0;
363 else
364 y = 0;
365
366 m_container->ClientToScreen(&x, &y);
367
368 int w, h;
369 w = body_w; h = body_h;
370
371 if (m_dragging == DSR_HORIZONTAL_TAB)
372 dc.DrawRectangle(x, y - 2, w, 4);
373 else
374 dc.DrawRectangle(x - 2, y, 4, h);
375 }
376
377 dc.EndDrawingOnTop();
378 }
379
380 wxDynamicSashWindowImpl *wxDynamicSashWindowImpl::FindParent(DynamicSashRegion side) const {
381 if (m_parent == NULL) {
382 return NULL;
383 }
384
385 if (m_parent->m_split == DSR_HORIZONTAL_TAB) {
386 if (side == DSR_TOP_EDGE && m_parent->m_child[1] == this)
387 return m_parent;
388 if (side == DSR_BOTTOM_EDGE && m_parent->m_child[0] == this)
389 return m_parent;
390 } else if (m_parent->m_split == DSR_VERTICAL_TAB) {
391 if (side == DSR_LEFT_EDGE && m_parent->m_child[1] == this)
392 return m_parent;
393 if (side == DSR_RIGHT_EDGE && m_parent->m_child[0] == this)
394 return m_parent;
395 }
396
397 return m_parent->FindParent(side);
398 }
399
400 wxDynamicSashWindowImpl *wxDynamicSashWindowImpl::FindUpperParent(wxDynamicSashWindowImpl *sash_a,
401 wxDynamicSashWindowImpl *sash_b) const {
402 wxWindow *win;
403 win = sash_a->m_container->GetParent();
404 while (win && !win->IsTopLevel()) {
405 if (win == sash_b->m_container) {
406 return sash_b;
407 }
408
409 win = win->GetParent();
410 }
411
412 return sash_a;
413 }
414
415
416 wxWindow *wxDynamicSashWindowImpl::FindFrame() const {
417 wxWindow *win;
418
419 win = m_window->GetParent();
420 while (win && !win->IsTopLevel()) {
421 win = win->GetParent();
422 }
423
424 return win;
425 }
426
427 wxScrollBar *wxDynamicSashWindowImpl::FindScrollBar(const wxWindow *child, int vert) const {
428 if (m_child[0] == NULL && m_leaf == NULL) {
429 return NULL;
430 }
431
432 if (!m_child[0]) {
433 return m_leaf->FindScrollBar(child, vert);
434 } else {
435 wxScrollBar *ret = m_child[0]->FindScrollBar(child, vert);
436 if (!ret) {
437 ret = m_child[1]->FindScrollBar(child, vert);
438 }
439
440 return ret;
441 }
442 }
443
444 void wxDynamicSashWindowImpl::ConstrainChildren(int px, int py) {
445 wxLayoutConstraints *layout = new wxLayoutConstraints();
446 layout->left.SameAs(m_container, wxLeft);
447 layout->top.SameAs(m_container, wxTop);
448 if (m_split == DSR_HORIZONTAL_TAB) {
449 layout->right.SameAs(m_container, wxRight);
450 layout->height.PercentOf(m_container, wxHeight, py);
451 } else {
452 layout->bottom.SameAs(m_container, wxBottom);
453 layout->width.PercentOf(m_container, wxWidth, px);
454 }
455 m_child[0]->m_container->SetConstraints(layout);
456
457 layout = new wxLayoutConstraints();
458 layout->right.SameAs(m_container, wxRight);
459 layout->bottom.SameAs(m_container, wxBottom);
460 if (m_split == DSR_HORIZONTAL_TAB) {
461 layout->top.Below(m_child[0]->m_container, 1);
462 layout->left.SameAs(m_container, wxLeft);
463 } else {
464 layout->left.RightOf(m_child[0]->m_container, 1);
465 layout->top.SameAs(m_container, wxTop);
466 }
467 m_child[1]->m_container->SetConstraints(layout);
468 }
469
470 void wxDynamicSashWindowImpl::Unify(int panel) {
471 int other = 0;
472 if (panel == 0) {
473 other = 1;
474 }
475
476 if (m_child[panel]->m_leaf) {
477 wxDynamicSashWindowImpl *child[2];
478
479 child[0] = m_child[0];
480 child[1] = m_child[1];
481
482 m_child[0] = m_child[1] = NULL;
483
484 m_leaf = new wxDynamicSashWindowLeaf(this);
485 m_leaf->Create();
486 m_leaf->m_child = child[panel]->m_leaf->m_child;
487
488 m_leaf->m_vscroll->SetScrollbar(child[panel]->m_leaf->m_vscroll->GetThumbPosition(),
489 child[panel]->m_leaf->m_vscroll->GetThumbSize(),
490 child[panel]->m_leaf->m_vscroll->GetRange(),
491 child[panel]->m_leaf->m_vscroll->GetPageSize());
492 m_leaf->m_hscroll->SetScrollbar(child[panel]->m_leaf->m_hscroll->GetThumbPosition(),
493 child[panel]->m_leaf->m_hscroll->GetThumbSize(),
494 child[panel]->m_leaf->m_hscroll->GetRange(),
495 child[panel]->m_leaf->m_hscroll->GetPageSize());
496 m_add_child_target = NULL;
497 wxDynamicSashReparentEvent event(m_leaf);
498 m_leaf->ProcessEvent(event);
499
500 delete child[0];
501 delete child[1];
502
503 m_split = DSR_NONE;
504
505 wxDynamicSashUnifyEvent unify(m_leaf->m_child);
506 m_leaf->m_child->ProcessEvent(unify);
507 } else {
508 m_split = m_child[panel]->m_split;
509
510 delete m_child[other];
511
512 wxDynamicSashWindowImpl *child_panel = m_child[panel];
513 m_child[0] = child_panel->m_child[0];
514 m_child[1] = child_panel->m_child[1];
515
516 m_child[0]->m_parent = this;
517 m_child[1]->m_parent = this;
518
519 m_add_child_target = NULL;
520 m_child[0]->m_container->Reparent(m_container);
521 m_child[1]->m_container->Reparent(m_container);
522
523 child_panel->m_child[0] = child_panel->m_child[1] = NULL;
524 delete child_panel;
525
526 wxSize size = m_container->GetSize();
527 wxSize child_size = m_child[0]->m_container->GetSize();
528
529 ConstrainChildren(child_size.GetWidth() * 100 / size.GetWidth(),
530 child_size.GetHeight() * 100 / size.GetHeight());
531
532 m_container->Layout();
533 }
534 }
535
536 void wxDynamicSashWindowImpl::Split(int px, int py) {
537
538 m_add_child_target = NULL;
539
540 m_child[0] = new wxDynamicSashWindowImpl(m_window);
541 m_child[0]->m_container = new wxWindow(m_container, -1);
542 m_child[0]->m_parent = this;
543 m_child[0]->m_top = m_top;
544 m_child[0]->Create();
545 if (m_leaf->m_child) {
546 m_leaf->m_child->Reparent(m_container);
547 m_child[0]->AddChild(m_leaf->m_child);
548 }
549
550 m_child[1] = new wxDynamicSashWindowImpl(m_window);
551 m_child[1]->m_container = new wxWindow(m_container, -1);
552 m_child[1]->m_parent = this;
553 m_child[1]->m_top = m_top;
554 m_child[1]->Create();
555
556 m_split = m_dragging;
557 ConstrainChildren(px, py);
558
559 m_top->m_add_child_target = m_child[1];
560 wxDynamicSashSplitEvent split(m_child[0]->m_leaf->m_child);
561 m_child[0]->m_leaf->m_child->ProcessEvent(split);
562
563 m_child[0]->m_leaf->m_vscroll->SetScrollbar(m_leaf->m_vscroll->GetThumbPosition(),
564 m_leaf->m_vscroll->GetThumbSize(),
565 m_leaf->m_vscroll->GetRange(),
566 m_leaf->m_vscroll->GetPageSize());
567 m_child[0]->m_leaf->m_hscroll->SetScrollbar(m_leaf->m_hscroll->GetThumbPosition(),
568 m_leaf->m_hscroll->GetThumbSize(),
569 m_leaf->m_hscroll->GetRange(),
570 m_leaf->m_hscroll->GetPageSize());
571 m_child[1]->m_leaf->m_vscroll->SetScrollbar(m_leaf->m_vscroll->GetThumbPosition(),
572 m_leaf->m_vscroll->GetThumbSize(),
573 m_leaf->m_vscroll->GetRange(),
574 m_leaf->m_vscroll->GetPageSize());
575 m_child[1]->m_leaf->m_hscroll->SetScrollbar(m_leaf->m_hscroll->GetThumbPosition(),
576 m_leaf->m_hscroll->GetThumbSize(),
577 m_leaf->m_hscroll->GetRange(),
578 m_leaf->m_hscroll->GetPageSize());
579 delete m_leaf;
580 m_leaf = NULL;
581
582 m_container->Layout();
583 }
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 (m_window->GetWindowStyle() & wxDS_DRAG_CORNER) != 0) {
779 DrawSash(m_drag_x, m_drag_y);
780 m_container->ReleaseMouse();
781
782 Resize(event.m_x, event.m_y);
783
784 m_dragging = DSR_NONE;
785 } else if (m_dragging) {
786 DrawSash(m_drag_x, m_drag_y);
787 m_container->ReleaseMouse();
788
789 wxSize size = m_container->GetSize();
790 int px = (int)((event.m_x * 100) / size.GetWidth() + 0.5);
791 int py = (int)((event.m_y * 100) / size.GetHeight() + 0.5);
792
793 if ((m_dragging == DSR_HORIZONTAL_TAB && py >= 10 && py <= 90)
794 || (m_dragging == DSR_VERTICAL_TAB && px >= 10 && px <= 90)) {
795 if (m_child[0] == NULL) {
796 Split(px, py);
797 } else {
798 /* It would be nice if moving *this* sash didn't implicitly move
799 the sashes of our children (if any). But this will do. */
800 wxLayoutConstraints *layout = m_child[0]->m_container->GetConstraints();
801 if (m_split == DSR_HORIZONTAL_TAB) {
802 layout->height.PercentOf(m_container, wxHeight, py);
803 } else {
804 layout->width.PercentOf(m_container, wxWidth, px);
805 }
806 m_container->Layout();
807 }
808 } else {
809 if (m_child[0] != NULL) {
810 if ((m_dragging == DSR_HORIZONTAL_TAB && py <= 10)
811 || (m_dragging == DSR_VERTICAL_TAB && px <= 10)) {
812 Unify(1);
813 } else {
814 Unify(0);
815 }
816 }
817 }
818
819 wxCursor cursor(wxCURSOR_ARROW);
820 if (m_split == DSR_HORIZONTAL_TAB) {
821 cursor = wxCursor(wxCURSOR_SIZENS);
822 } else if (m_split == DSR_VERTICAL_TAB) {
823 cursor = wxCursor(wxCURSOR_SIZEWE);
824 }
825 m_container->SetCursor(cursor);
826
827 m_dragging = DSR_NONE;
828 } else if (m_leaf) {
829 m_leaf->OnRelease(event);
830 }
831 }
832
833 // wxDynamicSashWindowLeaf //////////////////////////////////////////////////
834
835 wxDynamicSashWindowLeaf::wxDynamicSashWindowLeaf(wxDynamicSashWindowImpl *impl) {
836 m_impl = impl;
837
838 m_hscroll = m_vscroll = NULL;
839 m_child = NULL;
840 }
841
842 wxDynamicSashWindowLeaf::~wxDynamicSashWindowLeaf() {
843 m_hscroll->SetEventHandler(m_hscroll);
844 m_vscroll->SetEventHandler(m_vscroll);
845 m_viewport->SetEventHandler(m_viewport);
846
847 m_hscroll->Destroy();
848 m_vscroll->Destroy();
849 m_viewport->Destroy();
850 }
851
852 bool wxDynamicSashWindowLeaf::Create() {
853 bool success;
854
855 m_hscroll = new wxScrollBar();
856 m_vscroll = new wxScrollBar();
857 m_viewport = new wxWindow();
858
859 if (!m_hscroll || !m_vscroll || !m_viewport) {
860 return FALSE;
861 }
862
863 wxDynamicSashWindowImpl *add_child_target = m_impl->m_add_child_target;
864 m_impl->m_add_child_target = NULL;
865 success = m_hscroll->Create(m_impl->m_container, -1, wxDefaultPosition, wxDefaultSize,
866 wxSB_HORIZONTAL);
867 success = success && m_vscroll->Create(m_impl->m_container, -1, wxDefaultPosition, wxDefaultSize,
868 wxSB_VERTICAL);
869 success = success && m_viewport->Create(m_impl->m_container, -1);
870 m_impl->m_add_child_target = add_child_target;
871
872 wxCursor cursor(wxCURSOR_ARROW);
873 m_hscroll->SetCursor(cursor);
874 m_vscroll->SetCursor(cursor);
875 m_viewport->SetCursor(cursor);
876
877 m_viewport->SetEventHandler(this);
878 Connect(-1, wxEVT_DYNAMIC_SASH_REPARENT, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnReparent);
879
880 if (m_impl->m_window->GetWindowStyle() & wxDS_MANAGE_SCROLLBARS) {
881 m_hscroll->SetEventHandler(this);
882 m_vscroll->SetEventHandler(this);
883
884 Connect(-1, wxEVT_SET_FOCUS, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnFocus);
885 Connect(-1, wxEVT_SCROLL_TOP, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
886 Connect(-1, wxEVT_SCROLL_BOTTOM, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
887 Connect(-1, wxEVT_SCROLL_LINEUP, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
888 Connect(-1, wxEVT_SCROLL_LINEDOWN, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
889 Connect(-1, wxEVT_SCROLL_PAGEUP, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
890 Connect(-1, wxEVT_SCROLL_PAGEDOWN, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
891 Connect(-1, wxEVT_SCROLL_THUMBTRACK, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
892 Connect(-1, wxEVT_SCROLL_THUMBRELEASE, (wxObjectEventFunction)&wxDynamicSashWindowLeaf::OnScroll);
893 }
894
895 wxLayoutConstraints *layout = new wxLayoutConstraints();
896 if (!layout)
897 return FALSE;
898 wxSize size = m_hscroll->GetBestSize();
899 #ifdef __WXMSW__
900 size = m_hscroll->GetSize();
901 #endif
902
903 layout->left.SameAs(m_impl->m_container, wxLeft, 10);
904 layout->right.LeftOf(m_vscroll);
905 layout->bottom.SameAs(m_impl->m_container, wxBottom, 3);
906 layout->height.Absolute(size.GetHeight());
907 m_hscroll->SetConstraints(layout);
908
909 layout = new wxLayoutConstraints();
910 if (!layout)
911 return FALSE;
912 size = size = m_vscroll->GetBestSize();
913 #ifdef __WXMSW__
914 size = m_vscroll->GetSize();
915 #endif
916
917 layout->top.SameAs(m_impl->m_container, wxTop, 10);
918 layout->bottom.Above(m_hscroll);
919 layout->right.SameAs(m_impl->m_container, wxRight, 3);
920 layout->width.Absolute(size.GetWidth());
921 m_vscroll->SetConstraints(layout);
922
923 layout = new wxLayoutConstraints();
924 if (!layout)
925 return FALSE;
926 layout->left.SameAs(m_impl->m_container, wxLeft, 3);
927 layout->right.LeftOf(m_vscroll);
928 layout->top.SameAs(m_impl->m_container, wxTop, 3);
929 layout->bottom.Above(m_hscroll);
930 m_viewport->SetConstraints(layout);
931
932 m_impl->m_container->Layout();
933
934 return success;
935 }
936
937 void wxDynamicSashWindowLeaf::AddChild(wxWindow *window) {
938 if (m_child) {
939 m_child->Destroy();
940 }
941
942 m_child = window;
943
944 wxDynamicSashReparentEvent event(this);
945 AddPendingEvent(event);
946 }
947
948 DynamicSashRegion wxDynamicSashWindowLeaf::GetRegion(int x, int y) {
949 wxSize size = m_impl->m_container->GetSize();
950 int w = size.GetWidth();
951 int h = size.GetHeight();
952 size = m_hscroll->GetSize();
953 int sh = size.GetHeight();
954 size = m_vscroll->GetSize();
955 int sw = size.GetWidth();
956
957 if (x >= w - sw - 3 && x < w && y >= h - sh - 3 && y < h)
958 return DSR_CORNER;
959 if (x >= 3 && x < 10 && y >= h - sh - 3 && y < h - 2)
960 return DSR_VERTICAL_TAB;
961 if (x >= w - sw - 3 && x < w - 2 && y >= 3 && y < 10)
962 return DSR_HORIZONTAL_TAB;
963 if (x < 3)
964 return DSR_LEFT_EDGE;
965 if (y < 3)
966 return DSR_TOP_EDGE;
967 if (x >= w - 2)
968 return DSR_RIGHT_EDGE;
969 if (y >= h - 2)
970 return DSR_BOTTOM_EDGE;
971
972 return DSR_NONE;
973 }
974
975 void wxDynamicSashWindowLeaf::ResizeChild(wxSize size) {
976 if (m_child) {
977 if (m_impl->m_window->GetWindowStyle() & wxDS_MANAGE_SCROLLBARS) {
978 m_child->SetSize(size);
979 wxSize best_size = m_child->GetBestSize();
980 if (best_size.GetWidth() < size.GetWidth()) {
981 best_size.SetWidth(size.GetWidth());
982 }
983 if (best_size.GetHeight() < size.GetHeight()) {
984 best_size.SetHeight(size.GetHeight());
985 }
986 m_child->SetSize(best_size);
987
988 int hpos = m_hscroll->GetThumbPosition();
989 int vpos = m_vscroll->GetThumbPosition();
990
991 if (hpos < 0) {
992 hpos = 0;
993 }
994 if (vpos < 0) {
995 vpos = 0;
996 }
997 if (hpos > best_size.GetWidth() - size.GetWidth()) {
998 hpos = best_size.GetWidth() - size.GetWidth();
999 }
1000 if (vpos > best_size.GetHeight() - size.GetHeight()) {
1001 vpos = best_size.GetHeight() - size.GetHeight();
1002 }
1003
1004 m_hscroll->SetScrollbar(hpos, size.GetWidth(),
1005 best_size.GetWidth(), size.GetWidth());
1006 m_vscroll->SetScrollbar(vpos, size.GetHeight(),
1007 best_size.GetHeight(), size.GetHeight());
1008
1009 // Umm, the scrollbars are doing something insane under GTK+ and subtracting
1010 // one from the position I pass in. This works around that.
1011 m_hscroll->SetThumbPosition(hpos + hpos - m_hscroll->GetThumbPosition());
1012 m_vscroll->SetThumbPosition(vpos + vpos - m_vscroll->GetThumbPosition());
1013
1014 wxPoint pos = m_child->GetPosition();
1015 m_viewport->ScrollWindow(-hpos - pos.x, -vpos - pos.y);
1016 } else {
1017 m_child->SetSize(size);
1018 }
1019 }
1020 }
1021
1022 wxScrollBar *wxDynamicSashWindowLeaf::FindScrollBar(const wxWindow *child, int vert) const {
1023 if (m_child == child) {
1024 if (vert) {
1025 return m_vscroll;
1026 } else {
1027 return m_hscroll;
1028 }
1029 }
1030
1031 return NULL;
1032 }
1033
1034 void wxDynamicSashWindowLeaf::OnSize(wxSizeEvent &event) {
1035 m_impl->m_container->Refresh();
1036 ResizeChild(m_viewport->GetSize());
1037 }
1038
1039 void wxDynamicSashWindowLeaf::OnPaint(wxPaintEvent &event) {
1040 wxPaintDC dc(m_impl->m_container);
1041 dc.SetBackground(wxBrush(m_impl->m_container->GetBackgroundColour(), wxSOLID));
1042 dc.Clear();
1043
1044 wxPen highlight(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT), 1, wxSOLID);
1045 wxPen shadow(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNSHADOW), 1, wxSOLID);
1046 wxPen black(*wxBLACK, 1, wxSOLID);
1047
1048 wxSize size = m_impl->m_container->GetSize();
1049 int w = size.GetWidth();
1050 int h = size.GetHeight();
1051 size = m_hscroll->GetSize();
1052 int sh = size.GetHeight();
1053 size = m_vscroll->GetSize();
1054 int sw = size.GetWidth();
1055
1056 dc.SetPen(shadow);
1057 dc.DrawLine(1, 1, 1, h - 2);
1058 dc.DrawLine(1, 1, w - 2, 1);
1059 dc.SetPen(black);
1060 dc.DrawLine(2, 2, 2, h - 3);
1061 dc.DrawLine(2, 2, w - 3, 2);
1062 dc.SetPen(highlight);
1063 dc.DrawLine(w - 2, 2, w - 2, h - sh - 2);
1064 dc.DrawLine(w - 2, h - sh - 2, w - sw - 2, h - sh - 2);
1065 dc.DrawLine(w - sw - 2, h - sh - 2, w - sw - 2, h - 2);
1066 dc.DrawLine(w - sw - 2, h - 2, 2, h - 2);
1067
1068 dc.SetPen(highlight);
1069 dc.DrawLine(w - sw - 2, 8, w - sw - 2, 4);
1070 dc.DrawLine(w - sw - 2, 4, w - 5, 4);
1071 dc.SetPen(shadow);
1072 dc.DrawLine(w - 5, 4, w - 5, 8);
1073 dc.DrawLine(w - 5, 8, w - sw - 2, 8);
1074 dc.SetPen(black);
1075 dc.DrawLine(w - 4, 3, w - 4, 9);
1076 dc.DrawLine(w - 4, 9, w - sw - 3, 9);
1077
1078 dc.SetPen(highlight);
1079 dc.DrawLine(4, h - 5, 4, h - sh - 2);
1080 dc.DrawLine(4, h - sh - 2, 8, h - sh - 2);
1081 dc.SetPen(shadow);
1082 dc.DrawLine(8, h - sh - 2, 8, h - 5);
1083 dc.DrawLine(8, h - 5, 4, h - 5);
1084 dc.SetPen(black);
1085 dc.DrawLine(9, h - sh - 3, 9, h - 4);
1086 dc.DrawLine(9, h - 4, 3, h - 4);
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 (m_impl->m_window->GetWindowStyle() & wxDS_DRAG_CORNER) != 0) {
1142 cursor = wxCursor(wxCURSOR_SIZENWSE);
1143 } else if (region == DSR_LEFT_EDGE || region == DSR_TOP_EDGE
1144 || region == DSR_RIGHT_EDGE || region == DSR_BOTTOM_EDGE) {
1145 if (m_impl->FindParent(region)) {
1146 if (region == DSR_LEFT_EDGE || region == DSR_RIGHT_EDGE) {
1147 cursor = wxCursor(wxCURSOR_SIZEWE);
1148 } else {
1149 cursor = wxCursor(wxCURSOR_SIZENS);
1150 }
1151 }
1152 }
1153
1154 m_impl->m_container->SetCursor(cursor);
1155 }
1156
1157 void wxDynamicSashWindowLeaf::OnLeave(wxMouseEvent &event) {
1158 wxCursor cursor(wxCURSOR_ARROW);
1159 m_impl->m_container->SetCursor(cursor);
1160 }
1161
1162
1163 void wxDynamicSashWindowLeaf::OnPress(wxMouseEvent &event) {
1164 DynamicSashRegion region = GetRegion(event.m_x, event.m_y);
1165
1166 if ((region == DSR_CORNER) && (m_impl->m_window->GetWindowStyle() & wxDS_DRAG_CORNER) == 0)
1167 return;
1168
1169 if (region == DSR_HORIZONTAL_TAB || region == DSR_VERTICAL_TAB || region == DSR_CORNER) {
1170 m_impl->m_dragging = region;
1171 m_impl->m_drag_x = event.m_x;
1172 m_impl->m_drag_y = event.m_y;
1173 m_impl->DrawSash(event.m_x, event.m_y);
1174 m_impl->m_container->CaptureMouse();
1175 } else if (region == DSR_LEFT_EDGE || region == DSR_TOP_EDGE
1176 || region == DSR_RIGHT_EDGE || region == DSR_BOTTOM_EDGE) {
1177 wxDynamicSashWindowImpl *parent = m_impl->FindParent(region);
1178
1179 if (parent) {
1180 int x = event.m_x;
1181 int y = event.m_y;
1182
1183 m_impl->m_container->ClientToScreen(&x, &y);
1184 parent->m_container->ScreenToClient(&x, &y);
1185
1186 parent->m_dragging = parent->m_split;
1187 parent->m_drag_x = x;
1188 parent->m_drag_y = y;
1189 parent->DrawSash(x, y);
1190 parent->m_container->CaptureMouse();
1191 }
1192 }
1193 }
1194
1195 void wxDynamicSashWindowLeaf::OnRelease(wxMouseEvent &event) {
1196 }
1197
1198 void wxDynamicSashWindowLeaf::OnReparent(wxEvent &event) {
1199 if (m_child) {
1200 m_child->Reparent(m_viewport);
1201 }
1202
1203 ResizeChild(m_viewport->GetSize());
1204 }
1205
1206 // wxDynamicSashSplitEvent //////////////////////////////////////////////////
1207
1208 wxDynamicSashSplitEvent::wxDynamicSashSplitEvent() {
1209 m_eventObject = NULL;
1210 m_eventType = wxEVT_DYNAMIC_SASH_SPLIT;
1211 }
1212
1213 wxDynamicSashSplitEvent::wxDynamicSashSplitEvent(wxObject *object) {
1214 m_eventObject = object;
1215 m_eventType = wxEVT_DYNAMIC_SASH_SPLIT;
1216 }
1217
1218 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashSplitEvent, wxCommandEvent)
1219
1220 // wxDynamicSashUnifyEvent //////////////////////////////////////////////////
1221
1222 wxDynamicSashUnifyEvent::wxDynamicSashUnifyEvent() {
1223 m_eventObject = NULL;
1224 m_eventType = wxEVT_DYNAMIC_SASH_UNIFY;
1225 }
1226
1227 wxDynamicSashUnifyEvent::wxDynamicSashUnifyEvent(wxObject *object) {
1228 m_eventObject = object;
1229 m_eventType = wxEVT_DYNAMIC_SASH_UNIFY;
1230 }
1231
1232 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashUnifyEvent, wxCommandEvent)
1233
1234 // wxDynamicSsahReparentEvent ///////////////////////////////////////////////
1235
1236 wxDynamicSashReparentEvent::wxDynamicSashReparentEvent() {
1237 m_eventObject = NULL;
1238 m_eventType = wxEVT_DYNAMIC_SASH_REPARENT;
1239 }
1240
1241 wxDynamicSashReparentEvent::wxDynamicSashReparentEvent(wxObject *object) {
1242 m_eventObject = object;
1243 m_eventType = wxEVT_DYNAMIC_SASH_REPARENT;
1244 }
1245
1246 wxDynamicSashReparentEvent::wxDynamicSashReparentEvent(const wxDynamicSashReparentEvent& evt)
1247 : wxEvent(evt)
1248 {
1249 }
1250
1251 IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashReparentEvent, wxEvent)
1252
1253 /////////////////////////////////////////////////////////////////////////////