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