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