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 INCLUDED_SC_INC_CONDITIO_HXX
21 : #define INCLUDED_SC_INC_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 2740 : struct ScCondFormatData
104 : {
105 2740 : ScCondFormatData():
106 : pColorScale(NULL),
107 : pDataBar(NULL),
108 2740 : 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 400 : 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 5563 : bool operator() (double nVal1, double nVal2) const
145 : {
146 5563 : if(nVal1 < nVal2 && !rtl::math::approxEqual(nVal1, nVal2))
147 1178 : return true;
148 :
149 4385 : 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 210 : virtual void SetParent( ScConditionalFormat* pNew ) SAL_OVERRIDE { pCondFormat = pNew; }
208 :
209 : bool IsCellValid( ScRefCellValue& rCell, const ScAddress& rPos ) const;
210 :
211 129 : ScConditionMode GetOperation() const { return eOp; }
212 : void SetOperation(ScConditionMode eMode);
213 48 : bool IsIgnoreBlank() const { return ( nOptions & SC_COND_NOBLANKS ) == 0; }
214 : void SetIgnoreBlank(bool bSet);
215 19 : ScAddress GetSrcPos() const { return aSrcPos; }
216 :
217 : ScAddress GetValidSrcPos() const; // adjusted to allow textual representation of expressions
218 :
219 : void SetSrcString( const OUString& rNew ); // for XML import
220 :
221 : void SetFormula1( const ScTokenArray& rArray );
222 : void SetFormula2( const ScTokenArray& rArray );
223 :
224 : OUString GetExpression( const ScAddress& rCursor, sal_uInt16 nPos, sal_uLong nNumFmt = 0,
225 : const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
226 :
227 : ScTokenArray* CreateTokenArry( sal_uInt16 nPos ) const;
228 :
229 : void CompileAll();
230 : void CompileXML();
231 : virtual void UpdateReference( sc::RefUpdateContext& rCxt ) SAL_OVERRIDE;
232 : virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) SAL_OVERRIDE;
233 : virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) SAL_OVERRIDE;
234 : virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) SAL_OVERRIDE;
235 :
236 : void SourceChanged( const ScAddress& rChanged );
237 :
238 : bool MarkUsedExternalReferences() const;
239 :
240 10253 : virtual condformat::ScFormatEntryType GetType() const SAL_OVERRIDE { return condformat::CONDITION; }
241 :
242 : virtual ScFormatEntry* Clone(ScDocument* pDoc = NULL) const SAL_OVERRIDE;
243 :
244 : static ScConditionMode GetModeFromApi(sal_Int32 nOperator);
245 :
246 : virtual void endRendering() SAL_OVERRIDE;
247 : virtual void startRendering() SAL_OVERRIDE;
248 :
249 : protected:
250 : virtual void DataChanged( const ScRange* pModified ) const;
251 49 : ScDocument* GetDocument() const { return mpDoc; }
252 : ScConditionalFormat* pCondFormat;
253 :
254 : private:
255 :
256 : bool IsDuplicate(double nArg, const OUString& rStr) const;
257 : bool IsTopNElement( double nArg ) const;
258 : bool IsTopNPercent( double nArg ) const;
259 : bool IsBottomNElement( double nArg ) const;
260 : bool IsBottomNPercent( double nArg ) const;
261 : bool IsAboveAverage( double nArg, bool bEqual ) const;
262 : bool IsBelowAverage( double nArg, bool bEqual ) const;
263 :
264 : bool IsError( const ScAddress& rPos ) const;
265 :
266 : void FillCache() const;
267 :
268 47 : struct ScConditionEntryCache
269 : {
270 : typedef std::map<OUString, sal_Int32> StringCacheType;
271 : StringCacheType maStrings;
272 : typedef std::map<double, sal_Int32, approx_less> ValueCacheType;
273 : ValueCacheType maValues;
274 :
275 : // cache them for easier access
276 : size_t nValueItems;
277 :
278 47 : ScConditionEntryCache():
279 47 : nValueItems(0) {}
280 : };
281 :
282 : mutable boost::scoped_ptr<ScConditionEntryCache> mpCache;
283 : };
284 :
285 : // single condition entry for conditional formatting
286 : class SC_DLLPUBLIC ScCondFormatEntry : public ScConditionEntry
287 : {
288 : OUString aStyleName;
289 :
290 : using ScConditionEntry::operator==;
291 :
292 : public:
293 : ScCondFormatEntry( ScConditionMode eOper,
294 : const OUString& rExpr1, const OUString& rExpr2,
295 : ScDocument* pDocument, const ScAddress& rPos,
296 : const OUString& rStyle,
297 : const OUString& rExprNmsp1 = EMPTY_OUSTRING,
298 : const OUString& rExprNmsp2 = EMPTY_OUSTRING,
299 : formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT,
300 : formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT );
301 : ScCondFormatEntry( ScConditionMode eOper,
302 : const ScTokenArray* pArr1, const ScTokenArray* pArr2,
303 : ScDocument* pDocument, const ScAddress& rPos,
304 : const OUString& rStyle );
305 : ScCondFormatEntry( const ScCondFormatEntry& r );
306 : ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r );
307 : virtual ~ScCondFormatEntry();
308 :
309 : bool operator== ( const ScCondFormatEntry& r ) const;
310 :
311 6950 : const OUString& GetStyle() const { return aStyleName; }
312 0 : void UpdateStyleName(const OUString& rNew) { aStyleName=rNew; }
313 : virtual ScFormatEntry* Clone(ScDocument* pDoc) const SAL_OVERRIDE;
314 :
315 : protected:
316 : virtual void DataChanged( const ScRange* pModified ) const SAL_OVERRIDE;
317 : };
318 :
319 : namespace condformat {
320 :
321 : enum ScCondFormatDateType
322 : {
323 : TODAY,
324 : YESTERDAY,
325 : TOMORROW,
326 : LAST7DAYS,
327 : THISWEEK,
328 : LASTWEEK,
329 : NEXTWEEK,
330 : THISMONTH,
331 : LASTMONTH,
332 : NEXTMONTH,
333 : THISYEAR,
334 : LASTYEAR,
335 : NEXTYEAR
336 : };
337 :
338 : }
339 :
340 4 : class SC_DLLPUBLIC ScCondDateFormatEntry : public ScFormatEntry
341 : {
342 : public:
343 : ScCondDateFormatEntry(ScDocument* pDoc);
344 : ScCondDateFormatEntry(ScDocument* pDoc, const ScCondDateFormatEntry& rEntry);
345 :
346 : bool IsValid( const ScAddress& rPos ) const;
347 :
348 : void SetDateType(condformat::ScCondFormatDateType eType);
349 0 : condformat::ScCondFormatDateType GetDateType() const { return meType;}
350 :
351 0 : const OUString& GetStyleName() const { return maStyleName;}
352 : void SetStyleName( const OUString& rStyleName );
353 :
354 4 : virtual condformat::ScFormatEntryType GetType() const SAL_OVERRIDE { return condformat::DATE; }
355 0 : virtual void UpdateReference( sc::RefUpdateContext& ) SAL_OVERRIDE {}
356 0 : virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& ) SAL_OVERRIDE {}
357 0 : virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& ) SAL_OVERRIDE {}
358 0 : virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& ) SAL_OVERRIDE {}
359 :
360 : virtual ScFormatEntry* Clone( ScDocument* pDoc = NULL ) const SAL_OVERRIDE;
361 :
362 4 : virtual void SetParent( ScConditionalFormat* ) SAL_OVERRIDE {}
363 :
364 : bool operator==( const ScFormatEntry& ) const;
365 :
366 : virtual void startRendering() SAL_OVERRIDE;
367 : virtual void endRendering() SAL_OVERRIDE;
368 :
369 : private:
370 : condformat::ScCondFormatDateType meType;
371 :
372 : mutable boost::scoped_ptr<Date> mpCache;
373 :
374 : OUString maStyleName;
375 : };
376 :
377 : // complete conditional formatting
378 : class SC_DLLPUBLIC ScConditionalFormat: private boost::noncopyable
379 : {
380 : ScDocument* pDoc;
381 : sal_uInt32 nKey; // Index in attributes
382 :
383 : typedef boost::ptr_vector<ScFormatEntry> CondFormatContainer;
384 : CondFormatContainer maEntries;
385 : ScRangeList maRanges; // Ranges for conditional format
386 :
387 : public:
388 : ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument);
389 : ~ScConditionalFormat();
390 :
391 : // true copy of formulas (for Ref-Undo / between documents)
392 : ScConditionalFormat* Clone(ScDocument* pNewDoc = NULL) const;
393 :
394 : void AddEntry( ScFormatEntry* pNew );
395 : void RemoveEntry(size_t nIndex);
396 : void SetRange( const ScRangeList& rRanges );
397 636 : const ScRangeList& GetRange() const { return maRanges; }
398 : // don't use the same name as for the const version
399 0 : ScRangeList& GetRangeList() { return maRanges; }
400 :
401 : ScDocument* GetDocument() { return pDoc; }
402 :
403 : bool IsEmpty() const;
404 : size_t size() const;
405 :
406 : void CompileAll();
407 : void CompileXML();
408 : void UpdateReference( sc::RefUpdateContext& rCxt, bool bCopyAsMove = false );
409 : void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
410 : void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
411 : void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt );
412 :
413 : void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize);
414 : void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize);
415 :
416 : void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
417 : void RenameCellStyle( const OUString& rOld, const OUString& rNew );
418 :
419 : void SourceChanged( const ScAddress& rAddr );
420 :
421 : const ScFormatEntry* GetEntry( sal_uInt16 nPos ) const;
422 :
423 : const OUString& GetCellStyle( ScRefCellValue& rCell, const ScAddress& rPos ) const;
424 :
425 : ScCondFormatData GetData( ScRefCellValue& rCell, const ScAddress& rPos ) const;
426 :
427 : bool EqualEntries( const ScConditionalFormat& r ) const;
428 :
429 : void DoRepaint( const ScRange* pModified );
430 :
431 14663 : sal_uInt32 GetKey() const { return nKey; }
432 271 : void SetKey(sal_uInt32 nNew) { nKey = nNew; } // only if not inserted!
433 :
434 : bool MarkUsedExternalReferences() const;
435 :
436 : // sorted (via boost::ptr_set) by Index
437 : // operator== only for sorting
438 : bool operator ==( const ScConditionalFormat& r ) const { return nKey == r.nKey; }
439 607 : bool operator < ( const ScConditionalFormat& r ) const { return nKey < r.nKey; }
440 :
441 : void startRendering();
442 : void endRendering();
443 : };
444 :
445 : // List of all conditional formats in a sheet
446 : class SC_DLLPUBLIC ScConditionalFormatList
447 : {
448 : private:
449 : typedef boost::ptr_set<ScConditionalFormat> ConditionalFormatContainer;
450 : ConditionalFormatContainer maConditionalFormats;
451 :
452 : void operator =(ScConditionalFormatList const &) SAL_DELETED_FUNCTION;
453 :
454 : public:
455 2425 : ScConditionalFormatList() {}
456 : ScConditionalFormatList(const ScConditionalFormatList& rList);
457 : ScConditionalFormatList(ScDocument* pDoc, const ScConditionalFormatList& rList);
458 3228 : ~ScConditionalFormatList() {}
459 :
460 : void InsertNew( ScConditionalFormat* pNew );
461 :
462 : /**
463 : * Checks that all cond formats have a non empty range.
464 : * Deletes empty cond formats.
465 : * @return true if all cond formats were valid
466 : */
467 : bool CheckAllEntries();
468 :
469 : ScConditionalFormat* GetFormat( sal_uInt32 nKey );
470 : const ScConditionalFormat* GetFormat( sal_uInt32 nKey ) const;
471 :
472 : void CompileAll();
473 : void CompileXML();
474 : void UpdateReference( sc::RefUpdateContext& rCxt );
475 : void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
476 : void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
477 : void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt );
478 :
479 : void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize);
480 : void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize);
481 :
482 : void RenameCellStyle( const OUString& rOld, const OUString& rNew );
483 : void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
484 :
485 : void SourceChanged( const ScAddress& rAddr );
486 :
487 : bool operator==( const ScConditionalFormatList& r ) const; // for Ref-Undo
488 :
489 : typedef ConditionalFormatContainer::iterator iterator;
490 : typedef ConditionalFormatContainer::const_iterator const_iterator;
491 :
492 : iterator begin();
493 : const_iterator begin() const;
494 : iterator end();
495 : const_iterator end() const;
496 :
497 : size_t size() const;
498 :
499 : void erase(sal_uLong nIndex);
500 :
501 : void startRendering();
502 : void endRendering();
503 : };
504 :
505 : #endif
506 :
507 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|