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