LibreOffice Module oox (master)  1
datasourcecontext.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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
21 
23 
26 #include <oox/token/namespaces.hxx>
27 #include <oox/token/tokens.hxx>
28 #include <svl/zforlist.hxx>
29 #include <osl/diagnose.h>
30 
31 namespace oox::drawingml::chart {
32 
33 using ::oox::core::ContextHandler2Helper;
35 
36 using namespace ::com::sun::star;
37 
39  DataSequenceContextBase( rParent, rModel ),
40  mnPtIndex( -1 )
41 {
42 }
43 
45 {
46 }
47 
49 {
50  switch( getCurrentElement() )
51  {
52  case C_TOKEN( numRef ):
53  switch( nElement )
54  {
55  case C_TOKEN( f ):
56  case C_TOKEN( numCache ):
57  return this;
58  }
59  break;
60 
61  case C_TOKEN( numCache ):
62  case C_TOKEN( numLit ):
63  switch( nElement )
64  {
65  case C_TOKEN( formatCode ):
66  return this;
67  case C_TOKEN( ptCount ):
68  mrModel.mnPointCount = rAttribs.getInteger( XML_val, -1 );
69  return nullptr;
70  case C_TOKEN( pt ):
71  mnPtIndex = rAttribs.getInteger( XML_idx, -1 );
72  return this;
73  }
74  break;
75 
76  case C_TOKEN( pt ):
77  switch( nElement )
78  {
79  case C_TOKEN( v ):
80  return this;
81  }
82  break;
83  }
84  return nullptr;
85 }
86 
87 void DoubleSequenceContext::onCharacters( const OUString& rChars )
88 {
89  switch( getCurrentElement() )
90  {
91  case C_TOKEN( f ):
92  mrModel.maFormula = rChars;
93  break;
94  case C_TOKEN( formatCode ):
95  mrModel.maFormatCode = rChars;
96  break;
97  case C_TOKEN( v ):
98  if( mnPtIndex >= 0 )
99  {
100  /* Import categories as String even though it could
101  * be values.
102  * n#810508: xVal needs to be imported as double
103  * TODO: NumberFormat conversion, remove the check then.
104  */
105  if( isParentElement( C_TOKEN( cat ), 4 ) )
106  {
107  // workaround for bug n#889755
109  if( pNumFrmt )
110  {
111  sal_uInt32 nKey = pNumFrmt->GetEntryKey( mrModel.maFormatCode );
112  bool bNoKey = ( nKey == NUMBERFORMAT_ENTRY_NOT_FOUND );
113  if( bNoKey )
114  {
115  OUString aFormatCode = mrModel.maFormatCode;
116  sal_Int32 nCheckPos = 0;
118  pNumFrmt->PutEntry( aFormatCode, nCheckPos, nType, nKey );
119  bNoKey = (nCheckPos != 0);
120  }
121  if( bNoKey )
122  {
123  mrModel.maData[ mnPtIndex ] <<= rChars;
124  }
125  else
126  {
127  double fValue = rChars.toDouble();
128  const ::Color* pColor = nullptr;
129  OUString aFormattedValue;
130  // tdf#91250: use UNLIMITED_PRECISION in case of GENERAL Number Format of category axis labels
133  pNumFrmt->GetOutputString( fValue, nKey, aFormattedValue, &pColor );
134  mrModel.maData[ mnPtIndex ] <<= aFormattedValue;
135  }
136  }
137  else
138  {
139  mrModel.maData[ mnPtIndex ] <<= rChars;
140  }
141  }
142  else
143  {
144  mrModel.maData[ mnPtIndex ] <<= rChars.toDouble();
145  }
146  }
147  break;
148  }
149 }
150 
151 
153 {
154  if( mpNumberFormatter == nullptr )
155  {
156  uno::Reference<uno::XComponentContext> rContext =
158  mpNumberFormatter.reset(
159  new SvNumberFormatter(rContext, LANGUAGE_SYSTEM) );
160  }
161  return mpNumberFormatter.get();
162 }
163 
164 
166  : DataSequenceContextBase( rParent, rModel )
167  , mnPtIndex(-1)
168 {
169 }
170 
172 {
173 }
174 
176 {
177  switch( getCurrentElement() )
178  {
179  case C_TOKEN( multiLvlStrRef ):
180  switch( nElement )
181  {
182  case C_TOKEN( f ):
183  case C_TOKEN( multiLvlStrCache ):
184  return this;
185  }
186  break;
187 
188  case C_TOKEN( strRef ):
189  switch( nElement )
190  {
191  case C_TOKEN( f ):
192  case C_TOKEN( strCache ):
193  return this;
194  }
195  break;
196 
197  case C_TOKEN( strCache ):
198  case C_TOKEN( strLit ):
199  switch( nElement )
200  {
201  case C_TOKEN( ptCount ):
202  mrModel.mnPointCount = rAttribs.getInteger( XML_val, -1 );
203  return nullptr;
204  case C_TOKEN( pt ):
205  mnPtIndex = rAttribs.getInteger( XML_idx, -1 );
206  return this;
207  }
208  break;
209 
210  case C_TOKEN( multiLvlStrCache ):
211  switch (nElement)
212  {
213  case C_TOKEN( ptCount ):
214  mrModel.mnPointCount = rAttribs.getInteger(XML_val, -1);
215  mrModel.mnLevelCount--; // normalize level count
216  return nullptr;
217  case C_TOKEN( lvl ):
218  mrModel.mnLevelCount++;
219  return this;
220  }
221  break;
222 
223  case C_TOKEN( lvl ):
224  switch (nElement)
225  {
226  case C_TOKEN(pt):
227  mnPtIndex = rAttribs.getInteger(XML_idx, -1);
228  return this;
229  }
230  break;
231 
232  case C_TOKEN( pt ):
233  switch( nElement )
234  {
235  case C_TOKEN( v ):
236  return this;
237  }
238  break;
239  }
240  return nullptr;
241 }
242 
243 void StringSequenceContext::onCharacters( const OUString& rChars )
244 {
245  switch( getCurrentElement() )
246  {
247  case C_TOKEN( f ):
248  mrModel.maFormula = rChars;
249  break;
250  case C_TOKEN( v ):
251  if( mnPtIndex >= 0 )
252  mrModel.maData[ (mrModel.mnLevelCount-1) * mrModel.mnPointCount + mnPtIndex ] <<= rChars;
253  break;
254  }
255 }
256 
258  ContextBase< DataSourceModel >( rParent, rModel )
259 {
260 }
261 
263 {
264 }
265 
267 {
268  switch( getCurrentElement() )
269  {
270  case C_TOKEN( cat ):
271  case C_TOKEN( xVal ):
272  switch( nElement )
273  {
274  case C_TOKEN( multiLvlStrRef ):
275  case C_TOKEN( strLit ):
276  case C_TOKEN( strRef ):
277  OSL_ENSURE( !mrModel.mxDataSeq, "DataSourceContext::onCreateContext - multiple data sequences" );
278  return new StringSequenceContext( *this, mrModel.mxDataSeq.create() );
279 
280  case C_TOKEN( numLit ):
281  case C_TOKEN( numRef ):
282  OSL_ENSURE( !mrModel.mxDataSeq, "DataSourceContext::onCreateContext - multiple data sequences" );
283  return new DoubleSequenceContext( *this, mrModel.mxDataSeq.create() );
284  }
285  break;
286 
287  case C_TOKEN( plus ):
288  case C_TOKEN( minus ):
289  case C_TOKEN( val ):
290  case C_TOKEN( yVal ):
291  case C_TOKEN( bubbleSize ):
292  switch( nElement )
293  {
294  case C_TOKEN( numLit ):
295  case C_TOKEN( numRef ):
296  OSL_ENSURE( !mrModel.mxDataSeq, "DataSourceContext::onCreateContext - multiple data sequences" );
297  return new DoubleSequenceContext( *this, mrModel.mxDataSeq.create() );
298  }
299  break;
300  }
301  return nullptr;
302 }
303 
304 } // namespace oox::drawingml::chart
305 
306 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptValue< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
Returns the 32-bit signed integer value of the specified attribute (decimal).
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
StringSequenceContext(::oox::core::ContextHandler2Helper &rParent, DataSequenceModel &rModel)
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent=true)
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
sal_uInt16 GetStandardPrec() const
Handler for a double sequence context (c:numLit, c:numRef elements).
virtual void onCharacters(const OUString &rChars) override
Will be called before a new child element starts, or if the current element is about to be left...
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
#define LANGUAGE_SYSTEM
sal_Int32 getCurrentElement() const
Returns the identifier of the currently processed element.
const css::uno::Reference< css::uno::XComponentContext > & getComponentContext() const
Returns the component context passed in the filter constructor (always existing). ...
Definition: filterbase.cxx:212
SvNumFormatType
sal_uInt32 GetEntryKey(std::u16string_view sStr, LanguageType eLnge=LANGUAGE_DONTKNOW)
Provides access to attribute values of an element.
bool isParentElement(sal_Int32 nElement, sal_Int32 nCountBack=1) const
Returns true, if nElement contains the identifier of the specified parent element.
static const sal_uInt16 UNLIMITED_PRECISION
float v
DataSourceContext(::oox::core::ContextHandler2Helper &rParent, DataSourceModel &rModel)
XmlFilterBase & getFilter() const
Returns the filter instance.
::rtl::Reference< ContextHandler > ContextHandlerRef
QPRO_FUNC_TYPE nType
virtual void onCharacters(const OUString &rChars) override
Will be called before a new child element starts, or if the current element is about to be left...
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
Will be called to create a context handler for the passed element.
std::unique_ptr< SvNumberFormatter > mpNumberFormatter
Current data point index.
void(* f)(TrueTypeTable *)
Handler for a string sequence context (c:multiLvlStrRef, c:strLit, c:strRef elements).
void ChangeStandardPrec(short nPrec)
Helper class that provides a context stack.
DoubleSequenceContext(::oox::core::ContextHandler2Helper &rParent, DataSequenceModel &rModel)
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)