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