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