]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/toolwnd.cpp
Set minsize and implement DoGetBestSize
[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, wxT("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 delete mButtons[i];
116 }
117
118 void wxToolWindow::LayoutMiniButtons()
119 {
120 int w,h;
121
122 GetSize( &w, &h );
123
124 int x = w - mWndHorizGap - mInTitleMargin - BTN_BOX_WIDTH;
125 int y = mWndVertGap + 2;
126
127 for( size_t i = 0; i != mButtons.Count(); ++i )
128 {
129 mButtons[i]->SetPos( wxPoint( x,y ) );
130 x-= BTN_BOX_WIDTH + mButtonGap;
131 }
132 }
133
134 void wxToolWindow::SetClient( wxWindow* pWnd )
135 {
136 mpClientWnd = pWnd;
137 }
138
139 wxWindow* wxToolWindow::GetClient()
140 {
141 return mpClientWnd;
142 }
143
144 void wxToolWindow::SetTitleFont( wxFont& font )
145 {
146 mTitleFont = font;
147 }
148
149 void wxToolWindow::AddMiniButton( cbMiniButton* pBtn )
150 {
151 pBtn->mpWnd = this;
152
153 mButtons.Add( pBtn );
154
155 // not necesserely now..
156 //LayoutMiniButtons();
157 }
158
159 void wxToolWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
160 {
161 wxPaintDC pdc( this );
162 wxWindowDC dc( this );
163
164 int w,h;
165 GetSize( &w, &h );
166
167 wxBrush backGround( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE), wxSOLID );
168 //dc.SetBrush( *wxLIGHT_GREY_BRUSH );
169 dc.SetBrush( backGround );
170 dc.SetPen( *wxTRANSPARENT_PEN );
171
172 int y = mWndVertGap + mTitleHeight + mClntVertGap;
173
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 mButtons[i]->Draw( dc );
211
212 int x1 = mWndHorizGap + mClntHorizGap;
213 int x2 = mButtons[ mButtons.GetCount() - 1 ]->mPos.x - mClntHorizGap*2;
214
215 dc.SetClippingRegion( x1, mWndVertGap + mClntVertGap, x2 - x1, mTitleHeight );
216
217 dc.SetTextForeground( *wxWHITE );
218 dc.SetBackgroundMode( wxTRANSPARENT );
219 dc.DrawText( GetTitle(), mWndHorizGap + 2, mWndVertGap + 1 );
220 }
221
222 void wxToolWindow::GetScrWindowRect( wxRect& r )
223 {
224 int x,y;
225 GetPosition(&x,&y);
226 int w,h;
227 GetSize( &w, &h );
228
229 r.x = x; r.y = y;
230 r.width = w; r.height = h;
231 }
232
233 void wxToolWindow::GetScrMousePos( wxMouseEvent& event, wxPoint& pos )
234 {
235 int x = event.m_x, y = event.m_y;
236
237 ClientToScreen( &x, &y );
238
239 pos.x = x; pos.y = y;
240 }
241
242 int wxToolWindow::HitTestWindow( wxMouseEvent& event )
243 {
244 wxPoint pos;
245 wxRect r;
246
247 GetScrMousePos( event, pos );
248 GetScrWindowRect( r );
249
250 int k = mMTolerance;
251
252 if ( !( pos.x >= r.x && pos.y >= r.y &&
253 pos.x < r.x + r.width &&
254 pos.y < r.y + r.height )
255 )
256 return HITS_WND_NOTHING;
257
258 if ( pos.y <= r.y + k )
259 {
260 if ( pos.x < r.x + k*2 )
261 return HITS_WND_TOP_LEFT_CORNER;
262 else
263 {
264 if ( pos.x >= r.x + r.width - k*2 )
265 return HITS_WND_TOP_RIGHT_CORNER;
266 else
267 return HITS_WND_TOP_EDGE;
268 }
269 }
270 else
271 {
272 if ( pos.y >= r.y + r.height - k )
273 {
274 if ( pos.x < r.x + k*2 )
275 return HITS_WND_BOTTOM_LEFT_CORNER;
276 else
277 {
278 if ( pos.x > r.x + r.width - k*2 )
279 return HITS_WND_BOTTOM_RIGHT_CORNER;
280 else
281 return HITS_WND_BOTTOM_EDGE;
282 }
283 }
284 else
285 {
286 if ( pos.x <= r.x + k )
287 return HITS_WND_LEFT_EDGE;
288 else
289 {
290 if ( pos.x >= r.x + r.width - k )
291 return HITS_WND_RIGHT_EDGE;
292 else
293 {
294 if ( pos.y <= r.y + mWndVertGap + mTitleHeight + mClntVertGap )
295 return HITS_WND_TITLE;
296 else
297 return HITS_WND_CLIENT;
298 }
299 }
300 }
301 }
302 }
303
304 void wxToolWindow::DrawHintRect( const wxRect& r )
305 {
306 // BUG BUG BUG (wx):: somehow stippled brush works only
307 // when the bitmap created on stack, not
308 // as a member of the class
309
310 int prevLF = mpScrDc->GetLogicalFunction();
311
312 mpScrDc->SetLogicalFunction( wxXOR );
313
314 wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
315
316 wxBrush checkerBrush( checker );
317
318 mpScrDc->SetPen( *wxTRANSPARENT_PEN );
319 mpScrDc->SetBrush( checkerBrush );
320
321 int half = mHintBorder / 2;
322
323 mpScrDc->DrawRectangle( r.x - half, r.y - half,
324 r.width + 2*half, mHintBorder );
325
326 mpScrDc->DrawRectangle( r.x - half, r.y + r.height - half,
327 r.width + 2*half, mHintBorder );
328
329 mpScrDc->DrawRectangle( r.x - half, r.y + half - 1,
330 mHintBorder, r.height - 2*half + 2);
331
332 mpScrDc->DrawRectangle( r.x + r.width - half,
333 r.y + half - 1,
334 mHintBorder, r.height - 2*half + 2);
335
336 mpScrDc->SetBrush( wxNullBrush );
337
338 mpScrDc->SetLogicalFunction( prevLF );
339 }
340
341 void wxToolWindow::SetHintCursor( int type )
342 {
343 if ( mResizeStarted )
344 return;
345
346 if ( type == HITS_WND_NOTHING || type == HITS_WND_CLIENT )
347 {
348 // the cursor is out of window - reset to arrow
349
350 if ( mMouseCaptured )
351 {
352 ReleaseMouse();
353 mMouseCaptured = false;
354 }
355
356 SetCursor( wxCURSOR_ARROW );
357
358 mCursorType = type;
359
360 return;
361 }
362
363 // did the cursor actually changed?
364
365 if ( type != mCursorType )
366 {
367 mCursorType = type;
368
369 switch ( type )
370 {
371 case HITS_WND_LEFT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
372 case HITS_WND_RIGHT_EDGE : SetCursor( wxCURSOR_SIZEWE ); break;
373 case HITS_WND_TOP_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
374 case HITS_WND_BOTTOM_EDGE : SetCursor( wxCURSOR_SIZENS ); break;
375
376 case HITS_WND_TOP_LEFT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
377 case HITS_WND_BOTTOM_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENWSE ); break;
378 case HITS_WND_TOP_RIGHT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
379 case HITS_WND_BOTTOM_LEFT_CORNER : SetCursor( wxCURSOR_SIZENESW ); break;
380
381 case HITS_WND_TITLE : SetCursor( wxCURSOR_ARROW ); break;
382 case HITS_WND_CLIENT : SetCursor( wxCURSOR_ARROW ); break;
383
384 default: break;
385 }
386
387 if (mMouseCaptured)
388 ReleaseMouse();
389 }
390
391 if ( !mMouseCaptured )
392 {
393 mMouseCaptured = true;
394 CaptureMouse();
395 }
396 }
397
398 #define INFINITY 32768
399
400 static inline void clip_to( int& value, long from, long till )
401 {
402 if ( value < from )
403 value = from;
404
405 if ( value > till )
406 value = till;
407 }
408
409 void wxToolWindow::AdjustRectPos( const wxRect& original, const wxSize& newDim, wxRect& newRect )
410 {
411 if ( mCursorType == HITS_WND_TOP_EDGE ||
412 mCursorType == HITS_WND_TOP_LEFT_CORNER )
413 {
414 newRect.x = original.x + original.width - newDim.x;
415 newRect.y = original.y + original.height - newDim.y;
416 }
417 else
418 if ( mCursorType == HITS_WND_LEFT_EDGE ||
419 mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
420 {
421 newRect.x = original.x + original.width - newDim.x;
422 newRect.y = original.y;
423 }
424 else
425 if ( mCursorType == HITS_WND_RIGHT_EDGE ||
426 mCursorType == HITS_WND_TOP_RIGHT_CORNER )
427 {
428 newRect.x = original.x;
429 newRect.y = original.y + original.height - newDim.y;
430 }
431 else
432 if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
433 mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
434 {
435 newRect.x = original.x;
436 newRect.y = original.y;
437 }
438
439 newRect.width = newDim.x;
440 newRect.height = newDim.y;
441 }
442
443 void wxToolWindow::CalcResizedRect( wxRect& rect, wxPoint& delta, const wxSize& minDim )
444 {
445 // Microsoft's rect-coordinates are best suited
446 // for the case of corner-clipping
447
448 int left = mInitialRect.x;
449 int top = mInitialRect.y;
450 int right = mInitialRect.x + mInitialRect.width;
451 int bottom = mInitialRect.y + mInitialRect.height;
452
453 // constraint delta edge is dragged
454
455 switch ( mCursorType )
456 {
457 case HITS_WND_LEFT_EDGE : delta.y = 0; break;
458 case HITS_WND_RIGHT_EDGE : delta.y = 0; break;
459 case HITS_WND_TOP_EDGE : delta.x = 0; break;
460 case HITS_WND_BOTTOM_EDGE : delta.x = 0; break;
461 default: break;
462 }
463
464 if ( mCursorType == HITS_WND_TOP_EDGE ||
465 mCursorType == HITS_WND_TOP_LEFT_CORNER )
466 {
467 left += delta.x;
468 top += delta.y;
469
470 clip_to( left, -INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
471 clip_to( top, -INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
472 }
473 else
474 if ( mCursorType == HITS_WND_LEFT_EDGE ||
475 mCursorType == HITS_WND_BOTTOM_LEFT_CORNER )
476 {
477 left += delta.x;
478 bottom += delta.y;
479
480 clip_to( left, -INFINITY, mInitialRect.x + mInitialRect.width - minDim.x );
481 clip_to( bottom, mInitialRect.y + minDim.y, INFINITY );
482 }
483 else
484 if ( mCursorType == HITS_WND_RIGHT_EDGE ||
485 mCursorType == HITS_WND_TOP_RIGHT_CORNER )
486 {
487 right += delta.x;
488 top += delta.y;
489
490 clip_to( right, mInitialRect.x + minDim.x, INFINITY );
491 clip_to( top, -INFINITY, mInitialRect.y + mInitialRect.height - minDim.y );
492 }
493 else
494 if ( mCursorType == HITS_WND_BOTTOM_EDGE ||
495 mCursorType == HITS_WND_BOTTOM_RIGHT_CORNER )
496 {
497 right += delta.x;
498 bottom += delta.y;
499
500 clip_to( right, mInitialRect.x + minDim.x, INFINITY );
501 clip_to( bottom, mInitialRect.y + minDim.y, INFINITY );
502 }
503 else
504 {
505 wxFAIL_MSG( _T("what did the cursor hit?") );
506 }
507
508 rect.x = left;
509 rect.y = top;
510 rect.width = right - left;
511 rect.height = bottom - top;
512 }
513
514 wxSize wxToolWindow::GetMinimalWndDim()
515 {
516 return wxSize( (mWndHorizGap + mClntHorizGap)*2 + BTN_BOX_WIDTH*4,
517 (mWndVertGap + mClntVertGap )*2 + mTitleHeight );
518 }
519
520 void wxToolWindow::OnMotion( wxMouseEvent& event )
521 {
522 if ( !mResizeStarted )
523 {
524 for( size_t i = 0; i != mButtons.Count(); ++i )
525 mButtons[i]->OnMotion( wxPoint( event.m_x, event.m_y ) );
526
527 SetHintCursor( HitTestWindow( event ) );
528 return;
529 }
530
531 wxPoint pos;
532 GetScrMousePos( event, pos );
533
534 if ( mCursorType == HITS_WND_TITLE )
535 {
536 int w,h;
537 GetSize( &w, &h );
538
539 SetSize( mInitialRect.x + pos.x - mDragOrigin.x,
540 mInitialRect.y + pos.y - mDragOrigin.y,
541 w,h, 0 );
542 }
543
544 else
545 {
546 wxPoint delta( pos.x - mDragOrigin.x, pos.y - mDragOrigin.y );
547
548 wxRect newRect;
549
550 wxSize minDim = GetMinimalWndDim();
551
552 CalcResizedRect( newRect, delta, minDim );
553
554 wxSize borderDim( ( mWndHorizGap + mClntHorizGap )*2,
555 ( mWndVertGap + mClntVertGap )*2 + mTitleHeight );
556
557 wxSize preferred = GetPreferredSize( wxSize( newRect.width - borderDim.x,
558 newRect.height - borderDim.y ) );
559
560 preferred.x += borderDim.x;
561 preferred.y += borderDim.y;
562
563 //CalcResizedRect( newRect, delta, preferred );
564
565 wxRect finalRect = newRect;
566
567 AdjustRectPos( newRect, preferred, finalRect );
568
569 if ( mRealTimeUpdatesOn )
570 {
571 SetSize( finalRect.x, finalRect.y,
572 finalRect.width, finalRect.height, 0 );
573 }
574 else
575 {
576 DrawHintRect( mPrevHintRect );
577 DrawHintRect( finalRect );
578
579 ::wxLogTrace(wxT("wxToolWindow"),wxT("%d,%d / %d,%d\n"), finalRect.x, finalRect.y, finalRect.width, finalRect.height);
580 }
581
582 mPrevHintRect = finalRect;
583 }
584 }
585
586 void wxToolWindow::OnLeftDown( wxMouseEvent& event )
587 {
588 int result = HitTestWindow( event );
589
590 for( size_t i = 0; i != mButtons.Count(); ++i )
591 {
592 mButtons[i]->OnLeftDown( wxPoint( event.m_x, event.m_y ) );
593
594 if ( mButtons[i]->IsPressed() )
595 return; // button hitted,
596 }
597
598 if ( result >= HITS_WND_LEFT_EDGE || result == HITS_WND_TITLE )
599 {
600 GetScrMousePos( event, mDragOrigin );
601
602 /*
603 if ( mMouseCaptured `)
604 {
605 ReleaseMouse();
606 mMouseCaptured = false;
607 }*/
608
609 if ( result == HITS_WND_TITLE &&
610 HandleTitleClick( event ) )
611 return;
612
613 mResizeStarted = true;
614
615 int x,y;
616 GetPosition( &x, &y );
617
618 mInitialRect.x = x;
619 mInitialRect.y = y;
620
621 GetSize( &x, &y );
622 mInitialRect.width = x;
623 mInitialRect.height = y;
624
625 mPrevHintRect = mInitialRect;
626
627 if ( mCursorType != HITS_WND_TITLE && !mRealTimeUpdatesOn )
628 {
629 mpScrDc = new wxScreenDC();
630
631 wxScreenDC::StartDrawingOnTop( (wxRect*)NULL );
632
633 DrawHintRect( mInitialRect );
634 }
635 }
636 }
637
638 void wxToolWindow::OnLeftUp( wxMouseEvent& event )
639 {
640 for( size_t i = 0; i != mButtons.Count(); ++i )
641 {
642 mButtons[i]->OnLeftUp( wxPoint( event.m_x, event.m_y ) );
643
644 if ( mButtons[i]->WasClicked() )
645 {
646 OnMiniButtonClicked( i ); // notify derived classes
647 mButtons[i]->Reset();
648 }
649 }
650
651 if ( mResizeStarted )
652 {
653 mResizeStarted = false;
654
655 if ( mCursorType != HITS_WND_TITLE )
656 {
657 if ( !mRealTimeUpdatesOn )
658 {
659 DrawHintRect( mPrevHintRect );
660
661 wxScreenDC::EndDrawingOnTop();
662
663 delete mpScrDc;
664
665 mpScrDc = NULL;
666
667 SetSize( mPrevHintRect.x, mPrevHintRect.y,
668 mPrevHintRect.width, mPrevHintRect.height, 0 );
669 }
670 }
671 }
672 }
673
674 void wxToolWindow::OnSize( wxSizeEvent& WXUNUSED(event) )
675 {
676 if ( mpClientWnd )
677 {
678 int w,h;
679 GetSize( &w, &h );
680
681 int x = mWndHorizGap + mClntHorizGap;
682 int y = mWndVertGap + mTitleHeight + mClntVertGap;
683
684 mpClientWnd->SetSize( x-1, y-1,
685 w - 2*(mWndHorizGap + mClntHorizGap),
686 h - y - mClntVertGap - mWndVertGap,
687 0
688 );
689 }
690
691 LayoutMiniButtons();
692 }
693
694 wxSize wxToolWindow::GetPreferredSize( const wxSize& given )
695 {
696 return given;
697 }
698
699 void wxToolWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(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& WXUNUSED(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 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 dc.SetPen( *wxBLACK_PEN );
845 else
846 dc.SetPen( *wxWHITE_PEN );
847
848 dc.DrawLine( mPos.x, mPos.y + BTN_BOX_HEIGHT - 1,
849 mPos.x + BTN_BOX_WIDTH, mPos.y + BTN_BOX_HEIGHT - 1 );
850
851 dc.DrawLine( mPos.x + BTN_BOX_WIDTH - 1, mPos.y ,
852 mPos.x + BTN_BOX_WIDTH - 1, mPos.y + BTN_BOX_HEIGHT );
853 }
854
855 bool cbMiniButton::WasClicked()
856 {
857 return mWasClicked;
858 }
859
860 void cbMiniButton::Reset()
861 {
862 mWasClicked = false;
863 }
864
865 /***** Implementation fro class cbCloseBox *****/
866
867 void cbCloseBox::Draw( wxDC& dc )
868 {
869 #if defined(__WXGTK__) || defined(__WXX11__)
870
871 cbMiniButton::Draw( dc );
872
873 wxPen pen( wxColour( 64,64,64 ) ,1, wxSOLID );
874
875 dc.SetPen( pen );
876
877 int width = BTN_BOX_WIDTH - 7;
878
879 int xOfs = (mPressed) ? 4 : 3;
880 int yOfs = (mPressed) ? 4 : 3;
881
882 int one = 1;
883 for( int i = 0; i != BTN_X_WIEGHT; ++i )
884 {
885 dc.DrawLine( mPos.x + xOfs + i - one,
886 mPos.y + yOfs - one,
887 mPos.x + xOfs + i + width,
888 mPos.y + yOfs + width + one);
889
890 dc.DrawLine( mPos.x + xOfs + i + width ,
891 mPos.y + yOfs - one - one,
892 mPos.x + xOfs + i - one,
893 mPos.y + yOfs + width );
894 }
895
896 #else
897
898 cbMiniButton::Draw( dc );
899
900 dc.SetPen( *wxBLACK_PEN );
901
902 int width = BTN_BOX_WIDTH - 7;
903
904 int xOfs = (mPressed) ? 4 : 3;
905 int yOfs = (mPressed) ? 4 : 3;
906
907 for( int i = 0; i != BTN_X_WIEGHT; ++i )
908 {
909 dc.DrawLine( mPos.x + xOfs + i,
910 mPos.y + yOfs,
911 mPos.x + xOfs + i + width,
912 mPos.y + yOfs + width );
913
914 dc.DrawLine( mPos.x + xOfs + i + width - 1,
915 mPos.y + yOfs,
916 mPos.x + xOfs + i - 1,
917 mPos.y + yOfs + width );
918 }
919
920 #endif
921
922 }
923
924 /***** Implementation fro class cbCollapseBox *****/
925
926 inline static void my_swap( int& a, int& b )
927 {
928 long tmp = a;
929 a = b;
930 b = tmp;
931 }
932
933 void cbCollapseBox::Draw( wxDC& dc )
934 {
935 cbMiniButton::Draw( dc );
936
937 dc.SetPen( *wxTRANSPARENT_PEN );
938
939 wxPoint arr[3];
940
941 int yOfs = (mPressed) ? 3 : 2;
942 int xOfs = (mPressed) ? 5 : 4;
943 int width = BTN_BOX_WIDTH - 8;
944
945 // rotating/shifting triangle inside collapse box
946
947 arr[0].x = xOfs;
948 arr[0].y = yOfs-1;
949 arr[2].x = xOfs;
950 arr[2].y = BTN_BOX_HEIGHT - yOfs - 1;
951 arr[1].x = xOfs + width;
952 arr[1].y = (arr[2].y + arr[0].y)/2;
953
954 if ( !mIsAtLeft )
955 {
956 arr[0].x = BTN_BOX_WIDTH - arr[0].x;
957 arr[1].x = BTN_BOX_WIDTH - arr[1].x;
958 arr[2].x = BTN_BOX_WIDTH - arr[2].x;
959 }
960
961 if ( !mpPane->IsHorizontal() )
962 {
963 my_swap( arr[0].y, arr[0].x );
964 my_swap( arr[1].y, arr[1].x );
965 my_swap( arr[2].y, arr[2].x );
966
967 arr[0].x += 1;
968 arr[1].x += 1;
969 arr[2].x += 1;
970
971 //arr[1].y -= 1;
972 }
973
974 arr[0].x += mPos.x;
975 arr[0].y += mPos.y;
976 arr[1].x += mPos.x;
977 arr[1].y += mPos.y;
978 arr[2].x += mPos.x;
979 arr[2].y += mPos.y;
980
981 if ( !mEnabled ) dc.SetBrush( *wxGREY_BRUSH );
982 else dc.SetBrush( *wxBLACK_BRUSH );
983
984 dc.DrawPolygon( 3, arr );
985 dc.SetBrush( wxNullBrush );
986 }
987
988 /***** Implementation for class cbDockBoxBox *****/
989
990 void cbDockBox::Draw( wxDC& dc )
991 {
992 cbMiniButton::Draw( dc );
993
994 int width = BTN_BOX_WIDTH - 7;
995
996 int xOfs = (mPressed) ? 4 : 3;
997 int yOfs = (mPressed) ? 4 : 3;
998
999 dc.SetPen( *wxBLACK_PEN );
1000 dc.SetBrush( *wxBLACK_BRUSH );
1001
1002 dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width, width );
1003
1004 xOfs += 1;
1005 yOfs += 1;
1006
1007 dc.SetBrush( *wxWHITE_BRUSH );
1008
1009 dc.DrawRectangle( mPos.x + xOfs, mPos.y + yOfs, width-2, width-2 );
1010 }
1011
1012 /***** Implementation for class wxToolWindow *****/
1013
1014 IMPLEMENT_DYNAMIC_CLASS( cbFloatedBarWindow, wxToolWindow )
1015
1016 BEGIN_EVENT_TABLE( cbFloatedBarWindow, wxToolWindow )
1017
1018 EVT_LEFT_DCLICK( cbFloatedBarWindow::OnDblClick )
1019
1020 END_EVENT_TABLE()
1021
1022 cbFloatedBarWindow::cbFloatedBarWindow()
1023
1024 : mpBar( NULL )
1025 {
1026 AddMiniButton( new cbCloseBox() );
1027 AddMiniButton( new cbDockBox() );
1028 }
1029
1030 void cbFloatedBarWindow::SetBar( cbBarInfo* pBar )
1031 {
1032 mpBar = pBar;
1033 }
1034
1035 cbBarInfo* cbFloatedBarWindow::GetBar()
1036 {
1037 return mpBar;
1038 }
1039
1040 void cbFloatedBarWindow::SetLayout( wxFrameLayout* pLayout )
1041 {
1042 mpLayout = pLayout;
1043 }
1044
1045 void cbFloatedBarWindow::PositionFloatedWnd( int scrX, int scrY,
1046 int width, int height )
1047 {
1048 wxSize minDim = GetMinimalWndDim();
1049
1050 SetSize( scrX - mWndHorizGap - mClntHorizGap,
1051 scrY - mClntVertGap - mTitleHeight - mWndVertGap,
1052 width + minDim.x, height + minDim.y, 0 );
1053 }
1054
1055 wxSize cbFloatedBarWindow::GetPreferredSize( const wxSize& given )
1056 {
1057 if ( mpBar->mDimInfo.GetDimHandler() )
1058 {
1059 cbBarDimHandlerBase* pHandler = mpBar->mDimInfo.GetDimHandler();
1060
1061 wxSize prefDim;
1062
1063 // int vtad = *((int*)pHandler);
1064
1065 pHandler->OnResizeBar( mpBar, given, prefDim );
1066
1067 return prefDim;
1068 }
1069 else
1070 {
1071 if ( mpBar->IsFixed() )
1072 return mpBar->mDimInfo.mSizes[ wxCBAR_FLOATING ];
1073 else
1074 return given; // not-fixed bars are resized exactly the way user wants
1075 }
1076 }
1077
1078 void cbFloatedBarWindow::OnMiniButtonClicked( int btnIdx )
1079 {
1080 // #1 - close mini-button
1081 // #0 - dock mini-button
1082
1083 if ( btnIdx == 0 )
1084 {
1085 mpBar->mAlignment = -1; // sepcial "marking" for hidden bars out of floated state
1086 mpLayout->SetBarState( mpBar, wxCBAR_HIDDEN, true );
1087 }
1088 else
1089 mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, true );
1090 }
1091
1092 bool cbFloatedBarWindow::HandleTitleClick( wxMouseEvent& event )
1093 {
1094 ReleaseMouse();
1095 mMouseCaptured = false;
1096
1097 wxPoint scrPos;
1098 GetScrMousePos( event, scrPos );
1099
1100 int msX = scrPos.x,
1101 msY = scrPos.y;
1102
1103 mpLayout->GetParentFrame().ScreenToClient( &msX, &msY );
1104
1105 int x,y;
1106 GetPosition(&x,&y);
1107 int w,h;
1108 GetSize( &w, &h );
1109
1110 wxSize minDim = GetMinimalWndDim();
1111
1112 w -= minDim.x;
1113 h -= minDim.y;
1114
1115 x += mWndHorizGap + mClntHorizGap;
1116 y += mWndVertGap + mTitleHeight + mClntVertGap;
1117
1118 mpLayout->GetParentFrame().ScreenToClient( &x, &y );
1119
1120 wxRect& bounds = mpBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
1121
1122 bounds.x = x;
1123 bounds.y = y;
1124 bounds.width = w;
1125 bounds.height = h;
1126
1127 cbStartBarDraggingEvent dragEvt( mpBar, wxPoint(msX,msY),
1128 mpLayout->GetPanesArray()[FL_ALIGN_TOP] );
1129
1130 mpLayout->FirePluginEvent( dragEvt );
1131
1132 return true;
1133 }
1134
1135 void cbFloatedBarWindow::OnDblClick( wxMouseEvent& WXUNUSED(event) )
1136 {
1137 mpLayout->SetBarState( mpBar, wxCBAR_DOCKED_HORIZONTALLY, true );
1138
1139 //wxMessageBox("toolWnd - dblClick!");
1140 }
1141