From 58772e4992e1a0601bddbf76fddbf4bb916cf85e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 26 Jun 2006 01:04:44 +0000 Subject: [PATCH] picker controls improvements: fixes to valid paths recognition and event generation under GTK (patch 1510064) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39838 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/clrpicker.tex | 6 +--- docs/latex/wx/dirpicker.tex | 8 +++-- docs/latex/wx/filepicker.tex | 4 ++- docs/latex/wx/fontpicker.tex | 3 +- include/wx/filepicker.h | 68 +++++++++++++++++++++--------------- include/wx/gtk/filepicker.h | 32 +++++++++++------ src/common/filepickercmn.cpp | 50 ++++++++++++++++++++++---- src/gtk/filepicker.cpp | 32 +++++++++++++++-- 8 files changed, 146 insertions(+), 57 deletions(-) diff --git a/docs/latex/wx/clrpicker.tex b/docs/latex/wx/clrpicker.tex index cc4d6be23c..a6d349e46d 100644 --- a/docs/latex/wx/clrpicker.tex +++ b/docs/latex/wx/clrpicker.tex @@ -32,11 +32,7 @@ It is only available if \texttt{wxUSE\_COLOURPICKERCTRL} is set to $1$ (the defa \twocolwidtha{5cm}% \begin{twocollist}\itemsep=0pt -\twocolitem{\windowstyle{wxCLRP\_DEFAULT}}{Default style.} -\twocolitem{\windowstyle{wxCLRP\_USE\_TEXTCTRL}}{Creates a text control to the left of the -picker button which is completely managed by the \helpref{wxColourPickerCtrl}{wxcolourpickerctrl} -and which can be used by the user to specify a colour (see \helpref{SetColour}{wxcolourpickerctrlsetcolour}). -The text control is automatically synchronized with button's value. Use functions defined in \helpref{wxPickerBase}{wxpickerbase} to modify the text control.} +\twocolitem{\windowstyle{wxCLRP\_DEFAULT}}{The default style: 0.} \twocolitem{\windowstyle{wxCLRP\_USE\_TEXTCTRL}}{Creates a text control to the left of the picker button which is completely managed by the \helpref{wxColourPickerCtrl}{wxcolourpickerctrl} and which can be used by the user to specify a colour (see \helpref{SetColour}{wxcolourpickerctrlsetcolour}). diff --git a/docs/latex/wx/dirpicker.tex b/docs/latex/wx/dirpicker.tex index f9bd32ffea..89364c49f2 100644 --- a/docs/latex/wx/dirpicker.tex +++ b/docs/latex/wx/dirpicker.tex @@ -32,7 +32,8 @@ It is only available if \texttt{wxUSE\_DIRPICKERCTRL} is set to $1$ (the default \twocolwidtha{5cm}% \begin{twocollist}\itemsep=0pt -\twocolitem{\windowstyle{wxDIRP\_DEFAULT\_STYLE}}{Default style.} +\twocolitem{\windowstyle{wxDIRP\_DEFAULT\_STYLE}}{The default style: includes +wxDIRP\_DIR\_MUST\_EXIST and, under wxMSW only, wxDIRP\_USE\_TEXTCTRL.} \twocolitem{\windowstyle{wxDIRP\_USE\_TEXTCTRL}}{Creates a text control to the left of the picker button which is completely managed by the \helpref{wxDirPickerCtrl}{wxdirpickerctrl} and which can be used by the user to specify a path (see \helpref{SetPath}{wxdirpickerctrlsetpath}). @@ -47,7 +48,10 @@ The text control is automatically synchronized with button's value. Use function \twocolwidtha{7cm}% \begin{twocollist}\itemsep=0pt -\twocolitem{{\bf EVT\_DIRPICKER\_CHANGED(id, func)}}{The user changed the directory selected in the control either using the button or using text control (see wxDIRP_USE_TEXTCTRL; note that in this case the event is fired only if the user's input is valid, e.g. an existing directory path).} +\twocolitem{{\bf EVT\_DIRPICKER\_CHANGED(id, func)}}{The user changed the +directory selected in the control either using the button or using text control +(see wxDIRP\_USE\_TEXTCTRL; note that in this case the event is fired only if +the user's input is valid, e.g. an existing directory path).} \end{twocollist} \wxheading{See also} diff --git a/docs/latex/wx/filepicker.tex b/docs/latex/wx/filepicker.tex index f21c9e5687..46b2a7db49 100644 --- a/docs/latex/wx/filepicker.tex +++ b/docs/latex/wx/filepicker.tex @@ -32,7 +32,9 @@ It is only available if \texttt{wxUSE\_FILEPICKERCTRL} is set to $1$ (the defaul \twocolwidtha{5cm}% \begin{twocollist}\itemsep=0pt -\twocolitem{\windowstyle{wxFLP\_DEFAULT\_STYLE}}{Default style.} +\twocolitem{\windowstyle{wxFLP\_DEFAULT\_STYLE}}{The default style: includes +wxFLP\_OPEN | wxFLP\_FILE\_MUST\_EXIST and, under wxMSW only, +wxFLP\_USE\_TEXTCTRL.} \twocolitem{\windowstyle{wxFLP\_USE\_TEXTCTRL}}{Creates a text control to the left of the picker button which is completely managed by the \helpref{wxFilePickerCtrl}{wxfilepickerctrl} and which can be used by the user to specify a path (see \helpref{SetPath}{wxfilepickerctrlsetpath}). diff --git a/docs/latex/wx/fontpicker.tex b/docs/latex/wx/fontpicker.tex index 10f7f31c93..e3a46bbc0c 100644 --- a/docs/latex/wx/fontpicker.tex +++ b/docs/latex/wx/fontpicker.tex @@ -32,7 +32,8 @@ It is only available if \texttt{wxUSE\_FONTPICKERCTRL} is set to $1$ (the defaul \twocolwidtha{5cm}% \begin{twocollist}\itemsep=0pt -\twocolitem{\windowstyle{wxFNTP\_DEFAULT}}{Default style.} +\twocolitem{\windowstyle{wxFNTP\_DEFAULT}}{The default style: +wxFNTP\_FONTDESC\_AS\_LABEL | wxFNTP\_USEFONT\_FOR\_LABEL.} \twocolitem{\windowstyle{wxFNTP\_USE\_TEXTCTRL}}{Creates a text control to the left of the picker button which is completely managed by the \helpref{wxFontPickerCtrl}{wxfontpickerctrl} and which can be used by the user to specify a font (see \helpref{SetSelectedFont}{wxfontpickerctrlsetselectedfont}). diff --git a/include/wx/filepicker.h b/include/wx/filepicker.h index e94746736b..fb0f10f6d8 100644 --- a/include/wx/filepicker.h +++ b/include/wx/filepicker.h @@ -17,7 +17,6 @@ #if wxUSE_FILEPICKERCTRL || wxUSE_DIRPICKERCTRL #include "wx/pickerbase.h" -#include "wx/filename.h" class WXDLLIMPEXP_CORE wxDialog; class WXDLLIMPEXP_CORE wxFileDirPickerEvent; @@ -96,7 +95,6 @@ class WXDLLIMPEXP_CORE wxFileDirPickerCtrlBase : public wxPickerBase { public: wxFileDirPickerCtrlBase() : m_bIgnoreNextTextCtrlUpdate(false) {} - virtual ~wxFileDirPickerCtrlBase() {} // NB: no default values since this function will never be used // directly by the user and derived classes wouldn't use them @@ -139,6 +137,9 @@ public: // internal functions // Returns the event type sent by this picker virtual wxEventType GetEventType() const = 0; + // Returns the filtered value currently placed in the text control (if present). + virtual wxString GetTextCtrlValue() const = 0; + protected: // true if the next UpdateTextCtrl() call is to ignore @@ -160,16 +161,15 @@ protected: #ifdef __WXGTK__ // GTK apps usually don't have a textctrl next to the picker - #define wxFLP_DEFAULT_STYLE (wxFLP_OPEN) + #define wxFLP_DEFAULT_STYLE (wxFLP_OPEN|wxFLP_FILE_MUST_EXIST) #else - #define wxFLP_DEFAULT_STYLE (wxFLP_USE_TEXTCTRL|wxFLP_OPEN) + #define wxFLP_DEFAULT_STYLE (wxFLP_USE_TEXTCTRL|wxFLP_OPEN|wxFLP_FILE_MUST_EXIST) #endif class WXDLLIMPEXP_CORE wxFilePickerCtrl : public wxFileDirPickerCtrlBase { public: wxFilePickerCtrl() {} - virtual ~wxFilePickerCtrl() {} wxFilePickerCtrl(wxWindow *parent, wxWindowID id, @@ -217,10 +217,11 @@ public: // overrides return true; } - bool CheckPath(const wxString &path) const - { - return HasFlag(wxFLP_SAVE) || wxFileName::FileExists(path); - } + // return true if the given path is valid for this control + bool CheckPath(const wxString& path) const; + + // return the text control value in canonical form + wxString GetTextCtrlValue() const; bool IsCwdToUpdate() const { return HasFlag(wxFLP_CHANGE_DIR); } @@ -255,35 +256,43 @@ private: #ifdef __WXGTK__ // GTK apps usually don't have a textctrl next to the picker - #define wxDIRP_DEFAULT_STYLE 0 + #define wxDIRP_DEFAULT_STYLE (wxDIRP_DIR_MUST_EXIST) #else - #define wxDIRP_DEFAULT_STYLE (wxDIRP_USE_TEXTCTRL) + #define wxDIRP_DEFAULT_STYLE (wxDIRP_USE_TEXTCTRL|wxDIRP_DIR_MUST_EXIST) #endif class WXDLLIMPEXP_CORE wxDirPickerCtrl : public wxFileDirPickerCtrlBase { public: wxDirPickerCtrl() {} - virtual ~wxDirPickerCtrl() {} wxDirPickerCtrl(wxWindow *parent, wxWindowID id, - const wxString& path = wxEmptyString, - const wxString& message = wxDirSelectorPromptStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = wxDIRP_DEFAULT_STYLE, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxDirPickerCtrlNameStr) - { Create(parent, id, path, message, pos, size, style, validator, name); } + const wxString& path = wxEmptyString, + const wxString& message = wxDirSelectorPromptStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDIRP_DEFAULT_STYLE, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxDirPickerCtrlNameStr) + { + Create(parent, id, path, message, pos, size, style, validator, name); + } bool Create(wxWindow *parent, wxWindowID id, - const wxString& path = wxEmptyString, - const wxString& message = wxDirSelectorPromptStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = wxDIRP_DEFAULT_STYLE, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxDirPickerCtrlNameStr) - { return wxFileDirPickerCtrlBase::CreateBase(parent, id, path, message, wxEmptyString, - pos, size, style, validator, name); } + const wxString& path = wxEmptyString, + const wxString& message = wxDirSelectorPromptStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxDIRP_DEFAULT_STYLE, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxDirPickerCtrlNameStr) + { + return wxFileDirPickerCtrlBase::CreateBase + ( + parent, id, path, message, wxEmptyString, + pos, size, style, validator, name + ); + } public: // overrides @@ -297,8 +306,9 @@ public: // overrides return true; } - bool CheckPath(const wxString &path) const - { if (HasFlag(wxDIRP_DIR_MUST_EXIST)) return wxFileName::DirExists(path); else return true; } + bool CheckPath(const wxString &path) const; + + wxString GetTextCtrlValue() const; bool IsCwdToUpdate() const { return HasFlag(wxDIRP_CHANGE_DIR); } diff --git a/include/wx/gtk/filepicker.h b/include/wx/gtk/filepicker.h index 5e04b4f88a..7a9efccc53 100644 --- a/include/wx/gtk/filepicker.h +++ b/include/wx/gtk/filepicker.h @@ -39,12 +39,6 @@ { \ m_dialog->Destroy(); \ return wxButton::Destroy(); \ - } \ - \ - virtual void SetPath(const wxString &str) \ - { \ - m_path=str; \ - UpdateDialogPath(m_dialog); \ } @@ -105,6 +99,8 @@ public: // some overrides ~(wxFD_SAVE | wxFD_OVERWRITE_PROMPT)) | wxFD_OPEN; } + virtual void SetPath(const wxString &str); + // see macro defined above FILEDIRBTN_OVERRIDES @@ -123,7 +119,7 @@ private: class WXDLLIMPEXP_CORE wxDirButton : public wxGenericDirButton { public: - wxDirButton() { m_dialog = NULL;} + wxDirButton() { Init(); } wxDirButton(wxWindow *parent, wxWindowID id, const wxString& label = wxFilePickerWidgetLabel, @@ -135,7 +131,8 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxFilePickerWidgetNameStr) { - m_dialog = NULL; + Init(); + Create(parent, id, label, path, message, wxEmptyString, pos, size, style, validator, name); } @@ -157,9 +154,6 @@ public: // overrides const wxValidator& validator = wxDefaultValidator, const wxString& name = wxFilePickerWidgetNameStr); - // used by the GTK callback only - void UpdatePath(char *gtkpath) - { m_path = wxString::FromAscii(gtkpath); } // GtkFileChooserButton does not support GTK_FILE_CHOOSER_CREATE_FOLDER // thus we must ensure that the wxDD_DIR_MUST_EXIST style was given @@ -168,12 +162,28 @@ public: // overrides return (wxGenericDirButton::GetDialogStyle() | wxDD_DIR_MUST_EXIST); } + virtual void SetPath(const wxString &str); + // see macro defined above FILEDIRBTN_OVERRIDES protected: + // common part of all ctors + void Init() + { + m_dialog = NULL; + m_bIgnoreNextChange = false; + } + wxDialog *m_dialog; +public: // used by the GTK callback only + + bool m_bIgnoreNextChange; + + void UpdatePath(const char *gtkpath) + { m_path = wxString::FromAscii(gtkpath); } + private: DECLARE_DYNAMIC_CLASS(wxDirButton) }; diff --git a/src/common/filepickercmn.cpp b/src/common/filepickercmn.cpp index 3591e7d654..27fb86a331 100644 --- a/src/common/filepickercmn.cpp +++ b/src/common/filepickercmn.cpp @@ -27,6 +27,7 @@ #if wxUSE_FILEPICKERCTRL || wxUSE_DIRPICKERCTRL #include "wx/filepicker.h" +#include "wx/filename.h" #ifndef WX_PRECOMP #include "wx/textctrl.h" @@ -106,9 +107,7 @@ void wxFileDirPickerCtrlBase::UpdatePickerFromTextCtrl() // remove the eventually present path-separator from the end of the textctrl // string otherwise we would generate a wxFileDirPickerEvent when changing // from e.g. /home/user to /home/user/ and we want to avoid it ! - wxString newpath(m_text->GetValue()); - if (!newpath.empty() && wxFileName::IsPathSeparator(newpath.Last())) - newpath.RemoveLast(); + wxString newpath(GetTextCtrlValue()); if (!CheckPath(newpath)) return; // invalid user input @@ -120,7 +119,7 @@ void wxFileDirPickerCtrlBase::UpdatePickerFromTextCtrl() // NOTE: the path separator is required because if newpath is "C:" // then no change would happen if (IsCwdToUpdate()) - wxSetWorkingDirectory(newpath + wxFileName::GetPathSeparator()); + wxSetWorkingDirectory(newpath); // fire an event wxFileDirPickerEvent event(GetEventType(), this, GetId(), newpath); @@ -158,9 +157,48 @@ void wxFileDirPickerCtrlBase::OnFileDirChange(wxFileDirPickerEvent &ev) #endif // wxUSE_FILEPICKERCTRL || wxUSE_DIRPICKERCTRL +// ---------------------------------------------------------------------------- +// wxFileDirPickerCtrl +// ---------------------------------------------------------------------------- + #if wxUSE_FILEPICKERCTRL + IMPLEMENT_DYNAMIC_CLASS(wxFilePickerCtrl, wxPickerBase) -#endif + +bool wxFilePickerCtrl::CheckPath(const wxString& path) const +{ + // if wxFLP_SAVE was given or wxFLP_FILE_MUST_EXIST has NOT been given we + // must accept any path + return HasFlag(wxFLP_SAVE) || + !HasFlag(wxFLP_FILE_MUST_EXIST) || + wxFileName::FileExists(path); +} + +wxString wxFilePickerCtrl::GetTextCtrlValue() const +{ + // filter it through wxFileName to remove any spurious path separator + return wxFileName(m_text->GetValue()).GetFullPath(); +} + +#endif // wxUSE_FILEPICKERCTRL + +// ---------------------------------------------------------------------------- +// wxDirPickerCtrl +// ---------------------------------------------------------------------------- + #if wxUSE_DIRPICKERCTRL IMPLEMENT_DYNAMIC_CLASS(wxDirPickerCtrl, wxPickerBase) -#endif + +bool wxDirPickerCtrl::CheckPath(const wxString& path) const +{ + // if wxDIRP_DIR_MUST_EXIST has NOT been given we must accept any path + return !HasFlag(wxDIRP_DIR_MUST_EXIST) || wxFileName::DirExists(path); +} + +wxString wxDirPickerCtrl::GetTextCtrlValue() const +{ + // filter it through wxFileName to remove any spurious path separator + return wxFileName::DirName(m_text->GetValue()).GetPath(); +} + +#endif // wxUSE_DIRPICKERCTRL diff --git a/src/gtk/filepicker.cpp b/src/gtk/filepicker.cpp index 6784f90430..f5f6a0a97b 100644 --- a/src/gtk/filepicker.cpp +++ b/src/gtk/filepicker.cpp @@ -20,12 +20,10 @@ #if wxUSE_FILEPICKERCTRL && defined(__WXGTK26__) #include "wx/filepicker.h" - #include "wx/tooltip.h" #include -#include // chdir // ============================================================================ @@ -129,6 +127,13 @@ void wxFileButton::OnDialogOK(wxCommandEvent& ev) } } + +void wxFileButton::SetPath(const wxString &str) +{ + m_path = str; + UpdateDialogPath(m_dialog); +} + #endif // wxUSE_FILEPICKERCTRL && defined(__WXGTK26__) @@ -136,6 +141,8 @@ void wxFileButton::OnDialogOK(wxCommandEvent& ev) #if wxUSE_DIRPICKERCTRL && defined(__WXGTK26__) +#include // chdir + //----------------------------------------------------------------------------- // "current-folder-changed" //----------------------------------------------------------------------------- @@ -145,6 +152,12 @@ static void gtk_dirbutton_currentfolderchanged_callback(GtkFileChooserButton *wi wxDirButton *p) { // update the m_path member of the wxDirButtonGTK + // unless the path was changed by wxDirButton::SetPath() + if (p->m_bIgnoreNextChange) + { + p->m_bIgnoreNextChange=false; + return; + } wxASSERT(p); // NB: it's important to use gtk_file_chooser_get_filename instead of @@ -202,6 +215,7 @@ bool wxDirButton::Create( wxWindow *parent, wxWindowID id, m_wildcard = wildcard; if ((m_dialog = CreateDialog()) == NULL) return false; + SetPath(path); // little trick used to avoid problems when there are other GTK windows 'grabbed': // GtkFileChooserDialog won't be responsive to user events if there is another @@ -246,4 +260,18 @@ wxDirButton::~wxDirButton() m_dialog->m_widget = NULL; } +void wxDirButton::SetPath(const wxString &str) +{ + m_path = str; + + // wxDirButton uses the "current-folder-changed" signal which is triggered also + // when we set the path on the dialog associated with this button; thus we need + // to set the following flag to avoid sending a wxFileDirPickerEvent from this + // function (which would be inconsistent with wxFileButton's behaviour and in + // general with all wxWidgets control-manipulation functions which do not send events). + m_bIgnoreNextChange = true; + + UpdateDialogPath(m_dialog); +} + #endif // wxUSE_DIRPICKERCTRL && defined(__WXGTK26__) -- 2.45.2