summaryrefslogtreecommitdiffstats
path: root/chart2/source/controller/dialogs/tp_DataSource.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'chart2/source/controller/dialogs/tp_DataSource.cxx')
-rw-r--r--chart2/source/controller/dialogs/tp_DataSource.cxx926
1 files changed, 926 insertions, 0 deletions
diff --git a/chart2/source/controller/dialogs/tp_DataSource.cxx b/chart2/source/controller/dialogs/tp_DataSource.cxx
new file mode 100644
index 000000000..b142825b3
--- /dev/null
+++ b/chart2/source/controller/dialogs/tp_DataSource.cxx
@@ -0,0 +1,926 @@
+/* -*- 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 <ChartType.hxx>
+#include <ChartTypeTemplateProvider.hxx>
+#include <ChartTypeTemplate.hxx>
+#include <ChartModel.hxx>
+#include <RangeSelectionHelper.hxx>
+#include <DataSeries.hxx>
+#include <DataSeriesHelper.hxx>
+#include <ControllerLockGuard.hxx>
+#include <DataSourceHelper.hxx>
+#include <LabeledDataSequence.hxx>
+#include "DialogModel.hxx"
+#include <o3tl/safeint.hxx>
+#include <TabPageNotifiable.hxx>
+#include <com/sun/star/chart2/XDataSeries.hpp>
+#include <com/sun/star/chart2/data/XDataProvider.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
+{
+
+constexpr OUStringLiteral lcl_aLabelRole( u"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 = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
+ 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 = weld::fromId<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry));
+ 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 = weld::fromId<::chart::SeriesEntry*>(rRoleListBox.get_id(nEntry));
+ 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 uno::Reference< chart2::data::XLabeledDataSequence > & xLSequence,
+ const Reference< ::chart::DataSeries > & xSource )
+{
+ if( xSource.is())
+ {
+ std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > aData = xSource->getDataSequences2();
+ aData.push_back( xLSequence );
+ xSource->setData( aData );
+ }
+}
+
+uno::Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
+ const rtl::Reference< ::chart::DataSeries > & xDataSource )
+{
+ uno::Reference< chart2::data::XLabeledDataSequence > xResult;
+
+ for( uno::Reference< chart2::data::XLabeledDataSequence > const & labeledDataSeq : xDataSource->getDataSequences2() )
+ {
+ // no values are set but a label exists
+ if( ! labeledDataSeq->getValues().is() &&
+ labeledDataSeq->getLabel().is())
+ {
+ xResult = 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 { o3tl::narrowing<int>(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(weld::toId(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()
+{
+ rtl::Reference< DataSeries > xSelected;
+ SeriesEntry* pEntry = nullptr;
+ int nEntry = m_xLB_SERIES->get_selected_index();
+ if (nEntry != -1)
+ {
+ pEntry = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+ xSelected = 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
+ static const OUStringLiteral aReplacementStr( u"%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 = series.second.first;
+ pEntry->m_xChartType = series.second.second;
+ m_xLB_SERIES->append(weld::toId(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 = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
+ 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
+ static const OUStringLiteral aReplacementStr( u"%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();
+ rtl::Reference< DataSeries > xSeriesToInsertAfter;
+ rtl::Reference< ChartType > xChartTypeForNewSeries;
+ if( m_pTemplateProvider )
+ m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
+
+ if (nEntry != -1)
+ {
+ ::chart::SeriesEntry* pEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+ xSeriesToInsertAfter = pEntry->m_xDataSeries;
+ xChartTypeForNewSeries = pEntry->m_xChartType;
+ }
+ else
+ {
+ std::vector< rtl::Reference< ChartType > > aCntVec(
+ m_rDialogModel.getAllDataSeriesContainers());
+ if( ! aCntVec.empty())
+ xChartTypeForNewSeries = aCntVec.front();
+ }
+ 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 = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+ rtl::Reference< DataSeries > xNewSelSeries;
+ SeriesEntry * pNewSelEntry = nullptr;
+ if (nEntry + 1 < m_xLB_SERIES->n_children())
+ pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry + 1));
+ else if (nEntry > 0)
+ pNewSelEntry = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry - 1));
+ if (pNewSelEntry)
+ xNewSelSeries = 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 = weld::fromId<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(i));
+ 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 = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+
+ 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 = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry));
+
+ 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()))
+ {
+ uno::Reference< chart2::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 = 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 = weld::fromId<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry));
+ 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;
+
+ uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq =
+ DataSeriesHelper::getDataSequenceByRole( pSeriesEntry->m_xDataSeries, aSequenceRole );
+
+ if( xDataProvider.is())
+ {
+ if( bIsLabel )
+ {
+ if( ! xLabeledSeq.is())
+ {
+ // check if there is already an "orphan" label sequence
+ xLabeledSeq = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
+ if( ! xLabeledSeq.is())
+ {
+ // no corresponding labeled data sequence for label found
+ xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
+ lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
+ }
+ }
+ 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( OUString(lcl_aLabelRole) ));
+
+ //Labels should always include hidden cells, regardless of the setting chosen
+ xProp->setPropertyValue( "IncludeHiddenCells", uno::Any(true));
+ 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 = lcl_findLSequenceWithOnlyLabel( pSeriesEntry->m_xDataSeries );
+ if( ! xLabeledSeq.is())
+ {
+ xLabeledSeq = DataSourceHelper::createLabeledDataSequence();
+ lcl_addLSequenceToDataSource( xLabeledSeq, pSeriesEntry->m_xDataSeries );
+ }
+ }
+ 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
+ {
+ if( m_rDialogModel.getChartModel() )
+ m_rDialogModel.getChartModel()->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: */