1///////////////////////////////////////////////////////////////////////////// 2// Name: bardragpl.cpp 3// Purpose: cbBarDragPlugin implementation 4// Author: Aleksandras Gluchovas 5// Modified by: 6// Created: 23/09/98 7// RCS-ID: $Id: bardragpl.cpp 35650 2005-09-23 12:56:45Z MR $ 8// Copyright: (c) Aleksandras Gluchovas 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16#pragma hdrstop 17#endif 18 19#ifndef WX_PRECOMP 20#include "wx/wx.h" 21#endif 22 23#include "wx/fl/bardragpl.h" 24 25#define POS_UNDEFINED -32768 26 27// helpers, FOR NOW:: static 28 29static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 ) 30{ 31 if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) || 32 ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) ) 33 if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) || 34 ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) ) 35 return true; 36 return false; 37} 38 39static inline bool rect_contains_point( const wxRect& rect, int x, int y ) 40{ 41 return ( x >= rect.x && 42 y >= rect.y && 43 x < rect.x + rect.width && 44 y < rect.y + rect.height ); 45} 46 47/***** Implementation for class cbBarDragPlugin *****/ 48 49IMPLEMENT_DYNAMIC_CLASS( cbBarDragPlugin, cbPluginBase ) 50 51BEGIN_EVENT_TABLE( cbBarDragPlugin, cbPluginBase ) 52 53 //EVT_PL_LEFT_DOWN ( cbBarDragPlugin::OnLButtonDown ) 54 EVT_PL_LEFT_UP ( cbBarDragPlugin::OnLButtonUp ) 55 EVT_PL_MOTION ( cbBarDragPlugin::OnMouseMove ) 56 EVT_PL_DRAW_HINT_RECT ( cbBarDragPlugin::OnDrawHintRect ) 57 EVT_PL_START_BAR_DRAGGING ( cbBarDragPlugin::OnStartBarDragging ) 58 EVT_PL_LEFT_DCLICK ( cbBarDragPlugin::OnLDblClick ) 59 60END_EVENT_TABLE() 61 62cbBarDragPlugin::cbBarDragPlugin(void) 63 64 : mBarDragStarted ( false ), 65 mCanStick ( true ), 66 mpScrDc ( NULL ), 67 mpCurCursor ( NULL ), 68 mpDraggedBar ( NULL ), 69 mInClientHintBorder( 4 ) 70{} 71 72cbBarDragPlugin::cbBarDragPlugin( wxFrameLayout* pPanel, int paneMask ) 73 74 : cbPluginBase( pPanel, paneMask ), 75 76 mBarDragStarted ( false ), 77 mCanStick ( true ), 78 mpScrDc ( NULL ), 79 mpCurCursor ( NULL ), 80 mpDraggedBar ( NULL ), 81 mInClientHintBorder( 4 ) 82{} 83 84cbBarDragPlugin::~cbBarDragPlugin() 85{ 86 // nothing 87} 88 89// helper methods (protected) 90 91// clips (top/bottom) or (right/left) edges against the frame's bounding rect. 92 93void do_clip_edges( int len, int& rectPos, int& rectLen ) 94{ 95 if ( rectPos < 0 ) 96 { 97 rectLen += rectPos; 98 rectPos = 0; 99 if ( rectLen < 0 ) 100 rectLen = 1; 101 } 102 else 103 if ( rectPos > len-1 ) 104 { 105 rectPos = len-1; 106 rectLen = 1; 107 } 108 else 109 if ( rectPos + rectLen - 1 > len ) 110 rectLen -= (rectPos + rectLen) - len + 1; 111} 112 113void cbBarDragPlugin::ClipRectInFrame( wxRect& rect ) 114{ 115 int w, h; 116 mpLayout->GetParentFrame().GetClientSize( &w, &h ); 117 118 do_clip_edges( w, rect.x, rect.width ); 119 do_clip_edges( h, rect.y, rect.height ); 120} 121 122void cbBarDragPlugin::ClipPosInFrame( wxPoint& pos ) 123{ 124 int w, h; 125 mpLayout->GetParentFrame().GetClientSize( &w, &h ); 126 127 if ( pos.x < 0 ) 128 pos.x = 0; 129 if ( pos.y < 0 ) 130 pos.y = 0; 131 if ( pos.x > w ) 132 pos.x = w-1; 133 if ( pos.y > h ) 134 pos.y = h-1; 135} 136 137void cbBarDragPlugin::AdjustHintRect( wxPoint& mousePos ) 138{ 139 mHintRect.x = mousePos.x - mMouseInRectX; 140 mHintRect.y = mousePos.y - mMouseInRectY; 141} 142 143cbDockPane* cbBarDragPlugin::HitTestPanes( wxRect& rect ) 144{ 145 //wxRect clipped = rect; 146 147 //ClipRectInFrame( clipped ); 148 149 cbDockPane** pPanes = mpLayout->GetPanesArray(); 150 151 for( int i = 0; i != MAX_PANES; ++i ) 152 if ( rect_hits_rect( pPanes[i]->mBoundsInParent, rect ) ) 153 return pPanes[i]; 154 155 return NULL; 156} 157 158cbDockPane* cbBarDragPlugin::HitTestPanes( wxPoint& pos ) 159{ 160 wxPoint clipped = pos; 161 162 //ClipPosInFrame( pos ); 163 164 cbDockPane** pPanes = mpLayout->GetPanesArray(); 165 166 for( int i = 0; i != MAX_PANES; ++i ) 167 if ( rect_contains_point( pPanes[i]->mBoundsInParent, clipped.x, clipped.y ) ) 168 return pPanes[i]; 169 170 return NULL; 171} 172 173bool cbBarDragPlugin::HitsPane( cbDockPane* pPane, wxRect& rect ) 174{ 175 return rect_hits_rect( pPane->mBoundsInParent, rect ); 176} 177 178int cbBarDragPlugin::GetDistanceToPane( cbDockPane* pPane, wxPoint& mousePos ) 179{ 180 wxRect& bounds = pPane->mBoundsInParent; 181 182 switch( pPane->mAlignment ) 183 { 184 case FL_ALIGN_TOP : return mousePos.y - ( bounds.y + bounds.height ); 185 case FL_ALIGN_BOTTOM : return bounds.y - mousePos.y; 186 case FL_ALIGN_LEFT : return mousePos.x - ( bounds.x + bounds.width ); 187 case FL_ALIGN_RIGHT : return bounds.x - mousePos.x; 188 default : return 0; // never reached 189 } 190 191// return 0; 192} 193 194bool cbBarDragPlugin::IsInOtherPane( wxPoint& mousePos ) 195{ 196 cbDockPane* pPane = HitTestPanes( mousePos ); 197 198 if ( pPane && pPane != mpCurPane ) return true; 199 else return false; 200} 201 202bool cbBarDragPlugin::IsInClientArea( wxPoint& mousePos ) 203{ 204 return ( HitTestPanes( mousePos ) == NULL ); 205} 206 207bool cbBarDragPlugin::IsInClientArea( wxRect& rect ) 208{ 209 return ( HitTestPanes( rect ) == NULL ); 210} 211 212void cbBarDragPlugin::CalcOnScreenDims( wxRect& rect ) 213{ 214 if ( !mpCurPane || mpDraggedBar->IsFixed() ) return; 215 216 wxRect inPane = rect; 217 218 mpCurPane->FrameToPane( &inPane ); 219 220 int rowNo = mpCurPane->GetRowAt( inPane.y, inPane.y + inPane.height ); 221 222 bool isMaximized = ( rowNo >= (int)mpCurPane->GetRowList().Count() || rowNo < 0 ); 223 224 if ( isMaximized ) 225 { 226 inPane.x = 0; 227 inPane.width = mpCurPane->mPaneWidth; 228 229 mpCurPane->PaneToFrame( &inPane ); 230 231 rect = inPane; 232 } 233} 234 235// helpers 236 237static inline void check_upper_overrun( int& pos, int width, int mousePos ) 238{ 239 if ( mousePos >= pos + width ) 240 pos = mousePos - width/2; 241} 242 243static inline void check_lower_overrun( int& pos, int width, int mousePos ) 244{ 245 if ( mousePos <= pos ) 246 pos = mousePos - width/2; 247} 248 249void cbBarDragPlugin::StickToPane( cbDockPane* pPane, wxPoint& mousePos ) 250{ 251 int wInPane = GetBarWidthInPane ( pPane ); 252 int hInPane = GetBarHeightInPane( pPane ); 253 254 // adjsut hint-rect horizontally (in pane's orientation) 255 256 if ( pPane->IsHorizontal() ) 257 { 258 mHintRect.width = wInPane; 259 mHintRect.height = hInPane; 260 } 261 else 262 { 263 mHintRect.height = wInPane; 264 mHintRect.width = hInPane; 265 } 266 267 // adjsut hint-rect vertically (in pane's orientation) 268 269 wxRect& bounds = pPane->mBoundsInParent; 270 271 // true, if hint enters the pane through it's lower edge 272 273 bool fromLowerEdge = ( pPane->IsHorizontal() ) 274 ? mousePos.y > bounds.y 275 : mousePos.x > bounds.x; 276 277 // NOTE:: about all the below min/max things: they are meant to ensure 278 // that the mouse pointer doesn't overrun (leave) the hint-rectangle 279 // when its dimensions are recalculated upon sticking it to the pane 280 281 if ( pPane->IsHorizontal() && fromLowerEdge ) 282 { 283 int paneBottomEdgeY = bounds.y + bounds.height; 284 285 mHintRect.y = wxMin( paneBottomEdgeY, mousePos.y ); 286 287 check_lower_overrun( mHintRect.y, hInPane, mousePos.y ); 288 289 } 290 else 291 if ( pPane->IsHorizontal() && !fromLowerEdge ) 292 { 293 int paneTopEdgeY = bounds.y; 294 295 mHintRect.y = wxMax( paneTopEdgeY - hInPane, mousePos.y - hInPane ); 296 297 check_upper_overrun( mHintRect.y, hInPane, mousePos.y ); 298 } 299 else 300 if ( !pPane->IsHorizontal() && fromLowerEdge ) 301 { 302 int paneRightEdgeX = bounds.x + bounds.width; 303 304 mHintRect.x = wxMin( paneRightEdgeX, mousePos.x ); 305 306 check_lower_overrun( mHintRect.x, hInPane, mousePos.x ); 307 } 308 else 309 if ( !pPane->IsHorizontal() && !fromLowerEdge ) 310 { 311 int paneLeftEdgeX = bounds.x; 312 313 mHintRect.x = wxMax( paneLeftEdgeX - hInPane, mousePos.x - hInPane ); 314 315 check_upper_overrun( mHintRect.x, hInPane, mousePos.x ); 316 } 317 318 mMouseInRectX = mousePos.x - mHintRect.x; 319 mMouseInRectY = mousePos.y - mHintRect.y; 320 321 mpCurPane = pPane; // memorize pane to which the hint is currently sticked 322} 323 324void cbBarDragPlugin::UnstickFromPane( cbDockPane* pPane, wxPoint& mousePos ) 325{ 326 // unsticking causes rectangle to get the shape in which 327 // dragged control-bar would be when floated 328 329 int newWidth = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].x; 330 int newHeight = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].y; 331 332 wxRect& flBounds = mpDraggedBar->mDimInfo.mBounds[wxCBAR_FLOATING]; 333 334 if ( flBounds.width != -1 ) 335 { 336 newWidth = flBounds.width; 337 newHeight = flBounds.height; 338 } 339 340 mHintRect.width = newWidth; 341 mHintRect.height = newHeight; 342 343 wxRect& bounds = pPane->mBoundsInParent; 344 345 // true, if hint leaves the pane through it's lower edge 346 347 bool fromLowerEdge = ( pPane->IsHorizontal() ) 348 ? mousePos.y > bounds.y 349 : mousePos.x > bounds.x; 350 351 // NOTE:: ...all the below min/max things - see comments about it in StickToPane(..) 352 353 if ( pPane->IsHorizontal() && fromLowerEdge ) 354 { 355 // bool fromLowerEdge = mousePos.y > bounds.y; 356 357 mHintRect.y = wxMax( bounds.y + bounds.height + 1, mousePos.y - newHeight ); 358 359 check_upper_overrun( mHintRect.y, newHeight, mousePos.y ); 360 361 // this is how MFC's hint behaves: 362 363 if ( mMouseInRectX > newWidth ) 364 mHintRect.x = mousePos.x - ( newWidth / 2 ); 365 } 366 else 367 if ( pPane->IsHorizontal() && !fromLowerEdge ) 368 { 369 mHintRect.y = wxMin( bounds.y - newHeight - 1, mousePos.y ); 370 371 // -/- 372 373 if ( mMouseInRectX > newWidth ) 374 mHintRect.x = mousePos.x - ( newWidth / 2 ); 375 376 check_lower_overrun( mHintRect.y, newHeight, mousePos.y ); 377 } 378 else 379 if ( !pPane->IsHorizontal() && fromLowerEdge ) 380 { 381 mHintRect.x = wxMax( bounds.x + bounds.width, mousePos.x - newWidth ); 382 383 // -/- 384 385 if ( mMouseInRectY > newHeight ) 386 mHintRect.y = mousePos.y - ( newHeight / 2 ); 387 388 check_upper_overrun( mHintRect.x, newWidth, mousePos.x ); 389 } 390 else 391 if ( !pPane->IsHorizontal() && !fromLowerEdge ) 392 { 393 mHintRect.x = wxMin( bounds.x - newWidth - 1, mousePos.x ); 394 395 // -/- 396 397 if ( mMouseInRectY > newHeight ) 398 mHintRect.y = mousePos.y - ( newHeight / 2 ); 399 400 check_lower_overrun( mHintRect.x, newWidth, mousePos.x ); 401 } 402 403 mMouseInRectX = mousePos.x - mHintRect.x; 404 mMouseInRectY = mousePos.y - mHintRect.y; 405 406 mpCurPane = NULL; 407} 408 409int cbBarDragPlugin::GetBarWidthInPane( cbDockPane* pPane ) 410{ 411 if ( pPane == mpSrcPane ) 412 return mBarWidthInSrcPane; 413 414 // this is how MFC's bars behave: 415 416 if ( pPane->IsHorizontal() ) 417 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].x; 418 else 419 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].x; 420} 421 422int cbBarDragPlugin::GetBarHeightInPane( cbDockPane* pPane ) 423{ 424 if ( pPane->IsHorizontal() ) 425 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].y; 426 else 427 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].y; 428} 429 430void cbBarDragPlugin::ShowHint( bool prevWasInClient ) 431{ 432 bool wasDocked = false; 433 434 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false ) 435 { 436 // do heavy calculations first 437 438 wxRect actualRect = mHintRect; // will be adjusted depending on drag-settings 439 440 if ( mpSrcPane->mProps.mExactDockPredictionOn && mpCurPane ) 441 { 442#ifdef __WXDEBUG__ 443 bool success = 444#endif 445 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false ); 446 447 wxASSERT( success ); // DBG:: 448 449 actualRect = mpDraggedBar->mBounds; 450 451 mpCurPane->PaneToFrame( &actualRect ); 452 } 453 else 454 CalcOnScreenDims( actualRect ); 455 456 // release previous hint 457 458 if ( mPrevHintRect.x != POS_UNDEFINED ) 459 { 460 // erase previous rectangle 461 462 cbDrawHintRectEvent evt( mPrevHintRect, prevWasInClient, true, false ); 463 464 mpLayout->FirePluginEvent( evt ); 465 } 466 467 // draw new hint 468 469 cbDrawHintRectEvent evt( actualRect, mpCurPane == NULL, false, false ); 470 471 mpLayout->FirePluginEvent( evt ); 472 473 mPrevHintRect = actualRect; 474 } 475 else 476 { 477 // otherwise, if real-time updates option is ON 478 479 if ( mpDraggedBar->mState != wxCBAR_FLOATING && !mpCurPane ) 480 { 481 mpLayout->SetBarState( mpDraggedBar, wxCBAR_FLOATING, true ); 482 } 483 else 484 if ( mpDraggedBar->mState == wxCBAR_FLOATING && mpCurPane ) 485 { 486 mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, false ); 487 488 wasDocked = true; 489 } 490 491 if ( mpCurPane ) 492 { 493 mpLayout->GetUpdatesManager().OnStartChanges(); 494 495 if ( wasDocked ) 496 497 mpDraggedBar->mUMgrData.SetDirty( true ); 498 499#ifdef __WXDEBUG__ 500 bool success = 501#endif 502 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false ); 503 504 wxASSERT( success ); // DBG :: 505 506 mpLayout->GetUpdatesManager().OnFinishChanges(); 507 mpLayout->GetUpdatesManager().UpdateNow(); 508 } 509 else 510 { 511 if ( mpLayout->mFloatingOn ) 512 { 513 // move the top-most floated bar around as user drags the hint 514 515 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect; 516 517 mpLayout->ApplyBarProperties( mpDraggedBar ); 518 } 519 } 520 } 521} 522 523/*** event handlers ***/ 524 525void cbBarDragPlugin::OnMouseMove( cbMotionEvent& event ) 526{ 527 // calculate postion in frame's coordiantes 528 529 if ( !mBarDragStarted ) 530 { 531 event.Skip(); // pass event to the next plugin 532 return; 533 } 534 535 wxPoint mousePos = event.mPos; 536 537 event.mpPane->PaneToFrame( &mousePos.x, &mousePos.y ); 538 539 bool prevIsInClient = ( mpCurPane == 0 ); 540 541 AdjustHintRect( mousePos ); 542 543 // if the hint-rect is not "tempted" to any pane yet 544 545 if ( mpCurPane == NULL ) 546 { 547 cbDockPane* pPane = HitTestPanes( mHintRect ); 548 549 // enable sticking again, if we've left the pane completely 550 if ( !pPane ) 551 mCanStick = true; 552 553 if ( mCanStick && pPane && 554 GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) ) 555 StickToPane( pPane, mousePos ); 556 else 557 if ( pPane && HitTestPanes( mousePos ) == pPane && 0 ) // FOR NOW:: disabled 558 559 StickToPane( pPane, mousePos ); 560 } 561 else 562 { 563 // otherwise, when rect is now sticked to some of the panes 564 // check if it should still remain in this pane 565 566 mCanStick = true; 567 568 bool mouseInOther = IsInOtherPane( mousePos ); 569 570 if ( mouseInOther ) 571 { 572 cbDockPane* pPane = HitTestPanes( mousePos ); 573 574 StickToPane( pPane, mousePos ); 575 } 576 else 577 { 578 if ( IsInClientArea( mousePos ) ) 579 { 580 cbDockPane* pPane = HitTestPanes( mHintRect ); 581 582 if ( pPane && 583 pPane != mpCurPane && 584 GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) ) 585 StickToPane( pPane, mousePos ); 586 else 587 if ( !pPane ) 588 { 589 UnstickFromPane( mpCurPane, mousePos ); 590 591 // FOR NOW:: disabled, would cause some mess 592 // mCanStick = false; // prevents from sticking to this 593 // pane again, flag is reset when hint-rect 594 // leaves the pane completely 595 } 596 else 597 if ( GetDistanceToPane( pPane, mousePos ) > GetBarHeightInPane( pPane ) ) 598 { 599 if ( !HitsPane( mpCurPane, mHintRect ) ) 600 { 601 UnstickFromPane( mpCurPane, mousePos ); 602 603 // FOR NOW:: disabled, would cause some mess 604 // mCanStick = false; // prevents from sticking to this 605 // pane again, flag is reset when hint-rect 606 // leaves the pane completely 607 } 608 } 609 610 } 611 } 612 } 613 614 ShowHint( prevIsInClient ); 615 616 wxCursor* pPrevCurs = mpCurCursor; 617 618 if ( mpCurPane ) 619 { 620 mpCurCursor = mpLayout->mpNormalCursor; 621 } 622 else 623 { 624 // if floating is off, and we are in the client 625 // area, the cursor will be invalid, otherwise 626 // it will be the normal cursor 627 628 if (mpLayout->mFloatingOn) 629 { 630 mpCurCursor = mpLayout->mpNormalCursor; 631 } 632 else 633 { 634 mpCurCursor = mpLayout->mpNECursor; 635 } 636 637 } 638 if ( pPrevCurs != mpCurCursor ) 639 mpLayout->GetParentFrame().SetCursor( *mpCurCursor ); 640} 641 642void cbBarDragPlugin::OnLButtonDown( cbLeftDownEvent& event ) 643{ 644 if ( mBarDragStarted ) 645 { 646 wxMessageBox(wxT("DblClick!")); 647 } 648 649 event.Skip(); 650} 651 652void cbBarDragPlugin::OnLButtonUp( cbLeftUpEvent& event ) 653{ 654 if ( mBarDragStarted ) 655 { 656 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false ) 657 { 658 // erase current rectangle, and finsih on-screen drawing session 659 660 cbDrawHintRectEvent evt( mPrevHintRect, mpCurPane == NULL, true, true ); 661 662 mpLayout->FirePluginEvent( evt ); 663 664 if ( mpCurPane != NULL ) 665 { 666 if ( mpSrcPane->mProps.mExactDockPredictionOn ) 667 { 668 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false ); 669 670 mpLayout->GetUpdatesManager().OnFinishChanges(); 671 mpLayout->GetUpdatesManager().UpdateNow(); 672 } 673 else 674 { 675 if (mpDraggedBar->mState == wxCBAR_FLOATING) 676 { 677 mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, true); 678 } 679 680 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane ); 681 } 682 } 683 else 684 { 685 if (mpDraggedBar->mState != wxCBAR_FLOATING) 686 { 687 mpLayout->SetBarState(mpDraggedBar, wxCBAR_FLOATING, true); 688 } 689 690 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect; 691 mpLayout->ApplyBarProperties( mpDraggedBar ); 692 } 693 } 694 695 mHintRect.width = -1; 696 697 // In Windows, at least, the frame needs to have a null cursor 698 // else child windows (such as text windows) inherit the cursor 699#if 1 700 mpLayout->GetParentFrame().SetCursor( wxNullCursor ); 701#else 702 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor ); 703#endif 704 705 mpLayout->ReleaseEventsFromPane( event.mpPane ); 706 mpLayout->ReleaseEventsFromPlugin( this ); 707 708 mBarDragStarted = false; 709 710 if ( mBarWasFloating && mpDraggedBar->mState != wxCBAR_FLOATING ) 711 { 712 // save bar's floating position before it was docked 713 714 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mFloatedBarBounds; 715 } 716 } 717 else 718 event.Skip(); // pass event to the next plugin 719} 720 721void cbBarDragPlugin::OnLDblClick( cbLeftDClickEvent& event ) 722{ 723 int avoidCompilerWarning = 1; 724 if ( avoidCompilerWarning ) 725 { 726 cbBarInfo* pHittedBar; 727 cbRowInfo* pRow; 728 729 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes 730 &pRow, 731 &pHittedBar ) == CB_BAR_CONTENT_HITTED 732 ) 733 { 734 mpLayout->SetBarState( pHittedBar, wxCBAR_FLOATING, true ); 735 736 mpLayout->RepositionFloatedBar( pHittedBar ); 737 738 return; // event is "eaten" by this plugin 739 } 740 741 mBarDragStarted = false; 742 743 event.Skip(); 744 } 745 746 //wxMessageBox("Hi, dblclick arrived!"); 747} 748 749void cbBarDragPlugin::OnStartBarDragging( cbStartBarDraggingEvent& event ) 750{ 751 mpDraggedBar = event.mpBar; 752 mpSrcPane = event.mpPane; 753 754 mpLayout->CaptureEventsForPane( event.mpPane ); 755 mpLayout->CaptureEventsForPlugin( this ); 756 757 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor ); 758 759 mBarDragStarted = true; 760 761 wxRect inParent = mpDraggedBar->mBounds; 762 763 mBarWasFloating = mpDraggedBar->mState == wxCBAR_FLOATING; 764 765 if ( mBarWasFloating ) 766 { 767 inParent = mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ]; 768 mFloatedBarBounds = inParent; 769 } 770 else 771 event.mpPane->PaneToFrame( &inParent ); 772 773 mHintRect.x = POS_UNDEFINED; 774 775 mHintRect.width = inParent.width; 776 mHintRect.height = inParent.height; 777 778 mMouseInRectX = event.mPos.x - inParent.x; 779 mMouseInRectY = event.mPos.y - inParent.y; 780 781 mpSrcPane = event.mpPane; 782 783 if ( mpDraggedBar->mState == wxCBAR_FLOATING ) 784 785 mpCurPane = NULL; 786 else 787 mpCurPane = event.mpPane; 788 789 mPrevHintRect.x = POS_UNDEFINED; 790 791 mCanStick = false; // we're not stuck into any pane now - 792 // there's nowhere to "stick-twice" 793 794 mBarWidthInSrcPane = mpDraggedBar->mDimInfo.mSizes[ mpDraggedBar->mState ].x; 795 796 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false && 797 mpSrcPane->mProps.mExactDockPredictionOn ) 798 mpLayout->GetUpdatesManager().OnStartChanges(); // capture initial state of layout 799 800 // simulate the first mouse movement 801 802 int x = event.mPos.x, y = event.mPos.y; 803 mpSrcPane->FrameToPane( &x, &y ); 804 805 wxPoint pt(x,y); 806 cbMotionEvent motionEvt( pt, event.mpPane ); 807 this->OnMouseMove( motionEvt ); 808 809 return; // event is "eaten" by this plugin 810} 811 812/*** on-screen hint-tracking related methods ***/ 813 814void cbBarDragPlugin::OnDrawHintRect( cbDrawHintRectEvent& event ) 815{ 816 if ( !mpScrDc ) StartTracking(); 817 818 DoDrawHintRect( event.mRect, event.mIsInClient ); 819 820 if ( event.mLastTime ) 821 FinishTracking(); 822} 823 824#define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin) 825#define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin) 826#define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons. 827#define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons. 828 829// FOR NOW:: static 830 831static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D, 832 _IMG_A,_IMG_B,_IMG_C,_IMG_D, 833 _IMG_A,_IMG_B,_IMG_C,_IMG_D, 834 _IMG_A,_IMG_B,_IMG_C,_IMG_D 835 }; 836 837void cbBarDragPlugin::StartTracking() 838{ 839 mpScrDc = new wxScreenDC; 840 841 wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame()); 842} 843 844void cbBarDragPlugin::DoDrawHintRect( wxRect& rect, bool isInClientRect) 845{ 846 wxRect scrRect; 847 848 RectToScr( rect, scrRect ); 849 850 int prevLF = mpScrDc->GetLogicalFunction(); 851 852 mpScrDc->SetLogicalFunction( wxINVERT ); 853 854 if ( isInClientRect ) 855 { 856 // BUG BUG BUG (wx):: somehow stippled brush works only 857 // when the bitmap created on stack, not 858 // as a member of the class 859 860 wxBitmap checker( (const char*)_gCheckerImg, 8,8 ); 861 862 wxBrush checkerBrush( checker ); 863 864 mpScrDc->SetPen( mpLayout->mNullPen ); 865 mpScrDc->SetBrush( checkerBrush ); 866 867 int half = mInClientHintBorder / 2; 868 869 mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y - half, 870 scrRect.width + 2*half, mInClientHintBorder ); 871 872 mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + scrRect.height - half, 873 scrRect.width + 2*half, mInClientHintBorder ); 874 875 mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + half - 1, 876 mInClientHintBorder, scrRect.height - 2*half + 2); 877 878 mpScrDc->DrawRectangle( scrRect.x + scrRect.width - half, 879 scrRect.y + half - 1, 880 mInClientHintBorder, scrRect.height - 2*half + 2); 881 882 mpScrDc->SetBrush( wxNullBrush ); 883 } 884 else 885 { 886 mpScrDc->SetPen( mpLayout->mBlackPen ); 887 888 mpScrDc->DrawLine( scrRect.x, scrRect.y, 889 scrRect.x + scrRect.width, scrRect.y ); 890 891 mpScrDc->DrawLine( scrRect.x, scrRect.y + 1, 892 scrRect.x, scrRect.y + scrRect.height ); 893 894 mpScrDc->DrawLine( scrRect.x+1, scrRect.y + scrRect.height, 895 scrRect.x + scrRect.width, scrRect.y + scrRect.height ); 896 897 mpScrDc->DrawLine( scrRect.x + scrRect.width , scrRect.y, 898 scrRect.x + scrRect.width, scrRect.y + scrRect.height + 1); 899 } 900 901 mpScrDc->SetLogicalFunction( prevLF ); 902} 903 904void cbBarDragPlugin::DrawHintRect ( wxRect& rect, bool isInClientRect) 905{ 906 DoDrawHintRect( rect, isInClientRect ); 907} 908 909void cbBarDragPlugin::EraseHintRect( wxRect& rect, bool isInClientRect) 910{ 911 DoDrawHintRect( rect, isInClientRect ); 912} 913 914void cbBarDragPlugin::FinishTracking() 915{ 916 wxScreenDC::EndDrawingOnTop(); 917 918 delete mpScrDc; 919 920 mpScrDc = NULL; 921} 922 923void cbBarDragPlugin::RectToScr( wxRect& frameRect, wxRect& scrRect ) 924{ 925 scrRect = frameRect; 926 927 int x = frameRect.x, y = frameRect.y; 928 929 mpLayout->GetParentFrame().ClientToScreen( &x, &y ); 930 931 scrRect.x = x; 932 scrRect.y = y; 933} 934 935