summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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