]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/panedrawpl.cpp
wxX11:
[wxWidgets.git] / contrib / src / fl / panedrawpl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: panedrawpl.cpp
3 // Purpose: cbPaneDrawPlugin implementation.
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 06/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "panedrawpl.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include <math.h>
28 #include <stdlib.h>
29
30 #include "wx/utils.h" // import wxMin,wxMax macros
31
32 #include "wx/fl/panedrawpl.h"
33
34 // bitmap bits used by bar-resizing brush
35
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.
40
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
45 };
46
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 );
50 /*
51 static void set_cursor_bits( const char** img, char* bits, int width, int height )
52 {
53 for( int i = 0; i != (width*height)/8; ++i )
54 bits[i] = 0;
55
56 for( int y = 0; y != height; ++y )
57 {
58 const char* row = img[0];
59
60 for( int x = 0; x != width; ++x )
61 {
62 int bitNo = y*width + x;
63
64 char value = ( row[x] != '.' ) ? 1 : 0;
65
66 bits[ bitNo / sizeof(char) ] |=
67 ( ( bitNo %sizeof(char) ) << value );
68 }
69
70 ++img;
71 }
72 }
73 */
74
75 /***** Implementation for class cbPaneDrawPlugin *****/
76
77 IMPLEMENT_DYNAMIC_CLASS( cbPaneDrawPlugin, cbPluginBase )
78
79 BEGIN_EVENT_TABLE( cbPaneDrawPlugin, cbPluginBase )
80
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 )
86
87
88 EVT_PL_DRAW_PANE_BKGROUND ( cbPaneDrawPlugin::OnDrawPaneBackground )
89 EVT_PL_DRAW_PANE_DECOR ( cbPaneDrawPlugin::OnDrawPaneDecorations )
90
91 EVT_PL_DRAW_ROW_DECOR ( cbPaneDrawPlugin::OnDrawRowDecorations )
92 EVT_PL_DRAW_ROW_HANDLES ( cbPaneDrawPlugin::OnDrawRowHandles )
93 EVT_PL_DRAW_ROW_BKGROUND ( cbPaneDrawPlugin::OnDrawRowBackground )
94
95 EVT_PL_SIZE_BAR_WND ( cbPaneDrawPlugin::OnSizeBarWindow )
96 EVT_PL_DRAW_BAR_DECOR ( cbPaneDrawPlugin::OnDrawBarDecorations )
97 EVT_PL_DRAW_BAR_HANDLES ( cbPaneDrawPlugin::OnDrawBarHandles )
98
99 EVT_PL_START_DRAW_IN_AREA ( cbPaneDrawPlugin::OnStartDrawInArea )
100 EVT_PL_FINISH_DRAW_IN_AREA ( cbPaneDrawPlugin::OnFinishDrawInArea )
101
102 END_EVENT_TABLE()
103
104 cbPaneDrawPlugin::cbPaneDrawPlugin(void)
105
106 : mResizeStarted ( FALSE ),
107
108 mResizeCursorOn ( FALSE ),
109 mpDraggedBar ( NULL ),
110 mpResizedRow ( NULL ),
111
112 mRowHandleHitted ( FALSE ),
113 mIsUpperHandle ( FALSE ),
114 mBarHandleHitted ( FALSE ),
115 mIsLeftHandle ( FALSE ),
116 mBarContentHitted ( FALSE ),
117
118 mpClntDc ( NULL ),
119 mpPane ( NULL )
120 {}
121
122 cbPaneDrawPlugin::cbPaneDrawPlugin( wxFrameLayout* pPanel, int paneMask )
123
124 : cbPluginBase( pPanel, paneMask ),
125
126 // bar-row resizing state varaibles
127
128 mResizeStarted ( FALSE ),
129
130 mResizeCursorOn ( FALSE ),
131 mpDraggedBar ( NULL ),
132 mpResizedRow ( NULL ),
133
134 mRowHandleHitted ( FALSE ),
135 mIsUpperHandle ( FALSE ),
136 mBarHandleHitted ( FALSE ),
137 mIsLeftHandle ( FALSE ),
138 mBarContentHitted ( FALSE ),
139
140 mpClntDc ( NULL ),
141 mpPane ( NULL )
142 {}
143
144 cbPaneDrawPlugin::~cbPaneDrawPlugin()
145 {
146 // DBG::
147 wxASSERT( mpClntDc == NULL );
148 }
149
150 void cbPaneDrawPlugin::DrawDraggedHandle( const wxPoint& pos, cbDockPane& pane )
151 {
152 wxScreenDC dc;
153 int ofsX = 0;
154 int ofsY = 0;
155
156 wxPoint fpos = pos;
157 pane.PaneToFrame( &fpos.x, &fpos.y );
158
159 // short-cut
160 int resizeHndSize = pane.mProps.mResizeHandleSize;
161
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.
166
167 wxScreenDC::StartDrawingOnTop(&mpLayout->GetParentFrame());
168
169 mpLayout->GetParentFrame().ClientToScreen( &ofsX, &ofsY );
170
171 int prevLF = dc.GetLogicalFunction();
172
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
176
177 wxBitmap checker( (const char*)_gCheckerImg, 8,8 );
178
179 wxBrush checkerBrush( checker );
180
181 dc.SetPen( mpLayout->mNullPen );
182 dc.SetBrush( checkerBrush );
183 dc.SetLogicalFunction( wxXOR );
184
185 if ( mHandleIsVertical )
186 {
187 int delta = pos.x - mDragOrigin.x;
188
189 if ( !pane.IsHorizontal() )
190
191 delta = pos.y - mDragOrigin.y;
192
193 int realHndOfs;
194 realHndOfs = pane.mBoundsInParent.x + pane.mLeftMargin + mHandleOfs;
195
196 int newX = realHndOfs + delta;
197
198 if ( newX + resizeHndSize > mHandleDragArea.x + mHandleDragArea.width )
199
200 newX = mHandleDragArea.x + mHandleDragArea.width - 1;
201
202 if ( newX < mHandleDragArea.x )
203
204 newX = mHandleDragArea.x;
205
206 mDraggedDelta = newX - realHndOfs;
207
208 dc.DrawRectangle( newX + ofsX, mHandleDragArea.y + ofsY,
209 resizeHndSize + 1,
210 mHandleDragArea.height+1 );
211 }
212 else
213 {
214 // otherwise, draw horizontal handle
215
216 int delta = pos.y - mDragOrigin.y;
217
218 if ( !pane.IsHorizontal() )
219
220 delta = pos.x - mDragOrigin.x;
221
222 int realHndOfs;
223 realHndOfs = pane.mBoundsInParent.y + pane.mTopMargin + mHandleOfs;
224
225 int newY = realHndOfs + delta;
226
227 if ( newY + resizeHndSize > mHandleDragArea.y + mHandleDragArea.height )
228
229 newY = mHandleDragArea.y + mHandleDragArea.height - 1;
230
231 if ( newY < mHandleDragArea.y )
232
233 newY = mHandleDragArea.y;
234
235 mDraggedDelta = newY - realHndOfs;
236
237 dc.DrawRectangle( mHandleDragArea.x + ofsX, newY + ofsY,
238 mHandleDragArea.width + 1,
239 resizeHndSize + 1 );
240 }
241
242 dc.SetLogicalFunction( prevLF );
243
244 // "End drawing on top (frees the window used for drawing
245 // over the screen)" --J.S.
246 wxScreenDC::EndDrawingOnTop();
247 }
248
249 void cbPaneDrawPlugin::OnMouseMove( cbMotionEvent& event )
250 {
251 if ( !mResizeStarted )
252 {
253 // if nothing is started, do hit-tests
254
255 bool prevWasRowHandle = mRowHandleHitted;
256
257 mBarContentHitted = FALSE;
258 mBarHandleHitted = FALSE;
259 mRowHandleHitted = FALSE;
260
261 int testResult =
262 event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
263 &mpResizedRow,
264 &mpDraggedBar );
265
266 if ( testResult != CB_NO_ITEMS_HITTED )
267 {
268 if ( testResult == CB_BAR_CONTENT_HITTED )
269 {
270 // restore cursor, if non of the handles were hit
271 if ( mResizeCursorOn )
272 {
273 // remove resizing hints
274
275 mpLayout->ReleaseEventsFromPane( event.mpPane );
276 mpLayout->ReleaseEventsFromPlugin( this );
277
278 mResizeCursorOn = FALSE;
279
280 mBarContentHitted = TRUE;
281
282 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
283 }
284
285 // TBD:: fire something like "mouse-over-bar" event
286
287 event.Skip(); // pass event to the next handler in the chain
288 return;
289 }
290
291 wxCursor* pCurs = NULL;
292
293 if ( testResult == CB_UPPER_ROW_HANDLE_HITTED ||
294 testResult == CB_LOWER_ROW_HANDLE_HITTED)
295 {
296 if ( event.mpPane->IsHorizontal() )
297
298 pCurs = mpLayout->mpVertCursor;
299 else
300 pCurs = mpLayout->mpHorizCursor;
301
302 mRowHandleHitted = TRUE;
303 mIsUpperHandle = ( testResult == CB_UPPER_ROW_HANDLE_HITTED );
304 }
305 else
306 {
307 // otherwise, if inter-bar handle was hitted
308
309 if ( event.mpPane->IsHorizontal() )
310
311 pCurs = mpLayout->mpHorizCursor;
312 else
313 pCurs = mpLayout->mpVertCursor;
314
315 mBarHandleHitted = TRUE;
316 mIsLeftHandle = ( testResult == CB_LEFT_BAR_HANDLE_HITTED );
317 }
318
319 // avoid setting the same cursor twice
320
321 if ( !mResizeCursorOn || prevWasRowHandle != mRowHandleHitted )
322 {
323 if ( !mResizeCursorOn )
324 {
325 // caputre if not captured yet
326 mpLayout->CaptureEventsForPane( event.mpPane );
327 mpLayout->CaptureEventsForPlugin( this );
328 }
329
330 mpLayout->GetParentFrame().SetCursor( *pCurs );
331 }
332
333 mResizeCursorOn = TRUE;
334
335 // handled is being dragged now, thus event is "eaten" by this plugin
336
337 return;
338
339 } // end of if (HitTestBarHandles())
340
341 // restore cursor, if non of the handles were hit
342 if ( mResizeCursorOn )
343 {
344 mpLayout->ReleaseEventsFromPane( event.mpPane );
345 mpLayout->ReleaseEventsFromPlugin( this );
346
347 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
348
349 mResizeCursorOn = FALSE;
350 }
351
352 event.Skip(); // pass event to the next plugin
353 }
354
355 // othewise series of actions, if something has already started
356
357 else
358 if ( mResizeStarted )
359 {
360 // apply xor-mask twice
361 DrawDraggedHandle( mPrevPos, *event.mpPane );
362
363 // draw handle in the new position
364 DrawDraggedHandle( event.mPos, *event.mpPane );
365 mPrevPos = event.mPos;
366
367 // handled is dragged, thus event is "eaten" by this plugin
368 }
369 else
370 event.Skip(); // pass event to the next plugin
371 }
372
373 void cbPaneDrawPlugin::OnLDblClick( cbLeftDClickEvent& event )
374 {
375 if ( !mResizeCursorOn )
376 {
377 cbBarInfo* pBarToFloat;
378
379 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
380 &mpResizedRow,
381 &pBarToFloat ) == CB_BAR_CONTENT_HITTED
382 )
383 {
384 return;
385 }
386
387 event.Skip();
388 }
389 }
390
391 void cbPaneDrawPlugin::OnLButtonDown( cbLeftDownEvent& event )
392 {
393 wxASSERT( !mResizeStarted );
394
395 if ( mResizeCursorOn )
396 {
397 mResizeStarted = TRUE;
398 mDragOrigin = event.mPos;
399
400 // setup constraints for the dragging handle
401
402 int from, till;
403 mHandleOfs = 0;
404 mHandleIsVertical = FALSE;
405
406 if ( mRowHandleHitted )
407
408 event.mpPane->GetRowResizeRange( mpResizedRow, &from, &till, mIsUpperHandle );
409 else
410 // otherwise if bar handle was hitted
411 event.mpPane->GetBarResizeRange( mpDraggedBar, &from, &till, mIsLeftHandle );
412
413 if ( mRowHandleHitted )
414 {
415 mHandleIsVertical = ( event.mpPane->IsHorizontal() ) ? FALSE : TRUE;
416
417 mHandleDragArea.x = 0;
418 mHandleDragArea.width = event.mpPane->mPaneWidth;
419
420 mHandleDragArea.y = from;
421 mHandleDragArea.height = till - from;
422
423 if ( mIsUpperHandle )
424
425 mHandleOfs = mpResizedRow->mRowY;
426 else
427 mHandleOfs = mpResizedRow->mRowY +
428 mpResizedRow->mRowHeight -
429 event.mpPane->mProps.mResizeHandleSize;
430 }
431 else
432 {
433 // otehrwise if bar handle dragged
434
435 // cbRowInfo& rowInfo = *mpDraggedBar->mpRow;
436 wxRect& bounds = mpDraggedBar->mBounds;
437
438 mHandleIsVertical = ( event.mpPane->IsHorizontal() ) ? TRUE : FALSE;
439
440 mHandleDragArea.x = from;
441 mHandleDragArea.width = till - from;
442
443
444 mHandleDragArea.y = bounds.y;
445 mHandleDragArea.height = bounds.height;
446
447 // left-side-handle mBounds
448 if ( mIsLeftHandle )
449
450 mHandleOfs = bounds.x;
451 else
452 mHandleOfs = bounds.x +
453 bounds.width - event.mpPane->mProps.mResizeHandleSize;
454
455 }
456
457 event.mpPane->PaneToFrame( &mHandleDragArea );
458 DrawDraggedHandle(mDragOrigin, *event.mpPane);
459
460 mPrevPos = mDragOrigin;
461
462 return;
463 // handled is dragged, thus event is "eaten" by this plugin
464 }
465 else
466 {
467 cbBarInfo* pDraggedBar;
468
469 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
470 &mpResizedRow,
471 &pDraggedBar ) == CB_BAR_CONTENT_HITTED
472 )
473 {
474 int x = event.mPos.x,
475 y = event.mPos.y;
476
477 event.mpPane->PaneToFrame( &x, &y );
478
479 cbStartBarDraggingEvent dragEvt( pDraggedBar, wxPoint(x,y), event.mpPane );
480
481 mpLayout->FirePluginEvent( dragEvt );
482
483 return; // event is "eaten" by this plugin
484 }
485 }
486
487 event.Skip(); // pass event to the next plugin in the chain
488 }
489
490 void cbPaneDrawPlugin::OnLButtonUp( cbLeftUpEvent& event )
491 {
492 if ( mResizeStarted )
493 {
494 DrawDraggedHandle( event.mPos, *event.mpPane );
495
496 mResizeStarted = FALSE;
497 mResizeCursorOn = FALSE;
498
499 mpLayout->ReleaseEventsFromPane( event.mpPane );
500 mpLayout->ReleaseEventsFromPlugin( this );
501
502 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
503
504 if ( mRowHandleHitted )
505 {
506 event.mpPane->ResizeRow( mpResizedRow,
507 mDraggedDelta,
508 mIsUpperHandle );
509 }
510 else
511 {
512 event.mpPane->ResizeBar( mpDraggedBar,
513 mDraggedDelta,
514 mIsLeftHandle );
515 }
516
517 mpDraggedBar = NULL;
518 mpResizedRow = NULL;
519
520 // handled dragging action was finished by this mouse-up,
521 // thus event is "eaten" by this plugin
522
523 return;
524 }
525
526 event.Skip(); // pass event to the next plugin
527 }
528
529 void cbPaneDrawPlugin::OnRButtonUp( cbRightUpEvent& event )
530 {
531 wxPoint fpos = event.mPos;
532 event.mpPane->PaneToFrame( &fpos.x, &fpos.y );
533
534 cbBarInfo* pDraggedBar;
535
536 // user clicks inside the bar contnet, fire bar-customization event
537
538 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
539 &mpResizedRow,
540 &pDraggedBar ) == CB_BAR_CONTENT_HITTED
541 )
542 {
543 cbCustomizeBarEvent cbEvt( pDraggedBar, fpos, event.mpPane );
544
545 mpLayout->FirePluginEvent( cbEvt );
546
547 return; // event is "eaten" by this plugin
548 }
549
550 // otherwise fire whole-layout customization event
551
552 cbCustomizeLayoutEvent csEvt( fpos );
553
554 mpLayout->FirePluginEvent( csEvt );
555
556 // event is "eaten" by this plugin
557 }
558
559 void cbPaneDrawPlugin::OnSizeBarWindow( cbSizeBarWndEvent& event )
560 {
561 cbBarInfo& bar = *event.mpBar;
562 mpPane = event.mpPane;
563
564 // it's possible that a bar does not have it's own window!
565 if ( !bar.mpBarWnd ) return;
566
567 wxRect& bounds = event.mBoundsInParent;
568
569 // check visibility
570 if ( bounds.height != 0 )
571 {
572 // size smaller than bounds, to leave space for shade lines
573
574 // FIXME:: +/- 1s
575
576 bar.mpBarWnd->wxWindow::SetSize( bounds.x + 1 + bar.mDimInfo.mHorizGap,
577 bounds.y + 1 + bar.mDimInfo.mVertGap,
578 bounds.width - 2 - bar.mDimInfo.mHorizGap*2,
579 bounds.height - 2 - bar.mDimInfo.mVertGap *2 ,
580 0
581 );
582
583 if ( !bar.mpBarWnd->IsShown() )
584
585 bar.mpBarWnd->Show( TRUE );
586 }
587 else
588 // hide bar if not visible
589 bar.mpBarWnd->Show( FALSE );
590
591 event.Skip(); // pass event to the next plugin in the chain
592 }
593
594 void cbPaneDrawPlugin::OnDrawRowDecorations( cbDrawRowDecorEvent& event )
595 {
596 DrawPaneShadeForRow( event.mpRow, *event.mpDc );
597
598 event.Skip(); // pass event to the next plugin
599 }
600
601 void cbPaneDrawPlugin::DrawUpperRowHandle( cbRowInfo* pRow, wxDC& dc )
602 {
603 wxRect& bounds = pRow->mBoundsInParent;
604
605 if ( mpPane->IsHorizontal() )
606 {
607 if ( pRow->mHasUpperHandle )
608
609 mpPane->DrawHorizHandle( dc, bounds.x,
610 bounds.y-1,
611 pRow->mRowWidth );
612 }
613 else
614 {
615 if ( pRow->mHasUpperHandle )
616
617 mpPane->DrawVertHandle( dc, bounds.x-1,
618 bounds.y, pRow->mRowWidth );
619 }
620 }
621
622 void cbPaneDrawPlugin::DrawLowerRowHandle( cbRowInfo* pRow, wxDC& dc )
623 {
624 wxRect& bounds = pRow->mBoundsInParent;
625
626 // check if iter-row handles present
627
628 if ( mpPane->IsHorizontal() )
629 {
630 if ( pRow->mHasLowerHandle )
631
632 mpPane->DrawHorizHandle( dc, bounds.x, bounds.y + bounds.height - mpPane->mProps.mResizeHandleSize - 1,
633 pRow->mRowWidth );
634 }
635 else
636 {
637 if ( pRow->mHasLowerHandle )
638
639 mpPane->DrawVertHandle( dc, bounds.x + bounds.width - mpPane->mProps.mResizeHandleSize - 1,
640 bounds.y, pRow->mRowWidth );
641 }
642 }
643
644 void cbPaneDrawPlugin::OnDrawRowHandles( cbDrawRowHandlesEvent& event )
645 {
646 // short-cuts
647 cbRowInfo* pRow = event.mpRow;
648 wxDC& dc = *event.mpDc;
649 mpPane = event.mpPane;
650
651 // draw handles of surrounding rows first
652
653 if ( pRow->mpPrev && pRow->mpPrev->mHasLowerHandle )
654
655 DrawLowerRowHandle( pRow->mpPrev, dc );
656
657 if ( pRow->mpNext && pRow->mpNext->mHasUpperHandle )
658
659 DrawUpperRowHandle( pRow->mpNext, dc );
660
661 // draw handles of the given row
662
663 if ( pRow->mHasUpperHandle )
664
665 DrawUpperRowHandle( pRow, dc );
666
667 if ( pRow->mHasLowerHandle )
668
669 DrawLowerRowHandle( pRow, dc );
670
671 event.Skip(); // pass event to the next plugin
672 }
673
674 void cbPaneDrawPlugin::OnDrawPaneBackground ( cbDrawPaneBkGroundEvent& event )
675 {
676 wxDC& dc = *event.mpDc;
677 mpPane = event.mpPane;
678
679 // FOR NOW:: hard-coded
680 wxBrush bkBrush( mpLayout->mBorderPen.GetColour(), wxSOLID );
681
682 dc.SetBrush( bkBrush );
683 dc.SetPen( mpLayout->mNullPen );
684
685 wxRect& bounds = mpPane->mBoundsInParent;
686
687 if ( mpPane->mTopMargin >= 1 )
688
689 dc.DrawRectangle( bounds.x, bounds.y,
690 bounds.width+1,
691 mpPane->mTopMargin + 1);
692
693
694 if ( mpPane->mBottomMargin >= 1 )
695
696 dc.DrawRectangle( bounds.x,
697 bounds.y + bounds.height - mpPane->mBottomMargin,
698 bounds.width + 1,
699 mpPane->mBottomMargin + 1);
700
701
702 if ( mpPane->mLeftMargin >= 1 )
703
704 dc.DrawRectangle( bounds.x,
705 bounds.y + mpPane->mTopMargin - 1,
706 mpPane->mLeftMargin + 1,
707 bounds.height - mpPane->mTopMargin - mpPane->mBottomMargin + 2);
708
709
710 if ( mpPane->mRightMargin >= 1 )
711
712 dc.DrawRectangle( bounds.x + bounds.width - mpPane->mRightMargin,
713 bounds.y + mpPane->mTopMargin - 1,
714 mpPane->mRightMargin + 1,
715 bounds.height - mpPane->mTopMargin - mpPane->mBottomMargin + 2);
716
717 event.Skip(); // pass event to the next plugin
718 }
719
720 void cbPaneDrawPlugin::OnDrawRowBackground ( cbDrawRowBkGroundEvent& event )
721 {
722 // short-cuts
723 cbRowInfo* pRow = event.mpRow;
724 wxDC& dc = *event.mpDc;
725 mpPane = event.mpPane;
726
727 // get ready
728 wxRect rowBounds = pRow->mBoundsInParent;
729 bool isHorizontal = event.mpPane->IsHorizontal();
730
731 // int prevPos;
732
733 if ( isHorizontal )
734 {
735 // prevPos = rowBounds.x;
736 // include one line above and below the row
737 --rowBounds.y;
738 rowBounds.height += 2;
739
740 --rowBounds.x;
741 rowBounds.width += 2;
742 }
743 else
744 {
745 // prevPos = rowBounds.y;
746 // include one line above and below the row
747 --rowBounds.x;
748 rowBounds.width += 2;
749
750 --rowBounds.y;
751 rowBounds.height += 2;
752 }
753
754 //#define TEST_BK_ERASING
755
756 #ifdef TEST_BK_ERASING
757
758 // DBG::
759 wxBrush br0( wxColour(0,160,160), wxSOLID );
760 dc.SetBrush(br0);
761 dc.SetPen ( mpLayout->mNullPen );
762 dc.DrawRectangle( rowBounds.x, rowBounds.y,
763 rowBounds.width + 1,
764 rowBounds.height + 1 );
765 #endif
766
767 wxBrush bkBrush( mpLayout->mGrayPen.GetColour(), wxSOLID );
768
769 dc.SetPen ( mpLayout->mNullPen );
770 dc.SetBrush( bkBrush );
771
772 // fill background-recatangle of entire row area
773 dc.DrawRectangle( rowBounds.x, rowBounds.y,
774 rowBounds.width + 1,
775 rowBounds.height + 1 );
776
777 dc.SetBrush( wxNullBrush );
778
779 // draw "shaded-side-bars" for each bar
780 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
781 {
782 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
783
784 if ( isHorizontal )
785 {
786 DrawShade( 1, bounds, FL_ALIGN_LEFT, dc );
787 DrawShade( 1, bounds, FL_ALIGN_RIGHT, dc );
788 }
789 else
790 {
791 DrawShade( 1, bounds, FL_ALIGN_TOP, dc );
792 DrawShade( 1, bounds, FL_ALIGN_BOTTOM, dc );
793 }
794 }
795
796 // draw extra shades to simulate "glued-bricks" effect
797
798 // TBD:: reduce exessive drawing of shades, when the
799 // row handle is present, and shades will be overr-drawn anyway
800
801 DrawUpperRowShades( pRow, dc, 1 ); // outer shade
802
803 if ( pRow->mpPrev )
804 {
805 DrawLowerRowShades( pRow->mpPrev, dc, 1 ); // outter shade
806 DrawLowerRowShades( pRow->mpPrev, dc, 0 ); // inner shade
807 }
808
809 DrawLowerRowShades( pRow, dc, 1 );
810
811 if ( pRow->mpNext )
812 {
813 DrawUpperRowShades( pRow->mpNext, dc, 1 );
814 DrawUpperRowShades( pRow->mpNext, dc, 0 );
815 }
816
817 event.Skip(); // pass event to the next plugin
818 }
819
820 void cbPaneDrawPlugin::DrawUpperRowShades( cbRowInfo* pRow, wxDC& dc, int level )
821 {
822 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
823 {
824 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
825
826 if ( mpPane->IsHorizontal() )
827 {
828 DrawShade( level, bounds, FL_ALIGN_TOP, dc );
829 if ( level == 1 )
830 {
831 dc.SetPen( mpLayout->mDarkPen );
832 dc.DrawPoint( bounds.x - 1, bounds.y );
833 dc.SetPen( mpLayout->mLightPen );
834 dc.DrawPoint( bounds.x + bounds.width , bounds.y );
835 }
836 }
837 else
838 {
839 DrawShade( level, bounds, FL_ALIGN_LEFT, dc );
840 if ( level == 1 )
841 {
842 dc.SetPen( mpLayout->mDarkPen );
843 dc.DrawPoint( bounds.x, bounds.y -1 );
844 dc.SetPen( mpLayout->mLightPen );
845 dc.DrawPoint( bounds.x, bounds.y + bounds.height );
846 }
847 }
848 }
849 }
850
851 void cbPaneDrawPlugin::DrawLowerRowShades( cbRowInfo* pRow, wxDC& dc, int level )
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, FL_ALIGN_BOTTOM, 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, FL_ALIGN_RIGHT, 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 == FL_ALIGN_TOP && level == 1 ) ||
916 ( alignment == FL_ALIGN_BOTTOM && level == 0 ) ||
917 ( alignment == FL_ALIGN_LEFT && level == 1 ) ||
918 ( alignment == FL_ALIGN_RIGHT && level == 0 )
919 )
920
921 dc.SetPen( mpLayout->mDarkPen );
922 else
923 dc.SetPen( mpLayout->mLightPen );
924
925 if ( alignment == FL_ALIGN_TOP )
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 == FL_ALIGN_BOTTOM )
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 == FL_ALIGN_LEFT )
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 == FL_ALIGN_RIGHT )
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 == FL_ALIGN_TOP && level == 1 ) ||
993 ( alignment == FL_ALIGN_BOTTOM && level == 0 ) ||
994 ( alignment == FL_ALIGN_LEFT && level == 1 ) ||
995 ( alignment == FL_ALIGN_RIGHT && level == 0 )
996 )
997
998 dc.SetPen( mpLayout->mDarkPen );
999 else
1000 dc.SetPen( mpLayout->mLightPen );
1001
1002 if ( alignment == FL_ALIGN_TOP )
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 == FL_ALIGN_BOTTOM )
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 == FL_ALIGN_LEFT )
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 == FL_ALIGN_RIGHT )
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 == FL_ALIGN_TOP ||
1093 mpPane->mAlignment == FL_ALIGN_BOTTOM )
1094 {
1095 --bounds.y;
1096 bounds.height += 2;
1097
1098 DrawShade1( 0, bounds, FL_ALIGN_LEFT, dc );
1099 DrawShade1( 1, bounds, FL_ALIGN_LEFT, dc );
1100 DrawShade1( 0, bounds, FL_ALIGN_RIGHT, dc );
1101 DrawShade1( 1, bounds, FL_ALIGN_RIGHT, dc );
1102
1103 if ( !pRow->mpNext )
1104 DrawPaneShade( dc, FL_ALIGN_BOTTOM );
1105
1106 if ( !pRow->mpPrev )
1107 DrawPaneShade( dc, FL_ALIGN_TOP );
1108 }
1109 else
1110 {
1111 --bounds.x;
1112 bounds.width += 2;
1113
1114 DrawShade1( 0, bounds, FL_ALIGN_TOP, dc );
1115 DrawShade1( 1, bounds, FL_ALIGN_TOP, dc );
1116 DrawShade1( 0, bounds, FL_ALIGN_BOTTOM, dc );
1117 DrawShade1( 1, bounds, FL_ALIGN_BOTTOM, dc );
1118
1119 if ( !pRow->mpNext )
1120 DrawPaneShade( dc, FL_ALIGN_RIGHT );
1121
1122 if ( !pRow->mpPrev )
1123 DrawPaneShade( dc, FL_ALIGN_LEFT );
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, FL_ALIGN_TOP );
1155 DrawPaneShade( dc, FL_ALIGN_BOTTOM );
1156 DrawPaneShade( dc, FL_ALIGN_LEFT );
1157 DrawPaneShade( dc, FL_ALIGN_RIGHT );
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/destroy 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 }
1266