/************************************************************************* * * $RCSfile: framecontainer.cxx,v $ * * $Revision: 1.17 $ * * last change: $Author: as $ $Date: 2002-07-02 07:25:01 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library 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 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ //_________________________________________________________________________________________________________________ // my own includes //_________________________________________________________________________________________________________________ #ifndef __FRAMEWORK_FRAMECONTAINER_HXX_ #include #endif #ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_ #include #endif #ifndef __FRAMEWORK_THREADHELP_READGUARD_HXX_ #include #endif #ifndef __FRAMEWORK_COMMANDS_HXX_ #include #endif //_________________________________________________________________________________________________________________ // interface includes //_________________________________________________________________________________________________________________ #ifndef _COM_SUN_STAR_FRAME_FRAMESEARCH_FLAG_HPP_ #include #endif //_________________________________________________________________________________________________________________ // includes of other projects //_________________________________________________________________________________________________________________ #ifndef _SV_SVAPP_HXX #include #endif //_________________________________________________________________________________________________________________ // namespace //_________________________________________________________________________________________________________________ namespace framework{ //_________________________________________________________________________________________________________________ // non exported const //_________________________________________________________________________________________________________________ //_________________________________________________________________________________________________________________ // non exported definitions //_________________________________________________________________________________________________________________ //_________________________________________________________________________________________________________________ // declarations //_________________________________________________________________________________________________________________ /**-*************************************************************************************************************** @short initialize an empty container @descr The container will be empty then - special features (e.g. the async quit timer) are disabled. @threadsafe not neccessary - its not a singleton @modified 01.07.2002 14:42,as96863 *****************************************************************************************************************/ FrameContainer::FrameContainer() // initialize base classes first. // Order is neccessary for right initilization of his and OUR member ... m_aLock : ThreadHelpBase ( &Application::GetSolarMutex() ) { } /**-*************************************************************************************************************** @short deinitialize may a filled container @descr Special features (if the currently are running) will be dsiabled and we free all used other ressources. @threadsafe not neccessary - its not a singleton @modified 01.07.2002 14:43,as96863 *****************************************************************************************************************/ FrameContainer::~FrameContainer() { // Disable possible active quit timer! // He can be active for owner=desktop only. disableQuitTimer(); // Don't forget to free memory! clear(); } /**-*************************************************************************************************************** @short append a new frame to the container @descr We accept the incoming frame only, if it is a valid reference and dosnt exist already. @param xFrame frame, which should be added to this container Must be a valid reference. @threadsafe yes @modified 01.07.2002 14:44,as96863 *****************************************************************************************************************/ void FrameContainer::append( const css::uno::Reference< css::frame::XFrame >& xFrame ) { if (xFrame.is() && ! exist(xFrame)) { /* SAFE { */ WriteGuard aWriteLock( m_aLock ); m_aContainer.push_back( xFrame ); aWriteLock.unlock(); /* } SAFE */ } } /**-*************************************************************************************************************** @short remove a frame from the container @descr In case we remove the last frame and our internal special feature (the async quit timer) was enabled by the desktop instance, we start it. @param xFrame frame, which should be deleted from this container Must be a valid reference. @threadsafe yes @modified 01.07.2002 14:52,as96863 *****************************************************************************************************************/ void FrameContainer::remove( const css::uno::Reference< css::frame::XFrame >& xFrame ) { /* SAFE { */ // write lock neccessary for follwing erase()! WriteGuard aWriteLock( m_aLock ); TFrameIterator aSearchedItem = ::std::find( m_aContainer.begin(), m_aContainer.end(), xFrame ); if (aSearchedItem!=m_aContainer.end()) { m_aContainer.erase( aSearchedItem ); // If removed frame was the current active frame - reset state variable. if (m_xActiveFrame==xFrame) m_xActiveFrame = css::uno::Reference< css::frame::XFrame >(); // We don't need the write lock any longer ... // downgrade to read access. aWriteLock.downgrade(); // If last frame was removed and special quit timer is enabled by the desktop // we must terminate the desktop by using this timer! if (m_aContainer.size()<1 && m_rQuitTimer.isValid()) m_rQuitTimer->start(); } aWriteLock.unlock(); /* } SAFE */ } /**-*************************************************************************************************************** @short check if the given frame currently exist inside the container @descr - @param xFrame reference to the queried frame @return if frame is oart of this container otherwhise @threadsafe yes @modified 01.07.2002 14:55,as96863 *****************************************************************************************************************/ sal_Bool FrameContainer::exist( const css::uno::Reference< css::frame::XFrame >& xFrame ) const { /* SAFE { */ ReadGuard aReadLock( m_aLock ); return( ::std::find( m_aContainer.begin(), m_aContainer.end(), xFrame ) != m_aContainer.end() ); /* } SAFE */ } /**-*************************************************************************************************************** @short delete all existing items of the container @descr - @threadsafe yes @modified 01.07.2002 15:00,as96863 *****************************************************************************************************************/ void FrameContainer::clear() { /* SAFE { */ WriteGuard aWriteLock( m_aLock ); // Clear the container ... m_aContainer.clear(); // ... and don't forget to reset the active frame. // Its an reference to a valid container-item. // But no container item => no active frame! m_xActiveFrame = css::uno::Reference< css::frame::XFrame >(); // If special quit timer is used - we must terminate the desktop. // He is the owner of this container and can't work without any visible tasks/frames! if (m_rQuitTimer.isValid()) m_rQuitTimer->start(); aWriteLock.unlock(); /* } SAFE */ } /**-*************************************************************************************************************** @short returns count of all current existing frames @descr - @deprecated This value can't be guaranteed for multithreading environments. So it will be marked as deprecated and should be replaced by "getAllElements()". @return the count of existing container items @threadsafe yes @modified 01.07.2002 15:00,as96863 *****************************************************************************************************************/ sal_uInt32 FrameContainer::getCount() const { /* SAFE { */ ReadGuard aReadLock( m_aLock ); return( (sal_uInt32)m_aContainer.size() ); /* } SAFE */ } /**-*************************************************************************************************************** @short returns one item of this container @descr - @deprecated This value can't be guaranteed for multithreading environments. So it will be marked as deprecated and should be replaced by "getAllElements()". @param nIndex a valud between 0 and (getCount()-1) to adress one container item @return a reference to a frame inside the container, which match with given index @threadsafe yes @modified 01.07.2002 15:03,as96863 *****************************************************************************************************************/ css::uno::Reference< css::frame::XFrame > FrameContainer::operator[]( sal_uInt32 nIndex ) const { css::uno::Reference< css::frame::XFrame > xFrame; try { // Get element form container WITH automatic test of ranges! // If index not valid, a out_of_range exception is thrown. /* SAFE { */ ReadGuard aReadLock( m_aLock ); xFrame = m_aContainer.at( nIndex ); aReadLock.unlock(); /* } SAFE */ } catch( std::out_of_range& ) { // The index is not valid for current container-content - we must handle this case! // We can return the default value ... LOG_EXCEPTION( "FrameContainer::operator[]", "Exception catched ...", DECLARE_ASCII("::std::out_of_range") ) } return xFrame; } /**-*************************************************************************************************************** @short returns a snapshot of all currently existing frames inside this container @descr Should be used to replace the deprecated functions getCount()/operator[]! @return a list of all frame refrences inside this container @threadsafe yes @modified 01.07.2002 15:09,as96863 *****************************************************************************************************************/ css::uno::Sequence< css::uno::Reference< css::frame::XFrame > > FrameContainer::getAllElements() const { /* SAFE { */ ReadGuard aReadLock( m_aLock ); sal_Int32 nPosition = 0; css::uno::Sequence< css::uno::Reference< css::frame::XFrame > > lElements ( (sal_uInt32)m_aContainer.size() ); for (TConstFrameIterator pItem=m_aContainer.begin(); pItem!=m_aContainer.end(); ++pItem) lElements[nPosition++] = *pItem; aReadLock.unlock(); /* } SAFE */ return lElements; } /**-*************************************************************************************************************** @short return state information, if container is empty or not @descr - @return if container is filled or if he is empty. @threadsafe yes @modified 01.07.2002 15:09,as96863 *****************************************************************************************************************/ sal_Bool FrameContainer::hasElements() const { /* SAFE { */ ReadGuard aReadLock( m_aLock ); return( m_aContainer.size()>0 ); /* } SAFE */ } /**-*************************************************************************************************************** @short set the given frame as the new active one inside this container @descr We accept this frame only, if it's already a part of this container. @param xFrame reference to the new active frame Must be a valid reference and already part of this container. @threadsafe yes @modified 01.07.2002 15:11,as96863 *****************************************************************************************************************/ void FrameContainer::setActive( const css::uno::Reference< css::frame::XFrame >& xFrame ) { if (xFrame.is() && exist(xFrame)) { /* SAFE { */ WriteGuard aWriteLock( m_aLock ); m_xActiveFrame = xFrame; aWriteLock.unlock(); /* } SAFE */ } } /**-*************************************************************************************************************** @short return sthe current active frame of this container @descr Value can be null in case the frame was removed from the container and nobody from outside decide which of all others should be the new one ... @return a reference to the current active frame Value can be NULL! @threadsafe yes @modified 01.07.2002 15:11,as96863 *****************************************************************************************************************/ css::uno::Reference< css::frame::XFrame > FrameContainer::getActive() const { /* SAFE { */ ReadGuard aReadLock( m_aLock ); return m_xActiveFrame; /* } SAFE */ } /**-*************************************************************************************************************** @short enables the async quit timer, which terminates the office if last task will be closed @descr If the last visible task will gone, nobody shows any UI then. But without any UI the user has no chance to quit the application realy. So we must shutdown by ourself. We do that by an async quit timer, which will be initialized and check after hi times out, if any new task was opened. In case it wasn't ... it calls Desktop::terminate(). But note: It's not neccessary to start this timer if using the office doesn't require it. e.g. the command line parameters "-invisible", -headless" starts the office in a server mode. In this case the outside user controls the lifetime of it and must terminate it manually. @param xDesktop only the child frame container of the desktop instance can use this special quit timer Because only top level frames are used for cehcking. @threadsafe yes @modified 01.07.2002 14:30,as96863 *****************************************************************************************************************/ void FrameContainer::enableQuitTimer( const css::uno::Reference< css::frame::XDesktop >& xDesktop ) { /* SAFE { */ WriteGuard aWriteLock( m_aLock ); // If no current timer exist - create a new one. if( m_rQuitTimer.isEmpty() == sal_True ) { // How can we distinguish between the different office modes? // a) Office is plugged if command argument "-plugin" could be detected. => timeout = 2 min // b) Office runs in special "server" mode if "-headless", "-invisible" or "-server" could be detected. => timout disabled! // c) Otherwise office runs in normal mode. => timeout = 5 sec // Parse command line for right parameter. if( c_existCommand( COMMAND_PLUGIN ) == sal_True ) { m_rQuitTimer.bind( new AsyncQuit( xDesktop, E_PLUGIN ) ); } else if( ! c_existCommand( COMMAND_HEADLESS ) && ! c_existCommand( COMMAND_INVISIBLE ) && ! c_existCommand( COMMAND_SERVER ) ) { m_rQuitTimer.bind( new AsyncQuit( xDesktop, E_FATOFFICE ) ); } } /* } SAFE */ } /**-*************************************************************************************************************** @short disable the async quit timer again @descr Delete current quit timer. If user wish to create it again he must do it with "enableQuitTimer()". @threadsafe yes @modified 01.07.2002 14:37,as96863 *****************************************************************************************************************/ void FrameContainer::disableQuitTimer() { /* SAFE { */ WriteGuard aWriteLock( m_aLock ); if (m_rQuitTimer.isValid()) m_rQuitTimer.unbind(); /* } SAFE */ } /**-*************************************************************************************************************** @short implements a simple search based on current container items @descr It can be used for findFrame() and implements a deep down search. @param sName target name, which is searched @return reference to the found frame or NULL if not. @threadsafe yes @modified 01.07.2002 15:22,as96863 *****************************************************************************************************************/ css::uno::Reference< css::frame::XFrame > FrameContainer::searchOnAllChildrens( const ::rtl::OUString& sName ) const { /* SAFE { */ ReadGuard aReadLock( m_aLock ); // Step over all child frames. But if direct child isn't the right one search on his children first - before // you go to next direct child of this container! css::uno::Reference< css::frame::XFrame > xSearchedFrame; for( TConstFrameIterator pIterator=m_aContainer.begin(); pIterator!=m_aContainer.end(); ++pIterator ) { if ((*pIterator)->getName()==sName) { xSearchedFrame = *pIterator; break; } else { xSearchedFrame = (*pIterator)->findFrame( sName, css::frame::FrameSearchFlag::CHILDREN ); if (xSearchedFrame.is()) break; } } aReadLock.unlock(); /* } SAFE */ return xSearchedFrame; } /**-*************************************************************************************************************** @short implements a simple search based on current container items @descr It can be used for findFrame() and search on members of this container only! @param sName target name, which is searched @return reference to the found frame or NULL if not. @threadsafe yes @modified 01.07.2002 15:22,as96863 *****************************************************************************************************************/ css::uno::Reference< css::frame::XFrame > FrameContainer::searchOnDirectChildrens( const ::rtl::OUString& sName ) const { /* SAFE { */ ReadGuard aReadLock( m_aLock ); css::uno::Reference< css::frame::XFrame > xSearchedFrame; for( TConstFrameIterator pIterator=m_aContainer.begin(); pIterator!=m_aContainer.end(); ++pIterator ) { if ((*pIterator)->getName()==sName) { xSearchedFrame = *pIterator; break; } } aReadLock.unlock(); /* } SAFE */ return xSearchedFrame; } /**-*************************************************************************************************************** @short special debug mode! @descr Sometimes frames will be inserted in this container which hold no component inside! Or they will be empty after inserting. ALLOWED FOR DEBUG ONLY! We show assertion then. @threadsafe yes @modified 01.07.2002 15:39,as96863 *****************************************************************************************************************/ #ifdef ENABLE_ASSERTIONS void FrameContainer::impldbg_checkForZombie() const { /* SAFE { */ ReadGuard aReadLock(m_aLock); for (TConstFrameIterator pItem=m_aContainer.begin(); pItem!=m_aContainer.end(); ++pItem) { if ((*pItem)->getComponentWindow().is()) { LOG_WARNING("FrameContainer::impldbg_checkForZombie()", "Zombie found! Please check your frame tree ...") break; } } aReadLock.unlock(); /* } SAFE */ } #endif // #ifdef ENABLE_ASSERTIONS } // namespace framework