From 25f981bfadb95983b10ff4a14402385af8214f91 Mon Sep 17 00:00:00 2001 From: Dimitri Schoolwerth Date: Fri, 12 Feb 2021 23:40:20 +0100 Subject: [PATCH 1/5] Demonstrate wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES in dialogs sample Add a menu option (Ctrl+Cmd+S) to toggle showing of the filter choice with file types in open dialogs on macOS. --- samples/dialogs/dialogs.cpp | 18 ++++++++++++++++++ samples/dialogs/dialogs.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index 8a8f1998fc..a7ed02b5f5 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -203,6 +203,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(DIALOGS_FILES_OPEN_WINDOW_MODAL, MyFrame::FilesOpenWindowModal) EVT_MENU(DIALOGS_FILE_SAVE, MyFrame::FileSave) EVT_MENU(DIALOGS_FILE_SAVE_WINDOW_MODAL, MyFrame::FileSaveWindowModal) + EVT_MENU(DIALOGS_MAC_TOGGLE_ALWAYS_SHOW_TYPES, MyFrame::MacToggleAlwaysShowTypes) #endif // wxUSE_FILEDLG #if USE_FILEDLG_GENERIC @@ -504,6 +505,13 @@ bool MyApp::OnInit() filedlg_menu->Append(DIALOGS_FILE_SAVE_GENERIC, "Sa&ve file (generic)"); #endif // USE_FILEDLG_GENERIC +#ifdef __WXOSX_COCOA__ + filedlg_menu->AppendSeparator(); + filedlg_menu->AppendCheckItem(DIALOGS_MAC_TOGGLE_ALWAYS_SHOW_TYPES, + "macOS only: Toggle open file " + "\"Always show types\"\tRawCtrl+Ctrl+S"); +#endif + menuDlg->Append(wxID_ANY,"&File operations",filedlg_menu); #endif // wxUSE_FILEDLG @@ -1853,6 +1861,16 @@ void MyFrame::FileSaveWindowModalClosed(wxWindowModalDialogEvent& event) #endif // wxUSE_FILEDLG +void MyFrame::MacToggleAlwaysShowTypes(wxCommandEvent& event) +{ +#ifdef wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES + wxSystemOptions::SetOption(wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, + event.IsChecked()); +#else + wxUnusedVar(event); +#endif +} + #if USE_FILEDLG_GENERIC void MyFrame::FileOpenGeneric(wxCommandEvent& WXUNUSED(event) ) { diff --git a/samples/dialogs/dialogs.h b/samples/dialogs/dialogs.h index 8b7cf00b2b..4972a537e4 100644 --- a/samples/dialogs/dialogs.h +++ b/samples/dialogs/dialogs.h @@ -433,6 +433,7 @@ public: void FileSave(wxCommandEvent& event); void FileSaveWindowModal(wxCommandEvent& event); void FileSaveWindowModalClosed(wxWindowModalDialogEvent& event); + void MacToggleAlwaysShowTypes(wxCommandEvent& event); #endif // wxUSE_FILEDLG #if USE_FILEDLG_GENERIC @@ -616,6 +617,7 @@ enum DIALOGS_FILE_OPEN_GENERIC, DIALOGS_FILES_OPEN_GENERIC, DIALOGS_FILE_SAVE_GENERIC, + DIALOGS_MAC_TOGGLE_ALWAYS_SHOW_TYPES, DIALOGS_DIR_CHOOSE, DIALOGS_DIR_CHOOSE_WINDOW_MODAL, DIALOGS_DIRNEW_CHOOSE, From 5cc2f6ce9fd206c5e46e73188291e053b0013bb4 Mon Sep 17 00:00:00 2001 From: Dimitri Schoolwerth Date: Sat, 13 Feb 2021 00:04:45 +0100 Subject: [PATCH 2/5] Fix width of file type wxChoice in open dialogs on macOS When using both an extra control and wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES set to 1 to show file types, the controls for the latter stretch towards the dialog's width. Fix by not stretching the wxChoice used for filtering and surrounding the file type controls with stretching spacers instead. This makes the filter controls appear the same as without an extra control: horizontally centred and not stretching. --- src/osx/cocoa/filedlg.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/osx/cocoa/filedlg.mm b/src/osx/cocoa/filedlg.mm index 99536113ee..dabb77f4a8 100644 --- a/src/osx/cocoa/filedlg.mm +++ b/src/osx/cocoa/filedlg.mm @@ -261,10 +261,12 @@ wxWindow* wxFileDialog::CreateFilterPanel(wxWindow *extracontrol) { wxBoxSizer *horizontalSizer = new wxBoxSizer(wxHORIZONTAL); verticalSizer->Add(horizontalSizer, 0, wxEXPAND, 0); + horizontalSizer->AddStretchSpacer(); wxStaticText *stattext = new wxStaticText( extrapanel, wxID_ANY, _("File type:") ); horizontalSizer->Add(stattext, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); m_filterChoice = new wxChoice(extrapanel, wxID_ANY); - horizontalSizer->Add(m_filterChoice, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5); + horizontalSizer->Add(m_filterChoice, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + horizontalSizer->AddStretchSpacer(); m_filterChoice->Append(m_filterNames); if( m_filterNames.GetCount() > 0) { From 57688cf2dad58491d666e9042504ab4199b6cde6 Mon Sep 17 00:00:00 2001 From: Dimitri Schoolwerth Date: Sat, 13 Feb 2021 00:30:02 +0100 Subject: [PATCH 3/5] Refactor repetitions into wxFileDialogBase::UpdateExtraControlUI() No real changes, just prepare for the next commit before repeating more code. --- include/wx/filedlg.h | 3 +++ src/common/fldlgcmn.cpp | 6 ++++++ src/gtk/filedlg.cpp | 3 +-- src/msw/filedlg.cpp | 6 ++---- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/wx/filedlg.h b/include/wx/filedlg.h index 8689cc99cd..230caf4163 100644 --- a/include/wx/filedlg.h +++ b/include/wx/filedlg.h @@ -181,6 +181,9 @@ protected: { return m_extraControlCreator != NULL; } // get the size of the extra control by creating and deleting it wxSize GetExtraControlSize(); + // Helper function for native file dialog usage where no wx events + // are processed. + void UpdateExtraControlUI(); private: ExtraControlCreatorFunction m_extraControlCreator; diff --git a/src/common/fldlgcmn.cpp b/src/common/fldlgcmn.cpp index 466ce96d42..340df47af4 100644 --- a/src/common/fldlgcmn.cpp +++ b/src/common/fldlgcmn.cpp @@ -192,6 +192,12 @@ wxSize wxFileDialogBase::GetExtraControlSize() return (*m_extraControlCreator)(&dlg)->GetSize(); } +void wxFileDialogBase::UpdateExtraControlUI() +{ + if ( m_extraControl ) + m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE); +} + void wxFileDialogBase::SetPath(const wxString& path) { wxString ext; diff --git a/src/gtk/filedlg.cpp b/src/gtk/filedlg.cpp index ef23c2de18..6ab3fcae7c 100644 --- a/src/gtk/filedlg.cpp +++ b/src/gtk/filedlg.cpp @@ -496,8 +496,7 @@ void wxFileDialog::GTKSelectionChanged(const wxString& filename) { m_currentlySelectedFilename = filename; - if (m_extraControl) - m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE); + UpdateExtraControlUI(); } #endif // wxUSE_FILEDLG diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index 0234a4cece..c112a8656a 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -353,8 +353,7 @@ void wxFileDialog::MSWOnSelChange(WXHWND hDlg) else m_currentlySelectedFilename.clear(); - if ( m_extraControl ) - m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE); + UpdateExtraControlUI(); } void wxFileDialog::MSWOnTypeChange(WXHWND WXUNUSED(hDlg), int nFilterIndex) @@ -364,8 +363,7 @@ void wxFileDialog::MSWOnTypeChange(WXHWND WXUNUSED(hDlg), int nFilterIndex) // circumstances, so take care before decrementing it. m_currentlySelectedFilterIndex = nFilterIndex ? nFilterIndex - 1 : 0; - if ( m_extraControl ) - m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE); + UpdateExtraControlUI(); } // helper used below in ShowCommFileDialog(): style is used to determine From 40422db37d5df2a3552a5b10ccca741acaf9af98 Mon Sep 17 00:00:00 2001 From: Dimitri Schoolwerth Date: Sat, 13 Feb 2021 00:52:48 +0100 Subject: [PATCH 4/5] Add wxMac wxFileDialog::GetCurrentlySelectedFilterIndex() support Simply set the relevant variable while changing selection and give the extra control a chance to update. Note that updating the UI currently asserts with the dialog sample if wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES is 1 (toggable with Ctrl+Cmd+S in the sample), This will be fixed in the next commit. --- interface/wx/filedlg.h | 5 +++-- src/osx/cocoa/filedlg.mm | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/wx/filedlg.h b/interface/wx/filedlg.h index 3be2c15429..cd53f73e22 100644 --- a/interface/wx/filedlg.h +++ b/interface/wx/filedlg.h @@ -236,10 +236,11 @@ public: control to update its state depending on the currently selected file type filter. - Currently this function is fully implemented only under MSW and + Currently this function is fully implemented under macOS and MSW and always returns @c wxNOT_FOUND elsewhere. - @since 3.1.3 + @since 3.1.3 - MSW + @since 3.1.5 - macOS @return The 0-based index of the currently selected file type filter or wxNOT_FOUND if nothing is selected. diff --git a/src/osx/cocoa/filedlg.mm b/src/osx/cocoa/filedlg.mm index dabb77f4a8..3a5fecae72 100644 --- a/src/osx/cocoa/filedlg.mm +++ b/src/osx/cocoa/filedlg.mm @@ -295,6 +295,10 @@ void wxFileDialog::DoOnFilterSelected(int index) NSArray* types = GetTypesFromExtension(m_filterExtensions[index],m_currentExtensions); NSSavePanel* panel = (NSSavePanel*) GetWXWindow(); [panel setAllowedFileTypes:types]; + + m_currentlySelectedFilterIndex = index; + + UpdateExtraControlUI(); } // An item has been selected in the file filter wxChoice: From f048a03ea6b954ba199f5e56fd15cd90453d7a91 Mon Sep 17 00:00:00 2001 From: Dimitri Schoolwerth Date: Sat, 13 Feb 2021 01:24:21 +0100 Subject: [PATCH 5/5] Fix parent of extra control not being a wxFileDialogBase on macOS A wxEVT_UPDATE_UI handler expects the parent of the extra control panel to be at least a wxFileDialogBase. However with wxMac when showing file types the extra control gets reparented and has the panel containing file type controls as a parent. Fix by not reparenting in case the extra control itself already is a panel, and then instead use the extra control as a container for the file type controls. --- src/osx/cocoa/filedlg.mm | 45 +++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/osx/cocoa/filedlg.mm b/src/osx/cocoa/filedlg.mm index 3a5fecae72..102a105e93 100644 --- a/src/osx/cocoa/filedlg.mm +++ b/src/osx/cocoa/filedlg.mm @@ -246,16 +246,25 @@ void wxFileDialog::ShowWindowModal() } -// Create a panel with the file type drop down list -// If extra controls need to be added (see wxFileDialog::SetExtraControlCreator), add -// them to the panel as well -// Returns the newly created wxPanel +// Fill a new or existing panel with the file type drop down list. +// If extra controls need to be added (see wxFileDialog::SetExtraControlCreator), +// use that as a panel if possible, otherwise add them to a new panel. +// Returns a newly created wxPanel or extracontrol if it's suitable as a filter +// panel. wxWindow* wxFileDialog::CreateFilterPanel(wxWindow *extracontrol) { - wxPanel *extrapanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); + // Try to use extracontrol as a filter panel instead of creating a new one + // and then reparenting extracontrol. Reparenting is less desired as user + // code may expect the parent to be a wxFileDialog as on other platforms. + const bool useExtraControlAsPanel = extracontrol && + wxDynamicCast(extracontrol, wxPanel) != NULL; + + wxWindow* extrapanel = useExtraControlAsPanel + ? extracontrol + : static_cast(new wxPanel(this)); + wxBoxSizer *verticalSizer = new wxBoxSizer(wxVERTICAL); - extrapanel->SetSizer(verticalSizer); // the file type control { @@ -278,13 +287,29 @@ wxWindow* wxFileDialog::CreateFilterPanel(wxWindow *extracontrol) if(extracontrol) { - wxBoxSizer *horizontalSizer = new wxBoxSizer(wxHORIZONTAL); - verticalSizer->Add(horizontalSizer, 0, wxEXPAND, 0); + // Either use an extra control's existing sizer or the extra control + // itself, to be in the vertical sizer. - extracontrol->Reparent(extrapanel); - horizontalSizer->Add(extracontrol); + wxSizer* existingSizer = extracontrol->GetSizer(); + if ( useExtraControlAsPanel && existingSizer ) + { + // Move extra control's sizer to verticalSizer. + extracontrol->SetSizer(NULL, /* deleteOld = */ false); + verticalSizer->Add(existingSizer); + } + else + { + wxBoxSizer* horizontalSizer = new wxBoxSizer(wxHORIZONTAL); + verticalSizer->Add(horizontalSizer, 0, wxEXPAND, 0); + + if ( !useExtraControlAsPanel ) + extracontrol->Reparent(extrapanel); + horizontalSizer->Add(extracontrol); + } } + extrapanel->SetSizer(verticalSizer); + verticalSizer->Layout(); verticalSizer->SetSizeHints(extrapanel); return extrapanel;