]>
Commit | Line | Data |
---|---|---|
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$ | |
8 | // Copyright: (c) Aleksandras Gluchovas | |
9 | // Licence: wxWindows licence | |
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 | ||
169 | void cbBarHintsPlugin::ExcludeHints( wxRect& rect, cbBarInfo& info ) | |
170 | { | |
171 | int boxHeight = BTN_BOX_HEIGHT; | |
172 | ||
173 | // collapse and close box are not placed on fixed bars | |
174 | ||
175 | if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) ) | |
176 | ||
177 | boxHeight = 0; | |
178 | ||
179 | int height = wxMax( mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP) | |
180 | - GROOVE_TO_GROOVE_GAP, | |
181 | boxHeight | |
182 | ); | |
183 | ||
184 | if ( mpPane->IsHorizontal() ) | |
185 | { | |
186 | rect.x += ( mHintGap*2 + height ); | |
187 | rect.width -= (height + 2*mHintGap); | |
188 | ||
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); | |
196 | ||
197 | rect.y -= info.mDimInfo.mVertGap + 2; | |
198 | rect.height += info.mDimInfo.mVertGap + 2; | |
199 | } | |
200 | } | |
201 | ||
202 | void cbBarHintsPlugin::DoDrawHint( wxDC& dc, wxRect& rect, | |
203 | int pos, int boxOfs, int grooveOfs, | |
204 | bool isFixed ) | |
205 | { | |
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 ); | |
237 | } | |
238 | ||
239 | void cbBarHintsPlugin::GetHintsLayout( wxRect& rect, cbBarInfo& info, | |
240 | int& boxOfs, int& grooveOfs, int& pos ) | |
241 | { | |
242 | int boxHeight = BTN_BOX_HEIGHT; | |
243 | // int boxWidth = BTN_BOX_WIDTH + BOX_TO_GROOVE_GAP + BTN_BOX_WIDTH; | |
244 | ||
245 | // collapse and close box are not placed on fixed bars | |
246 | ||
247 | if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) ) | |
248 | { | |
249 | boxHeight = 0; | |
250 | // boxWidth = 0; | |
251 | } | |
252 | /* | |
253 | else | |
254 | if ( !mCloseBoxOn || !mCollapseBoxOn ) | |
255 | ||
256 | boxWidth = BTN_BOX_WIDTH; | |
257 | */ | |
258 | int grooveHeight = mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP) | |
259 | - GROOVE_TO_GROOVE_GAP; | |
260 | ||
261 | int height = wxMax( grooveHeight, boxHeight ); | |
262 | ||
263 | // center boxs and groves with respect to each other | |
264 | ||
265 | boxOfs = ( height - boxHeight ) / 2; | |
266 | grooveOfs = ( height - grooveHeight ) / 2; | |
267 | ||
268 | pos = ( mpPane->IsHorizontal() ) ? rect.y + mHintGap | |
269 | : rect.x + rect.width - mHintGap; | |
270 | ||
271 | // setup positions for boxes | |
272 | ||
273 | if ( !info.IsFixed() ) | |
274 | { | |
275 | // what direction "collapse-triangle" should look at? | |
276 | ||
277 | bool& isAtLeft = ((cbCollapseBox*)(mBoxes[COLLAPSE_BOX_IDX]))->mIsAtLeft; | |
278 | ||
279 | isAtLeft= info.mBounds.x <= mpPane->mPaneWidth - ( info.mBounds.x + info.mBounds.width ); | |
280 | ||
281 | if ( info.IsExpanded() ) | |
282 | { | |
283 | isAtLeft = FALSE; | |
284 | ||
285 | cbBarInfo* pCur = info.mpPrev; | |
286 | ||
287 | while( pCur ) | |
288 | { | |
289 | if ( !pCur->IsFixed() ) | |
290 | { | |
291 | isAtLeft = TRUE; break; | |
292 | } | |
293 | ||
294 | pCur = pCur->mpPrev; | |
295 | } | |
296 | } | |
297 | ||
298 | // collapse/expand works only when more not-fixed bars are present in the same row | |
299 | ||
300 | mBoxes[COLLAPSE_BOX_IDX]->Enable( info.mpRow->mNotFixedBarsCnt > 1 ); | |
301 | ||
302 | int i; | |
303 | for ( i = 0; i != BOXES_IN_HINT; ++i ) | |
304 | { | |
305 | mBoxes[i]->mpPane = mpPane; | |
306 | } | |
307 | ||
308 | if ( mpPane->IsHorizontal() ) | |
309 | { | |
310 | if ( mCloseBoxOn ) | |
311 | { | |
312 | mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos ); | |
313 | ||
314 | pos += BTN_BOX_HEIGHT; | |
315 | } | |
316 | ||
317 | if ( mCollapseBoxOn ) | |
318 | { | |
319 | if ( mCloseBoxOn ) pos += BOX_T_BOX_GAP; | |
320 | ||
321 | mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos ); | |
322 | ||
323 | pos += BTN_BOX_HEIGHT; | |
324 | ||
325 | pos += BOX_TO_GROOVE_GAP; | |
326 | } | |
327 | } | |
328 | else | |
329 | { | |
330 | if ( mCloseBoxOn ) | |
331 | { | |
332 | pos -= BTN_BOX_WIDTH; | |
333 | ||
334 | mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( pos , rect.y + mHintGap + boxOfs ); | |
335 | } | |
336 | ||
337 | if ( mCollapseBoxOn ) | |
338 | { | |
339 | if ( mCloseBoxOn ) pos -= BOX_T_BOX_GAP; | |
340 | ||
341 | pos -= BTN_BOX_WIDTH; | |
342 | ||
343 | mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( pos, rect.y + mHintGap + boxOfs ); | |
344 | ||
345 | pos -= BOX_TO_GROOVE_GAP; | |
346 | } | |
347 | } | |
348 | } | |
349 | } | |
350 | ||
351 | static inline bool is_in_box( const wxPoint& rectPos, const wxPoint& mousePos ) | |
352 | { | |
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 ); | |
357 | } | |
358 | ||
359 | int cbBarHintsPlugin::HitTestHints( cbBarInfo& info, const wxPoint& pos ) | |
360 | { | |
361 | wxPoint inPane = pos; | |
362 | mpPane->PaneToFrame( &inPane.x, &inPane.y ); | |
363 | ||
364 | wxRect& rect = info.mBoundsInParent; | |
365 | ||
366 | if ( info.IsFixed() ) return FALSE; | |
367 | ||
368 | int boxOfs, grooveOfs, coord; | |
369 | ||
370 | GetHintsLayout( rect, info, boxOfs, grooveOfs, coord ); | |
371 | ||
372 | if ( mpPane->IsHorizontal() ) | |
373 | { | |
374 | if ( mCloseBoxOn ) | |
375 | { | |
376 | if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) ) | |
377 | ||
378 | return CLOSE_BOX_HITTED; | |
379 | ||
380 | coord += BTN_BOX_HEIGHT; | |
381 | } | |
382 | ||
383 | if ( mCollapseBoxOn ) | |
384 | { | |
385 | if ( mCloseBoxOn ) coord += BOX_T_BOX_GAP; | |
386 | ||
387 | if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) ) | |
388 | ||
389 | return COLLAPSE_BOX_HITTED; | |
390 | ||
391 | coord += BTN_BOX_HEIGHT; | |
392 | } | |
393 | } | |
394 | else | |
395 | { | |
396 | if ( mCloseBoxOn ) | |
397 | { | |
398 | coord -= BTN_BOX_WIDTH; | |
399 | ||
400 | if ( is_in_box( wxPoint( coord , rect.y + mHintGap + boxOfs ), inPane ) ) | |
401 | ||
402 | return CLOSE_BOX_HITTED; | |
403 | } | |
404 | ||
405 | if ( mCollapseBoxOn ) | |
406 | { | |
407 | if ( mCloseBoxOn ) coord -= BOX_T_BOX_GAP; | |
408 | coord -= BTN_BOX_WIDTH; | |
409 | ||
410 | if ( is_in_box( wxPoint( coord, rect.y + mHintGap + boxOfs ), inPane ) ) | |
411 | ||
412 | return COLLAPSE_BOX_HITTED; | |
413 | } | |
414 | } | |
415 | ||
416 | return FALSE; | |
417 | } | |
418 | ||
419 | // handlers for plugin-events | |
420 | ||
421 | void cbBarHintsPlugin::OnSizeBarWindow( cbSizeBarWndEvent& event ) | |
422 | { | |
423 | wxRect& rect = event.mBoundsInParent; | |
424 | mpPane = event.mpPane; | |
425 | ||
426 | ExcludeHints( rect, *event.mpBar ); | |
427 | ||
428 | event.Skip(); // pass event to the next plugin in the chain | |
429 | } | |
430 | ||
431 | void cbBarHintsPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent& event ) | |
432 | { | |
433 | wxRect& rect = event.mBoundsInParent; | |
434 | mpPane = event.mpPane; | |
435 | ||
436 | int boxOfs, grooveOfs, pos; | |
437 | ||
438 | GetHintsLayout( rect, *event.mpBar, boxOfs, grooveOfs, pos ); | |
439 | ||
440 | DoDrawHint( *event.mpDc, rect, pos, boxOfs, grooveOfs, event.mpBar->IsFixed() ); | |
441 | ||
442 | // let other plugins add on their decorations | |
443 | ||
444 | event.Skip(); | |
445 | } | |
446 | ||
447 | void cbBarHintsPlugin::OnLeftDown( cbLeftDownEvent& event ) | |
448 | { | |
449 | mpPane = event.mpPane; | |
450 | wxPoint inFrame = event.mPos; | |
451 | ||
452 | mpPane->PaneToFrame( &inFrame.x, &inFrame.y ); | |
453 | ||
454 | wxBarIterator iter( mpPane->GetRowList() ); | |
455 | ||
456 | mpClickedBar = NULL; | |
457 | ||
458 | while ( iter.Next() ) | |
459 | { | |
460 | cbBarInfo& bar = iter.BarInfo(); | |
461 | ||
462 | int boxOfs, grooveOfs, pos; | |
463 | ||
464 | GetHintsLayout( bar.mBoundsInParent, bar, boxOfs, grooveOfs, pos ); | |
465 | ||
466 | if ( !bar.IsFixed() ) | |
467 | { | |
468 | int i; | |
469 | for ( i = 0; i != BOXES_IN_HINT; ++i ) | |
470 | { | |
471 | mBoxes[i]->OnLeftDown( inFrame ); | |
472 | ||
473 | if ( mBoxes[i]->mPressed ) | |
474 | { | |
475 | mBtnPressed = TRUE; | |
476 | mpClickedBar = &bar; | |
477 | ||
478 | return; // event handled | |
479 | } | |
480 | } | |
481 | } | |
482 | } | |
483 | ||
484 | event.Skip(); | |
485 | } | |
486 | ||
487 | void cbBarHintsPlugin::OnLeftUp( cbLeftUpEvent& event ) | |
488 | { | |
489 | if ( mBtnPressed ) | |
490 | { | |
491 | wxPoint inFrame = event.mPos; | |
492 | mpPane->PaneToFrame( &inFrame.x, &inFrame.y ); | |
493 | ||
494 | int boxOfs, grooveOfs, pos; | |
495 | ||
496 | GetHintsLayout( mpClickedBar->mBoundsInParent, *mpClickedBar, boxOfs, grooveOfs, pos ); | |
497 | ||
498 | int result = HitTestHints( *mpClickedBar, event.mPos ); | |
499 | ||
500 | int i; | |
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(); | |
526 | } | |
527 | ||
528 | void cbBarHintsPlugin::OnMotion( cbMotionEvent& event ) | |
529 | { | |
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(); | |
545 | } | |
546 | ||
547 | void cbBarHintsPlugin::OnInitPlugin() | |
548 | { | |
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(); | |
563 | } |