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 <condformatdlg.hxx>
12 #include <condformatdlgentry.hxx>
13 #include <conditio.hxx>
14 #include <compiler.hxx>
15 #include <colorscale.hxx>
16 #include <condformathelper.hxx>
17 
18 #include <document.hxx>
19 
20 #include <svl/style.hxx>
21 #include <sfx2/dispatch.hxx>
22 #include <sfx2/frame.hxx>
23 #include <svl/stritem.hxx>
24 #include <svl/intitem.hxx>
25 #include <svx/colorbox.hxx>
26 #include <vcl/settings.hxx>
27 #include <vcl/svapp.hxx>
28 #include <formula/token.hxx>
29 #include <formula/errorcodes.hxx>
30 #include <tokenarray.hxx>
31 #include <stlpool.hxx>
32 #include <tabvwsh.hxx>
33 #include <unotools/charclass.hxx>
34 
35 #include <colorformat.hxx>
36 #include <scresid.hxx>
37 #include <globstr.hrc>
38 #include <strings.hrc>
39 
40 #include <set>
41 
42 ScCondFrmtEntry::ScCondFrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, const ScAddress& rPos)
43     : mpParent(pParent)
44     , mxBuilder(Application::CreateBuilder(pParent->GetContainer(), "modules/scalc/ui/conditionalentry.ui"))
45     , mxBorder(mxBuilder->weld_widget("border"))
46     , mxGrid(mxBuilder->weld_container("grid"))
47     , mxFtCondNr(mxBuilder->weld_label("number"))
48     , mxFtCondition(mxBuilder->weld_label("condition"))
49     , mbActive(false)
50     , maStrCondition(ScResId(SCSTR_CONDITION))
51     , mxLbType(mxBuilder->weld_combo_box("type"))
52     , mpDoc(pDoc)
53     , maPos(rPos)
54 {
55     mxLbType->connect_changed(LINK(pParent, ScCondFormatList, TypeListHdl));
56     mxGrid->connect_mouse_press(LINK(this, ScCondFrmtEntry, EntrySelectHdl));
57     maClickHdl = LINK( pParent, ScCondFormatList, EntrySelectHdl );
58 
59     Show();
60 }
61 
62 ScCondFrmtEntry::~ScCondFrmtEntry()
63 {
64     mpParent->GetContainer()->move(mxBorder.get(), nullptr);
65 }
66 
67 IMPL_LINK_NOARG(ScCondFrmtEntry, EntrySelectHdl, const MouseEvent&, bool)
68 {
69     maClickHdl.Call(*this);
70     return false;
71 }
72 
73 void ScCondFrmtEntry::SetIndex(sal_Int32 nIndex)
74 {
75     mxFtCondNr->set_label(maStrCondition + OUString::number(nIndex));
76 }
77 
78 void ScCondFrmtEntry::Select()
79 {
80     mxFtCondition->set_label(OUString());
81     mxFtCondition->hide();
82     mxLbType->show();
83     mbActive = true;
84 }
85 
86 void ScCondFrmtEntry::Deselect()
87 {
88     OUString aCondText = GetExpressionString();
89     mxFtCondition->set_label(aCondText);
90     mxFtCondition->show();
91     mxLbType->hide();
92     mbActive = false;
93 }
94 
95 //condition
96 
97 namespace {
98 
99 void FillStyleListBox( const ScDocument* pDoc, weld::ComboBox& rLbStyle )
100 {
101     std::set<OUString> aStyleNames;
102     SfxStyleSheetIterator aStyleIter( pDoc->GetStyleSheetPool(), SfxStyleFamily::Para );
103     for ( SfxStyleSheetBase* pStyle = aStyleIter.First(); pStyle; pStyle = aStyleIter.Next() )
104     {
105         aStyleNames.insert(pStyle->GetName());
106     }
107     for(const auto& rStyleName : aStyleNames)
108     {
109         rLbStyle.append_text(rStyleName);
110     }
111 }
112 
113 }
114 
115 const ScConditionMode ScConditionFrmtEntry::mpEntryToCond[ScConditionFrmtEntry::NUM_COND_ENTRIES] = {
116     ScConditionMode::Equal,
117     ScConditionMode::Less,
118     ScConditionMode::Greater,
119     ScConditionMode::EqLess,
120     ScConditionMode::EqGreater,
121     ScConditionMode::NotEqual,
122     ScConditionMode::Between,
123     ScConditionMode::NotBetween,
124     ScConditionMode::Duplicate,
125     ScConditionMode::NotDuplicate,
126     ScConditionMode::Top10,
127     ScConditionMode::Bottom10,
128     ScConditionMode::TopPercent,
129     ScConditionMode::BottomPercent,
130     ScConditionMode::AboveAverage,
131     ScConditionMode::BelowAverage,
132     ScConditionMode::AboveEqualAverage,
133     ScConditionMode::BelowEqualAverage,
134     ScConditionMode::Error,
135     ScConditionMode::NoError,
136     ScConditionMode::BeginsWith,
137     ScConditionMode::EndsWith,
138     ScConditionMode::ContainsText,
139     ScConditionMode::NotContainsText
140 };
141 
142 ScConditionFrmtEntry::ScConditionFrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, ScCondFormatDlg* pDialogParent,
143         const ScAddress& rPos, const ScCondFormatEntry* pFormatEntry)
144     : ScCondFrmtEntry(pParent, pDoc, rPos)
145     , mxLbCondType(mxBuilder->weld_combo_box("typeis"))
146     , mxEdVal1(new formula::RefEdit(mxBuilder->weld_entry("val1")))
147     , mxEdVal2(new formula::RefEdit(mxBuilder->weld_entry("val2")))
148     , mxFtVal(mxBuilder->weld_label("valueft"))
149     , mxFtStyle(mxBuilder->weld_label("styleft"))
150     , mxLbStyle(mxBuilder->weld_combo_box("style"))
151     , mxWdPreviewWin(mxBuilder->weld_widget("previewwin"))
152     , mxWdPreview(new weld::CustomWeld(*mxBuilder, "preview", maWdPreview))
153     , mbIsInStyleCreate(false)
154 {
155     mxWdPreview->set_size_request(-1, mxLbStyle->get_preferred_size().Height());
156 
157     mxLbType->set_active(1);
158 
159     Init(pDialogParent);
160 
161     StartListening(*pDoc->GetStyleSheetPool(), DuplicateHandling::Prevent);
162 
163     if(pFormatEntry)
164     {
165         mxLbStyle->set_active_text(pFormatEntry->GetStyle());
166         StyleSelectHdl(*mxLbStyle);
167         ScConditionMode eMode = pFormatEntry->GetOperation();
168 
169         mxLbCondType->set_active(ConditionModeToEntryPos(eMode));
170 
171         switch(GetNumberEditFields(eMode))
172         {
173             case 0:
174                 mxEdVal1->GetWidget()->hide();
175                 mxEdVal2->GetWidget()->hide();
176                 break;
177             case 1:
178                 mxEdVal1->GetWidget()->show();
179                 mxEdVal1->SetText(pFormatEntry->GetExpression(maPos, 0));
180                 mxEdVal2->GetWidget()->hide();
181                 OnEdChanged(*mxEdVal1);
182                 break;
183             case 2:
184                 mxEdVal1->GetWidget()->show();
185                 mxEdVal1->SetText(pFormatEntry->GetExpression(maPos, 0));
186                 OnEdChanged(*mxEdVal1);
187                 mxEdVal2->GetWidget()->show();
188                 mxEdVal2->SetText(pFormatEntry->GetExpression(maPos, 1));
189                 OnEdChanged(*mxEdVal2);
190                 break;
191         }
192     }
193     else
194     {
195         mxLbCondType->set_active(0);
196         mxEdVal2->GetWidget()->hide();
197         mxLbStyle->set_active(1);
198     }
199 }
200 
201 ScConditionFrmtEntry::~ScConditionFrmtEntry()
202 {
203 }
204 
205 void ScConditionFrmtEntry::Init(ScCondFormatDlg* pDialogParent)
206 {
207     mxEdVal1->SetGetFocusHdl( LINK( pDialogParent, ScCondFormatDlg, RangeGetFocusHdl ) );
208     mxEdVal2->SetGetFocusHdl( LINK( pDialogParent, ScCondFormatDlg, RangeGetFocusHdl ) );
209 
210     mxEdVal1->SetModifyHdl( LINK( this, ScConditionFrmtEntry, OnEdChanged ) );
211     mxEdVal2->SetModifyHdl( LINK( this, ScConditionFrmtEntry, OnEdChanged ) );
212 
213     FillStyleListBox( mpDoc, *mxLbStyle );
214     mxLbStyle->connect_changed( LINK( this, ScConditionFrmtEntry, StyleSelectHdl ) );
215 
216     mxLbCondType->connect_changed( LINK( this, ScConditionFrmtEntry, ConditionTypeSelectHdl ) );
217 }
218 
219 ScFormatEntry* ScConditionFrmtEntry::createConditionEntry() const
220 {
221     ScConditionMode eMode = EntryPosToConditionMode(mxLbCondType->get_active());
222     OUString aExpr1 = mxEdVal1->GetText();
223     OUString aExpr2;
224     if (GetNumberEditFields(eMode) == 2)
225     {
226         aExpr2 = mxEdVal2->GetText();
227         if (aExpr2.isEmpty())
228         {
229             return nullptr;
230         }
231     }
232 
233     ScFormatEntry* pEntry = new ScCondFormatEntry(eMode, aExpr1, aExpr2, mpDoc, maPos, mxLbStyle->get_active_text());
234     return pEntry;
235 }
236 
237 IMPL_LINK(ScConditionFrmtEntry, OnEdChanged, formula::RefEdit&, rRefEdit, void)
238 {
239     weld::Entry& rEdit = *rRefEdit.GetWidget();
240     OUString aFormula = rEdit.get_text();
241 
242     if( aFormula.isEmpty() )
243     {
244         mxFtVal->set_label(ScResId(STR_ENTER_VALUE));
245         return;
246     }
247 
248     ScCompiler aComp( mpDoc, maPos, mpDoc->GetGrammar() );
249     std::unique_ptr<ScTokenArray> ta(aComp.CompileString(aFormula));
250 
251     // Error, warn the user
252     if( ta->GetCodeError() != FormulaError::NONE || ( ta->GetLen() == 0 ) )
253     {
254         rEdit.set_message_type(weld::EntryMessageType::Error);
255         mxFtVal->set_label(ScResId(STR_VALID_DEFERROR));
256         return;
257     }
258 
259     // Recognized col/row name or string token, warn the user
260     formula::FormulaToken* token = ta->FirstToken();
261     formula::StackVar t = token->GetType();
262     OpCode op = token->GetOpCode();
263     if( ( op == ocColRowName ) ||
264         ( ( op == ocBad ) && ( t == formula::svString ) )
265       )
266     {
267         rEdit.set_message_type(weld::EntryMessageType::Warning);
268         mxFtVal->set_label(ScResId(STR_UNQUOTED_STRING));
269         return;
270     }
271 
272     rEdit.set_message_type(weld::EntryMessageType::Normal);
273     mxFtVal->set_label("");
274 }
275 
276 void ScConditionFrmtEntry::Select()
277 {
278     mxFtVal->show();
279     ScCondFrmtEntry::Select();
280 }
281 
282 void ScConditionFrmtEntry::Deselect()
283 {
284     mxFtVal->hide();
285     ScCondFrmtEntry::Deselect();
286 }
287 
288 sal_Int32 ScConditionFrmtEntry::ConditionModeToEntryPos( ScConditionMode eMode )
289 {
290     for ( sal_Int32 i = 0; i < NUM_COND_ENTRIES; ++i )
291     {
292         if (mpEntryToCond[i] == eMode)
293         {
294             return i;
295         }
296     }
297     assert(false); // should never get here
298     return 0;
299 }
300 
301 ScConditionMode ScConditionFrmtEntry::EntryPosToConditionMode( sal_Int32 aEntryPos )
302 {
303     assert( 0 <= aEntryPos && aEntryPos < NUM_COND_ENTRIES );
304     return mpEntryToCond[aEntryPos];
305 }
306 
307 sal_Int32 ScConditionFrmtEntry::GetNumberEditFields( ScConditionMode eMode )
308 {
309     switch(eMode)
310     {
311         case ScConditionMode::Equal:
312         case ScConditionMode::Less:
313         case ScConditionMode::Greater:
314         case ScConditionMode::EqLess:
315         case ScConditionMode::EqGreater:
316         case ScConditionMode::NotEqual:
317         case ScConditionMode::Top10:
318         case ScConditionMode::Bottom10:
319         case ScConditionMode::TopPercent:
320         case ScConditionMode::BottomPercent:
321         case ScConditionMode::BeginsWith:
322         case ScConditionMode::EndsWith:
323         case ScConditionMode::ContainsText:
324         case ScConditionMode::NotContainsText:
325         case ScConditionMode::Error:
326         case ScConditionMode::NoError:
327             return 1;
328         case ScConditionMode::AboveAverage:
329         case ScConditionMode::BelowAverage:
330         case ScConditionMode::AboveEqualAverage:
331         case ScConditionMode::BelowEqualAverage:
332         case ScConditionMode::Duplicate:
333         case ScConditionMode::NotDuplicate:
334             return 0;
335         case ScConditionMode::Between:
336         case ScConditionMode::NotBetween:
337             return 2;
338         default:
339             assert(false); // should never get here
340             return 0;
341     }
342 }
343 
344 OUString ScConditionFrmtEntry::GetExpressionString()
345 {
346     return ScCondFormatHelper::GetExpression(CONDITION, mxLbCondType->get_active(), mxEdVal1->GetText(), mxEdVal2->GetText());
347 }
348 
349 ScFormatEntry* ScConditionFrmtEntry::GetEntry() const
350 {
351     return createConditionEntry();
352 }
353 
354 void ScConditionFrmtEntry::SetActive()
355 {
356     ScConditionMode eMode = EntryPosToConditionMode(mxLbCondType->get_active());
357     mxLbCondType->show();
358     switch(GetNumberEditFields(eMode))
359     {
360         case 1:
361             mxEdVal1->GetWidget()->show();
362             break;
363         case 2:
364             mxEdVal1->GetWidget()->show();
365             mxEdVal2->GetWidget()->show();
366             break;
367     }
368     mxFtStyle->show();
369     mxLbStyle->show();
370     mxWdPreviewWin->show();
371 
372     Select();
373 }
374 
375 void ScConditionFrmtEntry::SetInactive()
376 {
377     mxLbCondType->hide();
378     mxEdVal1->GetWidget()->hide();
379     mxEdVal2->GetWidget()->hide();
380     mxFtStyle->hide();
381     mxLbStyle->hide();
382     mxWdPreviewWin->hide();
383 
384     Deselect();
385 }
386 
387 namespace {
388 
389 void UpdateStyleList(weld::ComboBox& rLbStyle, const ScDocument* pDoc)
390 {
391     OUString aSelectedStyle = rLbStyle.get_active_text();
392     for (sal_Int32 i = rLbStyle.get_count(); i > 1; --i)
393         rLbStyle.remove(i - 1);
394     FillStyleListBox(pDoc, rLbStyle);
395     rLbStyle.set_active_text(aSelectedStyle);
396 }
397 
398 }
399 
400 void ScConditionFrmtEntry::Notify(SfxBroadcaster&, const SfxHint& rHint)
401 {
402     if(rHint.GetId() == SfxHintId::StyleSheetModified)
403     {
404         if(!mbIsInStyleCreate)
405             UpdateStyleList(*mxLbStyle, mpDoc);
406     }
407 }
408 
409 namespace {
410 
411 void StyleSelect(weld::Window* pDialogParent, weld::ComboBox& rLbStyle, const ScDocument* pDoc, FontPrevWindow& rWdPreview)
412 {
413     if (rLbStyle.get_active() == 0)
414     {
415         // call new style dialog
416         SfxUInt16Item aFamilyItem( SID_STYLE_FAMILY, sal_uInt16(SfxStyleFamily::Para) );
417         SfxStringItem aRefItem( SID_STYLE_REFERENCE, ScResId(STR_STYLENAME_STANDARD) );
418         css::uno::Any aAny(pDialogParent->GetXWindow());
419         SfxUnoAnyItem aDialogParent( SID_DIALOG_PARENT, aAny );
420 
421         // unlock the dispatcher so SID_STYLE_NEW can be executed
422         // (SetDispatcherLock would affect all Calc documents)
423         ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
424         SfxDispatcher* pDisp = pViewShell->GetDispatcher();
425         bool bLocked = pDisp->IsLocked();
426         if (bLocked)
427             pDisp->Lock(false);
428 
429         // Execute the "new style" slot, complete with undo and all necessary updates.
430         // The return value (SfxUInt16Item) is ignored, look for new styles instead.
431         pDisp->ExecuteList(SID_STYLE_NEW,
432             SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
433             { &aFamilyItem, &aRefItem }, { &aDialogParent });
434 
435         if (bLocked)
436             pDisp->Lock(true);
437 
438         // Find the new style and add it into the style list boxes
439         SfxStyleSheetIterator aStyleIter( pDoc->GetStyleSheetPool(), SfxStyleFamily::Para );
440         bool bFound = false;
441         for ( SfxStyleSheetBase* pStyle = aStyleIter.First(); pStyle && !bFound; pStyle = aStyleIter.Next() )
442         {
443             const OUString& aName = pStyle->GetName();
444             if (rLbStyle.find_text(aName) == -1)    // all lists contain the same entries
445             {
446                 for( sal_Int32 i = 1, n = rLbStyle.get_count(); i <= n && !bFound; ++i)
447                 {
448                     OUString aStyleName = ScGlobal::pCharClass->uppercase(rLbStyle.get_text(i));
449                     if( i == n )
450                     {
451                         rLbStyle.append_text(aName);
452                         rLbStyle.set_active_text(aName);
453                         bFound = true;
454                     }
455                     else if( aStyleName > ScGlobal::pCharClass->uppercase(aName) )
456                     {
457                         rLbStyle.insert_text(i, aName);
458                         rLbStyle.set_active_text(aName);
459                         bFound = true;
460                     }
461                 }
462             }
463         }
464     }
465 
466     OUString aStyleName = rLbStyle.get_active_text();
467     SfxStyleSheetBase* pStyleSheet = pDoc->GetStyleSheetPool()->Find( aStyleName, SfxStyleFamily::Para );
468     if(pStyleSheet)
469     {
470         const SfxItemSet& rSet = pStyleSheet->GetItemSet();
471         rWdPreview.SetFromItemSet(rSet, false);
472     }
473 }
474 
475 }
476 
477 IMPL_LINK_NOARG(ScConditionFrmtEntry, StyleSelectHdl, weld::ComboBox&, void)
478 {
479     mbIsInStyleCreate = true;
480     StyleSelect(mpParent->GetFrameWeld(), *mxLbStyle, mpDoc, maWdPreview);
481     mbIsInStyleCreate = false;
482 }
483 
484 // formula
485 
486 ScFormulaFrmtEntry::ScFormulaFrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, ScCondFormatDlg* pDialogParent, const ScAddress& rPos, const ScCondFormatEntry* pFormat)
487     : ScCondFrmtEntry(pParent, pDoc, rPos)
488     , mxFtStyle(mxBuilder->weld_label("styleft"))
489     , mxLbStyle(mxBuilder->weld_combo_box("style"))
490     , mxWdPreviewWin(mxBuilder->weld_widget("previewwin"))
491     , mxWdPreview(new weld::CustomWeld(*mxBuilder, "preview", maWdPreview))
492     , mxEdFormula(new formula::RefEdit(mxBuilder->weld_entry("formula")))
493 {
494     mxWdPreview->set_size_request(-1, mxLbStyle->get_preferred_size().Height());
495 
496     Init(pDialogParent);
497 
498     mxLbType->set_active(2);
499 
500     if(pFormat)
501     {
502         mxEdFormula->SetText(pFormat->GetExpression(rPos, 0, 0, pDoc->GetGrammar()));
503         mxLbStyle->set_active_text(pFormat->GetStyle());
504     }
505     else
506     {
507         mxLbStyle->set_active(1);
508     }
509 
510     StyleSelectHdl(*mxLbStyle);
511 }
512 
513 ScFormulaFrmtEntry::~ScFormulaFrmtEntry()
514 {
515 }
516 
517 void ScFormulaFrmtEntry::Init(ScCondFormatDlg* pDialogParent)
518 {
519     mxEdFormula->SetGetFocusHdl( LINK( pDialogParent, ScCondFormatDlg, RangeGetFocusHdl ) );
520 
521     FillStyleListBox( mpDoc, *mxLbStyle );
522     mxLbStyle->connect_changed( LINK( this, ScFormulaFrmtEntry, StyleSelectHdl ) );
523 }
524 
525 IMPL_LINK_NOARG(ScFormulaFrmtEntry, StyleSelectHdl, weld::ComboBox&, void)
526 {
527     StyleSelect(mpParent->GetFrameWeld(), *mxLbStyle, mpDoc, maWdPreview);
528 }
529 
530 ScFormatEntry* ScFormulaFrmtEntry::createFormulaEntry() const
531 {
532     OUString aFormula = mxEdFormula->GetText();
533     if(aFormula.isEmpty())
534         return nullptr;
535 
536     ScFormatEntry* pEntry = new ScCondFormatEntry(ScConditionMode::Direct, aFormula, OUString(), mpDoc, maPos, mxLbStyle->get_active_text());
537     return pEntry;
538 }
539 
540 ScFormatEntry* ScFormulaFrmtEntry::GetEntry() const
541 {
542     return createFormulaEntry();
543 }
544 
545 OUString ScFormulaFrmtEntry::GetExpressionString()
546 {
547     return ScCondFormatHelper::GetExpression(FORMULA, 0, mxEdFormula->GetText());
548 }
549 
550 void ScFormulaFrmtEntry::SetActive()
551 {
552     mxWdPreviewWin->show();
553     mxFtStyle->show();
554     mxLbStyle->show();
555     mxEdFormula->GetWidget()->show();
556 
557     Select();
558 }
559 
560 void ScFormulaFrmtEntry::SetInactive()
561 {
562     mxWdPreviewWin->hide();
563     mxFtStyle->hide();
564     mxLbStyle->hide();
565     mxEdFormula->GetWidget()->hide();
566 
567     Deselect();
568 }
569 
570 //color scale
571 
572 namespace {
573 
574 OUString convertNumberToString(double nVal, const ScDocument* pDoc)
575 {
576     SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
577     OUString aText;
578     pNumberFormatter->GetInputLineString(nVal, 0, aText);
579     return aText;
580 }
581 
582 const struct
583 {
584     ScColorScaleEntryType eType;
585     const char* sId;
586 } TypeIdMap[] = {
587     { COLORSCALE_AUTO,       "auto" },
588     { COLORSCALE_MIN,        "min" },
589     { COLORSCALE_MAX,        "max" },
590     { COLORSCALE_PERCENTILE, "percentil" },
591     { COLORSCALE_VALUE,      "value" },
592     { COLORSCALE_PERCENT,    "percent" },
593     { COLORSCALE_FORMULA,    "formula" },
594 };
595 
596 ScColorScaleEntryType getTypeForId(const OUString& sId)
597 {
598     for (auto& r : TypeIdMap)
599     {
600         if (sId.equalsAscii(r.sId))
601             return r.eType;
602     }
603     assert(false); // The id is not in TypeIdMap - something not in sync?
604     return COLORSCALE_AUTO; // invalid id - use default
605 }
606 
607 // Item ids are imported from .ui into OUString* and are referenced by entry data.
608 // See commit 83cefb5ceb4428d61a5b9fae80d1e673131e9bfe
609 
610 ScColorScaleEntryType getSelectedType(const weld::ComboBox& rListBox)
611 {
612     return getTypeForId(rListBox.get_active_id());
613 }
614 
615 sal_Int32 getEntryPos(const weld::ComboBox& rListBox, ScColorScaleEntryType eType)
616 {
617     const sal_Int32 nSize = rListBox.get_count();
618     for (sal_Int32 i = 0; i < nSize; ++i)
619     {
620         if (getTypeForId(rListBox.get_id(i)) == eType)
621             return i;
622     }
623     return -1;
624 }
625 
626 void selectType(weld::ComboBox& rListBox, ScColorScaleEntryType eType)
627 {
628     const sal_Int32 nPos = getEntryPos(rListBox, eType);
629     if (nPos >= 0)
630         rListBox.set_active(nPos);
631 }
632 
633 void removeType(weld::ComboBox& rListBox, ScColorScaleEntryType eType)
634 {
635     const sal_Int32 nPos = getEntryPos(rListBox, eType);
636     if (nPos >= 0)
637         rListBox.remove(nPos);
638 }
639 
640 void SetColorScaleEntryTypes( const ScColorScaleEntry& rEntry, weld::ComboBox& rLbType, weld::Entry& rEdit, ColorListBox& rLbCol, const ScDocument* pDoc )
641 {
642     // entry Automatic is not available for color scales
643     assert(rEntry.GetType() > COLORSCALE_AUTO);
644     selectType(rLbType, rEntry.GetType());
645     switch(rEntry.GetType())
646     {
647         case COLORSCALE_MIN:
648         case COLORSCALE_MAX:
649             break;
650         case COLORSCALE_PERCENTILE:
651         case COLORSCALE_VALUE:
652         case COLORSCALE_PERCENT:
653             {
654                 double nVal = rEntry.GetValue();
655                 rEdit.set_text(convertNumberToString(nVal, pDoc));
656             }
657             break;
658         case COLORSCALE_FORMULA:
659             rEdit.set_text(rEntry.GetFormula(formula::FormulaGrammar::GRAM_DEFAULT));
660             break;
661         case COLORSCALE_AUTO:
662             abort();
663             break;
664     }
665     rLbCol.SelectEntry(rEntry.GetColor());
666 }
667 
668 void SetColorScaleEntry(ScColorScaleEntry* pEntry, const weld::ComboBox& rType, const weld::Entry& rValue,
669                         ScDocument* pDoc, const ScAddress& rPos)
670 {
671     ScColorScaleEntryType eType = getSelectedType(rType);
672 
673     pEntry->SetType(eType);
674     switch (eType)
675     {
676         case COLORSCALE_AUTO:
677         case COLORSCALE_MIN:
678         case COLORSCALE_MAX:
679             break;
680         case COLORSCALE_PERCENTILE:
681         case COLORSCALE_VALUE:
682         case COLORSCALE_PERCENT:
683             {
684                 sal_uInt32 nIndex = 0;
685                 double nVal = 0;
686                 SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
687                 (void)pNumberFormatter->IsNumberFormat(rValue.get_text(), nIndex, nVal);
688                 pEntry->SetValue(nVal);
689             }
690             break;
691         case COLORSCALE_FORMULA:
692             pEntry->SetFormula(rValue.get_text(), pDoc, rPos);
693             break;
694         default:
695             break;
696     }
697 }
698 
699 ScColorScaleEntry* createColorScaleEntry( const weld::ComboBox& rType, const ColorListBox& rColor, const weld::Entry& rValue, ScDocument* pDoc, const ScAddress& rPos )
700 {
701     ScColorScaleEntry* pEntry = new ScColorScaleEntry();
702 
703     SetColorScaleEntry(pEntry, rType, rValue, pDoc, rPos);
704     Color aColor = rColor.GetSelectEntryColor();
705     pEntry->SetColor(aColor);
706     return pEntry;
707 }
708 
709 }
710 
711 ScColorScale2FrmtEntry::ScColorScale2FrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, const ScAddress& rPos, const ScColorScaleFormat* pFormat)
712     : ScCondFrmtEntry(pParent, pDoc, rPos)
713     , mxLbColorFormat(mxBuilder->weld_combo_box("colorformat"))
714     , mxLbEntryTypeMin(mxBuilder->weld_combo_box("colscalemin"))
715     , mxLbEntryTypeMax(mxBuilder->weld_combo_box("colscalemax"))
716     , mxEdMin(mxBuilder->weld_entry("edcolscalemin"))
717     , mxEdMax(mxBuilder->weld_entry("edcolscalemax"))
718     , mxLbColMin(new ColorListBox(mxBuilder->weld_menu_button("lbcolmin"), pParent->GetFrameWeld()))
719     , mxLbColMax(new ColorListBox(mxBuilder->weld_menu_button("lbcolmax"), pParent->GetFrameWeld()))
720     , mxFtMin(mxBuilder->weld_label("Label_minimum"))
721     , mxFtMax(mxBuilder->weld_label("Label_maximum"))
722 {
723     mxFtMin->show();
724     mxFtMax->show();
725 
726     // remove the automatic entry from color scales
727     removeType(*mxLbEntryTypeMin, COLORSCALE_AUTO);
728     removeType(*mxLbEntryTypeMax, COLORSCALE_AUTO);
729     // "min" selector doesn't need "max" entry, and vice versa
730     removeType(*mxLbEntryTypeMin, COLORSCALE_MAX);
731     removeType(*mxLbEntryTypeMax, COLORSCALE_MIN);
732 
733     mxLbType->set_active(0);
734     mxLbColorFormat->set_active(0);
735     Init();
736     if(pFormat)
737     {
738         ScColorScaleEntries::const_iterator itr = pFormat->begin();
739         SetColorScaleEntryTypes(*itr[0], *mxLbEntryTypeMin, *mxEdMin, *mxLbColMin, pDoc);
740         ++itr;
741         SetColorScaleEntryTypes(*itr[0], *mxLbEntryTypeMax, *mxEdMax, *mxLbColMax, pDoc);
742     }
743     else
744     {
745         selectType(*mxLbEntryTypeMin, COLORSCALE_MIN);
746         selectType(*mxLbEntryTypeMax, COLORSCALE_MAX);
747     }
748 
749     mxLbColorFormat->connect_changed( LINK( pParent, ScCondFormatList, ColFormatTypeHdl ) );
750 
751     EntryTypeHdl(*mxLbEntryTypeMin);
752     EntryTypeHdl(*mxLbEntryTypeMax);
753 }
754 
755 ScColorScale2FrmtEntry::~ScColorScale2FrmtEntry()
756 {
757 }
758 
759 void ScColorScale2FrmtEntry::Init()
760 {
761     mxLbEntryTypeMin->connect_changed( LINK( this, ScColorScale2FrmtEntry, EntryTypeHdl ) );
762     mxLbEntryTypeMax->connect_changed( LINK( this, ScColorScale2FrmtEntry, EntryTypeHdl ) );
763     mxLbColMin->SelectEntry(Color(0xFFF685)); // Light Yellow 2
764     mxLbColMax->SelectEntry(Color(0x65C295)); // Light Green 2
765 }
766 
767 ScFormatEntry* ScColorScale2FrmtEntry::createColorscaleEntry() const
768 {
769     ScColorScaleFormat* pColorScale = new ScColorScaleFormat(mpDoc);
770     pColorScale->AddEntry(createColorScaleEntry(*mxLbEntryTypeMin, *mxLbColMin, *mxEdMin, mpDoc, maPos));
771     pColorScale->AddEntry(createColorScaleEntry(*mxLbEntryTypeMax, *mxLbColMax, *mxEdMax, mpDoc, maPos));
772     return pColorScale;
773 }
774 
775 OUString ScColorScale2FrmtEntry::GetExpressionString()
776 {
777     return ScCondFormatHelper::GetExpression( COLORSCALE, 0 );
778 }
779 
780 ScFormatEntry* ScColorScale2FrmtEntry::GetEntry() const
781 {
782     return createColorscaleEntry();
783 }
784 
785 void ScColorScale2FrmtEntry::SetActive()
786 {
787     mxLbColorFormat->show();
788 
789     mxLbEntryTypeMin->show();
790     mxLbEntryTypeMax->show();
791 
792     mxEdMin->show();
793     mxEdMax->show();
794 
795     mxLbColMin->show();
796     mxLbColMax->show();
797 
798     Select();
799 }
800 
801 void ScColorScale2FrmtEntry::SetInactive()
802 {
803     mxLbColorFormat->hide();
804 
805     mxLbEntryTypeMin->hide();
806     mxLbEntryTypeMax->hide();
807 
808     mxEdMin->hide();
809     mxEdMax->hide();
810 
811     mxLbColMin->hide();
812     mxLbColMax->hide();
813 
814     Deselect();
815 }
816 
817 IMPL_LINK( ScColorScale2FrmtEntry, EntryTypeHdl, weld::ComboBox&, rBox, void )
818 {
819     weld::Entry* pEd = nullptr;
820     if (&rBox == mxLbEntryTypeMin.get())
821         pEd = mxEdMin.get();
822     else if (&rBox == mxLbEntryTypeMax.get())
823         pEd = mxEdMax.get();
824 
825     if (!pEd)
826         return;
827 
828     bool bEnableEdit = true;
829     if (getSelectedType(rBox) <= COLORSCALE_MAX)
830     {
831         bEnableEdit = false;
832     }
833 
834     if (bEnableEdit)
835         pEd->set_sensitive(true);
836     else
837         pEd->set_sensitive(false);
838 }
839 
840 ScColorScale3FrmtEntry::ScColorScale3FrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, const ScAddress& rPos, const ScColorScaleFormat* pFormat)
841     : ScCondFrmtEntry(pParent, pDoc, rPos)
842     , mxLbColorFormat(mxBuilder->weld_combo_box("colorformat"))
843     , mxLbEntryTypeMin(mxBuilder->weld_combo_box("colscalemin"))
844     , mxLbEntryTypeMiddle(mxBuilder->weld_combo_box("colscalemiddle"))
845     , mxLbEntryTypeMax(mxBuilder->weld_combo_box("colscalemax"))
846     , mxEdMin(mxBuilder->weld_entry("edcolscalemin"))
847     , mxEdMiddle(mxBuilder->weld_entry("edcolscalemiddle"))
848     , mxEdMax(mxBuilder->weld_entry("edcolscalemax"))
849     , mxLbColMin(new ColorListBox(mxBuilder->weld_menu_button("lbcolmin"), pParent->GetFrameWeld()))
850     , mxLbColMiddle(new ColorListBox(mxBuilder->weld_menu_button("lbcolmiddle"), pParent->GetFrameWeld()))
851     , mxLbColMax(new ColorListBox(mxBuilder->weld_menu_button("lbcolmax"), pParent->GetFrameWeld()))
852     , mxFtMin(mxBuilder->weld_label("Label_minimum"))
853     , mxFtMax(mxBuilder->weld_label("Label_maximum"))
854 {
855     mxFtMin->show();
856     mxFtMax->show();
857 
858     // remove the automatic entry from color scales
859     removeType(*mxLbEntryTypeMin, COLORSCALE_AUTO);
860     removeType(*mxLbEntryTypeMiddle, COLORSCALE_AUTO);
861     removeType(*mxLbEntryTypeMax, COLORSCALE_AUTO);
862     // "min" selector doesn't need "max" entry, and vice versa
863     removeType(*mxLbEntryTypeMin, COLORSCALE_MAX);
864     removeType(*mxLbEntryTypeMax, COLORSCALE_MIN);
865     mxLbColorFormat->set_active(1);
866 
867     Init();
868     mxLbType->set_active(0);
869     if(pFormat)
870     {
871         ScColorScaleEntries::const_iterator itr = pFormat->begin();
872         SetColorScaleEntryTypes(*itr[0], *mxLbEntryTypeMin, *mxEdMin, *mxLbColMin, pDoc);
873         assert(pFormat->size() == 3);
874         ++itr;
875         SetColorScaleEntryTypes(*itr[0], *mxLbEntryTypeMiddle, *mxEdMiddle, *mxLbColMiddle, pDoc);
876         ++itr;
877         SetColorScaleEntryTypes(*itr[0], *mxLbEntryTypeMax, *mxEdMax, *mxLbColMax, pDoc);
878     }
879     else
880     {
881         mxLbColorFormat->set_active(1);
882         selectType(*mxLbEntryTypeMin, COLORSCALE_MIN);
883         selectType(*mxLbEntryTypeMiddle, COLORSCALE_PERCENTILE);
884         selectType(*mxLbEntryTypeMax, COLORSCALE_MAX);
885         mxEdMiddle->set_text(OUString::number(50));
886     }
887 
888     mxLbColorFormat->connect_changed( LINK( pParent, ScCondFormatList, ColFormatTypeHdl ) );
889     EntryTypeHdl(*mxLbEntryTypeMin);
890     EntryTypeHdl(*mxLbEntryTypeMiddle);
891     EntryTypeHdl(*mxLbEntryTypeMax);
892 }
893 
894 ScColorScale3FrmtEntry::~ScColorScale3FrmtEntry()
895 {
896 }
897 
898 void ScColorScale3FrmtEntry::Init()
899 {
900     mxLbEntryTypeMin->connect_changed( LINK( this, ScColorScale3FrmtEntry, EntryTypeHdl ) );
901     mxLbEntryTypeMax->connect_changed( LINK( this, ScColorScale3FrmtEntry, EntryTypeHdl ) );
902     mxLbEntryTypeMiddle->connect_changed( LINK( this, ScColorScale3FrmtEntry, EntryTypeHdl ) );
903     mxLbColMin->SelectEntry(COL_LIGHTRED);
904     mxLbColMiddle->SelectEntry(COL_YELLOW);
905     mxLbColMax->SelectEntry(Color(0x00CC00));
906 }
907 
908 ScFormatEntry* ScColorScale3FrmtEntry::createColorscaleEntry() const
909 {
910     ScColorScaleFormat* pColorScale = new ScColorScaleFormat(mpDoc);
911     pColorScale->AddEntry(createColorScaleEntry(*mxLbEntryTypeMin, *mxLbColMin, *mxEdMin, mpDoc, maPos));
912     if (mxLbColorFormat->get_active() == 1)
913         pColorScale->AddEntry(createColorScaleEntry(*mxLbEntryTypeMiddle, *mxLbColMiddle, *mxEdMiddle, mpDoc, maPos));
914     pColorScale->AddEntry(createColorScaleEntry(*mxLbEntryTypeMax, *mxLbColMax, *mxEdMax, mpDoc, maPos));
915     return pColorScale;
916 }
917 
918 OUString ScColorScale3FrmtEntry::GetExpressionString()
919 {
920     return ScCondFormatHelper::GetExpression( COLORSCALE, 0 );
921 }
922 
923 ScFormatEntry* ScColorScale3FrmtEntry::GetEntry() const
924 {
925     return createColorscaleEntry();
926 }
927 
928 void ScColorScale3FrmtEntry::SetActive()
929 {
930     mxLbColorFormat->show();
931     mxLbEntryTypeMin->show();
932     mxLbEntryTypeMiddle->show();
933     mxLbEntryTypeMax->show();
934 
935     mxEdMin->show();
936     mxEdMiddle->show();
937     mxEdMax->show();
938 
939     mxLbColMin->show();
940     mxLbColMiddle->show();
941     mxLbColMax->show();
942 
943     Select();
944 }
945 
946 void ScColorScale3FrmtEntry::SetInactive()
947 {
948     mxLbColorFormat->hide();
949 
950     mxLbEntryTypeMin->hide();
951     mxLbEntryTypeMiddle->hide();
952     mxLbEntryTypeMax->hide();
953 
954     mxEdMin->hide();
955     mxEdMiddle->hide();
956     mxEdMax->hide();
957 
958     mxLbColMin->hide();
959     mxLbColMiddle->hide();
960     mxLbColMax->hide();
961 
962     Deselect();
963 }
964 
965 IMPL_LINK( ScColorScale3FrmtEntry, EntryTypeHdl, weld::ComboBox&, rBox, void )
966 {
967     weld::Entry* pEd = nullptr;
968     if(&rBox == mxLbEntryTypeMin.get())
969         pEd = mxEdMin.get();
970     else if(&rBox == mxLbEntryTypeMiddle.get())
971         pEd = mxEdMiddle.get();
972     else if(&rBox == mxLbEntryTypeMax.get())
973         pEd = mxEdMax.get();
974 
975     if (!pEd)
976         return;
977 
978     bool bEnableEdit = true;
979     if (getSelectedType(rBox) <= COLORSCALE_MAX)
980     {
981         bEnableEdit = false;
982     }
983 
984     if(bEnableEdit)
985         pEd->set_sensitive(true);
986     else
987         pEd->set_sensitive(false);
988 }
989 
990 IMPL_LINK_NOARG(ScConditionFrmtEntry, ConditionTypeSelectHdl, weld::ComboBox&, void)
991 {
992     sal_Int32 nSelectPos = mxLbCondType->get_active();
993     ScConditionMode eMode = EntryPosToConditionMode(nSelectPos);
994     switch(GetNumberEditFields(eMode))
995     {
996         case 0:
997             mxEdVal1->GetWidget()->hide();
998             mxEdVal2->GetWidget()->hide();
999             mxFtVal->hide();
1000             break;
1001         case 1:
1002             mxEdVal1->GetWidget()->show();
1003             mxEdVal2->GetWidget()->hide();
1004             mxFtVal->show();
1005             break;
1006         case 2:
1007             mxEdVal1->GetWidget()->show();
1008             mxEdVal2->GetWidget()->show();
1009             mxFtVal->show();
1010             break;
1011     }
1012 }
1013 
1014 //databar
1015 
1016 namespace {
1017 
1018 void SetDataBarEntryTypes( const ScColorScaleEntry& rEntry, weld::ComboBox& rLbType, weld::Entry& rEdit, const ScDocument* pDoc )
1019 {
1020     selectType(rLbType, rEntry.GetType());
1021     switch(rEntry.GetType())
1022     {
1023         case COLORSCALE_AUTO:
1024         case COLORSCALE_MIN:
1025         case COLORSCALE_MAX:
1026             break;
1027         case COLORSCALE_VALUE:
1028         case COLORSCALE_PERCENT:
1029         case COLORSCALE_PERCENTILE:
1030             {
1031                 double nVal = rEntry.GetValue();
1032                 SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
1033                 OUString aText;
1034                 pNumberFormatter->GetInputLineString(nVal, 0, aText);
1035                 rEdit.set_text(aText);
1036             }
1037             break;
1038         case COLORSCALE_FORMULA:
1039             rEdit.set_text(rEntry.GetFormula(formula::FormulaGrammar::GRAM_DEFAULT));
1040             break;
1041     }
1042 }
1043 
1044 }
1045 
1046 ScDataBarFrmtEntry::ScDataBarFrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, const ScAddress& rPos, const ScDataBarFormat* pFormat)
1047     : ScCondFrmtEntry(pParent, pDoc, rPos)
1048     , mxLbColorFormat(mxBuilder->weld_combo_box("colorformat"))
1049     , mxLbDataBarMinType(mxBuilder->weld_combo_box("colscalemin"))
1050     , mxLbDataBarMaxType(mxBuilder->weld_combo_box("colscalemax"))
1051     , mxEdDataBarMin(mxBuilder->weld_entry("edcolscalemin"))
1052     , mxEdDataBarMax(mxBuilder->weld_entry("edcolscalemax"))
1053     , mxBtOptions(mxBuilder->weld_button("options"))
1054     , mxFtMin(mxBuilder->weld_label("Label_minimum"))
1055     , mxFtMax(mxBuilder->weld_label("Label_maximum"))
1056 {
1057     // "min" selector doesn't need "max" entry, and vice versa
1058     removeType(*mxLbDataBarMinType, COLORSCALE_MAX);
1059     removeType(*mxLbDataBarMaxType, COLORSCALE_MIN);
1060 
1061     mxFtMin->show();
1062     mxFtMax->show();
1063 
1064     mxLbColorFormat->set_active(2);
1065     mxLbType->set_active(0);
1066     if(pFormat)
1067     {
1068         mpDataBarData.reset(new ScDataBarFormatData(*pFormat->GetDataBarData()));
1069         SetDataBarEntryTypes(*mpDataBarData->mpLowerLimit, *mxLbDataBarMinType, *mxEdDataBarMin, pDoc);
1070         SetDataBarEntryTypes(*mpDataBarData->mpUpperLimit, *mxLbDataBarMaxType, *mxEdDataBarMax, pDoc);
1071         DataBarTypeSelectHdl(*mxLbDataBarMinType);
1072     }
1073     else
1074     {
1075         selectType(*mxLbDataBarMinType, COLORSCALE_AUTO);
1076         selectType(*mxLbDataBarMaxType, COLORSCALE_AUTO);
1077         DataBarTypeSelectHdl(*mxLbDataBarMinType);
1078     }
1079     Init();
1080 
1081     mxLbColorFormat->connect_changed( LINK( pParent, ScCondFormatList, ColFormatTypeHdl ) );
1082 }
1083 
1084 ScDataBarFrmtEntry::~ScDataBarFrmtEntry()
1085 {
1086 }
1087 
1088 ScFormatEntry* ScDataBarFrmtEntry::GetEntry() const
1089 {
1090     return createDatabarEntry();
1091 }
1092 
1093 void ScDataBarFrmtEntry::Init()
1094 {
1095     mxLbDataBarMinType->connect_changed( LINK( this, ScDataBarFrmtEntry, DataBarTypeSelectHdl ) );
1096     mxLbDataBarMaxType->connect_changed( LINK( this, ScDataBarFrmtEntry, DataBarTypeSelectHdl ) );
1097 
1098     mxBtOptions->connect_clicked( LINK( this, ScDataBarFrmtEntry, OptionBtnHdl ) );
1099 
1100     if(!mpDataBarData)
1101     {
1102         mpDataBarData.reset(new ScDataBarFormatData());
1103         mpDataBarData->mpUpperLimit.reset(new ScColorScaleEntry());
1104         mpDataBarData->mpLowerLimit.reset(new ScColorScaleEntry());
1105         mpDataBarData->mpLowerLimit->SetType(COLORSCALE_AUTO);
1106         mpDataBarData->mpUpperLimit->SetType(COLORSCALE_AUTO);
1107         mpDataBarData->maPositiveColor = COL_LIGHTBLUE;
1108     }
1109 }
1110 
1111 ScFormatEntry* ScDataBarFrmtEntry::createDatabarEntry() const
1112 {
1113     SetColorScaleEntry(mpDataBarData->mpLowerLimit.get(), *mxLbDataBarMinType,
1114                        *mxEdDataBarMin, mpDoc, maPos);
1115     SetColorScaleEntry(mpDataBarData->mpUpperLimit.get(), *mxLbDataBarMaxType,
1116                        *mxEdDataBarMax, mpDoc, maPos);
1117     ScDataBarFormat* pDataBar = new ScDataBarFormat(mpDoc);
1118     pDataBar->SetDataBarData(new ScDataBarFormatData(*mpDataBarData));
1119     return pDataBar;
1120 }
1121 
1122 OUString ScDataBarFrmtEntry::GetExpressionString()
1123 {
1124     return ScCondFormatHelper::GetExpression( DATABAR, 0 );
1125 }
1126 
1127 void ScDataBarFrmtEntry::SetActive()
1128 {
1129     mxLbColorFormat->show();
1130 
1131     mxLbDataBarMinType->show();
1132     mxLbDataBarMaxType->show();
1133     mxEdDataBarMin->show();
1134     mxEdDataBarMax->show();
1135     mxBtOptions->show();
1136 
1137     Select();
1138 }
1139 
1140 void ScDataBarFrmtEntry::SetInactive()
1141 {
1142     mxLbColorFormat->hide();
1143 
1144     mxLbDataBarMinType->hide();
1145     mxLbDataBarMaxType->hide();
1146     mxEdDataBarMin->hide();
1147     mxEdDataBarMax->hide();
1148     mxBtOptions->hide();
1149 
1150     Deselect();
1151 }
1152 
1153 IMPL_LINK_NOARG( ScDataBarFrmtEntry, DataBarTypeSelectHdl, weld::ComboBox&, void )
1154 {
1155     if (getSelectedType(*mxLbDataBarMinType) <= COLORSCALE_MAX)
1156         mxEdDataBarMin->set_sensitive(false);
1157     else
1158         mxEdDataBarMin->set_sensitive(true);
1159 
1160     if (getSelectedType(*mxLbDataBarMaxType) <= COLORSCALE_MAX)
1161         mxEdDataBarMax->set_sensitive(false);
1162     else
1163         mxEdDataBarMax->set_sensitive(true);
1164 }
1165 
1166 IMPL_LINK_NOARG( ScDataBarFrmtEntry, OptionBtnHdl, weld::Button&, void )
1167 {
1168     SetColorScaleEntry(mpDataBarData->mpLowerLimit.get(), *mxLbDataBarMinType,
1169                        *mxEdDataBarMin, mpDoc, maPos);
1170     SetColorScaleEntry(mpDataBarData->mpUpperLimit.get(), *mxLbDataBarMaxType,
1171                        *mxEdDataBarMax, mpDoc, maPos);
1172     ScDataBarSettingsDlg aDlg(mpParent->GetFrameWeld(), *mpDataBarData, mpDoc, maPos);
1173     if (aDlg.run() == RET_OK)
1174     {
1175         mpDataBarData.reset(aDlg.GetData());
1176         SetDataBarEntryTypes(*mpDataBarData->mpLowerLimit, *mxLbDataBarMinType, *mxEdDataBarMin, mpDoc);
1177         SetDataBarEntryTypes(*mpDataBarData->mpUpperLimit, *mxLbDataBarMaxType, *mxEdDataBarMax, mpDoc);
1178         DataBarTypeSelectHdl(*mxLbDataBarMinType);
1179     }
1180 }
1181 
1182 ScDateFrmtEntry::ScDateFrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, const ScCondDateFormatEntry* pFormat)
1183     : ScCondFrmtEntry(pParent, pDoc, ScAddress())
1184     , mxLbDateEntry(mxBuilder->weld_combo_box("datetype"))
1185     , mxFtStyle(mxBuilder->weld_label("styleft"))
1186     , mxLbStyle(mxBuilder->weld_combo_box("style"))
1187     , mxWdPreviewWin(mxBuilder->weld_widget("previewwin"))
1188     , mxWdPreview(new weld::CustomWeld(*mxBuilder, "preview", maWdPreview))
1189     , mbIsInStyleCreate(false)
1190 {
1191     mxWdPreview->set_size_request(mxLbStyle->get_preferred_size().Height(), -1);
1192 
1193     Init();
1194 
1195     StartListening(*pDoc->GetStyleSheetPool(), DuplicateHandling::Prevent);
1196 
1197     if(pFormat)
1198     {
1199         sal_Int32 nPos = static_cast<sal_Int32>(pFormat->GetDateType());
1200         mxLbDateEntry->set_active(nPos);
1201 
1202         mxLbStyle->set_active_text(pFormat->GetStyleName());
1203     }
1204 
1205     StyleSelectHdl(*mxLbStyle);
1206 }
1207 
1208 ScDateFrmtEntry::~ScDateFrmtEntry()
1209 {
1210 }
1211 
1212 void ScDateFrmtEntry::Init()
1213 {
1214     mxLbDateEntry->set_active(0);
1215     mxLbType->set_active(3);
1216 
1217     FillStyleListBox( mpDoc, *mxLbStyle );
1218     mxLbStyle->connect_changed( LINK( this, ScDateFrmtEntry, StyleSelectHdl ) );
1219     mxLbStyle->set_active(1);
1220 }
1221 
1222 void ScDateFrmtEntry::SetActive()
1223 {
1224     mxLbDateEntry->show();
1225     mxFtStyle->show();
1226     mxWdPreviewWin->show();
1227     mxLbStyle->show();
1228 
1229     Select();
1230 }
1231 
1232 void ScDateFrmtEntry::SetInactive()
1233 {
1234     mxLbDateEntry->hide();
1235     mxFtStyle->hide();
1236     mxWdPreviewWin->hide();
1237     mxLbStyle->hide();
1238 
1239     Deselect();
1240 }
1241 
1242 void ScDateFrmtEntry::Notify( SfxBroadcaster&, const SfxHint& rHint )
1243 {
1244     if(rHint.GetId() == SfxHintId::StyleSheetModified)
1245     {
1246         if(!mbIsInStyleCreate)
1247             UpdateStyleList(*mxLbStyle, mpDoc);
1248     }
1249 }
1250 
1251 ScFormatEntry* ScDateFrmtEntry::GetEntry() const
1252 {
1253     ScCondDateFormatEntry* pNewEntry = new ScCondDateFormatEntry(mpDoc);
1254     condformat::ScCondFormatDateType eType = static_cast<condformat::ScCondFormatDateType>(mxLbDateEntry->get_active());
1255     pNewEntry->SetDateType(eType);
1256     pNewEntry->SetStyleName(mxLbStyle->get_active_text());
1257     return pNewEntry;
1258 }
1259 
1260 OUString ScDateFrmtEntry::GetExpressionString()
1261 {
1262     return ScCondFormatHelper::GetExpression(DATE, 0);
1263 }
1264 
1265 IMPL_LINK_NOARG( ScDateFrmtEntry, StyleSelectHdl, weld::ComboBox&, void )
1266 {
1267     mbIsInStyleCreate = true;
1268     StyleSelect(mpParent->GetFrameWeld(), *mxLbStyle, mpDoc, maWdPreview);
1269     mbIsInStyleCreate = false;
1270 }
1271 
1272 class ScIconSetFrmtDataEntry
1273 {
1274 protected:
1275     std::unique_ptr<weld::Builder> mxBuilder;
1276 private:
1277     std::unique_ptr<weld::Container> mxGrid;
1278     std::unique_ptr<weld::Image> mxImgIcon;
1279     std::unique_ptr<weld::Label> mxFtEntry;
1280     std::unique_ptr<weld::Entry> mxEdEntry;
1281     std::unique_ptr<weld::ComboBox> mxLbEntryType;
1282 
1283 public:
1284     ScIconSetFrmtDataEntry(weld::Container* pParent, ScIconSetType eType, ScDocument* pDoc,
1285             sal_Int32 i, const ScColorScaleEntry* pEntry = nullptr);
1286     void Show() { mxGrid->show(); }
1287     void Hide() { mxGrid->hide(); }
1288     void set_grid_top_attach(int nTop)
1289     {
1290         mxGrid->set_grid_left_attach(0);
1291         mxGrid->set_grid_top_attach(nTop);
1292     }
1293 
1294     ScColorScaleEntry* CreateEntry(ScDocument* pDoc, const ScAddress& rPos) const;
1295 
1296     void SetFirstEntry();
1297 };
1298 
1299 ScIconSetFrmtDataEntry::ScIconSetFrmtDataEntry(weld::Container* pParent, ScIconSetType eType, ScDocument* pDoc, sal_Int32 i, const ScColorScaleEntry* pEntry)
1300     : mxBuilder(Application::CreateBuilder(pParent, "modules/scalc/ui/conditionaliconset.ui"))
1301     , mxGrid(mxBuilder->weld_container("ConditionalIconSet"))
1302     , mxImgIcon(mxBuilder->weld_image("icon"))
1303     , mxFtEntry(mxBuilder->weld_label("label"))
1304     , mxEdEntry(mxBuilder->weld_entry("entry"))
1305     , mxLbEntryType(mxBuilder->weld_combo_box("listbox"))
1306 {
1307     mxImgIcon->set_from_icon_name(ScIconSetFormat::getIconName(eType, i));
1308     if(pEntry)
1309     {
1310         switch(pEntry->GetType())
1311         {
1312             case COLORSCALE_VALUE:
1313                 mxLbEntryType->set_active(0);
1314                 mxEdEntry->set_text(convertNumberToString(pEntry->GetValue(), pDoc));
1315                 break;
1316             case COLORSCALE_PERCENTILE:
1317                 mxLbEntryType->set_active(2);
1318                 mxEdEntry->set_text(convertNumberToString(pEntry->GetValue(), pDoc));
1319                 break;
1320             case COLORSCALE_PERCENT:
1321                 mxLbEntryType->set_active(1);
1322                 mxEdEntry->set_text(convertNumberToString(pEntry->GetValue(), pDoc));
1323                 break;
1324             case COLORSCALE_FORMULA:
1325                 mxLbEntryType->set_active(3);
1326                 mxEdEntry->set_text(pEntry->GetFormula(formula::FormulaGrammar::GRAM_DEFAULT));
1327                 break;
1328             default:
1329                 assert(false);
1330         }
1331     }
1332     else
1333     {
1334         mxLbEntryType->set_active(1);
1335     }
1336 }
1337 
1338 ScColorScaleEntry* ScIconSetFrmtDataEntry::CreateEntry(ScDocument* pDoc, const ScAddress& rPos) const
1339 {
1340     sal_Int32 nPos = mxLbEntryType->get_active();
1341     OUString aText = mxEdEntry->get_text();
1342     ScColorScaleEntry* pEntry = new ScColorScaleEntry();
1343 
1344     sal_uInt32 nIndex = 0;
1345     double nVal = 0;
1346     SvNumberFormatter* pNumberFormatter = pDoc->GetFormatTable();
1347     (void)pNumberFormatter->IsNumberFormat(aText, nIndex, nVal);
1348     pEntry->SetValue(nVal);
1349 
1350     switch(nPos)
1351     {
1352         case 0:
1353             pEntry->SetType(COLORSCALE_VALUE);
1354             break;
1355         case 1:
1356             pEntry->SetType(COLORSCALE_PERCENT);
1357             break;
1358         case 2:
1359             pEntry->SetType(COLORSCALE_PERCENTILE);
1360             break;
1361         case 3:
1362             pEntry->SetType(COLORSCALE_FORMULA);
1363             pEntry->SetFormula(aText, pDoc, rPos, pDoc->GetGrammar());
1364             break;
1365         default:
1366             assert(false);
1367     }
1368 
1369     return pEntry;
1370 }
1371 
1372 void ScIconSetFrmtDataEntry::SetFirstEntry()
1373 {
1374     mxEdEntry->hide();
1375     mxLbEntryType->hide();
1376     mxFtEntry->hide();
1377     mxEdEntry->set_text("0");
1378     mxLbEntryType->set_active(1);
1379 }
1380 
1381 ScIconSetFrmtEntry::ScIconSetFrmtEntry(ScCondFormatList* pParent, ScDocument* pDoc, const ScAddress& rPos, const ScIconSetFormat* pFormat)
1382     : ScCondFrmtEntry(pParent, pDoc, rPos)
1383     , mxLbColorFormat(mxBuilder->weld_combo_box("colorformat"))
1384     , mxLbIconSetType(mxBuilder->weld_combo_box("iconsettype"))
1385     , mxIconParent(mxBuilder->weld_container("iconparent"))
1386 {
1387     Init();
1388     mxLbColorFormat->connect_changed(LINK(pParent, ScCondFormatList, ColFormatTypeHdl));
1389 
1390     if(pFormat)
1391     {
1392         const ScIconSetFormatData* pIconSetFormatData = pFormat->GetIconSetData();
1393         ScIconSetType eType = pIconSetFormatData->eIconSetType;
1394         sal_Int32 nType = static_cast<sal_Int32>(eType);
1395         mxLbIconSetType->set_active(nType);
1396 
1397         for (size_t i = 0, n = pIconSetFormatData->m_Entries.size();
1398                 i < n; ++i)
1399         {
1400             maEntries.emplace_back(new ScIconSetFrmtDataEntry(
1401                 mxIconParent.get(), eType, pDoc, i, pIconSetFormatData->m_Entries[i].get()));
1402             maEntries[i]->set_grid_top_attach(i);
1403         }
1404         maEntries[0]->SetFirstEntry();
1405     }
1406     else
1407         IconSetTypeHdl(*mxLbIconSetType);
1408 }
1409 
1410 ScIconSetFrmtEntry::~ScIconSetFrmtEntry()
1411 {
1412 }
1413 
1414 void ScIconSetFrmtEntry::Init()
1415 {
1416     mxLbColorFormat->set_active(3);
1417     mxLbType->set_active(0);
1418     mxLbIconSetType->set_active(0);
1419 
1420     mxLbIconSetType->connect_changed(LINK(this, ScIconSetFrmtEntry, IconSetTypeHdl));
1421 }
1422 
1423 IMPL_LINK_NOARG( ScIconSetFrmtEntry, IconSetTypeHdl, weld::ComboBox&, void )
1424 {
1425     const ScIconSetMap* pMap = ScIconSetFormat::g_IconSetMap;
1426 
1427     sal_Int32 nPos = mxLbIconSetType->get_active();
1428     sal_uInt32 nElements = pMap[nPos].nElements;
1429 
1430     maEntries.clear();
1431 
1432     for(size_t i = 0; i < nElements; ++i)
1433     {
1434         maEntries.emplace_back(new ScIconSetFrmtDataEntry(mxIconParent.get(), static_cast<ScIconSetType>(nPos), mpDoc, i));
1435         maEntries[i]->set_grid_top_attach(i);
1436         maEntries[i]->Show();
1437     }
1438     maEntries[0]->SetFirstEntry();
1439 }
1440 
1441 OUString ScIconSetFrmtEntry::GetExpressionString()
1442 {
1443     return ScCondFormatHelper::GetExpression(ICONSET, 0);
1444 }
1445 
1446 void ScIconSetFrmtEntry::SetActive()
1447 {
1448     mxLbColorFormat->show();
1449     mxLbIconSetType->show();
1450     for(auto& rxEntry : maEntries)
1451     {
1452         rxEntry->Show();
1453     }
1454 
1455     Select();
1456 }
1457 
1458 void ScIconSetFrmtEntry::SetInactive()
1459 {
1460     mxLbColorFormat->hide();
1461     mxLbIconSetType->hide();
1462     for(auto& rxEntry : maEntries)
1463     {
1464         rxEntry->Hide();
1465     }
1466 
1467     Deselect();
1468 }
1469 
1470 ScFormatEntry* ScIconSetFrmtEntry::GetEntry() const
1471 {
1472     ScIconSetFormat* pFormat = new ScIconSetFormat(mpDoc);
1473 
1474     ScIconSetFormatData* pData = new ScIconSetFormatData;
1475     pData->eIconSetType = static_cast<ScIconSetType>(mxLbIconSetType->get_active());
1476     for(const auto& rxEntry : maEntries)
1477     {
1478         pData->m_Entries.push_back(std::unique_ptr<ScColorScaleEntry>(rxEntry->CreateEntry(mpDoc, maPos)));
1479     }
1480     pFormat->SetIconSetData(pData);
1481 
1482     return pFormat;
1483 }
1484 
1485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1486