Make Chart Creation Wizard async

* FuInsertChart as a memeber in ScTabViewShell
  stores instance is needed to react on the dialog's result
* CreationWizardUnoDlg converted to XAsynchronousExecutableDialog
  added dialog close handler which notifies listeners
  In the Online dialog become dead after closing, additional
  PostUserEvent was needed to kill the dialog after real close
  (without it user needed to select any cell to close dialog)
* Reuse in Writer

Change-Id: Ib09b5d83af9e1aa67218e093aa161419e8ddb922
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90380
Tested-by: Jenkins
Reviewed-by: Szymon Kłos <szymon.klos@collabora.com>
This commit is contained in:
Szymon Kłos 2019-04-17 17:33:10 +02:00
parent 835bced249
commit 77445e201c
13 changed files with 169 additions and 108 deletions

View file

@ -29,6 +29,8 @@
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <tools/diagnose_ex.h>
#include <comphelper/lok.hxx>
#include <sfx2/viewsh.hxx>
namespace chart
{
@ -81,9 +83,9 @@ void SAL_CALL CreationWizardUnoDlg::release() throw ()
}
uno::Any SAL_CALL CreationWizardUnoDlg::queryAggregation( uno::Type const & rType )
{
if (rType == cppu::UnoType<ui::dialogs::XExecutableDialog>::get())
if (rType == cppu::UnoType<ui::dialogs::XAsynchronousExecutableDialog>::get())
{
void * p = static_cast< ui::dialogs::XExecutableDialog * >( this );
void * p = static_cast< ui::dialogs::XAsynchronousExecutableDialog * >( this );
return uno::Any( &p, rType );
}
else if (rType == cppu::UnoType<lang::XServiceInfo>::get())
@ -118,9 +120,8 @@ uno::Sequence< uno::Type > CreationWizardUnoDlg::getTypes()
cppu::UnoType<lang::XServiceInfo>::get(),
cppu::UnoType<lang::XInitialization>::get(),
cppu::UnoType<frame::XTerminateListener>::get(),
cppu::UnoType<ui::dialogs::XExecutableDialog>::get(),
cppu::UnoType<ui::dialogs::XAsynchronousExecutableDialog>::get(),
cppu::UnoType<beans::XPropertySet>::get() };
return aTypeList;
}
@ -145,7 +146,7 @@ void SAL_CALL CreationWizardUnoDlg::disposing( const lang::EventObject& /*Source
//Listener should deregister himself and release all references to the closing object.
}
void SAL_CALL CreationWizardUnoDlg::setTitle( const OUString& /*rTitle*/ )
void SAL_CALL CreationWizardUnoDlg::setDialogTitle( const OUString& /*rTitle*/ )
{
}
void CreationWizardUnoDlg::createDialogOnDemand()
@ -169,24 +170,41 @@ void CreationWizardUnoDlg::createDialogOnDemand()
uno::Reference< XComponent > xKeepAlive( this );
if( m_xChartModel.is() )
{
m_xDialog = std::make_unique<CreationWizard>(Application::GetFrameWeld(m_xParentWindow), m_xChartModel, m_xCC);
m_xDialog = std::make_shared<CreationWizard>(Application::GetFrameWeld(m_xParentWindow), m_xChartModel, m_xCC);
}
}
sal_Int16 SAL_CALL CreationWizardUnoDlg::execute( )
IMPL_STATIC_LINK_NOARG(CreationWizardUnoDlg, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*)
{
sal_Int16 nRet = ui::dialogs::ExecutableDialogResults::CANCEL;
{
SolarMutexGuard aSolarGuard;
createDialogOnDemand();
if (!m_xDialog)
return nRet;
TimerTriggeredControllerLock aTimerTriggeredControllerLock( m_xChartModel );
if( m_bUnlockControllersOnExecute && m_xChartModel.is() )
m_xChartModel->unlockControllers();
nRet = m_xDialog->run();
}
return nRet;
return SfxViewShell::Current();
}
void SAL_CALL CreationWizardUnoDlg::startExecuteModal( const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener )
{
SolarMutexGuard aSolarGuard;
createDialogOnDemand();
if( !m_xDialog )
return;
m_xDialog->getDialog()->SetInstallLOKNotifierHdl(
LINK(this, CreationWizardUnoDlg, InstallLOKNotifierHdl));
TimerTriggeredControllerLock aTimerTriggeredControllerLock( m_xChartModel );
if( m_bUnlockControllersOnExecute && m_xChartModel.is() )
m_xChartModel->unlockControllers();
CreationWizardUnoDlg* xThat = this;
weld::DialogController::runAsync(m_xDialog, [xListener, xThat](sal_Int32 nResult){
if( xListener.is() )
{
::css::uno::Reference< ::css::uno::XInterface > xSource;
// Notify UNO listener to perform correct action depending on the result
css::ui::dialogs::DialogClosedEvent aEvent( xSource, nResult );
xListener->dialogClosed( aEvent );
}
xThat->m_xDialog.reset();
});
}
void SAL_CALL CreationWizardUnoDlg::initialize( const uno::Sequence< uno::Any >& aArguments )

View file

@ -26,9 +26,13 @@
#include <com/sun/star/frame/XTerminateListener.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
#include "dlg_CreationWizard.hxx"
#include <tools/link.hxx>
#include <vcl/vclptr.hxx>
#include <vcl/vclevent.hxx>
namespace com::sun::star::awt { class XWindow; }
namespace com::sun::star::frame { class XModel; }
@ -41,7 +45,7 @@ namespace chart
class CreationWizardUnoDlg : public MutexContainer
, public ::cppu::OComponentHelper
, public css::ui::dialogs::XExecutableDialog
, public css::ui::dialogs::XAsynchronousExecutableDialog
, public css::lang::XServiceInfo
, public css::lang::XInitialization
, public css::frame::XTerminateListener
@ -68,9 +72,9 @@ public:
virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
// XExecutableDialog
virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
virtual sal_Int16 SAL_CALL execute( ) override;
// XAsynchronousExecutableDialog
virtual void SAL_CALL setDialogTitle( const OUString& aTitle ) override;
virtual void SAL_CALL startExecuteModal( const css::uno::Reference<css::ui::dialogs::XDialogClosedListener>& xListener ) override;
// XInitialization
virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
@ -97,13 +101,14 @@ protected:
private:
void createDialogOnDemand();
DECL_STATIC_LINK(CreationWizardUnoDlg, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*);
private:
css::uno::Reference< css::frame::XModel > m_xChartModel;
css::uno::Reference< css::uno::XComponentContext> m_xCC;
css::uno::Reference< css::awt::XWindow > m_xParentWindow;
std::unique_ptr<CreationWizard> m_xDialog;
std::shared_ptr<CreationWizard> m_xDialog;
bool m_bUnlockControllersOnExecute;
};

View file

@ -53,10 +53,12 @@
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <com/sun/star/ui/dialogs/XDialogClosedListener.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/chart/ChartDataRowSource.hpp>
#include <cppuhelper/bootstrap.hxx>
#include <svtools/dialogclosedlistener.hxx>
#include <PivotTableDataProvider.hxx>
#include <chart2uno.hxx>
@ -399,7 +401,7 @@ FuInsertOLE::FuInsertOLE(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView*
}
FuInsertChart::FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
SdrModel* pDoc, SfxRequest& rReq)
SdrModel* pDoc, SfxRequest& rReq, const Link<css::ui::dialogs::DialogClosedEvent*, void>& rLink)
: FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
{
const SfxItemSet* pReqArgs = rReq.GetArgs();
@ -597,11 +599,10 @@ FuInsertChart::FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawV
// pView->InsertObjectAtView(pObj, *pPV);//this call leads to an immediate redraw and asks the chart for a visual representation
// use the page instead of the view to insert, so no undo action is created yet
SdrPage* pInsPage = pPV->GetPage();
pInsPage->InsertObject( pObj );
SdrPage* pPage = pPV->GetPage();
pPage->InsertObject( pObj );
pView->UnmarkAllObj();
pView->MarkObj( pObj, pPV );
bool bAddUndo = true; // add undo action later, unless the dialog is canceled
if (rReq.IsAPI())
{
@ -625,7 +626,7 @@ FuInsertChart::FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawV
uno::Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
if(xMCF.is())
{
uno::Reference< ui::dialogs::XExecutableDialog > xDialog(
css::uno::Reference<css::ui::dialogs::XAsynchronousExecutableDialog> xDialog(
xMCF->createInstanceWithContext(
"com.sun.star.comp.chart2.WizardDialog"
, xContext), uno::UNO_QUERY);
@ -670,62 +671,22 @@ FuInsertChart::FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawV
}
}
sal_Int16 nDialogRet = xDialog->execute();
if( nDialogRet == ui::dialogs::ExecutableDialogResults::CANCEL )
{
// leave OLE inplace mode and unmark
OSL_ASSERT( pView );
rViewShell.DeactivateOle();
pView->UnmarkAll();
pView->AddUndo(std::make_unique<SdrUndoNewObj>(*pObj));
::svt::DialogClosedListener* pListener = new ::svt::DialogClosedListener();
pListener->SetDialogClosedLink( rLink );
css::uno::Reference<css::ui::dialogs::XDialogClosedListener> xListener( pListener );
// old page view pointer is invalid after switching sheets
pPV = pView->GetSdrPageView();
// remove the chart
OSL_ASSERT( pPV );
SdrPage * pPage( pPV->GetPage());
OSL_ASSERT( pPage );
OSL_ASSERT( pObj );
if( pPage )
{
// Remove the OLE2 object from the sdr page.
SdrObject* pRemoved = pPage->RemoveObject(pObj->GetOrdNum());
OSL_ASSERT(pRemoved == pObj);
SdrObject::Free(pRemoved); // Don't forget to free it.
}
bAddUndo = false; // don't create the undo action for inserting
// leave the draw shell
rViewShell.SetDrawShell( false );
// reset marked cell area
rViewSh.GetViewData().GetViewShell()->SetMarkData(aMark);
}
else
{
OSL_ASSERT( nDialogRet == ui::dialogs::ExecutableDialogResults::OK );
//@todo maybe move chart to different table
}
xDialog->startExecuteModal( xListener );
}
else
{
uno::Reference< lang::XComponent > xComponent( xDialog, uno::UNO_QUERY );
if( xComponent.is())
xComponent->dispose();
}
uno::Reference< lang::XComponent > xComponent( xDialog, uno::UNO_QUERY );
if( xComponent.is())
xComponent->dispose();
}
}
}
else if( xChartModel.is() )
xChartModel->unlockControllers();
if ( bAddUndo )
{
// add undo action the same way as in SdrEditView::InsertObjectAtView
// (using UndoActionHdl etc.)
pView->AddUndo(std::make_unique<SdrUndoNewObj>(*pObj));
}
// BM/IHA --
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -22,6 +22,9 @@
#include "fupoor.hxx"
#include <scdllapi.h>
#include <svx/svdoole2.hxx>
#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
class FuInsertGraphic : public FuPoor
{
@ -40,9 +43,10 @@ public:
class FuInsertChart : public FuPoor
{
public:
FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pView,
SdrModel* pDoc, SfxRequest& rReq);
public:
FuInsertChart( ScTabViewShell& pViewSh, vcl::Window* pWin, ScDrawView* pView,
SdrModel* pDoc, SfxRequest& rReq,
const Link<css::ui::dialogs::DialogClosedEvent*, void>& rLink);
};
class FuInsertMedia : public FuPoor

View file

@ -32,6 +32,7 @@
#include "target.hxx"
#include <shellids.hxx>
#include <tabprotection.hxx>
#include <com/sun/star/ui/dialogs/XDialogClosedListener.hpp>
#include <memory>
#include <map>
@ -178,6 +179,7 @@ private:
DECL_LINK( SimpleRefAborted, const OUString&, void );
DECL_LINK( SimpleRefChange, const OUString&, void );
DECL_LINK( FormControlActivated, LinkParamNone*, void );
DECL_LINK( DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void );
protected:
virtual void Activate(bool bMDI) override;

View file

@ -87,7 +87,7 @@ void ScTabViewShell::ExecDraw(SfxRequest& rReq)
if ( nNewId == SID_DRAW_CHART )
{
// #i71254# directly insert a chart instead of drawing its output rectangle
FuInsertChart(*this, pWin, pView, pDoc, rReq);
FuInsertChart(*this, pWin, pView, pDoc, rReq, LINK( this, ScTabViewShell, DialogClosedHdl ));
return;
}

View file

@ -56,6 +56,7 @@
#include <inputwin.hxx>
#include <dbdata.hxx>
#include <reffact.hxx>
#include <fuinsert.hxx>
#include <viewuno.hxx>
#include <dispuno.hxx>
#include <chgtrack.hxx>

View file

@ -57,6 +57,8 @@
#include <drawview.hxx>
#include <ChartRangeSelectionListener.hxx>
#include <gridwin.hxx>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <svx/svdpagv.hxx>
#include <comphelper/lok.hxx>
@ -296,6 +298,37 @@ void ScTabViewShell::DeactivateOle()
pClient->DeactivateObject();
}
IMPL_LINK( ScTabViewShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvent, void )
{
if( pEvent->DialogResult == ui::dialogs::ExecutableDialogResults::CANCEL )
{
ScTabView* pTabView = GetViewData().GetView();
ScDrawView* pView = pTabView->GetScDrawView();
ScViewData& rData = GetViewData();
ScDocShell* pScDocSh = rData.GetDocShell();
ScDocument& rScDoc = pScDocSh->GetDocument();
// leave OLE inplace mode and unmark
OSL_ASSERT( pView );
DeactivateOle();
pView->UnMarkAll();
rScDoc.GetUndoManager()->Undo();
rScDoc.GetUndoManager()->ClearRedo();
// leave the draw shell
SetDrawShell( false );
// reset marked cell area
ScMarkData aMark = GetViewData().GetMarkData();
GetViewData().GetViewShell()->SetMarkData(aMark);
}
else
{
OSL_ASSERT( pEvent->DialogResult == ui::dialogs::ExecutableDialogResults::OK );
//@todo maybe move chart to different table
}
}
void ScTabViewShell::ExecDrawIns(SfxRequest& rReq)
{
sal_uInt16 nSlot = rReq.GetSlot();
@ -333,7 +366,7 @@ void ScTabViewShell::ExecDrawIns(SfxRequest& rReq)
break;
case SID_INSERT_DIAGRAM:
FuInsertChart(*this, pWin, pView, pDrModel, rReq);
FuInsertChart(*this, pWin, pView, pDrModel, rReq, LINK( this, ScTabViewShell, DialogClosedHdl ));
if (comphelper::LibreOfficeKit::isActive())
pDocSh->SetModified();
break;

View file

@ -20,11 +20,17 @@
#define INCLUDED_SW_SOURCE_UIBASE_INC_CHARTINS_HXX
#include <tools/gen.hxx>
#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
namespace vcl { class Window; }
Point SwGetChartDialogPos( const vcl::Window *pParentWin, const Size& rDialogSize, const tools::Rectangle& rLogicChart );
void SwInsertChart();
class SwInsertChart
{
public:
SwInsertChart( const Link<css::ui::dialogs::DialogClosedEvent*,void>& rLink );
};
#endif // INCLUDED_SW_SOURCE_UIBASE_INC_CHARTINS_HXX

View file

@ -22,11 +22,13 @@
#include "basesh.hxx"
#include <unotools/caserotate.hxx>
#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
class AbstractSvxPostItDialog;
class SwFieldMgr;
class SwFlyFrameAttrMgr;
class SvxHyperlinkItem;
class SwInsertChart;
class SW_DLLPUBLIC SwTextShell: public SwBaseShell
{
@ -46,6 +48,7 @@ private:
public:
DECL_LINK( RedlineNextHdl, AbstractSvxPostItDialog&, void );
DECL_LINK( RedlinePrevHdl, AbstractSvxPostItDialog&, void );
DECL_STATIC_LINK( SwTextShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, void );
void Execute(SfxRequest &);
void GetState(SfxItemSet &);

View file

@ -87,9 +87,30 @@ using namespace ::com::sun::star;
#include <drawdoc.hxx>
#include <svtools/embedhlp.hxx>
#include <sfx2/event.hxx>
#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <IDocumentUndoRedo.hxx>
SFX_IMPL_INTERFACE(SwTextShell, SwBaseShell)
IMPL_STATIC_LINK( SwTextShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvent, void )
{
SwView* pView = ::GetActiveView();
SwWrtShell& rWrtShell = pView->GetWrtShell();
sal_Int16 nDialogRet = pEvent->DialogResult;
if( nDialogRet == ui::dialogs::ExecutableDialogResults::CANCEL )
{
rWrtShell.Undo();
rWrtShell.GetIDocumentUndoRedo().ClearRedo();
}
else
{
OSL_ENSURE( nDialogRet == ui::dialogs::ExecutableDialogResults::OK,
"dialog execution failed" );
}
}
void SwTextShell::InitInterface_Impl()
{
GetStaticInterface()->RegisterPopupMenu("text");
@ -303,7 +324,7 @@ void SwTextShell::ExecInsert(SfxRequest &rReq)
break;
if(!rReq.IsAPI())
{
SwInsertChart();
SwInsertChart( LINK( this, SwTextShell, DialogClosedHdl ) );
}
else
{

View file

@ -41,11 +41,12 @@
#include <com/sun/star/awt/Point.hpp>
#include <com/sun/star/awt/Size.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <svtools/dialogclosedlistener.hxx>
#include <com/sun/star/chart2/data/XDataProvider.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
using namespace ::com::sun::star;
@ -122,7 +123,7 @@ Point SwGetChartDialogPos( const vcl::Window *pParentWin, const Size& rDialogSiz
return aRet;
}
void SwInsertChart()
SwInsertChart::SwInsertChart( const Link<css::ui::dialogs::DialogClosedEvent*, void>& rLink )
{
SwView *pView = ::GetActiveView();
@ -162,7 +163,7 @@ void SwInsertChart()
uno::Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
if(xMCF.is())
{
uno::Reference< ui::dialogs::XExecutableDialog > xDialog(
uno::Reference< ui::dialogs::XAsynchronousExecutableDialog > xDialog(
xMCF->createInstanceWithContext(
"com.sun.star.comp.chart2.WizardDialog", xContext),
uno::UNO_QUERY);
@ -208,21 +209,18 @@ void SwInsertChart()
}
}
sal_Int16 nDialogRet = xDialog->execute();
if( nDialogRet == ui::dialogs::ExecutableDialogResults::CANCEL )
{
rWrtShell.Undo();
rWrtShell.GetIDocumentUndoRedo().ClearRedo();
}
else
{
OSL_ENSURE( nDialogRet == ui::dialogs::ExecutableDialogResults::OK,
"dialog execution failed" );
}
::svt::DialogClosedListener* pListener = new ::svt::DialogClosedListener();
pListener->SetDialogClosedLink( rLink );
css::uno::Reference<css::ui::dialogs::XDialogClosedListener> xListener( pListener );
xDialog->startExecuteModal( xListener );
}
else
{
uno::Reference< lang::XComponent > xComponent( xDialog, uno::UNO_QUERY );
if( xComponent.is())
xComponent->dispose();
}
uno::Reference< lang::XComponent > xComponent( xDialog, uno::UNO_QUERY );
if( xComponent.is())
xComponent->dispose();
}
}
}

View file

@ -1087,11 +1087,17 @@ namespace vcl
{
if ( isTravelingSuspended() )
return;
WizardTravelSuspension aTravelGuard( *this );
if (!prepareLeaveCurrentState(WizardTypes::eFinish))
// prevent WizardTravelSuspension from using this instance
// after will be destructed due to onFinish and async response call
{
return;
WizardTravelSuspension aTravelGuard( *this );
if (!prepareLeaveCurrentState(WizardTypes::eFinish))
{
return;
}
}
onFinish();
}
@ -1386,6 +1392,9 @@ namespace vcl
void WizardMachine::resumeTraveling( AccessGuard )
{
if (!m_pImpl)
return;
DBG_ASSERT( m_pImpl->m_bTravelingSuspended, "WizardMachine::resumeTraveling: nothing to resume!" );
m_pImpl->m_bTravelingSuspended = false;
}