aboutsummaryrefslogtreecommitdiff
path: root/mp/src/vgui2/vgui_controls/PropertySheet.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/PropertySheet.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/PropertySheet.cpp')
-rw-r--r--mp/src/vgui2/vgui_controls/PropertySheet.cpp3348
1 files changed, 1674 insertions, 1674 deletions
diff --git a/mp/src/vgui2/vgui_controls/PropertySheet.cpp b/mp/src/vgui2/vgui_controls/PropertySheet.cpp
index b6705b55..18a36ca2 100644
--- a/mp/src/vgui2/vgui_controls/PropertySheet.cpp
+++ b/mp/src/vgui2/vgui_controls/PropertySheet.cpp
@@ -1,1674 +1,1674 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#include <vgui/IBorder.h>
-#include <vgui/IInput.h>
-#include <vgui/IPanel.h>
-#include <vgui/IScheme.h>
-#include <vgui/ISystem.h>
-#include <vgui/IVGui.h>
-#include <vgui/KeyCode.h>
-#include <KeyValues.h>
-#include <vgui/MouseCode.h>
-#include <vgui/ISurface.h>
-#include <vgui_controls/Button.h>
-#include <vgui_controls/Controls.h>
-#include <vgui_controls/Label.h>
-#include <vgui_controls/PropertySheet.h>
-#include <vgui_controls/ComboBox.h>
-#include <vgui_controls/Panel.h>
-#include <vgui_controls/ToolWindow.h>
-#include <vgui_controls/TextImage.h>
-#include <vgui_controls/ImagePanel.h>
-#include <vgui_controls/PropertyPage.h>
-#include "vgui_controls/AnimationController.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include <tier0/memdbgon.h>
-
-using namespace vgui;
-
-namespace vgui
-{
-
-class ContextLabel : public Label
-{
- DECLARE_CLASS_SIMPLE( ContextLabel, Label );
-public:
-
- ContextLabel( Button *parent, char const *panelName, char const *text ):
- BaseClass( (Panel *)parent, panelName, text ),
- m_pTabButton( parent )
- {
- SetBlockDragChaining( true );
- }
-
- virtual void OnMousePressed( MouseCode code )
- {
- if ( m_pTabButton )
- {
- m_pTabButton->FireActionSignal();
- }
- }
-
- virtual void OnMouseReleased( MouseCode code )
- {
- BaseClass::OnMouseReleased( code );
-
- if ( GetParent() )
- {
- GetParent()->OnCommand( "ShowContextMenu" );
- }
- }
-
- virtual void ApplySchemeSettings( IScheme *pScheme )
- {
- BaseClass::ApplySchemeSettings( pScheme );
-
- HFont marlett = pScheme->GetFont( "Marlett" );
- SetFont( marlett );
- SetTextInset( 0, 0 );
- SetContentAlignment( Label::a_northwest );
-
- if ( GetParent() )
- {
- SetFgColor( pScheme->GetColor( "Button.TextColor", GetParent()->GetFgColor() ) );
- SetBgColor( GetParent()->GetBgColor() );
- }
- }
-private:
-
- Button *m_pTabButton;
-};
-
-//-----------------------------------------------------------------------------
-// Purpose: Helper for drag drop
-// Input : msglist -
-// Output : static PropertySheet
-//-----------------------------------------------------------------------------
-static PropertySheet *IsDroppingSheet( CUtlVector< KeyValues * >& msglist )
-{
- if ( msglist.Count() == 0 )
- return NULL;
-
- KeyValues *data = msglist[ 0 ];
- PropertySheet *sheet = reinterpret_cast< PropertySheet * >( data->GetPtr( "propertysheet" ) );
- if ( sheet )
- return sheet;
-
- return NULL;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: A single tab
-//-----------------------------------------------------------------------------
-class PageTab : public Button
-{
- DECLARE_CLASS_SIMPLE( PageTab, Button );
-
-private:
- bool _active;
- Color _textColor;
- Color _dimTextColor;
- int m_bMaxTabWidth;
- IBorder *m_pActiveBorder;
- IBorder *m_pNormalBorder;
- PropertySheet *m_pParent;
- Panel *m_pPage;
- ImagePanel *m_pImage;
- char *m_pszImageName;
- bool m_bShowContextLabel;
- bool m_bAttemptingDrop;
- ContextLabel *m_pContextLabel;
- long m_hoverActivatePageTime;
- long m_dropHoverTime;
-
-public:
- PageTab(PropertySheet *parent, const char *panelName, const char *text, char const *imageName, int maxTabWidth, Panel *page, bool showContextButton, long hoverActivatePageTime = -1 ) :
- Button( (Panel *)parent, panelName, text),
- m_pParent( parent ),
- m_pPage( page ),
- m_pImage( 0 ),
- m_pszImageName( 0 ),
- m_bShowContextLabel( showContextButton ),
- m_bAttemptingDrop( false ),
- m_hoverActivatePageTime( hoverActivatePageTime ),
- m_dropHoverTime( -1 )
- {
- SetCommand(new KeyValues("TabPressed"));
- _active = false;
- m_bMaxTabWidth = maxTabWidth;
- SetDropEnabled( true );
- SetDragEnabled( m_pParent->IsDraggableTab() );
- if ( imageName )
- {
- m_pImage = new ImagePanel( this, text );
- int buflen = Q_strlen( imageName ) + 1;
- m_pszImageName = new char[ buflen ];
- Q_strncpy( m_pszImageName, imageName, buflen );
-
- }
- SetMouseClickEnabled( MOUSE_RIGHT, true );
- m_pContextLabel = m_bShowContextLabel ? new ContextLabel( this, "Context", "9" ) : NULL;
-
- REGISTER_COLOR_AS_OVERRIDABLE( _textColor, "selectedcolor" );
- REGISTER_COLOR_AS_OVERRIDABLE( _dimTextColor, "unselectedcolor" );
- }
-
- ~PageTab()
- {
- delete[] m_pszImageName;
- }
-
- virtual void Paint()
- {
- BaseClass::Paint();
- }
-
- virtual void OnCursorEntered()
- {
- m_dropHoverTime = system()->GetTimeMillis();
- }
-
- virtual void OnCursorExited()
- {
- m_dropHoverTime = -1;
- }
-
- virtual void OnThink()
- {
- if ( m_bAttemptingDrop && m_hoverActivatePageTime >= 0 && m_dropHoverTime >= 0 )
- {
- long hoverTime = system()->GetTimeMillis() - m_dropHoverTime;
- if ( hoverTime > m_hoverActivatePageTime )
- {
- FireActionSignal();
- SetSelected(true);
- Repaint();
- }
- }
- m_bAttemptingDrop = false;
-
- BaseClass::OnThink();
- }
-
- virtual bool IsDroppable( CUtlVector< KeyValues * >&msglist )
- {
- m_bAttemptingDrop = true;
-
- if ( !GetParent() )
- return false;
-
- PropertySheet *sheet = IsDroppingSheet( msglist );
- if ( sheet )
- return GetParent()->IsDroppable( msglist );
-
- return BaseClass::IsDroppable( msglist );
- }
-
- virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
- {
- PropertySheet *sheet = IsDroppingSheet( msglist );
- if ( sheet )
- {
- Panel *target = GetParent()->GetDropTarget( msglist );
- if ( target )
- {
- // Fixme, mouse pos could be wrong...
- target->OnDroppablePanelPaint( msglist, dragPanels );
- return;
- }
- }
-
- // Just highlight the tab if dropping onto active page via the tab
- BaseClass::OnDroppablePanelPaint( msglist, dragPanels );
- }
-
- virtual void OnPanelDropped( CUtlVector< KeyValues * >& msglist )
- {
- PropertySheet *sheet = IsDroppingSheet( msglist );
- if ( sheet )
- {
- Panel *target = GetParent()->GetDropTarget( msglist );
- if ( target )
- {
- // Fixme, mouse pos could be wrong...
- target->OnPanelDropped( msglist );
- }
- }
-
- // Defer to active page...
- Panel *active = m_pParent->GetActivePage();
- if ( !active || !active->IsDroppable( msglist ) )
- return;
-
- active->OnPanelDropped( msglist );
- }
-
- virtual void OnDragFailed( CUtlVector< KeyValues * >& msglist )
- {
- PropertySheet *sheet = IsDroppingSheet( msglist );
- if ( !sheet )
- return;
-
- // Create a new property sheet
- if ( m_pParent->IsDraggableTab() )
- {
- if ( msglist.Count() == 1 )
- {
- KeyValues *data = msglist[ 0 ];
- int screenx = data->GetInt( "screenx" );
- int screeny = data->GetInt( "screeny" );
-
- // m_pParent->ScreenToLocal( screenx, screeny );
- if ( !m_pParent->IsWithin( screenx, screeny ) )
- {
- Panel *page = reinterpret_cast< Panel * >( data->GetPtr( "propertypage" ) );
- PropertySheet *sheet = reinterpret_cast< PropertySheet * >( data->GetPtr( "propertysheet" ) );
- char const *title = data->GetString( "tabname", "" );
- if ( !page || !sheet )
- return;
-
- // Can only create if sheet was part of a ToolWindow derived object
- ToolWindow *tw = dynamic_cast< ToolWindow * >( sheet->GetParent() );
- if ( tw )
- {
- IToolWindowFactory *factory = tw->GetToolWindowFactory();
- if ( factory )
- {
- bool hasContextMenu = sheet->PageHasContextMenu( page );
- sheet->RemovePage( page );
- factory->InstanceToolWindow( tw->GetParent(), sheet->ShouldShowContextButtons(), page, title, hasContextMenu );
-
- if ( sheet->GetNumPages() == 0 )
- {
- tw->MarkForDeletion();
- }
- }
- }
- }
- }
- }
- }
-
- virtual void OnCreateDragData( KeyValues *msg )
- {
- Assert( m_pParent->IsDraggableTab() );
-
- msg->SetPtr( "propertypage", m_pPage );
- msg->SetPtr( "propertysheet", m_pParent );
- char sz[ 256 ];
- GetText( sz, sizeof( sz ) );
- msg->SetString( "tabname", sz );
- msg->SetString( "text", sz );
- }
-
- virtual void ApplySchemeSettings(IScheme *pScheme)
- {
- // set up the scheme settings
- Button::ApplySchemeSettings(pScheme);
-
- _textColor = GetSchemeColor("PropertySheet.SelectedTextColor", GetFgColor(), pScheme);
- _dimTextColor = GetSchemeColor("PropertySheet.TextColor", GetFgColor(), pScheme);
- m_pActiveBorder = pScheme->GetBorder("TabActiveBorder");
- m_pNormalBorder = pScheme->GetBorder("TabBorder");
-
- if ( m_pImage )
- {
- ClearImages();
- m_pImage->SetImage(scheme()->GetImage(m_pszImageName, false));
- AddImage( m_pImage->GetImage(), 2 );
- int w, h;
- m_pImage->GetSize( w, h );
- w += m_pContextLabel ? 10 : 0;
- if ( m_pContextLabel )
- {
- m_pImage->SetPos( 10, 0 );
- }
- SetSize( w + 4, h + 2 );
- }
- else
- {
- int wide, tall;
- int contentWide, contentTall;
- GetSize(wide, tall);
- GetContentSize(contentWide, contentTall);
-
- wide = max(m_bMaxTabWidth, contentWide + 10); // 10 = 5 pixels margin on each side
- wide += m_pContextLabel ? 10 : 0;
- SetSize(wide, tall);
- }
-
- if ( m_pContextLabel )
- {
- SetTextInset( 12, 0 );
- }
- }
-
- virtual void ApplySettings( KeyValues *inResourceData )
- {
- const char *pBorder = inResourceData->GetString("activeborder_override", "");
- if (*pBorder)
- {
- m_pActiveBorder = scheme()->GetIScheme(GetScheme())->GetBorder( pBorder );
- }
- pBorder = inResourceData->GetString("normalborder_override", "");
- if (*pBorder)
- {
- m_pNormalBorder = scheme()->GetIScheme(GetScheme())->GetBorder( pBorder );
- }
- BaseClass::ApplySettings(inResourceData);
- }
-
- virtual void OnCommand( char const *cmd )
- {
- if ( !Q_stricmp( cmd, "ShowContextMenu" ) )
- {
- KeyValues *kv = new KeyValues("OpenContextMenu");
- kv->SetPtr( "page", m_pPage );
- kv->SetPtr( "contextlabel", m_pContextLabel );
- PostActionSignal( kv );
- return;
- }
- BaseClass::OnCommand( cmd );
- }
-
- IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
- {
- if (_active)
- {
- return m_pActiveBorder;
- }
- return m_pNormalBorder;
- }
-
- virtual Color GetButtonFgColor()
- {
- if (_active)
- {
- return _textColor;
- }
- else
- {
- return _dimTextColor;
- }
- }
-
- virtual void SetActive(bool state)
- {
- _active = state;
- SetZPos( state ? 100 : 0 );
- InvalidateLayout();
- Repaint();
- }
-
- virtual void SetTabWidth( int iWidth )
- {
- m_bMaxTabWidth = iWidth;
- InvalidateLayout();
- }
-
- virtual bool CanBeDefaultButton(void)
- {
- return false;
- }
-
- //Fire action signal when mouse is pressed down instead of on release.
- virtual void OnMousePressed(MouseCode code)
- {
- // check for context menu open
- if (!IsEnabled())
- return;
-
- if (!IsMouseClickEnabled(code))
- return;
-
- if (IsUseCaptureMouseEnabled())
- {
- {
- RequestFocus();
- FireActionSignal();
- SetSelected(true);
- Repaint();
- }
-
- // lock mouse input to going to this button
- input()->SetMouseCapture(GetVPanel());
- }
- }
-
- virtual void OnMouseReleased(MouseCode code)
- {
- // ensure mouse capture gets released
- if (IsUseCaptureMouseEnabled())
- {
- input()->SetMouseCapture(NULL);
- }
-
- // make sure the button gets unselected
- SetSelected(false);
- Repaint();
-
- if (code == MOUSE_RIGHT)
- {
- KeyValues *kv = new KeyValues("OpenContextMenu");
- kv->SetPtr( "page", m_pPage );
- kv->SetPtr( "contextlabel", m_pContextLabel );
- PostActionSignal( kv );
- }
- }
-
- virtual void PerformLayout()
- {
- BaseClass::PerformLayout();
-
- if ( m_pContextLabel )
- {
- int w, h;
- GetSize( w, h );
- m_pContextLabel->SetBounds( 0, 0, 10, h );
- }
- }
-};
-
-
-}; // namespace vgui
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-//-----------------------------------------------------------------------------
-PropertySheet::PropertySheet(
- Panel *parent,
- const char *panelName,
- bool draggableTabs /*= false*/ ) : BaseClass(parent, panelName)
-{
- _activePage = NULL;
- _activeTab = NULL;
- _tabWidth = 64;
- _activeTabIndex = 0;
- _showTabs = true;
- _combo = NULL;
- _tabFocus = false;
- m_flPageTransitionEffectTime = 0.0f;
- m_bSmallTabs = false;
- m_tabFont = 0;
- m_bDraggableTabs = draggableTabs;
- m_pTabKV = NULL;
- m_iTabHeight = 0;
- m_iTabHeightSmall = 0;
-
- if ( m_bDraggableTabs )
- {
- SetDropEnabled( true );
- }
-
- m_bKBNavigationEnabled = true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor, associates pages with a combo box
-//-----------------------------------------------------------------------------
-PropertySheet::PropertySheet(Panel *parent, const char *panelName, ComboBox *combo) : BaseClass(parent, panelName)
-{
- _activePage = NULL;
- _activeTab = NULL;
- _tabWidth = 64;
- _activeTabIndex = 0;
- _combo=combo;
- _combo->AddActionSignalTarget(this);
- _showTabs = false;
- _tabFocus = false;
- m_flPageTransitionEffectTime = 0.0f;
- m_bSmallTabs = false;
- m_tabFont = 0;
- m_bDraggableTabs = false;
- m_pTabKV = NULL;
- m_iTabHeight = 0;
- m_iTabHeightSmall = 0;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Destructor
-//-----------------------------------------------------------------------------
-PropertySheet::~PropertySheet()
-{
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: ToolWindow uses this to drag tools from container to container by dragging the tab
-// Input : -
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool PropertySheet::IsDraggableTab() const
-{
- return m_bDraggableTabs;
-}
-
-void PropertySheet::SetDraggableTabs( bool state )
-{
- m_bDraggableTabs = state;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Lower profile tabs
-// Input : state -
-//-----------------------------------------------------------------------------
-void PropertySheet::SetSmallTabs( bool state )
-{
- m_bSmallTabs = state;
- m_tabFont = scheme()->GetIScheme( GetScheme() )->GetFont( m_bSmallTabs ? "DefaultVerySmall" : "Default" );
- int c = m_PageTabs.Count();
- for ( int i = 0; i < c ; ++i )
- {
- PageTab *tab = m_PageTabs[ i ];
- Assert( tab );
- tab->SetFont( m_tabFont );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : -
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool PropertySheet::IsSmallTabs() const
-{
- return m_bSmallTabs;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : state -
-//-----------------------------------------------------------------------------
-void PropertySheet::ShowContextButtons( bool state )
-{
- m_bContextButton = state;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : -
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool PropertySheet::ShouldShowContextButtons() const
-{
- return m_bContextButton;
-}
-
-int PropertySheet::FindPage( Panel *page ) const
-{
- int c = m_Pages.Count();
- for ( int i = 0; i < c; ++i )
- {
- if ( m_Pages[ i ].page == page )
- return i;
- }
-
- return m_Pages.InvalidIndex();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: adds a page to the sheet
-//-----------------------------------------------------------------------------
-void PropertySheet::AddPage(Panel *page, const char *title, char const *imageName /*= NULL*/, bool bHasContextMenu /*= false*/ )
-{
- if (!page)
- return;
-
- // don't add the page if we already have it
- if ( FindPage( page ) != m_Pages.InvalidIndex() )
- return;
-
- long hoverActivatePageTime = 250;
- PageTab *tab = new PageTab(this, "tab", title, imageName, _tabWidth, page, m_bContextButton && bHasContextMenu, hoverActivatePageTime );
- if ( m_bDraggableTabs )
- {
- tab->SetDragEnabled( true );
- }
-
- tab->SetFont( m_tabFont );
- if(_showTabs)
- {
- tab->AddActionSignalTarget(this);
- }
- else if (_combo)
- {
- _combo->AddItem(title, NULL);
- }
-
- if ( m_pTabKV )
- {
- tab->ApplySettings( m_pTabKV );
- }
-
- m_PageTabs.AddToTail(tab);
-
- Page_t info;
- info.page = page;
- info.contextMenu = m_bContextButton && bHasContextMenu;
-
- m_Pages.AddToTail( info );
-
- page->SetParent(this);
- page->AddActionSignalTarget(this);
- PostMessage(page, new KeyValues("ResetData"));
-
- page->SetVisible(false);
- InvalidateLayout();
-
- if (!_activePage)
- {
- // first page becomes the active page
- ChangeActiveTab( 0 );
- if ( _activePage )
- {
- _activePage->RequestFocus( 0 );
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::SetActivePage(Panel *page)
-{
- // walk the list looking for this page
- int index = FindPage( page );
- if (!m_Pages.IsValidIndex(index))
- return;
-
- ChangeActiveTab(index);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::SetTabWidth(int pixels)
-{
- if ( pixels < 0 )
- {
- if( !_activeTab )
- return;
-
- int nTall;
- _activeTab->GetContentSize( pixels, nTall );
- }
-
- if ( _tabWidth == pixels )
- return;
-
- _tabWidth = pixels;
- InvalidateLayout();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: reloads the data in all the property page
-//-----------------------------------------------------------------------------
-void PropertySheet::ResetAllData()
-{
- // iterate all the dialogs resetting them
- for (int i = 0; i < m_Pages.Count(); i++)
- {
- ipanel()->SendMessage(m_Pages[i].page->GetVPanel(), new KeyValues("ResetData"), GetVPanel());
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Applies any changes made by the dialog
-//-----------------------------------------------------------------------------
-void PropertySheet::ApplyChanges()
-{
- // iterate all the dialogs resetting them
- for (int i = 0; i < m_Pages.Count(); i++)
- {
- ipanel()->SendMessage(m_Pages[i].page->GetVPanel(), new KeyValues("ApplyChanges"), GetVPanel());
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: gets a pointer to the currently active page
-//-----------------------------------------------------------------------------
-Panel *PropertySheet::GetActivePage()
-{
- return _activePage;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: gets a pointer to the currently active tab
-//-----------------------------------------------------------------------------
-Panel *PropertySheet::GetActiveTab()
-{
- return _activeTab;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: returns the number of panels in the sheet
-//-----------------------------------------------------------------------------
-int PropertySheet::GetNumPages()
-{
- return m_Pages.Count();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: returns the name contained in the active tab
-// Input : a text buffer to contain the output
-//-----------------------------------------------------------------------------
-void PropertySheet::GetActiveTabTitle (char *textOut, int bufferLen )
-{
- if(_activeTab) _activeTab->GetText(textOut, bufferLen);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: returns the name contained in the active tab
-// Input : a text buffer to contain the output
-//-----------------------------------------------------------------------------
-bool PropertySheet::GetTabTitle( int i, char *textOut, int bufferLen )
-{
- if ( i < 0 || i >= m_PageTabs.Count() )
- {
- return false;
- }
-
- m_PageTabs[i]->GetText(textOut, bufferLen);
- return true;
-}
-
-bool PropertySheet::SetTabTitle( int i, char *pchTitle )
-{
- if ( i < 0 || i >= m_PageTabs.Count() )
- {
- return false;
- }
-
- m_PageTabs[ i ]->SetText( pchTitle );
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the index of the currently active page
-//-----------------------------------------------------------------------------
-int PropertySheet::GetActivePageNum()
-{
- for (int i = 0; i < m_Pages.Count(); i++)
- {
- if (m_Pages[i].page == _activePage)
- {
- return i;
- }
- }
- return -1;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Forwards focus requests to current active page
-//-----------------------------------------------------------------------------
-void PropertySheet::RequestFocus(int direction)
-{
- if (direction == -1 || direction == 0)
- {
- if (_activePage)
- {
- _activePage->RequestFocus(direction);
- _tabFocus = false;
- }
- }
- else
- {
- if (_showTabs && _activeTab)
- {
- _activeTab->RequestFocus(direction);
- _tabFocus = true;
- }
- else if (_activePage)
- {
- _activePage->RequestFocus(direction);
- _tabFocus = false;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: moves focus back
-//-----------------------------------------------------------------------------
-bool PropertySheet::RequestFocusPrev(VPANEL panel)
-{
- if (_tabFocus || !_showTabs || !_activeTab)
- {
- _tabFocus = false;
- return BaseClass::RequestFocusPrev(panel);
- }
- else
- {
- if (GetVParent())
- {
- PostMessage(GetVParent(), new KeyValues("FindDefaultButton"));
- }
- _activeTab->RequestFocus(-1);
- _tabFocus = true;
- return true;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: moves focus forward
-//-----------------------------------------------------------------------------
-bool PropertySheet::RequestFocusNext(VPANEL panel)
-{
- if (!_tabFocus || !_activePage)
- {
- return BaseClass::RequestFocusNext(panel);
- }
- else
- {
- if (!_activeTab)
- {
- return BaseClass::RequestFocusNext(panel);
- }
- else
- {
- _activePage->RequestFocus(1);
- _tabFocus = false;
- return true;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Gets scheme settings
-//-----------------------------------------------------------------------------
-void PropertySheet::ApplySchemeSettings(IScheme *pScheme)
-{
- BaseClass::ApplySchemeSettings(pScheme);
-
- // a little backwards-compatibility with old scheme files
- IBorder *pBorder = pScheme->GetBorder("PropertySheetBorder");
- if (pBorder == pScheme->GetBorder("Default"))
- {
- // get the old name
- pBorder = pScheme->GetBorder("RaisedBorder");
- }
-
- SetBorder(pBorder);
- m_flPageTransitionEffectTime = atof(pScheme->GetResourceString("PropertySheet.TransitionEffectTime"));
-
- m_tabFont = pScheme->GetFont( m_bSmallTabs ? "DefaultVerySmall" : "Default" );
-
- if ( m_pTabKV )
- {
- for (int i = 0; i < m_PageTabs.Count(); i++)
- {
- m_PageTabs[i]->ApplySettings( m_pTabKV );
- }
- }
-
-
- //=============================================================================
- // HPE_BEGIN:
- // [tj] Here, we used to use a single size variable and overwrite it when we scaled.
- // This led to problems when we changes resolutions, so now we recalcuate the absolute
- // size from the relative size each time (based on proportionality)
- //=============================================================================
- if ( IsProportional() )
- {
- m_iTabHeight = scheme()->GetProportionalScaledValueEx( GetScheme(), m_iSpecifiedTabHeight );
- m_iTabHeightSmall = scheme()->GetProportionalScaledValueEx( GetScheme(), m_iSpecifiedTabHeightSmall );
- }
- else
- {
- m_iTabHeight = m_iSpecifiedTabHeight;
- m_iTabHeightSmall = m_iSpecifiedTabHeightSmall;
- }
- //=============================================================================
- // HPE_END
- //=============================================================================
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::ApplySettings(KeyValues *inResourceData)
-{
- BaseClass::ApplySettings(inResourceData);
-
- KeyValues *pTabKV = inResourceData->FindKey( "tabskv" );
- if ( pTabKV )
- {
- if ( m_pTabKV )
- {
- m_pTabKV->deleteThis();
- }
- m_pTabKV = new KeyValues("tabkv");
- pTabKV->CopySubkeys( m_pTabKV );
- }
-
- KeyValues *pTabWidthKV = inResourceData->FindKey( "tabwidth" );
- if ( pTabWidthKV )
- {
- _tabWidth = scheme()->GetProportionalScaledValueEx(GetScheme(), pTabWidthKV->GetInt());
- for (int i = 0; i < m_PageTabs.Count(); i++)
- {
- m_PageTabs[i]->SetTabWidth( _tabWidth );
- }
- }
-
- KeyValues *pTransitionKV = inResourceData->FindKey( "transition_time" );
- if ( pTransitionKV )
- {
- m_flPageTransitionEffectTime = pTransitionKV->GetFloat();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Paint our border specially, with the tabs in mind
-//-----------------------------------------------------------------------------
-void PropertySheet::PaintBorder()
-{
- IBorder *border = GetBorder();
- if (!border)
- return;
-
- // draw the border, but with a break at the active tab
- int px = 0, py = 0, pwide = 0, ptall = 0;
- if (_activeTab)
- {
- _activeTab->GetBounds(px, py, pwide, ptall);
- ptall -= 1;
- }
-
- // draw the border underneath the buttons, with a break
- int wide, tall;
- GetSize(wide, tall);
- border->Paint(0, py + ptall, wide, tall, IBorder::SIDE_TOP, px + 1, px + pwide - 1);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Lays out the dialog
-//-----------------------------------------------------------------------------
-void PropertySheet::PerformLayout()
-{
- BaseClass::PerformLayout();
-
- int x, y, wide, tall;
- GetBounds(x, y, wide, tall);
- if (_activePage)
- {
- int tabHeight = IsSmallTabs() ? m_iTabHeightSmall : m_iTabHeight;
-
- if(_showTabs)
- {
- _activePage->SetBounds(0, tabHeight, wide, tall - tabHeight);
- }
- else
- {
- _activePage->SetBounds(0, 0, wide, tall );
- }
- _activePage->InvalidateLayout();
- }
-
-
- int xtab;
- int limit = m_PageTabs.Count();
-
- xtab = m_iTabXIndent;
-
- // draw the visible tabs
- if (_showTabs)
- {
- for (int i = 0; i < limit; i++)
- {
- int tabHeight = IsSmallTabs() ? (m_iTabHeightSmall-1) : (m_iTabHeight-1);
-
- int width, tall;
- m_PageTabs[i]->GetSize(width, tall);
-
- if ( m_bTabFitText )
- {
- m_PageTabs[i]->SizeToContents();
- width = m_PageTabs[i]->GetWide();
-
- int iXInset, iYInset;
- m_PageTabs[i]->GetTextInset( &iXInset, &iYInset );
- width += (iXInset * 2);
- }
-
- if (m_PageTabs[i] == _activeTab)
- {
- // active tab is taller
- _activeTab->SetBounds(xtab, 2, width, tabHeight);
- }
- else
- {
- m_PageTabs[i]->SetBounds(xtab, 4, width, tabHeight - 2);
- }
- m_PageTabs[i]->SetVisible(true);
- xtab += (width + 1) + m_iTabXDelta;
- }
- }
- else
- {
- for (int i = 0; i < limit; i++)
- {
- m_PageTabs[i]->SetVisible(false);
- }
- }
-
- // ensure draw order (page drawing over all the tabs except one)
- if (_activePage)
- {
- _activePage->MoveToFront();
- _activePage->Repaint();
- }
- if (_activeTab)
- {
- _activeTab->MoveToFront();
- _activeTab->Repaint();
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Switches the active panel
-//-----------------------------------------------------------------------------
-void PropertySheet::OnTabPressed(Panel *panel)
-{
- // look for the tab in the list
- for (int i = 0; i < m_PageTabs.Count(); i++)
- {
- if (m_PageTabs[i] == panel)
- {
- // flip to the new tab
- ChangeActiveTab(i);
- return;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: returns the panel associated with index i
-// Input : the index of the panel to return
-//-----------------------------------------------------------------------------
-Panel *PropertySheet::GetPage(int i)
-{
- if(i<0 || i>=m_Pages.Count())
- {
- return NULL;
- }
-
- return m_Pages[i].page;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: disables page by name
-//-----------------------------------------------------------------------------
-void PropertySheet::DisablePage(const char *title)
-{
- SetPageEnabled(title, false);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: enables page by name
-//-----------------------------------------------------------------------------
-void PropertySheet::EnablePage(const char *title)
-{
- SetPageEnabled(title, true);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: enabled or disables page by name
-//-----------------------------------------------------------------------------
-void PropertySheet::SetPageEnabled(const char *title, bool state)
-{
- for (int i = 0; i < m_PageTabs.Count(); i++)
- {
- if (_showTabs)
- {
- char tmp[50];
- m_PageTabs[i]->GetText(tmp,50);
- if (!strnicmp(title,tmp,strlen(tmp)))
- {
- m_PageTabs[i]->SetEnabled(state);
- }
- }
- else
- {
- _combo->SetItemEnabled(title,state);
- }
- }
-}
-
-void PropertySheet::RemoveAllPages()
-{
- int c = m_Pages.Count();
- for ( int i = c - 1; i >= 0 ; --i )
- {
- RemovePage( m_Pages[ i ].page );
- }
-}
-
-void PropertySheet::DeleteAllPages()
-{
- int c = m_Pages.Count();
- for ( int i = c - 1; i >= 0 ; --i )
- {
- DeletePage( m_Pages[ i ].page );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: deletes the page associated with panel
-// Input : *panel - the panel of the page to remove
-//-----------------------------------------------------------------------------
-void PropertySheet::RemovePage(Panel *panel)
-{
- int location = FindPage( panel );
- if ( location == m_Pages.InvalidIndex() )
- return;
-
- // Since it's being deleted, don't animate!!!
- m_hPreviouslyActivePage = NULL;
- _activeTab = NULL;
-
- // ASSUMPTION = that the number of pages equals number of tabs
- if( _showTabs )
- {
- m_PageTabs[location]->RemoveActionSignalTarget( this );
- }
- // now remove the tab
- PageTab *tab = m_PageTabs[ location ];
- m_PageTabs.Remove( location );
- tab->MarkForDeletion();
-
- // Remove from page list
- m_Pages.Remove( location );
-
- // Unparent
- panel->SetParent( (Panel *)NULL );
-
- if ( _activePage == panel )
- {
- _activePage = NULL;
- // if this page is currently active, backup to the page before this.
- ChangeActiveTab( max( location - 1, 0 ) );
- }
-
- PerformLayout();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: deletes the page associated with panel
-// Input : *panel - the panel of the page to remove
-//-----------------------------------------------------------------------------
-void PropertySheet::DeletePage(Panel *panel)
-{
- Assert( panel );
- RemovePage( panel );
- panel->MarkForDeletion();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: flips to the new tab, sending out all the right notifications
-// flipping to a tab activates the tab.
-//-----------------------------------------------------------------------------
-void PropertySheet::ChangeActiveTab( int index )
-{
- if ( !m_Pages.IsValidIndex( index ) )
- {
- _activeTab = NULL;
- if ( m_Pages.Count() > 0 )
- {
- _activePage = NULL;
-
- if ( index < 0 )
- {
- ChangeActiveTab( m_Pages.Count() - 1 );
- }
- else
- {
- ChangeActiveTab( 0 );
- }
- }
- return;
- }
-
- if ( m_Pages[index].page == _activePage )
- {
- if ( _activeTab )
- {
- _activeTab->RequestFocus();
- }
- _tabFocus = true;
- return;
- }
-
- int c = m_Pages.Count();
- for ( int i = 0; i < c; ++i )
- {
- m_Pages[ i ].page->SetVisible( false );
- }
-
- m_hPreviouslyActivePage = _activePage;
- // notify old page
- if (_activePage)
- {
- ivgui()->PostMessage(_activePage->GetVPanel(), new KeyValues("PageHide"), GetVPanel());
- KeyValues *msg = new KeyValues("PageTabActivated");
- msg->SetPtr("panel", (Panel *)NULL);
- ivgui()->PostMessage(_activePage->GetVPanel(), msg, GetVPanel());
- }
- if (_activeTab)
- {
- //_activeTabIndex=index;
- _activeTab->SetActive(false);
-
- // does the old tab have the focus?
- _tabFocus = _activeTab->HasFocus();
- }
- else
- {
- _tabFocus = false;
- }
-
- // flip page
- _activePage = m_Pages[index].page;
- _activeTab = m_PageTabs[index];
- _activeTabIndex = index;
-
- _activePage->SetVisible(true);
- _activePage->MoveToFront();
-
- _activeTab->SetVisible(true);
- _activeTab->MoveToFront();
- _activeTab->SetActive(true);
-
- if (_tabFocus)
- {
- // if a tab already has focused,give the new tab the focus
- _activeTab->RequestFocus();
- }
- else
- {
- // otherwise, give the focus to the page
- _activePage->RequestFocus();
- }
-
- if (!_showTabs)
- {
- _combo->ActivateItemByRow(index);
- }
-
- _activePage->MakeReadyForUse();
-
- // transition effect
- if (m_flPageTransitionEffectTime)
- {
- if (m_hPreviouslyActivePage.Get())
- {
- // fade out the previous page
- GetAnimationController()->RunAnimationCommand(m_hPreviouslyActivePage, "Alpha", 0.0f, 0.0f, m_flPageTransitionEffectTime / 2, AnimationController::INTERPOLATOR_LINEAR);
- }
-
- // fade in the new page
- _activePage->SetAlpha(0);
- GetAnimationController()->RunAnimationCommand(_activePage, "Alpha", 255.0f, m_flPageTransitionEffectTime / 2, m_flPageTransitionEffectTime / 2, AnimationController::INTERPOLATOR_LINEAR);
- }
- else
- {
- if (m_hPreviouslyActivePage.Get())
- {
- // no transition, just hide the previous page
- m_hPreviouslyActivePage->SetVisible(false);
- }
- _activePage->SetAlpha( 255 );
- }
-
- // notify
- ivgui()->PostMessage(_activePage->GetVPanel(), new KeyValues("PageShow"), GetVPanel());
-
- KeyValues *msg = new KeyValues("PageTabActivated");
- msg->SetPtr("panel", (Panel *)_activeTab);
- ivgui()->PostMessage(_activePage->GetVPanel(), msg, GetVPanel());
-
- // tell parent
- PostActionSignal(new KeyValues("PageChanged"));
-
- // Repaint
- InvalidateLayout();
- Repaint();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Gets the panel with the specified hotkey, from the current page
-//-----------------------------------------------------------------------------
-Panel *PropertySheet::HasHotkey(wchar_t key)
-{
- if (!_activePage)
- return NULL;
-
- for (int i = 0; i < _activePage->GetChildCount(); i++)
- {
- Panel *hot = _activePage->GetChild(i)->HasHotkey(key);
- if (hot)
- {
- return hot;
- }
- }
-
- return NULL;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: catches the opencontextmenu event
-//-----------------------------------------------------------------------------
-void PropertySheet::OnOpenContextMenu( KeyValues *params )
-{
- // tell parent
- KeyValues *kv = params->MakeCopy();
- PostActionSignal( kv );
- Panel *page = reinterpret_cast< Panel * >( params->GetPtr( "page" ) );
- if ( page )
- {
- PostMessage( page->GetVPanel(), params->MakeCopy() );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Handle key presses, through tabs.
-//-----------------------------------------------------------------------------
-void PropertySheet::OnKeyCodePressed(KeyCode code)
-{
- bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
- bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
- bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
-
- if ( ctrl && shift && alt && code == KEY_B )
- {
- // enable build mode
- EditablePanel *ep = dynamic_cast< EditablePanel * >( GetActivePage() );
- if ( ep )
- {
- ep->ActivateBuildMode();
- return;
- }
- }
-
- if ( IsKBNavigationEnabled() )
- {
- ButtonCode_t nButtonCode = GetBaseButtonCode( code );
-
- switch ( nButtonCode )
- {
- // for now left and right arrows just open or close submenus if they are there.
- case KEY_RIGHT:
- case KEY_XBUTTON_RIGHT:
- case KEY_XSTICK1_RIGHT:
- case KEY_XSTICK2_RIGHT:
- {
- ChangeActiveTab(_activeTabIndex+1);
- break;
- }
- case KEY_LEFT:
- case KEY_XBUTTON_LEFT:
- case KEY_XSTICK1_LEFT:
- case KEY_XSTICK2_LEFT:
- {
- ChangeActiveTab(_activeTabIndex-1);
- break;
- }
- default:
- BaseClass::OnKeyCodePressed(code);
- break;
- }
- }
- else
- {
- BaseClass::OnKeyCodePressed(code);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called by the associated combo box (if in that mode), changes the current panel
-//-----------------------------------------------------------------------------
-void PropertySheet::OnTextChanged(Panel *panel,const wchar_t *wszText)
-{
- if ( panel == _combo )
- {
- wchar_t tabText[30];
- for(int i = 0 ; i < m_PageTabs.Count() ; i++ )
- {
- tabText[0] = 0;
- m_PageTabs[i]->GetText(tabText,30);
- if ( !wcsicmp(wszText,tabText) )
- {
- ChangeActiveTab(i);
- }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::OnCommand(const char *command)
-{
- // propogate the close command to our parent
- if (!stricmp(command, "Close") && GetVParent())
- {
- CallParentFunction(new KeyValues("Command", "command", command));
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::OnApplyButtonEnable()
-{
- // tell parent
- PostActionSignal(new KeyValues("ApplyButtonEnable"));
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::OnCurrentDefaultButtonSet( vgui::VPANEL defaultButton )
-{
- // forward the message up
- if (GetVParent())
- {
- KeyValues *msg = new KeyValues("CurrentDefaultButtonSet");
- msg->SetInt("button", ivgui()->PanelToHandle( defaultButton ) );
- PostMessage(GetVParent(), msg);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::OnDefaultButtonSet( VPANEL defaultButton )
-{
- // forward the message up
- if (GetVParent())
- {
- KeyValues *msg = new KeyValues("DefaultButtonSet");
- msg->SetInt("button", ivgui()->PanelToHandle( defaultButton ) );
- PostMessage(GetVParent(), msg);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void PropertySheet::OnFindDefaultButton()
-{
- if (GetVParent())
- {
- PostMessage(GetVParent(), new KeyValues("FindDefaultButton"));
- }
-}
-
-bool PropertySheet::PageHasContextMenu( Panel *page ) const
-{
- int pageNum = FindPage( page );
- if ( pageNum == m_Pages.InvalidIndex() )
- return false;
-
- return m_Pages[ pageNum ].contextMenu;
-}
-
-void PropertySheet::OnPanelDropped( CUtlVector< KeyValues * >& msglist )
-{
- if ( msglist.Count() != 1 )
- {
- return;
- }
-
- PropertySheet *sheet = IsDroppingSheet( msglist );
- if ( !sheet )
- {
- // Defer to active page
- if ( _activePage && _activePage->IsDropEnabled() )
- {
- return _activePage->OnPanelDropped( msglist );
- }
- return;
- }
-
- KeyValues *data = msglist[ 0 ];
-
- Panel *page = reinterpret_cast< Panel * >( data->GetPtr( "propertypage" ) );
- char const *title = data->GetString( "tabname", "" );
- if ( !page || !sheet )
- return;
-
- // Can only create if sheet was part of a ToolWindow derived object
- ToolWindow *tw = dynamic_cast< ToolWindow * >( sheet->GetParent() );
- if ( tw )
- {
- IToolWindowFactory *factory = tw->GetToolWindowFactory();
- if ( factory )
- {
- bool showContext = sheet->PageHasContextMenu( page );
- sheet->RemovePage( page );
- if ( sheet->GetNumPages() == 0 )
- {
- tw->MarkForDeletion();
- }
-
- AddPage( page, title, NULL, showContext );
- }
- }
-}
-
-bool PropertySheet::IsDroppable( CUtlVector< KeyValues * >& msglist )
-{
- if ( !m_bDraggableTabs )
- return false;
-
- if ( msglist.Count() != 1 )
- {
- return false;
- }
-
- int mx, my;
- input()->GetCursorPos( mx, my );
- ScreenToLocal( mx, my );
-
- int tabHeight = IsSmallTabs() ? m_iTabHeightSmall : m_iTabHeight;
- if ( my > tabHeight )
- return false;
-
- PropertySheet *sheet = IsDroppingSheet( msglist );
- if ( !sheet )
- {
- return false;
- }
-
- if ( sheet == this )
- return false;
-
- return true;
-}
-
-// Mouse is now over a droppable panel
-void PropertySheet::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
-{
- // Convert this panel's bounds to screen space
- int x, y, w, h;
-
- GetSize( w, h );
-
- int tabHeight = IsSmallTabs() ? m_iTabHeightSmall : m_iTabHeight;
- h = tabHeight + 4;
-
- x = y = 0;
- LocalToScreen( x, y );
-
- surface()->DrawSetColor( GetDropFrameColor() );
- // Draw 2 pixel frame
- surface()->DrawOutlinedRect( x, y, x + w, y + h );
- surface()->DrawOutlinedRect( x+1, y+1, x + w-1, y + h-1 );
-
- if ( !IsDroppable( msglist ) )
- {
- return;
- }
-
- if ( !_showTabs )
- {
- return;
- }
-
- // Draw a fake new tab...
-
- x = 0;
- y = 2;
- w = 1;
- h = tabHeight;
-
- int last = m_PageTabs.Count();
- if ( last != 0 )
- {
- m_PageTabs[ last - 1 ]->GetBounds( x, y, w, h );
- }
-
- // Compute left edge of "fake" tab
-
- x += ( w + 1 );
-
- // Compute size of new panel
- KeyValues *data = msglist[ 0 ];
- char const *text = data->GetString( "tabname", "" );
- Assert( text );
-
- PageTab *fakeTab = new PageTab( this, "FakeTab", text, NULL, _tabWidth, NULL, false );
- fakeTab->SetBounds( x, 4, w, tabHeight - 4 );
- fakeTab->SetFont( m_tabFont );
- SETUP_PANEL( fakeTab );
- fakeTab->Repaint();
- surface()->SolveTraverse( fakeTab->GetVPanel(), true );
- surface()->PaintTraverse( fakeTab->GetVPanel() );
- delete fakeTab;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : state -
-//-----------------------------------------------------------------------------
-void PropertySheet::SetKBNavigationEnabled( bool state )
-{
- m_bKBNavigationEnabled = state;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : -
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool PropertySheet::IsKBNavigationEnabled() const
-{
- return m_bKBNavigationEnabled;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include <vgui/IBorder.h>
+#include <vgui/IInput.h>
+#include <vgui/IPanel.h>
+#include <vgui/IScheme.h>
+#include <vgui/ISystem.h>
+#include <vgui/IVGui.h>
+#include <vgui/KeyCode.h>
+#include <KeyValues.h>
+#include <vgui/MouseCode.h>
+#include <vgui/ISurface.h>
+#include <vgui_controls/Button.h>
+#include <vgui_controls/Controls.h>
+#include <vgui_controls/Label.h>
+#include <vgui_controls/PropertySheet.h>
+#include <vgui_controls/ComboBox.h>
+#include <vgui_controls/Panel.h>
+#include <vgui_controls/ToolWindow.h>
+#include <vgui_controls/TextImage.h>
+#include <vgui_controls/ImagePanel.h>
+#include <vgui_controls/PropertyPage.h>
+#include "vgui_controls/AnimationController.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+using namespace vgui;
+
+namespace vgui
+{
+
+class ContextLabel : public Label
+{
+ DECLARE_CLASS_SIMPLE( ContextLabel, Label );
+public:
+
+ ContextLabel( Button *parent, char const *panelName, char const *text ):
+ BaseClass( (Panel *)parent, panelName, text ),
+ m_pTabButton( parent )
+ {
+ SetBlockDragChaining( true );
+ }
+
+ virtual void OnMousePressed( MouseCode code )
+ {
+ if ( m_pTabButton )
+ {
+ m_pTabButton->FireActionSignal();
+ }
+ }
+
+ virtual void OnMouseReleased( MouseCode code )
+ {
+ BaseClass::OnMouseReleased( code );
+
+ if ( GetParent() )
+ {
+ GetParent()->OnCommand( "ShowContextMenu" );
+ }
+ }
+
+ virtual void ApplySchemeSettings( IScheme *pScheme )
+ {
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ HFont marlett = pScheme->GetFont( "Marlett" );
+ SetFont( marlett );
+ SetTextInset( 0, 0 );
+ SetContentAlignment( Label::a_northwest );
+
+ if ( GetParent() )
+ {
+ SetFgColor( pScheme->GetColor( "Button.TextColor", GetParent()->GetFgColor() ) );
+ SetBgColor( GetParent()->GetBgColor() );
+ }
+ }
+private:
+
+ Button *m_pTabButton;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper for drag drop
+// Input : msglist -
+// Output : static PropertySheet
+//-----------------------------------------------------------------------------
+static PropertySheet *IsDroppingSheet( CUtlVector< KeyValues * >& msglist )
+{
+ if ( msglist.Count() == 0 )
+ return NULL;
+
+ KeyValues *data = msglist[ 0 ];
+ PropertySheet *sheet = reinterpret_cast< PropertySheet * >( data->GetPtr( "propertysheet" ) );
+ if ( sheet )
+ return sheet;
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: A single tab
+//-----------------------------------------------------------------------------
+class PageTab : public Button
+{
+ DECLARE_CLASS_SIMPLE( PageTab, Button );
+
+private:
+ bool _active;
+ Color _textColor;
+ Color _dimTextColor;
+ int m_bMaxTabWidth;
+ IBorder *m_pActiveBorder;
+ IBorder *m_pNormalBorder;
+ PropertySheet *m_pParent;
+ Panel *m_pPage;
+ ImagePanel *m_pImage;
+ char *m_pszImageName;
+ bool m_bShowContextLabel;
+ bool m_bAttemptingDrop;
+ ContextLabel *m_pContextLabel;
+ long m_hoverActivatePageTime;
+ long m_dropHoverTime;
+
+public:
+ PageTab(PropertySheet *parent, const char *panelName, const char *text, char const *imageName, int maxTabWidth, Panel *page, bool showContextButton, long hoverActivatePageTime = -1 ) :
+ Button( (Panel *)parent, panelName, text),
+ m_pParent( parent ),
+ m_pPage( page ),
+ m_pImage( 0 ),
+ m_pszImageName( 0 ),
+ m_bShowContextLabel( showContextButton ),
+ m_bAttemptingDrop( false ),
+ m_hoverActivatePageTime( hoverActivatePageTime ),
+ m_dropHoverTime( -1 )
+ {
+ SetCommand(new KeyValues("TabPressed"));
+ _active = false;
+ m_bMaxTabWidth = maxTabWidth;
+ SetDropEnabled( true );
+ SetDragEnabled( m_pParent->IsDraggableTab() );
+ if ( imageName )
+ {
+ m_pImage = new ImagePanel( this, text );
+ int buflen = Q_strlen( imageName ) + 1;
+ m_pszImageName = new char[ buflen ];
+ Q_strncpy( m_pszImageName, imageName, buflen );
+
+ }
+ SetMouseClickEnabled( MOUSE_RIGHT, true );
+ m_pContextLabel = m_bShowContextLabel ? new ContextLabel( this, "Context", "9" ) : NULL;
+
+ REGISTER_COLOR_AS_OVERRIDABLE( _textColor, "selectedcolor" );
+ REGISTER_COLOR_AS_OVERRIDABLE( _dimTextColor, "unselectedcolor" );
+ }
+
+ ~PageTab()
+ {
+ delete[] m_pszImageName;
+ }
+
+ virtual void Paint()
+ {
+ BaseClass::Paint();
+ }
+
+ virtual void OnCursorEntered()
+ {
+ m_dropHoverTime = system()->GetTimeMillis();
+ }
+
+ virtual void OnCursorExited()
+ {
+ m_dropHoverTime = -1;
+ }
+
+ virtual void OnThink()
+ {
+ if ( m_bAttemptingDrop && m_hoverActivatePageTime >= 0 && m_dropHoverTime >= 0 )
+ {
+ long hoverTime = system()->GetTimeMillis() - m_dropHoverTime;
+ if ( hoverTime > m_hoverActivatePageTime )
+ {
+ FireActionSignal();
+ SetSelected(true);
+ Repaint();
+ }
+ }
+ m_bAttemptingDrop = false;
+
+ BaseClass::OnThink();
+ }
+
+ virtual bool IsDroppable( CUtlVector< KeyValues * >&msglist )
+ {
+ m_bAttemptingDrop = true;
+
+ if ( !GetParent() )
+ return false;
+
+ PropertySheet *sheet = IsDroppingSheet( msglist );
+ if ( sheet )
+ return GetParent()->IsDroppable( msglist );
+
+ return BaseClass::IsDroppable( msglist );
+ }
+
+ virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
+ {
+ PropertySheet *sheet = IsDroppingSheet( msglist );
+ if ( sheet )
+ {
+ Panel *target = GetParent()->GetDropTarget( msglist );
+ if ( target )
+ {
+ // Fixme, mouse pos could be wrong...
+ target->OnDroppablePanelPaint( msglist, dragPanels );
+ return;
+ }
+ }
+
+ // Just highlight the tab if dropping onto active page via the tab
+ BaseClass::OnDroppablePanelPaint( msglist, dragPanels );
+ }
+
+ virtual void OnPanelDropped( CUtlVector< KeyValues * >& msglist )
+ {
+ PropertySheet *sheet = IsDroppingSheet( msglist );
+ if ( sheet )
+ {
+ Panel *target = GetParent()->GetDropTarget( msglist );
+ if ( target )
+ {
+ // Fixme, mouse pos could be wrong...
+ target->OnPanelDropped( msglist );
+ }
+ }
+
+ // Defer to active page...
+ Panel *active = m_pParent->GetActivePage();
+ if ( !active || !active->IsDroppable( msglist ) )
+ return;
+
+ active->OnPanelDropped( msglist );
+ }
+
+ virtual void OnDragFailed( CUtlVector< KeyValues * >& msglist )
+ {
+ PropertySheet *sheet = IsDroppingSheet( msglist );
+ if ( !sheet )
+ return;
+
+ // Create a new property sheet
+ if ( m_pParent->IsDraggableTab() )
+ {
+ if ( msglist.Count() == 1 )
+ {
+ KeyValues *data = msglist[ 0 ];
+ int screenx = data->GetInt( "screenx" );
+ int screeny = data->GetInt( "screeny" );
+
+ // m_pParent->ScreenToLocal( screenx, screeny );
+ if ( !m_pParent->IsWithin( screenx, screeny ) )
+ {
+ Panel *page = reinterpret_cast< Panel * >( data->GetPtr( "propertypage" ) );
+ PropertySheet *sheet = reinterpret_cast< PropertySheet * >( data->GetPtr( "propertysheet" ) );
+ char const *title = data->GetString( "tabname", "" );
+ if ( !page || !sheet )
+ return;
+
+ // Can only create if sheet was part of a ToolWindow derived object
+ ToolWindow *tw = dynamic_cast< ToolWindow * >( sheet->GetParent() );
+ if ( tw )
+ {
+ IToolWindowFactory *factory = tw->GetToolWindowFactory();
+ if ( factory )
+ {
+ bool hasContextMenu = sheet->PageHasContextMenu( page );
+ sheet->RemovePage( page );
+ factory->InstanceToolWindow( tw->GetParent(), sheet->ShouldShowContextButtons(), page, title, hasContextMenu );
+
+ if ( sheet->GetNumPages() == 0 )
+ {
+ tw->MarkForDeletion();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ virtual void OnCreateDragData( KeyValues *msg )
+ {
+ Assert( m_pParent->IsDraggableTab() );
+
+ msg->SetPtr( "propertypage", m_pPage );
+ msg->SetPtr( "propertysheet", m_pParent );
+ char sz[ 256 ];
+ GetText( sz, sizeof( sz ) );
+ msg->SetString( "tabname", sz );
+ msg->SetString( "text", sz );
+ }
+
+ virtual void ApplySchemeSettings(IScheme *pScheme)
+ {
+ // set up the scheme settings
+ Button::ApplySchemeSettings(pScheme);
+
+ _textColor = GetSchemeColor("PropertySheet.SelectedTextColor", GetFgColor(), pScheme);
+ _dimTextColor = GetSchemeColor("PropertySheet.TextColor", GetFgColor(), pScheme);
+ m_pActiveBorder = pScheme->GetBorder("TabActiveBorder");
+ m_pNormalBorder = pScheme->GetBorder("TabBorder");
+
+ if ( m_pImage )
+ {
+ ClearImages();
+ m_pImage->SetImage(scheme()->GetImage(m_pszImageName, false));
+ AddImage( m_pImage->GetImage(), 2 );
+ int w, h;
+ m_pImage->GetSize( w, h );
+ w += m_pContextLabel ? 10 : 0;
+ if ( m_pContextLabel )
+ {
+ m_pImage->SetPos( 10, 0 );
+ }
+ SetSize( w + 4, h + 2 );
+ }
+ else
+ {
+ int wide, tall;
+ int contentWide, contentTall;
+ GetSize(wide, tall);
+ GetContentSize(contentWide, contentTall);
+
+ wide = max(m_bMaxTabWidth, contentWide + 10); // 10 = 5 pixels margin on each side
+ wide += m_pContextLabel ? 10 : 0;
+ SetSize(wide, tall);
+ }
+
+ if ( m_pContextLabel )
+ {
+ SetTextInset( 12, 0 );
+ }
+ }
+
+ virtual void ApplySettings( KeyValues *inResourceData )
+ {
+ const char *pBorder = inResourceData->GetString("activeborder_override", "");
+ if (*pBorder)
+ {
+ m_pActiveBorder = scheme()->GetIScheme(GetScheme())->GetBorder( pBorder );
+ }
+ pBorder = inResourceData->GetString("normalborder_override", "");
+ if (*pBorder)
+ {
+ m_pNormalBorder = scheme()->GetIScheme(GetScheme())->GetBorder( pBorder );
+ }
+ BaseClass::ApplySettings(inResourceData);
+ }
+
+ virtual void OnCommand( char const *cmd )
+ {
+ if ( !Q_stricmp( cmd, "ShowContextMenu" ) )
+ {
+ KeyValues *kv = new KeyValues("OpenContextMenu");
+ kv->SetPtr( "page", m_pPage );
+ kv->SetPtr( "contextlabel", m_pContextLabel );
+ PostActionSignal( kv );
+ return;
+ }
+ BaseClass::OnCommand( cmd );
+ }
+
+ IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
+ {
+ if (_active)
+ {
+ return m_pActiveBorder;
+ }
+ return m_pNormalBorder;
+ }
+
+ virtual Color GetButtonFgColor()
+ {
+ if (_active)
+ {
+ return _textColor;
+ }
+ else
+ {
+ return _dimTextColor;
+ }
+ }
+
+ virtual void SetActive(bool state)
+ {
+ _active = state;
+ SetZPos( state ? 100 : 0 );
+ InvalidateLayout();
+ Repaint();
+ }
+
+ virtual void SetTabWidth( int iWidth )
+ {
+ m_bMaxTabWidth = iWidth;
+ InvalidateLayout();
+ }
+
+ virtual bool CanBeDefaultButton(void)
+ {
+ return false;
+ }
+
+ //Fire action signal when mouse is pressed down instead of on release.
+ virtual void OnMousePressed(MouseCode code)
+ {
+ // check for context menu open
+ if (!IsEnabled())
+ return;
+
+ if (!IsMouseClickEnabled(code))
+ return;
+
+ if (IsUseCaptureMouseEnabled())
+ {
+ {
+ RequestFocus();
+ FireActionSignal();
+ SetSelected(true);
+ Repaint();
+ }
+
+ // lock mouse input to going to this button
+ input()->SetMouseCapture(GetVPanel());
+ }
+ }
+
+ virtual void OnMouseReleased(MouseCode code)
+ {
+ // ensure mouse capture gets released
+ if (IsUseCaptureMouseEnabled())
+ {
+ input()->SetMouseCapture(NULL);
+ }
+
+ // make sure the button gets unselected
+ SetSelected(false);
+ Repaint();
+
+ if (code == MOUSE_RIGHT)
+ {
+ KeyValues *kv = new KeyValues("OpenContextMenu");
+ kv->SetPtr( "page", m_pPage );
+ kv->SetPtr( "contextlabel", m_pContextLabel );
+ PostActionSignal( kv );
+ }
+ }
+
+ virtual void PerformLayout()
+ {
+ BaseClass::PerformLayout();
+
+ if ( m_pContextLabel )
+ {
+ int w, h;
+ GetSize( w, h );
+ m_pContextLabel->SetBounds( 0, 0, 10, h );
+ }
+ }
+};
+
+
+}; // namespace vgui
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+PropertySheet::PropertySheet(
+ Panel *parent,
+ const char *panelName,
+ bool draggableTabs /*= false*/ ) : BaseClass(parent, panelName)
+{
+ _activePage = NULL;
+ _activeTab = NULL;
+ _tabWidth = 64;
+ _activeTabIndex = 0;
+ _showTabs = true;
+ _combo = NULL;
+ _tabFocus = false;
+ m_flPageTransitionEffectTime = 0.0f;
+ m_bSmallTabs = false;
+ m_tabFont = 0;
+ m_bDraggableTabs = draggableTabs;
+ m_pTabKV = NULL;
+ m_iTabHeight = 0;
+ m_iTabHeightSmall = 0;
+
+ if ( m_bDraggableTabs )
+ {
+ SetDropEnabled( true );
+ }
+
+ m_bKBNavigationEnabled = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor, associates pages with a combo box
+//-----------------------------------------------------------------------------
+PropertySheet::PropertySheet(Panel *parent, const char *panelName, ComboBox *combo) : BaseClass(parent, panelName)
+{
+ _activePage = NULL;
+ _activeTab = NULL;
+ _tabWidth = 64;
+ _activeTabIndex = 0;
+ _combo=combo;
+ _combo->AddActionSignalTarget(this);
+ _showTabs = false;
+ _tabFocus = false;
+ m_flPageTransitionEffectTime = 0.0f;
+ m_bSmallTabs = false;
+ m_tabFont = 0;
+ m_bDraggableTabs = false;
+ m_pTabKV = NULL;
+ m_iTabHeight = 0;
+ m_iTabHeightSmall = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+PropertySheet::~PropertySheet()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: ToolWindow uses this to drag tools from container to container by dragging the tab
+// Input : -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool PropertySheet::IsDraggableTab() const
+{
+ return m_bDraggableTabs;
+}
+
+void PropertySheet::SetDraggableTabs( bool state )
+{
+ m_bDraggableTabs = state;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Lower profile tabs
+// Input : state -
+//-----------------------------------------------------------------------------
+void PropertySheet::SetSmallTabs( bool state )
+{
+ m_bSmallTabs = state;
+ m_tabFont = scheme()->GetIScheme( GetScheme() )->GetFont( m_bSmallTabs ? "DefaultVerySmall" : "Default" );
+ int c = m_PageTabs.Count();
+ for ( int i = 0; i < c ; ++i )
+ {
+ PageTab *tab = m_PageTabs[ i ];
+ Assert( tab );
+ tab->SetFont( m_tabFont );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool PropertySheet::IsSmallTabs() const
+{
+ return m_bSmallTabs;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : state -
+//-----------------------------------------------------------------------------
+void PropertySheet::ShowContextButtons( bool state )
+{
+ m_bContextButton = state;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool PropertySheet::ShouldShowContextButtons() const
+{
+ return m_bContextButton;
+}
+
+int PropertySheet::FindPage( Panel *page ) const
+{
+ int c = m_Pages.Count();
+ for ( int i = 0; i < c; ++i )
+ {
+ if ( m_Pages[ i ].page == page )
+ return i;
+ }
+
+ return m_Pages.InvalidIndex();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: adds a page to the sheet
+//-----------------------------------------------------------------------------
+void PropertySheet::AddPage(Panel *page, const char *title, char const *imageName /*= NULL*/, bool bHasContextMenu /*= false*/ )
+{
+ if (!page)
+ return;
+
+ // don't add the page if we already have it
+ if ( FindPage( page ) != m_Pages.InvalidIndex() )
+ return;
+
+ long hoverActivatePageTime = 250;
+ PageTab *tab = new PageTab(this, "tab", title, imageName, _tabWidth, page, m_bContextButton && bHasContextMenu, hoverActivatePageTime );
+ if ( m_bDraggableTabs )
+ {
+ tab->SetDragEnabled( true );
+ }
+
+ tab->SetFont( m_tabFont );
+ if(_showTabs)
+ {
+ tab->AddActionSignalTarget(this);
+ }
+ else if (_combo)
+ {
+ _combo->AddItem(title, NULL);
+ }
+
+ if ( m_pTabKV )
+ {
+ tab->ApplySettings( m_pTabKV );
+ }
+
+ m_PageTabs.AddToTail(tab);
+
+ Page_t info;
+ info.page = page;
+ info.contextMenu = m_bContextButton && bHasContextMenu;
+
+ m_Pages.AddToTail( info );
+
+ page->SetParent(this);
+ page->AddActionSignalTarget(this);
+ PostMessage(page, new KeyValues("ResetData"));
+
+ page->SetVisible(false);
+ InvalidateLayout();
+
+ if (!_activePage)
+ {
+ // first page becomes the active page
+ ChangeActiveTab( 0 );
+ if ( _activePage )
+ {
+ _activePage->RequestFocus( 0 );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::SetActivePage(Panel *page)
+{
+ // walk the list looking for this page
+ int index = FindPage( page );
+ if (!m_Pages.IsValidIndex(index))
+ return;
+
+ ChangeActiveTab(index);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::SetTabWidth(int pixels)
+{
+ if ( pixels < 0 )
+ {
+ if( !_activeTab )
+ return;
+
+ int nTall;
+ _activeTab->GetContentSize( pixels, nTall );
+ }
+
+ if ( _tabWidth == pixels )
+ return;
+
+ _tabWidth = pixels;
+ InvalidateLayout();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: reloads the data in all the property page
+//-----------------------------------------------------------------------------
+void PropertySheet::ResetAllData()
+{
+ // iterate all the dialogs resetting them
+ for (int i = 0; i < m_Pages.Count(); i++)
+ {
+ ipanel()->SendMessage(m_Pages[i].page->GetVPanel(), new KeyValues("ResetData"), GetVPanel());
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Applies any changes made by the dialog
+//-----------------------------------------------------------------------------
+void PropertySheet::ApplyChanges()
+{
+ // iterate all the dialogs resetting them
+ for (int i = 0; i < m_Pages.Count(); i++)
+ {
+ ipanel()->SendMessage(m_Pages[i].page->GetVPanel(), new KeyValues("ApplyChanges"), GetVPanel());
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: gets a pointer to the currently active page
+//-----------------------------------------------------------------------------
+Panel *PropertySheet::GetActivePage()
+{
+ return _activePage;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: gets a pointer to the currently active tab
+//-----------------------------------------------------------------------------
+Panel *PropertySheet::GetActiveTab()
+{
+ return _activeTab;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the number of panels in the sheet
+//-----------------------------------------------------------------------------
+int PropertySheet::GetNumPages()
+{
+ return m_Pages.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the name contained in the active tab
+// Input : a text buffer to contain the output
+//-----------------------------------------------------------------------------
+void PropertySheet::GetActiveTabTitle (char *textOut, int bufferLen )
+{
+ if(_activeTab) _activeTab->GetText(textOut, bufferLen);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the name contained in the active tab
+// Input : a text buffer to contain the output
+//-----------------------------------------------------------------------------
+bool PropertySheet::GetTabTitle( int i, char *textOut, int bufferLen )
+{
+ if ( i < 0 || i >= m_PageTabs.Count() )
+ {
+ return false;
+ }
+
+ m_PageTabs[i]->GetText(textOut, bufferLen);
+ return true;
+}
+
+bool PropertySheet::SetTabTitle( int i, char *pchTitle )
+{
+ if ( i < 0 || i >= m_PageTabs.Count() )
+ {
+ return false;
+ }
+
+ m_PageTabs[ i ]->SetText( pchTitle );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the index of the currently active page
+//-----------------------------------------------------------------------------
+int PropertySheet::GetActivePageNum()
+{
+ for (int i = 0; i < m_Pages.Count(); i++)
+ {
+ if (m_Pages[i].page == _activePage)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Forwards focus requests to current active page
+//-----------------------------------------------------------------------------
+void PropertySheet::RequestFocus(int direction)
+{
+ if (direction == -1 || direction == 0)
+ {
+ if (_activePage)
+ {
+ _activePage->RequestFocus(direction);
+ _tabFocus = false;
+ }
+ }
+ else
+ {
+ if (_showTabs && _activeTab)
+ {
+ _activeTab->RequestFocus(direction);
+ _tabFocus = true;
+ }
+ else if (_activePage)
+ {
+ _activePage->RequestFocus(direction);
+ _tabFocus = false;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: moves focus back
+//-----------------------------------------------------------------------------
+bool PropertySheet::RequestFocusPrev(VPANEL panel)
+{
+ if (_tabFocus || !_showTabs || !_activeTab)
+ {
+ _tabFocus = false;
+ return BaseClass::RequestFocusPrev(panel);
+ }
+ else
+ {
+ if (GetVParent())
+ {
+ PostMessage(GetVParent(), new KeyValues("FindDefaultButton"));
+ }
+ _activeTab->RequestFocus(-1);
+ _tabFocus = true;
+ return true;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: moves focus forward
+//-----------------------------------------------------------------------------
+bool PropertySheet::RequestFocusNext(VPANEL panel)
+{
+ if (!_tabFocus || !_activePage)
+ {
+ return BaseClass::RequestFocusNext(panel);
+ }
+ else
+ {
+ if (!_activeTab)
+ {
+ return BaseClass::RequestFocusNext(panel);
+ }
+ else
+ {
+ _activePage->RequestFocus(1);
+ _tabFocus = false;
+ return true;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Gets scheme settings
+//-----------------------------------------------------------------------------
+void PropertySheet::ApplySchemeSettings(IScheme *pScheme)
+{
+ BaseClass::ApplySchemeSettings(pScheme);
+
+ // a little backwards-compatibility with old scheme files
+ IBorder *pBorder = pScheme->GetBorder("PropertySheetBorder");
+ if (pBorder == pScheme->GetBorder("Default"))
+ {
+ // get the old name
+ pBorder = pScheme->GetBorder("RaisedBorder");
+ }
+
+ SetBorder(pBorder);
+ m_flPageTransitionEffectTime = atof(pScheme->GetResourceString("PropertySheet.TransitionEffectTime"));
+
+ m_tabFont = pScheme->GetFont( m_bSmallTabs ? "DefaultVerySmall" : "Default" );
+
+ if ( m_pTabKV )
+ {
+ for (int i = 0; i < m_PageTabs.Count(); i++)
+ {
+ m_PageTabs[i]->ApplySettings( m_pTabKV );
+ }
+ }
+
+
+ //=============================================================================
+ // HPE_BEGIN:
+ // [tj] Here, we used to use a single size variable and overwrite it when we scaled.
+ // This led to problems when we changes resolutions, so now we recalcuate the absolute
+ // size from the relative size each time (based on proportionality)
+ //=============================================================================
+ if ( IsProportional() )
+ {
+ m_iTabHeight = scheme()->GetProportionalScaledValueEx( GetScheme(), m_iSpecifiedTabHeight );
+ m_iTabHeightSmall = scheme()->GetProportionalScaledValueEx( GetScheme(), m_iSpecifiedTabHeightSmall );
+ }
+ else
+ {
+ m_iTabHeight = m_iSpecifiedTabHeight;
+ m_iTabHeightSmall = m_iSpecifiedTabHeightSmall;
+ }
+ //=============================================================================
+ // HPE_END
+ //=============================================================================
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::ApplySettings(KeyValues *inResourceData)
+{
+ BaseClass::ApplySettings(inResourceData);
+
+ KeyValues *pTabKV = inResourceData->FindKey( "tabskv" );
+ if ( pTabKV )
+ {
+ if ( m_pTabKV )
+ {
+ m_pTabKV->deleteThis();
+ }
+ m_pTabKV = new KeyValues("tabkv");
+ pTabKV->CopySubkeys( m_pTabKV );
+ }
+
+ KeyValues *pTabWidthKV = inResourceData->FindKey( "tabwidth" );
+ if ( pTabWidthKV )
+ {
+ _tabWidth = scheme()->GetProportionalScaledValueEx(GetScheme(), pTabWidthKV->GetInt());
+ for (int i = 0; i < m_PageTabs.Count(); i++)
+ {
+ m_PageTabs[i]->SetTabWidth( _tabWidth );
+ }
+ }
+
+ KeyValues *pTransitionKV = inResourceData->FindKey( "transition_time" );
+ if ( pTransitionKV )
+ {
+ m_flPageTransitionEffectTime = pTransitionKV->GetFloat();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Paint our border specially, with the tabs in mind
+//-----------------------------------------------------------------------------
+void PropertySheet::PaintBorder()
+{
+ IBorder *border = GetBorder();
+ if (!border)
+ return;
+
+ // draw the border, but with a break at the active tab
+ int px = 0, py = 0, pwide = 0, ptall = 0;
+ if (_activeTab)
+ {
+ _activeTab->GetBounds(px, py, pwide, ptall);
+ ptall -= 1;
+ }
+
+ // draw the border underneath the buttons, with a break
+ int wide, tall;
+ GetSize(wide, tall);
+ border->Paint(0, py + ptall, wide, tall, IBorder::SIDE_TOP, px + 1, px + pwide - 1);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Lays out the dialog
+//-----------------------------------------------------------------------------
+void PropertySheet::PerformLayout()
+{
+ BaseClass::PerformLayout();
+
+ int x, y, wide, tall;
+ GetBounds(x, y, wide, tall);
+ if (_activePage)
+ {
+ int tabHeight = IsSmallTabs() ? m_iTabHeightSmall : m_iTabHeight;
+
+ if(_showTabs)
+ {
+ _activePage->SetBounds(0, tabHeight, wide, tall - tabHeight);
+ }
+ else
+ {
+ _activePage->SetBounds(0, 0, wide, tall );
+ }
+ _activePage->InvalidateLayout();
+ }
+
+
+ int xtab;
+ int limit = m_PageTabs.Count();
+
+ xtab = m_iTabXIndent;
+
+ // draw the visible tabs
+ if (_showTabs)
+ {
+ for (int i = 0; i < limit; i++)
+ {
+ int tabHeight = IsSmallTabs() ? (m_iTabHeightSmall-1) : (m_iTabHeight-1);
+
+ int width, tall;
+ m_PageTabs[i]->GetSize(width, tall);
+
+ if ( m_bTabFitText )
+ {
+ m_PageTabs[i]->SizeToContents();
+ width = m_PageTabs[i]->GetWide();
+
+ int iXInset, iYInset;
+ m_PageTabs[i]->GetTextInset( &iXInset, &iYInset );
+ width += (iXInset * 2);
+ }
+
+ if (m_PageTabs[i] == _activeTab)
+ {
+ // active tab is taller
+ _activeTab->SetBounds(xtab, 2, width, tabHeight);
+ }
+ else
+ {
+ m_PageTabs[i]->SetBounds(xtab, 4, width, tabHeight - 2);
+ }
+ m_PageTabs[i]->SetVisible(true);
+ xtab += (width + 1) + m_iTabXDelta;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < limit; i++)
+ {
+ m_PageTabs[i]->SetVisible(false);
+ }
+ }
+
+ // ensure draw order (page drawing over all the tabs except one)
+ if (_activePage)
+ {
+ _activePage->MoveToFront();
+ _activePage->Repaint();
+ }
+ if (_activeTab)
+ {
+ _activeTab->MoveToFront();
+ _activeTab->Repaint();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Switches the active panel
+//-----------------------------------------------------------------------------
+void PropertySheet::OnTabPressed(Panel *panel)
+{
+ // look for the tab in the list
+ for (int i = 0; i < m_PageTabs.Count(); i++)
+ {
+ if (m_PageTabs[i] == panel)
+ {
+ // flip to the new tab
+ ChangeActiveTab(i);
+ return;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the panel associated with index i
+// Input : the index of the panel to return
+//-----------------------------------------------------------------------------
+Panel *PropertySheet::GetPage(int i)
+{
+ if(i<0 || i>=m_Pages.Count())
+ {
+ return NULL;
+ }
+
+ return m_Pages[i].page;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: disables page by name
+//-----------------------------------------------------------------------------
+void PropertySheet::DisablePage(const char *title)
+{
+ SetPageEnabled(title, false);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: enables page by name
+//-----------------------------------------------------------------------------
+void PropertySheet::EnablePage(const char *title)
+{
+ SetPageEnabled(title, true);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: enabled or disables page by name
+//-----------------------------------------------------------------------------
+void PropertySheet::SetPageEnabled(const char *title, bool state)
+{
+ for (int i = 0; i < m_PageTabs.Count(); i++)
+ {
+ if (_showTabs)
+ {
+ char tmp[50];
+ m_PageTabs[i]->GetText(tmp,50);
+ if (!strnicmp(title,tmp,strlen(tmp)))
+ {
+ m_PageTabs[i]->SetEnabled(state);
+ }
+ }
+ else
+ {
+ _combo->SetItemEnabled(title,state);
+ }
+ }
+}
+
+void PropertySheet::RemoveAllPages()
+{
+ int c = m_Pages.Count();
+ for ( int i = c - 1; i >= 0 ; --i )
+ {
+ RemovePage( m_Pages[ i ].page );
+ }
+}
+
+void PropertySheet::DeleteAllPages()
+{
+ int c = m_Pages.Count();
+ for ( int i = c - 1; i >= 0 ; --i )
+ {
+ DeletePage( m_Pages[ i ].page );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: deletes the page associated with panel
+// Input : *panel - the panel of the page to remove
+//-----------------------------------------------------------------------------
+void PropertySheet::RemovePage(Panel *panel)
+{
+ int location = FindPage( panel );
+ if ( location == m_Pages.InvalidIndex() )
+ return;
+
+ // Since it's being deleted, don't animate!!!
+ m_hPreviouslyActivePage = NULL;
+ _activeTab = NULL;
+
+ // ASSUMPTION = that the number of pages equals number of tabs
+ if( _showTabs )
+ {
+ m_PageTabs[location]->RemoveActionSignalTarget( this );
+ }
+ // now remove the tab
+ PageTab *tab = m_PageTabs[ location ];
+ m_PageTabs.Remove( location );
+ tab->MarkForDeletion();
+
+ // Remove from page list
+ m_Pages.Remove( location );
+
+ // Unparent
+ panel->SetParent( (Panel *)NULL );
+
+ if ( _activePage == panel )
+ {
+ _activePage = NULL;
+ // if this page is currently active, backup to the page before this.
+ ChangeActiveTab( max( location - 1, 0 ) );
+ }
+
+ PerformLayout();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: deletes the page associated with panel
+// Input : *panel - the panel of the page to remove
+//-----------------------------------------------------------------------------
+void PropertySheet::DeletePage(Panel *panel)
+{
+ Assert( panel );
+ RemovePage( panel );
+ panel->MarkForDeletion();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: flips to the new tab, sending out all the right notifications
+// flipping to a tab activates the tab.
+//-----------------------------------------------------------------------------
+void PropertySheet::ChangeActiveTab( int index )
+{
+ if ( !m_Pages.IsValidIndex( index ) )
+ {
+ _activeTab = NULL;
+ if ( m_Pages.Count() > 0 )
+ {
+ _activePage = NULL;
+
+ if ( index < 0 )
+ {
+ ChangeActiveTab( m_Pages.Count() - 1 );
+ }
+ else
+ {
+ ChangeActiveTab( 0 );
+ }
+ }
+ return;
+ }
+
+ if ( m_Pages[index].page == _activePage )
+ {
+ if ( _activeTab )
+ {
+ _activeTab->RequestFocus();
+ }
+ _tabFocus = true;
+ return;
+ }
+
+ int c = m_Pages.Count();
+ for ( int i = 0; i < c; ++i )
+ {
+ m_Pages[ i ].page->SetVisible( false );
+ }
+
+ m_hPreviouslyActivePage = _activePage;
+ // notify old page
+ if (_activePage)
+ {
+ ivgui()->PostMessage(_activePage->GetVPanel(), new KeyValues("PageHide"), GetVPanel());
+ KeyValues *msg = new KeyValues("PageTabActivated");
+ msg->SetPtr("panel", (Panel *)NULL);
+ ivgui()->PostMessage(_activePage->GetVPanel(), msg, GetVPanel());
+ }
+ if (_activeTab)
+ {
+ //_activeTabIndex=index;
+ _activeTab->SetActive(false);
+
+ // does the old tab have the focus?
+ _tabFocus = _activeTab->HasFocus();
+ }
+ else
+ {
+ _tabFocus = false;
+ }
+
+ // flip page
+ _activePage = m_Pages[index].page;
+ _activeTab = m_PageTabs[index];
+ _activeTabIndex = index;
+
+ _activePage->SetVisible(true);
+ _activePage->MoveToFront();
+
+ _activeTab->SetVisible(true);
+ _activeTab->MoveToFront();
+ _activeTab->SetActive(true);
+
+ if (_tabFocus)
+ {
+ // if a tab already has focused,give the new tab the focus
+ _activeTab->RequestFocus();
+ }
+ else
+ {
+ // otherwise, give the focus to the page
+ _activePage->RequestFocus();
+ }
+
+ if (!_showTabs)
+ {
+ _combo->ActivateItemByRow(index);
+ }
+
+ _activePage->MakeReadyForUse();
+
+ // transition effect
+ if (m_flPageTransitionEffectTime)
+ {
+ if (m_hPreviouslyActivePage.Get())
+ {
+ // fade out the previous page
+ GetAnimationController()->RunAnimationCommand(m_hPreviouslyActivePage, "Alpha", 0.0f, 0.0f, m_flPageTransitionEffectTime / 2, AnimationController::INTERPOLATOR_LINEAR);
+ }
+
+ // fade in the new page
+ _activePage->SetAlpha(0);
+ GetAnimationController()->RunAnimationCommand(_activePage, "Alpha", 255.0f, m_flPageTransitionEffectTime / 2, m_flPageTransitionEffectTime / 2, AnimationController::INTERPOLATOR_LINEAR);
+ }
+ else
+ {
+ if (m_hPreviouslyActivePage.Get())
+ {
+ // no transition, just hide the previous page
+ m_hPreviouslyActivePage->SetVisible(false);
+ }
+ _activePage->SetAlpha( 255 );
+ }
+
+ // notify
+ ivgui()->PostMessage(_activePage->GetVPanel(), new KeyValues("PageShow"), GetVPanel());
+
+ KeyValues *msg = new KeyValues("PageTabActivated");
+ msg->SetPtr("panel", (Panel *)_activeTab);
+ ivgui()->PostMessage(_activePage->GetVPanel(), msg, GetVPanel());
+
+ // tell parent
+ PostActionSignal(new KeyValues("PageChanged"));
+
+ // Repaint
+ InvalidateLayout();
+ Repaint();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Gets the panel with the specified hotkey, from the current page
+//-----------------------------------------------------------------------------
+Panel *PropertySheet::HasHotkey(wchar_t key)
+{
+ if (!_activePage)
+ return NULL;
+
+ for (int i = 0; i < _activePage->GetChildCount(); i++)
+ {
+ Panel *hot = _activePage->GetChild(i)->HasHotkey(key);
+ if (hot)
+ {
+ return hot;
+ }
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: catches the opencontextmenu event
+//-----------------------------------------------------------------------------
+void PropertySheet::OnOpenContextMenu( KeyValues *params )
+{
+ // tell parent
+ KeyValues *kv = params->MakeCopy();
+ PostActionSignal( kv );
+ Panel *page = reinterpret_cast< Panel * >( params->GetPtr( "page" ) );
+ if ( page )
+ {
+ PostMessage( page->GetVPanel(), params->MakeCopy() );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle key presses, through tabs.
+//-----------------------------------------------------------------------------
+void PropertySheet::OnKeyCodePressed(KeyCode code)
+{
+ bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
+ bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
+ bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
+
+ if ( ctrl && shift && alt && code == KEY_B )
+ {
+ // enable build mode
+ EditablePanel *ep = dynamic_cast< EditablePanel * >( GetActivePage() );
+ if ( ep )
+ {
+ ep->ActivateBuildMode();
+ return;
+ }
+ }
+
+ if ( IsKBNavigationEnabled() )
+ {
+ ButtonCode_t nButtonCode = GetBaseButtonCode( code );
+
+ switch ( nButtonCode )
+ {
+ // for now left and right arrows just open or close submenus if they are there.
+ case KEY_RIGHT:
+ case KEY_XBUTTON_RIGHT:
+ case KEY_XSTICK1_RIGHT:
+ case KEY_XSTICK2_RIGHT:
+ {
+ ChangeActiveTab(_activeTabIndex+1);
+ break;
+ }
+ case KEY_LEFT:
+ case KEY_XBUTTON_LEFT:
+ case KEY_XSTICK1_LEFT:
+ case KEY_XSTICK2_LEFT:
+ {
+ ChangeActiveTab(_activeTabIndex-1);
+ break;
+ }
+ default:
+ BaseClass::OnKeyCodePressed(code);
+ break;
+ }
+ }
+ else
+ {
+ BaseClass::OnKeyCodePressed(code);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called by the associated combo box (if in that mode), changes the current panel
+//-----------------------------------------------------------------------------
+void PropertySheet::OnTextChanged(Panel *panel,const wchar_t *wszText)
+{
+ if ( panel == _combo )
+ {
+ wchar_t tabText[30];
+ for(int i = 0 ; i < m_PageTabs.Count() ; i++ )
+ {
+ tabText[0] = 0;
+ m_PageTabs[i]->GetText(tabText,30);
+ if ( !wcsicmp(wszText,tabText) )
+ {
+ ChangeActiveTab(i);
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::OnCommand(const char *command)
+{
+ // propogate the close command to our parent
+ if (!stricmp(command, "Close") && GetVParent())
+ {
+ CallParentFunction(new KeyValues("Command", "command", command));
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::OnApplyButtonEnable()
+{
+ // tell parent
+ PostActionSignal(new KeyValues("ApplyButtonEnable"));
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::OnCurrentDefaultButtonSet( vgui::VPANEL defaultButton )
+{
+ // forward the message up
+ if (GetVParent())
+ {
+ KeyValues *msg = new KeyValues("CurrentDefaultButtonSet");
+ msg->SetInt("button", ivgui()->PanelToHandle( defaultButton ) );
+ PostMessage(GetVParent(), msg);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::OnDefaultButtonSet( VPANEL defaultButton )
+{
+ // forward the message up
+ if (GetVParent())
+ {
+ KeyValues *msg = new KeyValues("DefaultButtonSet");
+ msg->SetInt("button", ivgui()->PanelToHandle( defaultButton ) );
+ PostMessage(GetVParent(), msg);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void PropertySheet::OnFindDefaultButton()
+{
+ if (GetVParent())
+ {
+ PostMessage(GetVParent(), new KeyValues("FindDefaultButton"));
+ }
+}
+
+bool PropertySheet::PageHasContextMenu( Panel *page ) const
+{
+ int pageNum = FindPage( page );
+ if ( pageNum == m_Pages.InvalidIndex() )
+ return false;
+
+ return m_Pages[ pageNum ].contextMenu;
+}
+
+void PropertySheet::OnPanelDropped( CUtlVector< KeyValues * >& msglist )
+{
+ if ( msglist.Count() != 1 )
+ {
+ return;
+ }
+
+ PropertySheet *sheet = IsDroppingSheet( msglist );
+ if ( !sheet )
+ {
+ // Defer to active page
+ if ( _activePage && _activePage->IsDropEnabled() )
+ {
+ return _activePage->OnPanelDropped( msglist );
+ }
+ return;
+ }
+
+ KeyValues *data = msglist[ 0 ];
+
+ Panel *page = reinterpret_cast< Panel * >( data->GetPtr( "propertypage" ) );
+ char const *title = data->GetString( "tabname", "" );
+ if ( !page || !sheet )
+ return;
+
+ // Can only create if sheet was part of a ToolWindow derived object
+ ToolWindow *tw = dynamic_cast< ToolWindow * >( sheet->GetParent() );
+ if ( tw )
+ {
+ IToolWindowFactory *factory = tw->GetToolWindowFactory();
+ if ( factory )
+ {
+ bool showContext = sheet->PageHasContextMenu( page );
+ sheet->RemovePage( page );
+ if ( sheet->GetNumPages() == 0 )
+ {
+ tw->MarkForDeletion();
+ }
+
+ AddPage( page, title, NULL, showContext );
+ }
+ }
+}
+
+bool PropertySheet::IsDroppable( CUtlVector< KeyValues * >& msglist )
+{
+ if ( !m_bDraggableTabs )
+ return false;
+
+ if ( msglist.Count() != 1 )
+ {
+ return false;
+ }
+
+ int mx, my;
+ input()->GetCursorPos( mx, my );
+ ScreenToLocal( mx, my );
+
+ int tabHeight = IsSmallTabs() ? m_iTabHeightSmall : m_iTabHeight;
+ if ( my > tabHeight )
+ return false;
+
+ PropertySheet *sheet = IsDroppingSheet( msglist );
+ if ( !sheet )
+ {
+ return false;
+ }
+
+ if ( sheet == this )
+ return false;
+
+ return true;
+}
+
+// Mouse is now over a droppable panel
+void PropertySheet::OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels )
+{
+ // Convert this panel's bounds to screen space
+ int x, y, w, h;
+
+ GetSize( w, h );
+
+ int tabHeight = IsSmallTabs() ? m_iTabHeightSmall : m_iTabHeight;
+ h = tabHeight + 4;
+
+ x = y = 0;
+ LocalToScreen( x, y );
+
+ surface()->DrawSetColor( GetDropFrameColor() );
+ // Draw 2 pixel frame
+ surface()->DrawOutlinedRect( x, y, x + w, y + h );
+ surface()->DrawOutlinedRect( x+1, y+1, x + w-1, y + h-1 );
+
+ if ( !IsDroppable( msglist ) )
+ {
+ return;
+ }
+
+ if ( !_showTabs )
+ {
+ return;
+ }
+
+ // Draw a fake new tab...
+
+ x = 0;
+ y = 2;
+ w = 1;
+ h = tabHeight;
+
+ int last = m_PageTabs.Count();
+ if ( last != 0 )
+ {
+ m_PageTabs[ last - 1 ]->GetBounds( x, y, w, h );
+ }
+
+ // Compute left edge of "fake" tab
+
+ x += ( w + 1 );
+
+ // Compute size of new panel
+ KeyValues *data = msglist[ 0 ];
+ char const *text = data->GetString( "tabname", "" );
+ Assert( text );
+
+ PageTab *fakeTab = new PageTab( this, "FakeTab", text, NULL, _tabWidth, NULL, false );
+ fakeTab->SetBounds( x, 4, w, tabHeight - 4 );
+ fakeTab->SetFont( m_tabFont );
+ SETUP_PANEL( fakeTab );
+ fakeTab->Repaint();
+ surface()->SolveTraverse( fakeTab->GetVPanel(), true );
+ surface()->PaintTraverse( fakeTab->GetVPanel() );
+ delete fakeTab;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : state -
+//-----------------------------------------------------------------------------
+void PropertySheet::SetKBNavigationEnabled( bool state )
+{
+ m_bKBNavigationEnabled = state;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool PropertySheet::IsKBNavigationEnabled() const
+{
+ return m_bKBNavigationEnabled;
+}