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: dynamicsash.cpp 35650 2005-09-23 12:56:45Z MR $ 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 33const 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 91const wxEventType wxEVT_DYNAMIC_SASH_SPLIT = wxNewEventType(); 92const wxEventType wxEVT_DYNAMIC_SASH_UNIFY = wxNewEventType(); 93const wxEventType wxEVT_DYNAMIC_SASH_REPARENT = wxNewEventType(); 94 95enum 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*/ 116class wxDynamicSashReparentEvent : public wxEvent 117{ 118public: 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 129class wxDynamicSashWindowImpl : public wxEvtHandler 130{ 131public: 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 182class wxDynamicSashWindowLeaf : public wxEvtHandler 183{ 184public: 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 223wxDynamicSashWindow::wxDynamicSashWindow() 224{ 225 m_impl = NULL; 226} 227 228wxDynamicSashWindow::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 239wxDynamicSashWindow::~wxDynamicSashWindow() 240{ 241 SetEventHandler(this); 242 delete m_impl; 243} 244 245bool 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 272void wxDynamicSashWindow::AddChild(wxWindowBase *child) 273{ 274 wxWindow::AddChild(child); 275 276 m_impl->AddChild(wxDynamicCast(child, wxWindow)); 277} 278 279wxScrollBar *wxDynamicSashWindow::GetHScrollBar(const wxWindow *child) const 280{ 281 return m_impl->FindScrollBar(child, 0); 282} 283 284wxScrollBar *wxDynamicSashWindow::GetVScrollBar(const wxWindow *child) const 285{ 286 return m_impl->FindScrollBar(child, 1); 287} 288 289IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashWindow, wxWindow) 290 291 292// ============================================================================ 293// wxDynamicSashWindowImpl 294// ============================================================================ 295 296wxDynamicSashWindowImpl::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 311wxDynamicSashWindowImpl::~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 327bool 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 364void 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 370void 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 444wxDynamicSashWindowImpl * 445wxDynamicSashWindowImpl::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 468wxDynamicSashWindowImpl * 469wxDynamicSashWindowImpl::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 486wxWindow *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 503wxScrollBar * 504wxDynamicSashWindowImpl::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 521void 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 554void 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 621void 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. */ 682void 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 859void wxDynamicSashWindowImpl::OnSize(wxSizeEvent &event) 860{ 861 m_container->Layout(); 862 863 if (m_leaf) 864 m_leaf->OnSize(event); 865} 866 867void 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 879void 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 893void wxDynamicSashWindowImpl::OnLeave(wxMouseEvent &event) 894{ 895 if (m_leaf) 896 m_leaf->OnLeave(event); 897} 898 899void 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 915void 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 997wxDynamicSashWindowLeaf::wxDynamicSashWindowLeaf(wxDynamicSashWindowImpl *impl) 998{ 999 m_impl = impl; 1000 1001 m_hscroll = 1002 m_vscroll = NULL; 1003 1004 m_child = NULL; 1005} 1006 1007wxDynamicSashWindowLeaf::~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 1017bool 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 1118void 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 1129DynamicSashRegion 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 1157void 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 1202wxScrollBar * 1203wxDynamicSashWindowLeaf::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 1213void wxDynamicSashWindowLeaf::OnSize(wxSizeEvent &WXUNUSED(event)) 1214{ 1215 m_impl->m_container->Refresh(); 1216} 1217 1218void wxDynamicSashWindowLeaf::OnViewSize(wxSizeEvent &WXUNUSED(event)) 1219{ 1220 if ( m_viewport ) 1221 ResizeChild(m_viewport->GetSize()); 1222} 1223 1224void 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 1299void 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 1312void 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 1322void 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 1362void wxDynamicSashWindowLeaf::OnLeave(wxMouseEvent &WXUNUSED(event)) 1363{ 1364 wxCursor cursor(wxCURSOR_ARROW); 1365 m_impl->m_container->SetCursor(cursor); 1366} 1367 1368 1369void 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 1406void wxDynamicSashWindowLeaf::OnRelease(wxMouseEvent &WXUNUSED(event)) 1407{ 1408} 1409 1410void 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 1424wxDynamicSashSplitEvent::wxDynamicSashSplitEvent() 1425{ 1426 m_eventObject = NULL; 1427 m_eventType = wxEVT_DYNAMIC_SASH_SPLIT; 1428} 1429 1430wxDynamicSashSplitEvent::wxDynamicSashSplitEvent(wxObject *object) 1431{ 1432 m_eventObject = object; 1433 m_eventType = wxEVT_DYNAMIC_SASH_SPLIT; 1434} 1435 1436IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashSplitEvent, wxCommandEvent) 1437 1438wxDynamicSashUnifyEvent::wxDynamicSashUnifyEvent() 1439{ 1440 m_eventObject = NULL; 1441 m_eventType = wxEVT_DYNAMIC_SASH_UNIFY; 1442} 1443 1444wxDynamicSashUnifyEvent::wxDynamicSashUnifyEvent(wxObject *object) 1445{ 1446 m_eventObject = object; 1447 m_eventType = wxEVT_DYNAMIC_SASH_UNIFY; 1448} 1449 1450IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashUnifyEvent, wxCommandEvent) 1451 1452 1453wxDynamicSashReparentEvent::wxDynamicSashReparentEvent() 1454{ 1455 m_eventObject = NULL; 1456 m_eventType = wxEVT_DYNAMIC_SASH_REPARENT; 1457} 1458 1459wxDynamicSashReparentEvent::wxDynamicSashReparentEvent(wxObject *object) 1460{ 1461 m_eventObject = object; 1462 m_eventType = wxEVT_DYNAMIC_SASH_REPARENT; 1463} 1464 1465wxDynamicSashReparentEvent::wxDynamicSashReparentEvent(const wxDynamicSashReparentEvent& evt) 1466 : wxEvent(evt) 1467{ 1468} 1469 1470IMPLEMENT_DYNAMIC_CLASS(wxDynamicSashReparentEvent, wxEvent) 1471 1472