home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / generic / filedlgg.cpp < prev    next >
C/C++ Source or Header  |  2002-12-17  |  49KB  |  1,676 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        filedlgg.cpp
  3. // Purpose:     wxFileDialog
  4. // Author:      Robert Roebling
  5. // Modified by:
  6. // Created:     12/12/98
  7. // RCS-ID:      $Id: filedlgg.cpp,v 1.72.2.9 2002/12/17 22:31:37 JS Exp $
  8. // Copyright:   (c) Robert Roebling
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21. #pragma implementation "filedlgg.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28. #pragma hdrstop
  29. #endif
  30.  
  31. #if wxUSE_FILEDLG
  32.  
  33. #if !defined(__UNIX__) && !defined(__DOS__) && !defined(__WIN32__)
  34. #error wxFileDialog currently only supports Unix, win32 and DOS
  35. #endif
  36.  
  37. #include "wx/checkbox.h"
  38. #include "wx/textctrl.h"
  39. #include "wx/choice.h"
  40. #include "wx/checkbox.h"
  41. #include "wx/stattext.h"
  42. #include "wx/filedlg.h"
  43. #include "wx/debug.h"
  44. #include "wx/log.h"
  45. #include "wx/intl.h"
  46. #include "wx/listctrl.h"
  47. #include "wx/msgdlg.h"
  48. #include "wx/sizer.h"
  49. #include "wx/bmpbuttn.h"
  50. #include "wx/tokenzr.h"
  51. #include "wx/mimetype.h"
  52. #include "wx/image.h"
  53. #include "wx/module.h"
  54. #include "wx/config.h"
  55. #include "wx/imaglist.h"
  56. #include "wx/dir.h"
  57. #include "wx/artprov.h"
  58.  
  59. #if wxUSE_TOOLTIPS
  60.     #include "wx/tooltip.h"
  61. #endif
  62.  
  63. #include <sys/types.h>
  64. #include <sys/stat.h>
  65.  
  66. #ifdef __UNIX__
  67.     #include <dirent.h>
  68.     #include <pwd.h>
  69.     #ifndef __VMS
  70.     # include <grp.h>
  71.     #endif
  72. #endif
  73.  
  74. #ifdef __WATCOMC__
  75.     #include <direct.h>
  76. #endif
  77.  
  78. #include <time.h>
  79. #if defined(__UNIX__) || defined(__DOS__)
  80. #include <unistd.h>
  81. #endif
  82.  
  83. // ----------------------------------------------------------------------------
  84. // constants
  85. // ----------------------------------------------------------------------------
  86.  
  87. // the list ctrl fields in report view
  88. enum FileListField
  89. {
  90.     FileList_Name,
  91.     FileList_Type,
  92.     FileList_Date,
  93.     FileList_Time,
  94. #ifdef __UNIX__
  95.     FileList_Perm,
  96. #endif // __UNIX__
  97.     FileList_Max
  98. };
  99.  
  100. //-----------------------------------------------------------------------------
  101. //  wxFileData
  102. //-----------------------------------------------------------------------------
  103.  
  104. class wxFileData
  105. {
  106. public:
  107.     wxFileData( const wxString &name, const wxString &fname );
  108.     wxString GetName() const;
  109.     wxString GetFullName() const;
  110.     wxString GetHint() const;
  111.     wxString GetEntry( FileListField num ) const;
  112.  
  113.     bool IsDir() const { return m_isDir; }
  114.     bool IsLink() const { return m_isLink; }
  115.     bool IsExe() const { return m_isExe; }
  116.     long GetSize() const { return m_size; }
  117.  
  118.     void MakeItem( wxListItem &item );
  119.     void SetNewName( const wxString &name, const wxString &fname );
  120.  
  121. private:
  122.     wxString m_name;
  123.     wxString m_fileName;
  124.     long     m_size;
  125.     int      m_hour;
  126.     int      m_minute;
  127.     int      m_year;
  128.     int      m_month;
  129.     int      m_day;
  130.     wxString m_permissions;
  131.     bool     m_isDir;
  132.     bool     m_isLink;
  133.     bool     m_isExe;
  134. };
  135.  
  136. //-----------------------------------------------------------------------------
  137. //  wxFileCtrl
  138. //-----------------------------------------------------------------------------
  139.  
  140. class wxFileCtrl : public wxListCtrl
  141. {
  142. public:
  143.     wxFileCtrl();
  144.     wxFileCtrl( wxWindow *win,
  145.                 wxStaticText *labelDir,
  146.                 wxWindowID id,
  147.                 const wxString &wild,
  148.                 bool showHidden,
  149.                 const wxPoint &pos = wxDefaultPosition,
  150.                 const wxSize &size = wxDefaultSize,
  151.                 long style = wxLC_LIST,
  152.                 const wxValidator &validator = wxDefaultValidator,
  153.                 const wxString &name = wxT("filelist") );
  154.     virtual ~wxFileCtrl();
  155.  
  156.     void ChangeToListMode();
  157.     void ChangeToReportMode();
  158.     void ChangeToIconMode();
  159.     void ShowHidden( bool show = TRUE );
  160.     long Add( wxFileData *fd, wxListItem &item );
  161.     void UpdateFiles();
  162.     virtual void StatusbarText( wxChar *WXUNUSED(text) ) {};
  163.     void MakeDir();
  164.     void GoToParentDir();
  165.     void GoToHomeDir();
  166.     void GoToDir( const wxString &dir );
  167.     void SetWild( const wxString &wild );
  168.     void GetDir( wxString &dir );
  169.     void OnListDeleteItem( wxListEvent &event );
  170.     void OnListEndLabelEdit( wxListEvent &event );
  171.  
  172.     // Associate commonly used UI controls with wxFileCtrl so that they can be
  173.     // disabled when they cannot be used (e.g. can't go to parent directory
  174.     // if wxFileCtrl already is in the root dir):
  175.     void SetGoToParentControl(wxWindow *ctrl) { m_goToParentControl = ctrl; }
  176.     void SetNewDirControl(wxWindow *ctrl) { m_newDirControl = ctrl; }
  177.  
  178. private:
  179.     void FreeItemData(const wxListItem& item);
  180.     void FreeAllItemsData();
  181.  
  182.     wxString      m_dirName;
  183.     bool          m_showHidden;
  184.     wxString      m_wild;
  185.  
  186.     wxWindow     *m_goToParentControl;
  187.     wxWindow     *m_newDirControl;
  188.  
  189.     // the label showing the current directory
  190.     wxStaticText *m_labelDir;
  191.  
  192.     DECLARE_DYNAMIC_CLASS(wxFileCtrl);
  193.     DECLARE_EVENT_TABLE()
  194. };
  195.  
  196. // ----------------------------------------------------------------------------
  197. // private classes - icons list management
  198. // ----------------------------------------------------------------------------
  199.  
  200. class wxFileIconEntry : public wxObject
  201. {
  202. public:
  203.     wxFileIconEntry(int i) { id = i; }
  204.  
  205.     int id;
  206. };
  207.  
  208.  
  209. class wxFileIconsTable
  210. {
  211. public:
  212.     wxFileIconsTable();
  213.  
  214.     int GetIconID(const wxString& extension, const wxString& mime = wxEmptyString);
  215.     wxImageList *GetImageList() { return &m_ImageList; }
  216.  
  217. protected:
  218.     wxImageList m_ImageList;
  219.     wxHashTable m_HashTable;
  220. };
  221.  
  222. static wxFileIconsTable *g_IconsTable = NULL;
  223.  
  224. #define FI_FOLDER     0
  225. #define FI_UNKNOWN    1
  226. #define FI_EXECUTABLE 2
  227.  
  228. wxFileIconsTable::wxFileIconsTable() :
  229.                     m_ImageList(16, 16),
  230.                     m_HashTable(wxKEY_STRING)
  231. {
  232.     m_HashTable.DeleteContents(TRUE);
  233.     // FI_FOLDER:
  234.     m_ImageList.Add(wxArtProvider::GetBitmap(wxART_FOLDER, wxART_CMN_DIALOG));
  235.     // FI_UNKNOWN:
  236.     m_ImageList.Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_CMN_DIALOG));
  237.     // FI_EXECUTABLE:
  238.     if (GetIconID(wxEmptyString, _T("application/x-executable")) == FI_UNKNOWN)
  239.     {
  240.         m_ImageList.Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE, wxART_CMN_DIALOG));
  241.         m_HashTable.Delete(_T("exe"));
  242.         m_HashTable.Put(_T("exe"), new wxFileIconEntry(FI_EXECUTABLE));
  243.     }
  244.     /* else put into list by GetIconID
  245.        (KDE defines application/x-executable for *.exe and has nice icon)
  246.      */
  247. }
  248.  
  249.  
  250.  
  251. #if wxUSE_MIMETYPE
  252. // VS: we don't need this function w/o wxMimeTypesManager because we'll only have
  253. //     one icon and we won't resize it
  254.  
  255. static wxBitmap CreateAntialiasedBitmap(const wxImage& img)
  256. {
  257.     wxImage smallimg (16, 16);
  258.     unsigned char *p1, *p2, *ps;
  259.     unsigned char mr = img.GetMaskRed(),
  260.                   mg = img.GetMaskGreen(),
  261.                   mb = img.GetMaskBlue();
  262.  
  263.     unsigned x, y;
  264.     unsigned sr, sg, sb, smask;
  265.  
  266.     p1 = img.GetData(), p2 = img.GetData() + 3 * 32, ps = smallimg.GetData();
  267.     smallimg.SetMaskColour(mr, mr, mr);
  268.  
  269.     for (y = 0; y < 16; y++)
  270.     {
  271.         for (x = 0; x < 16; x++)
  272.         {
  273.             sr = sg = sb = smask = 0;
  274.             if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
  275.                 sr += p1[0], sg += p1[1], sb += p1[2];
  276.             else smask++;
  277.             p1 += 3;
  278.             if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
  279.                 sr += p1[0], sg += p1[1], sb += p1[2];
  280.             else smask++;
  281.             p1 += 3;
  282.             if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
  283.                 sr += p2[0], sg += p2[1], sb += p2[2];
  284.             else smask++;
  285.             p2 += 3;
  286.             if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
  287.                 sr += p2[0], sg += p2[1], sb += p2[2];
  288.             else smask++;
  289.             p2 += 3;
  290.  
  291.             if (smask > 2)
  292.                 ps[0] = ps[1] = ps[2] = mr;
  293.             else
  294.                 ps[0] = sr >> 2, ps[1] = sg >> 2, ps[2] = sb >> 2;
  295.             ps += 3;
  296.         }
  297.         p1 += 32 * 3, p2 += 32 * 3;
  298.     }
  299.  
  300.     return wxBitmap(smallimg);
  301. }
  302.  
  303. // finds empty borders and return non-empty area of image:
  304. static wxImage CutEmptyBorders(const wxImage& img)
  305. {
  306.     unsigned char mr = img.GetMaskRed(),
  307.                   mg = img.GetMaskGreen(),
  308.                   mb = img.GetMaskBlue();
  309.     unsigned char *dt = img.GetData(), *dttmp;
  310.     unsigned w = img.GetWidth(), h = img.GetHeight();
  311.  
  312.     unsigned top, bottom, left, right, i;
  313.     bool empt;
  314.  
  315. #define MK_DTTMP(x,y)      dttmp = dt + ((x + y * w) * 3)
  316. #define NOEMPTY_PIX(empt)  if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = FALSE; break;}
  317.  
  318.     for (empt = TRUE, top = 0; empt && top < h; top++)
  319.     {
  320.         MK_DTTMP(0, top);
  321.         for (i = 0; i < w; i++, dttmp+=3)
  322.             NOEMPTY_PIX(empt)
  323.     }
  324.     for (empt = TRUE, bottom = h-1; empt && bottom > top; bottom--)
  325.     {
  326.         MK_DTTMP(0, bottom);
  327.         for (i = 0; i < w; i++, dttmp+=3)
  328.             NOEMPTY_PIX(empt)
  329.     }
  330.     for (empt = TRUE, left = 0; empt && left < w; left++)
  331.     {
  332.         MK_DTTMP(left, 0);
  333.         for (i = 0; i < h; i++, dttmp+=3*w)
  334.             NOEMPTY_PIX(empt)
  335.     }
  336.     for (empt = TRUE, right = w-1; empt && right > left; right--)
  337.     {
  338.         MK_DTTMP(right, 0);
  339.         for (i = 0; i < h; i++, dttmp+=3*w)
  340.             NOEMPTY_PIX(empt)
  341.     }
  342.     top--, left--, bottom++, right++;
  343.  
  344.     return img.GetSubImage(wxRect(left, top, right - left + 1, bottom - top + 1));
  345. }
  346. #endif // wxUSE_MIMETYPE
  347.  
  348.  
  349.  
  350. int wxFileIconsTable::GetIconID(const wxString& extension, const wxString& mime)
  351. {
  352. #if wxUSE_MIMETYPE
  353.     if (!extension.IsEmpty())
  354.     {
  355.         wxFileIconEntry *entry = (wxFileIconEntry*) m_HashTable.Get(extension);
  356.         if (entry) return (entry -> id);
  357.     }
  358.  
  359.     wxFileType *ft = (mime.IsEmpty()) ?
  360.                    wxTheMimeTypesManager -> GetFileTypeFromExtension(extension) :
  361.                    wxTheMimeTypesManager -> GetFileTypeFromMimeType(mime);
  362.     wxIcon ic;
  363.     if (ft == NULL || (!ft -> GetIcon(&ic)) || (!ic.Ok()))
  364.     {
  365.         int newid = FI_UNKNOWN;
  366.         m_HashTable.Put(extension, new wxFileIconEntry(newid));
  367.         return newid;
  368.     }
  369. #ifdef __WIN32__
  370.     wxBitmap myBitmap (ic.GetWidth(), ic.GetHeight() ) ;
  371.     wxMemoryDC memDC;
  372.     memDC.SelectObject( myBitmap );
  373.     memDC.DrawIcon(ic,0,0);
  374.     memDC.SelectObject( wxNullBitmap );
  375.     wxImage img = myBitmap.ConvertToImage();
  376. #else
  377.     wxImage img = ic.ConvertToImage();
  378. #endif
  379.     delete ft;
  380.  
  381.     int id = m_ImageList.GetImageCount();
  382.     if (img.GetWidth() == 16 && img.GetHeight() == 16)
  383.         m_ImageList.Add(wxBitmap(img));
  384.     else
  385.     {
  386.         if (img.GetWidth() != 32 || img.GetHeight() != 32)
  387.             m_ImageList.Add(CreateAntialiasedBitmap(CutEmptyBorders(img).Rescale(32, 32)));
  388.         else
  389.             m_ImageList.Add(CreateAntialiasedBitmap(img));
  390.     }
  391.     m_HashTable.Put(extension, new wxFileIconEntry(id));
  392.     return id;
  393.  
  394. #else // !wxUSE_MIMETYPE
  395.  
  396.     if (extension == wxT("exe"))
  397.         return FI_EXECUTABLE;
  398.     else
  399.         return FI_UNKNOWN;
  400. #endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE
  401. }
  402.  
  403.  
  404.  
  405. // ----------------------------------------------------------------------------
  406. // private functions
  407. // ----------------------------------------------------------------------------
  408.  
  409. static
  410. int ListCompare( long data1, long data2, long WXUNUSED(data))
  411. {
  412.      wxFileData *fd1 = (wxFileData*)data1 ;
  413.      wxFileData *fd2 = (wxFileData*)data2 ;
  414.      if (fd1->GetName() == wxT("..")) return -1;
  415.      if (fd2->GetName() == wxT("..")) return 1;
  416.      if (fd1->IsDir() && !fd2->IsDir()) return -1;
  417.      if (fd2->IsDir() && !fd1->IsDir()) return 1;
  418.      return wxStrcmp( fd1->GetName(), fd2->GetName() );
  419. }
  420.  
  421. #ifdef __UNIX__
  422. #define IsTopMostDir(dir)   (dir == wxT("/"))
  423. #endif
  424.  
  425. #if defined(__DOS__) || defined(__WINDOWS__)
  426. #define IsTopMostDir(dir)   (dir.IsEmpty())
  427. #endif
  428.  
  429. #if defined(__DOS__) || defined(__WINDOWS__)
  430. extern bool wxIsDriveAvailable(const wxString& dirName);
  431. #endif
  432.  
  433. //-----------------------------------------------------------------------------
  434. //  wxFileData
  435. //-----------------------------------------------------------------------------
  436.  
  437. wxFileData::wxFileData( const wxString &name, const wxString &fname )
  438. {
  439.     m_name = name;
  440.     m_fileName = fname;
  441.  
  442. #if defined(__DOS__) || defined(__WINDOWS__)
  443.     // VS: In case the file is root directory of a volume (e.g. "C:"),
  444.     //     we don't want it stat()ed, since the drive may not be in:
  445.     if (name.length() == 2 && name[1u] == wxT(':'))
  446.     {
  447.         m_isDir = TRUE;
  448.         m_isExe = m_isLink = FALSE;
  449.         m_size = 0;
  450.         return;
  451.     }
  452. #endif
  453.  
  454.     wxStructStat buff;
  455.     wxStat( m_fileName, &buff );
  456.  
  457. #if defined(__UNIX__) && (!defined( __EMX__ ) && !defined(__VMS))
  458.     struct stat lbuff;
  459.     lstat( m_fileName.fn_str(), &lbuff );
  460.     m_isLink = S_ISLNK( lbuff.st_mode );
  461.     struct tm *t = localtime( &lbuff.st_mtime );
  462. #else
  463.     m_isLink = FALSE;
  464.     struct tm *t = localtime( &buff.st_mtime );
  465. #endif
  466.  
  467. //  struct passwd *user = getpwuid( buff.st_uid );
  468. //  struct group *grp = getgrgid( buff.st_gid );
  469.  
  470. #ifdef __VISUALC__
  471.     m_isDir = ((buff.st_mode & _S_IFDIR ) == _S_IFDIR );
  472. #else
  473.     m_isDir = S_ISDIR( buff.st_mode );
  474. #endif // VC++
  475.     m_isExe = ((buff.st_mode & wxS_IXUSR ) == wxS_IXUSR );
  476.  
  477.     m_size = buff.st_size;
  478.  
  479.     m_hour = t->tm_hour;
  480.     m_minute = t->tm_min;
  481.     m_month = t->tm_mon+1;
  482.     m_day = t->tm_mday;
  483.     m_year = t->tm_year;
  484.     m_year += 1900;
  485.  
  486.     char buffer[10];
  487.     sprintf( buffer, "%c%c%c",
  488.      ((( buff.st_mode & wxS_IRUSR ) == wxS_IRUSR ) ? 'r' : '-'),
  489.      ((( buff.st_mode & wxS_IWUSR ) == wxS_IWUSR ) ? 'w' : '-'),
  490.      ((( buff.st_mode & wxS_IXUSR ) == wxS_IXUSR ) ? 'x' : '-') );
  491. #if wxUSE_UNICODE
  492.     m_permissions = wxConvUTF8.cMB2WC( buffer );
  493. #else
  494.     m_permissions = buffer;
  495. #endif
  496.  
  497. //    m_permissions.sprintf( wxT("%c%c%c"),
  498. //     ((( buff.st_mode & S_IRUSR ) == S_IRUSR ) ? wxT('r') : wxT('-')),
  499. //     ((( buff.st_mode & S_IWUSR ) == S_IWUSR ) ? wxT('w') : wxT('-')),
  500. //     ((( buff.st_mode & S_IXUSR ) == S_IXUSR ) ? wxT('x') : wxT('-')) );
  501. }
  502.  
  503. wxString wxFileData::GetName() const
  504. {
  505.     return m_name;
  506. }
  507.  
  508. wxString wxFileData::GetFullName() const
  509. {
  510.     return m_fileName;
  511. }
  512.  
  513. wxString wxFileData::GetHint() const
  514. {
  515.     wxString s = m_fileName;
  516.     s += wxT("  ");
  517.     if (m_isDir) s += wxT("<DIR> ");
  518.     else if (m_isLink) s += wxT("<LINK> ");
  519.     else
  520.     {
  521.         s += LongToString( m_size );
  522.         s += wxT(" bytes ");
  523.     }
  524.     s += IntToString( m_day );
  525.     s += wxT(".");
  526.     s += IntToString( m_month );
  527.     s += wxT(".");
  528.     s += IntToString( m_year );
  529.     s += wxT("  ");
  530.     s += IntToString( m_hour );
  531.     s += wxT(":");
  532.     s += IntToString( m_minute );
  533.     s += wxT("  ");
  534.     s += m_permissions;
  535.     return s;
  536. };
  537.  
  538. wxString wxFileData::GetEntry( FileListField num ) const
  539. {
  540.     wxString s;
  541.     switch ( num )
  542.     {
  543.         case FileList_Name:
  544.             s = m_name;
  545.             break;
  546.  
  547.         case FileList_Type:
  548.             if (m_isDir)
  549.                 s = _("<DIR>");
  550.             else if (m_isLink)
  551.                 s = _("<LINK>");
  552.             else
  553.                 s.Printf(_T("%ld"), m_size);
  554.             break;
  555.  
  556.         case FileList_Date:
  557.             s.Printf(_T("%02d.%02d.%d"), m_day, m_month, m_year);
  558.             break;
  559.  
  560.         case FileList_Time:
  561.             s.Printf(_T("%02d:%02d"), m_hour, m_minute);
  562.             break;
  563.  
  564. #ifdef __UNIX__
  565.         case FileList_Perm:
  566.             s = m_permissions;
  567.             break;
  568. #endif // __UNIX__
  569.  
  570.         default:
  571.             wxFAIL_MSG( _T("unexpected field in wxFileData::GetEntry()") );
  572.     }
  573.  
  574.     return s;
  575. }
  576.  
  577. void wxFileData::SetNewName( const wxString &name, const wxString &fname )
  578. {
  579.     m_name = name;
  580.     m_fileName = fname;
  581. }
  582.  
  583. void wxFileData::MakeItem( wxListItem &item )
  584. {
  585.     item.m_text = m_name;
  586.     item.ClearAttributes();
  587.     if (IsExe())
  588.         item.SetTextColour(*wxRED);
  589.     if (IsDir())
  590.         item.SetTextColour(*wxBLUE);
  591.  
  592.     if (IsDir())
  593.         item.m_image = FI_FOLDER;
  594.     else if (IsExe())
  595.         item.m_image = FI_EXECUTABLE;
  596.     else if (m_name.Find(wxT('.')) != wxNOT_FOUND)
  597.         item.m_image = g_IconsTable->GetIconID(m_name.AfterLast(wxT('.')));
  598.     else
  599.         item.m_image = FI_UNKNOWN;
  600.  
  601.     if (IsLink())
  602.     {
  603.         wxColour *dg = wxTheColourDatabase->FindColour( _T("MEDIUM GREY") );
  604.         item.SetTextColour(*dg);
  605.     }
  606.     item.m_data = (long)this;
  607. }
  608.  
  609. //-----------------------------------------------------------------------------
  610. //  wxFileCtrl
  611. //-----------------------------------------------------------------------------
  612.  
  613. IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl,wxListCtrl)
  614.  
  615. BEGIN_EVENT_TABLE(wxFileCtrl,wxListCtrl)
  616.     EVT_LIST_DELETE_ITEM(-1, wxFileCtrl::OnListDeleteItem)
  617.     EVT_LIST_END_LABEL_EDIT(-1, wxFileCtrl::OnListEndLabelEdit)
  618. END_EVENT_TABLE()
  619.  
  620.  
  621. wxFileCtrl::wxFileCtrl()
  622. {
  623.     m_showHidden = FALSE;
  624. }
  625.  
  626. wxFileCtrl::wxFileCtrl(wxWindow *win,
  627.                        wxStaticText *labelDir,
  628.                        wxWindowID id,
  629.                        const wxString& wild,
  630.                        bool showHidden,
  631.                        const wxPoint& pos,
  632.                        const wxSize& size,
  633.                        long style,
  634.                        const wxValidator &validator,
  635.                        const wxString &name)
  636.           : wxListCtrl(win, id, pos, size, style, validator, name),
  637.             m_wild(wild)
  638. {
  639.     if (! g_IconsTable)
  640.         g_IconsTable = new wxFileIconsTable;
  641.     wxImageList *imageList = g_IconsTable->GetImageList();
  642.  
  643.     SetImageList( imageList, wxIMAGE_LIST_SMALL );
  644.  
  645.     m_goToParentControl =
  646.     m_newDirControl = NULL;
  647.  
  648.     m_labelDir = labelDir;
  649.  
  650.     m_showHidden = showHidden;
  651. }
  652.  
  653. void wxFileCtrl::ChangeToListMode()
  654. {
  655.     SetSingleStyle( wxLC_LIST );
  656.     UpdateFiles();
  657. }
  658.  
  659. void wxFileCtrl::ChangeToReportMode()
  660. {
  661.     SetSingleStyle( wxLC_REPORT );
  662.     UpdateFiles();
  663. }
  664.  
  665. void wxFileCtrl::ChangeToIconMode()
  666. {
  667.     SetSingleStyle( wxLC_ICON );
  668.     UpdateFiles();
  669. }
  670.  
  671. void wxFileCtrl::ShowHidden( bool show )
  672. {
  673.     m_showHidden = show;
  674.     UpdateFiles();
  675. }
  676.  
  677. long wxFileCtrl::Add( wxFileData *fd, wxListItem &item )
  678. {
  679.     long ret = -1;
  680.     item.m_mask = wxLIST_MASK_TEXT + wxLIST_MASK_DATA + wxLIST_MASK_IMAGE;
  681.     fd->MakeItem( item );
  682.     long my_style = GetWindowStyleFlag();
  683.     if (my_style & wxLC_REPORT)
  684.     {
  685.         ret = InsertItem( item );
  686.         for (int i = 1; i < FileList_Max; i++)
  687.             SetItem( item.m_itemId, i, fd->GetEntry((FileListField)i) );
  688.     }
  689.     else if (my_style & wxLC_LIST)
  690.     {
  691.         ret = InsertItem( item );
  692.     }
  693.     return ret;
  694. }
  695.  
  696. void wxFileCtrl::UpdateFiles()
  697. {
  698.     // don't do anything before ShowModal() call which sets m_dirName
  699.     if ( m_dirName.empty() )
  700.         return;
  701.  
  702.     wxBusyCursor bcur; // this may take a while...
  703.  
  704.     long my_style = GetWindowStyleFlag();
  705.     int name_col_width = 0;
  706.     if (my_style & wxLC_REPORT)
  707.     {
  708.         if (GetColumnCount() > 0)
  709.             name_col_width = GetColumnWidth( 0 );
  710.     }
  711.  
  712.     FreeAllItemsData();
  713.     ClearAll();
  714.  
  715.     if (my_style & wxLC_REPORT)
  716.     {
  717.         if (name_col_width < 140) name_col_width = 140;
  718.         InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT, name_col_width );
  719.         InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT, 60 );
  720.         InsertColumn( 2, _("Date"), wxLIST_FORMAT_LEFT, 65 );
  721.         InsertColumn( 3, _("Time"), wxLIST_FORMAT_LEFT, 50 );
  722. #ifdef __UNIX__
  723.         InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT, 120 );
  724. #endif
  725.     }
  726.     wxFileData *fd = (wxFileData *) NULL;
  727.     wxListItem item;
  728.     item.m_itemId = 0;
  729.     item.m_col = 0;
  730.  
  731. #if defined(__DOS__) || defined(__WINDOWS__)
  732.     if ( IsTopMostDir(m_dirName) )
  733.     {
  734.         // Pseudo-directory with all available drives listed...
  735.         for (int drive = 1; drive <= 26; drive++)
  736.         {
  737.             wxString path;
  738.             path.Printf(wxT("%c:\\"), (char)(drive + 'A' - 1));
  739.             if ( wxIsDriveAvailable(path) )
  740.             {
  741.                 path.RemoveLast();
  742.                 fd = new wxFileData(path, path);
  743.                 Add(fd, item);
  744.                 item.m_itemId++;
  745.             }
  746.         }
  747.     }
  748.     else
  749. #endif
  750.     {
  751.         // Real directory...
  752.         if ( !IsTopMostDir(m_dirName) )
  753.         {
  754.             wxString p(wxPathOnly(m_dirName));
  755. #ifdef __UNIX__
  756.             if (p.IsEmpty()) p = wxT("/");
  757. #endif
  758.             fd = new wxFileData( wxT(".."), p );
  759.             Add(fd, item);
  760.             item.m_itemId++;
  761.         }
  762.  
  763.         wxString dirname(m_dirName);
  764. #if defined(__DOS__) || defined(__WINDOWS__)
  765.         if (dirname.length() == 2 && dirname[1u] == wxT(':'))
  766.             dirname << wxT('\\');
  767. #endif
  768.         wxDir dir(dirname);
  769.  
  770.         if ( dir.IsOpened() )
  771.         {
  772.             wxString dirPrefix(dirname + wxFILE_SEP_PATH);
  773.             int hiddenFlag = m_showHidden ? wxDIR_HIDDEN : 0;
  774.  
  775.             bool cont;
  776.             wxString f;
  777.  
  778.             // Get the directories first (not matched against wildcards):
  779.             cont = dir.GetFirst(&f, wxEmptyString, wxDIR_DIRS | hiddenFlag);
  780.             while (cont)
  781.             {
  782.                 fd = new wxFileData(f, dirPrefix + f);
  783.                 Add(fd, item);
  784.                 item.m_itemId++;
  785.                 cont = dir.GetNext(&f);
  786.             }
  787.  
  788.             // Tokenize the wildcard string, so we can handle more than 1
  789.             // search pattern in a wildcard.
  790.             wxStringTokenizer tokenWild(m_wild, wxT(";"));
  791.             while ( tokenWild.HasMoreTokens() )
  792.             {
  793.                 cont = dir.GetFirst(&f, tokenWild.GetNextToken(),
  794.                                         wxDIR_FILES | hiddenFlag);
  795.                 while (cont)
  796.                 {
  797.                     fd = new wxFileData(f, dirPrefix + f);
  798.                     Add(fd, item);
  799.                     item.m_itemId++;
  800.                     cont = dir.GetNext(&f);
  801.                 }
  802.             }
  803.         }
  804.     }
  805.  
  806.     SortItems((wxListCtrlCompare)ListCompare, 0);
  807.  
  808.     if ( my_style & wxLC_REPORT )
  809.     {
  810.        SetColumnWidth(1, wxLIST_AUTOSIZE);
  811.        SetColumnWidth(2, wxLIST_AUTOSIZE);
  812.        SetColumnWidth(3, wxLIST_AUTOSIZE);
  813.     }
  814.  
  815.     // Finally, enable/disable context-dependent controls:
  816.     if ( m_goToParentControl )
  817.         m_goToParentControl->Enable(!IsTopMostDir(m_dirName));
  818. #if defined(__DOS__) || defined(__WINDOWS__)
  819.     if ( m_newDirControl )
  820.         m_newDirControl->Enable(!IsTopMostDir(m_dirName));
  821. #endif
  822. }
  823.  
  824. void wxFileCtrl::SetWild( const wxString &wild )
  825. {
  826.     m_wild = wild;
  827.     UpdateFiles();
  828. }
  829.  
  830. void wxFileCtrl::MakeDir()
  831. {
  832.     wxString new_name( _("NewName") );
  833.     wxString path( m_dirName );
  834.     path += wxFILE_SEP_PATH;
  835.     path += new_name;
  836.     if (wxFileExists(path))
  837.     {
  838.         // try NewName0, NewName1 etc.
  839.         int i = 0;
  840.         do {
  841.             new_name = _("NewName");
  842.             wxString num;
  843.             num.Printf( wxT("%d"), i );
  844.             new_name += num;
  845.  
  846.             path = m_dirName;
  847.             path += wxFILE_SEP_PATH;
  848.             path += new_name;
  849.             i++;
  850.         } while (wxFileExists(path));
  851.     }
  852.  
  853.     wxLogNull log;
  854.     if (!wxMkdir(path))
  855.     {
  856.         wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
  857.         dialog.ShowModal();
  858.         return;
  859.     }
  860.  
  861.     wxFileData *fd = new wxFileData( new_name, path );
  862.     wxListItem item;
  863.     item.m_itemId = 0;
  864.     item.m_col = 0;
  865.     long id = Add( fd, item );
  866.  
  867.     if (id != -1)
  868.     {
  869.         SortItems( (wxListCtrlCompare) ListCompare, 0 );
  870.         id = FindItem( 0, (long)fd );
  871.         EnsureVisible( id );
  872.         EditLabel( id );
  873.     }
  874. }
  875.  
  876. void wxFileCtrl::GoToParentDir()
  877. {
  878.     if (!IsTopMostDir(m_dirName))
  879.     {
  880.         size_t len = m_dirName.Len();
  881.         if (m_dirName[len-1] == wxFILE_SEP_PATH)
  882.             m_dirName.Remove( len-1, 1 );
  883.         wxString fname( wxFileNameFromPath(m_dirName) );
  884.         m_dirName = wxPathOnly( m_dirName );
  885. #ifdef __UNIX__
  886.         if (m_dirName.IsEmpty())
  887.             m_dirName = wxT("/");
  888. #endif
  889.         UpdateFiles();
  890.         long id = FindItem( 0, fname );
  891.         if (id != -1)
  892.         {
  893.             SetItemState( id, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
  894.             EnsureVisible( id );
  895.         }
  896.  
  897.         m_labelDir->SetLabel(m_dirName);
  898.     }
  899. }
  900.  
  901. void wxFileCtrl::GoToHomeDir()
  902. {
  903.     wxString s = wxGetUserHome( wxString() );
  904.     GoToDir(s);
  905. }
  906.  
  907. void wxFileCtrl::GoToDir( const wxString &dir )
  908. {
  909.     m_dirName = dir;
  910.     UpdateFiles();
  911.     SetItemState( 0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
  912.     EnsureVisible( 0 );
  913.  
  914.     m_labelDir->SetLabel(dir);
  915. }
  916.  
  917. void wxFileCtrl::GetDir( wxString &dir )
  918. {
  919.     dir = m_dirName;
  920. }
  921.  
  922. void wxFileCtrl::FreeItemData(const wxListItem& item)
  923. {
  924.     wxFileData *fd = (wxFileData*)item.m_data;
  925.     delete fd;
  926. }
  927.  
  928. void wxFileCtrl::OnListDeleteItem( wxListEvent &event )
  929. {
  930.     FreeItemData(event.m_item);
  931. }
  932.  
  933. void wxFileCtrl::FreeAllItemsData()
  934. {
  935.     wxListItem item;
  936.     item.m_mask = wxLIST_MASK_DATA;
  937.  
  938.     item.m_itemId = GetNextItem( -1, wxLIST_NEXT_ALL );
  939.     while ( item.m_itemId != -1 )
  940.     {
  941.         GetItem( item );
  942.         FreeItemData(item);
  943.         item.m_itemId = GetNextItem( item.m_itemId, wxLIST_NEXT_ALL );
  944.     }
  945. }
  946.  
  947. void wxFileCtrl::OnListEndLabelEdit( wxListEvent &event )
  948. {
  949.     wxFileData *fd = (wxFileData*)event.m_item.m_data;
  950.     wxASSERT( fd );
  951.  
  952.     if ((event.GetLabel().IsEmpty()) ||
  953.         (event.GetLabel() == _(".")) ||
  954.         (event.GetLabel() == _("..")) ||
  955.         (event.GetLabel().First( wxFILE_SEP_PATH ) != wxNOT_FOUND))
  956.     {
  957.         wxMessageDialog dialog(this, _("Illegal directory name."), _("Error"), wxOK | wxICON_ERROR );
  958.         dialog.ShowModal();
  959.         event.Veto();
  960.         return;
  961.     }
  962.  
  963.     wxString new_name( wxPathOnly( fd->GetFullName() ) );
  964.     new_name += wxFILE_SEP_PATH;
  965.     new_name += event.GetLabel();
  966.  
  967.     wxLogNull log;
  968.  
  969.     if (wxFileExists(new_name))
  970.     {
  971.         wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR );
  972.         dialog.ShowModal();
  973.         event.Veto();
  974.     }
  975.  
  976.     if (wxRenameFile(fd->GetFullName(),new_name))
  977.     {
  978.         fd->SetNewName( new_name, event.GetLabel() );
  979.         SetItemState( event.GetItem(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
  980.         EnsureVisible( event.GetItem() );
  981.     }
  982.     else
  983.     {
  984.         wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
  985.         dialog.ShowModal();
  986.         event.Veto();
  987.     }
  988. }
  989.  
  990. wxFileCtrl::~wxFileCtrl()
  991. {
  992.     FreeAllItemsData();
  993. }
  994.  
  995. //-----------------------------------------------------------------------------
  996. // wxFileDialog
  997. //-----------------------------------------------------------------------------
  998.  
  999. #define  ID_LIST_MODE     (wxID_FILEDLGG    )
  1000. #define  ID_REPORT_MODE   (wxID_FILEDLGG + 1)
  1001. #define  ID_UP_DIR        (wxID_FILEDLGG + 5)
  1002. #define  ID_PARENT_DIR    (wxID_FILEDLGG + 6)
  1003. #define  ID_NEW_DIR       (wxID_FILEDLGG + 7)
  1004. #define  ID_CHOICE        (wxID_FILEDLGG + 8)
  1005. #define  ID_TEXT          (wxID_FILEDLGG + 9)
  1006. #define  ID_LIST_CTRL     (wxID_FILEDLGG + 10)
  1007. #define  ID_ACTIVATED     (wxID_FILEDLGG + 11)
  1008. #define  ID_CHECK         (wxID_FILEDLGG + 12)
  1009.  
  1010. IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxDialog)
  1011.  
  1012. BEGIN_EVENT_TABLE(wxFileDialog,wxDialog)
  1013.         EVT_BUTTON(ID_LIST_MODE, wxFileDialog::OnList)
  1014.         EVT_BUTTON(ID_REPORT_MODE, wxFileDialog::OnReport)
  1015.         EVT_BUTTON(ID_UP_DIR, wxFileDialog::OnUp)
  1016.         EVT_BUTTON(ID_PARENT_DIR, wxFileDialog::OnHome)
  1017.         EVT_BUTTON(ID_NEW_DIR, wxFileDialog::OnNew)
  1018.         EVT_BUTTON(wxID_OK, wxFileDialog::OnListOk)
  1019.         EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL, wxFileDialog::OnSelected)
  1020.         EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL, wxFileDialog::OnActivated)
  1021.         EVT_CHOICE(ID_CHOICE,wxFileDialog::OnChoiceFilter)
  1022.         EVT_TEXT_ENTER(ID_TEXT,wxFileDialog::OnTextEnter)
  1023.         EVT_TEXT(ID_TEXT,wxFileDialog::OnTextChange)
  1024.         EVT_CHECKBOX(ID_CHECK,wxFileDialog::OnCheck)
  1025. END_EVENT_TABLE()
  1026.  
  1027. long wxFileDialog::ms_lastViewStyle = wxLC_LIST;
  1028. bool wxFileDialog::ms_lastShowHidden = FALSE;
  1029.  
  1030. wxFileDialog::wxFileDialog(wxWindow *parent,
  1031.                            const wxString& message,
  1032.                            const wxString& defaultDir,
  1033.                            const wxString& defaultFile,
  1034.                            const wxString& wildCard,
  1035.                            long style,
  1036.                            const wxPoint& pos )
  1037.             : wxDialog( parent, -1, message, pos, wxDefaultSize,
  1038.                         wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
  1039. {
  1040.     if (wxConfig::Get(FALSE))
  1041.     {
  1042.         wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"),
  1043.                               &ms_lastViewStyle);
  1044.         wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"),
  1045.                               &ms_lastShowHidden);
  1046.     }
  1047.  
  1048.     m_message = message;
  1049.     m_dialogStyle = style;
  1050.  
  1051.     if (m_dialogStyle == 0)
  1052.         m_dialogStyle = wxOPEN;
  1053.     if ((m_dialogStyle & wxMULTIPLE ) && !(m_dialogStyle & wxOPEN))
  1054.         m_dialogStyle |= wxOPEN;
  1055.  
  1056.     m_dir = defaultDir;
  1057.     if ((m_dir.empty()) || (m_dir == wxT(".")))
  1058.     {
  1059.         m_dir = wxGetCwd();
  1060.     }
  1061.  
  1062.     size_t len = m_dir.Len();
  1063.     if ((len > 1) && (m_dir[len-1] == wxFILE_SEP_PATH))
  1064.         m_dir.Remove( len-1, 1 );
  1065.  
  1066.     m_path = m_dir;
  1067.     m_path += wxFILE_SEP_PATH;
  1068.     m_path += defaultFile;
  1069.     m_fileName = defaultFile;
  1070.     m_wildCard = wildCard;
  1071.     m_filterIndex = 0;
  1072.     m_filterExtension = wxEmptyString;
  1073.  
  1074.     // interpret wildcards
  1075.  
  1076.     if (m_wildCard.IsEmpty())
  1077.         m_wildCard = _("All files (*)|*");
  1078.  
  1079.     wxStringTokenizer tokens( m_wildCard, wxT("|") );
  1080.     wxString firstWild;
  1081.     wxString firstWildText;
  1082.     if (tokens.CountTokens() == 1)
  1083.     {
  1084.         firstWildText = tokens.GetNextToken();
  1085.         firstWild = firstWildText;
  1086.     }
  1087.     else
  1088.     {
  1089.         wxASSERT_MSG( tokens.CountTokens() % 2 == 0, wxT("Wrong file type descripition") );
  1090.         firstWildText = tokens.GetNextToken();
  1091.         firstWild = tokens.GetNextToken();
  1092.     }
  1093.     if ( firstWild.Left( 2 ) == wxT("*.") )
  1094.         m_filterExtension = firstWild.Mid( 1 );
  1095.     if ( m_filterExtension == wxT(".*") )
  1096.         m_filterExtension = wxEmptyString;
  1097.  
  1098.     // layout
  1099.     
  1100.     bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
  1101.  
  1102.     wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );
  1103.  
  1104.     wxBoxSizer *buttonsizer = new wxBoxSizer( wxHORIZONTAL );
  1105.  
  1106.     wxBitmapButton *but;
  1107.  
  1108.     but = new wxBitmapButton(this, ID_LIST_MODE,
  1109.                              wxArtProvider::GetBitmap(wxART_LIST_VIEW, wxART_CMN_DIALOG));
  1110. #if wxUSE_TOOLTIPS
  1111.     but->SetToolTip( _("View files as a list view") );
  1112. #endif
  1113.     buttonsizer->Add( but, 0, wxALL, 5 );
  1114.  
  1115.     but = new wxBitmapButton(this, ID_REPORT_MODE,
  1116.                              wxArtProvider::GetBitmap(wxART_REPORT_VIEW, wxART_CMN_DIALOG));
  1117. #if wxUSE_TOOLTIPS
  1118.     but->SetToolTip( _("View files as a detailed view") );
  1119. #endif
  1120.     buttonsizer->Add( but, 0, wxALL, 5 );
  1121.  
  1122.     buttonsizer->Add( 30, 5, 1 );
  1123.  
  1124.     wxWindow *butDirUp =
  1125.         new wxBitmapButton(this, ID_UP_DIR,
  1126.                            wxArtProvider::GetBitmap(wxART_GO_DIR_UP, wxART_CMN_DIALOG));
  1127. #if wxUSE_TOOLTIPS
  1128.     butDirUp->SetToolTip( _("Go to parent directory") );
  1129. #endif
  1130.     buttonsizer->Add( butDirUp, 0, wxALL, 5 );
  1131.  
  1132. #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS...
  1133.     but = new wxBitmapButton(this, ID_PARENT_DIR,
  1134.                              wxArtProvider::GetBitmap(wxART_GO_HOME, wxART_CMN_DIALOG));
  1135. #if wxUSE_TOOLTIPS
  1136.     but->SetToolTip( _("Go to home directory") );
  1137. #endif
  1138.     buttonsizer->Add( but, 0, wxALL, 5);
  1139.  
  1140.     buttonsizer->Add( 20, 20 );
  1141. #endif //!__DOS__
  1142.  
  1143.     wxWindow *butNewDir =
  1144.         new wxBitmapButton(this, ID_NEW_DIR,
  1145.                            wxArtProvider::GetBitmap(wxART_NEW_DIR, wxART_CMN_DIALOG));
  1146. #if wxUSE_TOOLTIPS
  1147.     butNewDir->SetToolTip( _("Create new directory") );
  1148. #endif
  1149.     buttonsizer->Add( butNewDir, 0, wxALL, 5 );
  1150.  
  1151.     if (is_pda)
  1152.         mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 0 );
  1153.     else
  1154.         mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 5 );
  1155.  
  1156.     wxBoxSizer *staticsizer = new wxBoxSizer( wxHORIZONTAL );
  1157.     if (is_pda)
  1158.         staticsizer->Add( new wxStaticText( this, -1, _("Current directory:") ), 0, wxRIGHT, 10 );
  1159.     m_static = new wxStaticText( this, -1, m_dir );
  1160.     staticsizer->Add( m_static, 1 );
  1161.     mainsizer->Add( staticsizer, 0, wxEXPAND | wxLEFT|wxRIGHT|wxBOTTOM, 10 );
  1162.  
  1163.     long style2 = ms_lastViewStyle | wxSUNKEN_BORDER;
  1164.     if ( !(m_dialogStyle & wxMULTIPLE) )
  1165.         style2 |= wxLC_SINGLE_SEL;
  1166.  
  1167.     m_list = new wxFileCtrl( this, m_static, ID_LIST_CTRL,
  1168.                              firstWild, ms_lastShowHidden,
  1169.                              wxDefaultPosition, wxSize(540,200),
  1170.                              style2);
  1171.  
  1172.     m_list->SetNewDirControl(butNewDir);
  1173.     m_list->SetGoToParentControl(butDirUp);
  1174.  
  1175.     if (is_pda)
  1176.     {
  1177.         // PDAs have a different screen layout
  1178.         mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 5 );
  1179.  
  1180.         wxBoxSizer *choicesizer = new wxBoxSizer( wxHORIZONTAL );
  1181.         m_choice = new wxChoice( this, ID_CHOICE );
  1182.         choicesizer->Add( m_choice, 1, wxCENTER|wxALL, 5 );
  1183.         mainsizer->Add( choicesizer, 0, wxEXPAND );
  1184.  
  1185.         wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL );
  1186.         m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxPROCESS_ENTER );
  1187.         textsizer->Add( m_text, 1, wxCENTER | wxALL, 5 );
  1188.         mainsizer->Add( textsizer, 0, wxEXPAND );
  1189.  
  1190.         m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden files") );
  1191.         m_check->SetValue( ms_lastShowHidden );
  1192.         textsizer->Add( m_check, 0, wxCENTER|wxALL, 5 );
  1193.  
  1194.         buttonsizer = new wxBoxSizer( wxHORIZONTAL );
  1195.         buttonsizer->Add( new wxButton( this, wxID_OK, _("OK") ), 0, wxCENTER | wxALL, 5 );
  1196.         buttonsizer->Add( new wxButton( this, wxID_CANCEL, _("Cancel") ), 0, wxCENTER | wxALL, 5 );
  1197.         mainsizer->Add( buttonsizer, 0, wxALIGN_RIGHT );
  1198.     }
  1199.     else
  1200.     {
  1201.         mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 10 );
  1202.  
  1203.         wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL );
  1204.         m_text = new wxTextCtrl( this, ID_TEXT, m_fileName, wxDefaultPosition, wxDefaultSize, wxPROCESS_ENTER );
  1205.         textsizer->Add( m_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 );
  1206.         textsizer->Add( new wxButton( this, wxID_OK, _("OK") ), 0, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 );
  1207.         mainsizer->Add( textsizer, 0, wxEXPAND );
  1208.  
  1209.         wxBoxSizer *choicesizer = new wxBoxSizer( wxHORIZONTAL );
  1210.         m_choice = new wxChoice( this, ID_CHOICE );
  1211.         choicesizer->Add( m_choice, 1, wxCENTER|wxALL, 10 );
  1212.         m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden files") );
  1213.         m_check->SetValue( ms_lastShowHidden );
  1214.         choicesizer->Add( m_check, 0, wxCENTER|wxALL, 10 );
  1215.         choicesizer->Add( new wxButton( this, wxID_CANCEL, _("Cancel") ), 0, wxCENTER | wxALL, 10 );
  1216.         mainsizer->Add( choicesizer, 0, wxEXPAND );
  1217.     }
  1218.  
  1219.     m_choice->Append( firstWildText, (void*) new wxString( firstWild ) );
  1220.     while (tokens.HasMoreTokens())
  1221.     {
  1222.         firstWildText = tokens.GetNextToken();
  1223.         firstWild = tokens.GetNextToken();
  1224.         m_choice->Append( firstWildText, (void*) new wxString( firstWild ) );
  1225.     }
  1226.     m_choice->SetSelection( 0 );
  1227.  
  1228.     SetAutoLayout( TRUE );
  1229.     SetSizer( mainsizer );
  1230.  
  1231.     mainsizer->Fit( this );
  1232.     mainsizer->SetSizeHints( this );
  1233.  
  1234.     Centre( wxBOTH );
  1235.  
  1236.     m_text->SetFocus();
  1237. }
  1238.  
  1239. wxFileDialog::~wxFileDialog()
  1240. {
  1241.     if (wxConfig::Get(FALSE))
  1242.     {
  1243.         wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"),
  1244.                                ms_lastViewStyle);
  1245.         wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"),
  1246.                                ms_lastShowHidden);
  1247.     }
  1248. }
  1249.  
  1250. int wxFileDialog::ShowModal()
  1251. {
  1252.     m_list->GoToDir(m_dir);
  1253.     m_text->SetValue(m_fileName);
  1254.  
  1255.     return wxDialog::ShowModal();
  1256. }
  1257.  
  1258. void wxFileDialog::DoSetFilterIndex(int filterindex)
  1259. {
  1260.     wxString *str = (wxString*) m_choice->GetClientData( filterindex );
  1261.     m_list->SetWild( *str );
  1262.     m_filterIndex = filterindex;
  1263.     if ( str->Left(2) == wxT("*.") )
  1264.     {
  1265.         m_filterExtension = str->Mid(2);
  1266.         if (m_filterExtension == _T("*"))
  1267.             m_filterExtension.clear();
  1268.     }
  1269.     else
  1270.     {
  1271.         m_filterExtension.clear();
  1272.     }
  1273. }
  1274.  
  1275. void wxFileDialog::SetFilterIndex( int filterindex )
  1276. {
  1277.     m_choice->SetSelection( filterindex );
  1278.  
  1279.     DoSetFilterIndex(filterindex);
  1280. }
  1281.  
  1282. void wxFileDialog::OnChoiceFilter( wxCommandEvent &event )
  1283. {
  1284.     DoSetFilterIndex((int)event.GetInt());
  1285. }
  1286.  
  1287. void wxFileDialog::OnCheck( wxCommandEvent &event )
  1288. {
  1289.     m_list->ShowHidden( (ms_lastShowHidden = event.GetInt() != 0) );
  1290. }
  1291.  
  1292. void wxFileDialog::OnActivated( wxListEvent &event )
  1293. {
  1294.     HandleAction( event.m_item.m_text );
  1295. }
  1296.  
  1297. void wxFileDialog::OnTextEnter( wxCommandEvent &WXUNUSED(event) )
  1298. {
  1299.     wxCommandEvent cevent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK);
  1300.     cevent.SetEventObject( this );
  1301.     GetEventHandler()->ProcessEvent( cevent );
  1302. }
  1303.  
  1304. static bool ignoreChanges = FALSE;
  1305.  
  1306. void wxFileDialog::OnTextChange( wxCommandEvent &WXUNUSED(event) )
  1307. {
  1308.     if (!ignoreChanges)
  1309.     {
  1310.         // Clear selections.  Otherwise when the user types in a value they may
  1311.         // not get the file whose name they typed.
  1312.         if (m_list->GetSelectedItemCount() > 0)
  1313.         {
  1314.             long item = m_list->GetNextItem(-1, wxLIST_NEXT_ALL,
  1315.                 wxLIST_STATE_SELECTED);
  1316.             while ( item != -1 )
  1317.             {
  1318.                 m_list->SetItemState(item,0, wxLIST_STATE_SELECTED);
  1319.                 item = m_list->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
  1320.             }
  1321.         }
  1322.     }
  1323. }
  1324.  
  1325. void wxFileDialog::OnSelected( wxListEvent &event )
  1326. {
  1327.     wxString filename( event.m_item.m_text );
  1328.     if (filename == wxT("..")) return;
  1329.  
  1330.     wxString dir;
  1331.     m_list->GetDir( dir );
  1332.     if (!IsTopMostDir(dir))
  1333.         dir += wxFILE_SEP_PATH;
  1334.     dir += filename;
  1335.     if (wxDirExists(dir)) return;
  1336.  
  1337.     ignoreChanges = TRUE;
  1338.     m_text->SetValue( filename );
  1339.     ignoreChanges = FALSE;
  1340. }
  1341.  
  1342. void wxFileDialog::HandleAction( const wxString &fn )
  1343. {
  1344.     wxString filename( fn );
  1345.     wxString dir;
  1346.     m_list->GetDir( dir );
  1347.     if (filename.IsEmpty()) return;
  1348.     if (filename == wxT(".")) return;
  1349.  
  1350.     if (filename == wxT(".."))
  1351.     {
  1352.         m_list->GoToParentDir();
  1353.         m_list->SetFocus();
  1354.         return;
  1355.     }
  1356.  
  1357. #ifdef __UNIX__
  1358.     if (filename == wxT("~"))
  1359.     {
  1360.         m_list->GoToHomeDir();
  1361.         m_list->SetFocus();
  1362.         return;
  1363.     }
  1364.  
  1365.     if (filename[0u] == wxT('~'))
  1366.     {
  1367.         filename.Remove( 0, 1 );
  1368.         wxString tmp( wxGetUserHome() );
  1369.         tmp += wxT('/');
  1370.         tmp += filename;
  1371.         filename = tmp;
  1372.     }
  1373. #endif // __UNIX__
  1374.  
  1375.     if ((filename.Find(wxT('*')) != wxNOT_FOUND) ||
  1376.         (filename.Find(wxT('?')) != wxNOT_FOUND))
  1377.     {
  1378.         if (filename.Find(wxFILE_SEP_PATH) != wxNOT_FOUND)
  1379.         {
  1380.             wxMessageBox(_("Illegal file specification."), _("Error"), wxOK | wxICON_ERROR );
  1381.             return;
  1382.         }
  1383.         m_list->SetWild( filename );
  1384.         return;
  1385.     }
  1386.  
  1387.     if (!IsTopMostDir(dir))
  1388.         dir += wxFILE_SEP_PATH;
  1389.     if (!wxIsAbsolutePath(filename))
  1390.     {
  1391.         dir += filename;
  1392.         filename = dir;
  1393.     }
  1394.  
  1395.     if (wxDirExists(filename))
  1396.     {
  1397.         m_list->GoToDir( filename );
  1398.         return;
  1399.     }
  1400.  
  1401.     // append the default extension to the filename if it doesn't have any
  1402.     //
  1403.     // VZ: the logic of testing for !wxFileExists() only for the open file
  1404.     //     dialog is not entirely clear to me, why don't we allow saving to a
  1405.     //     file without extension as well?
  1406.     if ( !(m_dialogStyle & wxOPEN) || !wxFileExists(filename) )
  1407.     {
  1408.         wxString ext;
  1409.         wxSplitPath(filename, NULL, NULL, &ext);
  1410.         if ( ext.empty() )
  1411.         {
  1412.             // append the first extension of the filter string
  1413.             filename += m_filterExtension.BeforeFirst(_T(';'));
  1414.         }
  1415.     }
  1416.  
  1417.     // check that the file [doesn't] exist if necessary
  1418.     if ( (m_dialogStyle & wxSAVE) &&
  1419.             (m_dialogStyle & wxOVERWRITE_PROMPT) &&
  1420.                 wxFileExists( filename ) )
  1421.     {
  1422.         wxString msg;
  1423.         msg.Printf( _("File '%s' already exists, do you really want to "
  1424.                      "overwrite it?"), filename.c_str() );
  1425.  
  1426.         if (wxMessageBox(msg, _("Confirm"), wxYES_NO) != wxYES)
  1427.             return;
  1428.     }
  1429.     else if ( (m_dialogStyle & wxOPEN) &&
  1430.                 (m_dialogStyle & wxFILE_MUST_EXIST) &&
  1431.                     !wxFileExists(filename) )
  1432.     {
  1433.         wxMessageBox(_("Please choose an existing file."), _("Error"),
  1434.                      wxOK | wxICON_ERROR );
  1435.     }
  1436.  
  1437.     SetPath( filename );
  1438.  
  1439.     // change to the directory where the user went if asked
  1440.     if ( m_dialogStyle & wxCHANGE_DIR )
  1441.     {
  1442.         wxString cwd;
  1443.         wxSplitPath(filename, &cwd, NULL, NULL);
  1444.  
  1445.         if ( cwd != wxGetWorkingDirectory() )
  1446.         {
  1447.             wxSetWorkingDirectory(cwd);
  1448.         }
  1449.     }
  1450.  
  1451.     wxCommandEvent event;
  1452.     wxDialog::OnOK(event);
  1453. }
  1454.  
  1455. void wxFileDialog::OnListOk( wxCommandEvent &WXUNUSED(event) )
  1456. {
  1457.     HandleAction( m_text->GetValue() );
  1458. }
  1459.  
  1460. void wxFileDialog::OnList( wxCommandEvent &WXUNUSED(event) )
  1461. {
  1462.     m_list->ChangeToListMode();
  1463.     ms_lastViewStyle = wxLC_LIST;
  1464.     m_list->SetFocus();
  1465. }
  1466.  
  1467. void wxFileDialog::OnReport( wxCommandEvent &WXUNUSED(event) )
  1468. {
  1469.     m_list->ChangeToReportMode();
  1470.     ms_lastViewStyle = wxLC_REPORT;
  1471.     m_list->SetFocus();
  1472. }
  1473.  
  1474. void wxFileDialog::OnUp( wxCommandEvent &WXUNUSED(event) )
  1475. {
  1476.     m_list->GoToParentDir();
  1477.     m_list->SetFocus();
  1478. }
  1479.  
  1480. void wxFileDialog::OnHome( wxCommandEvent &WXUNUSED(event) )
  1481. {
  1482.     m_list->GoToHomeDir();
  1483.     m_list->SetFocus();
  1484. }
  1485.  
  1486. void wxFileDialog::OnNew( wxCommandEvent &WXUNUSED(event) )
  1487. {
  1488.     m_list->MakeDir();
  1489. }
  1490.  
  1491. void wxFileDialog::SetPath( const wxString& path )
  1492. {
  1493.     // not only set the full path but also update filename and dir
  1494.     m_path = path;
  1495.     if ( !path.empty() )
  1496.     {
  1497.         wxString ext;
  1498.         wxSplitPath(path, &m_dir, &m_fileName, &ext);
  1499.         if (!ext.empty())
  1500.         {
  1501.             m_fileName += wxT(".");
  1502.             m_fileName += ext;
  1503.         }
  1504.     }
  1505. }
  1506.  
  1507. void wxFileDialog::GetPaths( wxArrayString& paths ) const
  1508. {
  1509.     paths.Empty();
  1510.     if (m_list->GetSelectedItemCount() == 0)
  1511.     {
  1512.         paths.Add( GetPath() );
  1513.         return;
  1514.     }
  1515.  
  1516.     paths.Alloc( m_list->GetSelectedItemCount() );
  1517.  
  1518.     wxString dir;
  1519.     m_list->GetDir( dir );
  1520. #ifdef __UNIX__
  1521.     if (dir != wxT("/"))
  1522. #endif
  1523.         dir += wxFILE_SEP_PATH;
  1524.  
  1525.     wxListItem item;
  1526.     item.m_mask = wxLIST_MASK_TEXT;
  1527.  
  1528.     item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1529.     while ( item.m_itemId != -1 )
  1530.     {
  1531.         m_list->GetItem( item );
  1532.         paths.Add( dir + item.m_text );
  1533.         item.m_itemId = m_list->GetNextItem( item.m_itemId,
  1534.             wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1535.     }
  1536. }
  1537.  
  1538. void wxFileDialog::GetFilenames(wxArrayString& files) const
  1539. {
  1540.     files.Empty();
  1541.     if (m_list->GetSelectedItemCount() == 0)
  1542.     {
  1543.         files.Add( GetFilename() );
  1544.         return;
  1545.     }
  1546.     files.Alloc( m_list->GetSelectedItemCount() );
  1547.  
  1548.     wxListItem item;
  1549.     item.m_mask = wxLIST_MASK_TEXT;
  1550.  
  1551.     item.m_itemId = m_list->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1552.     while ( item.m_itemId != -1 )
  1553.     {
  1554.         m_list->GetItem( item );
  1555.         files.Add( item.m_text );
  1556.         item.m_itemId = m_list->GetNextItem( item.m_itemId,
  1557.             wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
  1558.     }
  1559. }
  1560.  
  1561.  
  1562.  
  1563. // ----------------------------------------------------------------------------
  1564. // global functions
  1565. // ----------------------------------------------------------------------------
  1566.  
  1567. wxString
  1568. wxFileSelectorEx(const wxChar *message,
  1569.                  const wxChar *default_path,
  1570.                  const wxChar *default_filename,
  1571.                  int *WXUNUSED(indexDefaultExtension),
  1572.                  const wxChar *wildcard,
  1573.                  int flags,
  1574.                  wxWindow *parent,
  1575.                  int x, int y)
  1576. {
  1577.     // TODO: implement this somehow
  1578.     return wxFileSelector(message, default_path, default_filename, wxT(""),
  1579.                           wildcard, flags, parent, x, y);
  1580. }
  1581.  
  1582. wxString wxFileSelector( const wxChar *title,
  1583.                       const wxChar *defaultDir, const wxChar *defaultFileName,
  1584.                       const wxChar *defaultExtension, const wxChar *filter, int flags,
  1585.                       wxWindow *parent, int x, int y )
  1586. {
  1587.     wxString filter2;
  1588.     if ( defaultExtension && !filter )
  1589.         filter2 = wxString(wxT("*.")) + wxString(defaultExtension) ;
  1590.     else if ( filter )
  1591.         filter2 = filter;
  1592.  
  1593.     wxString defaultDirString;
  1594.     if (defaultDir)
  1595.         defaultDirString = defaultDir;
  1596.  
  1597.     wxString defaultFilenameString;
  1598.     if (defaultFileName)
  1599.         defaultFilenameString = defaultFileName;
  1600.  
  1601.     wxFileDialog fileDialog( parent, title, defaultDirString, defaultFilenameString, filter2, flags, wxPoint(x, y) );
  1602.  
  1603.     if ( fileDialog.ShowModal() == wxID_OK )
  1604.     {
  1605.         return fileDialog.GetPath();
  1606.     }
  1607.     else
  1608.     {
  1609.         return wxEmptyString;
  1610.     }
  1611. }
  1612.  
  1613. static wxString GetWildcardString(const wxChar *ext)
  1614. {
  1615.     wxString wild;
  1616.     if ( ext )
  1617.     {
  1618.         if ( *ext == wxT('.') )
  1619.             ext++;
  1620.  
  1621.         wild << _T("*.") << ext;
  1622.     }
  1623.     else // no extension specified
  1624.     {
  1625.         wild = wxFileSelectorDefaultWildcardStr;
  1626.     }
  1627.  
  1628.     return wild;
  1629. }
  1630.  
  1631. wxString wxLoadFileSelector(const wxChar *what,
  1632.                             const wxChar *ext,
  1633.                             const wxChar *nameDef,
  1634.                             wxWindow *parent)
  1635. {
  1636.     wxString prompt;
  1637.     if ( what && *what )
  1638.         prompt = wxString::Format(_("Load %s file"), what);
  1639.     else
  1640.         prompt = _("Load file");
  1641.  
  1642.     return wxFileSelector(prompt, NULL, nameDef, ext,
  1643.                           GetWildcardString(ext), 0, parent);
  1644. }
  1645.  
  1646. wxString wxSaveFileSelector(const wxChar *what,
  1647.                             const wxChar *ext,
  1648.                             const wxChar *nameDef,
  1649.                             wxWindow *parent)
  1650. {
  1651.     wxString prompt;
  1652.     if ( what && *what )
  1653.         prompt = wxString::Format(_("Save %s file"), what);
  1654.     else
  1655.         prompt = _("Save file");
  1656.  
  1657.     return wxFileSelector(prompt, NULL, nameDef, ext,
  1658.                           GetWildcardString(ext), 0, parent);
  1659. }
  1660.  
  1661. // A module to allow icons table cleanup
  1662.  
  1663. class wxFileDialogGenericModule: public wxModule
  1664. {
  1665. DECLARE_DYNAMIC_CLASS(wxFileDialogGenericModule)
  1666. public:
  1667.     wxFileDialogGenericModule() {}
  1668.     bool OnInit() { return TRUE; }
  1669.     void OnExit() { if (g_IconsTable) {delete g_IconsTable; g_IconsTable = NULL;} }
  1670. };
  1671.  
  1672. IMPLEMENT_DYNAMIC_CLASS(wxFileDialogGenericModule, wxModule)
  1673.  
  1674. #endif // wxUSE_FILEDLG
  1675.  
  1676.