From 926df8a162ac02ccb102733c2c86d2cd50341d7e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 31 May 2013 23:21:27 +0000 Subject: [PATCH] Add wxFileDialog::GetCurrentlySelectedFilename(). Also send wxEVT_UPDATE_UI events for the extra controls in wxFileDialog. The combination of these changes allows extra controls to update their state depending on the current selection in the dialog. Show a simple example of doing it in the dialogs sample. Closes #15235. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74071 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/filedlg.h | 10 +++++++++ include/wx/gtk/filedlg.h | 3 +++ include/wx/msw/filedlg.h | 3 +++ interface/wx/filedlg.h | 20 ++++++++++++++++++ samples/dialogs/dialogs.cpp | 35 ++++++++++++++++++++++++++++--- src/gtk/filedlg.cpp | 19 +++++++++++++++++ src/msw/filedlg.cpp | 41 +++++++++++++++++++++++++++++++------ 8 files changed, 123 insertions(+), 9 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 448a54c66c..3093cd06b1 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -669,6 +669,7 @@ All (GUI): - Pass menu events to the handler in the associated wxMenuBar. - Add wxWindow::BeginRepositioningChildren() and EndRepositioningChildren(). - Fix wxStyledTextCtrl::SetInsertionPointEnd() (troelsk). +- Add wxFileDialog::GetCurrentlySelectedFilename() (Carl Godkin). wxGTK: diff --git a/include/wx/filedlg.h b/include/wx/filedlg.h index e2a6bfd3da..01a33015d6 100644 --- a/include/wx/filedlg.h +++ b/include/wx/filedlg.h @@ -122,6 +122,9 @@ public: virtual wxString GetWildcard() const { return m_wildCard; } virtual int GetFilterIndex() const { return m_filterIndex; } + virtual wxString GetCurrentlySelectedFilename() const + { return m_currentlySelectedFilename; } + // this function is called with wxFileDialog as parameter and should // create the window containing the extra controls we want to show in it typedef wxWindow *(*ExtraControlCreatorFunction)(wxWindow*); @@ -155,6 +158,13 @@ protected: wxString m_fileName; wxString m_wildCard; int m_filterIndex; + + // Currently selected, but not yet necessarily accepted by the user, file. + // This should be updated whenever the selection in the control changes by + // the platform-specific code to provide a useful implementation of + // GetCurrentlySelectedFilename(). + wxString m_currentlySelectedFilename; + wxWindow* m_extraControl; // returns true if control is created (if it already exists returns false) diff --git a/include/wx/gtk/filedlg.h b/include/wx/gtk/filedlg.h index f22b836692..ececadcf0b 100644 --- a/include/wx/gtk/filedlg.h +++ b/include/wx/gtk/filedlg.h @@ -58,6 +58,9 @@ public: virtual bool SupportsExtraControl() const { return true; } + // Implementation only. + void GTKSelectionChanged(const wxString& filename); + protected: // override this from wxTLW since the native diff --git a/include/wx/msw/filedlg.h b/include/wx/msw/filedlg.h index 4c4ec74993..889674199c 100644 --- a/include/wx/msw/filedlg.h +++ b/include/wx/msw/filedlg.h @@ -44,6 +44,9 @@ public: // called from the hook procedure on CDN_INITDONE reception virtual void MSWOnInitDone(WXHWND hDlg); + // called from the hook procedure on CDN_SELCHANGE. + void MSWOnSelChange(WXHWND hDlg); + protected: #if !(defined(__SMARTPHONE__) && defined(__WXWINCE__)) diff --git a/interface/wx/filedlg.h b/interface/wx/filedlg.h index 83648a7fa6..ac7daba24a 100644 --- a/interface/wx/filedlg.h +++ b/interface/wx/filedlg.h @@ -183,6 +183,26 @@ public: */ virtual ~wxFileDialog(); + /** + Returns the path of the file currently selected in dialog. + + Notice that this file is not necessarily going to be accepted by the + user, so calling this function mostly makes sense from an update UI + event handler of a custom file dialog extra control to update its state + depending on the currently selected file. + + Currently this function is fully implemented under GTK and MSW and + always returns an empty string elsewhere. + + @since 2.9.5 + + @return The path of the currently selected file or an empty string if + nothing is selected. + + @see SetExtraControlCreator() + */ + virtual wxString GetCurrentlySelectedFilename() const; + /** Returns the default directory. */ diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index 11a4bc4388..028d755f89 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -25,6 +25,7 @@ #include "wx/apptrait.h" #include "wx/datetime.h" +#include "wx/filename.h" #include "wx/image.h" #include "wx/bookctrl.h" #include "wx/artprov.h" @@ -1332,14 +1333,34 @@ class MyExtraPanel : public wxPanel { public: MyExtraPanel(wxWindow *parent); - void OnCheckBox(wxCommandEvent& event) { m_btn->Enable(event.IsChecked()); } wxString GetInfo() const { return wxString::Format("checkbox value = %d", (int) m_cb->GetValue()); } + private: + void OnCheckBox(wxCommandEvent& event) { m_btn->Enable(event.IsChecked()); } + void OnUpdateLabelUI(wxUpdateUIEvent& event) + { + wxFileDialog* const dialog = wxStaticCast(GetParent(), wxFileDialog); + const wxString fn = dialog->GetCurrentlySelectedFilename(); + + wxString msg; + if ( fn.empty() ) + msg = "Nothing"; + else if ( wxFileName::FileExists(fn) ) + msg = "File"; + else if ( wxFileName::DirExists(fn) ) + msg = "Directory"; + else + msg = "Something else"; + + event.SetText(msg + " selected"); + } + wxButton *m_btn; wxCheckBox *m_cb; + wxStaticText *m_label; }; MyExtraPanel::MyExtraPanel(wxWindow *parent) @@ -1348,12 +1369,20 @@ MyExtraPanel::MyExtraPanel(wxWindow *parent) m_btn = new wxButton(this, -1, wxT("Custom Button")); m_btn->Enable(false); m_cb = new wxCheckBox(this, -1, wxT("Enable Custom Button")); - m_cb->Connect(wxID_ANY, wxEVT_CHECKBOX, + m_cb->Connect(wxEVT_CHECKBOX, wxCommandEventHandler(MyExtraPanel::OnCheckBox), NULL, this); + m_label = new wxStaticText(this, wxID_ANY, "Nothing selected"); + m_label->Connect(wxEVT_UPDATE_UI, + wxUpdateUIEventHandler(MyExtraPanel::OnUpdateLabelUI), + NULL, this); + wxBoxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL); sizerTop->Add(m_cb, wxSizerFlags().Centre().Border()); sizerTop->AddStretchSpacer(); - sizerTop->Add(m_btn, wxSizerFlags().Right().Border()); + sizerTop->Add(m_btn, wxSizerFlags().Centre().Border()); + sizerTop->AddStretchSpacer(); + sizerTop->Add(m_label, wxSizerFlags().Centre().Border()); + SetSizerAndFit(sizerTop); } diff --git a/src/gtk/filedlg.cpp b/src/gtk/filedlg.cpp index a2f0712854..6f3b775ada 100644 --- a/src/gtk/filedlg.cpp +++ b/src/gtk/filedlg.cpp @@ -116,6 +116,15 @@ static void gtk_filedialog_response_callback(GtkWidget *w, gtk_filedialog_cancel_callback(w, dialog); } +static void gtk_filedialog_selchanged_callback(GtkFileChooser *chooser, + wxFileDialog *dialog) +{ + wxGtkString filename(gtk_file_chooser_get_preview_filename(chooser)); + + dialog->GTKSelectionChanged(wxString::FromUTF8(filename)); +} + + static void gtk_filedialog_update_preview_callback(GtkFileChooser *chooser, gpointer user_data) { @@ -249,6 +258,8 @@ bool wxFileDialog::Create(wxWindow *parent, const wxString& message, g_signal_connect (m_widget, "response", G_CALLBACK (gtk_filedialog_response_callback), this); + g_signal_connect (m_widget, "selection-changed", + G_CALLBACK (gtk_filedialog_selchanged_callback), this); // deal with extensions/filters SetWildcard(wildCard); @@ -463,4 +474,12 @@ int wxFileDialog::GetFilterIndex() const return m_fc.GetFilterIndex(); } +void wxFileDialog::GTKSelectionChanged(const wxString& filename) +{ + m_currentlySelectedFilename = filename; + + if (m_extraControl) + m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE); +} + #endif // wxUSE_FILEDLG diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index e1f5287021..fd71dc6b9c 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -173,13 +173,23 @@ wxFileDialogHookFunction(HWND hDlg, case WM_NOTIFY: { - OFNOTIFY *pNotifyCode = reinterpret_cast(lParam); - if ( pNotifyCode->hdr.code == CDN_INITDONE ) + OFNOTIFY* const + pNotifyCode = reinterpret_cast(lParam); + wxFileDialog* const + dialog = reinterpret_cast( + pNotifyCode->lpOFN->lCustData + ); + + switch ( pNotifyCode->hdr.code ) { - reinterpret_cast( - pNotifyCode->lpOFN->lCustData) - ->MSWOnInitDone((WXHWND)hDlg); - } + case CDN_INITDONE: + dialog->MSWOnInitDone((WXHWND)hDlg); + break; + + case CDN_SELCHANGE: + dialog->MSWOnSelChange((WXHWND)hDlg); + break; + } } break; @@ -323,10 +333,29 @@ void wxFileDialog::MSWOnInitDone(WXHWND hDlg) SetPosition(gs_rectDialog.GetPosition()); } + // Call selection change handler so that update handler will be + // called once with no selection. + MSWOnSelChange(hDlg); + // we shouldn't destroy this HWND SetHWND(NULL); } +void wxFileDialog::MSWOnSelChange(WXHWND hDlg) +{ + TCHAR buf[MAX_PATH]; + LRESULT len = SendMessage(::GetParent(hDlg), CDM_GETFILEPATH, + MAX_PATH, reinterpret_cast(buf)); + + if ( len > 0 ) + m_currentlySelectedFilename = buf; + else + m_currentlySelectedFilename.clear(); + + if ( m_extraControl ) + m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE); +} + // helper used below in ShowCommFileDialog(): style is used to determine // whether to show the "Save file" dialog (if it contains wxFD_SAVE bit) or // "Open file" one; returns true on success or false on failure in which case -- 2.45.2