X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d7a15103f7307a27c35a0c1cad095cda50d64aea..765e386bfab10b2e035a993fb09301f5c1239842:/src/generic/dirdlgg.cpp diff --git a/src/generic/dirdlgg.cpp b/src/generic/dirdlgg.cpp index b4b93e0035..ecea39fa8f 100644 --- a/src/generic/dirdlgg.cpp +++ b/src/generic/dirdlgg.cpp @@ -4,6 +4,7 @@ // Author: Harm van der Heijden and Robert Roebling // Modified by: // Created: 12/12/98 +// RCS-ID: $Id$ // Copyright: (c) Harm van der Heijden and Robert Roebling // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -12,7 +13,17 @@ #pragma implementation "dirdlgg.h" #endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + #include "wx/defs.h" + +#if wxUSE_DIRDLG + #include "wx/utils.h" #include "wx/dialog.h" #include "wx/button.h" @@ -24,9 +35,21 @@ #include "wx/gdicmn.h" #include "wx/intl.h" #include "wx/imaglist.h" +#include "wx/icon.h" +#include "wx/log.h" +#include "wx/sizer.h" + +#if wxUSE_STATLINE + #include "wx/statline.h" +#endif #include "wx/generic/dirdlgg.h" +// If compiled under Windows, this macro can cause problems +#ifdef GetFirstChild +#undef GetFirstChild +#endif + /* XPM */ static char * icon1_xpm[] = { /* width height ncolors chars_per_pixel */ @@ -56,6 +79,34 @@ static char * icon1_xpm[] = { " ", " "}; +/* XPM */ +static char * icon2_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 */ +" ", +" @@@@@ ", +" @$$$$$@ ", +" @$#+#+#$@@@@@@ ", +" @$+#+#+$$$$$$@.", +" @$#+#+#+#+#+#@.", +"@@@@@@@@@@@@@#@.", +"@$$$$$$$$$$@@+@.", +"@$#+#+#+#+##.@@.", +" @$#+#+#+#+#+.@.", +" @$+#+#+#+#+#.@.", +" @$+#+#+#+##@..", +" @@@@@@@@@@@@@.", +" .............", +" ", +" "}; static const int ID_DIRCTRL = 1000; static const int ID_TEXTCTRL = 1001; @@ -70,27 +121,32 @@ static const int ID_NEW = 1004; wxDirItemData::wxDirItemData(wxString& path, wxString& name) { - m_path = new wxString(path); - m_name = new wxString(name); - /* Insert logic to detect hidden files here - * In UnixLand we just check whether the first char is a dot - * For FileNameFromPath read LastDirNameInThisPath ;-) */ - // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.'); - m_isHidden = FALSE; - m_hasSubDirs = HasSubDirs(); + m_path = path; + m_name = name; + /* Insert logic to detect hidden files here + * In UnixLand we just check whether the first char is a dot + * For FileNameFromPath read LastDirNameInThisPath ;-) */ + // m_isHidden = (bool)(wxFileNameFromPath(*m_path)[0] == '.'); + m_isHidden = FALSE; + m_hasSubDirs = HasSubDirs(); } -wxDirItemData:: ~wxDirItemData() +wxDirItemData::~wxDirItemData() { - delete m_path; - delete m_name; +} + +void wxDirItemData::SetNewDirName( wxString path ) +{ + m_path = path; + m_name = wxFileNameFromPath( path ); } bool wxDirItemData::HasSubDirs() { - wxString search = *m_path + "/*"; - wxString path = wxFindFirstFile( search, wxDIR ); - return (bool)(!path.IsNull()); + wxString search = m_path + "/*"; + wxLogNull log; + wxString path = wxFindFirstFile( search, wxDIR ); + return (bool)(!path.IsNull()); } //----------------------------------------------------------------------------- @@ -102,12 +158,14 @@ IMPLEMENT_DYNAMIC_CLASS(wxDirCtrl,wxTreeCtrl) BEGIN_EVENT_TABLE(wxDirCtrl,wxTreeCtrl) EVT_TREE_ITEM_EXPANDING (-1, wxDirCtrl::OnExpandItem) EVT_TREE_ITEM_COLLAPSED (-1, wxDirCtrl::OnCollapseItem) + EVT_TREE_BEGIN_LABEL_EDIT (-1, wxDirCtrl::OnBeginEditItem) + EVT_TREE_END_LABEL_EDIT (-1, wxDirCtrl::OnEndEditItem) END_EVENT_TABLE() wxDirCtrl::wxDirCtrl(void) { - m_showHidden = FALSE; -}; + m_showHidden = FALSE; +} wxDirCtrl::wxDirCtrl(wxWindow *parent, const wxWindowID id, const wxString &WXUNUSED(dir), const wxPoint& pos, const wxSize& size, @@ -115,15 +173,18 @@ wxDirCtrl::wxDirCtrl(wxWindow *parent, const wxWindowID id, const wxString &WXUN : wxTreeCtrl( parent, id, pos, size, style, wxDefaultValidator, name ) { - m_imageListNormal = new wxImageList(16, 16, TRUE); - m_imageListNormal->Add(wxICON(icon1)); - SetImageList(m_imageListNormal); + #ifdef __WXMSW__ + m_imageListNormal = new wxImageList(16, 16, TRUE); + m_imageListNormal->Add(wxICON(icon1)); + m_imageListNormal->Add(wxICON(icon2)); + SetImageList(m_imageListNormal); + #endif - m_showHidden = FALSE; - m_rootId = AddRoot("Sections"); - SetItemHasChildren(m_rootId); - Expand(m_rootId); // automatically expand first level -}; + m_showHidden = FALSE; + m_rootId = AddRoot( _("Sections") ); + SetItemHasChildren(m_rootId); + Expand(m_rootId); // automatically expand first level +} /* Quick macro. Don't worry, I'll #undef it later */ #define ADD_SECTION(a,b) \ @@ -135,83 +196,156 @@ void wxDirCtrl::SetupSections() m_paths.Clear(); m_names.Clear(); - ADD_SECTION("/", _("The Computer") ) +#ifdef __WXMSW__ + // better than nothing + ADD_SECTION(_T("c:\\"), _("My Harddisk") ) +#else + ADD_SECTION(_T("/"), _("The Computer") ) wxGetHomeDir(&home); ADD_SECTION(home, _("My Home") ) - ADD_SECTION("/mnt", _("Mounted Devices") ) - ADD_SECTION("/usr", _("User") ) - ADD_SECTION("/usr/local", _("User Local") ) - ADD_SECTION("/var", _("Variables") ) - ADD_SECTION("/etc", _("Etcetera") ) - ADD_SECTION("/tmp", _("Temporary") ) + ADD_SECTION(_T("/mnt"), _("Mounted Devices") ) + ADD_SECTION(_T("/usr"), _("User") ) + ADD_SECTION(_T("/usr/local"), _("User Local") ) + ADD_SECTION(_T("/var"), _("Variables") ) + ADD_SECTION(_T("/etc"), _("Etcetera") ) + ADD_SECTION(_T("/tmp"), _("Temporary") ) +#endif } #undef ADD_SECTION void wxDirCtrl::CreateItems(const wxTreeItemId &parent) { - wxTreeItemId id; - wxDirItemData *dir_item; + wxTreeItemId id; + wxDirItemData *dir_item; // wxASSERT(m_paths.Count() == m_names.Count()); ? - for (unsigned int i=0; im_hasSubDirs) SetItemHasChildren(id); - } + for (unsigned int i=0; im_hasSubDirs) SetItemHasChildren(id); + } } -void wxDirCtrl::OnExpandItem( const wxTreeEvent &event ) +void wxDirCtrl::OnBeginEditItem(wxTreeEvent &event) { - if (event.GetItem() == m_rootId) - { - SetupSections(); - CreateItems(m_rootId); - return; - }; - - // This may take a longish time. Go to busy cursor - wxBeginBusyCursor(); + // don't rename the main entry "Sections" + if (event.GetItem() == m_rootId) + { + event.Veto(); + return; + } + + // don't rename the individual sections + if (GetParent( event.GetItem() ) == m_rootId) + { + event.Veto(); + return; + } +} - wxDirItemData *data = (wxDirItemData *)GetItemData(event.GetItem()); - wxASSERT(data); +void wxDirCtrl::OnEndEditItem(wxTreeEvent &event) +{ + if ((event.GetLabel().IsEmpty()) || + (event.GetLabel() == _(".")) || + (event.GetLabel() == _("..")) || + (event.GetLabel().First( _T("/") ) != wxNOT_FOUND)) + { + wxMessageDialog dialog(this, _("Illegal directory name."), _("Error"), wxOK | wxICON_ERROR ); + dialog.ShowModal(); + event.Veto(); + return; + } - wxString search,path,filename; + wxTreeItemId id = event.GetItem(); + wxDirItemData *data = (wxDirItemData*)GetItemData( id ); + wxASSERT( data ); + + wxString new_name( wxPathOnly( data->m_path ) ); + new_name += _T("/"); + new_name += event.GetLabel(); + + wxLogNull log; + + if (wxFileExists(new_name)) + { + wxMessageDialog dialog(this, _("File name exists already."), _("Error"), wxOK | wxICON_ERROR ); + dialog.ShowModal(); + event.Veto(); + } + + if (wxRenameFile(data->m_path,new_name)) + { + data->SetNewDirName( new_name ); + } + else + { + wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR ); + dialog.ShowModal(); + event.Veto(); + } +} - m_paths.Clear(); - m_names.Clear(); - search = *(data->m_path) + "/*"; - for (path = wxFindFirstFile( search, wxDIR ); !path.IsNull(); - path=wxFindNextFile() ) { - filename = wxFileNameFromPath( path ); - /* Don't add "." and ".." to the tree. I think wxFindNextFile - * also checks this, but I don't quite understand what happens - * there. Also wxFindNextFile seems to swallow hidden dirs */ - if ((filename != ".") && (filename != "..")) { - m_paths.Add(path); - m_names.Add(filename); +void wxDirCtrl::OnExpandItem(wxTreeEvent &event) +{ + if (event.GetItem() == m_rootId) + { + SetupSections(); + CreateItems(m_rootId); + return; } - } - CreateItems(event.GetItem()); - wxEndBusyCursor(); -}; + // This may take a longish time. Go to busy cursor + wxBeginBusyCursor(); + + wxDirItemData *data = (wxDirItemData *)GetItemData(event.GetItem()); + wxASSERT(data); + + wxString search,path,filename; + + m_paths.Clear(); + m_names.Clear(); + search = data->m_path + "/*"; + for (path = wxFindFirstFile( search, wxDIR ); !path.IsNull(); + path=wxFindNextFile() ) + { + filename = wxFileNameFromPath( path ); + /* Don't add "." and ".." to the tree. I think wxFindNextFile + * also checks this, but I don't quite understand what happens + * there. Also wxFindNextFile seems to swallow hidden dirs */ + if ((filename != ".") && (filename != "..")) + { + m_paths.Add(path); + m_names.Add(filename); + } + } + + CreateItems( event.GetItem() ); + SortChildren( event.GetItem() ); + + wxEndBusyCursor(); +} -void wxDirCtrl::OnCollapseItem( const wxTreeEvent &event ) +void wxDirCtrl::OnCollapseItem(wxTreeEvent &event ) { - wxTreeItemId child, parent = event.GetItem(); - long cookie; - /* Workaround because DeleteChildren has disapeared (why?) and - * CollapseAndReset doesn't work as advertised (deletes parent too) */ - child = GetFirstChild(parent, cookie); - while (child.IsOk()) { - Delete(child); - /* Not GetNextChild below, because the cookie mechanism can't - * handle disappearing children! */ + wxTreeItemId child, parent = event.GetItem(); + long cookie; + /* Workaround because DeleteChildren has disapeared (why?) and + * CollapseAndReset doesn't work as advertised (deletes parent too) */ child = GetFirstChild(parent, cookie); - } -}; + while (child.IsOk()) + { + Delete(child); + /* Not GetNextChild below, because the cookie mechanism can't + * handle disappearing children! */ + child = GetFirstChild(parent, cookie); + } +} //----------------------------------------------------------------------------- // wxDirDialog @@ -239,112 +373,78 @@ wxDirDialog::wxDirDialog(wxWindow *parent, const wxString& message, const wxString& defaultPath, long style, const wxPoint& pos) : wxDialog(parent, -1, message, pos, wxSize(300,300), - wxDEFAULT_DIALOG_STYLE|wxDIALOG_MODAL) + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - m_message = message; - m_dialogStyle = style; - m_parent = parent; + m_message = message; + m_dialogStyle = style; + m_parent = parent; - m_path = defaultPath; - - m_dir = new wxDirCtrl( this, ID_DIRCTRL, "/", wxDefaultPosition, wxDefaultSize, wxTR_HAS_BUTTONS | wxSUNKEN_BORDER ); - m_input = new wxTextCtrl( this, ID_TEXTCTRL, m_path, wxDefaultPosition ); - // m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden") ); - m_ok = new wxButton( this, ID_OK, _("OK") ); - m_cancel = new wxButton( this, ID_CANCEL, _("Cancel") ); - m_new = new wxButton( this, ID_NEW, _("New...") ); - - // m_check->SetValue(TRUE); - m_ok->SetDefault(); - m_dir->SetFocus(); - - doSize(); -} - -void wxDirDialog::OnSize(wxSizeEvent& WXUNUSED(event)) -{ - doSize(); -} + m_path = defaultPath; + + wxBeginBusyCursor(); + + wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); + + // 1) dir ctrl + m_dir = new wxDirCtrl( this, ID_DIRCTRL, "/", wxDefaultPosition, wxSize(200,200), + wxTR_HAS_BUTTONS | wxSUNKEN_BORDER | wxTR_EDIT_LABELS); + topsizer->Add( m_dir, 1, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 10 ); + + // 2) text ctrl + m_input = new wxTextCtrl( this, ID_TEXTCTRL, m_path, wxDefaultPosition ); + topsizer->Add( m_input, 0, wxTOP|wxLEFT|wxRIGHT | wxEXPAND, 10 ); + + // m_check = new wxCheckBox( this, ID_CHECK, _("Show hidden") ); + // m_check->SetValue(TRUE); + +#if wxUSE_STATLINE + // 3) static line + topsizer->Add( new wxStaticLine( this, -1 ), 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10 ); +#endif -void wxDirDialog::doSize() -{ - /* Figure out height of DirCtrl, which is what is left over by - * the textctrl and the buttons. Manually, because I can't seem - * to get the constraints stuff to do this */ - int w,h,h2; - - GetClientSize(&w, &h); - m_input->GetSize(&w,&h2); h -= h2; - m_ok->GetSize(&w, &h2); h -= h2; - //m_check->GetSize(&w, &h2); h -= h2; - h -= 20; - - wxLayoutConstraints *c = new wxLayoutConstraints; - c->left.SameAs (this, wxLeft,5); - c->right.SameAs (this, wxRight,5); - c->height.Absolute (h); - c->top.SameAs (this, wxTop,5); - m_dir->SetConstraints(c); - - c = new wxLayoutConstraints; - c->left.SameAs (this, wxLeft,5); - c->right.SameAs (this, wxRight,5); - c->height.AsIs (); - c->top.Below (m_dir,5); - m_input->SetConstraints(c); - - /* c = new wxLayoutConstraints; - c->left.SameAs (this, wxLeft,5); - c->right.SameAs (this, wxRight,5); - c->height.AsIs (); - c->top.Below (m_input,5); - m_check->SetConstraints(c); */ - - c = new wxLayoutConstraints; - c->width.SameAs (m_cancel, wxWidth); - c->height.AsIs (); - c->top.Below (m_input,5); - c->centreX.PercentOf (this, wxWidth, 25); - m_ok->SetConstraints(c); - - c = new wxLayoutConstraints; - c->width.SameAs (m_cancel, wxWidth); - c->height.AsIs (); - c->top.Below (m_input,5); - c->bottom.SameAs (this, wxBottom, 5); - c->centreX.PercentOf (this, wxWidth, 50); - m_new->SetConstraints(c); - - c = new wxLayoutConstraints; - c->width.AsIs (); - c->height.AsIs (); - c->top.Below (m_input,5); - c->centreX.PercentOf (this, wxWidth, 75); - m_cancel->SetConstraints(c); - - Layout(); + // 4) buttons + wxSizer* buttonsizer = new wxBoxSizer( wxHORIZONTAL ); + m_ok = new wxButton( this, ID_OK, _("OK") ); + buttonsizer->Add( m_ok, 0, wxLEFT|wxRIGHT, 10 ); + m_cancel = new wxButton( this, ID_CANCEL, _("Cancel") ); + buttonsizer->Add( m_cancel, 0, wxLEFT|wxRIGHT, 10 ); + m_new = new wxButton( this, ID_NEW, _("New...") ); + buttonsizer->Add( m_new, 0, wxLEFT|wxRIGHT, 10 ); + + topsizer->Add( buttonsizer, 0, wxALL | wxCENTER, 10 ); + + m_ok->SetDefault(); + m_dir->SetFocus(); + + SetAutoLayout( TRUE ); + SetSizer( topsizer ); + + topsizer->SetSizeHints( this ); + topsizer->Fit( this ); + + Centre( wxBOTH ); + + wxEndBusyCursor(); } int wxDirDialog::ShowModal() { - m_input->SetValue( m_path ); - return wxDialog::ShowModal(); + m_input->SetValue( m_path ); + return wxDialog::ShowModal(); } void wxDirDialog::OnTreeSelected( wxTreeEvent &event ) { - wxDirItemData *data = - (wxDirItemData*)m_dir->GetItemData(event.GetItem()); - if (data) - m_input->SetValue( *(data->m_path) ); + wxDirItemData *data = (wxDirItemData*)m_dir->GetItemData(event.GetItem()); + if (data) + m_input->SetValue( data->m_path ); }; -void wxDirDialog::OnTreeKeyDown( wxKeyEvent &WXUNUSED(event) ) +void wxDirDialog::OnTreeKeyDown( wxTreeEvent &WXUNUSED(event) ) { - wxDirItemData *data = - (wxDirItemData*)m_dir->GetItemData(m_dir->GetSelection()); - if (data) - m_input->SetValue( *(data->m_path) ); + wxDirItemData *data = (wxDirItemData*)m_dir->GetItemData(m_dir->GetSelection()); + if (data) + m_input->SetValue( data->m_path ); }; void wxDirDialog::OnOK( wxCommandEvent& WXUNUSED(event) ) @@ -360,9 +460,10 @@ void wxDirDialog::OnOK( wxCommandEvent& WXUNUSED(event) ) 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); + 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); @@ -372,7 +473,7 @@ void wxDirDialog::OnOK( wxCommandEvent& WXUNUSED(event) ) // Trouble... msg = _("Failed to create directory ")+m_path+ _("\n(Do you have the required permissions?)"); - wxMessageDialog errmsg(this, msg, _("Error creating directory"), wxOK); + 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. } @@ -387,24 +488,53 @@ void wxDirDialog::OnCancel( wxCommandEvent& WXUNUSED(event) ) void wxDirDialog::OnNew( wxCommandEvent& WXUNUSED(event) ) { - wxTextEntryDialog dialog(this, _("Enter the name of the directory to create"), - _("Create New Directory"), m_input->GetValue(), wxOK|wxCANCEL); + wxTreeItemId id = m_dir->GetSelection(); + if ((id == m_dir->GetRootItem()) || + (m_dir->GetParent(id) == m_dir->GetRootItem())) + { + wxMessageDialog msg(this, _("You cannot add a new directory to this section."), + _("Create directory"), wxOK | wxICON_INFORMATION ); + msg.ShowModal(); + return; + } - while (dialog.ShowModal() == wxID_OK) - { - // Okay, let's make it - if (wxMkdir(dialog.GetValue())) { - // The new dir was created okay. - m_path = dialog.GetValue(); - return; + wxTreeItemId parent = m_dir->GetParent( id ); + wxDirItemData *data = (wxDirItemData*)m_dir->GetItemData( parent ); + wxASSERT( data ); + + wxString new_name( _T("NewName") ); + wxString path( data->m_path ); + path += _T( "/" ); + path += new_name; + if (wxFileExists(path)) + { + // try NewName0, NewName1 etc. + int i = 0; + do { + new_name = _T("NewName"); + wxString num; + num.Printf( "%d", i ); + new_name += num; + + path = data->m_path; + path += _T( "/" ); + path += new_name; + i++; + } while (wxFileExists(path)); } - wxString msg = _("Failed to create directory ")+dialog.GetValue()+ - _("\n(Do you have the required permissions?)") ; - wxMessageDialog errmsg(this, msg, _("Error creating directory"), wxOK); - errmsg.ShowModal(); - // Show the create dialog again, until user clicks cancel or enters - // a valid dir. - } + + wxLogNull log; + if (!wxMkdir(path)) + { + wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR ); + dialog.ShowModal(); + return; + } + + wxDirItemData *new_data = new wxDirItemData( path, new_name ); + wxTreeItemId new_id = m_dir->AppendItem( parent, new_name, 0, 1, new_data ); + m_dir->EnsureVisible( new_id ); + m_dir->EditLabel( new_id ); } /* @@ -413,3 +543,5 @@ void wxDirDialog::OnCheck( wxCommandEvent& WXUNUSED(event) ) printf("Checkbox clicked: %s\n", ( m_check->GetValue() ? "on" : "off" ) ); } */ + +#endif