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