1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: cbRowDragPlugin implementation.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "rowdragpl.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/fl/rowdragpl.h"
29 #define MINIMAL_ROW_DRAG_OFS 5
31 // parameters for row-hints of NC-look
33 #define TRIANGLE_OFFSET 2
34 #define TRIANGLE_TO_PAT_GAP 2
36 #define COLLAPSED_ICON_WIDTH 45
37 #define COLLAPSED_ICON_HEIGHT 9
38 #define ROW_DRAG_HINT_WIDTH 10
39 #define ICON_TRIAN_WIDTH 6
40 #define ICON_TRIAN_HEIGHT 3
42 /***** Implementation for class cbHiddenBarInfo *****/
44 IMPLEMENT_DYNAMIC_CLASS( cbHiddenBarInfo
, wxObject
)
46 /***** Implementation for class cbRowDragPlugin *****/
48 IMPLEMENT_DYNAMIC_CLASS( cbRowDragPlugin
, cbPluginBase
)
50 BEGIN_EVENT_TABLE( cbRowDragPlugin
, cbPluginBase
)
52 EVT_PL_LEFT_DOWN ( cbRowDragPlugin::OnLButtonDown
)
53 EVT_PL_LEFT_UP ( cbRowDragPlugin::OnLButtonUp
)
54 EVT_PL_MOTION ( cbRowDragPlugin::OnMouseMove
)
56 EVT_PL_DRAW_PANE_DECOR ( cbRowDragPlugin::OnDrawPaneBackground
)
60 // FIXME:: how to eliminated these cut and pasted constructors?
62 cbRowDragPlugin::cbRowDragPlugin(void)
64 : mHightColor ( 192, 192, 255 ),
65 mLowColor ( 192, 192, 192 ),
66 mTrianInnerColor ( 0,0,255 ),
67 mTrianInnerPen ( mTrianInnerColor
, 1, wxSOLID
),
69 mDragStarted ( FALSE
),
70 mDecisionMode ( FALSE
),
72 mCaptureIsOn ( FALSE
),
74 mSvBottomMargin ( -1 ),
76 mSvRightMargin ( -1 ),
80 mpCombinedImage ( NULL
),
82 mpRowInFocus ( NULL
),
83 mCollapsedIconInFocus( -1 ),
89 cbRowDragPlugin::cbRowDragPlugin( wxFrameLayout
* pLayout
, int paneMask
)
91 : cbPluginBase( pLayout
, paneMask
),
93 mHightColor ( 192, 192, 255 ),
94 mLowColor ( 192, 192, 192 ),
95 mTrianInnerColor ( 0,0,255 ),
96 mTrianInnerPen ( mTrianInnerColor
, 1, wxSOLID
),
98 mDragStarted ( FALSE
),
99 mDecisionMode ( FALSE
),
101 mCaptureIsOn ( FALSE
),
103 mSvBottomMargin ( -1 ),
104 mSvLeftMargin ( -1 ),
105 mSvRightMargin ( -1 ),
107 mpPaneImage ( NULL
),
109 mpCombinedImage ( NULL
),
111 mpRowInFocus ( NULL
),
112 mCollapsedIconInFocus( -1 ),
118 cbRowDragPlugin::~cbRowDragPlugin()
122 // handlers for plugin events
123 void cbRowDragPlugin::OnMouseMove( cbMotionEvent
& event
)
126 wxPoint pos
= event
.mPos
;
127 mpPane
= event
.mpPane
;
129 mpPane
->PaneToFrame( &pos
.x
, &pos
.y
);
133 if ( mDecisionMode
&& mpRowInFocus
)
137 if ( mpPane
->IsHorizontal() )
139 ofs
= pos
.y
- mDragOrigin
.y
;
141 ofs
= pos
.x
- mDragOrigin
.x
;
143 // check if the item was dragged sufficeintly
144 // far, enough to consider that user really intends
147 if ( ofs
>= MINIMAL_ROW_DRAG_OFS
||
148 ofs
<= -MINIMAL_ROW_DRAG_OFS
)
151 //.wxPoint pos = event.mPos;
152 //wxPoint drg = mDragOrigin;
153 //int dif = event.mPos.x - mDragOrigin.x;
156 mDecisionMode
= FALSE
;
163 // this plugin "eats" all mouse input while item is dragged,
167 cbRowInfo
* pRow
= GetFirstRow();
169 bool focusFound
= FALSE
;
173 if ( HitTestRowDragHint( pRow
, pos
) )
175 CheckPrevItemInFocus( pRow
, -1 );
176 SetMouseCapture( TRUE
);
181 mCollapsedIconInFocus
= -1;
190 int hrCnt
= GetHRowsCountForPane( event
.mpPane
);
192 for( int i
= 0; i
!= hrCnt
; ++i
)
194 if ( HitTestCollapsedRowIcon( i
, pos
) )
196 CheckPrevItemInFocus( NULL
, i
);
197 SetMouseCapture( TRUE
);
201 mCollapsedIconInFocus
= i
;
208 if ( !focusFound
&& ItemIsInFocus() )
210 // kill focus from item previously been in focus
211 UnhighlightItemInFocus();
214 mCollapsedIconInFocus
= -1;
215 SetMouseCapture( FALSE
);
218 if ( !ItemIsInFocus() )
220 // delegate it to other plugins
225 // otherwise mouse pointer moves, when dragging is started
227 if ( mpPane
->IsHorizontal() )
230 wxPoint p
= event
.mPos
;
231 wxPoint d
= mDragOrigin
;
232 // int dif = event.mPos.x - mDragOrigin.x;
234 // row is dragged up or down;
235 ShowDraggedRow( pos
.y
- mDragOrigin
.y
);
240 wxPoint p
= event
.mPos
;
241 wxPoint d
= mDragOrigin
;
242 // int dif = event.mPos.x - mDragOrigin.x;
244 // row is dragged left or right
245 ShowDraggedRow( pos
.x
- mDragOrigin
.x
);
248 // this plugin "eats" all mouse input while item is dragged,
252 void cbRowDragPlugin::OnLButtonDown( cbLeftDownEvent
& event
)
254 mpPane
= event
.mpPane
;
257 wxASSERT( !mDragStarted
&& !mDecisionMode
);
259 if ( ItemIsInFocus() )
261 mDecisionMode
= TRUE
;
263 wxPoint pos
= event
.mPos
;
264 mpPane
->PaneToFrame( &pos
.x
, &pos
.y
);
268 SetMouseCapture( TRUE
);
271 // propagate event to other plugins
275 void cbRowDragPlugin::OnLButtonUp ( cbLeftUpEvent
& event
)
277 if ( !mDragStarted
&& !mDecisionMode
)
283 mpPane
= event
.mpPane
;
287 cbDockPane
* pPane
= mpPane
;
289 SetMouseCapture( FALSE
);
291 mDecisionMode
= FALSE
;
292 mDragStarted
= FALSE
;
294 wxPoint frmPos
= event
.mPos
;
295 pPane
->PaneToFrame( &frmPos
.x
, &frmPos
.y
);
299 CollapseRow( mpRowInFocus
);
304 ExpandRow( mCollapsedIconInFocus
);
305 mCollapsedIconInFocus
= -1;
311 pPane
->FrameToPane( &frmPos
.x
, &frmPos
.y
);
313 // give it another try after relayouting bars
315 cbMotionEvent
moveEvt( frmPos
, pPane
);
316 this->OnMouseMove( moveEvt
);
318 // this plugin has "eaten" the mouse-up event
324 // otherwise, the dragged row was dropped, determine
325 // where to insert it
327 // restore initial pane appearence
329 FinishOnScreenDraw();
331 cbRowInfo
* pRow
= GetFirstRow();
333 mpLayout
->GetUpdatesManager().OnStartChanges();
335 pRow
->mUMgrData
.SetDirty(TRUE
);
337 cbBarInfo
* pBar
= mpRowInFocus
->mBars
[0];
341 pBar
->mUMgrData
.SetDirty(TRUE
);
343 if ( pBar
->mpBarWnd
)
345 // do complete refresh
346 pBar
->mpBarWnd
->Show(FALSE
);
347 pBar
->mpBarWnd
->Show(TRUE
);
355 if ( mCurDragOfs
< pRow
->mRowY
)
357 InsertDraggedRowBefore( pRow
);
364 if ( pRow
== NULL
) InsertDraggedRowBefore( NULL
);
368 mpLayout
->RecalcLayout(FALSE
);
370 // finish change "transaction"
371 mpLayout
->GetUpdatesManager().OnFinishChanges();
372 mpLayout
->GetUpdatesManager().UpdateNow();
374 // finish drag action
375 SetMouseCapture( FALSE
);
376 mDragStarted
= FALSE
;
380 void cbRowDragPlugin::OnDrawPaneBackground ( cbDrawPaneDecorEvent
& event
)
382 mpPane
= event
.mpPane
;
384 // FIXME:: this may harm operation of other plugins
386 if ( GetNextHandler() && mpPane
->GetRowList().GetCount() )
388 // first, let other plugins add their decorations now
390 GetNextHandler()->ProcessEvent( event
);
394 wxClientDC
dc( &mpLayout
->GetParentFrame() );
396 dc
.SetClippingRegion( mpPane
->mBoundsInParent
.x
,
397 mpPane
->mBoundsInParent
.y
,
398 mpPane
->mBoundsInParent
.width
,
399 mpPane
->mBoundsInParent
.height
);
401 int cnt
= GetHRowsCountForPane( event
.mpPane
);
405 DrawCollapsedRowsBorder( dc
);
407 if ( mpPane
->GetRowList().GetCount() )
409 DrawRowsDragHintsBorder( dc
);
411 cbRowInfo
* pRow
= GetFirstRow();
415 DrawRowDragHint( pRow
, dc
, FALSE
);
419 for( int i
= 0; i
!= cnt
; ++i
)
421 DrawCollapsedRowIcon(i
, dc
, FALSE
);
424 int cbRowDragPlugin::GetHRowsCountForPane( cbDockPane
* pPane
)
426 wxNode
* pNode
= mHiddenBars
.First();
432 cbHiddenBarInfo
* pHBInfo
= (cbHiddenBarInfo
*)pNode
->Data();
434 if ( pHBInfo
->mAlignment
== pPane
->mAlignment
)
436 maxIconNo
= wxMax( maxIconNo
, pHBInfo
->mIconNo
);
438 pNode
= pNode
->Next();
441 return ( maxIconNo
+ 1 );
444 int cbRowDragPlugin::GetCollapsedRowIconHeight()
446 return COLLAPSED_ICON_HEIGHT
;
449 int cbRowDragPlugin::GetRowDragHintWidth()
451 return ROW_DRAG_HINT_WIDTH
;
454 void cbRowDragPlugin::SetPaneMargins()
456 int hiddenRowsCnt
= GetHRowsCountForPane( mpPane
);
458 if ( mSvTopMargin
== -1 )
460 mSvTopMargin
= mpPane
->mTopMargin
;
461 mSvBottomMargin
= mpPane
->mBottomMargin
;
462 mSvLeftMargin
= mpPane
->mLeftMargin
;
463 mSvRightMargin
= mpPane
->mRightMargin
;
466 if ( mpPane
->IsHorizontal() )
468 mpPane
->mTopMargin
= mSvTopMargin
;
469 mpPane
->mBottomMargin
= ( hiddenRowsCnt
== 0 )
471 : mSvBottomMargin
+ GetCollapsedRowIconHeight();
473 mpPane
->mLeftMargin
= mSvLeftMargin
+ GetRowDragHintWidth();
474 mpPane
->mRightMargin
= mSvRightMargin
;
478 mpPane
->mTopMargin
= mSvTopMargin
;
479 mpPane
->mBottomMargin
= mSvBottomMargin
+ GetRowDragHintWidth();
481 mpPane
->mLeftMargin
= mSvLeftMargin
;
482 mpPane
->mRightMargin
= ( hiddenRowsCnt
== 0 ) ?
483 mSvRightMargin
: mSvRightMargin
+ GetCollapsedRowIconHeight();
487 void cbRowDragPlugin::OnInitPlugin()
489 cbDockPane
** panes
= mpLayout
->GetPanesArray();
491 for( int i
= 0; i
!= MAX_PANES
; ++i
)
493 if ( panes
[i
]->MatchesMask( mPaneMask
) )
501 /*** helpers for drag&drop ***/
503 void cbRowDragPlugin::SetMouseCapture( bool captureOn
)
505 if ( mCaptureIsOn
== captureOn
) return;
509 mpLayout
->CaptureEventsForPane( mpPane
);
510 mpLayout
->CaptureEventsForPlugin( this );
514 mpLayout
->ReleaseEventsFromPane( mpPane
);
515 mpLayout
->ReleaseEventsFromPlugin( this );
518 mCaptureIsOn
= captureOn
;
521 void cbRowDragPlugin::UnhighlightItemInFocus()
523 wxClientDC
dc( &mpLayout
->GetParentFrame() );
527 DrawRowDragHint( mpRowInFocus
, dc
, FALSE
);
529 if ( mCollapsedIconInFocus
!= - 1 )
531 DrawCollapsedRowIcon( mCollapsedIconInFocus
, dc
, FALSE
);
534 void cbRowDragPlugin::ShowDraggedRow( int offset
)
536 // create combined image of pane and dragged
537 // row on it, in the mpCombinedImage bitmap
539 if ( mpPane
->IsHorizontal() )
541 if ( mInitialRowOfs
+ offset
+ mRowImgDim
.y
> mCombRect
.y
+ mCombRect
.height
)
543 offset
= mCombRect
.y
+ mCombRect
.height
- mRowImgDim
.y
- mInitialRowOfs
;
545 if ( mInitialRowOfs
+ offset
< mCombRect
.y
)
547 offset
= mCombRect
.y
- mInitialRowOfs
;
549 int x
, y
= mInitialRowOfs
+ offset
;
550 mpPane
->FrameToPane( &x
, &y
);
555 if ( mInitialRowOfs
+ offset
+ mRowImgDim
.x
> mCombRect
.x
+ mCombRect
.width
)
557 offset
= mCombRect
.x
+ mCombRect
.width
- mRowImgDim
.x
- mInitialRowOfs
;
559 if ( mInitialRowOfs
+ offset
< mCombRect
.x
)
561 offset
= mCombRect
.x
- mInitialRowOfs
;
563 int x
= mInitialRowOfs
+ offset
, y
;
564 mpPane
->FrameToPane( &x
, &y
);
569 rowImgDc
.SelectObject ( *mpRowImage
);
571 wxMemoryDC paneImgDc
;
572 paneImgDc
.SelectObject( *mpPaneImage
);
574 wxMemoryDC combImgDc
;
575 combImgDc
.SelectObject( *mpCombinedImage
);
577 combImgDc
.Blit( 0,0, mCombRect
.width
, mCombRect
.height
,
578 &paneImgDc
, 0,0, wxCOPY
);
580 if ( mpPane
->IsHorizontal() )
582 combImgDc
.Blit( 0, mInitialRowOfs
+ offset
- mCombRect
.y
,
583 mCombRect
.width
, mRowImgDim
.y
,
584 &rowImgDc
, 0,0, wxCOPY
);
588 combImgDc
.Blit( mInitialRowOfs
+ offset
- mCombRect
.x
,
590 mRowImgDim
.x
, mCombRect
.height
,
591 &rowImgDc
, 0,0, wxCOPY
);
594 int scrX
= mCombRect
.x
,
597 mpLayout
->GetParentFrame().ClientToScreen( &scrX
, &scrY
);
599 mpScrDc
->Blit( scrX
, scrY
, mCombRect
.width
, mCombRect
.height
,
600 &combImgDc
, 0,0, wxCOPY
);
602 rowImgDc
.SelectObject( wxNullBitmap
);
603 paneImgDc
.SelectObject( wxNullBitmap
);
604 combImgDc
.SelectObject( wxNullBitmap
);
607 wxBitmap
* cbRowDragPlugin::CaptureDCArea( wxDC
& dc
, wxRect
& area
)
609 wxBitmap
* pBmp
= new wxBitmap( int(area
.width
), int(area
.height
) );
612 mdc
.SelectObject( *pBmp
);
614 mdc
.Blit( 0,0, area
.width
, area
.height
, &dc
, area
.x
, area
.y
, wxCOPY
);
615 mdc
.SelectObject( wxNullBitmap
);
620 void cbRowDragPlugin::PrepareForRowDrag()
622 wxRect rowBounds
= mpRowInFocus
->mBoundsInParent
;
624 if ( mpPane
->IsHorizontal() )
626 mCombRect
= mpPane
->mBoundsInParent
;
628 mCombRect
.x
+= mpPane
->mLeftMargin
- ROW_DRAG_HINT_WIDTH
- 1;
629 mCombRect
.y
+= mpPane
->mTopMargin
;
631 mCombRect
.width
-= mpPane
->mLeftMargin
+ mpPane
->mRightMargin
- ROW_DRAG_HINT_WIDTH
- 1 - 1;
632 mCombRect
.height
-= mpPane
->mTopMargin
+ mpPane
->mBottomMargin
;
634 mCombRect
.height
+= 2*rowBounds
.height
;
635 mCombRect
.y
-= rowBounds
.height
;
636 mInitialRowOfs
= rowBounds
.y
;
639 rowBounds
.height
+= 2;
640 rowBounds
.x
= mCombRect
.x
;
641 rowBounds
.width
= mCombRect
.width
;
643 mRowImgDim
.y
= rowBounds
.height
;
647 mCombRect
= mpPane
->mBoundsInParent
;
649 mCombRect
.y
+= mpPane
->mTopMargin
- 1;
650 mCombRect
.x
+= mpPane
->mLeftMargin
- 1;
652 mCombRect
.height
-= mpPane
->mTopMargin
+ mpPane
->mBottomMargin
- ROW_DRAG_HINT_WIDTH
- 1 - 1;
653 mCombRect
.width
-= mpPane
->mLeftMargin
+ mpPane
->mRightMargin
;
655 mCombRect
.width
+= 2*rowBounds
.width
;
656 mCombRect
.x
-= rowBounds
.width
;
657 mInitialRowOfs
= rowBounds
.x
;
660 rowBounds
.width
+= 2;
661 rowBounds
.y
= mCombRect
.y
;
662 rowBounds
.height
= mCombRect
.height
;
664 mRowImgDim
.x
= rowBounds
.width
;
666 // output cobination results onto frame's client area
667 wxScreenDC::StartDrawingOnTop(&mpLayout
->GetParentFrame());
668 mpScrDc
= new wxScreenDC();
670 int x
= mCombRect
.x
, y
= mCombRect
.y
;
671 mpLayout
->GetParentFrame().ClientToScreen( &x
, &y
);
673 wxRect scrRect
= mCombRect
;
677 mpPaneImage
= CaptureDCArea( *mpScrDc
, scrRect
);
680 mdc
.SelectObject( *mpPaneImage
);
681 mdc
.SetDeviceOrigin( -mCombRect
.x
, -mCombRect
.y
);
683 DrawRectShade( rowBounds
, mdc
, -1, mpLayout
->mGrayPen
, mpLayout
->mDarkPen
);
684 DrawRectShade( rowBounds
, mdc
, 0, mpLayout
->mLightPen
, mpLayout
->mBlackPen
);
686 mpRowImage
= CaptureDCArea( mdc
, rowBounds
);
688 // draw dark empty-row placeholder
689 DrawEmptyRow( mdc
, rowBounds
);
691 //DrawRectShade( rowBounds, mdc, 0, mpLayout->mGrayPen, mpLayout->mDarkPen );
692 DrawRectShade( rowBounds
, mdc
, -1, mpLayout
->mGrayPen
, mpLayout
->mGrayPen
);
694 mdc
.SelectObject( wxNullBitmap
);
696 mpCombinedImage
= new wxBitmap( int(mCombRect
.width
), int(mCombRect
.height
) );
698 // show it for the first time
702 void cbRowDragPlugin::DrawEmptyRow( wxDC
& dc
, wxRect
& rowBounds
)
704 wxBrush
bkBrush( mpLayout
->mDarkPen
.GetColour(), wxSOLID
);
706 // paint the "dark" empty-row placeholder
708 dc
.SetBrush( bkBrush
);
709 dc
.SetPen ( mpLayout
->mNullPen
);
711 dc
.DrawRectangle( rowBounds
.x
, rowBounds
.y
,
712 rowBounds
.width
+1, rowBounds
.height
+1 );
714 dc
.SetBrush( wxNullBrush
);
717 void cbRowDragPlugin::ShowPaneImage()
719 int scrX
= 0, scrY
= 0;
721 mpLayout
->GetParentFrame().ClientToScreen( &scrX
, &scrY
);
724 mdc
.SelectObject( *mpPaneImage
);
726 mpScrDc
->Blit( mCombRect
.x
+ scrX
, mCombRect
.y
+ scrY
,
727 mCombRect
.width
, mCombRect
.height
,
730 mdc
.SelectObject( wxNullBitmap
);
733 void cbRowDragPlugin::FinishOnScreenDraw()
735 wxScreenDC::EndDrawingOnTop();
738 delete mpCombinedImage
;
744 mpCombinedImage
= mpPaneImage
= mpRowImage
= NULL
;
747 void cbRowDragPlugin::CollapseRow( cbRowInfo
* pRow
)
749 int iconCnt
= GetHRowsCountForPane( mpPane
);
751 mpLayout
->GetUpdatesManager().OnStartChanges();
753 cbBarInfo
* pBar
= pRow
->mBars
[0];
757 cbRowInfo
* pCur
= pRow
;
758 while( pCur
->mpPrev
) { ++rowNo
; pCur
= pCur
->mpPrev
; }
762 cbHiddenBarInfo
* pHBInfo
= new cbHiddenBarInfo();
764 pHBInfo
->mpBar
= pBar
;
765 pHBInfo
->mRowNo
= rowNo
;
766 pHBInfo
->mIconNo
= iconCnt
;
767 pHBInfo
->mAlignment
= mpPane
->mAlignment
;
769 mHiddenBars
.Append( (wxObject
*) pHBInfo
);
772 if ( pBar
->mpBarWnd
)
774 pBar
->mpBarWnd
->Show( FALSE
);
776 pBar
->mState
= wxCBAR_HIDDEN
;
778 cbBarInfo
* pNext
= pBar
->mpNext
;
787 mpPane
->GetRowList().Remove( pRow
);
788 mpPane
->InitLinksForRows();
794 mpLayout
->RecalcLayout(FALSE
);
798 mpLayout
->GetUpdatesManager().OnFinishChanges();
799 mpLayout
->GetUpdatesManager().UpdateNow();
802 void cbRowDragPlugin::ExpandRow( int collapsedIconIdx
)
804 mpLayout
->GetUpdatesManager().OnStartChanges();
806 cbRowInfo
* pNewRow
= new cbRowInfo();
808 wxNode
* pNode
= mHiddenBars
.First();
812 // move bars from internal list to the newly expanded row
816 cbHiddenBarInfo
* pHBInfo
= (cbHiddenBarInfo
*)pNode
->Data();
818 if ( pHBInfo
->mAlignment
== mpPane
->mAlignment
&&
819 pHBInfo
->mIconNo
== collapsedIconIdx
)
821 rowNo
= pHBInfo
->mRowNo
;
823 if ( pHBInfo
->mpBar
->mState
== wxCBAR_HIDDEN
)
825 pNewRow
->mBars
.Add( pHBInfo
->mpBar
);
827 pHBInfo
->mpBar
->mState
= ( mpPane
->IsHorizontal() )
828 ? wxCBAR_DOCKED_HORIZONTALLY
829 : wxCBAR_DOCKED_VERTICALLY
;
832 // remove bar info from internal list
834 wxNode
* pNext
= pNode
->Next();
837 mHiddenBars
.DeleteNode( pNode
);
843 // decrease incon numbers with higher indicies, since this
844 // row is now removed from the hidden-rows list
846 if ( pHBInfo
->mIconNo
> collapsedIconIdx
&&
847 pHBInfo
->mAlignment
== mpPane
->mAlignment
)
851 pNode
= pNode
->Next();
855 mpPane
->InitLinksForRow( pNewRow
);
857 // insert row into pane at it's original position
859 if ( pNewRow
->mBars
.GetCount() )
861 cbRowInfo
* beforeRowNode
= mpPane
->GetRow( rowNo
);
863 mpPane
->InsertRow( pNewRow
, beforeRowNode
);
870 mpLayout
->RecalcLayout(FALSE
);
872 mCollapsedIconInFocus
= -1;
874 mpLayout
->GetUpdatesManager().OnFinishChanges();
875 mpLayout
->GetUpdatesManager().UpdateNow();
879 wxNode* pRowNode = mHiddenRows.Nth( collapsedIconIdx );
881 mpLayout->GetUpdatesManager().OnStartChanges();
883 // insert at the end of rows list
884 mpPane->InsertRow( pRowNode, NULL );
886 int success = mHiddenRows.DeleteNode( pRowNode );
892 mpLayout->RecalcLayout(FALSE);
894 mCollapsedIconInFocus = -1;
896 mpLayout->GetUpdatesManager().OnFinishChanges();
897 mpLayout->GetUpdatesManager().UpdateNow();
901 void cbRowDragPlugin::InsertDraggedRowBefore( cbRowInfo
* pBeforeRow
)
903 if ( mpRowInFocus
!= pBeforeRow
&&
904 mpRowInFocus
->mpNext
!= pBeforeRow
907 mpPane
->GetRowList().Remove( mpRowInFocus
);
909 mpPane
->InsertRow( mpRowInFocus
, pBeforeRow
);
913 // otherwise, nothing has happned (row positions do not change)
915 //wxClientDC dc( &mpLayout->GetParentFrame() );
917 //mpPane->PaintRow( mpRowInFocus, dc );
918 //DrawRowDragHint( mpRowInFocus, dc, FALSE );
922 bool cbRowDragPlugin::ItemIsInFocus()
924 return ( mpRowInFocus
|| mCollapsedIconInFocus
!= - 1 );
927 void cbRowDragPlugin::CheckPrevItemInFocus( cbRowInfo
* pRow
, int iconIdx
)
929 wxClientDC
dc( &mpLayout
->GetParentFrame() );
931 if ( pRow
!= NULL
&& mpRowInFocus
== pRow
) return;
932 if ( iconIdx
!= -1 && mCollapsedIconInFocus
== iconIdx
) return;
934 UnhighlightItemInFocus();
936 if ( iconIdx
!= - 1 )
938 DrawCollapsedRowIcon( iconIdx
, dc
, TRUE
);
943 DrawRowDragHint( pRow
, dc
, TRUE
);
946 cbRowInfo
* cbRowDragPlugin::GetFirstRow()
948 return ( mpPane
->GetRowList().GetCount() )
949 ? mpPane
->GetRowList()[0]
953 /*** "hard-coded" metafile for NN-look ***/
955 void cbRowDragPlugin::DrawTrianUp( wxRect
& inRect
, wxDC
& dc
)
957 int xOfs
= (inRect
.width
- ICON_TRIAN_WIDTH
)/2;
959 wxBrush
br( mTrianInnerColor
, wxSOLID
);
962 dc
.SetPen( mpLayout
->mBlackPen
);
965 points
[0].x
= inRect
.x
+ xOfs
;
966 points
[0].y
= inRect
.y
+ inRect
.height
- 1;
967 points
[1].x
= inRect
.x
+ xOfs
+ ICON_TRIAN_WIDTH
/2 + 1;
968 points
[1].y
= inRect
.y
+ inRect
.height
- 2 - ICON_TRIAN_HEIGHT
;
969 points
[2].x
= inRect
.x
+ xOfs
+ ICON_TRIAN_WIDTH
+1;
970 points
[2].y
= inRect
.y
+ inRect
.height
- 1;
972 dc
.DrawPolygon( 3, points
);
974 // higlight upper-right edge of triangle
975 dc
.SetPen( mpLayout
->mLightPen
);
976 dc
.DrawLine( points
[2].x
, points
[2].y
,
977 points
[0].x
, points
[0].y
);
979 dc
.SetBrush( wxNullBrush
);
982 void cbRowDragPlugin::DrawTrianDown( wxRect
& inRect
, wxDC
& dc
)
984 int xOfs
= (inRect
.width
- ICON_TRIAN_WIDTH
)/2;
986 wxBrush
br( mTrianInnerColor
, wxSOLID
);
989 dc
.SetPen( mpLayout
->mBlackPen
);
992 points
[0].x
= inRect
.x
+ xOfs
;
993 points
[0].y
= inRect
.y
;
994 points
[1].x
= inRect
.x
+ xOfs
+ ICON_TRIAN_WIDTH
;
995 points
[1].y
= inRect
.y
;
996 points
[2].x
= inRect
.x
+ xOfs
+ ICON_TRIAN_WIDTH
/2;
997 points
[2].y
= inRect
.y
+ ICON_TRIAN_HEIGHT
;
999 dc
.DrawPolygon( 3, points
);
1001 // higlight upper-right edge of triangle
1002 dc
.SetPen( mpLayout
->mLightPen
);
1003 dc
.DrawLine( points
[2].x
, points
[2].y
,
1004 points
[1].x
, points
[1].y
);
1006 dc
.SetBrush( wxNullBrush
);
1009 void cbRowDragPlugin::DrawTrianRight( wxRect
& inRect
, wxDC
& dc
)
1011 int yOfs
= (inRect
.height
- ICON_TRIAN_WIDTH
)/2;
1013 wxBrush
br( mTrianInnerColor
, wxSOLID
);
1016 dc
.SetPen( mpLayout
->mBlackPen
);
1019 points
[0].x
= inRect
.x
;
1020 points
[0].y
= inRect
.y
+ yOfs
+ ICON_TRIAN_WIDTH
;
1021 points
[1].x
= inRect
.x
;
1022 points
[1].y
= inRect
.y
+ yOfs
;
1023 points
[2].x
= inRect
.x
+ ICON_TRIAN_HEIGHT
;
1024 points
[2].y
= inRect
.y
+ yOfs
+ ICON_TRIAN_WIDTH
/2;
1026 dc
.DrawPolygon( 3, points
);
1028 // higlight upper-right edge of triangle
1029 dc
.SetPen( mpLayout
->mLightPen
);
1030 dc
.DrawLine( points
[0].x
, points
[0].y
,
1031 points
[2].x
, points
[2].y
);
1033 dc
.SetBrush( wxNullBrush
);
1036 void cbRowDragPlugin::Draw3DPattern( wxRect
& inRect
, wxDC
& dc
)
1038 for( int y
= inRect
.y
; y
< inRect
.y
+ inRect
.height
; y
+=3 )
1040 for( int x
= inRect
.x
; x
< inRect
.x
+ inRect
.width
; x
+=3 )
1042 dc
.SetPen( mpLayout
->mLightPen
);
1043 dc
.DrawPoint( x
,y
);
1044 dc
.SetPen( mpLayout
->mBlackPen
);
1045 dc
.DrawPoint( x
+1, y
+1 );
1049 void cbRowDragPlugin::DrawRombShades( wxPoint
& p1
, wxPoint
& p2
,
1050 wxPoint
& p3
, wxPoint
& p4
,
1053 dc
.SetPen( mpLayout
->mLightPen
);
1054 dc
.DrawLine( p1
.x
, p1
.y
, p2
.x
, p2
.y
);
1055 dc
.DrawLine( p2
.x
, p2
.y
, p3
.x
, p3
.y
);
1056 dc
.SetPen( mpLayout
->mDarkPen
);
1057 dc
.DrawLine( p3
.x
, p3
.y
, p4
.x
, p4
.y
);
1058 dc
.DrawLine( p4
.x
, p4
.y
, p1
.x
, p1
.y
);
1061 void cbRowDragPlugin::DrawOrtoRomb( wxRect
& inRect
, wxDC
& dc
, wxBrush
& bkBrush
)
1063 dc
.SetBrush( bkBrush
);
1064 dc
.SetPen( mpLayout
->mBlackPen
);
1068 if ( inRect
.width
> inRect
.height
)
1070 // horizontal orienation
1071 points
[0].x
= inRect
.x
;
1072 points
[0].y
= inRect
.y
+ inRect
.height
;
1073 points
[1].x
= inRect
.x
;
1074 points
[1].y
= inRect
.y
;
1075 points
[2].x
= inRect
.x
+ inRect
.width
;
1076 points
[2].y
= inRect
.y
;
1077 points
[3].x
= inRect
.x
+ inRect
.width
- COLLAPSED_ICON_HEIGHT
;
1078 points
[3].y
= inRect
.y
+ inRect
.height
;
1080 dc
.DrawPolygon( 4, points
);
1082 // squeeze romb's bounds to create an inner-shade shape
1087 --points
[2].x
; --points
[2].x
;
1091 DrawRombShades( points
[0], points
[1], points
[2], points
[3], dc
);
1095 // vertical orientation
1096 points
[0].x
= inRect
.x
+ inRect
.width
;
1097 points
[0].y
= inRect
.y
+ inRect
.height
;
1098 points
[1].x
= inRect
.x
;
1099 points
[1].y
= inRect
.y
+ inRect
.height
;
1100 points
[2].x
= inRect
.x
;
1101 points
[2].y
= inRect
.y
;
1102 points
[3].x
= inRect
.x
+ inRect
.width
;
1103 points
[3].y
= inRect
.y
+ COLLAPSED_ICON_HEIGHT
;
1105 dc
.DrawPolygon( 4, points
);
1107 // squeeze romb's bounds to create an inner-shade shape
1112 ++points
[2].y
; ++points
[2].y
;
1116 DrawRombShades( points
[1], points
[2], points
[3], points
[0], dc
);
1119 dc
.SetBrush( wxNullBrush
);
1122 void cbRowDragPlugin::DrawRomb( wxRect
& inRect
, wxDC
& dc
, wxBrush
& bkBrush
)
1126 dc
.SetBrush( bkBrush
);
1127 dc
.SetPen( mpLayout
->mBlackPen
);
1129 if ( inRect
.width
> inRect
.height
)
1131 // horizontal orientation
1132 points
[0].x
= inRect
.x
;
1133 points
[0].y
= inRect
.y
+ inRect
.height
;
1134 points
[1].x
= inRect
.x
+ COLLAPSED_ICON_HEIGHT
;
1135 points
[1].y
= inRect
.y
;
1136 points
[2].x
= inRect
.x
+ inRect
.width
;
1137 points
[2].y
= inRect
.y
;
1138 points
[3].x
= inRect
.x
+ inRect
.width
- COLLAPSED_ICON_HEIGHT
;
1139 points
[3].y
= inRect
.y
+ inRect
.height
;
1141 dc
.DrawPolygon( 4, points
);
1143 // squeeze romb's bounds to create an inner-shade shape
1144 ++points
[0].x
;++points
[0].x
;
1147 --points
[2].x
; --points
[2].x
;
1152 DrawRombShades( points
[0], points
[1], points
[2], points
[3], dc
);
1157 // vertical orientation
1158 points
[0].x
= inRect
.x
+ inRect
.width
;
1159 points
[0].y
= inRect
.y
+ inRect
.height
;
1160 points
[1].x
= inRect
.x
;
1161 points
[1].y
= inRect
.y
+ inRect
.height
- COLLAPSED_ICON_HEIGHT
;
1162 points
[2].x
= inRect
.x
;
1163 points
[2].y
= inRect
.y
;
1164 points
[3].x
= inRect
.x
+ inRect
.width
;
1165 points
[3].y
= inRect
.y
+ COLLAPSED_ICON_HEIGHT
;
1167 dc
.DrawPolygon( 4, points
);
1169 // squeeze romb's bounds to create an inner-shade shape
1170 --points
[0].y
;--points
[0].y
;
1173 ++points
[2].y
; ++points
[2].y
;
1177 DrawRombShades( points
[1], points
[2], points
[3], points
[0], dc
);
1180 dc
.SetBrush( wxNullBrush
);
1183 void cbRowDragPlugin::DrawRectShade( wxRect
& inRect
, wxDC
& dc
,
1184 int level
, wxPen
& upperPen
, wxPen
& lowerPen
)
1187 dc
.SetPen( upperPen
);
1188 dc
.DrawLine( inRect
.x
- level
,
1190 inRect
.x
+ inRect
.width
- 1 + level
,
1192 dc
.DrawLine( inRect
.x
- level
, inRect
.y
- level
,
1193 inRect
.x
- level
, inRect
.y
+ inRect
.height
- 1 + level
);
1196 dc
.SetPen( lowerPen
);
1197 dc
.DrawLine( inRect
.x
- level
,
1198 inRect
.y
+ inRect
.height
- 1 + level
,
1199 inRect
.x
+ inRect
.width
+ level
,
1200 inRect
.y
+ inRect
.height
- 1 + level
);
1201 dc
.DrawLine( inRect
.x
+ inRect
.width
- 1 + level
,
1203 inRect
.x
+ inRect
.width
- 1 + level
,
1204 inRect
.y
+ inRect
.height
+ level
);
1206 dc
.SetBrush( wxNullBrush
);
1209 void cbRowDragPlugin::Draw3DRect( wxRect
& inRect
, wxDC
& dc
, wxBrush
& bkBrush
)
1211 dc
.SetPen( mpLayout
->mNullPen
);
1212 dc
.SetBrush( bkBrush
);
1214 dc
.DrawRectangle( inRect
.x
, inRect
.y
,
1215 inRect
.width
, inRect
.height
);
1217 DrawRectShade( inRect
, dc
, 0, mpLayout
->mLightPen
, mpLayout
->mDarkPen
);
1220 int cbRowDragPlugin::GetCollapsedIconsPos()
1222 RowArrayT
& rows
= mpPane
->GetRowList();
1224 if ( rows
.GetCount() == 0 )
1226 if ( mpPane
->IsHorizontal() )
1228 return mpPane
->mBoundsInParent
.y
+ mpPane
->mTopMargin
;
1230 return mpPane
->mBoundsInParent
.x
+ mpPane
->mLeftMargin
;
1233 wxRect
& bounds
= rows
[ rows
.GetCount() - 1 ]->mBoundsInParent
;
1235 if ( mpPane
->IsHorizontal() )
1237 return bounds
.y
+ bounds
.height
+ 1;
1239 return bounds
.x
+ bounds
.width
+ 1;
1243 void cbRowDragPlugin::GetRowHintRect( cbRowInfo
* pRow
, wxRect
& rect
)
1245 wxRect
& bounds
= pRow
->mBoundsInParent
;
1247 if ( mpPane
->IsHorizontal() )
1249 rect
.x
= bounds
.x
- ROW_DRAG_HINT_WIDTH
- 1;
1251 rect
.width
= ROW_DRAG_HINT_WIDTH
;
1252 rect
.height
= bounds
.height
;
1257 rect
.y
= bounds
.y
+ bounds
.height
+ 1;
1258 rect
.width
= bounds
.width
;
1259 rect
.height
= ROW_DRAG_HINT_WIDTH
;
1263 void cbRowDragPlugin::GetCollapsedInconRect( int iconIdx
, wxRect
& rect
)
1265 int upper
= GetCollapsedIconsPos();
1267 int right
= (iconIdx
== 0 )
1268 ? 0 : iconIdx
* (COLLAPSED_ICON_WIDTH
- COLLAPSED_ICON_HEIGHT
);
1270 if ( mpPane
->IsHorizontal() )
1272 rect
.x
= mpPane
->mBoundsInParent
.x
+ mpPane
->mLeftMargin
- ROW_DRAG_HINT_WIDTH
- 1
1276 rect
.width
= COLLAPSED_ICON_WIDTH
;
1277 rect
.height
= COLLAPSED_ICON_HEIGHT
;
1282 rect
.y
= mpPane
->mBoundsInParent
.y
+ mpPane
->mBoundsInParent
.height
1283 - mpPane
->mBottomMargin
+ ROW_DRAG_HINT_WIDTH
+ 1
1284 - right
- COLLAPSED_ICON_WIDTH
;
1286 rect
.height
= COLLAPSED_ICON_WIDTH
;
1287 rect
.width
= COLLAPSED_ICON_HEIGHT
;
1291 /*** overridables ***/
1293 void cbRowDragPlugin::DrawCollapsedRowIcon( int index
, wxDC
& dc
, bool isHighlighted
)
1296 GetCollapsedInconRect( index
, rect
);
1298 wxBrush
hiBrush ( mHightColor
, wxSOLID
);
1299 wxBrush
lowBrush( mLowColor
, wxSOLID
);
1300 wxBrush
& curBrush
= ( isHighlighted
) ? hiBrush
: lowBrush
;
1302 if ( mpPane
->IsHorizontal() )
1306 DrawOrtoRomb( rect
, dc
, curBrush
);
1308 DrawRomb( rect
, dc
, curBrush
);
1310 int triOfs
= (index
== 0) ? TRIANGLE_OFFSET
: TRIANGLE_OFFSET
+ COLLAPSED_ICON_HEIGHT
;
1313 triRect
.x
= triOfs
+ rect
.x
;
1315 triRect
.width
= ICON_TRIAN_HEIGHT
;
1317 triRect
.height
= rect
.height
;
1319 DrawTrianRight( triRect
, dc
);
1322 patRect
.x
= triOfs
+ ICON_TRIAN_HEIGHT
+ TRIANGLE_TO_PAT_GAP
+ rect
.x
;
1323 patRect
.y
= rect
.y
+ PAT_OFFSET
;
1324 patRect
.width
= rect
.width
- (patRect
.x
- rect
.x
) - COLLAPSED_ICON_HEIGHT
- PAT_OFFSET
;
1325 patRect
.height
= rect
.height
- PAT_OFFSET
*2;
1327 Draw3DPattern( patRect
, dc
);
1333 DrawOrtoRomb( rect
, dc
, curBrush
);
1335 DrawRomb( rect
, dc
, curBrush
);
1337 int triOfs
= (index
== 0)
1338 ? TRIANGLE_OFFSET
+ ICON_TRIAN_HEIGHT
1339 : TRIANGLE_OFFSET
+ COLLAPSED_ICON_HEIGHT
+ ICON_TRIAN_HEIGHT
;
1342 triRect
.y
= rect
.y
+ rect
.height
- triOfs
;
1344 triRect
.width
= rect
.width
;
1345 triRect
.height
= ICON_TRIAN_HEIGHT
;
1347 DrawTrianUp( triRect
, dc
);
1350 patRect
.y
= rect
.y
+ COLLAPSED_ICON_HEIGHT
+ PAT_OFFSET
;
1351 patRect
.x
= rect
.x
+ PAT_OFFSET
;
1352 patRect
.width
= rect
.width
- 2*PAT_OFFSET
;
1353 patRect
.height
= rect
.height
- triOfs
- 2*PAT_OFFSET
- COLLAPSED_ICON_HEIGHT
;
1355 Draw3DPattern( patRect
, dc
);
1359 void cbRowDragPlugin::DrawRowDragHint( cbRowInfo
* pRow
, wxDC
& dc
, bool isHighlighted
)
1362 GetRowHintRect( pRow
, rect
);
1364 wxBrush
hiBrush ( mHightColor
, wxSOLID
);
1365 wxBrush
lowBrush( mLowColor
, wxSOLID
);
1366 wxBrush
& curBrush
= ( isHighlighted
) ? hiBrush
: lowBrush
;
1368 Draw3DRect( rect
, dc
, curBrush
);
1370 if ( mpPane
->IsHorizontal() )
1373 triRect
.y
= rect
.y
+ TRIANGLE_OFFSET
;
1375 triRect
.width
= rect
.width
;
1376 triRect
.height
= ICON_TRIAN_HEIGHT
;
1378 DrawTrianDown( triRect
, dc
);
1381 patRect
.x
= rect
.x
+ PAT_OFFSET
;
1382 patRect
.y
= rect
.y
+ TRIANGLE_OFFSET
+ ICON_TRIAN_HEIGHT
+ TRIANGLE_TO_PAT_GAP
;
1383 patRect
.width
= rect
.width
- 2*PAT_OFFSET
;
1384 patRect
.height
= rect
.height
- ( patRect
.y
- rect
.y
) - PAT_OFFSET
;
1385 Draw3DPattern( patRect
, dc
);
1387 dc
.SetPen( mpLayout
->mLightPen
);
1388 dc
.DrawLine( rect
.x
, rect
.y
+ rect
.height
, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1393 triRect
.x
= rect
.x
+ TRIANGLE_OFFSET
;
1395 triRect
.height
= rect
.height
;
1396 triRect
.width
= ICON_TRIAN_HEIGHT
;
1398 DrawTrianRight( triRect
, dc
);
1401 patRect
.y
= rect
.y
+ PAT_OFFSET
;
1402 patRect
.x
= rect
.x
+ TRIANGLE_OFFSET
+ ICON_TRIAN_HEIGHT
+ TRIANGLE_TO_PAT_GAP
;
1403 patRect
.height
= rect
.height
- 2*PAT_OFFSET
;
1404 patRect
.width
= rect
.width
- ( patRect
.x
- rect
.x
) - PAT_OFFSET
;
1405 Draw3DPattern( patRect
, dc
);
1407 dc
.SetPen( mpLayout
->mLightPen
);
1408 dc
.DrawLine( rect
.x
+ rect
.width
, rect
.y
, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1412 void cbRowDragPlugin::DrawRowsDragHintsBorder( wxDC
& dc
)
1414 // FIXME:: what was that?
1417 void cbRowDragPlugin::DrawCollapsedRowsBorder( wxDC
& dc
)
1419 int colRowOfs
= GetCollapsedIconsPos();
1420 wxRect
& bounds
= mpPane
->mBoundsInParent
;
1422 wxBrush
bkBrush( mpLayout
->mGrayPen
.GetColour(), wxSOLID
);
1423 dc
.SetBrush( bkBrush
);
1424 dc
.SetPen( mpLayout
->mDarkPen
);
1426 if ( mpPane
->IsHorizontal() )
1428 dc
.DrawRectangle( bounds
.x
+ mpPane
->mLeftMargin
- ROW_DRAG_HINT_WIDTH
- 1,
1430 bounds
.width
- mpPane
->mLeftMargin
- mpPane
->mRightMargin
+ 2 + ROW_DRAG_HINT_WIDTH
,
1431 COLLAPSED_ICON_HEIGHT
+ 1);
1433 dc
.DrawRectangle( colRowOfs
,
1434 bounds
.y
+ mpPane
->mTopMargin
- 1,
1435 COLLAPSED_ICON_HEIGHT
+ 1,
1436 bounds
.height
- mpPane
->mTopMargin
- mpPane
->mBottomMargin
1437 - ROW_DRAG_HINT_WIDTH
- 2 );
1439 dc
.SetBrush( wxNullBrush
);
1442 static inline bool rect_contains_point( const wxRect
& rect
, int x
, int y
)
1444 return ( x
>= rect
.x
&&
1446 x
< rect
.x
+ rect
.width
&&
1447 y
< rect
.y
+ rect
.height
);
1450 bool cbRowDragPlugin::HitTestCollapsedRowIcon( int iconIdx
, const wxPoint
& pos
)
1453 GetCollapsedInconRect( iconIdx
, bounds
);
1455 return rect_contains_point( bounds
, pos
.x
, pos
.y
);
1458 bool cbRowDragPlugin::HitTestRowDragHint( cbRowInfo
* pRow
, const wxPoint
& pos
)
1461 GetRowHintRect( pRow
, bounds
);
1463 return rect_contains_point( bounds
, pos
.x
, pos
.y
);