Skip to content

Instantly share code, notes, and snippets.

@gabonator
Created April 26, 2012 13:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabonator/2499479 to your computer and use it in GitHub Desktop.
Save gabonator/2499479 to your computer and use it in GitHub Desktop.
Layout tables
#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);
}
#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