aboutsummaryrefslogtreecommitdiff
path: root/mp/src/vgui2/vgui_controls/ListViewPanel.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/vgui2/vgui_controls/ListViewPanel.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/vgui2/vgui_controls/ListViewPanel.cpp')
-rw-r--r--mp/src/vgui2/vgui_controls/ListViewPanel.cpp2164
1 files changed, 1082 insertions, 1082 deletions
diff --git a/mp/src/vgui2/vgui_controls/ListViewPanel.cpp b/mp/src/vgui2/vgui_controls/ListViewPanel.cpp
index b188a01b..59f05ab6 100644
--- a/mp/src/vgui2/vgui_controls/ListViewPanel.cpp
+++ b/mp/src/vgui2/vgui_controls/ListViewPanel.cpp
@@ -1,1082 +1,1082 @@
-//========= 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
-}
-
+//========= 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
+}
+