diff options
author | Caolán McNamara <caolanm@redhat.com> | 2018-04-24 14:14:34 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2018-04-27 09:54:08 +0200 |
commit | 28fc0962b10519ab84654d189d2ad0cca8f84f95 (patch) | |
tree | ff2b008cb13f69724abfff62157c6a4e133135a2 /sfx2 | |
parent | 3d97c9d292d80cb82391bdb416a9c6217a8e16e4 (diff) |
weld SwLabDlg
Change-Id: I55c543776c03b1d1da0331552b98e6e281e35937
Reviewed-on: https://gerrit.libreoffice.org/53488
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sfx2')
-rw-r--r-- | sfx2/source/dialog/tabdlg.cxx | 623 |
1 files changed, 616 insertions, 7 deletions
diff --git a/sfx2/source/dialog/tabdlg.cxx b/sfx2/source/dialog/tabdlg.cxx index dfca78c96d7f..a39efbd00cba 100644 --- a/sfx2/source/dialog/tabdlg.cxx +++ b/sfx2/source/dialog/tabdlg.cxx @@ -53,24 +53,27 @@ struct TabPageImpl bool mbStandard; sfx::ItemConnectionArray maItemConn; VclPtr<SfxTabDialog> mxDialog; + SfxTabDialogController* mpDialogController; css::uno::Reference< css::frame::XFrame > mxFrame; - TabPageImpl() : mbStandard( false ) {} + TabPageImpl() : mbStandard( false ), mpDialogController(nullptr) {} }; struct Data_Impl { - sal_uInt16 nId; // The ID + sal_uInt16 nId; // The ID + OString sId; // The ID CreateTabPage fnCreatePage; // Pointer to Factory GetTabPageRanges fnGetRanges; // Pointer to Ranges-Function VclPtr<SfxTabPage> pTabPage; // The TabPage itself bool bRefresh; // Flag: Page must be re-initialized // Constructor - Data_Impl( sal_uInt16 Id, CreateTabPage fnPage, + Data_Impl( sal_uInt16 Id, const OString& rId, CreateTabPage fnPage, GetTabPageRanges fnRanges ) : nId ( Id ), + sId ( rId ), fnCreatePage( fnPage ), fnGetRanges ( fnRanges ), pTabPage ( nullptr ), @@ -144,6 +147,24 @@ static Data_Impl* Find( const SfxTabDlgData_Impl& rArr, sal_uInt16 nId, sal_uInt return nullptr; } +static Data_Impl* Find( const SfxTabDlgData_Impl& rArr, const OString& rId, sal_uInt16* pPos = nullptr) +{ + const sal_uInt16 nCount = rArr.size(); + + for ( sal_uInt16 i = 0; i < nCount; ++i ) + { + Data_Impl* pObj = rArr[i]; + + if ( pObj->sId == rId ) + { + if ( pPos ) + *pPos = i; + return pObj; + } + } + return nullptr; +} + void SfxTabPage::SetFrame(const css::uno::Reference< css::frame::XFrame >& xFrame) { if (pImpl) @@ -318,6 +339,16 @@ SfxTabDialog* SfxTabPage::GetTabDialog() const return pImpl->mxDialog; } +void SfxTabPage::SetDialogController(SfxTabDialogController* pDialog) +{ + pImpl->mpDialogController = pDialog; +} + +SfxTabDialogController* SfxTabPage::GetDialogController() const +{ + return pImpl->mpDialogController; +} + OString SfxTabPage::GetConfigId() const { if (m_xContainer) @@ -624,8 +655,7 @@ sal_uInt16 SfxTabDialog::AddTabPage ) { sal_uInt16 nId = m_pTabCtrl->GetPageId(rName); - m_pImpl->aData.push_back( - new Data_Impl( nId, pCreateFunc, pRangesFunc ) ); + m_pImpl->aData.push_back(new Data_Impl(nId, rName, pCreateFunc, pRangesFunc)); return nId; } @@ -645,7 +675,7 @@ sal_uInt16 SfxTabDialog::AddTabPage assert(pCreateFunc); GetTabPageRanges pRangesFunc = pFact->GetTabPageRangesFunc(nPageCreateId); sal_uInt16 nPageId = m_pTabCtrl->GetPageId(rName); - m_pImpl->aData.push_back(new Data_Impl(nPageId, pCreateFunc, pRangesFunc)); + m_pImpl->aData.push_back(new Data_Impl(nPageId, rName, pCreateFunc, pRangesFunc)); return nPageId; } @@ -669,7 +699,7 @@ void SfxTabDialog::AddTabPage DBG_ASSERT( TAB_PAGE_NOTFOUND == m_pTabCtrl->GetPagePos( nId ), "Double Page-Ids in the Tabpage" ); m_pTabCtrl->InsertPage( nId, rRiderText, nPos ); - m_pImpl->aData.push_back( new Data_Impl( nId, pCreateFunc, pRangesFunc ) ); + m_pImpl->aData.push_back( new Data_Impl(nId, "", pCreateFunc, pRangesFunc ) ); } void SfxTabDialog::RemoveTabPage( sal_uInt16 nId ) @@ -1422,4 +1452,583 @@ bool SfxTabDialog::selectPageByUIXMLDescription(const OString& rUIXMLDescription return false; } +SfxTabDialogController::SfxTabDialogController +( + weld::Window* pParent, // Parent Window + const OUString& rUIXMLDescription, const OString& rID, // Dialog .ui path, Dialog Name + const SfxItemSet* pItemSet, // Itemset with the data; + // can be NULL, when Pages are onDemand + bool bEditFmt // when yes -> additional Button for standard +) + : GenericDialogController(pParent, rUIXMLDescription, rID) + , m_xTabCtrl(m_xBuilder->weld_notebook("tabcontrol")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xApplyBtn(m_xBuilder->weld_button("apply")) + , m_xCancelBtn(m_xBuilder->weld_button("cancel")) + , m_xResetBtn(m_xBuilder->weld_button("reset")) + , m_pSet(pItemSet ? new SfxItemSet(*pItemSet) : nullptr) + , m_pOutSet(nullptr) + , m_pRanges(nullptr) + , m_bStandardPushed(false) + , m_pExampleSet(nullptr) +{ + Init_Impl(bEditFmt); +} + +void SfxTabDialogController::Init_Impl(bool /*bFmtFlag*/) +{ + m_pImpl.reset(new TabDlg_Impl(m_xTabCtrl->get_n_pages())); + m_pImpl->bHideResetBtn = !m_xResetBtn->get_visible(); + m_xOKBtn->connect_clicked(LINK(this, SfxTabDialogController, OkHdl)); + m_xCancelBtn->connect_clicked(LINK(this, SfxTabDialogController, CancelHdl)); + m_xResetBtn->connect_clicked(LINK(this, SfxTabDialogController, ResetHdl)); + m_xResetBtn->set_label(SfxResId(STR_RESET)); + m_xTabCtrl->connect_enter_page(LINK(this, SfxTabDialogController, ActivatePageHdl)); + m_xTabCtrl->connect_leave_page(LINK(this, SfxTabDialogController, DeactivatePageHdl)); + m_xResetBtn->set_help_id(HID_TABDLG_RESET_BTN); + + if (m_pSet) + { + m_pExampleSet = new SfxItemSet(*m_pSet); + m_pOutSet.reset(new SfxItemSet(*m_pSet->GetPool(), m_pSet->GetRanges())); + } +} + +IMPL_LINK_NOARG(SfxTabDialogController, OkHdl, weld::Button&, void) + +/* [Description] + + Handler of the Ok-Buttons + This calls the current page <SfxTabPage::DeactivatePage(SfxItemSet *)>. + Returns <DeactivateRC::LeavePage>, <SfxTabDialog::Ok()> is called + and the Dialog is ended. +*/ + +{ + if (PrepareLeaveCurrentPage()) + m_xDialog->response(Ok()); +} + +IMPL_LINK_NOARG(SfxTabDialogController, CancelHdl, weld::Button&, void) +{ + m_xDialog->response(RET_USER_CANCEL); +} + +IMPL_LINK_NOARG(SfxTabDialogController, ResetHdl, weld::Button&, void) + +/* [Description] + + Handler behind the reset button. + The Current Page is new initialized with their initial data, all the + settings that the user has made on this page are repealed. +*/ + +{ + const OString sId = m_xTabCtrl->get_current_page_ident(); + Data_Impl* pDataObject = Find( m_pImpl->aData, sId ); + DBG_ASSERT( pDataObject, "Id not known" ); + + pDataObject->pTabPage->Reset( m_pSet ); + // Also reset relevant items of ExampleSet and OutSet to initial state + if (pDataObject->fnGetRanges) + { + if (!m_pExampleSet) + m_pExampleSet = new SfxItemSet(*m_pSet); + + const SfxItemPool* pPool = m_pSet->GetPool(); + const sal_uInt16* pTmpRanges = (pDataObject->fnGetRanges)(); + + while (*pTmpRanges) + { + const sal_uInt16* pU = pTmpRanges + 1; + + // Correct Range with multiple values + sal_uInt16 nTmp = *pTmpRanges, nTmpEnd = *pU; + DBG_ASSERT(nTmp <= nTmpEnd, "Range is sorted the wrong way"); + + if (nTmp > nTmpEnd) + { + // If really sorted wrongly, then set new + std::swap(nTmp, nTmpEnd); + } + + while (nTmp && nTmp <= nTmpEnd) + { + // Iterate over the Range and set the Items + sal_uInt16 nWh = pPool->GetWhich(nTmp); + const SfxPoolItem* pItem; + if (SfxItemState::SET == m_pSet->GetItemState(nWh, false, &pItem)) + { + m_pExampleSet->Put(*pItem); + m_pOutSet->Put(*pItem); + } + else + { + m_pExampleSet->ClearItem(nWh); + m_pOutSet->ClearItem(nWh); + } + nTmp++; + } + // Go to the next pair + pTmpRanges += 2; + } + } +} + +IMPL_LINK(SfxTabDialogController, ActivatePageHdl, const OString&, rPage, void) + +/* [Description] + + Handler that is called by StarView for switching to a different page. + If possible the <SfxTabPage::Reset(const SfxItemSet &)> or + <SfxTabPage::ActivatePage(const SfxItemSet &)> is called on the new page +*/ + +{ + assert(!m_pImpl->aData.empty() && "no Pages registered"); + Data_Impl* pDataObject = Find(m_pImpl->aData, rPage); + if (!pDataObject) + { + SAL_WARN("sfx.dialog", "Tab Page ID not known, this is pretty serious and needs investigation"); + return; + } + + VclPtr<SfxTabPage> pTabPage = pDataObject->pTabPage; + + if (pDataObject->bRefresh) + pTabPage->Reset(m_pSet); + pDataObject->bRefresh = false; + + if (m_pExampleSet) + pTabPage->ActivatePage(*m_pExampleSet); + + if (pTabPage->IsReadOnly() || m_pImpl->bHideResetBtn) + m_xResetBtn->hide(); + else + m_xResetBtn->show(); +} + +IMPL_LINK(SfxTabDialogController, DeactivatePageHdl, const OString&, rPage, bool) + +/* [Description] + + Handler that is called by StarView before leaving a page. + + [Cross-reference] + + <SfxTabPage::DeactivatePage(SfxItemSet *)> +*/ + +{ + assert(!m_pImpl->aData.empty() && "no Pages registered"); + Data_Impl* pDataObject = Find(m_pImpl->aData, rPage); + if (!pDataObject) + { + SAL_WARN("sfx.dialog", "Tab Page ID not known, this is pretty serious and needs investigation"); + return false; + } + + VclPtr<SfxTabPage> pPage = pDataObject->pTabPage; + DBG_ASSERT( pPage, "no active Page" ); + if (!pPage) + return false; + + DeactivateRC nRet = DeactivateRC::LeavePage; + + if (!m_pExampleSet && pPage->HasExchangeSupport() && m_pSet) + m_pExampleSet = new SfxItemSet(*m_pSet->GetPool(), m_pSet->GetRanges()); + + if (m_pSet) + { + SfxItemSet aTmp( *m_pSet->GetPool(), m_pSet->GetRanges() ); + + if (pPage->HasExchangeSupport()) + nRet = pPage->DeactivatePage(&aTmp); + else + nRet = pPage->DeactivatePage(nullptr); + if ( ( DeactivateRC::LeavePage & nRet ) == DeactivateRC::LeavePage && + aTmp.Count() && m_pExampleSet) + { + m_pExampleSet->Put( aTmp ); + m_pOutSet->Put( aTmp ); + } + } + else + { + if ( pPage->HasExchangeSupport() ) //!!! + { + if ( !m_pExampleSet ) + { + SfxItemPool* pPool = pPage->GetItemSet().GetPool(); + m_pExampleSet = + new SfxItemSet( *pPool, GetInputRanges( *pPool ) ); + } + nRet = pPage->DeactivatePage( m_pExampleSet ); + } + else + nRet = pPage->DeactivatePage( nullptr ); + } + + if ( nRet & DeactivateRC::RefreshSet ) + { + RefreshInputSet(); + // Flag all Pages as to be initialized as new + + for (auto const& elem : m_pImpl->aData) + { + elem->bRefresh = ( elem->pTabPage.get() != pPage ); // Do not refresh own Page anymore + } + } + return static_cast<bool>(nRet & DeactivateRC::LeavePage); +} + +bool SfxTabDialogController::PrepareLeaveCurrentPage() +{ + const OString sId = m_xTabCtrl->get_current_page_ident(); + Data_Impl* pDataObject = Find(m_pImpl->aData, sId); + DBG_ASSERT( pDataObject, "Id not known" ); + VclPtr<SfxTabPage> pPage = pDataObject ? pDataObject->pTabPage : nullptr; + + bool bEnd = !pPage; + + if ( pPage ) + { + DeactivateRC nRet = DeactivateRC::LeavePage; + if ( m_pSet ) + { + SfxItemSet aTmp( *m_pSet->GetPool(), m_pSet->GetRanges() ); + + if ( pPage->HasExchangeSupport() ) + nRet = pPage->DeactivatePage( &aTmp ); + else + nRet = pPage->DeactivatePage( nullptr ); + + if ( ( DeactivateRC::LeavePage & nRet ) == DeactivateRC::LeavePage + && aTmp.Count() ) + { + m_pExampleSet->Put( aTmp ); + m_pOutSet->Put( aTmp ); + } + } + else + nRet = pPage->DeactivatePage( nullptr ); + bEnd = nRet != DeactivateRC::KeepPage; + } + + return bEnd; +} + +const sal_uInt16* SfxTabDialogController::GetInputRanges(const SfxItemPool& rPool) + +/* [Description] + + Makes the set over the range of all pages of the dialogue. Pages have the + static method for querying their range in AddTabPage, ie deliver their + sets onDemand. + + [Return value] + + Pointer to a null-terminated array of sal_uInt16. This array belongs to the + dialog and is deleted when the dialogue is destroy. + + [Cross-reference] + + <SfxTabDialog::AddTabPage(sal_uInt16, CreateTabPage, GetTabPageRanges, bool)> + <SfxTabDialog::AddTabPage(sal_uInt16, const String &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)> + <SfxTabDialog::AddTabPage(sal_uInt16, const Bitmap &, CreateTabPage, GetTabPageRanges, bool, sal_uInt16)> +*/ + +{ + if ( m_pSet ) + { + SAL_WARN( "sfx.dialog", "Set already exists!" ); + return m_pSet->GetRanges(); + } + + if ( m_pRanges ) + return m_pRanges; + std::vector<sal_uInt16> aUS; + + for (auto const& elem : m_pImpl->aData) + { + + if ( elem->fnGetRanges ) + { + const sal_uInt16* pTmpRanges = (elem->fnGetRanges)(); + const sal_uInt16* pIter = pTmpRanges; + + sal_uInt16 nLen; + for( nLen = 0; *pIter; ++nLen, ++pIter ) + ; + aUS.insert( aUS.end(), pTmpRanges, pTmpRanges + nLen ); + } + } + + //! Remove duplicated Ids? + { + for (auto & elem : aUS) + elem = rPool.GetWhich(elem); + } + + // sort + if ( aUS.size() > 1 ) + { + std::sort( aUS.begin(), aUS.end() ); + } + + m_pRanges = new sal_uInt16[aUS.size() + 1]; + std::copy( aUS.begin(), aUS.end(), m_pRanges ); + m_pRanges[aUS.size()] = 0; + return m_pRanges; +} + +SfxTabDialogController::~SfxTabDialogController() +{ + SavePosAndId(); + + for (auto & elem : m_pImpl->aData) + { + if ( elem->pTabPage ) + { + // save settings of all pages (user data) + elem->pTabPage->FillUserData(); + OUString aPageData( elem->pTabPage->GetUserData() ); + if ( !aPageData.isEmpty() ) + { + // save settings of all pages (user data) + OUString sConfigId = OStringToOUString(elem->pTabPage->GetConfigId(), + RTL_TEXTENCODING_UTF8); + SvtViewOptions aPageOpt(EViewType::TabPage, sConfigId); + aPageOpt.SetUserItem( USERITEM_NAME, makeAny( aPageData ) ); + } + + elem->pTabPage.disposeAndClear(); + } + delete elem; + elem = nullptr; + } +} + +short SfxTabDialogController::Ok() + +/* [Description] + + Ok handler for the Dialogue. + + Dialog's current location and current page are saved for the next time + the dialog is shown. + + The OutputSet is created and for each page this or the special OutputSet + is set by calling the method <SfxTabPage::FillItemSet(SfxItemSet &)>, to + insert the entered data by the user into the set. + + [Return value] + + RET_OK: if at least one page has returned from FillItemSet, + otherwise RET_CANCEL. +*/ +{ + SavePosAndId(); //See fdo#38828 "Apply" resetting window position + + if ( !m_pOutSet ) + { + if ( m_pExampleSet ) + m_pOutSet.reset(new SfxItemSet( *m_pExampleSet )); + else if ( m_pSet ) + m_pOutSet = m_pSet->Clone( false ); // without Items + } + bool bModified = false; + + for (auto const& elem : m_pImpl->aData) + { + SfxTabPage* pTabPage = elem->pTabPage; + + if ( pTabPage ) + { + if ( m_pSet && !pTabPage->HasExchangeSupport() ) + { + SfxItemSet aTmp( *m_pSet->GetPool(), m_pSet->GetRanges() ); + + if ( pTabPage->FillItemSet( &aTmp ) ) + { + bModified = true; + if (m_pExampleSet) + m_pExampleSet->Put( aTmp ); + m_pOutSet->Put( aTmp ); + } + } + } + } + + if ( m_pOutSet && m_pOutSet->Count() > 0 ) + bModified = true; + + if (m_bStandardPushed) + bModified = true; + return bModified ? RET_OK : RET_CANCEL; +} + +void SfxTabDialogController::RefreshInputSet() + +/* [Description] + + Default implementation of the virtual Method. + This is called, when <SfxTabPage::DeactivatePage(SfxItemSet *)> + returns <DeactivateRC::RefreshSet>. +*/ + +{ + SAL_INFO ( "sfx.dialog", "RefreshInputSet not implemented" ); +} + +void SfxTabDialogController::PageCreated + +/* [Description] + + Default implementation of the virtual method. This is called immediately + after creating a page. Here the dialogue can call the TabPage Method + directly. +*/ + +( + const OString&, // Id of the created page + SfxTabPage& // Reference to the created page +) +{ +} + +void SfxTabDialogController::SavePosAndId() +{ + // save settings (screen position and current page) + SvtViewOptions aDlgOpt(EViewType::TabDialog, OStringToOUString(m_xDialog->get_help_id(), RTL_TEXTENCODING_UTF8)); + aDlgOpt.SetPageID(m_xTabCtrl->get_current_page_ident()); +} + +/* + Adds a page to the dialog. The Name must correspond to a entry in the + TabControl in the dialog .ui +*/ +void SfxTabDialogController::AddTabPage +( + const OString &rName, // Page ID + CreateTabPage pCreateFunc, // Pointer to the Factory Method + GetTabPageRanges pRangesFunc // Pointer to the Method for querying + // Ranges onDemand +) +{ + m_pImpl->aData.push_back(new Data_Impl(m_pImpl->aData.size(), rName, pCreateFunc, pRangesFunc)); + Data_Impl* pDataObject = m_pImpl->aData.back(); + + assert(pDataObject->pTabPage == nullptr && "create TabPage more than once"); + weld::Container* pPage = m_xTabCtrl->get_page(rName); + pDataObject->pTabPage = (pDataObject->fnCreatePage)(pPage, m_pSet); + pDataObject->pTabPage->SetDialogController(this); + + OUString sConfigId = OStringToOUString(pDataObject->pTabPage->GetConfigId(), RTL_TEXTENCODING_UTF8); + SvtViewOptions aPageOpt(EViewType::TabPage, sConfigId); + OUString sUserData; + Any aUserItem = aPageOpt.GetUserItem(USERITEM_NAME); + OUString aTemp; + if ( aUserItem >>= aTemp ) + sUserData = aTemp; + pDataObject->pTabPage->SetUserData(sUserData); + + PageCreated(rName, *pDataObject->pTabPage); + pDataObject->pTabPage->Reset(m_pSet); +} + +void SfxTabDialogController::RemoveTabPage(const OString& rId) + +/* [Description] + + Delete the TabPage with ID nId +*/ + +{ + sal_uInt16 nPos = 0; + m_xTabCtrl->remove_page(rId); + Data_Impl* pDataObject = Find( m_pImpl->aData, rId, &nPos ); + + if ( pDataObject ) + { + if ( pDataObject->pTabPage ) + { + pDataObject->pTabPage->FillUserData(); + OUString aPageData( pDataObject->pTabPage->GetUserData() ); + if ( !aPageData.isEmpty() ) + { + // save settings of this page (user data) + OUString sConfigId = OStringToOUString(pDataObject->pTabPage->GetConfigId(), + RTL_TEXTENCODING_UTF8); + SvtViewOptions aPageOpt(EViewType::TabPage, sConfigId); + aPageOpt.SetUserItem( USERITEM_NAME, makeAny( aPageData ) ); + } + + pDataObject->pTabPage.disposeAndClear(); + } + + delete pDataObject; + m_pImpl->aData.erase( m_pImpl->aData.begin() + nPos ); + } + else + { + SAL_INFO( "sfx.dialog", "TabPage-Id not known" ); + } +} + +void SfxTabDialogController::Start_Impl() +{ + assert(m_pImpl->aData.size() == static_cast<size_t>(m_xTabCtrl->get_n_pages()) + && "not all pages registered"); + + // load old settings, when exists + SvtViewOptions aDlgOpt(EViewType::TabDialog, OStringToOUString(m_xDialog->get_help_id(), RTL_TEXTENCODING_UTF8)); + if (aDlgOpt.Exists()) + m_xTabCtrl->set_current_page(aDlgOpt.GetPageID()); + + ActivatePageHdl(m_xTabCtrl->get_current_page_ident()); +} + +void SfxTabDialogController::SetCurPageId(const OString& rIdent) +{ + m_xTabCtrl->set_current_page(rIdent); +} + +short SfxTabDialogController::execute() +{ + Start_Impl(); + return m_xDialog->run(); +} + +void SfxTabDialogController::SetInputSet( const SfxItemSet* pInSet ) + +/* [Description] + + With this method the Input-Set can subsequently be set initially or re-set. +*/ + +{ + bool bSet = ( m_pSet != nullptr ); + delete m_pSet; + m_pSet = pInSet ? new SfxItemSet(*pInSet) : nullptr; + + if (!bSet && !m_pExampleSet && !m_pOutSet && m_pSet) + { + m_pExampleSet = new SfxItemSet( *m_pSet ); + m_pOutSet.reset(new SfxItemSet( *m_pSet->GetPool(), m_pSet->GetRanges() )); + } +} + +SfxItemSet* SfxTabDialogController::GetInputSetImpl() + +/* [Description] + + Derived classes may create new storage for the InputSet. This has to be + released in the Destructor. To do this, this method must be called. +*/ + +{ + return m_pSet; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |