1 /////////////////////////////////////////////////////////////////////////////
2 // Name: panedrawpl.cpp
3 // Purpose: cbPaneDrawPlugin implementation.
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
26 #include "wx/utils.h" // import wxMin,wxMax macros
28 #include "wx/fl/panedrawpl.h"
30 // bitmap bits used by bar-resizing brush
32 #define _IMG_A 0xAA // Note: modified from _A to _IMG_A, _A was already defined (cygwin)
33 #define _IMG_B 0x00 // Note: modified from _B to _IMG_A, _B was already defined (cygwin)
34 #define _IMG_C 0x55 // Note: modified from _C to _IMG_C, for consistency reasons.
35 #define _IMG_D 0x00 // Note: modified from _D to _IMG_D, for consistency reasons.
37 static const unsigned char _gCheckerImg
[16] = { _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
38 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
39 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
,
40 _IMG_A
,_IMG_B
,_IMG_C
,_IMG_D
43 // FIXME:: The below code somehow doesn't work - cursors remain unchanged
44 // Used: controlbar.cpp(1268): set_cursor_bits( _gHorizCursorImg, bits, 32, 16 );
45 // Used: controlbar.cpp(1272): set_cursor_bits( _gVertCursorImg, bits, 32, 16 );
47 static void set_cursor_bits( const char** img, char* bits, int width, int height )
49 for( int i = 0; i != (width*height)/8; ++i )
52 for( int y = 0; y != height; ++y )
54 const char* row = img[0];
56 for( int x = 0; x != width; ++x )
58 int bitNo = y*width + x;
60 char value = ( row[x] != '.' ) ? 1 : 0;
62 bits[ bitNo / sizeof(char) ] |=
63 ( ( bitNo %sizeof(char) ) << value );
71 /***** Implementation for class cbPaneDrawPlugin *****/
73 IMPLEMENT_DYNAMIC_CLASS( cbPaneDrawPlugin
, cbPluginBase
)
75 BEGIN_EVENT_TABLE( cbPaneDrawPlugin
, cbPluginBase
)
77 EVT_PL_LEFT_DOWN ( cbPaneDrawPlugin::OnLButtonDown
)
78 EVT_PL_LEFT_UP ( cbPaneDrawPlugin::OnLButtonUp
)
79 // EVT_PL_LEFT_DCLICK ( cbPaneDrawPlugin::OnLDblClick )
80 EVT_PL_RIGHT_UP ( cbPaneDrawPlugin::OnRButtonUp
)
81 EVT_PL_MOTION ( cbPaneDrawPlugin::OnMouseMove
)
84 EVT_PL_DRAW_PANE_BKGROUND ( cbPaneDrawPlugin::OnDrawPaneBackground
)
85 EVT_PL_DRAW_PANE_DECOR ( cbPaneDrawPlugin::OnDrawPaneDecorations
)
87 EVT_PL_DRAW_ROW_DECOR ( cbPaneDrawPlugin::OnDrawRowDecorations
)
88 EVT_PL_DRAW_ROW_HANDLES ( cbPaneDrawPlugin::OnDrawRowHandles
)
89 EVT_PL_DRAW_ROW_BKGROUND ( cbPaneDrawPlugin::OnDrawRowBackground
)
91 EVT_PL_SIZE_BAR_WND ( cbPaneDrawPlugin::OnSizeBarWindow
)
92 EVT_PL_DRAW_BAR_DECOR ( cbPaneDrawPlugin::OnDrawBarDecorations
)
93 EVT_PL_DRAW_BAR_HANDLES ( cbPaneDrawPlugin::OnDrawBarHandles
)
95 EVT_PL_START_DRAW_IN_AREA ( cbPaneDrawPlugin::OnStartDrawInArea
)
96 EVT_PL_FINISH_DRAW_IN_AREA ( cbPaneDrawPlugin::OnFinishDrawInArea
)
100 cbPaneDrawPlugin::cbPaneDrawPlugin(void)
102 : mResizeStarted ( false ),
104 mResizeCursorOn ( false ),
105 mpDraggedBar ( NULL
),
106 mpResizedRow ( NULL
),
108 mRowHandleHitted ( false ),
109 mIsUpperHandle ( false ),
110 mBarHandleHitted ( false ),
111 mIsLeftHandle ( false ),
112 mBarContentHitted ( false ),
118 cbPaneDrawPlugin::cbPaneDrawPlugin( wxFrameLayout
* pPanel
, int paneMask
)
120 : cbPluginBase( pPanel
, paneMask
),
122 // bar-row resizing state varaibles
124 mResizeStarted ( false ),
126 mResizeCursorOn ( false ),
127 mpDraggedBar ( NULL
),
128 mpResizedRow ( NULL
),
130 mRowHandleHitted ( false ),
131 mIsUpperHandle ( false ),
132 mBarHandleHitted ( false ),
133 mIsLeftHandle ( false ),
134 mBarContentHitted ( false ),
140 cbPaneDrawPlugin::~cbPaneDrawPlugin()
143 wxASSERT( mpClntDc
== NULL
);
146 void cbPaneDrawPlugin::DrawDraggedHandle( const wxPoint
& pos
, cbDockPane
& pane
)
153 pane
.PaneToFrame( &fpos
.x
, &fpos
.y
);
156 int resizeHndSize
= pane
.mProps
.mResizeHandleSize
;
158 // "Required for X to specify that
159 // that we wish to draw on top of all windows
160 // - and we optimise by specifying the area
161 // for creating the overlap window." --J.S.
163 wxScreenDC::StartDrawingOnTop(&mpLayout
->GetParentFrame());
165 mpLayout
->GetParentFrame().ClientToScreen( &ofsX
, &ofsY
);
167 int prevLF
= dc
.GetLogicalFunction();
169 // BUG BUG BUG (wx):: somehow stippled brush works only
170 // when the bitmap created on stack, not
171 // as a member of the class
173 wxBitmap
checker( (const char*)_gCheckerImg
, 8,8 );
175 wxBrush
checkerBrush( checker
);
177 dc
.SetPen( mpLayout
->mNullPen
);
178 dc
.SetBrush( checkerBrush
);
179 dc
.SetLogicalFunction( wxXOR
);
181 if ( mHandleIsVertical
)
183 int delta
= pos
.x
- mDragOrigin
.x
;
185 if ( !pane
.IsHorizontal() )
187 delta
= pos
.y
- mDragOrigin
.y
;
190 realHndOfs
= pane
.mBoundsInParent
.x
+ pane
.mLeftMargin
+ mHandleOfs
;
192 int newX
= realHndOfs
+ delta
;
194 if ( newX
+ resizeHndSize
> mHandleDragArea
.x
+ mHandleDragArea
.width
)
196 newX
= mHandleDragArea
.x
+ mHandleDragArea
.width
- 1;
198 if ( newX
< mHandleDragArea
.x
)
200 newX
= mHandleDragArea
.x
;
202 mDraggedDelta
= newX
- realHndOfs
;
204 dc
.DrawRectangle( newX
+ ofsX
, mHandleDragArea
.y
+ ofsY
,
206 mHandleDragArea
.height
+1 );
210 // otherwise, draw horizontal handle
212 int delta
= pos
.y
- mDragOrigin
.y
;
214 if ( !pane
.IsHorizontal() )
216 delta
= pos
.x
- mDragOrigin
.x
;
219 realHndOfs
= pane
.mBoundsInParent
.y
+ pane
.mTopMargin
+ mHandleOfs
;
221 int newY
= realHndOfs
+ delta
;
223 if ( newY
+ resizeHndSize
> mHandleDragArea
.y
+ mHandleDragArea
.height
)
225 newY
= mHandleDragArea
.y
+ mHandleDragArea
.height
- 1;
227 if ( newY
< mHandleDragArea
.y
)
229 newY
= mHandleDragArea
.y
;
231 mDraggedDelta
= newY
- realHndOfs
;
233 dc
.DrawRectangle( mHandleDragArea
.x
+ ofsX
, newY
+ ofsY
,
234 mHandleDragArea
.width
+ 1,
238 dc
.SetLogicalFunction( prevLF
);
240 // "End drawing on top (frees the window used for drawing
241 // over the screen)" --J.S.
242 wxScreenDC::EndDrawingOnTop();
245 void cbPaneDrawPlugin::OnMouseMove( cbMotionEvent
& event
)
247 if ( !mResizeStarted
)
249 // if nothing is started, do hit-tests
251 bool prevWasRowHandle
= mRowHandleHitted
;
253 mBarContentHitted
= false;
254 mBarHandleHitted
= false;
255 mRowHandleHitted
= false;
258 event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
262 if ( testResult
!= CB_NO_ITEMS_HITTED
)
264 if ( testResult
== CB_BAR_CONTENT_HITTED
)
266 // restore cursor, if non of the handles were hit
267 if ( mResizeCursorOn
)
269 // remove resizing hints
271 mpLayout
->ReleaseEventsFromPane( event
.mpPane
);
272 mpLayout
->ReleaseEventsFromPlugin( this );
274 mResizeCursorOn
= false;
276 mBarContentHitted
= true;
278 // In Windows, at least, the frame needs to have a null cursor
279 // else child windows (such as text windows) inherit the cursor
281 mpLayout
->GetParentFrame().SetCursor( wxNullCursor
);
283 mpLayout
->GetParentFrame().SetCursor( *mpLayout
->mpNormalCursor
);
287 // TBD:: fire something like "mouse-over-bar" event
289 event
.Skip(); // pass event to the next handler in the chain
295 if ( testResult
== CB_UPPER_ROW_HANDLE_HITTED
||
296 testResult
== CB_LOWER_ROW_HANDLE_HITTED
)
298 if ( event
.mpPane
->IsHorizontal() )
300 pCurs
= mpLayout
->mpVertCursor
;
302 pCurs
= mpLayout
->mpHorizCursor
;
304 mRowHandleHitted
= true;
305 mIsUpperHandle
= ( testResult
== CB_UPPER_ROW_HANDLE_HITTED
);
309 // otherwise, if inter-bar handle was hitted
311 if ( event
.mpPane
->IsHorizontal() )
313 pCurs
= mpLayout
->mpHorizCursor
;
315 pCurs
= mpLayout
->mpVertCursor
;
317 mBarHandleHitted
= true;
318 mIsLeftHandle
= ( testResult
== CB_LEFT_BAR_HANDLE_HITTED
);
321 // avoid setting the same cursor twice
323 if ( !mResizeCursorOn
|| prevWasRowHandle
!= mRowHandleHitted
)
325 mpLayout
->GetParentFrame().SetCursor( *pCurs
);
327 if ( !mResizeCursorOn
)
329 // caputre if not captured yet
330 mpLayout
->CaptureEventsForPane( event
.mpPane
);
331 mpLayout
->CaptureEventsForPlugin( this );
335 mResizeCursorOn
= true;
337 // handled is being dragged now, thus event is "eaten" by this plugin
341 } // end of if (HitTestBarHandles())
343 // restore cursor, if non of the handles were hit
344 if ( mResizeCursorOn
)
346 mpLayout
->ReleaseEventsFromPane( event
.mpPane
);
347 mpLayout
->ReleaseEventsFromPlugin( this );
349 // In Windows, at least, the frame needs to have a null cursor
350 // else child windows (such as text windows) inherit the cursor
352 mpLayout
->GetParentFrame().SetCursor( wxNullCursor
);
354 mpLayout
->GetParentFrame().SetCursor( *mpLayout
->mpNormalCursor
);
357 mResizeCursorOn
= false;
360 event
.Skip(); // pass event to the next plugin
363 // othewise series of actions, if something has already started
366 if ( mResizeStarted
)
368 // apply xor-mask twice
369 DrawDraggedHandle( mPrevPos
, *event
.mpPane
);
371 // draw handle in the new position
372 DrawDraggedHandle( event
.mPos
, *event
.mpPane
);
373 mPrevPos
= event
.mPos
;
375 // handled is dragged, thus event is "eaten" by this plugin
378 event
.Skip(); // pass event to the next plugin
381 void cbPaneDrawPlugin::OnLDblClick( cbLeftDClickEvent
& event
)
383 if ( !mResizeCursorOn
)
385 cbBarInfo
* pBarToFloat
;
387 if ( event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
389 &pBarToFloat
) == CB_BAR_CONTENT_HITTED
399 void cbPaneDrawPlugin::OnLButtonDown( cbLeftDownEvent
& event
)
401 wxASSERT( !mResizeStarted
);
403 if ( mResizeCursorOn
)
405 mResizeStarted
= true;
406 mDragOrigin
= event
.mPos
;
408 // setup constraints for the dragging handle
412 mHandleIsVertical
= false;
414 if ( mRowHandleHitted
)
416 event
.mpPane
->GetRowResizeRange( mpResizedRow
, &from
, &till
, mIsUpperHandle
);
418 // otherwise if bar handle was hitted
419 event
.mpPane
->GetBarResizeRange( mpDraggedBar
, &from
, &till
, mIsLeftHandle
);
421 if ( mRowHandleHitted
)
423 mHandleIsVertical
= ( event
.mpPane
->IsHorizontal() ) ? false : true;
425 mHandleDragArea
.x
= 0;
426 mHandleDragArea
.width
= event
.mpPane
->mPaneWidth
;
428 mHandleDragArea
.y
= from
;
429 mHandleDragArea
.height
= till
- from
;
431 if ( mIsUpperHandle
)
433 mHandleOfs
= mpResizedRow
->mRowY
;
435 mHandleOfs
= mpResizedRow
->mRowY
+
436 mpResizedRow
->mRowHeight
-
437 event
.mpPane
->mProps
.mResizeHandleSize
;
441 // otehrwise if bar handle dragged
443 // cbRowInfo& rowInfo = *mpDraggedBar->mpRow;
444 wxRect
& bounds
= mpDraggedBar
->mBounds
;
446 mHandleIsVertical
= ( event
.mpPane
->IsHorizontal() ) ? true : false;
448 mHandleDragArea
.x
= from
;
449 mHandleDragArea
.width
= till
- from
;
452 mHandleDragArea
.y
= bounds
.y
;
453 mHandleDragArea
.height
= bounds
.height
;
455 // left-side-handle mBounds
458 mHandleOfs
= bounds
.x
;
460 mHandleOfs
= bounds
.x
+
461 bounds
.width
- event
.mpPane
->mProps
.mResizeHandleSize
;
465 event
.mpPane
->PaneToFrame( &mHandleDragArea
);
466 DrawDraggedHandle(mDragOrigin
, *event
.mpPane
);
468 mPrevPos
= mDragOrigin
;
471 // handled is dragged, thus event is "eaten" by this plugin
475 cbBarInfo
* pDraggedBar
;
477 if ( event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
479 &pDraggedBar
) == CB_BAR_CONTENT_HITTED
482 int x
= event
.mPos
.x
,
485 event
.mpPane
->PaneToFrame( &x
, &y
);
487 cbStartBarDraggingEvent
dragEvt( pDraggedBar
, wxPoint(x
,y
), event
.mpPane
);
489 mpLayout
->FirePluginEvent( dragEvt
);
491 return; // event is "eaten" by this plugin
495 event
.Skip(); // pass event to the next plugin in the chain
498 void cbPaneDrawPlugin::OnLButtonUp( cbLeftUpEvent
& event
)
500 if ( mResizeStarted
)
502 DrawDraggedHandle( event
.mPos
, *event
.mpPane
);
504 mResizeStarted
= false;
505 mResizeCursorOn
= false;
507 mpLayout
->ReleaseEventsFromPane( event
.mpPane
);
508 mpLayout
->ReleaseEventsFromPlugin( this );
510 // In Windows, at least, the frame needs to have a null cursor
511 // else child windows (such as text windows) inherit the cursor
513 mpLayout
->GetParentFrame().SetCursor( wxNullCursor
);
515 mpLayout
->GetParentFrame().SetCursor( *mpLayout
->mpNormalCursor
);
518 if ( mRowHandleHitted
)
520 event
.mpPane
->ResizeRow( mpResizedRow
,
526 event
.mpPane
->ResizeBar( mpDraggedBar
,
534 // handled dragging action was finished by this mouse-up,
535 // thus event is "eaten" by this plugin
540 event
.Skip(); // pass event to the next plugin
543 void cbPaneDrawPlugin::OnRButtonUp( cbRightUpEvent
& event
)
545 wxPoint fpos
= event
.mPos
;
546 event
.mpPane
->PaneToFrame( &fpos
.x
, &fpos
.y
);
548 cbBarInfo
* pDraggedBar
;
550 // user clicks inside the bar contnet, fire bar-customization event
552 if ( event
.mpPane
->HitTestPaneItems( event
.mPos
, // in pane's coordiantes
554 &pDraggedBar
) == CB_BAR_CONTENT_HITTED
557 cbCustomizeBarEvent
cbEvt( pDraggedBar
, fpos
, event
.mpPane
);
559 mpLayout
->FirePluginEvent( cbEvt
);
561 return; // event is "eaten" by this plugin
564 // otherwise fire whole-layout customization event
566 cbCustomizeLayoutEvent
csEvt( fpos
);
568 mpLayout
->FirePluginEvent( csEvt
);
570 // event is "eaten" by this plugin
573 void cbPaneDrawPlugin::OnSizeBarWindow( cbSizeBarWndEvent
& event
)
575 cbBarInfo
& bar
= *event
.mpBar
;
576 mpPane
= event
.mpPane
;
578 // it's possible that a bar does not have it's own window!
579 if ( !bar
.mpBarWnd
) return;
581 wxRect
& bounds
= event
.mBoundsInParent
;
584 if ( bounds
.height
!= 0 )
586 // size smaller than bounds, to leave space for shade lines
590 int nNewHeight
= bounds
.height
- 2 - bar
.mDimInfo
.mVertGap
*2;
594 bar
.mpBarWnd
->wxWindow::SetSize( bounds
.x
+ 1 + bar
.mDimInfo
.mHorizGap
,
595 bounds
.y
+ 1 + bar
.mDimInfo
.mVertGap
,
596 bounds
.width
- 2 - bar
.mDimInfo
.mHorizGap
*2,
601 if ( !bar
.mpBarWnd
->IsShown() )
603 bar
.mpBarWnd
->Show( true );
606 // hide bar if not visible
607 bar
.mpBarWnd
->Show( false );
609 event
.Skip(); // pass event to the next plugin in the chain
612 void cbPaneDrawPlugin::OnDrawRowDecorations( cbDrawRowDecorEvent
& event
)
614 DrawPaneShadeForRow( event
.mpRow
, *event
.mpDc
);
616 event
.Skip(); // pass event to the next plugin
619 void cbPaneDrawPlugin::DrawUpperRowHandle( cbRowInfo
* pRow
, wxDC
& dc
)
621 wxRect
& bounds
= pRow
->mBoundsInParent
;
623 if ( mpPane
->IsHorizontal() )
625 if ( pRow
->mHasUpperHandle
)
627 mpPane
->DrawHorizHandle( dc
, bounds
.x
,
633 if ( pRow
->mHasUpperHandle
)
635 mpPane
->DrawVertHandle( dc
, bounds
.x
-1,
636 bounds
.y
, pRow
->mRowWidth
);
640 void cbPaneDrawPlugin::DrawLowerRowHandle( cbRowInfo
* pRow
, wxDC
& dc
)
642 wxRect
& bounds
= pRow
->mBoundsInParent
;
644 // check if iter-row handles present
646 if ( mpPane
->IsHorizontal() )
648 if ( pRow
->mHasLowerHandle
)
650 mpPane
->DrawHorizHandle( dc
, bounds
.x
, bounds
.y
+ bounds
.height
- mpPane
->mProps
.mResizeHandleSize
- 1,
655 if ( pRow
->mHasLowerHandle
)
657 mpPane
->DrawVertHandle( dc
, bounds
.x
+ bounds
.width
- mpPane
->mProps
.mResizeHandleSize
- 1,
658 bounds
.y
, pRow
->mRowWidth
);
662 void cbPaneDrawPlugin::OnDrawRowHandles( cbDrawRowHandlesEvent
& event
)
665 cbRowInfo
* pRow
= event
.mpRow
;
666 wxDC
& dc
= *event
.mpDc
;
667 mpPane
= event
.mpPane
;
669 // draw handles of surrounding rows first
671 if ( pRow
->mpPrev
&& pRow
->mpPrev
->mHasLowerHandle
)
673 DrawLowerRowHandle( pRow
->mpPrev
, dc
);
675 if ( pRow
->mpNext
&& pRow
->mpNext
->mHasUpperHandle
)
677 DrawUpperRowHandle( pRow
->mpNext
, dc
);
679 // draw handles of the given row
681 if ( pRow
->mHasUpperHandle
)
683 DrawUpperRowHandle( pRow
, dc
);
685 if ( pRow
->mHasLowerHandle
)
687 DrawLowerRowHandle( pRow
, dc
);
689 event
.Skip(); // pass event to the next plugin
692 void cbPaneDrawPlugin::OnDrawPaneBackground ( cbDrawPaneBkGroundEvent
& event
)
694 wxDC
& dc
= *event
.mpDc
;
695 mpPane
= event
.mpPane
;
697 // FOR NOW:: hard-coded
698 wxBrush
bkBrush( mpLayout
->mBorderPen
.GetColour(), wxSOLID
);
700 dc
.SetBrush( bkBrush
);
701 dc
.SetPen( mpLayout
->mNullPen
);
703 wxRect
& bounds
= mpPane
->mBoundsInParent
;
705 if ( mpPane
->mTopMargin
>= 1 )
707 dc
.DrawRectangle( bounds
.x
, bounds
.y
,
709 mpPane
->mTopMargin
+ 1);
712 if ( mpPane
->mBottomMargin
>= 1 )
714 dc
.DrawRectangle( bounds
.x
,
715 bounds
.y
+ bounds
.height
- mpPane
->mBottomMargin
,
717 mpPane
->mBottomMargin
+ 1);
720 if ( mpPane
->mLeftMargin
>= 1 )
722 dc
.DrawRectangle( bounds
.x
,
723 bounds
.y
+ mpPane
->mTopMargin
- 1,
724 mpPane
->mLeftMargin
+ 1,
725 bounds
.height
- mpPane
->mTopMargin
- mpPane
->mBottomMargin
+ 2);
728 if ( mpPane
->mRightMargin
>= 1 )
730 dc
.DrawRectangle( bounds
.x
+ bounds
.width
- mpPane
->mRightMargin
,
731 bounds
.y
+ mpPane
->mTopMargin
- 1,
732 mpPane
->mRightMargin
+ 1,
733 bounds
.height
- mpPane
->mTopMargin
- mpPane
->mBottomMargin
+ 2);
735 event
.Skip(); // pass event to the next plugin
738 void cbPaneDrawPlugin::OnDrawRowBackground ( cbDrawRowBkGroundEvent
& event
)
741 cbRowInfo
* pRow
= event
.mpRow
;
742 wxDC
& dc
= *event
.mpDc
;
743 mpPane
= event
.mpPane
;
746 wxRect rowBounds
= pRow
->mBoundsInParent
;
747 bool isHorizontal
= event
.mpPane
->IsHorizontal();
753 // prevPos = rowBounds.x;
754 // include one line above and below the row
756 rowBounds
.height
+= 2;
759 rowBounds
.width
+= 2;
763 // prevPos = rowBounds.y;
764 // include one line above and below the row
766 rowBounds
.width
+= 2;
769 rowBounds
.height
+= 2;
772 //#define TEST_BK_ERASING
774 #ifdef TEST_BK_ERASING
777 wxBrush
br0( wxColour(0,160,160), wxSOLID
);
779 dc
.SetPen ( mpLayout
->mNullPen
);
780 dc
.DrawRectangle( rowBounds
.x
, rowBounds
.y
,
782 rowBounds
.height
+ 1 );
785 wxBrush
bkBrush( mpLayout
->mGrayPen
.GetColour(), wxSOLID
);
787 dc
.SetPen ( mpLayout
->mNullPen
);
788 dc
.SetBrush( bkBrush
);
790 // fill background-recatangle of entire row area
791 dc
.DrawRectangle( rowBounds
.x
, rowBounds
.y
,
793 rowBounds
.height
+ 1 );
795 dc
.SetBrush( wxNullBrush
);
797 // draw "shaded-side-bars" for each bar
798 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
800 wxRect
& bounds
= pRow
->mBars
[i
]->mBoundsInParent
;
804 DrawShade( 1, bounds
, FL_ALIGN_LEFT
, dc
);
805 DrawShade( 1, bounds
, FL_ALIGN_RIGHT
, dc
);
809 DrawShade( 1, bounds
, FL_ALIGN_TOP
, dc
);
810 DrawShade( 1, bounds
, FL_ALIGN_BOTTOM
, dc
);
814 // draw extra shades to simulate "glued-bricks" effect
816 // TBD:: reduce exessive drawing of shades, when the
817 // row handle is present, and shades will be overr-drawn anyway
819 DrawUpperRowShades( pRow
, dc
, 1 ); // outer shade
823 DrawLowerRowShades( pRow
->mpPrev
, dc
, 1 ); // outter shade
824 DrawLowerRowShades( pRow
->mpPrev
, dc
, 0 ); // inner shade
827 DrawLowerRowShades( pRow
, dc
, 1 );
831 DrawUpperRowShades( pRow
->mpNext
, dc
, 1 );
832 DrawUpperRowShades( pRow
->mpNext
, dc
, 0 );
835 event
.Skip(); // pass event to the next plugin
838 void cbPaneDrawPlugin::DrawUpperRowShades( cbRowInfo
* pRow
, wxDC
& dc
, int level
)
840 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
842 wxRect
& bounds
= pRow
->mBars
[i
]->mBoundsInParent
;
844 if ( mpPane
->IsHorizontal() )
846 DrawShade( level
, bounds
, FL_ALIGN_TOP
, dc
);
849 dc
.SetPen( mpLayout
->mDarkPen
);
850 dc
.DrawPoint( bounds
.x
- 1, bounds
.y
);
851 dc
.SetPen( mpLayout
->mLightPen
);
852 dc
.DrawPoint( bounds
.x
+ bounds
.width
, bounds
.y
);
857 DrawShade( level
, bounds
, FL_ALIGN_LEFT
, dc
);
860 dc
.SetPen( mpLayout
->mDarkPen
);
861 dc
.DrawPoint( bounds
.x
, bounds
.y
-1 );
862 dc
.SetPen( mpLayout
->mLightPen
);
863 dc
.DrawPoint( bounds
.x
, bounds
.y
+ bounds
.height
);
869 void cbPaneDrawPlugin::DrawLowerRowShades( cbRowInfo
* pRow
, wxDC
& dc
, int level
)
871 for( size_t i
= 0; i
!= pRow
->mBars
.Count(); ++i
)
873 wxRect
& bounds
= pRow
->mBars
[i
]->mBoundsInParent
;
875 if ( mpPane
->IsHorizontal() )
877 DrawShade( level
, bounds
, FL_ALIGN_BOTTOM
, dc
);
880 dc
.SetPen( mpLayout
->mDarkPen
);
881 dc
.DrawPoint( bounds
.x
- 1, bounds
.y
+ bounds
.height
-1 );
882 dc
.SetPen( mpLayout
->mLightPen
);
883 dc
.DrawPoint( bounds
.x
+ bounds
.width
, bounds
.y
+ bounds
.height
-1 );
888 DrawShade( level
, bounds
, FL_ALIGN_RIGHT
, dc
);
891 dc
.SetPen( mpLayout
->mDarkPen
);
892 dc
.DrawPoint( bounds
.x
+ bounds
.width
- 1, bounds
.y
-1 );
893 dc
.SetPen( mpLayout
->mLightPen
);
894 dc
.DrawPoint( bounds
.x
+ bounds
.width
- 1, bounds
.y
+ bounds
.height
);
900 void cbPaneDrawPlugin::DrawBarInnerShadeRect( cbBarInfo
* pBar
, wxDC
& dc
)
902 wxRect
& bounds
= pBar
->mBoundsInParent
;
904 dc
.SetPen( mpLayout
->mDarkPen
);
906 dc
.DrawLine( bounds
.x
+ bounds
.width
- 1,
908 bounds
.x
+ bounds
.width
- 1,
909 bounds
.y
+ bounds
.height
);
911 dc
.DrawLine( bounds
.x
,
912 bounds
.y
+ bounds
.height
- 1,
913 bounds
.x
+ bounds
.width
,
914 bounds
.y
+ bounds
.height
-1 );
916 dc
.SetPen( mpLayout
->mLightPen
);
918 dc
.DrawLine( bounds
.x
,
920 bounds
.x
+ bounds
.width
- 1,
923 dc
.DrawLine( bounds
.x
,
926 bounds
.y
+ bounds
.height
- 1 );
929 void cbPaneDrawPlugin::DrawShade( int level
, wxRect
& rect
, int alignment
, wxDC
& dc
)
931 // simulates "guled-bricks" appearence of control bars
933 if ( ( alignment
== FL_ALIGN_TOP
&& level
== 1 ) ||
934 ( alignment
== FL_ALIGN_BOTTOM
&& level
== 0 ) ||
935 ( alignment
== FL_ALIGN_LEFT
&& level
== 1 ) ||
936 ( alignment
== FL_ALIGN_RIGHT
&& level
== 0 )
939 dc
.SetPen( mpLayout
->mDarkPen
);
941 dc
.SetPen( mpLayout
->mLightPen
);
943 if ( alignment
== FL_ALIGN_TOP
)
949 rect
.x
+ rect
.width
- 1,
952 dc
.DrawLine( rect
.x
- 1,
954 rect
.x
+ rect
.width
+ 0,
958 if ( alignment
== FL_ALIGN_BOTTOM
)
963 rect
.y
+ rect
.height
- 1,
965 rect
.y
+ rect
.height
- 1 );
967 dc
.DrawLine( rect
.x
- 1,
968 rect
.y
+ rect
.height
,
969 rect
.x
+ rect
.width
+ 1,
970 rect
.y
+ rect
.height
);
973 if ( alignment
== FL_ALIGN_LEFT
)
980 rect
.y
+ rect
.height
- 1 );
982 dc
.DrawLine( rect
.x
- 1,
985 rect
.y
+ rect
.height
);
988 if ( alignment
== FL_ALIGN_RIGHT
)
992 dc
.DrawLine( rect
.x
+ rect
.width
- 1,
994 rect
.x
+ rect
.width
- 1,
995 rect
.y
+ rect
.height
);
998 dc
.DrawLine( rect
.x
+ rect
.width
,
1000 rect
.x
+ rect
.width
,
1001 rect
.y
+ rect
.height
+ 1 );
1006 void cbPaneDrawPlugin::DrawShade1( int level
, wxRect
& rect
, int alignment
, wxDC
& dc
)
1008 // simulates "guled-bricks" appearence of control bars
1010 if ( ( alignment
== FL_ALIGN_TOP
&& level
== 1 ) ||
1011 ( alignment
== FL_ALIGN_BOTTOM
&& level
== 0 ) ||
1012 ( alignment
== FL_ALIGN_LEFT
&& level
== 1 ) ||
1013 ( alignment
== FL_ALIGN_RIGHT
&& level
== 0 )
1016 dc
.SetPen( mpLayout
->mDarkPen
);
1018 dc
.SetPen( mpLayout
->mLightPen
);
1020 if ( alignment
== FL_ALIGN_TOP
)
1024 dc
.DrawLine( rect
.x
,
1026 rect
.x
+ rect
.width
,
1029 dc
.DrawLine( rect
.x
,
1031 rect
.x
+ rect
.width
,
1035 if ( alignment
== FL_ALIGN_BOTTOM
)
1039 dc
.DrawLine( rect
.x
,
1040 rect
.y
+ rect
.height
- 1,
1041 rect
.x
+ rect
.width
,
1042 rect
.y
+ rect
.height
- 1 );
1044 dc
.DrawLine( rect
.x
,
1045 rect
.y
+ rect
.height
,
1046 rect
.x
+ rect
.width
,
1047 rect
.y
+ rect
.height
);
1050 if ( alignment
== FL_ALIGN_LEFT
)
1054 dc
.DrawLine( rect
.x
,
1057 rect
.y
+ rect
.height
);
1059 dc
.DrawLine( rect
.x
- 1,
1062 rect
.y
+ rect
.height
);
1065 if ( alignment
== FL_ALIGN_RIGHT
)
1069 dc
.DrawLine( rect
.x
+ rect
.width
- 1,
1071 rect
.x
+ rect
.width
- 1,
1072 rect
.y
+ rect
.height
);
1075 dc
.DrawLine( rect
.x
+ rect
.width
,
1077 rect
.x
+ rect
.width
,
1078 rect
.y
+ rect
.height
);
1083 void cbPaneDrawPlugin::DrawPaneShade( wxDC
& dc
, int alignment
)
1085 if ( !mpPane
->mProps
.mShow3DPaneBorderOn
) return;
1087 wxRect bounds
= mpPane
->mBoundsInParent
;
1089 bounds
.x
+= mpPane
->mLeftMargin
;
1090 bounds
.y
+= mpPane
->mTopMargin
;
1091 bounds
.width
-= ( mpPane
->mLeftMargin
+ mpPane
->mRightMargin
);
1092 bounds
.height
-= ( mpPane
->mTopMargin
+ mpPane
->mBottomMargin
);
1094 DrawShade( 0, bounds
, alignment
, dc
);
1095 DrawShade( 1, bounds
, alignment
, dc
);
1098 void cbPaneDrawPlugin::DrawPaneShadeForRow( cbRowInfo
* pRow
, wxDC
& dc
)
1100 if ( !mpPane
->mProps
.mShow3DPaneBorderOn
) return;
1102 // do not draw decoration, if pane has "vainished"
1103 if ( mpPane
->mPaneWidth
< 0 ||
1104 mpPane
->mPaneHeight
< 0 )
1108 wxRect bounds
= pRow
->mBoundsInParent
;
1110 if ( mpPane
->mAlignment
== FL_ALIGN_TOP
||
1111 mpPane
->mAlignment
== FL_ALIGN_BOTTOM
)
1116 DrawShade1( 0, bounds
, FL_ALIGN_LEFT
, dc
);
1117 DrawShade1( 1, bounds
, FL_ALIGN_LEFT
, dc
);
1118 DrawShade1( 0, bounds
, FL_ALIGN_RIGHT
, dc
);
1119 DrawShade1( 1, bounds
, FL_ALIGN_RIGHT
, dc
);
1121 if ( !pRow
->mpNext
)
1122 DrawPaneShade( dc
, FL_ALIGN_BOTTOM
);
1124 if ( !pRow
->mpPrev
)
1125 DrawPaneShade( dc
, FL_ALIGN_TOP
);
1132 DrawShade1( 0, bounds
, FL_ALIGN_TOP
, dc
);
1133 DrawShade1( 1, bounds
, FL_ALIGN_TOP
, dc
);
1134 DrawShade1( 0, bounds
, FL_ALIGN_BOTTOM
, dc
);
1135 DrawShade1( 1, bounds
, FL_ALIGN_BOTTOM
, dc
);
1137 if ( !pRow
->mpNext
)
1138 DrawPaneShade( dc
, FL_ALIGN_RIGHT
);
1140 if ( !pRow
->mpPrev
)
1141 DrawPaneShade( dc
, FL_ALIGN_LEFT
);
1145 void cbPaneDrawPlugin::OnDrawPaneDecorations( cbDrawPaneDecorEvent
& event
)
1147 wxDC
& dc
= *event
.mpDc
;
1149 cbDockPane
* pPane
= event
.mpPane
;
1151 RowArrayT
& lst
= pPane
->GetRowList();
1153 // FIXME:: this is a workaround for some glitches
1157 cbRowInfo
* pLastRow
= lst
[ lst
.Count() - 1 ];
1159 pPane
->PaintRowBackground( pLastRow
, dc
);
1160 pPane
->PaintRowDecorations( pLastRow
, dc
);
1161 pPane
->PaintRowHandles( pLastRow
, dc
);
1164 if ( !pPane
->mProps
.mShow3DPaneBorderOn
) return;
1166 // do not draw decoration, if pane is completely hidden
1167 if ( event
.mpPane
->mPaneWidth
< 0 ||
1168 event
.mpPane
->mPaneHeight
< 0 )
1172 DrawPaneShade( dc
, FL_ALIGN_TOP
);
1173 DrawPaneShade( dc
, FL_ALIGN_BOTTOM
);
1174 DrawPaneShade( dc
, FL_ALIGN_LEFT
);
1175 DrawPaneShade( dc
, FL_ALIGN_RIGHT
);
1177 event
.Skip(); // pass event to the next plugin
1180 // bar decoration/sizing handlers
1182 void cbPaneDrawPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent
& event
)
1184 // cbBarInfo* pBar = event.mpBar;
1185 wxDC
& dc
= *event
.mpDc
;
1187 // draw brick borders
1189 wxRect
& rect
= event
.mBoundsInParent
;
1191 dc
.SetPen( mpLayout
->mLightPen
);
1194 dc
.DrawLine( rect
.x
, rect
.y
,
1195 rect
.x
+ rect
.width
-1, rect
.y
);
1198 dc
.DrawLine( rect
.x
, rect
.y
,
1199 rect
.x
, rect
.y
+ rect
.height
-1 );
1202 dc
.SetPen( mpLayout
->mDarkPen
);
1205 dc
.DrawLine( rect
.x
+ rect
.width
-1, rect
.y
,
1206 rect
.x
+ rect
.width
-1, rect
.y
+ rect
.height
-1 );
1209 dc
.DrawLine( rect
.x
, rect
.y
+ rect
.height
-1,
1210 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
-1 );
1212 event
.Skip(); // pass event to the next plugin
1215 void cbPaneDrawPlugin::OnDrawBarHandles( cbDrawBarHandlesEvent
& event
)
1218 cbBarInfo
* pBar
= event
.mpBar
;
1219 wxDC
& dc
= *event
.mpDc
;
1220 mpPane
= event
.mpPane
;
1222 // draw handles around the bar if present
1224 if ( pBar
->mHasLeftHandle
||
1225 pBar
->mHasRightHandle
)
1227 wxRect
& bounds
= pBar
->mBoundsInParent
;
1229 if ( mpPane
->IsHorizontal() )
1231 if ( pBar
->mHasLeftHandle
)
1233 mpPane
->DrawVertHandle( dc
, bounds
.x
- mpPane
->mProps
.mResizeHandleSize
-1,
1234 bounds
.y
, bounds
.height
);
1236 if ( pBar
->mHasRightHandle
)
1238 mpPane
->DrawVertHandle( dc
,
1239 bounds
.x
+ bounds
.width
-1,
1240 bounds
.y
, bounds
.height
);
1244 if ( pBar
->mHasLeftHandle
)
1246 mpPane
->DrawHorizHandle( dc
, bounds
.x
,
1247 bounds
.y
- mpPane
->mProps
.mResizeHandleSize
- 1,
1250 if ( pBar
->mHasRightHandle
)
1252 mpPane
->DrawHorizHandle( dc
, bounds
.x
,
1253 bounds
.y
+ bounds
.height
- 1,
1258 event
.Skip(); // pass event to the next plugin
1261 void cbPaneDrawPlugin::OnStartDrawInArea( cbStartDrawInAreaEvent
& event
)
1264 wxASSERT( mpClntDc
== NULL
);
1266 // FOR NOW:: create/destroy client-dc upon each drawing
1267 mpClntDc
= new wxClientDC( &mpLayout
->GetParentFrame() );
1269 (*event
.mppDc
) = mpClntDc
;
1271 mpClntDc
->SetClippingRegion( event
.mArea
.x
, event
.mArea
.y
,
1272 event
.mArea
.width
, event
.mArea
.height
);
1275 void cbPaneDrawPlugin::OnFinishDrawInArea( cbFinishDrawInAreaEvent
& WXUNUSED(event
) )
1278 wxASSERT( mpClntDc
);