1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/filectrlg.cpp 
   3 // Purpose:     wxGenericFileCtrl Implementation 
   4 // Author:      Diaa M. Sami 
   7 // Copyright:   (c) Diaa M. Sami 
   8 // Licence:     wxWindows licence 
   9 /////////////////////////////////////////////////////////////////////////////// 
  11 #include "wx/wxprec.h" 
  19 #include "wx/generic/filectrlg.h" 
  22     #include "wx/settings.h" 
  24     #include "wx/stattext.h" 
  25     #include "wx/checkbox.h" 
  26     #include "wx/msgdlg.h" 
  28     #include "wx/filedlg.h" 
  31 #include "wx/clntdata.h" 
  32 #include "wx/file.h"        // for wxS_IXXX constants only 
  33 #include "wx/generic/dirctrlg.h" // for wxFileIconsTable 
  35 #include "wx/tokenzr.h" 
  38     #include "wx/msw/wrapwin.h" 
  41 #if defined(__WXWINCE__) 
  42 #define IsTopMostDir(dir) (dir == wxT("\\") || dir == wxT("/")) 
  43 #elif (defined(__DOS__) || defined(__WINDOWS__) || defined (__OS2__)) 
  44 #define IsTopMostDir(dir)   (dir.empty()) 
  46 #define IsTopMostDir(dir)   (dir == wxT("/")) 
  50 // ---------------------------------------------------------------------------- 
  52 // ---------------------------------------------------------------------------- 
  55 int wxCALLBACK 
wxFileDataNameCompare( long data1
, long data2
, long sortOrder
) 
  57      wxFileData 
*fd1 
= (wxFileData 
*)wxUIntToPtr(data1
); 
  58      wxFileData 
*fd2 
= (wxFileData 
*)wxUIntToPtr(data2
); 
  60      if (fd1
->GetFileName() == wxT("..")) 
  62      if (fd2
->GetFileName() == wxT("..")) 
  64      if (fd1
->IsDir() && !fd2
->IsDir()) 
  66      if (fd2
->IsDir() && !fd1
->IsDir()) 
  69      return sortOrder
*wxStrcmp( fd1
->GetFileName(), fd2
->GetFileName() ); 
  73 int wxCALLBACK 
wxFileDataSizeCompare(long data1
, long data2
, long sortOrder
) 
  75      wxFileData 
*fd1 
= (wxFileData 
*)wxUIntToPtr(data1
); 
  76      wxFileData 
*fd2 
= (wxFileData 
*)wxUIntToPtr(data2
); 
  78      if (fd1
->GetFileName() == wxT("..")) 
  80      if (fd2
->GetFileName() == wxT("..")) 
  82      if (fd1
->IsDir() && !fd2
->IsDir()) 
  84      if (fd2
->IsDir() && !fd1
->IsDir()) 
  86      if (fd1
->IsLink() && !fd2
->IsLink()) 
  88      if (fd2
->IsLink() && !fd1
->IsLink()) 
  91      return fd1
->GetSize() > fd2
->GetSize() ? sortOrder 
: -sortOrder
; 
  95 int wxCALLBACK 
wxFileDataTypeCompare(long data1
, long data2
, long sortOrder
) 
  97      wxFileData 
*fd1 
= (wxFileData 
*)wxUIntToPtr(data1
); 
  98      wxFileData 
*fd2 
= (wxFileData 
*)wxUIntToPtr(data2
); 
 100      if (fd1
->GetFileName() == wxT("..")) 
 102      if (fd2
->GetFileName() == wxT("..")) 
 104      if (fd1
->IsDir() && !fd2
->IsDir()) 
 106      if (fd2
->IsDir() && !fd1
->IsDir()) 
 108      if (fd1
->IsLink() && !fd2
->IsLink()) 
 110      if (fd2
->IsLink() && !fd1
->IsLink()) 
 113      return sortOrder
*wxStrcmp( fd1
->GetFileType(), fd2
->GetFileType() ); 
 117 int wxCALLBACK 
wxFileDataTimeCompare(long data1
, long data2
, long sortOrder
) 
 119      wxFileData 
*fd1 
= (wxFileData 
*)wxUIntToPtr(data1
); 
 120      wxFileData 
*fd2 
= (wxFileData 
*)wxUIntToPtr(data2
); 
 122      if (fd1
->GetFileName() == wxT("..")) 
 124      if (fd2
->GetFileName() == wxT("..")) 
 126      if (fd1
->IsDir() && !fd2
->IsDir()) 
 128      if (fd2
->IsDir() && !fd1
->IsDir()) 
 131      return fd1
->GetDateTime().IsLaterThan(fd2
->GetDateTime()) ? sortOrder 
: -sortOrder
; 
 134 // defined in src/generic/dirctrlg.cpp 
 135 extern size_t wxGetAvailableDrives(wxArrayString 
&paths
, wxArrayString 
&names
, wxArrayInt 
&icon_ids
); 
 137 //----------------------------------------------------------------------------- 
 139 //----------------------------------------------------------------------------- 
 141 wxFileData::wxFileData( const wxString 
&filePath
, const wxString 
&fileName
, fileType type
, int image_id 
) 
 144     m_fileName 
= fileName
; 
 145     m_filePath 
= filePath
; 
 152 void wxFileData::Init() 
 155     m_type 
= wxFileData::is_file
; 
 156     m_image 
= wxFileIconsTable::file
; 
 159 void wxFileData::Copy( const wxFileData
& fileData 
) 
 161     m_fileName 
= fileData
.GetFileName(); 
 162     m_filePath 
= fileData
.GetFilePath(); 
 163     m_size 
= fileData
.GetSize(); 
 164     m_dateTime 
= fileData
.GetDateTime(); 
 165     m_permissions 
= fileData
.GetPermissions(); 
 166     m_type 
= fileData
.GetType(); 
 167     m_image 
= fileData
.GetImageId(); 
 170 void wxFileData::ReadData() 
 178 #if defined(__DOS__) || (defined(__WINDOWS__) && !defined(__WXWINCE__)) || defined(__OS2__) 
 179     // c:\.. is a drive don't stat it 
 180     if ((m_fileName 
== wxT("..")) && (m_filePath
.length() <= 5)) 
 186 #endif // __DOS__ || __WINDOWS__ 
 192     DWORD fileAttribs 
= GetFileAttributes(m_filePath
.fn_str()); 
 193     m_type 
|= (fileAttribs 
& FILE_ATTRIBUTE_DIRECTORY
) != 0 ? is_dir 
: 0; 
 196     wxFileName::SplitPath(m_filePath
, & p
, & f
, & ext
); 
 197     if (wxStricmp(ext
, wxT("exe")) == 0) 
 202     HANDLE fileHandle 
= CreateFile(m_filePath
.fn_str(), 
 207             FILE_ATTRIBUTE_NORMAL
, 
 210     if (fileHandle 
!= INVALID_HANDLE_VALUE
) 
 212         m_size 
= GetFileSize(fileHandle
, 0); 
 213         CloseHandle(fileHandle
); 
 216     m_dateTime 
= wxFileModificationTime(m_filePath
); 
 224 #if defined(__UNIX__) && (!defined( __OS2__ ) && !defined(__VMS)) 
 225     lstat( m_filePath
.fn_str(), &buff 
); 
 226     m_type 
|= S_ISLNK(buff
.st_mode
) ? is_link 
: 0; 
 228     // only translate to file charset if we don't go by our 
 229     // wxStat implementation 
 230 #ifndef wxNEED_WX_UNISTD_H 
 231     wxStat( m_filePath
.fn_str() , &buff 
); 
 233     wxStat( m_filePath
, &buff 
); 
 237     m_type 
|= (buff
.st_mode 
& S_IFDIR
) != 0 ? is_dir 
: 0; 
 238     m_type 
|= (buff
.st_mode 
& wxS_IXUSR
) != 0 ? is_exe 
: 0; 
 240     m_size 
= buff
.st_size
; 
 242     m_dateTime 
= buff
.st_mtime
; 
 246 #if defined(__UNIX__) 
 247     m_permissions
.Printf(_T("%c%c%c%c%c%c%c%c%c"), 
 248                          buff
.st_mode 
& wxS_IRUSR 
? _T('r') : _T('-'), 
 249                          buff
.st_mode 
& wxS_IWUSR 
? _T('w') : _T('-'), 
 250                          buff
.st_mode 
& wxS_IXUSR 
? _T('x') : _T('-'), 
 251                          buff
.st_mode 
& wxS_IRGRP 
? _T('r') : _T('-'), 
 252                          buff
.st_mode 
& wxS_IWGRP 
? _T('w') : _T('-'), 
 253                          buff
.st_mode 
& wxS_IXGRP 
? _T('x') : _T('-'), 
 254                          buff
.st_mode 
& wxS_IROTH 
? _T('r') : _T('-'), 
 255                          buff
.st_mode 
& wxS_IWOTH 
? _T('w') : _T('-'), 
 256                          buff
.st_mode 
& wxS_IXOTH 
? _T('x') : _T('-')); 
 257 #elif defined(__WIN32__) 
 258     DWORD attribs 
= ::GetFileAttributes(m_filePath
.c_str()); 
 259     if (attribs 
!= (DWORD
)-1) 
 261         m_permissions
.Printf(_T("%c%c%c%c"), 
 262                              attribs 
& FILE_ATTRIBUTE_ARCHIVE  
? _T('A') : _T(' '), 
 263                              attribs 
& FILE_ATTRIBUTE_READONLY 
? _T('R') : _T(' '), 
 264                              attribs 
& FILE_ATTRIBUTE_HIDDEN   
? _T('H') : _T(' '), 
 265                              attribs 
& FILE_ATTRIBUTE_SYSTEM   
? _T('S') : _T(' ')); 
 269     // try to get a better icon 
 270     if (m_image 
== wxFileIconsTable::file
) 
 272         if (m_fileName
.Find(wxT('.'), true) != wxNOT_FOUND
) 
 274             m_image 
= wxTheFileIconsTable
->GetIconID( m_fileName
.AfterLast(wxT('.'))); 
 277             m_image 
= wxFileIconsTable::executable
; 
 282 wxString 
wxFileData::GetFileType() const 
 290     else if (m_fileName
.Find(wxT('.'), true) != wxNOT_FOUND
) 
 291         return m_fileName
.AfterLast(wxT('.')); 
 293     return wxEmptyString
; 
 296 wxString 
wxFileData::GetModificationTime() const 
 298     // want time as 01:02 so they line up nicely, no %r in WIN32 
 299     return m_dateTime
.FormatDate() + wxT(" ") + m_dateTime
.Format(wxT("%I:%M:%S %p")); 
 302 wxString 
wxFileData::GetHint() const 
 304     wxString s 
= m_filePath
; 
 314         s 
+= wxString::Format(wxPLURAL("%ld byte", "%ld bytes", m_size
), 
 315                               wxLongLong(m_size
).ToString().c_str()); 
 321         s 
<< GetModificationTime() 
 329 wxString 
wxFileData::GetEntry( fileListFieldType num 
) const 
 339             if (!IsDir() && !IsLink() && !IsDrive()) 
 340                 s 
= wxLongLong(m_size
).ToString(); 
 349                 s 
= GetModificationTime(); 
 352 #if defined(__UNIX__) || defined(__WIN32__) 
 356 #endif // defined(__UNIX__) || defined(__WIN32__) 
 359             wxFAIL_MSG( _T("unexpected field in wxFileData::GetEntry()") ); 
 365 void wxFileData::SetNewName( const wxString 
&filePath
, const wxString 
&fileName 
) 
 367     m_fileName 
= fileName
; 
 368     m_filePath 
= filePath
; 
 371 void wxFileData::MakeItem( wxListItem 
&item 
) 
 373     item
.m_text 
= m_fileName
; 
 374     item
.ClearAttributes(); 
 376         item
.SetTextColour(*wxRED
); 
 378         item
.SetTextColour(*wxBLUE
); 
 380     item
.m_image 
= m_image
; 
 384         wxColour dg 
= wxTheColourDatabase
->Find( _T("MEDIUM GREY") ); 
 386             item
.SetTextColour(dg
); 
 388     item
.m_data 
= wxPtrToUInt(this); 
 391 //----------------------------------------------------------------------------- 
 393 //----------------------------------------------------------------------------- 
 395 IMPLEMENT_DYNAMIC_CLASS(wxFileListCtrl
,wxListCtrl
) 
 397 BEGIN_EVENT_TABLE(wxFileListCtrl
,wxListCtrl
) 
 398     EVT_LIST_DELETE_ITEM(wxID_ANY
, wxFileListCtrl::OnListDeleteItem
) 
 399     EVT_LIST_DELETE_ALL_ITEMS(wxID_ANY
, wxFileListCtrl::OnListDeleteAllItems
) 
 400     EVT_LIST_END_LABEL_EDIT(wxID_ANY
, wxFileListCtrl::OnListEndLabelEdit
) 
 401     EVT_LIST_COL_CLICK(wxID_ANY
, wxFileListCtrl::OnListColClick
) 
 405 wxFileListCtrl::wxFileListCtrl() 
 407     m_showHidden 
= false; 
 408     m_sort_forward 
= true; 
 409     m_sort_field 
= wxFileData::FileList_Name
; 
 412 wxFileListCtrl::wxFileListCtrl(wxWindow 
*win
, 
 414                        const wxString
& wild
, 
 419                        const wxValidator 
&validator
, 
 420                        const wxString 
&name
) 
 421           : wxListCtrl(win
, id
, pos
, size
, style
, validator
, name
), 
 424     wxImageList 
*imageList 
= wxTheFileIconsTable
->GetSmallImageList(); 
 426     SetImageList( imageList
, wxIMAGE_LIST_SMALL 
); 
 428     m_showHidden 
= showHidden
; 
 430     m_sort_forward 
= true; 
 431     m_sort_field 
= wxFileData::FileList_Name
; 
 433     m_dirName 
= wxT("*"); 
 435     if (style 
& wxLC_REPORT
) 
 436         ChangeToReportMode(); 
 439 void wxFileListCtrl::ChangeToListMode() 
 442     SetSingleStyle( wxLC_LIST 
); 
 446 void wxFileListCtrl::ChangeToReportMode() 
 449     SetSingleStyle( wxLC_REPORT 
); 
 451     // do this since WIN32 does mm/dd/yy UNIX does mm/dd/yyyy 
 452     // don't hardcode since mm/dd is dd/mm elsewhere 
 454     wxDateTime 
dt(22, wxDateTime::Dec
, 2002, 22, 22, 22); 
 455     wxString txt 
= dt
.FormatDate() + wxT("22") + dt
.Format(wxT("%I:%M:%S %p")); 
 456     GetTextExtent(txt
, &w
, &h
); 
 458     InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT
, w 
); 
 459     InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT
, w
/2 ); 
 460     InsertColumn( 2, _("Type"), wxLIST_FORMAT_LEFT
, w
/2 ); 
 461     InsertColumn( 3, _("Modified"), wxLIST_FORMAT_LEFT
, w 
); 
 462 #if defined(__UNIX__) 
 463     GetTextExtent(wxT("Permissions 2"), &w
, &h
); 
 464     InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT
, w 
); 
 465 #elif defined(__WIN32__) 
 466     GetTextExtent(wxT("Attributes 2"), &w
, &h
); 
 467     InsertColumn( 4, _("Attributes"), wxLIST_FORMAT_LEFT
, w 
); 
 473 void wxFileListCtrl::ChangeToSmallIconMode() 
 476     SetSingleStyle( wxLC_SMALL_ICON 
); 
 480 void wxFileListCtrl::ShowHidden( bool show 
) 
 486 long wxFileListCtrl::Add( wxFileData 
*fd
, wxListItem 
&item 
) 
 489     item
.m_mask 
= wxLIST_MASK_TEXT 
+ wxLIST_MASK_DATA 
+ wxLIST_MASK_IMAGE
; 
 490     fd
->MakeItem( item 
); 
 491     long my_style 
= GetWindowStyleFlag(); 
 492     if (my_style 
& wxLC_REPORT
) 
 494         ret 
= InsertItem( item 
); 
 495         for (int i 
= 1; i 
< wxFileData::FileList_Max
; i
++) 
 496             SetItem( item
.m_itemId
, i
, fd
->GetEntry((wxFileData::fileListFieldType
)i
) ); 
 498     else if ((my_style 
& wxLC_LIST
) || (my_style 
& wxLC_SMALL_ICON
)) 
 500         ret 
= InsertItem( item 
); 
 505 void wxFileListCtrl::UpdateItem(const wxListItem 
&item
) 
 507     wxFileData 
*fd 
= (wxFileData
*)GetItemData(item
); 
 508     wxCHECK_RET(fd
, wxT("invalid filedata")); 
 512     SetItemText(item
, fd
->GetFileName()); 
 513     SetItemImage(item
, fd
->GetImageId()); 
 515     if (GetWindowStyleFlag() & wxLC_REPORT
) 
 517         for (int i 
= 1; i 
< wxFileData::FileList_Max
; i
++) 
 518             SetItem( item
.m_itemId
, i
, fd
->GetEntry((wxFileData::fileListFieldType
)i
) ); 
 522 void wxFileListCtrl::UpdateFiles() 
 524     // don't do anything before ShowModal() call which sets m_dirName 
 525     if ( m_dirName 
== wxT("*") ) 
 528     wxBusyCursor bcur
; // this may take a while... 
 536 #if (defined(__WINDOWS__) || defined(__DOS__) || defined(__WXMAC__) || defined(__OS2__)) && !defined(__WXWINCE__) 
 537     if ( IsTopMostDir(m_dirName
) ) 
 539         wxArrayString names
, paths
; 
 541         const size_t count 
= wxGetAvailableDrives(paths
, names
, icons
); 
 543         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 545             // use paths[n] as the drive name too as our HandleAction() can't 
 546             // deal with the drive names (of the form "System (C:)") currently 
 547             // as it mistakenly treats them as file names 
 549             // it would be preferable to show names, and not paths, in the 
 550             // dialog just as the native dialog does but for this we must: 
 551             //  a) store the item type as item data and modify HandleAction() 
 552             //     to use it instead of wxDirExists() to check whether the item 
 554             //  b) store the drives by their drive letters and not their 
 555             //     descriptions as otherwise it's pretty confusing to the user 
 556             wxFileData 
*fd 
= new wxFileData(paths
[n
], paths
[n
], 
 557                                             wxFileData::is_drive
, icons
[n
]); 
 558             if (Add(fd
, item
) != -1) 
 565 #endif // defined(__DOS__) || defined(__WINDOWS__) 
 568         if ( !IsTopMostDir(m_dirName
) && !m_dirName
.empty() ) 
 570             wxString 
p(wxPathOnly(m_dirName
)); 
 571 #if (defined(__UNIX__) || defined(__WXWINCE__)) && !defined(__OS2__) 
 572             if (p
.empty()) p 
= wxT("/"); 
 574             wxFileData 
*fd 
= new wxFileData(p
, wxT(".."), wxFileData::is_dir
, wxFileIconsTable::folder
); 
 575             if (Add(fd
, item
) != -1) 
 581         wxString 
dirname(m_dirName
); 
 582 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 583         if (dirname
.length() == 2 && dirname
[1u] == wxT(':')) 
 584             dirname 
<< wxT('\\'); 
 585 #endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 588             dirname 
= wxFILE_SEP_PATH
; 
 593         if ( dir
.IsOpened() ) 
 595             wxString 
dirPrefix(dirname
); 
 596             if (dirPrefix
.Last() != wxFILE_SEP_PATH
) 
 597                 dirPrefix 
+= wxFILE_SEP_PATH
; 
 599             int hiddenFlag 
= m_showHidden 
? wxDIR_HIDDEN 
: 0; 
 604             // Get the directories first (not matched against wildcards): 
 605             cont 
= dir
.GetFirst(&f
, wxEmptyString
, wxDIR_DIRS 
| hiddenFlag
); 
 608                 wxFileData 
*fd 
= new wxFileData(dirPrefix 
+ f
, f
, wxFileData::is_dir
, wxFileIconsTable::folder
); 
 609                 if (Add(fd
, item
) != -1) 
 614                 cont 
= dir
.GetNext(&f
); 
 617             // Tokenize the wildcard string, so we can handle more than 1 
 618             // search pattern in a wildcard. 
 619             wxStringTokenizer 
tokenWild(m_wild
, wxT(";")); 
 620             while ( tokenWild
.HasMoreTokens() ) 
 622                 cont 
= dir
.GetFirst(&f
, tokenWild
.GetNextToken(), 
 623                                         wxDIR_FILES 
| hiddenFlag
); 
 626                     wxFileData 
*fd 
= new wxFileData(dirPrefix 
+ f
, f
, wxFileData::is_file
, wxFileIconsTable::file
); 
 627                     if (Add(fd
, item
) != -1) 
 632                     cont 
= dir
.GetNext(&f
); 
 638     SortItems(m_sort_field
, m_sort_forward
); 
 641 void wxFileListCtrl::SetWild( const wxString 
&wild 
) 
 643     if (wild
.Find(wxT('|')) != wxNOT_FOUND
) 
 650 void wxFileListCtrl::MakeDir() 
 652     wxString 
new_name( _("NewName") ); 
 653     wxString 
path( m_dirName 
); 
 654     path 
+= wxFILE_SEP_PATH
; 
 656     if (wxFileExists(path
)) 
 658         // try NewName0, NewName1 etc. 
 661             new_name 
= _("NewName"); 
 663             num
.Printf( wxT("%d"), i 
); 
 667             path 
+= wxFILE_SEP_PATH
; 
 670         } while (wxFileExists(path
)); 
 676         wxMessageDialog 
dialog(this, _("Operation not permitted."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 681     wxFileData 
*fd 
= new wxFileData( path
, new_name
, wxFileData::is_dir
, wxFileIconsTable::folder 
); 
 685     long id 
= Add( fd
, item 
); 
 689         SortItems(m_sort_field
, m_sort_forward
); 
 690         id 
= FindItem( 0, wxPtrToUInt(fd
) ); 
 698 void wxFileListCtrl::GoToParentDir() 
 700     if (!IsTopMostDir(m_dirName
)) 
 702         size_t len 
= m_dirName
.length(); 
 703         if (wxEndsWithPathSeparator(m_dirName
)) 
 704             m_dirName
.Remove( len
-1, 1 ); 
 705         wxString 
fname( wxFileNameFromPath(m_dirName
) ); 
 706         m_dirName 
= wxPathOnly( m_dirName 
); 
 707 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__) 
 708         if (!m_dirName
.empty()) 
 710             if (m_dirName
.Last() == wxT('.')) 
 711                 m_dirName 
= wxEmptyString
; 
 713 #elif defined(__UNIX__) 
 714         if (m_dirName
.empty()) 
 715             m_dirName 
= wxT("/"); 
 718         long id 
= FindItem( 0, fname 
); 
 719         if (id 
!= wxNOT_FOUND
) 
 721             SetItemState( id
, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
 727 void wxFileListCtrl::GoToHomeDir() 
 729     wxString s 
= wxGetUserHome( wxString() ); 
 733 void wxFileListCtrl::GoToDir( const wxString 
&dir 
) 
 735     if (!wxDirExists(dir
)) return; 
 740     SetItemState( 0, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
 745 void wxFileListCtrl::FreeItemData(wxListItem
& item
) 
 749         wxFileData 
*fd 
= (wxFileData
*)item
.m_data
; 
 756 void wxFileListCtrl::OnListDeleteItem( wxListEvent 
&event 
) 
 758     FreeItemData(event
.m_item
); 
 761 void wxFileListCtrl::OnListDeleteAllItems( wxListEvent 
& WXUNUSED(event
) ) 
 766 void wxFileListCtrl::FreeAllItemsData() 
 769     item
.m_mask 
= wxLIST_MASK_DATA
; 
 771     item
.m_itemId 
= GetNextItem( -1, wxLIST_NEXT_ALL 
); 
 772     while ( item
.m_itemId 
!= -1 ) 
 776         item
.m_itemId 
= GetNextItem( item
.m_itemId
, wxLIST_NEXT_ALL 
); 
 780 void wxFileListCtrl::OnListEndLabelEdit( wxListEvent 
&event 
) 
 782     wxFileData 
*fd 
= (wxFileData
*)event
.m_item
.m_data
; 
 785     if ((event
.GetLabel().empty()) || 
 786         (event
.GetLabel() == wxT(".")) || 
 787         (event
.GetLabel() == wxT("..")) || 
 788         (event
.GetLabel().First( wxFILE_SEP_PATH 
) != wxNOT_FOUND
)) 
 790         wxMessageDialog 
dialog(this, _("Illegal directory name."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 796     wxString 
new_name( wxPathOnly( fd
->GetFilePath() ) ); 
 797     new_name 
+= wxFILE_SEP_PATH
; 
 798     new_name 
+= event
.GetLabel(); 
 802     if (wxFileExists(new_name
)) 
 804         wxMessageDialog 
dialog(this, _("File name exists already."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 809     if (wxRenameFile(fd
->GetFilePath(),new_name
)) 
 811         fd
->SetNewName( new_name
, event
.GetLabel() ); 
 813         SetItemState( event
.GetItem(), wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
 815         UpdateItem( event
.GetItem() ); 
 816         EnsureVisible( event
.GetItem() ); 
 820         wxMessageDialog 
dialog(this, _("Operation not permitted."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 826 void wxFileListCtrl::OnListColClick( wxListEvent 
&event 
) 
 828     int col 
= event
.GetColumn(); 
 832         case wxFileData::FileList_Name 
: 
 833         case wxFileData::FileList_Size 
: 
 834         case wxFileData::FileList_Type 
: 
 835         case wxFileData::FileList_Time 
: break; 
 839     if ((wxFileData::fileListFieldType
)col 
== m_sort_field
) 
 840         m_sort_forward 
= !m_sort_forward
; 
 842         m_sort_field 
= (wxFileData::fileListFieldType
)col
; 
 844     SortItems(m_sort_field
, m_sort_forward
); 
 847 void wxFileListCtrl::SortItems(wxFileData::fileListFieldType field
, bool forward
) 
 849     m_sort_field 
= field
; 
 850     m_sort_forward 
= forward
; 
 851     const long sort_dir 
= forward 
? 1 : -1; 
 853     switch (m_sort_field
) 
 855         case wxFileData::FileList_Size 
: 
 856             wxListCtrl::SortItems(wxFileDataSizeCompare
, sort_dir
); 
 859         case wxFileData::FileList_Type 
: 
 860             wxListCtrl::SortItems(wxFileDataTypeCompare
, sort_dir
); 
 863         case wxFileData::FileList_Time 
: 
 864             wxListCtrl::SortItems(wxFileDataTimeCompare
, sort_dir
); 
 867         case wxFileData::FileList_Name 
: 
 869             wxListCtrl::SortItems(wxFileDataNameCompare
, sort_dir
); 
 874 wxFileListCtrl::~wxFileListCtrl() 
 876     // Normally the data are freed via an EVT_LIST_DELETE_ALL_ITEMS event and 
 877     // wxFileListCtrl::OnListDeleteAllItems. But if the event is generated after 
 878     // the destruction of the wxFileListCtrl we need to free any data here: 
 882 #define  ID_CHOICE        (wxID_FILECTRL + 1) 
 883 #define  ID_TEXT          (wxID_FILECTRL + 2) 
 884 #define  ID_FILELIST_CTRL (wxID_FILECTRL + 3) 
 885 #define  ID_CHECK         (wxID_FILECTRL + 4) 
 887 /////////////////////////////////////////////////////////////////////////////// 
 888 // wxGenericFileCtrl implementation 
 889 /////////////////////////////////////////////////////////////////////////////// 
 891 IMPLEMENT_DYNAMIC_CLASS( wxGenericFileCtrl
, wxPanel 
) 
 893 BEGIN_EVENT_TABLE( wxGenericFileCtrl
, wxPanel 
) 
 894     EVT_LIST_ITEM_SELECTED( ID_FILELIST_CTRL
, wxGenericFileCtrl::OnSelected 
) 
 895     EVT_LIST_ITEM_ACTIVATED( ID_FILELIST_CTRL
, wxGenericFileCtrl::OnActivated 
) 
 896     EVT_CHOICE( ID_CHOICE
, wxGenericFileCtrl::OnChoiceFilter 
) 
 897     EVT_TEXT_ENTER( ID_TEXT
, wxGenericFileCtrl::OnTextEnter 
) 
 898     EVT_TEXT( ID_TEXT
, wxGenericFileCtrl::OnTextChange 
) 
 899     EVT_CHECKBOX( ID_CHECK
, wxGenericFileCtrl::OnCheck 
) 
 902 bool wxGenericFileCtrl::Create( wxWindow 
*parent
, 
 904                                 const wxString
& defaultDirectory
, 
 905                                 const wxString
& defaultFileName
, 
 906                                 const wxString
& wildCard
, 
 910                                 const wxString
& name 
) 
 912     this->m_style 
= style
; 
 913     m_inSelected 
= false; 
 914     m_noSelChgEvent 
= false; 
 917     // check that the styles are not contradictory 
 918     wxASSERT_MSG( !( ( m_style 
& wxFC_SAVE 
) && ( m_style 
& wxFC_OPEN 
) ), 
 919                   wxT( "can't specify both wxFC_SAVE and wxFC_OPEN at once" ) ); 
 921     wxASSERT_MSG( !( ( m_style 
& wxFC_SAVE 
) && ( m_style 
& wxFC_MULTIPLE 
) ), 
 922                   wxT( "wxFC_MULTIPLE can't be used with wxFC_SAVE" ) ); 
 924     wxPanel::Create( parent
, id
, pos
, size
, wxTAB_TRAVERSAL
, name 
); 
 926     m_dir 
= defaultDirectory
; 
 928     m_ignoreChanges 
= true; 
 930     if ( ( m_dir
.empty() ) || ( m_dir 
== wxT( "." ) ) ) 
 934             m_dir 
= wxFILE_SEP_PATH
; 
 937     const size_t len 
= m_dir
.length(); 
 938     if ( ( len 
> 1 ) && ( wxEndsWithPathSeparator( m_dir 
) ) ) 
 939         m_dir
.Remove( len 
- 1, 1 ); 
 941     m_filterExtension 
= wxEmptyString
; 
 945     const bool is_pda 
= ( wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA 
); 
 947     wxBoxSizer 
*mainsizer 
= new wxBoxSizer( wxVERTICAL 
); 
 949     wxBoxSizer 
*staticsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 951         staticsizer
->Add( new wxStaticText( this, wxID_ANY
, _( "Current directory:" ) ), 
 952                           wxSizerFlags().DoubleBorder(wxRIGHT
) ); 
 953     m_static 
= new wxStaticText( this, wxID_ANY
, m_dir 
); 
 954     staticsizer
->Add( m_static
, 1 ); 
 955     mainsizer
->Add( staticsizer
, wxSizerFlags().Expand().Border()); 
 957     long style2 
= wxLC_LIST
; 
 958     if ( !( m_style 
& wxFC_MULTIPLE 
) ) 
 959         style2 
|= wxLC_SINGLE_SEL
; 
 962     style2 
|= wxSIMPLE_BORDER
; 
 964     style2 
|= wxSUNKEN_BORDER
; 
 967     m_list 
= new wxFileListCtrl( this, ID_FILELIST_CTRL
, 
 968                                  wxEmptyString
, false, 
 969                                  wxDefaultPosition
, wxSize( 400, 140 ), 
 972     m_text 
= new wxTextCtrl( this, ID_TEXT
, wxEmptyString
, 
 973                              wxDefaultPosition
, wxDefaultSize
, 
 974                              wxTE_PROCESS_ENTER 
); 
 975     m_choice 
= new wxChoice( this, ID_CHOICE 
); 
 979         // PDAs have a different screen layout 
 980         mainsizer
->Add( m_list
, wxSizerFlags( 1 ).Expand().HorzBorder() ); 
 982         wxBoxSizer 
*textsizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 983         textsizer
->Add( m_text
, wxSizerFlags( 1 ).Centre().Border() ); 
 984         textsizer
->Add( m_choice
, wxSizerFlags( 1 ).Centre().Border() ); 
 985         mainsizer
->Add( textsizer
, wxSizerFlags().Expand() ); 
 990         mainsizer
->Add( m_list
, wxSizerFlags( 1 ).Expand().Border() ); 
 991         mainsizer
->Add( m_text
, wxSizerFlags().Expand().Border() ); 
 993         wxBoxSizer 
*choicesizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 994         choicesizer
->Add( m_choice
, wxSizerFlags( 1 ).Centre() ); 
 996         if ( !( m_style 
& wxFC_NOSHOWHIDDEN 
) ) 
 998             m_check 
= new wxCheckBox( this, ID_CHECK
, _( "Show &hidden files" ) ); 
 999             choicesizer
->Add( m_check
, wxSizerFlags().Centre().DoubleBorder(wxLEFT
) ); 
1002         mainsizer
->Add( choicesizer
, wxSizerFlags().Expand().Border() ); 
1005     SetWildcard( wildCard 
); 
1007     SetAutoLayout( true ); 
1008     SetSizer( mainsizer 
); 
1012         mainsizer
->Fit( this ); 
1015     m_list
->GoToDir( m_dir 
); 
1017     m_text
->SetValue( m_fileName 
); 
1019     m_ignoreChanges 
= false; 
1021     // must be after m_ignoreChanges = false 
1022     SetFilename( defaultFileName 
); 
1027 // NB: there is an unfortunate mismatch between wxFileName and wxFileDialog 
1028 //     method names but our GetDirectory() does correspond to wxFileName:: 
1029 //     GetPath() while our GetPath() is wxFileName::GetFullPath() 
1030 wxString 
wxGenericFileCtrl::GetPath() const 
1032     wxASSERT_MSG ( !(m_style 
& wxFC_MULTIPLE
), "use GetPaths() instead" ); 
1034     return DoGetFileName().GetFullPath(); 
1037 wxString 
wxGenericFileCtrl::GetFilename() const 
1039     wxASSERT_MSG ( !(m_style 
& wxFC_MULTIPLE
), "use GetFilenames() instead" ); 
1041     return DoGetFileName().GetFullName(); 
1044 wxString 
wxGenericFileCtrl::GetDirectory() const 
1046     // don't check for wxFC_MULTIPLE here, this one is probably safe to call in 
1047     // any case as it can be always taken to mean "current directory" 
1048     return DoGetFileName().GetPath(); 
1051 wxFileName 
wxGenericFileCtrl::DoGetFileName() const 
1055     wxString value 
= m_text
->GetValue(); 
1056     if ( value
.empty() ) 
1058         // nothing in the text control, get the selected file from the list 
1060         item
.m_itemId 
= m_list
->GetNextItem(-1, wxLIST_NEXT_ALL
, 
1061                                             wxLIST_STATE_SELECTED
); 
1062         m_list
->GetItem(item
); 
1064         fn
.Assign(m_list
->GetDir(), item
.m_text
); 
1066     else // user entered the value 
1068         // the path can be either absolute or relative 
1070         if ( fn
.IsRelative() ) 
1071             fn
.MakeAbsolute(m_list
->GetDir()); 
1077 // helper used in DoGetFilenames() and needed because Borland can't compile 
1078 // operator?: inline 
1079 static inline wxString 
GetFileNameOrPath(const wxFileName
& fn
, bool fullPath
) 
1081     return fullPath 
? fn
.GetFullPath() : fn
.GetFullName(); 
1085 wxGenericFileCtrl::DoGetFilenames(wxArrayString
& filenames
, bool fullPath
) const 
1089     const wxString dir 
= m_list
->GetDir(); 
1091     const wxString value 
= m_text
->GetValue(); 
1092     if ( !value
.empty() ) 
1094         wxFileName 
fn(value
); 
1095         if ( fn
.IsRelative() ) 
1096             fn
.MakeAbsolute(dir
); 
1098         filenames
.push_back(GetFileNameOrPath(fn
, fullPath
)); 
1102     const int numSel 
= m_list
->GetSelectedItemCount(); 
1106     filenames
.reserve(numSel
); 
1109     item
.m_mask 
= wxLIST_MASK_TEXT
; 
1113         item
.m_itemId 
= m_list
->GetNextItem(item
.m_itemId
, wxLIST_NEXT_ALL
, 
1114                                             wxLIST_STATE_SELECTED
); 
1116         if ( item
.m_itemId 
== -1 ) 
1119         m_list
->GetItem(item
); 
1121         const wxFileName 
fn(dir
, item
.m_text
); 
1122         filenames
.push_back(GetFileNameOrPath(fn
, fullPath
)); 
1126 bool wxGenericFileCtrl::SetDirectory( const wxString
& dir 
) 
1128     m_ignoreChanges 
= true; 
1129     m_list
->GoToDir( dir 
); 
1131     m_ignoreChanges 
= false; 
1133     return wxFileName( dir 
).SameAs( m_list
->GetDir() ); 
1136 bool wxGenericFileCtrl::SetFilename( const wxString
& name 
) 
1138     const long item 
= m_list
->FindItem( -1, name 
); 
1140     if ( item 
== -1 ) // file not found either because it doesn't exist or the 
1141         // current filter doesn't show it. 
1144     m_noSelChgEvent 
= true; 
1146     // Deselect selected items 
1148         const int numSelectedItems 
= m_list
->GetSelectedItemCount(); 
1150         if ( numSelectedItems 
> 0 ) 
1152             long itemIndex 
= -1; 
1156                 itemIndex 
= m_list
->GetNextItem( itemIndex
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED 
); 
1157                 if ( itemIndex 
== -1 ) 
1160                 m_list
->SetItemState( itemIndex
, 0, wxLIST_STATE_SELECTED 
); 
1165     m_list
->SetItemState( item
, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED 
); 
1166     m_list
->EnsureVisible( item 
); 
1168     m_noSelChgEvent 
= false; 
1173 void wxGenericFileCtrl::DoSetFilterIndex( int filterindex 
) 
1175     wxClientData 
*pcd 
= m_choice
->GetClientObject( filterindex 
); 
1179     const wxString
& str 
= ((static_cast<wxStringClientData 
*>(pcd
))->GetData()); 
1180     m_list
->SetWild( str 
); 
1181     m_filterIndex 
= filterindex
; 
1182     if ( str
.Left( 2 ) == wxT( "*." ) ) 
1184         m_filterExtension 
= str
.Mid( 1 ); 
1185         if ( m_filterExtension 
== _T( ".*" ) ) 
1186             m_filterExtension
.clear(); 
1190         m_filterExtension
.clear(); 
1194 void wxGenericFileCtrl::SetWildcard( const wxString
& wildCard 
) 
1196     if ( wildCard
.empty() || wildCard 
== wxFileSelectorDefaultWildcardStr 
) 
1198         m_wildCard 
= wxString::Format( _( "All files (%s)|%s" ), 
1199                                        wxFileSelectorDefaultWildcardStr
, 
1200                                        wxFileSelectorDefaultWildcardStr 
); 
1203         m_wildCard 
= wildCard
; 
1205     wxArrayString wildDescriptions
, wildFilters
; 
1206     const size_t count 
= wxParseCommonDialogsFilter( m_wildCard
, 
1209     wxCHECK_RET( count
, wxT( "wxFileDialog: bad wildcard string" ) ); 
1213     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1215         m_choice
->Append(wildDescriptions
[n
], new wxStringClientData(wildFilters
[n
])); 
1218     SetFilterIndex( 0 ); 
1221 void wxGenericFileCtrl::SetFilterIndex( int filterindex 
) 
1223     m_choice
->SetSelection( filterindex 
); 
1225     DoSetFilterIndex( filterindex 
); 
1228 void wxGenericFileCtrl::OnChoiceFilter( wxCommandEvent 
&event 
) 
1230     DoSetFilterIndex( ( int )event
.GetInt() ); 
1233 void wxGenericFileCtrl::OnCheck( wxCommandEvent 
&event 
) 
1235     m_list
->ShowHidden( event
.GetInt() != 0 ); 
1238 void wxGenericFileCtrl::OnActivated( wxListEvent 
&event 
) 
1240     HandleAction( event
.m_item
.m_text 
); 
1243 void wxGenericFileCtrl::OnTextEnter( wxCommandEvent 
&WXUNUSED( event 
) ) 
1245     HandleAction( m_text
->GetValue() ); 
1248 void wxGenericFileCtrl::OnTextChange( wxCommandEvent 
&WXUNUSED( event 
) ) 
1250     if ( !m_ignoreChanges 
) 
1252         // Clear selections.  Otherwise when the user types in a value they may 
1253         // not get the file whose name they typed. 
1254         if ( m_list
->GetSelectedItemCount() > 0 ) 
1256             long item 
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, 
1257                                              wxLIST_STATE_SELECTED 
); 
1258             while ( item 
!= -1 ) 
1260                 m_list
->SetItemState( item
, 0, wxLIST_STATE_SELECTED 
); 
1261                 item 
= m_list
->GetNextItem( item
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED 
); 
1267 void wxGenericFileCtrl::OnSelected( wxListEvent 
&event 
) 
1269     if ( m_ignoreChanges 
) 
1275     m_inSelected 
= true; 
1276     const wxString 
filename( event
.m_item
.m_text 
); 
1279     // No double-click on most WinCE devices, so do action immediately. 
1280     HandleAction( filename 
); 
1282     if ( filename 
== wxT( ".." ) ) 
1284         m_inSelected 
= false; 
1288     wxString dir 
= m_list
->GetDir(); 
1289     if ( !IsTopMostDir( dir 
) ) 
1290         dir 
+= wxFILE_SEP_PATH
; 
1292     if ( wxDirExists( dir 
) ) 
1294         m_inSelected 
= false; 
1300     m_ignoreChanges 
= true; 
1301     m_text
->SetValue( filename 
); 
1303     if ( m_list
->GetSelectedItemCount() > 1 ) 
1308     if ( !m_noSelChgEvent 
) 
1309         GenerateSelectionChangedEvent( this, this ); 
1311     m_ignoreChanges 
= false; 
1313     m_inSelected 
= false; 
1316 void wxGenericFileCtrl::HandleAction( const wxString 
&fn 
) 
1318     if ( m_ignoreChanges 
) 
1321     wxString 
filename( fn 
); 
1322     if ( filename
.empty() ) 
1326     if ( filename 
== wxT( "." ) ) return; 
1328     wxString dir 
= m_list
->GetDir(); 
1330     // "some/place/" means they want to chdir not try to load "place" 
1331     const bool want_dir 
= filename
.Last() == wxFILE_SEP_PATH
; 
1333         filename 
= filename
.RemoveLast(); 
1335     if ( filename 
== wxT( ".." ) ) 
1337         m_ignoreChanges 
= true; 
1338         m_list
->GoToParentDir(); 
1340         GenerateFolderChangedEvent( this, this ); 
1343         m_ignoreChanges 
= false; 
1348     if ( filename 
== wxT( "~" ) ) 
1350         m_ignoreChanges 
= true; 
1351         m_list
->GoToHomeDir(); 
1353         GenerateFolderChangedEvent( this, this ); 
1356         m_ignoreChanges 
= false; 
1360     if ( filename
.BeforeFirst( wxT( '/' ) ) == wxT( "~" ) ) 
1362         filename 
= wxString( wxGetUserHome() ) + filename
.Remove( 0, 1 ); 
1366     if ( !( m_style 
& wxFC_SAVE 
) ) 
1368         if ( ( filename
.Find( wxT( '*' ) ) != wxNOT_FOUND 
) || 
1369                 ( filename
.Find( wxT( '?' ) ) != wxNOT_FOUND 
) ) 
1371             if ( filename
.Find( wxFILE_SEP_PATH 
) != wxNOT_FOUND 
) 
1373                 wxMessageBox( _( "Illegal file specification." ), 
1374                               _( "Error" ), wxOK 
| wxICON_ERROR
, this ); 
1377             m_list
->SetWild( filename 
); 
1382     if ( !IsTopMostDir( dir 
) ) 
1383         dir 
+= wxFILE_SEP_PATH
; 
1384     if ( !wxIsAbsolutePath( filename 
) ) 
1390     if ( wxDirExists( filename 
) ) 
1392         m_ignoreChanges 
= true; 
1393         m_list
->GoToDir( filename 
); 
1396         GenerateFolderChangedEvent( this, this ); 
1398         m_ignoreChanges 
= false; 
1402     // they really wanted a dir, but it doesn't exist 
1405         wxMessageBox( _( "Directory doesn't exist." ), _( "Error" ), 
1406                       wxOK 
| wxICON_ERROR
, this ); 
1410     // append the default extension to the filename if it doesn't have any 
1412     // VZ: the logic of testing for !wxFileExists() only for the open file 
1413     //     dialog is not entirely clear to me, why don't we allow saving to a 
1414     //     file without extension as well? 
1415     if ( !( m_style 
& wxFC_OPEN 
) || !wxFileExists( filename 
) ) 
1417         filename 
= wxFileDialogBase::AppendExtension( filename
, m_filterExtension 
); 
1418         GenerateFileActivatedEvent( this, this, wxFileName( filename 
).GetFullName() ); 
1422     GenerateFileActivatedEvent( this, this ); 
1425 bool wxGenericFileCtrl::SetPath( const wxString
& path 
) 
1427     if ( !wxFileName::FileExists( ( path 
) ) ) 
1431     wxFileName::SplitPath( path
, &m_dir
, &m_fileName
, &ext 
); 
1434         m_fileName 
+= wxT( "." ); 
1438     SetDirectory( m_dir 
); 
1439     SetFilename( m_fileName 
); 
1444 void wxGenericFileCtrl::GetPaths( wxArrayString
& paths 
) const 
1446     DoGetFilenames( paths
, true ); 
1449 void wxGenericFileCtrl::GetFilenames( wxArrayString
& files 
) const 
1451     DoGetFilenames( files
, false ); 
1454 void wxGenericFileCtrl::UpdateControls() 
1456     const wxString dir 
= m_list
->GetDir(); 
1457     m_static
->SetLabel( dir 
); 
1460 void wxGenericFileCtrl::GoToParentDir() 
1462     m_list
->GoToParentDir(); 
1466 void wxGenericFileCtrl::GoToHomeDir() 
1468     m_list
->GoToHomeDir(); 
1472 #endif // wxUSE_FILECTRL