diff options
author | Caolán McNamara <caolanm@redhat.com> | 2018-02-17 21:21:32 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2018-02-19 16:54:33 +0100 |
commit | 837ba68ac04ed52716eef531f034b6a49f576178 (patch) | |
tree | 0b0188a7280d7722cb29f72d9b10f519ccfc13ad /vcl/source | |
parent | 82a213880ff3927d8b2b3e5135743002a3b4df35 (diff) |
weld: hook up help response
and keep the current legacy ownership behaviour when welding the
legacy backend
Change-Id: I7e1f90f2d235abf0e10062b4be11ba5150bbdbfb
Reviewed-on: https://gerrit.libreoffice.org/49918
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/source')
-rw-r--r-- | vcl/source/app/salvtables.cxx | 116 | ||||
-rw-r--r-- | vcl/source/window/builder.cxx | 62 | ||||
-rw-r--r-- | vcl/source/window/layout.cxx | 3 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 7 |
4 files changed, 149 insertions, 39 deletions
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 12ce25351a46..d2bef1fe030a 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -27,6 +27,7 @@ #include <salbmp.hxx> #include <salobj.hxx> #include <salmenu.hxx> +#include <svdata.hxx> #include <vcl/builder.hxx> #include <vcl/combobox.hxx> #include <vcl/lstbox.hxx> @@ -296,11 +297,28 @@ class SalInstanceWindow : public SalInstanceContainer, public virtual weld::Wind private: VclPtr<SystemWindow> m_xWindow; + DECL_LINK(HelpHdl, vcl::Window&, bool); + + void override_child_help(vcl::Window* pParent) + { + for (vcl::Window *pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next)) + override_child_help(pChild); + pParent->SetHelpHdl(LINK(this, SalInstanceWindow, HelpHdl)); + } + + void clear_child_help(vcl::Window* pParent) + { + for (vcl::Window *pChild = pParent->GetWindow(GetWindowType::FirstChild); pChild; pChild = pChild->GetWindow(GetWindowType::Next)) + clear_child_help(pChild); + pParent->SetHelpHdl(Link<vcl::Window&,bool>()); + } + public: SalInstanceWindow(SystemWindow* pWindow, bool bTakeOwnership) : SalInstanceContainer(pWindow, bTakeOwnership) , m_xWindow(pWindow) { + override_child_help(m_xWindow); } virtual void set_title(const OUString& rTitle) override @@ -312,8 +330,41 @@ public: { return m_xWindow->GetText(); } + + bool help() + { + //show help for widget with keyboard focus + vcl::Window* pWidget = ImplGetSVData()->maWinData.mpFocusWin; + if (!pWidget) + pWidget = m_xWindow; + OString sHelpId = pWidget->GetHelpId(); + while (sHelpId.isEmpty()) + { + pWidget = pWidget->GetParent(); + if (!pWidget) + break; + sHelpId = pWidget->GetHelpId(); + } + std::unique_ptr<weld::Widget> xTemp(pWidget != m_xWindow ? new SalInstanceWidget(pWidget, false) : nullptr); + weld::Widget* pSource = xTemp ? xTemp.get() : this; + bool bRunNormalHelpRequest = !m_aHelpRequestHdl.IsSet() || m_aHelpRequestHdl.Call(*pSource); + Help* pHelp = bRunNormalHelpRequest ? Application::GetHelp() : nullptr; + if (pHelp) + pHelp->Start(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), pSource); + return false; + } + + virtual ~SalInstanceWindow() override + { + clear_child_help(m_xWindow); + } }; +IMPL_LINK_NOARG(SalInstanceWindow, HelpHdl, vcl::Window&, bool) +{ + return help(); +} + class SalInstanceDialog : public SalInstanceWindow, public virtual weld::Dialog { private: @@ -328,7 +379,6 @@ public: virtual int run() override { - m_xDialog->Show(); return m_xDialog->Execute(); } @@ -1104,89 +1154,104 @@ public: class SalInstanceBuilder : public weld::Builder { private: - VclBuilder m_aBuilder; + std::unique_ptr<VclBuilder> m_xBuilder; + VclPtr<vcl::Window> m_aOwnedToplevel; public: SalInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile) : weld::Builder(rUIFile) - , m_aBuilder(pParent, rUIRoot, rUIFile) + , m_xBuilder(new VclBuilder(pParent, rUIRoot, rUIFile, OString(), css::uno::Reference<css::frame::XFrame>(), false)) { } virtual weld::MessageDialog* weld_message_dialog(const OString &id, bool bTakeOwnership) override { - MessageDialog* pMessageDialog = m_aBuilder.get<MessageDialog>(id); - return pMessageDialog ? new SalInstanceMessageDialog(pMessageDialog, bTakeOwnership) : nullptr; + MessageDialog* pMessageDialog = m_xBuilder->get<MessageDialog>(id); + weld::MessageDialog* pRet = pMessageDialog ? new SalInstanceMessageDialog(pMessageDialog, false) : nullptr; + if (bTakeOwnership && pMessageDialog) + { + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pMessageDialog); + m_xBuilder->drop_ownership(pMessageDialog); + } + return pRet; } virtual weld::Dialog* weld_dialog(const OString &id, bool bTakeOwnership) override { - Dialog* pDialog = m_aBuilder.get<Dialog>(id); - return pDialog ? new SalInstanceDialog(pDialog, bTakeOwnership) : nullptr; + Dialog* pDialog = m_xBuilder->get<Dialog>(id); + weld::Dialog* pRet = pDialog ? new SalInstanceDialog(pDialog, false) : nullptr; + if (bTakeOwnership && pDialog) + { + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pDialog); + m_xBuilder->drop_ownership(pDialog); + } + return pRet; } virtual weld::Window* weld_window(const OString &id, bool bTakeOwnership) override { - SystemWindow* pWindow = m_aBuilder.get<SystemWindow>(id); + SystemWindow* pWindow = m_xBuilder->get<SystemWindow>(id); return pWindow ? new SalInstanceWindow(pWindow, bTakeOwnership) : nullptr; } virtual weld::Widget* weld_widget(const OString &id, bool bTakeOwnership) override { - vcl::Window* pWidget = m_aBuilder.get<vcl::Window>(id); + vcl::Window* pWidget = m_xBuilder->get<vcl::Window>(id); return pWidget ? new SalInstanceWidget(pWidget, bTakeOwnership) : nullptr; } virtual weld::Container* weld_container(const OString &id, bool bTakeOwnership) override { - vcl::Window* pContainer = m_aBuilder.get<vcl::Window>(id); + vcl::Window* pContainer = m_xBuilder->get<vcl::Window>(id); return pContainer ? new SalInstanceContainer(pContainer, bTakeOwnership) : nullptr; } virtual weld::Frame* weld_frame(const OString &id, bool bTakeOwnership) override { - VclFrame* pFrame = m_aBuilder.get<VclFrame>(id); + VclFrame* pFrame = m_xBuilder->get<VclFrame>(id); return pFrame ? new SalInstanceFrame(pFrame, bTakeOwnership) : nullptr; } virtual weld::Notebook* weld_notebook(const OString &id, bool bTakeOwnership) override { - TabControl* pNotebook = m_aBuilder.get<TabControl>(id); + TabControl* pNotebook = m_xBuilder->get<TabControl>(id); return pNotebook ? new SalInstanceNotebook(pNotebook, bTakeOwnership) : nullptr; } virtual weld::Button* weld_button(const OString &id, bool bTakeOwnership) override { - Button* pButton = m_aBuilder.get<Button>(id); + Button* pButton = m_xBuilder->get<Button>(id); return pButton ? new SalInstanceButton(pButton, bTakeOwnership) : nullptr; } virtual weld::RadioButton* weld_radio_button(const OString &id, bool bTakeOwnership) override { - RadioButton* pRadioButton = m_aBuilder.get<RadioButton>(id); + RadioButton* pRadioButton = m_xBuilder->get<RadioButton>(id); return pRadioButton ? new SalInstanceRadioButton(pRadioButton, bTakeOwnership) : nullptr; } virtual weld::CheckButton* weld_check_button(const OString &id, bool bTakeOwnership) override { - CheckBox* pCheckButton = m_aBuilder.get<CheckBox>(id); + CheckBox* pCheckButton = m_xBuilder->get<CheckBox>(id); return pCheckButton ? new SalInstanceCheckButton(pCheckButton, bTakeOwnership) : nullptr; } virtual weld::Entry* weld_entry(const OString &id, bool bTakeOwnership) override { - Edit* pEntry = m_aBuilder.get<Edit>(id); + Edit* pEntry = m_xBuilder->get<Edit>(id); return pEntry ? new SalInstanceEntry(pEntry, bTakeOwnership) : nullptr; } virtual weld::SpinButton* weld_spin_button(const OString &id, bool bTakeOwnership) override { - NumericField* pSpinButton = m_aBuilder.get<NumericField>(id); + NumericField* pSpinButton = m_xBuilder->get<NumericField>(id); return pSpinButton ? new SalInstanceSpinButton(pSpinButton, bTakeOwnership) : nullptr; } virtual weld::ComboBoxText* weld_combo_box_text(const OString &id, bool bTakeOwnership) override { - vcl::Window* pComboBoxText = m_aBuilder.get<vcl::Window>(id); + vcl::Window* pComboBoxText = m_xBuilder->get<vcl::Window>(id); ComboBox* pComboBox = dynamic_cast<ComboBox*>(pComboBoxText); if (pComboBox) return new SalInstanceComboBoxText<ComboBox>(pComboBox, bTakeOwnership); @@ -1196,27 +1261,34 @@ public: virtual weld::TreeView* weld_tree_view(const OString &id, bool bTakeOwnership) override { - ListBox* pTreeView = m_aBuilder.get<ListBox>(id); + ListBox* pTreeView = m_xBuilder->get<ListBox>(id); return pTreeView ? new SalInstanceTreeView(pTreeView, bTakeOwnership) : nullptr; } virtual weld::Label* weld_label(const OString &id, bool bTakeOwnership) override { - FixedText* pLabel = m_aBuilder.get<FixedText>(id); + FixedText* pLabel = m_xBuilder->get<FixedText>(id); return pLabel ? new SalInstanceLabel(pLabel, bTakeOwnership) : nullptr; } virtual weld::TextView* weld_text_view(const OString &id, bool bTakeOwnership) override { - VclMultiLineEdit* pTextView = m_aBuilder.get<VclMultiLineEdit>(id); + VclMultiLineEdit* pTextView = m_xBuilder->get<VclMultiLineEdit>(id); return pTextView ? new SalInstanceTextView(pTextView, bTakeOwnership) : nullptr; } virtual weld::DrawingArea* weld_drawing_area(const OString &id, bool bTakeOwnership) override { - VclDrawingArea* pDrawingArea = m_aBuilder.get<VclDrawingArea>(id); + VclDrawingArea* pDrawingArea = m_xBuilder->get<VclDrawingArea>(id); return pDrawingArea ? new SalInstanceDrawingArea(pDrawingArea, bTakeOwnership) : nullptr; } + + virtual ~SalInstanceBuilder() override + { + if (VclBuilderContainer* pOwnedToplevel = dynamic_cast<VclBuilderContainer*>(m_aOwnedToplevel.get())) + pOwnedToplevel->m_pUIBuilder = std::move(m_xBuilder); + m_aOwnedToplevel.disposeAndClear(); + } }; weld::Builder* SalInstance::CreateBuilder(weld::Widget* pParent, const OUString& rUIRoot, const OUString& rUIFile) diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index cd7ffe99d051..c6d345434bc6 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -232,12 +232,14 @@ namespace weld } } -VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUString& sUIFile, const OString& sID, const css::uno::Reference<css::frame::XFrame>& rFrame) +VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUString& sUIFile, const OString& sID, + const css::uno::Reference<css::frame::XFrame>& rFrame, bool bLegacy) : m_sID(sID) , m_sHelpRoot(OUStringToOString(sUIFile, RTL_TEXTENCODING_UTF8)) , m_pStringReplace(Translate::GetReadStringHook()) , m_pParent(pParent) , m_bToplevelParentFound(false) + , m_bLegacy(bLegacy) , m_pParserState(new ParserState) , m_xFrame(rFrame) { @@ -869,7 +871,7 @@ namespace pButton->SetCommandHandler(aCommand); } - VclPtr<Button> extractStockAndBuildPushButton(vcl::Window *pParent, VclBuilder::stringmap &rMap) + VclPtr<Button> extractStockAndBuildPushButton(vcl::Window *pParent, VclBuilder::stringmap &rMap, bool bLegacy) { WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER; @@ -880,15 +882,18 @@ namespace if (extractStock(rMap)) { OUString sType = extractLabel(rMap); - if (sType == "gtk-ok") - xWindow = VclPtr<OKButton>::Create(pParent, nBits); - else if (sType == "gtk-cancel") - xWindow = VclPtr<CancelButton>::Create(pParent, nBits); - else if (sType == "gtk-close") - xWindow = VclPtr<CloseButton>::Create(pParent, nBits); - else if (sType == "gtk-help") - xWindow = VclPtr<HelpButton>::Create(pParent, nBits); - else + if (bLegacy) + { + if (sType == "gtk-ok") + xWindow = VclPtr<OKButton>::Create(pParent, nBits); + else if (sType == "gtk-cancel") + xWindow = VclPtr<CancelButton>::Create(pParent, nBits); + else if (sType == "gtk-close") + xWindow = VclPtr<CloseButton>::Create(pParent, nBits); + else if (sType == "gtk-help") + xWindow = VclPtr<HelpButton>::Create(pParent, nBits); + } + if (!xWindow) { xWindow = VclPtr<PushButton>::Create(pParent, nBits); xWindow->SetText(getStockText(sType)); @@ -1305,7 +1310,7 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString & } else if (name == "GtkMessageDialog") { - WinBits nBits = WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE; + WinBits nBits = WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE; if (extractResizable(rMap)) nBits |= WB_SIZEABLE; xWindow = VclPtr<MessageDialog>::Create(pParent, nBits); @@ -1357,7 +1362,7 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString & VclPtr<Button> xButton; OUString sMenu = BuilderUtils::extractCustomProperty(rMap); if (sMenu.isEmpty()) - xButton = extractStockAndBuildPushButton(pParent, rMap); + xButton = extractStockAndBuildPushButton(pParent, rMap, m_bLegacy); else { xButton = extractStockAndBuildMenuButton(pParent, rMap); @@ -3386,6 +3391,23 @@ short VclBuilder::get_response(const vcl::Window *pWindow) const return RET_CANCEL; } +IMPL_LINK(VclBuilder, ResponseHdl, ::Button*, pButton, void) +{ + short nResponse = get_response(pButton); + Dialog* pDialog = pButton->GetParentDialog(); + assert(pDialog && "who puts a response without a dialog"); + if (nResponse == RET_HELP) + { + vcl::Window* pFocusWin = Application::GetFocusWindow(); + if (!pFocusWin) + pFocusWin = pButton; + HelpEvent aEvt(pFocusWin->GetPointerPosPixel(), HelpEventMode::CONTEXT); + pFocusWin->RequestHelp(aEvt); + } + else + pDialog->EndDialog(nResponse); +} + void VclBuilder::set_response(const OString& sID, short nResponse) { switch (nResponse) @@ -3412,17 +3434,27 @@ void VclBuilder::set_response(const OString& sID, short nResponse) assert(nResponse >= 0); + bool bFound = false; + for (auto & child : m_aChildren) { if (child.m_sID == sID) { child.m_nResponseId = nResponse; - return; + bFound = true; + break; } } + if (!m_bLegacy) + { + PushButton* pPushButton = get<PushButton>(sID); + assert(pPushButton); + pPushButton->SetClickHdl(LINK(this, VclBuilder, ResponseHdl)); + } + //how did we not find sID ? - assert(false); + assert(bFound); (void)bFound; } void VclBuilder::delete_by_name(const OString& sID) diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx index 83f9616f5933..b36923871d10 100644 --- a/vcl/source/window/layout.cxx +++ b/vcl/source/window/layout.cxx @@ -2252,7 +2252,8 @@ void MessageDialog::setButtonHandlers(VclButtonBox const *pButtonBox) case WindowType::PUSHBUTTON: { PushButton* pButton = static_cast<PushButton*>(pChild); - pButton->SetClickHdl(LINK(this, MessageDialog, ButtonHdl)); + if (!pButton->GetClickHdl().IsSet()) + pButton->SetClickHdl(LINK(this, MessageDialog, ButtonHdl)); break; } //insist that the response ids match the default actions for those diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 111194255057..0945f881e7e9 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -1851,6 +1851,11 @@ void Window::LoseFocus() CompatNotify( aNEvt ); } +void Window::SetHelpHdl(const Link<vcl::Window&, bool>& rLink) +{ + mpWindowImpl->maHelpRequestHdl = rLink; +} + void Window::RequestHelp( const HelpEvent& rHEvt ) { // if Balloon-Help is requested, show the balloon @@ -1889,7 +1894,7 @@ void Window::RequestHelp( const HelpEvent& rHEvt ) Help::ShowQuickHelp( this, aRect, rStr, aHelpText, QuickHelpFlags::CtrlText ); } } - else + else if (!mpWindowImpl->maHelpRequestHdl.IsSet() || mpWindowImpl->maHelpRequestHdl.Call(*this)) { OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) ); if ( aStrHelpId.isEmpty() && ImplGetParent() ) |