use update UI handler for the up and new directory buttons instead of manually updati...
[wxWidgets.git] / src / generic / filedlgg.cpp
1 //////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/filedlgg.cpp
3 // Purpose: wxGenericFileDialog
4 // Author: Robert Roebling
5 // Modified by:
6 // Created: 12/12/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_FILEDLG
20
21 // NOTE : it probably also supports MAC, untested
22 #if !defined(__UNIX__) && !defined(__DOS__) && !defined(__WIN32__) && !defined(__OS2__)
23 #error wxGenericFileDialog currently only supports Unix, win32 and DOS
24 #endif
25
26 #ifndef WX_PRECOMP
27 #ifdef __WXMSW__
28 #include "wx/msw/wrapwin.h"
29 #endif
30 #include "wx/hash.h"
31 #include "wx/intl.h"
32 #include "wx/settings.h"
33 #include "wx/log.h"
34 #include "wx/msgdlg.h"
35 #include "wx/bmpbuttn.h"
36 #include "wx/checkbox.h"
37 #include "wx/choice.h"
38 #include "wx/stattext.h"
39 #include "wx/textctrl.h"
40 #include "wx/sizer.h"
41 #include "wx/filedlg.h" // wxFD_OPEN, wxFD_SAVE...
42 #endif
43
44 #include "wx/longlong.h"
45 #include "wx/config.h"
46 #include "wx/imaglist.h"
47 #include "wx/artprov.h"
48 #include "wx/filefn.h"
49 #include "wx/filectrl.h"
50 #include "wx/generic/filedlgg.h"
51 #include "wx/debug.h"
52
53 #if wxUSE_TOOLTIPS
54 #include "wx/tooltip.h"
55 #endif
56
57 #ifndef __WXWINCE__
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #endif
61
62 #ifdef __UNIX__
63 #include <dirent.h>
64 #include <pwd.h>
65 #ifndef __VMS
66 # include <grp.h>
67 #endif
68 #endif
69
70 #ifdef __WINDOWS__
71 #include "wx/msw/mslu.h"
72 #endif
73
74 #ifdef __WATCOMC__
75 #include <direct.h>
76 #endif
77
78 #ifndef __WXWINCE__
79 #include <time.h>
80 #endif
81
82 #if defined(__UNIX__) || defined(__DOS__)
83 #include <unistd.h>
84 #endif
85
86 #if defined(__WXWINCE__)
87 #define IsTopMostDir(dir) (dir == wxT("\\") || dir == wxT("/"))
88 #elif (defined(__DOS__) || defined(__WINDOWS__) || defined (__OS2__))
89 #define IsTopMostDir(dir) (dir.empty())
90 #else
91 #define IsTopMostDir(dir) (dir == wxT("/"))
92 #endif
93
94 //-----------------------------------------------------------------------------
95 // wxGenericFileDialog
96 //-----------------------------------------------------------------------------
97
98 #define ID_LIST_MODE (wxID_FILEDLGG )
99 #define ID_REPORT_MODE (wxID_FILEDLGG + 1)
100 #define ID_UP_DIR (wxID_FILEDLGG + 2)
101 #define ID_PARENT_DIR (wxID_FILEDLGG + 3)
102 #define ID_NEW_DIR (wxID_FILEDLGG + 4)
103 #define ID_FILE_CTRL (wxID_FILEDLGG + 5)
104
105 IMPLEMENT_DYNAMIC_CLASS(wxGenericFileDialog, wxFileDialogBase)
106
107 BEGIN_EVENT_TABLE(wxGenericFileDialog,wxDialog)
108 EVT_BUTTON(ID_LIST_MODE, wxGenericFileDialog::OnList)
109 EVT_BUTTON(ID_REPORT_MODE, wxGenericFileDialog::OnReport)
110 EVT_BUTTON(ID_UP_DIR, wxGenericFileDialog::OnUp)
111 EVT_BUTTON(ID_PARENT_DIR, wxGenericFileDialog::OnHome)
112 EVT_BUTTON(ID_NEW_DIR, wxGenericFileDialog::OnNew)
113 EVT_BUTTON(wxID_OK, wxGenericFileDialog::OnOk)
114 EVT_FILECTRL_FILEACTIVATED(ID_FILE_CTRL, wxGenericFileDialog::OnFileActivated)
115
116 EVT_UPDATE_UI(ID_UP_DIR, wxGenericFileDialog::OnUpdateButtonsUI)
117 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__)
118 EVT_UPDATE_UI(ID_NEW_DIR, wxGenericFileDialog::OnUpdateButtonsUI)
119 #endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__)
120 END_EVENT_TABLE()
121
122 long wxGenericFileDialog::ms_lastViewStyle = wxLC_LIST;
123 bool wxGenericFileDialog::ms_lastShowHidden = false;
124
125 void wxGenericFileDialog::Init()
126 {
127 m_bypassGenericImpl = false;
128
129 m_filectrl = NULL;
130 m_upDirButton = NULL;
131 m_newDirButton = NULL;
132 }
133
134 wxGenericFileDialog::wxGenericFileDialog(wxWindow *parent,
135 const wxString& message,
136 const wxString& defaultDir,
137 const wxString& defaultFile,
138 const wxString& wildCard,
139 long style,
140 const wxPoint& pos,
141 const wxSize& sz,
142 const wxString& name,
143 bool bypassGenericImpl ) : wxFileDialogBase()
144 {
145 Init();
146 Create( parent, message, defaultDir, defaultFile, wildCard, style, pos, sz, name, bypassGenericImpl );
147 }
148
149 bool wxGenericFileDialog::Create( wxWindow *parent,
150 const wxString& message,
151 const wxString& defaultDir,
152 const wxString& defaultFile,
153 const wxString& wildCard,
154 long style,
155 const wxPoint& pos,
156 const wxSize& sz,
157 const wxString& name,
158 bool bypassGenericImpl )
159 {
160 m_bypassGenericImpl = bypassGenericImpl;
161
162 parent = GetParentForModalDialog(parent);
163
164 if (!wxFileDialogBase::Create(parent, message, defaultDir, defaultFile,
165 wildCard, style, pos, sz, name))
166 {
167 return false;
168 }
169
170 if (m_bypassGenericImpl)
171 return true;
172
173 if (!wxDialog::Create( parent, wxID_ANY, message, pos, sz,
174 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | style, name
175 ))
176 {
177 return false;
178 }
179
180 #if wxUSE_CONFIG
181 if (wxConfig::Get(false))
182 {
183 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"),
184 &ms_lastViewStyle);
185 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"),
186 &ms_lastShowHidden);
187 }
188 #endif
189
190 if ((m_dir.empty()) || (m_dir == wxT(".")))
191 {
192 m_dir = wxGetCwd();
193 if (m_dir.empty())
194 m_dir = wxFILE_SEP_PATH;
195 }
196
197 const size_t len = m_dir.length();
198 if ((len > 1) && (wxEndsWithPathSeparator(m_dir)))
199 m_dir.Remove( len-1, 1 );
200
201 m_path = m_dir;
202 m_path += wxFILE_SEP_PATH;
203 m_path += defaultFile;
204 m_filterExtension = wxEmptyString;
205
206 // layout
207
208 const bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
209
210 wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );
211
212 wxBoxSizer *buttonsizer = new wxBoxSizer( wxHORIZONTAL );
213
214 wxBitmapButton *but;
215
216 but = new wxBitmapButton(this, ID_LIST_MODE,
217 wxArtProvider::GetBitmap(wxART_LIST_VIEW, wxART_BUTTON));
218 #if wxUSE_TOOLTIPS
219 but->SetToolTip( _("View files as a list view") );
220 #endif
221 buttonsizer->Add( but, 0, wxALL, 5 );
222
223 but = new wxBitmapButton(this, ID_REPORT_MODE,
224 wxArtProvider::GetBitmap(wxART_REPORT_VIEW, wxART_BUTTON));
225 #if wxUSE_TOOLTIPS
226 but->SetToolTip( _("View files as a detailed view") );
227 #endif
228 buttonsizer->Add( but, 0, wxALL, 5 );
229
230 buttonsizer->Add( 30, 5, 1 );
231
232 m_upDirButton = new wxBitmapButton(this, ID_UP_DIR,
233 wxArtProvider::GetBitmap(wxART_GO_DIR_UP, wxART_BUTTON));
234 #if wxUSE_TOOLTIPS
235 m_upDirButton->SetToolTip( _("Go to parent directory") );
236 #endif
237 buttonsizer->Add( m_upDirButton, 0, wxALL, 5 );
238
239 #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS...
240 but = new wxBitmapButton(this, ID_PARENT_DIR,
241 wxArtProvider::GetBitmap(wxART_GO_HOME, wxART_BUTTON));
242 #if wxUSE_TOOLTIPS
243 but->SetToolTip( _("Go to home directory") );
244 #endif
245 buttonsizer->Add( but, 0, wxALL, 5);
246
247 buttonsizer->Add( 20, 20 );
248 #endif //!__DOS__
249
250 m_newDirButton = new wxBitmapButton(this, ID_NEW_DIR,
251 wxArtProvider::GetBitmap(wxART_NEW_DIR, wxART_BUTTON));
252 #if wxUSE_TOOLTIPS
253 m_newDirButton->SetToolTip( _("Create new directory") );
254 #endif
255 buttonsizer->Add( m_newDirButton, 0, wxALL, 5 );
256
257 if (is_pda)
258 mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 0 );
259 else
260 mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 5 );
261
262 long style2 = 0;
263 if ( HasFdFlag(wxFD_MULTIPLE) )
264 style2 |= wxFC_MULTIPLE;
265
266 m_filectrl = new wxGenericFileCtrl( this, ID_FILE_CTRL,
267 m_dir, defaultFile,
268 wildCard,
269 style2,
270 wxDefaultPosition, wxSize(540,200)
271 );
272
273 m_filectrl->ShowHidden( ms_lastShowHidden );
274
275 if (ms_lastViewStyle == wxLC_LIST)
276 {
277 m_filectrl->ChangeToListMode();
278 }
279 else if (ms_lastViewStyle == wxLC_REPORT)
280 {
281 m_filectrl->ChangeToReportMode();
282 }
283
284 if (is_pda)
285 {
286 // PDAs have a different screen layout
287 mainsizer->Add(m_filectrl, wxSizerFlags(1).Expand().HorzBorder());
288
289 wxSizer *bsizer = CreateButtonSizer(wxOK | wxCANCEL);
290 if ( bsizer )
291 mainsizer->Add(bsizer, wxSizerFlags().Expand().Border());
292 }
293 else // !is_pda
294 {
295 mainsizer->Add(m_filectrl, wxSizerFlags(1).Expand().DoubleHorzBorder());
296
297 wxBoxSizer *okcancelsizer = new wxBoxSizer( wxHORIZONTAL );
298 okcancelsizer->Add(new wxButton(this, wxID_OK), wxSizerFlags().DoubleBorder().Centre());
299 okcancelsizer->Add(new wxButton(this, wxID_CANCEL), wxSizerFlags().DoubleBorder().Centre());
300 mainsizer->Add(okcancelsizer, wxSizerFlags().Center());
301 }
302
303 SetAutoLayout( true );
304 SetSizer( mainsizer );
305
306 if (!is_pda)
307 {
308 mainsizer->Fit( this );
309 mainsizer->SetSizeHints( this );
310
311 Centre( wxBOTH );
312 }
313
314 return true;
315 }
316
317 wxGenericFileDialog::~wxGenericFileDialog()
318 {
319 if (!m_bypassGenericImpl)
320 {
321 #if wxUSE_CONFIG
322 if (wxConfig::Get(false))
323 {
324 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"),
325 ms_lastViewStyle);
326 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"),
327 ms_lastShowHidden);
328 }
329 #endif
330 }
331 }
332
333 int wxGenericFileDialog::ShowModal()
334 {
335 m_filectrl->SetDirectory(m_dir);
336
337 return wxDialog::ShowModal();
338 }
339
340 bool wxGenericFileDialog::Show( bool show )
341 {
342 // Called by ShowModal, so don't repeate the update
343 #ifndef __WIN32__
344 if (show)
345 {
346 m_filectrl->SetDirectory(m_dir);
347 }
348 #endif
349
350 return wxDialog::Show( show );
351 }
352
353 void wxGenericFileDialog::SetWildcard(const wxString& wildCard)
354 {
355 m_filectrl->SetWildcard(wildCard);
356 }
357
358 void wxGenericFileDialog::SetFilterIndex( int filterindex )
359 {
360 m_filectrl->SetFilterIndex(filterindex);
361 }
362
363 void wxGenericFileDialog::OnOk( wxCommandEvent &WXUNUSED(event) )
364 {
365 wxArrayString selectedFiles;
366 m_filectrl->GetFilenames(selectedFiles);
367
368 if (selectedFiles.Count() == 0)
369 return;
370
371 if (selectedFiles.Count() == 1)
372 {
373 SetPath( selectedFiles[0] );
374 }
375
376 EndModal(wxID_OK);
377 }
378
379 void wxGenericFileDialog::OnList( wxCommandEvent &WXUNUSED(event) )
380 {
381 m_filectrl->ChangeToListMode();
382 ms_lastViewStyle = wxLC_LIST;
383 m_filectrl->GetFileList()->SetFocus();
384 }
385
386 void wxGenericFileDialog::OnReport( wxCommandEvent &WXUNUSED(event) )
387 {
388 m_filectrl->ChangeToReportMode();
389 ms_lastViewStyle = wxLC_REPORT;
390 m_filectrl->GetFileList()->SetFocus();
391 }
392
393 void wxGenericFileDialog::OnUp( wxCommandEvent &WXUNUSED(event) )
394 {
395 m_filectrl->GoToParentDir();
396 m_filectrl->GetFileList()->SetFocus();
397 }
398
399 void wxGenericFileDialog::OnHome( wxCommandEvent &WXUNUSED(event) )
400 {
401 m_filectrl->GoToHomeDir();
402 m_filectrl->SetFocus();
403 }
404
405 void wxGenericFileDialog::OnNew( wxCommandEvent &WXUNUSED(event) )
406 {
407 m_filectrl->GetFileList()->MakeDir();
408 }
409
410 void wxGenericFileDialog::OnFileActivated( wxFileCtrlEvent &WXUNUSED(event) )
411 {
412 wxCommandEvent dummy;
413 OnOk( dummy );
414 }
415
416 void wxGenericFileDialog::SetPath( const wxString& path )
417 {
418 // not only set the full path but also update filename and dir
419 m_path = path;
420
421 m_filectrl->SetPath(path);
422 }
423
424 void wxGenericFileDialog::GetPaths( wxArrayString& paths ) const
425 {
426 m_filectrl->GetPaths(paths);
427 }
428
429 void wxGenericFileDialog::GetFilenames(wxArrayString& files) const
430 {
431 m_filectrl->GetFilenames(files);
432 }
433
434 void wxGenericFileDialog::OnUpdateButtonsUI(wxUpdateUIEvent& event)
435 {
436 event.Enable( !IsTopMostDir(m_filectrl->GetDirectory()) );
437 }
438
439 #ifdef wxHAS_GENERIC_FILEDIALOG
440
441 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog, wxGenericFileDialog)
442
443 #endif // wxHAS_GENERIC_FILEDIALOG
444
445 #endif // wxUSE_FILEDLG