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
LayoutRoot(const uno::Reference<lang::XMultiServiceFactory> & xFactory)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
~LayoutRoot()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
ShowMessageBox(uno::Reference<lang::XMultiServiceFactory> const & xFactory,uno::Reference<awt::XToolkit> xToolkit,OUString const & aTitle,OUString const & aMessage)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
error(OUString const & message)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
initialize(const uno::Sequence<uno::Any> & aArguments)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
getLayoutContainer()192 uno::Reference< awt::XLayoutContainer > LayoutRoot::getLayoutContainer()
193 {
194 return uno::Reference< awt::XLayoutContainer >();
195 }
196
197 // local helper ...
addItem(const OUString & rName,const uno::Reference<awt::XLayoutConstrains> & xRef)198 void LayoutRoot::addItem( const OUString &rName,
199 const uno::Reference< awt::XLayoutConstrains > &xRef )
200 {
201 maItems[ rName ] = xRef;
202 }
203
204 // XNameAccess
getByName(const OUString & rName)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
hasByName(const OUString & rName)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
getElementNames()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
getElementType()242 uno::Type SAL_CALL LayoutRoot::getElementType()
243 {
244 return getCppuType( ( const uno::Reference< awt::XLayoutConstrains >* )NULL );
245 }
246
hasElements()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
dispose()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
addEventListener(const uno::Reference<lang::XEventListener> & xListener)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
removeEventListener(const uno::Reference<lang::XEventListener> & xListener)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
create(OUString id,const OUString unoName,long attrbs,uno::Reference<awt::XLayoutContainer> xParent)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
LayoutWidget(uno::Reference<awt::XToolkit> xToolkit,uno::Reference<awt::XLayoutContainer> xParent,OUString unoName,long attrbs)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
~LayoutWidget()349 LayoutWidget::~LayoutWidget()
350 {
351 /* should we dispose of the references...? */
352 // at least of its children... Or should root?
353 }
354
addChild(LayoutWidget * pChild)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
setProperties(PropList const & rProps)371 void LayoutWidget::setProperties( PropList const& rProps )
372 {
373 ::layoutimpl::setProperties( mxWidget, rProps );
374 }
375
setProperty(OUString const & attr,OUString const & value)376 void LayoutWidget::setProperty( OUString const& attr, OUString const& value )
377 {
378 ::layoutimpl::setProperty( mxWidget, attr, value );
379 }
380
setChildProperties(LayoutWidget * pChild,PropList const & rProps)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