1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/chart/ErrorBarStyle.hpp>
21 #include <com/sun/star/beans/XPropertySet.hpp>
22 #include <com/sun/star/chart/DataLabelPlacement.hpp>
23 #include <com/sun/star/chart2/XChartDocument.hpp>
24 #include <com/sun/star/chart2/XDataSeries.hpp>
25 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
26 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
27 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
28 #include <com/sun/star/util/XModifyBroadcaster.hpp>
30 #include <sal/log.hxx>
31 #include "ChartSeriesPanel.hxx"
32 #include <ChartController.hxx>
33 #include <vcl/fixed.hxx>
34 #include <vcl/lstbox.hxx>
36 #include <DataSeriesHelper.hxx>
37 #include <RegressionCurveHelper.hxx>
38 #include <StatisticsHelper.hxx>
41 using namespace css::uno
;
43 namespace chart
{ namespace sidebar
{
47 bool isDataLabelVisible(const css::uno::Reference
<css::frame::XModel
>& xModel
, const OUString
& rCID
)
49 css::uno::Reference
< css::chart2::XDataSeries
> xSeries
=
50 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
);
55 return DataSeriesHelper::hasDataLabelsAtSeries(xSeries
);
58 void setDataLabelVisible(const css::uno::Reference
<css::frame::XModel
>& xModel
, const OUString
& rCID
, bool bVisible
)
60 css::uno::Reference
< css::chart2::XDataSeries
> xSeries
=
61 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
);
67 DataSeriesHelper::insertDataLabelsToSeriesAndAllPoints(xSeries
);
69 DataSeriesHelper::deleteDataLabelsFromSeriesAndAllPoints(xSeries
);
72 struct LabelPlacementMap
78 static LabelPlacementMap
const aLabelPlacementMap
[] = {
79 { 0, css::chart::DataLabelPlacement::TOP
},
80 { 1, css::chart::DataLabelPlacement::BOTTOM
},
81 { 2, css::chart::DataLabelPlacement::CENTER
},
82 { 3, css::chart::DataLabelPlacement::OUTSIDE
},
83 { 4, css::chart::DataLabelPlacement::INSIDE
},
84 { 5, css::chart::DataLabelPlacement::NEAR_ORIGIN
}
87 sal_Int32
getDataLabelPlacement(const css::uno::Reference
<css::frame::XModel
>& xModel
,
90 css::uno::Reference
< css::beans::XPropertySet
> xSeries(
91 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
), uno::UNO_QUERY
);
96 css::uno::Any aAny
= xSeries
->getPropertyValue("LabelPlacement");
100 sal_Int32 nPlacement
= 0;
103 for (LabelPlacementMap
const & i
: aLabelPlacementMap
)
105 if (i
.nApi
== nPlacement
)
112 void setDataLabelPlacement(const css::uno::Reference
<css::frame::XModel
>& xModel
,
113 const OUString
& rCID
, sal_Int32 nPos
)
115 css::uno::Reference
< css::beans::XPropertySet
> xSeries(
116 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
), uno::UNO_QUERY
);
122 for (LabelPlacementMap
const & i
: aLabelPlacementMap
)
131 xSeries
->setPropertyValue("LabelPlacement", css::uno::Any(nApi
));
134 bool isTrendlineVisible(const css::uno::Reference
<css::frame::XModel
>& xModel
,
135 const OUString
& rCID
)
137 css::uno::Reference
< css::chart2::XRegressionCurveContainer
> xRegressionCurveContainer(
138 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
), uno::UNO_QUERY
);
140 if (!xRegressionCurveContainer
.is())
143 return xRegressionCurveContainer
->getRegressionCurves().hasElements();
146 void setTrendlineVisible(const css::uno::Reference
<css::frame::XModel
>&
147 xModel
, const OUString
& rCID
, bool bVisible
)
149 css::uno::Reference
< css::chart2::XRegressionCurveContainer
> xRegressionCurveContainer(
150 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
), uno::UNO_QUERY
);
152 if (!xRegressionCurveContainer
.is())
157 RegressionCurveHelper::addRegressionCurve(
158 SvxChartRegress::Linear
,
159 xRegressionCurveContainer
);
162 RegressionCurveHelper::removeAllExceptMeanValueLine(
163 xRegressionCurveContainer
);
167 bool isErrorBarVisible(const css::uno::Reference
<css::frame::XModel
>& xModel
,
168 const OUString
& rCID
, bool bYError
)
170 css::uno::Reference
< css::chart2::XDataSeries
> xSeries
=
171 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
);
176 return StatisticsHelper::hasErrorBars(xSeries
, bYError
);
179 void setErrorBarVisible(const css::uno::Reference
<css::frame::XModel
>&
180 xModel
, const OUString
& rCID
, bool bYError
, bool bVisible
)
182 css::uno::Reference
< css::chart2::XDataSeries
> xSeries
=
183 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
);
190 StatisticsHelper::addErrorBars( xSeries
,
191 css::chart::ErrorBarStyle::STANDARD_DEVIATION
,
196 StatisticsHelper::removeErrorBars( xSeries
, bYError
);
200 bool isPrimaryAxis(const css::uno::Reference
<css::frame::XModel
>&
201 xModel
, const OUString
& rCID
)
203 css::uno::Reference
< css::chart2::XDataSeries
> xSeries
=
204 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
);
209 return DataSeriesHelper::getAttachedAxisIndex(xSeries
) == 0;
212 void setAttachedAxisType(const css::uno::Reference
<css::frame::XModel
>&
213 xModel
, const OUString
& rCID
, bool bPrimary
)
215 css::uno::Reference
< css::beans::XPropertySet
> xSeries(
216 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
), uno::UNO_QUERY
);
221 sal_Int32 nIndex
= bPrimary
? 0 : 1;
222 xSeries
->setPropertyValue("AttachedAxisIndex", css::uno::Any(nIndex
));
225 css::uno::Reference
<css::chart2::XChartType
> getChartType(
226 const css::uno::Reference
<css::frame::XModel
>& xModel
)
228 css::uno::Reference
<css::chart2::XChartDocument
> xChartDoc (xModel
, css::uno::UNO_QUERY
);
229 css::uno::Reference
<css::chart2::XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
230 css::uno::Reference
< css::chart2::XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, UNO_QUERY_THROW
);
231 css::uno::Sequence
< css::uno::Reference
< css::chart2::XCoordinateSystem
> > xCooSysSequence( xCooSysContainer
->getCoordinateSystems());
232 css::uno::Reference
< css::chart2::XChartTypeContainer
> xChartTypeContainer( xCooSysSequence
[0], UNO_QUERY_THROW
);
233 css::uno::Sequence
< css::uno::Reference
< css::chart2::XChartType
> > xChartTypeSequence( xChartTypeContainer
->getChartTypes() );
234 return xChartTypeSequence
[0];
237 OUString
getSeriesLabel(const css::uno::Reference
<css::frame::XModel
>& xModel
, const OUString
& rCID
)
239 css::uno::Reference
< css::chart2::XDataSeries
> xSeries
=
240 ObjectIdentifier::getDataSeriesForCID(rCID
, xModel
);
245 css::uno::Reference
<css::chart2::XChartType
> xChartType
= getChartType(xModel
);
246 return DataSeriesHelper::getDataSeriesLabel(xSeries
, xChartType
->getRoleOfSequenceForSeriesLabel());
249 OUString
getCID(const css::uno::Reference
<css::frame::XModel
>& xModel
)
251 css::uno::Reference
<css::frame::XController
> xController(xModel
->getCurrentController());
252 css::uno::Reference
<css::view::XSelectionSupplier
> xSelectionSupplier(xController
, css::uno::UNO_QUERY
);
253 if (!xSelectionSupplier
.is())
256 uno::Any aAny
= xSelectionSupplier
->getSelection();
257 if (!aAny
.hasValue())
266 #if defined DBG_UTIL && !defined NDEBUG
267 ObjectType eType
= ObjectIdentifier::getObjectType(aCID
);
268 if (eType
!= OBJECTTYPE_DATA_SERIES
&&
269 eType
!= OBJECTTYPE_DATA_POINT
&&
270 eType
!= OBJECTTYPE_DATA_CURVE
)
271 SAL_WARN("chart2","Selected item is not a chart series");
279 ChartSeriesPanel::ChartSeriesPanel(
280 vcl::Window
* pParent
,
281 const css::uno::Reference
<css::frame::XFrame
>& rxFrame
,
282 ChartController
* pController
)
283 : PanelLayout(pParent
, "ChartSeriesPanel", "modules/schart/ui/sidebarseries.ui", rxFrame
),
284 mxModel(pController
->getModel()),
285 mxListener(new ChartSidebarModifyListener(this)),
286 mxSelectionListener(new ChartSidebarSelectionListener(this, OBJECTTYPE_DATA_SERIES
)),
289 get(mpCBLabel
, "checkbutton_label");
290 get(mpCBTrendline
, "checkbutton_trendline");
291 get(mpCBXError
, "checkbutton_x_error");
292 get(mpCBYError
, "checkbutton_y_error");
294 get(mpRBPrimaryAxis
, "radiobutton_primary_axis");
295 get(mpRBSecondaryAxis
, "radiobutton_secondary_axis");
297 get(mpBoxLabelPlacement
, "datalabel_box");
298 get(mpLBLabelPlacement
, "comboboxtext_label");
300 get(mpFTSeriesName
, "label_series_name");
301 get(mpFTSeriesTemplate
, "label_series_tmpl");
306 ChartSeriesPanel::~ChartSeriesPanel()
311 void ChartSeriesPanel::dispose()
313 css::uno::Reference
<css::util::XModifyBroadcaster
> xBroadcaster(mxModel
, css::uno::UNO_QUERY_THROW
);
314 xBroadcaster
->removeModifyListener(mxListener
);
315 css::uno::Reference
<css::view::XSelectionSupplier
> xSelectionSupplier(mxModel
->getCurrentController(), css::uno::UNO_QUERY
);
316 if (xSelectionSupplier
.is())
317 xSelectionSupplier
->removeSelectionChangeListener(mxSelectionListener
);
320 mpCBTrendline
.clear();
324 mpRBPrimaryAxis
.clear();
325 mpRBSecondaryAxis
.clear();
327 mpBoxLabelPlacement
.clear();
328 mpLBLabelPlacement
.clear();
330 mpFTSeriesName
.clear();
331 mpFTSeriesTemplate
.clear();
333 PanelLayout::dispose();
336 void ChartSeriesPanel::Initialize()
338 css::uno::Reference
<css::util::XModifyBroadcaster
> xBroadcaster(mxModel
, css::uno::UNO_QUERY_THROW
);
339 xBroadcaster
->addModifyListener(mxListener
);
340 css::uno::Reference
<css::view::XSelectionSupplier
> xSelectionSupplier(mxModel
->getCurrentController(), css::uno::UNO_QUERY
);
341 if (xSelectionSupplier
.is())
342 xSelectionSupplier
->addSelectionChangeListener(mxSelectionListener
);
346 Link
<Button
*,void> aLink
= LINK(this, ChartSeriesPanel
, CheckBoxHdl
);
347 mpCBLabel
->SetClickHdl(aLink
);
348 mpCBTrendline
->SetClickHdl(aLink
);
349 mpCBXError
->SetClickHdl(aLink
);
350 mpCBYError
->SetClickHdl(aLink
);
352 Link
<RadioButton
&,void> aLink2
= LINK(this, ChartSeriesPanel
, RadioBtnHdl
);
353 mpRBPrimaryAxis
->SetToggleHdl(aLink2
);
354 mpRBSecondaryAxis
->SetToggleHdl(aLink2
);
356 mpLBLabelPlacement
->SetSelectHdl(LINK(this, ChartSeriesPanel
, ListBoxHdl
));
359 void ChartSeriesPanel::updateData()
364 OUString aCID
= getCID(mxModel
);
365 ObjectType eType
= ObjectIdentifier::getObjectType(aCID
);
366 if (eType
!=OBJECTTYPE_DATA_SERIES
&&
367 eType
!= OBJECTTYPE_DATA_POINT
&&
368 eType
!= OBJECTTYPE_DATA_CURVE
)
371 SolarMutexGuard aGuard
;
372 bool bLabelVisible
= isDataLabelVisible(mxModel
, aCID
);
373 mpCBLabel
->Check(bLabelVisible
);
374 mpCBTrendline
->Check(isTrendlineVisible(mxModel
, aCID
));
375 mpCBXError
->Check(isErrorBarVisible(mxModel
, aCID
, false));
376 mpCBYError
->Check(isErrorBarVisible(mxModel
, aCID
, true));
378 bool bPrimaryAxis
= isPrimaryAxis(mxModel
, aCID
);
379 mpRBPrimaryAxis
->Check(bPrimaryAxis
);
380 mpRBSecondaryAxis
->Check(!bPrimaryAxis
);
382 mpBoxLabelPlacement
->Enable(bLabelVisible
);
383 mpLBLabelPlacement
->SelectEntryPos(getDataLabelPlacement(mxModel
, aCID
));
385 OUString aFrameLabel
= mpFTSeriesTemplate
->GetText();
386 aFrameLabel
= aFrameLabel
.replaceFirst("%1", getSeriesLabel(mxModel
, aCID
));
387 mpFTSeriesName
->SetText(aFrameLabel
);
390 VclPtr
<vcl::Window
> ChartSeriesPanel::Create (
391 vcl::Window
* pParent
,
392 const css::uno::Reference
<css::frame::XFrame
>& rxFrame
,
393 ChartController
* pController
)
395 if (pParent
== nullptr)
396 throw lang::IllegalArgumentException("no parent Window given to ChartSeriesPanel::Create", nullptr, 0);
398 throw lang::IllegalArgumentException("no XFrame given to ChartSeriesPanel::Create", nullptr, 1);
400 return VclPtr
<ChartSeriesPanel
>::Create(
401 pParent
, rxFrame
, pController
);
404 void ChartSeriesPanel::DataChanged(
405 const DataChangedEvent
& )
410 void ChartSeriesPanel::HandleContextChange(
411 const vcl::EnumContext
& )
416 void ChartSeriesPanel::NotifyItemUpdate(
418 SfxItemState
/*eState*/,
419 const SfxPoolItem
* /*pState*/ )
423 void ChartSeriesPanel::modelInvalid()
425 mbModelValid
= false;
428 void ChartSeriesPanel::updateModel(
429 css::uno::Reference
<css::frame::XModel
> xModel
)
433 css::uno::Reference
<css::util::XModifyBroadcaster
> xBroadcaster(mxModel
, css::uno::UNO_QUERY_THROW
);
434 xBroadcaster
->removeModifyListener(mxListener
);
440 css::uno::Reference
<css::util::XModifyBroadcaster
> xBroadcasterNew(mxModel
, css::uno::UNO_QUERY_THROW
);
441 xBroadcasterNew
->addModifyListener(mxListener
);
443 css::uno::Reference
<css::view::XSelectionSupplier
> xSelectionSupplier(mxModel
->getCurrentController(), css::uno::UNO_QUERY
);
444 if (xSelectionSupplier
.is())
445 xSelectionSupplier
->addSelectionChangeListener(mxSelectionListener
);
448 void ChartSeriesPanel::selectionChanged(bool bCorrectType
)
454 IMPL_LINK(ChartSeriesPanel
, CheckBoxHdl
, Button
*, pButton
, void)
456 CheckBox
* pCheckBox
= static_cast<CheckBox
*>(pButton
);
457 bool bChecked
= pCheckBox
->IsChecked();
458 OUString aCID
= getCID(mxModel
);
459 if (pCheckBox
== mpCBLabel
.get())
460 setDataLabelVisible(mxModel
, aCID
, bChecked
);
461 else if (pCheckBox
== mpCBTrendline
.get())
462 setTrendlineVisible(mxModel
, aCID
, bChecked
);
463 else if (pCheckBox
== mpCBXError
.get())
464 setErrorBarVisible(mxModel
, aCID
, false, bChecked
);
465 else if (pCheckBox
== mpCBYError
.get())
466 setErrorBarVisible(mxModel
, aCID
, true, bChecked
);
469 IMPL_LINK_NOARG(ChartSeriesPanel
, RadioBtnHdl
, RadioButton
&, void)
471 OUString aCID
= getCID(mxModel
);
472 bool bChecked
= mpRBPrimaryAxis
->IsChecked();
474 setAttachedAxisType(mxModel
, aCID
, bChecked
);
477 IMPL_LINK_NOARG(ChartSeriesPanel
, ListBoxHdl
, ListBox
&, void)
479 OUString aCID
= getCID(mxModel
);
481 sal_Int32 nPos
= mpLBLabelPlacement
->GetSelectedEntryPos();
482 setDataLabelPlacement(mxModel
, aCID
, nPos
);
485 }} // end of namespace ::chart::sidebar
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */