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