Created
April 26, 2012 13:16
-
-
Save gabonator/2499479 to your computer and use it in GitHub Desktop.
Layout tables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pch.h> | |
#include "Tables.h" | |
#define foreach(decl) for ( decl = m_pListFirst; pElement; pElement = pElement->m_pNext ) | |
/*virtual*/ | |
void CTableWnd::GetClientRect( LPRECT prcRect ) | |
{ | |
_ASSERT(prcRect); | |
CRect *pRect = (CRect*) prcRect; | |
pRect->left = 0; | |
pRect->top = 0; | |
pRect->right = m_szSize.cx; | |
pRect->bottom = m_szSize.cy; | |
} | |
/*virtual*/ | |
BOOL32 CTableWnd::SetWindowPos(const CWnd* pWndInsertAfter, INT x, INT y, | |
INT cx, INT cy, UINT nFlags) | |
{ | |
m_rcRect.left = x; | |
m_rcRect.top = y; | |
m_rcRect.right = x + cx; | |
m_rcRect.bottom = y + cy; | |
return TRUE; | |
} | |
CTable::CTable(CTable *pTable) | |
{ | |
m_nFlags = pTable->m_nFlags; | |
m_rcBorder = pTable->m_rcBorder; | |
m_pListFirst = pTable->m_pListFirst; | |
m_pListLast = pTable->m_pListLast; | |
pTable->m_pListFirst = NULL; | |
pTable->m_pListLast = NULL; | |
} | |
CTable::CTable(INT nFlags) | |
{ | |
m_nFlags = nFlags; | |
m_pListFirst = NULL; | |
m_pListLast = NULL; | |
} | |
CTable::~CTable() | |
{ | |
Reset(); | |
} | |
CTable& CTable::operator << (CTD el) | |
{ | |
if ( el.IsValid() ) | |
{ | |
CTD *pCtd = new CTD( el ); | |
pCtd->m_pNext = NULL; | |
if ( m_pListFirst == NULL ) | |
{ | |
m_pListFirst = pCtd; | |
m_pListLast = pCtd; | |
} else | |
{ | |
m_pListLast->m_pNext = pCtd; | |
m_pListLast = pCtd; | |
} | |
} | |
return *this; | |
} | |
CTable& CTable::operator << (const CTBorder& border) | |
{ | |
m_rcBorder = border; | |
return *this; | |
} | |
BOOL32 CTable::IsEmpty() | |
{ | |
return m_pListFirst == NULL; | |
} | |
CSize CTable::GetSize() | |
{ | |
CSize szTotal; | |
foreach(CTD* pElement) | |
{ | |
if ( pElement->IsTab() ) | |
pElement->m_szSize = CSize( 0, 0 ); | |
else | |
pElement->m_szSize = pElement->GetSize(); | |
} | |
switch ( m_nFlags & TFlags ) | |
{ | |
case TOverlay: | |
if ( m_pListFirst > 0 ) | |
szTotal = m_pListFirst->m_szSize; | |
break; | |
case THorizontal: | |
foreach(CTD* pElement) | |
{ | |
CSize& szElement = pElement->m_szSize; | |
szTotal.cx += szElement.cx; | |
szTotal.cy = max( szTotal.cy, szElement.cy ); | |
} | |
break; | |
case TVertical: | |
foreach(CTD* pElement) | |
{ | |
CSize& szElement = pElement->m_szSize; | |
szTotal.cx = max( szTotal.cx, szElement.cx ); | |
szTotal.cy += szElement.cy; | |
} | |
break; | |
} | |
szTotal.cx += m_rcBorder.left; | |
szTotal.cx += m_rcBorder.right; | |
szTotal.cy += m_rcBorder.top; | |
szTotal.cy += m_rcBorder.bottom; | |
return szTotal; | |
} | |
void CTable::Place( CRect rcRect ) | |
{ | |
rcRect.DeflateRect( &m_rcBorder ); | |
INT nLeft = rcRect.left; | |
INT nTop = rcRect.top; | |
CSize szTotal; | |
INT nTabs = 0; | |
foreach(CTD* pElement) | |
{ | |
if ( pElement->IsTab() ) | |
nTabs++; | |
else | |
szTotal += pElement->m_szSize; | |
} | |
switch ( m_nFlags & TFlags ) | |
{ | |
case TOverlay: | |
foreach(CTD* pElement) | |
pElement->Place( rcRect ); | |
break; | |
case THorizontal: | |
foreach(CTD* pElement) | |
{ | |
CSize& szElement = pElement->m_szSize; | |
if ( pElement->m_pTWnd.get() && pElement->m_pTWnd->Flags() & CTableWnd::TTab ) | |
szElement.cx = (rcRect.Width() - szTotal.cx) / nTabs; | |
CRect rcWorking = rcRect; | |
rcWorking.left = nLeft; | |
nLeft += szElement.cx; | |
rcWorking.right = nLeft; | |
pElement->Place( rcWorking ); | |
} | |
break; | |
case TVertical: | |
foreach(CTD* pElement) | |
{ | |
CSize& szElement = pElement->m_szSize; | |
if ( pElement->m_pTWnd.get() && pElement->m_pTWnd->Flags() & CTableWnd::TTab ) | |
szElement.cy = (rcRect.Height() - szTotal.cy) / nTabs; | |
CRect rcWorking = rcRect; | |
rcWorking.top = nTop; | |
nTop += szElement.cy; | |
rcWorking.bottom = nTop; | |
pElement->Place( rcWorking ); | |
} | |
break; | |
default: | |
_ASSERT( 0 ); | |
} | |
} | |
CRect CTable::operator ()( CPoint cpBase ) | |
{ | |
CRect rcPlace; | |
CSize szTotal = GetSize(); | |
rcPlace.SetRect( cpBase.x, cpBase.y, cpBase.x + szTotal.cx, cpBase.y + szTotal.cy ); | |
Place( rcPlace ); | |
return CRect( cpBase, szTotal ); | |
} | |
void CTable::Reset() | |
{ | |
while (m_pListFirst) | |
{ | |
CTD *pNext = m_pListFirst->m_pNext; | |
delete m_pListFirst; | |
m_pListFirst = pNext; | |
} | |
m_pListLast = NULL; | |
} | |
CTD::CTD( CTable& Table ) : m_pTWndStatic(NULL), m_nAlign( Table.m_nFlags & CTable::TDCFlags ) | |
{ | |
m_pTable.Reset( new CTable(&Table) ); | |
} | |
BOOL32 CTD::IsValid() | |
{ | |
return ( m_pWnd.get() || m_pTWnd.get() || m_pTable.get() || m_pTWndStatic ); | |
} | |
BOOL32 CTD::IsTab() | |
{ | |
if ( m_pTWnd.get() && m_pTWnd->Flags() & CTableWnd::TTab ) | |
return TRUE; | |
if ( m_pTWndStatic && m_pTWndStatic->Flags() & CTableWnd::TTab ) | |
return TRUE; | |
return FALSE; | |
} | |
CSize CTD::GetSize() | |
{ | |
if ( m_pWnd.get() ) | |
{ | |
CRect rcClient; | |
m_pWnd->GetClientRect( &rcClient ); | |
return CSize( rcClient.Width(), rcClient.Height() ); | |
} | |
if ( m_pTWnd.get() ) | |
{ | |
CRect rcClient; | |
m_pTWnd->GetClientRect( &rcClient ); | |
return CSize( rcClient.Width(), rcClient.Height() ); | |
} | |
if ( m_pTWndStatic ) | |
{ | |
CRect rcClient; | |
m_pTWndStatic->GetClientRect( &rcClient ); | |
return CSize( rcClient.Width(), rcClient.Height() ); | |
} | |
if ( m_pTable.get() ) | |
{ | |
return m_pTable->GetSize(); | |
} | |
_ASSERT(0); | |
return CSize(0, 0); | |
} | |
void CTD::Place( CRect rcRect ) | |
{ | |
if ( m_pWnd.get() ) | |
{ | |
if ( m_nAlign ) | |
rcRect = CQuickWnd::Align( rcRect, GetSize(), m_nAlign ); | |
m_pWnd->SetWindowPos( NULL, rcRect.left, rcRect.top, rcRect.Width(), rcRect.Height(), 0 ); | |
return; | |
} | |
if ( m_pTWnd.get() ) | |
{ | |
if ( m_nAlign ) | |
rcRect = CQuickWnd::Align( rcRect, GetSize(), m_nAlign ); | |
_ASSERT( m_pTWnd->Flags() < 0xffff ); | |
m_pTWnd->SetWindowPos( NULL, rcRect.left, rcRect.top, rcRect.Width(), rcRect.Height(), 0 ); | |
return; | |
} | |
if ( m_pTWndStatic ) | |
{ | |
if ( m_nAlign ) | |
rcRect = CQuickWnd::Align( rcRect, GetSize(), m_nAlign ); | |
_ASSERT( m_pTWndStatic->Flags() < 0xffff ); | |
m_pTWndStatic->SetWindowPos( NULL, rcRect.left, rcRect.top, rcRect.Width(), rcRect.Height(), 0 ); | |
return; | |
} | |
if ( m_pTable.get() ) | |
{ | |
if ( m_nAlign ) | |
rcRect = CQuickWnd::Align( rcRect, GetSize(), m_nAlign ); | |
m_pTable->Place( rcRect ); | |
return; | |
} | |
_ASSERT(0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _SKIP_PRAGMA_ONCE_ | |
#pragma once | |
#endif | |
#ifndef __TABLES_H__ | |
#define __TABLES_H__ | |
class CTable; | |
class CTBorder : public CRect | |
{ | |
public: | |
CTBorder(INT l, INT t, INT r, INT b) : CRect(l, t, r, b) | |
{ | |
} | |
CTBorder(CRect& rc) : CRect( rc ) | |
{ | |
} | |
}; | |
// Musi byt vzdy staticka instancia ! | |
class CTableWnd | |
{ | |
friend class CTD; | |
public: | |
enum ETWType { | |
TNormal = 1, | |
TTab = 2, | |
TSpacer = 3 | |
}; | |
protected: | |
CSize m_szSize; | |
CRect m_rcRect; | |
DWORD m_dwFlags; | |
public: | |
CTableWnd() : m_dwFlags( TNormal ) | |
{ | |
} | |
CTableWnd( const CSize& szSize ) : m_szSize( szSize ), m_dwFlags( TNormal ) | |
{ | |
} | |
CTableWnd( INT cx, INT cy ) : m_szSize( cx, cy ), m_dwFlags( TNormal ) | |
{ | |
} | |
operator const CSize&() const | |
{ | |
return m_szSize; | |
} | |
operator const CRect&() const | |
{ | |
return m_rcRect; | |
} | |
operator const LPCRECT() const | |
{ | |
return &m_rcRect; | |
} | |
const DWORD& Flags() | |
{ | |
return m_dwFlags; | |
} | |
void GetClientRect( LPRECT prcRect ); | |
BOOL32 SetWindowPos(const CWnd* pWndInsertAfter, INT x, INT y, | |
INT cx, INT cy, UINT nFlags); | |
}; | |
class CTTab | |
{ | |
public: | |
CTTab() | |
{ | |
} | |
}; | |
class CTSpacer | |
{ | |
public: | |
CSize m_szSize; | |
public: | |
CTSpacer() : m_szSize(0, 0) | |
{ | |
} | |
CTSpacer( INT nSize ) : m_szSize( nSize, nSize ) | |
{ | |
} | |
CTSpacer( INT cx, INT cy ) : m_szSize( cx, cy ) | |
{ | |
} | |
CTSpacer( CWnd* pWnd ) | |
{ | |
if ( !pWnd ) | |
return; | |
CRect rcClient; | |
pWnd->GetClientRect( &rcClient ); | |
m_szSize = rcClient.Size(); | |
} | |
}; | |
class CTD { | |
friend class CTable; | |
public: | |
SharedPtr<CWnd> m_pWnd; | |
SharedPtr<CTableWnd> m_pTWnd; | |
SharedPtr<CTable> m_pTable; | |
CTableWnd *m_pTWndStatic; | |
INT m_nAlign; | |
CSize m_szSize; | |
CTD *m_pNext; | |
// stromove strukturovanie | |
CTD( CTable& Table ); | |
// zakladny konstruktor pre pouzitie z 3d oknami | |
template <class T> | |
CTD( CSharedPtr<T> pWnd ) : m_pWnd(pWnd), m_pTWndStatic(NULL), m_nAlign( 0 ) | |
{ | |
} | |
template <class T> | |
CTD( CSharedPtr<T> pWnd, INT nAlign ) : m_pWnd( pWnd), m_pTWndStatic(NULL), m_nAlign( nAlign ) | |
{ | |
} | |
// staticke (pouzivaju napr poie, friends), nie prave elegantne riesenie | |
CTD( CTableWnd& Wnd ) : m_nAlign( 0 ) | |
{ | |
m_pTWndStatic = (CTableWnd*)(&Wnd); | |
} | |
CTD( CTableWnd& Wnd, INT nAlign ) : m_nAlign( nAlign ) | |
{ | |
m_pTWndStatic = (CTableWnd*)(&Wnd); | |
} | |
// tie ktorych finalny placement nas nezaujima - spacer a tab | |
CTD( const CTTab& Wnd ) : m_pTWndStatic(NULL), m_nAlign( 0 ) | |
{ | |
m_pTWnd.New(); | |
m_pTWnd->m_dwFlags = CTableWnd::TTab; | |
} | |
CTD( const CTSpacer& Wnd ) : m_pTWndStatic(NULL), m_nAlign( 0 ) | |
{ | |
m_pTWnd.New(); | |
*(m_pTWnd.get()) = Wnd.m_szSize; | |
} | |
CSize GetSize(); | |
void Place( CRect rcRect ); | |
BOOL32 IsValid(); | |
private: | |
BOOL32 IsTab(); | |
}; | |
class CTable | |
{ | |
public: | |
enum { | |
TDCFlags = CDC::DtLast - 1, | |
TFlags = ~TDCFlags, | |
TVertical = CDC::DtLast << 1, | |
THorizontal = CDC::DtLast << 2, | |
TOverlay = CDC::DtLast << 3 | |
}; | |
public: | |
CTD *m_pListFirst; | |
CTD *m_pListLast; | |
CRect m_rcBorder; | |
INT m_nFlags; | |
public: | |
CTable(CTable *pTable); | |
CTable(INT nFlags = THorizontal); | |
~CTable(); | |
CTable& operator << (CTD el); | |
CTable& operator << (const CTBorder& border); | |
CSize GetSize(); | |
void Place( CRect rcRect ); | |
CRect operator ()( CPoint cpBase = 0 ); | |
void Reset(); | |
BOOL32 IsEmpty(); | |
}; | |
class CTR : public CTable | |
{ | |
public: | |
CTR( INT nAlign = 0 ) : CTable(THorizontal | nAlign) {} | |
}; | |
class CTC : public CTable | |
{ | |
public: | |
CTC( INT nAlign = 0 ) : CTable(TVertical | nAlign) {} | |
}; | |
class CTO : public CTable | |
{ | |
public: | |
CTO( INT nAlign = 0 ) : CTable(TOverlay | nAlign) {} | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment