|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "tabwindow.h"
#include "ChoreoWidgetDrawHelper.h"
#include "hlfaceposer.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : *parent -
// x -
// y -
// w -
// h -
// id -
// style -
//-----------------------------------------------------------------------------
CTabWindow::CTabWindow( mxWindow *parent, int x, int y, int w, int h, int id /*= 0*/, int style /*=0*/ ) : mxWindow( parent, x, y, w, h, "", style ) { setId( id );
m_nSelected = -1;
m_nRowHeight = 20; m_nRowsRequired = 1;
m_nTabWidth = 80; m_nPixelDelta = 3; m_bInverted = false; m_bRightJustify = false; SetColor( COLOR_BG, GetSysColor( COLOR_BTNFACE ) ); SetColor( COLOR_FG, GetSysColor( COLOR_INACTIVECAPTION ) ); SetColor( COLOR_FG_SELECTED, GetSysColor( COLOR_ACTIVECAPTION ) ); SetColor( COLOR_HILITE, GetSysColor( COLOR_3DSHADOW ) ); SetColor( COLOR_HILITE_SELECTED, GetSysColor( COLOR_3DHILIGHT ) ); SetColor( COLOR_TEXT, GetSysColor( COLOR_CAPTIONTEXT ) ); SetColor( COLOR_TEXT_SELECTED, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
FacePoser_AddWindowStyle( this, WS_CLIPCHILDREN | WS_CLIPSIBLINGS ); }
//-----------------------------------------------------------------------------
// Purpose:
// Output : CTabWindow::~CTabWindow
//-----------------------------------------------------------------------------
CTabWindow::~CTabWindow ( void ) { removeAll(); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : index -
// clr -
//-----------------------------------------------------------------------------
void CTabWindow::SetColor( int index, COLORREF clr ) { if ( index < 0 || index >= NUM_COLORS ) return;
m_Colors[ index ] = clr; }
void CTabWindow::SetInverted( bool invert ) { m_bInverted = invert; RecomputeLayout( w2() ); }
void CTabWindow::SetRightJustify( bool rightjustify ) { m_bRightJustify = true; RecomputeLayout( w2() ); }
//-----------------------------------------------------------------------------
// Purpose: Tabs are sized to string content
// Input : rcClient -
// tabRect -
// tabNum -
//-----------------------------------------------------------------------------
void CTabWindow::GetTabRect( const RECT& rcClient, RECT& tabRect, int tabNum ) { tabRect = m_Items[ tabNum ].rect; }
//-----------------------------------------------------------------------------
// Purpose:
// Input : drawHelper -
// rcClient -
// tabnum -
// selected -
//-----------------------------------------------------------------------------
void CTabWindow::DrawTab( CChoreoWidgetDrawHelper& drawHelper, RECT& rcClient, int tabnum, bool selected ) { RECT rcTab;
if ( tabnum < 0 || tabnum >= m_Items.Size() ) return;
GetTabRect( rcClient, rcTab, tabnum );
COLORREF fgcolor = m_Colors[ selected ? COLOR_FG_SELECTED : COLOR_FG ]; COLORREF hilightcolor = m_Colors[ selected ? COLOR_HILITE_SELECTED : COLOR_HILITE ]; COLORREF text = m_Colors[ selected ? COLOR_TEXT_SELECTED : COLOR_TEXT ];
// Create a trapezoid/paralleogram
POINT region[4]; int cPoints = 4;
OffsetRect( &rcTab, 0, m_bInverted ? 1 : -1 );
if ( m_bInverted ) { region[ 0 ].x = rcTab.left - m_nPixelDelta; region[ 0 ].y = rcTab.top;
region[ 1 ].x = rcTab.right + m_nPixelDelta; region[ 1 ].y = rcTab.top;
region[ 2 ].x = rcTab.right - m_nPixelDelta; region[ 2 ].y = rcTab.bottom;
region[ 3 ].x = rcTab.left + m_nPixelDelta; region[ 3 ].y = rcTab.bottom; } else { region[ 0 ].x = rcTab.left + m_nPixelDelta; region[ 0 ].y = rcTab.top;
region[ 1 ].x = rcTab.right - m_nPixelDelta; region[ 1 ].y = rcTab.top;
region[ 2 ].x = rcTab.right + m_nPixelDelta; region[ 2 ].y = rcTab.bottom;
region[ 3 ].x = rcTab.left - m_nPixelDelta; region[ 3 ].y = rcTab.bottom; }
HDC dc = drawHelper.GrabDC();
HRGN rgn = CreatePolygonRgn( region, cPoints, ALTERNATE );
int oldPF = SetPolyFillMode( dc, ALTERNATE ); HBRUSH brBg = CreateSolidBrush( fgcolor ); HBRUSH brBorder = CreateSolidBrush( hilightcolor ); //HBRUSH brInset = CreateSolidBrush( fgcolor );
FillRgn( dc, rgn, brBg ); FrameRgn( dc, rgn, brBorder, 1, 1 );
SetPolyFillMode( dc, oldPF );
DeleteObject( rgn );
DeleteObject( brBg ); DeleteObject( brBorder ); //DeleteObject( brInset );
// Position label
InflateRect( &rcTab, -5, 0 ); OffsetRect( &rcTab, 2, 0 );
// Draw label
drawHelper.DrawColoredText( "Arial", 9, FW_NORMAL, text, rcTab, "%s%s", getPrefix( tabnum ), getLabel( tabnum ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTabWindow::redraw( void ) { CChoreoWidgetDrawHelper drawHelper( this, m_Colors[ COLOR_BG ] );
int liney = m_bInverted ? 1 : h2() - 2;
drawHelper.DrawColoredLine( m_Colors[ COLOR_HILITE ], PS_SOLID, 1, 0, liney, w(), liney ); RECT rc; drawHelper.GetClientRect( rc );
// Draw non-selected first
for ( int i = 0 ; i < m_Items.Size(); i++ ) { if ( i == m_nSelected ) continue;
DrawTab( drawHelper, rc, i ); }
// Draw selected last, so that it appears to pop to top of z order
if ( m_nSelected >= 0 && m_nSelected < m_Items.Size() ) { DrawTab( drawHelper, rc, m_nSelected, true ); } }
//-----------------------------------------------------------------------------
// Purpose:
// Input : mx -
// my -
// Output : int
//-----------------------------------------------------------------------------
int CTabWindow::GetItemUnderMouse( int mx, int my ) { RECT rcClient; GetClientRect( (HWND)getHandle(), &rcClient );
for ( int i = 0; i < m_Items.Size() ; i++ ) { RECT rcTab; GetTabRect( rcClient, rcTab, i );
if ( mx < rcTab.left || mx > rcTab.right || my < rcTab.top || my > rcTab.bottom ) { continue; } return i; }
return -1; }
//-----------------------------------------------------------------------------
// Purpose:
// Input : *event -
// Output : int CTabWindow::handleEvent
//-----------------------------------------------------------------------------
int CTabWindow::handleEvent (mxEvent *event) { int iret = 0;
switch ( event->event ) { case mxEvent::MouseDown: { int item = GetItemUnderMouse( (short)event->x, (short)event->y ); if ( item != -1 ) { m_nSelected = item; redraw();
// Send CBN_SELCHANGE WM_COMMAND message to parent
HWND parent = (HWND)( getParent() ? getParent()->getHandle() : NULL ); if ( parent ) { LPARAM lp; WPARAM wp;
wp = MAKEWPARAM( getId(), CBN_SELCHANGE ); lp = (long)getHandle();
PostMessage( parent, WM_COMMAND, wp, lp ); } iret = 1; }
if ( event->buttons & mxEvent::MouseRightButton ) { ShowRightClickMenu( (short)event->x, (short)event->y ); iret = 1; } } break; case mxEvent::Size: { RecomputeLayout( w2() ); } break; } return iret; }
//-----------------------------------------------------------------------------
// Purpose: Add string to table
// Input : *item -
//-----------------------------------------------------------------------------
void CTabWindow::add( const char *item ) { m_Items.AddToTail(); CETItem *p = &m_Items[ m_Items.Size() - 1 ]; Assert( p );
Q_memset( &p->rect, 0, sizeof( p->rect) );
strcpy( p->m_szString, item ); p->m_szPrefix[ 0 ] = 0; m_nSelected = min( m_nSelected, m_Items.Size() - 1 ); m_nSelected = max( m_nSelected, 0 );
RecomputeLayout( w2() );
redraw(); }
void CTabWindow::setPrefix( int item, char const *prefix ) { if ( item < 0 || item >= m_Items.Size() ) return;
Q_strncpy( m_Items[ item ].m_szPrefix, prefix, sizeof( m_Items[ item ].m_szPrefix ) ); // RecomputeLayout( w2() );
}
//-----------------------------------------------------------------------------
// Purpose: Change selected item
// Input : index -
//-----------------------------------------------------------------------------
void CTabWindow::select( int index ) { if ( index < 0 || index >= m_Items.Size() ) return;
m_nSelected = index; redraw(); }
//-----------------------------------------------------------------------------
// Purpose: Remove a string
// Input : index -
//-----------------------------------------------------------------------------
void CTabWindow::remove( int index ) { if ( index < 0 || index >= m_Items.Size() ) return; m_Items.Remove( index );
m_nSelected = min( m_nSelected, m_Items.Size() - 1 ); m_nSelected = max( m_nSelected, 0 );
RecomputeLayout( w2() );
redraw(); }
//-----------------------------------------------------------------------------
// Purpose: Clear out everything
//-----------------------------------------------------------------------------
void CTabWindow::removeAll() { m_nSelected = -1; m_Items.RemoveAll();
RecomputeLayout( w2() );
redraw(); }
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CTabWindow::getItemCount () const { return m_Items.Size(); }
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CTabWindow::getSelectedIndex () const { // Convert based on override index
return m_nSelected; }
char const *CTabWindow::getLabel( int item ) { if ( item < 0 || item >= m_Items.Count() ) return "";
return m_Items[ item ].m_szString; }
char const *CTabWindow::getPrefix( int item ) { if ( item < 0 || item >= m_Items.Count() ) return "";
return m_Items[ item ].m_szPrefix; }
void CTabWindow::SetRowHeight( int rowheight ) { m_nRowHeight = rowheight; RecomputeLayout( w2() ); redraw(); }
int CTabWindow::GetBestHeight( int width ) { return RecomputeLayout( width, false ) * m_nRowHeight; }
int CTabWindow::RecomputeLayout( int windowWidth, bool dolayout /*=true*/ ) { // Draw non-selected first
int curedge = m_nPixelDelta + 1; int curtop = 0;
if ( m_bRightJustify ) { curedge = windowWidth - ( m_nPixelDelta + 1 ) - 5; }
int startedge = curedge;
int currentrow = 0;
for ( int i = 0 ; i < m_Items.Size(); i++ ) { CETItem *p = &m_Items[ i ];
RECT rc;
int textwidth = CChoreoWidgetDrawHelper::CalcTextWidth( "Arial", 9, FW_NORMAL, "%s%s", p->m_szPrefix, p->m_szString ) + 15;
if ( !m_bRightJustify ) { // Starting column
if ( curedge + textwidth > windowWidth ) { curedge = startedge; curtop += m_nRowHeight; currentrow++; }
rc.left = curedge; rc.right = curedge + textwidth; rc.top = curtop + 2; rc.bottom = curtop + m_nRowHeight;
curedge += textwidth;
p->rect = rc; } else { // Starting column
if ( curedge - textwidth < 0 ) { curedge = startedge; curtop += m_nRowHeight; currentrow++; }
rc.left = curedge - textwidth; rc.right = curedge; rc.top = curtop; rc.bottom = curtop + m_nRowHeight - 2;
curedge -= textwidth; }
if ( dolayout ) { p->rect = rc; } }
if ( dolayout ) { m_nRowsRequired = currentrow + 1; }
return currentrow + 1; }
|