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