summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-08-05 17:26:53 +0100
committerCaolán McNamara <caolanm@redhat.com>2019-08-22 16:37:16 +0200
commit69057064d8957804c76e623d57c103c3413b7cbc (patch)
tree8026201f2750300a3b9f831a04dcc34016d54a95
parente724f245e9652230d4c1f58c353be150006affcd (diff)
weld ODbTypeWizDialogSetup
split up RoadmapWizard to sit its wizard logic on top of a a native GtkAssistant a) awkwardly GtkAssistant is not a GtkDialog, but derives directly from GtkWindow so some shuffling around required due to that b) hidden/unused pages are shuffled to the end of the list of pages and their titles turned off in order to hide them from the roadmap c) some nonstandard hackery required to get the gtk roadmap titles to wrap Change-Id: I0d2346c489fef744136a2785f33c846d97bd8dc6 Reviewed-on: https://gerrit.libreoffice.org/76876 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--cui/source/dialogs/about.cxx28
-rw-r--r--cui/source/inc/about.hxx11
-rw-r--r--dbaccess/UIConfig_dbaccess.mk1
-rw-r--r--dbaccess/source/ui/dlg/adminpages.cxx4
-rw-r--r--dbaccess/source/ui/dlg/dbwizsetup.cxx88
-rw-r--r--dbaccess/source/ui/dlg/generalpage.cxx44
-rw-r--r--dbaccess/source/ui/dlg/generalpage.hxx6
-rw-r--r--dbaccess/source/ui/dlg/sqlmessage.cxx2
-rw-r--r--dbaccess/source/ui/inc/dbwizsetup.hxx5
-rw-r--r--dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx6
-rw-r--r--dbaccess/uiconfig/ui/authentificationpage.ui4
-rw-r--r--dbaccess/uiconfig/ui/databasewizard.ui18
-rw-r--r--dbaccess/uiconfig/ui/dbasepage.ui4
-rw-r--r--dbaccess/uiconfig/ui/dbwizconnectionpage.ui5
-rw-r--r--dbaccess/uiconfig/ui/dbwizmysqlintropage.ui5
-rw-r--r--dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui8
-rw-r--r--dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui39
-rw-r--r--dbaccess/uiconfig/ui/dbwiztextpage.ui8
-rw-r--r--dbaccess/uiconfig/ui/finalpagewizard.ui23
-rw-r--r--dbaccess/uiconfig/ui/generalpagewizard.ui67
-rw-r--r--dbaccess/uiconfig/ui/jdbcconnectionpage.ui3
-rw-r--r--dbaccess/uiconfig/ui/ldapconnectionpage.ui4
-rw-r--r--dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui5
-rw-r--r--include/svtools/helpids.h3
-rw-r--r--include/tools/wintypes.hxx5
-rw-r--r--include/vcl/roadmapwizard.hxx146
-rw-r--r--include/vcl/vclenum.hxx15
-rw-r--r--include/vcl/weld.hxx42
-rw-r--r--include/vcl/wizardmachine.hxx251
-rw-r--r--vcl/source/app/salvtables.cxx293
-rw-r--r--vcl/source/control/button.cxx3
-rw-r--r--vcl/source/control/roadmapwizard.cxx356
-rw-r--r--vcl/source/control/wizardmachine.cxx598
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx399
34 files changed, 2219 insertions, 280 deletions
diff --git a/cui/source/dialogs/about.cxx b/cui/source/dialogs/about.cxx
index a9617f7a8381..da2e4d2b4e2d 100644
--- a/cui/source/dialogs/about.cxx
+++ b/cui/source/dialogs/about.cxx
@@ -68,13 +68,13 @@ AboutDialog::AboutDialog(weld::Window* pParent)
m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_WEBSITE), 102);
m_xDialog->add_button(CuiResId(RID_SVXSTR_ABOUT_RELEASE_NOTES), 103);
- m_pCreditsButton = m_xDialog->get_widget_for_response(101);
- m_pCreditsButton->set_secondary(true);
- m_pWebsiteButton = m_xDialog->get_widget_for_response(102);
- m_pWebsiteButton->set_secondary(true);
- m_pReleaseNotesButton = m_xDialog->get_widget_for_response(103);
- m_pReleaseNotesButton->set_secondary(true);
- m_pCloseButton = m_xDialog->get_widget_for_response(RET_CLOSE);
+ m_xCreditsButton.reset(m_xDialog->weld_widget_for_response(101));
+ m_xCreditsButton->set_secondary(true);
+ m_xWebsiteButton.reset(m_xDialog->weld_widget_for_response(102));
+ m_xWebsiteButton->set_secondary(true);
+ m_xReleaseNotesButton.reset(m_xDialog->weld_widget_for_response(103));
+ m_xReleaseNotesButton->set_secondary(true);
+ m_xCloseButton.reset(m_xDialog->weld_widget_for_response(RET_CLOSE));
m_buildIdLinkString = m_xDialog->get_website_label();
@@ -88,10 +88,10 @@ AboutDialog::AboutDialog(weld::Window* pParent)
m_xDialog->connect_size_allocate(LINK(this, AboutDialog, SizeAllocHdl));
// Connect all handlers
- m_pCreditsButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
- m_pWebsiteButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
- m_pReleaseNotesButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
- m_pCloseButton->grab_focus();
+ m_xCreditsButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
+ m_xWebsiteButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
+ m_xReleaseNotesButton->connect_clicked( LINK( this, AboutDialog, HandleClick ) );
+ m_xCloseButton->grab_focus();
}
AboutDialog::~AboutDialog()
@@ -103,14 +103,14 @@ IMPL_LINK(AboutDialog, HandleClick, weld::Button&, rButton, void)
OUString sURL = "";
// Find which button was pressed and from this, get the URL to be opened
- if (&rButton == m_pCreditsButton)
+ if (&rButton == m_xCreditsButton.get())
sURL = CuiResId(RID_SVXSTR_ABOUT_CREDITS_URL);
- else if (&rButton == m_pWebsiteButton)
+ else if (&rButton == m_xWebsiteButton.get())
{
sURL = officecfg::Office::Common::Help::StartCenter::InfoURL::get();
localizeWebserviceURI(sURL);
}
- else if (&rButton == m_pReleaseNotesButton)
+ else if (&rButton == m_xReleaseNotesButton.get())
{
sURL = officecfg::Office::Common::Menus::ReleaseNotesURL::get() +
"?LOvers=" + utl::ConfigManager::getProductVersion() +
diff --git a/cui/source/inc/about.hxx b/cui/source/inc/about.hxx
index adafb7448ef0..c51eb15433d8 100644
--- a/cui/source/inc/about.hxx
+++ b/cui/source/inc/about.hxx
@@ -27,18 +27,17 @@ class AboutDialog : public weld::DialogController
private:
std::unique_ptr<weld::Builder> m_xBuilder;
std::shared_ptr<weld::AboutDialog> m_xDialog;
- std::shared_ptr<weld::Container> m_xContentArea;
+ std::unique_ptr<weld::Container> m_xContentArea;
+ std::unique_ptr<weld::Button> m_xCreditsButton;
+ std::unique_ptr<weld::Button> m_xWebsiteButton;
+ std::unique_ptr<weld::Button> m_xReleaseNotesButton;
+ std::unique_ptr<weld::Button> m_xCloseButton;
BitmapEx aLogoBitmap;
BitmapEx aBackgroundBitmap;
OUString m_buildIdLinkString;
- weld::Button* m_pCreditsButton;
- weld::Button* m_pWebsiteButton;
- weld::Button* m_pReleaseNotesButton;
- weld::Button* m_pCloseButton;
-
void SetBuildIdLink();
void SetLogo();
diff --git a/dbaccess/UIConfig_dbaccess.mk b/dbaccess/UIConfig_dbaccess.mk
index eacb9eb112c2..ff79be062c22 100644
--- a/dbaccess/UIConfig_dbaccess.mk
+++ b/dbaccess/UIConfig_dbaccess.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_UIConfig_add_uifiles,dbaccess, \
dbaccess/uiconfig/ui/colwidthdialog \
dbaccess/uiconfig/ui/connectionpage \
dbaccess/uiconfig/ui/copytablepage \
+ dbaccess/uiconfig/ui/databasewizard \
dbaccess/uiconfig/ui/dbaseindexdialog \
dbaccess/uiconfig/ui/dbasepage \
dbaccess/uiconfig/ui/dbwizconnectionpage \
diff --git a/dbaccess/source/ui/dlg/adminpages.cxx b/dbaccess/source/ui/dlg/adminpages.cxx
index e0599f5f1517..3672e247de5c 100644
--- a/dbaccess/source/ui/dlg/adminpages.cxx
+++ b/dbaccess/source/ui/dlg/adminpages.cxx
@@ -64,8 +64,10 @@ namespace dbaui
, m_pAdminDialog(nullptr)
, m_pItemSetHelper(nullptr)
{
-
SetExchangeSupport();
+
+ Size aSize(LogicToPixel(::Size(WIZARD_PAGE_X, WIZARD_PAGE_Y), MapMode(MapUnit::MapAppFont)));
+ m_xContainer->set_size_request(aSize.Width(), aSize.Height());
}
DeactivateRC OGenericAdministrationPage::DeactivatePage(SfxItemSet* _pSet)
diff --git a/dbaccess/source/ui/dlg/dbwizsetup.cxx b/dbaccess/source/ui/dlg/dbwizsetup.cxx
index 97cdfdb5e609..e878a7d611eb 100644
--- a/dbaccess/source/ui/dlg/dbwizsetup.cxx
+++ b/dbaccess/source/ui/dlg/dbwizsetup.cxx
@@ -99,12 +99,12 @@ using namespace ::comphelper;
using namespace ::cppu;
// ODbTypeWizDialogSetup
-ODbTypeWizDialogSetup::ODbTypeWizDialogSetup(vcl::Window* _pParent
+ODbTypeWizDialogSetup::ODbTypeWizDialogSetup(weld::Window* _pParent
,SfxItemSet const * _pItems
,const Reference< XComponentContext >& _rxORB
,const css::uno::Any& _aDataSourceName
)
- :vcl::RoadmapWizard( _pParent )
+ : vcl::RoadmapWizardMachine( _pParent )
, m_bIsConnectable( false)
, m_sRM_IntroText( DBA_RES( STR_PAGETITLE_INTROPAGE ) )
@@ -135,14 +135,13 @@ ODbTypeWizDialogSetup::ODbTypeWizDialogSetup(vcl::Window* _pParent
OSL_ENSURE(m_pCollection, "ODbTypeWizDialogSetup::ODbTypeWizDialogSetup : really need a DSN type collection !");
- m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxORB,GetFrameWeld(),_pParent ? _pParent->GetFrameWeld() : nullptr, this));
+ m_pImpl.reset(new ODbDataSourceAdministrationHelper(_rxORB, m_xAssistant.get(), _pParent, this));
m_pImpl->setDataSourceOrName(_aDataSourceName);
Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource();
m_pOutSet.reset( new SfxItemSet( *_pItems->GetPool(), _pItems->GetRanges() ) );
m_pImpl->translateProperties(xDatasource, *m_pOutSet);
- SetPageSizePixel(LogicToPixel(::Size(WIZARD_PAGE_X, WIZARD_PAGE_Y), MapMode(MapUnit::MapAppFont)));
defaultButton(WizardButtonFlags::NEXT);
enableButtons(WizardButtonFlags::FINISH, true);
enableAutomaticNextButtonState();
@@ -165,13 +164,13 @@ ODbTypeWizDialogSetup::ODbTypeWizDialogSetup(vcl::Window* _pParent
aPath.push_back(PAGE_DBSETUPWIZARD_INTRO);
declarePath( static_cast<PathId>(m_pCollection->size()+1), aPath);
- m_pPrevPage->SetHelpId(HID_DBWIZ_PREVIOUS);
- m_pNextPage->SetHelpId(HID_DBWIZ_NEXT);
- m_pCancel->SetHelpId(HID_DBWIZ_CANCEL);
- m_pFinish->SetHelpId(HID_DBWIZ_FINISH);
- SetRoadmapInteractive( true );
+ m_xPrevPage->set_help_id(HID_DBWIZ_PREVIOUS);
+ m_xNextPage->set_help_id(HID_DBWIZ_NEXT);
+ m_xCancel->set_help_id(HID_DBWIZ_CANCEL);
+ m_xFinish->set_help_id(HID_DBWIZ_FINISH);
ActivatePage();
setTitleBase(DBA_RES(STR_DBWIZARDTITLE));
+ m_xAssistant->set_current_page(0);
}
void ODbTypeWizDialogSetup::declareAuthDepPath( const OUString& _sURL, PathId _nPathId, const vcl::RoadmapWizardTypes::WizardPath& _rPaths)
@@ -188,7 +187,7 @@ void ODbTypeWizDialogSetup::declareAuthDepPath( const OUString& _sURL, PathId _n
}
// call base method
- ::vcl::RoadmapWizard::declarePath( _nPathId, aPath );
+ ::vcl::RoadmapWizardMachine::declarePath( _nPathId, aPath );
}
OUString ODbTypeWizDialogSetup::getStateDisplayName( WizardState _nState ) const
@@ -256,16 +255,6 @@ OUString ODbTypeWizDialogSetup::getStateDisplayName( WizardState _nState ) const
ODbTypeWizDialogSetup::~ODbTypeWizDialogSetup()
{
- disposeOnce();
-}
-
-void ODbTypeWizDialogSetup::dispose()
-{
- m_pOutSet.reset();
- m_pGeneralPage.clear();
- m_pMySQLIntroPage.clear();
- m_pFinalPage.clear();
- vcl::RoadmapWizard::dispose();
}
IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnTypeSelected, OGeneralPage&, void)
@@ -458,10 +447,16 @@ VclPtr<TabPage> ODbTypeWizDialogSetup::createPage(WizardState _nState)
{
VclPtr<SfxTabPage> pFirstPage;
VclPtr<OGenericAdministrationPage> pPage;
+
+ OString sIdent(OString::number(_nState));
+ weld::Container* pPageContainer = m_xAssistant->append_page(sIdent);
+ // TODO eventually pass DialogController as distinct argument instead of bundling into TabPageParent
+ TabPageParent aParent(pPageContainer, this);
+
switch(_nState)
{
case PAGE_DBSETUPWIZARD_INTRO:
- pFirstPage = VclPtr<OGeneralPageWizard>::Create(this,*m_pOutSet);
+ pFirstPage = VclPtr<OGeneralPageWizard>::Create(aParent,*m_pOutSet);
pPage = static_cast<OGenericAdministrationPage*> (pFirstPage.get());
m_pGeneralPage = static_cast<OGeneralPageWizard*>(pFirstPage.get());
m_pGeneralPage->SetTypeSelectHandler(LINK(this, ODbTypeWizDialogSetup, OnTypeSelected));
@@ -471,70 +466,70 @@ VclPtr<TabPage> ODbTypeWizDialogSetup::createPage(WizardState _nState)
break;
case PAGE_DBSETUPWIZARD_DBASE:
- pPage = OConnectionTabPageSetup::CreateDbaseTabPage(this,*m_pOutSet);
+ pPage = OConnectionTabPageSetup::CreateDbaseTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_ADO:
- pPage = OConnectionTabPageSetup::CreateADOTabPage( this, *m_pOutSet);
+ pPage = OConnectionTabPageSetup::CreateADOTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_TEXT:
- pPage = OTextConnectionPageSetup::CreateTextTabPage(this,*m_pOutSet);
+ pPage = OTextConnectionPageSetup::CreateTextTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_ODBC:
- pPage = OConnectionTabPageSetup::CreateODBCTabPage( this, *m_pOutSet);
+ pPage = OConnectionTabPageSetup::CreateODBCTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_JDBC:
- pPage = OJDBCConnectionPageSetup::CreateJDBCTabPage( this, *m_pOutSet);
+ pPage = OJDBCConnectionPageSetup::CreateJDBCTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_MYSQL_ODBC:
m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:odbc:")));
- pPage = OConnectionTabPageSetup::CreateODBCTabPage( this, *m_pOutSet);
+ pPage = OConnectionTabPageSetup::CreateODBCTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_MYSQL_JDBC:
m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:jdbc:")));
- pPage = OGeneralSpecialJDBCConnectionPageSetup::CreateMySQLJDBCTabPage( this, *m_pOutSet);
+ pPage = OGeneralSpecialJDBCConnectionPageSetup::CreateMySQLJDBCTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_MYSQL_NATIVE:
m_pOutSet->Put(SfxStringItem(DSID_CONNECTURL, m_pCollection->getPrefix("sdbc:mysql:mysqlc:")));
- pPage = MySQLNativeSetupPage::Create( this, *m_pOutSet);
+ pPage = MySQLNativeSetupPage::Create(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_ORACLE:
- pPage = OGeneralSpecialJDBCConnectionPageSetup::CreateOracleJDBCTabPage( this, *m_pOutSet);
+ pPage = OGeneralSpecialJDBCConnectionPageSetup::CreateOracleJDBCTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_LDAP:
- pPage = OLDAPConnectionPageSetup::CreateLDAPTabPage(this,*m_pOutSet);
+ pPage = OLDAPConnectionPageSetup::CreateLDAPTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_DOCUMENT_OR_SPREADSHEET:
- pPage = OSpreadSheetConnectionPageSetup::CreateDocumentOrSpreadSheetTabPage(this,*m_pOutSet);
+ pPage = OSpreadSheetConnectionPageSetup::CreateDocumentOrSpreadSheetTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_MSACCESS:
- pPage = OConnectionTabPageSetup::CreateMSAccessTabPage(this,*m_pOutSet);
+ pPage = OConnectionTabPageSetup::CreateMSAccessTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_MYSQL_INTRO:
- m_pMySQLIntroPage = OMySQLIntroPageSetup::CreateMySQLIntroTabPage(this,*m_pOutSet);
+ m_pMySQLIntroPage = OMySQLIntroPageSetup::CreateMySQLIntroTabPage(aParent, *m_pOutSet);
m_pMySQLIntroPage->SetClickHdl(LINK( this, ODbTypeWizDialogSetup, ImplClickHdl ) );
pPage = m_pMySQLIntroPage;
break;
case PAGE_DBSETUPWIZARD_AUTHENTIFICATION:
- pPage = OAuthentificationPageSetup::CreateAuthentificationTabPage(this,*m_pOutSet);
+ pPage = OAuthentificationPageSetup::CreateAuthentificationTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_USERDEFINED:
- pPage = OConnectionTabPageSetup::CreateUserDefinedTabPage(this,*m_pOutSet);
+ pPage = OConnectionTabPageSetup::CreateUserDefinedTabPage(aParent, *m_pOutSet);
break;
case PAGE_DBSETUPWIZARD_FINAL:
- pPage = OFinalDBPageSetup::CreateFinalDBTabPageSetup(this,*m_pOutSet);
+ pPage = OFinalDBPageSetup::CreateFinalDBTabPageSetup(aParent, *m_pOutSet);
m_pFinalPage = static_cast<OFinalDBPageSetup*> (pPage.get());
break;
}
@@ -553,6 +548,8 @@ VclPtr<TabPage> ODbTypeWizDialogSetup::createPage(WizardState _nState)
enableButtons( WizardButtonFlags::FINISH, _nState == PAGE_DBSETUPWIZARD_FINAL );
enableButtons( WizardButtonFlags::NEXT, _nState != PAGE_DBSETUPWIZARD_FINAL );
pPage->Show();
+
+ m_xAssistant->set_page_title(sIdent, getStateDisplayName(_nState));
}
return pPage;
}
@@ -606,7 +603,7 @@ IMPL_LINK_NOARG(ODbTypeWizDialogSetup, OnSingleDocumentChosen, OGeneralPageWizar
void ODbTypeWizDialogSetup::enterState(WizardState _nState)
{
m_sURL = dbaui::ODbDataSourceAdministrationHelper::getDatasourceType(*m_pOutSet);
- RoadmapWizard::enterState(_nState);
+ RoadmapWizardMachine::enterState(_nState);
switch(_nState)
{
case PAGE_DBSETUPWIZARD_INTRO:
@@ -622,7 +619,7 @@ void ODbTypeWizDialogSetup::enterState(WizardState _nState)
void ODbTypeWizDialogSetup::saveDatasource()
{
- SfxTabPage* pPage = static_cast<SfxTabPage*>(WizardDialog::GetPage(getCurrentState()));
+ SfxTabPage* pPage = static_cast<SfxTabPage*>(GetPage(getCurrentState()));
if ( pPage )
pPage->FillItemSet(m_pOutSet.get());
}
@@ -635,14 +632,13 @@ bool ODbTypeWizDialogSetup::leaveState(WizardState _nState)
{
resetPages(m_pImpl->getCurrentDataSource());
}
- SfxTabPage* pPage = static_cast<SfxTabPage*>(WizardDialog::GetPage(_nState));
+ SfxTabPage* pPage = static_cast<SfxTabPage*>(GetPage(_nState));
return pPage && pPage->DeactivatePage(m_pOutSet.get()) != DeactivateRC::KeepPage;
}
-void ODbTypeWizDialogSetup::setTitle(const OUString& /*_sTitle*/)
+void ODbTypeWizDialogSetup::setTitle(const OUString& _sTitle)
{
- OSL_FAIL( "ODbTypeWizDialogSetup::setTitle: not implemented!" );
- // why?
+ m_xAssistant->set_title(_sTitle);
}
void ODbTypeWizDialogSetup::enableConfirmSettings( bool /*_bEnable*/ )
@@ -779,7 +775,7 @@ bool ODbTypeWizDialogSetup::SaveDatabaseDocument()
bool bRet = false;
::sfx2::FileDialogHelper aFileDlg(
ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
- FileDialogFlags::NONE, GetFrameWeld());
+ FileDialogFlags::NONE, m_xAssistant.get());
std::shared_ptr<const SfxFilter> pFilter = getStandardDatabaseFilter();
if ( pFilter )
{
@@ -971,7 +967,7 @@ bool ODbTypeWizDialogSetup::SaveDatabaseDocument()
// wants us to load could be a non-database document. Instead, we asynchronously
// open the selected document. Thus, the wizard's return value is RET_CANCEL,
// which means to not continue loading the database document
- if ( !OWizardMachine::Finish() )
+ if ( !WizardMachine::Finish() )
return false;
try
@@ -993,7 +989,7 @@ bool ODbTypeWizDialogSetup::SaveDatabaseDocument()
skipUntil(PAGE_DBSETUPWIZARD_FINAL);
}
if (getCurrentState() == PAGE_DBSETUPWIZARD_FINAL)
- return SaveDatabaseDocument() && OWizardMachine::onFinish();
+ return SaveDatabaseDocument() && WizardMachine::onFinish();
else
{
enableButtons( WizardButtonFlags::FINISH, false );
diff --git a/dbaccess/source/ui/dlg/generalpage.cxx b/dbaccess/source/ui/dlg/generalpage.cxx
index 2ed044a43795..5fe9655c37e9 100644
--- a/dbaccess/source/ui/dlg/generalpage.cxx
+++ b/dbaccess/source/ui/dlg/generalpage.cxx
@@ -239,6 +239,7 @@ namespace dbaui
{
implSetCurrentType( dbaccess::ODsnTypeCollection::getEmbeddedDatabase() );
sDisplayName = m_pCollection->getTypeDisplayName( m_eCurrentSelection );
+ onTypeSelected(m_eCurrentSelection);
}
// select the correct datasource type
@@ -451,6 +452,7 @@ namespace dbaui
, m_xFT_EmbeddedDBLabel(m_xBuilder->weld_label("embeddeddbLabel"))
, m_xEmbeddedDBType(m_xBuilder->weld_combo_box("embeddeddbList"))
, m_xFT_DocListLabel(m_xBuilder->weld_label("docListLabel"))
+ , m_xFT_HelpText(m_xBuilder->weld_label("helpText"))
, m_xLB_DocumentList(new OpenDocumentListBox(m_xBuilder->weld_combo_box("documentList"), "com.sun.star.sdb.OfficeDatabaseDocument"))
, m_xPB_OpenDatabase(new OpenDocumentButton(m_xBuilder->weld_button("openDatabase"), "com.sun.star.sdb.OfficeDatabaseDocument"))
, m_eOriginalCreationMode(eCreateNew)
@@ -482,7 +484,7 @@ namespace dbaui
// do some knittings
m_xEmbeddedDBType->connect_changed(LINK(this, OGeneralPageWizard, OnEmbeddedDBTypeSelected));
- m_xRB_CreateDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnCreateDatabaseModeSelected ) );
+ m_xRB_CreateDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
m_xRB_ConnectDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
m_xRB_OpenExistingDatabase->connect_clicked( LINK( this, OGeneralPageWizard, OnSetupModeSelected ) );
m_xLB_DocumentList->connect_changed( LINK( this, OGeneralPageWizard, OnDocumentSelected ) );
@@ -532,18 +534,13 @@ namespace dbaui
m_xFT_DocListLabel->set_sensitive( false );
m_xLB_DocumentList->set_sensitive( false );
}
- else
- {
- m_xDatasourceType->set_sensitive( false );
- m_xPB_OpenDatabase->set_sensitive( false );
- m_xFT_DocListLabel->set_sensitive( false );
- m_xLB_DocumentList->set_sensitive( false );
- }
if (m_xLB_DocumentList->get_count())
m_xLB_DocumentList->set_active(0);
m_eOriginalCreationMode = GetDatabaseCreationMode();
+
+ SetupModeSelected();
}
OUString OGeneralPageWizard::getDatasourceName(const SfxItemSet& _rSet)
@@ -620,12 +617,8 @@ namespace dbaui
return m_xLB_DocumentList->GetSelectedDocumentURL();
}
- IMPL_LINK_NOARG( OGeneralPageWizard, OnCreateDatabaseModeSelected, weld::Button&, void )
+ void OGeneralPageWizard::EnableControls()
{
- m_aCreationModeHandler.Call( *this );
-
- OnEmbeddedDBTypeSelected( *m_xEmbeddedDBType );
-
bool bValid, bReadonly;
getFlags( GetItemSet(), bValid, bReadonly );
if ( bValid && !bReadonly )
@@ -639,22 +632,21 @@ namespace dbaui
}
}
- IMPL_LINK_NOARG( OGeneralPageWizard, OnSetupModeSelected, weld::Button&, void )
+ void OGeneralPageWizard::SetupModeSelected()
{
m_aCreationModeHandler.Call( *this );
- OnDatasourceTypeSelected(*m_xDatasourceType);
- bool bValid, bReadonly;
- getFlags( GetItemSet(), bValid, bReadonly );
- if ( bValid && !bReadonly )
- {
- m_xEmbeddedDBType->set_sensitive(m_xRB_CreateDatabase->get_active());
- m_xFT_EmbeddedDBLabel->set_sensitive(m_xRB_CreateDatabase->get_active());
- m_xDatasourceType->set_sensitive(m_xRB_ConnectDatabase->get_active());
- m_xPB_OpenDatabase->set_sensitive(m_xRB_OpenExistingDatabase->get_active());
- m_xFT_DocListLabel->set_sensitive(m_xRB_OpenExistingDatabase->get_active());
- m_xLB_DocumentList->set_sensitive(m_xRB_OpenExistingDatabase->get_active());
- }
+ if (m_xRB_CreateDatabase->get_active())
+ OnEmbeddedDBTypeSelected(*m_xEmbeddedDBType);
+ else
+ OnDatasourceTypeSelected(*m_xDatasourceType);
+
+ EnableControls();
+ }
+
+ IMPL_LINK_NOARG( OGeneralPageWizard, OnSetupModeSelected, weld::Button&, void )
+ {
+ SetupModeSelected();
}
IMPL_LINK_NOARG( OGeneralPageWizard, OnDocumentSelected, weld::ComboBox&, void )
diff --git a/dbaccess/source/ui/dlg/generalpage.hxx b/dbaccess/source/ui/dlg/generalpage.hxx
index 359ed6641f82..63d8736ea38b 100644
--- a/dbaccess/source/ui/dlg/generalpage.hxx
+++ b/dbaccess/source/ui/dlg/generalpage.hxx
@@ -137,6 +137,7 @@ namespace dbaui
std::unique_ptr<weld::ComboBox> m_xEmbeddedDBType;
std::unique_ptr<weld::Label> m_xFT_DocListLabel;
+ std::unique_ptr<weld::Label> m_xFT_HelpText;
std::unique_ptr<OpenDocumentListBox> m_xLB_DocumentList;
std::unique_ptr<OpenDocumentButton> m_xPB_OpenDatabase;
@@ -151,6 +152,8 @@ namespace dbaui
bool m_bInitEmbeddedDBList : 1;
void insertEmbeddedDBTypeEntryData( const OUString& _sType, const OUString& sDisplayName );
+ void EnableControls();
+
public:
void SetCreationModeHandler( const Link<OGeneralPageWizard&,void>& _rHandler ) { m_aCreationModeHandler = _rHandler; }
CreationMode GetDatabaseCreationMode() const;
@@ -174,8 +177,9 @@ namespace dbaui
OUString getEmbeddedDBName( const SfxItemSet& _rSet );
void initializeEmbeddedDBList();
+ void SetupModeSelected();
+
DECL_LINK( OnEmbeddedDBTypeSelected, weld::ComboBox&, void );
- DECL_LINK( OnCreateDatabaseModeSelected, weld::Button&, void );
DECL_LINK( OnSetupModeSelected, weld::Button&, void );
DECL_LINK( OnDocumentSelected, weld::ComboBox&, void );
DECL_LINK( OnOpenDocument, weld::Button&, void );
diff --git a/dbaccess/source/ui/dlg/sqlmessage.cxx b/dbaccess/source/ui/dlg/sqlmessage.cxx
index f4e4204d9c4c..3bcb10c4ebcd 100644
--- a/dbaccess/source/ui/dlg/sqlmessage.cxx
+++ b/dbaccess/source/ui/dlg/sqlmessage.cxx
@@ -509,7 +509,7 @@ void OSQLMessageBox::impl_addDetailsButton()
if ( bMoreDetailsAvailable )
{
m_xDialog->add_button(Button::GetStandardText(StandardButtonType::More), RET_MORE);
- m_xMoreButton.reset(m_xDialog->get_widget_for_response(RET_MORE));
+ m_xMoreButton.reset(m_xDialog->weld_widget_for_response(RET_MORE));
m_xMoreButton->connect_clicked(LINK(this, OSQLMessageBox, ButtonClickHdl));
}
}
diff --git a/dbaccess/source/ui/inc/dbwizsetup.hxx b/dbaccess/source/ui/inc/dbwizsetup.hxx
index 25001361b3f5..16969b467ee3 100644
--- a/dbaccess/source/ui/inc/dbwizsetup.hxx
+++ b/dbaccess/source/ui/inc/dbwizsetup.hxx
@@ -54,7 +54,7 @@ class ODbDataSourceAdministrationHelper;
class OMySQLIntroPageSetup;
class OFinalDBPageSetup;
-class ODbTypeWizDialogSetup final : public vcl::RoadmapWizard , public IItemSetHelper, public IDatabaseSettingsDialog
+class ODbTypeWizDialogSetup final : public vcl::RoadmapWizardMachine, public IItemSetHelper, public IDatabaseSettingsDialog
{
private:
std::unique_ptr<ODbDataSourceAdministrationHelper> m_pImpl;
@@ -89,13 +89,12 @@ public:
/** ctor. The itemset given should have been created by <method>createItemSet</method> and should be destroyed
after the dialog has been destroyed
*/
- ODbTypeWizDialogSetup(vcl::Window* pParent
+ ODbTypeWizDialogSetup(weld::Window* pParent
,SfxItemSet const * _pItems
,const css::uno::Reference< css::uno::XComponentContext >& _rxORB
,const css::uno::Any& _aDataSourceName
);
virtual ~ODbTypeWizDialogSetup() override;
- virtual void dispose() override;
virtual const SfxItemSet* getOutputSet() const override;
virtual SfxItemSet* getWriteOutputSet() override;
diff --git a/dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx b/dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx
index f8d021055730..8361a2325cea 100644
--- a/dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx
+++ b/dbaccess/source/ui/uno/DBTypeWizDlgSetup.cxx
@@ -27,7 +27,7 @@
#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp>
#include <com/sun/star/sdbc/XDataSource.hpp>
#include <comphelper/processfactory.hxx>
-#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/svapp.hxx>
using namespace dbaui;
@@ -108,14 +108,14 @@ Reference<XPropertySetInfo> SAL_CALL ODBTypeWizDialogSetup::getPropertySetInfo(
svt::OGenericUnoDialog::Dialog ODBTypeWizDialogSetup::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
{
- return svt::OGenericUnoDialog::Dialog(VclPtr<ODbTypeWizDialogSetup>::Create(VCLUnoHelper::GetWindow(rParent), m_pDatasourceItems.get(), m_aContext, m_aInitialSelection));
+ return svt::OGenericUnoDialog::Dialog(std::make_unique<ODbTypeWizDialogSetup>(Application::GetFrameWeld(rParent), m_pDatasourceItems.get(), m_aContext, m_aInitialSelection));
}
void ODBTypeWizDialogSetup::executedDialog(sal_Int16 _nExecutionResult)
{
if ( _nExecutionResult == RET_OK )
{
- const ODbTypeWizDialogSetup* pDialog = static_cast<ODbTypeWizDialogSetup*>(m_aDialog.m_xVclDialog.get());
+ const ODbTypeWizDialogSetup* pDialog = static_cast<ODbTypeWizDialogSetup*>(m_aDialog.m_xWeldDialog.get());
m_bOpenDatabase = pDialog->IsDatabaseDocumentToBeOpened();
m_bStartTableWizard = pDialog->IsTableWizardToBeStarted();
}
diff --git a/dbaccess/uiconfig/ui/authentificationpage.ui b/dbaccess/uiconfig/ui/authentificationpage.ui
index 0c1a6a44a3b0..3515cb813f6b 100644
--- a/dbaccess/uiconfig/ui/authentificationpage.ui
+++ b/dbaccess/uiconfig/ui/authentificationpage.ui
@@ -34,8 +34,8 @@
<property name="margin_bottom">6</property>
<property name="label" translatable="yes" context="authentificationpage|helptext">Some databases require you to enter a user name.</property>
<property name="wrap">True</property>
- <property name="width_chars">60</property>
- <property name="max_width_chars">60</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
diff --git a/dbaccess/uiconfig/ui/databasewizard.ui b/dbaccess/uiconfig/ui/databasewizard.ui
new file mode 100644
index 000000000000..5f07332a825e
--- /dev/null
+++ b/dbaccess/uiconfig/ui/databasewizard.ui
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="dba">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAssistant" id="DatabaseWizard">
+ <property name="can_focus">True</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="databasewizard|DatabaseWizard">Database Wizard</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <property name="use_header_bar">0</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+</interface>
diff --git a/dbaccess/uiconfig/ui/dbasepage.ui b/dbaccess/uiconfig/ui/dbasepage.ui
index dfe64734364e..244b754d48bc 100644
--- a/dbaccess/uiconfig/ui/dbasepage.ui
+++ b/dbaccess/uiconfig/ui/dbasepage.ui
@@ -120,8 +120,8 @@
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="dbasepage|specMessageLabel">Note: When deleted, and thus inactive, records are displayed, you will not be able to delete records from the data source.</property>
<property name="wrap">True</property>
- <property name="width_chars">60</property>
- <property name="max_width_chars">60</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
diff --git a/dbaccess/uiconfig/ui/dbwizconnectionpage.ui b/dbaccess/uiconfig/ui/dbwizconnectionpage.ui
index 3d022c5307e7..81249794875d 100644
--- a/dbaccess/uiconfig/ui/dbwizconnectionpage.ui
+++ b/dbaccess/uiconfig/ui/dbwizconnectionpage.ui
@@ -33,7 +33,8 @@
<property name="margin_bottom">6</property>
<property name="label" translatable="yes" context="dbwizconnectionpage|helptext">label</property>
<property name="wrap">True</property>
- <property name="max_width_chars">60</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -46,6 +47,7 @@
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
@@ -92,6 +94,7 @@
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
<child>
<object class="GtkEntry" id="browseurl">
<property name="visible">True</property>
diff --git a/dbaccess/uiconfig/ui/dbwizmysqlintropage.ui b/dbaccess/uiconfig/ui/dbwizmysqlintropage.ui
index 8f1d39966b27..224f17189da2 100644
--- a/dbaccess/uiconfig/ui/dbwizmysqlintropage.ui
+++ b/dbaccess/uiconfig/ui/dbwizmysqlintropage.ui
@@ -23,7 +23,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
@@ -37,8 +36,8 @@
<property name="label" translatable="yes" context="dbwizmysqlintropage|label2">You can connect to a MySQL database using either ODBC or JDBC.
Please contact your system administrator if you are unsure about the following settings.</property>
<property name="wrap">True</property>
- <property name="width_chars">100</property>
- <property name="max_width_chars">100</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
diff --git a/dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui b/dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui
index 4eaa3ce7b4c1..5d2b38c6ecf4 100644
--- a/dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui
+++ b/dbaccess/uiconfig/ui/dbwizmysqlnativepage.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.22.1 -->
<interface domain="dba">
<requires lib="gtk+" version="3.18"/>
<object class="GtkBox" id="DBWizMysqlNativePage">
@@ -25,7 +25,6 @@
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
@@ -37,10 +36,11 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="xalign">0</property>
<property name="label" translatable="yes" context="dbwizmysqlnativepage|helptext">Please enter the required information to connect to a MySQL database.</property>
<property name="wrap">True</property>
- <property name="max_width_chars">100</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
+ <property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
diff --git a/dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui b/dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui
index 2dbe3dd2eb6b..ed65d12b29dc 100644
--- a/dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui
+++ b/dbaccess/uiconfig/ui/dbwizspreadsheetpage.ui
@@ -6,7 +6,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
- <property name="vexpand">True</property>
<property name="border_width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
@@ -24,7 +23,6 @@
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
@@ -40,7 +38,8 @@
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="wrap">True</property>
- <property name="max_width_chars">100</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -100,10 +99,12 @@
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
<child>
<object class="GtkEntry" id="browseurl">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="hexpand">True</property>
<property name="activates_default">True</property>
</object>
<packing>
@@ -127,6 +128,22 @@
<property name="top_attach">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="passwordrequired">
+ <property name="label" translatable="yes" context="dbwizspreadsheetpage|passwordrequired">_Password required</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">True</property>
@@ -154,21 +171,5 @@
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkCheckButton" id="passwordrequired">
- <property name="label" translatable="yes" context="dbwizspreadsheetpage|passwordrequired">_Password required</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
</object>
</interface>
diff --git a/dbaccess/uiconfig/ui/dbwiztextpage.ui b/dbaccess/uiconfig/ui/dbwiztextpage.ui
index bbb6600d4232..24b4e57a787f 100644
--- a/dbaccess/uiconfig/ui/dbwiztextpage.ui
+++ b/dbaccess/uiconfig/ui/dbwiztextpage.ui
@@ -24,7 +24,6 @@
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="top_padding">6</property>
- <property name="left_padding">12</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
@@ -40,7 +39,8 @@
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="wrap">True</property>
- <property name="max_width_chars">100</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -100,10 +100,12 @@
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
<child>
<object class="GtkEntry" id="browseurl">
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">1</property>
@@ -158,8 +160,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="border_width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
diff --git a/dbaccess/uiconfig/ui/finalpagewizard.ui b/dbaccess/uiconfig/ui/finalpagewizard.ui
index 919421029fa1..8e065ea1faa0 100644
--- a/dbaccess/uiconfig/ui/finalpagewizard.ui
+++ b/dbaccess/uiconfig/ui/finalpagewizard.ui
@@ -2,28 +2,28 @@
<!-- Generated with glade 3.22.1 -->
<interface domain="dba">
<requires lib="gtk+" version="3.18"/>
- <object class="GtkBox" id="PageFinal">
- <property name="width_request">400</property>
+ <object class="GtkGrid" id="PageFinal">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="border_width">8</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
<property name="orientation">vertical</property>
- <property name="spacing">12</property>
+ <property name="row_spacing">12</property>
<child>
<object class="GtkLabel" id="headerText">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="finalpagewizard|headerText">Decide How to Proceed After Saving the Database</property>
- <property name="wrap">True</property>
+ <property name="single_line_mode">True</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
@@ -42,7 +42,6 @@
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="finalpagewizard|helpText">Do you want the wizard to register the database in %PRODUCTNAME?</property>
<property name="wrap">True</property>
- <property name="wrap_mode">word-char</property>
<property name="width_chars">72</property>
<property name="max_width_chars">72</property>
<property name="xalign">0</property>
@@ -103,6 +102,7 @@
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="finalpagewizard|additionalText">After the database file has been saved, what do you want to do?</property>
<property name="wrap">True</property>
+ <property name="width_chars">72</property>
<property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
@@ -163,9 +163,8 @@
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
</object>
diff --git a/dbaccess/uiconfig/ui/generalpagewizard.ui b/dbaccess/uiconfig/ui/generalpagewizard.ui
index 8413935a4a34..32a666a71db9 100644
--- a/dbaccess/uiconfig/ui/generalpagewizard.ui
+++ b/dbaccess/uiconfig/ui/generalpagewizard.ui
@@ -2,34 +2,35 @@
<!-- Generated with glade 3.22.1 -->
<interface domain="dba">
<requires lib="gtk+" version="3.18"/>
- <object class="GtkBox" id="PageGeneral">
- <property name="width_request">400</property>
+ <object class="GtkGrid" id="PageGeneral">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="border_width">8</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
<property name="orientation">vertical</property>
- <property name="spacing">6</property>
+ <property name="row_spacing">6</property>
<child>
<object class="GtkLabel" id="headerText">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="generalpagewizard|headerText">Welcome to the %PRODUCTNAME Database Wizard</property>
- <property name="wrap">True</property>
+ <property name="single_line_mode">True</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="helpText">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="hexpand">True</property>
<property name="label" translatable="yes" context="generalpagewizard|helpText">Use the Database Wizard to create a new database, open an existing database file, or connect to a database stored on a server.</property>
<property name="wrap">True</property>
<property name="width_chars">72</property>
@@ -37,9 +38,8 @@
<property name="xalign">0</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
@@ -51,9 +51,8 @@
<property name="xalign">0</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
</packing>
</child>
<child>
@@ -69,9 +68,8 @@
<property name="draw_indicator">True</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">3</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
</packing>
</child>
<child>
@@ -108,9 +106,8 @@
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">4</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
</packing>
</child>
<child>
@@ -127,9 +124,8 @@
<property name="group">createDatabase</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">5</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
</packing>
</child>
<child>
@@ -167,9 +163,8 @@
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">6</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">6</property>
</packing>
</child>
<child>
@@ -183,9 +178,8 @@
<property name="always_show_image">True</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">7</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
</packing>
</child>
<child>
@@ -202,9 +196,8 @@
<property name="group">createDatabase</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">8</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">8</property>
</packing>
</child>
<child>
@@ -215,9 +208,8 @@
<property name="margin_left">24</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">9</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">9</property>
</packing>
</child>
<child>
@@ -226,9 +218,8 @@
<property name="xalign">0</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">10</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">10</property>
</packing>
</child>
</object>
diff --git a/dbaccess/uiconfig/ui/jdbcconnectionpage.ui b/dbaccess/uiconfig/ui/jdbcconnectionpage.ui
index 0df26ed00151..9e55d4e0e7ae 100644
--- a/dbaccess/uiconfig/ui/jdbcconnectionpage.ui
+++ b/dbaccess/uiconfig/ui/jdbcconnectionpage.ui
@@ -33,7 +33,8 @@
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="jdbcconnectionpage|helptext">Please enter the required information to connect to a JDBC database. Please contact your system administrator if you are unsure about the following settings.</property>
<property name="wrap">True</property>
- <property name="max_width_chars">60</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
diff --git a/dbaccess/uiconfig/ui/ldapconnectionpage.ui b/dbaccess/uiconfig/ui/ldapconnectionpage.ui
index e386c06102d2..a64373d9d43e 100644
--- a/dbaccess/uiconfig/ui/ldapconnectionpage.ui
+++ b/dbaccess/uiconfig/ui/ldapconnectionpage.ui
@@ -37,8 +37,8 @@
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="ldapconnectionpage|helpLabel">Please enter the required information to connect to an LDAP directory. Please contact your system administrator if you are unsure about the following settings.</property>
<property name="wrap">True</property>
- <property name="width_chars">80</property>
- <property name="max_width_chars">80</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
diff --git a/dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui b/dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui
index 8fa89c34d21c..c63f6a2c03e4 100644
--- a/dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui
+++ b/dbaccess/uiconfig/ui/specialjdbcconnectionpage.ui
@@ -38,8 +38,8 @@
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="specialjdbcconnectionpage|helpLabel">Please enter the required information to connect to a MySQL database using JDBC. Note that a JDBC driver class must be installed on your system and registered with %PRODUCTNAME. Please contact your system administrator if you are unsure about the following settings. </property>
<property name="wrap">True</property>
- <property name="width_chars">80</property>
- <property name="max_width_chars">80</property>
+ <property name="width_chars">72</property>
+ <property name="max_width_chars">72</property>
<property name="xalign">0</property>
</object>
<packing>
@@ -133,6 +133,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
+ <property name="activates_default">True</property>
<property name="adjustment">adjustment1</property>
</object>
<packing>
diff --git a/include/svtools/helpids.h b/include/svtools/helpids.h
index 0c296ba613c2..ce1b29cf6cd6 100644
--- a/include/svtools/helpids.h
+++ b/include/svtools/helpids.h
@@ -45,9 +45,6 @@
#define HID_FILEOPEN_IMAGE_TEMPLATE "SVT_HID_FILEOPEN_IMAGE_TEMPLATE"
#define HID_FILEOPEN_IMAGE_ANCHOR "SVT_HID_FILEOPEN_IMAGE_ANCHOR"
-#define HID_WIZARD_NEXT "SVT_HID_WIZARD_NEXT"
-#define HID_WIZARD_PREVIOUS "SVT_HID_WIZARD_PREVIOUS"
-
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/tools/wintypes.hxx b/include/tools/wintypes.hxx
index 4fa4eab908f9..5bcaec41aa17 100644
--- a/include/tools/wintypes.hxx
+++ b/include/tools/wintypes.hxx
@@ -257,7 +257,10 @@ enum class StandardButtonType
Ignore = 8,
Abort = 9,
Less = 10,
- Count = 11,
+ Back = 11,
+ Next = 12,
+ Finish = 13,
+ Count = 14,
};
// prominent place for ListBox window types
diff --git a/include/vcl/roadmapwizard.hxx b/include/vcl/roadmapwizard.hxx
index 6764d40f8c6e..df0632af5085 100644
--- a/include/vcl/roadmapwizard.hxx
+++ b/include/vcl/roadmapwizard.hxx
@@ -75,6 +75,12 @@ namespace vcl
void SetRoadmapInteractive( bool _bInteractive );
+ void InsertRoadmapItem(int nIndex, const OUString& rLabel, int nId, bool bEnabled);
+ void DeleteRoadmapItems();
+ int GetCurrentRoadmapItemID() const;
+ void SelectRoadmapItemByID(int nId);
+ void SetItemSelectHdl( const Link<LinkParamNone*,void>& _rHdl );
+
// returns whether a given state is enabled
bool isStateEnabled( WizardState _nState ) const;
@@ -213,6 +219,146 @@ namespace vcl
VCL_DLLPRIVATE void impl_construct();
};
+ class VCL_DLLPUBLIC RoadmapWizardMachine : public vcl::WizardMachine, public RoadmapWizardTypes
+ {
+ private:
+ std::unique_ptr<RoadmapWizardImpl> m_pImpl;
+
+ public:
+ RoadmapWizardMachine(weld::Window* _pParent);
+ virtual ~RoadmapWizardMachine( ) override;
+
+ void SetRoadmapHelpId( const OString& _rId );
+
+ void SetRoadmapInteractive( bool _bInteractive );
+
+ // returns whether a given state is enabled
+ bool isStateEnabled( WizardState _nState ) const;
+
+ // WizardDialog overridables
+ virtual bool canAdvance() const override;
+ virtual void updateTravelUI() override;
+
+ protected:
+ /** declares a valid path in the wizard
+
+ The very first path which is declared is automatically activated.
+
+ Note that all paths which are declared must have the very first state in
+ common. Also note that due to a restriction of the very base class (WizardDialog),
+ this common first state must be 0.
+
+ You cannot declare new paths once the wizard started, so it's recommended that
+ you do all declarations within your derivee's constructor.
+
+ @see activatePath
+
+ @param _nId
+ the unique id you wish to give this path. This id can later on be used
+ to refer to the path which you just declared
+ */
+ void declarePath( PathId _nPathId, const WizardPath& _lWizardStates);
+
+ /** provides basic information about a state
+
+ The given display name is used in the default implementation of getStateDisplayName,
+ and the given factory is used in the default implementation of createPage.
+ */
+ void describeState( WizardState _nState, const OUString& _rStateDisplayName, RoadmapPageFactory _pPageFactory );
+
+ /** activates a path which has previously been declared with <member>declarePath</member>
+
+ You can only activate paths which share the first <code>k</code> states with the path
+ which is previously active (if any), where <code>k</code> is the index of the
+ current state within the current path.
+
+ <example>
+ Say you have paths, <code>(0,1,2,5)</code> and <code>(0,1,4,5)</code>. This means that after
+ step <code>1</code>, you either continue with state <code>2</code> or state <code>4</code>,
+ and after this, you finish in state <code>5</code>.<br/>
+ Now if the first path is active, and your current state is <code>1</code>, then you can
+ easily switch to the second path, since both paths start with <code>(0,1)</code>.<br/>
+ However, if your current state is <code>2</code>, then you can not switch to the second
+ path anymore.
+ </example>
+
+ @param _nPathId
+ the id of the path. The path must have been declared (under this id) with
+ <member>declarePath</member> before it can be activated.
+
+ @param _bDecideForIt
+ If <TRUE/>, the path will be completely activated, even if it is a conflicting path
+ (i.e. there is another path which shares the first <code>k</code> states with
+ the to-be-activated path.)<br/>
+ If <FALSE/>, then the new path is checked for conflicts with other paths. If such
+ conflicts exists, the path is not completely activated, but only up to the point
+ where it does <em>not</em> conflict.<br/>
+ With the paths in the example above, if you activate the second path (when both are
+ already declared), then only steps <code>0</code> and <code>1</code> are activated,
+ since they are common to both paths.
+ */
+ void activatePath( PathId _nPathId, bool _bDecideForIt = false );
+
+ /** determine the next state to travel from the given one
+
+ This method (which is declared in OWizardMachine and overwritten here)
+ ensures that traveling happens along the active path.
+
+ @see activatePath
+ */
+ virtual WizardState determineNextState( WizardState _nCurrentState ) const override;
+
+ /** en- or disables a state
+
+ In the wizard's roadmap, states to travel to can be freely chosen. To prevent
+ users from selecting a state which is currently not available, you can declare this
+ state as being disabled.
+
+ A situation where you need this may be when you have a checkbox which, when checked
+ by the user, enables a page with additional settings. As long as this checkbox is
+ not checked, the respective state would be disabled.
+
+ Note that in theory, you can declare multiple paths, instead of disabling states.
+ For instance, if you have a path where one state can be potentially disabled, then
+ you could declare a second path, which does not contain this state. However, the
+ disadvantage is that then, not the complete path would be visible in the roadmap,
+ but only all steps up to the point where the both paths diverge.<br/>
+ Another disadvantage is that the number of needed paths grows exponentially with
+ the number of states which can be potentially disabled.
+
+ @see declarePath
+ */
+ void enableState( WizardState _nState, bool _bEnable = true );
+
+ /** returns true if and only if the given state is known in at least one declared path
+ */
+ bool knowsState( WizardState _nState ) const;
+
+ // OWizardMachine overriables
+ virtual void enterState( WizardState _nState ) override;
+
+ /** returns a human readable name for a given state
+
+ There is a default implementation for this method, which returns the display name
+ as given in a call to describeState. If there is no description for the given state,
+ this is worth an assertion in a non-product build, and then an empty string is
+ returned.
+ */
+ virtual OUString getStateDisplayName( WizardState _nState ) const;
+
+ /** asks for a new label of the wizard page
+
+ */
+ void updateRoadmapItemLabel( WizardState _nState );
+
+ private:
+ DECL_DLLPRIVATE_LINK( OnRoadmapItemSelected, const OString&, bool );
+
+ /** updates the roadmap control to show the given path, as far as possible
+ (modulo conflicts with other paths)
+ */
+ VCL_DLLPRIVATE void implUpdateRoadmap( );
+ };
} // namespace vcl
diff --git a/include/vcl/vclenum.hxx b/include/vcl/vclenum.hxx
index 1e8f59428e3f..c7ced830da49 100644
--- a/include/vcl/vclenum.hxx
+++ b/include/vcl/vclenum.hxx
@@ -273,6 +273,21 @@ enum class VclPolicyType
NEVER
};
+enum class WizardButtonFlags : sal_Int16
+{
+ NONE = 0x0000,
+ NEXT = 0x0001,
+ PREVIOUS = 0x0002,
+ FINISH = 0x0004,
+ CANCEL = 0x0008,
+ HELP = 0x0010,
+};
+
+namespace o3tl
+{
+ template<> struct typed_flags<WizardButtonFlags> : is_typed_flags<WizardButtonFlags, 0x001f> {};
+}
+
#endif // INCLUDED_VCL_VCLENUM_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 198b7a72f0d6..d4b688243c68 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -250,6 +250,8 @@ class VCL_DLLPUBLIC Container : virtual public Widget
public:
//remove and add in one go
virtual void move(weld::Widget* pWidget, weld::Container* pNewParent) = 0;
+ //recursively unset has-default on any buttons in the widget hierarchy
+ virtual void recursively_unset_default_buttons() = 0;
};
class VCL_DLLPUBLIC ScrolledWindow : virtual public Container
@@ -423,7 +425,7 @@ public:
virtual void add_button(const OUString& rText, int response, const OString& rHelpId = OString())
= 0;
virtual void set_default_response(int response) = 0;
- virtual Button* get_widget_for_response(int response) = 0;
+ virtual Button* weld_widget_for_response(int response) = 0;
virtual Container* weld_content_area() = 0;
// shrink the dialog down to shown just these widgets
@@ -457,6 +459,30 @@ public:
virtual void set_background(const css::uno::Reference<css::graphic::XGraphic>& rImage) = 0;
};
+class VCL_DLLPUBLIC Assistant : virtual public Dialog
+{
+protected:
+ Link<const OString&, bool> m_aJumpPageHdl;
+
+ bool signal_jump_page(const OString& rIdent) { return m_aJumpPageHdl.Call(rIdent); }
+
+public:
+ virtual int get_current_page() const = 0;
+ virtual int get_n_pages() const = 0;
+ virtual OString get_page_ident(int nPage) const = 0;
+ virtual OString get_current_page_ident() const = 0;
+ virtual void set_current_page(int nPage) = 0;
+ virtual void set_current_page(const OString& rIdent) = 0;
+ // move the page rIdent to position nIndex
+ virtual void set_page_index(const OString& rIdent, int nIndex) = 0;
+ virtual void set_page_title(const OString& rIdent, const OUString& rTitle) = 0;
+ virtual OUString get_page_title(const OString& rIdent) const = 0;
+ virtual void set_page_sensitive(const OString& rIdent, bool bSensitive) = 0;
+ virtual weld::Container* append_page(const OString& rIdent) = 0;
+
+ void connect_jump_page(const Link<const OString&, bool>& rLink) { m_aJumpPageHdl = rLink; }
+};
+
struct VCL_DLLPUBLIC ComboBoxEntry
{
OUString sString;
@@ -1785,6 +1811,8 @@ public:
virtual std::unique_ptr<AboutDialog> weld_about_dialog(const OString& id,
bool bTakeOwnership = true)
= 0;
+ virtual std::unique_ptr<Assistant> weld_assistant(const OString& id, bool bTakeOwnership = true)
+ = 0;
virtual std::unique_ptr<Window> weld_window(const OString& id, bool bTakeOwnership = true) = 0;
virtual std::unique_ptr<Widget> weld_widget(const OString& id, bool bTakeOwnership = false) = 0;
virtual std::unique_ptr<Container> weld_container(const OString& id,
@@ -1907,6 +1935,18 @@ public:
OUString get_primary_text() const { return m_xDialog->get_primary_text(); }
void set_default_response(int nResponse) { m_xDialog->set_default_response(nResponse); }
};
+
+class VCL_DLLPUBLIC AssistantController : public DialogController
+{
+protected:
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Assistant> m_xAssistant;
+
+public:
+ AssistantController(weld::Widget* pParent, const OUString& rUIFile, const OString& rDialogId);
+ virtual Dialog* getDialog() override;
+ virtual ~AssistantController() override;
+};
}
#endif
diff --git a/include/vcl/wizardmachine.hxx b/include/vcl/wizardmachine.hxx
index 0b0afbce1576..c840af3f0745 100644
--- a/include/vcl/wizardmachine.hxx
+++ b/include/vcl/wizardmachine.hxx
@@ -31,20 +31,6 @@ namespace weld {
class Container;
}
-enum class WizardButtonFlags
-{
- NONE = 0x0000,
- NEXT = 0x0001,
- PREVIOUS = 0x0002,
- FINISH = 0x0004,
- CANCEL = 0x0008,
- HELP = 0x0010,
-};
-namespace o3tl
-{
- template<> struct typed_flags<WizardButtonFlags> : is_typed_flags<WizardButtonFlags, 0x001f> {};
-}
-
namespace vcl
{
@@ -152,9 +138,6 @@ namespace vcl
class VCL_DLLPUBLIC OWizardMachine : public WizardDialog, public WizardTypes
{
private:
- // restrict access to some aspects of our base class
- using WizardDialog::AddPage;
- using WizardDialog::SetPage;
// TabPage* GetPage( sal_uInt16 nLevel ) const { return WizardDialog::GetPage(nLevel); }
// TODO: probably the complete page handling (next, previous etc.) should be prohibited ...
@@ -163,7 +146,7 @@ namespace vcl
// here (e.g. committing page data) depend on having full control over page traveling.
// So use the travelXXX methods if you need to travel
- protected:
+ public:
VclPtr<OKButton> m_pFinish;
VclPtr<CancelButton> m_pCancel;
VclPtr<PushButton> m_pNextPage;
@@ -358,23 +341,245 @@ namespace vcl
VCL_DLLPRIVATE void implConstruct( const WizardButtonFlags _nButtonFlags );
};
+ class VCL_DLLPUBLIC WizardMachine : public weld::AssistantController, public WizardTypes
+ {
+ private:
+ VclPtr<TabPage> m_xCurTabPage;
+
+ WizardState m_nCurState;
+ ImplWizPageData* m_pFirstPage;
+
+ protected:
+ std::unique_ptr<weld::Button> m_xFinish;
+ std::unique_ptr<weld::Button> m_xCancel;
+ std::unique_ptr<weld::Button> m_xNextPage;
+ std::unique_ptr<weld::Button> m_xPrevPage;
+ std::unique_ptr<weld::Button> m_xHelp;
+
+ private:
+ // hold members in this structure to allow keeping compatible when members are added
+ std::unique_ptr<WizardMachineImplData> m_pImpl;
+
+ public:
+ WizardMachine(weld::Window* _pParent, WizardButtonFlags _nButtonFlags );
+ virtual ~WizardMachine() override;
+
+ bool Finish(short nResult = RET_CANCEL);
+ bool ShowPage(WizardState nState);
+
+ void AddPage( TabPage* pPage );
+ void SetPage( WizardState nLevel, TabPage* pPage );
+ TabPage* GetPage( WizardState eState ) const;
+
+ /// enable (or disable) buttons
+ void enableButtons(WizardButtonFlags _nWizardButtonFlags, bool _bEnable);
+ /// set the default style for a button
+ void defaultButton(WizardButtonFlags _nWizardButtonFlags);
+ /// set the default style for a button
+ void defaultButton(weld::Button* _pNewDefButton);
+
+ /// set the base of the title to use - the title of the current page is appended
+ void setTitleBase(const OUString& _rTitleBase);
+
+ /// determines whether there is a next state to which we can advance
+ virtual bool canAdvance() const;
+
+ /** updates the user interface which deals with traveling in the wizard
+
+ The default implementation simply checks whether both the current page and the wizard
+ itself allow to advance to the next state (<code>canAdvance</code>), and enables the "Next"
+ button if and only if this is the case.
+ */
+ virtual void updateTravelUI();
+
+ protected:
+ // WizardDialog overridables
+ virtual void ActivatePage();
+ virtual bool DeactivatePage();
+
+ // our own overridables
+
+ /// to override to create new pages
+ virtual VclPtr<TabPage> createPage(WizardState _nState) = 0;
+
+ /// will be called when a new page is about to be displayed
+ virtual void enterState(WizardState _nState);
+
+ /** will be called when the current state is about to be left for the given reason
+
+ The base implementation in this class will simply call <member>OWizardPage::commitPage</member>
+ for the current page, and return whatever this call returns.
+
+ @param _eReason
+ The reason why the state is to be left.
+ @return
+ <TRUE/> if and only if the page is allowed to be left
+ */
+ virtual bool prepareLeaveCurrentState( CommitPageReason _eReason );
+
+ /** will be called when the given state is left
+
+ This is the very last possibility for derived classes to veto the deactivation
+ of a page.
+
+ @todo Normally, we would not need the return value here - derived classes now have
+ the possibility to veto page deactivations in <member>prepareLeaveCurrentState</member>. However,
+ changing this return type is too incompatible at the moment ...
+
+ @return
+ <TRUE/> if and only if the page is allowed to be left
+ */
+ virtual bool leaveState( WizardState _nState );
+
+ /** determine the next state to travel from the given one
+
+ The default behaviour is linear traveling, overwrite this to change it
+
+ Return WZS_INVALID_STATE to prevent traveling.
+ */
+ virtual WizardState determineNextState( WizardState _nCurrentState ) const;
+
+ /** called when the finish button is pressed
+ <p>By default, only the base class' Finish method (which is not virtual) is called</p>
+ */
+ virtual bool onFinish();
+
+ /// travel to the next state
+ bool travelNext();
+
+ /// travel to the previous state
+ bool travelPrevious();
+
+ /** enables the automatic enabled/disabled state of the "Next" button
+
+ If this is <TRUE/>, then upon entering a new state, the "Next" button will automatically be
+ enabled if and only if determineNextState does not return WZS_INVALID_STATE.
+ */
+ void enableAutomaticNextButtonState();
+ bool isAutomaticNextButtonStateEnabled() const;
+
+ /** removes a page from the history. Should be called when the page is being disabled
+ */
+ void removePageFromHistory( WizardState nToRemove );
+
+ /** skip a state
+
+ The method behaves as if from the current state, <arg>_nSteps</arg> <method>travelNext</method>s were
+ called, but without actually creating or displaying the \EDntermediate pages. Only the
+ (<arg>_nSteps</arg> + 1)th page is created.
+
+ The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
+
+ A very essential precondition for using this method is that your <method>determineNextState</method>
+ method is able to determine the next state without actually having the page of the current state.
+
+ @see skipUntil
+ @see skipBackwardUntil
+ */
+ void skip();
+
+ /** skips one or more states, until a given state is reached
+
+ The method behaves as if from the current state, <method>travelNext</method>s were called
+ successively, until <arg>_nTargetState</arg> is reached, but without actually creating or
+ displaying the \EDntermediate pages.
+
+ The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.
+
+ @return
+ <TRUE/> if and only if traveling was successful
+
+ @see skip
+ @see skipBackwardUntil
+ */
+ bool skipUntil( WizardState _nTargetState );
+
+ /** moves back one or more states, until a given state is reached
+
+ This method allows traveling backwards more than one state without actually showing the intermediate
+ states.
+
+ For instance, if you want to travel two steps backward at a time, you could used
+ two travelPrevious calls, but this would <em>show</em> both pages, which is not necessary,
+ since you're interested in the target page only. Using <member>skipBackwardUntil</member> relieves
+ you of this.
+
+ @return
+ <TRUE/> if and only if traveling was successful
+
+ @see skipUntil
+ @see skip
+ */
+ bool skipBackwardUntil( WizardState _nTargetState );
+
+ /** returns the current state of the machine
+
+ Vulgo, this is the identifier of the current tab page :)
+ */
+ WizardState getCurrentState() const { return m_nCurState; }
+
+ virtual IWizardPageController*
+ getPageController( TabPage* _pCurrentPage ) const;
+
+ /** retrieves a copy of the state history, i.e. all states we already visited
+ */
+ void getStateHistory( ::std::vector< WizardState >& _out_rHistory );
+
+ public:
+ class AccessGuard
+ {
+ friend class WizardTravelSuspension;
+ private:
+ AccessGuard() { }
+ };
+
+ void suspendTraveling( AccessGuard );
+ void resumeTraveling( AccessGuard );
+ bool isTravelingSuspended() const;
+
+ protected:
+ TabPage* GetOrCreatePage( const WizardState i_nState );
+
+ private:
+ DECL_DLLPRIVATE_LINK(OnNextPage, weld::Button&, void);
+ DECL_DLLPRIVATE_LINK(OnPrevPage, weld::Button&, void);
+ DECL_DLLPRIVATE_LINK(OnFinish, weld::Button&, void);
+ DECL_DLLPRIVATE_LINK(OnCancel, weld::Button&, void);
+
+ VCL_DLLPRIVATE void implUpdateTitle();
+ VCL_DLLPRIVATE void implConstruct( const WizardButtonFlags _nButtonFlags );
+ };
+
+
/// helper class to temporarily suspend any traveling in the wizard
class WizardTravelSuspension
{
public:
- WizardTravelSuspension( OWizardMachine& _rWizard )
- :m_rWizard( _rWizard )
+ WizardTravelSuspension(OWizardMachine& rWizard)
+ : m_pOWizard(&rWizard)
+ , m_pWizard(nullptr)
+ {
+ m_pOWizard->suspendTraveling(OWizardMachine::AccessGuard());
+ }
+
+ WizardTravelSuspension(WizardMachine& rWizard)
+ : m_pOWizard(nullptr)
+ , m_pWizard(&rWizard)
{
- m_rWizard.suspendTraveling( OWizardMachine::AccessGuard() );
+ m_pWizard->suspendTraveling(WizardMachine::AccessGuard());
}
~WizardTravelSuspension()
{
- m_rWizard.resumeTraveling( OWizardMachine::AccessGuard() );
+ if (m_pOWizard)
+ m_pOWizard->resumeTraveling(OWizardMachine::AccessGuard());
+ if (m_pWizard)
+ m_pWizard->resumeTraveling(WizardMachine::AccessGuard());
}
private:
- OWizardMachine& m_rWizard;
+ VclPtr<OWizardMachine> m_pOWizard;
+ WizardMachine* m_pWizard;
};
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 66b5e3d1bbe2..e0f3ad3f35c3 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -50,6 +50,7 @@
#include <vcl/menubtn.hxx>
#include <vcl/prgsbar.hxx>
#include <vcl/ptrstyle.hxx>
+#include <vcl/roadmapwizard.hxx>
#include <vcl/slider.hxx>
#include <vcl/sysdata.hxx>
#include <vcl/svimpbox.hxx>
@@ -966,6 +967,35 @@ class SalInstanceContainer : public SalInstanceWidget, public virtual weld::Cont
{
private:
VclPtr<vcl::Window> m_xContainer;
+
+ void implResetDefault(const vcl::Window* _pWindow)
+ {
+ vcl::Window* pChildLoop = _pWindow->GetWindow(GetWindowType::FirstChild);
+ while (pChildLoop)
+ {
+ // does the window participate in the tabbing order?
+ if (pChildLoop->GetStyle() & WB_DIALOGCONTROL)
+ implResetDefault(pChildLoop);
+
+ // is it a button?
+ WindowType eType = pChildLoop->GetType();
+ if ( (WindowType::PUSHBUTTON == eType)
+ || (WindowType::OKBUTTON == eType)
+ || (WindowType::CANCELBUTTON == eType)
+ || (WindowType::HELPBUTTON == eType)
+ || (WindowType::IMAGEBUTTON == eType)
+ || (WindowType::MENUBUTTON == eType)
+ || (WindowType::MOREBUTTON == eType)
+ )
+ {
+ pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON);
+ }
+
+ // the next one ...
+ pChildLoop = pChildLoop->GetWindow(GetWindowType::Next);
+ }
+ }
+
public:
SalInstanceContainer(vcl::Window* pContainer, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
: SalInstanceWidget(pContainer, pBuilder, bTakeOwnership)
@@ -980,6 +1010,10 @@ public:
assert(!pNewParent || pNewVclParent);
pVclWidget->getWidget()->SetParent(pNewVclParent ? pNewVclParent->getWidget() : nullptr);
}
+ virtual void recursively_unset_default_buttons() override
+ {
+ implResetDefault(m_xContainer.get());
+ }
};
std::unique_ptr<weld::Container> SalInstanceWidget::weld_parent() const
@@ -1358,7 +1392,7 @@ public:
return m_xDialog->IsModalInputMode();
}
- virtual weld::Button* get_widget_for_response(int nResponse) override;
+ virtual weld::Button* weld_widget_for_response(int nResponse) override;
virtual void set_default_response(int nResponse) override
{
@@ -1448,6 +1482,218 @@ public:
}
};
+class SalInstanceAssistant : public SalInstanceDialog, public virtual weld::Assistant
+{
+private:
+ VclPtr<vcl::RoadmapWizard> m_xWizard;
+ std::vector<std::unique_ptr<SalInstanceContainer>> m_aPages;
+ std::vector<VclPtr<TabPage>> m_aAddedPages;
+ std::vector<int> m_aIds;
+ std::vector<VclPtr<VclGrid>> m_aAddedGrids;
+ Idle m_aUpdateRoadmapIdle;
+
+ int find_page(const OString& rIdent) const
+ {
+ for (size_t i = 0; i < m_aAddedPages.size(); ++i)
+ {
+ if (m_aAddedPages[i]->get_id().toUtf8() == rIdent)
+ return i;
+ }
+ return -1;
+ }
+
+ int find_id(int nId) const
+ {
+ for (size_t i = 0; i < m_aIds.size(); ++i)
+ {
+ if (nId == m_aIds[i])
+ return i;
+ }
+ return -1;
+ }
+
+ DECL_LINK(OnRoadmapItemSelected, LinkParamNone*, void);
+ DECL_LINK(UpdateRoadmap_Hdl, Timer*, void);
+
+public:
+ SalInstanceAssistant(vcl::RoadmapWizard* pDialog, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
+ : SalInstanceDialog(pDialog, pBuilder, bTakeOwnership)
+ , m_xWizard(pDialog)
+ {
+ m_xWizard->SetItemSelectHdl(LINK(this, SalInstanceAssistant, OnRoadmapItemSelected));
+
+ m_aUpdateRoadmapIdle.SetInvokeHandler(LINK(this, SalInstanceAssistant, UpdateRoadmap_Hdl));
+ m_aUpdateRoadmapIdle.SetPriority(TaskPriority::HIGHEST);
+ }
+
+ virtual int get_current_page() const override
+ {
+ return find_id(m_xWizard->GetCurLevel());
+ }
+
+ virtual int get_n_pages() const override
+ {
+ return m_aAddedPages.size();
+ }
+
+ virtual OString get_page_ident(int nPage) const override
+ {
+ return m_aAddedPages[nPage]->get_id().toUtf8();
+ }
+
+ virtual OString get_current_page_ident() const override
+ {
+ return get_page_ident(get_current_page());
+ }
+
+ virtual void set_current_page(int nPage) override
+ {
+ disable_notify_events();
+
+ // take the first shown page as the size for all pages
+ if (m_xWizard->GetPageSizePixel().Width() == 0)
+ {
+ TabPage* pPage = m_xWizard->GetPage(m_aIds[nPage]);
+ assert(pPage);
+ Size aPageSize(pPage->get_preferred_size());
+ m_xWizard->SetPageSizePixel(aPageSize);
+ }
+
+ m_xWizard->ShowPage(m_aIds[nPage]);
+ enable_notify_events();
+ }
+
+ virtual void set_current_page(const OString& rIdent) override
+ {
+ int nIndex = find_page(rIdent);
+ if (nIndex == -1)
+ return;
+ set_current_page(nIndex);
+ }
+
+ virtual void set_page_index(const OString& rIdent, int nNewIndex) override
+ {
+ int nOldIndex = find_page(rIdent);
+
+ if (nOldIndex == -1)
+ return;
+
+ if (nOldIndex == nNewIndex)
+ return;
+
+ disable_notify_events();
+
+ auto entry = std::move(m_aAddedPages[nOldIndex]);
+ m_aAddedPages.erase(m_aAddedPages.begin() + nOldIndex);
+ m_aAddedPages.insert(m_aAddedPages.begin() + nNewIndex, std::move(entry));
+
+ int nId = m_aIds[nOldIndex];
+ m_aIds.erase(m_aIds.begin() + nOldIndex);
+ m_aIds.insert(m_aIds.begin() + nNewIndex, nId);
+
+ m_aUpdateRoadmapIdle.Start();
+
+ enable_notify_events();
+ }
+
+ virtual weld::Container* append_page(const OString& rIdent) override
+ {
+ VclPtrInstance<TabPage> xPage(m_xWizard);
+ VclPtrInstance<VclGrid> xGrid(xPage);
+ xPage->set_id(OUString::fromUtf8(rIdent));
+ xPage->Show();
+ xGrid->set_hexpand(true);
+ xGrid->set_vexpand(true);
+ xGrid->Show();
+ m_xWizard->AddPage(xPage);
+ m_aIds.push_back(m_aAddedPages.size());
+ m_xWizard->SetPage(m_aIds.back(), xPage);
+ m_aAddedPages.push_back(xPage);
+ m_aAddedGrids.push_back(xGrid);
+
+ m_aUpdateRoadmapIdle.Start();
+
+ m_aPages.emplace_back(new SalInstanceContainer(xGrid, m_pBuilder, false));
+ return m_aPages.back().get();
+ }
+
+ virtual OUString get_page_title(const OString& rIdent) const override
+ {
+ int nIndex = find_page(rIdent);
+ if (nIndex == -1)
+ return OUString();
+ return m_aAddedPages[nIndex]->GetText();
+ }
+
+ virtual void set_page_title(const OString& rIdent, const OUString& rTitle) override
+ {
+ int nIndex = find_page(rIdent);
+ if (nIndex == -1)
+ return;
+ if (m_aAddedPages[nIndex]->GetText() != rTitle)
+ {
+ disable_notify_events();
+ m_aAddedPages[nIndex]->SetText(rTitle);
+ m_aUpdateRoadmapIdle.Start();
+ enable_notify_events();
+ }
+ }
+
+ virtual void set_page_sensitive(const OString& rIdent, bool bSensitive) override
+ {
+ int nIndex = find_page(rIdent);
+ if (nIndex == -1)
+ return;
+ if (m_aAddedPages[nIndex]->IsEnabled() != bSensitive)
+ {
+ disable_notify_events();
+ m_aAddedPages[nIndex]->Enable(bSensitive);
+ m_aUpdateRoadmapIdle.Start();
+ enable_notify_events();
+ }
+ }
+
+ weld::Button* weld_widget_for_response(int nResponse) override;
+
+ virtual ~SalInstanceAssistant() override
+ {
+ for (auto &rGrid : m_aAddedGrids)
+ rGrid.disposeAndClear();
+ for (auto &rPage : m_aAddedPages)
+ rPage.disposeAndClear();
+ }
+};
+
+IMPL_LINK_NOARG(SalInstanceAssistant, OnRoadmapItemSelected, LinkParamNone*, void)
+{
+ if (notify_events_disabled())
+ return;
+ int nPageIndex(find_id(m_xWizard->GetCurrentRoadmapItemID()));
+ if (!signal_jump_page(get_page_ident(nPageIndex)))
+ m_xWizard->SelectRoadmapItemByID(m_xWizard->GetCurLevel());
+}
+
+IMPL_LINK_NOARG(SalInstanceAssistant, UpdateRoadmap_Hdl, Timer*, void)
+{
+ disable_notify_events();
+
+ m_xWizard->DeleteRoadmapItems();
+
+ int nPos = 0;
+ for (size_t i = 0; i < m_aAddedPages.size(); ++i)
+ {
+ const OUString& rLabel = m_aAddedPages[i]->GetText();
+ bool bSensitive = m_aAddedPages[i]->IsEnabled();
+ if (rLabel.isEmpty())
+ continue;
+ m_xWizard->InsertRoadmapItem(nPos++, rLabel, m_aIds[i], bSensitive);
+ }
+
+ m_xWizard->SelectRoadmapItemByID(m_aIds[get_current_page()]);
+
+ enable_notify_events();
+}
+
class SalInstanceFrame : public SalInstanceContainer, public virtual weld::Frame
{
private:
@@ -1978,12 +2224,30 @@ IMPL_LINK(SalInstanceButton, ClickHdl, ::Button*, pButton, void)
signal_clicked();
}
-weld::Button* SalInstanceDialog::get_widget_for_response(int nResponse)
+weld::Button* SalInstanceDialog::weld_widget_for_response(int nResponse)
{
PushButton* pButton = dynamic_cast<PushButton*>(m_xDialog->get_widget_for_response(nResponse));
return pButton ? new SalInstanceButton(pButton, nullptr, false) : nullptr;
}
+weld::Button* SalInstanceAssistant::weld_widget_for_response(int nResponse)
+{
+ PushButton* pButton = nullptr;
+ if (nResponse == static_cast<int>(WizardButtonFlags::NEXT))
+ pButton = m_xWizard->m_pNextPage;
+ else if (nResponse == static_cast<int>(WizardButtonFlags::PREVIOUS))
+ pButton = m_xWizard->m_pPrevPage;
+ else if (nResponse == static_cast<int>(WizardButtonFlags::FINISH))
+ pButton = m_xWizard->m_pFinish;
+ else if (nResponse == static_cast<int>(WizardButtonFlags::CANCEL))
+ pButton = m_xWizard->m_pCancel;
+ else if (nResponse == static_cast<int>(WizardButtonFlags::HELP))
+ pButton = m_xWizard->m_pHelp;
+ if (pButton)
+ return new SalInstanceButton(pButton, nullptr, false);
+ return nullptr;
+}
+
class SalInstanceMenuButton : public SalInstanceButton, public virtual weld::MenuButton
{
private:
@@ -5286,6 +5550,19 @@ public:
return pRet;
}
+ virtual std::unique_ptr<weld::Assistant> weld_assistant(const OString &id, bool bTakeOwnership) override
+ {
+ vcl::RoadmapWizard* pDialog = m_xBuilder->get<vcl::RoadmapWizard>(id);
+ std::unique_ptr<weld::Assistant> pRet(pDialog ? new SalInstanceAssistant(pDialog, this, false) : nullptr);
+ if (bTakeOwnership && pDialog)
+ {
+ assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed");
+ m_aOwnedToplevel.set(pDialog);
+ m_xBuilder->drop_ownership(pDialog);
+ }
+ return pRet;
+ }
+
virtual std::unique_ptr<weld::Window> weld_window(const OString &id, bool bTakeOwnership) override
{
SystemWindow* pWindow = m_xBuilder->get<SystemWindow>(id);
@@ -5676,6 +5953,18 @@ namespace weld
}
}
+ AssistantController::AssistantController(weld::Widget* pParent, const OUString &rUIFile, const OString& rDialogId)
+ : m_xBuilder(Application::CreateBuilder(pParent, rUIFile))
+ , m_xAssistant(m_xBuilder->weld_assistant(rDialogId))
+ {
+ }
+
+ Dialog* AssistantController::getDialog() { return m_xAssistant.get(); }
+
+ AssistantController::~AssistantController()
+ {
+ }
+
void TriStateEnabled::ButtonToggled(weld::ToggleButton& rToggle)
{
if (bTriStateEnabled)
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index 8a076fadceb9..8669e655479f 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -145,6 +145,9 @@ OUString Button::GetStandardText(StandardButtonType eButton)
SV_BUTTONTEXT_IGNORE,
SV_BUTTONTEXT_ABORT,
SV_BUTTONTEXT_LESS,
+ STR_WIZDLG_PREVIOUS,
+ STR_WIZDLG_NEXT,
+ STR_WIZDLG_FINISH,
};
return VclResId(aResIdAry[static_cast<sal_uInt16>(eButton)]);
diff --git a/vcl/source/control/roadmapwizard.cxx b/vcl/source/control/roadmapwizard.cxx
index ec27bb6dae82..2d29a71aa47a 100644
--- a/vcl/source/control/roadmapwizard.cxx
+++ b/vcl/source/control/roadmapwizard.cxx
@@ -124,6 +124,13 @@ namespace vcl
impl_construct();
}
+ RoadmapWizardMachine::RoadmapWizardMachine(weld::Window* pParent)
+ : WizardMachine(pParent, WizardButtonFlags::NEXT | WizardButtonFlags::PREVIOUS | WizardButtonFlags::FINISH | WizardButtonFlags::CANCEL | WizardButtonFlags::HELP)
+ , m_pImpl( new RoadmapWizardImpl )
+ {
+ m_xAssistant->connect_jump_page(LINK(this, RoadmapWizardMachine, OnRoadmapItemSelected));
+ }
+
void RoadmapWizard::impl_construct()
{
SetLeftAlignedButtonCount( 1 );
@@ -143,12 +150,15 @@ namespace vcl
m_pImpl->pRoadmap->Show();
}
-
RoadmapWizard::~RoadmapWizard()
{
disposeOnce();
}
+ RoadmapWizardMachine::~RoadmapWizardMachine()
+ {
+ }
+
void RoadmapWizard::dispose()
{
m_pImpl.reset();
@@ -160,12 +170,15 @@ namespace vcl
m_pImpl->pRoadmap->SetHelpId( _rId );
}
-
void RoadmapWizard::SetRoadmapInteractive( bool _bInteractive )
{
m_pImpl->pRoadmap->SetRoadmapInteractive( _bInteractive );
}
+ void RoadmapWizardMachine::SetRoadmapInteractive( bool _bInteractive )
+ {
+ m_pImpl->pRoadmap->SetRoadmapInteractive( _bInteractive );
+ }
void RoadmapWizard::declarePath( PathId _nPathId, const WizardPath& _lWizardStates)
{
@@ -179,6 +192,17 @@ namespace vcl
implUpdateRoadmap( );
}
+ void RoadmapWizardMachine::declarePath( PathId _nPathId, const WizardPath& _lWizardStates)
+ {
+
+ m_pImpl->aPaths.emplace( _nPathId, _lWizardStates );
+
+ if ( m_pImpl->aPaths.size() == 1 )
+ // the very first path -> activate it
+ activatePath( _nPathId );
+ else
+ implUpdateRoadmap( );
+ }
void RoadmapWizard::describeState( WizardState _nState, const OUString& _rStateDisplayName, RoadmapPageFactory _pPageFactory )
{
@@ -187,7 +211,6 @@ namespace vcl
m_pImpl->aStateDescriptors[ _nState ] = StateDescriptions::mapped_type( _rStateDisplayName, _pPageFactory );
}
-
void RoadmapWizard::activatePath( PathId _nPathId, bool _bDecideForIt )
{
@@ -231,6 +254,47 @@ namespace vcl
implUpdateRoadmap( );
}
+ void RoadmapWizardMachine::activatePath( PathId _nPathId, bool _bDecideForIt )
+ {
+ if ( ( _nPathId == m_pImpl->nActivePath ) && ( _bDecideForIt == m_pImpl->bActivePathIsDefinite ) )
+ // nothing to do
+ return;
+
+ // does the given path exist?
+ Paths::const_iterator aNewPathPos = m_pImpl->aPaths.find( _nPathId );
+ DBG_ASSERT( aNewPathPos != m_pImpl->aPaths.end(), "RoadmapWizard::activate: there is no such path!" );
+ if ( aNewPathPos == m_pImpl->aPaths.end() )
+ return;
+
+ // determine the index of the current state in the current path
+ sal_Int32 nCurrentStatePathIndex = -1;
+ if ( m_pImpl->nActivePath != -1 )
+ nCurrentStatePathIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath );
+
+ DBG_ASSERT( static_cast<sal_Int32>(aNewPathPos->second.size()) > nCurrentStatePathIndex,
+ "RoadmapWizard::activate: you cannot activate a path which has less states than we've already advanced!" );
+ // If this asserts, this for instance means that we are already in state number, say, 5
+ // of our current path, and the caller tries to activate a path which has less than 5
+ // states
+ if ( static_cast<sal_Int32>(aNewPathPos->second.size()) <= nCurrentStatePathIndex )
+ return;
+
+ // assert that the current and the new path are equal, up to nCurrentStatePathIndex
+ Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath );
+ if ( aActivePathPos != m_pImpl->aPaths.end() )
+ {
+ if ( RoadmapWizardImpl::getFirstDifferentIndex( aActivePathPos->second, aNewPathPos->second ) <= nCurrentStatePathIndex )
+ {
+ OSL_FAIL( "RoadmapWizard::activate: you cannot activate a path which conflicts with the current one *before* the current state!" );
+ return;
+ }
+ }
+
+ m_pImpl->nActivePath = _nPathId;
+ m_pImpl->bActivePathIsDefinite = _bDecideForIt;
+
+ implUpdateRoadmap( );
+ }
void RoadmapWizard::implUpdateRoadmap( )
{
@@ -337,6 +401,110 @@ namespace vcl
m_pImpl->pRoadmap->SetRoadmapComplete( !bIncompletePath );
}
+ void RoadmapWizardMachine::implUpdateRoadmap( )
+ {
+
+ DBG_ASSERT( m_pImpl->aPaths.find( m_pImpl->nActivePath ) != m_pImpl->aPaths.end(),
+ "RoadmapWizard::implUpdateRoadmap: there is no such path!" );
+ const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
+
+ sal_Int32 nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
+ if (nCurrentStatePathIndex < 0)
+ return;
+
+ // determine up to which index (in the new path) we have to display the items
+ RoadmapTypes::ItemIndex nUpperStepBoundary = static_cast<RoadmapTypes::ItemIndex>(rActivePath.size());
+ if ( !m_pImpl->bActivePathIsDefinite )
+ {
+ for (auto const& path : m_pImpl->aPaths)
+ {
+ if ( path.first == m_pImpl->nActivePath )
+ // it's the path we are just activating -> no need to check anything
+ continue;
+ // the index from which on both paths differ
+ sal_Int32 nDivergenceIndex = RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
+ if ( nDivergenceIndex <= nCurrentStatePathIndex )
+ // they differ in an index which we have already left behind us
+ // -> this is no conflict anymore
+ continue;
+
+ // the path conflicts with our new path -> don't activate the
+ // *complete* new path, but only up to the step which is unambiguous
+ nUpperStepBoundary = nDivergenceIndex;
+ }
+ }
+
+ // can we advance from the current page?
+ bool bCurrentPageCanAdvance = true;
+ TabPage* pCurrentPage = GetPage( getCurrentState() );
+ if ( pCurrentPage )
+ {
+ const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
+ OSL_ENSURE( pController != nullptr, "RoadmapWizard::implUpdateRoadmap: no controller for the current page!" );
+ bCurrentPageCanAdvance = !pController || pController->canAdvance();
+ }
+
+ // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active
+ // path, up to (excluding) nUpperStepBoundary
+ RoadmapTypes::ItemIndex nRoadmapItems = m_xAssistant->get_n_pages();
+ RoadmapTypes::ItemIndex nLoopUntil = ::std::max( nUpperStepBoundary, nRoadmapItems );
+ for ( RoadmapTypes::ItemIndex nItemIndex = nCurrentStatePathIndex; nItemIndex < nLoopUntil; ++nItemIndex )
+ {
+ bool bExistentItem = ( nItemIndex < nRoadmapItems );
+ bool bNeedItem = ( nItemIndex < nUpperStepBoundary );
+
+ bool bInsertItem = false;
+ if ( bExistentItem )
+ {
+ if ( !bNeedItem )
+ {
+ int nPages = nRoadmapItems;
+ for (int i = nPages - 1; i >= nItemIndex; --i)
+ {
+ m_xAssistant->set_page_title(m_xAssistant->get_page_ident(i), "");
+ --nRoadmapItems;
+ }
+ break;
+ }
+ else
+ {
+ // there is an item with this index in the roadmap - does it match what is requested by
+ // the respective state in the active path?
+ RoadmapTypes::ItemId nPresentItemId = m_xAssistant->get_page_ident(nItemIndex).toInt32();
+ WizardState nRequiredState = rActivePath[ nItemIndex ];
+ if ( nPresentItemId != nRequiredState )
+ {
+ m_xAssistant->set_page_title(OString::number(nPresentItemId), "");
+ bInsertItem = true;
+ }
+ }
+ }
+ else
+ {
+ DBG_ASSERT( bNeedItem, "RoadmapWizard::implUpdateRoadmap: ehm - none needed, none present - why did the loop not terminate?" );
+ bInsertItem = bNeedItem;
+ }
+
+ WizardState nState( rActivePath[ nItemIndex ] );
+
+ if ( bInsertItem )
+ {
+ GetOrCreatePage(nState);
+ }
+
+ OString sIdent(OString::number(nState));
+ m_xAssistant->set_page_index(sIdent, nItemIndex);
+ m_xAssistant->set_page_title(sIdent, getStateDisplayName(nState));
+
+ // if the item is *after* the current state, but the current page does not
+ // allow advancing, the disable the state. This relieves derived classes
+ // from disabling all future states just because the current state does not
+ // (yet) allow advancing.
+ const bool bUnconditionedDisable = !bCurrentPageCanAdvance && ( nItemIndex > nCurrentStatePathIndex );
+ const bool bEnable = !bUnconditionedDisable && ( m_pImpl->aDisabledStates.find( nState ) == m_pImpl->aDisabledStates.end() );
+ m_xAssistant->set_page_sensitive(sIdent, bEnable);
+ }
+ }
WizardTypes::WizardState RoadmapWizard::determineNextState( WizardState _nCurrentState ) const
{
@@ -367,6 +535,33 @@ namespace vcl
return aActivePathPos->second[ nNextStateIndex ];
}
+ WizardTypes::WizardState RoadmapWizardMachine::determineNextState( WizardState _nCurrentState ) const
+ {
+ sal_Int32 nCurrentStatePathIndex = -1;
+
+ Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath );
+ if ( aActivePathPos != m_pImpl->aPaths.end() )
+ nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( _nCurrentState, aActivePathPos->second );
+
+ DBG_ASSERT( nCurrentStatePathIndex != -1, "RoadmapWizard::determineNextState: ehm - how can we travel if there is no (valid) active path?" );
+ if ( nCurrentStatePathIndex == -1 )
+ return WZS_INVALID_STATE;
+
+ sal_Int32 nNextStateIndex = nCurrentStatePathIndex + 1;
+
+ while ( ( nNextStateIndex < static_cast<sal_Int32>(aActivePathPos->second.size()) )
+ && ( m_pImpl->aDisabledStates.find( aActivePathPos->second[ nNextStateIndex ] ) != m_pImpl->aDisabledStates.end() )
+ )
+ {
+ ++nNextStateIndex;
+ }
+
+ if ( nNextStateIndex >= static_cast<sal_Int32>(aActivePathPos->second.size()) )
+ // there is no next state in the current path (at least none which is enabled)
+ return WZS_INVALID_STATE;
+
+ return aActivePathPos->second[ nNextStateIndex ];
+ }
bool RoadmapWizard::canAdvance() const
{
@@ -398,6 +593,35 @@ namespace vcl
return *rPath.rbegin() != getCurrentState();
}
+ bool RoadmapWizardMachine::canAdvance() const
+ {
+ if ( !m_pImpl->bActivePathIsDefinite )
+ {
+ // check how many paths are still allowed
+ const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
+ sal_Int32 nCurrentStatePathIndex = RoadmapWizardImpl::getStateIndexInPath( getCurrentState(), rActivePath );
+
+ size_t nPossiblePaths(0);
+ for (auto const& path : m_pImpl->aPaths)
+ {
+ // the index from which on both paths differ
+ sal_Int32 nDivergenceIndex = RoadmapWizardImpl::getFirstDifferentIndex( rActivePath, path.second );
+
+ if ( nDivergenceIndex > nCurrentStatePathIndex )
+ // this path is still a possible path
+ nPossiblePaths += 1;
+ }
+
+ // if we have more than one path which is still possible, then we assume
+ // to always have a next state. Though there might be scenarios where this
+ // is not true, but this is too sophisticated (means not really needed) right now.
+ if ( nPossiblePaths > 1 )
+ return true;
+ }
+
+ const WizardPath& rPath = m_pImpl->aPaths[ m_pImpl->nActivePath ];
+ return *rPath.rbegin() != getCurrentState();
+ }
void RoadmapWizard::updateTravelUI()
{
@@ -421,6 +645,27 @@ namespace vcl
implUpdateRoadmap();
}
+ void RoadmapWizardMachine::updateTravelUI()
+ {
+ WizardMachine::updateTravelUI();
+
+ // disable the "Previous" button if all states in our history are disabled
+ ::std::vector< WizardState > aHistory;
+ getStateHistory( aHistory );
+ bool bHaveEnabledState = false;
+ for (auto const& state : aHistory)
+ {
+ if ( isStateEnabled(state) )
+ {
+ bHaveEnabledState = true;
+ break;
+ }
+ }
+
+ enableButtons( WizardButtonFlags::PREVIOUS, bHaveEnabledState );
+
+ implUpdateRoadmap();
+ }
IMPL_LINK_NOARG(RoadmapWizard, OnRoadmapItemSelected, LinkParamNone*, void)
{
@@ -463,10 +708,48 @@ namespace vcl
m_pImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() );
}
+ IMPL_LINK(RoadmapWizardMachine, OnRoadmapItemSelected, const OString&, rCurItemId, bool)
+ {
+ int nCurItemId = rCurItemId.toInt32();
+
+ if ( nCurItemId == getCurrentState() )
+ // nothing to do
+ return false;
+
+ if ( isTravelingSuspended() )
+ return false;
+
+ WizardTravelSuspension aTravelGuard( *this );
+
+ sal_Int32 nCurrentIndex = m_pImpl->getStateIndexInPath( getCurrentState(), m_pImpl->nActivePath );
+ sal_Int32 nNewIndex = m_pImpl->getStateIndexInPath( nCurItemId, m_pImpl->nActivePath );
+
+ DBG_ASSERT( ( nCurrentIndex != -1 ) && ( nNewIndex != -1 ),
+ "RoadmapWizard::OnRoadmapItemSelected: something's wrong here!" );
+ if ( ( nCurrentIndex == -1 ) || ( nNewIndex == -1 ) )
+ {
+ return false;
+ }
+
+ bool bResult = true;
+ if ( nNewIndex > nCurrentIndex )
+ {
+ bResult = skipUntil( static_cast<WizardState>(nCurItemId) );
+ WizardState nTemp = static_cast<WizardState>(nCurItemId);
+ while( nTemp )
+ {
+ if( m_pImpl->aDisabledStates.find( --nTemp ) != m_pImpl->aDisabledStates.end() )
+ removePageFromHistory( nTemp );
+ }
+ }
+ else
+ bResult = skipBackwardUntil( static_cast<WizardState>(nCurItemId) );
+
+ return bResult;
+ }
void RoadmapWizard::enterState( WizardState _nState )
{
-
OWizardMachine::enterState( _nState );
// synchronize the roadmap
@@ -474,6 +757,13 @@ namespace vcl
m_pImpl->pRoadmap->SelectRoadmapItemByID( getCurrentState() );
}
+ void RoadmapWizardMachine::enterState( WizardState _nState )
+ {
+ WizardMachine::enterState( _nState );
+
+ // synchronize the roadmap
+ implUpdateRoadmap();
+ }
OUString RoadmapWizard::getStateDisplayName( WizardState _nState ) const
{
@@ -488,6 +778,18 @@ namespace vcl
return sDisplayName;
}
+ OUString RoadmapWizardMachine::getStateDisplayName( WizardState _nState ) const
+ {
+ OUString sDisplayName;
+
+ StateDescriptions::const_iterator pos = m_pImpl->aStateDescriptors.find( _nState );
+ OSL_ENSURE( pos != m_pImpl->aStateDescriptors.end(),
+ "RoadmapWizard::getStateDisplayName: no default implementation available for this state!" );
+ if ( pos != m_pImpl->aStateDescriptors.end() )
+ sDisplayName = pos->second.first;
+
+ return sDisplayName;
+ }
VclPtr<TabPage> RoadmapWizard::createPage( WizardState _nState )
{
@@ -505,7 +807,6 @@ namespace vcl
return pPage;
}
-
void RoadmapWizard::enableState( WizardState _nState, bool _bEnable )
{
@@ -522,6 +823,20 @@ namespace vcl
m_pImpl->pRoadmap->EnableRoadmapItem( static_cast<RoadmapTypes::ItemId>(_nState), _bEnable );
}
+ void RoadmapWizardMachine::enableState( WizardState _nState, bool _bEnable )
+ {
+ // remember this (in case the state appears in the roadmap later on)
+ if ( _bEnable )
+ m_pImpl->aDisabledStates.erase( _nState );
+ else
+ {
+ m_pImpl->aDisabledStates.insert( _nState );
+ removePageFromHistory( _nState );
+ }
+
+ // if the state is currently in the roadmap, reflect it's new status
+ m_xAssistant->set_page_sensitive(OString::number(_nState), _bEnable);
+ }
bool RoadmapWizard::knowsState( WizardState i_nState ) const
{
@@ -541,6 +856,11 @@ namespace vcl
return m_pImpl->aDisabledStates.find( _nState ) == m_pImpl->aDisabledStates.end();
}
+ bool RoadmapWizardMachine::isStateEnabled( WizardState _nState ) const
+ {
+ return m_pImpl->aDisabledStates.find( _nState ) == m_pImpl->aDisabledStates.end();
+ }
+
void RoadmapWizard::updateRoadmapItemLabel( WizardState _nState )
{
const WizardPath& rActivePath( m_pImpl->aPaths[ m_pImpl->nActivePath ] );
@@ -569,6 +889,32 @@ namespace vcl
}
}
+ void RoadmapWizard::InsertRoadmapItem(int nItemIndex, const OUString& rText, int nItemId, bool bEnable)
+ {
+ m_pImpl->pRoadmap->InsertRoadmapItem(nItemIndex, rText, nItemId, bEnable);
+ }
+
+ void RoadmapWizard::SelectRoadmapItemByID(int nItemId)
+ {
+ m_pImpl->pRoadmap->SelectRoadmapItemByID(nItemId);
+ }
+
+ void RoadmapWizard::DeleteRoadmapItems()
+ {
+ while (m_pImpl->pRoadmap->GetItemCount())
+ m_pImpl->pRoadmap->DeleteRoadmapItem(0);
+ }
+
+ void RoadmapWizard::SetItemSelectHdl( const Link<LinkParamNone*,void>& _rHdl )
+ {
+ m_pImpl->pRoadmap->SetItemSelectHdl(_rHdl);
+ }
+
+ int RoadmapWizard::GetCurrentRoadmapItemID() const
+ {
+ return m_pImpl->pRoadmap->GetCurrentRoadmapItemID();
+ }
+
} // namespace vcl
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/control/wizardmachine.cxx b/vcl/source/control/wizardmachine.cxx
index f42c509bff37..8a1a92a707f2 100644
--- a/vcl/source/control/wizardmachine.cxx
+++ b/vcl/source/control/wizardmachine.cxx
@@ -18,7 +18,6 @@
*/
#include <vcl/wizardmachine.hxx>
-#include <svtools/helpids.h>
#include <tools/debug.hxx>
#include <tools/diagnose_ex.h>
#include <vcl/svapp.hxx>
@@ -26,6 +25,15 @@
#include <svdata.hxx>
#include <stack>
+#define HID_WIZARD_NEXT "SVT_HID_WIZARD_NEXT"
+#define HID_WIZARD_PREVIOUS "SVT_HID_WIZARD_PREVIOUS"
+
+struct ImplWizPageData
+{
+ ImplWizPageData* mpNext;
+ VclPtr<TabPage> mpPage;
+};
+
namespace vcl
{
//= WizardPageImplData
@@ -360,14 +368,13 @@ namespace vcl
m_pCancel->Enable(_bEnable);
}
-
void OWizardMachine::enterState(WizardState _nState)
{
// tell the page
IWizardPageController* pController = getPageController( GetPage( _nState ) );
- OSL_ENSURE( pController, "OWizardMachine::enterState: no controller for the given page!" );
- if ( pController )
- pController->initializePage();
+ if (!pController)
+ return;
+ pController->initializePage();
if ( isAutomaticNextButtonStateEnabled() )
enableButtons( WizardButtonFlags::NEXT, canAdvance() );
@@ -378,7 +385,6 @@ namespace vcl
implUpdateTitle();
}
-
bool OWizardMachine::leaveState(WizardState)
{
// no need to ask the page here.
@@ -522,7 +528,6 @@ namespace vcl
// all fine
}
-
bool OWizardMachine::travelNext()
{
// allowed to leave the current page?
@@ -679,7 +684,586 @@ namespace vcl
m_pImpl->m_bTravelingSuspended = false;
}
+ WizardMachine::WizardMachine(weld::Window* pParent, WizardButtonFlags nButtonFlags)
+ : AssistantController(pParent, "dbaccess/ui/databasewizard.ui", "DatabaseWizard")
+ , m_nCurState(0)
+ , m_pFirstPage(nullptr)
+ , m_xFinish(m_xAssistant->weld_widget_for_response(static_cast<int>(WizardButtonFlags::FINISH)))
+ , m_xCancel(m_xAssistant->weld_widget_for_response(static_cast<int>(WizardButtonFlags::CANCEL)))
+ , m_xNextPage(m_xAssistant->weld_widget_for_response(static_cast<int>(WizardButtonFlags::NEXT)))
+ , m_xPrevPage(m_xAssistant->weld_widget_for_response(static_cast<int>(WizardButtonFlags::PREVIOUS)))
+ , m_xHelp(m_xAssistant->weld_widget_for_response(static_cast<int>(WizardButtonFlags::HELP)))
+ , m_pImpl(new WizardMachineImplData)
+ {
+ implConstruct(nButtonFlags);
+ }
+
+ void WizardMachine::implConstruct(const WizardButtonFlags nButtonFlags)
+ {
+ m_pImpl->sTitleBase = m_xAssistant->get_title();
+
+ // create the buttons according to the wizard button flags
+ // the help button
+ if (nButtonFlags & WizardButtonFlags::HELP)
+ {
+ m_xHelp->show();
+ }
+
+ // the previous button
+ if (nButtonFlags & WizardButtonFlags::PREVIOUS)
+ {
+ m_xPrevPage->set_help_id( HID_WIZARD_PREVIOUS );
+ m_xPrevPage->show();
+
+ m_xPrevPage->connect_clicked( LINK( this, WizardMachine, OnPrevPage ) );
+ }
+
+ // the next button
+ if (nButtonFlags & WizardButtonFlags::NEXT)
+ {
+ m_xNextPage->set_help_id( HID_WIZARD_NEXT );
+ m_xNextPage->show();
+
+ m_xNextPage->connect_clicked( LINK( this, WizardMachine, OnNextPage ) );
+ }
+
+ // the finish button
+ if (nButtonFlags & WizardButtonFlags::FINISH)
+ {
+ m_xFinish->show();
+
+ m_xFinish->connect_clicked( LINK( this, WizardMachine, OnFinish ) );
+ }
+
+ // the cancel button
+ if (nButtonFlags & WizardButtonFlags::CANCEL)
+ {
+ m_xCancel->show();
+ m_xCancel->connect_clicked( LINK( this, WizardMachine, OnCancel ) );
+ }
+ }
+
+ WizardMachine::~WizardMachine()
+ {
+ if (m_pImpl)
+ {
+ for (WizardState i = 0; i < m_pImpl->nFirstUnknownPage; ++i)
+ {
+ TabPage *pPage = GetPage(i);
+ if (pPage)
+ pPage->disposeOnce();
+ }
+ m_pImpl.reset();
+ }
+ }
+
+ void WizardMachine::implUpdateTitle()
+ {
+ OUString sCompleteTitle(m_pImpl->sTitleBase);
+
+ // append the page title
+ TabPage* pCurrentPage = GetPage(getCurrentState());
+ if ( pCurrentPage && !pCurrentPage->GetText().isEmpty() )
+ {
+ sCompleteTitle += " - " + pCurrentPage->GetText();
+ }
+
+ m_xAssistant->set_title(sCompleteTitle);
+ }
+
+ void WizardMachine::setTitleBase(const OUString& _rTitleBase)
+ {
+ m_pImpl->sTitleBase = _rTitleBase;
+ implUpdateTitle();
+ }
+
+ TabPage* WizardMachine::GetOrCreatePage( const WizardState i_nState )
+ {
+ if ( nullptr == GetPage( i_nState ) )
+ {
+ VclPtr<TabPage> pNewPage = createPage( i_nState );
+ DBG_ASSERT( pNewPage, "WizardMachine::GetOrCreatePage: invalid new page (NULL)!" );
+
+ // fill up the page sequence of our base class (with dummies)
+ while ( m_pImpl->nFirstUnknownPage < i_nState )
+ {
+ AddPage( nullptr );
+ ++m_pImpl->nFirstUnknownPage;
+ }
+
+ if ( m_pImpl->nFirstUnknownPage == i_nState )
+ {
+ // encountered this page number the first time
+ AddPage( pNewPage );
+ ++m_pImpl->nFirstUnknownPage;
+ }
+ else
+ // already had this page - just change it
+ SetPage( i_nState, pNewPage );
+ }
+ return GetPage( i_nState );
+ }
+
+ void WizardMachine::ActivatePage()
+ {
+ WizardState nCurrentLevel = m_nCurState;
+ GetOrCreatePage( nCurrentLevel );
+
+ enterState( nCurrentLevel );
+ }
+
+ bool WizardMachine::DeactivatePage()
+ {
+ WizardState nCurrentState = getCurrentState();
+ return leaveState(nCurrentState);
+ }
+
+ void WizardMachine::defaultButton(WizardButtonFlags _nWizardButtonFlags)
+ {
+ // the new default button
+ weld::Button* pNewDefButton = nullptr;
+ if (_nWizardButtonFlags & WizardButtonFlags::FINISH)
+ pNewDefButton = m_xFinish.get();
+ if (_nWizardButtonFlags & WizardButtonFlags::NEXT)
+ pNewDefButton = m_xNextPage.get();
+ if (_nWizardButtonFlags & WizardButtonFlags::PREVIOUS)
+ pNewDefButton = m_xPrevPage.get();
+ if (_nWizardButtonFlags & WizardButtonFlags::HELP)
+ pNewDefButton = m_xHelp.get();
+ if (_nWizardButtonFlags & WizardButtonFlags::CANCEL)
+ pNewDefButton = m_xCancel.get();
+
+ if ( pNewDefButton )
+ defaultButton( pNewDefButton );
+ else
+ m_xAssistant->recursively_unset_default_buttons();
+ }
+ void WizardMachine::defaultButton(weld::Button* _pNewDefButton)
+ {
+ // loop through all (direct and indirect) descendants which participate in our tabbing order, and
+ // reset the WB_DEFBUTTON for every window which is a button
+ m_xAssistant->recursively_unset_default_buttons();
+
+ // set its new style
+ if (_pNewDefButton)
+ _pNewDefButton->set_has_default(true);
+ }
+
+ void WizardMachine::enableButtons(WizardButtonFlags _nWizardButtonFlags, bool _bEnable)
+ {
+ if (_nWizardButtonFlags & WizardButtonFlags::FINISH)
+ m_xFinish->set_sensitive(_bEnable);
+ if (_nWizardButtonFlags & WizardButtonFlags::NEXT)
+ m_xNextPage->set_sensitive(_bEnable);
+ if (_nWizardButtonFlags & WizardButtonFlags::PREVIOUS)
+ m_xPrevPage->set_sensitive(_bEnable);
+ if (_nWizardButtonFlags & WizardButtonFlags::HELP)
+ m_xHelp->set_sensitive(_bEnable);
+ if (_nWizardButtonFlags & WizardButtonFlags::CANCEL)
+ m_xCancel->set_sensitive(_bEnable);
+ }
+
+ void WizardMachine::enterState(WizardState _nState)
+ {
+ // tell the page
+ IWizardPageController* pController = getPageController( GetPage( _nState ) );
+ OSL_ENSURE( pController, "WizardMachine::enterState: no controller for the given page!" );
+ if ( pController )
+ pController->initializePage();
+
+ if ( isAutomaticNextButtonStateEnabled() )
+ enableButtons( WizardButtonFlags::NEXT, canAdvance() );
+
+ enableButtons( WizardButtonFlags::PREVIOUS, !m_pImpl->aStateHistory.empty() );
+
+ // set the new title - it depends on the current page (i.e. state)
+ implUpdateTitle();
+ }
+
+ bool WizardMachine::leaveState(WizardState)
+ {
+ // no need to ask the page here.
+ // If we reach this point, we already gave the current page the chance to commit it's data,
+ // and it was allowed to commit it's data
+
+ return true;
+ }
+
+ bool WizardMachine::onFinish()
+ {
+ return Finish( RET_OK );
+ }
+
+ IMPL_LINK_NOARG(WizardMachine, OnFinish, weld::Button&, void)
+ {
+ if ( isTravelingSuspended() )
+ return;
+ WizardTravelSuspension aTravelGuard( *this );
+ if ( !prepareLeaveCurrentState( eFinish ) )
+ {
+ return;
+ }
+ onFinish();
+ }
+
+ IMPL_LINK_NOARG(WizardMachine, OnCancel, weld::Button&, void)
+ {
+ m_xAssistant->response(static_cast<int>(WizardButtonFlags::CANCEL));
+ }
+
+ WizardMachine::WizardState WizardMachine::determineNextState( WizardState _nCurrentState ) const
+ {
+ return _nCurrentState + 1;
+ }
+
+ bool WizardMachine::prepareLeaveCurrentState( CommitPageReason _eReason )
+ {
+ IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
+ ENSURE_OR_RETURN( pController != nullptr, "WizardMachine::prepareLeaveCurrentState: no controller for the current page!", true );
+ return pController->commitPage( _eReason );
+ }
+
+
+ bool WizardMachine::skipBackwardUntil( WizardState _nTargetState )
+ {
+ // allowed to leave the current page?
+ if ( !prepareLeaveCurrentState( eTravelBackward ) )
+ return false;
+
+ // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong
+ ::std::stack< WizardState > aTravelVirtually = m_pImpl->aStateHistory;
+ ::std::stack< WizardState > aOldStateHistory = m_pImpl->aStateHistory;
+
+ WizardState nCurrentRollbackState = getCurrentState();
+ while ( nCurrentRollbackState != _nTargetState )
+ {
+ DBG_ASSERT( !aTravelVirtually.empty(), "WizardMachine::skipBackwardUntil: this target state does not exist in the history!" );
+ nCurrentRollbackState = aTravelVirtually.top();
+ aTravelVirtually.pop();
+ }
+ m_pImpl->aStateHistory = aTravelVirtually;
+ if ( !ShowPage( _nTargetState ) )
+ {
+ m_pImpl->aStateHistory = aOldStateHistory;
+ return false;
+ }
+ return true;
+ }
+
+
+ bool WizardMachine::skipUntil( WizardState _nTargetState )
+ {
+ WizardState nCurrentState = getCurrentState();
+
+ // allowed to leave the current page?
+ if ( !prepareLeaveCurrentState( nCurrentState < _nTargetState ? eTravelForward : eTravelBackward ) )
+ return false;
+
+ // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong
+ ::std::stack< WizardState > aTravelVirtually = m_pImpl->aStateHistory;
+ ::std::stack< WizardState > aOldStateHistory = m_pImpl->aStateHistory;
+ while ( nCurrentState != _nTargetState )
+ {
+ WizardState nNextState = determineNextState( nCurrentState );
+ if ( WZS_INVALID_STATE == nNextState )
+ {
+ OSL_FAIL( "WizardMachine::skipUntil: the given target state does not exist!" );
+ return false;
+ }
+
+ // remember the skipped state in the history
+ aTravelVirtually.push( nCurrentState );
+
+ // get the next state
+ nCurrentState = nNextState;
+ }
+ m_pImpl->aStateHistory = aTravelVirtually;
+ // show the target page
+ if ( !ShowPage( nCurrentState ) )
+ {
+ // argh! prepareLeaveCurrentPage succeeded, determineNextState succeeded,
+ // but ShowPage doesn't? Somebody behaves very strange here ....
+ OSL_FAIL( "WizardMachine::skipUntil: very unpolite ...." );
+ m_pImpl->aStateHistory = aOldStateHistory;
+ return false;
+ }
+ return true;
+ }
+
+
+ void WizardMachine::skip()
+ {
+ // allowed to leave the current page?
+ if ( !prepareLeaveCurrentState( eTravelForward ) )
+ return;
+
+ WizardState nCurrentState = getCurrentState();
+ WizardState nNextState = determineNextState(nCurrentState);
+
+ if (WZS_INVALID_STATE == nNextState)
+ return;
+
+ // remember the skipped state in the history
+ m_pImpl->aStateHistory.push(nCurrentState);
+
+ // get the next state
+ nCurrentState = nNextState;
+
+ // show the (n+1)th page
+ if (!ShowPage(nCurrentState))
+ {
+ // TODO: this leaves us in a state where we have no current page and an inconsistent state history.
+ // Perhaps we should rollback the skipping here ....
+ OSL_FAIL("WizardMachine::skip: very unpolite ....");
+ // if somebody does a skip and then does not allow to leave ...
+ // (can't be a commit error, as we've already committed the current page. So if ShowPage fails here,
+ // somebody behaves really strange ...)
+ return;
+ }
+
+ // all fine
+ }
+
+ bool WizardMachine::travelNext()
+ {
+ // allowed to leave the current page?
+ if ( !prepareLeaveCurrentState( eTravelForward ) )
+ return false;
+
+ // determine the next state to travel to
+ WizardState nCurrentState = getCurrentState();
+ WizardState nNextState = determineNextState(nCurrentState);
+ if (WZS_INVALID_STATE == nNextState)
+ return false;
+
+ // the state history is used by the enterState method
+ // all fine
+ m_pImpl->aStateHistory.push(nCurrentState);
+ if (!ShowPage(nNextState))
+ {
+ m_pImpl->aStateHistory.pop();
+ return false;
+ }
+
+ return true;
+ }
+
+ bool WizardMachine::ShowPage(WizardState nState)
+ {
+ if (DeactivatePage())
+ {
+ TabPage* pOldTabPage = m_xCurTabPage;
+
+ m_nCurState = nState;
+ ActivatePage();
+
+ if (pOldTabPage)
+ pOldTabPage->DeactivatePage();
+
+ m_xAssistant->set_current_page(OString::number(nState));
+
+ m_xCurTabPage = GetPage(m_nCurState);
+ m_xCurTabPage->ActivatePage();
+
+ return true;
+ }
+ return false;
+ }
+
+ bool WizardMachine::travelPrevious()
+ {
+ DBG_ASSERT(!m_pImpl->aStateHistory.empty(), "WizardMachine::travelPrevious: have no previous page!");
+
+ // allowed to leave the current page?
+ if ( !prepareLeaveCurrentState( eTravelBackward ) )
+ return false;
+
+ // the next state to switch to
+ WizardState nPreviousState = m_pImpl->aStateHistory.top();
+
+ // the state history is used by the enterState method
+ m_pImpl->aStateHistory.pop();
+ // show this page
+ if (!ShowPage(nPreviousState))
+ {
+ m_pImpl->aStateHistory.push(nPreviousState);
+ return false;
+ }
+
+ // all fine
+ return true;
+ }
+
+
+ void WizardMachine::removePageFromHistory( WizardState nToRemove )
+ {
+
+ ::std::stack< WizardState > aTemp;
+ while(!m_pImpl->aStateHistory.empty())
+ {
+ WizardState nPreviousState = m_pImpl->aStateHistory.top();
+ m_pImpl->aStateHistory.pop();
+ if(nPreviousState != nToRemove)
+ aTemp.push( nPreviousState );
+ else
+ break;
+ }
+ while(!aTemp.empty())
+ {
+ m_pImpl->aStateHistory.push( aTemp.top() );
+ aTemp.pop();
+ }
+ }
+
+
+ void WizardMachine::enableAutomaticNextButtonState()
+ {
+ m_pImpl->m_bAutoNextButtonState = true;
+ }
+
+
+ bool WizardMachine::isAutomaticNextButtonStateEnabled() const
+ {
+ return m_pImpl->m_bAutoNextButtonState;
+ }
+
+ IMPL_LINK_NOARG(WizardMachine, OnPrevPage, weld::Button&, void)
+ {
+ if ( isTravelingSuspended() )
+ return;
+ WizardTravelSuspension aTravelGuard( *this );
+ travelPrevious();
+ }
+
+ IMPL_LINK_NOARG(WizardMachine, OnNextPage, weld::Button&, void)
+ {
+ if ( isTravelingSuspended() )
+ return;
+ WizardTravelSuspension aTravelGuard( *this );
+ travelNext();
+ }
+
+ IWizardPageController* WizardMachine::getPageController( TabPage* _pCurrentPage ) const
+ {
+ IWizardPageController* pController = dynamic_cast< IWizardPageController* >( _pCurrentPage );
+ return pController;
+ }
+
+
+ void WizardMachine::getStateHistory( ::std::vector< WizardState >& _out_rHistory )
+ {
+ ::std::stack< WizardState > aHistoryCopy( m_pImpl->aStateHistory );
+ while ( !aHistoryCopy.empty() )
+ {
+ _out_rHistory.push_back( aHistoryCopy.top() );
+ aHistoryCopy.pop();
+ }
+ }
+
+
+ bool WizardMachine::canAdvance() const
+ {
+ return WZS_INVALID_STATE != determineNextState( getCurrentState() );
+ }
+
+
+ void WizardMachine::updateTravelUI()
+ {
+ const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
+ OSL_ENSURE( pController != nullptr, "RoadmapWizard::updateTravelUI: no controller for the current page!" );
+
+ bool bCanAdvance =
+ ( !pController || pController->canAdvance() ) // the current page allows to advance
+ && canAdvance(); // the dialog as a whole allows to advance
+ enableButtons( WizardButtonFlags::NEXT, bCanAdvance );
+ }
+
+
+ bool WizardMachine::isTravelingSuspended() const
+ {
+ return m_pImpl->m_bTravelingSuspended;
+ }
+
+
+ void WizardMachine::suspendTraveling( AccessGuard )
+ {
+ DBG_ASSERT( !m_pImpl->m_bTravelingSuspended, "WizardMachine::suspendTraveling: already suspended!" );
+ m_pImpl->m_bTravelingSuspended = true;
+ }
+
+ void WizardMachine::resumeTraveling( AccessGuard )
+ {
+ DBG_ASSERT( m_pImpl->m_bTravelingSuspended, "WizardMachine::resumeTraveling: nothing to resume!" );
+ m_pImpl->m_bTravelingSuspended = false;
+ }
+
+ bool WizardMachine::Finish(short nResult)
+ {
+ if ( DeactivatePage() )
+ {
+ if (m_xCurTabPage)
+ m_xCurTabPage->DeactivatePage();
+
+ m_xAssistant->response(nResult);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ void WizardMachine::AddPage( TabPage* pPage )
+ {
+ ImplWizPageData* pNewPageData = new ImplWizPageData;
+ pNewPageData->mpNext = nullptr;
+ pNewPageData->mpPage = pPage;
+
+ if ( !m_pFirstPage )
+ m_pFirstPage = pNewPageData;
+ else
+ {
+ ImplWizPageData* pPageData = m_pFirstPage;
+ while ( pPageData->mpNext )
+ pPageData = pPageData->mpNext;
+ pPageData->mpNext = pNewPageData;
+ }
+ }
+
+ void WizardMachine::SetPage(WizardState nLevel, TabPage* pPage)
+ {
+ sal_uInt16 nTempLevel = 0;
+ ImplWizPageData* pPageData = m_pFirstPage;
+ while ( pPageData )
+ {
+ if ( (nTempLevel == nLevel) || !pPageData->mpNext )
+ break;
+
+ nTempLevel++;
+ pPageData = pPageData->mpNext;
+ }
+
+ if ( pPageData )
+ {
+ if ( pPageData->mpPage == m_xCurTabPage )
+ m_xCurTabPage = nullptr;
+ pPageData->mpPage = pPage;
+ }
+ }
+
+ TabPage* WizardMachine::GetPage(WizardState nLevel) const
+ {
+ sal_uInt16 nTempLevel = 0;
+
+ for (ImplWizPageData* pPageData = m_pFirstPage; pPageData;
+ pPageData = pPageData->mpNext)
+ {
+ if ( nTempLevel == nLevel )
+ return pPageData->mpPage;
+ nTempLevel++;
+ }
+
+ return nullptr;
+ }
} // namespace svt
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 10e3331ee355..45f6ae5a9813 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -38,6 +38,7 @@
#include <unotools/resmgr.hxx>
#include <unx/gstsink.hxx>
#include <vcl/ImageTree.hxx>
+#include <vcl/button.hxx>
#include <vcl/i18nhelp.hxx>
#include <vcl/quickselectionengine.hxx>
#include <vcl/mnemonic.hxx>
@@ -2619,6 +2620,15 @@ class GtkInstanceContainer : public GtkInstanceWidget, public virtual weld::Cont
{
private:
GtkContainer* m_pContainer;
+
+ static void implResetDefault(GtkWidget *pWidget, gpointer user_data)
+ {
+ if (GTK_IS_BUTTON(pWidget))
+ g_object_set(G_OBJECT(pWidget), "has-default", false, nullptr);
+ if (GTK_IS_CONTAINER(pWidget))
+ gtk_container_forall(GTK_CONTAINER(pWidget), implResetDefault, user_data);
+ }
+
public:
GtkInstanceContainer(GtkContainer* pContainer, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
: GtkInstanceWidget(GTK_WIDGET(pContainer), pBuilder, bTakeOwnership)
@@ -2642,6 +2652,11 @@ public:
gtk_container_add(pNewGtkParent->getContainer(), pChild);
g_object_unref(pChild);
}
+
+ virtual void recursively_unset_default_buttons() override
+ {
+ implResetDefault(GTK_WIDGET(m_pContainer), nullptr);
+ }
};
std::unique_ptr<weld::Container> GtkInstanceWidget::weld_parent() const
@@ -2964,21 +2979,21 @@ class GtkInstanceDialog;
struct DialogRunner
{
- GtkDialog *m_pDialog;
+ GtkWindow* m_pDialog;
GtkInstanceDialog *m_pInstance;
gint m_nResponseId;
GMainLoop *m_pLoop;
VclPtr<vcl::Window> m_xFrameWindow;
int m_nModalDepth;
- DialogRunner(GtkDialog* pDialog, GtkInstanceDialog* pInstance)
+ DialogRunner(GtkWindow* pDialog, GtkInstanceDialog* pInstance)
: m_pDialog(pDialog)
, m_pInstance(pInstance)
, m_nResponseId(GTK_RESPONSE_NONE)
, m_pLoop(nullptr)
, m_nModalDepth(0)
{
- GtkWindow* pParent = gtk_window_get_transient_for(GTK_WINDOW(m_pDialog));
+ GtkWindow* pParent = gtk_window_get_transient_for(m_pDialog);
GtkSalFrame* pFrame = pParent ? GtkSalFrame::getFromWindow(pParent) : nullptr;
m_xFrameWindow = pFrame ? pFrame->GetWindow() : nullptr;
}
@@ -2995,6 +3010,7 @@ struct DialogRunner
}
static void signal_response(GtkDialog*, gint nResponseId, gpointer data);
+ static void signal_cancel(GtkDialog*, gpointer data);
static gboolean signal_delete(GtkDialog*, GdkEventAny*, gpointer data)
{
@@ -3038,14 +3054,15 @@ struct DialogRunner
inc_modal_count();
- bool bWasModal = gtk_window_get_modal(GTK_WINDOW(m_pDialog));
+ bool bWasModal = gtk_window_get_modal(m_pDialog);
if (!bWasModal)
- gtk_window_set_modal(GTK_WINDOW(m_pDialog), true);
+ gtk_window_set_modal(m_pDialog, true);
if (!gtk_widget_get_visible(GTK_WIDGET(m_pDialog)))
gtk_widget_show(GTK_WIDGET(m_pDialog));
- gulong nSignalResponseId = g_signal_connect(m_pDialog, "response", G_CALLBACK(signal_response), this);
+ gulong nSignalResponseId = GTK_IS_DIALOG(m_pDialog) ? g_signal_connect(m_pDialog, "response", G_CALLBACK(signal_response), this) : 0;
+ gulong nSignalCancelId = GTK_IS_ASSISTANT(m_pDialog) ? g_signal_connect(m_pDialog, "cancel", G_CALLBACK(signal_cancel), this) : 0;
gulong nSignalDeleteId = g_signal_connect(m_pDialog, "delete-event", G_CALLBACK(signal_delete), this);
gulong nSignalDestroyId = g_signal_connect(m_pDialog, "destroy", G_CALLBACK(signal_destroy), this);
@@ -3061,9 +3078,12 @@ struct DialogRunner
m_pLoop = nullptr;
if (!bWasModal)
- gtk_window_set_modal(GTK_WINDOW(m_pDialog), false);
+ gtk_window_set_modal(m_pDialog, false);
- g_signal_handler_disconnect(m_pDialog, nSignalResponseId);
+ if (nSignalResponseId)
+ g_signal_handler_disconnect(m_pDialog, nSignalResponseId);
+ if (nSignalCancelId)
+ g_signal_handler_disconnect(m_pDialog, nSignalCancelId);
g_signal_handler_disconnect(m_pDialog, nSignalDeleteId);
g_signal_handler_disconnect(m_pDialog, nSignalDestroyId);
@@ -3125,7 +3145,7 @@ class GtkInstanceButton;
class GtkInstanceDialog : public GtkInstanceWindow, public virtual weld::Dialog
{
private:
- GtkDialog* m_pDialog;
+ GtkWindow* m_pDialog;
DialogRunner m_aDialogRun;
std::shared_ptr<weld::DialogController> m_xDialogController;
// Used to keep ourself alive during a runAsync(when doing runAsync without a DialogController)
@@ -3164,7 +3184,7 @@ private:
return true; /* Do not destroy */
}
- static int GtkToVcl(int ret)
+ virtual int GtkToVcl(int ret)
{
if (ret == GTK_RESPONSE_OK)
ret = RET_OK;
@@ -3181,11 +3201,28 @@ private:
return ret;
}
+ virtual int VclToGtk(int nResponse)
+ {
+ if (nResponse == RET_OK)
+ return GTK_RESPONSE_OK;
+ else if (nResponse == RET_CANCEL)
+ return GTK_RESPONSE_CANCEL;
+ else if (nResponse == RET_CLOSE)
+ return GTK_RESPONSE_CLOSE;
+ else if (nResponse == RET_YES)
+ return GTK_RESPONSE_YES;
+ else if (nResponse == RET_NO)
+ return GTK_RESPONSE_NO;
+ else if (nResponse == RET_HELP)
+ return GTK_RESPONSE_HELP;
+ return nResponse;
+ }
+
void asyncresponse(gint ret);
public:
- GtkInstanceDialog(GtkDialog* pDialog, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
- : GtkInstanceWindow(GTK_WINDOW(pDialog), pBuilder, bTakeOwnership)
+ GtkInstanceDialog(GtkWindow* pDialog, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
+ : GtkInstanceWindow(pDialog, pBuilder, bTakeOwnership)
, m_pDialog(pDialog)
, m_aDialogRun(pDialog, this)
, m_nCloseSignalId(g_signal_connect(m_pDialog, "close", G_CALLBACK(signalClose), this))
@@ -3243,7 +3280,8 @@ public:
{
if (gtk_widget_get_visible(m_pWidget))
return;
- sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(m_pDialog)));
+ if (GTK_IS_DIALOG(m_pDialog))
+ sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(m_pDialog))));
gtk_widget_show(m_pWidget);
}
@@ -3272,42 +3310,30 @@ public:
}
}
- static int VclToGtk(int nResponse)
- {
- if (nResponse == RET_OK)
- return GTK_RESPONSE_OK;
- else if (nResponse == RET_CANCEL)
- return GTK_RESPONSE_CANCEL;
- else if (nResponse == RET_CLOSE)
- return GTK_RESPONSE_CLOSE;
- else if (nResponse == RET_YES)
- return GTK_RESPONSE_YES;
- else if (nResponse == RET_NO)
- return GTK_RESPONSE_NO;
- else if (nResponse == RET_HELP)
- return GTK_RESPONSE_HELP;
- return nResponse;
- }
-
virtual void response(int nResponse) override;
virtual void add_button(const OUString& rText, int nResponse, const OString& rHelpId) override
{
- GtkWidget* pWidget = gtk_dialog_add_button(m_pDialog, MapToGtkAccelerator(rText).getStr(), VclToGtk(nResponse));
+ GtkWidget* pWidget = gtk_dialog_add_button(GTK_DIALOG(m_pDialog), MapToGtkAccelerator(rText).getStr(), VclToGtk(nResponse));
if (!rHelpId.isEmpty())
::set_help_id(pWidget, rHelpId);
}
virtual void set_default_response(int nResponse) override
{
- gtk_dialog_set_default_response(m_pDialog, VclToGtk(nResponse));
+ gtk_dialog_set_default_response(GTK_DIALOG(m_pDialog), VclToGtk(nResponse));
}
- virtual weld::Button* get_widget_for_response(int nResponse) override;
+ virtual GtkButton* get_widget_for_response(int nGtkResponse)
+ {
+ return GTK_BUTTON(gtk_dialog_get_widget_for_response(GTK_DIALOG(m_pDialog), nGtkResponse));
+ }
+
+ virtual weld::Button* weld_widget_for_response(int nVclResponse) override;
virtual Container* weld_content_area() override
{
- return new GtkInstanceContainer(GTK_CONTAINER(gtk_dialog_get_content_area(m_pDialog)), m_pBuilder, false);
+ return new GtkInstanceContainer(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(m_pDialog))), m_pBuilder, false);
}
virtual void collapse(weld::Widget* pEdit, weld::Widget* pButton) override
@@ -3327,7 +3353,7 @@ public:
//mark widgets we want to be visible, starting with pRefEdit
//and all its direct parents.
winset aVisibleWidgets;
- GtkWidget *pContentArea = gtk_dialog_get_content_area(m_pDialog);
+ GtkWidget *pContentArea = gtk_dialog_get_content_area(GTK_DIALOG(m_pDialog));
for (GtkWidget *pCandidate = pRefEdit;
pCandidate && pCandidate != pContentArea && gtk_widget_get_visible(pCandidate);
pCandidate = gtk_widget_get_parent(pCandidate))
@@ -3350,7 +3376,7 @@ public:
gtk_widget_set_size_request(pRefEdit, m_nOldEditWidth, -1);
m_nOldBorderWidth = gtk_container_get_border_width(GTK_CONTAINER(m_pDialog));
gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), 0);
- if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog))
+ if (GtkWidget* pActionArea = gtk_dialog_get_action_area(GTK_DIALOG(m_pDialog)))
gtk_widget_hide(pActionArea);
// calc's insert->function is springing back to its original size if the ref-button
@@ -3385,7 +3411,7 @@ public:
gtk_widget_set_size_request(m_pRefEdit, m_nOldEditWidthReq, -1);
m_pRefEdit = nullptr;
gtk_container_set_border_width(GTK_CONTAINER(m_pDialog), m_nOldBorderWidth);
- if (GtkWidget* pActionArea = gtk_dialog_get_action_area(m_pDialog))
+ if (GtkWidget* pActionArea = gtk_dialog_get_action_area(GTK_DIALOG(m_pDialog)))
gtk_widget_show(pActionArea);
resize_to_request();
present();
@@ -3430,13 +3456,21 @@ void DialogRunner::signal_response(GtkDialog*, gint nResponseId, gpointer data)
pThis->loop_quit();
}
+void DialogRunner::signal_cancel(GtkDialog*, gpointer data)
+{
+ DialogRunner* pThis = static_cast<DialogRunner*>(data);
+
+ // make esc in an assistant act as if cancel button was pressed
+ pThis->m_pInstance->close(false);
+}
+
class GtkInstanceMessageDialog : public GtkInstanceDialog, public virtual weld::MessageDialog
{
private:
GtkMessageDialog* m_pMessageDialog;
public:
GtkInstanceMessageDialog(GtkMessageDialog* pMessageDialog, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
- : GtkInstanceDialog(GTK_DIALOG(pMessageDialog), pBuilder, bTakeOwnership)
+ : GtkInstanceDialog(GTK_WINDOW(pMessageDialog), pBuilder, bTakeOwnership)
, m_pMessageDialog(pMessageDialog)
{
}
@@ -3475,7 +3509,7 @@ private:
std::unique_ptr<utl::TempFile> mxBackgroundImage;
public:
GtkInstanceAboutDialog(GtkAboutDialog* pAboutDialog, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
- : GtkInstanceDialog(GTK_DIALOG(pAboutDialog), pBuilder, bTakeOwnership)
+ : GtkInstanceDialog(GTK_WINDOW(pAboutDialog), pBuilder, bTakeOwnership)
, m_pAboutDialog(pAboutDialog)
, m_pCssProvider(nullptr)
{
@@ -3564,6 +3598,260 @@ public:
}
};
+class GtkInstanceAssistant : public GtkInstanceDialog, public virtual weld::Assistant
+{
+private:
+ GtkAssistant* m_pAssistant;
+ GtkWidget* m_pSidebar;
+ GtkButtonBox* m_pButtonBox;
+ GtkButton* m_pHelp;
+ GtkButton* m_pBack;
+ GtkButton* m_pNext;
+ GtkButton* m_pFinish;
+ GtkButton* m_pCancel;
+ std::vector<std::unique_ptr<GtkInstanceContainer>> m_aPages;
+
+ int find_page(const OString& rIdent) const
+ {
+ int nPages = gtk_assistant_get_n_pages(m_pAssistant);
+ for (int i = 0; i < nPages; ++i)
+ {
+ GtkWidget* pPage = gtk_assistant_get_nth_page(m_pAssistant, i);
+ const gchar* pStr = gtk_buildable_get_name(GTK_BUILDABLE(pPage));
+ if (g_strcmp0(pStr, rIdent.getStr()) == 0)
+ return i;
+ }
+ return -1;
+ }
+
+ virtual int GtkToVcl(int ret) override
+ {
+ if (ret == GTK_RESPONSE_OK)
+ ret = static_cast<int>(WizardButtonFlags::FINISH);
+ else if (ret == GTK_RESPONSE_CANCEL)
+ ret = static_cast<int>(WizardButtonFlags::CANCEL);
+ else if (ret == GTK_RESPONSE_DELETE_EVENT)
+ ret = static_cast<int>(WizardButtonFlags::CANCEL);
+ else if (ret == GTK_RESPONSE_CLOSE)
+ ret = static_cast<int>(WizardButtonFlags::CANCEL);
+ else if (ret == GTK_RESPONSE_ACCEPT)
+ ret = static_cast<int>(WizardButtonFlags::NEXT);
+ else if (ret == GTK_RESPONSE_REJECT)
+ ret = static_cast<int>(WizardButtonFlags::PREVIOUS);
+ else if (ret == GTK_RESPONSE_HELP)
+ ret = static_cast<int>(WizardButtonFlags::HELP);
+ return ret;
+ }
+
+ virtual int VclToGtk(int nResponse) override
+ {
+ if (nResponse == static_cast<int>(WizardButtonFlags::NEXT))
+ return GTK_RESPONSE_ACCEPT;
+ if (nResponse == static_cast<int>(WizardButtonFlags::PREVIOUS))
+ return GTK_RESPONSE_REJECT;
+ else if (nResponse == static_cast<int>(WizardButtonFlags::FINISH))
+ return GTK_RESPONSE_OK;
+ else if (nResponse == static_cast<int>(WizardButtonFlags::CANCEL))
+ return GTK_RESPONSE_CANCEL;
+ else if (nResponse == static_cast<int>(WizardButtonFlags::HELP))
+ return GTK_RESPONSE_HELP;
+ return nResponse;
+ }
+
+ static void wrap_sidebar_label(GtkWidget *pWidget, gpointer /*user_data*/)
+ {
+ if (GTK_IS_LABEL(pWidget))
+ {
+ gtk_label_set_line_wrap(GTK_LABEL(pWidget), true);
+ gtk_label_set_width_chars(GTK_LABEL(pWidget), 22);
+ gtk_label_set_max_width_chars(GTK_LABEL(pWidget), 22);
+ }
+ }
+
+ static void find_sidebar(GtkWidget *pWidget, gpointer user_data)
+ {
+ if (g_strcmp0(gtk_buildable_get_name(GTK_BUILDABLE(pWidget)), "sidebar") == 0)
+ {
+ GtkWidget **ppSidebar = static_cast<GtkWidget**>(user_data);
+ *ppSidebar = pWidget;
+ }
+ if (GTK_IS_CONTAINER(pWidget))
+ gtk_container_forall(GTK_CONTAINER(pWidget), find_sidebar, user_data);
+ }
+
+public:
+ GtkInstanceAssistant(GtkAssistant* pAssistant, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
+ : GtkInstanceDialog(GTK_WINDOW(pAssistant), pBuilder, bTakeOwnership)
+ , m_pAssistant(pAssistant)
+ , m_pSidebar(nullptr)
+ {
+ m_pButtonBox = GTK_BUTTON_BOX(gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL));
+ gtk_button_box_set_layout(m_pButtonBox, GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(m_pButtonBox), 6);
+
+ m_pBack = GTK_BUTTON(gtk_button_new_with_mnemonic(MapToGtkAccelerator(Button::GetStandardText(StandardButtonType::Back)).getStr()));
+ gtk_widget_set_can_default(GTK_WIDGET(m_pBack), true);
+ gtk_buildable_set_name(GTK_BUILDABLE(m_pBack), "previous");
+ gtk_box_pack_end(GTK_BOX(m_pButtonBox), GTK_WIDGET(m_pBack), false, false, 0);
+
+ m_pNext = GTK_BUTTON(gtk_button_new_with_mnemonic(MapToGtkAccelerator(Button::GetStandardText(StandardButtonType::Next)).getStr()));
+ gtk_widget_set_can_default(GTK_WIDGET(m_pNext), true);
+ gtk_buildable_set_name(GTK_BUILDABLE(m_pNext), "next");
+ gtk_box_pack_end(GTK_BOX(m_pButtonBox), GTK_WIDGET(m_pNext), false, false, 0);
+
+ m_pCancel = GTK_BUTTON(gtk_button_new_with_mnemonic(MapToGtkAccelerator(Button::GetStandardText(StandardButtonType::Cancel)).getStr()));
+ gtk_widget_set_can_default(GTK_WIDGET(m_pCancel), true);
+ gtk_box_pack_end(GTK_BOX(m_pButtonBox), GTK_WIDGET(m_pCancel), false, false, 0);
+
+ m_pFinish = GTK_BUTTON(gtk_button_new_with_mnemonic(MapToGtkAccelerator(Button::GetStandardText(StandardButtonType::Finish)).getStr()));
+ gtk_widget_set_can_default(GTK_WIDGET(m_pFinish), true);
+ gtk_buildable_set_name(GTK_BUILDABLE(m_pFinish), "finish");
+ gtk_box_pack_end(GTK_BOX(m_pButtonBox), GTK_WIDGET(m_pFinish), false, false, 0);
+
+ m_pHelp = GTK_BUTTON(gtk_button_new_with_mnemonic(MapToGtkAccelerator(Button::GetStandardText(StandardButtonType::Help)).getStr()));
+ gtk_widget_set_can_default(GTK_WIDGET(m_pHelp), true);
+ gtk_box_pack_end(GTK_BOX(m_pButtonBox), GTK_WIDGET(m_pHelp), false, false, 0);
+
+ gtk_assistant_add_action_widget(pAssistant, GTK_WIDGET(m_pButtonBox));
+ gtk_button_box_set_child_secondary(m_pButtonBox, GTK_WIDGET(m_pHelp), true);
+ gtk_widget_set_hexpand(GTK_WIDGET(m_pButtonBox), true);
+
+ GtkWidget* pParent = gtk_widget_get_parent(GTK_WIDGET(m_pButtonBox));
+ gtk_container_child_set(GTK_CONTAINER(pParent), GTK_WIDGET(m_pButtonBox), "expand", true, "fill", true, nullptr);
+ gtk_widget_set_halign(pParent, GTK_ALIGN_FILL);
+
+ // Hide the built-in ones early so we get a nice optimal size for the width without
+ // including the unused contents
+ GList* pChildren = gtk_container_get_children(GTK_CONTAINER(pParent));
+ for (GList* pChild = g_list_first(pChildren); pChild; pChild = g_list_next(pChild))
+ {
+ GtkWidget* pWidget = static_cast<GtkWidget*>(pChild->data);
+ gtk_widget_hide(pWidget);
+ }
+ g_list_free(pChildren);
+
+ gtk_widget_show_all(GTK_WIDGET(m_pButtonBox));
+
+ find_sidebar(GTK_WIDGET(m_pAssistant), &m_pSidebar);
+ }
+
+ virtual int get_current_page() const override
+ {
+ return gtk_assistant_get_current_page(m_pAssistant);
+ }
+
+ virtual int get_n_pages() const override
+ {
+ return gtk_assistant_get_n_pages(m_pAssistant);
+ }
+
+ virtual OString get_page_ident(int nPage) const override
+ {
+ const GtkWidget* pWidget = gtk_assistant_get_nth_page(m_pAssistant, nPage);
+ const gchar* pStr = gtk_buildable_get_name(GTK_BUILDABLE(pWidget));
+ return OString(pStr, pStr ? strlen(pStr) : 0);
+ }
+
+ virtual OString get_current_page_ident() const override
+ {
+ return get_page_ident(get_current_page());
+ }
+
+ virtual void set_current_page(int nPage) override
+ {
+ gtk_assistant_set_current_page(m_pAssistant, nPage);
+ }
+
+ virtual void set_current_page(const OString& rIdent) override
+ {
+ int nPage = find_page(rIdent);
+ if (nPage == -1)
+ return;
+ set_current_page(nPage);
+ }
+
+ virtual void set_page_title(const OString& rIdent, const OUString& rTitle) override
+ {
+ int nIndex = find_page(rIdent);
+ if (nIndex == -1)
+ return;
+ GtkWidget* pPage = gtk_assistant_get_nth_page(m_pAssistant, nIndex);
+ gtk_assistant_set_page_title(m_pAssistant, pPage,
+ OUStringToOString(rTitle, RTL_TEXTENCODING_UTF8).getStr());
+ gtk_container_forall(GTK_CONTAINER(m_pSidebar), wrap_sidebar_label, nullptr);
+ }
+
+ virtual OUString get_page_title(const OString& rIdent) const override
+ {
+ int nIndex = find_page(rIdent);
+ if (nIndex == -1)
+ return OUString();
+ GtkWidget* pPage = gtk_assistant_get_nth_page(m_pAssistant, nIndex);
+ const gchar* pStr = gtk_assistant_get_page_title(m_pAssistant, pPage);
+ return OUString(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8);
+ }
+
+ virtual void set_page_sensitive(const OString& /*rIdent*/, bool /*bSensitive*/) override
+ {
+ // seeing as the GtkAssistant doesn't have clickable roadmap entries
+ // sensitive vs insensitive is moot
+ }
+
+ virtual void set_page_index(const OString& rIdent, int nNewIndex) override
+ {
+ int nOldIndex = find_page(rIdent);
+ if (nOldIndex == -1)
+ return;
+
+ if (nOldIndex == nNewIndex)
+ return;
+
+ GtkWidget* pPage = gtk_assistant_get_nth_page(m_pAssistant, nOldIndex);
+
+ g_object_ref(pPage);
+ OString sTitle(gtk_assistant_get_page_title(m_pAssistant, pPage));
+ gtk_assistant_remove_page(m_pAssistant, nOldIndex);
+ gtk_assistant_insert_page(m_pAssistant, pPage, nNewIndex);
+ gtk_assistant_set_page_type(m_pAssistant, pPage, GTK_ASSISTANT_PAGE_CUSTOM);
+ gtk_assistant_set_page_title(m_pAssistant, pPage, sTitle.getStr());
+ gtk_container_forall(GTK_CONTAINER(m_pSidebar), wrap_sidebar_label, nullptr);
+ g_object_unref(pPage);
+ }
+
+ virtual weld::Container* append_page(const OString& rIdent) override
+ {
+ disable_notify_events();
+
+ GtkWidget *pChild = gtk_grid_new();
+ gtk_buildable_set_name(GTK_BUILDABLE(pChild), rIdent.getStr());
+ gtk_assistant_append_page(m_pAssistant, pChild);
+ gtk_assistant_set_page_type(m_pAssistant, pChild, GTK_ASSISTANT_PAGE_CUSTOM);
+ gtk_widget_show(pChild);
+
+ enable_notify_events();
+
+ m_aPages.emplace_back(new GtkInstanceContainer(GTK_CONTAINER(pChild), m_pBuilder, false));
+
+ return m_aPages.back().get();
+ }
+
+ virtual GtkButton* get_widget_for_response(int nGtkResponse) override
+ {
+ GtkButton* pButton = nullptr;
+ if (nGtkResponse == GTK_RESPONSE_ACCEPT)
+ pButton = m_pNext;
+ else if (nGtkResponse == GTK_RESPONSE_REJECT)
+ pButton = m_pBack;
+ else if (nGtkResponse == GTK_RESPONSE_OK)
+ pButton = m_pFinish;
+ else if (nGtkResponse == GTK_RESPONSE_CANCEL)
+ pButton = m_pCancel;
+ else if (nGtkResponse == GTK_RESPONSE_HELP)
+ pButton = m_pHelp;
+ return pButton;
+ }
+};
+
class GtkInstanceFrame : public GtkInstanceContainer, public virtual weld::Frame
{
private:
@@ -4869,7 +5157,8 @@ void GtkInstanceDialog::asyncresponse(gint ret)
int GtkInstanceDialog::run()
{
- sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(m_pDialog)));
+ if (GTK_IS_DIALOG(m_pDialog))
+ sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(GTK_DIALOG(m_pDialog))));
int ret;
while (true)
{
@@ -4887,9 +5176,9 @@ int GtkInstanceDialog::run()
return GtkToVcl(ret);
}
-weld::Button* GtkInstanceDialog::get_widget_for_response(int nResponse)
+weld::Button* GtkInstanceDialog::weld_widget_for_response(int nVclResponse)
{
- GtkButton* pButton = GTK_BUTTON(gtk_dialog_get_widget_for_response(m_pDialog, VclToGtk(nResponse)));
+ GtkButton* pButton = get_widget_for_response(VclToGtk(nVclResponse));
if (!pButton)
return nullptr;
return new GtkInstanceButton(pButton, m_pBuilder, false);
@@ -4897,15 +5186,22 @@ weld::Button* GtkInstanceDialog::get_widget_for_response(int nResponse)
void GtkInstanceDialog::response(int nResponse)
{
+ int nGtkResponse = VclToGtk(nResponse);
//unblock this response now when activated through code
- if (GtkWidget* pWidget = gtk_dialog_get_widget_for_response(m_pDialog, VclToGtk(nResponse)))
+ if (GtkButton* pWidget = get_widget_for_response(nGtkResponse))
{
void* pData = g_object_get_data(G_OBJECT(pWidget), "g-lo-GtkInstanceButton");
GtkInstanceButton* pButton = static_cast<GtkInstanceButton*>(pData);
if (pButton)
pButton->clear_click_handler();
}
- gtk_dialog_response(m_pDialog, VclToGtk(nResponse));
+ if (GTK_IS_DIALOG(m_pDialog))
+ gtk_dialog_response(GTK_DIALOG(m_pDialog), nGtkResponse);
+ else if (GTK_IS_ASSISTANT(m_pDialog))
+ {
+ m_aDialogRun.m_nResponseId = nGtkResponse;
+ m_aDialogRun.loop_quit();
+ }
}
void GtkInstanceDialog::close(bool bCloseSignal)
@@ -4928,7 +5224,7 @@ GtkInstanceButton* GtkInstanceDialog::has_click_handler(int nResponse)
GtkInstanceButton* pButton = nullptr;
// e.g. map GTK_RESPONSE_DELETE_EVENT to GTK_RESPONSE_CANCEL
nResponse = VclToGtk(GtkToVcl(nResponse));
- if (GtkWidget* pWidget = gtk_dialog_get_widget_for_response(m_pDialog, nResponse))
+ if (GtkButton* pWidget = get_widget_for_response(nResponse))
{
void* pData = g_object_get_data(G_OBJECT(pWidget), "g-lo-GtkInstanceButton");
pButton = static_cast<GtkInstanceButton*>(pData);
@@ -10368,7 +10664,7 @@ private:
set_help_id(pWidget, sHelpId);
//hook up for extended help
const ImplSVData* pSVData = ImplGetSVData();
- if (pSVData->maHelpData.mbBalloonHelp && !GTK_IS_DIALOG(pWidget))
+ if (pSVData->maHelpData.mbBalloonHelp && !GTK_IS_DIALOG(pWidget) && !GTK_IS_ASSISTANT(pWidget))
{
gtk_widget_set_has_tooltip(pWidget, true);
g_signal_connect(pWidget, "query-tooltip", G_CALLBACK(signalTooltipQuery), nullptr);
@@ -10602,6 +10898,15 @@ public:
return std::make_unique<GtkInstanceAboutDialog>(pAboutDialog, this, bTakeOwnership);
}
+ virtual std::unique_ptr<weld::Assistant> weld_assistant(const OString &id, bool bTakeOwnership) override
+ {
+ GtkAssistant* pAssistant = GTK_ASSISTANT(gtk_builder_get_object(m_pBuilder, id.getStr()));
+ if (!pAssistant)
+ return nullptr;
+ gtk_window_set_transient_for(GTK_WINDOW(pAssistant), GTK_WINDOW(gtk_widget_get_toplevel(m_pParentWidget)));
+ return std::make_unique<GtkInstanceAssistant>(pAssistant, this, bTakeOwnership);
+ }
+
virtual std::unique_ptr<weld::Dialog> weld_dialog(const OString &id, bool bTakeOwnership) override
{
GtkDialog* pDialog = GTK_DIALOG(gtk_builder_get_object(m_pBuilder, id.getStr()));
@@ -10609,7 +10914,7 @@ public:
return nullptr;
if (m_pParentWidget)
gtk_window_set_transient_for(GTK_WINDOW(pDialog), GTK_WINDOW(gtk_widget_get_toplevel(m_pParentWidget)));
- return std::make_unique<GtkInstanceDialog>(pDialog, this, bTakeOwnership);
+ return std::make_unique<GtkInstanceDialog>(GTK_WINDOW(pDialog), this, bTakeOwnership);
}
virtual std::unique_ptr<weld::Window> weld_window(const OString &id, bool bTakeOwnership) override