]> git.saurik.com Git - wxWidgets.git/blame - src/generic/dirdlgg.cpp
Added Property List classes to main library; added proplist sample; merged
[wxWidgets.git] / src / generic / dirdlgg.cpp
CommitLineData
d7a15103
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: dirdlg.cpp
3// Purpose: wxDirDialog
4// Author: Harm van der Heijden and Robert Roebling
5// Modified by:
6// Created: 12/12/98
7// Copyright: (c) Harm van der Heijden and Robert Roebling
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12#pragma implementation "dirdlgg.h"
13#endif
14
1e6d9499
JS
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19#pragma hdrstop
20#endif
21
d7a15103
JS
22#include "wx/defs.h"
23#include "wx/utils.h"
24#include "wx/dialog.h"
25#include "wx/button.h"
26#include "wx/layout.h"
27#include "wx/msgdlg.h"
28#include "wx/textdlg.h"
29#include "wx/filefn.h"
30#include "wx/cmndata.h"
31#include "wx/gdicmn.h"
32#include "wx/intl.h"
33#include "wx/imaglist.h"
34
35#include "wx/generic/dirdlgg.h"
36
37/* XPM */
38static char * icon1_xpm[] = {
39/* width height ncolors chars_per_pixel */
40"16 16 6 1",
41/* colors */
42" s None c None",
43". c #000000",
44"+ c #c0c0c0",
45"@ c #808080",
46"# c #ffff00",
47"$ c #ffffff",
48/* pixels */
49" ",
50" @@@@@ ",
51" @#+#+#@ ",
52" @#+#+#+#@@@@@@ ",
53" @$$$$$$$$$$$$@.",
54" @$#+#+#+#+#+#@.",
55" @$+#+#+#+#+#+@.",
56" @$#+#+#+#+#+#@.",
57" @$+#+#+#+#+#+@.",
58" @$#+#+#+#+#+#@.",
59" @$+#+#+#+#+#+@.",
60" @$#+#+#+#+#+#@.",
61" @@@@@@@@@@@@@@.",
62" ..............",
63" ",
64" "};
65
0659e7ee
RR
66/* XPM */
67static char * icon2_xpm[] = {
68/* width height ncolors chars_per_pixel */
69"16 16 6 1",
70/* colors */
71" s None c None",
72". c #000000",
73"+ c #c0c0c0",
74"@ c #808080",
75"# c #ffff00",
76"$ c #ffffff",
77/* pixels */
78" ",
79" @@@@@ ",
80" @$$$$$@ ",
81" @$#+#+#$@@@@@@ ",
82" @$+#+#+$$$$$$@.",
83" @$#+#+#+#+#+#@.",
84"@@@@@@@@@@@@@#@.",
85"@$$$$$$$$$$@@+@.",
86"@$#+#+#+#+##.@@.",
87" @$#+#+#+#+#+.@.",
88" @$+#+#+#+#+#.@.",
89" @$+#+#+#+##@..",
90" @@@@@@@@@@@@@.",
91" .............",
92" ",
93" "};
d7a15103
JS
94
95static const int ID_DIRCTRL = 1000;
96static const int ID_TEXTCTRL = 1001;
97static const int ID_OK = 1002;
98static const int ID_CANCEL = 1003;
99static const int ID_NEW = 1004;
100//static const int ID_CHECK = 1005;
101
102//-----------------------------------------------------------------------------
103// wxDirItemData
104//-----------------------------------------------------------------------------
105
0659e7ee
RR
106class wxDirItemData : public wxTreeItemData
107{
108public:
109 wxDirItemData(wxString& path, wxString& name);
110 ~wxDirItemData();
111 bool HasSubDirs();
112 wxString *m_path, *m_name;
113 bool m_isHidden;
114 bool m_hasSubDirs;
115};
116
117//-----------------------------------------------------------------------------
118// wxDirCtrl
119//-----------------------------------------------------------------------------
120
121class wxDirCtrl: public wxTreeCtrl
122{
123 DECLARE_DYNAMIC_CLASS(wxDirCtrl)
124
125 public:
126 bool m_showHidden;
127 wxTreeItemId m_rootId;
128
129 wxDirCtrl(void);
130 wxDirCtrl(wxWindow *parent, const wxWindowID id = -1,
131 const wxString &dir = "/",
132 const wxPoint& pos = wxDefaultPosition,
133 const wxSize& size = wxDefaultSize,
134 const long style = wxTR_HAS_BUTTONS,
135 const wxString& name = "wxTreeCtrl" );
1e6d9499
JS
136 void OnExpandItem(wxTreeEvent &event );
137 void OnCollapseItem(wxTreeEvent &event );
0659e7ee
RR
138 void ShowHidden( const bool yesno );
139 DECLARE_EVENT_TABLE()
140 protected:
141 void CreateItems(const wxTreeItemId &parent);
142 void SetupSections(void);
143 wxArrayString m_paths, m_names;
144};
145
146//-----------------------------------------------------------------------------
147// wxDirItemData
148//-----------------------------------------------------------------------------
149
d7a15103
JS
150wxDirItemData::wxDirItemData(wxString& path, wxString& name)
151{
152 m_path = new wxString(path);
153 m_name = new wxString(name);
154 /* Insert logic to detect hidden files here
155 * In UnixLand we just check whether the first char is a dot
156 * For FileNameFromPath read LastDirNameInThisPath ;-) */
157 // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.');
158 m_isHidden = FALSE;
159 m_hasSubDirs = HasSubDirs();
160}
161
162wxDirItemData:: ~wxDirItemData()
163{
164 delete m_path;
165 delete m_name;
166}
167
168bool wxDirItemData::HasSubDirs()
169{
170 wxString search = *m_path + "/*";
171 wxString path = wxFindFirstFile( search, wxDIR );
172 return (bool)(!path.IsNull());
173}
174
175//-----------------------------------------------------------------------------
176// wxDirCtrl
177//-----------------------------------------------------------------------------
178
179IMPLEMENT_DYNAMIC_CLASS(wxDirCtrl,wxTreeCtrl)
180
181BEGIN_EVENT_TABLE(wxDirCtrl,wxTreeCtrl)
182 EVT_TREE_ITEM_EXPANDING (-1, wxDirCtrl::OnExpandItem)
183 EVT_TREE_ITEM_COLLAPSED (-1, wxDirCtrl::OnCollapseItem)
184END_EVENT_TABLE()
185
186wxDirCtrl::wxDirCtrl(void)
187{
188 m_showHidden = FALSE;
189};
190
191wxDirCtrl::wxDirCtrl(wxWindow *parent, const wxWindowID id, const wxString &WXUNUSED(dir),
192 const wxPoint& pos, const wxSize& size,
193 const long style, const wxString& name )
194 :
195 wxTreeCtrl( parent, id, pos, size, style, wxDefaultValidator, name )
196{
197 m_imageListNormal = new wxImageList(16, 16, TRUE);
198 m_imageListNormal->Add(wxICON(icon1));
0659e7ee 199 m_imageListNormal->Add(wxICON(icon2));
d7a15103
JS
200 SetImageList(m_imageListNormal);
201
202 m_showHidden = FALSE;
203 m_rootId = AddRoot("Sections");
204 SetItemHasChildren(m_rootId);
205 Expand(m_rootId); // automatically expand first level
206};
207
208/* Quick macro. Don't worry, I'll #undef it later */
209#define ADD_SECTION(a,b) \
210 if (wxPathExists((a))) { m_paths.Add( (a) ); m_names.Add( (b) ); };
211
212void wxDirCtrl::SetupSections()
213{
214 wxString home;
215
216 m_paths.Clear();
217 m_names.Clear();
218 ADD_SECTION("/", _("The Computer") )
219 wxGetHomeDir(&home);
220 ADD_SECTION(home, _("My Home") )
221 ADD_SECTION("/mnt", _("Mounted Devices") )
222 ADD_SECTION("/usr", _("User") )
223 ADD_SECTION("/usr/local", _("User Local") )
224 ADD_SECTION("/var", _("Variables") )
225 ADD_SECTION("/etc", _("Etcetera") )
226 ADD_SECTION("/tmp", _("Temporary") )
227}
228#undef ADD_SECTION
229
230void wxDirCtrl::CreateItems(const wxTreeItemId &parent)
231{
232 wxTreeItemId id;
233 wxDirItemData *dir_item;
234
235// wxASSERT(m_paths.Count() == m_names.Count()); ?
236
237 for (unsigned int i=0; i<m_paths.Count(); i++)
238 {
239 dir_item = new wxDirItemData(m_paths[i],m_names[i]);
0659e7ee 240 id = AppendItem( parent, m_names[i], 0, 1, dir_item);
d7a15103
JS
241 if (dir_item->m_hasSubDirs) SetItemHasChildren(id);
242 }
243}
244
1e6d9499 245void wxDirCtrl::OnExpandItem(wxTreeEvent &event )
d7a15103
JS
246{
247 if (event.GetItem() == m_rootId)
248 {
249 SetupSections();
250 CreateItems(m_rootId);
251 return;
252 };
253
254 // This may take a longish time. Go to busy cursor
255 wxBeginBusyCursor();
256
257 wxDirItemData *data = (wxDirItemData *)GetItemData(event.GetItem());
258 wxASSERT(data);
259
260 wxString search,path,filename;
261
262 m_paths.Clear();
263 m_names.Clear();
264 search = *(data->m_path) + "/*";
265 for (path = wxFindFirstFile( search, wxDIR ); !path.IsNull();
266 path=wxFindNextFile() ) {
267 filename = wxFileNameFromPath( path );
268 /* Don't add "." and ".." to the tree. I think wxFindNextFile
269 * also checks this, but I don't quite understand what happens
270 * there. Also wxFindNextFile seems to swallow hidden dirs */
271 if ((filename != ".") && (filename != "..")) {
272 m_paths.Add(path);
273 m_names.Add(filename);
274 }
275 }
276 CreateItems(event.GetItem());
277 wxEndBusyCursor();
63852e78
RR
278
279 SortChildren( event.GetItem() );
d7a15103
JS
280};
281
282
1e6d9499 283void wxDirCtrl::OnCollapseItem(wxTreeEvent &event )
d7a15103
JS
284{
285 wxTreeItemId child, parent = event.GetItem();
286 long cookie;
287 /* Workaround because DeleteChildren has disapeared (why?) and
288 * CollapseAndReset doesn't work as advertised (deletes parent too) */
289 child = GetFirstChild(parent, cookie);
290 while (child.IsOk()) {
291 Delete(child);
292 /* Not GetNextChild below, because the cookie mechanism can't
293 * handle disappearing children! */
294 child = GetFirstChild(parent, cookie);
295 }
296};
297
298//-----------------------------------------------------------------------------
299// wxDirDialog
300//-----------------------------------------------------------------------------
301
302
303#if !USE_SHARED_LIBRARY
304IMPLEMENT_CLASS(wxDirDialog, wxDialog)
305#else
306IMPLEMENT_DYNAMIC_CLASS( wxDirDialog, wxDialog )
307#endif
308
309BEGIN_EVENT_TABLE( wxDirDialog, wxDialog )
310 EVT_TREE_KEY_DOWN (ID_DIRCTRL, wxDirDialog::OnTreeKeyDown)
311 EVT_TREE_SEL_CHANGED (ID_DIRCTRL, wxDirDialog::OnTreeSelected)
312 EVT_SIZE ( wxDirDialog::OnSize)
313 EVT_BUTTON (ID_OK, wxDirDialog::OnOK)
314 EVT_BUTTON (ID_CANCEL, wxDirDialog::OnCancel)
315 EVT_BUTTON (ID_NEW, wxDirDialog::OnNew)
316 EVT_TEXT_ENTER (ID_TEXTCTRL, wxDirDialog::OnOK)
317 // EVT_CHECKBOX (ID_CHECK, wxDirDialog::OnCheck)
318END_EVENT_TABLE()
319
320wxDirDialog::wxDirDialog(wxWindow *parent, const wxString& message,
321 const wxString& defaultPath, long style,
322 const wxPoint& pos) :
323 wxDialog(parent, -1, message, pos, wxSize(300,300),
324 wxDEFAULT_DIALOG_STYLE|wxDIALOG_MODAL)
325{
326 m_message = message;
327 m_dialogStyle = style;
328 m_parent = parent;
329
330 m_path = defaultPath;
331
332 m_dir = new wxDirCtrl( this, ID_DIRCTRL, "/", wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxSUNKEN_BORDER );
333 m_input = new wxTextCtrl( this, ID_TEXTCTRL, m_path, wxDefaultPosition );
334 // m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden") );
335 m_ok = new wxButton( this, ID_OK, _("OK") );
336 m_cancel = new wxButton( this, ID_CANCEL, _("Cancel") );
337 m_new = new wxButton( this, ID_NEW, _("New...") );
338
339 // m_check->SetValue(TRUE);
340 m_ok->SetDefault();
341 m_dir->SetFocus();
342
343 doSize();
344}
345
346void wxDirDialog::OnSize(wxSizeEvent& WXUNUSED(event))
347{
348 doSize();
349}
350
351void wxDirDialog::doSize()
352{
353 /* Figure out height of DirCtrl, which is what is left over by
354 * the textctrl and the buttons. Manually, because I can't seem
355 * to get the constraints stuff to do this */
356 int w,h,h2;
357
358 GetClientSize(&w, &h);
359 m_input->GetSize(&w,&h2); h -= h2;
360 m_ok->GetSize(&w, &h2); h -= h2;
361 //m_check->GetSize(&w, &h2); h -= h2;
362 h -= 20;
363
364 wxLayoutConstraints *c = new wxLayoutConstraints;
365 c->left.SameAs (this, wxLeft,5);
366 c->right.SameAs (this, wxRight,5);
367 c->height.Absolute (h);
368 c->top.SameAs (this, wxTop,5);
369 m_dir->SetConstraints(c);
370
371 c = new wxLayoutConstraints;
372 c->left.SameAs (this, wxLeft,5);
373 c->right.SameAs (this, wxRight,5);
374 c->height.AsIs ();
375 c->top.Below (m_dir,5);
376 m_input->SetConstraints(c);
377
378 /* c = new wxLayoutConstraints;
379 c->left.SameAs (this, wxLeft,5);
380 c->right.SameAs (this, wxRight,5);
381 c->height.AsIs ();
382 c->top.Below (m_input,5);
383 m_check->SetConstraints(c); */
384
385 c = new wxLayoutConstraints;
386 c->width.SameAs (m_cancel, wxWidth);
387 c->height.AsIs ();
388 c->top.Below (m_input,5);
389 c->centreX.PercentOf (this, wxWidth, 25);
390 m_ok->SetConstraints(c);
391
392 c = new wxLayoutConstraints;
393 c->width.SameAs (m_cancel, wxWidth);
394 c->height.AsIs ();
395 c->top.Below (m_input,5);
396 c->bottom.SameAs (this, wxBottom, 5);
397 c->centreX.PercentOf (this, wxWidth, 50);
398 m_new->SetConstraints(c);
399
400 c = new wxLayoutConstraints;
401 c->width.AsIs ();
402 c->height.AsIs ();
403 c->top.Below (m_input,5);
404 c->centreX.PercentOf (this, wxWidth, 75);
405 m_cancel->SetConstraints(c);
406
407 Layout();
408}
409
410int wxDirDialog::ShowModal()
411{
412 m_input->SetValue( m_path );
413 return wxDialog::ShowModal();
414}
415
416void wxDirDialog::OnTreeSelected( wxTreeEvent &event )
417{
418 wxDirItemData *data =
419 (wxDirItemData*)m_dir->GetItemData(event.GetItem());
420 if (data)
421 m_input->SetValue( *(data->m_path) );
422};
423
1e6d9499 424void wxDirDialog::OnTreeKeyDown( wxTreeEvent &WXUNUSED(event) )
d7a15103
JS
425{
426 wxDirItemData *data =
427 (wxDirItemData*)m_dir->GetItemData(m_dir->GetSelection());
428 if (data)
429 m_input->SetValue( *(data->m_path) );
430};
431
432void wxDirDialog::OnOK( wxCommandEvent& WXUNUSED(event) )
433{
434 m_path = m_input->GetValue();
435 // Does the path exist? (User may have typed anything in m_input)
436 if (wxPathExists(m_path)) {
437 // OK, path exists, we're done.
438 EndModal(wxID_OK);
439 return;
440 }
441 // Interact with user, find out if the dir is a typo or to be created
442 wxString msg( _("The directory ") );
443 msg = msg + m_path;
444 msg = msg + _("\ndoes not exist\nCreate it now?") ;
445 wxMessageDialog dialog(this, msg, _("Directory does not exist"), wxYES_NO);
446 if ( dialog.ShowModal() == wxID_YES ) {
447 // Okay, let's make it
448 if (wxMkdir(m_path)) {
449 // The new dir was created okay.
450 EndModal(wxID_OK);
451 return;
452 }
453 else {
454 // Trouble...
455 msg = _("Failed to create directory ")+m_path+
456 _("\n(Do you have the required permissions?)");
457 wxMessageDialog errmsg(this, msg, _("Error creating directory"), wxOK);
458 errmsg.ShowModal();
459 // We still don't have a valid dir. Back to the main dialog.
460 }
461 }
462 // User has answered NO to create dir.
463}
464
465void wxDirDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
466{
467 EndModal(wxID_CANCEL);
468}
469
470void wxDirDialog::OnNew( wxCommandEvent& WXUNUSED(event) )
471{
472 wxTextEntryDialog dialog(this, _("Enter the name of the directory to create"),
473 _("Create New Directory"), m_input->GetValue(), wxOK|wxCANCEL);
474
475 while (dialog.ShowModal() == wxID_OK)
476 {
477 // Okay, let's make it
478 if (wxMkdir(dialog.GetValue())) {
479 // The new dir was created okay.
480 m_path = dialog.GetValue();
481 return;
482 }
483 wxString msg = _("Failed to create directory ")+dialog.GetValue()+
484 _("\n(Do you have the required permissions?)") ;
485 wxMessageDialog errmsg(this, msg, _("Error creating directory"), wxOK);
486 errmsg.ShowModal();
487 // Show the create dialog again, until user clicks cancel or enters
488 // a valid dir.
489 }
490}
491
492/*
493void wxDirDialog::OnCheck( wxCommandEvent& WXUNUSED(event) )
494{
495 printf("Checkbox clicked: %s\n", ( m_check->GetValue() ? "on" : "off" ) );
496}
497*/