From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/vgui2/vgui_controls/ListViewPanel.cpp | 2164 +++++++++++++------------- 1 file changed, 1082 insertions(+), 1082 deletions(-) (limited to 'mp/src/vgui2/vgui_controls/ListViewPanel.cpp') 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -// memdbgon must be the last include file in a .cpp file!!! -#include - -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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// memdbgon must be the last include file in a .cpp file!!! +#include + +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 +} + -- cgit v1.2.3