2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
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.
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.
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/>.
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.
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.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
32 #include "../../sys/win32/win_local.h"
33 #include "../../sys/win32/rc/common_resource.h"
34 #include "OpenFileDialog.h"
36 char rvOpenFileDialog::mLookin[ MAX_OSPATH ];
40 rvOpenFileDialog::rvOpenFileDialog
45 rvOpenFileDialog::rvOpenFileDialog( void )
56 rvOpenFileDialog::~rvOpenFileDialog
61 rvOpenFileDialog::~rvOpenFileDialog ( void )
65 ImageList_Destroy ( mImageList );
70 DeleteObject ( mBackBitmap );
76 rvOpenFileDialog::DoModal
78 Opens the dialog and returns true if a filename was found
81 bool rvOpenFileDialog::DoModal ( HWND parent )
83 mInstance = win32.hInstance;
85 INITCOMMONCONTROLSEX ex;
86 ex.dwICC = ICC_USEREX_CLASSES | ICC_LISTVIEW_CLASSES;
87 ex.dwSize = sizeof(INITCOMMONCONTROLSEX);
89 InitCommonControlsEx ( &ex );
91 return DialogBoxParam ( mInstance, MAKEINTRESOURCE(IDD_TOOLS_OPEN), parent, DlgProc, (LPARAM)this ) ? true : false;
96 rvOpenFileDialog::UpdateLookIn
98 Updates the lookin combo box with the current lookin state
101 void rvOpenFileDialog::UpdateLookIn ( void )
107 // Reset the combo box
108 SendMessage ( mWndLookin, CB_RESETCONTENT, 0, 0 );
110 // Setup the common item structure components
111 ZeroMemory ( &item, sizeof(item) );
112 item.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
114 // Add the top left folder
115 item.pszText = (LPSTR)"base";
116 SendMessage ( mWndLookin, CBEM_INSERTITEM, 0, (LPARAM)&item );
118 // Break the lookin path up into its individual components and add them
122 while ( path.Length ( ) )
124 int slash = path.Find ( "/" );
126 // Parse out the next subfolder
129 file = path.Left ( slash );
130 path = path.Right ( path.Length ( ) - slash - 1 );
138 // Add the sub folder
139 item.pszText = (LPSTR)file.c_str();
141 item.iItem = item.iIndent;
142 SendMessage ( mWndLookin, CBEM_INSERTITEM, 0, (LPARAM)&item );
145 // Set the selection to the last one since thats the deepest folder
146 SendMessage ( mWndLookin, CB_SETCURSEL, item.iIndent, 0 );
151 rvOpenFileDialog::UpdateFileList
153 Updates the file list with the files that match the filter in the current
157 void rvOpenFileDialog::UpdateFileList ( void )
159 const char *basepath = mLookin;
161 HWND list = GetDlgItem ( mWnd, IDC_TOOLS_FILELIST );
165 ListView_DeleteAllItems ( list );
167 // Add all the folders first
168 files = fileSystem->ListFiles ( basepath, "/", true );
169 for ( i = 0; i < files->GetNumFiles(); i ++ )
171 if ( files->GetFile( i )[0] == '.' )
177 item.mask = LVIF_TEXT;
178 item.iItem = ListView_GetItemCount ( list );
179 item.pszText = (LPSTR)files->GetFile( i );
181 ListView_InsertItem ( list, &item );
183 fileSystem->FreeFileList( files );
185 // Add all the files in the current lookin directory that match the
187 for ( filter = 0; filter < mFilters.Num(); filter ++ )
189 files = fileSystem->ListFiles( basepath, mFilters[filter], true );
190 for ( i = 0; i < files->GetNumFiles(); i ++ )
192 if ( files->GetFile( i )[0] == '.' )
198 item.mask = LVIF_TEXT|LVIF_IMAGE;
200 item.iItem = ListView_GetItemCount( list );
201 item.pszText = (LPSTR)files->GetFile( i );
203 ListView_InsertItem ( list, &item );
205 fileSystem->FreeFileList( files );
211 rvOpenFileDialog::HandleCommandOK
213 Handles the pressing of the OK button but either opening a selected folder
214 or closing the dialog with the resulting filename
217 void rvOpenFileDialog::HandleCommandOK ( void )
222 // If nothing is selected then there is nothing to open
223 int sel = ListView_GetNextItem ( mWndFileList, -1, LVNI_SELECTED );
226 GetWindowText ( GetDlgItem ( mWnd, IDC_TOOLS_FILENAME ), temp, sizeof(temp)-1 );
236 // Get the currently selected item
237 item.mask = LVIF_IMAGE|LVIF_TEXT;
241 item.cchTextMax = 256;
243 ListView_GetItem ( mWndFileList, &item );
246 // If the item is a folder then just open that folder
247 if ( item.iImage == 0 )
249 if ( strlen( mLookin ) )
251 idStr::snPrintf( mLookin, sizeof( mLookin ), "%s/%s", mLookin, temp );
253 idStr::Copynz( mLookin, temp, sizeof( mLookin ) );
258 // If the item is a file then build the filename and end the dialog
259 else if ( item.iImage == 2 )
262 if ( mFilename.Length ( ) )
264 mFilename.Append ( "/" );
266 mFilename.Append ( temp );
268 // Make sure the file exists
269 if ( mFlags & OFD_MUSTEXIST )
272 file = fileSystem->OpenFileRead ( mFilename );
275 MessageBox ( mWnd, va("%s\nFile not found.\nPlease verify the correct file name was given", mFilename.c_str() ), "Open", MB_ICONERROR|MB_OK );
278 fileSystem->CloseFile ( file );
281 EndDialog ( mWnd, 1 );
289 rvOpenFileDialog::HandleInitDialog
291 Handles the init dialog message
294 void rvOpenFileDialog::HandleInitDialog ( void )
296 // Cache the more used window handles
297 mWndFileList = GetDlgItem ( mWnd, IDC_TOOLS_FILELIST );
298 mWndLookin = GetDlgItem ( mWnd, IDC_TOOLS_LOOKIN );
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 );
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 );
308 // Back button is a bitmap button
309 SendMessage( GetDlgItem ( mWnd, IDC_TOOLS_BACK ), BM_SETIMAGE, IMAGE_BITMAP, (LONG) mBackBitmap );
311 // Allow custom titles
312 SetWindowText ( mWnd, mTitle );
314 // Custom ok button title
315 if ( mOKTitle.Length ( ) )
317 SetWindowText ( GetDlgItem ( mWnd, IDOK ), mOKTitle );
320 // See if there is a filename in the lookin
322 idStr filename = mLookin;
323 filename.ExtractFileExtension ( temp );
324 if ( temp.Length ( ) )
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() );
332 // Update our controls
339 rvOpenFileDialog::HandleLookInChange
341 Handles a selection change within the lookin control
344 void rvOpenFileDialog::HandleLookInChange ( void )
353 sel = SendMessage ( mWndLookin, CB_GETCURSEL, 0, 0 );
355 // If something other than base is selected then walk up the list
356 // and build the new lookin path
359 SendMessage ( mWndLookin, CB_GETLBTEXT, 1, (LPARAM)temp );
360 idStr::snPrintf( mLookin, sizeof( mLookin ), "%s", temp );
361 for ( i = 2; i <= sel; i ++ )
363 SendMessage ( mWndLookin, CB_GETLBTEXT, i, (LPARAM)temp );
364 idStr::snPrintf( mLookin, sizeof( mLookin ), "%s/%s", mLookin, temp );
372 // Update the controls with the new lookin path
379 rvOpenFileDialog::SetFilter
381 Set the extensions available in the dialog
384 void rvOpenFileDialog::SetFilter ( const char* s )
389 while ( filters.Length ( ) )
391 int semi = filters.Find ( ';' );
394 filter = filters.Left ( semi );
395 filters = filters.Right ( filters.Length ( ) - semi );
403 mFilters.Append ( filter.c_str() + (filter[0] == '*' ? 1 : 0) );
409 rvOpenFileDialog::DlgProc
411 Dialog Procedure for the open file dialog
414 INT_PTR rvOpenFileDialog::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
416 rvOpenFileDialog* dlg = (rvOpenFileDialog*) GetWindowLong ( wnd, GWL_USERDATA );
421 dlg = (rvOpenFileDialog*) lparam;
422 SetWindowLong ( wnd, GWL_USERDATA, lparam );
424 dlg->HandleInitDialog ( );
429 NMHDR* nm = (NMHDR*) lparam;
430 switch ( nm->idFrom )
432 case IDC_TOOLS_FILELIST:
435 case LVN_ITEMCHANGED:
437 NMLISTVIEW* nmlv = (NMLISTVIEW*)nm;
438 if ( nmlv->uNewState & LVIS_SELECTED )
440 // Get the currently selected item
443 item.mask = LVIF_IMAGE|LVIF_TEXT;
446 item.cchTextMax = sizeof(temp)-1;
447 item.iItem = nmlv->iItem;
448 ListView_GetItem ( dlg->mWndFileList, &item );
450 if ( item.iImage == 2 )
452 SetWindowText ( GetDlgItem ( wnd, IDC_TOOLS_FILENAME ), temp );
459 dlg->HandleCommandOK ( );
468 switch ( LOWORD ( wparam ) )
472 dlg->HandleCommandOK ( );
477 EndDialog ( wnd, 0 );
482 int sel = SendMessage ( GetDlgItem ( wnd, IDC_TOOLS_LOOKIN ), CB_GETCURSEL, 0, 0 );
486 SendMessage ( GetDlgItem ( wnd, IDC_TOOLS_LOOKIN ), CB_SETCURSEL, sel, 0 );
487 dlg->HandleLookInChange ( );
493 case IDC_TOOLS_LOOKIN:
494 if ( HIWORD ( wparam ) == CBN_SELCHANGE )
496 dlg->HandleLookInChange ( );