diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2018-07-25 15:41:14 +0200 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2018-11-08 09:14:28 +0100 |
commit | 7af710953ca8e1b3a1615e3aaa7e02e7697e4599 (patch) | |
tree | ff2f095c220551da872f57436a48e9230fbad8a0 /vcl | |
parent | 89f49fadb8c5cf82cc06f44a8de671290eec53a0 (diff) |
custom widgets: Custom Widget Themes
Change-Id: I7ec57d18fe99f906aeb6dbb40d0d30c2ac8b51c4
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/headless/CustomWidgetDraw.cxx | 176 | ||||
-rw-r--r-- | vcl/inc/WidgetDrawInterface.hxx | 99 | ||||
-rw-r--r-- | vcl/inc/WidgetThemeLibrary.hxx | 35 | ||||
-rw-r--r-- | vcl/inc/headless/CustomWidgetDraw.hxx | 54 | ||||
-rw-r--r-- | vcl/inc/salgdi.hxx | 7 | ||||
-rw-r--r-- | vcl/source/gdi/salgdilayout.cxx | 4 | ||||
-rw-r--r-- | vcl/source/gdi/salnativewidgets-none.cxx | 50 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx | 34 |
9 files changed, 441 insertions, 19 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 1291ee598b56..8fb1e5ec0a6a 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -525,6 +525,7 @@ vcl_headless_code= \ vcl/headless/svpdummies \ vcl/headless/svpinst \ vcl/headless/svpvd \ + vcl/headless/CustomWidgetDraw \ vcl/unx/generic/app/gendisp \ vcl/unx/generic/app/geninst \ vcl/unx/generic/app/gensys \ diff --git a/vcl/headless/CustomWidgetDraw.cxx b/vcl/headless/CustomWidgetDraw.cxx new file mode 100644 index 000000000000..0a8b4086eead --- /dev/null +++ b/vcl/headless/CustomWidgetDraw.cxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <headless/CustomWidgetDraw.hxx> +#include <vcl/salnativewidgets.hxx> +#include <sal/main.h> +#include <sal/config.h> +#include <rtl/bootstrap.hxx> +#include <tools/svlibrary.h> +#include <osl/module.hxx> +#include <cairo.h> + +namespace vcl +{ +WidgetThemeLibrary* CustomWidgetDraw::s_pWidgetImplementation = nullptr; + +CustomWidgetDraw::CustomWidgetDraw(SvpSalGraphics& rGraphics) + : m_rGraphics(rGraphics) +{ + if (!s_pWidgetImplementation) + { + OUString aUrl("${LO_LIB_DIR}/" SVLIBRARY("vcl_widget_theme")); + rtl::Bootstrap::expandMacros(aUrl); + osl::Module aLibrary; + aLibrary.load(aUrl, SAL_LOADMODULE_GLOBAL); + auto fCreateWidgetThemeLibraryFunction + = reinterpret_cast<vcl::WidgetThemeLibrary*(SAL_CALL*)()>( + aLibrary.getFunctionSymbol("CreateWidgetThemeLibrary")); + aLibrary.release(); + + if (fCreateWidgetThemeLibraryFunction) + s_pWidgetImplementation = (*fCreateWidgetThemeLibraryFunction)(); + } +} + +CustomWidgetDraw::~CustomWidgetDraw() {} + +bool CustomWidgetDraw::isNativeControlSupported(ControlType eType, ControlPart /*ePart*/) +{ + switch (eType) + { + case ControlType::Pushbutton: + return true; + default: + break; + } + + return false; +} + +bool CustomWidgetDraw::hitTestNativeControl(ControlType /*eType*/, ControlPart /*ePart*/, + const tools::Rectangle& /*rBoundingControlRegion*/, + const Point& /*aPos*/, bool& /*rIsInside*/) +{ + //printf ("CustomWidgetDraw::hitTestNativeControl\n"); + return false; +} + +bool CustomWidgetDraw::drawNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rControlRegion, + ControlState /*eState*/, + const ImplControlValue& /*aValue*/, + const OUString& /*aCaptions*/) +{ + printf("CustomWidgetDraw::drawNativeControl %d %d\n", sal_Int32(eType), sal_Int32(ePart)); + if (s_pWidgetImplementation == nullptr) + return false; + + switch (eType) + { + case ControlType::Generic: + break; + case ControlType::Pushbutton: + { + printf("drawNativeControl -- ControlType::Pushbutton\n"); + + cairo_t* pCairoContext = m_rGraphics.getCairoContext(false); + m_rGraphics.clipRegion(pCairoContext); + cairo_translate(pCairoContext, rControlRegion.Left(), rControlRegion.Top()); + + long nX = 0; + long nY = 0; + long nWidth = rControlRegion.GetWidth(); + long nHeight = rControlRegion.GetHeight(); + + if (ePart == ControlPart::Focus) + s_pWidgetImplementation->drawPushButtonFocus(pCairoContext, nX, nY, nWidth, + nHeight); + else + s_pWidgetImplementation->drawPushButton(pCairoContext, nX, nY, nWidth, nHeight); + + cairo_destroy(pCairoContext); // unref + + return true; + } + break; + case ControlType::Radiobutton: + break; + case ControlType::Checkbox: + break; + case ControlType::Combobox: + break; + case ControlType::Editbox: + break; + case ControlType::EditboxNoBorder: + break; + case ControlType::MultilineEditbox: + break; + case ControlType::Listbox: + break; + case ControlType::Spinbox: + break; + case ControlType::SpinButtons: + break; + case ControlType::TabItem: + break; + case ControlType::TabPane: + break; + case ControlType::TabHeader: + break; + case ControlType::TabBody: + break; + case ControlType::Scrollbar: + break; + case ControlType::Slider: + break; + case ControlType::Fixedline: + break; + case ControlType::Toolbar: + break; + case ControlType::Menubar: + break; + case ControlType::MenuPopup: + break; + case ControlType::Progress: + break; + case ControlType::IntroProgress: + break; + case ControlType::Tooltip: + break; + case ControlType::WindowBackground: + break; + case ControlType::Frame: + break; + case ControlType::ListNode: + break; + case ControlType::ListNet: + break; + case ControlType::ListHeader: + break; + } + return false; +} + +bool CustomWidgetDraw::getNativeControlRegion(ControlType /*eType*/, ControlPart /*ePart*/, + const tools::Rectangle& /*rBoundingControlRegion*/, + ControlState /*eState*/, + const ImplControlValue& /*aValue*/, + const OUString& /*aCaption*/, + tools::Rectangle& /*rNativeBoundingRegion*/, + tools::Rectangle& /*rNativeContentRegion*/) +{ + //printf ("CustomWidgetDraw::getNativeControlRegion\n"); + return false; +} + +} // end vcl namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/WidgetDrawInterface.hxx b/vcl/inc/WidgetDrawInterface.hxx new file mode 100644 index 000000000000..ce6c5d43babe --- /dev/null +++ b/vcl/inc/WidgetDrawInterface.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_VCL_INC_WIDGETDRAWINTERFACE_HXX +#define INCLUDED_VCL_INC_WIDGETDRAWINTERFACE_HXX + +#include <vcl/dllapi.h> + +namespace vcl +{ +class VCL_PLUGIN_PUBLIC WidgetDrawInterface +{ +public: + virtual ~WidgetDrawInterface() {} + + /** + * Query the platform layer for native control support. + * + * @param [in] eType The widget type. + * @param [in] ePart The part of the widget. + * @return true if the platform supports native drawing of the widget type defined by part. + */ + virtual bool isNativeControlSupported(ControlType eType, ControlPart ePart) = 0; + + /** + * Query if a position is inside the native widget part. + * + * Mainly used for scrollbars. + * + * @param [in] eType The widget type. + * @param [in] ePart The part of the widget. + * @param [in] rBoundingControlRegion The bounding Rectangle of + the complete control in VCL frame coordinates. + * @param [in] aPos The position to check the hit. + * @param [out] rIsInside true, if \a aPos was inside the native widget. + * @return true, if the query was successful. + */ + virtual bool hitTestNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, + const Point& aPos, bool& rIsInside) + = 0; + + /** + * Draw the requested control. + * + * @param [in] eType The widget type. + * @param [in] ePart The part of the widget. + * @param [in] rBoundingControlRegion The bounding rectangle of + * the complete control in VCL frame coordinates. + * @param [in] eState The general state of the control (enabled, focused, etc.). + * @param [in] aValue Addition control specific information. + * @param [in] aCaption A caption or title string (like button text etc.). + * @return true, if the control could be drawn. + */ + virtual bool drawNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, + ControlState eState, const ImplControlValue& aValue, + const OUString& aCaptions) + = 0; + + /** + * Get the native control regions for the control part. + * + * If the return value is true, \a rNativeBoundingRegion contains + * the true bounding region covered by the control including any + * adornment, while \a rNativeContentRegion contains the area + * within the control that can be safely drawn into without drawing over + * the borders of the control. + * + * @param [in] eType Type of the widget. + * @param [in] ePart Specification of the widget's part if it consists of more than one. + * @param [in] rBoundingControlRegion The bounding region of the control in VCL frame coordinates. + * @param [in] eState The general state of the control (enabled, focused, etc.). + * @param [in] aValue Addition control specific information. + * @param [in] aCaption A caption or title string (like button text etc.). + * @param [out] rNativeBoundingRegion The region covered by the control including any adornment. + * @param [out] rNativeContentRegion The region within the control that can be safely drawn into. + * @return true, if the regions are filled. + */ + virtual bool getNativeControlRegion(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, + ControlState eState, const ImplControlValue& aValue, + const OUString& aCaption, + tools::Rectangle& rNativeBoundingRegion, + tools::Rectangle& rNativeContentRegion) + = 0; +}; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/WidgetThemeLibrary.hxx b/vcl/inc/WidgetThemeLibrary.hxx new file mode 100644 index 000000000000..18afbc9c50fa --- /dev/null +++ b/vcl/inc/WidgetThemeLibrary.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_VCL_INC_WIDGETTHEME_HXX +#define INCLUDED_VCL_INC_WIDGETTHEME_HXX + +#include <cairo.h> +#include <vcl/dllapi.h> + +namespace vcl +{ +class SAL_DLLPUBLIC_RTTI WidgetThemeLibrary +{ +public: + WidgetThemeLibrary(); + virtual ~WidgetThemeLibrary(); + + virtual bool drawPushButtonFocus(cairo_t* pCairo, long nX, long nY, long nWidth, long nHeight); + virtual bool drawPushButton(cairo_t* pCairo, long nX, long nY, long nWidth, long nHeight); +}; + +extern "C" vcl::WidgetThemeLibrary* CreateWidgetThemeLibrary(); + +} // end vcl namespace + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/headless/CustomWidgetDraw.hxx b/vcl/inc/headless/CustomWidgetDraw.hxx new file mode 100644 index 000000000000..ce749ac15b63 --- /dev/null +++ b/vcl/inc/headless/CustomWidgetDraw.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_VCL_INC_CUSTOMWIDGETDRAW_HXX +#define INCLUDED_VCL_INC_CUSTOMWIDGETDRAW_HXX + +#include <vcl/dllapi.h> +#include <vcl/salnativewidgets.hxx> +#include <WidgetDrawInterface.hxx> +#include <WidgetThemeLibrary.hxx> +#include <headless/svpgdi.hxx> +#include <memory> + +namespace vcl +{ +class VCL_DLLPUBLIC CustomWidgetDraw : public vcl::WidgetDrawInterface +{ +private: + static WidgetThemeLibrary* s_pWidgetImplementation; + SvpSalGraphics& m_rGraphics; + +public: + CustomWidgetDraw(SvpSalGraphics& rGraphics); + virtual ~CustomWidgetDraw(); + + bool isNativeControlSupported(ControlType eType, ControlPart ePart) override; + + bool hitTestNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, const Point& aPos, + bool& rIsInside) override; + + bool drawNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, ControlState eState, + const ImplControlValue& aValue, const OUString& aCaptions) override; + + bool getNativeControlRegion(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, ControlState eState, + const ImplControlValue& aValue, const OUString& aCaption, + tools::Rectangle& rNativeBoundingRegion, + tools::Rectangle& rNativeContentRegion) override; +}; + +} // end vcl namespace + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx index 32b51f6630d9..557447da2e38 100644 --- a/vcl/inc/salgdi.hxx +++ b/vcl/inc/salgdi.hxx @@ -25,6 +25,7 @@ #include "impfontmetricdata.hxx" #include "salgdiimpl.hxx" #include "sallayout.hxx" +#include <WidgetDrawInterface.hxx> #include <config_cairo_canvas.h> @@ -648,6 +649,12 @@ protected: /// flags which hold the SetAntialiasing() value from OutputDevice bool m_bAntiAliasB2DDraw : 1; + bool hasWidgetDraw() + { + return bool(m_pWidgetDraw); + } + + std::unique_ptr<vcl::WidgetDrawInterface> m_pWidgetDraw; }; #endif // INCLUDED_VCL_INC_SALGDI_HXX diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx index 732a7181cf2b..18b05f19da37 100644 --- a/vcl/source/gdi/salgdilayout.cxx +++ b/vcl/source/gdi/salgdilayout.cxx @@ -49,8 +49,8 @@ SalFrameGeometry SalFrame::GetGeometry() } SalGraphics::SalGraphics() -: m_nLayout( SalLayoutFlags::NONE ), - m_bAntiAliasB2DDraw(false) + : m_nLayout(SalLayoutFlags::NONE) + , m_bAntiAliasB2DDraw(false) { // read global RTL settings if( AllSettings::GetLayoutRTL() ) diff --git a/vcl/source/gdi/salnativewidgets-none.cxx b/vcl/source/gdi/salnativewidgets-none.cxx index 6de0ace197c7..2f8051e7e1c2 100644 --- a/vcl/source/gdi/salnativewidgets-none.cxx +++ b/vcl/source/gdi/salnativewidgets-none.cxx @@ -19,33 +19,55 @@ #include <salgdi.hxx> -/**************************************************************** - * Placeholder for no native widgets - ***************************************************************/ - -bool SalGraphics::IsNativeControlSupported( ControlType, ControlPart ) +bool SalGraphics::IsNativeControlSupported(ControlType eType, ControlPart ePart) { + if (hasWidgetDraw()) + return m_pWidgetDraw->isNativeControlSupported(eType, ePart); + return false; } -bool SalGraphics::hitTestNativeControl( ControlType, ControlPart, - const tools::Rectangle&, const Point&, bool& ) +bool SalGraphics::hitTestNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, + const Point& rPosition, bool& rIsInside) { + if (hasWidgetDraw()) + { + return m_pWidgetDraw->hitTestNativeControl(eType, ePart, rBoundingControlRegion, rPosition, rIsInside); + } + return false; } -bool SalGraphics::drawNativeControl( ControlType, ControlPart, - const tools::Rectangle&, ControlState, - const ImplControlValue&, const OUString& ) +bool SalGraphics::drawNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, + ControlState eState, const ImplControlValue& aValue, + const OUString& aCaptions) { + if (hasWidgetDraw()) + { + return m_pWidgetDraw->drawNativeControl(eType, ePart, rBoundingControlRegion, + eState, aValue, aCaptions); + } + return false; } -bool SalGraphics::getNativeControlRegion( ControlType, ControlPart, - const tools::Rectangle&, ControlState, - const ImplControlValue&, - const OUString&, tools::Rectangle&, tools::Rectangle& ) +bool SalGraphics::getNativeControlRegion(ControlType eType, ControlPart ePart, + const tools::Rectangle& rBoundingControlRegion, + ControlState eState, + const ImplControlValue& aValue, + const OUString& aCaption, + tools::Rectangle& rNativeBoundingRegion, + tools::Rectangle& rNativeContentRegion) { + if (hasWidgetDraw()) + { + return m_pWidgetDraw->getNativeControlRegion(eType, ePart, rBoundingControlRegion, + eState, aValue, aCaption, + rNativeBoundingRegion, rNativeContentRegion); + } + return false; } diff --git a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx index f37ed7cb93dd..bd70ea6e86a8 100644 --- a/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk3/gtk3salnativewidgets-gtk.cxx @@ -19,6 +19,8 @@ #include <vcl/decoview.hxx> #include <vcl/settings.hxx> #include <unx/fontmanager.hxx> +#include <headless/CustomWidgetDraw.hxx> + #include "cairo_gtk3_cairo.hxx" #if defined(GDK_WINDOWING_WAYLAND) # include <gdk/gdkwayland.h> @@ -2174,8 +2176,19 @@ static gfloat getArrowSize(GtkStyleContext* context) bool GtkSalGraphics::drawNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState nState, const ImplControlValue& rValue, - const OUString& ) + const OUString& aCaptions) { + if (m_pWidgetDraw) + { + bool bReturn = m_pWidgetDraw->drawNativeControl(nType, nPart, rControlRegion, + nState, rValue, aCaptions); + + if (bReturn && !rControlRegion.IsEmpty()) + mpFrame->damaged(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight()); + + return bReturn; + } + RenderType renderType = nPart == ControlPart::Focus ? RenderType::Focus : RenderType::BackgroundAndFrame; GtkStyleContext *context = nullptr; const gchar *styleClass = nullptr; @@ -2606,10 +2619,17 @@ tools::Rectangle AdjustRectForTextBordersPadding(GtkStyleContext* pStyle, long n return aEditRect; } -bool GtkSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState, - const ImplControlValue& rValue, const OUString&, +bool GtkSalGraphics::getNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState eState, + const ImplControlValue& rValue, const OUString& aCaption, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion ) { + if (hasWidgetDraw()) + { + return m_pWidgetDraw->getNativeControlRegion(nType, nPart, rControlRegion, + eState, rValue, aCaption, + rNativeBoundingRegion, rNativeContentRegion); + } + /* TODO: all this functions needs improvements */ tools::Rectangle aEditRect = rControlRegion; gint indicator_size, indicator_spacing, point; @@ -3168,6 +3188,11 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings ) bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) { + if (m_pWidgetDraw) + { + return m_pWidgetDraw->isNativeControlSupported(nType, nPart); + } + switch(nType) { case ControlType::Pushbutton: @@ -3344,6 +3369,9 @@ GtkSalGraphics::GtkSalGraphics( GtkSalFrame *pFrame, GtkWidget *pWindow ) mpFrame( pFrame ), mpWindow( pWindow ) { + /* Set Custom Widget Draw*/ + m_pWidgetDraw.reset(new vcl::CustomWidgetDraw(*this)); + if (style_loaded) return; |