/* =========================================================================== Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). Doom 3 Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 Source Code. If not, see . 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. 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. =========================================================================== */ #include "tools/edit_gui_common.h" #include "../../sys/win32/win_local.h" #include "../../sys/win32/rc/common_resource.h" #include "OpenFileDialog.h" char rvOpenFileDialog::mLookin[ MAX_OSPATH ]; /* ================ rvOpenFileDialog::rvOpenFileDialog constructor ================ */ rvOpenFileDialog::rvOpenFileDialog( void ) { mWnd = NULL; mInstance = NULL; mBackBitmap = NULL; mImageList = NULL; mFlags = 0; } /* ================ rvOpenFileDialog::~rvOpenFileDialog destructor ================ */ rvOpenFileDialog::~rvOpenFileDialog ( void ) { if ( mImageList ) { ImageList_Destroy ( mImageList ); } if ( mBackBitmap ) { DeleteObject ( mBackBitmap ); } } /* ================ rvOpenFileDialog::DoModal Opens the dialog and returns true if a filename was found ================ */ bool rvOpenFileDialog::DoModal ( HWND parent ) { mInstance = win32.hInstance; INITCOMMONCONTROLSEX ex; ex.dwICC = ICC_USEREX_CLASSES | ICC_LISTVIEW_CLASSES; ex.dwSize = sizeof(INITCOMMONCONTROLSEX); InitCommonControlsEx ( &ex ); return DialogBoxParam ( mInstance, MAKEINTRESOURCE(IDD_TOOLS_OPEN), parent, DlgProc, (LPARAM)this ) ? true : false; } /* ================ rvOpenFileDialog::UpdateLookIn Updates the lookin combo box with the current lookin state ================ */ void rvOpenFileDialog::UpdateLookIn ( void ) { COMBOBOXEXITEM item; idStr file; idStr path; // Reset the combo box SendMessage ( mWndLookin, CB_RESETCONTENT, 0, 0 ); // Setup the common item structure components ZeroMemory ( &item, sizeof(item) ); item.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE; // Add the top left folder item.pszText = (LPSTR)"base"; SendMessage ( mWndLookin, CBEM_INSERTITEM, 0, (LPARAM)&item ); // Break the lookin path up into its individual components and add them // to the combo box path = mLookin; while ( path.Length ( ) ) { int slash = path.Find ( "/" ); // Parse out the next subfolder if ( slash != -1 ) { file = path.Left ( slash ); path = path.Right ( path.Length ( ) - slash - 1 ); } else { file = path; path.Empty ( ); } // Add the sub folder item.pszText = (LPSTR)file.c_str(); item.iIndent++; item.iItem = item.iIndent; SendMessage ( mWndLookin, CBEM_INSERTITEM, 0, (LPARAM)&item ); } // Set the selection to the last one since thats the deepest folder SendMessage ( mWndLookin, CB_SETCURSEL, item.iIndent, 0 ); } /* ================ rvOpenFileDialog::UpdateFileList Updates the file list with the files that match the filter in the current look in directory ================ */ void rvOpenFileDialog::UpdateFileList ( void ) { const char *basepath = mLookin; idFileList *files; HWND list = GetDlgItem ( mWnd, IDC_TOOLS_FILELIST ); int i; int filter; ListView_DeleteAllItems ( list ); // Add all the folders first files = fileSystem->ListFiles ( basepath, "/", true ); for ( i = 0; i < files->GetNumFiles(); i ++ ) { if ( files->GetFile( i )[0] == '.' ) { continue; } LVITEM item; item.mask = LVIF_TEXT; item.iItem = ListView_GetItemCount ( list ); item.pszText = (LPSTR)files->GetFile( i ); item.iSubItem = 0; ListView_InsertItem ( list, &item ); } fileSystem->FreeFileList( files ); // Add all the files in the current lookin directory that match the // current filters. for ( filter = 0; filter < mFilters.Num(); filter ++ ) { files = fileSystem->ListFiles( basepath, mFilters[filter], true ); for ( i = 0; i < files->GetNumFiles(); i ++ ) { if ( files->GetFile( i )[0] == '.' ) { continue; } LVITEM item; item.mask = LVIF_TEXT|LVIF_IMAGE; item.iImage = 2; item.iItem = ListView_GetItemCount( list ); item.pszText = (LPSTR)files->GetFile( i ); item.iSubItem = 0; ListView_InsertItem ( list, &item ); } fileSystem->FreeFileList( files ); } } /* ================ rvOpenFileDialog::HandleCommandOK Handles the pressing of the OK button but either opening a selected folder or closing the dialog with the resulting filename ================ */ void rvOpenFileDialog::HandleCommandOK ( void ) { char temp[256]; LVITEM item; // If nothing is selected then there is nothing to open int sel = ListView_GetNextItem ( mWndFileList, -1, LVNI_SELECTED ); if ( sel == -1 ) { GetWindowText ( GetDlgItem ( mWnd, IDC_TOOLS_FILENAME ), temp, sizeof(temp)-1 ); if ( !temp[0] ) { return; } item.iImage = 2; } else { // Get the currently selected item item.mask = LVIF_IMAGE|LVIF_TEXT; item.iImage = sel; item.iSubItem = 0; item.pszText = temp; item.cchTextMax = 256; item.iItem = sel; ListView_GetItem ( mWndFileList, &item ); } // If the item is a folder then just open that folder if ( item.iImage == 0 ) { if ( strlen( mLookin ) ) { idStr::snPrintf( mLookin, sizeof( mLookin ), "%s/%s", mLookin, temp ); } else { idStr::Copynz( mLookin, temp, sizeof( mLookin ) ); } UpdateLookIn ( ); UpdateFileList ( ); } // If the item is a file then build the filename and end the dialog else if ( item.iImage == 2 ) { mFilename = mLookin; if ( mFilename.Length ( ) ) { mFilename.Append ( "/" ); } mFilename.Append ( temp ); // Make sure the file exists if ( mFlags & OFD_MUSTEXIST ) { idFile* file; file = fileSystem->OpenFileRead ( mFilename ); if ( !file ) { MessageBox ( mWnd, va("%s\nFile not found.\nPlease verify the correct file name was given", mFilename.c_str() ), "Open", MB_ICONERROR|MB_OK ); return; } fileSystem->CloseFile ( file ); } EndDialog ( mWnd, 1 ); } return; } /* ================ rvOpenFileDialog::HandleInitDialog Handles the init dialog message ================ */ void rvOpenFileDialog::HandleInitDialog ( void ) { // Cache the more used window handles mWndFileList = GetDlgItem ( mWnd, IDC_TOOLS_FILELIST ); mWndLookin = GetDlgItem ( mWnd, IDC_TOOLS_LOOKIN ); // Load the custom resources used by the controls mImageList = ImageList_LoadBitmap ( mInstance, MAKEINTRESOURCE(IDB_TOOLS_OPEN),16,1,RGB(255,255,255) ); mBackBitmap = (HBITMAP)LoadImage ( mInstance, MAKEINTRESOURCE(IDB_TOOLS_BACK), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR|LR_LOADMAP3DCOLORS ); // Attach the image list to the file list and lookin controls ListView_SetImageList ( mWndFileList, mImageList, LVSIL_SMALL ); SendMessage( mWndLookin,CBEM_SETIMAGELIST,0,(LPARAM) mImageList ); // Back button is a bitmap button SendMessage( GetDlgItem ( mWnd, IDC_TOOLS_BACK ), BM_SETIMAGE, IMAGE_BITMAP, (LONG_PTR) mBackBitmap ); // Allow custom titles SetWindowText ( mWnd, mTitle ); // Custom ok button title if ( mOKTitle.Length ( ) ) { SetWindowText ( GetDlgItem ( mWnd, IDOK ), mOKTitle ); } // See if there is a filename in the lookin idStr temp; idStr filename = mLookin; filename.ExtractFileExtension ( temp ); if ( temp.Length ( ) ) { filename.ExtractFileName ( temp ); SetWindowText ( GetDlgItem ( mWnd, IDC_TOOLS_FILENAME ), temp ); filename.StripFilename ( ); idStr::snPrintf( mLookin, sizeof( mLookin ), "%s", filename.c_str() ); } // Update our controls UpdateLookIn ( ); UpdateFileList ( ); } /* ================ rvOpenFileDialog::HandleLookInChange Handles a selection change within the lookin control ================ */ void rvOpenFileDialog::HandleLookInChange ( void ) { char temp[256]; int sel; int i; idStr lookin; temp[0] = 0; sel = SendMessage ( mWndLookin, CB_GETCURSEL, 0, 0 ); // If something other than base is selected then walk up the list // and build the new lookin path if ( sel >= 1 ) { SendMessage ( mWndLookin, CB_GETLBTEXT, 1, (LPARAM)temp ); idStr::snPrintf( mLookin, sizeof( mLookin ), "%s", temp ); for ( i = 2; i <= sel; i ++ ) { SendMessage ( mWndLookin, CB_GETLBTEXT, i, (LPARAM)temp ); idStr::snPrintf( mLookin, sizeof( mLookin ), "%s/%s", mLookin, temp ); } } else { mLookin[0] = 0; } // Update the controls with the new lookin path UpdateLookIn ( ); UpdateFileList ( ); } /* ================ rvOpenFileDialog::SetFilter Set the extensions available in the dialog ================ */ void rvOpenFileDialog::SetFilter ( const char* s ) { idStr filters = s; idStr filter; while ( filters.Length ( ) ) { int semi = filters.Find ( ';' ); if ( semi != -1 ) { filter = filters.Left ( semi ); filters = filters.Right ( filters.Length ( ) - semi ); } else { filter = filters; filters.Empty ( ); } mFilters.Append ( filter.c_str() + (filter[0] == '*' ? 1 : 0) ); } } /* ================ rvOpenFileDialog::DlgProc Dialog Procedure for the open file dialog ================ */ INT_PTR rvOpenFileDialog::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ) { rvOpenFileDialog* dlg = (rvOpenFileDialog*) GetWindowLongPtr ( wnd, GWLP_USERDATA ); switch ( msg ) { case WM_INITDIALOG: dlg = (rvOpenFileDialog*) lparam; SetWindowLongPtr ( wnd, GWLP_USERDATA, lparam ); dlg->mWnd = wnd; dlg->HandleInitDialog ( ); return TRUE; case WM_NOTIFY: { NMHDR* nm = (NMHDR*) lparam; switch ( nm->idFrom ) { case IDC_TOOLS_FILELIST: switch ( nm->code ) { case LVN_ITEMCHANGED: { NMLISTVIEW* nmlv = (NMLISTVIEW*)nm; if ( nmlv->uNewState & LVIS_SELECTED ) { // Get the currently selected item LVITEM item; char temp[256]; item.mask = LVIF_IMAGE|LVIF_TEXT; item.iSubItem = 0; item.pszText = temp; item.cchTextMax = sizeof(temp)-1; item.iItem = nmlv->iItem; ListView_GetItem ( dlg->mWndFileList, &item ); if ( item.iImage == 2 ) { SetWindowText ( GetDlgItem ( wnd, IDC_TOOLS_FILENAME ), temp ); } } break; } case NM_DBLCLK: dlg->HandleCommandOK ( ); break; } break; } break; } case WM_COMMAND: switch ( LOWORD ( wparam ) ) { case IDOK: { dlg->HandleCommandOK ( ); break; } case IDCANCEL: EndDialog ( wnd, 0 ); break; case IDC_TOOLS_BACK: { int sel = SendMessage ( GetDlgItem ( wnd, IDC_TOOLS_LOOKIN ), CB_GETCURSEL, 0, 0 ); if ( sel > 0 ) { sel--; SendMessage ( GetDlgItem ( wnd, IDC_TOOLS_LOOKIN ), CB_SETCURSEL, sel, 0 ); dlg->HandleLookInChange ( ); } break; } case IDC_TOOLS_LOOKIN: if ( HIWORD ( wparam ) == CBN_SELCHANGE ) { dlg->HandleLookInChange ( ); } break; } break; } return FALSE; }