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
10 #include <memory>
11 #include "ucalc.hxx"
12 #include "helper/qahelper.hxx"
13
14 #include <conditio.hxx>
15 #include <colorscale.hxx>
16
17 #include <clipparam.hxx>
18 #include <globstr.hrc>
19 #include <scresid.hxx>
20 #include <docfunc.hxx>
21 #include <scitems.hxx>
22 #include <attrib.hxx>
23 #include <fillinfo.hxx>
24 #include <compiler.hxx>
25 #include <tokenarray.hxx>
26
27 #include <svl/sharedstringpool.hxx>
28
testCopyPasteSkipEmptyConditionalFormatting()29 void Test::testCopyPasteSkipEmptyConditionalFormatting()
30 {
31 m_pDoc->InsertTab(0, "Test");
32
33 ScRange aDestRange(0,0,0,1,2,0);
34 ScRange aSrcRange(3,3,0,5,4,0);
35
36 ScMarkData aMark(MAXROW, MAXCOL);
37 aMark.SetMarkArea(aDestRange);
38
39 m_pDoc->SetValue(0,0,0,1);
40 m_pDoc->SetValue(1,0,0,1);
41 m_pDoc->SetValue(0,1,0,1);
42 m_pDoc->SetValue(0,2,0,1);
43 m_pDoc->SetValue(1,2,0,1);
44
45 //create conditional formatting for A1:B3
46 ScConditionalFormatList* pCondFormatList = new ScConditionalFormatList();
47 m_pDoc->SetCondFormList(pCondFormatList, 0);
48
49 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
50 pFormat->SetRange(aDestRange);
51 sal_uLong nCondFormatKey = m_pDoc->AddCondFormat(std::move(pFormat), 0);
52
53 // Prepare a clipboard content interleaved with empty cells.
54 ScDocument aClipDoc(SCDOCMODE_CLIP);
55 aClipDoc.ResetClip(m_pDoc, &aMark);
56 ScClipParam aParam(aSrcRange, false);
57 aClipDoc.SetClipParam(aParam);
58 aClipDoc.SetValue(3,3,0,2);
59 aClipDoc.SetValue(4,3,0,2);
60 aClipDoc.SetValue(4,4,0,2);
61 aClipDoc.SetValue(3,5,0,2);
62 aClipDoc.SetValue(4,5,0,2);
63
64 auto pClipFormat = std::make_unique<ScConditionalFormat>(2, &aClipDoc);
65 pClipFormat->SetRange(aSrcRange);
66 aClipDoc.AddCondFormat(std::move(pClipFormat), 0);
67
68 // Create undo document.
69 ScDocument* pUndoDoc = new ScDocument(SCDOCMODE_UNDO);
70 pUndoDoc->InitUndo(m_pDoc, 0, 0);
71 m_pDoc->CopyToDocument(aDestRange, InsertDeleteFlags::CONTENTS, false, *pUndoDoc, &aMark);
72
73 // Paste clipboard content onto A1:A5 but skip empty cells.
74 m_pDoc->CopyFromClip(aDestRange, aMark, InsertDeleteFlags::CONTENTS, pUndoDoc, &aClipDoc, true, false, false, true/*bSkipEmpty*/);
75
76 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
77 CPPUNIT_ASSERT_EQUAL(size_t(2), pList->size());
78 CPPUNIT_ASSERT(m_pDoc->GetCondFormat(1,1,0));
79 // empty cell in copy area does not overwrite conditional formatting
80 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nCondFormatKey), m_pDoc->GetCondFormat(1,1,0)->GetKey());
81 for(SCCOL nCol = 0; nCol <= 1; ++nCol)
82 {
83 for(SCROW nRow = 0; nRow <= 2; ++nRow)
84 {
85 if(nRow == 1 && nCol == 1)
86 continue;
87
88 CPPUNIT_ASSERT(m_pDoc->GetCondFormat(nCol, nRow, 0));
89 CPPUNIT_ASSERT(nCondFormatKey != m_pDoc->GetCondFormat(nCol, nRow, 0)->GetKey());
90 }
91 }
92 m_pDoc->DeleteTab(0);
93 }
94
testCondFormatINSDEL()95 void Test::testCondFormatINSDEL()
96 {
97 // fdo#62206
98 m_pDoc->InsertTab(0, "Test");
99 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
100
101 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
102 ScRangeList aRangeList(ScRange(0,0,0,0,3,0));
103 pFormat->SetRange(aRangeList);
104 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
105 pFormat->AddEntry(pEntry);
106
107 m_pDoc->AddCondFormatData(pFormat->GetRange(), 0, 1);
108 auto pFormatTmp = pFormat.get();
109 pList->InsertNew(std::move(pFormat));
110
111 m_pDoc->InsertCol(0,0,MAXROW,0,0,2);
112 const ScRangeList& rRange = pFormatTmp->GetRange();
113 CPPUNIT_ASSERT_EQUAL(static_cast<const ScRangeList&>(ScRange(2,0,0,2,3,0)), rRange);
114
115 OUString aExpr = pEntry->GetExpression(ScAddress(2,0,0), 0);
116 CPPUNIT_ASSERT_EQUAL(OUString("D2"), aExpr);
117
118 m_pDoc->DeleteTab(0);
119 }
120
testCondFormatInsertCol()121 void Test::testCondFormatInsertCol()
122 {
123 m_pDoc->InsertTab(0, "Test");
124 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
125
126 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
127 ScRangeList aRangeList(ScRange(0,0,0,3,3,0));
128 pFormat->SetRange(aRangeList);
129
130 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
131 pFormat->AddEntry(pEntry);
132
133 m_pDoc->AddCondFormatData(pFormat->GetRange(), 0, 1);
134 auto pFormatTmp = pFormat.get();
135 pList->InsertNew(std::move(pFormat));
136
137 m_pDoc->InsertCol(0,0,MAXROW,0,4,2);
138 const ScRangeList& rRange = pFormatTmp->GetRange();
139 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,0,5,3,0)), rRange);
140
141 m_pDoc->DeleteTab(0);
142 }
143
testCondFormatInsertRow()144 void Test::testCondFormatInsertRow()
145 {
146 m_pDoc->InsertTab(0, "Test");
147 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
148
149 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
150 ScRangeList aRangeList(ScRange(0,0,0,3,3,0));
151 pFormat->SetRange(aRangeList);
152
153 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
154 pFormat->AddEntry(pEntry);
155
156 m_pDoc->AddCondFormatData(pFormat->GetRange(), 0, 1);
157 auto pFormatTmp = pFormat.get();
158 pList->InsertNew(std::move(pFormat));
159
160 m_pDoc->InsertRow(0,0,MAXCOL,0,4,2);
161 const ScRangeList& rRange = pFormatTmp->GetRange();
162 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,0,3,5,0)), rRange);
163
164 m_pDoc->DeleteTab(0);
165 }
166
testCondFormatInsertDeleteSheets()167 void Test::testCondFormatInsertDeleteSheets()
168 {
169 m_pDoc->InsertTab(0, "Test");
170
171 // Add a conditional format to B2:B4.
172 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
173 pFormat->SetRange(ScRange(1,1,0,1,3,0));
174
175 auto pFormatTmp = pFormat.get();
176 sal_uLong nKey = m_pDoc->AddCondFormat(std::move(pFormat), 0);
177
178 // Add condition in which if the value equals 2, set the "Result" style.
179 ScCondFormatEntry* pEntry = new ScCondFormatEntry(
180 ScConditionMode::Equal, "=2", "" , m_pDoc, ScAddress(0,0,0), ScResId(STR_STYLENAME_RESULT));
181 pFormatTmp->AddEntry(pEntry);
182
183 // Apply the format to the range.
184 m_pDoc->AddCondFormatData(pFormatTmp->GetRange(), 0, nKey);
185
186 // Make sure this conditional format entry is really there.
187 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
188 CPPUNIT_ASSERT(pList);
189 const ScConditionalFormat* pCheck = pList->GetFormat(nKey);
190 CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong conditional format instance.", pCheck, const_cast<const ScConditionalFormat*>(pFormatTmp));
191
192 // ... and its range is B2:B4.
193 ScRangeList aCheckRange = pCheck->GetRange();
194 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange.size());
195 const ScRange* pRange = &aCheckRange[0];
196 CPPUNIT_ASSERT(pRange);
197 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4.", ScRange(1,1,0,1,3,0), *pRange);
198
199 ScDocFunc& rFunc = getDocShell().GetDocFunc();
200
201 // Insert a new sheet at the left.
202 bool bInserted = rFunc.InsertTable(0, "Inserted", true, true);
203 CPPUNIT_ASSERT(bInserted);
204
205 pList = m_pDoc->GetCondFormList(1);
206 CPPUNIT_ASSERT(pList);
207 pCheck = pList->GetFormat(nKey);
208 CPPUNIT_ASSERT(pCheck);
209
210 // Make sure the range also got shifted.
211 aCheckRange = pCheck->GetRange();
212 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange.size());
213 pRange = &aCheckRange[0];
214 CPPUNIT_ASSERT(pRange);
215 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4 on the 2nd sheet after the sheet insertion.", ScRange(1,1,1,1,3,1), *pRange);
216
217 // Delete the sheet to the left.
218 bool bDeleted = rFunc.DeleteTable(0, true);
219 CPPUNIT_ASSERT(bDeleted);
220
221 pList = m_pDoc->GetCondFormList(0);
222 CPPUNIT_ASSERT(pList);
223 pCheck = pList->GetFormat(nKey);
224 CPPUNIT_ASSERT(pCheck);
225
226 // Make sure the range got shifted back.
227 aCheckRange = pCheck->GetRange();
228 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange.size());
229 pRange = &aCheckRange[0];
230 CPPUNIT_ASSERT(pRange);
231 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4 on the 1st sheet after the sheet removal.", ScRange(1,1,0,1,3,0), *pRange);
232
233 SfxUndoManager* pUndoMgr = m_pDoc->GetUndoManager();
234 CPPUNIT_ASSERT(pUndoMgr);
235
236 // Undo and re-check.
237 pUndoMgr->Undo();
238
239 pList = m_pDoc->GetCondFormList(1);
240 CPPUNIT_ASSERT(pList);
241 pCheck = pList->GetFormat(nKey);
242 CPPUNIT_ASSERT(pCheck);
243
244 aCheckRange = pCheck->GetRange();
245 CPPUNIT_ASSERT_EQUAL_MESSAGE("This should be a single range.", size_t(1), aCheckRange.size());
246 pRange = &aCheckRange[0];
247 CPPUNIT_ASSERT(pRange);
248 CPPUNIT_ASSERT_EQUAL_MESSAGE("Format should be applied to B2:B4 on the 2nd sheet after the undo of the sheet removal.", ScRange(1,1,1,1,3,1), *pRange);
249
250 #if 0 // TODO : Undo of sheet insertion currently depends on the presence of
251 // view shell, and crashes when executed during cppunit run.
252
253 // Undo again and re-check.
254 pUndoMgr->Undo();
255
256 pList = m_pDoc->GetCondFormList(0);
257 CPPUNIT_ASSERT(pList);
258 pCheck = pList->GetFormat(nKey);
259 CPPUNIT_ASSERT(pCheck);
260
261 // Make sure the range got shifted back.
262 aCheckRange = pCheck->GetRange();
263 CPPUNIT_ASSERT_MESSAGE("This should be a single range.", aCheckRange.size() == 1);
264 pRange = aCheckRange[0];
265 CPPUNIT_ASSERT(pRange);
266 CPPUNIT_ASSERT_MESSAGE("Format should be applied to B2:B4 on the 1st sheet after the undo of sheet insertion.", *pRange == ScRange(1,1,0,1,3,0));
267 #else
268 m_pDoc->DeleteTab(1);
269 #endif
270
271 m_pDoc->DeleteTab(0);
272 }
273
testCondCopyPaste()274 void Test::testCondCopyPaste()
275 {
276 m_pDoc->InsertTab(0, "Test");
277
278 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
279 ScRange aCondFormatRange(0,0,0,3,3,0);
280 ScRangeList aRangeList(aCondFormatRange);
281 pFormat->SetRange(aRangeList);
282
283 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
284 pFormat->AddEntry(pEntry);
285 sal_uLong nIndex = m_pDoc->AddCondFormat(std::move(pFormat), 0);
286
287 ScDocument aClipDoc(SCDOCMODE_CLIP);
288 copyToClip(m_pDoc, aCondFormatRange, &aClipDoc);
289
290 ScRange aTargetRange(4,4,0,7,7,0);
291 pasteFromClip(m_pDoc, aTargetRange, &aClipDoc);
292
293 ScConditionalFormat* pPastedFormat = m_pDoc->GetCondFormat(7,7,0);
294 CPPUNIT_ASSERT(pPastedFormat);
295
296 // Pasting the same conditional format must modify existing format, making its range
297 // combined of previous range and newly pasted range having the conditional format.
298 // No new conditional formats must be created.
299 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetCondFormList(0)->size());
300 aRangeList.Join(aTargetRange);
301 CPPUNIT_ASSERT_EQUAL(aRangeList, pPastedFormat->GetRange());
302 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pPastedFormat->GetKey());
303 const SfxPoolItem* pItem = m_pDoc->GetAttr( 7, 7, 0, ATTR_CONDITIONAL );
304 const ScCondFormatItem* pCondFormatItem = static_cast<const ScCondFormatItem*>(pItem);
305
306 CPPUNIT_ASSERT(pCondFormatItem);
307 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
308 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front());
309
310 m_pDoc->DeleteTab(0);
311 }
312
testCondCopyPasteSingleCell()313 void Test::testCondCopyPasteSingleCell()
314 {
315 m_pDoc->InsertTab(0, "Test");
316
317 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
318 ScRange aCondFormatRange(0,0,0,3,3,0);
319 ScRangeList aRangeList(aCondFormatRange);
320 pFormat->SetRange(aRangeList);
321
322 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
323 pFormat->AddEntry(pEntry);
324 sal_uLong nIndex = m_pDoc->AddCondFormat(std::move(pFormat), 0);
325
326 ScDocument aClipDoc(SCDOCMODE_CLIP);
327 copyToClip(m_pDoc, ScRange(0,0,0,0,0,0), &aClipDoc);
328
329 ScRange aTargetRange(4,4,0,4,4,0);
330 pasteOneCellFromClip(m_pDoc, aTargetRange, &aClipDoc);
331
332 ScConditionalFormat* pPastedFormat = m_pDoc->GetCondFormat(4,4,0);
333 CPPUNIT_ASSERT(pPastedFormat);
334
335 // Pasting the same conditional format must modify existing format, making its range
336 // combined of previous range and newly pasted range having the conditional format.
337 // No new conditional formats must be created.
338 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetCondFormList(0)->size());
339 aRangeList.Join(aTargetRange);
340 CPPUNIT_ASSERT_EQUAL(aRangeList, pPastedFormat->GetRange());
341 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pPastedFormat->GetKey());
342 const SfxPoolItem* pItem = m_pDoc->GetAttr( 4, 4, 0, ATTR_CONDITIONAL );
343 const ScCondFormatItem* pCondFormatItem = static_cast<const ScCondFormatItem*>(pItem);
344
345 CPPUNIT_ASSERT(pCondFormatItem);
346 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
347 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front() );
348
349 m_pDoc->DeleteTab(0);
350 }
351
testCondCopyPasteSingleCellToRange()352 void Test::testCondCopyPasteSingleCellToRange()
353 {
354 m_pDoc->InsertTab(0, "Test");
355
356 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
357 ScRange aCondFormatRange(0,0,0,3,3,0);
358 ScRangeList aRangeList(aCondFormatRange);
359 pFormat->SetRange(aRangeList);
360
361 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
362 pFormat->AddEntry(pEntry);
363 sal_uLong nIndex = m_pDoc->AddCondFormat(std::move(pFormat), 0);
364
365 ScDocument aClipDoc(SCDOCMODE_CLIP);
366 copyToClip(m_pDoc, ScRange(0,0,0,0,0,0), &aClipDoc);
367 ScRange aTargetRange(4,4,0,5,8,0);
368 pasteOneCellFromClip(m_pDoc, aTargetRange, &aClipDoc);
369
370 // Pasting the same conditional format must modify existing format, making its range
371 // combined of previous range and newly pasted range having the conditional format.
372 // No new conditional formats must be created.
373 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetCondFormList(0)->size());
374 aRangeList.Join(aTargetRange);
375 for(SCROW nRow = 4; nRow <= 8; ++nRow)
376 {
377 for (SCCOL nCol = 4; nCol <= 5; ++nCol)
378 {
379 ScConditionalFormat* pPastedFormat = m_pDoc->GetCondFormat(nCol, nRow, 0);
380 CPPUNIT_ASSERT(pPastedFormat);
381
382 CPPUNIT_ASSERT_EQUAL(aRangeList, pPastedFormat->GetRange());
383 sal_uLong nPastedKey = pPastedFormat->GetKey();
384 CPPUNIT_ASSERT_EQUAL(nIndex, nPastedKey);
385 const SfxPoolItem* pItem = m_pDoc->GetAttr( nCol, nRow, 0, ATTR_CONDITIONAL );
386 const ScCondFormatItem* pCondFormatItem = static_cast<const ScCondFormatItem*>(pItem);
387
388 CPPUNIT_ASSERT(pCondFormatItem);
389 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
390 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front() );
391 }
392 }
393
394 m_pDoc->DeleteTab(0);
395 }
396
testCondCopyPasteSingleCellIntoSameFormatRange()397 void Test::testCondCopyPasteSingleCellIntoSameFormatRange()
398 {
399 m_pDoc->InsertTab(0, "Test");
400
401 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
402 ScRange aCondFormatRange(0, 0, 0, 3, 3, 0);
403 ScRangeList aRangeList(aCondFormatRange);
404 pFormat->SetRange(aRangeList);
405
406 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct, "=B2", "", m_pDoc, ScAddress(0, 0, 0), ScResId(STR_STYLENAME_RESULT));
407 pFormat->AddEntry(pEntry);
408 sal_uLong nIndex = m_pDoc->AddCondFormat(std::move(pFormat), 0);
409
410 ScDocument aClipDoc(SCDOCMODE_CLIP);
411 copyToClip(m_pDoc, ScRange(1, 1, 0, 1, 1, 0), &aClipDoc);
412
413 ScRange aTargetRange(2, 2, 0, 2, 2, 0);
414 pasteFromClip(m_pDoc, aTargetRange, &aClipDoc);
415
416 ScConditionalFormat* pPastedFormat = m_pDoc->GetCondFormat(2, 2, 0);
417 CPPUNIT_ASSERT(pPastedFormat);
418
419 // Pasting the same conditional format into the same range must not modify existing format,
420 // since it already covers the pasted range. No new conditional formats must be created.
421 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetCondFormList(0)->size());
422 CPPUNIT_ASSERT_EQUAL(aRangeList, pPastedFormat->GetRange());
423 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pPastedFormat->GetKey());
424 const SfxPoolItem* pItem = m_pDoc->GetAttr(2, 2, 0, ATTR_CONDITIONAL);
425 const ScCondFormatItem* pCondFormatItem = static_cast<const ScCondFormatItem*>(pItem);
426
427 CPPUNIT_ASSERT(pCondFormatItem);
428 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
429 CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front());
430
431 m_pDoc->DeleteTab(0);
432 }
433
testCondCopyPasteSingleRowToRange()434 void Test::testCondCopyPasteSingleRowToRange()
435 {
436 m_pDoc->InsertTab(0, "Test");
437
438 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
439 ScRange aCondFormatRange(0,0,0,0,0,0);
440 ScRangeList aRangeList(aCondFormatRange);
441 pFormat->SetRange(aRangeList);
442
443 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
444 pFormat->AddEntry(pEntry);
445 auto pFormatTmp = pFormat.get();
446 m_pDoc->AddCondFormat(std::move(pFormat), 0);
447
448 ScDocument aClipDoc(SCDOCMODE_CLIP);
449 copyToClip(m_pDoc, ScRange(0,0,0,MAXCOL,0,0), &aClipDoc);
450 ScRange aTargetRange(0,4,0,MAXCOL,4,0);
451 pasteOneCellFromClip(m_pDoc, aTargetRange, &aClipDoc);
452
453 ScConditionalFormat* pNewFormat = m_pDoc->GetCondFormat(0, 4, 0);
454 CPPUNIT_ASSERT(pNewFormat);
455 CPPUNIT_ASSERT_EQUAL(pNewFormat->GetKey(), pFormatTmp->GetKey());
456
457 for (SCCOL nCol = 1; nCol <= MAXCOL; ++nCol)
458 {
459 ScConditionalFormat* pNewFormat2 = m_pDoc->GetCondFormat(nCol, 4, 0);
460 CPPUNIT_ASSERT(!pNewFormat2);
461 }
462
463 m_pDoc->DeleteTab(0);
464 }
465
testCondCopyPasteSingleRowToRange2()466 void Test::testCondCopyPasteSingleRowToRange2()
467 {
468 m_pDoc->InsertTab(0, "Test");
469
470 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
471 ScRange aCondFormatRange(0,0,0,0,0,0);
472 ScRangeList aRangeList(aCondFormatRange);
473 pFormat->SetRange(aRangeList);
474
475 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
476 pFormat->AddEntry(pEntry);
477 m_pDoc->AddCondFormat(std::move(pFormat), 0);
478
479 ScDocument aClipDoc(SCDOCMODE_CLIP);
480 copyToClip(m_pDoc, ScRange(0,0,0,3,0,0), &aClipDoc);
481 ScRange aTargetRange(0,4,0,MAXCOL,4,0);
482 pasteOneCellFromClip(m_pDoc, aTargetRange, &aClipDoc);
483
484 for (SCCOL nCol = 0; nCol <= MAXCOL; ++nCol)
485 {
486 ScConditionalFormat* pNewFormat = m_pDoc->GetCondFormat(nCol, 4, 0);
487 if (nCol % 4 == 0)
488 CPPUNIT_ASSERT(pNewFormat);
489 else
490 CPPUNIT_ASSERT(!pNewFormat);
491 }
492
493 m_pDoc->DeleteTab(0);
494 }
495
testCondCopyPasteSheetBetweenDoc()496 void Test::testCondCopyPasteSheetBetweenDoc()
497 {
498 m_pDoc->InsertTab(0, "Test");
499
500 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
501 ScRange aCondFormatRange(0,0,0,3,3,0);
502 ScRangeList aRangeList(aCondFormatRange);
503 pFormat->SetRange(aRangeList);
504
505 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
506 pFormat->AddEntry(pEntry);
507 m_pDoc->AddCondFormat(std::move(pFormat), 0);
508
509 ScDocument aDoc;
510 aDoc.TransferTab(m_pDoc, 0, 0);
511
512 ScConditionalFormatList* pList = aDoc.GetCondFormList(0);
513 CPPUNIT_ASSERT_EQUAL(size_t(1), pList->size());
514
515 m_pDoc->DeleteTab(0);
516 }
517
testCondCopyPasteSheet()518 void Test::testCondCopyPasteSheet()
519 {
520 m_pDoc->InsertTab(0, "Test");
521
522 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
523 ScRange aCondFormatRange(0,0,0,3,3,0);
524 ScRangeList aRangeList(aCondFormatRange);
525 pFormat->SetRange(aRangeList);
526
527 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct,"=B2","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
528 pFormat->AddEntry(pEntry);
529 m_pDoc->AddCondFormat(std::move(pFormat), 0);
530
531 m_pDoc->CopyTab(0, SC_TAB_APPEND);
532
533 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(1);
534 CPPUNIT_ASSERT_EQUAL(size_t(1), pList->size());
535
536 ScConditionalFormat& rFormat = **pList->begin();
537 const ScRangeList& rRange = rFormat.GetRange();
538 CPPUNIT_ASSERT_EQUAL(ScRangeList(ScRange(0,0,1,3,3,1)), rRange);
539 sal_uInt32 nKey = rFormat.GetKey();
540 const SfxPoolItem* pItem = m_pDoc->GetAttr( 2, 2, 1, ATTR_CONDITIONAL );
541 const ScCondFormatItem* pCondFormatItem = static_cast<const ScCondFormatItem*>(pItem);
542
543 CPPUNIT_ASSERT(pCondFormatItem);
544 CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
545 CPPUNIT_ASSERT_EQUAL( nKey, pCondFormatItem->GetCondFormatData().front() );
546
547 m_pDoc->DeleteTab(1);
548 m_pDoc->DeleteTab(0);
549 }
550
testIconSet()551 void Test::testIconSet()
552 {
553 m_pDoc->InsertTab(0, "Test");
554 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
555
556 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
557 ScRangeList aRangeList(ScRange(0,0,0,0,0,0));
558 pFormat->SetRange(aRangeList);
559
560 ScIconSetFormat* pEntry = new ScIconSetFormat(m_pDoc);
561 ScIconSetFormatData* pData = new ScIconSetFormatData;
562 pData->m_Entries.push_back(std::make_unique<ScColorScaleEntry>(0, COL_BLUE));
563 pData->m_Entries.push_back(std::make_unique<ScColorScaleEntry>(1, COL_GREEN));
564 pData->m_Entries.push_back(std::make_unique<ScColorScaleEntry>(2, COL_RED));
565 pEntry->SetIconSetData(pData);
566
567 m_pDoc->AddCondFormatData(pFormat->GetRange(), 0, 1);
568 pList->InsertNew(std::move(pFormat));
569
570 static struct {
571 double nVal; sal_Int32 nIndex;
572 } const aTests[] = {
573 { -1.0, 0 },
574 { 0.0, 0 },
575 { 1.0, 1 },
576 { 2.0, 2 },
577 { 3.0, 2 }
578 };
579 for(size_t i = 0; i < SAL_N_ELEMENTS(aTests); ++i)
580 {
581 m_pDoc->SetValue(0,0,0,aTests[i].nVal);
582 std::unique_ptr<ScIconSetInfo> pInfo = pEntry->GetIconSetInfo(ScAddress(0,0,0));
583 CPPUNIT_ASSERT_EQUAL(aTests[i].nIndex, pInfo->nIconIndex);
584 }
585
586 delete pEntry;
587 m_pDoc->DeleteTab(0);
588 }
589
590 namespace {
591
592 struct ScDataBarLengthData
593 {
594 double const nVal;
595 double const nLength;
596 };
597
testDataBarLengthImpl(ScDocument * pDoc,const ScDataBarLengthData * pData,const ScRange & rRange,double nMinVal,ScColorScaleEntryType eMinType,double nMaxVal,ScColorScaleEntryType eMaxType,double nZeroPos,databar::ScAxisPosition eAxisPos)598 void testDataBarLengthImpl(ScDocument* pDoc, const ScDataBarLengthData* pData, const ScRange& rRange,
599 double nMinVal, ScColorScaleEntryType eMinType,
600 double nMaxVal, ScColorScaleEntryType eMaxType,
601 double nZeroPos, databar::ScAxisPosition eAxisPos)
602 {
603 std::unique_ptr<ScConditionalFormat> pFormat(new ScConditionalFormat(1, pDoc));
604 ScRangeList aRangeList(rRange);
605 pFormat->SetRange(aRangeList);
606
607 SCCOL nCol = rRange.aStart.Col();
608
609 ScDataBarFormat* pDatabar = new ScDataBarFormat(pDoc);
610 pFormat->AddEntry(pDatabar);
611
612 ScDataBarFormatData* pFormatData = new ScDataBarFormatData();
613 pFormatData->meAxisPosition = eAxisPos;
614
615 pFormatData->mpLowerLimit.reset(new ScColorScaleEntry());
616 pFormatData->mpLowerLimit->SetValue(nMinVal);
617 pFormatData->mpLowerLimit->SetType(eMinType);
618 pFormatData->mpUpperLimit.reset(new ScColorScaleEntry());
619 pFormatData->mpUpperLimit->SetValue(nMaxVal);
620 pFormatData->mpUpperLimit->SetType(eMaxType);
621 pDatabar->SetDataBarData(pFormatData);
622
623 for (size_t i = 0; pData[i].nLength != -200; ++i)
624 {
625 pDoc->SetValue(nCol, i, 0, pData[i].nVal);
626 }
627
628 for (size_t i = 0; pData[i].nLength != -200; ++i)
629 {
630 std::unique_ptr<ScDataBarInfo> xInfo(pDatabar->GetDataBarInfo(ScAddress(nCol, i, 0)));
631 CPPUNIT_ASSERT(xInfo);
632 ASSERT_DOUBLES_EQUAL(pData[i].nLength, xInfo->mnLength);
633 ASSERT_DOUBLES_EQUAL(nZeroPos, xInfo->mnZero);
634 }
635 }
636
637 }
638
testDataBarLengthAutomaticAxis()639 void Test::testDataBarLengthAutomaticAxis()
640 {
641 m_pDoc->InsertTab(0, "Test");
642
643 static const ScDataBarLengthData aValues[] = {
644 { 2, 0 },
645 { 3, 0 },
646 { 4, 25.0 },
647 { 5, 50.0 },
648 { 6, 75.0 },
649 { 7, 100.0 },
650 { 8, 100.0 },
651 { 9, 100.0 },
652 { 0, -200 }
653 };
654
655 testDataBarLengthImpl(m_pDoc, aValues, ScRange(0,0,0,0,7,0),
656 3, COLORSCALE_VALUE, 7, COLORSCALE_VALUE, 0.0, databar::AUTOMATIC);
657
658 static const ScDataBarLengthData aValues2[] = {
659 { -6, -100 },
660 { -5, -100 },
661 { -4, -100 },
662 { -3, -75.0 },
663 { -2, -50.0 },
664 { -1, -25.0 },
665 { 0, 0.0 },
666 { 1, 12.5 },
667 { 2, 25.0 },
668 { 3, 37.5 },
669 { 4, 50.0 },
670 { 5, 62.5 },
671 { 6, 75.0 },
672 { 7, 87.5 },
673 { 8, 100.0 },
674 { 9, 100.0 },
675 { 0, -200 }
676 };
677 testDataBarLengthImpl(m_pDoc, aValues2, ScRange(1,0,0,1,15,0),
678 -4, COLORSCALE_VALUE, 8, COLORSCALE_VALUE, 1.0/3.0 * 100, databar::AUTOMATIC);
679
680 static const ScDataBarLengthData aValues3[] = {
681 { 2, 0.0 },
682 { 3, 25.0 },
683 { 4, 50.0 },
684 { 6, 100.0 },
685 { 0, -200 }
686 };
687 testDataBarLengthImpl(m_pDoc, aValues3, ScRange(2,0,0,2,3,0),
688 0, COLORSCALE_MIN, 0, COLORSCALE_MAX, 0, databar::AUTOMATIC);
689
690 static const ScDataBarLengthData aValues4[] = {
691 { 2, 40.0 },
692 { 3, 60.0 },
693 { 4, 80.0 },
694 { 5, 100.0 },
695 { 0, -200 }
696 };
697 testDataBarLengthImpl(m_pDoc, aValues4, ScRange(3,0,0,3,3,0),
698 0, COLORSCALE_AUTO, 0, COLORSCALE_AUTO, 0, databar::AUTOMATIC);
699
700 m_pDoc->DeleteTab(0);
701 }
702
testDataBarLengthMiddleAxis()703 void Test::testDataBarLengthMiddleAxis()
704 {
705 m_pDoc->InsertTab(0, "Test");
706
707 static const ScDataBarLengthData aValues[] = {
708 { 1, 25.0 },
709 { 2, 25.0 },
710 { 3, 37.5 },
711 { 4, 50.0 },
712 { 5, 62.5 },
713 { 6, 75.0 },
714 { 7, 87.5 },
715 { 8, 100.0 },
716 { 9, 100.0 },
717 { 0, -200 }
718 };
719
720 testDataBarLengthImpl(m_pDoc, aValues, ScRange(0,0,0,0,8,0),
721 2, COLORSCALE_VALUE, 8, COLORSCALE_VALUE, 50.0, databar::MIDDLE);
722
723 static const ScDataBarLengthData aValues2[] = {
724 { -6, -50 },
725 { -5, -50 },
726 { -4, -50 },
727 { -3, -37.5 },
728 { -2, -25.0 },
729 { -1, -12.5 },
730 { 0, 0.0 },
731 { 1, 12.5 },
732 { 2, 25.0 },
733 { 3, 37.5 },
734 { 4, 50.0 },
735 { 5, 62.5 },
736 { 6, 75.0 },
737 { 7, 87.5 },
738 { 8, 100.0 },
739 { 9, 100.0 },
740 { 0, -200 }
741 };
742 testDataBarLengthImpl(m_pDoc, aValues2, ScRange(1,0,0,1,15,0),
743 -4, COLORSCALE_VALUE, 8, COLORSCALE_VALUE, 50.0, databar::MIDDLE);
744
745 m_pDoc->DeleteTab(0);
746 }
747
testCondFormatEndsWithStr()748 void Test::testCondFormatEndsWithStr()
749 {
750 m_pDoc->InsertTab(0, "Test");
751
752 ScConditionEntry aEntry(ScConditionMode::EndsWith, "\"TestString\"", "", m_pDoc, ScAddress(),
753 "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
754
755 svl::SharedStringPool& rStringPool = m_pDoc->GetSharedStringPool();
756 svl::SharedString aStr = rStringPool.intern("SimpleTestString");
757 ScRefCellValue aVal(&aStr);
758 ScAddress aPos(0, 0, 0);
759
760 bool bValid = aEntry.IsCellValid(aVal, aPos);
761 CPPUNIT_ASSERT(bValid);
762
763 m_pDoc->DeleteTab(0);
764 }
765
testCondFormatEndsWithVal()766 void Test::testCondFormatEndsWithVal()
767 {
768 m_pDoc->InsertTab(0, "Test");
769
770 ScConditionEntry aEntry(ScConditionMode::EndsWith, "2", "", m_pDoc, ScAddress(),
771 "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
772
773 for (sal_Int32 i = 0; i < 15; ++i)
774 {
775 ScRefCellValue aVal(i);
776 ScAddress aPos(0, 0, 0);
777
778 bool bValid = aEntry.IsCellValid(aVal, aPos);
779 bool bShouldBeValid = (i % 10) == 2;
780 CPPUNIT_ASSERT_EQUAL(bShouldBeValid, bValid);
781 }
782
783 m_pDoc->DeleteTab(0);
784 }
785
testFormulaListenerSingleCellToSingleCell()786 void Test::testFormulaListenerSingleCellToSingleCell()
787 {
788 m_pDoc->InsertTab(0, "test");
789
790 ScCompiler aCompiler(m_pDoc, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH);
791
792 std::unique_ptr<ScTokenArray> pTokenArray(aCompiler.CompileString("A1"));
793
794 ScFormulaListener aListener(m_pDoc);
795
796 aListener.addTokenArray(pTokenArray.get(), ScAddress(10, 10, 0));
797
798 m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0);
799 CPPUNIT_ASSERT(aListener.NeedsRepaint());
800
801 m_pDoc->DeleteTab(0);
802 }
803
testFormulaListenerSingleCellToMultipleCells()804 void Test::testFormulaListenerSingleCellToMultipleCells()
805 {
806 m_pDoc->InsertTab(0, "test");
807
808 ScCompiler aCompiler(m_pDoc, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH);
809
810 std::unique_ptr<ScTokenArray> pTokenArray(aCompiler.CompileString("A1"));
811
812 ScFormulaListener aListener(m_pDoc);
813
814 aListener.addTokenArray(pTokenArray.get(), ScAddress(10, 10, 0));
815
816 m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0);
817 CPPUNIT_ASSERT(aListener.NeedsRepaint());
818
819 m_pDoc->DeleteTab(0);
820 }
821
testFormulaListenerMultipleCellsToSingleCell()822 void Test::testFormulaListenerMultipleCellsToSingleCell()
823 {
824 m_pDoc->InsertTab(0, "test");
825
826 ScCompiler aCompiler(m_pDoc, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH);
827
828 std::unique_ptr<ScTokenArray> pTokenArray(aCompiler.CompileString("A1"));
829
830 ScFormulaListener aListener(m_pDoc);
831
832 aListener.addTokenArray(pTokenArray.get(), ScAddress(10, 10, 0));
833
834 m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0);
835 CPPUNIT_ASSERT(aListener.NeedsRepaint());
836
837 m_pDoc->DeleteTab(0);
838 }
839
testFormulaListenerMultipleCellsToMultipleCells()840 void Test::testFormulaListenerMultipleCellsToMultipleCells()
841 {
842 m_pDoc->InsertTab(0, "test");
843
844 ScCompiler aCompiler(m_pDoc, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH);
845
846 std::unique_ptr<ScTokenArray> pTokenArray(aCompiler.CompileString("A1"));
847
848 ScFormulaListener aListener(m_pDoc);
849
850 aListener.addTokenArray(pTokenArray.get(), ScAddress(10, 10, 0));
851
852 m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0);
853 CPPUNIT_ASSERT(aListener.NeedsRepaint());
854
855 m_pDoc->DeleteTab(0);
856 }
857
testFormulaListenerUpdateInsertTab()858 void Test::testFormulaListenerUpdateInsertTab()
859 {
860 m_pDoc->InsertTab(0, "test");
861
862 ScCompiler aCompiler(m_pDoc, ScAddress(10, 10, 0), formula::FormulaGrammar::GRAM_ENGLISH);
863 std::unique_ptr<ScTokenArray> pTokenArray(aCompiler.CompileString("A1"));
864
865 ScFormulaListener aListener(m_pDoc);
866 aListener.addTokenArray(pTokenArray.get(), ScAddress(10, 10, 0));
867 CPPUNIT_ASSERT(!aListener.NeedsRepaint());
868
869 m_pDoc->InsertTab(0, "new_tab");
870
871 // check that the listener has moved to the new sheet
872 m_pDoc->SetValue(ScAddress(0, 0, 1), 1.0);
873 CPPUNIT_ASSERT(aListener.NeedsRepaint());
874
875 // check that we are not listening to the old sheet
876 m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0);
877 CPPUNIT_ASSERT(!aListener.NeedsRepaint());
878
879 m_pDoc->DeleteTab(0);
880 }
881
testFormulaListenerUpdateDeleteTab()882 void Test::testFormulaListenerUpdateDeleteTab()
883 {
884 m_pDoc->InsertTab(0, "test");
885 m_pDoc->InsertTab(0, "to_delete");
886
887 ScCompiler aCompiler(m_pDoc, ScAddress(10, 10, 1), formula::FormulaGrammar::GRAM_ENGLISH);
888 std::unique_ptr<ScTokenArray> pTokenArray(aCompiler.CompileString("A1"));
889
890 ScFormulaListener aListener(m_pDoc);
891 aListener.addTokenArray(pTokenArray.get(), ScAddress(10, 10, 1));
892 CPPUNIT_ASSERT(!aListener.NeedsRepaint());
893
894 m_pDoc->DeleteTab(0);
895
896 // check that the listener has moved
897 m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0);
898 CPPUNIT_ASSERT(aListener.NeedsRepaint());
899
900 m_pDoc->DeleteTab(0);
901 }
902
testCondFormatUpdateMoveTab()903 void Test::testCondFormatUpdateMoveTab()
904 {
905 m_pDoc->InsertTab(0, "test");
906 m_pDoc->InsertTab(1, "Test2");
907
908 ScConditionEntry* pEntry = new ScConditionEntry(ScConditionMode::Equal, "A1", "", m_pDoc, ScAddress(10, 10, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
909
910 auto pFormat = std::make_unique<ScConditionalFormat>(0, m_pDoc);
911 pFormat->SetRange(ScRange(10, 10, 0, 10, 12, 0));
912 auto pFormatTmp = pFormat.get();
913 m_pDoc->AddCondFormat(std::move(pFormat), 0);
914
915 pFormatTmp->AddEntry(pEntry);
916
917 // the conditional format should listen to A1:A3
918 for (SCROW nRow = 0; nRow < 3; ++nRow)
919 {
920 m_pDoc->SetValue(ScAddress(0, nRow, 0), 1.0);
921 CPPUNIT_ASSERT(pEntry->NeedsRepaint());
922 }
923
924 m_pDoc->MoveTab(0, 1);
925
926 // the conditional format should listen to A1:A3 on the second sheet
927 for (SCROW nRow = 0; nRow < 3; ++nRow)
928 {
929 m_pDoc->SetValue(ScAddress(0, nRow, 1), 1.0);
930 CPPUNIT_ASSERT(pEntry->NeedsRepaint());
931
932 m_pDoc->SetValue(ScAddress(0, nRow, 0), 1.0);
933 CPPUNIT_ASSERT(!pEntry->NeedsRepaint());
934 }
935
936 m_pDoc->DeleteTab(1);
937 m_pDoc->DeleteTab(0);
938 }
939
testCondFormatUpdateInsertTab()940 void Test::testCondFormatUpdateInsertTab()
941 {
942 m_pDoc->InsertTab(0, "test");
943
944 ScConditionEntry* pEntry = new ScConditionEntry(ScConditionMode::Equal, "A1", "", m_pDoc, ScAddress(10, 10, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
945
946 auto pFormat = std::make_unique<ScConditionalFormat>(0, m_pDoc);
947 pFormat->SetRange(ScRange(10, 10, 0, 10, 12, 0));
948 auto pFormatTmp = pFormat.get();
949 m_pDoc->AddCondFormat(std::move(pFormat), 0);
950
951 pFormatTmp->AddEntry(pEntry);
952
953 // the conditional format should listen to A1:A3
954 for (SCROW nRow = 0; nRow < 3; ++nRow)
955 {
956 m_pDoc->SetValue(ScAddress(0, nRow, 0), 1.0);
957 CPPUNIT_ASSERT(pEntry->NeedsRepaint());
958
959 m_pDoc->SetValue(ScAddress(0, nRow, 1), 1.0);
960 CPPUNIT_ASSERT(!pEntry->NeedsRepaint());
961 }
962
963 m_pDoc->InsertTab(0, "test2");
964
965 // the conditional format should listen to A1:A3 on the second sheet
966 for (SCROW nRow = 0; nRow < 3; ++nRow)
967 {
968 m_pDoc->SetValue(ScAddress(0, nRow, 1), 1.0);
969 CPPUNIT_ASSERT(pEntry->NeedsRepaint());
970
971 m_pDoc->SetValue(ScAddress(0, nRow, 0), 1.0);
972 CPPUNIT_ASSERT(!pEntry->NeedsRepaint());
973 }
974
975 m_pDoc->DeleteTab(1);
976 m_pDoc->DeleteTab(0);
977 }
978
testCondFormatUpdateDeleteTab()979 void Test::testCondFormatUpdateDeleteTab()
980 {
981 m_pDoc->InsertTab(0, "test");
982 m_pDoc->InsertTab(1, "Test2");
983
984 ScConditionEntry* pEntry = new ScConditionEntry(ScConditionMode::Equal, "A1", "", m_pDoc, ScAddress(10, 10, 1), "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
985
986 auto pFormat = std::make_unique<ScConditionalFormat>(0, m_pDoc);
987 pFormat->SetRange(ScRange(10, 10, 1, 10, 12, 1));
988 auto pFormatTmp = pFormat.get();
989 m_pDoc->AddCondFormat(std::move(pFormat), 1);
990
991 pFormatTmp->AddEntry(pEntry);
992
993 // the conditional format should listen to A1:A3 on the second sheet
994 for (SCROW nRow = 0; nRow < 3; ++nRow)
995 {
996 m_pDoc->SetValue(ScAddress(0, nRow, 1), 1.0);
997 CPPUNIT_ASSERT(pEntry->NeedsRepaint());
998 }
999
1000 m_pDoc->DeleteTab(0);
1001
1002 // the conditional format should listen to A1:A3 on the second sheet
1003 for (SCROW nRow = 0; nRow < 3; ++nRow)
1004 {
1005 m_pDoc->SetValue(ScAddress(0, nRow, 0), 1.0);
1006 CPPUNIT_ASSERT(pEntry->NeedsRepaint());
1007 }
1008
1009 m_pDoc->DeleteTab(0);
1010 }
1011
testCondFormatUpdateReference()1012 void Test::testCondFormatUpdateReference()
1013 {
1014 m_pDoc->InsertTab(0, "test");
1015 m_pDoc->InsertTab(1, "Test2");
1016
1017 ScConditionEntry* pEntry = new ScConditionEntry(ScConditionMode::Equal, "A1", "", m_pDoc, ScAddress(10, 10, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
1018
1019 auto pFormat = std::make_unique<ScConditionalFormat>(0, m_pDoc);
1020 pFormat->SetRange(ScRange(10, 10, 0, 10, 12, 0));
1021 auto pFormatTmp = pFormat.get();
1022 m_pDoc->AddCondFormat(std::move(pFormat), 0);
1023
1024 pFormatTmp->AddEntry(pEntry);
1025
1026 // the conditional format should listen to A1:A3
1027 for (SCROW nRow = 0; nRow < 3; ++nRow)
1028 {
1029 m_pDoc->SetValue(ScAddress(0, nRow, 0), 1.0);
1030 CPPUNIT_ASSERT(pEntry->NeedsRepaint());
1031 }
1032
1033 m_pDoc->DeleteTab(1);
1034 m_pDoc->DeleteTab(0);
1035 }
1036
testCondFormatUpdateReferenceDelRow()1037 void Test::testCondFormatUpdateReferenceDelRow()
1038 {
1039 m_pDoc->InsertTab(0, "test");
1040
1041 ScConditionEntry* pEntry = new ScConditionEntry(ScConditionMode::Equal, "B6", "", m_pDoc, ScAddress(0, 5, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
1042
1043 auto pFormat = std::make_unique<ScConditionalFormat>(0, m_pDoc);
1044 pFormat->SetRange(ScRange(0, 5, 0, 0, 5, 0));
1045 auto pFormatTmp = pFormat.get();
1046 m_pDoc->AddCondFormat(std::move(pFormat), 0);
1047
1048 pFormatTmp->AddEntry(pEntry);
1049
1050 m_pDoc->DeleteRow(0, 0, MAXCOL, 0, 4, 1);
1051
1052 OUString aStr = pEntry->GetExpression(ScAddress(0, 4, 0), 0);
1053 CPPUNIT_ASSERT_EQUAL(OUString("B5"), aStr);
1054
1055 m_pDoc->DeleteTab(0);
1056 }
1057
testCondFormatUpdateReferenceInsRow()1058 void Test::testCondFormatUpdateReferenceInsRow()
1059 {
1060 m_pDoc->InsertTab(0, "test");
1061
1062 ScConditionEntry* pEntry = new ScConditionEntry(ScConditionMode::Equal, "B6", "", m_pDoc, ScAddress(0, 5, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
1063
1064 auto pFormat = std::make_unique<ScConditionalFormat>(0, m_pDoc);
1065 pFormat->SetRange(ScRange(0, 5, 0, 0, 5, 0));
1066 auto pFormatTmp = pFormat.get();
1067 m_pDoc->AddCondFormat(std::move(pFormat), 0);
1068
1069 pFormatTmp->AddEntry(pEntry);
1070
1071 m_pDoc->InsertRow(0, 0, MAXCOL, 0, 4, 1);
1072
1073 OUString aStr = pEntry->GetExpression(ScAddress(0, 6, 0), 0);
1074 CPPUNIT_ASSERT_EQUAL(OUString("B7"), aStr);
1075
1076 m_pDoc->DeleteTab(0);
1077 }
1078
testCondFormatUndoList()1079 void Test::testCondFormatUndoList()
1080 {
1081 m_pDoc->InsertTab(0, "test");
1082
1083 ScConditionEntry* pEntry = new ScConditionEntry(ScConditionMode::Equal, "B6", "", m_pDoc, ScAddress(0, 5, 0), "", "", formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::GRAM_DEFAULT);
1084
1085 auto pFormat = std::make_unique<ScConditionalFormat>(0, m_pDoc);
1086 pFormat->AddEntry(pEntry);
1087 pFormat->SetRange(ScRange(0, 0, 0, 0, 5, 0));
1088 auto pFormatTmp = pFormat.get();
1089 m_pDoc->AddCondFormat(std::move(pFormat), 0);
1090 m_pDoc->AddCondFormatData(pFormatTmp->GetRange(), 0, pFormatTmp->GetKey());
1091
1092 ScDocFunc& rFunc = getDocShell().GetDocFunc();
1093
1094 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetCondFormList(0)->size());
1095 for (SCROW nRow = 0; nRow <= 5; ++nRow)
1096 CPPUNIT_ASSERT(m_pDoc->GetCondFormat(0, nRow, 0));
1097
1098 ScConditionalFormatList* pNewList = new ScConditionalFormatList();
1099
1100 rFunc.SetConditionalFormatList(pNewList, 0);
1101
1102 CPPUNIT_ASSERT_EQUAL(size_t(0), m_pDoc->GetCondFormList(0)->size());
1103 for (SCROW nRow = 0; nRow <= 5; ++nRow)
1104 CPPUNIT_ASSERT(!m_pDoc->GetCondFormat(0, nRow, 0));
1105
1106 m_pDoc->GetUndoManager()->Undo();
1107
1108 CPPUNIT_ASSERT_EQUAL(size_t(1), m_pDoc->GetCondFormList(0)->size());
1109 for (SCROW nRow = 0; nRow <= 5; ++nRow)
1110 CPPUNIT_ASSERT(m_pDoc->GetCondFormat(0, nRow, 0));
1111
1112 m_pDoc->GetUndoManager()->Redo();
1113
1114 CPPUNIT_ASSERT_EQUAL(size_t(0), m_pDoc->GetCondFormList(0)->size());
1115 for (SCROW nRow = 0; nRow <= 5; ++nRow)
1116 CPPUNIT_ASSERT(!m_pDoc->GetCondFormat(0, nRow, 0));
1117
1118 m_pDoc->DeleteTab(0);
1119 }
1120
1121 namespace {
1122
addSingleCellCondFormat(ScDocument * pDoc,const ScAddress & rAddr,sal_uInt32 nKey,const OUString & rCondition)1123 sal_uInt32 addSingleCellCondFormat(ScDocument* pDoc, const ScAddress& rAddr, sal_uInt32 nKey, const OUString& rCondition)
1124 {
1125 auto pFormat = std::make_unique<ScConditionalFormat>(nKey, pDoc);
1126 ScRange aCondFormatRange(rAddr);
1127 ScRangeList aRangeList(aCondFormatRange);
1128 pFormat->SetRange(aRangeList);
1129
1130 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct, rCondition, "",
1131 pDoc, ScAddress(0,0,0), ScResId(STR_STYLENAME_RESULT));
1132 pFormat->AddEntry(pEntry);
1133 return pDoc->AddCondFormat(std::move(pFormat), 0);
1134 }
1135
1136 }
1137
testMultipleSingleCellCondFormatCopyPaste()1138 void Test::testMultipleSingleCellCondFormatCopyPaste()
1139 {
1140 m_pDoc->InsertTab(0, "Test");
1141
1142 sal_uInt32 nFirstCondFormatKey = addSingleCellCondFormat(m_pDoc, ScAddress(0, 0, 0), 1, "=A2");
1143 sal_uInt32 nSecondCondFormatKey = addSingleCellCondFormat(m_pDoc, ScAddress(1, 0, 0), 2, "=B3");
1144
1145 ScDocument aClipDoc(SCDOCMODE_CLIP);
1146 copyToClip(m_pDoc, ScRange(0,0,0,2,0,0), &aClipDoc);
1147 ScRange aTargetRange(2,4,0,7,4,0);
1148 pasteOneCellFromClip(m_pDoc, aTargetRange, &aClipDoc);
1149
1150 for (SCCOL nCol = 2; nCol <= 7; ++nCol)
1151 {
1152 ScConditionalFormat* pFormat = m_pDoc->GetCondFormat(nCol, 4, 0);
1153 if (((nCol - 2) % 3) == 0)
1154 {
1155 CPPUNIT_ASSERT_EQUAL(pFormat->GetKey(), nFirstCondFormatKey);
1156 }
1157 else if (((nCol - 2) % 3) == 1)
1158 {
1159 CPPUNIT_ASSERT_EQUAL(pFormat->GetKey(), nSecondCondFormatKey);
1160 }
1161 else
1162 {
1163 CPPUNIT_ASSERT(!pFormat);
1164 }
1165 }
1166
1167 m_pDoc->DeleteTab(0);
1168 }
1169
testDeduplicateMultipleCondFormats()1170 void Test::testDeduplicateMultipleCondFormats()
1171 {
1172 m_pDoc->InsertTab(0, "Test");
1173
1174 sal_uInt32 nFirstCondFormatKey = addSingleCellCondFormat(m_pDoc, ScAddress(0, 0, 0), 1, "=B2");
1175 sal_uInt32 nSecondCondFormatKey = addSingleCellCondFormat(m_pDoc, ScAddress(1, 0, 0), 2, "=B2");
1176
1177 ScDocument aClipDoc(SCDOCMODE_CLIP);
1178 copyToClip(m_pDoc, ScRange(0,0,0,2,0,0), &aClipDoc);
1179 ScRange aTargetRange(2,4,0,7,4,0);
1180 pasteOneCellFromClip(m_pDoc, aTargetRange, &aClipDoc);
1181
1182 for (SCCOL nCol = 2; nCol <= 7; ++nCol)
1183 {
1184 ScConditionalFormat* pFormat = m_pDoc->GetCondFormat(nCol, 4, 0);
1185 if (((nCol - 2) % 3) == 0)
1186 {
1187 CPPUNIT_ASSERT_EQUAL(pFormat->GetKey(), nFirstCondFormatKey);
1188 }
1189 else if (((nCol - 2) % 3) == 1)
1190 {
1191 CPPUNIT_ASSERT_EQUAL(pFormat->GetKey(), nSecondCondFormatKey);
1192 }
1193 else
1194 {
1195 CPPUNIT_ASSERT(!pFormat);
1196 }
1197 }
1198
1199 m_pDoc->DeleteTab(0);
1200 }
1201
testCondFormatListenToOwnRange()1202 void Test::testCondFormatListenToOwnRange()
1203 {
1204 m_pDoc->InsertTab(0, "Test");
1205
1206 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
1207
1208 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
1209 ScRangeList aRangeList(ScRange(0,0,0,10,0,0));
1210 pFormat->SetRange(aRangeList);
1211
1212 ScIconSetFormat* pEntry = new ScIconSetFormat(m_pDoc);
1213 ScIconSetFormatData* pData = new ScIconSetFormatData;
1214 pData->m_Entries.push_back(std::make_unique<ScColorScaleEntry>(0, COL_BLUE));
1215 pData->m_Entries.push_back(std::make_unique<ScColorScaleEntry>(1, COL_GREEN));
1216 pData->m_Entries.push_back(std::make_unique<ScColorScaleEntry>(2, COL_RED));
1217 pEntry->SetIconSetData(pData);
1218 pEntry->SetParent(pFormat.get());
1219
1220 m_pDoc->AddCondFormatData(pFormat->GetRange(), 0, 1);
1221 pFormat->AddEntry(pEntry);
1222 pList->InsertNew(std::move(pFormat));
1223
1224 bool bFirstCallbackCalled = false;
1225 bool bSecondCallbackCalled = false;
1226 bool bThirdCallbackCalled = false;
1227 std::function<void()> aFirstCallback = [&]() {bFirstCallbackCalled = true;};
1228 std::function<void()> aSecondCallback = [&]() {bSecondCallbackCalled = true;};
1229 std::function<void()> aThirdCallback = [&]() {bThirdCallbackCalled = true;};
1230 pData->m_Entries[0]->SetType(COLORSCALE_PERCENT);
1231 pData->m_Entries[0]->SetRepaintCallback(aFirstCallback);
1232
1233 m_pDoc->SetValue(0, 0, 0, -1.0);
1234
1235 CPPUNIT_ASSERT(bFirstCallbackCalled);
1236
1237 m_pDoc->DeleteTab(0);
1238 }
1239
testCondFormatVolatileFunctionRecalc()1240 void Test::testCondFormatVolatileFunctionRecalc()
1241 {
1242 m_pDoc->InsertTab(0, "Test");
1243
1244 m_pDoc->SetValue(0, 0, 0, 0.5);
1245
1246 ScConditionalFormatList* pList = m_pDoc->GetCondFormList(0);
1247
1248 auto pFormat = std::make_unique<ScConditionalFormat>(1, m_pDoc);
1249 ScRangeList aRangeList(ScRange(0,0,0,10,0,0));
1250 pFormat->SetRange(aRangeList);
1251
1252 ScCondFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Greater,"RAND()","",m_pDoc,ScAddress(0,0,0),ScResId(STR_STYLENAME_RESULT));
1253 pEntry->SetParent(pFormat.get());
1254
1255 m_pDoc->AddCondFormatData(pFormat->GetRange(), 0, 1);
1256 pFormat->AddEntry(pEntry);
1257 auto pFormatTmp = pFormat.get();
1258 pList->InsertNew(std::move(pFormat));
1259
1260 ScRefCellValue aCell(*m_pDoc, ScAddress(0, 0, 0));
1261 bool bValid = pEntry->IsCellValid(aCell, ScAddress(0, 0, 0));
1262
1263 bool bNewValid = bValid;
1264 // chance of a random failure is 0.5^100, anyone hitting that will get a beer from me
1265 for (size_t i = 0; i < 100; ++i)
1266 {
1267 pFormatTmp->CalcAll();
1268 bNewValid = pEntry->IsCellValid(aCell, ScAddress(0, 0, 0));
1269
1270 if (bValid != bNewValid)
1271 break;
1272 }
1273
1274 CPPUNIT_ASSERT(bValid != bNewValid);
1275
1276 m_pDoc->DeleteTab(0);
1277 }
1278
1279 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1280