1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxFileDialog
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "filedlgg.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
26 #error wxFileDialog currently only supports unix
29 #include "wx/checkbox.h"
30 #include "wx/textctrl.h"
31 #include "wx/choice.h"
32 #include "wx/checkbox.h"
33 #include "wx/stattext.h"
34 #include "wx/filedlg.h"
38 #include "wx/listctrl.h"
39 #include "wx/msgdlg.h"
41 #include "wx/bmpbuttn.h"
42 #include "wx/tokenzr.h"
43 #include "wx/mimetype.h"
45 #include "wx/module.h"
46 #include "wx/config.h"
47 #include "wx/imaglist.h"
50 #include "wx/tooltip.h"
53 #include <sys/types.h>
63 #include "wx/generic/home.xpm"
64 #include "wx/generic/listview.xpm"
65 #include "wx/generic/repview.xpm"
66 #include "wx/generic/new_dir.xpm"
67 #include "wx/generic/dir_up.xpm"
68 #include "wx/generic/folder.xpm"
69 #include "wx/generic/deffile.xpm"
70 #include "wx/generic/exefile.xpm"
72 //-----------------------------------------------------------------------------
74 //-----------------------------------------------------------------------------
76 class wxFileData
: public wxObject
87 wxString m_permissions
;
94 wxFileData( const wxString
&name
, const wxString
&fname
);
95 wxString
GetName() const;
96 wxString
GetFullName() const;
97 wxString
GetHint() const;
98 wxString
GetEntry( int num
);
103 void MakeItem( wxListItem
&item
);
104 void SetNewName( const wxString
&name
, const wxString
&fname
);
107 DECLARE_DYNAMIC_CLASS(wxFileData
);
110 //-----------------------------------------------------------------------------
112 //-----------------------------------------------------------------------------
114 class wxFileCtrl
: public wxListCtrl
123 wxFileCtrl( wxWindow
*win
,
125 const wxString
&dirName
,
126 const wxString
&wild
,
127 const wxPoint
&pos
= wxDefaultPosition
,
128 const wxSize
&size
= wxDefaultSize
,
129 long style
= wxLC_LIST
,
130 const wxValidator
&validator
= wxDefaultValidator
,
131 const wxString
&name
= wxT("filelist") );
132 void ChangeToListMode();
133 void ChangeToReportMode();
134 void ChangeToIconMode();
135 void ShowHidden( bool show
= TRUE
);
136 long Add( wxFileData
*fd
, wxListItem
&item
);
138 virtual void StatusbarText( wxChar
*WXUNUSED(text
) ) {};
140 void GoToParentDir();
142 void GoToDir( const wxString
&dir
);
143 void SetWild( const wxString
&wild
);
144 void GetDir( wxString
&dir
);
145 void OnListDeleteItem( wxListEvent
&event
);
146 void OnListDeleteAllItems( wxListEvent
&event
);
147 void OnListEndLabelEdit( wxListEvent
&event
);
150 DECLARE_DYNAMIC_CLASS(wxFileCtrl
);
151 DECLARE_EVENT_TABLE()
154 // ----------------------------------------------------------------------------
155 // private classes - icons list management
156 // ----------------------------------------------------------------------------
158 class wxFileIconEntry
: public wxObject
161 wxFileIconEntry(int i
) { id
= i
; }
167 class wxFileIconsTable
172 int GetIconID(const wxString
& extension
, const wxString
& mime
= wxEmptyString
);
173 wxImageList
*GetImageList() { return &m_ImageList
; }
176 wxImageList m_ImageList
;
177 wxHashTable m_HashTable
;
180 static wxFileIconsTable
*g_IconsTable
= NULL
;
184 #define FI_EXECUTABLE 2
186 wxFileIconsTable::wxFileIconsTable() :
188 m_HashTable(wxKEY_STRING
)
190 m_HashTable
.DeleteContents(TRUE
);
191 m_ImageList
.Add(wxBitmap(folder_xpm
)); // FI_FOLDER
192 m_ImageList
.Add(wxBitmap(deffile_xpm
)); // FI_UNKNOWN
193 if (GetIconID(wxEmptyString
, _T("application/x-executable")) == FI_UNKNOWN
)
195 m_ImageList
.Add(wxBitmap(exefile_xpm
));
196 m_HashTable
.Delete(_T("exe"));
197 m_HashTable
.Put(_T("exe"), new wxFileIconEntry(FI_EXECUTABLE
));
199 /* else put into list by GetIconID
200 (KDE defines application/x-executable for *.exe and has nice icon)
206 static wxBitmap
CreateAntialiasedBitmap(const wxImage
& img
)
208 wxImage
small(16, 16);
209 unsigned char *p1
, *p2
, *ps
;
210 unsigned char mr
= img
.GetMaskRed(),
211 mg
= img
.GetMaskGreen(),
212 mb
= img
.GetMaskBlue();
215 unsigned sr
, sg
, sb
, smask
;
217 p1
= img
.GetData(), p2
= img
.GetData() + 3 * 32, ps
= small
.GetData();
218 small
.SetMaskColour(mr
, mr
, mr
);
220 for (y
= 0; y
< 16; y
++)
222 for (x
= 0; x
< 16; x
++)
224 sr
= sg
= sb
= smask
= 0;
225 if (p1
[0] != mr
|| p1
[1] != mg
|| p1
[2] != mb
)
226 sr
+= p1
[0], sg
+= p1
[1], sb
+= p1
[2];
229 if (p1
[0] != mr
|| p1
[1] != mg
|| p1
[2] != mb
)
230 sr
+= p1
[0], sg
+= p1
[1], sb
+= p1
[2];
233 if (p2
[0] != mr
|| p2
[1] != mg
|| p2
[2] != mb
)
234 sr
+= p2
[0], sg
+= p2
[1], sb
+= p2
[2];
237 if (p2
[0] != mr
|| p2
[1] != mg
|| p2
[2] != mb
)
238 sr
+= p2
[0], sg
+= p2
[1], sb
+= p2
[2];
243 ps
[0] = ps
[1] = ps
[2] = mr
;
245 ps
[0] = sr
>> 2, ps
[1] = sg
>> 2, ps
[2] = sb
>> 2;
248 p1
+= 32 * 3, p2
+= 32 * 3;
251 return small
.ConvertToBitmap();
255 // finds empty borders and return non-empty area of image:
256 static wxImage
CutEmptyBorders(const wxImage
& img
)
258 unsigned char mr
= img
.GetMaskRed(),
259 mg
= img
.GetMaskGreen(),
260 mb
= img
.GetMaskBlue();
261 unsigned char *dt
= img
.GetData(), *dttmp
;
262 unsigned w
= img
.GetWidth(), h
= img
.GetHeight();
264 unsigned top
, bottom
, left
, right
, i
;
267 #define MK_DTTMP(x,y) dttmp = dt + ((x + y * w) * 3)
268 #define NOEMPTY_PIX(empt) if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = FALSE; break;}
270 for (empt
= TRUE
, top
= 0; empt
&& top
< h
; top
++)
273 for (i
= 0; i
< w
; i
++, dttmp
+=3)
276 for (empt
= TRUE
, bottom
= h
-1; empt
&& bottom
> top
; bottom
--)
279 for (i
= 0; i
< w
; i
++, dttmp
+=3)
282 for (empt
= TRUE
, left
= 0; empt
&& left
< w
; left
++)
285 for (i
= 0; i
< h
; i
++, dttmp
+=3*w
)
288 for (empt
= TRUE
, right
= w
-1; empt
&& right
> left
; right
--)
291 for (i
= 0; i
< h
; i
++, dttmp
+=3*w
)
294 top
--, left
--, bottom
++, right
++;
296 return img
.GetSubImage(wxRect(left
, top
, right
- left
+ 1, bottom
- top
+ 1));
301 int wxFileIconsTable::GetIconID(const wxString
& extension
, const wxString
& mime
)
303 if (!extension
.IsEmpty())
305 wxFileIconEntry
*entry
= (wxFileIconEntry
*) m_HashTable
.Get(extension
);
306 if (entry
) return (entry
-> id
);
309 wxFileType
*ft
= (mime
.IsEmpty()) ?
310 wxTheMimeTypesManager
-> GetFileTypeFromExtension(extension
) :
311 wxTheMimeTypesManager
-> GetFileTypeFromMimeType(mime
);
313 if (ft
== NULL
|| (!ft
-> GetIcon(&ic
)) || (!ic
.Ok()))
315 int newid
= FI_UNKNOWN
;
316 m_HashTable
.Put(extension
, new wxFileIconEntry(newid
));
322 int id
= m_ImageList
.GetImageCount();
323 if (img
.GetWidth() == 16 && img
.GetHeight() == 16)
324 m_ImageList
.Add(img
.ConvertToBitmap());
327 if (img
.GetWidth() != 32 || img
.GetHeight() != 32)
328 m_ImageList
.Add(CreateAntialiasedBitmap(CutEmptyBorders(img
).Rescale(32, 32)));
330 m_ImageList
.Add(CreateAntialiasedBitmap(img
));
332 m_HashTable
.Put(extension
, new wxFileIconEntry(id
));
338 // ----------------------------------------------------------------------------
340 // ----------------------------------------------------------------------------
343 int ListCompare( long data1
, long data2
, long WXUNUSED(data
) )
345 wxFileData
*fd1
= (wxFileData
*)data1
;
346 wxFileData
*fd2
= (wxFileData
*)data2
;
347 if (fd1
->GetName() == wxT("..")) return -1;
348 if (fd2
->GetName() == wxT("..")) return 1;
349 if (fd1
->IsDir() && !fd2
->IsDir()) return -1;
350 if (fd2
->IsDir() && !fd1
->IsDir()) return 1;
351 return wxStrcmp( fd1
->GetName(), fd2
->GetName() );
354 //-----------------------------------------------------------------------------
356 //-----------------------------------------------------------------------------
358 IMPLEMENT_DYNAMIC_CLASS(wxFileData
,wxObject
);
360 wxFileData::wxFileData( const wxString
&name
, const wxString
&fname
)
366 stat( m_fileName
.fn_str(), &buff
);
368 #if !defined( __EMX__ ) && !defined(__VMS)
370 lstat( m_fileName
.fn_str(), &lbuff
);
371 m_isLink
= S_ISLNK( lbuff
.st_mode
);
372 struct tm
*t
= localtime( &lbuff
.st_mtime
);
375 struct tm
*t
= localtime( &buff
.st_mtime
);
378 // struct passwd *user = getpwuid( buff.st_uid );
379 // struct group *grp = getgrgid( buff.st_gid );
381 m_isDir
= S_ISDIR( buff
.st_mode
);
382 m_isExe
= ((buff
.st_mode
& S_IXUSR
) == S_IXUSR
);
384 m_size
= buff
.st_size
;
387 m_minute
= t
->tm_min
;
388 m_month
= t
->tm_mon
+1;
393 m_permissions
.sprintf( wxT("%c%c%c"),
394 ((( buff
.st_mode
& S_IRUSR
) == S_IRUSR
) ? wxT('r') : wxT('-')),
395 ((( buff
.st_mode
& S_IWUSR
) == S_IWUSR
) ? wxT('w') : wxT('-')),
396 ((( buff
.st_mode
& S_IXUSR
) == S_IXUSR
) ? wxT('x') : wxT('-')) );
399 wxString
wxFileData::GetName() const
404 wxString
wxFileData::GetFullName() const
409 wxString
wxFileData::GetHint() const
411 wxString s
= m_fileName
;
413 if (m_isDir
) s
+= _("<DIR> ");
414 else if (m_isLink
) s
+= _("<LINK> ");
417 s
+= LongToString( m_size
);
420 s
+= IntToString( m_day
);
422 s
+= IntToString( m_month
);
424 s
+= IntToString( m_year
);
426 s
+= IntToString( m_hour
);
428 s
+= IntToString( m_minute
);
434 wxString
wxFileData::GetEntry( int num
)
446 if (m_isDir
) s
= _("<DIR>");
447 else if (m_isLink
) s
= _("<LINK>");
448 else s
= LongToString( m_size
);
453 if (m_day
< 10) s
= wxT("0"); else s
= wxT("");
454 s
+= IntToString( m_day
);
456 if (m_month
< 10) s
+= wxT("0");
457 s
+= IntToString( m_month
);
459 s
+= IntToString( m_year
);
464 if (m_hour
< 10) s
= wxT("0"); else s
= wxT("");
465 s
+= IntToString( m_hour
);
467 if (m_minute
< 10) s
+= wxT("0");
468 s
+= IntToString( m_minute
);
481 bool wxFileData::IsDir()
486 bool wxFileData::IsExe()
491 bool wxFileData::IsLink()
496 long wxFileData::GetSize()
501 void wxFileData::SetNewName( const wxString
&name
, const wxString
&fname
)
507 void wxFileData::MakeItem( wxListItem
&item
)
509 item
.m_text
= m_name
;
510 item
.ClearAttributes();
511 if (IsExe()) item
.SetTextColour(*wxRED
);
512 if (IsDir()) item
.SetTextColour(*wxBLUE
);
515 item
.m_image
= FI_FOLDER
;
517 item
.m_image
= FI_EXECUTABLE
;
518 else if (m_name
.Find(wxT('.')) != wxNOT_FOUND
)
519 item
.m_image
= g_IconsTable
-> GetIconID(m_name
.AfterLast(wxT('.')));
521 item
.m_image
= FI_UNKNOWN
;
525 wxColour
*dg
= wxTheColourDatabase
->FindColour( "MEDIUM GREY" );
526 item
.SetTextColour(*dg
);
528 item
.m_data
= (long)this;
531 //-----------------------------------------------------------------------------
533 //-----------------------------------------------------------------------------
535 IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl
,wxListCtrl
);
537 BEGIN_EVENT_TABLE(wxFileCtrl
,wxListCtrl
)
538 EVT_LIST_DELETE_ITEM(-1, wxFileCtrl::OnListDeleteItem
)
539 EVT_LIST_DELETE_ALL_ITEMS(-1, wxFileCtrl::OnListDeleteAllItems
)
540 EVT_LIST_END_LABEL_EDIT(-1, wxFileCtrl::OnListEndLabelEdit
)
544 wxFileCtrl::wxFileCtrl()
546 m_dirName
= wxT("/");
547 m_showHidden
= FALSE
;
550 wxFileCtrl::wxFileCtrl( wxWindow
*win
, wxWindowID id
,
551 const wxString
&dirName
, const wxString
&wild
,
552 const wxPoint
&pos
, const wxSize
&size
,
553 long style
, const wxValidator
&validator
, const wxString
&name
) :
554 wxListCtrl( win
, id
, pos
, size
, style
, validator
, name
)
556 if (! g_IconsTable
) g_IconsTable
= new wxFileIconsTable
;
557 wxImageList
*imageList
= g_IconsTable
-> GetImageList();
559 SetImageList( imageList
, wxIMAGE_LIST_SMALL
);
563 m_showHidden
= FALSE
;
567 void wxFileCtrl::ChangeToListMode()
569 SetSingleStyle( wxLC_LIST
);
573 void wxFileCtrl::ChangeToReportMode()
575 SetSingleStyle( wxLC_REPORT
);
579 void wxFileCtrl::ChangeToIconMode()
581 SetSingleStyle( wxLC_ICON
);
585 void wxFileCtrl::ShowHidden( bool show
)
591 long wxFileCtrl::Add( wxFileData
*fd
, wxListItem
&item
)
594 item
.m_mask
= wxLIST_MASK_TEXT
+ wxLIST_MASK_DATA
+ wxLIST_MASK_IMAGE
;
595 fd
->MakeItem( item
);
596 long my_style
= GetWindowStyleFlag();
597 if (my_style
& wxLC_REPORT
)
599 ret
= InsertItem( item
);
600 for (int i
= 1; i
< 5; i
++) SetItem( item
.m_itemId
, i
, fd
->GetEntry( i
) );
602 else if (my_style
& wxLC_LIST
)
604 ret
= InsertItem( item
);
609 void wxFileCtrl::Update()
611 long my_style
= GetWindowStyleFlag();
612 int name_col_width
= 0;
613 if (my_style
& wxLC_REPORT
)
615 if (GetColumnCount() > 0)
616 name_col_width
= GetColumnWidth( 0 );
620 if (my_style
& wxLC_REPORT
)
622 if (name_col_width
< 140) name_col_width
= 140;
623 InsertColumn( 0, _("Name"), wxLIST_FORMAT_LEFT
, name_col_width
);
624 InsertColumn( 1, _("Size"), wxLIST_FORMAT_LEFT
, 60 );
625 InsertColumn( 2, _("Date"), wxLIST_FORMAT_LEFT
, 65 );
626 InsertColumn( 3, _("Time"), wxLIST_FORMAT_LEFT
, 50 );
627 InsertColumn( 4, _("Permissions"), wxLIST_FORMAT_LEFT
, 120 );
629 wxFileData
*fd
= (wxFileData
*) NULL
;
634 if (m_dirName
!= wxT("/"))
636 wxString
p( wxPathOnly(m_dirName
) );
637 if (p
.IsEmpty()) p
= wxT("/");
638 fd
= new wxFileData( wxT(".."), p
);
643 wxString res
= m_dirName
+ wxT("/*");
644 wxString
f( wxFindFirstFile( res
.GetData(), wxDIR
) );
647 res
= wxFileNameFromPath( f
);
648 fd
= new wxFileData( res
, f
);
649 wxString s
= fd
->GetName();
650 if (m_showHidden
|| (s
[0u] != wxT('.')))
655 f
= wxFindNextFile();
658 // Tokenize the wildcard string, so we can handle more than 1
659 // search pattern in a wildcard.
660 wxStringTokenizer
tokenWild( m_wild
, ";" );
661 while ( tokenWild
.HasMoreTokens() )
663 res
= m_dirName
+ wxT("/") + tokenWild
.GetNextToken();
664 f
= wxFindFirstFile( res
.GetData(), wxFILE
);
667 res
= wxFileNameFromPath( f
);
668 fd
= new wxFileData( res
, f
);
669 wxString s
= fd
->GetName();
670 if (m_showHidden
|| (s
[0u] != wxT('.')))
675 f
= wxFindNextFile();
679 SortItems( ListCompare
, 0 );
681 if (my_style
& wxLC_REPORT
)
683 SetColumnWidth( 1, wxLIST_AUTOSIZE
);
684 SetColumnWidth( 2, wxLIST_AUTOSIZE
);
685 SetColumnWidth( 3, wxLIST_AUTOSIZE
);
689 void wxFileCtrl::SetWild( const wxString
&wild
)
695 void wxFileCtrl::MakeDir()
697 wxString
new_name( wxT("NewName") );
698 wxString
path( m_dirName
);
701 if (wxFileExists(path
))
703 // try NewName0, NewName1 etc.
706 new_name
= _("NewName");
708 num
.Printf( wxT("%d"), i
);
715 } while (wxFileExists(path
));
721 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
726 wxFileData
*fd
= new wxFileData( new_name
, path
);
730 long id
= Add( fd
, item
);
734 SortItems( ListCompare
, 0 );
735 id
= FindItem( 0, (long)fd
);
741 void wxFileCtrl::GoToParentDir()
743 if (m_dirName
!= wxT("/"))
745 wxString
fname( wxFileNameFromPath(m_dirName
) );
746 m_dirName
= wxPathOnly( m_dirName
);
747 if (m_dirName
.IsEmpty()) m_dirName
= wxT("/");
749 long id
= FindItem( 0, fname
);
752 SetItemState( id
, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
758 void wxFileCtrl::GoToHomeDir()
760 wxString s
= wxGetUserHome( wxString() );
763 SetItemState( 0, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
767 void wxFileCtrl::GoToDir( const wxString
&dir
)
771 SetItemState( 0, wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
775 void wxFileCtrl::GetDir( wxString
&dir
)
780 void wxFileCtrl::OnListDeleteItem( wxListEvent
&event
)
782 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
786 void wxFileCtrl::OnListDeleteAllItems( wxListEvent
&WXUNUSED(event
) )
789 item
.m_mask
= wxLIST_MASK_DATA
;
791 item
.m_itemId
= GetNextItem( -1, wxLIST_NEXT_ALL
);
792 while ( item
.m_itemId
!= -1 )
795 wxFileData
*fd
= (wxFileData
*)item
.m_data
;
799 item
.m_itemId
= GetNextItem( item
.m_itemId
, wxLIST_NEXT_ALL
);
803 void wxFileCtrl::OnListEndLabelEdit( wxListEvent
&event
)
805 wxFileData
*fd
= (wxFileData
*)event
.m_item
.m_data
;
808 if ((event
.GetLabel().IsEmpty()) ||
809 (event
.GetLabel() == _(".")) ||
810 (event
.GetLabel() == _("..")) ||
811 (event
.GetLabel().First( wxT("/") ) != wxNOT_FOUND
))
813 wxMessageDialog
dialog(this, _("Illegal directory name."), _("Error"), wxOK
| wxICON_ERROR
);
819 wxString
new_name( wxPathOnly( fd
->GetFullName() ) );
820 new_name
+= wxT("/");
821 new_name
+= event
.GetLabel();
825 if (wxFileExists(new_name
))
827 wxMessageDialog
dialog(this, _("File name exists already."), _("Error"), wxOK
| wxICON_ERROR
);
832 if (wxRenameFile(fd
->GetFullName(),new_name
))
834 fd
->SetNewName( new_name
, event
.GetLabel() );
835 SetItemState( event
.GetItem(), wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
836 EnsureVisible( event
.GetItem() );
840 wxMessageDialog
dialog(this, _("Operation not permitted."), _("Error"), wxOK
| wxICON_ERROR
);
846 //-----------------------------------------------------------------------------
848 //-----------------------------------------------------------------------------
850 #define ID_LIST_MODE wxID_FILEDLGG
851 #define ID_REPORT_MODE wxID_FILEDLGG + 1
852 #define ID_UP_DIR wxID_FILEDLGG + 5
853 #define ID_PARENT_DIR wxID_FILEDLGG + 6
854 #define ID_NEW_DIR wxID_FILEDLGG + 7
855 #define ID_CHOICE wxID_FILEDLGG + 8
856 #define ID_TEXT wxID_FILEDLGG + 9
857 #define ID_LIST_CTRL wxID_FILEDLGG + 10
858 #define ID_ACTIVATED wxID_FILEDLGG + 11
859 #define ID_CHECK wxID_FILEDLGG + 12
861 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog
,wxDialog
)
863 BEGIN_EVENT_TABLE(wxFileDialog
,wxDialog
)
864 EVT_BUTTON(ID_LIST_MODE
, wxFileDialog::OnList
)
865 EVT_BUTTON(ID_REPORT_MODE
, wxFileDialog::OnReport
)
866 EVT_BUTTON(ID_UP_DIR
, wxFileDialog::OnUp
)
867 EVT_BUTTON(ID_PARENT_DIR
, wxFileDialog::OnHome
)
868 EVT_BUTTON(ID_NEW_DIR
, wxFileDialog::OnNew
)
869 EVT_BUTTON(wxID_OK
, wxFileDialog::OnListOk
)
870 EVT_LIST_ITEM_SELECTED(ID_LIST_CTRL
, wxFileDialog::OnSelected
)
871 EVT_LIST_ITEM_ACTIVATED(ID_LIST_CTRL
, wxFileDialog::OnActivated
)
872 EVT_CHOICE(ID_CHOICE
,wxFileDialog::OnChoice
)
873 EVT_TEXT_ENTER(ID_TEXT
,wxFileDialog::OnTextEnter
)
874 EVT_CHECKBOX(ID_CHECK
,wxFileDialog::OnCheck
)
877 long wxFileDialog::s_lastViewStyle
= wxLC_LIST
;
878 bool wxFileDialog::s_lastShowHidden
= FALSE
;
880 wxFileDialog::wxFileDialog(wxWindow
*parent
,
881 const wxString
& message
,
882 const wxString
& defaultDir
,
883 const wxString
& defaultFile
,
884 const wxString
& wildCard
,
886 const wxPoint
& pos
) :
887 wxDialog( parent
, -1, message
, pos
, wxDefaultSize
, wxDEFAULT_DIALOG_STYLE
| wxRESIZE_BORDER
)
891 if (wxConfig::Get(FALSE
))
893 wxConfig::Get() -> Read(wxT("/wxWindows/wxFileDialog/ViewStyle"), &s_lastViewStyle
);
894 wxConfig::Get() -> Read(wxT("/wxWindows/wxFileDialog/ShowHidden"), &s_lastShowHidden
);
898 m_dialogStyle
= style
;
900 if (m_dialogStyle
== 0) m_dialogStyle
= wxOPEN
;
901 if ((m_dialogStyle
& wxMULTIPLE
) && !(m_dialogStyle
& wxOPEN
))
902 m_dialogStyle
|= wxOPEN
;
905 if ((m_dir
.IsEmpty()) || (m_dir
== wxT(".")))
908 m_dir
= getcwd( buf
, sizeof(buf
) );
912 m_path
+= defaultFile
;
913 m_fileName
= defaultFile
;
914 m_wildCard
= wildCard
;
916 m_filterExtension
= wxEmptyString
;
918 // interpret wildcards
920 if (m_wildCard
.IsEmpty())
921 m_wildCard
= _("All files (*)|*");
923 wxStringTokenizer
tokens( m_wildCard
, wxT("|") );
925 wxString firstWildText
;
926 if (tokens
.CountTokens() == 1)
928 firstWildText
= tokens
.GetNextToken();
929 firstWild
= firstWildText
;
933 wxASSERT_MSG( tokens
.CountTokens() % 2 == 0, wxT("Wrong file type descripition") );
934 firstWildText
= tokens
.GetNextToken();
935 firstWild
= tokens
.GetNextToken();
937 if ( firstWild
.Left( 2 ) == wxT("*.") )
938 m_filterExtension
= firstWild
.Mid( 1 );
939 if ( m_filterExtension
== ".*" ) m_filterExtension
= wxEmptyString
;
943 wxBoxSizer
*mainsizer
= new wxBoxSizer( wxVERTICAL
);
945 wxBoxSizer
*buttonsizer
= new wxBoxSizer( wxHORIZONTAL
);
949 but
= new wxBitmapButton( this, ID_LIST_MODE
, wxBitmap( listview_xpm
) );
951 but
->SetToolTip( _("View files as a list view") );
953 buttonsizer
->Add( but
, 0, wxALL
, 5 );
955 but
= new wxBitmapButton( this, ID_REPORT_MODE
, wxBitmap( repview_xpm
) );
957 but
->SetToolTip( _("View files as a detailed view") );
959 buttonsizer
->Add( but
, 0, wxALL
, 5 );
961 buttonsizer
->Add( 30, 5, 1 );
963 but
= new wxBitmapButton( this, ID_UP_DIR
, wxBitmap( dir_up_xpm
) );
965 but
->SetToolTip( _("Go to parent directory") );
967 buttonsizer
->Add( but
, 0, wxALL
, 5 );
969 but
= new wxBitmapButton( this, ID_PARENT_DIR
, wxBitmap(home_xpm
) );
971 but
->SetToolTip( _("Go to home directory") );
973 buttonsizer
->Add( but
, 0, wxALL
, 5);
975 buttonsizer
->Add( 20, 20 );
977 but
= new wxBitmapButton( this, ID_NEW_DIR
, wxBitmap(new_dir_xpm
) );
979 but
->SetToolTip( _("Create new directory") );
981 buttonsizer
->Add( but
, 0, wxALL
, 5 );
983 mainsizer
->Add( buttonsizer
, 0, wxALL
| wxEXPAND
, 5 );
985 wxBoxSizer
*staticsizer
= new wxBoxSizer( wxHORIZONTAL
);
986 staticsizer
->Add( new wxStaticText( this, -1, _("Current directory:") ), 0, wxRIGHT
, 10 );
987 m_static
= new wxStaticText( this, -1, m_dir
);
988 staticsizer
->Add( m_static
, 1 );
989 mainsizer
->Add( staticsizer
, 0, wxEXPAND
| wxLEFT
|wxRIGHT
|wxBOTTOM
, 10 );
991 if (m_dialogStyle
& wxMULTIPLE
)
992 m_list
= new wxFileCtrl( this, ID_LIST_CTRL
, m_dir
, firstWild
, wxDefaultPosition
,
993 wxSize(440,180), s_lastViewStyle
| wxSUNKEN_BORDER
);
995 m_list
= new wxFileCtrl( this, ID_LIST_CTRL
, m_dir
, firstWild
, wxDefaultPosition
,
996 wxSize(440,180), s_lastViewStyle
| wxSUNKEN_BORDER
| wxLC_SINGLE_SEL
);
997 m_list
-> ShowHidden(s_lastShowHidden
);
998 mainsizer
->Add( m_list
, 1, wxEXPAND
| wxLEFT
|wxRIGHT
, 10 );
1000 wxBoxSizer
*textsizer
= new wxBoxSizer( wxHORIZONTAL
);
1001 m_text
= new wxTextCtrl( this, ID_TEXT
, m_fileName
, wxDefaultPosition
, wxDefaultSize
, wxPROCESS_ENTER
);
1002 textsizer
->Add( m_text
, 1, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
1003 textsizer
->Add( new wxButton( this, wxID_OK
, _("OK") ), 0, wxCENTER
| wxLEFT
|wxRIGHT
|wxTOP
, 10 );
1004 mainsizer
->Add( textsizer
, 0, wxEXPAND
);
1006 wxBoxSizer
*choicesizer
= new wxBoxSizer( wxHORIZONTAL
);
1007 m_choice
= new wxChoice( this, ID_CHOICE
);
1008 choicesizer
->Add( m_choice
, 1, wxCENTER
|wxALL
, 10 );
1009 m_check
= new wxCheckBox( this, ID_CHECK
, _("Show hidden files") );
1010 m_check
->SetValue( s_lastShowHidden
);
1011 choicesizer
->Add( m_check
, 0, wxCENTER
|wxALL
, 10 );
1012 choicesizer
->Add( new wxButton( this, wxID_CANCEL
, _("Cancel") ), 0, wxCENTER
| wxALL
, 10 );
1013 mainsizer
->Add( choicesizer
, 0, wxEXPAND
);
1015 m_choice
->Append( firstWildText
, (void*) new wxString( firstWild
) );
1016 while (tokens
.HasMoreTokens())
1018 firstWildText
= tokens
.GetNextToken();
1019 firstWild
= tokens
.GetNextToken();
1020 m_choice
->Append( firstWildText
, (void*) new wxString( firstWild
) );
1022 m_choice
->SetSelection( 0 );
1024 SetAutoLayout( TRUE
);
1025 SetSizer( mainsizer
);
1027 mainsizer
->Fit( this );
1028 mainsizer
->SetSizeHints( this );
1033 if (m_fileName.IsEmpty())
1042 wxFileDialog::~wxFileDialog()
1044 if (wxConfig::Get(FALSE
))
1046 wxConfig::Get() -> Write(wxT("/wxWindows/wxFileDialog/ViewStyle"), s_lastViewStyle
);
1047 wxConfig::Get() -> Write(wxT("/wxWindows/wxFileDialog/ShowHidden"), s_lastShowHidden
);
1051 void wxFileDialog::OnChoice( wxCommandEvent
&event
)
1053 int index
= (int)event
.GetInt();
1054 wxString
*str
= (wxString
*) m_choice
->GetClientData( index
);
1055 m_list
->SetWild( *str
);
1056 m_filterIndex
= index
;
1057 if ( str
-> Left( 2 ) == wxT("*.") )
1059 m_filterExtension
= str
-> Mid( 1 );
1060 if (m_filterExtension
== ".*") m_filterExtension
= wxEmptyString
;
1063 m_filterExtension
= wxEmptyString
;
1066 void wxFileDialog::OnCheck( wxCommandEvent
&event
)
1068 m_list
->ShowHidden( (s_lastShowHidden
= event
.GetInt() != 0) );
1071 void wxFileDialog::OnActivated( wxListEvent
&event
)
1073 HandleAction( event
.m_item
.m_text
);
1076 void wxFileDialog::OnTextEnter( wxCommandEvent
&WXUNUSED(event
) )
1078 wxCommandEvent
cevent(wxEVT_COMMAND_BUTTON_CLICKED
, wxID_OK
);
1079 cevent
.SetEventObject( this );
1080 GetEventHandler()->ProcessEvent( cevent
);
1083 void wxFileDialog::OnSelected( wxListEvent
&event
)
1085 if (FindFocus() != m_list
) return;
1087 wxString
filename( event
.m_item
.m_text
);
1088 if (filename
== wxT("..")) return;
1091 m_list
->GetDir( dir
);
1092 if (dir
!= wxT("/")) dir
+= wxT("/");
1094 if (wxDirExists(dir
)) return;
1096 m_text
->SetValue( filename
);
1099 void wxFileDialog::HandleAction( const wxString
&fn
)
1101 wxString
filename( fn
);
1103 m_list
->GetDir( dir
);
1104 if (filename
.IsEmpty()) return;
1105 if (filename
== wxT(".")) return;
1107 if (filename
== wxT(".."))
1109 m_list
->GoToParentDir();
1111 m_list
->GetDir( dir
);
1112 m_static
->SetLabel( dir
);
1116 if (filename
== wxT("~"))
1118 m_list
->GoToHomeDir();
1120 m_list
->GetDir( dir
);
1121 m_static
->SetLabel( dir
);
1125 if (filename
[0u] == wxT('~'))
1127 filename
.Remove( 0, 1 );
1128 wxString
tmp( wxGetUserHome() );
1134 if ((filename
.Find(wxT('*')) != wxNOT_FOUND
) ||
1135 (filename
.Find(wxT('?')) != wxNOT_FOUND
))
1137 if (filename
.Find(wxT('/')) != wxNOT_FOUND
)
1139 wxMessageBox(_("Illegal file specification."), _("Error"), wxOK
| wxICON_ERROR
);
1142 m_list
->SetWild( filename
);
1146 if (dir
!= wxT("/")) dir
+= wxT("/");
1147 if (filename
[0u] != wxT('/'))
1153 if (wxDirExists(filename
))
1155 m_list
->GoToDir( filename
);
1156 m_list
->GetDir( dir
);
1157 m_static
->SetLabel( dir
);
1162 if ( (m_dialogStyle
& wxSAVE
) && (m_dialogStyle
& wxOVERWRITE_PROMPT
) )
1164 if (filename
.Find( wxT('.') ) == wxNOT_FOUND
||
1165 filename
.AfterLast( wxT('.') ).Find( wxT('/') ) != wxNOT_FOUND
)
1166 filename
<< m_filterExtension
;
1167 if (wxFileExists( filename
))
1170 msg
.Printf( _("File '%s' already exists, do you really want to "
1171 "overwrite it?"), filename
.c_str() );
1173 if (wxMessageBox(msg
, _("Confirm"), wxYES_NO
) != wxYES
)
1177 else if ( m_dialogStyle
& wxOPEN
)
1179 if ( !wxFileExists( filename
) )
1180 if (filename
.Find( wxT('.') ) == wxNOT_FOUND
||
1181 filename
.AfterLast( wxT('.') ).Find( wxT('/') ) != wxNOT_FOUND
)
1182 filename
<< m_filterExtension
;
1184 if ( m_dialogStyle
& wxFILE_MUST_EXIST
)
1186 if ( !wxFileExists( filename
) )
1188 wxMessageBox(_("Please choose an existing file."), _("Error"), wxOK
| wxICON_ERROR
);
1194 SetPath( filename
);
1196 // change to the directory where the user went if asked
1197 if ( m_dialogStyle
& wxCHANGE_DIR
)
1200 wxSplitPath(filename
, &cwd
, NULL
, NULL
);
1202 if ( cwd
!= wxGetWorkingDirectory() )
1204 wxSetWorkingDirectory(cwd
);
1208 wxCommandEvent event
;
1209 wxDialog::OnOK(event
);
1212 void wxFileDialog::OnListOk( wxCommandEvent
&WXUNUSED(event
) )
1214 HandleAction( m_text
->GetValue() );
1217 void wxFileDialog::OnList( wxCommandEvent
&WXUNUSED(event
) )
1219 m_list
->ChangeToListMode();
1220 s_lastViewStyle
= wxLC_LIST
;
1224 void wxFileDialog::OnReport( wxCommandEvent
&WXUNUSED(event
) )
1226 m_list
->ChangeToReportMode();
1227 s_lastViewStyle
= wxLC_REPORT
;
1231 void wxFileDialog::OnUp( wxCommandEvent
&WXUNUSED(event
) )
1233 m_list
->GoToParentDir();
1236 m_list
->GetDir( dir
);
1237 m_static
->SetLabel( dir
);
1240 void wxFileDialog::OnHome( wxCommandEvent
&WXUNUSED(event
) )
1242 m_list
->GoToHomeDir();
1245 m_list
->GetDir( dir
);
1246 m_static
->SetLabel( dir
);
1249 void wxFileDialog::OnNew( wxCommandEvent
&WXUNUSED(event
) )
1254 void wxFileDialog::SetPath( const wxString
& path
)
1256 // not only set the full path but also update filename and dir
1261 wxSplitPath(path
, &m_dir
, &m_fileName
, &ext
);
1264 m_fileName
+= wxT(".");
1270 void wxFileDialog::GetPaths( wxArrayString
& paths
) const
1273 if (m_list
->GetSelectedItemCount() == 0)
1275 paths
.Add( GetPath() );
1279 paths
.Alloc( m_list
->GetSelectedItemCount() );
1282 m_list
->GetDir( dir
);
1283 if (dir
!= wxT("/")) dir
+= wxT("/");
1286 item
.m_mask
= wxLIST_MASK_TEXT
;
1288 item
.m_itemId
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1289 while ( item
.m_itemId
!= -1 )
1291 m_list
->GetItem( item
);
1292 paths
.Add( dir
+ item
.m_text
);
1293 item
.m_itemId
= m_list
->GetNextItem( item
.m_itemId
,
1294 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1298 void wxFileDialog::GetFilenames(wxArrayString
& files
) const
1301 if (m_list
->GetSelectedItemCount() == 0)
1303 files
.Add( GetFilename() );
1306 files
.Alloc( m_list
->GetSelectedItemCount() );
1309 item
.m_mask
= wxLIST_MASK_TEXT
;
1311 item
.m_itemId
= m_list
->GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1312 while ( item
.m_itemId
!= -1 )
1314 m_list
->GetItem( item
);
1315 files
.Add( item
.m_text
);
1316 item
.m_itemId
= m_list
->GetNextItem( item
.m_itemId
,
1317 wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
1323 // ----------------------------------------------------------------------------
1325 // ----------------------------------------------------------------------------
1328 wxFileSelectorEx(const wxChar
*message
,
1329 const wxChar
*default_path
,
1330 const wxChar
*default_filename
,
1331 int *WXUNUSED(indexDefaultExtension
),
1332 const wxChar
*wildcard
,
1337 // TODO: implement this somehow
1338 return wxFileSelector(message
, default_path
, default_filename
, wxT(""),
1339 wildcard
, flags
, parent
, x
, y
);
1342 wxString
wxFileSelector( const wxChar
*title
,
1343 const wxChar
*defaultDir
, const wxChar
*defaultFileName
,
1344 const wxChar
*defaultExtension
, const wxChar
*filter
, int flags
,
1345 wxWindow
*parent
, int x
, int y
)
1348 if ( defaultExtension
&& !filter
)
1349 filter2
= wxString(wxT("*.")) + wxString(defaultExtension
) ;
1353 wxString defaultDirString
;
1355 defaultDirString
= defaultDir
;
1357 wxString defaultFilenameString
;
1358 if (defaultFileName
)
1359 defaultFilenameString
= defaultFileName
;
1361 wxFileDialog
fileDialog( parent
, title
, defaultDirString
, defaultFilenameString
, filter2
, flags
, wxPoint(x
, y
) );
1363 if ( fileDialog
.ShowModal() == wxID_OK
)
1365 return fileDialog
.GetPath();
1369 return wxEmptyString
;
1373 wxString
wxLoadFileSelector( const wxChar
*what
, const wxChar
*ext
, const wxChar
*default_name
, wxWindow
*parent
)
1375 wxString prompt
= wxString::Format(_("Load %s file"), what
);
1377 if (*ext
== wxT('.'))
1380 wxString wild
= wxString::Format(_T("*.%s"), ext
);
1382 return wxFileSelector(prompt
, (const wxChar
*) NULL
, default_name
,
1383 ext
, wild
, 0, parent
);
1386 wxString
wxSaveFileSelector(const wxChar
*what
, const wxChar
*extension
, const wxChar
*default_name
,
1389 wxChar
*ext
= (wxChar
*)extension
;
1391 wxString prompt
= wxString::Format(_("Save %s file"), what
);
1393 if (*ext
== wxT('.'))
1396 wxString wild
= wxString::Format(_T("*.%s"), ext
);
1398 return wxFileSelector(prompt
, (const wxChar
*) NULL
, default_name
,
1399 ext
, wild
, 0, parent
);
1407 // A module to allow icons table cleanup
1409 class wxFileDialogGenericModule
: public wxModule
1411 DECLARE_DYNAMIC_CLASS(wxFileDialogGenericModule
)
1413 wxFileDialogGenericModule() {}
1414 bool OnInit() { return TRUE
; }
1415 void OnExit() { if (g_IconsTable
) {delete g_IconsTable
; g_IconsTable
= NULL
;} }
1418 IMPLEMENT_DYNAMIC_CLASS(wxFileDialogGenericModule
, wxModule
)
1420 #endif // wxUSE_FILEDLG