X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ab1ce969dfb27f5d366ee6a0de3ff2bc0205b56a..f740587c9d406b5c7087853b85dbbb353362cb9a:/src/generic/filedlgg.cpp diff --git a/src/generic/filedlgg.cpp b/src/generic/filedlgg.cpp index 2bbe652c8d..f34ff0a9ed 100644 --- a/src/generic/filedlgg.cpp +++ b/src/generic/filedlgg.cpp @@ -19,11 +19,14 @@ #if wxUSE_FILEDLG // NOTE : it probably also supports MAC, untested -#if !defined(__UNIX__) && !defined(__DOS__) && !defined(__WIN32__) && !defined(__OS2__) +#if !defined(__UNIX__) && !defined(__DOS__) && !defined(__WIN32__) && !defined(__OS2__) && !defined(__PALMOS__) #error wxGenericFileDialog currently only supports Unix, win32 and DOS #endif #ifndef WX_PRECOMP + #ifdef __WXMSW__ + #include "wx/msw/wrapwin.h" + #endif #include "wx/hash.h" #include "wx/intl.h" #include "wx/settings.h" @@ -31,28 +34,30 @@ #include "wx/msgdlg.h" #include "wx/bmpbuttn.h" #include "wx/checkbox.h" + #include "wx/choice.h" + #include "wx/stattext.h" + #include "wx/textctrl.h" + #include "wx/sizer.h" + #include "wx/filedlg.h" // wxFD_OPEN, wxFD_SAVE... #endif -#include "wx/textctrl.h" -#include "wx/choice.h" -#include "wx/stattext.h" #include "wx/longlong.h" -#include "wx/sizer.h" -#include "wx/tokenzr.h" #include "wx/config.h" #include "wx/imaglist.h" -#include "wx/dir.h" #include "wx/artprov.h" #include "wx/filefn.h" -#include "wx/file.h" // for wxS_IXXX constants only -#include "wx/filedlg.h" // wxFD_OPEN, wxFD_SAVE... +#include "wx/filectrl.h" #include "wx/generic/filedlgg.h" -#include "wx/generic/dirctrlg.h" // for wxFileIconsTable +#include "wx/debug.h" #if wxUSE_TOOLTIPS #include "wx/tooltip.h" #endif +#if wxUSE_CONFIG + #include "wx/config.h" +#endif +#ifndef __WXPALMOS5__ #ifndef __WXWINCE__ #include #include @@ -67,7 +72,6 @@ #endif #ifdef __WINDOWS__ - #include "wx/msw/wrapwin.h" #include "wx/msw/mslu.h" #endif @@ -82,90 +86,7 @@ #if defined(__UNIX__) || defined(__DOS__) #include #endif - -// ---------------------------------------------------------------------------- -// private functions -// ---------------------------------------------------------------------------- - -static -int wxCALLBACK wxFileDataNameCompare( long data1, long data2, long sortOrder) -{ - wxFileData *fd1 = (wxFileData *)wxUIntToPtr(data1); - wxFileData *fd2 = (wxFileData *)wxUIntToPtr(data2); - - if (fd1->GetFileName() == wxT("..")) - return -sortOrder; - if (fd2->GetFileName() == wxT("..")) - return sortOrder; - if (fd1->IsDir() && !fd2->IsDir()) - return -sortOrder; - if (fd2->IsDir() && !fd1->IsDir()) - return sortOrder; - - return sortOrder*wxStrcmp( fd1->GetFileName(), fd2->GetFileName() ); -} - -static -int wxCALLBACK wxFileDataSizeCompare(long data1, long data2, long sortOrder) -{ - wxFileData *fd1 = (wxFileData *)wxUIntToPtr(data1); - wxFileData *fd2 = (wxFileData *)wxUIntToPtr(data2); - - if (fd1->GetFileName() == wxT("..")) - return -sortOrder; - if (fd2->GetFileName() == wxT("..")) - return sortOrder; - if (fd1->IsDir() && !fd2->IsDir()) - return -sortOrder; - if (fd2->IsDir() && !fd1->IsDir()) - return sortOrder; - if (fd1->IsLink() && !fd2->IsLink()) - return -sortOrder; - if (fd2->IsLink() && !fd1->IsLink()) - return sortOrder; - - return fd1->GetSize() > fd2->GetSize() ? sortOrder : -sortOrder; -} - -static -int wxCALLBACK wxFileDataTypeCompare(long data1, long data2, long sortOrder) -{ - wxFileData *fd1 = (wxFileData *)wxUIntToPtr(data1); - wxFileData *fd2 = (wxFileData *)wxUIntToPtr(data2); - - if (fd1->GetFileName() == wxT("..")) - return -sortOrder; - if (fd2->GetFileName() == wxT("..")) - return sortOrder; - if (fd1->IsDir() && !fd2->IsDir()) - return -sortOrder; - if (fd2->IsDir() && !fd1->IsDir()) - return sortOrder; - if (fd1->IsLink() && !fd2->IsLink()) - return -sortOrder; - if (fd2->IsLink() && !fd1->IsLink()) - return sortOrder; - - return sortOrder*wxStrcmp( fd1->GetFileType(), fd2->GetFileType() ); -} - -static -int wxCALLBACK wxFileDataTimeCompare(long data1, long data2, long sortOrder) -{ - wxFileData *fd1 = (wxFileData *)wxUIntToPtr(data1); - wxFileData *fd2 = (wxFileData *)wxUIntToPtr(data2); - - if (fd1->GetFileName() == wxT("..")) - return -sortOrder; - if (fd2->GetFileName() == wxT("..")) - return sortOrder; - if (fd1->IsDir() && !fd2->IsDir()) - return -sortOrder; - if (fd2->IsDir() && !fd1->IsDir()) - return sortOrder; - - return fd1->GetDateTime().IsLaterThan(fd2->GetDateTime()) ? sortOrder : -sortOrder; -} +#endif // ! __WXPALMOS5__ #if defined(__WXWINCE__) #define IsTopMostDir(dir) (dir == wxT("\\") || dir == wxT("/")) @@ -175,779 +96,32 @@ int wxCALLBACK wxFileDataTimeCompare(long data1, long data2, long sortOrder) #define IsTopMostDir(dir) (dir == wxT("/")) #endif -// defined in src/generic/dirctrlg.cpp -extern size_t wxGetAvailableDrives(wxArrayString &paths, wxArrayString &names, wxArrayInt &icon_ids); - -//----------------------------------------------------------------------------- -// wxFileData -//----------------------------------------------------------------------------- - -wxFileData::wxFileData( const wxString &filePath, const wxString &fileName, fileType type, int image_id ) -{ - Init(); - m_fileName = fileName; - m_filePath = filePath; - m_type = type; - m_image = image_id; - - ReadData(); -} - -void wxFileData::Init() -{ - m_size = 0; - m_type = wxFileData::is_file; - m_image = wxFileIconsTable::file; -} - -void wxFileData::Copy( const wxFileData& fileData ) -{ - m_fileName = fileData.GetFileName(); - m_filePath = fileData.GetFilePath(); - m_size = fileData.GetSize(); - m_dateTime = fileData.GetDateTime(); - m_permissions = fileData.GetPermissions(); - m_type = fileData.GetType(); - m_image = fileData.GetImageId(); -} - -void wxFileData::ReadData() -{ - if (IsDrive()) - { - m_size = 0; - return; - } - -#if defined(__DOS__) || (defined(__WINDOWS__) && !defined(__WXWINCE__)) || defined(__OS2__) - // c:\.. is a drive don't stat it - if ((m_fileName == wxT("..")) && (m_filePath.length() <= 5)) - { - m_type = is_drive; - m_size = 0; - return; - } -#endif // __DOS__ || __WINDOWS__ - -#ifdef __WXWINCE__ - - // WinCE - - DWORD fileAttribs = GetFileAttributes(m_filePath.fn_str()); - m_type |= (fileAttribs & FILE_ATTRIBUTE_DIRECTORY) != 0 ? is_dir : 0; - - wxString p, f, ext; - wxSplitPath(m_filePath, & p, & f, & ext); - if (wxStricmp(ext, wxT("exe")) == 0) - m_type |= is_exe; - - // Find out size - m_size = 0; - HANDLE fileHandle = CreateFile(m_filePath.fn_str(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (fileHandle != INVALID_HANDLE_VALUE) - { - m_size = GetFileSize(fileHandle, 0); - CloseHandle(fileHandle); - } - - m_dateTime = wxFileModificationTime(m_filePath); - -#else - - // OTHER PLATFORMS - - wxStructStat buff; - -#if defined(__UNIX__) && (!defined( __OS2__ ) && !defined(__VMS)) - lstat( m_filePath.fn_str(), &buff ); - m_type |= S_ISLNK( buff.st_mode ) != 0 ? is_link : 0; -#else // no lstat() - // only translate to file charset if we don't go by our - // wxStat implementation -#ifndef wxNEED_WX_UNISTD_H - wxStat( m_filePath.fn_str() , &buff ); -#else - wxStat( m_filePath, &buff ); -#endif -#endif - - m_type |= (buff.st_mode & S_IFDIR) != 0 ? is_dir : 0; - m_type |= (buff.st_mode & wxS_IXUSR) != 0 ? is_exe : 0; - - m_size = buff.st_size; - - m_dateTime = buff.st_mtime; -#endif - // __WXWINCE__ - -#if defined(__UNIX__) - m_permissions.Printf(_T("%c%c%c%c%c%c%c%c%c"), - buff.st_mode & wxS_IRUSR ? _T('r') : _T('-'), - buff.st_mode & wxS_IWUSR ? _T('w') : _T('-'), - buff.st_mode & wxS_IXUSR ? _T('x') : _T('-'), - buff.st_mode & wxS_IRGRP ? _T('r') : _T('-'), - buff.st_mode & wxS_IWGRP ? _T('w') : _T('-'), - buff.st_mode & wxS_IXGRP ? _T('x') : _T('-'), - buff.st_mode & wxS_IROTH ? _T('r') : _T('-'), - buff.st_mode & wxS_IWOTH ? _T('w') : _T('-'), - buff.st_mode & wxS_IXOTH ? _T('x') : _T('-')); -#elif defined(__WIN32__) - DWORD attribs = ::GetFileAttributes(m_filePath.c_str()); - if (attribs != (DWORD)-1) - { - m_permissions.Printf(_T("%c%c%c%c"), - attribs & FILE_ATTRIBUTE_ARCHIVE ? _T('A') : _T(' '), - attribs & FILE_ATTRIBUTE_READONLY ? _T('R') : _T(' '), - attribs & FILE_ATTRIBUTE_HIDDEN ? _T('H') : _T(' '), - attribs & FILE_ATTRIBUTE_SYSTEM ? _T('S') : _T(' ')); - } -#endif - - // try to get a better icon - if (m_image == wxFileIconsTable::file) - { - if (m_fileName.Find(wxT('.'), true) != wxNOT_FOUND) - { - m_image = wxTheFileIconsTable->GetIconID( m_fileName.AfterLast(wxT('.'))); - } else if (IsExe()) - { - m_image = wxFileIconsTable::executable; - } - } -} - -wxString wxFileData::GetFileType() const -{ - if (IsDir()) - return _(""); - else if (IsLink()) - return _(""); - else if (IsDrive()) - return _(""); - else if (m_fileName.Find(wxT('.'), true) != wxNOT_FOUND) - return m_fileName.AfterLast(wxT('.')); - - return wxEmptyString; -} - -wxString wxFileData::GetModificationTime() const -{ - // want time as 01:02 so they line up nicely, no %r in WIN32 - return m_dateTime.FormatDate() + wxT(" ") + m_dateTime.Format(wxT("%I:%M:%S %p")); -} - -wxString wxFileData::GetHint() const -{ - wxString s = m_filePath; - s += wxT(" "); - - if (IsDir()) - s += _(""); - else if (IsLink()) - s += _(""); - else if (IsDrive()) - s += _(""); - else // plain file - s += wxString::Format(_("%ld bytes"), - wxLongLong(m_size).ToString().c_str()); - - s += wxT(' '); - - if ( !IsDrive() ) - { - s << GetModificationTime() - << wxT(" ") - << m_permissions; - } - - return s; -} - -wxString wxFileData::GetEntry( fileListFieldType num ) const -{ - wxString s; - switch ( num ) - { - case FileList_Name: - s = m_fileName; - break; - - case FileList_Size: - if (!IsDir() && !IsLink() && !IsDrive()) - s = wxLongLong(m_size).ToString(); - break; - - case FileList_Type: - s = GetFileType(); - break; - - case FileList_Time: - if (!IsDrive()) - s = GetModificationTime(); - break; - -#if defined(__UNIX__) || defined(__WIN32__) - case FileList_Perm: - s = m_permissions; - break; -#endif // defined(__UNIX__) || defined(__WIN32__) - - default: - wxFAIL_MSG( _T("unexpected field in wxFileData::GetEntry()") ); - } - - return s; -} - -void wxFileData::SetNewName( const wxString &filePath, const wxString &fileName ) -{ - m_fileName = fileName; - m_filePath = filePath; -} - -void wxFileData::MakeItem( wxListItem &item ) -{ - item.m_text = m_fileName; - item.ClearAttributes(); - if (IsExe()) - item.SetTextColour(*wxRED); - if (IsDir()) - item.SetTextColour(*wxBLUE); - - item.m_image = m_image; - - if (IsLink()) - { - wxColour dg = wxTheColourDatabase->Find( _T("MEDIUM GREY") ); - if ( dg.Ok() ) - item.SetTextColour(dg); - } - item.m_data = wxPtrToUInt(this); -} - -//----------------------------------------------------------------------------- -// wxFileCtrl -//----------------------------------------------------------------------------- - -static bool ignoreChanges = false; - -IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl,wxListCtrl) - -BEGIN_EVENT_TABLE(wxFileCtrl,wxListCtrl) - EVT_LIST_DELETE_ITEM(wxID_ANY, wxFileCtrl::OnListDeleteItem) - EVT_LIST_DELETE_ALL_ITEMS(wxID_ANY, wxFileCtrl::OnListDeleteAllItems) - EVT_LIST_END_LABEL_EDIT(wxID_ANY, wxFileCtrl::OnListEndLabelEdit) - EVT_LIST_COL_CLICK(wxID_ANY, wxFileCtrl::OnListColClick) -END_EVENT_TABLE() - - -wxFileCtrl::wxFileCtrl() -{ - m_showHidden = false; - m_sort_foward = 1; - m_sort_field = wxFileData::FileList_Name; -} - -wxFileCtrl::wxFileCtrl(wxWindow *win, - wxWindowID id, - const wxString& wild, - bool showHidden, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator &validator, - const wxString &name) - : wxListCtrl(win, id, pos, size, style, validator, name), - m_wild(wild) -{ - wxImageList *imageList = wxTheFileIconsTable->GetSmallImageList(); - - SetImageList( imageList, wxIMAGE_LIST_SMALL ); - - m_showHidden = showHidden; - - m_sort_foward = 1; - m_sort_field = wxFileData::FileList_Name; - - m_dirName = wxT("*"); - - if (style & wxLC_REPORT) - ChangeToReportMode(); -} - -void wxFileCtrl::ChangeToListMode() -{ - ClearAll(); - SetSingleStyle( wxLC_LIST ); - UpdateFiles(); -} - -void wxFileCtrl::ChangeToReportMode() -{ - ClearAll(); - SetSingleStyle( wxLC_REPORT ); - - // do this since WIN32 does mm/dd/yy UNIX does mm/dd/yyyy - // don't hardcode since mm/dd is dd/mm elsewhere - int w, h; - wxDateTime dt(22, wxDateTime::Dec, 2002, 22, 22, 22); - wxString txt = dt.FormatDate() + wxT("22") + dt.Format(wxT("%I:%M:%S %p")); - GetTextExtent(txt, &w, &h); - - InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT, w ); - InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT, w/2 ); - InsertColumn( 2, _("Type"), wxLIST_FORMAT_LEFT, w/2 ); - InsertColumn( 3, _("Modified"), wxLIST_FORMAT_LEFT, w ); -#if defined(__UNIX__) - GetTextExtent(wxT("Permissions 2"), &w, &h); - InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT, w ); -#elif defined(__WIN32__) - GetTextExtent(wxT("Attributes 2"), &w, &h); - InsertColumn( 4, _("Attributes"), wxLIST_FORMAT_LEFT, w ); -#endif - - UpdateFiles(); -} - -void wxFileCtrl::ChangeToSmallIconMode() -{ - ClearAll(); - SetSingleStyle( wxLC_SMALL_ICON ); - UpdateFiles(); -} - -void wxFileCtrl::ShowHidden( bool show ) -{ - m_showHidden = show; - UpdateFiles(); -} - -long wxFileCtrl::Add( wxFileData *fd, wxListItem &item ) -{ - long ret = -1; - item.m_mask = wxLIST_MASK_TEXT + wxLIST_MASK_DATA + wxLIST_MASK_IMAGE; - fd->MakeItem( item ); - long my_style = GetWindowStyleFlag(); - if (my_style & wxLC_REPORT) - { - ret = InsertItem( item ); - for (int i = 1; i < wxFileData::FileList_Max; i++) - SetItem( item.m_itemId, i, fd->GetEntry((wxFileData::fileListFieldType)i) ); - } - else if ((my_style & wxLC_LIST) || (my_style & wxLC_SMALL_ICON)) - { - ret = InsertItem( item ); - } - return ret; -} - -void wxFileCtrl::UpdateItem(const wxListItem &item) -{ - wxFileData *fd = (wxFileData*)GetItemData(item); - wxCHECK_RET(fd, wxT("invalid filedata")); - - fd->ReadData(); - - SetItemText(item, fd->GetFileName()); - SetItemImage(item, fd->GetImageId()); - - if (GetWindowStyleFlag() & wxLC_REPORT) - { - for (int i = 1; i < wxFileData::FileList_Max; i++) - SetItem( item.m_itemId, i, fd->GetEntry((wxFileData::fileListFieldType)i) ); - } -} - -void wxFileCtrl::UpdateFiles() -{ - // don't do anything before ShowModal() call which sets m_dirName - if ( m_dirName == wxT("*") ) - return; - - wxBusyCursor bcur; // this may take a while... - - DeleteAllItems(); - - wxListItem item; - item.m_itemId = 0; - item.m_col = 0; - -#if (defined(__WINDOWS__) || defined(__DOS__) || defined(__WXMAC__) || defined(__OS2__)) && !defined(__WXWINCE__) - if ( IsTopMostDir(m_dirName) ) - { - wxArrayString names, paths; - wxArrayInt icons; - size_t n, count = wxGetAvailableDrives(paths, names, icons); - - for (n=0; nGetFilePath() ) ); - new_name += wxFILE_SEP_PATH; - new_name += event.GetLabel(); - - wxLogNull log; - - if (wxFileExists(new_name)) - { - wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR ); - dialog.ShowModal(); - event.Veto(); - } - - if (wxRenameFile(fd->GetFilePath(),new_name)) - { - fd->SetNewName( new_name, event.GetLabel() ); - - ignoreChanges = true; - SetItemState( event.GetItem(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); - ignoreChanges = false; - - UpdateItem( event.GetItem() ); - EnsureVisible( event.GetItem() ); - } - else - { - wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR ); - dialog.ShowModal(); - event.Veto(); - } -} - -void wxFileCtrl::OnListColClick( wxListEvent &event ) -{ - int col = event.GetColumn(); - - switch (col) - { - case wxFileData::FileList_Name : - case wxFileData::FileList_Size : - case wxFileData::FileList_Type : - case wxFileData::FileList_Time : break; - default : return; - } - - if ((wxFileData::fileListFieldType)col == m_sort_field) - m_sort_foward = !m_sort_foward; - else - m_sort_field = (wxFileData::fileListFieldType)col; - - SortItems(m_sort_field, m_sort_foward); -} - -void wxFileCtrl::SortItems(wxFileData::fileListFieldType field, bool forward) -{ - m_sort_field = field; - m_sort_foward = forward; - const long sort_dir = forward ? 1 : -1; - - switch (m_sort_field) - { - case wxFileData::FileList_Size : - wxListCtrl::SortItems(wxFileDataSizeCompare, sort_dir); - break; - - case wxFileData::FileList_Type : - wxListCtrl::SortItems(wxFileDataTypeCompare, sort_dir); - break; - - case wxFileData::FileList_Time : - wxListCtrl::SortItems(wxFileDataTimeCompare, sort_dir); - break; - - case wxFileData::FileList_Name : - default : - wxListCtrl::SortItems(wxFileDataNameCompare, sort_dir); - break; - } -} - -wxFileCtrl::~wxFileCtrl() -{ - // Normally the data are freed via an EVT_LIST_DELETE_ALL_ITEMS event and - // wxFileCtrl::OnListDeleteAllItems. But if the event is generated after - // the destruction of the wxFileCtrl we need to free any data here: - FreeAllItemsData(); -} - //----------------------------------------------------------------------------- // wxGenericFileDialog //----------------------------------------------------------------------------- #define ID_LIST_MODE (wxID_FILEDLGG ) #define ID_REPORT_MODE (wxID_FILEDLGG + 1) -#define ID_UP_DIR (wxID_FILEDLGG + 5) -#define ID_PARENT_DIR (wxID_FILEDLGG + 6) -#define ID_NEW_DIR (wxID_FILEDLGG + 7) -#define ID_CHOICE (wxID_FILEDLGG + 8) -#define ID_TEXT (wxID_FILEDLGG + 9) -#define ID_LIST_CTRL (wxID_FILEDLGG + 10) -#define ID_CHECK (wxID_FILEDLGG + 12) +#define ID_UP_DIR (wxID_FILEDLGG + 2) +#define ID_HOME_DIR (wxID_FILEDLGG + 3) +#define ID_NEW_DIR (wxID_FILEDLGG + 4) +#define ID_FILE_CTRL (wxID_FILEDLGG + 5) IMPLEMENT_DYNAMIC_CLASS(wxGenericFileDialog, wxFileDialogBase) BEGIN_EVENT_TABLE(wxGenericFileDialog,wxDialog) - EVT_BUTTON(ID_LIST_MODE, wxGenericFileDialog::OnList) - EVT_BUTTON(ID_REPORT_MODE, wxGenericFileDialog::OnReport) - EVT_BUTTON(ID_UP_DIR, wxGenericFileDialog::OnUp) - EVT_BUTTON(ID_PARENT_DIR, wxGenericFileDialog::OnHome) - EVT_BUTTON(ID_NEW_DIR, wxGenericFileDialog::OnNew) - EVT_BUTTON(wxID_OK, wxGenericFileDialog::OnListOk) - EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL, wxGenericFileDialog::OnSelected) - EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL, wxGenericFileDialog::OnActivated) - EVT_CHOICE(ID_CHOICE,wxGenericFileDialog::OnChoiceFilter) - EVT_TEXT_ENTER(ID_TEXT,wxGenericFileDialog::OnTextEnter) - EVT_TEXT(ID_TEXT,wxGenericFileDialog::OnTextChange) - EVT_CHECKBOX(ID_CHECK,wxGenericFileDialog::OnCheck) + EVT_BUTTON(ID_LIST_MODE, wxGenericFileDialog::OnList) + EVT_BUTTON(ID_REPORT_MODE, wxGenericFileDialog::OnReport) + EVT_BUTTON(ID_UP_DIR, wxGenericFileDialog::OnUp) + EVT_BUTTON(ID_HOME_DIR, wxGenericFileDialog::OnHome) + EVT_BUTTON(ID_NEW_DIR, wxGenericFileDialog::OnNew) + EVT_BUTTON(wxID_OK, wxGenericFileDialog::OnOk) + EVT_FILECTRL_FILEACTIVATED(ID_FILE_CTRL, wxGenericFileDialog::OnFileActivated) + + EVT_UPDATE_UI(ID_UP_DIR, wxGenericFileDialog::OnUpdateButtonsUI) +#if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) + EVT_UPDATE_UI(ID_NEW_DIR, wxGenericFileDialog::OnUpdateButtonsUI) +#endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) END_EVENT_TABLE() long wxGenericFileDialog::ms_lastViewStyle = wxLC_LIST; @@ -957,11 +131,7 @@ void wxGenericFileDialog::Init() { m_bypassGenericImpl = false; - m_choice = NULL; - m_text = NULL; - m_list = NULL; - m_check = NULL; - m_static = NULL; + m_filectrl = NULL; m_upDirButton = NULL; m_newDirButton = NULL; } @@ -994,6 +164,8 @@ bool wxGenericFileDialog::Create( wxWindow *parent, { m_bypassGenericImpl = bypassGenericImpl; + parent = GetParentForModalDialog(parent, style); + if (!wxFileDialogBase::Create(parent, message, defaultDir, defaultFile, wildCard, style, pos, sz, name)) { @@ -1004,14 +176,13 @@ bool wxGenericFileDialog::Create( wxWindow *parent, return true; if (!wxDialog::Create( parent, wxID_ANY, message, pos, sz, - wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER, name + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | style, name )) { return false; } - ignoreChanges = true; - +#if wxUSE_CONFIG if (wxConfig::Get(false)) { wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"), @@ -1019,6 +190,7 @@ bool wxGenericFileDialog::Create( wxWindow *parent, wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"), &ms_lastShowHidden); } +#endif if ((m_dir.empty()) || (m_dir == wxT("."))) { @@ -1027,163 +199,92 @@ bool wxGenericFileDialog::Create( wxWindow *parent, m_dir = wxFILE_SEP_PATH; } - size_t len = m_dir.Len(); + const size_t len = m_dir.length(); if ((len > 1) && (wxEndsWithPathSeparator(m_dir))) m_dir.Remove( len-1, 1 ); - m_path = m_dir; - m_path += wxFILE_SEP_PATH; - m_path += defaultFile; m_filterExtension = wxEmptyString; // layout - bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA); + const bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA); wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL ); wxBoxSizer *buttonsizer = new wxBoxSizer( wxHORIZONTAL ); - - wxBitmapButton *but; - - but = new wxBitmapButton(this, ID_LIST_MODE, - wxArtProvider::GetBitmap(wxART_LIST_VIEW, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - but->SetToolTip( _("View files as a list view") ); -#endif - buttonsizer->Add( but, 0, wxALL, 5 ); - - but = new wxBitmapButton(this, ID_REPORT_MODE, - wxArtProvider::GetBitmap(wxART_REPORT_VIEW, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - but->SetToolTip( _("View files as a detailed view") ); -#endif - buttonsizer->Add( but, 0, wxALL, 5 ); - + AddBitmapButton( ID_LIST_MODE, wxART_LIST_VIEW, + _("View files as a list view"), buttonsizer ); + AddBitmapButton( ID_REPORT_MODE, wxART_REPORT_VIEW, + _("View files as a detailed view"), buttonsizer ); buttonsizer->Add( 30, 5, 1 ); - - m_upDirButton = new wxBitmapButton(this, ID_UP_DIR, - wxArtProvider::GetBitmap(wxART_GO_DIR_UP, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - m_upDirButton->SetToolTip( _("Go to parent directory") ); -#endif - buttonsizer->Add( m_upDirButton, 0, wxALL, 5 ); + m_upDirButton = AddBitmapButton( ID_UP_DIR, wxART_GO_DIR_UP, + _("Go to parent directory"), buttonsizer ); #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS... - but = new wxBitmapButton(this, ID_PARENT_DIR, - wxArtProvider::GetBitmap(wxART_GO_HOME, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - but->SetToolTip( _("Go to home directory") ); -#endif - buttonsizer->Add( but, 0, wxALL, 5); - + AddBitmapButton( ID_HOME_DIR, wxART_GO_HOME, + _("Go to home directory"), buttonsizer ); buttonsizer->Add( 20, 20 ); #endif //!__DOS__ - m_newDirButton = new wxBitmapButton(this, ID_NEW_DIR, - wxArtProvider::GetBitmap(wxART_NEW_DIR, wxART_BUTTON)); -#if wxUSE_TOOLTIPS - m_newDirButton->SetToolTip( _("Create new directory") ); -#endif - buttonsizer->Add( m_newDirButton, 0, wxALL, 5 ); + m_newDirButton = AddBitmapButton( ID_NEW_DIR, wxART_NEW_DIR, + _("Create new directory"), buttonsizer ); if (is_pda) - mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 0 ); + mainsizer->Add( buttonsizer, wxSizerFlags().Expand() ); else - mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 5 ); + mainsizer->Add( buttonsizer, wxSizerFlags().Expand() + .Border( wxLEFT | wxRIGHT | wxTOP ) ); - wxBoxSizer *staticsizer = new wxBoxSizer( wxHORIZONTAL ); - if (is_pda) - staticsizer->Add( new wxStaticText( this, wxID_ANY, _("Current directory:") ), 0, wxRIGHT, 10 ); - m_static = new wxStaticText( this, wxID_ANY, m_dir ); - staticsizer->Add( m_static, 1 ); - mainsizer->Add( staticsizer, 0, wxEXPAND | wxLEFT|wxRIGHT|wxBOTTOM, 10 ); + long style2 = 0; + if ( HasFdFlag(wxFD_MULTIPLE) ) + style2 |= wxFC_MULTIPLE; - long style2 = ms_lastViewStyle; - if ( !HasFlag(wxFD_MULTIPLE) ) - style2 |= wxLC_SINGLE_SEL; - -#ifdef __WXWINCE__ - style2 |= wxSIMPLE_BORDER; -#else - style2 |= wxSUNKEN_BORDER; -#endif + m_filectrl = new wxGenericFileCtrl( this, ID_FILE_CTRL, + m_dir, defaultFile, + wildCard, + style2, + wxDefaultPosition, wxSize(540,200) + ); - m_list = new wxFileCtrl( this, ID_LIST_CTRL, - wxEmptyString, ms_lastShowHidden, - wxDefaultPosition, wxSize(540,200), - style2); + m_filectrl->ShowHidden( ms_lastShowHidden ); - if (is_pda) + if (ms_lastViewStyle == wxLC_LIST) { - // PDAs have a different screen layout - mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 5 ); - - wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL ); - m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - textsizer->Add( m_text, 1, wxCENTER | wxALL, 5 ); - mainsizer->Add( textsizer, 0, wxEXPAND ); - - m_check = NULL; - m_choice = new wxChoice( this, ID_CHOICE ); - textsizer->Add( m_choice, 1, wxCENTER|wxALL, 5 ); - - wxSizer *bsizer = CreateButtonSizer( wxOK|wxCANCEL , false, 5 ); - if(bsizer->GetChildren().GetCount() > 0 ) - { - mainsizer->Add( bsizer, 0, wxEXPAND | wxALL, 5 ); - } - else - { - delete bsizer; - } + m_filectrl->ChangeToListMode(); } - else + else if (ms_lastViewStyle == wxLC_REPORT) { - mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 10 ); - - wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL ); - m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - textsizer->Add( m_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 ); - textsizer->Add( new wxButton( this, wxID_OK ), 0, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 ); - mainsizer->Add( textsizer, 0, wxEXPAND ); - - wxBoxSizer *choicesizer = new wxBoxSizer( wxHORIZONTAL ); - m_choice = new wxChoice( this, ID_CHOICE ); - choicesizer->Add( m_choice, 1, wxCENTER|wxALL, 10 ); - m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden files") ); - m_check->SetValue( ms_lastShowHidden ); - choicesizer->Add( m_check, 0, wxCENTER|wxALL, 10 ); - choicesizer->Add( new wxButton( this, wxID_CANCEL ), 0, wxCENTER | wxALL, 10 ); - mainsizer->Add( choicesizer, 0, wxEXPAND ); + m_filectrl->ChangeToReportMode(); } - SetWildcard(wildCard); + mainsizer->Add(m_filectrl, wxSizerFlags(1).Expand().HorzBorder()); + + wxSizer *bsizer = CreateButtonSizer(wxOK | wxCANCEL); + if ( bsizer ) + { + if (is_pda) + mainsizer->Add(bsizer, wxSizerFlags().Expand().Border()); + else + mainsizer->Add(bsizer, wxSizerFlags().Expand().DoubleBorder()); + } - SetAutoLayout( true ); SetSizer( mainsizer ); if (!is_pda) { - mainsizer->Fit( this ); mainsizer->SetSizeHints( this ); Centre( wxBOTH ); } - m_text->SetFocus(); - - ignoreChanges = false; - return true; } wxGenericFileDialog::~wxGenericFileDialog() { - ignoreChanges = true; - if (!m_bypassGenericImpl) { +#if wxUSE_CONFIG if (wxConfig::Get(false)) { wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"), @@ -1191,24 +292,33 @@ wxGenericFileDialog::~wxGenericFileDialog() wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"), ms_lastShowHidden); } - - const int count = m_choice->GetCount(); - for ( int i = 0; i < count; i++ ) - { - delete (wxString *)m_choice->GetClientData(i); - } +#endif } } -int wxGenericFileDialog::ShowModal() +wxBitmapButton* wxGenericFileDialog::AddBitmapButton( wxWindowID winId, + const wxArtID& artId, + const wxString& tip, + wxSizer *sizer) { - ignoreChanges = true; + wxBitmapButton *but = new wxBitmapButton(this, winId, + wxArtProvider::GetBitmap(artId, wxART_BUTTON)); + but->SetToolTip(tip); + sizer->Add(but, wxSizerFlags().Border()); + return but; +} - m_list->GoToDir(m_dir); - UpdateControls(); - m_text->SetValue(m_fileName); +int wxGenericFileDialog::ShowModal() +{ + if (CreateExtraControl()) + { + wxSizer *sizer = GetSizer(); + sizer->Insert(2 /* after m_filectrl */, m_extraControl, + wxSizerFlags().Expand().HorzBorder()); + sizer->Fit(this); + } - ignoreChanges = false; + m_filectrl->SetDirectory(m_dir); return wxDialog::ShowModal(); } @@ -1219,418 +329,78 @@ bool wxGenericFileDialog::Show( bool show ) #ifndef __WIN32__ if (show) { - m_list->GoToDir(m_dir); - UpdateControls(); - m_text->SetValue(m_fileName); + m_filectrl->SetDirectory(m_dir); } #endif return wxDialog::Show( show ); } -void wxGenericFileDialog::DoSetFilterIndex(int filterindex) -{ - wxString *str = (wxString*) m_choice->GetClientData( filterindex ); - m_list->SetWild( *str ); - m_filterIndex = filterindex; - if ( str->Left(2) == wxT("*.") ) - { - m_filterExtension = str->Mid(1); - if (m_filterExtension == _T(".*")) - m_filterExtension.clear(); - } - else - { - m_filterExtension.clear(); - } -} - -void wxGenericFileDialog::SetWildcard(const wxString& wildCard) +void wxGenericFileDialog::OnOk( wxCommandEvent &WXUNUSED(event) ) { - wxFileDialogBase::SetWildcard(wildCard); - - wxArrayString wildDescriptions, wildFilters; - const size_t count = wxParseCommonDialogsFilter(m_wildCard, - wildDescriptions, - wildFilters); - wxCHECK_RET( count, wxT("wxFileDialog: bad wildcard string") ); - - const size_t countOld = m_choice->GetCount(); - size_t n; - for ( n = 0; n < countOld; n++ ) - { - delete (wxString *)m_choice->GetClientData(n); - } - - for ( n = 0; n < count; n++ ) - { - m_choice->Append( wildDescriptions[n], new wxString( wildFilters[n] ) ); - } - - SetFilterIndex( 0 ); -} + wxArrayString selectedFiles; + m_filectrl->GetFilenames(selectedFiles); -void wxGenericFileDialog::SetFilterIndex( int filterindex ) -{ - m_choice->SetSelection( filterindex ); - - DoSetFilterIndex(filterindex); -} - -void wxGenericFileDialog::OnChoiceFilter( wxCommandEvent &event ) -{ - DoSetFilterIndex((int)event.GetInt()); -} - -void wxGenericFileDialog::OnCheck( wxCommandEvent &event ) -{ - m_list->ShowHidden( (ms_lastShowHidden = event.GetInt() != 0) ); -} - -void wxGenericFileDialog::OnActivated( wxListEvent &event ) -{ - HandleAction( event.m_item.m_text ); -} - -void wxGenericFileDialog::OnTextEnter( wxCommandEvent &WXUNUSED(event) ) -{ - HandleAction( m_text->GetValue() ); -} - -void wxGenericFileDialog::OnTextChange( wxCommandEvent &WXUNUSED(event) ) -{ - if (!ignoreChanges) - { - // Clear selections. Otherwise when the user types in a value they may - // not get the file whose name they typed. - if (m_list->GetSelectedItemCount() > 0) - { - long item = m_list->GetNextItem(-1, wxLIST_NEXT_ALL, - wxLIST_STATE_SELECTED); - while ( item != -1 ) - { - m_list->SetItemState(item,0, wxLIST_STATE_SELECTED); - item = m_list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - } - } - } -} - -void wxGenericFileDialog::OnSelected( wxListEvent &event ) -{ - static bool inSelected = false; - - if (inSelected) - return; - - inSelected = true; - wxString filename( event.m_item.m_text ); - -#ifdef __WXWINCE__ - // No double-click on most WinCE devices, so do action immediately. - HandleAction( filename ); -#else - if (filename == wxT("..")) - { - inSelected = false; - return; - } - - wxString dir = m_list->GetDir(); - if (!IsTopMostDir(dir)) - dir += wxFILE_SEP_PATH; - dir += filename; - if (wxDirExists(dir)) - { - inSelected = false; - return; - } - - ignoreChanges = true; - m_text->SetValue( filename ); - ignoreChanges = false; -#endif - inSelected = false; -} - -void wxGenericFileDialog::HandleAction( const wxString &fn ) -{ - if (ignoreChanges) - return; - - wxString filename( fn ); - if (filename.empty()) - { -#ifdef __WXWINCE__ - EndModal(wxID_CANCEL); -#endif - return; - } - if (filename == wxT(".")) return; - - wxString dir = m_list->GetDir(); - - // "some/place/" means they want to chdir not try to load "place" - bool want_dir = filename.Last() == wxFILE_SEP_PATH; - if (want_dir) - filename = filename.RemoveLast(); - - if (filename == wxT("..")) - { - ignoreChanges = true; - m_list->GoToParentDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; - return; - } - -#ifdef __UNIX__ - if (filename == wxT("~")) - { - ignoreChanges = true; - m_list->GoToHomeDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; - return; - } - - if (filename.BeforeFirst(wxT('/')) == wxT("~")) - { - filename = wxString(wxGetUserHome()) + filename.Remove(0, 1); - } -#endif // __UNIX__ - - if (!HasFlag(wxFD_SAVE)) - { - if ((filename.Find(wxT('*')) != wxNOT_FOUND) || - (filename.Find(wxT('?')) != wxNOT_FOUND)) - { - if (filename.Find(wxFILE_SEP_PATH) != wxNOT_FOUND) - { - wxMessageBox(_("Illegal file specification."), _("Error"), wxOK | wxICON_ERROR ); - return; - } - m_list->SetWild( filename ); - return; - } - } - - if (!IsTopMostDir(dir)) - dir += wxFILE_SEP_PATH; - if (!wxIsAbsolutePath(filename)) - { - dir += filename; - filename = dir; - } - - if (wxDirExists(filename)) - { - ignoreChanges = true; - m_list->GoToDir( filename ); - UpdateControls(); - ignoreChanges = false; - return; - } - - // they really wanted a dir, but it doesn't exist - if (want_dir) - { - wxMessageBox(_("Directory doesn't exist."), _("Error"), - wxOK | wxICON_ERROR ); + if (selectedFiles.Count() == 0) return; - } - // append the default extension to the filename if it doesn't have any - // - // VZ: the logic of testing for !wxFileExists() only for the open file - // dialog is not entirely clear to me, why don't we allow saving to a - // file without extension as well? - if ( !HasFlag(wxFD_OPEN) || !wxFileExists(filename) ) + if (selectedFiles.Count() == 1) { - filename = AppendExtension(filename, m_filterExtension); - } - - // check that the file [doesn't] exist if necessary - if ( HasFlag(wxFD_SAVE) && HasFlag(wxFD_OVERWRITE_PROMPT) && - wxFileExists( filename ) ) - { - wxString msg; - msg.Printf( _("File '%s' already exists, do you really want to overwrite it?"), filename.c_str() ); - - if (wxMessageBox(msg, _("Confirm"), wxYES_NO) != wxYES) - return; - } - else if ( HasFlag(wxFD_OPEN) && HasFlag(wxFD_FILE_MUST_EXIST) && - !wxFileExists(filename) ) - { - wxMessageBox(_("Please choose an existing file."), _("Error"), - wxOK | wxICON_ERROR ); - } - - SetPath( filename ); - - // change to the directory where the user went if asked - if ( HasFlag(wxFD_CHANGE_DIR) ) - { - wxString cwd; - wxSplitPath(filename, &cwd, NULL, NULL); - - if ( cwd != wxGetCwd() ) - { - wxSetWorkingDirectory(cwd); - } + SetPath( selectedFiles[0] ); } EndModal(wxID_OK); } -void wxGenericFileDialog::OnListOk( wxCommandEvent &WXUNUSED(event) ) -{ - HandleAction( m_text->GetValue() ); -} - void wxGenericFileDialog::OnList( wxCommandEvent &WXUNUSED(event) ) { - ignoreChanges = true; - m_list->ChangeToListMode(); + m_filectrl->ChangeToListMode(); ms_lastViewStyle = wxLC_LIST; - m_list->SetFocus(); - ignoreChanges = false; + m_filectrl->GetFileList()->SetFocus(); } void wxGenericFileDialog::OnReport( wxCommandEvent &WXUNUSED(event) ) { - ignoreChanges = true; - m_list->ChangeToReportMode(); + m_filectrl->ChangeToReportMode(); ms_lastViewStyle = wxLC_REPORT; - m_list->SetFocus(); - ignoreChanges = false; + m_filectrl->GetFileList()->SetFocus(); } void wxGenericFileDialog::OnUp( wxCommandEvent &WXUNUSED(event) ) { - ignoreChanges = true; - m_list->GoToParentDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; + m_filectrl->GoToParentDir(); + m_filectrl->GetFileList()->SetFocus(); } void wxGenericFileDialog::OnHome( wxCommandEvent &WXUNUSED(event) ) { - ignoreChanges = true; - m_list->GoToHomeDir(); - m_list->SetFocus(); - UpdateControls(); - ignoreChanges = false; + m_filectrl->GoToHomeDir(); + m_filectrl->SetFocus(); } void wxGenericFileDialog::OnNew( wxCommandEvent &WXUNUSED(event) ) { - ignoreChanges = true; - - m_list->MakeDir(); - - ignoreChanges = false; -} - -void wxGenericFileDialog::SetPath( const wxString& path ) -{ - // not only set the full path but also update filename and dir - m_path = path; - -#ifdef __WXWINCE__ - if (m_path.empty()) - m_path = wxFILE_SEP_PATH; -#endif - - if ( !path.empty() ) - { - wxString ext; - wxSplitPath(path, &m_dir, &m_fileName, &ext); - if (!ext.empty()) - { - m_fileName += wxT("."); - m_fileName += ext; - } - } -} - -void wxGenericFileDialog::GetPaths( wxArrayString& paths ) const -{ - paths.Empty(); - if (m_list->GetSelectedItemCount() == 0) - { - paths.Add( GetPath() ); - return; - } - - paths.Alloc( m_list->GetSelectedItemCount() ); - - wxString dir = m_list->GetDir(); -#ifdef __UNIX__ - if (dir != wxT("/")) -#endif -#ifdef __WXWINCE__ - if (dir != wxT("/") && dir != wxT("\\")) -#endif - dir += wxFILE_SEP_PATH; - - wxListItem item; - item.m_mask = wxLIST_MASK_TEXT; - - item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - while ( item.m_itemId != -1 ) - { - m_list->GetItem( item ); - paths.Add( dir + item.m_text ); - item.m_itemId = m_list->GetNextItem( item.m_itemId, - wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - } + m_filectrl->GetFileList()->MakeDir(); } -void wxGenericFileDialog::GetFilenames(wxArrayString& files) const +void wxGenericFileDialog::OnFileActivated( wxFileCtrlEvent &WXUNUSED(event) ) { - files.Empty(); - if (m_list->GetSelectedItemCount() == 0) - { - files.Add( GetFilename() ); - return; - } - files.Alloc( m_list->GetSelectedItemCount() ); - - wxListItem item; - item.m_mask = wxLIST_MASK_TEXT; - - item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - while ( item.m_itemId != -1 ) - { - m_list->GetItem( item ); - files.Add( item.m_text ); - item.m_itemId = m_list->GetNextItem( item.m_itemId, - wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); - } + wxCommandEvent dummy; + OnOk( dummy ); } -void wxGenericFileDialog::UpdateControls() +void wxGenericFileDialog::OnUpdateButtonsUI(wxUpdateUIEvent& event) { - wxString dir = m_list->GetDir(); - m_static->SetLabel(dir); - - bool enable = !IsTopMostDir(dir); - m_upDirButton->Enable(enable); - -#if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) - m_newDirButton->Enable(enable); -#endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) + // surprisingly, we can be called before m_filectrl is set in Create() as + // wxFileCtrl ctor itself can generate idle events, so we need this test + if ( m_filectrl ) + event.Enable( !IsTopMostDir(m_filectrl->GetShownDirectory()) ); } -#ifdef USE_GENERIC_FILEDIALOG +#ifdef wxHAS_GENERIC_FILEDIALOG IMPLEMENT_DYNAMIC_CLASS(wxFileDialog, wxGenericFileDialog) -#endif // USE_GENERIC_FILEDIALOG +#endif // wxHAS_GENERIC_FILEDIALOG #endif // wxUSE_FILEDLG