include/vcl/button.hxx | 4 +++ include/vcl/weld.hxx | 9 ++++++++ vcl/inc/salvtables.hxx | 2 + vcl/source/app/salvtables.cxx | 9 ++++++++ vcl/source/control/button.cxx | 24 +++++++++++++++++++++- vcl/unx/gtk3/gtk3gtkinst.cxx | 44 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 1 deletion(-)
New commits: commit 9b12f2fe15403ab0a82abd11ba14dae4a70774a6 Author: Caolán McNamara <[email protected]> AuthorDate: Thu Dec 3 17:15:06 2020 +0000 Commit: Caolán McNamara <[email protected]> CommitDate: Thu Dec 3 21:29:46 2020 +0100 support completely styling a welded button Change-Id: I6e45c711b406a3836dd230ceaa738c5a250ff846 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107173 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> diff --git a/include/vcl/button.hxx b/include/vcl/button.hxx index 627c68192acc..58cb4c1f81fd 100644 --- a/include/vcl/button.hxx +++ b/include/vcl/button.hxx @@ -82,6 +82,10 @@ public: DrawButtonFlags GetButtonState() const; DrawButtonFlags& GetButtonState(); + /// Set an image to use as the complete render view of a custom button, + /// instead of the usual contents of a button + void SetCustomButtonImage( const Image& rImage ); + Image const & GetCustomButtonImage() const; bool IsSmallSymbol() const; void SetSmallSymbol(); diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index a4c07aeebede..98c012378060 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -1296,6 +1296,15 @@ public: // font size is in points, not pixels, e.g. see Window::[G]etPointFont virtual void set_font(const vcl::Font& rFont) = 0; + /* Sometimes, a widget should behave like a button (activate on click, + accept keyboard focus, etc), but look entirely different. + + pDevice, the custom look to use, or nullptr to unset. + + Typically doing this is ill advised. Consider using + set_accessible_name if you do. */ + virtual void set_custom_button(VirtualDevice* pDevice) = 0; + void connect_clicked(const Link<Button&, void>& rLink) { m_aClickHdl = rLink; } }; diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 9fe7a6a5dac5..2fd7198a7b65 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -1007,6 +1007,8 @@ public: virtual void set_font(const vcl::Font& rFont) override; + virtual void set_custom_button(VirtualDevice* pDevice) override; + virtual ~SalInstanceButton() override; }; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 0daf586ebb89..ccc3757e6718 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -2488,6 +2488,15 @@ void SalInstanceButton::set_font(const vcl::Font& rFont) m_xButton->Invalidate(); } +void SalInstanceButton::set_custom_button(VirtualDevice* pDevice) +{ + if (pDevice) + m_xButton->SetCustomButtonImage(createImage(*pDevice)); + else + m_xButton->SetCustomButtonImage(Image()); + m_xButton->Invalidate(); +} + OUString SalInstanceButton::get_label() const { return m_xButton->GetText(); } SalInstanceButton::~SalInstanceButton() { m_xButton->SetClickHdl(Link<::Button*, void>()); } diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx index 66a399c15bbc..38b32d4f54af 100644 --- a/vcl/source/control/button.cxx +++ b/vcl/source/control/button.cxx @@ -83,12 +83,14 @@ public: ImageAlign meImageAlign; SymbolAlign meSymbolAlign; + Image maCustomContentImage; + /** StatusListener. Updates the button as the slot state changes */ rtl::Reference<VclStatusListener<Button>> mpStatusListener; }; ImplCommonButtonData::ImplCommonButtonData() : maFocusRect(), mnSeparatorX(0), mnButtonState(DrawButtonFlags::NONE), -mbSmallSymbol(false), maImage(), meImageAlign(ImageAlign::Top), meSymbolAlign(SymbolAlign::LEFT) +mbSmallSymbol(false), maImage(), meImageAlign(ImageAlign::Top), meSymbolAlign(SymbolAlign::LEFT), maCustomContentImage() { } @@ -158,6 +160,20 @@ ImageAlign Button::GetImageAlign() const return mpButtonData->meImageAlign; } +void Button::SetCustomButtonImage(const Image& rImage) +{ + if (rImage != mpButtonData->maCustomContentImage) + { + mpButtonData->maCustomContentImage = rImage; + StateChanged( StateChangedType::Data ); + } +} + +Image const & Button::GetCustomButtonImage() const +{ + return mpButtonData->maCustomContentImage; +} + tools::Long Button::ImplGetSeparatorX() const { return mpButtonData->mnSeparatorX; @@ -1294,6 +1310,12 @@ void PushButton::FillLayoutData() const void PushButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) { + const Image& rCustomButtonImage = GetCustomButtonImage(); + if (!!rCustomButtonImage) + { + rRenderContext.DrawImage(Point(0, 0), rCustomButtonImage); + return; + } ImplDrawPushButton(rRenderContext); } diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 1863076ddfcf..c4df0cca2855 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -6815,8 +6815,10 @@ class GtkInstanceButton : public GtkInstanceContainer, public virtual weld::Butt { private: GtkButton* m_pButton; + GtkCssProvider* m_pCustomCssProvider; gulong m_nSignalId; std::unique_ptr<vcl::Font> m_xFont; + std::unique_ptr<utl::TempFile> m_xCustomImage; static void signalClicked(GtkButton*, gpointer widget) { @@ -6856,6 +6858,39 @@ private: return pChild; } + // See: https://developer.gnome.org/Buttons/ + void use_custom_content(VirtualDevice* pDevice) + { + GtkStyleContext *pWidgetContext = gtk_widget_get_style_context(GTK_WIDGET(m_pButton)); + + if (m_pCustomCssProvider) + { + gtk_style_context_remove_provider(pWidgetContext, GTK_STYLE_PROVIDER(m_pCustomCssProvider)); + m_pCustomCssProvider = nullptr; + } + + m_xCustomImage.reset(); + + if (!pDevice) + return; + + m_xCustomImage.reset(new utl::TempFile); + m_xCustomImage->EnableKillingFile(true); + + cairo_surface_t* surface = get_underlying_cairo_surface(*pDevice); + Size aSize = pDevice->GetOutputSizePixel(); + cairo_surface_write_to_png(surface, OUStringToOString(m_xCustomImage->GetFileName(), osl_getThreadTextEncoding()).getStr()); + + m_pCustomCssProvider = gtk_css_provider_new(); + OUString aBuffer = "* { background-image: url(\"" + m_xCustomImage->GetURL() + "\"); " + "background-size: " + OUString::number(aSize.Width()) + "px " + OUString::number(aSize.Height()) + "px; " + "border-radius: 0; border-width: 0; }"; + OString aResult = OUStringToOString(aBuffer, RTL_TEXTENCODING_UTF8); + gtk_css_provider_load_from_data(m_pCustomCssProvider, aResult.getStr(), aResult.getLength(), nullptr); + gtk_style_context_add_provider(pWidgetContext, GTK_STYLE_PROVIDER(m_pCustomCssProvider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + protected: GtkWidget* get_label_widget() { @@ -6875,6 +6910,7 @@ public: GtkInstanceButton(GtkButton* pButton, GtkInstanceBuilder* pBuilder, bool bTakeOwnership) : GtkInstanceContainer(GTK_CONTAINER(pButton), pBuilder, bTakeOwnership) , m_pButton(pButton) + , m_pCustomCssProvider(nullptr) , m_nSignalId(g_signal_connect(pButton, "clicked", G_CALLBACK(signalClicked), this)) { g_object_set_data(G_OBJECT(m_pButton), "g-lo-GtkInstanceButton", this); @@ -6919,6 +6955,11 @@ public: } } + virtual void set_custom_button(VirtualDevice* pDevice) override + { + use_custom_content(pDevice); + } + virtual OUString get_label() const override { return ::get_label(m_pButton); @@ -6971,6 +7012,9 @@ public: { g_object_steal_data(G_OBJECT(m_pButton), "g-lo-GtkInstanceButton"); g_signal_handler_disconnect(m_pButton, m_nSignalId); + if (m_pCustomCssProvider) + use_custom_content(nullptr); + assert(!m_pCustomCssProvider); } }; _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
