]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/framelayout/src/controlarea.cpp
Added Aleksandras' framelayout code, with more or less working Linux Makefiles
[wxWidgets.git] / utils / framelayout / src / controlarea.cpp
diff --git a/utils/framelayout/src/controlarea.cpp b/utils/framelayout/src/controlarea.cpp
new file mode 100644 (file)
index 0000000..b960b1c
--- /dev/null
@@ -0,0 +1,1164 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        No names yet.
+// Purpose:     Contrib. demo
+// Author:      Aleksandras Gluchovas
+// Modified by:
+// Created:     07/09/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Aleksandras Gluchovas
+// Licence:    wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "controlarea.h"
+// #pragma interface
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "wx/string.h"
+#include "wx/utils.h"     // import wxMin/wxMax macros and wxFileExist(..) 
+
+#include "controlarea.h"
+
+
+/***** Implementation for class twTabInfo *****/
+
+IMPLEMENT_DYNAMIC_CLASS( twTabInfo, wxObject )
+
+twTabInfo::twTabInfo()
+       : mpContent( 0 )
+{}
+
+twTabInfo::~twTabInfo()
+{
+       // FOR NOW:: nothing
+}
+
+int twTabInfo::ImgWidth()
+{
+       if ( mBitMap.Ok() ) return mBitMap.GetWidth();
+                          else return 0;
+}
+
+int twTabInfo::ImgHeight()
+{
+       if ( mBitMap.Ok() ) return mBitMap.GetHeight();
+                          else return 0;
+}
+
+int twTabInfo::ImageToTxtGap( int prefGap )
+{
+       if ( mBitMap.Ok() ) return prefGap;
+                              else return 0;
+}
+
+bool twTabInfo::HasImg()
+{
+       return mBitMap.Ok();
+}
+
+bool twTabInfo::HasText()
+{
+       return mText.Length();
+}
+
+wxBitmap& twTabInfo::GetImg()
+{
+       return mBitMap;
+}
+
+wxString& twTabInfo::GetText()
+{
+       return mText;
+}
+
+wxWindow& twTabInfo::GetContent()
+{
+       return *mpContent;
+}
+
+/***** Implementation for class wxTabbedWindow *****/
+
+IMPLEMENT_DYNAMIC_CLASS( wxTabbedWindow, wxPanel )
+
+BEGIN_EVENT_TABLE( wxTabbedWindow, wxPanel )
+
+       EVT_SIZE ( wxTabbedWindow::OnSize )
+       EVT_PAINT( wxTabbedWindow::OnPaint )
+       EVT_LEFT_DOWN( wxTabbedWindow::OnLButtonDown )
+
+// TDB:: filciker reduction 
+//     EVT_ERASE_BACKGROUND( wxTabbedWindow::OnBkErase )
+
+END_EVENT_TABLE()
+
+wxTabbedWindow::wxTabbedWindow()
+
+       : mpTabScroll  ( NULL ),
+         mpHorizScroll( NULL ),
+         mpVertScroll ( NULL ),
+
+         mVertGap ( 0 ),
+         mHorizGap( 0 ),
+
+         mTitleVertGap ( 3  ),
+         mTitleHorizGap( 4  ),
+         mImageTextGap ( 2  ),
+         mFirstTitleGap( 11 ),
+
+         mBorderOnlyWidth( 8 ),
+
+         mWhitePen( wxColour(255,255,255), 1, wxSOLID ),
+         mGrayPen ( wxColour(192,192,192), 1, wxSOLID ),
+         mDarkPen ( wxColour(128,128,128), 1, wxSOLID ),
+         mBlackPen( wxColour(  0,  0,  0), 1, wxSOLID ),
+
+         // state variables
+
+         mActiveTab  ( 0 ),
+         mTitleHeight( 0 ),
+         mLayoutType( wxTITLE_IMG_AND_TEXT )
+{}
+
+wxTabbedWindow::~wxTabbedWindow()
+{
+       wxNode* pTab = mTabs.First();
+
+       while( pTab )
+       {
+               delete ((twTabInfo*)pTab->Data());
+
+               pTab = pTab->Next();
+       }
+}
+
+void wxTabbedWindow::SizeTabs(int x,int y, int width, int height, bool repant)
+{
+       wxNode* pTabNode = mTabs.First();
+       int n = 0;
+
+       while( pTabNode )
+       {
+               twTabInfo& info = *((twTabInfo*)pTabNode->Data());
+
+               if ( n == mActiveTab )
+               {
+                       //wxSizeEvent evt;
+                       //info.mpContent->GetEventHandler()->ProcessEvent( evt );
+
+                       info.mpContent->SetSize( x, y, width, height, 0 );
+                       info.mpContent->Show(TRUE);
+                       info.mpContent->Refresh();
+
+               }
+               else
+               {
+                       info.mpContent->Show(FALSE);
+               }
+
+               pTabNode = pTabNode->Next();
+               ++n;
+       }
+}
+
+void wxTabbedWindow::AddTab( wxWindow* pContent,
+                                                        wxString  tabText,
+                                                        wxString  imageFileName,
+                                                        long      imageType )
+{
+       twTabInfo* pTab = new twTabInfo();
+
+       pTab->mpContent = pContent;
+       pTab->mText     = tabText;
+
+       if ( wxFileExists( imageFileName ) &&
+
+                pTab->mBitMap.LoadFile( imageFileName, imageType ) )
+       {
+               pTab->mImageFile = imageFileName;
+               pTab->mImageType = imageType;
+       }
+
+       bool ok = pTab->mBitMap.Ok();
+               
+       if ( pContent->GetParent() == NULL )
+       
+               pContent->Create( this, -1 );
+
+       mTabs.Append( (wxObject*)pTab );
+
+       RecalcLayout(TRUE);
+
+       OnTabAdded( pTab );
+}
+
+void wxTabbedWindow::AddTab( wxWindow* pContent,
+                                                       wxString  tabText,
+                                   wxBitmap* pImage   )
+{
+       twTabInfo* pTab = new twTabInfo();
+
+       pTab->mpContent = pContent;
+       pTab->mText     = tabText;
+
+       if ( pImage ) pTab->mBitMap = *pImage;
+
+       if ( pContent->GetParent() == NULL )
+       
+               pContent->Create( this, -1 );
+
+       mTabs.Append( (wxObject*)pTab );
+
+       RecalcLayout(TRUE);
+
+       OnTabAdded( pTab );
+}
+
+
+
+void wxTabbedWindow::RemoveTab( int tabNo )
+{
+       twTabInfo* pTab = ((twTabInfo*)(mTabs.Nth( tabNo )->Data()));
+
+       pTab->mpContent->Destroy();
+
+       delete pTab;
+
+       mTabs.DeleteNode( mTabs.Nth( tabNo ) );
+
+       if ( mActiveTab >= mTabs.Number() );
+
+               mActiveTab = mTabs.Number() - 1;
+
+       SetActiveTab( mActiveTab );
+}
+
+int wxTabbedWindow::GetTabCount()
+{
+       return mTabs.Number();
+}
+
+wxWindow* wxTabbedWindow::GetTab( int tabNo )
+{
+       return ((twTabInfo*)(mTabs.Nth( tabNo )->Data()))->mpContent;
+}
+
+wxWindow* wxTabbedWindow::GetActiveTab()
+{
+       // FIMXE:: this is lame
+
+       return GetTab( mActiveTab );
+}
+
+void wxTabbedWindow::SetActiveTab( int tabNo )
+{
+       mActiveTab = tabNo;
+       
+       RecalcLayout(TRUE);
+
+       Refresh();
+}
+
+// width of the decorations border (4 shade-lines), should not be changed
+
+#define BORDER_SZ 4
+
+void wxTabbedWindow::DrawShadedRect( int x, int y, int width, int height,
+                                                                   wxPen& upperPen, wxPen& lowerPen, wxDC& dc 
+                                                                 )
+{
+       // darw the lightened upper-left sides of the rectangle
+
+       dc.SetPen( upperPen );
+       dc.DrawLine( x,y, x, y + height - 1 ); // vert
+       dc.DrawLine( x,y, x + width - 1,  y ); // horiz
+
+       // draw the unenlightened lower-right sides of the rectangle
+
+       dc.SetPen( lowerPen );
+       dc.DrawLine( x + width - 1,  y, x + width - 1, y + height - 1 ); // vert
+       dc.DrawLine( x, y + height - 1, x + width, y + height - 1 );     // horiz
+}
+
+void wxTabbedWindow::DrawDecorations( wxDC& dc )
+{
+       // Protability NOTE::: DrawLine(..) draws a line from the first position, 
+       //                     but not including the point specified by last position.
+       //                     This way Windows draws lines, not sure how Motif and Gtk 
+       //                     prots behave...
+       
+       int width, height;
+       GetClientSize( &width, &height );
+
+       // check if there's at least a bit of space to draw things
+       
+       if ( width  < mHorizGap*2 + BORDER_SZ*2+1 || 
+                height < mVertGap*2  + BORDER_SZ*2+1 + mTitleHeight
+          )
+               return;
+
+       // step #1 - draw border around the tab content area
+
+       // setup position for kind of "pencil"
+       int curX = mHorizGap;
+       int curY = mVertGap;
+                                                         
+       int xSize = width  - mHorizGap*2;
+       int ySize = height - mVertGap *2  - mTitleHeight;
+
+       // layer 1 (upper white)
+       DrawShadedRect( curX+0, curY+0, xSize-0, ySize-0, 
+                                       mWhitePen, mBlackPen, dc  );
+
+       // layer 2 (upper gray)
+       DrawShadedRect( curX+1, curY+1, xSize-2-1, ySize-2-1, 
+                                       mGrayPen, mGrayPen, dc  );
+
+       // layer 3 (upper darkGray)
+       DrawShadedRect( curX+2, curY+2, xSize-3-2, ySize-3-2, 
+                                       mDarkPen, mWhitePen, dc  );
+
+       // layer 4 (upper black)
+       DrawShadedRect( curX+3, curY+3, xSize-4-3, ySize-4-3, 
+                                       mBlackPen, mGrayPen, dc  );
+
+       // add non-siemtric layer from the lower-right side (confroming to MFC-look)
+
+       dc.SetPen( mDarkPen );
+       dc.DrawLine( curX+1, curY + ySize - 2, curX + xSize - 1, curY + ySize - 2 );   // horiz
+       dc.DrawLine( curX + xSize - 2, curY + 1, curX + xSize - 2, curY + ySize - 2 ); // vert
+
+       // step #2 - draw tab title bars
+
+       curX = mFirstTitleGap;
+       curY = height - mVertGap - mTitleHeight;
+
+       int tabNo = 0;
+       wxNode* pNode = mTabs.First();
+
+       while( pNode )
+       {
+               // "hard-coded metafile" for decorations
+
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               xSize = tab.mDims.x;
+               ySize = mTitleHeight;
+
+               if ( tabNo == mActiveTab )
+               {
+                       dc.SetPen( mGrayPen );
+                       dc.DrawLine( curX+1, curY-2, curX+xSize-2, curY-2 );
+                       dc.DrawLine( curX+1, curY-1, curX+xSize-2, curY-1 );
+               }
+
+               dc.SetPen( mWhitePen );
+
+               if ( tabNo == mActiveTab )
+                       dc.DrawLine( curX, curY-2, curX, curY+ySize-2 );
+               else
+                       dc.DrawLine( curX, curY, curX, curY+ySize-2 );
+
+               dc.SetPen( mDarkPen );
+               dc.DrawLine( curX+1, curY+ySize-3, curX+1, curY+ySize-1 ); // to pix down
+               dc.DrawLine( curX+2, curY+ySize-2, curX+xSize-2, curY+ySize-2 );
+               dc.DrawLine( curX+xSize-3, curY+ySize-3, curX+xSize-2, curY+ySize-3 );
+               if ( tabNo == mActiveTab )
+                       dc.DrawLine( curX+xSize-2, curY+ySize-3, curX+xSize-2, curY-3 );
+               else
+                       dc.DrawLine( curX+xSize-2, curY+ySize-3, curX+xSize-2, curY-1 );
+
+               dc.SetPen( mBlackPen );
+               dc.DrawLine( curX+xSize-1, curY, curX+xSize-1, curY+ySize-2 );
+               dc.DrawLine( curX+xSize-2, curY+ySize-2, curX+xSize-3, curY+ySize-2 );
+               dc.DrawLine( curX+xSize-3, curY+ySize-1, curX+1, curY+ySize-1 );
+
+               pNode = pNode->Next();
+               ++tabNo;
+               
+               // darw image and (or without) text centered within the
+               // title bar rectangle
+
+               if ( mLayoutType != wxTITLE_BORDER_ONLY && tab.HasImg() )
+               {
+                       wxMemoryDC tmpDc;
+                   tmpDc.SelectObject( tab.GetImg() );
+  
+                   dc.Blit( curX + mTitleHorizGap, 
+                                    curY + ( ySize - tab.ImgHeight() ) / 2,
+                                        tab.ImgWidth(),
+                                        tab.ImgHeight(),
+                                        &tmpDc, 0, 0, wxCOPY
+                                  );
+               }
+
+               if ( mLayoutType == wxTITLE_IMG_AND_TEXT && tab.HasText() )
+               {
+                       long x,w,h;
+
+                       // set select default font of the window into it's device context
+                       dc.SetFont( GetLabelingFont() );
+
+                       dc.SetTextBackground( GetBackgroundColour() );
+
+                       dc.GetTextExtent(tab.mText, &w, &h );
+
+                       x = curX + mTitleHorizGap + 
+                               tab.ImgWidth() + tab.ImageToTxtGap(mImageTextGap);
+
+                       dc.DrawText( tab.GetText(), x, curY + ( ySize - h ) / 2 );
+               }
+               curX += xSize;
+
+       } // end of `while (pNode)'
+}
+
+int wxTabbedWindow::HitTest( const wxPoint& pos )
+{
+       int width, height;
+       GetClientSize( &width, &height );
+
+       int curX = mFirstTitleGap;
+       int curY = height - mVertGap - mTitleHeight;
+
+       int     tabNo = 0;
+       wxNode* pNode = mTabs.First();
+
+       int x = pos.x;
+       int y = pos.y;
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               int w,h;
+               w = tab.mDims.x;
+               h = tab.mDims.y;
+               // hit test rectangle of the currnet tab title bar
+               if ( pos.x >= curX && pos.x < curX + tab.mDims.x  &&
+                        pos.y >= curY && pos.y < curY + tab.mDims.y 
+                  )
+               {
+                       return tabNo;
+               }
+
+               curX += tab.mDims.x;
+
+               pNode = pNode->Next();
+               ++tabNo;
+       }
+
+       return -1;
+}
+
+void wxTabbedWindow::HideInactiveTabs( bool andRepaint )
+{
+       if ( !andRepaint )
+               return;
+
+       wxNode* pNode = mTabs.First();
+       int     tabNo = 0;
+
+       while( pNode )
+       {
+               if ( tabNo != mActiveTab )
+               {
+                       twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+                       tab.mpContent->Show(FALSE);
+               }
+
+               pNode = pNode->Next();
+               ++tabNo;
+       }
+}
+
+wxFont wxTabbedWindow::GetLabelingFont()
+{
+       wxFont font;
+#ifdef __WINDOWS__
+       font.SetFaceName("MS Sans Serif");
+#else
+       font.SetFamily( wxSWISS );
+#endif
+
+       font.SetStyle(40);
+       font.SetWeight(40);
+       font.SetPointSize( 8 );
+
+#ifdef __WINDOWS__
+       font.RealizeResource();
+#endif
+
+       return font;
+}
+
+void wxTabbedWindow::RecalcLayout(bool andRepaint)
+{
+       HideInactiveTabs(andRepaint);
+
+       // resetup position of the active tab
+
+       int width, height;
+       GetClientSize( &width, &height );
+
+       int curX = mHorizGap + BORDER_SZ;
+       int curY = mVertGap  + BORDER_SZ;
+
+       int xSize = width  - mHorizGap*2 - BORDER_SZ*2-1;
+       int ySize = height - mVertGap*2  - BORDER_SZ*2-1 - mTitleHeight;
+
+       SizeTabs( curX, curY, xSize, ySize, andRepaint );
+
+       // pass #1 - try to layout assuming it's wxTITLE_IMG_AND_TEXT
+
+       mLayoutType = wxTITLE_IMG_AND_TEXT;
+
+       wxNode* pNode = mTabs.First();
+
+       curX = mFirstTitleGap; // the left-side gap
+       mTitleHeight = 0;
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               wxWindowDC dc(this);
+
+               long w,h;
+
+               // set select default font of the window into it's device context
+               dc.SetFont( GetLabelingFont() );
+
+               dc.GetTextExtent(tab.mText, &w, &h );
+
+               tab.mDims.x = w + tab.ImageToTxtGap(mImageTextGap) + 
+                                 tab.ImgWidth() + mTitleHorizGap*2;
+
+               tab.mDims.y  = wxMax( h, tab.ImgHeight() ) + mTitleVertGap*2;
+               mTitleHeight = wxMax( mTitleHeight, tab.mDims.y );
+
+               curX += tab.mDims.x;
+               
+               pNode = pNode->Next();
+       }
+
+       curX += mHorizGap; // the right-side gap
+
+       // make all title bars of equel height
+
+       pNode = mTabs.First();
+
+       while( pNode )
+       {
+               ((twTabInfo*)(pNode->Data()))->mDims.y = mTitleHeight;;
+               pNode = pNode->Next();
+       }
+
+       // if curX has'nt ran out of bounds, leave TITLE_IMG layout and return
+       if ( curX < width - mHorizGap )
+               return;
+
+       // pass #2 - try to layout assuming wxTITLE_IMG_ONLY
+
+       mLayoutType = wxTITLE_IMG_ONLY;
+
+       pNode = mTabs.First();
+
+       curX = mFirstTitleGap; // the left-side gap
+
+       int denomiator = mTabs.Number();
+       if ( denomiator == 0 ) ++denomiator;
+
+       mBorderOnlyWidth = (width - mFirstTitleGap - mHorizGap) / denomiator; 
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               if ( tab.HasImg() )
+               {
+                       tab.mDims.x = tab.ImgWidth()  + mTitleHorizGap*2;
+                       tab.mDims.y = tab.ImgHeight() + mTitleVertGap*2;
+               }
+               else
+               {
+                       tab.mDims.x = mBorderOnlyWidth;
+                       tab.mDims.y = mTitleHeight;
+               }
+
+               curX += tab.mDims.x;
+               
+               pNode = pNode->Next();
+       }
+
+       curX += mHorizGap; // the right-side gap
+
+       // if curX has'nt ran out of bounds, leave IMG_ONLY layout and return
+       if ( curX < width  - mHorizGap )
+               return;
+
+       // pass #3 - set the narrowest layout wxTITLE_BORDER_ONLY
+
+       mLayoutType = wxTITLE_BORDER_ONLY;
+
+       pNode = mTabs.First();
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               tab.mDims.x = mBorderOnlyWidth;
+               tab.mDims.y = mTitleHeight;
+               
+               pNode = pNode->Next();
+       }
+}
+
+// wx event handlers
+
+void wxTabbedWindow::OnPaint( wxPaintEvent& event )
+{
+       wxPaintDC dc(this);
+       DrawDecorations( dc );
+}
+
+void wxTabbedWindow::OnSize ( wxSizeEvent& event )
+{
+       SetBackgroundColour( wxColour( 192,192,192 ) );
+       RecalcLayout(TRUE);
+}
+
+void wxTabbedWindow::OnBkErase( wxEraseEvent& event )
+{
+       // do nothing
+}
+
+void wxTabbedWindow::OnLButtonDown( wxMouseEvent& event )
+{
+       // floats, why?
+       int x = (int)event.m_x;
+       int y = (int)event.m_y;
+
+       int tabNo = HitTest( wxPoint(x,y) );
+
+       if ( tabNo != -1 )
+       {
+               SetActiveTab( tabNo );
+       }
+}
+
+/***** Implementation for class wxPaggedWindow *****/
+
+IMPLEMENT_DYNAMIC_CLASS( wxPaggedWindow, wxTabbedWindow )
+
+BEGIN_EVENT_TABLE( wxPaggedWindow, wxTabbedWindow )
+       EVT_SIZE     ( wxPaggedWindow::OnSize        )
+       EVT_PAINT    ( wxPaggedWindow::OnPaint       )
+       EVT_LEFT_DOWN( wxPaggedWindow::OnLButtonDown )
+       EVT_LEFT_UP  ( wxPaggedWindow::OnLButtonUp   )
+       EVT_MOTION   ( wxPaggedWindow::OnMouseMove   )
+       EVT_SCROLL   ( wxPaggedWindow::OnScroll      )
+END_EVENT_TABLE()
+
+// border for pagged-window is 2 shaded-lines
+
+#undef  BORDER_SZ
+#define BORDER_SZ 2
+
+wxPaggedWindow::wxPaggedWindow()
+
+    : mScrollEventInProgress( FALSE ),
+
+         mTabTrianGap(4),
+         
+         mWhiteBrush( wxColour(255,255,255), wxSOLID ),
+         mGrayBrush ( wxColour(192,192,192), wxSOLID ),
+
+         mCurentRowOfs( 0 ),
+         mAdjustableTitleRowLen( 300 ),
+
+         mIsDragged    ( FALSE ),
+         mDagOrigin    ( 0 ),
+         mCursorChanged( FALSE ),
+         mResizeCursor ( wxCURSOR_SIZEWE ),
+         mNormalCursor ( wxCURSOR_ARROW  )
+{
+       mTitleVertGap = 2;
+       mTitleHorizGap = 10;
+}
+
+wxPaggedWindow::~wxPaggedWindow()
+{
+       // nothing (base class handles destruction)
+}
+
+wxFont wxPaggedWindow::GetLabelingFont()
+{
+       wxFont font;
+
+#ifdef __WINDOWS__
+       font.SetFaceName("Arial");
+#else
+       font.SetFamily( wxSWISS );
+#endif
+
+       font.SetStyle(40);
+       font.SetWeight(40);
+       font.SetPointSize( 8 );
+
+#ifdef __WINDOWS__
+       bool success = font.RealizeResource();
+#endif
+
+       return font;
+}
+
+void wxPaggedWindow::OnTabAdded( twTabInfo* pInfo )
+{
+       int units = GetWholeTabRowLen() / 20;
+
+       mpTabScroll->SetScrollbar( 0, 1, units, 1, FALSE );
+}
+
+wxScrollBar& wxPaggedWindow::GetVerticalScrollBar()
+{
+       return *mpVertScroll;
+}
+
+wxScrollBar& wxPaggedWindow::GetHorizontalScrollBar()
+{
+       return *mpHorizScroll;
+}
+
+
+int wxPaggedWindow::GetWholeTabRowLen()
+{
+       wxNode* pNode = mTabs.First();
+
+       int len = 0;
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               len += tab.mDims.x;
+               pNode = pNode->Next();
+       }
+
+       return len;
+}
+
+void wxPaggedWindow::DrawPaperBar( twTabInfo& tab, int x, int y, 
+                                                                        wxBrush& brush, wxPen& pen, wxDC& dc )
+{
+       wxPoint poly[4];
+
+       // draw organizer-style paper outlet
+
+       poly[0].x = x - mTabTrianGap;
+       poly[0].y = y;
+
+       poly[1].x = x + mTabTrianGap;
+       poly[1].y = y + tab.mDims.y-1;
+
+       poly[2].x = x + tab.mDims.x - mTabTrianGap;
+       poly[2].y = y + tab.mDims.y-1;
+
+       poly[3].x = x + tab.mDims.x + mTabTrianGap;
+       poly[3].y = y;
+
+       dc.SetPen( pen );
+       dc.SetBrush( brush );
+
+       dc.DrawPolygon( 4, poly );
+
+       long w,h;
+
+       // set select default font of the window into it's device context
+       dc.SetFont( GetLabelingFont() );
+
+       dc.SetTextBackground( brush.GetColour() );
+
+       dc.GetTextExtent(tab.mText, &w, &h );
+
+       if ( tab.HasImg() )
+       {
+                       wxMemoryDC tmpDc;
+                   tmpDc.SelectObject( tab.GetImg() );
+  
+                   dc.Blit( x + mTitleHorizGap, 
+                                    y + ( tab.mDims.y - tab.ImgHeight() ) / 2,
+                                        tab.ImgWidth(),
+                                        tab.ImgHeight(),
+                                        &tmpDc, 0, 0, wxCOPY
+                                  );
+       }
+
+       if ( tab.HasText() )
+       {
+               int tx = x + mTitleHorizGap + 
+                       tab.ImgWidth() + tab.ImageToTxtGap(mImageTextGap);
+           
+               dc.DrawText( tab.GetText(), tx, y + ( tab.mDims.y - h ) / 2 );
+       }
+}
+
+void wxPaggedWindow::DrawDecorations( wxDC& dc )
+{
+       // FIXME:: the is big body have to be split!
+
+       int width, height;
+       GetClientSize( &width, &height );
+
+       int curX = mHorizGap;
+       int curY = mVertGap;
+
+       int xSize = width  - mHorizGap*2;
+       int ySize = height - mVertGap*2;
+
+       DrawShadedRect( curX, curY, xSize, ySize,
+                           mDarkPen, mWhitePen, dc );
+
+       DrawShadedRect( curX+1, curY+1, xSize-2, ySize-2,
+                           mBlackPen, mGrayPen, dc );
+
+       // draw inactive tab title bars frist (left-to-right)
+
+       wxNode* pNode = mTabs.First();
+       int     tabNo = 0;
+
+       /* OLD STUFF::
+       curX = mTitleRowStart;
+       curY = height - mVertGap - BORDER_SZ - mTitleHeight;
+       */
+
+       curX = mTabTrianGap;
+       curY = 0;
+
+       // FOR NOW:: avoid creating bitmap with invalid dimensions
+       
+       if ( mTitleRowLen < 1 || mTitleHeight < 1 ) return;
+
+       wxMemoryDC tmpDc;
+       wxBitmap   tmpBmp( mTitleRowLen, mTitleHeight );
+
+       tmpDc.SelectObject( tmpBmp );
+       tmpDc.SetPen( mGrayPen );
+       tmpDc.SetBrush( mGrayBrush );
+       tmpDc.DrawRectangle( 0,0, mTitleRowLen, mTitleHeight );
+
+       tmpDc.SetDeviceOrigin( mCurentRowOfs, 0 );
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               if ( tabNo != mActiveTab )
+
+                       DrawPaperBar( tab, curX, curY, mGrayBrush, mBlackPen, tmpDc );
+
+               curX += tab.mDims.x;
+
+               pNode = pNode->Next();
+               ++tabNo;
+       }
+
+       // finally, draw the active tab (white-filled)
+
+       pNode = mTabs.First();
+       tabNo = 0;
+
+       curX = mTabTrianGap;
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               if ( tabNo == mActiveTab )
+               {
+                       DrawPaperBar( tab, curX, curY, mWhiteBrush, mBlackPen, tmpDc );
+
+                       tmpDc.SetPen( mWhitePen );
+
+                       tmpDc.DrawLine( curX - mTabTrianGap+1, curY, 
+                                           curX + tab.mDims.x + mTabTrianGap, curY );
+                       break;
+               }
+               curX += tab.mDims.x;
+
+               pNode = pNode->Next();
+               ++tabNo;
+       }
+
+       // back to initial device origin
+
+       tmpDc.SetDeviceOrigin( 0, 0 );
+
+       // draw resize-hint-stick
+
+       curX = mTitleRowLen - 6;
+
+       DrawShadedRect( curX+0, 0+0, 6,   mTitleHeight,   mGrayPen,  mBlackPen, tmpDc );
+       DrawShadedRect( curX+1, 0+1, 6-2, mTitleHeight-2, mWhitePen, mDarkPen,  tmpDc );
+       DrawShadedRect( curX+2, 0+2, 6-4, mTitleHeight-4, mGrayPen,  mGrayPen,  tmpDc );
+
+
+
+       dc.Blit( mTitleRowStart, 
+                    height - mVertGap - BORDER_SZ - mTitleHeight,
+                        mTitleRowLen, mTitleHeight,
+                        &tmpDc, 0,0, wxCOPY );
+}
+
+int wxPaggedWindow::HitTest( const wxPoint& pos )
+{
+       return wxTabbedWindow::HitTest( pos );
+}
+
+void wxPaggedWindow::RecalcLayout(bool andRepaint)
+{
+       mTitleRowLen = mAdjustableTitleRowLen;
+
+       if ( int(mpTabScroll) == -1 ) return;
+
+       // scroll bars should be created after Create() for this window is called
+       if ( !mpTabScroll )
+       {
+               mpTabScroll   = 
+                       new wxScrollBar( this, -1, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL );
+           
+               mpHorizScroll = 
+                       new wxScrollBar( this, -1, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL );
+           
+               mpVertScroll  = 
+                       new wxScrollBar( this, -1, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL );
+       }
+
+       {
+               int units = GetWholeTabRowLen() / 20;
+
+               mpTabScroll->SetScrollbar( 0, 1, units, 1, FALSE );
+       }
+
+       // resetup position of the active tab
+
+       int thumbLen = 16; // FOR NOW:: hardcoded
+
+       int width, height;
+       GetClientSize( &width, &height );
+
+       mTitleHeight = thumbLen;
+
+       int curX = mHorizGap + BORDER_SZ;
+       int curY = mVertGap  + BORDER_SZ;
+
+       int xSize = width  - mHorizGap*2 - BORDER_SZ*2 - thumbLen;
+
+       int ySize = height - mVertGap*2  - BORDER_SZ*2 - mTitleHeight;
+
+       SizeTabs( curX, curY, xSize, ySize, andRepaint );
+
+       // setup title bar LINES's horizontal scroll bar
+
+       curY = height - mVertGap - BORDER_SZ - thumbLen;
+
+       mpTabScroll->SetSize( curX, curY, thumbLen*2, thumbLen );
+
+       // setup view's HORIZONTAL scroll bar
+
+       curX += thumbLen*2;
+
+       mTitleRowStart = curX;
+       mFirstTitleGap = curX + mCurentRowOfs + mTabTrianGap;
+
+       mTitleRowLen = wxMin( mAdjustableTitleRowLen,
+                                 width - mHorizGap - BORDER_SZ - thumbLen*4 - curX );
+
+       curX += mTitleRowLen;
+
+       mpHorizScroll->SetSize( curX, curY, 
+                                                 width - curX - mHorizGap - BORDER_SZ - thumbLen,
+                                                 thumbLen
+                                               );
+
+       // setup view's VERTICAL scroll bar
+
+       curX = width - mHorizGap - BORDER_SZ - thumbLen;
+
+       curY = mVertGap  + BORDER_SZ;
+
+       mpVertScroll->SetSize( curX, curY, thumbLen, 
+                                                 height - curY - mVertGap - BORDER_SZ - thumbLen
+                                               );
+       
+       // layout tab title bars
+
+       mLayoutType = wxTITLE_IMG_AND_TEXT;
+
+       wxNode* pNode = mTabs.First();
+
+       while( pNode )
+       {
+               twTabInfo& tab = *((twTabInfo*)(pNode->Data()));
+
+               wxWindowDC dc(this);
+
+               long w,h;
+
+               // set select default font of the window into it's device context
+               dc.SetFont( GetLabelingFont() );
+               dc.GetTextExtent(tab.mText, &w, &h );
+
+               tab.mDims.x = w + tab.ImageToTxtGap(mImageTextGap) + 
+                                 tab.ImgWidth() + mTitleHorizGap*2;
+
+               tab.mDims.y  = mTitleHeight;
+               
+               pNode = pNode->Next();
+       }
+
+       // disable title-bar scroller if there's nowhere to scroll to
+
+       mpTabScroll->Enable( mTitleRowLen < GetWholeTabRowLen() || mCurentRowOfs < 0  );
+}
+
+// event handlers
+
+void wxPaggedWindow::OnPaint( wxPaintEvent& event )
+{
+       wxPaintDC dc(this);
+       DrawDecorations( dc );
+}
+
+void wxPaggedWindow::OnSize ( wxSizeEvent& event )
+{
+       wxTabbedWindow::OnSize(event);
+}
+
+void wxPaggedWindow::OnLButtonDown( wxMouseEvent& event )
+{
+       if ( mCursorChanged )
+       {
+               mIsDragged = TRUE;
+               mDagOrigin = event.m_x;
+
+               mOriginalTitleRowLen = mAdjustableTitleRowLen;
+
+               CaptureMouse();
+       }
+       else
+       {
+               wxTabbedWindow::OnLButtonDown( event );
+       }
+}
+
+void wxPaggedWindow::OnLButtonUp( wxMouseEvent& event )
+{
+       if ( mIsDragged )
+       {
+               mIsDragged     = FALSE;
+               mCursorChanged = FALSE;
+               SetCursor( mNormalCursor );
+
+               ReleaseMouse();
+       }
+}
+
+void wxPaggedWindow::OnMouseMove( wxMouseEvent& event )
+{
+       int width, height;
+       GetClientSize( &width, &height );
+
+       if ( !mIsDragged )
+       {
+               int y = height - mVertGap - BORDER_SZ - mTitleHeight;
+               int x = mTitleRowStart + mTitleRowLen - 6;
+
+               if ( event.m_x >= x && event.m_y >= y &&
+                        event.m_x <  x + 6               &&
+                        event.m_y <  y + mTitleHeight 
+                  )
+               {
+                       if ( !mCursorChanged )
+                       {
+                               SetCursor( mResizeCursor );
+                               
+                               mCursorChanged = TRUE;
+                       }
+               }
+               else
+               if ( mCursorChanged )
+               {
+                       SetCursor( mNormalCursor );
+
+                       mCursorChanged = FALSE;
+               }
+       }
+       else
+       if ( mIsDragged )
+       {
+               mAdjustableTitleRowLen = mOriginalTitleRowLen + ( event.m_x - mDagOrigin );
+
+               // FOR NOW:: fixed
+               if ( mAdjustableTitleRowLen < 6 ) mAdjustableTitleRowLen = 6; 
+
+               wxWindowDC dc(this); 
+               DrawDecorations( dc );
+
+               RecalcLayout(FALSE);
+
+               //Refresh();
+       }
+}
+
+void wxPaggedWindow::OnScroll( wxScrollEvent& event )
+{
+       int cmd = event.m_commandInt;
+
+       wxScrollBar* pSender = (wxScrollBar*)event.GetEventObject();
+
+       if ( pSender == mpTabScroll )
+       {
+               int maxLen = GetWholeTabRowLen();
+
+               int maxUnits = GetWholeTabRowLen() / 20;
+
+               mCurentRowOfs = -event.GetPosition()*maxUnits;
+
+               mFirstTitleGap = mTitleRowStart + mCurentRowOfs + mTabTrianGap;
+
+               // let' it automatically disable itself if it's time
+               mpTabScroll->Enable( mTitleRowLen < GetWholeTabRowLen() || mCurentRowOfs < 0 );
+
+               // repaint title bars
+               wxWindowDC dc(this); 
+               DrawDecorations( dc );
+       }
+       else
+       if ( !mScrollEventInProgress )
+       {
+               mScrollEventInProgress = TRUE;
+
+               GetActiveTab()->GetEventHandler()->ProcessEvent( event );
+       }
+       else
+       {
+               // event bounced back to us, from here we
+               // know that it has traveled the loop - thus it's processed!
+
+               mScrollEventInProgress = FALSE; 
+       }
+}