tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / dialogs / SparklineDialog.cxx
blobad092b6659e230af0ed0524d591a791e7954c04a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <SparklineDialog.hxx>
11 #include <SparklineData.hxx>
12 #include <SparklineGroup.hxx>
13 #include <Sparkline.hxx>
14 #include <reffact.hxx>
16 #include <docfunc.hxx>
18 #include <svx/colorbox.hxx>
19 #include <vcl/formatter.hxx>
21 namespace sc
23 SparklineDialog::SparklineDialog(SfxBindings* pBindings, SfxChildWindow* pChildWindow,
24 weld::Window* pWindow, ScViewData& rViewData)
25 : ScAnyRefDlgController(pBindings, pChildWindow, pWindow,
26 u"modules/scalc/ui/sparklinedialog.ui"_ustr, u"SparklineDialog"_ustr)
27 , mrViewData(rViewData)
28 , mrDocument(rViewData.GetDocument())
29 , mpActiveEdit(nullptr)
30 , mbDialogLostFocus(false)
31 , mxButtonOk(m_xBuilder->weld_button(u"ok"_ustr))
32 , mxButtonCancel(m_xBuilder->weld_button(u"cancel"_ustr))
33 , mxFrameData(m_xBuilder->weld_frame(u"frmData"_ustr))
34 , mxInputRangeLabel(m_xBuilder->weld_label(u"lbInputRange"_ustr))
35 , mxInputRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"edInputRange"_ustr)))
36 , mxInputRangeButton(new formula::RefButton(m_xBuilder->weld_button(u"btnInputRange"_ustr)))
37 , mxOutputRangeLabel(m_xBuilder->weld_label(u"lbOutputRange"_ustr))
38 , mxOutputRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"edOutputRange"_ustr)))
39 , mxOutputRangeButton(new formula::RefButton(m_xBuilder->weld_button(u"btnOutputRange"_ustr)))
40 , mxColorSeries(new ColorListBox(m_xBuilder->weld_menu_button(u"colSeries"_ustr),
41 [pWindow] { return pWindow; }))
42 , mxColorNegative(new ColorListBox(m_xBuilder->weld_menu_button(u"colNegative"_ustr),
43 [pWindow] { return pWindow; }))
44 , mxColorMarker(new ColorListBox(m_xBuilder->weld_menu_button(u"colMarker"_ustr),
45 [pWindow] { return pWindow; }))
46 , mxColorHigh(new ColorListBox(m_xBuilder->weld_menu_button(u"colHigh"_ustr),
47 [pWindow] { return pWindow; }))
48 , mxColorLow(new ColorListBox(m_xBuilder->weld_menu_button(u"colLow"_ustr),
49 [pWindow] { return pWindow; }))
50 , mxColorFirst(new ColorListBox(m_xBuilder->weld_menu_button(u"colFirst"_ustr),
51 [pWindow] { return pWindow; }))
52 , mxColorLast(new ColorListBox(m_xBuilder->weld_menu_button(u"colLast"_ustr),
53 [pWindow] { return pWindow; }))
54 , mxCheckButtonNegative(m_xBuilder->weld_check_button(u"cbNegative"_ustr))
55 , mxCheckButtonMarker(m_xBuilder->weld_check_button(u"cbMarker"_ustr))
56 , mxCheckButtonHigh(m_xBuilder->weld_check_button(u"cbHigh"_ustr))
57 , mxCheckButtonLow(m_xBuilder->weld_check_button(u"cbLow"_ustr))
58 , mxCheckButtonFirst(m_xBuilder->weld_check_button(u"cbFirst"_ustr))
59 , mxCheckButtonLast(m_xBuilder->weld_check_button(u"cbLast"_ustr))
60 , mxSpinLineWidth(m_xBuilder->weld_spin_button(u"seLineWidth"_ustr))
61 , mxType(m_xBuilder->weld_combo_box(u"cbType"_ustr))
62 , mxCheckDisplayXAxis(m_xBuilder->weld_check_button(u"cbDisplayXAxis"_ustr))
63 , mxCheckDisplayHidden(m_xBuilder->weld_check_button(u"cbHidden"_ustr))
64 , mxCheckRightToLeft(m_xBuilder->weld_check_button(u"cbRTL"_ustr))
65 , mxDisplayEmptyGap(m_xBuilder->weld_combo_box(u"cbEmptyCells"_ustr))
66 , mxComboMinAxisType(m_xBuilder->weld_combo_box(u"cbMinAxisType"_ustr))
67 , mxComboMaxAxisType(m_xBuilder->weld_combo_box(u"cbMaxAxisType"_ustr))
68 , mxSpinCustomMin(m_xBuilder->weld_formatted_spin_button(u"seMinAxis"_ustr))
69 , mxSpinCustomMax(m_xBuilder->weld_formatted_spin_button(u"seMaxAxis"_ustr))
70 , mbEditMode(false)
72 mxInputRangeEdit->SetReferences(this, mxInputRangeLabel.get());
73 mxInputRangeButton->SetReferences(this, mxInputRangeEdit.get());
75 mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
76 mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
78 mxButtonCancel->connect_clicked(LINK(this, SparklineDialog, ButtonClicked));
79 mxButtonOk->connect_clicked(LINK(this, SparklineDialog, ButtonClicked));
80 mxButtonOk->set_sensitive(false);
82 Link<formula::RefEdit&, void> aEditLink = LINK(this, SparklineDialog, EditFocusHandler);
83 mxInputRangeEdit->SetGetFocusHdl(aEditLink);
84 mxOutputRangeEdit->SetGetFocusHdl(aEditLink);
85 aEditLink = LINK(this, SparklineDialog, LoseEditFocusHandler);
86 mxInputRangeEdit->SetLoseFocusHdl(aEditLink);
87 mxOutputRangeEdit->SetLoseFocusHdl(aEditLink);
89 Link<formula::RefButton&, void> aButtonLink = LINK(this, SparklineDialog, ButtonFocusHandler);
90 mxInputRangeButton->SetGetFocusHdl(aButtonLink);
91 mxOutputRangeButton->SetGetFocusHdl(aButtonLink);
92 aButtonLink = LINK(this, SparklineDialog, LoseButtonFocusHandler);
93 mxInputRangeButton->SetLoseFocusHdl(aButtonLink);
94 mxOutputRangeButton->SetLoseFocusHdl(aButtonLink);
96 Link<formula::RefEdit&, void> aModifyLink = LINK(this, SparklineDialog, RefInputModifyHandler);
97 mxInputRangeEdit->SetModifyHdl(aModifyLink);
98 mxOutputRangeEdit->SetModifyHdl(aModifyLink);
100 mxType->connect_changed(LINK(this, SparklineDialog, SelectSparklineType));
101 mxDisplayEmptyGap->connect_changed(LINK(this, SparklineDialog, SelectSparklineType));
103 Link<weld::Toggleable&, void> aLink = LINK(this, SparklineDialog, ToggleHandler);
104 mxCheckButtonNegative->connect_toggled(aLink);
105 mxCheckButtonMarker->connect_toggled(aLink);
106 mxCheckButtonHigh->connect_toggled(aLink);
107 mxCheckButtonLow->connect_toggled(aLink);
108 mxCheckButtonFirst->connect_toggled(aLink);
109 mxCheckButtonLast->connect_toggled(aLink);
110 mxCheckDisplayXAxis->connect_toggled(aLink);
111 mxCheckDisplayHidden->connect_toggled(aLink);
112 mxCheckRightToLeft->connect_toggled(aLink);
114 mxSpinLineWidth->connect_value_changed(LINK(this, SparklineDialog, SpinLineWidthChanged));
116 mxComboMinAxisType->connect_changed(LINK(this, SparklineDialog, ComboValueChanged));
117 mxComboMaxAxisType->connect_changed(LINK(this, SparklineDialog, ComboValueChanged));
119 mxSpinCustomMin->connect_value_changed(LINK(this, SparklineDialog, SpinCustomChanged));
120 Formatter& rSpinCustomMinFormatter = mxSpinCustomMin->GetFormatter();
121 rSpinCustomMinFormatter.ClearMinValue();
122 rSpinCustomMinFormatter.ClearMaxValue();
123 rSpinCustomMinFormatter.UseInputStringForFormatting();
125 mxSpinCustomMax->connect_value_changed(LINK(this, SparklineDialog, SpinCustomChanged));
126 Formatter& rSpinCustomMaxFormatter = mxSpinCustomMax->GetFormatter();
127 rSpinCustomMaxFormatter.ClearMinValue();
128 rSpinCustomMaxFormatter.ClearMaxValue();
129 rSpinCustomMaxFormatter.UseInputStringForFormatting();
131 setupValues();
133 mxOutputRangeEdit->GrabFocus();
134 mxButtonOk->set_sensitive(checkValidInputOutput());
137 SparklineDialog::~SparklineDialog() = default;
139 void SparklineDialog::setInputSelection()
141 mrViewData.GetSimpleArea(maInputRange);
142 OUString aString = maInputRange.Format(mrDocument, ScRefFlags::VALID | ScRefFlags::TAB_3D,
143 mrDocument.GetAddressConvention());
144 mxInputRangeEdit->SetRefString(aString);
147 void SparklineDialog::setupValues()
149 ScRange aSelectionRange;
150 mrViewData.GetSimpleArea(aSelectionRange);
152 if (mrDocument.HasOneSparklineGroup(aSelectionRange))
154 if (auto pSparkline = mrDocument.GetSparkline(aSelectionRange.aStart))
156 mpSparklineGroup = pSparkline->getSparklineGroup();
157 maAttributes = mpSparklineGroup->getAttributes();
158 mxFrameData->set_visible(false);
159 mbEditMode = true;
162 else
164 maInputRange = aSelectionRange;
167 setInputSelection();
169 switch (maAttributes.getType())
171 case sc::SparklineType::Line:
172 mxType->set_active(0);
173 break;
174 case sc::SparklineType::Column:
175 mxType->set_active(1);
176 break;
177 case sc::SparklineType::Stacked:
178 mxType->set_active(2);
179 break;
182 switch (maAttributes.getDisplayEmptyCellsAs())
184 case sc::DisplayEmptyCellsAs::Gap:
185 mxDisplayEmptyGap->set_active(0);
186 break;
187 case sc::DisplayEmptyCellsAs::Zero:
188 mxDisplayEmptyGap->set_active(1);
189 break;
190 case sc::DisplayEmptyCellsAs::Span:
191 mxDisplayEmptyGap->set_active(2);
192 break;
195 mxColorSeries->SelectEntry(maAttributes.getColorSeries().getFinalColor());
196 mxColorNegative->SelectEntry(maAttributes.getColorNegative().getFinalColor());
197 mxColorMarker->SelectEntry(maAttributes.getColorMarkers().getFinalColor());
198 mxColorHigh->SelectEntry(maAttributes.getColorHigh().getFinalColor());
199 mxColorLow->SelectEntry(maAttributes.getColorLow().getFinalColor());
200 mxColorFirst->SelectEntry(maAttributes.getColorFirst().getFinalColor());
201 mxColorLast->SelectEntry(maAttributes.getColorLast().getFinalColor());
203 mxCheckButtonNegative->set_active(maAttributes.isNegative());
204 mxCheckButtonMarker->set_active(maAttributes.isMarkers());
205 mxCheckButtonHigh->set_active(maAttributes.isHigh());
206 mxCheckButtonLow->set_active(maAttributes.isLow());
207 mxCheckButtonFirst->set_active(maAttributes.isFirst());
208 mxCheckButtonLast->set_active(maAttributes.isLast());
210 mxSpinLineWidth->set_value(sal_Int64(maAttributes.getLineWeight() * 100.0));
212 mxCheckDisplayXAxis->set_active(maAttributes.shouldDisplayXAxis());
213 mxCheckDisplayHidden->set_active(maAttributes.shouldDisplayHidden());
214 mxCheckRightToLeft->set_active(maAttributes.isRightToLeft());
216 switch (maAttributes.getMinAxisType())
218 case sc::AxisType::Individual:
219 mxComboMinAxisType->set_active(0);
220 mxSpinCustomMin->GetFormatter().SetValue(0.0);
221 break;
222 case sc::AxisType::Group:
223 mxComboMinAxisType->set_active(1);
224 mxSpinCustomMin->GetFormatter().SetValue(0.0);
225 break;
226 case sc::AxisType::Custom:
227 mxComboMinAxisType->set_active(2);
228 if (maAttributes.getManualMin())
229 mxSpinCustomMin->GetFormatter().SetValue(*maAttributes.getManualMin());
230 break;
232 ComboValueChanged(*mxComboMinAxisType);
234 switch (maAttributes.getMaxAxisType())
236 case sc::AxisType::Individual:
237 mxComboMaxAxisType->set_active(0);
238 mxSpinCustomMax->GetFormatter().SetValue(0.0);
239 break;
240 case sc::AxisType::Group:
241 mxComboMaxAxisType->set_active(1);
242 mxSpinCustomMax->GetFormatter().SetValue(0.0);
243 break;
244 case sc::AxisType::Custom:
245 mxComboMaxAxisType->set_active(2);
246 if (maAttributes.getManualMax())
247 mxSpinCustomMax->GetFormatter().SetValue(*maAttributes.getManualMax());
248 break;
250 ComboValueChanged(*mxComboMaxAxisType);
253 void SparklineDialog::Close() { DoClose(sc::SparklineDialogWrapper::GetChildWindowId()); }
255 void SparklineDialog::SetActive()
257 if (mbDialogLostFocus)
259 mbDialogLostFocus = false;
260 if (mpActiveEdit)
261 mpActiveEdit->GrabFocus();
263 else
265 m_xDialog->grab_focus();
267 RefInputDone();
270 void SparklineDialog::SetReference(const ScRange& rReferenceRange, ScDocument& rDocument)
272 if (mpActiveEdit)
274 if (rReferenceRange.aStart != rReferenceRange.aEnd)
275 RefInputStart(mpActiveEdit);
277 OUString aString;
278 const ScRefFlags eFlags = ScRefFlags::VALID | ScRefFlags::TAB_3D;
279 auto eAddressConvention = rDocument.GetAddressConvention();
281 if (mpActiveEdit == mxInputRangeEdit.get())
283 maInputRange = rReferenceRange;
284 aString = maInputRange.Format(rDocument, eFlags, eAddressConvention);
285 mxInputRangeEdit->SetRefString(aString);
287 else if (mpActiveEdit == mxOutputRangeEdit.get())
289 maOutputRange = rReferenceRange;
290 aString = maOutputRange.Format(rDocument, eFlags, eAddressConvention);
291 mxOutputRangeEdit->SetRefString(aString);
295 mxButtonOk->set_sensitive(checkValidInputOutput());
298 IMPL_LINK(SparklineDialog, EditFocusHandler, formula::RefEdit&, rEdit, void)
300 auto* pEdit = &rEdit;
302 if (mxInputRangeEdit.get() == pEdit)
303 mpActiveEdit = mxInputRangeEdit.get();
304 else if (mxOutputRangeEdit.get() == pEdit)
305 mpActiveEdit = mxOutputRangeEdit.get();
306 else
307 mpActiveEdit = nullptr;
309 if (mpActiveEdit)
310 mpActiveEdit->SelectAll();
313 IMPL_LINK(SparklineDialog, ButtonFocusHandler, formula::RefButton&, rButton, void)
315 auto* pButton = &rButton;
317 if (mxInputRangeButton.get() == pButton)
318 mpActiveEdit = mxInputRangeEdit.get();
319 else if (mxOutputRangeButton.get() == pButton)
320 mpActiveEdit = mxOutputRangeEdit.get();
321 else
322 mpActiveEdit = nullptr;
324 if (mpActiveEdit)
325 mpActiveEdit->SelectAll();
328 IMPL_LINK_NOARG(SparklineDialog, LoseEditFocusHandler, formula::RefEdit&, void)
330 mbDialogLostFocus = !m_xDialog->has_toplevel_focus();
333 IMPL_LINK_NOARG(SparklineDialog, LoseButtonFocusHandler, formula::RefButton&, void)
335 mbDialogLostFocus = !m_xDialog->has_toplevel_focus();
338 IMPL_LINK_NOARG(SparklineDialog, RefInputModifyHandler, formula::RefEdit&, void)
340 if (mpActiveEdit)
342 if (mpActiveEdit == mxInputRangeEdit.get())
344 ScRangeList aRangeList;
345 bool bValid = ParseWithNames(aRangeList, mxInputRangeEdit->GetText(), mrDocument);
346 const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
347 if (pRange)
349 maInputRange = *pRange;
350 mxInputRangeEdit->StartUpdateData();
352 else
354 maInputRange = ScRange(ScAddress::INITIALIZE_INVALID);
357 else if (mpActiveEdit == mxOutputRangeEdit.get())
359 ScRangeList aRangeList;
360 bool bValid = ParseWithNames(aRangeList, mxOutputRangeEdit->GetText(), mrDocument);
361 const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
362 if (pRange)
364 maOutputRange = *pRange;
365 mxOutputRangeEdit->StartUpdateData();
367 else
369 maOutputRange = ScRange(ScAddress::INITIALIZE_INVALID);
374 mxButtonOk->set_sensitive(checkValidInputOutput());
377 IMPL_LINK(SparklineDialog, ButtonClicked, weld::Button&, rButton, void)
379 if (mxButtonOk.get() == &rButton)
381 perform();
382 response(RET_OK);
384 else
386 response(RET_CANCEL);
390 IMPL_LINK(SparklineDialog, ToggleHandler, weld::Toggleable&, rToggle, void)
392 if (mxCheckButtonNegative.get() == &rToggle)
393 maAttributes.setNegative(mxCheckButtonNegative->get_active());
394 if (mxCheckButtonMarker.get() == &rToggle)
395 maAttributes.setMarkers(mxCheckButtonMarker->get_active());
396 if (mxCheckButtonHigh.get() == &rToggle)
397 maAttributes.setHigh(mxCheckButtonHigh->get_active());
398 if (mxCheckButtonLow.get() == &rToggle)
399 maAttributes.setLow(mxCheckButtonLow->get_active());
400 if (mxCheckButtonFirst.get() == &rToggle)
401 maAttributes.setFirst(mxCheckButtonFirst->get_active());
402 if (mxCheckButtonLast.get() == &rToggle)
403 maAttributes.setLast(mxCheckButtonLast->get_active());
404 if (mxCheckDisplayXAxis.get() == &rToggle)
405 maAttributes.setDisplayXAxis(mxCheckDisplayXAxis->get_active());
406 if (mxCheckDisplayHidden.get() == &rToggle)
407 maAttributes.setDisplayHidden(mxCheckDisplayHidden->get_active());
408 if (mxCheckRightToLeft.get() == &rToggle)
409 maAttributes.setRightToLeft(mxCheckRightToLeft->get_active());
412 IMPL_LINK_NOARG(SparklineDialog, SelectSparklineType, weld::ComboBox&, void)
414 switch (mxType->get_active())
416 case 0:
417 maAttributes.setType(sc::SparklineType::Line);
418 break;
419 case 1:
420 maAttributes.setType(sc::SparklineType::Column);
421 break;
422 case 2:
423 maAttributes.setType(sc::SparklineType::Stacked);
424 break;
426 switch (mxDisplayEmptyGap->get_active())
428 case 1:
429 maAttributes.setDisplayEmptyCellsAs(sc::DisplayEmptyCellsAs::Gap);
430 break;
431 case 2:
432 maAttributes.setDisplayEmptyCellsAs(sc::DisplayEmptyCellsAs::Zero);
433 break;
434 case 3:
435 maAttributes.setDisplayEmptyCellsAs(sc::DisplayEmptyCellsAs::Span);
436 break;
440 IMPL_LINK_NOARG(SparklineDialog, SpinLineWidthChanged, weld::SpinButton&, void)
442 double value = mxSpinLineWidth->get_value() / 100.0;
443 maAttributes.setLineWeight(value);
446 IMPL_LINK(SparklineDialog, SpinCustomChanged, weld::FormattedSpinButton&, rFormatted, void)
448 if (mxSpinCustomMin.get() == &rFormatted)
450 maAttributes.setManualMin(rFormatted.GetFormatter().GetValue());
452 else if (mxSpinCustomMax.get() == &rFormatted)
454 maAttributes.setManualMax(rFormatted.GetFormatter().GetValue());
458 IMPL_LINK(SparklineDialog, ComboValueChanged, weld::ComboBox&, rComboBox, void)
460 int nActive = rComboBox.get_active();
462 if (mxComboMinAxisType.get() == &rComboBox)
464 switch (nActive)
466 case 0:
467 maAttributes.setMinAxisType(sc::AxisType::Individual);
468 mxSpinCustomMin->set_sensitive(false);
469 break;
470 case 1:
471 maAttributes.setMinAxisType(sc::AxisType::Group);
472 mxSpinCustomMin->set_sensitive(false);
473 break;
474 case 2:
475 maAttributes.setMinAxisType(sc::AxisType::Custom);
476 mxSpinCustomMin->set_sensitive(true);
477 break;
478 default:
479 break;
482 else if (mxComboMaxAxisType.get() == &rComboBox)
484 switch (nActive)
486 case 0:
487 maAttributes.setMaxAxisType(sc::AxisType::Individual);
488 mxSpinCustomMax->set_sensitive(false);
489 break;
490 case 1:
491 maAttributes.setMaxAxisType(sc::AxisType::Group);
492 mxSpinCustomMax->set_sensitive(false);
493 break;
494 case 2:
495 maAttributes.setMaxAxisType(sc::AxisType::Custom);
496 mxSpinCustomMax->set_sensitive(true);
497 break;
498 default:
499 break;
504 bool SparklineDialog::checkValidInputOutput()
506 if (mbEditMode)
507 return true;
509 if (!maInputRange.IsValid() || !maOutputRange.IsValid())
510 return false;
512 sc::RangeOrientation eInputOrientation = sc::RangeOrientation::Unknown;
513 if (maOutputRange.aStart.Col() == maOutputRange.aEnd.Col())
515 sal_Int32 nOutputRowSize = maOutputRange.aEnd.Row() - maOutputRange.aStart.Row();
516 eInputOrientation = sc::calculateOrientation(nOutputRowSize, maInputRange);
518 else if (maOutputRange.aStart.Row() == maOutputRange.aEnd.Row())
520 sal_Int32 nOutputColSize = maOutputRange.aEnd.Col() - maOutputRange.aStart.Col();
521 eInputOrientation = sc::calculateOrientation(nOutputColSize, maInputRange);
524 return eInputOrientation != sc::RangeOrientation::Unknown;
527 void SparklineDialog::perform()
529 maAttributes.setColorSeries(mxColorSeries->GetSelectedEntry().getComplexColor());
530 maAttributes.setColorNegative(mxColorNegative->GetSelectedEntry().getComplexColor());
531 maAttributes.setColorMarkers(mxColorMarker->GetSelectedEntry().getComplexColor());
532 maAttributes.setColorHigh(mxColorHigh->GetSelectedEntry().getComplexColor());
533 maAttributes.setColorLow(mxColorLow->GetSelectedEntry().getComplexColor());
534 maAttributes.setColorFirst(mxColorFirst->GetSelectedEntry().getComplexColor());
535 maAttributes.setColorLast(mxColorLast->GetSelectedEntry().getComplexColor());
537 auto& rDocFunc = mrViewData.GetDocShell()->GetDocFunc();
539 if (mpSparklineGroup)
541 rDocFunc.ChangeSparklineGroupAttributes(mpSparklineGroup, maAttributes);
543 else
545 auto pNewSparklineGroup = std::make_shared<sc::SparklineGroup>(maAttributes);
546 rDocFunc.InsertSparklines(maInputRange, maOutputRange, pNewSparklineGroup);
550 } // end sc
552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */