LibreOffice Module sc (master) 1
SparklineFragment.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <SparklineFragment.hxx>
12#include <oox/token/tokens.hxx>
13#include <oox/token/namespaces.hxx>
14#include <oox/helper/helper.hxx>
16#include <document.hxx>
17#include <rangeutl.hxx>
18#include <Sparkline.hxx>
19#include <themebuffer.hxx>
20
21using ::oox::core::ContextHandlerRef;
22
23namespace oox::xls
24{
25namespace
26{
27// TODO: deduplicate with importOOXColor
28::Color getColor(const AttributeList& rAttribs, ThemeBuffer const& rThemeBuffer)
29{
30 if (rAttribs.hasAttribute(XML_rgb))
31 {
32 return ::Color(ColorAlpha, rAttribs.getIntegerHex(XML_rgb, sal_Int32(API_RGB_TRANSPARENT)));
33 }
34 else if (rAttribs.hasAttribute(XML_theme))
35 {
36 sal_uInt32 nThemeIndex = rAttribs.getUnsigned(XML_theme, 0);
37
38 // Excel has a bug in the mapping of index 0, 1, 2 and 3.
39 if (nThemeIndex == 0)
40 nThemeIndex = 1;
41 else if (nThemeIndex == 1)
42 nThemeIndex = 0;
43 else if (nThemeIndex == 2)
44 nThemeIndex = 3;
45 else if (nThemeIndex == 3)
46 nThemeIndex = 2;
47
48 ::Color aColor = rThemeBuffer.getColorByIndex(nThemeIndex);
49 double nTint = rAttribs.getDouble(XML_tint, 0.0);
50
51 if (nTint > 0.0)
52 aColor.ApplyTintOrShade(nTint * 10000);
53 return aColor;
54 }
55
56 return ::Color();
57}
58
59void addColorsToSparklineAttributes(sc::SparklineAttributes& rAttributes, sal_Int32 nElement,
60 const AttributeList& rAttribs, ThemeBuffer& rThemeBuffer)
61{
62 switch (nElement)
63 {
64 case XLS14_TOKEN(colorSeries):
65 rAttributes.setColorSeries(getColor(rAttribs, rThemeBuffer));
66 break;
67 case XLS14_TOKEN(colorNegative):
68 rAttributes.setColorNegative(getColor(rAttribs, rThemeBuffer));
69 break;
70 case XLS14_TOKEN(colorAxis):
71 rAttributes.setColorAxis(getColor(rAttribs, rThemeBuffer));
72 break;
73 case XLS14_TOKEN(colorMarkers):
74 rAttributes.setColorMarkers(getColor(rAttribs, rThemeBuffer));
75 break;
76 case XLS14_TOKEN(colorFirst):
77 rAttributes.setColorFirst(getColor(rAttribs, rThemeBuffer));
78 break;
79 case XLS14_TOKEN(colorLast):
80 rAttributes.setColorLast(getColor(rAttribs, rThemeBuffer));
81 break;
82 case XLS14_TOKEN(colorHigh):
83 rAttributes.setColorHigh(getColor(rAttribs, rThemeBuffer));
84 break;
85 case XLS14_TOKEN(colorLow):
86 rAttributes.setColorLow(getColor(rAttribs, rThemeBuffer));
87 break;
88 default:
89 break;
90 }
91}
92
93sc::SparklineType parseSparklineType(std::u16string_view rString)
94{
95 if (rString == u"column")
97 else if (rString == u"stacked")
100}
101
102sc::DisplayEmptyCellsAs parseDisplayEmptyCellsAs(std::u16string_view rString)
103{
104 if (rString == u"span")
106 else if (rString == u"gap")
109}
110
111sc::AxisType parseAxisType(std::u16string_view rString)
112{
113 if (rString == u"group")
114 return sc::AxisType::Group;
115 else if (rString == u"custom")
118}
119
120void addAttributesToSparklineAttributes(sc::SparklineAttributes& rSparklineAttributes,
121 const AttributeList& rAttribs)
122{
123 auto oManualMax = rAttribs.getDouble(XML_manualMax);
124 auto oManualMin = rAttribs.getDouble(XML_manualMin);
125
126 rSparklineAttributes.setLineWeight(rAttribs.getDouble(XML_lineWeight, 0.75));
127
128 OUString sType = rAttribs.getString(XML_type, "line");
129 rSparklineAttributes.setType(parseSparklineType(sType));
130
131 rSparklineAttributes.setDateAxis(rAttribs.getBool(XML_dateAxis, false));
132
133 OUString sDisplayEmptyCellsAs = rAttribs.getString(XML_displayEmptyCellsAs, "zero");
134 rSparklineAttributes.setDisplayEmptyCellsAs(parseDisplayEmptyCellsAs(sDisplayEmptyCellsAs));
135
136 rSparklineAttributes.setMarkers(rAttribs.getBool(XML_markers, false));
137 rSparklineAttributes.setHigh(rAttribs.getBool(XML_high, false));
138 rSparklineAttributes.setLow(rAttribs.getBool(XML_low, false));
139 rSparklineAttributes.setFirst(rAttribs.getBool(XML_first, false));
140 rSparklineAttributes.setLast(rAttribs.getBool(XML_last, false));
141 rSparklineAttributes.setNegative(rAttribs.getBool(XML_negative, false));
142 rSparklineAttributes.setDisplayXAxis(rAttribs.getBool(XML_displayXAxis, false));
143 rSparklineAttributes.setDisplayHidden(rAttribs.getBool(XML_displayHidden, false));
144
145 OUString sMinAxisType = rAttribs.getString(XML_minAxisType, "individual");
146 rSparklineAttributes.setMinAxisType(parseAxisType(sMinAxisType));
147
148 OUString sMaxAxisType = rAttribs.getString(XML_maxAxisType, "individual");
149 rSparklineAttributes.setMaxAxisType(parseAxisType(sMaxAxisType));
150
151 rSparklineAttributes.setRightToLeft(rAttribs.getBool(XML_rightToLeft, false));
152
153 if (rSparklineAttributes.getMaxAxisType() == sc::AxisType::Custom)
154 rSparklineAttributes.setManualMax(oManualMax.value());
155 if (rSparklineAttributes.getMinAxisType() == sc::AxisType::Custom)
156 rSparklineAttributes.setManualMin(oManualMin.value());
157}
158
159} // end anonymous namespace
160
162 : WorksheetContextBase(rFragment)
163{
164}
165
167 const AttributeList& rAttribs)
168{
169 switch (nElement)
170 {
171 case XLS14_TOKEN(sparklineGroup):
172 {
173 auto& rLastGroup = m_aSparklineGroups.emplace_back();
174 auto& rSparklineAttributes = rLastGroup.getSparklineGroup()->getAttributes();
175 addAttributesToSparklineAttributes(rSparklineAttributes, rAttribs);
176 OUString sGUID = rAttribs.getString(XR2_TOKEN(uid), OUString());
177 tools::Guid aGuid(OUStringToOString(sGUID, RTL_TEXTENCODING_ASCII_US));
178 rLastGroup.getSparklineGroup()->setID(aGuid);
179 return this;
180 }
181 case XLS14_TOKEN(colorSeries):
182 case XLS14_TOKEN(colorNegative):
183 case XLS14_TOKEN(colorAxis):
184 case XLS14_TOKEN(colorMarkers):
185 case XLS14_TOKEN(colorFirst):
186 case XLS14_TOKEN(colorLast):
187 case XLS14_TOKEN(colorHigh):
188 case XLS14_TOKEN(colorLow):
189 {
190 auto& rLastGroup = m_aSparklineGroups.back();
191 auto& rSparklineAttributes = rLastGroup.getSparklineGroup()->getAttributes();
192 addColorsToSparklineAttributes(rSparklineAttributes, nElement, rAttribs, getTheme());
193 return this;
194 }
195 case XLS14_TOKEN(sparklines):
196 {
197 return this;
198 }
199 case XLS14_TOKEN(sparkline):
200 {
201 auto& rLastGroup = m_aSparklineGroups.back();
202 rLastGroup.getSparklines().emplace_back();
203 return this;
204 }
205 }
206 return this;
207}
208
210
211void SparklineGroupsContext::onCharacters(const OUString& rChars)
212{
213 if (getCurrentElement() == XM_TOKEN(sqref) || getCurrentElement() == XM_TOKEN(f))
214 {
215 ScDocument& rDocument = getScDocument();
216 auto& rLastGroup = m_aSparklineGroups.back();
217 auto& rLastSparkline = rLastGroup.getSparklines().back();
218 ScRangeList aRange;
219 if (ScRangeStringConverter::GetRangeListFromString(aRange, rChars, rDocument,
221 {
222 if (!aRange.empty())
223 {
224 if (getCurrentElement() == XM_TOKEN(sqref))
225 {
226 rLastSparkline.m_aTargetRange = aRange;
227
228 // Need to set the current sheet index to the range as
229 // it is assumed that the address string refers to
230 // the current sheet and is not defined in the string.
231 for (auto& rRange : rLastSparkline.m_aTargetRange)
232 {
233 rRange.aStart.SetTab(getSheetIndex());
234 rRange.aEnd.SetTab(getSheetIndex());
235 }
236 }
237 else if (getCurrentElement() == XM_TOKEN(f))
238 rLastSparkline.m_aInputRange = aRange;
239 }
240 }
241 }
242}
243
245{
246 if (getCurrentElement() == XLS14_TOKEN(sparklineGroup))
247 {
248 auto& rLastGroup = m_aSparklineGroups.back();
249 for (Sparkline& rSparkline : rLastGroup.getSparklines())
250 {
251 insertSparkline(rLastGroup, rSparkline);
252 }
253 }
254}
255
257{
258 auto& rDocument = getScDocument();
259 if (rSparkline.m_aTargetRange.size() == 1)
260 {
261 auto& rRange = rSparkline.m_aTargetRange[0];
262 if (rRange.aStart == rRange.aEnd)
263 {
264 auto pSparklineGroup = rSparklineGroup.getSparklineGroup();
265 auto* pCreated = rDocument.CreateSparkline(rRange.aStart, pSparklineGroup);
266 pCreated->setInputRange(rSparkline.m_aInputRange);
267 }
268 }
269}
270
271} //namespace oox::xls
272
273/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sType
void ApplyTintOrShade(sal_Int16 n100thPercent)
bool empty() const
Definition: rangelst.hxx:88
size_t size() const
Definition: rangelst.hxx:89
static bool GetRangeListFromString(ScRangeList &rRangeList, std::u16string_view rRangeListStr, const ScDocument &rDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Unicode cSeparator=' ', sal_Unicode cQuote='\'')
Definition: rangeutl.cxx:552
std::optional< OUString > getString(sal_Int32 nAttrToken) const
Transitional sparkline group data.
const std::shared_ptr< sc::SparklineGroup > & getSparklineGroup()
void onStartElement(const AttributeList &rAttribs) override
SparklineGroupsContext(WorksheetContextBase &rFragment)
std::vector< SparklineGroup > m_aSparklineGroups
void onCharacters(const OUString &rCharacters) override
oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
void insertSparkline(SparklineGroup &rSparklineGroup, Sparkline &rSparkline)
Transitional sparkline data.
ThemeBuffer & getTheme() const
Returns the office theme object read from the theme substorage.
Context handler derived from the WorksheetHelper helper class.
SCTAB getSheetIndex() const
Returns the index of the current sheet.
Common properties for a group of sparklines.
void setType(SparklineType eType)
void setDisplayHidden(bool bValue)
void setManualMax(std::optional< double > aValue)
void setMaxAxisType(AxisType eAxisType)
void setDisplayEmptyCellsAs(DisplayEmptyCellsAs eValue)
void setLineWeight(double nWeight)
void setRightToLeft(bool bValue)
void setMinAxisType(AxisType eAxisType)
void setManualMin(std::optional< double > aValue)
void setDisplayXAxis(bool bValue)
const ::Color API_RGB_TRANSPARENT(ColorTransparency, 0xffffffff)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
SparklineType
Supported sparkline types.
DisplayEmptyCellsAs
Determines how to display the empty cells.
AxisType
The method of calculating the axis min or max value.
const char * sGUID