etqw-sdk/source/game/guis/UIList.h

863 lines
26 KiB
C
Raw Permalink Normal View History

2008-05-29 00:00:00 +00:00
// Copyright (C) 2007 Id Software, Inc.
//
#ifndef __GAME_GUIS_USERINTERFACELIST_H__
#define __GAME_GUIS_USERINTERFACELIST_H__
#include "../../idlib/PropertiesImpl.h"
#include "UserInterfaceTypes.h"
#include "UIWindow.h"
extern const char sdUITemplateFunctionInstance_IdentifierList[];
extern const char sdUIListItem_Identifier[];
extern const char sdUIListColumn_Identifier[];
/*
============
sdUIList
============
*/
SD_UI_PUSH_CLASS_TAG( sdUIList )
SD_UI_CLASS_INFO_TAG(
/* ============ */
"The list window type can be used if you want display a list in the GUI. It is the most complex " \
"window type in the GUI system. Some of the features of the list type are column headers, drawing of text or materials " \
"in headers and items, saving additional data in items, column sorting, variable row height, filling from enumerators, mouse and key events " \
"on header columns and items."
/* ============ */
)
SD_UI_CLASS_EXAMPLE_TAG(
/* ============ */
" windowDef vPlayerList {\n" \
" \ttype list;\n" \
" \tproperties {\n" \
" \t\tfloat fontSize = 48;\n" \
" \t\t// Truncate player name to the item rectangle\n" \
" \t\tfloat flags = immediate( flags ) | WF_TRUNCATE_TEXT;\n" \
" \t\trect rect = 24, 50, 590, 350;\n" \
" \t\tcolor backColor = 0,0,0,0;\n" \
" \t}\n" \
" \tevents {\n" \
" \t\tonCreate {\n" \
" \t\t\tinsertColumn( gui.blankWStr, 0, 0 ); // Class icon column.\n" \
" \t\t\tinsertColumn( gui.blankWStr, 590, 1 ) // Player name column;\n" \
" \t\t}\n" \
" \t}\n" \
" \ttimeLine {\n" \
" \t\tonTime 250 {\n" \
" \t\t\t// Have the gamecode update the list of players in the vehicle every 250 milliseconds.\n" \
" \t\t\tfillFromEnumerator( \"vehiclePlayerList\" );\n" \
" \t\t\tresetTime( 0 );\n" \
" \t\t}\n" \
" \t}\n" \
" }\n"
/* ============ */
)
SD_UI_POP_CLASS_TAG
SD_UI_PROPERTY_TAG(
alias = "list";
"2. Drawing/1. Selected Items" = "Collapse";
"2. Drawing/2. Columns" = "Collapse";
)
class sdUIList :
public sdUIWindow {
public:
SD_UI_DECLARE_CLASS( sdUIList )
typedef enum listEvent_e {
LE_SELECT_ITEM = WE_NUM_EVENTS + 1,
LE_ITEM_ADDED,
LE_ITEM_REMOVED,
LE_DRAW_SELECTED_BACKGROUND,
LE_DRAW_ITEM_BACKGROUND,
LE_DRAW_ITEM,
LE_DRAW_COLUMN,
LE_ENTER_COLUMN,
LE_EXIT_COLUMN,
LE_CLICK_COLUMN,
LE_ENTER_ITEM,
LE_EXIT_ITEM,
LE_NUM_EVENTS,
} listEvent_t;
enum listFlag_e {
LF_AUTO_SCROLL_TO_SELECTION = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 0 >::VALUE,
LF_HOT_TRACK = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 1 >::VALUE,
LF_COLUMN_SORT = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 2 >::VALUE,
LF_SHOW_HEADINGS = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 3 >::VALUE,
LF_NO_NULL_SELECTION = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 4 >::VALUE, // clicking in an empty area won't deselect the current item
LF_VARIABLE_HEIGHT_ROWS = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 5 >::VALUE,
LF_NO_KEY_EVENTS = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 6 >::VALUE,
LF_TRUNCATE_COLUMNS = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 7 >::VALUE, // only truncate column text
LF_DIRECT_UPDATES = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 8 >::VALUE, // allow for directly updating item text without triggering sorting
};
enum listGetItemRect_e {
GIR_MIN = -1,
GIR_COLUMN,
GIR_FULLWIDTH,
GIR_MAX,
};
typedef sdUITemplateFunction< sdUIList > ListTemplateFunction;
sdUIList();
virtual ~sdUIList();
virtual const char* GetScopeClassName() const { return "sdUIList"; }
virtual void ApplyLayout();
virtual bool PostEvent( const sdSysEvent* event );
virtual void EnumerateEvents( const char* name, const idList<unsigned short>& flags, idList< sdUIEventInfo >& events, const idTokenCache& tokenCache );
virtual void EndLevelLoad();
virtual void CacheEvents();
int RemapIndex( int index ) const;
void SelectItem( int item );
void SetItemGranularity( int granularity );
void BeginBatch() { inBatchOperation = true; }
void EndBatch() { inBatchOperation = false; Sort(); }
void Script_InsertItem( sdUIFunctionStack& stack );
void Script_InsertBlankItems( sdUIFunctionStack& stack );
void Script_SetItemText( sdUIFunctionStack& stack );
void Script_SetItemForeColor( sdUIFunctionStack& stack );
void Script_SetItemBackColor( sdUIFunctionStack& stack );
void Script_SetItemMaterialSize( sdUIFunctionStack& stack );
void Script_SetItemTextFlags( sdUIFunctionStack& stack );
void Script_DeleteItem( sdUIFunctionStack& stack );
void Script_InsertColumn( sdUIFunctionStack& stack );
void Script_DeleteColumn( sdUIFunctionStack& stack );
void Script_SetColumnText( sdUIFunctionStack& stack );
void Script_SetColumnWidth( sdUIFunctionStack& stack );
void Script_SetColumnTextFlags( sdUIFunctionStack& stack );
void Script_SetColumnFlags( sdUIFunctionStack& stack );
void Script_ClearItems( sdUIFunctionStack& stack );
void Script_ClearColumns( sdUIFunctionStack& stack );
void Script_GetItemText( sdUIFunctionStack& stack );
void Script_SetItemIcon( sdUIFunctionStack& stack );
void Script_FillFromEnumerator( sdUIFunctionStack& stack );
void Script_Sort( sdUIFunctionStack& stack );
void Script_GetItemAtPoint( sdUIFunctionStack& stack );
void Script_FindItem( sdUIFunctionStack& stack );
void Script_FindItemDataInt( sdUIFunctionStack& stack );
void Script_SetItemDataInt( sdUIFunctionStack& stack );
void Script_GetItemDataInt( sdUIFunctionStack& stack );
void Script_StoreVisualState( sdUIFunctionStack& stack );
void Script_RestoreVisualState( sdUIFunctionStack& stack );
void Script_TransitionItemVec4( sdUIFunctionStack& stack );
void Script_GetItemTransitionVec4Result( sdUIFunctionStack& stack );
void Script_TransitionColumnVec4( sdUIFunctionStack& stack );
void Script_GetColumnTransitionVec4Result( sdUIFunctionStack& stack );
void Script_ClearTransitions( sdUIFunctionStack& stack );
void Script_GetItemRect( sdUIFunctionStack& stack );
void Script_DrawItemMaterial( sdUIFunctionStack& stack );
void Script_SizeLastColumn( sdUIFunctionStack& stack );
void Script_SetItemFlags( sdUIFunctionStack& stack );
void Script_EnsureItemIsVisible( sdUIFunctionStack& stack );
void Script_FillFromFile( sdUIFunctionStack& stack );
virtual sdUIFunctionInstance* GetFunction( const char* name );
virtual bool RunNamedMethod( const char* name, sdUIFunctionStack& stack );
static void InitFunctions( void );
static void ShutdownFunctions( void ) { listFunctions.DeleteContents(); }
static const ListTemplateFunction* FindFunction( const char* name );
static int InsertItem( sdUIWindow* list, const wchar_t* name, int item, int column );
static void DeleteItem( sdUIWindow* list, int item );
static void SetItemText( sdUIWindow* list, const wchar_t* name, int item, int column );
static void SetItemForeColor( sdUIWindow* list, const idVec4& color, int item, int column );
static void SetItemBackColor( sdUIWindow* list, const idVec4& color, int item, int column );
static void SetItemIcon( sdUIWindow* list, const char* iconMaterial, int item, int column );
static void ClearItems( sdUIWindow* list );
static void ClearColumns( sdUIWindow* list );
static void CleanUserInput( idWStr& input );
static void StripFormatting( idWStr& string );
template< class F >
void Sort( F sorter ) { sdQuickSort( indices.Begin(), indices.End(), sorter ); }
void SetItemDataInt( int integer, int item, int column, bool direct = false );
void SetItemDataPtr( void* ptr, int item, int column, bool direct = false );
int GetItemDataInt( int item, int column, bool direct = false ) const;
void* GetItemDataPtr( int item, int column, bool direct = false ) const;
const wchar_t* GetItemText( int item, int column, bool direct = false ) const;
virtual int GetMaxEventTypes( void ) const { return LE_NUM_EVENTS; }
virtual const char* GetEventNameForType( int event ) const { return ( event < ( WE_NUM_EVENTS + 1 )) ? sdUIWindow::GetEventNameForType( event ): eventNames[ event - WE_NUM_EVENTS - 1 ]; }
int GetCurrentSelection() const { return idMath::Ftoi( currentSelection ); }
int GetNumItems() const;
protected:
virtual void DrawLocal();
virtual void InitProperties();
void OnFixedRowHeightChanged( const float oldValue, const float newValue );
void OnCurrentItemChanged( const float oldValue, const float newValue );
void OnActiveColumnChanged( const float oldValue, const float newValue );
void OnInternalBorderChanged( const float oldValue, const float newValue );
bool IndexCheck( int row, int column, const char* warningText = NULL ) const;
void DrawItemMaterial( int row, int col, const idVec4& rect, const idVec4& color, bool directIndex );
// columnWidths should be preallocated with columns.Num() elements
void CalcColumnWidths( float* columnWidths ) const;
bool CheckHeaderMouseOver( const sdBounds2D& windowBounds, const idVec2& point );
bool CheckItemMouseOver( const sdBounds2D& windowBounds, const idVec2& point );
private:
enum listTransitionProperty_e { LTP_FORECOLOR = -2,
LTP_BACKCOLOR = -1,
LTP_PROPERTY_0 = 0,
LTP_PROPERTY_1 = 1,
LTP_PROPERTY_2 = 2,
LTP_PROPERTY_MAX = 3
};
static const int MAX_VEC4_EVALUATORS = LTP_PROPERTY_MAX;
typedef sdTransitionEvaluator< idVec4 > vec4Evaluator_t;
typedef idStaticList< vec4Evaluator_t, MAX_VEC4_EVALUATORS > vec4EvaluatorList_t;
class sdTransition {
public:
sdTransition() : evaluators( NULL ) {
backColor.InitConstant( idVec4( 0.0f, 0.0f, 0.0f, 0.0f ) );
foreColor.InitConstant( colorWhite );
}
~sdTransition() {
FreeEvaluators();
}
vec4Evaluator_t* GetEvaluator( int index, bool allowCreate );
void FreeEvaluators() {
vec4EvaluatorListAllocator.Free( evaluators );
evaluators = NULL;
}
vec4Evaluator_t backColor;
vec4Evaluator_t foreColor;
vec4EvaluatorList_t* evaluators;
};
static idBlockAlloc< vec4EvaluatorList_t, 32 > vec4EvaluatorListAllocator;
/*
============
sdUIListItem
============
*/
class sdUIListItem :
public sdPoolAllocator< sdUIListItem, sdUIListItem_Identifier, 1024 > {
public:
sdUIListItem();
~sdUIListItem();
idWStr text;
int textHandle;
uiDrawPart_t part;
int textFlags;
union data_t {
void* ptr;
int integer;
} data;
struct flags_t {
bool customDraw : 1;
bool mouseFocused : 1;
} flags;
};
/*
============
sdUIListColumn
============
*/
class sdUIListColumn :
public sdPoolAllocator< sdUIListColumn, sdUIListColumn_Identifier, 1024 > {
public:
sdUIListColumn();
~sdUIListColumn() {
items.DeleteContents( true );
}
void ResetUserFlags() {
flags.numericSort = false;
flags.customDraw = false;
flags.allowSort = true;
flags.dataSort = false;
}
float baseWidth;
idWStr text;
uiDrawPart_t part;
int textHandle;
int textFlags;
idList< sdUIListItem* > items;
idList< sdTransition > itemTransitions;
sdTransition transition;
struct flags_t {
bool allowSort : 1;
bool numericSort : 1;
bool dataSort : 1;
bool sortDescending : 1;
bool customDraw : 1;
bool widthPercent : 1; // the width field should be interpreted as a percentage of the parent window
bool mouseFocused : 1;
} flags;
};
/*
============
sdColumnSort
local functor class to sort based on the active column
============
*/
class sdColumnSort {
public:
sdColumnSort( sdUIListColumn& c ) : column( c ) {}
int operator()( const int first, const int second ) const {
sdUIListItem* firstItem = column.items[ first ];
sdUIListItem* secondItem = column.items[ second ];
return idWStr::IcmpNoColor( firstItem->text.c_str(), secondItem->text.c_str() );
}
private:
sdUIListColumn& column;
};
/*
============
sdColumnSortNumeric
local functor class to sort based on the active column
============
*/
class sdColumnSortNumeric {
public:
sdColumnSortNumeric( sdUIListColumn& c ) : column( c ) {}
int operator()( const int first, const int second ) const {
sdUIListItem* firstItem = column.items[ first ];
sdUIListItem* secondItem = column.items[ second ];
float value1 = sdTypeFromString< float >( firstItem->text.c_str() );
float value2 = sdTypeFromString< float >( secondItem->text.c_str() );
return value1 - value2;
}
private:
sdUIListColumn& column;
};
/*
============
sdColumnSortData
local functor class to sort based on the active column
============
*/
class sdColumnSortData {
public:
sdColumnSortData( sdUIListColumn& c ) : column( c ) {}
int operator()( const int first, const int second ) const {
sdUIListItem* firstItem = column.items[ first ];
sdUIListItem* secondItem = column.items[ second ];
return firstItem->data.integer - secondItem->data.integer;
}
private:
sdUIListColumn& column;
};
private:
void Scroll( float amount );
void ScrollToItem( int item );
void ScrollPercent( float percent );
// is the item completely visible within the client rect?
// returns how far above or below the item is, or 0 if it is visible
float GetVisibleItemOffset( int item ) const;
void GetItemRect( const int row, idVec4& rect ) const; // get the full (control-width) rectangle of the item
void GetItemRect( const int row, const int col, idVec4& rect, const float* columnWidths ) const; // get the column width rectangle of the item
void GetThumbRect( idVec4& rect ) const;
void GetHeaderColumnRect( const int column, idVec4& rect, const float* columnWidths ) const;
int GetFirstVisibleItem() const;
int GetLastVisibleItem( int firstVisible ) const;
bool IsItemVisible( int item ) const;
float GetHeaderHeight() const;
float GetMaxScrollAmount() const;
sdUIListItem* GetItem( int row, int column, const char* warningText = "GetItem", bool direct = false );
const sdUIListItem* GetItem( int row, int column, const char* warningText = "GetItem", bool direct = false ) const;
bool CheckItemClick( const sdSysEvent* event, const idVec2& point );
bool CheckHeaderClick( const sdSysEvent* event, const idVec2& point );
bool HandleKeyInput( const sdSysEvent* event );
void Sort();
bool ExtractColorFromString( const wchar_t* format, const wchar_t* indicator, idVec4& color );
void ExtractTextFormatFromString( const wchar_t* format, const wchar_t* indicator, int& flags );
void ExtractMaterialFromString( const wchar_t* format, const wchar_t* indicator, uiDrawPart_t& mat );
void ExtractLocalizedTextFromString( const wchar_t* format, const wchar_t* indicator, int& handle );
void ExtractItemFlagsFromString( const wchar_t* format, const wchar_t* indicator, sdUIListItem& item );
void ExtractColumnFlagsFromString( const wchar_t* format, const wchar_t* indicator, sdUIListColumn& column );
void ExtractColumnWidthFromString( const wchar_t* format, const wchar_t* indicator, sdUIListColumn& column );
void InitVec4Transition( const idVec4& from, const idVec4& to, const int time, const idStr& accel, vec4Evaluator_t& evaluator );
void ClearTransition( sdTransition& transition );
void FormatItemText( sdUIListItem& item, sdTransition& transition, const wchar_t* text );
float GetTotalHeight( int start = 0, int end = -1 ) const;
float GetVisibleHeight() const;
protected:
static idHashMap< ListTemplateFunction* > listFunctions;
private:
// selection
// rows
SD_UI_PROPERTY_TAG(
title = "1. Behavior/Current Selection";
desc = "The current selected item";
editor = "edit";
datatype = "float";
)
sdFloatProperty currentSelection;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Internal Border";
desc = "Border to uniformly shrink items by";
editor = "edit";
datatype = "float";
)
sdFloatProperty internalBorderWidth;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/1. Selected Items/Foreground Color";
desc = "Foreground color of a selected item";
editor = "edit";
option1 = "{editorComponents} {r,g,b,a}";
option2 = "{editorSeparator} {,}";
datatype = "vec4";
aliasdatatype = "color";
)
sdVec4Property selectedItemForeColor;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/2. Columns/Text scale";
desc = "Column font size";
editor = "edit";
datatype = "float";
)
sdFloatProperty columnFontSize;
// ===========================================
// rows
SD_UI_PROPERTY_TAG(
title = "2. Drawing/2. Columns/Row spacing";
desc = "Vertical space between rows";
editor = "edit";
datatype = "float";
)
sdFloatProperty rowSpacing;
// ===========================================
// row height
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Row height";
desc = "If specified, uses a fixed row height, set to 0 for auto-sizing.";
editor = "edit";
datatype = "float";
)
sdFloatProperty fixedRowHeight;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Drop Shadow Image";
desc = "Draw a drop shadow under images. Specifies the number of pixels to offset.";
editor = "edit";
datatype = "float";
)
sdFloatProperty dropShadowOffsetImage;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Active Column";
desc = "Column used for sorting.";
editor = "edit";
datatype = "float";
)
sdFloatProperty activeColumn;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Active Column Sort";
desc = "Direction of sorting. -1 for descending, 1 for ascending.";
editor = "edit";
datatype = "float";
)
sdFloatProperty activeColumnSort;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Scroll Amount";
desc = "Offset from top ( 0 ).";
editor = "edit";
datatype = "float";
)
sdFloatProperty scrollAmount;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Scroll Amount Max";
desc = "Maximum offset from top, inclusive.";
editor = "edit";
datatype = "float";
readOnly = "true";
)
sdFloatProperty scrollAmountMax;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Page Size";
desc = "Size in pixels of one full page of items.";
editor = "edit";
datatype = "float";
readOnly = "true";
)
sdFloatProperty pageSize;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Column Border";
desc = "Column border between items.";
editor = "edit";
datatype = "float";
)
sdFloatProperty columnBorder;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Column Height";
desc = "Derived as the max height of each column's title.";
editor = "edit";
datatype = "float";
readOnly = "true";
)
sdFloatProperty columnHeight;
// ===========================================
SD_UI_PROPERTY_TAG(
title = "2. Drawing/Num Items";
desc = "Number of rows in the list.";
editor = "edit";
datatype = "float";
readOnly = "true";
)
sdFloatProperty numItems;
// ===========================================
static const char* eventNames[ LE_NUM_EVENTS - WE_NUM_EVENTS ];
sdUIEventHandle drawColumnHandle;
sdUIEventHandle drawItemHandle;
sdUIEventHandle drawItemBackHandle;
sdUIEventHandle drawSelectedItemBackHandle;
private:
idList< int > indices;
idList< sdUIListColumn* > columns;
idList< int > rowHeights;
float storedScrollAmount;
int scrollToItem;
bool inBatchOperation;
float sizeLastColumnDelta;
idWToken token; // shared token for parsing format strings
};
/*
============
sdUIList::GetFirstVisibleItem
============
*/
ID_INLINE int sdUIList::GetFirstVisibleItem() const {
int num = GetNumItems();
int index = 0;
float bottom = 0.0f;
while( index < num - 1 ) {
bottom += rowHeights[ index ];
if( bottom >= scrollAmount ) {
break;
}
index++;
}
return index;
}
/*
============
sdUIList::GetNumItems
============
*/
ID_INLINE int sdUIList::GetNumItems() const {
if( !columns.Num()) {
return 0;
}
return ( columns[ 0 ]->items.Num() );
}
/*
============
sdUIList::Scroll
============
*/
ID_INLINE void sdUIList::Scroll( float amount ) {
scrollAmount = idMath::ClampFloat( 0.0f, GetMaxScrollAmount(), scrollAmount + amount );
}
/*
============
sdUIList::GetMaxScrollAmount
============
*/
ID_INLINE float sdUIList::GetMaxScrollAmount() const {
float total = GetTotalHeight();
float visible = GetVisibleHeight();
if( visible >= total ) {
return 0.0f;
}
return total - visible;
}
/*
============
sdUIList::ScrollPercent
============
*/
ID_INLINE void sdUIList::ScrollPercent( float percent ) {
scrollAmount = idMath::ClampFloat( GetMaxScrollAmount(), 0.0f, percent * GetMaxScrollAmount() );
}
/*
============
sdUIList::ScrollToItem
============
*/
ID_INLINE void sdUIList::ScrollToItem( int item ) {
Scroll( GetVisibleItemOffset( item ));
}
/*
============
sdUIList::GetItemRect
============
*/
ID_INLINE void sdUIList::GetItemRect( const int row, idVec4& rect ) const {
rect.x = cachedClientRect.x;
rect.x += borderWidth + internalBorderWidth;
//rect.y = GetHeaderHeight() + cachedClientRect.y + ( rowHeight * row );
rect.y = GetHeaderHeight() + cachedClientRect.y + GetTotalHeight( 0, row );
rect.y += borderWidth + internalBorderWidth;
rect.y -= scrollAmount;
rect.z = cachedClientRect.z;
//rect.w = rowHeight - rowSpacing;
rect.w = rowHeights[ row ] - rowSpacing;
}
/*
============
sdUIList::GetItemRect
============
*/
ID_INLINE void sdUIList::GetItemRect( const int row, int col, idVec4& rect, const float* columnWidths ) const {
GetItemRect( row, rect );
int i = 0;
while( i <= col ) {
if( i == col ) {
rect.z = columnWidths[ i ] - ( 2.0f * ( borderWidth + internalBorderWidth ) ) - columnBorder;
break;
}
rect.x += columnWidths[ i ];
i++;
}
}
/*
============
sdUIList::GetHeaderColumnRect
============
*/
ID_INLINE void sdUIList::GetHeaderColumnRect( const int column, idVec4& rect, const float* columnWidths ) const {
assert( columnWidths != NULL );
rect.Zero();
rect.x = cachedClientRect.x + borderWidth;
rect.y = cachedClientRect.y + borderWidth;
rect.w = GetHeaderHeight();
for( int i = 0; i < columns.Num(); i++ ) {
if( column == i ) {
rect.z = columnWidths[ i ];
break;
}
rect.x += columnWidths[ i ];
}
}
/*
============
sdUIList::IsItemVisible
============
*/
ID_INLINE bool sdUIList::IsItemVisible( int item ) const {
int firstVisible = GetFirstVisibleItem();
int lastVisible = GetLastVisibleItem( firstVisible );
return ( item >= firstVisible ) && ( item <= lastVisible );
}
/*
============
sdUIList::GetHeaderHeight
============
*/
ID_INLINE float sdUIList::GetHeaderHeight() const {
return TestFlag( LF_SHOW_HEADINGS ) ? columnHeight.GetValue() : 0.0f;
}
/*
============
sdUIList::IndexCheck
============
*/
ID_INLINE bool sdUIList::IndexCheck( int row, int column, const char* warningText ) const {
if( column < 0 ||
column >= columns.Num() ||
row < 0 ||
row >= columns[ 0 ]->items.Num() ) {
if( warningText != NULL ) {
gameLocal.Warning( "%s: %s: index out of range (row %i, column %i)", name.GetValue().c_str(), warningText, row, column );
}
return false;
}
return true;
}
/*
============
sdUIList::GetItem
============
*/
ID_INLINE sdUIList::sdUIListItem* sdUIList::GetItem( int row, int column, const char* warningText, bool direct ) {
if( !IndexCheck( row, column, warningText )) {
return NULL;
}
if( direct ) {
return columns[ column ]->items[ row ];
}
return columns[ column ]->items[ indices[ row ] ];
}
/*
============
sdUIList::GetItem
============
*/
ID_INLINE const sdUIList::sdUIListItem* sdUIList::GetItem( int row, int column, const char* warningText, bool direct ) const {
if( !IndexCheck( row, column, warningText )) {
return NULL;
}
if( direct ) {
return columns[ column ]->items[ row ];
}
return columns[ column ]->items[ indices[ row ] ];
}
/*
============
sdUIList::RemapIndex
============
*/
ID_INLINE int sdUIList::RemapIndex( int index ) const {
if( columns.Num() == 0 || index < 0 || index >= columns[ 0 ]->items.Num() ) {
return -1;
}
return indices[ index ];
}
/*
============
sdUIList::GetTotalHeight
============
*/
ID_INLINE float sdUIList::GetTotalHeight( int start, int end ) const {
if( end == -1 ) {
end = GetNumItems();
}
float total = 0.0f;
for( int i = start; i < end; i++ ) {
total += rowHeights[ i ];
}
return total;
}
/*
============
sdUIList::GetVisibleHeight
============
*/
ID_INLINE float sdUIList::GetVisibleHeight() const {
return cachedClientRect.w - ( GetHeaderHeight() + 2.0f * ( internalBorderWidth + borderWidth ) );
}
/*
============
sdUIList::GetLastVisibleItem
============
*/
ID_INLINE int sdUIList::GetLastVisibleItem( int firstVisible ) const {
float y = GetTotalHeight( 0, firstVisible );
float maxY = y + GetVisibleHeight();
int index = firstVisible;
int num = GetNumItems();
if( num == 0 ) {
return -1;
}
while( index < num - 1 && y <= maxY ) {
y += rowHeights[ index ];
index++;
}
return index;
}
#endif // ! __GAME_GUIS_USERINTERFACELIST_H__