Line data Source code
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 :
20 : #ifndef SC_CONDITIO_HXX
21 : #define SC_CONDITIO_HXX
22 :
23 : #include "global.hxx"
24 : #include "address.hxx"
25 : #include "formula/grammar.hxx"
26 : #include "scdllapi.h"
27 : #include "rangelst.hxx"
28 :
29 : #include <rtl/math.hxx>
30 : #include <tools/date.hxx>
31 :
32 : #include <map>
33 :
34 : #include <boost/ptr_container/ptr_set.hpp>
35 : #include <boost/ptr_container/ptr_vector.hpp>
36 : #include <boost/scoped_ptr.hpp>
37 :
38 : #include <map>
39 :
40 : class ScBaseCell;
41 : class ScFormulaCell;
42 : class ScTokenArray;
43 :
44 :
45 : // nOptions Flags
46 : #define SC_COND_NOBLANKS 1
47 :
48 : #define DUMP_FORMAT_INFO 1
49 :
50 : enum ScConditionMode
51 : {
52 : SC_COND_EQUAL,
53 : SC_COND_LESS,
54 : SC_COND_GREATER,
55 : SC_COND_EQLESS,
56 : SC_COND_EQGREATER,
57 : SC_COND_NOTEQUAL,
58 : SC_COND_BETWEEN,
59 : SC_COND_NOTBETWEEN,
60 : SC_COND_DUPLICATE,
61 : SC_COND_NOTDUPLICATE,
62 : SC_COND_DIRECT,
63 : SC_COND_TOP10,
64 : SC_COND_BOTTOM10,
65 : SC_COND_TOP_PERCENT,
66 : SC_COND_BOTTOM_PERCENT,
67 : SC_COND_ABOVE_AVERAGE,
68 : SC_COND_BELOW_AVERAGE,
69 : SC_COND_ERROR,
70 : SC_COND_NOERROR,
71 : SC_COND_BEGINS_WITH,
72 : SC_COND_ENDS_WITH,
73 : SC_COND_CONTAINS_TEXT,
74 : SC_COND_NOT_CONTAINS_TEXT,
75 : SC_COND_NONE
76 : };
77 :
78 : class ScConditionalFormat;
79 : struct ScDataBarInfo;
80 : struct ScIconSetInfo;
81 :
82 : namespace condformat
83 : {
84 :
85 : enum ScFormatEntryType
86 : {
87 : CONDITION,
88 : COLORSCALE,
89 : DATABAR,
90 : ICONSET,
91 : DATE
92 : };
93 :
94 : }
95 :
96 0 : struct ScCondFormatData
97 : {
98 0 : ScCondFormatData():
99 : pColorScale(NULL),
100 : pDataBar(NULL),
101 0 : pIconSet(NULL) {}
102 :
103 : Color* pColorScale;
104 : ScDataBarInfo* pDataBar;
105 : ScIconSetInfo* pIconSet;
106 : rtl::OUString aStyleName;
107 : };
108 :
109 : class SC_DLLPUBLIC ScFormatEntry
110 : {
111 : public:
112 : ScFormatEntry(ScDocument* pDoc);
113 89 : virtual ~ScFormatEntry() {}
114 :
115 : virtual condformat::ScFormatEntryType GetType() const = 0;
116 : virtual void UpdateReference( UpdateRefMode eUpdateRefMode,
117 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) = 0;
118 : virtual void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos ) = 0;
119 :
120 : virtual ScFormatEntry* Clone( ScDocument* pDoc = NULL ) const = 0;
121 :
122 : virtual void SetParent( ScConditionalFormat* pNew ) = 0;
123 :
124 : bool operator==( const ScFormatEntry& ) const;
125 :
126 : #if DUMP_FORMAT_INFO
127 : virtual void dumpInfo(rtl::OUStringBuffer& rBuf) const = 0;
128 : #endif
129 :
130 : virtual void startRendering();
131 : virtual void endRendering();
132 : protected:
133 : ScDocument* mpDoc;
134 :
135 : };
136 :
137 : class approx_less : public std::binary_function<double, double, bool>
138 : {
139 : public:
140 1888 : bool operator() (double nVal1, double nVal2) const
141 : {
142 1888 : if(nVal1 < nVal2 && !rtl::math::approxEqual(nVal1, nVal2))
143 396 : return true;
144 :
145 1492 : return false;
146 : }
147 : };
148 :
149 : class SC_DLLPUBLIC ScConditionEntry : public ScFormatEntry
150 : {
151 : // stored data:
152 : ScConditionMode eOp;
153 : sal_uInt16 nOptions;
154 : double nVal1; // input or calculated
155 : double nVal2;
156 : rtl::OUString aStrVal1; // input or calculated
157 : rtl::OUString aStrVal2;
158 : rtl::OUString aStrNmsp1; // namespace to be used on (re)compilation, e.g. in XML import
159 : rtl::OUString aStrNmsp2; // namespace to be used on (re)compilation, e.g. in XML import
160 : formula::FormulaGrammar::Grammar eTempGrammar1; // grammar to be used on (re)compilation, e.g. in XML import
161 : formula::FormulaGrammar::Grammar eTempGrammar2; // grammar to be used on (re)compilation, e.g. in XML import
162 : bool bIsStr1; // for recognition of empty strings
163 : bool bIsStr2;
164 : ScTokenArray* pFormula1; // entered formula
165 : ScTokenArray* pFormula2;
166 : ScAddress aSrcPos; // source position for formulas
167 : // temporary data:
168 : rtl::OUString aSrcString; // formula source position as text during XML import
169 : ScFormulaCell* pFCell1;
170 : ScFormulaCell* pFCell2;
171 : bool bRelRef1;
172 : bool bRelRef2;
173 : bool bFirstRun;
174 :
175 : void MakeCells( const ScAddress& rPos );
176 : void Compile( const rtl::OUString& rExpr1, const rtl::OUString& rExpr2,
177 : const rtl::OUString& rExprNmsp1, const rtl::OUString& rExprNmsp2,
178 : formula::FormulaGrammar::Grammar eGrammar1,
179 : formula::FormulaGrammar::Grammar eGrammar2,
180 : bool bTextToReal );
181 : void Interpret( const ScAddress& rPos );
182 :
183 : bool IsValid( double nArg, const ScAddress& rPos ) const;
184 : bool IsValidStr( const rtl::OUString& rArg, const ScAddress& rPos ) const;
185 :
186 : public:
187 : ScConditionEntry( ScConditionMode eOper,
188 : const rtl::OUString& rExpr1, const rtl::OUString& rExpr2,
189 : ScDocument* pDocument, const ScAddress& rPos,
190 : const rtl::OUString& rExprNmsp1, const rtl::OUString& rExprNmsp2,
191 : formula::FormulaGrammar::Grammar eGrammar1,
192 : formula::FormulaGrammar::Grammar eGrammar2 );
193 : ScConditionEntry( ScConditionMode eOper,
194 : const ScTokenArray* pArr1, const ScTokenArray* pArr2,
195 : ScDocument* pDocument, const ScAddress& rPos );
196 : ScConditionEntry( const ScConditionEntry& r ); // flat copy of formulas
197 : // true copy of formulas (for Ref-Undo):
198 : ScConditionEntry( ScDocument* pDocument, const ScConditionEntry& r );
199 : virtual ~ScConditionEntry();
200 :
201 : int operator== ( const ScConditionEntry& r ) const;
202 :
203 69 : virtual void SetParent( ScConditionalFormat* pNew ) { pCondFormat = pNew; }
204 :
205 : bool IsCellValid( ScBaseCell* pCell, const ScAddress& rPos ) const;
206 :
207 32 : ScConditionMode GetOperation() const { return eOp; }
208 0 : bool IsIgnoreBlank() const { return ( nOptions & SC_COND_NOBLANKS ) == 0; }
209 : void SetIgnoreBlank(bool bSet);
210 0 : ScAddress GetSrcPos() const { return aSrcPos; }
211 :
212 : ScAddress GetValidSrcPos() const; // adjusted to allow textual representation of expressions
213 :
214 : void SetSrcString( const rtl::OUString& rNew ); // for XML import
215 :
216 : void SetFormula1( const ScTokenArray& rArray );
217 : void SetFormula2( const ScTokenArray& rArray );
218 :
219 : rtl::OUString GetExpression( const ScAddress& rCursor, sal_uInt16 nPos, sal_uLong nNumFmt = 0,
220 : const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
221 :
222 : ScTokenArray* CreateTokenArry( sal_uInt16 nPos ) const;
223 :
224 : void CompileAll();
225 : void CompileXML();
226 : void UpdateReference( UpdateRefMode eUpdateRefMode,
227 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
228 : void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos );
229 :
230 : void SourceChanged( const ScAddress& rChanged );
231 :
232 : bool MarkUsedExternalReferences() const;
233 :
234 417 : virtual condformat::ScFormatEntryType GetType() const { return condformat::CONDITION; }
235 :
236 : virtual ScFormatEntry* Clone(ScDocument* pDoc = NULL) const;
237 :
238 : static ScConditionMode GetModeFromApi(sal_Int32 nOperator);
239 :
240 : #if DUMP_FORMAT_INFO
241 0 : virtual void dumpInfo(rtl::OUStringBuffer& ) const {}
242 : #endif
243 :
244 : virtual void endRendering();
245 : virtual void startRendering();
246 :
247 : protected:
248 : virtual void DataChanged( const ScRange* pModified ) const;
249 15 : ScDocument* GetDocument() const { return mpDoc; }
250 : ScConditionalFormat* pCondFormat;
251 :
252 : private:
253 :
254 : bool IsDuplicate(double nArg, const rtl::OUString& rStr) const;
255 : bool IsTopNElement( double nArg ) const;
256 : bool IsTopNPercent( double nArg ) const;
257 : bool IsBottomNElement( double nArg ) const;
258 : bool IsBottomNPercent( double nArg ) const;
259 : bool IsAboveAverage( double nArg ) const;
260 : bool IsBelowAverage( double nArg ) const;
261 :
262 : bool IsError( const ScAddress& rPos ) const;
263 :
264 : void FillCache() const;
265 :
266 0 : struct ScConditionEntryCache
267 : {
268 : typedef std::map<rtl::OUString, sal_Int32> StringCacheType;
269 : StringCacheType maStrings;
270 : typedef std::map<double, sal_Int32, approx_less> ValueCacheType;
271 : ValueCacheType maValues;
272 :
273 : // cache them for easier access
274 : size_t nValueItems;
275 :
276 16 : ScConditionEntryCache():
277 16 : nValueItems(0) {}
278 : };
279 :
280 : mutable boost::scoped_ptr<ScConditionEntryCache> mpCache;
281 : };
282 :
283 : //
284 : // single entry for conditional formatting
285 : //
286 :
287 : class SC_DLLPUBLIC ScCondFormatEntry : public ScConditionEntry
288 : {
289 : rtl::OUString aStyleName;
290 :
291 : using ScConditionEntry::operator==;
292 :
293 : public:
294 : ScCondFormatEntry( ScConditionMode eOper,
295 : const rtl::OUString& rExpr1, const rtl::OUString& rExpr2,
296 : ScDocument* pDocument, const ScAddress& rPos,
297 : const rtl::OUString& rStyle,
298 0 : const rtl::OUString& rExprNmsp1 = EMPTY_STRING,
299 0 : const rtl::OUString& rExprNmsp2 = EMPTY_STRING,
300 : formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT,
301 : formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT );
302 : ScCondFormatEntry( ScConditionMode eOper,
303 : const ScTokenArray* pArr1, const ScTokenArray* pArr2,
304 : ScDocument* pDocument, const ScAddress& rPos,
305 : const rtl::OUString& rStyle );
306 : ScCondFormatEntry( const ScCondFormatEntry& r );
307 : ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r );
308 : virtual ~ScCondFormatEntry();
309 :
310 : int operator== ( const ScCondFormatEntry& r ) const;
311 :
312 161 : const rtl::OUString& GetStyle() const { return aStyleName; }
313 0 : void UpdateStyleName(const rtl::OUString& rNew) { aStyleName=rNew; }
314 : virtual ScFormatEntry* Clone(ScDocument* pDoc) const;
315 :
316 : protected:
317 : virtual void DataChanged( const ScRange* pModified ) const;
318 : };
319 :
320 : namespace condformat {
321 :
322 : enum ScCondFormatDateType
323 : {
324 : TODAY,
325 : YESTERDAY,
326 : TOMORROW,
327 : LAST7DAYS,
328 : THISWEEK,
329 : LASTWEEK,
330 : NEXTWEEK,
331 : THISMONTH,
332 : LASTMONTH,
333 : NEXTMONTH,
334 : THISYEAR,
335 : LASTYEAR,
336 : NEXTYEAR
337 : };
338 :
339 : }
340 :
341 0 : class SC_DLLPUBLIC ScCondDateFormatEntry : public ScFormatEntry
342 : {
343 : public:
344 : ScCondDateFormatEntry(ScDocument* pDoc);
345 : ScCondDateFormatEntry(ScDocument* pDoc, const ScCondDateFormatEntry& rEntry);
346 :
347 : bool IsValid( const ScAddress& rPos ) const;
348 :
349 : void SetDateType(condformat::ScCondFormatDateType eType);
350 : condformat::ScCondFormatDateType GetDateType() const;
351 :
352 : const rtl::OUString& GetStyleName() const;
353 : void SetStyleName( const rtl::OUString& rStyleName );
354 :
355 0 : virtual condformat::ScFormatEntryType GetType() const { return condformat::DATE; }
356 0 : virtual void UpdateReference( UpdateRefMode, const ScRange&,
357 0 : SCsCOL, SCsROW, SCsTAB ) {}
358 0 : virtual void UpdateMoveTab( SCTAB, SCTAB ) {}
359 :
360 : virtual ScFormatEntry* Clone( ScDocument* pDoc = NULL ) const;
361 :
362 0 : virtual void SetParent( ScConditionalFormat* ) {}
363 :
364 : bool operator==( const ScFormatEntry& ) const;
365 :
366 : #if DUMP_FORMAT_INFO
367 : virtual void dumpInfo(rtl::OUStringBuffer& rBuf) const;
368 : #endif
369 :
370 : virtual void startRendering();
371 : virtual void endRendering();
372 :
373 : private:
374 : condformat::ScCondFormatDateType meType;
375 :
376 : mutable boost::scoped_ptr<Date> mpCache;
377 :
378 : rtl::OUString maStyleName;
379 : };
380 :
381 : //
382 : // complete conditional formatting
383 : //
384 :
385 : class SC_DLLPUBLIC ScConditionalFormat
386 : {
387 : ScDocument* pDoc;
388 : sal_uInt32 nKey; // Index in attributes
389 :
390 : typedef boost::ptr_vector<ScFormatEntry> CondFormatContainer;
391 : CondFormatContainer maEntries;
392 : ScRangeList maRanges; // Ranges for conditional format
393 :
394 : public:
395 : ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument);
396 : ScConditionalFormat(const ScConditionalFormat& r);
397 : ~ScConditionalFormat();
398 :
399 : // true copy of formulas (for Ref-Undo / between documents)
400 : ScConditionalFormat* Clone(ScDocument* pNewDoc = NULL) const;
401 :
402 : void AddEntry( ScFormatEntry* pNew );
403 : void AddRange( const ScRangeList& rRanges );
404 33 : const ScRangeList& GetRange() const { return maRanges; }
405 : // don't use the same name as for the const version
406 0 : ScRangeList& GetRangeList() { return maRanges; }
407 :
408 0 : bool IsEmpty() const { return maEntries.empty(); }
409 39 : size_t size() const { return maEntries.size(); }
410 :
411 : void CompileAll();
412 : void CompileXML();
413 : void UpdateReference( UpdateRefMode eUpdateRefMode,
414 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
415 : void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
416 : void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos );
417 : void RenameCellStyle( const rtl::OUString& rOld, const rtl::OUString& rNew );
418 :
419 : void SourceChanged( const ScAddress& rAddr );
420 :
421 : const ScFormatEntry* GetEntry( sal_uInt16 nPos ) const;
422 :
423 : const rtl::OUString& GetCellStyle( ScBaseCell* pCell, const ScAddress& rPos ) const;
424 :
425 : ScCondFormatData GetData( ScBaseCell* pCell, const ScAddress& rPos ) const;
426 :
427 : bool EqualEntries( const ScConditionalFormat& r ) const;
428 :
429 : void DoRepaint( const ScRange* pModified );
430 :
431 1658 : sal_uInt32 GetKey() const { return nKey; }
432 37 : void SetKey(sal_uInt32 nNew) { nKey = nNew; } // only if not inserted!
433 :
434 : bool MarkUsedExternalReferences() const;
435 :
436 : #if DUMP_FORMAT_INFO
437 : void dumpInfo(rtl::OUStringBuffer& rBuf) const;
438 : #endif
439 :
440 : // sorted (via PTRARR) by Index
441 : // operator== only for sorting
442 : bool operator ==( const ScConditionalFormat& r ) const { return nKey == r.nKey; }
443 124 : bool operator < ( const ScConditionalFormat& r ) const { return nKey < r.nKey; }
444 :
445 : void startRendering();
446 : void endRendering();
447 : };
448 :
449 : //
450 : // List of areas and formats:
451 : //
452 :
453 : class SC_DLLPUBLIC ScConditionalFormatList
454 : {
455 : private:
456 : boost::ptr_set<ScConditionalFormat> maConditionalFormats;
457 : typedef boost::ptr_set<ScConditionalFormat> ConditionalFormatContainer;
458 : public:
459 270 : ScConditionalFormatList() {}
460 : ScConditionalFormatList(const ScConditionalFormatList& rList);
461 : ScConditionalFormatList(ScDocument* pDoc, const ScConditionalFormatList& rList);
462 211 : ~ScConditionalFormatList() {}
463 :
464 34 : void InsertNew( ScConditionalFormat* pNew )
465 34 : { maConditionalFormats.insert(pNew); }
466 : /**
467 : * Checks that all cond formats have a non empty range.
468 : * Deletes empty cond formats.
469 : * @return true if all cond formats were valid
470 : */
471 : bool CheckAllEntries();
472 :
473 : ScConditionalFormat* GetFormat( sal_uInt32 nKey );
474 :
475 : void CompileAll();
476 : void CompileXML();
477 : void UpdateReference( UpdateRefMode eUpdateRefMode,
478 : const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
479 : void RenameCellStyle( const rtl::OUString& rOld, const rtl::OUString& rNew );
480 : void UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos );
481 : void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
482 :
483 : void SourceChanged( const ScAddress& rAddr );
484 :
485 : bool operator==( const ScConditionalFormatList& r ) const; // for Ref-Undo
486 :
487 : typedef ConditionalFormatContainer::iterator iterator;
488 : typedef ConditionalFormatContainer::const_iterator const_iterator;
489 :
490 : iterator begin();
491 : const_iterator begin() const;
492 : iterator end();
493 : const_iterator end() const;
494 :
495 : size_t size() const;
496 :
497 : void erase(sal_uLong nIndex);
498 :
499 : void startRendering();
500 : void endRendering();
501 : };
502 :
503 : // see http://www.boost.org/doc/libs/1_49_0/libs/ptr_container/doc/tutorial.html#cloneability
504 : //for MSVC we need:
505 : inline ScFormatEntry* new_clone( const ScFormatEntry& rFormat )
506 : {
507 : return rFormat.Clone();
508 : }
509 :
510 : #endif
511 :
512 :
513 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|