summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/oox/SparklineFragment.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/oox/SparklineFragment.cxx')
-rw-r--r--sc/source/filter/oox/SparklineFragment.cxx273
1 files changed, 273 insertions, 0 deletions
diff --git a/sc/source/filter/oox/SparklineFragment.cxx b/sc/source/filter/oox/SparklineFragment.cxx
new file mode 100644
index 000000000..bb341d4a8
--- /dev/null
+++ b/sc/source/filter/oox/SparklineFragment.cxx
@@ -0,0 +1,273 @@
+/* -*- 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 <SparklineFragment.hxx>
+#include <oox/core/contexthandler.hxx>
+#include <oox/token/tokens.hxx>
+#include <oox/token/namespaces.hxx>
+#include <oox/helper/helper.hxx>
+#include <oox/helper/attributelist.hxx>
+#include <document.hxx>
+#include <rangeutl.hxx>
+#include <Sparkline.hxx>
+#include <themebuffer.hxx>
+
+using ::oox::core::ContextHandlerRef;
+
+namespace oox::xls
+{
+namespace
+{
+// TODO: deduplicate with importOOXColor
+::Color getColor(const AttributeList& rAttribs, ThemeBuffer const& rThemeBuffer)
+{
+ if (rAttribs.hasAttribute(XML_rgb))
+ {
+ return ::Color(ColorAlpha, rAttribs.getIntegerHex(XML_rgb, sal_Int32(API_RGB_TRANSPARENT)));
+ }
+ else if (rAttribs.hasAttribute(XML_theme))
+ {
+ sal_uInt32 nThemeIndex = rAttribs.getUnsigned(XML_theme, 0);
+
+ // Excel has a bug in the mapping of index 0, 1, 2 and 3.
+ if (nThemeIndex == 0)
+ nThemeIndex = 1;
+ else if (nThemeIndex == 1)
+ nThemeIndex = 0;
+ else if (nThemeIndex == 2)
+ nThemeIndex = 3;
+ else if (nThemeIndex == 3)
+ nThemeIndex = 2;
+
+ ::Color aColor = rThemeBuffer.getColorByIndex(nThemeIndex);
+ double nTint = rAttribs.getDouble(XML_tint, 0.0);
+
+ if (nTint > 0.0)
+ aColor.ApplyTintOrShade(nTint * 10000);
+ return aColor;
+ }
+
+ return ::Color();
+}
+
+void addColorsToSparklineAttributes(sc::SparklineAttributes& rAttributes, sal_Int32 nElement,
+ const AttributeList& rAttribs, ThemeBuffer& rThemeBuffer)
+{
+ switch (nElement)
+ {
+ case XLS14_TOKEN(colorSeries):
+ rAttributes.setColorSeries(getColor(rAttribs, rThemeBuffer));
+ break;
+ case XLS14_TOKEN(colorNegative):
+ rAttributes.setColorNegative(getColor(rAttribs, rThemeBuffer));
+ break;
+ case XLS14_TOKEN(colorAxis):
+ rAttributes.setColorAxis(getColor(rAttribs, rThemeBuffer));
+ break;
+ case XLS14_TOKEN(colorMarkers):
+ rAttributes.setColorMarkers(getColor(rAttribs, rThemeBuffer));
+ break;
+ case XLS14_TOKEN(colorFirst):
+ rAttributes.setColorFirst(getColor(rAttribs, rThemeBuffer));
+ break;
+ case XLS14_TOKEN(colorLast):
+ rAttributes.setColorLast(getColor(rAttribs, rThemeBuffer));
+ break;
+ case XLS14_TOKEN(colorHigh):
+ rAttributes.setColorHigh(getColor(rAttribs, rThemeBuffer));
+ break;
+ case XLS14_TOKEN(colorLow):
+ rAttributes.setColorLow(getColor(rAttribs, rThemeBuffer));
+ break;
+ default:
+ break;
+ }
+}
+
+sc::SparklineType parseSparklineType(std::u16string_view rString)
+{
+ if (rString == u"column")
+ return sc::SparklineType::Column;
+ else if (rString == u"stacked")
+ return sc::SparklineType::Stacked;
+ return sc::SparklineType::Line;
+}
+
+sc::DisplayEmptyCellsAs parseDisplayEmptyCellsAs(std::u16string_view rString)
+{
+ if (rString == u"span")
+ return sc::DisplayEmptyCellsAs::Span;
+ else if (rString == u"gap")
+ return sc::DisplayEmptyCellsAs::Gap;
+ return sc::DisplayEmptyCellsAs::Zero;
+}
+
+sc::AxisType parseAxisType(std::u16string_view rString)
+{
+ if (rString == u"group")
+ return sc::AxisType::Group;
+ else if (rString == u"custom")
+ return sc::AxisType::Custom;
+ return sc::AxisType::Individual;
+}
+
+void addAttributesToSparklineAttributes(sc::SparklineAttributes& rSparklineAttributes,
+ const AttributeList& rAttribs)
+{
+ auto oManualMax = rAttribs.getDouble(XML_manualMax);
+ auto oManualMin = rAttribs.getDouble(XML_manualMin);
+
+ rSparklineAttributes.setLineWeight(rAttribs.getDouble(XML_lineWeight, 0.75));
+
+ OUString sType = rAttribs.getString(XML_type, "line");
+ rSparklineAttributes.setType(parseSparklineType(sType));
+
+ rSparklineAttributes.setDateAxis(rAttribs.getBool(XML_dateAxis, false));
+
+ OUString sDisplayEmptyCellsAs = rAttribs.getString(XML_displayEmptyCellsAs, "zero");
+ rSparklineAttributes.setDisplayEmptyCellsAs(parseDisplayEmptyCellsAs(sDisplayEmptyCellsAs));
+
+ rSparklineAttributes.setMarkers(rAttribs.getBool(XML_markers, false));
+ rSparklineAttributes.setHigh(rAttribs.getBool(XML_high, false));
+ rSparklineAttributes.setLow(rAttribs.getBool(XML_low, false));
+ rSparklineAttributes.setFirst(rAttribs.getBool(XML_first, false));
+ rSparklineAttributes.setLast(rAttribs.getBool(XML_last, false));
+ rSparklineAttributes.setNegative(rAttribs.getBool(XML_negative, false));
+ rSparklineAttributes.setDisplayXAxis(rAttribs.getBool(XML_displayXAxis, false));
+ rSparklineAttributes.setDisplayHidden(rAttribs.getBool(XML_displayHidden, false));
+
+ OUString sMinAxisType = rAttribs.getString(XML_minAxisType, "individual");
+ rSparklineAttributes.setMinAxisType(parseAxisType(sMinAxisType));
+
+ OUString sMaxAxisType = rAttribs.getString(XML_maxAxisType, "individual");
+ rSparklineAttributes.setMaxAxisType(parseAxisType(sMaxAxisType));
+
+ rSparklineAttributes.setRightToLeft(rAttribs.getBool(XML_rightToLeft, false));
+
+ if (rSparklineAttributes.getMaxAxisType() == sc::AxisType::Custom)
+ rSparklineAttributes.setManualMax(oManualMax.get());
+ if (rSparklineAttributes.getMinAxisType() == sc::AxisType::Custom)
+ rSparklineAttributes.setManualMin(oManualMin.get());
+}
+
+} // end anonymous namespace
+
+SparklineGroupsContext::SparklineGroupsContext(WorksheetContextBase& rFragment)
+ : WorksheetContextBase(rFragment)
+{
+}
+
+ContextHandlerRef SparklineGroupsContext::onCreateContext(sal_Int32 nElement,
+ const AttributeList& rAttribs)
+{
+ switch (nElement)
+ {
+ case XLS14_TOKEN(sparklineGroup):
+ {
+ auto& rLastGroup = m_aSparklineGroups.emplace_back();
+ auto& rSparklineAttributes = rLastGroup.getSparklineGroup()->getAttributes();
+ addAttributesToSparklineAttributes(rSparklineAttributes, rAttribs);
+ OUString sGUID = rAttribs.getString(XR2_TOKEN(uid), OUString());
+ tools::Guid aGuid(OUStringToOString(sGUID, RTL_TEXTENCODING_ASCII_US));
+ rLastGroup.getSparklineGroup()->setID(aGuid);
+ return this;
+ }
+ case XLS14_TOKEN(colorSeries):
+ case XLS14_TOKEN(colorNegative):
+ case XLS14_TOKEN(colorAxis):
+ case XLS14_TOKEN(colorMarkers):
+ case XLS14_TOKEN(colorFirst):
+ case XLS14_TOKEN(colorLast):
+ case XLS14_TOKEN(colorHigh):
+ case XLS14_TOKEN(colorLow):
+ {
+ auto& rLastGroup = m_aSparklineGroups.back();
+ auto& rSparklineAttributes = rLastGroup.getSparklineGroup()->getAttributes();
+ addColorsToSparklineAttributes(rSparklineAttributes, nElement, rAttribs, getTheme());
+ return this;
+ }
+ case XLS14_TOKEN(sparklines):
+ {
+ return this;
+ }
+ case XLS14_TOKEN(sparkline):
+ {
+ auto& rLastGroup = m_aSparklineGroups.back();
+ rLastGroup.getSparklines().emplace_back();
+ return this;
+ }
+ }
+ return this;
+}
+
+void SparklineGroupsContext::onStartElement(const AttributeList&) {}
+
+void SparklineGroupsContext::onCharacters(const OUString& rChars)
+{
+ if (getCurrentElement() == XM_TOKEN(sqref) || getCurrentElement() == XM_TOKEN(f))
+ {
+ ScDocument& rDocument = getScDocument();
+ auto& rLastGroup = m_aSparklineGroups.back();
+ auto& rLastSparkline = rLastGroup.getSparklines().back();
+ ScRangeList aRange;
+ if (ScRangeStringConverter::GetRangeListFromString(aRange, rChars, rDocument,
+ formula::FormulaGrammar::CONV_XL_OOX))
+ {
+ if (!aRange.empty())
+ {
+ if (getCurrentElement() == XM_TOKEN(sqref))
+ {
+ rLastSparkline.m_aTargetRange = aRange;
+
+ // Need to set the current sheet index to the range as
+ // it is assumed that the address string refers to
+ // the current sheet and is not defined in the string.
+ for (auto& rRange : rLastSparkline.m_aTargetRange)
+ {
+ rRange.aStart.SetTab(getSheetIndex());
+ rRange.aEnd.SetTab(getSheetIndex());
+ }
+ }
+ else if (getCurrentElement() == XM_TOKEN(f))
+ rLastSparkline.m_aInputRange = aRange;
+ }
+ }
+ }
+}
+
+void SparklineGroupsContext::onEndElement()
+{
+ if (getCurrentElement() == XLS14_TOKEN(sparklineGroup))
+ {
+ auto& rLastGroup = m_aSparklineGroups.back();
+ for (Sparkline& rSparkline : rLastGroup.getSparklines())
+ {
+ insertSparkline(rLastGroup, rSparkline);
+ }
+ }
+}
+
+void SparklineGroupsContext::insertSparkline(SparklineGroup& rSparklineGroup, Sparkline& rSparkline)
+{
+ auto& rDocument = getScDocument();
+ if (rSparkline.m_aTargetRange.size() == 1)
+ {
+ auto& rRange = rSparkline.m_aTargetRange[0];
+ if (rRange.aStart == rRange.aEnd)
+ {
+ auto pSparklineGroup = rSparklineGroup.getSparklineGroup();
+ auto* pCreated = rDocument.CreateSparkline(rRange.aStart, pSparklineGroup);
+ pCreated->setInputRange(rSparkline.m_aInputRange);
+ }
+ }
+}
+
+} //namespace oox::xls
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */