chart2/Library_chartcontroller.mk | 2 chart2/Library_chartcore.mk | 4 chart2/UIConfig_chart2.mk | 2 chart2/inc/ChartModel.hxx | 22 chart2/source/controller/chartcontroller.component | 4 chart2/source/controller/sidebar/Chart2PanelFactory.cxx | 3 chart2/source/controller/sidebar/ChartAreaPanel.cxx | 11 chart2/source/controller/sidebar/ChartAreaPanel.hxx | 1 chart2/source/controller/sidebar/ChartColorPaletteControl.cxx | 353 ++++++++++ chart2/source/controller/sidebar/ChartColorPaletteControl.hxx | 94 ++ chart2/source/controller/sidebar/ChartColorWrapper.cxx | 5 chart2/source/controller/sidebar/ChartColorsPanel.cxx | 295 ++++++++ chart2/source/controller/sidebar/ChartColorsPanel.hxx | 87 ++ chart2/source/inc/BaseColorScheme.hxx | 44 + chart2/source/inc/ChartColorPaletteHelper.hxx | 48 + chart2/source/inc/ChartColorPalettes.hxx | 38 + chart2/source/inc/ChartColorScheme.hxx | 40 + chart2/source/inc/ConfigColorScheme.hxx | 23 chart2/source/model/main/ChartModel.cxx | 143 ++++ chart2/source/tools/BaseColorScheme.cxx | 43 + chart2/source/tools/ChartColorPaletteHelper.cxx | 199 +++++ chart2/source/tools/ChartColorPalettes.cxx | 59 + chart2/source/tools/ChartColorScheme.cxx | 51 + chart2/source/tools/ConfigColorScheme.cxx | 12 chart2/source/view/main/SeriesPlotterContainer.cxx | 8 chart2/uiconfig/ui/chartcolorpalettepopup.ui | 130 +++ chart2/uiconfig/ui/sidebarcolors.ui | 58 + include/svl/hint.hxx | 2 include/svx/ChartColorPaletteType.hxx | 36 + officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu | 11 officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu | 30 sc/source/ui/theme/ThemeColorChanger.cxx | 2 sd/source/core/ThemeColorChanger.cxx | 2 sd/source/ui/unoidl/unomodel.cxx | 3 static/CustomTarget_emscripten_fs_image.mk | 2 sw/source/core/model/ThemeColorChanger.cxx | 2 vcl/jsdialog/enabled.cxx | 4 37 files changed, 1844 insertions(+), 29 deletions(-)
New commits: commit 2645d348cfa9127e8747ef6ef1cf6c02f6d71272 Author: Marco Cecchetti <marco.cecche...@collabora.com> AuthorDate: Sun Apr 13 18:36:05 2025 +0200 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Thu May 1 07:32:22 2025 +0200 chart color palette for data series: sidebar panel Change-Id: I6f661515e2de11ea1ead0b79435413d6a0e81c9d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184264 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/chart2/Library_chartcontroller.mk b/chart2/Library_chartcontroller.mk index b2d05298c237..ab3249e36e76 100644 --- a/chart2/Library_chartcontroller.mk +++ b/chart2/Library_chartcontroller.mk @@ -198,6 +198,8 @@ $(eval $(call gb_Library_add_exception_objects,chartcontroller,\ chart2/source/controller/main/UndoGuard \ chart2/source/controller/sidebar/Chart2PanelFactory \ chart2/source/controller/sidebar/ChartAreaPanel \ + chart2/source/controller/sidebar/ChartColorsPanel \ + chart2/source/controller/sidebar/ChartColorPaletteControl \ chart2/source/controller/sidebar/ChartAxisPanel \ chart2/source/controller/sidebar/ChartColorWrapper \ chart2/source/controller/sidebar/ChartElementsPanel \ diff --git a/chart2/Library_chartcore.mk b/chart2/Library_chartcore.mk index ad204c1ef094..236cb07aabf8 100644 --- a/chart2/Library_chartcore.mk +++ b/chart2/Library_chartcore.mk @@ -177,9 +177,13 @@ $(eval $(call gb_Library_add_exception_objects,chartcore,\ # tools pieces $(eval $(call gb_Library_add_exception_objects,chartcore,\ chart2/source/tools/AxisHelper \ + chart2/source/tools/BaseColorScheme \ chart2/source/tools/BaseGFXHelper \ chart2/source/tools/CachedDataSequence \ chart2/source/tools/CharacterProperties \ + chart2/source/tools/ChartColorPalettes \ + chart2/source/tools/ChartColorPaletteHelper \ + chart2/source/tools/ChartColorScheme \ chart2/source/tools/ChartModelHelper \ chart2/source/tools/ChartTypeHelper \ chart2/source/tools/ChartViewHelper \ diff --git a/chart2/UIConfig_chart2.mk b/chart2/UIConfig_chart2.mk index 274efd02638f..93d8db3154d9 100644 --- a/chart2/UIConfig_chart2.mk +++ b/chart2/UIConfig_chart2.mk @@ -37,6 +37,7 @@ $(eval $(call gb_UIConfig_add_toolbarfiles,modules/schart,\ $(eval $(call gb_UIConfig_add_uifiles,modules/schart,\ chart2/uiconfig/ui/3dviewdialog \ chart2/uiconfig/ui/attributedialog \ + chart2/uiconfig/ui/chartcolorpalettepopup \ chart2/uiconfig/ui/chardialog \ chart2/uiconfig/ui/chartdatadialog \ chart2/uiconfig/ui/charttypedialog \ @@ -53,6 +54,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/schart,\ chart2/uiconfig/ui/inserttitledlg \ chart2/uiconfig/ui/paradialog \ chart2/uiconfig/ui/sidebaraxis \ + chart2/uiconfig/ui/sidebarcolors \ chart2/uiconfig/ui/sidebarelements \ chart2/uiconfig/ui/sidebarerrorbar \ chart2/uiconfig/ui/sidebarseries \ diff --git a/chart2/inc/ChartModel.hxx b/chart2/inc/ChartModel.hxx index 911fcc4e409f..19c91645a008 100644 --- a/chart2/inc/ChartModel.hxx +++ b/chart2/inc/ChartModel.hxx @@ -52,6 +52,8 @@ #include <cppuhelper/implbase.hxx> #include <comphelper/interfacecontainer2.hxx> #include <vcl/GraphicObject.hxx> +#include <svl/lstner.hxx> +#include <svx/ChartColorPaletteType.hxx> #include <memory> @@ -68,6 +70,8 @@ namespace com::sun::star::uno { class XAggregation; } class SvNumberFormatter; class SvNumberFormatsSupplierObj; +namespace model { class Theme; } + namespace chart { class Diagram; @@ -116,7 +120,7 @@ class UndoManager; class ChartView; class UNLESS_MERGELIBS(OOO_DLLPUBLIC_CHARTTOOLS) SAL_LOPLUGIN_ANNOTATE("crosscast") ChartModel final : - public impl::ChartModel_Base + public impl::ChartModel_Base, private SfxListener { private: @@ -175,6 +179,9 @@ private: rtl::Reference< ::chart::NameContainer > m_xXMLNamespaceMap; + ChartColorPaletteType m_eColorPaletteType; + sal_uInt32 m_nColorPaletteIndex; + private: //private methods @@ -456,6 +463,9 @@ public: // XDumper virtual OUString SAL_CALL dump(OUString const & kind) override; + // SfxListener + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; + // normal methods css::uno::Reference< css::util::XNumberFormatsSupplier > const & getNumberFormatsSupplier(); @@ -479,6 +489,16 @@ public: rtl::Reference< ::chart::Title > getTitleObject2() const; void setTitleObject( const rtl::Reference< ::chart::Title >& Title ); + std::shared_ptr<model::Theme> getDocumentTheme() const; + ChartColorPaletteType getColorPaletteType() const { return m_eColorPaletteType; } + sal_uInt32 getColorPaletteIndex() const { return m_nColorPaletteIndex; } + void setColorPalette(ChartColorPaletteType eType, sal_uInt32 nIndex); + void clearColorPalette(); + bool usesColorPalette() const; + std::optional<ChartColorPalette> getCurrentColorPalette() const; + void applyColorPaletteToDataSeries(const ChartColorPalette& rColorPalette); + void onDocumentThemeChanged(); + private: void dumpAsXml(xmlTextWriterPtr pWriter) const; diff --git a/chart2/source/controller/chartcontroller.component b/chart2/source/controller/chartcontroller.component index ef8e748242e8..e795da632683 100644 --- a/chart2/source/controller/chartcontroller.component +++ b/chart2/source/controller/chartcontroller.component @@ -50,4 +50,8 @@ constructor="org_libreoffice_chart2_Chart2ToolboxController"> <service name="com.sun.star.frame.ToolbarController"/> </implementation> + <implementation name="com.sun.star.comp.chart2.ChartColorPaletteControl" + constructor="com_sun_star_comp_chart2_ChartColorPaletteControl_get_implementation"> + <service name="com.sun.star.frame.ToolbarController"/> + </implementation> </component> diff --git a/chart2/source/controller/sidebar/Chart2PanelFactory.cxx b/chart2/source/controller/sidebar/Chart2PanelFactory.cxx index a0483a22b6ed..e058e6f7fa62 100644 --- a/chart2/source/controller/sidebar/Chart2PanelFactory.cxx +++ b/chart2/source/controller/sidebar/Chart2PanelFactory.cxx @@ -34,6 +34,7 @@ #include "ChartErrorBarPanel.hxx" #include "ChartAreaPanel.hxx" #include "ChartLinePanel.hxx" +#include "ChartColorsPanel.hxx" using namespace css::uno; @@ -98,6 +99,8 @@ Reference<css::ui::XUIElement> SAL_CALL ChartPanelFactory::createUIElement ( xPanel = ChartAreaPanel::Create(pParent, xFrame, pController); else if (rsResourceURL.endsWith("/LinePanel")) xPanel = ChartLinePanel::Create(pParent, xFrame, pController); + else if (rsResourceURL.endsWith("/ColorsPanel")) + xPanel = ChartColorsPanel::Create(pParent, xFrame, pController); if (xPanel) xElement = sfx2::sidebar::SidebarPanelBase::Create( diff --git a/chart2/source/controller/sidebar/ChartAreaPanel.cxx b/chart2/source/controller/sidebar/ChartAreaPanel.cxx index 967bc20a0d91..87a49974eb8c 100644 --- a/chart2/source/controller/sidebar/ChartAreaPanel.cxx +++ b/chart2/source/controller/sidebar/ChartAreaPanel.cxx @@ -306,6 +306,13 @@ void ChartAreaPanel::Initialize() updateData(); } +bool ChartAreaPanel::selectionIsDataSeries() const +{ + OUString aCID = getCID(mxModel); + ObjectType eType = ObjectIdentifier::getObjectType(aCID); + return eType == ObjectType::OBJECTTYPE_DATA_SERIES || eType == ObjectType::OBJECTTYPE_DATA_POINT; +} + void ChartAreaPanel::setFillTransparence(const XFillTransparenceItem& rItem) { PreventUpdate aProtector(mbUpdate); @@ -357,6 +364,10 @@ void ChartAreaPanel::setFillStyleAndColor(const XFillStyleItem* pStyleItem, if (pStyleItem) xPropSet->setPropertyValue(u"FillStyle"_ustr, css::uno::Any(pStyleItem->GetValue())); xPropSet->setPropertyValue(u"FillColor"_ustr, css::uno::Any(rColorItem.GetValue())); + if (selectionIsDataSeries()) + { + mxModel->clearColorPalette(); + } } void ChartAreaPanel::setFillStyleAndGradient(const XFillStyleItem* pStyleItem, diff --git a/chart2/source/controller/sidebar/ChartAreaPanel.hxx b/chart2/source/controller/sidebar/ChartAreaPanel.hxx index e1edd3d832e8..24f0d85912b1 100644 --- a/chart2/source/controller/sidebar/ChartAreaPanel.hxx +++ b/chart2/source/controller/sidebar/ChartAreaPanel.hxx @@ -74,6 +74,7 @@ private: void Initialize(); void doUpdateModel(const rtl::Reference<::chart::ChartModel>& xModel); + bool selectionIsDataSeries() const; bool mbUpdate; bool mbModelValid; diff --git a/chart2/source/controller/sidebar/ChartColorPaletteControl.cxx b/chart2/source/controller/sidebar/ChartColorPaletteControl.cxx new file mode 100644 index 000000000000..b5a4503ffbfe --- /dev/null +++ b/chart2/source/controller/sidebar/ChartColorPaletteControl.cxx @@ -0,0 +1,353 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/drawing/FillStyle.hpp> + +#include <memory> +#include <utility> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/virdev.hxx> + +#include <ChartColorPaletteHelper.hxx> +#include "ChartColorPaletteControl.hxx" + +#include <vcl/gdimtf.hxx> +#include <vcl/graph.hxx> + +using namespace css; + +namespace chart::sidebar +{ +constexpr tools::Long BORDER = ChartColorPaletteLayout::ItemBorder; +constexpr tools::Long SIZE = ChartColorPaletteLayout::ItemSize; +constexpr tools::Long constElementNumber = ChartColorPaletteSize; + +ChartColorPaletteControl::ChartColorPaletteControl( + const uno::Reference<uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) + , meColorPaletteType(ChartColorPaletteType::Unknown) + , mnColorPaletteIndex(0) +{ +} + +ChartColorPaletteControl::~ChartColorPaletteControl() = default; + +void ChartColorPaletteControl::initialize(const uno::Sequence<uno::Any>& rArguments) +{ + svt::PopupWindowController::initialize(rArguments); + + if (m_pToolbar) + { + mxPopoverContainer = std::make_unique<ToolbarPopupContainer>(m_pToolbar); + m_pToolbar->set_item_popover(m_aCommandURL, mxPopoverContainer->getTopLevel()); + m_pToolbar->set_item_sensitive(m_aCommandURL, true); + } + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (getToolboxId(nId, &pToolBox)) + { + pToolBox->SetItemBits(nId, pToolBox->GetItemBits(nId) | ToolBoxItemBits::DROPDOWNONLY); + pToolBox->EnableItem(nId, true); + } +} + +void ChartColorPaletteControl::execute(sal_Int16 /*nKeyModifier*/) +{ + if (m_pToolbar) + { + // Toggle the popup also when toolbutton is activated + m_pToolbar->set_menu_item_active(m_aCommandURL, + !m_pToolbar->get_menu_item_active(m_aCommandURL)); + } + else + { + // Open the popup also when Enter key is pressed. + createPopupWindow(); + } +} + +void ChartColorPaletteControl::statusChanged(const frame::FeatureStateEvent& rEvent) +{ + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (!getToolboxId(nId, &pToolBox) && !m_pToolbar) + return; + + if (rEvent.FeatureURL.Complete == m_aCommandURL) + { + updateStatus(); + } +} + +void ChartColorPaletteControl::updateStatus(bool bForce) +{ + if (!mpHandler) + return; + + if (bForce || meColorPaletteType != getColorPaletteType() + || mnColorPaletteIndex != getColorPaletteIndex()) + { + meColorPaletteType = getColorPaletteType(); + mnColorPaletteIndex = getColorPaletteIndex(); + + ToolBox* pToolBox = nullptr; + ToolBoxItemId nId; + if (!getToolboxId(nId, &pToolBox) && !m_pToolbar) + return; + + auto pDev = VclPtr<VirtualDevice>::Create(); + renderSelectedColorPalette(pDev); + auto aSelItemImg(pDev->GetBitmapEx(Point(), pDev->GetOutputSizePixel())); + if (m_pToolbar) + { + m_pToolbar->set_item_image(m_aCommandURL, Graphic(aSelItemImg).GetXGraphic()); + } + else + { + pToolBox->SetItemImage(nId, Image(aSelItemImg)); + } + } +} + +void ChartColorPaletteControl::renderSelectedColorPalette(const VclPtr<VirtualDevice>& pDev) const +{ + if (!pDev) + return; + + const auto pHelper = getColorPaletteHelper(); + if (!pHelper) + return; + + static constexpr Point aPosition(0, 0); + static constexpr Size aSize + = { BORDER * 6 + SIZE * constElementNumber / 2, BORDER * 5 + SIZE * 2 }; + static constexpr tools::Rectangle aDrawArea(aPosition, aSize); + + pDev->SetOutputSizePixel(aSize, /*bErase*/ true, /*bAlphaMaskTransparent*/ true); + + if (getColorPaletteType() == ChartColorPaletteType::Unknown) + { + ChartColorPaletteHelper::renderNoPalette(pDev, aDrawArea); + return; + } + + const ChartColorPalette aColorPalette + = pHelper->getColorPalette(getColorPaletteType(), getColorPaletteIndex()); + ChartColorPaletteHelper::renderColorPalette(pDev, aDrawArea, aColorPalette, true); +} + +void ChartColorPaletteControl::setColorPaletteHandler( + std::shared_ptr<IColorPaletteHandler> rColorPaletteHandler) +{ + if (!mpHandler) + { + mpHandler = rColorPaletteHandler; + updateStatus(true); + } +} + +std::shared_ptr<ChartColorPaletteHelper> ChartColorPaletteControl::getColorPaletteHelper() const +{ + if (mpHandler) + return mpHandler->getHelper(); + return nullptr; +} + +ChartColorPaletteType ChartColorPaletteControl::getColorPaletteType() const +{ + if (mpHandler) + return mpHandler->getType(); + return ChartColorPaletteType::Unknown; +} + +sal_uInt32 ChartColorPaletteControl::getColorPaletteIndex() const +{ + if (mpHandler) + return mpHandler->getIndex(); + return 0; +} + +void ChartColorPaletteControl::dispatchColorPaletteCommand(const ChartColorPaletteType eType, + const sal_uInt32 nIndex) const +{ + if (mpHandler) + mpHandler->select(eType, nIndex); +} + +void ChartColorPaletteControl::applyColorPalette(const ChartColorPalette* pColorPalette) const +{ + if (mpHandler) + mpHandler->apply(pColorPalette); +} + +std::unique_ptr<WeldToolbarPopup> ChartColorPaletteControl::weldPopupWindow() +{ + return std::make_unique<ChartColorPalettePopup>(this, m_pToolbar); +} + +VclPtr<vcl::Window> ChartColorPaletteControl::createVclPopupWindow(vcl::Window* pParent) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create( + getFrameInterface(), pParent, + std::make_unique<ChartColorPalettePopup>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString ChartColorPaletteControl::getImplementationName() +{ + return "com.sun.star.comp.chart2.ChartColorPaletteControl"; +} + +uno::Sequence<OUString> ChartColorPaletteControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_comp_chart2_ChartColorPaletteControl_get_implementation( + uno::XComponentContext* rContext, uno::Sequence<uno::Any> const&) +{ + return cppu::acquire(new ChartColorPaletteControl(rContext)); +} + +ChartColorPalettePopup::ChartColorPalettePopup(ChartColorPaletteControl* pControl, + weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, + "modules/schart/ui/chartcolorpalettepopup.ui", "ColorPaletteWindow") + , mxControl(pControl) + , mxColorfulValueSet(new ChartColorPalettes) + , mxColorfulValueSetWin( + new weld::CustomWeld(*m_xBuilder, "colorful_palettes", *mxColorfulValueSet)) + , mxMonoValueSet(new ChartColorPalettes) + , mxMonoValueSetWin( + new weld::CustomWeld(*m_xBuilder, "monochromatic_palettes", *mxMonoValueSet)) +{ + mxColorfulValueSet->SetColCount(2); + mxColorfulValueSet->SetLineCount(2); + mxColorfulValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor()); + + mxMonoValueSet->SetColCount(2); + mxMonoValueSet->SetLineCount(3); + mxMonoValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFaceColor()); + + initColorPalettes(); + + mxColorfulValueSet->SetOptimalSize(); + mxColorfulValueSet->SetSelectHdl(LINK(this, ChartColorPalettePopup, SelectColorfulValueSetHdl)); + + mxMonoValueSet->SetOptimalSize(); + mxMonoValueSet->SetSelectHdl(LINK(this, ChartColorPalettePopup, SelectMonoValueSetHdl)); + + selectItem(mxControl->getColorPaletteType(), mxControl->getColorPaletteIndex() + 1); +} + +ChartColorPalettePopup::~ChartColorPalettePopup() {} + +void ChartColorPalettePopup::selectItem(const ChartColorPaletteType eType, + const sal_uInt32 nIndex) const +{ + switch (eType) + { + default: + case ChartColorPaletteType::Unknown: + mxColorfulValueSet->SetNoSelection(); + mxMonoValueSet->SetNoSelection(); + break; + case ChartColorPaletteType::Colorful: + mxColorfulValueSet->SelectItem(nIndex); + break; + case ChartColorPaletteType::Monochromatic: + mxMonoValueSet->SelectItem(nIndex); + break; + } +} + +void ChartColorPalettePopup::initColorPalettes() const +{ + const auto pColorPaletteHelper = mxControl->getColorPaletteHelper(); + if (!pColorPaletteHelper) + return; + // colorful palettes + for (size_t i = 0; i < ChartColorPaletteHelper::ColorfulPaletteSize; ++i) + mxColorfulValueSet->insert( + pColorPaletteHelper->getColorPalette(ChartColorPaletteType::Colorful, i)); + // monotonic palettes + for (size_t i = 0; i < ChartColorPaletteHelper::MonotonicPaletteSize; ++i) + mxMonoValueSet->insert( + pColorPaletteHelper->getColorPalette(ChartColorPaletteType::Monochromatic, i)); +} + +void ChartColorPalettePopup::GrabFocus() +{ + if (mxMonoValueSet->IsNoSelection()) + mxColorfulValueSet->GrabFocus(); + else + mxMonoValueSet->GrabFocus(); +} + +IMPL_LINK_NOARG(ChartColorPalettePopup, SelectColorfulValueSetHdl, ValueSet*, void) +{ + sal_uInt32 nIndex = SelectValueSetHdl(mxColorfulValueSet); + if (nIndex != static_cast<sal_uInt32>(-1)) + { + mxControl->dispatchColorPaletteCommand(ChartColorPaletteType::Colorful, nIndex); + mxMonoValueSet->SetNoSelection(); + mxControl->updateStatus(); + } + mxControl->EndPopupMode(); +} + +IMPL_LINK_NOARG(ChartColorPalettePopup, SelectMonoValueSetHdl, ValueSet*, void) +{ + sal_uInt32 nIndex = SelectValueSetHdl(mxMonoValueSet); + if (nIndex != static_cast<sal_uInt32>(-1)) + { + mxControl->dispatchColorPaletteCommand(ChartColorPaletteType::Monochromatic, nIndex); + mxColorfulValueSet->SetNoSelection(); + mxControl->updateStatus(); + } + mxControl->EndPopupMode(); +} + +sal_uInt32 ChartColorPalettePopup::SelectValueSetHdl( + const std::unique_ptr<ChartColorPalettes>& xValueSet) const +{ + const sal_uInt32 nItemId = xValueSet->GetSelectedItemId(); + + if (!nItemId) + return -1; + + const sal_uInt32 nIndex = nItemId - 1; + + if (const ChartColorPalette* pPalette = xValueSet->getPalette(nIndex)) + { + mxControl->applyColorPalette(pPalette); + return nIndex; + } + return -1; +} + +} // end namespace chart::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/sidebar/ChartColorPaletteControl.hxx b/chart2/source/controller/sidebar/ChartColorPaletteControl.hxx new file mode 100644 index 000000000000..a2007bd79b6f --- /dev/null +++ b/chart2/source/controller/sidebar/ChartColorPaletteControl.hxx @@ -0,0 +1,94 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <svtools/popupwindowcontroller.hxx> +#include <svtools/toolbarmenu.hxx> +#include <ChartColorPalettes.hxx> + +namespace chart +{ +class ChartColorPaletteHelper; + +namespace sidebar +{ +struct IColorPaletteHandler +{ + virtual ~IColorPaletteHandler() = default; + virtual void select(ChartColorPaletteType eType, sal_uInt32 nIndex) = 0; + virtual void apply(const ChartColorPalette* pColorPalette) = 0; + [[nodiscard]] virtual std::shared_ptr<ChartColorPaletteHelper> getHelper() const = 0; + [[nodiscard]] virtual ChartColorPaletteType getType() const = 0; + [[nodiscard]] virtual sal_uInt32 getIndex() const = 0; +}; + +class ChartColorPaletteControl final : public svt::PopupWindowController +{ + std::shared_ptr<IColorPaletteHandler> mpHandler; + ChartColorPaletteType meColorPaletteType; + sal_uInt32 mnColorPaletteIndex; + +public: + explicit ChartColorPaletteControl( + const css::uno::Reference<css::uno::XComponentContext>& rContext); + + // XInitialization + void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override; + + // XServiceInfo + OUString SAL_CALL getImplementationName() override; + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + void SAL_CALL execute(sal_Int16 nKeyModifier) override; + void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& rEvent) override; + + ~ChartColorPaletteControl() override; + + void setColorPaletteHandler(std::shared_ptr<IColorPaletteHandler> rColorPaletteHandler); + std::shared_ptr<ChartColorPaletteHelper> getColorPaletteHelper() const; + ChartColorPaletteType getColorPaletteType() const; + sal_uInt32 getColorPaletteIndex() const; + void dispatchColorPaletteCommand(ChartColorPaletteType eType, sal_uInt32 nIndex) const; + void applyColorPalette(const ChartColorPalette* pColorPalette) const; + void updateStatus(bool bForce = false); + +private: + std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + VclPtr<vcl::Window> createVclPopupWindow(vcl::Window* pParent) override; + + void renderSelectedColorPalette(const VclPtr<VirtualDevice>& pDev) const; +}; + +class ChartColorPalettePopup final : public WeldToolbarPopup +{ + rtl::Reference<ChartColorPaletteControl> mxControl; + std::unique_ptr<ChartColorPalettes> mxColorfulValueSet; + std::unique_ptr<weld::CustomWeld> mxColorfulValueSetWin; + std::unique_ptr<ChartColorPalettes> mxMonoValueSet; + std::unique_ptr<weld::CustomWeld> mxMonoValueSetWin; + + DECL_LINK(SelectColorfulValueSetHdl, ValueSet*, void); + DECL_LINK(SelectMonoValueSetHdl, ValueSet*, void); + sal_uInt32 SelectValueSetHdl(const std::unique_ptr<ChartColorPalettes>& xValueSet) const; + + void GrabFocus() override; + + void selectItem(ChartColorPaletteType eType, sal_uInt32 nIndex) const; + void initColorPalettes() const; + +public: + ChartColorPalettePopup(ChartColorPaletteControl* pControl, weld::Widget* pParent); + ~ChartColorPalettePopup() override; +}; +} // end namespace sidebar +} // end namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/sidebar/ChartColorWrapper.cxx b/chart2/source/controller/sidebar/ChartColorWrapper.cxx index 64126b13a06c..f706f763e737 100644 --- a/chart2/source/controller/sidebar/ChartColorWrapper.cxx +++ b/chart2/source/controller/sidebar/ChartColorWrapper.cxx @@ -101,6 +101,11 @@ void ChartColorWrapper::operator()([[maybe_unused]] const OUString& , const Name } xPropSet->setPropertyValue(maPropertyName, css::uno::Any(rColor.m_aColor)); + + OUString aCID = getCID(mxModel); + ObjectType eType = ObjectIdentifier::getObjectType(aCID); + if (eType == OBJECTTYPE_DATA_SERIES || eType == OBJECTTYPE_DATA_POINT) + mxModel->clearColorPalette(); } void ChartColorWrapper::updateModel(const rtl::Reference<::chart::ChartModel>& xModel) diff --git a/chart2/source/controller/sidebar/ChartColorsPanel.cxx b/chart2/source/controller/sidebar/ChartColorsPanel.cxx new file mode 100644 index 000000000000..b3e878180171 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartColorsPanel.cxx @@ -0,0 +1,295 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/log.hxx> +#include <vcl/svapp.hxx> + +#include "ChartColorsPanel.hxx" +#include "ChartColorPaletteControl.hxx" + +#include <ChartColorPaletteHelper.hxx> +#include <ChartController.hxx> +#include <ChartModel.hxx> +#include <DataSeries.hxx> + +#include <com/sun/star/drawing/FillStyle.hpp> + +#include <sfx2/weldutils.hxx> +#include <svtools/toolbarmenu.hxx> + +#include <algorithm> + +using namespace css; + +namespace chart::sidebar +{ +namespace +{ +OUString getCID(const uno::Reference<frame::XModel>& xModel) +{ + const uno::Reference<frame::XController> xController(xModel->getCurrentController()); + const uno::Reference<view::XSelectionSupplier> xSelectionSupplier(xController, uno::UNO_QUERY); + if (!xSelectionSupplier.is()) + return OUString(); + + const uno::Any aAny = xSelectionSupplier->getSelection(); + assert(aAny.hasValue()); + OUString aCID; + aAny >>= aCID; + return aCID; +} + +ChartColorPaletteControl* getChartColorPaletteControl(const ToolbarUnoDispatcher& rToolBoxColor) +{ + const uno::Reference<frame::XToolbarController> xController + = rToolBoxColor.GetControllerForCommand(sUnoChartColorPalette); + const auto pToolBoxLineStyleControl + = dynamic_cast<ChartColorPaletteControl*>(xController.get()); + return pToolBoxLineStyleControl; +} +} // end unnamed namespace + +class ColorPaletteWrapper final : public IColorPaletteHandler +{ +public: + ColorPaletteWrapper(rtl::Reference<ChartModel> mxModel, ChartColorPaletteControl* pControl); + + void updateModel(const rtl::Reference<ChartModel>& xModel); + void updateData() const; + + void select(ChartColorPaletteType eType, sal_uInt32 nIndex) override; + void apply(const ChartColorPalette* pColorPalette) override; + [[nodiscard]] std::shared_ptr<ChartColorPaletteHelper> getHelper() const override; + [[nodiscard]] ChartColorPaletteType getType() const override; + [[nodiscard]] sal_uInt32 getIndex() const override; + +private: + rtl::Reference<ChartModel> mxModel; + ChartColorPaletteControl* mpControl; +}; + +ColorPaletteWrapper::ColorPaletteWrapper(rtl::Reference<ChartModel> mxModel, + ChartColorPaletteControl* pControl) + : mxModel(std::move(mxModel)) + , mpControl(pControl) +{ +} + +void ColorPaletteWrapper::updateModel(const rtl::Reference<ChartModel>& xModel) +{ + mxModel = xModel; +} + +void ColorPaletteWrapper::updateData() const +{ + util::URL aUrl; + aUrl.Complete = sUnoChartColorPalette; + + frame::FeatureStateEvent aEvent; + aEvent.FeatureURL = aUrl; + aEvent.IsEnabled = true; + + if (mpControl) + mpControl->statusChanged(aEvent); +} + +void ColorPaletteWrapper::select(ChartColorPaletteType eType, const sal_uInt32 nIndex) +{ + mxModel->setColorPalette(eType, nIndex); +} + +void ColorPaletteWrapper::apply(const ChartColorPalette* pColorPalette) +{ + if (pColorPalette) + mxModel->applyColorPaletteToDataSeries(*pColorPalette); +} + +std::shared_ptr<ChartColorPaletteHelper> ColorPaletteWrapper::getHelper() const +{ + const std::shared_ptr<model::Theme> pTheme = mxModel->getDocumentTheme(); + return std::make_shared<ChartColorPaletteHelper>(pTheme); +} + +ChartColorPaletteType ColorPaletteWrapper::getType() const +{ + return mxModel->getColorPaletteType(); +} + +sal_uInt32 ColorPaletteWrapper::getIndex() const { return mxModel->getColorPaletteIndex(); } + +const std::vector<ObjectType> ChartColorsPanel::maAcceptedTypes{ + OBJECTTYPE_PAGE, OBJECTTYPE_LEGEND, OBJECTTYPE_DIAGRAM, + OBJECTTYPE_DIAGRAM_WALL, OBJECTTYPE_DIAGRAM_FLOOR, OBJECTTYPE_DATA_SERIES, + OBJECTTYPE_DATA_POINT, +}; + +ChartColorsPanel::ChartColorsPanel(weld::Widget* pParent, + const uno::Reference<frame::XFrame>& rxFrame, + ChartController* pController) + : PanelLayout(pParent, "ChartColorsPanel", "modules/schart/ui/sidebarcolors.ui") + , mxModel(pController->getChartModel()) + , mxModifyListener(new ChartSidebarModifyListener(this)) + , mxSelectionListener(new ChartSidebarSelectionListener(this)) + , mbModelValid(true) + , mxColorPaletteTB(m_xBuilder->weld_toolbar("colorpalettetype")) + , mxColorPaletteDispatch(new ToolbarUnoDispatcher(*mxColorPaletteTB, *m_xBuilder, rxFrame)) +{ + auto aAcceptedTypes(maAcceptedTypes); + mxSelectionListener->setAcceptedTypes(std::move(aAcceptedTypes)); + Initialize(); +} + +ChartColorsPanel::~ChartColorsPanel() +{ + doUpdateModel(nullptr); + mxColorPaletteDispatch.reset(); + mxColorPaletteTB.reset(); +} + +void ChartColorsPanel::Initialize() +{ + mxModel->addModifyListener(mxModifyListener); + + uno::Reference<view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), + uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); + + ChartColorPaletteControl* pColorPaletteControl + = getChartColorPaletteControl(*mxColorPaletteDispatch); + assert(pColorPaletteControl); + mxColorPaletteWrapper = std::make_shared<ColorPaletteWrapper>(mxModel, pColorPaletteControl); + pColorPaletteControl->setColorPaletteHandler(mxColorPaletteWrapper); + + updateData(); +} + +void ChartColorsPanel::updateData() +{ + if (!mbModelValid) + return; + + const OUString aCID = getCID(mxModel); + const ObjectType eType = ObjectIdentifier::getObjectType(aCID); + + if (std::find(maAcceptedTypes.begin(), maAcceptedTypes.end(), eType) == maAcceptedTypes.end()) + return; + + // if fill style is not solid clear palette selection + if (eType == OBJECTTYPE_DATA_SERIES || eType == OBJECTTYPE_DATA_POINT) + { + const uno::Reference<beans::XPropertySet> xPropSet + = ObjectIdentifier::getObjectPropertySet(aCID, mxModel); + if (!xPropSet.is()) + return; + + uno::Reference<beans::XPropertySetInfo> xInfo(xPropSet->getPropertySetInfo()); + if (!xInfo.is()) + return; + + SolarMutexGuard aGuard; + if (xInfo->hasPropertyByName("FillStyle")) + { + drawing::FillStyle eFillStyle = drawing::FillStyle_SOLID; + xPropSet->getPropertyValue("FillStyle") >>= eFillStyle; + if (eFillStyle != drawing::FillStyle_SOLID) + { + mxModel->clearColorPalette(); + } + } + } + + mxColorPaletteWrapper->updateData(); +} + +std::unique_ptr<PanelLayout> ChartColorsPanel::Create(weld::Widget* pParent, + const uno::Reference<frame::XFrame>& rxFrame, + ChartController* pController) +{ + if (pParent == nullptr) + throw lang::IllegalArgumentException("no parent Window given to ChartColorsPanel::Create", + nullptr, 0); + if (!rxFrame.is()) + throw lang::IllegalArgumentException("no XFrame given to ChartColorsPanel::Create", nullptr, + 1); + + return std::make_unique<ChartColorsPanel>(pParent, rxFrame, pController); +} + +void ChartColorsPanel::DataChanged(const DataChangedEvent& rEvent) +{ + PanelLayout::DataChanged(rEvent); + updateData(); +} + +void ChartColorsPanel::HandleContextChange(const vcl::EnumContext&) { updateData(); } + +void ChartColorsPanel::NotifyItemUpdate(sal_uInt16 /*nSID*/, SfxItemState /*eState*/, + const SfxPoolItem* /*pState*/) +{ +} + +void ChartColorsPanel::modelInvalid() { mbModelValid = false; } + +void ChartColorsPanel::doUpdateModel(const rtl::Reference<ChartModel>& xModel) +{ + if (mbModelValid) + { + mxModel->removeModifyListener(mxModifyListener); + + const uno::Reference<view::XSelectionSupplier> oldSelectionSupplier( + mxModel->getCurrentController(), uno::UNO_QUERY); + if (oldSelectionSupplier.is()) + { + oldSelectionSupplier->removeSelectionChangeListener(mxSelectionListener); + } + } + + mxModel = xModel; + mbModelValid = mxModel.is(); + + if (!mbModelValid) + return; + + mxColorPaletteWrapper->updateModel(mxModel); + + mxModel->addModifyListener(mxModifyListener); + + uno::Reference<view::XSelectionSupplier> xSelectionSupplier(mxModel->getCurrentController(), + uno::UNO_QUERY); + if (xSelectionSupplier.is()) + xSelectionSupplier->addSelectionChangeListener(mxSelectionListener); +} + +void ChartColorsPanel::updateModel(const uno::Reference<frame::XModel> xModel) +{ + const auto pModel = dynamic_cast<ChartModel*>(xModel.get()); + assert(!xModel || pModel); + doUpdateModel(pModel); +} + +void ChartColorsPanel::selectionChanged(const bool bCorrectType) +{ + if (bCorrectType) + updateData(); +} + +} // end of namespace ::chart::sidebar + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/sidebar/ChartColorsPanel.hxx b/chart2/source/controller/sidebar/ChartColorsPanel.hxx new file mode 100644 index 000000000000..3180f7660f58 --- /dev/null +++ b/chart2/source/controller/sidebar/ChartColorsPanel.hxx @@ -0,0 +1,87 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <com/sun/star/frame/XFrame.hpp> + +#include <sfx2/sidebar/ControllerItem.hxx> +#include <sfx2/sidebar/IContextChangeReceiver.hxx> +#include <sfx2/sidebar/SidebarModelUpdate.hxx> +#include <sfx2/sidebar/PanelLayout.hxx> +#include "ChartSidebarModifyListener.hxx" +#include "ChartSidebarSelectionListener.hxx" +#include <ChartColorPalettes.hxx> + +class ToolbarUnoDispatcher; + +namespace chart +{ +class ChartController; + +namespace sidebar +{ +class ColorPaletteWrapper; + +class ChartColorsPanel final : public PanelLayout, + public sfx2::sidebar::IContextChangeReceiver, + public sfx2::sidebar::ControllerItem::ItemUpdateReceiverInterface, + public sfx2::sidebar::SidebarModelUpdate, + public ChartSidebarModifyListenerParent, + public ChartSidebarSelectionListenerParent +{ +public: + static const std::vector<ObjectType> maAcceptedTypes; + + static std::unique_ptr<PanelLayout> + Create(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame, + ChartController* pController); + + void DataChanged(const DataChangedEvent& rEvent) override; + + void HandleContextChange(const vcl::EnumContext& rContext) override; + + void NotifyItemUpdate(sal_uInt16 nSId, SfxItemState eState, const SfxPoolItem* pState) override; + + void GetControlState(const sal_uInt16 /*nSId*/, + boost::property_tree::ptree& /*rState*/) override + { + } + + // constructor/destructor + ChartColorsPanel(weld::Widget* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame, + ChartController* pController); + ~ChartColorsPanel() override; + + void updateData() override; + void modelInvalid() override; + + void selectionChanged(bool bCorrectType) override; + + void updateModel(css::uno::Reference<css::frame::XModel> xModel) override; + +private: + rtl::Reference<ChartModel> mxModel; + css::uno::Reference<css::util::XModifyListener> mxModifyListener; + rtl::Reference<ChartSidebarSelectionListener> mxSelectionListener; + + bool mbModelValid; + + std::unique_ptr<weld::Toolbar> mxColorPaletteTB; + std::unique_ptr<ToolbarUnoDispatcher> mxColorPaletteDispatch; + std::shared_ptr<ColorPaletteWrapper> mxColorPaletteWrapper; + + void Initialize(); + void doUpdateModel(const rtl::Reference<ChartModel>& xModel); +}; +} // end of namespace sidebar +} // end of namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/BaseColorScheme.hxx b/chart2/source/inc/BaseColorScheme.hxx new file mode 100644 index 000000000000..e916711be357 --- /dev/null +++ b/chart2/source/inc/BaseColorScheme.hxx @@ -0,0 +1,44 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/chart2/XColorScheme.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +namespace chart +{ +class BaseColorScheme + : public ::cppu::WeakImplHelper<css::chart2::XColorScheme, css::lang::XServiceInfo> +{ +public: + explicit BaseColorScheme(); + + /// declare XServiceInfo methods + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + +protected: + // member variables + mutable css::uno::Sequence<sal_Int64> m_aColorSequence; + mutable sal_Int32 m_nNumberOfColors; +}; +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/ChartColorPaletteHelper.hxx b/chart2/source/inc/ChartColorPaletteHelper.hxx new file mode 100644 index 000000000000..696e807876ac --- /dev/null +++ b/chart2/source/inc/ChartColorPaletteHelper.hxx @@ -0,0 +1,48 @@ +/* -*- 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/. + */ + +#pragma once + +#include "charttoolsdllapi.hxx" +#include <svx/svxdllapi.h> +#include <svx/ChartColorPaletteType.hxx> +#include <docmodel/theme/Theme.hxx> +#include <tools/gen.hxx> + +#include <array> + +class OutputDevice; + +namespace chart +{ +class OOO_DLLPUBLIC_CHARTTOOLS ChartColorPaletteHelper +{ +public: + static constexpr size_t ColorfulPaletteSize = 4; + static constexpr size_t MonotonicPaletteSize = 6; + + explicit ChartColorPaletteHelper(const std::shared_ptr<model::Theme>& pTheme); + + ChartColorPalette getColorPalette(ChartColorPaletteType eType, sal_uInt32 nIndex) const; + static void renderColorPalette(OutputDevice* pDev, const tools::Rectangle& rDrawArea, + const ChartColorPalette& rColorSet, + bool bDrawItemBorder = false); + static void renderNoPalette(OutputDevice* pDev, const tools::Rectangle& rDrawArea); + +private: + void createBasePaletteFromTheme(const std::shared_ptr<model::Theme>& pTheme); + ChartColorPalette createColorfulPalette(sal_uInt32 nIndex) const; + ChartColorPalette createColorfulPaletteImpl(size_t nIdx1, size_t nIdx2, size_t nIdx3) const; + ChartColorPalette createMonotonicPalette(sal_uInt32 nIndex) const; + + ChartColorPalette mBasePalette; +}; +} // end namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/ChartColorPalettes.hxx b/chart2/source/inc/ChartColorPalettes.hxx new file mode 100644 index 000000000000..8bb5aa052c25 --- /dev/null +++ b/chart2/source/inc/ChartColorPalettes.hxx @@ -0,0 +1,38 @@ +/* -*- 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/. + */ + +#pragma once + +#include "charttoolsdllapi.hxx" + +#include <svx/ChartColorPaletteType.hxx> +#include <svtools/valueset.hxx> + +namespace chart +{ +class OOO_DLLPUBLIC_CHARTTOOLS ChartColorPalettes final : public ValueSet +{ + std::vector<ChartColorPalette> maColorSets; + +public: + ChartColorPalettes() + : ValueSet(nullptr) + { + } + + void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + void UserDraw(const UserDrawEvent& rUserDrawEvent) override; + void StyleUpdated() override; + + void insert(ChartColorPalette const& rColorSet); + const ChartColorPalette* getPalette(sal_uInt32 nItem) const; +}; +} // end namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/ChartColorScheme.hxx b/chart2/source/inc/ChartColorScheme.hxx new file mode 100644 index 000000000000..f330d31ababc --- /dev/null +++ b/chart2/source/inc/ChartColorScheme.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include "BaseColorScheme.hxx" +#include <svx/ChartColorPaletteType.hxx> + +namespace chart +{ +class ChartColorScheme final : public BaseColorScheme +{ +public: + explicit ChartColorScheme(const ChartColorPalette& rPalette); + + /// declare XServiceInfo methods + OUString SAL_CALL getImplementationName() override; + +protected: + // ____ XColorScheme ____ + ::sal_Int32 SAL_CALL getColorByIndex(::sal_Int32 nIndex) override; +}; +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/inc/ConfigColorScheme.hxx b/chart2/source/inc/ConfigColorScheme.hxx index fe73dc671bb6..98b0007c7ff5 100644 --- a/chart2/source/inc/ConfigColorScheme.hxx +++ b/chart2/source/inc/ConfigColorScheme.hxx @@ -19,9 +19,7 @@ #pragma once #include "charttoolsdllapi.hxx" -#include <cppuhelper/implbase.hxx> -#include <com/sun/star/chart2/XColorScheme.hpp> -#include <com/sun/star/lang/XServiceInfo.hpp> +#include "BaseColorScheme.hxx" #include <memory> @@ -30,31 +28,26 @@ namespace com::sun::star::uno { class XComponentContext; } namespace chart { -OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference< css::chart2::XColorScheme > createConfigColorScheme( - const css::uno::Reference< css::uno::XComponentContext > & xContext ); +OOO_DLLPUBLIC_CHARTTOOLS css::uno::Reference<css::chart2::XColorScheme> +createConfigColorScheme(const css::uno::Reference<css::uno::XComponentContext>& xContext); namespace impl { class ChartConfigItem; } -class ConfigColorScheme final : - public ::cppu::WeakImplHelper< - css::chart2::XColorScheme, - css::lang::XServiceInfo > +class ConfigColorScheme final : public BaseColorScheme { public: explicit ConfigColorScheme( const css::uno::Reference< css::uno::XComponentContext > & xContext ); virtual ~ConfigColorScheme() override; - /// declare XServiceInfo methods - virtual OUString SAL_CALL getImplementationName() override; - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; - virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; - // ____ ConfigItemListener ____ void notify(); + /// declare XServiceInfo methods + virtual OUString SAL_CALL getImplementationName() override; + protected: // ____ XColorScheme ____ virtual ::sal_Int32 SAL_CALL getColorByIndex( ::sal_Int32 nIndex ) override; @@ -65,8 +58,6 @@ private: // member variables css::uno::Reference< css::uno::XComponentContext > m_xContext; std::unique_ptr< impl::ChartConfigItem > m_apChartConfigItem; - mutable css::uno::Sequence< sal_Int64 > m_aColorSequence; - mutable sal_Int32 m_nNumberOfColors; bool m_bNeedsUpdate; }; diff --git a/chart2/source/model/main/ChartModel.cxx b/chart2/source/model/main/ChartModel.cxx index bc718c89878d..65e8aabc13ff 100644 --- a/chart2/source/model/main/ChartModel.cxx +++ b/chart2/source/model/main/ChartModel.cxx @@ -32,6 +32,8 @@ #include <CloneHelper.hxx> #include <NameContainer.hxx> #include "UndoManager.hxx" + +#include <ChartColorPaletteHelper.hxx> #include <ChartView.hxx> #include <PopupRequest.hxx> #include <ModifyListenerHelper.hxx> @@ -54,8 +56,12 @@ #include <com/sun/star/embed/Aspects.hpp> #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp> #include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/document/DocumentProperties.hpp> +#include <com/sun/star/text/XTextDocument.hpp> #include <com/sun/star/util/CloseVetoException.hpp> #include <com/sun/star/util/XModifyBroadcaster.hpp> @@ -64,6 +70,11 @@ #include <comphelper/diagnose_ex.hxx> #include <libxml/xmlwriter.h> +#include <sfx2/objsh.hxx> +#include <com/sun/star/util/XTheme.hpp> +#include <docmodel/uno/UnoTheme.hxx> +#include <docmodel/theme/Theme.hxx> + using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Any; @@ -86,6 +97,19 @@ constexpr OUString lcl_aGDIMetaFileMIMETypeHighContrast( namespace chart { +namespace +{ +SfxObjectShell* getParentShell(const uno::Reference<frame::XModel>& xDocModel) +{ + uno::Reference<lang::XUnoTunnel> xUnoTunnel(xDocModel, uno::UNO_QUERY); + if (xUnoTunnel.is()) + { + return comphelper::getFromUnoTunnel<SfxObjectShell>(xUnoTunnel); + } + return nullptr; +} +} + ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext) : m_aLifeTimeManager( this, this ) , m_bReadOnly( false ) @@ -99,6 +123,8 @@ ChartModel::ChartModel(uno::Reference<uno::XComponentContext > xContext) , m_aVisualAreaSize( ChartModelHelper::getDefaultPageSize() ) , m_xPageBackground( new PageBackground ) , m_xXMLNamespaceMap( new NameContainer() ) + , m_eColorPaletteType(ChartColorPaletteType::Unknown) + , m_nColorPaletteIndex(0) , mnStart(0) , mnEnd(0) { @@ -139,6 +165,8 @@ ChartModel::ChartModel( const ChartModel & rOther ) , m_aGraphicObjectVector( rOther.m_aGraphicObjectVector ) , m_xDataProvider( rOther.m_xDataProvider ) , m_xInternalDataProvider( rOther.m_xInternalDataProvider ) + , m_eColorPaletteType(ChartColorPaletteType::Unknown) + , m_nColorPaletteIndex(0) , mnStart(rOther.mnStart) , mnEnd(rOther.mnEnd) { @@ -186,6 +214,8 @@ ChartModel::ChartModel( const ChartModel & rOther ) ChartModel::~ChartModel() { + if (SfxObjectShell* pShell = getParentShell(m_xParent)) + EndListening(*pShell); if( m_xOldModelAgg.is()) m_xOldModelAgg->setDelegator( nullptr ); } @@ -1276,7 +1306,13 @@ Reference< uno::XInterface > SAL_CALL ChartModel::getParent() void SAL_CALL ChartModel::setParent( const Reference< uno::XInterface >& Parent ) { if( Parent != m_xParent ) + { + if (SfxObjectShell* pShell = getParentShell(m_xParent)) + EndListening(*pShell); m_xParent.set( Parent, uno::UNO_QUERY ); + if (SfxObjectShell* pShell = getParentShell(m_xParent)) + StartListening(*pShell); + } } // ____ XDataSource ____ @@ -1333,6 +1369,113 @@ bool ChartModel::isDataFromPivotTable() const return xPivotTableDataProvider.is(); } +void ChartModel::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + if (rHint.GetId() == SfxHintId::ThemeColorsChanged) + { + onDocumentThemeChanged(); + } +} + +std::shared_ptr<model::Theme> ChartModel::getDocumentTheme() const +{ + std::shared_ptr<model::Theme> pTheme; + uno::Any aThemeValue; + + auto pParent = const_cast<ChartModel*>(this)->getParent(); + uno::Reference<frame::XModel> xDocModel(pParent, uno::UNO_QUERY); + uno::Reference<text::XTextDocument> xTextDoc(xDocModel, uno::UNO_QUERY); + + if (!xTextDoc.is()) // Calc, Impress + { + uno::Reference<beans::XPropertySet> xPropSet(xDocModel, uno::UNO_QUERY); + if (xPropSet.is()) + { + aThemeValue = xPropSet->getPropertyValue("Theme"); + } + } + else // Writer + { + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xDocModel, uno::UNO_QUERY); + if (xDrawPageSupplier.is()) + { + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + if (xDrawPage.is()) + { + uno::Reference<beans::XPropertySet> xPropSet(xDrawPage, uno::UNO_QUERY); + if (xPropSet.is()) + { + aThemeValue = xPropSet->getPropertyValue("Theme"); + } + } + } + } + + uno::Reference<util::XTheme> xTheme(aThemeValue, uno::UNO_QUERY); + if (xTheme.is()) + { + if (auto* pUnoTheme = dynamic_cast<UnoTheme*>(xTheme.get())) + { + pTheme = pUnoTheme->getTheme(); + } + } + else + { + pTheme = model::Theme::FromAny(aThemeValue); + } + + return pTheme; +} + +void ChartModel::setColorPalette(ChartColorPaletteType eType, sal_uInt32 nIndex) +{ + m_eColorPaletteType = eType; + m_nColorPaletteIndex = nIndex; +} + +void ChartModel::clearColorPalette() { setColorPalette(ChartColorPaletteType::Unknown, 0); } + +bool ChartModel::usesColorPalette() const +{ + return m_eColorPaletteType != ChartColorPaletteType::Unknown; +} + +std::optional<ChartColorPalette> ChartModel::getCurrentColorPalette() const +{ + if (!usesColorPalette()) + { + SAL_WARN("chart2", "ChartModel::getCurrentColorPalette: no palette is in use"); + return std::nullopt; + } + + const std::shared_ptr<model::Theme> pTheme = getDocumentTheme(); + // when pTheme is null, ChartColorPaletteHelper uses a default theme + const ChartColorPaletteHelper aColorPaletteHelper(pTheme); + return aColorPaletteHelper.getColorPalette(getColorPaletteType(), getColorPaletteIndex()); +} + +void ChartModel::applyColorPaletteToDataSeries(const ChartColorPalette& rColorPalette) +{ + const rtl::Reference<Diagram> xDiagram = getFirstChartDiagram(); + const auto xDataSeriesArray = xDiagram->getDataSeries(); + for (size_t i = 0; i < xDataSeriesArray.size(); ++i) + { + const uno::Reference<beans::XPropertySet> xPropSet = xDataSeriesArray[i]; + const size_t nPaletteIndex = i % rColorPalette.size(); + xPropSet->setPropertyValue("FillStyle", uno::Any(drawing::FillStyle_SOLID)); + xPropSet->setPropertyValue("FillColor", uno::Any(rColorPalette[nPaletteIndex])); + } +} + +void ChartModel::onDocumentThemeChanged() +{ + if (const auto oColorPalette = getCurrentColorPalette()) + { + applyColorPaletteToDataSeries(*oColorPalette); + setModified(true); + } +} + } // namespace chart extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * diff --git a/chart2/source/tools/BaseColorScheme.cxx b/chart2/source/tools/BaseColorScheme.cxx new file mode 100644 index 000000000000..14e2e813cf55 --- /dev/null +++ b/chart2/source/tools/BaseColorScheme.cxx @@ -0,0 +1,43 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <BaseColorScheme.hxx> + +#include <cppuhelper/supportsservice.hxx> + +namespace chart +{ +// explicit +BaseColorScheme::BaseColorScheme() + : m_nNumberOfColors(0) +{ +} + +sal_Bool SAL_CALL BaseColorScheme::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence<OUString> SAL_CALL BaseColorScheme::getSupportedServiceNames() +{ + return { u"com.sun.star.chart2.ColorScheme"_ustr }; +} +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/ChartColorPaletteHelper.cxx b/chart2/source/tools/ChartColorPaletteHelper.cxx new file mode 100644 index 000000000000..9373bf242b70 --- /dev/null +++ b/chart2/source/tools/ChartColorPaletteHelper.cxx @@ -0,0 +1,199 @@ +/* -*- 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 <ChartColorPaletteHelper.hxx> +#include <ChartModel.hxx> +#include <sal/log.hxx> +#include <docmodel/uno/UnoTheme.hxx> +#include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> + +namespace chart +{ +constexpr tools::Long BORDER = ChartColorPaletteLayout::ItemBorder; +constexpr tools::Long SIZE = ChartColorPaletteLayout::ItemSize; + +namespace +{ +void decreaseLuminance(Color& color) +{ + const sal_uInt8 nLumDiff = std::floor(color.GetLuminance() * 0.40); + color.DecreaseLuminance(nLumDiff); +} +} // end of unnamed namespace + +ChartColorPaletteHelper::ChartColorPaletteHelper(const std::shared_ptr<model::Theme>& pTheme) +{ + createBasePaletteFromTheme(pTheme); +} + +void ChartColorPaletteHelper::createBasePaletteFromTheme( + const std::shared_ptr<model::Theme>& pTheme) +{ + if (pTheme) + { + mBasePalette[0] = pTheme->GetColor(model::ThemeColorType::Accent1); + mBasePalette[1] = pTheme->GetColor(model::ThemeColorType::Accent2); + mBasePalette[2] = pTheme->GetColor(model::ThemeColorType::Accent3); + mBasePalette[3] = pTheme->GetColor(model::ThemeColorType::Accent4); + mBasePalette[4] = pTheme->GetColor(model::ThemeColorType::Accent5); + mBasePalette[5] = pTheme->GetColor(model::ThemeColorType::Accent6); + } + else // default palette + { + SAL_WARN("chart2", + "ChartColorPaletteHelper::createBasePaletteFromTheme: no valid theme provided"); + mBasePalette[0] = Color::STRtoRGB(u"18A303"); + mBasePalette[1] = Color::STRtoRGB(u"0369A3"); + mBasePalette[2] = Color::STRtoRGB(u"A33E03"); + mBasePalette[3] = Color::STRtoRGB(u"8E03A3"); + mBasePalette[4] = Color::STRtoRGB(u"C99C00"); + mBasePalette[5] = Color::STRtoRGB(u"C9211E"); + } +} + +ChartColorPalette ChartColorPaletteHelper::getColorPalette(const ChartColorPaletteType eType, + const sal_uInt32 nIndex) const +{ + switch (eType) + { + case ChartColorPaletteType::Colorful: + return createColorfulPalette(nIndex); + case ChartColorPaletteType::Monochromatic: + return createMonotonicPalette(nIndex); + default: + SAL_WARN("chart2", + "ChartColorPaletteHelper::getColorPalette: unknown palette type requested"); + return mBasePalette; + } +} + +ChartColorPalette ChartColorPaletteHelper::createColorfulPalette(const sal_uInt32 nIndex) const +{ + if (nIndex >= ColorfulPaletteSize) + { + SAL_WARN("chart2", + "ChartColorPaletteHelper::createColorfulPalette: wrong index: " << nIndex); + return mBasePalette; + } + + switch (nIndex) + { + default: + case 0: + return mBasePalette; + case 1: + return createColorfulPaletteImpl(0, 2, 4); + case 2: + return createColorfulPaletteImpl(1, 3, 5); + case 3: + return createColorfulPaletteImpl(5, 4, 3); + } +} + +ChartColorPalette ChartColorPaletteHelper::createColorfulPaletteImpl(const size_t nIdx1, + const size_t nIdx2, + const size_t nIdx3) const +{ + ChartColorPalette colorPalette = { + mBasePalette[nIdx1], mBasePalette[nIdx2], mBasePalette[nIdx3], + mBasePalette[nIdx1], mBasePalette[nIdx2], mBasePalette[nIdx3], + }; + decreaseLuminance(colorPalette[3]); + decreaseLuminance(colorPalette[4]); + decreaseLuminance(colorPalette[5]); + return colorPalette; +} + +ChartColorPalette ChartColorPaletteHelper::createMonotonicPalette(sal_uInt32 nIndex) const +{ + if (nIndex >= mBasePalette.size()) + { + SAL_WARN("chart2", + "ChartColorPaletteHelper::createMonotonicPalette: wrong index: " << nIndex); + nIndex = 0; + } + + ChartColorPalette colorPalette = { + mBasePalette[nIndex], mBasePalette[nIndex], mBasePalette[nIndex], + mBasePalette[nIndex], mBasePalette[nIndex], mBasePalette[nIndex], + }; + + for (size_t i = 0; i < colorPalette.size(); ++i) + { + Color& color = colorPalette[i]; + sal_uInt16 nH, nS, nB; + color.RGBtoHSB(nH, nS, nB); + SAL_INFO("chart2", "createMonotonicPalette: i: " << i << ": before: nH: " << nH + << ", nS: " << nS << ", nB: " << nB); + nB += (static_cast<int>(i) - 2) * std::round(nB * 0.13); + nB = std::clamp(nB, sal_uInt16{ 0 }, sal_uInt16{ 100 }); + + if (i < 2) + nS += (2 - i) * std::round(nS * 0.013); + else if (i > 2) + nS = nS / (2 * (i - 2)); + nS = std::clamp(nS, sal_uInt16{ 0 }, sal_uInt16{ 100 }); + + SAL_INFO("chart2", "createMonotonicPalette: i: " << i << ": after: nH: " << nH + << ", nS: " << nS << ", nB: " << nB); + color = Color::HSBtoRGB(nH, nS, nB); + } + + return colorPalette; +} + +void ChartColorPaletteHelper::renderColorPalette(OutputDevice* pDev, + const tools::Rectangle& rDrawArea, + const ChartColorPalette& rColorSet, + const bool bDrawItemBorder) +{ + const Point aPosition = rDrawArea.GetPos(); + const Size aSize = rDrawArea.GetSize(); + + static constexpr Size aMin(BORDER * 6 + SIZE * ChartColorPaletteSize / 2, + BORDER * 5 + SIZE * 2); + + const tools::Long startX = (aSize.Width() / 2.0) - (aMin.Width() / 2.0) + BORDER; + const tools::Long startY = (aSize.Height() / 2.0) - (aMin.Height() / 2.0) + BORDER; + tools::Long x = BORDER; + static constexpr tools::Long y1 = BORDER; + static constexpr tools::Long y2 = y1 + SIZE + BORDER; + + pDev->SetFillColor(); + + if (bDrawItemBorder) + { + pDev->SetLineColor(COL_BLACK); + pDev->DrawRect(tools::Rectangle(aPosition, aSize)); + } + + for (sal_uInt32 i = 0; i < ChartColorPaletteSize / 2; i += 1) + { + pDev->SetFillColor(rColorSet[i]); + pDev->DrawRect(tools::Rectangle( + Point(aPosition.X() + x + startX, aPosition.Y() + startY + y1), Size(SIZE, SIZE))); + + pDev->SetFillColor(rColorSet[i + ChartColorPaletteSize / 2]); + pDev->DrawRect(tools::Rectangle( + Point(aPosition.X() + x + startX, aPosition.Y() + startY + y2), Size(SIZE, SIZE))); + + x += SIZE + BORDER; + } +} + +void ChartColorPaletteHelper::renderNoPalette(OutputDevice* pDev, const tools::Rectangle& rDrawArea) +{ + pDev->SetLineColor(COL_BLACK); + pDev->SetFillColor(Application::GetSettings().GetStyleSettings().GetFaceColor()); + pDev->DrawRect(rDrawArea); +} +} // end of namespace ::chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/ChartColorPalettes.cxx b/chart2/source/tools/ChartColorPalettes.cxx new file mode 100644 index 000000000000..dbe7697c7210 --- /dev/null +++ b/chart2/source/tools/ChartColorPalettes.cxx @@ -0,0 +1,59 @@ +/* -*- 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 <ChartColorPalettes.hxx> +#include <ChartColorPaletteHelper.hxx> +#include <vcl/event.hxx> + +namespace chart +{ +constexpr tools::Long BORDER = ChartColorPaletteLayout::ItemBorder; +constexpr tools::Long SIZE = ChartColorPaletteLayout::ItemSize; + +void ChartColorPalettes::insert(ChartColorPalette const& rColorSet) +{ + maColorSets.push_back(rColorSet); + InsertItem(maColorSets.size()); +} + +const ChartColorPalette* ChartColorPalettes::getPalette(const sal_uInt32 nItem) const +{ + if (maColorSets.size() > nItem) + { + return &maColorSets[nItem]; + } + return nullptr; +} + +void ChartColorPalettes::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + ValueSet::SetDrawingArea(pDrawingArea); + SetStyle(WB_TABSTOP | WB_DOUBLEBORDER); + SetItemWidth(BORDER * 6 + SIZE * ChartColorPaletteSize / 2); + SetItemHeight(BORDER * 5 + SIZE * 2); +} + +void ChartColorPalettes::UserDraw(const UserDrawEvent& rUserDrawEvent) +{ + vcl::RenderContext* pDev = rUserDrawEvent.GetRenderContext(); + const tools::Rectangle aDrawArea = rUserDrawEvent.GetRect(); + const sal_uInt16 nItemId = rUserDrawEvent.GetItemId(); + ChartColorPalette const& rColorSet = maColorSets[nItemId - 1]; + ChartColorPaletteHelper::renderColorPalette(pDev, aDrawArea, rColorSet, false); +} + +void ChartColorPalettes::StyleUpdated() +{ + SetFormat(); + Invalidate(); + ValueSet::StyleUpdated(); +} +} // end namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/ChartColorScheme.cxx b/chart2/source/tools/ChartColorScheme.cxx new file mode 100644 index 000000000000..816ecb422423 --- /dev/null +++ b/chart2/source/tools/ChartColorScheme.cxx @@ -0,0 +1,51 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartColorScheme.hxx> + +#include <cppuhelper/supportsservice.hxx> + +namespace chart +{ +// explicit +ChartColorScheme::ChartColorScheme(const ChartColorPalette& rPalette) + : BaseColorScheme() +{ + m_nNumberOfColors = rPalette.size(); + m_aColorSequence.realloc(m_nNumberOfColors); + sal_Int64* pColors = m_aColorSequence.getArray(); + for (size_t i = 0; i < rPalette.size(); ++i) + { + pColors[i] = static_cast<sal_Int32>(rPalette[i]); + } +} + +::sal_Int32 SAL_CALL ChartColorScheme::getColorByIndex(::sal_Int32 nIndex) +{ + assert(m_nNumberOfColors > 0); + return static_cast<sal_Int32>(m_aColorSequence[nIndex % m_nNumberOfColors]); +} + +OUString SAL_CALL ChartColorScheme::getImplementationName() +{ + return "com.sun.star.comp.chart2.ChartColorScheme"; +} +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/tools/ConfigColorScheme.cxx b/chart2/source/tools/ConfigColorScheme.cxx index 997c677d0145..b4bbd8dfa369 100644 --- a/chart2/source/tools/ConfigColorScheme.cxx +++ b/chart2/source/tools/ConfigColorScheme.cxx @@ -93,8 +93,8 @@ uno::Any ChartConfigItem::getProperty( const OUString & aPropertyName ) // explicit ConfigColorScheme::ConfigColorScheme( const Reference< uno::XComponentContext > & xContext ) : + BaseColorScheme(), m_xContext( xContext ), - m_nNumberOfColors( 0 ), m_bNeedsUpdate( true ) { } @@ -154,16 +154,6 @@ OUString SAL_CALL ConfigColorScheme::getImplementationName() return u"com.sun.star.comp.chart2.ConfigDefaultColorScheme"_ustr ; } -sal_Bool SAL_CALL ConfigColorScheme::supportsService( const OUString& rServiceName ) -{ - return cppu::supportsService(this, rServiceName); -} - -css::uno::Sequence< OUString > SAL_CALL ConfigColorScheme::getSupportedServiceNames() -{ - return { u"com.sun.star.chart2.ColorScheme"_ustr }; -} - } // namespace chart extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * diff --git a/chart2/source/view/main/SeriesPlotterContainer.cxx b/chart2/source/view/main/SeriesPlotterContainer.cxx index 8ad97c3d1717..e911ba389b21 100644 --- a/chart2/source/view/main/SeriesPlotterContainer.cxx +++ b/chart2/source/view/main/SeriesPlotterContainer.cxx @@ -33,6 +33,8 @@ #include <DiagramHelper.hxx> #include <Axis.hxx> #include <AxisIndexDefines.hxx> +#include <ConfigColorScheme.hxx> +#include <ChartColorScheme.hxx> #include <DataSeriesHelper.hxx> #include <ExplicitCategoriesProvider.hxx> #include <unonames.hxx> @@ -185,7 +187,11 @@ void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter(ChartModel& rChart // - add plotter to coordinate systems //iterate through all coordinate systems - uno::Reference<XColorScheme> xColorScheme(xDiagram->getDefaultColorScheme()); + uno::Reference<XColorScheme> xColorScheme; + if (!rChartModel.usesColorPalette()) + xColorScheme = xDiagram->getDefaultColorScheme(); + else + xColorScheme = new ChartColorScheme(*rChartModel.getCurrentColorPalette()); auto aCooSysList = xDiagram->getBaseCoordinateSystems(); sal_Int32 nGlobalSeriesIndex = 0; //for automatic symbols for (std::size_t nCS = 0; nCS < aCooSysList.size(); ++nCS) diff --git a/chart2/uiconfig/ui/chartcolorpalettepopup.ui b/chart2/uiconfig/ui/chartcolorpalettepopup.ui new file mode 100644 index 000000000000..0bb803ae9a5b --- /dev/null +++ b/chart2/uiconfig/ui/chartcolorpalettepopup.ui @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.40.0 --> +<interface domain="chart"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkPopover" id="ColorPaletteWindow"> + <property name="can-focus">False</property> + <child> + <object class="GtkBox" id="container"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <!-- n-columns=1 n-rows=4 --> + <object class="GtkGrid" id="grid1"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="border-width">6</property> + <property name="row-spacing">3</property> + <property name="column-spacing">6</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="margin-bottom">1</property> + <property name="label" translatable="yes" context="chartcolorpalettepopup|colorfulwin">Colorful</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + <accessibility> + <relation type="label-for" target="colorful_palettes"/> + </accessibility> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="colorfulwin"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkDrawingArea" id="colorful_palettes"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <accessibility> + <relation type="labelled-by" target="label1"/> + </accessibility> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="margin-top">6</property> + <property name="margin-bottom">1</property> + <property name="label" translatable="yes" context="chartcolorpalettepopup|monochromaticwin">Monochromatic</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + <accessibility> + <relation type="label-for" target="monochromatic_palettes"/> + </accessibility> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">2</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="monochromaticwin"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkDrawingArea" id="monochromatic_palettes"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <accessibility> + <relation type="labelled-by" target="label2"/> + </accessibility> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + </object> +</interface> diff --git a/chart2/uiconfig/ui/sidebarcolors.ui b/chart2/uiconfig/ui/sidebarcolors.ui new file mode 100644 index 000000000000..95c882ecc6ce --- /dev/null +++ b/chart2/uiconfig/ui/sidebarcolors.ui @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.40.0 --> +<interface domain="chart"> + <requires lib="gtk+" version="3.20"/> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="ChartColorsPanel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid1"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="border-width">6</property> + <property name="row-spacing">3</property> + <property name="column-spacing">6</property> + <child> + <object class="GtkToolbar" id="colorpalettetype"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="valign">start</property> + <property name="toolbar-style">icons</property> + <property name="show-arrow">False</property> + <property name="icon_size">2</property> + <child> + <object class="GtkMenuToolButton" id=".uno:ChartColorPalette"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes" context="sidebarcellappearance|bordertype|tooltip_text">Allow to select a color palette to apply to current chart data series.</property> + <property name="halign">start</property> + <property name="valign">start</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="homogeneous">True</property> + </packing> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="colorpalettetype-atkobject"> + <property name="AtkObject::accessible-name" translatable="yes" context="sidebarcellappearance|cellbordertype-atkobject">Border Style</property> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + </object> +</interface> diff --git a/include/svl/hint.hxx b/include/svl/hint.hxx index 522da6126435..3e46ea0c9ec9 100644 --- a/include/svl/hint.hxx +++ b/include/svl/hint.hxx @@ -36,6 +36,7 @@ enum class SfxHintId { Deinitializing, ModeChanged, ColorsChanged, + ThemeColorsChanged, LanguageChanged, RedlineChanged, DocumentRepair, @@ -252,6 +253,7 @@ inline std::basic_ostream<charT, traits> & operator <<( case SfxHintId::Deinitializing: return stream << "Deinitializing"; case SfxHintId::ModeChanged: return stream << "ModeChanged"; case SfxHintId::ColorsChanged: return stream << "ColorsChanged"; + case SfxHintId::ThemeColorsChanged: return stream << "ThemeColorsChanged"; case SfxHintId::LanguageChanged: return stream << "LanguageChanged"; case SfxHintId::RedlineChanged: return stream << "RedlineChanged"; case SfxHintId::DocumentRepair: return stream << "DocumentRepair"; diff --git a/include/svx/ChartColorPaletteType.hxx b/include/svx/ChartColorPaletteType.hxx new file mode 100644 index 000000000000..30f6844ee876 --- /dev/null +++ b/include/svx/ChartColorPaletteType.hxx @@ -0,0 +1,36 @@ +/* -*- 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/. + */ + +#pragma once + +#include <sal/types.h> +#include <tools/long.hxx> +#include <tools/color.hxx> +#include <array> + +constexpr OUString sUnoChartColorPalette = u".uno:ChartColorPalette"_ustr; + +constexpr size_t ChartColorPaletteSize = 6; + +typedef std::array<Color, ChartColorPaletteSize> ChartColorPalette; + +enum class ChartColorPaletteType : sal_Int32 +{ + Unknown = -1, + Colorful = 0, + Monochromatic = 1, +}; + +struct ChartColorPaletteLayout +{ + static constexpr tools::Long ItemSize = 24; + static constexpr tools::Long ItemBorder = 4; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu index afda5d02e4f9..89fbd5d39931 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu @@ -2043,6 +2043,17 @@ <value>distributebar</value> </prop> </node> + <node oor:name="ChartColorPaletteControl" oor:op="replace"> + <prop oor:name="Command"> + <value>.uno:ChartColorPalette</value> + </prop> + <prop oor:name="Module"> + <value/> + </prop> + <prop oor:name="Controller"> + <value>com.sun.star.comp.chart2.ChartColorPaletteControl</value> + </prop> + </node> </node> <node oor:name="StatusBar"> <node oor:name="c5" oor:op="replace"> diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu index 1823fba79cce..c29130edd381 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/Sidebar.xcu @@ -2019,6 +2019,36 @@ </prop> </node> + <node oor:name="ChartColorsPanel" oor:op="replace"> + <prop oor:name="Title" oor:type="xs:string"> + <value xml:lang="en-US">Colors</value> + </prop> + <prop oor:name="Id" oor:type="xs:string"> + <value>ChartColorsPanel</value> + </prop> + <prop oor:name="DeckId" oor:type="xs:string"> + <value>PropertyDeck</value> + </prop> + <prop oor:name="DefaultMenuCommand"> + <value>.uno:ChartProperties</value> + </prop> + <prop oor:name="ContextList"> + <value oor:separator=";"> + Chart, Chart, visible ; + Chart, Series, visible ; + </value> + </prop> + <prop oor:name="ImplementationURL" oor:type="xs:string"> + <value>private:resource/toolpanel/ChartPanelFactory/ColorsPanel</value> + </prop> + <prop oor:name="OrderIndex" oor:type="xs:int"> + <value>8</value> + </prop> + <prop oor:name="WantsAWT" oor:type="xs:boolean"> + <value>false</value> + </prop> + </node> + <node oor:name="ChartAreaPanel" oor:op="replace"> <prop oor:name="Title" oor:type="xs:string"> <value xml:lang="en-US">Area</value> diff --git a/sc/source/ui/theme/ThemeColorChanger.cxx b/sc/source/ui/theme/ThemeColorChanger.cxx index 0654f9bc498e..8745459d37a5 100644 --- a/sc/source/ui/theme/ThemeColorChanger.cxx +++ b/sc/source/ui/theme/ThemeColorChanger.cxx @@ -34,6 +34,7 @@ #include <undoblk.hxx> #include <SparklineGroup.hxx> #include <SparklineList.hxx> +#include <sfx2/app.hxx> #include <undo/UndoThemeChange.hxx> @@ -342,6 +343,7 @@ void ThemeColorChanger::doApply(std::shared_ptr<model::ColorSet> const& pColorSe changeSparklines(m_rDocShell, *pColorSet); changeThemeColorInTheDocModel(m_rDocShell, pColorSet); + m_rDocShell.Broadcast(SfxHint(SfxHintId::ThemeColorsChanged)); if (bUndo) { diff --git a/sd/source/core/ThemeColorChanger.cxx b/sd/source/core/ThemeColorChanger.cxx index 14b8f6e0517f..d8b7b0239c92 100644 --- a/sd/source/core/ThemeColorChanger.cxx +++ b/sd/source/core/ThemeColorChanger.cxx @@ -184,6 +184,8 @@ void ThemeColorChanger::doApply(std::shared_ptr<model::ColorSet> const& pColorSe changeThemeColors(mpDocShell, pCurrentPage, pColorSet); } + mpDocShell->Broadcast(SfxHint(SfxHintId::ThemeColorsChanged)); + pUndoManager->LeaveListAction(); } diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index c67f9c6d3495..6eb83feda1b5 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -1938,6 +1938,9 @@ sal_Int64 SAL_CALL SdXImpressDocument::getSomething( const css::uno::Sequence< s if (comphelper::isUnoTunnelId<SdrModel>(rIdentifier)) return comphelper::getSomething_cast(mpDoc); + if (comphelper::isUnoTunnelId<SfxObjectShell>(rIdentifier)) + return comphelper::getSomething_cast(mpDocShell); + return comphelper::getSomethingImpl(rIdentifier, this, comphelper::FallbackToGetSomethingOf<SfxBaseModel>{}); } diff --git a/static/CustomTarget_emscripten_fs_image.mk b/static/CustomTarget_emscripten_fs_image.mk index 145157a96669..8b854a3f06e5 100644 --- a/static/CustomTarget_emscripten_fs_image.mk +++ b/static/CustomTarget_emscripten_fs_image.mk @@ -1431,6 +1431,7 @@ gb_emscripten_fs_image_files += \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/toolbar/toolbar.xml \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/3dviewdialog.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/attributedialog.ui \ + $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/chartcolorpalettepopup.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/chardialog.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/chartdatadialog.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/charttypedialog.ui \ @@ -1446,6 +1447,7 @@ gb_emscripten_fs_image_files += \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/inserttitledlg.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/paradialog.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/sidebaraxis.ui \ + $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/sidebarcolors.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/sidebarelements.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/sidebarerrorbar.ui \ $(INSTROOT)/$(LIBO_SHARE_FOLDER)/config/soffice.cfg/modules/schart/ui/sidebarseries.ui \ diff --git a/sw/source/core/model/ThemeColorChanger.cxx b/sw/source/core/model/ThemeColorChanger.cxx index c61ea96b2a5a..d0560ac3ce9c 100644 --- a/sw/source/core/model/ThemeColorChanger.cxx +++ b/sw/source/core/model/ThemeColorChanger.cxx @@ -441,6 +441,8 @@ void ThemeColorChanger::doApply(std::shared_ptr<model::ColorSet> const& pColorSe aModelTraverser.addNodeHandler(pHandler); aModelTraverser.traverse(); + mpDocSh->Broadcast(SfxHint(SfxHintId::ThemeColorsChanged)); + pDocument->GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr); } diff --git a/vcl/jsdialog/enabled.cxx b/vcl/jsdialog/enabled.cxx index 065ec9896f35..8a817ad8833f 100644 --- a/vcl/jsdialog/enabled.cxx +++ b/vcl/jsdialog/enabled.cxx @@ -355,6 +355,8 @@ constexpr auto PopupList { u"modules/scalc/ui/filtersubdropdown.ui" }, { u"modules/scalc/ui/floatingborderstyle.ui" }, { u"modules/scalc/ui/floatinglinestyle.ui" }, + // schart + { u"modules/schart/ui/chartcolorpalettepopup.ui" }, // svt { u"svt/ui/datewindow.ui" }, { u"svt/ui/linewindow.ui" }, @@ -392,6 +394,7 @@ constexpr auto SidebarList { u"modules/scalc/ui/sidebarnumberformat.ui" }, // schart { u"modules/schart/ui/sidebaraxis.ui" }, + { u"modules/schart/ui/sidebarcolors.ui" }, { u"modules/schart/ui/sidebarelements.ui" }, { u"modules/schart/ui/sidebarerrorbar.ui" }, { u"modules/schart/ui/sidebarseries.ui" }, @@ -565,6 +568,7 @@ bool isBuilderEnabledForMenu(std::u16string_view rUIFile) bool isBuilderEnabledForSidebar(std::u16string_view rUIFile) { return isInMap(SidebarList, rUIFile); + } bool isBuilderEnabledForNavigator(std::u16string_view rUIFile)