xref: /aoo42x/main/toolkit/source/layout/core/root.cxx (revision cdf0e10c)
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