#pragma hdrstop
#endif
-#include "wx/defs.h"
+#if wxUSE_DIRDLG
#include "wx/utils.h"
#include "wx/dialog.h"
#include "wx/button.h"
#include "wx/layout.h"
#include "wx/msgdlg.h"
+#include "wx/textctrl.h"
#include "wx/textdlg.h"
#include "wx/filefn.h"
#include "wx/cmndata.h"
#ifdef __WXMSW__
#include <windows.h>
+
+// FIXME - Mingw32 1.0 has both _getdrive() and _chdrive(). For now, let's assume
+// older releases don't, but it should be verified and the checks modified
+// accordingly.
+#if !defined(__GNUWIN32__) || \
+ (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
+ #include <direct.h>
+ #include <stdlib.h>
+ #include <ctype.h>
+#endif
+
+#endif
+
+#ifdef __WXPM__
+
+#define INCL_BASE
+#include <os2.h>
#include <direct.h>
#include <stdlib.h>
#include <ctype.h>
+
+#endif // __WXPM__
+
+#if defined(__WXMAC__)
+# include "MoreFilesExtras.h"
+#endif
+
+#ifdef __BORLANDC__
+#include "dos.h"
#endif
// If compiled under Windows, this macro can cause problems
#undef GetFirstChild
#endif
-#if !defined(__WXMSW__) || wxUSE_XPM_IN_MSW
/* Closed folder */
static char * icon1_xpm[] = {
/* width height ncolors chars_per_pixel */
" ",
" ",
" "};
-#endif // !wxMSW
static const int ID_DIRCTRL = 1000;
static const int ID_TEXTCTRL = 1001;
static const int ID_NEW = 1004;
//static const int ID_CHECK = 1005;
-#ifdef __WXMSW__
+#if defined(__WXMSW__) || defined(__WXPM__) || defined(__DOS__)
+int setdrive(int drive)
+{
+#if defined(__GNUWIN32__) && \
+ (defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
+ return _chdrive(drive);
+#else
+ wxChar newdrive[3];
+
+ if (drive < 1 || drive > 31)
+ return -1;
+ newdrive[0] = (wxChar)(wxT('A') + drive - 1);
+ newdrive[1] = wxT(':');
+ newdrive[2] = wxT('\0');
+#if defined(__WXMSW__)
+#ifdef __WIN16__
+ if (wxSetWorkingDirectory(newdrive))
+#else
+ if (::SetCurrentDirectory(newdrive))
+#endif
+#else
+ // VA doesn't know what LPSTR is and has its own set
+ if (DosSetCurrentDir((PSZ)newdrive))
+#endif
+ return 0;
+ else
+ return -1;
+#endif // !GNUWIN32
+}
+
static bool wxIsDriveAvailable(const wxString dirName)
{
#ifdef __WIN32__
if (dirName.Len() == 3 && dirName[(size_t)1] == wxT(':'))
{
wxString dirNameLower(dirName.Lower());
+#if defined(__GNUWIN32__) && \
+ !(defined(__MINGW32_MAJOR_VERSION) && __MINGW32_MAJOR_VERSION >= 1)
+ success = wxPathExists(dirNameLower);
+#else
int currentDrive = _getdrive();
int thisDrive = (int) (dirNameLower[(size_t)0] - 'a' + 1) ;
- int err = _chdrive( thisDrive ) ;
- _chdrive( currentDrive );
+ int err = setdrive( thisDrive ) ;
+ setdrive( currentDrive );
if (err == -1)
{
success = FALSE;
}
+#endif
}
#ifdef __WIN32__
(void) SetErrorMode(errorMode);
}
#endif
+// Function which is called by quick sort. We want to override the default wxArrayString behaviour,
+// and sort regardless of case.
+static int LINKAGEMODE wxDirCtrlStringCompareFunction(const void *first, const void *second)
+{
+ wxString *strFirst = (wxString *)first;
+ wxString *strSecond = (wxString *)second;
+
+ return strFirst->CmpNoCase(*strSecond);
+}
+
//-----------------------------------------------------------------------------
// wxDirItemDataEx
//-----------------------------------------------------------------------------
* For FileNameFromPath read LastDirNameInThisPath ;-) */
// m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.');
m_isHidden = FALSE;
- m_hasSubDirs = HasSubDirs();
+ // m_hasSubDirs is no longer needed
+ m_hasSubDirs = TRUE; // HasSubDirs();
m_isExpanded = FALSE;
m_isDir = isDir;
}
m_name = wxFileNameFromPath( path );
}
-bool wxDirItemDataEx::HasSubDirs()
-{
- if (m_path.IsEmpty())
- return TRUE;
-
- // On WIN32, must check if this volume is mounted or
- // we get an error dialog for e.g. drive a:
-#ifdef __WIN32__
- if (!wxIsDriveAvailable(m_path))
- return FALSE;
-#endif
-
- wxString search = m_path;
-
- if (m_path.Last() != wxFILE_SEP_PATH)
- {
- search += wxString(wxFILE_SEP_PATH);
- }
- search += wxT("*");
-
- wxLogNull log;
- wxString path = wxFindFirstFile( search, wxDIR );
- return (bool)(!path.IsNull());
-}
-
//-----------------------------------------------------------------------------
// wxGenericDirCtrl
//-----------------------------------------------------------------------------
Init();
- long treeStyle = wxTR_HAS_BUTTONS;
+ long treeStyle = wxTR_HAS_BUTTONS ; // | wxTR_EDIT_LABELS;
if ((style & wxDIRCTRL_3D_INTERNAL) == 0)
treeStyle |= wxNO_BORDER;
m_filterListCtrl->FillFilterList(filter, defaultFilter);
m_imageList = new wxImageList(16, 16, TRUE);
-#if !defined(__WXMSW__) || wxUSE_XPM_IN_MSW
m_imageList->Add(wxIcon(icon1_xpm));
m_imageList->Add(wxIcon(icon2_xpm));
m_imageList->Add(wxIcon(icon3_xpm));
m_imageList->Add(wxIcon(icon6_xpm));
m_imageList->Add(wxIcon(icon7_xpm));
m_imageList->Add(wxIcon(icon8_xpm));
-#elif defined(__WXMSW__)
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_CLOSED_FOLDER"), wxBITMAP_TYPE_ICO_RESOURCE));
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_OPEN_FOLDER"), wxBITMAP_TYPE_ICO_RESOURCE));
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_FILE"), wxBITMAP_TYPE_ICO_RESOURCE));
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_COMPUTER"), wxBITMAP_TYPE_ICO_RESOURCE));
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_DRIVE"), wxBITMAP_TYPE_ICO_RESOURCE));
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_CDROM"), wxBITMAP_TYPE_ICO_RESOURCE));
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_FLOPPY"), wxBITMAP_TYPE_ICO_RESOURCE));
- m_imageList->Add(wxIcon(wxT("wxICON_SMALL_REMOVEABLE"), wxBITMAP_TYPE_ICO_RESOURCE));
-#else
-#error "Sorry, we don't have icons available for this platforms."
-#endif
m_treeCtrl->SetImageList(m_imageList);
m_showHidden = FALSE;
wxString rootName;
-#ifdef __WXMSW__
+#if defined(__WXMSW__) || defined(__WXPM__)
rootName = _("Computer");
#else
rootName = _("Sections");
{
wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,name,TRUE);
-#ifdef __WXMSW__
- // Windows: sections are displayed as drives
+#if defined(__WXMSW__) || defined(__WXPM__)
+ // Windows and OS/2: sections are displayed as drives
wxTreeItemId id = m_treeCtrl->AppendItem( m_rootId, name, imageId, -1, dir_item);
#else
// Unix: sections are displayed as folders
void wxGenericDirCtrl::SetupSections()
{
-#ifdef __WXMSW__
+#if defined(__WXMSW__) || defined(__WXPM__)
-#ifdef __WIN32__
+# ifdef __WIN32__
wxChar driveBuffer[256];
size_t n = (size_t) GetLogicalDriveStrings(255, driveBuffer);
size_t i = 0;
if (driveBuffer[i] == wxT('\0'))
break;
}
-#else
+# else
int drive;
int currentDrive;
if (wxIsDriveAvailable(path))
{
-
+
AddSection(path, name);
}
}
-#endif
-
+# endif
+#elif defined(__WXMAC__)
+ FSSpec volume ;
+ short index = 1 ;
+ while(1) {
+ short actualCount = 0 ;
+ if ( OnLine( &volume , 1 , &actualCount , &index ) != noErr || actualCount == 0 )
+ break ;
+
+ wxString name = wxMacFSSpec2MacFilename( &volume ) ;
+ AddSection(name + wxFILE_SEP_PATH, name, 0);
+ }
#else
AddSection(wxT("/"), _("The Computer"), 0);
AddSection(wxGetHomeDir(), _("My Home"), 0 );
wxString dirName(data->m_path);
-#ifdef __WXMSW__
+#if defined(__WXMSW__) || defined(__WXPM__)
// Check if this is a root directory and if so,
// whether the drive is avaiable.
if (!wxIsDriveAvailable(dirName))
{
data->m_isExpanded = FALSE;
- wxMessageBox(wxT("Sorry, this drive is not available."));
- return;
+ //wxMessageBox(wxT("Sorry, this drive is not available."));
+ return;
}
#endif
// This may take a longish time. Go to busy cursor
wxBusyCursor busy;
-#ifdef __WXMSW__
+#if defined(__WXMSW__) || defined(__WXPM__)
if (dirName.Last() == ':')
dirName += wxString(wxFILE_SEP_PATH);
#endif
while (d.GetNext(& eachFilename)) ;
}
}
- dirs.Sort();
+ dirs.Sort((wxArrayString::CompareFunction) wxDirCtrlStringCompareFunction);
// Now do the filenames -- but only if we're allowed to
if ((GetWindowStyle() & wxDIRCTRL_DIR_ONLY) == 0)
wxLogNull log;
d.Open(dirName);
-
+
if (d.IsOpened())
{
if (d.GetFirst(& eachFilename, m_currentFilterStr, wxDIR_FILES))
while (d.GetNext(& eachFilename)) ;
}
}
- filenames.Sort();
+ filenames.Sort((wxArrayString::CompareFunction) wxDirCtrlStringCompareFunction);
}
// Add the sorted dirs
wxDirItemDataEx *dir_item = new wxDirItemDataEx(path,eachFilename,TRUE);
wxTreeItemId id = m_treeCtrl->AppendItem( parentId, eachFilename, 0, -1, dir_item);
m_treeCtrl->SetItemImage( id, 1, wxTreeItemIcon_Expanded );
-
+
// Has this got any children? If so, make it expandable.
int options = wxDIR_DEFAULT;
if (GetWindowStyle() & wxDIRCTRL_DIR_ONLY) // If only showing dirs, then we specify dirs only here
wxTreeItemId wxGenericDirCtrl::FindChild(wxTreeItemId parentId, const wxString& path, bool& done)
{
wxString path2(path);
-
+
// Make sure all separators are as per the current platform
path2.Replace(wxT("\\"), wxString(wxFILE_SEP_PATH));
path2.Replace(wxT("/"), wxString(wxFILE_SEP_PATH));
-
+
// Append a separator to foil bogus substring matching
path2 += wxString(wxFILE_SEP_PATH);
-
- // In MSW, case is not significant
-#ifdef __WXMSW__
+
+ // In MSW or PM, case is not significant
+#if defined(__WXMSW__) || defined(__WXPM__)
path2.MakeLower();
#endif
-
+
long cookie;
wxTreeItemId childId = m_treeCtrl->GetFirstChild(parentId, cookie);
- while (childId != 0)
+ while (childId.IsOk())
{
wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(childId);
-
+
if (data && data->m_path != "")
{
wxString childPath(data->m_path);
if (childPath.Last() != wxFILE_SEP_PATH)
childPath += wxString(wxFILE_SEP_PATH);
-
- // In MSW, case is not significant
-#ifdef __WXMSW__
+
+ // In MSW and PM, case is not significant
+#if defined(__WXMSW__) || defined(__WXPM__)
childPath.MakeLower();
#endif
-
+
if (childPath.Len() <= path2.Len())
{
wxString path3 = path2.Mid(0, childPath.Len());
}
}
}
-
+
childId = m_treeCtrl->GetNextChild(childId, cookie);
}
wxTreeItemId invalid;
bool done = FALSE;
wxTreeItemId id = FindChild(m_rootId, path, done);
wxTreeItemId lastId = id; // The last non-zero id
- while ((id > 0) && !done)
+ while (id.IsOk() && !done)
{
ExpandDir(id);
id = FindChild(id, path, done);
- if (id != 0)
+ if (id.IsOk())
lastId = id;
}
- if (lastId > 0)
+ if (lastId.IsOk())
{
wxDirItemDataEx *data = (wxDirItemDataEx *) m_treeCtrl->GetItemData(lastId);
if (data->m_isDir)
long cookie;
wxTreeItemId childId = m_treeCtrl->GetFirstChild(lastId, cookie);
bool selectedChild = FALSE;
- while (childId != 0)
+ while (childId.IsOk())
{
wxDirItemDataEx* data = (wxDirItemDataEx*) m_treeCtrl->GetItemData(childId);
-
+
if (data && data->m_path != "" && !data->m_isDir)
{
m_treeCtrl->SelectItem(childId);
wxString dirName(data->m_path);
-#ifdef __WXMSW__
+#if defined(__WXMSW__) || defined(__WXPM__)
if (dirName.Last() == ':')
dirName += wxString(wxFILE_SEP_PATH);
#endif
description = descriptions[n];
return TRUE;
}
- else
- return FALSE;
+
+ return FALSE;
}
// Parses the global filter, returning the number of filters.
}
-void wxGenericDirCtrl::OnSize(wxSizeEvent &event)
+void wxGenericDirCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
{
DoResize();
}
m_dirCtrl = NULL;
}
-void wxDirFilterListCtrl::OnSelFilter(wxCommandEvent& event)
+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
BEGIN_EVENT_TABLE(wxGenericDirDialog, wxDialog)
EVT_BUTTON(wxID_OK, wxGenericDirDialog::OnOK)
+ EVT_BUTTON(wxID_NEW, wxGenericDirDialog::OnNew)
+ EVT_BUTTON (wxID_NEW, wxGenericDirDialog::OnNew)
EVT_CLOSE(wxGenericDirDialog::OnCloseWindow)
+ EVT_TREE_KEY_DOWN (-1, wxGenericDirDialog::OnTreeKeyDown)
+ EVT_TREE_SEL_CHANGED (-1, wxGenericDirDialog::OnTreeSelected)
+ EVT_TEXT_ENTER (ID_TEXTCTRL, wxGenericDirDialog::OnOK)
END_EVENT_TABLE()
wxGenericDirDialog::wxGenericDirDialog(wxWindow* parent, const wxString& title,
const wxString& defaultPath, long style, const wxPoint& pos, const wxSize& sz, const wxString& name):
wxDialog(parent, ID_DIRCTRL, title, pos, sz, style, name)
{
+ m_dirCtrl = NULL;
+ m_path = defaultPath;
+
wxBusyCursor cursor;
wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
topsizer->Add( m_dirCtrl, 1, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 10 );
- // 2) TODO: text control for entering path?
+ // 2) text ctrl
+ m_input = new wxTextCtrl( this, ID_TEXTCTRL, m_path, wxDefaultPosition );
+ topsizer->Add( m_input, 0, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 10 );
#if wxUSE_STATLINE
// 3) Static line
wxButton* cancelButton = new wxButton(this, wxID_CANCEL, _("Cancel"));
buttonsizer->Add( cancelButton, 0, wxLEFT|wxRIGHT, 10 );
-/* TODO: new directory button
- wxButton* newButton = new wxButton( this, ID_NEW, _("New...") );
+ // I'm not convinced we need a New button, and we tend to get annoying
+ // accidental-editing with label editing enabled.
+#if 0
+ wxButton* newButton = new wxButton( this, wxID_NEW, _("New...") );
buttonsizer->Add( newButton, 0, wxLEFT|wxRIGHT, 10 );
-*/
+#endif
+
topsizer->Add( buttonsizer, 0, wxALL | wxCENTER, 10 );
okButton->SetDefault();
Centre( wxBOTH );
}
-void wxGenericDirDialog::OnCloseWindow(wxCloseEvent& event)
+void wxGenericDirDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
{
EndModal(wxID_CANCEL);
}
-void wxGenericDirDialog::OnOK(wxCommandEvent& event)
+void wxGenericDirDialog::OnOK(wxCommandEvent& WXUNUSED(event))
{
- EndModal(wxID_OK);
+ m_path = m_input->GetValue();
+ // Does the path exist? (User may have typed anything in m_input)
+ if (wxPathExists(m_path)) {
+ // OK, path exists, we're done.
+ EndModal(wxID_OK);
+ return;
+ }
+ // Interact with user, find out if the dir is a typo or to be created
+ wxString msg( _("The directory ") );
+ msg = msg + m_path;
+ msg = msg + _("\ndoes not exist\nCreate it now?") ;
+ wxMessageDialog dialog(this, msg, _("Directory does not exist"), wxYES_NO | wxICON_WARNING );
+ if ( dialog.ShowModal() == wxID_YES ) {
+ // Okay, let's make it
+ wxLogNull log;
+ if (wxMkdir(m_path)) {
+ // The new dir was created okay.
+ EndModal(wxID_OK);
+ return;
+ }
+ else {
+ // Trouble...
+ msg = _("Failed to create directory ")+m_path+
+ _("\n(Do you have the required permissions?)");
+ wxMessageDialog errmsg(this, msg, _("Error creating directory"), wxOK | wxICON_ERROR);
+ errmsg.ShowModal();
+ // We still don't have a valid dir. Back to the main dialog.
+ }
+ }
+ // User has answered NO to create dir.
}
void wxGenericDirDialog::SetPath(const wxString& path)
{
m_dirCtrl->SetPath(path);
+ m_path = path;
}
wxString wxGenericDirDialog::GetPath(void) const
{
- return m_dirCtrl->GetPath();
+ return m_path;
+}
+
+int wxGenericDirDialog::ShowModal()
+{
+ //m_input->SetValue( m_path );
+ return wxDialog::ShowModal();
}
+
+void wxGenericDirDialog::OnTreeSelected( wxTreeEvent &event )
+{
+ if (!m_dirCtrl)
+ return;
+
+ wxDirItemDataEx *data = (wxDirItemDataEx*)m_dirCtrl->GetTreeCtrl()->GetItemData(event.GetItem());
+ if (data)
+ m_input->SetValue( data->m_path );
+};
+
+void wxGenericDirDialog::OnTreeKeyDown( wxTreeEvent &WXUNUSED(event) )
+{
+ if (!m_dirCtrl)
+ return;
+
+ wxDirItemDataEx *data = (wxDirItemDataEx*)m_dirCtrl->GetTreeCtrl()->GetItemData(m_dirCtrl->GetTreeCtrl()->GetSelection());
+ if (data)
+ m_input->SetValue( data->m_path );
+};
+
+void wxGenericDirDialog::OnNew( wxCommandEvent& WXUNUSED(event) )
+{
+ wxTreeItemId id = m_dirCtrl->GetTreeCtrl()->GetSelection();
+ if ((id == m_dirCtrl->GetTreeCtrl()->GetRootItem()) ||
+ (m_dirCtrl->GetTreeCtrl()->GetParent(id) == m_dirCtrl->GetTreeCtrl()->GetRootItem()))
+ {
+ wxMessageDialog msg(this, _("You cannot add a new directory to this section."),
+ _("Create directory"), wxOK | wxICON_INFORMATION );
+ msg.ShowModal();
+ return;
+ }
+
+ wxTreeItemId parent = id ; // m_dirCtrl->GetTreeCtrl()->GetParent( id );
+ wxDirItemDataEx *data = (wxDirItemDataEx*)m_dirCtrl->GetTreeCtrl()->GetItemData( parent );
+ wxASSERT( data );
+
+ wxString new_name( wxT("NewName") );
+ wxString path( data->m_path );
+ if (path.Last() != wxFILE_SEP_PATH)
+ path += wxFILE_SEP_PATH;
+ path += new_name;
+ if (wxFileExists(path))
+ {
+ // try NewName0, NewName1 etc.
+ int i = 0;
+ do {
+ new_name = wxT("NewName");
+ wxString num;
+ num.Printf( wxT("%d"), i );
+ new_name += num;
+
+ path = data->m_path;
+ if (path.Last() != wxFILE_SEP_PATH)
+ path += wxFILE_SEP_PATH;
+ path += new_name;
+ i++;
+ } while (wxFileExists(path));
+ }
+
+ wxLogNull log;
+ if (!wxMkdir(path))
+ {
+ wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR );
+ dialog.ShowModal();
+ return;
+ }
+
+ wxDirItemDataEx *new_data = new wxDirItemDataEx( path, new_name, TRUE );
+
+ // TODO: THIS CODE DOESN'T WORK YET. We need to avoid duplication of the first child
+ // of the parent.
+ wxTreeItemId new_id = m_dirCtrl->GetTreeCtrl()->AppendItem( parent, new_name, 0, 0, new_data );
+ m_dirCtrl->GetTreeCtrl()->EnsureVisible( new_id );
+ m_dirCtrl->GetTreeCtrl()->EditLabel( new_id );
+}
+
+#endif // wxUSE_DIRDLG