]> git.saurik.com Git - wxWidgets.git/blob - utils/framelayout/src/controlarea.cpp
Added Aleksandras' framelayout code, with more or less working Linux Makefiles
[wxWidgets.git] / utils / framelayout / src / controlarea.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: No names yet.
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: 07/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "controlarea.h"
14 // #pragma interface
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/wx.h"
26 #endif
27
28 #include <math.h>
29 #include <stdlib.h>
30
31 #include "wx/string.h"
32 #include "wx/utils.h" // import wxMin/wxMax macros and wxFileExist(..)
33
34 #include "controlarea.h"
35
36
37 /***** Implementation for class twTabInfo *****/
38
39 IMPLEMENT_DYNAMIC_CLASS( twTabInfo, wxObject )
40
41 twTabInfo::twTabInfo()
42 : mpContent( 0 )
43 {}
44
45 twTabInfo::~twTabInfo()
46 {
47 // FOR NOW:: nothing
48 }
49
50 int twTabInfo::ImgWidth()
51 {
52 if ( mBitMap.Ok() ) return mBitMap.GetWidth();
53 else return 0;
54 }
55
56 int twTabInfo::ImgHeight()
57 {
58 if ( mBitMap.Ok() ) return mBitMap.GetHeight();
59 else return 0;
60 }
61
62 int twTabInfo::ImageToTxtGap( int prefGap )
63 {
64 if ( mBitMap.Ok() ) return prefGap;
65 else return 0;
66 }
67
68 bool twTabInfo::HasImg()
69 {
70 return mBitMap.Ok();
71 }
72
73 bool twTabInfo::HasText()
74 {
75 return mText.Length();
76 }
77
78 wxBitmap& twTabInfo::GetImg()
79 {
80 return mBitMap;
81 }
82
83 wxString& twTabInfo::GetText()
84 {
85 return mText;
86 }
87
88 wxWindow& twTabInfo::GetContent()
89 {
90 return *mpContent;
91 }
92
93 /***** Implementation for class wxTabbedWindow *****/
94
95 IMPLEMENT_DYNAMIC_CLASS( wxTabbedWindow, wxPanel )
96
97 BEGIN_EVENT_TABLE( wxTabbedWindow, wxPanel )
98
99 EVT_SIZE ( wxTabbedWindow::OnSize )
100 EVT_PAINT( wxTabbedWindow::OnPaint )
101 EVT_LEFT_DOWN( wxTabbedWindow::OnLButtonDown )
102
103 // TDB:: filciker reduction
104 // EVT_ERASE_BACKGROUND( wxTabbedWindow::OnBkErase )
105
106 END_EVENT_TABLE()
107
108 wxTabbedWindow::wxTabbedWindow()
109
110 : mpTabScroll ( NULL ),
111 mpHorizScroll( NULL ),
112 mpVertScroll ( NULL ),
113
114 mVertGap ( 0 ),
115 mHorizGap( 0 ),
116
117 mTitleVertGap ( 3 ),
118 mTitleHorizGap( 4 ),
119 mImageTextGap ( 2 ),
120 mFirstTitleGap( 11 ),
121
122 mBorderOnlyWidth( 8 ),
123
124 mWhitePen( wxColour(255,255,255), 1, wxSOLID ),
125 mGrayPen ( wxColour(192,192,192), 1, wxSOLID ),
126 mDarkPen ( wxColour(128,128,128), 1, wxSOLID ),
127 mBlackPen( wxColour( 0, 0, 0), 1, wxSOLID ),
128
129 // state variables
130
131 mActiveTab ( 0 ),
132 mTitleHeight( 0 ),
133 mLayoutType( wxTITLE_IMG_AND_TEXT )
134 {}
135
136 wxTabbedWindow::~wxTabbedWindow()
137 {
138 wxNode* pTab = mTabs.First();
139
140 while( pTab )
141 {
142 delete ((twTabInfo*)pTab->Data());
143
144 pTab = pTab->Next();
145 }
146 }
147
148 void wxTabbedWindow::SizeTabs(int x,int y, int width, int height, bool repant)
149 {
150 wxNode* pTabNode = mTabs.First();
151 int n = 0;
152
153 while( pTabNode )
154 {
155 twTabInfo& info = *((twTabInfo*)pTabNode->Data());
156
157 if ( n == mActiveTab )
158 {
159 //wxSizeEvent evt;
160 //info.mpContent->GetEventHandler()->ProcessEvent( evt );
161
162 info.mpContent->SetSize( x, y, width, height, 0 );
163 info.mpContent->Show(TRUE);
164 info.mpContent->Refresh();
165
166 }
167 else
168 {
169 info.mpContent->Show(FALSE);
170 }
171
172 pTabNode = pTabNode->Next();
173 ++n;
174 }
175 }
176
177 void wxTabbedWindow::AddTab( wxWindow* pContent,
178 wxString tabText,
179 wxString imageFileName,
180 long imageType )
181 {
182 twTabInfo* pTab = new twTabInfo();
183
184 pTab->mpContent = pContent;
185 pTab->mText = tabText;
186
187 if ( wxFileExists( imageFileName ) &&
188
189 pTab->mBitMap.LoadFile( imageFileName, imageType ) )
190 {
191 pTab->mImageFile = imageFileName;
192 pTab->mImageType = imageType;
193 }
194
195 bool ok = pTab->mBitMap.Ok();
196
197 if ( pContent->GetParent() == NULL )
198
199 pContent->Create( this, -1 );
200
201 mTabs.Append( (wxObject*)pTab );
202
203 RecalcLayout(TRUE);
204
205 OnTabAdded( pTab );
206 }
207
208 void wxTabbedWindow::AddTab( wxWindow* pContent,
209 wxString tabText,
210 wxBitmap* pImage )
211 {
212 twTabInfo* pTab = new twTabInfo();
213
214 pTab->mpContent = pContent;
215 pTab->mText = tabText;
216
217 if ( pImage ) pTab->mBitMap = *pImage;
218
219 if ( pContent->GetParent() == NULL )
220
221 pContent->Create( this, -1 );
222
223 mTabs.Append( (wxObject*)pTab );
224
225 RecalcLayout(TRUE);
226
227 OnTabAdded( pTab );
228 }
229
230
231
232 void wxTabbedWindow::RemoveTab( int tabNo )
233 {
234 twTabInfo* pTab = ((twTabInfo*)(mTabs.Nth( tabNo )->Data()));
235
236 pTab->mpContent->Destroy();
237
238 delete pTab;
239
240 mTabs.DeleteNode( mTabs.Nth( tabNo ) );
241
242 if ( mActiveTab >= mTabs.Number() );
243
244 mActiveTab = mTabs.Number() - 1;
245
246 SetActiveTab( mActiveTab );
247 }
248
249 int wxTabbedWindow::GetTabCount()
250 {
251 return mTabs.Number();
252 }
253
254 wxWindow* wxTabbedWindow::GetTab( int tabNo )
255 {
256 return ((twTabInfo*)(mTabs.Nth( tabNo )->Data()))->mpContent;
257 }
258
259 wxWindow* wxTabbedWindow::GetActiveTab()
260 {
261 // FIMXE:: this is lame
262
263 return GetTab( mActiveTab );
264 }
265
266 void wxTabbedWindow::SetActiveTab( int tabNo )
267 {
268 mActiveTab = tabNo;
269
270 RecalcLayout(TRUE);
271
272 Refresh();
273 }
274
275 // width of the decorations border (4 shade-lines), should not be changed
276
277 #define BORDER_SZ 4
278
279 void wxTabbedWindow::DrawShadedRect( int x, int y, int width, int height,
280 wxPen& upperPen, wxPen& lowerPen, wxDC& dc
281 )
282 {
283 // darw the lightened upper-left sides of the rectangle
284
285 dc.SetPen( upperPen );
286 dc.DrawLine( x,y, x, y + height - 1 ); // vert
287 dc.DrawLine( x,y, x + width - 1, y ); // horiz
288
289 // draw the unenlightened lower-right sides of the rectangle
290
291 dc.SetPen( lowerPen );
292 dc.DrawLine( x + width - 1, y, x + width - 1, y + height - 1 ); // vert
293 dc.DrawLine( x, y + height - 1, x + width, y + height - 1 ); // horiz
294 }
295
296 void wxTabbedWindow::DrawDecorations( wxDC& dc )
297 {
298 // Protability NOTE::: DrawLine(..) draws a line from the first position,
299 // but not including the point specified by last position.
300 // This way Windows draws lines, not sure how Motif and Gtk
301 // prots behave...
302
303 int width, height;
304 GetClientSize( &width, &height );
305
306 // check if there's at least a bit of space to draw things
307
308 if ( width < mHorizGap*2 + BORDER_SZ*2+1 ||
309 height < mVertGap*2 + BORDER_SZ*2+1 + mTitleHeight
310 )
311 return;
312
313 // step #1 - draw border around the tab content area
314
315 // setup position for kind of "pencil"
316 int curX = mHorizGap;
317 int curY = mVertGap;
318
319 int xSize = width - mHorizGap*2;
320 int ySize = height - mVertGap *2 - mTitleHeight;
321
322 // layer 1 (upper white)
323 DrawShadedRect( curX+0, curY+0, xSize-0, ySize-0,
324 mWhitePen, mBlackPen, dc );
325
326 // layer 2 (upper gray)
327 DrawShadedRect( curX+1, curY+1, xSize-2-1, ySize-2-1,
328 mGrayPen, mGrayPen, dc );
329
330 // layer 3 (upper darkGray)
331 DrawShadedRect( curX+2, curY+2, xSize-3-2, ySize-3-2,
332 mDarkPen, mWhitePen, dc );
333
334 // layer 4 (upper black)
335 DrawShadedRect( curX+3, curY+3, xSize-4-3, ySize-4-3,
336 mBlackPen, mGrayPen, dc );
337
338 // add non-siemtric layer from the lower-right side (confroming to MFC-look)
339
340 dc.SetPen( mDarkPen );
341 dc.DrawLine( curX+1, curY + ySize - 2, curX + xSize - 1, curY + ySize - 2 ); // horiz
342 dc.DrawLine( curX + xSize - 2, curY + 1, curX + xSize - 2, curY + ySize - 2 ); // vert
343
344 // step #2 - draw tab title bars
345
346 curX = mFirstTitleGap;
347 curY = height - mVertGap - mTitleHeight;
348
349 int tabNo = 0;
350 wxNode* pNode = mTabs.First();
351
352 while( pNode )
353 {
354 // "hard-coded metafile" for decorations
355
356 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
357
358 xSize = tab.mDims.x;
359 ySize = mTitleHeight;
360
361 if ( tabNo == mActiveTab )
362 {
363 dc.SetPen( mGrayPen );
364 dc.DrawLine( curX+1, curY-2, curX+xSize-2, curY-2 );
365 dc.DrawLine( curX+1, curY-1, curX+xSize-2, curY-1 );
366 }
367
368 dc.SetPen( mWhitePen );
369
370 if ( tabNo == mActiveTab )
371 dc.DrawLine( curX, curY-2, curX, curY+ySize-2 );
372 else
373 dc.DrawLine( curX, curY, curX, curY+ySize-2 );
374
375 dc.SetPen( mDarkPen );
376 dc.DrawLine( curX+1, curY+ySize-3, curX+1, curY+ySize-1 ); // to pix down
377 dc.DrawLine( curX+2, curY+ySize-2, curX+xSize-2, curY+ySize-2 );
378 dc.DrawLine( curX+xSize-3, curY+ySize-3, curX+xSize-2, curY+ySize-3 );
379 if ( tabNo == mActiveTab )
380 dc.DrawLine( curX+xSize-2, curY+ySize-3, curX+xSize-2, curY-3 );
381 else
382 dc.DrawLine( curX+xSize-2, curY+ySize-3, curX+xSize-2, curY-1 );
383
384 dc.SetPen( mBlackPen );
385 dc.DrawLine( curX+xSize-1, curY, curX+xSize-1, curY+ySize-2 );
386 dc.DrawLine( curX+xSize-2, curY+ySize-2, curX+xSize-3, curY+ySize-2 );
387 dc.DrawLine( curX+xSize-3, curY+ySize-1, curX+1, curY+ySize-1 );
388
389 pNode = pNode->Next();
390 ++tabNo;
391
392 // darw image and (or without) text centered within the
393 // title bar rectangle
394
395 if ( mLayoutType != wxTITLE_BORDER_ONLY && tab.HasImg() )
396 {
397 wxMemoryDC tmpDc;
398 tmpDc.SelectObject( tab.GetImg() );
399
400 dc.Blit( curX + mTitleHorizGap,
401 curY + ( ySize - tab.ImgHeight() ) / 2,
402 tab.ImgWidth(),
403 tab.ImgHeight(),
404 &tmpDc, 0, 0, wxCOPY
405 );
406 }
407
408 if ( mLayoutType == wxTITLE_IMG_AND_TEXT && tab.HasText() )
409 {
410 long x,w,h;
411
412 // set select default font of the window into it's device context
413 dc.SetFont( GetLabelingFont() );
414
415 dc.SetTextBackground( GetBackgroundColour() );
416
417 dc.GetTextExtent(tab.mText, &w, &h );
418
419 x = curX + mTitleHorizGap +
420 tab.ImgWidth() + tab.ImageToTxtGap(mImageTextGap);
421
422 dc.DrawText( tab.GetText(), x, curY + ( ySize - h ) / 2 );
423 }
424 curX += xSize;
425
426 } // end of `while (pNode)'
427 }
428
429 int wxTabbedWindow::HitTest( const wxPoint& pos )
430 {
431 int width, height;
432 GetClientSize( &width, &height );
433
434 int curX = mFirstTitleGap;
435 int curY = height - mVertGap - mTitleHeight;
436
437 int tabNo = 0;
438 wxNode* pNode = mTabs.First();
439
440 int x = pos.x;
441 int y = pos.y;
442
443 while( pNode )
444 {
445 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
446
447 int w,h;
448 w = tab.mDims.x;
449 h = tab.mDims.y;
450 // hit test rectangle of the currnet tab title bar
451 if ( pos.x >= curX && pos.x < curX + tab.mDims.x &&
452 pos.y >= curY && pos.y < curY + tab.mDims.y
453 )
454 {
455 return tabNo;
456 }
457
458 curX += tab.mDims.x;
459
460 pNode = pNode->Next();
461 ++tabNo;
462 }
463
464 return -1;
465 }
466
467 void wxTabbedWindow::HideInactiveTabs( bool andRepaint )
468 {
469 if ( !andRepaint )
470 return;
471
472 wxNode* pNode = mTabs.First();
473 int tabNo = 0;
474
475 while( pNode )
476 {
477 if ( tabNo != mActiveTab )
478 {
479 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
480 tab.mpContent->Show(FALSE);
481 }
482
483 pNode = pNode->Next();
484 ++tabNo;
485 }
486 }
487
488 wxFont wxTabbedWindow::GetLabelingFont()
489 {
490 wxFont font;
491 #ifdef __WINDOWS__
492 font.SetFaceName("MS Sans Serif");
493 #else
494 font.SetFamily( wxSWISS );
495 #endif
496
497 font.SetStyle(40);
498 font.SetWeight(40);
499 font.SetPointSize( 8 );
500
501 #ifdef __WINDOWS__
502 font.RealizeResource();
503 #endif
504
505 return font;
506 }
507
508 void wxTabbedWindow::RecalcLayout(bool andRepaint)
509 {
510 HideInactiveTabs(andRepaint);
511
512 // resetup position of the active tab
513
514 int width, height;
515 GetClientSize( &width, &height );
516
517 int curX = mHorizGap + BORDER_SZ;
518 int curY = mVertGap + BORDER_SZ;
519
520 int xSize = width - mHorizGap*2 - BORDER_SZ*2-1;
521 int ySize = height - mVertGap*2 - BORDER_SZ*2-1 - mTitleHeight;
522
523 SizeTabs( curX, curY, xSize, ySize, andRepaint );
524
525 // pass #1 - try to layout assuming it's wxTITLE_IMG_AND_TEXT
526
527 mLayoutType = wxTITLE_IMG_AND_TEXT;
528
529 wxNode* pNode = mTabs.First();
530
531 curX = mFirstTitleGap; // the left-side gap
532 mTitleHeight = 0;
533
534 while( pNode )
535 {
536 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
537
538 wxWindowDC dc(this);
539
540 long w,h;
541
542 // set select default font of the window into it's device context
543 dc.SetFont( GetLabelingFont() );
544
545 dc.GetTextExtent(tab.mText, &w, &h );
546
547 tab.mDims.x = w + tab.ImageToTxtGap(mImageTextGap) +
548 tab.ImgWidth() + mTitleHorizGap*2;
549
550 tab.mDims.y = wxMax( h, tab.ImgHeight() ) + mTitleVertGap*2;
551 mTitleHeight = wxMax( mTitleHeight, tab.mDims.y );
552
553 curX += tab.mDims.x;
554
555 pNode = pNode->Next();
556 }
557
558 curX += mHorizGap; // the right-side gap
559
560 // make all title bars of equel height
561
562 pNode = mTabs.First();
563
564 while( pNode )
565 {
566 ((twTabInfo*)(pNode->Data()))->mDims.y = mTitleHeight;;
567 pNode = pNode->Next();
568 }
569
570 // if curX has'nt ran out of bounds, leave TITLE_IMG layout and return
571 if ( curX < width - mHorizGap )
572 return;
573
574 // pass #2 - try to layout assuming wxTITLE_IMG_ONLY
575
576 mLayoutType = wxTITLE_IMG_ONLY;
577
578 pNode = mTabs.First();
579
580 curX = mFirstTitleGap; // the left-side gap
581
582 int denomiator = mTabs.Number();
583 if ( denomiator == 0 ) ++denomiator;
584
585 mBorderOnlyWidth = (width - mFirstTitleGap - mHorizGap) / denomiator;
586
587 while( pNode )
588 {
589 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
590
591 if ( tab.HasImg() )
592 {
593 tab.mDims.x = tab.ImgWidth() + mTitleHorizGap*2;
594 tab.mDims.y = tab.ImgHeight() + mTitleVertGap*2;
595 }
596 else
597 {
598 tab.mDims.x = mBorderOnlyWidth;
599 tab.mDims.y = mTitleHeight;
600 }
601
602 curX += tab.mDims.x;
603
604 pNode = pNode->Next();
605 }
606
607 curX += mHorizGap; // the right-side gap
608
609 // if curX has'nt ran out of bounds, leave IMG_ONLY layout and return
610 if ( curX < width - mHorizGap )
611 return;
612
613 // pass #3 - set the narrowest layout wxTITLE_BORDER_ONLY
614
615 mLayoutType = wxTITLE_BORDER_ONLY;
616
617 pNode = mTabs.First();
618
619 while( pNode )
620 {
621 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
622
623 tab.mDims.x = mBorderOnlyWidth;
624 tab.mDims.y = mTitleHeight;
625
626 pNode = pNode->Next();
627 }
628 }
629
630 // wx event handlers
631
632 void wxTabbedWindow::OnPaint( wxPaintEvent& event )
633 {
634 wxPaintDC dc(this);
635 DrawDecorations( dc );
636 }
637
638 void wxTabbedWindow::OnSize ( wxSizeEvent& event )
639 {
640 SetBackgroundColour( wxColour( 192,192,192 ) );
641 RecalcLayout(TRUE);
642 }
643
644 void wxTabbedWindow::OnBkErase( wxEraseEvent& event )
645 {
646 // do nothing
647 }
648
649 void wxTabbedWindow::OnLButtonDown( wxMouseEvent& event )
650 {
651 // floats, why?
652 int x = (int)event.m_x;
653 int y = (int)event.m_y;
654
655 int tabNo = HitTest( wxPoint(x,y) );
656
657 if ( tabNo != -1 )
658 {
659 SetActiveTab( tabNo );
660 }
661 }
662
663 /***** Implementation for class wxPaggedWindow *****/
664
665 IMPLEMENT_DYNAMIC_CLASS( wxPaggedWindow, wxTabbedWindow )
666
667 BEGIN_EVENT_TABLE( wxPaggedWindow, wxTabbedWindow )
668 EVT_SIZE ( wxPaggedWindow::OnSize )
669 EVT_PAINT ( wxPaggedWindow::OnPaint )
670 EVT_LEFT_DOWN( wxPaggedWindow::OnLButtonDown )
671 EVT_LEFT_UP ( wxPaggedWindow::OnLButtonUp )
672 EVT_MOTION ( wxPaggedWindow::OnMouseMove )
673 EVT_SCROLL ( wxPaggedWindow::OnScroll )
674 END_EVENT_TABLE()
675
676 // border for pagged-window is 2 shaded-lines
677
678 #undef BORDER_SZ
679 #define BORDER_SZ 2
680
681 wxPaggedWindow::wxPaggedWindow()
682
683 : mScrollEventInProgress( FALSE ),
684
685 mTabTrianGap(4),
686
687 mWhiteBrush( wxColour(255,255,255), wxSOLID ),
688 mGrayBrush ( wxColour(192,192,192), wxSOLID ),
689
690 mCurentRowOfs( 0 ),
691 mAdjustableTitleRowLen( 300 ),
692
693 mIsDragged ( FALSE ),
694 mDagOrigin ( 0 ),
695 mCursorChanged( FALSE ),
696 mResizeCursor ( wxCURSOR_SIZEWE ),
697 mNormalCursor ( wxCURSOR_ARROW )
698 {
699 mTitleVertGap = 2;
700 mTitleHorizGap = 10;
701 }
702
703 wxPaggedWindow::~wxPaggedWindow()
704 {
705 // nothing (base class handles destruction)
706 }
707
708 wxFont wxPaggedWindow::GetLabelingFont()
709 {
710 wxFont font;
711
712 #ifdef __WINDOWS__
713 font.SetFaceName("Arial");
714 #else
715 font.SetFamily( wxSWISS );
716 #endif
717
718 font.SetStyle(40);
719 font.SetWeight(40);
720 font.SetPointSize( 8 );
721
722 #ifdef __WINDOWS__
723 bool success = font.RealizeResource();
724 #endif
725
726 return font;
727 }
728
729 void wxPaggedWindow::OnTabAdded( twTabInfo* pInfo )
730 {
731 int units = GetWholeTabRowLen() / 20;
732
733 mpTabScroll->SetScrollbar( 0, 1, units, 1, FALSE );
734 }
735
736 wxScrollBar& wxPaggedWindow::GetVerticalScrollBar()
737 {
738 return *mpVertScroll;
739 }
740
741 wxScrollBar& wxPaggedWindow::GetHorizontalScrollBar()
742 {
743 return *mpHorizScroll;
744 }
745
746
747 int wxPaggedWindow::GetWholeTabRowLen()
748 {
749 wxNode* pNode = mTabs.First();
750
751 int len = 0;
752
753 while( pNode )
754 {
755 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
756
757 len += tab.mDims.x;
758 pNode = pNode->Next();
759 }
760
761 return len;
762 }
763
764 void wxPaggedWindow::DrawPaperBar( twTabInfo& tab, int x, int y,
765 wxBrush& brush, wxPen& pen, wxDC& dc )
766 {
767 wxPoint poly[4];
768
769 // draw organizer-style paper outlet
770
771 poly[0].x = x - mTabTrianGap;
772 poly[0].y = y;
773
774 poly[1].x = x + mTabTrianGap;
775 poly[1].y = y + tab.mDims.y-1;
776
777 poly[2].x = x + tab.mDims.x - mTabTrianGap;
778 poly[2].y = y + tab.mDims.y-1;
779
780 poly[3].x = x + tab.mDims.x + mTabTrianGap;
781 poly[3].y = y;
782
783 dc.SetPen( pen );
784 dc.SetBrush( brush );
785
786 dc.DrawPolygon( 4, poly );
787
788 long w,h;
789
790 // set select default font of the window into it's device context
791 dc.SetFont( GetLabelingFont() );
792
793 dc.SetTextBackground( brush.GetColour() );
794
795 dc.GetTextExtent(tab.mText, &w, &h );
796
797 if ( tab.HasImg() )
798 {
799 wxMemoryDC tmpDc;
800 tmpDc.SelectObject( tab.GetImg() );
801
802 dc.Blit( x + mTitleHorizGap,
803 y + ( tab.mDims.y - tab.ImgHeight() ) / 2,
804 tab.ImgWidth(),
805 tab.ImgHeight(),
806 &tmpDc, 0, 0, wxCOPY
807 );
808 }
809
810 if ( tab.HasText() )
811 {
812 int tx = x + mTitleHorizGap +
813 tab.ImgWidth() + tab.ImageToTxtGap(mImageTextGap);
814
815 dc.DrawText( tab.GetText(), tx, y + ( tab.mDims.y - h ) / 2 );
816 }
817 }
818
819 void wxPaggedWindow::DrawDecorations( wxDC& dc )
820 {
821 // FIXME:: the is big body have to be split!
822
823 int width, height;
824 GetClientSize( &width, &height );
825
826 int curX = mHorizGap;
827 int curY = mVertGap;
828
829 int xSize = width - mHorizGap*2;
830 int ySize = height - mVertGap*2;
831
832 DrawShadedRect( curX, curY, xSize, ySize,
833 mDarkPen, mWhitePen, dc );
834
835 DrawShadedRect( curX+1, curY+1, xSize-2, ySize-2,
836 mBlackPen, mGrayPen, dc );
837
838 // draw inactive tab title bars frist (left-to-right)
839
840 wxNode* pNode = mTabs.First();
841 int tabNo = 0;
842
843 /* OLD STUFF::
844 curX = mTitleRowStart;
845 curY = height - mVertGap - BORDER_SZ - mTitleHeight;
846 */
847
848 curX = mTabTrianGap;
849 curY = 0;
850
851 // FOR NOW:: avoid creating bitmap with invalid dimensions
852
853 if ( mTitleRowLen < 1 || mTitleHeight < 1 ) return;
854
855 wxMemoryDC tmpDc;
856 wxBitmap tmpBmp( mTitleRowLen, mTitleHeight );
857
858 tmpDc.SelectObject( tmpBmp );
859 tmpDc.SetPen( mGrayPen );
860 tmpDc.SetBrush( mGrayBrush );
861 tmpDc.DrawRectangle( 0,0, mTitleRowLen, mTitleHeight );
862
863 tmpDc.SetDeviceOrigin( mCurentRowOfs, 0 );
864
865 while( pNode )
866 {
867 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
868
869 if ( tabNo != mActiveTab )
870
871 DrawPaperBar( tab, curX, curY, mGrayBrush, mBlackPen, tmpDc );
872
873 curX += tab.mDims.x;
874
875 pNode = pNode->Next();
876 ++tabNo;
877 }
878
879 // finally, draw the active tab (white-filled)
880
881 pNode = mTabs.First();
882 tabNo = 0;
883
884 curX = mTabTrianGap;
885
886 while( pNode )
887 {
888 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
889
890 if ( tabNo == mActiveTab )
891 {
892 DrawPaperBar( tab, curX, curY, mWhiteBrush, mBlackPen, tmpDc );
893
894 tmpDc.SetPen( mWhitePen );
895
896 tmpDc.DrawLine( curX - mTabTrianGap+1, curY,
897 curX + tab.mDims.x + mTabTrianGap, curY );
898 break;
899 }
900 curX += tab.mDims.x;
901
902 pNode = pNode->Next();
903 ++tabNo;
904 }
905
906 // back to initial device origin
907
908 tmpDc.SetDeviceOrigin( 0, 0 );
909
910 // draw resize-hint-stick
911
912 curX = mTitleRowLen - 6;
913
914 DrawShadedRect( curX+0, 0+0, 6, mTitleHeight, mGrayPen, mBlackPen, tmpDc );
915 DrawShadedRect( curX+1, 0+1, 6-2, mTitleHeight-2, mWhitePen, mDarkPen, tmpDc );
916 DrawShadedRect( curX+2, 0+2, 6-4, mTitleHeight-4, mGrayPen, mGrayPen, tmpDc );
917
918
919
920 dc.Blit( mTitleRowStart,
921 height - mVertGap - BORDER_SZ - mTitleHeight,
922 mTitleRowLen, mTitleHeight,
923 &tmpDc, 0,0, wxCOPY );
924 }
925
926 int wxPaggedWindow::HitTest( const wxPoint& pos )
927 {
928 return wxTabbedWindow::HitTest( pos );
929 }
930
931 void wxPaggedWindow::RecalcLayout(bool andRepaint)
932 {
933 mTitleRowLen = mAdjustableTitleRowLen;
934
935 if ( int(mpTabScroll) == -1 ) return;
936
937 // scroll bars should be created after Create() for this window is called
938 if ( !mpTabScroll )
939 {
940 mpTabScroll =
941 new wxScrollBar( this, -1, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL );
942
943 mpHorizScroll =
944 new wxScrollBar( this, -1, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL );
945
946 mpVertScroll =
947 new wxScrollBar( this, -1, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL );
948 }
949
950 {
951 int units = GetWholeTabRowLen() / 20;
952
953 mpTabScroll->SetScrollbar( 0, 1, units, 1, FALSE );
954 }
955
956 // resetup position of the active tab
957
958 int thumbLen = 16; // FOR NOW:: hardcoded
959
960 int width, height;
961 GetClientSize( &width, &height );
962
963 mTitleHeight = thumbLen;
964
965 int curX = mHorizGap + BORDER_SZ;
966 int curY = mVertGap + BORDER_SZ;
967
968 int xSize = width - mHorizGap*2 - BORDER_SZ*2 - thumbLen;
969
970 int ySize = height - mVertGap*2 - BORDER_SZ*2 - mTitleHeight;
971
972 SizeTabs( curX, curY, xSize, ySize, andRepaint );
973
974 // setup title bar LINES's horizontal scroll bar
975
976 curY = height - mVertGap - BORDER_SZ - thumbLen;
977
978 mpTabScroll->SetSize( curX, curY, thumbLen*2, thumbLen );
979
980 // setup view's HORIZONTAL scroll bar
981
982 curX += thumbLen*2;
983
984 mTitleRowStart = curX;
985 mFirstTitleGap = curX + mCurentRowOfs + mTabTrianGap;
986
987 mTitleRowLen = wxMin( mAdjustableTitleRowLen,
988 width - mHorizGap - BORDER_SZ - thumbLen*4 - curX );
989
990 curX += mTitleRowLen;
991
992 mpHorizScroll->SetSize( curX, curY,
993 width - curX - mHorizGap - BORDER_SZ - thumbLen,
994 thumbLen
995 );
996
997 // setup view's VERTICAL scroll bar
998
999 curX = width - mHorizGap - BORDER_SZ - thumbLen;
1000
1001 curY = mVertGap + BORDER_SZ;
1002
1003 mpVertScroll->SetSize( curX, curY, thumbLen,
1004 height - curY - mVertGap - BORDER_SZ - thumbLen
1005 );
1006
1007 // layout tab title bars
1008
1009 mLayoutType = wxTITLE_IMG_AND_TEXT;
1010
1011 wxNode* pNode = mTabs.First();
1012
1013 while( pNode )
1014 {
1015 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
1016
1017 wxWindowDC dc(this);
1018
1019 long w,h;
1020
1021 // set select default font of the window into it's device context
1022 dc.SetFont( GetLabelingFont() );
1023 dc.GetTextExtent(tab.mText, &w, &h );
1024
1025 tab.mDims.x = w + tab.ImageToTxtGap(mImageTextGap) +
1026 tab.ImgWidth() + mTitleHorizGap*2;
1027
1028 tab.mDims.y = mTitleHeight;
1029
1030 pNode = pNode->Next();
1031 }
1032
1033 // disable title-bar scroller if there's nowhere to scroll to
1034
1035 mpTabScroll->Enable( mTitleRowLen < GetWholeTabRowLen() || mCurentRowOfs < 0 );
1036 }
1037
1038 // event handlers
1039
1040 void wxPaggedWindow::OnPaint( wxPaintEvent& event )
1041 {
1042 wxPaintDC dc(this);
1043 DrawDecorations( dc );
1044 }
1045
1046 void wxPaggedWindow::OnSize ( wxSizeEvent& event )
1047 {
1048 wxTabbedWindow::OnSize(event);
1049 }
1050
1051 void wxPaggedWindow::OnLButtonDown( wxMouseEvent& event )
1052 {
1053 if ( mCursorChanged )
1054 {
1055 mIsDragged = TRUE;
1056 mDagOrigin = event.m_x;
1057
1058 mOriginalTitleRowLen = mAdjustableTitleRowLen;
1059
1060 CaptureMouse();
1061 }
1062 else
1063 {
1064 wxTabbedWindow::OnLButtonDown( event );
1065 }
1066 }
1067
1068 void wxPaggedWindow::OnLButtonUp( wxMouseEvent& event )
1069 {
1070 if ( mIsDragged )
1071 {
1072 mIsDragged = FALSE;
1073 mCursorChanged = FALSE;
1074 SetCursor( mNormalCursor );
1075
1076 ReleaseMouse();
1077 }
1078 }
1079
1080 void wxPaggedWindow::OnMouseMove( wxMouseEvent& event )
1081 {
1082 int width, height;
1083 GetClientSize( &width, &height );
1084
1085 if ( !mIsDragged )
1086 {
1087 int y = height - mVertGap - BORDER_SZ - mTitleHeight;
1088 int x = mTitleRowStart + mTitleRowLen - 6;
1089
1090 if ( event.m_x >= x && event.m_y >= y &&
1091 event.m_x < x + 6 &&
1092 event.m_y < y + mTitleHeight
1093 )
1094 {
1095 if ( !mCursorChanged )
1096 {
1097 SetCursor( mResizeCursor );
1098
1099 mCursorChanged = TRUE;
1100 }
1101 }
1102 else
1103 if ( mCursorChanged )
1104 {
1105 SetCursor( mNormalCursor );
1106
1107 mCursorChanged = FALSE;
1108 }
1109 }
1110 else
1111 if ( mIsDragged )
1112 {
1113 mAdjustableTitleRowLen = mOriginalTitleRowLen + ( event.m_x - mDagOrigin );
1114
1115 // FOR NOW:: fixed
1116 if ( mAdjustableTitleRowLen < 6 ) mAdjustableTitleRowLen = 6;
1117
1118 wxWindowDC dc(this);
1119 DrawDecorations( dc );
1120
1121 RecalcLayout(FALSE);
1122
1123 //Refresh();
1124 }
1125 }
1126
1127 void wxPaggedWindow::OnScroll( wxScrollEvent& event )
1128 {
1129 int cmd = event.m_commandInt;
1130
1131 wxScrollBar* pSender = (wxScrollBar*)event.GetEventObject();
1132
1133 if ( pSender == mpTabScroll )
1134 {
1135 int maxLen = GetWholeTabRowLen();
1136
1137 int maxUnits = GetWholeTabRowLen() / 20;
1138
1139 mCurentRowOfs = -event.GetPosition()*maxUnits;
1140
1141 mFirstTitleGap = mTitleRowStart + mCurentRowOfs + mTabTrianGap;
1142
1143 // let' it automatically disable itself if it's time
1144 mpTabScroll->Enable( mTitleRowLen < GetWholeTabRowLen() || mCurentRowOfs < 0 );
1145
1146 // repaint title bars
1147 wxWindowDC dc(this);
1148 DrawDecorations( dc );
1149 }
1150 else
1151 if ( !mScrollEventInProgress )
1152 {
1153 mScrollEventInProgress = TRUE;
1154
1155 GetActiveTab()->GetEventHandler()->ProcessEvent( event );
1156 }
1157 else
1158 {
1159 // event bounced back to us, from here we
1160 // know that it has traveled the loop - thus it's processed!
1161
1162 mScrollEventInProgress = FALSE;
1163 }
1164 }