1///////////////////////////////////////////////////////////////////////////// 2// Name: barhintspl.h 3// Purpose: Implementation for cbBarHintsPlugin 4// Author: Aleksandras Gluchovas 5// Modified by: 6// Created: 30/11/98 (my 22th birthday :-) 7// RCS-ID: $Id: barhintspl.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/utils.h" 24#include "wx/fl/barhintspl.h" 25 26// fixed settings 27 28#define GROOVE_WIDTH 3 // left shade + middle line + right shade 29#define GROOVE_TO_GROOVE_GAP 1 30#define BOX_T_BOX_GAP 2 31#define BOX_TO_GROOVE_GAP 3 32 33#define BOXES_IN_HINT 2 34#define CLOSE_BOX_IDX 0 35#define COLLAPSE_BOX_IDX 1 36 37// used interally 38 39#define CLOSE_BOX_HITTED 1 40#define COLLAPSE_BOX_HITTED 2 41 42/***** Implementation fro class cbBarHintsPlugin *****/ 43 44IMPLEMENT_DYNAMIC_CLASS( cbBarHintsPlugin, cbPluginBase ) 45 46BEGIN_EVENT_TABLE( cbBarHintsPlugin, cbPluginBase ) 47 48 EVT_PL_SIZE_BAR_WND ( cbBarHintsPlugin::OnSizeBarWindow ) 49 EVT_PL_DRAW_BAR_DECOR( cbBarHintsPlugin::OnDrawBarDecorations ) 50 51 EVT_PL_LEFT_DOWN( cbBarHintsPlugin::OnLeftDown ) 52 EVT_PL_LEFT_UP ( cbBarHintsPlugin::OnLeftUp ) 53 EVT_PL_MOTION ( cbBarHintsPlugin::OnMotion ) 54 55END_EVENT_TABLE() 56 57cbBarHintsPlugin::cbBarHintsPlugin(void) 58 59 : mpPane( 0 ), 60 mBtnPressed ( false ), 61 mCloseBoxOn ( true ), 62 mCollapseBoxOn( true ), 63 mGrooveCount ( 2 ), 64 mHintGap ( 4 ), 65 mXWeight ( 2 ) 66{ 67 mBoxes[CLOSE_BOX_IDX] = NULL; 68 mBoxes[COLLAPSE_BOX_IDX] = NULL; 69} 70 71cbBarHintsPlugin::cbBarHintsPlugin( wxFrameLayout* pLayout, int paneMask ) 72 73 : cbPluginBase( pLayout, paneMask ), 74 mpPane( 0 ), 75 mBtnPressed ( false ), 76 mCloseBoxOn ( true ), 77 mCollapseBoxOn( true ), 78 mGrooveCount ( 2 ), 79 mHintGap ( 5 ), 80 mXWeight ( 2 ) 81{ 82 mBoxes[CLOSE_BOX_IDX] = NULL; 83 mBoxes[COLLAPSE_BOX_IDX] = NULL; 84} 85 86 87cbBarHintsPlugin::~cbBarHintsPlugin() 88{ 89 if (mBoxes[CLOSE_BOX_IDX]) 90 delete mBoxes[CLOSE_BOX_IDX]; 91 92 if (mBoxes[COLLAPSE_BOX_IDX]) 93 delete mBoxes[COLLAPSE_BOX_IDX]; 94} // cbBarHintsPlugin destructor 95 96 97void cbBarHintsPlugin::SetGrooveCount( int nGrooves ) 98{ 99 mGrooveCount = nGrooves; 100} 101 102void cbBarHintsPlugin::CreateBoxes() 103{ 104 cbCloseBox* box1 = new cbCloseBox(); 105 cbCollapseBox* box2 = new cbCollapseBox(); 106 107 mBoxes[CLOSE_BOX_IDX] = box1; 108 mBoxes[COLLAPSE_BOX_IDX] = box2; 109 110 int i; 111 for ( i = 0; i != BOXES_IN_HINT; ++i ) 112 { 113 mBoxes[i]->mpLayout = mpLayout; 114 mBoxes[i]->mpPlugin = this; 115 mBoxes[i]->mpWnd = NULL; 116 } 117} 118 119 120void cbBarHintsPlugin::Draw3DBox( wxDC& WXUNUSED(dc), const wxPoint& WXUNUSED(pos), bool WXUNUSED(pressed) ) 121{ 122} 123 124void cbBarHintsPlugin::DrawCloseBox( wxDC& WXUNUSED(dc), const wxPoint& WXUNUSED(pos), bool WXUNUSED(pressed) ) 125{ 126} 127 128void cbBarHintsPlugin::DrawCollapseBox( wxDC& WXUNUSED(dc), const wxPoint& WXUNUSED(pos), 129 bool WXUNUSED(atLeft), bool WXUNUSED(disabled), bool WXUNUSED(pressed) ) 130{ 131} 132 133void cbBarHintsPlugin::DrawGrooves( wxDC& dc, const wxPoint& pos, int length ) 134{ 135 int ofs = 0; 136 137 int i; 138 for ( i = 0; i != mGrooveCount; ++i, ofs += ( GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP ) ) 139 { 140 if ( mpPane->IsHorizontal() ) 141 { 142 dc.SetPen( mpLayout->mLightPen ); 143 dc.DrawLine( pos.x + ofs, pos.y, pos.x + ofs, pos.y + length - 1 ); 144 dc.DrawPoint( pos.x + ofs + 1, pos.y ); 145 146 dc.SetPen( mpLayout->mDarkPen ); 147 dc.DrawLine( pos.x + ofs + 2, pos.y, pos.x + ofs + 2, pos.y + length ); 148 dc.DrawPoint( pos.x + ofs + 1, pos.y + length - 1 ); 149 dc.DrawPoint( pos.x + ofs, pos.y + length - 1 ); 150 } 151 else 152 { 153 dc.SetPen( mpLayout->mLightPen ); 154 dc.DrawLine( pos.x, pos.y + ofs, pos.x + length - 1, pos.y + ofs ); 155 dc.DrawPoint( pos.x, pos.y + ofs + 1 ); 156 157 dc.SetPen( mpLayout->mDarkPen ); 158 dc.DrawLine( pos.x, pos.y + ofs + 2, pos.x + length, pos.y + ofs + 2 ); 159 dc.DrawPoint( pos.x + length - 1, pos.y + ofs + 1 ); 160 dc.DrawPoint( pos.x + length - 1, pos.y + ofs ); 161 } 162 } 163} 164 165void cbBarHintsPlugin::ExcludeHints( wxRect& rect, cbBarInfo& info ) 166{ 167 int boxHeight = BTN_BOX_HEIGHT; 168 169 // collapse and close box are not placed on fixed bars 170 171 if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) ) 172 173 boxHeight = 0; 174 175 int height = wxMax( mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP) 176 - GROOVE_TO_GROOVE_GAP, 177 boxHeight 178 ); 179 180 if ( mpPane->IsHorizontal() ) 181 { 182 rect.x += ( mHintGap*2 + height ); 183 rect.width -= (height + 2*mHintGap); 184 185 rect.x -= info.mDimInfo.mHorizGap + 2; 186 rect.width += info.mDimInfo.mHorizGap + 2; 187 } 188 else 189 { 190 rect.y += (mHintGap*2 + height); 191 rect.height -= (height + 2*mHintGap); 192 193 rect.y -= info.mDimInfo.mVertGap + 2; 194 rect.height += info.mDimInfo.mVertGap + 2; 195 } 196} 197 198void cbBarHintsPlugin::DoDrawHint( wxDC& dc, wxRect& rect, 199 int pos, int WXUNUSED(boxOfs), int grooveOfs, 200 bool isFixed ) 201{ 202 if ( !isFixed ) 203 { 204 if ( mpPane->IsHorizontal() ) 205 { 206 if ( mCloseBoxOn ) 207 208 mBoxes[CLOSE_BOX_IDX]->Draw( dc ); 209 210 if ( mCollapseBoxOn ) 211 212 mBoxes[COLLAPSE_BOX_IDX]->Draw( dc ); 213 } 214 else 215 { 216 if ( mCloseBoxOn ) 217 218 mBoxes[CLOSE_BOX_IDX]->Draw( dc ); 219 220 if ( mCollapseBoxOn ) 221 222 mBoxes[COLLAPSE_BOX_IDX]->Draw( dc ); 223 } 224 } 225 226 if ( mpPane->IsHorizontal() ) 227 228 DrawGrooves( dc, wxPoint( rect.x + mHintGap + grooveOfs, pos ), 229 rect.height - (pos - rect.y) - mHintGap ); 230 else 231 DrawGrooves( dc, wxPoint( rect.x + mHintGap, rect.y + mHintGap + grooveOfs ), 232 (pos - rect.x) - mHintGap ); 233} 234 235void cbBarHintsPlugin::GetHintsLayout( wxRect& rect, cbBarInfo& info, 236 int& boxOfs, int& grooveOfs, int& pos ) 237{ 238 int boxHeight = BTN_BOX_HEIGHT; 239// int boxWidth = BTN_BOX_WIDTH + BOX_TO_GROOVE_GAP + BTN_BOX_WIDTH; 240 241 // collapse and close box are not placed on fixed bars 242 243 if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) ) 244 { 245 boxHeight = 0; 246// boxWidth = 0; 247 } 248/* 249 else 250 if ( !mCloseBoxOn || !mCollapseBoxOn ) 251 252 boxWidth = BTN_BOX_WIDTH; 253*/ 254 int grooveHeight = mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP) 255 - GROOVE_TO_GROOVE_GAP; 256 257 int height = wxMax( grooveHeight, boxHeight ); 258 259 // center boxs and groves with respect to each other 260 261 boxOfs = ( height - boxHeight ) / 2; 262 grooveOfs = ( height - grooveHeight ) / 2; 263 264 pos = ( mpPane->IsHorizontal() ) ? rect.y + mHintGap 265 : rect.x + rect.width - mHintGap; 266 267 // setup positions for boxes 268 269 if ( !info.IsFixed() ) 270 { 271 // what direction "collapse-triangle" should look at? 272 273 bool& isAtLeft = ((cbCollapseBox*)(mBoxes[COLLAPSE_BOX_IDX]))->mIsAtLeft; 274 275 isAtLeft= info.mBounds.x <= mpPane->mPaneWidth - ( info.mBounds.x + info.mBounds.width ); 276 277 if ( info.IsExpanded() ) 278 { 279 isAtLeft = false; 280 281 cbBarInfo* pCur = info.mpPrev; 282 283 while( pCur ) 284 { 285 if ( !pCur->IsFixed() ) 286 { 287 isAtLeft = true; break; 288 } 289 290 pCur = pCur->mpPrev; 291 } 292 } 293 294 // collapse/expand works only when more not-fixed bars are present in the same row 295 296 mBoxes[COLLAPSE_BOX_IDX]->Enable( info.mpRow->mNotFixedBarsCnt > 1 ); 297 298 int i; 299 for ( i = 0; i != BOXES_IN_HINT; ++i ) 300 { 301 mBoxes[i]->mpPane = mpPane; 302 } 303 304 if ( mpPane->IsHorizontal() ) 305 { 306 if ( mCloseBoxOn ) 307 { 308 mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos ); 309 310 pos += BTN_BOX_HEIGHT; 311 } 312 313 if ( mCollapseBoxOn ) 314 { 315 if ( mCloseBoxOn ) pos += BOX_T_BOX_GAP; 316 317 mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos ); 318 319 pos += BTN_BOX_HEIGHT; 320 321 pos += BOX_TO_GROOVE_GAP; 322 } 323 } 324 else 325 { 326 if ( mCloseBoxOn ) 327 { 328 pos -= BTN_BOX_WIDTH; 329 330 mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( pos , rect.y + mHintGap + boxOfs ); 331 } 332 333 if ( mCollapseBoxOn ) 334 { 335 if ( mCloseBoxOn ) pos -= BOX_T_BOX_GAP; 336 337 pos -= BTN_BOX_WIDTH; 338 339 mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( pos, rect.y + mHintGap + boxOfs ); 340 341 pos -= BOX_TO_GROOVE_GAP; 342 } 343 } 344 } 345} 346 347static inline bool is_in_box( const wxPoint& rectPos, const wxPoint& mousePos ) 348{ 349 return ( mousePos.x >= rectPos.x && 350 mousePos.y >= rectPos.y && 351 mousePos.x < rectPos.x + BTN_BOX_WIDTH && 352 mousePos.y < rectPos.y + BTN_BOX_HEIGHT ); 353} 354 355int cbBarHintsPlugin::HitTestHints( cbBarInfo& info, const wxPoint& pos ) 356{ 357 wxPoint inPane = pos; 358 mpPane->PaneToFrame( &inPane.x, &inPane.y ); 359 360 wxRect& rect = info.mBoundsInParent; 361 362 if ( info.IsFixed() ) return false; 363 364 int boxOfs, grooveOfs, coord; 365 366 GetHintsLayout( rect, info, boxOfs, grooveOfs, coord ); 367 368 if ( mpPane->IsHorizontal() ) 369 { 370 if ( mCloseBoxOn ) 371 { 372 if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) ) 373 374 return CLOSE_BOX_HITTED; 375 376 coord += BTN_BOX_HEIGHT; 377 } 378 379 if ( mCollapseBoxOn ) 380 { 381 if ( mCloseBoxOn ) coord += BOX_T_BOX_GAP; 382 383 if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) ) 384 385 return COLLAPSE_BOX_HITTED; 386 387 coord += BTN_BOX_HEIGHT; 388 } 389 } 390 else 391 { 392 if ( mCloseBoxOn ) 393 { 394 coord -= BTN_BOX_WIDTH; 395 396 if ( is_in_box( wxPoint( coord , rect.y + mHintGap + boxOfs ), inPane ) ) 397 398 return CLOSE_BOX_HITTED; 399 } 400 401 if ( mCollapseBoxOn ) 402 { 403 if ( mCloseBoxOn ) coord -= BOX_T_BOX_GAP; 404 coord -= BTN_BOX_WIDTH; 405 406 if ( is_in_box( wxPoint( coord, rect.y + mHintGap + boxOfs ), inPane ) ) 407 408 return COLLAPSE_BOX_HITTED; 409 } 410 } 411 412 return false; 413} 414 415// handlers for plugin-events 416 417void cbBarHintsPlugin::OnSizeBarWindow( cbSizeBarWndEvent& event ) 418{ 419 wxRect& rect = event.mBoundsInParent; 420 mpPane = event.mpPane; 421 422 ExcludeHints( rect, *event.mpBar ); 423 424 event.Skip(); // pass event to the next plugin in the chain 425} 426 427void cbBarHintsPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent& event ) 428{ 429 wxRect& rect = event.mBoundsInParent; 430 mpPane = event.mpPane; 431 432 int boxOfs, grooveOfs, pos; 433 434 GetHintsLayout( rect, *event.mpBar, boxOfs, grooveOfs, pos ); 435 436 DoDrawHint( *event.mpDc, rect, pos, boxOfs, grooveOfs, event.mpBar->IsFixed() ); 437 438 // let other plugins add on their decorations 439 440 event.Skip(); 441} 442 443void cbBarHintsPlugin::OnLeftDown( cbLeftDownEvent& event ) 444{ 445 mpPane = event.mpPane; 446 wxPoint inFrame = event.mPos; 447 448 mpPane->PaneToFrame( &inFrame.x, &inFrame.y ); 449 450 wxBarIterator iter( mpPane->GetRowList() ); 451 452 mpClickedBar = NULL; 453 454 while ( iter.Next() ) 455 { 456 cbBarInfo& bar = iter.BarInfo(); 457 458 int boxOfs, grooveOfs, pos; 459 460 GetHintsLayout( bar.mBoundsInParent, bar, boxOfs, grooveOfs, pos ); 461 462 if ( !bar.IsFixed() ) 463 { 464 int i; 465 for ( i = 0; i != BOXES_IN_HINT; ++i ) 466 { 467 mBoxes[i]->mPressed = false; 468 mBoxes[i]->mWasClicked = false; 469 } 470 for ( i = 0; i != BOXES_IN_HINT; ++i ) 471 { 472 mBoxes[i]->OnLeftDown( inFrame ); 473 474 if ( mBoxes[i]->mPressed ) 475 { 476 mBtnPressed = true; 477 mpClickedBar = &bar; 478 479 return; // event handled 480 } 481 } 482 } 483 } 484 485 event.Skip(); 486} 487 488void cbBarHintsPlugin::OnLeftUp( cbLeftUpEvent& event ) 489{ 490 if ( mBtnPressed ) 491 { 492 wxPoint inFrame = event.mPos; 493 mpPane->PaneToFrame( &inFrame.x, &inFrame.y ); 494 495 int boxOfs, grooveOfs, pos; 496 497 GetHintsLayout( mpClickedBar->mBoundsInParent, *mpClickedBar, boxOfs, grooveOfs, pos ); 498 499 HitTestHints( *mpClickedBar, event.mPos ); 500 501 int i; 502 for ( i = 0; i != BOXES_IN_HINT; ++i ) 503 { 504 mBoxes[i]->OnLeftUp( inFrame ); 505 506 if ( mBoxes[i]->WasClicked() ) 507 { 508 if ( i == 0 ) 509 { 510 mpLayout->SetBarState( mpClickedBar, wxCBAR_HIDDEN, true ); 511 // Notify bar child window of close event: 512 if(mpClickedBar->mpBarWnd!=NULL) 513 mpClickedBar->mpBarWnd->Close(); 514 } 515 else 516 { 517 if ( mpClickedBar->IsExpanded() ) 518 mpPane->ContractBar( mpClickedBar ); 519 else 520 mpPane->ExpandBar( mpClickedBar ); 521 } 522 } 523 } 524 525 mBtnPressed = false; 526 return; 527 } 528 else 529 event.Skip(); 530} 531 532void cbBarHintsPlugin::OnMotion( cbMotionEvent& event ) 533{ 534 if ( mBtnPressed ) 535 { 536 wxPoint inFrame = event.mPos; 537 mpPane->PaneToFrame( &inFrame.x, &inFrame.y ); 538 539 mpPane = event.mpPane; 540 541 int i; 542 for ( i = 0; i != BOXES_IN_HINT; ++i ) 543 { 544 mBoxes[i]->OnMotion( inFrame ); 545 } 546 } 547 else 548 event.Skip(); 549} 550 551void cbBarHintsPlugin::OnInitPlugin() 552{ 553 cbPluginBase::OnInitPlugin(); 554 555 cbDockPane** panes = mpLayout->GetPanesArray(); 556 557 int i; 558 for ( i = 0; i != MAX_PANES; ++i ) 559 { 560 if ( panes[i]->MatchesMask( mPaneMask ) ) 561 { 562 panes[i]->mProps.mMinCBarDim.x = 25; 563 panes[i]->mProps.mMinCBarDim.y = 16; 564 } 565 } 566 CreateBoxes(); 567} 568