Use flat generic status bar by default and add wxSB_SUNKEN.
[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 #include "wx/testing.h"
53
54 #if wxUSE_TOOLTIPS
55 #include "wx/tooltip.h"
56 #endif
57 #if wxUSE_CONFIG
58 #include "wx/config.h"
59 #endif
60
61 #ifndef __WXWINCE__
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #endif
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 __WINDOWS__
75 #include "wx/msw/mslu.h"
76 #endif
77
78 #ifdef __WATCOMC__
79 #include <direct.h>
80 #endif
81
82 #ifndef __WXWINCE__
83 #include <time.h>
84 #endif
85
86 #if defined(__UNIX__) || defined(__DOS__)
87 #include <unistd.h>
88 #endif
89
90 #if defined(__WXWINCE__)
91 #define IsTopMostDir(dir) (dir == wxT("\\") || dir == wxT("/"))
92 #elif (defined(__DOS__) || defined(__WINDOWS__) || defined (__OS2__))
93 #define IsTopMostDir(dir) (dir.empty())
94 #else
95 #define IsTopMostDir(dir) (dir == wxT("/"))
96 #endif
97
98 //-----------------------------------------------------------------------------
99 // wxGenericFileDialog
100 //-----------------------------------------------------------------------------
101
102 #define ID_LIST_MODE (wxID_FILEDLGG )
103 #define ID_REPORT_MODE (wxID_FILEDLGG + 1)
104 #define ID_UP_DIR (wxID_FILEDLGG + 2)
105 #define ID_HOME_DIR (wxID_FILEDLGG + 3)
106 #define ID_NEW_DIR (wxID_FILEDLGG + 4)
107 #define ID_FILE_CTRL (wxID_FILEDLGG + 5)
108
109 IMPLEMENT_DYNAMIC_CLASS(wxGenericFileDialog, wxFileDialogBase)
110
111 BEGIN_EVENT_TABLE(wxGenericFileDialog,wxDialog)
112 EVT_BUTTON(ID_LIST_MODE, wxGenericFileDialog::OnList)
113 EVT_BUTTON(ID_REPORT_MODE, wxGenericFileDialog::OnReport)
114 EVT_BUTTON(ID_UP_DIR, wxGenericFileDialog::OnUp)
115 EVT_BUTTON(ID_HOME_DIR, wxGenericFileDialog::OnHome)
116 EVT_BUTTON(ID_NEW_DIR, wxGenericFileDialog::OnNew)
117 EVT_BUTTON(wxID_OK, wxGenericFileDialog::OnOk)
118 EVT_FILECTRL_FILEACTIVATED(ID_FILE_CTRL, wxGenericFileDialog::OnFileActivated)
119
120 EVT_UPDATE_UI(ID_UP_DIR, wxGenericFileDialog::OnUpdateButtonsUI)
121 #if defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__)
122 EVT_UPDATE_UI(ID_NEW_DIR, wxGenericFileDialog::OnUpdateButtonsUI)
123 #endif // defined(__DOS__) || defined(__WINDOWS__) || defined(__OS2__)
124 END_EVENT_TABLE()
125
126 long wxGenericFileDialog::ms_lastViewStyle = wxLC_LIST;
127 bool wxGenericFileDialog::ms_lastShowHidden = false;
128
129 void wxGenericFileDialog::Init()
130 {
131 m_bypassGenericImpl = false;
132
133 m_filectrl = NULL;
134 m_upDirButton = NULL;
135 m_newDirButton = NULL;
136 }
137
138 wxGenericFileDialog::wxGenericFileDialog(wxWindow *parent,
139 const wxString& message,
140 const wxString& defaultDir,
141 const wxString& defaultFile,
142 const wxString& wildCard,
143 long style,
144 const wxPoint& pos,
145 const wxSize& sz,
146 const wxString& name,
147 bool bypassGenericImpl ) : wxFileDialogBase()
148 {
149 Init();
150 Create( parent, message, defaultDir, defaultFile, wildCard, style, pos, sz, name, bypassGenericImpl );
151 }
152
153 bool wxGenericFileDialog::Create( wxWindow *parent,
154 const wxString& message,
155 const wxString& defaultDir,
156 const wxString& defaultFile,
157 const wxString& wildCard,
158 long style,
159 const wxPoint& pos,
160 const wxSize& sz,
161 const wxString& name,
162 bool bypassGenericImpl )
163 {
164 m_bypassGenericImpl = bypassGenericImpl;
165
166 parent = GetParentForModalDialog(parent, style);
167
168 if (!wxFileDialogBase::Create(parent, message, defaultDir, defaultFile,
169 wildCard, style, pos, sz, name))
170 {
171 return false;
172 }
173
174 if (m_bypassGenericImpl)
175 return true;
176
177 if (!wxDialog::Create( parent, wxID_ANY, message, pos, sz,
178 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | style, name
179 ))
180 {
181 return false;
182 }
183
184 #if wxUSE_CONFIG
185 if (wxConfig::Get(false))
186 {
187 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"),
188 &ms_lastViewStyle);
189 wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"),
190 &ms_lastShowHidden);
191 }
192 #endif
193
194 if ((m_dir.empty()) || (m_dir == wxT(".")))
195 {
196 m_dir = wxGetCwd();
197 if (m_dir.empty())
198 m_dir = wxFILE_SEP_PATH;
199 }
200
201 const size_t len = m_dir.length();
202 if ((len > 1) && (wxEndsWithPathSeparator(m_dir)))
203 m_dir.Remove( len-1, 1 );
204
205 m_filterExtension = wxEmptyString;
206
207 // layout
208
209 const bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
210
211 wxBoxSizer *mainsizer = new wxBoxSizer( wxVERTICAL );
212
213 wxBoxSizer *buttonsizer = new wxBoxSizer( wxHORIZONTAL );
214 AddBitmapButton( ID_LIST_MODE, wxART_LIST_VIEW,
215 _("View files as a list view"), buttonsizer );
216 AddBitmapButton( ID_REPORT_MODE, wxART_REPORT_VIEW,
217 _("View files as a detailed view"), buttonsizer );
218 buttonsizer->Add( 30, 5, 1 );
219 m_upDirButton = AddBitmapButton( ID_UP_DIR, wxART_GO_DIR_UP,
220 _("Go to parent directory"), buttonsizer );
221
222 #ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS...
223 AddBitmapButton( ID_HOME_DIR, wxART_GO_HOME,
224 _("Go to home directory"), buttonsizer );
225 buttonsizer->Add( 20, 20 );
226 #endif //!__DOS__
227
228 m_newDirButton = AddBitmapButton( ID_NEW_DIR, wxART_NEW_DIR,
229 _("Create new directory"), buttonsizer );
230
231 if (is_pda)
232 mainsizer->Add( buttonsizer, wxSizerFlags().Expand() );
233 else
234 mainsizer->Add( buttonsizer, wxSizerFlags().Expand()
235 .Border( wxLEFT | wxRIGHT | wxTOP ) );
236
237 long style2 = 0;
238 if ( HasFdFlag(wxFD_MULTIPLE) )
239 style2 |= wxFC_MULTIPLE;
240
241 m_filectrl = new wxGenericFileCtrl( this, ID_FILE_CTRL,
242 m_dir, defaultFile,
243 wildCard,
244 style2,
245 wxDefaultPosition, wxSize(540,200)
246 );
247
248 m_filectrl->ShowHidden( ms_lastShowHidden );
249
250 if (ms_lastViewStyle == wxLC_LIST)
251 {
252 m_filectrl->ChangeToListMode();
253 }
254 else if (ms_lastViewStyle == wxLC_REPORT)
255 {
256 m_filectrl->ChangeToReportMode();
257 }
258
259 mainsizer->Add(m_filectrl, wxSizerFlags(1).Expand().HorzBorder());
260
261 wxSizer *bsizer = CreateButtonSizer(wxOK | wxCANCEL);
262 if ( bsizer )
263 {
264 if (is_pda)
265 mainsizer->Add(bsizer, wxSizerFlags().Expand().Border());
266 else
267 mainsizer->Add(bsizer, wxSizerFlags().Expand().DoubleBorder());
268 }
269
270 SetSizer( mainsizer );
271
272 if (!is_pda)
273 {
274 mainsizer->SetSizeHints( this );
275
276 Centre( wxBOTH );
277 }
278
279 return true;
280 }
281
282 wxGenericFileDialog::~wxGenericFileDialog()
283 {
284 if (!m_bypassGenericImpl)
285 {
286 #if wxUSE_CONFIG
287 if (wxConfig::Get(false))
288 {
289 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"),
290 ms_lastViewStyle);
291 wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"),
292 ms_lastShowHidden);
293 }
294 #endif
295 }
296 }
297
298 wxBitmapButton* wxGenericFileDialog::AddBitmapButton( wxWindowID winId,
299 const wxArtID& artId,
300 const wxString& tip,
301 wxSizer *sizer)
302 {
303 wxBitmapButton *but = new wxBitmapButton(this, winId,
304 wxArtProvider::GetBitmap(artId, wxART_BUTTON));
305 but->SetToolTip(tip);
306 sizer->Add(but, wxSizerFlags().Border());
307 return but;
308 }
309
310 int wxGenericFileDialog::ShowModal()
311 {
312 WX_TESTING_SHOW_MODAL_HOOK();
313
314 if (CreateExtraControl())
315 {
316 wxSizer *sizer = GetSizer();
317 sizer->Insert(2 /* after m_filectrl */, m_extraControl,
318 wxSizerFlags().Expand().HorzBorder());
319 sizer->Fit(this);
320 }
321
322 m_filectrl->SetDirectory(m_dir);
323
324 return wxDialog::ShowModal();
325 }
326
327 bool wxGenericFileDialog::Show( bool show )
328 {
329 // Called by ShowModal, so don't repeate the update
330 #ifndef __WIN32__
331 if (show)
332 {
333 m_filectrl->SetDirectory(m_dir);
334 }
335 #endif
336
337 return wxDialog::Show( show );
338 }
339
340 void wxGenericFileDialog::OnOk( wxCommandEvent &WXUNUSED(event) )
341 {
342 wxArrayString selectedFiles;
343 m_filectrl->GetFilenames(selectedFiles);
344
345 if (selectedFiles.Count() == 0)
346 return;
347
348 if (selectedFiles.Count() == 1)
349 {
350 SetPath( selectedFiles[0] );
351 }
352
353 EndModal(wxID_OK);
354 }
355
356 void wxGenericFileDialog::OnList( wxCommandEvent &WXUNUSED(event) )
357 {
358 m_filectrl->ChangeToListMode();
359 ms_lastViewStyle = wxLC_LIST;
360 m_filectrl->GetFileList()->SetFocus();
361 }
362
363 void wxGenericFileDialog::OnReport( wxCommandEvent &WXUNUSED(event) )
364 {
365 m_filectrl->ChangeToReportMode();
366 ms_lastViewStyle = wxLC_REPORT;
367 m_filectrl->GetFileList()->SetFocus();
368 }
369
370 void wxGenericFileDialog::OnUp( wxCommandEvent &WXUNUSED(event) )
371 {
372 m_filectrl->GoToParentDir();
373 m_filectrl->GetFileList()->SetFocus();
374 }
375
376 void wxGenericFileDialog::OnHome( wxCommandEvent &WXUNUSED(event) )
377 {
378 m_filectrl->GoToHomeDir();
379 m_filectrl->SetFocus();
380 }
381
382 void wxGenericFileDialog::OnNew( wxCommandEvent &WXUNUSED(event) )
383 {
384 m_filectrl->GetFileList()->MakeDir();
385 }
386
387 void wxGenericFileDialog::OnFileActivated( wxFileCtrlEvent &WXUNUSED(event) )
388 {
389 wxCommandEvent dummy;
390 OnOk( dummy );
391 }
392
393 void wxGenericFileDialog::OnUpdateButtonsUI(wxUpdateUIEvent& event)
394 {
395 // surprisingly, we can be called before m_filectrl is set in Create() as
396 // wxFileCtrl ctor itself can generate idle events, so we need this test
397 if ( m_filectrl )
398 event.Enable( !IsTopMostDir(m_filectrl->GetShownDirectory()) );
399 }
400
401 #ifdef wxHAS_GENERIC_FILEDIALOG
402
403 IMPLEMENT_DYNAMIC_CLASS(wxFileDialog, wxGenericFileDialog)
404
405 #endif // wxHAS_GENERIC_FILEDIALOG
406
407 #endif // wxUSE_FILEDLG