]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/bardragpl.cpp
Improved ugly custom tool button drawing
[wxWidgets.git] / contrib / src / fl / bardragpl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bardragpl.cpp
3 // Purpose: cbBarDragPlugin implementation
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 23/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
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
29 static inline bool rect_hits_rect( const wxRect& r1, const wxRect& r2 )
30 {
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;
37 }
38
39 static inline bool rect_contains_point( const wxRect& rect, int x, int y )
40 {
41 return ( x >= rect.x &&
42 y >= rect.y &&
43 x < rect.x + rect.width &&
44 y < rect.y + rect.height );
45 }
46
47 /***** Implementation for class cbBarDragPlugin *****/
48
49 IMPLEMENT_DYNAMIC_CLASS( cbBarDragPlugin, cbPluginBase )
50
51 BEGIN_EVENT_TABLE( cbBarDragPlugin, cbPluginBase )
52
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 )
59
60 END_EVENT_TABLE()
61
62 cbBarDragPlugin::cbBarDragPlugin(void)
63
64 : mBarDragStarted ( false ),
65 mCanStick ( true ),
66 mpScrDc ( NULL ),
67 mpCurCursor ( NULL ),
68 mpDraggedBar ( NULL ),
69 mInClientHintBorder( 4 )
70 {}
71
72 cbBarDragPlugin::cbBarDragPlugin( wxFrameLayout* pPanel, int paneMask )
73
74 : cbPluginBase( pPanel, paneMask ),
75
76 mBarDragStarted ( false ),
77 mCanStick ( true ),
78 mpScrDc ( NULL ),
79 mpCurCursor ( NULL ),
80 mpDraggedBar ( NULL ),
81 mInClientHintBorder( 4 )
82 {}
83
84 cbBarDragPlugin::~cbBarDragPlugin()
85 {
86 // nothing
87 }
88
89 // helper methods (protected)
90
91 // clips (top/bottom) or (right/left) edges against the frame's bounding rect.
92
93 void do_clip_edges( int len, int& rectPos, int& rectLen )
94 {
95 if ( rectPos < 0 )
96 {
97 rectLen += rectPos;
98 rectPos = 0;
99 if ( rectLen < 0 )
100 rectLen = 1;
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;
111 }
112
113 void cbBarDragPlugin::ClipRectInFrame( wxRect& rect )
114 {
115 int w, h;
116 mpLayout->GetParentFrame().GetClientSize( &w, &h );
117
118 do_clip_edges( w, rect.x, rect.width );
119 do_clip_edges( h, rect.y, rect.height );
120 }
121
122 void cbBarDragPlugin::ClipPosInFrame( wxPoint& pos )
123 {
124 int w, h;
125 mpLayout->GetParentFrame().GetClientSize( &w, &h );
126
127 if ( pos.x < 0 )
128 pos.x = 0;
129 if ( pos.y < 0 )
130 pos.y = 0;
131 if ( pos.x > w )
132 pos.x = w-1;
133 if ( pos.y > h )
134 pos.y = h-1;
135 }
136
137 void cbBarDragPlugin::AdjustHintRect( wxPoint& mousePos )
138 {
139 mHintRect.x = mousePos.x - mMouseInRectX;
140 mHintRect.y = mousePos.y - mMouseInRectY;
141 }
142
143 cbDockPane* cbBarDragPlugin::HitTestPanes( wxRect& rect )
144 {
145 //wxRect clipped = rect;
146
147 //ClipRectInFrame( clipped );
148
149 cbDockPane** pPanes = mpLayout->GetPanesArray();
150
151 for( int i = 0; i != MAX_PANES; ++i )
152 if ( rect_hits_rect( pPanes[i]->mBoundsInParent, rect ) )
153 return pPanes[i];
154
155 return NULL;
156 }
157
158 cbDockPane* cbBarDragPlugin::HitTestPanes( wxPoint& pos )
159 {
160 wxPoint clipped = pos;
161
162 //ClipPosInFrame( pos );
163
164 cbDockPane** pPanes = mpLayout->GetPanesArray();
165
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];
169
170 return NULL;
171 }
172
173 bool cbBarDragPlugin::HitsPane( cbDockPane* pPane, wxRect& rect )
174 {
175 return rect_hits_rect( pPane->mBoundsInParent, rect );
176 }
177
178 int cbBarDragPlugin::GetDistanceToPane( cbDockPane* pPane, wxPoint& mousePos )
179 {
180 wxRect& bounds = pPane->mBoundsInParent;
181
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 }
190
191 // return 0;
192 }
193
194 bool cbBarDragPlugin::IsInOtherPane( wxPoint& mousePos )
195 {
196 cbDockPane* pPane = HitTestPanes( mousePos );
197
198 if ( pPane && pPane != mpCurPane ) return true;
199 else return false;
200 }
201
202 bool cbBarDragPlugin::IsInClientArea( wxPoint& mousePos )
203 {
204 return ( HitTestPanes( mousePos ) == NULL );
205 }
206
207 bool cbBarDragPlugin::IsInClientArea( wxRect& rect )
208 {
209 return ( HitTestPanes( rect ) == NULL );
210 }
211
212 void cbBarDragPlugin::CalcOnScreenDims( wxRect& rect )
213 {
214 if ( !mpCurPane || mpDraggedBar->IsFixed() ) return;
215
216 wxRect inPane = rect;
217
218 mpCurPane->FrameToPane( &inPane );
219
220 int rowNo = mpCurPane->GetRowAt( inPane.y, inPane.y + inPane.height );
221
222 bool isMaximized = ( rowNo >= (int)mpCurPane->GetRowList().Count() || rowNo < 0 );
223
224 if ( isMaximized )
225 {
226 inPane.x = 0;
227 inPane.width = mpCurPane->mPaneWidth;
228
229 mpCurPane->PaneToFrame( &inPane );
230
231 rect = inPane;
232 }
233 }
234
235 // helpers
236
237 static inline void check_upper_overrun( int& pos, int width, int mousePos )
238 {
239 if ( mousePos >= pos + width )
240 pos = mousePos - width/2;
241 }
242
243 static inline void check_lower_overrun( int& pos, int width, int mousePos )
244 {
245 if ( mousePos <= pos )
246 pos = mousePos - width/2;
247 }
248
249 void cbBarDragPlugin::StickToPane( cbDockPane* pPane, wxPoint& mousePos )
250 {
251 int wInPane = GetBarWidthInPane ( pPane );
252 int hInPane = GetBarHeightInPane( pPane );
253
254 // adjsut hint-rect horizontally (in pane's orientation)
255
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 }
266
267 // adjsut hint-rect vertically (in pane's orientation)
268
269 wxRect& bounds = pPane->mBoundsInParent;
270
271 // true, if hint enters the pane through it's lower edge
272
273 bool fromLowerEdge = ( pPane->IsHorizontal() )
274 ? mousePos.y > bounds.y
275 : mousePos.x > bounds.x;
276
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
280
281 if ( pPane->IsHorizontal() && fromLowerEdge )
282 {
283 int paneBottomEdgeY = bounds.y + bounds.height;
284
285 mHintRect.y = wxMin( paneBottomEdgeY, mousePos.y );
286
287 check_lower_overrun( mHintRect.y, hInPane, mousePos.y );
288
289 }
290 else
291 if ( pPane->IsHorizontal() && !fromLowerEdge )
292 {
293 int paneTopEdgeY = bounds.y;
294
295 mHintRect.y = wxMax( paneTopEdgeY - hInPane, mousePos.y - hInPane );
296
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;
303
304 mHintRect.x = wxMin( paneRightEdgeX, mousePos.x );
305
306 check_lower_overrun( mHintRect.x, hInPane, mousePos.x );
307 }
308 else
309 if ( !pPane->IsHorizontal() && !fromLowerEdge )
310 {
311 int paneLeftEdgeX = bounds.x;
312
313 mHintRect.x = wxMax( paneLeftEdgeX - hInPane, mousePos.x - hInPane );
314
315 check_upper_overrun( mHintRect.x, hInPane, mousePos.x );
316 }
317
318 mMouseInRectX = mousePos.x - mHintRect.x;
319 mMouseInRectY = mousePos.y - mHintRect.y;
320
321 mpCurPane = pPane; // memorize pane to which the hint is currently sticked
322 }
323
324 void cbBarDragPlugin::UnstickFromPane( cbDockPane* pPane, wxPoint& mousePos )
325 {
326 // unsticking causes rectangle to get the shape in which
327 // dragged control-bar would be when floated
328
329 int newWidth = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].x;
330 int newHeight = mpDraggedBar->mDimInfo.mSizes[wxCBAR_FLOATING].y;
331
332 wxRect& flBounds = mpDraggedBar->mDimInfo.mBounds[wxCBAR_FLOATING];
333
334 if ( flBounds.width != -1 )
335 {
336 newWidth = flBounds.width;
337 newHeight = flBounds.height;
338 }
339
340 mHintRect.width = newWidth;
341 mHintRect.height = newHeight;
342
343 wxRect& bounds = pPane->mBoundsInParent;
344
345 // true, if hint leaves the pane through it's lower edge
346
347 bool fromLowerEdge = ( pPane->IsHorizontal() )
348 ? mousePos.y > bounds.y
349 : mousePos.x > bounds.x;
350
351 // NOTE:: ...all the below min/max things - see comments about it in StickToPane(..)
352
353 if ( pPane->IsHorizontal() && fromLowerEdge )
354 {
355 // bool fromLowerEdge = mousePos.y > bounds.y;
356
357 mHintRect.y = wxMax( bounds.y + bounds.height + 1, mousePos.y - newHeight );
358
359 check_upper_overrun( mHintRect.y, newHeight, mousePos.y );
360
361 // this is how MFC's hint behaves:
362
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 );
370
371 // -/-
372
373 if ( mMouseInRectX > newWidth )
374 mHintRect.x = mousePos.x - ( newWidth / 2 );
375
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 );
382
383 // -/-
384
385 if ( mMouseInRectY > newHeight )
386 mHintRect.y = mousePos.y - ( newHeight / 2 );
387
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 );
394
395 // -/-
396
397 if ( mMouseInRectY > newHeight )
398 mHintRect.y = mousePos.y - ( newHeight / 2 );
399
400 check_lower_overrun( mHintRect.x, newWidth, mousePos.x );
401 }
402
403 mMouseInRectX = mousePos.x - mHintRect.x;
404 mMouseInRectY = mousePos.y - mHintRect.y;
405
406 mpCurPane = NULL;
407 }
408
409 int cbBarDragPlugin::GetBarWidthInPane( cbDockPane* pPane )
410 {
411 if ( pPane == mpSrcPane )
412 return mBarWidthInSrcPane;
413
414 // this is how MFC's bars behave:
415
416 if ( pPane->IsHorizontal() )
417 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].x;
418 else
419 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].x;
420 }
421
422 int cbBarDragPlugin::GetBarHeightInPane( cbDockPane* pPane )
423 {
424 if ( pPane->IsHorizontal() )
425 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_HORIZONTALLY].y;
426 else
427 return mpDraggedBar->mDimInfo.mSizes[wxCBAR_DOCKED_VERTICALLY ].y;
428 }
429
430 void cbBarDragPlugin::ShowHint( bool prevWasInClient )
431 {
432 bool wasDocked = false;
433
434 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false )
435 {
436 // do heavy calculations first
437
438 wxRect actualRect = mHintRect; // will be adjusted depending on drag-settings
439
440 if ( mpSrcPane->mProps.mExactDockPredictionOn && mpCurPane )
441 {
442 #ifdef __WXDEBUG__
443 bool success =
444 #endif
445 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );
446
447 wxASSERT( success ); // DBG::
448
449 actualRect = mpDraggedBar->mBounds;
450
451 mpCurPane->PaneToFrame( &actualRect );
452 }
453 else
454 CalcOnScreenDims( actualRect );
455
456 // release previous hint
457
458 if ( mPrevHintRect.x != POS_UNDEFINED )
459 {
460 // erase previous rectangle
461
462 cbDrawHintRectEvent evt( mPrevHintRect, prevWasInClient, true, false );
463
464 mpLayout->FirePluginEvent( evt );
465 }
466
467 // draw new hint
468
469 cbDrawHintRectEvent evt( actualRect, mpCurPane == NULL, false, false );
470
471 mpLayout->FirePluginEvent( evt );
472
473 mPrevHintRect = actualRect;
474 }
475 else
476 {
477 // otherwise, if real-time updates option is ON
478
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 );
487
488 wasDocked = true;
489 }
490
491 if ( mpCurPane )
492 {
493 mpLayout->GetUpdatesManager().OnStartChanges();
494
495 if ( wasDocked )
496
497 mpDraggedBar->mUMgrData.SetDirty( true );
498
499 #ifdef __WXDEBUG__
500 bool success =
501 #endif
502 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );
503
504 wxASSERT( success ); // DBG ::
505
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
514
515 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
516
517 mpLayout->ApplyBarProperties( mpDraggedBar );
518 }
519 }
520 }
521 }
522
523 /*** event handlers ***/
524
525 void cbBarDragPlugin::OnMouseMove( cbMotionEvent& event )
526 {
527 // calculate postion in frame's coordiantes
528
529 if ( !mBarDragStarted )
530 {
531 event.Skip(); // pass event to the next plugin
532 return;
533 }
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
550 if ( !pPane )
551 mCanStick = true;
552
553 if ( mCanStick && pPane &&
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
582 if ( pPane &&
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 {
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
627
628 if (mpLayout->mFloatingOn)
629 {
630 mpCurCursor = mpLayout->mpNormalCursor;
631 }
632 else
633 {
634 mpCurCursor = mpLayout->mpNECursor;
635 }
636
637 }
638 if ( pPrevCurs != mpCurCursor )
639 mpLayout->GetParentFrame().SetCursor( *mpCurCursor );
640 }
641
642 void cbBarDragPlugin::OnLButtonDown( cbLeftDownEvent& event )
643 {
644 if ( mBarDragStarted )
645 {
646 wxMessageBox(wxT("DblClick!"));
647 }
648
649 event.Skip();
650 }
651
652 void cbBarDragPlugin::OnLButtonUp( cbLeftUpEvent& event )
653 {
654 if ( mBarDragStarted )
655 {
656 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false )
657 {
658 // erase current rectangle, and finsih on-screen drawing session
659
660 cbDrawHintRectEvent evt( mPrevHintRect, mpCurPane == NULL, true, true );
661
662 mpLayout->FirePluginEvent( evt );
663
664 if ( mpCurPane != NULL )
665 {
666 if ( mpSrcPane->mProps.mExactDockPredictionOn )
667 {
668 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane, false );
669
670 mpLayout->GetUpdatesManager().OnFinishChanges();
671 mpLayout->GetUpdatesManager().UpdateNow();
672 }
673 else
674 {
675 if (mpDraggedBar->mState == wxCBAR_FLOATING)
676 {
677 mpLayout->SetBarState( mpDraggedBar, wxCBAR_DOCKED_HORIZONTALLY, true);
678 }
679
680 mpLayout->RedockBar( mpDraggedBar, mHintRect, mpCurPane );
681 }
682 }
683 else
684 {
685 if (mpDraggedBar->mState != wxCBAR_FLOATING)
686 {
687 mpLayout->SetBarState(mpDraggedBar, wxCBAR_FLOATING, true);
688 }
689
690 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mHintRect;
691 mpLayout->ApplyBarProperties( mpDraggedBar );
692 }
693 }
694
695 mHintRect.width = -1;
696
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
704
705 mpLayout->ReleaseEventsFromPane( event.mpPane );
706 mpLayout->ReleaseEventsFromPlugin( this );
707
708 mBarDragStarted = false;
709
710 if ( mBarWasFloating && mpDraggedBar->mState != wxCBAR_FLOATING )
711 {
712 // save bar's floating position before it was docked
713
714 mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ] = mFloatedBarBounds;
715 }
716 }
717 else
718 event.Skip(); // pass event to the next plugin
719 }
720
721 void cbBarDragPlugin::OnLDblClick( cbLeftDClickEvent& event )
722 {
723 int avoidCompilerWarning = 1;
724 if ( avoidCompilerWarning )
725 {
726 cbBarInfo* pHittedBar;
727 cbRowInfo* pRow;
728
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 );
735
736 mpLayout->RepositionFloatedBar( pHittedBar );
737
738 return; // event is "eaten" by this plugin
739 }
740
741 mBarDragStarted = false;
742
743 event.Skip();
744 }
745
746 //wxMessageBox("Hi, dblclick arrived!");
747 }
748
749 void cbBarDragPlugin::OnStartBarDragging( cbStartBarDraggingEvent& event )
750 {
751 mpDraggedBar = event.mpBar;
752 mpSrcPane = event.mpPane;
753
754 mpLayout->CaptureEventsForPane( event.mpPane );
755 mpLayout->CaptureEventsForPlugin( this );
756
757 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
758
759 mBarDragStarted = true;
760
761 wxRect inParent = mpDraggedBar->mBounds;
762
763 mBarWasFloating = mpDraggedBar->mState == wxCBAR_FLOATING;
764
765 if ( mBarWasFloating )
766 {
767 inParent = mpDraggedBar->mDimInfo.mBounds[ wxCBAR_FLOATING ];
768 mFloatedBarBounds = inParent;
769 }
770 else
771 event.mpPane->PaneToFrame( &inParent );
772
773 mHintRect.x = POS_UNDEFINED;
774
775 mHintRect.width = inParent.width;
776 mHintRect.height = inParent.height;
777
778 mMouseInRectX = event.mPos.x - inParent.x;
779 mMouseInRectY = event.mPos.y - inParent.y;
780
781 mpSrcPane = event.mpPane;
782
783 if ( mpDraggedBar->mState == wxCBAR_FLOATING )
784
785 mpCurPane = NULL;
786 else
787 mpCurPane = event.mpPane;
788
789 mPrevHintRect.x = POS_UNDEFINED;
790
791 mCanStick = false; // we're not stuck into any pane now -
792 // there's nowhere to "stick-twice"
793
794 mBarWidthInSrcPane = mpDraggedBar->mDimInfo.mSizes[ mpDraggedBar->mState ].x;
795
796 if ( mpSrcPane->mProps.mRealTimeUpdatesOn == false &&
797 mpSrcPane->mProps.mExactDockPredictionOn )
798 mpLayout->GetUpdatesManager().OnStartChanges(); // capture initial state of layout
799
800 // simulate the first mouse movement
801
802 int x = event.mPos.x, y = event.mPos.y;
803 mpSrcPane->FrameToPane( &x, &y );
804
805 wxPoint pt(x,y);
806 cbMotionEvent motionEvt( pt, event.mpPane );
807 this->OnMouseMove( motionEvt );
808
809 return; // event is "eaten" by this plugin
810 }
811
812 /*** on-screen hint-tracking related methods ***/
813
814 void cbBarDragPlugin::OnDrawHintRect( cbDrawHintRectEvent& event )
815 {
816 if ( !mpScrDc ) StartTracking();
817
818 DoDrawHintRect( event.mRect, event.mIsInClient );
819
820 if ( event.mLastTime )
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