doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OpenFileDialog.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "../../sys/win32/win_local.h"
33 #include "../../sys/win32/rc/common_resource.h"
34 #include "OpenFileDialog.h"
35 
37 
38 /*
39 ================
40 rvOpenFileDialog::rvOpenFileDialog
41 
42 constructor
43 ================
44 */
46 {
47  mWnd = NULL;
48  mInstance = NULL;
49  mBackBitmap = NULL;
50  mImageList = NULL;
51  mFlags = 0;
52 }
53 
54 /*
55 ================
56 rvOpenFileDialog::~rvOpenFileDialog
57 
58 destructor
59 ================
60 */
62 {
63  if ( mImageList )
64  {
65  ImageList_Destroy ( mImageList );
66  }
67 
68  if ( mBackBitmap )
69  {
70  DeleteObject ( mBackBitmap );
71  }
72 }
73 
74 /*
75 ================
76 rvOpenFileDialog::DoModal
77 
78 Opens the dialog and returns true if a filename was found
79 ================
80 */
81 bool rvOpenFileDialog::DoModal ( HWND parent )
82 {
84 
85  INITCOMMONCONTROLSEX ex;
86  ex.dwICC = ICC_USEREX_CLASSES | ICC_LISTVIEW_CLASSES;
87  ex.dwSize = sizeof(INITCOMMONCONTROLSEX);
88 
89  InitCommonControlsEx ( &ex );
90 
91  return DialogBoxParam ( mInstance, MAKEINTRESOURCE(IDD_TOOLS_OPEN), parent, DlgProc, (LPARAM)this ) ? true : false;
92 }
93 
94 /*
95 ================
96 rvOpenFileDialog::UpdateLookIn
97 
98 Updates the lookin combo box with the current lookin state
99 ================
100 */
102 {
103  COMBOBOXEXITEM item;
104  idStr file;
105  idStr path;
106 
107  // Reset the combo box
108  SendMessage ( mWndLookin, CB_RESETCONTENT, 0, 0 );
109 
110  // Setup the common item structure components
111  ZeroMemory ( &item, sizeof(item) );
112  item.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
113 
114  // Add the top left folder
115  item.pszText = (LPSTR)"base";
116  SendMessage ( mWndLookin, CBEM_INSERTITEM, 0, (LPARAM)&item );
117 
118  // Break the lookin path up into its individual components and add them
119  // to the combo box
120  path = mLookin;
121 
122  while ( path.Length ( ) )
123  {
124  int slash = path.Find ( "/" );
125 
126  // Parse out the next subfolder
127  if ( slash != -1 )
128  {
129  file = path.Left ( slash );
130  path = path.Right ( path.Length ( ) - slash - 1 );
131  }
132  else
133  {
134  file = path;
135  path.Empty ( );
136  }
137 
138  // Add the sub folder
139  item.pszText = (LPSTR)file.c_str();
140  item.iIndent++;
141  item.iItem = item.iIndent;
142  SendMessage ( mWndLookin, CBEM_INSERTITEM, 0, (LPARAM)&item );
143  }
144 
145  // Set the selection to the last one since thats the deepest folder
146  SendMessage ( mWndLookin, CB_SETCURSEL, item.iIndent, 0 );
147 }
148 
149 /*
150 ================
151 rvOpenFileDialog::UpdateFileList
152 
153 Updates the file list with the files that match the filter in the current
154 look in directory
155 ================
156 */
158 {
159  const char *basepath = mLookin;
160  idFileList *files;
161  HWND list = GetDlgItem ( mWnd, IDC_TOOLS_FILELIST );
162  int i;
163  int filter;
164 
165  ListView_DeleteAllItems ( list );
166 
167  // Add all the folders first
168  files = fileSystem->ListFiles ( basepath, "/", true );
169  for ( i = 0; i < files->GetNumFiles(); i ++ )
170  {
171  if ( files->GetFile( i )[0] == '.' )
172  {
173  continue;
174  }
175 
176  LVITEM item;
177  item.mask = LVIF_TEXT;
178  item.iItem = ListView_GetItemCount ( list );
179  item.pszText = (LPSTR)files->GetFile( i );
180  item.iSubItem = 0;
181  ListView_InsertItem ( list, &item );
182  }
183  fileSystem->FreeFileList( files );
184 
185  // Add all the files in the current lookin directory that match the
186  // current filters.
187  for ( filter = 0; filter < mFilters.Num(); filter ++ )
188  {
189  files = fileSystem->ListFiles( basepath, mFilters[filter], true );
190  for ( i = 0; i < files->GetNumFiles(); i ++ )
191  {
192  if ( files->GetFile( i )[0] == '.' )
193  {
194  continue;
195  }
196 
197  LVITEM item;
198  item.mask = LVIF_TEXT|LVIF_IMAGE;
199  item.iImage = 2;
200  item.iItem = ListView_GetItemCount( list );
201  item.pszText = (LPSTR)files->GetFile( i );
202  item.iSubItem = 0;
203  ListView_InsertItem ( list, &item );
204  }
205  fileSystem->FreeFileList( files );
206  }
207 }
208 
209 /*
210 ================
211 rvOpenFileDialog::HandleCommandOK
212 
213 Handles the pressing of the OK button but either opening a selected folder
214 or closing the dialog with the resulting filename
215 ================
216 */
218 {
219  char temp[256];
220  LVITEM item;
221 
222  // If nothing is selected then there is nothing to open
223  int sel = ListView_GetNextItem ( mWndFileList, -1, LVNI_SELECTED );
224  if ( sel == -1 )
225  {
226  GetWindowText ( GetDlgItem ( mWnd, IDC_TOOLS_FILENAME ), temp, sizeof(temp)-1 );
227  if ( !temp[0] )
228  {
229  return;
230  }
231 
232  item.iImage = 2;
233  }
234  else
235  {
236  // Get the currently selected item
237  item.mask = LVIF_IMAGE|LVIF_TEXT;
238  item.iImage = sel;
239  item.iSubItem = 0;
240  item.pszText = temp;
241  item.cchTextMax = 256;
242  item.iItem = sel;
243  ListView_GetItem ( mWndFileList, &item );
244  }
245 
246  // If the item is a folder then just open that folder
247  if ( item.iImage == 0 )
248  {
249  if ( strlen( mLookin ) )
250  {
251  idStr::snPrintf( mLookin, sizeof( mLookin ), "%s/%s", mLookin, temp );
252  } else {
253  idStr::Copynz( mLookin, temp, sizeof( mLookin ) );
254  }
255  UpdateLookIn ( );
256  UpdateFileList ( );
257  }
258  // If the item is a file then build the filename and end the dialog
259  else if ( item.iImage == 2 )
260  {
261  mFilename = mLookin;
262  if ( mFilename.Length ( ) )
263  {
264  mFilename.Append ( "/" );
265  }
266  mFilename.Append ( temp );
267 
268  // Make sure the file exists
269  if ( mFlags & OFD_MUSTEXIST )
270  {
271  idFile* file;
272  file = fileSystem->OpenFileRead ( mFilename );
273  if ( !file )
274  {
275  MessageBox ( mWnd, va("%s\nFile not found.\nPlease verify the correct file name was given", mFilename.c_str() ), "Open", MB_ICONERROR|MB_OK );
276  return;
277  }
278  fileSystem->CloseFile ( file );
279  }
280 
281  EndDialog ( mWnd, 1 );
282  }
283 
284  return;
285 }
286 
287 /*
288 ================
289 rvOpenFileDialog::HandleInitDialog
290 
291 Handles the init dialog message
292 ================
293 */
295 {
296  // Cache the more used window handles
297  mWndFileList = GetDlgItem ( mWnd, IDC_TOOLS_FILELIST );
298  mWndLookin = GetDlgItem ( mWnd, IDC_TOOLS_LOOKIN );
299 
300  // Load the custom resources used by the controls
301  mImageList = ImageList_LoadBitmap ( mInstance, MAKEINTRESOURCE(IDB_TOOLS_OPEN),16,1,RGB(255,255,255) );
302  mBackBitmap = (HBITMAP)LoadImage ( mInstance, MAKEINTRESOURCE(IDB_TOOLS_BACK), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR|LR_LOADMAP3DCOLORS );
303 
304  // Attach the image list to the file list and lookin controls
305  ListView_SetImageList ( mWndFileList, mImageList, LVSIL_SMALL );
306  SendMessage( mWndLookin,CBEM_SETIMAGELIST,0,(LPARAM) mImageList );
307 
308  // Back button is a bitmap button
309  SendMessage( GetDlgItem ( mWnd, IDC_TOOLS_BACK ), BM_SETIMAGE, IMAGE_BITMAP, (LONG) mBackBitmap );
310 
311  // Allow custom titles
312  SetWindowText ( mWnd, mTitle );
313 
314  // Custom ok button title
315  if ( mOKTitle.Length ( ) )
316  {
317  SetWindowText ( GetDlgItem ( mWnd, IDOK ), mOKTitle );
318  }
319 
320  // See if there is a filename in the lookin
321  idStr temp;
322  idStr filename = mLookin;
323  filename.ExtractFileExtension ( temp );
324  if ( temp.Length ( ) )
325  {
326  filename.ExtractFileName ( temp );
327  SetWindowText ( GetDlgItem ( mWnd, IDC_TOOLS_FILENAME ), temp );
328  filename.StripFilename ( );
329  idStr::snPrintf( mLookin, sizeof( mLookin ), "%s", filename.c_str() );
330  }
331 
332  // Update our controls
333  UpdateLookIn ( );
334  UpdateFileList ( );
335 }
336 
337 /*
338 ================
339 rvOpenFileDialog::HandleLookInChange
340 
341 Handles a selection change within the lookin control
342 ================
343 */
345 {
346  char temp[256];
347  int sel;
348  int i;
349  idStr lookin;
350 
351  temp[0] = 0;
352 
353  sel = SendMessage ( mWndLookin, CB_GETCURSEL, 0, 0 );
354 
355  // If something other than base is selected then walk up the list
356  // and build the new lookin path
357  if ( sel >= 1 )
358  {
359  SendMessage ( mWndLookin, CB_GETLBTEXT, 1, (LPARAM)temp );
360  idStr::snPrintf( mLookin, sizeof( mLookin ), "%s", temp );
361  for ( i = 2; i <= sel; i ++ )
362  {
363  SendMessage ( mWndLookin, CB_GETLBTEXT, i, (LPARAM)temp );
364  idStr::snPrintf( mLookin, sizeof( mLookin ), "%s/%s", mLookin, temp );
365  }
366  }
367  else
368  {
369  mLookin[0] = 0;
370  }
371 
372  // Update the controls with the new lookin path
373  UpdateLookIn ( );
374  UpdateFileList ( );
375 }
376 
377 /*
378 ================
379 rvOpenFileDialog::SetFilter
380 
381 Set the extensions available in the dialog
382 ================
383 */
384 void rvOpenFileDialog::SetFilter ( const char* s )
385 {
386  idStr filters = s;
387  idStr filter;
388 
389  while ( filters.Length ( ) )
390  {
391  int semi = filters.Find ( ';' );
392  if ( semi != -1 )
393  {
394  filter = filters.Left ( semi );
395  filters = filters.Right ( filters.Length ( ) - semi );
396  }
397  else
398  {
399  filter = filters;
400  filters.Empty ( );
401  }
402 
403  mFilters.Append ( filter.c_str() + (filter[0] == '*' ? 1 : 0) );
404  }
405 }
406 
407 /*
408 ================
409 rvOpenFileDialog::DlgProc
410 
411 Dialog Procedure for the open file dialog
412 ================
413 */
414 INT_PTR rvOpenFileDialog::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
415 {
416  rvOpenFileDialog* dlg = (rvOpenFileDialog*) GetWindowLong ( wnd, GWL_USERDATA );
417 
418  switch ( msg )
419  {
420  case WM_INITDIALOG:
421  dlg = (rvOpenFileDialog*) lparam;
422  SetWindowLong ( wnd, GWL_USERDATA, lparam );
423  dlg->mWnd = wnd;
424  dlg->HandleInitDialog ( );
425  return TRUE;
426 
427  case WM_NOTIFY:
428  {
429  NMHDR* nm = (NMHDR*) lparam;
430  switch ( nm->idFrom )
431  {
432  case IDC_TOOLS_FILELIST:
433  switch ( nm->code )
434  {
435  case LVN_ITEMCHANGED:
436  {
437  NMLISTVIEW* nmlv = (NMLISTVIEW*)nm;
438  if ( nmlv->uNewState & LVIS_SELECTED )
439  {
440  // Get the currently selected item
441  LVITEM item;
442  char temp[256];
443  item.mask = LVIF_IMAGE|LVIF_TEXT;
444  item.iSubItem = 0;
445  item.pszText = temp;
446  item.cchTextMax = sizeof(temp)-1;
447  item.iItem = nmlv->iItem;
448  ListView_GetItem ( dlg->mWndFileList, &item );
449 
450  if ( item.iImage == 2 )
451  {
452  SetWindowText ( GetDlgItem ( wnd, IDC_TOOLS_FILENAME ), temp );
453  }
454  }
455  break;
456  }
457 
458  case NM_DBLCLK:
459  dlg->HandleCommandOK ( );
460  break;
461  }
462  break;
463  }
464  break;
465  }
466 
467  case WM_COMMAND:
468  switch ( LOWORD ( wparam ) )
469  {
470  case IDOK:
471  {
472  dlg->HandleCommandOK ( );
473  break;
474  }
475 
476  case IDCANCEL:
477  EndDialog ( wnd, 0 );
478  break;
479 
480  case IDC_TOOLS_BACK:
481  {
482  int sel = SendMessage ( GetDlgItem ( wnd, IDC_TOOLS_LOOKIN ), CB_GETCURSEL, 0, 0 );
483  if ( sel > 0 )
484  {
485  sel--;
486  SendMessage ( GetDlgItem ( wnd, IDC_TOOLS_LOOKIN ), CB_SETCURSEL, sel, 0 );
487  dlg->HandleLookInChange ( );
488  }
489 
490  break;
491  }
492 
493  case IDC_TOOLS_LOOKIN:
494  if ( HIWORD ( wparam ) == CBN_SELCHANGE )
495  {
496  dlg->HandleLookInChange ( );
497  }
498  break;
499  }
500  break;
501  }
502 
503  return FALSE;
504 }
virtual idFile * OpenFileRead(const char *relativePath, bool allowCopyFiles=true, const char *gamedir=NULL)=0
void UpdateLookIn(void)
static int snPrintf(char *dest, int size, const char *fmt,...) id_attribute((format(printf
Definition: Str.cpp:1465
#define IDD_TOOLS_OPEN
virtual idFileList * ListFiles(const char *relativePath, const char *extension, bool sort=false, bool fullRelativePath=false, const char *gamedir=NULL)=0
void HandleInitDialog(void)
#define OFD_MUSTEXIST
CONST PIXELFORMATDESCRIPTOR UINT
Definition: win_qgl.cpp:47
static char mLookin[MAX_OSPATH]
HIMAGELIST mImageList
int Length(void) const
Definition: Str.h:702
int GetNumFiles(void) const
Definition: FileSystem.h:126
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
void HandleCommandOK(void)
const char * Left(int len, idStr &result) const
Definition: Str.h:892
GLdouble s
Definition: glext.h:2935
int i
Definition: process.py:33
#define IDC_TOOLS_LOOKIN
Definition: File.h:50
#define IDC_TOOLS_FILELIST
void ExtractFileName(idStr &dest) const
Definition: Str.cpp:921
void Empty(void)
Definition: Str.h:714
#define NULL
Definition: Lib.h:88
const char * GetFile(int index) const
Definition: FileSystem.h:127
static void Copynz(char *dest, const char *src, int destsize)
Definition: Str.cpp:1376
const char * path
Definition: sws.c:117
const char * Right(int len, idStr &result) const
Definition: Str.h:896
int Find(const char c, int start=0, int end=-1) const
Definition: Str.h:874
virtual void FreeFileList(idFileList *fileList)=0
#define MAX_OSPATH
Definition: posix_main.cpp:47
#define IDB_TOOLS_BACK
long LONG
int Append(const type &obj)
Definition: List.h:646
idStrList mFilters
void HandleLookInChange(void)
GLenum filter
Definition: glext.h:3704
void Append(const char a)
Definition: Str.h:729
int Num(void) const
Definition: List.h:265
Definition: Str.h:116
static INT_PTR CALLBACK DlgProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
const char * c_str(void) const
Definition: Str.h:487
#define FALSE
Definition: mprintf.c:70
#define IDC_TOOLS_FILENAME
HINSTANCE mInstance
#define TRUE
Definition: mprintf.c:69
void UpdateFileList(void)
HINSTANCE hInstance
Definition: win_local.h:102
char * va(const char *fmt,...)
Definition: Str.cpp:1568
void ExtractFileExtension(idStr &dest) const
Definition: Str.cpp:965
Win32Vars_t win32
Definition: win_main.cpp:65
virtual void CloseFile(idFile *f)=0
bool DoModal(HWND parent)
#define IDB_TOOLS_OPEN
idStr & StripFilename(void)
Definition: Str.cpp:864
#define IDC_TOOLS_BACK
void SetFilter(const char *filter)