]> git.saurik.com Git - wxWidgets.git/blame - src/generic/dirctrlg.cpp
incomplete paste error
[wxWidgets.git] / src / generic / dirctrlg.cpp
CommitLineData
51a58d8b 1/////////////////////////////////////////////////////////////////////////////
7fc65a03 2// Name: src/generic/dirctrlg.cpp
51a58d8b
JS
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
65571936 9// Licence: wxWindows licence
51a58d8b
JS
10/////////////////////////////////////////////////////////////////////////////
11
51a58d8b
JS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
32d4c30a 16 #pragma hdrstop
51a58d8b
JS
17#endif
18
13de0c8c 19#if wxUSE_DIRDLG || wxUSE_FILEDLG
51a58d8b 20
88a7a4e1
WS
21#include "wx/generic/dirctrlg.h"
22
32d4c30a
WS
23#ifndef WX_PRECOMP
24 #include "wx/hash.h"
88a7a4e1 25 #include "wx/intl.h"
e4db172a 26 #include "wx/log.h"
de6185e2 27 #include "wx/utils.h"
f1e01716 28 #include "wx/button.h"
923d28da 29 #include "wx/icon.h"
9eddec69 30 #include "wx/settings.h"
246c5004 31 #include "wx/msgdlg.h"
b36e08d0 32 #include "wx/choice.h"
fec9cc08 33 #include "wx/textctrl.h"
ed2fbeb8
WS
34 #include "wx/layout.h"
35 #include "wx/sizer.h"
949c9f74 36 #include "wx/textdlg.h"
dd05139a 37 #include "wx/gdicmn.h"
155ecd4c 38 #include "wx/image.h"
02761f6c 39 #include "wx/module.h"
32d4c30a
WS
40#endif
41
35c2aa4f 42#include "wx/filename.h"
51a58d8b 43#include "wx/filefn.h"
51a58d8b 44#include "wx/imaglist.h"
51a58d8b
JS
45#include "wx/tokenzr.h"
46#include "wx/dir.h"
06cc1fb9 47#include "wx/artprov.h"
06cc1fb9 48#include "wx/mimetype.h"
51a58d8b
JS
49
50#if wxUSE_STATLINE
51 #include "wx/statline.h"
52#endif
53
76a5e5d2 54#if defined(__WXMAC__)
33ddeaba 55 #include "wx/osx/private.h" // includes mac headers
76a5e5d2
SC
56#endif
57
bb5a9514 58#ifdef __WINDOWS__
2736b3ce 59#include <windows.h>
7acf6a92 60#include "wx/msw/winundef.h"
006b7af2 61#include "wx/volume.h"
7328394a 62
c9ecda60
VS
63// FIXME - Mingw32 1.0 has both _getdrive() and _chdrive(). For now, let's assume
64// older releases don't, but it should be verified and the checks modified
65// accordingly.
b4da152e 66#if !defined(__GNUWIN32__) || (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
1c193821 67#if !defined(__WXWINCE__)
32d4c30a 68 #include <direct.h>
1c193821 69#endif
32d4c30a
WS
70 #include <stdlib.h>
71 #include <ctype.h>
51a58d8b
JS
72#endif
73
bb5a9514 74#endif // __WINDOWS__
7328394a 75
1c53456f 76#if defined(__OS2__) || defined(__DOS__)
ed2fbeb8
WS
77 #ifdef __OS2__
78 #define INCL_BASE
79 #include <os2.h>
80 #ifndef __EMX__
81 #include <direct.h>
82 #endif
83 #include <stdlib.h>
84 #include <ctype.h>
1c53456f 85 #endif
0d853c54 86#endif // __OS2__
ec1b28a3 87
f4ac0693 88#if defined(__WXMAC__)
e1f31102 89// #include "MoreFilesX.h"
bedaf53e
SC
90#endif
91
267a7108 92#ifdef __BORLANDC__
32d4c30a 93 #include "dos.h"
267a7108
JS
94#endif
95
f36e602b 96extern WXDLLEXPORT_DATA(const char) wxFileSelectorDefaultWildcardStr[];
a3e70e1f 97
51a58d8b
JS
98// If compiled under Windows, this macro can cause problems
99#ifdef GetFirstChild
100#undef GetFirstChild
101#endif
102
207ddcc9
VZ
103bool wxIsDriveAvailable(const wxString& dirName);
104
84605707
VZ
105// ----------------------------------------------------------------------------
106// events
107// ----------------------------------------------------------------------------
108
40c7c7f4 109wxDEFINE_EVENT( wxEVT_DIRCTRL_SELECTIONCHANGED, wxTreeEvent );
4d623b67 110wxDEFINE_EVENT( wxEVT_DIRCTRL_FILEACTIVATED, wxTreeEvent );
84605707 111
06cc1fb9 112// ----------------------------------------------------------------------------
0d853c54 113// wxGetAvailableDrives, for WINDOWS, DOS, OS2, MAC, UNIX (returns "/")
06cc1fb9 114// ----------------------------------------------------------------------------
51a58d8b 115
06cc1fb9
JS
116size_t wxGetAvailableDrives(wxArrayString &paths, wxArrayString &names, wxArrayInt &icon_ids)
117{
35c2aa4f 118#ifdef wxHAS_FILESYSTEM_VOLUMES
51a58d8b 119
4676948b
JS
120#ifdef __WXWINCE__
121 // No logical drives; return "\"
122 paths.Add(wxT("\\"));
123 names.Add(wxT("\\"));
1ab36908 124 icon_ids.Add(wxFileIconsTable::computer);
006b7af2
VZ
125#elif defined(__WIN32__) && wxUSE_FSVOLUME
126 // TODO: this code (using wxFSVolumeBase) should be used for all platforms
127 // but unfortunately wxFSVolumeBase is not implemented everywhere
128 const wxArrayString as = wxFSVolumeBase::GetVolumes();
0026e0f2 129
006b7af2
VZ
130 for (size_t i = 0; i < as.GetCount(); i++)
131 {
132 wxString path = as[i];
133 wxFSVolume vol(path);
999836aa 134 int imageId;
006b7af2 135 switch (vol.GetKind())
06cc1fb9 136 {
006b7af2
VZ
137 case wxFS_VOL_FLOPPY:
138 if ( (path == wxT("a:\\")) || (path == wxT("b:\\")) )
06cc1fb9
JS
139 imageId = wxFileIconsTable::floppy;
140 else
141 imageId = wxFileIconsTable::removeable;
142 break;
006b7af2
VZ
143 case wxFS_VOL_DVDROM:
144 case wxFS_VOL_CDROM:
06cc1fb9
JS
145 imageId = wxFileIconsTable::cdrom;
146 break;
006b7af2
VZ
147 case wxFS_VOL_NETWORK:
148 if (path[0] == wxT('\\'))
149 continue; // skip "\\computer\folder"
150 imageId = wxFileIconsTable::drive;
151 break;
152 case wxFS_VOL_DISK:
153 case wxFS_VOL_OTHER:
06cc1fb9
JS
154 default:
155 imageId = wxFileIconsTable::drive;
156 break;
157 }
06cc1fb9 158 paths.Add(path);
006b7af2 159 names.Add(vol.GetDisplayName());
06cc1fb9 160 icon_ids.Add(imageId);
06cc1fb9 161 }
0d853c54
SN
162#elif defined(__OS2__)
163 APIRET rc;
164 ULONG ulDriveNum = 0;
165 ULONG ulDriveMap = 0;
166 rc = ::DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
ca65c044
WS
167 if ( rc == 0)
168 {
0d853c54
SN
169 size_t i = 0;
170 while (i < 26)
171 {
ca65c044
WS
172 if (ulDriveMap & ( 1 << i ))
173 {
35c2aa4f
VZ
174 const wxString path = wxFileName::GetVolumeString(
175 'A' + i, wxPATH_GET_SEPARATOR);
176 const wxString name = wxFileName::GetVolumeString(
177 'A' + i, wxPATH_NO_SEPARATOR);
ca65c044 178
be283c77
SN
179 // Note: If _filesys is unsupported by some compilers,
180 // we can always replace it by DosQueryFSAttach
181 char filesysname[20];
7fc65a03
WS
182#ifdef __WATCOMC__
183 ULONG cbBuffer = sizeof(filesysname);
184 PFSQBUFFER2 pfsqBuffer = (PFSQBUFFER2)filesysname;
185 APIRET rc = ::DosQueryFSAttach(name.fn_str(),0,FSAIL_QUERYNAME,pfsqBuffer,&cbBuffer);
186 if (rc != NO_ERROR)
187 {
188 filesysname[0] = '\0';
189 }
190#else
be283c77 191 _filesys(name.fn_str(), filesysname, sizeof(filesysname));
7fc65a03 192#endif
be283c77 193 /* FAT, LAN, HPFS, CDFS, NFS */
ca65c044
WS
194 int imageId;
195 if (path == wxT("A:\\") || path == wxT("B:\\"))
196 imageId = wxFileIconsTable::floppy;
be283c77
SN
197 else if (!strcmp(filesysname, "CDFS"))
198 imageId = wxFileIconsTable::cdrom;
199 else if (!strcmp(filesysname, "LAN") ||
200 !strcmp(filesysname, "NFS"))
201 imageId = wxFileIconsTable::drive;
ca65c044
WS
202 else
203 imageId = wxFileIconsTable::drive;
204 paths.Add(path);
205 names.Add(name);
206 icon_ids.Add(imageId);
207 }
0d853c54 208 i ++;
ca65c044
WS
209 }
210 }
0d853c54 211#else // !__WIN32__, !__OS2__
06cc1fb9 212 /* If we can switch to the drive, it exists. */
35c2aa4f 213 for ( char drive = 'A'; drive <= 'Z'; drive++ )
06cc1fb9 214 {
35c2aa4f
VZ
215 const wxString
216 path = wxFileName::GetVolumeString(drive, wxPATH_GET_SEPARATOR);
51a58d8b 217
06cc1fb9
JS
218 if (wxIsDriveAvailable(path))
219 {
220 paths.Add(path);
35c2aa4f
VZ
221 names.Add(wxFileName::GetVolumeString(drive, wxPATH_NO_SEPARATOR));
222 icon_ids.Add(drive <= 2 ? wxFileIconsTable::floppy
223 : wxFileIconsTable::drive);
06cc1fb9
JS
224 }
225 }
226#endif // __WIN32__/!__WIN32__
227
96f04e1d 228#elif defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON
06cc1fb9 229
a2b77260
SC
230 ItemCount volumeIndex = 1;
231 OSErr err = noErr ;
44d60c0b 232
a2b77260
SC
233 while( noErr == err )
234 {
235 HFSUniStr255 volumeName ;
236 FSRef fsRef ;
237 FSVolumeInfo volumeInfo ;
44d60c0b
WS
238 err = FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoFlags , &volumeInfo , &volumeName, &fsRef);
239 if( noErr == err )
240 {
241 wxString path = wxMacFSRefToPath( &fsRef ) ;
a2b77260 242 wxString name = wxMacHFSUniStrToString( &volumeName ) ;
44d60c0b 243
a2b77260 244 if ( (volumeInfo.flags & kFSVolFlagSoftwareLockedMask) || (volumeInfo.flags & kFSVolFlagHardwareLockedMask) )
06cc1fb9 245 {
a2b77260 246 icon_ids.Add(wxFileIconsTable::cdrom);
06cc1fb9 247 }
a2b77260
SC
248 else
249 {
250 icon_ids.Add(wxFileIconsTable::drive);
06cc1fb9 251 }
a2b77260 252 // todo other removable
44d60c0b 253
06cc1fb9
JS
254 paths.Add(path);
255 names.Add(name);
a2b77260 256 volumeIndex++ ;
44d60c0b 257 }
06cc1fb9 258 }
06cc1fb9 259
bd362275 260#elif defined(__UNIX__)
06cc1fb9
JS
261 paths.Add(wxT("/"));
262 names.Add(wxT("/"));
263 icon_ids.Add(wxFileIconsTable::computer);
264#else
265 #error "Unsupported platform in wxGenericDirCtrl!"
266#endif
e9890600
WS
267 wxASSERT_MSG( (paths.GetCount() == names.GetCount()), wxT("The number of paths and their human readable names should be equal in number."));
268 wxASSERT_MSG( (paths.GetCount() == icon_ids.GetCount()), wxT("Wrong number of icons for available drives."));
06cc1fb9
JS
269 return paths.GetCount();
270}
51a58d8b 271
06cc1fb9
JS
272// ----------------------------------------------------------------------------
273// wxIsDriveAvailable
274// ----------------------------------------------------------------------------
748fcded 275
748fcded 276#if defined(__DOS__)
db5333a5 277
37fd1c97 278bool wxIsDriveAvailable(const wxString& dirName)
db5333a5 279{
0e1f8ea4 280 // FIXME: this method leads to hang up under Watcom for some reason
127eab18
WS
281#ifdef __WATCOMC__
282 wxUnusedVar(dirName);
283#else
b36e08d0 284 if ( dirName.length() == 3 && dirName[1u] == wxT(':') )
db5333a5
VS
285 {
286 wxString dirNameLower(dirName.Lower());
ca65c044 287 // VS: always return true for removable media, since Win95 doesn't
db5333a5
VS
288 // like it when MS-DOS app accesses empty floppy drive
289 return (dirNameLower[0u] == wxT('a') ||
290 dirNameLower[0u] == wxT('b') ||
da865fdd 291 wxDirExists(dirNameLower));
db5333a5
VS
292 }
293 else
6157794c 294#endif
ca65c044 295 return true;
db5333a5
VS
296}
297
0d853c54 298#elif defined(__WINDOWS__) || defined(__OS2__)
db5333a5 299
0c0d1521 300int setdrive(int WXUNUSED_IN_WINCE(drive))
33ac7e6f 301{
4676948b
JS
302#ifdef __WXWINCE__
303 return 0;
304#elif defined(__GNUWIN32__) && \
c9ecda60
VS
305 (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
306 return _chdrive(drive);
307#else
ca65c044 308 wxChar newdrive[4];
33ac7e6f 309
ca65c044
WS
310 if (drive < 1 || drive > 31)
311 return -1;
312 newdrive[0] = (wxChar)(wxT('A') + drive - 1);
313 newdrive[1] = wxT(':');
0d853c54 314#ifdef __OS2__
ca65c044
WS
315 newdrive[2] = wxT('\\');
316 newdrive[3] = wxT('\0');
0d853c54 317#else
ca65c044 318 newdrive[2] = wxT('\0');
0d853c54 319#endif
bb5a9514 320#if defined(__WINDOWS__)
ca65c044 321 if (::SetCurrentDirectory(newdrive))
50c76ce1
DW
322#else
323 // VA doesn't know what LPSTR is and has its own set
ca65c044 324 if (!DosSetCurrentDir((PSZ)newdrive))
50c76ce1 325#endif
ca65c044
WS
326 return 0;
327 else
328 return -1;
c9ecda60 329#endif // !GNUWIN32
33ac7e6f
KB
330}
331
0c0d1521 332bool wxIsDriveAvailable(const wxString& WXUNUSED_IN_WINCE(dirName))
ad9cd15c 333{
4676948b 334#ifdef __WXWINCE__
ca65c044 335 return false;
4676948b 336#else
ad9cd15c 337#ifdef __WIN32__
33fed835 338 UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
ad9cd15c 339#endif
ca65c044 340 bool success = true;
ad9cd15c
JS
341
342 // Check if this is a root directory and if so,
2d4e4f80 343 // whether the drive is available.
b36e08d0 344 if (dirName.length() == 3 && dirName[(size_t)1] == wxT(':'))
ad9cd15c 345 {
33fed835 346 wxString dirNameLower(dirName.Lower());
b4da152e 347#if defined(__GNUWIN32__) && !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
da865fdd 348 success = wxDirExists(dirNameLower);
7328394a 349#else
0d853c54
SN
350 #if defined(__OS2__)
351 // Avoid changing to drive since no media may be inserted.
352 if (dirNameLower[(size_t)0] == 'a' || dirNameLower[(size_t)0] == 'b')
353 return success;
354 #endif
ad9cd15c 355 int currentDrive = _getdrive();
33fed835 356 int thisDrive = (int) (dirNameLower[(size_t)0] - 'a' + 1) ;
33ac7e6f
KB
357 int err = setdrive( thisDrive ) ;
358 setdrive( currentDrive );
ad9cd15c
JS
359
360 if (err == -1)
361 {
ca65c044 362 success = false;
ad9cd15c 363 }
7328394a 364#endif
ad9cd15c
JS
365 }
366#ifdef __WIN32__
33fed835 367 (void) SetErrorMode(errorMode);
ad9cd15c
JS
368#endif
369
33fed835 370 return success;
4676948b 371#endif
ad9cd15c 372}
0d853c54 373#endif // __WINDOWS__ || __OS2__
ad9cd15c 374
13de0c8c
WS
375#endif // wxUSE_DIRDLG || wxUSE_FILEDLG
376
377
378
379#if wxUSE_DIRDLG
b600ed13 380
57e26a09
JS
381// Function which is called by quick sort. We want to override the default wxArrayString behaviour,
382// and sort regardless of case.
a2a03d78 383static int wxCMPFUNC_CONV wxDirCtrlStringCompareFunction(const wxString& strFirst, const wxString& strSecond)
57e26a09 384{
a2a03d78 385 return strFirst.CmpNoCase(strSecond);
57e26a09
JS
386}
387
51a58d8b 388//-----------------------------------------------------------------------------
748fcded 389// wxDirItemData
51a58d8b
JS
390//-----------------------------------------------------------------------------
391
748fcded
VS
392wxDirItemData::wxDirItemData(const wxString& path, const wxString& name,
393 bool isDir)
51a58d8b
JS
394{
395 m_path = path;
396 m_name = name;
397 /* Insert logic to detect hidden files here
398 * In UnixLand we just check whether the first char is a dot
399 * For FileNameFromPath read LastDirNameInThisPath ;-) */
400 // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.');
ca65c044
WS
401 m_isHidden = false;
402 m_isExpanded = false;
51a58d8b
JS
403 m_isDir = isDir;
404}
405
748fcded 406void wxDirItemData::SetNewDirName(const wxString& path)
51a58d8b
JS
407{
408 m_path = path;
748fcded
VS
409 m_name = wxFileNameFromPath(path);
410}
411
412bool wxDirItemData::HasSubDirs() const
413{
44d60c0b 414 if (m_path.empty())
ca65c044 415 return false;
748fcded
VS
416
417 wxDir dir;
418 {
419 wxLogNull nolog;
420 if ( !dir.Open(m_path) )
ca65c044 421 return false;
748fcded
VS
422 }
423
424 return dir.HasSubDirs();
425}
426
574c939e 427bool wxDirItemData::HasFiles(const wxString& WXUNUSED(spec)) const
748fcded 428{
44d60c0b 429 if (m_path.empty())
ca65c044 430 return false;
748fcded
VS
431
432 wxDir dir;
433 {
434 wxLogNull nolog;
435 if ( !dir.Open(m_path) )
ca65c044 436 return false;
748fcded
VS
437 }
438
439 return dir.HasFiles();
51a58d8b
JS
440}
441
51a58d8b
JS
442//-----------------------------------------------------------------------------
443// wxGenericDirCtrl
444//-----------------------------------------------------------------------------
445
51a58d8b 446BEGIN_EVENT_TABLE(wxGenericDirCtrl, wxControl)
6b707fc3
JS
447 EVT_TREE_ITEM_EXPANDING (wxID_TREECTRL, wxGenericDirCtrl::OnExpandItem)
448 EVT_TREE_ITEM_COLLAPSED (wxID_TREECTRL, wxGenericDirCtrl::OnCollapseItem)
449 EVT_TREE_BEGIN_LABEL_EDIT (wxID_TREECTRL, wxGenericDirCtrl::OnBeginEditItem)
450 EVT_TREE_END_LABEL_EDIT (wxID_TREECTRL, wxGenericDirCtrl::OnEndEditItem)
84605707 451 EVT_TREE_SEL_CHANGED (wxID_TREECTRL, wxGenericDirCtrl::OnTreeSelChange)
4d623b67 452 EVT_TREE_ITEM_ACTIVATED (wxID_TREECTRL, wxGenericDirCtrl::OnItemActivated)
51a58d8b
JS
453 EVT_SIZE (wxGenericDirCtrl::OnSize)
454END_EVENT_TABLE()
455
456wxGenericDirCtrl::wxGenericDirCtrl(void)
457{
458 Init();
459}
460
c06dde42
JS
461void wxGenericDirCtrl::ExpandRoot()
462{
463 ExpandDir(m_rootId); // automatically expand first level
464
465 // Expand and select the default path
466 if (!m_defaultPath.empty())
467 {
468 ExpandPath(m_defaultPath);
469 }
470#ifdef __UNIX__
471 else
472 {
473 // On Unix, there's only one node under the (hidden) root node. It
474 // represents the / path, so the user would always have to expand it;
475 // let's do it ourselves
476 ExpandPath( wxT("/") );
477 }
478#endif
479}
480
51a58d8b 481bool wxGenericDirCtrl::Create(wxWindow *parent,
c1ec7ee8 482 const wxWindowID treeid,
748fcded
VS
483 const wxString& dir,
484 const wxPoint& pos,
485 const wxSize& size,
486 long style,
487 const wxString& filter,
488 int defaultFilter,
489 const wxString& name)
51a58d8b 490{
c1ec7ee8 491 if (!wxControl::Create(parent, treeid, pos, size, style, wxDefaultValidator, name))
ca65c044 492 return false;
51a58d8b 493
db5333a5 494 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
e1957703 495 SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
51a58d8b
JS
496
497 Init();
498
3bd8a405
JS
499 long treeStyle = wxTR_HAS_BUTTONS;
500
501 // On Windows CE, if you hide the root, you get a crash when
502 // attempting to access data for children of the root item.
503#ifndef __WXWINCE__
504 treeStyle |= wxTR_HIDE_ROOT;
505#endif
2997ca30 506
82c1f2a3
RR
507#ifdef __WXGTK20__
508 treeStyle |= wxTR_NO_LINES;
509#endif
fd775aae 510
dabd1377 511 if (style & wxDIRCTRL_EDIT_LABELS)
fd775aae
JS
512 treeStyle |= wxTR_EDIT_LABELS;
513
80f624ec
VZ
514 if (style & wxDIRCTRL_MULTIPLE)
515 treeStyle |= wxTR_MULTIPLE;
516
51a58d8b
JS
517 if ((style & wxDIRCTRL_3D_INTERNAL) == 0)
518 treeStyle |= wxNO_BORDER;
519
a78955e3 520 m_treeCtrl = CreateTreeCtrl(this, wxID_TREECTRL,
c47addef 521 wxPoint(0,0), GetClientSize(), treeStyle);
51a58d8b 522
aa9453d6 523 if (!filter.empty() && (style & wxDIRCTRL_SHOW_FILTERS))
d0bc78e2 524 m_filterListCtrl = new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL);
51a58d8b
JS
525
526 m_defaultPath = dir;
527 m_filter = filter;
528
dd0138d9 529 if (m_filter.empty())
d0bc78e2 530 m_filter = wxFileSelectorDefaultWildcardStr;
dd0138d9 531
51a58d8b
JS
532 SetFilterIndex(defaultFilter);
533
534 if (m_filterListCtrl)
535 m_filterListCtrl->FillFilterList(filter, defaultFilter);
536
06cc1fb9 537 m_treeCtrl->SetImageList(wxTheFileIconsTable->GetSmallImageList());
51a58d8b 538
ca65c044
WS
539 m_showHidden = false;
540 wxDirItemData* rootData = new wxDirItemData(wxEmptyString, wxEmptyString, true);
51a58d8b
JS
541
542 wxString rootName;
543
0d853c54 544#if defined(__WINDOWS__) || defined(__OS2__) || defined(__DOS__)
51a58d8b
JS
545 rootName = _("Computer");
546#else
547 rootName = _("Sections");
548#endif
549
550 m_rootId = m_treeCtrl->AddRoot( rootName, 3, -1, rootData);
551 m_treeCtrl->SetItemHasChildren(m_rootId);
2997ca30 552
c06dde42 553 ExpandRoot();
51a58d8b 554
4a89f0e9 555 SetInitialSize(size);
51a58d8b
JS
556 DoResize();
557
ca65c044 558 return true;
51a58d8b
JS
559}
560
561wxGenericDirCtrl::~wxGenericDirCtrl()
562{
51a58d8b
JS
563}
564
565void wxGenericDirCtrl::Init()
566{
ca65c044 567 m_showHidden = false;
51a58d8b
JS
568 m_currentFilter = 0;
569 m_currentFilterStr = wxEmptyString; // Default: any file
570 m_treeCtrl = NULL;
571 m_filterListCtrl = NULL;
572}
573
c1ec7ee8 574wxTreeCtrl* wxGenericDirCtrl::CreateTreeCtrl(wxWindow *parent, wxWindowID treeid, const wxPoint& pos, const wxSize& size, long treeStyle)
a78955e3 575{
c1ec7ee8 576 return new wxTreeCtrl(parent, treeid, pos, size, treeStyle);
a78955e3
VS
577}
578
42dcacf0
RR
579void wxGenericDirCtrl::ShowHidden( bool show )
580{
9092371c
VZ
581 if ( m_showHidden == show )
582 return;
583
42dcacf0 584 m_showHidden = show;
574c939e 585
80f624ec
VZ
586 if ( HasFlag(wxDIRCTRL_MULTIPLE) )
587 {
588 wxArrayString paths;
589 GetPaths(paths);
590 ReCreateTree();
591 for ( unsigned n = 0; n < paths.size(); n++ )
592 {
593 ExpandPath(paths[n]);
594 }
595 }
596 else
597 {
598 wxString path = GetPath();
599 ReCreateTree();
600 SetPath(path);
601 }
42dcacf0
RR
602}
603
22328fa4
JS
604const wxTreeItemId
605wxGenericDirCtrl::AddSection(const wxString& path, const wxString& name, int imageId)
51a58d8b 606{
ca65c044 607 wxDirItemData *dir_item = new wxDirItemData(path,name,true);
51a58d8b 608
c1ec7ee8 609 wxTreeItemId treeid = AppendItem( m_rootId, name, imageId, -1, dir_item);
4f5c180e 610
c1ec7ee8 611 m_treeCtrl->SetItemHasChildren(treeid);
22328fa4 612
c1ec7ee8 613 return treeid;
06cc1fb9 614}
51a58d8b 615
06cc1fb9
JS
616void wxGenericDirCtrl::SetupSections()
617{
618 wxArrayString paths, names;
619 wxArrayInt icons;
2d4e4f80 620
06cc1fb9 621 size_t n, count = wxGetAvailableDrives(paths, names, icons);
4f5c180e 622
82c1f2a3
RR
623#ifdef __WXGTK20__
624 wxString home = wxGetHomeDir();
625 AddSection( home, _("Home directory"), 1);
626 home += wxT("/Desktop");
627 AddSection( home, _("Desktop"), 1);
628#endif
629
06cc1fb9 630 for (n = 0; n < count; n++)
06cc1fb9 631 AddSection(paths[n], names[n], icons[n]);
51a58d8b
JS
632}
633
905e0905
VZ
634void wxGenericDirCtrl::SetFocus()
635{
636 // we don't need focus ourselves, give it to the tree so that the user
637 // could navigate it
d095f867
RR
638 if (m_treeCtrl)
639 m_treeCtrl->SetFocus();
905e0905
VZ
640}
641
51a58d8b
JS
642void wxGenericDirCtrl::OnBeginEditItem(wxTreeEvent &event)
643{
644 // don't rename the main entry "Sections"
645 if (event.GetItem() == m_rootId)
646 {
647 event.Veto();
648 return;
649 }
650
651 // don't rename the individual sections
99006e44 652 if (m_treeCtrl->GetItemParent( event.GetItem() ) == m_rootId)
51a58d8b
JS
653 {
654 event.Veto();
655 return;
656 }
657}
658
659void wxGenericDirCtrl::OnEndEditItem(wxTreeEvent &event)
660{
6e86472f
VZ
661 if (event.IsEditCancelled())
662 return;
663
44d60c0b 664 if ((event.GetLabel().empty()) ||
47b8afad
MR
665 (event.GetLabel() == wxT(".")) ||
666 (event.GetLabel() == wxT("..")) ||
06cc1fb9
JS
667 (event.GetLabel().Find(wxT('/')) != wxNOT_FOUND) ||
668 (event.GetLabel().Find(wxT('\\')) != wxNOT_FOUND) ||
669 (event.GetLabel().Find(wxT('|')) != wxNOT_FOUND))
51a58d8b
JS
670 {
671 wxMessageDialog dialog(this, _("Illegal directory name."), _("Error"), wxOK | wxICON_ERROR );
672 dialog.ShowModal();
673 event.Veto();
674 return;
675 }
676
c1ec7ee8 677 wxTreeItemId treeid = event.GetItem();
0d6f66f4 678 wxDirItemData *data = GetItemData( treeid );
51a58d8b
JS
679 wxASSERT( data );
680
681 wxString new_name( wxPathOnly( data->m_path ) );
ad9cd15c 682 new_name += wxString(wxFILE_SEP_PATH);
51a58d8b
JS
683 new_name += event.GetLabel();
684
685 wxLogNull log;
686
687 if (wxFileExists(new_name))
688 {
689 wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR );
690 dialog.ShowModal();
691 event.Veto();
692 }
693
694 if (wxRenameFile(data->m_path,new_name))
695 {
696 data->SetNewDirName( new_name );
697 }
698 else
699 {
700 wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
701 dialog.ShowModal();
702 event.Veto();
703 }
704}
705
84605707
VZ
706void wxGenericDirCtrl::OnTreeSelChange(wxTreeEvent &event)
707{
40c7c7f4 708 wxTreeEvent changedEvent(wxEVT_DIRCTRL_SELECTIONCHANGED, GetId());
84605707 709
9cf565e2 710 changedEvent.SetEventObject(this);
84605707
VZ
711 changedEvent.SetItem(event.GetItem());
712 changedEvent.SetClientObject(m_treeCtrl->GetItemData(event.GetItem()));
713
9cf565e2 714 if (GetEventHandler()->SafelyProcessEvent(changedEvent) && !changedEvent.IsAllowed())
9cf565e2 715 event.Veto();
9cf565e2 716 else
4d623b67
VZ
717 event.Skip();
718}
719
720void wxGenericDirCtrl::OnItemActivated(wxTreeEvent &event)
721{
722 wxTreeItemId treeid = event.GetItem();
723 const wxDirItemData *data = GetItemData(treeid);
724
725 if (data->m_isDir)
9cf565e2 726 {
4d623b67 727 // is dir
9cf565e2
VZ
728 event.Skip();
729 }
4d623b67
VZ
730 else
731 {
732 // is file
733 wxTreeEvent changedEvent(wxEVT_DIRCTRL_FILEACTIVATED, GetId());
734
735 changedEvent.SetEventObject(this);
736 changedEvent.SetItem(treeid);
737 changedEvent.SetClientObject(m_treeCtrl->GetItemData(treeid));
738
739 if (GetEventHandler()->SafelyProcessEvent(changedEvent) && !changedEvent.IsAllowed())
740 event.Veto();
741 else
742 event.Skip();
743 }
84605707
VZ
744}
745
51a58d8b
JS
746void wxGenericDirCtrl::OnExpandItem(wxTreeEvent &event)
747{
748 wxTreeItemId parentId = event.GetItem();
749
748fcded
VS
750 // VS: this is needed because the event handler is called from wxTreeCtrl
751 // ctor when wxTR_HIDE_ROOT was specified
4ded51f2
CE
752
753 if (!m_rootId.IsOk())
748fcded
VS
754 m_rootId = m_treeCtrl->GetRootItem();
755
51a58d8b
JS
756 ExpandDir(parentId);
757}
758
759void wxGenericDirCtrl::OnCollapseItem(wxTreeEvent &event )
760{
08887820
VS
761 CollapseDir(event.GetItem());
762}
763
764void wxGenericDirCtrl::CollapseDir(wxTreeItemId parentId)
765{
766 wxTreeItemId child;
51a58d8b 767
0d6f66f4 768 wxDirItemData *data = GetItemData(parentId);
51a58d8b
JS
769 if (!data->m_isExpanded)
770 return;
771
ca65c044 772 data->m_isExpanded = false;
5b806097
JS
773
774 m_treeCtrl->Freeze();
c06dde42 775 if (parentId != m_treeCtrl->GetRootItem())
5b806097
JS
776 m_treeCtrl->CollapseAndReset(parentId);
777 m_treeCtrl->DeleteChildren(parentId);
778 m_treeCtrl->Thaw();
51a58d8b
JS
779}
780
ef57807f 781void wxGenericDirCtrl::PopulateNode(wxTreeItemId parentId)
51a58d8b 782{
0d6f66f4 783 wxDirItemData *data = GetItemData(parentId);
51a58d8b
JS
784
785 if (data->m_isExpanded)
786 return;
787
ca65c044 788 data->m_isExpanded = true;
51a58d8b 789
748fcded 790 if (parentId == m_treeCtrl->GetRootItem())
51a58d8b
JS
791 {
792 SetupSections();
793 return;
794 }
795
796 wxASSERT(data);
797
798 wxString search,path,filename;
799
800 wxString dirName(data->m_path);
801
3bd8a405 802#if (defined(__WINDOWS__) && !defined(__WXWINCE__)) || defined(__DOS__) || defined(__OS2__)
51a58d8b
JS
803 // Check if this is a root directory and if so,
804 // whether the drive is avaiable.
33fed835
MB
805 if (!wxIsDriveAvailable(dirName))
806 {
ca65c044 807 data->m_isExpanded = false;
7328394a
JS
808 //wxMessageBox(wxT("Sorry, this drive is not available."));
809 return;
33fed835 810 }
51a58d8b
JS
811#endif
812
813 // This may take a longish time. Go to busy cursor
814 wxBusyCursor busy;
815
0d853c54 816#if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)
51a58d8b
JS
817 if (dirName.Last() == ':')
818 dirName += wxString(wxFILE_SEP_PATH);
819#endif
820
821 wxArrayString dirs;
822 wxArrayString filenames;
823
824 wxDir d;
825 wxString eachFilename;
826
f9c165b1 827 wxLogNull log;
51a58d8b
JS
828 d.Open(dirName);
829
830 if (d.IsOpened())
831 {
42dcacf0
RR
832 int style = wxDIR_DIRS;
833 if (m_showHidden) style |= wxDIR_HIDDEN;
834 if (d.GetFirst(& eachFilename, wxEmptyString, style))
51a58d8b
JS
835 {
836 do
837 {
838 if ((eachFilename != wxT(".")) && (eachFilename != wxT("..")))
839 {
840 dirs.Add(eachFilename);
841 }
842 }
2b0a7c09 843 while (d.GetNext(&eachFilename));
51a58d8b
JS
844 }
845 }
222ed1d6 846 dirs.Sort(wxDirCtrlStringCompareFunction);
51a58d8b
JS
847
848 // Now do the filenames -- but only if we're allowed to
d9c98a9a 849 if (!HasFlag(wxDIRCTRL_DIR_ONLY))
51a58d8b
JS
850 {
851 d.Open(dirName);
ec1b28a3 852
51a58d8b
JS
853 if (d.IsOpened())
854 {
2b0a7c09
RN
855 int style = wxDIR_FILES;
856 if (m_showHidden) style |= wxDIR_HIDDEN;
3da4e4bd
JS
857 // Process each filter (ex: "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg")
858 wxStringTokenizer strTok;
859 wxString curFilter;
860 strTok.SetString(m_currentFilterStr,wxT(";"));
861 while(strTok.HasMoreTokens())
51a58d8b 862 {
3da4e4bd 863 curFilter = strTok.GetNextToken();
f0e5a44d 864 if (d.GetFirst(& eachFilename, curFilter, style))
51a58d8b 865 {
3da4e4bd 866 do
51a58d8b 867 {
3da4e4bd
JS
868 if ((eachFilename != wxT(".")) && (eachFilename != wxT("..")))
869 {
870 filenames.Add(eachFilename);
871 }
51a58d8b 872 }
3da4e4bd 873 while (d.GetNext(& eachFilename));
51a58d8b 874 }
51a58d8b
JS
875 }
876 }
222ed1d6 877 filenames.Sort(wxDirCtrlStringCompareFunction);
51a58d8b
JS
878 }
879
c72fa1cd
VZ
880 // Now we really know whether we have any children so tell the tree control
881 // about it.
882 m_treeCtrl->SetItemHasChildren(parentId, !dirs.empty() || !filenames.empty());
883
51a58d8b
JS
884 // Add the sorted dirs
885 size_t i;
b4a980f4 886 for (i = 0; i < dirs.GetCount(); i++)
51a58d8b 887 {
4e115ed2 888 eachFilename = dirs[i];
51a58d8b 889 path = dirName;
083f7497 890 if (!wxEndsWithPathSeparator(path))
51a58d8b
JS
891 path += wxString(wxFILE_SEP_PATH);
892 path += eachFilename;
893
ca65c044 894 wxDirItemData *dir_item = new wxDirItemData(path,eachFilename,true);
c1ec7ee8 895 wxTreeItemId treeid = AppendItem( parentId, eachFilename,
06cc1fb9 896 wxFileIconsTable::folder, -1, dir_item);
c1ec7ee8 897 m_treeCtrl->SetItemImage( treeid, wxFileIconsTable::folder_open,
06cc1fb9 898 wxTreeItemIcon_Expanded );
ec1b28a3 899
d9c98a9a
VZ
900 // assume that it does have children by default as it can take a long
901 // time to really check for this (think remote drives...)
902 //
c72fa1cd 903 // and if we're wrong, we'll correct the icon later if
d9c98a9a 904 // the user really tries to open this item
c1ec7ee8 905 m_treeCtrl->SetItemHasChildren(treeid);
51a58d8b
JS
906 }
907
908 // Add the sorted filenames
d9c98a9a 909 if (!HasFlag(wxDIRCTRL_DIR_ONLY))
51a58d8b 910 {
b4a980f4 911 for (i = 0; i < filenames.GetCount(); i++)
51a58d8b 912 {
4e115ed2 913 eachFilename = filenames[i];
51a58d8b 914 path = dirName;
083f7497 915 if (!wxEndsWithPathSeparator(path))
51a58d8b
JS
916 path += wxString(wxFILE_SEP_PATH);
917 path += eachFilename;
918 //path = dirName + wxString(wxT("/")) + eachFilename;
ca65c044 919 wxDirItemData *dir_item = new wxDirItemData(path,eachFilename,false);
06cc1fb9
JS
920 int image_id = wxFileIconsTable::file;
921 if (eachFilename.Find(wxT('.')) != wxNOT_FOUND)
922 image_id = wxTheFileIconsTable->GetIconID(eachFilename.AfterLast(wxT('.')));
22328fa4 923 (void) AppendItem( parentId, eachFilename, image_id, -1, dir_item);
51a58d8b
JS
924 }
925 }
926}
927
ef57807f
VZ
928void wxGenericDirCtrl::ExpandDir(wxTreeItemId parentId)
929{
930 // ExpandDir() will not actually expand the tree node, just populate it
931 PopulateNode(parentId);
932}
933
08887820
VS
934void wxGenericDirCtrl::ReCreateTree()
935{
936 CollapseDir(m_treeCtrl->GetRootItem());
c06dde42
JS
937 ExpandRoot();
938}
939
940void wxGenericDirCtrl::CollapseTree()
941{
942 wxTreeItemIdValue cookie;
943 wxTreeItemId child = m_treeCtrl->GetFirstChild(m_rootId, cookie);
944 while (child.IsOk())
945 {
946 CollapseDir(child);
947 child = m_treeCtrl->GetNextChild(m_rootId, cookie);
948 }
08887820
VS
949}
950
51a58d8b
JS
951// Find the child that matches the first part of 'path'.
952// E.g. if a child path is "/usr" and 'path' is "/usr/include"
953// then the child for /usr is returned.
954wxTreeItemId wxGenericDirCtrl::FindChild(wxTreeItemId parentId, const wxString& path, bool& done)
955{
956 wxString path2(path);
ec1b28a3 957
51a58d8b
JS
958 // Make sure all separators are as per the current platform
959 path2.Replace(wxT("\\"), wxString(wxFILE_SEP_PATH));
960 path2.Replace(wxT("/"), wxString(wxFILE_SEP_PATH));
ec1b28a3 961
51a58d8b
JS
962 // Append a separator to foil bogus substring matching
963 path2 += wxString(wxFILE_SEP_PATH);
ec1b28a3
DW
964
965 // In MSW or PM, case is not significant
0d853c54 966#if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)
51a58d8b
JS
967 path2.MakeLower();
968#endif
ec1b28a3 969
2d75caaa 970 wxTreeItemIdValue cookie;
51a58d8b 971 wxTreeItemId childId = m_treeCtrl->GetFirstChild(parentId, cookie);
53ccf1c0 972 while (childId.IsOk())
51a58d8b 973 {
0d6f66f4 974 wxDirItemData* data = GetItemData(childId);
ec1b28a3 975
44d60c0b 976 if (data && !data->m_path.empty())
51a58d8b
JS
977 {
978 wxString childPath(data->m_path);
083f7497 979 if (!wxEndsWithPathSeparator(childPath))
51a58d8b 980 childPath += wxString(wxFILE_SEP_PATH);
ec1b28a3
DW
981
982 // In MSW and PM, case is not significant
0d853c54 983#if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)
51a58d8b
JS
984 childPath.MakeLower();
985#endif
ec1b28a3 986
b36e08d0 987 if (childPath.length() <= path2.length())
51a58d8b 988 {
b36e08d0 989 wxString path3 = path2.Mid(0, childPath.length());
51a58d8b
JS
990 if (childPath == path3)
991 {
b36e08d0 992 if (path3.length() == path2.length())
ca65c044 993 done = true;
51a58d8b 994 else
ca65c044 995 done = false;
51a58d8b
JS
996 return childId;
997 }
998 }
999 }
ec1b28a3 1000
748fcded 1001 childId = m_treeCtrl->GetNextChild(parentId, cookie);
51a58d8b 1002 }
3fa4bd0e
VS
1003 wxTreeItemId invalid;
1004 return invalid;
51a58d8b
JS
1005}
1006
1007// Try to expand as much of the given path as possible,
1008// and select the given tree item.
1009bool wxGenericDirCtrl::ExpandPath(const wxString& path)
1010{
ca65c044 1011 bool done = false;
c1ec7ee8
SC
1012 wxTreeItemId treeid = FindChild(m_rootId, path, done);
1013 wxTreeItemId lastId = treeid; // The last non-zero treeid
1014 while (treeid.IsOk() && !done)
51a58d8b 1015 {
c1ec7ee8 1016 ExpandDir(treeid);
51a58d8b 1017
c1ec7ee8
SC
1018 treeid = FindChild(treeid, path, done);
1019 if (treeid.IsOk())
1020 lastId = treeid;
51a58d8b 1021 }
4e115ed2
VZ
1022 if (!lastId.IsOk())
1023 return false;
1024
0d6f66f4 1025 wxDirItemData *data = GetItemData(lastId);
4e115ed2 1026 if (data->m_isDir)
51a58d8b 1027 {
4e115ed2
VZ
1028 m_treeCtrl->Expand(lastId);
1029 }
d9c98a9a 1030 if (HasFlag(wxDIRCTRL_SELECT_FIRST) && data->m_isDir)
4e115ed2
VZ
1031 {
1032 // Find the first file in this directory
1033 wxTreeItemIdValue cookie;
1034 wxTreeItemId childId = m_treeCtrl->GetFirstChild(lastId, cookie);
1035 bool selectedChild = false;
1036 while (childId.IsOk())
51a58d8b 1037 {
0d6f66f4 1038 data = GetItemData(childId);
ec1b28a3 1039
4e115ed2 1040 if (data && data->m_path != wxEmptyString && !data->m_isDir)
51a58d8b 1041 {
4e115ed2
VZ
1042 m_treeCtrl->SelectItem(childId);
1043 m_treeCtrl->EnsureVisible(childId);
1044 selectedChild = true;
1045 break;
51a58d8b 1046 }
4e115ed2 1047 childId = m_treeCtrl->GetNextChild(lastId, cookie);
51a58d8b 1048 }
4e115ed2 1049 if (!selectedChild)
51a58d8b
JS
1050 {
1051 m_treeCtrl->SelectItem(lastId);
1052 m_treeCtrl->EnsureVisible(lastId);
1053 }
51a58d8b
JS
1054 }
1055 else
4e115ed2
VZ
1056 {
1057 m_treeCtrl->SelectItem(lastId);
1058 m_treeCtrl->EnsureVisible(lastId);
1059 }
1060
1061 return true;
51a58d8b
JS
1062}
1063
f395a825
VZ
1064
1065bool wxGenericDirCtrl::CollapsePath(const wxString& path)
1066{
1067 bool done = false;
c1ec7ee8
SC
1068 wxTreeItemId treeid = FindChild(m_rootId, path, done);
1069 wxTreeItemId lastId = treeid; // The last non-zero treeid
f395a825 1070
c1ec7ee8 1071 while ( treeid.IsOk() && !done )
f395a825 1072 {
c1ec7ee8 1073 CollapseDir(treeid);
f395a825 1074
c1ec7ee8 1075 treeid = FindChild(treeid, path, done);
f395a825 1076
c1ec7ee8
SC
1077 if ( treeid.IsOk() )
1078 lastId = treeid;
f395a825
VZ
1079 }
1080
1081 if ( !lastId.IsOk() )
1082 return false;
1083
1084 m_treeCtrl->SelectItem(lastId);
1085 m_treeCtrl->EnsureVisible(lastId);
1086
1087 return true;
1088}
1089
0d6f66f4
VZ
1090wxDirItemData* wxGenericDirCtrl::GetItemData(wxTreeItemId itemId)
1091{
1092 return static_cast<wxDirItemData*>(m_treeCtrl->GetItemData(itemId));
1093}
1094
e3f084fd
VZ
1095wxString wxGenericDirCtrl::GetPath(wxTreeItemId itemId) const
1096{
1097 const wxDirItemData*
1098 data = static_cast<wxDirItemData*>(m_treeCtrl->GetItemData(itemId));
1099
1100 return data->m_path;
1101}
f395a825 1102
51a58d8b
JS
1103wxString wxGenericDirCtrl::GetPath() const
1104{
2dd62dc0
RR
1105 // Allow calling GetPath() in multiple selection from OnSelFilter
1106 if (m_treeCtrl->HasFlag(wxTR_MULTIPLE))
1107 {
1108 wxArrayTreeItemIds items;
1109 m_treeCtrl->GetSelections(items);
1110 if (items.size() > 0)
1111 {
1112 // return first string only
c1ec7ee8 1113 wxTreeItemId treeid = items[0];
e3f084fd 1114 return GetPath(treeid);
2dd62dc0 1115 }
ce00f59b 1116
2dd62dc0
RR
1117 return wxEmptyString;
1118 }
1119
c1ec7ee8
SC
1120 wxTreeItemId treeid = m_treeCtrl->GetSelection();
1121 if (treeid)
51a58d8b 1122 {
e3f084fd 1123 return GetPath(treeid);
51a58d8b
JS
1124 }
1125 else
1126 return wxEmptyString;
1127}
1128
80f624ec
VZ
1129void wxGenericDirCtrl::GetPaths(wxArrayString& paths) const
1130{
1131 paths.clear();
1132
1133 wxArrayTreeItemIds items;
1134 m_treeCtrl->GetSelections(items);
1135 for ( unsigned n = 0; n < items.size(); n++ )
1136 {
c1ec7ee8 1137 wxTreeItemId treeid = items[n];
e3f084fd 1138 paths.push_back(GetPath(treeid));
80f624ec
VZ
1139 }
1140}
1141
51a58d8b
JS
1142wxString wxGenericDirCtrl::GetFilePath() const
1143{
c1ec7ee8
SC
1144 wxTreeItemId treeid = m_treeCtrl->GetSelection();
1145 if (treeid)
51a58d8b 1146 {
c1ec7ee8 1147 wxDirItemData* data = (wxDirItemData*) m_treeCtrl->GetItemData(treeid);
51a58d8b
JS
1148 if (data->m_isDir)
1149 return wxEmptyString;
1150 else
1151 return data->m_path;
1152 }
1153 else
1154 return wxEmptyString;
1155}
1156
80f624ec
VZ
1157void wxGenericDirCtrl::GetFilePaths(wxArrayString& paths) const
1158{
1159 paths.clear();
1160
1161 wxArrayTreeItemIds items;
1162 m_treeCtrl->GetSelections(items);
1163 for ( unsigned n = 0; n < items.size(); n++ )
1164 {
c1ec7ee8
SC
1165 wxTreeItemId treeid = items[n];
1166 wxDirItemData* data = (wxDirItemData*) m_treeCtrl->GetItemData(treeid);
80f624ec
VZ
1167 if ( !data->m_isDir )
1168 paths.Add(data->m_path);
1169 }
1170}
1171
51a58d8b
JS
1172void wxGenericDirCtrl::SetPath(const wxString& path)
1173{
1174 m_defaultPath = path;
1175 if (m_rootId)
1176 ExpandPath(path);
1177}
1178
80f624ec
VZ
1179void wxGenericDirCtrl::SelectPath(const wxString& path, bool select)
1180{
1181 bool done = false;
c1ec7ee8
SC
1182 wxTreeItemId treeid = FindChild(m_rootId, path, done);
1183 wxTreeItemId lastId = treeid; // The last non-zero treeid
1184 while ( treeid.IsOk() && !done )
80f624ec 1185 {
c1ec7ee8
SC
1186 treeid = FindChild(treeid, path, done);
1187 if ( treeid.IsOk() )
1188 lastId = treeid;
80f624ec
VZ
1189 }
1190 if ( !lastId.IsOk() )
1191 return;
1192
1193 if ( done )
1194 {
c1ec7ee8 1195 m_treeCtrl->SelectItem(treeid, select);
80f624ec
VZ
1196 }
1197}
1198
1199void wxGenericDirCtrl::SelectPaths(const wxArrayString& paths)
1200{
1201 if ( HasFlag(wxDIRCTRL_MULTIPLE) )
1202 {
1203 UnselectAll();
1204 for ( unsigned n = 0; n < paths.size(); n++ )
1205 {
1206 SelectPath(paths[n]);
1207 }
1208 }
1209}
1210
1211void wxGenericDirCtrl::UnselectAll()
1212{
1213 m_treeCtrl->UnselectAll();
1214}
1215
51a58d8b
JS
1216// Not used
1217#if 0
c1ec7ee8 1218void wxGenericDirCtrl::FindChildFiles(wxTreeItemId treeid, int dirFlags, wxArrayString& filenames)
51a58d8b 1219{
c1ec7ee8 1220 wxDirItemData *data = (wxDirItemData *) m_treeCtrl->GetItemData(treeid);
51a58d8b
JS
1221
1222 // This may take a longish time. Go to busy cursor
1223 wxBusyCursor busy;
1224
1225 wxASSERT(data);
1226
1227 wxString search,path,filename;
1228
1229 wxString dirName(data->m_path);
1230
bb5a9514 1231#if defined(__WINDOWS__) || defined(__OS2__)
51a58d8b
JS
1232 if (dirName.Last() == ':')
1233 dirName += wxString(wxFILE_SEP_PATH);
1234#endif
1235
1236 wxDir d;
1237 wxString eachFilename;
1238
f9c165b1 1239 wxLogNull log;
51a58d8b
JS
1240 d.Open(dirName);
1241
1242 if (d.IsOpened())
1243 {
1244 if (d.GetFirst(& eachFilename, m_currentFilterStr, dirFlags))
1245 {
1246 do
1247 {
1248 if ((eachFilename != wxT(".")) && (eachFilename != wxT("..")))
1249 {
1250 filenames.Add(eachFilename);
1251 }
1252 }
1253 while (d.GetNext(& eachFilename)) ;
1254 }
1255 }
1256}
1257#endif
1258
1259void wxGenericDirCtrl::SetFilterIndex(int n)
1260{
1261 m_currentFilter = n;
1262
1263 wxString f, d;
1264 if (ExtractWildcard(m_filter, n, f, d))
1265 m_currentFilterStr = f;
1266 else
dd0138d9
RR
1267#ifdef __UNIX__
1268 m_currentFilterStr = wxT("*");
1269#else
51a58d8b 1270 m_currentFilterStr = wxT("*.*");
dd0138d9 1271#endif
51a58d8b
JS
1272}
1273
1274void wxGenericDirCtrl::SetFilter(const wxString& filter)
1275{
1276 m_filter = filter;
1277
aa9453d6 1278 if (!filter.empty() && !m_filterListCtrl && HasFlag(wxDIRCTRL_SHOW_FILTERS))
d0bc78e2
VZ
1279 m_filterListCtrl = new wxDirFilterListCtrl(this, wxID_FILTERLISTCTRL);
1280 else if (filter.empty() && m_filterListCtrl)
1281 {
1282 m_filterListCtrl->Destroy();
1283 m_filterListCtrl = NULL;
1284 }
1285
51a58d8b
JS
1286 wxString f, d;
1287 if (ExtractWildcard(m_filter, m_currentFilter, f, d))
1288 m_currentFilterStr = f;
1289 else
dd0138d9
RR
1290#ifdef __UNIX__
1291 m_currentFilterStr = wxT("*");
1292#else
51a58d8b 1293 m_currentFilterStr = wxT("*.*");
dd0138d9 1294#endif
d0bc78e2
VZ
1295 // current filter index is meaningless after filter change, set it to zero
1296 SetFilterIndex(0);
1297 if (m_filterListCtrl)
1298 m_filterListCtrl->FillFilterList(m_filter, 0);
51a58d8b
JS
1299}
1300
1301// Extract description and actual filter from overall filter string
1302bool wxGenericDirCtrl::ExtractWildcard(const wxString& filterStr, int n, wxString& filter, wxString& description)
1303{
1304 wxArrayString filters, descriptions;
daf32463 1305 int count = wxParseCommonDialogsFilter(filterStr, descriptions, filters);
51a58d8b
JS
1306 if (count > 0 && n < count)
1307 {
1308 filter = filters[n];
1309 description = descriptions[n];
ca65c044 1310 return true;
51a58d8b 1311 }
5716a1ab 1312
ca65c044 1313 return false;
51a58d8b
JS
1314}
1315
51a58d8b
JS
1316
1317void wxGenericDirCtrl::DoResize()
1318{
1319 wxSize sz = GetClientSize();
1320 int verticalSpacing = 3;
1321 if (m_treeCtrl)
1322 {
1323 wxSize filterSz ;
1324 if (m_filterListCtrl)
1325 {
1326 filterSz = m_filterListCtrl->GetSize();
1327 sz.y -= (filterSz.y + verticalSpacing);
1328 }
1329 m_treeCtrl->SetSize(0, 0, sz.x, sz.y);
1330 if (m_filterListCtrl)
1331 {
1332 m_filterListCtrl->SetSize(0, sz.y + verticalSpacing, sz.x, filterSz.y);
1333 // Don't know why, but this needs refreshing after a resize (wxMSW)
1334 m_filterListCtrl->Refresh();
1335 }
1336 }
1337}
1338
1339
33ac7e6f 1340void wxGenericDirCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
51a58d8b
JS
1341{
1342 DoResize();
1343}
1344
22328fa4 1345wxTreeItemId wxGenericDirCtrl::AppendItem (const wxTreeItemId & parent,
ca65c044
WS
1346 const wxString & text,
1347 int image, int selectedImage,
1348 wxTreeItemData * data)
22328fa4
JS
1349{
1350 wxTreeCtrl *treeCtrl = GetTreeCtrl ();
1351
1352 wxASSERT (treeCtrl);
1353
1354 if (treeCtrl)
1355 {
1356 return treeCtrl->AppendItem (parent, text, image, selectedImage, data);
1357 }
1358 else
1359 {
1360 return wxTreeItemId();
1361 }
1362}
1363
1364
51a58d8b
JS
1365//-----------------------------------------------------------------------------
1366// wxDirFilterListCtrl
1367//-----------------------------------------------------------------------------
1368
1369IMPLEMENT_CLASS(wxDirFilterListCtrl, wxChoice)
1370
1371BEGIN_EVENT_TABLE(wxDirFilterListCtrl, wxChoice)
ca65c044 1372 EVT_CHOICE(wxID_ANY, wxDirFilterListCtrl::OnSelFilter)
51a58d8b
JS
1373END_EVENT_TABLE()
1374
d0bc78e2 1375bool wxDirFilterListCtrl::Create(wxGenericDirCtrl* parent,
c1ec7ee8 1376 const wxWindowID treeid,
d0bc78e2
VZ
1377 const wxPoint& pos,
1378 const wxSize& size,
1379 long style)
51a58d8b
JS
1380{
1381 m_dirCtrl = parent;
d0bc78e2
VZ
1382
1383 // by default our border style is determined by the style of our parent
1384 if ( !(style & wxBORDER_MASK) )
1385 {
1386 style |= parent->HasFlag(wxDIRCTRL_3D_INTERNAL) ? wxBORDER_SUNKEN
1387 : wxBORDER_NONE;
1388 }
1389
c1ec7ee8 1390 return wxChoice::Create(parent, treeid, pos, size, 0, NULL, style);
51a58d8b
JS
1391}
1392
1393void wxDirFilterListCtrl::Init()
1394{
1395 m_dirCtrl = NULL;
1396}
1397
33ac7e6f 1398void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent& WXUNUSED(event))
51a58d8b
JS
1399{
1400 int sel = GetSelection();
1401
9e48865c
SL
1402 if (m_dirCtrl->HasFlag(wxDIRCTRL_MULTIPLE))
1403 {
1404 wxArrayString paths;
1405 m_dirCtrl->GetPaths(paths);
1406
1407 m_dirCtrl->SetFilterIndex(sel);
ec1b28a3 1408
9e48865c
SL
1409 // If the filter has changed, the view is out of date, so
1410 // collapse the tree.
1411 m_dirCtrl->ReCreateTree();
1412
1413 // Expand and select the previously selected paths
1414 for (unsigned int i = 0; i < paths.GetCount(); i++)
1415 {
1416 m_dirCtrl->ExpandPath(paths.Item(i));
1417 }
1418 }
1419 else
1420 {
1421 wxString currentPath = m_dirCtrl->GetPath();
51a58d8b 1422
9e48865c
SL
1423 m_dirCtrl->SetFilterIndex(sel);
1424 m_dirCtrl->ReCreateTree();
51a58d8b 1425
9e48865c
SL
1426 // Try to restore the selection, or at least the directory
1427 m_dirCtrl->ExpandPath(currentPath);
1428 }
51a58d8b
JS
1429}
1430
1431void wxDirFilterListCtrl::FillFilterList(const wxString& filter, int defaultFilter)
1432{
1433 Clear();
1434 wxArrayString descriptions, filters;
866918a8 1435 size_t n = (size_t) wxParseCommonDialogsFilter(filter, descriptions, filters);
51a58d8b
JS
1436
1437 if (n > 0 && defaultFilter < (int) n)
1438 {
999836aa 1439 for (size_t i = 0; i < n; i++)
51a58d8b
JS
1440 Append(descriptions[i]);
1441 SetSelection(defaultFilter);
1442 }
1443}
13de0c8c 1444#endif // wxUSE_DIRDLG
51a58d8b 1445
13de0c8c 1446#if wxUSE_DIRDLG || wxUSE_FILEDLG
22328fa4 1447
06cc1fb9
JS
1448// ----------------------------------------------------------------------------
1449// wxFileIconsTable icons
1450// ----------------------------------------------------------------------------
1451
ff654490 1452#ifndef __WXGTK20__
13b22a67 1453/* Computer (c) Julian Smart */
a243da29 1454static const char* const file_icons_tbl_computer_xpm[] = {
13b22a67
JS
1455/* columns rows colors chars-per-pixel */
1456"16 16 42 1",
1457"r c #4E7FD0",
1458"$ c #7198D9",
1459"; c #DCE6F6",
1460"q c #FFFFFF",
1461"u c #4A7CCE",
1462"# c #779DDB",
1463"w c #95B2E3",
1464"y c #7FA2DD",
1465"f c #3263B4",
1466"= c #EAF0FA",
1467"< c #B1C7EB",
1468"% c #6992D7",
1469"9 c #D9E4F5",
1470"o c #9BB7E5",
1471"6 c #F7F9FD",
1472", c #BED0EE",
1473"3 c #F0F5FC",
1474"1 c #A8C0E8",
1475" c None",
1476"0 c #FDFEFF",
1477"4 c #C4D5F0",
1478"@ c #81A4DD",
1479"e c #4377CD",
1480"- c #E2EAF8",
1481"i c #9FB9E5",
1482"> c #CCDAF2",
1483"+ c #89A9DF",
1484"s c #5584D1",
1485"t c #5D89D3",
1486": c #D2DFF4",
1487"5 c #FAFCFE",
1488"2 c #F5F8FD",
1489"8 c #DFE8F7",
1490"& c #5E8AD4",
1491"X c #638ED5",
1492"a c #CEDCF2",
1493"p c #90AFE2",
1494"d c #2F5DA9",
1495"* c #5282D0",
1496"7 c #E5EDF9",
1497". c #A2BCE6",
1498"O c #8CACE0",
1499/* pixels */
1500" ",
1501" .XXXXXXXXXXX ",
1502" oXO++@#$%&*X ",
1503" oX=-;:>,<1%X ",
1504" oX23=-;:4,$X ",
1505" oX5633789:@X ",
1506" oX05623=78+X ",
1507" oXqq05623=OX ",
1508" oX,,,,,<<<$X ",
1509" wXXXXXXXXXXe ",
1510" XrtX%$$y@+O,, ",
1511" uyiiiiiiiii@< ",
1512" ouiiiiiiiiiip<a",
1513" rustX%$$y@+Ow,,",
1514" dfffffffffffffd",
1515" "
1516};
ff654490 1517#endif // !GTK+ 2
06cc1fb9 1518
06cc1fb9
JS
1519// ----------------------------------------------------------------------------
1520// wxFileIconsTable & friends
1521// ----------------------------------------------------------------------------
1522
1523// global instance of a wxFileIconsTable
d3b9f782 1524wxFileIconsTable* wxTheFileIconsTable = NULL;
06cc1fb9
JS
1525
1526// A module to allow icons table cleanup
1527
1528class wxFileIconsTableModule: public wxModule
1529{
1530DECLARE_DYNAMIC_CLASS(wxFileIconsTableModule)
1531public:
1532 wxFileIconsTableModule() {}
ca65c044 1533 bool OnInit() { wxTheFileIconsTable = new wxFileIconsTable; return true; }
06cc1fb9
JS
1534 void OnExit()
1535 {
5276b0a5 1536 wxDELETE(wxTheFileIconsTable);
06cc1fb9
JS
1537 }
1538};
1539
1540IMPLEMENT_DYNAMIC_CLASS(wxFileIconsTableModule, wxModule)
1541
1542class wxFileIconEntry : public wxObject
1543{
1544public:
c1ec7ee8 1545 wxFileIconEntry(int i) { iconid = i; }
06cc1fb9 1546
c1ec7ee8 1547 int iconid;
06cc1fb9
JS
1548};
1549
1550wxFileIconsTable::wxFileIconsTable()
1551{
1552 m_HashTable = NULL;
1553 m_smallImageList = NULL;
1554}
1555
1556wxFileIconsTable::~wxFileIconsTable()
1557{
222ed1d6
MB
1558 if (m_HashTable)
1559 {
1560 WX_CLEAR_HASH_TABLE(*m_HashTable);
1561 delete m_HashTable;
1562 }
06cc1fb9
JS
1563 if (m_smallImageList) delete m_smallImageList;
1564}
1565
1566// delayed initialization - wait until first use (wxArtProv not created yet)
1567void wxFileIconsTable::Create()
1568{
1569 wxCHECK_RET(!m_smallImageList && !m_HashTable, wxT("creating icons twice"));
06cc1fb9
JS
1570 m_HashTable = new wxHashTable(wxKEY_STRING);
1571 m_smallImageList = new wxImageList(16, 16);
1572
06cc1fb9 1573 // folder:
4b92a33f
VS
1574 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_FOLDER,
1575 wxART_CMN_DIALOG,
1576 wxSize(16, 16)));
06cc1fb9 1577 // folder_open
82c1f2a3
RR
1578 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_FOLDER_OPEN,
1579 wxART_CMN_DIALOG,
1580 wxSize(16, 16)));
06cc1fb9 1581 // computer
ff654490 1582#ifdef __WXGTK20__
82c1f2a3
RR
1583 // GTK24 uses this icon in the file open dialog
1584 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_HARDDISK,
1585 wxART_CMN_DIALOG,
1586 wxSize(16, 16)));
1587#else
06cc1fb9 1588 m_smallImageList->Add(wxIcon(file_icons_tbl_computer_xpm));
82c1f2a3 1589#endif
06cc1fb9 1590 // drive
82c1f2a3
RR
1591 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_HARDDISK,
1592 wxART_CMN_DIALOG,
1593 wxSize(16, 16)));
06cc1fb9 1594 // cdrom
82c1f2a3
RR
1595 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_CDROM,
1596 wxART_CMN_DIALOG,
1597 wxSize(16, 16)));
06cc1fb9 1598 // floppy
82c1f2a3
RR
1599 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_FLOPPY,
1600 wxART_CMN_DIALOG,
1601 wxSize(16, 16)));
06cc1fb9 1602 // removeable
82c1f2a3
RR
1603 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_REMOVABLE,
1604 wxART_CMN_DIALOG,
1605 wxSize(16, 16)));
06cc1fb9 1606 // file
4b92a33f
VS
1607 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE,
1608 wxART_CMN_DIALOG,
1609 wxSize(16, 16)));
06cc1fb9 1610 // executable
9a83f860 1611 if (GetIconID(wxEmptyString, wxT("application/x-executable")) == file)
06cc1fb9 1612 {
4b92a33f
VS
1613 m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE,
1614 wxART_CMN_DIALOG,
1615 wxSize(16, 16)));
9a83f860
VZ
1616 delete m_HashTable->Get(wxT("exe"));
1617 m_HashTable->Delete(wxT("exe"));
1618 m_HashTable->Put(wxT("exe"), new wxFileIconEntry(executable));
06cc1fb9
JS
1619 }
1620 /* else put into list by GetIconID
1621 (KDE defines application/x-executable for *.exe and has nice icon)
1622 */
1623}
1624
1625wxImageList *wxFileIconsTable::GetSmallImageList()
1626{
1627 if (!m_smallImageList)
1628 Create();
1629
1630 return m_smallImageList;
1631}
1632
bb5a9514 1633#if wxUSE_MIMETYPE && wxUSE_IMAGE && (!defined(__WINDOWS__) || wxUSE_WXDIB)
06cc1fb9
JS
1634// VS: we don't need this function w/o wxMimeTypesManager because we'll only have
1635// one icon and we won't resize it
1636
1637static wxBitmap CreateAntialiasedBitmap(const wxImage& img)
1638{
1d529ef7 1639 const unsigned int size = 16;
ca65c044 1640
1d529ef7 1641 wxImage smallimg (size, size);
06cc1fb9
JS
1642 unsigned char *p1, *p2, *ps;
1643 unsigned char mr = img.GetMaskRed(),
1644 mg = img.GetMaskGreen(),
1645 mb = img.GetMaskBlue();
1646
1647 unsigned x, y;
1648 unsigned sr, sg, sb, smask;
1649
1d529ef7 1650 p1 = img.GetData(), p2 = img.GetData() + 3 * size*2, ps = smallimg.GetData();
06cc1fb9
JS
1651 smallimg.SetMaskColour(mr, mr, mr);
1652
1d529ef7 1653 for (y = 0; y < size; y++)
06cc1fb9 1654 {
1d529ef7 1655 for (x = 0; x < size; x++)
06cc1fb9
JS
1656 {
1657 sr = sg = sb = smask = 0;
1658 if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
1659 sr += p1[0], sg += p1[1], sb += p1[2];
1660 else smask++;
1661 p1 += 3;
1662 if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
1663 sr += p1[0], sg += p1[1], sb += p1[2];
1664 else smask++;
1665 p1 += 3;
1666 if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
1667 sr += p2[0], sg += p2[1], sb += p2[2];
1668 else smask++;
1669 p2 += 3;
1670 if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
1671 sr += p2[0], sg += p2[1], sb += p2[2];
1672 else smask++;
1673 p2 += 3;
1674
1675 if (smask > 2)
1676 ps[0] = ps[1] = ps[2] = mr;
1677 else
8253f2e0
WS
1678 {
1679 ps[0] = (unsigned char)(sr >> 2);
1680 ps[1] = (unsigned char)(sg >> 2);
1681 ps[2] = (unsigned char)(sb >> 2);
1682 }
06cc1fb9
JS
1683 ps += 3;
1684 }
1d529ef7 1685 p1 += size*2 * 3, p2 += size*2 * 3;
06cc1fb9 1686 }
ca65c044 1687
06cc1fb9
JS
1688 return wxBitmap(smallimg);
1689}
1690
b126fe3a
DS
1691// This function is currently not unused anymore
1692#if 0
06cc1fb9
JS
1693// finds empty borders and return non-empty area of image:
1694static wxImage CutEmptyBorders(const wxImage& img)
1695{
1696 unsigned char mr = img.GetMaskRed(),
1697 mg = img.GetMaskGreen(),
1698 mb = img.GetMaskBlue();
1699 unsigned char *dt = img.GetData(), *dttmp;
1700 unsigned w = img.GetWidth(), h = img.GetHeight();
1701
1702 unsigned top, bottom, left, right, i;
1703 bool empt;
1704
1705#define MK_DTTMP(x,y) dttmp = dt + ((x + y * w) * 3)
ca65c044 1706#define NOEMPTY_PIX(empt) if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = false; break;}
06cc1fb9 1707
ca65c044 1708 for (empt = true, top = 0; empt && top < h; top++)
06cc1fb9
JS
1709 {
1710 MK_DTTMP(0, top);
1711 for (i = 0; i < w; i++, dttmp+=3)
1712 NOEMPTY_PIX(empt)
1713 }
ca65c044 1714 for (empt = true, bottom = h-1; empt && bottom > top; bottom--)
06cc1fb9
JS
1715 {
1716 MK_DTTMP(0, bottom);
1717 for (i = 0; i < w; i++, dttmp+=3)
1718 NOEMPTY_PIX(empt)
1719 }
ca65c044 1720 for (empt = true, left = 0; empt && left < w; left++)
06cc1fb9
JS
1721 {
1722 MK_DTTMP(left, 0);
1723 for (i = 0; i < h; i++, dttmp+=3*w)
1724 NOEMPTY_PIX(empt)
1725 }
ca65c044 1726 for (empt = true, right = w-1; empt && right > left; right--)
06cc1fb9
JS
1727 {
1728 MK_DTTMP(right, 0);
1729 for (i = 0; i < h; i++, dttmp+=3*w)
1730 NOEMPTY_PIX(empt)
1731 }
1732 top--, left--, bottom++, right++;
1733
1734 return img.GetSubImage(wxRect(left, top, right - left + 1, bottom - top + 1));
1735}
b126fe3a
DS
1736#endif // #if 0
1737
06cc1fb9
JS
1738#endif // wxUSE_MIMETYPE
1739
1740int wxFileIconsTable::GetIconID(const wxString& extension, const wxString& mime)
1741{
1742 if (!m_smallImageList)
1743 Create();
1744
1745#if wxUSE_MIMETYPE
44d60c0b 1746 if (!extension.empty())
06cc1fb9
JS
1747 {
1748 wxFileIconEntry *entry = (wxFileIconEntry*) m_HashTable->Get(extension);
c1ec7ee8 1749 if (entry) return (entry -> iconid);
06cc1fb9
JS
1750 }
1751
44d60c0b 1752 wxFileType *ft = (mime.empty()) ?
06cc1fb9
JS
1753 wxTheMimeTypesManager -> GetFileTypeFromExtension(extension) :
1754 wxTheMimeTypesManager -> GetFileTypeFromMimeType(mime);
55d0aaa3
VZ
1755
1756 wxIconLocation iconLoc;
06cc1fb9 1757 wxIcon ic;
02dd0487 1758
55d0aaa3 1759 {
02dd0487
JS
1760 wxLogNull logNull;
1761 if ( ft && ft->GetIcon(&iconLoc) )
1762 {
8e5c6521 1763 ic = wxIcon( iconLoc );
02dd0487 1764 }
55d0aaa3 1765 }
ca65c044 1766
55d0aaa3
VZ
1767 delete ft;
1768
a1b806b9 1769 if ( !ic.IsOk() )
06cc1fb9
JS
1770 {
1771 int newid = file;
1772 m_HashTable->Put(extension, new wxFileIconEntry(newid));
1773 return newid;
1774 }
1775
3fc93ebd
JS
1776 wxBitmap bmp;
1777 bmp.CopyFromIcon(ic);
06cc1fb9 1778
a1b806b9 1779 if ( !bmp.IsOk() )
b6668c25
JS
1780 {
1781 int newid = file;
1782 m_HashTable->Put(extension, new wxFileIconEntry(newid));
1783 return newid;
1784 }
1785
1d529ef7 1786 const unsigned int size = 16;
ca65c044 1787
c1ec7ee8 1788 int treeid = m_smallImageList->GetImageCount();
1aa81b17 1789 if ((bmp.GetWidth() == (int) size) && (bmp.GetHeight() == (int) size))
1d529ef7 1790 {
3fc93ebd 1791 m_smallImageList->Add(bmp);
1d529ef7 1792 }
bb5a9514 1793#if wxUSE_IMAGE && (!defined(__WINDOWS__) || wxUSE_WXDIB)
06cc1fb9
JS
1794 else
1795 {
3fc93ebd
JS
1796 wxImage img = bmp.ConvertToImage();
1797
1d529ef7
RR
1798 if ((img.GetWidth() != size*2) || (img.GetHeight() != size*2))
1799// m_smallImageList->Add(CreateAntialiasedBitmap(CutEmptyBorders(img).Rescale(size*2, size*2)));
1800 m_smallImageList->Add(CreateAntialiasedBitmap(img.Rescale(size*2, size*2)));
06cc1fb9
JS
1801 else
1802 m_smallImageList->Add(CreateAntialiasedBitmap(img));
1803 }
1904aa72
DS
1804#endif // wxUSE_IMAGE
1805
c1ec7ee8
SC
1806 m_HashTable->Put(extension, new wxFileIconEntry(treeid));
1807 return treeid;
06cc1fb9
JS
1808
1809#else // !wxUSE_MIMETYPE
1810
79e162f5 1811 wxUnusedVar(mime);
06cc1fb9
JS
1812 if (extension == wxT("exe"))
1813 return executable;
1814 else
1815 return file;
1816#endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE
1817}
1818
13de0c8c 1819#endif // wxUSE_DIRDLG || wxUSE_FILEDLG