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