fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / chart2 / source / controller / dialogs / tp_DataSource.cxx
blob66e8944d264b270522efcc0bf52818d6463061fb
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 "chartview/ChartSfxItemIds.hxx"
24 #include "macros.hxx"
25 #include "ChartTypeTemplateProvider.hxx"
26 #include "RangeSelectionHelper.hxx"
27 #include "DataSeriesHelper.hxx"
28 #include "tp_DataSourceControls.hxx"
29 #include "ControllerLockGuard.hxx"
30 #include "DataSourceHelper.hxx"
31 #include <com/sun/star/sheet/XRangeSelection.hpp>
32 #include <com/sun/star/table/XCellRange.hpp>
33 #include <com/sun/star/chart2/XChartType.hpp>
34 #include <com/sun/star/chart2/XChartTypeTemplate.hpp>
35 #include <com/sun/star/util/XModifiable.hpp>
36 #include <com/sun/star/chart2/data/XDataSink.hpp>
38 #include <vcl/msgbox.hxx>
39 #include <rtl/ustrbuf.hxx>
41 #include <functional>
42 #include <algorithm>
43 #include <map>
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::chart2;
48 using ::com::sun::star::uno::Reference;
49 using ::com::sun::star::uno::Sequence;
51 namespace
54 const OUString lcl_aLabelRole( "label" );
56 OUString lcl_GetRoleLBEntry(
57 const OUString & rRole, const OUString & rRange )
59 OUStringBuffer aEntry( rRole );
60 aEntry.append( "\t" );
61 aEntry.append( OUString(
62 ::chart::DialogModel::ConvertRoleFromInternalToUI( rRole )) );
63 aEntry.append( "\t" );
64 aEntry.append(OUString( rRange ));
66 OUString sFoo = aEntry.makeStringAndClear();
67 return sFoo;
70 void lcl_UpdateCurrentRange(
71 SvTabListBox & rOutListBox,
72 const OUString & rRole, const OUString & rRange )
74 SvTreeListEntry * pEntry = rOutListBox.FirstSelected();
75 if( pEntry )
76 rOutListBox.SetEntryText( lcl_GetRoleLBEntry( rRole, rRange ), pEntry );
79 bool lcl_UpdateCurrentSeriesName(
80 SvTreeListBox & rOutListBox )
82 bool bResult = false;
83 ::chart::SeriesEntry * pEntry = dynamic_cast< ::chart::SeriesEntry * >( rOutListBox.FirstSelected());
84 if( pEntry &&
85 pEntry->m_xDataSeries.is() &&
86 pEntry->m_xChartType.is())
88 OUString aLabel( ::chart::DataSeriesHelper::getDataSeriesLabel(
89 pEntry->m_xDataSeries,
90 pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel()));
91 if( !aLabel.isEmpty())
93 rOutListBox.SetEntryText( pEntry, aLabel );
94 bResult = true;
97 return bResult;
100 OUString lcl_GetSelectedRole( const SvTabListBox & rRoleListBox, bool bUITranslated = false )
102 OUString aResult;
103 SvTreeListEntry * pEntry = rRoleListBox.FirstSelected();
104 if( pEntry )
105 aResult = OUString( SvTabListBox::GetEntryText( pEntry,
106 bUITranslated ? 1 : 0 ));
107 return aResult;
110 OUString lcl_GetSelectedRolesRange( const SvTabListBox & rRoleListBox )
112 OUString aResult;
113 SvTreeListEntry * pEntry = rRoleListBox.FirstSelected();
114 if( pEntry )
115 aResult = OUString( SvTabListBox::GetEntryText( pEntry, 2 ));
116 return aResult;
119 OUString lcl_GetSequenceNameForLabel( ::chart::SeriesEntry * pEntry )
121 OUString aResult( "values-y" );
122 if( pEntry &&
123 pEntry->m_xChartType.is())
125 aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel();
127 return aResult;
130 static long lcl_pRoleListBoxTabs[] =
131 { 3, // Number of Tabs
132 0, 0, 75
135 void lcl_enableRangeChoosing( bool bEnable, Dialog * pDialog )
137 if( pDialog )
139 pDialog->Show( !bEnable );
140 pDialog->SetModalInputMode( !bEnable );
144 void lcl_addLSequenceToDataSource(
145 const Reference< chart2::data::XLabeledDataSequence > & xLSequence,
146 const Reference< chart2::data::XDataSource > & xSource )
148 Reference< data::XDataSink > xSink( xSource, uno::UNO_QUERY );
149 if( xSink.is())
151 Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
152 aData.realloc( aData.getLength() + 1 );
153 aData[ aData.getLength() - 1 ] = xLSequence;
154 xSink->setData( aData );
158 Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
159 const Reference< chart2::data::XDataSource > & xDataSource )
161 Reference< chart2::data::XLabeledDataSequence > xResult;
162 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
164 for( sal_Int32 i=0; i<aSequences.getLength(); ++i )
166 // no values are set but a label exists
167 if( ! aSequences[i]->getValues().is() &&
168 aSequences[i]->getLabel().is())
170 xResult.set( aSequences[i] );
171 break;
175 return xResult;
178 } // anonymous namespace
180 namespace chart
183 DataSourceTabPage::DataSourceTabPage(
184 vcl::Window * pParent,
185 DialogModel & rDialogModel,
186 ChartTypeTemplateProvider* pTemplateProvider,
187 Dialog * pParentDialog,
188 bool bHideDescription /* = false */ ) :
189 ::svt::OWizardPage( pParent
190 ,"tp_DataSource"
191 ,"modules/schart/ui/tp_DataSource.ui"),
192 m_pTemplateProvider( pTemplateProvider ),
193 m_rDialogModel( rDialogModel ),
195 m_pCurrentRangeChoosingField( 0 ),
196 m_bIsDirty( false ),
197 m_pParentDialog( pParentDialog ),
198 m_pTabPageNotifiable( dynamic_cast< TabPageNotifiable * >( pParentDialog ))
201 get(m_pFT_CAPTION ,"FT_CAPTION_FOR_WIZARD");
202 get(m_pFT_SERIES ,"FT_SERIES");
204 get(m_pLB_SERIES ,"LB_SERIES");
206 get(m_pBTN_ADD ,"BTN_ADD");
207 get(m_pBTN_REMOVE ,"BTN_REMOVE");
208 get(m_pBTN_UP ,"BTN_UP");
209 get(m_pBTN_DOWN ,"BTN_DOWN");
210 get(m_pFT_ROLE ,"FT_ROLE");
211 get(m_pLB_ROLE ,"LB_ROLE");
212 get(m_pFT_RANGE ,"FT_RANGE");
213 get(m_pEDT_RANGE ,"EDT_RANGE");
214 get(m_pIMB_RANGE_MAIN ,"IMB_RANGE_MAIN");
215 get(m_pFT_CATEGORIES ,"FT_CATEGORIES");
216 get(m_pFT_DATALABELS ,"FT_DATALABELS");
217 get(m_pEDT_CATEGORIES ,"EDT_CATEGORIES");
218 get(m_pIMB_RANGE_CAT ,"IMB_RANGE_CAT");
220 m_pFT_CAPTION->Show(!bHideDescription);
222 m_aFixedTextRange = OUString( m_pFT_RANGE->GetText() );
223 this->SetText( SCH_RESSTR( STR_OBJECT_DATASERIES_PLURAL ) );
225 // set handlers
226 m_pLB_SERIES->SetSelectHdl( LINK( this, DataSourceTabPage, SeriesSelectionChangedHdl ));
228 m_pLB_ROLE->SetSelectHdl( LINK( this, DataSourceTabPage, RoleSelectionChangedHdl ));
230 m_pIMB_RANGE_MAIN->SetClickHdl( LINK( this, DataSourceTabPage, MainRangeButtonClickedHdl ));
231 m_pIMB_RANGE_CAT->SetClickHdl( LINK( this, DataSourceTabPage, CategoriesRangeButtonClickedHdl ));
233 m_pBTN_ADD->SetClickHdl( LINK( this, DataSourceTabPage, AddButtonClickedHdl ));
234 m_pBTN_REMOVE->SetClickHdl( LINK( this, DataSourceTabPage, RemoveButtonClickedHdl ));
236 m_pBTN_UP->SetClickHdl( LINK( this, DataSourceTabPage, UpButtonClickedHdl ));
237 m_pBTN_DOWN->SetClickHdl( LINK( this, DataSourceTabPage, DownButtonClickedHdl ));
239 m_pEDT_RANGE->SetModifyHdl( LINK( this, DataSourceTabPage, RangeModifiedHdl ));
240 m_pEDT_CATEGORIES->SetModifyHdl( LINK( this, DataSourceTabPage, RangeModifiedHdl ));
241 m_pEDT_RANGE->SetUpdateDataHdl( LINK( this, DataSourceTabPage, RangeUpdateDataHdl ));
242 m_pEDT_CATEGORIES->SetUpdateDataHdl( LINK( this, DataSourceTabPage, RangeUpdateDataHdl ));
244 // #i75179# enable setting the background to a different color
245 m_pEDT_RANGE->SetStyle( m_pEDT_RANGE->GetStyle() | WB_FORCECTRLBACKGROUND );
246 m_pEDT_CATEGORIES->SetStyle( m_pEDT_CATEGORIES->GetStyle() | WB_FORCECTRLBACKGROUND );
248 // set symbol font for arrows
249 // note: StarSymbol is substituted to OpenSymbol for OOo
250 vcl::Font aSymbolFont( m_pBTN_UP->GetFont());
251 aSymbolFont.SetName( "StarSymbol" );
252 m_pBTN_UP->SetControlFont( aSymbolFont );
253 m_pBTN_DOWN->SetControlFont( aSymbolFont );
255 // set button text
256 sal_Unicode cBlackUpPointingTriangle( 0x25b2 );
257 sal_Unicode cBlackDownPointingTriangle( 0x25bc );
258 m_pBTN_UP->SetText( OUString( cBlackUpPointingTriangle ));
259 m_pBTN_DOWN->SetText( OUString( cBlackDownPointingTriangle ));
261 // init controls
262 m_pLB_ROLE->SetTabs( lcl_pRoleListBoxTabs, MAP_APPFONT );
263 m_pLB_ROLE->Show();
265 updateControlsFromDialogModel();
267 // select first series
268 if( m_pLB_SERIES->First())
269 m_pLB_SERIES->Select( m_pLB_SERIES->First());
270 m_pLB_SERIES->GrabFocus();
272 m_pBTN_UP->SetAccessibleName(SCH_RESSTR(STR_BUTTON_UP));
273 m_pBTN_DOWN->SetAccessibleName(SCH_RESSTR(STR_BUTTON_DOWN));
276 DataSourceTabPage::~DataSourceTabPage()
278 disposeOnce();
281 void DataSourceTabPage::dispose()
283 m_pFT_CAPTION.clear();
284 m_pFT_SERIES.clear();
285 m_pLB_SERIES.clear();
286 m_pBTN_ADD.clear();
287 m_pBTN_REMOVE.clear();
288 m_pBTN_UP.clear();
289 m_pBTN_DOWN.clear();
290 m_pFT_ROLE.clear();
291 m_pLB_ROLE.clear();
292 m_pFT_RANGE.clear();
293 m_pEDT_RANGE.clear();
294 m_pIMB_RANGE_MAIN.clear();
295 m_pFT_CATEGORIES.clear();
296 m_pFT_DATALABELS.clear();
297 m_pEDT_CATEGORIES.clear();
298 m_pIMB_RANGE_CAT.clear();
299 m_pCurrentRangeChoosingField.clear();
300 m_pParentDialog.clear();
301 ::svt::OWizardPage::dispose();
304 void DataSourceTabPage::ActivatePage()
306 OWizardPage::ActivatePage();
307 updateControlsFromDialogModel();
310 void DataSourceTabPage::initializePage()
314 void DataSourceTabPage::DeactivatePage()
316 commitPage();
317 svt::OWizardPage::DeactivatePage();
320 void DataSourceTabPage::commitPage()
322 commitPage(::svt::WizardTypes::eFinish);
325 bool DataSourceTabPage::commitPage( ::svt::WizardTypes::CommitPageReason /*eReason*/ )
327 //ranges may have been edited in the meanwhile (dirty is true in that case here)
328 if( isValid() )
330 updateModelFromControl( 0 /*update all*/ );
331 return true; //return false if this page should not be left
333 else
334 return false;
337 bool DataSourceTabPage::isRangeFieldContentValid( Edit & rEdit )
339 OUString aRange( rEdit.GetText());
340 bool bIsValid = ( aRange.isEmpty() ) ||
341 m_rDialogModel.getRangeSelectionHelper()->verifyCellRange( aRange );
343 if( bIsValid )
345 rEdit.SetControlForeground();
346 rEdit.SetControlBackground();
348 else
350 rEdit.SetControlBackground( RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR );
351 rEdit.SetControlForeground( RANGE_SELECTION_INVALID_RANGE_FOREGROUND_COLOR );
354 return bIsValid;
357 bool DataSourceTabPage::isValid()
359 bool bRoleRangeValid = true;
360 bool bCategoriesRangeValid = true;
361 bool bHasSelectedEntry = (m_pLB_SERIES->FirstSelected() != 0);
363 if( bHasSelectedEntry )
364 bRoleRangeValid = isRangeFieldContentValid( *m_pEDT_RANGE );
365 if( m_pEDT_CATEGORIES->IsEnabled() )
366 bCategoriesRangeValid = isRangeFieldContentValid( *m_pEDT_CATEGORIES );
367 bool bValid = ( bRoleRangeValid && bCategoriesRangeValid );
369 if( m_pTabPageNotifiable )
371 if( bValid )
372 m_pTabPageNotifiable->setValidPage( this );
373 else
374 m_pTabPageNotifiable->setInvalidPage( this );
377 return bValid;
380 void DataSourceTabPage::setDirty()
382 m_bIsDirty = true;
385 void DataSourceTabPage::updateControlsFromDialogModel()
387 // series
388 fillSeriesListBox();
389 SeriesSelectionChangedHdl( 0 );
391 // categories
392 m_pEDT_CATEGORIES->SetText( m_rDialogModel.getCategoriesRange() );
394 updateControlState();
397 void DataSourceTabPage::fillSeriesListBox()
399 m_pLB_SERIES->SetUpdateMode( false );
401 Reference< XDataSeries > xSelected;
402 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
403 if( pEntry )
404 xSelected.set( pEntry->m_xDataSeries );
406 bool bHasSelectedEntry = (pEntry != 0);
407 SvTreeListEntry * pSelectedEntry = 0;
408 m_pLB_SERIES->Clear();
410 ::std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries(
411 m_rDialogModel.getAllDataSeriesWithLabel() );
413 sal_Int32 nUnnamedSeriesIndex = 1;
414 for( ::std::vector< DialogModel::tSeriesWithChartTypeByName >::const_iterator aIt = aSeries.begin();
415 aIt != aSeries.end(); ++aIt )
417 OUString aLabel( (*aIt).first );
418 if( aLabel.isEmpty())
420 if( nUnnamedSeriesIndex > 1 )
422 OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ).toString());
424 // replace index of unnamed series
425 const OUString aReplacementStr( "%NUMBER" );
426 sal_Int32 nIndex = aResString.indexOf( aReplacementStr );
427 if( nIndex != -1 )
428 aLabel = OUString( aResString.replaceAt(
429 nIndex, aReplacementStr.getLength(),
430 OUString::number(nUnnamedSeriesIndex)));
432 if( aLabel.isEmpty() )
433 aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES ).toString();
435 ++nUnnamedSeriesIndex;
437 pEntry = dynamic_cast< SeriesEntry * >(
438 m_pLB_SERIES->InsertEntry( aLabel ));
439 if( pEntry )
441 pEntry->m_xDataSeries.set( (*aIt).second.first );
442 pEntry->m_xChartType.set( (*aIt).second.second );
443 if( bHasSelectedEntry && ((*aIt).second.first == xSelected))
444 pSelectedEntry = pEntry;
448 if( bHasSelectedEntry && pSelectedEntry )
449 m_pLB_SERIES->Select( pSelectedEntry );
451 m_pLB_SERIES->SetUpdateMode( true );
454 void DataSourceTabPage::fillRoleListBox()
456 SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
457 bool bHasSelectedEntry = (pSeriesEntry != 0);
459 SvTreeListEntry * pRoleEntry = m_pLB_ROLE->FirstSelected();
460 sal_uLong nRoleIndex = SAL_MAX_UINT32;
461 if( pRoleEntry )
462 nRoleIndex = m_pLB_ROLE->GetModel()->GetAbsPos( pRoleEntry );
464 if( bHasSelectedEntry )
466 DialogModel::tRolesWithRanges aRoles(
467 DialogModel::getRolesWithRanges(
468 pSeriesEntry->m_xDataSeries,
469 lcl_GetSequenceNameForLabel( pSeriesEntry ),
470 pSeriesEntry->m_xChartType ));
472 // fill role list
473 m_pLB_ROLE->SetUpdateMode( false );
474 m_pLB_ROLE->Clear();
475 m_pLB_ROLE->RemoveSelection();
477 for( DialogModel::tRolesWithRanges::const_iterator aIt( aRoles.begin());
478 aIt != aRoles.end(); ++ aIt )
480 m_pLB_ROLE->InsertEntry( lcl_GetRoleLBEntry( aIt->first, aIt->second ));
483 // series may contain no roles, check listbox size before selecting entries
484 if( m_pLB_ROLE->GetEntryCount() > 0 )
486 if( nRoleIndex >= m_pLB_ROLE->GetEntryCount())
487 nRoleIndex = 0;
488 m_pLB_ROLE->Select( m_pLB_ROLE->GetEntry( nRoleIndex ));
491 m_pLB_ROLE->SetUpdateMode( true );
495 void DataSourceTabPage::updateControlState()
497 SvTreeListEntry * pSeriesEntry = m_pLB_SERIES->FirstSelected();
498 bool bHasSelectedSeries = (pSeriesEntry != 0);
499 bool bHasValidRole = false;
500 bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
502 if( bHasSelectedSeries )
504 SvTreeListEntry * pRoleEntry = m_pLB_ROLE->FirstSelected();
505 bHasValidRole = (pRoleEntry != 0);
508 m_pBTN_ADD->Enable( true );
509 m_pBTN_REMOVE->Enable( bHasSelectedSeries );
511 m_pBTN_UP->Enable( bHasSelectedSeries && (pSeriesEntry != m_pLB_SERIES->First()));
512 m_pBTN_DOWN->Enable( bHasSelectedSeries && (pSeriesEntry != m_pLB_SERIES->Last()));
514 bool bHasCategories = m_rDialogModel.isCategoryDiagram();
516 m_pFT_DATALABELS->Show(!bHasCategories);
517 m_pFT_CATEGORIES->Show( bHasCategories);
518 bool bShowIB = bHasRangeChooser;
520 m_pIMB_RANGE_CAT->Show(bShowIB);
522 m_pFT_SERIES->Enable();
523 m_pLB_SERIES->Enable();
525 m_pFT_ROLE->Enable( bHasSelectedSeries );
526 m_pLB_ROLE->Enable( bHasSelectedSeries );
528 m_pFT_RANGE->Enable( bHasValidRole );
529 m_pEDT_RANGE->Enable( bHasValidRole );
531 m_pIMB_RANGE_MAIN->Show(bShowIB);
533 isValid();
536 IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl)
538 m_rDialogModel.startControllerLockTimer();
539 if( m_pLB_SERIES->FirstSelected())
541 fillRoleListBox();
542 RoleSelectionChangedHdl( 0 );
544 updateControlState();
546 return 0;
549 IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl)
551 m_rDialogModel.startControllerLockTimer();
552 SvTreeListEntry * pEntry = m_pLB_ROLE->FirstSelected();
553 if( pEntry )
555 OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_pLB_ROLE, true );
556 OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_pLB_ROLE );
558 // replace role in fixed text label
559 const OUString aReplacementStr( "%VALUETYPE" );
560 sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
561 if( nIndex != -1 )
563 m_pFT_RANGE->SetText(
564 m_aFixedTextRange.replaceAt(
565 nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
568 m_pEDT_RANGE->SetText( aSelectedRange );
569 isValid();
572 return 0;
575 IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl)
577 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
578 m_pCurrentRangeChoosingField = m_pEDT_RANGE;
579 if( !m_pEDT_RANGE->GetText().isEmpty() &&
580 ! updateModelFromControl( m_pCurrentRangeChoosingField ))
581 return 0;
583 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
584 bool bHasSelectedEntry = (pEntry != 0);
586 OUString aSelectedRolesRange = lcl_GetSelectedRolesRange( *m_pLB_ROLE );
588 if( bHasSelectedEntry && (m_pLB_ROLE->FirstSelected() != 0))
590 OUString aUIStr(SCH_RESSTR(STR_DATA_SELECT_RANGE_FOR_SERIES));
592 // replace role
593 OUString aReplacement( "%VALUETYPE" );
594 sal_Int32 nIndex = aUIStr.indexOf( aReplacement );
595 if( nIndex != -1 )
597 aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
598 lcl_GetSelectedRole( *m_pLB_ROLE, true ));
600 // replace series name
601 aReplacement = "%SERIESNAME";
602 nIndex = aUIStr.indexOf( aReplacement );
603 if( nIndex != -1 )
605 aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
606 OUString( m_pLB_SERIES->GetEntryText( pEntry )));
609 lcl_enableRangeChoosing( true, m_pParentDialog );
610 m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this );
612 else
613 m_pCurrentRangeChoosingField = 0;
615 return 0;
618 IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl)
620 OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
621 m_pCurrentRangeChoosingField = m_pEDT_CATEGORIES;
622 if( !m_pEDT_CATEGORIES->GetText().isEmpty() &&
623 ! updateModelFromControl( m_pCurrentRangeChoosingField ))
624 return 0;
626 OUString aStr( SCH_RESSTR( m_pFT_CATEGORIES->IsVisible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS ));
627 lcl_enableRangeChoosing( true, m_pParentDialog );
628 m_rDialogModel.getRangeSelectionHelper()->chooseRange(
629 m_rDialogModel.getCategoriesRange(), aStr, *this );
630 return 0;
633 IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl)
635 m_rDialogModel.startControllerLockTimer();
636 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
637 Reference< XDataSeries > xSeriesToInsertAfter;
638 Reference< XChartType > xChartTypeForNewSeries;
639 if( m_pTemplateProvider )
640 m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
642 if( pEntry )
644 xSeriesToInsertAfter.set( pEntry->m_xDataSeries );
645 xChartTypeForNewSeries.set( pEntry->m_xChartType );
647 else
649 ::std::vector< Reference< XDataSeriesContainer > > aCntVec(
650 m_rDialogModel.getAllDataSeriesContainers());
651 if( ! aCntVec.empty())
652 xChartTypeForNewSeries.set( aCntVec.front(), uno::UNO_QUERY );
654 OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" );
656 m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries );
657 setDirty();
659 fillSeriesListBox();
660 // note the box was cleared and refilled, so pEntry is invalid now
661 SvTreeListEntry * pSelEntry = m_pLB_SERIES->FirstSelected();
662 if( pSelEntry )
664 SvTreeListEntry * pNextEntry = m_pLB_SERIES->Next( pSelEntry );
665 if( pNextEntry )
666 m_pLB_SERIES->Select( pNextEntry );
668 SeriesSelectionChangedHdl( 0 );
670 return 0;
673 IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl)
675 m_rDialogModel.startControllerLockTimer();
676 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
677 if( pEntry )
679 Reference< XDataSeries > xNewSelSeries;
680 SeriesEntry * pNewSelEntry = dynamic_cast< SeriesEntry * >(m_pLB_SERIES->Next( pEntry ));
681 if( pNewSelEntry )
682 xNewSelSeries.set( pNewSelEntry->m_xDataSeries );
683 else
685 pNewSelEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->Prev( pEntry ));
686 if( pNewSelEntry )
687 xNewSelSeries.set( pNewSelEntry->m_xDataSeries );
690 m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType );
691 setDirty();
693 m_pLB_SERIES->RemoveSelection();
694 fillSeriesListBox();
696 // select previous or next series
697 //@improve: see methods GetModel()->GetAbsPos()/GetEntry() for absolute list positions
698 if( xNewSelSeries.is())
700 pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->First());
701 while( pEntry )
703 if( pEntry->m_xDataSeries == xNewSelSeries )
705 m_pLB_SERIES->Select( pEntry );
706 break;
708 pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->Next( pEntry ));
711 SeriesSelectionChangedHdl( 0 );
714 return 0;
717 IMPL_LINK_NOARG(DataSourceTabPage, UpButtonClickedHdl)
719 m_rDialogModel.startControllerLockTimer();
720 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
721 bool bHasSelectedEntry = (pEntry != 0);
723 if( bHasSelectedEntry )
725 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_UP );
726 setDirty();
727 fillSeriesListBox();
728 SeriesSelectionChangedHdl(0);
731 return 0;
734 IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl)
736 m_rDialogModel.startControllerLockTimer();
737 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
738 bool bHasSelectedEntry = (pEntry != 0);
740 if( bHasSelectedEntry )
742 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_DOWN );
743 setDirty();
744 fillSeriesListBox();
745 SeriesSelectionChangedHdl(0);
748 return 0;
751 IMPL_LINK( DataSourceTabPage, RangeModifiedHdl, Edit*, pEdit )
753 // note: isValid sets the color of the edit field
754 if( isRangeFieldContentValid( *pEdit ))
756 setDirty();
757 updateModelFromControl( pEdit );
758 if( pEdit == m_pEDT_RANGE )
760 if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
761 fillSeriesListBox();
765 // enable/disable OK button
766 isValid();
768 return 0;
771 IMPL_LINK( DataSourceTabPage, RangeUpdateDataHdl, Edit*, pEdit )
773 // note: isValid sets the color of the edit field
774 if( isRangeFieldContentValid( *pEdit ))
776 setDirty();
777 updateModelFromControl( pEdit );
778 if( pEdit == m_pEDT_RANGE )
780 if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
781 fillSeriesListBox();
784 // enable/disable OK button
785 isValid();
787 return 0;
790 void DataSourceTabPage::listeningFinished(
791 const OUString & rNewRange )
793 // rNewRange becomes invalid after removing the listener
794 OUString aRange( rNewRange );
796 m_rDialogModel.startControllerLockTimer();
798 // stop listening
799 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
801 // change edit field
802 ToTop();
803 GrabFocus();
804 if( m_pCurrentRangeChoosingField )
806 m_pCurrentRangeChoosingField->SetText( aRange );
807 m_pCurrentRangeChoosingField->GrabFocus();
810 if( m_pCurrentRangeChoosingField == m_pEDT_RANGE )
812 m_pEDT_RANGE->SetText( aRange );
813 setDirty();
815 else if( m_pCurrentRangeChoosingField == m_pEDT_CATEGORIES )
817 m_pEDT_CATEGORIES->SetText( aRange );
818 setDirty();
821 updateModelFromControl( m_pCurrentRangeChoosingField );
822 if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
823 fillSeriesListBox();
825 m_pCurrentRangeChoosingField = 0;
827 updateControlState();
828 lcl_enableRangeChoosing( false, m_pParentDialog );
831 void DataSourceTabPage::disposingRangeSelection()
833 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
836 bool DataSourceTabPage::updateModelFromControl( Edit * pField )
838 if( !m_bIsDirty )
839 return true;
841 ControllerLockGuardUNO aLockedControllers( m_rDialogModel.getChartModel() );
843 // @todo: validity check of field content
844 bool bResult = true;
845 bool bAll = (pField == 0);
846 Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider());
848 if( bAll || (pField == m_pEDT_CATEGORIES) )
850 Reference< data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() );
851 if( xDataProvider.is())
853 OUString aRange( m_pEDT_CATEGORIES->GetText());
854 if( !aRange.isEmpty())
856 // create or change categories
857 if( !xLabeledSeq.is())
859 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
860 m_rDialogModel.setCategories( xLabeledSeq );
864 xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
866 catch( const uno::Exception & ex )
868 // should work as validation should have happened before
869 ASSERT_EXCEPTION( ex );
872 else if( xLabeledSeq.is())
874 // clear existing categories
875 xLabeledSeq.set(0);
876 m_rDialogModel.setCategories( xLabeledSeq );
881 SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
882 bool bHasSelectedEntry = (pSeriesEntry != 0);
884 if( bHasSelectedEntry )
886 if( bAll || (pField == m_pEDT_RANGE) )
890 OUString aSelectedRole = lcl_GetSelectedRole( *m_pLB_ROLE );
891 OUString aRange( m_pEDT_RANGE->GetText());
892 OUString aSequenceRole( aSelectedRole );
893 bool bIsLabel = (aSequenceRole == lcl_aLabelRole );
894 OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry ));
896 if( bIsLabel )
897 aSequenceRole = aSequenceNameForLabel;
899 Reference< data::XDataSource > xSource( pSeriesEntry->m_xDataSeries, uno::UNO_QUERY_THROW );
900 Reference< data::XLabeledDataSequence > xLabeledSeq(
901 DataSeriesHelper::getDataSequenceByRole( xSource, aSequenceRole ));
903 if( xDataProvider.is())
905 if( bIsLabel )
907 if( ! xLabeledSeq.is())
909 // check if there is already an "orphan" label sequence
910 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
911 if( ! xLabeledSeq.is())
913 // no corresponding labeled data sequence for label found
914 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
915 lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
918 if( xLabeledSeq.is())
920 if( !aRange.isEmpty())
922 Reference< data::XDataSequence > xNewSeq;
925 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
927 catch( const uno::Exception & ex )
929 // should work as validation should have happened before
930 ASSERT_EXCEPTION( ex );
932 if( xNewSeq.is())
934 // update range name by the full string provided
935 // by the data provider. E.g. "a1" might become
936 // "$Sheet1.$A$1"
937 aRange = xNewSeq->getSourceRangeRepresentation();
938 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
939 xProp->setPropertyValue( "Role" , uno::makeAny( lcl_aLabelRole ));
940 xLabeledSeq->setLabel( xNewSeq );
943 else
945 xLabeledSeq->setLabel( Reference< data::XDataSequence >());
949 else
951 if( !aRange.isEmpty())
953 Reference< data::XDataSequence > xNewSeq;
956 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
958 catch( const uno::Exception & ex )
960 // should work as validation should have happened before
961 ASSERT_EXCEPTION( ex );
963 if( xNewSeq.is())
965 // update range name by the full string provided
966 // by the data provider. E.g. "a1:e1" might become
967 // "$Sheet1.$A$1:$E$1"
968 aRange = xNewSeq->getSourceRangeRepresentation();
970 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
971 xProp->setPropertyValue( "Role" , uno::makeAny( aSelectedRole ));
972 if( !xLabeledSeq.is())
974 if( aSelectedRole == aSequenceNameForLabel )
975 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
976 if( ! xLabeledSeq.is())
978 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
979 lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
982 xLabeledSeq->setValues( xNewSeq );
988 lcl_UpdateCurrentRange( *m_pLB_ROLE, aSelectedRole, aRange );
990 catch( const uno::Exception & ex )
992 bResult = false;
993 ASSERT_EXCEPTION( ex );
998 // update View
999 // @todo remove this when automatic view updates from calc, writer and own data sequences are available
1000 if( bResult )
1004 Reference< util::XModifiable > xModifiable( m_rDialogModel.getChartModel(), uno::UNO_QUERY );
1005 if( xModifiable.is() )
1006 xModifiable->setModified( sal_True );
1007 const DialogModelTimeBasedInfo& rInfo = m_rDialogModel.getTimeBasedInfo();
1008 if(rInfo.bTimeBased)
1010 m_rDialogModel.setTimeBasedRange(rInfo.bTimeBased, rInfo.nStart, rInfo.nEnd);
1013 catch( const uno::Exception & ex )
1015 ASSERT_EXCEPTION( ex );
1019 return bResult;
1022 } // namespace chart
1024 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */