LibreOffice Module chart2 (master) 1
tp_RangeChooser.cxx
Go to the documentation of this file.
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_RangeChooser.hxx"
21#include <DataSourceHelper.hxx>
23#include <ChartTypeTemplate.hxx>
24#include "DialogModel.hxx"
26#include <TabPageNotifiable.hxx>
27#include <com/sun/star/beans/PropertyState.hpp>
28#include <com/sun/star/beans/PropertyValue.hpp>
29#include <officecfg/Office/Common.hxx>
30#include <osl/diagnose.h>
31
32namespace
33{
34 void lcl_ShowChooserButton(
35 weld::Button& rChooserButton,
36 bool bShow)
37 {
38 if( rChooserButton.get_visible() != bShow )
39 {
40 rChooserButton.set_visible( bShow );
41 }
42 }
43
44 void lcl_enableRangeChoosing(bool bEnable, weld::DialogController* pDialog)
45 {
46 if (!pDialog)
47 return;
48 weld::Dialog* pDlg = pDialog->getDialog();
49 pDlg->set_modal(!bEnable);
50 pDlg->set_visible(!bEnable);
51 }
52
53} // anonymous namespace
54
55namespace chart
56{
57using namespace ::com::sun::star;
58using namespace ::com::sun::star::chart2;
59
60using ::com::sun::star::uno::Sequence;
61
63 ChartTypeTemplateProvider* pTemplateProvider,
64 bool bHideDescription /* = false */)
65 : OWizardPage(pPage, pController, "modules/schart/ui/tp_RangeChooser.ui", "tp_RangeChooser")
66 , m_nChangingControlCalls(0)
67 , m_bIsDirty(false)
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_xED_Range(m_xBuilder->weld_entry("ED_RANGE"))
73 , m_xIB_Range(m_xBuilder->weld_button("IB_RANGE"))
74 , m_xRB_Rows(m_xBuilder->weld_radio_button("RB_DATAROWS"))
75 , m_xRB_Columns(m_xBuilder->weld_radio_button("RB_DATACOLS"))
76 , m_xCB_FirstRowAsLabel(m_xBuilder->weld_check_button("CB_FIRST_ROW_ASLABELS"))
77 , m_xCB_FirstColumnAsLabel(m_xBuilder->weld_check_button("CB_FIRST_COLUMN_ASLABELS"))
78 , m_xFTTitle(m_xBuilder->weld_label("STR_PAGE_DATA_RANGE"))
79 , m_xFL_TimeBased(m_xBuilder->weld_widget("separator1"))
80 , m_xCB_TimeBased(m_xBuilder->weld_check_button("CB_TIME_BASED"))
81 , m_xFT_TimeStart(m_xBuilder->weld_label("label1"))
82 , m_xEd_TimeStart(m_xBuilder->weld_entry("ED_TIME_BASED_START"))
83 , m_xFT_TimeEnd(m_xBuilder->weld_label("label2"))
84 , m_xEd_TimeEnd(m_xBuilder->weld_entry("ED_TIME_BASED_END"))
85{
86 m_xFT_Caption->set_visible(!bHideDescription);
87
88 SetPageTitle(m_xFTTitle->get_label());// OH:remove later with dialog
89
90 // set defaults as long as DetectArguments does not work
91 m_xRB_Columns->set_active(true);
92 m_xCB_FirstColumnAsLabel->set_active(true);
93 m_xCB_FirstRowAsLabel->set_active(true);
94
95 // BM: Note, that the range selection is not available, if there is no view.
96 // This happens for charts having their own embedded spreadsheet. If you
97 // force to get the range selection here, this would mean when entering this
98 // page the calc view would be created in this case. So, I enable the
99 // button here, and in the worst case nothing happens when it is pressed.
100 // Not nice, but I see no better solution for the moment.
101 m_xIB_Range->connect_clicked( LINK( this, RangeChooserTabPage, ChooseRangeHdl ));
102
103 m_xED_Range->connect_changed( LINK( this, RangeChooserTabPage, ControlEditedHdl ));
104 m_xRB_Rows->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedRadioHdl ) );
105 m_xCB_FirstRowAsLabel->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) );
106 m_xCB_FirstColumnAsLabel->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) );
107 m_xCB_TimeBased->connect_toggled( LINK( this, RangeChooserTabPage, ControlChangedCheckBoxHdl ) );
108 m_xEd_TimeStart->connect_changed( LINK( this, RangeChooserTabPage, ControlChangedHdl ) );
109 m_xEd_TimeEnd->connect_changed( LINK( this, RangeChooserTabPage, ControlChangedHdl ) );
110
111 if ( !officecfg::Office::Common::Misc::ExperimentalMode::get() )
112 {
113 m_xFL_TimeBased->hide();
114 m_xCB_TimeBased->hide();
115 m_xFT_TimeStart->hide();
116 m_xEd_TimeStart->hide();
117 m_xFT_TimeEnd->hide();
118 m_xEd_TimeEnd->hide();
119 }
120}
121
123{
124}
125
127{
128 OWizardPage::Activate();
130 m_xED_Range->grab_focus();
131}
132
134{
136
139
140 bool bUseColumns = !m_xRB_Rows->get_active();
141 bool bFirstCellAsLabel = bUseColumns ? m_xCB_FirstRowAsLabel->get_active() : m_xCB_FirstColumnAsLabel->get_active();
142 bool bHasCategories = bUseColumns ? m_xCB_FirstColumnAsLabel->get_active() : m_xCB_FirstRowAsLabel->get_active();
143
145 if( bIsValid )
146 m_rDialogModel.detectArguments(m_aLastValidRangeString, bUseColumns, bFirstCellAsLabel, bHasCategories );
147 else
149
151
152 m_xRB_Rows->set_active( !bUseColumns );
153 m_xRB_Columns->set_active( bUseColumns );
154
155 m_xCB_FirstRowAsLabel->set_active( m_xRB_Rows->get_active()?bHasCategories:bFirstCellAsLabel );
156 m_xCB_FirstColumnAsLabel->set_active( m_xRB_Columns->get_active()?bHasCategories:bFirstCellAsLabel );
157
158 isValid();
159
161}
162
164{
165 commitPage();
167}
168
170{
171 commitPage(::vcl::WizardTypes::eFinish);
172}
173
175{
176 //ranges may have been edited in the meanwhile (dirty is true in that case here)
177 if( isValid() )
178 {
180 return true; // return false if this page should not be left
181 }
182 else
183 return false;
184}
185
187{
189 return;
190
192 {
196 {
197 OSL_FAIL( "Need a template to change data source" );
198 return;
199 }
200 }
201
202 if( !m_bIsDirty )
203 return;
204
205 bool bFirstCellAsLabel = ( m_xCB_FirstColumnAsLabel->get_active() && !m_xRB_Columns->get_active() )
206 || ( m_xCB_FirstRowAsLabel->get_active() && !m_xRB_Rows->get_active() );
207 bool bHasCategories = ( m_xCB_FirstColumnAsLabel->get_active() && m_xRB_Columns->get_active() )
208 || ( m_xCB_FirstRowAsLabel->get_active() && m_xRB_Rows->get_active() );
209 bool bTimeBased = m_xCB_TimeBased->get_active();
210
213 m_xRB_Columns->get_active(), bFirstCellAsLabel, bHasCategories ) );
214
215 if(bTimeBased)
216 {
217 aArguments.realloc( aArguments.getLength() + 1 );
218 aArguments.getArray()[aArguments.getLength() - 1] =
219 beans::PropertyValue( "TimeBased", -1, uno::Any(bTimeBased),
220 beans::PropertyState_DIRECT_VALUE );
221 }
222
223 // only if range is valid
224 if( m_aLastValidRangeString != m_xED_Range->get_text())
225 return;
226
228 aArguments.realloc( aArguments.getLength() + 1 );
229 aArguments.getArray()[aArguments.getLength() - 1] =
230 beans::PropertyValue( "CellRangeRepresentation" , -1,
232 beans::PropertyState_DIRECT_VALUE );
234 m_bIsDirty = false;
235
236 if(bTimeBased)
237 {
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);
241 }
242
243 //@todo warn user that the selected range is not valid
244 //@todo better: disable OK-Button if range is invalid
245}
246
248{
249 OUString aRange( m_xED_Range->get_text());
250 bool bFirstCellAsLabel = ( m_xCB_FirstColumnAsLabel->get_active() && !m_xRB_Columns->get_active() )
251 || ( m_xCB_FirstRowAsLabel->get_active() && !m_xRB_Rows->get_active() );
252 bool bHasCategories = ( m_xCB_FirstColumnAsLabel->get_active() && m_xRB_Columns->get_active() )
253 || ( m_xCB_FirstRowAsLabel->get_active() && m_xRB_Rows->get_active() );
254 bool bIsValid = ( aRange.isEmpty() ) ||
255 m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
257 aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(), bFirstCellAsLabel, bHasCategories ));
258
259 if( bIsValid )
260 {
263 m_pTabPageNotifiable->setValidPage( this );
265 }
266 else
267 {
270 m_pTabPageNotifiable->setInvalidPage( this );
271 }
272
273 // enable/disable controls
274 // #i79531# if the range is valid but an action of one of these buttons
275 // would render it invalid, the button should be disabled
276 if( bIsValid )
277 {
278 bool bDataInColumns = m_xRB_Columns->get_active();
279 bool bIsSwappedRangeValid = m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
281 aRange, Sequence< sal_Int32 >(), ! bDataInColumns, bHasCategories, bFirstCellAsLabel ));
282 m_xRB_Rows->set_sensitive( bIsSwappedRangeValid );
283 m_xRB_Columns->set_sensitive( bIsSwappedRangeValid );
284
285 m_xCB_FirstRowAsLabel->set_sensitive(
286 m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
288 aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(),
289 bDataInColumns ? ! bFirstCellAsLabel : bFirstCellAsLabel,
290 bDataInColumns ? bHasCategories : ! bHasCategories )));
291 m_xCB_FirstColumnAsLabel->set_sensitive(
292 m_rDialogModel.getRangeSelectionHelper()->verifyArguments(
294 aRange, Sequence< sal_Int32 >(), m_xRB_Columns->get_active(),
295 bDataInColumns ? bFirstCellAsLabel : ! bFirstCellAsLabel,
296 bDataInColumns ? ! bHasCategories : bHasCategories )));
297 }
298 else
299 {
300 m_xRB_Rows->set_sensitive( bIsValid );
301 m_xRB_Columns->set_sensitive( bIsValid );
302 m_xCB_FirstRowAsLabel->set_sensitive( bIsValid );
303 m_xCB_FirstColumnAsLabel->set_sensitive( bIsValid );
304 }
305
306 bool bShowIB = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection();
307 lcl_ShowChooserButton( *m_xIB_Range, bShowIB );
308
309 return bIsValid;
310}
311
313{
314 setDirty();
315 isValid();
316}
317
319{
320 ControlChangedHdl(*m_xED_Range);
321}
322
323IMPL_LINK_NOARG(RangeChooserTabPage, ControlChangedCheckBoxHdl, weld::Toggleable&, void)
324{
325 ControlChangedHdl(*m_xED_Range);
326}
327
329{
330 setDirty();
331 if( isValid())
332 changeDialogModelAccordingToControls();
333}
334
336{
337 OUString aRange = m_xED_Range->get_text();
338 OUString aTitle = m_xFTTitle->get_label();
339
340 lcl_enableRangeChoosing(true, m_pDialogController);
341 m_rDialogModel.getRangeSelectionHelper()->chooseRange( aRange, aTitle, *this );
342}
343
344void RangeChooserTabPage::listeningFinished( const OUString & rNewRange )
345{
346 //user has selected a new range
347
348 // rNewRange becomes invalid after removing the listener
349 OUString aRange( rNewRange );
350
352
353 // stop listening
354 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening();
355
356 //update dialog state
357 m_xED_Range->set_text(aRange);
358 m_xED_Range->grab_focus();
359
360 setDirty();
361 if( isValid())
363
364 lcl_enableRangeChoosing(false, m_pDialogController);
365}
366
368{
369 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false );
370}
371
373{
374 if( m_nChangingControlCalls == 0 )
375 m_bIsDirty = true;
376}
377
378} //namespace chart
379
380/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetPageTitle(const OUString &rPageTitle)
virtual void Deactivate()
weld::DialogController * m_pDialogController
virtual rtl::Reference<::chart::ChartTypeTemplate > getCurrentTemplate() const =0
static css::uno::Sequence< css::beans::PropertyValue > createArguments(bool bUseColumns, bool bFirstCellAsLabel, bool bHasCategories)
void setData(const css::uno::Sequence< css::beans::PropertyValue > &rArguments)
void detectArguments(OUString &rOutRangeString, bool &rOutUseColumns, bool &rOutFirstCellAsLabel, bool &rOutHasCategories) const
void setTemplate(const rtl::Reference< ::chart::ChartTypeTemplate > &xTemplate)
void setTimeBasedRange(bool bTimeBased, sal_Int32 nStart, sal_Int32 nEnd) const
bool allArgumentsForRectRangeDetected() const
std::shared_ptr< RangeSelectionHelper > const & getRangeSelectionHelper() const
void startControllerLockTimer()
std::unique_ptr< weld::RadioButton > m_xRB_Rows
std::unique_ptr< weld::Label > m_xFT_Caption
TabPageNotifiable * m_pTabPageNotifiable
virtual void disposingRangeSelection() override
std::unique_ptr< weld::Entry > m_xED_Range
virtual void listeningFinished(const OUString &rNewRange) override
ChartTypeTemplateProvider * m_pTemplateProvider
std::unique_ptr< weld::Label > m_xFTTitle
std::unique_ptr< weld::CheckButton > m_xCB_FirstRowAsLabel
std::unique_ptr< weld::Widget > m_xFL_TimeBased
RangeChooserTabPage(weld::Container *pPage, weld::DialogController *pController, DialogModel &rDialogModel, ChartTypeTemplateProvider *pTemplateProvider, bool bHideDescription=false)
rtl::Reference< ::chart::ChartTypeTemplate > m_xCurrentChartTypeTemplate
std::unique_ptr< weld::Entry > m_xEd_TimeEnd
virtual void Deactivate() override
std::unique_ptr< weld::Entry > m_xEd_TimeStart
std::unique_ptr< weld::Label > m_xFT_TimeStart
virtual ~RangeChooserTabPage() override
std::unique_ptr< weld::Label > m_xFT_TimeEnd
std::unique_ptr< weld::CheckButton > m_xCB_TimeBased
virtual void Activate() override
std::unique_ptr< weld::RadioButton > m_xRB_Columns
std::unique_ptr< weld::CheckButton > m_xCB_FirstColumnAsLabel
std::unique_ptr< weld::Button > m_xIB_Range
virtual Dialog * getDialog()=0
virtual void set_visible(bool visible)
virtual bool get_visible() const=0
virtual void set_modal(bool bModal)=0
Sequence< PropertyValue > aArguments
IMPL_LINK_NOARG(SplinePropertiesDialog, SplineTypeListBoxHdl, weld::ComboBox &, void)