Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1083 lines
26 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <assert.h>
#include <ctype.h>
#include <vgui/MouseCode.h>
#include <vgui/KeyCode.h>
#include <KeyValues.h>
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include <vgui/IInput.h>
#include <vgui/IPanel.h>
#include <vgui/ILocalize.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/ScrollBar.h>
#include <vgui_controls/ImageList.h>
#include <vgui_controls/ImagePanel.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/TextImage.h>
#include <vgui_controls/ListViewPanel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
using namespace vgui;
enum
{
WINDOW_BORDER_WIDTH=2 // the width of the window's border
};
namespace vgui
{
class ListViewItem : public Label
{
DECLARE_CLASS_SIMPLE( ListViewItem, Label );
public:
ListViewItem(Panel *parent) : Label(parent, NULL, "")
{
m_pListViewPanel = (ListViewPanel*) parent;
m_pData = NULL;
m_bSelected = false;
SetPaintBackgroundEnabled(true);
}
~ListViewItem()
{
if (m_pData)
{
m_pData->deleteThis();
m_pData = NULL;
}
}
void SetData(const KeyValues *data)
{
if (m_pData)
{
m_pData->deleteThis();
}
m_pData = data->MakeCopy();
}
virtual void OnMousePressed( MouseCode code)
{
m_pListViewPanel->OnItemMousePressed(this, code);
}
virtual void OnMouseDoublePressed( MouseCode code)
{
// double press should only select the item
m_pListViewPanel->OnItemMouseDoublePressed(this, code);
}
KeyValues *GetData()
{
return m_pData;
}
void SetSelected(bool bSelected)
{
if (bSelected == m_bSelected)
return;
m_bSelected = bSelected;
if (bSelected)
{
RequestFocus();
}
UpdateImage();
InvalidateLayout();
Repaint();
}
virtual void PerformLayout()
{
TextImage *textImage = GetTextImage();
if (m_bSelected)
{
VPANEL focus = input()->GetFocus();
// if one of the children of the SectionedListPanel has focus, then 'we have focus' if we're selected
if (HasFocus() || (focus && ipanel()->HasParent(focus, GetVParent())))
{
textImage->SetColor(m_ArmedFgColor2);
}
else
{
textImage->SetColor(m_FgColor2);
}
}
else
{
textImage->SetColor(GetFgColor());
}
BaseClass::PerformLayout();
Repaint();
}
virtual void PaintBackground()
{
int wide, tall;
GetSize(wide, tall);
if ( m_bSelected )
{
VPANEL focus = input()->GetFocus();
// if one of the children of the SectionedListPanel has focus, then 'we have focus' if we're selected
if (HasFocus() || (focus && ipanel()->HasParent(focus, GetVParent())))
{
surface()->DrawSetColor(m_ArmedBgColor);
}
else
{
surface()->DrawSetColor(m_SelectionBG2Color);
}
}
else
{
surface()->DrawSetColor(GetBgColor());
}
surface()->DrawFilledRect(0, 0, wide, tall);
}
virtual void ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
m_ArmedFgColor2 = GetSchemeColor("ListPanel.SelectedTextColor", pScheme);
m_ArmedBgColor = GetSchemeColor("ListPanel.SelectedBgColor", pScheme);
m_FgColor1 = GetSchemeColor("ListPanel.TextColor", pScheme);
m_FgColor2 = GetSchemeColor("ListPanel.SelectedTextColor", pScheme);
m_BgColor = GetSchemeColor("ListPanel.BgColor", GetBgColor(), pScheme);
m_BgColor = GetSchemeColor("ListPanel.TextBgColor", m_BgColor, pScheme);
m_SelectionBG2Color = GetSchemeColor("ListPanel.SelectedOutOfFocusBgColor", pScheme);
SetBgColor(m_BgColor);
SetFgColor(m_FgColor1);
UpdateImage();
}
void UpdateImage()
{
if ( m_pListViewPanel->m_pImageList )
{
int imageIndex = 0;
if ( m_bSelected )
{
imageIndex = m_pData->GetInt("imageSelected", 0);
}
if ( imageIndex == 0 )
{
imageIndex = m_pData->GetInt("image", 0);
}
if ( m_pListViewPanel->m_pImageList->IsValidIndex(imageIndex) )
{
SetImageAtIndex(0, m_pListViewPanel->m_pImageList->GetImage(imageIndex), 0);
}
else
{
// use the default
SetImageAtIndex(0, m_pListViewPanel->m_pImageList->GetImage(1), 0);
}
SizeToContents();
InvalidateLayout();
}
}
private:
Color m_FgColor1;
Color m_FgColor2;
Color m_BgColor;
Color m_ArmedFgColor2;
Color m_ArmedBgColor;
Color m_SelectionBG2Color;
//IBorder *_keyFocusBorder; // maybe in the future when I'm the 'active' but not selected item, I'll have a border
KeyValues *m_pData;
ListViewPanel *m_pListViewPanel;
bool m_bSelected;
};
}
static bool DefaultSortFunc(KeyValues *kv1, KeyValues *kv2)
{
const char *string1 = kv1->GetString("text");
const char *string2 = kv2->GetString("text");
return Q_stricmp(string1, string2) < 0;
}
DECLARE_BUILD_FACTORY( ListViewPanel );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
ListViewPanel::ListViewPanel(Panel *parent, const char *panelName) : Panel(parent, panelName)
{
m_iRowHeight = 20;
m_bNeedsSort = false;
m_hFont = NULL;
m_pImageList = NULL;
m_bDeleteImageListWhenDone = false;
m_pSortFunc = DefaultSortFunc;
m_ShiftStartItemID = -1;
m_hbar = new ScrollBar(this, "HorizScrollBar", false);
m_hbar->AddActionSignalTarget(this);
m_hbar->SetVisible(false);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ListViewPanel::~ListViewPanel()
{
DeleteAllItems();
delete m_hbar;
if ( m_bDeleteImageListWhenDone )
{
delete m_pImageList;
m_pImageList = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int ListViewPanel::AddItem(const KeyValues *data, bool bScrollToItem, bool bSortOnAdd)
{
ListViewItem *pNewItem = new ListViewItem(this);
pNewItem->SetData(data);
if (m_hFont)
{
pNewItem->SetFont(m_hFont);
}
int itemID = m_DataItems.AddToTail(pNewItem);
ApplyItemChanges(itemID);
m_SortedItems.AddToTail(itemID);
if ( bSortOnAdd )
{
m_bNeedsSort = true;
}
InvalidateLayout();
if ( bScrollToItem )
{
ScrollToItem(itemID);
}
return itemID;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::ScrollToItem(int itemID)
{
if (!m_hbar->IsVisible())
{
return;
}
int val = m_hbar->GetValue();
int wide, tall;
GetSize( wide, tall );
int maxWidth = GetItemsMaxWidth();
int maxColVisible = wide / maxWidth;
int itemsPerCol = GetItemsPerColumn();
int itemIndex = m_SortedItems.Find(itemID);
int desiredCol = itemIndex / itemsPerCol;
if (desiredCol < val || desiredCol >= (val + maxColVisible) )
{
m_hbar->SetValue(desiredCol);
}
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int ListViewPanel::GetItemCount()
{
return m_DataItems.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
KeyValues *ListViewPanel::GetItem(int itemID)
{
if ( !m_DataItems.IsValidIndex(itemID) )
return NULL;
return m_DataItems[itemID]->GetData();
}
//-----------------------------------------------------------------------------
// Purpose: Get ItemID from position in panel - valid from [0, GetItemCount)
//-----------------------------------------------------------------------------
int ListViewPanel::GetItemIDFromPos(int iPos)
{
if ( m_SortedItems.IsValidIndex(iPos) )
{
return m_SortedItems[iPos];
}
else
{
return m_DataItems.InvalidIndex();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::ApplyItemChanges(int itemID)
{
if ( !m_DataItems.IsValidIndex(itemID) )
return;
KeyValues *kv = m_DataItems[itemID]->GetData();
ListViewItem *pLabel = m_DataItems[itemID];
pLabel->SetText(kv->GetString("text"));
pLabel->SetTextImageIndex(1);
pLabel->SetImagePreOffset(1, 5);
TextImage *pTextImage = pLabel->GetTextImage();
pTextImage->ResizeImageToContent();
pLabel->UpdateImage();
pLabel->SizeToContents();
pLabel->InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::RemoveItem(int itemID)
{
if ( !m_DataItems.IsValidIndex(itemID) )
return;
m_DataItems[itemID]->MarkForDeletion();
// mark the keyValues for deletion
m_DataItems.Remove(itemID);
m_SortedItems.FindAndRemove(itemID);
m_SelectedItems.FindAndRemove(itemID);
InvalidateLayout();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::DeleteAllItems()
{
FOR_EACH_LL( m_DataItems, index )
{
m_DataItems[index]->MarkForDeletion();
}
m_DataItems.RemoveAll();
m_SortedItems.RemoveAll();
m_SelectedItems.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int ListViewPanel::InvalidItemID()
{
return m_DataItems.InvalidIndex();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool ListViewPanel::IsValidItemID(int itemID)
{
return m_DataItems.IsValidIndex(itemID);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::SetSortFunc(ListViewSortFunc_t func)
{
if ( func )
{
m_pSortFunc = func;
SortList();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::SortList()
{
m_SortedItems.RemoveAll();
// find all the items in this section
for( int i = m_DataItems.Head(); i != m_DataItems.InvalidIndex(); i = m_DataItems.Next( i ) )
{
// insert the items sorted
if (m_pSortFunc)
{
int insertionPoint;
for (insertionPoint = 0; insertionPoint < m_SortedItems.Count(); insertionPoint++)
{
if ( m_pSortFunc(m_DataItems[i]->GetData(), m_DataItems[m_SortedItems[insertionPoint]]->GetData() ) )
break;
}
if (insertionPoint == m_SortedItems.Count())
{
m_SortedItems.AddToTail(i);
}
else
{
m_SortedItems.InsertBefore(insertionPoint, i);
}
}
else
{
// just add to the end
m_SortedItems.AddToTail(i);
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::SetImageList(ImageList *imageList, bool deleteImageListWhenDone)
{
// get rid of existing list image if there's one and we're supposed to get rid of it
if ( m_pImageList && m_bDeleteImageListWhenDone )
{
delete m_pImageList;
m_pImageList = NULL;
}
m_bDeleteImageListWhenDone = deleteImageListWhenDone;
m_pImageList = imageList;
FOR_EACH_LL( m_DataItems, i )
{
m_DataItems[i]->UpdateImage();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::SetFont(HFont font)
{
Assert( font );
if ( !font )
return;
m_hFont = font;
m_iRowHeight = surface()->GetFontTall(font) + 1;
FOR_EACH_LL( m_DataItems, i )
{
m_DataItems[i]->SetFont(m_hFont);
TextImage *pTextImage = m_DataItems[i]->GetTextImage();
pTextImage->ResizeImageToContent();
m_DataItems[i]->SizeToContents();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int ListViewPanel::GetSelectedItemsCount()
{
return m_SelectedItems.Count();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int ListViewPanel::GetSelectedItem(int selectionIndex)
{
if ( m_SelectedItems.IsValidIndex(selectionIndex) )
return m_SelectedItems[selectionIndex];
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::ClearSelectedItems()
{
int i;
for (i = 0 ; i < m_SelectedItems.Count(); i++)
{
if ( m_DataItems.IsValidIndex(m_SelectedItems[i]) )
{
m_DataItems[m_SelectedItems[i]]->SetSelected(false);
}
}
m_SelectedItems.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::AddSelectedItem(int itemID)
{
if ( m_SelectedItems.Find(itemID) == -1 )
{
m_SelectedItems.AddToTail(itemID);
m_DataItems[itemID]->SetSelected(true);
m_LastSelectedItemID = itemID;
m_ShiftStartItemID = itemID;
PostActionSignal(new KeyValues("ListViewItemSelected"));
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::SetSingleSelectedItem(int itemID)
{
ClearSelectedItems();
AddSelectedItem(itemID);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnMouseWheeled(int delta)
{
int val = m_hbar->GetValue();
val -= delta;
m_hbar->SetValue(val);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnSizeChanged(int wide, int tall)
{
BaseClass::OnSizeChanged(wide, tall);
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int ListViewPanel::GetItemsMaxWidth()
{
int maxWidth = 0;
FOR_EACH_LL( m_DataItems, i )
{
int labelWide, labelTall;
m_DataItems[i]->GetSize(labelWide, labelTall);
if (labelWide > maxWidth)
{
maxWidth = labelWide + 25;
}
}
return maxWidth;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::PerformLayout()
{
if (m_bNeedsSort)
{
SortList();
}
if ( m_DataItems.Count() == 0 )
return;
int wide, tall;
GetSize(wide, tall);
int maxWidth = GetItemsMaxWidth();
if (maxWidth < 24)
{
maxWidth = 24;
}
int maxColVisible = wide / maxWidth;
m_hbar->SetVisible(false);
int itemsPerCol = GetItemsPerColumn();
if (itemsPerCol < 1)
{
itemsPerCol = 1;
}
int cols = ( GetItemCount() + (itemsPerCol - 1) ) / itemsPerCol;
int startItem = 0;
if ( cols > maxColVisible)
{
m_hbar->SetVisible(true);
// recalulate # per column now that we've made the hbar visible
itemsPerCol = GetItemsPerColumn();
cols = ( GetItemCount() + (itemsPerCol - 1) ) / (itemsPerCol > 0 ? itemsPerCol : 1 );
m_hbar->SetEnabled(false);
m_hbar->SetRangeWindow( maxColVisible );
m_hbar->SetRange( 0, cols);
m_hbar->SetButtonPressedScrollValue( 1 );
m_hbar->SetPos(0, tall - (m_hbar->GetTall()+WINDOW_BORDER_WIDTH));
m_hbar->SetSize(wide - (WINDOW_BORDER_WIDTH*2), m_hbar->GetTall());
m_hbar->InvalidateLayout();
int val = m_hbar->GetValue();
startItem += val*itemsPerCol;
}
else
{
m_hbar->SetVisible(false);
}
int lastItemVisible = startItem + (( maxColVisible + 1 )* itemsPerCol) - 1;
int itemsThisCol = 0;
int x = 0;
int y = 0;
int i;
for ( i = 0 ; i < m_SortedItems.Count() ; i++ )
{
if ( i >= startItem && i <= lastItemVisible )
{
m_DataItems[ m_SortedItems[i] ]->SetVisible(true);
m_DataItems[ m_SortedItems[i] ]->SetPos(x, y);
itemsThisCol++;
if ( itemsThisCol == itemsPerCol )
{
y = 0;
x += maxWidth;
itemsThisCol = 0;
}
else
{
y += m_iRowHeight;
}
}
else
{
m_DataItems[ m_SortedItems[i] ]->SetVisible(false);
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::Paint()
{
BaseClass::Paint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetBgColor(GetSchemeColor("ListPanel.BgColor", pScheme));
SetBorder(pScheme->GetBorder("ButtonDepressedBorder"));
m_LabelFgColor = GetSchemeColor("ListPanel.TextColor", pScheme);
m_SelectionFgColor = GetSchemeColor("ListPanel.SelectedTextColor", m_LabelFgColor, pScheme);
m_hFont = pScheme->GetFont("Default", IsProportional());
SetFont(m_hFont);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnMousePressed( MouseCode code)
{
if (code == MOUSE_LEFT || code == MOUSE_RIGHT)
{
ClearSelectedItems();
RequestFocus();
}
// check for context menu open
if (code == MOUSE_RIGHT)
{
// post it, but with the invalid row
PostActionSignal(new KeyValues("OpenContextMenu", "itemID", -1));
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnShiftSelect(int itemID)
{
// if we dont' have a valid selected ItemID - then we just choose the first item
if ( !m_DataItems.IsValidIndex(m_ShiftStartItemID) )
{
m_ShiftStartItemID = m_DataItems.Head();
}
// find out if the just pressed item is "earlier" or is the 'last selected item'
int lowerPos = -1, upperPos = -1;
int i;
for ( i = 0 ; i < m_SortedItems.Count() ; i++ )
{
if ( m_SortedItems[i] == itemID )
{
lowerPos = i;
upperPos = m_SortedItems.Find(m_ShiftStartItemID);
break;
}
else if ( m_SortedItems[i] == m_ShiftStartItemID )
{
lowerPos = m_SortedItems.Find(m_ShiftStartItemID);
upperPos = i;
break;
}
}
assert(lowerPos <= upperPos);
if ( !input()->IsKeyDown(KEY_LCONTROL) && !input()->IsKeyDown(KEY_RCONTROL) )
{
ClearSelectedItems();
}
for ( i = lowerPos ; i <= upperPos ; i ++)
{
// do not use AddSelectedItem because we don't want to switch the shiftStartItemID
m_DataItems[ m_SortedItems[i] ]->SetSelected(true);
m_SelectedItems.AddToTail(m_SortedItems[i]);
m_LastSelectedItemID = itemID;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnItemMousePressed(ListViewItem* pItem, MouseCode code)
{
int itemID = m_DataItems.Find(pItem);
if (!m_DataItems.IsValidIndex(itemID))
return;
// check for context menu open
if (code == MOUSE_RIGHT)
{
// if this is a new item - unselect everything else
if ( m_SelectedItems.Find(itemID) == -1)
{
ClearSelectedItems();
AddSelectedItem(itemID);
}
PostActionSignal(new KeyValues("OpenContextMenu", "itemID", itemID));
}
else
{
if ( input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT) )
{
OnShiftSelect(itemID);
}
else if ( input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL) )
{
if ( m_SelectedItems.Find(itemID) != -1)
{
m_SelectedItems.FindAndRemove(itemID);
pItem->SetSelected(false);
// manually select these since we 'last' clicked on these items
m_ShiftStartItemID = itemID;
m_LastSelectedItemID = itemID;
m_DataItems[itemID]->RequestFocus();
}
else
{
AddSelectedItem(itemID);
}
}
else
{
ClearSelectedItems();
AddSelectedItem(itemID);
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnMouseDoublePressed( MouseCode code)
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnItemMouseDoublePressed(ListViewItem* pItem, MouseCode code)
{
if (code == MOUSE_LEFT)
{
OnKeyCodeTyped(KEY_ENTER);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::FinishKeyPress(int itemID)
{
if ( input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT) )
{
OnShiftSelect(itemID);
}
else if ( input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL) )
{
m_DataItems[itemID]->RequestFocus();
m_LastSelectedItemID = itemID;
}
else
{
SetSingleSelectedItem(itemID);
}
ScrollToItem(itemID);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnKeyCodeTyped( KeyCode code )
{
if ( m_DataItems.Count() == 0 )
return;
switch (code)
{
case KEY_HOME:
{
if (m_SortedItems.Count() > 0)
{
int itemID = m_SortedItems[0];
FinishKeyPress(itemID);
}
break;
}
case KEY_END:
{
if (m_DataItems.Count() > 0)
{
int itemID = m_SortedItems[ m_SortedItems.Count() - 1 ];
FinishKeyPress(itemID);
}
break;
}
case KEY_UP:
{
int itemPos = m_SortedItems.Find( m_LastSelectedItemID );
itemPos--;
if (itemPos < 0)
itemPos = 0;
FinishKeyPress(m_SortedItems[itemPos]);
break;
}
case KEY_DOWN:
{
int itemPos = m_SortedItems.Find( m_LastSelectedItemID );
itemPos++;
if (itemPos >= m_DataItems.Count())
itemPos = m_DataItems.Count() - 1;
FinishKeyPress(m_SortedItems[itemPos]);
break;
}
case KEY_LEFT:
{
int itemPos = m_SortedItems.Find( m_LastSelectedItemID );
itemPos -= GetItemsPerColumn();
if (itemPos < 0)
{
itemPos = 0;
}
FinishKeyPress(m_SortedItems[itemPos]);
break;
}
case KEY_RIGHT:
{
int itemPos = m_SortedItems.Find( m_LastSelectedItemID );
itemPos += GetItemsPerColumn();
if (itemPos >= m_SortedItems.Count())
{
itemPos = m_SortedItems.Count() - 1;
}
FinishKeyPress(m_SortedItems[itemPos]);
break;
}
case KEY_PAGEUP:
{
int wide, tall;
GetSize(wide, tall);
int maxWidth = GetItemsMaxWidth();
if (maxWidth == 0)
{
maxWidth = wide;
}
int maxColVisible = wide / maxWidth;
int delta = maxColVisible * GetItemsPerColumn();
int itemPos = m_SortedItems.Find( m_LastSelectedItemID );
itemPos -= delta;
if (itemPos < 0)
{
itemPos = 0;
}
FinishKeyPress(m_SortedItems[itemPos]);
break;
}
case KEY_PAGEDOWN:
{
int wide, tall;
GetSize(wide, tall);
int maxWidth = GetItemsMaxWidth();
if (maxWidth == 0)
{
maxWidth = wide;
}
int maxColVisible = wide / maxWidth;
int delta = maxColVisible * GetItemsPerColumn();
int itemPos = m_SortedItems.Find( m_LastSelectedItemID );
itemPos += delta;
if (itemPos >= m_SortedItems.Count())
{
itemPos = m_SortedItems.Count() - 1;
}
FinishKeyPress(m_SortedItems[itemPos]);
break;
}
default:
{
BaseClass::OnKeyCodeTyped(code);
break;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnKeyTyped(wchar_t unichar)
{
if (!iswcntrl(unichar))
{
wchar_t uniString[2];
uniString[0] = unichar;
uniString[1] = 0;
char buf[2];
g_pVGuiLocalize->ConvertUnicodeToANSI(uniString, buf, sizeof(buf));
int i;
int itemPos = m_SortedItems.Find(m_LastSelectedItemID);
if ( m_SortedItems.IsValidIndex(itemPos))
{
itemPos++;
// start from the item AFTER our last selected Item and go to end
for ( i = itemPos ; i != m_SortedItems.Count(); i++)
{
KeyValues *kv = m_DataItems[ m_SortedItems[i] ]->GetData();
const char *pszText = kv->GetString("text");
if (!strnicmp(pszText, buf, 1))
{
// select the next of this letter
SetSingleSelectedItem(m_SortedItems[i]);
ScrollToItem(m_SortedItems[i]);
return;
}
}
// if the after this item we couldn't fine an item with the same letter, fall through and just start from the beginning of list to the last selected item
}
for ( i = 0 ; i < m_SortedItems.Count() ; i++ )
{
// we've gone all the way around - break - if we had a valid index, this is one more that last selectedItem, if not it's an illegal index
if ( i == itemPos)
break;
KeyValues *kv = m_DataItems[ m_SortedItems[i] ]->GetData();
const char *pszText = kv->GetString("text");
if (!strnicmp(pszText, buf, 1))
{
SetSingleSelectedItem(m_SortedItems[i]);
ScrollToItem(m_SortedItems[i]);
return;
}
}
}
else
BaseClass::OnKeyTyped(unichar);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ListViewPanel::OnSliderMoved()
{
InvalidateLayout();
Repaint();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int ListViewPanel::GetItemsPerColumn()
{
int wide, tall;
GetSize(wide, tall);
if ( m_hbar->IsVisible() )
{
tall -= m_hbar->GetTall();
}
return tall / m_iRowHeight; // should round down
}