// Notebook.cpp : Implementation of cNotebook #include "stdafx.h" #include "DecalControls.h" #include "Notebook.h" ///////////////////////////////////////////////////////////////////////////// // cNotebook cNotebook::cNotebook(): m_nNextPageID( 1001 ), m_nActiveTab( -1 ), m_nCaptureTab( -1 ), m_bHitCapture( false ) { } long cNotebook::hitTest( MouseState *pMS ) { if( pMS->over != this ) // Not hitting us, therefore not hitting a tab return -1; // Yes for y boundaries if( pMS->client.y < 0 || pMS->client.y >= 16 ) return -1; // Walk through the list of tabs for( cPageList::iterator i = m_pages.begin(); i != m_pages.end(); ++ i ) { if( pMS->client.x >= i->m_nLeft && pMS->client.x < i->m_nRight ) // Hit a tab! return ( i - m_pages.begin() ); } // No tabs hit return -1; } void cNotebook::positionActiveTab() { if( m_nActiveTab == -1 ) return; RECT rcClient; m_pSite->get_Position( &rcClient ); CComPtr< ILayerSite > pChild; m_pSite->get_Child( m_pages[ m_nActiveTab ].m_nPageID, ePositionByID, &pChild ); RECT rcChild = { 0, 16, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top }; pChild->put_Position( &rcChild ); } STDMETHODIMP cNotebook::AddPage(BSTR strText, IControl *pClient) { cPage p; p.m_strName = strText; p.m_nPageID = m_nNextPageID ++; CComPtr< ILayer > pClientLayer; pClient->QueryInterface( &pClientLayer ); LayerParams lp = { p.m_nPageID, { 0, 0, 0, 0 }, eRenderClipped }; m_pSite->CreateChild( &lp, pClientLayer ); m_pages.push_back( p ); if( m_nActiveTab == -1 ) // Activate the page if it's the first one m_nActiveTab = 0; m_pSite->Reformat(); return S_OK; } void cNotebook::onCreate() { // Load the images CComPtr< IPluginSite > pPlugin; m_pSite->get_PluginSite( &pPlugin ); pPlugin->LoadBitmapFile( _bstr_t( _T( "Tab-Active.bmp" ) ), &m_pActive ); pPlugin->LoadBitmapFile( _bstr_t( _T( "Tab-Inactive.bmp" ) ), &m_pInactive ); BSTR bstrFontName; pPlugin->get_FontName(&bstrFontName); pPlugin->CreateFont( bstrFontName /*_bstr_t( _T( "Times New Roman" ) )*/, 14, 0, &m_pFont ); } void cNotebook::onDestroy() { m_pActive.Release(); m_pInactive.Release(); } #define TEXT_LR_MARGIN 5 STDMETHODIMP cNotebook::Reformat() { // Walk through the tabs and position the graphics long nTabPos = 0; for( cPageList::iterator i = m_pages.begin(); i != m_pages.end(); ++ i ) { // Calculate the text length SIZE sz; m_pFont->MeasureText( i->m_strName, &sz ); long nWidth = sz.cx + TEXT_LR_MARGIN * 2; i->m_nLeft = nTabPos; i->m_nRight = nTabPos + nWidth; nTabPos += nWidth; } if( m_nActiveTab != -1 ) positionActiveTab(); _ASSERTMEM( _CrtCheckMemory( ) ); return S_OK; } STDMETHODIMP cNotebook::Render( ICanvas *pCanvas ) { for( cPageList::iterator i = m_pages.begin(); i != m_pages.end(); ++ i ) { POINT ptTab = { i->m_nLeft, 0 }; long nWidth = i->m_nRight - i->m_nLeft; long nIndex = i - m_pages.begin(); bool bActive = ( ( nIndex == m_nActiveTab ) || ( m_nCaptureTab != -1 && m_bHitCapture && nIndex == m_nCaptureTab ) ); if( bActive ) m_pActive->StretchBlt( pCanvas, &ptTab, nWidth, 7, 90 ); else m_pInactive->StretchBlt( pCanvas, &ptTab, nWidth, 7, 90 ); // Draw the text POINT ptText = { i->m_nLeft + TEXT_LR_MARGIN, 2 }; m_pFont->DrawText( &ptText, i->m_strName, ( bActive ) ? RGB( 0, 0, 0 ) : RGB( 192, 192, 192 ), pCanvas ); } _ASSERTMEM( _CrtCheckMemory( ) ); return S_OK; } STDMETHODIMP cNotebook::MouseDown( MouseState *pMS ) { m_nCaptureTab = hitTest( pMS ); if( m_nCaptureTab != -1 ) { m_bHitCapture = true; m_pSite->Invalidate(); } return S_OK; } STDMETHODIMP cNotebook::MouseUp( MouseState *pMS ) { _ASSERTMEM( _CrtCheckMemory( ) ); if( m_nCaptureTab == -1 ) return S_OK; if( hitTest( pMS ) == m_nCaptureTab ) put_ActiveTab( m_nCaptureTab ); _ASSERTMEM( _CrtCheckMemory( ) ); m_nCaptureTab = -1; return S_OK; } STDMETHODIMP cNotebook::MouseMove( MouseState *pMS ) { if( m_nCaptureTab == -1 ) // We are hitting in progress return S_OK; // Check for a hit bool bHitCapture = ( hitTest( pMS ) == m_nCaptureTab ); if( bHitCapture != m_bHitCapture ) { m_bHitCapture = bHitCapture; m_pSite->Invalidate(); } return S_OK; } STDMETHODIMP cNotebook::get_ActiveTab(long *pVal) { *pVal = m_nActiveTab; return S_OK; } STDMETHODIMP cNotebook::put_ActiveTab(long newVal) { if( m_nActiveTab != -1 ) { // Hide the current active view static RECT rcHide = { 0, 0, 0, 0 }; CComPtr< ILayerSite > pChild; m_pSite->get_Child( m_pages[ m_nActiveTab ].m_nPageID, ePositionByID, &pChild ); pChild->put_Position( &rcHide ); } m_nActiveTab = newVal; if( m_nActiveTab != -1 ) positionActiveTab(); long nID; m_pSite->get_ID( &nID ); Fire_Change( nID, m_nActiveTab ); m_pSite->Invalidate(); return S_OK; } STDMETHODIMP cNotebook::SchemaLoad(IView *pView, IUnknown *pSchema) { MSXML::IXMLDOMElementPtr pElement = pSchema; MSXML::IXMLDOMElementPtr pPage; for( MSXML::IXMLDOMNodeListPtr pPages = pElement->selectNodes( _T( "page" ) ); ( pPage = pPages->nextNode() ).GetInterfacePtr() != NULL; ) { // We have the page, get the text, then recurse and generate the control _variant_t vText = pPage->getAttribute( _T( "label" ) ); _ASSERTE( vText.vt == VT_BSTR ); cPage p; p.m_strName = vText.bstrVal; p.m_nPageID = m_nNextPageID ++; m_pages.push_back( p ); MSXML::IXMLDOMElementPtr pControl = pPage->selectSingleNode( _T( "control" ) ); _ASSERTE( pControl.GetInterfacePtr() != NULL ); long nAssigned; pView->LoadControl( m_pSite, p.m_nPageID, pControl, &nAssigned ); } if( m_nActiveTab == -1 && m_pages.size() > 0 ) // Activate the page if it's the first one m_nActiveTab = 0; return S_OK; } STDMETHODIMP cNotebook::get_PageText(long nIndex, BSTR *pVal) { _ASSERTE( pVal != NULL ); _ASSERTE( nIndex >= 0 ); _ASSERTE( nIndex < m_pages.size() ); *pVal = OLE2BSTR( m_pages[ nIndex ].m_strName ); return S_OK; } STDMETHODIMP cNotebook::put_PageText(long nIndex, BSTR newVal) { _ASSERTE( newVal != NULL ); _ASSERTE( nIndex >= 0 ); _ASSERTE( nIndex < m_pages.size() ); m_pages[ nIndex ].m_strName = newVal; m_pSite->Reformat(); return S_OK; }