1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "tp_RangeChooser.hxx"
21 #include <DataSourceHelper.hxx>
22 #include <ChartTypeTemplateProvider.hxx>
23 #include "DialogModel.hxx"
24 #include <RangeSelectionHelper.hxx>
25 #include <TabPageNotifiable.hxx>
26 #include <com/sun/star/beans/PropertyState.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <svtools/miscopt.hxx>
29 #include <osl/diagnose.h>
33 void lcl_ShowChooserButton(
34 weld::Button
& rChooserButton
,
37 if( rChooserButton
.get_visible() != bShow
)
39 rChooserButton
.set_visible( bShow
);
43 void lcl_enableRangeChoosing(bool bEnable
, weld::DialogController
* pDialog
)
47 weld::Dialog
* pDlg
= pDialog
->getDialog();
48 pDlg
->set_modal(!bEnable
);
49 pDlg
->set_visible(!bEnable
);
52 } // anonymous namespace
56 using namespace ::com::sun::star
;
57 using namespace ::com::sun::star::chart2
;
59 using ::com::sun::star::uno::Sequence
;
61 RangeChooserTabPage::RangeChooserTabPage(weld::Container
* pPage
, weld::DialogController
* pController
, DialogModel
& rDialogModel
,
62 ChartTypeTemplateProvider
* pTemplateProvider
,
63 bool bHideDescription
/* = false */)
64 : OWizardPage(pPage
, pController
, "modules/schart/ui/tp_RangeChooser.ui", "tp_RangeChooser")
65 , m_nChangingControlCalls(0)
67 , m_aLastValidRangeString()
68 , m_pTemplateProvider(pTemplateProvider
)
69 , m_rDialogModel( rDialogModel
)
70 , m_pTabPageNotifiable(dynamic_cast<TabPageNotifiable
*>(pController
))
71 , m_xFT_Caption(m_xBuilder
->weld_label("FT_CAPTION_FOR_WIZARD"))
72 , m_xFT_Range(m_xBuilder
->weld_label("FT_RANGE"))
73 , m_xED_Range(m_xBuilder
->weld_entry("ED_RANGE"))
74 , m_xIB_Range(m_xBuilder
->weld_button("IB_RANGE"))
75 , m_xRB_Rows(m_xBuilder
->weld_radio_button("RB_DATAROWS"))
76 , m_xRB_Columns(m_xBuilder
->weld_radio_button("RB_DATACOLS"))
77 , m_xCB_FirstRowAsLabel(m_xBuilder
->weld_check_button("CB_FIRST_ROW_ASLABELS"))
78 , m_xCB_FirstColumnAsLabel(m_xBuilder
->weld_check_button("CB_FIRST_COLUMN_ASLABELS"))
79 , m_xFTTitle(m_xBuilder
->weld_label("STR_PAGE_DATA_RANGE"))
80 , m_xFL_TimeBased(m_xBuilder
->weld_widget("separator1"))
81 , m_xCB_TimeBased(m_xBuilder
->weld_check_button("CB_TIME_BASED"))
82 , m_xFT_TimeStart(m_xBuilder
->weld_label("label1"))
83 , m_xEd_TimeStart(m_xBuilder
->weld_entry("ED_TIME_BASED_START"))
84 , m_xFT_TimeEnd(m_xBuilder
->weld_label("label2"))
85 , m_xEd_TimeEnd(m_xBuilder
->weld_entry("ED_TIME_BASED_END"))
87 m_xFT_Caption
->set_visible(!bHideDescription
);
89 SetPageTitle(m_xFTTitle
->get_label());// OH:remove later with dialog
91 // set defaults as long as DetectArguments does not work
92 m_xRB_Columns
->set_active(true);
93 m_xCB_FirstColumnAsLabel
->set_active(true);
94 m_xCB_FirstRowAsLabel
->set_active(true);
96 // BM: Note, that the range selection is not available, if there is no view.
97 // This happens for charts having their own embedded spreadsheet. If you
98 // force to get the range selection here, this would mean when entering this
99 // page the calc view would be created in this case. So, I enable the
100 // button here, and in the worst case nothing happens when it is pressed.
101 // Not nice, but I see no better solution for the moment.
102 m_xIB_Range
->connect_clicked( LINK( this, RangeChooserTabPage
, ChooseRangeHdl
));
104 m_xED_Range
->connect_changed( LINK( this, RangeChooserTabPage
, ControlEditedHdl
));
105 m_xRB_Rows
->connect_toggled( LINK( this, RangeChooserTabPage
, ControlChangedRadioHdl
) );
106 m_xCB_FirstRowAsLabel
->connect_toggled( LINK( this, RangeChooserTabPage
, ControlChangedCheckBoxHdl
) );
107 m_xCB_FirstColumnAsLabel
->connect_toggled( LINK( this, RangeChooserTabPage
, ControlChangedCheckBoxHdl
) );
108 m_xCB_TimeBased
->connect_toggled( LINK( this, RangeChooserTabPage
, ControlChangedCheckBoxHdl
) );
109 m_xEd_TimeStart
->connect_changed( LINK( this, RangeChooserTabPage
, ControlChangedHdl
) );
110 m_xEd_TimeEnd
->connect_changed( LINK( this, RangeChooserTabPage
, ControlChangedHdl
) );
112 SvtMiscOptions aOpts
;
113 if ( !aOpts
.IsExperimentalMode() )
115 m_xFL_TimeBased
->hide();
116 m_xCB_TimeBased
->hide();
117 m_xFT_TimeStart
->hide();
118 m_xEd_TimeStart
->hide();
119 m_xFT_TimeEnd
->hide();
120 m_xEd_TimeEnd
->hide();
124 RangeChooserTabPage::~RangeChooserTabPage()
128 void RangeChooserTabPage::Activate()
130 OWizardPage::Activate();
131 initControlsFromModel();
132 m_xED_Range
->grab_focus();
135 void RangeChooserTabPage::initControlsFromModel()
137 m_nChangingControlCalls
++;
139 if(m_pTemplateProvider
)
140 m_xCurrentChartTypeTemplate
= m_pTemplateProvider
->getCurrentTemplate();
142 bool bUseColumns
= !m_xRB_Rows
->get_active();
143 bool bFirstCellAsLabel
= bUseColumns
? m_xCB_FirstRowAsLabel
->get_active() : m_xCB_FirstColumnAsLabel
->get_active();
144 bool bHasCategories
= bUseColumns
? m_xCB_FirstColumnAsLabel
->get_active() : m_xCB_FirstRowAsLabel
->get_active();
146 bool bIsValid
= m_rDialogModel
.allArgumentsForRectRangeDetected();
148 m_rDialogModel
.detectArguments(m_aLastValidRangeString
, bUseColumns
, bFirstCellAsLabel
, bHasCategories
);
150 m_aLastValidRangeString
.clear();
152 m_xED_Range
->set_text( m_aLastValidRangeString
);
154 m_xRB_Rows
->set_active( !bUseColumns
);
155 m_xRB_Columns
->set_active( bUseColumns
);
157 m_xCB_FirstRowAsLabel
->set_active( m_xRB_Rows
->get_active()?bHasCategories
:bFirstCellAsLabel
);
158 m_xCB_FirstColumnAsLabel
->set_active( m_xRB_Columns
->get_active()?bHasCategories
:bFirstCellAsLabel
);
162 m_nChangingControlCalls
--;
165 void RangeChooserTabPage::Deactivate()
168 vcl::OWizardPage::Deactivate();
171 void RangeChooserTabPage::commitPage()
173 commitPage(::vcl::WizardTypes::eFinish
);
176 bool RangeChooserTabPage::commitPage( ::vcl::WizardTypes::CommitPageReason
/*eReason*/ )
178 //ranges may have been edited in the meanwhile (dirty is true in that case here)
181 changeDialogModelAccordingToControls();
182 return true; // return false if this page should not be left
188 void RangeChooserTabPage::changeDialogModelAccordingToControls()
190 if(m_nChangingControlCalls
>0)
193 if( !m_xCurrentChartTypeTemplate
.is() )
195 if(m_pTemplateProvider
)
196 m_xCurrentChartTypeTemplate
.set( m_pTemplateProvider
->getCurrentTemplate());
197 if( !m_xCurrentChartTypeTemplate
.is())
199 OSL_FAIL( "Need a template to change data source" );
206 bool bFirstCellAsLabel
= ( m_xCB_FirstColumnAsLabel
->get_active() && !m_xRB_Columns
->get_active() )
207 || ( m_xCB_FirstRowAsLabel
->get_active() && !m_xRB_Rows
->get_active() );
208 bool bHasCategories
= ( m_xCB_FirstColumnAsLabel
->get_active() && m_xRB_Columns
->get_active() )
209 || ( m_xCB_FirstRowAsLabel
->get_active() && m_xRB_Rows
->get_active() );
210 bool bTimeBased
= m_xCB_TimeBased
->get_active();
212 Sequence
< beans::PropertyValue
> aArguments(
213 DataSourceHelper::createArguments(
214 m_xRB_Columns
->get_active(), bFirstCellAsLabel
, bHasCategories
) );
218 aArguments
.realloc( aArguments
.getLength() + 1 );
219 aArguments
[aArguments
.getLength() - 1] =
220 beans::PropertyValue( "TimeBased", -1, uno::Any(bTimeBased
),
221 beans::PropertyState_DIRECT_VALUE
);
224 // only if range is valid
225 if( m_aLastValidRangeString
== m_xED_Range
->get_text())
227 m_rDialogModel
.setTemplate( m_xCurrentChartTypeTemplate
);
228 aArguments
.realloc( aArguments
.getLength() + 1 );
229 aArguments
[aArguments
.getLength() - 1] =
230 beans::PropertyValue( "CellRangeRepresentation" , -1,
231 uno::Any( m_aLastValidRangeString
),
232 beans::PropertyState_DIRECT_VALUE
);
233 m_rDialogModel
.setData( aArguments
);
238 sal_Int32 nStart
= m_xEd_TimeStart
->get_text().toInt32();
239 sal_Int32 nEnd
= m_xEd_TimeEnd
->get_text().toInt32();
240 m_rDialogModel
.setTimeBasedRange(true, nStart
, nEnd
);
244 //@todo warn user that the selected range is not valid
245 //@todo better: disable OK-Button if range is invalid
249 bool RangeChooserTabPage::isValid()
251 OUString
aRange( m_xED_Range
->get_text());
252 bool bFirstCellAsLabel
= ( m_xCB_FirstColumnAsLabel
->get_active() && !m_xRB_Columns
->get_active() )
253 || ( m_xCB_FirstRowAsLabel
->get_active() && !m_xRB_Rows
->get_active() );
254 bool bHasCategories
= ( m_xCB_FirstColumnAsLabel
->get_active() && m_xRB_Columns
->get_active() )
255 || ( m_xCB_FirstRowAsLabel
->get_active() && m_xRB_Rows
->get_active() );
256 bool bIsValid
= ( aRange
.isEmpty() ) ||
257 m_rDialogModel
.getRangeSelectionHelper()->verifyArguments(
258 DataSourceHelper::createArguments(
259 aRange
, Sequence
< sal_Int32
>(), m_xRB_Columns
->get_active(), bFirstCellAsLabel
, bHasCategories
));
263 m_xED_Range
->set_message_type(weld::EntryMessageType::Normal
);
264 if( m_pTabPageNotifiable
)
265 m_pTabPageNotifiable
->setValidPage( this );
266 m_aLastValidRangeString
= aRange
;
270 m_xED_Range
->set_message_type(weld::EntryMessageType::Error
);
271 if( m_pTabPageNotifiable
)
272 m_pTabPageNotifiable
->setInvalidPage( this );
275 // enable/disable controls
276 // #i79531# if the range is valid but an action of one of these buttons
277 // would render it invalid, the button should be disabled
280 bool bDataInColumns
= m_xRB_Columns
->get_active();
281 bool bIsSwappedRangeValid
= m_rDialogModel
.getRangeSelectionHelper()->verifyArguments(
282 DataSourceHelper::createArguments(
283 aRange
, Sequence
< sal_Int32
>(), ! bDataInColumns
, bHasCategories
, bFirstCellAsLabel
));
284 m_xRB_Rows
->set_sensitive( bIsSwappedRangeValid
);
285 m_xRB_Columns
->set_sensitive( bIsSwappedRangeValid
);
287 m_xCB_FirstRowAsLabel
->set_sensitive(
288 m_rDialogModel
.getRangeSelectionHelper()->verifyArguments(
289 DataSourceHelper::createArguments(
290 aRange
, Sequence
< sal_Int32
>(), m_xRB_Columns
->get_active(),
291 bDataInColumns
? ! bFirstCellAsLabel
: bFirstCellAsLabel
,
292 bDataInColumns
? bHasCategories
: ! bHasCategories
)));
293 m_xCB_FirstColumnAsLabel
->set_sensitive(
294 m_rDialogModel
.getRangeSelectionHelper()->verifyArguments(
295 DataSourceHelper::createArguments(
296 aRange
, Sequence
< sal_Int32
>(), m_xRB_Columns
->get_active(),
297 bDataInColumns
? bFirstCellAsLabel
: ! bFirstCellAsLabel
,
298 bDataInColumns
? ! bHasCategories
: bHasCategories
)));
302 m_xRB_Rows
->set_sensitive( bIsValid
);
303 m_xRB_Columns
->set_sensitive( bIsValid
);
304 m_xCB_FirstRowAsLabel
->set_sensitive( bIsValid
);
305 m_xCB_FirstColumnAsLabel
->set_sensitive( bIsValid
);
308 bool bShowIB
= m_rDialogModel
.getRangeSelectionHelper()->hasRangeSelection();
309 lcl_ShowChooserButton( *m_xIB_Range
, bShowIB
);
314 IMPL_LINK_NOARG(RangeChooserTabPage
, ControlEditedHdl
, weld::Entry
&, void)
320 IMPL_LINK_NOARG(RangeChooserTabPage
, ControlChangedRadioHdl
, weld::ToggleButton
&, void)
322 ControlChangedHdl(*m_xED_Range
);
325 IMPL_LINK_NOARG(RangeChooserTabPage
, ControlChangedCheckBoxHdl
, weld::ToggleButton
&, void)
327 ControlChangedHdl(*m_xED_Range
);
330 IMPL_LINK_NOARG(RangeChooserTabPage
, ControlChangedHdl
, weld::Entry
&, void)
334 changeDialogModelAccordingToControls();
337 IMPL_LINK_NOARG(RangeChooserTabPage
, ChooseRangeHdl
, weld::Button
&, void)
339 OUString aRange
= m_xED_Range
->get_text();
340 OUString aTitle
= m_xFTTitle
->get_label();
342 lcl_enableRangeChoosing(true, m_pDialogController
);
343 m_rDialogModel
.getRangeSelectionHelper()->chooseRange( aRange
, aTitle
, *this );
346 void RangeChooserTabPage::listeningFinished( const OUString
& rNewRange
)
348 //user has selected a new range
350 // rNewRange becomes invalid after removing the listener
351 OUString
aRange( rNewRange
);
353 m_rDialogModel
.startControllerLockTimer();
356 m_rDialogModel
.getRangeSelectionHelper()->stopRangeListening();
358 //update dialog state
359 m_xED_Range
->set_text(aRange
);
360 m_xED_Range
->grab_focus();
364 changeDialogModelAccordingToControls();
366 lcl_enableRangeChoosing(false, m_pDialogController
);
369 void RangeChooserTabPage::disposingRangeSelection()
371 m_rDialogModel
.getRangeSelectionHelper()->stopRangeListening( false );
374 void RangeChooserTabPage::setDirty()
376 if( m_nChangingControlCalls
== 0 )
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */