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