2010-10-12 15:53:47 +02:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2003-03-25 17:22:13 +00:00
/*************************************************************************
*
2008-04-11 07:23:31 +00:00
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
2003-03-25 17:22:13 +00:00
*
2010-02-12 15:01:35 +01:00
* Copyright 2000 , 2010 Oracle and / or its affiliates .
2003-03-25 17:22:13 +00:00
*
2008-04-11 07:23:31 +00:00
* OpenOffice . org - a multi - platform office productivity suite
2003-03-25 17:22:13 +00:00
*
2008-04-11 07:23:31 +00:00
* This file is part of OpenOffice . org .
2003-03-25 17:22:13 +00:00
*
2008-04-11 07:23:31 +00:00
* OpenOffice . org is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser General Public License version 3
* only , as published by the Free Software Foundation .
2003-03-25 17:22:13 +00:00
*
2008-04-11 07:23:31 +00:00
* OpenOffice . org is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Lesser General Public License version 3 for more details
* ( a copy is included in the LICENSE file that accompanied this code ) .
2003-03-25 17:22:13 +00:00
*
2008-04-11 07:23:31 +00:00
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice . org . If not , see
* < http : //www.openoffice.org/license.html>
* for a copy of the LGPLv3 License .
2003-03-25 17:22:13 +00:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-16 12:53:13 +00:00
// MARKER(update_precomp.py): autogen include statement, do not remove
# include "precompiled_framework.hxx"
2004-06-10 12:20:58 +00:00
//_______________________________________________
// my own includes
2003-03-25 17:22:13 +00:00
# include <dispatch/closedispatcher.hxx>
2004-06-10 12:20:58 +00:00
# include <pattern/frame.hxx>
2003-03-25 17:22:13 +00:00
# include <threadhelp/readguard.hxx>
# include <threadhelp/writeguard.hxx>
# include <classes/framelistanalyzer.hxx>
# include <services.h>
2004-02-25 16:45:53 +00:00
# include <general.h>
2004-06-10 12:20:58 +00:00
//_______________________________________________
// interface includes
# include <com/sun/star/frame/XDesktop.hpp>
2003-03-25 17:22:13 +00:00
# include <com/sun/star/frame/XController.hpp>
2004-11-16 13:52:50 +00:00
# include <com/sun/star/frame/CommandGroup.hpp>
2009-09-08 04:57:32 +00:00
# include <com/sun/star/lang/DisposedException.hpp>
2007-04-16 15:37:38 +00:00
# include <com/sun/star/awt/XTopWindow.hpp>
2009-09-18 10:15:03 +00:00
# include <com/sun/star/document/XActionLockable.hpp>
2008-03-05 16:22:02 +00:00
# include "com/sun/star/beans/XFastPropertySet.hpp"
2007-04-16 15:37:38 +00:00
# include <toolkit/helper/vclunohelper.hxx>
2004-06-10 12:20:58 +00:00
//_______________________________________________
// includes of other projects
2003-03-25 17:22:13 +00:00
2007-04-16 15:37:38 +00:00
# include <vcl/window.hxx>
2003-03-25 17:22:13 +00:00
# include <vcl/svapp.hxx>
2007-04-16 15:37:38 +00:00
# include <vos/mutex.hxx>
2009-10-06 07:38:24 +02:00
# include <unotools/moduleoptions.hxx>
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
//_______________________________________________
// namespace
2003-03-25 17:22:13 +00:00
namespace framework {
2004-06-10 12:20:58 +00:00
# ifdef fpf
# error "Who uses \"fpf\" as define. It will overwrite my namespace alias ..."
# endif
namespace fpf = : : framework : : pattern : : frame ;
2003-03-25 17:22:13 +00:00
//_______________________________________________
2004-06-10 12:20:58 +00:00
// non exported const
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
static : : rtl : : OUString URL_CLOSEDOC = DECLARE_ASCII ( " .uno:CloseDoc " ) ;
static : : rtl : : OUString URL_CLOSEWIN = DECLARE_ASCII ( " .uno:CloseWin " ) ;
static : : rtl : : OUString URL_CLOSEFRAME = DECLARE_ASCII ( " .uno:CloseFrame " ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
//_______________________________________________
// declarations
2006-10-13 08:42:39 +00:00
DEFINE_XINTERFACE_4 ( CloseDispatcher ,
2004-11-16 13:52:50 +00:00
OWeakObject ,
DIRECT_INTERFACE ( css : : lang : : XTypeProvider ) ,
DIRECT_INTERFACE ( css : : frame : : XNotifyingDispatch ) ,
DIRECT_INTERFACE ( css : : frame : : XDispatch ) ,
2006-10-13 08:42:39 +00:00
DIRECT_INTERFACE ( css : : frame : : XDispatchInformationProvider ) )
2004-06-10 12:20:58 +00:00
// Note: XStatusListener is an implementation detail. Hide it for scripting!
2004-11-16 13:52:50 +00:00
DEFINE_XTYPEPROVIDER_4 ( CloseDispatcher ,
css : : lang : : XTypeProvider ,
css : : frame : : XDispatchInformationProvider ,
css : : frame : : XNotifyingDispatch ,
css : : frame : : XDispatch )
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
2007-04-16 15:37:38 +00:00
CloseDispatcher : : CloseDispatcher ( const css : : uno : : Reference < css : : lang : : XMultiServiceFactory > & xSMGR ,
const css : : uno : : Reference < css : : frame : : XFrame > & xFrame ,
const : : rtl : : OUString & sTarget )
2004-06-10 12:20:58 +00:00
: ThreadHelpBase ( & Application : : GetSolarMutex ( ) )
, : : cppu : : OWeakObject ( )
, m_xSMGR ( xSMGR )
, m_aAsyncCallback ( LINK ( this , CloseDispatcher , impl_asyncCallback ) )
, m_lStatusListener ( m_aLock . getShareableOslMutex ( ) )
2003-03-25 17:22:13 +00:00
{
2007-04-16 15:37:38 +00:00
m_xCloseFrame = CloseDispatcher : : static_impl_searchRightTargetFrame ( xFrame , sTarget ) ;
2003-03-25 17:22:13 +00:00
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
2003-03-25 17:22:13 +00:00
CloseDispatcher : : ~ CloseDispatcher ( )
{
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
void SAL_CALL CloseDispatcher : : dispatch ( const css : : util : : URL & aURL ,
const css : : uno : : Sequence < css : : beans : : PropertyValue > & lArguments )
throw ( css : : uno : : RuntimeException )
2003-03-25 17:22:13 +00:00
{
2004-06-10 12:20:58 +00:00
dispatchWithNotification ( aURL , lArguments , css : : uno : : Reference < css : : frame : : XDispatchResultListener > ( ) ) ;
2003-03-25 17:22:13 +00:00
}
2004-11-16 13:52:50 +00:00
//-----------------------------------------------
css : : uno : : Sequence < sal_Int16 > SAL_CALL CloseDispatcher : : getSupportedCommandGroups ( )
throw ( css : : uno : : RuntimeException )
{
css : : uno : : Sequence < sal_Int16 > lGroups ( 2 ) ;
lGroups [ 0 ] = css : : frame : : CommandGroup : : VIEW ;
lGroups [ 1 ] = css : : frame : : CommandGroup : : DOCUMENT ;
return lGroups ;
}
//-----------------------------------------------
css : : uno : : Sequence < css : : frame : : DispatchInformation > SAL_CALL CloseDispatcher : : getConfigurableDispatchInformation ( sal_Int16 nCommandGroup )
throw ( css : : uno : : RuntimeException )
{
if ( nCommandGroup = = css : : frame : : CommandGroup : : VIEW )
{
/* Attention: Dont add .uno:CloseFrame here. Because its not realy
a configurable feature . . . and further it does not have
a valid UIName entry inside the GenericCommands . xcu . . . */
css : : uno : : Sequence < css : : frame : : DispatchInformation > lViewInfos ( 1 ) ;
lViewInfos [ 0 ] . Command = URL_CLOSEWIN ;
lViewInfos [ 0 ] . GroupId = css : : frame : : CommandGroup : : VIEW ;
return lViewInfos ;
}
else
if ( nCommandGroup = = css : : frame : : CommandGroup : : DOCUMENT )
{
css : : uno : : Sequence < css : : frame : : DispatchInformation > lDocInfos ( 1 ) ;
lDocInfos [ 0 ] . Command = URL_CLOSEDOC ;
lDocInfos [ 0 ] . GroupId = css : : frame : : CommandGroup : : DOCUMENT ;
return lDocInfos ;
}
return css : : uno : : Sequence < css : : frame : : DispatchInformation > ( ) ;
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
2006-06-19 10:15:19 +00:00
void SAL_CALL CloseDispatcher : : addStatusListener ( const css : : uno : : Reference < css : : frame : : XStatusListener > & /*xListener*/ ,
const css : : util : : URL & /*aURL*/ )
2004-06-10 12:20:58 +00:00
throw ( css : : uno : : RuntimeException )
2003-03-25 17:22:13 +00:00
{
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
2006-06-19 10:15:19 +00:00
void SAL_CALL CloseDispatcher : : removeStatusListener ( const css : : uno : : Reference < css : : frame : : XStatusListener > & /*xListener*/ ,
const css : : util : : URL & /*aURL*/ )
2004-06-10 12:20:58 +00:00
throw ( css : : uno : : RuntimeException )
2003-03-25 17:22:13 +00:00
{
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
void SAL_CALL CloseDispatcher : : dispatchWithNotification ( const css : : util : : URL & aURL ,
2009-09-18 10:15:03 +00:00
const css : : uno : : Sequence < css : : beans : : PropertyValue > & lArguments ,
2004-06-10 12:20:58 +00:00
const css : : uno : : Reference < css : : frame : : XDispatchResultListener > & xListener )
throw ( css : : uno : : RuntimeException )
{
// SAFE -> ----------------------------------
WriteGuard aWriteLock ( m_aLock ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// This reference indicates, that we was already called before and
// our asynchronous process was not finished yet.
// We have to reject double calls. Otherwhise we risk,
// that we try to close an already closed resource ...
// And its no problem to do nothing then. The UI user will try it again, if
// non of these jobs was successfully.
if ( m_xSelfHold . is ( ) )
{
aWriteLock . unlock ( ) ;
// <- SAFE ------------------------------
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
implts_notifyResultListener (
xListener ,
css : : frame : : DispatchResultState : : DONTKNOW ,
css : : uno : : Any ( ) ) ;
return ;
}
2003-03-25 17:22:13 +00:00
// First we have to check, if this dispatcher is used right. Means if valid URLs are used.
// If not - we have to break this operation. But an optional listener must be informed.
2004-06-10 12:20:58 +00:00
// BTW: We save the information about the requested operation. Because
// we need it later.
if ( aURL . Complete . equals ( URL_CLOSEDOC ) )
m_eOperation = E_CLOSE_DOC ;
else
if ( aURL . Complete . equals ( URL_CLOSEWIN ) )
m_eOperation = E_CLOSE_WIN ;
else
if ( aURL . Complete . equals ( URL_CLOSEFRAME ) )
m_eOperation = E_CLOSE_FRAME ;
else
2003-03-25 17:22:13 +00:00
{
2004-06-10 12:20:58 +00:00
aWriteLock . unlock ( ) ;
// <- SAFE ------------------------------
implts_notifyResultListener (
2003-03-25 17:22:13 +00:00
xListener ,
css : : frame : : DispatchResultState : : FAILURE ,
css : : uno : : Any ( ) ) ;
return ;
}
// OK - URLs are the right ones.
2004-06-10 12:20:58 +00:00
// But we cant execute synchronously :-)
// May we are called from a generic key-input handler,
// which isnt aware that this call kill its own environment ...
// Do it asynchronous everytimes!
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// But dont forget to hold usself alive.
// We are called back from an environment, which doesnt know an uno reference.
// They call us back by using our c++ interface.
m_xResultListener = xListener ;
m_xSelfHold = css : : uno : : Reference < css : : uno : : XInterface > ( static_cast < : : cppu : : OWeakObject * > ( this ) , css : : uno : : UNO_QUERY ) ;
aWriteLock . unlock ( ) ;
// <- SAFE ----------------------------------
2009-09-18 10:15:03 +00:00
sal_Bool bIsSynchron = sal_False ;
for ( sal_Int32 nArgs = 0 ; nArgs < lArguments . getLength ( ) ; nArgs + + )
{
if ( lArguments [ nArgs ] . Name . equalsAscii ( " SynchronMode " ) )
{
lArguments [ nArgs ] . Value > > = bIsSynchron ;
break ;
}
}
if ( bIsSynchron )
impl_asyncCallback ( 0 ) ;
else
m_aAsyncCallback . Post ( 0 ) ;
2004-06-10 12:20:58 +00:00
}
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
2003-03-25 17:22:13 +00:00
/**
2004-06-10 12:20:58 +00:00
@ short asynchronous callback
@ descr We start all actions inside this object asnychronoue .
( see comments there ) .
Now we do the following :
- close all views to the same document , if needed and possible
- make the current frame empty
! This step is neccessary to handle errors during closing the
document inside the frame . May the document shows a dialog and
the user ignore it . Then the state of the office can be changed
during we try to close frame and document .
- check the environment ( menas count open frames - exlcuding our
current one )
- decide then , if we must close this frame only , establish the backing mode
or shutdown the whole application .
2003-03-25 17:22:13 +00:00
*/
2006-06-19 10:15:19 +00:00
IMPL_LINK ( CloseDispatcher , impl_asyncCallback , void * , EMPTYARG )
2003-03-25 17:22:13 +00:00
{
2005-07-12 13:14:34 +00:00
try
{
2004-06-10 12:20:58 +00:00
// Allow calling of XController->suspend() everytimes.
// Dispatch is an UI functionality. We implement such dispatch object here.
// And further XController->suspend() was designed to bring an UI ...
2007-08-17 14:49:06 +00:00
sal_Bool bAllowSuspend = sal_True ;
sal_Bool bControllerSuspended = sal_False ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// SAFE -> ----------------------------------
ReadGuard aReadLock ( m_aLock ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// Closing of all views, related to the same document, is allowed
// only if the dispatched URL was ".uno:CloseDoc"!
sal_Bool bCloseAllViewsToo = ( m_eOperation = = E_CLOSE_DOC ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// BTW: Make some copies, which are needed later ...
EOperation eOperation = m_eOperation ;
css : : uno : : Reference < css : : lang : : XMultiServiceFactory > xSMGR = m_xSMGR ;
2005-07-12 13:14:34 +00:00
css : : uno : : Reference < css : : frame : : XFrame > xCloseFrame ( m_xCloseFrame . get ( ) , css : : uno : : UNO_QUERY ) ;
2004-06-10 12:20:58 +00:00
css : : uno : : Reference < css : : frame : : XDispatchResultListener > xListener = m_xResultListener ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
aReadLock . unlock ( ) ;
// <- SAFE ----------------------------------
2005-07-12 13:14:34 +00:00
// frame already dead ?!
// Nothing to do !
if ( ! xCloseFrame . is ( ) )
return 0 ;
2004-06-10 12:20:58 +00:00
sal_Bool bCloseFrame = sal_False ;
sal_Bool bEstablishBackingMode = sal_False ;
sal_Bool bTerminateApp = sal_False ;
// Analyze the environment a first time.
// If we found some special cases, we can
// make some decisions erliar!
css : : uno : : Reference < css : : frame : : XFramesSupplier > xDesktop ( xSMGR - > createInstance ( SERVICENAME_DESKTOP ) , css : : uno : : UNO_QUERY_THROW ) ;
FrameListAnalyzer aCheck1 ( xDesktop , xCloseFrame , FrameListAnalyzer : : E_HELP | FrameListAnalyzer : : E_BACKINGCOMPONENT ) ;
2005-11-11 11:04:54 +00:00
// a) If the curent frame (where the close dispatch was requested for) does not have
// any parent frame ... it will close this frame only. Such frame isnt part of the
// global desktop tree ... and such frames are used as "implementation details" only.
// E.g. the live previews of our wizards doing such things. And then the owner of the frame
// is responsible for closing the application or accepting closing of the application
// by others.
if ( ! xCloseFrame - > getCreator ( ) . is ( ) )
bCloseFrame = sal_True ;
else
// b) The help window cant disagree with any request.
2004-06-10 12:20:58 +00:00
// Because it doesnt implement a controller - it uses a window only.
// Further t cant be the last open frame - if we do all other things
// right inside this CloseDispatcher implementation.
// => close it!
if ( aCheck1 . m_bReferenceIsHelp )
bCloseFrame = sal_True ;
else
2003-03-25 17:22:13 +00:00
2005-11-11 11:04:54 +00:00
// c) If we are already in "backing mode", we have to terminate
2004-06-10 12:20:58 +00:00
// the application, if this special frame is closed.
// It doesnt matter, how many other frames (can be the help or hidden frames only)
// are open then.
// => terminate the application!
if ( aCheck1 . m_bReferenceIsBacking )
bTerminateApp = sal_True ;
2003-03-25 17:22:13 +00:00
else
2004-06-10 12:20:58 +00:00
2005-11-11 11:04:54 +00:00
// d) Otherwhise we have to: close all views to the same document, close the
2004-06-10 12:20:58 +00:00
// document inside our own frame and decide then again, what has to be done!
2003-03-25 17:22:13 +00:00
{
2007-08-17 14:49:06 +00:00
if ( implts_prepareFrameForClosing ( m_xCloseFrame , bAllowSuspend , bCloseAllViewsToo , bControllerSuspended ) )
2004-06-10 12:20:58 +00:00
{
// OK; this frame is empty now.
// Check the environment again to decide, what is the next step.
FrameListAnalyzer aCheck2 ( xDesktop , xCloseFrame , FrameListAnalyzer : : E_ALL ) ;
// c1) there is as minimum 1 frame open, which is visible and contains a document
// different from our one. And its not the help!
// => close our frame only - nothing else.
if ( aCheck2 . m_lOtherVisibleFrames . getLength ( ) > 0 )
bCloseFrame = sal_True ;
else
2003-03-25 17:22:13 +00:00
2004-12-03 13:04:26 +00:00
// c2) if we close the current view ... but not all other views
// to the same document, we must close the current frame only!
// Because implts_closeView() suspended this view only - does not
// close the frame.
if (
( ! bCloseAllViewsToo ) & &
( aCheck2 . m_lModelFrames . getLength ( ) > 0 )
)
bCloseFrame = sal_True ;
2007-04-16 15:37:38 +00:00
else
2004-12-03 13:04:26 +00:00
// c3) there is no other (visible) frame open ...
2004-06-10 12:20:58 +00:00
// The help module will be ignored everytimes!
// But we have to decide if we must terminate the
// application or establish the backing mode now.
// And that depends from the dispatched URL ...
{
if ( eOperation = = E_CLOSE_FRAME )
bTerminateApp = sal_True ;
2008-03-05 16:22:02 +00:00
else if ( SvtModuleOptions ( ) . IsModuleInstalled ( SvtModuleOptions : : E_SSTARTMODULE ) )
2004-06-10 12:20:58 +00:00
bEstablishBackingMode = sal_True ;
2008-03-05 16:22:02 +00:00
else
bTerminateApp = sal_True ;
2004-06-10 12:20:58 +00:00
}
}
}
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// Do it now ...
sal_Bool bSuccess = sal_False ;
if ( bCloseFrame )
bSuccess = implts_closeFrame ( ) ;
else
if ( bEstablishBackingMode )
2008-03-05 16:22:02 +00:00
# if defined QUARTZ
{
// on mac close down, quickstarter keeps the process alive
// however if someone has shut down the quickstarter
// behave as any other platform
bool bQuickstarterRunning = false ;
// get quickstart service
try
{
css : : uno : : Reference < css : : beans : : XFastPropertySet > xSet ( xSMGR - > createInstance ( IMPLEMENTATIONNAME_QUICKLAUNCHER ) , css : : uno : : UNO_QUERY_THROW ) ;
if ( xSet . is ( ) )
{
css : : uno : : Any aVal ( xSet - > getFastPropertyValue ( 0 ) ) ;
sal_Bool bState = sal_False ;
if ( aVal > > = bState )
bQuickstarterRunning = bState ;
}
}
catch ( css : : uno : : Exception & )
{
}
bSuccess = bQuickstarterRunning ? implts_terminateApplication ( ) : implts_establishBackingMode ( ) ;
}
# else
2004-06-10 12:20:58 +00:00
bSuccess = implts_establishBackingMode ( ) ;
2008-03-05 16:22:02 +00:00
# endif
2004-06-10 12:20:58 +00:00
else
if ( bTerminateApp )
bSuccess = implts_terminateApplication ( ) ;
2003-03-25 17:22:13 +00:00
2007-08-17 14:49:06 +00:00
if (
( ! bSuccess ) & &
( bControllerSuspended )
)
{
css : : uno : : Reference < css : : frame : : XController > xController = xCloseFrame - > getController ( ) ;
if ( xController . is ( ) )
xController - > suspend ( sal_False ) ;
}
2004-06-10 12:20:58 +00:00
// inform listener
sal_Int16 nState = css : : frame : : DispatchResultState : : FAILURE ;
if ( bSuccess )
nState = css : : frame : : DispatchResultState : : SUCCESS ;
implts_notifyResultListener ( xListener , nState , css : : uno : : Any ( ) ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// SAFE -> ----------------------------------
2003-03-25 17:22:13 +00:00
WriteGuard aWriteLock ( m_aLock ) ;
// This method was called asynchronous from our main thread by using a pointer.
2004-06-10 12:20:58 +00:00
// We reached this method only, by using a reference to ourself :-)
// Further this member is used to detect still running and not yet finished
// ansynchronous operations. So its time now to release this reference.
// But hold it temp alive. Otherwhise we die before we can finish this method realy :-))
css : : uno : : Reference < css : : uno : : XInterface > xTempHold = m_xSelfHold ;
m_xSelfHold . clear ( ) ;
m_xResultListener . clear ( ) ;
2003-03-25 17:22:13 +00:00
aWriteLock . unlock ( ) ;
2004-06-10 12:20:58 +00:00
// <- SAFE ----------------------------------
2003-03-25 17:22:13 +00:00
2005-07-12 13:14:34 +00:00
}
catch ( const css : : lang : : DisposedException & )
{
LOG_ERROR ( " CloseDispatcher::impl_asyncCallback " , " Congratulation! You found the reason for bug #120310#. Please contact the right developer and show him a scenario, which trigger this bug. THX. " )
}
2003-03-25 17:22:13 +00:00
return 0 ;
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
2007-08-17 14:49:06 +00:00
sal_Bool CloseDispatcher : : implts_prepareFrameForClosing ( const css : : uno : : Reference < css : : frame : : XFrame > & xFrame ,
sal_Bool bAllowSuspend ,
sal_Bool bCloseAllOtherViewsToo ,
sal_Bool & bControllerSuspended )
2003-03-25 17:22:13 +00:00
{
2005-07-12 13:14:34 +00:00
// Frame already dead ... so this view is closed ... is closed ... is ... .-)
if ( ! xFrame . is ( ) )
return sal_True ;
2004-06-10 12:20:58 +00:00
// Close all views to the same document ... if forced to do so.
// But dont touch our own frame here!
2004-12-03 13:04:26 +00:00
// We must do so ... because the may be following controller->suspend()
// will show the "save/discard/cancel" dialog for the last view only!
2004-06-10 12:20:58 +00:00
if ( bCloseAllOtherViewsToo )
{
2007-08-17 14:49:06 +00:00
// SAFE -> ----------------------------------
ReadGuard aReadLock ( m_aLock ) ;
css : : uno : : Reference < css : : lang : : XMultiServiceFactory > xSMGR = m_xSMGR ;
aReadLock . unlock ( ) ;
// <- SAFE ----------------------------------
2004-06-10 12:20:58 +00:00
css : : uno : : Reference < css : : frame : : XFramesSupplier > xDesktop ( xSMGR - > createInstance ( SERVICENAME_DESKTOP ) , css : : uno : : UNO_QUERY_THROW ) ;
FrameListAnalyzer aCheck ( xDesktop , xFrame , FrameListAnalyzer : : E_ALL ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
sal_Int32 c = aCheck . m_lModelFrames . getLength ( ) ;
sal_Int32 i = 0 ;
for ( i = 0 ; i < c ; + + i )
{
if ( ! fpf : : closeIt ( aCheck . m_lModelFrames [ i ] , sal_False ) )
return sal_False ;
2003-03-25 17:22:13 +00:00
}
}
2004-12-03 13:04:26 +00:00
// If allowed - inform user about modified documents or
// still running jobs (e.g. printing).
if ( bAllowSuspend )
{
css : : uno : : Reference < css : : frame : : XController > xController = xFrame - > getController ( ) ;
2007-08-17 14:49:06 +00:00
if ( xController . is ( ) ) // some views dont uses a controller .-( (e.g. the help window)
2004-12-03 13:04:26 +00:00
{
2007-08-17 14:49:06 +00:00
bControllerSuspended = xController - > suspend ( sal_True ) ;
if ( ! bControllerSuspended )
return sal_False ;
2004-12-03 13:04:26 +00:00
}
}
// dont remove the component realy by e.g. calling setComponent(null, null).
// It's enough to suspend the controller.
// If we close the frame later this controller doesnt show the same dialog again.
return sal_True ;
2003-03-25 17:22:13 +00:00
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
sal_Bool CloseDispatcher : : implts_closeFrame ( )
2003-03-25 17:22:13 +00:00
{
2004-06-10 12:20:58 +00:00
// SAFE -> ----------------------------------
2003-03-25 17:22:13 +00:00
ReadGuard aReadLock ( m_aLock ) ;
2005-07-12 13:14:34 +00:00
css : : uno : : Reference < css : : frame : : XFrame > xFrame ( m_xCloseFrame . get ( ) , css : : uno : : UNO_QUERY ) ;
2003-03-25 17:22:13 +00:00
aReadLock . unlock ( ) ;
2004-06-10 12:20:58 +00:00
// <- SAFE ----------------------------------
2003-03-25 17:22:13 +00:00
2005-07-12 13:14:34 +00:00
// frame already dead ? => so it's closed ... it's closed ...
if ( ! xFrame . is ( ) )
return sal_True ;
2004-06-10 12:20:58 +00:00
// dont deliver owner ship; our "UI user" will try it again if it failed.
// OK - he will get an empty frame then. But normaly an empty frame
// should be closeable always :-)
if ( ! fpf : : closeIt ( xFrame , sal_False ) )
return sal_False ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// SAFE -> ----------------------------------
WriteGuard aWriteLock ( m_aLock ) ;
2005-07-12 13:14:34 +00:00
m_xCloseFrame = css : : uno : : WeakReference < css : : frame : : XFrame > ( ) ;
2004-06-10 12:20:58 +00:00
aWriteLock . unlock ( ) ;
// <- SAFE ----------------------------------
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
return sal_True ;
}
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
sal_Bool CloseDispatcher : : implts_establishBackingMode ( )
2003-03-25 17:22:13 +00:00
{
2004-06-10 12:20:58 +00:00
// SAFE -> ----------------------------------
ReadGuard aReadLock ( m_aLock ) ;
css : : uno : : Reference < css : : lang : : XMultiServiceFactory > xSMGR = m_xSMGR ;
2005-07-12 13:14:34 +00:00
css : : uno : : Reference < css : : frame : : XFrame > xFrame ( m_xCloseFrame . get ( ) , css : : uno : : UNO_QUERY ) ;
2004-06-10 12:20:58 +00:00
aReadLock . unlock ( ) ;
// <- SAFE ----------------------------------
2003-03-25 17:22:13 +00:00
2005-07-12 13:14:34 +00:00
if ( ! xFrame . is ( ) )
return sal_False ;
2009-09-18 10:15:03 +00:00
css : : uno : : Reference < css : : document : : XActionLockable > xLock ( xFrame , css : : uno : : UNO_QUERY ) ;
if ( xLock . is ( ) & & xLock - > isActionLocked ( ) )
return sal_False ;
2004-06-10 12:20:58 +00:00
css : : uno : : Reference < css : : awt : : XWindow > xContainerWindow = xFrame - > getContainerWindow ( ) ;
css : : uno : : Sequence < css : : uno : : Any > lArgs ( 1 ) ;
lArgs [ 0 ] < < = xContainerWindow ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
css : : uno : : Reference < css : : frame : : XController > xBackingComp (
xSMGR - > createInstanceWithArguments ( SERVICENAME_STARTMODULE , lArgs ) ,
css : : uno : : UNO_QUERY_THROW ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
// Attention: You MUST(!) call setComponent() before you call attachFrame().
css : : uno : : Reference < css : : awt : : XWindow > xBackingWin ( xBackingComp , css : : uno : : UNO_QUERY ) ;
xFrame - > setComponent ( xBackingWin , xBackingComp ) ;
xBackingComp - > attachFrame ( xFrame ) ;
xContainerWindow - > setVisible ( sal_True ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
return sal_True ;
2003-03-25 17:22:13 +00:00
}
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
sal_Bool CloseDispatcher : : implts_terminateApplication ( )
{
// SAFE -> ----------------------------------
ReadGuard aReadLock ( m_aLock ) ;
css : : uno : : Reference < css : : lang : : XMultiServiceFactory > xSMGR = m_xSMGR ;
aReadLock . unlock ( ) ;
// <- SAFE ----------------------------------
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
css : : uno : : Reference < css : : frame : : XDesktop > xDesktop (
xSMGR - > createInstance ( SERVICENAME_DESKTOP ) , css : : uno : : UNO_QUERY_THROW ) ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
return xDesktop - > terminate ( ) ;
}
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
//-----------------------------------------------
void CloseDispatcher : : implts_notifyResultListener ( const css : : uno : : Reference < css : : frame : : XDispatchResultListener > & xListener ,
sal_Int16 nState ,
const css : : uno : : Any & aResult )
2003-03-25 17:22:13 +00:00
{
2004-06-10 12:20:58 +00:00
if ( ! xListener . is ( ) )
return ;
2003-03-25 17:22:13 +00:00
2004-06-10 12:20:58 +00:00
css : : frame : : DispatchResultEvent aEvent (
css : : uno : : Reference < css : : uno : : XInterface > ( static_cast < : : cppu : : OWeakObject * > ( this ) , css : : uno : : UNO_QUERY ) ,
nState ,
aResult ) ;
xListener - > dispatchFinished ( aEvent ) ;
2003-03-25 17:22:13 +00:00
}
2007-04-16 15:37:38 +00:00
//-----------------------------------------------
css : : uno : : Reference < css : : frame : : XFrame > CloseDispatcher : : static_impl_searchRightTargetFrame ( const css : : uno : : Reference < css : : frame : : XFrame > & xFrame ,
const : : rtl : : OUString & sTarget )
{
if ( sTarget . equalsIgnoreAsciiCaseAscii ( " _self " ) )
return xFrame ;
OSL_ENSURE ( ( sTarget . getLength ( ) < 1 ) , " CloseDispatch used for unexpected target. Magic things will happen now .-) " ) ;
css : : uno : : Reference < css : : frame : : XFrame > xTarget = xFrame ;
while ( sal_True )
{
// a) top frames wil be closed
if ( xTarget - > isTop ( ) )
return xTarget ;
2007-08-17 14:49:06 +00:00
// b) even child frame containing top level windows (e.g. query designer of database) will be closed
css : : uno : : Reference < css : : awt : : XWindow > xWindow = xTarget - > getContainerWindow ( ) ;
css : : uno : : Reference < css : : awt : : XTopWindow > xTopWindowCheck ( xWindow , css : : uno : : UNO_QUERY ) ;
if ( xTopWindowCheck . is ( ) )
{
// b1) Note: Toolkit interface XTopWindow sometimes is used by real VCL-child-windows also .-)
// Be sure that these window is realy a "top system window".
// Attention ! Checking Window->GetParent() isnt the right approach here.
// Because sometimes VCL create "implicit border windows" as parents even we created
// a simple XWindow using the toolkit only .-(
: : vos : : OGuard aSolarLock ( & Application : : GetSolarMutex ( ) ) ;
Window * pWindow = VCLUnoHelper : : GetWindow ( xWindow ) ;
if (
( pWindow ) & &
( pWindow - > IsSystemWindow ( ) )
)
return xTarget ;
}
2007-04-16 15:37:38 +00:00
// c) try to find better results on parent frame
// If no parent frame exists (because this frame is used outside the desktop tree)
// the given frame must be used directly.
css : : uno : : Reference < css : : frame : : XFrame > xParent ( xTarget - > getCreator ( ) , css : : uno : : UNO_QUERY ) ;
if ( ! xParent . is ( ) )
return xTarget ;
// c1) check parent frame inside next loop ...
xTarget = xParent ;
}
}
2003-03-25 17:22:13 +00:00
} // namespace framework
2010-10-12 15:53:47 +02:00
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */