1 /////////////////////////////////////////////////////////////////////////////
2 // Name: panedrawpl.cpp
3 // Purpose: cbPaneDrawPlugin implementation.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "panedrawpl.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
30 #include "wx/utils.h" // import wxMin,wxMax macros
32 #include "wx/fl/panedrawpl.h"
34 // bitmap bits used by bar-resizing brush
36 #define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
37 #define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
38 #define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons.
39 #define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons.
41 static const unsigned char _gCheckerImg
[16] = { _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
42 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
43 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
44 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
47 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
48 // Used: controlbar.cpp(1268): set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
49 // Used: controlbar.cpp(1272): set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
51 static void set_cursor_bits( const char** img, char* bits, int width, int height )
53 for( int i = 0; i != (width*height)/8; ++i )
56 for( int y = 0; y != height; ++y )
58 const char* row = img[0];
60 for( int x = 0; x != width; ++x )
62 int bitNo = y*width + x;
64 char value = ( row[x] != '.' ) ? 1 : 0;
66 bits[ bitNo / sizeof(char) ] |=
67 ( ( bitNo %sizeof(char) ) << value );
75 /***** Implementation for class cbPaneDrawPlugin *****/
77 IMPLEMENT_DYNAMIC_CLASS( cbPaneDrawPlugin
, cbPluginBase
)
79 BEGIN_EVENT_TABLE( cbPaneDrawPlugin
, cbPluginBase
)
81 EVT_PL_LEFT_DOWN ( cbPaneDrawPlugin::OnLButtonDown
)
82 EVT_PL_LEFT_UP ( cbPaneDrawPlugin::OnLButtonUp
)
83 // EVT_PL_LEFT_DCLICK ( cbPaneDrawPlugin::OnLDblClick )
84 EVT_PL_RIGHT_UP ( cbPaneDrawPlugin::OnRButtonUp
)
85 EVT_PL_MOTION ( cbPaneDrawPlugin::OnMouseMove
)
88 EVT_PL_DRAW_PANE_BKGROUND ( cbPaneDrawPlugin::OnDrawPaneBackground
)
89 EVT_PL_DRAW_PANE_DECOR ( cbPaneDrawPlugin::OnDrawPaneDecorations
)
91 EVT_PL_DRAW_ROW_DECOR ( cbPaneDrawPlugin::OnDrawRowDecorations
)
92 EVT_PL_DRAW_ROW_HANDLES ( cbPaneDrawPlugin::OnDrawRowHandles
)
93 EVT_PL_DRAW_ROW_BKGROUND ( cbPaneDrawPlugin::OnDrawRowBackground
)
95 EVT_PL_SIZE_BAR_WND ( cbPaneDrawPlugin::OnSizeBarWindow
)
96 EVT_PL_DRAW_BAR_DECOR ( cbPaneDrawPlugin::OnDrawBarDecorations
)
97 EVT_PL_DRAW_BAR_HANDLES ( cbPaneDrawPlugin::OnDrawBarHandles
)
99 EVT_PL_START_DRAW_IN_AREA ( cbPaneDrawPlugin::OnStartDrawInArea
)
100 EVT_PL_FINISH_DRAW_IN_AREA ( cbPaneDrawPlugin::OnFinishDrawInArea
)
104 cbPaneDrawPlugin::cbPaneDrawPlugin(void)
106 : mResizeStarted ( FALSE
),
108 mResizeCursorOn ( FALSE
),
109 mpDraggedBar ( NULL
),
110 mpResizedRow ( NULL
),
112 mRowHandleHitted ( FALSE
),
113 mIsUpperHandle ( FALSE
),
114 mBarHandleHitted ( FALSE
),
115 mIsLeftHandle ( FALSE
),
116 mBarContentHitted ( FALSE
),
122 cbPaneDrawPlugin::cbPaneDrawPlugin( wxFrameLayout
* pPanel
, int paneMask
)
124 : cbPluginBase( pPanel
, paneMask
),
126 // bar-row resizing state varaibles
128 mResizeStarted ( FALSE
),
130 mResizeCursorOn ( FALSE
),
131 mpDraggedBar ( NULL
),
132 mpResizedRow ( NULL
),
134 mRowHandleHitted ( FALSE
),
135 mIsUpperHandle ( FALSE
),
136 mBarHandleHitted ( FALSE
),
137 mIsLeftHandle ( FALSE
),
138 mBarContentHitted ( FALSE
),
144 cbPaneDrawPlugin::~cbPaneDrawPlugin()
147 wxASSERT( mpClntDc
== NULL
);
150 void cbPaneDrawPlugin::DrawDraggedHandle( const wxPoint
& pos
, cbDockPane
& pane
)
157 pane
.PaneToFrame( &fpos
.x
, &fpos
.y
);
160 int resizeHndSize
= pane
.mProps
.mResizeHandleSize
;
162 // "Required for X to specify that
163 // that we wish to draw on top of all windows
164 // - and we optimise by specifying the area
165 // for creating the overlap window." --J.S.
167 wxScreenDC::StartDrawingOnTop(&mpLayout
->GetParentFrame());
169 mpLayout
->GetParentFrame().ClientToScreen( &ofsX
, &ofsY
);
171 int prevLF
= dc
.GetLogicalFunction();
173 // BUG BUG BUG (wx):: somehow stippled brush works only
174 // when the bitmap created on stack, not
175 // as a member of the class
177 wxBitmap
checker( (const char*)_gCheckerImg
, 8,8 );
179 wxBrush
checkerBrush( checker
);
181 dc
.SetPen( mpLayout
->mNullPen
);
182 dc
.SetBrush( checkerBrush
);
183 dc
.SetLogicalFunction( wxXOR
);
185 if ( mHandleIsVertical
)
187 int delta
= pos
.x
- mDragOrigin
.x
;
189 if ( !pane
.IsHorizontal() )
191 delta
= pos
.y
- mDragOrigin
.y
;
194 realHndOfs
= pane
.mBoundsInParent
.x
+ pane
.mLeftMargin
+ mHandleOfs
;
196 int newX
= realHndOfs
+ delta
;
198 if ( newX
+ resizeHndSize
> mHandleDragArea
.x
+ mHandleDragArea
.width
)
200 newX
= mHandleDragArea
.x
+ mHandleDragArea
.width
- 1;
202 if ( newX
< mHandleDragArea
.x
)
204 newX
= mHandleDragArea
.x
;
206 mDraggedDelta
= newX
- realHndOfs
;
208 dc
.DrawRectangle( newX
+ ofsX
, mHandleDragArea
.y
+ ofsY
,
210 mHandleDragArea
.height
+1 );
214 // otherwise, draw horizontal handle
216 int delta
= pos
.y
- mDragOrigin
.y
;
218 if ( !pane
.IsHorizontal() )
220 delta
= pos
.x
- mDragOrigin
.x
;
223 realHndOfs
= pane
.mBoundsInParent
.y
+ pane
.mTopMargin
+ mHandleOfs
;
225 int newY
= realHndOfs
+ delta
;
227 if ( newY
+ resizeHndSize
> mHandleDragArea
.y
+ mHandleDragArea
.height
)
229 newY
= mHandleDragArea
.y
+ mHandleDragArea
.height
- 1;
231 if ( newY
< mHandleDragArea
.y
)
233 newY
= mHandleDragArea
.y
;
235 mDraggedDelta
= newY
- realHndOfs
;
237 dc
.DrawRectangle( mHandleDragArea
.x
+ ofsX
, newY
+ ofsY
,
238 mHandleDragArea
.width
+ 1,
242 dc
.SetLogicalFunction( prevLF
);
244 // "End drawing on top (frees the window used for drawing
245 // over the screen)" --J.S.
246 wxScreenDC::EndDrawingOnTop();
249 void cbPaneDrawPlugin::OnMouseMove( cbMotionEvent
& event
)
251 if ( !mResizeStarted
)
253 // if nothing is started, do hit-tests
255 bool prevWasRowHandle
= mRowHandleHitted
;
257 mBarContentHitted
= FALSE
;
258 mBarHandleHitted
= FALSE
;
259 mRowHandleHitted
= FALSE
;
262 event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
266 if ( testResult
!= CB_NO_ITEMS_HITTED
)
268 if ( testResult
== CB_BAR_CONTENT_HITTED
)
270 // restore cursor, if non of the handles were hit
271 if ( mResizeCursorOn
)
273 // remove resizing hints
275 mpLayout
->ReleaseEventsFromPane( event
.mpPane
);
276 mpLayout
->ReleaseEventsFromPlugin( this );
278 mResizeCursorOn
= FALSE
;
280 mBarContentHitted
= TRUE
;
282 // In Windows, at least, the frame needs to have a null cursor
283 // else child windows (such as text windows) inherit the cursor
285 mpLayout
->GetParentFrame().SetCursor( wxNullCursor
);
287 mpLayout
->GetParentFrame().SetCursor( *mpLayout
->mpNormalCursor
);
291 // TBD:: fire something like "mouse-over-bar" event
293 event
.Skip(); // pass event to the next handler in the chain
297 wxCursor
* pCurs
= NULL
;
299 if ( testResult
== CB_UPPER_ROW_HANDLE_HITTED
||
300 testResult
== CB_LOWER_ROW_HANDLE_HITTED
)
302 if ( event
.mpPane
->IsHorizontal() )
304 pCurs
= mpLayout
->mpVertCursor
;
306 pCurs
= mpLayout
->mpHorizCursor
;
308 mRowHandleHitted
= TRUE
;
309 mIsUpperHandle
= ( testResult
== CB_UPPER_ROW_HANDLE_HITTED
);
313 // otherwise, if inter-bar handle was hitted
315 if ( event
.mpPane
->IsHorizontal() )
317 pCurs
= mpLayout
->mpHorizCursor
;
319 pCurs
= mpLayout
->mpVertCursor
;
321 mBarHandleHitted
= TRUE
;
322 mIsLeftHandle
= ( testResult
== CB_LEFT_BAR_HANDLE_HITTED
);
325 // avoid setting the same cursor twice
327 if ( !mResizeCursorOn
|| prevWasRowHandle
!= mRowHandleHitted
)
329 if ( !mResizeCursorOn
)
331 // caputre if not captured yet
332 mpLayout
->CaptureEventsForPane( event
.mpPane
);
333 mpLayout
->CaptureEventsForPlugin( this );
336 mpLayout
->GetParentFrame().SetCursor( *pCurs
);
339 mResizeCursorOn
= TRUE
;
341 // handled is being dragged now, thus event is "eaten" by this plugin
345 } // end of if (HitTestBarHandles())
347 // restore cursor, if non of the handles were hit
348 if ( mResizeCursorOn
)
350 mpLayout
->ReleaseEventsFromPane( event
.mpPane
);
351 mpLayout
->ReleaseEventsFromPlugin( this );
353 // In Windows, at least, the frame needs to have a null cursor
354 // else child windows (such as text windows) inherit the cursor
356 mpLayout
->GetParentFrame().SetCursor( wxNullCursor
);
358 mpLayout
->GetParentFrame().SetCursor( *mpLayout
->mpNormalCursor
);
361 mResizeCursorOn
= FALSE
;
364 event
.Skip(); // pass event to the next plugin
367 // othewise series of actions, if something has already started
370 if ( mResizeStarted
)
372 // apply xor-mask twice
373 DrawDraggedHandle( mPrevPos
, *event
.mpPane
);
375 // draw handle in the new position
376 DrawDraggedHandle( event
.mPos
, *event
.mpPane
);
377 mPrevPos
= event
.mPos
;
379 // handled is dragged, thus event is "eaten" by this plugin
382 event
.Skip(); // pass event to the next plugin
385 void cbPaneDrawPlugin::OnLDblClick( cbLeftDClickEvent
& event
)
387 if ( !mResizeCursorOn
)
389 cbBarInfo
* pBarToFloat
;
391 if ( event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
393 &pBarToFloat
) == CB_BAR_CONTENT_HITTED
403 void cbPaneDrawPlugin::OnLButtonDown( cbLeftDownEvent
& event
)
405 wxASSERT( !mResizeStarted
);
407 if ( mResizeCursorOn
)
409 mResizeStarted
= TRUE
;
410 mDragOrigin
= event
.mPos
;
412 // setup constraints for the dragging handle
416 mHandleIsVertical
= FALSE
;
418 if ( mRowHandleHitted
)
420 event
.mpPane
->GetRowResizeRange( mpResizedRow
, &from
, &till
, mIsUpperHandle
);
422 // otherwise if bar handle was hitted
423 event
.mpPane
->GetBarResizeRange( mpDraggedBar
, &from
, &till
, mIsLeftHandle
);
425 if ( mRowHandleHitted
)
427 mHandleIsVertical
= ( event
.mpPane
->IsHorizontal() ) ? FALSE
: TRUE
;
429 mHandleDragArea
.x
= 0;
430 mHandleDragArea
.width
= event
.mpPane
->mPaneWidth
;
432 mHandleDragArea
.y
= from
;
433 mHandleDragArea
.height
= till
- from
;
435 if ( mIsUpperHandle
)
437 mHandleOfs
= mpResizedRow
->mRowY
;
439 mHandleOfs
= mpResizedRow
->mRowY
+
440 mpResizedRow
->mRowHeight
-
441 event
.mpPane
->mProps
.mResizeHandleSize
;
445 // otehrwise if bar handle dragged
447 // cbRowInfo& rowInfo = *mpDraggedBar->mpRow;
448 wxRect
& bounds
= mpDraggedBar
->mBounds
;
450 mHandleIsVertical
= ( event
.mpPane
->IsHorizontal() ) ? TRUE
: FALSE
;
452 mHandleDragArea
.x
= from
;
453 mHandleDragArea
.width
= till
- from
;
456 mHandleDragArea
.y
= bounds
.y
;
457 mHandleDragArea
.height
= bounds
.height
;
459 // left-side-handle mBounds
462 mHandleOfs
= bounds
.x
;
464 mHandleOfs
= bounds
.x
+
465 bounds
.width
- event
.mpPane
->mProps
.mResizeHandleSize
;
469 event
.mpPane
->PaneToFrame( &mHandleDragArea
);
470 DrawDraggedHandle(mDragOrigin
, *event
.mpPane
);
472 mPrevPos
= mDragOrigin
;
475 // handled is dragged, thus event is "eaten" by this plugin
479 cbBarInfo
* pDraggedBar
;
481 if ( event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
483 &pDraggedBar
) == CB_BAR_CONTENT_HITTED
486 int x
= event
.mPos
.x
,
489 event
.mpPane
->PaneToFrame( &x
, &y
);
491 cbStartBarDraggingEvent
dragEvt( pDraggedBar
, wxPoint(x
,y
), event
.mpPane
);
493 mpLayout
->FirePluginEvent( dragEvt
);
495 return; // event is "eaten" by this plugin
499 event
.Skip(); // pass event to the next plugin in the chain
502 void cbPaneDrawPlugin::OnLButtonUp( cbLeftUpEvent
& event
)
504 if ( mResizeStarted
)
506 DrawDraggedHandle( event
.mPos
, *event
.mpPane
);
508 mResizeStarted
= FALSE
;
509 mResizeCursorOn
= FALSE
;
511 mpLayout
->ReleaseEventsFromPane( event
.mpPane
);
512 mpLayout
->ReleaseEventsFromPlugin( this );
514 // In Windows, at least, the frame needs to have a null cursor
515 // else child windows (such as text windows) inherit the cursor
517 mpLayout
->GetParentFrame().SetCursor( wxNullCursor
);
519 mpLayout
->GetParentFrame().SetCursor( *mpLayout
->mpNormalCursor
);
522 if ( mRowHandleHitted
)
524 event
.mpPane
->ResizeRow( mpResizedRow
,
530 event
.mpPane
->ResizeBar( mpDraggedBar
,
538 // handled dragging action was finished by this mouse-up,
539 // thus event is "eaten" by this plugin
544 event
.Skip(); // pass event to the next plugin
547 void cbPaneDrawPlugin::OnRButtonUp( cbRightUpEvent
& event
)
549 wxPoint fpos
= event
.mPos
;
550 event
.mpPane
->PaneToFrame( &fpos
.x
, &fpos
.y
);
552 cbBarInfo
* pDraggedBar
;
554 // user clicks inside the bar contnet, fire bar-customization event
556 if ( event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
558 &pDraggedBar
) == CB_BAR_CONTENT_HITTED
561 cbCustomizeBarEvent
cbEvt( pDraggedBar
, fpos
, event
.mpPane
);
563 mpLayout
->FirePluginEvent( cbEvt
);
565 return; // event is "eaten" by this plugin
568 // otherwise fire whole-layout customization event
570 cbCustomizeLayoutEvent
csEvt( fpos
);
572 mpLayout
->FirePluginEvent( csEvt
);
574 // event is "eaten" by this plugin
577 void cbPaneDrawPlugin::OnSizeBarWindow( cbSizeBarWndEvent
& event
)
579 cbBarInfo
& bar
= *event
.mpBar
;
580 mpPane
= event
.mpPane
;
582 // it's possible that a bar does not have it's own window!
583 if ( !bar
.mpBarWnd
) return;
585 wxRect
& bounds
= event
.mBoundsInParent
;
588 if ( bounds
.height
!= 0 )
590 // size smaller than bounds, to leave space for shade lines
594 int nNewHeight
= bounds
.height
- 2 - bar
.mDimInfo
.mVertGap
*2;
598 bar
.mpBarWnd
->wxWindow::SetSize( bounds
.x
+ 1 + bar
.mDimInfo
.mHorizGap
,
599 bounds
.y
+ 1 + bar
.mDimInfo
.mVertGap
,
600 bounds
.width
- 2 - bar
.mDimInfo
.mHorizGap
*2,
605 if ( !bar
.mpBarWnd
->IsShown() )
607 bar
.mpBarWnd
->Show( TRUE
);
610 // hide bar if not visible
611 bar
.mpBarWnd
->Show( FALSE
);
613 event
.Skip(); // pass event to the next plugin in the chain
616 void cbPaneDrawPlugin::OnDrawRowDecorations( cbDrawRowDecorEvent
& event
)
618 DrawPaneShadeForRow( event
.mpRow
, *event
.mpDc
);
620 event
.Skip(); // pass event to the next plugin
623 void cbPaneDrawPlugin::DrawUpperRowHandle( cbRowInfo
* pRow
, wxDC
& dc
)
625 wxRect
& bounds
= pRow
->mBoundsInParent
;
627 if ( mpPane
->IsHorizontal() )
629 if ( pRow
->mHasUpperHandle
)
631 mpPane
->DrawHorizHandle( dc
, bounds
.x
,
637 if ( pRow
->mHasUpperHandle
)
639 mpPane
->DrawVertHandle( dc
, bounds
.x
-1,
640 bounds
.y
, pRow
->mRowWidth
);
644 void cbPaneDrawPlugin::DrawLowerRowHandle( cbRowInfo
* pRow
, wxDC
& dc
)
646 wxRect
& bounds
= pRow
->mBoundsInParent
;
648 // check if iter-row handles present
650 if ( mpPane
->IsHorizontal() )
652 if ( pRow
->mHasLowerHandle
)
654 mpPane
->DrawHorizHandle( dc
, bounds
.x
, bounds
.y
+ bounds
.height
- mpPane
->mProps
.mResizeHandleSize
- 1,
659 if ( pRow
->mHasLowerHandle
)
661 mpPane
->DrawVertHandle( dc
, bounds
.x
+ bounds
.width
- mpPane
->mProps
.mResizeHandleSize
- 1,
662 bounds
.y
, pRow
->mRowWidth
);
666 void cbPaneDrawPlugin::OnDrawRowHandles( cbDrawRowHandlesEvent
& event
)
669 cbRowInfo
* pRow
= event
.mpRow
;
670 wxDC
& dc
= *event
.mpDc
;
671 mpPane
= event
.mpPane
;
673 // draw handles of surrounding rows first
675 if ( pRow
->mpPrev
&& pRow
->mpPrev
->mHasLowerHandle
)
677 DrawLowerRowHandle( pRow
->mpPrev
, dc
);
679 if ( pRow
->mpNext
&& pRow
->mpNext
->mHasUpperHandle
)
681 DrawUpperRowHandle( pRow
->mpNext
, dc
);
683 // draw handles of the given row
685 if ( pRow
->mHasUpperHandle
)
687 DrawUpperRowHandle( pRow
, dc
);
689 if ( pRow
->mHasLowerHandle
)
691 DrawLowerRowHandle( pRow
, dc
);
693 event
.Skip(); // pass event to the next plugin
696 void cbPaneDrawPlugin::OnDrawPaneBackground ( cbDrawPaneBkGroundEvent
& event
)
698 wxDC
& dc
= *event
.mpDc
;
699 mpPane
= event
.mpPane
;
701 // FOR NOW:: hard-coded
702 wxBrush
bkBrush( mpLayout
->mBorderPen
.GetColour(), wxSOLID
);
704 dc
.SetBrush( bkBrush
);
705 dc
.SetPen( mpLayout
->mNullPen
);
707 wxRect
& bounds
= mpPane
->mBoundsInParent
;
709 if ( mpPane
->mTopMargin
>= 1 )
711 dc
.DrawRectangle( bounds
.x
, bounds
.y
,
713 mpPane
->mTopMargin
+ 1);
716 if ( mpPane
->mBottomMargin
>= 1 )
718 dc
.DrawRectangle( bounds
.x
,
719 bounds
.y
+ bounds
.height
- mpPane
->mBottomMargin
,
721 mpPane
->mBottomMargin
+ 1);
724 if ( mpPane
->mLeftMargin
>= 1 )
726 dc
.DrawRectangle( bounds
.x
,
727 bounds
.y
+ mpPane
->mTopMargin
- 1,
728 mpPane
->mLeftMargin
+ 1,
729 bounds
.height
- mpPane
->mTopMargin
- mpPane
->mBottomMargin
+ 2);
732 if ( mpPane
->mRightMargin
>= 1 )
734 dc
.DrawRectangle( bounds
.x
+ bounds
.width
- mpPane
->mRightMargin
,
735 bounds
.y
+ mpPane
->mTopMargin
- 1,
736 mpPane
->mRightMargin
+ 1,
737 bounds
.height
- mpPane
->mTopMargin
- mpPane
->mBottomMargin
+ 2);
739 event
.Skip(); // pass event to the next plugin
742 void cbPaneDrawPlugin::OnDrawRowBackground ( cbDrawRowBkGroundEvent
& event
)
745 cbRowInfo
* pRow
= event
.mpRow
;
746 wxDC
& dc
= *event
.mpDc
;
747 mpPane
= event
.mpPane
;
750 wxRect rowBounds
= pRow
->mBoundsInParent
;
751 bool isHorizontal
= event
.mpPane
->IsHorizontal();
757 // prevPos = rowBounds.x;
758 // include one line above and below the row
760 rowBounds
.height
+= 2;
763 rowBounds
.width
+= 2;
767 // prevPos = rowBounds.y;
768 // include one line above and below the row
770 rowBounds
.width
+= 2;
773 rowBounds
.height
+= 2;
776 //#define TEST_BK_ERASING
778 #ifdef TEST_BK_ERASING
781 wxBrush
br0( wxColour(0,160,160), wxSOLID
);
783 dc
.SetPen ( mpLayout
->mNullPen
);
784 dc
.DrawRectangle( rowBounds
.x
, rowBounds
.y
,
786 rowBounds
.height
+ 1 );
789 wxBrush
bkBrush( mpLayout
->mGrayPen
.GetColour(), wxSOLID
);
791 dc
.SetPen ( mpLayout
->mNullPen
);
792 dc
.SetBrush( bkBrush
);
794 // fill background-recatangle of entire row area
795 dc
.DrawRectangle( rowBounds
.x
, rowBounds
.y
,
797 rowBounds
.height
+ 1 );
799 dc
.SetBrush( wxNullBrush
);
801 // draw "shaded-side-bars" for each bar
802 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
804 wxRect
& bounds
= pRow
->mBars
[i
]->mBoundsInParent
;
808 DrawShade( 1, bounds
, FL_ALIGN_LEFT
, dc
);
809 DrawShade( 1, bounds
, FL_ALIGN_RIGHT
, dc
);
813 DrawShade( 1, bounds
, FL_ALIGN_TOP
, dc
);
814 DrawShade( 1, bounds
, FL_ALIGN_BOTTOM
, dc
);
818 // draw extra shades to simulate "glued-bricks" effect
820 // TBD:: reduce exessive drawing of shades, when the
821 // row handle is present, and shades will be overr-drawn anyway
823 DrawUpperRowShades( pRow
, dc
, 1 ); // outer shade
827 DrawLowerRowShades( pRow
->mpPrev
, dc
, 1 ); // outter shade
828 DrawLowerRowShades( pRow
->mpPrev
, dc
, 0 ); // inner shade
831 DrawLowerRowShades( pRow
, dc
, 1 );
835 DrawUpperRowShades( pRow
->mpNext
, dc
, 1 );
836 DrawUpperRowShades( pRow
->mpNext
, dc
, 0 );
839 event
.Skip(); // pass event to the next plugin
842 void cbPaneDrawPlugin::DrawUpperRowShades( cbRowInfo
* pRow
, wxDC
& dc
, int level
)
844 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
846 wxRect
& bounds
= pRow
->mBars
[i
]->mBoundsInParent
;
848 if ( mpPane
->IsHorizontal() )
850 DrawShade( level
, bounds
, FL_ALIGN_TOP
, dc
);
853 dc
.SetPen( mpLayout
->mDarkPen
);
854 dc
.DrawPoint( bounds
.x
- 1, bounds
.y
);
855 dc
.SetPen( mpLayout
->mLightPen
);
856 dc
.DrawPoint( bounds
.x
+ bounds
.width
, bounds
.y
);
861 DrawShade( level
, bounds
, FL_ALIGN_LEFT
, dc
);
864 dc
.SetPen( mpLayout
->mDarkPen
);
865 dc
.DrawPoint( bounds
.x
, bounds
.y
-1 );
866 dc
.SetPen( mpLayout
->mLightPen
);
867 dc
.DrawPoint( bounds
.x
, bounds
.y
+ bounds
.height
);
873 void cbPaneDrawPlugin::DrawLowerRowShades( cbRowInfo
* pRow
, wxDC
& dc
, int level
)
875 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
877 wxRect
& bounds
= pRow
->mBars
[i
]->mBoundsInParent
;
879 if ( mpPane
->IsHorizontal() )
881 DrawShade( level
, bounds
, FL_ALIGN_BOTTOM
, dc
);
884 dc
.SetPen( mpLayout
->mDarkPen
);
885 dc
.DrawPoint( bounds
.x
- 1, bounds
.y
+ bounds
.height
-1 );
886 dc
.SetPen( mpLayout
->mLightPen
);
887 dc
.DrawPoint( bounds
.x
+ bounds
.width
, bounds
.y
+ bounds
.height
-1 );
892 DrawShade( level
, bounds
, FL_ALIGN_RIGHT
, dc
);
895 dc
.SetPen( mpLayout
->mDarkPen
);
896 dc
.DrawPoint( bounds
.x
+ bounds
.width
- 1, bounds
.y
-1 );
897 dc
.SetPen( mpLayout
->mLightPen
);
898 dc
.DrawPoint( bounds
.x
+ bounds
.width
- 1, bounds
.y
+ bounds
.height
);
904 void cbPaneDrawPlugin::DrawBarInnerShadeRect( cbBarInfo
* pBar
, wxDC
& dc
)
906 wxRect
& bounds
= pBar
->mBoundsInParent
;
908 dc
.SetPen( mpLayout
->mDarkPen
);
910 dc
.DrawLine( bounds
.x
+ bounds
.width
- 1,
912 bounds
.x
+ bounds
.width
- 1,
913 bounds
.y
+ bounds
.height
);
915 dc
.DrawLine( bounds
.x
,
916 bounds
.y
+ bounds
.height
- 1,
917 bounds
.x
+ bounds
.width
,
918 bounds
.y
+ bounds
.height
-1 );
920 dc
.SetPen( mpLayout
->mLightPen
);
922 dc
.DrawLine( bounds
.x
,
924 bounds
.x
+ bounds
.width
- 1,
927 dc
.DrawLine( bounds
.x
,
930 bounds
.y
+ bounds
.height
- 1 );
933 void cbPaneDrawPlugin::DrawShade( int level
, wxRect
& rect
, int alignment
, wxDC
& dc
)
935 // simulates "guled-bricks" appearence of control bars
937 if ( ( alignment
== FL_ALIGN_TOP
&& level
== 1 ) ||
938 ( alignment
== FL_ALIGN_BOTTOM
&& level
== 0 ) ||
939 ( alignment
== FL_ALIGN_LEFT
&& level
== 1 ) ||
940 ( alignment
== FL_ALIGN_RIGHT
&& level
== 0 )
943 dc
.SetPen( mpLayout
->mDarkPen
);
945 dc
.SetPen( mpLayout
->mLightPen
);
947 if ( alignment
== FL_ALIGN_TOP
)
953 rect
.x
+ rect
.width
- 1,
956 dc
.DrawLine( rect
.x
- 1,
958 rect
.x
+ rect
.width
+ 0,
962 if ( alignment
== FL_ALIGN_BOTTOM
)
967 rect
.y
+ rect
.height
- 1,
969 rect
.y
+ rect
.height
- 1 );
971 dc
.DrawLine( rect
.x
- 1,
972 rect
.y
+ rect
.height
,
973 rect
.x
+ rect
.width
+ 1,
974 rect
.y
+ rect
.height
);
977 if ( alignment
== FL_ALIGN_LEFT
)
984 rect
.y
+ rect
.height
- 1 );
986 dc
.DrawLine( rect
.x
- 1,
989 rect
.y
+ rect
.height
);
992 if ( alignment
== FL_ALIGN_RIGHT
)
996 dc
.DrawLine( rect
.x
+ rect
.width
- 1,
998 rect
.x
+ rect
.width
- 1,
999 rect
.y
+ rect
.height
);
1002 dc
.DrawLine( rect
.x
+ rect
.width
,
1004 rect
.x
+ rect
.width
,
1005 rect
.y
+ rect
.height
+ 1 );
1010 void cbPaneDrawPlugin::DrawShade1( int level
, wxRect
& rect
, int alignment
, wxDC
& dc
)
1012 // simulates "guled-bricks" appearence of control bars
1014 if ( ( alignment
== FL_ALIGN_TOP
&& level
== 1 ) ||
1015 ( alignment
== FL_ALIGN_BOTTOM
&& level
== 0 ) ||
1016 ( alignment
== FL_ALIGN_LEFT
&& level
== 1 ) ||
1017 ( alignment
== FL_ALIGN_RIGHT
&& level
== 0 )
1020 dc
.SetPen( mpLayout
->mDarkPen
);
1022 dc
.SetPen( mpLayout
->mLightPen
);
1024 if ( alignment
== FL_ALIGN_TOP
)
1028 dc
.DrawLine( rect
.x
,
1030 rect
.x
+ rect
.width
,
1033 dc
.DrawLine( rect
.x
,
1035 rect
.x
+ rect
.width
,
1039 if ( alignment
== FL_ALIGN_BOTTOM
)
1043 dc
.DrawLine( rect
.x
,
1044 rect
.y
+ rect
.height
- 1,
1045 rect
.x
+ rect
.width
,
1046 rect
.y
+ rect
.height
- 1 );
1048 dc
.DrawLine( rect
.x
,
1049 rect
.y
+ rect
.height
,
1050 rect
.x
+ rect
.width
,
1051 rect
.y
+ rect
.height
);
1054 if ( alignment
== FL_ALIGN_LEFT
)
1058 dc
.DrawLine( rect
.x
,
1061 rect
.y
+ rect
.height
);
1063 dc
.DrawLine( rect
.x
- 1,
1066 rect
.y
+ rect
.height
);
1069 if ( alignment
== FL_ALIGN_RIGHT
)
1073 dc
.DrawLine( rect
.x
+ rect
.width
- 1,
1075 rect
.x
+ rect
.width
- 1,
1076 rect
.y
+ rect
.height
);
1079 dc
.DrawLine( rect
.x
+ rect
.width
,
1081 rect
.x
+ rect
.width
,
1082 rect
.y
+ rect
.height
);
1087 void cbPaneDrawPlugin::DrawPaneShade( wxDC
& dc
, int alignment
)
1089 if ( !mpPane
->mProps
.mShow3DPaneBorderOn
) return;
1091 wxRect bounds
= mpPane
->mBoundsInParent
;
1093 bounds
.x
+= mpPane
->mLeftMargin
;
1094 bounds
.y
+= mpPane
->mTopMargin
;
1095 bounds
.width
-= ( mpPane
->mLeftMargin
+ mpPane
->mRightMargin
);
1096 bounds
.height
-= ( mpPane
->mTopMargin
+ mpPane
->mBottomMargin
);
1098 DrawShade( 0, bounds
, alignment
, dc
);
1099 DrawShade( 1, bounds
, alignment
, dc
);
1102 void cbPaneDrawPlugin::DrawPaneShadeForRow( cbRowInfo
* pRow
, wxDC
& dc
)
1104 if ( !mpPane
->mProps
.mShow3DPaneBorderOn
) return;
1106 // do not draw decoration, if pane has "vainished"
1107 if ( mpPane
->mPaneWidth
< 0 ||
1108 mpPane
->mPaneHeight
< 0 )
1112 wxRect bounds
= pRow
->mBoundsInParent
;
1114 if ( mpPane
->mAlignment
== FL_ALIGN_TOP
||
1115 mpPane
->mAlignment
== FL_ALIGN_BOTTOM
)
1120 DrawShade1( 0, bounds
, FL_ALIGN_LEFT
, dc
);
1121 DrawShade1( 1, bounds
, FL_ALIGN_LEFT
, dc
);
1122 DrawShade1( 0, bounds
, FL_ALIGN_RIGHT
, dc
);
1123 DrawShade1( 1, bounds
, FL_ALIGN_RIGHT
, dc
);
1125 if ( !pRow
->mpNext
)
1126 DrawPaneShade( dc
, FL_ALIGN_BOTTOM
);
1128 if ( !pRow
->mpPrev
)
1129 DrawPaneShade( dc
, FL_ALIGN_TOP
);
1136 DrawShade1( 0, bounds
, FL_ALIGN_TOP
, dc
);
1137 DrawShade1( 1, bounds
, FL_ALIGN_TOP
, dc
);
1138 DrawShade1( 0, bounds
, FL_ALIGN_BOTTOM
, dc
);
1139 DrawShade1( 1, bounds
, FL_ALIGN_BOTTOM
, dc
);
1141 if ( !pRow
->mpNext
)
1142 DrawPaneShade( dc
, FL_ALIGN_RIGHT
);
1144 if ( !pRow
->mpPrev
)
1145 DrawPaneShade( dc
, FL_ALIGN_LEFT
);
1149 void cbPaneDrawPlugin::OnDrawPaneDecorations( cbDrawPaneDecorEvent
& event
)
1151 wxDC
& dc
= *event
.mpDc
;
1153 cbDockPane
* pPane
= event
.mpPane
;
1155 RowArrayT
& lst
= pPane
->GetRowList();
1157 // FIXME:: this is a workaround for some glitches
1161 cbRowInfo
* pLastRow
= lst
[ lst
.Count() - 1 ];
1163 pPane
->PaintRowBackground( pLastRow
, dc
);
1164 pPane
->PaintRowDecorations( pLastRow
, dc
);
1165 pPane
->PaintRowHandles( pLastRow
, dc
);
1168 if ( !pPane
->mProps
.mShow3DPaneBorderOn
) return;
1170 // do not draw decoration, if pane is completely hidden
1171 if ( event
.mpPane
->mPaneWidth
< 0 ||
1172 event
.mpPane
->mPaneHeight
< 0 )
1176 DrawPaneShade( dc
, FL_ALIGN_TOP
);
1177 DrawPaneShade( dc
, FL_ALIGN_BOTTOM
);
1178 DrawPaneShade( dc
, FL_ALIGN_LEFT
);
1179 DrawPaneShade( dc
, FL_ALIGN_RIGHT
);
1181 event
.Skip(); // pass event to the next plugin
1184 // bar decoration/sizing handlers
1186 void cbPaneDrawPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent
& event
)
1188 // cbBarInfo* pBar = event.mpBar;
1189 wxDC
& dc
= *event
.mpDc
;
1191 // draw brick borders
1193 wxRect
& rect
= event
.mBoundsInParent
;
1195 dc
.SetPen( mpLayout
->mLightPen
);
1198 dc
.DrawLine( rect
.x
, rect
.y
,
1199 rect
.x
+ rect
.width
-1, rect
.y
);
1202 dc
.DrawLine( rect
.x
, rect
.y
,
1203 rect
.x
, rect
.y
+ rect
.height
-1 );
1206 dc
.SetPen( mpLayout
->mDarkPen
);
1209 dc
.DrawLine( rect
.x
+ rect
.width
-1, rect
.y
,
1210 rect
.x
+ rect
.width
-1, rect
.y
+ rect
.height
-1 );
1213 dc
.DrawLine( rect
.x
, rect
.y
+ rect
.height
-1,
1214 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
-1 );
1216 event
.Skip(); // pass event to the next plugin
1219 void cbPaneDrawPlugin::OnDrawBarHandles( cbDrawBarHandlesEvent
& event
)
1222 cbBarInfo
* pBar
= event
.mpBar
;
1223 wxDC
& dc
= *event
.mpDc
;
1224 mpPane
= event
.mpPane
;
1226 // draw handles around the bar if present
1228 if ( pBar
->mHasLeftHandle
||
1229 pBar
->mHasRightHandle
)
1231 wxRect
& bounds
= pBar
->mBoundsInParent
;
1233 if ( mpPane
->IsHorizontal() )
1235 if ( pBar
->mHasLeftHandle
)
1237 mpPane
->DrawVertHandle( dc
, bounds
.x
- mpPane
->mProps
.mResizeHandleSize
-1,
1238 bounds
.y
, bounds
.height
);
1240 if ( pBar
->mHasRightHandle
)
1242 mpPane
->DrawVertHandle( dc
,
1243 bounds
.x
+ bounds
.width
-1,
1244 bounds
.y
, bounds
.height
);
1248 if ( pBar
->mHasLeftHandle
)
1250 mpPane
->DrawHorizHandle( dc
, bounds
.x
,
1251 bounds
.y
- mpPane
->mProps
.mResizeHandleSize
- 1,
1254 if ( pBar
->mHasRightHandle
)
1256 mpPane
->DrawHorizHandle( dc
, bounds
.x
,
1257 bounds
.y
+ bounds
.height
- 1,
1262 event
.Skip(); // pass event to the next plugin
1265 void cbPaneDrawPlugin::OnStartDrawInArea( cbStartDrawInAreaEvent
& event
)
1268 wxASSERT( mpClntDc
== NULL
);
1270 // FOR NOW:: create/destroy client-dc upon each drawing
1271 mpClntDc
= new wxClientDC( &mpLayout
->GetParentFrame() );
1273 (*event
.mppDc
) = mpClntDc
;
1275 mpClntDc
->SetClippingRegion( event
.mArea
.x
, event
.mArea
.y
,
1276 event
.mArea
.width
, event
.mArea
.height
);
1279 void cbPaneDrawPlugin::OnFinishDrawInArea( cbFinishDrawInAreaEvent
& event
)
1282 wxASSERT( mpClntDc
);