1///////////////////////////////////////////////////////////////////////////// 2// Name: src/generic/dirdlg.cpp 3// Purpose: wxDirDialog 4// Author: Harm van der Heijden, Robert Roebling & Julian Smart 5// Modified by: 6// Created: 12/12/98 7// RCS-ID: $Id: dirdlgg.cpp 41838 2006-10-09 21:08:45Z VZ $ 8// Copyright: (c) Harm van der Heijden, Robert Roebling, Julian Smart 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16 #pragma hdrstop 17#endif 18 19#if wxUSE_DIRDLG 20 21#ifndef WX_PRECOMP 22 #include "wx/textctrl.h" 23 #include "wx/button.h" 24 #include "wx/checkbox.h" 25 #include "wx/sizer.h" 26 #include "wx/intl.h" 27 #include "wx/log.h" 28 #include "wx/msgdlg.h" 29 #include "wx/bmpbuttn.h" 30#endif 31 32#include "wx/statline.h" 33#include "wx/dirctrl.h" 34#include "wx/generic/dirdlgg.h" 35#include "wx/artprov.h" 36 37// ---------------------------------------------------------------------------- 38// constants 39// ---------------------------------------------------------------------------- 40 41static const int ID_DIRCTRL = 1000; 42static const int ID_TEXTCTRL = 1001; 43static const int ID_NEW = 1004; 44static const int ID_SHOW_HIDDEN = 1005; 45static const int ID_GO_HOME = 1006; 46 47//----------------------------------------------------------------------------- 48// wxGenericDirDialog 49//----------------------------------------------------------------------------- 50 51IMPLEMENT_DYNAMIC_CLASS(wxGenericDirDialog, wxDialog) 52 53BEGIN_EVENT_TABLE(wxGenericDirDialog, wxDialog) 54 EVT_CLOSE (wxGenericDirDialog::OnCloseWindow) 55 EVT_BUTTON (wxID_OK, wxGenericDirDialog::OnOK) 56 EVT_BUTTON (ID_NEW, wxGenericDirDialog::OnNew) 57 EVT_BUTTON (ID_GO_HOME, wxGenericDirDialog::OnGoHome) 58 EVT_TREE_KEY_DOWN (wxID_ANY, wxGenericDirDialog::OnTreeKeyDown) 59 EVT_TREE_SEL_CHANGED (wxID_ANY, wxGenericDirDialog::OnTreeSelected) 60 EVT_TEXT_ENTER (ID_TEXTCTRL, wxGenericDirDialog::OnOK) 61 EVT_CHECKBOX (ID_SHOW_HIDDEN, wxGenericDirDialog::OnShowHidden) 62END_EVENT_TABLE() 63 64wxGenericDirDialog::wxGenericDirDialog(wxWindow* parent, const wxString& title, 65 const wxString& defaultPath, long style, 66 const wxPoint& pos, const wxSize& sz, 67 const wxString& name) 68{ 69 Create(parent, title, defaultPath, style, pos, sz, name); 70} 71 72bool wxGenericDirDialog::Create(wxWindow* parent, 73 const wxString& title, 74 const wxString& defaultPath, long style, 75 const wxPoint& pos, 76 const wxSize& sz, 77 const wxString& name) 78{ 79 wxBusyCursor cursor; 80 81 if (!wxDirDialogBase::Create(parent, title, defaultPath, style, pos, sz, name)) 82 return false; 83 84 m_path = defaultPath; 85 if (m_path == wxT("~")) 86 wxGetHomeDir(&m_path); 87 if (m_path == wxT(".")) 88 m_path = wxGetCwd(); 89 90 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); 91 92 // smartphones does not support or do not waste space for wxButtons 93#if defined(__SMARTPHONE__) 94 95 wxMenu *dirMenu = new wxMenu; 96 dirMenu->Append(ID_GO_HOME, _("Home")); 97 98 if (!HasFlag(wxDD_DIR_MUST_EXIST)) 99 { 100 dirMenu->Append(ID_NEW, _("New directory")); 101 } 102 103 dirMenu->AppendCheckItem(ID_SHOW_HIDDEN, _("Show hidden directories")); 104 dirMenu->AppendSeparator(); 105 dirMenu->Append(wxID_CANCEL, _("Cancel")); 106 107#else 108 109 // 0) 'New' and 'Home' Buttons 110 wxSizer* buttonsizer = new wxBoxSizer( wxHORIZONTAL ); 111 112 // VS: 'Home directory' concept is unknown to MS-DOS 113#if !defined(__DOS__) 114 wxBitmapButton* homeButton = 115 new wxBitmapButton(this, ID_GO_HOME, 116 wxArtProvider::GetBitmap(wxART_GO_HOME, wxART_BUTTON)); 117 buttonsizer->Add( homeButton, 0, wxLEFT|wxRIGHT, 10 ); 118#endif 119 120 // I'm not convinced we need a New button, and we tend to get annoying 121 // accidental-editing with label editing enabled. 122 if (!HasFlag(wxDD_DIR_MUST_EXIST)) 123 { 124 wxBitmapButton* newButton = 125 new wxBitmapButton(this, ID_NEW, 126 wxArtProvider::GetBitmap(wxART_NEW_DIR, wxART_BUTTON)); 127 buttonsizer->Add( newButton, 0, wxRIGHT, 10 ); 128#if wxUSE_TOOLTIPS 129 newButton->SetToolTip(_("Create new directory")); 130#endif 131 } 132 133#if wxUSE_TOOLTIPS 134 homeButton->SetToolTip(_("Go to home directory")); 135#endif 136 137 topsizer->Add( buttonsizer, 0, wxTOP | wxALIGN_RIGHT, 10 ); 138 139#endif // __SMARTPHONE__/!__SMARTPHONE__ 140 141 // 1) dir ctrl 142 m_dirCtrl = NULL; // this is necessary, event handler called from 143 // wxGenericDirCtrl would crash otherwise! 144 long dirStyle = wxDIRCTRL_DIR_ONLY | wxDEFAULT_CONTROL_BORDER; 145 146#ifdef __WXMSW__ 147 if (!HasFlag(wxDD_DIR_MUST_EXIST)) 148 { 149 // Only under Windows do we need the wxTR_EDIT_LABEL tree control style 150 // before we can call EditLabel (required for "New directory") 151 dirStyle |= wxDIRCTRL_EDIT_LABELS; 152 } 153#endif 154 155 m_dirCtrl = new wxGenericDirCtrl(this, ID_DIRCTRL, 156 m_path, wxDefaultPosition, 157 wxSize(300, 200), 158 dirStyle); 159 160 wxSizerFlags flagsBorder2; 161 flagsBorder2.DoubleBorder(wxTOP | wxLEFT | wxRIGHT); 162 163 topsizer->Add(m_dirCtrl, wxSizerFlags(flagsBorder2).Proportion(1).Expand()); 164 165#ifndef __SMARTPHONE__ 166 // Make the an option depending on a flag? 167 wxCheckBox * 168 check = new wxCheckBox(this, ID_SHOW_HIDDEN, _("Show &hidden directories")); 169 topsizer->Add(check, wxSizerFlags(flagsBorder2).Right()); 170#endif // !__SMARTPHONE__ 171 172 // 2) text ctrl 173 m_input = new wxTextCtrl( this, ID_TEXTCTRL, m_path, wxDefaultPosition ); 174 topsizer->Add(m_input, wxSizerFlags(flagsBorder2).Expand()); 175 176 // 3) buttons if any 177 wxSizer *buttonSizer = CreateSeparatedButtonSizer(wxOK | wxCANCEL); 178 if ( buttonSizer ) 179 { 180 topsizer->Add(buttonSizer, wxSizerFlags().Expand().DoubleBorder()); 181 } 182 183#ifdef __SMARTPHONE__ 184 // overwrite menu set by CreateSeparatedButtonSizer() call above 185 SetRightMenu(wxID_ANY, _("Options"), dirMenu); 186#endif 187 188 m_input->SetFocus(); 189 190 SetAutoLayout( true ); 191 SetSizer( topsizer ); 192 193 topsizer->SetSizeHints( this ); 194 topsizer->Fit( this ); 195 196 Centre( wxBOTH ); 197 198 return true; 199} 200 201void wxGenericDirDialog::EndModal(int retCode) 202{ 203 // before proceeding, change the current working directory if user asked so 204 if (retCode == wxID_OK && HasFlag(wxDD_CHANGE_DIR)) 205 wxSetWorkingDirectory(m_path); 206 207 wxDialog::EndModal(retCode); 208} 209 210void wxGenericDirDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event)) 211{ 212 EndModal(wxID_CANCEL); 213} 214 215void wxGenericDirDialog::OnOK(wxCommandEvent& WXUNUSED(event)) 216{ 217 m_path = m_input->GetValue(); 218 219 // Does the path exist? (User may have typed anything in m_input) 220 if (wxDirExists(m_path)) 221 { 222 // OK, path exists, we're done. 223 EndModal(wxID_OK); 224 return; 225 } 226 227 // Interact with user, find out if the dir is a typo or to be created 228 wxString msg; 229 msg.Printf(_("The directory '%s' does not exist\nCreate it now?"), 230 m_path.c_str()); 231 wxMessageDialog dialog(this, msg, _("Directory does not exist"), 232 wxYES_NO | wxICON_WARNING); 233 234 if ( dialog.ShowModal() == wxID_YES ) 235 { 236 // Okay, let's make it 237 wxLogNull log; 238 if (wxMkdir(m_path)) 239 { 240 // The new dir was created okay. 241 EndModal(wxID_OK); 242 return; 243 } 244 else 245 { 246 // Trouble... 247 msg.Printf(_("Failed to create directory '%s'\n(Do you have the required permissions?)"), 248 m_path.c_str()); 249 wxMessageDialog errmsg(this, msg, _("Error creating directory"), wxOK | wxICON_ERROR); 250 errmsg.ShowModal(); 251 // We still don't have a valid dir. Back to the main dialog. 252 } 253 } 254 // User has answered NO to create dir. 255} 256 257void wxGenericDirDialog::SetPath(const wxString& path) 258{ 259 m_dirCtrl->SetPath(path); 260 m_path = path; 261} 262 263wxString wxGenericDirDialog::GetPath(void) const 264{ 265 return m_path; 266} 267 268int wxGenericDirDialog::ShowModal() 269{ 270 m_input->SetValue( m_path ); 271 return wxDialog::ShowModal(); 272} 273 274void wxGenericDirDialog::OnTreeSelected( wxTreeEvent &event ) 275{ 276 if (!m_dirCtrl) 277 return; 278 279 wxTreeItemId item = event.GetItem(); 280 281 wxDirItemData *data = NULL; 282 283 if(item.IsOk()) 284 data = (wxDirItemData*)m_dirCtrl->GetTreeCtrl()->GetItemData(item); 285 286 if (data) 287 m_input->SetValue( data->m_path ); 288} 289 290void wxGenericDirDialog::OnTreeKeyDown( wxTreeEvent &WXUNUSED(event) ) 291{ 292 if (!m_dirCtrl) 293 return; 294 295 wxDirItemData *data = (wxDirItemData*)m_dirCtrl->GetTreeCtrl()->GetItemData(m_dirCtrl->GetTreeCtrl()->GetSelection()); 296 if (data) 297 m_input->SetValue( data->m_path ); 298} 299 300void wxGenericDirDialog::OnShowHidden( wxCommandEvent& event ) 301{ 302 if (!m_dirCtrl) 303 return; 304 305 m_dirCtrl->ShowHidden( event.GetInt() != 0 ); 306} 307 308void wxGenericDirDialog::OnNew( wxCommandEvent& WXUNUSED(event) ) 309{ 310 wxTreeItemId id = m_dirCtrl->GetTreeCtrl()->GetSelection(); 311 if ((id == m_dirCtrl->GetTreeCtrl()->GetRootItem()) || 312 (m_dirCtrl->GetTreeCtrl()->GetItemParent(id) == m_dirCtrl->GetTreeCtrl()->GetRootItem())) 313 { 314 wxMessageDialog msg(this, _("You cannot add a new directory to this section."), 315 _("Create directory"), wxOK | wxICON_INFORMATION ); 316 msg.ShowModal(); 317 return; 318 } 319 320 wxTreeItemId parent = id ; // m_dirCtrl->GetTreeCtrl()->GetItemParent( id ); 321 wxDirItemData *data = (wxDirItemData*)m_dirCtrl->GetTreeCtrl()->GetItemData( parent ); 322 wxASSERT( data ); 323 324 wxString new_name( _("NewName") ); 325 wxString path( data->m_path ); 326 if (!wxEndsWithPathSeparator(path)) 327 path += wxFILE_SEP_PATH; 328 path += new_name; 329 if (wxDirExists(path)) 330 { 331 // try NewName0, NewName1 etc. 332 int i = 0; 333 do { 334 new_name = _("NewName"); 335 wxString num; 336 num.Printf( wxT("%d"), i ); 337 new_name += num; 338 339 path = data->m_path; 340 if (!wxEndsWithPathSeparator(path)) 341 path += wxFILE_SEP_PATH; 342 path += new_name; 343 i++; 344 } while (wxDirExists(path)); 345 } 346 347 wxLogNull log; 348 if (!wxMkdir(path)) 349 { 350 wxMessageDialog dialog(this, _("Operation not permitted."), _("Error"), wxOK | wxICON_ERROR ); 351 dialog.ShowModal(); 352 return; 353 } 354 355 wxDirItemData *new_data = new wxDirItemData( path, new_name, true ); 356 357 // TODO: THIS CODE DOESN'T WORK YET. We need to avoid duplication of the first child 358 // of the parent. 359 wxTreeItemId new_id = m_dirCtrl->GetTreeCtrl()->AppendItem( parent, new_name, 0, 0, new_data ); 360 m_dirCtrl->GetTreeCtrl()->EnsureVisible( new_id ); 361 m_dirCtrl->GetTreeCtrl()->EditLabel( new_id ); 362} 363 364void wxGenericDirDialog::OnGoHome(wxCommandEvent& WXUNUSED(event)) 365{ 366 SetPath(wxGetUserHome()); 367} 368 369#endif // wxUSE_DIRDLG 370