diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2019-01-22 21:24:15 +0100 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2019-03-04 12:29:29 +0100 |
commit | fd23d1ed012549907f21720c5aa8b169497ef952 (patch) | |
tree | 1000207a197127d9b704f8925bccdae0c1318624 | |
parent | Add definition.xml to share LO folder (theme_definitions subfolder) (diff) | |
download | core-fd23d1ed012549907f21720c5aa8b169497ef952.tar.gz core-fd23d1ed012549907f21720c5aa8b169497ef952.zip |
Draw basic PushButton from the theme definition
Change-Id: Iee130a48a5ea671962d15d84ec56ac2f16227749
Reviewed-on: https://gerrit.libreoffice.org/68652
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | vcl/inc/widgetdraw/WidgetDefinitionReader.hxx | 77 | ||||
-rw-r--r-- | vcl/source/gdi/FileDefinitionWidgetDraw.cxx | 145 | ||||
-rw-r--r-- | vcl/source/gdi/WidgetDefinitionReader.cxx | 242 | ||||
-rw-r--r-- | vcl/uiconfig/theme_definitions/definition.xml | 15 |
4 files changed, 470 insertions, 9 deletions
diff --git a/vcl/inc/widgetdraw/WidgetDefinitionReader.hxx b/vcl/inc/widgetdraw/WidgetDefinitionReader.hxx index 350696a87dae..a5d8661304ea 100644 --- a/vcl/inc/widgetdraw/WidgetDefinitionReader.hxx +++ b/vcl/inc/widgetdraw/WidgetDefinitionReader.hxx @@ -15,14 +15,87 @@ #include <memory> #include <rtl/ustring.hxx> #include <tools/color.hxx> +#include <tools/XmlWalker.hxx> +#include <unordered_map> +#include <vector> +#include <vcl/salnativewidgets.hxx> namespace vcl { +enum class DrawCommandType +{ + RECTANGLE +}; + +class VCL_DLLPUBLIC DrawCommand +{ +public: + DrawCommand(DrawCommandType aType) + : maType(aType) + , mnStrokeWidth(-1) + , mnMargin(0) + { + } + + DrawCommandType maType; + + Color maStrokeColor; + Color maFillColor; + sal_Int32 mnStrokeWidth; + sal_Int32 mnMargin; +}; + +class VCL_DLLPUBLIC RectangleDrawCommand : public DrawCommand +{ +public: + sal_Int32 mnRx; + sal_Int32 mnRy; + + RectangleDrawCommand() + : DrawCommand(DrawCommandType::RECTANGLE) + , mnRx(0) + , mnRy(0) + { + } +}; + +class VCL_DLLPUBLIC WidgetDefinitionState +{ +public: + OString msEnabled; + OString msFocused; + OString msPressed; + OString msRollover; + OString msDefault; + OString msSelected; + + WidgetDefinitionState(OString const& sEnabled, OString const& sFocused, OString const& sPressed, + OString const& sRollover, OString const& sDefault, + OString const& sSelected); + + std::vector<std::shared_ptr<DrawCommand>> mpDrawCommands; + + void addDrawRectangle(Color aStrokeColor, sal_Int32 nStrokeWidth, Color aFillColor, + sal_Int32 nRx, sal_Int32 nRy, sal_Int32 nMargin); +}; + +class VCL_DLLPUBLIC WidgetDefinition +{ +public: + std::vector<std::shared_ptr<WidgetDefinitionState>> getStates(ControlState eState); + + std::vector<std::shared_ptr<WidgetDefinitionState>> maStates; +}; + class VCL_DLLPUBLIC WidgetDefinitionReader { private: OUString m_rFilePath; + void readPushButton(tools::XmlWalker& rWalker); + static void readDrawingDefinition(tools::XmlWalker& rWalker, + std::shared_ptr<WidgetDefinitionState>& rStates); + public: Color maFaceColor; Color maCheckedColor; @@ -75,6 +148,10 @@ public: Color maToolTextColor; Color maFontColor; + std::unordered_map<OString, std::shared_ptr<WidgetDefinition>> maPushButtonDefinitions; + + std::shared_ptr<WidgetDefinition> getPushButtonDefinition(ControlPart ePart); + WidgetDefinitionReader(OUString const& rFilePath); bool read(); }; diff --git a/vcl/source/gdi/FileDefinitionWidgetDraw.cxx b/vcl/source/gdi/FileDefinitionWidgetDraw.cxx index d9ffc93e92ad..7b493c507b26 100644 --- a/vcl/source/gdi/FileDefinitionWidgetDraw.cxx +++ b/vcl/source/gdi/FileDefinitionWidgetDraw.cxx @@ -39,9 +39,43 @@ FileDefinitionWidgetDraw::FileDefinitionWidgetDraw(SalGraphics& rGraphics) pSVData->maNWFData.mbNoFocusRectsForFlatButtons = true; } -bool FileDefinitionWidgetDraw::isNativeControlSupported(ControlType /*eType*/, - ControlPart /*ePart*/) +bool FileDefinitionWidgetDraw::isNativeControlSupported(ControlType eType, ControlPart /*ePart*/) { + switch (eType) + { + case ControlType::Generic: + case ControlType::Pushbutton: + return true; + case ControlType::Radiobutton: + case ControlType::Checkbox: + case ControlType::Combobox: + case ControlType::Editbox: + case ControlType::EditboxNoBorder: + case ControlType::MultilineEditbox: + case ControlType::Listbox: + case ControlType::Spinbox: + case ControlType::SpinButtons: + case ControlType::TabItem: + case ControlType::TabPane: + case ControlType::TabHeader: + case ControlType::TabBody: + case ControlType::Scrollbar: + case ControlType::Slider: + case ControlType::Fixedline: + case ControlType::Toolbar: + case ControlType::Menubar: + case ControlType::MenuPopup: + case ControlType::Progress: + case ControlType::IntroProgress: + case ControlType::Tooltip: + case ControlType::WindowBackground: + case ControlType::Frame: + case ControlType::ListNode: + case ControlType::ListNet: + case ControlType::ListHeader: + return false; + } + return false; } @@ -52,14 +86,111 @@ bool FileDefinitionWidgetDraw::hitTestNativeControl( return false; } -bool FileDefinitionWidgetDraw::drawNativeControl(ControlType /*eType*/, ControlPart /*ePart*/, - const tools::Rectangle& /*rControlRegion*/, - ControlState /*eState*/, +namespace +{ +void munchDrawCommands(std::vector<std::shared_ptr<DrawCommand>> const& rDrawCommands, + SalGraphics& rGraphics, long nX, long nY, long nWidth, long nHeight) +{ + for (std::shared_ptr<DrawCommand> const& pDrawCommand : rDrawCommands) + { + switch (pDrawCommand->maType) + { + case DrawCommandType::RECTANGLE: + { + auto const& rRectDrawCommand + = static_cast<RectangleDrawCommand const&>(*pDrawCommand); + Point aRectPoint(nX, nY); + Size aRectSize(nWidth - 1, nHeight - 1); + tools::Polygon aPolygon(tools::Rectangle(aRectPoint, aRectSize), + rRectDrawCommand.mnRx, rRectDrawCommand.mnRy); + + basegfx::B2DPolygon aB2DPolygon(aPolygon.getB2DPolygon()); + rGraphics.SetLineColor(rRectDrawCommand.maStrokeColor); + rGraphics.SetFillColor(rRectDrawCommand.maFillColor); + rGraphics.DrawPolyPolygon(basegfx::B2DHomMatrix(), + basegfx::B2DPolyPolygon(aB2DPolygon), 0.0f, nullptr); + } + break; + } + } +} + +} // end anonymous namespace + +bool FileDefinitionWidgetDraw::drawNativeControl(ControlType eType, ControlPart ePart, + const tools::Rectangle& rControlRegion, + ControlState eState, const ImplControlValue& /*rValue*/, const OUString& /*aCaptions*/) { - (void)m_rGraphics; // avoid unused warning - return false; + bool bOldAA = m_rGraphics.getAntiAliasB2DDraw(); + m_rGraphics.setAntiAliasB2DDraw(true); + + long nWidth = rControlRegion.GetWidth(); + long nHeight = rControlRegion.GetHeight(); + long nX = rControlRegion.Left() + 1; + long nY = rControlRegion.Top() + 1; + + bool bOK = false; + + switch (eType) + { + case ControlType::Generic: + { + } + break; + case ControlType::Pushbutton: + { + std::shared_ptr<WidgetDefinition> pDefinition + = m_WidgetDefinitionReader.getPushButtonDefinition(ePart); + if (pDefinition) + { + std::shared_ptr<WidgetDefinitionState> pState + = pDefinition->getStates(eState).back(); + { + munchDrawCommands(pState->mpDrawCommands, m_rGraphics, nX, nY, nWidth, nHeight); + bOK = true; + } + } + } + break; + case ControlType::Radiobutton: + case ControlType::Checkbox: + case ControlType::Combobox: + case ControlType::Editbox: + case ControlType::EditboxNoBorder: + case ControlType::MultilineEditbox: + case ControlType::Listbox: + case ControlType::Spinbox: + case ControlType::SpinButtons: + case ControlType::TabItem: + case ControlType::TabPane: + case ControlType::TabBody: + case ControlType::Scrollbar: + case ControlType::Slider: + case ControlType::Fixedline: + case ControlType::Toolbar: + case ControlType::Menubar: + break; + case ControlType::MenuPopup: + break; + case ControlType::Progress: + case ControlType::IntroProgress: + break; + case ControlType::Tooltip: + break; + case ControlType::WindowBackground: + case ControlType::Frame: + case ControlType::ListNode: + case ControlType::ListNet: + case ControlType::ListHeader: + default: + break; + } + + m_rGraphics.setAntiAliasB2DDraw(bOldAA); + + return bOK; } bool FileDefinitionWidgetDraw::getNativeControlRegion( diff --git a/vcl/source/gdi/WidgetDefinitionReader.cxx b/vcl/source/gdi/WidgetDefinitionReader.cxx index 1bb7acb37eeb..0d78522abfd2 100644 --- a/vcl/source/gdi/WidgetDefinitionReader.cxx +++ b/vcl/source/gdi/WidgetDefinitionReader.cxx @@ -13,7 +13,6 @@ #include <sal/config.h> #include <osl/file.hxx> #include <tools/stream.hxx> -#include <tools/XmlWalker.hxx> #include <unordered_map> namespace vcl @@ -63,6 +62,82 @@ WidgetDefinitionReader::WidgetDefinitionReader(OUString const& rFilePath) { } +void WidgetDefinitionReader::readDrawingDefinition(tools::XmlWalker& rWalker, + std::shared_ptr<WidgetDefinitionState>& rpState) +{ + rWalker.children(); + while (rWalker.isValid()) + { + if (rWalker.name() == "rect") + { + Color aStrokeColor; + readColor(rWalker.attribute("stroke"), aStrokeColor); + Color aFillColor; + readColor(rWalker.attribute("fill"), aFillColor); + OString sStrokeWidth = rWalker.attribute("stroke-width"); + sal_Int32 nStrokeWidth = -1; + if (!sStrokeWidth.isEmpty()) + nStrokeWidth = sStrokeWidth.toInt32(); + + sal_Int32 nRx = -1; + OString sRx = rWalker.attribute("rx"); + if (!sRx.isEmpty()) + nRx = sRx.toInt32(); + + sal_Int32 nRy = -1; + OString sRy = rWalker.attribute("ry"); + if (!sRy.isEmpty()) + nRy = sRy.toInt32(); + + sal_Int32 nMargin = 0; + OString sMargin = rWalker.attribute("margin"); + if (!sMargin.isEmpty()) + nMargin = sMargin.toInt32(); + + rpState->addDrawRectangle(aStrokeColor, nStrokeWidth, aFillColor, nRx, nRy, nMargin); + } + rWalker.next(); + } + rWalker.parent(); +} + +void WidgetDefinitionReader::readPushButton(tools::XmlWalker& rWalker) +{ + rWalker.children(); + while (rWalker.isValid()) + { + if (rWalker.name() == "part") + { + OString sPart = rWalker.attribute("value"); + std::shared_ptr<WidgetDefinition> pPart = std::make_shared<WidgetDefinition>(); + maPushButtonDefinitions.emplace(sPart, pPart); + rWalker.children(); + while (rWalker.isValid()) + { + if (rWalker.name() == "state") + { + OString sEnabled = rWalker.attribute("enabled"); + OString sFocused = rWalker.attribute("focused"); + OString sPressed = rWalker.attribute("pressed"); + OString sRollover = rWalker.attribute("rollover"); + OString sDefault = rWalker.attribute("default"); + OString sSelected = rWalker.attribute("selected"); + + std::shared_ptr<WidgetDefinitionState> pState + = std::make_shared<WidgetDefinitionState>(sEnabled, sFocused, sPressed, + sRollover, sDefault, sSelected); + pPart->maStates.push_back(pState); + readDrawingDefinition(rWalker, pState); + } + rWalker.next(); + } + rWalker.parent(); + } + rWalker.next(); + } + rWalker.parent(); +} + bool WidgetDefinitionReader::read() { if (!lcl_fileExists(m_rFilePath)) @@ -147,6 +222,10 @@ bool WidgetDefinitionReader::read() } aWalker.parent(); } + else if (aWalker.name() == "pushbutton") + { + readPushButton(aWalker); + } aWalker.next(); } aWalker.parent(); @@ -154,6 +233,167 @@ bool WidgetDefinitionReader::read() return true; } +namespace +{ +OString xmlControlPart(ControlPart ePart) +{ + switch (ePart) + { + case ControlPart::NONE: + return "NONE"; + case ControlPart::Entire: + return "Entire"; + case ControlPart::ListboxWindow: + return "ListboxWindow"; + case ControlPart::Button: + return "NONE"; + case ControlPart::ButtonUp: + return "NONE"; + case ControlPart::ButtonDown: + return "NONE"; + case ControlPart::ButtonLeft: + return "NONE"; + case ControlPart::ButtonRight: + return "NONE"; + case ControlPart::AllButtons: + return "NONE"; + case ControlPart::SeparatorHorz: + return "NONE"; + case ControlPart::SeparatorVert: + return "NONE"; + case ControlPart::TrackHorzLeft: + return "NONE"; + case ControlPart::TrackVertUpper: + return "NONE"; + case ControlPart::TrackHorzRight: + return "NONE"; + case ControlPart::TrackVertLower: + return "NONE"; + case ControlPart::TrackHorzArea: + return "NONE"; + case ControlPart::TrackVertArea: + return "NONE"; + case ControlPart::Arrow: + return "NONE"; + case ControlPart::ThumbHorz: + return "NONE"; + case ControlPart::ThumbVert: + return "NONE"; + case ControlPart::MenuItem: + return "NONE"; + case ControlPart::MenuItemCheckMark: + return "NONE"; + case ControlPart::MenuItemRadioMark: + return "NONE"; + case ControlPart::Separator: + return "NONE"; + case ControlPart::SubmenuArrow: + return "NONE"; + case ControlPart::SubEdit: + return "NONE"; + case ControlPart::DrawBackgroundHorz: + return "NONE"; + case ControlPart::DrawBackgroundVert: + return "NONE"; + case ControlPart::TabsDrawRtl: + return "NONE"; + case ControlPart::HasBackgroundTexture: + return "NONE"; + case ControlPart::HasThreeButtons: + return "NONE"; + case ControlPart::BackgroundWindow: + return "NONE"; + case ControlPart::BackgroundDialog: + return "NONE"; + case ControlPart::Border: + return "NONE"; + case ControlPart::Focus: + return "FOCUS"; + + default: + break; + } + return "NONE"; +} + +} // end anonymous namespace + +std::shared_ptr<WidgetDefinition> WidgetDefinitionReader::getPushButtonDefinition(ControlPart ePart) +{ + auto aIterator = maPushButtonDefinitions.find(xmlControlPart(ePart)); + + if (aIterator != maPushButtonDefinitions.end()) + return aIterator->second; + return std::shared_ptr<WidgetDefinition>(); +} + +std::vector<std::shared_ptr<WidgetDefinitionState>> WidgetDefinition::getStates(ControlState eState) +{ + std::vector<std::shared_ptr<WidgetDefinitionState>> aStatesToAdd; + + for (auto& state : maStates) + { + bool bAdd = true; + + if (state->msEnabled != "any" + && !((state->msEnabled == "true" && eState & ControlState::ENABLED) + || (state->msEnabled == "false" && !(eState & ControlState::ENABLED)))) + bAdd = false; + if (state->msFocused != "any" + && !((state->msFocused == "true" && eState & ControlState::FOCUSED) + || (state->msFocused == "false" && !(eState & ControlState::FOCUSED)))) + bAdd = false; + if (state->msPressed != "any" + && !((state->msPressed == "true" && eState & ControlState::PRESSED) + || (state->msPressed == "false" && !(eState & ControlState::PRESSED)))) + bAdd = false; + if (state->msRollover != "any" + && !((state->msRollover == "true" && eState & ControlState::ROLLOVER) + || (state->msRollover == "false" && !(eState & ControlState::ROLLOVER)))) + bAdd = false; + if (state->msDefault != "any" + && !((state->msDefault == "true" && eState & ControlState::DEFAULT) + || (state->msDefault == "false" && !(eState & ControlState::DEFAULT)))) + bAdd = false; + if (state->msSelected != "any" + && !((state->msSelected == "true" && eState & ControlState::SELECTED) + || (state->msSelected == "false" && !(eState & ControlState::SELECTED)))) + bAdd = false; + + if (bAdd) + aStatesToAdd.push_back(state); + } + + return aStatesToAdd; +} + +WidgetDefinitionState::WidgetDefinitionState(OString const& sEnabled, OString const& sFocused, + OString const& sPressed, OString const& sRollover, + OString const& sDefault, OString const& sSelected) + : msEnabled(sEnabled) + , msFocused(sFocused) + , msPressed(sPressed) + , msRollover(sRollover) + , msDefault(sDefault) + , msSelected(sSelected) +{ +} + +void WidgetDefinitionState::addDrawRectangle(Color aStrokeColor, sal_Int32 nStrokeWidth, + Color aFillColor, sal_Int32 nRx, sal_Int32 nRy, + sal_Int32 nMargin) +{ + std::shared_ptr<DrawCommand> pCommand(std::make_shared<RectangleDrawCommand>()); + pCommand->maStrokeColor = aStrokeColor; + pCommand->maFillColor = aFillColor; + pCommand->mnStrokeWidth = nStrokeWidth; + pCommand->mnMargin = nMargin; + RectangleDrawCommand& rRectCommand = static_cast<RectangleDrawCommand&>(*pCommand); + rRectCommand.mnRx = nRx; + rRectCommand.mnRy = nRy; + mpDrawCommands.push_back(pCommand); +} + } // end vcl namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/uiconfig/theme_definitions/definition.xml b/vcl/uiconfig/theme_definitions/definition.xml index d19db6043a7c..dbf87fddd6ba 100644 --- a/vcl/uiconfig/theme_definitions/definition.xml +++ b/vcl/uiconfig/theme_definitions/definition.xml @@ -1,4 +1,4 @@ - <?xml version="1.0" encoding="UTF-8"?> +<?xml version="1.0" encoding="UTF-8"?> <widgets> <style> @@ -53,4 +53,17 @@ <toolTextColor value="#000000"/> <fontColor value="#000000"/> </style> + + <pushbutton> + <part value="Entire"> + <state enabled="any" focused="any" pressed="any" rollover="any" default="any" selected="any"> + <rect stroke="#007AFF" fill="#FFFFFF" stroke-width="1" rx="5" ry="5" margin="0"/> + </state> + + <state enabled="true" focused="any" pressed="any" rollover="true" default="any" selected="any"> + <rect stroke="#007AFF" fill="#007AFF" stroke-width="1" rx="5" ry="5" margin="0"/> + </state> + </part> + </pushbutton> + </widgets> |