]> git.saurik.com Git - wxWidgets.git/blob - utils/framelayout/src/panedrawpl.cpp
don't crash when invalid colour is set as fg/bg colour
[wxWidgets.git] / utils / framelayout / src / panedrawpl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: No names yet.
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 06/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "panedrawpl.h"
14 // #pragma interface
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/wx.h"
26 #endif
27
28 #include <math.h>
29 #include <stdlib.h>
30
31 #include "wx/utils.h" // import wxMin,wxMax macros
32
33 #include "panedrawpl.h"
34
35 // bitmap bits used by bar-resizing brush
36
37 #define _A 0xAA
38 #define _B 0x00
39 #define _C 0x55
40 #define _D 0x00
41
42 static const unsigned char _gCheckerImg[16] = { _A,_B,_C,_D,
43 _A,_B,_C,_D,
44 _A,_B,_C,_D,
45 _A,_B,_C,_D
46 };
47
48 static void set_cursor_bits( const char** img, char* bits, int width, int height )
49 {
50 for( int i = 0; i != (width*height)/8; ++i )
51 bits[i] = 0;
52
53 for( int y = 0; y != height; ++y )
54 {
55 const char* row = img[0];
56
57 for( int x = 0; x != width; ++x )
58 {
59 int bitNo = y*width + x;
60
61 char value = ( row[x] != '.' ) ? 1 : 0;
62
63 bits[ bitNo / sizeof(char) ] |=
64 ( ( bitNo %sizeof(char) ) << value );
65 }
66
67 ++img;
68 }
69 }
70
71 /***** Implementation for class cbPaneDrawPlugin *****/
72
73 IMPLEMENT_DYNAMIC_CLASS( cbPaneDrawPlugin, cbPluginBase )
74
75 BEGIN_EVENT_TABLE( cbPaneDrawPlugin, cbPluginBase )
76
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 )
82
83
84 EVT_PL_DRAW_PANE_BKGROUND ( cbPaneDrawPlugin::OnDrawPaneBackground )
85 EVT_PL_DRAW_PANE_DECOR ( cbPaneDrawPlugin::OnDrawPaneDecorations )
86
87 EVT_PL_DRAW_ROW_DECOR ( cbPaneDrawPlugin::OnDrawRowDecorations )
88 EVT_PL_DRAW_ROW_HANDLES ( cbPaneDrawPlugin::OnDrawRowHandles )
89 EVT_PL_DRAW_ROW_BKGROUND ( cbPaneDrawPlugin::OnDrawRowBackground )
90
91 EVT_PL_SIZE_BAR_WND ( cbPaneDrawPlugin::OnSizeBarWindow )
92 EVT_PL_DRAW_BAR_DECOR ( cbPaneDrawPlugin::OnDrawBarDecorations )
93 EVT_PL_DRAW_BAR_HANDLES ( cbPaneDrawPlugin::OnDrawBarHandles )
94
95 EVT_PL_START_DRAW_IN_AREA ( cbPaneDrawPlugin::OnStartDrawInArea )
96 EVT_PL_FINISH_DRAW_IN_AREA ( cbPaneDrawPlugin::OnFinishDrawInArea )
97
98 END_EVENT_TABLE()
99
100 cbPaneDrawPlugin::cbPaneDrawPlugin(void)
101
102 : mResizeStarted ( FALSE ),
103
104 mResizeCursorOn ( FALSE ),
105 mpDraggedBar ( NULL ),
106 mpResizedRow ( NULL ),
107
108 mpClntDc ( NULL ),
109 mpPane ( NULL )
110 {}
111
112 cbPaneDrawPlugin::cbPaneDrawPlugin( wxFrameLayout* pPanel, int paneMask )
113
114 : cbPluginBase( pPanel, paneMask ),
115
116 // bar-row resizing state varaibles
117
118 mResizeStarted ( FALSE ),
119
120 mResizeCursorOn ( FALSE ),
121 mpDraggedBar ( NULL ),
122 mpResizedRow ( NULL ),
123
124 mRowHandleHitted ( FALSE ),
125 mIsUpperHandle ( FALSE ),
126 mBarHandleHitted ( FALSE ),
127 mIsLeftHandle ( FALSE ),
128 mBarContentHitted ( FALSE ),
129
130 mpClntDc ( NULL ),
131 mpPane ( NULL )
132 {}
133
134 cbPaneDrawPlugin::~cbPaneDrawPlugin()
135 {
136 // DBG::
137 wxASSERT( mpClntDc == NULL );
138 }
139
140 void cbPaneDrawPlugin::DrawDraggedHandle( const wxPoint& pos, cbDockPane& pane )
141 {
142 wxScreenDC dc;
143 int ofsX = 0;
144 int ofsY = 0;
145
146 wxPoint fpos = pos;
147 pane.PaneToFrame( &fpos.x, &fpos.y );
148
149 // short-cut
150 int resizeHndSize = pane.mProps.mResizeHandleSize;
151
152 // "Required for X to specify that
153 // that we wish to draw on top of all windows
154 // - and we optimise by specifying the area
155 // for creating the overlap window." --J.S.
156
157 wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());
158
159 mpLayout->GetParentFrame().ClientToScreen( &ofsX, &ofsY );
160
161 int prevLF = dc.GetLogicalFunction();
162
163 // BUG BUG BUG (wx):: somehow stippled brush works only
164 // when the bitmap created on stack, not
165 // as a member of the class
166
167 wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
168
169 wxBrush checkerBrush( checker );
170
171 dc.SetPen( mpLayout->mNullPen );
172 dc.SetBrush( checkerBrush );
173 dc.SetLogicalFunction( wxXOR );
174
175 if ( mHandleIsVertical )
176 {
177 int delta = pos.x - mDragOrigin.x;
178
179 if ( !pane.IsHorizontal() )
180
181 delta = pos.y - mDragOrigin.y;
182
183 int realHndOfs;
184 realHndOfs = pane.mBoundsInParent.x + pane.mLeftMargin + mHandleOfs;
185
186 int newX = realHndOfs + delta;
187
188 if ( newX + resizeHndSize > mHandleDragArea.x + mHandleDragArea.width )
189
190 newX = mHandleDragArea.x + mHandleDragArea.width - 1;
191
192 if ( newX < mHandleDragArea.x )
193
194 newX = mHandleDragArea.x;
195
196 mDraggedDelta = newX - realHndOfs;
197
198 dc.DrawRectangle( newX + ofsX, mHandleDragArea.y + ofsY,
199 resizeHndSize + 1,
200 mHandleDragArea.height+1 );
201 }
202 else
203 {
204 // otherwise, draw horizontal handle
205
206 int delta = pos.y - mDragOrigin.y;
207
208 if ( !pane.IsHorizontal() )
209
210 delta = pos.x - mDragOrigin.x;
211
212 int realHndOfs;
213 realHndOfs = pane.mBoundsInParent.y + pane.mTopMargin + mHandleOfs;
214
215 int newY = realHndOfs + delta;
216
217 if ( newY + resizeHndSize > mHandleDragArea.y + mHandleDragArea.height )
218
219 newY = mHandleDragArea.y + mHandleDragArea.height - 1;
220
221 if ( newY < mHandleDragArea.y )
222
223 newY = mHandleDragArea.y;
224
225 mDraggedDelta = newY - realHndOfs;
226
227 dc.DrawRectangle( mHandleDragArea.x + ofsX, newY + ofsY,
228 mHandleDragArea.width + 1,
229 resizeHndSize + 1 );
230 }
231
232 dc.SetLogicalFunction( prevLF );
233
234 // "End drawing on top (frees the window used for drawing
235 // over the screen)" --J.S.
236 wxScreenDC::EndDrawingOnTop();
237 }
238
239 void cbPaneDrawPlugin::OnMouseMove( cbMotionEvent& event )
240 {
241 if ( !mResizeStarted )
242 {
243 // if nothing is started, do hit-tests
244
245 bool prevWasRowHandle = mRowHandleHitted;
246
247 mBarContentHitted = FALSE;
248 mBarHandleHitted = FALSE;
249 mRowHandleHitted = FALSE;
250
251 int testResult =
252 event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
253 &mpResizedRow,
254 &mpDraggedBar );
255
256 if ( testResult != CB_NO_ITEMS_HITTED )
257 {
258 if ( testResult == CB_BAR_CONTENT_HITTED )
259 {
260 // restore cursor, if non of the handles were hit
261 if ( mResizeCursorOn )
262 {
263 // remove resizing hints
264
265 mpLayout->ReleaseEventsFromPane( event.mpPane );
266 mpLayout->ReleaseEventsFromPlugin( this );
267
268 mResizeCursorOn = FALSE;
269
270 mBarContentHitted = TRUE;
271
272 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
273 }
274
275 // TBD:: fire something like "mouse-over-bar" event
276
277 event.Skip(); // pass event to the next handler in the chain
278 return;
279 }
280
281 wxCursor* pCurs = NULL;
282
283 if ( testResult == CB_UPPER_ROW_HANDLE_HITTED ||
284 testResult == CB_LOWER_ROW_HANDLE_HITTED)
285 {
286 if ( event.mpPane->IsHorizontal() )
287
288 pCurs = mpLayout->mpVertCursor;
289 else
290 pCurs = mpLayout->mpHorizCursor;
291
292 mRowHandleHitted = TRUE;
293 mIsUpperHandle = ( testResult == CB_UPPER_ROW_HANDLE_HITTED );
294 }
295 else
296 {
297 // otherwise, if inter-bar handle was hitted
298
299 if ( event.mpPane->IsHorizontal() )
300
301 pCurs = mpLayout->mpHorizCursor;
302 else
303 pCurs = mpLayout->mpVertCursor;
304
305 mBarHandleHitted = TRUE;
306 mIsLeftHandle = ( testResult == CB_LEFT_BAR_HANDLE_HITTED );
307 }
308
309 // avoid setting the same cursor twice
310
311 if ( !mResizeCursorOn || prevWasRowHandle != mRowHandleHitted )
312 {
313 if ( !mResizeCursorOn )
314 {
315 // caputre if not captured yet
316 mpLayout->CaptureEventsForPane( event.mpPane );
317 mpLayout->CaptureEventsForPlugin( this );
318 }
319
320 mpLayout->GetParentFrame().SetCursor( *pCurs );
321 }
322
323 mResizeCursorOn = TRUE;
324
325 // handled is being dragged now, thus event is "eaten" by this plugin
326
327 return;
328
329 } // end of if (HitTestBarHandles())
330
331 // restore cursor, if non of the handles were hit
332 if ( mResizeCursorOn )
333 {
334 mpLayout->ReleaseEventsFromPane( event.mpPane );
335 mpLayout->ReleaseEventsFromPlugin( this );
336
337 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
338
339 mResizeCursorOn = FALSE;
340 }
341
342 event.Skip(); // pass event to the next plugin
343 }
344
345 // othewise series of actions, if something has already started
346
347 else
348 if ( mResizeStarted )
349 {
350 // apply xor-mask twice
351 DrawDraggedHandle( mPrevPos, *event.mpPane );
352
353 // draw handle in the new position
354 DrawDraggedHandle( event.mPos, *event.mpPane );
355 mPrevPos = event.mPos;
356
357 // handled is dragged, thus event is "eaten" by this plugin
358 }
359 else
360 event.Skip(); // pass event to the next plugin
361 }
362
363 void cbPaneDrawPlugin::OnLDblClick( cbLeftDClickEvent& event )
364 {
365 if ( !mResizeCursorOn )
366 {
367 cbBarInfo* pBarToFloat;
368
369 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
370 &mpResizedRow,
371 &pBarToFloat ) == CB_BAR_CONTENT_HITTED
372 )
373 {
374 return;
375
376 mpLayout->SetBarState( pBarToFloat, wxCBAR_FLOATING, TRUE );
377
378 mpLayout->RepositionFloatedBar( pBarToFloat );
379
380 return; // event is "eaten" by this plugin
381 }
382
383 event.Skip();
384 }
385 }
386
387 void cbPaneDrawPlugin::OnLButtonDown( cbLeftDownEvent& event )
388 {
389 wxASSERT( !mResizeStarted );
390
391 if ( mResizeCursorOn )
392 {
393 mResizeStarted = TRUE;
394 mDragOrigin = event.mPos;
395
396 cbBarInfo* pInfo = NULL;
397
398 // setup constraints for the dragging handle
399
400 int from, till;
401 mHandleOfs = 0;
402 mHandleIsVertical = FALSE;
403
404 if ( mRowHandleHitted )
405
406 event.mpPane->GetRowResizeRange( mpResizedRow, &from, &till, mIsUpperHandle );
407 else
408 // otherwise if bar handle was hitted
409 event.mpPane->GetBarResizeRange( mpDraggedBar, &from, &till, mIsLeftHandle );
410
411 if ( mRowHandleHitted )
412 {
413 mHandleIsVertical = ( event.mpPane->IsHorizontal() ) ? FALSE : TRUE;
414
415 mHandleDragArea.x = 0;
416 mHandleDragArea.width = event.mpPane->mPaneWidth;
417
418 mHandleDragArea.y = from;
419 mHandleDragArea.height = till - from;
420
421 if ( mIsUpperHandle )
422
423 mHandleOfs = mpResizedRow->mRowY;
424 else
425 mHandleOfs = mpResizedRow->mRowY +
426 mpResizedRow->mRowHeight -
427 event.mpPane->mProps.mResizeHandleSize;
428 }
429 else
430 {
431 // otehrwise if bar handle dragged
432
433 cbRowInfo& rowInfo = *mpDraggedBar->mpRow;
434 wxRect& bounds = mpDraggedBar->mBounds;
435
436 mHandleIsVertical = ( event.mpPane->IsHorizontal() ) ? TRUE : FALSE;
437
438 mHandleDragArea.x = from;
439 mHandleDragArea.width = till - from;
440
441
442 mHandleDragArea.y = bounds.y;
443 mHandleDragArea.height = bounds.height;
444
445 // left-side-handle mBounds
446 if ( mIsLeftHandle )
447
448 mHandleOfs = bounds.x;
449 else
450 mHandleOfs = bounds.x +
451 bounds.width - event.mpPane->mProps.mResizeHandleSize;
452
453 }
454
455 event.mpPane->PaneToFrame( &mHandleDragArea );
456 DrawDraggedHandle(mDragOrigin, *event.mpPane);
457
458 mPrevPos = mDragOrigin;
459
460 return;
461 // handled is dragged, thus event is "eaten" by this plugin
462 }
463 else
464 {
465 cbBarInfo* pDraggedBar;
466
467 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
468 &mpResizedRow,
469 &pDraggedBar ) == CB_BAR_CONTENT_HITTED
470 )
471 {
472 long x = event.mPos.x,
473 y = event.mPos.y;
474
475 event.mpPane->PaneToFrame( &x, &y );
476
477 cbStartBarDraggingEvent dragEvt( pDraggedBar, wxPoint(x,y), event.mpPane );
478
479 mpLayout->FirePluginEvent( dragEvt );
480
481 return; // event is "eaten" by this plugin
482 }
483 }
484
485 event.Skip(); // pass event to the next plugin in the chain
486 }
487
488 void cbPaneDrawPlugin::OnLButtonUp( cbLeftUpEvent& event )
489 {
490 if ( mResizeStarted )
491 {
492 DrawDraggedHandle( event.mPos, *event.mpPane );
493
494 mResizeStarted = FALSE;
495 mResizeCursorOn = FALSE;
496
497 mpLayout->ReleaseEventsFromPane( event.mpPane );
498 mpLayout->ReleaseEventsFromPlugin( this );
499
500 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
501
502 if ( mRowHandleHitted )
503 {
504 event.mpPane->ResizeRow( mpResizedRow,
505 mDraggedDelta,
506 mIsUpperHandle );
507 }
508 else
509 {
510 event.mpPane->ResizeBar( mpDraggedBar,
511 mDraggedDelta,
512 mIsLeftHandle );
513 }
514
515 mpDraggedBar = NULL;
516 mpResizedRow = NULL;
517
518 // handled dragging action was finished by this mouse-up,
519 // thus event is "eaten" by this plugin
520
521 return;
522 }
523
524 event.Skip(); // pass event to the next plugin
525 }
526
527 void cbPaneDrawPlugin::OnRButtonUp( cbRightUpEvent& event )
528 {
529 wxPoint fpos = event.mPos;
530 event.mpPane->PaneToFrame( &fpos.x, &fpos.y );
531
532 cbBarInfo* pDraggedBar;
533
534 // user clicks inside the bar contnet, fire bar-customization event
535
536 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
537 &mpResizedRow,
538 &pDraggedBar ) == CB_BAR_CONTENT_HITTED
539 )
540 {
541 cbCustomizeBarEvent cbEvt( pDraggedBar, fpos, event.mpPane );
542
543 mpLayout->FirePluginEvent( cbEvt );
544
545 return; // event is "eaten" by this plugin
546 }
547
548 // otherwise fire whole-layout customization event
549
550 cbCustomizeLayoutEvent csEvt( fpos );
551
552 mpLayout->FirePluginEvent( csEvt );
553
554 // event is "eaten" by this plugin
555 }
556
557 void cbPaneDrawPlugin::OnSizeBarWindow( cbSizeBarWndEvent& event )
558 {
559 cbBarInfo& bar = *event.mpBar;
560 mpPane = event.mpPane;
561
562 // it's possible that a bar does not have it's own window!
563 if ( !bar.mpBarWnd ) return;
564
565 wxRect& bounds = event.mBoundsInParent;
566
567 // check visibility
568 if ( bounds.height != 0 )
569 {
570 // size smaller than bounds, to leave space for shade lines
571
572 // FIXME:: +/- 1s
573
574 bar.mpBarWnd->wxWindow::SetSize( bounds.x + 1 + bar.mDimInfo.mHorizGap,
575 bounds.y + 1 + bar.mDimInfo.mVertGap,
576 bounds.width - 2 - bar.mDimInfo.mHorizGap*2,
577 bounds.height - 2 - bar.mDimInfo.mVertGap *2 ,
578 0
579 );
580
581 if ( !bar.mpBarWnd->IsShown() )
582
583 bar.mpBarWnd->Show( TRUE );
584 }
585 else
586 // hide bar if not visable
587 bar.mpBarWnd->Show( FALSE );
588
589 event.Skip(); // pass event to the next plugin in the chain
590 }
591
592 void cbPaneDrawPlugin::OnDrawRowDecorations( cbDrawRowDecorEvent& event )
593 {
594 DrawPaneShadeForRow( event.mpRow, *event.mpDc );
595
596 event.Skip(); // pass event to the next plugin
597 }
598
599 void cbPaneDrawPlugin::DrawUpperRowHandle( cbRowInfo* pRow, wxDC& dc )
600 {
601 wxRect& bounds = pRow->mBoundsInParent;
602
603 if ( mpPane->IsHorizontal() )
604 {
605 if ( pRow->mHasUpperHandle )
606
607 mpPane->DrawHorizHandle( dc, bounds.x,
608 bounds.y-1,
609 pRow->mRowWidth );
610 }
611 else
612 {
613 if ( pRow->mHasUpperHandle )
614
615 mpPane->DrawVertHandle( dc, bounds.x-1,
616 bounds.y, pRow->mRowWidth );
617 }
618 }
619
620 void cbPaneDrawPlugin::DrawLowerRowHandle( cbRowInfo* pRow, wxDC& dc )
621 {
622 wxRect& bounds = pRow->mBoundsInParent;
623
624 // check if iter-row handles present
625
626 if ( mpPane->IsHorizontal() )
627 {
628 if ( pRow->mHasLowerHandle )
629
630 mpPane->DrawHorizHandle( dc, bounds.x, bounds.y + bounds.height - mpPane->mProps.mResizeHandleSize - 1,
631 pRow->mRowWidth );
632 }
633 else
634 {
635 if ( pRow->mHasLowerHandle )
636
637 mpPane->DrawVertHandle( dc, bounds.x + bounds.width - mpPane->mProps.mResizeHandleSize - 1,
638 bounds.y, pRow->mRowWidth );
639 }
640 }
641
642 void cbPaneDrawPlugin::OnDrawRowHandles( cbDrawRowHandlesEvent& event )
643 {
644 // short-cuts
645 cbRowInfo* pRow = event.mpRow;
646 wxDC& dc = *event.mpDc;
647 mpPane = event.mpPane;
648
649 // draw handles of surrounding rows first
650
651 if ( pRow->mpPrev && pRow->mpPrev->mHasLowerHandle )
652
653 DrawLowerRowHandle( pRow->mpPrev, dc );
654
655 if ( pRow->mpNext && pRow->mpNext->mHasUpperHandle )
656
657 DrawUpperRowHandle( pRow->mpNext, dc );
658
659 // draw handles of the given row
660
661 if ( pRow->mHasUpperHandle )
662
663 DrawUpperRowHandle( pRow, dc );
664
665 if ( pRow->mHasLowerHandle )
666
667 DrawLowerRowHandle( pRow, dc );
668
669 event.Skip(); // pass event to the next plugin
670 }
671
672 void cbPaneDrawPlugin::OnDrawPaneBackground ( cbDrawPaneBkGroundEvent& event )
673 {
674 wxDC& dc = *event.mpDc;
675 mpPane = event.mpPane;
676
677 // FOR NOW:: hard-coded
678 wxBrush bkBrush( mpLayout->mBorderPen.GetColour(), wxSOLID );
679
680 dc.SetBrush( bkBrush );
681 dc.SetPen( mpLayout->mNullPen );
682
683 wxRect& bounds = mpPane->mBoundsInParent;
684
685 if ( mpPane->mTopMargin >= 1 )
686
687 dc.DrawRectangle( bounds.x, bounds.y,
688 bounds.width+1,
689 mpPane->mTopMargin + 1);
690
691
692 if ( mpPane->mBottomMargin >= 1 )
693
694 dc.DrawRectangle( bounds.x,
695 bounds.y + bounds.height - mpPane->mBottomMargin,
696 bounds.width + 1,
697 mpPane->mBottomMargin + 1);
698
699
700 if ( mpPane->mLeftMargin >= 1 )
701
702 dc.DrawRectangle( bounds.x,
703 bounds.y + mpPane->mTopMargin - 1,
704 mpPane->mLeftMargin + 1,
705 bounds.height - mpPane->mTopMargin - mpPane->mBottomMargin + 2);
706
707
708 if ( mpPane->mRightMargin >= 1 )
709
710 dc.DrawRectangle( bounds.x + bounds.width - mpPane->mRightMargin,
711 bounds.y + mpPane->mTopMargin - 1,
712 mpPane->mRightMargin + 1,
713 bounds.height - mpPane->mTopMargin - mpPane->mBottomMargin + 2);
714
715 event.Skip(); // pass event to the next plugin
716 }
717
718 void cbPaneDrawPlugin::OnDrawRowBackground ( cbDrawRowBkGroundEvent& event )
719 {
720 // short-cuts
721 cbRowInfo* pRow = event.mpRow;
722 wxDC& dc = *event.mpDc;
723 mpPane = event.mpPane;
724
725 // get ready
726 wxRect rowBounds = pRow->mBoundsInParent;
727 bool isHorizontal = event.mpPane->IsHorizontal();
728
729 int prevPos;
730
731 if ( isHorizontal )
732 {
733 prevPos = rowBounds.x;
734 // include one line obove and below the row
735 --rowBounds.y;
736 rowBounds.height +=2;
737
738 --rowBounds.x;
739 rowBounds.width += 2;
740 }
741 else
742 {
743 prevPos = rowBounds.y;
744 // include one line obove and below the row
745 --rowBounds.x;
746 rowBounds.width += 2;
747
748 --rowBounds.y;
749 rowBounds.height +=2;
750 }
751
752 //#define TEST_BK_ERASING
753
754 #ifdef TEST_BK_ERASING
755
756 // DBG::
757 wxBrush br0( wxColour(0,160,160), wxSOLID );
758 dc.SetBrush(br0);
759 dc.SetPen ( mpLayout->mNullPen );
760 dc.DrawRectangle( rowBounds.x, rowBounds.y,
761 rowBounds.width + 1,
762 rowBounds.height + 1 );
763 #endif
764
765 wxBrush bkBrush( mpLayout->mGrayPen.GetColour(), wxSOLID );
766
767 dc.SetPen ( mpLayout->mNullPen );
768 dc.SetBrush( bkBrush );
769
770 // fill background-recatangle of entire row area
771 dc.DrawRectangle( rowBounds.x, rowBounds.y,
772 rowBounds.width + 1,
773 rowBounds.height + 1 );
774
775 dc.SetBrush( wxNullBrush );
776
777 // draw "shaded-side-bars" for each bar
778 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
779 {
780 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
781
782 if ( isHorizontal )
783 {
784 DrawShade( 1, bounds, wxLEFT, dc );
785 DrawShade( 1, bounds, wxRIGHT, dc );
786 }
787 else
788 {
789 DrawShade( 1, bounds, wxTOP, dc );
790 DrawShade( 1, bounds, wxBOTTOM, dc );
791 }
792 }
793
794 // draw extra shades to simulate "glued-bricks" effect
795
796 // TBD:: reduce exessive drawing of shades, when the
797 // row handle is present, and shades will be overr-drawn anyway
798
799 DrawUpperRowShades( pRow, dc, 1 ); // outer shade
800
801 if ( pRow->mpPrev )
802 {
803 DrawLowerRowShades( pRow->mpPrev, dc, 1 ); // outter shade
804 DrawLowerRowShades( pRow->mpPrev, dc, 0 ); // inner shade
805 }
806
807 DrawLowerRowShades( pRow, dc, 1 );
808
809 if ( pRow->mpNext )
810 {
811 DrawUpperRowShades( pRow->mpNext, dc, 1 );
812 DrawUpperRowShades( pRow->mpNext, dc, 0 );
813 }
814
815 event.Skip(); // pass event to the next plugin
816 }
817
818 void cbPaneDrawPlugin::DrawUpperRowShades( cbRowInfo* pRow, wxDC& dc, int level )
819 {
820 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
821 {
822 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
823
824 if ( mpPane->IsHorizontal() )
825 {
826 DrawShade( level, bounds, wxTOP, dc );
827 if ( level == 1 )
828 {
829 dc.SetPen( mpLayout->mDarkPen );
830 dc.DrawPoint( bounds.x - 1, bounds.y );
831 dc.SetPen( mpLayout->mLightPen );
832 dc.DrawPoint( bounds.x + bounds.width , bounds.y );
833 }
834 }
835 else
836 {
837 DrawShade( level, bounds, wxLEFT, dc );
838 if ( level == 1 )
839 {
840 dc.SetPen( mpLayout->mDarkPen );
841 dc.DrawPoint( bounds.x, bounds.y -1 );
842 dc.SetPen( mpLayout->mLightPen );
843 dc.DrawPoint( bounds.x, bounds.y + bounds.height );
844 }
845 }
846 }
847 }
848
849 void cbPaneDrawPlugin::DrawLowerRowShades( cbRowInfo* pRow, wxDC& dc, int level )
850 {
851 int prevX = 0;
852
853 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
854 {
855 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
856
857 if ( mpPane->IsHorizontal() )
858 {
859 DrawShade( level, bounds, wxBOTTOM, dc );
860 if ( level == 1 )
861 {
862 dc.SetPen( mpLayout->mDarkPen );
863 dc.DrawPoint( bounds.x - 1, bounds.y + bounds.height -1 );
864 dc.SetPen( mpLayout->mLightPen );
865 dc.DrawPoint( bounds.x + bounds.width , bounds.y + bounds.height -1 );
866 }
867 }
868 else
869 {
870 DrawShade( level, bounds, wxRIGHT, dc );
871 if ( level == 1 )
872 {
873 dc.SetPen( mpLayout->mDarkPen );
874 dc.DrawPoint( bounds.x + bounds.width - 1, bounds.y -1 );
875 dc.SetPen( mpLayout->mLightPen );
876 dc.DrawPoint( bounds.x + bounds.width - 1, bounds.y + bounds.height );
877 }
878 }
879 }
880 }
881
882 void cbPaneDrawPlugin::DrawBarInnerShadeRect( cbBarInfo* pBar, wxDC& dc )
883 {
884 wxRect& bounds = pBar->mBoundsInParent;
885
886 dc.SetPen( mpLayout->mDarkPen );
887
888 dc.DrawLine( bounds.x + bounds.width - 1,
889 bounds.y,
890 bounds.x + bounds.width - 1,
891 bounds.y + bounds.height );
892
893 dc.DrawLine( bounds.x,
894 bounds.y + bounds.height - 1,
895 bounds.x + bounds.width,
896 bounds.y + bounds.height -1 );
897
898 dc.SetPen( mpLayout->mLightPen );
899
900 dc.DrawLine( bounds.x,
901 bounds.y,
902 bounds.x + bounds.width - 1,
903 bounds.y );
904
905 dc.DrawLine( bounds.x,
906 bounds.y,
907 bounds.x,
908 bounds.y + bounds.height - 1 );
909 }
910
911 void cbPaneDrawPlugin::DrawShade( int level, wxRect& rect, int alignment, wxDC& dc )
912 {
913 // simulates "guled-bricks" appearence of control bars
914
915 if ( ( alignment == wxTOP && level == 1 ) ||
916 ( alignment == wxBOTTOM && level == 0 ) ||
917 ( alignment == wxLEFT && level == 1 ) ||
918 ( alignment == wxRIGHT && level == 0 )
919 )
920
921 dc.SetPen( mpLayout->mDarkPen );
922 else
923 dc.SetPen( mpLayout->mLightPen );
924
925 if ( alignment == wxTOP )
926 {
927 if ( level == 0 )
928
929 dc.DrawLine( rect.x,
930 rect.y,
931 rect.x + rect.width - 1,
932 rect.y );
933 else
934 dc.DrawLine( rect.x - 1,
935 rect.y - 1,
936 rect.x + rect.width + 0,
937 rect.y - 1 );
938 }
939 else
940 if ( alignment == wxBOTTOM )
941 {
942 if ( level == 0 )
943
944 dc.DrawLine( rect.x,
945 rect.y + rect.height - 1,
946 rect.x + rect.width,
947 rect.y + rect.height - 1 );
948 else
949 dc.DrawLine( rect.x - 1,
950 rect.y + rect.height,
951 rect.x + rect.width + 1,
952 rect.y + rect.height );
953 }
954 else
955 if ( alignment == wxLEFT )
956 {
957 if ( level == 0 )
958
959 dc.DrawLine( rect.x,
960 rect.y,
961 rect.x,
962 rect.y + rect.height - 1 );
963 else
964 dc.DrawLine( rect.x - 1,
965 rect.y - 1,
966 rect.x - 1,
967 rect.y + rect.height );
968 }
969 else
970 if ( alignment == wxRIGHT )
971 {
972 if ( level == 0 )
973
974 dc.DrawLine( rect.x + rect.width - 1,
975 rect.y,
976 rect.x + rect.width - 1,
977 rect.y + rect.height );
978 else
979 {
980 dc.DrawLine( rect.x + rect.width,
981 rect.y - 1,
982 rect.x + rect.width,
983 rect.y + rect.height + 1 );
984 }
985 }
986 }
987
988 void cbPaneDrawPlugin::DrawShade1( int level, wxRect& rect, int alignment, wxDC& dc )
989 {
990 // simulates "guled-bricks" appearence of control bars
991
992 if ( ( alignment == wxTOP && level == 1 ) ||
993 ( alignment == wxBOTTOM && level == 0 ) ||
994 ( alignment == wxLEFT && level == 1 ) ||
995 ( alignment == wxRIGHT && level == 0 )
996 )
997
998 dc.SetPen( mpLayout->mDarkPen );
999 else
1000 dc.SetPen( mpLayout->mLightPen );
1001
1002 if ( alignment == wxTOP )
1003 {
1004 if ( level == 0 )
1005
1006 dc.DrawLine( rect.x,
1007 rect.y,
1008 rect.x + rect.width,
1009 rect.y );
1010 else
1011 dc.DrawLine( rect.x,
1012 rect.y - 1,
1013 rect.x + rect.width,
1014 rect.y - 1 );
1015 }
1016 else
1017 if ( alignment == wxBOTTOM )
1018 {
1019 if ( level == 0 )
1020
1021 dc.DrawLine( rect.x,
1022 rect.y + rect.height - 1,
1023 rect.x + rect.width,
1024 rect.y + rect.height - 1 );
1025 else
1026 dc.DrawLine( rect.x,
1027 rect.y + rect.height,
1028 rect.x + rect.width,
1029 rect.y + rect.height );
1030 }
1031 else
1032 if ( alignment == wxLEFT )
1033 {
1034 if ( level == 0 )
1035
1036 dc.DrawLine( rect.x,
1037 rect.y,
1038 rect.x,
1039 rect.y + rect.height );
1040 else
1041 dc.DrawLine( rect.x - 1,
1042 rect.y,
1043 rect.x - 1,
1044 rect.y + rect.height );
1045 }
1046 else
1047 if ( alignment == wxRIGHT )
1048 {
1049 if ( level == 0 )
1050
1051 dc.DrawLine( rect.x + rect.width - 1,
1052 rect.y,
1053 rect.x + rect.width - 1,
1054 rect.y + rect.height );
1055 else
1056 {
1057 dc.DrawLine( rect.x + rect.width,
1058 rect.y ,
1059 rect.x + rect.width,
1060 rect.y + rect.height );
1061 }
1062 }
1063 }
1064
1065 void cbPaneDrawPlugin::DrawPaneShade( wxDC& dc, int alignment )
1066 {
1067 if ( !mpPane->mProps.mShow3DPaneBorderOn ) return;
1068
1069 wxRect bounds = mpPane->mBoundsInParent;
1070
1071 bounds.x += mpPane->mLeftMargin;
1072 bounds.y += mpPane->mTopMargin;
1073 bounds.width -= ( mpPane->mLeftMargin + mpPane->mRightMargin );
1074 bounds.height -= ( mpPane->mTopMargin + mpPane->mBottomMargin );
1075
1076 DrawShade( 0, bounds, alignment, dc );
1077 DrawShade( 1, bounds, alignment, dc );
1078 }
1079
1080 void cbPaneDrawPlugin::DrawPaneShadeForRow( cbRowInfo* pRow, wxDC& dc )
1081 {
1082 if ( !mpPane->mProps.mShow3DPaneBorderOn ) return;
1083
1084 // do not draw decoration, if pane has "vainished"
1085 if ( mpPane->mPaneWidth < 0 ||
1086 mpPane->mPaneHeight < 0 )
1087
1088 return;
1089
1090 wxRect bounds = pRow->mBoundsInParent;
1091
1092 if ( mpPane->mAlignment == wxTOP ||
1093 mpPane->mAlignment == wxBOTTOM )
1094 {
1095 --bounds.y;
1096 bounds.height += 2;
1097
1098 DrawShade1( 0, bounds, wxLEFT, dc );
1099 DrawShade1( 1, bounds, wxLEFT, dc );
1100 DrawShade1( 0, bounds, wxRIGHT, dc );
1101 DrawShade1( 1, bounds, wxRIGHT, dc );
1102
1103 if ( !pRow->mpNext )
1104 DrawPaneShade( dc, wxBOTTOM );
1105
1106 if ( !pRow->mpPrev )
1107 DrawPaneShade( dc, wxTOP );
1108 }
1109 else
1110 {
1111 --bounds.x;
1112 bounds.width += 2;
1113
1114 DrawShade1( 0, bounds, wxTOP, dc );
1115 DrawShade1( 1, bounds, wxTOP, dc );
1116 DrawShade1( 0, bounds, wxBOTTOM, dc );
1117 DrawShade1( 1, bounds, wxBOTTOM, dc );
1118
1119 if ( !pRow->mpNext )
1120 DrawPaneShade( dc, wxRIGHT );
1121
1122 if ( !pRow->mpPrev )
1123 DrawPaneShade( dc, wxLEFT );
1124 }
1125 }
1126
1127 void cbPaneDrawPlugin::OnDrawPaneDecorations( cbDrawPaneDecorEvent& event )
1128 {
1129 wxDC& dc = *event.mpDc;
1130
1131 cbDockPane* pPane = event.mpPane;
1132
1133 RowArrayT& lst = pPane->GetRowList();
1134
1135 // FIXME:: this is a workaround for some glitches
1136
1137 if ( lst.Count() )
1138 {
1139 cbRowInfo* pLastRow = lst[ lst.Count() - 1 ];
1140
1141 pPane->PaintRowBackground( pLastRow, dc );
1142 pPane->PaintRowDecorations( pLastRow, dc );
1143 pPane->PaintRowHandles( pLastRow, dc );
1144 }
1145
1146 if ( !pPane->mProps.mShow3DPaneBorderOn ) return;
1147
1148 // do not draw decoration, if pane is completely hidden
1149 if ( event.mpPane->mPaneWidth < 0 ||
1150 event.mpPane->mPaneHeight < 0 )
1151
1152 return;
1153
1154 DrawPaneShade( dc, wxTOP );
1155 DrawPaneShade( dc, wxBOTTOM );
1156 DrawPaneShade( dc, wxLEFT );
1157 DrawPaneShade( dc, wxRIGHT );
1158
1159 event.Skip(); // pass event to the next plugin
1160 }
1161
1162 // bar decoration/sizing handlers
1163
1164 void cbPaneDrawPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent& event )
1165 {
1166 cbBarInfo* pBar = event.mpBar;
1167 wxDC& dc = *event.mpDc;
1168
1169 // draw brick borders
1170
1171 wxRect& rect = event.mBoundsInParent;
1172
1173 dc.SetPen( mpLayout->mLightPen );
1174
1175 // horiz
1176 dc.DrawLine( rect.x, rect.y,
1177 rect.x + rect.width-1, rect.y );
1178
1179 // vert
1180 dc.DrawLine( rect.x, rect.y,
1181 rect.x, rect.y + rect.height-1 );
1182
1183
1184 dc.SetPen( mpLayout->mDarkPen );
1185
1186 // vert
1187 dc.DrawLine( rect.x + rect.width-1, rect.y,
1188 rect.x + rect.width-1, rect.y + rect.height-1 );
1189
1190 // horiz
1191 dc.DrawLine( rect.x, rect.y + rect.height-1,
1192 rect.x + rect.width, rect.y + rect.height-1 );
1193
1194 event.Skip(); // pass event to the next plugin
1195 }
1196
1197 void cbPaneDrawPlugin::OnDrawBarHandles( cbDrawBarHandlesEvent& event )
1198 {
1199 // short-cuts
1200 cbBarInfo* pBar = event.mpBar;
1201 wxDC& dc = *event.mpDc;
1202 mpPane = event.mpPane;
1203
1204 // draw handles around the bar if present
1205
1206 if ( pBar->mHasLeftHandle ||
1207 pBar->mHasRightHandle )
1208 {
1209 wxRect& bounds = pBar->mBoundsInParent;
1210
1211 if ( mpPane->IsHorizontal() )
1212 {
1213 if ( pBar->mHasLeftHandle )
1214
1215 mpPane->DrawVertHandle( dc, bounds.x - mpPane->mProps.mResizeHandleSize -1,
1216 bounds.y, bounds.height );
1217
1218 if ( pBar->mHasRightHandle )
1219
1220 mpPane->DrawVertHandle( dc,
1221 bounds.x + bounds.width -1,
1222 bounds.y, bounds.height );
1223 }
1224 else
1225 {
1226 if ( pBar->mHasLeftHandle )
1227
1228 mpPane->DrawHorizHandle( dc, bounds.x,
1229 bounds.y - mpPane->mProps.mResizeHandleSize - 1,
1230 bounds.width );
1231
1232 if ( pBar->mHasRightHandle )
1233
1234 mpPane->DrawHorizHandle( dc, bounds.x,
1235 bounds.y + bounds.height - 1,
1236 bounds.width );
1237 }
1238 }
1239
1240 event.Skip(); // pass event to the next plugin
1241 }
1242
1243 void cbPaneDrawPlugin::OnStartDrawInArea( cbStartDrawInAreaEvent& event )
1244 {
1245 // DBG::
1246 wxASSERT( mpClntDc == NULL );
1247
1248 // FOR NOW:: create/destory client-dc upon each drawing
1249 mpClntDc = new wxClientDC( &mpLayout->GetParentFrame() );
1250
1251 (*event.mppDc) = mpClntDc;
1252
1253 mpClntDc->SetClippingRegion( event.mArea.x, event.mArea.y,
1254 event.mArea.width, event.mArea.height );
1255 }
1256
1257 void cbPaneDrawPlugin::OnFinishDrawInArea( cbFinishDrawInAreaEvent& event )
1258 {
1259 // DBG::
1260 wxASSERT( mpClntDc );
1261
1262 delete mpClntDc;
1263
1264 mpClntDc = NULL;
1265 }