diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/vgui2/vgui_controls/PropertySheet.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-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.cpp | 3348 |
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; +} |