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