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 34 : 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( rRoleListBox.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( rRoleListBox.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 ? sal_False : sal_True );
140 0 : pDialog->SetModalInputMode( bEnable ? sal_False : sal_True );
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 0 : {}
278 :
279 0 : void DataSourceTabPage::ActivatePage()
280 : {
281 0 : OWizardPage::ActivatePage();
282 0 : updateControlsFromDialogModel();
283 0 : }
284 :
285 0 : void DataSourceTabPage::initializePage()
286 : {
287 0 : }
288 :
289 0 : void DataSourceTabPage::DeactivatePage()
290 : {
291 0 : commitPage();
292 0 : svt::OWizardPage::DeactivatePage();
293 0 : }
294 :
295 0 : void DataSourceTabPage::commitPage()
296 : {
297 0 : commitPage(::svt::WizardTypes::eFinish);
298 0 : }
299 :
300 0 : bool DataSourceTabPage::commitPage( ::svt::WizardTypes::CommitPageReason /*eReason*/ )
301 : {
302 : //ranges may have been edited in the meanwhile (dirty is true in that case here)
303 0 : if( isValid() )
304 : {
305 0 : updateModelFromControl( 0 /*update all*/ );
306 0 : return true; //return false if this page should not be left
307 : }
308 : else
309 0 : return false;
310 : }
311 :
312 0 : bool DataSourceTabPage::isRangeFieldContentValid( Edit & rEdit )
313 : {
314 0 : OUString aRange( rEdit.GetText());
315 0 : bool bIsValid = ( aRange.isEmpty() ) ||
316 0 : m_rDialogModel.getRangeSelectionHelper()->verifyCellRange( aRange );
317 :
318 0 : if( bIsValid )
319 : {
320 0 : rEdit.SetControlForeground();
321 0 : rEdit.SetControlBackground();
322 : }
323 : else
324 : {
325 0 : rEdit.SetControlBackground( RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR );
326 0 : rEdit.SetControlForeground( RANGE_SELECTION_INVALID_RANGE_FOREGROUND_COLOR );
327 : }
328 :
329 0 : return bIsValid;
330 : }
331 :
332 0 : bool DataSourceTabPage::isValid()
333 : {
334 0 : bool bRoleRangeValid = true;
335 0 : bool bCategoriesRangeValid = true;
336 0 : bool bHasSelectedEntry = (m_pLB_SERIES->FirstSelected() != 0);
337 :
338 0 : if( bHasSelectedEntry )
339 0 : bRoleRangeValid = isRangeFieldContentValid( *m_pEDT_RANGE );
340 0 : if( m_pEDT_CATEGORIES->IsEnabled() )
341 0 : bCategoriesRangeValid = isRangeFieldContentValid( *m_pEDT_CATEGORIES );
342 0 : bool bValid = ( bRoleRangeValid && bCategoriesRangeValid );
343 :
344 0 : if( m_pTabPageNotifiable )
345 : {
346 0 : if( bValid )
347 0 : m_pTabPageNotifiable->setValidPage( this );
348 : else
349 0 : m_pTabPageNotifiable->setInvalidPage( this );
350 : }
351 :
352 0 : return bValid;
353 : }
354 :
355 0 : void DataSourceTabPage::setDirty()
356 : {
357 0 : m_bIsDirty = true;
358 0 : }
359 :
360 0 : void DataSourceTabPage::updateControlsFromDialogModel()
361 : {
362 : // series
363 0 : fillSeriesListBox();
364 0 : SeriesSelectionChangedHdl( 0 );
365 :
366 : // categories
367 0 : m_pEDT_CATEGORIES->SetText( m_rDialogModel.getCategoriesRange() );
368 :
369 0 : updateControlState();
370 0 : }
371 :
372 0 : void DataSourceTabPage::fillSeriesListBox()
373 : {
374 0 : m_pLB_SERIES->SetUpdateMode( false );
375 :
376 0 : Reference< XDataSeries > xSelected;
377 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
378 0 : if( pEntry )
379 0 : xSelected.set( pEntry->m_xDataSeries );
380 :
381 0 : bool bHasSelectedEntry = (pEntry != 0);
382 0 : SvTreeListEntry * pSelectedEntry = 0;
383 0 : m_pLB_SERIES->Clear();
384 :
385 : ::std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries(
386 0 : m_rDialogModel.getAllDataSeriesWithLabel() );
387 :
388 0 : sal_Int32 nUnnamedSeriesIndex = 1;
389 0 : for( ::std::vector< DialogModel::tSeriesWithChartTypeByName >::const_iterator aIt = aSeries.begin();
390 0 : aIt != aSeries.end(); ++aIt )
391 : {
392 0 : OUString aLabel( (*aIt).first );
393 0 : if( aLabel.isEmpty())
394 : {
395 0 : if( nUnnamedSeriesIndex > 1 )
396 : {
397 0 : OUString aResString(::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ).toString());
398 :
399 : // replace index of unnamed series
400 0 : const OUString aReplacementStr( "%NUMBER" );
401 0 : sal_Int32 nIndex = aResString.indexOf( aReplacementStr );
402 0 : if( nIndex != -1 )
403 0 : aLabel = OUString( aResString.replaceAt(
404 : nIndex, aReplacementStr.getLength(),
405 0 : OUString::number(nUnnamedSeriesIndex)));
406 : }
407 0 : if( aLabel.isEmpty() )
408 0 : aLabel = ::chart::SchResId( STR_DATA_UNNAMED_SERIES ).toString();
409 :
410 0 : ++nUnnamedSeriesIndex;
411 : }
412 : pEntry = dynamic_cast< SeriesEntry * >(
413 0 : m_pLB_SERIES->InsertEntry( aLabel ));
414 0 : if( pEntry )
415 : {
416 0 : pEntry->m_xDataSeries.set( (*aIt).second.first );
417 0 : pEntry->m_xChartType.set( (*aIt).second.second );
418 0 : if( bHasSelectedEntry && ((*aIt).second.first == xSelected))
419 0 : pSelectedEntry = pEntry;
420 : }
421 0 : }
422 :
423 0 : if( bHasSelectedEntry && pSelectedEntry )
424 0 : m_pLB_SERIES->Select( pSelectedEntry );
425 :
426 0 : m_pLB_SERIES->SetUpdateMode( true );
427 0 : }
428 :
429 0 : void DataSourceTabPage::fillRoleListBox()
430 : {
431 0 : SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
432 0 : bool bHasSelectedEntry = (pSeriesEntry != 0);
433 :
434 0 : SvTreeListEntry * pRoleEntry = m_pLB_ROLE->FirstSelected();
435 0 : sal_uLong nRoleIndex = SAL_MAX_UINT32;
436 0 : if( pRoleEntry )
437 0 : nRoleIndex = m_pLB_ROLE->GetModel()->GetAbsPos( pRoleEntry );
438 :
439 0 : if( bHasSelectedEntry )
440 : {
441 : DialogModel::tRolesWithRanges aRoles(
442 : m_rDialogModel.getRolesWithRanges(
443 : pSeriesEntry->m_xDataSeries,
444 : lcl_GetSequenceNameForLabel( pSeriesEntry ),
445 0 : pSeriesEntry->m_xChartType ));
446 :
447 : // fill role list
448 0 : m_pLB_ROLE->SetUpdateMode( false );
449 0 : m_pLB_ROLE->Clear();
450 0 : m_pLB_ROLE->RemoveSelection();
451 :
452 0 : for( DialogModel::tRolesWithRanges::const_iterator aIt( aRoles.begin());
453 0 : aIt != aRoles.end(); ++ aIt )
454 : {
455 0 : m_pLB_ROLE->InsertEntry( lcl_GetRoleLBEntry( aIt->first, aIt->second ));
456 : }
457 :
458 : // series may contain no roles, check listbox size before selecting entries
459 0 : if( m_pLB_ROLE->GetEntryCount() > 0 )
460 : {
461 0 : if( nRoleIndex >= m_pLB_ROLE->GetEntryCount())
462 0 : nRoleIndex = 0;
463 0 : m_pLB_ROLE->Select( m_pLB_ROLE->GetEntry( nRoleIndex ));
464 : }
465 :
466 0 : m_pLB_ROLE->SetUpdateMode( true );
467 : }
468 0 : }
469 :
470 0 : void DataSourceTabPage::updateControlState()
471 : {
472 0 : SvTreeListEntry * pSeriesEntry = m_pLB_SERIES->FirstSelected();
473 0 : bool bHasSelectedSeries = (pSeriesEntry != 0);
474 0 : bool bHasValidRole = false;
475 0 : bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
476 :
477 0 : if( bHasSelectedSeries )
478 : {
479 0 : SvTreeListEntry * pRoleEntry = m_pLB_ROLE->FirstSelected();
480 0 : bHasValidRole = (pRoleEntry != 0);
481 : }
482 :
483 0 : m_pBTN_ADD->Enable( true );
484 0 : m_pBTN_REMOVE->Enable( bHasSelectedSeries );
485 :
486 0 : m_pBTN_UP->Enable( bHasSelectedSeries && (pSeriesEntry != m_pLB_SERIES->First()));
487 0 : m_pBTN_DOWN->Enable( bHasSelectedSeries && (pSeriesEntry != m_pLB_SERIES->Last()));
488 :
489 0 : bool bHasCategories = m_rDialogModel.isCategoryDiagram();
490 :
491 0 : m_pFT_DATALABELS->Show(!bHasCategories);
492 0 : m_pFT_CATEGORIES->Show( bHasCategories);
493 0 : bool bShowIB = bHasRangeChooser;
494 :
495 0 : m_pIMB_RANGE_CAT->Show(bShowIB);
496 :
497 0 : m_pFT_SERIES->Enable();
498 0 : m_pLB_SERIES->Enable();
499 :
500 0 : m_pFT_ROLE->Enable( bHasSelectedSeries );
501 0 : m_pLB_ROLE->Enable( bHasSelectedSeries );
502 :
503 0 : m_pFT_RANGE->Enable( bHasValidRole );
504 0 : m_pEDT_RANGE->Enable( bHasValidRole );
505 :
506 0 : m_pIMB_RANGE_MAIN->Show(bShowIB);
507 :
508 0 : isValid();
509 0 : }
510 :
511 0 : IMPL_LINK_NOARG(DataSourceTabPage, SeriesSelectionChangedHdl)
512 : {
513 0 : m_rDialogModel.startControllerLockTimer();
514 0 : if( m_pLB_SERIES->FirstSelected())
515 : {
516 0 : fillRoleListBox();
517 0 : RoleSelectionChangedHdl( 0 );
518 : }
519 0 : updateControlState();
520 :
521 0 : return 0;
522 : }
523 :
524 0 : IMPL_LINK_NOARG(DataSourceTabPage, RoleSelectionChangedHdl)
525 : {
526 0 : m_rDialogModel.startControllerLockTimer();
527 0 : SvTreeListEntry * pEntry = m_pLB_ROLE->FirstSelected();
528 0 : if( pEntry )
529 : {
530 0 : OUString aSelectedRoleUI = lcl_GetSelectedRole( *m_pLB_ROLE, true );
531 0 : OUString aSelectedRange = lcl_GetSelectedRolesRange( *m_pLB_ROLE );
532 :
533 : // replace role in fixed text label
534 0 : const OUString aReplacementStr( "%VALUETYPE" );
535 0 : sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr );
536 0 : if( nIndex != -1 )
537 : {
538 : m_pFT_RANGE->SetText(
539 : m_aFixedTextRange.replaceAt(
540 0 : nIndex, aReplacementStr.getLength(), aSelectedRoleUI ));
541 : }
542 :
543 0 : m_pEDT_RANGE->SetText( aSelectedRange );
544 0 : isValid();
545 : }
546 :
547 0 : return 0;
548 : }
549 :
550 0 : IMPL_LINK_NOARG(DataSourceTabPage, MainRangeButtonClickedHdl)
551 : {
552 : OSL_ASSERT( m_pCurrentRangeChoosingField == 0 );
553 0 : m_pCurrentRangeChoosingField = m_pEDT_RANGE;
554 0 : if( !m_pEDT_RANGE->GetText().isEmpty() &&
555 0 : ! updateModelFromControl( m_pCurrentRangeChoosingField ))
556 0 : return 0;
557 :
558 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
559 0 : bool bHasSelectedEntry = (pEntry != 0);
560 :
561 0 : OUString aSelectedRolesRange = lcl_GetSelectedRolesRange( *m_pLB_ROLE );
562 :
563 0 : if( bHasSelectedEntry && (m_pLB_ROLE->FirstSelected() != 0))
564 : {
565 0 : OUString aUIStr(SCH_RESSTR(STR_DATA_SELECT_RANGE_FOR_SERIES));
566 :
567 : // replace role
568 0 : OUString aReplacement( "%VALUETYPE" );
569 0 : sal_Int32 nIndex = aUIStr.indexOf( aReplacement );
570 0 : if( nIndex != -1 )
571 : {
572 0 : aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
573 0 : lcl_GetSelectedRole( *m_pLB_ROLE, true ));
574 : }
575 : // replace series name
576 0 : aReplacement = "%SERIESNAME";
577 0 : nIndex = aUIStr.indexOf( aReplacement );
578 0 : if( nIndex != -1 )
579 : {
580 0 : aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(),
581 0 : OUString( m_pLB_SERIES->GetEntryText( pEntry )));
582 : }
583 :
584 0 : lcl_enableRangeChoosing( true, m_pParentDialog );
585 0 : m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this );
586 : }
587 : else
588 0 : m_pCurrentRangeChoosingField = 0;
589 :
590 0 : return 0;
591 : }
592 :
593 0 : IMPL_LINK_NOARG(DataSourceTabPage, CategoriesRangeButtonClickedHdl)
594 : {
595 : OSL_ASSERT( m_pCurrentRangeChoosingField == 0 );
596 0 : m_pCurrentRangeChoosingField = m_pEDT_CATEGORIES;
597 0 : if( !m_pEDT_CATEGORIES->GetText().isEmpty() &&
598 0 : ! updateModelFromControl( m_pCurrentRangeChoosingField ))
599 0 : return 0;
600 :
601 0 : OUString aStr( SCH_RESSTR( m_pFT_CATEGORIES->IsVisible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS ));
602 0 : lcl_enableRangeChoosing( true, m_pParentDialog );
603 : m_rDialogModel.getRangeSelectionHelper()->chooseRange(
604 0 : m_rDialogModel.getCategoriesRange(), aStr, *this );
605 0 : return 0;
606 : }
607 :
608 0 : IMPL_LINK_NOARG(DataSourceTabPage, AddButtonClickedHdl)
609 : {
610 0 : m_rDialogModel.startControllerLockTimer();
611 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
612 0 : Reference< XDataSeries > xSeriesToInsertAfter;
613 0 : Reference< XChartType > xChartTypeForNewSeries;
614 0 : if( m_pTemplateProvider )
615 0 : m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate());
616 :
617 0 : if( pEntry )
618 : {
619 0 : xSeriesToInsertAfter.set( pEntry->m_xDataSeries );
620 0 : xChartTypeForNewSeries.set( pEntry->m_xChartType );
621 : }
622 : else
623 : {
624 : ::std::vector< Reference< XDataSeriesContainer > > aCntVec(
625 0 : m_rDialogModel.getAllDataSeriesContainers());
626 0 : if( ! aCntVec.empty())
627 0 : xChartTypeForNewSeries.set( aCntVec.front(), uno::UNO_QUERY );
628 : }
629 : OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" );
630 :
631 0 : m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries );
632 0 : setDirty();
633 :
634 0 : fillSeriesListBox();
635 : // note the box was cleared and refilled, so pEntry is invalid now
636 0 : SvTreeListEntry * pSelEntry = m_pLB_SERIES->FirstSelected();
637 0 : if( pSelEntry )
638 : {
639 0 : SvTreeListEntry * pNextEntry = m_pLB_SERIES->Next( pSelEntry );
640 0 : if( pNextEntry )
641 0 : m_pLB_SERIES->Select( pNextEntry );
642 : }
643 0 : SeriesSelectionChangedHdl( 0 );
644 :
645 0 : return 0;
646 : }
647 :
648 0 : IMPL_LINK_NOARG(DataSourceTabPage, RemoveButtonClickedHdl)
649 : {
650 0 : m_rDialogModel.startControllerLockTimer();
651 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
652 0 : if( pEntry )
653 : {
654 0 : Reference< XDataSeries > xNewSelSeries;
655 0 : SeriesEntry * pNewSelEntry = dynamic_cast< SeriesEntry * >(m_pLB_SERIES->Next( pEntry ));
656 0 : if( pNewSelEntry )
657 0 : xNewSelSeries.set( pNewSelEntry->m_xDataSeries );
658 : else
659 : {
660 0 : pNewSelEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->Prev( pEntry ));
661 0 : if( pNewSelEntry )
662 0 : xNewSelSeries.set( pNewSelEntry->m_xDataSeries );
663 : }
664 :
665 0 : m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType );
666 0 : setDirty();
667 :
668 0 : m_pLB_SERIES->RemoveSelection();
669 0 : fillSeriesListBox();
670 :
671 : // select previous or next series
672 : //@improve: see methods GetModel()->GetAbsPos()/GetEntry() for absolute list positions
673 0 : if( xNewSelSeries.is())
674 : {
675 0 : pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->First());
676 0 : while( pEntry )
677 : {
678 0 : if( pEntry->m_xDataSeries == xNewSelSeries )
679 : {
680 0 : m_pLB_SERIES->Select( pEntry );
681 0 : break;
682 : }
683 0 : pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->Next( pEntry ));
684 : }
685 : }
686 0 : SeriesSelectionChangedHdl( 0 );
687 : }
688 :
689 0 : return 0;
690 : }
691 :
692 0 : IMPL_LINK_NOARG(DataSourceTabPage, UpButtonClickedHdl)
693 : {
694 0 : m_rDialogModel.startControllerLockTimer();
695 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
696 0 : bool bHasSelectedEntry = (pEntry != 0);
697 :
698 0 : if( bHasSelectedEntry )
699 : {
700 0 : m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_UP );
701 0 : setDirty();
702 0 : fillSeriesListBox();
703 0 : SeriesSelectionChangedHdl(0);
704 : }
705 :
706 0 : return 0;
707 : }
708 :
709 0 : IMPL_LINK_NOARG(DataSourceTabPage, DownButtonClickedHdl)
710 : {
711 0 : m_rDialogModel.startControllerLockTimer();
712 0 : SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
713 0 : bool bHasSelectedEntry = (pEntry != 0);
714 :
715 0 : if( bHasSelectedEntry )
716 : {
717 0 : m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_DOWN );
718 0 : setDirty();
719 0 : fillSeriesListBox();
720 0 : SeriesSelectionChangedHdl(0);
721 : }
722 :
723 0 : return 0;
724 : }
725 :
726 0 : IMPL_LINK( DataSourceTabPage, RangeModifiedHdl, Edit*, pEdit )
727 : {
728 : // note: isValid sets the color of the edit field
729 0 : if( isRangeFieldContentValid( *pEdit ))
730 : {
731 0 : setDirty();
732 0 : updateModelFromControl( pEdit );
733 0 : if( pEdit == m_pEDT_RANGE )
734 : {
735 0 : if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
736 0 : fillSeriesListBox();
737 : }
738 : }
739 :
740 : // enable/disable OK button
741 0 : isValid();
742 :
743 0 : return 0;
744 : }
745 :
746 0 : IMPL_LINK( DataSourceTabPage, RangeUpdateDataHdl, Edit*, pEdit )
747 : {
748 : // note: isValid sets the color of the edit field
749 0 : if( isRangeFieldContentValid( *pEdit ))
750 : {
751 0 : setDirty();
752 0 : updateModelFromControl( pEdit );
753 0 : if( pEdit == m_pEDT_RANGE )
754 : {
755 0 : if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
756 0 : fillSeriesListBox();
757 : }
758 : }
759 : // enable/disable OK button
760 0 : isValid();
761 :
762 0 : return 0;
763 : }
764 :
765 0 : void DataSourceTabPage::listeningFinished(
766 : const OUString & rNewRange )
767 : {
768 : // rNewRange becomes invalid after removing the listener
769 0 : OUString aRange( rNewRange );
770 :
771 0 : m_rDialogModel.startControllerLockTimer();
772 :
773 : // stop listening
774 0 : m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
775 :
776 : // change edit field
777 0 : ToTop();
778 0 : GrabFocus();
779 0 : if( m_pCurrentRangeChoosingField )
780 : {
781 0 : m_pCurrentRangeChoosingField->SetText( aRange );
782 0 : m_pCurrentRangeChoosingField->GrabFocus();
783 : }
784 :
785 0 : if( m_pCurrentRangeChoosingField == m_pEDT_RANGE )
786 : {
787 0 : m_pEDT_RANGE->SetText( aRange );
788 0 : setDirty();
789 : }
790 0 : else if( m_pCurrentRangeChoosingField == m_pEDT_CATEGORIES )
791 : {
792 0 : m_pEDT_CATEGORIES->SetText( aRange );
793 0 : setDirty();
794 : }
795 :
796 0 : updateModelFromControl( m_pCurrentRangeChoosingField );
797 0 : if( ! lcl_UpdateCurrentSeriesName( *m_pLB_SERIES ))
798 0 : fillSeriesListBox();
799 :
800 0 : m_pCurrentRangeChoosingField = 0;
801 :
802 0 : updateControlState();
803 0 : lcl_enableRangeChoosing( false, m_pParentDialog );
804 0 : }
805 :
806 0 : void DataSourceTabPage::disposingRangeSelection()
807 : {
808 0 : m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
809 0 : }
810 :
811 0 : bool DataSourceTabPage::updateModelFromControl( Edit * pField )
812 : {
813 0 : if( !m_bIsDirty )
814 0 : return true;
815 :
816 0 : ControllerLockGuardUNO aLockedControllers( m_rDialogModel.getChartModel() );
817 :
818 : // @todo: validity check of field content
819 0 : bool bResult = true;
820 0 : bool bAll = (pField == 0);
821 0 : Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider());
822 :
823 0 : if( bAll || (pField == m_pEDT_CATEGORIES) )
824 : {
825 0 : Reference< data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() );
826 0 : if( xDataProvider.is())
827 : {
828 0 : OUString aRange( m_pEDT_CATEGORIES->GetText());
829 0 : if( !aRange.isEmpty())
830 : {
831 : // create or change categories
832 0 : if( !xLabeledSeq.is())
833 : {
834 0 : xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
835 0 : m_rDialogModel.setCategories( xLabeledSeq );
836 : }
837 : try
838 : {
839 0 : xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
840 : }
841 0 : catch( const uno::Exception & ex )
842 : {
843 : // should work as validation should have happened before
844 : ASSERT_EXCEPTION( ex );
845 : }
846 : }
847 0 : else if( xLabeledSeq.is())
848 : {
849 : // clear existing categories
850 0 : xLabeledSeq.set(0);
851 0 : m_rDialogModel.setCategories( xLabeledSeq );
852 0 : }
853 0 : }
854 : }
855 :
856 0 : SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_pLB_SERIES->FirstSelected());
857 0 : bool bHasSelectedEntry = (pSeriesEntry != 0);
858 :
859 0 : if( bHasSelectedEntry )
860 : {
861 0 : if( bAll || (pField == m_pEDT_RANGE) )
862 : {
863 : try
864 : {
865 0 : OUString aSelectedRole = lcl_GetSelectedRole( *m_pLB_ROLE );
866 0 : OUString aRange( m_pEDT_RANGE->GetText());
867 0 : OUString aSequenceRole( aSelectedRole );
868 0 : bool bIsLabel = (aSequenceRole == lcl_aLabelRole );
869 0 : OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry ));
870 :
871 0 : if( bIsLabel )
872 0 : aSequenceRole = aSequenceNameForLabel;
873 :
874 0 : Reference< data::XDataSource > xSource( pSeriesEntry->m_xDataSeries, uno::UNO_QUERY_THROW );
875 : Reference< data::XLabeledDataSequence > xLabeledSeq(
876 0 : DataSeriesHelper::getDataSequenceByRole( xSource, aSequenceRole ));
877 :
878 0 : if( xDataProvider.is())
879 : {
880 0 : if( bIsLabel )
881 : {
882 0 : if( ! xLabeledSeq.is())
883 : {
884 : // check if there is already an "orphan" label sequence
885 0 : xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
886 0 : if( ! xLabeledSeq.is())
887 : {
888 : // no corresponding labeled data sequence for label found
889 0 : xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
890 0 : lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
891 : }
892 : }
893 0 : if( xLabeledSeq.is())
894 : {
895 0 : if( !aRange.isEmpty())
896 : {
897 0 : Reference< data::XDataSequence > xNewSeq;
898 : try
899 : {
900 0 : xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
901 : }
902 0 : catch( const uno::Exception & ex )
903 : {
904 : // should work as validation should have happened before
905 : ASSERT_EXCEPTION( ex );
906 : }
907 0 : if( xNewSeq.is())
908 : {
909 : // update range name by the full string provided
910 : // by the data provider. E.g. "a1" might become
911 : // "$Sheet1.$A$1"
912 0 : aRange = xNewSeq->getSourceRangeRepresentation();
913 0 : Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
914 0 : xProp->setPropertyValue( "Role" , uno::makeAny( lcl_aLabelRole ));
915 0 : xLabeledSeq->setLabel( xNewSeq );
916 0 : }
917 : }
918 : else
919 : {
920 0 : xLabeledSeq->setLabel( Reference< data::XDataSequence >());
921 : }
922 : }
923 : }
924 : else
925 : {
926 0 : if( !aRange.isEmpty())
927 : {
928 0 : Reference< data::XDataSequence > xNewSeq;
929 : try
930 : {
931 0 : xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange ));
932 : }
933 0 : catch( const uno::Exception & ex )
934 : {
935 : // should work as validation should have happened before
936 : ASSERT_EXCEPTION( ex );
937 : }
938 0 : if( xNewSeq.is())
939 : {
940 : // update range name by the full string provided
941 : // by the data provider. E.g. "a1:e1" might become
942 : // "$Sheet1.$A$1:$E$1"
943 0 : aRange = xNewSeq->getSourceRangeRepresentation();
944 :
945 0 : Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW );
946 0 : xProp->setPropertyValue( "Role" , uno::makeAny( aSelectedRole ));
947 0 : if( !xLabeledSeq.is())
948 : {
949 0 : if( aSelectedRole == aSequenceNameForLabel )
950 0 : xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource ));
951 0 : if( ! xLabeledSeq.is())
952 : {
953 0 : xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0)));
954 0 : lcl_addLSequenceToDataSource( xLabeledSeq, xSource );
955 : }
956 : }
957 0 : xLabeledSeq->setValues( xNewSeq );
958 0 : }
959 : }
960 : }
961 : }
962 :
963 0 : lcl_UpdateCurrentRange( *m_pLB_ROLE, aSelectedRole, aRange );
964 : }
965 0 : catch( const uno::Exception & ex )
966 : {
967 0 : bResult = false;
968 : ASSERT_EXCEPTION( ex );
969 : }
970 : }
971 : }
972 :
973 : // update View
974 : // @todo remove this when automatic view updates from calc, writer and own data sequences are available
975 0 : if( bResult )
976 : {
977 : try
978 : {
979 0 : Reference< util::XModifiable > xModifiable( m_rDialogModel.getChartModel(), uno::UNO_QUERY );
980 0 : if( xModifiable.is() )
981 0 : xModifiable->setModified( sal_True );
982 0 : const DialogModelTimeBasedInfo& rInfo = m_rDialogModel.getTimeBasedInfo();
983 0 : if(rInfo.bTimeBased)
984 : {
985 0 : m_rDialogModel.setTimeBasedRange(rInfo.bTimeBased, rInfo.nStart, rInfo.nEnd);
986 0 : }
987 : }
988 0 : catch( const uno::Exception & ex )
989 : {
990 : ASSERT_EXCEPTION( ex );
991 : }
992 : }
993 :
994 0 : return bResult;
995 : }
996 :
997 102 : } // namespace chart
998 :
999 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|