dhewm3/neo/tools/common/OpenFileDialog.cpp
2021-06-17 05:44:23 +02:00

505 lines
12 KiB
C++

/*
===========================================================================
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 <http://www.gnu.org/licenses/>.
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 + 1));
filters.Strip(' ');
}
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;
}