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