Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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>
37 :
38 : #include <vcl/msgbox.hxx>
39 : #include <rtl/ustrbuf.hxx>
40 :
41 : #include <functional>
42 : #include <algorithm>
43 : #include <map>
44 :
45 : using namespace ::com::sun::star;
46 : using namespace ::com::sun::star::chart2;
47 :
48 : using ::com::sun::star::uno::Reference;
49 : using ::com::sun::star::uno::Sequence;
50 :
51 : namespace
52 : {
53 :
54 19 : const OUString lcl_aLabelRole( "label" );
55 :
56 0 : OUString lcl_GetRoleLBEntry(
57 : const OUString & rRole, const OUString & rRange )
58 : {
59 0 : OUStringBuffer aEntry( rRole );
60 0 : aEntry.append( "\t" );
61 : aEntry.append( OUString(
62 0 : ::chart::DialogModel::ConvertRoleFromInternalToUI( rRole )) );
63 0 : aEntry.append( "\t" );
64 0 : aEntry.append(OUString( rRange ));
65 :
66 0 : OUString sFoo = aEntry.makeStringAndClear();
67 0 : return sFoo;
68 : }
69 :
70 0 : void lcl_UpdateCurrentRange(
71 : SvTabListBox & rOutListBox,
72 : const OUString & rRole, const OUString & rRange )
73 : {
74 0 : SvTreeListEntry * pEntry = rOutListBox.FirstSelected();
75 0 : if( pEntry )
76 0 : rOutListBox.SetEntryText( lcl_GetRoleLBEntry( rRole, rRange ), pEntry );
77 0 : }
78 :
79 0 : bool lcl_UpdateCurrentSeriesName(
80 : SvTreeListBox & rOutListBox )
81 : {
82 0 : bool bResult = false;
83 0 : ::chart::SeriesEntry * pEntry = dynamic_cast< ::chart::SeriesEntry * >( rOutListBox.FirstSelected());
84 0 : if( pEntry &&
85 0 : pEntry->m_xDataSeries.is() &&
86 0 : pEntry->m_xChartType.is())
87 : {
88 : OUString aLabel( ::chart::DataSeriesHelper::getDataSeriesLabel(
89 : pEntry->m_xDataSeries,
90 0 : pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel()));
91 0 : if( !aLabel.isEmpty())
92 : {
93 0 : rOutListBox.SetEntryText( pEntry, aLabel );
94 0 : bResult = true;
95 0 : }
96 : }
97 0 : return bResult;
98 : }
99 :
100 0 : OUString lcl_GetSelectedRole( const SvTabListBox & rRoleListBox, bool bUITranslated = false )
101 : {
102 0 : OUString aResult;
103 0 : SvTreeListEntry * pEntry = rRoleListBox.FirstSelected();
104 0 : if( pEntry )
105 0 : aResult = OUString( SvTabListBox::GetEntryText( pEntry,
106 0 : bUITranslated ? 1 : 0 ));
107 0 : return aResult;
108 : }
109 :
110 0 : OUString lcl_GetSelectedRolesRange( const SvTabListBox & rRoleListBox )
111 : {
112 0 : OUString aResult;
113 0 : SvTreeListEntry * pEntry = rRoleListBox.FirstSelected();
114 0 : if( pEntry )
115 0 : aResult = OUString( SvTabListBox::GetEntryText( pEntry, 2 ));
116 0 : return aResult;
117 : }
118 :
119 0 : OUString lcl_GetSequenceNameForLabel( ::chart::SeriesEntry * pEntry )
120 : {
121 0 : OUString aResult( "values-y" );
122 0 : if( pEntry &&
123 0 : pEntry->m_xChartType.is())
124 : {
125 0 : aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel();
126 : }
127 0 : return aResult;
128 : }
129 :
130 : static long lcl_pRoleListBoxTabs[] =
131 : { 3, // Number of Tabs
132 : 0, 0, 75
133 : };
134 :
135 0 : void lcl_enableRangeChoosing( bool bEnable, Dialog * pDialog )
136 : {
137 0 : if( pDialog )
138 : {
139 0 : pDialog->Show( !bEnable );
140 0 : pDialog->SetModalInputMode( !bEnable );
141 : }
142 0 : }
143 :
144 0 : void lcl_addLSequenceToDataSource(
145 : const Reference< chart2::data::XLabeledDataSequence > & xLSequence,
146 : const Reference< chart2::data::XDataSource > & xSource )
147 : {
148 0 : Reference< data::XDataSink > xSink( xSource, uno::UNO_QUERY );
149 0 : if( xSink.is())
150 : {
151 0 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences());
152 0 : aData.realloc( aData.getLength() + 1 );
153 0 : aData[ aData.getLength() - 1 ] = xLSequence;
154 0 : xSink->setData( aData );
155 0 : }
156 0 : }
157 :
158 0 : Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel(
159 : const Reference< chart2::data::XDataSource > & xDataSource )
160 : {
161 0 : Reference< chart2::data::XLabeledDataSequence > xResult;
162 0 : Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
163 :
164 0 : for( sal_Int32 i=0; i<aSequences.getLength(); ++i )
165 : {
166 : // no values are set but a label exists
167 0 : if( ! aSequences[i]->getValues().is() &&
168 0 : aSequences[i]->getLabel().is())
169 : {
170 0 : xResult.set( aSequences[i] );
171 0 : break;
172 : }
173 : }
174 :
175 0 : return xResult;
176 : }
177 :
178 : } // anonymous namespace
179 :
180 : namespace chart
181 : {
182 :
183 0 : 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 ),
194 :
195 : m_pCurrentRangeChoosingField( 0 ),
196 : m_bIsDirty( false ),
197 : m_pParentDialog( pParentDialog ),
198 0 : m_pTabPageNotifiable( dynamic_cast< TabPageNotifiable * >( pParentDialog ))
199 : {
200 :
201 0 : get(m_pFT_CAPTION ,"FT_CAPTION_FOR_WIZARD");
202 0 : get(m_pFT_SERIES ,"FT_SERIES");
203 :
204 0 : get(m_pLB_SERIES ,"LB_SERIES");
205 :
206 0 : get(m_pBTN_ADD ,"BTN_ADD");
207 0 : get(m_pBTN_REMOVE ,"BTN_REMOVE");
208 0 : get(m_pBTN_UP ,"BTN_UP");
209 0 : get(m_pBTN_DOWN ,"BTN_DOWN");
210 0 : get(m_pFT_ROLE ,"FT_ROLE");
211 0 : get(m_pLB_ROLE ,"LB_ROLE");
212 0 : get(m_pFT_RANGE ,"FT_RANGE");
213 0 : get(m_pEDT_RANGE ,"EDT_RANGE");
214 0 : get(m_pIMB_RANGE_MAIN ,"IMB_RANGE_MAIN");
215 0 : get(m_pFT_CATEGORIES ,"FT_CATEGORIES");
216 0 : get(m_pFT_DATALABELS ,"FT_DATALABELS");
217 0 : get(m_pEDT_CATEGORIES ,"EDT_CATEGORIES");
218 0 : get(m_pIMB_RANGE_CAT ,"IMB_RANGE_CAT");
219 :
220 0 : m_pFT_CAPTION->Show(!bHideDescription);
221 :
222 0 : m_aFixedTextRange = OUString( m_pFT_RANGE->GetText() );
223 0 : this->SetText( SCH_RESSTR( STR_OBJECT_DATASERIES_PLURAL ) );
224 :
225 : // set handlers
226 0 : m_pLB_SERIES->SetSelectHdl( LINK( this, DataSourceTabPage, SeriesSelectionChangedHdl ));
227 :
228 0 : m_pLB_ROLE->SetSelectHdl( LINK( this, DataSourceTabPage, RoleSelectionChangedHdl ));
229 :
230 0 : m_pIMB_RANGE_MAIN->SetClickHdl( LINK( this, DataSourceTabPage, MainRangeButtonClickedHdl ));
231 0 : m_pIMB_RANGE_CAT->SetClickHdl( LINK( this, DataSourceTabPage, CategoriesRangeButtonClickedHdl ));
232 :
233 0 : m_pBTN_ADD->SetClickHdl( LINK( this, DataSourceTabPage, AddButtonClickedHdl ));
234 0 : m_pBTN_REMOVE->SetClickHdl( LINK( this, DataSourceTabPage, RemoveButtonClickedHdl ));
235 :
236 0 : m_pBTN_UP->SetClickHdl( LINK( this, DataSourceTabPage, UpButtonClickedHdl ));
237 0 : m_pBTN_DOWN->SetClickHdl( LINK( this, DataSourceTabPage, DownButtonClickedHdl ));
238 :
239 0 : m_pEDT_RANGE->SetModifyHdl( LINK( this, DataSourceTabPage, RangeModifiedHdl ));
240 0 : m_pEDT_CATEGORIES->SetModifyHdl( LINK( this, DataSourceTabPage, RangeModifiedHdl ));
241 0 : m_pEDT_RANGE->SetUpdateDataHdl( LINK( this, DataSourceTabPage, RangeUpdateDataHdl ));
242 0 : m_pEDT_CATEGORIES->SetUpdateDataHdl( LINK( this, DataSourceTabPage, RangeUpdateDataHdl ));
243 :
244 : // #i75179# enable setting the background to a different color
245 0 : m_pEDT_RANGE->SetStyle( m_pEDT_RANGE->GetStyle() | WB_FORCECTRLBACKGROUND );
246 0 : m_pEDT_CATEGORIES->SetStyle( m_pEDT_CATEGORIES->GetStyle() | WB_FORCECTRLBACKGROUND );
247 :
248 : // set symbol font for arrows
249 : // note: StarSymbol is substituted to OpenSymbol for OOo
250 0 : vcl::Font aSymbolFont( m_pBTN_UP->GetFont());
251 0 : aSymbolFont.SetName( "StarSymbol" );
252 0 : m_pBTN_UP->SetControlFont( aSymbolFont );
253 0 : m_pBTN_DOWN->SetControlFont( aSymbolFont );
254 :
255 : // set button text
256 0 : sal_Unicode cBlackUpPointingTriangle( 0x25b2 );
257 0 : sal_Unicode cBlackDownPointingTriangle( 0x25bc );
258 0 : m_pBTN_UP->SetText( OUString( cBlackUpPointingTriangle ));
259 0 : m_pBTN_DOWN->SetText( OUString( cBlackDownPointingTriangle ));
260 :
261 : // init controls
262 0 : m_pLB_ROLE->SetTabs( lcl_pRoleListBoxTabs, MAP_APPFONT );
263 0 : m_pLB_ROLE->Show();
264 :
265 0 : updateControlsFromDialogModel();
266 :
267 : // select first series
268 0 : if( m_pLB_SERIES->First())
269 0 : m_pLB_SERIES->Select( m_pLB_SERIES->First());
270 0 : m_pLB_SERIES->GrabFocus();
271 :
272 0 : m_pBTN_UP->SetAccessibleName(SCH_RESSTR(STR_BUTTON_UP));
273 0 : m_pBTN_DOWN->SetAccessibleName(SCH_RESSTR(STR_BUTTON_DOWN));
274 0 : }
275 :
276 0 : DataSourceTabPage::~DataSourceTabPage()
277 : {
278 0 : disposeOnce();
279 0 : }
280 :
281 0 : void DataSourceTabPage::dispose()
282 : {
283 0 : m_pFT_CAPTION.clear();
284 0 : m_pFT_SERIES.clear();
285 0 : m_pLB_SERIES.clear();
286 0 : m_pBTN_ADD.clear();
287 0 : m_pBTN_REMOVE.clear();
288 0 : m_pBTN_UP.clear();
289 0 : m_pBTN_DOWN.clear();
290 0 : m_pFT_ROLE.clear();
291 0 : m_pLB_ROLE.clear();
292 0 : m_pFT_RANGE.clear();
293 0 : m_pEDT_RANGE.clear();
294 0 : m_pIMB_RANGE_MAIN.clear();
295 0 : m_pFT_CATEGORIES.clear();
296 0 : m_pFT_DATALABELS.clear();
297 0 : m_pEDT_CATEGORIES.clear();
298 0 : m_pIMB_RANGE_CAT.clear();
299 0 : m_pCurrentRangeChoosingField.clear();
300 0 : m_pParentDialog.clear();
301 0 : ::svt::OWizardPage::dispose();
302 0 : }
303 :
304 0 : void DataSourceTabPage::ActivatePage()
305 : {
306 0 : OWizardPage::ActivatePage();
307 0 : updateControlsFromDialogModel();
308 0 : }
309 :
310 0 : void DataSourceTabPage::initializePage()
311 : {
312 0 : }
313 :
314 0 : void DataSourceTabPage::DeactivatePage()
315 : {
316 0 : commitPage();
317 0 : svt::OWizardPage::DeactivatePage();
318 0 : }
319 :
320 0 : void DataSourceTabPage::commitPage()
321 : {
322 0 : commitPage(::svt::WizardTypes::eFinish);
323 0 : }
324 :
325 0 : bool DataSourceTabPage::commitPage( ::svt::WizardTypes::CommitPageReason /*eReason*/ )
326 : {
327 : //ranges may have been edited in the meanwhile (dirty is true in that case here)
328 0 : if( isValid() )
329 : {
330 0 : updateModelFromControl( 0 /*update all*/ );
331 0 : return true; //return false if this page should not be left
332 : }
333 : else
334 0 : return false;
335 : }
336 :
337 0 : bool DataSourceTabPage::isRangeFieldContentValid( Edit & rEdit )
338 : {
339 0 : OUString aRange( rEdit.GetText());
340 0 : bool bIsValid = ( aRange.isEmpty() ) ||
341 0 : m_rDialogModel.getRangeSelectionHelper()->verifyCellRange( aRange );
342 :
343 0 : if( bIsValid )
344 : {
345 0 : rEdit.SetControlForeground();
346 0 : rEdit.SetControlBackground();
347 : }
348 : else
349 : {
350 0 : rEdit.SetControlBackground( RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR );
351 0 : rEdit.SetControlForeground( RANGE_SELECTION_INVALID_RANGE_FOREGROUND_COLOR );
352 : }
353 :
354 0 : return bIsValid;
355 : }
356 :
357 0 : bool DataSourceTabPage::isValid()
358 : {
359 0 : bool bRoleRangeValid = true;
360 0 : bool bCategoriesRangeValid = true;
361 0 : bool bHasSelectedEntry = (m_pLB_SERIES->FirstSelected() != 0);
362 :
363 0 : if( bHasSelectedEntry )
364 0 : bRoleRangeValid = isRangeFieldContentValid( *m_pEDT_RANGE );
365 0 : if( m_pEDT_CATEGORIES->IsEnabled() )
366 0 : bCategoriesRangeValid = isRangeFieldContentValid( *m_pEDT_CATEGORIES );
367 0 : bool bValid = ( bRoleRangeValid && bCategoriesRangeValid );
368 :
369 0 : if( m_pTabPageNotifiable )
370 : {
371 0 : if( bValid )
372 0 : m_pTabPageNotifiable->setValidPage( this );
373 : else
374 0 : m_pTabPageNotifiable->setInvalidPage( this );
375 : }
376 :
377 0 : return bValid;
378 : }
379 :
380 0 : void DataSourceTabPage::setDirty()
381 : {
382 0 : m_bIsDirty = true;
383 0 : }
384 :
385 0 : void DataSourceTabPage::updateControlsFromDialogModel()
386 : {
387 : // series
388 0 : fillSeriesListBox();
389 0 : SeriesSelectionChangedHdl( 0 );
390 :
391 : // categories
392 0 : m_pEDT_CATEGORIES->SetText( m_rDialogModel.getCategoriesRange() );
393 :
394 0 : updateControlState();
395 0 : }
396 :
397 0 : void DataSourceTabPage::fillSeriesListBox()
398 : {
399 0 : m_pLB_SERIES->SetUpdateMode( false );
400 :
401 0 : Reference< XDataSeries > xSelected;
402 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
403 0 : if( pEntry )
404 0 : xSelected.set( pEntry->m_xDataSeries );
405 :
406 0 : bool bHasSelectedEntry = (pEntry != 0);
407 0 : SvTreeListEntry * pSelectedEntry = 0;
408 0 : m_pLB_SERIES->Clear();
409 :
410 : ::std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries(
411 0 : m_rDialogModel.getAllDataSeriesWithLabel() );
412 :
413 0 : sal_Int32 nUnnamedSeriesIndex = 1;
414 0 : for( ::std::vector< DialogModel::tSeriesWithChartTypeByName >::const_iterator aIt = aSeries.begin();
415 0 : aIt != aSeries.end(); ++aIt )
416 : {
417 0 : OUString aLabel( (*aIt).first );
418 0 : if( aLabel.isEmpty())
419 : {
420 0 : if( nUnnamedSeriesIndex > 1 )
421 : {
422 0 : OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ).toString());
423 :
424 : // replace index of unnamed series
425 0 : const OUString aReplacementStr( "%NUMBER" );
426 0 : sal_Int32 nIndex = aResString.indexOf( aReplacementStr );
427 0 : if( nIndex != -1 )
428 0 : aLabel = OUString( aResString.replaceAt(
429 : nIndex, aReplacementStr.getLength(),
430 0 : OUString::number(nUnnamedSeriesIndex)));
431 : }
432 0 : if( aLabel.isEmpty() )
433 0 : aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES ).toString();
434 :
435 0 : ++nUnnamedSeriesIndex;
436 : }
437 : pEntry = dynamic_cast< SeriesEntry * >(
438 0 : m_pLB_SERIES->InsertEntry( aLabel ));
439 0 : if( pEntry )
440 : {
441 0 : pEntry->m_xDataSeries.set( (*aIt).second.first );
442 0 : pEntry->m_xChartType.set( (*aIt).second.second );
443 0 : if( bHasSelectedEntry && ((*aIt).second.first == xSelected))
444 0 : pSelectedEntry = pEntry;
445 : }
446 0 : }
447 :
448 0 : if( bHasSelectedEntry && pSelectedEntry )
449 0 : m_pLB_SERIES->Select( pSelectedEntry );
450 :
451 0 : m_pLB_SERIES->SetUpdateMode( true );
452 0 : }
453 :
454 0 : void DataSourceTabPage::fillRoleListBox()
455 : {
456 0 : SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
457 0 : bool bHasSelectedEntry = (pSeriesEntry != 0);
458 :
459 0 : SvTreeListEntry * pRoleEntry = m_pLB_ROLE->FirstSelected();
460 0 : sal_uLong nRoleIndex = SAL_MAX_UINT32;
461 0 : if( pRoleEntry )
462 0 : nRoleIndex = m_pLB_ROLE->GetModel()->GetAbsPos( pRoleEntry );
463 :
464 0 : if( bHasSelectedEntry )
465 : {
466 : DialogModel::tRolesWithRanges aRoles(
467 : DialogModel::getRolesWithRanges(
468 : pSeriesEntry->m_xDataSeries,
469 : lcl_GetSequenceNameForLabel( pSeriesEntry ),
470 0 : pSeriesEntry->m_xChartType ));
471 :
472 : // fill role list
473 0 : m_pLB_ROLE->SetUpdateMode( false );
474 0 : m_pLB_ROLE->Clear();
475 0 : m_pLB_ROLE->RemoveSelection();
476 :
477 0 : for( DialogModel::tRolesWithRanges::const_iterator aIt( aRoles.begin());
478 0 : aIt != aRoles.end(); ++ aIt )
479 : {
480 0 : m_pLB_ROLE->InsertEntry( lcl_GetRoleLBEntry( aIt->first, aIt->second ));
481 : }
482 :
483 : // series may contain no roles, check listbox size before selecting entries
484 0 : if( m_pLB_ROLE->GetEntryCount() > 0 )
485 : {
486 0 : if( nRoleIndex >= m_pLB_ROLE->GetEntryCount())
487 0 : nRoleIndex = 0;
488 0 : m_pLB_ROLE->Select( m_pLB_ROLE->GetEntry( nRoleIndex ));
489 : }
490 :
491 0 : m_pLB_ROLE->SetUpdateMode( true );
492 : }
493 0 : }
494 :
495 0 : void DataSourceTabPage::updateControlState()
496 : {
497 0 : SvTreeListEntry * pSeriesEntry = m_pLB_SERIES->FirstSelected();
498 0 : bool bHasSelectedSeries = (pSeriesEntry != 0);
499 0 : bool bHasValidRole = false;
500 0 : bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
501 :
502 0 : if( bHasSelectedSeries )
503 : {
504 0 : SvTreeListEntry * pRoleEntry = m_pLB_ROLE->FirstSelected();
505 0 : bHasValidRole = (pRoleEntry != 0);
506 : }
507 :
508 0 : m_pBTN_ADD->Enable( true );
509 0 : m_pBTN_REMOVE->Enable( bHasSelectedSeries );
510 :
511 0 : m_pBTN_UP->Enable( bHasSelectedSeries && (pSeriesEntry != m_pLB_SERIES->First()));
512 0 : m_pBTN_DOWN->Enable( bHasSelectedSeries && (pSeriesEntry != m_pLB_SERIES->Last()));
513 :
514 0 : bool bHasCategories = m_rDialogModel.isCategoryDiagram();
515 :
516 0 : m_pFT_DATALABELS->Show(!bHasCategories);
517 0 : m_pFT_CATEGORIES->Show( bHasCategories);
518 0 : bool bShowIB = bHasRangeChooser;
519 :
520 0 : m_pIMB_RANGE_CAT->Show(bShowIB);
521 :
522 0 : m_pFT_SERIES->Enable();
523 0 : m_pLB_SERIES->Enable();
524 :
525 0 : m_pFT_ROLE->Enable( bHasSelectedSeries );
526 0 : m_pLB_ROLE->Enable( bHasSelectedSeries );
527 :
528 0 : m_pFT_RANGE->Enable( bHasValidRole );
529 0 : m_pEDT_RANGE->Enable( bHasValidRole );
530 :
531 0 : m_pIMB_RANGE_MAIN->Show(bShowIB);
532 :
533 0 : isValid();
534 0 : }
535 :
536 0 : IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl)
537 : {
538 0 : m_rDialogModel.startControllerLockTimer();
539 0 : if( m_pLB_SERIES->FirstSelected())
540 : {
541 0 : fillRoleListBox();
542 0 : RoleSelectionChangedHdl( 0 );
543 : }
544 0 : updateControlState();
545 :
546 0 : return 0;
547 : }
548 :
549 0 : IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl)
550 : {
551 0 : m_rDialogModel.startControllerLockTimer();
552 0 : SvTreeListEntry * pEntry = m_pLB_ROLE->FirstSelected();
553 0 : if( pEntry )
554 : {
555 0 : OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_pLB_ROLE, true );
556 0 : OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_pLB_ROLE );
557 :
558 : // replace role in fixed text label
559 0 : const OUString aReplacementStr( "%VALUETYPE" );
560 0 : sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
561 0 : if( nIndex != -1 )
562 : {
563 0 : m_pFT_RANGE->SetText(
564 : m_aFixedTextRange.replaceAt(
565 0 : nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
566 : }
567 :
568 0 : m_pEDT_RANGE->SetText( aSelectedRange );
569 0 : isValid();
570 : }
571 :
572 0 : return 0;
573 : }
574 :
575 0 : IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl)
576 : {
577 : OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
578 0 : m_pCurrentRangeChoosingField = m_pEDT_RANGE;
579 0 : if( !m_pEDT_RANGE->GetText().isEmpty() &&
580 0 : ! updateModelFromControl( m_pCurrentRangeChoosingField ))
581 0 : return 0;
582 :
583 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
584 0 : bool bHasSelectedEntry = (pEntry != 0);
585 :
586 0 : OUString aSelectedRolesRange = lcl_GetSelectedRolesRange( *m_pLB_ROLE );
587 :
588 0 : if( bHasSelectedEntry && (m_pLB_ROLE->FirstSelected() != 0))
589 : {
590 0 : OUString aUIStr(SCH_RESSTR(STR_DATA_SELECT_RANGE_FOR_SERIES));
591 :
592 : // replace role
593 0 : OUString aReplacement( "%VALUETYPE" );
594 0 : sal_Int32 nIndex = aUIStr.indexOf( aReplacement );
595 0 : if( nIndex != -1 )
596 : {
597 0 : aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
598 0 : lcl_GetSelectedRole( *m_pLB_ROLE, true ));
599 : }
600 : // replace series name
601 0 : aReplacement = "%SERIESNAME";
602 0 : nIndex = aUIStr.indexOf( aReplacement );
603 0 : if( nIndex != -1 )
604 : {
605 0 : aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
606 0 : OUString( m_pLB_SERIES->GetEntryText( pEntry )));
607 : }
608 :
609 0 : lcl_enableRangeChoosing( true, m_pParentDialog );
610 0 : m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this );
611 : }
612 : else
613 0 : m_pCurrentRangeChoosingField = 0;
614 :
615 0 : return 0;
616 : }
617 :
618 0 : IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl)
619 : {
620 : OSL_ASSERT( m_pCurrentRangeChoosingField == nullptr );
621 0 : m_pCurrentRangeChoosingField = m_pEDT_CATEGORIES;
622 0 : if( !m_pEDT_CATEGORIES->GetText().isEmpty() &&
623 0 : ! updateModelFromControl( m_pCurrentRangeChoosingField ))
624 0 : return 0;
625 :
626 0 : OUString aStr( SCH_RESSTR( m_pFT_CATEGORIES->IsVisible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS ));
627 0 : lcl_enableRangeChoosing( true, m_pParentDialog );
628 : m_rDialogModel.getRangeSelectionHelper()->chooseRange(
629 0 : m_rDialogModel.getCategoriesRange(), aStr, *this );
630 0 : return 0;
631 : }
632 :
633 0 : IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl)
634 : {
635 0 : m_rDialogModel.startControllerLockTimer();
636 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
637 0 : Reference< XDataSeries > xSeriesToInsertAfter;
638 0 : Reference< XChartType > xChartTypeForNewSeries;
639 0 : if( m_pTemplateProvider )
640 0 : m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
641 :
642 0 : if( pEntry )
643 : {
644 0 : xSeriesToInsertAfter.set( pEntry->m_xDataSeries );
645 0 : xChartTypeForNewSeries.set( pEntry->m_xChartType );
646 : }
647 : else
648 : {
649 : ::std::vector< Reference< XDataSeriesContainer > > aCntVec(
650 0 : m_rDialogModel.getAllDataSeriesContainers());
651 0 : if( ! aCntVec.empty())
652 0 : xChartTypeForNewSeries.set( aCntVec.front(), uno::UNO_QUERY );
653 : }
654 : OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" );
655 :
656 0 : m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries );
657 0 : setDirty();
658 :
659 0 : fillSeriesListBox();
660 : // note the box was cleared and refilled, so pEntry is invalid now
661 0 : SvTreeListEntry * pSelEntry = m_pLB_SERIES->FirstSelected();
662 0 : if( pSelEntry )
663 : {
664 0 : SvTreeListEntry * pNextEntry = m_pLB_SERIES->Next( pSelEntry );
665 0 : if( pNextEntry )
666 0 : m_pLB_SERIES->Select( pNextEntry );
667 : }
668 0 : SeriesSelectionChangedHdl( 0 );
669 :
670 0 : return 0;
671 : }
672 :
673 0 : IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl)
674 : {
675 0 : m_rDialogModel.startControllerLockTimer();
676 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
677 0 : if( pEntry )
678 : {
679 0 : Reference< XDataSeries > xNewSelSeries;
680 0 : SeriesEntry * pNewSelEntry = dynamic_cast< SeriesEntry * >(m_pLB_SERIES->Next( pEntry ));
681 0 : if( pNewSelEntry )
682 0 : xNewSelSeries.set( pNewSelEntry->m_xDataSeries );
683 : else
684 : {
685 0 : pNewSelEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->Prev( pEntry ));
686 0 : if( pNewSelEntry )
687 0 : xNewSelSeries.set( pNewSelEntry->m_xDataSeries );
688 : }
689 :
690 0 : m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType );
691 0 : setDirty();
692 :
693 0 : m_pLB_SERIES->RemoveSelection();
694 0 : fillSeriesListBox();
695 :
696 : // select previous or next series
697 : //@improve: see methods GetModel()->GetAbsPos()/GetEntry() for absolute list positions
698 0 : if( xNewSelSeries.is())
699 : {
700 0 : pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->First());
701 0 : while( pEntry )
702 : {
703 0 : if( pEntry->m_xDataSeries == xNewSelSeries )
704 : {
705 0 : m_pLB_SERIES->Select( pEntry );
706 0 : break;
707 : }
708 0 : pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->Next( pEntry ));
709 : }
710 : }
711 0 : SeriesSelectionChangedHdl( 0 );
712 : }
713 :
714 0 : return 0;
715 : }
716 :
717 0 : IMPL_LINK_NOARG(DataSourceTabPage, UpButtonClickedHdl)
718 : {
719 0 : m_rDialogModel.startControllerLockTimer();
720 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
721 0 : bool bHasSelectedEntry = (pEntry != 0);
722 :
723 0 : if( bHasSelectedEntry )
724 : {
725 0 : m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_UP );
726 0 : setDirty();
727 0 : fillSeriesListBox();
728 0 : SeriesSelectionChangedHdl(0);
729 : }
730 :
731 0 : return 0;
732 : }
733 :
734 0 : IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl)
735 : {
736 0 : m_rDialogModel.startControllerLockTimer();
737 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
738 0 : bool bHasSelectedEntry = (pEntry != 0);
739 :
740 0 : if( bHasSelectedEntry )
741 : {
742 0 : m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_DOWN );
743 0 : setDirty();
744 0 : fillSeriesListBox();
745 0 : SeriesSelectionChangedHdl(0);
746 : }
747 :
748 0 : return 0;
749 : }
750 :
751 0 : IMPL_LINK( DataSourceTabPage, RangeModifiedHdl, Edit*, pEdit )
752 : {
753 : // note: isValid sets the color of the edit field
754 0 : if( isRangeFieldContentValid( *pEdit ))
755 : {
756 0 : setDirty();
757 0 : updateModelFromControl( pEdit );
758 0 : if( pEdit == m_pEDT_RANGE )
759 : {
760 0 : if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
761 0 : fillSeriesListBox();
762 : }
763 : }
764 :
765 : // enable/disable OK button
766 0 : isValid();
767 :
768 0 : return 0;
769 : }
770 :
771 0 : IMPL_LINK( DataSourceTabPage, RangeUpdateDataHdl, Edit*, pEdit )
772 : {
773 : // note: isValid sets the color of the edit field
774 0 : if( isRangeFieldContentValid( *pEdit ))
775 : {
776 0 : setDirty();
777 0 : updateModelFromControl( pEdit );
778 0 : if( pEdit == m_pEDT_RANGE )
779 : {
780 0 : if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
781 0 : fillSeriesListBox();
782 : }
783 : }
784 : // enable/disable OK button
785 0 : isValid();
786 :
787 0 : return 0;
788 : }
789 :
790 0 : void DataSourceTabPage::listeningFinished(
791 : const OUString & rNewRange )
792 : {
793 : // rNewRange becomes invalid after removing the listener
794 0 : OUString aRange( rNewRange );
795 :
796 0 : m_rDialogModel.startControllerLockTimer();
797 :
798 : // stop listening
799 0 : m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
800 :
801 : // change edit field
802 0 : ToTop();
803 0 : GrabFocus();
804 0 : if( m_pCurrentRangeChoosingField )
805 : {
806 0 : m_pCurrentRangeChoosingField->SetText( aRange );
807 0 : m_pCurrentRangeChoosingField->GrabFocus();
808 : }
809 :
810 0 : if( m_pCurrentRangeChoosingField == m_pEDT_RANGE )
811 : {
812 0 : m_pEDT_RANGE->SetText( aRange );
813 0 : setDirty();
814 : }
815 0 : else if( m_pCurrentRangeChoosingField == m_pEDT_CATEGORIES )
816 : {
817 0 : m_pEDT_CATEGORIES->SetText( aRange );
818 0 : setDirty();
819 : }
820 :
821 0 : updateModelFromControl( m_pCurrentRangeChoosingField );
822 0 : if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
823 0 : fillSeriesListBox();
824 :
825 0 : m_pCurrentRangeChoosingField = 0;
826 :
827 0 : updateControlState();
828 0 : lcl_enableRangeChoosing( false, m_pParentDialog );
829 0 : }
830 :
831 0 : void DataSourceTabPage::disposingRangeSelection()
832 : {
833 0 : m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
834 0 : }
835 :
836 0 : bool DataSourceTabPage::updateModelFromControl( Edit * pField )
837 : {
838 0 : if( !m_bIsDirty )
839 0 : return true;
840 :
841 0 : ControllerLockGuardUNO aLockedControllers( m_rDialogModel.getChartModel() );
842 :
843 : // @todo: validity check of field content
844 0 : bool bResult = true;
845 0 : bool bAll = (pField == 0);
846 0 : Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider());
847 :
848 0 : if( bAll || (pField == m_pEDT_CATEGORIES) )
849 : {
850 0 : Reference< data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() );
851 0 : if( xDataProvider.is())
852 : {
853 0 : OUString aRange( m_pEDT_CATEGORIES->GetText());
854 0 : if( !aRange.isEmpty())
855 : {
856 : // create or change categories
857 0 : if( !xLabeledSeq.is())
858 : {
859 0 : xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
860 0 : m_rDialogModel.setCategories( xLabeledSeq );
861 : }
862 : try
863 : {
864 0 : xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
865 : }
866 0 : catch( const uno::Exception & ex )
867 : {
868 : // should work as validation should have happened before
869 : ASSERT_EXCEPTION( ex );
870 : }
871 : }
872 0 : else if( xLabeledSeq.is())
873 : {
874 : // clear existing categories
875 0 : xLabeledSeq.set(0);
876 0 : m_rDialogModel.setCategories( xLabeledSeq );
877 0 : }
878 0 : }
879 : }
880 :
881 0 : SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
882 0 : bool bHasSelectedEntry = (pSeriesEntry != 0);
883 :
884 0 : if( bHasSelectedEntry )
885 : {
886 0 : if( bAll || (pField == m_pEDT_RANGE) )
887 : {
888 : try
889 : {
890 0 : OUString aSelectedRole = lcl_GetSelectedRole( *m_pLB_ROLE );
891 0 : OUString aRange( m_pEDT_RANGE->GetText());
892 0 : OUString aSequenceRole( aSelectedRole );
893 0 : bool bIsLabel = (aSequenceRole == lcl_aLabelRole );
894 0 : OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry ));
895 :
896 0 : if( bIsLabel )
897 0 : aSequenceRole = aSequenceNameForLabel;
898 :
899 0 : Reference< data::XDataSource > xSource( pSeriesEntry->m_xDataSeries, uno::UNO_QUERY_THROW );
900 : Reference< data::XLabeledDataSequence > xLabeledSeq(
901 0 : DataSeriesHelper::getDataSequenceByRole( xSource, aSequenceRole ));
902 :
903 0 : if( xDataProvider.is())
904 : {
905 0 : if( bIsLabel )
906 : {
907 0 : if( ! xLabeledSeq.is())
908 : {
909 : // check if there is already an "orphan" label sequence
910 0 : xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
911 0 : if( ! xLabeledSeq.is())
912 : {
913 : // no corresponding labeled data sequence for label found
914 0 : xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
915 0 : lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
916 : }
917 : }
918 0 : if( xLabeledSeq.is())
919 : {
920 0 : if( !aRange.isEmpty())
921 : {
922 0 : Reference< data::XDataSequence > xNewSeq;
923 : try
924 : {
925 0 : xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
926 : }
927 0 : catch( const uno::Exception & ex )
928 : {
929 : // should work as validation should have happened before
930 : ASSERT_EXCEPTION( ex );
931 : }
932 0 : if( xNewSeq.is())
933 : {
934 : // update range name by the full string provided
935 : // by the data provider. E.g. "a1" might become
936 : // "$Sheet1.$A$1"
937 0 : aRange = xNewSeq->getSourceRangeRepresentation();
938 0 : Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
939 0 : xProp->setPropertyValue( "Role" , uno::makeAny( lcl_aLabelRole ));
940 0 : xLabeledSeq->setLabel( xNewSeq );
941 0 : }
942 : }
943 : else
944 : {
945 0 : xLabeledSeq->setLabel( Reference< data::XDataSequence >());
946 : }
947 : }
948 : }
949 : else
950 : {
951 0 : if( !aRange.isEmpty())
952 : {
953 0 : Reference< data::XDataSequence > xNewSeq;
954 : try
955 : {
956 0 : xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
957 : }
958 0 : catch( const uno::Exception & ex )
959 : {
960 : // should work as validation should have happened before
961 : ASSERT_EXCEPTION( ex );
962 : }
963 0 : if( xNewSeq.is())
964 : {
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 0 : aRange = xNewSeq->getSourceRangeRepresentation();
969 :
970 0 : Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
971 0 : xProp->setPropertyValue( "Role" , uno::makeAny( aSelectedRole ));
972 0 : if( !xLabeledSeq.is())
973 : {
974 0 : if( aSelectedRole == aSequenceNameForLabel )
975 0 : xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
976 0 : if( ! xLabeledSeq.is())
977 : {
978 0 : xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
979 0 : lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
980 : }
981 : }
982 0 : xLabeledSeq->setValues( xNewSeq );
983 0 : }
984 : }
985 : }
986 : }
987 :
988 0 : lcl_UpdateCurrentRange( *m_pLB_ROLE, aSelectedRole, aRange );
989 : }
990 0 : catch( const uno::Exception & ex )
991 : {
992 0 : bResult = false;
993 : ASSERT_EXCEPTION( ex );
994 : }
995 : }
996 : }
997 :
998 : // update View
999 : // @todo remove this when automatic view updates from calc, writer and own data sequences are available
1000 0 : if( bResult )
1001 : {
1002 : try
1003 : {
1004 0 : Reference< util::XModifiable > xModifiable( m_rDialogModel.getChartModel(), uno::UNO_QUERY );
1005 0 : if( xModifiable.is() )
1006 0 : xModifiable->setModified( sal_True );
1007 0 : const DialogModelTimeBasedInfo& rInfo = m_rDialogModel.getTimeBasedInfo();
1008 0 : if(rInfo.bTimeBased)
1009 : {
1010 0 : m_rDialogModel.setTimeBasedRange(rInfo.bTimeBased, rInfo.nStart, rInfo.nEnd);
1011 0 : }
1012 : }
1013 0 : catch( const uno::Exception & ex )
1014 : {
1015 : ASSERT_EXCEPTION( ex );
1016 : }
1017 : }
1018 :
1019 0 : return bResult;
1020 : }
1021 :
1022 57 : } // namespace chart
1023 :
1024 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|