///////////////////////////////////////////////////////////////////////////// // Name: No names yet. // Purpose: Contrib. demo // Author: Aleksandras Gluchovas // Modified by: 19990908 : mj10777@gmx.net // - rename to tabpgwin // - restruction of Variable declaration // - to prevent Warnings under MingGW32 // Modified by: 19990909 : mj10777@gmx.net // - mNoVertScroll TRUE = no / FALSE = Original Code // the Original Code Paints a Vertical Scroll in wxPaggedWindow // which is not needed in this Version. Use TRUE for this. // 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 #include #include "wx/string.h" #include "wx/utils.h" // import wxMin/wxMax macros and wxFileExist(..) #include "tabpgwin.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(); unsigned int 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; } 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() ); 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(); 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; mNoVertScroll = TRUE; // Horizontale Scroll abschalten } //--------------------------------------------------------------------------- wxPaggedWindow::~wxPaggedWindow() { // nothing (base class handles destruction) } //--------------------------------------------------------------------------- wxFont wxPaggedWindow::GetLabelingFont() { wxFont font; #ifdef __WINDOWS__ font.SetFaceName("Comic Sans MS"); #else font.SetFamily( wxSWISS ); #endif font.SetStyle(40); font.SetWeight(40); font.SetPointSize( 8 ); 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 ); if (!mNoVertScroll) // Vertical Scroll (Original) 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; if (!mNoVertScroll) // Vertical Scroll (Original) xSize = width - mHorizGap*2 - BORDER_SZ*2 - thumbLen; else xSize = width - mHorizGap*2 - BORDER_SZ*2; 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; if (!mNoVertScroll) // Vertical Scroll (Original) mpHorizScroll->SetSize( curX, curY,width - curX - mHorizGap - BORDER_SZ - thumbLen, thumbLen ); else mpHorizScroll->SetSize( curX, curY,width - curX - mHorizGap - BORDER_SZ-4, thumbLen ); // setup view's VERTICAL scroll bar if (!mNoVertScroll) // Vertical Scroll (Original) { 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 ) { wxScrollBar* pSender = (wxScrollBar*)event.GetEventObject(); // wxMessageBox("wxPaggedWindow::OnScroll","-I->"); if ( pSender == mpTabScroll ) { 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; } } //---------------------------------------------------------------------------