]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/panedrawpl.cpp
Various tweaks, fixes, and additions
[wxWidgets.git] / contrib / src / fl / 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 #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 // TBD: ????
385 return;
386
387 mpLayout->SetBarState( pBarToFloat, wxCBAR_FLOATING, TRUE );
388
389 mpLayout->RepositionFloatedBar( pBarToFloat );
390
391 return; // event is "eaten" by this plugin
392 }
393
394 event.Skip();
395 }
396 }
397
398 void cbPaneDrawPlugin::OnLButtonDown( cbLeftDownEvent& event )
399 {
400 wxASSERT( !mResizeStarted );
401
402 if ( mResizeCursorOn )
403 {
404 mResizeStarted = TRUE;
405 mDragOrigin = event.mPos;
406
407 // setup constraints for the dragging handle
408
409 int from, till;
410 mHandleOfs = 0;
411 mHandleIsVertical = FALSE;
412
413 if ( mRowHandleHitted )
414
415 event.mpPane->GetRowResizeRange( mpResizedRow, &from, &till, mIsUpperHandle );
416 else
417 // otherwise if bar handle was hitted
418 event.mpPane->GetBarResizeRange( mpDraggedBar, &from, &till, mIsLeftHandle );
419
420 if ( mRowHandleHitted )
421 {
422 mHandleIsVertical = ( event.mpPane->IsHorizontal() ) ? FALSE : TRUE;
423
424 mHandleDragArea.x = 0;
425 mHandleDragArea.width = event.mpPane->mPaneWidth;
426
427 mHandleDragArea.y = from;
428 mHandleDragArea.height = till - from;
429
430 if ( mIsUpperHandle )
431
432 mHandleOfs = mpResizedRow->mRowY;
433 else
434 mHandleOfs = mpResizedRow->mRowY +
435 mpResizedRow->mRowHeight -
436 event.mpPane->mProps.mResizeHandleSize;
437 }
438 else
439 {
440 // otehrwise if bar handle dragged
441
442 cbRowInfo& rowInfo = *mpDraggedBar->mpRow;
443 wxRect& bounds = mpDraggedBar->mBounds;
444
445 mHandleIsVertical = ( event.mpPane->IsHorizontal() ) ? TRUE : FALSE;
446
447 mHandleDragArea.x = from;
448 mHandleDragArea.width = till - from;
449
450
451 mHandleDragArea.y = bounds.y;
452 mHandleDragArea.height = bounds.height;
453
454 // left-side-handle mBounds
455 if ( mIsLeftHandle )
456
457 mHandleOfs = bounds.x;
458 else
459 mHandleOfs = bounds.x +
460 bounds.width - event.mpPane->mProps.mResizeHandleSize;
461
462 }
463
464 event.mpPane->PaneToFrame( &mHandleDragArea );
465 DrawDraggedHandle(mDragOrigin, *event.mpPane);
466
467 mPrevPos = mDragOrigin;
468
469 return;
470 // handled is dragged, thus event is "eaten" by this plugin
471 }
472 else
473 {
474 cbBarInfo* pDraggedBar;
475
476 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
477 &mpResizedRow,
478 &pDraggedBar ) == CB_BAR_CONTENT_HITTED
479 )
480 {
481 int x = event.mPos.x,
482 y = event.mPos.y;
483
484 event.mpPane->PaneToFrame( &x, &y );
485
486 cbStartBarDraggingEvent dragEvt( pDraggedBar, wxPoint(x,y), event.mpPane );
487
488 mpLayout->FirePluginEvent( dragEvt );
489
490 return; // event is "eaten" by this plugin
491 }
492 }
493
494 event.Skip(); // pass event to the next plugin in the chain
495 }
496
497 void cbPaneDrawPlugin::OnLButtonUp( cbLeftUpEvent& event )
498 {
499 if ( mResizeStarted )
500 {
501 DrawDraggedHandle( event.mPos, *event.mpPane );
502
503 mResizeStarted = FALSE;
504 mResizeCursorOn = FALSE;
505
506 mpLayout->ReleaseEventsFromPane( event.mpPane );
507 mpLayout->ReleaseEventsFromPlugin( this );
508
509 mpLayout->GetParentFrame().SetCursor( *mpLayout->mpNormalCursor );
510
511 if ( mRowHandleHitted )
512 {
513 event.mpPane->ResizeRow( mpResizedRow,
514 mDraggedDelta,
515 mIsUpperHandle );
516 }
517 else
518 {
519 event.mpPane->ResizeBar( mpDraggedBar,
520 mDraggedDelta,
521 mIsLeftHandle );
522 }
523
524 mpDraggedBar = NULL;
525 mpResizedRow = NULL;
526
527 // handled dragging action was finished by this mouse-up,
528 // thus event is "eaten" by this plugin
529
530 return;
531 }
532
533 event.Skip(); // pass event to the next plugin
534 }
535
536 void cbPaneDrawPlugin::OnRButtonUp( cbRightUpEvent& event )
537 {
538 wxPoint fpos = event.mPos;
539 event.mpPane->PaneToFrame( &fpos.x, &fpos.y );
540
541 cbBarInfo* pDraggedBar;
542
543 // user clicks inside the bar contnet, fire bar-customization event
544
545 if ( event.mpPane->HitTestPaneItems( event.mPos, // in pane's coordiantes
546 &mpResizedRow,
547 &pDraggedBar ) == CB_BAR_CONTENT_HITTED
548 )
549 {
550 cbCustomizeBarEvent cbEvt( pDraggedBar, fpos, event.mpPane );
551
552 mpLayout->FirePluginEvent( cbEvt );
553
554 return; // event is "eaten" by this plugin
555 }
556
557 // otherwise fire whole-layout customization event
558
559 cbCustomizeLayoutEvent csEvt( fpos );
560
561 mpLayout->FirePluginEvent( csEvt );
562
563 // event is "eaten" by this plugin
564 }
565
566 void cbPaneDrawPlugin::OnSizeBarWindow( cbSizeBarWndEvent& event )
567 {
568 cbBarInfo& bar = *event.mpBar;
569 mpPane = event.mpPane;
570
571 // it's possible that a bar does not have it's own window!
572 if ( !bar.mpBarWnd ) return;
573
574 wxRect& bounds = event.mBoundsInParent;
575
576 // check visibility
577 if ( bounds.height != 0 )
578 {
579 // size smaller than bounds, to leave space for shade lines
580
581 // FIXME:: +/- 1s
582
583 bar.mpBarWnd->wxWindow::SetSize( bounds.x + 1 + bar.mDimInfo.mHorizGap,
584 bounds.y + 1 + bar.mDimInfo.mVertGap,
585 bounds.width - 2 - bar.mDimInfo.mHorizGap*2,
586 bounds.height - 2 - bar.mDimInfo.mVertGap *2 ,
587 0
588 );
589
590 if ( !bar.mpBarWnd->IsShown() )
591
592 bar.mpBarWnd->Show( TRUE );
593 }
594 else
595 // hide bar if not visible
596 bar.mpBarWnd->Show( FALSE );
597
598 event.Skip(); // pass event to the next plugin in the chain
599 }
600
601 void cbPaneDrawPlugin::OnDrawRowDecorations( cbDrawRowDecorEvent& event )
602 {
603 DrawPaneShadeForRow( event.mpRow, *event.mpDc );
604
605 event.Skip(); // pass event to the next plugin
606 }
607
608 void cbPaneDrawPlugin::DrawUpperRowHandle( cbRowInfo* pRow, wxDC& dc )
609 {
610 wxRect& bounds = pRow->mBoundsInParent;
611
612 if ( mpPane->IsHorizontal() )
613 {
614 if ( pRow->mHasUpperHandle )
615
616 mpPane->DrawHorizHandle( dc, bounds.x,
617 bounds.y-1,
618 pRow->mRowWidth );
619 }
620 else
621 {
622 if ( pRow->mHasUpperHandle )
623
624 mpPane->DrawVertHandle( dc, bounds.x-1,
625 bounds.y, pRow->mRowWidth );
626 }
627 }
628
629 void cbPaneDrawPlugin::DrawLowerRowHandle( cbRowInfo* pRow, wxDC& dc )
630 {
631 wxRect& bounds = pRow->mBoundsInParent;
632
633 // check if iter-row handles present
634
635 if ( mpPane->IsHorizontal() )
636 {
637 if ( pRow->mHasLowerHandle )
638
639 mpPane->DrawHorizHandle( dc, bounds.x, bounds.y + bounds.height - mpPane->mProps.mResizeHandleSize - 1,
640 pRow->mRowWidth );
641 }
642 else
643 {
644 if ( pRow->mHasLowerHandle )
645
646 mpPane->DrawVertHandle( dc, bounds.x + bounds.width - mpPane->mProps.mResizeHandleSize - 1,
647 bounds.y, pRow->mRowWidth );
648 }
649 }
650
651 void cbPaneDrawPlugin::OnDrawRowHandles( cbDrawRowHandlesEvent& event )
652 {
653 // short-cuts
654 cbRowInfo* pRow = event.mpRow;
655 wxDC& dc = *event.mpDc;
656 mpPane = event.mpPane;
657
658 // draw handles of surrounding rows first
659
660 if ( pRow->mpPrev && pRow->mpPrev->mHasLowerHandle )
661
662 DrawLowerRowHandle( pRow->mpPrev, dc );
663
664 if ( pRow->mpNext && pRow->mpNext->mHasUpperHandle )
665
666 DrawUpperRowHandle( pRow->mpNext, dc );
667
668 // draw handles of the given row
669
670 if ( pRow->mHasUpperHandle )
671
672 DrawUpperRowHandle( pRow, dc );
673
674 if ( pRow->mHasLowerHandle )
675
676 DrawLowerRowHandle( pRow, dc );
677
678 event.Skip(); // pass event to the next plugin
679 }
680
681 void cbPaneDrawPlugin::OnDrawPaneBackground ( cbDrawPaneBkGroundEvent& event )
682 {
683 wxDC& dc = *event.mpDc;
684 mpPane = event.mpPane;
685
686 // FOR NOW:: hard-coded
687 wxBrush bkBrush( mpLayout->mBorderPen.GetColour(), wxSOLID );
688
689 dc.SetBrush( bkBrush );
690 dc.SetPen( mpLayout->mNullPen );
691
692 wxRect& bounds = mpPane->mBoundsInParent;
693
694 if ( mpPane->mTopMargin >= 1 )
695
696 dc.DrawRectangle( bounds.x, bounds.y,
697 bounds.width+1,
698 mpPane->mTopMargin + 1);
699
700
701 if ( mpPane->mBottomMargin >= 1 )
702
703 dc.DrawRectangle( bounds.x,
704 bounds.y + bounds.height - mpPane->mBottomMargin,
705 bounds.width + 1,
706 mpPane->mBottomMargin + 1);
707
708
709 if ( mpPane->mLeftMargin >= 1 )
710
711 dc.DrawRectangle( bounds.x,
712 bounds.y + mpPane->mTopMargin - 1,
713 mpPane->mLeftMargin + 1,
714 bounds.height - mpPane->mTopMargin - mpPane->mBottomMargin + 2);
715
716
717 if ( mpPane->mRightMargin >= 1 )
718
719 dc.DrawRectangle( bounds.x + bounds.width - mpPane->mRightMargin,
720 bounds.y + mpPane->mTopMargin - 1,
721 mpPane->mRightMargin + 1,
722 bounds.height - mpPane->mTopMargin - mpPane->mBottomMargin + 2);
723
724 event.Skip(); // pass event to the next plugin
725 }
726
727 void cbPaneDrawPlugin::OnDrawRowBackground ( cbDrawRowBkGroundEvent& event )
728 {
729 // short-cuts
730 cbRowInfo* pRow = event.mpRow;
731 wxDC& dc = *event.mpDc;
732 mpPane = event.mpPane;
733
734 // get ready
735 wxRect rowBounds = pRow->mBoundsInParent;
736 bool isHorizontal = event.mpPane->IsHorizontal();
737
738 int prevPos;
739
740 if ( isHorizontal )
741 {
742 prevPos = rowBounds.x;
743 // include one line obove and below the row
744 --rowBounds.y;
745 rowBounds.height +=2;
746
747 --rowBounds.x;
748 rowBounds.width += 2;
749 }
750 else
751 {
752 prevPos = rowBounds.y;
753 // include one line obove and below the row
754 --rowBounds.x;
755 rowBounds.width += 2;
756
757 --rowBounds.y;
758 rowBounds.height +=2;
759 }
760
761 //#define TEST_BK_ERASING
762
763 #ifdef TEST_BK_ERASING
764
765 // DBG::
766 wxBrush br0( wxColour(0,160,160), wxSOLID );
767 dc.SetBrush(br0);
768 dc.SetPen ( mpLayout->mNullPen );
769 dc.DrawRectangle( rowBounds.x, rowBounds.y,
770 rowBounds.width + 1,
771 rowBounds.height + 1 );
772 #endif
773
774 wxBrush bkBrush( mpLayout->mGrayPen.GetColour(), wxSOLID );
775
776 dc.SetPen ( mpLayout->mNullPen );
777 dc.SetBrush( bkBrush );
778
779 // fill background-recatangle of entire row area
780 dc.DrawRectangle( rowBounds.x, rowBounds.y,
781 rowBounds.width + 1,
782 rowBounds.height + 1 );
783
784 dc.SetBrush( wxNullBrush );
785
786 // draw "shaded-side-bars" for each bar
787 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
788 {
789 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
790
791 if ( isHorizontal )
792 {
793 DrawShade( 1, bounds, FL_ALIGN_LEFT, dc );
794 DrawShade( 1, bounds, FL_ALIGN_RIGHT, dc );
795 }
796 else
797 {
798 DrawShade( 1, bounds, FL_ALIGN_TOP, dc );
799 DrawShade( 1, bounds, FL_ALIGN_BOTTOM, dc );
800 }
801 }
802
803 // draw extra shades to simulate "glued-bricks" effect
804
805 // TBD:: reduce exessive drawing of shades, when the
806 // row handle is present, and shades will be overr-drawn anyway
807
808 DrawUpperRowShades( pRow, dc, 1 ); // outer shade
809
810 if ( pRow->mpPrev )
811 {
812 DrawLowerRowShades( pRow->mpPrev, dc, 1 ); // outter shade
813 DrawLowerRowShades( pRow->mpPrev, dc, 0 ); // inner shade
814 }
815
816 DrawLowerRowShades( pRow, dc, 1 );
817
818 if ( pRow->mpNext )
819 {
820 DrawUpperRowShades( pRow->mpNext, dc, 1 );
821 DrawUpperRowShades( pRow->mpNext, dc, 0 );
822 }
823
824 event.Skip(); // pass event to the next plugin
825 }
826
827 void cbPaneDrawPlugin::DrawUpperRowShades( cbRowInfo* pRow, wxDC& dc, int level )
828 {
829 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
830 {
831 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
832
833 if ( mpPane->IsHorizontal() )
834 {
835 DrawShade( level, bounds, FL_ALIGN_TOP, dc );
836 if ( level == 1 )
837 {
838 dc.SetPen( mpLayout->mDarkPen );
839 dc.DrawPoint( bounds.x - 1, bounds.y );
840 dc.SetPen( mpLayout->mLightPen );
841 dc.DrawPoint( bounds.x + bounds.width , bounds.y );
842 }
843 }
844 else
845 {
846 DrawShade( level, bounds, FL_ALIGN_LEFT, dc );
847 if ( level == 1 )
848 {
849 dc.SetPen( mpLayout->mDarkPen );
850 dc.DrawPoint( bounds.x, bounds.y -1 );
851 dc.SetPen( mpLayout->mLightPen );
852 dc.DrawPoint( bounds.x, bounds.y + bounds.height );
853 }
854 }
855 }
856 }
857
858 void cbPaneDrawPlugin::DrawLowerRowShades( cbRowInfo* pRow, wxDC& dc, int level )
859 {
860 for( size_t i = 0; i != pRow->mBars.Count(); ++i )
861 {
862 wxRect& bounds = pRow->mBars[i]->mBoundsInParent;
863
864 if ( mpPane->IsHorizontal() )
865 {
866 DrawShade( level, bounds, FL_ALIGN_BOTTOM, dc );
867 if ( level == 1 )
868 {
869 dc.SetPen( mpLayout->mDarkPen );
870 dc.DrawPoint( bounds.x - 1, bounds.y + bounds.height -1 );
871 dc.SetPen( mpLayout->mLightPen );
872 dc.DrawPoint( bounds.x + bounds.width , bounds.y + bounds.height -1 );
873 }
874 }
875 else
876 {
877 DrawShade( level, bounds, FL_ALIGN_RIGHT, dc );
878 if ( level == 1 )
879 {
880 dc.SetPen( mpLayout->mDarkPen );
881 dc.DrawPoint( bounds.x + bounds.width - 1, bounds.y -1 );
882 dc.SetPen( mpLayout->mLightPen );
883 dc.DrawPoint( bounds.x + bounds.width - 1, bounds.y + bounds.height );
884 }
885 }
886 }
887 }
888
889 void cbPaneDrawPlugin::DrawBarInnerShadeRect( cbBarInfo* pBar, wxDC& dc )
890 {
891 wxRect& bounds = pBar->mBoundsInParent;
892
893 dc.SetPen( mpLayout->mDarkPen );
894
895 dc.DrawLine( bounds.x + bounds.width - 1,
896 bounds.y,
897 bounds.x + bounds.width - 1,
898 bounds.y + bounds.height );
899
900 dc.DrawLine( bounds.x,
901 bounds.y + bounds.height - 1,
902 bounds.x + bounds.width,
903 bounds.y + bounds.height -1 );
904
905 dc.SetPen( mpLayout->mLightPen );
906
907 dc.DrawLine( bounds.x,
908 bounds.y,
909 bounds.x + bounds.width - 1,
910 bounds.y );
911
912 dc.DrawLine( bounds.x,
913 bounds.y,
914 bounds.x,
915 bounds.y + bounds.height - 1 );
916 }
917
918 void cbPaneDrawPlugin::DrawShade( int level, wxRect& rect, int alignment, wxDC& dc )
919 {
920 // simulates "guled-bricks" appearence of control bars
921
922 if ( ( alignment == FL_ALIGN_TOP && level == 1 ) ||
923 ( alignment == FL_ALIGN_BOTTOM && level == 0 ) ||
924 ( alignment == FL_ALIGN_LEFT && level == 1 ) ||
925 ( alignment == FL_ALIGN_RIGHT && level == 0 )
926 )
927
928 dc.SetPen( mpLayout->mDarkPen );
929 else
930 dc.SetPen( mpLayout->mLightPen );
931
932 if ( alignment == FL_ALIGN_TOP )
933 {
934 if ( level == 0 )
935
936 dc.DrawLine( rect.x,
937 rect.y,
938 rect.x + rect.width - 1,
939 rect.y );
940 else
941 dc.DrawLine( rect.x - 1,
942 rect.y - 1,
943 rect.x + rect.width + 0,
944 rect.y - 1 );
945 }
946 else
947 if ( alignment == FL_ALIGN_BOTTOM )
948 {
949 if ( level == 0 )
950
951 dc.DrawLine( rect.x,
952 rect.y + rect.height - 1,
953 rect.x + rect.width,
954 rect.y + rect.height - 1 );
955 else
956 dc.DrawLine( rect.x - 1,
957 rect.y + rect.height,
958 rect.x + rect.width + 1,
959 rect.y + rect.height );
960 }
961 else
962 if ( alignment == FL_ALIGN_LEFT )
963 {
964 if ( level == 0 )
965
966 dc.DrawLine( rect.x,
967 rect.y,
968 rect.x,
969 rect.y + rect.height - 1 );
970 else
971 dc.DrawLine( rect.x - 1,
972 rect.y - 1,
973 rect.x - 1,
974 rect.y + rect.height );
975 }
976 else
977 if ( alignment == FL_ALIGN_RIGHT )
978 {
979 if ( level == 0 )
980
981 dc.DrawLine( rect.x + rect.width - 1,
982 rect.y,
983 rect.x + rect.width - 1,
984 rect.y + rect.height );
985 else
986 {
987 dc.DrawLine( rect.x + rect.width,
988 rect.y - 1,
989 rect.x + rect.width,
990 rect.y + rect.height + 1 );
991 }
992 }
993 }
994
995 void cbPaneDrawPlugin::DrawShade1( int level, wxRect& rect, int alignment, wxDC& dc )
996 {
997 // simulates "guled-bricks" appearence of control bars
998
999 if ( ( alignment == FL_ALIGN_TOP && level == 1 ) ||
1000 ( alignment == FL_ALIGN_BOTTOM && level == 0 ) ||
1001 ( alignment == FL_ALIGN_LEFT && level == 1 ) ||
1002 ( alignment == FL_ALIGN_RIGHT && level == 0 )
1003 )
1004
1005 dc.SetPen( mpLayout->mDarkPen );
1006 else
1007 dc.SetPen( mpLayout->mLightPen );
1008
1009 if ( alignment == FL_ALIGN_TOP )
1010 {
1011 if ( level == 0 )
1012
1013 dc.DrawLine( rect.x,
1014 rect.y,
1015 rect.x + rect.width,
1016 rect.y );
1017 else
1018 dc.DrawLine( rect.x,
1019 rect.y - 1,
1020 rect.x + rect.width,
1021 rect.y - 1 );
1022 }
1023 else
1024 if ( alignment == FL_ALIGN_BOTTOM )
1025 {
1026 if ( level == 0 )
1027
1028 dc.DrawLine( rect.x,
1029 rect.y + rect.height - 1,
1030 rect.x + rect.width,
1031 rect.y + rect.height - 1 );
1032 else
1033 dc.DrawLine( rect.x,
1034 rect.y + rect.height,
1035 rect.x + rect.width,
1036 rect.y + rect.height );
1037 }
1038 else
1039 if ( alignment == FL_ALIGN_LEFT )
1040 {
1041 if ( level == 0 )
1042
1043 dc.DrawLine( rect.x,
1044 rect.y,
1045 rect.x,
1046 rect.y + rect.height );
1047 else
1048 dc.DrawLine( rect.x - 1,
1049 rect.y,
1050 rect.x - 1,
1051 rect.y + rect.height );
1052 }
1053 else
1054 if ( alignment == FL_ALIGN_RIGHT )
1055 {
1056 if ( level == 0 )
1057
1058 dc.DrawLine( rect.x + rect.width - 1,
1059 rect.y,
1060 rect.x + rect.width - 1,
1061 rect.y + rect.height );
1062 else
1063 {
1064 dc.DrawLine( rect.x + rect.width,
1065 rect.y ,
1066 rect.x + rect.width,
1067 rect.y + rect.height );
1068 }
1069 }
1070 }
1071
1072 void cbPaneDrawPlugin::DrawPaneShade( wxDC& dc, int alignment )
1073 {
1074 if ( !mpPane->mProps.mShow3DPaneBorderOn ) return;
1075
1076 wxRect bounds = mpPane->mBoundsInParent;
1077
1078 bounds.x += mpPane->mLeftMargin;
1079 bounds.y += mpPane->mTopMargin;
1080 bounds.width -= ( mpPane->mLeftMargin + mpPane->mRightMargin );
1081 bounds.height -= ( mpPane->mTopMargin + mpPane->mBottomMargin );
1082
1083 DrawShade( 0, bounds, alignment, dc );
1084 DrawShade( 1, bounds, alignment, dc );
1085 }
1086
1087 void cbPaneDrawPlugin::DrawPaneShadeForRow( cbRowInfo* pRow, wxDC& dc )
1088 {
1089 if ( !mpPane->mProps.mShow3DPaneBorderOn ) return;
1090
1091 // do not draw decoration, if pane has "vainished"
1092 if ( mpPane->mPaneWidth < 0 ||
1093 mpPane->mPaneHeight < 0 )
1094
1095 return;
1096
1097 wxRect bounds = pRow->mBoundsInParent;
1098
1099 if ( mpPane->mAlignment == FL_ALIGN_TOP ||
1100 mpPane->mAlignment == FL_ALIGN_BOTTOM )
1101 {
1102 --bounds.y;
1103 bounds.height += 2;
1104
1105 DrawShade1( 0, bounds, FL_ALIGN_LEFT, dc );
1106 DrawShade1( 1, bounds, FL_ALIGN_LEFT, dc );
1107 DrawShade1( 0, bounds, FL_ALIGN_RIGHT, dc );
1108 DrawShade1( 1, bounds, FL_ALIGN_RIGHT, dc );
1109
1110 if ( !pRow->mpNext )
1111 DrawPaneShade( dc, FL_ALIGN_BOTTOM );
1112
1113 if ( !pRow->mpPrev )
1114 DrawPaneShade( dc, FL_ALIGN_TOP );
1115 }
1116 else
1117 {
1118 --bounds.x;
1119 bounds.width += 2;
1120
1121 DrawShade1( 0, bounds, FL_ALIGN_TOP, dc );
1122 DrawShade1( 1, bounds, FL_ALIGN_TOP, dc );
1123 DrawShade1( 0, bounds, FL_ALIGN_BOTTOM, dc );
1124 DrawShade1( 1, bounds, FL_ALIGN_BOTTOM, dc );
1125
1126 if ( !pRow->mpNext )
1127 DrawPaneShade( dc, FL_ALIGN_RIGHT );
1128
1129 if ( !pRow->mpPrev )
1130 DrawPaneShade( dc, FL_ALIGN_LEFT );
1131 }
1132 }
1133
1134 void cbPaneDrawPlugin::OnDrawPaneDecorations( cbDrawPaneDecorEvent& event )
1135 {
1136 wxDC& dc = *event.mpDc;
1137
1138 cbDockPane* pPane = event.mpPane;
1139
1140 RowArrayT& lst = pPane->GetRowList();
1141
1142 // FIXME:: this is a workaround for some glitches
1143
1144 if ( lst.Count() )
1145 {
1146 cbRowInfo* pLastRow = lst[ lst.Count() - 1 ];
1147
1148 pPane->PaintRowBackground( pLastRow, dc );
1149 pPane->PaintRowDecorations( pLastRow, dc );
1150 pPane->PaintRowHandles( pLastRow, dc );
1151 }
1152
1153 if ( !pPane->mProps.mShow3DPaneBorderOn ) return;
1154
1155 // do not draw decoration, if pane is completely hidden
1156 if ( event.mpPane->mPaneWidth < 0 ||
1157 event.mpPane->mPaneHeight < 0 )
1158
1159 return;
1160
1161 DrawPaneShade( dc, FL_ALIGN_TOP );
1162 DrawPaneShade( dc, FL_ALIGN_BOTTOM );
1163 DrawPaneShade( dc, FL_ALIGN_LEFT );
1164 DrawPaneShade( dc, FL_ALIGN_RIGHT );
1165
1166 event.Skip(); // pass event to the next plugin
1167 }
1168
1169 // bar decoration/sizing handlers
1170
1171 void cbPaneDrawPlugin::OnDrawBarDecorations( cbDrawBarDecorEvent& event )
1172 {
1173 cbBarInfo* pBar = event.mpBar;
1174 wxDC& dc = *event.mpDc;
1175
1176 // draw brick borders
1177
1178 wxRect& rect = event.mBoundsInParent;
1179
1180 dc.SetPen( mpLayout->mLightPen );
1181
1182 // horiz
1183 dc.DrawLine( rect.x, rect.y,
1184 rect.x + rect.width-1, rect.y );
1185
1186 // vert
1187 dc.DrawLine( rect.x, rect.y,
1188 rect.x, rect.y + rect.height-1 );
1189
1190
1191 dc.SetPen( mpLayout->mDarkPen );
1192
1193 // vert
1194 dc.DrawLine( rect.x + rect.width-1, rect.y,
1195 rect.x + rect.width-1, rect.y + rect.height-1 );
1196
1197 // horiz
1198 dc.DrawLine( rect.x, rect.y + rect.height-1,
1199 rect.x + rect.width, rect.y + rect.height-1 );
1200
1201 event.Skip(); // pass event to the next plugin
1202 }
1203
1204 void cbPaneDrawPlugin::OnDrawBarHandles( cbDrawBarHandlesEvent& event )
1205 {
1206 // short-cuts
1207 cbBarInfo* pBar = event.mpBar;
1208 wxDC& dc = *event.mpDc;
1209 mpPane = event.mpPane;
1210
1211 // draw handles around the bar if present
1212
1213 if ( pBar->mHasLeftHandle ||
1214 pBar->mHasRightHandle )
1215 {
1216 wxRect& bounds = pBar->mBoundsInParent;
1217
1218 if ( mpPane->IsHorizontal() )
1219 {
1220 if ( pBar->mHasLeftHandle )
1221
1222 mpPane->DrawVertHandle( dc, bounds.x - mpPane->mProps.mResizeHandleSize -1,
1223 bounds.y, bounds.height );
1224
1225 if ( pBar->mHasRightHandle )
1226
1227 mpPane->DrawVertHandle( dc,
1228 bounds.x + bounds.width -1,
1229 bounds.y, bounds.height );
1230 }
1231 else
1232 {
1233 if ( pBar->mHasLeftHandle )
1234
1235 mpPane->DrawHorizHandle( dc, bounds.x,
1236 bounds.y - mpPane->mProps.mResizeHandleSize - 1,
1237 bounds.width );
1238
1239 if ( pBar->mHasRightHandle )
1240
1241 mpPane->DrawHorizHandle( dc, bounds.x,
1242 bounds.y + bounds.height - 1,
1243 bounds.width );
1244 }
1245 }
1246
1247 event.Skip(); // pass event to the next plugin
1248 }
1249
1250 void cbPaneDrawPlugin::OnStartDrawInArea( cbStartDrawInAreaEvent& event )
1251 {
1252 // DBG::
1253 wxASSERT( mpClntDc == NULL );
1254
1255 // FOR NOW:: create/destroy client-dc upon each drawing
1256 mpClntDc = new wxClientDC( &mpLayout->GetParentFrame() );
1257
1258 (*event.mppDc) = mpClntDc;
1259
1260 mpClntDc->SetClippingRegion( event.mArea.x, event.mArea.y,
1261 event.mArea.width, event.mArea.height );
1262 }
1263
1264 void cbPaneDrawPlugin::OnFinishDrawInArea( cbFinishDrawInAreaEvent& event )
1265 {
1266 // DBG::
1267 wxASSERT( mpClntDc );
1268
1269 delete mpClntDc;
1270
1271 mpClntDc = NULL;
1272 }
1273