1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "root.hxx" 29 30 #include <cassert> 31 32 #include <com/sun/star/awt/WindowAttribute.hpp> 33 #include <com/sun/star/awt/XMessageBox.hpp> 34 #include <com/sun/star/awt/MessageBoxButtons.hpp> 35 #include <com/sun/star/frame/XDesktop.hpp> 36 #include <com/sun/star/awt/XMessageBoxFactory.hpp> 37 #include <com/sun/star/xml/sax/SAXParseException.hpp> 38 #include <com/sun/star/xml/sax/XParser.hpp> 39 40 #include "helper.hxx" 41 #include "import.hxx" 42 #include "timer.hxx" 43 #include "translate.hxx" 44 45 namespace layoutimpl 46 { 47 48 using namespace css; 49 using ::rtl::OUString; 50 51 LayoutRoot::LayoutRoot( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 52 : mbDisposed( sal_False ) 53 , mxFactory( xFactory ) 54 , mpListeners( NULL ) 55 , mpToplevel( NULL ) 56 { 57 if ( !xFactory.is() ) 58 throw uno::RuntimeException(); 59 mxLayoutUnit = uno::Reference< awt::XLayoutUnit >( new LayoutUnit() ); 60 } 61 62 LayoutRoot::~LayoutRoot() 63 { 64 // TODO: we want to delete the top level LayoutWidget... 65 ::osl::MutexGuard aGuard( maMutex ); 66 if ( !mbDisposed ) 67 { 68 try 69 { 70 m_refCount++; // inhibit multiple destruction 71 dispose(); 72 } 73 catch( uno::Exception& ) 74 { 75 } 76 } 77 } 78 79 void ShowMessageBox( uno::Reference< lang::XMultiServiceFactory > const& xFactory, uno::Reference< awt::XToolkit > xToolkit, OUString const& aTitle, OUString const& aMessage ) 80 { 81 uno::Reference< uno::XInterface > iDesktop = xFactory->createInstance 82 ( OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ); 83 uno::Reference< frame::XDesktop > xDesktop ( iDesktop, uno::UNO_QUERY ); 84 uno::Reference< frame::XFrame > xFrame ( xDesktop->getCurrentFrame() ); 85 uno::Reference< awt::XWindow > xContainerWindow( xFrame->getContainerWindow() ); 86 uno::Reference< awt::XWindowPeer > xWindowPeer( xContainerWindow, uno::UNO_QUERY_THROW ); 87 uno::Reference< awt::XMessageBoxFactory > xMessageBoxFactory( xToolkit, uno::UNO_QUERY ); 88 89 awt::Rectangle aRectangle; 90 uno::Reference< awt::XMessageBox > xMessageBox 91 = xMessageBoxFactory->createMessageBox 92 ( xWindowPeer, aRectangle, OUString::createFromAscii( "errorbox" ), 93 awt::MessageBoxButtons::BUTTONS_OK, aTitle, aMessage ); 94 95 if ( xMessageBox.is() ) 96 xMessageBox->execute(); 97 //FIXME: exceptions not caught and printed at top level?? 98 //else 99 //printf( "%s\n", OUSTRING_CSTR( aMessage ) ); 100 } 101 102 void LayoutRoot::error( OUString const& message ) 103 { 104 OSL_TRACE( "%s\n", OUSTRING_CSTR( message ) ); 105 ShowMessageBox( mxFactory, mxToolkit, 106 OUString::createFromAscii( "Fatal error" ), 107 message ); 108 throw uno::RuntimeException( message, uno::Reference< uno::XInterface >() ); 109 } 110 111 // XInitialization 112 void SAL_CALL LayoutRoot::initialize( const uno::Sequence< uno::Any >& aArguments ) 113 throw ( uno::Exception, 114 uno::RuntimeException ) 115 { 116 ::osl::MutexGuard aGuard( maMutex ); 117 118 if ( mbDisposed ) 119 throw lang::DisposedException(); 120 121 if ( mxContainer.is() ) // only 1 init ... 122 throw uno::Exception(); 123 124 if ( !aArguments.getLength() ) 125 throw lang::IllegalArgumentException(); 126 127 OSL_ENSURE( aArguments.getLength() == 1, "Wrong arg count\n" ); 128 129 OUString aXMLName; 130 if ( !( aArguments[0] >>= aXMLName ) ) 131 throw lang::IllegalArgumentException(); 132 133 uno::Reference< xml::sax::XParser > xParser 134 ( mxFactory->createInstance( 135 OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) ), 136 uno::UNO_QUERY ); 137 OSL_ASSERT( xParser.is() ); 138 if (! xParser.is()) 139 { 140 throw uno::RuntimeException( 141 OUString::createFromAscii( "cannot create sax-parser component" ), 142 uno::Reference< uno::XInterface >() ); 143 } 144 145 // FIXME: quite possibly we want to pass this in ... 146 uno::Reference< awt::XToolkit > xToolkit; 147 148 mxToolkit = uno::Reference< awt::XToolkit >( 149 mxFactory->createInstance( 150 OUString::createFromAscii( "com.sun.star.awt.Toolkit" ) ), 151 uno::UNO_QUERY ); 152 153 if ( !mxToolkit.is() ) 154 throw uno::RuntimeException( 155 OUString::createFromAscii( "failed to create toolkit!" ), 156 uno::Reference< uno::XInterface >() ); 157 158 OUString aXMLFile = readRightTranslation( aXMLName ); 159 uno::Reference< io::XInputStream > xStream = getFileAsStream( aXMLFile ); 160 if (! xStream.is() ) 161 error( OUString::createFromAscii( "Installation problem: cannot find XML file:" ) + aXMLName ); 162 163 // error handler, entity resolver omitted 164 165 ImportContext *pCtx = new ImportContext( *this ); 166 167 uno::Reference< xml::input::XRoot > xRoot( pCtx ); 168 uno::Sequence < uno::Any > aArgs( 1 ); 169 aArgs[0] <<= xRoot; 170 uno::Reference< xml::sax::XDocumentHandler > xDocHandler 171 (mxFactory->createInstanceWithArguments 172 ( OUString::createFromAscii( "com.sun.star.xml.input.SaxDocumentHandler" ), 173 aArgs ), uno::UNO_QUERY ); 174 175 if (! xDocHandler.is() ) 176 error( OUString::createFromAscii( "cannot find SAx handler for document type of:") + aXMLName ); 177 178 xParser->setDocumentHandler( xDocHandler ); 179 180 xml::sax::InputSource source; 181 source.aInputStream = xStream; 182 source.sSystemId = OUString::createFromAscii( "virtual file" ); 183 184 try 185 { 186 xParser->parseStream( source ); 187 } 188 catch ( xml::sax::SAXParseException& e ) 189 { 190 OUString c = OUString::createFromAscii( ":" ); 191 error( aXMLName 192 + c + OUString::valueOf( e.LineNumber ) 193 + c + OUString::valueOf( e.ColumnNumber ) 194 + c + OUString::createFromAscii( "Sax parse error" ) ); 195 } 196 } 197 198 // XLayoutContainer 199 uno::Reference< awt::XLayoutContainer > LayoutRoot::getLayoutContainer() throw (uno::RuntimeException) 200 { 201 return uno::Reference< awt::XLayoutContainer >(); 202 } 203 204 // local helper ... 205 void LayoutRoot::addItem( const OUString &rName, 206 const uno::Reference< awt::XLayoutConstrains > &xRef ) 207 { 208 maItems[ rName ] = xRef; 209 } 210 211 // XNameAccess 212 uno::Any SAL_CALL LayoutRoot::getByName( const OUString &rName ) 213 throw ( container::NoSuchElementException, 214 lang::WrappedTargetException, 215 uno::RuntimeException ) 216 { 217 ::osl::MutexGuard aGuard( maMutex ); 218 if ( mbDisposed ) 219 throw lang::DisposedException(); 220 221 uno::Reference< awt::XLayoutConstrains > xItem; 222 ItemHash::iterator i = maItems.find( rName ); 223 if ( i != maItems.end() ) 224 xItem = i->second; 225 return uno::makeAny( xItem ); 226 } 227 228 sal_Bool SAL_CALL LayoutRoot::hasByName( const OUString &rName ) 229 throw (uno::RuntimeException) 230 { 231 ::osl::MutexGuard aGuard( maMutex ); 232 if ( mbDisposed ) throw lang::DisposedException(); 233 234 ItemHash::iterator i = maItems.find( rName ); 235 return i != maItems.end(); 236 } 237 238 uno::Sequence< OUString > SAL_CALL LayoutRoot::getElementNames() 239 throw ( uno::RuntimeException ) 240 { 241 ::osl::MutexGuard aGuard( maMutex ); 242 if ( mbDisposed ) throw lang::DisposedException(); 243 244 uno::Sequence< OUString > aNames( maItems.size() ); 245 sal_Int32 nPos = 0; 246 247 for ( ItemHash::const_iterator it = maItems.begin(); 248 it != maItems.end(); it++ ) 249 aNames[ nPos++ ] = it->first; 250 251 return aNames; 252 } 253 254 uno::Type SAL_CALL LayoutRoot::getElementType() 255 throw ( uno::RuntimeException ) 256 { 257 return getCppuType( ( const uno::Reference< awt::XLayoutConstrains >* )NULL ); 258 } 259 260 sal_Bool SAL_CALL LayoutRoot::hasElements() 261 throw ( uno::RuntimeException ) 262 { 263 ::osl::MutexGuard aGuard( maMutex ); 264 265 if ( mbDisposed ) throw lang::DisposedException(); 266 267 return maItems.size() > 0; 268 } 269 270 // XComponent 271 void SAL_CALL LayoutRoot::dispose() 272 throw ( uno::RuntimeException ) 273 { 274 ::osl::MutexGuard aGuard( maMutex ); 275 276 if ( mbDisposed ) throw lang::DisposedException(); 277 278 if ( mpListeners ) 279 { 280 281 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); 282 mpListeners->disposeAndClear( aSource ); 283 delete mpListeners; 284 mpListeners = NULL; 285 } 286 287 maItems.clear(); 288 mbDisposed = sal_True; 289 } 290 291 void SAL_CALL LayoutRoot::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) 292 throw ( uno::RuntimeException ) 293 { 294 ::osl::MutexGuard aGuard( maMutex ); 295 296 if ( mbDisposed ) throw lang::DisposedException(); 297 298 if ( !mpListeners ) 299 mpListeners = new ::cppu::OInterfaceContainerHelper( maMutex ); 300 mpListeners->addInterface( xListener ); 301 } 302 303 void SAL_CALL LayoutRoot::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) 304 throw ( uno::RuntimeException ) 305 { 306 ::osl::MutexGuard aGuard( maMutex ); 307 308 if ( mbDisposed ) throw lang::DisposedException(); 309 310 if ( mpListeners ) 311 mpListeners->removeInterface( xListener ); 312 } 313 314 // builder 315 316 LayoutWidget *LayoutRoot::create( OUString id, const OUString unoName, long attrbs,uno::Reference< awt::XLayoutContainer > xParent ) 317 { 318 LayoutWidget *pWidget = new LayoutWidget( mxToolkit, xParent, unoName, attrbs ); 319 if ( !mpToplevel ) 320 { 321 mpToplevel = pWidget; 322 mxWindow = uno::Reference< awt::XWindow >( pWidget->getPeer(), uno::UNO_QUERY ); 323 mxContainer = pWidget->mxContainer; 324 } 325 if ( pWidget->mxContainer.is() ) 326 pWidget->mxContainer->setLayoutUnit( mxLayoutUnit ); 327 if ( id.getLength() ) 328 maItems[ id ] = pWidget->getPeer(); 329 return pWidget; 330 } 331 332 #if 0 333 uno::Reference< awt::XLayoutConstrains > LayoutRoot::getToplevel() 334 { 335 if ( mpToplevel ) 336 return mpToplevel->getPeer(); 337 return uno::Reference< awt::XLayoutConstrains > (); 338 } 339 340 uno::Reference< awt::XLayoutConstrains > LayoutRoot::getById( OUString id ) 341 { 342 uno::Reference< awt::XLayoutConstrains > rRef = 0; 343 ItemHash::iterator it = maItems.find( id ); 344 if ( it != maItems.end() ) 345 rRef = it->second; 346 return rRef; 347 } 348 #endif 349 350 LayoutWidget::LayoutWidget( uno::Reference< awt::XToolkit > xToolkit, 351 uno::Reference< awt::XLayoutContainer > xParent, 352 OUString unoName, long attrbs ) 353 { 354 while ( xParent.is() && !uno::Reference< awt::XWindow >( xParent, uno::UNO_QUERY ).is() ) 355 { 356 uno::Reference< awt::XLayoutContainer > xContainer( xParent, uno::UNO_QUERY ); 357 assert( xContainer.is() ); 358 xParent = uno::Reference< awt::XLayoutContainer >( xContainer->getParent(), uno::UNO_QUERY ); 359 } 360 361 mxWidget = WidgetFactory::createWidget( xToolkit, xParent, unoName, attrbs ); 362 assert( mxWidget.is() ); 363 mxContainer = uno::Reference< awt::XLayoutContainer >( mxWidget, uno::UNO_QUERY ); 364 } 365 366 LayoutWidget::~LayoutWidget() 367 { 368 /* should we dispose of the references...? */ 369 // at least of its children... Or should root? 370 } 371 372 bool LayoutWidget::addChild( LayoutWidget *pChild ) 373 { 374 if ( !mxContainer.is() ) 375 return false; 376 377 try 378 { 379 mxContainer->addChild( pChild->mxWidget ); 380 } 381 catch( awt::MaxChildrenException ex ) 382 { 383 return false; 384 } 385 return true; 386 } 387 388 void LayoutWidget::setProperties( PropList const& rProps ) 389 { 390 ::layoutimpl::setProperties( mxWidget, rProps ); 391 } 392 393 void LayoutWidget::setProperty( OUString const& attr, OUString const& value ) 394 { 395 ::layoutimpl::setProperty( mxWidget, attr, value ); 396 } 397 398 void LayoutWidget::setChildProperties( LayoutWidget *pChild, 399 PropList const& rProps ) 400 { 401 uno::Reference< beans::XPropertySet > xChildPeer; 402 xChildPeer = mxContainer->getChildProperties( pChild->mxWidget ); 403 404 if ( xChildPeer.is() ) 405 ::layoutimpl::setProperties( xChildPeer, rProps ); 406 } 407 408 } // namespace layoutimpl 409 410