1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
24 #include "address.hxx"
25 #include <formula/grammar.hxx>
27 #include "rangelst.hxx"
29 #include <svl/hint.hxx>
30 #include <svl/listener.hxx>
31 #include <svl/broadcast.hxx>
33 #include <comphelper/stl_types.hxx>
35 #include <rtl/math.hxx>
36 #include <tools/date.hxx>
44 struct ScRefCellValue
;
48 struct RefUpdateContext
;
49 struct RefUpdateInsertTabContext
;
50 struct RefUpdateDeleteTabContext
;
51 struct RefUpdateMoveTabContext
;
56 #define SC_COND_NOBLANKS 1
74 SC_COND_BOTTOM_PERCENT
,
75 SC_COND_ABOVE_AVERAGE
,
76 SC_COND_BELOW_AVERAGE
,
77 SC_COND_ABOVE_EQUAL_AVERAGE
,
78 SC_COND_BELOW_EQUAL_AVERAGE
,
83 SC_COND_CONTAINS_TEXT
,
84 SC_COND_NOT_CONTAINS_TEXT
,
88 class ScFormulaListener
: public SvtListener
91 std::vector
<ScRange
> maCells
;
94 std::function
<void()> maCallbackFunction
;
96 void startListening(ScTokenArray
* pTokens
, const ScRange
& rPos
);
99 explicit ScFormulaListener(ScFormulaCell
* pCell
);
100 explicit ScFormulaListener(ScDocument
* pDoc
);
101 virtual ~ScFormulaListener() override
;
103 void Notify( const SfxHint
& rHint
) override
;
105 bool NeedsRepaint() const;
107 void addTokenArray(ScTokenArray
* pTokens
, const ScRange
& rRange
);
108 void stopListening();
109 void setCallback(const std::function
<void()>& aCallbackFunction
);
112 class ScConditionalFormat
;
113 struct ScDataBarInfo
;
114 struct ScIconSetInfo
;
119 enum ScFormatEntryType
130 struct ScCondFormatData
133 pColorScale(nullptr),
138 ScDataBarInfo
* pDataBar
;
139 ScIconSetInfo
* pIconSet
;
143 class SC_DLLPUBLIC ScFormatEntry
146 ScFormatEntry(ScDocument
* pDoc
);
147 virtual ~ScFormatEntry() {}
149 virtual condformat::ScFormatEntryType
GetType() const = 0;
150 virtual void UpdateReference( sc::RefUpdateContext
& rCxt
) = 0;
151 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
) = 0;
152 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
) = 0;
153 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
) = 0;
155 virtual ScFormatEntry
* Clone( ScDocument
* pDoc
) const = 0;
157 virtual void SetParent( ScConditionalFormat
* pNew
) = 0;
159 bool operator==( const ScFormatEntry
& ) const;
161 virtual void startRendering();
162 virtual void endRendering();
168 class approx_less
: public std::binary_function
<double, double, bool>
171 bool operator() (double nVal1
, double nVal2
) const
173 if(nVal1
< nVal2
&& !rtl::math::approxEqual(nVal1
, nVal2
))
180 class SC_DLLPUBLIC ScConditionEntry
: public ScFormatEntry
185 double nVal1
; // input or calculated
187 OUString aStrVal1
; // input or calculated
189 OUString aStrNmsp1
; // namespace to be used on (re)compilation, e.g. in XML import
190 OUString aStrNmsp2
; // namespace to be used on (re)compilation, e.g. in XML import
191 formula::FormulaGrammar::Grammar eTempGrammar1
; // grammar to be used on (re)compilation, e.g. in XML import
192 formula::FormulaGrammar::Grammar eTempGrammar2
; // grammar to be used on (re)compilation, e.g. in XML import
193 bool bIsStr1
; // for recognition of empty strings
195 ScTokenArray
* pFormula1
; // entered formula
196 ScTokenArray
* pFormula2
;
197 ScAddress aSrcPos
; // source position for formulas
199 OUString aSrcString
; // formula source position as text during XML import
200 ScFormulaCell
* pFCell1
;
201 ScFormulaCell
* pFCell2
;
205 std::unique_ptr
<ScFormulaListener
> mpListener
;
207 void MakeCells( const ScAddress
& rPos
);
208 void Compile( const OUString
& rExpr1
, const OUString
& rExpr2
,
209 const OUString
& rExprNmsp1
, const OUString
& rExprNmsp2
,
210 formula::FormulaGrammar::Grammar eGrammar1
,
211 formula::FormulaGrammar::Grammar eGrammar2
,
213 void Interpret( const ScAddress
& rPos
);
215 bool IsValid( double nArg
, const ScAddress
& rPos
) const;
216 bool IsValidStr( const OUString
& rArg
, const ScAddress
& rPos
) const;
217 void StartListening();
220 ScConditionEntry( ScConditionMode eOper
,
221 const OUString
& rExpr1
, const OUString
& rExpr2
,
222 ScDocument
* pDocument
, const ScAddress
& rPos
,
223 const OUString
& rExprNmsp1
, const OUString
& rExprNmsp2
,
224 formula::FormulaGrammar::Grammar eGrammar1
,
225 formula::FormulaGrammar::Grammar eGrammar2
);
226 ScConditionEntry( ScConditionMode eOper
,
227 const ScTokenArray
* pArr1
, const ScTokenArray
* pArr2
,
228 ScDocument
* pDocument
, const ScAddress
& rPos
);
229 ScConditionEntry( const ScConditionEntry
& r
); // flat copy of formulas
230 // true copy of formulas (for Ref-Undo):
231 ScConditionEntry( ScDocument
* pDocument
, const ScConditionEntry
& r
);
232 virtual ~ScConditionEntry() override
;
234 bool operator== ( const ScConditionEntry
& r
) const;
236 virtual void SetParent( ScConditionalFormat
* pNew
) override
;
238 bool IsCellValid( ScRefCellValue
& rCell
, const ScAddress
& rPos
) const;
240 ScConditionMode
GetOperation() const { return eOp
; }
241 void SetOperation(ScConditionMode eMode
);
242 bool IsIgnoreBlank() const { return ( nOptions
& SC_COND_NOBLANKS
) == 0; }
243 void SetIgnoreBlank(bool bSet
);
244 const ScAddress
& GetSrcPos() const { return aSrcPos
; }
246 ScAddress
GetValidSrcPos() const; // adjusted to allow textual representation of expressions
248 void SetSrcString( const OUString
& rNew
); // for XML import
250 void SetFormula1( const ScTokenArray
& rArray
);
251 void SetFormula2( const ScTokenArray
& rArray
);
253 OUString
GetExpression( const ScAddress
& rCursor
, sal_uInt16 nPos
, sal_uLong nNumFmt
= 0,
254 const formula::FormulaGrammar::Grammar eGrammar
= formula::FormulaGrammar::GRAM_DEFAULT
) const;
256 /** Create a flat copy using ScTokenArray copy-ctor with
258 ScTokenArray
* CreateFlatCopiedTokenArray( sal_uInt16 nPos
) const;
262 virtual void UpdateReference( sc::RefUpdateContext
& rCxt
) override
;
263 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
) override
;
264 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
) override
;
265 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
) override
;
267 bool MarkUsedExternalReferences() const;
269 virtual condformat::ScFormatEntryType
GetType() const override
{ return condformat::CONDITION
; }
271 virtual ScFormatEntry
* Clone(ScDocument
* pDoc
) const override
;
273 static ScConditionMode
GetModeFromApi(sal_Int32 nOperator
);
275 virtual void endRendering() override
;
276 virtual void startRendering() override
;
278 bool NeedsRepaint() const;
281 virtual void DataChanged() const;
282 ScDocument
* GetDocument() const { return mpDoc
; }
283 ScConditionalFormat
* pCondFormat
;
287 bool IsDuplicate(double nArg
, const OUString
& rStr
) const;
288 bool IsTopNElement( double nArg
) const;
289 bool IsTopNPercent( double nArg
) const;
290 bool IsBottomNElement( double nArg
) const;
291 bool IsBottomNPercent( double nArg
) const;
292 bool IsAboveAverage( double nArg
, bool bEqual
) const;
293 bool IsBelowAverage( double nArg
, bool bEqual
) const;
295 bool IsError( const ScAddress
& rPos
) const;
297 void FillCache() const;
299 struct ScConditionEntryCache
301 typedef std::map
<OUString
, sal_Int32
> StringCacheType
;
302 StringCacheType maStrings
;
303 typedef std::map
<double, sal_Int32
, approx_less
> ValueCacheType
;
304 ValueCacheType maValues
;
306 // cache them for easier access
309 ScConditionEntryCache():
313 mutable std::unique_ptr
<ScConditionEntryCache
> mpCache
;
316 // single condition entry for conditional formatting
317 class SC_DLLPUBLIC ScCondFormatEntry
: public ScConditionEntry
321 using ScConditionEntry::operator==;
324 ScCondFormatEntry( ScConditionMode eOper
,
325 const OUString
& rExpr1
, const OUString
& rExpr2
,
326 ScDocument
* pDocument
, const ScAddress
& rPos
,
327 const OUString
& rStyle
,
328 const OUString
& rExprNmsp1
= EMPTY_OUSTRING
,
329 const OUString
& rExprNmsp2
= EMPTY_OUSTRING
,
330 formula::FormulaGrammar::Grammar eGrammar1
= formula::FormulaGrammar::GRAM_DEFAULT
,
331 formula::FormulaGrammar::Grammar eGrammar2
= formula::FormulaGrammar::GRAM_DEFAULT
);
332 ScCondFormatEntry( ScConditionMode eOper
,
333 const ScTokenArray
* pArr1
, const ScTokenArray
* pArr2
,
334 ScDocument
* pDocument
, const ScAddress
& rPos
,
335 const OUString
& rStyle
);
336 ScCondFormatEntry( const ScCondFormatEntry
& r
);
337 ScCondFormatEntry( ScDocument
* pDocument
, const ScCondFormatEntry
& r
);
338 virtual ~ScCondFormatEntry() override
;
340 bool operator== ( const ScCondFormatEntry
& r
) const;
342 const OUString
& GetStyle() const { return aStyleName
; }
343 void UpdateStyleName(const OUString
& rNew
) { aStyleName
=rNew
; }
344 virtual ScFormatEntry
* Clone(ScDocument
* pDoc
) const override
;
347 virtual void DataChanged() const override
;
350 namespace condformat
{
352 enum ScCondFormatDateType
371 class SC_DLLPUBLIC ScCondDateFormatEntry
: public ScFormatEntry
374 ScCondDateFormatEntry(ScDocument
* pDoc
);
375 ScCondDateFormatEntry(ScDocument
* pDoc
, const ScCondDateFormatEntry
& rEntry
);
377 bool IsValid( const ScAddress
& rPos
) const;
379 void SetDateType(condformat::ScCondFormatDateType eType
);
380 condformat::ScCondFormatDateType
GetDateType() const { return meType
;}
382 const OUString
& GetStyleName() const { return maStyleName
;}
383 void SetStyleName( const OUString
& rStyleName
);
385 virtual condformat::ScFormatEntryType
GetType() const override
{ return condformat::DATE
; }
386 virtual void UpdateReference( sc::RefUpdateContext
& ) override
{}
387 virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext
& ) override
{}
388 virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& ) override
{}
389 virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext
& ) override
{}
391 virtual ScFormatEntry
* Clone( ScDocument
* pDoc
) const override
;
393 virtual void SetParent( ScConditionalFormat
* ) override
{}
395 virtual void startRendering() override
;
396 virtual void endRendering() override
;
399 condformat::ScCondFormatDateType meType
;
401 mutable std::unique_ptr
<Date
> mpCache
;
403 OUString maStyleName
;
406 // complete conditional formatting
407 class SC_DLLPUBLIC ScConditionalFormat
410 sal_uInt32 nKey
; // Index in attributes
412 typedef std::vector
<std::unique_ptr
<ScFormatEntry
>> CondFormatContainer
;
413 CondFormatContainer maEntries
;
414 ScRangeList maRanges
; // Ranges for conditional format
417 ScConditionalFormat(sal_uInt32 nNewKey
, ScDocument
* pDocument
);
418 ~ScConditionalFormat();
419 ScConditionalFormat(const ScConditionalFormat
&) = delete;
420 const ScConditionalFormat
& operator=(const ScConditionalFormat
&) = delete;
422 // true copy of formulas (for Ref-Undo / between documents)
423 ScConditionalFormat
* Clone(ScDocument
* pNewDoc
= nullptr) const;
425 void AddEntry( ScFormatEntry
* pNew
);
426 void RemoveEntry(size_t nIndex
);
427 void SetRange( const ScRangeList
& rRanges
);
428 const ScRangeList
& GetRange() const { return maRanges
; }
429 // don't use the same name as for the const version
430 ScRangeList
& GetRangeList() { return maRanges
; }
432 bool IsEmpty() const;
437 void UpdateReference( sc::RefUpdateContext
& rCxt
, bool bCopyAsMove
= false );
438 void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
);
439 void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
);
440 void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
);
442 void InsertRow(SCTAB nTab
, SCCOL nColStart
, SCCOL nColEnd
, SCROW nRowStart
, SCSIZE nSize
);
443 void InsertCol(SCTAB nTab
, SCROW nRowStart
, SCROW nRowEnd
, SCCOL nColStart
, SCSIZE nSize
);
445 void DeleteArea( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
446 void RenameCellStyle( const OUString
& rOld
, const OUString
& rNew
);
448 const ScFormatEntry
* GetEntry( sal_uInt16 nPos
) const;
450 const OUString
& GetCellStyle( ScRefCellValue
& rCell
, const ScAddress
& rPos
) const;
452 ScCondFormatData
GetData( ScRefCellValue
& rCell
, const ScAddress
& rPos
) const;
454 bool EqualEntries( const ScConditionalFormat
& r
) const;
458 sal_uInt32
GetKey() const { return nKey
; }
459 void SetKey(sal_uInt32 nNew
) { nKey
= nNew
; } // only if not inserted!
461 bool MarkUsedExternalReferences() const;
463 // sorted (via std::set) by Index
464 bool operator < ( const ScConditionalFormat
& r
) const { return nKey
< r
.nKey
; }
466 void startRendering();
470 // List of all conditional formats in a sheet
471 class SC_DLLPUBLIC ScConditionalFormatList
474 typedef std::set
<std::unique_ptr
<ScConditionalFormat
>,
475 comphelper::UniquePtrValueLess
<ScConditionalFormat
>> ConditionalFormatContainer
;
476 ConditionalFormatContainer m_ConditionalFormats
;
478 void operator =(ScConditionalFormatList
const &) = delete;
481 ScConditionalFormatList() {}
482 ScConditionalFormatList(const ScConditionalFormatList
& rList
);
483 ScConditionalFormatList(ScDocument
* pDoc
, const ScConditionalFormatList
& rList
);
484 ~ScConditionalFormatList() {}
486 void InsertNew( ScConditionalFormat
* pNew
);
489 * Checks that all cond formats have a non empty range.
490 * Deletes empty cond formats.
491 * @return true if all cond formats were valid
493 bool CheckAllEntries();
495 ScConditionalFormat
* GetFormat( sal_uInt32 nKey
);
496 const ScConditionalFormat
* GetFormat( sal_uInt32 nKey
) const;
500 void UpdateReference( sc::RefUpdateContext
& rCxt
);
501 void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
);
502 void UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
);
503 void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
);
505 void InsertRow(SCTAB nTab
, SCCOL nColStart
, SCCOL nColEnd
, SCROW nRowStart
, SCSIZE nSize
);
506 void InsertCol(SCTAB nTab
, SCROW nRowStart
, SCROW nRowEnd
, SCCOL nColStart
, SCSIZE nSize
);
508 void RenameCellStyle( const OUString
& rOld
, const OUString
& rNew
);
509 void DeleteArea( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
);
511 typedef ConditionalFormatContainer::iterator iterator
;
512 typedef ConditionalFormatContainer::const_iterator const_iterator
;
515 const_iterator
begin() const;
517 const_iterator
end() const;
521 void erase(sal_uLong nIndex
);
524 void startRendering();
527 sal_uInt32
getMaxKey() const;
532 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */