]> git.saurik.com Git - wxWidgets.git/blame - demos/dbbrowse/tabpgwin.cpp
remove HWND association when DestroyWindow
[wxWidgets.git] / demos / dbbrowse / tabpgwin.cpp
CommitLineData
b5ffecfc
GT
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//---------------------------------------------------------------------------
45IMPLEMENT_DYNAMIC_CLASS( twTabInfo, wxObject )
b5ce269b
BJ
46 //---------------------------------------------------------------------------
47 twTabInfo::twTabInfo()
48 : mpContent( 0 )
b5ffecfc
GT
49{}
50//---------------------------------------------------------------------------
51twTabInfo::~twTabInfo()
52{
b5ce269b 53 // FOR NOW:: nothing
b5ffecfc
GT
54}
55//---------------------------------------------------------------------------
56int twTabInfo::ImgWidth()
57{
b5ce269b 58 if ( mBitMap.Ok() ) return mBitMap.GetWidth();
b5ffecfc
GT
59 else return 0;
60}
61//---------------------------------------------------------------------------
62int twTabInfo::ImgHeight()
63{
b5ce269b 64 if ( mBitMap.Ok() ) return mBitMap.GetHeight();
b5ffecfc
GT
65 else return 0;
66}
67//---------------------------------------------------------------------------
68int twTabInfo::ImageToTxtGap( int prefGap )
69{
b5ce269b 70 if ( mBitMap.Ok() ) return prefGap;
b5ffecfc
GT
71 else return 0;
72}
73//---------------------------------------------------------------------------
74bool twTabInfo::HasImg()
75{
b5ce269b 76 return mBitMap.Ok();
b5ffecfc
GT
77}
78//---------------------------------------------------------------------------
79// bool twTabInfo::HasText();
80unsigned int twTabInfo::HasText()
81{
b5ce269b 82 return mText.Length();
b5ffecfc
GT
83}
84//---------------------------------------------------------------------------
85wxBitmap& twTabInfo::GetImg()
86{
b5ce269b 87 return mBitMap;
b5ffecfc
GT
88}
89//---------------------------------------------------------------------------
90wxString& twTabInfo::GetText()
91{
b5ce269b 92 return mText;
b5ffecfc
GT
93}
94//---------------------------------------------------------------------------
95wxWindow& twTabInfo::GetContent()
96{
b5ce269b 97 return *mpContent;
b5ffecfc
GT
98}
99//---------------------------------------------------------------------------
100// Implementation for class wxTabbedWindow
101//---------------------------------------------------------------------------
102IMPLEMENT_DYNAMIC_CLASS( wxTabbedWindow, wxPanel )
b5ce269b
BJ
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 )
b5ffecfc
GT
138{}
139//---------------------------------------------------------------------------
140wxTabbedWindow::~wxTabbedWindow()
141{
b5ce269b
BJ
142 wxNode* pTab = mTabs.First();
143
144 while( pTab )
145 {
146 delete ((twTabInfo*)pTab->Data());
147 pTab = pTab->Next();
148 }
b5ffecfc
GT
149}
150//---------------------------------------------------------------------------
151void wxTabbedWindow::SizeTabs(int x,int y, int width, int height, bool repant)
152{
b5ce269b
BJ
153 wxNode* pTabNode = mTabs.First();
154 int n = 0;
155
b5ffecfc 156 while( pTabNode )
b5ce269b
BJ
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 }
b5ffecfc
GT
178}
179//---------------------------------------------------------------------------
180void wxTabbedWindow::AddTab( wxWindow* pContent,
b5ce269b
BJ
181 wxString tabText,
182 wxString imageFileName,
183 long imageType )
b5ffecfc 184{
b5ce269b
BJ
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 );
b5ffecfc
GT
207}
208//---------------------------------------------------------------------------
209void wxTabbedWindow::AddTab( wxWindow* pContent,
b5ce269b 210 wxString tabText, wxBitmap* pImage )
b5ffecfc 211{
b5ce269b
BJ
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 );
b5ffecfc
GT
226}
227//---------------------------------------------------------------------------
228void wxTabbedWindow::RemoveTab( int tabNo )
229{
b5ce269b
BJ
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 );
b5ffecfc
GT
238}
239//---------------------------------------------------------------------------
240int wxTabbedWindow::GetTabCount()
241{
242 return mTabs.Number();
243}
244//---------------------------------------------------------------------------
245wxWindow* wxTabbedWindow::GetTab( int tabNo )
246{
b5ce269b 247 return ((twTabInfo*)(mTabs.Nth( tabNo )->Data()))->mpContent;
b5ffecfc
GT
248}
249//---------------------------------------------------------------------------
250wxWindow* wxTabbedWindow::GetActiveTab()
251{
b5ce269b
BJ
252 // FIMXE:: this is lame
253 return GetTab( mActiveTab );
b5ffecfc
GT
254}
255//---------------------------------------------------------------------------
256void wxTabbedWindow::SetActiveTab( int tabNo )
257{
b5ce269b
BJ
258 mActiveTab = tabNo;
259 RecalcLayout(TRUE);
260 Refresh();
b5ffecfc
GT
261}
262//---------------------------------------------------------------------------
263// width of the decorations border (4 shade-lines), should not be changed
264//---------------------------------------------------------------------------
265#define BORDER_SZ 4
266//---------------------------------------------------------------------------
267void wxTabbedWindow::DrawShadedRect( int x, int y, int width, int height,
b5ce269b
BJ
268 wxPen& upperPen, wxPen& lowerPen, wxDC& dc
269 )
b5ffecfc 270{
b5ce269b
BJ
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
b5ffecfc
GT
282}
283//---------------------------------------------------------------------------
284void wxTabbedWindow::DrawDecorations( wxDC& dc )
285{
b5ce269b
BJ
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;
b5ffecfc 292 GetClientSize( &width, &height );
b5ce269b
BJ
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
b5ffecfc 358 if ( tabNo == mActiveTab )
b5ce269b 359 dc.DrawLine( curX, curY-2, curX, curY+ySize-2 );
b5ffecfc 360 else
b5ce269b
BJ
361 dc.DrawLine( curX, curY, curX, curY+ySize-2 );
362
b5ffecfc
GT
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 )
b5ce269b 368 dc.DrawLine( curX+xSize-2, curY+ySize-3, curX+xSize-2, curY-3 );
b5ffecfc 369 else
b5ce269b
BJ
370 dc.DrawLine( curX+xSize-2, curY+ySize-3, curX+xSize-2, curY-1 );
371
b5ffecfc
GT
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 );
b5ce269b 376
b5ffecfc
GT
377 pNode = pNode->Next();
378 ++tabNo;
b5ce269b 379
b5ffecfc
GT
380 // darw image and (or without) text centered within the
381 // title bar rectangle
b5ce269b 382
b5ffecfc 383 if ( mLayoutType != wxTITLE_BORDER_ONLY && tab.HasImg() )
b5ce269b
BJ
384 {
385 wxMemoryDC tmpDc;
b5ffecfc 386 tmpDc.SelectObject( tab.GetImg() );
b5ce269b 387
b5ffecfc 388 dc.Blit( curX + mTitleHorizGap,
b5ce269b
BJ
389 curY + ( ySize - tab.ImgHeight() ) / 2,
390 tab.ImgWidth(),
391 tab.ImgHeight(),
392 &tmpDc, 0, 0, wxCOPY
393 );
394 }
395
b5ffecfc 396 if ( mLayoutType == wxTITLE_IMG_AND_TEXT && tab.HasText() )
b5ce269b
BJ
397 {
398 long x,w,h;
399
400 // set select default font of the window into it's device context
ed6e827e 401 //dc.SetFont( GetLabelingFont() );
b5ce269b
BJ
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 }
b5ffecfc 412 curX += xSize;
b5ce269b
BJ
413
414 } // end of `while (pNode)'
b5ffecfc
GT
415}
416//---------------------------------------------------------------------------
417int wxTabbedWindow::HitTest( const wxPoint& pos )
418{
b5ce269b 419 int width, height;
b5ffecfc 420 GetClientSize( &width, &height );
b5ce269b
BJ
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;
b5ffecfc
GT
450}
451//---------------------------------------------------------------------------
452void wxTabbedWindow::HideInactiveTabs( bool andRepaint )
453{
b5ce269b
BJ
454 if ( !andRepaint )
455 return;
456
457 wxNode* pNode = mTabs.First();
458 int tabNo = 0;
459
460 while( pNode )
461 {
462 if ( tabNo != mActiveTab )
b5ffecfc 463 {
b5ce269b
BJ
464 twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
465 tab.mpContent->Show(FALSE);
b5ffecfc 466 }
b5ce269b
BJ
467
468 pNode = pNode->Next();
469 ++tabNo;
470 }
b5ffecfc
GT
471}
472//---------------------------------------------------------------------------
473wxFont wxTabbedWindow::GetLabelingFont()
474{
b5ce269b 475 wxFont font;
b5ffecfc 476#ifdef __WINDOWS__
b5ce269b 477 font.SetFaceName("MS Sans Serif");
b5ffecfc 478#else
b5ce269b 479 font.SetFamily( wxSWISS );
b5ffecfc 480#endif
b5ce269b
BJ
481
482 font.SetStyle(40);
483 font.SetWeight(40);
484 font.SetPointSize( 8 );
485
b5ffecfc 486#ifdef __WINDOWS__
b5ce269b 487 font.RealizeResource();
b5ffecfc 488#endif
b5ce269b
BJ
489
490 return font;
b5ffecfc
GT
491}
492//---------------------------------------------------------------------------
493void wxTabbedWindow::RecalcLayout(bool andRepaint)
494{
b5ce269b
BJ
495 HideInactiveTabs(andRepaint);
496
497 // resetup position of the active tab
498
499 int width, height;
b5ffecfc 500 GetClientSize( &width, &height );
b5ce269b
BJ
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
ed6e827e 528 //dc.SetFont( GetLabelingFont() );
b5ce269b 529
b5ffecfc 530 dc.GetTextExtent(tab.mText, &w, &h );
b5ce269b 531
b5ffecfc 532 tab.mDims.x = w + tab.ImageToTxtGap(mImageTextGap) +
b5ce269b
BJ
533 tab.ImgWidth() + mTitleHorizGap*2;
534
b5ffecfc
GT
535 tab.mDims.y = wxMax( h, tab.ImgHeight() ) + mTitleVertGap*2;
536 mTitleHeight = wxMax( mTitleHeight, tab.mDims.y );
b5ce269b 537
b5ffecfc 538 curX += tab.mDims.x;
b5ce269b 539
b5ffecfc 540 pNode = pNode->Next();
b5ce269b
BJ
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
b5ffecfc 594 // if curX has'nt ran out of bounds, leave IMG_ONLY layout and return
b5ce269b
BJ
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 }
b5ffecfc
GT
613}
614//---------------------------------------------------------------------------
615// wx event handlers
616//---------------------------------------------------------------------------
617void wxTabbedWindow::OnPaint( wxPaintEvent& event )
618{
b5ce269b
BJ
619 wxPaintDC dc(this);
620 DrawDecorations( dc );
b5ffecfc
GT
621}
622//---------------------------------------------------------------------------
623void wxTabbedWindow::OnSize ( wxSizeEvent& event )
624{
b5ce269b
BJ
625 SetBackgroundColour( wxColour( 192,192,192 ) );
626 RecalcLayout(TRUE);
b5ffecfc
GT
627}
628//---------------------------------------------------------------------------
629void wxTabbedWindow::OnBkErase( wxEraseEvent& event )
630{
b5ce269b 631 // do nothing
b5ffecfc
GT
632}
633//---------------------------------------------------------------------------
634void wxTabbedWindow::OnLButtonDown( wxMouseEvent& event )
635{
b5ce269b
BJ
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 }
b5ffecfc
GT
646}
647//---------------------------------------------------------------------------
648// Implementation for class wxPaggedWindow
649//---------------------------------------------------------------------------
650IMPLEMENT_DYNAMIC_CLASS( wxPaggedWindow, wxTabbedWindow )
b5ce269b
BJ
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 //---------------------------------------------------------------------------
b5ffecfc
GT
663#undef BORDER_SZ
664#define BORDER_SZ 2
b5ce269b
BJ
665 //---------------------------------------------------------------------------
666 wxPaggedWindow::wxPaggedWindow()
667
b5ffecfc 668 : mScrollEventInProgress( FALSE ),
b5ce269b
BJ
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 )
b5ffecfc 683{
b5ce269b
BJ
684 mTitleVertGap = 2;
685 mTitleHorizGap = 10;
b5ffecfc
GT
686 mNoVertScroll = TRUE; // Horizontale Scroll abschalten
687}
688//---------------------------------------------------------------------------
689wxPaggedWindow::~wxPaggedWindow()
690{
b5ce269b 691 // nothing (base class handles destruction)
b5ffecfc
GT
692}
693//---------------------------------------------------------------------------
694wxFont wxPaggedWindow::GetLabelingFont()
695{
b5ce269b
BJ
696 wxFont font;
697
b5ffecfc 698#ifdef __WINDOWS__
b5ce269b 699 font.SetFaceName("Comic Sans MS");
b5ffecfc 700#else
b5ce269b 701 font.SetFamily( wxSWISS );
b5ffecfc 702#endif
b5ce269b 703
b5ffecfc
GT
704 font.SetStyle(40);
705 font.SetWeight(40);
706 font.SetPointSize( 8 );
b5ce269b 707
b5ffecfc
GT
708 return font;
709}
710//---------------------------------------------------------------------------
711void wxPaggedWindow::OnTabAdded( twTabInfo* pInfo )
712{
b5ce269b 713 int units = GetWholeTabRowLen() / 20;
b5ffecfc 714
b5ce269b 715 mpTabScroll->SetScrollbar( 0, 1, units, 1, FALSE );
b5ffecfc
GT
716}
717//---------------------------------------------------------------------------
718wxScrollBar& wxPaggedWindow::GetVerticalScrollBar()
719{
b5ce269b 720 return *mpVertScroll;
b5ffecfc
GT
721}
722//---------------------------------------------------------------------------
723wxScrollBar& wxPaggedWindow::GetHorizontalScrollBar()
724{
b5ce269b 725 return *mpHorizScroll;
b5ffecfc
GT
726}
727//---------------------------------------------------------------------------
728int wxPaggedWindow::GetWholeTabRowLen()
729{
b5ce269b
BJ
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;
b5ffecfc
GT
743}
744//---------------------------------------------------------------------------
745void wxPaggedWindow::DrawPaperBar( twTabInfo& tab, int x, int y,
b5ce269b 746 wxBrush& brush, wxPen& pen, wxDC& dc )
b5ffecfc 747{
b5ce269b
BJ
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
ed6e827e 772 //dc.SetFont( GetLabelingFont() );
b5ce269b
BJ
773
774 dc.SetTextBackground( brush.GetColour() );
775
776 dc.GetTextExtent(tab.mText, &w, &h );
777
778 if ( tab.HasImg() )
779 {
780 wxMemoryDC tmpDc;
b5ffecfc 781 tmpDc.SelectObject( tab.GetImg() );
b5ce269b 782
b5ffecfc 783 dc.Blit( x + mTitleHorizGap,
b5ce269b
BJ
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 }
b5ffecfc
GT
798}
799//---------------------------------------------------------------------------
800void wxPaggedWindow::DrawDecorations( wxDC& dc )
801{
b5ce269b
BJ
802 // FIXME:: the is big body have to be split!
803
804 int width, height;
b5ffecfc
GT
805 GetClientSize( &width, &height );
806
b5ce269b
BJ
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 );
b5ffecfc
GT
905}
906//---------------------------------------------------------------------------
907int wxPaggedWindow::HitTest( const wxPoint& pos )
908{
b5ce269b 909 return wxTabbedWindow::HitTest( pos );
b5ffecfc
GT
910}
911//---------------------------------------------------------------------------
912void wxPaggedWindow::RecalcLayout(bool andRepaint)
913{
b5ce269b
BJ
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;
b5ffecfc 949 if (!mNoVertScroll) // Vertical Scroll (Original)
b5ce269b
BJ
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,
b5ffecfc 971 width - mHorizGap - BORDER_SZ - thumbLen*4 - curX );
b5ce269b
BJ
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
ed6e827e 1002 //dc.SetFont( GetLabelingFont() );
b5ce269b
BJ
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 );
b5ffecfc
GT
1016}
1017//---------------------------------------------------------------------------
1018// event handlers
1019//---------------------------------------------------------------------------
1020void wxPaggedWindow::OnPaint( wxPaintEvent& event )
1021{
b5ce269b
BJ
1022 wxPaintDC dc(this);
1023 DrawDecorations( dc );
b5ffecfc
GT
1024}
1025//---------------------------------------------------------------------------
1026void wxPaggedWindow::OnSize ( wxSizeEvent& event )
1027{
b5ce269b 1028 wxTabbedWindow::OnSize(event);
b5ffecfc
GT
1029}
1030//---------------------------------------------------------------------------
1031void wxPaggedWindow::OnLButtonDown( wxMouseEvent& event )
1032{
b5ce269b
BJ
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 }
b5ffecfc
GT
1046}
1047//---------------------------------------------------------------------------
1048void wxPaggedWindow::OnLButtonUp( wxMouseEvent& event )
1049{
b5ce269b
BJ
1050 if ( mIsDragged )
1051 {
1052 mIsDragged = FALSE;
1053 mCursorChanged = FALSE;
1054 SetCursor( mNormalCursor );
1055
1056 ReleaseMouse();
1057 }
b5ffecfc
GT
1058}
1059//---------------------------------------------------------------------------
1060void wxPaggedWindow::OnMouseMove( wxMouseEvent& event )
1061{
b5ce269b 1062 int width, height;
b5ffecfc 1063 GetClientSize( &width, &height );
b5ce269b
BJ
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 }
b5ffecfc 1090 else
b5ce269b
BJ
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 }
b5ffecfc
GT
1105}
1106//---------------------------------------------------------------------------
1107void wxPaggedWindow::OnScroll( wxScrollEvent& event )
1108{
b5ce269b
BJ
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 }
b5ffecfc
GT
1142}
1143//---------------------------------------------------------------------------
b5ce269b 1144