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