]> git.saurik.com Git - wxWidgets.git/blame - src/generic/dirctrlg.cpp
Corrected (maybe) the object.h token syntax; corrected typo in makefile.g95
[wxWidgets.git] / src / generic / dirctrlg.cpp
CommitLineData
51a58d8b
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: dirctrlg.cpp
3// Purpose: wxGenericDirCtrl
4// Author: Harm van der Heijden, Robert Roebling, Julian Smart
5// Modified by:
6// Created: 12/12/98
7// RCS-ID: $Id$
8// Copyright: (c) Harm van der Heijden, Robert Roebling and Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
3fa4bd0e 13#pragma implementation "dirctrlg.h"
51a58d8b
JS
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
1e6feb95 23#if wxUSE_DIRDLG
51a58d8b
JS
24
25#include "wx/utils.h"
26#include "wx/dialog.h"
27#include "wx/button.h"
28#include "wx/layout.h"
29#include "wx/msgdlg.h"
618a5e38 30#include "wx/textctrl.h"
51a58d8b
JS
31#include "wx/textdlg.h"
32#include "wx/filefn.h"
33#include "wx/cmndata.h"
34#include "wx/gdicmn.h"
35#include "wx/intl.h"
36#include "wx/imaglist.h"
37#include "wx/icon.h"
38#include "wx/log.h"
39#include "wx/sizer.h"
40#include "wx/tokenzr.h"
41#include "wx/dir.h"
3fa4bd0e 42#include "wx/settings.h"
51a58d8b
JS
43
44#if wxUSE_STATLINE
45 #include "wx/statline.h"
46#endif
47
48#include "wx/generic/dirctrlg.h"
49
50#ifdef __WXMSW__
2736b3ce 51#include <windows.h>
7328394a 52
c9ecda60
VS
53// FIXME - Mingw32 1.0 has both _getdrive() and _chdrive(). For now, let's assume
54// older releases don't, but it should be verified and the checks modified
55// accordingly.
56#if !defined(__GNUWIN32__) || \
57 (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
58 #include <direct.h>
59 #include <stdlib.h>
60 #include <ctype.h>
51a58d8b
JS
61#endif
62
7328394a
JS
63#endif
64
ec1b28a3
DW
65#ifdef __WXPM__
66
67#define INCL_BASE
68#include <os2.h>
69#include <direct.h>
70#include <stdlib.h>
71#include <ctype.h>
72
73#endif // __WXPM__
74
f4ac0693
GD
75#if defined(__WXMAC__)
76# include "MoreFilesExtras.h"
bedaf53e
SC
77#endif
78
267a7108
JS
79#ifdef __BORLANDC__
80#include "dos.h"
81#endif
82
51a58d8b
JS
83// If compiled under Windows, this macro can cause problems
84#ifdef GetFirstChild
85#undef GetFirstChild
86#endif
87
51a58d8b
JS
88/* Closed folder */
89static char * icon1_xpm[] = {
90/* width height ncolors chars_per_pixel */
91"16 16 6 1",
92/* colors */
93" s None c None",
94". c #000000",
95"+ c #c0c0c0",
96"@ c #808080",
97"# c #ffff00",
98"$ c #ffffff",
99/* pixels */
100" ",
101" @@@@@ ",
102" @#+#+#@ ",
103" @#+#+#+#@@@@@@ ",
104" @$$$$$$$$$$$$@.",
105" @$#+#+#+#+#+#@.",
106" @$+#+#+#+#+#+@.",
107" @$#+#+#+#+#+#@.",
108" @$+#+#+#+#+#+@.",
109" @$#+#+#+#+#+#@.",
110" @$+#+#+#+#+#+@.",
111" @$#+#+#+#+#+#@.",
112" @@@@@@@@@@@@@@.",
113" ..............",
114" ",
115" "};
116
117/* Open folder */
118static char * icon2_xpm[] = {
119/* width height ncolors chars_per_pixel */
120"16 16 6 1",
121/* colors */
122" s None c None",
123". c #000000",
124"+ c #c0c0c0",
125"@ c #808080",
126"# c #ffff00",
127"$ c #ffffff",
128/* pixels */
129" ",
130" @@@@@ ",
131" @$$$$$@ ",
132" @$#+#+#$@@@@@@ ",
133" @$+#+#+$$$$$$@.",
134" @$#+#+#+#+#+#@.",
135"@@@@@@@@@@@@@#@.",
136"@$$$$$$$$$$@@+@.",
137"@$#+#+#+#+##.@@.",
138" @$#+#+#+#+#+.@.",
139" @$+#+#+#+#+#.@.",
140" @$+#+#+#+##@..",
141" @@@@@@@@@@@@@.",
142" .............",
143" ",
144" "};
145
146/* File */
147static char * icon3_xpm[] = {
148/* width height ncolors chars_per_pixel */
149"16 16 3 1",
150/* colors */
33fed835
MB
151" s None c None",
152". c #000000",
153"+ c #ffffff",
51a58d8b
JS
154/* pixels */
155" ",
156" ........ ",
157" .++++++.. ",
158" .+.+.++.+. ",
159" .++++++.... ",
160" .+.+.+++++. ",
161" .+++++++++. ",
162" .+.+.+.+.+. ",
163" .+++++++++. ",
164" .+.+.+.+.+. ",
165" .+++++++++. ",
166" .+.+.+.+.+. ",
167" .+++++++++. ",
168" ........... ",
169" ",
170" "};
171
172/* Computer */
173static char * icon4_xpm[] = {
174"16 16 7 1",
33fed835
MB
175" s None c None",
176". c #808080",
177"X c #c0c0c0",
178"o c Black",
179"O c Gray100",
180"+ c #008080",
181"@ c Blue",
51a58d8b
JS
182" ........... ",
183" .XXXXXXXXXX.o",
184" .OOOOOOOOO..o",
185" .OoooooooX..o",
186" .Oo+...@+X..o",
187" .Oo+XXX.+X..o",
188" .Oo+....+X..o",
189" .Oo++++++X..o",
190" .OXXXXXXXX.oo",
191" ..........o.o",
192" ...........Xo",
193" .XXXXXXXXXX.o",
194" .o.o.o.o.o...o",
195" .oXoXoXoXoXo.o ",
196".XOXXXXXXXXX.o ",
197"............o "};
198
199/* Drive */
200static char * icon5_xpm[] = {
201"16 16 7 1",
33fed835
MB
202" s None c None",
203". c #808080",
204"X c #c0c0c0",
205"o c Black",
206"O c Gray100",
207"+ c Green",
208"@ c #008000",
51a58d8b
JS
209" ",
210" ",
211" ",
212" ",
213" ............. ",
214" .XXXXXXXXXXXX.o",
215".OOOOOOOOOOOO..o",
216".XXXXXXXXX+@X..o",
217".XXXXXXXXXXXX..o",
218".X..........X..o",
219".XOOOOOOOOOOX..o",
220"..............o ",
221" ooooooooooooo ",
222" ",
223" ",
224" "};
225
226/* CD-ROM */
227static char *icon6_xpm[] = {
228"16 16 10 1",
33fed835
MB
229" s None c None",
230". c #808080",
231"X c #c0c0c0",
232"o c Yellow",
233"O c Blue",
234"+ c Black",
235"@ c Gray100",
236"# c #008080",
237"$ c Green",
238"% c #008000",
51a58d8b
JS
239" ... ",
240" ..XoX.. ",
241" .O.XoXXX+ ",
242" ...O.oXXXX+ ",
243" .O..X.XXXX+ ",
244" ....X.+..XXX+",
245" .XXX.+@+.XXX+",
246" .X@XX.+.X@@X+",
247" .....X...#XX@+ ",
248".@@@...XXo.O@X+ ",
249".@XXX..XXoXOO+ ",
250".@++++..XoX+++ ",
251".@$%@@XX+++X.+ ",
252".............+ ",
253" ++++++++++++ ",
254" "};
255
256/* Floppy */
257static char * icon7_xpm[] = {
258"16 16 7 1",
33fed835
MB
259" s None c None",
260". c #808080",
261"X c Gray100",
262"o c #c0c0c0",
263"O c Black",
264"+ c Cyan",
265"@ c Red",
51a58d8b
JS
266" ......X",
267" .ooooooO",
268" .+++++OO",
269" .++++++O",
270" .++++++O",
271" .ooooooO",
272" .......o....oO",
273" .oooooo.o.O.XoO",
274".XXXXXXXXOOOOOO ",
275".ooooooooo@o..O ",
276".ooo....oooo..O ",
277".o..OOOO...o..O ",
278".oooXXXXoooo..O ",
279".............O ",
280" OOOOOOOOOOOO ",
281" "};
282
283/* Removeable */
284static char * icon8_xpm[] = {
285"16 16 7 1",
33fed835
MB
286" s None c None",
287". c #808080",
288"X c #c0c0c0",
289"o c Black",
290"O c Gray100",
291"+ c Red",
292"@ c #800000",
51a58d8b
JS
293" ",
294" ",
295" ",
296" ............. ",
297" .XXXXXXXXXXXX.o",
298".OOOOOOOOOOOO..o",
299".OXXXXXXXXXXX..o",
300".O+@.oooooo.X..o",
301".OXXOooooooOX..o",
302".OXXXOOOOOOXX..o",
303".OXXXXXXXXXXX..o",
304".O............o ",
305" ooooooooooooo ",
306" ",
307" ",
308" "};
51a58d8b
JS
309
310static const int ID_DIRCTRL = 1000;
311static const int ID_TEXTCTRL = 1001;
312static const int ID_OK = 1002;
313static const int ID_CANCEL = 1003;
314static const int ID_NEW = 1004;
315//static const int ID_CHECK = 1005;
316
c9ecda60 317#if defined(__WXMSW__) || defined(__WXPM__) || defined(__DOS__)
33ac7e6f
KB
318int setdrive(int drive)
319{
c9ecda60
VS
320#if defined(__GNUWIN32__) && \
321 (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
322 return _chdrive(drive);
323#else
e987a489 324 wxChar newdrive[3];
33ac7e6f
KB
325
326 if (drive < 1 || drive > 31)
327 return -1;
e987a489
VS
328 newdrive[0] = (wxChar)(wxT('A') + drive - 1);
329 newdrive[1] = wxT(':');
330 newdrive[2] = wxT('\0');
50c76ce1 331#if defined(__WXMSW__)
788722ac
JS
332#ifdef __WIN16__
333 if (wxSetWorkingDirectory(newdrive))
334#else
e987a489 335 if (::SetCurrentDirectory(newdrive))
788722ac 336#endif
50c76ce1
DW
337#else
338 // VA doesn't know what LPSTR is and has its own set
339 if (DosSetCurrentDir((PSZ)newdrive))
340#endif
33ac7e6f
KB
341 return 0;
342 else
343 return -1;
c9ecda60 344#endif // !GNUWIN32
33ac7e6f
KB
345}
346
ad9cd15c
JS
347static bool wxIsDriveAvailable(const wxString dirName)
348{
349#ifdef __WIN32__
33fed835 350 UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
ad9cd15c 351#endif
33fed835 352 bool success = TRUE;
ad9cd15c
JS
353
354 // Check if this is a root directory and if so,
355 // whether the drive is avaiable.
33fed835 356 if (dirName.Len() == 3 && dirName[(size_t)1] == wxT(':'))
ad9cd15c 357 {
33fed835 358 wxString dirNameLower(dirName.Lower());
c9ecda60
VS
359#if defined(__GNUWIN32__) && \
360 !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
7328394a
JS
361 success = wxPathExists(dirNameLower);
362#else
ad9cd15c 363 int currentDrive = _getdrive();
33fed835 364 int thisDrive = (int) (dirNameLower[(size_t)0] - 'a' + 1) ;
33ac7e6f
KB
365 int err = setdrive( thisDrive ) ;
366 setdrive( currentDrive );
ad9cd15c
JS
367
368 if (err == -1)
369 {
370 success = FALSE;
371 }
7328394a 372#endif
ad9cd15c
JS
373 }
374#ifdef __WIN32__
33fed835 375 (void) SetErrorMode(errorMode);
ad9cd15c
JS
376#endif
377
33fed835 378 return success;
ad9cd15c
JS
379}
380#endif
381
57e26a09
JS
382// Function which is called by quick sort. We want to override the default wxArrayString behaviour,
383// and sort regardless of case.
384static int LINKAGEMODE wxDirCtrlStringCompareFunction(const void *first, const void *second)
385{
386 wxString *strFirst = (wxString *)first;
387 wxString *strSecond = (wxString *)second;
388
389 return strFirst->CmpNoCase(*strSecond);
390}
391
51a58d8b
JS
392//-----------------------------------------------------------------------------
393// wxDirItemDataEx
394//-----------------------------------------------------------------------------
395
396wxDirItemDataEx::wxDirItemDataEx(const wxString& path, const wxString& name,
397 bool isDir)
398{
399 m_path = path;
400 m_name = name;
401 /* Insert logic to detect hidden files here
402 * In UnixLand we just check whether the first char is a dot
403 * For FileNameFromPath read LastDirNameInThisPath ;-) */
404 // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.');
405 m_isHidden = FALSE;
e63fdcd6
JS
406 // m_hasSubDirs is no longer needed
407 m_hasSubDirs = TRUE; // HasSubDirs();
51a58d8b
JS
408 m_isExpanded = FALSE;
409 m_isDir = isDir;
410}
411
412wxDirItemDataEx::~wxDirItemDataEx()
413{
414}
415
416void wxDirItemDataEx::SetNewDirName( wxString path )
417{
418 m_path = path;
419 m_name = wxFileNameFromPath( path );
420}
421
51a58d8b
JS
422//-----------------------------------------------------------------------------
423// wxGenericDirCtrl
424//-----------------------------------------------------------------------------
425
426IMPLEMENT_DYNAMIC_CLASS(wxGenericDirCtrl, wxControl)
427
428BEGIN_EVENT_TABLE(wxGenericDirCtrl, wxControl)
429 EVT_TREE_ITEM_EXPANDING (-1, wxGenericDirCtrl::OnExpandItem)
430 EVT_TREE_ITEM_COLLAPSED (-1, wxGenericDirCtrl::OnCollapseItem)
431 EVT_TREE_BEGIN_LABEL_EDIT (-1, wxGenericDirCtrl::OnBeginEditItem)
432 EVT_TREE_END_LABEL_EDIT (-1, wxGenericDirCtrl::OnEndEditItem)
433 EVT_SIZE (wxGenericDirCtrl::OnSize)
434END_EVENT_TABLE()
435
436wxGenericDirCtrl::wxGenericDirCtrl(void)
437{
438 Init();
439}
440
441bool wxGenericDirCtrl::Create(wxWindow *parent,
442 const wxWindowID id,
443 const wxString& dir,
444 const wxPoint& pos,
445 const wxSize& size,
446 long style,
447 const wxString& filter,
448 int defaultFilter,
449 const wxString& name )
450{
451 if (!wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name))
452 return FALSE;
453
454 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
455
456 Init();
457
3438012b 458 long treeStyle = wxTR_HAS_BUTTONS ; // | wxTR_EDIT_LABELS;
51a58d8b
JS
459 if ((style & wxDIRCTRL_3D_INTERNAL) == 0)
460 treeStyle |= wxNO_BORDER;
461
462 long filterStyle = 0;
463 if ((style & wxDIRCTRL_3D_INTERNAL) == 0)
464 filterStyle |= wxNO_BORDER;
465
466 m_treeCtrl = new wxTreeCtrl(this, wxID_TREECTRL, pos, size, treeStyle);
467
468 if (!filter.IsEmpty() && (style & wxDIRCTRL_SHOW_FILTERS))
469 m_filterListCtrl = new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL, wxDefaultPosition, wxDefaultSize, filterStyle);
470
471 m_defaultPath = dir;
472 m_filter = filter;
473
474 SetFilterIndex(defaultFilter);
475
476 if (m_filterListCtrl)
477 m_filterListCtrl->FillFilterList(filter, defaultFilter);
478
479 m_imageList = new wxImageList(16, 16, TRUE);
51a58d8b
JS
480 m_imageList->Add(wxIcon(icon1_xpm));
481 m_imageList->Add(wxIcon(icon2_xpm));
482 m_imageList->Add(wxIcon(icon3_xpm));
483 m_imageList->Add(wxIcon(icon4_xpm));
484 m_imageList->Add(wxIcon(icon5_xpm));
485 m_imageList->Add(wxIcon(icon6_xpm));
486 m_imageList->Add(wxIcon(icon7_xpm));
487 m_imageList->Add(wxIcon(icon8_xpm));
51a58d8b
JS
488 m_treeCtrl->SetImageList(m_imageList);
489
490 m_showHidden = FALSE;
491 wxDirItemDataEx* rootData = new wxDirItemDataEx(wxT(""), wxT(""), TRUE);
492
493 wxString rootName;
494
ec1b28a3 495#if defined(__WXMSW__) || defined(__WXPM__)
51a58d8b
JS
496 rootName = _("Computer");
497#else
498 rootName = _("Sections");
499#endif
500
501 m_rootId = m_treeCtrl->AddRoot( rootName, 3, -1, rootData);
502 m_treeCtrl->SetItemHasChildren(m_rootId);
503 m_treeCtrl->Expand(m_rootId); // automatically expand first level
504
505 // Expand and select the default path
506 if (!m_defaultPath.IsEmpty())
507 ExpandPath(m_defaultPath);
508
509 DoResize();
510
511 return TRUE;
512}
513
514wxGenericDirCtrl::~wxGenericDirCtrl()
515{
516 m_treeCtrl->SetImageList(NULL);
517 delete m_imageList;
518}
519
520void wxGenericDirCtrl::Init()
521{
522 m_showHidden = FALSE;
523 m_imageList = NULL;
51a58d8b
JS
524 m_currentFilter = 0;
525 m_currentFilterStr = wxEmptyString; // Default: any file
526 m_treeCtrl = NULL;
527 m_filterListCtrl = NULL;
528}
529
530void wxGenericDirCtrl::AddSection(const wxString& path, const wxString& name, int imageId)
531{
532 wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,name,TRUE);
533
ec1b28a3
DW
534#if defined(__WXMSW__) || defined(__WXPM__)
535 // Windows and OS/2: sections are displayed as drives
51a58d8b
JS
536 wxTreeItemId id = m_treeCtrl->AppendItem( m_rootId, name, imageId, -1, dir_item);
537#else
538 // Unix: sections are displayed as folders
539 wxTreeItemId id = m_treeCtrl->AppendItem( m_rootId, name, 0, -1, dir_item);
3fa4bd0e 540 m_treeCtrl->SetItemImage( id, 1, wxTreeItemIcon_Expanded );
51a58d8b
JS
541#endif
542 // TODO: other operating systems.
543
544 m_treeCtrl->SetItemHasChildren(id);
545}
546
547void wxGenericDirCtrl::SetupSections()
548{
ec1b28a3 549#if defined(__WXMSW__) || defined(__WXPM__)
51a58d8b 550
a044cb72 551# ifdef __WIN32__
51a58d8b
JS
552 wxChar driveBuffer[256];
553 size_t n = (size_t) GetLogicalDriveStrings(255, driveBuffer);
554 size_t i = 0;
555 while (i < n)
556 {
557 wxString path, name;
558 path.Printf(wxT("%c:\\"), driveBuffer[i]);
559 name.Printf(wxT("(%c:)"), driveBuffer[i]);
560
561 int imageId = 4;
562 int driveType = ::GetDriveType(path);
563 switch (driveType)
564 {
565 case DRIVE_REMOVABLE:
566 if (path == wxT("a:\\") || path == wxT("b:\\"))
567 imageId = 6; // Floppy
568 else
569 imageId = 7;
570 break;
571 case DRIVE_FIXED:
572 imageId = 4;
573 break;
574 case DRIVE_REMOTE:
575 imageId = 4;
576 break;
577 case DRIVE_CDROM:
578 imageId = 5;
579 break;
580 default:
581 imageId = 4;
582 break;
583 }
584
585 AddSection(path, name, imageId);
586
587 while (driveBuffer[i] != wxT('\0'))
588 i ++;
589 i ++;
590 if (driveBuffer[i] == wxT('\0'))
591 break;
592 }
a044cb72 593# else
51a58d8b
JS
594 int drive;
595 int currentDrive;
596
51a58d8b
JS
597 /* If we can switch to the drive, it exists. */
598 for( drive = 1; drive <= 26; drive++ )
599 {
600 wxString path, name;
601 path.Printf(wxT("%c:\\"), (char) (drive + 'a' - 1));
602 name.Printf(wxT("(%c:)"), (char) (drive + 'a' - 1));
603
33fed835 604 if (wxIsDriveAvailable(path))
51a58d8b 605 {
ec1b28a3 606
51a58d8b
JS
607 AddSection(path, name);
608 }
609 }
a044cb72 610# endif
f4ac0693 611#elif defined(__WXMAC__)
bedaf53e
SC
612 FSSpec volume ;
613 short index = 1 ;
614 while(1) {
615 short actualCount = 0 ;
616 if ( OnLine( &volume , 1 , &actualCount , &index ) != noErr || actualCount == 0 )
617 break ;
618
619 wxString name = wxMacFSSpec2MacFilename( &volume ) ;
a044cb72 620 AddSection(name + wxFILE_SEP_PATH, name, 0);
bedaf53e 621 }
51a58d8b 622#else
3fa4bd0e
VS
623 AddSection(wxT("/"), _("The Computer"), 0);
624 AddSection(wxGetHomeDir(), _("My Home"), 0 );
625 AddSection(wxT("/mnt"), _("Mounted Devices"), 0 );
626 AddSection(wxT("/usr/local"), _("User Local"), 0 );
627 AddSection(wxT("/usr"), _("User"), 0 );
628 AddSection(wxT("/var"), _("Variables"), 0 );
629 AddSection(wxT("/etc"), _("Etcetera"), 0 );
630 AddSection(wxT("/tmp"), _("Temporary"), 0 );
51a58d8b
JS
631#endif
632}
633
634void wxGenericDirCtrl::OnBeginEditItem(wxTreeEvent &event)
635{
636 // don't rename the main entry "Sections"
637 if (event.GetItem() == m_rootId)
638 {
639 event.Veto();
640 return;
641 }
642
643 // don't rename the individual sections
644 if (m_treeCtrl->GetParent( event.GetItem() ) == m_rootId)
645 {
646 event.Veto();
647 return;
648 }
649}
650
651void wxGenericDirCtrl::OnEndEditItem(wxTreeEvent &event)
652{
653 if ((event.GetLabel().IsEmpty()) ||
654 (event.GetLabel() == _(".")) ||
655 (event.GetLabel() == _("..")) ||
656 (event.GetLabel().First( wxT("/") ) != wxNOT_FOUND))
657 {
658 wxMessageDialog dialog(this, _("Illegal directory name."), _("Error"), wxOK | wxICON_ERROR );
659 dialog.ShowModal();
660 event.Veto();
661 return;
662 }
663
664 wxTreeItemId id = event.GetItem();
665 wxDirItemDataEx *data = (wxDirItemDataEx*)m_treeCtrl->GetItemData( id );
666 wxASSERT( data );
667
668 wxString new_name( wxPathOnly( data->m_path ) );
ad9cd15c 669 new_name += wxString(wxFILE_SEP_PATH);
51a58d8b
JS
670 new_name += event.GetLabel();
671
672 wxLogNull log;
673
674 if (wxFileExists(new_name))
675 {
676 wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR );
677 dialog.ShowModal();
678 event.Veto();
679 }
680
681 if (wxRenameFile(data->m_path,new_name))
682 {
683 data->SetNewDirName( new_name );
684 }
685 else
686 {
687 wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
688 dialog.ShowModal();
689 event.Veto();
690 }
691}
692
693void wxGenericDirCtrl::OnExpandItem(wxTreeEvent &event)
694{
695 wxTreeItemId parentId = event.GetItem();
696
697 ExpandDir(parentId);
698}
699
700void wxGenericDirCtrl::OnCollapseItem(wxTreeEvent &event )
701{
702 wxTreeItemId child, parent = event.GetItem();
703
704 wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(event.GetItem());
705 if (!data->m_isExpanded)
706 return;
707
708 data->m_isExpanded = FALSE;
709 long cookie;
710 /* Workaround because DeleteChildren has disapeared (why?) and
711 * CollapseAndReset doesn't work as advertised (deletes parent too) */
712 child = m_treeCtrl->GetFirstChild(parent, cookie);
713 while (child.IsOk())
714 {
715 m_treeCtrl->Delete(child);
716 /* Not GetNextChild below, because the cookie mechanism can't
717 * handle disappearing children! */
718 child = m_treeCtrl->GetFirstChild(parent, cookie);
719 }
720}
721
722void wxGenericDirCtrl::ExpandDir(wxTreeItemId parentId)
723{
724 wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(parentId);
725
726 if (data->m_isExpanded)
727 return;
728
729 data->m_isExpanded = TRUE;
730
731 if (parentId == m_rootId)
732 {
733 SetupSections();
734 return;
735 }
736
737 wxASSERT(data);
738
739 wxString search,path,filename;
740
741 wxString dirName(data->m_path);
742
ec1b28a3 743#if defined(__WXMSW__) || defined(__WXPM__)
51a58d8b
JS
744 // Check if this is a root directory and if so,
745 // whether the drive is avaiable.
33fed835
MB
746 if (!wxIsDriveAvailable(dirName))
747 {
ad9cd15c 748 data->m_isExpanded = FALSE;
7328394a
JS
749 //wxMessageBox(wxT("Sorry, this drive is not available."));
750 return;
33fed835 751 }
51a58d8b
JS
752#endif
753
754 // This may take a longish time. Go to busy cursor
755 wxBusyCursor busy;
756
ec1b28a3 757#if defined(__WXMSW__) || defined(__WXPM__)
51a58d8b
JS
758 if (dirName.Last() == ':')
759 dirName += wxString(wxFILE_SEP_PATH);
760#endif
761
762 wxArrayString dirs;
763 wxArrayString filenames;
764
765 wxDir d;
766 wxString eachFilename;
767
f9c165b1 768 wxLogNull log;
51a58d8b
JS
769 d.Open(dirName);
770
771 if (d.IsOpened())
772 {
773 if (d.GetFirst(& eachFilename, wxEmptyString, wxDIR_DIRS))
774 {
775 do
776 {
777 if ((eachFilename != wxT(".")) && (eachFilename != wxT("..")))
778 {
779 dirs.Add(eachFilename);
780 }
781 }
782 while (d.GetNext(& eachFilename)) ;
783 }
784 }
57e26a09 785 dirs.Sort((wxArrayString::CompareFunction) wxDirCtrlStringCompareFunction);
51a58d8b
JS
786
787 // Now do the filenames -- but only if we're allowed to
788 if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY) == 0)
789 {
f9c165b1
JS
790 wxLogNull log;
791
51a58d8b 792 d.Open(dirName);
ec1b28a3 793
51a58d8b
JS
794 if (d.IsOpened())
795 {
796 if (d.GetFirst(& eachFilename, m_currentFilterStr, wxDIR_FILES))
797 {
798 do
799 {
800 if ((eachFilename != wxT(".")) && (eachFilename != wxT("..")))
801 {
802 filenames.Add(eachFilename);
803 }
804 }
805 while (d.GetNext(& eachFilename)) ;
806 }
807 }
57e26a09 808 filenames.Sort((wxArrayString::CompareFunction) wxDirCtrlStringCompareFunction);
51a58d8b
JS
809 }
810
811 // Add the sorted dirs
812 size_t i;
813 for (i = 0; i < dirs.Count(); i++)
814 {
815 wxString eachFilename(dirs[i]);
816 path = dirName;
817 if (path.Last() != wxFILE_SEP_PATH)
818 path += wxString(wxFILE_SEP_PATH);
819 path += eachFilename;
820
821 wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,eachFilename,TRUE);
822 wxTreeItemId id = m_treeCtrl->AppendItem( parentId, eachFilename, 0, -1, dir_item);
823 m_treeCtrl->SetItemImage( id, 1, wxTreeItemIcon_Expanded );
ec1b28a3 824
51a58d8b
JS
825 // Has this got any children? If so, make it expandable.
826 int options = wxDIR_DEFAULT;
827 if (GetWindowStyle() & wxDIRCTRL_DIR_ONLY) // If only showing dirs, then we specify dirs only here
828 {
829 options = wxDIR_DIRS;
830 }
831
f9c165b1
JS
832 wxLogNull log;
833 wxDir dir2;
834 if (dir2.Open(path))
51a58d8b 835 {
f9c165b1
JS
836 wxString str;
837 // Have to test for wxDIR_DIRS separately in case m_currentFilterStr is non-empty and
838 // and filters out any directories
839 if (dir2.GetFirst(& str, m_currentFilterStr, options) || dir2.GetFirst(& str, wxEmptyString, wxDIR_DIRS))
840 {
841 m_treeCtrl->SetItemHasChildren(id);
842 }
33fed835 843 }
51a58d8b
JS
844 }
845
846 // Add the sorted filenames
847 if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY) == 0)
848 {
849 for (i = 0; i < filenames.Count(); i++)
850 {
851 wxString eachFilename(filenames[i]);
852 path = dirName;
853 if (path.Last() != wxFILE_SEP_PATH)
854 path += wxString(wxFILE_SEP_PATH);
855 path += eachFilename;
856 //path = dirName + wxString(wxT("/")) + eachFilename;
857 wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,eachFilename,FALSE);
3fa4bd0e 858 (void)m_treeCtrl->AppendItem( parentId, eachFilename, 2, -1, dir_item);
51a58d8b
JS
859 }
860 }
861}
862
863// Find the child that matches the first part of 'path'.
864// E.g. if a child path is "/usr" and 'path' is "/usr/include"
865// then the child for /usr is returned.
866wxTreeItemId wxGenericDirCtrl::FindChild(wxTreeItemId parentId, const wxString& path, bool& done)
867{
868 wxString path2(path);
ec1b28a3 869
51a58d8b
JS
870 // Make sure all separators are as per the current platform
871 path2.Replace(wxT("\\"), wxString(wxFILE_SEP_PATH));
872 path2.Replace(wxT("/"), wxString(wxFILE_SEP_PATH));
ec1b28a3 873
51a58d8b
JS
874 // Append a separator to foil bogus substring matching
875 path2 += wxString(wxFILE_SEP_PATH);
ec1b28a3
DW
876
877 // In MSW or PM, case is not significant
878#if defined(__WXMSW__) || defined(__WXPM__)
51a58d8b
JS
879 path2.MakeLower();
880#endif
ec1b28a3 881
51a58d8b
JS
882 long cookie;
883 wxTreeItemId childId = m_treeCtrl->GetFirstChild(parentId, cookie);
53ccf1c0 884 while (childId.IsOk())
51a58d8b
JS
885 {
886 wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(childId);
ec1b28a3 887
51a58d8b
JS
888 if (data && data->m_path != "")
889 {
890 wxString childPath(data->m_path);
891 if (childPath.Last() != wxFILE_SEP_PATH)
892 childPath += wxString(wxFILE_SEP_PATH);
ec1b28a3
DW
893
894 // In MSW and PM, case is not significant
895#if defined(__WXMSW__) || defined(__WXPM__)
51a58d8b
JS
896 childPath.MakeLower();
897#endif
ec1b28a3 898
51a58d8b
JS
899 if (childPath.Len() <= path2.Len())
900 {
901 wxString path3 = path2.Mid(0, childPath.Len());
902 if (childPath == path3)
903 {
904 if (path3.Len() == path2.Len())
905 done = TRUE;
906 else
907 done = FALSE;
908 return childId;
909 }
910 }
911 }
ec1b28a3 912
51a58d8b
JS
913 childId = m_treeCtrl->GetNextChild(childId, cookie);
914 }
3fa4bd0e
VS
915 wxTreeItemId invalid;
916 return invalid;
51a58d8b
JS
917}
918
919// Try to expand as much of the given path as possible,
920// and select the given tree item.
921bool wxGenericDirCtrl::ExpandPath(const wxString& path)
922{
923 bool done = FALSE;
924 wxTreeItemId id = FindChild(m_rootId, path, done);
925 wxTreeItemId lastId = id; // The last non-zero id
237387ad 926 while (id.IsOk() && !done)
51a58d8b
JS
927 {
928 ExpandDir(id);
929
930 id = FindChild(id, path, done);
53ccf1c0 931 if (id.IsOk())
51a58d8b
JS
932 lastId = id;
933 }
53ccf1c0 934 if (lastId.IsOk())
51a58d8b
JS
935 {
936 wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(lastId);
937 if (data->m_isDir)
938 {
939 m_treeCtrl->Expand(lastId);
940 }
941 if ((GetWindowStyle() & wxDIRCTRL_SELECT_FIRST) && data->m_isDir)
942 {
943 // Find the first file in this directory
944 long cookie;
945 wxTreeItemId childId = m_treeCtrl->GetFirstChild(lastId, cookie);
946 bool selectedChild = FALSE;
53ccf1c0 947 while (childId.IsOk())
51a58d8b
JS
948 {
949 wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(childId);
ec1b28a3 950
51a58d8b
JS
951 if (data && data->m_path != "" && !data->m_isDir)
952 {
953 m_treeCtrl->SelectItem(childId);
954 m_treeCtrl->EnsureVisible(childId);
955 selectedChild = TRUE;
956 break;
957 }
958 childId = m_treeCtrl->GetNextChild(lastId, cookie);
959 }
960 if (!selectedChild)
961 {
962 m_treeCtrl->SelectItem(lastId);
963 m_treeCtrl->EnsureVisible(lastId);
964 }
965 }
966 else
967 {
968 m_treeCtrl->SelectItem(lastId);
969 m_treeCtrl->EnsureVisible(lastId);
970 }
971
972 return TRUE;
973 }
974 else
975 return FALSE;
976}
977
978wxString wxGenericDirCtrl::GetPath() const
979{
980 wxTreeItemId id = m_treeCtrl->GetSelection();
981 if (id)
982 {
983 wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(id);
984 return data->m_path;
985 }
986 else
987 return wxEmptyString;
988}
989
990wxString wxGenericDirCtrl::GetFilePath() const
991{
992 wxTreeItemId id = m_treeCtrl->GetSelection();
993 if (id)
994 {
995 wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(id);
996 if (data->m_isDir)
997 return wxEmptyString;
998 else
999 return data->m_path;
1000 }
1001 else
1002 return wxEmptyString;
1003}
1004
1005void wxGenericDirCtrl::SetPath(const wxString& path)
1006{
1007 m_defaultPath = path;
1008 if (m_rootId)
1009 ExpandPath(path);
1010}
1011
1012// Not used
1013#if 0
1014void wxGenericDirCtrl::FindChildFiles(wxTreeItemId id, int dirFlags, wxArrayString& filenames)
1015{
1016 wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(id);
1017
1018 // This may take a longish time. Go to busy cursor
1019 wxBusyCursor busy;
1020
1021 wxASSERT(data);
1022
1023 wxString search,path,filename;
1024
1025 wxString dirName(data->m_path);
1026
ec1b28a3 1027#if defined(__WXMSW__) || defined(__WXPM__)
51a58d8b
JS
1028 if (dirName.Last() == ':')
1029 dirName += wxString(wxFILE_SEP_PATH);
1030#endif
1031
1032 wxDir d;
1033 wxString eachFilename;
1034
f9c165b1 1035 wxLogNull log;
51a58d8b
JS
1036 d.Open(dirName);
1037
1038 if (d.IsOpened())
1039 {
1040 if (d.GetFirst(& eachFilename, m_currentFilterStr, dirFlags))
1041 {
1042 do
1043 {
1044 if ((eachFilename != wxT(".")) && (eachFilename != wxT("..")))
1045 {
1046 filenames.Add(eachFilename);
1047 }
1048 }
1049 while (d.GetNext(& eachFilename)) ;
1050 }
1051 }
1052}
1053#endif
1054
1055void wxGenericDirCtrl::SetFilterIndex(int n)
1056{
1057 m_currentFilter = n;
1058
1059 wxString f, d;
1060 if (ExtractWildcard(m_filter, n, f, d))
1061 m_currentFilterStr = f;
1062 else
1063 m_currentFilterStr = wxT("*.*");
1064}
1065
1066void wxGenericDirCtrl::SetFilter(const wxString& filter)
1067{
1068 m_filter = filter;
1069
1070 wxString f, d;
1071 if (ExtractWildcard(m_filter, m_currentFilter, f, d))
1072 m_currentFilterStr = f;
1073 else
1074 m_currentFilterStr = wxT("*.*");
1075}
1076
1077// Extract description and actual filter from overall filter string
1078bool wxGenericDirCtrl::ExtractWildcard(const wxString& filterStr, int n, wxString& filter, wxString& description)
1079{
1080 wxArrayString filters, descriptions;
1081 int count = ParseFilter(filterStr, filters, descriptions);
1082 if (count > 0 && n < count)
1083 {
1084 filter = filters[n];
1085 description = descriptions[n];
1086 return TRUE;
1087 }
5716a1ab
VZ
1088
1089 return FALSE;
51a58d8b
JS
1090}
1091
1092// Parses the global filter, returning the number of filters.
1093// Returns 0 if none or if there's a problem.
1094// filterStr is in the form:
1095//
1096// "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpg"
1097
1098int wxGenericDirCtrl::ParseFilter(const wxString& filterStr, wxArrayString& filters, wxArrayString& descriptions)
1099{
1100 wxString str(filterStr);
1101
1102 wxString description, filter;
1103 int pos;
1104 bool finished = FALSE;
1105 do
1106 {
1107 pos = str.Find(wxT('|'));
1108 if (pos == -1)
1109 return 0; // Problem
1110 description = str.Left(pos);
1111 str = str.Mid(pos+1);
1112 pos = str.Find(wxT('|'));
1113 if (pos == -1)
1114 {
1115 filter = str;
1116 finished = TRUE;
1117 }
1118 else
1119 {
1120 filter = str.Left(pos);
1121 str = str.Mid(pos+1);
1122 }
1123 descriptions.Add(description);
1124 filters.Add(filter);
1125 }
1126 while (!finished) ;
1127
1128 return filters.Count();
1129}
1130
1131void wxGenericDirCtrl::DoResize()
1132{
1133 wxSize sz = GetClientSize();
1134 int verticalSpacing = 3;
1135 if (m_treeCtrl)
1136 {
1137 wxSize filterSz ;
1138 if (m_filterListCtrl)
1139 {
1140 filterSz = m_filterListCtrl->GetSize();
1141 sz.y -= (filterSz.y + verticalSpacing);
1142 }
1143 m_treeCtrl->SetSize(0, 0, sz.x, sz.y);
1144 if (m_filterListCtrl)
1145 {
1146 m_filterListCtrl->SetSize(0, sz.y + verticalSpacing, sz.x, filterSz.y);
1147 // Don't know why, but this needs refreshing after a resize (wxMSW)
1148 m_filterListCtrl->Refresh();
1149 }
1150 }
1151}
1152
1153
33ac7e6f 1154void wxGenericDirCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
51a58d8b
JS
1155{
1156 DoResize();
1157}
1158
1159//-----------------------------------------------------------------------------
1160// wxDirFilterListCtrl
1161//-----------------------------------------------------------------------------
1162
1163IMPLEMENT_CLASS(wxDirFilterListCtrl, wxChoice)
1164
1165BEGIN_EVENT_TABLE(wxDirFilterListCtrl, wxChoice)
1166 EVT_CHOICE(-1, wxDirFilterListCtrl::OnSelFilter)
1167END_EVENT_TABLE()
1168
1169bool wxDirFilterListCtrl::Create(wxGenericDirCtrl* parent, const wxWindowID id,
1170 const wxPoint& pos,
1171 const wxSize& size,
1172 long style)
1173{
1174 m_dirCtrl = parent;
1175 return wxChoice::Create(parent, id, pos, size, 0, NULL, style);
1176}
1177
1178void wxDirFilterListCtrl::Init()
1179{
1180 m_dirCtrl = NULL;
1181}
1182
33ac7e6f 1183void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent& WXUNUSED(event))
51a58d8b
JS
1184{
1185 int sel = GetSelection();
1186
1187 wxString currentPath = m_dirCtrl->GetPath();
ec1b28a3 1188
51a58d8b
JS
1189 m_dirCtrl->SetFilterIndex(sel);
1190
1191 // If the filter has changed, the view is out of date, so
1192 // collapse the tree.
1193 m_dirCtrl->GetTreeCtrl()->Collapse(m_dirCtrl->GetRootId());
1194 m_dirCtrl->GetTreeCtrl()->Expand(m_dirCtrl->GetRootId());
1195
1196 // Try to restore the selection, or at least the directory
1197 m_dirCtrl->ExpandPath(currentPath);
1198}
1199
1200void wxDirFilterListCtrl::FillFilterList(const wxString& filter, int defaultFilter)
1201{
1202 Clear();
1203 wxArrayString descriptions, filters;
1204 size_t n = (size_t) m_dirCtrl->ParseFilter(filter, filters, descriptions);
1205
1206 if (n > 0 && defaultFilter < (int) n)
1207 {
1208 size_t i = 0;
1209 for (i = 0; i < n; i++)
1210 Append(descriptions[i]);
1211 SetSelection(defaultFilter);
1212 }
1213}
1214
1215// wxGenericDirDialog implementation
1216// This should be moved into dirdlgg.cpp eventually
1217
1218BEGIN_EVENT_TABLE(wxGenericDirDialog, wxDialog)
1219 EVT_BUTTON(wxID_OK, wxGenericDirDialog::OnOK)
3438012b 1220 EVT_BUTTON(wxID_NEW, wxGenericDirDialog::OnNew)
e63fdcd6 1221 EVT_BUTTON (wxID_NEW, wxGenericDirDialog::OnNew)
51a58d8b 1222 EVT_CLOSE(wxGenericDirDialog::OnCloseWindow)
08793a6d
JS
1223 EVT_TREE_KEY_DOWN (-1, wxGenericDirDialog::OnTreeKeyDown)
1224 EVT_TREE_SEL_CHANGED (-1, wxGenericDirDialog::OnTreeSelected)
e63fdcd6 1225 EVT_TEXT_ENTER (ID_TEXTCTRL, wxGenericDirDialog::OnOK)
51a58d8b
JS
1226END_EVENT_TABLE()
1227
1228wxGenericDirDialog::wxGenericDirDialog(wxWindow* parent, const wxString& title,
1229 const wxString& defaultPath, long style, const wxPoint& pos, const wxSize& sz, const wxString& name):
1230 wxDialog(parent, ID_DIRCTRL, title, pos, sz, style, name)
1231{
08793a6d
JS
1232 m_dirCtrl = NULL;
1233 m_path = defaultPath;
1234
51a58d8b
JS
1235 wxBusyCursor cursor;
1236
1237 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
1238
1239 // 1) dir ctrl
1240 m_dirCtrl = new wxGenericDirCtrl(this, ID_DIRCTRL,
1241 defaultPath, wxPoint(5, 5),
f9c165b1 1242 wxSize(300, 200), wxDIRCTRL_DIR_ONLY|wxSUNKEN_BORDER);
51a58d8b
JS
1243
1244 topsizer->Add( m_dirCtrl, 1, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 10 );
1245
e63fdcd6 1246 // 2) text ctrl
08793a6d 1247 m_input = new wxTextCtrl( this, ID_TEXTCTRL, m_path, wxDefaultPosition );
e63fdcd6 1248 topsizer->Add( m_input, 0, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 10 );
51a58d8b
JS
1249
1250#if wxUSE_STATLINE
1251 // 3) Static line
1252 topsizer->Add( new wxStaticLine( this, -1 ), 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10 );
1253#endif
1254
1255 // 4) Buttons
1256 wxSizer* buttonsizer = new wxBoxSizer( wxHORIZONTAL );
1257 wxButton* okButton = new wxButton(this, wxID_OK, _("OK"));
1258 buttonsizer->Add( okButton, 0, wxLEFT|wxRIGHT, 10 );
1259 wxButton* cancelButton = new wxButton(this, wxID_CANCEL, _("Cancel"));
1260 buttonsizer->Add( cancelButton, 0, wxLEFT|wxRIGHT, 10 );
1261
3438012b
JS
1262 // I'm not convinced we need a New button, and we tend to get annoying
1263 // accidental-editing with label editing enabled.
1264#if 0
1265 wxButton* newButton = new wxButton( this, wxID_NEW, _("New...") );
51a58d8b 1266 buttonsizer->Add( newButton, 0, wxLEFT|wxRIGHT, 10 );
3438012b
JS
1267#endif
1268
51a58d8b
JS
1269 topsizer->Add( buttonsizer, 0, wxALL | wxCENTER, 10 );
1270
1271 okButton->SetDefault();
1272 m_dirCtrl->SetFocus();
1273
1274 SetAutoLayout( TRUE );
1275 SetSizer( topsizer );
1276
1277 topsizer->SetSizeHints( this );
1278 topsizer->Fit( this );
1279
1280 Centre( wxBOTH );
1281}
1282
33ac7e6f 1283void wxGenericDirDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
51a58d8b
JS
1284{
1285 EndModal(wxID_CANCEL);
1286}
1287
33ac7e6f 1288void wxGenericDirDialog::OnOK(wxCommandEvent& WXUNUSED(event))
51a58d8b 1289{
e63fdcd6
JS
1290 m_path = m_input->GetValue();
1291 // Does the path exist? (User may have typed anything in m_input)
1292 if (wxPathExists(m_path)) {
1293 // OK, path exists, we're done.
1294 EndModal(wxID_OK);
1295 return;
1296 }
1297 // Interact with user, find out if the dir is a typo or to be created
1298 wxString msg( _("The directory ") );
1299 msg = msg + m_path;
1300 msg = msg + _("\ndoes not exist\nCreate it now?") ;
1301 wxMessageDialog dialog(this, msg, _("Directory does not exist"), wxYES_NO | wxICON_WARNING );
1302 if ( dialog.ShowModal() == wxID_YES ) {
1303 // Okay, let's make it
1304 wxLogNull log;
1305 if (wxMkdir(m_path)) {
1306 // The new dir was created okay.
1307 EndModal(wxID_OK);
1308 return;
1309 }
1310 else {
1311 // Trouble...
1312 msg = _("Failed to create directory ")+m_path+
1313 _("\n(Do you have the required permissions?)");
1314 wxMessageDialog errmsg(this, msg, _("Error creating directory"), wxOK | wxICON_ERROR);
1315 errmsg.ShowModal();
1316 // We still don't have a valid dir. Back to the main dialog.
1317 }
1318 }
1319 // User has answered NO to create dir.
51a58d8b
JS
1320}
1321
1322void wxGenericDirDialog::SetPath(const wxString& path)
1323{
1324 m_dirCtrl->SetPath(path);
08793a6d 1325 m_path = path;
51a58d8b
JS
1326}
1327
1328wxString wxGenericDirDialog::GetPath(void) const
1329{
08793a6d 1330 return m_path;
51a58d8b 1331}
e63fdcd6
JS
1332
1333int wxGenericDirDialog::ShowModal()
1334{
08793a6d 1335 //m_input->SetValue( m_path );
e63fdcd6
JS
1336 return wxDialog::ShowModal();
1337}
1338
1339void wxGenericDirDialog::OnTreeSelected( wxTreeEvent &event )
1340{
08793a6d
JS
1341 if (!m_dirCtrl)
1342 return;
1343
e63fdcd6
JS
1344 wxDirItemDataEx *data = (wxDirItemDataEx*)m_dirCtrl->GetTreeCtrl()->GetItemData(event.GetItem());
1345 if (data)
1346 m_input->SetValue( data->m_path );
1347};
1348
1349void wxGenericDirDialog::OnTreeKeyDown( wxTreeEvent &WXUNUSED(event) )
1350{
08793a6d
JS
1351 if (!m_dirCtrl)
1352 return;
1353
e63fdcd6
JS
1354 wxDirItemDataEx *data = (wxDirItemDataEx*)m_dirCtrl->GetTreeCtrl()->GetItemData(m_dirCtrl->GetTreeCtrl()->GetSelection());
1355 if (data)
1356 m_input->SetValue( data->m_path );
1357};
1358
1359void wxGenericDirDialog::OnNew( wxCommandEvent& WXUNUSED(event) )
1360{
3438012b
JS
1361 wxTreeItemId id = m_dirCtrl->GetTreeCtrl()->GetSelection();
1362 if ((id == m_dirCtrl->GetTreeCtrl()->GetRootItem()) ||
1363 (m_dirCtrl->GetTreeCtrl()->GetParent(id) == m_dirCtrl->GetTreeCtrl()->GetRootItem()))
e63fdcd6
JS
1364 {
1365 wxMessageDialog msg(this, _("You cannot add a new directory to this section."),
1366 _("Create directory"), wxOK | wxICON_INFORMATION );
1367 msg.ShowModal();
1368 return;
1369 }
1370
3438012b
JS
1371 wxTreeItemId parent = id ; // m_dirCtrl->GetTreeCtrl()->GetParent( id );
1372 wxDirItemDataEx *data = (wxDirItemDataEx*)m_dirCtrl->GetTreeCtrl()->GetItemData( parent );
e63fdcd6
JS
1373 wxASSERT( data );
1374
1375 wxString new_name( wxT("NewName") );
1376 wxString path( data->m_path );
3438012b
JS
1377 if (path.Last() != wxFILE_SEP_PATH)
1378 path += wxFILE_SEP_PATH;
e63fdcd6
JS
1379 path += new_name;
1380 if (wxFileExists(path))
1381 {
1382 // try NewName0, NewName1 etc.
1383 int i = 0;
1384 do {
1385 new_name = wxT("NewName");
1386 wxString num;
1387 num.Printf( wxT("%d"), i );
1388 new_name += num;
1389
1390 path = data->m_path;
3438012b
JS
1391 if (path.Last() != wxFILE_SEP_PATH)
1392 path += wxFILE_SEP_PATH;
e63fdcd6
JS
1393 path += new_name;
1394 i++;
1395 } while (wxFileExists(path));
1396 }
1397
1398 wxLogNull log;
1399 if (!wxMkdir(path))
1400 {
1401 wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
1402 dialog.ShowModal();
1403 return;
1404 }
1405
3438012b
JS
1406 wxDirItemDataEx *new_data = new wxDirItemDataEx( path, new_name, TRUE );
1407
1408 // TODO: THIS CODE DOESN'T WORK YET. We need to avoid duplication of the first child
1409 // of the parent.
1410 wxTreeItemId new_id = m_dirCtrl->GetTreeCtrl()->AppendItem( parent, new_name, 0, 0, new_data );
1411 m_dirCtrl->GetTreeCtrl()->EnsureVisible( new_id );
1412 m_dirCtrl->GetTreeCtrl()->EditLabel( new_id );
e63fdcd6 1413}
1e6feb95
VZ
1414
1415#endif // wxUSE_DIRDLG