1///////////////////////////////////////////////////////////////////////////// 2// Name: toolwnd.cpp 3// Purpose: wxToolWindow implementation. 4// Author: Aleksandras Gluchovas 5// Modified by: 6// Created: 06/09/98 7// RCS-ID: $Id: toolwnd.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/toolwnd.h" 24 25#define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin) 26#define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin) 27#define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons. 28#define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons. 29 30// FOR NOW:: static 31 32static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D, 33 _IMG_A,_IMG_B,_IMG_C,_IMG_D, 34 _IMG_A,_IMG_B,_IMG_C,_IMG_D, 35 _IMG_A,_IMG_B,_IMG_C,_IMG_D 36 }; 37 38/***** Implementation for class wxToolWindow *****/ 39 40IMPLEMENT_DYNAMIC_CLASS( wxToolWindow, wxFrame) 41 42BEGIN_EVENT_TABLE( wxToolWindow, wxFrame ) 43 44 EVT_PAINT ( wxToolWindow::OnPaint ) 45 EVT_MOTION ( wxToolWindow::OnMotion ) 46 EVT_LEFT_DOWN( wxToolWindow::OnLeftDown ) 47 EVT_LEFT_UP ( wxToolWindow::OnLeftUp ) 48 EVT_SIZE ( wxToolWindow::OnSize ) 49 50 51 EVT_ERASE_BACKGROUND( wxToolWindow::OnEraseBackground ) 52 53END_EVENT_TABLE() 54 55enum INTERNAL_HIT_CODES 56{ 57 HITS_WND_NOTHING, 58 HITS_WND_CLIENT, 59 HITS_WND_TITLE, 60 61 HITS_WND_LEFT_EDGE, 62 HITS_WND_RIGHT_EDGE, 63 HITS_WND_TOP_EDGE, 64 HITS_WND_BOTTOM_EDGE, 65 66 HITS_WND_TOP_LEFT_CORNER, 67 HITS_WND_BOTTOM_RIGHT_CORNER, 68 HITS_WND_TOP_RIGHT_CORNER, 69 HITS_WND_BOTTOM_LEFT_CORNER 70}; 71 72wxToolWindow::wxToolWindow() 73 74 : mpClientWnd ( NULL ), 75 76#ifndef __WXMSW__ 77 mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL ), 78#else 79 // just to simulate MS-Dev style 80 mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL, false, wxT("MS Sans Serif") ), 81#endif 82 83 mTitleHeight ( 16 ), 84 mClntHorizGap ( 2 ), 85 mClntVertGap ( 2 ), 86 mWndVertGap ( 4 ), 87 mWndHorizGap ( 4 ), 88 89 mButtonGap ( 2 ), 90 mInTitleMargin( 4 ), 91 mHintBorder ( 4 ), 92 93 mResizeStarted( false ), 94 mRealTimeUpdatesOn( true ), 95 96 mMTolerance ( 5 ), // mouse-resizing tollerance 97 98 mCursorType( HITS_WND_NOTHING ), 99 mMouseCaptured( false ), 100 101 mpScrDc( NULL ) 102 103{ 104} 105 106wxToolWindow::~wxToolWindow() 107{ 108 if ( mpScrDc ) delete mpScrDc; 109 110 for( size_t i = 0; i != mButtons.Count(); ++i ) 111 delete mButtons[i]; 112} 113 114void wxToolWindow::LayoutMiniButtons() 115{ 116 int w,h; 117 118 GetSize( &w, &h ); 119 120 int x = w - mWndHorizGap - mInTitleMargin - BTN_BOX_WIDTH; 121 int y = mWndVertGap + 2; 122 123 for( size_t i = 0; i != mButtons.Count(); ++i ) 124 { 125 mButtons[i]->SetPos( wxPoint( x,y ) ); 126 x-= BTN_BOX_WIDTH + mButtonGap; 127 } 128} 129 130void wxToolWindow::SetClient( wxWindow* pWnd ) 131{ 132 mpClientWnd = pWnd; 133} 134 135wxWindow* wxToolWindow::GetClient() 136{ 137 return mpClientWnd; 138} 139 140void wxToolWindow::SetTitleFont( wxFont& font ) 141{ 142 mTitleFont = font; 143} 144 145void wxToolWindow::AddMiniButton( cbMiniButton* pBtn ) 146{ 147 pBtn->mpWnd = this; 148 149 mButtons.Add( pBtn ); 150 151 // not necesserely now.. 152 //LayoutMiniButtons(); 153} 154 155void wxToolWindow::OnPaint( wxPaintEvent& WXUNUSED(event) ) 156{ 157 wxPaintDC pdc( this ); 158 wxWindowDC dc( this ); 159 160 int w,h; 161 GetSize( &w, &h ); 162 163 wxBrush backGround( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxSOLID ); 164 //dc.SetBrush( *wxLIGHT_GREY_BRUSH ); 165 dc.SetBrush( backGround ); 166 dc.SetPen( *wxTRANSPARENT_PEN ); 167 168 int y = mWndVertGap + mTitleHeight + mClntVertGap; 169 170 dc.DrawRectangle( 0,0, w, y ); // Top grey part. 171 dc.DrawRectangle( 0,y-1, mWndHorizGap + mClntHorizGap, h - y ); // Left grey part. 172 dc.DrawRectangle( w - ( mWndHorizGap + mClntHorizGap ), y-1, 173 mWndHorizGap + mClntHorizGap, h - y ); // Right grey part. 174 dc.DrawRectangle( 0, h - mWndVertGap - mClntVertGap, w, mWndVertGap + mClntVertGap ); // Bottom grey part. 175 176 // draw shades 177 dc.SetPen( *wxLIGHT_GREY_PEN ); 178 179 dc.DrawLine( 0,0, w, 0 ); 180 dc.DrawLine( 0,0, 0, h ); 181 182 dc.SetPen( *wxWHITE_PEN ); 183 184 dc.DrawLine( 1,1, w, 1 ); 185 dc.DrawLine( 1,2, 1, h ); 186 187 dc.SetPen( *wxGREY_PEN ); 188 189 dc.DrawLine( w - 2, 1, w - 2, h - 1 ); 190 dc.DrawLine( 1, h - 2, w - 2, h - 2 ); 191 192 dc.SetPen( *wxBLACK_PEN ); 193 194 dc.DrawLine( 0, h - 1, w, h - 1 ); 195 dc.DrawLine( w-1, 0, w-1, h ); 196 197 // fill inner area 198 199 dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( wxColour( 0,0,128 ), wxSOLID ) ); 200 201 dc.DrawRectangle( mWndHorizGap, mWndVertGap, w - mWndHorizGap*2, mTitleHeight ); 202 203 dc.SetFont( mTitleFont ); 204 205 for( size_t i = 0; i != mButtons.Count(); ++i ) 206 mButtons[i]->Draw( dc ); 207 208 int x1 = mWndHorizGap + mClntHorizGap; 209 int x2 = mButtons[ mButtons.GetCount() - 1 ]->mPos.x - mClntHorizGap*2; 210 211 dc.SetClippingRegion( x1, mWndVertGap + mClntVertGap, x2 - x1, mTitleHeight ); 212 213 dc.SetTextForeground( *wxWHITE ); 214 dc.SetBackgroundMode( wxTRANSPARENT ); 215 dc.DrawText( GetTitle(), mWndHorizGap + 2, mWndVertGap + 1 ); 216} 217 218void wxToolWindow::GetScrWindowRect( wxRect& r ) 219{ 220 int x,y; 221 GetPosition(&x,&y); 222 int w,h; 223 GetSize( &w, &h ); 224 225 r.x = x; r.y = y; 226 r.width = w; r.height = h; 227} 228 229void wxToolWindow::GetScrMousePos( wxMouseEvent& event, wxPoint& pos ) 230{ 231 int x = event.m_x, y = event.m_y; 232 233 ClientToScreen( &x, &y ); 234 235 pos.x = x; pos.y = y; 236} 237 238int wxToolWindow::HitTestWindow( wxMouseEvent& event ) 239{ 240 wxPoint pos; 241 wxRect r; 242 243 GetScrMousePos( event, pos ); 244 GetScrWindowRect( r ); 245 246 int k = mMTolerance; 247 248 if ( !( pos.x >= r.x && pos.y >= r.y && 249 pos.x < r.x + r.width && 250 pos.y < r.y + r.height ) 251 ) 252 return HITS_WND_NOTHING; 253 254 if ( pos.y <= r.y + k ) 255 { 256 if ( pos.x < r.x + k*2 ) 257 return HITS_WND_TOP_LEFT_CORNER; 258 else 259 { 260 if ( pos.x >= r.x + r.width - k*2 ) 261 return HITS_WND_TOP_RIGHT_CORNER; 262 else 263 return HITS_WND_TOP_EDGE; 264 } 265 } 266 else 267 { 268 if ( pos.y >= r.y + r.height - k ) 269 { 270 if ( pos.x < r.x + k*2 ) 271 return HITS_WND_BOTTOM_LEFT_CORNER; 272 else 273 { 274 if ( pos.x > r.x + r.width - k*2 ) 275 return HITS_WND_BOTTOM_RIGHT_CORNER; 276 else 277 return HITS_WND_BOTTOM_EDGE; 278 } 279 } 280 else 281 { 282 if ( pos.x <= r.x + k ) 283 return HITS_WND_LEFT_EDGE; 284 else 285 { 286 if ( pos.x >= r.x + r.width - k ) 287 return HITS_WND_RIGHT_EDGE; 288 else 289 { 290 if ( pos.y <= r.y + mWndVertGap + mTitleHeight + mClntVertGap ) 291 return HITS_WND_TITLE; 292 else 293 return HITS_WND_CLIENT; 294 } 295 } 296 } 297 } 298} 299 300void wxToolWindow::DrawHintRect( const wxRect& r ) 301{ 302 // BUG BUG BUG (wx):: somehow stippled brush works only 303 // when the bitmap created on stack, not 304 // as a member of the class 305 306 int prevLF = mpScrDc->GetLogicalFunction(); 307 308 mpScrDc->SetLogicalFunction( wxXOR ); 309 310 wxBitmap checker( (const char*)_gCheckerImg, 8,8 ); 311 312 wxBrush checkerBrush( checker ); 313 314 mpScrDc->SetPen( *wxTRANSPARENT_PEN ); 315 mpScrDc->SetBrush( checkerBrush ); 316 317 int half = mHintBorder / 2; 318 319 mpScrDc->DrawRectangle( r.x - half, r.y - half, 320 r.width + 2*half, mHintBorder ); 321 322 mpScrDc->DrawRectangle( r.x - half, r.y + r.height - half, 323 r.width + 2*half, mHintBorder ); 324 325 mpScrDc->DrawRectangle( r.x - half, r.y + half - 1, 326 mHintBorder, r.height - 2*half + 2); 327 328 mpScrDc->DrawRectangle( r.x + r.width - half, 329 r.y + half - 1, 330 mHintBorder, r.height - 2*half + 2); 331 332 mpScrDc->SetBrush( wxNullBrush ); 333 334 mpScrDc->SetLogicalFunction( prevLF ); 335} 336 337void wxToolWindow::SetHintCursor( int type ) 338{ 339 if ( mResizeStarted ) 340 return; 341 342 if ( type == HITS_WND_NOTHING || type == HITS_WND_CLIENT ) 343 { 344 // the cursor is out of window - reset to arrow 345 346 if ( mMouseCaptured ) 347 { 348 ReleaseMouse(); 349 mMouseCaptured = false; 350 } 351 352 SetCursor( wxCURSOR_ARROW ); 353 354 mCursorType = type; 355 356 return; 357 } 358 359 // did the cursor actually changed? 360 361 if ( type != mCursorType ) 362 { 363 mCursorType = type; 364 365 switch ( type ) 366 { 367 case HITS_WND_LEFT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break; 368 case HITS_WND_RIGHT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break; 369 case HITS_WND_TOP_EDGE : SetCursor( wxCURSOR_SIZENS ); break; 370 case HITS_WND_BOTTOM_EDGE : SetCursor( wxCURSOR_SIZENS ); break; 371 372 case HITS_WND_TOP_LEFT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break; 373 case HITS_WND_BOTTOM_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break; 374 case HITS_WND_TOP_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break; 375 case HITS_WND_BOTTOM_LEFT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break; 376 377 case HITS_WND_TITLE : SetCursor( wxCURSOR_ARROW ); break; 378 case HITS_WND_CLIENT : SetCursor( wxCURSOR_ARROW ); break; 379 380 default: break; 381 } 382 383 if (mMouseCaptured) 384 { 385 mMouseCaptured = false; 386 ReleaseMouse(); 387 } 388 } 389 390 if ( !mMouseCaptured ) 391 { 392 mMouseCaptured = true; 393 CaptureMouse(); 394 } 395} 396 397#define FL_INFINITY 32768 398 399static inline void clip_to( int& value, long from, long till ) 400{ 401 if ( value < from ) 402 value = from; 403 404 if ( value > till ) 405 value = till; 406} 407 408void wxToolWindow::AdjustRectPos( const wxRect& original, const wxSize& newDim, wxRect& newRect ) 409{ 410 if ( mCursorType == HITS_WND_TOP_EDGE || 411 mCursorType == HITS_WND_TOP_LEFT_CORNER ) 412 { 413 newRect.x = original.x + original.width - newDim.x; 414 newRect.y = original.y + original.height - newDim.y; 415 } 416 else 417 if ( mCursorType == HITS_WND_LEFT_EDGE || 418 mCursorType == HITS_WND_BOTTOM_LEFT_CORNER ) 419 { 420 newRect.x = original.x + original.width - newDim.x; 421 newRect.y = original.y; 422 } 423 else 424 if ( mCursorType == HITS_WND_RIGHT_EDGE || 425 mCursorType == HITS_WND_TOP_RIGHT_CORNER ) 426 { 427 newRect.x = original.x; 428 newRect.y = original.y + original.height - newDim.y; 429 } 430 else 431 if ( mCursorType == HITS_WND_BOTTOM_EDGE || 432 mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER ) 433 { 434 newRect.x = original.x; 435 newRect.y = original.y; 436 } 437 438 newRect.width = newDim.x; 439 newRect.height = newDim.y; 440} 441 442void wxToolWindow::CalcResizedRect( wxRect& rect, wxPoint& delta, const wxSize& minDim ) 443{ 444 // Microsoft's rect-coordinates are best suited 445 // for the case of corner-clipping 446 447 int left = mInitialRect.x; 448 int top = mInitialRect.y; 449 int right = mInitialRect.x + mInitialRect.width; 450 int bottom = mInitialRect.y + mInitialRect.height; 451 452 // constraint delta edge is dragged 453 454 switch ( mCursorType ) 455 { 456 case HITS_WND_LEFT_EDGE : delta.y = 0; break; 457 case HITS_WND_RIGHT_EDGE : delta.y = 0; break; 458 case HITS_WND_TOP_EDGE : delta.x = 0; break; 459 case HITS_WND_BOTTOM_EDGE : delta.x = 0; break; 460 default: break; 461 } 462 463 if ( mCursorType == HITS_WND_TOP_EDGE || 464 mCursorType == HITS_WND_TOP_LEFT_CORNER ) 465 { 466 left += delta.x; 467 top += delta.y; 468 469 clip_to( left, -FL_INFINITY, mInitialRect.x + mInitialRect.width - minDim.x ); 470 clip_to( top, -FL_INFINITY, mInitialRect.y + mInitialRect.height - minDim.y ); 471 } 472 else 473 if ( mCursorType == HITS_WND_LEFT_EDGE || 474 mCursorType == HITS_WND_BOTTOM_LEFT_CORNER ) 475 { 476 left += delta.x; 477 bottom += delta.y; 478 479 clip_to( left, -FL_INFINITY, mInitialRect.x + mInitialRect.width - minDim.x ); 480 clip_to( bottom, mInitialRect.y + minDim.y, FL_INFINITY ); 481 } 482 else 483 if ( mCursorType == HITS_WND_RIGHT_EDGE || 484 mCursorType == HITS_WND_TOP_RIGHT_CORNER ) 485 { 486 right += delta.x; 487 top += delta.y; 488 489 clip_to( right, mInitialRect.x + minDim.x, FL_INFINITY ); 490 clip_to( top, -FL_INFINITY, mInitialRect.y + mInitialRect.height - minDim.y ); 491 } 492 else 493 if ( mCursorType == HITS_WND_BOTTOM_EDGE || 494 mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER ) 495 { 496 right += delta.x; 497 bottom += delta.y; 498 499 clip_to( right, mInitialRect.x + minDim.x, FL_INFINITY ); 500 clip_to( bottom, mInitialRect.y + minDim.y, FL_INFINITY ); 501 } 502 else 503 { 504 wxFAIL_MSG( _T("what did the cursor hit?") ); 505 } 506 507 rect.x = left; 508 rect.y = top; 509 rect.width = right - left; 510 rect.height = bottom - top; 511} 512 513wxSize wxToolWindow::GetMinimalWndDim() 514{ 515 return wxSize( (mWndHorizGap + mClntHorizGap)*2 + BTN_BOX_WIDTH*4, 516 (mWndVertGap + mClntVertGap )*2 + mTitleHeight ); 517} 518 519void wxToolWindow::OnMotion( wxMouseEvent& event ) 520{ 521 if ( !mResizeStarted ) 522 { 523 for( size_t i = 0; i != mButtons.Count(); ++i ) 524 mButtons[i]->OnMotion( wxPoint( event.m_x, event.m_y ) ); 525 526 SetHintCursor( HitTestWindow( event ) ); 527 return; 528 } 529 530 wxPoint pos; 531 GetScrMousePos( event, pos ); 532 533 if ( mCursorType == HITS_WND_TITLE ) 534 { 535 int w,h; 536 GetSize( &w, &h ); 537 538 SetSize( mInitialRect.x + pos.x - mDragOrigin.x, 539 mInitialRect.y + pos.y - mDragOrigin.y, 540 w,h, 0 ); 541 } 542 543 else 544 { 545 wxPoint delta( pos.x - mDragOrigin.x, pos.y - mDragOrigin.y ); 546 547 wxRect newRect; 548 549 wxSize minDim = GetMinimalWndDim(); 550 551 CalcResizedRect( newRect, delta, minDim ); 552 553 wxSize borderDim( ( mWndHorizGap + mClntHorizGap )*2, 554 ( mWndVertGap + mClntVertGap )*2 + mTitleHeight ); 555 556 wxSize preferred = GetPreferredSize( wxSize( newRect.width - borderDim.x, 557 newRect.height - borderDim.y ) ); 558 559 preferred.x += borderDim.x; 560 preferred.y += borderDim.y; 561 562 //CalcResizedRect( newRect, delta, preferred ); 563 564 wxRect finalRect = newRect; 565 566 AdjustRectPos( newRect, preferred, finalRect ); 567 568 if ( mRealTimeUpdatesOn ) 569 { 570 SetSize( finalRect.x, finalRect.y, 571 finalRect.width, finalRect.height, 0 ); 572 } 573 else 574 { 575 DrawHintRect( mPrevHintRect ); 576 DrawHintRect( finalRect ); 577 578 ::wxLogTrace(wxT("wxToolWindow"),wxT("%d,%d / %d,%d\n"), finalRect.x, finalRect.y, finalRect.width, finalRect.height); 579 } 580 581 mPrevHintRect = finalRect; 582 } 583} 584 585void wxToolWindow::OnLeftDown( wxMouseEvent& event ) 586{ 587 int result = HitTestWindow( event ); 588 589 for( size_t i = 0; i != mButtons.Count(); ++i ) 590 { 591 mButtons[i]->OnLeftDown( wxPoint( event.m_x, event.m_y ) ); 592 593 if ( mButtons[i]->IsPressed() ) 594 return; // button hitted, 595 } 596 597 if ( result >= HITS_WND_LEFT_EDGE || result == HITS_WND_TITLE ) 598 { 599 GetScrMousePos( event, mDragOrigin ); 600 601 /* 602 if ( mMouseCaptured `) 603 { 604 ReleaseMouse(); 605 mMouseCaptured = false; 606 }*/ 607 608 if ( result == HITS_WND_TITLE && 609 HandleTitleClick( event ) ) 610 return; 611 612 mResizeStarted = true; 613 614 int x,y; 615 GetPosition( &x, &y ); 616 617 mInitialRect.x = x; 618 mInitialRect.y = y; 619 620 GetSize( &x, &y ); 621 mInitialRect.width = x; 622 mInitialRect.height = y; 623 624 mPrevHintRect = mInitialRect; 625 626 if ( mCursorType != HITS_WND_TITLE && !mRealTimeUpdatesOn ) 627 { 628 mpScrDc = new wxScreenDC(); 629 630 wxScreenDC::StartDrawingOnTop( (wxRect*)NULL ); 631 632 DrawHintRect( mInitialRect ); 633 } 634 } 635} 636 637void wxToolWindow::OnLeftUp( wxMouseEvent& event ) 638{ 639 for( size_t i = 0; i != mButtons.Count(); ++i ) 640 { 641 mButtons[i]->OnLeftUp( wxPoint( event.m_x, event.m_y ) ); 642 643 if ( mButtons[i]->WasClicked() ) 644 { 645 OnMiniButtonClicked( i ); // notify derived classes 646 mButtons[i]->Reset(); 647 } 648 } 649 650 if ( mResizeStarted ) 651 { 652 mResizeStarted = false; 653 654 if ( mCursorType != HITS_WND_TITLE ) 655 { 656 if ( !mRealTimeUpdatesOn ) 657 { 658 DrawHintRect( mPrevHintRect ); 659 660 wxScreenDC::EndDrawingOnTop(); 661 662 delete mpScrDc; 663 664 mpScrDc = NULL; 665 666 SetSize( mPrevHintRect.x, mPrevHintRect.y, 667 mPrevHintRect.width, mPrevHintRect.height, 0 ); 668 } 669 } 670 } 671} 672 673void wxToolWindow::OnSize( wxSizeEvent& WXUNUSED(event) ) 674{ 675 if ( mpClientWnd ) 676 { 677 int w,h; 678 GetSize( &w, &h ); 679 680 int x = mWndHorizGap + mClntHorizGap; 681 int y = mWndVertGap + mTitleHeight + mClntVertGap; 682 683 mpClientWnd->SetSize( x-1, y-1, 684 w - 2*(mWndHorizGap + mClntHorizGap), 685 h - y - mClntVertGap - mWndVertGap, 686 0 687 ); 688 } 689 690 LayoutMiniButtons(); 691} 692 693wxSize wxToolWindow::GetPreferredSize( const wxSize& given ) 694{ 695 return given; 696} 697 698void wxToolWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) ) 699{ 700 // nothing 701} 702 703/***** Implementation for class cbMiniButton *****/ 704 705cbMiniButton::cbMiniButton() 706 707 : mVisible( true ), 708 mEnabled( true ), 709 710 mpLayout( NULL ), 711 mpPane ( NULL ), 712 mpPlugin( NULL ), 713 mpWnd ( NULL ), 714 715 mWasClicked( false ), 716 mDragStarted( false ), 717 mPressed( false ) 718{} 719 720void cbMiniButton::SetPos( const wxPoint& pos ) 721{ 722 mPos = pos; 723} 724 725bool cbMiniButton::HitTest( const wxPoint& pos ) 726{ 727 if ( !mVisible ) return false; 728 729 return ( pos.x >= mPos.x && pos.y >= mPos.y && 730 pos.x < mPos.x + BTN_BOX_WIDTH && 731 pos.y < mPos.y + BTN_BOX_HEIGHT ); 732} 733 734void cbMiniButton::OnLeftDown( const wxPoint& pos ) 735{ 736 if ( !mVisible || mDragStarted ) return; 737 738 if ( HitTest( pos ) && mEnabled ) 739 { 740 if ( mpPlugin ) 741 { 742 mpLayout->CaptureEventsForPane( mpPane ); 743 mpLayout->CaptureEventsForPlugin( mpPlugin ); 744 } 745 else 746 mpWnd->CaptureMouse(); 747 748 mDragStarted = true; 749 mPressed = true; 750 mWasClicked = false; 751 752 Refresh(); 753 } 754} 755 756void cbMiniButton::OnLeftUp( const wxPoint& WXUNUSED(pos) ) 757{ 758 if ( !mVisible || !mDragStarted ) return; 759 760 if ( mpPlugin ) 761 { 762 mpLayout->ReleaseEventsFromPane( mpPane ); 763 mpLayout->ReleaseEventsFromPlugin( mpPlugin ); 764 } 765 else 766 mpWnd->ReleaseMouse(); 767 768 mWasClicked = mPressed; 769 mDragStarted = false; 770 771 mPressed = false; 772 Refresh(); 773} 774 775void cbMiniButton::OnMotion( const wxPoint& pos ) 776{ 777 if ( !mVisible ) return; 778 779 if ( mDragStarted ) 780 { 781 mPressed = HitTest( pos ); 782 783 Refresh(); 784 } 785} 786 787void cbMiniButton::Refresh() 788{ 789 if ( mpLayout ) 790 { 791 wxClientDC dc( &mpLayout->GetParentFrame() ); 792 793 Draw( dc ); 794 } 795 else 796 { 797 wxWindowDC dc( mpWnd ); 798 799 Draw( dc ); 800 } 801} 802 803void cbMiniButton::Draw( wxDC& dc ) 804{ 805 if ( !mVisible ) return; 806 807 dc.SetPen( *wxTRANSPARENT_PEN ); 808 809 dc.SetBrush( *wxLIGHT_GREY_BRUSH ); 810 811 dc.DrawRectangle( mPos.x + 1, mPos.y + 1, BTN_BOX_WIDTH - 2, BTN_BOX_HEIGHT - 2 ); 812 813 // "hard-code" metafile 814 815 if ( !mPressed ) 816 dc.SetPen( *wxWHITE_PEN ); 817 else 818 dc.SetPen( *wxBLACK_PEN ); 819 820 dc.DrawLine( mPos.x, mPos.y, mPos.x + BTN_BOX_WIDTH, mPos.y ); 821 dc.DrawLine( mPos.x, mPos.y, mPos.x, mPos.y + BTN_BOX_HEIGHT ); 822 823 dc.SetPen( *wxGREY_PEN ); 824 825 if ( !mPressed ) 826 { 827 dc.DrawLine( mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2, 828 mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT - 2 ); 829 830 dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1, 831 mPos.x + BTN_BOX_WIDTH - 2, mPos.y + BTN_BOX_HEIGHT - 1 ); 832 } 833 else 834 { 835 dc.DrawLine( mPos.x + 1, mPos.y + 1, 836 mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1 ); 837 838 dc.DrawLine( mPos.x + 1, mPos.y + 1, 839 mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2 ); 840 } 841 842 if ( !mPressed ) 843 dc.SetPen( *wxBLACK_PEN ); 844 else 845 dc.SetPen( *wxWHITE_PEN ); 846 847 dc.DrawLine( mPos.x, mPos.y + BTN_BOX_HEIGHT - 1, 848 mPos.x + BTN_BOX_WIDTH, mPos.y + BTN_BOX_HEIGHT - 1 ); 849 850 dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 1, mPos.y , 851 mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT ); 852} 853 854bool cbMiniButton::WasClicked() 855{ 856 return mWasClicked; 857} 858 859void cbMiniButton::Reset() 860{ 861 mWasClicked = false; 862} 863 864/***** Implementation fro class cbCloseBox *****/ 865 866void cbCloseBox::Draw( wxDC& dc ) 867{ 868 cbMiniButton::Draw( dc ); 869 870 dc.SetPen( *wxBLACK_PEN ); 871 872 int width = BTN_BOX_WIDTH - 7; 873 874 int xOfs = (mPressed) ? 4 : 3; 875 int yOfs = (mPressed) ? 4 : 3; 876 877 for( int i = 0; i != BTN_X_WEIGHT; ++i ) 878 { 879 dc.DrawLine( mPos.x + xOfs + i, 880 mPos.y + yOfs, 881 mPos.x + xOfs + i + width, 882 mPos.y + yOfs + width ); 883 884 dc.DrawLine( mPos.x + xOfs + i + width - 1, 885 mPos.y + yOfs, 886 mPos.x + xOfs + i - 1, 887 mPos.y + yOfs + width ); 888 } 889} 890 891/***** Implementation fro class cbCollapseBox *****/ 892 893inline static void my_swap( int& a, int& b ) 894{ 895 long tmp = a; 896 a = b; 897 b = tmp; 898} 899 900void cbCollapseBox::Draw( wxDC& dc ) 901{ 902 cbMiniButton::Draw( dc ); 903 904 dc.SetPen( *wxTRANSPARENT_PEN ); 905 906 wxPoint arr[3]; 907 908 int yOfs = (mPressed) ? 3 : 2; 909 int xOfs = (mPressed) ? 5 : 4; 910 int width = BTN_BOX_WIDTH - 8; 911 912 // rotating/shifting triangle inside collapse box 913 914 arr[0].x = xOfs; 915 arr[0].y = yOfs-1; 916 arr[2].x = xOfs; 917 arr[2].y = BTN_BOX_HEIGHT - yOfs - 1; 918 arr[1].x = xOfs + width; 919 arr[1].y = (arr[2].y + arr[0].y)/2; 920 921 if ( !mIsAtLeft ) 922 { 923 arr[0].x = BTN_BOX_WIDTH - arr[0].x; 924 arr[1].x = BTN_BOX_WIDTH - arr[1].x; 925 arr[2].x = BTN_BOX_WIDTH - arr[2].x; 926 } 927 928 if ( !mpPane->IsHorizontal() ) 929 { 930 my_swap( arr[0].y, arr[0].x ); 931 my_swap( arr[1].y, arr[1].x ); 932 my_swap( arr[2].y, arr[2].x ); 933 934 arr[0].x += 1; 935 arr[1].x += 1; 936 arr[2].x += 1; 937 938 //arr[1].y -= 1; 939 } 940 941 arr[0].x += mPos.x; 942 arr[0].y += mPos.y; 943 arr[1].x += mPos.x; 944 arr[1].y += mPos.y; 945 arr[2].x += mPos.x; 946 arr[2].y += mPos.y; 947 948 if ( !mEnabled ) dc.SetBrush( *wxGREY_BRUSH ); 949 else dc.SetBrush( *wxBLACK_BRUSH ); 950 951 dc.DrawPolygon( 3, arr ); 952 dc.SetBrush( wxNullBrush ); 953} 954 955/***** Implementation for class cbDockBoxBox *****/ 956 957void cbDockBox::Draw( wxDC& dc ) 958{ 959 cbMiniButton::Draw( dc ); 960 961 int width = BTN_BOX_WIDTH - 7; 962 963 int xOfs = (mPressed) ? 4 : 3; 964 int yOfs = (mPressed) ? 4 : 3; 965 966 dc.SetPen( *wxBLACK_PEN ); 967 dc.SetBrush( *wxBLACK_BRUSH ); 968 969 dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width, width ); 970 971 xOfs += 1; 972 yOfs += 1; 973 974 dc.SetBrush( *wxWHITE_BRUSH ); 975 976 dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width-2, width-2 ); 977} 978 979/***** Implementation for class wxToolWindow *****/ 980 981IMPLEMENT_DYNAMIC_CLASS( cbFloatedBarWindow, wxToolWindow ) 982 983BEGIN_EVENT_TABLE( cbFloatedBarWindow, wxToolWindow ) 984 985 EVT_LEFT_DCLICK( cbFloatedBarWindow::OnDblClick ) 986 987END_EVENT_TABLE() 988 989cbFloatedBarWindow::cbFloatedBarWindow() 990 991 : mpBar( NULL ) 992{ 993 AddMiniButton( new cbCloseBox() ); 994 AddMiniButton( new cbDockBox() ); 995} 996 997void cbFloatedBarWindow::SetBar( cbBarInfo* pBar ) 998{ 999 mpBar = pBar; 1000} 1001 1002cbBarInfo* cbFloatedBarWindow::GetBar() 1003{ 1004 return mpBar; 1005} 1006 1007void cbFloatedBarWindow::SetLayout( wxFrameLayout* pLayout ) 1008{ 1009 mpLayout = pLayout; 1010} 1011 1012void cbFloatedBarWindow::PositionFloatedWnd( int scrX, int scrY, 1013 int width, int height ) 1014{ 1015 wxSize minDim = GetMinimalWndDim(); 1016 1017 SetSize( scrX - mWndHorizGap - mClntHorizGap, 1018 scrY - mClntVertGap - mTitleHeight - mWndVertGap, 1019 width + minDim.x, height + minDim.y, 0 ); 1020} 1021 1022wxSize cbFloatedBarWindow::GetPreferredSize( const wxSize& given ) 1023{ 1024 if ( mpBar->mDimInfo.GetDimHandler() ) 1025 { 1026 cbBarDimHandlerBase* pHandler = mpBar->mDimInfo.GetDimHandler(); 1027 1028 wxSize prefDim; 1029 1030 // int vtad = *((int*)pHandler); 1031 1032 pHandler->OnResizeBar( mpBar, given, prefDim ); 1033 1034 return prefDim; 1035 } 1036 else 1037 { 1038 if ( mpBar->IsFixed() ) 1039 return mpBar->mDimInfo.mSizes[ wxCBAR_FLOATING ]; 1040 else 1041 return given; // not-fixed bars are resized exactly the way user wants 1042 } 1043} 1044 1045void cbFloatedBarWindow::OnMiniButtonClicked( int btnIdx ) 1046{ 1047 // #1 - close mini-button 1048 // #0 - dock mini-button 1049 1050 if ( btnIdx == 0 ) 1051 { 1052 mpBar->mAlignment = -1; // sepcial "marking" for hidden bars out of floated state 1053 mpLayout->SetBarState( mpBar, wxCBAR_HIDDEN, true ); 1054 } 1055 else 1056 mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, true ); 1057} 1058 1059bool cbFloatedBarWindow::HandleTitleClick( wxMouseEvent& event ) 1060{ 1061 ReleaseMouse(); 1062 mMouseCaptured = false; 1063 1064 wxPoint scrPos; 1065 GetScrMousePos( event, scrPos ); 1066 1067 int msX = scrPos.x, 1068 msY = scrPos.y; 1069 1070 mpLayout->GetParentFrame().ScreenToClient( &msX, &msY ); 1071 1072 int x,y; 1073 GetPosition(&x,&y); 1074 int w,h; 1075 GetSize( &w, &h ); 1076 1077 wxSize minDim = GetMinimalWndDim(); 1078 1079 w -= minDim.x; 1080 h -= minDim.y; 1081 1082 x += mWndHorizGap + mClntHorizGap; 1083 y += mWndVertGap + mTitleHeight + mClntVertGap; 1084 1085 mpLayout->GetParentFrame().ScreenToClient( &x, &y ); 1086 1087 wxRect& bounds = mpBar->mDimInfo.mBounds[ wxCBAR_FLOATING ]; 1088 1089 bounds.x = x; 1090 bounds.y = y; 1091 bounds.width = w; 1092 bounds.height = h; 1093 1094 cbStartBarDraggingEvent dragEvt( mpBar, wxPoint(msX,msY), 1095 mpLayout->GetPanesArray()[FL_ALIGN_TOP] ); 1096 1097 mpLayout->FirePluginEvent( dragEvt ); 1098 1099 return true; 1100} 1101 1102void cbFloatedBarWindow::OnDblClick( wxMouseEvent& WXUNUSED(event) ) 1103{ 1104 mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, true ); 1105 1106 //wxMessageBox("toolWnd - dblClick!"); 1107} 1108 1109