summaryrefslogtreecommitdiffstats
path: root/chart2/source/controller/sidebar/ChartErrorBarPanel.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/controller/sidebar/ChartErrorBarPanel.cxx')
-rw-r--r--chart2/source/controller/sidebar/ChartErrorBarPanel.cxx425
1 files changed, 425 insertions, 0 deletions
diff --git a/chart2/source/controller/sidebar/ChartErrorBarPanel.cxx b/chart2/source/controller/sidebar/ChartErrorBarPanel.cxx
new file mode 100644
index 000000000..e86fdf0fe
--- /dev/null
+++ b/chart2/source/controller/sidebar/ChartErrorBarPanel.cxx
@@ -0,0 +1,425 @@
+/* -*- 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/chart/ErrorBarStyle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include "ChartErrorBarPanel.hxx"
+#include <ChartController.hxx>
+#include <ChartModel.hxx>
+#include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+
+
+using namespace css;
+using namespace css::uno;
+
+namespace chart::sidebar {
+
+namespace {
+
+enum class ErrorBarDirection
+{
+ POSITIVE,
+ NEGATIVE
+};
+
+css::uno::Reference<css::beans::XPropertySet> getErrorBarPropSet(
+ const rtl::Reference<::chart::ChartModel>& xModel, const OUString& rCID)
+{
+ return ObjectIdentifier::getObjectPropertySet(rCID, xModel);
+}
+
+bool showPositiveError(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return false;
+
+ css::uno::Any aAny = xPropSet->getPropertyValue("ShowPositiveError");
+
+ if (!aAny.hasValue())
+ return false;
+
+ bool bShow = false;
+ aAny >>= bShow;
+ return bShow;
+}
+
+bool showNegativeError(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return false;
+
+ css::uno::Any aAny = xPropSet->getPropertyValue("ShowNegativeError");
+
+ if (!aAny.hasValue())
+ return false;
+
+ bool bShow = false;
+ aAny >>= bShow;
+ return bShow;
+}
+
+void setShowPositiveError(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID, bool bShow)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ xPropSet->setPropertyValue("ShowPositiveError", css::uno::Any(bShow));
+}
+
+void setShowNegativeError(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID, bool bShow)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ xPropSet->setPropertyValue("ShowNegativeError", css::uno::Any(bShow));
+}
+
+struct ErrorBarTypeMap
+{
+ sal_Int32 nPos;
+ sal_Int32 nApi;
+};
+
+ErrorBarTypeMap const aErrorBarType[] = {
+ { 0, css::chart::ErrorBarStyle::ABSOLUTE },
+ { 1, css::chart::ErrorBarStyle::RELATIVE },
+ { 2, css::chart::ErrorBarStyle::FROM_DATA },
+ { 3, css::chart::ErrorBarStyle::STANDARD_DEVIATION },
+ { 4, css::chart::ErrorBarStyle::STANDARD_ERROR },
+ { 5, css::chart::ErrorBarStyle::VARIANCE},
+ { 6, css::chart::ErrorBarStyle::ERROR_MARGIN },
+};
+
+sal_Int32 getTypePos(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return 0;
+
+ css::uno::Any aAny = xPropSet->getPropertyValue("ErrorBarStyle");
+
+ if (!aAny.hasValue())
+ return 0;
+
+ sal_Int32 nApi = 0;
+ aAny >>= nApi;
+
+ for (ErrorBarTypeMap const & i : aErrorBarType)
+ {
+ if (i.nApi == nApi)
+ return i.nPos;
+ }
+
+ return 0;
+}
+
+void setTypePos(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID, sal_Int32 nPos)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ sal_Int32 nApi = 0;
+ for (ErrorBarTypeMap const & i : aErrorBarType)
+ {
+ if (i.nPos == nPos)
+ nApi = i.nApi;
+ }
+
+ xPropSet->setPropertyValue("ErrorBarStyle", css::uno::Any(nApi));
+}
+
+double getValue(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID, ErrorBarDirection eDir)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return 0;
+
+ OUString aName = "PositiveError";
+ if (eDir == ErrorBarDirection::NEGATIVE)
+ aName = "NegativeError";
+
+ css::uno::Any aAny = xPropSet->getPropertyValue(aName);
+
+ if (!aAny.hasValue())
+ return 0;
+
+ double nVal = 0;
+ aAny >>= nVal;
+
+ return nVal;
+}
+
+void setValue(const rtl::Reference<::chart::ChartModel>& xModel,
+ const OUString& rCID, double nVal, ErrorBarDirection eDir)
+{
+ css::uno::Reference<css::beans::XPropertySet> xPropSet =
+ getErrorBarPropSet(xModel, rCID);
+
+ if (!xPropSet.is())
+ return;
+
+ OUString aName = "PositiveError";
+ if (eDir == ErrorBarDirection::NEGATIVE)
+ aName = "NegativeError";
+
+ xPropSet->setPropertyValue(aName, css::uno::Any(nVal));
+}
+
+OUString getCID(const rtl::Reference<::chart::ChartModel>& xModel)
+{
+ css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
+ css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
+ if (!xSelectionSupplier.is())
+ return OUString();
+
+ uno::Any aAny = xSelectionSupplier->getSelection();
+ assert(aAny.hasValue());
+ OUString aCID;
+ aAny >>= aCID;
+#if defined DBG_UTIL && !defined NDEBUG
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType != OBJECTTYPE_DATA_ERRORS_X &&
+ eType != OBJECTTYPE_DATA_ERRORS_Y &&
+ eType != OBJECTTYPE_DATA_ERRORS_Z)
+ SAL_WARN("chart2","Selected item is not an error bar");
+
+#endif
+
+ return aCID;
+}
+
+}
+
+ChartErrorBarPanel::ChartErrorBarPanel(weld::Widget* pParent, ChartController* pController)
+ : PanelLayout(pParent, "ChartErrorBarPanel", "modules/schart/ui/sidebarerrorbar.ui")
+ , mxRBPosAndNeg(m_xBuilder->weld_radio_button("radiobutton_positive_negative"))
+ , mxRBPos(m_xBuilder->weld_radio_button("radiobutton_positive"))
+ , mxRBNeg(m_xBuilder->weld_radio_button("radiobutton_negative"))
+ , mxLBType(m_xBuilder->weld_combo_box("comboboxtext_type"))
+ , mxMFPos(m_xBuilder->weld_spin_button("spinbutton_pos"))
+ , mxMFNeg(m_xBuilder->weld_spin_button("spinbutton_neg"))
+ , mxModel(pController->getChartModel())
+ , mxListener(new ChartSidebarModifyListener(this))
+ , mbModelValid(true)
+{
+ Initialize();
+}
+
+ChartErrorBarPanel::~ChartErrorBarPanel()
+{
+ doUpdateModel(nullptr);
+
+ mxRBPosAndNeg.reset();
+ mxRBPos.reset();
+ mxRBNeg.reset();
+
+ mxLBType.reset();
+
+ mxMFPos.reset();
+ mxMFNeg.reset();
+}
+
+void ChartErrorBarPanel::Initialize()
+{
+ mxModel->addModifyListener(mxListener);
+ mxRBNeg->set_active(false);
+ mxRBPos->set_active(false);
+ mxRBPosAndNeg->set_active(false);
+
+ updateData();
+
+ Link<weld::Toggleable&,void> aLink = LINK(this, ChartErrorBarPanel, RadioBtnHdl);
+ mxRBPosAndNeg->connect_toggled(aLink);
+ mxRBPos->connect_toggled(aLink);
+ mxRBNeg->connect_toggled(aLink);
+
+ mxLBType->connect_changed(LINK(this, ChartErrorBarPanel, ListBoxHdl));
+
+ Link<weld::SpinButton&,void> aLink2 = LINK(this, ChartErrorBarPanel, NumericFieldHdl);
+ mxMFPos->connect_value_changed(aLink2);
+ mxMFNeg->connect_value_changed(aLink2);
+}
+
+void ChartErrorBarPanel::updateData()
+{
+ if (!mbModelValid)
+ return;
+
+ OUString aCID = getCID(mxModel);
+ ObjectType eType = ObjectIdentifier::getObjectType(aCID);
+ if (eType != OBJECTTYPE_DATA_ERRORS_X &&
+ eType != OBJECTTYPE_DATA_ERRORS_Y &&
+ eType != OBJECTTYPE_DATA_ERRORS_Z)
+ return;
+
+ bool bPos = showPositiveError(mxModel, aCID);
+ bool bNeg = showNegativeError(mxModel, aCID);
+
+ SolarMutexGuard aGuard;
+
+ if (bPos && bNeg)
+ mxRBPosAndNeg->set_active(true);
+ else if (bPos)
+ mxRBPos->set_active(true);
+ else if (bNeg)
+ mxRBNeg->set_active(true);
+
+ sal_Int32 nTypePos = getTypePos(mxModel, aCID);
+ mxLBType->set_active(nTypePos);
+
+ if (nTypePos <= 1)
+ {
+ if (bPos)
+ mxMFPos->set_sensitive(true);
+ else
+ mxMFPos->set_sensitive(false);
+
+ if (bNeg)
+ mxMFNeg->set_sensitive(true);
+ else
+ mxMFNeg->set_sensitive(false);
+
+ double nValPos = getValue(mxModel, aCID, ErrorBarDirection::POSITIVE);
+ double nValNeg = getValue(mxModel, aCID, ErrorBarDirection::NEGATIVE);
+
+ mxMFPos->set_value(nValPos);
+ mxMFNeg->set_value(nValNeg);
+ }
+ else
+ {
+ mxMFPos->set_sensitive(false);
+ mxMFNeg->set_sensitive(false);
+ }
+}
+
+std::unique_ptr<PanelLayout> ChartErrorBarPanel::Create (
+ weld::Widget* pParent,
+ ChartController* pController)
+{
+ if (pParent == nullptr)
+ throw lang::IllegalArgumentException("no parent Window given to ChartErrorBarPanel::Create", nullptr, 0);
+ return std::make_unique<ChartErrorBarPanel>(pParent, pController);
+}
+
+void ChartErrorBarPanel::DataChanged(const DataChangedEvent& rEvent)
+{
+ PanelLayout::DataChanged(rEvent);
+ updateData();
+}
+
+void ChartErrorBarPanel::HandleContextChange(
+ const vcl::EnumContext& )
+{
+ updateData();
+}
+
+void ChartErrorBarPanel::NotifyItemUpdate(
+ sal_uInt16 /*nSID*/,
+ SfxItemState /*eState*/,
+ const SfxPoolItem* /*pState*/ )
+{
+}
+
+void ChartErrorBarPanel::modelInvalid()
+{
+ mbModelValid = false;
+}
+
+void ChartErrorBarPanel::doUpdateModel(rtl::Reference<::chart::ChartModel> xModel)
+{
+ if (mbModelValid)
+ {
+ mxModel->removeModifyListener(mxListener);
+ }
+
+ mxModel = xModel;
+ mbModelValid = mxModel.is();
+
+ if (!mbModelValid)
+ return;
+
+ mxModel->addModifyListener(mxListener);
+}
+
+void ChartErrorBarPanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
+{
+ ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
+ assert(!xModel || pModel);
+ doUpdateModel(pModel);
+}
+
+IMPL_LINK_NOARG(ChartErrorBarPanel, RadioBtnHdl, weld::Toggleable&, void)
+{
+ OUString aCID = getCID(mxModel);
+ bool bPos = mxRBPosAndNeg->get_active() || mxRBPos->get_active();
+ bool bNeg = mxRBPosAndNeg->get_active() || mxRBNeg->get_active();
+
+ setShowPositiveError(mxModel, aCID, bPos);
+ setShowNegativeError(mxModel, aCID, bNeg);
+}
+
+IMPL_LINK_NOARG(ChartErrorBarPanel, ListBoxHdl, weld::ComboBox&, void)
+{
+ OUString aCID = getCID(mxModel);
+ sal_Int32 nPos = mxLBType->get_active();
+
+ setTypePos(mxModel, aCID, nPos);
+}
+
+IMPL_LINK(ChartErrorBarPanel, NumericFieldHdl, weld::SpinButton&, rMetricField, void)
+{
+ OUString aCID = getCID(mxModel);
+ double nVal = rMetricField.get_value();
+ if (&rMetricField == mxMFPos.get())
+ setValue(mxModel, aCID, nVal, ErrorBarDirection::POSITIVE);
+ else if (&rMetricField == mxMFNeg.get())
+ setValue(mxModel, aCID, nVal, ErrorBarDirection::NEGATIVE);
+}
+
+} // end of namespace ::chart::sidebar
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */