text: ﻿//========= Copyright Valve Corporation, All rights reserved. ============//
  //
  // Purpose: 
  //
  //=============================================================================
  
  #include "filesystem.h"
  #include "matsys_controls/picker.h"
  #include "tier1/KeyValues.h"
  #include "vgui_controls/ListPanel.h"
  #include "vgui_controls/TextEntry.h"
  #include "vgui_controls/Button.h"
  #include "vgui/ISurface.h"
  #include "vgui/IInput.h"
  
  
  using namespace vgui;
  
  
  //-----------------------------------------------------------------------------
  //
  // Base asset Picker
  //
  //-----------------------------------------------------------------------------
  
  
  //-----------------------------------------------------------------------------
  // Sort by asset name
  //-----------------------------------------------------------------------------
  static int __cdecl PickerBrowserSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
  {
  	const char *string1 = item1.kv->GetString("choice");
  	const char *string2 = item2.kv->GetString("choice");
  	return stricmp( string1, string2 );
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Constructor
  //-----------------------------------------------------------------------------
  CPicker::CPicker( vgui::Panel *pParent, const char *pColumnHeader, const char *pTextType ) : 
  	BaseClass( pParent, "Picker" )
  {
  	m_pPickerType = pColumnHeader;
  	m_pPickerTextType = pTextType;
  
  	// FIXME: Make this an image browser
  	m_pPickerBrowser = new vgui::ListPanel( this, "Browser" );
   	m_pPickerBrowser->AddColumnHeader( 0, "choice", m_pPickerType, 52, 0 );
      m_pPickerBrowser->SetSelectIndividualCells( true );
  	m_pPickerBrowser->SetEmptyListText( "Nothing to pick" );
   	m_pPickerBrowser->SetDragEnabled( true );
   	m_pPickerBrowser->AddActionSignalTarget( this );
  	m_pPickerBrowser->SetSortFunc( 0, PickerBrowserSortFunc );
  	m_pPickerBrowser->SetSortColumn( 0 );
  						 
  	// filter selection
  	m_pFilterList = new TextEntry( this, "FilterList" );
  	m_pFilterList->AddActionSignalTarget( this );
  	m_pFilterList->RequestFocus();
  
  	LoadControlSettingsAndUserConfig( "resource/picker.res" );
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Destructor
  //-----------------------------------------------------------------------------
  CPicker::~CPicker()
  {
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: 
  //-----------------------------------------------------------------------------
  void CPicker::OnKeyCodePressed( KeyCode code )
  {
  	if (( code == KEY_UP ) || ( code == KEY_DOWN ) || ( code == KEY_PAGEUP ) || ( code == KEY_PAGEDOWN ))
  	{
  		KeyValues *pMsg = new KeyValues("KeyCodePressed", "code", code);
  		vgui::ipanel()->SendMessage( m_pPickerBrowser->GetVPanel(), pMsg, GetVPanel());
  		pMsg->deleteThis();
  	}
  	else
  	{
  		BaseClass::OnKeyCodePressed( code );
  	}
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: refreshes the asset list
  //-----------------------------------------------------------------------------
  void CPicker::SetStringList( const PickerList_t &list ) 
  {
  	m_Type = list.m_Type;
  	m_pPickerBrowser->RemoveAll();	
  
  	int nCount = list.Count();
  	for ( int i = 0; i < nCount; ++i )
  	{
  		const char *pPickerName = list[i].m_pChoiceString;
  		KeyValues *kv = new KeyValues( "node", "choice", pPickerName );
  		if ( m_Type == PICKER_CHOICE_STRING )
  		{
  			kv->SetString( "value", list[i].m_pChoiceValue ); 
  		}
  		else
  		{
  			kv->SetPtr( "value", list[i].m_pChoiceValuePtr ); 
  		}
  		int nItemID = m_pPickerBrowser->AddItem( kv, 0, false, false );
  
  		if ( m_Type == PICKER_CHOICE_STRING )
  		{
  			KeyValues *pDrag = new KeyValues( "drag", "text", list[i].m_pChoiceValue );
  			if ( m_pPickerTextType )
  			{
  				pDrag->SetString( "texttype", m_pPickerTextType );
  			}
  			m_pPickerBrowser->SetItemDragData( nItemID, pDrag );
  		}
  	}
  	RefreshChoiceList();
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: refreshes the choice list
  //-----------------------------------------------------------------------------
  void CPicker::RefreshChoiceList( ) 
  {
  	// Check the filter matches
  	int nMatchingCount = 0;
  	int nTotalCount = 0;
  	for ( int nItemID = m_pPickerBrowser->FirstItem(); nItemID != m_pPickerBrowser->InvalidItemID(); nItemID = m_pPickerBrowser->NextItem( nItemID ) )
  	{
  		KeyValues *kv = m_pPickerBrowser->GetItem( nItemID );
  		const char *pPickerName = kv->GetString( "choice" );
  		bool bVisible = !m_Filter.Length() || Q_stristr( pPickerName, m_Filter.Get() );
  		m_pPickerBrowser->SetItemVisible( nItemID, bVisible );
  		if ( bVisible )
  		{
  			++nMatchingCount;
  		}
  		++nTotalCount;
  	}
  
  	char pColumnTitle[512];
  	Q_snprintf( pColumnTitle, sizeof(pColumnTitle), "%s (%d/%d)",
  		m_pPickerType, nMatchingCount, nTotalCount );
  	m_pPickerBrowser->SetColumnHeaderText( 0, pColumnTitle );
  
  	m_pPickerBrowser->SortList();
  	if ( ( m_pPickerBrowser->GetSelectedItemsCount() == 0 ) && ( m_pPickerBrowser->GetItemCount() > 0 ) )
  	{
  		int nItemID = m_pPickerBrowser->GetItemIDFromRow( 0 );
  		m_pPickerBrowser->SetSelectedCell( nItemID, 0 );
  	}
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: refreshes dialog on text changing
  //-----------------------------------------------------------------------------
  void CPicker::OnTextChanged( )
  {
  	int nLength = m_pFilterList->GetTextLength();
  	m_Filter.SetLength( nLength );
  	if ( nLength > 0 )
  	{
  		m_pFilterList->GetText( m_Filter.GetForModify(), nLength+1 );
  	}
  	RefreshChoiceList();
  }
  
  
  //-----------------------------------------------------------------------------
  // Returns the selected string
  //-----------------------------------------------------------------------------
  PickerChoiceType_t CPicker::GetSelectionType() const
  {
  	return m_Type;
  }
  
  const char *CPicker::GetSelectedString( ) const
  {
  	if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
  		return NULL;
  
  	if ( m_Type != PICKER_CHOICE_STRING )
  		return NULL;
  
  	int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
  	KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
  	return pItemKeyValues->GetString( "value" );
  }
  
  void *CPicker::GetSelectedPtr( ) const
  {
  	if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
  		return NULL;
  
  	if ( m_Type != PICKER_CHOICE_PTR )
  		return NULL;
  
  	int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
  	KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
  	return pItemKeyValues->GetPtr( "value" );
  }
  
  
  //-----------------------------------------------------------------------------
  // Returns the index of the selected string
  //-----------------------------------------------------------------------------
  int CPicker::GetSelectedIndex()
  {
  	if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
  		return -1;
  
  	return m_pPickerBrowser->GetSelectedItem( 0 );
  }
  
  	
  //-----------------------------------------------------------------------------
  //
  // Purpose: Modal picker frame
  //
  //-----------------------------------------------------------------------------
  CPickerFrame::CPickerFrame( vgui::Panel *pParent, const char *pTitle, const char *pPickerType, const char *pTextType ) : 
  	BaseClass( pParent, "PickerFrame" )
  {
  	m_pContextKeyValues = NULL;
  	SetDeleteSelfOnClose( true );
  	m_pPicker = new CPicker( this, pPickerType, pTextType );
  	m_pPicker->AddActionSignalTarget( this );
  	m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
  	m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
  	SetBlockDragChaining( true );
  
  	LoadControlSettingsAndUserConfig( "resource/pickerframe.res" );
  
  	SetTitle( pTitle, false );
  }
  
  CPickerFrame::~CPickerFrame()
  {
  	CleanUpMessage();
  }
  
  
  //-----------------------------------------------------------------------------
  // Deletes the message
  //-----------------------------------------------------------------------------
  void CPickerFrame::CleanUpMessage()
  {
  	if ( m_pContextKeyValues )
  	{
  		m_pContextKeyValues->deleteThis();
  		m_pContextKeyValues = NULL;
  	}
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Activate the dialog
  //-----------------------------------------------------------------------------
  void CPickerFrame::DoModal( const PickerList_t &list, KeyValues *pContextKeyValues )
  {
  	CleanUpMessage();
  	m_pContextKeyValues = pContextKeyValues;
   	m_pPicker->SetStringList( list );
  	BaseClass::DoModal();
  }
  
  
  //-----------------------------------------------------------------------------
  // On command
  //-----------------------------------------------------------------------------
  void CPickerFrame::OnCommand( const char *pCommand )
  {
  	if ( !Q_stricmp( pCommand, "Open" ) )
  	{
  		KeyValues *pActionKeys = new KeyValues( "Picked" );
  		pActionKeys->SetInt( "choiceIndex", m_pPicker->GetSelectedIndex( ) );
  
  		if ( m_pPicker->GetSelectionType() == PICKER_CHOICE_STRING )
  		{
  			const char *pPickerName = m_pPicker->GetSelectedString( );
  			pActionKeys->SetString( "choice", pPickerName );
  		}
  		else
  		{
  			void *pPickerPtr = m_pPicker->GetSelectedPtr( );
  			pActionKeys->SetPtr( "choice", pPickerPtr );
  		}
  
  		if ( m_pContextKeyValues )
  		{
  			pActionKeys->AddSubKey( m_pContextKeyValues );
  			m_pContextKeyValues = NULL;
  		}
  		PostActionSignal( pActionKeys );
  		CloseModal();
  		return;
  	}
  
  	if ( !Q_stricmp( pCommand, "Cancel" ) )
  	{
  		CloseModal();
  		return;
  	}
  
  	BaseClass::OnCommand( pCommand );
  }
  
  	
  