diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /chart2/source/controller/dialogs | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2/source/controller/dialogs')
79 files changed, 17755 insertions, 0 deletions
diff --git a/chart2/source/controller/dialogs/ChangingResource.cxx b/chart2/source/controller/dialogs/ChangingResource.cxx new file mode 100644 index 000000000..c50f274da --- /dev/null +++ b/chart2/source/controller/dialogs/ChangingResource.cxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChangingResource.hxx> + +namespace chart +{ + +ResourceChangeListener::~ResourceChangeListener() +{ +} + +ChangingResource::ChangingResource() + : m_pChangeListener(nullptr) +{ +} +ChangingResource::~ChangingResource() +{ +} +void ChangingResource::setChangeListener( ResourceChangeListener* pListener ) +{ + m_pChangeListener = pListener; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx b/chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx new file mode 100644 index 000000000..91307afaa --- /dev/null +++ b/chart2/source/controller/dialogs/ChartResourceGroupDlgs.cxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartResourceGroupDlgs.hxx> +#include <ChartTypeDialogController.hxx> + +#include <strings.hrc> +#include <ResId.hxx> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +const sal_uInt16 CUBIC_SPLINE_POS = 0; +const sal_uInt16 B_SPLINE_POS = 1; + +SplinePropertiesDialog::SplinePropertiesDialog(weld::Window* pParent) + : GenericDialogController(pParent, "modules/schart/ui/smoothlinesdlg.ui", "SmoothLinesDialog") + , m_xLB_Spline_Type(m_xBuilder->weld_combo_box("SplineTypeComboBox")) + , m_xMF_SplineResolution(m_xBuilder->weld_spin_button("ResolutionSpinbutton")) + , m_xFT_SplineOrder(m_xBuilder->weld_label("PolynomialsLabel")) + , m_xMF_SplineOrder(m_xBuilder->weld_spin_button("PolynomialsSpinButton")) +{ + m_xDialog->set_title(SchResId(STR_DLG_SMOOTH_LINE_PROPERTIES)); + + m_xLB_Spline_Type->connect_changed(LINK(this, SplinePropertiesDialog, SplineTypeListBoxHdl)); +} + +void SplinePropertiesDialog::fillControls(const ChartTypeParameter& rParameter) +{ + switch (rParameter.eCurveStyle) + { + case CurveStyle_CUBIC_SPLINES: + m_xLB_Spline_Type->set_active(CUBIC_SPLINE_POS); + break; + case CurveStyle_B_SPLINES: + m_xLB_Spline_Type->set_active(B_SPLINE_POS); + break; + default: + m_xLB_Spline_Type->set_active(CUBIC_SPLINE_POS); + break; + } + m_xMF_SplineOrder->set_value(rParameter.nSplineOrder); + m_xMF_SplineResolution->set_value(rParameter.nCurveResolution); + + //dis/enabling + m_xFT_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS); + m_xMF_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS); +} + +void SplinePropertiesDialog::fillParameter(ChartTypeParameter& rParameter, bool bSmoothLines) +{ + if (!bSmoothLines) + rParameter.eCurveStyle = CurveStyle_LINES; + else if (m_xLB_Spline_Type->get_active() == CUBIC_SPLINE_POS) + rParameter.eCurveStyle = CurveStyle_CUBIC_SPLINES; + else if (m_xLB_Spline_Type->get_active() == B_SPLINE_POS) + rParameter.eCurveStyle = CurveStyle_B_SPLINES; + + rParameter.nCurveResolution = m_xMF_SplineResolution->get_value(); + rParameter.nSplineOrder = m_xMF_SplineOrder->get_value(); +} + +IMPL_LINK_NOARG(SplinePropertiesDialog, SplineTypeListBoxHdl, weld::ComboBox&, void) +{ + m_xFT_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS); + m_xMF_SplineOrder->set_sensitive(m_xLB_Spline_Type->get_active() == B_SPLINE_POS); +} + +SteppedPropertiesDialog::SteppedPropertiesDialog(weld::Window* pParent) + : GenericDialogController(pParent, "modules/schart/ui/steppedlinesdlg.ui", "SteppedLinesDialog") + , m_xRB_Start(m_xBuilder->weld_radio_button("step_start_rb")) + , m_xRB_End(m_xBuilder->weld_radio_button("step_end_rb")) + , m_xRB_CenterX(m_xBuilder->weld_radio_button("step_center_x_rb")) + , m_xRB_CenterY(m_xBuilder->weld_radio_button("step_center_y_rb")) +{ + m_xDialog->set_title(SchResId(STR_DLG_STEPPED_LINE_PROPERTIES)); +} + +void SteppedPropertiesDialog::fillControls(const ChartTypeParameter& rParameter) +{ + switch (rParameter.eCurveStyle) + { + case CurveStyle_STEP_END: + m_xRB_End->set_active(true); + break; + case CurveStyle_STEP_CENTER_X: + m_xRB_CenterX->set_active(true); + break; + case CurveStyle_STEP_CENTER_Y: + m_xRB_CenterY->set_active(true); + break; + default: // includes CurveStyle_STEP_START + m_xRB_Start->set_active(true); + break; + } +} +void SteppedPropertiesDialog::fillParameter(ChartTypeParameter& rParameter, bool bSteppedLines) +{ + if (!bSteppedLines) + rParameter.eCurveStyle = CurveStyle_LINES; + else if (m_xRB_CenterY->get_active()) + rParameter.eCurveStyle = CurveStyle_STEP_CENTER_Y; + else if (m_xRB_Start->get_active()) + rParameter.eCurveStyle = CurveStyle_STEP_START; + else if (m_xRB_End->get_active()) + rParameter.eCurveStyle = CurveStyle_STEP_END; + else if (m_xRB_CenterX->get_active()) + rParameter.eCurveStyle = CurveStyle_STEP_CENTER_X; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/ChartResourceGroups.cxx b/chart2/source/controller/dialogs/ChartResourceGroups.cxx new file mode 100644 index 000000000..199606abe --- /dev/null +++ b/chart2/source/controller/dialogs/ChartResourceGroups.cxx @@ -0,0 +1,359 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartResourceGroups.hxx> +#include <ChartResourceGroupDlgs.hxx> + +#include <strings.hrc> +#include <ResId.hxx> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +Dim3DLookResourceGroup::Dim3DLookResourceGroup(weld::Builder* pBuilder) + : ChangingResource() + , m_xCB_3DLook(pBuilder->weld_check_button("3dlook")) + , m_xLB_Scheme(pBuilder->weld_combo_box("3dscheme")) +{ + m_xCB_3DLook->connect_toggled(LINK(this, Dim3DLookResourceGroup, Dim3DLookCheckHdl)); + m_xLB_Scheme->connect_changed(LINK(this, Dim3DLookResourceGroup, SelectSchemeHdl)); +} + +void Dim3DLookResourceGroup::showControls(bool bShow) +{ + m_xCB_3DLook->set_visible(bShow); + m_xLB_Scheme->set_visible(bShow); +} + +void Dim3DLookResourceGroup::fillControls(const ChartTypeParameter& rParameter) +{ + m_xCB_3DLook->set_active(rParameter.b3DLook); + m_xLB_Scheme->set_sensitive(rParameter.b3DLook); + + if (rParameter.eThreeDLookScheme == ThreeDLookScheme_Simple) + m_xLB_Scheme->set_active(POS_3DSCHEME_SIMPLE); + else if (rParameter.eThreeDLookScheme == ThreeDLookScheme_Realistic) + m_xLB_Scheme->set_active(POS_3DSCHEME_REALISTIC); + else + m_xLB_Scheme->set_active(-1); +} + +void Dim3DLookResourceGroup::fillParameter(ChartTypeParameter& rParameter) +{ + rParameter.b3DLook = m_xCB_3DLook->get_active(); + const int nPos = m_xLB_Scheme->get_active(); + if (nPos == POS_3DSCHEME_SIMPLE) + rParameter.eThreeDLookScheme = ThreeDLookScheme_Simple; + else if (nPos == POS_3DSCHEME_REALISTIC) + rParameter.eThreeDLookScheme = ThreeDLookScheme_Realistic; + else + rParameter.eThreeDLookScheme = ThreeDLookScheme_Unknown; +} + +IMPL_LINK_NOARG(Dim3DLookResourceGroup, Dim3DLookCheckHdl, weld::ToggleButton&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +IMPL_LINK_NOARG(Dim3DLookResourceGroup, SelectSchemeHdl, weld::ComboBox&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +SortByXValuesResourceGroup::SortByXValuesResourceGroup(weld::Builder* pBuilder) + : ChangingResource() + , m_xCB_XValueSorting(pBuilder->weld_check_button("sort")) +{ + m_xCB_XValueSorting->connect_toggled( + LINK(this, SortByXValuesResourceGroup, SortByXValuesCheckHdl)); +} + +void SortByXValuesResourceGroup::showControls(bool bShow) +{ + m_xCB_XValueSorting->set_visible(bShow); +} + +void SortByXValuesResourceGroup::fillControls(const ChartTypeParameter& rParameter) +{ + m_xCB_XValueSorting->set_active(rParameter.bSortByXValues); +} + +void SortByXValuesResourceGroup::fillParameter(ChartTypeParameter& rParameter) +{ + rParameter.bSortByXValues = m_xCB_XValueSorting->get_active(); +} + +IMPL_LINK_NOARG(SortByXValuesResourceGroup, SortByXValuesCheckHdl, weld::ToggleButton&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +StackingResourceGroup::StackingResourceGroup(weld::Builder* pBuilder) + : ChangingResource() + , m_xCB_Stacked(pBuilder->weld_check_button("stack")) + , m_xRB_Stack_Y(pBuilder->weld_radio_button("ontop")) + , m_xRB_Stack_Y_Percent(pBuilder->weld_radio_button("percent")) + , m_xRB_Stack_Z(pBuilder->weld_radio_button("deep")) +{ + m_xCB_Stacked->connect_toggled(LINK(this, StackingResourceGroup, StackingEnableHdl)); + m_xRB_Stack_Y->connect_toggled(LINK(this, StackingResourceGroup, StackingChangeHdl)); + m_xRB_Stack_Y_Percent->connect_toggled(LINK(this, StackingResourceGroup, StackingChangeHdl)); + m_xRB_Stack_Z->connect_toggled(LINK(this, StackingResourceGroup, StackingChangeHdl)); +} + +void StackingResourceGroup::showControls(bool bShow) +{ + m_xCB_Stacked->set_visible(bShow); + m_xRB_Stack_Y->set_visible(bShow); + m_xRB_Stack_Y_Percent->set_visible(bShow); + m_xRB_Stack_Z->set_visible(false); +} + +void StackingResourceGroup::fillControls(const ChartTypeParameter& rParameter) +{ + m_xCB_Stacked->set_active( + rParameter.eStackMode != GlobalStackMode_NONE + && rParameter.eStackMode + != GlobalStackMode_STACK_Z); //todo remove this condition if z stacking radio button is really used + switch (rParameter.eStackMode) + { + case GlobalStackMode_STACK_Y: + m_xRB_Stack_Y->set_active(true); + break; + case GlobalStackMode_STACK_Y_PERCENT: + m_xRB_Stack_Y_Percent->set_active(true); + break; + case GlobalStackMode_STACK_Z: + //todo uncomment this condition if z stacking radio button is really used + /* + if( rParameter.b3DLook ) + m_xRB_Stack_Z->set_active(true); + else + */ + m_xRB_Stack_Y->set_active(true); + break; + default: + m_xRB_Stack_Y->set_active(true); + break; + } + //dis/enabling + m_xCB_Stacked->set_sensitive(!rParameter.bXAxisWithValues); + m_xRB_Stack_Y->set_sensitive(m_xCB_Stacked->get_active() && !rParameter.bXAxisWithValues); + m_xRB_Stack_Y_Percent->set_sensitive(m_xCB_Stacked->get_active() + && !rParameter.bXAxisWithValues); + m_xRB_Stack_Z->set_sensitive(m_xCB_Stacked->get_active() && rParameter.b3DLook); +} + +void StackingResourceGroup::fillParameter(ChartTypeParameter& rParameter) +{ + if (!m_xCB_Stacked->get_active()) + rParameter.eStackMode = GlobalStackMode_NONE; + else if (m_xRB_Stack_Y->get_active()) + rParameter.eStackMode = GlobalStackMode_STACK_Y; + else if (m_xRB_Stack_Y_Percent->get_active()) + rParameter.eStackMode = GlobalStackMode_STACK_Y_PERCENT; + else if (m_xRB_Stack_Z->get_active()) + rParameter.eStackMode = GlobalStackMode_STACK_Z; +} + +IMPL_LINK(StackingResourceGroup, StackingChangeHdl, weld::ToggleButton&, rRadio, void) +{ + //for each radio click there are coming two change events + //first uncheck of previous button -> ignore that call + //the second call gives the check of the new button + if (m_pChangeListener && rRadio.get_active()) + m_pChangeListener->stateChanged(); +} + +IMPL_LINK_NOARG(StackingResourceGroup, StackingEnableHdl, weld::ToggleButton&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +SplineResourceGroup::SplineResourceGroup(weld::Builder* pBuilder, weld::Window* pParent) + : ChangingResource() + , m_pParent(pParent) + , m_xFT_LineType(pBuilder->weld_label("linetypeft")) + , m_xLB_LineType(pBuilder->weld_combo_box("linetype")) + , m_xPB_DetailsDialog(pBuilder->weld_button("properties")) +{ + m_xLB_LineType->connect_changed(LINK(this, SplineResourceGroup, LineTypeChangeHdl)); +} + +SplinePropertiesDialog& SplineResourceGroup::getSplinePropertiesDialog() +{ + if (!m_xSplinePropertiesDialog) + { + m_xSplinePropertiesDialog.reset(new SplinePropertiesDialog(m_pParent)); + } + return *m_xSplinePropertiesDialog; +} + +SteppedPropertiesDialog& SplineResourceGroup::getSteppedPropertiesDialog() +{ + if (!m_xSteppedPropertiesDialog) + { + m_xSteppedPropertiesDialog.reset(new SteppedPropertiesDialog(m_pParent)); + } + return *m_xSteppedPropertiesDialog; +} + +void SplineResourceGroup::showControls(bool bShow) +{ + m_xFT_LineType->set_visible(bShow); + m_xLB_LineType->set_visible(bShow); + m_xPB_DetailsDialog->set_visible(bShow); +} + +void SplineResourceGroup::fillControls(const ChartTypeParameter& rParameter) +{ + switch (rParameter.eCurveStyle) + { + case CurveStyle_LINES: + m_xLB_LineType->set_active(POS_LINETYPE_STRAIGHT); + m_xPB_DetailsDialog->set_sensitive(false); + break; + case CurveStyle_CUBIC_SPLINES: + case CurveStyle_B_SPLINES: + m_xLB_LineType->set_active(POS_LINETYPE_SMOOTH); + m_xPB_DetailsDialog->set_sensitive(true); + m_xPB_DetailsDialog->connect_clicked( + LINK(this, SplineResourceGroup, SplineDetailsDialogHdl)); + m_xPB_DetailsDialog->set_tooltip_text(SchResId(STR_DLG_SMOOTH_LINE_PROPERTIES)); + getSplinePropertiesDialog().fillControls(rParameter); + break; + case CurveStyle_STEP_START: + case CurveStyle_STEP_END: + case CurveStyle_STEP_CENTER_X: + case CurveStyle_STEP_CENTER_Y: + m_xLB_LineType->set_active(POS_LINETYPE_STEPPED); + m_xPB_DetailsDialog->set_sensitive(true); + m_xPB_DetailsDialog->connect_clicked( + LINK(this, SplineResourceGroup, SteppedDetailsDialogHdl)); + m_xPB_DetailsDialog->set_tooltip_text(SchResId(STR_DLG_STEPPED_LINE_PROPERTIES)); + getSteppedPropertiesDialog().fillControls(rParameter); + break; + default: + m_xLB_LineType->set_active(-1); + m_xPB_DetailsDialog->set_sensitive(false); + } +} +void SplineResourceGroup::fillParameter(ChartTypeParameter& rParameter) +{ + switch (m_xLB_LineType->get_active()) + { + case POS_LINETYPE_SMOOTH: + getSplinePropertiesDialog().fillParameter(rParameter, true); + break; + case POS_LINETYPE_STEPPED: + getSteppedPropertiesDialog().fillParameter(rParameter, true); + break; + default: // includes POS_LINETYPE_STRAIGHT + rParameter.eCurveStyle = CurveStyle_LINES; + break; + } +} + +IMPL_LINK_NOARG(SplineResourceGroup, LineTypeChangeHdl, weld::ComboBox&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +IMPL_LINK_NOARG(SplineResourceGroup, SplineDetailsDialogHdl, weld::Button&, void) +{ + ChartTypeParameter aOldParameter; + getSplinePropertiesDialog().fillParameter(aOldParameter, + m_xLB_LineType->get_active() == POS_LINETYPE_SMOOTH); + + const sal_Int32 iOldLineTypePos = m_xLB_LineType->get_active(); + m_xLB_LineType->set_active(POS_LINETYPE_SMOOTH); + if (getSplinePropertiesDialog().run() == RET_OK) + { + if (m_pChangeListener) + m_pChangeListener->stateChanged(); + } + else + { + //restore old state: + m_xLB_LineType->set_active(iOldLineTypePos); + getSplinePropertiesDialog().fillControls(aOldParameter); + } +} + +IMPL_LINK_NOARG(SplineResourceGroup, SteppedDetailsDialogHdl, weld::Button&, void) +{ + ChartTypeParameter aOldParameter; + getSteppedPropertiesDialog().fillParameter(aOldParameter, m_xLB_LineType->get_active() + == POS_LINETYPE_STEPPED); + + const sal_Int32 iOldLineTypePos = m_xLB_LineType->get_active(); + m_xLB_LineType->set_active(POS_LINETYPE_STEPPED); + if (getSteppedPropertiesDialog().run() == RET_OK) + { + if (m_pChangeListener) + m_pChangeListener->stateChanged(); + } + else + { + //restore old state: + m_xLB_LineType->set_active(iOldLineTypePos); + getSteppedPropertiesDialog().fillControls(aOldParameter); + } +} + +GeometryResourceGroup::GeometryResourceGroup(weld::Builder* pBuilder) + : ChangingResource() + , m_aGeometryResources(pBuilder) +{ + m_aGeometryResources.connect_changed(LINK(this, GeometryResourceGroup, GeometryChangeHdl)); +} + +void GeometryResourceGroup::showControls(bool bShow) { m_aGeometryResources.set_visible(bShow); } + +void GeometryResourceGroup::fillControls(const ChartTypeParameter& rParameter) +{ + sal_uInt16 nGeometry3D = static_cast<sal_uInt16>(rParameter.nGeometry3D); + m_aGeometryResources.select(nGeometry3D); + m_aGeometryResources.set_sensitive(rParameter.b3DLook); +} + +void GeometryResourceGroup::fillParameter(ChartTypeParameter& rParameter) +{ + rParameter.nGeometry3D = 1; + int nSelected = m_aGeometryResources.get_selected_index(); + if (nSelected != -1) + rParameter.nGeometry3D = nSelected; +} + +IMPL_LINK_NOARG(GeometryResourceGroup, GeometryChangeHdl, weld::TreeView&, void) +{ + if (m_pChangeListener) + m_pChangeListener->stateChanged(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx new file mode 100644 index 000000000..6153c03ed --- /dev/null +++ b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx @@ -0,0 +1,1253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ChartTypeDialogController.hxx> +#include <ResId.hxx> +#include <strings.hrc> +#include <bitmaps.hlst> +#include <ChartModelHelper.hxx> +#include <DiagramHelper.hxx> +#include <ControllerLockGuard.hxx> +#include <AxisHelper.hxx> +#include <unonames.hxx> + +#include <com/sun/star/chart2/DataPointGeometry3D.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> + +#include <svtools/valueset.hxx> +#include <vcl/image.hxx> +#include <vcl/settings.hxx> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <tools/diagnose_ex.h> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +ChartTypeParameter::ChartTypeParameter() + : nSubTypeIndex( 1 ) + , bXAxisWithValues( false ) + , b3DLook( false ) + , bSymbols( true ) + , bLines( true ) + , eStackMode( GlobalStackMode_NONE ) + , eCurveStyle( CurveStyle_LINES ) + , nCurveResolution(20) + , nSplineOrder(3) + , nGeometry3D(DataPointGeometry3D::CUBOID) + , eThreeDLookScheme(ThreeDLookScheme_Realistic) + , bSortByXValues(false) + , mbRoundedEdge(false) +{ +} + +ChartTypeParameter::ChartTypeParameter( sal_Int32 SubTypeIndex, bool HasXAxisWithValues + , bool Is3DLook, GlobalStackMode nStackMode + , bool HasSymbols, bool HasLines + , CurveStyle nCurveStyle ) + : nSubTypeIndex( SubTypeIndex ) + , bXAxisWithValues( HasXAxisWithValues ) + , b3DLook( Is3DLook ) + , bSymbols( HasSymbols ) + , bLines( HasLines ) + , eStackMode( nStackMode ) + , eCurveStyle( nCurveStyle ) + , nCurveResolution(20) + , nSplineOrder(3) + , nGeometry3D(DataPointGeometry3D::CUBOID) + , eThreeDLookScheme(ThreeDLookScheme_Realistic) + , bSortByXValues(false) + , mbRoundedEdge(false) +{ +} + +bool ChartTypeParameter::mapsToSameService( const ChartTypeParameter& rParameter ) const +{ + return mapsToSimilarService( rParameter, 0 ); +} +bool ChartTypeParameter::mapsToSimilarService( const ChartTypeParameter& rParameter, sal_Int32 nTheHigherTheLess ) const +{ + sal_Int32 nMax=7; + if(nTheHigherTheLess>nMax) + return true; + if( bXAxisWithValues!=rParameter.bXAxisWithValues ) + return nTheHigherTheLess>nMax-1; + if( b3DLook!=rParameter.b3DLook ) + return nTheHigherTheLess>nMax-2; + if( eStackMode!=rParameter.eStackMode ) + return nTheHigherTheLess>nMax-3; + if( nSubTypeIndex!=rParameter.nSubTypeIndex ) + return nTheHigherTheLess>nMax-4; + if( bSymbols!=rParameter.bSymbols ) + return nTheHigherTheLess>nMax-5; + if( bLines!=rParameter.bLines ) + return nTheHigherTheLess>nMax-6; + return true; +} + +ChartTypeDialogController::ChartTypeDialogController() + : bSupportsXAxisWithValues(false) + , bSupports3D(true) +{ +} + +ChartTypeDialogController::~ChartTypeDialogController() +{ +} + +bool ChartTypeDialogController::isSubType( const OUString& rServiceName ) +{ + const tTemplateServiceChartTypeParameterMap& rTemplateMap = getTemplateMap(); + tTemplateServiceChartTypeParameterMap::const_iterator aIt( rTemplateMap.find( rServiceName )); + return aIt != rTemplateMap.end(); +} +ChartTypeParameter ChartTypeDialogController::getChartTypeParameterForService( + const OUString& rServiceName + , const uno::Reference< beans::XPropertySet >& xTemplateProps ) +{ + ChartTypeParameter aRet; + const tTemplateServiceChartTypeParameterMap& rTemplateMap = getTemplateMap(); + tTemplateServiceChartTypeParameterMap::const_iterator aIt( rTemplateMap.find( rServiceName )); + if( aIt != rTemplateMap.end()) + aRet = (*aIt).second; + if( xTemplateProps.is() ) + { + try + { + xTemplateProps->getPropertyValue( CHART_UNONAME_CURVE_STYLE ) >>= aRet.eCurveStyle; + xTemplateProps->getPropertyValue( CHART_UNONAME_CURVE_RESOLUTION ) >>= aRet.nCurveResolution; + xTemplateProps->getPropertyValue( CHART_UNONAME_SPLINE_ORDER ) >>= aRet.nSplineOrder; + } + catch( uno::Exception & ex ) + { + //not all templates need to support CurveStyle, CurveResolution or SplineOrder + ex.Context.is();//to have debug information without compilation warnings + } + + try + { + xTemplateProps->getPropertyValue( "Geometry3D" ) >>= aRet.nGeometry3D; + } + catch( uno::Exception& ex ) + { + //not all templates need to support Geometry3D + ex.Context.is();//to have debug information without compilation warnings + } + } + return aRet; +} +void ChartTypeDialogController::adjustSubTypeAndEnableControls( ChartTypeParameter& /*rParameter*/ ) +{ +} +void ChartTypeDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + switch( rParameter.nSubTypeIndex ) + { + case 2: + rParameter.eStackMode=GlobalStackMode_STACK_Y; + break; + case 3: + rParameter.eStackMode=GlobalStackMode_STACK_Y_PERCENT; + break; + case 4: + rParameter.eStackMode=GlobalStackMode_STACK_Z; + break; + default: + rParameter.eStackMode=GlobalStackMode_NONE; + break; + } +} +void ChartTypeDialogController::adjustParameterToMainType( ChartTypeParameter& rParameter ) +{ + bool bFoundSomeMatch=false; + + rParameter.bXAxisWithValues = bSupportsXAxisWithValues; + if( rParameter.b3DLook && !bSupports3D ) + rParameter.b3DLook = false; + if(!rParameter.b3DLook && rParameter.eStackMode==GlobalStackMode_STACK_Z) + rParameter.eStackMode = GlobalStackMode_NONE; + + const tTemplateServiceChartTypeParameterMap& rMap = getTemplateMap(); + for( sal_Int32 nMatchPrecision=0; nMatchPrecision<7 && !bFoundSomeMatch; nMatchPrecision++ ) + { + for (auto const& elem : rMap) + { + if( rParameter.mapsToSimilarService( elem.second, nMatchPrecision ) ) + { + //remind some values + ThreeDLookScheme aScheme = rParameter.eThreeDLookScheme; + sal_Int32 nCurveResolution = rParameter.nCurveResolution; + sal_Int32 nSplineOrder = rParameter.nSplineOrder; + CurveStyle eCurveStyle = rParameter.eCurveStyle; + sal_Int32 nGeometry3D = rParameter.nGeometry3D; + bool bSortByXValues = rParameter.bSortByXValues; + bool bRoundedEdge = rParameter.mbRoundedEdge; + + rParameter = elem.second; + + //some values should not be changed with charttype + rParameter.eThreeDLookScheme = aScheme; + rParameter.nCurveResolution = nCurveResolution; + rParameter.nSplineOrder =nSplineOrder; + rParameter.eCurveStyle = eCurveStyle; + rParameter.nGeometry3D = nGeometry3D; + rParameter.bSortByXValues = bSortByXValues; + rParameter.mbRoundedEdge = bRoundedEdge; + + bFoundSomeMatch = true; + break; + } + } + } + if(!bFoundSomeMatch) + { + if(!rMap.empty()) + rParameter = (*rMap.begin()).second; + else + rParameter = ChartTypeParameter(); + } +} +OUString ChartTypeDialogController::getServiceNameForParameter( const ChartTypeParameter& rParameter ) const +{ + ChartTypeParameter aParameter(rParameter); + if( aParameter.bXAxisWithValues ) + aParameter.eStackMode = GlobalStackMode_NONE; + if(!aParameter.b3DLook && aParameter.eStackMode==GlobalStackMode_STACK_Z) + aParameter.eStackMode = GlobalStackMode_NONE; + const tTemplateServiceChartTypeParameterMap& rMap = getTemplateMap(); + for (auto const& elem : rMap) + { + if( aParameter.mapsToSameService(elem.second) ) + return elem.first; + } + + OSL_FAIL( "ChartType not implemented yet - use fallback to similar type" ); + for( sal_Int32 nMatchPrecision=1; nMatchPrecision<8; nMatchPrecision++ ) + { + for (auto const& elem : rMap) + { + if( aParameter.mapsToSimilarService(elem.second, nMatchPrecision) ) + return elem.first; + } + } + return OUString(); +} +uno::Reference< XChartTypeTemplate > ChartTypeDialogController::getCurrentTemplate( + const ChartTypeParameter& rParameter + , const uno::Reference< lang::XMultiServiceFactory >& xTemplateManager ) const +{ + uno::Reference< XChartTypeTemplate > xTemplate; + + OUString aServiceName( getServiceNameForParameter( rParameter ) ); + if(!aServiceName.isEmpty()) + { + xTemplate.set( xTemplateManager->createInstance( aServiceName ), uno::UNO_QUERY ); + if(xTemplate.is()) + { + uno::Reference< beans::XPropertySet > xTemplateProps( xTemplate, uno::UNO_QUERY ); + if(xTemplateProps.is()) + { + try + { + xTemplateProps->setPropertyValue( CHART_UNONAME_CURVE_STYLE , uno::Any(rParameter.eCurveStyle) ); + xTemplateProps->setPropertyValue( CHART_UNONAME_CURVE_RESOLUTION , uno::Any(rParameter.nCurveResolution) ); + xTemplateProps->setPropertyValue( CHART_UNONAME_SPLINE_ORDER , uno::Any(rParameter.nSplineOrder) ); + } + catch( uno::Exception & ex ) + { + //not all templates need to support CurveStyle, CurveResolution or SplineOrder + ex.Context.is();//to have debug information without compilation warnings + } + try + { + xTemplateProps->setPropertyValue( "Geometry3D" , uno::Any(rParameter.nGeometry3D) ); + } + catch( uno::Exception & ex ) + { + //not all templates need to support Geometry3D + ex.Context.is();//to have debug information without compilation warnings + } + + try + { + setTemplateProperties( xTemplateProps ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + } + return xTemplate; +} + +void ChartTypeDialogController::commitToModel( const ChartTypeParameter& rParameter + , const uno::Reference< XChartDocument >& xChartModel ) +{ + uno::Reference< lang::XMultiServiceFactory > xTemplateManager( xChartModel->getChartTypeManager(), uno::UNO_QUERY ); + uno::Reference< XChartTypeTemplate > xTemplate( getCurrentTemplate( rParameter, xTemplateManager ) ); + if(!xTemplate.is()) + return; + + // locked controllers + ControllerLockGuardUNO aCtrlLockGuard( xChartModel ); + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartModel ); + DiagramHelper::tTemplateWithServiceName aTemplateWithService( + DiagramHelper::getTemplateForDiagram( xDiagram, xTemplateManager )); + if( aTemplateWithService.first.is()) + aTemplateWithService.first->resetStyles( xDiagram ); + xTemplate->changeDiagram( xDiagram ); + if( AllSettings::GetMathLayoutRTL() ) + AxisHelper::setRTLAxisLayout( AxisHelper::getCoordinateSystemByIndex( xDiagram, 0 ) ); + if( rParameter.b3DLook ) + ThreeDHelper::setScheme( xDiagram, rParameter.eThreeDLookScheme ); + + uno::Reference<beans::XPropertySet> xDiaProp(xDiagram, uno::UNO_QUERY); + if (xDiaProp.is()) + { + xDiaProp->setPropertyValue(CHART_UNONAME_SORT_BY_XVALUES, uno::Any(rParameter.bSortByXValues)); + } +} +void ChartTypeDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ ) +{ + rSubTypeList.Clear(); +} +bool ChartTypeDialogController::shouldShow_3DLookControl() const +{ + return false; +} +bool ChartTypeDialogController::shouldShow_StackingControl() const +{ + return false; +} +bool ChartTypeDialogController::shouldShow_SplineControl() const +{ + return false; +} +bool ChartTypeDialogController::shouldShow_GeometryControl() const +{ + return false; +} +bool ChartTypeDialogController::shouldShow_SortByXValuesResourceGroup() const +{ + return false; +} + +void ChartTypeDialogController::showExtraControls(weld::Builder* /*pBuilder*/) +{ +} +void ChartTypeDialogController::hideExtraControls() const +{ +} +void ChartTypeDialogController::fillExtraControls( const uno::Reference< XChartDocument >& /*xChartModel*/ + , const uno::Reference< beans::XPropertySet >& /*xTemplateProps*/ ) const +{ +} +void ChartTypeDialogController::setTemplateProperties( const uno::Reference< beans::XPropertySet >& /*xTemplateProps*/ ) const +{ +} + +ColumnOrBarChartDialogController_Base::ColumnOrBarChartDialogController_Base() + : ChartTypeDialogController() +{ +} +ColumnOrBarChartDialogController_Base::~ColumnOrBarChartDialogController_Base() +{ +} +bool ColumnOrBarChartDialogController_Base::shouldShow_3DLookControl() const +{ + return true; +} +bool ColumnOrBarChartDialogController_Base::shouldShow_GeometryControl() const +{ + return true; +} +void ColumnOrBarChartDialogController_Base::adjustSubTypeAndEnableControls( ChartTypeParameter& rParameter ) +{ + if(rParameter.nSubTypeIndex>3 && !rParameter.b3DLook) + { + rParameter.nSubTypeIndex=1; + } +} +ColumnChartDialogController::ColumnChartDialogController() +{ +} +ColumnChartDialogController::~ColumnChartDialogController() +{ +} +OUString ColumnChartDialogController::getName() +{ + return SchResId(STR_TYPE_COLUMN); +} + +OUString ColumnChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_COLUMN); +} + +const tTemplateServiceChartTypeParameterMap& ColumnChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Column" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE)}, + {"com.sun.star.chart2.template.StackedColumn" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)}, + {"com.sun.star.chart2.template.PercentStackedColumn" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT)}, + {"com.sun.star.chart2.template.ThreeDColumnFlat" , ChartTypeParameter(1,false,true,GlobalStackMode_NONE)}, + {"com.sun.star.chart2.template.StackedThreeDColumnFlat" , ChartTypeParameter(2,false,true,GlobalStackMode_STACK_Y)}, + {"com.sun.star.chart2.template.PercentStackedThreeDColumnFlat" , ChartTypeParameter(3,false,true,GlobalStackMode_STACK_Y_PERCENT)}, + {"com.sun.star.chart2.template.ThreeDColumnDeep" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Z)}}; + return s_aTemplateMap; +} +void ColumnChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter ) +{ + rSubTypeList.Clear(); + + if( rParameter.b3DLook ) + { + switch(rParameter.nGeometry3D) + { + case DataPointGeometry3D::CYLINDER: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_SAEULE_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_SAEULE_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_SAEULE_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_SAEULE_3D_4)); + break; + case DataPointGeometry3D::CONE: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_KEGEL_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_KEGEL_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_KEGEL_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_KEGEL_3D_4)); + break; + case DataPointGeometry3D::PYRAMID: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_PYRAMID_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_PYRAMID_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_PYRAMID_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_PYRAMID_3D_4)); + break; + default: //DataPointGeometry3D::CUBOID: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_COLUMNS_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_COLUMNS_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_COLUMNS_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_COLUMNS_3D)); + break; + } + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_COLUMNS_2D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_COLUMNS_2D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_COLUMNS_2D_3)); + } + + rSubTypeList.SetItemText( 1, SchResId( STR_NORMAL ) ); + rSubTypeList.SetItemText( 2, SchResId( STR_STACKED ) ); + rSubTypeList.SetItemText( 3, SchResId( STR_PERCENT ) ); + rSubTypeList.SetItemText( 4, SchResId( STR_DEEP ) ); +} + +BarChartDialogController::BarChartDialogController() +{ +} + +BarChartDialogController::~BarChartDialogController() +{ +} + +OUString BarChartDialogController::getName() +{ + return SchResId(STR_TYPE_BAR); +} + +OUString BarChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_BAR); +} + +const tTemplateServiceChartTypeParameterMap& BarChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Bar" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE)}, + {"com.sun.star.chart2.template.StackedBar" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)}, + {"com.sun.star.chart2.template.PercentStackedBar" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT)}, + {"com.sun.star.chart2.template.ThreeDBarFlat" , ChartTypeParameter(1,false,true,GlobalStackMode_NONE)}, + {"com.sun.star.chart2.template.StackedThreeDBarFlat" , ChartTypeParameter(2,false,true,GlobalStackMode_STACK_Y)}, + {"com.sun.star.chart2.template.PercentStackedThreeDBarFlat" , ChartTypeParameter(3,false,true,GlobalStackMode_STACK_Y_PERCENT)}, + {"com.sun.star.chart2.template.ThreeDBarDeep" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Z)}}; + return s_aTemplateMap; +} +void BarChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter ) +{ + rSubTypeList.Clear(); + + if( rParameter.b3DLook ) + { + switch(rParameter.nGeometry3D) + { + case DataPointGeometry3D::CYLINDER: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_ROEHRE_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_ROEHRE_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_ROEHRE_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_ROEHRE_3D_4)); + break; + case DataPointGeometry3D::CONE: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_KEGELQ_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_KEGELQ_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_KEGELQ_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_KEGELQ_3D_4)); + break; + case DataPointGeometry3D::PYRAMID: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_PYRAMIDQ_3D_4)); + break; + default: //DataPointGeometry3D::CUBOID: + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_BARS_3D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_BARS_3D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_BARS_3D_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_BARS_3D)); + break; + } + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_BARS_2D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_BARS_2D_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_BARS_2D_3)); + } + rSubTypeList.SetItemText( 1, SchResId( STR_NORMAL ) ); + rSubTypeList.SetItemText( 2, SchResId( STR_STACKED ) ); + rSubTypeList.SetItemText( 3, SchResId( STR_PERCENT ) ); + rSubTypeList.SetItemText( 4, SchResId( STR_DEEP ) ); +} + +PieChartDialogController::PieChartDialogController() +{ +} + +PieChartDialogController::~PieChartDialogController() +{ +} + +OUString PieChartDialogController::getName() +{ + return SchResId(STR_TYPE_PIE); +} + +OUString PieChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_PIE); +} + +const tTemplateServiceChartTypeParameterMap& PieChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Pie" , ChartTypeParameter(1,false,false)}, + {"com.sun.star.chart2.template.PieAllExploded" , ChartTypeParameter(2,false,false)}, + {"com.sun.star.chart2.template.Donut" , ChartTypeParameter(3,false,false)}, + {"com.sun.star.chart2.template.DonutAllExploded" , ChartTypeParameter(4,false,false)}, + {"com.sun.star.chart2.template.ThreeDPie" , ChartTypeParameter(1,false,true)}, + {"com.sun.star.chart2.template.ThreeDPieAllExploded" , ChartTypeParameter(2,false,true)}, + {"com.sun.star.chart2.template.ThreeDDonut" , ChartTypeParameter(3,false,true)}, + {"com.sun.star.chart2.template.ThreeDDonutAllExploded" , ChartTypeParameter(4,false,true)}}; + return s_aTemplateMap; +} +void PieChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter ) +{ + rSubTypeList.Clear(); + + if( rParameter.b3DLook ) + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_CIRCLES_3D)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_CIRCLES_3D_EXPLODED)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_DONUT_3D)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_DONUT_3D_EXPLODED)); + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_CIRCLES_2D)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_CIRCLES_2D_EXPLODED)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_DONUT_2D)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_DONUT_2D_EXPLODED)); + } + rSubTypeList.SetItemText( 1, SchResId( STR_NORMAL ) ); + rSubTypeList.SetItemText( 2, SchResId( STR_PIE_EXPLODED ) ); + rSubTypeList.SetItemText( 3, SchResId( STR_DONUT ) ); + rSubTypeList.SetItemText( 4, SchResId( STR_DONUT_EXPLODED ) ); +} + +bool PieChartDialogController::shouldShow_3DLookControl() const +{ + return true; +} + +void PieChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + if(rParameter.eStackMode==GlobalStackMode_STACK_Z) + rParameter.eStackMode = GlobalStackMode_NONE; +} + +LineChartDialogController::LineChartDialogController() +{ +} + +LineChartDialogController::~LineChartDialogController() +{ +} + +OUString LineChartDialogController::getName() +{ + return SchResId(STR_TYPE_LINE); +} + +OUString LineChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_LINE); +} + +const tTemplateServiceChartTypeParameterMap& LineChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Symbol" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE,true,false)}, + {"com.sun.star.chart2.template.StackedSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y,true,false)}, + {"com.sun.star.chart2.template.PercentStackedSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y_PERCENT,true,false)}, + {"com.sun.star.chart2.template.LineSymbol" , ChartTypeParameter(2,false,false,GlobalStackMode_NONE,true,true)}, + {"com.sun.star.chart2.template.StackedLineSymbol" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y,true,true)}, + {"com.sun.star.chart2.template.PercentStackedLineSymbol" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y_PERCENT,true,true)}, + {"com.sun.star.chart2.template.Line" , ChartTypeParameter(3,false,false,GlobalStackMode_NONE,false,true)}, + {"com.sun.star.chart2.template.StackedLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y,false,true)}, + {"com.sun.star.chart2.template.PercentStackedLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT,false,true)}, + {"com.sun.star.chart2.template.StackedThreeDLine" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Y,false,true)}, + {"com.sun.star.chart2.template.PercentStackedThreeDLine" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Y_PERCENT,false,true)}, + {"com.sun.star.chart2.template.ThreeDLineDeep" , ChartTypeParameter(4,false,true,GlobalStackMode_STACK_Z,false,true)}}; + return s_aTemplateMap; +} +void LineChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter ) +{ + rSubTypeList.Clear(); + + switch( rParameter.eCurveStyle ) + { + case CurveStyle_CUBIC_SPLINES: + case CurveStyle_B_SPLINES: + if( rParameter.eStackMode == GlobalStackMode_NONE || rParameter.eStackMode == GlobalStackMode_STACK_Z ) + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XCATEGORY)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XCATEGORY_SMOOTH)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XCATEGORY_SMOOTH)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XCATEGORY_SMOOTH)); + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_STACKED)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_STACKED_SMOOTH)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_STACKED_SMOOTH)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_STACKED_SMOOTH)); + } + break; + case CurveStyle_STEP_START: + case CurveStyle_STEP_END: + case CurveStyle_STEP_CENTER_X: + case CurveStyle_STEP_CENTER_Y: + if( rParameter.eStackMode == GlobalStackMode_NONE || rParameter.eStackMode == GlobalStackMode_STACK_Z ) + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XCATEGORY)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XCATEGORY_STEPPED)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XCATEGORY_STEPPED)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XCATEGORY_STEPPED)); + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_STACKED)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_STACKED_STEPPED)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_STACKED_STEPPED)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_STACKED_STEPPED)); + } + break; + default: // includes CurveStyle_LINES + //direct lines + if( rParameter.eStackMode == GlobalStackMode_NONE || rParameter.eStackMode == GlobalStackMode_STACK_Z ) + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XCATEGORY)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XCATEGORY)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XCATEGORY)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XCATEGORY)); + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_STACKED)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_STACKED)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_STACKED)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_STACKED)); + } + } + + rSubTypeList.SetItemText( 1, SchResId( STR_POINTS_ONLY ) ); + rSubTypeList.SetItemText( 2, SchResId( STR_POINTS_AND_LINES ) ); + rSubTypeList.SetItemText( 3, SchResId( STR_LINES_ONLY ) ); + rSubTypeList.SetItemText( 4, SchResId( STR_LINES_3D ) ); +} +bool LineChartDialogController::shouldShow_StackingControl() const +{ + return true; +} +bool LineChartDialogController::shouldShow_SplineControl() const +{ + return true; +} +void LineChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.b3DLook = false; + + switch( rParameter.nSubTypeIndex ) + { + case 2: + rParameter.bSymbols = true; + rParameter.bLines = true; + break; + case 3: + rParameter.bSymbols = false; + rParameter.bLines = true; + break; + case 4: + rParameter.bSymbols = false; + rParameter.bLines = true; + rParameter.b3DLook = true; + if( rParameter.eStackMode == GlobalStackMode_NONE ) + rParameter.eStackMode = GlobalStackMode_STACK_Z; + break; + default: + rParameter.bSymbols = true; + rParameter.bLines = false; + break; + } + + if(!rParameter.b3DLook && rParameter.eStackMode == GlobalStackMode_STACK_Z ) + rParameter.eStackMode = GlobalStackMode_NONE; +} +void LineChartDialogController::adjustParameterToMainType( ChartTypeParameter& rParameter ) +{ + if( rParameter.b3DLook && rParameter.eStackMode == GlobalStackMode_NONE ) + rParameter.eStackMode = GlobalStackMode_STACK_Z; + + ChartTypeDialogController::adjustParameterToMainType( rParameter ); +} + +XYChartDialogController::XYChartDialogController() +{ + bSupportsXAxisWithValues = true; +} + +XYChartDialogController::~XYChartDialogController() +{ +} + +OUString XYChartDialogController::getName() +{ + return SchResId(STR_TYPE_XY); +} + +OUString XYChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_XY); +} + +const tTemplateServiceChartTypeParameterMap& XYChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.ScatterSymbol" , ChartTypeParameter(1,true,false,GlobalStackMode_NONE,true,false)}, + {"com.sun.star.chart2.template.ScatterLineSymbol" , ChartTypeParameter(2,true,false,GlobalStackMode_NONE,true,true)}, + {"com.sun.star.chart2.template.ScatterLine" , ChartTypeParameter(3,true,false,GlobalStackMode_NONE,false,true)}, + {"com.sun.star.chart2.template.ThreeDScatter" , ChartTypeParameter(4,true,true,GlobalStackMode_NONE,false,true)}}; + return s_aTemplateMap; +} + +void XYChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter ) +{ + rSubTypeList.Clear(); + + switch (rParameter.eCurveStyle) + { + case CurveStyle_CUBIC_SPLINES: + case CurveStyle_B_SPLINES: + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XVALUES)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XVALUES_SMOOTH)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XVALUES_SMOOTH)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XVALUES_SMOOTH)); + break; + } + case CurveStyle_STEP_START: + case CurveStyle_STEP_END: + case CurveStyle_STEP_CENTER_X: + case CurveStyle_STEP_CENTER_Y: + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XVALUES)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XVALUES_STEPPED)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XVALUES_STEPPED)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XVALUES_STEPPED)); + break; + } + default: // includes CurveStyle_LINES + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_POINTS_XVALUES)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_LINE_P_XVALUES)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_LINE_O_XVALUES)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_LINE3D_XVALUES)); + } + + rSubTypeList.SetItemText( 1, SchResId( STR_POINTS_ONLY ) ); + rSubTypeList.SetItemText( 2, SchResId( STR_POINTS_AND_LINES ) ); + rSubTypeList.SetItemText( 3, SchResId( STR_LINES_ONLY ) ); + rSubTypeList.SetItemText( 4, SchResId( STR_LINES_3D ) ); +} +bool XYChartDialogController::shouldShow_SplineControl() const +{ + return true; +} +bool XYChartDialogController::shouldShow_SortByXValuesResourceGroup() const +{ + return true; +} +void XYChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.eStackMode=GlobalStackMode_NONE; + rParameter.b3DLook = false; + rParameter.bXAxisWithValues = true; + + switch( rParameter.nSubTypeIndex ) + { + case 2: + rParameter.bSymbols = true; + rParameter.bLines = true; + break; + case 3: + rParameter.bSymbols = false; + rParameter.bLines = true; + break; + case 4: + rParameter.bSymbols = false; + rParameter.bLines = true; + rParameter.b3DLook = true; + rParameter.eStackMode=GlobalStackMode_STACK_Z; + break; + default: + rParameter.bSymbols = true; + rParameter.bLines = false; + break; + } +} + +AreaChartDialogController::AreaChartDialogController() +{ +} + +AreaChartDialogController::~AreaChartDialogController() +{ +} + +OUString AreaChartDialogController::getName() +{ + return SchResId(STR_TYPE_AREA); +} + +OUString AreaChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_AREA); +} + +bool AreaChartDialogController::shouldShow_3DLookControl() const +{ + return true; +} + +const tTemplateServiceChartTypeParameterMap& AreaChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Area" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE)}, + {"com.sun.star.chart2.template.ThreeDArea" , ChartTypeParameter(1,false,true,GlobalStackMode_STACK_Z)}, + {"com.sun.star.chart2.template.StackedArea" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)}, + {"com.sun.star.chart2.template.StackedThreeDArea" , ChartTypeParameter(2,false,true,GlobalStackMode_STACK_Y)}, + {"com.sun.star.chart2.template.PercentStackedArea" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT)}, + {"com.sun.star.chart2.template.PercentStackedThreeDArea" , ChartTypeParameter(3,false,true,GlobalStackMode_STACK_Y_PERCENT)}}; + return s_aTemplateMap; +} + +void AreaChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter ) +{ + rSubTypeList.Clear(); + + if( rParameter.b3DLook ) + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_AREAS_3D)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_AREAS_3D_1)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_AREAS_3D_2)); + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_AREAS_2D_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_AREAS_2D)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_AREAS_2D_3)); + } + + rSubTypeList.SetItemText( 1, SchResId( rParameter.b3DLook ? STR_DEEP : STR_NORMAL ) ); + rSubTypeList.SetItemText( 2, SchResId( STR_STACKED ) ); + rSubTypeList.SetItemText( 3, SchResId( STR_PERCENT ) ); +} +void AreaChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.eCurveStyle = CurveStyle_LINES; + + if( rParameter.nSubTypeIndex>3 ) + rParameter.nSubTypeIndex = 1; + switch( rParameter.nSubTypeIndex ) + { + case 2: + rParameter.eStackMode=GlobalStackMode_STACK_Y; + break; + case 3: + rParameter.eStackMode=GlobalStackMode_STACK_Y_PERCENT; + break; + default: + if( rParameter.b3DLook ) + rParameter.eStackMode=GlobalStackMode_STACK_Z; + else + rParameter.eStackMode=GlobalStackMode_NONE; + break; + } +} +void AreaChartDialogController::adjustParameterToMainType( ChartTypeParameter& rParameter ) +{ + if( rParameter.b3DLook && rParameter.eStackMode == GlobalStackMode_NONE ) + rParameter.eStackMode = GlobalStackMode_STACK_Z; + + ChartTypeDialogController::adjustParameterToMainType( rParameter ); +} + +NetChartDialogController::NetChartDialogController() +{ + bSupports3D = false; +} + +NetChartDialogController::~NetChartDialogController() +{ +} + +OUString NetChartDialogController::getName() +{ + return SchResId(STR_TYPE_NET); +} + +OUString NetChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_NET); +} + +bool NetChartDialogController::shouldShow_StackingControl() const +{ + return true; +} + +const tTemplateServiceChartTypeParameterMap& NetChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + //@todo need templates with symbols only + {"com.sun.star.chart2.template.NetSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_NONE,true,false)}, + {"com.sun.star.chart2.template.StackedNetSymbol" , ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y,true,false)}, + {"com.sun.star.chart2.template.PercentStackedNetSymbol" ,ChartTypeParameter(1,false,false,GlobalStackMode_STACK_Y_PERCENT,true,false)}, + + {"com.sun.star.chart2.template.Net" , ChartTypeParameter(2,false,false,GlobalStackMode_NONE,true,true)}, + {"com.sun.star.chart2.template.StackedNet" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y,true,true)}, + {"com.sun.star.chart2.template.PercentStackedNet" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y_PERCENT,true,true)}, + + {"com.sun.star.chart2.template.NetLine" , ChartTypeParameter(3,false,false,GlobalStackMode_NONE,false,true)}, + {"com.sun.star.chart2.template.StackedNetLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y,false,true)}, + {"com.sun.star.chart2.template.PercentStackedNetLine" , ChartTypeParameter(3,false,false,GlobalStackMode_STACK_Y_PERCENT,false,true)}, + + {"com.sun.star.chart2.template.FilledNet" , ChartTypeParameter(4,false,false,GlobalStackMode_NONE,false,false)}, + {"com.sun.star.chart2.template.StackedFilledNet" , ChartTypeParameter(4,false,false,GlobalStackMode_STACK_Y,false,false)}, + {"com.sun.star.chart2.template.PercentStackedFilledNet" ,ChartTypeParameter(4,false,false,GlobalStackMode_STACK_Y_PERCENT,false,false)}}; + return s_aTemplateMap; +} +void NetChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& rParameter ) +{ + rSubTypeList.Clear(); + + if( rParameter.eStackMode == GlobalStackMode_NONE ) + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_NET_SYMB)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_NET_LINESYMB)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_NET)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_NET_FILL)); + } + else + { + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_NET_SYMB_STACK)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_NET_LINESYMB_STACK)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_NET_STACK)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_NET_FILL_STACK)); + } + + rSubTypeList.SetItemText( 1, SchResId( STR_POINTS_ONLY ) ); + rSubTypeList.SetItemText( 2, SchResId( STR_POINTS_AND_LINES ) ); + rSubTypeList.SetItemText( 3, SchResId( STR_LINES_ONLY ) ); + rSubTypeList.SetItemText( 4, SchResId( STR_FILLED ) ); +} +void NetChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.b3DLook = false; + if(rParameter.eStackMode==GlobalStackMode_STACK_Z) + rParameter.eStackMode = GlobalStackMode_NONE; + + switch( rParameter.nSubTypeIndex ) + { + case 2: + rParameter.bSymbols = true; + rParameter.bLines = true; + break; + case 3: + rParameter.bSymbols = false; + rParameter.bLines = true; + break; + case 4: + rParameter.bSymbols = false; + rParameter.bLines = false; + break; + default: + rParameter.bSymbols = true; + rParameter.bLines = false; + break; + } +} +StockChartDialogController::StockChartDialogController() +{ + bSupports3D = false; +} + +StockChartDialogController::~StockChartDialogController() +{ +} + +OUString StockChartDialogController::getName() +{ + return SchResId(STR_TYPE_STOCK); +} + +OUString StockChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_STOCK); +} + +const tTemplateServiceChartTypeParameterMap& StockChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.StockLowHighClose" , ChartTypeParameter(1)}, + {"com.sun.star.chart2.template.StockOpenLowHighClose" , ChartTypeParameter(2)}, + {"com.sun.star.chart2.template.StockVolumeLowHighClose" , ChartTypeParameter(3)}, + {"com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ,ChartTypeParameter(4)}}; + return s_aTemplateMap; +} + +void StockChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ ) +{ + rSubTypeList.Clear(); + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_STOCK_1)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_STOCK_2)); + rSubTypeList.InsertItem(3, Image(StockImage::Yes, BMP_STOCK_3)); + rSubTypeList.InsertItem(4, Image(StockImage::Yes, BMP_STOCK_4)); + + rSubTypeList.SetItemText( 1, SchResId(STR_STOCK_1) ); + rSubTypeList.SetItemText( 2, SchResId(STR_STOCK_2) ); + rSubTypeList.SetItemText( 3, SchResId(STR_STOCK_3) ); + rSubTypeList.SetItemText( 4, SchResId(STR_STOCK_4) ); +} + +void StockChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.b3DLook = false; + rParameter.eStackMode = GlobalStackMode_NONE; +} + +CombiColumnLineChartDialogController::CombiColumnLineChartDialogController() +{ + bSupports3D = false; +} + +OUString CombiColumnLineChartDialogController::getName() +{ + return SchResId(STR_TYPE_COMBI_COLUMN_LINE); +} + +OUString CombiColumnLineChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_COLUMN_LINE); +} + +const tTemplateServiceChartTypeParameterMap& CombiColumnLineChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.ColumnWithLine" , ChartTypeParameter(1)}, + {"com.sun.star.chart2.template.StackedColumnWithLine" , ChartTypeParameter(2,false,false,GlobalStackMode_STACK_Y)}}; + return s_aTemplateMap; +} + +void CombiColumnLineChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ ) +{ + rSubTypeList.Clear(); + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_COLUMN_LINE)); + rSubTypeList.InsertItem(2, Image(StockImage::Yes, BMP_COLUMN_LINE_STACKED)); + + rSubTypeList.SetItemText(1, SchResId(STR_LINE_COLUMN)); + rSubTypeList.SetItemText(2, SchResId(STR_LINE_STACKEDCOLUMN)); +} + +void CombiColumnLineChartDialogController::showExtraControls(weld::Builder* pBuilder) +{ + if (!m_xFT_NumberOfLines) + { + m_xFT_NumberOfLines = pBuilder->weld_label("nolinesft"); + } + if (!m_xMF_NumberOfLines) + { + m_xMF_NumberOfLines = pBuilder->weld_spin_button("nolines"); + + m_xMF_NumberOfLines->set_increments(1, 10); + m_xMF_NumberOfLines->set_range(1, 100); + + m_xMF_NumberOfLines->connect_value_changed( LINK( this, CombiColumnLineChartDialogController, ChangeLineCountHdl ) ); + } + + m_xFT_NumberOfLines->show(); + m_xMF_NumberOfLines->show(); +} + +void CombiColumnLineChartDialogController::hideExtraControls() const +{ + if (m_xFT_NumberOfLines) + m_xFT_NumberOfLines->hide(); + if (m_xMF_NumberOfLines) + m_xMF_NumberOfLines->hide(); +} + +void CombiColumnLineChartDialogController::fillExtraControls( + const uno::Reference< XChartDocument >& xChartModel + , const uno::Reference< beans::XPropertySet >& xTemplateProps ) const +{ + if (!m_xMF_NumberOfLines) + return; + + uno::Reference< frame::XModel > xModel = xChartModel; + + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xModel ); + if(!xDiagram.is()) + return; + + sal_Int32 nNumLines = 0; + + if(xTemplateProps.is()) + { + try + { + xTemplateProps->getPropertyValue( "NumberOfLines" ) >>= nNumLines; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + if( nNumLines < 0 ) + nNumLines = 0; + m_xMF_NumberOfLines->set_value(nNumLines); + + sal_Int32 nMaxLines = ChartModelHelper::getDataSeries( xModel ).size() - 1; + if( nMaxLines < 0 ) + nMaxLines = 0; + m_xMF_NumberOfLines->set_max(nMaxLines); +} +void CombiColumnLineChartDialogController::setTemplateProperties( const uno::Reference< beans::XPropertySet >& xTemplateProps ) const +{ + if( xTemplateProps.is() ) + { + sal_Int32 nNumLines = m_xMF_NumberOfLines->get_value(); + xTemplateProps->setPropertyValue( "NumberOfLines" , uno::Any(nNumLines) ); + } +} + +IMPL_LINK_NOARG(CombiColumnLineChartDialogController, ChangeLineCountHdl, weld::SpinButton&, void) +{ + if( m_pChangeListener ) + m_pChangeListener->stateChanged(); +} +void CombiColumnLineChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.b3DLook = false; + if(rParameter.eStackMode==GlobalStackMode_STACK_Z) + rParameter.eStackMode = GlobalStackMode_NONE; + + switch( rParameter.nSubTypeIndex ) + { + case 2: + rParameter.eStackMode=GlobalStackMode_STACK_Y; + break; + default: + rParameter.eStackMode=GlobalStackMode_NONE; + break; + } +} + +BubbleChartDialogController::BubbleChartDialogController() +{ +} + +BubbleChartDialogController::~BubbleChartDialogController() +{ +} + +OUString BubbleChartDialogController::getName() +{ + return SchResId(STR_TYPE_BUBBLE); +} + +OUString BubbleChartDialogController::getImage() +{ + return OUStringLiteral(BMP_TYPE_BUBBLE); +} + +const tTemplateServiceChartTypeParameterMap& BubbleChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap s_aTemplateMap{ + {"com.sun.star.chart2.template.Bubble" , ChartTypeParameter(1,true)}}; + return s_aTemplateMap; +} +void BubbleChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, const ChartTypeParameter& /*rParameter*/ ) +{ + rSubTypeList.Clear(); + rSubTypeList.InsertItem(1, Image(StockImage::Yes, BMP_BUBBLE_1)); + + rSubTypeList.SetItemText( 1, SchResId(STR_BUBBLE_1) ); +} +void BubbleChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.b3DLook = false; + rParameter.eStackMode = GlobalStackMode_NONE; +} +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/DataBrowser.cxx b/chart2/source/controller/dialogs/DataBrowser.cxx new file mode 100644 index 000000000..d772905dc --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowser.cxx @@ -0,0 +1,1389 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svl/zforlist.hxx> + +#include "DataBrowser.hxx" +#include "DataBrowserModel.hxx" +#include <strings.hrc> +#include <DataSeriesHelper.hxx> +#include <DiagramHelper.hxx> +#include <CommonConverters.hxx> +#include <NumberFormatterWrapper.hxx> +#include <servicenames_charttypes.hxx> +#include <ResId.hxx> +#include <bitmaps.hlst> +#include <helpids.h> + +#include <vcl/weld.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> +#include <rtl/math.hxx> +#include <o3tl/safeint.hxx> +#include <osl/diagnose.h> +#include <toolkit/helper/vclunohelper.hxx> + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartType.hpp> +#include <com/sun/star/container/XIndexReplace.hpp> + +#include <algorithm> + + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +using namespace ::svt; + +namespace +{ +/* BrowserMode::COLUMNSELECTION : single cells may be selected rather than only + entire rows + BrowserMode::(H|V)LINES : show horizontal or vertical grid-lines + BrowserMode::AUTO_(H|V)SCROLL : scroll automated horizontally or vertically when + cursor is moved beyond the edge of the dialog + BrowserMode::HIDESELECT : Do not mark the current row with selection color + (usually blue) + ! BrowserMode::HIDECURSOR would prevent flickering in edit fields, but navigating + with shift up/down, and entering non-editable cells would be problematic, + e.g. the first cell, or when being in read-only mode +*/ +const BrowserMode BrowserStdFlags = BrowserMode::COLUMNSELECTION | + BrowserMode::HLINES | BrowserMode::VLINES | + BrowserMode::AUTO_HSCROLL | BrowserMode::AUTO_VSCROLL | + BrowserMode::HIDESELECT; + +sal_Int32 lcl_getRowInData( long nRow ) +{ + return static_cast< sal_Int32 >( nRow ); +} + +sal_Int32 lcl_getColumnInData( sal_uInt16 nCol ) +{ + return static_cast< sal_Int32 >( nCol ) - 1; +} + +} // anonymous namespace + +namespace chart +{ + +namespace impl +{ + +class SeriesHeaderEdit +{ +public: + explicit SeriesHeaderEdit(std::unique_ptr<weld::Entry> xControl); + + void setStartColumn( sal_Int32 nStartColumn ); + sal_Int32 getStartColumn() const { return m_nStartColumn;} + void SetShowWarningBox( bool bShowWarning ); + + OUString GetText() const { return m_xControl->get_text(); } + void SetText(const OUString& rText) { m_xControl->set_text(rText); } + + bool HasFocus() const { return m_xControl->has_focus(); } + + void set_size_request(int nWidth, int nHeight) { m_xControl->set_size_request(nWidth, nHeight); } + void set_margin_left(int nLeft) { m_xControl->set_margin_left(nLeft); } + + void SetModifyHdl(const Link<SeriesHeaderEdit&,void>& rLink) { m_aModifyHdl = rLink; } + void SetGetFocusHdl(const Link<SeriesHeaderEdit&,void>& rLink) { m_aFocusInHdl = rLink; } + +private: + DECL_LINK(NameEdited, weld::Entry&, void); + DECL_LINK(NameFocusIn, weld::Widget&, void); + DECL_LINK(MousePressHdl, const MouseEvent&, bool); + + std::unique_ptr<weld::Entry> m_xControl; + Link<SeriesHeaderEdit&,void> m_aModifyHdl; + Link<SeriesHeaderEdit&,void> m_aFocusInHdl; + sal_Int32 m_nStartColumn; + bool m_bShowWarningBox; +}; + +SeriesHeaderEdit::SeriesHeaderEdit(std::unique_ptr<weld::Entry> xControl) + : m_xControl(std::move(xControl)) + , m_nStartColumn(0) + , m_bShowWarningBox(false) +{ + m_xControl->set_help_id(HID_SCH_DATA_SERIES_LABEL); + m_xControl->connect_changed(LINK(this, SeriesHeaderEdit, NameEdited)); + m_xControl->connect_focus_in(LINK(this, SeriesHeaderEdit, NameFocusIn)); + m_xControl->connect_mouse_press(LINK(this, SeriesHeaderEdit, MousePressHdl)); +} + +IMPL_LINK_NOARG(SeriesHeaderEdit, NameEdited, weld::Entry&, void) +{ + m_aModifyHdl.Call(*this); +} + +IMPL_LINK_NOARG(SeriesHeaderEdit, NameFocusIn, weld::Widget&, void) +{ + m_aFocusInHdl.Call(*this); +} + +void SeriesHeaderEdit::setStartColumn( sal_Int32 nStartColumn ) +{ + m_nStartColumn = nStartColumn; +} + +void SeriesHeaderEdit::SetShowWarningBox( bool bShowWarning ) +{ + m_bShowWarningBox = bShowWarning; +} + +IMPL_LINK_NOARG(SeriesHeaderEdit, MousePressHdl, const MouseEvent&, bool) +{ + if (m_bShowWarningBox) + { + std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(m_xControl.get(), + VclMessageType::Warning, VclButtonsType::Ok, + SchResId(STR_INVALID_NUMBER))); + xWarn->run(); + } + + return false; +} + +class SeriesHeader +{ +public: + explicit SeriesHeader(weld::Container* pParent, weld::Container* pColorParent); + ~SeriesHeader(); + + void SetColor( const Color & rCol ); + void SetPos(); + void SetWidth( sal_Int32 nWidth ); + void SetChartType( const Reference< chart2::XChartType > & xChartType, + bool bSwapXAndYAxis ); + void SetSeriesName( const OUString & rName ); + void SetRange( sal_Int32 nStartCol, sal_Int32 nEndCol ); + + void SetPixelWidth( sal_Int32 nWidth ); + + sal_Int32 GetStartColumn() const { return m_nStartCol;} + sal_Int32 GetEndColumn() const { return m_nEndCol;} + + static const sal_Int32 nSymbolHeight = 10; + static const sal_Int32 nSymbolDistance = 2; + + static sal_Int32 GetRelativeAppFontXPosForNameField() { return nSymbolHeight + nSymbolDistance; } + + void Show(); + void Hide(); + + /** call this before destroying the class. This notifies the listeners to + changes of the edit field for the series name. + */ + void applyChanges(); + + void SetGetFocusHdl(const Link<SeriesHeaderEdit&,void>& rLink); + + void SetEditChangedHdl( const Link<SeriesHeaderEdit&,void> & rLink ); + + bool HasFocus() const; + +private: + Timer m_aUpdateDataTimer; + + std::unique_ptr<weld::Builder> m_xBuilder1; + std::unique_ptr<weld::Builder> m_xBuilder2; + + weld::Container* m_pParent; + weld::Container* m_pColorParent; + + std::unique_ptr<weld::Container> m_xContainer1; + std::unique_ptr<weld::Container> m_xContainer2; + std::unique_ptr<weld::Image> m_spSymbol; + std::unique_ptr<SeriesHeaderEdit> m_spSeriesName; + std::unique_ptr<weld::Image> m_spColorBar; + VclPtr< OutputDevice> m_xDevice; + Link<SeriesHeaderEdit&,void> m_aChangeLink; + Color m_aColor; + + void notifyChanges(); + DECL_LINK( ImplUpdateDataHdl, Timer*, void ); + DECL_LINK( SeriesNameEdited, SeriesHeaderEdit&, void ); + + static OUString GetChartTypeImage( + const Reference< chart2::XChartType > & xChartType, + bool bSwapXAndYAxis + ); + + sal_Int32 m_nStartCol, m_nEndCol; + sal_Int32 m_nWidth; + bool m_bSeriesNameChangePending; +}; + +SeriesHeader::SeriesHeader(weld::Container* pParent, weld::Container* pColorParent) + : m_aUpdateDataTimer("UpdateDataTimer") + , m_xBuilder1(Application::CreateBuilder(pParent, "modules/schart/ui/columnfragment.ui")) + , m_xBuilder2(Application::CreateBuilder(pColorParent, "modules/schart/ui/imagefragment.ui")) + , m_pParent(pParent) + , m_pColorParent(pColorParent) + , m_xContainer1(m_xBuilder1->weld_container("container")) + , m_xContainer2(m_xBuilder2->weld_container("container")) + , m_spSymbol(m_xBuilder1->weld_image("image")) + , m_spSeriesName(new SeriesHeaderEdit(m_xBuilder1->weld_entry("entry"))) + , m_spColorBar(m_xBuilder2->weld_image("image")) + , m_xDevice(Application::GetDefaultDevice()) + , m_nStartCol( 0 ) + , m_nEndCol( 0 ) + , m_nWidth( 42 ) + , m_bSeriesNameChangePending( false ) +{ + m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SeriesHeader, ImplUpdateDataHdl)); + m_aUpdateDataTimer.SetDebugName( "SeriesHeader UpdateDataTimer" ); + m_aUpdateDataTimer.SetTimeout(4 * EDIT_UPDATEDATA_TIMEOUT); + + m_spSeriesName->SetModifyHdl(LINK(this, SeriesHeader, SeriesNameEdited)); + Show(); +} + +SeriesHeader::~SeriesHeader() +{ + m_aUpdateDataTimer.Stop(); + m_pParent->move(m_xContainer1.get(), nullptr); + m_pColorParent->move(m_xContainer2.get(), nullptr); +} + +void SeriesHeader::notifyChanges() +{ + m_aChangeLink.Call(*m_spSeriesName); + m_bSeriesNameChangePending = false; +} + +void SeriesHeader::applyChanges() +{ + if( m_bSeriesNameChangePending ) + { + notifyChanges(); + } +} + +void SeriesHeader::SetColor( const Color & rCol ) +{ + m_aColor = rCol; +} + +void SeriesHeader::SetPos() +{ + // chart type symbol + Size aSize( nSymbolHeight, nSymbolHeight ); + aSize = m_xDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont)); + m_spSymbol->set_size_request(aSize.Width(), aSize.Height()); + + // series name edit field + m_spSeriesName->set_margin_left(2); + + aSize.setWidth(nSymbolHeight); + aSize.setHeight(12); + aSize = m_xDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont)); + aSize.setWidth(m_nWidth - aSize.Width() - 2); + m_spSeriesName->set_size_request(aSize.Width(), aSize.Height()); + + // color bar + aSize.setHeight(3); + aSize = m_xDevice->LogicToPixel(aSize, MapMode(MapUnit::MapAppFont)); + aSize.setWidth(m_nWidth); + m_spColorBar->set_size_request(aSize.Width(), aSize.Height()); + + auto xVirDev(m_spColorBar->create_virtual_device()); + xVirDev->SetOutputSizePixel(aSize); + xVirDev->SetFillColor(m_aColor); + xVirDev->SetLineColor(m_aColor); + xVirDev->DrawRect(tools::Rectangle(Point(0, 0), aSize)); + m_spColorBar->set_image(xVirDev.get()); +} + +void SeriesHeader::SetWidth( sal_Int32 nWidth ) +{ + m_nWidth = nWidth; + SetPos(); +} + +void SeriesHeader::SetPixelWidth( sal_Int32 nWidth ) +{ + SetWidth(nWidth); +} + +void SeriesHeader::SetChartType( + const Reference< chart2::XChartType > & xChartType, + bool bSwapXAndYAxis +) +{ + m_spSymbol->set_from_icon_name( GetChartTypeImage( xChartType, bSwapXAndYAxis ) ); +} + +void SeriesHeader::SetSeriesName( const OUString & rName ) +{ + m_spSeriesName->SetText(rName); +} + +void SeriesHeader::SetRange( sal_Int32 nStartCol, sal_Int32 nEndCol ) +{ + m_nStartCol = nStartCol; + m_nEndCol = std::max(nEndCol, nStartCol); + m_spSeriesName->setStartColumn( nStartCol ); +} + +void SeriesHeader::Show() +{ + m_xContainer1->show(); + m_xContainer2->show(); +} + +void SeriesHeader::Hide() +{ + m_xContainer1->hide(); + m_xContainer2->hide(); +} + +void SeriesHeader::SetEditChangedHdl( const Link<SeriesHeaderEdit&,void> & rLink ) +{ + m_aChangeLink = rLink; +} + +IMPL_LINK_NOARG(SeriesHeader, ImplUpdateDataHdl, Timer*, void) +{ + notifyChanges(); +} + +IMPL_LINK_NOARG(SeriesHeader, SeriesNameEdited, SeriesHeaderEdit&, void) +{ + m_bSeriesNameChangePending = true; + m_aUpdateDataTimer.Start(); +} + +void SeriesHeader::SetGetFocusHdl( const Link<SeriesHeaderEdit&,void>& rLink ) +{ + m_spSeriesName->SetGetFocusHdl( rLink ); +} + +bool SeriesHeader::HasFocus() const +{ + return m_spSeriesName->HasFocus(); +} + +OUString SeriesHeader::GetChartTypeImage( + const Reference< chart2::XChartType > & xChartType, + bool bSwapXAndYAxis +) +{ + OUString aResult; + if( !xChartType.is()) + return aResult; + OUString aChartTypeName( xChartType->getChartType()); + + if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_AREA ) + { + aResult = BMP_TYPE_AREA; + } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ) + { + if( bSwapXAndYAxis ) + aResult = BMP_TYPE_BAR; + else + aResult = BMP_TYPE_COLUMN; + } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_LINE ) + { + aResult = BMP_TYPE_LINE; + } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_SCATTER ) + { + aResult = BMP_TYPE_XY; + } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_PIE ) + { + aResult = BMP_TYPE_PIE; + } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_NET + || aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET ) + { + aResult = BMP_TYPE_NET; + } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ) + { + // @todo: correct image for candle-stick type + aResult = BMP_TYPE_STOCK; + } + else if( aChartTypeName == CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE ) + { + aResult = BMP_TYPE_BUBBLE; + } + + return aResult; +} + +} // namespace impl + +namespace +{ + +/** returns false, if no header as the focus. + + If a header has the focus, true is returned and the index of the header + with focus is set at pIndex if pOutIndex is not 0. +*/ +bool lcl_SeriesHeaderHasFocus( + const std::vector< std::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader, + sal_Int32 * pOutIndex = nullptr ) +{ + sal_Int32 nIndex = 0; + for (auto const& elem : rSeriesHeader) + { + if(elem->HasFocus()) + { + if( pOutIndex ) + *pOutIndex = nIndex; + return true; + } + ++nIndex; + } + return false; +} + +sal_Int32 lcl_getColumnInDataOrHeader( + sal_uInt16 nCol, const std::vector< std::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader ) +{ + sal_Int32 nColIdx = 0; + bool bHeaderHasFocus( lcl_SeriesHeaderHasFocus( rSeriesHeader, &nColIdx )); + + if( bHeaderHasFocus ) + nColIdx = lcl_getColumnInData( static_cast< sal_uInt16 >( rSeriesHeader[nColIdx]->GetStartColumn())); + else + nColIdx = lcl_getColumnInData( nCol ); + + return nColIdx; +} + +} // anonymous namespace + +DataBrowser::DataBrowser(const css::uno::Reference<css::awt::XWindow> &rParent, + weld::Container* pColumns, weld::Container* pColors) : + ::svt::EditBrowseBox(VCLUnoHelper::GetWindow(rParent), + EditBrowseBoxFlags::SMART_TAB_TRAVEL | EditBrowseBoxFlags::HANDLE_COLUMN_TEXT, + WB_BORDER | WB_TABSTOP, BrowserStdFlags ), + m_nSeekRow( 0 ), + m_bIsReadOnly( false ), + m_bDataValid( true ), + m_aNumberEditField( VclPtr<FormattedField>::Create( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ) ), + m_aTextEditField( VclPtr<Edit>::Create( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ) ), + m_pColumnsWin(pColumns), + m_pColorsWin(pColors), + m_rNumberEditController( new ::svt::FormattedFieldCellController( m_aNumberEditField.get() )), + m_rTextEditController( new ::svt::EditCellController( m_aTextEditField.get() )) +{ + double fNan; + ::rtl::math::setNan( & fNan ); + m_aNumberEditField->SetDefaultValue( fNan ); + m_aNumberEditField->TreatAsNumber( true ); + RenewTable(); +} + +DataBrowser::~DataBrowser() +{ + disposeOnce(); +} + +void DataBrowser::dispose() +{ + m_aSeriesHeaders.clear(); + m_aNumberEditField.disposeAndClear(); + m_aTextEditField.disposeAndClear(); + ::svt::EditBrowseBox::dispose(); +} + +bool DataBrowser::MayInsertRow() const +{ + return ! IsReadOnly() + && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders )); +} + +bool DataBrowser::MayInsertColumn() const +{ + return ! IsReadOnly(); +} + +bool DataBrowser::MayDeleteRow() const +{ + return ! IsReadOnly() + && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders )) + && ( GetCurRow() >= 0 ) + && ( GetRowCount() > 1 ); +} + +bool DataBrowser::MayDeleteColumn() const +{ + // if a series header has the focus + if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders )) + return true; + + return ! IsReadOnly() + && ( GetCurColumnId() > 1 ) + && ( ColCount() > 2 ); +} + +bool DataBrowser::MayMoveUpRows() const +{ + return ! IsReadOnly() + && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders )) + && ( GetCurRow() > 0 ) + && ( GetCurRow() <= GetRowCount() - 1 ); +} + +bool DataBrowser::MayMoveDownRows() const +{ + return ! IsReadOnly() + && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders )) + && ( GetCurRow() >= 0 ) + && ( GetCurRow() < GetRowCount() - 1 ); +} + +bool DataBrowser::MayMoveLeftColumns() const +{ + // if a series header (except the last one) has the focus + { + sal_Int32 nColIndex(0); + if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders, &nColIndex )) + return (o3tl::make_unsigned( nColIndex ) <= (m_aSeriesHeaders.size() - 1)) && (static_cast< sal_uInt32 >( nColIndex ) != 0); + } + + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + return ! IsReadOnly() + && ( nColIdx > 1 ) + && ( nColIdx <= ColCount() - 2 ) + && m_apDataBrowserModel + && !m_apDataBrowserModel->isCategoriesColumn( nColIdx ); +} + +bool DataBrowser::MayMoveRightColumns() const +{ + // if a series header (except the last one) has the focus + { + sal_Int32 nColIndex(0); + if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders, &nColIndex )) + return (o3tl::make_unsigned( nColIndex ) < (m_aSeriesHeaders.size() - 1)); + } + + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + return ! IsReadOnly() + && ( nColIdx > 0 ) + && ( nColIdx < ColCount()-2 ) + && m_apDataBrowserModel + && !m_apDataBrowserModel->isCategoriesColumn( nColIdx ); +} + +void DataBrowser::clearHeaders() +{ + for( const auto& spHeader : m_aSeriesHeaders ) + spHeader->applyChanges(); + m_aSeriesHeaders.clear(); +} + +void DataBrowser::RenewTable() +{ + if (!m_apDataBrowserModel) + return; + + long nOldRow = GetCurRow(); + sal_uInt16 nOldColId = GetCurColumnId(); + + bool bLastUpdateMode = GetUpdateMode(); + SetUpdateMode( false ); + + if( IsModified() ) + SaveModified(); + + DeactivateCell(); + + RemoveColumns(); + RowRemoved( 1, GetRowCount() ); + + // for row numbers + InsertHandleColumn( static_cast< sal_uInt16 >( + GetDataWindow().LogicToPixel( Size( 42, 0 )).getWidth() )); + + OUString aDefaultSeriesName(SchResId(STR_COLUMN_LABEL)); + replaceParamterInString( aDefaultSeriesName, "%COLUMNNUMBER", OUString::number( 24 ) ); + sal_Int32 nColumnWidth = GetDataWindow().GetTextWidth( aDefaultSeriesName ) + + GetDataWindow().LogicToPixel(Point(8 + impl::SeriesHeader::GetRelativeAppFontXPosForNameField(), 0), MapMode(MapUnit::MapAppFont)).X(); + sal_Int32 nColumnCount = m_apDataBrowserModel->getColumnCount(); + // nRowCount is a member of a base class + sal_Int32 nRowCountLocal = m_apDataBrowserModel->getMaxRowCount(); + for( sal_Int32 nColIdx=1; nColIdx<=nColumnCount; ++nColIdx ) + { + InsertDataColumn( static_cast< sal_uInt16 >( nColIdx ), GetColString( nColIdx ), nColumnWidth ); + } + + RowInserted( 1, nRowCountLocal ); + GoToRow( std::min( nOldRow, GetRowCount() - 1 )); + GoToColumnId( std::min( nOldColId, static_cast< sal_uInt16 >( ColCount() - 1 ))); + + // fill series headers + clearHeaders(); + const DataBrowserModel::tDataHeaderVector& aHeaders( m_apDataBrowserModel->getDataHeaders()); + Link<impl::SeriesHeaderEdit&,void> aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus )); + Link<impl::SeriesHeaderEdit&,void> aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged )); + + for (auto const& elemHeader : aHeaders) + { + auto spHeader = std::make_shared<impl::SeriesHeader>( m_pColumnsWin, m_pColorsWin ); + Reference< beans::XPropertySet > xSeriesProp( elemHeader.m_xDataSeries, uno::UNO_QUERY ); + sal_Int32 nColor = 0; + // @todo: Set "DraftColor", i.e. interpolated colors for gradients, bitmaps, etc. + if( xSeriesProp.is() && + ( xSeriesProp->getPropertyValue( "Color" ) >>= nColor )) + spHeader->SetColor( Color( nColor )); + spHeader->SetChartType( elemHeader.m_xChartType, elemHeader.m_bSwapXAndYAxis ); + spHeader->SetSeriesName( + DataSeriesHelper::getDataSeriesLabel( + elemHeader.m_xDataSeries, + (elemHeader.m_xChartType.is() ? + elemHeader.m_xChartType->getRoleOfSequenceForSeriesLabel() : + OUString("values-y")))); + // index is 1-based, as 0 is for the column that contains the row-numbers + spHeader->SetRange( elemHeader.m_nStartColumn + 1, elemHeader.m_nEndColumn + 1 ); + spHeader->SetGetFocusHdl( aFocusLink ); + spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink ); + m_aSeriesHeaders.push_back( spHeader ); + } + + ImplAdjustHeaderControls(); + SetUpdateMode( bLastUpdateMode ); + ActivateCell(); + Invalidate(); +} + +OUString DataBrowser::GetColString( sal_Int32 nColumnId ) const +{ + OSL_ASSERT(m_apDataBrowserModel); + if( nColumnId > 0 ) + return m_apDataBrowserModel->getRoleOfColumn( nColumnId - 1 ); + return OUString(); +} + +OUString DataBrowser::GetCellText( long nRow, sal_uInt16 nColumnId ) const +{ + OUString aResult; + + if( nColumnId == 0 ) + { + aResult = OUString::number(static_cast< sal_Int32 >( nRow ) + 1); + } + else if( nRow >= 0 && m_apDataBrowserModel) + { + sal_Int32 nColIndex = static_cast< sal_Int32 >( nColumnId ) - 1; + + if( m_apDataBrowserModel->getCellType( nColIndex ) == DataBrowserModel::NUMBER ) + { + double fData( m_apDataBrowserModel->getCellNumber( nColIndex, nRow )); + Color nLabelColor; + + if( ! std::isnan( fData ) && + m_spNumberFormatterWrapper ) + { + bool bColorChanged = false; + aResult = m_spNumberFormatterWrapper->getFormattedString( + GetNumberFormatKey( nColumnId ), + fData, nLabelColor, bColorChanged ); + } + } + else if( m_apDataBrowserModel->getCellType( nColIndex ) == DataBrowserModel::TEXTORDATE ) + { + uno::Any aAny = m_apDataBrowserModel->getCellAny( nColIndex, nRow ); + OUString aText; + double fDouble=0.0; + if( aAny>>=aText ) + aResult = aText; + else if( aAny>>=fDouble ) + { + if( ! std::isnan( fDouble ) && m_spNumberFormatterWrapper ) + { + // If a numberformat was available here we could directly + // obtain the corresponding edit format in + // getDateTimeInputNumberFormat() instead of doing the + // guess work. + sal_Int32 nNumberFormat = DiagramHelper::getDateTimeInputNumberFormat( + Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY), fDouble ); + Color nLabelColor; + bool bColorChanged = false; + aResult = m_spNumberFormatterWrapper->getFormattedString( + nNumberFormat, fDouble, nLabelColor, bColorChanged ); + } + } + } + else + { + OSL_ASSERT( m_apDataBrowserModel->getCellType( nColIndex ) == DataBrowserModel::TEXT ); + aResult = m_apDataBrowserModel->getCellText( nColIndex, nRow ); + } + } + + return aResult; +} + +double DataBrowser::GetCellNumber( long nRow, sal_uInt16 nColumnId ) const +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + if(( nColumnId >= 1 ) && ( nRow >= 0 ) && m_apDataBrowserModel) + { + fResult = m_apDataBrowserModel->getCellNumber( + static_cast< sal_Int32 >( nColumnId ) - 1, nRow ); + } + + return fResult; +} + +void DataBrowser::Resize() +{ + bool bLastUpdateMode = GetUpdateMode(); + SetUpdateMode( false ); + + ::svt::EditBrowseBox::Resize(); + ImplAdjustHeaderControls(); + SetUpdateMode( bLastUpdateMode ); +} + +void DataBrowser::SetReadOnly( bool bNewState ) +{ + if( m_bIsReadOnly != bNewState ) + { + m_bIsReadOnly = bNewState; + Invalidate(); + DeactivateCell(); + } +} + +void DataBrowser::CursorMoved() +{ + EditBrowseBox::CursorMoved(); + + if( GetUpdateMode() ) + m_aCursorMovedHdlLink.Call( this ); +} + +void DataBrowser::MouseButtonDown( const BrowserMouseEvent& rEvt ) +{ + if( !m_bDataValid ) + ShowWarningBox(); + else + EditBrowseBox::MouseButtonDown( rEvt ); +} + +void DataBrowser::ShowWarningBox() +{ + std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + SchResId(STR_INVALID_NUMBER))); + xWarn->run(); +} + +bool DataBrowser::ShowQueryBox() +{ + std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Question, VclButtonsType::YesNo, + SchResId(STR_DATA_EDITOR_INCORRECT_INPUT))); + return xQueryBox->run() == RET_YES; +} + +bool DataBrowser::IsDataValid() const +{ + bool bValid = true; + const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId()); + + if( m_apDataBrowserModel->getCellType( nCol ) == DataBrowserModel::NUMBER ) + { + sal_uInt32 nDummy = 0; + double fDummy = 0.0; + OUString aText( m_aNumberEditField->GetText()); + + if( !aText.isEmpty() && + m_spNumberFormatterWrapper && + m_spNumberFormatterWrapper->getSvNumberFormatter() && + ! m_spNumberFormatterWrapper->getSvNumberFormatter()->IsNumberFormat( + aText, nDummy, fDummy )) + { + bValid = false; + } + } + + return bValid; +} + +void DataBrowser::CellModified() +{ + m_bDataValid = IsDataValid(); + m_aCursorMovedHdlLink.Call( this ); +} + +void DataBrowser::SetDataFromModel( + const Reference< chart2::XChartDocument > & xChartDoc, + const Reference< uno::XComponentContext > & xContext ) +{ + m_xChartDoc.set( xChartDoc ); + + m_apDataBrowserModel.reset( new DataBrowserModel( m_xChartDoc, xContext )); + m_spNumberFormatterWrapper = + std::make_shared<NumberFormatterWrapper>( + Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY )); + + m_aNumberEditField->SetFormatter( m_spNumberFormatterWrapper->getSvNumberFormatter() ); + + RenewTable(); + + const sal_Int32 nColCnt = m_apDataBrowserModel->getColumnCount(); + const sal_Int32 nRowCnt = m_apDataBrowserModel->getMaxRowCount(); + if( nRowCnt && nColCnt ) + { + GoToRow( 0 ); + GoToColumnId( 1 ); + } +} + +void DataBrowser::InsertColumn() +{ + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + + if( nColIdx >= 0 && m_apDataBrowserModel) + { + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->insertDataSeries( nColIdx ); + RenewTable(); + } +} + +void DataBrowser::InsertTextColumn() +{ + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + + if( nColIdx >= 0 && m_apDataBrowserModel) + { + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->insertComplexCategoryLevel( nColIdx ); + RenewTable(); + } +} + +void DataBrowser::RemoveColumn() +{ + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + + if( nColIdx >= 0 && m_apDataBrowserModel) + { + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_bDataValid = true; + m_apDataBrowserModel->removeDataSeriesOrComplexCategoryLevel( nColIdx ); + RenewTable(); + } +} + +void DataBrowser::InsertRow() +{ + sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow()); + + if( nRowIdx >= 0 && m_apDataBrowserModel) + { + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->insertDataPointForAllSeries( nRowIdx ); + RenewTable(); + } +} + +void DataBrowser::RemoveRow() +{ + sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow()); + + if( nRowIdx >= 0 && m_apDataBrowserModel) + { + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_bDataValid = true; + m_apDataBrowserModel->removeDataPointForAllSeries( nRowIdx ); + RenewTable(); + } +} + +void DataBrowser::MoveLeftColumn() +{ + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + + if( !(nColIdx > 0 && m_apDataBrowserModel)) + return; + + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->swapDataSeries( nColIdx - 1 ); + + // keep cursor in swapped column + if(( 0 < GetCurColumnId() ) && ( GetCurColumnId() <= ColCount() - 1 )) + { + Dispatch( BROWSER_CURSORLEFT ); + } + RenewTable(); +} + +void DataBrowser::MoveRightColumn() +{ + sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders ); + + if( !(nColIdx >= 0 && m_apDataBrowserModel)) + return; + + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->swapDataSeries( nColIdx ); + + // keep cursor in swapped column + if( GetCurColumnId() < ColCount() - 1 ) + { + Dispatch( BROWSER_CURSORRIGHT ); + } + RenewTable(); +} + +void DataBrowser::MoveUpRow() +{ + sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow()); + + if( !(nRowIdx > 0 && m_apDataBrowserModel)) + return; + + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->swapDataPointForAllSeries( nRowIdx - 1 ); + + // keep cursor in swapped row + if(( 0 < GetCurRow() ) && ( GetCurRow() <= GetRowCount() - 1 )) + { + Dispatch( BROWSER_CURSORUP ); + } + RenewTable(); +} + +void DataBrowser::MoveDownRow() +{ + sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow()); + + if( !(nRowIdx >= 0 && m_apDataBrowserModel)) + return; + + // save changes made to edit-field + if( IsModified() ) + SaveModified(); + + m_apDataBrowserModel->swapDataPointForAllSeries( nRowIdx ); + + // keep cursor in swapped row + if( GetCurRow() < GetRowCount() - 1 ) + { + Dispatch( BROWSER_CURSORDOWN ); + } + RenewTable(); +} + +void DataBrowser::SetCursorMovedHdl( const Link<DataBrowser*,void>& rLink ) +{ + m_aCursorMovedHdlLink = rLink; +} + +// implementations for ::svt::EditBrowseBox (pure virtual methods) +void DataBrowser::PaintCell( + OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const +{ + Point aPos( rRect.TopLeft()); + aPos.AdjustX(1 ); + + OUString aText = GetCellText( m_nSeekRow, nColumnId ); + Size TxtSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight()); + + // clipping + if( aPos.X() < rRect.Right() || aPos.X() + TxtSize.Width() > rRect.Right() || + aPos.Y() < rRect.Top() || aPos.Y() + TxtSize.Height() > rRect.Bottom()) + rDev.SetClipRegion(vcl::Region(rRect)); + + // allow for a disabled control ... + bool bEnabled = IsEnabled(); + Color aOriginalColor = rDev.GetTextColor(); + if( ! bEnabled ) + rDev.SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() ); + + // draw the text + rDev.DrawText( aPos, aText ); + + // reset the color (if necessary) + if( ! bEnabled ) + rDev.SetTextColor( aOriginalColor ); + + if( rDev.IsClipRegion()) + rDev.SetClipRegion(); +} + +bool DataBrowser::SeekRow( long nRow ) +{ + if( ! EditBrowseBox::SeekRow( nRow )) + return false; + + if( nRow < 0 ) + m_nSeekRow = - 1; + else + m_nSeekRow = nRow; + + return true; +} + +bool DataBrowser::IsTabAllowed( bool bForward ) const +{ + long nRow = GetCurRow(); + long nCol = GetCurColumnId(); + + // column 0 is header-column + long nBadCol = bForward + ? GetColumnCount() - 1 + : 1; + long nBadRow = bForward + ? GetRowCount() - 1 + : 0; + + if( !m_bDataValid ) + { + const_cast< DataBrowser* >( this )->ShowWarningBox(); + return false; + } + + return ( nRow != nBadRow || + nCol != nBadCol ); +} + +::svt::CellController* DataBrowser::GetController( long /*nRow*/, sal_uInt16 nCol ) +{ + if( m_bIsReadOnly ) + return nullptr; + + if( CellContainsNumbers( nCol )) + { + m_aNumberEditField->UseInputStringForFormatting(); + m_aNumberEditField->SetFormatKey( GetNumberFormatKey( nCol )); + return m_rNumberEditController.get(); + } + + return m_rTextEditController.get(); +} + +void DataBrowser::InitController( + ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol ) +{ + if( rController == m_rTextEditController ) + { + OUString aText( GetCellText( nRow, nCol ) ); + m_aTextEditField->SetText( aText ); + m_aTextEditField->SetSelection( ::Selection( 0, aText.getLength() )); + } + else if( rController == m_rNumberEditController ) + { + // treat invalid and empty text as Nan + m_aNumberEditField->EnableNotANumber( true ); + if( std::isnan( GetCellNumber( nRow, nCol ))) + m_aNumberEditField->SetTextValue( OUString()); + else + m_aNumberEditField->SetValue( GetCellNumber( nRow, nCol ) ); + OUString aText( m_aNumberEditField->GetText()); + m_aNumberEditField->SetSelection( ::Selection( 0, aText.getLength())); + } + else + { + OSL_FAIL( "Invalid Controller" ); + } +} + +bool DataBrowser::CellContainsNumbers( sal_uInt16 nCol ) const +{ + if (!m_apDataBrowserModel) + return false; + return m_apDataBrowserModel->getCellType( lcl_getColumnInData( nCol )) == DataBrowserModel::NUMBER; +} + +sal_uInt32 DataBrowser::GetNumberFormatKey( sal_uInt16 nCol ) const +{ + if (!m_apDataBrowserModel) + return 0; + return m_apDataBrowserModel->getNumberFormatKey( lcl_getColumnInData( nCol ) ); +} + +bool DataBrowser::isDateTimeString( const OUString& aInputString, double& fOutDateTimeValue ) +{ + sal_uInt32 nNumberFormat=0; + SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper ? m_spNumberFormatterWrapper->getSvNumberFormatter() : nullptr; + if( !aInputString.isEmpty() && pSvNumberFormatter && pSvNumberFormatter->IsNumberFormat( aInputString, nNumberFormat, fOutDateTimeValue ) ) + { + SvNumFormatType nType = pSvNumberFormatter->GetType( nNumberFormat); + return (nType & SvNumFormatType::DATE) || (nType & SvNumFormatType::TIME); + } + return false; +} + +bool DataBrowser::SaveModified() +{ + if( ! IsModified() ) + return true; + + bool bChangeValid = true; + + const sal_Int32 nRow = lcl_getRowInData( GetCurRow()); + const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId()); + + OSL_ENSURE( nRow >= 0 || nCol >= 0, "This cell should not be modified!" ); + + SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper ? m_spNumberFormatterWrapper->getSvNumberFormatter() : nullptr; + switch( m_apDataBrowserModel->getCellType( nCol )) + { + case DataBrowserModel::NUMBER: + { + sal_uInt32 nDummy = 0; + double fDummy = 0.0; + OUString aText( m_aNumberEditField->GetText()); + // an empty string is valid, if no numberformatter exists, all + // values are treated as valid + if( !aText.isEmpty() && pSvNumberFormatter && + ! pSvNumberFormatter->IsNumberFormat( aText, nDummy, fDummy ) ) + { + bChangeValid = false; + } + else + { + double fData = m_aNumberEditField->GetValue(); + bChangeValid = m_apDataBrowserModel->setCellNumber( nCol, nRow, fData ); + } + } + break; + case DataBrowserModel::TEXTORDATE: + { + OUString aText( m_aTextEditField->GetText() ); + double fValue = 0.0; + bChangeValid = false; + if( isDateTimeString( aText, fValue ) ) + bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::Any( fValue ) ); + if(!bChangeValid) + bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::Any( aText ) ); + } + break; + case DataBrowserModel::TEXT: + { + OUString aText( m_aTextEditField->GetText()); + bChangeValid = m_apDataBrowserModel->setCellText( nCol, nRow, aText ); + } + break; + } + + // the first valid change changes this to true + if( bChangeValid ) + { + RowModified( GetCurRow(), GetCurColumnId()); + ::svt::CellController* pCtrl = GetController( GetCurRow(), GetCurColumnId()); + if( pCtrl ) + pCtrl->ClearModified(); + } + + return bChangeValid; +} + +bool DataBrowser::EndEditing() +{ + SaveModified(); + + // apply changes made to series headers + for( const auto& spHeader : m_aSeriesHeaders ) + spHeader->applyChanges(); + + if( m_bDataValid ) + return true; + else + return ShowQueryBox(); +} + +void DataBrowser::ColumnResized( sal_uInt16 nColId ) +{ + bool bLastUpdateMode = GetUpdateMode(); + SetUpdateMode( false ); + + EditBrowseBox::ColumnResized( nColId ); + ImplAdjustHeaderControls(); + SetUpdateMode( bLastUpdateMode ); +} + +void DataBrowser::EndScroll() +{ + bool bLastUpdateMode = GetUpdateMode(); + SetUpdateMode( false ); + + EditBrowseBox::EndScroll(); + RenewSeriesHeaders(); + + SetUpdateMode( bLastUpdateMode ); +} + +void DataBrowser::RenewSeriesHeaders() +{ + clearHeaders(); + DataBrowserModel::tDataHeaderVector aHeaders( m_apDataBrowserModel->getDataHeaders()); + Link<impl::SeriesHeaderEdit&,void> aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus )); + Link<impl::SeriesHeaderEdit&,void> aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged )); + + for (auto const& elemHeader : aHeaders) + { + auto spHeader = std::make_shared<impl::SeriesHeader>( m_pColumnsWin, m_pColorsWin ); + Reference< beans::XPropertySet > xSeriesProp(elemHeader.m_xDataSeries, uno::UNO_QUERY); + sal_Int32 nColor = 0; + if( xSeriesProp.is() && + ( xSeriesProp->getPropertyValue( "Color" ) >>= nColor )) + spHeader->SetColor( Color( nColor )); + spHeader->SetChartType( elemHeader.m_xChartType, elemHeader.m_bSwapXAndYAxis ); + spHeader->SetSeriesName( + DataSeriesHelper::getDataSeriesLabel( + elemHeader.m_xDataSeries, + (elemHeader.m_xChartType.is() ? + elemHeader.m_xChartType->getRoleOfSequenceForSeriesLabel() : + OUString( "values-y")))); + spHeader->SetRange( elemHeader.m_nStartColumn + 1, elemHeader.m_nEndColumn + 1 ); + spHeader->SetGetFocusHdl( aFocusLink ); + spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink ); + m_aSeriesHeaders.push_back( spHeader ); + } + + ImplAdjustHeaderControls(); +} + +void DataBrowser::ImplAdjustHeaderControls() +{ + sal_uInt16 nColCount = GetColumnCount(); + sal_uInt32 nCurrentPos = GetPosPixel().getX(); + sal_uInt32 nMaxPos = nCurrentPos + GetOutputSizePixel().getWidth(); + sal_uInt32 nStartPos = nCurrentPos; + + // width of header column + nCurrentPos += GetColumnWidth( 0 ); + + weld::Container* pWin = m_pColumnsWin; + weld::Container* pColorWin = m_pColorsWin; + pWin->set_margin_left(nCurrentPos); + pColorWin->set_margin_left(nCurrentPos); + + tSeriesHeaderContainer::iterator aIt( m_aSeriesHeaders.begin()); + sal_uInt16 i = GetFirstVisibleColNumber(); + while( (aIt != m_aSeriesHeaders.end()) && ((*aIt)->GetStartColumn() < i) ) + { + (*aIt)->Hide(); + ++aIt; + } + for( ; i < nColCount && aIt != m_aSeriesHeaders.end(); ++i ) + { + if( (*aIt)->GetStartColumn() == i ) + nStartPos = nCurrentPos; + + nCurrentPos += (GetColumnWidth( i )); + + if( (*aIt)->GetEndColumn() == i ) + { + if( nStartPos < nMaxPos ) + { + (*aIt)->SetPixelWidth( nCurrentPos - nStartPos ); + (*aIt)->Show(); + + if (pWin) + { + pWin->set_margin_left(nStartPos); + pColorWin->set_margin_left(nStartPos); + pWin = pColorWin = nullptr; + } + + } + else + (*aIt)->Hide(); + ++aIt; + } + } +} + +IMPL_LINK( DataBrowser, SeriesHeaderGotFocus, impl::SeriesHeaderEdit&, rEdit, void ) +{ + rEdit.SetShowWarningBox( !m_bDataValid ); + + if( !m_bDataValid ) + GoToCell( 0, 0 ); + else + { + MakeFieldVisible( GetCurRow(), static_cast< sal_uInt16 >( rEdit.getStartColumn()) ); + ActivateCell(); + m_aCursorMovedHdlLink.Call( this ); + } +} + +IMPL_LINK( DataBrowser, SeriesHeaderChanged, impl::SeriesHeaderEdit&, rEdit, void ) +{ + Reference< chart2::XDataSeries > xSeries( + m_apDataBrowserModel->getDataSeriesByColumn( rEdit.getStartColumn() - 1 )); + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + if( !xSource.is()) + return; + + Reference< chart2::XChartType > xChartType( + m_apDataBrowserModel->getHeaderForSeries( xSeries ).m_xChartType ); + if( xChartType.is()) + { + Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + DataSeriesHelper::getDataSequenceByRole( xSource, xChartType->getRoleOfSequenceForSeriesLabel())); + if( xLabeledSeq.is()) + { + Reference< container::XIndexReplace > xIndexReplace( xLabeledSeq->getLabel(), uno::UNO_QUERY ); + if( xIndexReplace.is()) + xIndexReplace->replaceByIndex( + 0, uno::Any( rEdit.GetText())); + } + } +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/DataBrowser.hxx b/chart2/source/controller/dialogs/DataBrowser.hxx new file mode 100644 index 000000000..8e6372b0b --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowser.hxx @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSER_HXX + +#include <svtools/editbrowsebox.hxx> +#include <vcl/fmtfield.hxx> +#include <vcl/weld.hxx> + +#include <memory> +#include <vector> + +namespace com::sun::star { + namespace awt { + class XWindow; + } + namespace chart2 { + class XChartDocument; + } +} + +namespace com::sun::star::uno { class XComponentContext; } + +class OutputDevice; + +namespace chart +{ + +class DataBrowserModel; +class NumberFormatterWrapper; + +namespace impl +{ +class SeriesHeader; +class SeriesHeaderEdit; +} + +class DataBrowser : public ::svt::EditBrowseBox +{ +protected: + // EditBrowseBox overridables + virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const override; + virtual bool SeekRow( long nRow ) override; + virtual bool IsTabAllowed( bool bForward ) const override; + virtual ::svt::CellController* GetController( long nRow, sal_uInt16 nCol ) override; + virtual void InitController( ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol ) override; + virtual bool SaveModified() override; + virtual void CursorMoved() override; + // called whenever the control of the current cell has been modified + virtual void CellModified() override; + virtual void ColumnResized( sal_uInt16 nColId ) override; + virtual void EndScroll() override; + virtual void MouseButtonDown( const BrowserMouseEvent& rEvt ) override; + +public: + DataBrowser(const css::uno::Reference<css::awt::XWindow> &rParent, + weld::Container* pColumns, weld::Container* pColors); + + virtual ~DataBrowser() override; + virtual void dispose() override; + + /** GetCellText returns the text at the given position + @param nRow + the number of the row + @param nColId + the ID of the column + @return + the text out of the cell + */ + virtual OUString GetCellText(long nRow, sal_uInt16 nColId) const override; + + /** returns the number in the given cell. If a cell is empty or contains a + string, the result will be Nan + */ + double GetCellNumber( long nRow, sal_uInt16 nColumnId ) const; + + bool isDateTimeString( const OUString& aInputString, double& fOutDateTimeValue ); + + // Window + virtual void Resize() override; + + void SetReadOnly( bool bNewState ); + bool IsReadOnly() const { return m_bIsReadOnly;} + + void SetDataFromModel( const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc, + const css::uno::Reference< css::uno::XComponentContext > & xContext ); + + // predicates to determine what actions are possible at the current cursor + // position. This depends on the implementation of the according mutators + // below. (They are used for enabling toolbar icons) + bool MayInsertRow() const; + bool MayInsertColumn() const; + bool MayDeleteRow() const; + bool MayDeleteColumn() const; + + bool MayMoveUpRows() const; + bool MayMoveDownRows() const; + bool MayMoveRightColumns() const; + bool MayMoveLeftColumns() const; + + // mutators mutating data + void InsertRow(); + void InsertColumn(); + void InsertTextColumn(); + void RemoveRow(); + void RemoveColumn(); + + using BrowseBox::RemoveColumn; + using BrowseBox::MouseButtonDown; + + void MoveUpRow(); + void MoveDownRow(); + void MoveLeftColumn(); + void MoveRightColumn(); + + void SetCursorMovedHdl( const Link<DataBrowser*,void>& rLink ); + + /// confirms all pending changes to be ready to be closed + bool EndEditing(); + + bool CellContainsNumbers( sal_uInt16 nCol ) const; + + sal_uInt32 GetNumberFormatKey( sal_uInt16 nCol ) const; + + bool IsEnableItem() const { return m_bDataValid;} + bool IsDataValid() const; + void ShowWarningBox(); + bool ShowQueryBox(); + + void RenewSeriesHeaders(); + +private: + css::uno::Reference< css::chart2::XChartDocument > m_xChartDoc; + std::unique_ptr< DataBrowserModel > m_apDataBrowserModel; + + typedef std::vector< std::shared_ptr< impl::SeriesHeader > > tSeriesHeaderContainer; + tSeriesHeaderContainer m_aSeriesHeaders; + + std::shared_ptr< NumberFormatterWrapper > m_spNumberFormatterWrapper; + + /// the row that is currently painted + long m_nSeekRow; + bool m_bIsReadOnly; + bool m_bDataValid; + + VclPtr<FormattedField> m_aNumberEditField; + VclPtr<Edit> m_aTextEditField; + weld::Container* m_pColumnsWin; + weld::Container* m_pColorsWin; + + /// note: m_aNumberEditField must precede this member! + ::svt::CellControllerRef m_rNumberEditController; + /// note: m_aTextEditField must precede this member! + ::svt::CellControllerRef m_rTextEditController; + + Link<DataBrowser*,void> m_aCursorMovedHdlLink; + + void clearHeaders(); + void RenewTable(); + void ImplAdjustHeaderControls(); + + OUString GetColString( sal_Int32 nColumnId ) const; + + DECL_LINK( SeriesHeaderGotFocus, impl::SeriesHeaderEdit&, void ); + DECL_LINK( SeriesHeaderChanged, impl::SeriesHeaderEdit&, void ); + + DataBrowser( const DataBrowser & ) = delete; +}; + +} // namespace chart + +#endif // INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/DataBrowserModel.cxx b/chart2/source/controller/dialogs/DataBrowserModel.cxx new file mode 100644 index 000000000..c8359f74a --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowserModel.cxx @@ -0,0 +1,963 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "DataBrowserModel.hxx" +#include "DialogModel.hxx" +#include <ChartModelHelper.hxx> +#include <DiagramHelper.hxx> +#include <DataSeriesHelper.hxx> +#include <ControllerLockGuard.hxx> +#include <StatisticsHelper.hxx> +#include <ChartTypeHelper.hxx> +#include <chartview/ExplicitValueProvider.hxx> +#include <ExplicitCategoriesProvider.hxx> + +#include <ChartModel.hxx> +#include <unonames.hxx> + +#include <com/sun/star/container/XIndexReplace.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/XInternalDataProvider.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/data/XDataSource.hpp> +#include <com/sun/star/chart2/data/XLabeledDataSequence.hpp> +#include <com/sun/star/chart2/data/XNumericalDataSequence.hpp> +#include <com/sun/star/chart2/data/XTextualDataSequence.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <o3tl/safeint.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/property.hxx> + +#include <rtl/math.hxx> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart { + +namespace { + +OUString lcl_getRole( + const Reference< chart2::data::XDataSequence > & xSeq ) +{ + OUString aResult; + Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY ); + if( xProp.is()) + { + try + { + xProp->getPropertyValue( "Role" ) >>= aResult; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + return aResult; +} + +OUString lcl_getUIRoleName( + const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) +{ + OUString aResult = DataSeriesHelper::getRole(xLSeq); + if( !aResult.isEmpty()) + aResult = DialogModel::ConvertRoleFromInternalToUI(aResult); + return aResult; +} + +void lcl_copyDataSequenceProperties( + const Reference< chart2::data::XDataSequence > & xOldSequence, + const Reference< chart2::data::XDataSequence > & xNewSequence ) +{ + Reference< beans::XPropertySet > xOldSeqProp( xOldSequence, uno::UNO_QUERY ); + Reference< beans::XPropertySet > xNewSeqProp( xNewSequence, uno::UNO_QUERY ); + comphelper::copyProperties( xOldSeqProp, xNewSeqProp ); +} + +bool lcl_SequenceOfSeriesIsShared( + const Reference< chart2::XDataSeries > & xSeries, + const Reference< chart2::data::XDataSequence > & xValues ) +{ + bool bResult = false; + if( !xValues.is()) + return bResult; + try + { + OUString aValuesRole( lcl_getRole( xValues )); + OUString aValuesRep( xValues->getSourceRangeRepresentation()); + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW ); + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences()); + for( Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : aLSeq ) + if (labeledDataSeq.is() && DataSeriesHelper::getRole(labeledDataSeq) == aValuesRole) + { + // getValues().is(), because lcl_getRole checked that already + bResult = (aValuesRep == labeledDataSeq->getValues()->getSourceRangeRepresentation()); + // assumption: a role appears only once in a series + break; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return bResult; +} + +typedef std::vector< Reference< chart2::data::XLabeledDataSequence > > lcl_tSharedSeqVec; + +lcl_tSharedSeqVec lcl_getSharedSequences( const Sequence< Reference< chart2::XDataSeries > > & rSeries ) +{ + // @todo: if only some series share a sequence, those have to be duplicated + // and made unshared for all series + lcl_tSharedSeqVec aResult; + // if we have only one series, we don't want any shared sequences + if( rSeries.getLength() <= 1 ) + return aResult; + + Reference< chart2::data::XDataSource > xSource( rSeries[0], uno::UNO_QUERY ); + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeq( xSource->getDataSequences()); + for( Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : aLSeq ) + { + Reference< chart2::data::XDataSequence > xValues( labeledDataSeq->getValues()); + bool bShared = true; + for( sal_Int32 nSeriesIdx=1; nSeriesIdx<rSeries.getLength(); ++nSeriesIdx ) + { + bShared = lcl_SequenceOfSeriesIsShared( rSeries[nSeriesIdx], xValues ); + if( !bShared ) + break; + } + if( bShared ) + aResult.push_back( labeledDataSeq ); + } + + return aResult; +} + +sal_Int32 lcl_getValuesRepresentationIndex( + const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) +{ + sal_Int32 nResult = -1; + if( xLSeq.is()) + { + Reference< chart2::data::XDataSequence > xSeq( xLSeq->getValues()); + if( xSeq.is()) + { + OUString aRep( xSeq->getSourceRangeRepresentation()); + nResult = aRep.toInt32(); + } + } + return nResult; +} + +struct lcl_RepresentationsOfLSeqMatch +{ + explicit lcl_RepresentationsOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) : + m_aValuesRep( xLSeq.is() ? + (xLSeq->getValues().is() ? xLSeq->getValues()->getSourceRangeRepresentation() : OUString()) + : OUString() ) + {} + bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) + { + if (!xLSeq.is() || !xLSeq->getValues().is()) + return false; + + return xLSeq->getValues()->getSourceRangeRepresentation() == m_aValuesRep; + } +private: + OUString m_aValuesRep; +}; + +struct lcl_RolesOfLSeqMatch +{ + explicit lcl_RolesOfLSeqMatch( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) : + m_aRole(DataSeriesHelper::getRole(xLSeq)) {} + + bool operator() ( const Reference< chart2::data::XLabeledDataSequence > & xLSeq ) + { + return DataSeriesHelper::getRole(xLSeq) == m_aRole; + } +private: + OUString m_aRole; +}; + +bool lcl_ShowCategoriesAsDataLabel( const Reference< chart2::XDiagram > & xDiagram ) +{ + return !DiagramHelper::isCategoryDiagram(xDiagram); +} + +} // anonymous namespace + +struct DataBrowserModel::tDataColumn +{ + uno::Reference<chart2::XDataSeries> m_xDataSeries; + OUString m_aUIRoleName; + uno::Reference<chart2::data::XLabeledDataSequence> m_xLabeledDataSequence; + eCellType m_eCellType; + sal_Int32 m_nNumberFormatKey; + + // default CTOR + tDataColumn() : m_eCellType( TEXT ), m_nNumberFormatKey( 0 ) {} + // "full" CTOR + tDataColumn( + const uno::Reference<chart2::XDataSeries> & xDataSeries, + const OUString& aUIRoleName, + const uno::Reference<chart2::data::XLabeledDataSequence>& xLabeledDataSequence, + eCellType aCellType, + sal_Int32 nNumberFormatKey ) : + m_xDataSeries( xDataSeries ), + m_aUIRoleName( aUIRoleName ), + m_xLabeledDataSequence( xLabeledDataSequence ), + m_eCellType( aCellType ), + m_nNumberFormatKey( nNumberFormatKey ) + {} +}; + +struct DataBrowserModel::implColumnLess +{ + bool operator() ( const DataBrowserModel::tDataColumn & rLeft, const DataBrowserModel::tDataColumn & rRight ) + { + if( rLeft.m_xLabeledDataSequence.is() && rRight.m_xLabeledDataSequence.is()) + { + return DialogModel::GetRoleIndexForSorting(DataSeriesHelper::getRole(rLeft.m_xLabeledDataSequence)) < + DialogModel::GetRoleIndexForSorting(DataSeriesHelper::getRole(rRight.m_xLabeledDataSequence)); + } + return true; + } +}; + +DataBrowserModel::DataBrowserModel( + const Reference< chart2::XChartDocument > & xChartDoc, + const Reference< uno::XComponentContext > & xContext ) : + m_xChartDocument( xChartDoc ), + m_apDialogModel( new DialogModel( xChartDoc, xContext )) +{ + updateFromModel(); +} + +DataBrowserModel::~DataBrowserModel() +{} + +namespace +{ +struct lcl_DataSeriesOfHeaderMatches +{ + explicit lcl_DataSeriesOfHeaderMatches( + const Reference< chart2::XDataSeries > & xSeriesToCompareWith ) : + m_xSeries( xSeriesToCompareWith ) + {} + bool operator() ( const ::chart::DataBrowserModel::tDataHeader & rHeader ) + { + return (m_xSeries == rHeader.m_xDataSeries); + } +private: + Reference< chart2::XDataSeries > m_xSeries; +}; +} + +void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex ) +{ + OSL_ASSERT(m_apDialogModel); + Reference< chart2::XInternalDataProvider > xDataProvider( + m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + + if (!xDataProvider.is()) + return; + + if( isCategoriesColumn(nAfterColumnIndex) ) + // Move to the last category column. + nAfterColumnIndex = getCategoryColumnCount()-1; + + sal_Int32 nStartCol = 0; + Reference<chart2::XDiagram> xDiagram = ChartModelHelper::findDiagram(m_xChartDocument); + Reference<chart2::XChartType> xChartType; + Reference<chart2::XDataSeries> xSeries; + if (o3tl::make_unsigned(nAfterColumnIndex) < m_aColumns.size()) + // Get the data series at specific column position (if available). + xSeries.set( m_aColumns[nAfterColumnIndex].m_xDataSeries ); + + sal_Int32 nSeriesNumberFormat = 0; + if( xSeries.is()) + { + // Use the chart type of the currently selected data series. + xChartType.set( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries )); + + // Find the corresponding header and determine the last column of this + // data series. + tDataHeaderVector::const_iterator aIt( + std::find_if( m_aHeaders.begin(), m_aHeaders.end(), + lcl_DataSeriesOfHeaderMatches( xSeries ))); + if( aIt != m_aHeaders.end()) + nStartCol = aIt->m_nEndColumn; + + // Get the number format too. + Reference< beans::XPropertySet > xSeriesProps( xSeries, uno::UNO_QUERY ); + if( xSeriesProps.is() ) + xSeriesProps->getPropertyValue(CHART_UNONAME_NUMFMT) >>= nSeriesNumberFormat; + } + else + { + // No data series at specified column position. Use the first chart type. + xChartType.set( DiagramHelper::getChartTypeByIndex( xDiagram, 0 )); + nStartCol = nAfterColumnIndex; + } + + if (!xChartType.is()) + return; + + // Get shared sequences of current series. Normally multiple data series + // only share "values-x" sequences. (TODO: simplify this logic). + Reference< chart2::XDataSeriesContainer > xSeriesCnt( xChartType, uno::UNO_QUERY ); + lcl_tSharedSeqVec aSharedSequences; + if( xSeriesCnt.is()) + aSharedSequences = lcl_getSharedSequences( xSeriesCnt->getDataSeries()); + + Reference<chart2::XDataSeries> xNewSeries = + m_apDialogModel->insertSeriesAfter(xSeries, xChartType, true); + + if (!xNewSeries.is()) + // Failed to insert new data series to the model. Bail out. + return; + + Reference< chart2::data::XDataSource > xSource( xNewSeries, uno::UNO_QUERY ); + if (xSource.is()) + { + Sequence<Reference<chart2::data::XLabeledDataSequence> > aLSequences = xSource->getDataSequences(); + sal_Int32 nSeqIdx = 0; + sal_Int32 nSeqSize = aLSequences.getLength(); + for (sal_Int32 nIndex = nStartCol; nSeqIdx < nSeqSize; ++nSeqIdx) + { + lcl_tSharedSeqVec::const_iterator aSharedIt( + std::find_if( aSharedSequences.begin(), aSharedSequences.end(), + lcl_RolesOfLSeqMatch( aLSequences[nSeqIdx] ))); + + if( aSharedIt != aSharedSequences.end()) + { + // Shared sequence. Most likely "values-x" sequence. Copy it from existing sequence. + aLSequences[nSeqIdx]->setValues( (*aSharedIt)->getValues()); + aLSequences[nSeqIdx]->setLabel( (*aSharedIt)->getLabel()); + } + else + { + // Insert a new column in the internal data for the new sequence. + xDataProvider->insertSequence( nIndex - 1 ); + + // values + Reference< chart2::data::XDataSequence > xNewSeq( + xDataProvider->createDataSequenceByRangeRepresentation( + OUString::number( nIndex ))); + lcl_copyDataSequenceProperties( + aLSequences[nSeqIdx]->getValues(), xNewSeq ); + aLSequences[nSeqIdx]->setValues( xNewSeq ); + + // labels + Reference< chart2::data::XDataSequence > xNewLabelSeq( + xDataProvider->createDataSequenceByRangeRepresentation( + "label " + + OUString::number( nIndex ))); + lcl_copyDataSequenceProperties( + aLSequences[nSeqIdx]->getLabel(), xNewLabelSeq ); + aLSequences[nSeqIdx]->setLabel( xNewLabelSeq ); + ++nIndex; + } + } + } + + if( nSeriesNumberFormat != 0 ) + { + //give the new series the same number format as the former series especially for bubble charts thus the bubble size values can be edited with same format immediately + Reference< beans::XPropertySet > xNewSeriesProps( xNewSeries, uno::UNO_QUERY ); + if( xNewSeriesProps.is() ) + xNewSeriesProps->setPropertyValue(CHART_UNONAME_NUMFMT , uno::Any(nSeriesNumberFormat)); + } + + updateFromModel(); +} + +void DataBrowserModel::insertComplexCategoryLevel( sal_Int32 nAfterColumnIndex ) +{ + //create a new text column for complex categories + + OSL_ASSERT(m_apDialogModel); + Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + if (!xDataProvider.is()) + return; + + if( !isCategoriesColumn(nAfterColumnIndex) ) + nAfterColumnIndex = getCategoryColumnCount()-1; + + if(nAfterColumnIndex<0) + { + OSL_FAIL( "wrong index for category level insertion" ); + return; + } + + m_apDialogModel->startControllerLockTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + xDataProvider->insertComplexCategoryLevel( nAfterColumnIndex+1 ); + updateFromModel(); +} + +void DataBrowserModel::removeComplexCategoryLevel( sal_Int32 nAtColumnIndex ) +{ + //delete a category column if there is more than one level (in case of a single column we do not get here) + OSL_ENSURE(nAtColumnIndex>0, "wrong index for categories deletion" ); + + Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + if (!xDataProvider.is()) + return; + + m_apDialogModel->startControllerLockTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + xDataProvider->deleteComplexCategoryLevel( nAtColumnIndex ); + + updateFromModel(); +} + +void DataBrowserModel::removeDataSeriesOrComplexCategoryLevel( sal_Int32 nAtColumnIndex ) +{ + OSL_ASSERT(m_apDialogModel); + if (nAtColumnIndex < 0 || o3tl::make_unsigned(nAtColumnIndex) >= m_aColumns.size()) + // Out of bound. + return; + + if (isCategoriesColumn(nAtColumnIndex)) + { + removeComplexCategoryLevel(nAtColumnIndex); + return; + } + + const Reference<chart2::XDataSeries>& xSeries = m_aColumns[nAtColumnIndex].m_xDataSeries; + + m_apDialogModel->deleteSeries(xSeries, getHeaderForSeries(xSeries).m_xChartType); + + //delete sequences from internal data provider that are not used anymore + //but do not delete sequences that are still in use by the remaining series + + Reference< chart2::XInternalDataProvider > xDataProvider( m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + Reference< chart2::data::XDataSource > xSourceOfDeleted( xSeries, uno::UNO_QUERY ); + if (!xDataProvider.is() || !xSourceOfDeleted.is()) + { + // Something went wrong. Bail out. + updateFromModel(); + return; + } + + Reference<chart2::XDataSeriesContainer> xSeriesCnt( + getHeaderForSeries(xSeries).m_xChartType, uno::UNO_QUERY); + if (!xSeriesCnt.is()) + { + // Unexpected happened. Bail out. + updateFromModel(); + return; + } + + // Collect all the remaining data sequences in the same chart type. The + // deleted data series is already gone by this point. + std::vector<Reference<chart2::data::XLabeledDataSequence> > aAllDataSeqs = + DataSeriesHelper::getAllDataSequences(xSeriesCnt->getDataSeries()); + + // Check if the sequences to be deleted are still referenced by any of + // the other data series. If not, mark them for deletion. + std::vector<sal_Int32> aSequenceIndexesToDelete; + const Sequence<Reference<chart2::data::XLabeledDataSequence> > aSequencesOfDeleted = xSourceOfDeleted->getDataSequences(); + for (auto const & labeledDataSeq : aSequencesOfDeleted) + { + // if not used by the remaining series this sequence can be deleted + if( std::none_of( aAllDataSeqs.begin(), aAllDataSeqs.end(), + lcl_RepresentationsOfLSeqMatch( labeledDataSeq )) ) + aSequenceIndexesToDelete.push_back( lcl_getValuesRepresentationIndex( labeledDataSeq ) ); + } + + // delete unnecessary sequences of the internal data + // iterate using greatest index first, so that deletion does not + // shift other sequences that will be deleted later + std::sort( aSequenceIndexesToDelete.begin(), aSequenceIndexesToDelete.end()); + for( std::vector< sal_Int32 >::reverse_iterator aIt( + aSequenceIndexesToDelete.rbegin()); aIt != aSequenceIndexesToDelete.rend(); ++aIt ) + { + if( *aIt != -1 ) + xDataProvider->deleteSequence( *aIt ); + } + + updateFromModel(); +} + +void DataBrowserModel::swapDataSeries( sal_Int32 nFirstColumnIndex ) +{ + OSL_ASSERT(m_apDialogModel); + if( o3tl::make_unsigned( nFirstColumnIndex ) < m_aColumns.size() - 1 ) + { + Reference< chart2::XDataSeries > xSeries( m_aColumns[nFirstColumnIndex].m_xDataSeries ); + if( xSeries.is()) + { + m_apDialogModel->moveSeries( xSeries, DialogModel::MoveDirection::Down ); + updateFromModel(); + } + } +} + +void DataBrowserModel::swapDataPointForAllSeries( sal_Int32 nFirstIndex ) +{ + OSL_ASSERT(m_apDialogModel); + Reference< chart2::XInternalDataProvider > xDataProvider( + m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + // lockControllers + ControllerLockGuardUNO aGuard( m_apDialogModel->getChartModel()); + if( xDataProvider.is()) + xDataProvider->swapDataPointWithNextOneForAllSequences( nFirstIndex ); + // unlockControllers +} + +void DataBrowserModel::insertDataPointForAllSeries( sal_Int32 nAfterIndex ) +{ + Reference< chart2::XInternalDataProvider > xDataProvider( + m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + // lockControllers + ControllerLockGuardUNO aGuard( m_apDialogModel->getChartModel()); + if( xDataProvider.is()) + xDataProvider->insertDataPointForAllSequences( nAfterIndex ); + // unlockControllers +} + +void DataBrowserModel::removeDataPointForAllSeries( sal_Int32 nAtIndex ) +{ + Reference< chart2::XInternalDataProvider > xDataProvider( + m_apDialogModel->getDataProvider(), uno::UNO_QUERY ); + // lockControllers + ControllerLockGuardUNO aGuard( m_apDialogModel->getChartModel()); + if( xDataProvider.is()) + xDataProvider->deleteDataPointForAllSequences( nAtIndex ); + // unlockControllers +} + +DataBrowserModel::tDataHeader DataBrowserModel::getHeaderForSeries( + const Reference< chart2::XDataSeries > & xSeries ) const +{ + for (auto const& elemHeader : m_aHeaders) + { + if( elemHeader.m_xDataSeries == xSeries ) + return elemHeader; + } + return tDataHeader(); +} + +Reference< chart2::XDataSeries > + DataBrowserModel::getDataSeriesByColumn( sal_Int32 nColumn ) const +{ + tDataColumnVector::size_type nIndex( nColumn ); + if( nIndex < m_aColumns.size()) + return m_aColumns[nIndex].m_xDataSeries; + return nullptr; +} + +DataBrowserModel::eCellType DataBrowserModel::getCellType( sal_Int32 nAtColumn ) const +{ + eCellType eResult = TEXT; + tDataColumnVector::size_type nIndex( nAtColumn ); + if( nIndex < m_aColumns.size()) + eResult = m_aColumns[nIndex].m_eCellType; + return eResult; +} + +double DataBrowserModel::getCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow ) +{ + double fResult; + ::rtl::math::setNan( & fResult ); + + tDataColumnVector::size_type nIndex( nAtColumn ); + if( nIndex < m_aColumns.size() && + m_aColumns[ nIndex ].m_xLabeledDataSequence.is()) + { + Reference< chart2::data::XNumericalDataSequence > xData( + m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY ); + if( xData.is()) + { + Sequence< double > aValues( xData->getNumericalData()); + if( nAtRow < aValues.getLength()) + fResult = aValues[nAtRow]; + } + } + return fResult; +} + +uno::Any DataBrowserModel::getCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow ) +{ + uno::Any aResult; + + tDataColumnVector::size_type nIndex( nAtColumn ); + if( nIndex < m_aColumns.size() && + m_aColumns[ nIndex ].m_xLabeledDataSequence.is()) + { + Reference< chart2::data::XDataSequence > xData( + m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues() ); + if( xData.is() ) + { + Sequence< uno::Any > aValues( xData->getData()); + if( nAtRow < aValues.getLength()) + aResult = aValues[nAtRow]; + } + } + return aResult; +} + +OUString DataBrowserModel::getCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow ) +{ + OUString aResult; + + tDataColumnVector::size_type nIndex( nAtColumn ); + if( nIndex < m_aColumns.size() && + m_aColumns[ nIndex ].m_xLabeledDataSequence.is()) + { + Reference< chart2::data::XTextualDataSequence > xData( + m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY ); + if( xData.is()) + { + Sequence< OUString > aValues( xData->getTextualData()); + if( nAtRow < aValues.getLength()) + aResult = aValues[nAtRow]; + } + } + return aResult; +} + +sal_uInt32 DataBrowserModel::getNumberFormatKey( sal_Int32 nAtColumn ) +{ + tDataColumnVector::size_type nIndex( nAtColumn ); + if( nIndex < m_aColumns.size()) + return m_aColumns[ nIndex ].m_nNumberFormatKey; + return 0; +} + +bool DataBrowserModel::setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const uno::Any & rValue ) +{ + bool bResult = false; + tDataColumnVector::size_type nIndex( nAtColumn ); + if( nIndex < m_aColumns.size() && + m_aColumns[ nIndex ].m_xLabeledDataSequence.is()) + { + bResult = true; + try + { + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + // label + if( nAtRow == -1 ) + { + Reference< container::XIndexReplace > xIndexReplace( + m_aColumns[ nIndex ].m_xLabeledDataSequence->getLabel(), uno::UNO_QUERY_THROW ); + xIndexReplace->replaceByIndex( 0, rValue ); + } + else + { + Reference< container::XIndexReplace > xIndexReplace( + m_aColumns[ nIndex ].m_xLabeledDataSequence->getValues(), uno::UNO_QUERY_THROW ); + xIndexReplace->replaceByIndex( nAtRow, rValue ); + } + + m_apDialogModel->startControllerLockTimer(); + //notify change directly to the model (this is necessary here as sequences for complex categories not known directly to the chart model so they do not notify their changes) (for complex categories see issue #i82971#) + Reference< util::XModifiable > xModifiable( m_xChartDocument, uno::UNO_QUERY ); + if( xModifiable.is() ) + xModifiable->setModified(true); + } + catch( const uno::Exception & ) + { + bResult = false; + } + } + return bResult; +} + +bool DataBrowserModel::setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue ) +{ + return (getCellType( nAtColumn ) == NUMBER) && + setCellAny( nAtColumn, nAtRow, uno::Any( fValue )); +} + +bool DataBrowserModel::setCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow, const OUString & rText ) +{ + return (getCellType( nAtColumn ) == TEXT) && + setCellAny( nAtColumn, nAtRow, uno::Any( rText )); +} + +sal_Int32 DataBrowserModel::getColumnCount() const +{ + return static_cast< sal_Int32 >( m_aColumns.size()); +} + +sal_Int32 DataBrowserModel::getMaxRowCount() const +{ + sal_Int32 nResult = 0; + for (auto const& column : m_aColumns) + { + if( column.m_xLabeledDataSequence.is()) + { + Reference< chart2::data::XDataSequence > xSeq( + column.m_xLabeledDataSequence->getValues()); + if( !xSeq.is()) + continue; + sal_Int32 nLength( xSeq->getData().getLength()); + if( nLength > nResult ) + nResult = nLength; + } + } + + return nResult; +} + +OUString DataBrowserModel::getRoleOfColumn( sal_Int32 nColumnIndex ) const +{ + if( nColumnIndex != -1 && + o3tl::make_unsigned( nColumnIndex ) < m_aColumns.size()) + return m_aColumns[ nColumnIndex ].m_aUIRoleName; + return OUString(); +} + +bool DataBrowserModel::isCategoriesColumn( sal_Int32 nColumnIndex ) const +{ + if (nColumnIndex < 0) + return false; + + if (o3tl::make_unsigned(nColumnIndex) >= m_aColumns.size()) + return false; + + // A column is a category when it doesn't have an associated data series. + return !m_aColumns[nColumnIndex].m_xDataSeries.is(); +} + +sal_Int32 DataBrowserModel::getCategoryColumnCount() +{ + sal_Int32 nLastTextColumnIndex = -1; + for (auto const& column : m_aColumns) + { + if( !column.m_xDataSeries.is() ) + nLastTextColumnIndex++; + else + break; + } + return nLastTextColumnIndex+1; +} + +void DataBrowserModel::updateFromModel() +{ + if( !m_xChartDocument.is()) + return; + m_aColumns.clear(); + m_aHeaders.clear(); + + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartDocument )); + if( !xDiagram.is()) + return; + + // set template at DialogModel + uno::Reference< lang::XMultiServiceFactory > xFact( m_xChartDocument->getChartTypeManager(), uno::UNO_QUERY ); + DiagramHelper::tTemplateWithServiceName aTemplateAndService = + DiagramHelper::getTemplateForDiagram( xDiagram, xFact ); + if( aTemplateAndService.first.is()) + m_apDialogModel->setTemplate( aTemplateAndService.first ); + + sal_Int32 nHeaderStart = 0; + sal_Int32 nHeaderEnd = 0; + { + Reference< frame::XModel > xChartModel = m_xChartDocument; + ChartModel* pModel = dynamic_cast<ChartModel*>(xChartModel.get()); + if (!pModel) + return; + ExplicitCategoriesProvider aExplicitCategoriesProvider( ChartModelHelper::getFirstCoordinateSystem(xChartModel), *pModel ); + + const Sequence< Reference< chart2::data::XLabeledDataSequence> >& rSplitCategoriesList( aExplicitCategoriesProvider.getSplitCategoriesList() ); + sal_Int32 nLevelCount = rSplitCategoriesList.getLength(); + for( sal_Int32 nL = 0; nL<nLevelCount; nL++ ) + { + Reference< chart2::data::XLabeledDataSequence > xCategories( rSplitCategoriesList[nL] ); + if( !xCategories.is() ) + continue; + + tDataColumn aCategories; + aCategories.m_xLabeledDataSequence.set( xCategories ); + if( lcl_ShowCategoriesAsDataLabel( xDiagram )) + aCategories.m_aUIRoleName = DialogModel::GetRoleDataLabel(); + else + aCategories.m_aUIRoleName = lcl_getUIRoleName( xCategories ); + aCategories.m_eCellType = TEXTORDATE; + m_aColumns.push_back( aCategories ); + ++nHeaderStart; + } + } + + Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY ); + if( !xCooSysCnt.is()) + return; + const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); + for( Reference< chart2::XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< chart2::XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + const Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); + sal_Int32 nXAxisNumberFormat = DataSeriesHelper::getNumberFormatKeyFromAxis( nullptr, coords, 0, 0 ); + + for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx ) + { + Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY ); + if( xSeriesCnt.is()) + { + OUString aRoleForDataLabelNumberFormat = ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( aChartTypes[nCTIdx] ); + + const Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries()); + lcl_tSharedSeqVec aSharedSequences( lcl_getSharedSequences( aSeries )); + for (auto const& sharedSequence : aSharedSequences) + { + tDataColumn aSharedSequence; + aSharedSequence.m_xLabeledDataSequence = sharedSequence; + aSharedSequence.m_aUIRoleName = lcl_getUIRoleName(sharedSequence); + aSharedSequence.m_eCellType = NUMBER; + // as the sequences are shared it should be ok to take the first series + // @todo: dimension index 0 for x-values used here. This is just a guess. + // Also, the axis index is 0, as there is usually only one x-axis + aSharedSequence.m_nNumberFormatKey = nXAxisNumberFormat; + m_aColumns.push_back( aSharedSequence ); + ++nHeaderStart; + } + for( Reference< chart2::XDataSeries > const & dataSeries : aSeries ) + { + tDataColumnVector::size_type nStartColIndex = m_aColumns.size(); + Reference< chart2::XDataSeries > xSeries( dataSeries ); + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + if( xSource.is()) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqs( xSource->getDataSequences()); + if( !aLSeqs.hasElements() ) + continue; + nHeaderEnd = nHeaderStart; + + // @todo: dimension index 1 for y-values used here. This is just a guess + sal_Int32 nYAxisNumberFormatKey = + DataSeriesHelper::getNumberFormatKeyFromAxis( + dataSeries, coords, 1 ); + + sal_Int32 nSeqIdx=0; + for( ; nSeqIdx<aLSeqs.getLength(); ++nSeqIdx ) + { + sal_Int32 nSequenceNumberFormatKey = nYAxisNumberFormatKey; + OUString aRole = DataSeriesHelper::getRole(aLSeqs[nSeqIdx]); + + if( aRole == aRoleForDataLabelNumberFormat ) + { + nSequenceNumberFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( + Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY )); + } + else if( aRole == "values-x" ) + nSequenceNumberFormatKey = nXAxisNumberFormat; + + if( std::none_of( aSharedSequences.begin(), aSharedSequences.end(), + lcl_RepresentationsOfLSeqMatch( aLSeqs[nSeqIdx] )) ) + { + // no shared sequence + m_aColumns.emplace_back( + dataSeries, + lcl_getUIRoleName( aLSeqs[nSeqIdx] ), + aLSeqs[nSeqIdx], + NUMBER, + nSequenceNumberFormatKey ); + ++nHeaderEnd; + } + // else skip + } + bool bSwapXAndYAxis = false; + try + { + Reference< beans::XPropertySet > xProp( coords, uno::UNO_QUERY ); + xProp->getPropertyValue( "SwapXAndYAxis" ) >>= bSwapXAndYAxis; + } + catch( const beans::UnknownPropertyException & ) {} + + // add ranges for error bars if present for a series + if( StatisticsHelper::usesErrorBarRanges( dataSeries )) + addErrorBarRanges( dataSeries, nYAxisNumberFormatKey, nSeqIdx, nHeaderEnd, true ); + + if( StatisticsHelper::usesErrorBarRanges( dataSeries, /* bYError = */ false )) + addErrorBarRanges( dataSeries, nYAxisNumberFormatKey, nSeqIdx, nHeaderEnd, false ); + + m_aHeaders.emplace_back( + dataSeries, + aChartTypes[nCTIdx], + bSwapXAndYAxis, + nHeaderStart, + nHeaderEnd - 1 ); + + nHeaderStart = nHeaderEnd; + + std::sort( m_aColumns.begin() + nStartColIndex, m_aColumns.end(), implColumnLess() ); + } + } + } + } + } +} + +void DataBrowserModel::addErrorBarRanges( + const Reference< chart2::XDataSeries > & xDataSeries, + sal_Int32 nNumberFormatKey, + sal_Int32 & rInOutSequenceIndex, + sal_Int32 & rInOutHeaderEnd, bool bYError ) +{ + try + { + std::vector< Reference< chart2::data::XLabeledDataSequence > > aSequences; + + Reference< chart2::data::XDataSource > xErrorSource( + StatisticsHelper::getErrorBars( xDataSeries, bYError ), uno::UNO_QUERY ); + + Reference< chart2::data::XLabeledDataSequence > xErrorLSequence( + StatisticsHelper::getErrorLabeledDataSequenceFromDataSource( + xErrorSource, + /* bPositiveValue = */ true, + bYError )); + if( xErrorLSequence.is()) + aSequences.push_back( xErrorLSequence ); + + xErrorLSequence.set( + StatisticsHelper::getErrorLabeledDataSequenceFromDataSource( + xErrorSource, + /* bPositiveValue = */ false, + bYError )); + if( xErrorLSequence.is()) + aSequences.push_back( xErrorLSequence ); + + for (Reference<chart2::data::XLabeledDataSequence> const & rDataSequence : aSequences) + { + m_aColumns.emplace_back(xDataSeries, lcl_getUIRoleName(rDataSequence), + rDataSequence, NUMBER, nNumberFormatKey); + ++rInOutSequenceIndex; + ++rInOutHeaderEnd; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/DataBrowserModel.hxx b/chart2/source/controller/dialogs/DataBrowserModel.hxx new file mode 100644 index 000000000..a4ba44987 --- /dev/null +++ b/chart2/source/controller/dialogs/DataBrowserModel.hxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSERMODEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSERMODEL_HXX + +#include <com/sun/star/uno/Reference.hxx> + +#include <memory> +#include <vector> + +namespace com::sun::star::chart2 { class XChartDocument; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace com::sun::star::chart2 { + class XDataSeries; + class XChartType; +} + +namespace chart +{ + +class DialogModel; + +class DataBrowserModel final +{ +public: + explicit DataBrowserModel( + const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc, + const css::uno::Reference< css::uno::XComponentContext > & xContext ); + ~DataBrowserModel(); + + /** Inserts a new data series after the data series to which the data column + with index nAfterColumnIndex belongs. + */ + void insertDataSeries( sal_Int32 nAfterColumnIndex ); + + /** Inserts a new text column for complex categories. + */ + void insertComplexCategoryLevel( sal_Int32 nAfterColumnIndex ); + + /** Removes a data series to which the data column with index nAtColumnIndex + belongs. + */ + void removeDataSeriesOrComplexCategoryLevel( sal_Int32 nAtColumnIndex ); + + /** Swaps the series to which the data column with index nFirstIndex belongs + with the next series (which starts at an index >= nFirstIndex + 1) + */ + void swapDataSeries( sal_Int32 nFirstIndex ); + void swapDataPointForAllSeries( sal_Int32 nFirstIndex ); + + void insertDataPointForAllSeries( sal_Int32 nAfterIndex ); + void removeDataPointForAllSeries( sal_Int32 nAtIndex ); + + enum eCellType + { + NUMBER, + TEXT, + TEXTORDATE + }; + + eCellType getCellType( sal_Int32 nAtColumn ) const; + /// If getCellType( nAtColumn, nAtRow ) returns TEXT, the result will be Nan + double getCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow ); + OUString getCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow ); + css::uno::Any getCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow ); + sal_uInt32 getNumberFormatKey( sal_Int32 nAtColumn ); + + /// returns </sal_True> if the number could successfully be set at the given position + bool setCellNumber( sal_Int32 nAtColumn, sal_Int32 nAtRow, double fValue ); + /// returns </sal_True> if the text could successfully be set at the given position + bool setCellText( sal_Int32 nAtColumn, sal_Int32 nAtRow, const OUString & rText ); + bool setCellAny( sal_Int32 nAtColumn, sal_Int32 nAtRow, const css::uno::Any & aValue ); + + sal_Int32 getColumnCount() const; + sal_Int32 getMaxRowCount() const; + + // returns the UI string of the corresponding role + OUString getRoleOfColumn( sal_Int32 nColumnIndex ) const; + bool isCategoriesColumn( sal_Int32 nColumnIndex ) const; + + struct tDataHeader + { + css::uno::Reference< css::chart2::XDataSeries > m_xDataSeries; + css::uno::Reference< css::chart2::XChartType > m_xChartType; + bool m_bSwapXAndYAxis; + sal_Int32 m_nStartColumn; + sal_Int32 m_nEndColumn; + + // default CTOR + tDataHeader() : + m_bSwapXAndYAxis( false ), + m_nStartColumn( -1 ), + m_nEndColumn( -1 ) + {} + // "full" CTOR + tDataHeader( + css::uno::Reference< css::chart2::XDataSeries > const & xDataSeries, + css::uno::Reference< css::chart2::XChartType > const &xChartType, + bool bSwapXAndYAxis, + sal_Int32 nStartColumn, + sal_Int32 nEndColumn ) : + m_xDataSeries( xDataSeries ), + m_xChartType( xChartType ), + m_bSwapXAndYAxis( bSwapXAndYAxis ), + m_nStartColumn( nStartColumn ), + m_nEndColumn( nEndColumn ) + {} + }; + + typedef std::vector< tDataHeader > tDataHeaderVector; + + const tDataHeaderVector& getDataHeaders() const { return m_aHeaders;} + + tDataHeader getHeaderForSeries( + const css::uno::Reference< css::chart2::XDataSeries > &xSeries ) const; + + css::uno::Reference< css::chart2::XDataSeries > + getDataSeriesByColumn( sal_Int32 nColumn ) const; + +private: + void updateFromModel(); + + void removeComplexCategoryLevel( sal_Int32 nAtColumnIndex ); + + void addErrorBarRanges( + const css::uno::Reference<css::chart2::XDataSeries > & xDataSeries, + sal_Int32 nNumberFormatKey, + sal_Int32 & rInOutSequenceIndex, + sal_Int32 & rInOutHeaderEnd, bool bYError ); + + sal_Int32 getCategoryColumnCount(); + + css::uno::Reference< css::chart2::XChartDocument > m_xChartDocument; + std::unique_ptr< DialogModel > m_apDialogModel; + + struct tDataColumn; + struct implColumnLess; + + typedef std::vector< tDataColumn > tDataColumnVector; + + tDataColumnVector m_aColumns; + tDataHeaderVector m_aHeaders; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DATABROWSERMODEL_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/DialogModel.cxx b/chart2/source/controller/dialogs/DialogModel.cxx new file mode 100644 index 000000000..b4bdbae65 --- /dev/null +++ b/chart2/source/controller/dialogs/DialogModel.cxx @@ -0,0 +1,860 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "DialogModel.hxx" +#include <RangeSelectionHelper.hxx> +#include <DataSeriesHelper.hxx> +#include <DataSourceHelper.hxx> +#include <DiagramHelper.hxx> +#include <strings.hrc> +#include <ResId.hxx> +#include <ControllerLockGuard.hxx> +#include <ChartTypeHelper.hxx> +#include <ThreeDHelper.hxx> +#include <ChartModel.hxx> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/data/XDataSink.hpp> +#include <comphelper/sequence.hxx> +#include <tools/diagnose_ex.h> + +#include <rtl/ustring.hxx> + +#include <utility> +#include <algorithm> +#include <iterator> +#include <numeric> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +const OUString lcl_aLabelRole( "label" ); + +struct lcl_ChartTypeToSeriesCnt +{ + Reference< XDataSeriesContainer > operator() ( + const Reference< XChartType > & xChartType ) + { + return Reference< XDataSeriesContainer >::query( xChartType ); + } +}; + +OUString lcl_ConvertRole( const OUString & rRoleString ) +{ + OUString aResult( rRoleString ); + + typedef std::map< OUString, OUString > tTranslationMap; + static tTranslationMap aTranslationMap = + { + { "categories", ::chart::SchResId( STR_DATA_ROLE_CATEGORIES ) }, + { "error-bars-x", ::chart::SchResId( STR_DATA_ROLE_X_ERROR ) }, + { "error-bars-x-positive", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_POSITIVE ) }, + { "error-bars-x-negative", ::chart::SchResId( STR_DATA_ROLE_X_ERROR_NEGATIVE ) }, + { "error-bars-y", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR ) }, + { "error-bars-y-positive", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_POSITIVE ) }, + { "error-bars-y-negative", ::chart::SchResId( STR_DATA_ROLE_Y_ERROR_NEGATIVE ) }, + { "label", ::chart::SchResId( STR_DATA_ROLE_LABEL ) }, + { "values-first", ::chart::SchResId( STR_DATA_ROLE_FIRST ) }, + { "values-last", ::chart::SchResId( STR_DATA_ROLE_LAST ) }, + { "values-max", ::chart::SchResId( STR_DATA_ROLE_MAX ) }, + { "values-min", ::chart::SchResId( STR_DATA_ROLE_MIN ) }, + { "values-x", ::chart::SchResId( STR_DATA_ROLE_X ) }, + { "values-y", ::chart::SchResId( STR_DATA_ROLE_Y ) }, + { "values-size", ::chart::SchResId( STR_DATA_ROLE_SIZE ) }, + { "FillColor", ::chart::SchResId( STR_PROPERTY_ROLE_FILLCOLOR ) }, + { "BorderColor", ::chart::SchResId( STR_PROPERTY_ROLE_BORDERCOLOR ) }, + }; + + tTranslationMap::const_iterator aIt( aTranslationMap.find( rRoleString )); + if( aIt != aTranslationMap.end()) + { + aResult = (*aIt).second; + } + return aResult; +} + +typedef std::map< OUString, sal_Int32 > lcl_tRoleIndexMap; + +lcl_tRoleIndexMap lcl_createRoleIndexMap() +{ + lcl_tRoleIndexMap aMap; + sal_Int32 nIndex = 0; + + aMap[ "label" ] = ++nIndex; + aMap[ "categories" ] = ++nIndex; + aMap[ "values-x" ] = ++nIndex; + aMap[ "values-y" ] = ++nIndex; + aMap[ "error-bars-x" ] = ++nIndex; + aMap[ "error-bars-x-positive" ] = ++nIndex; + aMap[ "error-bars-x-negative" ] = ++nIndex; + aMap[ "error-bars-y" ] = ++nIndex; + aMap[ "error-bars-y-positive" ] = ++nIndex; + aMap[ "error-bars-y-negative" ] = ++nIndex; + aMap[ "values-first" ] = ++nIndex; + aMap[ "values-min" ] = ++nIndex; + aMap[ "values-max" ] = ++nIndex; + aMap[ "values-last" ] = ++nIndex; + aMap[ "values-size" ] = ++nIndex; + + return aMap; +} + +struct lcl_DataSeriesContainerAppend +{ + typedef Reference< XDataSeriesContainer > value_type; + typedef std::vector< ::chart::DialogModel::tSeriesWithChartTypeByName > tContainerType; + + explicit lcl_DataSeriesContainerAppend( tContainerType * rCnt ) + : m_rDestCnt( rCnt ) + {} + + lcl_DataSeriesContainerAppend & operator= ( const value_type & xVal ) + { + try + { + if( xVal.is()) + { + const Sequence< Reference< XDataSeries > > aSeq( xVal->getDataSeries()); + OUString aRole( "values-y" ); + Reference< XChartType > xCT( xVal, uno::UNO_QUERY ); + if( xCT.is()) + aRole = xCT->getRoleOfSequenceForSeriesLabel(); + for( Reference< XDataSeries > const & dataSeries : aSeq ) + { + m_rDestCnt->push_back( + ::chart::DialogModel::tSeriesWithChartTypeByName( + ::chart::DataSeriesHelper::getDataSeriesLabel( dataSeries, aRole ), + std::make_pair( dataSeries, xCT ))); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return *this; + } + + // Implement output operator requirements as required by std::copy (and + // implement prefix increment in terms of postfix increment to avoid unused + // member function warnings for the latter in the common case where + // std::copy would not actually need it): + lcl_DataSeriesContainerAppend & operator* () { return *this; } + lcl_DataSeriesContainerAppend & operator++ () { return operator++(0); } + lcl_DataSeriesContainerAppend & operator++ (int) { return *this; } + +private: + tContainerType * m_rDestCnt; +}; + +struct lcl_RolesWithRangeAppend +{ + typedef Reference< data::XLabeledDataSequence > value_type; + typedef ::chart::DialogModel::tRolesWithRanges tContainerType; + + explicit lcl_RolesWithRangeAppend( tContainerType * rCnt, + const OUString & aLabelRole ) + : m_rDestCnt( rCnt ), + m_aRoleForLabelSeq( aLabelRole ) + {} + + lcl_RolesWithRangeAppend & operator= ( const value_type & xVal ) + { + try + { + if( xVal.is()) + { + // data sequence + Reference< data::XDataSequence > xSeq( xVal->getValues()); + if( xSeq.is()) + { + OUString aRole; + Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW ); + if( xProp->getPropertyValue( "Role" ) >>= aRole ) + { + m_rDestCnt->emplace(aRole, xSeq->getSourceRangeRepresentation()); + // label + if( aRole == m_aRoleForLabelSeq ) + { + Reference< data::XDataSequence > xLabelSeq( xVal->getLabel()); + if( xLabelSeq.is()) + { + m_rDestCnt->emplace( + lcl_aLabelRole, xLabelSeq->getSourceRangeRepresentation()); + } + } + } + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return *this; + } + + // Implement output operator requirements as required by std::copy (and + // implement prefix increment in terms of postfix increment to avoid unused + // member function warnings for the latter in the common case where + // std::copy would not actually need it): + lcl_RolesWithRangeAppend & operator* () { return *this; } + lcl_RolesWithRangeAppend & operator++ () { return operator++(0); } + lcl_RolesWithRangeAppend & operator++ (int) { return *this; } + +private: + tContainerType * m_rDestCnt; + OUString m_aRoleForLabelSeq; +}; + +} + +namespace std +{ + template<> struct iterator_traits<lcl_DataSeriesContainerAppend> + { + typedef std::output_iterator_tag iterator_category; + typedef Reference< XDataSeriesContainer > value_type; + }; + + template<> struct iterator_traits<lcl_RolesWithRangeAppend> + { + typedef std::output_iterator_tag iterator_category; + typedef Reference< data::XLabeledDataSequence > value_type; + }; +} + +namespace { + +void lcl_SetSequenceRole( + const Reference< data::XDataSequence > & xSeq, + const OUString & rRole ) +{ + Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY ); + if( xProp.is()) + xProp->setPropertyValue( "Role" , uno::Any( rRole )); +} + +Reference< XDataSeries > lcl_CreateNewSeries( + const Reference< uno::XComponentContext > & xContext, + const Reference< XChartType > & xChartType, + sal_Int32 nNewSeriesIndex, + sal_Int32 nTotalNumberOfSeriesInCTGroup, + const Reference< XDiagram > & xDiagram, + const Reference< XChartTypeTemplate > & xTemplate, + bool bCreateDataCachedSequences ) +{ + // create plain series + Reference< XDataSeries > xResult( + xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.chart2.DataSeries" , + xContext ), uno::UNO_QUERY ); + if( xTemplate.is()) + { + Reference< beans::XPropertySet > xResultProp( xResult, uno::UNO_QUERY ); + if( xResultProp.is()) + { + // @deprecated: correct default color should be found by view + // without setting it as hard attribute + Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xColorScheme.is()) + xResultProp->setPropertyValue( "Color" , uno::Any( xColorScheme->getColorByIndex( nNewSeriesIndex ))); + } + sal_Int32 nGroupIndex=0; + if( xChartType.is()) + { + Sequence< Reference< XChartType > > aCTs( + ::chart::DiagramHelper::getChartTypesFromDiagram( xDiagram )); + for( ; nGroupIndex<aCTs.getLength(); ++nGroupIndex) + if( aCTs[nGroupIndex] == xChartType ) + break; + if( nGroupIndex == aCTs.getLength()) + nGroupIndex = 0; + } + xTemplate->applyStyle( xResult, nGroupIndex, nNewSeriesIndex, nTotalNumberOfSeriesInCTGroup ); + } + + if( bCreateDataCachedSequences ) + { + // set chart type specific roles + Reference< data::XDataSink > xSink( xResult, uno::UNO_QUERY ); + if( xChartType.is() && xSink.is()) + { + std::vector< Reference< data::XLabeledDataSequence > > aNewSequences; + const OUString aRoleOfSeqForSeriesLabel = xChartType->getRoleOfSequenceForSeriesLabel(); + const OUString aLabel(::chart::SchResId(STR_DATA_UNNAMED_SERIES)); + const Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); + const Sequence< OUString > aOptRoles( xChartType->getSupportedOptionalRoles()); + + for(OUString const & role : aRoles) + { + if( role == lcl_aLabelRole ) + continue; + Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence() ); + lcl_SetSequenceRole( xSeq, role ); + // assert that aRoleOfSeqForSeriesLabel is part of the mandatory roles + if( role == aRoleOfSeqForSeriesLabel ) + { + Reference< data::XDataSequence > xLabel( ::chart::DataSourceHelper::createCachedDataSequence( aLabel )); + lcl_SetSequenceRole( xLabel, lcl_aLabelRole ); + aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq, xLabel )); + } + else + aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq )); + } + + for(OUString const & role : aOptRoles) + { + if( role == lcl_aLabelRole ) + continue; + Reference< data::XDataSequence > xSeq( ::chart::DataSourceHelper::createCachedDataSequence()); + lcl_SetSequenceRole( xSeq, role ); + aNewSequences.push_back( ::chart::DataSourceHelper::createLabeledDataSequence( xSeq )); + } + + xSink->setData( comphelper::containerToSequence( aNewSequences )); + } + } + + return xResult; +} + +struct lcl_addSeriesNumber +{ + sal_Int32 operator() ( sal_Int32 nCurrentNumber, const Reference< XDataSeriesContainer > & xCnt ) const + { + if( xCnt.is()) + return nCurrentNumber + (xCnt->getDataSeries().getLength()); + return nCurrentNumber; + } +}; + +} // anonymous namespace + +namespace chart +{ + +DialogModelTimeBasedInfo::DialogModelTimeBasedInfo(): + bTimeBased(false), + nStart(0), + nEnd(0) +{ +} + +DialogModel::DialogModel( + const Reference< XChartDocument > & xChartDocument, + const Reference< uno::XComponentContext > & xContext ) : + m_xChartDocument( xChartDocument ), + m_xContext( xContext ), + m_aTimerTriggeredControllerLock( m_xChartDocument ) +{ +} + +DialogModel::~DialogModel() +{ + if(maTimeBasedInfo.bTimeBased) + { + getModel().setTimeBasedRange(maTimeBasedInfo.nStart, maTimeBasedInfo.nEnd); + } +} + +void DialogModel::setTemplate( + const Reference< XChartTypeTemplate > & xTemplate ) +{ + m_xTemplate = xTemplate; +} + +std::shared_ptr< RangeSelectionHelper > const & + DialogModel::getRangeSelectionHelper() const +{ + if( ! m_spRangeSelectionHelper) + m_spRangeSelectionHelper = + std::make_shared<RangeSelectionHelper>( m_xChartDocument ); + + return m_spRangeSelectionHelper; +} + +Reference< frame::XModel > DialogModel::getChartModel() const +{ + return m_xChartDocument; +} + +Reference< data::XDataProvider > DialogModel::getDataProvider() const +{ + Reference< data::XDataProvider > xResult; + if( m_xChartDocument.is()) + xResult.set( m_xChartDocument->getDataProvider()); + return xResult; +} + +std::vector< Reference< XDataSeriesContainer > > + DialogModel::getAllDataSeriesContainers() const +{ + std::vector< Reference< XDataSeriesContainer > > aResult; + + try + { + Reference< XDiagram > xDiagram; + if( m_xChartDocument.is()) + xDiagram.set( m_xChartDocument->getFirstDiagram()); + if( xDiagram.is()) + { + Reference< XCoordinateSystemContainer > xCooSysCnt( + xDiagram, uno::UNO_QUERY_THROW ); + const Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( Reference< XCoordinateSystem > const & coords : aCooSysSeq ) + { + Reference< XChartTypeContainer > xCTCnt( coords, uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + std::transform( + aChartTypeSeq.begin(), aChartTypeSeq.end(), + std::back_inserter( aResult ), + lcl_ChartTypeToSeriesCnt() ); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + return aResult; +} + +std::vector< DialogModel::tSeriesWithChartTypeByName > + DialogModel::getAllDataSeriesWithLabel() const +{ + std::vector< tSeriesWithChartTypeByName > aResult; + std::vector< Reference< XDataSeriesContainer > > aContainers( + getAllDataSeriesContainers()); + + std::copy( aContainers.begin(), aContainers.end(), + lcl_DataSeriesContainerAppend( &aResult )); + return aResult; +} + +namespace { + +void addMissingRoles(DialogModel::tRolesWithRanges& rResult, const uno::Sequence<OUString>& rRoles) +{ + for(OUString const & role : rRoles) + { + if(rResult.find(role) == rResult.end()) + rResult.emplace(role, OUString()); + } +} + +/** + * Insert a new data series to chart type at position after specified series + * position. + * + * @param xChartType chart type that contains data series. + * @param xSeries insertion position. The new series will be inserted after + * this one. + * @param xNewSeries new data series to insert. + */ +void addNewSeriesToContainer( + const Reference<XChartType>& xChartType, + const Reference<XDataSeries>& xSeries, + const Reference<XDataSeries>& xNewSeries ) +{ + Reference<XDataSeriesContainer> xSeriesCnt(xChartType, uno::UNO_QUERY_THROW); + auto aSeries = comphelper::sequenceToContainer<std::vector<Reference<XDataSeries> >>(xSeriesCnt->getDataSeries()); + + std::vector<Reference<XDataSeries> >::iterator aIt = + std::find( aSeries.begin(), aSeries.end(), xSeries); + + if( aIt == aSeries.end()) + // if we have no series we insert at the first position. + aIt = aSeries.begin(); + else + // vector::insert inserts before, so we have to advance + ++aIt; + + aSeries.insert(aIt, xNewSeries); + xSeriesCnt->setDataSeries(comphelper::containerToSequence(aSeries)); +} + +} + +DialogModel::tRolesWithRanges DialogModel::getRolesWithRanges( + const Reference< XDataSeries > & xSeries, + const OUString & aRoleOfSequenceForLabel, + const Reference< chart2::XChartType > & xChartType ) +{ + DialogModel::tRolesWithRanges aResult; + try + { + Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY_THROW ); + const Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSource->getDataSequences()); + std::copy( aSeq.begin(), aSeq.end(), + lcl_RolesWithRangeAppend( &aResult, aRoleOfSequenceForLabel )); + if( xChartType.is()) + { + // add missing mandatory roles + Sequence< OUString > aRoles( xChartType->getSupportedMandatoryRoles()); + addMissingRoles(aResult, aRoles); + + // add missing optional roles + aRoles = xChartType->getSupportedOptionalRoles(); + addMissingRoles(aResult, aRoles); + + // add missing property roles + aRoles = xChartType->getSupportedPropertyRoles(); + addMissingRoles(aResult, aRoles); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return aResult; +} + +void DialogModel::moveSeries( + const Reference< XDataSeries > & xSeries, + MoveDirection eDirection ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + DiagramHelper::moveSeries( xDiagram, xSeries, eDirection==MoveDirection::Down ); +} + +Reference< chart2::XDataSeries > DialogModel::insertSeriesAfter( + const Reference< XDataSeries > & xSeries, + const Reference< XChartType > & xChartType, + bool bCreateDataCachedSequences /* = false */ ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + Reference< XDataSeries > xNewSeries; + + try + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + sal_Int32 nSeriesInChartType = 0; + const sal_Int32 nTotalSeries = countSeries(); + if( xChartType.is()) + { + Reference< XDataSeriesContainer > xCnt( xChartType, uno::UNO_QUERY_THROW ); + nSeriesInChartType = xCnt->getDataSeries().getLength(); + } + + // create new series + xNewSeries.set( + lcl_CreateNewSeries( + m_xContext, + xChartType, + nTotalSeries, // new series' index + nSeriesInChartType, + xDiagram, + m_xTemplate, + bCreateDataCachedSequences )); + + // add new series to container + if( xNewSeries.is()) + addNewSeriesToContainer(xChartType, xSeries, xNewSeries); + + ThreeDHelper::setScheme( xDiagram, e3DScheme ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xNewSeries; +} + +void DialogModel::deleteSeries( + const Reference< XDataSeries > & xSeries, + const Reference< XChartType > & xChartType ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + DataSeriesHelper::deleteSeries( xSeries, xChartType ); +} + +Reference< data::XLabeledDataSequence > DialogModel::getCategories() const +{ + Reference< data::XLabeledDataSequence > xResult; + try + { + if( m_xChartDocument.is()) + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + xResult.set( DiagramHelper::getCategoriesFromDiagram( xDiagram )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return xResult; +} + +void DialogModel::setCategories( const Reference< chart2::data::XLabeledDataSequence > & xCategories ) +{ + if( !m_xChartDocument.is()) + return; + + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + if( !xDiagram.is()) + return; + + // categories + bool bSupportsCategories = true; + + Reference< XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + if( xFirstChartType.is() ) + { + sal_Int32 nAxisType = ChartTypeHelper::getAxisType( xFirstChartType, 0 ); // x-axis + bSupportsCategories = (nAxisType == AxisType::CATEGORY); + } + DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram, true, bSupportsCategories ); +} + +OUString DialogModel::getCategoriesRange() const +{ + Reference< data::XLabeledDataSequence > xLSeq( getCategories()); + OUString aRange; + if( xLSeq.is()) + { + Reference< data::XDataSequence > xSeq( xLSeq->getValues()); + if( xSeq.is()) + aRange = xSeq->getSourceRangeRepresentation(); + } + return aRange; +} + +bool DialogModel::isCategoryDiagram() const +{ + bool bRet = false; + if( m_xChartDocument.is()) + bRet = DiagramHelper::isCategoryDiagram( m_xChartDocument->getFirstDiagram() ); + return bRet; +} + +void DialogModel::detectArguments( + OUString & rOutRangeString, + bool & rOutUseColumns, + bool & rOutFirstCellAsLabel, + bool & rOutHasCategories ) const +{ + try + { + uno::Sequence< sal_Int32 > aSequenceMapping;//todo YYYX + + // Note: unused data is currently not supported in being passed to detectRangeSegmentation + if( m_xChartDocument.is()) + DataSourceHelper::detectRangeSegmentation( + Reference< frame::XModel >( m_xChartDocument, uno::UNO_QUERY_THROW ), + rOutRangeString, aSequenceMapping, rOutUseColumns, rOutFirstCellAsLabel, rOutHasCategories ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +bool DialogModel::allArgumentsForRectRangeDetected() const +{ + return DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument ); +} + +void DialogModel::startControllerLockTimer() +{ + m_aTimerTriggeredControllerLock.startTimer(); +} + +void DialogModel::setData( + const Sequence< beans::PropertyValue > & rArguments ) +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aLockedControllers( m_xChartDocument ); + + Reference< data::XDataProvider > xDataProvider( getDataProvider()); + if( ! xDataProvider.is() || + ! m_xTemplate.is() ) + { + OSL_FAIL( "Model objects missing" ); + return; + } + + try + { + Reference< chart2::data::XDataSource > xDataSource( + xDataProvider->createDataSource( rArguments ) ); + + Reference< chart2::XDataInterpreter > xInterpreter( + m_xTemplate->getDataInterpreter()); + if( xInterpreter.is()) + { + Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); + ThreeDLookScheme e3DScheme = ThreeDHelper::detectScheme( xDiagram ); + + std::vector< Reference< XDataSeries > > aSeriesToReUse( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + applyInterpretedData( + xInterpreter->interpretDataSource( + xDataSource, rArguments, + comphelper::containerToSequence( aSeriesToReUse )), + aSeriesToReUse); + + ThreeDHelper::setScheme( xDiagram, e3DScheme ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void DialogModel::setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const +{ + maTimeBasedInfo.nStart = nStart; + maTimeBasedInfo.nEnd = nEnd; + maTimeBasedInfo.bTimeBased = bTimeBased; +} + +OUString DialogModel::ConvertRoleFromInternalToUI( const OUString & rRoleString ) +{ + return lcl_ConvertRole( rRoleString ); +} + +OUString DialogModel::GetRoleDataLabel() +{ + return ::chart::SchResId(STR_OBJECT_DATALABELS); +} + +sal_Int32 DialogModel::GetRoleIndexForSorting( const OUString & rInternalRoleString ) +{ + static lcl_tRoleIndexMap aRoleIndexMap = lcl_createRoleIndexMap(); + + lcl_tRoleIndexMap::const_iterator aIt( aRoleIndexMap.find( rInternalRoleString )); + if( aIt != aRoleIndexMap.end()) + return aIt->second; + + return 0; +} + +// private methods + +void DialogModel::applyInterpretedData( + const InterpretedData & rNewData, + const std::vector< Reference< XDataSeries > > & rSeriesToReUse ) +{ + if( ! m_xChartDocument.is()) + return; + + m_aTimerTriggeredControllerLock.startTimer(); + Reference< XDiagram > xDiagram( m_xChartDocument->getFirstDiagram()); + if( !xDiagram.is()) + return; + + // styles + if( m_xTemplate.is() ) + { + sal_Int32 nGroup = 0; + sal_Int32 nSeriesCounter = 0; + sal_Int32 nNewSeriesIndex = static_cast< sal_Int32 >( rSeriesToReUse.size()); + const sal_Int32 nOuterSize=rNewData.Series.getLength(); + + for(; nGroup < nOuterSize; ++nGroup) + { + Sequence< Reference< XDataSeries > > aSeries( rNewData.Series[ nGroup ] ); + const sal_Int32 nSeriesInGroup = aSeries.getLength(); + for( sal_Int32 nSeries=0; nSeries<nSeriesInGroup; ++nSeries, ++nSeriesCounter ) + { + if( std::find( rSeriesToReUse.begin(), rSeriesToReUse.end(), aSeries[nSeries] ) + == rSeriesToReUse.end()) + { + Reference< beans::XPropertySet > xSeriesProp( aSeries[nSeries], uno::UNO_QUERY ); + if( xSeriesProp.is()) + { + // @deprecated: correct default color should be found by view + // without setting it as hard attribute + Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + if( xColorScheme.is()) + xSeriesProp->setPropertyValue( "Color" , + uno::Any( xColorScheme->getColorByIndex( nSeriesCounter ))); + } + m_xTemplate->applyStyle( aSeries[nSeries], nGroup, nNewSeriesIndex++, nSeriesInGroup ); + } + } + } + } + + // data series + std::vector< Reference< XDataSeriesContainer > > aSeriesCnt( getAllDataSeriesContainers()); + auto aNewSeries( + comphelper::sequenceToContainer<std::vector< Sequence< Reference< XDataSeries > > >>( rNewData.Series )); + + OSL_ASSERT( aSeriesCnt.size() == aNewSeries.size()); + + std::vector< Sequence< Reference< XDataSeries > > >::const_iterator aSrcIt( aNewSeries.begin()); + std::vector< Reference< XDataSeriesContainer > >::iterator aDestIt( aSeriesCnt.begin()); + for(; aSrcIt != aNewSeries.end() && aDestIt != aSeriesCnt.end(); + ++aSrcIt, ++aDestIt ) + { + try + { + OSL_ASSERT( (*aDestIt).is()); + (*aDestIt)->setDataSeries( *aSrcIt ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + DialogModel::setCategories(rNewData.Categories); +} + +sal_Int32 DialogModel::countSeries() const +{ + std::vector< Reference< XDataSeriesContainer > > aCnt( getAllDataSeriesContainers()); + return std::accumulate( aCnt.begin(), aCnt.end(), 0, lcl_addSeriesNumber()); +} + +ChartModel& DialogModel::getModel() const +{ + uno::Reference< frame::XModel > xModel = getChartModel(); + ChartModel* pModel = dynamic_cast<ChartModel*>(xModel.get()); + assert(pModel); + return *pModel; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/DialogModel.hxx b/chart2/source/controller/dialogs/DialogModel.hxx new file mode 100644 index 000000000..8b3a2a5c0 --- /dev/null +++ b/chart2/source/controller/dialogs/DialogModel.hxx @@ -0,0 +1,183 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DIALOGMODEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DIALOGMODEL_HXX + +#include <TimerTriggeredControllerLock.hxx> +#include <rtl/ustring.hxx> + +#include <map> +#include <memory> +#include <vector> + +namespace chart { class ChartModel; } +namespace com::sun::star::beans { struct PropertyValue; } +namespace com::sun::star::chart2 { class XChartDocument; } +namespace com::sun::star::frame { class XModel; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::uno { template <class E> class Sequence; } + +namespace com::sun::star::chart2 { + class XDataSeriesContainer; + class XDataSeries; + class XChartType; + class XChartTypeTemplate; + struct InterpretedData; + namespace data { + class XDataProvider; + class XLabeledDataSequence; + } +} + +namespace chart +{ + +class RangeSelectionHelper; + +struct DialogModelTimeBasedInfo +{ + DialogModelTimeBasedInfo(); + + bool bTimeBased; + sal_Int32 nStart; + sal_Int32 nEnd; +}; + +class DialogModel +{ +public: + explicit DialogModel( + const css::uno::Reference< css::chart2::XChartDocument > & xChartDocument, + const css::uno::Reference< css::uno::XComponentContext > & xContext ); + ~DialogModel(); + + typedef std::pair< + OUString, + std::pair< css::uno::Reference< css::chart2::XDataSeries >, + css::uno::Reference< css::chart2::XChartType > > > + tSeriesWithChartTypeByName; + + typedef std::map< OUString, OUString > + tRolesWithRanges; + + void setTemplate( + const css::uno::Reference< css::chart2::XChartTypeTemplate > & xTemplate ); + + std::shared_ptr< RangeSelectionHelper > const & + getRangeSelectionHelper() const; + + css::uno::Reference< css::frame::XModel > + getChartModel() const; + + css::uno::Reference< css::chart2::data::XDataProvider > + getDataProvider() const; + + std::vector< css::uno::Reference< css::chart2::XDataSeriesContainer > > + getAllDataSeriesContainers() const; + + std::vector< tSeriesWithChartTypeByName > + getAllDataSeriesWithLabel() const; + + static tRolesWithRanges getRolesWithRanges( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const OUString & aRoleOfSequenceForLabel, + const css::uno::Reference< css::chart2::XChartType > & xChartType ); + + enum class MoveDirection + { + Down, Up + }; + + void moveSeries( const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + MoveDirection eDirection ); + + /// @return the newly inserted series + css::uno::Reference< + css::chart2::XDataSeries > insertSeriesAfter( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XChartType > & xChartType, + bool bCreateDataCachedSequences = false ); + + void deleteSeries( + const css::uno::Reference< css::chart2::XDataSeries > & xSeries, + const css::uno::Reference< css::chart2::XChartType > & xChartType ); + + css::uno::Reference< css::chart2::data::XLabeledDataSequence > + getCategories() const; + + void setCategories( const css::uno::Reference< css::chart2::data::XLabeledDataSequence > & xCategories ); + + OUString getCategoriesRange() const; + + bool isCategoryDiagram() const; + + void detectArguments( + OUString & rOutRangeString, + bool & rOutUseColumns, bool & rOutFirstCellAsLabel, bool & rOutHasCategories ) const; + + bool allArgumentsForRectRangeDetected() const; + + void setData( const css::uno::Sequence< css::beans::PropertyValue > & rArguments ); + + void setTimeBasedRange( bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const; + + const DialogModelTimeBasedInfo& getTimeBasedInfo() const { return maTimeBasedInfo; } + + void startControllerLockTimer(); + + static OUString ConvertRoleFromInternalToUI( const OUString & rRoleString ); + static OUString GetRoleDataLabel(); + + // pass a role string (not translated) and get an index that serves for + // relative ordering, to get e.g. x-values and y-values in the right order + static sal_Int32 GetRoleIndexForSorting( const OUString & rInternalRoleString ); + + ChartModel& getModel() const; + +private: + css::uno::Reference< css::chart2::XChartDocument > + m_xChartDocument; + + css::uno::Reference< css::chart2::XChartTypeTemplate > + m_xTemplate; + + css::uno::Reference< css::uno::XComponentContext > + m_xContext; + + mutable std::shared_ptr< RangeSelectionHelper > + m_spRangeSelectionHelper; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + +private: + void applyInterpretedData( + const css::chart2::InterpretedData & rNewData, + const std::vector< css::uno::Reference< css::chart2::XDataSeries > > & rSeriesToReUse ); + + sal_Int32 countSeries() const; + + mutable DialogModelTimeBasedInfo maTimeBasedInfo; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DIALOGMODEL_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/ObjectNameProvider.cxx b/chart2/source/controller/dialogs/ObjectNameProvider.cxx new file mode 100644 index 000000000..2a3d954a6 --- /dev/null +++ b/chart2/source/controller/dialogs/ObjectNameProvider.cxx @@ -0,0 +1,865 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ObjectNameProvider.hxx> +#include <ResId.hxx> +#include <strings.hrc> +#include <AxisHelper.hxx> +#include <ChartModel.hxx> +#include <ChartModelHelper.hxx> +#include <DiagramHelper.hxx> +#include <DataSeriesHelper.hxx> +#include <TitleHelper.hxx> +#include <ExplicitCategoriesProvider.hxx> +#include <CommonConverters.hxx> +#include <NumberFormatterWrapper.hxx> +#include <RegressionCurveHelper.hxx> +#include <rtl/math.hxx> +#include <rtl/ustring.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <unotools/localedatawrapper.hxx> + +#include <com/sun/star/chart2/XTitle.hpp> +#include <com/sun/star/chart2/XRegressionCurveContainer.hpp> +#include <tools/diagnose_ex.h> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Any; + +namespace +{ + +OUString lcl_getDataSeriesName( const OUString& rObjectCID, const Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ); + if( xDiagram.is() && xSeries.is() ) + { + Reference< XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) ); + if( xChartType.is() ) + { + aRet = ::chart::DataSeriesHelper::getDataSeriesLabel( + xSeries, xChartType->getRoleOfSequenceForSeriesLabel() ) ; + } + } + + return aRet; +} + +OUString lcl_getFullSeriesName( const OUString& rObjectCID, const Reference< frame::XModel >& xChartModel ) +{ + OUString aRet(SchResId(STR_TIP_DATASERIES)); + OUString aWildcard( "%SERIESNAME" ); + sal_Int32 nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) ); + return aRet; +} + +void lcl_addText( OUString& rOut, const OUString& rSeparator, const OUString& rNext ) +{ + if( !(rOut.isEmpty() || rNext.isEmpty()) ) + rOut+=rSeparator; + if( !rNext.isEmpty() ) + rOut+=rNext; +} + +OUString lcl_getDataPointValueText( const Reference< XDataSeries >& xSeries, sal_Int32 nPointIndex, + const Reference< XCoordinateSystem >& xCooSys, + const Reference< frame::XModel >& xChartModel ) +{ + + OUString aRet; + + Reference<data::XDataSource> xDataSource( + uno::Reference<data::XDataSource>( xSeries, uno::UNO_QUERY ) ); + if(!xDataSource.is()) + return aRet; + + Sequence< Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); + + OUString aX, aY, aY_Min, aY_Max, aY_First, aY_Last, a_Size; + double fValue = 0; + + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY ); + NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier ); + Color nLabelColor;//dummy + bool bColorChanged;//dummy + + for(sal_Int32 nN = aDataSequences.getLength();nN--;) + { + uno::Reference<data::XDataSequence> xDataSequence( aDataSequences[nN]->getValues()); + if( !xDataSequence.is() ) + continue; + Sequence< Any > aData( xDataSequence->getData() ); + if( nPointIndex >= aData.getLength() ) + continue; + uno::Reference<beans::XPropertySet> xProp(xDataSequence, uno::UNO_QUERY ); + if( xProp.is()) + { + try + { + uno::Any aARole = xProp->getPropertyValue( "Role" ); + OUString aRole; + aARole >>= aRole; + + if( aRole == "values-x" ) + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + aX = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } + else if( aRole == "values-y") + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + aY = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } + else if( aRole == "values-first" ) + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + aY_First = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } + else if( aRole == "values-min" ) + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + aY_Min = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } + else if( aRole == "values-max" ) + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + aY_Max = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } + else if( aRole == "values-last" ) + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + aY_Last = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } + else if( aRole == "values-size" ) + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + a_Size = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + + if( aX.isEmpty() ) + { + ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartModel); + aRet = ExplicitCategoriesProvider::getCategoryByIndex( xCooSys, rModel, nPointIndex ); + } + else + { + aRet = aX; + } + + OUString aSeparator( " " ); + + lcl_addText( aRet, aSeparator, aY ); + lcl_addText( aRet, aSeparator, aY_First ); + lcl_addText( aRet, aSeparator, aY_Min ); + lcl_addText( aRet, aSeparator, aY_Max ); + lcl_addText( aRet, aSeparator, aY_Last ); + lcl_addText( aRet, aSeparator, a_Size ); + + return aRet; +} + +} //end anonymous namespace + +OUString ObjectNameProvider::getName( ObjectType eObjectType, bool bPlural ) +{ + OUString aRet; + switch( eObjectType ) + { + case OBJECTTYPE_PAGE: + aRet=SchResId(STR_OBJECT_PAGE); + break; + case OBJECTTYPE_TITLE: + { + if(bPlural) + aRet=SchResId(STR_OBJECT_TITLES); + else + aRet=SchResId(STR_OBJECT_TITLE); + } + break; + case OBJECTTYPE_LEGEND: + aRet=SchResId(STR_OBJECT_LEGEND); + break; + case OBJECTTYPE_LEGEND_ENTRY: + aRet=SchResId(STR_OBJECT_LEGEND_SYMBOL);//@todo change string if we do differentiate symbol and legend entry in future + break; + case OBJECTTYPE_DIAGRAM: + aRet=SchResId(STR_OBJECT_DIAGRAM); + break; + case OBJECTTYPE_DIAGRAM_WALL: + aRet=SchResId(STR_OBJECT_DIAGRAM_WALL); + break; + case OBJECTTYPE_DIAGRAM_FLOOR: + aRet=SchResId(STR_OBJECT_DIAGRAM_FLOOR); + break; + case OBJECTTYPE_AXIS: + { + if(bPlural) + aRet=SchResId(STR_OBJECT_AXES); + else + aRet=SchResId(STR_OBJECT_AXIS); + } + break; + case OBJECTTYPE_AXIS_UNITLABEL: + aRet=SchResId(STR_OBJECT_LABEL);//@todo maybe a more concrete name + break; + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: //maybe todo: different names for subgrids + { + if(bPlural) + aRet=SchResId(STR_OBJECT_GRIDS); + else + aRet=SchResId(STR_OBJECT_GRID); + } + break; + case OBJECTTYPE_DATA_SERIES: + { + if(bPlural) + aRet=SchResId(STR_OBJECT_DATASERIES_PLURAL); + else + aRet=SchResId(STR_OBJECT_DATASERIES); + } + break; + case OBJECTTYPE_DATA_POINT: + { + if(bPlural) + aRet=SchResId(STR_OBJECT_DATAPOINTS); + else + aRet=SchResId(STR_OBJECT_DATAPOINT); + } + break; + case OBJECTTYPE_DATA_LABELS: + aRet=SchResId(STR_OBJECT_DATALABELS); + break; + case OBJECTTYPE_DATA_LABEL: + aRet=SchResId(STR_OBJECT_LABEL); + break; + case OBJECTTYPE_DATA_ERRORS_X: + aRet=SchResId(STR_OBJECT_ERROR_BARS_X); + break; + case OBJECTTYPE_DATA_ERRORS_Y: + aRet=SchResId(STR_OBJECT_ERROR_BARS_Y); + break; + case OBJECTTYPE_DATA_ERRORS_Z: + aRet=SchResId(STR_OBJECT_ERROR_BARS_Z); + break; + case OBJECTTYPE_DATA_AVERAGE_LINE: + aRet=SchResId(STR_OBJECT_AVERAGE_LINE); + break; + case OBJECTTYPE_DATA_CURVE: + { + if(bPlural) + aRet=SchResId(STR_OBJECT_CURVES); + else + aRet=SchResId(STR_OBJECT_CURVE); + } + break; + case OBJECTTYPE_DATA_STOCK_RANGE: + break; + case OBJECTTYPE_DATA_STOCK_LOSS: + aRet=SchResId(STR_OBJECT_STOCK_LOSS); + break; + case OBJECTTYPE_DATA_STOCK_GAIN: + aRet=SchResId(STR_OBJECT_STOCK_GAIN); + break; + case OBJECTTYPE_DATA_CURVE_EQUATION: + aRet=SchResId(STR_OBJECT_CURVE_EQUATION); + break; + default: //OBJECTTYPE_UNKNOWN + ; + } + return aRet; +} + +OUString ObjectNameProvider::getAxisName( const OUString& rObjectCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + Reference< XAxis > xAxis( + ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ), uno::UNO_QUERY ); + + sal_Int32 nCooSysIndex = 0; + sal_Int32 nDimensionIndex = 0; + sal_Int32 nAxisIndex = 0; + AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ), nCooSysIndex, nDimensionIndex, nAxisIndex ); + + switch(nDimensionIndex) + { + case 0://x-axis + if( nAxisIndex == 0 ) + aRet=SchResId(STR_OBJECT_AXIS_X); + else + aRet=SchResId(STR_OBJECT_SECONDARY_X_AXIS); + break; + case 1://y-axis + if( nAxisIndex == 0 ) + aRet=SchResId(STR_OBJECT_AXIS_Y); + else + aRet=SchResId(STR_OBJECT_SECONDARY_Y_AXIS); + break; + case 2://z-axis + aRet=SchResId(STR_OBJECT_AXIS_Z); + break; + default://axis + aRet=SchResId(STR_OBJECT_AXIS); + break; + } + + return aRet; +} + +OUString ObjectNameProvider::getTitleNameByType( TitleHelper::eTitleType eType ) +{ + OUString aRet; + + switch(eType) + { + case TitleHelper::MAIN_TITLE: + aRet=SchResId(STR_OBJECT_TITLE_MAIN); + break; + case TitleHelper::SUB_TITLE: + aRet=SchResId(STR_OBJECT_TITLE_SUB); + break; + case TitleHelper::X_AXIS_TITLE: + aRet=SchResId(STR_OBJECT_TITLE_X_AXIS); + break; + case TitleHelper::Y_AXIS_TITLE: + aRet=SchResId(STR_OBJECT_TITLE_Y_AXIS); + break; + case TitleHelper::Z_AXIS_TITLE: + aRet=SchResId(STR_OBJECT_TITLE_Z_AXIS); + break; + case TitleHelper::SECONDARY_X_AXIS_TITLE: + aRet=SchResId(STR_OBJECT_TITLE_SECONDARY_X_AXIS); + break; + case TitleHelper::SECONDARY_Y_AXIS_TITLE: + aRet=SchResId(STR_OBJECT_TITLE_SECONDARY_Y_AXIS); + break; + default: + OSL_FAIL("unknown title type"); + break; + } + + if( aRet.isEmpty() ) + aRet=SchResId(STR_OBJECT_TITLE); + + return aRet; +} + +OUString ObjectNameProvider::getTitleName( const OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + Reference< XTitle > xTitle( + ObjectIdentifier::getObjectPropertySet( rObjectCID , xChartModel ), uno::UNO_QUERY ); + if( xTitle.is() ) + { + TitleHelper::eTitleType eType; + if( TitleHelper::getTitleType( eType, xTitle, xChartModel ) ) + aRet = ObjectNameProvider::getTitleNameByType( eType ); + } + if( aRet.isEmpty() ) + aRet=SchResId(STR_OBJECT_TITLE); + + return aRet; +} + +OUString ObjectNameProvider::getGridName( const OUString& rObjectCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + OUString aRet; + + sal_Int32 nCooSysIndex = -1; + sal_Int32 nDimensionIndex = -1; + sal_Int32 nAxisIndex = -1; + Reference< XAxis > xAxis( ObjectIdentifier::getAxisForCID( rObjectCID , xChartModel ) ); + AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram( xChartModel ) + , nCooSysIndex , nDimensionIndex, nAxisIndex ); + + bool bMainGrid = (ObjectIdentifier::getObjectType( rObjectCID ) == OBJECTTYPE_GRID); + + if( bMainGrid ) + { + switch(nDimensionIndex) + { + case 0://x-axis + aRet=SchResId(STR_OBJECT_GRID_MAJOR_X); + break; + case 1://y-axis + aRet=SchResId(STR_OBJECT_GRID_MAJOR_Y); + break; + case 2://z-axis + aRet=SchResId(STR_OBJECT_GRID_MAJOR_Z); + break; + default://axis + aRet=SchResId(STR_OBJECT_GRID); + break; + } + } + else + { + switch(nDimensionIndex) + { + case 0://x-axis + aRet=SchResId(STR_OBJECT_GRID_MINOR_X); + break; + case 1://y-axis + aRet=SchResId(STR_OBJECT_GRID_MINOR_Y); + break; + case 2://z-axis + aRet=SchResId(STR_OBJECT_GRID_MINOR_Z); + break; + default://axis + aRet=SchResId(STR_OBJECT_GRID); + break; + } + } + return aRet; +} + +OUString ObjectNameProvider::getHelpText( const OUString& rObjectCID, const Reference< chart2::XChartDocument >& xChartDocument ) +{ + return getHelpText( rObjectCID, Reference< frame::XModel >( xChartDocument ) ); +} + +OUString ObjectNameProvider::getHelpText( const OUString& rObjectCID, const Reference< frame::XModel >& xChartModel, bool bVerbose ) +{ + OUString aRet; + ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) ); + if( eObjectType == OBJECTTYPE_AXIS ) + { + aRet=ObjectNameProvider::getAxisName( rObjectCID, xChartModel ); + } + else if( eObjectType == OBJECTTYPE_GRID + || eObjectType == OBJECTTYPE_SUBGRID ) + { + aRet=ObjectNameProvider::getGridName( rObjectCID, xChartModel ); + } + else if( eObjectType == OBJECTTYPE_TITLE ) + { + aRet=ObjectNameProvider::getTitleName( rObjectCID, xChartModel ); + } + else if( eObjectType == OBJECTTYPE_DATA_SERIES ) + { + aRet = lcl_getFullSeriesName( rObjectCID, xChartModel ); + } + else if( eObjectType == OBJECTTYPE_DATA_POINT ) + { + if( bVerbose ) + { + aRet= SchResId(STR_TIP_DATAPOINT_INDEX) + "\n" + + SchResId(STR_TIP_DATASERIES) + "\n" + + SchResId(STR_TIP_DATAPOINT_VALUES); + } + else + aRet=SchResId(STR_TIP_DATAPOINT); + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ); + if( xDiagram.is() && xSeries.is() ) + { + sal_Int32 nPointIndex( ObjectIdentifier::getParticleID(rObjectCID).toInt32() ); + + //replace data point index + OUString aWildcard( "%POINTNUMBER" ); + sal_Int32 nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + { + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), OUString::number(nPointIndex+1) ); + } + + //replace data series index + aWildcard = "%SERIESNUMBER"; + nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + { + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 nSeriesIndex = -1; + for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;) + { + if( aSeriesVector[nSeriesIndex] == xSeries ) + { + break; + } + } + + OUString aReplacement( OUString::number(nSeriesIndex+1) ); + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), aReplacement ); + } + + //replace point values + aWildcard = "%POINTVALUES"; + nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataPointValueText( + xSeries,nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartModel ) ); + + //replace series name + aWildcard = "%SERIESNAME"; + nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), lcl_getDataSeriesName( rObjectCID, xChartModel ) ); + } + } + else if( eObjectType == OBJECTTYPE_DATA_CURVE ) + { + if( bVerbose ) + { + aRet = SchResId( STR_OBJECT_CURVE_WITH_PARAMETERS ); + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel )); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + + if( xCurveCnt.is()) + { + sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID ); + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xCurveCnt, nCurveIndex) ); + if( xCurve.is()) + { + try + { + Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_SET_THROW ); + sal_Int32 aDegree = 2; + sal_Int32 aPeriod = 2; + bool bForceIntercept = false; + double aInterceptValue = 0.0; + OUString aXName ("x"), aYName ("f(x)"); + const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper(); + const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep(); + sal_Unicode cDecSeparator = aNumDecimalSep[0]; + + uno::Reference< beans::XPropertySet > xProperties( xCurve, uno::UNO_QUERY ); + if ( xProperties.is()) + { + xProperties->getPropertyValue( "PolynomialDegree") >>= aDegree; + xProperties->getPropertyValue( "MovingAveragePeriod") >>= aPeriod; + xProperties->getPropertyValue( "ForceIntercept") >>= bForceIntercept; + if (bForceIntercept) + xProperties->getPropertyValue( "InterceptValue") >>= aInterceptValue; + uno::Reference< beans::XPropertySet > xEqProp( xCurve->getEquationProperties()); + if( xEqProp.is()) + { + if ( !(xEqProp->getPropertyValue( "XName") >>= aXName) ) + aXName = "x"; + if ( !(xEqProp->getPropertyValue( "YName") >>= aYName) ) + aYName = "f(x)"; + } + } + xCalculator->setRegressionProperties(aDegree, bForceIntercept, aInterceptValue, 2); + xCalculator->setXYNames ( aXName, aYName ); + RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel ); + + // change text for Moving Average + OUString aWildcard( "%PERIOD" ); + sal_Int32 nIndex = xCalculator->getRepresentation().indexOf( aWildcard ); + if( nIndex != -1 ) + { // replace period + aRet = xCalculator->getRepresentation(); + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), OUString::number(aPeriod) ); + } + + // replace formula + aWildcard = "%FORMULA"; + nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + { + OUString aFormula ( xCalculator->getRepresentation() ); + if ( cDecSeparator != '.' ) + { + aFormula = aFormula.replace( '.', cDecSeparator ); + } + aRet = aRet.replaceAt( nIndex, aWildcard.getLength(), aFormula ); + } + + // replace r^2 + aWildcard = "%RSQUARED"; + nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + { + double fR( xCalculator->getCorrelationCoefficient()); + aRet = aRet.replaceAt( + nIndex, aWildcard.getLength(), + ::rtl::math::doubleToUString( + fR*fR, rtl_math_StringFormat_G, 4, cDecSeparator, true )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + } + else + { + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID(rObjectCID , xChartModel)); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + aRet += getName(eObjectType); + + if( xCurveCnt.is()) + { + sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID ); + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xCurveCnt, nCurveIndex) ); + if( xCurve.is()) + { + aRet += " (" + RegressionCurveHelper::getRegressionCurveName(xCurve) + " )"; + } + } + } + } + else if( eObjectType == OBJECTTYPE_DATA_AVERAGE_LINE ) + { + if( bVerbose ) + { + aRet = SchResId(STR_OBJECT_AVERAGE_LINE_WITH_PARAMETERS); + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel )); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + if( xCurveCnt.is()) + { + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getMeanValueLine( xCurveCnt )); + if( xCurve.is()) + { + try + { + Reference< chart2::XRegressionCurveCalculator > xCalculator( xCurve->getCalculator(), uno::UNO_SET_THROW ); + RegressionCurveHelper::initializeCurveCalculator( xCalculator, xSeries, xChartModel ); + + const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper(); + const OUString& aNumDecimalSep = rLocaleDataWrapper.getNumDecimalSep(); + sal_Unicode cDecSeparator = aNumDecimalSep[0]; + + OUString aWildcard( "%AVERAGE_VALUE" ); + sal_Int32 nIndex = aRet.indexOf( aWildcard ); + // as the curve is constant, the value at any x-value is ok + if( nIndex != -1 ) + { + const double fMeanValue( xCalculator->getCurveValue( 0.0 )); + aRet = aRet.replaceAt( + nIndex, aWildcard.getLength(), + ::rtl::math::doubleToUString( + fMeanValue, rtl_math_StringFormat_G, 4, cDecSeparator, true )); + } + + // replace standard deviation + aWildcard = "%STD_DEVIATION"; + nIndex = aRet.indexOf( aWildcard ); + if( nIndex != -1 ) + { + const double fStdDev( xCalculator->getCorrelationCoefficient()); + aRet = aRet.replaceAt( + nIndex, aWildcard.getLength(), + ::rtl::math::doubleToUString( + fStdDev, rtl_math_StringFormat_G, 4, cDecSeparator, true )); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + } + } + else + { + // non-verbose + aRet = ObjectNameProvider::getName( eObjectType ); + } + } + else + { + aRet = ObjectNameProvider::getName( eObjectType ); + } + return aRet; +} + +OUString ObjectNameProvider::getSelectedObjectText( const OUString & rObjectCID, const css::uno::Reference< css::chart2::XChartDocument >& xChartDocument ) +{ + OUString aRet; + ObjectType eObjectType( ObjectIdentifier::getObjectType(rObjectCID) ); + Reference< frame::XModel > xChartModel = xChartDocument; + + if( eObjectType == OBJECTTYPE_DATA_POINT ) + { + aRet = SchResId( STR_STATUS_DATAPOINT_MARKED ); + + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rObjectCID , xChartModel ); + if( xDiagram.is() && xSeries.is() ) + { + sal_Int32 nPointIndex( ObjectIdentifier::getParticleID(rObjectCID).toInt32() ); + + // replace data point index + replaceParamterInString( aRet, "%POINTNUMBER", OUString::number( nPointIndex + 1 )); + + // replace data series index + { + std::vector< Reference< chart2::XDataSeries > > aSeriesVector( + DiagramHelper::getDataSeriesFromDiagram( xDiagram ) ); + sal_Int32 nSeriesIndex = -1; + for( nSeriesIndex=aSeriesVector.size();nSeriesIndex--;) + { + if( aSeriesVector[nSeriesIndex] == xSeries ) + break; + } + replaceParamterInString( aRet, "%SERIESNUMBER", OUString::number( nSeriesIndex + 1 ) ); + } + + // replace point value + replaceParamterInString( aRet, "%POINTVALUES", lcl_getDataPointValueText( + xSeries, nPointIndex, DataSeriesHelper::getCoordinateSystemOfSeries(xSeries, xDiagram), xChartModel ) ); + } + } + else + { + // use the verbose text including the formula for trend lines + const bool bVerbose( eObjectType == OBJECTTYPE_DATA_CURVE || eObjectType == OBJECTTYPE_DATA_AVERAGE_LINE ); + const OUString aHelpText( getHelpText( rObjectCID, xChartModel, bVerbose )); + if( !aHelpText.isEmpty()) + { + aRet = SchResId( STR_STATUS_OBJECT_MARKED ); + replaceParamterInString( aRet, "%OBJECTNAME", aHelpText ); + } + } + + return aRet; +} + +OUString ObjectNameProvider::getNameForCID( + const OUString& rObjectCID, + const uno::Reference< chart2::XChartDocument >& xChartDocument ) +{ + ObjectType eType( ObjectIdentifier::getObjectType( rObjectCID )); + Reference< frame::XModel > xModel = xChartDocument; + + switch( eType ) + { + case OBJECTTYPE_AXIS: + return getAxisName( rObjectCID, xModel ); + case OBJECTTYPE_TITLE: + return getTitleName( rObjectCID, xModel ); + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: + return getGridName( rObjectCID, xModel ); + case OBJECTTYPE_DATA_SERIES: + return lcl_getFullSeriesName( rObjectCID, xModel ); + case OBJECTTYPE_DATA_POINT: + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_LABEL: + case OBJECTTYPE_DATA_ERRORS_X: + case OBJECTTYPE_DATA_ERRORS_Y: + case OBJECTTYPE_DATA_ERRORS_Z: + case OBJECTTYPE_DATA_AVERAGE_LINE: + case OBJECTTYPE_DATA_CURVE: + case OBJECTTYPE_DATA_CURVE_EQUATION: + { + OUString aRet = lcl_getFullSeriesName( rObjectCID, xModel ) + " "; + if( eType == OBJECTTYPE_DATA_POINT || eType == OBJECTTYPE_DATA_LABEL ) + { + aRet += getName( OBJECTTYPE_DATA_POINT ); + sal_Int32 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID ); + aRet += " " + OUString::number(nPointIndex+1); + if( eType == OBJECTTYPE_DATA_LABEL ) + { + aRet += " " + getName( OBJECTTYPE_DATA_LABEL ); + } + } + else if (eType == OBJECTTYPE_DATA_CURVE || eType == OBJECTTYPE_DATA_CURVE_EQUATION) + { + Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( rObjectCID , xModel )); + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + + aRet += " " + getName(eType); + + if( xCurveCnt.is()) + { + sal_Int32 nCurveIndex = ObjectIdentifier::getIndexFromParticleOrCID( rObjectCID ); + Reference< chart2::XRegressionCurve > xCurve( RegressionCurveHelper::getRegressionCurveAtIndex(xCurveCnt, nCurveIndex) ); + if( xCurve.is()) + { + aRet += " (" + RegressionCurveHelper::getRegressionCurveName(xCurve) + ")"; + } + } + } + else + { + aRet += getName( eType ); + } + return aRet; + } + default: + break; + } + + return getName( eType ); +} + +OUString ObjectNameProvider::getName_ObjectForSeries( + ObjectType eObjectType, + const OUString& rSeriesCID, + const uno::Reference< chart2::XChartDocument >& xChartDocument ) +{ + uno::Reference< frame::XModel> xChartModel = xChartDocument; + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSeriesCID , xChartModel ); + if( xSeries.is() ) + { + OUString aRet = SchResId(STR_OBJECT_FOR_SERIES); + replaceParamterInString( aRet, "%OBJECTNAME", getName( eObjectType ) ); + replaceParamterInString( aRet, "%SERIESNAME", lcl_getDataSeriesName( rSeriesCID, xChartModel ) ); + return aRet; + } + else + return ObjectNameProvider::getName_ObjectForAllSeries( eObjectType ); +} + +OUString ObjectNameProvider::getName_ObjectForAllSeries( ObjectType eObjectType ) +{ + OUString aRet = SchResId(STR_OBJECT_FOR_ALL_SERIES); + replaceParamterInString( aRet, "%OBJECTNAME", getName( eObjectType, true /*bPlural*/ ) ); + return aRet; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/RangeSelectionHelper.cxx b/chart2/source/controller/dialogs/RangeSelectionHelper.cxx new file mode 100644 index 000000000..8cd8f64c8 --- /dev/null +++ b/chart2/source/controller/dialogs/RangeSelectionHelper.cxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <RangeSelectionHelper.hxx> +#include <RangeSelectionListener.hxx> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/data/XDataProvider.hpp> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +RangeSelectionHelper::RangeSelectionHelper( + const Reference< chart2::XChartDocument > & xChartDocument ) : + m_xChartDocument( xChartDocument ) +{} + +RangeSelectionHelper::~RangeSelectionHelper() +{} + +bool RangeSelectionHelper::hasRangeSelection() +{ + return getRangeSelection().is(); +} + +Reference< sheet::XRangeSelection > const & RangeSelectionHelper::getRangeSelection() +{ + if( !m_xRangeSelection.is() && + m_xChartDocument.is() ) + { + try + { + Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider()); + if( xDataProvider.is()) + m_xRangeSelection.set( xDataProvider->getRangeSelection()); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + + m_xRangeSelection.clear(); + } + } + + return m_xRangeSelection; +} + +void RangeSelectionHelper::raiseRangeSelectionDocument() +{ + Reference< sheet::XRangeSelection > xRangeSel( getRangeSelection()); + if( !xRangeSel.is()) + return; + + try + { + // bring document to front + Reference< frame::XController > xCtrl( xRangeSel, uno::UNO_QUERY ); + if( xCtrl.is()) + { + Reference< frame::XFrame > xFrame( xCtrl->getFrame()); + if( xFrame.is()) + { + Reference< awt::XTopWindow > xWin( xFrame->getContainerWindow(), + uno::UNO_QUERY_THROW ); + xWin->toFront(); + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +bool RangeSelectionHelper::chooseRange( + const OUString & aCurrentRange, + const OUString & aUIString, + RangeSelectionListenerParent & rListenerParent ) +{ + ControllerLockGuardUNO aGuard( m_xChartDocument ); + + bool bResult = true; + raiseRangeSelectionDocument(); + + try + { + Reference< sheet::XRangeSelection > xRangeSel( getRangeSelection()); + if( xRangeSel.is()) + { + Sequence< beans::PropertyValue > aArgs( 4 ); + aArgs[0] = beans::PropertyValue( + "InitialValue", -1, uno::Any( aCurrentRange ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[1] = beans::PropertyValue( + "Title", -1, + uno::Any( aUIString ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[2] = beans::PropertyValue( + "CloseOnMouseRelease", -1, uno::Any( true ), + beans::PropertyState_DIRECT_VALUE ); + aArgs[3] = beans::PropertyValue( + "MultiSelectionMode", -1, uno::Any( true ), + beans::PropertyState_DIRECT_VALUE ); + + if( m_xRangeSelectionListener.is() ) + stopRangeListening(); + m_xRangeSelectionListener.set( Reference< sheet::XRangeSelectionListener >( + new RangeSelectionListener( rListenerParent, aCurrentRange, m_xChartDocument ))); + + xRangeSel->addRangeSelectionListener( m_xRangeSelectionListener ); + xRangeSel->startRangeSelection( aArgs ); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + bResult = false; + } + + return bResult; +} + +void RangeSelectionHelper::stopRangeListening( bool bRemoveListener /* = true */ ) +{ + if( bRemoveListener && + m_xRangeSelectionListener.is() && + m_xRangeSelection.is() ) + { + m_xRangeSelection->removeRangeSelectionListener( m_xRangeSelectionListener ); + } + + m_xRangeSelectionListener = nullptr; +} + +bool RangeSelectionHelper::verifyCellRange( const OUString & rRangeStr ) +{ + Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider()); + if( ! xDataProvider.is()) + return false; + + return xDataProvider->createDataSequenceByRangeRepresentationPossible( rRangeStr ); +} + +bool RangeSelectionHelper::verifyArguments( const Sequence< beans::PropertyValue > & rArguments ) +{ + Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider()); + if( ! xDataProvider.is()) + return false; + + return xDataProvider->createDataSourcePossible( rArguments ); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/RangeSelectionListener.cxx b/chart2/source/controller/dialogs/RangeSelectionListener.cxx new file mode 100644 index 000000000..ca0d9ae2c --- /dev/null +++ b/chart2/source/controller/dialogs/RangeSelectionListener.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <RangeSelectionListener.hxx> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +RangeSelectionListener::RangeSelectionListener( + RangeSelectionListenerParent & rParent, + const OUString & rInitialRange, + const Reference< frame::XModel >& xModelToLockController ) : + m_rParent( rParent ), + m_aRange( rInitialRange ), + m_aControllerLockGuard( xModelToLockController ) +{} + +RangeSelectionListener::~RangeSelectionListener() +{} + +// ____ XRangeSelectionListener ____ +void SAL_CALL RangeSelectionListener::done( const sheet::RangeSelectionEvent& aEvent ) +{ + m_aRange = aEvent.RangeDescriptor; + m_rParent.listeningFinished( m_aRange ); +} + +void SAL_CALL RangeSelectionListener::aborted( const sheet::RangeSelectionEvent& /*aEvent*/ ) +{ + m_rParent.listeningFinished( m_aRange ); +} + +// ____ XEventListener ____ +void SAL_CALL RangeSelectionListener::disposing( const lang::EventObject& /*Source*/ ) +{ + m_rParent.disposingRangeSelection(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/TextDirectionListBox.cxx b/chart2/source/controller/dialogs/TextDirectionListBox.cxx new file mode 100644 index 000000000..68181fdfc --- /dev/null +++ b/chart2/source/controller/dialogs/TextDirectionListBox.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <TextDirectionListBox.hxx> +#include <ResId.hxx> +#include <strings.hrc> + +namespace chart +{ +TextDirectionListBox::TextDirectionListBox(std::unique_ptr<weld::ComboBox> pControl) + : svx::FrameDirectionListBox(std::move(pControl)) +{ + append(SvxFrameDirection::Horizontal_LR_TB, SchResId(STR_TEXT_DIRECTION_LTR)); + append(SvxFrameDirection::Horizontal_RL_TB, SchResId(STR_TEXT_DIRECTION_RTL)); + append(SvxFrameDirection::Environment, SchResId(STR_TEXT_DIRECTION_SUPER)); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx b/chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx new file mode 100644 index 000000000..166846da6 --- /dev/null +++ b/chart2/source/controller/dialogs/TimerTriggeredControllerLock.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/frame/XModel.hpp> +#include <TimerTriggeredControllerLock.hxx> +#include <ControllerLockGuard.hxx> + +namespace chart +{ + +using namespace ::com::sun::star; + +TimerTriggeredControllerLock::TimerTriggeredControllerLock( const uno::Reference< frame::XModel >& xModel ) + : m_xModel( xModel ) + , m_apControllerLockGuard() + , m_aTimer() +{ + m_aTimer.SetTimeout( 4*EDIT_UPDATEDATA_TIMEOUT ); + m_aTimer.SetInvokeHandler( LINK( this, TimerTriggeredControllerLock, TimerTimeout ) ); +} +TimerTriggeredControllerLock::~TimerTriggeredControllerLock() +{ + m_aTimer.Stop(); +} + +void TimerTriggeredControllerLock::startTimer() +{ + if (!m_apControllerLockGuard) + m_apControllerLockGuard.reset( new ControllerLockGuardUNO(m_xModel) ); + m_aTimer.Start(); +} +IMPL_LINK_NOARG(TimerTriggeredControllerLock, TimerTimeout, Timer *, void) +{ + m_apControllerLockGuard.reset(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/TitleDialogData.cxx b/chart2/source/controller/dialogs/TitleDialogData.cxx new file mode 100644 index 000000000..e4e909901 --- /dev/null +++ b/chart2/source/controller/dialogs/TitleDialogData.cxx @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/frame/XModel.hpp> + +#include <TitleDialogData.hxx> +#include <TitleHelper.hxx> +#include <ChartModelHelper.hxx> +#include <AxisHelper.hxx> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +TitleDialogData::TitleDialogData( std::unique_ptr<ReferenceSizeProvider> pRefSizeProvider ) + : aPossibilityList(7) + , aExistenceList(7) + , aTextList(7) + , apReferenceSizeProvider( std::move(pRefSizeProvider) ) +{ + for (sal_Int32 i = 0; i < 7; i++) + { + aPossibilityList[i] = true; + aExistenceList[i] = false; + } +} + +void TitleDialogData::readFromModel( const uno::Reference< frame::XModel>& xChartModel ) +{ + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram(xChartModel); + + //get possibilities + uno::Sequence< sal_Bool > aAxisPossibilityList; + AxisHelper::getAxisOrGridPossibilities( aAxisPossibilityList, xDiagram ); + aPossibilityList[2]=aAxisPossibilityList[0];//x axis title + aPossibilityList[3]=aAxisPossibilityList[1];//y axis title + aPossibilityList[4]=aAxisPossibilityList[2];//z axis title + aPossibilityList[5]=aAxisPossibilityList[3];//secondary x axis title + aPossibilityList[6]=aAxisPossibilityList[4];//secondary y axis title + + //find out which title exists and get their text + //main title: + for( sal_Int32 nTitleIndex = static_cast< sal_Int32 >( TitleHelper::TITLE_BEGIN); + nTitleIndex < static_cast< sal_Int32 >( TitleHelper::NORMAL_TITLE_END ); + nTitleIndex++) + { + uno::Reference< XTitle > xTitle = TitleHelper::getTitle( + static_cast< TitleHelper::eTitleType >( nTitleIndex ), xChartModel ); + aExistenceList[nTitleIndex] = xTitle.is(); + aTextList[nTitleIndex]=TitleHelper::getCompleteString( xTitle ); + } +} + +bool TitleDialogData::writeDifferenceToModel( + const uno::Reference< frame::XModel >& xChartModel + , const uno::Reference< uno::XComponentContext >& xContext + , TitleDialogData* pOldState ) +{ + bool bChanged = false; + for( sal_Int32 nN = static_cast< sal_Int32 >( TitleHelper::TITLE_BEGIN ); + nN < static_cast< sal_Int32 >( TitleHelper::NORMAL_TITLE_END ); + nN++) + { + if( !pOldState || ( pOldState->aExistenceList[nN] != aExistenceList[nN] ) ) + { + if(aExistenceList[nN]) + { + TitleHelper::createTitle( + static_cast< TitleHelper::eTitleType >( nN ), aTextList[nN], xChartModel, xContext, + apReferenceSizeProvider.get() ); + bChanged = true; + } + else + { + TitleHelper::removeTitle( static_cast< TitleHelper::eTitleType >( nN ), xChartModel ); + bChanged = true; + } + } + else if( !pOldState || ( pOldState->aTextList[nN] != aTextList[nN] ) ) + { + //change content + uno::Reference< XTitle > xTitle( + TitleHelper::getTitle( static_cast< TitleHelper::eTitleType >( nN ), xChartModel ) ); + if(xTitle.is()) + { + TitleHelper::setCompleteString( aTextList[nN], xTitle, xContext ); + bChanged = true; + } + } + } + return bChanged; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_ChartType.cxx b/chart2/source/controller/dialogs/dlg_ChartType.cxx new file mode 100644 index 000000000..d1c2acc3c --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ChartType.cxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_ChartType.hxx> +#include "tp_ChartType.hxx" +#include <com/sun/star/chart2/XChartDocument.hpp> + + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +ChartTypeDialog::ChartTypeDialog(weld::Window* pParent, + const uno::Reference< frame::XModel >& xChartModel) + : GenericDialogController(pParent, "modules/schart/ui/charttypedialog.ui", "ChartTypeDialog") + , m_xChartModel(xChartModel) + , m_xContentArea(m_xDialog->weld_content_area()) +{ + m_xChartTypeTabPage = std::make_unique<ChartTypeTabPage>( + m_xContentArea.get(), this, + uno::Reference<XChartDocument>::query(m_xChartModel), + false/*don't show title description*/); + + m_xChartTypeTabPage->initializePage(); +} + +ChartTypeDialog::~ChartTypeDialog() +{ + m_xChartTypeTabPage.reset(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx b/chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx new file mode 100644 index 000000000..1a34d47b4 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ChartType_UNO.cxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_ChartType_UNO.hxx> +#include <dlg_ChartType.hxx> +#include <servicenames.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/frame/XModel.hpp> + +namespace com::sun::star::awt { class XWindow; } + +namespace chart +{ +using namespace ::com::sun::star; +ChartTypeUnoDlg::ChartTypeUnoDlg( const uno::Reference< uno::XComponentContext >& _xContext ) + : ChartTypeUnoDlg_BASE( _xContext ) +{ +} +ChartTypeUnoDlg::~ChartTypeUnoDlg() +{ + // we do this here cause the base class' call to destroyDialog won't reach us anymore: we're within a dtor, + // so this virtual-method-call the base class does not work, we're already dead then... + if (m_xDialog) + { + ::osl::MutexGuard aGuard(m_aMutex); + if (m_xDialog) + destroyDialog(); + } +} +// lang::XServiceInfo +OUString SAL_CALL ChartTypeUnoDlg::getImplementationName() +{ + return CHART_TYPE_DIALOG_SERVICE_IMPLEMENTATION_NAME; +} + +css::uno::Sequence<OUString> SAL_CALL ChartTypeUnoDlg::getSupportedServiceNames() +{ + return { CHART_TYPE_DIALOG_SERVICE_NAME }; +} +uno::Sequence< sal_Int8 > SAL_CALL ChartTypeUnoDlg::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} +void ChartTypeUnoDlg::implInitialize(const uno::Any& _rValue) +{ + beans::PropertyValue aProperty; + if (_rValue >>= aProperty) + { + if (aProperty.Name == "ChartModel") + m_xChartModel.set(aProperty.Value,uno::UNO_QUERY); + else + ChartTypeUnoDlg_BASE::implInitialize(_rValue); + } + else + ChartTypeUnoDlg_BASE::implInitialize(_rValue); +} + +std::unique_ptr<weld::DialogController> ChartTypeUnoDlg::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) +{ + return std::make_unique<ChartTypeDialog>(Application::GetFrameWeld(rParent), m_xChartModel); +} + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ChartTypeUnoDlg::getPropertySetInfo() +{ + return createPropertySetInfo( getInfoHelper() ); +} + +::cppu::IPropertyArrayHelper& ChartTypeUnoDlg::getInfoHelper() +{ + return *getArrayHelper(); +} + +::cppu::IPropertyArrayHelper* ChartTypeUnoDlg::createArrayHelper( ) const +{ + uno::Sequence< beans::Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} + +} //namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_ChartTypeDialog_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new chart::ChartTypeUnoDlg(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_CreationWizard.cxx b/chart2/source/controller/dialogs/dlg_CreationWizard.cxx new file mode 100644 index 000000000..da073c2f9 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_CreationWizard.cxx @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_CreationWizard.hxx> +#include <ResId.hxx> +#include <strings.hrc> +#include <helpids.h> +#include <ChartModel.hxx> + +#include "tp_ChartType.hxx" +#include "tp_RangeChooser.hxx" +#include "tp_Wizard_TitlesAndObjects.hxx" +#include "tp_DataSource.hxx" +#include <ChartTypeTemplateProvider.hxx> +#include "DialogModel.hxx" + +using namespace css; + +using vcl::RoadmapWizardTypes::WizardPath; + +namespace chart +{ +#define PATH_FULL 1 +#define STATE_FIRST 0 +#define STATE_CHARTTYPE STATE_FIRST +#define STATE_SIMPLE_RANGE 1 +#define STATE_DATA_SERIES 2 +#define STATE_OBJECTS 3 +#define STATE_LAST STATE_OBJECTS + +CreationWizard::CreationWizard(weld::Window* pParent, const uno::Reference<frame::XModel>& xChartModel, + const uno::Reference<uno::XComponentContext>& xContext) + : vcl::RoadmapWizardMachine(pParent) + , m_xChartModel(xChartModel,uno::UNO_QUERY) + , m_xComponentContext(xContext) + , m_pTemplateProvider(nullptr) + , m_aTimerTriggeredControllerLock(xChartModel) + , m_bCanTravel(true) +{ + m_pDialogModel.reset(new DialogModel(m_xChartModel, m_xComponentContext)); + defaultButton(WizardButtonFlags::FINISH); + + setTitleBase(SchResId(STR_DLG_CHART_WIZARD)); + + // tdf#134386 set m_pTemplateProvider before creating any other pages + m_pTemplateProvider = static_cast<ChartTypeTabPage*>(GetOrCreatePage(STATE_CHARTTYPE)); + assert(m_pTemplateProvider && "must exist"); + m_pDialogModel->setTemplate(m_pTemplateProvider->getCurrentTemplate()); + + WizardPath aPath = { + STATE_CHARTTYPE, + STATE_SIMPLE_RANGE, + STATE_DATA_SERIES, + STATE_OBJECTS + }; + + declarePath(PATH_FULL, aPath); + + SetRoadmapHelpId(HID_SCH_WIZARD_ROADMAP); + + if (!m_pDialogModel->getModel().isDataFromSpreadsheet()) + { + enableState(STATE_SIMPLE_RANGE, false); + enableState(STATE_DATA_SERIES, false); + } + + // Call ActivatePage, to create and activate the first page + ActivatePage(); + + m_xAssistant->set_current_page(0); +} + +CreationWizard::~CreationWizard() = default; + +std::unique_ptr<BuilderPage> CreationWizard::createPage(WizardState nState) +{ + std::unique_ptr<vcl::OWizardPage> xRet; + + OString sIdent(OString::number(nState)); + weld::Container* pPageContainer = m_xAssistant->append_page(sIdent); + + switch( nState ) + { + case STATE_CHARTTYPE: + { + m_aTimerTriggeredControllerLock.startTimer(); + xRet = std::make_unique<ChartTypeTabPage>(pPageContainer, this, m_xChartModel); + break; + } + case STATE_SIMPLE_RANGE: + { + m_aTimerTriggeredControllerLock.startTimer(); + xRet = std::make_unique<RangeChooserTabPage>(pPageContainer, this, *m_pDialogModel, m_pTemplateProvider); + break; + } + case STATE_DATA_SERIES: + { + m_aTimerTriggeredControllerLock.startTimer(); + xRet = std::make_unique<DataSourceTabPage>(pPageContainer, this, *m_pDialogModel, m_pTemplateProvider); + break; + } + case STATE_OBJECTS: + { + xRet = std::make_unique<TitlesAndObjectsTabPage>(pPageContainer, this, m_xChartModel, m_xComponentContext); + m_aTimerTriggeredControllerLock.startTimer(); + break; + } + default: + break; + } + + if (xRet) + xRet->SetPageTitle(OUString()); //remove title of pages to not get them in the wizard title + + return xRet; +} + +bool CreationWizard::leaveState( WizardState /*_nState*/ ) +{ + return m_bCanTravel; +} + +vcl::WizardTypes::WizardState CreationWizard::determineNextState( WizardState nCurrentState ) const +{ + if( !m_bCanTravel ) + return WZS_INVALID_STATE; + if( nCurrentState == STATE_LAST ) + return WZS_INVALID_STATE; + vcl::WizardTypes::WizardState nNextState = nCurrentState + 1; + while( !isStateEnabled( nNextState ) && nNextState <= STATE_LAST ) + ++nNextState; + return (nNextState==STATE_LAST+1) ? WZS_INVALID_STATE : nNextState; +} + +void CreationWizard::enterState(WizardState nState) +{ + m_aTimerTriggeredControllerLock.startTimer(); + enableButtons( WizardButtonFlags::PREVIOUS, nState > STATE_FIRST ); + enableButtons( WizardButtonFlags::NEXT, nState < STATE_LAST ); + if( isStateEnabled( nState )) + vcl::RoadmapWizardMachine::enterState(nState); +} + +void CreationWizard::setInvalidPage(BuilderPage* pTabPage) +{ + if (pTabPage == m_pCurTabPage) + m_bCanTravel = false; +} + +void CreationWizard::setValidPage(BuilderPage* pTabPage) +{ + if (pTabPage == m_pCurTabPage) + m_bCanTravel = true; +} + +OUString CreationWizard::getStateDisplayName( WizardState nState ) const +{ + const char* pResId = nullptr; + switch( nState ) + { + case STATE_CHARTTYPE: + pResId = STR_PAGE_CHARTTYPE; + break; + case STATE_SIMPLE_RANGE: + pResId = STR_PAGE_DATA_RANGE; + break; + case STATE_DATA_SERIES: + pResId = STR_OBJECT_DATASERIES_PLURAL; + break; + case STATE_OBJECTS: + pResId = STR_PAGE_CHART_ELEMENTS; + break; + default: + break; + } + if (!pResId) + return OUString(); + return SchResId(pResId); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx b/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx new file mode 100644 index 000000000..5411277f8 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_CreationWizard_UNO.cxx @@ -0,0 +1,349 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_CreationWizard_UNO.hxx> +#include <dlg_CreationWizard.hxx> +#include <servicenames.hxx> +#include <TimerTriggeredControllerLock.hxx> +#include <vcl/svapp.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <tools/diagnose_ex.h> +#include <comphelper/lok.hxx> +#include <sfx2/viewsh.hxx> + +namespace chart +{ +using namespace ::com::sun::star; + +CreationWizardUnoDlg::CreationWizardUnoDlg(const uno::Reference<uno::XComponentContext>& xContext) + : OComponentHelper(m_aMutex) + , m_xCC(xContext) + , m_bUnlockControllersOnExecute(false) +{ + uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(m_xCC); + uno::Reference< frame::XTerminateListener > xListener( this ); + xDesktop->addTerminateListener( xListener ); +} + +CreationWizardUnoDlg::~CreationWizardUnoDlg() +{ + SolarMutexGuard aSolarGuard; + m_xDialog.reset(); +} + +// lang::XServiceInfo +OUString SAL_CALL CreationWizardUnoDlg::getImplementationName() +{ + return CHART_WIZARD_DIALOG_SERVICE_IMPLEMENTATION_NAME; +} + +sal_Bool SAL_CALL CreationWizardUnoDlg::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL CreationWizardUnoDlg::getSupportedServiceNames() +{ + return { CHART_WIZARD_DIALOG_SERVICE_NAME }; +} + +// XInterface +uno::Any SAL_CALL CreationWizardUnoDlg::queryInterface( const uno::Type& aType ) +{ + return OComponentHelper::queryInterface( aType ); +} +void SAL_CALL CreationWizardUnoDlg::acquire() throw () +{ + OComponentHelper::acquire(); +} +void SAL_CALL CreationWizardUnoDlg::release() throw () +{ + OComponentHelper::release(); +} +uno::Any SAL_CALL CreationWizardUnoDlg::queryAggregation( uno::Type const & rType ) +{ + if (rType == cppu::UnoType<ui::dialogs::XAsynchronousExecutableDialog>::get()) + { + void * p = static_cast< ui::dialogs::XAsynchronousExecutableDialog * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType<lang::XServiceInfo>::get()) + { + void * p = static_cast< lang::XServiceInfo * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType<lang::XInitialization>::get()) + { + void * p = static_cast< lang::XInitialization * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType<frame::XTerminateListener>::get()) + { + void * p = static_cast< frame::XTerminateListener * >( this ); + return uno::Any( &p, rType ); + } + else if (rType == cppu::UnoType<beans::XPropertySet>::get()) + { + void * p = static_cast< beans::XPropertySet * >( this ); + return uno::Any( &p, rType ); + } + return OComponentHelper::queryAggregation( rType ); +} + +uno::Sequence< uno::Type > CreationWizardUnoDlg::getTypes() +{ + static uno::Sequence<uno::Type> aTypeList{ cppu::UnoType<lang::XComponent>::get(), + cppu::UnoType<lang::XTypeProvider>::get(), + cppu::UnoType<uno::XAggregation>::get(), + cppu::UnoType<uno::XWeak>::get(), + cppu::UnoType<lang::XServiceInfo>::get(), + cppu::UnoType<lang::XInitialization>::get(), + cppu::UnoType<frame::XTerminateListener>::get(), + cppu::UnoType<ui::dialogs::XAsynchronousExecutableDialog>::get(), + cppu::UnoType<beans::XPropertySet>::get() }; + return aTypeList; +} + +uno::Sequence< sal_Int8 > SAL_CALL CreationWizardUnoDlg::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XTerminateListener +void SAL_CALL CreationWizardUnoDlg::queryTermination( const lang::EventObject& /*Event*/ ) +{ +} + +void SAL_CALL CreationWizardUnoDlg::notifyTermination( const lang::EventObject& /*Event*/ ) +{ + // we are going down, so dispose us! + dispose(); +} + +void SAL_CALL CreationWizardUnoDlg::disposing( const lang::EventObject& /*Source*/ ) +{ + //Listener should deregister himself and release all references to the closing object. +} + +void SAL_CALL CreationWizardUnoDlg::setDialogTitle( const OUString& /*rTitle*/ ) +{ +} +void CreationWizardUnoDlg::createDialogOnDemand() +{ + SolarMutexGuard aSolarGuard; + if (m_xDialog) + return; + + if( !m_xParentWindow.is() && m_xChartModel.is() ) + { + uno::Reference< frame::XController > xController( + m_xChartModel->getCurrentController() ); + if( xController.is() ) + { + uno::Reference< frame::XFrame > xFrame( + xController->getFrame() ); + if(xFrame.is()) + m_xParentWindow = xFrame->getContainerWindow(); + } + } + uno::Reference< XComponent > xKeepAlive( this ); + if( m_xChartModel.is() ) + { + m_xDialog = std::make_shared<CreationWizard>(Application::GetFrameWeld(m_xParentWindow), m_xChartModel, m_xCC); + } +} + +IMPL_STATIC_LINK_NOARG(CreationWizardUnoDlg, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*) +{ + return SfxViewShell::Current(); +} + +void SAL_CALL CreationWizardUnoDlg::startExecuteModal( const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener ) +{ + SolarMutexGuard aSolarGuard; + createDialogOnDemand(); + + if( !m_xDialog ) + return; + + m_xDialog->getDialog()->SetInstallLOKNotifierHdl( + LINK(this, CreationWizardUnoDlg, InstallLOKNotifierHdl)); + + TimerTriggeredControllerLock aTimerTriggeredControllerLock( m_xChartModel ); + if( m_bUnlockControllersOnExecute && m_xChartModel.is() ) + m_xChartModel->unlockControllers(); + + CreationWizardUnoDlg* xThat = this; + weld::DialogController::runAsync(m_xDialog, [xListener, xThat](sal_Int32 nResult){ + if( xListener.is() ) + { + ::css::uno::Reference< ::css::uno::XInterface > xSource; + // Notify UNO listener to perform correct action depending on the result + css::ui::dialogs::DialogClosedEvent aEvent( xSource, nResult ); + xListener->dialogClosed( aEvent ); + } + xThat->m_xDialog.reset(); + }); +} + +void SAL_CALL CreationWizardUnoDlg::initialize( const uno::Sequence< uno::Any >& aArguments ) +{ + for(const uno::Any& rArgument : aArguments) + { + beans::PropertyValue aProperty; + if(rArgument >>= aProperty) + { + if( aProperty.Name == "ParentWindow" ) + { + aProperty.Value >>= m_xParentWindow; + } + else if( aProperty.Name == "ChartModel" ) + { + aProperty.Value >>= m_xChartModel; + } + } + } +} + +// ____ OComponentHelper ____ +/// Called in dispose method after the listeners were notified. +void SAL_CALL CreationWizardUnoDlg::disposing() +{ + m_xChartModel.clear(); + m_xParentWindow.clear(); + + SolarMutexGuard aSolarGuard; + m_xDialog.reset(); + + try + { + uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(m_xCC); + uno::Reference< frame::XTerminateListener > xListener( this ); + xDesktop->removeTerminateListener( xListener ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +//XPropertySet +uno::Reference< beans::XPropertySetInfo > SAL_CALL CreationWizardUnoDlg::getPropertySetInfo() +{ + OSL_FAIL("not implemented"); + return nullptr; +} + +void SAL_CALL CreationWizardUnoDlg::setPropertyValue(const OUString& rPropertyName, + const uno::Any& rValue) +{ + if( rPropertyName == "Position" ) + { + SolarMutexGuard aSolarGuard; + createDialogOnDemand(); + + //read only property, do nothing else + } + else if( rPropertyName == "Size") + { + //read only property, do nothing + } + else if( rPropertyName == "UnlockControllersOnExecute" ) + { + if( ! (rValue >>= m_bUnlockControllersOnExecute) ) + throw lang::IllegalArgumentException( "Property 'UnlockControllers' requires value of type boolean" , nullptr, 0 ); + } + else + throw beans::UnknownPropertyException( "unknown property was tried to set to chart wizard" , nullptr ); +} + +uno::Any SAL_CALL CreationWizardUnoDlg::getPropertyValue( const OUString& rPropertyName ) +{ + uno::Any aRet; + if( rPropertyName == "Position" ) + { + //get left upper outer corner relative to screen + //pixels, screen position + SolarMutexGuard aSolarGuard; + createDialogOnDemand(); + if (m_xDialog) + { + Point aPos(m_xDialog->getDialog()->get_position()); + awt::Point aPoint(aPos.X(), aPos.Y()); + aRet <<= aPoint; + } + } + else if( rPropertyName == "Size" ) + { + //get outer size inclusive decoration + //pixels, screen position + SolarMutexGuard aSolarGuard; + createDialogOnDemand(); + if (m_xDialog) + { + Size aRect(m_xDialog->getDialog()->get_size()); + awt::Size aSize(aRect.Width(), aRect.Height()); + aRet <<= aSize; + } + } + else if( rPropertyName == "UnlockControllersOnExecute" ) + { + aRet <<= m_bUnlockControllersOnExecute; + } + else + throw beans::UnknownPropertyException( "unknown property was tried to get from chart wizard" , nullptr ); + return aRet; +} + +void SAL_CALL CreationWizardUnoDlg::addPropertyChangeListener( + const OUString& /* aPropertyName */, const uno::Reference< beans::XPropertyChangeListener >& /* xListener */ ) +{ + OSL_FAIL("not implemented"); +} +void SAL_CALL CreationWizardUnoDlg::removePropertyChangeListener( + const OUString& /* aPropertyName */, const uno::Reference< beans::XPropertyChangeListener >& /* aListener */ ) +{ + OSL_FAIL("not implemented"); +} + +void SAL_CALL CreationWizardUnoDlg::addVetoableChangeListener( const OUString& /* PropertyName */, const uno::Reference< beans::XVetoableChangeListener >& /* aListener */ ) +{ + OSL_FAIL("not implemented"); +} + +void SAL_CALL CreationWizardUnoDlg::removeVetoableChangeListener( const OUString& /* PropertyName */, const uno::Reference< beans::XVetoableChangeListener >& /* aListener */ ) +{ + OSL_FAIL("not implemented"); +} + +} //namespace chart + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_chart2_WizardDialog_get_implementation(css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new chart::CreationWizardUnoDlg(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_DataEditor.cxx b/chart2/source/controller/dialogs/dlg_DataEditor.cxx new file mode 100644 index 000000000..3cb9598cb --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_DataEditor.cxx @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_DataEditor.hxx> +#include "DataBrowser.hxx" +#include <comphelper/stl_types.hxx> + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/frame/XStorable.hpp> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +DataEditor::DataEditor(weld::Window* pParent, + const Reference< chart2::XChartDocument > & xChartDoc, + const Reference< uno::XComponentContext > & xContext) + : GenericDialogController(pParent, "modules/schart/ui/chartdatadialog.ui", "ChartDataDialog") + , m_bReadOnly(false) + , m_xChartDoc(xChartDoc) + , m_xContext(xContext) + , m_xTbxData(m_xBuilder->weld_toolbar("toolbar")) + , m_xCloseBtn(m_xBuilder->weld_button("close")) + , m_xTable(m_xBuilder->weld_container("datawindow")) + , m_xColumns(m_xBuilder->weld_container("columns")) + , m_xColors(m_xBuilder->weld_container("colorcolumns")) + , m_xTableCtrlParent(m_xTable->CreateChildFrame()) + , m_xBrwData(VclPtr<DataBrowser>::Create(m_xTableCtrlParent, m_xColumns.get(), m_xColors.get())) +{ + m_xCloseBtn->connect_clicked(LINK(this, DataEditor, CloseHdl)); + + Size aSize(m_xTable->get_approximate_digit_width() * 75, m_xTable->get_text_height() * 15); + m_xTable->set_size_request(aSize.Width(), aSize.Height()); + + m_xBrwData->Show(); + + m_xTbxData->connect_clicked(LINK(this, DataEditor, ToolboxHdl)); + + m_xBrwData->SetCursorMovedHdl( LINK( this, DataEditor, BrowserCursorMovedHdl )); + + m_xBrwData->SetDataFromModel( m_xChartDoc, m_xContext ); + m_xBrwData->GrabFocus(); + + bool bReadOnly = true; + Reference< frame::XStorable > xStor( m_xChartDoc, uno::UNO_QUERY ); + if( xStor.is()) + bReadOnly = xStor->isReadonly(); + SetReadOnly( bReadOnly ); +} + +DataEditor::~DataEditor() +{ + m_xBrwData.disposeAndClear(); + m_xTableCtrlParent->dispose(); + m_xTableCtrlParent.clear(); +} + +// react on click (or keypress) on toolbar icon +IMPL_LINK(DataEditor, ToolboxHdl, const OString&, rId, void) +{ + if (rId == "InsertRow") + m_xBrwData->InsertRow(); + else if (rId == "InsertColumn") + m_xBrwData->InsertColumn(); + else if (rId == "InsertTextColumn") + m_xBrwData->InsertTextColumn(); + else if (rId == "RemoveRow") + m_xBrwData->RemoveRow(); + else if (rId == "RemoveColumn") + m_xBrwData->RemoveColumn(); + else if (rId == "MoveLeftColumn") + m_xBrwData->MoveLeftColumn(); + else if (rId == "MoveRightColumn") + m_xBrwData->MoveRightColumn(); + else if (rId == "MoveUpRow") + m_xBrwData->MoveUpRow(); + else if (rId == "MoveDownRow") + m_xBrwData->MoveDownRow(); +} + +// refresh toolbar icons according to currently selected cell in browse box +IMPL_LINK_NOARG(DataEditor, BrowserCursorMovedHdl, DataBrowser*, void) +{ + if( m_bReadOnly ) + return; + + bool bIsDataValid = m_xBrwData->IsEnableItem(); + + m_xTbxData->set_item_sensitive("InsertRow", bIsDataValid && m_xBrwData->MayInsertRow() ); + m_xTbxData->set_item_sensitive("InsertColumn", bIsDataValid && m_xBrwData->MayInsertColumn() ); + m_xTbxData->set_item_sensitive("InsertTextColumn", bIsDataValid && m_xBrwData->MayInsertColumn() ); + m_xTbxData->set_item_sensitive("RemoveRow", m_xBrwData->MayDeleteRow() ); + m_xTbxData->set_item_sensitive("RemoveColumn", m_xBrwData->MayDeleteColumn() ); + + m_xTbxData->set_item_sensitive("MoveLeftColumn", bIsDataValid && m_xBrwData->MayMoveLeftColumns() ); + m_xTbxData->set_item_sensitive("MoveRightColumn", bIsDataValid && m_xBrwData->MayMoveRightColumns() ); + m_xTbxData->set_item_sensitive("MoveUpRow", bIsDataValid && m_xBrwData->MayMoveDownRows() ); + m_xTbxData->set_item_sensitive("MoveDownRow", bIsDataValid && m_xBrwData->MayMoveUpRows() ); +} + +// disable all modifying controls +void DataEditor::SetReadOnly( bool bReadOnly ) +{ + m_bReadOnly = bReadOnly; + if( m_bReadOnly ) + { + m_xTbxData->set_item_sensitive("InsertRow", false); + m_xTbxData->set_item_sensitive("InsertColumn", false); + m_xTbxData->set_item_sensitive("InsertTextColumn", false); + m_xTbxData->set_item_sensitive("RemoveRow", false); + m_xTbxData->set_item_sensitive("RemoveColumn", false); + m_xTbxData->set_item_sensitive("MoveLeftColumn", false); + m_xTbxData->set_item_sensitive("MoveRightColumn", false); + m_xTbxData->set_item_sensitive("MoveUpRow", false); + m_xTbxData->set_item_sensitive("MoveDownRow", false); + } + + m_xBrwData->SetReadOnly( m_bReadOnly ); +} + +IMPL_LINK_NOARG(DataEditor, CloseHdl, weld::Button&, void) +{ + bool bApplied = m_xBrwData->EndEditing(); // apply changes to model + if (bApplied) + m_xDialog->response(RET_CLOSE); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_DataSource.cxx b/chart2/source/controller/dialogs/dlg_DataSource.cxx new file mode 100644 index 000000000..b196b24d9 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_DataSource.cxx @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include <dlg_DataSource.hxx> +#include <ChartTypeTemplateProvider.hxx> +#include <DiagramHelper.hxx> +#include "DialogModel.hxx" + +#include "tp_RangeChooser.hxx" +#include "tp_DataSource.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::chart; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +namespace { + +class DocumentChartTypeTemplateProvider : public ChartTypeTemplateProvider +{ +public: + explicit DocumentChartTypeTemplateProvider( + const Reference< chart2::XChartDocument > & xDoc ); + + // ____ ChartTypeTemplateProvider ____ + virtual Reference< chart2::XChartTypeTemplate > getCurrentTemplate() const override; + +private: + Reference< chart2::XChartTypeTemplate > m_xTemplate; +}; + +} + +DocumentChartTypeTemplateProvider::DocumentChartTypeTemplateProvider( + const Reference< chart2::XChartDocument > & xDoc ) +{ + if( !xDoc.is()) + return; + + Reference< chart2::XDiagram > xDia( xDoc->getFirstDiagram()); + if( xDia.is()) + { + DiagramHelper::tTemplateWithServiceName aResult( + DiagramHelper::getTemplateForDiagram( + xDia, + Reference< lang::XMultiServiceFactory >( + xDoc->getChartTypeManager(), uno::UNO_QUERY ) )); + m_xTemplate.set( aResult.first ); + } +} + +Reference< chart2::XChartTypeTemplate > DocumentChartTypeTemplateProvider::getCurrentTemplate() const +{ + return m_xTemplate; +} + +sal_uInt16 DataSourceDialog::m_nLastPageId = 0; + +DataSourceDialog::DataSourceDialog(weld::Window * pParent, + const Reference< XChartDocument > & xChartDocument, + const Reference< uno::XComponentContext > & xContext) + : GenericDialogController(pParent, "modules/schart/ui/datarangedialog.ui", + "DataRangeDialog") + , m_apDocTemplateProvider(new DocumentChartTypeTemplateProvider(xChartDocument)) + , m_apDialogModel(new DialogModel(xChartDocument, xContext)) + , m_bRangeChooserTabIsValid(true) + , m_bDataSourceTabIsValid(true) + , m_bTogglingEnabled(true) + , m_xTabControl(m_xBuilder->weld_notebook("tabcontrol")) + , m_xBtnOK(m_xBuilder->weld_button("ok")) +{ + m_xRangeChooserTabPage = std::make_unique<RangeChooserTabPage>(m_xTabControl->get_page("range"), this, + *m_apDialogModel, + m_apDocTemplateProvider.get(), true /* bHideDescription */ ); + m_xDataSourceTabPage = std::make_unique<DataSourceTabPage>(m_xTabControl->get_page("series"), this, + *m_apDialogModel, + m_apDocTemplateProvider.get(), true /* bHideDescription */ ); + m_xTabControl->connect_enter_page(LINK(this, DataSourceDialog, ActivatePageHdl)); + m_xTabControl->connect_leave_page(LINK(this, DataSourceDialog, DeactivatePageHdl)); + ActivatePageHdl(m_xTabControl->get_current_page_ident()); + if (m_nLastPageId != 0) + { + m_xTabControl->set_current_page(m_nLastPageId); + ActivatePageHdl(m_xTabControl->get_current_page_ident()); + } +} + +DataSourceDialog::~DataSourceDialog() +{ + m_xRangeChooserTabPage.reset(); + m_xDataSourceTabPage.reset(); + m_nLastPageId = m_xTabControl->get_current_page(); +} + +short DataSourceDialog::run() +{ + short nResult = GenericDialogController::run(); + if( nResult == RET_OK ) + { + if( m_xRangeChooserTabPage ) + m_xRangeChooserTabPage->commitPage(); + if( m_xDataSourceTabPage ) + m_xDataSourceTabPage->commitPage(); + } + return nResult; +} + +IMPL_LINK(DataSourceDialog, ActivatePageHdl, const OString&, rPage, void) +{ + if (rPage == "range") + m_xRangeChooserTabPage->Activate(); + else if (rPage == "series") + m_xDataSourceTabPage->Activate(); +} + +// allow/disallow user to leave page +IMPL_LINK_NOARG(DataSourceDialog, DeactivatePageHdl, const OString&, bool) +{ + return m_bTogglingEnabled; +} + +void DataSourceDialog::setInvalidPage(BuilderPage* pTabPage) +{ + if (pTabPage == m_xRangeChooserTabPage.get()) + m_bRangeChooserTabIsValid = false; + else if (pTabPage == m_xDataSourceTabPage.get()) + m_bDataSourceTabIsValid = false; + + if (!(m_bRangeChooserTabIsValid && m_bDataSourceTabIsValid)) + { + m_xBtnOK->set_sensitive(false); + // note: there seems to be no suitable mechanism to address pages by + // identifier, at least it is unclear what the page identifiers are. + // @todo: change the fixed numbers to identifiers + if( m_bRangeChooserTabIsValid ) + m_xTabControl->set_current_page(1); + else if( m_bDataSourceTabIsValid ) + m_xTabControl->set_current_page(0); + m_bTogglingEnabled = false; + } +} + +void DataSourceDialog::setValidPage(BuilderPage* pTabPage) +{ + if( pTabPage == m_xRangeChooserTabPage.get() ) + m_bRangeChooserTabIsValid = true; + else if( pTabPage == m_xDataSourceTabPage.get() ) + m_bDataSourceTabIsValid = true; + + if (m_bRangeChooserTabIsValid && m_bDataSourceTabIsValid) + { + m_xBtnOK->set_sensitive(true); + m_bTogglingEnabled = true; + } +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx b/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx new file mode 100644 index 000000000..3843263ad --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertAxis_Grid.cxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_InsertAxis_Grid.hxx> + +namespace chart +{ + +InsertAxisOrGridDialogData::InsertAxisOrGridDialogData() + : aPossibilityList(6) + , aExistenceList(6) +{ + sal_Int32 nN = 0; + for(nN=6;nN--;) + aPossibilityList[nN]=true; + for(nN=6;nN--;) + aExistenceList[nN]=false; +} + +// SchAxisDlg + +SchAxisDlg::SchAxisDlg(weld::Window* pWindow, + const InsertAxisOrGridDialogData& rInput, bool bAxisDlg) + : GenericDialogController(pWindow, + bAxisDlg ? + OUString("modules/schart/ui/insertaxisdlg.ui") : + OUString("modules/schart/ui/insertgriddlg.ui"), + bAxisDlg ? + OString("InsertAxisDialog") : + OString("InsertGridDialog")) + , m_xCbPrimaryX(m_xBuilder->weld_check_button("primaryX")) + , m_xCbPrimaryY(m_xBuilder->weld_check_button("primaryY")) + , m_xCbPrimaryZ(m_xBuilder->weld_check_button("primaryZ")) + , m_xCbSecondaryX(m_xBuilder->weld_check_button("secondaryX")) + , m_xCbSecondaryY(m_xBuilder->weld_check_button("secondaryY")) + , m_xCbSecondaryZ(m_xBuilder->weld_check_button("secondaryZ")) +{ + if (bAxisDlg) + { + //todo: remove if secondary z axis are possible somewhere + m_xCbSecondaryZ->hide(); + } + + m_xCbPrimaryX->set_active( rInput.aExistenceList[0] ); + m_xCbPrimaryY->set_active( rInput.aExistenceList[1] ); + m_xCbPrimaryZ->set_active( rInput.aExistenceList[2] ); + m_xCbSecondaryX->set_active( rInput.aExistenceList[3] ); + m_xCbSecondaryY->set_active( rInput.aExistenceList[4] ); + m_xCbSecondaryZ->set_active( rInput.aExistenceList[5] ); + + m_xCbPrimaryX->set_sensitive( rInput.aPossibilityList[0] ); + m_xCbPrimaryY->set_sensitive( rInput.aPossibilityList[1] ); + m_xCbPrimaryZ->set_sensitive( rInput.aPossibilityList[2] ); + m_xCbSecondaryX->set_sensitive( rInput.aPossibilityList[3] ); + m_xCbSecondaryY->set_sensitive( rInput.aPossibilityList[4] ); + m_xCbSecondaryZ->set_sensitive( rInput.aPossibilityList[5] ); +} + +void SchAxisDlg::getResult( InsertAxisOrGridDialogData& rOutput ) +{ + rOutput.aExistenceList[0]=m_xCbPrimaryX->get_active(); + rOutput.aExistenceList[1]=m_xCbPrimaryY->get_active(); + rOutput.aExistenceList[2]=m_xCbPrimaryZ->get_active(); + rOutput.aExistenceList[3]=m_xCbSecondaryX->get_active(); + rOutput.aExistenceList[4]=m_xCbSecondaryY->get_active(); + rOutput.aExistenceList[5]=m_xCbSecondaryZ->get_active(); +} + +SchGridDlg::SchGridDlg(weld::Window* pParent, const InsertAxisOrGridDialogData& rInput) + : SchAxisDlg(pParent, rInput, false) //rInAttrs, b3D, bNet, bSecondaryX, bSecondaryY, false ) +{ +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx b/chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx new file mode 100644 index 000000000..57817d883 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertDataLabel.cxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_InsertDataLabel.hxx> +#include "res_DataLabel.hxx" + +namespace chart +{ + +DataLabelsDialog::DataLabelsDialog(weld::Window* pWindow, const SfxItemSet& rInAttrs, SvNumberFormatter* pFormatter) + : GenericDialogController(pWindow, "modules/schart/ui/dlg_DataLabel.ui", "dlg_DataLabels") + , m_apDataLabelResources(new DataLabelResources(m_xBuilder.get(), pWindow, rInAttrs)) +{ + m_apDataLabelResources->SetNumberFormatter( pFormatter ); + m_apDataLabelResources->Reset(rInAttrs); +} + +DataLabelsDialog::~DataLabelsDialog() = default; + +void DataLabelsDialog::FillItemSet(SfxItemSet& rOutAttrs) +{ + m_apDataLabelResources->FillItemSet(&rOutAttrs); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx b/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx new file mode 100644 index 000000000..a7aeb35d7 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertErrorBars.cxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_InsertErrorBars.hxx> +#include <res_ErrorBar.hxx> +#include <chartview/ExplicitScaleValues.hxx> +#include <chartview/ExplicitValueProvider.hxx> +#include <ChartModelHelper.hxx> +#include <ObjectIdentifier.hxx> +#include <DiagramHelper.hxx> +#include <AxisHelper.hxx> +#include <ObjectNameProvider.hxx> + +#include <com/sun/star/frame/XModel.hpp> +#include <comphelper/servicehelper.hxx> + +using ::com::sun::star::uno::Reference; +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +namespace chart +{ + +InsertErrorBarsDialog::InsertErrorBarsDialog( + weld::Window* pParent, const SfxItemSet& rMyAttrs, + const uno::Reference< chart2::XChartDocument > & xChartDocument, + ErrorBarResources::tErrorBarType eType /* = ErrorBarResources::ERROR_BAR_Y */ ) + : GenericDialogController(pParent, "modules/schart/ui/dlg_InsertErrorBars.ui", "dlg_InsertErrorBars") + , m_apErrorBarResources( new ErrorBarResources( + m_xBuilder.get(), this, rMyAttrs, + /* bNoneAvailable = */ true, eType )) +{ + ObjectType objType = eType == ErrorBarResources::ERROR_BAR_Y ? OBJECTTYPE_DATA_ERRORS_Y : OBJECTTYPE_DATA_ERRORS_X; + + m_xDialog->set_title(ObjectNameProvider::getName_ObjectForAllSeries(objType)); + + m_apErrorBarResources->SetChartDocumentForRangeChoosing( xChartDocument ); +} + +void InsertErrorBarsDialog::FillItemSet(SfxItemSet& rOutAttrs) +{ + m_apErrorBarResources->FillItemSet(rOutAttrs); +} + +void InsertErrorBarsDialog::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth ) +{ + m_apErrorBarResources->SetAxisMinorStepWidthForErrorBarDecimals( fMinorStepWidth ); +} + +double InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( + const Reference< frame::XModel >& xChartModel, + const Reference< uno::XInterface >& xChartView, + const OUString& rSelectedObjectCID ) +{ + double fStepWidth = 0.001; + + ExplicitValueProvider* pExplicitValueProvider( comphelper::getUnoTunnelImplementation<ExplicitValueProvider>(xChartView) ); + if( pExplicitValueProvider ) + { + Reference< XAxis > xAxis; + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSelectedObjectCID, xChartModel ); + xAxis = DiagramHelper::getAttachedAxis( xSeries, xDiagram ); + if(!xAxis.is()) + xAxis = AxisHelper::getAxis( 1/*nDimensionIndex*/, true/*bMainAxis*/, xDiagram ); + if(xAxis.is()) + { + ExplicitScaleData aExplicitScale; + ExplicitIncrementData aExplicitIncrement; + pExplicitValueProvider->getExplicitValuesForAxis( xAxis,aExplicitScale, aExplicitIncrement ); + + fStepWidth = aExplicitIncrement.Distance; + if( !aExplicitIncrement.SubIncrements.empty() && aExplicitIncrement.SubIncrements[0].IntervalCount>0 ) + fStepWidth=fStepWidth/double(aExplicitIncrement.SubIncrements[0].IntervalCount); + else + fStepWidth/=10; + } + } + + return fStepWidth; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_InsertLegend.cxx b/chart2/source/controller/dialogs/dlg_InsertLegend.cxx new file mode 100644 index 000000000..65dc9010e --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertLegend.cxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_InsertLegend.hxx> +#include <res_LegendPosition.hxx> + +namespace chart +{ + +using namespace ::com::sun::star; + +SchLegendDlg::SchLegendDlg(weld::Window* pWindow, const uno::Reference< uno::XComponentContext>& xCC) + : GenericDialogController(pWindow, "modules/schart/ui/dlg_InsertLegend.ui", "dlg_InsertLegend") + , m_xLegendPositionResources(new LegendPositionResources(*m_xBuilder, xCC)) +{ +} + +void SchLegendDlg::init( const uno::Reference< frame::XModel >& xChartModel ) +{ + m_xLegendPositionResources->writeToResources( xChartModel ); +} + +void SchLegendDlg::writeToModel( const uno::Reference< frame::XModel >& xChartModel ) const +{ + m_xLegendPositionResources->writeToModel( xChartModel ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_InsertTitle.cxx b/chart2/source/controller/dialogs/dlg_InsertTitle.cxx new file mode 100644 index 000000000..f228e037d --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_InsertTitle.cxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_InsertTitle.hxx> +#include <res_Titles.hxx> +#include <ObjectNameProvider.hxx> + +namespace chart +{ + +SchTitleDlg::SchTitleDlg(weld::Window* pWindow, const TitleDialogData& rInput) + : GenericDialogController(pWindow, "modules/schart/ui/inserttitledlg.ui", "InsertTitleDialog") + , m_xTitleResources(new TitleResources(*m_xBuilder, true)) +{ + m_xDialog->set_title(ObjectNameProvider::getName(OBJECTTYPE_TITLE, true)); + m_xTitleResources->writeToResources( rInput ); +} + +void SchTitleDlg::getResult( TitleDialogData& rOutput ) +{ + m_xTitleResources->readFromResources( rOutput ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_NumberFormat.cxx b/chart2/source/controller/dialogs/dlg_NumberFormat.cxx new file mode 100644 index 000000000..d91b545cd --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_NumberFormat.cxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "dlg_NumberFormat.hxx" + +#include <svl/itemset.hxx> +#include <svx/dialogs.hrc> +#include <svx/svxids.hrc> +#include <sfx2/tabdlg.hxx> +#include <sfx2/sfxdlg.hxx> + +namespace chart +{ +using namespace ::com::sun::star; + +NumberFormatDialog::NumberFormatDialog(weld::Window* pParent, SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet, "cui/ui/formatnumberdialog.ui", "FormatNumberDialog") +{ + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_NUMBERFORMAT ); + if (fnCreatePage) + { + std::unique_ptr<SfxTabPage> xTabPage = (*fnCreatePage)(get_content_area(), this, &rSet); + xTabPage->PageCreated(rSet); + SetTabPage(std::move(xTabPage)); + } +} + +SfxItemSet NumberFormatDialog::CreateEmptyItemSetForNumberFormatDialog( SfxItemPool& rItemPool ) +{ + static const sal_uInt16 nWhichPairs[] = + { + SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO, + SID_ATTR_NUMBERFORMAT_NOLANGUAGE, SID_ATTR_NUMBERFORMAT_NOLANGUAGE, + SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA, + SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, + 0 + }; + return SfxItemSet( rItemPool, nWhichPairs ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_NumberFormat.hxx b/chart2/source/controller/dialogs/dlg_NumberFormat.hxx new file mode 100644 index 000000000..f0c69702f --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_NumberFormat.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DLG_NUMBERFORMAT_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_DLG_NUMBERFORMAT_HXX + +#include <sfx2/basedlgs.hxx> + +namespace weld { class Window; } +class SfxItemSet; +class SfxItemPool; + +namespace chart +{ + +class NumberFormatDialog : public SfxSingleTabDialogController +{ +public: + NumberFormatDialog(weld::Window* pParent, SfxItemSet& rSet); + + static SfxItemSet CreateEmptyItemSetForNumberFormatDialog( SfxItemPool& rItemPool ); +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx new file mode 100644 index 000000000..1add0435b --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ObjectProperties.cxx @@ -0,0 +1,624 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_ObjectProperties.hxx> +#include <strings.hrc> +#include "tp_AxisLabel.hxx" +#include "tp_DataLabel.hxx" +#include "tp_LegendPosition.hxx" +#include "tp_PointGeometry.hxx" +#include "tp_Scale.hxx" +#include "tp_AxisPositions.hxx" +#include "tp_ErrorBars.hxx" +#include "tp_Trendline.hxx" +#include "tp_SeriesToAxis.hxx" +#include "tp_TitleRotation.hxx" +#include "tp_PolarOptions.hxx" +#include "tp_DataPointOption.hxx" +#include <ResId.hxx> +#include <ViewElementListProvider.hxx> +#include <ChartModelHelper.hxx> +#include <ChartTypeHelper.hxx> +#include <ObjectNameProvider.hxx> +#include <DiagramHelper.hxx> +#include <NumberFormatterWrapper.hxx> +#include <AxisHelper.hxx> +#include <ExplicitCategoriesProvider.hxx> +#include <ChartModel.hxx> +#include <CommonConverters.hxx> +#include <RegressionCalculationHelper.hxx> + +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/XAxis.hpp> +#include <svl/intitem.hxx> +#include <svl/languageoptions.hxx> + +#include <svx/svxids.hrc> + +#include <svx/drawitem.hxx> +#include <svx/ofaitem.hxx> +#include <svx/svxgrahicitem.hxx> + +#include <svx/dialogs.hrc> +#include <editeng/flstitem.hxx> + +#include <svx/flagsdef.hxx> +#include <svx/numinf.hxx> + +#include <svl/cjkoptions.hxx> +#include <tools/diagnose_ex.h> + +namespace com::sun::star::chart2 { class XChartType; } +namespace com::sun::star::chart2 { class XDataSeries; } + +namespace chart +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::beans::XPropertySet; + +ObjectPropertiesDialogParameter::ObjectPropertiesDialogParameter( const OUString& rObjectCID ) + : m_aObjectCID( rObjectCID ) + , m_eObjectType( ObjectIdentifier::getObjectType( m_aObjectCID ) ) + , m_bAffectsMultipleObjects(false) + , m_aLocalizedName() + , m_bHasGeometryProperties(false) + , m_bHasStatisticProperties(false) + , m_bProvidesSecondaryYAxis(false) + , m_bProvidesOverlapAndGapWidth(false) + , m_bProvidesBarConnectors(false) + , m_bHasAreaProperties(false) + , m_bHasSymbolProperties(false) + , m_bHasNumberProperties(false) + , m_bProvidesStartingAngle(false) + , m_bProvidesMissingValueTreatments(false) + , m_bIsPieChartDataPoint(false) + , m_bHasScaleProperties(false) + , m_bCanAxisLabelsBeStaggered(false) + , m_bSupportingAxisPositioning(false) + , m_bShowAxisOrigin(false) + , m_bIsCrossingAxisIsCategoryAxis(false) + , m_bSupportingCategoryPositioning(false) + , m_aCategories() + , m_bComplexCategoriesAxis( false ) + , m_nNbPoints( 0 ) +{ + OUString aParticleID = ObjectIdentifier::getParticleID( m_aObjectCID ); + m_bAffectsMultipleObjects = (aParticleID == "ALLELEMENTS"); +} +ObjectPropertiesDialogParameter::~ObjectPropertiesDialogParameter() +{ +} + +void ObjectPropertiesDialogParameter::init( const uno::Reference< frame::XModel >& xChartModel ) +{ + m_xChartDocument.set( xChartModel, uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aObjectCID, xChartModel ); + uno::Reference< XChartType > xChartType = ChartModelHelper::getChartTypeOfSeries( xChartModel, xSeries ); + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + + bool bHasSeriesProperties = (m_eObjectType==OBJECTTYPE_DATA_SERIES); + bool bHasDataPointproperties = (m_eObjectType==OBJECTTYPE_DATA_POINT); + + if( bHasSeriesProperties || bHasDataPointproperties ) + { + m_bHasGeometryProperties = ChartTypeHelper::isSupportingGeometryProperties( xChartType, nDimensionCount ); + m_bHasAreaProperties = ChartTypeHelper::isSupportingAreaProperties( xChartType, nDimensionCount ); + m_bHasSymbolProperties = ChartTypeHelper::isSupportingSymbolProperties( xChartType, nDimensionCount ); + m_bIsPieChartDataPoint = bHasDataPointproperties && ChartTypeHelper::isSupportingStartingAngle( xChartType ); + + if( bHasSeriesProperties ) + { + m_bHasStatisticProperties = ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ); + m_bProvidesSecondaryYAxis = ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount ); + m_bProvidesOverlapAndGapWidth = ChartTypeHelper::isSupportingOverlapAndGapWidthProperties( xChartType, nDimensionCount ); + m_bProvidesBarConnectors = ChartTypeHelper::isSupportingBarConnectors( xChartType, nDimensionCount ); + m_bProvidesStartingAngle = ChartTypeHelper::isSupportingStartingAngle( xChartType ); + + m_bProvidesMissingValueTreatments = ChartTypeHelper::getSupportedMissingValueTreatments( xChartType ) + .hasElements(); + } + } + + if( m_eObjectType == OBJECTTYPE_DATA_ERRORS_X || + m_eObjectType == OBJECTTYPE_DATA_ERRORS_Y || + m_eObjectType == OBJECTTYPE_DATA_ERRORS_Z) + m_bHasStatisticProperties = true; + + if( m_eObjectType == OBJECTTYPE_AXIS ) + { + //show scale properties only for a single axis not for multiselection + m_bHasScaleProperties = !m_bAffectsMultipleObjects; + + if( m_bHasScaleProperties ) + { + uno::Reference< XAxis > xAxis( ObjectIdentifier::getAxisForCID( m_aObjectCID, xChartModel ) ); + if( xAxis.is() ) + { + //no scale page for series axis + ScaleData aData( xAxis->getScaleData() ); + if( aData.AxisType == chart2::AxisType::SERIES ) + m_bHasScaleProperties = false; + if( aData.AxisType != chart2::AxisType::SERIES ) + m_bHasNumberProperties = true; + + //is the crossing main axis a category axes?: + uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis( xAxis, xDiagram ) ); + uno::Reference< XAxis > xCrossingMainAxis( AxisHelper::getCrossingMainAxis( xAxis, xCooSys ) ); + if( xCrossingMainAxis.is() ) + { + ScaleData aScale( xCrossingMainAxis->getScaleData() ); + m_bIsCrossingAxisIsCategoryAxis = ( aScale.AxisType == chart2::AxisType::CATEGORY ); + if( m_bIsCrossingAxisIsCategoryAxis ) + { + ChartModel* pModel = dynamic_cast<ChartModel*>(xChartModel.get()); + if (pModel) + m_aCategories = DiagramHelper::getExplicitSimpleCategories( *pModel ); + } + } + + sal_Int32 nCooSysIndex=0; + sal_Int32 nDimensionIndex=0; + sal_Int32 nAxisIndex=0; + if( AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ) ) + { + xChartType = AxisHelper::getFirstChartTypeWithSeriesAttachedToAxisIndex( xDiagram, nAxisIndex ); + //show positioning controls only if they make sense + m_bSupportingAxisPositioning = ChartTypeHelper::isSupportingAxisPositioning( xChartType, nDimensionCount, nDimensionIndex ); + + //show axis origin only for secondary y axis + if( nDimensionIndex==1 && nAxisIndex==1 && ChartTypeHelper::isSupportingBaseValue( xChartType ) ) + m_bShowAxisOrigin = true; + + if ( nDimensionIndex == 0 && ( aData.AxisType == chart2::AxisType::CATEGORY || aData.AxisType == chart2::AxisType::DATE ) ) + { + ChartModel* pModel = dynamic_cast<ChartModel*>(xChartModel.get()); + if (pModel) + { + ExplicitCategoriesProvider aExplicitCategoriesProvider( xCooSys, *pModel ); + m_bComplexCategoriesAxis = aExplicitCategoriesProvider.hasComplexCategories(); + } + + if (!m_bComplexCategoriesAxis) + m_bSupportingCategoryPositioning = ChartTypeHelper::isSupportingCategoryPositioning( xChartType, nDimensionCount ); + } + } + } + } + + //no staggering of labels for 3D axis + m_bCanAxisLabelsBeStaggered = nDimensionCount==2; + } + + if( m_eObjectType == OBJECTTYPE_DATA_CURVE ) + { + uno::Reference< data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); + Sequence< Reference< data::XLabeledDataSequence > > aDataSeqs( xSource->getDataSequences()); + Sequence< double > aXValues, aYValues; + bool bXValuesFound = false, bYValuesFound = false; + m_nNbPoints = 0; + sal_Int32 i = 0; + for( i=0; + ! (bXValuesFound && bYValuesFound) && i<aDataSeqs.getLength(); + ++i ) + { + try + { + Reference< data::XDataSequence > xSeq( aDataSeqs[i]->getValues()); + Reference< XPropertySet > xProp( xSeq, uno::UNO_QUERY_THROW ); + OUString aRole; + if( xProp->getPropertyValue( "Role" ) >>= aRole ) + { + if( !bXValuesFound && aRole == "values-x" ) + { + aXValues = DataSequenceToDoubleSequence( xSeq ); + bXValuesFound = true; + } + else if( !bYValuesFound && aRole == "values-y" ) + { + aYValues = DataSequenceToDoubleSequence( xSeq ); + bYValuesFound = true; + } + } + } + catch( const Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + if( !bXValuesFound && bYValuesFound ) + { + // initialize with 1, 2, ... + //first category (index 0) matches with real number 1.0 + aXValues.realloc( aYValues.getLength() ); + for( i=0; i<aXValues.getLength(); ++i ) + aXValues[i] = i+1; + bXValuesFound = true; + } + + if( bXValuesFound && bYValuesFound && + aXValues.hasElements() && + aYValues.hasElements() ) + { + RegressionCalculationHelper::tDoubleVectorPair aValues( + RegressionCalculationHelper::cleanup( aXValues, aYValues, RegressionCalculationHelper::isValid())); + m_nNbPoints = aValues.second.size(); + } + } + + //create gui name for this object + { + if( !m_bAffectsMultipleObjects && m_eObjectType == OBJECTTYPE_AXIS ) + { + m_aLocalizedName = ObjectNameProvider::getAxisName( m_aObjectCID, xChartModel ); + } + else if( !m_bAffectsMultipleObjects && ( m_eObjectType == OBJECTTYPE_GRID || m_eObjectType == OBJECTTYPE_SUBGRID ) ) + { + m_aLocalizedName = ObjectNameProvider::getGridName( m_aObjectCID, xChartModel ); + } + else if( !m_bAffectsMultipleObjects && m_eObjectType == OBJECTTYPE_TITLE ) + { + m_aLocalizedName = ObjectNameProvider::getTitleName( m_aObjectCID, xChartModel ); + } + else + { + switch( m_eObjectType ) + { + case OBJECTTYPE_DATA_POINT: + case OBJECTTYPE_DATA_LABEL: + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_ERRORS_X: + case OBJECTTYPE_DATA_ERRORS_Y: + case OBJECTTYPE_DATA_ERRORS_Z: + case OBJECTTYPE_DATA_AVERAGE_LINE: + case OBJECTTYPE_DATA_CURVE: + case OBJECTTYPE_DATA_CURVE_EQUATION: + if( m_bAffectsMultipleObjects ) + m_aLocalizedName = ObjectNameProvider::getName_ObjectForAllSeries( m_eObjectType ); + else + m_aLocalizedName = ObjectNameProvider::getName_ObjectForSeries( m_eObjectType, m_aObjectCID, m_xChartDocument ); + break; + default: + m_aLocalizedName = ObjectNameProvider::getName(m_eObjectType,m_bAffectsMultipleObjects); + break; + } + } + } +} + +const sal_uInt16 nNoArrowNoShadowDlg = 1101; + +void SchAttribTabDlg::setSymbolInformation( std::unique_ptr<SfxItemSet> pSymbolShapeProperties, + std::unique_ptr<Graphic> pAutoSymbolGraphic ) +{ + m_pSymbolShapeProperties = std::move(pSymbolShapeProperties); + m_pAutoSymbolGraphic = std::move(pAutoSymbolGraphic); +} + +void SchAttribTabDlg::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth ) +{ + m_fAxisMinorStepWidthForErrorBarDecimals = fMinorStepWidth; +} + +SchAttribTabDlg::SchAttribTabDlg(weld::Window* pParent, + const SfxItemSet* pAttr, + const ObjectPropertiesDialogParameter* pDialogParameter, + const ViewElementListProvider* pViewElementListProvider, + const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier) + : SfxTabDialogController(pParent, "modules/schart/ui/attributedialog.ui", "AttributeDialog", pAttr) + , m_pParameter( pDialogParameter ) + , m_pViewElementListProvider( pViewElementListProvider ) + , m_pNumberFormatter(nullptr) + , m_fAxisMinorStepWidthForErrorBarDecimals(0.1) + , m_bOKPressed(false) +{ + NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier ); + m_pNumberFormatter = aNumberFormatterWrapper.getSvNumberFormatter(); + + m_xDialog->set_title(pDialogParameter->getLocalizedName()); + + SvtCJKOptions aCJKOptions; + + switch (pDialogParameter->getObjectType()) + { + case OBJECTTYPE_TITLE: + AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE); + AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA); + AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE); + AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME); + AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS); + AddTabPage("alignment", SchResId(STR_PAGE_ALIGNMENT), SchAlignmentTabPage::Create); + if( aCJKOptions.IsAsianTypographyEnabled() ) + AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN); + break; + + case OBJECTTYPE_LEGEND: + AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE); + AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA); + AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE); + AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME); + AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS); + AddTabPage("legendpos", SchResId(STR_PAGE_POSITION), SchLegendPosTabPage::Create); + if (aCJKOptions.IsAsianTypographyEnabled()) + AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN); + break; + + case OBJECTTYPE_DATA_SERIES: + case OBJECTTYPE_DATA_POINT: + if( m_pParameter->ProvidesSecondaryYAxis() || m_pParameter->ProvidesOverlapAndGapWidth() || m_pParameter->ProvidesMissingValueTreatments() ) + AddTabPage("options", SchResId(STR_PAGE_OPTIONS),SchOptionTabPage::Create); + if( m_pParameter->ProvidesStartingAngle()) + AddTabPage("polaroptions", SchResId(STR_PAGE_OPTIONS), PolarOptionsTabPage::Create); + if (m_pParameter->IsPieChartDataPoint()) + AddTabPage("datapointoption", SchResId(STR_PAGE_OPTIONS), DataPointOptionTabPage::Create); + + if( m_pParameter->HasGeometryProperties() ) + AddTabPage("layout", SchResId(STR_PAGE_LAYOUT), SchLayoutTabPage::Create); + + if(m_pParameter->HasAreaProperties()) + { + AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA); + AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE); + } + AddTabPage("border", SchResId( m_pParameter->HasAreaProperties() ? STR_PAGE_BORDER : STR_PAGE_LINE ), RID_SVXPAGE_LINE); + break; + + case OBJECTTYPE_DATA_LABEL: + case OBJECTTYPE_DATA_LABELS: + AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE); + AddTabPage("datalabels", SchResId(STR_OBJECT_DATALABELS), DataLabelsTabPage::Create); + AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME); + AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS); + if( aCJKOptions.IsAsianTypographyEnabled() ) + AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN); + + break; + + case OBJECTTYPE_AXIS: + { + if( m_pParameter->HasScaleProperties() ) + { + AddTabPage("scale", SchResId(STR_PAGE_SCALE), ScaleTabPage::Create); + //no positioning page for z axes so far as the tickmarks are not shown so far + AddTabPage("axispos", SchResId(STR_PAGE_POSITIONING), AxisPositionsTabPage::Create); + } + AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE); + AddTabPage("axislabel", SchResId(STR_OBJECT_LABEL), SchAxisLabelTabPage::Create); + if( m_pParameter->HasNumberProperties() ) + AddTabPage("numberformat", SchResId(STR_PAGE_NUMBERS), RID_SVXPAGE_NUMBERFORMAT); + AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME); + AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS); + if( aCJKOptions.IsAsianTypographyEnabled() ) + AddTabPage("asian", SchResId(STR_PAGE_ASIAN), RID_SVXPAGE_PARA_ASIAN); + break; + } + + case OBJECTTYPE_DATA_ERRORS_X: + AddTabPage("xerrorbar", SchResId(STR_PAGE_XERROR_BARS), ErrorBarsTabPage::Create); + AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE); + break; + + case OBJECTTYPE_DATA_ERRORS_Y: + AddTabPage("yerrorbar", SchResId(STR_PAGE_YERROR_BARS), ErrorBarsTabPage::Create); + AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE); + break; + + case OBJECTTYPE_DATA_ERRORS_Z: + break; + + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: + case OBJECTTYPE_DATA_AVERAGE_LINE: + case OBJECTTYPE_DATA_STOCK_RANGE: + AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE); + break; + + case OBJECTTYPE_DATA_CURVE: + AddTabPage("trendline", SchResId(STR_PAGE_TRENDLINE_TYPE), TrendlineTabPage::Create); + AddTabPage("border", SchResId(STR_PAGE_LINE), RID_SVXPAGE_LINE); + break; + + case OBJECTTYPE_DATA_STOCK_LOSS: + case OBJECTTYPE_DATA_STOCK_GAIN: + case OBJECTTYPE_PAGE: + case OBJECTTYPE_DIAGRAM_FLOOR: + case OBJECTTYPE_DIAGRAM_WALL: + case OBJECTTYPE_DIAGRAM: + AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE); + AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA); + AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE); + break; + + case OBJECTTYPE_LEGEND_ENTRY: + case OBJECTTYPE_AXIS_UNITLABEL: + case OBJECTTYPE_UNKNOWN: + // nothing + break; + case OBJECTTYPE_DATA_CURVE_EQUATION: + AddTabPage("border", SchResId(STR_PAGE_BORDER), RID_SVXPAGE_LINE); + AddTabPage("area", SchResId(STR_PAGE_AREA), RID_SVXPAGE_AREA); + AddTabPage("transparent", SchResId(STR_PAGE_TRANSPARENCY), RID_SVXPAGE_TRANSPARENCE); + AddTabPage("fontname", SchResId(STR_PAGE_FONT), RID_SVXPAGE_CHAR_NAME); + AddTabPage("effects", SchResId(STR_PAGE_FONT_EFFECTS), RID_SVXPAGE_CHAR_EFFECTS); + AddTabPage("numberformat", SchResId(STR_PAGE_NUMBERS), RID_SVXPAGE_NUMBERFORMAT); + if (SvtLanguageOptions().IsCTLFontEnabled()) + { + /* When rotation is supported for equation text boxes, use + SchAlignmentTabPage::Create here. The special + SchAlignmentTabPage::CreateWithoutRotation can be deleted. */ + AddTabPage("alignment", SchResId(STR_PAGE_ALIGNMENT), SchAlignmentTabPage::CreateWithoutRotation); + } + break; + default: + break; + } + + // used to find out if user left the dialog with OK. When OK is pressed but + // no changes were done, Cancel is returned by the SfxTabDialog. See method + // DialogWasClosedWithOK. + GetOKButton().connect_clicked(LINK(this, SchAttribTabDlg, OKPressed)); +} + +SchAttribTabDlg::~SchAttribTabDlg() +{ +} + +void SchAttribTabDlg::PageCreated(const OString& rId, SfxTabPage &rPage) +{ + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + if (rId == "border") + { + aSet.Put (SvxColorListItem(m_pViewElementListProvider->GetColorTable(),SID_COLOR_TABLE)); + aSet.Put (SvxDashListItem(m_pViewElementListProvider->GetDashList(),SID_DASH_LIST)); + aSet.Put (SvxLineEndListItem(m_pViewElementListProvider->GetLineEndList(),SID_LINEEND_LIST)); + aSet.Put (SfxUInt16Item(SID_PAGE_TYPE,0)); + aSet.Put (SfxUInt16Item(SID_DLG_TYPE,nNoArrowNoShadowDlg)); + + if( m_pParameter->HasSymbolProperties() ) + { + aSet.Put(OfaPtrItem(SID_OBJECT_LIST,m_pViewElementListProvider->GetSymbolList())); + if( m_pSymbolShapeProperties ) + aSet.Put(SfxTabDialogItem(SID_ATTR_SET,*m_pSymbolShapeProperties)); + if( m_pAutoSymbolGraphic ) + aSet.Put(SvxGraphicItem(*m_pAutoSymbolGraphic)); + } + rPage.PageCreated(aSet); + } + else if (rId == "area") + { + aSet.Put(SvxColorListItem(m_pViewElementListProvider->GetColorTable(),SID_COLOR_TABLE)); + aSet.Put(SvxGradientListItem(m_pViewElementListProvider->GetGradientList(),SID_GRADIENT_LIST)); + aSet.Put(SvxHatchListItem(m_pViewElementListProvider->GetHatchList(),SID_HATCH_LIST)); + aSet.Put(SvxBitmapListItem(m_pViewElementListProvider->GetBitmapList(),SID_BITMAP_LIST)); + aSet.Put(SvxPatternListItem(m_pViewElementListProvider->GetPatternList(),SID_PATTERN_LIST)); + aSet.Put(SfxUInt16Item(SID_PAGE_TYPE,0)); + aSet.Put(SfxUInt16Item(SID_DLG_TYPE,nNoArrowNoShadowDlg)); + rPage.PageCreated(aSet); + } + else if (rId == "transparent") + { + aSet.Put (SfxUInt16Item(SID_PAGE_TYPE,0)); + aSet.Put (SfxUInt16Item(SID_DLG_TYPE,nNoArrowNoShadowDlg)); + rPage.PageCreated(aSet); + } + else if (rId == "fontname") + { + aSet.Put (SvxFontListItem(m_pViewElementListProvider->getFontList(), SID_ATTR_CHAR_FONTLIST)); + rPage.PageCreated(aSet); + } + else if (rId == "effects") + { + aSet.Put (SfxUInt16Item(SID_DISABLE_CTL,DISABLE_CASEMAP)); + rPage.PageCreated(aSet); + } + else if (rId == "axislabel") + { + bool bShowStaggeringControls = m_pParameter->CanAxisLabelsBeStaggered(); + static_cast<SchAxisLabelTabPage&>(rPage).ShowStaggeringControls( bShowStaggeringControls ); + dynamic_cast< SchAxisLabelTabPage& >( rPage ).SetComplexCategories( m_pParameter->IsComplexCategoriesAxis() ); + } + else if (rId == "axispos") + { + AxisPositionsTabPage* pPage = dynamic_cast< AxisPositionsTabPage* >( &rPage ); + if(pPage) + { + pPage->SetNumFormatter( m_pNumberFormatter ); + if( m_pParameter->IsCrossingAxisIsCategoryAxis() ) + { + pPage->SetCrossingAxisIsCategoryAxis( m_pParameter->IsCrossingAxisIsCategoryAxis() ); + pPage->SetCategories( m_pParameter->GetCategories() ); + } + pPage->SupportAxisPositioning( m_pParameter->IsSupportingAxisPositioning() ); + pPage->SupportCategoryPositioning( m_pParameter->IsSupportingCategoryPositioning() ); + } + } + else if (rId == "scale") + { + ScaleTabPage* pScaleTabPage = dynamic_cast< ScaleTabPage* >( &rPage ); + if(pScaleTabPage) + { + pScaleTabPage->SetNumFormatter( m_pNumberFormatter ); + pScaleTabPage->ShowAxisOrigin( m_pParameter->ShowAxisOrigin() ); + } + } + else if (rId == "datalabels") + { + DataLabelsTabPage* pLabelPage = dynamic_cast< DataLabelsTabPage* >( &rPage ); + if( pLabelPage ) + pLabelPage->SetNumberFormatter( m_pNumberFormatter ); + } + else if (rId == "numberformat") + { + aSet.Put (SvxNumberInfoItem( m_pNumberFormatter, static_cast<sal_uInt16>(SID_ATTR_NUMBERFORMAT_INFO))); + rPage.PageCreated(aSet); + } + else if (rId == "xerrorbar") + { + ErrorBarsTabPage * pTabPage = dynamic_cast< ErrorBarsTabPage * >( &rPage ); + OSL_ASSERT( pTabPage ); + if( pTabPage ) + { + pTabPage->SetAxisMinorStepWidthForErrorBarDecimals( m_fAxisMinorStepWidthForErrorBarDecimals ); + pTabPage->SetErrorBarType( ErrorBarResources::ERROR_BAR_X ); + pTabPage->SetChartDocumentForRangeChoosing( m_pParameter->getDocument()); + } + } + else if (rId == "yerrorbar") + { + ErrorBarsTabPage * pTabPage = dynamic_cast< ErrorBarsTabPage * >( &rPage ); + OSL_ASSERT( pTabPage ); + if( pTabPage ) + { + pTabPage->SetAxisMinorStepWidthForErrorBarDecimals( m_fAxisMinorStepWidthForErrorBarDecimals ); + pTabPage->SetErrorBarType( ErrorBarResources::ERROR_BAR_Y ); + pTabPage->SetChartDocumentForRangeChoosing( m_pParameter->getDocument()); + } + } + else if (rId == "options") + { + SchOptionTabPage* pTabPage = dynamic_cast< SchOptionTabPage* >( &rPage ); + if( pTabPage && m_pParameter ) + pTabPage->Init( m_pParameter->ProvidesSecondaryYAxis(), m_pParameter->ProvidesOverlapAndGapWidth(), + m_pParameter->ProvidesBarConnectors() ); + } + else if (rId == "trendline") + { + TrendlineTabPage* pTrendlineTabPage = dynamic_cast< TrendlineTabPage* >( &rPage ); + if(pTrendlineTabPage) + { + pTrendlineTabPage->SetNumFormatter( m_pNumberFormatter ); + pTrendlineTabPage->SetNbPoints( m_pParameter->getNbPoints() ); + } + } +} + +IMPL_LINK(SchAttribTabDlg, OKPressed, weld::Button&, rButton, void) +{ + m_bOKPressed = true; + OkHdl(rButton); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_ShapeFont.cxx b/chart2/source/controller/dialogs/dlg_ShapeFont.cxx new file mode 100644 index 000000000..f5fc702a2 --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ShapeFont.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_ShapeFont.hxx> +#include <ViewElementListProvider.hxx> + +#include <svl/intitem.hxx> +#include <svx/dialogs.hrc> +#include <svx/svxids.hrc> +#include <svx/flagsdef.hxx> +#include <editeng/flstitem.hxx> + +using namespace ::com::sun::star; + +namespace chart +{ + +ShapeFontDialog::ShapeFontDialog(weld::Window* pParent, const SfxItemSet* pAttr, + const ViewElementListProvider* pViewElementListProvider) + : SfxTabDialogController(pParent, "modules/schart/ui/chardialog.ui", "CharDialog", pAttr) + , m_pViewElementListProvider(pViewElementListProvider) +{ + AddTabPage("font", RID_SVXPAGE_CHAR_NAME); + AddTabPage("fonteffects", RID_SVXPAGE_CHAR_EFFECTS); + AddTabPage("position", RID_SVXPAGE_CHAR_POSITION ); +} + +void ShapeFontDialog::PageCreated(const OString& rId, SfxTabPage& rPage) +{ + SfxAllItemSet aSet( *( GetInputSetImpl()->GetPool() ) ); + if (rId == "font") + { + aSet.Put( SvxFontListItem( m_pViewElementListProvider->getFontList(), SID_ATTR_CHAR_FONTLIST ) ); + rPage.PageCreated( aSet ); + } + else if (rId == "fonteffects") + { + aSet.Put( SfxUInt16Item( SID_DISABLE_CTL, DISABLE_CASEMAP ) ); + rPage.PageCreated( aSet ); + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx b/chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx new file mode 100644 index 000000000..c990161cf --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_ShapeParagraph.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_ShapeParagraph.hxx> + +#include <svl/cjkoptions.hxx> +#include <svl/intitem.hxx> +#include <svx/dialogs.hrc> +#include <svx/svxids.hrc> +#include <svx/flagsdef.hxx> + +using namespace ::com::sun::star; + +namespace chart +{ + +ShapeParagraphDialog::ShapeParagraphDialog(weld::Window* pParent, + const SfxItemSet* pAttr) + : SfxTabDialogController(pParent, "modules/schart/ui/paradialog.ui", "ParagraphDialog", pAttr) +{ + SvtCJKOptions aCJKOptions; + + AddTabPage("labelTP_PARA_STD", RID_SVXPAGE_STD_PARAGRAPH); + AddTabPage("labelTP_PARA_ALIGN", RID_SVXPAGE_ALIGN_PARAGRAPH ); + if (aCJKOptions.IsAsianTypographyEnabled()) + { + AddTabPage("labelTP_PARA_ASIAN", RID_SVXPAGE_PARA_ASIAN); + } + else + { + RemoveTabPage("labelTP_PARA_ASIAN"); + } + AddTabPage("labelTP_TABULATOR", RID_SVXPAGE_TABULATOR); +} + +void ShapeParagraphDialog::PageCreated(const OString& rId, SfxTabPage& rPage) +{ + if (rId == "labelTP_TABULATOR") + { + SfxAllItemSet aSet( *( GetInputSetImpl()->GetPool() ) ); + TabulatorDisableFlags const nFlags(( TabulatorDisableFlags::TypeMask &~TabulatorDisableFlags::TypeLeft ) | + ( TabulatorDisableFlags::FillMask &~TabulatorDisableFlags::FillNone )); + aSet.Put( SfxUInt16Item( SID_SVXTABULATORTABPAGE_DISABLEFLAGS, static_cast<sal_uInt16>(nFlags)) ); + rPage.PageCreated( aSet ); + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/dlg_View3D.cxx b/chart2/source/controller/dialogs/dlg_View3D.cxx new file mode 100644 index 000000000..b81b7ecac --- /dev/null +++ b/chart2/source/controller/dialogs/dlg_View3D.cxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <dlg_View3D.hxx> +#include <strings.hrc> +#include <ResId.hxx> +#include "tp_3D_SceneGeometry.hxx" +#include "tp_3D_SceneAppearance.hxx" +#include "tp_3D_SceneIllumination.hxx" +#include <ChartModelHelper.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/chart2/XDiagram.hpp> +#include <com/sun/star/frame/XModel.hpp> + +namespace chart +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +sal_uInt16 View3DDialog::m_nLastPageId = 0; + +View3DDialog::View3DDialog(weld::Window* pParent, const uno::Reference< frame::XModel > & xChartModel) + : GenericDialogController(pParent, "modules/schart/ui/3dviewdialog.ui", "3DViewDialog") + , m_aControllerLocker(xChartModel) + , m_xTabControl(m_xBuilder->weld_notebook("tabcontrol")) +{ + uno::Reference< beans::XPropertySet > xSceneProperties( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + + m_xTabControl->append_page("geometry", SchResId(STR_PAGE_PERSPECTIVE)); + m_xGeometry.reset(new ThreeD_SceneGeometry_TabPage(m_xTabControl->get_page("geometry"), xSceneProperties, m_aControllerLocker)); + + m_xTabControl->append_page("appearance", SchResId(STR_PAGE_APPEARANCE)); + m_xAppearance.reset(new ThreeD_SceneAppearance_TabPage(m_xTabControl->get_page("appearance"), xChartModel, m_aControllerLocker)); + + m_xTabControl->append_page("illumination", SchResId(STR_PAGE_ILLUMINATION)); + m_xIllumination.reset(new ThreeD_SceneIllumination_TabPage(m_xTabControl->get_page("illumination"), m_xDialog.get(), + xSceneProperties, xChartModel)); + + m_xTabControl->connect_enter_page(LINK(this, View3DDialog, ActivatePageHdl)); + + m_xTabControl->set_current_page(m_nLastPageId); +} + +IMPL_LINK(View3DDialog, ActivatePageHdl, const OString&, rPage, void) +{ + if (rPage == "appearance") + m_xAppearance->ActivatePage(); +} + +View3DDialog::~View3DDialog() +{ + m_nLastPageId = m_xTabControl->get_current_page(); +} + +short View3DDialog::run() +{ + short nResult = GenericDialogController::run(); + if (nResult == RET_OK && m_xGeometry) + m_xGeometry->commitPendingChanges(); + return nResult; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_BarGeometry.cxx b/chart2/source/controller/dialogs/res_BarGeometry.cxx new file mode 100644 index 000000000..6b0a7eac2 --- /dev/null +++ b/chart2/source/controller/dialogs/res_BarGeometry.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <res_BarGeometry.hxx> +#include <ResId.hxx> +#include <chart.hrc> + +namespace chart +{ + +BarGeometryResources::BarGeometryResources(weld::Builder* pBuilder) + : m_xFT_Geometry(pBuilder->weld_label("shapeft")) + , m_xLB_Geometry(pBuilder->weld_tree_view("shape")) +{ + for (size_t i = 0; i < SAL_N_ELEMENTS(CHART_TYPE); ++i) + m_xLB_Geometry->append_text(SchResId(CHART_TYPE[i])); + m_xLB_Geometry->set_size_request(-1, m_xLB_Geometry->get_height_rows(4)); +} + +void BarGeometryResources::connect_changed(const Link<weld::TreeView&,void>& rLink) +{ + m_xLB_Geometry->connect_changed(rLink); +} + +void BarGeometryResources::set_visible( bool bShow ) +{ + m_xFT_Geometry->set_visible( bShow ); + m_xLB_Geometry->set_visible( bShow ); +} + +void BarGeometryResources::set_sensitive( bool bEnable ) +{ + m_xFT_Geometry->set_sensitive( bEnable ); + m_xLB_Geometry->set_sensitive( bEnable ); +} + +sal_Int32 BarGeometryResources::get_selected_index() const +{ + return m_xLB_Geometry->get_selected_index(); +} + +void BarGeometryResources::select(sal_Int32 nPos) +{ + if (nPos < m_xLB_Geometry->n_children()) + m_xLB_Geometry->select(nPos); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_DataLabel.cxx b/chart2/source/controller/dialogs/res_DataLabel.cxx new file mode 100644 index 000000000..ca1918c17 --- /dev/null +++ b/chart2/source/controller/dialogs/res_DataLabel.cxx @@ -0,0 +1,359 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "res_DataLabel.hxx" + +#include <TextDirectionListBox.hxx> +#include <chartview/ChartSfxItemIds.hxx> +#include "dlg_NumberFormat.hxx" + +#include <svx/numinf.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svl/ilstitem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <svx/svxids.hrc> +#include <osl/diagnose.h> + +namespace chart +{ + +namespace +{ + +const OUStringLiteral our_aLBEntryMap[] = {" ", ", ", "; ", "\n", ". "}; + +bool lcl_ReadNumberFormatFromItemSet( const SfxItemSet& rSet, sal_uInt16 nValueWhich, sal_uInt16 nSourceFormatWhich, sal_uLong& rnFormatKeyOut, bool& rbSourceFormatOut, bool& rbSourceFormatMixedStateOut ) +{ + bool bSet = false; + const SfxPoolItem *pItem1 = nullptr; + if( rSet.GetItemState( nValueWhich, true, &pItem1 ) == SfxItemState::SET ) + { + const SfxUInt32Item * pNumItem = dynamic_cast< const SfxUInt32Item * >( pItem1 ); + if( pNumItem ) + { + rnFormatKeyOut = pNumItem->GetValue(); + bSet = true; + } + } + + rbSourceFormatMixedStateOut=true; + const SfxPoolItem *pItem2 = nullptr; + if( rSet.GetItemState( nSourceFormatWhich, true, &pItem2 ) == SfxItemState::SET ) + { + const SfxBoolItem * pBoolItem = dynamic_cast< const SfxBoolItem * >( pItem2 ); + if( pBoolItem ) + { + rbSourceFormatOut = pBoolItem->GetValue(); + rbSourceFormatMixedStateOut=false; + } + } + return bSet; +} + +void lcl_setBoolItemToCheckBox(const SfxItemSet& rInAttrs, sal_uInt16 nWhichId, weld::CheckButton& rCheckbox) +{ + const SfxPoolItem *pPoolItem = nullptr; + if( rInAttrs.GetItemState(nWhichId, true, &pPoolItem) == SfxItemState::SET ) + rCheckbox.set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + else + rCheckbox.set_state(TRISTATE_INDET); +} + +}//end anonymous namespace + +DataLabelResources::DataLabelResources(weld::Builder* pBuilder, weld::Window* pParent, const SfxItemSet& rInAttrs) + : m_pNumberFormatter(nullptr) + , m_bNumberFormatMixedState(true) + , m_bPercentFormatMixedState(true) + , m_nNumberFormatForValue(0) + , m_nNumberFormatForPercent(11) + , m_bSourceFormatMixedState(true) + , m_bPercentSourceMixedState(true) + , m_bSourceFormatForValue(true) + , m_bSourceFormatForPercent(true) + , m_pWindow(pParent) + , m_pPool(rInAttrs.GetPool()) + , m_xCBNumber(pBuilder->weld_check_button("CB_VALUE_AS_NUMBER")) + , m_xPB_NumberFormatForValue(pBuilder->weld_button("PB_NUMBERFORMAT")) + , m_xCBPercent(pBuilder->weld_check_button("CB_VALUE_AS_PERCENTAGE")) + , m_xPB_NumberFormatForPercent(pBuilder->weld_button("PB_PERCENT_NUMBERFORMAT")) + , m_xFT_NumberFormatForPercent(pBuilder->weld_label("STR_DLG_NUMBERFORMAT_FOR_PERCENTAGE_VALUE")) + , m_xCBCategory(pBuilder->weld_check_button("CB_CATEGORY")) + , m_xCBSymbol(pBuilder->weld_check_button("CB_SYMBOL")) + , m_xCBWrapText(pBuilder->weld_check_button("CB_WRAP_TEXT")) + , m_xSeparatorResources(pBuilder->weld_widget("boxSEPARATOR")) + , m_xLB_Separator(pBuilder->weld_combo_box("LB_TEXT_SEPARATOR")) + , m_xBxLabelPlacement(pBuilder->weld_widget("boxPLACEMENT")) + , m_xLB_LabelPlacement(pBuilder->weld_combo_box("LB_LABEL_PLACEMENT")) + , m_xBxOrientation(pBuilder->weld_widget("boxORIENTATION")) + , m_xFT_Dial(pBuilder->weld_label("CT_LABEL_DIAL")) + , m_xNF_Degrees(pBuilder->weld_metric_spin_button("NF_LABEL_DEGREES", FieldUnit::DEGREE)) + , m_xBxTextDirection(pBuilder->weld_widget("boxTXT_DIRECTION")) + , m_xLB_TextDirection(new TextDirectionListBox(pBuilder->weld_combo_box("LB_LABEL_TEXTDIR"))) + , m_xDC_Dial(new svx::DialControl) + , m_xDC_DialWin(new weld::CustomWeld(*pBuilder, "CT_DIAL", *m_xDC_Dial)) +{ + m_xDC_Dial->SetText(m_xFT_Dial->get_label()); + + //fill label placement list + std::map< sal_Int32, OUString > aPlacementToStringMap; + for( sal_Int32 nEnum=0; nEnum<m_xLB_LabelPlacement->get_count(); ++nEnum ) + aPlacementToStringMap[nEnum] = m_xLB_LabelPlacement->get_text(static_cast<sal_uInt16>(nEnum)); + + + std::vector< sal_Int32 > aAvailablePlacementList; + const SfxPoolItem *pPoolItem = nullptr; + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, true, &pPoolItem) == SfxItemState::SET ) + aAvailablePlacementList = static_cast<const SfxIntegerListItem*>(pPoolItem)->GetList(); + + m_xLB_LabelPlacement->clear(); + for( size_t nN=0; nN<aAvailablePlacementList.size(); ++nN ) + { + sal_uInt16 nListBoxPos = static_cast<sal_uInt16>( nN ); + sal_Int32 nPlacement = aAvailablePlacementList[nN]; + m_aPlacementToListBoxMap[nPlacement]=nListBoxPos; + m_aListBoxToPlacementMap[nListBoxPos]=nPlacement; + m_xLB_LabelPlacement->append_text( aPlacementToStringMap[nPlacement] ); + } + + //some click handler + m_xPB_NumberFormatForValue->connect_clicked( LINK( this, DataLabelResources, NumberFormatDialogHdl ) ); + m_xPB_NumberFormatForPercent->connect_clicked( LINK( this, DataLabelResources, NumberFormatDialogHdl ) ); + m_xCBNumber->connect_toggled( LINK( this, DataLabelResources, CheckHdl )); + m_xCBPercent->connect_toggled( LINK( this, DataLabelResources, CheckHdl )); + m_xCBCategory->connect_toggled( LINK( this, DataLabelResources, CheckHdl )); + m_xCBSymbol->connect_toggled( LINK( this, DataLabelResources, CheckHdl )); + m_xCBWrapText->connect_toggled( LINK( this, DataLabelResources, CheckHdl )); + + m_bNumberFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_SOURCE, m_nNumberFormatForValue, m_bSourceFormatForValue, m_bSourceFormatMixedState ); + m_bPercentFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SCHATTR_PERCENT_NUMBERFORMAT_VALUE, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, m_nNumberFormatForPercent, m_bSourceFormatForPercent , m_bPercentSourceMixedState); + + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_NO_PERCENTVALUE, true, &pPoolItem) == SfxItemState::SET ) + { + bool bForbidPercentValue = rInAttrs.Get( SCHATTR_DATADESCR_NO_PERCENTVALUE ).GetValue(); + if( bForbidPercentValue ) + m_xCBPercent->set_sensitive(false); + } + + m_xDC_Dial->SetLinkedField(m_xNF_Degrees.get()); +} + +DataLabelResources::~DataLabelResources() +{ +} + +void DataLabelResources::SetNumberFormatter( SvNumberFormatter* pFormatter ) +{ + m_pNumberFormatter = pFormatter; +} + +IMPL_LINK(DataLabelResources, NumberFormatDialogHdl, weld::Button&, rButton, void) +{ + if( !m_pPool || !m_pNumberFormatter ) + { + OSL_FAIL("Missing item pool or number formatter"); + return; + } + + if (&rButton == m_xPB_NumberFormatForValue.get() && !m_xCBNumber->get_active()) + m_xCBNumber->set_active(true); + else if (&rButton == m_xPB_NumberFormatForPercent.get() && !m_xCBPercent->get_active()) + m_xCBPercent->set_active(true); + + SfxItemSet aNumberSet = NumberFormatDialog::CreateEmptyItemSetForNumberFormatDialog( *m_pPool ); + aNumberSet.Put (SvxNumberInfoItem( m_pNumberFormatter, static_cast<sal_uInt16>(SID_ATTR_NUMBERFORMAT_INFO))); + + bool bPercent = (&rButton == m_xPB_NumberFormatForPercent.get()); + + sal_uLong& rnFormatKey = bPercent ? m_nNumberFormatForPercent : m_nNumberFormatForValue; + bool& rUseSourceFormat = bPercent ? m_bSourceFormatForPercent : m_bSourceFormatForValue; + bool& rbMixedState = bPercent ? m_bPercentFormatMixedState : m_bNumberFormatMixedState; + bool& rbSourceMixedState = bPercent ? m_bPercentSourceMixedState : m_bSourceFormatMixedState; + + if(!rbMixedState) + aNumberSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, rnFormatKey )); + aNumberSet.Put( SfxBoolItem( SID_ATTR_NUMBERFORMAT_SOURCE, rUseSourceFormat )); + + NumberFormatDialog aDlg(m_pWindow, aNumberSet); + if( bPercent ) + aDlg.set_title(m_xFT_NumberFormatForPercent->get_label()); + if (aDlg.run() != RET_OK) + return; + + const SfxItemSet* pResult = aDlg.GetOutputItemSet(); + if( pResult ) + { + bool bOldSource = rUseSourceFormat; + sal_uLong nOldFormat = rnFormatKey; + bool bOldMixedState = rbMixedState || rbSourceMixedState; + + rbMixedState = !lcl_ReadNumberFormatFromItemSet( *pResult, SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_SOURCE, rnFormatKey, rUseSourceFormat, rbSourceMixedState ); + + //todo this maybe can be removed when the numberformatter dialog does handle mixed state for source format correctly + if( bOldMixedState && bOldSource == rUseSourceFormat && nOldFormat == rnFormatKey ) + rbMixedState = rbSourceMixedState = true; + } +} + +IMPL_LINK_NOARG(DataLabelResources, CheckHdl, weld::ToggleButton&, void) +{ + EnableControls(); +} + +void DataLabelResources::EnableControls() +{ + m_xCBSymbol->set_sensitive( m_xCBNumber->get_active() || (m_xCBPercent->get_active() && m_xCBPercent->get_sensitive()) + || m_xCBCategory->get_active() ); + + m_xCBWrapText->set_sensitive( m_xCBNumber->get_active() || (m_xCBPercent->get_active() && m_xCBPercent->get_sensitive()) + || m_xCBCategory->get_active() ); + + // Enable or disable separator, placement and direction based on the check + // box states. Note that the check boxes are tri-state. + { + long nNumberOfCheckedLabelParts = 0; + if (m_xCBNumber->get_state() != TRISTATE_FALSE) + ++nNumberOfCheckedLabelParts; + if (m_xCBPercent->get_state() != TRISTATE_FALSE && m_xCBPercent->get_sensitive()) + ++nNumberOfCheckedLabelParts; + if (m_xCBCategory->get_state() != TRISTATE_FALSE) + ++nNumberOfCheckedLabelParts; + + m_xSeparatorResources->set_sensitive( nNumberOfCheckedLabelParts > 1 ); + + bool bEnableTextDir = nNumberOfCheckedLabelParts > 0; + m_xBxTextDirection->set_sensitive( bEnableTextDir ); + bool bEnablePlacement = nNumberOfCheckedLabelParts > 0 && m_xLB_LabelPlacement->get_count()>1; + m_xBxLabelPlacement->set_sensitive( bEnablePlacement ); + } + + m_xPB_NumberFormatForValue->set_sensitive( m_pNumberFormatter && m_xCBNumber->get_active() ); + m_xPB_NumberFormatForPercent->set_sensitive( m_pNumberFormatter && m_xCBPercent->get_active() && m_xCBPercent->get_sensitive() ); + + bool bEnableRotation = ( m_xCBNumber->get_active() || m_xCBPercent->get_active() || m_xCBCategory->get_active() ); + m_xBxOrientation->set_sensitive( bEnableRotation ); +} + +void DataLabelResources::FillItemSet( SfxItemSet* rOutAttrs ) const +{ + if( m_xCBNumber->get_active() ) + { + if( !m_bNumberFormatMixedState ) + rOutAttrs->Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, m_nNumberFormatForValue )); + if( !m_bSourceFormatMixedState ) + rOutAttrs->Put( SfxBoolItem( SID_ATTR_NUMBERFORMAT_SOURCE, m_bSourceFormatForValue )); + } + if( m_xCBPercent->get_active() ) + { + if( !m_bPercentFormatMixedState ) + rOutAttrs->Put( SfxUInt32Item( SCHATTR_PERCENT_NUMBERFORMAT_VALUE, m_nNumberFormatForPercent )); + if( !m_bPercentSourceMixedState ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, m_bSourceFormatForPercent )); + } + + if( m_xCBNumber->get_state()!= TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_NUMBER, m_xCBNumber->get_active() ) ); + if( m_xCBPercent->get_state()!= TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_PERCENTAGE, m_xCBPercent->get_active() ) ); + if( m_xCBCategory->get_state()!= TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_CATEGORY, m_xCBCategory->get_active() ) ); + if( m_xCBSymbol->get_state()!= TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_SYMBOL, m_xCBSymbol->get_active()) ); + if( m_xCBWrapText->get_state()!= TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_DATADESCR_WRAP_TEXT, m_xCBWrapText->get_active()) ); + + OUString aSep = our_aLBEntryMap[m_xLB_Separator->get_active()]; + rOutAttrs->Put( SfxStringItem( SCHATTR_DATADESCR_SEPARATOR, aSep) ); + + std::map< sal_uInt16, sal_Int32 >::const_iterator aIt( m_aListBoxToPlacementMap.find(m_xLB_LabelPlacement->get_active()) ); + if(aIt!=m_aListBoxToPlacementMap.end()) + { + sal_Int32 nValue = aIt->second; + rOutAttrs->Put( SfxInt32Item( SCHATTR_DATADESCR_PLACEMENT, nValue ) ); + } + + if (m_xLB_TextDirection->get_active() != -1) + rOutAttrs->Put( SvxFrameDirectionItem( m_xLB_TextDirection->get_active_id(), EE_PARA_WRITINGDIR ) ); + + if( m_xDC_Dial->IsVisible() ) + { + sal_Int32 nDegrees = m_xDC_Dial->GetRotation(); + rOutAttrs->Put(SfxInt32Item( SCHATTR_TEXT_DEGREES, nDegrees ) ); + } +} + +void DataLabelResources::Reset(const SfxItemSet& rInAttrs) +{ + // default state + m_xCBSymbol->set_sensitive( false ); + + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_NUMBER, *m_xCBNumber ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_PERCENTAGE, *m_xCBPercent ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_CATEGORY, *m_xCBCategory ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_SHOW_SYMBOL, *m_xCBSymbol ); + lcl_setBoolItemToCheckBox( rInAttrs, SCHATTR_DATADESCR_WRAP_TEXT, *m_xCBWrapText ); + + m_bNumberFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_SOURCE, m_nNumberFormatForValue, m_bSourceFormatForValue, m_bSourceFormatMixedState ); + m_bPercentFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SCHATTR_PERCENT_NUMBERFORMAT_VALUE, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, m_nNumberFormatForPercent, m_bSourceFormatForPercent , m_bPercentSourceMixedState); + + const SfxPoolItem *pPoolItem = nullptr; + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_SEPARATOR, true, &pPoolItem) == SfxItemState::SET ) + for(size_t i=0; i < SAL_N_ELEMENTS(our_aLBEntryMap); ++i ) + { + if( our_aLBEntryMap[i] == static_cast<const SfxStringItem*>(pPoolItem)->GetValue()) + m_xLB_Separator->set_active( i ); + } + else + m_xLB_Separator->set_active( 0 ); + + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_PLACEMENT, true, &pPoolItem) == SfxItemState::SET ) + { + sal_Int32 nPlacement = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + std::map< sal_Int32, sal_uInt16 >::const_iterator aIt( m_aPlacementToListBoxMap.find(nPlacement) ); + if(aIt!=m_aPlacementToListBoxMap.end()) + { + sal_uInt16 nPos = aIt->second; + m_xLB_LabelPlacement->set_active( nPos ); + } + else + m_xLB_LabelPlacement->set_active(-1); + } + else + m_xLB_LabelPlacement->set_active(-1); + + if( rInAttrs.GetItemState(EE_PARA_WRITINGDIR, true, &pPoolItem ) == SfxItemState::SET ) + m_xLB_TextDirection->set_active_id( static_cast<const SvxFrameDirectionItem*>(pPoolItem)->GetValue() ); + + if( rInAttrs.GetItemState( SCHATTR_TEXT_DEGREES, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nDegrees = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xDC_Dial->SetRotation( nDegrees ); + } + else + m_xDC_Dial->SetRotation( 0 ); + + EnableControls(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_DataLabel.hxx b/chart2/source/controller/dialogs/res_DataLabel.hxx new file mode 100644 index 000000000..d21856cb4 --- /dev/null +++ b/chart2/source/controller/dialogs/res_DataLabel.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_DATALABEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_DATALABEL_HXX + +#include <svl/itemset.hxx> +#include <svx/dialcontrol.hxx> + +#include <map> + +class SvNumberFormatter; +namespace chart { class TextDirectionListBox; } + +namespace chart +{ + +class DataLabelResources final +{ +public: + DataLabelResources(weld::Builder* pBuilder, weld::Window* pParent, const SfxItemSet& rInAttrs); + ~DataLabelResources(); + + void FillItemSet(SfxItemSet* rOutAttrs) const; + void Reset(const SfxItemSet& rInAttrs); + + void SetNumberFormatter( SvNumberFormatter* pFormatter ); + +private: + std::map< sal_Int32, sal_uInt16 > m_aPlacementToListBoxMap; + std::map< sal_uInt16, sal_Int32 > m_aListBoxToPlacementMap; + + SvNumberFormatter* m_pNumberFormatter; + bool m_bNumberFormatMixedState; + bool m_bPercentFormatMixedState; + sal_uLong m_nNumberFormatForValue; + sal_uLong m_nNumberFormatForPercent; + + bool m_bSourceFormatMixedState; + bool m_bPercentSourceMixedState; + bool m_bSourceFormatForValue; + bool m_bSourceFormatForPercent; + + weld::Window* m_pWindow; + SfxItemPool* m_pPool; + + std::unique_ptr<weld::CheckButton> m_xCBNumber; + std::unique_ptr<weld::Button> m_xPB_NumberFormatForValue; + std::unique_ptr<weld::CheckButton> m_xCBPercent; + std::unique_ptr<weld::Button> m_xPB_NumberFormatForPercent; + std::unique_ptr<weld::Label> m_xFT_NumberFormatForPercent; + std::unique_ptr<weld::CheckButton> m_xCBCategory; + std::unique_ptr<weld::CheckButton> m_xCBSymbol; + std::unique_ptr<weld::CheckButton> m_xCBWrapText; + + std::unique_ptr<weld::Widget> m_xSeparatorResources; + std::unique_ptr<weld::ComboBox> m_xLB_Separator; + + std::unique_ptr<weld::Widget> m_xBxLabelPlacement; + std::unique_ptr<weld::ComboBox> m_xLB_LabelPlacement; + + std::unique_ptr<weld::Widget> m_xBxOrientation; + std::unique_ptr<weld::Label> m_xFT_Dial; + std::unique_ptr<weld::MetricSpinButton> m_xNF_Degrees; + + std::unique_ptr<weld::Widget> m_xBxTextDirection; + + std::unique_ptr<TextDirectionListBox> m_xLB_TextDirection; + std::unique_ptr<svx::DialControl> m_xDC_Dial; + std::unique_ptr<weld::CustomWeld> m_xDC_DialWin; + + DECL_LINK(NumberFormatDialogHdl, weld::Button&, void ); + DECL_LINK(CheckHdl, weld::ToggleButton&, void ); + void EnableControls(); +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_ErrorBar.cxx b/chart2/source/controller/dialogs/res_ErrorBar.cxx new file mode 100644 index 000000000..aaa1c6eed --- /dev/null +++ b/chart2/source/controller/dialogs/res_ErrorBar.cxx @@ -0,0 +1,718 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <res_ErrorBar.hxx> +#include <bitmaps.hlst> +#include <RangeSelectionHelper.hxx> +#include <helpids.h> +#include <chartview/ChartSfxItemIds.hxx> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <vcl/weld.hxx> + +#include <rtl/math.hxx> +#include <tools/diagnose_ex.h> +#include <osl/diagnose.h> +#include <svl/stritem.hxx> + +#define CHART_LB_FUNCTION_STD_ERROR 0 +#define CHART_LB_FUNCTION_STD_DEV 1 +#define CHART_LB_FUNCTION_VARIANCE 2 +#define CHART_LB_FUNCTION_ERROR_MARGIN 3 + +using namespace ::com::sun::star; + +namespace +{ +void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pController) +{ + weld::Window* pWeldDialog = pController->getDialog(); + pWeldDialog->set_modal(!bEnable); + pWeldDialog->set_visible(!bEnable); +} + +sal_uInt16 lcl_getLbEntryPosByErrorKind( SvxChartKindError eErrorKind ) +{ + sal_uInt16 nResult = 0; + switch( eErrorKind ) + { + // for these cases select the default in the list box + case SvxChartKindError::NONE: + case SvxChartKindError::Percent: + case SvxChartKindError::Const: + case SvxChartKindError::Range: + nResult = CHART_LB_FUNCTION_STD_DEV; + break; + case SvxChartKindError::Variant: + nResult = CHART_LB_FUNCTION_VARIANCE; + break; + case SvxChartKindError::Sigma: + nResult = CHART_LB_FUNCTION_STD_DEV; + break; + case SvxChartKindError::BigError: + nResult = CHART_LB_FUNCTION_ERROR_MARGIN; + break; + case SvxChartKindError::StdError: + nResult = CHART_LB_FUNCTION_STD_ERROR; + break; + } + return nResult; +} +} // anonymous namespace + +namespace chart +{ + +ErrorBarResources::ErrorBarResources(weld::Builder* pParent, weld::DialogController* pController, + const SfxItemSet& rInAttrs, bool bNoneAvailable, + tErrorBarType eType /* = ERROR_BAR_Y */ ) + : m_eErrorKind( SvxChartKindError::NONE ) + , m_eIndicate( SvxChartIndicate::Both ) + , m_bErrorKindUnique( true ) + , m_bIndicatorUnique( true ) + , m_bRangePosUnique( true ) + , m_bRangeNegUnique( true ) + , m_eErrorBarType( eType ) + , m_nConstDecimalDigits( 1 ) + , m_nConstSpinSize( 1 ) + , m_fPlusValue(0.0) + , m_fMinusValue(0.0) + , m_pController(pController) + , m_pCurrentRangeChoosingField( nullptr ) + , m_bHasInternalDataProvider( true ) + , m_bEnableDataTableDialog( true ) + , m_xRbNone(pParent->weld_radio_button("RB_NONE")) + , m_xRbConst(pParent->weld_radio_button("RB_CONST")) + , m_xRbPercent(pParent->weld_radio_button("RB_PERCENT")) + , m_xRbFunction(pParent->weld_radio_button("RB_FUNCTION")) + , m_xRbRange(pParent->weld_radio_button("RB_RANGE")) + , m_xLbFunction(pParent->weld_combo_box("LB_FUNCTION")) + , m_xFlParameters(pParent->weld_frame("framePARAMETERS")) + , m_xBxPositive(pParent->weld_widget("boxPOSITIVE")) + , m_xMfPositive(pParent->weld_metric_spin_button("MF_POSITIVE", FieldUnit::NONE)) + , m_xEdRangePositive(pParent->weld_entry("ED_RANGE_POSITIVE")) + , m_xIbRangePositive(pParent->weld_button("IB_RANGE_POSITIVE")) + , m_xBxNegative(pParent->weld_widget("boxNEGATIVE")) + , m_xMfNegative(pParent->weld_metric_spin_button("MF_NEGATIVE", FieldUnit::NONE)) + , m_xEdRangeNegative(pParent->weld_entry("ED_RANGE_NEGATIVE")) + , m_xIbRangeNegative(pParent->weld_button("IB_RANGE_NEGATIVE")) + , m_xCbSyncPosNeg(pParent->weld_check_button("CB_SYN_POS_NEG")) + , m_xRbBoth(pParent->weld_radio_button("RB_BOTH")) + , m_xRbPositive(pParent->weld_radio_button("RB_POSITIVE")) + , m_xRbNegative(pParent->weld_radio_button("RB_NEGATIVE")) + , m_xFiBoth(pParent->weld_image("FI_BOTH")) + , m_xFiPositive(pParent->weld_image("FI_POSITIVE")) + , m_xFiNegative(pParent->weld_image("FI_NEGATIVE")) + , m_xUIStringPos(pParent->weld_label("STR_DATA_SELECT_RANGE_FOR_POSITIVE_ERRORBARS")) + , m_xUIStringNeg(pParent->weld_label("STR_DATA_SELECT_RANGE_FOR_NEGATIVE_ERRORBARS")) + , m_xUIStringRbRange(pParent->weld_label("STR_CONTROLTEXT_ERROR_BARS_FROM_DATA")) +{ + if( bNoneAvailable ) + m_xRbNone->connect_toggled(LINK(this, ErrorBarResources, CategoryChosen)); + else + m_xRbNone->hide(); + + m_xRbConst->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen )); + m_xRbPercent->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen )); + m_xRbFunction->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen )); + m_xRbRange->connect_toggled( LINK( this, ErrorBarResources, CategoryChosen )); + m_xLbFunction->connect_changed( LINK( this, ErrorBarResources, CategoryChosen2 )); + + m_xCbSyncPosNeg->set_active( false ); + m_xCbSyncPosNeg->connect_toggled( LINK( this, ErrorBarResources, SynchronizePosAndNeg )); + + m_xMfPositive->connect_value_changed( LINK( this, ErrorBarResources, PosValueChanged )); + m_xEdRangePositive->connect_changed( LINK( this, ErrorBarResources, RangeChanged )); + m_xEdRangeNegative->connect_changed( LINK( this, ErrorBarResources, RangeChanged )); + + m_xRbPositive->connect_toggled( LINK( this, ErrorBarResources, IndicatorChanged )); + m_xRbNegative->connect_toggled( LINK( this, ErrorBarResources, IndicatorChanged )); + m_xRbBoth->connect_toggled( LINK( this, ErrorBarResources, IndicatorChanged )); + + m_xIbRangePositive->connect_clicked( LINK( this, ErrorBarResources, ChooseRange )); + m_xIbRangeNegative->connect_clicked( LINK( this, ErrorBarResources, ChooseRange )); + + FillValueSets(); + Reset( rInAttrs ); +} + +ErrorBarResources::~ErrorBarResources() +{ +} + +void ErrorBarResources::SetErrorBarType( tErrorBarType eNewType ) +{ + if( m_eErrorBarType != eNewType ) + { + m_eErrorBarType = eNewType; + FillValueSets(); + } +} + +void ErrorBarResources::SetChartDocumentForRangeChoosing( + const uno::Reference< chart2::XChartDocument > & xChartDocument ) +{ + if( xChartDocument.is()) + { + m_bHasInternalDataProvider = xChartDocument->hasInternalDataProvider(); + uno::Reference< beans::XPropertySet > xProps( xChartDocument, uno::UNO_QUERY ); + if ( xProps.is() ) + { + try + { + xProps->getPropertyValue("EnableDataTableDialog") >>= m_bEnableDataTableDialog; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + } + m_apRangeSelectionHelper.reset( new RangeSelectionHelper( xChartDocument )); + + // has internal data provider => rename "cell range" to "from data" + OSL_ASSERT(m_apRangeSelectionHelper); + if( m_bHasInternalDataProvider ) + { + m_xRbRange->set_label(m_xUIStringRbRange->get_label()); + m_xRbRange->set_help_id(HID_SCH_ERROR_BARS_FROM_DATA); + } + + if( m_xRbRange->get_active()) + { + isRangeFieldContentValid( *m_xEdRangePositive ); + isRangeFieldContentValid( *m_xEdRangeNegative ); + } +} + +void ErrorBarResources::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth ) +{ + if( fMinorStepWidth < 0 ) + fMinorStepWidth = -fMinorStepWidth; + + sal_Int32 nExponent = static_cast< sal_Int32 >( ::rtl::math::approxFloor( log10( fMinorStepWidth ))); + if( nExponent <= 0 ) + { + // one digit precision more + m_nConstDecimalDigits = static_cast< sal_uInt16 >( (-nExponent) + 1 ); + m_nConstSpinSize = 10; + } + else + { + m_nConstDecimalDigits = 0; + m_nConstSpinSize = static_cast< sal_Int64 >( pow( 10.0, static_cast<int>(nExponent) )); + } +} + +void ErrorBarResources::UpdateControlStates() +{ + // function + bool bIsFunction = m_xRbFunction->get_active(); + m_xLbFunction->set_sensitive( bIsFunction ); + + // range buttons + m_xRbRange->set_sensitive( !m_bHasInternalDataProvider || m_bEnableDataTableDialog ); + bool bShowRange = m_xRbRange->get_active(); + bool bCanChooseRange = + ( bShowRange && + m_apRangeSelectionHelper && + m_apRangeSelectionHelper->hasRangeSelection()); + + m_xMfPositive->set_visible( ! bShowRange ); + m_xMfNegative->set_visible( ! bShowRange ); + + // use range but without range chooser => hide controls + m_xEdRangePositive->set_visible( bShowRange && ! m_bHasInternalDataProvider ); + m_xIbRangePositive->set_visible( bCanChooseRange ); + m_xEdRangeNegative->set_visible( bShowRange && ! m_bHasInternalDataProvider ); + m_xIbRangeNegative->set_visible( bCanChooseRange ); + + bool bShowPosNegAndSync = ! (bShowRange && m_bHasInternalDataProvider); + m_xFlParameters->set_visible( bShowPosNegAndSync ); + + // unit for metric fields + bool bIsErrorMargin( + ( m_xRbFunction->get_active()) && + ( m_xLbFunction->get_active() == CHART_LB_FUNCTION_ERROR_MARGIN )); + bool bIsPercentage( m_xRbPercent->get_active() || bIsErrorMargin ); + FieldUnit eFieldUnit = FieldUnit::NONE; + + if( bIsPercentage ) + { + eFieldUnit = FieldUnit::PERCENT; + m_xMfPositive->set_digits( 1 ); + m_xMfPositive->set_increments(10, 100, FieldUnit::NONE); + m_xMfNegative->set_digits( 1 ); + m_xMfNegative->set_increments(10, 100, FieldUnit::NONE); + } + else + { + m_xMfPositive->set_digits( m_nConstDecimalDigits ); + m_xMfPositive->set_increments(m_nConstSpinSize, m_nConstSpinSize * 10, FieldUnit::NONE); + m_xMfNegative->set_digits( m_nConstDecimalDigits ); + m_xMfNegative->set_increments(m_nConstSpinSize, m_nConstSpinSize * 10, FieldUnit::NONE); + } + + sal_Int32 nPlusValue = static_cast< sal_Int32 >( m_fPlusValue * pow(10.0,m_xMfPositive->get_digits()) ); + sal_Int32 nMinusValue = static_cast< sal_Int32 >( m_fMinusValue * pow(10.0,m_xMfNegative->get_digits()) ); + + m_xMfPositive->set_value(nPlusValue, FieldUnit::NONE); + m_xMfNegative->set_value(nMinusValue, FieldUnit::NONE); + + m_xMfPositive->set_unit(eFieldUnit); + m_xMfNegative->set_unit(eFieldUnit); + + // positive and negative value fields + bool bPosEnabled = ( m_xRbPositive->get_active() || m_xRbBoth->get_active()); + bool bNegEnabled = ( m_xRbNegative->get_active() || m_xRbBoth->get_active()); + if( !( bPosEnabled || bNegEnabled )) + { + // all three controls are not checked -> ambiguous state + bPosEnabled = true; + bNegEnabled = true; + } + + // functions with only one parameter + bool bOneParameterCategory = + bIsErrorMargin || m_xRbPercent->get_active(); + if( bOneParameterCategory ) + { + m_xCbSyncPosNeg->set_active(true); + } + + if( m_xCbSyncPosNeg->get_active()) + { + bPosEnabled = true; + bNegEnabled = false; + } + + // all functions except error margin take no arguments + if( m_xRbFunction->get_active() && ( m_xLbFunction->get_active() != CHART_LB_FUNCTION_ERROR_MARGIN )) + { + bPosEnabled = false; + bNegEnabled = false; + } + + // enable/disable pos/neg fields + m_xBxPositive->set_sensitive( bPosEnabled ); + m_xBxNegative->set_sensitive( bNegEnabled ); + if( bShowRange ) + { + m_xEdRangePositive->set_sensitive( bPosEnabled ); + m_xIbRangePositive->set_sensitive( bPosEnabled ); + m_xEdRangeNegative->set_sensitive( bNegEnabled ); + m_xIbRangeNegative->set_sensitive( bNegEnabled ); + } + else + { + m_xMfPositive->set_sensitive( bPosEnabled ); + m_xMfNegative->set_sensitive( bNegEnabled ); + } + + m_xCbSyncPosNeg->set_sensitive( !bOneParameterCategory && ( bPosEnabled || bNegEnabled )); + + // mark invalid entries in the range fields + if( bShowRange && ! m_bHasInternalDataProvider ) + { + isRangeFieldContentValid( *m_xEdRangePositive ); + isRangeFieldContentValid( *m_xEdRangeNegative ); + } +} + +IMPL_LINK_NOARG( ErrorBarResources, CategoryChosen2, weld::ComboBox&, void ) +{ + CategoryChosen(*m_xRbConst); +} + +IMPL_LINK_NOARG( ErrorBarResources, CategoryChosen, weld::ToggleButton&, void ) +{ + m_bErrorKindUnique = true; + SvxChartKindError eOldError = m_eErrorKind; + + if( m_xRbNone->get_active()) + m_eErrorKind = SvxChartKindError::NONE; + else if( m_xRbConst->get_active()) + m_eErrorKind = SvxChartKindError::Const; + else if( m_xRbPercent->get_active()) + m_eErrorKind = SvxChartKindError::Percent; + else if( m_xRbRange->get_active()) + m_eErrorKind = SvxChartKindError::Range; + else if( m_xRbFunction->get_active()) + { + switch( m_xLbFunction->get_active()) + { + case CHART_LB_FUNCTION_STD_ERROR: + m_eErrorKind = SvxChartKindError::StdError; break; + case CHART_LB_FUNCTION_STD_DEV: + m_eErrorKind = SvxChartKindError::Sigma; break; + case CHART_LB_FUNCTION_VARIANCE: + m_eErrorKind = SvxChartKindError::Variant; break; + case CHART_LB_FUNCTION_ERROR_MARGIN: + m_eErrorKind = SvxChartKindError::BigError; break; + default: + m_bErrorKindUnique = false; + } + } + else + { + OSL_FAIL( "Unknown category chosen" ); + m_bErrorKindUnique = false; + } + + // changed to range + if( m_eErrorKind == SvxChartKindError::Range && + eOldError != SvxChartKindError::Range ) + { + m_xCbSyncPosNeg->set_active( + (!m_xEdRangePositive->get_text().isEmpty()) && + m_xEdRangePositive->get_text() == m_xEdRangeNegative->get_text()); + } + // changed from range + else if( m_eErrorKind != SvxChartKindError::Range && + eOldError == SvxChartKindError::Range ) + { + m_xCbSyncPosNeg->set_active( m_xMfPositive->get_value(FieldUnit::NONE) == m_xMfNegative->get_value(FieldUnit::NONE)); + } + + UpdateControlStates(); +} + +IMPL_LINK_NOARG(ErrorBarResources, SynchronizePosAndNeg, weld::ToggleButton&, void) +{ + UpdateControlStates(); + PosValueChanged( *m_xMfPositive ); +} + +IMPL_LINK_NOARG(ErrorBarResources, PosValueChanged, weld::MetricSpinButton&, void) +{ + if( m_xCbSyncPosNeg->get_active()) + { + if( m_xRbRange->get_active()) + { + m_xEdRangeNegative->set_text( m_xEdRangePositive->get_text()); + m_bRangeNegUnique = m_bRangePosUnique; + } + else + m_xMfNegative->set_value(m_xMfPositive->get_value(FieldUnit::NONE), FieldUnit::NONE); + } +} + +IMPL_LINK_NOARG(ErrorBarResources, IndicatorChanged, weld::ToggleButton&, void) +{ + m_bIndicatorUnique = true; + if( m_xRbBoth->get_active()) + m_eIndicate = SvxChartIndicate::Both; + else if( m_xRbPositive->get_active()) + m_eIndicate = SvxChartIndicate::Up; + else if( m_xRbNegative->get_active()) + m_eIndicate = SvxChartIndicate::Down; + else + m_bIndicatorUnique = false; + + UpdateControlStates(); +} + +IMPL_LINK(ErrorBarResources, ChooseRange, weld::Button&, rButton, void) +{ + OSL_ASSERT(m_apRangeSelectionHelper); + if (!m_apRangeSelectionHelper) + return; + OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr ); + + OUString aUIString; + + if (&rButton == m_xIbRangePositive.get()) + { + m_pCurrentRangeChoosingField = m_xEdRangePositive.get(); + aUIString = m_xUIStringPos->get_label(); + } + else + { + m_pCurrentRangeChoosingField = m_xEdRangeNegative.get(); + aUIString = m_xUIStringNeg->get_label(); + } + + lcl_enableRangeChoosing(true, m_pController); + m_apRangeSelectionHelper->chooseRange( + m_pCurrentRangeChoosingField->get_text(), + aUIString, *this ); +} + +IMPL_LINK( ErrorBarResources, RangeChanged, weld::Entry&, rEdit, void ) +{ + if( &rEdit == m_xEdRangePositive.get() ) + { + m_bRangePosUnique = true; + PosValueChanged( *m_xMfPositive ); + } + else + { + m_bRangeNegUnique = true; + } + + isRangeFieldContentValid( rEdit ); +} + +void ErrorBarResources::Reset(const SfxItemSet& rInAttrs) +{ + const SfxPoolItem *pPoolItem = nullptr; + + // category + m_eErrorKind = SvxChartKindError::NONE; + SfxItemState aState = rInAttrs.GetItemState( SCHATTR_STAT_KIND_ERROR, true, &pPoolItem ); + m_bErrorKindUnique = ( aState != SfxItemState::DONTCARE ); + + if( aState == SfxItemState::SET ) + m_eErrorKind = static_cast<const SvxChartKindErrorItem*>(pPoolItem)->GetValue(); + + m_xLbFunction->set_active( lcl_getLbEntryPosByErrorKind( m_eErrorKind )); + + if( m_bErrorKindUnique ) + { + switch( m_eErrorKind ) + { + case SvxChartKindError::NONE: + m_xRbNone->set_active(true); + break; + case SvxChartKindError::Percent: + m_xRbPercent->set_active(true); + break; + case SvxChartKindError::Const: + m_xRbConst->set_active(true); + break; + case SvxChartKindError::StdError: + case SvxChartKindError::Variant: + case SvxChartKindError::Sigma: + case SvxChartKindError::BigError: + m_xRbFunction->set_active(true); + break; + case SvxChartKindError::Range: + m_xRbRange->set_active(true); + break; + } + } + else + { + m_xRbNone->set_active( false ); + m_xRbConst->set_active( false ); + m_xRbPercent->set_active( false ); + m_xRbFunction->set_active( false ); + } + + // parameters + aState = rInAttrs.GetItemState( SCHATTR_STAT_CONSTPLUS, true, &pPoolItem ); + if( aState == SfxItemState::SET ) + { + m_fPlusValue = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue(); + } + + aState = rInAttrs.GetItemState( SCHATTR_STAT_CONSTMINUS, true, &pPoolItem ); + if( aState == SfxItemState::SET ) + { + m_fMinusValue = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue(); + + if( m_eErrorKind != SvxChartKindError::Range && + m_fPlusValue == m_fMinusValue ) + m_xCbSyncPosNeg->set_active(true); + } + + // indicator + aState = rInAttrs.GetItemState( SCHATTR_STAT_INDICATE, true, &pPoolItem ); + m_bIndicatorUnique = ( aState != SfxItemState::DONTCARE ); + if( aState == SfxItemState::SET) + m_eIndicate = static_cast<const SvxChartIndicateItem *>(pPoolItem)->GetValue(); + + if( m_bIndicatorUnique ) + { + switch( m_eIndicate ) + { + case SvxChartIndicate::NONE : + // no longer used, use both as default + m_eIndicate = SvxChartIndicate::Both; + [[fallthrough]]; // to BOTH + case SvxChartIndicate::Both : + m_xRbBoth->set_active(true); break; + case SvxChartIndicate::Up : + m_xRbPositive->set_active(true); break; + case SvxChartIndicate::Down : + m_xRbNegative->set_active(true); break; + } + } + else + { + m_xRbBoth->set_active( false ); + m_xRbPositive->set_active( false ); + m_xRbNegative->set_active( false ); + } + + // ranges + aState = rInAttrs.GetItemState( SCHATTR_STAT_RANGE_POS, true, &pPoolItem ); + m_bRangePosUnique = ( aState != SfxItemState::DONTCARE ); + if( aState == SfxItemState::SET ) + { + OUString sRangePositive = static_cast< const SfxStringItem * >( pPoolItem )->GetValue(); + m_xEdRangePositive->set_text( sRangePositive ); + } + + aState = rInAttrs.GetItemState( SCHATTR_STAT_RANGE_NEG, true, &pPoolItem ); + m_bRangeNegUnique = ( aState != SfxItemState::DONTCARE ); + if( aState == SfxItemState::SET ) + { + OUString sRangeNegative = static_cast< const SfxStringItem * >( pPoolItem )->GetValue(); + m_xEdRangeNegative->set_text( sRangeNegative ); + if( m_eErrorKind == SvxChartKindError::Range && + !sRangeNegative.isEmpty() && + sRangeNegative == m_xEdRangePositive->get_text() ) + m_xCbSyncPosNeg->set_active(true); + } + + UpdateControlStates(); +} + +void ErrorBarResources::FillItemSet(SfxItemSet& rOutAttrs) const +{ + if( m_bErrorKindUnique ) + rOutAttrs.Put( SvxChartKindErrorItem( m_eErrorKind, SCHATTR_STAT_KIND_ERROR )); + if( m_bIndicatorUnique ) + rOutAttrs.Put( SvxChartIndicateItem( m_eIndicate, SCHATTR_STAT_INDICATE )); + + if( m_bErrorKindUnique ) + { + if( m_eErrorKind == SvxChartKindError::Range ) + { + OUString aPosRange; + OUString aNegRange; + if( m_bHasInternalDataProvider ) + { + // the strings aPosRange/aNegRange have to be set to a non-empty + // arbitrary string to generate error-bar sequences + aPosRange = "x"; + aNegRange = aPosRange; + } + else + { + aPosRange = m_xEdRangePositive->get_text(); + if( m_xCbSyncPosNeg->get_active()) + aNegRange = aPosRange; + else + aNegRange = m_xEdRangeNegative->get_text(); + } + + if( m_bRangePosUnique ) + rOutAttrs.Put( SfxStringItem( SCHATTR_STAT_RANGE_POS, aPosRange )); + if( m_bRangeNegUnique ) + rOutAttrs.Put( SfxStringItem( SCHATTR_STAT_RANGE_NEG, aNegRange )); + } + else if( m_eErrorKind == SvxChartKindError::Const || + m_eErrorKind == SvxChartKindError::Percent || + m_eErrorKind == SvxChartKindError::BigError ) + { + double fPosValue = static_cast< double >( m_xMfPositive->get_value(FieldUnit::NONE)) / + pow( 10.0, m_xMfPositive->get_digits()); + double fNegValue = 0.0; + + if( m_xCbSyncPosNeg->get_active()) + fNegValue = fPosValue; + else + fNegValue = static_cast< double >( m_xMfNegative->get_value(FieldUnit::NONE)) / + pow( 10.0, m_xMfNegative->get_digits()); + + rOutAttrs.Put( SvxDoubleItem( fPosValue, SCHATTR_STAT_CONSTPLUS )); + rOutAttrs.Put( SvxDoubleItem( fNegValue, SCHATTR_STAT_CONSTMINUS )); + } + } + + rOutAttrs.Put( SfxBoolItem( SCHATTR_STAT_ERRORBAR_TYPE , m_eErrorBarType == ERROR_BAR_Y )); +} + +void ErrorBarResources::FillValueSets() +{ + if( m_eErrorBarType == ERROR_BAR_Y ) + { + m_xFiNegative->set_from_icon_name(BMP_INDICATE_DOWN); + m_xFiPositive->set_from_icon_name(BMP_INDICATE_UP); + m_xFiBoth->set_from_icon_name(BMP_INDICATE_BOTH_VERTI); + } + else if( m_eErrorBarType == ERROR_BAR_X ) + { + m_xFiNegative->set_from_icon_name(BMP_INDICATE_LEFT); + m_xFiPositive->set_from_icon_name(BMP_INDICATE_RIGHT); + m_xFiBoth->set_from_icon_name(BMP_INDICATE_BOTH_HORI); + } +} + +void ErrorBarResources::listeningFinished( + const OUString & rNewRange ) +{ + OSL_ASSERT(m_apRangeSelectionHelper); + if (!m_apRangeSelectionHelper) + return; + + // rNewRange becomes invalid after removing the listener + OUString aRange( rNewRange ); + + // stop listening + m_apRangeSelectionHelper->stopRangeListening(); + + // change edit field +// if( m_pParentWindow ) +// { +// m_pParentWindow->ToTop(); +// m_pParentWindow->grab_focus(); +// } + + if( m_pCurrentRangeChoosingField ) + { + m_pCurrentRangeChoosingField->set_text( aRange ); + m_pCurrentRangeChoosingField->grab_focus(); + PosValueChanged( *m_xMfPositive ); + } + + m_pCurrentRangeChoosingField = nullptr; + + UpdateControlStates(); + lcl_enableRangeChoosing(false, m_pController); +} + +void ErrorBarResources::disposingRangeSelection() +{ + OSL_ASSERT(m_apRangeSelectionHelper); + if (m_apRangeSelectionHelper) + m_apRangeSelectionHelper->stopRangeListening( false ); +} + +void ErrorBarResources::isRangeFieldContentValid(weld::Entry& rEdit) +{ + OUString aRange( rEdit.get_text()); + bool bIsValid = ( aRange.isEmpty() ) || + ( m_apRangeSelectionHelper && + m_apRangeSelectionHelper->verifyCellRange( aRange )); + + if( bIsValid || !rEdit.get_sensitive()) + { + rEdit.set_message_type(weld::EntryMessageType::Normal); + } + else + { + rEdit.set_message_type(weld::EntryMessageType::Error); + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_LegendPosition.cxx b/chart2/source/controller/dialogs/res_LegendPosition.cxx new file mode 100644 index 000000000..50ac0602b --- /dev/null +++ b/chart2/source/controller/dialogs/res_LegendPosition.cxx @@ -0,0 +1,237 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <res_LegendPosition.hxx> +#include <ChartModelHelper.hxx> +#include <LegendHelper.hxx> +#include <ChartModel.hxx> + +#include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart/ChartLegendExpansion.hpp> + +//itemset stuff +#include <chartview/ChartSfxItemIds.hxx> +#include <svl/intitem.hxx> +#include <svl/eitem.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/weld.hxx> + +namespace chart +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +LegendPositionResources::LegendPositionResources(weld::Builder& rBuilder) + : m_xRbtLeft(rBuilder.weld_radio_button("left")) + , m_xRbtRight(rBuilder.weld_radio_button("right")) + , m_xRbtTop(rBuilder.weld_radio_button("top")) + , m_xRbtBottom(rBuilder.weld_radio_button("bottom")) +{ + impl_setRadioButtonToggleHdl(); +} + +LegendPositionResources::LegendPositionResources(weld::Builder& rBuilder, + const uno::Reference< uno::XComponentContext >& xCC) + : m_xCC(xCC) + , m_xCbxShow(rBuilder.weld_check_button("show")) + , m_xRbtLeft(rBuilder.weld_radio_button("left")) + , m_xRbtRight(rBuilder.weld_radio_button("right")) + , m_xRbtTop(rBuilder.weld_radio_button("top")) + , m_xRbtBottom(rBuilder.weld_radio_button("bottom")) +{ + m_xCbxShow->connect_toggled( LINK( this, LegendPositionResources, PositionEnableHdl ) ); + impl_setRadioButtonToggleHdl(); +} + +void LegendPositionResources::impl_setRadioButtonToggleHdl() +{ + m_xRbtLeft->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) ); + m_xRbtTop->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) ); + m_xRbtRight->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) ); + m_xRbtBottom->connect_toggled( LINK( this, LegendPositionResources, PositionChangeHdl ) ); +} + +LegendPositionResources::~LegendPositionResources() +{ +} + +void LegendPositionResources::writeToResources( const uno::Reference< frame::XModel >& xChartModel ) +{ + try + { + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xChartModel ); + uno::Reference< beans::XPropertySet > xProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xProp.is() ) + { + //show + bool bShowLegend = false; + xProp->getPropertyValue( "Show" ) >>= bShowLegend; + if (m_xCbxShow) + m_xCbxShow->set_active( bShowLegend ); + PositionEnableHdl(*m_xCbxShow); + + //position + chart2::LegendPosition ePos; + xProp->getPropertyValue( "AnchorPosition" ) >>= ePos; + switch( ePos ) + { + case chart2::LegendPosition_LINE_START: + m_xRbtLeft->set_active(true); + break; + case chart2::LegendPosition_PAGE_START: + m_xRbtTop->set_active(true); + break; + case chart2::LegendPosition_PAGE_END: + m_xRbtBottom->set_active(true); + break; + case chart2::LegendPosition_LINE_END: + default: + m_xRbtRight->set_active(true); + break; + } + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +void LegendPositionResources::writeToModel( const css::uno::Reference< frame::XModel >& xChartModel ) const +{ + try + { + bool bShowLegend = m_xCbxShow && m_xCbxShow->get_active(); + ChartModel& rModel = dynamic_cast<ChartModel&>(*xChartModel); + uno::Reference< beans::XPropertySet > xProp(LegendHelper::getLegend(rModel, m_xCC, bShowLegend), uno::UNO_QUERY); + if( xProp.is() ) + { + //show + xProp->setPropertyValue( "Show" , uno::Any( bShowLegend )); + + //position + chart2::LegendPosition eNewPos; + css::chart::ChartLegendExpansion eExp = css::chart::ChartLegendExpansion_HIGH; + + if( m_xRbtLeft->get_active() ) + eNewPos = chart2::LegendPosition_LINE_START; + else if( m_xRbtRight->get_active() ) + { + eNewPos = chart2::LegendPosition_LINE_END; + } + else if( m_xRbtTop->get_active() ) + { + eNewPos = chart2::LegendPosition_PAGE_START; + eExp = css::chart::ChartLegendExpansion_WIDE; + } + else if( m_xRbtBottom->get_active() ) + { + eNewPos = chart2::LegendPosition_PAGE_END; + eExp = css::chart::ChartLegendExpansion_WIDE; + } + + xProp->setPropertyValue( "AnchorPosition" , uno::Any( eNewPos )); + xProp->setPropertyValue( "Expansion" , uno::Any( eExp )); + xProp->setPropertyValue( "RelativePosition" , uno::Any()); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2" ); + } +} + +IMPL_LINK_NOARG(LegendPositionResources, PositionEnableHdl, weld::ToggleButton&, void) +{ + bool bEnable = !m_xCbxShow || m_xCbxShow->get_active(); + + m_xRbtLeft->set_sensitive( bEnable ); + m_xRbtTop->set_sensitive( bEnable ); + m_xRbtRight->set_sensitive( bEnable ); + m_xRbtBottom->set_sensitive( bEnable ); + + m_aChangeLink.Call(nullptr); +} + +void LegendPositionResources::initFromItemSet( const SfxItemSet& rInAttrs ) +{ + const SfxPoolItem* pPoolItem = nullptr; + if( rInAttrs.GetItemState( SCHATTR_LEGEND_POS, true, &pPoolItem ) == SfxItemState::SET ) + { + chart2::LegendPosition nLegendPosition = static_cast<chart2::LegendPosition>(static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()); + switch( nLegendPosition ) + { + case chart2::LegendPosition_LINE_START: + m_xRbtLeft->set_active(true); + break; + case chart2::LegendPosition_PAGE_START: + m_xRbtTop->set_active(true); + break; + case chart2::LegendPosition_LINE_END: + m_xRbtRight->set_active(true); + break; + case chart2::LegendPosition_PAGE_END: + m_xRbtBottom->set_active(true); + break; + default: + break; + } + } + + if( m_xCbxShow && rInAttrs.GetItemState( SCHATTR_LEGEND_SHOW, true, &pPoolItem ) == SfxItemState::SET ) + { + bool bShow = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCbxShow->set_active(bShow); + } +} + +void LegendPositionResources::writeToItemSet( SfxItemSet& rOutAttrs ) const +{ + chart2::LegendPosition nLegendPosition = chart2::LegendPosition_LINE_END; + if( m_xRbtLeft->get_active() ) + nLegendPosition = chart2::LegendPosition_LINE_START; + else if( m_xRbtTop->get_active() ) + nLegendPosition = chart2::LegendPosition_PAGE_START; + else if( m_xRbtRight->get_active() ) + nLegendPosition = chart2::LegendPosition_LINE_END; + else if( m_xRbtBottom->get_active() ) + nLegendPosition = chart2::LegendPosition_PAGE_END; + rOutAttrs.Put( SfxInt32Item(SCHATTR_LEGEND_POS, static_cast<sal_Int32>(nLegendPosition) ) ); + + rOutAttrs.Put( SfxBoolItem(SCHATTR_LEGEND_SHOW, !m_xCbxShow || m_xCbxShow->get_active()) ); +} + +IMPL_LINK (LegendPositionResources, PositionChangeHdl, weld::ToggleButton&, rRadio, void) +{ + //for each radio click there are coming two change events + //first uncheck of previous button -> ignore that call + //the second call gives the check of the new button + if( rRadio.get_active() ) + m_aChangeLink.Call(nullptr); +} + +void LegendPositionResources::SetChangeHdl( const Link<LinkParamNone*,void>& rLink ) +{ + m_aChangeLink = rLink; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_Titles.cxx b/chart2/source/controller/dialogs/res_Titles.cxx new file mode 100644 index 000000000..e4cbe6d52 --- /dev/null +++ b/chart2/source/controller/dialogs/res_Titles.cxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <res_Titles.hxx> +#include <TitleDialogData.hxx> +#include <vcl/weld.hxx> + +namespace chart +{ + +TitleResources::TitleResources(weld::Builder& rBuilder, bool bShowSecondaryAxesTitle) + : m_xFT_Main(rBuilder.weld_label("labelMainTitle")) + , m_xFT_Sub(rBuilder.weld_label("labelSubTitle")) + , m_xEd_Main(rBuilder.weld_entry("maintitle")) + , m_xEd_Sub(rBuilder.weld_entry("subtitle")) + , m_xFT_XAxis(rBuilder.weld_label("labelPrimaryXaxis")) + , m_xFT_YAxis(rBuilder.weld_label("labelPrimaryYaxis")) + , m_xFT_ZAxis(rBuilder.weld_label("labelPrimaryZaxis")) + , m_xEd_XAxis(rBuilder.weld_entry("primaryXaxis")) + , m_xEd_YAxis(rBuilder.weld_entry("primaryYaxis")) + , m_xEd_ZAxis(rBuilder.weld_entry("primaryZaxis")) + , m_xFT_SecondaryXAxis(rBuilder.weld_label("labelSecondaryXAxis")) + , m_xFT_SecondaryYAxis(rBuilder.weld_label("labelSecondaryYAxis")) + , m_xEd_SecondaryXAxis(rBuilder.weld_entry("secondaryXaxis")) + , m_xEd_SecondaryYAxis(rBuilder.weld_entry("secondaryYaxis")) +{ + m_xFT_SecondaryXAxis->set_visible( bShowSecondaryAxesTitle ); + m_xFT_SecondaryYAxis->set_visible( bShowSecondaryAxesTitle ); + m_xEd_SecondaryXAxis->set_visible( bShowSecondaryAxesTitle ); + m_xEd_SecondaryYAxis->set_visible( bShowSecondaryAxesTitle ); +} + +TitleResources::~TitleResources() +{ +} + +void TitleResources::connect_changed( const Link<weld::Entry&,void>& rLink ) +{ + m_xEd_Main->connect_changed( rLink ); + m_xEd_Sub->connect_changed( rLink ); + m_xEd_XAxis->connect_changed( rLink ); + m_xEd_YAxis->connect_changed( rLink ); + m_xEd_ZAxis->connect_changed( rLink ); + m_xEd_SecondaryXAxis->connect_changed( rLink ); + m_xEd_SecondaryYAxis->connect_changed( rLink ); +} + +bool TitleResources::get_value_changed_from_saved() const +{ + return m_xEd_Main->get_value_changed_from_saved() + || m_xEd_Sub->get_value_changed_from_saved() + || m_xEd_XAxis->get_value_changed_from_saved() + || m_xEd_YAxis->get_value_changed_from_saved() + || m_xEd_ZAxis->get_value_changed_from_saved() + || m_xEd_SecondaryXAxis->get_value_changed_from_saved() + || m_xEd_SecondaryYAxis->get_value_changed_from_saved(); +} + +void TitleResources::save_value() +{ + m_xEd_Main->save_value(); + m_xEd_Sub->save_value(); + m_xEd_XAxis->save_value(); + m_xEd_YAxis->save_value(); + m_xEd_ZAxis->save_value(); + m_xEd_SecondaryXAxis->save_value(); + m_xEd_SecondaryYAxis->save_value(); +} + +void TitleResources::writeToResources( const TitleDialogData& rInput ) +{ + m_xFT_Main->set_sensitive( rInput.aPossibilityList[0] ); + m_xFT_Sub->set_sensitive( rInput.aPossibilityList[1] ); + m_xFT_XAxis->set_sensitive( rInput.aPossibilityList[2] ); + m_xFT_YAxis->set_sensitive( rInput.aPossibilityList[3] ); + m_xFT_ZAxis->set_sensitive( rInput.aPossibilityList[4] ); + m_xFT_SecondaryXAxis->set_sensitive( rInput.aPossibilityList[5] ); + m_xFT_SecondaryYAxis->set_sensitive( rInput.aPossibilityList[6] ); + + m_xEd_Main->set_sensitive( rInput.aPossibilityList[0] ); + m_xEd_Sub->set_sensitive( rInput.aPossibilityList[1] ); + m_xEd_XAxis->set_sensitive( rInput.aPossibilityList[2] ); + m_xEd_YAxis->set_sensitive( rInput.aPossibilityList[3] ); + m_xEd_ZAxis->set_sensitive( rInput.aPossibilityList[4] ); + m_xEd_SecondaryXAxis->set_sensitive( rInput.aPossibilityList[5] ); + m_xEd_SecondaryYAxis->set_sensitive( rInput.aPossibilityList[6] ); + + m_xEd_Main->set_text(rInput.aTextList[0]); + m_xEd_Sub->set_text(rInput.aTextList[1]); + m_xEd_XAxis->set_text(rInput.aTextList[2]); + m_xEd_YAxis->set_text(rInput.aTextList[3]); + m_xEd_ZAxis->set_text(rInput.aTextList[4]); + m_xEd_SecondaryXAxis->set_text(rInput.aTextList[5]); + m_xEd_SecondaryYAxis->set_text(rInput.aTextList[6]); +} + +void TitleResources::readFromResources( TitleDialogData& rOutput ) +{ + rOutput.aExistenceList[0] = !m_xEd_Main->get_text().isEmpty(); + rOutput.aExistenceList[1] = !m_xEd_Sub->get_text().isEmpty(); + rOutput.aExistenceList[2] = !m_xEd_XAxis->get_text().isEmpty(); + rOutput.aExistenceList[3] = !m_xEd_YAxis->get_text().isEmpty(); + rOutput.aExistenceList[4] = !m_xEd_ZAxis->get_text().isEmpty(); + rOutput.aExistenceList[5] = !m_xEd_SecondaryXAxis->get_text().isEmpty(); + rOutput.aExistenceList[6] = !m_xEd_SecondaryYAxis->get_text().isEmpty(); + + rOutput.aTextList[0] = m_xEd_Main->get_text(); + rOutput.aTextList[1] = m_xEd_Sub->get_text(); + rOutput.aTextList[2] = m_xEd_XAxis->get_text(); + rOutput.aTextList[3] = m_xEd_YAxis->get_text(); + rOutput.aTextList[4] = m_xEd_ZAxis->get_text(); + rOutput.aTextList[5] = m_xEd_SecondaryXAxis->get_text(); + rOutput.aTextList[6] = m_xEd_SecondaryYAxis->get_text(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_Trendline.cxx b/chart2/source/controller/dialogs/res_Trendline.cxx new file mode 100644 index 000000000..0eaea7b4e --- /dev/null +++ b/chart2/source/controller/dialogs/res_Trendline.cxx @@ -0,0 +1,392 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "res_Trendline.hxx" +#include <bitmaps.hlst> +#include <chartview/ChartSfxItemIds.hxx> + +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svl/zforlist.hxx> +#include <vcl/weld.hxx> + +namespace chart +{ + +static void lcl_setValue(weld::FormattedSpinButton& rFmtField, double fValue ) +{ + rFmtField.set_value(fValue); +//TODO rFmtField.SetDefaultValue( fValue ); +} + +TrendlineResources::TrendlineResources(weld::Builder& rBuilder, const SfxItemSet& rInAttrs) + : m_eTrendLineType(SvxChartRegress::Linear) + , m_bTrendLineUnique(true) + , m_pNumFormatter(nullptr) + , m_nNbPoints(0) + , m_xRB_Linear(rBuilder.weld_radio_button("linear")) + , m_xRB_Logarithmic(rBuilder.weld_radio_button("logarithmic")) + , m_xRB_Exponential(rBuilder.weld_radio_button("exponential")) + , m_xRB_Power(rBuilder.weld_radio_button("power")) + , m_xRB_Polynomial(rBuilder.weld_radio_button("polynomial")) + , m_xRB_MovingAverage(rBuilder.weld_radio_button("movingAverage")) + , m_xFI_Linear(rBuilder.weld_image("imageLinear")) + , m_xFI_Logarithmic(rBuilder.weld_image("imageLogarithmic")) + , m_xFI_Exponential(rBuilder.weld_image("imageExponential")) + , m_xFI_Power(rBuilder.weld_image("imagePower")) + , m_xFI_Polynomial(rBuilder.weld_image("imagePolynomial")) + , m_xFI_MovingAverage(rBuilder.weld_image("imageMovingAverage")) + , m_xNF_Degree(rBuilder.weld_spin_button("degree")) + , m_xNF_Period(rBuilder.weld_spin_button("period")) + , m_xEE_Name(rBuilder.weld_entry("entry_name")) + , m_xFmtFld_ExtrapolateForward(rBuilder.weld_formatted_spin_button("extrapolateForward")) + , m_xFmtFld_ExtrapolateBackward(rBuilder.weld_formatted_spin_button("extrapolateBackward")) + , m_xCB_SetIntercept(rBuilder.weld_check_button("setIntercept")) + , m_xFmtFld_InterceptValue(rBuilder.weld_formatted_spin_button("interceptValue")) + , m_xCB_ShowEquation(rBuilder.weld_check_button("showEquation")) + , m_xEE_XName(rBuilder.weld_entry("entry_Xname")) + , m_xEE_YName(rBuilder.weld_entry("entry_Yname")) + , m_xCB_ShowCorrelationCoeff(rBuilder.weld_check_button("showCorrelationCoefficient")) +{ + FillValueSets(); + + Link<weld::ToggleButton&,void> aLink = LINK(this, TrendlineResources, SelectTrendLine); + m_xRB_Linear->connect_toggled( aLink ); + m_xRB_Logarithmic->connect_toggled( aLink ); + m_xRB_Exponential->connect_toggled( aLink ); + m_xRB_Power->connect_toggled( aLink ); + m_xRB_Polynomial->connect_toggled( aLink ); + m_xRB_MovingAverage->connect_toggled( aLink ); + + Link<weld::SpinButton&,void> aLink2 = LINK(this, TrendlineResources, ChangeSpinValue); + m_xNF_Degree->connect_value_changed(aLink2); + m_xNF_Period->connect_value_changed(aLink2); + m_xFmtFld_InterceptValue->connect_value_changed(LINK(this, TrendlineResources, ChangeFormattedValue)); + + m_xCB_ShowEquation->connect_toggled(LINK(this, TrendlineResources, ShowEquation)); + + Reset( rInAttrs ); + UpdateControlStates(); +} + +TrendlineResources::~TrendlineResources() +{} + +IMPL_LINK_NOARG(TrendlineResources, SelectTrendLine, weld::ToggleButton&, void) +{ + if (m_xRB_Linear->get_active()) + m_eTrendLineType = SvxChartRegress::Linear; + else if (m_xRB_Logarithmic->get_active()) + m_eTrendLineType = SvxChartRegress::Log; + else if (m_xRB_Exponential->get_active()) + m_eTrendLineType = SvxChartRegress::Exp; + else if (m_xRB_Power->get_active()) + m_eTrendLineType = SvxChartRegress::Power; + else if (m_xRB_Polynomial->get_active()) + m_eTrendLineType = SvxChartRegress::Polynomial; + else if (m_xRB_MovingAverage->get_active()) + m_eTrendLineType = SvxChartRegress::MovingAverage; + m_bTrendLineUnique = true; + + UpdateControlStates(); +} + +void TrendlineResources::Reset( const SfxItemSet& rInAttrs ) +{ + const SfxPoolItem *pPoolItem = nullptr; + + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_CURVE_NAME, true, &pPoolItem ) == SfxItemState::SET ) + { + OUString aName = static_cast< const SfxStringItem* >(pPoolItem)->GetValue(); + m_xEE_Name->set_text(aName); + } + else + { + m_xEE_Name->set_text(""); + } + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_XNAME, true, &pPoolItem ) == SfxItemState::SET ) + { + OUString aName = static_cast< const SfxStringItem* >(pPoolItem)->GetValue(); + m_xEE_XName->set_text(aName); + } + else + { + m_xEE_XName->set_text("x"); + } + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_YNAME, true, &pPoolItem ) == SfxItemState::SET ) + { + OUString aName = static_cast< const SfxStringItem* >(pPoolItem)->GetValue(); + m_xEE_YName->set_text(aName); + } + else + { + m_xEE_YName->set_text("f(x)"); + } + + SfxItemState aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_TYPE, true, &pPoolItem ); + m_bTrendLineUnique = ( aState != SfxItemState::DONTCARE ); + if( aState == SfxItemState::SET ) + { + const SvxChartRegressItem * pItem = dynamic_cast< const SvxChartRegressItem * >( pPoolItem ); + if( pItem ) + { + m_eTrendLineType = pItem->GetValue(); + } + } + + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_DEGREE, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nDegree = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xNF_Degree->set_value( nDegree ); + } + else + { + m_xNF_Degree->set_value( 2 ); + } + + m_xNF_Degree->save_value(); + + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_PERIOD, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nPeriod = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xNF_Period->set_value( nPeriod ); + } + else + { + m_xNF_Period->set_value( 2 ); + } + + m_xNF_Period->save_value(); + + double nValue = 0.0; + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD, true, &pPoolItem ) == SfxItemState::SET ) + { + nValue = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue() ; + } + lcl_setValue(*m_xFmtFld_ExtrapolateForward, nValue); + + nValue = 0.0; + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD, true, &pPoolItem ) == SfxItemState::SET ) + { + nValue = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue() ; + } + lcl_setValue(*m_xFmtFld_ExtrapolateBackward, nValue); + + nValue = 0.0; + if( rInAttrs.GetItemState( SCHATTR_REGRESSION_INTERCEPT_VALUE, true, &pPoolItem ) == SfxItemState::SET ) + { + nValue = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue() ; + } + lcl_setValue(*m_xFmtFld_InterceptValue, nValue); + + aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SET_INTERCEPT, true, &pPoolItem ); + if( aState == SfxItemState::DONTCARE ) + { + m_xCB_SetIntercept->set_state(TRISTATE_INDET); + } + else + { + if( aState == SfxItemState::SET ) + m_xCB_SetIntercept->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue()); + } + + aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_EQUATION, true, &pPoolItem ); + if( aState == SfxItemState::DONTCARE ) + { + m_xCB_ShowEquation->set_state(TRISTATE_INDET); + } + else + { + if( aState == SfxItemState::SET ) + m_xCB_ShowEquation->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue()); + } + + aState = rInAttrs.GetItemState( SCHATTR_REGRESSION_SHOW_COEFF, true, &pPoolItem ); + if( aState == SfxItemState::DONTCARE ) + { + m_xCB_ShowCorrelationCoeff->set_state(TRISTATE_INDET); + } + else + { + if( aState == SfxItemState::SET ) + m_xCB_ShowCorrelationCoeff->set_active( static_cast< const SfxBoolItem * >( pPoolItem )->GetValue()); + } + + if( !m_bTrendLineUnique ) + return; + + switch( m_eTrendLineType ) + { + case SvxChartRegress::Linear : + m_xRB_Linear->set_active(true); + break; + case SvxChartRegress::Log : + m_xRB_Logarithmic->set_active(true); + break; + case SvxChartRegress::Exp : + m_xRB_Exponential->set_active(true); + break; + case SvxChartRegress::Power : + m_xRB_Power->set_active(true); + break; + case SvxChartRegress::Polynomial : + m_xRB_Polynomial->set_active(true); + break; + case SvxChartRegress::MovingAverage : + m_xRB_MovingAverage->set_active(true); + break; + default: + break; + } +} + +void TrendlineResources::FillItemSet(SfxItemSet* rOutAttrs) const +{ + if( m_bTrendLineUnique ) + rOutAttrs->Put( SvxChartRegressItem( m_eTrendLineType, SCHATTR_REGRESSION_TYPE )); + + if( m_xCB_ShowEquation->get_state() != TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_REGRESSION_SHOW_EQUATION, m_xCB_ShowEquation->get_active() )); + + if( m_xCB_ShowCorrelationCoeff->get_state() != TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_REGRESSION_SHOW_COEFF, m_xCB_ShowCorrelationCoeff->get_active() )); + + OUString aName = m_xEE_Name->get_text(); + rOutAttrs->Put(SfxStringItem(SCHATTR_REGRESSION_CURVE_NAME, aName)); + aName = m_xEE_XName->get_text(); + if ( aName.isEmpty() ) + aName = "x"; + rOutAttrs->Put(SfxStringItem(SCHATTR_REGRESSION_XNAME, aName)); + aName = m_xEE_YName->get_text(); + if ( aName.isEmpty() ) + aName = "f(x)"; + rOutAttrs->Put(SfxStringItem(SCHATTR_REGRESSION_YNAME, aName)); + + sal_Int32 aDegree = m_xNF_Degree->get_value(); + rOutAttrs->Put(SfxInt32Item( SCHATTR_REGRESSION_DEGREE, aDegree ) ); + + sal_Int32 aPeriod = m_xNF_Period->get_value(); + rOutAttrs->Put(SfxInt32Item( SCHATTR_REGRESSION_PERIOD, aPeriod ) ); + + sal_uInt32 nIndex = 0; + double aValue = 0.0; + (void)m_pNumFormatter->IsNumberFormat(m_xFmtFld_ExtrapolateForward->get_text(),nIndex,aValue); + rOutAttrs->Put(SvxDoubleItem( aValue, SCHATTR_REGRESSION_EXTRAPOLATE_FORWARD ) ); + + aValue = 0.0; + (void)m_pNumFormatter->IsNumberFormat(m_xFmtFld_ExtrapolateBackward->get_text(),nIndex,aValue); + rOutAttrs->Put(SvxDoubleItem( aValue, SCHATTR_REGRESSION_EXTRAPOLATE_BACKWARD ) ); + + if( m_xCB_SetIntercept->get_state() != TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_REGRESSION_SET_INTERCEPT, m_xCB_SetIntercept->get_active() )); + + aValue = 0.0; + (void)m_pNumFormatter->IsNumberFormat(m_xFmtFld_InterceptValue->get_text(),nIndex,aValue); + rOutAttrs->Put(SvxDoubleItem( aValue, SCHATTR_REGRESSION_INTERCEPT_VALUE ) ); +} + +void TrendlineResources::FillValueSets() +{ + m_xFI_Linear->set_from_icon_name(BMP_REGRESSION_LINEAR); + m_xFI_Logarithmic->set_from_icon_name(BMP_REGRESSION_LOG); + m_xFI_Exponential->set_from_icon_name(BMP_REGRESSION_EXP); + m_xFI_Power->set_from_icon_name(BMP_REGRESSION_POWER); + m_xFI_Polynomial->set_from_icon_name(BMP_REGRESSION_POLYNOMIAL); + m_xFI_MovingAverage->set_from_icon_name(BMP_REGRESSION_MOVING_AVERAGE); +} + +void TrendlineResources::UpdateControlStates() +{ + if( m_nNbPoints > 0 ) + { + sal_Int32 nMaxValue = m_nNbPoints - 1 + (m_xCB_SetIntercept->get_active() ? 1 : 0); + m_xNF_Degree->set_max(nMaxValue); + m_xNF_Period->set_max(m_nNbPoints - 1); + } + bool bMovingAverage = ( m_eTrendLineType == SvxChartRegress::MovingAverage ); + bool bInterceptAvailable = ( m_eTrendLineType == SvxChartRegress::Linear ) + || ( m_eTrendLineType == SvxChartRegress::Polynomial ) + || ( m_eTrendLineType == SvxChartRegress::Exp ); + m_xFmtFld_ExtrapolateForward->set_sensitive( !bMovingAverage ); + m_xFmtFld_ExtrapolateBackward->set_sensitive( !bMovingAverage ); + m_xCB_SetIntercept->set_sensitive( bInterceptAvailable ); + m_xFmtFld_InterceptValue->set_sensitive( bInterceptAvailable ); + if( bMovingAverage ) + { + m_xCB_ShowEquation->set_state(TRISTATE_FALSE); + m_xCB_ShowCorrelationCoeff->set_state(TRISTATE_FALSE); + } + m_xCB_ShowEquation->set_sensitive( !bMovingAverage ); + m_xCB_ShowCorrelationCoeff->set_sensitive( !bMovingAverage ); + m_xEE_XName->set_sensitive( !bMovingAverage && m_xCB_ShowEquation->get_active() ); + m_xEE_YName->set_sensitive( !bMovingAverage && m_xCB_ShowEquation->get_active() ); +} + +IMPL_LINK(TrendlineResources, ChangeSpinValue, weld::SpinButton&, rNumericField, void) +{ + if (&rNumericField == m_xNF_Degree.get()) + { + if (!m_xRB_Polynomial->get_active() && m_xNF_Degree->get_value_changed_from_saved()) + { + m_xRB_Polynomial->set_active(true); + SelectTrendLine(*m_xRB_Polynomial); + } + } + else if (&rNumericField == m_xNF_Period.get()) + { + if (!m_xRB_MovingAverage->get_active() && m_xNF_Period->get_value_changed_from_saved()) + { + m_xRB_MovingAverage->set_active(true); + SelectTrendLine(*m_xRB_MovingAverage); + } + } + UpdateControlStates(); +} + +IMPL_LINK_NOARG(TrendlineResources, ChangeFormattedValue, weld::FormattedSpinButton&, void) +{ + if (!m_xCB_SetIntercept->get_active()) + m_xCB_SetIntercept->set_active(true); + UpdateControlStates(); +} + +void TrendlineResources::SetNumFormatter( SvNumberFormatter* pFormatter ) +{ + m_pNumFormatter = pFormatter; + m_xFmtFld_ExtrapolateForward->set_formatter( m_pNumFormatter ); + m_xFmtFld_ExtrapolateBackward->set_formatter( m_pNumFormatter ); + m_xFmtFld_InterceptValue->set_formatter( m_pNumFormatter ); +} + +void TrendlineResources::SetNbPoints( sal_Int32 nNbPoints ) +{ + m_nNbPoints = nNbPoints; + UpdateControlStates(); +} + +IMPL_LINK_NOARG(TrendlineResources, ShowEquation, weld::ToggleButton&, void) +{ + m_xEE_XName->set_sensitive(m_xCB_ShowEquation->get_active()); + m_xEE_YName->set_sensitive(m_xCB_ShowEquation->get_active()); + UpdateControlStates(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/res_Trendline.hxx b/chart2/source/controller/dialogs/res_Trendline.hxx new file mode 100644 index 000000000..91f70f241 --- /dev/null +++ b/chart2/source/controller/dialogs/res_Trendline.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_TRENDLINE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_TRENDLINE_HXX + +#include <tools/link.hxx> +#include <svl/itemset.hxx> +#include <svx/chrtitem.hxx> + +namespace weld { class Builder; } +namespace weld { class CheckButton; } +namespace weld { class Entry; } +namespace weld { class FormattedSpinButton; } +namespace weld { class Image; } +namespace weld { class RadioButton; } +namespace weld { class SpinButton; } +namespace weld { class ToggleButton; } + +class SvNumberFormatter; + +namespace chart +{ + +class TrendlineResources final +{ +public: + TrendlineResources(weld::Builder& rParent, const SfxItemSet& rInAttrs); + ~TrendlineResources(); + + void Reset(const SfxItemSet& rInAttrs); + void FillItemSet(SfxItemSet* rOutAttrs) const; + + void FillValueSets(); + + void SetNumFormatter( SvNumberFormatter* pFormatter ); + void SetNbPoints( sal_Int32 nNbPoints ); + +private: + SvxChartRegress m_eTrendLineType; + + bool m_bTrendLineUnique; + + SvNumberFormatter* m_pNumFormatter; + sal_Int32 m_nNbPoints; + + std::unique_ptr<weld::RadioButton> m_xRB_Linear; + std::unique_ptr<weld::RadioButton> m_xRB_Logarithmic; + std::unique_ptr<weld::RadioButton> m_xRB_Exponential; + std::unique_ptr<weld::RadioButton> m_xRB_Power; + std::unique_ptr<weld::RadioButton> m_xRB_Polynomial; + std::unique_ptr<weld::RadioButton> m_xRB_MovingAverage; + + std::unique_ptr<weld::Image> m_xFI_Linear; + std::unique_ptr<weld::Image> m_xFI_Logarithmic; + std::unique_ptr<weld::Image> m_xFI_Exponential; + std::unique_ptr<weld::Image> m_xFI_Power; + std::unique_ptr<weld::Image> m_xFI_Polynomial; + std::unique_ptr<weld::Image> m_xFI_MovingAverage; + + std::unique_ptr<weld::SpinButton> m_xNF_Degree; + std::unique_ptr<weld::SpinButton> m_xNF_Period; + std::unique_ptr<weld::Entry> m_xEE_Name; + std::unique_ptr<weld::FormattedSpinButton> m_xFmtFld_ExtrapolateForward; + std::unique_ptr<weld::FormattedSpinButton> m_xFmtFld_ExtrapolateBackward; + std::unique_ptr<weld::CheckButton> m_xCB_SetIntercept; + std::unique_ptr<weld::FormattedSpinButton> m_xFmtFld_InterceptValue; + std::unique_ptr<weld::CheckButton> m_xCB_ShowEquation; + std::unique_ptr<weld::Entry> m_xEE_XName; + std::unique_ptr<weld::Entry> m_xEE_YName; + std::unique_ptr<weld::CheckButton> m_xCB_ShowCorrelationCoeff; + + void UpdateControlStates(); + DECL_LINK(SelectTrendLine, weld::ToggleButton&, void); + DECL_LINK(ChangeSpinValue, weld::SpinButton&, void); + DECL_LINK(ChangeFormattedValue, weld::FormattedSpinButton&, void); + DECL_LINK(ShowEquation, weld::ToggleButton&, void); +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_RES_TRENDLINE_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx new file mode 100644 index 000000000..c24cf6fab --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.cxx @@ -0,0 +1,320 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_3D_SceneAppearance.hxx" +#include <ChartModelHelper.hxx> +#include <ThreeDHelper.hxx> +#include <ControllerLockGuard.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/chart2/XDiagram.hpp> +#include <com/sun/star/drawing/ShadeMode.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> + +using namespace ::com::sun::star; + +namespace +{ + +struct lcl_ModelProperties +{ + drawing::ShadeMode m_aShadeMode; + sal_Int32 m_nRoundedEdges; + sal_Int32 m_nObjectLines; + ::chart::ThreeDLookScheme m_eScheme; + + lcl_ModelProperties() + : m_aShadeMode(drawing::ShadeMode_FLAT) + , m_nRoundedEdges(-1) + , m_nObjectLines(-1) + , m_eScheme(::chart::ThreeDLookScheme_Unknown) + {} +}; + +lcl_ModelProperties lcl_getPropertiesFromModel( uno::Reference< frame::XModel > const & xModel ) +{ + lcl_ModelProperties aProps; + try + { + uno::Reference< chart2::XDiagram > xDiagram( ::chart::ChartModelHelper::findDiagram( xModel ) ); + uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW ); + xDiaProp->getPropertyValue( "D3DSceneShadeMode" ) >>= aProps.m_aShadeMode; + ::chart::ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, aProps.m_nRoundedEdges, aProps.m_nObjectLines ); + aProps.m_eScheme = ::chart::ThreeDHelper::detectScheme( xDiagram ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return aProps; +} + +void lcl_setShadeModeAtModel( uno::Reference< frame::XModel > const & xModel, drawing::ShadeMode aShadeMode ) +{ + try + { + uno::Reference< beans::XPropertySet > xDiaProp( + ::chart::ChartModelHelper::findDiagram( xModel ), uno::UNO_QUERY_THROW ); + xDiaProp->setPropertyValue( "D3DSceneShadeMode" , uno::Any( aShadeMode )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +} // anonymous namespace + +namespace chart +{ + +#define POS_3DSCHEME_SIMPLE 0 +#define POS_3DSCHEME_REALISTIC 1 +#define POS_3DSCHEME_CUSTOM 2 + +ThreeD_SceneAppearance_TabPage::ThreeD_SceneAppearance_TabPage(weld::Container* pParent, + const uno::Reference<frame::XModel>& xChartModel, + ControllerLockHelper& rControllerLockHelper) + : m_xChartModel(xChartModel) + , m_bUpdateOtherControls(true) + , m_bCommitToModel(true) + , m_rControllerLockHelper(rControllerLockHelper) + , m_xBuilder(Application::CreateBuilder(pParent, "modules/schart/ui/tp_3D_SceneAppearance.ui")) + , m_xContainer(m_xBuilder->weld_container("tp_3D_SceneAppearance")) + , m_xLB_Scheme(m_xBuilder->weld_combo_box("LB_SCHEME")) + , m_xCB_Shading(m_xBuilder->weld_check_button("CB_SHADING")) + , m_xCB_ObjectLines(m_xBuilder->weld_check_button("CB_OBJECTLINES")) + , m_xCB_RoundedEdge(m_xBuilder->weld_check_button("CB_ROUNDEDEDGE")) +{ + m_aCustom = m_xLB_Scheme->get_text(POS_3DSCHEME_CUSTOM); + m_xLB_Scheme->remove(POS_3DSCHEME_CUSTOM); + + m_xLB_Scheme->connect_changed( LINK( this, ThreeD_SceneAppearance_TabPage, SelectSchemeHdl ) ); + + m_xCB_RoundedEdge->connect_toggled( LINK( this, ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines ) ); + m_xCB_Shading->connect_toggled( LINK( this, ThreeD_SceneAppearance_TabPage, SelectShading ) ); + m_xCB_ObjectLines->connect_toggled( LINK( this, ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines ) ); + + initControlsFromModel(); +} + +ThreeD_SceneAppearance_TabPage::~ThreeD_SceneAppearance_TabPage() +{ +} + +void ThreeD_SceneAppearance_TabPage::ActivatePage() +{ + updateScheme(); +} + +void ThreeD_SceneAppearance_TabPage::applyRoundedEdgeAndObjectLinesToModel() +{ + if(!m_bCommitToModel) + return; + + sal_Int32 nObjectLines = -1; + + switch( m_xCB_ObjectLines->get_state()) + { + case TRISTATE_FALSE: + nObjectLines = 0; + break; + case TRISTATE_TRUE: + nObjectLines = 1; + break; + case TRISTATE_INDET: + nObjectLines = -1; + break; + } + + sal_Int32 nCurrentRoundedEdges = -1; + switch( m_xCB_RoundedEdge->get_state() ) + { + case TRISTATE_FALSE: + nCurrentRoundedEdges = 0; + break; + case TRISTATE_TRUE: + nCurrentRoundedEdges = 5; + break; + case TRISTATE_INDET: + nCurrentRoundedEdges = -1; + break; + } + + // locked controllers + ControllerLockHelperGuard aGuard( m_rControllerLockHelper ); + ThreeDHelper::setRoundedEdgesAndObjectLines( + ::chart::ChartModelHelper::findDiagram( m_xChartModel ), nCurrentRoundedEdges, nObjectLines ); +} + +void ThreeD_SceneAppearance_TabPage::applyShadeModeToModel() +{ + if(!m_bCommitToModel) + return; + + drawing::ShadeMode aShadeMode = drawing::ShadeMode_PHONG; + + switch( m_xCB_Shading->get_state()) + { + case TRISTATE_FALSE: + aShadeMode = drawing::ShadeMode_FLAT; + break; + case TRISTATE_TRUE: + aShadeMode = drawing::ShadeMode_SMOOTH; + break; + case TRISTATE_INDET: + // nothing + break; + } + + lcl_setShadeModeAtModel( m_xChartModel, aShadeMode ); +} + +void ThreeD_SceneAppearance_TabPage::initControlsFromModel() +{ + m_bCommitToModel = false; + m_bUpdateOtherControls = false; + + lcl_ModelProperties aProps( lcl_getPropertiesFromModel( m_xChartModel )); + + if(aProps.m_aShadeMode == drawing::ShadeMode_FLAT) + { + m_xCB_Shading->set_active(false); + } + else if(aProps.m_aShadeMode == drawing::ShadeMode_SMOOTH) + { + m_xCB_Shading->set_active(true); + } + else + { + m_xCB_Shading->set_state(TRISTATE_INDET); + } + + if(aProps.m_nObjectLines == 0) + { + m_xCB_ObjectLines->set_active(false); + } + else if(aProps.m_nObjectLines==1) + { + m_xCB_ObjectLines->set_active(true); + } + else + { + m_xCB_ObjectLines->set_state(TRISTATE_INDET); + } + + if(aProps.m_nRoundedEdges >= 5) + { + m_xCB_RoundedEdge->set_active(true); + } + else if(aProps.m_nRoundedEdges<0) + { + m_xCB_RoundedEdge->set_state(TRISTATE_INDET); + } + else + { + m_xCB_RoundedEdge->set_active(false); + } + m_xCB_RoundedEdge->set_sensitive( !m_xCB_ObjectLines->get_active() ); + + updateScheme(); + + m_bCommitToModel = true; + m_bUpdateOtherControls = true; +} + +void ThreeD_SceneAppearance_TabPage::updateScheme() +{ + lcl_ModelProperties aProps( lcl_getPropertiesFromModel( m_xChartModel )); + + if (m_xLB_Scheme->get_count() == (POS_3DSCHEME_CUSTOM+1)) + m_xLB_Scheme->remove(POS_3DSCHEME_CUSTOM); + switch( aProps.m_eScheme ) + { + case ThreeDLookScheme_Simple: + m_xLB_Scheme->set_active( POS_3DSCHEME_SIMPLE ); + break; + case ThreeDLookScheme_Realistic: + m_xLB_Scheme->set_active( POS_3DSCHEME_REALISTIC ); + break; + case ThreeDLookScheme_Unknown: + { + m_xLB_Scheme->insert_text(POS_3DSCHEME_CUSTOM, m_aCustom); + m_xLB_Scheme->set_active(POS_3DSCHEME_CUSTOM); + } + break; + } +} + +IMPL_LINK_NOARG(ThreeD_SceneAppearance_TabPage, SelectSchemeHdl, weld::ComboBox&, void) +{ + if( !m_bUpdateOtherControls ) + return; + + { + // locked controllers + ControllerLockHelperGuard aGuard( m_rControllerLockHelper ); + + uno::Reference< chart2::XDiagram > xDiagram( ::chart::ChartModelHelper::findDiagram( m_xChartModel ) ); + + if( m_xLB_Scheme->get_active() == POS_3DSCHEME_REALISTIC ) + ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Realistic ); + else if( m_xLB_Scheme->get_active() == POS_3DSCHEME_SIMPLE ) + ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Simple ); + else + { + OSL_FAIL( "Invalid Entry selected" ); + } + } + + // update other controls + initControlsFromModel(); +} + +IMPL_LINK_NOARG(ThreeD_SceneAppearance_TabPage, SelectShading, weld::ToggleButton&, void) +{ + if( !m_bUpdateOtherControls ) + return; + + applyShadeModeToModel(); + updateScheme(); +} + +IMPL_LINK(ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines, weld::ToggleButton&, rCheckBox, void) +{ + if( !m_bUpdateOtherControls ) + return; + + if (&rCheckBox == m_xCB_ObjectLines.get()) + { + m_bUpdateOtherControls = false; + m_xCB_RoundedEdge->set_sensitive( !m_xCB_ObjectLines->get_active() ); + if(!m_xCB_RoundedEdge->get_sensitive()) + m_xCB_RoundedEdge->set_active(false); + m_bUpdateOtherControls = true; + } + + applyRoundedEdgeAndObjectLinesToModel(); + updateScheme(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx new file mode 100644 index 000000000..00bc4e3f4 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneAppearance.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEAPPEARANCE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEAPPEARANCE_HXX + +#include <vcl/weld.hxx> + +namespace chart { class ControllerLockHelper; } +namespace com::sun::star::frame { class XModel; } + +namespace chart +{ + +class ThreeD_SceneAppearance_TabPage +{ +public: + ThreeD_SceneAppearance_TabPage( + weld::Container* pParent, + const css::uno::Reference< css::frame::XModel > & xChartModel, + ControllerLockHelper & rControllerLockHelper ); + void ActivatePage(); + ~ThreeD_SceneAppearance_TabPage(); + +private: + DECL_LINK( SelectSchemeHdl, weld::ComboBox&, void ); + DECL_LINK( SelectShading, weld::ToggleButton&, void ); + DECL_LINK( SelectRoundedEdgeOrObjectLines, weld::ToggleButton&, void ); + + void initControlsFromModel(); + void applyShadeModeToModel(); + void applyRoundedEdgeAndObjectLinesToModel(); + void updateScheme(); + +private: + css::uno::Reference<css::frame::XModel> m_xChartModel; + + bool m_bUpdateOtherControls; + bool m_bCommitToModel; + OUString m_aCustom; + + ControllerLockHelper& m_rControllerLockHelper; + + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + std::unique_ptr<weld::ComboBox> m_xLB_Scheme; + std::unique_ptr<weld::CheckButton> m_xCB_Shading; + std::unique_ptr<weld::CheckButton> m_xCB_ObjectLines; + std::unique_ptr<weld::CheckButton> m_xCB_RoundedEdge; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx new file mode 100644 index 000000000..238df9a00 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.cxx @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_3D_SceneGeometry.hxx" + +#include <DiagramHelper.hxx> +#include <ChartTypeHelper.hxx> +#include <ThreeDHelper.hxx> +#include <ControllerLockGuard.hxx> +#include <com/sun/star/drawing/ProjectionMode.hpp> +#include <tools/diagnose_ex.h> +#include <tools/helpers.hxx> +#include <vcl/svapp.hxx> + +namespace chart +{ + +using namespace ::com::sun::star; + +namespace +{ + +void lcl_SetMetricFieldLimits(weld::MetricSpinButton& rField, sal_Int64 nLimit) +{ + rField.set_range(-1*nLimit, nLimit, FieldUnit::DEGREE); +} + +} + +ThreeD_SceneGeometry_TabPage::ThreeD_SceneGeometry_TabPage(weld::Container* pParent, + const uno::Reference< beans::XPropertySet > & xSceneProperties, + ControllerLockHelper & rControllerLockHelper) + : m_xSceneProperties( xSceneProperties ) + , m_nXRotation(0) + , m_nYRotation(0) + , m_nZRotation(0) + , m_bAngleChangePending( false ) + , m_bPerspectiveChangePending( false ) + , m_rControllerLockHelper( rControllerLockHelper ) + , m_xBuilder(Application::CreateBuilder(pParent, "modules/schart/ui/tp_3D_SceneGeometry.ui")) + , m_xContainer(m_xBuilder->weld_container("tp_3DSceneGeometry")) + , m_xCbxRightAngledAxes(m_xBuilder->weld_check_button("CBX_RIGHT_ANGLED_AXES")) + , m_xMFXRotation(m_xBuilder->weld_metric_spin_button("MTR_FLD_X_ROTATION", FieldUnit::DEGREE)) + , m_xMFYRotation(m_xBuilder->weld_metric_spin_button("MTR_FLD_Y_ROTATION", FieldUnit::DEGREE)) + , m_xFtZRotation(m_xBuilder->weld_label("FT_Z_ROTATION")) + , m_xMFZRotation(m_xBuilder->weld_metric_spin_button("MTR_FLD_Z_ROTATION", FieldUnit::DEGREE)) + , m_xCbxPerspective(m_xBuilder->weld_check_button("CBX_PERSPECTIVE")) + , m_xMFPerspective(m_xBuilder->weld_metric_spin_button("MTR_FLD_PERSPECTIVE", FieldUnit::PERCENT)) +{ + double fXAngle, fYAngle, fZAngle; + ThreeDHelper::getRotationAngleFromDiagram( m_xSceneProperties, fXAngle, fYAngle, fZAngle ); + + fXAngle = basegfx::rad2deg(fXAngle); + fYAngle = basegfx::rad2deg(fYAngle); + fZAngle = basegfx::rad2deg(fZAngle); + + OSL_ENSURE( fZAngle>=-90 && fZAngle<=90, "z angle is out of valid range" ); + + lcl_SetMetricFieldLimits( *m_xMFZRotation, 90 ); + + m_nXRotation = NormAngle180( + ::basegfx::fround(fXAngle * pow(10.0, m_xMFXRotation->get_digits()))); + m_nYRotation = NormAngle180( + ::basegfx::fround(-1.0 * fYAngle * pow(10.0, m_xMFYRotation->get_digits()))); + m_nZRotation = NormAngle180( + ::basegfx::fround(-1.0 * fZAngle * pow(10.0, m_xMFZRotation->get_digits()))); + + m_xMFXRotation->set_value(m_nXRotation, FieldUnit::DEGREE); + m_xMFYRotation->set_value(m_nYRotation, FieldUnit::DEGREE); + m_xMFZRotation->set_value(m_nZRotation, FieldUnit::DEGREE); + + const int nTimeout = 4*EDIT_UPDATEDATA_TIMEOUT; + m_aAngleTimer.SetTimeout(nTimeout); + m_aAngleTimer.SetInvokeHandler( LINK( this, ThreeD_SceneGeometry_TabPage, AngleChanged ) ); + + Link<weld::MetricSpinButton&,void> aAngleEditedLink( LINK( this, ThreeD_SceneGeometry_TabPage, AngleEdited )); + m_xMFXRotation->connect_value_changed( aAngleEditedLink ); + m_xMFYRotation->connect_value_changed( aAngleEditedLink ); + m_xMFZRotation->connect_value_changed( aAngleEditedLink ); + + drawing::ProjectionMode aProjectionMode = drawing::ProjectionMode_PERSPECTIVE; + m_xSceneProperties->getPropertyValue( "D3DScenePerspective" ) >>= aProjectionMode; + m_xCbxPerspective->set_active( aProjectionMode == drawing::ProjectionMode_PERSPECTIVE ); + m_xCbxPerspective->connect_toggled( LINK( this, ThreeD_SceneGeometry_TabPage, PerspectiveToggled )); + + sal_Int32 nPerspectivePercentage = 20; + m_xSceneProperties->getPropertyValue( "Perspective" ) >>= nPerspectivePercentage; + m_xMFPerspective->set_value(nPerspectivePercentage, FieldUnit::PERCENT); + + m_aPerspectiveTimer.SetTimeout(nTimeout); + m_aPerspectiveTimer.SetInvokeHandler( LINK( this, ThreeD_SceneGeometry_TabPage, PerspectiveChanged ) ); + m_xMFPerspective->connect_value_changed( LINK( this, ThreeD_SceneGeometry_TabPage, PerspectiveEdited ) ); + m_xMFPerspective->set_sensitive( m_xCbxPerspective->get_active() ); + + //RightAngledAxes + uno::Reference< chart2::XDiagram > xDiagram( m_xSceneProperties, uno::UNO_QUERY ); + if (ChartTypeHelper::isSupportingRightAngledAxes(DiagramHelper::getChartTypeByIndex(xDiagram, 0))) + { + bool bRightAngledAxes = false; + m_xSceneProperties->getPropertyValue( "RightAngledAxes" ) >>= bRightAngledAxes; + m_xCbxRightAngledAxes->connect_toggled( LINK( this, ThreeD_SceneGeometry_TabPage, RightAngledAxesToggled )); + m_xCbxRightAngledAxes->set_active( bRightAngledAxes ); + RightAngledAxesToggled(*m_xCbxRightAngledAxes); + } + else + { + m_xCbxRightAngledAxes->set_sensitive(false); + } +} + +ThreeD_SceneGeometry_TabPage::~ThreeD_SceneGeometry_TabPage() +{ +} + +void ThreeD_SceneGeometry_TabPage::commitPendingChanges() +{ + ControllerLockHelperGuard aGuard( m_rControllerLockHelper ); + + if( m_bAngleChangePending ) + applyAnglesToModel(); + if( m_bPerspectiveChangePending ) + applyPerspectiveToModel(); +} + +void ThreeD_SceneGeometry_TabPage::applyAnglesToModel() +{ + ControllerLockHelperGuard aGuard( m_rControllerLockHelper ); + + double fXAngle = 0.0, fYAngle = 0.0, fZAngle = 0.0; + + if (m_xMFZRotation->get_sensitive()) + m_nZRotation = m_xMFZRotation->get_value(FieldUnit::DEGREE); + + fXAngle = double(m_nXRotation)/pow(10.0,m_xMFXRotation->get_digits()); + fYAngle = double(-1.0*m_nYRotation)/pow(10.0,m_xMFYRotation->get_digits()); + fZAngle = double(-1.0*m_nZRotation)/pow(10.0,m_xMFZRotation->get_digits()); + + fXAngle = basegfx::deg2rad(fXAngle); + fYAngle = basegfx::deg2rad(fYAngle); + fZAngle = basegfx::deg2rad(fZAngle); + + ThreeDHelper::setRotationAngleToDiagram( m_xSceneProperties, fXAngle, fYAngle, fZAngle ); + + m_bAngleChangePending = false; + m_aAngleTimer.Stop(); +} + +IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, AngleEdited, weld::MetricSpinButton&, void) +{ + m_nXRotation = m_xMFXRotation->get_value(FieldUnit::DEGREE); + m_nYRotation = m_xMFYRotation->get_value(FieldUnit::DEGREE); + + m_bAngleChangePending = true; + + m_aAngleTimer.Start(); +} + +IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, AngleChanged, Timer *, void) +{ + applyAnglesToModel(); +} + +void ThreeD_SceneGeometry_TabPage::applyPerspectiveToModel() +{ + ControllerLockHelperGuard aGuard( m_rControllerLockHelper ); + + drawing::ProjectionMode aMode = m_xCbxPerspective->get_active() + ? drawing::ProjectionMode_PERSPECTIVE + : drawing::ProjectionMode_PARALLEL; + + try + { + m_xSceneProperties->setPropertyValue( "D3DScenePerspective" , uno::Any( aMode )); + m_xSceneProperties->setPropertyValue( "Perspective" , uno::Any( static_cast<sal_Int32>(m_xMFPerspective->get_value(FieldUnit::PERCENT)) )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + m_bPerspectiveChangePending = false; + m_aPerspectiveTimer.Stop(); +} + +IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, PerspectiveEdited, weld::MetricSpinButton&, void) +{ + m_bPerspectiveChangePending = true; + m_aPerspectiveTimer.Start(); +} + +IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, PerspectiveChanged, Timer *, void) +{ + applyPerspectiveToModel(); +} + +IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, PerspectiveToggled, weld::ToggleButton&, void) +{ + m_xMFPerspective->set_sensitive(m_xCbxPerspective->get_active()); + applyPerspectiveToModel(); +} + +IMPL_LINK_NOARG(ThreeD_SceneGeometry_TabPage, RightAngledAxesToggled, weld::ToggleButton&, void) +{ + ControllerLockHelperGuard aGuard( m_rControllerLockHelper ); + + bool bEnableZ = !m_xCbxRightAngledAxes->get_active(); + m_xFtZRotation->set_sensitive( bEnableZ ); + m_xMFZRotation->set_sensitive( bEnableZ ); + if (!bEnableZ) + { + m_nXRotation = m_xMFXRotation->get_value(FieldUnit::DEGREE); + m_nYRotation = m_xMFYRotation->get_value(FieldUnit::DEGREE); + m_nZRotation = m_xMFZRotation->get_value(FieldUnit::DEGREE); + + m_xMFXRotation->set_value(static_cast<sal_Int64>(ThreeDHelper::getValueClippedToRange(static_cast<double>(m_nXRotation), ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes())), FieldUnit::DEGREE); + m_xMFYRotation->set_value(static_cast<sal_Int64>(ThreeDHelper::getValueClippedToRange(static_cast<double>(m_nYRotation), ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes())), FieldUnit::DEGREE); + m_xMFZRotation->set_text(""); + + lcl_SetMetricFieldLimits( *m_xMFXRotation, static_cast<sal_Int64>(ThreeDHelper::getXDegreeAngleLimitForRightAngledAxes())); + lcl_SetMetricFieldLimits( *m_xMFYRotation, static_cast<sal_Int64>(ThreeDHelper::getYDegreeAngleLimitForRightAngledAxes())); + } + else + { + lcl_SetMetricFieldLimits( *m_xMFXRotation, 180 ); + lcl_SetMetricFieldLimits( *m_xMFYRotation, 180 ); + + m_xMFXRotation->set_value(m_nXRotation, FieldUnit::DEGREE); + m_xMFYRotation->set_value(m_nYRotation, FieldUnit::DEGREE); + m_xMFZRotation->set_value(m_nZRotation, FieldUnit::DEGREE); + } + + ThreeDHelper::switchRightAngledAxes( m_xSceneProperties, m_xCbxRightAngledAxes->get_active() ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx new file mode 100644 index 000000000..21597d382 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneGeometry.hxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEGEOMETRY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEGEOMETRY_HXX + +#include <vcl/timer.hxx> +#include <vcl/weld.hxx> + +namespace com::sun::star::beans { class XPropertySet; } +namespace chart { class ControllerLockHelper; } + +namespace chart +{ + +class ThreeD_SceneGeometry_TabPage +{ +public: + ThreeD_SceneGeometry_TabPage(weld::Container* pWindow, + const css::uno::Reference< css::beans::XPropertySet > & xSceneProperties, + ControllerLockHelper & rControllerLockHelper); + ~ThreeD_SceneGeometry_TabPage(); + + // has to be called in case the dialog was closed with OK + void commitPendingChanges(); + + // is called by timer to apply changes to model + DECL_LINK( AngleChanged, Timer *, void); + // is called immediately when a field changes + DECL_LINK( AngleEdited, weld::MetricSpinButton&, void ); + + // is called by timer to apply changes to model + DECL_LINK( PerspectiveChanged, Timer *, void); + // is called immediately when a field changes + DECL_LINK( PerspectiveEdited, weld::MetricSpinButton&, void ); + DECL_LINK( PerspectiveToggled, weld::ToggleButton&, void ); + DECL_LINK( RightAngledAxesToggled, weld::ToggleButton&, void ); + +private: + void applyAnglesToModel(); + void applyPerspectiveToModel(); + + css::uno::Reference< css::beans::XPropertySet > m_xSceneProperties; + + Timer m_aAngleTimer; + Timer m_aPerspectiveTimer; + + //to keep old values when switching to right angled axes + sal_Int64 m_nXRotation; + sal_Int64 m_nYRotation; + sal_Int64 m_nZRotation; + + bool m_bAngleChangePending; + bool m_bPerspectiveChangePending; + + ControllerLockHelper & m_rControllerLockHelper; + + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + std::unique_ptr<weld::CheckButton> m_xCbxRightAngledAxes; + std::unique_ptr<weld::MetricSpinButton> m_xMFXRotation; + std::unique_ptr<weld::MetricSpinButton> m_xMFYRotation; + std::unique_ptr<weld::Label> m_xFtZRotation; + std::unique_ptr<weld::MetricSpinButton> m_xMFZRotation; + std::unique_ptr<weld::CheckButton> m_xCbxPerspective; + std::unique_ptr<weld::MetricSpinButton> m_xMFPerspective; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx new file mode 100644 index 000000000..e656ef206 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.cxx @@ -0,0 +1,529 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_3D_SceneIllumination.hxx" +#include <bitmaps.hlst> +#include <CommonConverters.hxx> +#include <ControllerLockGuard.hxx> + +#include <svx/colorbox.hxx> +#include <svx/float3d.hxx> +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> +#include <svtools/colrdlg.hxx> +#include <svx/svx3ditems.hxx> +#include <svx/svddef.hxx> +#include <vcl/svapp.hxx> +#include <tools/diagnose_ex.h> + +#include <com/sun/star/beans/XPropertySet.hpp> + +namespace chart +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +namespace { + +struct LightSource +{ + Color nDiffuseColor; + css::drawing::Direction3D aDirection; + bool bIsEnabled; + + LightSource() : + nDiffuseColor( 0xcccccc ), + aDirection( 1.0, 1.0, -1.0 ), + bIsEnabled( false ) + {} +}; + +} + +struct LightSourceInfo +{ + LightButton* pButton; + LightSource aLightSource; + + LightSourceInfo(); + void initButtonFromSource(); +}; + +LightSourceInfo::LightSourceInfo() + : pButton(nullptr) + , aLightSource() +{ + aLightSource.nDiffuseColor = Color(0xffffff); // white + aLightSource.aDirection = drawing::Direction3D(1,1,1); + aLightSource.bIsEnabled = false; +} + +void LightSourceInfo::initButtonFromSource() +{ + if (!pButton) + return; + pButton->switchLightOn(aLightSource.bIsEnabled); +} + +namespace +{ + OUString lcl_makeColorName(const Color& rColor) + { + OUString aStr = SvxResId(RID_SVXFLOAT3D_FIX_R) + + OUString::number(rColor.GetRed()) + + " " + + SvxResId(RID_SVXFLOAT3D_FIX_G) + + OUString::number(rColor.GetGreen()) + + " " + + SvxResId(RID_SVXFLOAT3D_FIX_B) + + OUString::number(rColor.GetBlue()); + return aStr; + } + + void lcl_selectColor(ColorListBox& rListBox, const Color& rColor) + { + rListBox.SetNoSelection(); + rListBox.SelectEntry(std::make_pair(rColor, lcl_makeColorName(rColor))); + } + + ::chart::LightSource lcl_getLightSourceFromProperties( + const uno::Reference< beans::XPropertySet > & xSceneProperties, + sal_Int32 nIndex ) + { + ::chart::LightSource aResult; + if( 0 <= nIndex && nIndex < 8 ) + { + OUString aIndex( OUString::number( nIndex + 1 )); + + try + { + xSceneProperties->getPropertyValue( "D3DSceneLightColor" + aIndex ) >>= aResult.nDiffuseColor; + xSceneProperties->getPropertyValue( "D3DSceneLightDirection" + aIndex ) >>= aResult.aDirection; + xSceneProperties->getPropertyValue( "D3DSceneLightOn" + aIndex ) >>= aResult.bIsEnabled; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + return aResult; + } + + void lcl_setLightSource( + const uno::Reference< beans::XPropertySet > & xSceneProperties, + const ::chart::LightSource & rLightSource, + sal_Int32 nIndex ) + { + if( !(0 <= nIndex && nIndex < 8) ) + return; + + OUString aIndex( OUString::number( nIndex + 1 )); + + try + { + xSceneProperties->setPropertyValue( "D3DSceneLightColor" + aIndex, + uno::makeAny( rLightSource.nDiffuseColor )); + xSceneProperties->setPropertyValue( "D3DSceneLightDirection" + aIndex, + uno::Any( rLightSource.aDirection )); + xSceneProperties->setPropertyValue( "D3DSceneLightOn" + aIndex, + uno::Any( rLightSource.bIsEnabled )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + Color lcl_getAmbientColor( + const uno::Reference< beans::XPropertySet > & xSceneProperties ) + { + sal_Int32 nResult = 0x000000; + try + { + xSceneProperties->getPropertyValue("D3DSceneAmbientColor") >>= nResult; + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + return Color( nResult ); + } + + void lcl_setAmbientColor( + const uno::Reference< beans::XPropertySet > & xSceneProperties, + const Color & rColor ) + { + try + { + xSceneProperties->setPropertyValue("D3DSceneAmbientColor", + uno::makeAny( rColor )); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } +} + +ThreeD_SceneIllumination_TabPage::ThreeD_SceneIllumination_TabPage(weld::Container* pParent, + weld::Window* pTopLevel, + const uno::Reference< beans::XPropertySet > & xSceneProperties, + const uno::Reference< frame::XModel >& xChartModel) + : m_xSceneProperties( xSceneProperties ) + , m_aTimerTriggeredControllerLock( xChartModel ) + , m_bInCommitToModel( false ) + , m_xChartModel( xChartModel ) + , m_pTopLevel(pTopLevel) + , m_xBuilder(Application::CreateBuilder(pParent, "modules/schart/ui/tp_3D_SceneIllumination.ui")) + , m_xContainer(m_xBuilder->weld_container("tp_3D_SceneIllumination")) + , m_xBtn_Light1(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_1"))) + , m_xBtn_Light2(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_2"))) + , m_xBtn_Light3(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_3"))) + , m_xBtn_Light4(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_4"))) + , m_xBtn_Light5(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_5"))) + , m_xBtn_Light6(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_6"))) + , m_xBtn_Light7(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_7"))) + , m_xBtn_Light8(new LightButton(m_xBuilder->weld_toggle_button("BTN_LIGHT_8"))) + , m_xLB_LightSource(new ColorListBox(m_xBuilder->weld_menu_button("LB_LIGHTSOURCE"), pTopLevel)) + , m_xBtn_LightSource_Color(m_xBuilder->weld_button("BTN_LIGHTSOURCE_COLOR")) + , m_xLB_AmbientLight(new ColorListBox(m_xBuilder->weld_menu_button("LB_AMBIENTLIGHT"), pTopLevel)) + , m_xBtn_AmbientLight_Color(m_xBuilder->weld_button("BTN_AMBIENT_COLOR")) + , m_xHoriScale(m_xBuilder->weld_scale("hori")) + , m_xVertScale(m_xBuilder->weld_scale("vert")) + , m_xBtn_Corner(m_xBuilder->weld_button("corner")) + , m_xPreview(new Svx3DLightControl) + , m_xPreviewWnd(new weld::CustomWeld(*m_xBuilder, "CTL_LIGHT_PREVIEW", *m_xPreview)) + , m_xCtl_Preview(new SvxLightCtl3D(*m_xPreview, *m_xHoriScale, *m_xVertScale, *m_xBtn_Corner)) +{ + m_pLightSourceInfoList.reset(new LightSourceInfo[8]); + m_pLightSourceInfoList[0].pButton = m_xBtn_Light1.get(); + m_pLightSourceInfoList[1].pButton = m_xBtn_Light2.get(); + m_pLightSourceInfoList[2].pButton = m_xBtn_Light3.get(); + m_pLightSourceInfoList[3].pButton = m_xBtn_Light4.get(); + m_pLightSourceInfoList[4].pButton = m_xBtn_Light5.get(); + m_pLightSourceInfoList[5].pButton = m_xBtn_Light6.get(); + m_pLightSourceInfoList[6].pButton = m_xBtn_Light7.get(); + m_pLightSourceInfoList[7].pButton = m_xBtn_Light8.get(); + + fillControlsFromModel(nullptr); + + m_xBtn_Light1->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light2->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light3->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light4->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light5->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light6->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light7->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + m_xBtn_Light8->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl ) ); + + m_xLB_AmbientLight->SetSelectHdl( LINK( this, ThreeD_SceneIllumination_TabPage, SelectColorHdl ) ); + m_xLB_LightSource->SetSelectHdl( LINK( this, ThreeD_SceneIllumination_TabPage, SelectColorHdl ) ); + + m_xBtn_AmbientLight_Color->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ColorDialogHdl ) ); + m_xBtn_LightSource_Color->connect_clicked( LINK( this, ThreeD_SceneIllumination_TabPage, ColorDialogHdl ) ); + + m_xCtl_Preview->SetUserInteractiveChangeCallback( LINK( this, ThreeD_SceneIllumination_TabPage, PreviewChangeHdl ) ); + m_xCtl_Preview->SetUserSelectionChangeCallback( LINK( this, ThreeD_SceneIllumination_TabPage, PreviewSelectHdl ) ); + + ClickLightSourceButtonHdl(*m_xBtn_Light2->get_widget()); +} + +ThreeD_SceneIllumination_TabPage::~ThreeD_SceneIllumination_TabPage() +{ +} + +IMPL_LINK_NOARG(ThreeD_SceneIllumination_TabPage, fillControlsFromModel, void*, void) +{ + if( m_bInCommitToModel )//don't read own changes + return; + + sal_Int32 nL=0; + for( nL=0; nL<8; nL++) + m_pLightSourceInfoList[nL].aLightSource = lcl_getLightSourceFromProperties( m_xSceneProperties, nL ); + for( nL=0; nL<8; nL++) + m_pLightSourceInfoList[nL].initButtonFromSource(); + + lcl_selectColor( *m_xLB_AmbientLight, lcl_getAmbientColor( m_xSceneProperties )); + + updatePreview(); +} + +void ThreeD_SceneIllumination_TabPage::applyLightSourceToModel( sal_uInt32 nLightNumber ) +{ + ControllerLockGuardUNO aGuard( m_xChartModel ); + m_bInCommitToModel = true; + sal_Int32 nIndex( nLightNumber ); + lcl_setLightSource( m_xSceneProperties, m_pLightSourceInfoList[nIndex].aLightSource, nIndex ); + m_bInCommitToModel = false; +} + +void ThreeD_SceneIllumination_TabPage::applyLightSourcesToModel() +{ + m_aTimerTriggeredControllerLock.startTimer(); + ControllerLockGuardUNO aGuard( m_xChartModel ); + for( sal_Int32 nL=0; nL<8; nL++) + applyLightSourceToModel( nL ); + m_aTimerTriggeredControllerLock.startTimer(); +} + +IMPL_LINK_NOARG(ThreeD_SceneIllumination_TabPage, PreviewChangeHdl, SvxLightCtl3D*, void) +{ + m_aTimerTriggeredControllerLock.startTimer(); + + //update m_pLightSourceInfoList from preview + const SfxItemSet a3DLightAttributes(m_xCtl_Preview->GetSvx3DLightControl().Get3DAttributes()); + LightSourceInfo* pInfo = &m_pLightSourceInfoList[0]; + + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_1).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_1).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_1).GetValue()); + + pInfo = &m_pLightSourceInfoList[1]; + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_2).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_2).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_2).GetValue()); + + pInfo = &m_pLightSourceInfoList[2]; + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_3).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_3).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_3).GetValue()); + + pInfo = &m_pLightSourceInfoList[3]; + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_4).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_4).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_4).GetValue()); + + pInfo = &m_pLightSourceInfoList[4]; + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_5).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_5).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_5).GetValue()); + + pInfo = &m_pLightSourceInfoList[5]; + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_6).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_6).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_6).GetValue()); + + pInfo = &m_pLightSourceInfoList[6]; + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_7).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_7).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_7).GetValue()); + + pInfo = &m_pLightSourceInfoList[7]; + pInfo->aLightSource.nDiffuseColor = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTCOLOR_8).GetValue(); + pInfo->aLightSource.bIsEnabled = a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTON_8).GetValue(); + pInfo->aLightSource.aDirection = B3DVectorToDirection3D(a3DLightAttributes.Get(SDRATTR_3DSCENE_LIGHTDIRECTION_8).GetValue()); + + applyLightSourcesToModel(); +} + +IMPL_LINK_NOARG(ThreeD_SceneIllumination_TabPage, PreviewSelectHdl, SvxLightCtl3D*, void) +{ + sal_uInt32 nLightNumber = m_xCtl_Preview->GetSvx3DLightControl().GetSelectedLight(); + if(nLightNumber<8) + { + LightButton* pButton = m_pLightSourceInfoList[nLightNumber].pButton; + if(!pButton->get_active()) + ClickLightSourceButtonHdl(*pButton->get_widget()); + + applyLightSourcesToModel(); + } +} + +IMPL_LINK( ThreeD_SceneIllumination_TabPage, ColorDialogHdl, weld::Button&, rButton, void ) +{ + bool bIsAmbientLight = (&rButton == m_xBtn_AmbientLight_Color.get()); + ColorListBox* pListBox = bIsAmbientLight ? m_xLB_AmbientLight.get() : m_xLB_LightSource.get(); + + SvColorDialog aColorDlg; + aColorDlg.SetColor( pListBox->GetSelectEntryColor() ); + if( aColorDlg.Execute(m_pTopLevel) != RET_OK ) + return; + + Color aColor( aColorDlg.GetColor()); + lcl_selectColor( *pListBox, aColor ); + if( bIsAmbientLight ) + { + m_bInCommitToModel = true; + lcl_setAmbientColor( m_xSceneProperties, aColor ); + m_bInCommitToModel = false; + } + else + { + //get active lightsource: + LightSourceInfo* pInfo = nullptr; + sal_Int32 nL=0; + for( nL=0; nL<8; nL++) + { + pInfo = &m_pLightSourceInfoList[nL]; + if(pInfo->pButton->get_active()) + break; + pInfo = nullptr; + } + if(pInfo) + applyLightSourceToModel( nL ); + } + SelectColorHdl( *pListBox ); +} + +IMPL_LINK( ThreeD_SceneIllumination_TabPage, SelectColorHdl, ColorListBox&, rBox, void ) +{ + ColorListBox* pListBox = &rBox; + if (pListBox == m_xLB_AmbientLight.get()) + { + m_bInCommitToModel = true; + lcl_setAmbientColor( m_xSceneProperties, pListBox->GetSelectEntryColor()); + m_bInCommitToModel = false; + } + else if (pListBox == m_xLB_LightSource.get()) + { + //get active lightsource: + LightSourceInfo* pInfo = nullptr; + sal_Int32 nL=0; + for( nL=0; nL<8; nL++) + { + pInfo = &m_pLightSourceInfoList[nL]; + if (pInfo->pButton->get_active()) + break; + pInfo = nullptr; + } + if(pInfo) + { + pInfo->aLightSource.nDiffuseColor = pListBox->GetSelectEntryColor(); + applyLightSourceToModel( nL ); + } + } + updatePreview(); +} + +IMPL_LINK(ThreeD_SceneIllumination_TabPage, ClickLightSourceButtonHdl, weld::Button&, rBtn, void) +{ + LightButton* pButton = nullptr; + LightSourceInfo* pInfo = nullptr; + sal_Int32 nL=0; + for( nL=0; nL<8; nL++) + { + if (m_pLightSourceInfoList[nL].pButton->get_widget() == &rBtn) + { + pButton = m_pLightSourceInfoList[nL].pButton; + pInfo = &m_pLightSourceInfoList[nL]; + break; + } + } + + assert(pInfo); + + bool bIsChecked = pInfo->pButton->get_prev_active(); + + ControllerLockGuardUNO aGuard( m_xChartModel ); + for( nL=0; nL<8; nL++) + { + LightButton* pLightButton = m_pLightSourceInfoList[nL].pButton; + if (pLightButton == pButton) + { + pLightButton->set_active(true); + if (!pLightButton->get_widget()->has_focus()) + pLightButton->get_widget()->grab_focus(); + m_pLightSourceInfoList[nL].pButton->set_prev_active(true); + } + else + { + pLightButton->set_active(false); + m_pLightSourceInfoList[nL].pButton->set_prev_active(false); + } + } + + //update light button + if (bIsChecked) + { + pButton->switchLightOn(!pButton->isLightOn()); + pInfo->aLightSource.bIsEnabled=pButton->isLightOn(); + applyLightSourceToModel( nL ); + } + + //update color list box + lcl_selectColor( *m_xLB_LightSource, pInfo->aLightSource.nDiffuseColor ); + updatePreview(); +} + +void ThreeD_SceneIllumination_TabPage::updatePreview() +{ + SfxItemSet aItemSet(m_xCtl_Preview->GetSvx3DLightControl().Get3DAttributes()); + LightSourceInfo* pInfo = &m_pLightSourceInfoList[0]; + + // AmbientColor + aItemSet.Put(makeSvx3DAmbientcolorItem(m_xLB_AmbientLight->GetSelectEntryColor())); + + aItemSet.Put(makeSvx3DLightcolor1Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff1Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection1Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + pInfo = &m_pLightSourceInfoList[1]; + aItemSet.Put(makeSvx3DLightcolor2Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff2Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection2Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + pInfo = &m_pLightSourceInfoList[2]; + aItemSet.Put(makeSvx3DLightcolor3Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff3Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection3Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + pInfo = &m_pLightSourceInfoList[3]; + aItemSet.Put(makeSvx3DLightcolor4Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff4Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection4Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + pInfo = &m_pLightSourceInfoList[4]; + aItemSet.Put(makeSvx3DLightcolor5Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff5Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection5Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + pInfo = &m_pLightSourceInfoList[5]; + aItemSet.Put(makeSvx3DLightcolor6Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff6Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection6Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + pInfo = &m_pLightSourceInfoList[6]; + aItemSet.Put(makeSvx3DLightcolor7Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff7Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection7Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + pInfo = &m_pLightSourceInfoList[7]; + aItemSet.Put(makeSvx3DLightcolor8Item(pInfo->aLightSource.nDiffuseColor)); + aItemSet.Put(makeSvx3DLightOnOff8Item(pInfo->aLightSource.bIsEnabled)); + aItemSet.Put(makeSvx3DLightDirection8Item(Direction3DToB3DVector(pInfo->aLightSource.aDirection))); + + // set lights and ambient light + m_xCtl_Preview->GetSvx3DLightControl().Set3DAttributes(aItemSet); + + // select light + for(sal_uInt32 a(0); a < 8; a++) + { + if (m_pLightSourceInfoList[a].pButton->get_active()) + { + m_xCtl_Preview->GetSvx3DLightControl().SelectLight(a); + m_xCtl_Preview->CheckSelection(); + break; + } + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx new file mode 100644 index 000000000..27606079e --- /dev/null +++ b/chart2/source/controller/dialogs/tp_3D_SceneIllumination.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEILLUMINATION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_3D_SCENEILLUMINATION_HXX + +#include <TimerTriggeredControllerLock.hxx> +#include <vcl/weld.hxx> +#include <svx/dlgctl3d.hxx> + +namespace com::sun::star::beans { class XPropertySet; } + +class ColorListBox; +class LightButton; + +namespace chart +{ + +struct LightSourceInfo; + +class ThreeD_SceneIllumination_TabPage +{ +public: + ThreeD_SceneIllumination_TabPage( + weld::Container* pParent, weld::Window* pTopLevel, + const css::uno::Reference< css::beans::XPropertySet > & xSceneProperties, + const css::uno::Reference< css::frame::XModel >& xChartModel ); + ~ThreeD_SceneIllumination_TabPage(); + +private: + DECL_LINK( ClickLightSourceButtonHdl, weld::Button&, void ); + DECL_LINK( SelectColorHdl, ColorListBox&, void ); + DECL_LINK( ColorDialogHdl, weld::Button&, void ); + DECL_LINK( PreviewChangeHdl, SvxLightCtl3D*, void ); + DECL_LINK( PreviewSelectHdl, SvxLightCtl3D*, void ); + + void updatePreview(); + +private: + DECL_LINK(fillControlsFromModel, void *, void); + + void applyLightSourceToModel( sal_uInt32 nLightNumber ); + void applyLightSourcesToModel(); + + std::unique_ptr<LightSourceInfo[]> m_pLightSourceInfoList; + + css::uno::Reference< css::beans::XPropertySet > m_xSceneProperties; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + bool m_bInCommitToModel; + + css::uno::Reference<css::frame::XModel> m_xChartModel; + + weld::Window* m_pTopLevel; + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + std::unique_ptr<LightButton> m_xBtn_Light1; + std::unique_ptr<LightButton> m_xBtn_Light2; + std::unique_ptr<LightButton> m_xBtn_Light3; + std::unique_ptr<LightButton> m_xBtn_Light4; + std::unique_ptr<LightButton> m_xBtn_Light5; + std::unique_ptr<LightButton> m_xBtn_Light6; + std::unique_ptr<LightButton> m_xBtn_Light7; + std::unique_ptr<LightButton> m_xBtn_Light8; + std::unique_ptr<ColorListBox> m_xLB_LightSource; + std::unique_ptr<weld::Button> m_xBtn_LightSource_Color; + std::unique_ptr<ColorListBox> m_xLB_AmbientLight; + std::unique_ptr<weld::Button> m_xBtn_AmbientLight_Color; + std::unique_ptr<weld::Scale> m_xHoriScale; + std::unique_ptr<weld::Scale> m_xVertScale; + std::unique_ptr<weld::Button> m_xBtn_Corner; + std::unique_ptr<Svx3DLightControl> m_xPreview; + std::unique_ptr<weld::CustomWeld> m_xPreviewWnd; + std::unique_ptr<SvxLightCtl3D> m_xCtl_Preview; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_AxisLabel.cxx b/chart2/source/controller/dialogs/tp_AxisLabel.cxx new file mode 100644 index 000000000..1eaaa4063 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisLabel.cxx @@ -0,0 +1,303 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_AxisLabel.hxx" + +#include <chartview/ChartSfxItemIds.hxx> +#include <TextDirectionListBox.hxx> + +#include <svx/chrtitem.hxx> +#include <svl/intitem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/frmdiritem.hxx> + +namespace chart +{ + +SchAxisLabelTabPage::SchAxisLabelTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_axisLabel.ui", "AxisLabelTabPage", &rInAttrs) + , m_bShowStaggeringControls( true ) + , m_nInitialDegrees( 0 ) + , m_bHasInitialDegrees( true ) + , m_bInitialStacking( false ) + , m_bHasInitialStacking( true ) + , m_bComplexCategories( false ) + , m_xCbShowDescription(m_xBuilder->weld_check_button("showlabelsCB")) + , m_xFlOrder(m_xBuilder->weld_label("orderL")) + , m_xRbSideBySide(m_xBuilder->weld_radio_button("tile")) + , m_xRbUpDown(m_xBuilder->weld_radio_button("odd")) + , m_xRbDownUp(m_xBuilder->weld_radio_button("even")) + , m_xRbAuto(m_xBuilder->weld_radio_button("auto")) + , m_xFlTextFlow(m_xBuilder->weld_label("textflowL")) + , m_xCbTextOverlap(m_xBuilder->weld_check_button("overlapCB")) + , m_xCbTextBreak(m_xBuilder->weld_check_button("breakCB")) + , m_xFtABCD(m_xBuilder->weld_label("labelABCD")) + , m_xFlOrient(m_xBuilder->weld_label("labelTextOrient")) + , m_xFtRotate(m_xBuilder->weld_label("degreeL")) + , m_xNfRotate(m_xBuilder->weld_metric_spin_button("OrientDegree", FieldUnit::DEGREE)) + , m_xCbStacked(m_xBuilder->weld_check_button("stackedCB")) + , m_xFtTextDirection(m_xBuilder->weld_label("textdirL")) + , m_xLbTextDirection(new TextDirectionListBox(m_xBuilder->weld_combo_box("textdirLB"))) + , m_xCtrlDial(new svx::DialControl) + , m_xCtrlDialWin(new weld::CustomWeld(*m_xBuilder, "dialCtrl", *m_xCtrlDial)) +{ + m_xCtrlDial->SetText(m_xFtABCD->get_label()); + m_xCtrlDial->SetLinkedField(m_xNfRotate.get()); + m_xCtrlDialWin->set_sensitive(true); + m_xNfRotate->set_sensitive(true); + m_xCbStacked->set_sensitive(true); + m_xFtRotate->set_sensitive(true); + + m_xCbStacked->connect_toggled(LINK(this, SchAxisLabelTabPage, StackedToggleHdl)); + m_xCbShowDescription->connect_toggled(LINK(this, SchAxisLabelTabPage, ToggleShowLabel)); +} + +SchAxisLabelTabPage::~SchAxisLabelTabPage() +{ + m_xCtrlDialWin.reset(); + m_xCtrlDial.reset(); + m_xLbTextDirection.reset(); +} + +std::unique_ptr<SfxTabPage> SchAxisLabelTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrs) +{ + return std::make_unique<SchAxisLabelTabPage>(pPage, pController, *rAttrs); +} + +bool SchAxisLabelTabPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + bool bStacked = false; + if (m_xCbStacked->get_state() != TRISTATE_INDET ) + { + bStacked = m_xCbStacked->get_state() == TRISTATE_TRUE; + if( !m_bHasInitialStacking || (bStacked != m_bInitialStacking) ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_TEXT_STACKED, bStacked ) ); + } + + if( m_xCtrlDial->HasRotation() ) + { + sal_Int32 nDegrees = bStacked ? 0 : m_xCtrlDial->GetRotation(); + if( !m_bHasInitialDegrees || (nDegrees != m_nInitialDegrees) ) + rOutAttrs->Put( SfxInt32Item( SCHATTR_TEXT_DEGREES, nDegrees ) ); + } + + if( m_bShowStaggeringControls ) + { + SvxChartTextOrder eOrder = SvxChartTextOrder::SideBySide; + bool bRadioButtonChecked = true; + + if( m_xRbUpDown->get_active()) + eOrder = SvxChartTextOrder::UpDown; + else if( m_xRbDownUp->get_active()) + eOrder = SvxChartTextOrder::DownUp; + else if( m_xRbAuto->get_active()) + eOrder = SvxChartTextOrder::Auto; + else if( m_xRbSideBySide->get_active()) + eOrder = SvxChartTextOrder::SideBySide; + else + bRadioButtonChecked = false; + + if( bRadioButtonChecked ) + rOutAttrs->Put( SvxChartTextOrderItem( eOrder, SCHATTR_AXIS_LABEL_ORDER )); + } + + if( m_xCbTextOverlap->get_state() != TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_AXIS_LABEL_OVERLAP, m_xCbTextOverlap->get_active() ) ); + if( m_xCbTextBreak->get_state() != TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_AXIS_LABEL_BREAK, m_xCbTextBreak->get_active() ) ); + if( m_xCbShowDescription->get_state() != TRISTATE_INDET ) + rOutAttrs->Put( SfxBoolItem( SCHATTR_AXIS_SHOWDESCR, m_xCbShowDescription->get_active() ) ); + + if (m_xLbTextDirection->get_active() != -1) + rOutAttrs->Put( SvxFrameDirectionItem( m_xLbTextDirection->get_active_id(), EE_PARA_WRITINGDIR ) ); + + return true; +} + +void SchAxisLabelTabPage::Reset( const SfxItemSet* rInAttrs ) +{ + const SfxPoolItem* pPoolItem = nullptr; + + // show description + SfxItemState aState = rInAttrs->GetItemState( SCHATTR_AXIS_SHOWDESCR, false, &pPoolItem ); + if( aState == SfxItemState::DONTCARE ) + { + m_xCbShowDescription->set_state( TRISTATE_INDET ); + } + else + { + bool bCheck = false; + if( aState == SfxItemState::SET ) + bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCbShowDescription->set_active( bCheck ); + + if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET ) + m_xCbShowDescription->hide(); + } + + // Rotation as orient item or in degrees ---------- + + // check new degree item + m_nInitialDegrees = 0; + aState = rInAttrs->GetItemState( SCHATTR_TEXT_DEGREES, false, &pPoolItem ); + if( aState == SfxItemState::SET ) + m_nInitialDegrees = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + + m_bHasInitialDegrees = aState != SfxItemState::DONTCARE; + if( m_bHasInitialDegrees ) + m_xCtrlDial->SetRotation( m_nInitialDegrees ); + else + m_xCtrlDial->SetNoRotation(); + + // check stacked item + m_bInitialStacking = false; + aState = rInAttrs->GetItemState( SCHATTR_TEXT_STACKED, false, &pPoolItem ); + if( aState == SfxItemState::SET ) + m_bInitialStacking = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + + m_bHasInitialStacking = aState != SfxItemState::DONTCARE; + if( m_bHasInitialDegrees ) + m_xCbStacked->set_state(m_bInitialStacking ? TRISTATE_TRUE : TRISTATE_FALSE); + else + m_xCbStacked->set_state(TRISTATE_INDET); + StackedToggleHdl(*m_xCbStacked); + + if( rInAttrs->GetItemState( EE_PARA_WRITINGDIR, true, &pPoolItem ) == SfxItemState::SET ) + m_xLbTextDirection->set_active_id( static_cast<const SvxFrameDirectionItem*>(pPoolItem)->GetValue() ); + + // Text overlap ---------- + aState = rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_OVERLAP, false, &pPoolItem ); + if( aState == SfxItemState::DONTCARE ) + { + m_xCbTextOverlap->set_state( TRISTATE_INDET ); + } + else + { + bool bCheck = false; + if( aState == SfxItemState::SET ) + bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCbTextOverlap->set_active( bCheck ); + + if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET ) + m_xCbTextOverlap->hide(); + } + + // text break ---------- + aState = rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_BREAK, false, &pPoolItem ); + if( aState == SfxItemState::DONTCARE ) + { + m_xCbTextBreak->set_state( TRISTATE_INDET ); + } + else + { + bool bCheck = false; + if( aState == SfxItemState::SET ) + bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCbTextBreak->set_active( bCheck ); + + if( aState != SfxItemState::DEFAULT && aState != SfxItemState::SET ) + { + m_xCbTextBreak->hide(); + if( ! m_xCbTextOverlap->get_visible() ) + m_xFlTextFlow->hide(); + } + } + + // text order ---------- + if( m_bShowStaggeringControls ) + { + aState = rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_ORDER, false, &pPoolItem ); + if( aState == SfxItemState::SET ) + { + SvxChartTextOrder eOrder = static_cast< const SvxChartTextOrderItem * >( pPoolItem )->GetValue(); + + switch( eOrder ) + { + case SvxChartTextOrder::SideBySide: + m_xRbSideBySide->set_active(true); + break; + case SvxChartTextOrder::UpDown: + m_xRbUpDown->set_active(true); + break; + case SvxChartTextOrder::DownUp: + m_xRbDownUp->set_active(true); + break; + case SvxChartTextOrder::Auto: + m_xRbAuto->set_active(true); + break; + } + } + } + + ToggleShowLabel(*m_xCbShowDescription); +} + +void SchAxisLabelTabPage::ShowStaggeringControls( bool bShowStaggeringControls ) +{ + m_bShowStaggeringControls = bShowStaggeringControls; + + if( !m_bShowStaggeringControls ) + { + m_xRbSideBySide->hide(); + m_xRbUpDown->hide(); + m_xRbDownUp->hide(); + m_xRbAuto->hide(); + m_xFlOrder->hide(); + } +} + +void SchAxisLabelTabPage::SetComplexCategories( bool bComplexCategories ) +{ + m_bComplexCategories = bComplexCategories; +} + +// event handling routines + +IMPL_LINK_NOARG(SchAxisLabelTabPage, StackedToggleHdl, weld::ToggleButton&, void) +{ + bool bActive = m_xCbStacked->get_active() && m_xCbStacked->get_sensitive(); + m_xNfRotate->set_sensitive(!bActive); + m_xCtrlDialWin->set_sensitive(!bActive); + m_xCtrlDial->StyleUpdated(); + m_xFtRotate->set_sensitive(!bActive); +} + +IMPL_LINK_NOARG(SchAxisLabelTabPage, ToggleShowLabel, weld::ToggleButton&, void) +{ + bool bEnable = ( m_xCbShowDescription->get_state() != TRISTATE_FALSE ); + + m_xCbStacked->set_sensitive(bEnable); + StackedToggleHdl(*m_xCbStacked); + + m_xFlOrder->set_sensitive( bEnable ); + m_xRbSideBySide->set_sensitive( bEnable ); + m_xRbUpDown->set_sensitive( bEnable ); + m_xRbDownUp->set_sensitive( bEnable ); + m_xRbAuto->set_sensitive( bEnable ); + + m_xFlTextFlow->set_sensitive( bEnable ); + m_xCbTextOverlap->set_sensitive( bEnable && !m_bComplexCategories ); + m_xCbTextBreak->set_sensitive( bEnable ); + + m_xFtTextDirection->set_sensitive( bEnable ); + m_xLbTextDirection->set_sensitive( bEnable ); +} +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_AxisLabel.hxx b/chart2/source/controller/dialogs/tp_AxisLabel.hxx new file mode 100644 index 000000000..0e7b9a097 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisLabel.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISLABEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISLABEL_HXX + +#include <sfx2/tabdlg.hxx> +#include <svx/dialcontrol.hxx> + +namespace chart { class TextDirectionListBox; } +namespace weld { + class CheckButton; + class CustomWeld; + class Label; + class RadioButton; + class SpinButton; + class ToggleButton; +} + +namespace chart +{ + +class SchAxisLabelTabPage : public SfxTabPage +{ +private: + bool m_bShowStaggeringControls; + + sal_Int32 m_nInitialDegrees; + bool m_bHasInitialDegrees; /// false = DialControl in tristate + bool m_bInitialStacking; + bool m_bHasInitialStacking; /// false = checkbox in tristate + bool m_bComplexCategories; + + std::unique_ptr<weld::CheckButton> m_xCbShowDescription; + std::unique_ptr<weld::Label> m_xFlOrder; + std::unique_ptr<weld::RadioButton> m_xRbSideBySide; + std::unique_ptr<weld::RadioButton> m_xRbUpDown; + std::unique_ptr<weld::RadioButton> m_xRbDownUp; + std::unique_ptr<weld::RadioButton> m_xRbAuto; + std::unique_ptr<weld::Label> m_xFlTextFlow; + std::unique_ptr<weld::CheckButton> m_xCbTextOverlap; + std::unique_ptr<weld::CheckButton> m_xCbTextBreak; + std::unique_ptr<weld::Label> m_xFtABCD; + std::unique_ptr<weld::Label> m_xFlOrient; + std::unique_ptr<weld::Label> m_xFtRotate; + std::unique_ptr<weld::MetricSpinButton> m_xNfRotate; + std::unique_ptr<weld::CheckButton> m_xCbStacked; + std::unique_ptr<weld::Label> m_xFtTextDirection; + std::unique_ptr<TextDirectionListBox> m_xLbTextDirection; + std::unique_ptr<svx::DialControl> m_xCtrlDial; + std::unique_ptr<weld::CustomWeld> m_xCtrlDialWin; + + DECL_LINK(StackedToggleHdl, weld::ToggleButton&, void); + DECL_LINK(ToggleShowLabel, weld::ToggleButton&, void); + +public: + SchAxisLabelTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SchAxisLabelTabPage() override; + + static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs ); + virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override; + virtual void Reset( const SfxItemSet* rInAttrs ) override; + + void ShowStaggeringControls( bool bShowStaggeringControls ); + void SetComplexCategories( bool bComplexCategories ); +}; +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_AxisPositions.cxx b/chart2/source/controller/dialogs/tp_AxisPositions.cxx new file mode 100644 index 000000000..89b8c3899 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisPositions.cxx @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_AxisPositions.hxx" + +#include <chartview/ChartSfxItemIds.hxx> +#include <AxisHelper.hxx> + +#include <rtl/math.hxx> +#include <svx/chrtitem.hxx> +#include <svl/intitem.hxx> + +using namespace ::com::sun::star; + +namespace chart +{ + +AxisPositionsTabPage::AxisPositionsTabPage(weld::Container* pPage, weld::DialogController* pController,const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_AxisPositions.ui", "tp_AxisPositions", &rInAttrs) + , m_pNumFormatter(nullptr) + , m_bCrossingAxisIsCategoryAxis(false) + , m_aCategories() + , m_bSupportAxisPositioning(false) + , m_bSupportCategoryPositioning(false) + , m_xFL_AxisLine(m_xBuilder->weld_frame("FL_AXIS_LINE")) + , m_xLB_CrossesAt(m_xBuilder->weld_combo_box("LB_CROSSES_OTHER_AXIS_AT")) + , m_xED_CrossesAt(m_xBuilder->weld_formatted_spin_button("EDT_CROSSES_OTHER_AXIS_AT")) + , m_xED_CrossesAtCategory(m_xBuilder->weld_combo_box( "EDT_CROSSES_OTHER_AXIS_AT_CATEGORY")) + , m_xCB_AxisBetweenCategories(m_xBuilder->weld_check_button("CB_AXIS_BETWEEN_CATEGORIES")) + , m_xFL_Position(m_xBuilder->weld_frame("FL_POSITION")) + , m_xRB_On(m_xBuilder->weld_radio_button("RB_ON")) + , m_xRB_Between(m_xBuilder->weld_radio_button("RB_BETWEEN")) + , m_xFL_Labels(m_xBuilder->weld_frame("FL_LABELS")) + , m_xLB_PlaceLabels(m_xBuilder->weld_combo_box("LB_PLACE_LABELS")) + , m_xED_LabelDistance(m_xBuilder->weld_formatted_spin_button("EDT_AXIS_LABEL_DISTANCE")) + , m_xCB_TicksInner(m_xBuilder->weld_check_button("CB_TICKS_INNER")) + , m_xCB_TicksOuter(m_xBuilder->weld_check_button("CB_TICKS_OUTER")) + , m_xCB_MinorInner(m_xBuilder->weld_check_button("CB_MINOR_INNER")) + , m_xCB_MinorOuter(m_xBuilder->weld_check_button("CB_MINOR_OUTER")) + , m_xBxPlaceTicks(m_xBuilder->weld_widget("boxPLACE_TICKS")) + , m_xLB_PlaceTicks(m_xBuilder->weld_combo_box("LB_PLACE_TICKS")) +{ + m_xLB_CrossesAt->connect_changed(LINK(this, AxisPositionsTabPage, CrossesAtSelectHdl)); + m_xLB_PlaceLabels->connect_changed(LINK(this, AxisPositionsTabPage, PlaceLabelsSelectHdl)); + + const double nMin = static_cast<double>(SAL_MIN_INT64); + const double nMax = static_cast<double>(SAL_MAX_INT64); + m_xED_CrossesAt->set_range(nMin, nMax); + m_xED_LabelDistance->set_range(nMin, nMax); +} + +AxisPositionsTabPage::~AxisPositionsTabPage() +{ +} + +std::unique_ptr<SfxTabPage> AxisPositionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<AxisPositionsTabPage>(pPage, pController, *rOutAttrs); +} + +bool AxisPositionsTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + // axis line + sal_Int32 nPos = m_xLB_CrossesAt->get_active(); + rOutAttrs->Put( SfxInt32Item( SCHATTR_AXIS_POSITION, nPos+1 )); + if( nPos==2 ) + { + double fCrossover = m_xED_CrossesAt->get_value(); + if( m_bCrossingAxisIsCategoryAxis ) + fCrossover = m_xED_CrossesAtCategory->get_active()+1; + rOutAttrs->Put(SvxDoubleItem(fCrossover,SCHATTR_AXIS_POSITION_VALUE)); + } + + // shifted category position + if (m_xFL_Position->get_visible()) + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION, m_xRB_Between->get_active())); + + // labels + sal_Int32 nLabelPos = m_xLB_PlaceLabels->get_active(); + if (nLabelPos != -1) + rOutAttrs->Put( SfxInt32Item( SCHATTR_AXIS_LABEL_POSITION, nLabelPos )); + + // tick marks + long nTicks=0; + long nMinorTicks=0; + + if(m_xCB_MinorInner->get_active()) + nMinorTicks|=CHAXIS_MARK_INNER; + if(m_xCB_MinorOuter->get_active()) + nMinorTicks|=CHAXIS_MARK_OUTER; + if(m_xCB_TicksInner->get_active()) + nTicks|=CHAXIS_MARK_INNER; + if(m_xCB_TicksOuter->get_active()) + nTicks|=CHAXIS_MARK_OUTER; + + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_TICKS,nTicks)); + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_HELPTICKS,nMinorTicks)); + + sal_Int32 nMarkPos = m_xLB_PlaceTicks->get_active(); + if (nMarkPos != -1) + rOutAttrs->Put( SfxInt32Item( SCHATTR_AXIS_MARK_POSITION, nMarkPos )); + + return true; +} + +void AxisPositionsTabPage::Reset(const SfxItemSet* rInAttrs) +{ + //init and enable controls + m_xED_CrossesAt->set_visible( !m_bCrossingAxisIsCategoryAxis ); + m_xED_CrossesAtCategory->set_visible( m_bCrossingAxisIsCategoryAxis ); + if (m_bCrossingAxisIsCategoryAxis) + { + for( auto const & cat : std::as_const(m_aCategories) ) + m_xED_CrossesAtCategory->append_text(cat); + } + + if( m_xLB_CrossesAt->get_count() > 3 ) + { + if( m_bCrossingAxisIsCategoryAxis ) + m_xLB_CrossesAt->remove(2); + else + m_xLB_CrossesAt->remove(3); + } + + //fill controls + const SfxPoolItem *pPoolItem = nullptr; + + //axis line + if(rInAttrs->GetItemState(SCHATTR_AXIS_POSITION,true, &pPoolItem)== SfxItemState::SET) + { + bool bZero = false; + sal_Int32 nPos = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + if(nPos==0) + { + //switch to value + bZero = true; + nPos = 2; + } + else + nPos--; + + if( nPos < m_xLB_CrossesAt->get_count() ) + m_xLB_CrossesAt->set_active( nPos ); + CrossesAtSelectHdl( *m_xLB_CrossesAt ); + + if( rInAttrs->GetItemState(SCHATTR_AXIS_POSITION_VALUE,true, &pPoolItem)== SfxItemState::SET || bZero ) + { + double fCrossover = 0.0; + if( !bZero ) + fCrossover = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue(); + if( m_bCrossingAxisIsCategoryAxis ) + m_xED_CrossesAtCategory->set_active( static_cast<sal_uInt16>(::rtl::math::round(fCrossover-1.0)) ); + else + m_xED_CrossesAt->set_value(fCrossover); + } + else + { + m_xED_CrossesAtCategory->set_active(-1); + m_xED_CrossesAt->set_text(""); + } + } + else + { + m_xLB_CrossesAt->set_active(-1); + m_xED_CrossesAt->set_sensitive( false ); + } + + // shifted category position + if (m_bSupportCategoryPositioning && rInAttrs->GetItemState(SCHATTR_AXIS_SHIFTED_CATEGORY_POSITION, true, &pPoolItem) == SfxItemState::SET) + { + if (static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()) + m_xRB_Between->set_active(true); + else + m_xRB_On->set_active(true); + } + else + m_xFL_Position->hide(); + + // Labels + if( rInAttrs->GetItemState( SCHATTR_AXIS_LABEL_POSITION, false, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nPos = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + if( nPos < m_xLB_PlaceLabels->get_count() ) + m_xLB_PlaceLabels->set_active( nPos ); + } + else + m_xLB_PlaceLabels->set_active(-1); + PlaceLabelsSelectHdl( *m_xLB_PlaceLabels ); + + // Tick marks + long nTicks = 0, nMinorTicks = 0; + if (rInAttrs->GetItemState(SCHATTR_AXIS_TICKS,true, &pPoolItem)== SfxItemState::SET) + nTicks = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + if (rInAttrs->GetItemState(SCHATTR_AXIS_HELPTICKS,true, &pPoolItem)== SfxItemState::SET) + nMinorTicks = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + + m_xCB_TicksInner->set_active(bool(nTicks&CHAXIS_MARK_INNER)); + m_xCB_TicksOuter->set_active(bool(nTicks&CHAXIS_MARK_OUTER)); + m_xCB_MinorInner->set_active(bool(nMinorTicks&CHAXIS_MARK_INNER)); + m_xCB_MinorOuter->set_active(bool(nMinorTicks&CHAXIS_MARK_OUTER)); + + // Tick position + if( rInAttrs->GetItemState( SCHATTR_AXIS_MARK_POSITION, false, &pPoolItem ) == SfxItemState::SET ) + { + sal_Int32 nPos = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + if( nPos < m_xLB_PlaceTicks->get_count() ) + m_xLB_PlaceTicks->set_active( nPos ); + } + else + m_xLB_PlaceTicks->set_active(-1); + + if( !m_bSupportAxisPositioning ) + { + m_xFL_AxisLine->hide(); + m_xFL_Labels->hide(); + m_xBxPlaceTicks->hide(); + } + else if( !AxisHelper::isAxisPositioningEnabled() ) + { + m_xFL_AxisLine->set_sensitive(false); + m_xFL_Labels->set_sensitive(false); + m_xBxPlaceTicks->set_sensitive(false); + //todo: maybe set a special help id to all those controls + } +} + +DeactivateRC AxisPositionsTabPage::DeactivatePage(SfxItemSet* pItemSet) +{ + if( pItemSet ) + FillItemSet( pItemSet ); + + return DeactivateRC::LeavePage; +} + +void AxisPositionsTabPage::SetNumFormatter( SvNumberFormatter* pFormatter ) +{ + m_pNumFormatter = pFormatter; + m_xED_CrossesAt->set_formatter(m_pNumFormatter); + + const SfxPoolItem *pPoolItem = nullptr; + if( GetItemSet().GetItemState( SCHATTR_AXIS_CROSSING_MAIN_AXIS_NUMBERFORMAT, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_uLong nFmt = static_cast<const SfxUInt32Item*>(pPoolItem)->GetValue(); + m_xED_CrossesAt->set_format_key( nFmt ); + } +} + +void AxisPositionsTabPage::SetCrossingAxisIsCategoryAxis( bool bCrossingAxisIsCategoryAxis ) +{ + m_bCrossingAxisIsCategoryAxis = bCrossingAxisIsCategoryAxis; +} + +void AxisPositionsTabPage::SetCategories( const css::uno::Sequence< OUString >& rCategories ) +{ + m_aCategories = rCategories; +} + +void AxisPositionsTabPage::SupportAxisPositioning( bool bSupportAxisPositioning ) +{ + m_bSupportAxisPositioning = bSupportAxisPositioning; +} + +void AxisPositionsTabPage::SupportCategoryPositioning( bool bSupportCategoryPositioning ) +{ + m_bSupportCategoryPositioning = bSupportCategoryPositioning; +} + +IMPL_LINK_NOARG(AxisPositionsTabPage, CrossesAtSelectHdl, weld::ComboBox&, void) +{ + sal_Int32 nPos = m_xLB_CrossesAt->get_active(); + m_xED_CrossesAt->set_visible( (nPos==2) && !m_bCrossingAxisIsCategoryAxis ); + m_xED_CrossesAtCategory->set_visible( (nPos==2) && m_bCrossingAxisIsCategoryAxis ); + + if (m_xED_CrossesAt->get_text().isEmpty()) + m_xED_CrossesAt->set_value(0.0); + if (m_xED_CrossesAtCategory->get_active() == -1) + m_xED_CrossesAtCategory->set_active(0); + + PlaceLabelsSelectHdl(*m_xLB_PlaceLabels); +} + +IMPL_LINK_NOARG(AxisPositionsTabPage, PlaceLabelsSelectHdl, weld::ComboBox&, void) +{ + sal_Int32 nLabelPos = m_xLB_PlaceLabels->get_active(); + + bool bEnableTickmarkPlacement = (nLabelPos>1); + if( bEnableTickmarkPlacement ) + { + sal_Int32 nAxisPos = m_xLB_CrossesAt->get_active(); + if( nLabelPos-2 == nAxisPos ) + bEnableTickmarkPlacement=false; + } + m_xBxPlaceTicks->set_sensitive(bEnableTickmarkPlacement); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_AxisPositions.hxx b/chart2/source/controller/dialogs/tp_AxisPositions.hxx new file mode 100644 index 000000000..6be65c9de --- /dev/null +++ b/chart2/source/controller/dialogs/tp_AxisPositions.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISPOSITIONS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_AXISPOSITIONS_HXX + +#include <sfx2/tabdlg.hxx> + +namespace chart +{ + +class AxisPositionsTabPage : public SfxTabPage +{ +public: + AxisPositionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~AxisPositionsTabPage() override; + + static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs ); + virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override; + virtual void Reset( const SfxItemSet* rInAttrs ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pItemSet ) override; + + void SetNumFormatter( SvNumberFormatter* pFormatter ); + + void SetCrossingAxisIsCategoryAxis( bool bCrossingAxisIsCategoryAxis ); + void SetCategories( const css::uno::Sequence< OUString >& rCategories ); + + void SupportAxisPositioning( bool bSupportAxisPositioning ); + void SupportCategoryPositioning( bool bSupportCategoryPositioning ); + +private: //methods: + DECL_LINK(CrossesAtSelectHdl, weld::ComboBox&, void); + DECL_LINK(PlaceLabelsSelectHdl, weld::ComboBox&, void); + +private: //member: + SvNumberFormatter* m_pNumFormatter; + + bool m_bCrossingAxisIsCategoryAxis; + css::uno::Sequence< OUString > m_aCategories; + + bool m_bSupportAxisPositioning; + bool m_bSupportCategoryPositioning; + + std::unique_ptr<weld::Frame> m_xFL_AxisLine; + std::unique_ptr<weld::ComboBox> m_xLB_CrossesAt; + std::unique_ptr<weld::FormattedSpinButton> m_xED_CrossesAt; + std::unique_ptr<weld::ComboBox> m_xED_CrossesAtCategory; + std::unique_ptr<weld::CheckButton> m_xCB_AxisBetweenCategories; + + std::unique_ptr<weld::Frame> m_xFL_Position; + std::unique_ptr<weld::RadioButton> m_xRB_On; + std::unique_ptr<weld::RadioButton> m_xRB_Between; + + std::unique_ptr<weld::Frame> m_xFL_Labels; + std::unique_ptr<weld::ComboBox> m_xLB_PlaceLabels; + std::unique_ptr<weld::FormattedSpinButton> m_xED_LabelDistance; + + std::unique_ptr<weld::CheckButton> m_xCB_TicksInner; + std::unique_ptr<weld::CheckButton> m_xCB_TicksOuter; + + std::unique_ptr<weld::CheckButton> m_xCB_MinorInner; + std::unique_ptr<weld::CheckButton> m_xCB_MinorOuter; + + std::unique_ptr<weld::Widget> m_xBxPlaceTicks; + std::unique_ptr<weld::ComboBox> m_xLB_PlaceTicks; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_ChartType.cxx b/chart2/source/controller/dialogs/tp_ChartType.cxx new file mode 100644 index 000000000..271d4721c --- /dev/null +++ b/chart2/source/controller/dialogs/tp_ChartType.cxx @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_ChartType.hxx" +#include <ChartResourceGroups.hxx> +#include <strings.hrc> +#include <ResId.hxx> +#include <ChartModelHelper.hxx> +#include <DiagramHelper.hxx> +#include <unonames.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> + +#include <svtools/valueset.hxx> + +#include <vcl/weld.hxx> +#include <vcl/outdev.hxx> +#include <tools/diagnose_ex.h> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +ChartTypeTabPage::ChartTypeTabPage(weld::Container* pPage, weld::DialogController* pController, const uno::Reference< XChartDocument >& xChartModel, + bool bShowDescription) + : OWizardPage(pPage, pController, "modules/schart/ui/tp_ChartType.ui", "tp_ChartType") + , m_pDim3DLookResourceGroup( new Dim3DLookResourceGroup(m_xBuilder.get()) ) + , m_pStackingResourceGroup( new StackingResourceGroup(m_xBuilder.get()) ) + , m_pSplineResourceGroup( new SplineResourceGroup(m_xBuilder.get(), pController->getDialog()) ) + , m_pGeometryResourceGroup( new GeometryResourceGroup(m_xBuilder.get()) ) + , m_pSortByXValuesResourceGroup( new SortByXValuesResourceGroup(m_xBuilder.get()) ) + , m_xChartModel( xChartModel ) + , m_aChartTypeDialogControllerList(0) + , m_pCurrentMainType(nullptr) + , m_nChangingCalls(0) + , m_aTimerTriggeredControllerLock( m_xChartModel ) + , m_xFT_ChooseType(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD")) + , m_xMainTypeList(m_xBuilder->weld_tree_view("charttype")) + , m_xSubTypeList(new ValueSet(m_xBuilder->weld_scrolled_window("subtypewin"))) + , m_xSubTypeListWin(new weld::CustomWeld(*m_xBuilder, "subtype", *m_xSubTypeList)) +{ + Size aSize(m_xSubTypeList->GetDrawingArea()->get_ref_device().LogicToPixel(Size(150, 50), MapMode(MapUnit::MapAppFont))); + m_xSubTypeListWin->set_size_request(aSize.Width(), aSize.Height()); + + if (bShowDescription) + { + m_xFT_ChooseType->show(); + } + else + { + m_xFT_ChooseType->hide(); + } + + SetPageTitle(SchResId(STR_PAGE_CHARTTYPE)); + + m_xMainTypeList->connect_changed(LINK(this, ChartTypeTabPage, SelectMainTypeHdl)); + m_xSubTypeList->SetSelectHdl( LINK( this, ChartTypeTabPage, SelectSubTypeHdl ) ); + + m_xSubTypeList->SetStyle(m_xSubTypeList->GetStyle() | + WB_ITEMBORDER | WB_DOUBLEBORDER | WB_NAMEFIELD | WB_FLATVALUESET | WB_3DLOOK ); + m_xSubTypeList->SetColCount(4); + m_xSubTypeList->SetLineCount(1); + + bool bEnableComplexChartTypes = true; + uno::Reference< beans::XPropertySet > xProps( m_xChartModel, uno::UNO_QUERY ); + if ( xProps.is() ) + { + try + { + xProps->getPropertyValue("EnableComplexChartTypes") >>= bEnableComplexChartTypes; + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION("chart2", "" ); + } + } + + m_aChartTypeDialogControllerList.push_back(std::make_unique<ColumnChartDialogController>()); + m_aChartTypeDialogControllerList.push_back(std::make_unique<BarChartDialogController>()); + m_aChartTypeDialogControllerList.push_back(std::make_unique<PieChartDialogController>()); + m_aChartTypeDialogControllerList.push_back(std::make_unique<AreaChartDialogController>()); + m_aChartTypeDialogControllerList.push_back(std::make_unique<LineChartDialogController>()); + if (bEnableComplexChartTypes) + { + m_aChartTypeDialogControllerList.push_back(std::make_unique<XYChartDialogController>()); + m_aChartTypeDialogControllerList.push_back( + std::make_unique<BubbleChartDialogController>()); + } + m_aChartTypeDialogControllerList.push_back(std::make_unique<NetChartDialogController>()); + if (bEnableComplexChartTypes) + { + m_aChartTypeDialogControllerList.push_back(std::make_unique<StockChartDialogController>()); + } + m_aChartTypeDialogControllerList.push_back( + std::make_unique<CombiColumnLineChartDialogController>()); + + for (auto const& elem : m_aChartTypeDialogControllerList) + { + m_xMainTypeList->append("", elem->getName(), elem->getImage()); + elem->setChangeListener( this ); + } + + m_xMainTypeList->set_size_request(m_xMainTypeList->get_preferred_size().Width(), -1); + + m_pDim3DLookResourceGroup->setChangeListener( this ); + m_pStackingResourceGroup->setChangeListener( this ); + m_pSplineResourceGroup->setChangeListener( this ); + m_pGeometryResourceGroup->setChangeListener( this ); + m_pSortByXValuesResourceGroup->setChangeListener( this ); +} + +ChartTypeTabPage::~ChartTypeTabPage() +{ + //delete all dialog controller + m_aChartTypeDialogControllerList.clear(); + + //delete all resource helper + m_pDim3DLookResourceGroup.reset(); + m_pStackingResourceGroup.reset(); + m_pSplineResourceGroup.reset(); + m_pGeometryResourceGroup.reset(); + m_pSortByXValuesResourceGroup.reset(); + m_xSubTypeListWin.reset(); + m_xSubTypeList.reset(); +} + +ChartTypeParameter ChartTypeTabPage::getCurrentParamter() const +{ + ChartTypeParameter aParameter; + aParameter.nSubTypeIndex = static_cast<sal_Int32>(m_xSubTypeList->GetSelectedItemId()); + m_pDim3DLookResourceGroup->fillParameter( aParameter ); + m_pStackingResourceGroup->fillParameter( aParameter ); + m_pSplineResourceGroup->fillParameter( aParameter ); + m_pGeometryResourceGroup->fillParameter( aParameter ); + m_pSortByXValuesResourceGroup->fillParameter( aParameter ); + return aParameter; +} + +void ChartTypeTabPage::commitToModel( const ChartTypeParameter& rParameter ) +{ + if( !m_pCurrentMainType ) + return; + + m_aTimerTriggeredControllerLock.startTimer(); + m_pCurrentMainType->commitToModel( rParameter, m_xChartModel ); +} + +void ChartTypeTabPage::stateChanged() +{ + if(m_nChangingCalls) + return; + m_nChangingCalls++; + + ChartTypeParameter aParameter( getCurrentParamter() ); + if( m_pCurrentMainType ) + { + m_pCurrentMainType->adjustParameterToSubType( aParameter ); + m_pCurrentMainType->adjustSubTypeAndEnableControls( aParameter ); + } + commitToModel( aParameter ); + + //detect the new ThreeDLookScheme + uno::Reference<XDiagram> xDiagram = ChartModelHelper::findDiagram(m_xChartModel); + aParameter.eThreeDLookScheme = ThreeDHelper::detectScheme(xDiagram); + try + { + uno::Reference<beans::XPropertySet> xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues; + } + catch ( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + //the controls have to be enabled/disabled accordingly + fillAllControls( aParameter ); + + m_nChangingCalls--; +} + +ChartTypeDialogController* ChartTypeTabPage::getSelectedMainType() +{ + ChartTypeDialogController* pTypeController = nullptr; + auto nM = static_cast< std::vector< ChartTypeDialogController* >::size_type >( + m_xMainTypeList->get_selected_index() ); + if( nM<m_aChartTypeDialogControllerList.size() ) + pTypeController = m_aChartTypeDialogControllerList[nM].get(); + return pTypeController; +} + +IMPL_LINK_NOARG(ChartTypeTabPage, SelectSubTypeHdl, ValueSet*, void) +{ + if( m_pCurrentMainType ) + { + ChartTypeParameter aParameter( getCurrentParamter() ); + m_pCurrentMainType->adjustParameterToSubType( aParameter ); + fillAllControls( aParameter, false ); + commitToModel( aParameter ); + } +} + +IMPL_LINK_NOARG(ChartTypeTabPage, SelectMainTypeHdl, weld::TreeView&, void) +{ + selectMainType(); +} + +void ChartTypeTabPage::selectMainType() +{ + ChartTypeParameter aParameter( getCurrentParamter() ); + + if( m_pCurrentMainType ) + { + m_pCurrentMainType->adjustParameterToSubType( aParameter ); + m_pCurrentMainType->hideExtraControls(); + } + + m_pCurrentMainType = getSelectedMainType(); + if( !m_pCurrentMainType ) + return; + + showAllControls(*m_pCurrentMainType); + + m_pCurrentMainType->adjustParameterToMainType( aParameter ); + commitToModel( aParameter ); + //detect the new ThreeDLookScheme + aParameter.eThreeDLookScheme = ThreeDHelper::detectScheme( ChartModelHelper::findDiagram( m_xChartModel ) ); + if(!aParameter.b3DLook && aParameter.eThreeDLookScheme!=ThreeDLookScheme_Realistic ) + aParameter.eThreeDLookScheme=ThreeDLookScheme_Realistic; + + uno::Reference<XDiagram> xDiagram = ChartModelHelper::findDiagram(m_xChartModel); + try + { + uno::Reference<beans::XPropertySet> xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues; + } + catch ( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + fillAllControls( aParameter ); + uno::Reference< beans::XPropertySet > xTemplateProps( getCurrentTemplate(), uno::UNO_QUERY ); + m_pCurrentMainType->fillExtraControls(m_xChartModel,xTemplateProps); +} + +void ChartTypeTabPage::showAllControls( ChartTypeDialogController& rTypeController ) +{ + m_xMainTypeList->show(); + m_xSubTypeList->Show(); + + bool bShow = rTypeController.shouldShow_3DLookControl(); + m_pDim3DLookResourceGroup->showControls( bShow ); + bShow = rTypeController.shouldShow_StackingControl(); + m_pStackingResourceGroup->showControls( bShow ); + bShow = rTypeController.shouldShow_SplineControl(); + m_pSplineResourceGroup->showControls( bShow ); + bShow = rTypeController.shouldShow_GeometryControl(); + m_pGeometryResourceGroup->showControls( bShow ); + bShow = rTypeController.shouldShow_SortByXValuesResourceGroup(); + m_pSortByXValuesResourceGroup->showControls( bShow ); + rTypeController.showExtraControls(m_xBuilder.get()); +} + +void ChartTypeTabPage::fillAllControls( const ChartTypeParameter& rParameter, bool bAlsoResetSubTypeList ) +{ + m_nChangingCalls++; + if( m_pCurrentMainType && bAlsoResetSubTypeList ) + { + m_pCurrentMainType->fillSubTypeList(*m_xSubTypeList, rParameter); + } + m_xSubTypeList->SelectItem( static_cast<sal_uInt16>( rParameter.nSubTypeIndex) ); + m_pDim3DLookResourceGroup->fillControls( rParameter ); + m_pStackingResourceGroup->fillControls( rParameter ); + m_pSplineResourceGroup->fillControls( rParameter ); + m_pGeometryResourceGroup->fillControls( rParameter ); + m_pSortByXValuesResourceGroup->fillControls( rParameter ); + m_nChangingCalls--; +} + +void ChartTypeTabPage::initializePage() +{ + if( !m_xChartModel.is() ) + return; + uno::Reference< lang::XMultiServiceFactory > xTemplateManager( m_xChartModel->getChartTypeManager(), uno::UNO_QUERY ); + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) ); + DiagramHelper::tTemplateWithServiceName aTemplate = + DiagramHelper::getTemplateForDiagram( xDiagram, xTemplateManager ); + OUString aServiceName( aTemplate.second ); + + bool bFound = false; + + sal_uInt16 nM=0; + for (auto const& elem : m_aChartTypeDialogControllerList) + { + if( elem->isSubType(aServiceName) ) + { + bFound = true; + + m_xMainTypeList->select(nM); + showAllControls(*elem); + uno::Reference< beans::XPropertySet > xTemplateProps( aTemplate.first, uno::UNO_QUERY ); + ChartTypeParameter aParameter = elem->getChartTypeParameterForService( aServiceName, xTemplateProps ); + m_pCurrentMainType = getSelectedMainType(); + + //set ThreeDLookScheme + aParameter.eThreeDLookScheme = ThreeDHelper::detectScheme( xDiagram ); + if(!aParameter.b3DLook && aParameter.eThreeDLookScheme!=ThreeDLookScheme_Realistic ) + aParameter.eThreeDLookScheme=ThreeDLookScheme_Realistic; + + try + { + uno::Reference<beans::XPropertySet> xPropSet(xDiagram, uno::UNO_QUERY_THROW); + xPropSet->getPropertyValue(CHART_UNONAME_SORT_BY_XVALUES) >>= aParameter.bSortByXValues; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + + fillAllControls( aParameter ); + if( m_pCurrentMainType ) + m_pCurrentMainType->fillExtraControls(m_xChartModel,xTemplateProps); + break; + } + ++nM; + } + + if( !bFound ) + { + m_xSubTypeList->Hide(); + m_pDim3DLookResourceGroup->showControls( false ); + m_pStackingResourceGroup->showControls( false ); + m_pSplineResourceGroup->showControls( false ); + m_pGeometryResourceGroup->showControls( false ); + m_pSortByXValuesResourceGroup->showControls( false ); + } +} + +bool ChartTypeTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ ) +{ + return true; // return false if this page should not be left +} + +uno::Reference< XChartTypeTemplate > ChartTypeTabPage::getCurrentTemplate() const +{ + if( m_pCurrentMainType && m_xChartModel.is() ) + { + ChartTypeParameter aParameter( getCurrentParamter() ); + m_pCurrentMainType->adjustParameterToSubType( aParameter ); + uno::Reference< lang::XMultiServiceFactory > xTemplateManager( m_xChartModel->getChartTypeManager(), uno::UNO_QUERY ); + return m_pCurrentMainType->getCurrentTemplate( aParameter, xTemplateManager ); + } + return nullptr; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_ChartType.hxx b/chart2/source/controller/dialogs/tp_ChartType.hxx new file mode 100644 index 000000000..405c3c9ed --- /dev/null +++ b/chart2/source/controller/dialogs/tp_ChartType.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_CHARTTYPE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_CHARTTYPE_HXX + +#include <vector> + +#include <ChartTypeDialogController.hxx> +#include <ChartTypeTemplateProvider.hxx> +#include <TimerTriggeredControllerLock.hxx> + +#include <vcl/wizardmachine.hxx> + +namespace com::sun::star::chart2 { class XChartDocument; } +namespace weld { class CustomWeld; } + +class ValueSet; + +namespace chart +{ + +class Dim3DLookResourceGroup; +class StackingResourceGroup; +class SplineResourceGroup; +class GeometryResourceGroup; +class SortByXValuesResourceGroup; + +class ChartTypeTabPage final : public ResourceChangeListener, public vcl::OWizardPage, public ChartTypeTemplateProvider +{ +public: + ChartTypeTabPage( weld::Container* pPage, weld::DialogController* pController + , const css::uno::Reference< css::chart2::XChartDocument >& xChartModel + , bool bShowDescription = true ); + virtual ~ChartTypeTabPage() override; + + virtual void initializePage() override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override; + + virtual css::uno::Reference< css::chart2::XChartTypeTemplate > getCurrentTemplate() const override; + +private: + ChartTypeDialogController* getSelectedMainType(); + void showAllControls( ChartTypeDialogController& rTypeController ); + void fillAllControls( const ChartTypeParameter& rParameter, bool bAlsoResetSubTypeList=true ); + ChartTypeParameter getCurrentParamter() const; + + virtual void stateChanged() override; + + void commitToModel( const ChartTypeParameter& rParameter ); + void selectMainType(); + + DECL_LINK(SelectMainTypeHdl, weld::TreeView&, void); + DECL_LINK(SelectSubTypeHdl, ValueSet*, void ); + + std::unique_ptr<Dim3DLookResourceGroup> m_pDim3DLookResourceGroup; + std::unique_ptr<StackingResourceGroup> m_pStackingResourceGroup; + std::unique_ptr<SplineResourceGroup> m_pSplineResourceGroup; + std::unique_ptr<GeometryResourceGroup> m_pGeometryResourceGroup; + std::unique_ptr<SortByXValuesResourceGroup> m_pSortByXValuesResourceGroup; + + css::uno::Reference< css::chart2::XChartDocument > m_xChartModel; + + std::vector< std::unique_ptr<ChartTypeDialogController> > m_aChartTypeDialogControllerList; + ChartTypeDialogController* m_pCurrentMainType; + + sal_Int32 m_nChangingCalls; + + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + std::unique_ptr<weld::Label> m_xFT_ChooseType; + std::unique_ptr<weld::TreeView> m_xMainTypeList; + std::unique_ptr<ValueSet> m_xSubTypeList; + std::unique_ptr<weld::CustomWeld> m_xSubTypeListWin; +}; + +} //namespace chart +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_DataLabel.cxx b/chart2/source/controller/dialogs/tp_DataLabel.cxx new file mode 100644 index 000000000..3594e3e8f --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataLabel.cxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_DataLabel.hxx" + +namespace chart +{ + +DataLabelsTabPage::DataLabelsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_DataLabel.ui", "tp_DataLabel", &rInAttrs) + , m_aDataLabelResources(m_xBuilder.get(), pController->getDialog(), rInAttrs) +{ +} + +std::unique_ptr<SfxTabPage> DataLabelsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<DataLabelsTabPage>(pPage, pController, *rOutAttrs); +} + +bool DataLabelsTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + m_aDataLabelResources.FillItemSet(rOutAttrs); + return true; +} + +void DataLabelsTabPage::Reset(const SfxItemSet* rInAttrs) +{ + m_aDataLabelResources.Reset(*rInAttrs); +} + +void DataLabelsTabPage::SetNumberFormatter( SvNumberFormatter* pFormatter ) +{ + m_aDataLabelResources.SetNumberFormatter( pFormatter ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_DataLabel.hxx b/chart2/source/controller/dialogs/tp_DataLabel.hxx new file mode 100644 index 000000000..e7d052728 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataLabel.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATALABEL_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATALABEL_HXX + +#include "res_DataLabel.hxx" +#include <sfx2/tabdlg.hxx> + +class SvNumberFormatter; + +namespace chart +{ + +class DataLabelsTabPage : public SfxTabPage +{ +public: + DataLabelsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + + void SetNumberFormatter( SvNumberFormatter* pFormatter ); + + virtual void Reset(const SfxItemSet* rInAttrs) override; + virtual bool FillItemSet(SfxItemSet* rOutAttrs) override; + +private: + DataLabelResources m_aDataLabelResources; +}; + +} //namespace chart +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_DataPointOption.cxx b/chart2/source/controller/dialogs/tp_DataPointOption.cxx new file mode 100644 index 000000000..7fb9f230e --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataPointOption.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_DataPointOption.hxx" + +#include <chartview/ChartSfxItemIds.hxx> +#include <svl/eitem.hxx> + +namespace chart +{ +DataPointOptionTabPage::DataPointOptionTabPage(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_DataPointOption.ui", + "tp_DataPointOption", &rInAttrs) + , m_xCBHideLegendEntry(m_xBuilder->weld_check_button("CB_LEGEND_ENTRY_HIDDEN")) +{ +} + +DataPointOptionTabPage::~DataPointOptionTabPage() {} + +std::unique_ptr<SfxTabPage> DataPointOptionTabPage::Create(weld::Container* pPage, + weld::DialogController* pController, + const SfxItemSet* rOutAttrs) +{ + return std::make_unique<DataPointOptionTabPage>(pPage, pController, *rOutAttrs); +} + +bool DataPointOptionTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + if (m_xCBHideLegendEntry->get_visible()) + rOutAttrs->Put( + SfxBoolItem(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, m_xCBHideLegendEntry->get_active())); + + return true; +} + +void DataPointOptionTabPage::Reset(const SfxItemSet* rInAttrs) +{ + const SfxPoolItem* pPoolItem = nullptr; + + if (rInAttrs->GetItemState(SCHATTR_HIDE_DATA_POINT_LEGEND_ENTRY, true, &pPoolItem) + == SfxItemState::SET) + { + bool bVal = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + m_xCBHideLegendEntry->set_active(bVal); + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_DataPointOption.hxx b/chart2/source/controller/dialogs/tp_DataPointOption.hxx new file mode 100644 index 000000000..5473d93c8 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataPointOption.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATAPOINTOPTION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATAPOINTOPTION_HXX + +#include <sfx2/tabdlg.hxx> + +namespace weld +{ +class CheckButton; +} + +namespace chart +{ +class DataPointOptionTabPage : public SfxTabPage +{ +public: + DataPointOptionTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rInAttrs); + virtual ~DataPointOptionTabPage() override; + + static std::unique_ptr<SfxTabPage> + Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + virtual bool FillItemSet(SfxItemSet* rOutAttrs) override; + virtual void Reset(const SfxItemSet* rInAttrs) override; + +private: + std::unique_ptr<weld::CheckButton> m_xCBHideLegendEntry; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_DataSource.cxx b/chart2/source/controller/dialogs/tp_DataSource.cxx new file mode 100644 index 000000000..b6ebe98d0 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataSource.cxx @@ -0,0 +1,928 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_DataSource.hxx" +#include <strings.hrc> +#include <ResId.hxx> +#include <ChartTypeTemplateProvider.hxx> +#include <RangeSelectionHelper.hxx> +#include <DataSeriesHelper.hxx> +#include <ControllerLockGuard.hxx> +#include <DataSourceHelper.hxx> +#include "DialogModel.hxx" +#include <TabPageNotifiable.hxx> +#include <com/sun/star/chart2/XChartType.hpp> +#include <com/sun/star/chart2/XDataSeries.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart2/data/XDataProvider.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/chart2/data/XDataSink.hpp> + +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ + +const OUString lcl_aLabelRole( "label" ); + +void lcl_UpdateCurrentRange(weld::TreeView& rOutListBox, const OUString & rRole, + const OUString& rRange) +{ + int nEntry = rOutListBox.get_selected_index(); + if (nEntry != -1) + { + rOutListBox.set_text(nEntry, ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole), 0); + rOutListBox.set_text(nEntry, rRange, 1); + ::chart::SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry).toInt64()); + pEntry->m_sRole = rRole; + } +} + +bool lcl_UpdateCurrentSeriesName(weld::TreeView& rOutListBox) +{ + int nEntry = rOutListBox.get_selected_index(); + if (nEntry == -1) + return false; + + bool bResult = false; + ::chart::SeriesEntry * pEntry = reinterpret_cast<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry).toInt64()); + if (pEntry->m_xDataSeries.is() && pEntry->m_xChartType.is()) + { + OUString aLabel(::chart::DataSeriesHelper::getDataSeriesLabel( + pEntry->m_xDataSeries, + pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel())); + if (!aLabel.isEmpty()) + { + rOutListBox.set_text(nEntry, aLabel); + bResult = true; + } + } + return bResult; +} + +OUString lcl_GetSelectedRole(const weld::TreeView& rRoleListBox, bool bUITranslated = false) +{ + int nEntry = rRoleListBox.get_selected_index(); + if (nEntry != -1) + { + if (bUITranslated) + return rRoleListBox.get_text(nEntry); + ::chart::SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(rRoleListBox.get_id(nEntry).toInt64()); + return pEntry->m_sRole; + } + return OUString(); +} + +OUString lcl_GetSelectedRolesRange( const weld::TreeView& rRoleListBox ) +{ + OUString aResult; + int nEntry = rRoleListBox.get_selected_index(); + if (nEntry != -1) + aResult = rRoleListBox.get_text(nEntry, 1); + return aResult; +} + +OUString lcl_GetSequenceNameForLabel(const ::chart::SeriesEntry* pEntry) +{ + OUString aResult("values-y"); + if (pEntry && pEntry->m_xChartType.is()) + aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel(); + return aResult; +} + +void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pDialog) +{ + if (!pDialog) + return; + weld::Dialog* pDlg = pDialog->getDialog(); + pDlg->set_modal(!bEnable); + pDlg->set_visible(!bEnable); +} + +void lcl_addLSequenceToDataSource( + const Reference< chart2::data::XLabeledDataSequence > & xLSequence, + const Reference< chart2::data::XDataSource > & xSource ) +{ + Reference< data::XDataSink > xSink( xSource, uno::UNO_QUERY ); + if( xSink.is()) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences()); + aData.realloc( aData.getLength() + 1 ); + aData[ aData.getLength() - 1 ] = xLSequence; + xSink->setData( aData ); + } +} + +Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel( + const Reference< chart2::data::XDataSource > & xDataSource ) +{ + Reference< chart2::data::XLabeledDataSequence > xResult; + const Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); + + for( Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : aSequences ) + { + // no values are set but a label exists + if( ! labeledDataSeq->getValues().is() && + labeledDataSeq->getLabel().is()) + { + xResult.set( labeledDataSeq ); + break; + } + } + + return xResult; +} + +} // anonymous namespace + +namespace chart +{ + +DataSourceTabPage::DataSourceTabPage(weld::Container* pPage, weld::DialogController* pController, + DialogModel & rDialogModel, + ChartTypeTemplateProvider* pTemplateProvider, + bool bHideDescription /* = false */) + : ::vcl::OWizardPage(pPage, pController, "modules/schart/ui/tp_DataSource.ui", "tp_DataSource") + , m_pTemplateProvider(pTemplateProvider) + , m_rDialogModel(rDialogModel) + , m_pCurrentRangeChoosingField( nullptr ) + , m_bIsDirty( false ) + , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController)) + , m_xFT_CAPTION(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD")) + , m_xFT_SERIES(m_xBuilder->weld_label("FT_SERIES")) + , m_xLB_SERIES(m_xBuilder->weld_tree_view("LB_SERIES")) + , m_xBTN_ADD(m_xBuilder->weld_button("BTN_ADD")) + , m_xBTN_REMOVE(m_xBuilder->weld_button("BTN_REMOVE")) + , m_xBTN_UP(m_xBuilder->weld_button("BTN_UP")) + , m_xBTN_DOWN(m_xBuilder->weld_button("BTN_DOWN")) + , m_xFT_ROLE(m_xBuilder->weld_label("FT_ROLE")) + , m_xLB_ROLE(m_xBuilder->weld_tree_view("LB_ROLE")) + , m_xFT_RANGE(m_xBuilder->weld_label("FT_RANGE")) + , m_xEDT_RANGE(m_xBuilder->weld_entry("EDT_RANGE")) + , m_xIMB_RANGE_MAIN(m_xBuilder->weld_button("IMB_RANGE_MAIN")) + , m_xFT_CATEGORIES(m_xBuilder->weld_label("FT_CATEGORIES")) + , m_xFT_DATALABELS(m_xBuilder->weld_label("FT_DATALABELS")) + , m_xEDT_CATEGORIES(m_xBuilder->weld_entry("EDT_CATEGORIES")) + , m_xIMB_RANGE_CAT(m_xBuilder->weld_button("IMB_RANGE_CAT")) +{ + m_xLB_SERIES->set_size_request(m_xLB_SERIES->get_approximate_digit_width() * 25, + m_xLB_SERIES->get_height_rows(10)); + m_xLB_ROLE->set_size_request(m_xLB_ROLE->get_approximate_digit_width() * 60, + m_xLB_ROLE->get_height_rows(5)); + m_xFT_CAPTION->set_visible(!bHideDescription); + + m_aFixedTextRange = m_xFT_RANGE->get_label(); + SetPageTitle(SchResId(STR_OBJECT_DATASERIES_PLURAL)); + + // set handlers + m_xLB_SERIES->connect_changed(LINK(this, DataSourceTabPage, SeriesSelectionChangedHdl)); + m_xLB_ROLE->connect_changed(LINK(this, DataSourceTabPage, RoleSelectionChangedHdl)); + + m_xIMB_RANGE_MAIN->connect_clicked(LINK(this, DataSourceTabPage, MainRangeButtonClickedHdl)); + m_xIMB_RANGE_CAT->connect_clicked(LINK(this, DataSourceTabPage, CategoriesRangeButtonClickedHdl)); + + m_xBTN_ADD->connect_clicked(LINK(this, DataSourceTabPage, AddButtonClickedHdl)); + m_xBTN_REMOVE->connect_clicked(LINK(this, DataSourceTabPage, RemoveButtonClickedHdl)); + + m_xBTN_UP->connect_clicked(LINK(this, DataSourceTabPage, UpButtonClickedHdl)); + m_xBTN_DOWN->connect_clicked(LINK(this, DataSourceTabPage, DownButtonClickedHdl)); + + m_xEDT_RANGE->connect_changed(LINK(this, DataSourceTabPage, RangeModifiedHdl)); + m_xEDT_CATEGORIES->connect_changed(LINK( this, DataSourceTabPage, RangeModifiedHdl)); + + // init controls + std::vector<int> aWidths; + aWidths.push_back(m_xLB_ROLE->get_approximate_digit_width() * 20); + m_xLB_ROLE->set_column_fixed_widths(aWidths); + m_xLB_ROLE->show(); + + updateControlsFromDialogModel(); + + // select first series + if (m_xLB_SERIES->n_children()) + m_xLB_SERIES->select(0); +} + +void DataSourceTabPage::InsertRoleLBEntry(const OUString& rRole, const OUString& rRange) +{ + m_aEntries.emplace_back(new SeriesEntry); + SeriesEntry* pEntry = m_aEntries.back().get(); + pEntry->m_sRole = rRole; + m_xLB_ROLE->append(OUString::number(reinterpret_cast<sal_Int64>(pEntry)), + ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole)); + m_xLB_ROLE->set_text(m_xLB_ROLE->n_children() - 1, rRange, 1); +} + +DataSourceTabPage::~DataSourceTabPage() +{ +} + +void DataSourceTabPage::Activate() +{ + OWizardPage::Activate(); + updateControlsFromDialogModel(); + m_xLB_SERIES->grab_focus(); +} + +void DataSourceTabPage::initializePage() +{ +} + +void DataSourceTabPage::Deactivate() +{ + commitPage(); + vcl::OWizardPage::Deactivate(); +} + +void DataSourceTabPage::commitPage() +{ + commitPage(::vcl::WizardTypes::eFinish); +} + +bool DataSourceTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ ) +{ + //ranges may have been edited in the meanwhile (dirty is true in that case here) + if( isValid() ) + { + updateModelFromControl(); + return true; //return false if this page should not be left + } + else + return false; +} + +bool DataSourceTabPage::isRangeFieldContentValid(weld::Entry& rEdit ) +{ + OUString aRange(rEdit.get_text()); + bool bIsValid = aRange.isEmpty() || + m_rDialogModel.getRangeSelectionHelper()->verifyCellRange(aRange); + rEdit.set_message_type(bIsValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error); + return bIsValid; +} + +bool DataSourceTabPage::isValid() +{ + bool bRoleRangeValid = true; + bool bCategoriesRangeValid = true; + bool bHasSelectedEntry = (m_xLB_SERIES->get_selected_index() != -1); + + if (bHasSelectedEntry) + bRoleRangeValid = isRangeFieldContentValid(*m_xEDT_RANGE); + if (m_xEDT_CATEGORIES->get_sensitive()) + bCategoriesRangeValid = isRangeFieldContentValid( *m_xEDT_CATEGORIES ); + bool bValid = ( bRoleRangeValid && bCategoriesRangeValid ); + + if( m_pTabPageNotifiable ) + { + if( bValid ) + m_pTabPageNotifiable->setValidPage( this ); + else + m_pTabPageNotifiable->setInvalidPage( this ); + } + + return bValid; +} + +void DataSourceTabPage::setDirty() +{ + m_bIsDirty = true; +} + +void DataSourceTabPage::updateControlsFromDialogModel() +{ + // series + fillSeriesListBox(); + SeriesSelectionChangedHdl(*m_xLB_SERIES); + + // categories + m_xEDT_CATEGORIES->set_text(m_rDialogModel.getCategoriesRange()); + + updateControlState(); +} + +void DataSourceTabPage::fillSeriesListBox() +{ + Reference< XDataSeries > xSelected; + SeriesEntry* pEntry = nullptr; + int nEntry = m_xLB_SERIES->get_selected_index(); + if (nEntry != -1) + { + pEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64()); + xSelected.set(pEntry->m_xDataSeries); + } + + bool bHasSelectedEntry = (pEntry != nullptr); + int nSelectedEntry = -1; + + m_xLB_SERIES->freeze(); + m_xLB_SERIES->clear(); + + std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries( + m_rDialogModel.getAllDataSeriesWithLabel() ); + + sal_Int32 nUnnamedSeriesIndex = 1; + nEntry = 0; + for (auto const& series : aSeries) + { + OUString aLabel(series.first); + if (aLabel.isEmpty()) + { + if( nUnnamedSeriesIndex > 1 ) + { + OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX )); + + // replace index of unnamed series + const OUString aReplacementStr( "%NUMBER" ); + sal_Int32 nIndex = aResString.indexOf( aReplacementStr ); + if( nIndex != -1 ) + aLabel = aResString.replaceAt( + nIndex, aReplacementStr.getLength(), + OUString::number(nUnnamedSeriesIndex)); + } + if( aLabel.isEmpty() ) + aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES ); + + ++nUnnamedSeriesIndex; + } + + m_aEntries.emplace_back(new SeriesEntry); + pEntry = m_aEntries.back().get(); + pEntry->m_xDataSeries.set(series.second.first); + pEntry->m_xChartType.set(series.second.second); + m_xLB_SERIES->append(OUString::number(reinterpret_cast<sal_Int64>(pEntry)), aLabel); + if (bHasSelectedEntry && series.second.first == xSelected) + nSelectedEntry = nEntry; + ++nEntry; + } + + m_xLB_SERIES->thaw(); + + if (bHasSelectedEntry && nSelectedEntry != -1) + m_xLB_SERIES->select(nSelectedEntry); +} + +void DataSourceTabPage::fillRoleListBox() +{ + int nSeriesEntry = m_xLB_SERIES->get_selected_index(); + SeriesEntry* pSeriesEntry = nullptr; + if (nSeriesEntry != -1) + pSeriesEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry).toInt64()); + bool bHasSelectedEntry = (pSeriesEntry != nullptr); + + int nRoleIndex = m_xLB_ROLE->get_selected_index(); + if (!bHasSelectedEntry) + return; + + DialogModel::tRolesWithRanges aRoles( + DialogModel::getRolesWithRanges( + pSeriesEntry->m_xDataSeries, + lcl_GetSequenceNameForLabel( pSeriesEntry ), + pSeriesEntry->m_xChartType )); + + // fill role list + m_xLB_ROLE->freeze(); + m_xLB_ROLE->clear(); + + for (auto const& elemRole : aRoles) + { + InsertRoleLBEntry(elemRole.first, elemRole.second); + } + + m_xLB_ROLE->thaw(); + + // series may contain no roles, check listbox size before selecting entries + if (m_xLB_ROLE->n_children() > 0) + { + if (nRoleIndex == -1 || nRoleIndex >= m_xLB_ROLE->n_children()) + nRoleIndex = 0; + m_xLB_ROLE->select(nRoleIndex); + } +} + +void DataSourceTabPage::updateControlState() +{ + int nSeriesEntry = m_xLB_SERIES->get_selected_index(); + bool bHasSelectedSeries = nSeriesEntry != -1; + bool bHasValidRole = false; + bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection(); + + if( bHasSelectedSeries ) + { + int nRoleEntry = m_xLB_ROLE->get_selected_index(); + bHasValidRole = nRoleEntry != -1; + } + + m_xBTN_ADD->set_sensitive(true); + m_xBTN_REMOVE->set_sensitive(bHasSelectedSeries); + + m_xBTN_UP->set_sensitive(bHasSelectedSeries && (nSeriesEntry != 0)); + m_xBTN_DOWN->set_sensitive(bHasSelectedSeries && (nSeriesEntry != m_xLB_SERIES->n_children() - 1)); + + bool bHasCategories = m_rDialogModel.isCategoryDiagram(); + + m_xFT_DATALABELS->set_visible(!bHasCategories); + m_xFT_CATEGORIES->set_visible( bHasCategories); + bool bShowIB = bHasRangeChooser; + + m_xIMB_RANGE_CAT->set_visible(bShowIB); + + m_xFT_ROLE->set_sensitive(bHasSelectedSeries); + m_xLB_ROLE->set_sensitive(bHasSelectedSeries); + + m_xFT_RANGE->set_sensitive(bHasValidRole); + m_xEDT_RANGE->set_sensitive(bHasValidRole); + + m_xFT_SERIES->set_sensitive(true); + m_xLB_SERIES->set_sensitive(true); + + m_xIMB_RANGE_MAIN->set_visible(bShowIB); + + isValid(); +} + +IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl, weld::TreeView&, void) +{ + m_rDialogModel.startControllerLockTimer(); + if (m_xLB_SERIES->get_selected_index() != -1) + { + fillRoleListBox(); + RoleSelectionChangedHdl(*m_xLB_ROLE); + } + updateControlState(); +} + +IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl, weld::TreeView&, void) +{ + m_rDialogModel.startControllerLockTimer(); + int nEntry = m_xLB_ROLE->get_selected_index(); + if (nEntry == -1) + return; + + OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_xLB_ROLE, true ); + OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_xLB_ROLE ); + + // replace role in fixed text label + const OUString aReplacementStr( "%VALUETYPE" ); + sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr ); + if( nIndex != -1 ) + { + m_xFT_RANGE->set_label( + m_aFixedTextRange.replaceAt( + nIndex, aReplacementStr.getLength(), aSelectedRoleUI )); + } + + m_xEDT_RANGE->set_text(aSelectedRange); + isValid(); +} + +IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl, weld::Button&, void) +{ + OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr ); + m_pCurrentRangeChoosingField = m_xEDT_RANGE.get(); + if (!m_xEDT_RANGE->get_text().isEmpty() && + !updateModelFromControl( m_pCurrentRangeChoosingField)) + return; + + int nEntry = m_xLB_SERIES->get_selected_index(); + bool bHasSelectedEntry = (nEntry != -1); + + OUString aSelectedRolesRange = lcl_GetSelectedRolesRange(*m_xLB_ROLE); + + if (bHasSelectedEntry && (m_xLB_ROLE->get_selected_index() != -1)) + { + OUString aUIStr(SchResId(STR_DATA_SELECT_RANGE_FOR_SERIES)); + + // replace role + OUString aReplacement( "%VALUETYPE" ); + sal_Int32 nIndex = aUIStr.indexOf( aReplacement ); + if( nIndex != -1 ) + { + aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(), + lcl_GetSelectedRole( *m_xLB_ROLE, true )); + } + // replace series name + aReplacement = "%SERIESNAME"; + nIndex = aUIStr.indexOf( aReplacement ); + if( nIndex != -1 ) + { + aUIStr = aUIStr.replaceAt(nIndex, aReplacement.getLength(), + m_xLB_SERIES->get_text(nEntry)); + } + + lcl_enableRangeChoosing(true, m_pDialogController); + m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this ); + } + else + m_pCurrentRangeChoosingField = nullptr; +} + +IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl, weld::Button&, void) +{ + OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr ); + m_pCurrentRangeChoosingField = m_xEDT_CATEGORIES.get(); + if( !m_xEDT_CATEGORIES->get_text().isEmpty() && + ! updateModelFromControl( m_pCurrentRangeChoosingField )) + return; + + OUString aStr(SchResId(m_xFT_CATEGORIES->get_visible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS)); + lcl_enableRangeChoosing(true, m_pDialogController); + m_rDialogModel.getRangeSelectionHelper()->chooseRange( + m_rDialogModel.getCategoriesRange(), aStr, *this ); +} + +IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl, weld::Button&, void) +{ + m_rDialogModel.startControllerLockTimer(); + int nEntry = m_xLB_SERIES->get_selected_index(); + Reference< XDataSeries > xSeriesToInsertAfter; + Reference< XChartType > xChartTypeForNewSeries; + if( m_pTemplateProvider ) + m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate()); + + if (nEntry != -1) + { + ::chart::SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64()); + xSeriesToInsertAfter.set(pEntry->m_xDataSeries); + xChartTypeForNewSeries.set(pEntry->m_xChartType); + } + else + { + std::vector< Reference< XDataSeriesContainer > > aCntVec( + m_rDialogModel.getAllDataSeriesContainers()); + if( ! aCntVec.empty()) + xChartTypeForNewSeries.set( aCntVec.front(), uno::UNO_QUERY ); + } + OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" ); + + m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries ); + setDirty(); + + fillSeriesListBox(); + // note the box was cleared and refilled, so nEntry is invalid now + + int nSelEntry = m_xLB_SERIES->get_selected_index(); + if (nSelEntry != -1) + { + ++nSelEntry; + if (nSelEntry < m_xLB_SERIES->n_children()) + m_xLB_SERIES->select(nSelEntry); + } + SeriesSelectionChangedHdl(*m_xLB_SERIES); +} + +IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl, weld::Button&, void) +{ + m_rDialogModel.startControllerLockTimer(); + int nEntry = m_xLB_SERIES->get_selected_index(); + if (nEntry == -1) + return; + + SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64()); + Reference< XDataSeries > xNewSelSeries; + SeriesEntry * pNewSelEntry = nullptr; + if (nEntry + 1 < m_xLB_SERIES->n_children()) + pNewSelEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry + 1).toInt64()); + else if (nEntry > 0) + pNewSelEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry - 1).toInt64()); + if (pNewSelEntry) + xNewSelSeries.set(pNewSelEntry->m_xDataSeries); + + m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType ); + setDirty(); + + m_xLB_SERIES->remove(nEntry); + fillSeriesListBox(); + + // select previous or next series + if (xNewSelSeries.is()) + { + for (int i = 0; i < m_xLB_SERIES->n_children(); ++i) + { + pEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(i).toInt64()); + if (pEntry->m_xDataSeries == xNewSelSeries) + { + m_xLB_SERIES->select(i); + break; + } + } + } + SeriesSelectionChangedHdl(*m_xLB_SERIES); +} + +IMPL_LINK_NOARG(DataSourceTabPage, UpButtonClickedHdl, weld::Button&, void) +{ + m_rDialogModel.startControllerLockTimer(); + + int nEntry = m_xLB_SERIES->get_selected_index(); + SeriesEntry* pEntry = nullptr; + if (nEntry != -1) + pEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64()); + + bool bHasSelectedEntry = (pEntry != nullptr); + + if (bHasSelectedEntry) + { + m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Up ); + setDirty(); + fillSeriesListBox(); + SeriesSelectionChangedHdl(*m_xLB_SERIES); + } +} + +IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl, weld::Button&, void) +{ + m_rDialogModel.startControllerLockTimer(); + + int nEntry = m_xLB_SERIES->get_selected_index(); + SeriesEntry* pEntry = nullptr; + if (nEntry != -1) + pEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64()); + + bool bHasSelectedEntry = (pEntry != nullptr); + + if (bHasSelectedEntry) + { + m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Down ); + setDirty(); + fillSeriesListBox(); + SeriesSelectionChangedHdl(*m_xLB_SERIES); + } +} + +IMPL_LINK(DataSourceTabPage, RangeModifiedHdl, weld::Entry&, rEdit, void) +{ + // note: isValid sets the color of the edit field + if( isRangeFieldContentValid( rEdit )) + { + setDirty(); + updateModelFromControl( &rEdit ); + if (&rEdit == m_xEDT_RANGE.get()) + { + if( ! lcl_UpdateCurrentSeriesName( *m_xLB_SERIES )) + fillSeriesListBox(); + } + } + + // enable/disable OK button + isValid(); +} + +void DataSourceTabPage::listeningFinished( + const OUString & rNewRange ) +{ + // rNewRange becomes invalid after removing the listener + OUString aRange( rNewRange ); + + m_rDialogModel.startControllerLockTimer(); + + // stop listening + m_rDialogModel.getRangeSelectionHelper()->stopRangeListening(); + + // change edit field + if( m_pCurrentRangeChoosingField ) + { + m_pCurrentRangeChoosingField->set_text(aRange); + m_pCurrentRangeChoosingField->grab_focus(); + } + + if (m_pCurrentRangeChoosingField == m_xEDT_RANGE.get()) + { + m_xEDT_RANGE->set_text(aRange); + setDirty(); + } + else if (m_pCurrentRangeChoosingField == m_xEDT_CATEGORIES.get()) + { + m_xEDT_CATEGORIES->set_text(aRange); + setDirty(); + } + + updateModelFromControl(m_pCurrentRangeChoosingField); + if (!lcl_UpdateCurrentSeriesName(*m_xLB_SERIES)) + fillSeriesListBox(); + + m_pCurrentRangeChoosingField = nullptr; + + updateControlState(); + lcl_enableRangeChoosing(false, m_pDialogController); +} + +void DataSourceTabPage::disposingRangeSelection() +{ + m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false ); +} + +bool DataSourceTabPage::updateModelFromControl(const weld::Entry* pField) +{ + if (!m_bIsDirty) + return true; + + ControllerLockGuardUNO aLockedControllers( m_rDialogModel.getChartModel() ); + + // @todo: validity check of field content + bool bResult = true; + bool bAll = (pField == nullptr); + Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider()); + + if (bAll || (pField == m_xEDT_CATEGORIES.get())) + { + Reference< data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() ); + if( xDataProvider.is()) + { + OUString aRange(m_xEDT_CATEGORIES->get_text()); + if (!aRange.isEmpty()) + { + // create or change categories + if( !xLabeledSeq.is()) + { + xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() ); + m_rDialogModel.setCategories( xLabeledSeq ); + } + try + { + xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange )); + } + catch( const uno::Exception & ) + { + // should work as validation should have happened before + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + else if( xLabeledSeq.is()) + { + // clear existing categories + xLabeledSeq.set(nullptr); + m_rDialogModel.setCategories( xLabeledSeq ); + } + } + } + + int nSeriesEntry = m_xLB_SERIES->get_selected_index(); + SeriesEntry* pSeriesEntry = nullptr; + if (nSeriesEntry != -1) + pSeriesEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry).toInt64()); + bool bHasSelectedEntry = (pSeriesEntry != nullptr); + + if( bHasSelectedEntry ) + { + if( bAll || (pField == m_xEDT_RANGE.get()) ) + { + try + { + OUString aSelectedRole = lcl_GetSelectedRole( *m_xLB_ROLE ); + OUString aRange(m_xEDT_RANGE->get_text()); + OUString aSequenceRole( aSelectedRole ); + bool bIsLabel = (aSequenceRole == lcl_aLabelRole ); + OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry )); + + if( bIsLabel ) + aSequenceRole = aSequenceNameForLabel; + + Reference< data::XDataSource > xSource( pSeriesEntry->m_xDataSeries, uno::UNO_QUERY_THROW ); + Reference< data::XLabeledDataSequence > xLabeledSeq( + DataSeriesHelper::getDataSequenceByRole( xSource, aSequenceRole )); + + if( xDataProvider.is()) + { + if( bIsLabel ) + { + if( ! xLabeledSeq.is()) + { + // check if there is already an "orphan" label sequence + xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource )); + if( ! xLabeledSeq.is()) + { + // no corresponding labeled data sequence for label found + xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() ); + lcl_addLSequenceToDataSource( xLabeledSeq, xSource ); + } + } + if( xLabeledSeq.is()) + { + if( !aRange.isEmpty()) + { + Reference< data::XDataSequence > xNewSeq; + try + { + xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange )); + } + catch( const uno::Exception & ) + { + // should work as validation should have happened before + DBG_UNHANDLED_EXCEPTION("chart2"); + } + if( xNewSeq.is()) + { + // update range name by the full string provided + // by the data provider. E.g. "a1" might become + // "$Sheet1.$A$1" + aRange = xNewSeq->getSourceRangeRepresentation(); + Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW ); + xProp->setPropertyValue( "Role" , uno::Any( lcl_aLabelRole )); + xLabeledSeq->setLabel( xNewSeq ); + } + } + else + { + xLabeledSeq->setLabel( Reference< data::XDataSequence >()); + } + } + } + else + { + if( !aRange.isEmpty()) + { + Reference< data::XDataSequence > xNewSeq; + try + { + xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange )); + } + catch( const uno::Exception & ) + { + // should work as validation should have happened before + DBG_UNHANDLED_EXCEPTION("chart2"); + } + if( xNewSeq.is()) + { + // update range name by the full string provided + // by the data provider. E.g. "a1:e1" might become + // "$Sheet1.$A$1:$E$1" + aRange = xNewSeq->getSourceRangeRepresentation(); + + Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW ); + xProp->setPropertyValue( "Role" , uno::Any( aSelectedRole )); + if( !xLabeledSeq.is()) + { + if( aSelectedRole == aSequenceNameForLabel ) + xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource )); + if( ! xLabeledSeq.is()) + { + xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() ); + lcl_addLSequenceToDataSource( xLabeledSeq, xSource ); + } + } + xLabeledSeq->setValues( xNewSeq ); + } + } + } + } + + lcl_UpdateCurrentRange( *m_xLB_ROLE, aSelectedRole, aRange ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + bResult = false; + } + } + } + + // update View + // @todo remove this when automatic view updates from calc, writer and own data sequences are available + if( bResult ) + { + try + { + Reference< util::XModifiable > xModifiable( m_rDialogModel.getChartModel(), uno::UNO_QUERY ); + if( xModifiable.is() ) + xModifiable->setModified( true ); + const DialogModelTimeBasedInfo& rInfo = m_rDialogModel.getTimeBasedInfo(); + if(rInfo.bTimeBased) + { + m_rDialogModel.setTimeBasedRange(rInfo.bTimeBased, rInfo.nStart, rInfo.nEnd); + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return bResult; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_DataSource.hxx b/chart2/source/controller/dialogs/tp_DataSource.hxx new file mode 100644 index 000000000..3ba36a1cf --- /dev/null +++ b/chart2/source/controller/dialogs/tp_DataSource.hxx @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATASOURCE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATASOURCE_HXX + +#include <vcl/wizardmachine.hxx> + +#include <RangeSelectionListener.hxx> + +namespace com::sun::star::chart2 { class XChartType; } +namespace com::sun::star::chart2 { class XDataSeries; } + +namespace chart { class TabPageNotifiable; } + +namespace chart +{ + +class ChartTypeTemplateProvider; +class DialogModel; + +class SeriesEntry +{ +public: + OUString m_sRole; + + /// the corresponding data series + css::uno::Reference< css::chart2::XDataSeries > m_xDataSeries; + + /// the chart type that contains the series (via XDataSeriesContainer) + css::uno::Reference< css::chart2::XChartType > m_xChartType; +}; + +class DataSourceTabPage final : + public ::vcl::OWizardPage, + public RangeSelectionListenerParent +{ +public: + explicit DataSourceTabPage(weld::Container* pPage, weld::DialogController* pController, + DialogModel & rDialogModel, + ChartTypeTemplateProvider* pTemplateProvider, + bool bHideDescription = false); + virtual ~DataSourceTabPage() override; + + virtual void Activate() override; + + void commitPage(); + +private: + // OWizardPage + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override; + + //TabPage + virtual void Deactivate() override; + + virtual void initializePage() override; + + DECL_LINK( SeriesSelectionChangedHdl, weld::TreeView&, void ); + DECL_LINK( RoleSelectionChangedHdl, weld::TreeView&, void ); + DECL_LINK( MainRangeButtonClickedHdl, weld::Button&, void ); + DECL_LINK( CategoriesRangeButtonClickedHdl, weld::Button&, void ); + DECL_LINK( AddButtonClickedHdl, weld::Button&, void ); + DECL_LINK( RemoveButtonClickedHdl, weld::Button&, void ); + DECL_LINK( RangeModifiedHdl, weld::Entry&, void ); + DECL_LINK( UpButtonClickedHdl, weld::Button&, void ); + DECL_LINK( DownButtonClickedHdl, weld::Button&, void ); + + // ____ RangeSelectionListenerParent ____ + virtual void listeningFinished( const OUString & rNewRange ) override; + virtual void disposingRangeSelection() override; + + void InsertRoleLBEntry(const OUString& rRole, const OUString& rRange); + + void updateControlState(); + + /** updates the internal data according to the content of the given edit + field. If pField is 0, all relevant fields are used + + @return + <TRUE/> if the text from the field is a valid format to the internal + data was valid + */ + bool updateModelFromControl(const weld::Entry* pField = nullptr); + + /** @return </sal_True>, if the edit field contains a valid range entry. If no + XCellRangesAccess can be obtained, </sal_False> is returned. + */ + bool isRangeFieldContentValid(weld::Entry& rEdit); + + /** @return </sal_True>, if the tab-page is in a consistent (committable) state + */ + bool isValid(); + void setDirty(); + + void updateControlsFromDialogModel(); + + void fillSeriesListBox(); + void fillRoleListBox(); + + std::vector<std::unique_ptr<SeriesEntry>> m_aEntries; + + OUString m_aFixedTextRange; + + ChartTypeTemplateProvider * m_pTemplateProvider; + DialogModel & m_rDialogModel; + weld::Entry* m_pCurrentRangeChoosingField; + bool m_bIsDirty; + + TabPageNotifiable * m_pTabPageNotifiable; + + std::unique_ptr<weld::Label> m_xFT_CAPTION; + std::unique_ptr<weld::Label> m_xFT_SERIES; + std::unique_ptr<weld::TreeView> m_xLB_SERIES; + std::unique_ptr<weld::Button> m_xBTN_ADD; + std::unique_ptr<weld::Button> m_xBTN_REMOVE; + std::unique_ptr<weld::Button> m_xBTN_UP; + std::unique_ptr<weld::Button> m_xBTN_DOWN; + std::unique_ptr<weld::Label> m_xFT_ROLE; + std::unique_ptr<weld::TreeView> m_xLB_ROLE; + std::unique_ptr<weld::Label> m_xFT_RANGE; + std::unique_ptr<weld::Entry> m_xEDT_RANGE; + std::unique_ptr<weld::Button> m_xIMB_RANGE_MAIN; + std::unique_ptr<weld::Label> m_xFT_CATEGORIES; + std::unique_ptr<weld::Label> m_xFT_DATALABELS;//used for xy charts + std::unique_ptr<weld::Entry> m_xEDT_CATEGORIES; + std::unique_ptr<weld::Button> m_xIMB_RANGE_CAT; +}; + +} // namespace chart + +// INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_DATASOURCE_HXX +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_ErrorBars.cxx b/chart2/source/controller/dialogs/tp_ErrorBars.cxx new file mode 100644 index 000000000..94a3d6c77 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_ErrorBars.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_ErrorBars.hxx" + +using namespace ::com::sun::star; + +namespace chart +{ + +ErrorBarsTabPage::ErrorBarsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_ErrorBars.ui", "tp_ErrorBars", &rInAttrs) + , m_aErrorBarResources(m_xBuilder.get(), pController, rInAttrs, /* bNoneAvailable = */ false) +{ +} + +std::unique_ptr<SfxTabPage> ErrorBarsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<ErrorBarsTabPage>(pPage, pController, *rOutAttrs); +} + +bool ErrorBarsTabPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + m_aErrorBarResources.FillItemSet( *rOutAttrs ); + return true; +} + +void ErrorBarsTabPage::Reset( const SfxItemSet* rInAttrs ) +{ + m_aErrorBarResources.Reset( *rInAttrs ); +} + +void ErrorBarsTabPage::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth ) +{ + m_aErrorBarResources.SetAxisMinorStepWidthForErrorBarDecimals( fMinorStepWidth ); +} + +void ErrorBarsTabPage::SetErrorBarType( ErrorBarResources::tErrorBarType eNewType ) +{ + m_aErrorBarResources.SetErrorBarType( eNewType ); +} + +void ErrorBarsTabPage::SetChartDocumentForRangeChoosing( + const uno::Reference< chart2::XChartDocument > & xChartDocument ) +{ + m_aErrorBarResources.SetChartDocumentForRangeChoosing( xChartDocument ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_ErrorBars.hxx b/chart2/source/controller/dialogs/tp_ErrorBars.hxx new file mode 100644 index 000000000..2ce941a1d --- /dev/null +++ b/chart2/source/controller/dialogs/tp_ErrorBars.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_ERRORBARS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_ERRORBARS_HXX + +#include <res_ErrorBar.hxx> + +#include <sfx2/tabdlg.hxx> + +namespace chart +{ + +class ErrorBarsTabPage : public SfxTabPage +{ +public: + ErrorBarsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + + void SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth ); + void SetErrorBarType( ErrorBarResources::tErrorBarType eNewType ); + void SetChartDocumentForRangeChoosing( + const css::uno::Reference< css::chart2::XChartDocument > & xChartDocument ); + + static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs ); + virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override; + virtual void Reset( const SfxItemSet* rInAttrs ) override; + +private: + ErrorBarResources m_aErrorBarResources; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_LegendPosition.cxx b/chart2/source/controller/dialogs/tp_LegendPosition.cxx new file mode 100644 index 000000000..04697e75e --- /dev/null +++ b/chart2/source/controller/dialogs/tp_LegendPosition.cxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_LegendPosition.hxx" +#include <res_LegendPosition.hxx> +#include <TextDirectionListBox.hxx> +#include <chartview/ChartSfxItemIds.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/frmdiritem.hxx> + +namespace chart +{ + +SchLegendPosTabPage::SchLegendPosTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_LegendPosition.ui", "tp_LegendPosition", &rInAttrs) + , m_aLegendPositionResources(*m_xBuilder) + , m_xLbTextDirection(new TextDirectionListBox(m_xBuilder->weld_combo_box("LB_LEGEND_TEXTDIR"))) + , m_xCBLegendNoOverlay(m_xBuilder->weld_check_button("CB_NO_OVERLAY")) +{ +} + +SchLegendPosTabPage::~SchLegendPosTabPage() +{ + m_xLbTextDirection.reset(); +} + +std::unique_ptr<SfxTabPage> SchLegendPosTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<SchLegendPosTabPage>(pPage, pController, *rOutAttrs); +} + +bool SchLegendPosTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + m_aLegendPositionResources.writeToItemSet(*rOutAttrs); + + if (m_xLbTextDirection->get_active() != -1) + rOutAttrs->Put(SvxFrameDirectionItem(m_xLbTextDirection->get_active_id(), EE_PARA_WRITINGDIR)); + + if (m_xCBLegendNoOverlay->get_visible()) + rOutAttrs->Put(SfxBoolItem(SCHATTR_LEGEND_NO_OVERLAY, m_xCBLegendNoOverlay->get_active())); + + return true; +} + +void SchLegendPosTabPage::Reset(const SfxItemSet* rInAttrs) +{ + m_aLegendPositionResources.initFromItemSet(*rInAttrs); + + const SfxPoolItem* pPoolItem = nullptr; + if( rInAttrs->GetItemState( EE_PARA_WRITINGDIR, true, &pPoolItem ) == SfxItemState::SET ) + m_xLbTextDirection->set_active_id( static_cast<const SvxFrameDirectionItem*>(pPoolItem)->GetValue() ); + + if (rInAttrs->GetItemState(SCHATTR_LEGEND_NO_OVERLAY, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + m_xCBLegendNoOverlay->set_active(bVal); + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_LegendPosition.hxx b/chart2/source/controller/dialogs/tp_LegendPosition.hxx new file mode 100644 index 000000000..61e4c8929 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_LegendPosition.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_LEGENDPOSITION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_LEGENDPOSITION_HXX + +#include <sfx2/tabdlg.hxx> + +#include <res_LegendPosition.hxx> + +namespace chart { class TextDirectionListBox; } + +namespace chart +{ + +class SchLegendPosTabPage : public SfxTabPage +{ +private: + + LegendPositionResources m_aLegendPositionResources; + std::unique_ptr<TextDirectionListBox> m_xLbTextDirection; + std::unique_ptr<weld::CheckButton> m_xCBLegendNoOverlay; + +public: + SchLegendPosTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SchLegendPosTabPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + virtual bool FillItemSet(SfxItemSet* rOutAttrs) override; + virtual void Reset(const SfxItemSet* rInAttrs) override; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_PointGeometry.cxx b/chart2/source/controller/dialogs/tp_PointGeometry.cxx new file mode 100644 index 000000000..6d2ac1b45 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PointGeometry.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_PointGeometry.hxx" +#include <res_BarGeometry.hxx> + +#include <chartview/ChartSfxItemIds.hxx> + +#include <svl/intitem.hxx> +#include <svx/svx3ditems.hxx> + +namespace chart +{ + +SchLayoutTabPage::SchLayoutTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_ChartType.ui", "tp_ChartType", &rInAttrs) +{ + m_pGeometryResources.reset(new BarGeometryResources(m_xBuilder.get())); +} + +SchLayoutTabPage::~SchLayoutTabPage() +{ + m_pGeometryResources.reset(); +} + +std::unique_ptr<SfxTabPage> SchLayoutTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<SchLayoutTabPage>(pPage, pController, *rOutAttrs); +} + +bool SchLayoutTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + int nShape = m_pGeometryResources ? m_pGeometryResources->get_selected_index() : -1; + if (nShape != -1) + { + long nSegs=32; + + if (nShape==CHART_SHAPE3D_PYRAMID) + nSegs=4; + + rOutAttrs->Put(SfxInt32Item(SCHATTR_STYLE_SHAPE,nShape)); + rOutAttrs->Put(makeSvx3DHorizontalSegmentsItem(nSegs)); + } + return true; +} + +void SchLayoutTabPage::Reset(const SfxItemSet* rInAttrs) +{ + const SfxPoolItem *pPoolItem = nullptr; + + if (rInAttrs->GetItemState(SCHATTR_STYLE_SHAPE,true, &pPoolItem) == SfxItemState::SET) + { + long nVal = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + if(m_pGeometryResources) + { + m_pGeometryResources->select(static_cast<sal_uInt16>(nVal)); + m_pGeometryResources->set_visible(true); + } + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_PointGeometry.hxx b/chart2/source/controller/dialogs/tp_PointGeometry.hxx new file mode 100644 index 000000000..2438ce898 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PointGeometry.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POINTGEOMETRY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POINTGEOMETRY_HXX + +#include <sfx2/tabdlg.hxx> + +namespace chart +{ + +class BarGeometryResources; +class SchLayoutTabPage : public SfxTabPage +{ +public: + SchLayoutTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SchLayoutTabPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + virtual bool FillItemSet(SfxItemSet* rOutAttrs) override; + virtual void Reset(const SfxItemSet* rInAttrs) override; + +private: + std::unique_ptr<BarGeometryResources> m_pGeometryResources; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_PolarOptions.cxx b/chart2/source/controller/dialogs/tp_PolarOptions.cxx new file mode 100644 index 000000000..804c42212 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PolarOptions.cxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_PolarOptions.hxx" +#include <chartview/ChartSfxItemIds.hxx> + +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> + +namespace chart +{ + +PolarOptionsTabPage::PolarOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_PolarOptions.ui", "tp_PolarOptions", &rInAttrs) + , m_xCB_Clockwise(m_xBuilder->weld_check_button("CB_CLOCKWISE")) + , m_xFL_StartingAngle(m_xBuilder->weld_frame("frameANGLE")) + , m_xNF_StartingAngle(m_xBuilder->weld_metric_spin_button("NF_STARTING_ANGLE", FieldUnit::DEGREE)) + , m_xFL_PlotOptions(m_xBuilder->weld_frame("framePLOT_OPTIONS")) + , m_xCB_IncludeHiddenCells(m_xBuilder->weld_check_button("CB_INCLUDE_HIDDEN_CELLS_POLAR")) + , m_xAngleDial(new svx::DialControl) + , m_xAngleDialWin(new weld::CustomWeld(*m_xBuilder, "CT_ANGLE_DIAL", *m_xAngleDial)) +{ + m_xAngleDial->SetLinkedField(m_xNF_StartingAngle.get()); +} + +PolarOptionsTabPage::~PolarOptionsTabPage() +{ + m_xAngleDialWin.reset(); + m_xAngleDial.reset(); +} + +std::unique_ptr<SfxTabPage> PolarOptionsTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<PolarOptionsTabPage>(pPage, pController, *rOutAttrs); +} + +bool PolarOptionsTabPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + if (m_xAngleDialWin->get_visible()) + { + rOutAttrs->Put(SfxInt32Item(SCHATTR_STARTING_ANGLE, + static_cast< sal_Int32 >(m_xAngleDial->GetRotation()/100))); + } + + if( m_xCB_Clockwise->get_visible() ) + rOutAttrs->Put(SfxBoolItem(SCHATTR_CLOCKWISE,m_xCB_Clockwise->get_active())); + + if (m_xCB_IncludeHiddenCells->get_visible()) + rOutAttrs->Put(SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, m_xCB_IncludeHiddenCells->get_active())); + + return true; +} + +void PolarOptionsTabPage::Reset(const SfxItemSet* rInAttrs) +{ + const SfxPoolItem *pPoolItem = nullptr; + + if (rInAttrs->GetItemState(SCHATTR_STARTING_ANGLE, true, &pPoolItem) == SfxItemState::SET) + { + long nTmp = static_cast<long>(static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()); + m_xAngleDial->SetRotation( nTmp*100 ); + } + else + { + m_xFL_StartingAngle->hide(); + } + if (rInAttrs->GetItemState(SCHATTR_CLOCKWISE, true, &pPoolItem) == SfxItemState::SET) + { + bool bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCB_Clockwise->set_active(bCheck); + } + else + { + m_xCB_Clockwise->hide(); + } + if (rInAttrs->GetItemState(SCHATTR_INCLUDE_HIDDEN_CELLS, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + m_xCB_IncludeHiddenCells->set_active(bVal); + } + else + { + m_xFL_PlotOptions->hide(); + } +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_PolarOptions.hxx b/chart2/source/controller/dialogs/tp_PolarOptions.hxx new file mode 100644 index 000000000..e5d4287cb --- /dev/null +++ b/chart2/source/controller/dialogs/tp_PolarOptions.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POLAROPTIONS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_POLAROPTIONS_HXX + +#include <sfx2/tabdlg.hxx> +#include <svx/dialcontrol.hxx> + +namespace weld { + class CheckButton; + class CustomWeld; + class Frame; + class SpinButton; +} + +namespace chart +{ + +class PolarOptionsTabPage : public SfxTabPage +{ + +public: + PolarOptionsTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~PolarOptionsTabPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + virtual bool FillItemSet(SfxItemSet* rOutAttrs) override; + virtual void Reset(const SfxItemSet* rInAttrs) override; + +private: + std::unique_ptr<weld::CheckButton> m_xCB_Clockwise; + std::unique_ptr<weld::Frame> m_xFL_StartingAngle; + std::unique_ptr<weld::MetricSpinButton> m_xNF_StartingAngle; + std::unique_ptr<weld::Frame> m_xFL_PlotOptions; + std::unique_ptr<weld::CheckButton> m_xCB_IncludeHiddenCells; + std::unique_ptr<svx::DialControl> m_xAngleDial; + std::unique_ptr<weld::CustomWeld> m_xAngleDialWin; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_RangeChooser.cxx b/chart2/source/controller/dialogs/tp_RangeChooser.cxx new file mode 100644 index 000000000..c11c9eee8 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_RangeChooser.cxx @@ -0,0 +1,382 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_RangeChooser.hxx" +#include <DataSourceHelper.hxx> +#include <ChartTypeTemplateProvider.hxx> +#include "DialogModel.hxx" +#include <RangeSelectionHelper.hxx> +#include <TabPageNotifiable.hxx> +#include <com/sun/star/beans/PropertyState.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <svtools/miscopt.hxx> +#include <osl/diagnose.h> + +namespace +{ + void lcl_ShowChooserButton( + weld::Button& rChooserButton, + bool bShow) + { + if( rChooserButton.get_visible() != bShow ) + { + rChooserButton.set_visible( bShow ); + } + } + + void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pDialog) + { + if (!pDialog) + return; + weld::Dialog* pDlg = pDialog->getDialog(); + pDlg->set_modal(!bEnable); + pDlg->set_visible(!bEnable); + } + +} // anonymous namespace + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Sequence; + +RangeChooserTabPage::RangeChooserTabPage(weld::Container* pPage, weld::DialogController* pController, DialogModel & rDialogModel, + ChartTypeTemplateProvider* pTemplateProvider, + bool bHideDescription /* = false */) + : OWizardPage(pPage, pController, "modules/schart/ui/tp_RangeChooser.ui", "tp_RangeChooser") + , m_nChangingControlCalls(0) + , m_bIsDirty(false) + , m_aLastValidRangeString() + , m_pTemplateProvider(pTemplateProvider) + , m_rDialogModel( rDialogModel ) + , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController)) + , m_xFT_Caption(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD")) + , m_xFT_Range(m_xBuilder->weld_label("FT_RANGE")) + , m_xED_Range(m_xBuilder->weld_entry("ED_RANGE")) + , m_xIB_Range(m_xBuilder->weld_button("IB_RANGE")) + , m_xRB_Rows(m_xBuilder->weld_radio_button("RB_DATAROWS")) + , m_xRB_Columns(m_xBuilder->weld_radio_button("RB_DATACOLS")) + , m_xCB_FirstRowAsLabel(m_xBuilder->weld_check_button("CB_FIRST_ROW_ASLABELS")) + , m_xCB_FirstColumnAsLabel(m_xBuilder->weld_check_button("CB_FIRST_COLUMN_ASLABELS")) + , m_xFTTitle(m_xBuilder->weld_label("STR_PAGE_DATA_RANGE")) + , m_xFL_TimeBased(m_xBuilder->weld_widget("separator1")) + , m_xCB_TimeBased(m_xBuilder->weld_check_button("CB_TIME_BASED")) + , m_xFT_TimeStart(m_xBuilder->weld_label("label1")) + , m_xEd_TimeStart(m_xBuilder->weld_entry("ED_TIME_BASED_START")) + , m_xFT_TimeEnd(m_xBuilder->weld_label("label2")) + , m_xEd_TimeEnd(m_xBuilder->weld_entry("ED_TIME_BASED_END")) +{ + m_xFT_Caption->set_visible(!bHideDescription); + + SetPageTitle(m_xFTTitle->get_label());// OH:remove later with dialog + + // set defaults as long as DetectArguments does not work + m_xRB_Columns->set_active(true); + m_xCB_FirstColumnAsLabel->set_active(true); + m_xCB_FirstRowAsLabel->set_active(true); + + // BM: Note, that the range selection is not available, if there is no view. + // This happens for charts having their own embedded spreadsheet. If you + // force to get the range selection here, this would mean when entering this + // page the calc view would be created in this case. So, I enable the + // button here, and in the worst case nothing happens when it is pressed. + // Not nice, but I see no better solution for the moment. + m_xIB_Range->connect_clicked( LINK( this, RangeChooserTabPage, ChooseRangeHdl )); + + m_xED_Range->connect_changed( LINK( this, RangeChooserTabPage, ControlEditedHdl )); + m_xRB_Rows->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedRadioHdl ) ); + m_xCB_FirstRowAsLabel->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) ); + m_xCB_FirstColumnAsLabel->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) ); + m_xCB_TimeBased->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) ); + m_xEd_TimeStart->connect_changed( LINK( this, RangeChooserTabPage, ControlChangedHdl ) ); + m_xEd_TimeEnd->connect_changed( LINK( this, RangeChooserTabPage, ControlChangedHdl ) ); + + SvtMiscOptions aOpts; + if ( !aOpts.IsExperimentalMode() ) + { + m_xFL_TimeBased->hide(); + m_xCB_TimeBased->hide(); + m_xFT_TimeStart->hide(); + m_xEd_TimeStart->hide(); + m_xFT_TimeEnd->hide(); + m_xEd_TimeEnd->hide(); + } +} + +RangeChooserTabPage::~RangeChooserTabPage() +{ +} + +void RangeChooserTabPage::Activate() +{ + OWizardPage::Activate(); + initControlsFromModel(); + m_xED_Range->grab_focus(); +} + +void RangeChooserTabPage::initControlsFromModel() +{ + m_nChangingControlCalls++; + + if(m_pTemplateProvider) + m_xCurrentChartTypeTemplate = m_pTemplateProvider->getCurrentTemplate(); + + bool bUseColumns = !m_xRB_Rows->get_active(); + bool bFirstCellAsLabel = bUseColumns ? m_xCB_FirstRowAsLabel->get_active() : m_xCB_FirstColumnAsLabel->get_active(); + bool bHasCategories = bUseColumns ? m_xCB_FirstColumnAsLabel->get_active() : m_xCB_FirstRowAsLabel->get_active(); + + bool bIsValid = m_rDialogModel.allArgumentsForRectRangeDetected(); + if( bIsValid ) + m_rDialogModel.detectArguments(m_aLastValidRangeString, bUseColumns, bFirstCellAsLabel, bHasCategories ); + else + m_aLastValidRangeString.clear(); + + m_xED_Range->set_text( m_aLastValidRangeString ); + + m_xRB_Rows->set_active( !bUseColumns ); + m_xRB_Columns->set_active( bUseColumns ); + + m_xCB_FirstRowAsLabel->set_active( m_xRB_Rows->get_active()?bHasCategories:bFirstCellAsLabel ); + m_xCB_FirstColumnAsLabel->set_active( m_xRB_Columns->get_active()?bHasCategories:bFirstCellAsLabel ); + + isValid(); + + m_nChangingControlCalls--; +} + +void RangeChooserTabPage::Deactivate() +{ + commitPage(); + vcl::OWizardPage::Deactivate(); +} + +void RangeChooserTabPage::commitPage() +{ + commitPage(::vcl::WizardTypes::eFinish); +} + +bool RangeChooserTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ ) +{ + //ranges may have been edited in the meanwhile (dirty is true in that case here) + if( isValid() ) + { + changeDialogModelAccordingToControls(); + return true; // return false if this page should not be left + } + else + return false; +} + +void RangeChooserTabPage::changeDialogModelAccordingToControls() +{ + if(m_nChangingControlCalls>0) + return; + + if( !m_xCurrentChartTypeTemplate.is() ) + { + if(m_pTemplateProvider) + m_xCurrentChartTypeTemplate.set( m_pTemplateProvider->getCurrentTemplate()); + if( !m_xCurrentChartTypeTemplate.is()) + { + OSL_FAIL( "Need a template to change data source" ); + return; + } + } + + if( !m_bIsDirty ) + return; + + bool bFirstCellAsLabel = ( m_xCB_FirstColumnAsLabel->get_active() && !m_xRB_Columns->get_active() ) + || ( m_xCB_FirstRowAsLabel->get_active() && !m_xRB_Rows->get_active() ); + bool bHasCategories = ( m_xCB_FirstColumnAsLabel->get_active() && m_xRB_Columns->get_active() ) + || ( m_xCB_FirstRowAsLabel->get_active() && m_xRB_Rows->get_active() ); + bool bTimeBased = m_xCB_TimeBased->get_active(); + + Sequence< beans::PropertyValue > aArguments( + DataSourceHelper::createArguments( + m_xRB_Columns->get_active(), bFirstCellAsLabel, bHasCategories ) ); + + if(bTimeBased) + { + aArguments.realloc( aArguments.getLength() + 1 ); + aArguments[aArguments.getLength() - 1] = + beans::PropertyValue( "TimeBased", -1, uno::Any(bTimeBased), + beans::PropertyState_DIRECT_VALUE ); + } + + // only if range is valid + if( m_aLastValidRangeString != m_xED_Range->get_text()) + return; + + m_rDialogModel.setTemplate( m_xCurrentChartTypeTemplate ); + aArguments.realloc( aArguments.getLength() + 1 ); + aArguments[aArguments.getLength() - 1] = + beans::PropertyValue( "CellRangeRepresentation" , -1, + uno::Any( m_aLastValidRangeString ), + beans::PropertyState_DIRECT_VALUE ); + m_rDialogModel.setData( aArguments ); + m_bIsDirty = false; + + if(bTimeBased) + { + sal_Int32 nStart = m_xEd_TimeStart->get_text().toInt32(); + sal_Int32 nEnd = m_xEd_TimeEnd->get_text().toInt32(); + m_rDialogModel.setTimeBasedRange(true, nStart, nEnd); + } + + //@todo warn user that the selected range is not valid + //@todo better: disable OK-Button if range is invalid +} + +bool RangeChooserTabPage::isValid() +{ + OUString aRange( m_xED_Range->get_text()); + bool bFirstCellAsLabel = ( m_xCB_FirstColumnAsLabel->get_active() && !m_xRB_Columns->get_active() ) + || ( m_xCB_FirstRowAsLabel->get_active() && !m_xRB_Rows->get_active() ); + bool bHasCategories = ( m_xCB_FirstColumnAsLabel->get_active() && m_xRB_Columns->get_active() ) + || ( m_xCB_FirstRowAsLabel->get_active() && m_xRB_Rows->get_active() ); + bool bIsValid = ( aRange.isEmpty() ) || + m_rDialogModel.getRangeSelectionHelper()->verifyArguments( + DataSourceHelper::createArguments( + aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(), bFirstCellAsLabel, bHasCategories )); + + if( bIsValid ) + { + m_xED_Range->set_message_type(weld::EntryMessageType::Normal); + if( m_pTabPageNotifiable ) + m_pTabPageNotifiable->setValidPage( this ); + m_aLastValidRangeString = aRange; + } + else + { + m_xED_Range->set_message_type(weld::EntryMessageType::Error); + if( m_pTabPageNotifiable ) + m_pTabPageNotifiable->setInvalidPage( this ); + } + + // enable/disable controls + // #i79531# if the range is valid but an action of one of these buttons + // would render it invalid, the button should be disabled + if( bIsValid ) + { + bool bDataInColumns = m_xRB_Columns->get_active(); + bool bIsSwappedRangeValid = m_rDialogModel.getRangeSelectionHelper()->verifyArguments( + DataSourceHelper::createArguments( + aRange, Sequence< sal_Int32 >(), ! bDataInColumns, bHasCategories, bFirstCellAsLabel )); + m_xRB_Rows->set_sensitive( bIsSwappedRangeValid ); + m_xRB_Columns->set_sensitive( bIsSwappedRangeValid ); + + m_xCB_FirstRowAsLabel->set_sensitive( + m_rDialogModel.getRangeSelectionHelper()->verifyArguments( + DataSourceHelper::createArguments( + aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(), + bDataInColumns ? ! bFirstCellAsLabel : bFirstCellAsLabel, + bDataInColumns ? bHasCategories : ! bHasCategories ))); + m_xCB_FirstColumnAsLabel->set_sensitive( + m_rDialogModel.getRangeSelectionHelper()->verifyArguments( + DataSourceHelper::createArguments( + aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(), + bDataInColumns ? bFirstCellAsLabel : ! bFirstCellAsLabel, + bDataInColumns ? ! bHasCategories : bHasCategories ))); + } + else + { + m_xRB_Rows->set_sensitive( bIsValid ); + m_xRB_Columns->set_sensitive( bIsValid ); + m_xCB_FirstRowAsLabel->set_sensitive( bIsValid ); + m_xCB_FirstColumnAsLabel->set_sensitive( bIsValid ); + } + + bool bShowIB = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection(); + lcl_ShowChooserButton( *m_xIB_Range, bShowIB ); + + return bIsValid; +} + +IMPL_LINK_NOARG(RangeChooserTabPage, ControlEditedHdl, weld::Entry&, void) +{ + setDirty(); + isValid(); +} + +IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedRadioHdl, weld::ToggleButton&, void) +{ + ControlChangedHdl(*m_xED_Range); +} + +IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedCheckBoxHdl, weld::ToggleButton&, void) +{ + ControlChangedHdl(*m_xED_Range); +} + +IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedHdl, weld::Entry&, void) +{ + setDirty(); + if( isValid()) + changeDialogModelAccordingToControls(); +} + +IMPL_LINK_NOARG(RangeChooserTabPage, ChooseRangeHdl, weld::Button&, void) +{ + OUString aRange = m_xED_Range->get_text(); + OUString aTitle = m_xFTTitle->get_label(); + + lcl_enableRangeChoosing(true, m_pDialogController); + m_rDialogModel.getRangeSelectionHelper()->chooseRange( aRange, aTitle, *this ); +} + +void RangeChooserTabPage::listeningFinished( const OUString & rNewRange ) +{ + //user has selected a new range + + // rNewRange becomes invalid after removing the listener + OUString aRange( rNewRange ); + + m_rDialogModel.startControllerLockTimer(); + + // stop listening + m_rDialogModel.getRangeSelectionHelper()->stopRangeListening(); + + //update dialog state + m_xED_Range->set_text(aRange); + m_xED_Range->grab_focus(); + + setDirty(); + if( isValid()) + changeDialogModelAccordingToControls(); + + lcl_enableRangeChoosing(false, m_pDialogController); +} + +void RangeChooserTabPage::disposingRangeSelection() +{ + m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false ); +} + +void RangeChooserTabPage::setDirty() +{ + if( m_nChangingControlCalls == 0 ) + m_bIsDirty = true; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_RangeChooser.hxx b/chart2/source/controller/dialogs/tp_RangeChooser.hxx new file mode 100644 index 000000000..b337910cc --- /dev/null +++ b/chart2/source/controller/dialogs/tp_RangeChooser.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_RANGECHOOSER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_RANGECHOOSER_HXX + +#include <RangeSelectionListener.hxx> + +#include <vcl/wizardmachine.hxx> + +namespace chart { class TabPageNotifiable; } +namespace com::sun::star::chart2 { class XChartTypeTemplate; } + +namespace chart +{ + +class ChartTypeTemplateProvider; +class DialogModel; + +class RangeChooserTabPage final : public vcl::OWizardPage, public RangeSelectionListenerParent +{ +public: + + RangeChooserTabPage(weld::Container* pPage, weld::DialogController* pController, DialogModel & rDialogModel, + ChartTypeTemplateProvider* pTemplateProvider, + bool bHideDescription = false); + virtual ~RangeChooserTabPage() override; + + //RangeSelectionListenerParent + virtual void listeningFinished( const OUString & rNewRange ) override; + virtual void disposingRangeSelection() override; + + virtual void Activate() override; + + void commitPage(); + +private: + + //OWizardPage + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override; + + //TabPage + virtual void Deactivate() override; + + void initControlsFromModel(); + void changeDialogModelAccordingToControls(); + bool isValid(); + void setDirty(); + + DECL_LINK( ChooseRangeHdl, weld::Button&, void ); + DECL_LINK( ControlChangedHdl, weld::Entry&, void ); + DECL_LINK( ControlChangedCheckBoxHdl, weld::ToggleButton&, void ); + DECL_LINK( ControlChangedRadioHdl, weld::ToggleButton&, void ); + DECL_LINK( ControlEditedHdl, weld::Entry&, void ); + + sal_Int32 m_nChangingControlCalls; + bool m_bIsDirty; + + OUString m_aLastValidRangeString; + css::uno::Reference< css::chart2::XChartTypeTemplate > m_xCurrentChartTypeTemplate; + ChartTypeTemplateProvider* m_pTemplateProvider; + + DialogModel & m_rDialogModel; + TabPageNotifiable * m_pTabPageNotifiable; + + std::unique_ptr<weld::Label> m_xFT_Caption; + std::unique_ptr<weld::Label> m_xFT_Range; + std::unique_ptr<weld::Entry> m_xED_Range; + std::unique_ptr<weld::Button> m_xIB_Range; + std::unique_ptr<weld::RadioButton> m_xRB_Rows; + std::unique_ptr<weld::RadioButton> m_xRB_Columns; + std::unique_ptr<weld::CheckButton> m_xCB_FirstRowAsLabel; + std::unique_ptr<weld::CheckButton> m_xCB_FirstColumnAsLabel; + std::unique_ptr<weld::Label> m_xFTTitle; + std::unique_ptr<weld::Widget> m_xFL_TimeBased; + std::unique_ptr<weld::CheckButton> m_xCB_TimeBased; + std::unique_ptr<weld::Label> m_xFT_TimeStart; + std::unique_ptr<weld::Entry> m_xEd_TimeStart; + std::unique_ptr<weld::Label> m_xFT_TimeEnd; + std::unique_ptr<weld::Entry> m_xEd_TimeEnd; +}; + +} //namespace chart +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_Scale.cxx b/chart2/source/controller/dialogs/tp_Scale.cxx new file mode 100644 index 000000000..0c6266677 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Scale.cxx @@ -0,0 +1,604 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_Scale.hxx" + +#include <ResId.hxx> +#include <strings.hrc> +#include <chartview/ChartSfxItemIds.hxx> +#include <AxisHelper.hxx> + +#include <svx/svxids.hrc> +#include <osl/diagnose.h> +#include <svx/chrtitem.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <vcl/weld.hxx> +#include <svl/zformat.hxx> +#include <vcl/svapp.hxx> + +#include <com/sun/star/chart2/AxisType.hpp> + +using namespace ::com::sun::star; + +namespace chart +{ + +namespace +{ + +void lcl_setValue(weld::FormattedSpinButton& rFmtField, double fValue) +{ + rFmtField.set_value(fValue); +} + +} + +ScaleTabPage::ScaleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_Scale.ui", "tp_Scale", &rInAttrs) + , fMin(0.0) + , fMax(0.0) + , fStepMain(0.0) + , nStepHelp(0) + , fOrigin(0.0) + , m_nTimeResolution(1) + , m_nMainTimeUnit(1) + , m_nHelpTimeUnit(1) + , m_nAxisType(chart2::AxisType::REALNUMBER) + , m_bAllowDateAxis(false) + , pNumFormatter(nullptr) + , m_bShowAxisOrigin(false) + , m_xCbxReverse(m_xBuilder->weld_check_button("CBX_REVERSE")) + , m_xCbxLogarithm(m_xBuilder->weld_check_button("CBX_LOGARITHM")) + , m_xBxType(m_xBuilder->weld_widget("boxTYPE")) + , m_xLB_AxisType(m_xBuilder->weld_combo_box("LB_AXIS_TYPE")) + , m_xBxMinMax(m_xBuilder->weld_widget("gridMINMAX")) + , m_xFmtFldMin(m_xBuilder->weld_formatted_spin_button("EDT_MIN")) + , m_xCbxAutoMin(m_xBuilder->weld_check_button("CBX_AUTO_MIN")) + , m_xFmtFldMax(m_xBuilder->weld_formatted_spin_button("EDT_MAX")) + , m_xCbxAutoMax(m_xBuilder->weld_check_button("CBX_AUTO_MAX")) + , m_xBxResolution(m_xBuilder->weld_widget("boxRESOLUTION")) + , m_xLB_TimeResolution(m_xBuilder->weld_combo_box("LB_TIME_RESOLUTION")) + , m_xCbx_AutoTimeResolution(m_xBuilder->weld_check_button("CBX_AUTO_TIME_RESOLUTION")) + , m_xTxtMain(m_xBuilder->weld_label("TXT_STEP_MAIN")) + , m_xFmtFldStepMain(m_xBuilder->weld_formatted_spin_button("EDT_STEP_MAIN")) + , m_xMt_MainDateStep(m_xBuilder->weld_spin_button("MT_MAIN_DATE_STEP")) + , m_xLB_MainTimeUnit(m_xBuilder->weld_combo_box("LB_MAIN_TIME_UNIT")) + , m_xCbxAutoStepMain(m_xBuilder->weld_check_button("CBX_AUTO_STEP_MAIN")) + , m_xTxtHelpCount(m_xBuilder->weld_label("TXT_STEP_HELP_COUNT")) + , m_xTxtHelp(m_xBuilder->weld_label("TXT_STEP_HELP")) + , m_xMtStepHelp(m_xBuilder->weld_spin_button("MT_STEPHELP")) + , m_xLB_HelpTimeUnit(m_xBuilder->weld_combo_box("LB_HELP_TIME_UNIT")) + , m_xCbxAutoStepHelp(m_xBuilder->weld_check_button("CBX_AUTO_STEP_HELP")) + , m_xFmtFldOrigin(m_xBuilder->weld_formatted_spin_button("EDT_ORIGIN")) + , m_xCbxAutoOrigin(m_xBuilder->weld_check_button("CBX_AUTO_ORIGIN")) + , m_xBxOrigin(m_xBuilder->weld_widget("boxORIGIN")) +{ + m_xCbxAutoMin->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); + m_xCbxAutoMax->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); + m_xCbxAutoStepMain->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); + m_xCbxAutoStepHelp->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); + m_xCbxAutoOrigin->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); + m_xCbx_AutoTimeResolution->connect_toggled(LINK(this, ScaleTabPage, EnableValueHdl)); + + const double nMin = static_cast<double>(SAL_MIN_INT64); + const double nMax = static_cast<double>(SAL_MAX_INT64); + m_xFmtFldMin->set_range(nMin, nMax); + m_xFmtFldMax->set_range(nMin, nMax); + m_xFmtFldStepMain->set_range(nMin, nMax); + m_xFmtFldOrigin->set_range(nMin, nMax); + + m_xLB_AxisType->connect_changed(LINK(this, ScaleTabPage, SelectAxisTypeHdl)); + + HideAllControls(); +} + +ScaleTabPage::~ScaleTabPage() +{ +} + +void ScaleTabPage::EnableControls() +{ + bool bValueAxis = m_nAxisType == chart2::AxisType::REALNUMBER + || m_nAxisType == chart2::AxisType::PERCENT + || m_nAxisType == chart2::AxisType::DATE; + bool bDateAxis = m_nAxisType == chart2::AxisType::DATE; + + m_xBxType->set_visible(m_bAllowDateAxis); + + m_xCbxLogarithm->set_visible( bValueAxis && !bDateAxis ); + + m_xBxMinMax->set_visible(bValueAxis); + + m_xTxtMain->set_visible( bValueAxis ); + m_xCbxAutoStepMain->set_visible( bValueAxis ); + + m_xTxtHelpCount->set_visible( bValueAxis && !bDateAxis ); + m_xTxtHelp->set_visible( bDateAxis ); + m_xMtStepHelp->set_visible( bValueAxis ); + m_xCbxAutoStepHelp->set_visible( bValueAxis ); + + m_xBxOrigin->set_visible( m_bShowAxisOrigin && bValueAxis ); + m_xBxResolution->set_visible( bDateAxis ); + + bool bWasDateAxis = m_xMt_MainDateStep->get_visible(); + if( bWasDateAxis != bDateAxis ) + { + //transport value from one to other control + if( bWasDateAxis ) + lcl_setValue( *m_xFmtFldStepMain, m_xMt_MainDateStep->get_value() ); + else + m_xMt_MainDateStep->set_value(m_xFmtFldStepMain->get_value()); + } + + m_xFmtFldStepMain->set_visible( bValueAxis && !bDateAxis ); + m_xMt_MainDateStep->set_visible( bDateAxis ); + + m_xLB_MainTimeUnit->set_visible( bDateAxis ); + m_xLB_HelpTimeUnit->set_visible( bDateAxis ); + + EnableValueHdl(*m_xCbxAutoMin); + EnableValueHdl(*m_xCbxAutoMax); + EnableValueHdl(*m_xCbxAutoStepMain); + EnableValueHdl(*m_xCbxAutoStepHelp); + EnableValueHdl(*m_xCbxAutoOrigin); + EnableValueHdl(*m_xCbx_AutoTimeResolution); +} + +IMPL_LINK( ScaleTabPage, EnableValueHdl, weld::ToggleButton&, rCbx, void ) +{ + bool bEnable = !rCbx.get_active() && rCbx.get_sensitive(); + if (&rCbx == m_xCbxAutoMin.get()) + { + m_xFmtFldMin->set_sensitive( bEnable ); + } + else if (&rCbx == m_xCbxAutoMax.get()) + { + m_xFmtFldMax->set_sensitive( bEnable ); + } + else if (&rCbx == m_xCbxAutoStepMain.get()) + { + m_xFmtFldStepMain->set_sensitive( bEnable ); + m_xMt_MainDateStep->set_sensitive( bEnable ); + m_xLB_MainTimeUnit->set_sensitive( bEnable ); + } + else if (&rCbx == m_xCbxAutoStepHelp.get()) + { + m_xMtStepHelp->set_sensitive( bEnable ); + m_xLB_HelpTimeUnit->set_sensitive( bEnable ); + } + else if (&rCbx == m_xCbx_AutoTimeResolution.get()) + { + m_xLB_TimeResolution->set_sensitive( bEnable ); + } + else if (&rCbx == m_xCbxAutoOrigin.get()) + { + m_xFmtFldOrigin->set_sensitive( bEnable ); + } +} + +namespace { + +enum AxisTypeListBoxEntry +{ + TYPE_AUTO=0, + TYPE_TEXT=1, + TYPE_DATE=2 +}; + +} + +IMPL_LINK_NOARG(ScaleTabPage, SelectAxisTypeHdl, weld::ComboBox&, void) +{ + const sal_Int32 nPos = m_xLB_AxisType->get_active(); + if( nPos==TYPE_DATE ) + m_nAxisType = chart2::AxisType::DATE; + else + m_nAxisType = chart2::AxisType::CATEGORY; + if( m_nAxisType == chart2::AxisType::DATE ) + m_xCbxLogarithm->set_active(false); + EnableControls(); + SetNumFormat(); +} + +std::unique_ptr<SfxTabPage> ScaleTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<ScaleTabPage>(pPage, pController, *rOutAttrs); +} + +bool ScaleTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + OSL_PRECOND( pNumFormatter, "No NumberFormatter available" ); + + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXISTYPE, m_nAxisType)); + if(m_bAllowDateAxis) + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_DATEAXIS, m_xLB_AxisType->get_active()==TYPE_AUTO)); + + bool bAutoScale = false; + if( m_nAxisType==chart2::AxisType::CATEGORY ) + bAutoScale = true;//reset scaling for category charts + + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_MIN ,bAutoScale || m_xCbxAutoMin->get_active())); + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_MAX ,bAutoScale || m_xCbxAutoMax->get_active())); + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_HELP,bAutoScale || m_xCbxAutoStepHelp->get_active())); + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_ORIGIN ,bAutoScale || m_xCbxAutoOrigin->get_active())); + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_LOGARITHM ,m_xCbxLogarithm->get_active())); + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_REVERSE ,m_xCbxReverse->get_active())); + rOutAttrs->Put(SvxDoubleItem(fMax , SCHATTR_AXIS_MAX)); + rOutAttrs->Put(SvxDoubleItem(fMin , SCHATTR_AXIS_MIN)); + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_STEP_HELP, nStepHelp)); + rOutAttrs->Put(SvxDoubleItem(fOrigin , SCHATTR_AXIS_ORIGIN)); + + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_STEP_MAIN,bAutoScale || m_xCbxAutoStepMain->get_active())); + rOutAttrs->Put(SvxDoubleItem(fStepMain,SCHATTR_AXIS_STEP_MAIN)); + + rOutAttrs->Put(SfxBoolItem(SCHATTR_AXIS_AUTO_TIME_RESOLUTION,bAutoScale || m_xCbx_AutoTimeResolution->get_active())); + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_TIME_RESOLUTION,m_nTimeResolution)); + + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_MAIN_TIME_UNIT,m_nMainTimeUnit)); + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS_HELP_TIME_UNIT,m_nHelpTimeUnit)); + + return true; +} + +void ScaleTabPage::Reset(const SfxItemSet* rInAttrs) +{ + OSL_PRECOND( pNumFormatter, "No NumberFormatter available" ); + if(!pNumFormatter) + return; + + const SfxPoolItem *pPoolItem = nullptr; + if (rInAttrs->GetItemState(SCHATTR_AXIS_ALLOW_DATEAXIS, true, &pPoolItem) == SfxItemState::SET) + m_bAllowDateAxis = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + m_nAxisType=chart2::AxisType::REALNUMBER; + if (rInAttrs->GetItemState(SCHATTR_AXISTYPE, true, &pPoolItem) == SfxItemState::SET) + m_nAxisType = static_cast<int>(static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()); + if( m_nAxisType==chart2::AxisType::DATE && !m_bAllowDateAxis ) + m_nAxisType=chart2::AxisType::CATEGORY; + if( m_bAllowDateAxis ) + { + bool bAutoDateAxis = false; + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_DATEAXIS, true, &pPoolItem) == SfxItemState::SET) + bAutoDateAxis = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + + sal_uInt16 nPos = 0; + if( m_nAxisType==chart2::AxisType::DATE ) + nPos=TYPE_DATE; + else if( bAutoDateAxis ) + nPos=TYPE_AUTO; + else + nPos=TYPE_TEXT; + m_xLB_AxisType->set_active( nPos ); + } + + m_xCbxAutoMin->set_active(true); + m_xCbxAutoMax->set_active(true); + m_xCbxAutoStepMain->set_active(true); + m_xCbxAutoStepHelp->set_active(true); + m_xCbxAutoOrigin->set_active(true); + m_xCbx_AutoTimeResolution->set_active(true); + + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_MIN,true,&pPoolItem) == SfxItemState::SET) + m_xCbxAutoMin->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + + if (rInAttrs->GetItemState(SCHATTR_AXIS_MIN,true, &pPoolItem) == SfxItemState::SET) + { + fMin = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldMin, fMin ); + m_xFmtFldMin->save_value(); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_MAX,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoMax->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + + if (rInAttrs->GetItemState(SCHATTR_AXIS_MAX,true, &pPoolItem) == SfxItemState::SET) + { + fMax = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldMax, fMax ); + m_xFmtFldMax->save_value(); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_STEP_MAIN,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoStepMain->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + + if (rInAttrs->GetItemState(SCHATTR_AXIS_STEP_MAIN,true, &pPoolItem) == SfxItemState::SET) + { + fStepMain = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldStepMain, fStepMain ); + m_xFmtFldStepMain->save_value(); + m_xMt_MainDateStep->set_value( static_cast<sal_Int32>(fStepMain) ); + m_xMt_MainDateStep->save_value(); + } + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_STEP_HELP,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoStepHelp->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_LOGARITHM,true, &pPoolItem) == SfxItemState::SET) + m_xCbxLogarithm->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_REVERSE,true, &pPoolItem) == SfxItemState::SET) + m_xCbxReverse->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_STEP_HELP,true, &pPoolItem) == SfxItemState::SET) + { + nStepHelp = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + m_xMtStepHelp->set_value( nStepHelp ); + m_xMtStepHelp->save_value(); + } + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_ORIGIN,true, &pPoolItem) == SfxItemState::SET) + m_xCbxAutoOrigin->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_ORIGIN,true, &pPoolItem) == SfxItemState::SET) + { + fOrigin = static_cast<const SvxDoubleItem*>(pPoolItem)->GetValue(); + lcl_setValue( *m_xFmtFldOrigin, fOrigin ); + m_xFmtFldOrigin->save_value(); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_AUTO_TIME_RESOLUTION,true, &pPoolItem) == SfxItemState::SET) + m_xCbx_AutoTimeResolution->set_active(static_cast<const SfxBoolItem*>(pPoolItem)->GetValue()); + if (rInAttrs->GetItemState(SCHATTR_AXIS_TIME_RESOLUTION,true, &pPoolItem) == SfxItemState::SET) + { + m_nTimeResolution = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + m_xLB_TimeResolution->set_active( m_nTimeResolution ); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_MAIN_TIME_UNIT,true, &pPoolItem) == SfxItemState::SET) + { + m_nMainTimeUnit = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + m_xLB_MainTimeUnit->set_active( m_nMainTimeUnit ); + } + if (rInAttrs->GetItemState(SCHATTR_AXIS_HELP_TIME_UNIT,true, &pPoolItem) == SfxItemState::SET) + { + m_nHelpTimeUnit = static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + m_xLB_HelpTimeUnit->set_active( m_nHelpTimeUnit ); + } + + EnableControls(); + SetNumFormat(); +} + +DeactivateRC ScaleTabPage::DeactivatePage(SfxItemSet* pItemSet) +{ + if( !pNumFormatter ) + { + OSL_FAIL( "No NumberFormatter available" ); + return DeactivateRC::LeavePage; + } + + bool bDateAxis = m_nAxisType == chart2::AxisType::DATE; + + sal_uInt32 nMinMaxOriginFmt = m_xFmtFldMax->get_format_key(); + if (pNumFormatter->GetType(nMinMaxOriginFmt) == SvNumFormatType::TEXT) + nMinMaxOriginFmt = 0; + // numberformat_text cause numbers to fail being numbers... Shouldn't happen, but can. + sal_uInt32 nStepFmt = m_xFmtFldStepMain->get_format_key(); + if (pNumFormatter->GetType(nStepFmt) == SvNumFormatType::TEXT) + nStepFmt = 0; + + weld::Widget* pControl = nullptr; + const char* pErrStrId = nullptr; + double fDummy; + + fMax = m_xFmtFldMax->get_value(); + fMin = m_xFmtFldMin->get_value(); + fOrigin = m_xFmtFldOrigin->get_value(); + fStepMain = bDateAxis ? m_xMt_MainDateStep->get_value() : m_xFmtFldStepMain->get_value(); + nStepHelp = m_xMtStepHelp->get_value(); + m_nTimeResolution = m_xLB_TimeResolution->get_active(); + m_nMainTimeUnit = m_xLB_MainTimeUnit->get_active(); + m_nHelpTimeUnit = m_xLB_HelpTimeUnit->get_active(); + + if( m_nAxisType != chart2::AxisType::REALNUMBER ) + m_xCbxLogarithm->hide(); + + //check which entries need user action + + if ( m_xCbxLogarithm->get_active() && + ( ( !m_xCbxAutoMin->get_active() && fMin <= 0.0 ) + || ( !m_xCbxAutoMax->get_active() && fMax <= 0.0 ) ) ) + { + pControl = m_xFmtFldMin.get(); + pErrStrId = STR_BAD_LOGARITHM; + } + // check for entries that cannot be parsed for the current number format + else if ( m_xFmtFldMin->get_value_changed_from_saved() + && !m_xCbxAutoMin->get_active() + && !pNumFormatter->IsNumberFormat( m_xFmtFldMin->get_text(), nMinMaxOriginFmt, fDummy)) + { + pControl = m_xFmtFldMin.get(); + pErrStrId = STR_INVALID_NUMBER; + } + else if ( m_xFmtFldMax->get_value_changed_from_saved() + && !m_xCbxAutoMax->get_active() + && !pNumFormatter->IsNumberFormat( m_xFmtFldMax->get_text(), nMinMaxOriginFmt, fDummy)) + { + pControl = m_xFmtFldMax.get(); + pErrStrId = STR_INVALID_NUMBER; + } + else if ( !bDateAxis && m_xFmtFldStepMain->get_value_changed_from_saved() + && !m_xCbxAutoStepMain->get_active() + && !pNumFormatter->IsNumberFormat( m_xFmtFldStepMain->get_text(), nStepFmt, fDummy)) + { + pControl = m_xFmtFldStepMain.get(); + pErrStrId = STR_INVALID_NUMBER; + } + else if (m_xFmtFldOrigin->get_value_changed_from_saved() && !m_xCbxAutoOrigin->get_active() && + !pNumFormatter->IsNumberFormat( m_xFmtFldOrigin->get_text(), nMinMaxOriginFmt, fDummy)) + { + pControl = m_xFmtFldOrigin.get(); + pErrStrId = STR_INVALID_NUMBER; + } + else if (!m_xCbxAutoStepMain->get_active() && fStepMain <= 0.0) + { + pControl = m_xFmtFldStepMain.get(); + pErrStrId = STR_STEP_GT_ZERO; + } + else if (!m_xCbxAutoMax->get_active() && !m_xCbxAutoMin->get_active() && + fMin >= fMax) + { + pControl = m_xFmtFldMin.get(); + pErrStrId = STR_MIN_GREATER_MAX; + } + else if( bDateAxis ) + { + if( !m_xCbxAutoStepMain->get_active() && !m_xCbxAutoStepHelp->get_active() ) + { + if( m_nHelpTimeUnit > m_nMainTimeUnit ) + { + pControl = m_xLB_MainTimeUnit.get(); + pErrStrId = STR_INVALID_INTERVALS; + } + else if( m_nHelpTimeUnit == m_nMainTimeUnit && nStepHelp > fStepMain ) + { + pControl = m_xLB_MainTimeUnit.get(); + pErrStrId = STR_INVALID_INTERVALS; + } + } + if( !pErrStrId && !m_xCbx_AutoTimeResolution->get_active() ) + { + if( (!m_xCbxAutoStepMain->get_active() && m_nTimeResolution > m_nMainTimeUnit ) + || + (!m_xCbxAutoStepHelp->get_active() && m_nTimeResolution > m_nHelpTimeUnit ) + ) + { + pControl = m_xLB_TimeResolution.get(); + pErrStrId = STR_INVALID_TIME_UNIT; + } + } + } + + if( ShowWarning( pErrStrId, pControl ) ) + return DeactivateRC::KeepPage; + + if( pItemSet ) + FillItemSet( pItemSet ); + + return DeactivateRC::LeavePage; +} + +void ScaleTabPage::SetNumFormatter( SvNumberFormatter* pFormatter ) +{ + pNumFormatter = pFormatter; + m_xFmtFldMax->set_formatter( pNumFormatter ); + m_xFmtFldMin->set_formatter( pNumFormatter ); + m_xFmtFldStepMain->set_formatter( pNumFormatter ); + m_xFmtFldOrigin->set_formatter( pNumFormatter ); + SetNumFormat(); +} + +void ScaleTabPage::SetNumFormat() +{ + const SfxPoolItem *pPoolItem = nullptr; + + if( GetItemSet().GetItemState( SID_ATTR_NUMBERFORMAT_VALUE, true, &pPoolItem ) != SfxItemState::SET ) + return; + + sal_uLong nFmt = static_cast<const SfxUInt32Item*>(pPoolItem)->GetValue(); + + m_xFmtFldMax->set_format_key(nFmt); + m_xFmtFldMin->set_format_key(nFmt); + m_xFmtFldOrigin->set_format_key(nFmt); + + if( pNumFormatter ) + { + SvNumFormatType eType = pNumFormatter->GetType( nFmt ); + if( eType == SvNumFormatType::DATE ) + { + // for intervals use standard format for dates (so you can enter a number of days) + const SvNumberformat* pFormat = pNumFormatter->GetEntry( nFmt ); + if( pFormat ) + nFmt = pNumFormatter->GetStandardIndex( pFormat->GetLanguage()); + else + nFmt = pNumFormatter->GetStandardIndex(); + } + else if( eType == SvNumFormatType::DATETIME ) + { + // for intervals use time format for date times + const SvNumberformat* pFormat = pNumFormatter->GetEntry( nFmt ); + if( pFormat ) + nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::TIME, pFormat->GetLanguage() ); + else + nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::TIME ); + } + + if( m_nAxisType == chart2::AxisType::DATE && ( eType != SvNumFormatType::DATE && eType != SvNumFormatType::DATETIME) ) + { + const SvNumberformat* pFormat = pNumFormatter->GetEntry( nFmt ); + if( pFormat ) + nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::DATE, pFormat->GetLanguage() ); + else + nFmt = pNumFormatter->GetStandardFormat( SvNumFormatType::DATE ); + + m_xFmtFldMax->set_format_key(nFmt); + m_xFmtFldMin->set_format_key(nFmt); + m_xFmtFldOrigin->set_format_key(nFmt); + } + } + + m_xFmtFldStepMain->set_format_key(nFmt); +} + +void ScaleTabPage::ShowAxisOrigin( bool bShowOrigin ) +{ + m_bShowAxisOrigin = bShowOrigin; + if( !AxisHelper::isAxisPositioningEnabled() ) + m_bShowAxisOrigin = true; +} + +bool ScaleTabPage::ShowWarning(const char* pResIdMessage, weld::Widget* pControl /* = nullptr */) +{ + if (pResIdMessage == nullptr) + return false; + + std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetFrameWeld(), + VclMessageType::Warning, VclButtonsType::Ok, + SchResId(pResIdMessage))); + xWarn->run(); + if (pControl) + { + pControl->grab_focus(); + weld::Entry* pEdit = dynamic_cast<weld::Entry*>(pControl); + if (pEdit) + pEdit->select_region(0, -1); + } + return true; +} + +void ScaleTabPage::HideAllControls() +{ + // We need to set these controls invisible when the class is instantiated + // since some code in EnableControls() depends on that logic. The real + // visibility of these controls depend on axis data type, and are + // set in EnableControls(). + + m_xBxType->hide(); + m_xCbxLogarithm->hide(); + m_xBxMinMax->hide(); + m_xTxtMain->hide(); + m_xFmtFldStepMain->hide(); + m_xMt_MainDateStep->hide(); + m_xLB_MainTimeUnit->hide(); + m_xCbxAutoStepMain->hide(); + m_xTxtHelpCount->hide(); + m_xTxtHelp->hide(); + m_xMtStepHelp->hide(); + m_xCbxAutoStepHelp->hide(); + m_xBxOrigin->hide(); + m_xBxResolution->hide(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_Scale.hxx b/chart2/source/controller/dialogs/tp_Scale.hxx new file mode 100644 index 000000000..b0e308845 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Scale.hxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SCALE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SCALE_HXX + +#include <sfx2/tabdlg.hxx> + +namespace chart +{ + +class ScaleTabPage : public SfxTabPage +{ +public: + ScaleTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~ScaleTabPage() override; + + static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs ); + virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override; + virtual void Reset( const SfxItemSet* rInAttrs ) override; + virtual DeactivateRC DeactivatePage( SfxItemSet* pItemSet ) override; + + void SetNumFormatter( SvNumberFormatter* pFormatter ); + void SetNumFormat(); + + void ShowAxisOrigin( bool bShowOrigin ); + +private: + double fMin; + double fMax; + double fStepMain; + sal_Int32 nStepHelp; + double fOrigin; + sal_Int32 m_nTimeResolution; + sal_Int32 m_nMainTimeUnit; + sal_Int32 m_nHelpTimeUnit; + int m_nAxisType; + bool m_bAllowDateAxis; + SvNumberFormatter* pNumFormatter; + + bool m_bShowAxisOrigin; + + std::unique_ptr<weld::CheckButton> m_xCbxReverse; + std::unique_ptr<weld::CheckButton> m_xCbxLogarithm; + std::unique_ptr<weld::Widget> m_xBxType; + std::unique_ptr<weld::ComboBox> m_xLB_AxisType; + std::unique_ptr<weld::Widget> m_xBxMinMax; + std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldMin; + std::unique_ptr<weld::CheckButton> m_xCbxAutoMin; + std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldMax; + std::unique_ptr<weld::CheckButton> m_xCbxAutoMax; + std::unique_ptr<weld::Widget> m_xBxResolution; + std::unique_ptr<weld::ComboBox> m_xLB_TimeResolution; + std::unique_ptr<weld::CheckButton> m_xCbx_AutoTimeResolution; + std::unique_ptr<weld::Label> m_xTxtMain; + std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldStepMain; + std::unique_ptr<weld::SpinButton> m_xMt_MainDateStep; + std::unique_ptr<weld::ComboBox> m_xLB_MainTimeUnit; + std::unique_ptr<weld::CheckButton> m_xCbxAutoStepMain; + std::unique_ptr<weld::Label> m_xTxtHelpCount; + std::unique_ptr<weld::Label> m_xTxtHelp; + std::unique_ptr<weld::SpinButton> m_xMtStepHelp; + std::unique_ptr<weld::ComboBox> m_xLB_HelpTimeUnit; + std::unique_ptr<weld::CheckButton> m_xCbxAutoStepHelp; + std::unique_ptr<weld::FormattedSpinButton> m_xFmtFldOrigin; + std::unique_ptr<weld::CheckButton> m_xCbxAutoOrigin; + std::unique_ptr<weld::Widget> m_xBxOrigin; + + void EnableControls(); + + DECL_LINK(SelectAxisTypeHdl, weld::ComboBox&, void); + DECL_LINK(EnableValueHdl, weld::ToggleButton&, void); + + /** shows a warning window due to an invalid input. + + @param pResIdMessage + The resource identifier that represents the localized warning text. + If this is nullptr, no warning is shown and false is returned. + + @param pControl + If non-NULL, contains a pointer to the control in which the + erroneous value was in. This method gives this control the focus + and selects its content. + + @return false, if nResIdMessage was 0, true otherwise + */ + bool ShowWarning(const char* pResIdMessage, weld::Widget* pControl); + + void HideAllControls(); +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx b/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx new file mode 100644 index 000000000..82bd80ab6 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_SeriesToAxis.cxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_SeriesToAxis.hxx" + +#include <chartview/ChartSfxItemIds.hxx> + +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/ilstitem.hxx> + +#include <com/sun/star/chart/MissingValueTreatment.hpp> + +namespace chart +{ + +SchOptionTabPage::SchOptionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_SeriesToAxis.ui", "TP_OPTIONS", &rInAttrs) + , m_nAllSeriesAxisIndex(0) + , m_bProvidesSecondaryYAxis(true) + , m_bProvidesOverlapAndGapWidth(false) + , m_bProvidesBarConnectors(false) + , m_xGrpAxis(m_xBuilder->weld_widget("frameGrpAxis")) + , m_xRbtAxis1(m_xBuilder->weld_radio_button("RBT_OPT_AXIS_1")) + , m_xRbtAxis2(m_xBuilder->weld_radio_button("RBT_OPT_AXIS_2")) + , m_xGrpBar(m_xBuilder->weld_widget("frameSettings")) + , m_xMTGap(m_xBuilder->weld_metric_spin_button("MT_GAP", FieldUnit::PERCENT)) + , m_xMTOverlap(m_xBuilder->weld_metric_spin_button("MT_OVERLAP", FieldUnit::PERCENT)) + , m_xCBConnect(m_xBuilder->weld_check_button("CB_CONNECTOR")) + , m_xCBAxisSideBySide(m_xBuilder->weld_check_button("CB_BARS_SIDE_BY_SIDE")) + , m_xGrpPlotOptions(m_xBuilder->weld_widget("frameFL_PLOT_OPTIONS")) + , m_xGridPlotOptions(m_xBuilder->weld_widget("gridPLOT_OPTIONS")) + , m_xRB_DontPaint(m_xBuilder->weld_radio_button("RB_DONT_PAINT")) + , m_xRB_AssumeZero(m_xBuilder->weld_radio_button("RB_ASSUME_ZERO")) + , m_xRB_ContinueLine(m_xBuilder->weld_radio_button("RB_CONTINUE_LINE")) + , m_xCBIncludeHiddenCells(m_xBuilder->weld_check_button("CB_INCLUDE_HIDDEN_CELLS")) + , m_xCBHideLegendEntry(m_xBuilder->weld_check_button("CB_LEGEND_ENTRY_HIDDEN")) +{ + m_xRbtAxis1->connect_toggled(LINK(this, SchOptionTabPage, EnableHdl)); + m_xRbtAxis2->connect_toggled(LINK(this, SchOptionTabPage, EnableHdl)); +} + +SchOptionTabPage::~SchOptionTabPage() +{ +} + +IMPL_LINK_NOARG(SchOptionTabPage, EnableHdl, weld::ToggleButton&, void) +{ + if( m_nAllSeriesAxisIndex == 0 ) + m_xCBAxisSideBySide->set_sensitive( m_xRbtAxis2->get_active()); + else if( m_nAllSeriesAxisIndex == 1 ) + m_xCBAxisSideBySide->set_sensitive( m_xRbtAxis1->get_active()); +} + +std::unique_ptr<SfxTabPage> SchOptionTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rOutAttrs) +{ + return std::make_unique<SchOptionTabPage>(pPage, pController, *rOutAttrs); +} + +bool SchOptionTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + if(m_xRbtAxis2->get_active()) + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS,CHART_AXIS_SECONDARY_Y)); + else + rOutAttrs->Put(SfxInt32Item(SCHATTR_AXIS,CHART_AXIS_PRIMARY_Y)); + + if(m_xMTGap->get_visible()) + rOutAttrs->Put(SfxInt32Item(SCHATTR_BAR_GAPWIDTH,static_cast< sal_Int32 >( m_xMTGap->get_value(FieldUnit::PERCENT)))); + + if(m_xMTOverlap->get_visible()) + rOutAttrs->Put(SfxInt32Item(SCHATTR_BAR_OVERLAP,static_cast< sal_Int32 >( m_xMTOverlap->get_value(FieldUnit::PERCENT)))); + + if(m_xCBConnect->get_visible()) + rOutAttrs->Put(SfxBoolItem(SCHATTR_BAR_CONNECT,m_xCBConnect->get_active())); + + // model property is "group bars per axis", UI feature is the other way + // round: "show bars side by side" + if(m_xCBAxisSideBySide->get_visible()) + rOutAttrs->Put(SfxBoolItem(SCHATTR_GROUP_BARS_PER_AXIS, ! m_xCBAxisSideBySide->get_active())); + + if(m_xRB_DontPaint->get_active()) + rOutAttrs->Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,css::chart::MissingValueTreatment::LEAVE_GAP)); + else if(m_xRB_AssumeZero->get_active()) + rOutAttrs->Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,css::chart::MissingValueTreatment::USE_ZERO)); + else if(m_xRB_ContinueLine->get_active()) + rOutAttrs->Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,css::chart::MissingValueTreatment::CONTINUE)); + + if (m_xCBIncludeHiddenCells->get_visible()) + rOutAttrs->Put(SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, m_xCBIncludeHiddenCells->get_active())); + + if(m_xCBHideLegendEntry->get_visible()) + rOutAttrs->Put(SfxBoolItem(SCHATTR_HIDE_LEGEND_ENTRY, m_xCBHideLegendEntry->get_active())); + + return true; +} + +void SchOptionTabPage::Reset(const SfxItemSet* rInAttrs) +{ + const SfxPoolItem *pPoolItem = nullptr; + + m_xRbtAxis1->set_active(true); + m_xRbtAxis2->set_active(false); + if (rInAttrs->GetItemState(SCHATTR_AXIS,true, &pPoolItem) == SfxItemState::SET) + { + long nVal=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + if(nVal==CHART_AXIS_SECONDARY_Y) + { + m_xRbtAxis2->set_active(true); + m_xRbtAxis1->set_active(false); + } + } + + long nTmp; + if (rInAttrs->GetItemState(SCHATTR_BAR_GAPWIDTH, true, &pPoolItem) == SfxItemState::SET) + { + nTmp = static_cast<long>(static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()); + m_xMTGap->set_value(nTmp, FieldUnit::PERCENT); + } + + if (rInAttrs->GetItemState(SCHATTR_BAR_OVERLAP, true, &pPoolItem) == SfxItemState::SET) + { + nTmp = static_cast<long>(static_cast<const SfxInt32Item*>(pPoolItem)->GetValue()); + m_xMTOverlap->set_value(nTmp, FieldUnit::PERCENT); + } + + if (rInAttrs->GetItemState(SCHATTR_BAR_CONNECT, true, &pPoolItem) == SfxItemState::SET) + { + bool bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCBConnect->set_active(bCheck); + } + + if (rInAttrs->GetItemState(SCHATTR_AXIS_FOR_ALL_SERIES, true, &pPoolItem) == SfxItemState::SET) + { + m_nAllSeriesAxisIndex = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue(); + m_xCBAxisSideBySide->set_sensitive(false); + } + if (rInAttrs->GetItemState(SCHATTR_GROUP_BARS_PER_AXIS, true, &pPoolItem) == SfxItemState::SET) + { + // model property is "group bars per axis", UI feature is the other way + // round: "show bars side by side" + bool bCheck = ! static_cast< const SfxBoolItem * >( pPoolItem )->GetValue(); + m_xCBAxisSideBySide->set_active( bCheck ); + } + else + { + m_xCBAxisSideBySide->hide(); + } + + //missing value treatment + { + std::vector< sal_Int32 > aMissingValueTreatments; + if( rInAttrs->GetItemState(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, true, &pPoolItem) == SfxItemState::SET ) + aMissingValueTreatments = static_cast<const SfxIntegerListItem*>(pPoolItem)->GetList(); + + if ( aMissingValueTreatments.size()>1 && rInAttrs->GetItemState(SCHATTR_MISSING_VALUE_TREATMENT,true, &pPoolItem) == SfxItemState::SET) + { + m_xRB_DontPaint->set_sensitive(false); + m_xRB_AssumeZero->set_sensitive(false); + m_xRB_ContinueLine->set_sensitive(false); + + for(int nVal : aMissingValueTreatments) + { + if(nVal==css::chart::MissingValueTreatment::LEAVE_GAP) + m_xRB_DontPaint->set_sensitive(true); + else if(nVal==css::chart::MissingValueTreatment::USE_ZERO) + m_xRB_AssumeZero->set_sensitive(true); + else if(nVal==css::chart::MissingValueTreatment::CONTINUE) + m_xRB_ContinueLine->set_sensitive(true); + } + + long nVal=static_cast<const SfxInt32Item*>(pPoolItem)->GetValue(); + if(nVal==css::chart::MissingValueTreatment::LEAVE_GAP) + m_xRB_DontPaint->set_active(true); + else if(nVal==css::chart::MissingValueTreatment::USE_ZERO) + m_xRB_AssumeZero->set_active(true); + else if(nVal==css::chart::MissingValueTreatment::CONTINUE) + m_xRB_ContinueLine->set_active(true); + } + else + { + m_xGridPlotOptions->hide(); + } + } + + // Include hidden cells + if (rInAttrs->GetItemState(SCHATTR_INCLUDE_HIDDEN_CELLS, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + m_xCBIncludeHiddenCells->set_active(bVal); + } + else + { + m_xCBIncludeHiddenCells->hide(); + // check if the radiobutton guys above + // are visible. If they aren't, we can + // as well hide the whole frame + if(!m_xGridPlotOptions->get_visible()) + m_xGrpPlotOptions->hide(); + } + + if (rInAttrs->GetItemState(SCHATTR_HIDE_LEGEND_ENTRY, true, &pPoolItem) == SfxItemState::SET) + { + bool bVal = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue(); + m_xCBHideLegendEntry->set_active(bVal); + } + + AdaptControlPositionsAndVisibility(); +} + +void SchOptionTabPage::Init( bool bProvidesSecondaryYAxis, bool bProvidesOverlapAndGapWidth, bool bProvidesBarConnectors ) +{ + m_bProvidesSecondaryYAxis = bProvidesSecondaryYAxis; + m_bProvidesOverlapAndGapWidth = bProvidesOverlapAndGapWidth; + m_bProvidesBarConnectors = bProvidesBarConnectors; + + AdaptControlPositionsAndVisibility(); +} + +void SchOptionTabPage::AdaptControlPositionsAndVisibility() +{ + m_xGrpAxis->set_visible(m_bProvidesSecondaryYAxis); + m_xGrpBar->set_visible(m_bProvidesOverlapAndGapWidth); + m_xCBConnect->set_visible(m_bProvidesBarConnectors); + + if (!m_xMTGap->get_visible() && !m_xMTOverlap->get_visible()) + m_xGrpBar->hide(); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx b/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx new file mode 100644 index 000000000..8580e5722 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_SeriesToAxis.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SERIESTOAXIS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_SERIESTOAXIS_HXX + +#include <sfx2/tabdlg.hxx> + +namespace weld { + class CheckButton; + class MetricSpinButton; + class RadioButton; + class ToggleButton; + class Widget; +} + +namespace chart +{ + +class SchOptionTabPage : public SfxTabPage +{ +public: + SchOptionTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + virtual ~SchOptionTabPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + virtual bool FillItemSet(SfxItemSet* rOutAttrs) override; + virtual void Reset(const SfxItemSet* rInAttrs) override; + + void Init( bool bProvidesSecondaryYAxis, bool bProvidesOverlapAndGapWidth, bool bProvidesBarConnectors ); + +private: //methods + void AdaptControlPositionsAndVisibility(); + +private: //member + DECL_LINK(EnableHdl, weld::ToggleButton&, void ); + + sal_Int32 m_nAllSeriesAxisIndex; + + bool m_bProvidesSecondaryYAxis; + bool m_bProvidesOverlapAndGapWidth; + bool m_bProvidesBarConnectors; + + std::unique_ptr<weld::Widget> m_xGrpAxis; + std::unique_ptr<weld::RadioButton> m_xRbtAxis1; + std::unique_ptr<weld::RadioButton> m_xRbtAxis2; + std::unique_ptr<weld::Widget> m_xGrpBar; + std::unique_ptr<weld::MetricSpinButton> m_xMTGap; + std::unique_ptr<weld::MetricSpinButton> m_xMTOverlap; + std::unique_ptr<weld::CheckButton> m_xCBConnect; + std::unique_ptr<weld::CheckButton> m_xCBAxisSideBySide; + std::unique_ptr<weld::Widget> m_xGrpPlotOptions; + std::unique_ptr<weld::Widget> m_xGridPlotOptions; + std::unique_ptr<weld::RadioButton> m_xRB_DontPaint; + std::unique_ptr<weld::RadioButton> m_xRB_AssumeZero; + std::unique_ptr<weld::RadioButton> m_xRB_ContinueLine; + std::unique_ptr<weld::CheckButton> m_xCBIncludeHiddenCells; + std::unique_ptr<weld::CheckButton> m_xCBHideLegendEntry; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_TitleRotation.cxx b/chart2/source/controller/dialogs/tp_TitleRotation.cxx new file mode 100644 index 000000000..d23e393d5 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_TitleRotation.cxx @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_TitleRotation.hxx" + +#include <chartview/ChartSfxItemIds.hxx> +#include <TextDirectionListBox.hxx> + +#include <editeng/eeitem.hxx> +#include <editeng/frmdiritem.hxx> +#include <svl/intitem.hxx> + +namespace chart +{ + +SchAlignmentTabPage::SchAlignmentTabPage(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet& rInAttrs, bool bWithRotation) + : SfxTabPage(pPage, pController, "modules/schart/ui/titlerotationtabpage.ui", "TitleRotationTabPage", &rInAttrs) + , m_xFtRotate(m_xBuilder->weld_label("degreeL")) + , m_xNfRotate(m_xBuilder->weld_metric_spin_button("OrientDegree", FieldUnit::DEGREE)) + , m_xCbStacked(m_xBuilder->weld_check_button("stackedCB")) + , m_xFtTextDirection(m_xBuilder->weld_label("textdirL")) + , m_xFtABCD(m_xBuilder->weld_label("labelABCD")) + , m_xLbTextDirection(new TextDirectionListBox(m_xBuilder->weld_combo_box("textdirLB"))) + , m_xCtrlDial(new svx::DialControl) + , m_xCtrlDialWin(new weld::CustomWeld(*m_xBuilder, "dialCtrl", *m_xCtrlDial)) +{ + m_xCtrlDial->SetLinkedField(m_xNfRotate.get()); + m_xCtrlDial->SetText(m_xFtABCD->get_label()); + m_xCbStacked->connect_toggled(LINK(this, SchAlignmentTabPage, StackedToggleHdl)); + + m_xCtrlDialWin->set_sensitive(true); + m_xNfRotate->set_sensitive(true); + m_xCbStacked->set_sensitive(true); + m_xFtRotate->set_sensitive(true); + + if( !bWithRotation ) + { + m_xCtrlDialWin->hide(); + m_xNfRotate->hide(); + m_xCbStacked->hide(); + m_xFtRotate->hide(); + } +} + +IMPL_LINK_NOARG(SchAlignmentTabPage, StackedToggleHdl, weld::ToggleButton&, void) +{ + bool bActive = m_xCbStacked->get_active(); + m_xNfRotate->set_sensitive(!bActive); + m_xCtrlDialWin->set_sensitive(!bActive); + m_xCtrlDial->StyleUpdated(); + m_xFtRotate->set_sensitive(!bActive); +} + +SchAlignmentTabPage::~SchAlignmentTabPage() +{ + m_xCtrlDialWin.reset(); + m_xCtrlDial.reset(); + m_xLbTextDirection.reset(); +} + +std::unique_ptr<SfxTabPage> SchAlignmentTabPage::Create(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rInAttrs) +{ + return std::make_unique<SchAlignmentTabPage>(pPage, pController, *rInAttrs); +} + +std::unique_ptr<SfxTabPage> SchAlignmentTabPage::CreateWithoutRotation(weld::Container* pPage, weld::DialogController* pController, + const SfxItemSet* rInAttrs) +{ + return std::make_unique<SchAlignmentTabPage>(pPage, pController, *rInAttrs, false); +} + +bool SchAlignmentTabPage::FillItemSet(SfxItemSet* rOutAttrs) +{ + //Since 04/1998 text can be rotated by an arbitrary angle: SCHATTR_TEXT_DEGREES + bool bStacked = m_xCbStacked->get_active(); + rOutAttrs->Put( SfxBoolItem( SCHATTR_TEXT_STACKED, bStacked ) ); + + sal_Int32 nDegrees = bStacked ? 0 : m_xCtrlDial->GetRotation(); + rOutAttrs->Put( SfxInt32Item( SCHATTR_TEXT_DEGREES, nDegrees ) ); + + SvxFrameDirection aDirection( m_xLbTextDirection->get_active_id() ); + rOutAttrs->Put( SvxFrameDirectionItem( aDirection, EE_PARA_WRITINGDIR ) ); + + return true; +} + +void SchAlignmentTabPage::Reset(const SfxItemSet* rInAttrs) +{ + const SfxPoolItem* pItem = GetItem( *rInAttrs, SCHATTR_TEXT_DEGREES ); + + sal_Int32 nDegrees = pItem ? static_cast<const SfxInt32Item*>(pItem)->GetValue() : 0; + m_xCtrlDial->SetRotation( nDegrees ); + + pItem = GetItem( *rInAttrs, SCHATTR_TEXT_STACKED ); + bool bStacked = pItem && static_cast<const SfxBoolItem*>(pItem)->GetValue(); + m_xCbStacked->set_active(bStacked); + StackedToggleHdl(*m_xCbStacked); + + if( rInAttrs->GetItemState(EE_PARA_WRITINGDIR, true, &pItem) == SfxItemState::SET) + m_xLbTextDirection->set_active_id(static_cast<const SvxFrameDirectionItem*>(pItem)->GetValue()); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_TitleRotation.hxx b/chart2/source/controller/dialogs/tp_TitleRotation.hxx new file mode 100644 index 000000000..b6b184eea --- /dev/null +++ b/chart2/source/controller/dialogs/tp_TitleRotation.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TITLEROTATION_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TITLEROTATION_HXX + +#include <sfx2/tabdlg.hxx> +#include <svx/dialcontrol.hxx> + +namespace chart { class TextDirectionListBox; } +namespace weld { + class CheckButton; + class CustomWeld; + class Label; + class SpinButton; + class ToggleButton; +} + +namespace chart +{ + +class SchAlignmentTabPage : public SfxTabPage +{ +private: + std::unique_ptr<weld::Label> m_xFtRotate; + std::unique_ptr<weld::MetricSpinButton> m_xNfRotate; + std::unique_ptr<weld::CheckButton> m_xCbStacked; + std::unique_ptr<weld::Label> m_xFtTextDirection; + std::unique_ptr<weld::Label> m_xFtABCD; + std::unique_ptr<TextDirectionListBox> m_xLbTextDirection; + std::unique_ptr<svx::DialControl> m_xCtrlDial; + std::unique_ptr<weld::CustomWeld> m_xCtrlDialWin; + + DECL_LINK(StackedToggleHdl, weld::ToggleButton&, void); + +public: + SchAlignmentTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs, bool bWithRotation = true); + virtual ~SchAlignmentTabPage() override; + + static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + static std::unique_ptr<SfxTabPage> CreateWithoutRotation(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs); + virtual bool FillItemSet(SfxItemSet* rOutAttrs) override; + virtual void Reset(const SfxItemSet* rInAttrs) override; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_Trendline.cxx b/chart2/source/controller/dialogs/tp_Trendline.cxx new file mode 100644 index 000000000..fe25959bd --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Trendline.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_Trendline.hxx" + +namespace chart +{ + +TrendlineTabPage::TrendlineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs) + : SfxTabPage(pPage, pController, "modules/schart/ui/tp_Trendline.ui", "TP_TRENDLINE", &rInAttrs) + , m_aTrendlineResources(*m_xBuilder, rInAttrs) +{ +} + +std::unique_ptr<SfxTabPage> TrendlineTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rOutAttrs) +{ + return std::make_unique<TrendlineTabPage>(pPage, pController, *rOutAttrs); +} + +bool TrendlineTabPage::FillItemSet( SfxItemSet* rOutAttrs ) +{ + m_aTrendlineResources.FillItemSet( rOutAttrs ); + return true; +} + +void TrendlineTabPage::Reset( const SfxItemSet* rInAttrs ) +{ + m_aTrendlineResources.Reset( *rInAttrs ); +} + +void TrendlineTabPage::SetNumFormatter( SvNumberFormatter* pNumFormatter ) +{ + m_aTrendlineResources.SetNumFormatter( pNumFormatter ); +} + +void TrendlineTabPage::SetNbPoints( sal_Int32 nNbPoints ) +{ + m_aTrendlineResources.SetNbPoints( nNbPoints ); +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_Trendline.hxx b/chart2/source/controller/dialogs/tp_Trendline.hxx new file mode 100644 index 000000000..596ff339b --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Trendline.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TRENDLINE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_TRENDLINE_HXX + +#include "res_Trendline.hxx" + +#include <sfx2/tabdlg.hxx> + +namespace chart +{ + +class TrendlineTabPage : public SfxTabPage +{ +public: + TrendlineTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rInAttrs); + + static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rInAttrs ); + virtual bool FillItemSet( SfxItemSet* rOutAttrs ) override; + virtual void Reset( const SfxItemSet* rInAttrs ) override; + + void SetNumFormatter( SvNumberFormatter* pFormatter ); + void SetNbPoints( sal_Int32 nNbPoints ); + +private: + TrendlineResources m_aTrendlineResources; +}; + +} //namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx new file mode 100644 index 000000000..b191f2a42 --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.cxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "tp_Wizard_TitlesAndObjects.hxx" +#include <res_Titles.hxx> +#include <res_LegendPosition.hxx> +#include <ChartModelHelper.hxx> +#include <AxisHelper.hxx> +#include <ControllerLockGuard.hxx> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> + +namespace chart +{ +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +TitlesAndObjectsTabPage::TitlesAndObjectsTabPage(weld::Container* pPage, weld::DialogController* pController, + const uno::Reference< XChartDocument >& xChartModel, + const uno::Reference< uno::XComponentContext >& xContext ) + : OWizardPage(pPage, pController, "modules/schart/ui/wizelementspage.ui", "WizElementsPage") + , m_xTitleResources(new TitleResources(*m_xBuilder, false)) + , m_xLegendPositionResources(new LegendPositionResources(*m_xBuilder, xContext)) + , m_xChartModel(xChartModel) + , m_xCC(xContext) + , m_bCommitToModel(true) + , m_aTimerTriggeredControllerLock( m_xChartModel ) + , m_xCB_Grid_X(m_xBuilder->weld_check_button("x")) + , m_xCB_Grid_Y(m_xBuilder->weld_check_button("y")) + , m_xCB_Grid_Z(m_xBuilder->weld_check_button("z")) +{ + m_xTitleResources->connect_changed( LINK( this, TitlesAndObjectsTabPage, ChangeEditHdl )); + m_xLegendPositionResources->SetChangeHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl )); + + m_xCB_Grid_X->connect_toggled( LINK( this, TitlesAndObjectsTabPage, ChangeCheckBoxHdl )); + m_xCB_Grid_Y->connect_toggled( LINK( this, TitlesAndObjectsTabPage, ChangeCheckBoxHdl )); + m_xCB_Grid_Z->connect_toggled( LINK( this, TitlesAndObjectsTabPage, ChangeCheckBoxHdl )); +} + +TitlesAndObjectsTabPage::~TitlesAndObjectsTabPage() +{ +} + +void TitlesAndObjectsTabPage::initializePage() +{ + m_bCommitToModel = false; + + //init titles + { + TitleDialogData aTitleInput; + aTitleInput.readFromModel( m_xChartModel ); + m_xTitleResources->writeToResources( aTitleInput ); + } + + //init legend + { + m_xLegendPositionResources->writeToResources( m_xChartModel ); + } + + //init grid checkboxes + { + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( m_xChartModel ); + uno::Sequence< sal_Bool > aPossibilityList; + uno::Sequence< sal_Bool > aExistenceList; + AxisHelper::getAxisOrGridPossibilities( aPossibilityList, xDiagram, false ); + AxisHelper::getAxisOrGridExcistence( aExistenceList, xDiagram, false ); + m_xCB_Grid_X->set_sensitive( aPossibilityList[0] ); + m_xCB_Grid_Y->set_sensitive( aPossibilityList[1] ); + m_xCB_Grid_Z->set_sensitive( aPossibilityList[2] ); + m_xCB_Grid_X->set_active( aExistenceList[0] ); + m_xCB_Grid_Y->set_active( aExistenceList[1] ); + m_xCB_Grid_Z->set_active( aExistenceList[2] ); + } + + m_bCommitToModel = true; +} + +bool TitlesAndObjectsTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ ) +{ + if( m_xTitleResources->get_value_changed_from_saved() ) //titles may have changed in the meanwhile + commitToModel(); + return true;//return false if this page should not be left +} + +void TitlesAndObjectsTabPage::commitToModel() +{ + m_aTimerTriggeredControllerLock.startTimer(); + uno::Reference< frame::XModel > xModel = m_xChartModel; + + ControllerLockGuardUNO aLockedControllers( xModel ); + + //commit title changes to model + { + TitleDialogData aTitleOutput; + m_xTitleResources->readFromResources( aTitleOutput ); + aTitleOutput.writeDifferenceToModel( xModel, m_xCC ); + m_xTitleResources->save_value(); + } + + //commit legend changes to model + { + m_xLegendPositionResources->writeToModel( xModel ); + } + + //commit grid changes to model + { + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xModel ); + uno::Sequence< sal_Bool > aOldExistenceList; + AxisHelper::getAxisOrGridExcistence( aOldExistenceList, xDiagram, false ); + uno::Sequence< sal_Bool > aNewExistenceList(aOldExistenceList); + aNewExistenceList[0] = m_xCB_Grid_X->get_active(); + aNewExistenceList[1] = m_xCB_Grid_Y->get_active(); + aNewExistenceList[2] = m_xCB_Grid_Z->get_active(); + AxisHelper::changeVisibilityOfGrids( xDiagram + , aOldExistenceList, aNewExistenceList ); + } +} + +IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeCheckBoxHdl, weld::ToggleButton&, void) +{ + ChangeHdl(nullptr); +} + +IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeEditHdl, weld::Entry&, void) +{ + ChangeHdl(nullptr); +} + +IMPL_LINK_NOARG(TitlesAndObjectsTabPage, ChangeHdl, LinkParamNone*, void) +{ + if( m_bCommitToModel ) + commitToModel(); +} + +bool TitlesAndObjectsTabPage::canAdvance() const +{ + return false; +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx new file mode 100644 index 000000000..f6c5bbc4b --- /dev/null +++ b/chart2/source/controller/dialogs/tp_Wizard_TitlesAndObjects.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_WIZARD_TITLESANDOBJECTS_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_DIALOGS_TP_WIZARD_TITLESANDOBJECTS_HXX + +#include <TimerTriggeredControllerLock.hxx> + +#include <vcl/wizardmachine.hxx> + +#include <memory> + +namespace chart { class LegendPositionResources; } +namespace chart { class TitleResources; } +namespace com::sun::star::chart2 { class XChartDocument; } +namespace com::sun::star::uno { class XComponentContext; } + +namespace chart +{ + +class TitlesAndObjectsTabPage final : public vcl::OWizardPage +{ +public: + TitlesAndObjectsTabPage(weld::Container* pPage, weld::DialogController* pController, + const css::uno::Reference< css::chart2::XChartDocument >& xChartModel, + const css::uno::Reference< css::uno::XComponentContext >& xContext); + virtual ~TitlesAndObjectsTabPage() override; + + virtual void initializePage() override; + virtual bool commitPage( ::vcl::WizardTypes::CommitPageReason eReason ) override; + virtual bool canAdvance() const override; + +private: + void commitToModel(); + DECL_LINK( ChangeHdl, LinkParamNone*, void ); + DECL_LINK( ChangeEditHdl, weld::Entry&, void ); + DECL_LINK( ChangeCheckBoxHdl, weld::ToggleButton&, void ); + + std::unique_ptr< TitleResources > m_xTitleResources; + std::unique_ptr< LegendPositionResources > m_xLegendPositionResources; + + css::uno::Reference< css::chart2::XChartDocument > m_xChartModel; + css::uno::Reference< css::uno::XComponentContext> m_xCC; + + bool m_bCommitToModel; + TimerTriggeredControllerLock m_aTimerTriggeredControllerLock; + + std::unique_ptr<weld::CheckButton> m_xCB_Grid_X; + std::unique_ptr<weld::CheckButton> m_xCB_Grid_Y; + std::unique_ptr<weld::CheckButton> m_xCB_Grid_Z; +}; + +} //namespace chart +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |