LibreOffice Module chart2 (master) 1
ChartErrorBarPanel.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <com/sun/star/chart/ErrorBarStyle.hpp>
21#include <com/sun/star/beans/XPropertySet.hpp>
22
24#include <ChartController.hxx>
25#include <ChartModel.hxx>
26#include <vcl/svapp.hxx>
27#include <sal/log.hxx>
28
29
30using namespace css;
31using namespace css::uno;
32
33namespace chart::sidebar {
34
35namespace {
36
37enum class ErrorBarDirection
38{
39 POSITIVE,
40 NEGATIVE
41};
42
43css::uno::Reference<css::beans::XPropertySet> getErrorBarPropSet(
44 const rtl::Reference<::chart::ChartModel>& xModel, std::u16string_view rCID)
45{
46 return ObjectIdentifier::getObjectPropertySet(rCID, xModel);
47}
48
49bool showPositiveError(const rtl::Reference<::chart::ChartModel>& xModel,
50 std::u16string_view rCID)
51{
52 css::uno::Reference<css::beans::XPropertySet> xPropSet =
53 getErrorBarPropSet(xModel, rCID);
54
55 if (!xPropSet.is())
56 return false;
57
58 css::uno::Any aAny = xPropSet->getPropertyValue("ShowPositiveError");
59
60 if (!aAny.hasValue())
61 return false;
62
63 bool bShow = false;
64 aAny >>= bShow;
65 return bShow;
66}
67
68bool showNegativeError(const rtl::Reference<::chart::ChartModel>& xModel,
69 std::u16string_view rCID)
70{
71 css::uno::Reference<css::beans::XPropertySet> xPropSet =
72 getErrorBarPropSet(xModel, rCID);
73
74 if (!xPropSet.is())
75 return false;
76
77 css::uno::Any aAny = xPropSet->getPropertyValue("ShowNegativeError");
78
79 if (!aAny.hasValue())
80 return false;
81
82 bool bShow = false;
83 aAny >>= bShow;
84 return bShow;
85}
86
87void setShowPositiveError(const rtl::Reference<::chart::ChartModel>& xModel,
88 std::u16string_view rCID, bool bShow)
89{
90 css::uno::Reference<css::beans::XPropertySet> xPropSet =
91 getErrorBarPropSet(xModel, rCID);
92
93 if (!xPropSet.is())
94 return;
95
96 xPropSet->setPropertyValue("ShowPositiveError", css::uno::Any(bShow));
97}
98
99void setShowNegativeError(const rtl::Reference<::chart::ChartModel>& xModel,
100 std::u16string_view rCID, bool bShow)
101{
102 css::uno::Reference<css::beans::XPropertySet> xPropSet =
103 getErrorBarPropSet(xModel, rCID);
104
105 if (!xPropSet.is())
106 return;
107
108 xPropSet->setPropertyValue("ShowNegativeError", css::uno::Any(bShow));
109}
110
111struct ErrorBarTypeMap
112{
113 sal_Int32 nPos;
114 sal_Int32 nApi;
115};
116
117ErrorBarTypeMap const aErrorBarType[] = {
118 { 0, css::chart::ErrorBarStyle::ABSOLUTE },
119 { 1, css::chart::ErrorBarStyle::RELATIVE },
120 { 2, css::chart::ErrorBarStyle::FROM_DATA },
121 { 3, css::chart::ErrorBarStyle::STANDARD_DEVIATION },
122 { 4, css::chart::ErrorBarStyle::STANDARD_ERROR },
123 { 5, css::chart::ErrorBarStyle::VARIANCE},
124 { 6, css::chart::ErrorBarStyle::ERROR_MARGIN },
125};
126
127sal_Int32 getTypePos(const rtl::Reference<::chart::ChartModel>& xModel,
128 std::u16string_view rCID)
129{
130 css::uno::Reference<css::beans::XPropertySet> xPropSet =
131 getErrorBarPropSet(xModel, rCID);
132
133 if (!xPropSet.is())
134 return 0;
135
136 css::uno::Any aAny = xPropSet->getPropertyValue("ErrorBarStyle");
137
138 if (!aAny.hasValue())
139 return 0;
140
141 sal_Int32 nApi = 0;
142 aAny >>= nApi;
143
144 for (ErrorBarTypeMap const & i : aErrorBarType)
145 {
146 if (i.nApi == nApi)
147 return i.nPos;
148 }
149
150 return 0;
151}
152
153void setTypePos(const rtl::Reference<::chart::ChartModel>& xModel,
154 std::u16string_view rCID, sal_Int32 nPos)
155{
156 css::uno::Reference<css::beans::XPropertySet> xPropSet =
157 getErrorBarPropSet(xModel, rCID);
158
159 if (!xPropSet.is())
160 return;
161
162 sal_Int32 nApi = 0;
163 for (ErrorBarTypeMap const & i : aErrorBarType)
164 {
165 if (i.nPos == nPos)
166 nApi = i.nApi;
167 }
168
169 xPropSet->setPropertyValue("ErrorBarStyle", css::uno::Any(nApi));
170}
171
173 std::u16string_view rCID, ErrorBarDirection eDir)
174{
175 css::uno::Reference<css::beans::XPropertySet> xPropSet =
176 getErrorBarPropSet(xModel, rCID);
177
178 if (!xPropSet.is())
179 return 0;
180
181 OUString aName = "PositiveError";
182 if (eDir == ErrorBarDirection::NEGATIVE)
183 aName = "NegativeError";
184
185 css::uno::Any aAny = xPropSet->getPropertyValue(aName);
186
187 if (!aAny.hasValue())
188 return 0;
189
190 double nVal = 0;
191 aAny >>= nVal;
192
193 return nVal;
194}
195
197 std::u16string_view rCID, double nVal, ErrorBarDirection eDir)
198{
199 css::uno::Reference<css::beans::XPropertySet> xPropSet =
200 getErrorBarPropSet(xModel, rCID);
201
202 if (!xPropSet.is())
203 return;
204
205 OUString aName = "PositiveError";
206 if (eDir == ErrorBarDirection::NEGATIVE)
207 aName = "NegativeError";
208
209 xPropSet->setPropertyValue(aName, css::uno::Any(nVal));
210}
211
212OUString getCID(const rtl::Reference<::chart::ChartModel>& xModel)
213{
214 css::uno::Reference<css::frame::XController> xController(xModel->getCurrentController());
215 css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier(xController, css::uno::UNO_QUERY);
216 if (!xSelectionSupplier.is())
217 return OUString();
218
219 uno::Any aAny = xSelectionSupplier->getSelection();
220 assert(aAny.hasValue());
221 OUString aCID;
222 aAny >>= aCID;
223#if defined DBG_UTIL && !defined NDEBUG
225 if (eType != OBJECTTYPE_DATA_ERRORS_X &&
226 eType != OBJECTTYPE_DATA_ERRORS_Y &&
228 SAL_WARN("chart2","Selected item is not an error bar");
229
230#endif
231
232 return aCID;
233}
234
235}
236
238 : PanelLayout(pParent, "ChartErrorBarPanel", "modules/schart/ui/sidebarerrorbar.ui")
239 , mxRBPosAndNeg(m_xBuilder->weld_radio_button("radiobutton_positive_negative"))
240 , mxRBPos(m_xBuilder->weld_radio_button("radiobutton_positive"))
241 , mxRBNeg(m_xBuilder->weld_radio_button("radiobutton_negative"))
242 , mxLBType(m_xBuilder->weld_combo_box("comboboxtext_type"))
243 , mxMFPos(m_xBuilder->weld_spin_button("spinbutton_pos"))
244 , mxMFNeg(m_xBuilder->weld_spin_button("spinbutton_neg"))
245 , mxModel(pController->getChartModel())
247 , mbModelValid(true)
248{
249 Initialize();
250}
251
253{
254 doUpdateModel(nullptr);
255
256 mxRBPosAndNeg.reset();
257 mxRBPos.reset();
258 mxRBNeg.reset();
259
260 mxLBType.reset();
261
262 mxMFPos.reset();
263 mxMFNeg.reset();
264}
265
267{
268 mxModel->addModifyListener(mxListener);
269 mxRBNeg->set_active(false);
270 mxRBPos->set_active(false);
271 mxRBPosAndNeg->set_active(false);
272
273 updateData();
274
275 Link<weld::Toggleable&,void> aLink = LINK(this, ChartErrorBarPanel, RadioBtnHdl);
276 mxRBPosAndNeg->connect_toggled(aLink);
277 mxRBPos->connect_toggled(aLink);
278 mxRBNeg->connect_toggled(aLink);
279
280 mxLBType->connect_changed(LINK(this, ChartErrorBarPanel, ListBoxHdl));
281
282 Link<weld::SpinButton&,void> aLink2 = LINK(this, ChartErrorBarPanel, NumericFieldHdl);
283 mxMFPos->connect_value_changed(aLink2);
284 mxMFNeg->connect_value_changed(aLink2);
285}
286
288{
289 if (!mbModelValid)
290 return;
291
292 OUString aCID = getCID(mxModel);
297 return;
298
299 bool bPos = showPositiveError(mxModel, aCID);
300 bool bNeg = showNegativeError(mxModel, aCID);
301
302 SolarMutexGuard aGuard;
303
304 if (bPos && bNeg)
305 mxRBPosAndNeg->set_active(true);
306 else if (bPos)
307 mxRBPos->set_active(true);
308 else if (bNeg)
309 mxRBNeg->set_active(true);
310
311 sal_Int32 nTypePos = getTypePos(mxModel, aCID);
312 mxLBType->set_active(nTypePos);
313
314 if (nTypePos <= 1)
315 {
316 if (bPos)
317 mxMFPos->set_sensitive(true);
318 else
319 mxMFPos->set_sensitive(false);
320
321 if (bNeg)
322 mxMFNeg->set_sensitive(true);
323 else
324 mxMFNeg->set_sensitive(false);
325
326 double nValPos = getValue(mxModel, aCID, ErrorBarDirection::POSITIVE);
327 double nValNeg = getValue(mxModel, aCID, ErrorBarDirection::NEGATIVE);
328
329 mxMFPos->set_value(nValPos);
330 mxMFNeg->set_value(nValNeg);
331 }
332 else
333 {
334 mxMFPos->set_sensitive(false);
335 mxMFNeg->set_sensitive(false);
336 }
337}
338
339std::unique_ptr<PanelLayout> ChartErrorBarPanel::Create (
340 weld::Widget* pParent,
341 ChartController* pController)
342{
343 if (pParent == nullptr)
344 throw lang::IllegalArgumentException("no parent Window given to ChartErrorBarPanel::Create", nullptr, 0);
345 return std::make_unique<ChartErrorBarPanel>(pParent, pController);
346}
347
349{
351 updateData();
352}
353
355 const vcl::EnumContext& )
356{
357 updateData();
358}
359
361 sal_uInt16 /*nSID*/,
362 SfxItemState /*eState*/,
363 const SfxPoolItem* /*pState*/ )
364{
365}
366
368{
369 mbModelValid = false;
370}
371
373{
374 if (mbModelValid)
375 {
376 mxModel->removeModifyListener(mxListener);
377 }
378
379 mxModel = xModel;
380 mbModelValid = mxModel.is();
381
382 if (!mbModelValid)
383 return;
384
385 mxModel->addModifyListener(mxListener);
386}
387
388void ChartErrorBarPanel::updateModel(css::uno::Reference<css::frame::XModel> xModel)
389{
390 ::chart::ChartModel* pModel = dynamic_cast<::chart::ChartModel*>(xModel.get());
391 assert(!xModel || pModel);
392 doUpdateModel(pModel);
393}
394
396{
397 OUString aCID = getCID(mxModel);
398 bool bPos = mxRBPosAndNeg->get_active() || mxRBPos->get_active();
399 bool bNeg = mxRBPosAndNeg->get_active() || mxRBNeg->get_active();
400
401 setShowPositiveError(mxModel, aCID, bPos);
402 setShowNegativeError(mxModel, aCID, bNeg);
403}
404
406{
407 OUString aCID = getCID(mxModel);
408 sal_Int32 nPos = mxLBType->get_active();
409
410 setTypePos(mxModel, aCID, nPos);
411}
412
413IMPL_LINK(ChartErrorBarPanel, NumericFieldHdl, weld::SpinButton&, rMetricField, void)
414{
415 OUString aCID = getCID(mxModel);
416 double nVal = rMetricField.get_value();
417 if (&rMetricField == mxMFPos.get())
418 setValue(mxModel, aCID, nVal, ErrorBarDirection::POSITIVE);
419 else if (&rMetricField == mxMFNeg.get())
420 setValue(mxModel, aCID, nVal, ErrorBarDirection::NEGATIVE);
421}
422
423} // end of namespace ::chart::sidebar
424
425/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 nPos
sal_Int32 nApi
css::uno::Reference< css::frame::XModel2 > mxModel
virtual void DataChanged(const DataChangedEvent &rEvent)
static css::uno::Reference< css::beans::XPropertySet > getObjectPropertySet(std::u16string_view rObjectCID, const rtl::Reference< ::chart::ChartModel > &xChartDocument)
ObjectType getObjectType() const
virtual void updateModel(css::uno::Reference< css::frame::XModel > xModel) override
css::uno::Reference< css::util::XModifyListener > mxListener
std::unique_ptr< weld::SpinButton > mxMFPos
virtual void HandleContextChange(const vcl::EnumContext &rContext) override
std::unique_ptr< weld::RadioButton > mxRBPos
std::unique_ptr< weld::RadioButton > mxRBPosAndNeg
void doUpdateModel(rtl::Reference<::chart::ChartModel > xModel)
std::unique_ptr< weld::ComboBox > mxLBType
ChartErrorBarPanel(weld::Widget *pParent, ChartController *pController)
rtl::Reference<::chart::ChartModel > mxModel
static std::unique_ptr< PanelLayout > Create(weld::Widget *pParent, ChartController *pController)
virtual void NotifyItemUpdate(const sal_uInt16 nSId, const SfxItemState eState, const SfxPoolItem *pState) override
std::unique_ptr< weld::RadioButton > mxRBNeg
virtual void DataChanged(const DataChangedEvent &rEvent) override
std::unique_ptr< weld::SpinButton > mxMFNeg
Reference< script::XScriptListener > mxListener
DocumentType eType
OUString aName
#define SAL_WARN(area, stream)
IMPL_LINK_NOARG(ChartAxisPanel, ListBoxHdl, weld::ComboBox &, void)
IMPL_LINK(ChartAxisPanel, CheckBoxHdl, weld::Toggleable &, rCheckbox, void)
@ OBJECTTYPE_DATA_ERRORS_X
@ OBJECTTYPE_DATA_ERRORS_Y
@ OBJECTTYPE_DATA_ERRORS_Z
int i
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
ObjectType
SfxItemState
RegError REGISTRY_CALLTYPE setValue(RegKeyHandle hKey, rtl_uString *keyName, RegValueType valueType, RegValue pData, sal_uInt32 valueSize)
bool hasValue()
Reference< XController > xController
Reference< XModel > xModel