Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sc / inc / conditio.hxx
blob6fd387a0e100b5f67276748757c8c3cbb0beb8ae
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_SC_INC_CONDITIO_HXX
21 #define INCLUDED_SC_INC_CONDITIO_HXX
23 #include "global.hxx"
24 #include "address.hxx"
25 #include <formula/grammar.hxx>
26 #include "scdllapi.h"
27 #include "rangelst.hxx"
29 #include <svl/listener.hxx>
31 #include <comphelper/stl_types.hxx>
32 #include <com/sun/star/sheet/ConditionOperator.hpp>
34 #include <rtl/math.hxx>
35 #include <tools/date.hxx>
36 #include <tools/link.hxx>
38 #include <map>
39 #include <memory>
40 #include <set>
42 class ScFormulaCell;
43 class ScTokenArray;
44 struct ScRefCellValue;
46 namespace sc {
48 struct RefUpdateContext;
49 struct RefUpdateInsertTabContext;
50 struct RefUpdateDeleteTabContext;
51 struct RefUpdateMoveTabContext;
55 // nOptions Flags
56 #define SC_COND_NOBLANKS 1
58 enum class ScConditionMode
60 Equal,
61 Less,
62 Greater,
63 EqLess,
64 EqGreater,
65 NotEqual,
66 Between,
67 NotBetween,
68 Duplicate,
69 NotDuplicate,
70 Direct,
71 Top10,
72 Bottom10,
73 TopPercent,
74 BottomPercent,
75 AboveAverage,
76 BelowAverage,
77 AboveEqualAverage,
78 BelowEqualAverage,
79 Error,
80 NoError,
81 BeginsWith,
82 EndsWith,
83 ContainsText,
84 NotContainsText,
85 NONE
88 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
89 template<typename charT, typename traits>
90 inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScConditionMode& rMode)
92 switch (rMode)
94 case ScConditionMode::Equal:
95 stream << "EQUAL";
96 break;
97 case ScConditionMode::Less:
98 stream << "LESS";
99 break;
100 case ScConditionMode::Greater:
101 stream << "GREATER";
102 break;
103 case ScConditionMode::EqLess:
104 stream << "EQLESS";
105 break;
106 case ScConditionMode::EqGreater:
107 stream << "EQGREATER";
108 break;
109 case ScConditionMode::NotEqual:
110 stream << "NOTEQUAL";
111 break;
112 case ScConditionMode::Between:
113 stream << "BETWEEN";
114 break;
115 case ScConditionMode::NotBetween:
116 stream << "NOTBETWEEN";
117 break;
118 case ScConditionMode::Duplicate:
119 stream << "DUPLICATE";
120 break;
121 case ScConditionMode::NotDuplicate:
122 stream << "NOTDUPLICATE";
123 break;
124 case ScConditionMode::Direct:
125 stream << "DIRECT";
126 break;
127 case ScConditionMode::Top10:
128 stream << "TOP10";
129 break;
130 case ScConditionMode::Bottom10:
131 stream << "BOTTOM10";
132 break;
133 case ScConditionMode::TopPercent:
134 stream << "TOPPERCENT";
135 break;
136 case ScConditionMode::BottomPercent:
137 stream << "BOTTOMPERCENT";
138 break;
139 case ScConditionMode::AboveAverage:
140 stream << "ABOVEAVERAGE";
141 break;
142 case ScConditionMode::BelowAverage:
143 stream << "BELOWAVERAGE";
144 break;
145 case ScConditionMode::AboveEqualAverage:
146 stream << "ABOVEEQUALAVERAGE";
147 break;
148 case ScConditionMode::BelowEqualAverage:
149 stream << "BELOWEQUALAVERAGE";
150 break;
151 case ScConditionMode::Error:
152 stream << "ERROR";
153 break;
154 case ScConditionMode::NoError:
155 stream << "NOERROR";
156 break;
157 case ScConditionMode::BeginsWith:
158 stream << "BEGINSWITH";
159 break;
160 case ScConditionMode::EndsWith:
161 stream << "ENDSWITH";
162 break;
163 case ScConditionMode::ContainsText:
164 stream << "CONTAINSTEXT";
165 break;
166 case ScConditionMode::NotContainsText:
167 stream << "NOTCONTAINSTEXT";
168 break;
169 case ScConditionMode::NONE:
170 stream << "NONE";
171 break;
172 default:
173 stream << "?(" << static_cast<int>(rMode) << ")";
174 break;
177 return stream;
180 class ScFormulaListener : public SvtListener
182 private:
183 mutable bool mbDirty;
184 ScDocument* mpDoc;
185 std::function<void()> maCallbackFunction;
187 void startListening(const ScTokenArray* pTokens, const ScRange& rPos);
189 public:
190 explicit ScFormulaListener(ScFormulaCell* pCell);
191 explicit ScFormulaListener(ScDocument* pDoc);
192 virtual ~ScFormulaListener() override;
194 void Notify( const SfxHint& rHint ) override;
196 bool NeedsRepaint() const;
198 void addTokenArray(const ScTokenArray* pTokens, const ScRange& rRange);
199 void stopListening();
200 void setCallback(const std::function<void()>& aCallbackFunction);
203 class ScConditionalFormat;
204 struct ScDataBarInfo;
205 struct ScIconSetInfo;
207 struct ScCondFormatData
209 ScCondFormatData():
210 pColorScale(nullptr),
211 pDataBar(nullptr),
212 pIconSet(nullptr) {}
214 Color* pColorScale;
215 ScDataBarInfo* pDataBar;
216 ScIconSetInfo* pIconSet;
217 OUString aStyleName;
220 class SC_DLLPUBLIC ScFormatEntry
222 public:
223 ScFormatEntry(ScDocument* pDoc);
224 virtual ~ScFormatEntry() {}
226 enum class Type
228 Condition,
229 Colorscale,
230 Databar,
231 Iconset,
232 Date
235 virtual Type GetType() const = 0;
236 virtual void UpdateReference( sc::RefUpdateContext& rCxt ) = 0;
237 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) = 0;
238 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) = 0;
239 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) = 0;
241 virtual ScFormatEntry* Clone( ScDocument* pDoc ) const = 0;
243 virtual void SetParent( ScConditionalFormat* pNew ) = 0;
245 bool operator==( const ScFormatEntry& ) const;
246 virtual bool IsEqual( const ScFormatEntry&, bool bIgnoreSrcPos ) const;
248 virtual void startRendering();
249 virtual void endRendering();
250 protected:
251 ScDocument* mpDoc;
255 template<typename charT, typename traits>
256 inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScFormatEntry::Type& rType)
258 switch (rType)
260 case ScFormatEntry::Type::Condition:
261 stream << "Condition";
262 break;
263 case ScFormatEntry::Type::Colorscale:
264 stream << "Colorscale";
265 break;
266 case ScFormatEntry::Type::Databar:
267 stream << "Databar";
268 break;
269 case ScFormatEntry::Type::Iconset:
270 stream << "Iconset";
271 break;
272 case ScFormatEntry::Type::Date:
273 stream << "Data";
274 break;
275 default:
276 stream << "?(" << static_cast<int>(rType) << ")";
277 break;
279 return stream;
282 class approx_less
284 public:
285 bool operator() (double nVal1, double nVal2) const
287 if(nVal1 < nVal2 && !rtl::math::approxEqual(nVal1, nVal2))
288 return true;
290 return false;
294 class SC_DLLPUBLIC ScConditionEntry : public ScFormatEntry
296 // stored data:
297 ScConditionMode eOp;
298 sal_uInt16 nOptions;
299 double nVal1; // input or calculated
300 double nVal2;
301 OUString aStrVal1; // input or calculated
302 OUString aStrVal2;
303 const OUString aStrNmsp1; // namespace to be used on (re)compilation, e.g. in XML import
304 const OUString aStrNmsp2; // namespace to be used on (re)compilation, e.g. in XML import
305 const formula::FormulaGrammar::Grammar eTempGrammar1; // grammar to be used on (re)compilation, e.g. in XML import
306 const formula::FormulaGrammar::Grammar eTempGrammar2; // grammar to be used on (re)compilation, e.g. in XML import
307 bool bIsStr1; // for recognition of empty strings
308 bool bIsStr2;
309 std::unique_ptr<ScTokenArray> pFormula1; // entered formula
310 std::unique_ptr<ScTokenArray> pFormula2;
311 ScAddress aSrcPos; // source position for formulas
312 // temporary data:
313 OUString aSrcString; // formula source position as text during XML import
314 std::unique_ptr<ScFormulaCell> pFCell1;
315 std::unique_ptr<ScFormulaCell> pFCell2;
316 bool bRelRef1;
317 bool bRelRef2;
318 bool bFirstRun;
319 std::unique_ptr<ScFormulaListener> mpListener;
321 void SimplifyCompiledFormula( std::unique_ptr<ScTokenArray>& rFormula,
322 double& rVal,
323 bool& rIsStr,
324 OUString& rStrVal );
326 void MakeCells( const ScAddress& rPos );
327 void Compile( const OUString& rExpr1, const OUString& rExpr2,
328 const OUString& rExprNmsp1, const OUString& rExprNmsp2,
329 formula::FormulaGrammar::Grammar eGrammar1,
330 formula::FormulaGrammar::Grammar eGrammar2,
331 bool bTextToReal );
332 void Interpret( const ScAddress& rPos );
334 bool IsValid( double nArg, const ScAddress& rPos ) const;
335 bool IsValidStr( const OUString& rArg, const ScAddress& rPos ) const;
336 void StartListening();
338 public:
339 ScConditionEntry( ScConditionMode eOper,
340 const OUString& rExpr1, const OUString& rExpr2,
341 ScDocument* pDocument, const ScAddress& rPos,
342 const OUString& rExprNmsp1, const OUString& rExprNmsp2,
343 formula::FormulaGrammar::Grammar eGrammar1,
344 formula::FormulaGrammar::Grammar eGrammar2 );
345 ScConditionEntry( ScConditionMode eOper,
346 const ScTokenArray* pArr1, const ScTokenArray* pArr2,
347 ScDocument* pDocument, const ScAddress& rPos );
348 ScConditionEntry( const ScConditionEntry& r ); // flat copy of formulas
349 // true copy of formulas (for Ref-Undo):
350 ScConditionEntry( ScDocument* pDocument, const ScConditionEntry& r );
351 virtual ~ScConditionEntry() override;
353 bool IsEqual( const ScFormatEntry& r, bool bIgnoreSrcPos ) const override;
355 virtual void SetParent( ScConditionalFormat* pNew ) override;
357 bool IsCellValid( ScRefCellValue& rCell, const ScAddress& rPos ) const;
359 ScConditionMode GetOperation() const { return eOp; }
360 void SetOperation(ScConditionMode eMode);
361 bool IsIgnoreBlank() const { return ( nOptions & SC_COND_NOBLANKS ) == 0; }
362 void SetIgnoreBlank(bool bSet);
363 const OUString& GetSrcString() const { return aSrcString; }
364 const ScAddress& GetSrcPos() const { return aSrcPos; }
366 ScAddress GetValidSrcPos() const; // adjusted to allow textual representation of expressions
368 void SetSrcString( const OUString& rNew ); // for XML import
370 void SetFormula1( const ScTokenArray& rArray );
371 void SetFormula2( const ScTokenArray& rArray );
373 OUString GetExpression( const ScAddress& rCursor, sal_uInt16 nPos, sal_uInt32 nNumFmt = 0,
374 const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
376 /** Create a flat copy using ScTokenArray copy-ctor with
377 shared tokens. */
378 ScTokenArray* CreateFlatCopiedTokenArray( sal_uInt16 nPos ) const;
380 void CompileAll();
381 void CompileXML();
382 virtual void UpdateReference( sc::RefUpdateContext& rCxt ) override;
383 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) override;
384 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) override;
385 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) override;
387 bool MarkUsedExternalReferences() const;
389 virtual Type GetType() const override { return Type::Condition; }
391 virtual ScFormatEntry* Clone(ScDocument* pDoc) const override;
393 static ScConditionMode GetModeFromApi(css::sheet::ConditionOperator nOperator);
395 virtual void endRendering() override;
396 virtual void startRendering() override;
398 bool NeedsRepaint() const;
400 protected:
401 virtual void DataChanged() const;
402 ScDocument* GetDocument() const { return mpDoc; }
403 ScConditionalFormat* pCondFormat;
405 private:
407 bool IsDuplicate(double nArg, const OUString& rStr) const;
408 bool IsTopNElement( double nArg ) const;
409 bool IsTopNPercent( double nArg ) const;
410 bool IsBottomNElement( double nArg ) const;
411 bool IsBottomNPercent( double nArg ) const;
412 bool IsAboveAverage( double nArg, bool bEqual ) const;
413 bool IsBelowAverage( double nArg, bool bEqual ) const;
415 bool IsError( const ScAddress& rPos ) const;
417 void FillCache() const;
419 struct ScConditionEntryCache
421 typedef std::map<OUString, sal_Int32> StringCacheType;
422 StringCacheType maStrings;
423 typedef std::map<double, sal_Int32, approx_less> ValueCacheType;
424 ValueCacheType maValues;
426 // cache them for easier access
427 size_t nValueItems;
429 ScConditionEntryCache():
430 nValueItems(0) {}
433 mutable std::unique_ptr<ScConditionEntryCache> mpCache;
436 // single condition entry for conditional formatting
437 class SC_DLLPUBLIC ScCondFormatEntry : public ScConditionEntry
439 OUString aStyleName;
441 public:
442 ScCondFormatEntry( ScConditionMode eOper,
443 const OUString& rExpr1, const OUString& rExpr2,
444 ScDocument* pDocument, const ScAddress& rPos,
445 const OUString& rStyle,
446 const OUString& rExprNmsp1 = EMPTY_OUSTRING,
447 const OUString& rExprNmsp2 = EMPTY_OUSTRING,
448 formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT,
449 formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT );
450 ScCondFormatEntry( ScConditionMode eOper,
451 const ScTokenArray* pArr1, const ScTokenArray* pArr2,
452 ScDocument* pDocument, const ScAddress& rPos,
453 const OUString& rStyle );
454 ScCondFormatEntry( const ScCondFormatEntry& r );
455 ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r );
456 virtual ~ScCondFormatEntry() override;
458 bool IsEqual( const ScFormatEntry& r, bool bIgnoreSrcPos ) const override;
460 const OUString& GetStyle() const { return aStyleName; }
461 void UpdateStyleName(const OUString& rNew) { aStyleName=rNew; }
462 virtual ScFormatEntry* Clone(ScDocument* pDoc) const override;
464 protected:
465 virtual void DataChanged() const override;
468 namespace condformat {
470 enum ScCondFormatDateType
472 TODAY,
473 YESTERDAY,
474 TOMORROW,
475 LAST7DAYS,
476 THISWEEK,
477 LASTWEEK,
478 NEXTWEEK,
479 THISMONTH,
480 LASTMONTH,
481 NEXTMONTH,
482 THISYEAR,
483 LASTYEAR,
484 NEXTYEAR
489 class SC_DLLPUBLIC ScCondDateFormatEntry : public ScFormatEntry
491 public:
492 ScCondDateFormatEntry(ScDocument* pDoc);
493 ScCondDateFormatEntry(ScDocument* pDoc, const ScCondDateFormatEntry& rEntry);
495 bool IsValid( const ScAddress& rPos ) const;
497 void SetDateType(condformat::ScCondFormatDateType eType);
498 condformat::ScCondFormatDateType GetDateType() const { return meType;}
500 const OUString& GetStyleName() const { return maStyleName;}
501 void SetStyleName( const OUString& rStyleName );
503 virtual Type GetType() const override { return Type::Date; }
504 virtual void UpdateReference( sc::RefUpdateContext& ) override {}
505 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& ) override {}
506 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& ) override {}
507 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& ) override {}
509 virtual ScFormatEntry* Clone( ScDocument* pDoc ) const override;
511 virtual void SetParent( ScConditionalFormat* ) override {}
513 virtual void startRendering() override;
514 virtual void endRendering() override;
516 private:
517 condformat::ScCondFormatDateType meType;
519 mutable std::unique_ptr<Date> mpCache;
521 OUString maStyleName;
524 // complete conditional formatting
525 class SC_DLLPUBLIC ScConditionalFormat
527 ScDocument* pDoc;
528 sal_uInt32 nKey; // Index in attributes
530 std::vector<std::unique_ptr<ScFormatEntry>> maEntries;
531 ScRangeList maRanges; // Ranges for conditional format
533 public:
534 ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument);
535 ~ScConditionalFormat();
536 ScConditionalFormat(const ScConditionalFormat&) = delete;
537 const ScConditionalFormat& operator=(const ScConditionalFormat&) = delete;
539 // true copy of formulas (for Ref-Undo / between documents)
540 ScConditionalFormat* Clone(ScDocument* pNewDoc = nullptr) const;
542 void AddEntry( ScFormatEntry* pNew );
543 void RemoveEntry(size_t nIndex);
544 void SetRange( const ScRangeList& rRanges );
545 const ScRangeList& GetRange() const { return maRanges; }
546 // don't use the same name as for the const version
547 ScRangeList& GetRangeList() { return maRanges; }
549 bool IsEmpty() const;
550 size_t size() const;
552 void CompileAll();
553 void CompileXML();
554 void UpdateReference( sc::RefUpdateContext& rCxt, bool bCopyAsMove = false );
555 void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
556 void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
557 void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt );
559 void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize);
560 void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize);
562 void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
563 void RenameCellStyle( const OUString& rOld, const OUString& rNew );
565 const ScFormatEntry* GetEntry( sal_uInt16 nPos ) const;
567 const OUString& GetCellStyle( ScRefCellValue& rCell, const ScAddress& rPos ) const;
569 ScCondFormatData GetData( ScRefCellValue& rCell, const ScAddress& rPos ) const;
571 bool EqualEntries( const ScConditionalFormat& r, bool bIgnoreSrcPos = false ) const;
573 void DoRepaint();
575 sal_uInt32 GetKey() const { return nKey; }
576 void SetKey(sal_uInt32 nNew) { nKey = nNew; } // only if not inserted!
578 bool MarkUsedExternalReferences() const;
580 // sorted (via std::set) by Index
581 bool operator < ( const ScConditionalFormat& r ) const { return nKey < r.nKey; }
583 void startRendering();
584 void endRendering();
587 // List of all conditional formats in a sheet
588 class SC_DLLPUBLIC ScConditionalFormatList
590 private:
591 typedef std::set<std::unique_ptr<ScConditionalFormat>,
592 comphelper::UniquePtrValueLess<ScConditionalFormat>> ConditionalFormatContainer;
593 ConditionalFormatContainer m_ConditionalFormats;
595 void operator =(ScConditionalFormatList const &) = delete;
597 public:
598 ScConditionalFormatList() {}
599 ScConditionalFormatList(const ScConditionalFormatList& rList);
600 ScConditionalFormatList(ScDocument* pDoc, const ScConditionalFormatList& rList);
602 void InsertNew( ScConditionalFormat* pNew );
605 * Checks that all cond formats have a non empty range.
606 * Deletes empty cond formats. Optionally call rLink
607 * on the empty format before deleting it.
608 * @return true if all cond formats were valid
610 bool CheckAllEntries(const Link<ScConditionalFormat*,void>& rLink = Link<ScConditionalFormat*,void>());
612 ScConditionalFormat* GetFormat( sal_uInt32 nKey );
613 const ScConditionalFormat* GetFormat( sal_uInt32 nKey ) const;
615 void CompileAll();
616 void CompileXML();
617 void UpdateReference( sc::RefUpdateContext& rCxt );
618 void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
619 void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
620 void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt );
622 void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize);
623 void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize);
625 void RenameCellStyle( const OUString& rOld, const OUString& rNew );
626 void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
628 typedef ConditionalFormatContainer::iterator iterator;
629 typedef ConditionalFormatContainer::const_iterator const_iterator;
631 ScRangeList GetCombinedRange() const;
633 void RemoveFromDocument(ScDocument* pDoc) const;
634 void AddToDocument(ScDocument* pDoc) const;
636 iterator begin();
637 const_iterator begin() const;
638 iterator end();
639 const_iterator end() const;
641 size_t size() const;
643 void erase(sal_uLong nIndex);
644 void clear();
646 void startRendering();
647 void endRendering();
649 sal_uInt32 getMaxKey() const;
652 #endif
654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */