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 "groupboxwiz.hxx"
21 #include "commonpagesdbp.hxx"
22 #include <tools/debug.hxx>
23 #include <comphelper/diagnose_ex.hxx>
24 #include "optiongrouplayouter.hxx"
26 #include <o3tl/safeint.hxx>
28 #define GBW_STATE_OPTIONLIST 0
29 #define GBW_STATE_DEFAULTOPTION 1
30 #define GBW_STATE_OPTIONVALUES 2
31 #define GBW_STATE_DBFIELD 3
32 #define GBW_STATE_FINALIZE 4
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::lang
;
38 using namespace ::com::sun::star::beans
;
39 using namespace ::com::sun::star::form
;
41 OGroupBoxWizard::OGroupBoxWizard(weld::Window
* _pParent
,
42 const Reference
< XPropertySet
>& _rxObjectModel
, const Reference
< XComponentContext
>& _rxContext
)
43 : OControlWizard(_pParent
, _rxObjectModel
, _rxContext
)
44 , m_bVisitedDefault(false)
47 initControlSettings(&m_aSettings
);
49 m_xPrevPage
->set_help_id(HID_GROUPWIZARD_PREVIOUS
);
50 m_xNextPage
->set_help_id(HID_GROUPWIZARD_NEXT
);
51 m_xCancel
->set_help_id(HID_GROUPWIZARD_CANCEL
);
52 m_xFinish
->set_help_id(HID_GROUPWIZARD_FINISH
);
53 setTitleBase(compmodule::ModuleRes(RID_STR_GROUPWIZARD_TITLE
));
56 bool OGroupBoxWizard::approveControl(sal_Int16 _nClassId
)
58 return FormComponentType::GROUPBOX
== _nClassId
;
61 std::unique_ptr
<BuilderPage
> OGroupBoxWizard::createPage(::vcl::WizardTypes::WizardState _nState
)
63 OUString
sIdent(OUString::number(_nState
));
64 weld::Container
* pPageContainer
= m_xAssistant
->append_page(sIdent
);
68 case GBW_STATE_OPTIONLIST
:
69 return std::make_unique
<ORadioSelectionPage
>(pPageContainer
, this);
71 case GBW_STATE_DEFAULTOPTION
:
72 return std::make_unique
<ODefaultFieldSelectionPage
>(pPageContainer
, this);
74 case GBW_STATE_OPTIONVALUES
:
75 return std::make_unique
<OOptionValuesPage
>(pPageContainer
, this);
77 case GBW_STATE_DBFIELD
:
78 return std::make_unique
<OOptionDBFieldPage
>(pPageContainer
, this);
80 case GBW_STATE_FINALIZE
:
81 return std::make_unique
<OFinalizeGBWPage
>(pPageContainer
, this);
87 vcl::WizardTypes::WizardState
OGroupBoxWizard::determineNextState( ::vcl::WizardTypes::WizardState _nCurrentState
) const
89 switch (_nCurrentState
)
91 case GBW_STATE_OPTIONLIST
:
92 return GBW_STATE_DEFAULTOPTION
;
94 case GBW_STATE_DEFAULTOPTION
:
95 return GBW_STATE_OPTIONVALUES
;
97 case GBW_STATE_OPTIONVALUES
:
98 if (getContext().aFieldNames
.hasElements())
99 return GBW_STATE_DBFIELD
;
101 return GBW_STATE_FINALIZE
;
103 case GBW_STATE_DBFIELD
:
104 return GBW_STATE_FINALIZE
;
107 return WZS_INVALID_STATE
;
110 void OGroupBoxWizard::enterState(::vcl::WizardTypes::WizardState _nState
)
112 // some stuff to do before calling the base class (modifying our settings)
115 case GBW_STATE_DEFAULTOPTION
:
116 if (!m_bVisitedDefault
)
117 { // assume that the first of the radio buttons should be selected
118 DBG_ASSERT(m_aSettings
.aLabels
.size(), "OGroupBoxWizard::enterState: should never have reached this state!");
119 m_aSettings
.sDefaultField
= m_aSettings
.aLabels
[0];
121 m_bVisitedDefault
= true;
124 case GBW_STATE_DBFIELD
:
126 { // try to generate a default for the DB field
127 // (simply use the first field in the DB names collection)
128 if (getContext().aFieldNames
.hasElements())
129 m_aSettings
.sDBField
= getContext().aFieldNames
[0];
135 // setting the def button... to be done before the base class is called, too, 'cause the base class
136 // calls the pages, which are allowed to override our def button behaviour
137 defaultButton(GBW_STATE_FINALIZE
== _nState
? WizardButtonFlags::FINISH
: WizardButtonFlags::NEXT
);
139 // allow "finish" on the last page only
140 enableButtons(WizardButtonFlags::FINISH
, GBW_STATE_FINALIZE
== _nState
);
141 // allow previous on all pages but the first one
142 enableButtons(WizardButtonFlags::PREVIOUS
, GBW_STATE_OPTIONLIST
!= _nState
);
143 // allow next on all pages but the last one
144 enableButtons(WizardButtonFlags::NEXT
, GBW_STATE_FINALIZE
!= _nState
);
146 OControlWizard::enterState(_nState
);
149 bool OGroupBoxWizard::onFinish()
151 // commit the basic control settings
152 commitControlSettings(&m_aSettings
);
154 // create the radio buttons
157 OOptionGroupLayouter
aLayouter( getComponentContext() );
158 aLayouter
.doLayout(getContext(), getSettings());
160 catch(const Exception
&)
162 TOOLS_WARN_EXCEPTION("extensions.dbpilots",
163 "caught an exception while creating the radio shapes!");
166 return OControlWizard::onFinish();
169 ORadioSelectionPage::ORadioSelectionPage(weld::Container
* pPage
, OControlWizard
* pWizard
)
170 : OGBWPage(pPage
, pWizard
, "modules/sabpilot/ui/groupradioselectionpage.ui", "GroupRadioSelectionPage")
171 , m_xRadioName(m_xBuilder
->weld_entry("radiolabels"))
172 , m_xMoveRight(m_xBuilder
->weld_button("toright"))
173 , m_xMoveLeft(m_xBuilder
->weld_button("toleft"))
174 , m_xExistingRadios(m_xBuilder
->weld_tree_view("radiobuttons"))
176 if (getContext().aFieldNames
.hasElements())
178 enableFormDatasourceDisplay();
181 m_xMoveLeft
->connect_clicked(LINK(this, ORadioSelectionPage
, OnMoveEntry
));
182 m_xMoveRight
->connect_clicked(LINK(this, ORadioSelectionPage
, OnMoveEntry
));
183 m_xRadioName
->connect_changed(LINK(this, ORadioSelectionPage
, OnNameModified
));
184 m_xExistingRadios
->connect_changed(LINK(this, ORadioSelectionPage
, OnEntrySelected
));
186 implCheckMoveButtons();
187 m_xExistingRadios
->set_selection_mode(SelectionMode::Multiple
);
189 getDialog()->defaultButton(m_xMoveRight
.get());
192 ORadioSelectionPage::~ORadioSelectionPage()
196 void ORadioSelectionPage::Activate()
198 OGBWPage::Activate();
199 m_xRadioName
->grab_focus();
202 void ORadioSelectionPage::initializePage()
204 OGBWPage::initializePage();
206 m_xRadioName
->set_text("");
208 // no need to initialize the list of radios here
209 // (we're the only one affecting this special setting, so it will be in the same state as last time this
210 // page was committed)
212 implCheckMoveButtons();
215 bool ORadioSelectionPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason
)
217 if (!OGBWPage::commitPage(_eReason
))
220 // copy the names of the radio buttons to be inserted
221 // and initialize the values
222 OOptionGroupSettings
& rSettings
= getSettings();
223 rSettings
.aLabels
.clear();
224 rSettings
.aValues
.clear();
225 rSettings
.aLabels
.reserve(m_xExistingRadios
->n_children());
226 rSettings
.aValues
.reserve(m_xExistingRadios
->n_children());
227 for (sal_Int32 i
=0; i
<m_xExistingRadios
->n_children(); ++i
)
229 rSettings
.aLabels
.push_back(m_xExistingRadios
->get_text(i
));
230 rSettings
.aValues
.push_back(OUString::number(i
+ 1));
236 IMPL_LINK( ORadioSelectionPage
, OnMoveEntry
, weld::Button
&, rButton
, void )
238 bool bMoveLeft
= (m_xMoveLeft
.get() == &rButton
);
241 while (m_xExistingRadios
->count_selected_rows())
242 m_xExistingRadios
->remove(m_xExistingRadios
->get_selected_index());
246 m_xExistingRadios
->append_text(m_xRadioName
->get_text());
247 m_xRadioName
->set_text("");
250 implCheckMoveButtons();
254 m_xExistingRadios
->grab_focus();
256 m_xRadioName
->grab_focus();
259 IMPL_LINK_NOARG( ORadioSelectionPage
, OnEntrySelected
, weld::TreeView
&, void )
261 implCheckMoveButtons();
264 IMPL_LINK_NOARG( ORadioSelectionPage
, OnNameModified
, weld::Entry
&, void )
266 implCheckMoveButtons();
269 bool ORadioSelectionPage::canAdvance() const
271 return 0 != m_xExistingRadios
->n_children();
274 void ORadioSelectionPage::implCheckMoveButtons()
276 bool bHaveSome
= (0 != m_xExistingRadios
->n_children());
277 bool bSelectedSome
= (0 != m_xExistingRadios
->count_selected_rows());
278 bool bUnfinishedInput
= !m_xRadioName
->get_text().isEmpty();
280 m_xMoveLeft
->set_sensitive(bSelectedSome
);
281 m_xMoveRight
->set_sensitive(bUnfinishedInput
);
283 OControlWizard
* pDialogController
= getDialog();
285 pDialogController
->enableButtons(WizardButtonFlags::NEXT
, bHaveSome
);
287 weld::Dialog
* pDialog
= pDialogController
->getDialog();
289 if (bUnfinishedInput
)
291 if (!pDialog
->is_default_widget(m_xMoveRight
.get()))
292 pDialogController
->defaultButton(m_xMoveRight
.get());
296 if (pDialog
->is_default_widget(m_xMoveRight
.get()))
297 pDialogController
->defaultButton(WizardButtonFlags::NEXT
);
301 ODefaultFieldSelectionPage::ODefaultFieldSelectionPage(weld::Container
* pPage
, OControlWizard
* pWizard
)
302 : OMaybeListSelectionPage(pPage
, pWizard
, "modules/sabpilot/ui/defaultfieldselectionpage.ui", "DefaultFieldSelectionPage")
303 , m_xDefSelYes(m_xBuilder
->weld_radio_button("defaultselectionyes"))
304 , m_xDefSelNo(m_xBuilder
->weld_radio_button("defaultselectionno"))
305 , m_xDefSelection(m_xBuilder
->weld_combo_box("defselectionfield"))
307 announceControls(*m_xDefSelYes
, *m_xDefSelNo
, *m_xDefSelection
);
310 ODefaultFieldSelectionPage::~ODefaultFieldSelectionPage()
314 void ODefaultFieldSelectionPage::initializePage()
316 OMaybeListSelectionPage::initializePage();
318 const OOptionGroupSettings
& rSettings
= getSettings();
321 m_xDefSelection
->clear();
322 for (auto const& label
: rSettings
.aLabels
)
323 m_xDefSelection
->append_text(label
);
325 implInitialize(rSettings
.sDefaultField
);
328 bool ODefaultFieldSelectionPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason
)
330 if (!OMaybeListSelectionPage::commitPage(_eReason
))
333 OOptionGroupSettings
& rSettings
= getSettings();
334 implCommit(rSettings
.sDefaultField
);
339 OOptionValuesPage::OOptionValuesPage(weld::Container
* pPage
, OControlWizard
* pWizard
)
340 : OGBWPage(pPage
, pWizard
, "modules/sabpilot/ui/optionvaluespage.ui", "OptionValuesPage")
341 , m_xValue(m_xBuilder
->weld_entry("optionvalue"))
342 , m_xOptions(m_xBuilder
->weld_tree_view("radiobuttons"))
343 , m_nLastSelection(::vcl::WizardTypes::WizardState(-1))
345 m_xOptions
->connect_changed(LINK(this, OOptionValuesPage
, OnOptionSelected
));
348 OOptionValuesPage::~OOptionValuesPage()
352 IMPL_LINK_NOARG( OOptionValuesPage
, OnOptionSelected
, weld::TreeView
&, void )
354 implTraveledOptions();
357 void OOptionValuesPage::Activate()
359 OGBWPage::Activate();
360 m_xValue
->grab_focus();
363 void OOptionValuesPage::implTraveledOptions()
365 if (::vcl::WizardTypes::WizardState(-1) != m_nLastSelection
)
367 // save the value for the last option
368 DBG_ASSERT(o3tl::make_unsigned(m_nLastSelection
) < m_aUncommittedValues
.size(), "OOptionValuesPage::implTraveledOptions: invalid previous selection index!");
369 m_aUncommittedValues
[m_nLastSelection
] = m_xValue
->get_text();
372 m_nLastSelection
= m_xOptions
->get_selected_index();
373 DBG_ASSERT(o3tl::make_unsigned(m_nLastSelection
) < m_aUncommittedValues
.size(), "OOptionValuesPage::implTraveledOptions: invalid new selection index!");
374 m_xValue
->set_text(m_aUncommittedValues
[m_nLastSelection
]);
377 void OOptionValuesPage::initializePage()
379 OGBWPage::initializePage();
381 const OOptionGroupSettings
& rSettings
= getSettings();
382 DBG_ASSERT(rSettings
.aLabels
.size(), "OOptionValuesPage::initializePage: no options!!");
383 DBG_ASSERT(rSettings
.aLabels
.size() == rSettings
.aValues
.size(), "OOptionValuesPage::initializePage: inconsistent data!");
385 // fill the list with all available options
387 m_nLastSelection
= -1;
388 for (auto const& label
: rSettings
.aLabels
)
389 m_xOptions
->append_text(label
);
391 // remember the values ... can't set them directly in the settings without the explicit commit call
392 // so we need have a copy of the values
393 m_aUncommittedValues
= rSettings
.aValues
;
395 // select the first entry
396 m_xOptions
->select(0);
397 implTraveledOptions();
400 bool OOptionValuesPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason
)
402 if (!OGBWPage::commitPage(_eReason
))
405 OOptionGroupSettings
& rSettings
= getSettings();
407 // commit the current value
408 implTraveledOptions();
409 // copy the uncommitted values
410 rSettings
.aValues
= m_aUncommittedValues
;
415 OOptionDBFieldPage::OOptionDBFieldPage(weld::Container
* pPage
, OControlWizard
* pWizard
)
416 : ODBFieldPage(pPage
, pWizard
)
418 setDescriptionText(compmodule::ModuleRes(RID_STR_GROUPWIZ_DBFIELD
));
421 OUString
& OOptionDBFieldPage::getDBFieldSetting()
423 return static_cast<OGroupBoxWizard
*>(getDialog())->getSettings().sDBField
;
426 OFinalizeGBWPage::OFinalizeGBWPage(weld::Container
* pPage
, OControlWizard
* pWizard
)
427 : OGBWPage(pPage
, pWizard
, "modules/sabpilot/ui/optionsfinalpage.ui", "OptionsFinalPage")
428 , m_xName(m_xBuilder
->weld_entry("nameit"))
432 OFinalizeGBWPage::~OFinalizeGBWPage()
436 void OFinalizeGBWPage::Activate()
438 OGBWPage::Activate();
439 m_xName
->grab_focus();
442 bool OFinalizeGBWPage::canAdvance() const
447 void OFinalizeGBWPage::initializePage()
449 OGBWPage::initializePage();
451 const OOptionGroupSettings
& rSettings
= getSettings();
452 m_xName
->set_text(rSettings
.sControlLabel
);
455 bool OFinalizeGBWPage::commitPage( ::vcl::WizardTypes::CommitPageReason _eReason
)
457 if (!OGBWPage::commitPage(_eReason
))
460 getSettings().sControlLabel
= m_xName
->get_text();
468 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */