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