From 26c375671aa362b2f59d84645784938677ae1719 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Thu, 4 Oct 2018 12:41:22 +0100 Subject: weld SwWordCountFloatDlg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit enable modeless dialogs to emit a response so runAsync can be used with them and get something called when the dialog is dismissed Change-Id: Ie9603bcc063cefabbae635949671baf06620785d Reviewed-on: https://gerrit.libreoffice.org/61383 Tested-by: Jenkins Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara --- sfx2/source/appl/childwin.cxx | 73 +++++++++++++++++------ sfx2/source/appl/workwin.cxx | 85 +++++++++++++++++++++++---- sfx2/source/dialog/basedlgs.cxx | 126 +++++++++++++++++++++++++++++++++++++++- sfx2/source/inc/workwin.hxx | 11 ++++ 4 files changed, 265 insertions(+), 30 deletions(-) (limited to 'sfx2') diff --git a/sfx2/source/appl/childwin.cxx b/sfx2/source/appl/childwin.cxx index aa8018eb0ed4..e2bbc3ee9e7f 100644 --- a/sfx2/source/appl/childwin.cxx +++ b/sfx2/source/appl/childwin.cxx @@ -194,7 +194,10 @@ SfxChildWindow::~SfxChildWindow() { pContext.reset(); ClearWorkwin(); - pWindow.disposeAndClear(); + if (xController) + xController->DeInit(); + else + pWindow.disposeAndClear(); } @@ -270,7 +273,7 @@ SfxChildWindow* SfxChildWindow::CreateChildWindow( sal_uInt16 nId, DBG_ASSERT(pFact && (pChild || !rInfo.bVisible), "ChildWindow-Typ not registered!"); - if ( pChild && !pChild->pWindow ) + if (pChild && (!pChild->pWindow && !pChild->xController)) { DELETEZ(pChild); SAL_INFO("sfx.appl", "ChildWindow has no Window!"); @@ -319,26 +322,38 @@ void SfxChildWindow::SetAlignment(SfxChildAlignment eAlign) SfxChildWinInfo SfxChildWindow::GetInfo() const { - SfxChildWinInfo aInfo(pImpl->pFact->aInfo); - aInfo.aPos = pWindow->GetPosPixel(); - aInfo.aSize = pWindow->GetSizePixel(); - if ( pWindow->IsSystemWindow() ) + if (xController) { + weld::Dialog* pDialog = xController->getDialog(); + aInfo.aPos = pDialog->get_position(); + aInfo.aSize = pDialog->get_size(); WindowStateMask nMask = WindowStateMask::Pos | WindowStateMask::State; - if ( pWindow->GetStyle() & WB_SIZEABLE ) - nMask |= ( WindowStateMask::Width | WindowStateMask::Height ); - aInfo.aWinState = static_cast(pWindow.get())->GetWindowState( nMask ); + if (pDialog->get_resizable()) + nMask |= (WindowStateMask::Width | WindowStateMask::Height); + aInfo.aWinState = pDialog->get_window_state(nMask); } - else if (DockingWindow* pDockingWindow = dynamic_cast(pWindow.get())) + else if (pWindow) { - if (pDockingWindow->GetFloatingWindow()) - aInfo.aWinState = pDockingWindow->GetFloatingWindow()->GetWindowState(); - else if (SfxDockingWindow* pSfxDockingWindow = dynamic_cast(pDockingWindow)) + aInfo.aPos = pWindow->GetPosPixel(); + aInfo.aSize = pWindow->GetSizePixel(); + if ( pWindow->IsSystemWindow() ) { - SfxChildWinInfo aTmpInfo; - pSfxDockingWindow->FillInfo( aTmpInfo ); - aInfo.aExtraString = aTmpInfo.aExtraString; + WindowStateMask nMask = WindowStateMask::Pos | WindowStateMask::State; + if ( pWindow->GetStyle() & WB_SIZEABLE ) + nMask |= ( WindowStateMask::Width | WindowStateMask::Height ); + aInfo.aWinState = static_cast(pWindow.get())->GetWindowState( nMask ); + } + else if (DockingWindow* pDockingWindow = dynamic_cast(pWindow.get())) + { + if (pDockingWindow->GetFloatingWindow()) + aInfo.aWinState = pDockingWindow->GetFloatingWindow()->GetWindowState(); + else if (SfxDockingWindow* pSfxDockingWindow = dynamic_cast(pDockingWindow)) + { + SfxChildWinInfo aTmpInfo; + pSfxDockingWindow->FillInfo( aTmpInfo ); + aInfo.aExtraString = aTmpInfo.aExtraString; + } } } @@ -608,12 +623,24 @@ void SfxChildWindow::SetVisible_Impl( bool bVis ) void SfxChildWindow::Hide() { - pWindow->Hide(); + if (xController) + xController->EndDialog(); + else + pWindow->Hide(); } void SfxChildWindow::Show( ShowFlags nFlags ) { - pWindow->Show(true, nFlags); + if (xController) + { + if (!xController->getDialog()->get_visible()) + { + weld::DialogController::runAsync(xController, + [=](sal_Int32 /*nResult*/){ xController->Close(); }); + } + } + else + pWindow->Show(true, nFlags); } vcl::Window* SfxChildWindow::GetContextWindow( SfxModule const *pModule ) const @@ -646,7 +673,15 @@ bool SfxChildWindow::QueryClose() } if ( bAllow ) - bAllow = !GetWindow()->IsInModalMode(); + { + if (GetController()) + { + weld::Dialog* pDialog = GetController()->getDialog(); + bAllow = !pDialog->get_visible() || !pDialog->get_modal(); + } + else if (GetWindow()) + bAllow = !GetWindow()->IsInModalMode(); + } return bAllow; } diff --git a/sfx2/source/appl/workwin.cxx b/sfx2/source/appl/workwin.cxx index 363b3005d1f9..69e29d2e6d83 100644 --- a/sfx2/source/appl/workwin.cxx +++ b/sfx2/source/appl/workwin.cxx @@ -864,7 +864,6 @@ bool SfxWorkWindow::PrepareClose_Impl() return true; } - SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl( vcl::Window& rWindow, SfxChildAlignment eAlign ) { @@ -885,6 +884,19 @@ SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl( vcl::Window& rWindow, return aChildren.back(); } +SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl(std::shared_ptr& rController, + SfxChildAlignment eAlign ) +{ + DBG_ASSERT( aChildren.size() < 255, "too many children" ); + DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" ); + + SfxChild_Impl *pChild = new SfxChild_Impl(rController, eAlign); + + aChildren.push_back(pChild); + bSorted = false; + nChildren++; + return aChildren.back(); +} void SfxWorkWindow::ReleaseChild_Impl( vcl::Window& rWindow ) { @@ -910,6 +922,29 @@ void SfxWorkWindow::ReleaseChild_Impl( vcl::Window& rWindow ) } } +void SfxWorkWindow::ReleaseChild_Impl(SfxModelessDialogController& rController) +{ + + SfxChild_Impl *pChild = nullptr; + decltype(aChildren)::size_type nPos; + for ( nPos = 0; nPos < aChildren.size(); ++nPos ) + { + pChild = aChildren[nPos]; + if (pChild && pChild->xController.get() == &rController) + break; + } + + if ( nPos < aChildren.size() ) + { + bSorted = false; + nChildren--; + aChildren.erase(aChildren.begin() + nPos); + delete pChild; + } + else { + OSL_FAIL( "releasing unregistered child" ); + } +} SfxChild_Impl* SfxWorkWindow::FindChild_Impl( const vcl::Window& rWindow ) const { @@ -933,8 +968,10 @@ void SfxWorkWindow::ShowChildren_Impl() for (SfxChild_Impl* pCli : aChildren) { + if (!pCli) + continue; SfxChildWin_Impl* pCW = nullptr; - if ( pCli && pCli->pWin ) + if (pCli->pWin || pCli->xController) { // We have to find the SfxChildWin_Impl to retrieve the // SFX_CHILDWIN flags that can influence visibility. @@ -961,12 +998,27 @@ void SfxWorkWindow::ShowChildren_Impl() if ( SfxChildVisibility::VISIBLE == (pCli->nVisible & SfxChildVisibility::VISIBLE) && bVisible ) { ShowFlags nFlags = pCli->bSetFocus ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate; - pCli->pWin->Show(true, nFlags); + if (pCli->xController) + { + if (!pCli->xController->getDialog()->get_visible()) + { + weld::DialogController::runAsync(pCli->xController, + [=](sal_Int32 /*nResult*/){ pCli->xController->Close(); }); + } + } + else + pCli->pWin->Show(true, nFlags); pCli->bSetFocus = false; } else { - pCli->pWin->Hide(); + if (pCli->xController) + { + if (pCli->xController->getDialog()->get_visible()) + pCli->xController->response(RET_CLOSE); + } + else + pCli->pWin->Hide(); } } } @@ -978,12 +1030,15 @@ void SfxWorkWindow::HideChildren_Impl() for ( sal_uInt16 nPos = aChildren.size(); nPos > 0; --nPos ) { SfxChild_Impl *pChild = aChildren[nPos-1]; - if (pChild && pChild->pWin) + if (!pChild) + continue; + if (pChild->xController) + pChild->xController->response(RET_CLOSE); + else if (pChild->pWin) pChild->pWin->Hide(); } } - void SfxWorkWindow::ResetObjectBars_Impl() { for ( auto & n: aObjBarList ) @@ -1324,7 +1379,10 @@ void SfxWorkWindow::CreateChildWin_Impl( SfxChildWin_Impl *pCW, bool bSetFocus ) { // The window is not docked or docked outside of one split windows // and must therefore be registered explicitly as a Child - pCW->pCli = RegisterChild_Impl(*(pChildWin->GetWindow()), pChildWin->GetAlignment()); + if (pChildWin->GetController()) + pCW->pCli = RegisterChild_Impl(pChildWin->GetController(), pChildWin->GetAlignment()); + else + pCW->pCli = RegisterChild_Impl(*(pChildWin->GetWindow()), pChildWin->GetAlignment()); pCW->pCli->nVisible = SfxChildVisibility::VISIBLE; if ( pChildWin->GetAlignment() != SfxChildAlignment::NOALIGNMENT && bIsFullScreen ) pCW->pCli->nVisible ^= SfxChildVisibility::ACTIVE; @@ -1363,7 +1421,10 @@ void SfxWorkWindow::RemoveChildWin_Impl( SfxChildWin_Impl *pCW ) // Child window is a direct child window and must therefore unregister // itself from the WorkWindow pCW->pCli = nullptr; - ReleaseChild_Impl(*pChildWin->GetWindow()); + if (pChildWin->GetController()) + ReleaseChild_Impl(*pChildWin->GetController()); + else + ReleaseChild_Impl(*pChildWin->GetWindow()); } else { @@ -2382,8 +2443,12 @@ void SfxWorkWindow::DataChanged_Impl() for (n=0; npWin ) - pCW->pWin->GetWindow()->UpdateSettings( Application::GetSettings() ); + if (pCW && pCW->pWin) + { + // TODO does this really have any meaning ? + if (pCW->pWin->GetWindow()) + pCW->pWin->GetWindow()->UpdateSettings(Application::GetSettings()); + } } ArrangeChildren_Impl(); diff --git a/sfx2/source/dialog/basedlgs.cxx b/sfx2/source/dialog/basedlgs.cxx index f4a07696af43..8fcb0cb1137f 100644 --- a/sfx2/source/dialog/basedlgs.cxx +++ b/sfx2/source/dialog/basedlgs.cxx @@ -56,6 +56,7 @@ public: OString aWinState; SfxChildWindow* pMgr; bool bConstructed; + bool bClosing; void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; Idle aMoveIdle; @@ -284,6 +285,7 @@ void SfxModelessDialog::Init(SfxBindings *pBindinx, SfxChildWindow *pCW) pImpl.reset(new SfxModelessDialog_Impl); pImpl->pMgr = pCW; pImpl->bConstructed = false; + pImpl->bClosing = false; if ( pBindinx ) pImpl->StartListening( *pBindinx ); pImpl->aMoveIdle.SetPriority(TaskPriority::RESIZE); @@ -382,6 +384,129 @@ void SfxModelessDialog::FillInfo(SfxChildWinInfo& rInfo) const rInfo.nFlags |= SfxChildWindowFlags::ZOOMIN; } +void SfxModelessDialogController::Initialize(SfxChildWinInfo const *pInfo) + +/* [Description] + + Initialization of the class SfxModelessDialog via a SfxChildWinInfo. + The initialization is done only in a 2nd step after the constructor, this + constructor should be called from the derived class or from the + SfxChildWindows. +*/ + +{ + if (!pInfo) + return; + m_xImpl->aWinState = pInfo->aWinState; + if (m_xImpl->aWinState.isEmpty()) + return; + m_xDialog->set_window_state(m_xImpl->aWinState); +} + +SfxModelessDialogController::SfxModelessDialogController(SfxBindings* pBindinx, + SfxChildWindow *pCW, weld::Window *pParent, const OUString& rUIXMLDescription, + const OString& rID) + : SfxDialogController(pParent, rUIXMLDescription, rID) +{ + Init(pBindinx, pCW); + m_xDialog->connect_focus_in(LINK(this, SfxModelessDialogController, FocusInHdl)); + m_xDialog->connect_focus_out(LINK(this, SfxModelessDialogController, FocusOutHdl)); +} + +void SfxModelessDialogController::Init(SfxBindings *pBindinx, SfxChildWindow *pCW) +{ + m_pBindings = pBindinx; + m_xImpl.reset(new SfxModelessDialog_Impl); + m_xImpl->pMgr = pCW; + m_xImpl->bConstructed = true; + m_xImpl->bClosing = false; + if (pBindinx) + m_xImpl->StartListening( *pBindinx ); +} + +void SfxModelessDialogController::DeInit() +{ + if (m_xImpl->pMgr) + { + WindowStateMask nMask = WindowStateMask::Pos | WindowStateMask::State; + if (m_xDialog->get_resizable()) + nMask |= ( WindowStateMask::Width | WindowStateMask::Height ); + m_xImpl->aWinState = m_xDialog->get_window_state(nMask); + GetBindings().GetWorkWindow_Impl()->ConfigChild_Impl( SfxChildIdentifier::DOCKINGWINDOW, SfxDockingConfig::ALIGNDOCKINGWINDOW, m_xImpl->pMgr->GetType() ); + } + + m_xImpl->pMgr = nullptr; +} + +/* [Description] + + If a ModelessDialog is enabled its ViewFrame will be activated. + This is necessary by PluginInFrames. +*/ +IMPL_LINK_NOARG(SfxModelessDialogController, FocusInHdl, weld::Widget&, void) +{ + if (!m_xImpl) + return; + m_pBindings->SetActiveFrame(m_xImpl->pMgr->GetFrame()); + m_xImpl->pMgr->Activate_Impl(); +} + +IMPL_LINK_NOARG(SfxModelessDialogController, FocusOutHdl, weld::Widget&, void) +{ + if (!m_xImpl) + return; + m_pBindings->SetActiveFrame(css::uno::Reference< css::frame::XFrame>()); +} + +SfxModelessDialogController::~SfxModelessDialogController() +{ + if (!m_xImpl->pMgr) + return; + auto xFrame = m_xImpl->pMgr->GetFrame(); + if (!xFrame) + return; + if (xFrame == m_pBindings->GetActiveFrame()) + m_pBindings->SetActiveFrame(nullptr); +} + +void SfxModelessDialogController::EndDialog() +{ + if (!m_xDialog->get_visible()) + return; + m_xImpl->bClosing = true; + response(RET_CLOSE); + m_xImpl->bClosing = false; +} + +/* [Description] + + The window is closed when the ChildWindow is destroyed by running the + ChildWindow-slots. +*/ +void SfxModelessDialogController::Close() +{ + if (m_xImpl->bClosing) + return; + // Execute with Parameters, since Toggle is ignored by some ChildWindows. + SfxBoolItem aValue(m_xImpl->pMgr->GetType(), false); + m_pBindings->GetDispatcher_Impl()->ExecuteList( + m_xImpl->pMgr->GetType(), + SfxCallMode::RECORD|SfxCallMode::SYNCHRON, { &aValue } ); +} + +/* [Description] + + Fills a SfxChildWinInfo with specific data from SfxModelessDialog, + so that it can be written in the INI file. It is assumed that rinfo + receives all other possible relevant data in the ChildWindow class. + ModelessDialogs have no specific information, so that the base + implementation does nothing and therefore must not be called. +*/ +void SfxModelessDialogController::FillInfo(SfxChildWinInfo& rInfo) const +{ + rInfo.aSize = m_xDialog->get_size(); +} + bool SfxFloatingWindow::EventNotify( NotifyEvent& rEvt ) /* [Description] @@ -756,7 +881,6 @@ void SfxSingleTabDialogController::SetTabPage(SfxTabPage* pTabPage) aUserItem >>= sUserData; m_xSfxPage->SetUserData(sUserData); m_xSfxPage->Reset(GetInputItemSet()); -//TODO m_xSfxPage->Show(); m_xHelpBtn->show(Help::IsContextHelpEnabled()); diff --git a/sfx2/source/inc/workwin.hxx b/sfx2/source/inc/workwin.hxx index 7b37d065afa4..38c41653dfdb 100644 --- a/sfx2/source/inc/workwin.hxx +++ b/sfx2/source/inc/workwin.hxx @@ -84,6 +84,7 @@ namespace o3tl struct SfxChild_Impl { VclPtr pWin; + std::shared_ptr xController; Size aSize; SfxChildAlignment eAlign; SfxChildVisibility nVisible; @@ -97,6 +98,14 @@ struct SfxChild_Impl { nVisible = bIsVisible ? SfxChildVisibility::VISIBLE : SfxChildVisibility::NOT_VISIBLE; } + + SfxChild_Impl(std::shared_ptr& rChild, + SfxChildAlignment eAlignment): + pWin(nullptr), xController(rChild), eAlign(eAlignment), bResize(false), + bSetFocus( false ) + { + nVisible = xController->getDialog()->get_visible() ? SfxChildVisibility::VISIBLE : SfxChildVisibility::NOT_VISIBLE; + } }; struct SfxChildWin_Impl @@ -239,7 +248,9 @@ public: // Methods for all Child windows void DataChanged_Impl(); void ReleaseChild_Impl( vcl::Window& rWindow ); + void ReleaseChild_Impl(SfxModelessDialogController&); SfxChild_Impl* RegisterChild_Impl( vcl::Window& rWindow, SfxChildAlignment eAlign ); + SfxChild_Impl* RegisterChild_Impl(std::shared_ptr& rController, SfxChildAlignment eAlign); void ShowChildren_Impl(); void HideChildren_Impl(); bool PrepareClose_Impl(); -- cgit