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