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