/src/libreoffice/sc/inc/conditio.hxx
Line | Count | Source |
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 | | #pragma once |
21 | | |
22 | | #include <tools/solar.h> |
23 | | #include <tools/color.hxx> |
24 | | #include "address.hxx" |
25 | | #include <formula/grammar.hxx> |
26 | | #include "scdllapi.h" |
27 | | #include "rangelst.hxx" |
28 | | #include "tokenarray.hxx" |
29 | | |
30 | | #include <svl/listener.hxx> |
31 | | |
32 | | #include <com/sun/star/sheet/ConditionOperator.hpp> |
33 | | |
34 | | #include <rtl/math.hxx> |
35 | | #include <tools/date.hxx> |
36 | | #include <tools/link.hxx> |
37 | | #include <o3tl/lru_map.hxx> |
38 | | #include <vcl/dropcache.hxx> |
39 | | |
40 | | #include <optional> |
41 | | #include <map> |
42 | | #include <memory> |
43 | | #include <set> |
44 | | |
45 | | class RepaintInIdle; |
46 | | class ScFormulaCell; |
47 | | class ScTokenArray; |
48 | | struct ScRefCellValue; |
49 | | |
50 | | namespace sc { |
51 | | |
52 | | struct RefUpdateContext; |
53 | | struct RefUpdateInsertTabContext; |
54 | | struct RefUpdateDeleteTabContext; |
55 | | struct RefUpdateMoveTabContext; |
56 | | |
57 | | } |
58 | | |
59 | | // nOptions Flags |
60 | 996 | #define SC_COND_NOBLANKS 1 |
61 | 30.9k | #define SC_COND_CASESENS 2 |
62 | | |
63 | | enum class ScConditionMode |
64 | | { |
65 | | Equal, |
66 | | Less, |
67 | | Greater, |
68 | | EqLess, |
69 | | EqGreater, |
70 | | NotEqual, |
71 | | Between, |
72 | | NotBetween, |
73 | | Duplicate, |
74 | | NotDuplicate, |
75 | | Direct, |
76 | | Top10, |
77 | | Bottom10, |
78 | | TopPercent, |
79 | | BottomPercent, |
80 | | AboveAverage, |
81 | | BelowAverage, |
82 | | AboveEqualAverage, |
83 | | BelowEqualAverage, |
84 | | Error, |
85 | | NoError, |
86 | | BeginsWith, |
87 | | EndsWith, |
88 | | ContainsText, |
89 | | NotContainsText, |
90 | | NONE |
91 | | }; |
92 | | |
93 | | // For use in SAL_DEBUG etc. Output format not guaranteed to be stable. |
94 | | template<typename charT, typename traits> |
95 | | inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScConditionMode& rMode) |
96 | | { |
97 | | switch (rMode) |
98 | | { |
99 | | case ScConditionMode::Equal: |
100 | | stream << "EQUAL"; |
101 | | break; |
102 | | case ScConditionMode::Less: |
103 | | stream << "LESS"; |
104 | | break; |
105 | | case ScConditionMode::Greater: |
106 | | stream << "GREATER"; |
107 | | break; |
108 | | case ScConditionMode::EqLess: |
109 | | stream << "EQLESS"; |
110 | | break; |
111 | | case ScConditionMode::EqGreater: |
112 | | stream << "EQGREATER"; |
113 | | break; |
114 | | case ScConditionMode::NotEqual: |
115 | | stream << "NOTEQUAL"; |
116 | | break; |
117 | | case ScConditionMode::Between: |
118 | | stream << "BETWEEN"; |
119 | | break; |
120 | | case ScConditionMode::NotBetween: |
121 | | stream << "NOTBETWEEN"; |
122 | | break; |
123 | | case ScConditionMode::Duplicate: |
124 | | stream << "DUPLICATE"; |
125 | | break; |
126 | | case ScConditionMode::NotDuplicate: |
127 | | stream << "NOTDUPLICATE"; |
128 | | break; |
129 | | case ScConditionMode::Direct: |
130 | | stream << "DIRECT"; |
131 | | break; |
132 | | case ScConditionMode::Top10: |
133 | | stream << "TOP10"; |
134 | | break; |
135 | | case ScConditionMode::Bottom10: |
136 | | stream << "BOTTOM10"; |
137 | | break; |
138 | | case ScConditionMode::TopPercent: |
139 | | stream << "TOPPERCENT"; |
140 | | break; |
141 | | case ScConditionMode::BottomPercent: |
142 | | stream << "BOTTOMPERCENT"; |
143 | | break; |
144 | | case ScConditionMode::AboveAverage: |
145 | | stream << "ABOVEAVERAGE"; |
146 | | break; |
147 | | case ScConditionMode::BelowAverage: |
148 | | stream << "BELOWAVERAGE"; |
149 | | break; |
150 | | case ScConditionMode::AboveEqualAverage: |
151 | | stream << "ABOVEEQUALAVERAGE"; |
152 | | break; |
153 | | case ScConditionMode::BelowEqualAverage: |
154 | | stream << "BELOWEQUALAVERAGE"; |
155 | | break; |
156 | | case ScConditionMode::Error: |
157 | | stream << "ERROR"; |
158 | | break; |
159 | | case ScConditionMode::NoError: |
160 | | stream << "NOERROR"; |
161 | | break; |
162 | | case ScConditionMode::BeginsWith: |
163 | | stream << "BEGINSWITH"; |
164 | | break; |
165 | | case ScConditionMode::EndsWith: |
166 | | stream << "ENDSWITH"; |
167 | | break; |
168 | | case ScConditionMode::ContainsText: |
169 | | stream << "CONTAINSTEXT"; |
170 | | break; |
171 | | case ScConditionMode::NotContainsText: |
172 | | stream << "NOTCONTAINSTEXT"; |
173 | | break; |
174 | | case ScConditionMode::NONE: |
175 | | stream << "NONE"; |
176 | | break; |
177 | | default: |
178 | | stream << "?(" << static_cast<int>(rMode) << ")"; |
179 | | break; |
180 | | } |
181 | | |
182 | | return stream; |
183 | | } |
184 | | |
185 | | class ScFormulaListener final : public SvtListener |
186 | | { |
187 | | private: |
188 | | mutable bool mbDirty; |
189 | | ScDocument& mrDoc; |
190 | | std::function<void()> maCallbackFunction; |
191 | | |
192 | | void startListening(const ScTokenArray* pTokens, const ScRange& rPos); |
193 | | void startListening(const ScRangeList& rPos); |
194 | | |
195 | | public: |
196 | | explicit ScFormulaListener(ScFormulaCell* pCell); |
197 | | explicit ScFormulaListener(ScDocument& rDoc); |
198 | | explicit ScFormulaListener(ScDocument& rDoc, const ScRangeList& rRange); |
199 | | virtual ~ScFormulaListener() override; |
200 | | |
201 | | void Notify( const SfxHint& rHint ) override; |
202 | | |
203 | | bool NeedsRepaint() const; |
204 | | |
205 | | void addTokenArray(const ScTokenArray* pTokens, const ScRange& rRange); |
206 | | void stopListening(); |
207 | | void setCallback(const std::function<void()>& aCallbackFunction); |
208 | | |
209 | | }; |
210 | | |
211 | | class ScConditionalFormat; |
212 | | struct ScDataBarInfo; |
213 | | struct ScIconSetInfo; |
214 | | |
215 | | struct SC_DLLPUBLIC ScCondFormatData |
216 | | { |
217 | | ScCondFormatData(); |
218 | | ScCondFormatData(ScCondFormatData&&); |
219 | | ~ScCondFormatData(); |
220 | | |
221 | | std::optional<Color> mxColorScale; |
222 | | std::unique_ptr<ScDataBarInfo> pDataBar; |
223 | | std::unique_ptr<ScIconSetInfo> pIconSet; |
224 | | OUString aStyleName; |
225 | | }; |
226 | | |
227 | | class SC_DLLPUBLIC ScFormatEntry |
228 | | { |
229 | | public: |
230 | | ScFormatEntry(ScDocument& rDoc); |
231 | 11.6k | virtual ~ScFormatEntry() {} |
232 | | |
233 | | enum class Type |
234 | | { |
235 | | Condition, |
236 | | ExtCondition, |
237 | | Colorscale, |
238 | | Databar, |
239 | | Iconset, |
240 | | Date |
241 | | }; |
242 | | |
243 | | virtual Type GetType() const = 0; |
244 | | virtual void UpdateReference( sc::RefUpdateContext& rCxt ) = 0; |
245 | | virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) = 0; |
246 | | virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) = 0; |
247 | | virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) = 0; |
248 | | |
249 | | virtual ScFormatEntry* Clone( ScDocument& rDoc ) const = 0; |
250 | | |
251 | | virtual void SetParent( ScConditionalFormat* pNew ) = 0; |
252 | | |
253 | | bool operator==( const ScFormatEntry& ) const; |
254 | | virtual bool IsEqual( const ScFormatEntry&, bool bIgnoreSrcPos ) const; |
255 | | |
256 | | virtual void startRendering(); |
257 | | virtual void endRendering(); |
258 | | virtual void updateValues(); |
259 | | protected: |
260 | | ScDocument& mrDoc; |
261 | | |
262 | | }; |
263 | | |
264 | | template<typename charT, typename traits> |
265 | | inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ScFormatEntry::Type& rType) |
266 | | { |
267 | | switch (rType) |
268 | | { |
269 | | case ScFormatEntry::Type::Condition: |
270 | | stream << "Condition"; |
271 | | break; |
272 | | case ScFormatEntry::Type::ExtCondition: |
273 | | stream << "ExtCondition"; |
274 | | break; |
275 | | case ScFormatEntry::Type::Colorscale: |
276 | | stream << "Colorscale"; |
277 | | break; |
278 | | case ScFormatEntry::Type::Databar: |
279 | | stream << "Databar"; |
280 | | break; |
281 | | case ScFormatEntry::Type::Iconset: |
282 | | stream << "Iconset"; |
283 | | break; |
284 | | case ScFormatEntry::Type::Date: |
285 | | stream << "Date"; |
286 | | break; |
287 | | default: |
288 | | stream << "?(" << static_cast<int>(rType) << ")"; |
289 | | break; |
290 | | } |
291 | | return stream; |
292 | | } |
293 | | |
294 | | class approx_less |
295 | | { |
296 | | public: |
297 | | bool operator() (double nVal1, double nVal2) const |
298 | 1.54k | { |
299 | 1.54k | if(nVal1 < nVal2 && !rtl::math::approxEqual(nVal1, nVal2)) |
300 | 883 | return true; |
301 | | |
302 | 659 | return false; |
303 | 1.54k | } |
304 | | }; |
305 | | |
306 | | class SAL_DLLPUBLIC_RTTI ScConditionEntry : public ScFormatEntry, public CacheOwner |
307 | | { |
308 | | // stored data: |
309 | | ScConditionMode eOp; |
310 | | sal_uInt16 nOptions; |
311 | | double nVal1; // input or calculated |
312 | | double nVal2; |
313 | | OUString aStrVal1; // input or calculated |
314 | | OUString aStrVal2; |
315 | | const OUString aStrNmsp1; // namespace to be used on (re)compilation, e.g. in XML import |
316 | | const OUString aStrNmsp2; // namespace to be used on (re)compilation, e.g. in XML import |
317 | | const formula::FormulaGrammar::Grammar eTempGrammar1; // grammar to be used on (re)compilation, e.g. in XML import |
318 | | const formula::FormulaGrammar::Grammar eTempGrammar2; // grammar to be used on (re)compilation, e.g. in XML import |
319 | | bool bIsStr1; // for recognition of empty strings |
320 | | bool bIsStr2; |
321 | | std::unique_ptr<ScTokenArray> pFormula1; // entered formula |
322 | | std::unique_ptr<ScTokenArray> pFormula2; |
323 | | ScAddress aSrcPos; // source position for formulas |
324 | | // temporary data: |
325 | | OUString aSrcString; // formula source position as text during XML import |
326 | | std::unique_ptr<ScFormulaCell> pFCell1; |
327 | | std::unique_ptr<ScFormulaCell> pFCell2; |
328 | | typedef o3tl::lru_map<ScAddress, std::unique_ptr<ScFormulaCell>> RelRefCells; |
329 | | std::unique_ptr<RelRefCells> xRelRefCells1; |
330 | | std::unique_ptr<RelRefCells> xRelRefCells2; |
331 | | bool bRelRef1; |
332 | | bool bRelRef2; |
333 | | bool bFirstRun; |
334 | | std::unique_ptr<ScFormulaListener> mpListener; |
335 | | Type eConditionType; //It can be Condition or ExtCondition |
336 | | |
337 | | static void SimplifyCompiledFormula( std::unique_ptr<ScTokenArray>& rFormula, |
338 | | double& rVal, |
339 | | bool& rIsStr, |
340 | | OUString& rStrVal ); |
341 | | |
342 | | void MakeCells( const ScAddress& rPos ); |
343 | | void Compile( const OUString& rExpr1, const OUString& rExpr2, |
344 | | const OUString& rExprNmsp1, const OUString& rExprNmsp2, |
345 | | formula::FormulaGrammar::Grammar eGrammar1, |
346 | | formula::FormulaGrammar::Grammar eGrammar2, |
347 | | bool bTextToReal ); |
348 | | void Interpret( const ScAddress& rPos ); |
349 | | |
350 | | bool IsValid( double nArg, const ScAddress& rPos ) const; |
351 | | bool IsValidStr( const OUString& rArg, const ScAddress& rPos ) const; |
352 | | void StartListening(); |
353 | | |
354 | | static std::unique_ptr<RelRefCells> makeRelRefCells(); |
355 | | |
356 | | public: |
357 | | ScConditionEntry( ScConditionMode eOper, |
358 | | const OUString& rExpr1, const OUString& rExpr2, |
359 | | ScDocument& rDocument, const ScAddress& rPos, |
360 | | const OUString& rExprNmsp1, const OUString& rExprNmsp2, |
361 | | formula::FormulaGrammar::Grammar eGrammar1, |
362 | | formula::FormulaGrammar::Grammar eGrammar2, |
363 | | Type eType = Type::Condition ); |
364 | | ScConditionEntry( ScConditionMode eOper, |
365 | | const ScTokenArray* pArr1, const ScTokenArray* pArr2, |
366 | | ScDocument& rDocument, const ScAddress& rPos ); |
367 | | ScConditionEntry( const ScConditionEntry& r ); // flat copy of formulas |
368 | | // true copy of formulas (for Ref-Undo): |
369 | | ScConditionEntry( ScDocument& rDocument, const ScConditionEntry& r ); |
370 | | virtual ~ScConditionEntry() override; |
371 | | |
372 | | bool IsEqual( const ScFormatEntry& r, bool bIgnoreSrcPos ) const override; |
373 | | |
374 | | virtual void SetParent( ScConditionalFormat* pNew ) override; |
375 | | |
376 | | SC_DLLPUBLIC bool IsCellValid( const ScRefCellValue& rCell, const ScAddress& rPos ) const; |
377 | | |
378 | 0 | ScConditionMode GetOperation() const { return eOp; } |
379 | | void SetOperation(ScConditionMode eMode); |
380 | | |
381 | 0 | bool IsIgnoreBlank() const { return ( nOptions & SC_COND_NOBLANKS ) == 0; } |
382 | | SC_DLLPUBLIC void SetIgnoreBlank(bool bSet); |
383 | | |
384 | 30.0k | bool IsCaseSensitive() const { return ( nOptions & SC_COND_CASESENS ) != 0; } |
385 | | SC_DLLPUBLIC void SetCaseSensitive(bool bSet); |
386 | | |
387 | 0 | const OUString& GetSrcString() const { return aSrcString; } |
388 | 0 | const ScAddress& GetSrcPos() const { return aSrcPos; } |
389 | | |
390 | | SC_DLLPUBLIC ScAddress GetValidSrcPos() const; // adjusted to allow textual representation of expressions |
391 | | |
392 | | SC_DLLPUBLIC void SetSrcString( const OUString& rNew ); // for XML import |
393 | | |
394 | | void SetFormula1( const ScTokenArray& rArray ); |
395 | | void SetFormula2( const ScTokenArray& rArray ); |
396 | | |
397 | | SC_DLLPUBLIC OUString GetExpression( const ScAddress& rCursor, sal_uInt16 nPos, sal_uInt32 nNumFmt = 0, |
398 | | const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const; |
399 | | |
400 | | /** Create a flat copy using ScTokenArray copy-ctor with |
401 | | shared tokens. */ |
402 | | SC_DLLPUBLIC std::unique_ptr<ScTokenArray> CreateFlatCopiedTokenArray( sal_uInt16 nPos ) const; |
403 | | |
404 | | void CompileAll(); |
405 | | void CompileXML(); |
406 | | virtual void UpdateReference( sc::RefUpdateContext& rCxt ) override; |
407 | | virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ) override; |
408 | | virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ) override; |
409 | | virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ) override; |
410 | | |
411 | | virtual bool dropCaches() override; |
412 | | virtual void dumpState(rtl::OStringBuffer& rState) override; |
413 | | virtual OUString getCacheName() const override; |
414 | | |
415 | | bool MarkUsedExternalReferences() const; |
416 | | |
417 | 2.13k | virtual Type GetType() const override { return eConditionType; } |
418 | | |
419 | | virtual ScFormatEntry* Clone(ScDocument& rDoc) const override; |
420 | | |
421 | | static ScConditionMode GetModeFromApi(css::sheet::ConditionOperator nOperator); |
422 | | |
423 | | virtual void endRendering() override; |
424 | | virtual void startRendering() override; |
425 | | |
426 | | bool NeedsRepaint() const; |
427 | | void CalcAll(); |
428 | | |
429 | | protected: |
430 | | virtual void DataChanged() const; |
431 | 996 | ScDocument& GetDocument() const { return mrDoc; } |
432 | | ScConditionalFormat* pCondFormat; |
433 | | |
434 | | private: |
435 | | |
436 | | bool IsDuplicate(double nArg, const OUString& rStr) const; |
437 | | bool IsTopNElement( double nArg ) const; |
438 | | bool IsTopNPercent( double nArg ) const; |
439 | | bool IsBottomNElement( double nArg ) const; |
440 | | bool IsBottomNPercent( double nArg ) const; |
441 | | bool IsAboveAverage( double nArg, bool bEqual ) const; |
442 | | bool IsBelowAverage( double nArg, bool bEqual ) const; |
443 | | |
444 | | bool IsError( const ScAddress& rPos ) const; |
445 | | |
446 | | void FillCache() const; |
447 | | |
448 | | struct ScConditionEntryCache |
449 | | { |
450 | | typedef std::map<OUString, sal_Int32> StringCacheType; |
451 | | StringCacheType maStrings; |
452 | | typedef std::map<double, sal_Int32, approx_less> ValueCacheType; |
453 | | ValueCacheType maValues; |
454 | | |
455 | | // cache them for easier access |
456 | | size_t nValueItems; |
457 | | |
458 | | ScConditionEntryCache(): |
459 | 23 | nValueItems(0) {} |
460 | | }; |
461 | | |
462 | | mutable std::unique_ptr<ScConditionEntryCache> mpCache; |
463 | | |
464 | | std::unique_ptr<RepaintInIdle> mpRepaintTask; |
465 | | }; |
466 | | |
467 | | // single condition entry for conditional formatting |
468 | | class SAL_DLLPUBLIC_RTTI ScCondFormatEntry final : public ScConditionEntry |
469 | | { |
470 | | OUString aStyleName; |
471 | | Type eCondFormatType = Type::Condition; |
472 | | |
473 | | public: |
474 | | SC_DLLPUBLIC ScCondFormatEntry( ScConditionMode eOper, |
475 | | const OUString& rExpr1, const OUString& rExpr2, |
476 | | ScDocument& rDocument, const ScAddress& rPos, |
477 | | OUString aStyle, |
478 | | const OUString& rExprNmsp1 = OUString(), |
479 | | const OUString& rExprNmsp2 = OUString(), |
480 | | formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT, |
481 | | formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT, |
482 | | Type eType = Type::Condition); |
483 | | SC_DLLPUBLIC ScCondFormatEntry( ScConditionMode eOper, |
484 | | const ScTokenArray* pArr1, const ScTokenArray* pArr2, |
485 | | ScDocument& rDocument, const ScAddress& rPos, |
486 | | OUString aStyle ); |
487 | | SC_DLLPUBLIC ScCondFormatEntry( const ScCondFormatEntry& r ); |
488 | | ScCondFormatEntry( ScDocument& rDocument, const ScCondFormatEntry& r ); |
489 | | SC_DLLPUBLIC virtual ~ScCondFormatEntry() override; |
490 | | |
491 | | bool IsEqual( const ScFormatEntry& r, bool bIgnoreSrcPos ) const override; |
492 | | |
493 | 7.70k | const OUString& GetStyle() const { return aStyleName; } |
494 | 0 | void UpdateStyleName(const OUString& rNew) { aStyleName=rNew; } |
495 | | virtual ScFormatEntry* Clone(ScDocument& rDoc) const override; |
496 | 48.9k | virtual Type GetType() const override { return eCondFormatType; } |
497 | | |
498 | | private: |
499 | | virtual void DataChanged() const override; |
500 | | }; |
501 | | |
502 | | namespace condformat { |
503 | | |
504 | | enum ScCondFormatDateType |
505 | | { |
506 | | TODAY, |
507 | | YESTERDAY, |
508 | | TOMORROW, |
509 | | LAST7DAYS, |
510 | | THISWEEK, |
511 | | LASTWEEK, |
512 | | NEXTWEEK, |
513 | | THISMONTH, |
514 | | LASTMONTH, |
515 | | NEXTMONTH, |
516 | | THISYEAR, |
517 | | LASTYEAR, |
518 | | NEXTYEAR |
519 | | }; |
520 | | |
521 | | } |
522 | | |
523 | | class SC_DLLPUBLIC ScCondDateFormatEntry final : public ScFormatEntry |
524 | | { |
525 | | public: |
526 | | ScCondDateFormatEntry(ScDocument& rDoc); |
527 | | ScCondDateFormatEntry(ScDocument& rDoc, const ScCondDateFormatEntry& rEntry); |
528 | | |
529 | | bool IsValid( const ScAddress& rPos ) const; |
530 | | |
531 | | void SetDateType(condformat::ScCondFormatDateType eType); |
532 | 0 | condformat::ScCondFormatDateType GetDateType() const { return meType;} |
533 | | |
534 | 0 | const OUString& GetStyleName() const { return maStyleName;} |
535 | | void SetStyleName( const OUString& rStyleName ); |
536 | | |
537 | 200 | virtual Type GetType() const override { return Type::Date; } |
538 | 0 | virtual void UpdateReference( sc::RefUpdateContext& ) override {} |
539 | 0 | virtual void UpdateInsertTab( sc::RefUpdateInsertTabContext& ) override {} |
540 | 0 | virtual void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& ) override {} |
541 | 0 | virtual void UpdateMoveTab( sc::RefUpdateMoveTabContext& ) override {} |
542 | | |
543 | | virtual ScFormatEntry* Clone( ScDocument& rDoc ) const override; |
544 | | |
545 | 14 | virtual void SetParent( ScConditionalFormat* ) override {} |
546 | | |
547 | | virtual void startRendering() override; |
548 | | virtual void endRendering() override; |
549 | | |
550 | | private: |
551 | | condformat::ScCondFormatDateType meType; |
552 | | |
553 | | mutable std::unique_ptr<Date> mpCache; |
554 | | |
555 | | OUString maStyleName; |
556 | | }; |
557 | | |
558 | | class ScColorFormatCache final : public SvtListener |
559 | | { |
560 | | public: |
561 | | explicit ScColorFormatCache(ScDocument& rDoc, const ScRangeList& rRanges); |
562 | | virtual ~ScColorFormatCache() override; |
563 | | |
564 | | void Notify( const SfxHint& rHint ) override; |
565 | | |
566 | | ScDocument& mrDoc; |
567 | | ScRangeList maRanges; |
568 | | std::vector<double> maValues; |
569 | | }; |
570 | | |
571 | | // complete conditional formatting |
572 | | class ScConditionalFormat |
573 | | { |
574 | | ScDocument& mrDoc; |
575 | | sal_uInt32 mnKey; // Index in attributes |
576 | | |
577 | | std::vector<std::unique_ptr<ScFormatEntry>> maEntries; |
578 | | ScRangeList maRanges; // Ranges for conditional format |
579 | | |
580 | | mutable std::unique_ptr<ScColorFormatCache> mpCache; |
581 | | |
582 | | public: |
583 | | SC_DLLPUBLIC ScConditionalFormat(sal_uInt32 nNewKey, ScDocument& rDocument); |
584 | | SC_DLLPUBLIC ~ScConditionalFormat(); |
585 | | ScConditionalFormat(const ScConditionalFormat&) = delete; |
586 | | const ScConditionalFormat& operator=(const ScConditionalFormat&) = delete; |
587 | | |
588 | | // true copy of formulas (for Ref-Undo / between documents) |
589 | | SC_DLLPUBLIC std::unique_ptr<ScConditionalFormat> Clone(ScDocument* pNewDoc = nullptr) const; |
590 | | |
591 | | SC_DLLPUBLIC void AddEntry( ScFormatEntry* pNew ); |
592 | | void RemoveEntry(size_t nIndex); |
593 | | SC_DLLPUBLIC void SetRange( const ScRangeList& rRanges ); |
594 | 8.85k | const ScRangeList& GetRange() const { return maRanges; } |
595 | | // don't use the same name as for the const version |
596 | 0 | ScRangeList& GetRangeList() { return maRanges; } |
597 | | |
598 | | bool IsEmpty() const; |
599 | | SC_DLLPUBLIC size_t size() const; |
600 | | |
601 | | ScDocument& GetDocument(); |
602 | | |
603 | | void CompileAll(); |
604 | | void CompileXML(); |
605 | | void UpdateReference( sc::RefUpdateContext& rCxt, bool bCopyAsMove = false ); |
606 | | void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ); |
607 | | void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ); |
608 | | void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ); |
609 | | |
610 | | void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize); |
611 | | void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize); |
612 | | |
613 | | void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); |
614 | | void RenameCellStyle( std::u16string_view rOld, const OUString& rNew ); |
615 | | |
616 | | SC_DLLPUBLIC const ScFormatEntry* GetEntry( sal_uInt16 nPos ) const; |
617 | | |
618 | | SC_DLLPUBLIC OUString GetCellStyle( const ScRefCellValue& rCell, const ScAddress& rPos ) const; |
619 | | |
620 | | SC_DLLPUBLIC ScCondFormatData GetData( const ScRefCellValue& rCell, const ScAddress& rPos ) const; |
621 | | |
622 | | bool EqualEntries( const ScConditionalFormat& r, bool bIgnoreSrcPos = false ) const; |
623 | | |
624 | | void DoRepaint(); |
625 | | |
626 | 131k | sal_uInt32 GetKey() const { return mnKey; } |
627 | 4.39k | void SetKey(sal_uInt32 nNew) { mnKey = nNew; } // only if not inserted! |
628 | | |
629 | | bool MarkUsedExternalReferences() const; |
630 | | |
631 | | // sorted (via std::set) by Index |
632 | 45.2k | bool operator < ( const ScConditionalFormat& r ) const { return mnKey < r.mnKey; } |
633 | | |
634 | | void startRendering(); |
635 | | void endRendering(); |
636 | | |
637 | | void updateValues(); |
638 | | |
639 | | // Forced recalculation for formulas |
640 | | void CalcAll(); |
641 | | |
642 | | void ResetCache() const; |
643 | | void SetCache(const std::vector<double>& aValues) const; |
644 | | std::vector<double>* GetCache() const; |
645 | | }; |
646 | | |
647 | | class RepaintInIdle final : public Idle |
648 | | { |
649 | | ScConditionalFormat* mpCondFormat; |
650 | | |
651 | | public: |
652 | | RepaintInIdle(ScConditionalFormat* pCondFormat) |
653 | 8.36k | : Idle("Conditional Format Repaint Idle") |
654 | 8.36k | , mpCondFormat(pCondFormat) |
655 | 8.36k | {} |
656 | | |
657 | | void Invoke() override |
658 | 0 | { |
659 | 0 | if (mpCondFormat) |
660 | 0 | mpCondFormat->DoRepaint(); |
661 | 0 | } |
662 | | }; |
663 | | |
664 | | struct CompareScConditionalFormat |
665 | | { |
666 | | using is_transparent = void; |
667 | | bool operator()(std::unique_ptr<ScConditionalFormat> const& lhs, |
668 | | std::unique_ptr<ScConditionalFormat> const& rhs) const |
669 | 45.2k | { |
670 | 45.2k | return (*lhs) < (*rhs); |
671 | 45.2k | } |
672 | | bool operator()(sal_uInt32 nKey, std::unique_ptr<ScConditionalFormat> const& rpFormat) const |
673 | 37.1k | { |
674 | 37.1k | return nKey < rpFormat->GetKey(); |
675 | 37.1k | } |
676 | | bool operator()(std::unique_ptr<ScConditionalFormat> const& rpFormat, sal_uInt32 nKey) const |
677 | 89.9k | { |
678 | 89.9k | return rpFormat->GetKey() < nKey; |
679 | 89.9k | } |
680 | | }; |
681 | | |
682 | | // List of all conditional formats in a sheet |
683 | | class ScConditionalFormatList |
684 | | { |
685 | | private: |
686 | | typedef std::set<std::unique_ptr<ScConditionalFormat>, |
687 | | CompareScConditionalFormat> ConditionalFormatContainer; |
688 | | ConditionalFormatContainer m_ConditionalFormats; |
689 | | |
690 | | ScConditionalFormatList(ScDocument& rDoc, const ScConditionalFormatList& rList); |
691 | | void operator =(ScConditionalFormatList const &) = delete; |
692 | | |
693 | | public: |
694 | 250k | ScConditionalFormatList() {} |
695 | | SC_DLLPUBLIC ScConditionalFormatList(const ScConditionalFormatList& rList); |
696 | | |
697 | | ScConditionalFormatList* Clone(ScDocument& rDestDoc) const |
698 | 0 | { |
699 | 0 | return new ScConditionalFormatList(rDestDoc, *this); |
700 | 0 | } |
701 | | |
702 | | void InsertNew( std::unique_ptr<ScConditionalFormat> pNew ); |
703 | | |
704 | | /** |
705 | | * Checks that all cond formats have a non empty range. |
706 | | * Deletes empty cond formats. Optionally call rLink |
707 | | * on the empty format before deleting it. |
708 | | * @return true if all cond formats were valid |
709 | | */ |
710 | | bool CheckAllEntries(const Link<ScConditionalFormat*,void>& rLink = Link<ScConditionalFormat*,void>()); |
711 | | |
712 | | SC_DLLPUBLIC ScConditionalFormat* GetFormat( sal_uInt32 nKey ); |
713 | | const ScConditionalFormat* GetFormat( sal_uInt32 nKey ) const; |
714 | | |
715 | | void CompileAll(); |
716 | | void CompileXML(); |
717 | | void UpdateReference( sc::RefUpdateContext& rCxt ); |
718 | | void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt ); |
719 | | void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt ); |
720 | | void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt ); |
721 | | |
722 | | void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowStart, SCSIZE nSize); |
723 | | void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColStart, SCSIZE nSize); |
724 | | |
725 | | void RenameCellStyle( std::u16string_view rOld, const OUString& rNew ); |
726 | | void DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); |
727 | | |
728 | | typedef ConditionalFormatContainer::iterator iterator; |
729 | | typedef ConditionalFormatContainer::const_iterator const_iterator; |
730 | | |
731 | | ScRangeList GetCombinedRange() const; |
732 | | |
733 | | void RemoveFromDocument(ScDocument& rDoc) const; |
734 | | void AddToDocument(ScDocument& rDoc) const; |
735 | | |
736 | | SC_DLLPUBLIC iterator begin(); |
737 | | SC_DLLPUBLIC const_iterator begin() const; |
738 | | SC_DLLPUBLIC iterator end(); |
739 | | SC_DLLPUBLIC const_iterator end() const; |
740 | | |
741 | | SC_DLLPUBLIC size_t size() const; |
742 | | SC_DLLPUBLIC bool empty() const; |
743 | | |
744 | | SC_DLLPUBLIC void erase(sal_uLong nIndex); |
745 | | void clear(); |
746 | | |
747 | | void startRendering(); |
748 | | void endRendering(); |
749 | | |
750 | | void updateValues(); |
751 | | |
752 | | sal_uInt32 getMaxKey() const; |
753 | | |
754 | | /// Forced recalculation of formulas |
755 | | void CalcAll(); |
756 | | }; |
757 | | |
758 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |