]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/toolwnd.cpp
fixed Fit() to avoid showing scrollbars
[wxWidgets.git] / contrib / src / fl / toolwnd.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: No names yet.
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 06/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "toolwnd.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/fl/toolwnd.h"
28
29 #define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
30 #define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
31 #define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons.
32 #define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons.
33
34 // FOR NOW:: static
35
36 static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
37 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
38 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
39 _IMG_A,_IMG_B,_IMG_C,_IMG_D
40 };
41
42 /***** Implementation for class wxToolWindow *****/
43
44 IMPLEMENT_DYNAMIC_CLASS( wxToolWindow, wxWindow )
45
46 BEGIN_EVENT_TABLE( wxToolWindow, wxWindow )
47
48 EVT_PAINT ( wxToolWindow::OnPaint )
49 EVT_MOTION ( wxToolWindow::OnMotion )
50 EVT_LEFT_DOWN( wxToolWindow::OnLeftDown )
51 EVT_LEFT_UP ( wxToolWindow::OnLeftUp )
52 EVT_SIZE ( wxToolWindow::OnSize )
53
54
55 EVT_ERASE_BACKGROUND( wxToolWindow::OnEraseBackground )
56
57 END_EVENT_TABLE()
58
59 enum INTERNAL_HIT_CODES
60 {
61 HITS_WND_NOTHING,
62 HITS_WND_CLIENT,
63 HITS_WND_TITLE,
64
65 HITS_WND_LEFT_EDGE,
66 HITS_WND_RIGHT_EDGE,
67 HITS_WND_TOP_EDGE,
68 HITS_WND_BOTTOM_EDGE,
69
70 HITS_WND_TOP_LEFT_CORNER,
71 HITS_WND_BOTTOM_RIGHT_CORNER,
72 HITS_WND_TOP_RIGHT_CORNER,
73 HITS_WND_BOTTOM_LEFT_CORNER
74 };
75
76 wxToolWindow::wxToolWindow()
77
78 : mpClientWnd ( NULL ),
79
80 #ifndef __WXMSW__
81 mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL ),
82 #else
83 // just to simulate MS-Dev style
84 mTitleFont( 8, wxSWISS, wxNORMAL, wxNORMAL, FALSE, "MS Sans Serif" ),
85 #endif
86
87 mTitleHeight ( 16 ),
88 mClntHorizGap ( 2 ),
89 mClntVertGap ( 2 ),
90 mWndVertGap ( 4 ),
91 mWndHorizGap ( 4 ),
92
93 mButtonGap ( 2 ),
94 mInTitleMargin( 4 ),
95 mHintBorder ( 4 ),
96
97 mResizeStarted( FALSE ),
98 mRealTimeUpdatesOn( TRUE ),
99
100 mMTolerance ( 5 ), // mouse-resizing tollerance
101
102 mCursorType( HITS_WND_NOTHING ),
103 mMouseCaptured( FALSE ),
104
105 mpScrDc( NULL )
106
107 {
108 }
109
110 wxToolWindow::~wxToolWindow()
111 {
112 if ( mpScrDc ) delete mpScrDc;
113
114 for( size_t i = 0; i != mButtons.Count(); ++i )
115
116 delete mButtons[i];
117 }
118
119 void wxToolWindow::LayoutMiniButtons()
120 {
121 int w,h;
122
123 GetSize( &w, &h );
124
125 int x = w - mWndHorizGap - mInTitleMargin - BTN_BOX_WIDTH;
126 int y = mWndVertGap + 2;
127
128 for( size_t i = 0; i != mButtons.Count(); ++i )
129 {
130 mButtons[i]->SetPos( wxPoint( x,y ) );
131 x-= BTN_BOX_WIDTH + mButtonGap;
132 }
133 }
134
135 void wxToolWindow::SetClient( wxWindow* pWnd )
136 {
137 mpClientWnd = pWnd;
138 }
139
140 wxWindow* wxToolWindow::GetClient()
141 {
142 return mpClientWnd;
143 }
144
145 void wxToolWindow::SetTitleFont( wxFont& font )
146 {
147 mTitleFont = font;
148 }
149
150 void wxToolWindow::AddMiniButton( cbMiniButton* pBtn )
151 {
152 pBtn->mpWnd = this;
153
154 mButtons.Add( pBtn );
155
156 // not necesserely now..
157 //LayoutMiniButtons();
158 }
159
160 void wxToolWindow::OnPaint( wxPaintEvent& event )
161 {
162 wxPaintDC pdc( this );
163 wxWindowDC dc( this );
164
165 int w,h;
166 GetSize( &w, &h );
167
168 dc.SetBrush( *wxLIGHT_GREY_BRUSH );
169 dc.SetPen( *wxTRANSPARENT_PEN );
170
171 int y = mWndVertGap + mTitleHeight + mClntVertGap + 1;
172 dc.DrawRectangle( 0,0, w, y );
173 dc.DrawRectangle( 0,y-1, mWndHorizGap + mClntHorizGap + 1, h - y );
174 dc.DrawRectangle( w - ( mWndHorizGap + mClntHorizGap ), y-1,
175 mWndHorizGap + mClntHorizGap, h - y );
176 dc.DrawRectangle( 0, h - mWndVertGap - mClntVertGap, w, mWndVertGap + mClntVertGap );
177
178 // draw shades
179 dc.SetPen( *wxLIGHT_GREY_PEN );
180
181 dc.DrawLine( 0,0, w, 0 );
182 dc.DrawLine( 0,0, 0, h );
183
184 dc.SetPen( *wxWHITE_PEN );
185
186 dc.DrawLine( 1,1, w, 1 );
187 dc.DrawLine( 1,2, 1, h );
188
189 dc.SetPen( *wxGREY_PEN );
190
191 dc.DrawLine( w - 2, 1, w - 2, h - 1 );
192 dc.DrawLine( 1, h - 2, w - 2, h - 2 );
193
194 dc.SetPen( *wxBLACK_PEN );
195
196 dc.DrawLine( 0, h - 1, w, h - 1 );
197 dc.DrawLine( w-1, 0, w-1, h );
198
199 // fill inner area
200
201 dc.SetBrush( *wxTheBrushList->FindOrCreateBrush( wxColour( 0,0,128 ), wxSOLID ) );
202
203 dc.DrawRectangle( mWndHorizGap, mWndVertGap, w - mWndHorizGap*2, mTitleHeight );
204
205 dc.SetFont( mTitleFont );
206
207 for( size_t i = 0; i != mButtons.Count(); ++i )
208
209 mButtons[i]->Draw( dc );
210
211 int x1 = mWndHorizGap + mClntHorizGap;
212 int x2 = mButtons[ mButtons.GetCount() - 1 ]->mPos.x - mClntHorizGap*2;
213
214 dc.SetClippingRegion( x1, mWndVertGap + mClntVertGap, x2 - x1, mTitleHeight );
215
216 dc.SetTextForeground( *wxWHITE );
217 dc.SetBackgroundMode( wxTRANSPARENT );
218 dc.DrawText( GetTitle(), mWndHorizGap + 2, mWndVertGap + 1 );
219 }
220
221 void wxToolWindow::GetScrWindowRect( wxRect& r )
222 {
223 int x,y;
224 GetPosition(&x,&y);
225 int w,h;
226 GetSize( &w, &h );
227
228 r.x = x; r.y = y;
229 r.width = w; r.height = h;
230 }
231
232 void wxToolWindow::GetScrMousePos( wxMouseEvent& event, wxPoint& pos )
233 {
234 int x = event.m_x, y = event.m_y;
235
236 ClientToScreen( &x, &y );
237
238 pos.x = x; pos.y = y;
239 }
240
241 int wxToolWindow::HitTestWindow( wxMouseEvent& event )
242 {
243 wxPoint pos;
244 wxRect r;
245
246 GetScrMousePos( event, pos );
247 GetScrWindowRect( r );
248
249 int k = mMTolerance;
250
251 if ( !( pos.x >= r.x && pos.y >= r.y &&
252 pos.x < r.x + r.width &&
253 pos.y < r.y + r.height )
254 )
255 return HITS_WND_NOTHING;
256
257 if ( pos.y <= r.y + k )
258 {
259 if ( pos.x < r.x + k*2 )
260
261 return HITS_WND_TOP_LEFT_CORNER;
262 else
263 if ( pos.x >= r.x + r.width - k*2 )
264
265 return HITS_WND_TOP_RIGHT_CORNER;
266 else
267 return HITS_WND_TOP_EDGE;
268 }
269 else
270 if ( pos.y >= r.y + r.height - k )
271 {
272 if ( pos.x < r.x + k*2 )
273
274 return HITS_WND_BOTTOM_LEFT_CORNER;
275 else
276 if ( pos.x > r.x + r.width - k*2 )
277
278 return HITS_WND_BOTTOM_RIGHT_CORNER;
279 else
280 return HITS_WND_BOTTOM_EDGE;
281 }
282 else
283 if ( pos.x <= r.x + k )
284
285 return HITS_WND_LEFT_EDGE;
286 else
287 if ( pos.x >= r.x + r.width - k )
288
289 return HITS_WND_RIGHT_EDGE;
290 else
291 {
292 if ( pos.y <= r.y + mWndVertGap + mTitleHeight + mClntVertGap )
293
294 return HITS_WND_TITLE;
295 else
296 return HITS_WND_CLIENT;
297 }
298 }
299
300 void wxToolWindow::DrawHintRect( const wxRect& r )
301 {
302 // BUG BUG BUG (wx):: somehow stippled brush works only
303 // when the bitmap created on stack, not
304 // as a member of the class
305
306 int prevLF = mpScrDc->GetLogicalFunction();
307
308 mpScrDc->SetLogicalFunction( wxXOR );
309
310 wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
311
312 wxBrush checkerBrush( checker );
313
314 mpScrDc->SetPen( *wxTRANSPARENT_PEN );
315 mpScrDc->SetBrush( checkerBrush );
316
317 int half = mHintBorder / 2;
318
319 mpScrDc->DrawRectangle( r.x - half, r.y - half,
320 r.width + 2*half, mHintBorder );
321
322 mpScrDc->DrawRectangle( r.x - half, r.y + r.height - half,
323 r.width + 2*half, mHintBorder );
324
325 mpScrDc->DrawRectangle( r.x - half, r.y + half - 1,
326 mHintBorder, r.height - 2*half + 2);
327
328 mpScrDc->DrawRectangle( r.x + r.width - half,
329 r.y + half - 1,
330 mHintBorder, r.height - 2*half + 2);
331
332 mpScrDc->SetBrush( wxNullBrush );
333
334 mpScrDc->SetLogicalFunction( prevLF );
335 }
336
337 void wxToolWindow::SetHintCursor( int type )
338 {
339 if ( mResizeStarted ) return;
340
341 if ( type == HITS_WND_NOTHING || type == HITS_WND_CLIENT )
342 {
343 // the cursor is out of window - reset to arrow
344
345 if ( mMouseCaptured && !mResizeStarted )
346 {
347 ReleaseMouse();
348 mMouseCaptured = FALSE;
349 }
350
351 if ( mCursorType == HITS_WND_NOTHING && !mResizeStarted )
352
353 SetCursor( wxCURSOR_ARROW );
354
355 mCursorType = type;
356
357 return;
358 }
359
360 if ( !mMouseCaptured )
361 {
362 mMouseCaptured = TRUE;
363 CaptureMouse();
364 }
365
366 // did the cursor actually changed?
367
368 if ( type != mCursorType )
369 {
370 mCursorType = type;
371
372 switch ( type )
373 {
374 case HITS_WND_LEFT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
375 case HITS_WND_RIGHT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
376 case HITS_WND_TOP_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
377 case HITS_WND_BOTTOM_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
378
379 case HITS_WND_TOP_LEFT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
380 case HITS_WND_BOTTOM_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
381 case HITS_WND_TOP_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
382 case HITS_WND_BOTTOM_LEFT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
383
384 case HITS_WND_TITLE : SetCursor( wxCURSOR_ARROW ); break;
385 case HITS_WND_CLIENT : SetCursor( wxCURSOR_ARROW ); break;
386
387 default: break;
388 }
389 }
390 }
391
392 #define INFINITY 32768
393
394 static inline void clip_to( int& value, long from, long till )
395 {
396 if ( value < from )
397 value = from;
398
399 if ( value > till )
400 value = till;
401 }
402
403 void wxToolWindow::AdjustRectPos( const wxRect& original, const wxSize& newDim, wxRect& newRect )
404 {
405 if ( mCursorType == HITS_WND_TOP_EDGE ||
406 mCursorType == HITS_WND_TOP_LEFT_CORNER )
407 {
408 newRect.x = original.x + original.width - newDim.x;
409 newRect.y = original.y + original.height - newDim.y;
410 }
411 else
412 if ( mCursorType == HITS_WND_LEFT_EDGE ||
413 mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
414 {
415 newRect.x = original.x + original.width - newDim.x;
416 newRect.y = original.y;
417 }
418 else
419 if ( mCursorType == HITS_WND_RIGHT_EDGE ||
420 mCursorType == HITS_WND_TOP_RIGHT_CORNER )
421 {
422 newRect.x = original.x;
423 newRect.y = original.y + original.height - newDim.y;
424 }
425 else
426 if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
427 mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
428 {
429 newRect.x = original.x;
430 newRect.y = original.y;
431 }
432
433 newRect.width = newDim.x;
434 newRect.height = newDim.y;
435 }
436
437 void wxToolWindow::CalcResizedRect( wxRect& rect, wxPoint& delta, const wxSize& minDim )
438 {
439 // Microsoft's rect-coordinates are best suited
440 // for the case of corner-clipping
441
442 int left = mInitialRect.x;
443 int top = mInitialRect.y;
444 int right = mInitialRect.x + mInitialRect.width;
445 int bottom = mInitialRect.y + mInitialRect.height;
446
447 // constraint delta edge is dragged
448
449 switch ( mCursorType )
450 {
451 case HITS_WND_LEFT_EDGE : delta.y = 0; break;
452 case HITS_WND_RIGHT_EDGE : delta.y = 0; break;
453 case HITS_WND_TOP_EDGE : delta.x = 0; break;
454 case HITS_WND_BOTTOM_EDGE : delta.x = 0; break;
455 default: break;
456 }
457
458 if ( mCursorType == HITS_WND_TOP_EDGE ||
459 mCursorType == HITS_WND_TOP_LEFT_CORNER )
460 {
461 left += delta.x;
462 top += delta.y;
463
464 clip_to( left, -INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
465 clip_to( top, -INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
466 }
467 else
468 if ( mCursorType == HITS_WND_LEFT_EDGE ||
469 mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
470 {
471 left += delta.x;
472 bottom += delta.y;
473
474 clip_to( left, -INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
475 clip_to( bottom, mInitialRect.y + minDim.y, INFINITY );
476 }
477 else
478 if ( mCursorType == HITS_WND_RIGHT_EDGE ||
479 mCursorType == HITS_WND_TOP_RIGHT_CORNER )
480 {
481 right += delta.x;
482 top += delta.y;
483
484 clip_to( right, mInitialRect.x + minDim.x, INFINITY );
485 clip_to( top, -INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
486 }
487 else
488 if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
489 mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
490 {
491 right += delta.x;
492 bottom += delta.y;
493
494 clip_to( right, mInitialRect.x + minDim.x, INFINITY );
495 clip_to( bottom, mInitialRect.y + minDim.y, INFINITY );
496 }
497 else
498 {
499 wxFAIL( _T("what did the cursor hit?") );
500 }
501
502 rect.x = left;
503 rect.y = top;
504 rect.width = right - left;
505 rect.height = bottom - top;
506 }
507
508 wxSize wxToolWindow::GetMinimalWndDim()
509 {
510 return wxSize( (mWndHorizGap + mClntHorizGap)*2 + BTN_BOX_WIDTH*4,
511 (mWndVertGap + mClntVertGap )*2 + mTitleHeight );
512 }
513
514 void wxToolWindow::OnMotion( wxMouseEvent& event )
515 {
516 if ( !mResizeStarted )
517 {
518 for( size_t i = 0; i != mButtons.Count(); ++i )
519
520 mButtons[i]->OnMotion( wxPoint( event.m_x, event.m_y ) );
521
522 SetHintCursor( HitTestWindow( event ) );
523 return;
524 }
525
526 wxPoint pos;
527 GetScrMousePos( event, pos );
528
529 if ( mCursorType == HITS_WND_TITLE )
530 {
531 int w,h;
532 GetSize( &w, &h );
533
534 SetSize( mInitialRect.x + pos.x - mDragOrigin.x,
535 mInitialRect.y + pos.y - mDragOrigin.y,
536 w,h, 0 );
537 }
538
539 else
540 {
541 wxPoint delta( pos.x - mDragOrigin.x, pos.y - mDragOrigin.y );
542
543 wxRect newRect;
544
545 wxSize minDim = GetMinimalWndDim();
546
547 CalcResizedRect( newRect, delta, minDim );
548
549 wxSize borderDim( ( mWndHorizGap + mClntHorizGap )*2,
550 ( mWndVertGap + mClntVertGap )*2 + mTitleHeight );
551
552 wxSize preferred = GetPreferredSize( wxSize( newRect.width - borderDim.x,
553 newRect.height - borderDim.y ) );
554
555 preferred.x += borderDim.x;
556 preferred.y += borderDim.y;
557
558 //CalcResizedRect( newRect, delta, preferred );
559
560 wxRect finalRect = newRect;
561
562 AdjustRectPos( newRect, preferred, finalRect );
563
564 if ( mRealTimeUpdatesOn )
565 {
566 SetSize( finalRect.x, finalRect.y,
567 finalRect.width, finalRect.height, 0 );
568 }
569 else
570 {
571 DrawHintRect( mPrevHintRect );
572 DrawHintRect( finalRect );
573 }
574
575 mPrevHintRect = finalRect;
576 }
577 }
578
579 void wxToolWindow::OnLeftDown( wxMouseEvent& event )
580 {
581 int result = HitTestWindow( event );
582
583 for( size_t i = 0; i != mButtons.Count(); ++i )
584 {
585 mButtons[i]->OnLeftDown( wxPoint( event.m_x, event.m_y ) );
586
587 if ( mButtons[i]->IsPressed() )
588
589 return; // button hitted,
590 }
591
592 if ( result >= HITS_WND_LEFT_EDGE || result == HITS_WND_TITLE )
593 {
594 GetScrMousePos( event, mDragOrigin );
595
596 /*
597 if ( mMouseCaptured `)
598 {
599 ReleaseMouse();
600 mMouseCaptured = FALSE;
601 }*/
602
603 if ( result == HITS_WND_TITLE &&
604 HandleTitleClick( event )
605 )
606 {
607
608 return;
609 }
610
611 mResizeStarted = TRUE;
612
613 int x,y;
614 GetPosition( &x, &y );
615
616 mInitialRect.x = x;
617 mInitialRect.y = y;
618
619 GetSize( &x, &y );
620 mInitialRect.width = x;
621 mInitialRect.height = y;
622
623 mPrevHintRect = mInitialRect;
624
625 if ( mCursorType != HITS_WND_TITLE && !mRealTimeUpdatesOn )
626 {
627 mpScrDc = new wxScreenDC();
628
629 wxScreenDC::StartDrawingOnTop( (wxRect*)NULL );
630
631 DrawHintRect( mInitialRect );
632 }
633 }
634 }
635
636 void wxToolWindow::OnLeftUp( wxMouseEvent& event )
637 {
638 for( size_t i = 0; i != mButtons.Count(); ++i )
639 {
640 mButtons[i]->OnLeftUp( wxPoint( event.m_x, event.m_y ) );
641
642 if ( mButtons[i]->WasClicked() )
643 {
644 OnMiniButtonClicked( i ); // notify derived classes
645 mButtons[i]->Reset();
646 }
647 }
648
649 if ( mResizeStarted )
650 {
651 mResizeStarted = FALSE;
652
653 if ( mCursorType != HITS_WND_TITLE )
654 {
655 if ( !mRealTimeUpdatesOn )
656 {
657 DrawHintRect( mPrevHintRect );
658
659 wxScreenDC::EndDrawingOnTop();
660
661 delete mpScrDc;
662
663 mpScrDc = NULL;
664
665 SetSize( mPrevHintRect.x, mPrevHintRect.y,
666 mPrevHintRect.width, mPrevHintRect.height, 0 );
667 }
668 }
669 }
670 }
671
672 void wxToolWindow::OnSize( wxSizeEvent& event )
673 {
674 if ( mpClientWnd )
675 {
676 int w,h;
677 GetSize( &w, &h );
678
679 int x = mWndHorizGap + mClntHorizGap;
680 int y = mWndVertGap + mTitleHeight + mClntVertGap;
681
682 #if 1
683 mpClientWnd->SetSize( x -1, y -1,
684 w - 2*(mWndHorizGap + mClntHorizGap),
685 h - y - mClntVertGap - mWndVertGap,
686 0
687 );
688 #endif
689 }
690
691 LayoutMiniButtons();
692 }
693
694 wxSize wxToolWindow::GetPreferredSize( const wxSize& given )
695 {
696 return given;
697 }
698
699 void wxToolWindow::OnEraseBackground( wxEraseEvent& event )
700 {
701 // nothing
702 }
703
704 /***** Implementation for class cbMiniButton *****/
705
706 cbMiniButton::cbMiniButton()
707
708 : mVisible( TRUE ),
709 mEnabled( TRUE ),
710
711 mpLayout( NULL ),
712 mpPane ( NULL ),
713 mpPlugin( NULL ),
714 mpWnd ( NULL ),
715
716 mWasClicked( FALSE ),
717 mDragStarted( FALSE ),
718 mPressed( FALSE )
719 {}
720
721 void cbMiniButton::SetPos( const wxPoint& pos )
722 {
723 mPos = pos;
724 }
725
726 bool cbMiniButton::HitTest( const wxPoint& pos )
727 {
728 if ( !mVisible ) return FALSE;
729
730 return ( pos.x >= mPos.x && pos.y >= mPos.y &&
731 pos.x < mPos.x + BTN_BOX_WIDTH &&
732 pos.y < mPos.y + BTN_BOX_HEIGHT );
733 }
734
735 void cbMiniButton::OnLeftDown( const wxPoint& pos )
736 {
737 if ( !mVisible || mDragStarted ) return;
738
739 if ( HitTest( pos ) && mEnabled )
740 {
741 if ( mpPlugin )
742 {
743 mpLayout->CaptureEventsForPane( mpPane );
744 mpLayout->CaptureEventsForPlugin( mpPlugin );
745 }
746 else
747 mpWnd->CaptureMouse();
748
749 mDragStarted = TRUE;
750 mPressed = TRUE;
751 mWasClicked = FALSE;
752
753 Refresh();
754 }
755 }
756
757 void cbMiniButton::OnLeftUp( const wxPoint& pos )
758 {
759 if ( !mVisible || !mDragStarted ) return;
760
761 if ( mpPlugin )
762 {
763 mpLayout->ReleaseEventsFromPane( mpPane );
764 mpLayout->ReleaseEventsFromPlugin( mpPlugin );
765 }
766 else
767 mpWnd->ReleaseMouse();
768
769 mWasClicked = mPressed;
770 mDragStarted = FALSE;
771
772 mPressed = FALSE;
773 Refresh();
774 }
775
776 void cbMiniButton::OnMotion( const wxPoint& pos )
777 {
778 if ( !mVisible ) return;
779
780 if ( mDragStarted )
781 {
782 mPressed = HitTest( pos );
783
784 Refresh();
785 }
786 }
787
788 void cbMiniButton::Refresh()
789 {
790 if ( mpLayout )
791 {
792 wxClientDC dc( &mpLayout->GetParentFrame() );
793
794 Draw( dc );
795 }
796 else
797 {
798 wxWindowDC dc( mpWnd );
799
800 Draw( dc );
801 }
802 }
803
804 void cbMiniButton::Draw( wxDC& dc )
805 {
806 if ( !mVisible ) return;
807
808 dc.SetPen( *wxTRANSPARENT_PEN );
809
810 dc.SetBrush( *wxLIGHT_GREY_BRUSH );
811
812 dc.DrawRectangle( mPos.x + 1, mPos.y + 1, BTN_BOX_WIDTH - 2, BTN_BOX_HEIGHT - 2 );
813
814 // "hard-code" metafile
815
816 if ( !mPressed )
817
818 dc.SetPen( *wxWHITE_PEN );
819 else
820 dc.SetPen( *wxBLACK_PEN );
821
822 dc.DrawLine( mPos.x, mPos.y, mPos.x + BTN_BOX_WIDTH, mPos.y );
823 dc.DrawLine( mPos.x, mPos.y, mPos.x, mPos.y + BTN_BOX_HEIGHT );
824
825 dc.SetPen( *wxGREY_PEN );
826
827 if ( !mPressed )
828 {
829 dc.DrawLine( mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2,
830 mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT - 2 );
831
832 dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1,
833 mPos.x + BTN_BOX_WIDTH - 2, mPos.y + BTN_BOX_HEIGHT - 1 );
834 }
835 else
836 {
837 dc.DrawLine( mPos.x + 1, mPos.y + 1,
838 mPos.x + BTN_BOX_WIDTH - 2, mPos.y + 1 );
839
840 dc.DrawLine( mPos.x + 1, mPos.y + 1,
841 mPos.x + 1, mPos.y + BTN_BOX_HEIGHT - 2 );
842 }
843
844 if ( !mPressed )
845
846 dc.SetPen( *wxBLACK_PEN );
847 else
848 dc.SetPen( *wxWHITE_PEN );
849
850 dc.DrawLine( mPos.x, mPos.y + BTN_BOX_HEIGHT - 1,
851 mPos.x + BTN_BOX_WIDTH, mPos.y + BTN_BOX_HEIGHT - 1 );
852
853 dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 1, mPos.y ,
854 mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT );
855 }
856
857 bool cbMiniButton::WasClicked()
858 {
859 return mWasClicked;
860 }
861
862 void cbMiniButton::Reset()
863 {
864 mWasClicked = FALSE;
865 }
866
867 /***** Implementation fro class cbCloseBox *****/
868
869 void cbCloseBox::Draw( wxDC& dc )
870 {
871 #ifdef __WXGTK__
872
873 cbMiniButton::Draw( dc );
874
875 wxPen pen( wxColour( 64,64,64 ) ,1, wxSOLID );
876
877 dc.SetPen( pen );
878
879 int width = BTN_BOX_WIDTH - 7;
880
881 int xOfs = (mPressed) ? 4 : 3;
882 int yOfs = (mPressed) ? 4 : 3;
883
884 int one = 1;
885 for( int i = 0; i != BTN_X_WIEGHT; ++i )
886 {
887 dc.DrawLine( mPos.x + xOfs + i - one,
888 mPos.y + yOfs - one,
889 mPos.x + xOfs + i + width,
890 mPos.y + yOfs + width + one);
891
892 dc.DrawLine( mPos.x + xOfs + i + width ,
893 mPos.y + yOfs - one - one,
894 mPos.x + xOfs + i - one,
895 mPos.y + yOfs + width );
896 }
897
898 #else
899
900 cbMiniButton::Draw( dc );
901
902 dc.SetPen( *wxBLACK_PEN );
903
904 int width = BTN_BOX_WIDTH - 7;
905
906 int xOfs = (mPressed) ? 4 : 3;
907 int yOfs = (mPressed) ? 4 : 3;
908
909 for( int i = 0; i != BTN_X_WIEGHT; ++i )
910 {
911 dc.DrawLine( mPos.x + xOfs + i,
912 mPos.y + yOfs,
913 mPos.x + xOfs + i + width,
914 mPos.y + yOfs + width );
915
916 dc.DrawLine( mPos.x + xOfs + i + width - 1,
917 mPos.y + yOfs,
918 mPos.x + xOfs + i - 1,
919 mPos.y + yOfs + width );
920 }
921
922 #endif
923
924 }
925
926 /***** Implementation fro class cbCollapseBox *****/
927
928 inline static void my_swap( int& a, int& b )
929 {
930 long tmp = a;
931 a = b;
932 b = tmp;
933 }
934
935 void cbCollapseBox::Draw( wxDC& dc )
936 {
937 cbMiniButton::Draw( dc );
938
939 dc.SetPen( *wxTRANSPARENT_PEN );
940
941 wxPoint arr[3];
942
943 int yOfs = (mPressed) ? 3 : 2;
944 int xOfs = (mPressed) ? 5 : 4;
945 int width = BTN_BOX_WIDTH - 8;
946
947 // rotating/shifting triangle inside collapse box
948
949 arr[0].x = xOfs;
950 arr[0].y = yOfs-1;
951 arr[2].x = xOfs;
952 arr[2].y = BTN_BOX_HEIGHT - yOfs - 1;
953 arr[1].x = xOfs + width;
954 arr[1].y = (arr[2].y + arr[0].y)/2;
955
956 if ( !mIsAtLeft )
957 {
958 arr[0].x = BTN_BOX_WIDTH - arr[0].x;
959 arr[1].x = BTN_BOX_WIDTH - arr[1].x;
960 arr[2].x = BTN_BOX_WIDTH - arr[2].x;
961 }
962
963 if ( !mpPane->IsHorizontal() )
964 {
965 my_swap( arr[0].y, arr[0].x );
966 my_swap( arr[1].y, arr[1].x );
967 my_swap( arr[2].y, arr[2].x );
968
969 arr[0].x += 1;
970 arr[1].x += 1;
971 arr[2].x += 1;
972
973 //arr[1].y -= 1;
974 }
975
976 arr[0].x += mPos.x;
977 arr[0].y += mPos.y;
978 arr[1].x += mPos.x;
979 arr[1].y += mPos.y;
980 arr[2].x += mPos.x;
981 arr[2].y += mPos.y;
982
983 if ( !mEnabled ) dc.SetBrush( *wxGREY_BRUSH );
984 else dc.SetBrush( *wxBLACK_BRUSH );
985
986 dc.DrawPolygon( 3, arr );
987 dc.SetBrush( wxNullBrush );
988 }
989
990 /***** Implementation for class cbDockBoxBox *****/
991
992 void cbDockBox::Draw( wxDC& dc )
993 {
994 cbMiniButton::Draw( dc );
995
996 int width = BTN_BOX_WIDTH - 7;
997
998 int xOfs = (mPressed) ? 4 : 3;
999 int yOfs = (mPressed) ? 4 : 3;
1000
1001 dc.SetPen( *wxBLACK_PEN );
1002 dc.SetBrush( *wxBLACK_BRUSH );
1003
1004 dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width, width );
1005
1006 xOfs += 1;
1007 yOfs += 1;
1008
1009 dc.SetBrush( *wxWHITE_BRUSH );
1010
1011 dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width-2, width-2 );
1012 }
1013
1014 /***** Implementation for class wxToolWindow *****/
1015
1016 IMPLEMENT_DYNAMIC_CLASS( cbFloatedBarWindow, wxToolWindow )
1017
1018 BEGIN_EVENT_TABLE( cbFloatedBarWindow, wxToolWindow )
1019
1020 EVT_LEFT_DCLICK( cbFloatedBarWindow::OnDblClick )
1021
1022 END_EVENT_TABLE()
1023
1024 cbFloatedBarWindow::cbFloatedBarWindow()
1025
1026 : mpBar( NULL )
1027 {
1028 AddMiniButton( new cbCloseBox() );
1029 AddMiniButton( new cbDockBox() );
1030 }
1031
1032 void cbFloatedBarWindow::SetBar( cbBarInfo* pBar )
1033 {
1034 mpBar = pBar;
1035 }
1036
1037 cbBarInfo* cbFloatedBarWindow::GetBar()
1038 {
1039 return mpBar;
1040 }
1041
1042 void cbFloatedBarWindow::SetLayout( wxFrameLayout* pLayout )
1043 {
1044 mpLayout = pLayout;
1045 }
1046
1047 void cbFloatedBarWindow::PositionFloatedWnd( int scrX, int scrY,
1048 int width, int height )
1049 {
1050 wxSize minDim = GetMinimalWndDim();
1051
1052 SetSize( scrX - mWndHorizGap - mClntHorizGap,
1053 scrY - mClntVertGap - mTitleHeight - mWndVertGap,
1054 width + minDim.x, height + minDim.y, 0 );
1055 }
1056
1057 wxSize cbFloatedBarWindow::GetPreferredSize( const wxSize& given )
1058 {
1059 if ( mpBar->mDimInfo.GetDimHandler() )
1060 {
1061
1062 cbBarDimHandlerBase* pHandler = mpBar->mDimInfo.GetDimHandler();
1063
1064 wxSize prefDim;
1065
1066 // int vtad = *((int*)pHandler);
1067
1068 pHandler->OnResizeBar( mpBar, given, prefDim );
1069
1070 return prefDim;
1071 }
1072 else
1073 {
1074 if ( mpBar->IsFixed() )
1075
1076 return mpBar->mDimInfo.mSizes[ wxCBAR_FLOATING ];
1077 else
1078 return given; // not-fixed bars are resized exactly the way user wants
1079 }
1080 }
1081
1082 void cbFloatedBarWindow::OnMiniButtonClicked( int btnIdx )
1083 {
1084 // #1 - close mini-button
1085 // #0 - dock mini-button
1086
1087 if ( btnIdx == 0 )
1088 {
1089 mpBar->mAlignment = -1; // sepcial "marking" for hidden bars out of floated state
1090 mpLayout->SetBarState( mpBar, wxCBAR_HIDDEN, TRUE );
1091 }
1092 else
1093 mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, TRUE );
1094 }
1095
1096 bool cbFloatedBarWindow::HandleTitleClick( wxMouseEvent& event )
1097 {
1098 ReleaseMouse();
1099 mMouseCaptured = FALSE;
1100
1101 wxPoint scrPos;
1102 GetScrMousePos( event, scrPos );
1103
1104 int msX = scrPos.x,
1105 msY = scrPos.y;
1106
1107 mpLayout->GetParentFrame().ScreenToClient( &msX, &msY );
1108
1109 int x,y;
1110 GetPosition(&x,&y);
1111 int w,h;
1112 GetSize( &w, &h );
1113
1114 wxSize minDim = GetMinimalWndDim();
1115
1116 w -= minDim.x;
1117 h -= minDim.y;
1118
1119 x += mWndHorizGap + mClntHorizGap;
1120 y += mWndVertGap + mTitleHeight + mClntVertGap;
1121
1122 mpLayout->GetParentFrame().ScreenToClient( &x, &y );
1123
1124 wxRect& bounds = mpBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
1125
1126 bounds.x = x;
1127 bounds.y = y;
1128 bounds.width = w;
1129 bounds.height = h;
1130
1131 cbStartBarDraggingEvent dragEvt( mpBar, wxPoint(msX,msY),
1132 mpLayout->GetPanesArray()[FL_ALIGN_TOP] );
1133
1134 mpLayout->FirePluginEvent( dragEvt );
1135
1136 return TRUE;
1137 }
1138
1139 void cbFloatedBarWindow::OnDblClick( wxMouseEvent& event )
1140 {
1141 mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, TRUE );
1142
1143 //wxMessageBox("toolWnd - dblClick!");
1144 }
1145