summaryrefslogtreecommitdiff
path: root/public/panorama/controls/grid.h
blob: c5f0f6379447dd6b1943410071c13e036653456f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//=========== Copyright Valve Corporation, All rights reserved. ===============//
//
// Purpose: 
//=============================================================================//

#ifndef GRID_H
#define GRID_H

#ifdef _WIN32
#pragma once
#endif

#include "panel2d.h"
#include "panorama/controls/label.h"
#include "panorama/controls/mousescroll.h"

namespace panorama
{

DECLARE_PANEL_EVENT0( ReadyPanelForDisplay )
DECLARE_PANEL_EVENT0( PanelDoneWithDisplay )
DECLARE_PANEL_EVENT0( GridMotionTimeout );
DECLARE_PANEL_EVENT0( GridInFastMotion );
DECLARE_PANEL_EVENT0( GridStoppingFastMotion );
DECLARE_PANEL_EVENT0( GridPageLeft );
DECLARE_PANEL_EVENT0( GridPageRight );
DECLARE_PANEL_EVENT0( GridDirectionalMove );
DECLARE_PANEL_EVENT1( ChildIndexSelected, int );

//-----------------------------------------------------------------------------
// Purpose: Button
//-----------------------------------------------------------------------------
class CGrid : public CPanel2D
{
	DECLARE_PANEL2D( CGrid, CPanel2D );

public:
	CGrid( CPanel2D *parent, const char * pchPanelID );
	virtual ~CGrid();

	CPanel2D * AccessSelectedPanel() { return m_pFocusedChild.Get(); }

	virtual void SetupJavascriptObjectTemplate() OVERRIDE;

	// Scroll the grid so the focused panel is in the top left corner
	void MoveFocusToTopLeft();

	// Scroll the grid all the way to the left regardless of what's
	// focused.
	void ScrollPanelToLeftEdge();

	// Trigger fast motion style temporarily, do this if you are directly setting focus ahead a bunch
	void TriggerFastMotion();
	void BumpFastMotionTimeout();

	void SetHorizontalCount( int nCount ) { SetHorizontalAndVerticalCount( nCount, m_nVerticalCount ); }
	void SetVerticalCount( int nCount ) { SetHorizontalAndVerticalCount( m_nHorizontalCount, nCount ); }
	int GetHorizontalCount() const { return m_nHorizontalCount; }
	int GetVerticalCount() const { return m_nVerticalCount; }

	void SetHorizontalFocusLimit( int nCount ) { m_nHorizontalFocusLimit = nCount; InvalidateSizeAndPosition(); }
	int GetHorizontalFocusLimit() const { return m_nHorizontalFocusLimit; }

	float GetScrollProgress() const { return m_flScrollProgress; }

	virtual bool OnMoveUp( int nRepeats );
	virtual bool OnMoveDown( int nRepeats );
	virtual bool OnMoveRight( int nRepeats );
	virtual bool OnMoveLeft( int nRepeats );
	virtual bool OnTabForward( int nRepeats );
	virtual bool OnTabBackward( int nRepeats );
	virtual bool OnMouseWheel( const panorama::MouseData_t &code );
	virtual bool OnGamePadDown( const panorama::GamePadData_t &code );
	virtual bool OnKeyDown( const KeyData_t &code );

	virtual bool BRequiresContentClipLayer() OVERRIDE { return true; }

	virtual void Paint();
	virtual bool OnSetFocusToNextPanel( int nRepeats, EFocusMoveDirection moveType, bool bAllowWrap, float flTabIndexCurrent, float flXPosCurrent, float flYPosCurrent, float flXStart, float fYStart ) OVERRIDE
	{
		switch( moveType )
		{
		case k_ENextInTabOrder:
			if ( OnTabForward( nRepeats ) )
				return true;
			break;
		case k_ENextByXPosition:
			if ( OnMoveRight( nRepeats ) )
				return true;
			break;
		case k_EPrevInTabOrder:
			if ( OnTabBackward( nRepeats ) )
				return true;
			break;
		case k_EPrevByXPosition:
			if ( OnMoveLeft( nRepeats ) )
				return true;
			break;
		case k_ENextByYPosition:
			if ( OnMoveDown( nRepeats ) )
				return true;
			break;
		case k_EPrevByYPosition:
			if ( OnMoveUp( nRepeats ) )
				return true;
			break;
		default:
			break;
		}

		return false;
	}

	void SetHorizontalAndVerticalCount( int nHorizontalCount, int nVerticalCount );

	void SetIgnoreFastMotion( bool bValue ) { m_bIgnoreFastMotion = bValue; }

#ifdef DBGFLAG_VALIDATE
	virtual void ValidateClientPanel( CValidator &validator, const tchar *pchName ) OVERRIDE;
#endif

protected:
	virtual bool BSetProperty( CPanoramaSymbol symName, const char *pchValue ) OVERRIDE;
	virtual void OnLayoutTraverse( float flFinalWidth, float flFinalHeight );
	virtual void OnBeforeChildrenChanged() { m_bForceRelayout = true;  }

	virtual void OnChildStylesChanged() OVERRIDE { m_bVecVisibleDirty = true; }
	virtual void OnAfterChildrenChanged() OVERRIDE { m_bVecVisibleDirty = true; }
private:

	void UpdateVecVisible();
	int GetVisibleChildCount();
	CPanel2D *GetVisibleChild( int iVisibleIndex );

	// event handlers
	bool EventInputFocusSet( const CPanelPtr< IUIPanel > &ptrPanel );
	bool EventInputFocusLost( const CPanelPtr< IUIPanel > &ptrPanel );
	bool MotionTimeout( const CPanelPtr< IUIPanel > &ptrPanel );
	bool OnMouseScroll( const CPanelPtr< IUIPanel > &ptrPanel, int cRepeat );
	void LayoutMouseScrollRegions( float flFinalWidth, float flFinalHeight );
	bool EventWindowCursorShown( IUIWindow *pWindow );
	bool EventWindowCursorHidden( IUIWindow *pWindow );

	void RegisterForCursorChanges();
	void UnregisterForCursorChanges();

	int GetFocusedChildVisibleIndex();
	void UpdateChildPositions( bool bForceTopLeft = false );

	bool m_bHadFocus;

	CPanelPtr< CPanel2D > m_pFocusedChild;
	CUtlVector< CPanelPtr<CPanel2D> > m_vecPanelsReadyForDisplay;

	int m_nScrollOffset;

	float m_flChildWidth;
	float m_flChildHeight;
	float m_flScaleOffset;

	float m_flScrollProgress;

	int m_nHorizontalCount;
	int m_nVerticalCount;
	
	// Override how far right you can move before all items must shift, should be smaller than m_nHorizontalCount
	int m_nHorizontalFocusLimit;

	double m_flLastMouseWheel;
	bool m_bForceRelayout;

	bool m_bIgnoreFastMotion;
	double m_flStartedMotion;
	double m_flLastMotion;
	uint64 m_ulMotionSinceStart;
	bool m_bFastMotionStarted;
	bool m_bVecVisibleDirty;

	CUtlVector< CPanel2D * > m_vecVisibleChildren;
	
	panorama::CMouseScrollRegion *m_pLeftMouseScrollRegion;
	panorama::CMouseScrollRegion *m_pRightMouseScrollRegion;

};


} // namespace panorama

#endif // GRID_H