+ // Append a separator to foil bogus substring matching
+ path2 += wxString(wxFILE_SEP_PATH);
+
+ // In MSW or PM, case is not significant
+#if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)
+ path2.MakeLower();
+#endif
+
+ wxTreeItemIdValue cookie;
+ wxTreeItemId childId = m_treeCtrl->GetFirstChild(parentId, cookie);
+ while (childId.IsOk())
+ {
+ wxDirItemData* data = (wxDirItemData*) m_treeCtrl->GetItemData(childId);
+
+ if (data && !data->m_path.IsEmpty())
+ {
+ wxString childPath(data->m_path);
+ if (!wxEndsWithPathSeparator(childPath))
+ childPath += wxString(wxFILE_SEP_PATH);
+
+ // In MSW and PM, case is not significant
+#if defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)
+ childPath.MakeLower();
+#endif
+
+ if (childPath.Len() <= path2.Len())
+ {
+ wxString path3 = path2.Mid(0, childPath.Len());
+ if (childPath == path3)
+ {
+ if (path3.Len() == path2.Len())
+ done = true;
+ else
+ done = false;
+ return childId;
+ }
+ }
+ }
+
+ childId = m_treeCtrl->GetNextChild(parentId, cookie);
+ }
+ wxTreeItemId invalid;
+ return invalid;
+}
+
+// Try to expand as much of the given path as possible,
+// and select the given tree item.
+bool wxGenericDirCtrl::ExpandPath(const wxString& path)
+{
+ bool done = false;
+ wxTreeItemId id = FindChild(m_rootId, path, done);
+ wxTreeItemId lastId = id; // The last non-zero id
+ while (id.IsOk() && !done)
+ {
+ ExpandDir(id);
+
+ id = FindChild(id, path, done);
+ if (id.IsOk())
+ lastId = id;
+ }
+ if (lastId.IsOk())
+ {
+ wxDirItemData *data = (wxDirItemData *) m_treeCtrl->GetItemData(lastId);
+ if (data->m_isDir)
+ {
+ m_treeCtrl->Expand(lastId);
+ }
+ if ((GetWindowStyle() & wxDIRCTRL_SELECT_FIRST) && data->m_isDir)
+ {
+ // Find the first file in this directory
+ wxTreeItemIdValue cookie;
+ wxTreeItemId childId = m_treeCtrl->GetFirstChild(lastId, cookie);
+ bool selectedChild = false;
+ while (childId.IsOk())
+ {
+ wxDirItemData* data = (wxDirItemData*) m_treeCtrl->GetItemData(childId);
+
+ if (data && data->m_path != wxEmptyString && !data->m_isDir)
+ {
+ m_treeCtrl->SelectItem(childId);
+ m_treeCtrl->EnsureVisible(childId);
+ selectedChild = true;
+ break;
+ }
+ childId = m_treeCtrl->GetNextChild(lastId, cookie);
+ }
+ if (!selectedChild)
+ {
+ m_treeCtrl->SelectItem(lastId);
+ m_treeCtrl->EnsureVisible(lastId);
+ }
+ }
+ else
+ {
+ m_treeCtrl->SelectItem(lastId);
+ m_treeCtrl->EnsureVisible(lastId);
+ }
+
+ return true;
+ }
+ else
+ return false;
+}
+
+wxString wxGenericDirCtrl::GetPath() const
+{
+ wxTreeItemId id = m_treeCtrl->GetSelection();
+ if (id)
+ {
+ wxDirItemData* data = (wxDirItemData*) m_treeCtrl->GetItemData(id);
+ return data->m_path;
+ }
+ else
+ return wxEmptyString;
+}
+
+wxString wxGenericDirCtrl::GetFilePath() const
+{
+ wxTreeItemId id = m_treeCtrl->GetSelection();
+ if (id)
+ {
+ wxDirItemData* data = (wxDirItemData*) m_treeCtrl->GetItemData(id);
+ if (data->m_isDir)
+ return wxEmptyString;
+ else
+ return data->m_path;
+ }
+ else
+ return wxEmptyString;
+}
+
+void wxGenericDirCtrl::SetPath(const wxString& path)
+{
+ m_defaultPath = path;
+ if (m_rootId)
+ ExpandPath(path);
+}
+
+// Not used
+#if 0
+void wxGenericDirCtrl::FindChildFiles(wxTreeItemId id, int dirFlags, wxArrayString& filenames)
+{
+ wxDirItemData *data = (wxDirItemData *) m_treeCtrl->GetItemData(id);
+
+ // This may take a longish time. Go to busy cursor
+ wxBusyCursor busy;
+
+ wxASSERT(data);
+
+ wxString search,path,filename;
+
+ wxString dirName(data->m_path);
+
+#if defined(__WXMSW__) || defined(__OS2__)
+ if (dirName.Last() == ':')
+ dirName += wxString(wxFILE_SEP_PATH);
+#endif
+
+ wxDir d;
+ wxString eachFilename;
+
+ wxLogNull log;
+ d.Open(dirName);
+
+ if (d.IsOpened())
+ {
+ if (d.GetFirst(& eachFilename, m_currentFilterStr, dirFlags))
+ {
+ do
+ {
+ if ((eachFilename != wxT(".")) && (eachFilename != wxT("..")))
+ {
+ filenames.Add(eachFilename);
+ }
+ }
+ while (d.GetNext(& eachFilename)) ;
+ }
+ }
+}
+#endif
+
+void wxGenericDirCtrl::SetFilterIndex(int n)
+{
+ m_currentFilter = n;
+
+ wxString f, d;
+ if (ExtractWildcard(m_filter, n, f, d))
+ m_currentFilterStr = f;
+ else
+ m_currentFilterStr = wxT("*.*");
+}
+
+void wxGenericDirCtrl::SetFilter(const wxString& filter)
+{
+ m_filter = filter;
+
+ wxString f, d;
+ if (ExtractWildcard(m_filter, m_currentFilter, f, d))
+ m_currentFilterStr = f;
+ else
+ m_currentFilterStr = wxT("*.*");
+}
+
+// Extract description and actual filter from overall filter string
+bool wxGenericDirCtrl::ExtractWildcard(const wxString& filterStr, int n, wxString& filter, wxString& description)
+{
+ wxArrayString filters, descriptions;
+ int count = wxParseCommonDialogsFilter(filterStr, descriptions, filters);
+ if (count > 0 && n < count)
+ {
+ filter = filters[n];
+ description = descriptions[n];
+ return true;
+ }
+
+ return false;
+}
+
+#if WXWIN_COMPATIBILITY_2_4
+// Parses the global filter, returning the number of filters.
+// Returns 0 if none or if there's a problem.
+// filterStr is in the form: "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpg"
+int wxGenericDirCtrl::ParseFilter(const wxString& filterStr, wxArrayString& filters, wxArrayString& descriptions)
+{
+ return wxParseCommonDialogsFilter(filterStr, descriptions, filters );
+}
+#endif // WXWIN_COMPATIBILITY_2_4
+
+void wxGenericDirCtrl::DoResize()
+{
+ wxSize sz = GetClientSize();
+ int verticalSpacing = 3;
+ if (m_treeCtrl)
+ {
+ wxSize filterSz ;
+ if (m_filterListCtrl)
+ {
+#ifdef __WXMSW__
+ // For some reason, this is required in order for the
+ // correct control height to always be returned, rather
+ // than the drop-down list height which is sometimes returned.
+ wxSize oldSize = m_filterListCtrl->GetSize();
+ m_filterListCtrl->SetSize(wxDefaultCoord,
+ wxDefaultCoord,
+ oldSize.x+10,
+ wxDefaultCoord,
+ wxSIZE_USE_EXISTING);
+ m_filterListCtrl->SetSize(wxDefaultCoord,
+ wxDefaultCoord,
+ oldSize.x,
+ wxDefaultCoord,
+ wxSIZE_USE_EXISTING);
+#endif
+ filterSz = m_filterListCtrl->GetSize();
+ sz.y -= (filterSz.y + verticalSpacing);
+ }
+ m_treeCtrl->SetSize(0, 0, sz.x, sz.y);
+ if (m_filterListCtrl)
+ {
+ m_filterListCtrl->SetSize(0, sz.y + verticalSpacing, sz.x, filterSz.y);
+ // Don't know why, but this needs refreshing after a resize (wxMSW)
+ m_filterListCtrl->Refresh();
+ }
+ }
+}
+
+
+void wxGenericDirCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+ DoResize();
+}
+
+wxTreeItemId wxGenericDirCtrl::AppendItem (const wxTreeItemId & parent,
+ const wxString & text,
+ int image, int selectedImage,
+ wxTreeItemData * data)
+{
+ wxTreeCtrl *treeCtrl = GetTreeCtrl ();
+
+ wxASSERT (treeCtrl);
+
+ if (treeCtrl)
+ {
+ return treeCtrl->AppendItem (parent, text, image, selectedImage, data);
+ }
+ else
+ {
+ return wxTreeItemId();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// wxDirFilterListCtrl
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(wxDirFilterListCtrl, wxChoice)
+
+BEGIN_EVENT_TABLE(wxDirFilterListCtrl, wxChoice)
+ EVT_CHOICE(wxID_ANY, wxDirFilterListCtrl::OnSelFilter)
+END_EVENT_TABLE()
+
+bool wxDirFilterListCtrl::Create(wxGenericDirCtrl* parent, const wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style)
+{
+ m_dirCtrl = parent;
+ return wxChoice::Create(parent, id, pos, size, 0, NULL, style);
+}
+
+void wxDirFilterListCtrl::Init()
+{
+ m_dirCtrl = NULL;
+}
+
+void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent& WXUNUSED(event))
+{
+ int sel = GetSelection();
+
+ wxString currentPath = m_dirCtrl->GetPath();
+
+ m_dirCtrl->SetFilterIndex(sel);
+
+ // If the filter has changed, the view is out of date, so
+ // collapse the tree.
+ m_dirCtrl->ReCreateTree();
+
+ // Try to restore the selection, or at least the directory
+ m_dirCtrl->ExpandPath(currentPath);
+}
+
+void wxDirFilterListCtrl::FillFilterList(const wxString& filter, int defaultFilter)
+{
+ Clear();
+ wxArrayString descriptions, filters;
+ size_t n = (size_t) wxParseCommonDialogsFilter(filter, filters, descriptions);
+
+ if (n > 0 && defaultFilter < (int) n)
+ {
+ for (size_t i = 0; i < n; i++)
+ Append(descriptions[i]);
+ SetSelection(defaultFilter);
+ }
+}
+#endif // wxUSE_DIRDLG
+
+#if wxUSE_DIRDLG || wxUSE_FILEDLG
+
+// ----------------------------------------------------------------------------
+// wxFileIconsTable icons
+// ----------------------------------------------------------------------------
+
+/* Open folder */
+static const char * file_icons_tbl_folder_open_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"16 16 6 1",
+/* colors */
+" s None c None",
+". c #000000",
+"+ c #c0c0c0",
+"@ c #808080",
+"# c #ffff00",
+"$ c #ffffff",
+/* pixels */
+" ",
+" @@@@@ ",
+" @$$$$$@ ",
+" @$#+#+#$@@@@@@ ",
+" @$+#+#+$$$$$$@.",
+" @$#+#+#+#+#+#@.",
+"@@@@@@@@@@@@@#@.",
+"@$$$$$$$$$$@@+@.",
+"@$#+#+#+#+##.@@.",
+" @$#+#+#+#+#+.@.",
+" @$+#+#+#+#+#.@.",
+" @$+#+#+#+##@..",
+" @@@@@@@@@@@@@.",
+" .............",
+" ",
+" "};
+
+/* Computer */
+static const char * file_icons_tbl_computer_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Black",
+"O c Gray100",
+"+ c #008080",
+"@ c Blue",
+" ........... ",
+" .XXXXXXXXXX.o",
+" .OOOOOOOOO..o",
+" .OoooooooX..o",
+" .Oo+...@+X..o",
+" .Oo+XXX.+X..o",
+" .Oo+....+X..o",
+" .Oo++++++X..o",
+" .OXXXXXXXX.oo",
+" ..........o.o",
+" ...........Xo",
+" .XXXXXXXXXX.o",
+" .o.o.o.o.o...o",
+" .oXoXoXoXoXo.o ",
+".XOXXXXXXXXX.o ",
+"............o "};
+
+/* Drive */
+static const char * file_icons_tbl_drive_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Black",
+"O c Gray100",
+"+ c Green",
+"@ c #008000",
+" ",
+" ",
+" ",
+" ",
+" ............. ",
+" .XXXXXXXXXXXX.o",
+".OOOOOOOOOOOO..o",
+".XXXXXXXXX+@X..o",
+".XXXXXXXXXXXX..o",
+".X..........X..o",
+".XOOOOOOOOOOX..o",
+"..............o ",
+" ooooooooooooo ",
+" ",
+" ",
+" "};
+
+/* CD-ROM */
+static const char *file_icons_tbl_cdrom_xpm[] = {
+"16 16 10 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Yellow",
+"O c Blue",
+"+ c Black",
+"@ c Gray100",
+"# c #008080",
+"$ c Green",
+"% c #008000",
+" ... ",
+" ..XoX.. ",
+" .O.XoXXX+ ",
+" ...O.oXXXX+ ",
+" .O..X.XXXX+ ",
+" ....X.+..XXX+",
+" .XXX.+@+.XXX+",
+" .X@XX.+.X@@X+",
+" .....X...#XX@+ ",
+".@@@...XXo.O@X+ ",
+".@XXX..XXoXOO+ ",
+".@++++..XoX+++ ",
+".@$%@@XX+++X.+ ",
+".............+ ",
+" ++++++++++++ ",
+" "};
+
+/* Floppy */
+static const char * file_icons_tbl_floppy_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c Gray100",
+"o c #c0c0c0",
+"O c Black",
+"+ c Cyan",
+"@ c Red",
+" ......X",
+" .ooooooO",
+" .+++++OO",
+" .++++++O",
+" .++++++O",
+" .ooooooO",
+" .......o....oO",
+" .oooooo.o.O.XoO",
+".XXXXXXXXOOOOOO ",
+".ooooooooo@o..O ",
+".ooo....oooo..O ",
+".o..OOOO...o..O ",
+".oooXXXXoooo..O ",
+".............O ",
+" OOOOOOOOOOOO ",
+" "};
+
+/* Removeable */
+static const char * file_icons_tbl_removeable_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Black",
+"O c Gray100",
+"+ c Red",
+"@ c #800000",
+" ",
+" ",
+" ",
+" ............. ",
+" .XXXXXXXXXXXX.o",
+".OOOOOOOOOOOO..o",
+".OXXXXXXXXXXX..o",
+".O+@.oooooo.X..o",
+".OXXOooooooOX..o",
+".OXXXOOOOOOXX..o",
+".OXXXXXXXXXXX..o",
+".O............o ",
+" ooooooooooooo ",
+" ",
+" ",
+" "};
+
+// ----------------------------------------------------------------------------
+// wxFileIconsTable & friends
+// ----------------------------------------------------------------------------