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