1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxGenericDirCtrl 
   4 // Author:      Harm van der Heijden, Robert Roebling, Julian Smart 
   8 // Copyright:   (c) Harm van der Heijden, Robert Roebling and Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "dirctrlg.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  26 #include "wx/dialog.h" 
  27 #include "wx/button.h" 
  28 #include "wx/layout.h" 
  29 #include "wx/msgdlg.h" 
  30 #include "wx/textctrl.h" 
  31 #include "wx/textdlg.h" 
  32 #include "wx/filefn.h" 
  33 #include "wx/cmndata.h" 
  34 #include "wx/gdicmn.h" 
  36 #include "wx/imaglist.h" 
  40 #include "wx/tokenzr.h" 
  42 #include "wx/settings.h" 
  45     #include "wx/statline.h" 
  48 #include "wx/generic/dirctrlg.h" 
  50 #if defined(__WXMAC__) 
  51   #include  "wx/mac/private.h"  // includes mac headers 
  57 // FIXME - Mingw32 1.0 has both _getdrive() and _chdrive(). For now, let's assume 
  58 //         older releases don't, but it should be verified and the checks modified 
  60 #if !defined(__GNUWIN32__) || \ 
  61     (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
  79 #if defined(__WXMAC__) 
  80 #  include "MoreFilesExtras.h" 
  87 // If compiled under Windows, this macro can cause problems 
  93 static const char * icon1_xpm
[] = { 
  94 /* width height ncolors chars_per_pixel */ 
 122 static const char * icon2_xpm
[] = { 
 123 /* width height ncolors chars_per_pixel */ 
 151 static const char * icon3_xpm
[] = { 
 152 /* width height ncolors chars_per_pixel */ 
 177 static const char * icon4_xpm
[] = { 
 204 static const char * icon5_xpm
[] = { 
 231 static const char *icon6_xpm
[] = { 
 261 static const char * icon7_xpm
[] = { 
 288 static const char * icon8_xpm
[] = { 
 315 #define wxID_TREECTRL          7000 
 316 #define wxID_FILTERLISTCTRL    7001 
 320 bool wxIsDriveAvailable(const wxString
& dirName
) 
 322     // FIXME_MGL - this method leads to hang up under Watcom for some reason 
 324     if ( dirName
.Len() == 3 && dirName
[1u] == wxT(':') ) 
 326         wxString 
dirNameLower(dirName
.Lower()); 
 327         // VS: always return TRUE for removable media, since Win95 doesn't 
 328         //     like it when MS-DOS app accesses empty floppy drive 
 329         return (dirNameLower
[0u] == wxT('a') || 
 330                 dirNameLower
[0u] == wxT('b') || 
 331                 wxPathExists(dirNameLower
)); 
 338 #elif defined(__WINDOWS__) || defined(__WXPM__) 
 340 int setdrive(int drive
) 
 342 #if defined(__GNUWIN32__) && \ 
 343     (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
 344     return _chdrive(drive
); 
 348         if (drive 
< 1 || drive 
> 31) 
 350         newdrive
[0] = (wxChar
)(wxT('A') + drive 
- 1); 
 351         newdrive
[1] = wxT(':'); 
 352         newdrive
[2] = wxT('\0'); 
 353 #if defined(__WXMSW__) 
 355     if (wxSetWorkingDirectory(newdrive
)) 
 357         if (::SetCurrentDirectory(newdrive
)) 
 360     // VA doesn't know what LPSTR is and has its own set 
 361         if (DosSetCurrentDir((PSZ
)newdrive
)) 
 369 bool wxIsDriveAvailable(const wxString
& dirName
) 
 372     UINT errorMode 
= SetErrorMode(SEM_FAILCRITICALERRORS 
| SEM_NOOPENFILEERRORBOX
); 
 376     // Check if this is a root directory and if so, 
 377     // whether the drive is avaiable. 
 378     if (dirName
.Len() == 3 && dirName
[(size_t)1] == wxT(':')) 
 380         wxString 
dirNameLower(dirName
.Lower()); 
 381 #if defined(__GNUWIN32__) && \ 
 382     !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1) 
 383         success 
= wxPathExists(dirNameLower
); 
 385         int currentDrive 
= _getdrive(); 
 386         int thisDrive 
= (int) (dirNameLower
[(size_t)0] - 'a' + 1) ; 
 387         int err 
= setdrive( thisDrive 
) ; 
 388         setdrive( currentDrive 
); 
 397     (void) SetErrorMode(errorMode
); 
 402 #endif // __WINDOWS__ || __WXPM__ 
 404 // Function which is called by quick sort. We want to override the default wxArrayString behaviour, 
 405 // and sort regardless of case. 
 406 static int LINKAGEMODE 
wxDirCtrlStringCompareFunction(const void *first
, const void *second
) 
 408     wxString 
*strFirst 
= (wxString 
*)first
; 
 409     wxString 
*strSecond 
= (wxString 
*)second
; 
 411     return strFirst
->CmpNoCase(*strSecond
); 
 414 //----------------------------------------------------------------------------- 
 416 //----------------------------------------------------------------------------- 
 418 wxDirItemData::wxDirItemData(const wxString
& path
, const wxString
& name
, 
 423     /* Insert logic to detect hidden files here 
 424      * In UnixLand we just check whether the first char is a dot 
 425      * For FileNameFromPath read LastDirNameInThisPath ;-) */ 
 426     // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.'); 
 428     m_isExpanded 
= FALSE
; 
 432 wxDirItemData::~wxDirItemData() 
 436 void wxDirItemData::SetNewDirName(const wxString
& path
) 
 439     m_name 
= wxFileNameFromPath(path
); 
 442 bool wxDirItemData::HasSubDirs() const 
 444     if (m_path
.IsEmpty()) 
 450         if ( !dir
.Open(m_path
) ) 
 454     return dir
.HasSubDirs(); 
 457 bool wxDirItemData::HasFiles(const wxString
& WXUNUSED(spec
)) const 
 459     if (m_path
.IsEmpty()) 
 465         if ( !dir
.Open(m_path
) ) 
 469     return dir
.HasFiles(); 
 472 //----------------------------------------------------------------------------- 
 474 //----------------------------------------------------------------------------- 
 476 IMPLEMENT_DYNAMIC_CLASS(wxGenericDirCtrl
, wxControl
) 
 478 BEGIN_EVENT_TABLE(wxGenericDirCtrl
, wxControl
) 
 479   EVT_TREE_ITEM_EXPANDING     (-1, wxGenericDirCtrl::OnExpandItem
) 
 480   EVT_TREE_ITEM_COLLAPSED     (-1, wxGenericDirCtrl::OnCollapseItem
) 
 481   EVT_TREE_BEGIN_LABEL_EDIT   (-1, wxGenericDirCtrl::OnBeginEditItem
) 
 482   EVT_TREE_END_LABEL_EDIT     (-1, wxGenericDirCtrl::OnEndEditItem
) 
 483   EVT_SIZE                    (wxGenericDirCtrl::OnSize
) 
 486 wxGenericDirCtrl::wxGenericDirCtrl(void) 
 491 bool wxGenericDirCtrl::Create(wxWindow 
*parent
, 
 497                               const wxString
& filter
, 
 499                               const wxString
& name
) 
 501     if (!wxControl::Create(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
)) 
 504     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)); 
 508     long treeStyle 
= wxTR_HAS_BUTTONS 
; // | wxTR_EDIT_LABELS ; 
 511     treeStyle 
|= wxTR_HIDE_ROOT
; 
 514     if ((style 
& wxDIRCTRL_3D_INTERNAL
) == 0) 
 515         treeStyle 
|= wxNO_BORDER
; 
 517     long filterStyle 
= 0; 
 518     if ((style 
& wxDIRCTRL_3D_INTERNAL
) == 0) 
 519         filterStyle 
|= wxNO_BORDER
; 
 521     m_treeCtrl 
= new wxTreeCtrl(this, wxID_TREECTRL
, pos
, size
, treeStyle
); 
 523     if (!filter
.IsEmpty() && (style 
& wxDIRCTRL_SHOW_FILTERS
)) 
 524         m_filterListCtrl 
= new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL
, wxDefaultPosition
, wxDefaultSize
, filterStyle
); 
 529     SetFilterIndex(defaultFilter
); 
 531     if (m_filterListCtrl
) 
 532         m_filterListCtrl
->FillFilterList(filter
, defaultFilter
); 
 534     m_imageList 
= new wxImageList(16, 16, TRUE
); 
 535     m_imageList
->Add(wxIcon(icon1_xpm
)); 
 536     m_imageList
->Add(wxIcon(icon2_xpm
)); 
 537     m_imageList
->Add(wxIcon(icon3_xpm
)); 
 538     m_imageList
->Add(wxIcon(icon4_xpm
)); 
 539     m_imageList
->Add(wxIcon(icon5_xpm
)); 
 540     m_imageList
->Add(wxIcon(icon6_xpm
)); 
 541     m_imageList
->Add(wxIcon(icon7_xpm
)); 
 542     m_imageList
->Add(wxIcon(icon8_xpm
)); 
 543     m_treeCtrl
->AssignImageList(m_imageList
); 
 545     m_showHidden 
= FALSE
; 
 546     wxDirItemData
* rootData 
= new wxDirItemData(wxT(""), wxT(""), TRUE
); 
 550 #if defined(__WINDOWS__) || defined(__WXPM__) || defined(__DOS__) 
 551     rootName 
= _("Computer"); 
 553     rootName 
= _("Sections"); 
 556     m_rootId 
= m_treeCtrl
->AddRoot( rootName
, 3, -1, rootData
); 
 557     m_treeCtrl
->SetItemHasChildren(m_rootId
); 
 558     m_treeCtrl
->Expand(m_rootId
); // automatically expand first level 
 560     // Expand and select the default path 
 561     if (!m_defaultPath
.IsEmpty()) 
 562         ExpandPath(m_defaultPath
); 
 569 wxGenericDirCtrl::~wxGenericDirCtrl() 
 573 void wxGenericDirCtrl::Init() 
 575     m_showHidden 
= FALSE
; 
 578     m_currentFilterStr 
= wxEmptyString
; // Default: any file 
 580     m_filterListCtrl 
= NULL
; 
 583 void wxGenericDirCtrl::ShowHidden( bool show 
) 
 587     wxString path 
= GetPath(); 
 588     m_treeCtrl
->Collapse(m_treeCtrl
->GetRootItem()); 
 589     m_treeCtrl
->Expand(m_treeCtrl
->GetRootItem()); 
 593 void wxGenericDirCtrl::AddSection(const wxString
& path
, const wxString
& name
, int imageId
) 
 595     wxDirItemData 
*dir_item 
= new wxDirItemData(path
,name
,TRUE
); 
 597     wxTreeItemId id 
= m_treeCtrl
->AppendItem( m_rootId
, name
, imageId
, -1, dir_item
); 
 599     m_treeCtrl
->SetItemHasChildren(id
); 
 602 void wxGenericDirCtrl::SetupSections() 
 604 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__WXPM__) 
 607     wxChar driveBuffer
[256]; 
 608     size_t n 
= (size_t) GetLogicalDriveStrings(255, driveBuffer
); 
 613         path
.Printf(wxT("%c:\\"), driveBuffer
[i
]); 
 614         name
.Printf(wxT("(%c:)"), driveBuffer
[i
]); 
 617         int driveType 
= ::GetDriveType(path
); 
 620             case DRIVE_REMOVABLE
: 
 621                 if (path 
== wxT("a:\\") || path 
== wxT("b:\\")) 
 622                     imageId 
= 6; // Floppy 
 640         AddSection(path
, name
, imageId
); 
 642         while (driveBuffer
[i
] != wxT('\0')) 
 645         if (driveBuffer
[i
] == wxT('\0')) 
 651     /* If we can switch to the drive, it exists. */ 
 652     for( drive 
= 1; drive 
<= 26; drive
++ ) 
 655         path
.Printf(wxT("%c:\\"), (char) (drive 
+ 'a' - 1)); 
 656         name
.Printf(wxT("(%c:)"), (char) (drive 
+ 'A' - 1)); 
 658         if (wxIsDriveAvailable(path
)) 
 660             AddSection(path
, name
, (drive 
<= 2) ? 6/*floppy*/ : 4/*disk*/); 
 663 #endif // __WIN32__/!__WIN32__ 
 665 #elif defined(__WXMAC__) 
 669       short actualCount 
= 0 ; 
 670       if ( OnLine( &volume 
, 1 , &actualCount 
, &index 
) != noErr 
|| actualCount 
== 0 ) 
 673       wxString name 
= wxMacFSSpec2MacFilename( &volume 
) ; 
 674       AddSection(name 
+ wxFILE_SEP_PATH
, name
, 0); 
 676 #elif defined(__UNIX__) 
 677     AddSection(wxT("/"), wxT("/"), 3/*computer icon*/); 
 679     #error "Unsupported platform in wxGenericDirCtrl!" 
 683 void wxGenericDirCtrl::OnBeginEditItem(wxTreeEvent 
&event
) 
 685     // don't rename the main entry "Sections" 
 686     if (event
.GetItem() == m_rootId
) 
 692     // don't rename the individual sections 
 693     if (m_treeCtrl
->GetParent( event
.GetItem() ) == m_rootId
) 
 700 void wxGenericDirCtrl::OnEndEditItem(wxTreeEvent 
&event
) 
 702     if ((event
.GetLabel().IsEmpty()) || 
 703         (event
.GetLabel() == _(".")) || 
 704         (event
.GetLabel() == _("..")) || 
 705         (event
.GetLabel().First( wxT("/") ) != wxNOT_FOUND
)) 
 707         wxMessageDialog 
dialog(this, _("Illegal directory name."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 713     wxTreeItemId id 
= event
.GetItem(); 
 714     wxDirItemData 
*data 
= (wxDirItemData
*)m_treeCtrl
->GetItemData( id 
); 
 717     wxString 
new_name( wxPathOnly( data
->m_path 
) ); 
 718     new_name 
+= wxString(wxFILE_SEP_PATH
); 
 719     new_name 
+= event
.GetLabel(); 
 723     if (wxFileExists(new_name
)) 
 725         wxMessageDialog 
dialog(this, _("File name exists already."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 730     if (wxRenameFile(data
->m_path
,new_name
)) 
 732         data
->SetNewDirName( new_name 
); 
 736         wxMessageDialog 
dialog(this, _("Operation not permitted."), _("Error"), wxOK 
| wxICON_ERROR 
); 
 742 void wxGenericDirCtrl::OnExpandItem(wxTreeEvent 
&event
) 
 744     wxTreeItemId parentId 
= event
.GetItem(); 
 746     // VS: this is needed because the event handler is called from wxTreeCtrl 
 747     //     ctor when wxTR_HIDE_ROOT was specified 
 749         m_rootId 
= m_treeCtrl
->GetRootItem(); 
 754 void wxGenericDirCtrl::OnCollapseItem(wxTreeEvent 
&event 
) 
 756     wxTreeItemId child
, parent 
= event
.GetItem(); 
 758     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(event
.GetItem()); 
 759     if (!data
->m_isExpanded
) 
 762     data
->m_isExpanded 
= FALSE
; 
 764     /* Workaround because DeleteChildren has disapeared (why?) and 
 765      * CollapseAndReset doesn't work as advertised (deletes parent too) */ 
 766     child 
= m_treeCtrl
->GetFirstChild(parent
, cookie
); 
 769         m_treeCtrl
->Delete(child
); 
 770         /* Not GetNextChild below, because the cookie mechanism can't 
 771          * handle disappearing children! */ 
 772         child 
= m_treeCtrl
->GetFirstChild(parent
, cookie
); 
 776 void wxGenericDirCtrl::ExpandDir(wxTreeItemId parentId
) 
 778     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(parentId
); 
 780     if (data
->m_isExpanded
) 
 783     data
->m_isExpanded 
= TRUE
; 
 785     if (parentId 
== m_treeCtrl
->GetRootItem()) 
 793     wxString search
,path
,filename
; 
 795     wxString 
dirName(data
->m_path
); 
 797 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__WXPM__) 
 798     // Check if this is a root directory and if so, 
 799     // whether the drive is avaiable. 
 800     if (!wxIsDriveAvailable(dirName
)) 
 802         data
->m_isExpanded 
= FALSE
; 
 803         //wxMessageBox(wxT("Sorry, this drive is not available.")); 
 808     // This may take a longish time. Go to busy cursor 
 811 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__WXPM__) 
 812     if (dirName
.Last() == ':') 
 813         dirName 
+= wxString(wxFILE_SEP_PATH
); 
 817     wxArrayString filenames
; 
 820     wxString eachFilename
; 
 827         int style 
= wxDIR_DIRS
; 
 828         if (m_showHidden
) style 
|= wxDIR_HIDDEN
; 
 829         if (d
.GetFirst(& eachFilename
, wxEmptyString
, style
)) 
 833                 if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
 835                     dirs
.Add(eachFilename
); 
 838             while (d
.GetNext(& eachFilename
)); 
 841     dirs
.Sort((wxArrayString::CompareFunction
) wxDirCtrlStringCompareFunction
); 
 843     // Now do the filenames -- but only if we're allowed to 
 844     if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY
) == 0) 
 852             if (d
.GetFirst(& eachFilename
, m_currentFilterStr
, wxDIR_FILES
)) 
 856                     if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
 858                         filenames
.Add(eachFilename
); 
 861                 while (d
.GetNext(& eachFilename
)); 
 864         filenames
.Sort((wxArrayString::CompareFunction
) wxDirCtrlStringCompareFunction
); 
 867     // Add the sorted dirs 
 869     for (i 
= 0; i 
< dirs
.Count(); i
++) 
 871         wxString 
eachFilename(dirs
[i
]); 
 873         if (path
.Last() != wxFILE_SEP_PATH
) 
 874             path 
+= wxString(wxFILE_SEP_PATH
); 
 875         path 
+= eachFilename
; 
 877         wxDirItemData 
*dir_item 
= new wxDirItemData(path
,eachFilename
,TRUE
); 
 878         wxTreeItemId id 
= m_treeCtrl
->AppendItem( parentId
, eachFilename
, 0, -1, dir_item
); 
 879         m_treeCtrl
->SetItemImage( id
, 1, wxTreeItemIcon_Expanded 
); 
 881         // Has this got any children? If so, make it expandable. 
 882         // (There are two situations when a dir has children: either it 
 883         // has subdirectories or it contains files that weren't filtered 
 884         // out. The latter only applies to dirctrl with files.) 
 885         if ( dir_item
->HasSubDirs() || 
 886              (((GetWindowStyle() & wxDIRCTRL_DIR_ONLY
) == 0) && 
 887                dir_item
->HasFiles(m_currentFilterStr
)) ) 
 889             m_treeCtrl
->SetItemHasChildren(id
); 
 893     // Add the sorted filenames 
 894     if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY
) == 0) 
 896         for (i 
= 0; i 
< filenames
.Count(); i
++) 
 898             wxString 
eachFilename(filenames
[i
]); 
 900             if (path
.Last() != wxFILE_SEP_PATH
) 
 901                 path 
+= wxString(wxFILE_SEP_PATH
); 
 902             path 
+= eachFilename
; 
 903             //path = dirName + wxString(wxT("/")) + eachFilename; 
 904             wxDirItemData 
*dir_item 
= new wxDirItemData(path
,eachFilename
,FALSE
); 
 905             (void)m_treeCtrl
->AppendItem( parentId
, eachFilename
, 2, -1, dir_item
); 
 910 // Find the child that matches the first part of 'path'. 
 911 // E.g. if a child path is "/usr" and 'path' is "/usr/include" 
 912 // then the child for /usr is returned. 
 913 wxTreeItemId 
wxGenericDirCtrl::FindChild(wxTreeItemId parentId
, const wxString
& path
, bool& done
) 
 915     wxString 
path2(path
); 
 917     // Make sure all separators are as per the current platform 
 918     path2
.Replace(wxT("\\"), wxString(wxFILE_SEP_PATH
)); 
 919     path2
.Replace(wxT("/"), wxString(wxFILE_SEP_PATH
)); 
 921     // Append a separator to foil bogus substring matching 
 922     path2 
+= wxString(wxFILE_SEP_PATH
); 
 924     // In MSW or PM, case is not significant 
 925 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__WXPM__) 
 930     wxTreeItemId childId 
= m_treeCtrl
->GetFirstChild(parentId
, cookie
); 
 931     while (childId
.IsOk()) 
 933         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(childId
); 
 935         if (data 
&& !data
->m_path
.IsEmpty()) 
 937             wxString 
childPath(data
->m_path
); 
 938             if (childPath
.Last() != wxFILE_SEP_PATH
) 
 939                 childPath 
+= wxString(wxFILE_SEP_PATH
); 
 941             // In MSW and PM, case is not significant 
 942 #if defined(__WINDOWS__) || defined(__DOS__) || defined(__WXPM__) 
 943             childPath
.MakeLower(); 
 946             if (childPath
.Len() <= path2
.Len()) 
 948                 wxString path3 
= path2
.Mid(0, childPath
.Len()); 
 949                 if (childPath 
== path3
) 
 951                     if (path3
.Len() == path2
.Len()) 
 960         childId 
= m_treeCtrl
->GetNextChild(parentId
, cookie
); 
 962     wxTreeItemId invalid
; 
 966 // Try to expand as much of the given path as possible, 
 967 // and select the given tree item. 
 968 bool wxGenericDirCtrl::ExpandPath(const wxString
& path
) 
 971     wxTreeItemId id 
= FindChild(m_rootId
, path
, done
); 
 972     wxTreeItemId lastId 
= id
; // The last non-zero id 
 973     while (id
.IsOk() && !done
) 
 977         id 
= FindChild(id
, path
, done
); 
 983         wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(lastId
); 
 986             m_treeCtrl
->Expand(lastId
); 
 988         if ((GetWindowStyle() & wxDIRCTRL_SELECT_FIRST
) && data
->m_isDir
) 
 990             // Find the first file in this directory 
 992             wxTreeItemId childId 
= m_treeCtrl
->GetFirstChild(lastId
, cookie
); 
 993             bool selectedChild 
= FALSE
; 
 994             while (childId
.IsOk()) 
 996                 wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(childId
); 
 998                 if (data 
&& data
->m_path 
!= "" && !data
->m_isDir
) 
1000                     m_treeCtrl
->SelectItem(childId
); 
1001                     m_treeCtrl
->EnsureVisible(childId
); 
1002                     selectedChild 
= TRUE
; 
1005                 childId 
= m_treeCtrl
->GetNextChild(lastId
, cookie
); 
1009                 m_treeCtrl
->SelectItem(lastId
); 
1010                 m_treeCtrl
->EnsureVisible(lastId
); 
1015             m_treeCtrl
->SelectItem(lastId
); 
1016             m_treeCtrl
->EnsureVisible(lastId
); 
1025 wxString 
wxGenericDirCtrl::GetPath() const 
1027     wxTreeItemId id 
= m_treeCtrl
->GetSelection(); 
1030         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1031         return data
->m_path
; 
1034         return wxEmptyString
; 
1037 wxString 
wxGenericDirCtrl::GetFilePath() const 
1039     wxTreeItemId id 
= m_treeCtrl
->GetSelection(); 
1042         wxDirItemData
* data 
= (wxDirItemData
*) m_treeCtrl
->GetItemData(id
); 
1044             return wxEmptyString
; 
1046             return data
->m_path
; 
1049         return wxEmptyString
; 
1052 void wxGenericDirCtrl::SetPath(const wxString
& path
) 
1054     m_defaultPath 
= path
; 
1061 void wxGenericDirCtrl::FindChildFiles(wxTreeItemId id
, int dirFlags
, wxArrayString
& filenames
) 
1063     wxDirItemData 
*data 
= (wxDirItemData 
*) m_treeCtrl
->GetItemData(id
); 
1065     // This may take a longish time. Go to busy cursor 
1070     wxString search
,path
,filename
; 
1072     wxString 
dirName(data
->m_path
); 
1074 #if defined(__WXMSW__) || defined(__WXPM__) 
1075     if (dirName
.Last() == ':') 
1076         dirName 
+= wxString(wxFILE_SEP_PATH
); 
1080     wxString eachFilename
; 
1087         if (d
.GetFirst(& eachFilename
, m_currentFilterStr
, dirFlags
)) 
1091                 if ((eachFilename 
!= wxT(".")) && (eachFilename 
!= wxT(".."))) 
1093                     filenames
.Add(eachFilename
); 
1096             while (d
.GetNext(& eachFilename
)) ; 
1102 void wxGenericDirCtrl::SetFilterIndex(int n
) 
1104     m_currentFilter 
= n
; 
1107     if (ExtractWildcard(m_filter
, n
, f
, d
)) 
1108         m_currentFilterStr 
= f
; 
1110         m_currentFilterStr 
= wxT("*.*"); 
1113 void wxGenericDirCtrl::SetFilter(const wxString
& filter
) 
1118     if (ExtractWildcard(m_filter
, m_currentFilter
, f
, d
)) 
1119         m_currentFilterStr 
= f
; 
1121         m_currentFilterStr 
= wxT("*.*"); 
1124 // Extract description and actual filter from overall filter string 
1125 bool wxGenericDirCtrl::ExtractWildcard(const wxString
& filterStr
, int n
, wxString
& filter
, wxString
& description
) 
1127     wxArrayString filters
, descriptions
; 
1128     int count 
= ParseFilter(filterStr
, filters
, descriptions
); 
1129     if (count 
> 0 && n 
< count
) 
1131         filter 
= filters
[n
]; 
1132         description 
= descriptions
[n
]; 
1139 // Parses the global filter, returning the number of filters. 
1140 // Returns 0 if none or if there's a problem. 
1141 // filterStr is in the form: 
1143 // "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpg" 
1145 int wxGenericDirCtrl::ParseFilter(const wxString
& filterStr
, wxArrayString
& filters
, wxArrayString
& descriptions
) 
1147     wxString 
str(filterStr
); 
1149     wxString description
, filter
; 
1151     bool finished 
= FALSE
; 
1154         pos 
= str
.Find(wxT('|')); 
1156             return 0; // Problem 
1157         description 
= str
.Left(pos
); 
1158         str 
= str
.Mid(pos
+1); 
1159         pos 
= str
.Find(wxT('|')); 
1167             filter 
= str
.Left(pos
); 
1168             str 
= str
.Mid(pos
+1); 
1170         descriptions
.Add(description
); 
1171         filters
.Add(filter
); 
1175     return filters
.Count(); 
1178 void wxGenericDirCtrl::DoResize() 
1180     wxSize sz 
= GetClientSize(); 
1181     int verticalSpacing 
= 3; 
1185         if (m_filterListCtrl
) 
1187             filterSz 
= m_filterListCtrl
->GetSize(); 
1188             sz
.y 
-= (filterSz
.y 
+ verticalSpacing
); 
1190         m_treeCtrl
->SetSize(0, 0, sz
.x
, sz
.y
); 
1191         if (m_filterListCtrl
) 
1193             m_filterListCtrl
->SetSize(0, sz
.y 
+ verticalSpacing
, sz
.x
, filterSz
.y
); 
1194             // Don't know why, but this needs refreshing after a resize (wxMSW) 
1195             m_filterListCtrl
->Refresh(); 
1201 void wxGenericDirCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
1206 //----------------------------------------------------------------------------- 
1207 // wxDirFilterListCtrl 
1208 //----------------------------------------------------------------------------- 
1210 IMPLEMENT_CLASS(wxDirFilterListCtrl
, wxChoice
) 
1212 BEGIN_EVENT_TABLE(wxDirFilterListCtrl
, wxChoice
) 
1213     EVT_CHOICE(-1, wxDirFilterListCtrl::OnSelFilter
) 
1216 bool wxDirFilterListCtrl::Create(wxGenericDirCtrl
* parent
, const wxWindowID id
, 
1222     return wxChoice::Create(parent
, id
, pos
, size
, 0, NULL
, style
); 
1225 void wxDirFilterListCtrl::Init() 
1230 void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent
& WXUNUSED(event
)) 
1232     int sel 
= GetSelection(); 
1234     wxString currentPath 
= m_dirCtrl
->GetPath(); 
1236     m_dirCtrl
->SetFilterIndex(sel
); 
1238     // If the filter has changed, the view is out of date, so 
1239     // collapse the tree. 
1240     m_dirCtrl
->GetTreeCtrl()->Collapse(m_dirCtrl
->GetRootId()); 
1241     m_dirCtrl
->GetTreeCtrl()->Expand(m_dirCtrl
->GetRootId()); 
1243     // Try to restore the selection, or at least the directory 
1244     m_dirCtrl
->ExpandPath(currentPath
); 
1247 void wxDirFilterListCtrl::FillFilterList(const wxString
& filter
, int defaultFilter
) 
1250     wxArrayString descriptions
, filters
; 
1251     size_t n 
= (size_t) m_dirCtrl
->ParseFilter(filter
, filters
, descriptions
); 
1253     if (n 
> 0 && defaultFilter 
< (int) n
) 
1256         for (i 
= 0; i 
< n
; i
++) 
1257             Append(descriptions
[i
]); 
1258         SetSelection(defaultFilter
); 
1262 #endif // wxUSE_DIRDLG