]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/fl/bardragpl.cpp
deprecated wxString::GetWriteBuf() and friends in favour of wxStringBuffer
[wxWidgets.git] / contrib / src / fl / bardragpl.cpp
CommitLineData
8e08b761 1/////////////////////////////////////////////////////////////////////////////
4cbc57f0
JS
2// Name: bardragpl.cpp
3// Purpose: cbBarDragPlugin implementation
8e08b761
JS
4// Author: Aleksandras Gluchovas
5// Modified by:
6// Created: 23/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/bardragpl.h"
24
25#define POS_UNDEFINED -32768
26
27// helpers, FOR NOW:: static
28
29static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
30{
c82c42d4
WS
31 if ( ( r2.x >= r1.x && r2.x <= r1.x + r1.width ) ||
32 ( r1.x >= r2.x && r1.x <= r2.x + r2.width ) )
33 if ( ( r2.y >= r1.y && r2.y <= r1.y + r1.height ) ||
34 ( r1.y >= r2.y && r1.y <= r2.y + r2.height ) )
35 return true;
36 return false;
8e08b761
JS
37}
38
39static inline bool rect_contains_point( const wxRect& rect, int x, int y )
40{
c82c42d4
WS
41 return ( x >= rect.x &&
42 y >= rect.y &&
43 x < rect.x + rect.width &&
44 y < rect.y + rect.height );
8e08b761
JS
45}
46
47/***** Implementation for class cbBarDragPlugin *****/
48
49IMPLEMENT_DYNAMIC_CLASS( cbBarDragPlugin, cbPluginBase )
50
51BEGIN_EVENT_TABLE( cbBarDragPlugin, cbPluginBase )
52
c82c42d4
WS
53 //EVT_PL_LEFT_DOWN ( cbBarDragPlugin::OnLButtonDown )
54 EVT_PL_LEFT_UP ( cbBarDragPlugin::OnLButtonUp )
55 EVT_PL_MOTION ( cbBarDragPlugin::OnMouseMove )
56 EVT_PL_DRAW_HINT_RECT ( cbBarDragPlugin::OnDrawHintRect )
57 EVT_PL_START_BAR_DRAGGING ( cbBarDragPlugin::OnStartBarDragging )
58 EVT_PL_LEFT_DCLICK ( cbBarDragPlugin::OnLDblClick )
8e08b761
JS
59
60END_EVENT_TABLE()
61
62cbBarDragPlugin::cbBarDragPlugin(void)
63
c82c42d4
WS
64 : mBarDragStarted ( false ),
65 mCanStick ( true ),
66 mpScrDc ( NULL ),
67 mpCurCursor ( NULL ),
68 mpDraggedBar ( NULL ),
69 mInClientHintBorder( 4 )
8e08b761
JS
70{}
71
72cbBarDragPlugin::cbBarDragPlugin( wxFrameLayout* pPanel, int paneMask )
73
c82c42d4
WS
74 : cbPluginBase( pPanel, paneMask ),
75
76 mBarDragStarted ( false ),
77 mCanStick ( true ),
78 mpScrDc ( NULL ),
79 mpCurCursor ( NULL ),
80 mpDraggedBar ( NULL ),
81 mInClientHintBorder( 4 )
8e08b761
JS
82{}
83
84cbBarDragPlugin::~cbBarDragPlugin()
85{
c82c42d4 86 // nothing
8e08b761
JS
87}
88
89// helper methods (protected)
90
91// clips (top/bottom) or (right/left) edges against the frame's bounding rect.
92
93void do_clip_edges( int len, int& rectPos, int& rectLen )
94{
c82c42d4
WS
95 if ( rectPos < 0 )
96 {
97 rectLen += rectPos;
98 rectPos = 0;
99 if ( rectLen < 0 )
8e08b761 100 rectLen = 1;
c82c42d4
WS
101 }
102 else
103 if ( rectPos > len-1 )
104 {
105 rectPos = len-1;
106 rectLen = 1;
107 }
108 else
109 if ( rectPos + rectLen - 1 > len )
110 rectLen -= (rectPos + rectLen) - len + 1;
8e08b761
JS
111}
112
113void cbBarDragPlugin::ClipRectInFrame( wxRect& rect )
114{
c82c42d4
WS
115 int w, h;
116 mpLayout->GetParentFrame().GetClientSize( &w, &h );
8e08b761 117
c82c42d4
WS
118 do_clip_edges( w, rect.x, rect.width );
119 do_clip_edges( h, rect.y, rect.height );
8e08b761
JS
120}
121
122void cbBarDragPlugin::ClipPosInFrame( wxPoint& pos )
123{
c82c42d4
WS
124 int w, h;
125 mpLayout->GetParentFrame().GetClientSize( &w, &h );
8e08b761 126
c82c42d4 127 if ( pos.x < 0 )
8e08b761 128 pos.x = 0;
c82c42d4 129 if ( pos.y < 0 )
8e08b761 130 pos.y = 0;
c82c42d4 131 if ( pos.x > w )
8e08b761 132 pos.x = w-1;
c82c42d4 133 if ( pos.y > h )
8e08b761
JS
134 pos.y = h-1;
135}
136
137void cbBarDragPlugin::AdjustHintRect( wxPoint& mousePos )
138{
c82c42d4
WS
139 mHintRect.x = mousePos.x - mMouseInRectX;
140 mHintRect.y = mousePos.y - mMouseInRectY;
8e08b761
JS
141}
142
143cbDockPane* cbBarDragPlugin::HitTestPanes( wxRect& rect )
144{
c82c42d4 145 //wxRect clipped = rect;
8e08b761 146
c82c42d4 147 //ClipRectInFrame( clipped );
8e08b761 148
c82c42d4 149 cbDockPane** pPanes = mpLayout->GetPanesArray();
8e08b761 150
c82c42d4
WS
151 for( int i = 0; i != MAX_PANES; ++i )
152 if ( rect_hits_rect( pPanes[i]->mBoundsInParent, rect ) )
153 return pPanes[i];
8e08b761 154
c82c42d4 155 return NULL;
8e08b761
JS
156}
157
158cbDockPane* cbBarDragPlugin::HitTestPanes( wxPoint& pos )
159{
c82c42d4 160 wxPoint clipped = pos;
8e08b761 161
c82c42d4 162 //ClipPosInFrame( pos );
8e08b761 163
c82c42d4 164 cbDockPane** pPanes = mpLayout->GetPanesArray();
8e08b761 165
c82c42d4
WS
166 for( int i = 0; i != MAX_PANES; ++i )
167 if ( rect_contains_point( pPanes[i]->mBoundsInParent, clipped.x, clipped.y ) )
168 return pPanes[i];
8e08b761 169
c82c42d4 170 return NULL;
8e08b761
JS
171}
172
173bool cbBarDragPlugin::HitsPane( cbDockPane* pPane, wxRect& rect )
174{
c82c42d4 175 return rect_hits_rect( pPane->mBoundsInParent, rect );
8e08b761
JS
176}
177
178int cbBarDragPlugin::GetDistanceToPane( cbDockPane* pPane, wxPoint& mousePos )
179{
c82c42d4 180 wxRect& bounds = pPane->mBoundsInParent;
8e08b761 181
c82c42d4
WS
182 switch( pPane->mAlignment )
183 {
184 case FL_ALIGN_TOP : return mousePos.y - ( bounds.y + bounds.height );
185 case FL_ALIGN_BOTTOM : return bounds.y - mousePos.y;
186 case FL_ALIGN_LEFT : return mousePos.x - ( bounds.x + bounds.width );
187 case FL_ALIGN_RIGHT : return bounds.x - mousePos.x;
188 default : return 0; // never reached
189 }
8e08b761 190
c82c42d4 191// return 0;
8e08b761
JS
192}
193
194bool cbBarDragPlugin::IsInOtherPane( wxPoint& mousePos )
195{
c82c42d4 196 cbDockPane* pPane = HitTestPanes( mousePos );
8e08b761 197
c82c42d4
WS
198 if ( pPane && pPane != mpCurPane ) return true;
199 else return false;
8e08b761
JS
200}
201
202bool cbBarDragPlugin::IsInClientArea( wxPoint& mousePos )
203{
c82c42d4 204 return ( HitTestPanes( mousePos ) == NULL );
8e08b761
JS
205}
206
207bool cbBarDragPlugin::IsInClientArea( wxRect& rect )
208{
c82c42d4 209 return ( HitTestPanes( rect ) == NULL );
8e08b761
JS
210}
211
212void cbBarDragPlugin::CalcOnScreenDims( wxRect& rect )
213{
c82c42d4 214 if ( !mpCurPane || mpDraggedBar->IsFixed() ) return;
8e08b761 215
c82c42d4 216 wxRect inPane = rect;
8e08b761 217
c82c42d4 218 mpCurPane->FrameToPane( &inPane );
8e08b761 219
c82c42d4 220 int rowNo = mpCurPane->GetRowAt( inPane.y, inPane.y + inPane.height );
8e08b761 221
c82c42d4 222 bool isMaximized = ( rowNo >= (int)mpCurPane->GetRowList().Count() || rowNo < 0 );
8e08b761 223
c82c42d4
WS
224 if ( isMaximized )
225 {
226 inPane.x = 0;
227 inPane.width = mpCurPane->mPaneWidth;
8e08b761 228
c82c42d4 229 mpCurPane->PaneToFrame( &inPane );
8e08b761 230
c82c42d4
WS
231 rect = inPane;
232 }
8e08b761
JS
233}
234
18c45cd6 235// helpers
8e08b761
JS
236
237static inline void check_upper_overrun( int& pos, int width, int mousePos )
238{
c82c42d4
WS
239 if ( mousePos >= pos + width )
240 pos = mousePos - width/2;
8e08b761
JS
241}
242
243static inline void check_lower_overrun( int& pos, int width, int mousePos )
244{
c82c42d4
WS
245 if ( mousePos <= pos )
246 pos = mousePos - width/2;
8e08b761
JS
247}
248
249void cbBarDragPlugin::StickToPane( cbDockPane* pPane, wxPoint& mousePos )
250{
c82c42d4
WS
251 int wInPane = GetBarWidthInPane ( pPane );
252 int hInPane = GetBarHeightInPane( pPane );
253
254 // adjsut hint-rect horizontally (in pane's orientation)
8e08b761 255
c82c42d4
WS
256 if ( pPane->IsHorizontal() )
257 {
258 mHintRect.width = wInPane;
259 mHintRect.height = hInPane;
260 }
261 else
262 {
263 mHintRect.height = wInPane;
264 mHintRect.width = hInPane;
265 }
8e08b761 266
c82c42d4 267 // adjsut hint-rect vertically (in pane's orientation)
8e08b761 268
c82c42d4 269 wxRect& bounds = pPane->mBoundsInParent;
8e08b761 270
c82c42d4 271 // true, if hint enters the pane through it's lower edge
8e08b761 272
18c45cd6 273 bool fromLowerEdge = ( pPane->IsHorizontal() )
c82c42d4
WS
274 ? mousePos.y > bounds.y
275 : mousePos.x > bounds.x;
8e08b761 276
c82c42d4
WS
277 // NOTE:: about all the below min/max things: they are meant to ensure
278 // that the mouse pointer doesn't overrun (leave) the hint-rectangle
279 // when its dimensions are recalculated upon sticking it to the pane
8e08b761 280
c82c42d4
WS
281 if ( pPane->IsHorizontal() && fromLowerEdge )
282 {
283 int paneBottomEdgeY = bounds.y + bounds.height;
8e08b761 284
c82c42d4 285 mHintRect.y = wxMin( paneBottomEdgeY, mousePos.y );
8e08b761 286
c82c42d4 287 check_lower_overrun( mHintRect.y, hInPane, mousePos.y );
8e08b761 288
c82c42d4
WS
289 }
290 else
291 if ( pPane->IsHorizontal() && !fromLowerEdge )
292 {
293 int paneTopEdgeY = bounds.y;
8e08b761 294
c82c42d4 295 mHintRect.y = wxMax( paneTopEdgeY - hInPane, mousePos.y - hInPane );
8e08b761 296
c82c42d4
WS
297 check_upper_overrun( mHintRect.y, hInPane, mousePos.y );
298 }
299 else
300 if ( !pPane->IsHorizontal() && fromLowerEdge )
301 {
302 int paneRightEdgeX = bounds.x + bounds.width;
8e08b761 303
c82c42d4 304 mHintRect.x = wxMin( paneRightEdgeX, mousePos.x );
8e08b761 305
c82c42d4
WS
306 check_lower_overrun( mHintRect.x, hInPane, mousePos.x );
307 }
308 else
309 if ( !pPane->IsHorizontal() && !fromLowerEdge )
310 {
311 int paneLeftEdgeX = bounds.x;
8e08b761 312
c82c42d4 313 mHintRect.x = wxMax( paneLeftEdgeX - hInPane, mousePos.x - hInPane );
8e08b761 314
c82c42d4
WS
315 check_upper_overrun( mHintRect.x, hInPane, mousePos.x );
316 }
8e08b761 317
c82c42d4
WS
318 mMouseInRectX = mousePos.x - mHintRect.x;
319 mMouseInRectY = mousePos.y - mHintRect.y;
8e08b761 320
c82c42d4 321 mpCurPane = pPane; // memorize pane to which the hint is currently sticked
8e08b761
JS
322}
323
324void cbBarDragPlugin::UnstickFromPane( cbDockPane* pPane, wxPoint& mousePos )
325{
c82c42d4
WS
326 // unsticking causes rectangle to get the shape in which
327 // dragged control-bar would be when floated
8e08b761 328
c82c42d4
WS
329 int newWidth = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].x;
330 int newHeight = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].y;
8e08b761 331
c82c42d4 332 wxRect& flBounds = mpDraggedBar->mDimInfo.mBounds[wxCBAR_FLOATING];
8e08b761 333
c82c42d4
WS
334 if ( flBounds.width != -1 )
335 {
336 newWidth = flBounds.width;
337 newHeight = flBounds.height;
338 }
8e08b761 339
c82c42d4
WS
340 mHintRect.width = newWidth;
341 mHintRect.height = newHeight;
8e08b761 342
c82c42d4 343 wxRect& bounds = pPane->mBoundsInParent;
8e08b761 344
c82c42d4 345 // true, if hint leaves the pane through it's lower edge
8e08b761 346
18c45cd6 347 bool fromLowerEdge = ( pPane->IsHorizontal() )
c82c42d4
WS
348 ? mousePos.y > bounds.y
349 : mousePos.x > bounds.x;
8e08b761 350
c82c42d4 351 // NOTE:: ...all the below min/max things - see comments about it in StickToPane(..)
8e08b761 352
c82c42d4
WS
353 if ( pPane->IsHorizontal() && fromLowerEdge )
354 {
355 // bool fromLowerEdge = mousePos.y > bounds.y;
8e08b761 356
c82c42d4 357 mHintRect.y = wxMax( bounds.y + bounds.height + 1, mousePos.y - newHeight );
8e08b761 358
c82c42d4 359 check_upper_overrun( mHintRect.y, newHeight, mousePos.y );
8e08b761 360
c82c42d4 361 // this is how MFC's hint behaves:
8e08b761 362
c82c42d4
WS
363 if ( mMouseInRectX > newWidth )
364 mHintRect.x = mousePos.x - ( newWidth / 2 );
365 }
366 else
367 if ( pPane->IsHorizontal() && !fromLowerEdge )
368 {
369 mHintRect.y = wxMin( bounds.y - newHeight - 1, mousePos.y );
8e08b761 370
c82c42d4 371 // -/-
8e08b761 372
c82c42d4
WS
373 if ( mMouseInRectX > newWidth )
374 mHintRect.x = mousePos.x - ( newWidth / 2 );
8e08b761 375
c82c42d4
WS
376 check_lower_overrun( mHintRect.y, newHeight, mousePos.y );
377 }
378 else
379 if ( !pPane->IsHorizontal() && fromLowerEdge )
380 {
381 mHintRect.x = wxMax( bounds.x + bounds.width, mousePos.x - newWidth );
8e08b761 382
c82c42d4 383 // -/-
8e08b761 384
c82c42d4
WS
385 if ( mMouseInRectY > newHeight )
386 mHintRect.y = mousePos.y - ( newHeight / 2 );
8e08b761 387
c82c42d4
WS
388 check_upper_overrun( mHintRect.x, newWidth, mousePos.x );
389 }
390 else
391 if ( !pPane->IsHorizontal() && !fromLowerEdge )
392 {
393 mHintRect.x = wxMin( bounds.x - newWidth - 1, mousePos.x );
8e08b761 394
c82c42d4 395 // -/-
8e08b761 396
c82c42d4
WS
397 if ( mMouseInRectY > newHeight )
398 mHintRect.y = mousePos.y - ( newHeight / 2 );
8e08b761 399
c82c42d4
WS
400 check_lower_overrun( mHintRect.x, newWidth, mousePos.x );
401 }
8e08b761 402
c82c42d4
WS
403 mMouseInRectX = mousePos.x - mHintRect.x;
404 mMouseInRectY = mousePos.y - mHintRect.y;
8e08b761 405
c82c42d4
WS
406 mpCurPane = NULL;
407}
8e08b761
JS
408
409int cbBarDragPlugin::GetBarWidthInPane( cbDockPane* pPane )
410{
c82c42d4
WS
411 if ( pPane == mpSrcPane )
412 return mBarWidthInSrcPane;
8e08b761 413
c82c42d4 414 // this is how MFC's bars behave:
8e08b761 415
c82c42d4
WS
416 if ( pPane->IsHorizontal() )
417 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].x;
418 else
419 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].x;
8e08b761
JS
420}
421
422int cbBarDragPlugin::GetBarHeightInPane( cbDockPane* pPane )
423{
c82c42d4
WS
424 if ( pPane->IsHorizontal() )
425 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].y;
426 else
427 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].y;
8e08b761
JS
428}
429
430void cbBarDragPlugin::ShowHint( bool prevWasInClient )
431{
c82c42d4 432 bool wasDocked = false;
8e08b761 433
c82c42d4
WS
434 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false )
435 {
436 // do heavy calculations first
8e08b761 437
c82c42d4 438 wxRect actualRect = mHintRect; // will be adjusted depending on drag-settings
8e08b761 439
c82c42d4
WS
440 if ( mpSrcPane->mProps.mExactDockPredictionOn && mpCurPane )
441 {
442#ifdef __WXDEBUG__
18c45cd6 443 bool success =
c82c42d4
WS
444#endif
445 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );
8e08b761 446
c82c42d4 447 wxASSERT( success ); // DBG::
8e08b761 448
c82c42d4 449 actualRect = mpDraggedBar->mBounds;
8e08b761 450
c82c42d4
WS
451 mpCurPane->PaneToFrame( &actualRect );
452 }
453 else
454 CalcOnScreenDims( actualRect );
8e08b761 455
c82c42d4 456 // release previous hint
8e08b761 457
c82c42d4
WS
458 if ( mPrevHintRect.x != POS_UNDEFINED )
459 {
460 // erase previous rectangle
8e08b761 461
c82c42d4 462 cbDrawHintRectEvent evt( mPrevHintRect, prevWasInClient, true, false );
8e08b761 463
c82c42d4
WS
464 mpLayout->FirePluginEvent( evt );
465 }
8e08b761 466
c82c42d4 467 // draw new hint
8e08b761 468
c82c42d4 469 cbDrawHintRectEvent evt( actualRect, mpCurPane == NULL, false, false );
8e08b761 470
c82c42d4 471 mpLayout->FirePluginEvent( evt );
8e08b761 472
c82c42d4
WS
473 mPrevHintRect = actualRect;
474 }
18c45cd6 475 else
c82c42d4
WS
476 {
477 // otherwise, if real-time updates option is ON
8e08b761 478
c82c42d4
WS
479 if ( mpDraggedBar->mState != wxCBAR_FLOATING && !mpCurPane )
480 {
481 mpLayout->SetBarState( mpDraggedBar, wxCBAR_FLOATING, true );
482 }
483 else
484 if ( mpDraggedBar->mState == wxCBAR_FLOATING && mpCurPane )
485 {
486 mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, false );
879da8c8 487
c82c42d4
WS
488 wasDocked = true;
489 }
879da8c8 490
c82c42d4
WS
491 if ( mpCurPane )
492 {
493 mpLayout->GetUpdatesManager().OnStartChanges();
8e08b761 494
c82c42d4 495 if ( wasDocked )
8e08b761 496
c82c42d4 497 mpDraggedBar->mUMgrData.SetDirty( true );
8e08b761 498
c82c42d4 499#ifdef __WXDEBUG__
18c45cd6 500 bool success =
c82c42d4
WS
501#endif
502 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );
8e08b761 503
c82c42d4 504 wxASSERT( success ); // DBG ::
8e08b761 505
c82c42d4
WS
506 mpLayout->GetUpdatesManager().OnFinishChanges();
507 mpLayout->GetUpdatesManager().UpdateNow();
508 }
509 else
510 {
511 if ( mpLayout->mFloatingOn )
512 {
513 // move the top-most floated bar around as user drags the hint
8e08b761 514
c82c42d4 515 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
8e08b761 516
c82c42d4
WS
517 mpLayout->ApplyBarProperties( mpDraggedBar );
518 }
519 }
520 }
8e08b761
JS
521}
522
523/*** event handlers ***/
524
525void cbBarDragPlugin::OnMouseMove( cbMotionEvent& event )
526{
c82c42d4
WS
527 // calculate postion in frame's coordiantes
528
529 if ( !mBarDragStarted )
879da8c8 530 {
c82c42d4
WS
531 event.Skip(); // pass event to the next plugin
532 return;
879da8c8 533 }
c82c42d4
WS
534
535 wxPoint mousePos = event.mPos;
536
537 event.mpPane->PaneToFrame( &mousePos.x, &mousePos.y );
538
539 bool prevIsInClient = ( mpCurPane == 0 );
540
541 AdjustHintRect( mousePos );
542
543 // if the hint-rect is not "tempted" to any pane yet
544
545 if ( mpCurPane == NULL )
546 {
547 cbDockPane* pPane = HitTestPanes( mHintRect );
548
549 // enable sticking again, if we've left the pane completely
18c45cd6 550 if ( !pPane )
c82c42d4
WS
551 mCanStick = true;
552
18c45cd6 553 if ( mCanStick && pPane &&
c82c42d4
WS
554 GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) )
555 StickToPane( pPane, mousePos );
556 else
557 if ( pPane && HitTestPanes( mousePos ) == pPane && 0 ) // FOR NOW:: disabled
558
559 StickToPane( pPane, mousePos );
560 }
561 else
562 {
563 // otherwise, when rect is now sticked to some of the panes
564 // check if it should still remain in this pane
565
566 mCanStick = true;
567
568 bool mouseInOther = IsInOtherPane( mousePos );
569
570 if ( mouseInOther )
571 {
572 cbDockPane* pPane = HitTestPanes( mousePos );
573
574 StickToPane( pPane, mousePos );
575 }
576 else
577 {
578 if ( IsInClientArea( mousePos ) )
579 {
580 cbDockPane* pPane = HitTestPanes( mHintRect );
581
18c45cd6 582 if ( pPane &&
c82c42d4
WS
583 pPane != mpCurPane &&
584 GetDistanceToPane( pPane, mousePos ) < GetBarHeightInPane( pPane ) )
585 StickToPane( pPane, mousePos );
586 else
587 if ( !pPane )
588 {
589 UnstickFromPane( mpCurPane, mousePos );
590
591 // FOR NOW:: disabled, would cause some mess
592 // mCanStick = false; // prevents from sticking to this
593 // pane again, flag is reset when hint-rect
594 // leaves the pane completely
595 }
596 else
597 if ( GetDistanceToPane( pPane, mousePos ) > GetBarHeightInPane( pPane ) )
598 {
599 if ( !HitsPane( mpCurPane, mHintRect ) )
600 {
601 UnstickFromPane( mpCurPane, mousePos );
602
603 // FOR NOW:: disabled, would cause some mess
604 // mCanStick = false; // prevents from sticking to this
605 // pane again, flag is reset when hint-rect
606 // leaves the pane completely
607 }
608 }
609
610 }
611 }
612 }
613
614 ShowHint( prevIsInClient );
615
616 wxCursor* pPrevCurs = mpCurCursor;
617
618 if ( mpCurPane )
619 {
620 mpCurCursor = mpLayout->mpNormalCursor;
621 }
622 else
623 {
879da8c8
JS
624 // if floating is off, and we are in the client
625 // area, the cursor will be invalid, otherwise
626 // it will be the normal cursor
c82c42d4 627
879da8c8
JS
628 if (mpLayout->mFloatingOn)
629 {
c82c42d4 630 mpCurCursor = mpLayout->mpNormalCursor;
879da8c8 631 }
c82c42d4 632 else
879da8c8 633 {
c82c42d4
WS
634 mpCurCursor = mpLayout->mpNECursor;
635 }
879da8c8 636
c82c42d4
WS
637 }
638 if ( pPrevCurs != mpCurCursor )
639 mpLayout->GetParentFrame().SetCursor( *mpCurCursor );
8e08b761
JS
640}
641
642void cbBarDragPlugin::OnLButtonDown( cbLeftDownEvent& event )
643{
c82c42d4
WS
644 if ( mBarDragStarted )
645 {
646 wxMessageBox(wxT("DblClick!"));
647 }
8e08b761 648
c82c42d4 649 event.Skip();
8e08b761
JS
650}
651
652void cbBarDragPlugin::OnLButtonUp( cbLeftUpEvent& event )
653{
c82c42d4
WS
654 if ( mBarDragStarted )
655 {
656 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false )
657 {
658 // erase current rectangle, and finsih on-screen drawing session
8e08b761 659
c82c42d4 660 cbDrawHintRectEvent evt( mPrevHintRect, mpCurPane == NULL, true, true );
8e08b761 661
c82c42d4 662 mpLayout->FirePluginEvent( evt );
8e08b761 663
c82c42d4
WS
664 if ( mpCurPane != NULL )
665 {
666 if ( mpSrcPane->mProps.mExactDockPredictionOn )
667 {
668 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );
8e08b761 669
c82c42d4
WS
670 mpLayout->GetUpdatesManager().OnFinishChanges();
671 mpLayout->GetUpdatesManager().UpdateNow();
672 }
673 else
879da8c8
JS
674 {
675 if (mpDraggedBar->mState == wxCBAR_FLOATING)
676 {
c82c42d4 677 mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, true);
879da8c8
JS
678 }
679
c82c42d4
WS
680 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane );
681 }
682 }
683 else
879da8c8
JS
684 {
685 if (mpDraggedBar->mState != wxCBAR_FLOATING)
686 {
687 mpLayout->SetBarState(mpDraggedBar, wxCBAR_FLOATING, true);
688 }
689
c82c42d4
WS
690 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
691 mpLayout->ApplyBarProperties( mpDraggedBar );
879da8c8 692 }
c82c42d4
WS
693 }
694
695 mHintRect.width = -1;
8e08b761 696
a570d5b3
JS
697 // In Windows, at least, the frame needs to have a null cursor
698 // else child windows (such as text windows) inherit the cursor
699#if 1
700 mpLayout->GetParentFrame().SetCursor( wxNullCursor );
701#else
702 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
703#endif
8e08b761 704
c82c42d4
WS
705 mpLayout->ReleaseEventsFromPane( event.mpPane );
706 mpLayout->ReleaseEventsFromPlugin( this );
8e08b761 707
c82c42d4 708 mBarDragStarted = false;
8e08b761 709
c82c42d4
WS
710 if ( mBarWasFloating && mpDraggedBar->mState != wxCBAR_FLOATING )
711 {
18c45cd6 712 // save bar's floating position before it was docked
8e08b761 713
c82c42d4
WS
714 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mFloatedBarBounds;
715 }
716 }
717 else
718 event.Skip(); // pass event to the next plugin
8e08b761
JS
719}
720
721void cbBarDragPlugin::OnLDblClick( cbLeftDClickEvent& event )
722{
c82c42d4
WS
723 int avoidCompilerWarning = 1;
724 if ( avoidCompilerWarning )
725 {
726 cbBarInfo* pHittedBar;
727 cbRowInfo* pRow;
8e08b761 728
c82c42d4
WS
729 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
730 &pRow,
731 &pHittedBar ) == CB_BAR_CONTENT_HITTED
732 )
733 {
734 mpLayout->SetBarState( pHittedBar, wxCBAR_FLOATING, true );
8e08b761 735
c82c42d4 736 mpLayout->RepositionFloatedBar( pHittedBar );
8e08b761 737
c82c42d4
WS
738 return; // event is "eaten" by this plugin
739 }
8e08b761 740
c82c42d4 741 mBarDragStarted = false;
8e08b761 742
c82c42d4
WS
743 event.Skip();
744 }
8e08b761 745
c82c42d4 746 //wxMessageBox("Hi, dblclick arrived!");
8e08b761
JS
747}
748
749void cbBarDragPlugin::OnStartBarDragging( cbStartBarDraggingEvent& event )
750{
c82c42d4 751 mpDraggedBar = event.mpBar;
18c45cd6 752 mpSrcPane = event.mpPane;
c82c42d4
WS
753
754 mpLayout->CaptureEventsForPane( event.mpPane );
755 mpLayout->CaptureEventsForPlugin( this );
8e08b761 756
c82c42d4 757 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
8e08b761 758
c82c42d4 759 mBarDragStarted = true;
8e08b761 760
c82c42d4 761 wxRect inParent = mpDraggedBar->mBounds;
8e08b761 762
c82c42d4 763 mBarWasFloating = mpDraggedBar->mState == wxCBAR_FLOATING;
8e08b761 764
c82c42d4
WS
765 if ( mBarWasFloating )
766 {
767 inParent = mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
768 mFloatedBarBounds = inParent;
769 }
770 else
771 event.mpPane->PaneToFrame( &inParent );
8e08b761 772
c82c42d4 773 mHintRect.x = POS_UNDEFINED;
8e08b761 774
c82c42d4
WS
775 mHintRect.width = inParent.width;
776 mHintRect.height = inParent.height;
8e08b761 777
c82c42d4
WS
778 mMouseInRectX = event.mPos.x - inParent.x;
779 mMouseInRectY = event.mPos.y - inParent.y;
8e08b761 780
c82c42d4 781 mpSrcPane = event.mpPane;
8e08b761 782
c82c42d4 783 if ( mpDraggedBar->mState == wxCBAR_FLOATING )
8e08b761 784
c82c42d4
WS
785 mpCurPane = NULL;
786 else
787 mpCurPane = event.mpPane;
8e08b761 788
c82c42d4 789 mPrevHintRect.x = POS_UNDEFINED;
8e08b761 790
18c45cd6 791 mCanStick = false; // we're not stuck into any pane now -
c82c42d4 792 // there's nowhere to "stick-twice"
8e08b761 793
c82c42d4 794 mBarWidthInSrcPane = mpDraggedBar->mDimInfo.mSizes[ mpDraggedBar->mState ].x;
8e08b761 795
18c45cd6 796 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false &&
c82c42d4
WS
797 mpSrcPane->mProps.mExactDockPredictionOn )
798 mpLayout->GetUpdatesManager().OnStartChanges(); // capture initial state of layout
8e08b761 799
c82c42d4 800 // simulate the first mouse movement
8e08b761 801
c82c42d4 802 int x = event.mPos.x, y = event.mPos.y;
c82c42d4 803 mpSrcPane->FrameToPane( &x, &y );
8e08b761 804
18c45cd6
WS
805 wxPoint pt(x,y);
806 cbMotionEvent motionEvt( pt, event.mpPane );
c82c42d4
WS
807 this->OnMouseMove( motionEvt );
808
809 return; // event is "eaten" by this plugin
8e08b761
JS
810}
811
812/*** on-screen hint-tracking related methods ***/
813
814void cbBarDragPlugin::OnDrawHintRect( cbDrawHintRectEvent& event )
815{
c82c42d4 816 if ( !mpScrDc ) StartTracking();
8e08b761 817
c82c42d4 818 DoDrawHintRect( event.mRect, event.mIsInClient );
8e08b761 819
c82c42d4
WS
820 if ( event.mLastTime )
821 FinishTracking();
8e08b761
JS
822}
823
824#define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
825#define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
826#define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons.
827#define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons.
828
829// FOR NOW:: static
830
831static const unsigned char _gCheckerImg[16] = { _IMG_A,_IMG_B,_IMG_C,_IMG_D,
c82c42d4
WS
832 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
833 _IMG_A,_IMG_B,_IMG_C,_IMG_D,
834 _IMG_A,_IMG_B,_IMG_C,_IMG_D
835 };
8e08b761
JS
836
837void cbBarDragPlugin::StartTracking()
838{
c82c42d4 839 mpScrDc = new wxScreenDC;
8e08b761 840
c82c42d4 841 wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());
8e08b761
JS
842}
843
844void cbBarDragPlugin::DoDrawHintRect( wxRect& rect, bool isInClientRect)
845{
c82c42d4 846 wxRect scrRect;
8e08b761 847
c82c42d4 848 RectToScr( rect, scrRect );
8e08b761 849
c82c42d4 850 int prevLF = mpScrDc->GetLogicalFunction();
8e08b761 851
c82c42d4 852 mpScrDc->SetLogicalFunction( wxINVERT );
8e08b761 853
c82c42d4
WS
854 if ( isInClientRect )
855 {
18c45cd6 856 // BUG BUG BUG (wx):: somehow stippled brush works only
c82c42d4
WS
857 // when the bitmap created on stack, not
858 // as a member of the class
8e08b761 859
c82c42d4 860 wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
8e08b761 861
c82c42d4 862 wxBrush checkerBrush( checker );
8e08b761 863
c82c42d4
WS
864 mpScrDc->SetPen( mpLayout->mNullPen );
865 mpScrDc->SetBrush( checkerBrush );
8e08b761 866
c82c42d4 867 int half = mInClientHintBorder / 2;
8e08b761 868
c82c42d4
WS
869 mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y - half,
870 scrRect.width + 2*half, mInClientHintBorder );
8e08b761 871
c82c42d4
WS
872 mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + scrRect.height - half,
873 scrRect.width + 2*half, mInClientHintBorder );
8e08b761 874
c82c42d4
WS
875 mpScrDc->DrawRectangle( scrRect.x - half, scrRect.y + half - 1,
876 mInClientHintBorder, scrRect.height - 2*half + 2);
8e08b761 877
c82c42d4
WS
878 mpScrDc->DrawRectangle( scrRect.x + scrRect.width - half,
879 scrRect.y + half - 1,
880 mInClientHintBorder, scrRect.height - 2*half + 2);
8e08b761 881
c82c42d4
WS
882 mpScrDc->SetBrush( wxNullBrush );
883 }
884 else
885 {
886 mpScrDc->SetPen( mpLayout->mBlackPen );
8e08b761 887
18c45cd6 888 mpScrDc->DrawLine( scrRect.x, scrRect.y,
c82c42d4 889 scrRect.x + scrRect.width, scrRect.y );
8e08b761 890
18c45cd6 891 mpScrDc->DrawLine( scrRect.x, scrRect.y + 1,
c82c42d4 892 scrRect.x, scrRect.y + scrRect.height );
8e08b761 893
18c45cd6 894 mpScrDc->DrawLine( scrRect.x+1, scrRect.y + scrRect.height,
c82c42d4 895 scrRect.x + scrRect.width, scrRect.y + scrRect.height );
8e08b761 896
18c45cd6 897 mpScrDc->DrawLine( scrRect.x + scrRect.width , scrRect.y,
c82c42d4
WS
898 scrRect.x + scrRect.width, scrRect.y + scrRect.height + 1);
899 }
8e08b761 900
c82c42d4 901 mpScrDc->SetLogicalFunction( prevLF );
8e08b761
JS
902}
903
904void cbBarDragPlugin::DrawHintRect ( wxRect& rect, bool isInClientRect)
905{
c82c42d4 906 DoDrawHintRect( rect, isInClientRect );
8e08b761
JS
907}
908
909void cbBarDragPlugin::EraseHintRect( wxRect& rect, bool isInClientRect)
910{
c82c42d4 911 DoDrawHintRect( rect, isInClientRect );
8e08b761
JS
912}
913
914void cbBarDragPlugin::FinishTracking()
915{
c82c42d4 916 wxScreenDC::EndDrawingOnTop();
8e08b761 917
c82c42d4 918 delete mpScrDc;
8e08b761 919
c82c42d4 920 mpScrDc = NULL;
8e08b761
JS
921}
922
923void cbBarDragPlugin::RectToScr( wxRect& frameRect, wxRect& scrRect )
924{
c82c42d4 925 scrRect = frameRect;
8e08b761 926
c82c42d4 927 int x = frameRect.x, y = frameRect.y;
8e08b761 928
c82c42d4 929 mpLayout->GetParentFrame().ClientToScreen( &x, &y );
8e08b761 930
c82c42d4
WS
931 scrRect.x = x;
932 scrRect.y = y;
8e08b761
JS
933}
934