vcl: allow for overriding the default PDF rendering resolution
[LibreOffice.git] / chart2 / source / controller / dialogs / tp_DataSource.cxx
blobb4cad889bb7e596dc2b46053cf49fe5979073337
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "tp_DataSource.hxx"
21 #include <strings.hrc>
22 #include <ResId.hxx>
23 #include <ChartTypeTemplateProvider.hxx>
24 #include <RangeSelectionHelper.hxx>
25 #include <DataSeriesHelper.hxx>
26 #include <ControllerLockGuard.hxx>
27 #include <DataSourceHelper.hxx>
28 #include "DialogModel.hxx"
29 #include <TabPageNotifiable.hxx>
30 #include <com/sun/star/chart2/XChartType.hpp>
31 #include <com/sun/star/chart2/data/XDataProvider.hpp>
32 #include <com/sun/star/util/XModifiable.hpp>
33 #include <com/sun/star/chart2/data/XDataSink.hpp>
35 #include <tools/diagnose_ex.h>
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::chart2;
40 using ::com::sun::star::uno::Reference;
41 using ::com::sun::star::uno::Sequence;
43 namespace
46 const OUString lcl_aLabelRole( "label" );
48 void lcl_UpdateCurrentRange(weld::TreeView& rOutListBox, const OUString & rRole,
49 const OUString& rRange)
51 int nEntry = rOutListBox.get_selected_index();
52 if (nEntry != -1)
54 rOutListBox.set_text(nEntry, ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole), 0);
55 rOutListBox.set_text(nEntry, rRange, 1);
56 ::chart::SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry).toInt64());
57 pEntry->m_sRole = rRole;
61 bool lcl_UpdateCurrentSeriesName(weld::TreeView& rOutListBox)
63 int nEntry = rOutListBox.get_selected_index();
64 if (nEntry == -1)
65 return false;
67 bool bResult = false;
68 ::chart::SeriesEntry * pEntry = reinterpret_cast<::chart::SeriesEntry*>(rOutListBox.get_id(nEntry).toInt64());
69 if (pEntry->m_xDataSeries.is() && pEntry->m_xChartType.is())
71 OUString aLabel(::chart::DataSeriesHelper::getDataSeriesLabel(
72 pEntry->m_xDataSeries,
73 pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel()));
74 if (!aLabel.isEmpty())
76 rOutListBox.set_text(nEntry, aLabel);
77 bResult = true;
80 return bResult;
83 OUString lcl_GetSelectedRole(const weld::TreeView& rRoleListBox, bool bUITranslated = false)
85 int nEntry = rRoleListBox.get_selected_index();
86 if (nEntry != -1)
88 if (bUITranslated)
89 return rRoleListBox.get_text(nEntry);
90 ::chart::SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(rRoleListBox.get_id(nEntry).toInt64());
91 return pEntry->m_sRole;
93 return OUString();
96 OUString lcl_GetSelectedRolesRange( const weld::TreeView& rRoleListBox )
98 OUString aResult;
99 int nEntry = rRoleListBox.get_selected_index();
100 if (nEntry != -1)
101 aResult = rRoleListBox.get_text(nEntry, 1);
102 return aResult;
105 OUString lcl_GetSequenceNameForLabel(const ::chart::SeriesEntry* pEntry)
107 OUString aResult("values-y");
108 if (pEntry && pEntry->m_xChartType.is())
109 aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel();
110 return aResult;
113 void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pDialog)
115 if (!pDialog)
116 return;
117 weld::Dialog* pDlg = pDialog->getDialog();
118 pDlg->set_modal(!bEnable);
119 pDlg->set_visible(!bEnable);
122 void lcl_addLSequenceToDataSource(
123 const Reference< chart2::data::XLabeledDataSequence > & xLSequence,
124 const Reference< chart2::data::XDataSource > & xSource )
126 Reference< data::XDataSink > xSink( xSource, uno::UNO_QUERY );
127 if( xSink.is())
129 Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
130 aData.realloc( aData.getLength() + 1 );
131 aData[ aData.getLength() - 1 ] = xLSequence;
132 xSink->setData( aData );
136 Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
137 const Reference< chart2::data::XDataSource > & xDataSource )
139 Reference< chart2::data::XLabeledDataSequence > xResult;
140 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
142 for( sal_Int32 i=0; i<aSequences.getLength(); ++i )
144 // no values are set but a label exists
145 if( ! aSequences[i]->getValues().is() &&
146 aSequences[i]->getLabel().is())
148 xResult.set( aSequences[i] );
149 break;
153 return xResult;
156 } // anonymous namespace
158 namespace chart
161 DataSourceTabPage::DataSourceTabPage(weld::Container* pPage, weld::DialogController* pController,
162 DialogModel & rDialogModel,
163 ChartTypeTemplateProvider* pTemplateProvider,
164 bool bHideDescription /* = false */)
165 : ::vcl::OWizardPage(pPage, pController, "modules/schart/ui/tp_DataSource.ui", "tp_DataSource")
166 , m_pTemplateProvider(pTemplateProvider)
167 , m_rDialogModel(rDialogModel)
168 , m_pCurrentRangeChoosingField( nullptr )
169 , m_bIsDirty( false )
170 , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable*>(pController))
171 , m_xFT_CAPTION(m_xBuilder->weld_label("FT_CAPTION_FOR_WIZARD"))
172 , m_xFT_SERIES(m_xBuilder->weld_label("FT_SERIES"))
173 , m_xLB_SERIES(m_xBuilder->weld_tree_view("LB_SERIES"))
174 , m_xBTN_ADD(m_xBuilder->weld_button("BTN_ADD"))
175 , m_xBTN_REMOVE(m_xBuilder->weld_button("BTN_REMOVE"))
176 , m_xBTN_UP(m_xBuilder->weld_button("BTN_UP"))
177 , m_xBTN_DOWN(m_xBuilder->weld_button("BTN_DOWN"))
178 , m_xFT_ROLE(m_xBuilder->weld_label("FT_ROLE"))
179 , m_xLB_ROLE(m_xBuilder->weld_tree_view("LB_ROLE"))
180 , m_xFT_RANGE(m_xBuilder->weld_label("FT_RANGE"))
181 , m_xEDT_RANGE(m_xBuilder->weld_entry("EDT_RANGE"))
182 , m_xIMB_RANGE_MAIN(m_xBuilder->weld_button("IMB_RANGE_MAIN"))
183 , m_xFT_CATEGORIES(m_xBuilder->weld_label("FT_CATEGORIES"))
184 , m_xFT_DATALABELS(m_xBuilder->weld_label("FT_DATALABELS"))
185 , m_xEDT_CATEGORIES(m_xBuilder->weld_entry("EDT_CATEGORIES"))
186 , m_xIMB_RANGE_CAT(m_xBuilder->weld_button("IMB_RANGE_CAT"))
188 m_xLB_SERIES->set_size_request(m_xLB_SERIES->get_approximate_digit_width() * 25,
189 m_xLB_SERIES->get_height_rows(10));
190 m_xLB_ROLE->set_size_request(m_xLB_ROLE->get_approximate_digit_width() * 60,
191 m_xLB_ROLE->get_height_rows(5));
192 m_xFT_CAPTION->set_visible(!bHideDescription);
194 m_aFixedTextRange = m_xFT_RANGE->get_label();
195 SetPageTitle(SchResId(STR_OBJECT_DATASERIES_PLURAL));
197 // set handlers
198 m_xLB_SERIES->connect_changed(LINK(this, DataSourceTabPage, SeriesSelectionChangedHdl));
199 m_xLB_ROLE->connect_changed(LINK(this, DataSourceTabPage, RoleSelectionChangedHdl));
201 m_xIMB_RANGE_MAIN->connect_clicked(LINK(this, DataSourceTabPage, MainRangeButtonClickedHdl));
202 m_xIMB_RANGE_CAT->connect_clicked(LINK(this, DataSourceTabPage, CategoriesRangeButtonClickedHdl));
204 m_xBTN_ADD->connect_clicked(LINK(this, DataSourceTabPage, AddButtonClickedHdl));
205 m_xBTN_REMOVE->connect_clicked(LINK(this, DataSourceTabPage, RemoveButtonClickedHdl));
207 m_xBTN_UP->connect_clicked(LINK(this, DataSourceTabPage, UpButtonClickedHdl));
208 m_xBTN_DOWN->connect_clicked(LINK(this, DataSourceTabPage, DownButtonClickedHdl));
210 m_xEDT_RANGE->connect_changed(LINK(this, DataSourceTabPage, RangeModifiedHdl));
211 m_xEDT_CATEGORIES->connect_changed(LINK( this, DataSourceTabPage, RangeModifiedHdl));
213 // init controls
214 std::vector<int> aWidths;
215 aWidths.push_back(m_xLB_ROLE->get_approximate_digit_width() * 20);
216 m_xLB_ROLE->set_column_fixed_widths(aWidths);
217 m_xLB_ROLE->show();
219 updateControlsFromDialogModel();
221 // select first series
222 if (m_xLB_SERIES->n_children())
223 m_xLB_SERIES->select(0);
226 void DataSourceTabPage::InsertRoleLBEntry(const OUString& rRole, const OUString& rRange)
228 m_aEntries.emplace_back(new SeriesEntry);
229 SeriesEntry* pEntry = m_aEntries.back().get();
230 pEntry->m_sRole = rRole;
231 m_xLB_ROLE->append(OUString::number(reinterpret_cast<sal_Int64>(pEntry)),
232 ::chart::DialogModel::ConvertRoleFromInternalToUI(rRole));
233 m_xLB_ROLE->set_text(m_xLB_ROLE->n_children() - 1, rRange, 1);
236 DataSourceTabPage::~DataSourceTabPage()
240 void DataSourceTabPage::Activate()
242 OWizardPage::Activate();
243 updateControlsFromDialogModel();
244 m_xLB_SERIES->grab_focus();
247 void DataSourceTabPage::initializePage()
251 void DataSourceTabPage::Deactivate()
253 commitPage();
254 vcl::OWizardPage::Deactivate();
257 void DataSourceTabPage::commitPage()
259 commitPage(::vcl::WizardTypes::eFinish);
262 bool DataSourceTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason /*eReason*/ )
264 //ranges may have been edited in the meanwhile (dirty is true in that case here)
265 if( isValid() )
267 updateModelFromControl();
268 return true; //return false if this page should not be left
270 else
271 return false;
274 bool DataSourceTabPage::isRangeFieldContentValid(weld::Entry& rEdit )
276 OUString aRange(rEdit.get_text());
277 bool bIsValid = aRange.isEmpty() ||
278 m_rDialogModel.getRangeSelectionHelper()->verifyCellRange(aRange);
279 rEdit.set_message_type(bIsValid ? weld::EntryMessageType::Normal : weld::EntryMessageType::Error);
280 return bIsValid;
283 bool DataSourceTabPage::isValid()
285 bool bRoleRangeValid = true;
286 bool bCategoriesRangeValid = true;
287 bool bHasSelectedEntry = (m_xLB_SERIES->get_selected_index() != -1);
289 if (bHasSelectedEntry)
290 bRoleRangeValid = isRangeFieldContentValid(*m_xEDT_RANGE);
291 if (m_xEDT_CATEGORIES->get_sensitive())
292 bCategoriesRangeValid = isRangeFieldContentValid( *m_xEDT_CATEGORIES );
293 bool bValid = ( bRoleRangeValid && bCategoriesRangeValid );
295 if( m_pTabPageNotifiable )
297 if( bValid )
298 m_pTabPageNotifiable->setValidPage( this );
299 else
300 m_pTabPageNotifiable->setInvalidPage( this );
303 return bValid;
306 void DataSourceTabPage::setDirty()
308 m_bIsDirty = true;
311 void DataSourceTabPage::updateControlsFromDialogModel()
313 // series
314 fillSeriesListBox();
315 SeriesSelectionChangedHdl(*m_xLB_SERIES);
317 // categories
318 m_xEDT_CATEGORIES->set_text(m_rDialogModel.getCategoriesRange());
320 updateControlState();
323 void DataSourceTabPage::fillSeriesListBox()
325 Reference< XDataSeries > xSelected;
326 SeriesEntry* pEntry = nullptr;
327 int nEntry = m_xLB_SERIES->get_selected_index();
328 if (nEntry != -1)
330 pEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64());
331 xSelected.set(pEntry->m_xDataSeries);
334 bool bHasSelectedEntry = (pEntry != nullptr);
335 int nSelectedEntry = -1;
337 m_xLB_SERIES->freeze();
338 m_xLB_SERIES->clear();
340 std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries(
341 m_rDialogModel.getAllDataSeriesWithLabel() );
343 sal_Int32 nUnnamedSeriesIndex = 1;
344 nEntry = 0;
345 for (auto const& series : aSeries)
347 OUString aLabel(series.first);
348 if (aLabel.isEmpty())
350 if( nUnnamedSeriesIndex > 1 )
352 OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ));
354 // replace index of unnamed series
355 const OUString aReplacementStr( "%NUMBER" );
356 sal_Int32 nIndex = aResString.indexOf( aReplacementStr );
357 if( nIndex != -1 )
358 aLabel = aResString.replaceAt(
359 nIndex, aReplacementStr.getLength(),
360 OUString::number(nUnnamedSeriesIndex));
362 if( aLabel.isEmpty() )
363 aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES );
365 ++nUnnamedSeriesIndex;
368 m_aEntries.emplace_back(new SeriesEntry);
369 pEntry = m_aEntries.back().get();
370 pEntry->m_xDataSeries.set(series.second.first);
371 pEntry->m_xChartType.set(series.second.second);
372 m_xLB_SERIES->append(OUString::number(reinterpret_cast<sal_Int64>(pEntry)), aLabel);
373 if (bHasSelectedEntry && series.second.first == xSelected)
374 nSelectedEntry = nEntry;
375 ++nEntry;
378 m_xLB_SERIES->thaw();
380 if (bHasSelectedEntry && nSelectedEntry != -1)
381 m_xLB_SERIES->select(nSelectedEntry);
384 void DataSourceTabPage::fillRoleListBox()
386 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
387 SeriesEntry* pSeriesEntry = nullptr;
388 if (nSeriesEntry != -1)
389 pSeriesEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry).toInt64());
390 bool bHasSelectedEntry = (pSeriesEntry != nullptr);
392 int nRoleIndex = m_xLB_ROLE->get_selected_index();
393 if (bHasSelectedEntry)
395 DialogModel::tRolesWithRanges aRoles(
396 DialogModel::getRolesWithRanges(
397 pSeriesEntry->m_xDataSeries,
398 lcl_GetSequenceNameForLabel( pSeriesEntry ),
399 pSeriesEntry->m_xChartType ));
401 // fill role list
402 m_xLB_ROLE->freeze();
403 m_xLB_ROLE->clear();
405 for (auto const& elemRole : aRoles)
407 InsertRoleLBEntry(elemRole.first, elemRole.second);
410 m_xLB_ROLE->thaw();
412 // series may contain no roles, check listbox size before selecting entries
413 if (m_xLB_ROLE->n_children() > 0)
415 if (nRoleIndex == -1 || nRoleIndex >= m_xLB_ROLE->n_children())
416 nRoleIndex = 0;
417 m_xLB_ROLE->select(nRoleIndex);
422 void DataSourceTabPage::updateControlState()
424 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
425 bool bHasSelectedSeries = nSeriesEntry != -1;
426 bool bHasValidRole = false;
427 bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
429 if( bHasSelectedSeries )
431 int nRoleEntry = m_xLB_ROLE->get_selected_index();
432 bHasValidRole = nRoleEntry != -1;
435 m_xBTN_ADD->set_sensitive(true);
436 m_xBTN_REMOVE->set_sensitive(bHasSelectedSeries);
438 m_xBTN_UP->set_sensitive(bHasSelectedSeries && (nSeriesEntry != 0));
439 m_xBTN_DOWN->set_sensitive(bHasSelectedSeries && (nSeriesEntry != m_xLB_SERIES->n_children() - 1));
441 bool bHasCategories = m_rDialogModel.isCategoryDiagram();
443 m_xFT_DATALABELS->set_visible(!bHasCategories);
444 m_xFT_CATEGORIES->set_visible( bHasCategories);
445 bool bShowIB = bHasRangeChooser;
447 m_xIMB_RANGE_CAT->set_visible(bShowIB);
449 m_xFT_ROLE->set_sensitive(bHasSelectedSeries);
450 m_xLB_ROLE->set_sensitive(bHasSelectedSeries);
452 m_xFT_RANGE->set_sensitive(bHasValidRole);
453 m_xEDT_RANGE->set_sensitive(bHasValidRole);
455 m_xFT_SERIES->set_sensitive(true);
456 m_xLB_SERIES->set_sensitive(true);
458 m_xIMB_RANGE_MAIN->set_visible(bShowIB);
460 isValid();
463 IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl, weld::TreeView&, void)
465 m_rDialogModel.startControllerLockTimer();
466 if (m_xLB_SERIES->get_selected_index() != -1)
468 fillRoleListBox();
469 RoleSelectionChangedHdl(*m_xLB_ROLE);
471 updateControlState();
474 IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl, weld::TreeView&, void)
476 m_rDialogModel.startControllerLockTimer();
477 int nEntry = m_xLB_ROLE->get_selected_index();
478 if (nEntry != -1)
480 OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_xLB_ROLE, true );
481 OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_xLB_ROLE );
483 // replace role in fixed text label
484 const OUString aReplacementStr( "%VALUETYPE" );
485 sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
486 if( nIndex != -1 )
488 m_xFT_RANGE->set_label(
489 m_aFixedTextRange.replaceAt(
490 nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
493 m_xEDT_RANGE->set_text(aSelectedRange);
494 isValid();
498 IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl, weld::Button&, void)
500 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
501 m_pCurrentRangeChoosingField = m_xEDT_RANGE.get();
502 if (!m_xEDT_RANGE->get_text().isEmpty() &&
503 !updateModelFromControl( m_pCurrentRangeChoosingField))
504 return;
506 int nEntry = m_xLB_SERIES->get_selected_index();
507 bool bHasSelectedEntry = (nEntry != -1);
509 OUString aSelectedRolesRange = lcl_GetSelectedRolesRange(*m_xLB_ROLE);
511 if (bHasSelectedEntry && (m_xLB_ROLE->get_selected_index() != -1))
513 OUString aUIStr(SchResId(STR_DATA_SELECT_RANGE_FOR_SERIES));
515 // replace role
516 OUString aReplacement( "%VALUETYPE" );
517 sal_Int32 nIndex = aUIStr.indexOf( aReplacement );
518 if( nIndex != -1 )
520 aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
521 lcl_GetSelectedRole( *m_xLB_ROLE, true ));
523 // replace series name
524 aReplacement = "%SERIESNAME";
525 nIndex = aUIStr.indexOf( aReplacement );
526 if( nIndex != -1 )
528 aUIStr = aUIStr.replaceAt(nIndex, aReplacement.getLength(),
529 m_xLB_SERIES->get_text(nEntry));
532 lcl_enableRangeChoosing(true, m_pDialogController);
533 m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this );
535 else
536 m_pCurrentRangeChoosingField = nullptr;
539 IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl, weld::Button&, void)
541 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
542 m_pCurrentRangeChoosingField = m_xEDT_CATEGORIES.get();
543 if( !m_xEDT_CATEGORIES->get_text().isEmpty() &&
544 ! updateModelFromControl( m_pCurrentRangeChoosingField ))
545 return;
547 OUString aStr(SchResId(m_xFT_CATEGORIES->get_visible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS));
548 lcl_enableRangeChoosing(true, m_pDialogController);
549 m_rDialogModel.getRangeSelectionHelper()->chooseRange(
550 m_rDialogModel.getCategoriesRange(), aStr, *this );
553 IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl, weld::Button&, void)
555 m_rDialogModel.startControllerLockTimer();
556 int nEntry = m_xLB_SERIES->get_selected_index();
557 Reference< XDataSeries > xSeriesToInsertAfter;
558 Reference< XChartType > xChartTypeForNewSeries;
559 if( m_pTemplateProvider )
560 m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
562 if (nEntry != -1)
564 ::chart::SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64());
565 xSeriesToInsertAfter.set(pEntry->m_xDataSeries);
566 xChartTypeForNewSeries.set(pEntry->m_xChartType);
568 else
570 std::vector< Reference< XDataSeriesContainer > > aCntVec(
571 m_rDialogModel.getAllDataSeriesContainers());
572 if( ! aCntVec.empty())
573 xChartTypeForNewSeries.set( aCntVec.front(), uno::UNO_QUERY );
575 OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" );
577 m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries );
578 setDirty();
580 fillSeriesListBox();
581 // note the box was cleared and refilled, so nEntry is invalid now
583 int nSelEntry = m_xLB_SERIES->get_selected_index();
584 if (nSelEntry != -1)
586 ++nSelEntry;
587 if (nSelEntry < m_xLB_SERIES->n_children())
588 m_xLB_SERIES->select(nSelEntry);
590 SeriesSelectionChangedHdl(*m_xLB_SERIES);
593 IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl, weld::Button&, void)
595 m_rDialogModel.startControllerLockTimer();
596 int nEntry = m_xLB_SERIES->get_selected_index();
597 if (nEntry != -1)
599 SeriesEntry* pEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64());
600 Reference< XDataSeries > xNewSelSeries;
601 SeriesEntry * pNewSelEntry = nullptr;
602 if (nEntry + 1 < m_xLB_SERIES->n_children())
603 pNewSelEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry + 1).toInt64());
604 else if (nEntry > 0)
605 pNewSelEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(nEntry - 1).toInt64());
606 if (pNewSelEntry)
607 xNewSelSeries.set(pNewSelEntry->m_xDataSeries);
609 m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType );
610 setDirty();
612 m_xLB_SERIES->remove(nEntry);
613 fillSeriesListBox();
615 // select previous or next series
616 if (xNewSelSeries.is())
618 for (int i = 0; i < m_xLB_SERIES->n_children(); ++i)
620 pEntry = reinterpret_cast<::chart::SeriesEntry*>(m_xLB_SERIES->get_id(i).toInt64());
621 if (pEntry->m_xDataSeries == xNewSelSeries)
623 m_xLB_SERIES->select(i);
624 break;
628 SeriesSelectionChangedHdl(*m_xLB_SERIES);
632 IMPL_LINK_NOARG(DataSourceTabPage, UpButtonClickedHdl, weld::Button&, void)
634 m_rDialogModel.startControllerLockTimer();
636 int nEntry = m_xLB_SERIES->get_selected_index();
637 SeriesEntry* pEntry = nullptr;
638 if (nEntry != -1)
639 pEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64());
641 bool bHasSelectedEntry = (pEntry != nullptr);
643 if (bHasSelectedEntry)
645 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Up );
646 setDirty();
647 fillSeriesListBox();
648 SeriesSelectionChangedHdl(*m_xLB_SERIES);
652 IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl, weld::Button&, void)
654 m_rDialogModel.startControllerLockTimer();
656 int nEntry = m_xLB_SERIES->get_selected_index();
657 SeriesEntry* pEntry = nullptr;
658 if (nEntry != -1)
659 pEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nEntry).toInt64());
661 bool bHasSelectedEntry = (pEntry != nullptr);
663 if (bHasSelectedEntry)
665 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MoveDirection::Down );
666 setDirty();
667 fillSeriesListBox();
668 SeriesSelectionChangedHdl(*m_xLB_SERIES);
672 IMPL_LINK(DataSourceTabPage, RangeModifiedHdl, weld::Entry&, rEdit, void)
674 // note: isValid sets the color of the edit field
675 if( isRangeFieldContentValid( rEdit ))
677 setDirty();
678 updateModelFromControl( &rEdit );
679 if (&rEdit == m_xEDT_RANGE.get())
681 if( ! lcl_UpdateCurrentSeriesName( *m_xLB_SERIES ))
682 fillSeriesListBox();
686 // enable/disable OK button
687 isValid();
690 void DataSourceTabPage::listeningFinished(
691 const OUString & rNewRange )
693 // rNewRange becomes invalid after removing the listener
694 OUString aRange( rNewRange );
696 m_rDialogModel.startControllerLockTimer();
698 // stop listening
699 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
701 // change edit field
702 if( m_pCurrentRangeChoosingField )
704 m_pCurrentRangeChoosingField->set_text(aRange);
705 m_pCurrentRangeChoosingField->grab_focus();
708 if (m_pCurrentRangeChoosingField == m_xEDT_RANGE.get())
710 m_xEDT_RANGE->set_text(aRange);
711 setDirty();
713 else if (m_pCurrentRangeChoosingField == m_xEDT_CATEGORIES.get())
715 m_xEDT_CATEGORIES->set_text(aRange);
716 setDirty();
719 updateModelFromControl(m_pCurrentRangeChoosingField);
720 if (!lcl_UpdateCurrentSeriesName(*m_xLB_SERIES))
721 fillSeriesListBox();
723 m_pCurrentRangeChoosingField = nullptr;
725 updateControlState();
726 lcl_enableRangeChoosing(false, m_pDialogController);
729 void DataSourceTabPage::disposingRangeSelection()
731 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
734 bool DataSourceTabPage::updateModelFromControl(const weld::Entry* pField)
736 if (!m_bIsDirty)
737 return true;
739 ControllerLockGuardUNO aLockedControllers( m_rDialogModel.getChartModel() );
741 // @todo: validity check of field content
742 bool bResult = true;
743 bool bAll = (pField == nullptr);
744 Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider());
746 if (bAll || (pField == m_xEDT_CATEGORIES.get()))
748 Reference< data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() );
749 if( xDataProvider.is())
751 OUString aRange(m_xEDT_CATEGORIES->get_text());
752 if (!aRange.isEmpty())
754 // create or change categories
755 if( !xLabeledSeq.is())
757 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() );
758 m_rDialogModel.setCategories( xLabeledSeq );
762 xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
764 catch( const uno::Exception & )
766 // should work as validation should have happened before
767 DBG_UNHANDLED_EXCEPTION("chart2");
770 else if( xLabeledSeq.is())
772 // clear existing categories
773 xLabeledSeq.set(nullptr);
774 m_rDialogModel.setCategories( xLabeledSeq );
779 int nSeriesEntry = m_xLB_SERIES->get_selected_index();
780 SeriesEntry* pSeriesEntry = nullptr;
781 if (nSeriesEntry != -1)
782 pSeriesEntry = reinterpret_cast<SeriesEntry*>(m_xLB_SERIES->get_id(nSeriesEntry).toInt64());
783 bool bHasSelectedEntry = (pSeriesEntry != nullptr);
785 if( bHasSelectedEntry )
787 if( bAll || (pField == m_xEDT_RANGE.get()) )
791 OUString aSelectedRole = lcl_GetSelectedRole( *m_xLB_ROLE );
792 OUString aRange(m_xEDT_RANGE->get_text());
793 OUString aSequenceRole( aSelectedRole );
794 bool bIsLabel = (aSequenceRole == lcl_aLabelRole );
795 OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry ));
797 if( bIsLabel )
798 aSequenceRole = aSequenceNameForLabel;
800 Reference< data::XDataSource > xSource( pSeriesEntry->m_xDataSeries, uno::UNO_QUERY_THROW );
801 Reference< data::XLabeledDataSequence > xLabeledSeq(
802 DataSeriesHelper::getDataSequenceByRole( xSource, aSequenceRole ));
804 if( xDataProvider.is())
806 if( bIsLabel )
808 if( ! xLabeledSeq.is())
810 // check if there is already an "orphan" label sequence
811 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
812 if( ! xLabeledSeq.is())
814 // no corresponding labeled data sequence for label found
815 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() );
816 lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
819 if( xLabeledSeq.is())
821 if( !aRange.isEmpty())
823 Reference< data::XDataSequence > xNewSeq;
826 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
828 catch( const uno::Exception & )
830 // should work as validation should have happened before
831 DBG_UNHANDLED_EXCEPTION("chart2");
833 if( xNewSeq.is())
835 // update range name by the full string provided
836 // by the data provider. E.g. "a1" might become
837 // "$Sheet1.$A$1"
838 aRange = xNewSeq->getSourceRangeRepresentation();
839 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
840 xProp->setPropertyValue( "Role" , uno::Any( lcl_aLabelRole ));
841 xLabeledSeq->setLabel( xNewSeq );
844 else
846 xLabeledSeq->setLabel( Reference< data::XDataSequence >());
850 else
852 if( !aRange.isEmpty())
854 Reference< data::XDataSequence > xNewSeq;
857 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
859 catch( const uno::Exception & )
861 // should work as validation should have happened before
862 DBG_UNHANDLED_EXCEPTION("chart2");
864 if( xNewSeq.is())
866 // update range name by the full string provided
867 // by the data provider. E.g. "a1:e1" might become
868 // "$Sheet1.$A$1:$E$1"
869 aRange = xNewSeq->getSourceRangeRepresentation();
871 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
872 xProp->setPropertyValue( "Role" , uno::Any( aSelectedRole ));
873 if( !xLabeledSeq.is())
875 if( aSelectedRole == aSequenceNameForLabel )
876 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
877 if( ! xLabeledSeq.is())
879 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence() );
880 lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
883 xLabeledSeq->setValues( xNewSeq );
889 lcl_UpdateCurrentRange( *m_xLB_ROLE, aSelectedRole, aRange );
891 catch( const uno::Exception & )
893 DBG_UNHANDLED_EXCEPTION("chart2");
894 bResult = false;
899 // update View
900 // @todo remove this when automatic view updates from calc, writer and own data sequences are available
901 if( bResult )
905 Reference< util::XModifiable > xModifiable( m_rDialogModel.getChartModel(), uno::UNO_QUERY );
906 if( xModifiable.is() )
907 xModifiable->setModified( true );
908 const DialogModelTimeBasedInfo& rInfo = m_rDialogModel.getTimeBasedInfo();
909 if(rInfo.bTimeBased)
911 m_rDialogModel.setTimeBasedRange(rInfo.bTimeBased, rInfo.nStart, rInfo.nEnd);
914 catch( const uno::Exception & )
916 DBG_UNHANDLED_EXCEPTION("chart2");
920 return bResult;
923 } // namespace chart
925 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */