/* -*- 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 <vcl/svapp.hxx>
#include "ChartColorsPanel.hxx"
#include "ChartColorPaletteControl.hxx"
#include <ChartColorPaletteHelper.hxx>
#include <ChartController.hxx>
#include <ChartModel.hxx>
#include <DataSeries.hxx>
#include <Diagram.hxx>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <sfx2/weldutils.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());
uno::Reference<view::XSelectionSupplier> xSelectionSupplier(xController, uno::UNO_QUERY);
if (!xSelectionSupplier.is())
return {};
uno::Any aAny = xSelectionSupplier->getSelection();
if (!aAny.hasValue())
{
// if no selection, default to diagram wall so sidebar can show some editable properties
if (auto* pController = dynamic_cast<ChartController*>(xController.get()))
{
pController->select(
uno::Any(ObjectIdentifier::createClassifiedIdentifier(OBJECTTYPE_PAGE, u"")));
xSelectionSupplier
= uno::Reference<css::view::XSelectionSupplier>(xController, uno::UNO_QUERY);
if (xSelectionSupplier.is())
aAny = xSelectionSupplier->getSelection();
}
if (!aAny.hasValue())
return {};
}
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 createDiagramSnapshot() override;
void restoreOriginalDiagram() override;
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;
rtl::Reference<Diagram> mxDiagramSnapshot;
};
ColorPaletteWrapper::ColorPaletteWrapper(rtl::Reference<ChartModel> xModel,
ChartColorPaletteControl* pControl)
: mxModel(std::move(xModel))
, mpControl(pControl)
{
}
void ColorPaletteWrapper::updateModel(const rtl::Reference<ChartModel>& xModel)
{
mxModel = xModel;
}
void ColorPaletteWrapper::updateData() const
{
frame::FeatureStateEvent aEvent;
aEvent.FeatureURL.Complete = sUnoChartColorPalette;
aEvent.IsEnabled = true;
if (mpControl)
mpControl->statusChanged(aEvent);
}
void ColorPaletteWrapper::createDiagramSnapshot()
{
const rtl::Reference<Diagram> xDiagram = mxModel->getFirstChartDiagram();
mxDiagramSnapshot = new ::chart::Diagram(*xDiagram);
}
void ColorPaletteWrapper::restoreOriginalDiagram()
{
if (mxDiagramSnapshot)
{
const rtl::Reference<Diagram> xDiagram = new ::chart::Diagram(*mxDiagramSnapshot);
// setDiagram didn't make a copy internally, so we need to pass a copy or
// the diagram snapshot would be modified on preview
mxModel->setFirstDiagram(xDiagram);
}
}
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);
if (aCID.isEmpty())
return;
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: */
↑ V1001 The 'aAny' variable is assigned but is not used by the end of the function.