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
40IMPLEMENT_DYNAMIC_CLASS( cbHiddenBarInfo, wxObject )
41
42/***** Implementation for class cbRowDragPlugin *****/
43
44IMPLEMENT_DYNAMIC_CLASS( cbRowDragPlugin, cbPluginBase )
45
46BEGIN_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
54END_EVENT_TABLE()
55
56// FIXME:: how to eliminated these cut and pasted constructors?
57
58cbRowDragPlugin::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
85cbRowDragPlugin::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
114cbRowDragPlugin::~cbRowDragPlugin()
115{
116}
117
118// handlers for plugin events
119void 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
238void 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
261void 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
366void 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
410int 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
430int cbRowDragPlugin::GetCollapsedRowIconHeight()
431{
432    return COLLAPSED_ICON_HEIGHT;
433}
434
435int cbRowDragPlugin::GetRowDragHintWidth()
436{
437    return ROW_DRAG_HINT_WIDTH;
438}
439
440void 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
473void 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
489void 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
507void 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
520void 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
593wxBitmap* 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
606void 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
688void 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
703void 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
719void 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
733void 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
788void 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
887void 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
908bool cbRowDragPlugin::ItemIsInFocus()
909{
910    return ( mpRowInFocus || mCollapsedIconInFocus != - 1 );
911}
912
913void 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
932cbRowInfo* cbRowDragPlugin::GetFirstRow()
933{
934    return ( mpPane->GetRowList().GetCount() )
935           ? mpPane->GetRowList()[0]
936           : NULL;
937}
938
939/*** "hard-coded" metafile for NN-look ***/
940
941void 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
968void 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
995void 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
1022void 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
1035void 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
1047void 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
1108void 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
1169void 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
1195void 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
1206int  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
1229void 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
1249void 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
1279void 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
1345void 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
1398void cbRowDragPlugin::DrawRowsDragHintsBorder( wxDC& WXUNUSED(dc) )
1399{
1400    // FIXME:: what was that?
1401}
1402
1403void 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
1428static 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
1436bool 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
1444bool 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