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