]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/fl/barhintspl.cpp
Only support detection of "near the edge" coordinates, if dragging grid lines
[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
8e08b761
JS
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
11a68fa3
GT
48 EVT_PL_SIZE_BAR_WND ( cbBarHintsPlugin::OnSizeBarWindow )
49 EVT_PL_DRAW_BAR_DECOR( cbBarHintsPlugin::OnDrawBarDecorations )
8e08b761 50
11a68fa3
GT
51 EVT_PL_LEFT_DOWN( cbBarHintsPlugin::OnLeftDown )
52 EVT_PL_LEFT_UP ( cbBarHintsPlugin::OnLeftUp )
53 EVT_PL_MOTION ( cbBarHintsPlugin::OnMotion )
8e08b761
JS
54
55END_EVENT_TABLE()
56
57cbBarHintsPlugin::cbBarHintsPlugin(void)
58
11a68fa3 59 : mpPane( 0 ),
c82c42d4
WS
60 mBtnPressed ( false ),
61 mCloseBoxOn ( true ),
62 mCollapseBoxOn( true ),
11a68fa3
GT
63 mGrooveCount ( 2 ),
64 mHintGap ( 4 ),
65 mXWeight ( 2 )
8e08b761 66{
11a68fa3
GT
67 mBoxes[CLOSE_BOX_IDX] = NULL;
68 mBoxes[COLLAPSE_BOX_IDX] = NULL;
8e08b761
JS
69}
70
71cbBarHintsPlugin::cbBarHintsPlugin( wxFrameLayout* pLayout, int paneMask )
72
11a68fa3
GT
73 : cbPluginBase( pLayout, paneMask ),
74 mpPane( 0 ),
c82c42d4
WS
75 mBtnPressed ( false ),
76 mCloseBoxOn ( true ),
77 mCollapseBoxOn( true ),
11a68fa3
GT
78 mGrooveCount ( 2 ),
79 mHintGap ( 5 ),
80 mXWeight ( 2 )
8e08b761 81{
11a68fa3
GT
82 mBoxes[CLOSE_BOX_IDX] = NULL;
83 mBoxes[COLLAPSE_BOX_IDX] = NULL;
8e08b761
JS
84}
85
86
87cbBarHintsPlugin::~cbBarHintsPlugin()
88{
89 if (mBoxes[CLOSE_BOX_IDX])
90 delete mBoxes[CLOSE_BOX_IDX];
91
11a68fa3 92 if (mBoxes[COLLAPSE_BOX_IDX])
8e08b761
JS
93 delete mBoxes[COLLAPSE_BOX_IDX];
94} // cbBarHintsPlugin destructor
95
96
97void cbBarHintsPlugin::SetGrooveCount( int nGrooves )
98{
11a68fa3 99 mGrooveCount = nGrooves;
8e08b761
JS
100}
101
102void cbBarHintsPlugin::CreateBoxes()
103{
11a68fa3
GT
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 }
8e08b761
JS
117}
118
119
196be0f1 120void cbBarHintsPlugin::Draw3DBox( wxDC& WXUNUSED(dc), const wxPoint& WXUNUSED(pos), bool WXUNUSED(pressed) )
8e08b761
JS
121{
122}
123
196be0f1 124void cbBarHintsPlugin::DrawCloseBox( wxDC& WXUNUSED(dc), const wxPoint& WXUNUSED(pos), bool WXUNUSED(pressed) )
8e08b761
JS
125{
126}
127
196be0f1
JS
128void cbBarHintsPlugin::DrawCollapseBox( wxDC& WXUNUSED(dc), const wxPoint& WXUNUSED(pos),
129 bool WXUNUSED(atLeft), bool WXUNUSED(disabled), bool WXUNUSED(pressed) )
8e08b761
JS
130{
131}
132
133void cbBarHintsPlugin::DrawGrooves( wxDC& dc, const wxPoint& pos, int length )
134{
11a68fa3
GT
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 }
8e08b761
JS
163}
164
165void cbBarHintsPlugin::ExcludeHints( wxRect& rect, cbBarInfo& info )
166{
11a68fa3 167 int boxHeight = BTN_BOX_HEIGHT;
8e08b761 168
11a68fa3 169 // collapse and close box are not placed on fixed bars
8e08b761 170
11a68fa3 171 if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) )
8e08b761 172
11a68fa3 173 boxHeight = 0;
8e08b761 174
11a68fa3
GT
175 int height = wxMax( mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP)
176 - GROOVE_TO_GROOVE_GAP,
177 boxHeight
178 );
8e08b761 179
11a68fa3
GT
180 if ( mpPane->IsHorizontal() )
181 {
182 rect.x += ( mHintGap*2 + height );
183 rect.width -= (height + 2*mHintGap);
8e08b761 184
11a68fa3
GT
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);
8e08b761 192
11a68fa3
GT
193 rect.y -= info.mDimInfo.mVertGap + 2;
194 rect.height += info.mDimInfo.mVertGap + 2;
195 }
8e08b761
JS
196}
197
198void cbBarHintsPlugin::DoDrawHint( wxDC& dc, wxRect& rect,
196be0f1 199 int pos, int WXUNUSED(boxOfs), int grooveOfs,
11a68fa3 200 bool isFixed )
8e08b761 201{
11a68fa3
GT
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 );
8e08b761
JS
233}
234
235void cbBarHintsPlugin::GetHintsLayout( wxRect& rect, cbBarInfo& info,
11a68fa3 236 int& boxOfs, int& grooveOfs, int& pos )
8e08b761 237{
11a68fa3
GT
238 int boxHeight = BTN_BOX_HEIGHT;
239// int boxWidth = BTN_BOX_WIDTH + BOX_TO_GROOVE_GAP + BTN_BOX_WIDTH;
8e08b761 240
11a68fa3 241 // collapse and close box are not placed on fixed bars
8e08b761 242
11a68fa3
GT
243 if ( info.IsFixed() || ( !mCloseBoxOn && !mCollapseBoxOn ) )
244 {
245 boxHeight = 0;
246// boxWidth = 0;
247 }
248/*
249 else
250 if ( !mCloseBoxOn || !mCollapseBoxOn )
8e08b761 251
11a68fa3
GT
252 boxWidth = BTN_BOX_WIDTH;
253*/
254 int grooveHeight = mGrooveCount*(GROOVE_WIDTH + GROOVE_TO_GROOVE_GAP)
255 - GROOVE_TO_GROOVE_GAP;
8e08b761 256
11a68fa3 257 int height = wxMax( grooveHeight, boxHeight );
8e08b761 258
11a68fa3 259 // center boxs and groves with respect to each other
8e08b761 260
11a68fa3
GT
261 boxOfs = ( height - boxHeight ) / 2;
262 grooveOfs = ( height - grooveHeight ) / 2;
8e08b761 263
11a68fa3
GT
264 pos = ( mpPane->IsHorizontal() ) ? rect.y + mHintGap
265 : rect.x + rect.width - mHintGap;
8e08b761 266
11a68fa3 267 // setup positions for boxes
8e08b761 268
11a68fa3
GT
269 if ( !info.IsFixed() )
270 {
271 // what direction "collapse-triangle" should look at?
8e08b761 272
11a68fa3
GT
273 bool& isAtLeft = ((cbCollapseBox*)(mBoxes[COLLAPSE_BOX_IDX]))->mIsAtLeft;
274
275 isAtLeft= info.mBounds.x <= mpPane->mPaneWidth - ( info.mBounds.x + info.mBounds.width );
8e08b761 276
11a68fa3
GT
277 if ( info.IsExpanded() )
278 {
c82c42d4 279 isAtLeft = false;
8e08b761 280
11a68fa3 281 cbBarInfo* pCur = info.mpPrev;
8e08b761 282
11a68fa3
GT
283 while( pCur )
284 {
285 if ( !pCur->IsFixed() )
286 {
c82c42d4 287 isAtLeft = true; break;
11a68fa3 288 }
8e08b761 289
11a68fa3
GT
290 pCur = pCur->mpPrev;
291 }
292 }
8e08b761 293
11a68fa3 294 // collapse/expand works only when more not-fixed bars are present in the same row
8e08b761 295
11a68fa3 296 mBoxes[COLLAPSE_BOX_IDX]->Enable( info.mpRow->mNotFixedBarsCnt > 1 );
8e08b761 297
11a68fa3
GT
298 int i;
299 for ( i = 0; i != BOXES_IN_HINT; ++i )
300 {
301 mBoxes[i]->mpPane = mpPane;
302 }
8e08b761 303
11a68fa3
GT
304 if ( mpPane->IsHorizontal() )
305 {
306 if ( mCloseBoxOn )
307 {
308 mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos );
8e08b761 309
11a68fa3
GT
310 pos += BTN_BOX_HEIGHT;
311 }
8e08b761 312
11a68fa3
GT
313 if ( mCollapseBoxOn )
314 {
315 if ( mCloseBoxOn ) pos += BOX_T_BOX_GAP;
8e08b761 316
11a68fa3 317 mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( rect.x + mHintGap + boxOfs, pos );
8e08b761 318
11a68fa3 319 pos += BTN_BOX_HEIGHT;
8e08b761 320
11a68fa3
GT
321 pos += BOX_TO_GROOVE_GAP;
322 }
323 }
324 else
325 {
326 if ( mCloseBoxOn )
327 {
328 pos -= BTN_BOX_WIDTH;
8e08b761 329
11a68fa3
GT
330 mBoxes[CLOSE_BOX_IDX]->mPos = wxPoint( pos , rect.y + mHintGap + boxOfs );
331 }
8e08b761 332
11a68fa3
GT
333 if ( mCollapseBoxOn )
334 {
335 if ( mCloseBoxOn ) pos -= BOX_T_BOX_GAP;
8e08b761 336
11a68fa3 337 pos -= BTN_BOX_WIDTH;
8e08b761 338
11a68fa3 339 mBoxes[COLLAPSE_BOX_IDX]->mPos = wxPoint( pos, rect.y + mHintGap + boxOfs );
8e08b761 340
11a68fa3
GT
341 pos -= BOX_TO_GROOVE_GAP;
342 }
343 }
344 }
8e08b761
JS
345}
346
347static inline bool is_in_box( const wxPoint& rectPos, const wxPoint& mousePos )
348{
11a68fa3
GT
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 );
8e08b761
JS
353}
354
355int cbBarHintsPlugin::HitTestHints( cbBarInfo& info, const wxPoint& pos )
356{
11a68fa3
GT
357 wxPoint inPane = pos;
358 mpPane->PaneToFrame( &inPane.x, &inPane.y );
8e08b761 359
11a68fa3 360 wxRect& rect = info.mBoundsInParent;
8e08b761 361
c82c42d4 362 if ( info.IsFixed() ) return false;
8e08b761 363
11a68fa3 364 int boxOfs, grooveOfs, coord;
8e08b761 365
11a68fa3 366 GetHintsLayout( rect, info, boxOfs, grooveOfs, coord );
8e08b761 367
11a68fa3
GT
368 if ( mpPane->IsHorizontal() )
369 {
370 if ( mCloseBoxOn )
371 {
372 if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) )
8e08b761 373
11a68fa3 374 return CLOSE_BOX_HITTED;
8e08b761 375
11a68fa3
GT
376 coord += BTN_BOX_HEIGHT;
377 }
8e08b761 378
11a68fa3
GT
379 if ( mCollapseBoxOn )
380 {
381 if ( mCloseBoxOn ) coord += BOX_T_BOX_GAP;
8e08b761 382
11a68fa3 383 if ( is_in_box( wxPoint( rect.x + mHintGap + boxOfs, coord ), inPane ) )
8e08b761 384
11a68fa3 385 return COLLAPSE_BOX_HITTED;
8e08b761 386
11a68fa3
GT
387 coord += BTN_BOX_HEIGHT;
388 }
389 }
390 else
391 {
392 if ( mCloseBoxOn )
393 {
394 coord -= BTN_BOX_WIDTH;
8e08b761 395
11a68fa3 396 if ( is_in_box( wxPoint( coord , rect.y + mHintGap + boxOfs ), inPane ) )
8e08b761 397
11a68fa3
GT
398 return CLOSE_BOX_HITTED;
399 }
8e08b761 400
11a68fa3
GT
401 if ( mCollapseBoxOn )
402 {
403 if ( mCloseBoxOn ) coord -= BOX_T_BOX_GAP;
404 coord -= BTN_BOX_WIDTH;
8e08b761 405
11a68fa3 406 if ( is_in_box( wxPoint( coord, rect.y + mHintGap + boxOfs ), inPane ) )
8e08b761 407
11a68fa3
GT
408 return COLLAPSE_BOX_HITTED;
409 }
410 }
8e08b761 411
c82c42d4 412 return false;
8e08b761
JS
413}
414
415// handlers for plugin-events
416
417void cbBarHintsPlugin::OnSizeBarWindow( cbSizeBarWndEvent& event )
418{
11a68fa3
GT
419 wxRect& rect = event.mBoundsInParent;
420 mpPane = event.mpPane;
8e08b761 421
11a68fa3 422 ExcludeHints( rect, *event.mpBar );
8e08b761 423
11a68fa3 424 event.Skip(); // pass event to the next plugin in the chain
8e08b761
JS
425}
426
427void cbBarHintsPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent& event )
428{
11a68fa3
GT
429 wxRect& rect = event.mBoundsInParent;
430 mpPane = event.mpPane;
8e08b761 431
11a68fa3 432 int boxOfs, grooveOfs, pos;
8e08b761 433
11a68fa3 434 GetHintsLayout( rect, *event.mpBar, boxOfs, grooveOfs, pos );
8e08b761 435
11a68fa3 436 DoDrawHint( *event.mpDc, rect, pos, boxOfs, grooveOfs, event.mpBar->IsFixed() );
8e08b761 437
11a68fa3 438 // let other plugins add on their decorations
8e08b761 439
11a68fa3 440 event.Skip();
8e08b761
JS
441}
442
443void cbBarHintsPlugin::OnLeftDown( cbLeftDownEvent& event )
444{
11a68fa3
GT
445 mpPane = event.mpPane;
446 wxPoint inFrame = event.mPos;
8e08b761 447
11a68fa3 448 mpPane->PaneToFrame( &inFrame.x, &inFrame.y );
8e08b761 449
11a68fa3 450 wxBarIterator iter( mpPane->GetRowList() );
8e08b761 451
11a68fa3 452 mpClickedBar = NULL;
8e08b761 453
11a68fa3
GT
454 while ( iter.Next() )
455 {
456 cbBarInfo& bar = iter.BarInfo();
8e08b761 457
11a68fa3 458 int boxOfs, grooveOfs, pos;
8e08b761 459
11a68fa3 460 GetHintsLayout( bar.mBoundsInParent, bar, boxOfs, grooveOfs, pos );
8e08b761 461
11a68fa3
GT
462 if ( !bar.IsFixed() )
463 {
464 int i;
465 for ( i = 0; i != BOXES_IN_HINT; ++i )
879da8c8 466 {
c82c42d4
WS
467 mBoxes[i]->mPressed = false;
468 mBoxes[i]->mWasClicked = false;
879da8c8
JS
469 }
470 for ( i = 0; i != BOXES_IN_HINT; ++i )
11a68fa3
GT
471 {
472 mBoxes[i]->OnLeftDown( inFrame );
8e08b761 473
11a68fa3
GT
474 if ( mBoxes[i]->mPressed )
475 {
c82c42d4 476 mBtnPressed = true;
11a68fa3 477 mpClickedBar = &bar;
8e08b761 478
11a68fa3
GT
479 return; // event handled
480 }
481 }
482 }
483 }
8e08b761 484
11a68fa3 485 event.Skip();
8e08b761
JS
486}
487
488void cbBarHintsPlugin::OnLeftUp( cbLeftUpEvent& event )
489{
11a68fa3
GT
490 if ( mBtnPressed )
491 {
492 wxPoint inFrame = event.mPos;
493 mpPane->PaneToFrame( &inFrame.x, &inFrame.y );
8e08b761 494
11a68fa3 495 int boxOfs, grooveOfs, pos;
8e08b761 496
11a68fa3 497 GetHintsLayout( mpClickedBar->mBoundsInParent, *mpClickedBar, boxOfs, grooveOfs, pos );
8e08b761 498
196be0f1 499 HitTestHints( *mpClickedBar, event.mPos );
8e08b761
JS
500
501 int i;
11a68fa3
GT
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 {
c82c42d4 510 mpLayout->SetBarState( mpClickedBar, wxCBAR_HIDDEN, true );
083f7497
JS
511 // Notify bar child window of close event:
512 if(mpClickedBar->mpBarWnd!=NULL)
513 mpClickedBar->mpBarWnd->Close();
11a68fa3
GT
514 }
515 else
516 {
517 if ( mpClickedBar->IsExpanded() )
518 mpPane->ContractBar( mpClickedBar );
519 else
520 mpPane->ExpandBar( mpClickedBar );
521 }
522 }
523 }
524
c82c42d4 525 mBtnPressed = false;
11a68fa3
GT
526 return;
527 }
528 else
529 event.Skip();
8e08b761
JS
530}
531
532void cbBarHintsPlugin::OnMotion( cbMotionEvent& event )
533{
11a68fa3
GT
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();
8e08b761
JS
549}
550
551void cbBarHintsPlugin::OnInitPlugin()
552{
11a68fa3
GT
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();
8e08b761 567}