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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_toolkit.hxx"
30 
31 #ifndef _TOOLKIT_ROADMAP_CONTROL_HXX
32 #include <toolkit/controls/roadmapcontrol.hxx>
33 #endif
34 #include <toolkit/helper/unopropertyarrayhelper.hxx>
35 #include <toolkit/helper/property.hxx>
36 #include <com/sun/star/awt/XVclWindowPeer.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <osl/diagnose.h>
39 
40 //........................................................................
41 namespace toolkit
42 {
43 //........................................................................
44 
45 	using namespace ::com::sun::star::uno;
46 	using namespace ::com::sun::star::awt;
47 	using namespace ::com::sun::star::lang;
48 	using namespace ::com::sun::star::beans;
49     using namespace ::com::sun::star::container;
50 
51 //	----------------------------------------------------
52 //  helper
53 //	----------------------------------------------------
54 
55 static void lcl_throwIllegalArgumentException( )
56 {	// throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
57 	throw IllegalArgumentException();
58 }
59 
60 static void lcl_throwIndexOutOfBoundsException( )
61 {	// throwing is expensive (in terms of code size), thus we hope the compiler does not inline this ....
62 	throw IndexOutOfBoundsException();
63 }
64 
65 	// ===================================================================
66 	// = UnoControlRoadmapModel
67 	// ===================================================================
68 	// -------------------------------------------------------------------
69 	UnoControlRoadmapModel::UnoControlRoadmapModel( const Reference< XMultiServiceFactory >& i_factory )
70         :UnoControlRoadmapModel_Base( i_factory )
71         ,maContainerListeners( *this )
72 	{
73 		ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
74 		ImplRegisterProperty( BASEPROPERTY_BORDER );
75 		ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
76 		ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
77 		ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
78 		ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
79 		ImplRegisterProperty( BASEPROPERTY_HELPURL );
80 		ImplRegisterProperty( BASEPROPERTY_IMAGEURL );
81 		ImplRegisterProperty( BASEPROPERTY_GRAPHIC );
82         ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
83 		ImplRegisterProperty( BASEPROPERTY_COMPLETE );
84 		ImplRegisterProperty( BASEPROPERTY_ACTIVATED );
85 		ImplRegisterProperty( BASEPROPERTY_CURRENTITEMID );
86         ImplRegisterProperty( BASEPROPERTY_TABSTOP );
87         ImplRegisterProperty( BASEPROPERTY_TEXT );
88 	}
89 
90 	// -------------------------------------------------------------------
91 	::rtl::OUString UnoControlRoadmapModel::getServiceName() throw(RuntimeException)
92 	{
93 		return ::rtl::OUString::createFromAscii( szServiceName_UnoControlRoadmapModel );
94 	}
95 
96 
97 	// -------------------------------------------------------------------
98 	Any UnoControlRoadmapModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
99 	{
100 		Any aReturn;
101 		switch (nPropId)
102 		{
103                 case BASEPROPERTY_COMPLETE:
104                     aReturn <<= (sal_Bool) sal_True;
105                     break;
106                 case BASEPROPERTY_ACTIVATED:
107                     aReturn <<= (sal_Bool) sal_True;
108                     break;
109                 case BASEPROPERTY_CURRENTITEMID:
110                     aReturn <<= (sal_Int16) -1;
111                     break;
112                 case BASEPROPERTY_TEXT:
113                    break;
114                 case BASEPROPERTY_BORDER:
115                     aReturn <<= (sal_Int16) 2;              // No Border
116                     break;
117 			    case BASEPROPERTY_DEFAULTCONTROL:
118                     aReturn <<= ::rtl::OUString( ::rtl::OUString::createFromAscii( szServiceName_UnoControlRoadmap ) );
119                     break;
120 			default : aReturn = UnoControlRoadmapModel_Base::ImplGetDefaultValue( nPropId ); break;
121 		}
122 
123 		return aReturn;
124 	}
125 
126 
127     Reference< XInterface > SAL_CALL UnoControlRoadmapModel::createInstance(  ) throw (Exception, ::com::sun::star::uno::RuntimeException)
128     {
129 		ORoadmapEntry* pRoadmapItem = new ORoadmapEntry();
130 	    Reference< XInterface > xNewRoadmapItem = (::cppu::OWeakObject*)pRoadmapItem;
131 	    return xNewRoadmapItem;
132     }
133 
134 
135     Reference< XInterface > SAL_CALL UnoControlRoadmapModel::createInstanceWithArguments( const Sequence< Any >& /*aArguments*/ ) throw (Exception, RuntimeException)
136     {
137         // Todo: implementation of the arguments handling
138 		ORoadmapEntry* pRoadmapItem = new ORoadmapEntry();
139 	    Reference< XInterface > xNewRoadmapItem = (::cppu::OWeakObject*)pRoadmapItem;
140 	    return xNewRoadmapItem;
141     }
142 
143 
144  IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoControlRoadmapModel, UnoControlRoadmapModel_Base, UnoControlRoadmapModel_IBase )
145 
146 
147 	// -------------------------------------------------------------------
148     ::com::sun::star::uno::Any	SAL_CALL UnoControlRoadmapModel::queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
149     {
150         Any aRet = UnoControlRoadmapModel_Base::queryAggregation( rType );
151         if ( !aRet.hasValue() )
152             aRet = UnoControlRoadmapModel_IBase::queryInterface( rType );
153  	    return aRet;
154     }
155 
156 
157 	// -------------------------------------------------------------------
158 	::cppu::IPropertyArrayHelper& UnoControlRoadmapModel::getInfoHelper()
159 	{
160 		static UnoPropertyArrayHelper* pHelper = NULL;
161 		if ( !pHelper )
162 		{
163 			Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
164 			pHelper = new UnoPropertyArrayHelper( aIDs );
165 		}
166 		return *pHelper;
167 	}
168 
169 
170 	// beans::XMultiPropertySet
171 	// -------------------------------------------------------------------
172 	Reference< XPropertySetInfo > UnoControlRoadmapModel::getPropertySetInfo(  ) throw(RuntimeException)
173 	{
174 		static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
175 		return xInfo;
176 	}
177 
178 
179     sal_Int32 SAL_CALL UnoControlRoadmapModel::getCount() throw(RuntimeException)
180     {
181         return maRoadmapItems.size();
182     }
183 
184     Any SAL_CALL UnoControlRoadmapModel::getByIndex( sal_Int32 Index ) throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
185     {
186         if (( Index >= (sal_Int32)maRoadmapItems.size()) || (Index < 0))
187             lcl_throwIndexOutOfBoundsException( );
188         Any aAny;
189         aAny = makeAny( maRoadmapItems.at( Index ));
190         return aAny;
191     }
192 
193 
194 
195     void UnoControlRoadmapModel::MakeRMItemValidation( sal_Int32 Index, Reference< XInterface > xRoadmapItem )
196     {
197         if ((Index > (sal_Int32)maRoadmapItems.size()) || ( Index < 0 ) )
198             lcl_throwIndexOutOfBoundsException( );
199         if ( !xRoadmapItem.is() )
200 		    lcl_throwIllegalArgumentException();
201         Reference< XServiceInfo > xServiceInfo( xRoadmapItem, UNO_QUERY );
202         sal_Bool bIsRoadmapItem = xServiceInfo->supportsService( ::rtl::OUString::createFromAscii( "com.sun.star.awt.RoadmapItem" ) );
203         if ( !bIsRoadmapItem )
204     	    lcl_throwIllegalArgumentException();
205     }
206 
207 
208     void UnoControlRoadmapModel::SetRMItemDefaultProperties( const sal_Int32 , Reference< XInterface > xRoadmapItem)
209     {
210 		Any	aAny;
211         Reference< XPropertySet > xPropertySet( xRoadmapItem, UNO_QUERY );
212         Reference< XPropertySet > xProps( xRoadmapItem, UNO_QUERY );
213 	    if ( xProps.is() )
214         {
215             sal_Int32 LocID = 0;
216             Any aValue = xPropertySet->getPropertyValue( ::rtl::OUString::createFromAscii( "ID" ) );
217             aValue >>= LocID;
218             if (LocID < 0)              // index may not be smaller than zero
219             {
220                 aAny <<= GetUniqueID();
221                 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "ID" ), aAny );
222             }
223         }
224     }
225 
226 
227 // The performance of this method could certainly be improved.
228 // As long as only vectors with up to 10 elements are
229 // involved it should be sufficient
230        sal_Int32 UnoControlRoadmapModel::GetUniqueID()
231       {
232           Any aAny;
233           sal_Bool bIncrement = sal_True;
234           sal_Int32 CurID = 0;
235           sal_Int32 n_CurItemID = 0;
236           Reference< XInterface > CurRoadmapItem;
237           while ( bIncrement )
238           {
239  	      bIncrement = sal_False;
240               for ( RoadmapItemHolderList::iterator i = maRoadmapItems.begin(); i < maRoadmapItems.end(); i++ )
241               {
242                 CurRoadmapItem = *i;
243                 Reference< XPropertySet > xPropertySet( CurRoadmapItem, UNO_QUERY );
244                 aAny = xPropertySet->getPropertyValue( ::rtl::OUString::createFromAscii( "ID" ) );
245                 aAny >>= n_CurItemID;
246                 if (n_CurItemID == CurID)
247                 {
248                     bIncrement = sal_True;
249                     CurID++;
250                     break;
251                 }
252             }
253         }
254         return CurID;
255     }
256 
257 
258     ContainerEvent UnoControlRoadmapModel::GetContainerEvent(sal_Int32 Index, Reference< XInterface > xRoadmapItem)
259     {
260 	    ContainerEvent aEvent;
261 	    aEvent.Source = *this;
262 	    aEvent.Element <<= xRoadmapItem;
263         aEvent.Accessor = makeAny(Index);
264         return aEvent;
265     }
266 
267 
268     sal_Int16 UnoControlRoadmapModel::GetCurrentItemID( Reference< XPropertySet > xPropertySet )
269     {
270         Any aAny = xPropertySet->getPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ) );
271         sal_Int16 n_CurrentItemID = 0;
272         aAny >>= n_CurrentItemID;
273         return n_CurrentItemID;
274     }
275 
276 
277     void SAL_CALL UnoControlRoadmapModel::insertByIndex( const sal_Int32 Index, const Any& _Element)
278                                     throw (IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
279     {
280         if ( ( Index >= ( (sal_Int32)maRoadmapItems.size() + 1 ) ) || (Index < 0))
281             lcl_throwIndexOutOfBoundsException( );
282         Reference< XInterface > xRoadmapItem;
283         _Element >>= xRoadmapItem;
284         MakeRMItemValidation( Index, xRoadmapItem);
285         SetRMItemDefaultProperties( Index, xRoadmapItem );
286         maRoadmapItems.insert( maRoadmapItems.begin() + Index, xRoadmapItem);
287 	    ContainerEvent aEvent = GetContainerEvent(Index, xRoadmapItem);
288 	    maContainerListeners.elementInserted( aEvent );
289         Reference< XPropertySet > xPropertySet( (XAggregation*) (::cppu::OWeakAggObject*)this, UNO_QUERY );
290         sal_Int16 n_CurrentItemID = GetCurrentItemID( xPropertySet );
291         if ( Index <= n_CurrentItemID )
292         {
293             Any aAny;
294             aAny <<= ( sal_Int16 ) ( n_CurrentItemID + 1 );
295             xPropertySet->setPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ), aAny );
296         }
297     }
298 
299 
300 
301     void SAL_CALL UnoControlRoadmapModel::removeByIndex( sal_Int32 Index)
302                                                 throw	 (IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
303     {
304         if (( Index > (sal_Int32)maRoadmapItems.size()) || (Index < 0))
305             lcl_throwIndexOutOfBoundsException( );
306         Reference< XInterface > xRoadmapItem;
307         maRoadmapItems.erase( maRoadmapItems.begin() + Index );
308 	    ContainerEvent aEvent = GetContainerEvent(Index, xRoadmapItem);
309 	    maContainerListeners.elementRemoved( aEvent );
310         Reference< XPropertySet > xPropertySet( (XAggregation*) (::cppu::OWeakAggObject*)this, UNO_QUERY );
311         sal_Int16 n_CurrentItemID = GetCurrentItemID( xPropertySet );
312         Any aAny;
313         if ( Index <= n_CurrentItemID )
314         {
315             if ( n_CurrentItemID >= (sal_Int32)maRoadmapItems.size() )
316             {
317                 n_CurrentItemID = sal::static_int_cast< sal_Int16 >(
318                     maRoadmapItems.size()-1);
319                 if ( n_CurrentItemID < 0 )
320                     return;
321                 aAny <<= n_CurrentItemID;
322             }
323             else if (Index == n_CurrentItemID)
324                 aAny <<= ( sal_Int16 ) -1;
325             else if( Index < n_CurrentItemID)
326                 aAny <<= ( sal_Int16 ) ( n_CurrentItemID - 1 );
327             xPropertySet->setPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ), aAny );
328         }
329     }
330 
331 
332 	void SAL_CALL UnoControlRoadmapModel::replaceByIndex( const sal_Int32 Index, const Any& _Element)
333                                 throw (IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
334     {
335         Reference< XInterface > xRoadmapItem;
336         _Element >>= xRoadmapItem;
337         MakeRMItemValidation( Index, xRoadmapItem);
338         SetRMItemDefaultProperties( Index, xRoadmapItem );
339         maRoadmapItems.erase( maRoadmapItems.begin() + Index );
340         maRoadmapItems.insert( maRoadmapItems.begin() + Index, xRoadmapItem);        //push_back( xRoadmapItem );
341 	    ContainerEvent aEvent = GetContainerEvent(Index, xRoadmapItem);
342 	    maContainerListeners.elementReplaced( aEvent );
343     }
344 
345 
346 	Type SAL_CALL UnoControlRoadmapModel::getElementType() throw(RuntimeException)
347     {
348 	    Type aType = getCppuType( ( Reference< XPropertySet>* ) NULL );
349 	    return aType;
350     }
351 
352 
353     sal_Bool SAL_CALL UnoControlRoadmapModel::hasElements() throw(RuntimeException)
354     {
355         return !maRoadmapItems.empty();
356     }
357 
358 
359     void SAL_CALL UnoControlRoadmapModel::addContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
360     {
361 	    maContainerListeners.addInterface( xListener );
362     }
363 
364     void SAL_CALL UnoControlRoadmapModel::removeContainerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener >& xListener ) throw (::com::sun::star::uno::RuntimeException)
365     {
366 	    maContainerListeners.removeInterface( xListener );
367     }
368 
369     // ===================================================================
370 	// = UnoRoadmapControl
371 	// ===================================================================
372 	// -------------------------------------------------------------------
373     UnoRoadmapControl::UnoRoadmapControl( const Reference< XMultiServiceFactory >& i_factory )
374         :UnoControlRoadmap_Base( i_factory )
375         ,maItemListeners( *this )
376 	{
377 	}
378 
379 IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoRoadmapControl, UnoControlRoadmap_Base, UnoControlRoadmap_IBase )
380 IMPLEMENT_FORWARD_XINTERFACE2( UnoRoadmapControl, UnoControlRoadmap_Base, UnoControlRoadmap_IBase )
381 
382 
383 sal_Bool SAL_CALL UnoRoadmapControl::setModel(const Reference< XControlModel >& _rModel) throw ( RuntimeException )
384     {
385 
386 
387    	    Reference< XContainer > xC( getModel(), UNO_QUERY );
388 	    if ( xC.is() )
389 		    xC->removeContainerListener( this );
390 
391         sal_Bool bReturn = UnoControlBase::setModel( _rModel );
392 
393 	    xC = xC.query( getModel());
394 	    if ( xC.is() )
395 		    xC->addContainerListener( this );
396 
397         return bReturn;
398     }
399 
400 
401 	// -------------------------------------------------------------------
402 	::rtl::OUString UnoRoadmapControl::GetComponentServiceName()
403 	{
404 		return ::rtl::OUString::createFromAscii( "Roadmap" );
405 	}
406 
407 
408 
409     void UnoRoadmapControl::dispose() throw(RuntimeException)
410     {
411 	    EventObject aEvt;
412 	    aEvt.Source = (::cppu::OWeakObject*)this;
413 	    maItemListeners.disposeAndClear( aEvt );
414 	    UnoControl::dispose();
415     }
416 
417 
418 
419 void UnoRoadmapControl::elementInserted( const ContainerEvent& rEvent )throw(RuntimeException)
420 {
421     Reference< XInterface > xRoadmapItem;
422     rEvent.Element >>= xRoadmapItem;
423     Reference< XPropertySet > xRoadmapPropertySet( xRoadmapItem, UNO_QUERY );
424 	if ( xRoadmapPropertySet.is() )
425         xRoadmapPropertySet->addPropertyChangeListener( rtl::OUString(), this );
426 
427     Reference< XContainerListener >  xPeer(getPeer(), UNO_QUERY);
428     if ( xPeer.is() )
429     {
430         xPeer->elementInserted( rEvent );
431 		Reference < XPropertySet > xPropertySet( xPeer, UNO_QUERY );
432         if ( xPropertySet.is() )
433 		    xPropertySet->addPropertyChangeListener( rtl::OUString(), this );
434     }
435 }
436 
437 
438 void UnoRoadmapControl::elementRemoved( const ContainerEvent& rEvent )throw(RuntimeException)
439 {
440     Reference< XContainerListener >  xPeer(getPeer(), UNO_QUERY);
441     if ( xPeer.is() )
442         xPeer->elementRemoved( rEvent );
443     Reference< XInterface > xRoadmapItem;
444     rEvent.Element >>= xRoadmapItem;
445     Reference< XPropertySet > xPropertySet( xRoadmapItem, UNO_QUERY );
446 	if ( xPropertySet.is() )
447         xPropertySet->removePropertyChangeListener( rtl::OUString(), this );
448 }
449 
450 
451 void UnoRoadmapControl::elementReplaced( const ContainerEvent& rEvent )throw(RuntimeException)
452 {
453     Reference< XContainerListener >  xPeer(getPeer(), UNO_QUERY);
454     if ( xPeer.is() )
455         xPeer->elementReplaced( rEvent );
456 }
457 
458 
459 void SAL_CALL UnoRoadmapControl::itemStateChanged( const ItemEvent& rEvent ) throw (RuntimeException)
460 {
461     sal_Int16 CurItemIndex = sal::static_int_cast< sal_Int16 >(rEvent.ItemId);
462     Any aAny;
463     aAny <<= CurItemIndex;
464     Reference< XControlModel > xModel( getModel( ), UNO_QUERY );
465     Reference< XPropertySet > xPropertySet( xModel, UNO_QUERY );
466     xPropertySet->setPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ), aAny );
467     if ( maItemListeners.getLength() )
468 		maItemListeners.itemStateChanged( rEvent );
469 }
470 
471 
472 void SAL_CALL UnoRoadmapControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
473 {
474     maItemListeners.addInterface( l );
475 	if( getPeer().is() && maItemListeners.getLength() == 1 )
476 	{
477 		Reference < XItemEventBroadcaster > xRoadmap( getPeer(), UNO_QUERY );
478 		xRoadmap->addItemListener( this );
479 	}
480 }
481 
482 
483 void SAL_CALL UnoRoadmapControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
484 {
485 	if( getPeer().is() && maItemListeners.getLength() == 1 )
486 	{
487 		Reference < XItemEventBroadcaster >  xRoadmap( getPeer(), UNO_QUERY );
488 		xRoadmap->removeItemListener( this );
489 	}
490 
491     maItemListeners.removeInterface( l );
492 }
493 
494 
495 void SAL_CALL UnoRoadmapControl::propertyChange( const PropertyChangeEvent& evt ) throw (RuntimeException)
496 {
497     Reference< XPropertyChangeListener >  xPeer(getPeer(), UNO_QUERY);
498     if ( xPeer.is() )
499         xPeer->propertyChange( evt );
500 }
501 
502 }
503 
504