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