summaryrefslogtreecommitdiff
path: root/public/panorama/controls/fileopendialog.h
blob: 79dc451403f37b5b5598fab049d389f632bf73aa (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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//=========== Copyright Valve Corporation, All rights reserved. ===============//
//
// Purpose: 
//=============================================================================//

#ifndef PANORAMA_FILEOPENDIALOG_H
#define PANORAMA_FILEOPENDIALOG_H

#ifdef _WIN32
#pragma once
#endif

#include "panel2d.h"
#include "../uievent.h"
#include "panorama/controls/button.h"

namespace panorama
{

class CDropDown;
class CLabel;
class CTextEntry;
class CFileOpenDialogEntry;

DECLARE_PANORAMA_EVENT0( FileOpenDialogOpen );
DECLARE_PANORAMA_EVENT0( FileOpenDialogCancel );
DECLARE_PANORAMA_EVENT0( FileOpenDialogClose );
DECLARE_PANORAMA_EVENT0( FileOpenDialogFolderUp );
DECLARE_PANEL_EVENT1( FileOpenDialogSortByColumn, int );
DECLARE_PANEL_EVENT1( FileOpenDialogSelectFile, uint32 );
DECLARE_PANEL_EVENT1( FileOpenDialogDoubleClickFile, uint32 );
DECLARE_PANORAMA_EVENT0( FileOpenDialogFullPathChanged );
DECLARE_PANORAMA_EVENT0( FileOpenDialogFilterChanged );
DECLARE_PANEL_EVENT1( FileOpenDialogFilesSelected, const char * );

//-----------------------------------------------------------------------------
// Purpose: generic open/save as file dialog, by default deletes itself on close
//-----------------------------------------------------------------------------
enum FileOpenDialogType_t
{
	FOD_SAVE = 0,
	FOD_OPEN,
	FOD_SELECT_DIRECTORY,
	FOD_OPEN_MULTIPLE,
};

struct FileData_t
{
	CUtlString		m_FileAttributes;
	CUtlString		m_CreationTime;
	int64			m_nCreationTime;
	CUtlString		m_LastAccessTime;
	CUtlString		m_LastWriteTime;
	int64			m_nLastWriteTime;
	int64			m_nFileSize;
	CUtlString		m_FileName;
	CUtlString		m_FullPath;
	CUtlString		m_FileType;

	bool			m_bDirectory;
};

enum FileOpenDialogSorting_t
{
	FOD_SORT_NAME = 0,
	FOD_SORT_SIZE,
	FOD_SORT_TYPE,
	FOD_SORT_DATE_MODIFIED
};

//-----------------------------------------------------------------------------
// Purpose: FileOpenDialog
//-----------------------------------------------------------------------------
class CFileOpenDialog : public CPanel2D
{
	DECLARE_PANEL2D( CFileOpenDialog, CPanel2D );

public:
	CFileOpenDialog( CPanel2D *parent, const char * pchPanelID, FileOpenDialogType_t type );
	CFileOpenDialog( panorama::IUIWindow *pParent, const char * pchPanelID, FileOpenDialogType_t type );
	virtual ~CFileOpenDialog();

	// Set the directory the file search starts in
	void SetStartDirectory(const char *dir);

	// Sets the start directory context (and resets the start directory in the process)
	// NOTE: If you specify a startdir context, then if you've already opened
	// a file with that same start dir context before, it will start in the
	// same directory it ended up in.
	void SetStartDirectoryContext( const char *pContext, const char *pDefaultDir );

	// Add filters for the drop down combo box
	// The filter info, if specified, gets sent back to the app in the FileSelected message
	void AddFilter( const char *filter, const char *filterName, bool bActive, const char *pFilterInfo = NULL );

	// Get the directory this is currently in
	void GetDirectory( char *buf, int bufSize );

	// Get the last selected file name
	void GetSelectedFileName( char *buf, int bufSize );

	/*
		messages sent:
			"FileSelected"
				"fullpath"	// specifies the fullpath of the file
				"filterinfo"	// Returns the filter info associated with the active filter
			"FileSelectionCancelled"
	*/

	static bool FileNameWildCardMatch( char const *pchFileName, char const *pchPattern );

	// event handlers
	bool EventOpen();
	bool EventCancel();
	bool EventClose();
	bool EventFolderUp();
	bool EventColumnSortingChanged( const CPanelPtr< IUIPanel > &pPanel, int nColumn );
	bool EventSelectFile( const CPanelPtr< IUIPanel > &pPanel, uint32 unModifiers );
	bool EventDoubleClickFile( const CPanelPtr< IUIPanel > &pPanel, uint32 unModifiers );
	bool EventFullPathChanged();
	bool EventFilterChanged();

protected:
	void Init();

	void PopulateFileList();
	void PopulateDriveList();

	void OnOpen();

	// TODO: needs message? hooked up to buttons/rows?
	void OnSelectFolder();
	void OnMatchStringSelected();

	// moves the directory structure up
	void MoveUpFolder();

	// validates that the current path is valid
	void ValidatePath();

private:

	// Does the specified extension match something in the filter list?
	bool ExtensionMatchesFilter( const char *pExt );

	// Choose the first non *.* filter in the filter list
	void ChooseExtension( char *pExt, int nBufLen );

	// Saves the file to the start dir context
	void SaveFileToStartDirContext( const char *pFullPath );

	// Posts a file selected message
	void PostFileSelectedMessage( const char *pFileName );

	// Posts a multiple file selected message
	void PostMultiFileSelectedMessage();

	void BuildFileList();
	void FilterFileList();
	void SortEntries();

	bool PassesFilter( FileData_t *fd );
	int  CountSubstringMatches();

	void DeselectAllEntries();

	CDropDown 		*m_pFullPathDropDown;
	CPanel2D		*m_pFileList;	// TODO: custom spreadsheet style control?
	
	CTextEntry 		*m_pFileNameTextEntry;

	CDropDown 		*m_pFileTypeCombo;
	CButton 		*m_pOpenButton;
	CButton 		*m_pCancelButton;
	CButton 		*m_pFolderUpButton;
	CLabel			*m_pFileTypeLabel;
	CUtlVector<CPanel2D*> m_vecColumnHeaders;

	KeyValues			*m_pContextKeyValues;

	FileOpenDialogSorting_t m_nSorting;
	bool m_bSortingReversed;

	char m_szLastPath[1024];
	unsigned short m_nStartDirContext;
	FileOpenDialogType_t m_DialogType;
	bool m_bFileSelected : 1;

	CUtlVector< FileData_t > m_Files;
	CUtlVector< FileData_t * > m_Filtered;

	CUtlVector< CFileOpenDialogEntry* > m_vecSelectedEntries;

	CUtlString			m_CurrentSubstringFilter;
};

//-----------------------------------------------------------------------------
// Purpose: CFileOpenDialogEntry - single row in the dialog, represents one file
//-----------------------------------------------------------------------------
class CFileOpenDialogEntry : public CButton
{
	DECLARE_PANEL2D( CFileOpenDialogEntry, CButton );

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

	void SetFileData( FileData_t *pFileData );
	const FileData_t* GetFileData() const { return &m_FileData; }

	virtual bool OnMouseButtonUp( const panorama::MouseData_t &code ) OVERRIDE;
	virtual bool OnMouseButtonDoubleClick( const panorama::MouseData_t &code ) OVERRIDE;

	bool OnScrolledIntoView( const CPanelPtr< IUIPanel > &panelPtr );

private:
	FileData_t m_FileData;

	bool m_bCreatedControls;
};

} // namespace panorama

#endif // PANORAMA_FILEOPENDIALOG_H