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 uno::Reference< awt::XMessageBox > xMessageBox 86 = xMessageBoxFactory->createMessageBox 87 ( xWindowPeer, awt::MessageBoxType_ERRORBOX, 88 awt::MessageBoxButtons::BUTTONS_OK, aTitle, aMessage ); 89 90 if ( xMessageBox.is() ) 91 xMessageBox->execute(); 92 //FIXME: exceptions not caught and printed at top level?? 93 //else 94 //printf( "%s\n", OUSTRING_CSTR( aMessage ) ); 95 } 96 97 void LayoutRoot::error( OUString const& message ) 98 { 99 OSL_TRACE( "%s\n", OUSTRING_CSTR( message ) ); 100 ShowMessageBox( mxFactory, mxToolkit, 101 OUString::createFromAscii( "Fatal error" ), 102 message ); 103 throw uno::RuntimeException( message, uno::Reference< uno::XInterface >() ); 104 } 105 106 // XInitialization 107 void SAL_CALL LayoutRoot::initialize( const uno::Sequence< uno::Any >& aArguments ) 108 throw ( uno::Exception, 109 uno::RuntimeException ) 110 { 111 ::osl::MutexGuard aGuard( maMutex ); 112 113 if ( mbDisposed ) 114 throw lang::DisposedException(); 115 116 if ( mxContainer.is() ) // only 1 init ... 117 throw uno::Exception(); 118 119 if ( !aArguments.getLength() ) 120 throw lang::IllegalArgumentException(); 121 122 OSL_ENSURE( aArguments.getLength() == 1, "Wrong arg count\n" ); 123 124 OUString aXMLName; 125 if ( !( aArguments[0] >>= aXMLName ) ) 126 throw lang::IllegalArgumentException(); 127 128 uno::Reference< xml::sax::XParser > xParser 129 ( mxFactory->createInstance( 130 OUString::createFromAscii( "com.sun.star.xml.sax.Parser" ) ), 131 uno::UNO_QUERY ); 132 OSL_ASSERT( xParser.is() ); 133 if (! xParser.is()) 134 { 135 throw uno::RuntimeException( 136 OUString::createFromAscii( "cannot create sax-parser component" ), 137 uno::Reference< uno::XInterface >() ); 138 } 139 140 // FIXME: quite possibly we want to pass this in ... 141 uno::Reference< awt::XToolkit > xToolkit; 142 143 mxToolkit = uno::Reference< awt::XToolkit >( 144 mxFactory->createInstance( 145 OUString::createFromAscii( "com.sun.star.awt.Toolkit" ) ), 146 uno::UNO_QUERY ); 147 148 if ( !mxToolkit.is() ) 149 throw uno::RuntimeException( 150 OUString::createFromAscii( "failed to create toolkit!" ), 151 uno::Reference< uno::XInterface >() ); 152 153 OUString aXMLFile = readRightTranslation( aXMLName ); 154 uno::Reference< io::XInputStream > xStream = getFileAsStream( aXMLFile ); 155 if (! xStream.is() ) 156 error( OUString::createFromAscii( "Installation problem: cannot find XML file:" ) + aXMLName ); 157 158 // error handler, entity resolver omitted 159 160 ImportContext *pCtx = new ImportContext( *this ); 161 162 uno::Reference< xml::input::XRoot > xRoot( pCtx ); 163 uno::Sequence < uno::Any > aArgs( 1 ); 164 aArgs[0] <<= xRoot; 165 uno::Reference< xml::sax::XDocumentHandler > xDocHandler 166 (mxFactory->createInstanceWithArguments 167 ( OUString::createFromAscii( "com.sun.star.xml.input.SaxDocumentHandler" ), 168 aArgs ), uno::UNO_QUERY ); 169 170 if (! xDocHandler.is() ) 171 error( OUString::createFromAscii( "cannot find SAx handler for document type of:") + aXMLName ); 172 173 xParser->setDocumentHandler( xDocHandler ); 174 175 xml::sax::InputSource source; 176 source.aInputStream = xStream; 177 source.sSystemId = OUString::createFromAscii( "virtual file" ); 178 179 try 180 { 181 xParser->parseStream( source ); 182 } 183 catch ( xml::sax::SAXParseException& e ) 184 { 185 OUString c = OUString::createFromAscii( ":" ); 186 error( aXMLName 187 + c + OUString::valueOf( e.LineNumber ) 188 + c + OUString::valueOf( e.ColumnNumber ) 189 + c + OUString::createFromAscii( "Sax parse error" ) ); 190 } 191 } 192 193 // XLayoutContainer 194 uno::Reference< awt::XLayoutContainer > LayoutRoot::getLayoutContainer() throw (uno::RuntimeException) 195 { 196 return uno::Reference< awt::XLayoutContainer >(); 197 } 198 199 // local helper ... 200 void LayoutRoot::addItem( const OUString &rName, 201 const uno::Reference< awt::XLayoutConstrains > &xRef ) 202 { 203 maItems[ rName ] = xRef; 204 } 205 206 // XNameAccess 207 uno::Any SAL_CALL LayoutRoot::getByName( const OUString &rName ) 208 throw ( container::NoSuchElementException, 209 lang::WrappedTargetException, 210 uno::RuntimeException ) 211 { 212 ::osl::MutexGuard aGuard( maMutex ); 213 if ( mbDisposed ) 214 throw lang::DisposedException(); 215 216 uno::Reference< awt::XLayoutConstrains > xItem; 217 ItemHash::iterator i = maItems.find( rName ); 218 if ( i != maItems.end() ) 219 xItem = i->second; 220 return uno::makeAny( xItem ); 221 } 222 223 sal_Bool SAL_CALL LayoutRoot::hasByName( const OUString &rName ) 224 throw (uno::RuntimeException) 225 { 226 ::osl::MutexGuard aGuard( maMutex ); 227 if ( mbDisposed ) throw lang::DisposedException(); 228 229 ItemHash::iterator i = maItems.find( rName ); 230 return i != maItems.end(); 231 } 232 233 uno::Sequence< OUString > SAL_CALL LayoutRoot::getElementNames() 234 throw ( uno::RuntimeException ) 235 { 236 ::osl::MutexGuard aGuard( maMutex ); 237 if ( mbDisposed ) throw lang::DisposedException(); 238 239 uno::Sequence< OUString > aNames( maItems.size() ); 240 sal_Int32 nPos = 0; 241 242 for ( ItemHash::const_iterator it = maItems.begin(); 243 it != maItems.end(); it++ ) 244 aNames[ nPos++ ] = it->first; 245 246 return aNames; 247 } 248 249 uno::Type SAL_CALL LayoutRoot::getElementType() 250 throw ( uno::RuntimeException ) 251 { 252 return getCppuType( ( const uno::Reference< awt::XLayoutConstrains >* )NULL ); 253 } 254 255 sal_Bool SAL_CALL LayoutRoot::hasElements() 256 throw ( uno::RuntimeException ) 257 { 258 ::osl::MutexGuard aGuard( maMutex ); 259 260 if ( mbDisposed ) throw lang::DisposedException(); 261 262 return maItems.size() > 0; 263 } 264 265 // XComponent 266 void SAL_CALL LayoutRoot::dispose() 267 throw ( uno::RuntimeException ) 268 { 269 ::osl::MutexGuard aGuard( maMutex ); 270 271 if ( mbDisposed ) throw lang::DisposedException(); 272 273 if ( mpListeners ) 274 { 275 276 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); 277 mpListeners->disposeAndClear( aSource ); 278 delete mpListeners; 279 mpListeners = NULL; 280 } 281 282 maItems.clear(); 283 mbDisposed = sal_True; 284 } 285 286 void SAL_CALL LayoutRoot::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) 287 throw ( uno::RuntimeException ) 288 { 289 ::osl::MutexGuard aGuard( maMutex ); 290 291 if ( mbDisposed ) throw lang::DisposedException(); 292 293 if ( !mpListeners ) 294 mpListeners = new ::cppu::OInterfaceContainerHelper( maMutex ); 295 mpListeners->addInterface( xListener ); 296 } 297 298 void SAL_CALL LayoutRoot::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) 299 throw ( uno::RuntimeException ) 300 { 301 ::osl::MutexGuard aGuard( maMutex ); 302 303 if ( mbDisposed ) throw lang::DisposedException(); 304 305 if ( mpListeners ) 306 mpListeners->removeInterface( xListener ); 307 } 308 309 // builder 310 311 LayoutWidget *LayoutRoot::create( OUString id, const OUString unoName, long attrbs,uno::Reference< awt::XLayoutContainer > xParent ) 312 { 313 LayoutWidget *pWidget = new LayoutWidget( mxToolkit, xParent, unoName, attrbs ); 314 if ( !mpToplevel ) 315 { 316 mpToplevel = pWidget; 317 mxWindow = uno::Reference< awt::XWindow >( pWidget->getPeer(), uno::UNO_QUERY ); 318 mxContainer = pWidget->mxContainer; 319 } 320 if ( pWidget->mxContainer.is() ) 321 pWidget->mxContainer->setLayoutUnit( mxLayoutUnit ); 322 if ( id.getLength() ) 323 maItems[ id ] = pWidget->getPeer(); 324 return pWidget; 325 } 326 327 #if 0 328 uno::Reference< awt::XLayoutConstrains > LayoutRoot::getToplevel() 329 { 330 if ( mpToplevel ) 331 return mpToplevel->getPeer(); 332 return uno::Reference< awt::XLayoutConstrains > (); 333 } 334 335 uno::Reference< awt::XLayoutConstrains > LayoutRoot::getById( OUString id ) 336 { 337 uno::Reference< awt::XLayoutConstrains > rRef = 0; 338 ItemHash::iterator it = maItems.find( id ); 339 if ( it != maItems.end() ) 340 rRef = it->second; 341 return rRef; 342 } 343 #endif 344 345 LayoutWidget::LayoutWidget( uno::Reference< awt::XToolkit > xToolkit, 346 uno::Reference< awt::XLayoutContainer > xParent, 347 OUString unoName, long attrbs ) 348 { 349 while ( xParent.is() && !uno::Reference< awt::XWindow >( xParent, uno::UNO_QUERY ).is() ) 350 { 351 uno::Reference< awt::XLayoutContainer > xContainer( xParent, uno::UNO_QUERY ); 352 assert( xContainer.is() ); 353 xParent = uno::Reference< awt::XLayoutContainer >( xContainer->getParent(), uno::UNO_QUERY ); 354 } 355 356 mxWidget = WidgetFactory::createWidget( xToolkit, xParent, unoName, attrbs ); 357 assert( mxWidget.is() ); 358 mxContainer = uno::Reference< awt::XLayoutContainer >( mxWidget, uno::UNO_QUERY ); 359 } 360 361 LayoutWidget::~LayoutWidget() 362 { 363 /* should we dispose of the references...? */ 364 // at least of its children... Or should root? 365 } 366 367 bool LayoutWidget::addChild( LayoutWidget *pChild ) 368 { 369 if ( !mxContainer.is() ) 370 return false; 371 372 try 373 { 374 mxContainer->addChild( pChild->mxWidget ); 375 } 376 catch( awt::MaxChildrenException ex ) 377 { 378 return false; 379 } 380 return true; 381 } 382 383 void LayoutWidget::setProperties( PropList const& rProps ) 384 { 385 ::layoutimpl::setProperties( mxWidget, rProps ); 386 } 387 388 void LayoutWidget::setProperty( OUString const& attr, OUString const& value ) 389 { 390 ::layoutimpl::setProperty( mxWidget, attr, value ); 391 } 392 393 void LayoutWidget::setChildProperties( LayoutWidget *pChild, 394 PropList const& rProps ) 395 { 396 uno::Reference< beans::XPropertySet > xChildPeer; 397 xChildPeer = mxContainer->getChildProperties( pChild->mxWidget ); 398 399 if ( xChildPeer.is() ) 400 ::layoutimpl::setProperties( xChildPeer, rProps ); 401 } 402 403 } // namespace layoutimpl 404 405