// BorderLayout.cpp : Implementation of cBorderLayout #include "stdafx.h" #include "DecalControls.h" #include "BorderLayout.h" ///////////////////////////////////////////////////////////////////////////// // cBorderLayout void cBorderLayout::onSchemaLoad( IView *pView, MSXML::IXMLDOMElementPtr &pElement ) { static _bstr_t _strEdge = _T( "border" ), _strCenter = _T( "center" ); static _variant_t _strLeft = _T( "left" ), _strRight = _T( "right" ), _strTop = _T( "top" ), _strBottom = _T( "bottom" ); // Walk through the list of children - select all elements MSXML::IXMLDOMElementPtr pChild; for( MSXML::IXMLDOMNodeListPtr pChildren = pElement->selectNodes( _T( "*" ) ); ( pChild = pChildren->nextNode() ).GetInterfacePtr() != NULL; ) { if( pChild->tagName == _strEdge ) { // Attempt to extract the edge indicator and the size indicator _variant_t vEdge = pChild->getAttribute( _T( "edge" ) ), vSize = pChild->getAttribute( _T( "size" ) ); _ASSERTE( vEdge.vt != VT_NULL ); _ASSERTE( vSize.vt != VT_NULL ); // Got values, check if they're good eBorderEdge eEdge; if( _strLeft == vEdge ) eEdge = eEdgeLeft; else if( vEdge == _strRight ) eEdge = eEdgeRight; else if( vEdge == _strTop ) eEdge = eEdgeTop; else if( vEdge == _strBottom ) eEdge = eEdgeBottom; #ifdef _DEBUG else // Invalid value here _ASSERTE( FALSE ); #endif // Convert the size try { long nSize = vSize; // Cannot have a 0 or negative edge size _ASSERTE( nSize > 0 ); cEdgePlacement ep = { eEdge, nSize, loadChildControl( pView, pChild->selectSingleNode( _T( "control" ) ) ) }; m_edges.push_back( ep ); } catch( ... ) { // The size could no be converted to a long value _ASSERTE( FALSE ); } } else if( pChild->tagName == _strCenter ) { // Make sure there isn't a center already created _ASSERTE( m_nCenterID == -1 ); m_nCenterID = loadChildControl( pView, pChild->selectSingleNode( _T( "control" ) ) ); } #ifdef _DEBUG else // This is an invalid child element type _ASSERTE( FALSE ); #endif } } void cBorderLayout::onChildDestroy( long nID ) { // Check if this is the center if( nID == m_nCenterID ) { m_nCenterID = -1; m_pSite->Reformat(); return; } // Check if it on an edge for( cEdgePlacementList::iterator i = m_edges.begin(); i != m_edges.end(); ++ i ) { if( i->m_nID == nID ) { m_edges.erase( i ); m_pSite->Reformat(); break; } } } STDMETHODIMP cBorderLayout::CreateEdge(eBorderEdge eEdge, long nSize, ILayer *pSink) { _ASSERTE( nSize > 0 ); _ASSERTE( pSink != NULL ); LayerParams lp = { dispenseID(), { 0, 0, 0, 0 }, eRenderClipped }; m_pSite->CreateChild( &lp, pSink ); cEdgePlacement ep = { eEdge, nSize, lp.ID }; m_edges.push_back( ep ); m_pSite->Reformat(); return S_OK; } STDMETHODIMP cBorderLayout::CreateCenter(ILayer *pSink) { _ASSERTE( m_nCenterID == -1 ); LayerParams lp = { dispenseID(), { 0, 0, 0, 0 }, eRenderClipped }; m_pSite->CreateChild( &lp, pSink ); m_nCenterID = lp.ID; m_pSite->Reformat(); return S_OK; } STDMETHODIMP cBorderLayout::Reformat() { // Walk through the list of edges in order and // set their positions RECT rcLayer; m_pSite->get_Position( &rcLayer ); RECT rcClient = { 0, 0, rcLayer.right - rcLayer.left, rcLayer.bottom - rcLayer.top }; for( cEdgePlacementList::iterator i = m_edges.begin(); i != m_edges.end(); ++ i ) { RECT rcPosition = rcClient; switch( i->m_edge ) { case eEdgeLeft: rcPosition.right = rcPosition.left + i->m_nSize; rcClient.left += i->m_nSize; break; case eEdgeTop: rcPosition.bottom = rcPosition.top + i->m_nSize; rcClient.top += i->m_nSize; break; case eEdgeRight: rcPosition.left = rcPosition.right - i->m_nSize; rcClient.right -= i->m_nSize; break; case eEdgeBottom: rcPosition.top = rcPosition.bottom - i->m_nSize; rcClient.bottom -= i->m_nSize; break; default: // Invalid edge value _ASSERTE( FALSE ); } // Sanity checks to make sure we haven't overrun our area //_ASSERTE( rcClient.bottom > rcClient.top ); _ASSERTE( rcClient.right > rcClient.left ); _ASSERTE( rcPosition.bottom > rcPosition.top ); _ASSERTE( rcPosition.right > rcPosition.left ); CComPtr< ILayerSite > pChild; HRESULT hRes = m_pSite->get_Child( i->m_nID, ePositionByID, &pChild ); _ASSERTE( SUCCEEDED( hRes ) ); pChild->put_Position( &rcPosition ); } if( m_nCenterID != -1 ) { CComPtr< ILayerSite > pChild; HRESULT hRes = m_pSite->get_Child( m_nCenterID, ePositionByID, &pChild ); _ASSERTE( SUCCEEDED( hRes ) ); pChild->put_Position( &rcClient ); } return S_OK; }