1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        rowdragpl.cpp
3 // Purpose:     cbRowDragPlugin implementation.
4 // Author:      Aleksandras Gluchovas
5 // Modified by:
6 // Created:     06/10/98
7 // RCS-ID:      $Id: rowdragpl.cpp 38927 2006-04-26 16:27:20Z PC $
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/rowdragpl.h"
24 
25 #define MINIMAL_ROW_DRAG_OFS  5
26 
27 // parameters for row-hints of NC-look
28 
29 #define TRIANGLE_OFFSET       2
30 #define TRIANGLE_TO_PAT_GAP   2
31 #define PAT_OFFSET            2
32 #define COLLAPSED_ICON_WIDTH  45
33 #define COLLAPSED_ICON_HEIGHT 9
34 #define ROW_DRAG_HINT_WIDTH   10
35 #define ICON_TRIAN_WIDTH      6
36 #define ICON_TRIAN_HEIGHT     3
37 
38 /***** Implementation for class cbHiddenBarInfo *****/
39 
IMPLEMENT_DYNAMIC_CLASS(cbHiddenBarInfo,wxObject)40 IMPLEMENT_DYNAMIC_CLASS( cbHiddenBarInfo, wxObject )
41 
42 /***** Implementation for class cbRowDragPlugin *****/
43 
44 IMPLEMENT_DYNAMIC_CLASS( cbRowDragPlugin, cbPluginBase )
45 
46 BEGIN_EVENT_TABLE( cbRowDragPlugin, cbPluginBase )
47 
48     EVT_PL_LEFT_DOWN          ( cbRowDragPlugin::OnLButtonDown        )
49     EVT_PL_LEFT_UP              ( cbRowDragPlugin::OnLButtonUp          )
50     EVT_PL_MOTION              ( cbRowDragPlugin::OnMouseMove          )
51 
52     EVT_PL_DRAW_PANE_DECOR    ( cbRowDragPlugin::OnDrawPaneBackground )
53 
54 END_EVENT_TABLE()
55 
56 // FIXME:: how to eliminated these cut and pasted constructors?
57 
58 cbRowDragPlugin::cbRowDragPlugin(void)
59 
60     : mHightColor          ( 192, 192, 255 ),
61       mLowColor            ( 192, 192, 192 ),
62       mTrianInnerColor     ( 0,0,255 ),
63       mTrianInnerPen       ( mTrianInnerColor, 1, wxSOLID ),
64 
65       mDragStarted         ( false ),
66       mDecisionMode        ( false ),
67       mCurDragOfs          ( 0 ),
68       mCaptureIsOn         ( false ),
69       mSvTopMargin         ( -1 ),
70       mSvBottomMargin      ( -1 ),
71       mSvLeftMargin        ( -1 ),
72       mSvRightMargin       ( -1 ),
73 
74       mpPaneImage          ( NULL ),
75       mpRowImage           ( NULL ),
76       mpCombinedImage        ( NULL ),
77 
78       mpRowInFocus         ( NULL ),
79       mCollapsedIconInFocus( -1 ),
80 
81       mpPane               ( NULL )
82 {
83 }
84 
cbRowDragPlugin(wxFrameLayout * pLayout,int paneMask)85 cbRowDragPlugin::cbRowDragPlugin( wxFrameLayout* pLayout, int paneMask )
86 
87     : cbPluginBase( pLayout, paneMask ),
88 
89          mHightColor          ( 192, 192, 255 ),
90       mLowColor            ( 192, 192, 192 ),
91       mTrianInnerColor     ( 0,0,255 ),
92       mTrianInnerPen       ( mTrianInnerColor, 1, wxSOLID ),
93 
94       mDragStarted         ( false ),
95       mDecisionMode        ( false ),
96       mCurDragOfs          ( 0 ),
97       mCaptureIsOn         ( false ),
98       mSvTopMargin         ( -1 ),
99       mSvBottomMargin      ( -1 ),
100       mSvLeftMargin        ( -1 ),
101       mSvRightMargin       ( -1 ),
102 
103       mpPaneImage          ( NULL ),
104       mpRowImage           ( NULL ),
105       mpCombinedImage        ( NULL ),
106 
107       mpRowInFocus         ( NULL ),
108       mCollapsedIconInFocus( -1 ),
109 
110       mpPane               ( NULL )
111 {
112 }
113 
~cbRowDragPlugin()114 cbRowDragPlugin::~cbRowDragPlugin()
115 {
116 }
117 
118 // handlers for plugin events
OnMouseMove(cbMotionEvent & event)119 void cbRowDragPlugin::OnMouseMove( cbMotionEvent& event )
120 {
121     // short-cuts
122     wxPoint pos = event.mPos;
123     mpPane      = event.mpPane;
124 
125     mpPane->PaneToFrame( &pos.x, &pos.y );
126 
127     if ( !mDragStarted )
128     {
129         if ( mDecisionMode && mpRowInFocus )
130         {
131             int ofs;
132 
133             if ( mpPane->IsHorizontal() )
134 
135                 ofs = pos.y - mDragOrigin.y;
136             else
137                 ofs = pos.x - mDragOrigin.x;
138 
139             // check if the item was dragged sufficeintly
140             // far, enough to consider that user really intends
141             // to drag it
142 
143             if ( ofs >= MINIMAL_ROW_DRAG_OFS ||
144                  ofs <= -MINIMAL_ROW_DRAG_OFS )
145             {
146                 // DBG::
147                 //.wxPoint pos = event.mPos;
148                 //wxPoint drg = mDragOrigin;
149                 //int dif = event.mPos.x - mDragOrigin.x;
150 
151                 mDragStarted  = true;
152                 mDecisionMode = false;
153                 mDragOrigin   = pos;
154 
155                 PrepareForRowDrag();
156                 return;
157             }
158 
159             // this plugin "eats" all mouse input while item is dragged,
160             return;
161         }
162 
163         cbRowInfo* pRow = GetFirstRow();
164 
165         bool focusFound = false;
166 
167         while( pRow )
168         {
169             if ( HitTestRowDragHint( pRow, pos ) )
170             {
171                 CheckPrevItemInFocus( pRow, -1 );
172                 SetMouseCapture( true );
173 
174                 focusFound = true;
175 
176                 mpRowInFocus          = pRow;
177                 mCollapsedIconInFocus = -1;
178                 break;
179             }
180 
181             pRow = pRow->mpNext;
182         }
183 
184         if ( !focusFound )
185         {
186             int hrCnt = GetHRowsCountForPane( event.mpPane );
187 
188             for( int i = 0; i != hrCnt; ++i )
189             {
190                 if ( HitTestCollapsedRowIcon( i, pos ) )
191                 {
192                     CheckPrevItemInFocus( NULL, i );
193                     SetMouseCapture( true );
194 
195                     focusFound = true;
196 
197                     mCollapsedIconInFocus = i;
198                     mpRowInFocus          = NULL;
199                     break;
200                 }
201             }
202         }
203 
204         if ( !focusFound && ItemIsInFocus() )
205         {
206             // kill focus from item previously been in focus
207             UnhighlightItemInFocus();
208 
209             mpRowInFocus          = NULL;
210             mCollapsedIconInFocus = -1;
211             SetMouseCapture( false );
212         }
213 
214         if ( !ItemIsInFocus() )
215 
216                 // delegate it to other plugins
217                 event.Skip();
218     }
219     else
220     {
221         // otherwise mouse pointer moves, when dragging is started
222 
223         if ( mpPane->IsHorizontal() )
224         {
225             // row is dragged up or down;
226             ShowDraggedRow( pos.y - mDragOrigin.y );
227         }
228         else
229         {
230             // row is dragged left or right
231             ShowDraggedRow( pos.x - mDragOrigin.x );
232         }
233 
234         // this plugin "eats" all mouse input while item is dragged,
235     }
236 }
237 
OnLButtonDown(cbLeftDownEvent & event)238 void cbRowDragPlugin::OnLButtonDown( cbLeftDownEvent& event )
239 {
240     mpPane = event.mpPane;
241 
242     // DBG::
243     wxASSERT( !mDragStarted && !mDecisionMode );
244 
245     if ( ItemIsInFocus() )
246     {
247         mDecisionMode = true;
248 
249         wxPoint pos = event.mPos;
250         mpPane->PaneToFrame( &pos.x, &pos.y );
251 
252         mDragOrigin = pos;
253 
254         SetMouseCapture( true );
255     }
256     else
257         // propagate event to other plugins
258         event.Skip();
259 }
260 
OnLButtonUp(cbLeftUpEvent & event)261 void cbRowDragPlugin::OnLButtonUp  ( cbLeftUpEvent& event )
262 {
263     if ( !mDragStarted && !mDecisionMode )
264     {
265         event.Skip();
266         return;
267     }
268 
269     mpPane = event.mpPane;
270 
271     if ( mDecisionMode )
272     {
273         cbDockPane* pPane = mpPane;
274 
275         SetMouseCapture( false );
276 
277         mDecisionMode = false;
278         mDragStarted  = false;
279 
280         wxPoint frmPos = event.mPos;
281         pPane->PaneToFrame( &frmPos.x, &frmPos.y );
282 
283         if ( mpRowInFocus )
284         {
285             CollapseRow( mpRowInFocus );
286             mpRowInFocus = 0;
287         }
288         else
289         {
290             ExpandRow( mCollapsedIconInFocus );
291             mCollapsedIconInFocus = -1;
292         }
293 
294         mpRowInFocus  = NULL;
295         mpPane = pPane;
296 
297         pPane->FrameToPane( &frmPos.x, &frmPos.y );
298 
299         // give it another try after relayouting bars
300 
301         cbMotionEvent moveEvt( frmPos, pPane );
302         this->OnMouseMove( moveEvt );
303 
304         // this plugin has "eaten" the mouse-up event
305 
306         return;
307     }
308     else
309     {
310         // otherwise, the dragged row was dropped, determine
311         // where to insert it
312 
313         // restore initial pane appearence
314         ShowPaneImage();
315         FinishOnScreenDraw();
316 
317         cbRowInfo* pRow = GetFirstRow();
318 
319         mpLayout->GetUpdatesManager().OnStartChanges();
320 
321         pRow->mUMgrData.SetDirty(true);
322 
323         cbBarInfo* pBar = mpRowInFocus->mBars[0];
324 
325         while ( pBar )
326         {
327             pBar->mUMgrData.SetDirty(true);
328 
329             if ( pBar->mpBarWnd )
330             {
331                 // do complete refresh
332                 pBar->mpBarWnd->Show(false);
333                 pBar->mpBarWnd->Show(true);
334             }
335 
336             pBar = pBar->mpNext;
337         }
338 
339         while( pRow )
340         {
341             if ( mCurDragOfs < pRow->mRowY )
342             {
343                 InsertDraggedRowBefore( pRow );
344                 break;
345             }
346 
347             pRow = pRow->mpNext;
348         }
349 
350         if ( pRow == NULL ) InsertDraggedRowBefore( NULL );
351 
352         mpRowInFocus = NULL;
353 
354         mpLayout->RecalcLayout(false);
355 
356         // finish change "transaction"
357         mpLayout->GetUpdatesManager().OnFinishChanges();
358         mpLayout->GetUpdatesManager().UpdateNow();
359 
360         // finish drag action
361         SetMouseCapture( false );
362         mDragStarted = false;
363     }
364 }
365 
OnDrawPaneBackground(cbDrawPaneDecorEvent & event)366 void cbRowDragPlugin::OnDrawPaneBackground ( cbDrawPaneDecorEvent& event )
367 {
368     mpPane = event.mpPane;
369 
370     // FIXME:: this may harm operation of other plugins
371 
372     if ( GetNextHandler() && mpPane->GetRowList().GetCount() )
373     {
374         // first, let other plugins add their decorations now
375 
376         GetNextHandler()->ProcessEvent( event );
377         event.Skip(false);
378     }
379 
380     wxClientDC dc( &mpLayout->GetParentFrame() );
381 
382     dc.SetClippingRegion( mpPane->mBoundsInParent.x,
383                           mpPane->mBoundsInParent.y,
384                           mpPane->mBoundsInParent.width,
385                           mpPane->mBoundsInParent.height );
386 
387     int cnt = GetHRowsCountForPane( event.mpPane );
388 
389     if ( cnt > 0 )
390 
391         DrawCollapsedRowsBorder( dc );
392 
393     if ( mpPane->GetRowList().GetCount() )
394 
395         DrawRowsDragHintsBorder( dc );
396 
397     cbRowInfo* pRow = GetFirstRow();
398 
399     while( pRow )
400     {
401         DrawRowDragHint( pRow, dc, false );
402         pRow = pRow->mpNext;
403     }
404 
405     for( int i = 0; i != cnt; ++i )
406 
407         DrawCollapsedRowIcon(i, dc, false );
408 }
409 
GetHRowsCountForPane(cbDockPane * pPane)410 int cbRowDragPlugin::GetHRowsCountForPane( cbDockPane* pPane )
411 {
412     wxNode* pNode = mHiddenBars.GetFirst();
413 
414     int maxIconNo = -1;
415 
416     while( pNode )
417     {
418         cbHiddenBarInfo* pHBInfo = (cbHiddenBarInfo*)pNode->GetData();
419 
420         if ( pHBInfo->mAlignment == pPane->mAlignment )
421 
422             maxIconNo = wxMax( maxIconNo, pHBInfo->mIconNo );
423 
424         pNode = pNode->GetNext();
425     }
426 
427     return ( maxIconNo + 1 );
428 }
429 
GetCollapsedRowIconHeight()430 int cbRowDragPlugin::GetCollapsedRowIconHeight()
431 {
432     return COLLAPSED_ICON_HEIGHT;
433 }
434 
GetRowDragHintWidth()435 int cbRowDragPlugin::GetRowDragHintWidth()
436 {
437     return ROW_DRAG_HINT_WIDTH;
438 }
439 
SetPaneMargins()440 void cbRowDragPlugin::SetPaneMargins()
441 {
442     int hiddenRowsCnt = GetHRowsCountForPane( mpPane );
443 
444     if ( mSvTopMargin == -1 )
445     {
446         mSvTopMargin    = mpPane->mTopMargin;
447         mSvBottomMargin    = mpPane->mBottomMargin;
448         mSvLeftMargin   = mpPane->mLeftMargin;
449         mSvRightMargin  = mpPane->mRightMargin;
450     }
451 
452     if ( mpPane->IsHorizontal() )
453     {
454         mpPane->mTopMargin    = mSvTopMargin;
455         mpPane->mBottomMargin = ( hiddenRowsCnt == 0 )
456                                 ?  mSvBottomMargin
457                                 :  mSvBottomMargin + GetCollapsedRowIconHeight();
458 
459         mpPane->mLeftMargin   = mSvLeftMargin + GetRowDragHintWidth();
460         mpPane->mRightMargin  = mSvRightMargin;
461     }
462     else
463     {
464         mpPane->mTopMargin    = mSvTopMargin;
465         mpPane->mBottomMargin = mSvBottomMargin + GetRowDragHintWidth();
466 
467         mpPane->mLeftMargin   = mSvLeftMargin;
468         mpPane->mRightMargin  = ( hiddenRowsCnt == 0 ) ?
469                                 mSvRightMargin : mSvRightMargin + GetCollapsedRowIconHeight();
470     }
471 }
472 
OnInitPlugin()473 void cbRowDragPlugin::OnInitPlugin()
474 {
475     cbDockPane** panes = mpLayout->GetPanesArray();
476 
477     for( int i = 0; i != MAX_PANES; ++i )
478 
479         if ( panes[i]->MatchesMask( mPaneMask ) )
480         {
481             mpPane = panes[i];
482 
483             SetPaneMargins();
484         }
485 }
486 
487 /*** helpers for drag&drop ***/
488 
SetMouseCapture(bool captureOn)489 void cbRowDragPlugin::SetMouseCapture( bool captureOn )
490 {
491     if ( mCaptureIsOn == captureOn ) return;
492 
493     if ( captureOn )
494     {
495         mpLayout->CaptureEventsForPane( mpPane );
496         mpLayout->CaptureEventsForPlugin( this );
497     }
498     else
499     {
500         mpLayout->ReleaseEventsFromPane( mpPane );
501         mpLayout->ReleaseEventsFromPlugin( this );
502     }
503 
504     mCaptureIsOn = captureOn;
505 }
506 
UnhighlightItemInFocus()507 void cbRowDragPlugin::UnhighlightItemInFocus()
508 {
509     wxClientDC dc( &mpLayout->GetParentFrame() );
510 
511     if ( mpRowInFocus )
512 
513         DrawRowDragHint( mpRowInFocus, dc, false );
514     else
515     if ( mCollapsedIconInFocus != - 1 )
516 
517         DrawCollapsedRowIcon( mCollapsedIconInFocus, dc, false );
518 }
519 
ShowDraggedRow(int offset)520 void cbRowDragPlugin::ShowDraggedRow( int offset )
521 {
522     // create combined image of pane and dragged
523     // row on it, in the mpCombinedImage bitmap
524 
525     if ( mpPane->IsHorizontal() )
526     {
527         if ( mInitialRowOfs + offset + mRowImgDim.y > mCombRect.y + mCombRect.height )
528 
529             offset = mCombRect.y + mCombRect.height - mRowImgDim.y - mInitialRowOfs;
530 
531         if ( mInitialRowOfs + offset < mCombRect.y )
532 
533             offset = mCombRect.y - mInitialRowOfs;
534 
535         int x, y = mInitialRowOfs + offset;
536         mpPane->FrameToPane( &x, &y );
537         mCurDragOfs = y;
538     }
539     else
540     {
541         if ( mInitialRowOfs + offset + mRowImgDim.x > mCombRect.x + mCombRect.width )
542 
543             offset = mCombRect.x + mCombRect.width - mRowImgDim.x - mInitialRowOfs;
544 
545         if ( mInitialRowOfs + offset < mCombRect.x )
546 
547             offset = mCombRect.x - mInitialRowOfs;
548 
549         int x = mInitialRowOfs + offset, y;
550         mpPane->FrameToPane( &x, &y );
551         mCurDragOfs = x;
552     }
553 
554     wxMemoryDC rowImgDc;
555     rowImgDc.SelectObject ( *mpRowImage );
556 
557     wxMemoryDC paneImgDc;
558     paneImgDc.SelectObject( *mpPaneImage );
559 
560     wxMemoryDC combImgDc;
561     combImgDc.SelectObject( *mpCombinedImage );
562 
563     combImgDc.Blit( 0,0, mCombRect.width, mCombRect.height,
564                     &paneImgDc, 0,0, wxCOPY );
565 
566     if ( mpPane->IsHorizontal() )
567     {
568         combImgDc.Blit( 0, mInitialRowOfs + offset - mCombRect.y,
569                         mCombRect.width, mRowImgDim.y,
570                         &rowImgDc, 0,0, wxCOPY );
571     }
572     else
573     {
574         combImgDc.Blit( mInitialRowOfs + offset - mCombRect.x,
575                         0,
576                         mRowImgDim.x, mCombRect.height,
577                         &rowImgDc, 0,0, wxCOPY );
578     }
579 
580     int scrX = mCombRect.x,
581         scrY = mCombRect.y;
582 
583     mpLayout->GetParentFrame().ClientToScreen( &scrX, &scrY );
584 
585     mpScrDc->Blit( scrX, scrY, mCombRect.width, mCombRect.height,
586                    &combImgDc, 0,0, wxCOPY );
587 
588     rowImgDc .SelectObject( wxNullBitmap );
589     paneImgDc.SelectObject( wxNullBitmap );
590     combImgDc.SelectObject( wxNullBitmap );
591 }
592 
CaptureDCArea(wxDC & dc,wxRect & area)593 wxBitmap* cbRowDragPlugin::CaptureDCArea( wxDC& dc, wxRect& area )
594 {
595     wxBitmap* pBmp = new wxBitmap( int(area.width), int(area.height) );
596 
597     wxMemoryDC mdc;
598     mdc.SelectObject( *pBmp );
599 
600     mdc.Blit( 0,0, area.width, area.height, &dc, area.x, area.y, wxCOPY );
601     mdc.SelectObject( wxNullBitmap );
602 
603     return pBmp;
604 }
605 
PrepareForRowDrag()606 void cbRowDragPlugin::PrepareForRowDrag()
607 {
608     wxRect rowBounds = mpRowInFocus->mBoundsInParent;
609 
610     if ( mpPane->IsHorizontal() )
611     {
612         mCombRect         = mpPane->mBoundsInParent;
613 
614         mCombRect.x += mpPane->mLeftMargin - ROW_DRAG_HINT_WIDTH - 1;
615         mCombRect.y += mpPane->mTopMargin;
616 
617         mCombRect.width  -= mpPane->mLeftMargin + mpPane->mRightMargin - ROW_DRAG_HINT_WIDTH - 1 - 1;
618         mCombRect.height -= mpPane->mTopMargin  + mpPane->mBottomMargin;
619 
620         mCombRect.height += 2*rowBounds.height;
621         mCombRect.y      -= rowBounds.height;
622         mInitialRowOfs     = rowBounds.y;
623 
624         rowBounds.y      -= 1;
625         rowBounds.height += 2;
626         rowBounds.x      = mCombRect.x;
627         rowBounds.width  = mCombRect.width;
628 
629         mRowImgDim.y     = rowBounds.height;
630     }
631     else
632     {
633         mCombRect = mpPane->mBoundsInParent;
634 
635         mCombRect.y += mpPane->mTopMargin  - 1;
636         mCombRect.x += mpPane->mLeftMargin - 1;
637             ;
638         mCombRect.height -= mpPane->mTopMargin  + mpPane->mBottomMargin - ROW_DRAG_HINT_WIDTH - 1 - 1;
639         mCombRect.width  -= mpPane->mLeftMargin + mpPane->mRightMargin;
640 
641         mCombRect.width += 2*rowBounds.width;
642         mCombRect.x     -= rowBounds.width;
643         mInitialRowOfs    = rowBounds.x;
644 
645         rowBounds.x      -= 1;
646         rowBounds.width  += 2;
647         rowBounds.y      = mCombRect.y;
648         rowBounds.height = mCombRect.height;
649 
650         mRowImgDim.x     = rowBounds.width;
651     }
652     // output cobination results onto frame's client area
653     wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());
654     mpScrDc = new wxScreenDC();
655 
656     int x = mCombRect.x, y = mCombRect.y;
657     mpLayout->GetParentFrame().ClientToScreen( &x, &y );
658 
659     wxRect scrRect = mCombRect;
660     scrRect.x = x;
661     scrRect.y = y;
662 
663     mpPaneImage = CaptureDCArea( *mpScrDc, scrRect );
664 
665     wxMemoryDC mdc;
666     mdc.SelectObject( *mpPaneImage );
667     mdc.SetDeviceOrigin( -mCombRect.x, -mCombRect.y );
668 
669     DrawRectShade( rowBounds, mdc, -1, mpLayout->mGrayPen,  mpLayout->mDarkPen  );
670     DrawRectShade( rowBounds, mdc, 0, mpLayout->mLightPen, mpLayout->mBlackPen );
671 
672     mpRowImage = CaptureDCArea( mdc, rowBounds );
673 
674     // draw dark empty-row placeholder
675     DrawEmptyRow( mdc, rowBounds );
676 
677     //DrawRectShade( rowBounds, mdc, 0, mpLayout->mGrayPen,  mpLayout->mDarkPen  );
678     DrawRectShade( rowBounds, mdc, -1, mpLayout->mGrayPen, mpLayout->mGrayPen );
679 
680     mdc.SelectObject( wxNullBitmap );
681 
682     mpCombinedImage = new wxBitmap( int(mCombRect.width), int(mCombRect.height) );
683 
684     // show it for the first time
685     ShowDraggedRow( 0 );
686 }
687 
DrawEmptyRow(wxDC & dc,wxRect & rowBounds)688 void cbRowDragPlugin::DrawEmptyRow( wxDC& dc, wxRect& rowBounds )
689 {
690     wxBrush bkBrush( mpLayout->mDarkPen.GetColour(), wxSOLID );
691 
692     // paint the "dark" empty-row placeholder
693 
694     dc.SetBrush( bkBrush );
695     dc.SetPen  ( mpLayout->mNullPen );
696 
697     dc.DrawRectangle( rowBounds.x, rowBounds.y,
698                       rowBounds.width+1, rowBounds.height+1 );
699 
700     dc.SetBrush( wxNullBrush );
701 }
702 
ShowPaneImage()703 void cbRowDragPlugin::ShowPaneImage()
704 {
705     int scrX = 0, scrY = 0;
706 
707     mpLayout->GetParentFrame().ClientToScreen( &scrX, &scrY );
708 
709     wxMemoryDC mdc;
710     mdc.SelectObject( *mpPaneImage );
711 
712     mpScrDc->Blit( mCombRect.x + scrX, mCombRect.y + scrY,
713                    mCombRect.width, mCombRect.height,
714                    &mdc, 0,0, wxCOPY );
715 
716     mdc.SelectObject( wxNullBitmap );
717 }
718 
FinishOnScreenDraw()719 void cbRowDragPlugin::FinishOnScreenDraw()
720 {
721     wxScreenDC::EndDrawingOnTop();
722 
723     delete mpScrDc;
724     delete mpCombinedImage;
725     delete mpPaneImage;
726     delete mpRowImage;
727 
728     mpScrDc = NULL;
729 
730     mpCombinedImage = mpPaneImage = mpRowImage = NULL;
731 }
732 
CollapseRow(cbRowInfo * pRow)733 void cbRowDragPlugin::CollapseRow( cbRowInfo* pRow )
734 {
735     int iconCnt = GetHRowsCountForPane( mpPane );
736 
737     mpLayout->GetUpdatesManager().OnStartChanges();
738 
739     cbBarInfo* pBar = pRow->mBars[0];
740 
741     int rowNo = 0;
742 
743     cbRowInfo* pCur = pRow;
744     while( pCur->mpPrev ) { ++rowNo; pCur = pCur->mpPrev; }
745 
746     while( pBar )
747     {
748         cbHiddenBarInfo* pHBInfo = new cbHiddenBarInfo();
749 
750         pHBInfo->mpBar      = pBar;
751         pHBInfo->mRowNo     = rowNo;
752         pHBInfo->mIconNo    = iconCnt;
753         pHBInfo->mAlignment    = mpPane->mAlignment;
754 
755         mHiddenBars.Append( (wxObject*) pHBInfo );
756 
757         // hide it
758         if ( pBar->mpBarWnd )
759 
760             pBar->mpBarWnd->Show( false );
761 
762         pBar->mState = wxCBAR_HIDDEN;
763 
764         cbBarInfo* pNext = pBar->mpNext;
765 
766         pBar->mpRow  = NULL;
767         pBar->mpNext = NULL;
768         pBar->mpPrev = NULL;
769 
770         pBar = pNext;
771     }
772 
773     mpPane->GetRowList().Remove( pRow );
774     mpPane->InitLinksForRows();
775 
776     delete pRow;
777 
778     SetPaneMargins();
779 
780     mpLayout->RecalcLayout(false);
781 
782     mpRowInFocus = NULL;
783 
784     mpLayout->GetUpdatesManager().OnFinishChanges();
785     mpLayout->GetUpdatesManager().UpdateNow();
786 }
787 
ExpandRow(int collapsedIconIdx)788 void cbRowDragPlugin::ExpandRow( int collapsedIconIdx )
789 {
790     mpLayout->GetUpdatesManager().OnStartChanges();
791 
792     cbRowInfo* pNewRow = new cbRowInfo();
793 
794     wxNode* pNode = mHiddenBars.GetFirst();
795 
796     int rowNo = 0;
797 
798     // move bars from internal list to the newly expanded row
799 
800     while( pNode )
801     {
802         cbHiddenBarInfo* pHBInfo = (cbHiddenBarInfo*)pNode->GetData();
803 
804         if ( pHBInfo->mAlignment     == mpPane->mAlignment &&
805              pHBInfo->mIconNo        == collapsedIconIdx   )
806         {
807             rowNo = pHBInfo->mRowNo;
808 
809             if ( pHBInfo->mpBar->mState == wxCBAR_HIDDEN )
810             {
811                 pNewRow->mBars.Add( pHBInfo->mpBar );
812 
813                 pHBInfo->mpBar->mState = ( mpPane->IsHorizontal() )
814                                          ? wxCBAR_DOCKED_HORIZONTALLY
815                                          : wxCBAR_DOCKED_VERTICALLY;
816             }
817 
818             // remove bar info from internal list
819 
820             wxNode* pNext = pNode->GetNext();
821 
822             delete pHBInfo;
823             mHiddenBars.DeleteNode( pNode );
824 
825             pNode = pNext;
826         }
827         else
828         {
829             // decrease incon numbers with higher indicies, since this
830             // row is now removed from the hidden-rows list
831 
832             if ( pHBInfo->mIconNo    > collapsedIconIdx &&
833                  pHBInfo->mAlignment == mpPane->mAlignment )
834 
835                 --pHBInfo->mIconNo;
836 
837             pNode = pNode->GetNext();
838         }
839     }
840 
841     mpPane->InitLinksForRow( pNewRow );
842 
843     // insert row into pane at it's original position
844 
845     if ( pNewRow->mBars.GetCount() )
846     {
847         cbRowInfo* beforeRowNode = mpPane->GetRow( rowNo );
848 
849         mpPane->InsertRow( pNewRow, beforeRowNode );
850     }
851     else
852         delete pNewRow;
853 
854     SetPaneMargins();
855 
856     mpLayout->RecalcLayout(false);
857 
858     mCollapsedIconInFocus = -1;
859 
860     mpLayout->GetUpdatesManager().OnFinishChanges();
861     mpLayout->GetUpdatesManager().UpdateNow();
862 
863 
864     /*
865     wxNode* pRowNode = mHiddenRows.Nth( collapsedIconIdx );
866 
867     mpLayout->GetUpdatesManager().OnStartChanges();
868 
869     // insert at the end of rows list
870     mpPane->InsertRow( pRowNode, NULL );
871 
872     int success = mHiddenRows.DeleteNode( pRowNode );
873     // DBG::
874     wxASSERT( success );
875 
876     SetPaneMargins();
877 
878     mpLayout->RecalcLayout(false);
879 
880     mCollapsedIconInFocus = -1;
881 
882     mpLayout->GetUpdatesManager().OnFinishChanges();
883     mpLayout->GetUpdatesManager().UpdateNow();
884     */
885 }
886 
InsertDraggedRowBefore(cbRowInfo * pBeforeRow)887 void cbRowDragPlugin::InsertDraggedRowBefore( cbRowInfo* pBeforeRow )
888 {
889     if ( mpRowInFocus != pBeforeRow &&
890          mpRowInFocus->mpNext != pBeforeRow
891        )
892     {
893         mpPane->GetRowList().Remove( mpRowInFocus );
894 
895         mpPane->InsertRow( mpRowInFocus, pBeforeRow );
896     }
897     else
898     {
899         // otherwise, nothing has happned (row positions do not change)
900 
901         //wxClientDC dc( &mpLayout->GetParentFrame() );
902 
903         //mpPane->PaintRow( mpRowInFocus, dc );
904         //DrawRowDragHint( mpRowInFocus, dc, false );
905     }
906 }
907 
ItemIsInFocus()908 bool cbRowDragPlugin::ItemIsInFocus()
909 {
910     return ( mpRowInFocus || mCollapsedIconInFocus != - 1 );
911 }
912 
CheckPrevItemInFocus(cbRowInfo * pRow,int iconIdx)913 void cbRowDragPlugin::CheckPrevItemInFocus( cbRowInfo* pRow, int iconIdx )
914 {
915     wxClientDC dc( &mpLayout->GetParentFrame() );
916 
917     if ( pRow != NULL && mpRowInFocus == pRow ) return;
918     if ( iconIdx != -1 && mCollapsedIconInFocus == iconIdx ) return;
919 
920     UnhighlightItemInFocus();
921 
922     if ( iconIdx != - 1 )
923 
924         DrawCollapsedRowIcon( iconIdx, dc, true );
925 
926     else
927     if ( pRow != NULL )
928 
929         DrawRowDragHint( pRow, dc, true );
930 }
931 
GetFirstRow()932 cbRowInfo* cbRowDragPlugin::GetFirstRow()
933 {
934     return ( mpPane->GetRowList().GetCount() )
935            ? mpPane->GetRowList()[0]
936            : NULL;
937 }
938 
939 /*** "hard-coded" metafile for NN-look ***/
940 
DrawTrianUp(wxRect & inRect,wxDC & dc)941 void cbRowDragPlugin::DrawTrianUp( wxRect& inRect, wxDC& dc )
942 {
943     int xOfs = (inRect.width - ICON_TRIAN_WIDTH)/2;
944 
945     wxBrush br( mTrianInnerColor, wxSOLID );
946 
947     dc.SetBrush( br );
948     dc.SetPen( mpLayout->mBlackPen );
949 
950     wxPoint points[3];
951     points[0].x = inRect.x + xOfs;
952     points[0].y = inRect.y + inRect.height - 1;
953     points[1].x = inRect.x + xOfs + ICON_TRIAN_WIDTH/2 + 1;
954     points[1].y = inRect.y + inRect.height - 2 - ICON_TRIAN_HEIGHT;
955     points[2].x = inRect.x + xOfs + ICON_TRIAN_WIDTH+1;
956     points[2].y = inRect.y + inRect.height - 1;
957 
958     dc.DrawPolygon( 3, points );
959 
960     // higlight upper-right edge of triangle
961     dc.SetPen( mpLayout->mLightPen );
962     dc.DrawLine( points[2].x, points[2].y,
963                  points[0].x, points[0].y );
964 
965     dc.SetBrush( wxNullBrush );
966 }
967 
DrawTrianDown(wxRect & inRect,wxDC & dc)968 void cbRowDragPlugin::DrawTrianDown( wxRect& inRect, wxDC& dc )
969 {
970     int xOfs = (inRect.width - ICON_TRIAN_WIDTH)/2;
971 
972     wxBrush br( mTrianInnerColor, wxSOLID );
973 
974     dc.SetBrush( br );
975     dc.SetPen( mpLayout->mBlackPen );
976 
977     wxPoint points[3];
978     points[0].x = inRect.x + xOfs;
979     points[0].y = inRect.y;
980     points[1].x = inRect.x + xOfs + ICON_TRIAN_WIDTH;
981     points[1].y = inRect.y;
982     points[2].x = inRect.x + xOfs + ICON_TRIAN_WIDTH/2;
983     points[2].y = inRect.y + ICON_TRIAN_HEIGHT;
984 
985     dc.DrawPolygon( 3, points );
986 
987     // higlight upper-right edge of triangle
988     dc.SetPen( mpLayout->mLightPen );
989     dc.DrawLine( points[2].x, points[2].y,
990                  points[1].x, points[1].y );
991 
992     dc.SetBrush( wxNullBrush );
993 }
994 
DrawTrianRight(wxRect & inRect,wxDC & dc)995 void cbRowDragPlugin::DrawTrianRight( wxRect& inRect, wxDC& dc )
996 {
997     int yOfs = (inRect.height - ICON_TRIAN_WIDTH)/2;
998 
999     wxBrush br( mTrianInnerColor, wxSOLID );
1000 
1001     dc.SetBrush( br );
1002     dc.SetPen( mpLayout->mBlackPen );
1003 
1004     wxPoint points[3];
1005     points[0].x = inRect.x;
1006     points[0].y = inRect.y + yOfs + ICON_TRIAN_WIDTH;
1007     points[1].x = inRect.x;
1008     points[1].y = inRect.y + yOfs;
1009     points[2].x = inRect.x + ICON_TRIAN_HEIGHT;
1010     points[2].y = inRect.y + yOfs + ICON_TRIAN_WIDTH/2;
1011 
1012     dc.DrawPolygon( 3, points );
1013 
1014     // higlight upper-right edge of triangle
1015     dc.SetPen( mpLayout->mLightPen );
1016     dc.DrawLine( points[0].x, points[0].y,
1017                  points[2].x, points[2].y );
1018 
1019     dc.SetBrush( wxNullBrush );
1020 }
1021 
Draw3DPattern(wxRect & inRect,wxDC & dc)1022 void cbRowDragPlugin::Draw3DPattern( wxRect& inRect, wxDC& dc )
1023 {
1024     for( int y = inRect.y; y < inRect.y + inRect.height; y+=3 )
1025 
1026         for( int x = inRect.x; x < inRect.x + inRect.width; x+=3 )
1027         {
1028             dc.SetPen( mpLayout->mLightPen );
1029             dc.DrawPoint( x,y );
1030             dc.SetPen( mpLayout->mBlackPen );
1031             dc.DrawPoint( x+1, y+1 );
1032         }
1033 }
1034 
DrawRombShades(wxPoint & p1,wxPoint & p2,wxPoint & p3,wxPoint & p4,wxDC & dc)1035 void cbRowDragPlugin::DrawRombShades( wxPoint& p1, wxPoint& p2,
1036                                       wxPoint& p3, wxPoint& p4,
1037                                       wxDC& dc )
1038 {
1039     dc.SetPen( mpLayout->mLightPen );
1040     dc.DrawLine( p1.x, p1.y, p2.x, p2.y );
1041     dc.DrawLine( p2.x, p2.y, p3.x, p3.y );
1042     dc.SetPen( mpLayout->mDarkPen );
1043     dc.DrawLine( p3.x, p3.y, p4.x, p4.y );
1044     dc.DrawLine( p4.x, p4.y, p1.x, p1.y );
1045 }
1046 
DrawOrtoRomb(wxRect & inRect,wxDC & dc,const wxBrush & bkBrush)1047 void cbRowDragPlugin::DrawOrtoRomb( wxRect& inRect, wxDC& dc, const wxBrush& bkBrush )
1048 {
1049     dc.SetBrush( bkBrush );
1050     dc.SetPen( mpLayout->mBlackPen );
1051 
1052     wxPoint points[4];
1053 
1054     if ( inRect.width > inRect.height )
1055     {
1056         // horizontal orienation
1057         points[0].x = inRect.x;
1058         points[0].y = inRect.y + inRect.height;
1059         points[1].x = inRect.x;
1060         points[1].y = inRect.y;
1061         points[2].x = inRect.x + inRect.width;
1062         points[2].y = inRect.y;
1063         points[3].x = inRect.x + inRect.width - COLLAPSED_ICON_HEIGHT;
1064         points[3].y = inRect.y + inRect.height;
1065 
1066         dc.DrawPolygon( 4, points );
1067 
1068         // squeeze romb's bounds to create an inner-shade shape
1069         ++points[0].x;
1070         --points[0].y;
1071         ++points[1].x;
1072         ++points[1].y;
1073         --points[2].x; --points[2].x;
1074         ++points[2].y;
1075         --points[3].y;
1076 
1077         DrawRombShades( points[0], points[1], points[2], points[3], dc );
1078     }
1079     else
1080     {
1081         // vertical orientation
1082         points[0].x = inRect.x + inRect.width;
1083         points[0].y = inRect.y + inRect.height;
1084         points[1].x = inRect.x;
1085         points[1].y = inRect.y + inRect.height;
1086         points[2].x = inRect.x;
1087         points[2].y = inRect.y;
1088         points[3].x = inRect.x + inRect.width;
1089         points[3].y = inRect.y + COLLAPSED_ICON_HEIGHT;
1090 
1091         dc.DrawPolygon( 4, points );
1092 
1093         // squeeze romb's bounds to create an inner-shade shape
1094         --points[0].y ;
1095         --points[0].x;
1096         ++points[1].x;
1097         --points[1].y;
1098         ++points[2].y; ++points[2].y;
1099         ++points[2].x;
1100         --points[3].x;
1101 
1102         DrawRombShades( points[1], points[2], points[3], points[0], dc );
1103     }
1104 
1105     dc.SetBrush( wxNullBrush );
1106 }
1107 
DrawRomb(wxRect & inRect,wxDC & dc,const wxBrush & bkBrush)1108 void cbRowDragPlugin::DrawRomb( wxRect& inRect, wxDC& dc, const wxBrush& bkBrush )
1109 {
1110     wxPoint points[4];
1111 
1112     dc.SetBrush( bkBrush );
1113     dc.SetPen( mpLayout->mBlackPen );
1114 
1115     if ( inRect.width > inRect.height )
1116     {
1117         // horizontal orientation
1118         points[0].x = inRect.x;
1119         points[0].y = inRect.y + inRect.height;
1120         points[1].x = inRect.x + COLLAPSED_ICON_HEIGHT;
1121         points[1].y = inRect.y;
1122         points[2].x = inRect.x + inRect.width;
1123         points[2].y = inRect.y;
1124         points[3].x = inRect.x + inRect.width - COLLAPSED_ICON_HEIGHT;
1125         points[3].y = inRect.y + inRect.height;
1126 
1127         dc.DrawPolygon( 4, points );
1128 
1129         // squeeze romb's bounds to create an inner-shade shape
1130         ++points[0].x ;++points[0].x ;
1131         --points[0].y;
1132         ++points[1].y;
1133         --points[2].x; --points[2].x;
1134         ++points[2].y;
1135         //--points[3].x ;
1136         --points[3].y;
1137 
1138         DrawRombShades( points[0], points[1], points[2], points[3], dc );
1139 
1140     }
1141     else
1142     {
1143         // vertical orientation
1144         points[0].x = inRect.x + inRect.width;
1145         points[0].y = inRect.y + inRect.height;
1146         points[1].x = inRect.x;
1147         points[1].y = inRect.y + inRect.height - COLLAPSED_ICON_HEIGHT;
1148         points[2].x = inRect.x;
1149         points[2].y = inRect.y;
1150         points[3].x = inRect.x + inRect.width;
1151         points[3].y = inRect.y + COLLAPSED_ICON_HEIGHT;
1152 
1153         dc.DrawPolygon( 4, points );
1154 
1155         // squeeze romb's bounds to create an inner-shade shape
1156         --points[0].y ;--points[0].y ;
1157         --points[0].x;
1158         ++points[1].x;
1159         ++points[2].y; ++points[2].y;
1160         ++points[2].x;
1161         --points[3].x;
1162 
1163         DrawRombShades( points[1], points[2], points[3], points[0], dc );
1164     }
1165 
1166     dc.SetBrush( wxNullBrush );
1167 }
1168 
DrawRectShade(wxRect & inRect,wxDC & dc,int level,const wxPen & upperPen,const wxPen & lowerPen)1169 void cbRowDragPlugin::DrawRectShade( wxRect& inRect, wxDC& dc,
1170                                      int level, const wxPen& upperPen, const wxPen& lowerPen )
1171 {
1172     // upper shade
1173     dc.SetPen( upperPen );
1174     dc.DrawLine( inRect.x - level,
1175                  inRect.y - level,
1176                  inRect.x + inRect.width - 1 + level,
1177                  inRect.y - level);
1178     dc.DrawLine( inRect.x - level, inRect.y - level,
1179                  inRect.x - level, inRect.y + inRect.height - 1 + level );
1180 
1181     // lower shade
1182     dc.SetPen( lowerPen );
1183     dc.DrawLine( inRect.x - level,
1184                  inRect.y + inRect.height - 1 + level,
1185                  inRect.x + inRect.width  + level,
1186                  inRect.y + inRect.height - 1 + level);
1187     dc.DrawLine( inRect.x + inRect.width - 1 + level,
1188                  inRect.y - level,
1189                  inRect.x + inRect.width - 1 + level,
1190                  inRect.y + inRect.height + level);
1191 
1192     dc.SetBrush( wxNullBrush );
1193 }
1194 
Draw3DRect(wxRect & inRect,wxDC & dc,const wxBrush & bkBrush)1195 void cbRowDragPlugin::Draw3DRect( wxRect& inRect, wxDC& dc, const wxBrush& bkBrush )
1196 {
1197     dc.SetPen( mpLayout->mNullPen );
1198     dc.SetBrush( bkBrush );
1199 
1200     dc.DrawRectangle( inRect.x, inRect.y,
1201                       inRect.width, inRect.height );
1202 
1203     DrawRectShade( inRect, dc, 0, mpLayout->mLightPen, mpLayout->mDarkPen );
1204 }
1205 
GetCollapsedIconsPos()1206 int  cbRowDragPlugin::GetCollapsedIconsPos()
1207 {
1208     RowArrayT& rows = mpPane->GetRowList();
1209 
1210     if ( rows.GetCount() == 0 )
1211     {
1212         if ( mpPane->IsHorizontal() )
1213 
1214             return mpPane->mBoundsInParent.y + mpPane->mTopMargin;
1215         else
1216             return mpPane->mBoundsInParent.x + mpPane->mLeftMargin;
1217     }
1218 
1219     wxRect& bounds = rows[ rows.GetCount() - 1 ]->mBoundsInParent;
1220 
1221     if ( mpPane->IsHorizontal() )
1222 
1223         return bounds.y + bounds.height + 1;
1224     else
1225         return bounds.x + bounds.width  + 1;
1226 
1227 }
1228 
GetRowHintRect(cbRowInfo * pRow,wxRect & rect)1229 void cbRowDragPlugin::GetRowHintRect( cbRowInfo* pRow, wxRect& rect )
1230 {
1231     wxRect& bounds = pRow->mBoundsInParent;
1232 
1233     if ( mpPane->IsHorizontal() )
1234     {
1235         rect.x = bounds.x - ROW_DRAG_HINT_WIDTH - 1;
1236         rect.y = bounds.y;
1237         rect.width = ROW_DRAG_HINT_WIDTH;
1238         rect.height = bounds.height;
1239     }
1240     else
1241     {
1242         rect.x = bounds.x;
1243         rect.y = bounds.y + bounds.height + 1;
1244         rect.width = bounds.width;
1245         rect.height = ROW_DRAG_HINT_WIDTH;
1246     }
1247 }
1248 
GetCollapsedInconRect(int iconIdx,wxRect & rect)1249 void cbRowDragPlugin::GetCollapsedInconRect( int iconIdx, wxRect& rect )
1250 {
1251     int upper = GetCollapsedIconsPos();
1252 
1253     int right = (iconIdx == 0 )
1254                 ? 0 : iconIdx * (COLLAPSED_ICON_WIDTH - COLLAPSED_ICON_HEIGHT);
1255 
1256     if ( mpPane->IsHorizontal() )
1257     {
1258         rect.x = mpPane->mBoundsInParent.x + mpPane->mLeftMargin - ROW_DRAG_HINT_WIDTH - 1
1259                  + right;
1260 
1261         rect.y = upper;
1262         rect.width  = COLLAPSED_ICON_WIDTH;
1263         rect.height = COLLAPSED_ICON_HEIGHT;
1264     }
1265     else
1266     {
1267          rect.x = upper;
1268          rect.y = mpPane->mBoundsInParent.y + mpPane->mBoundsInParent.height
1269                  - mpPane->mBottomMargin + ROW_DRAG_HINT_WIDTH + 1
1270                  - right - COLLAPSED_ICON_WIDTH;
1271 
1272         rect.height = COLLAPSED_ICON_WIDTH;
1273         rect.width  = COLLAPSED_ICON_HEIGHT;
1274     }
1275 }
1276 
1277 /*** overridables ***/
1278 
DrawCollapsedRowIcon(int index,wxDC & dc,bool isHighlighted)1279 void cbRowDragPlugin::DrawCollapsedRowIcon( int index, wxDC& dc, bool isHighlighted )
1280 {
1281     wxRect rect;
1282     GetCollapsedInconRect( index, rect );
1283 
1284     wxBrush  hiBrush ( mHightColor, wxSOLID );
1285     wxBrush  lowBrush( mLowColor,   wxSOLID );
1286     wxBrush& curBrush = ( isHighlighted ) ? hiBrush : lowBrush;
1287 
1288     if ( mpPane->IsHorizontal() )
1289     {
1290         if ( index == 0 )
1291 
1292             DrawOrtoRomb( rect, dc, curBrush );
1293         else
1294             DrawRomb( rect, dc, curBrush );
1295 
1296         int triOfs = (index == 0) ? TRIANGLE_OFFSET : TRIANGLE_OFFSET + COLLAPSED_ICON_HEIGHT;
1297 
1298         wxRect triRect;
1299         triRect.x = triOfs + rect.x;
1300 
1301         triRect.width = ICON_TRIAN_HEIGHT;
1302         triRect.y = rect.y;
1303         triRect.height = rect.height;
1304 
1305         DrawTrianRight( triRect, dc );
1306 
1307         wxRect patRect;
1308         patRect.x      = triOfs + ICON_TRIAN_HEIGHT + TRIANGLE_TO_PAT_GAP + rect.x;
1309         patRect.y      = rect.y + PAT_OFFSET;
1310         patRect.width  = rect.width - (patRect.x - rect.x) - COLLAPSED_ICON_HEIGHT - PAT_OFFSET;
1311         patRect.height = rect.height - PAT_OFFSET*2;
1312 
1313         Draw3DPattern( patRect, dc );
1314     }
1315     else
1316     {
1317         if ( index == 0 )
1318 
1319             DrawOrtoRomb( rect, dc, curBrush );
1320         else
1321             DrawRomb( rect, dc, curBrush );
1322 
1323         int triOfs = (index == 0)
1324                      ? TRIANGLE_OFFSET + ICON_TRIAN_HEIGHT
1325                      : TRIANGLE_OFFSET + COLLAPSED_ICON_HEIGHT + ICON_TRIAN_HEIGHT;
1326 
1327         wxRect triRect;
1328         triRect.y      = rect.y + rect.height - triOfs;
1329         triRect.x      = rect.x;
1330         triRect.width  = rect.width;
1331         triRect.height = ICON_TRIAN_HEIGHT;
1332 
1333         DrawTrianUp( triRect, dc );
1334 
1335         wxRect patRect;
1336         patRect.y      = rect.y + COLLAPSED_ICON_HEIGHT + PAT_OFFSET;
1337         patRect.x      = rect.x + PAT_OFFSET;
1338         patRect.width  = rect.width - 2*PAT_OFFSET ;
1339         patRect.height = rect.height - triOfs - 2*PAT_OFFSET - COLLAPSED_ICON_HEIGHT;
1340 
1341         Draw3DPattern( patRect, dc );
1342     }
1343 }
1344 
DrawRowDragHint(cbRowInfo * pRow,wxDC & dc,bool isHighlighted)1345 void cbRowDragPlugin::DrawRowDragHint( cbRowInfo* pRow , wxDC& dc, bool isHighlighted )
1346 {
1347     wxRect rect;
1348     GetRowHintRect( pRow, rect );
1349 
1350     wxBrush  hiBrush ( mHightColor, wxSOLID );
1351     wxBrush  lowBrush( mLowColor,   wxSOLID );
1352     wxBrush& curBrush = ( isHighlighted ) ? hiBrush : lowBrush;
1353 
1354     Draw3DRect( rect, dc, curBrush );
1355 
1356     if ( mpPane->IsHorizontal() )
1357     {
1358         wxRect triRect;
1359         triRect.y       = rect.y + TRIANGLE_OFFSET;
1360         triRect.x       = rect.x;
1361         triRect.width  = rect.width;
1362         triRect.height = ICON_TRIAN_HEIGHT;
1363 
1364         DrawTrianDown( triRect, dc );
1365 
1366         wxRect patRect;
1367         patRect.x      = rect.x + PAT_OFFSET;
1368         patRect.y      = rect.y + TRIANGLE_OFFSET + ICON_TRIAN_HEIGHT + TRIANGLE_TO_PAT_GAP;
1369         patRect.width  = rect.width - 2*PAT_OFFSET;
1370         patRect.height = rect.height - ( patRect.y - rect.y ) - PAT_OFFSET;
1371         Draw3DPattern( patRect, dc );
1372 
1373         dc.SetPen( mpLayout->mLightPen );
1374         dc.DrawLine( rect.x, rect.y + rect.height, rect.x + rect.width, rect.y + rect.height );
1375     }
1376     else
1377     {
1378         wxRect triRect;
1379         triRect.x       = rect.x + TRIANGLE_OFFSET;
1380         triRect.y       = rect.y;
1381         triRect.height = rect.height;
1382         triRect.width  = ICON_TRIAN_HEIGHT;
1383 
1384         DrawTrianRight( triRect, dc );
1385 
1386         wxRect patRect;
1387         patRect.y      = rect.y + PAT_OFFSET;
1388         patRect.x      = rect.x + TRIANGLE_OFFSET + ICON_TRIAN_HEIGHT + TRIANGLE_TO_PAT_GAP;
1389         patRect.height = rect.height - 2*PAT_OFFSET;
1390         patRect.width  = rect.width - ( patRect.x - rect.x ) - PAT_OFFSET;
1391         Draw3DPattern( patRect, dc );
1392 
1393         dc.SetPen( mpLayout->mLightPen );
1394         dc.DrawLine( rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + rect.height );
1395     }
1396 }
1397 
DrawRowsDragHintsBorder(wxDC & WXUNUSED (dc))1398 void cbRowDragPlugin::DrawRowsDragHintsBorder( wxDC& WXUNUSED(dc) )
1399 {
1400     // FIXME:: what was that?
1401 }
1402 
DrawCollapsedRowsBorder(wxDC & dc)1403 void cbRowDragPlugin::DrawCollapsedRowsBorder( wxDC& dc )
1404 {
1405     int colRowOfs = GetCollapsedIconsPos();
1406     wxRect& bounds = mpPane->mBoundsInParent;
1407 
1408     wxBrush bkBrush( mpLayout->mGrayPen.GetColour(), wxSOLID );
1409     dc.SetBrush( bkBrush );
1410     dc.SetPen( mpLayout->mDarkPen );
1411 
1412     if ( mpPane->IsHorizontal() )
1413 
1414         dc.DrawRectangle( bounds.x + mpPane->mLeftMargin - ROW_DRAG_HINT_WIDTH - 1,
1415                           colRowOfs,
1416                           bounds.width - mpPane->mLeftMargin - mpPane->mRightMargin + 2 + ROW_DRAG_HINT_WIDTH,
1417                           COLLAPSED_ICON_HEIGHT + 1);
1418     else
1419         dc.DrawRectangle( colRowOfs,
1420                           bounds.y + mpPane->mTopMargin - 1,
1421                           COLLAPSED_ICON_HEIGHT + 1,
1422                           bounds.height - mpPane->mTopMargin - mpPane->mBottomMargin
1423                           - ROW_DRAG_HINT_WIDTH - 2 );
1424 
1425     dc.SetBrush( wxNullBrush );
1426 }
1427 
rect_contains_point(const wxRect & rect,int x,int y)1428 static inline bool rect_contains_point( const wxRect& rect, int x, int y )
1429 {
1430     return ( x >= rect.x &&
1431              y >= rect.y &&
1432              x <  rect.x + rect.width  &&
1433              y <  rect.y + rect.height );
1434 }
1435 
HitTestCollapsedRowIcon(int iconIdx,const wxPoint & pos)1436 bool cbRowDragPlugin::HitTestCollapsedRowIcon( int iconIdx, const wxPoint& pos )
1437 {
1438     wxRect bounds;
1439     GetCollapsedInconRect( iconIdx, bounds );
1440 
1441     return rect_contains_point( bounds, pos.x, pos.y );
1442 }
1443 
HitTestRowDragHint(cbRowInfo * pRow,const wxPoint & pos)1444 bool cbRowDragPlugin::HitTestRowDragHint( cbRowInfo* pRow, const wxPoint& pos )
1445 {
1446     wxRect bounds;
1447     GetRowHintRect( pRow, bounds );
1448 
1449     return rect_contains_point( bounds, pos.x, pos.y );
1450 }
1451 
1452