1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/filepickercmn.cpp
3 // Purpose:     wxFilePickerCtrl class implementation
4 // Author:      Francesco Montorsi (readapted code written by Vadim Zeitlin)
5 // Modified by:
6 // Created:     15/04/2006
7 // Copyright:   (c) Vadim Zeitlin, Francesco Montorsi
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 
23 #if wxUSE_FILEPICKERCTRL || wxUSE_DIRPICKERCTRL
24 
25 #include "wx/filepicker.h"
26 #include "wx/filename.h"
27 
28 #ifndef WX_PRECOMP
29     #include "wx/textctrl.h"
30 #endif
31 
32 // ============================================================================
33 // implementation
34 // ============================================================================
35 
36 const char wxFilePickerCtrlNameStr[] = "filepicker";
37 const char wxFilePickerWidgetNameStr[] = "filepickerwidget";
38 const char wxDirPickerCtrlNameStr[] = "dirpicker";
39 const char wxDirPickerWidgetNameStr[] = "dirpickerwidget";
40 const char wxFilePickerWidgetLabel[] = wxTRANSLATE("Browse");
41 const char wxDirPickerWidgetLabel[] = wxTRANSLATE("Browse");
42 
43 wxDEFINE_EVENT( wxEVT_FILEPICKER_CHANGED, wxFileDirPickerEvent );
44 wxDEFINE_EVENT( wxEVT_DIRPICKER_CHANGED,  wxFileDirPickerEvent );
45 wxIMPLEMENT_DYNAMIC_CLASS(wxFileDirPickerEvent, wxCommandEvent);
46 
47 // ----------------------------------------------------------------------------
48 // wxFileDirPickerCtrlBase
49 // ----------------------------------------------------------------------------
50 
CreateBase(wxWindow * parent,wxWindowID id,const wxString & path,const wxString & message,const wxString & wildcard,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)51 bool wxFileDirPickerCtrlBase::CreateBase(wxWindow *parent,
52                                          wxWindowID id,
53                                          const wxString &path,
54                                          const wxString &message,
55                                          const wxString &wildcard,
56                                          const wxPoint &pos,
57                                          const wxSize &size,
58                                          long style,
59                                          const wxValidator& validator,
60                                          const wxString &name )
61 {
62     if (!wxPickerBase::CreateBase(parent, id, path, pos, size,
63                                    style, validator, name))
64         return false;
65 
66     if (!HasFlag(wxFLP_OPEN) && !HasFlag(wxFLP_SAVE))
67         m_windowStyle |= wxFLP_OPEN;     // wxFD_OPEN is the default
68 
69     // check that the styles are not contradictory
70     wxASSERT_MSG( !(HasFlag(wxFLP_SAVE) && HasFlag(wxFLP_OPEN)),
71                   wxT("can't specify both wxFLP_SAVE and wxFLP_OPEN at once") );
72 
73     wxASSERT_MSG( !HasFlag(wxFLP_SAVE) || !HasFlag(wxFLP_FILE_MUST_EXIST),
74                    wxT("wxFLP_FILE_MUST_EXIST can't be used with wxFLP_SAVE" ) );
75 
76     wxASSERT_MSG( !HasFlag(wxFLP_OPEN) || !HasFlag(wxFLP_OVERWRITE_PROMPT),
77                   wxT("wxFLP_OVERWRITE_PROMPT can't be used with wxFLP_OPEN") );
78 
79     // create a wxFilePickerWidget or a wxDirPickerWidget...
80     m_pickerIface = CreatePicker(this, path, message, wildcard);
81     if ( !m_pickerIface )
82         return false;
83     m_picker = m_pickerIface->AsControl();
84 
85     // complete sizer creation
86     wxPickerBase::PostCreation();
87 
88     DoConnect( m_picker, this );
89 
90     // default's wxPickerBase textctrl limit is too small for this control:
91     // make it bigger
92     if (m_text) m_text->SetMaxLength(512);
93 
94     return true;
95 }
96 
GetPath() const97 wxString wxFileDirPickerCtrlBase::GetPath() const
98 {
99     return m_pickerIface->GetPath();
100 }
101 
SetPath(const wxString & path)102 void wxFileDirPickerCtrlBase::SetPath(const wxString &path)
103 {
104     m_pickerIface->SetPath(path);
105     UpdateTextCtrlFromPicker();
106 }
107 
UpdatePickerFromTextCtrl()108 void wxFileDirPickerCtrlBase::UpdatePickerFromTextCtrl()
109 {
110     wxASSERT(m_text);
111 
112     // remove the eventually present path-separator from the end of the textctrl
113     // string otherwise we would generate a wxFileDirPickerEvent when changing
114     // from e.g. /home/user to /home/user/ and we want to avoid it !
115     wxString newpath(GetTextCtrlValue());
116 
117     // Notice that we use to check here whether the current path is valid, i.e.
118     // if the corresponding file or directory exists for the controls with
119     // wxFLP_FILE_MUST_EXIST or wxDIRP_DIR_MUST_EXIST flag, however we don't do
120     // this any more as we still must notify the program about any changes in
121     // the control, otherwise its view of it would be different from what is
122     // actually shown on the screen, resulting in very confusing UI.
123 
124     if (m_pickerIface->GetPath() != newpath)
125     {
126         m_pickerIface->SetPath(newpath);
127 
128         // update current working directory, if necessary
129         // NOTE: the path separator is required because if newpath is "C:"
130         //       then no change would happen
131         if (IsCwdToUpdate())
132             wxSetWorkingDirectory(newpath);
133 
134         // fire an event
135         wxFileDirPickerEvent event(GetEventType(), this, GetId(), newpath);
136         GetEventHandler()->ProcessEvent(event);
137     }
138 }
139 
UpdateTextCtrlFromPicker()140 void wxFileDirPickerCtrlBase::UpdateTextCtrlFromPicker()
141 {
142     if (!m_text)
143         return;     // no textctrl to update
144 
145     // Take care to use ChangeValue() here and not SetValue() to avoid
146     // generating an event that would trigger UpdateTextCtrlFromPicker()
147     // resulting in infinite recursion.
148     m_text->ChangeValue(m_pickerIface->GetPath());
149 }
150 
151 
152 
153 // ----------------------------------------------------------------------------
154 // wxFileDirPickerCtrlBase - event handlers
155 // ----------------------------------------------------------------------------
156 
OnFileDirChange(wxFileDirPickerEvent & ev)157 void wxFileDirPickerCtrlBase::OnFileDirChange(wxFileDirPickerEvent &ev)
158 {
159     UpdateTextCtrlFromPicker();
160 
161     // the wxFilePickerWidget sent us a colour-change notification.
162     // forward this event to our parent
163     wxFileDirPickerEvent event(GetEventType(), this, GetId(), ev.GetPath());
164     GetEventHandler()->ProcessEvent(event);
165 }
166 
167 #endif  // wxUSE_FILEPICKERCTRL || wxUSE_DIRPICKERCTRL
168 
169 // ----------------------------------------------------------------------------
170 // wxFileDirPickerCtrl
171 // ----------------------------------------------------------------------------
172 
173 #if wxUSE_FILEPICKERCTRL
174 
175 wxIMPLEMENT_DYNAMIC_CLASS(wxFilePickerCtrl, wxPickerBase);
176 
Create(wxWindow * parent,wxWindowID id,const wxString & path,const wxString & message,const wxString & wildcard,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)177 bool wxFilePickerCtrl::Create(wxWindow *parent,
178                               wxWindowID id,
179                               const wxString& path,
180                               const wxString& message,
181                               const wxString& wildcard,
182                               const wxPoint& pos,
183                               const wxSize& size,
184                               long style,
185                               const wxValidator& validator,
186                               const wxString& name)
187 {
188     if ( !wxFileDirPickerCtrlBase::CreateBase
189                                    (
190                                         parent, id, path, message, wildcard,
191                                         pos, size, style, validator, name
192                                    ) )
193         return false;
194 
195     if ( HasTextCtrl() )
196         GetTextCtrl()->AutoCompleteFileNames();
197 
198     return true;
199 }
200 
GetTextCtrlValue() const201 wxString wxFilePickerCtrl::GetTextCtrlValue() const
202 {
203     wxCHECK_MSG( m_text, wxString(), "Can't be used if no text control" );
204 
205     // filter it through wxFileName to remove any spurious path separator
206     return wxFileName(m_text->GetValue()).GetFullPath();
207 }
208 
209 #endif // wxUSE_FILEPICKERCTRL
210 
211 // ----------------------------------------------------------------------------
212 // wxDirPickerCtrl
213 // ----------------------------------------------------------------------------
214 
215 #if wxUSE_DIRPICKERCTRL
216 wxIMPLEMENT_DYNAMIC_CLASS(wxDirPickerCtrl, wxPickerBase);
217 
Create(wxWindow * parent,wxWindowID id,const wxString & path,const wxString & message,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)218 bool wxDirPickerCtrl::Create(wxWindow *parent,
219                              wxWindowID id,
220                              const wxString& path,
221                              const wxString& message,
222                              const wxPoint& pos,
223                              const wxSize& size,
224                              long style,
225                              const wxValidator& validator,
226                              const wxString& name)
227 {
228     if ( !wxFileDirPickerCtrlBase::CreateBase
229                                    (
230                                         parent, id, path, message, wxString(),
231                                         pos, size, style, validator, name
232                                    ) )
233         return false;
234 
235     if ( HasTextCtrl() )
236         GetTextCtrl()->AutoCompleteDirectories();
237 
238     return true;
239 }
240 
GetTextCtrlValue() const241 wxString wxDirPickerCtrl::GetTextCtrlValue() const
242 {
243     wxCHECK_MSG( m_text, wxString(), "Can't be used if no text control" );
244 
245     // filter it through wxFileName to remove any spurious path separator
246     return wxFileName::DirName(m_text->GetValue()).GetPath();
247 }
248 
249 #endif // wxUSE_DIRPICKERCTRL
250