1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/io/XMarkableStream.hpp>
21 #include <com/sun/star/uno/XComponentContext.hpp>
23 #include <toolkit/controls/stdtabcontrollermodel.hxx>
24 #include <toolkit/helper/macros.hxx>
25 #include <toolkit/helper/servicenames.hxx>
26 #include <toolkit/helper/property.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <cppuhelper/typeprovider.hxx>
29 #include <cppuhelper/queryinterface.hxx>
32 #include <tools/debug.hxx>
34 #define UNOCONTROL_STREAMVERSION short(2)
37 // class UnoControlModelEntryList
39 UnoControlModelEntryList::UnoControlModelEntryList()
43 UnoControlModelEntryList::~UnoControlModelEntryList()
48 void UnoControlModelEntryList::Reset()
50 for ( size_t n
= maList
.size(); n
; )
54 void UnoControlModelEntryList::DestroyEntry( size_t nEntry
)
56 UnoControlModelEntryListBase::iterator it
= maList
.begin();
57 ::std::advance( it
, nEntry
);
62 delete (*it
)->pxControl
;
68 size_t UnoControlModelEntryList::size() const {
72 UnoControlModelEntry
* UnoControlModelEntryList::operator[]( size_t i
) const {
73 return ( i
< maList
.size() ) ? maList
[ i
] : nullptr;
76 void UnoControlModelEntryList::push_back( UnoControlModelEntry
* item
) {
77 maList
.push_back( item
);
80 void UnoControlModelEntryList::insert( size_t i
, UnoControlModelEntry
* item
) {
81 if ( i
< maList
.size() ) {
82 UnoControlModelEntryListBase::iterator it
= maList
.begin();
83 ::std::advance( it
, i
);
84 maList
.insert( it
, item
);
86 maList
.push_back( item
);
91 // class StdTabControllerModel
93 StdTabControllerModel::StdTabControllerModel()
95 mbGroupControl
= true;
98 StdTabControllerModel::~StdTabControllerModel()
102 sal_uInt32
StdTabControllerModel::ImplGetControlCount( const UnoControlModelEntryList
& rList
) const
104 sal_uInt32 nCount
= 0;
105 size_t nEntries
= rList
.size();
106 for ( size_t n
= 0; n
< nEntries
; n
++ )
108 UnoControlModelEntry
* pEntry
= rList
[ n
];
109 if ( pEntry
->bGroup
)
110 nCount
+= ImplGetControlCount( *pEntry
->pGroup
);
117 void StdTabControllerModel::ImplGetControlModels( css::uno::Reference
< css::awt::XControlModel
> ** ppRefs
, const UnoControlModelEntryList
& rList
) const
119 size_t nEntries
= rList
.size();
120 for ( size_t n
= 0; n
< nEntries
; n
++ )
122 UnoControlModelEntry
* pEntry
= rList
[ n
];
123 if ( pEntry
->bGroup
)
124 ImplGetControlModels( ppRefs
, *pEntry
->pGroup
);
127 **ppRefs
= *pEntry
->pxControl
;
133 void StdTabControllerModel::ImplSetControlModels( UnoControlModelEntryList
& rList
, const css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> >& Controls
)
135 const css::uno::Reference
< css::awt::XControlModel
> * pRefs
= Controls
.getConstArray();
136 sal_uInt32 nControls
= Controls
.getLength();
137 for ( sal_uInt32 n
= 0; n
< nControls
; n
++ )
139 UnoControlModelEntry
* pNewEntry
= new UnoControlModelEntry
;
140 pNewEntry
->bGroup
= false;
141 pNewEntry
->pxControl
= new css::uno::Reference
< css::awt::XControlModel
> ;
142 *pNewEntry
->pxControl
= pRefs
[n
];
143 rList
.push_back( pNewEntry
);
147 sal_uInt32
StdTabControllerModel::ImplGetControlPos( const css::uno::Reference
< css::awt::XControlModel
>& rCtrl
, const UnoControlModelEntryList
& rList
)
149 for ( size_t n
= rList
.size(); n
; )
151 UnoControlModelEntry
* pEntry
= rList
[ --n
];
152 if ( !pEntry
->bGroup
&& ( *pEntry
->pxControl
== rCtrl
) )
155 return CONTROLPOS_NOTFOUND
;
158 void ImplWriteControls( const css::uno::Reference
< css::io::XObjectOutputStream
> & OutStream
, const css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> >& rCtrls
)
160 css::uno::Reference
< css::io::XMarkableStream
> xMark( OutStream
, css::uno::UNO_QUERY
);
161 DBG_ASSERT( xMark
.is(), "write: no XMarkableStream!" );
163 sal_uInt32 nStoredControls
= 0;
164 sal_Int32 nDataBeginMark
= xMark
->createMark();
166 OutStream
->writeLong( 0 ); // DataLen
167 OutStream
->writeLong( 0 ); // nStoredControls
169 sal_uInt32 nCtrls
= rCtrls
.getLength();
170 for ( sal_uInt32 n
= 0; n
< nCtrls
; n
++ )
172 const css::uno::Reference
< css::awt::XControlModel
> xI
= rCtrls
.getConstArray()[n
];
173 css::uno::Reference
< css::io::XPersistObject
> xPO( xI
, css::uno::UNO_QUERY
);
174 DBG_ASSERT( xPO
.is(), "write: Control doesn't support XPersistObject" );
177 OutStream
->writeObject( xPO
);
181 sal_Int32 nDataLen
= xMark
->offsetToMark( nDataBeginMark
);
182 xMark
->jumpToMark( nDataBeginMark
);
183 OutStream
->writeLong( nDataLen
);
184 OutStream
->writeLong( nStoredControls
);
185 xMark
->jumpToFurthest();
186 xMark
->deleteMark(nDataBeginMark
);
189 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > ImplReadControls( const css::uno::Reference
< css::io::XObjectInputStream
> & InStream
)
191 css::uno::Reference
< css::io::XMarkableStream
> xMark( InStream
, css::uno::UNO_QUERY
);
192 DBG_ASSERT( xMark
.is(), "write: no XMarkableStream!" );
194 sal_Int32 nDataBeginMark
= xMark
->createMark();
196 sal_Int32 nDataLen
= InStream
->readLong();
197 sal_uInt32 nCtrls
= InStream
->readLong();
199 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > aSeq( nCtrls
);
200 for ( sal_uInt32 n
= 0; n
< nCtrls
; n
++ )
202 css::uno::Reference
< css::io::XPersistObject
> xObj
= InStream
->readObject();
203 css::uno::Reference
< css::awt::XControlModel
> xI( xObj
, css::uno::UNO_QUERY
);
204 aSeq
.getArray()[n
] = xI
;
207 // Skip remainder if more data exists than this version recognizes
208 xMark
->jumpToMark( nDataBeginMark
);
209 InStream
->skipBytes( nDataLen
);
210 xMark
->deleteMark(nDataBeginMark
);
215 // css::uno::XInterface
216 css::uno::Any
StdTabControllerModel::queryAggregation( const css::uno::Type
& rType
)
218 css::uno::Any aRet
= ::cppu::queryInterface( rType
,
219 static_cast< css::awt::XTabControllerModel
* >(this),
220 static_cast< css::lang::XServiceInfo
* >(this),
221 static_cast< css::io::XPersistObject
* >(this),
222 static_cast< css::lang::XTypeProvider
* >(this) );
223 return (aRet
.hasValue() ? aRet
: OWeakAggObject::queryAggregation( rType
));
226 // css::lang::XTypeProvider
227 IMPL_XTYPEPROVIDER_START( StdTabControllerModel
)
228 cppu::UnoType
<css::awt::XTabControllerModel
>::get(),
229 cppu::UnoType
<css::lang::XServiceInfo
>::get(),
230 cppu::UnoType
<css::io::XPersistObject
>::get()
231 IMPL_XTYPEPROVIDER_END
233 sal_Bool
StdTabControllerModel::getGroupControl( )
235 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
237 return mbGroupControl
;
240 void StdTabControllerModel::setGroupControl( sal_Bool GroupControl
)
242 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
244 mbGroupControl
= GroupControl
;
247 void StdTabControllerModel::setControlModels( const css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> >& Controls
)
249 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
252 ImplSetControlModels( maControls
, Controls
);
255 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > StdTabControllerModel::getControlModels( )
257 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
259 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > aSeq( ImplGetControlCount( maControls
) );
260 css::uno::Reference
< css::awt::XControlModel
> * pRefs
= aSeq
.getArray();
261 ImplGetControlModels( &pRefs
, maControls
);
265 void StdTabControllerModel::setGroup( const css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> >& Group
, const OUString
& GroupName
)
267 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
269 // The controls might occur as a flat list and will be grouped.
270 // Nested groups are not possible.
271 // The first element of a group determines its position.
272 UnoControlModelEntry
* pNewEntry
= new UnoControlModelEntry
;
273 pNewEntry
->bGroup
= true;
274 pNewEntry
->pGroup
= new UnoControlModelEntryList
;
275 pNewEntry
->pGroup
->SetName( GroupName
);
276 ImplSetControlModels( *pNewEntry
->pGroup
, Group
);
278 bool bInserted
= false;
279 size_t nElements
= pNewEntry
->pGroup
->size();
280 for ( size_t n
= 0; n
< nElements
; n
++ )
282 UnoControlModelEntry
* pEntry
= (*pNewEntry
->pGroup
)[ n
];
283 if ( !pEntry
->bGroup
)
285 sal_uInt32 nPos
= ImplGetControlPos( *pEntry
->pxControl
, maControls
);
286 // At the beginning, all Controls should be in a flattened list
287 DBG_ASSERT( nPos
!= CONTROLPOS_NOTFOUND
, "setGroup - Element not found" );
288 if ( nPos
!= CONTROLPOS_NOTFOUND
)
290 maControls
.DestroyEntry( nPos
);
293 maControls
.insert( nPos
, pNewEntry
);
300 maControls
.push_back( pNewEntry
);
303 sal_Int32
StdTabControllerModel::getGroupCount( )
305 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
307 // Start with only one group layer, even though Model and Impl-methods
308 // work recursively, this is not presented to the outside.
310 sal_Int32 nGroups
= 0;
311 size_t nEntries
= maControls
.size();
312 for ( size_t n
= 0; n
< nEntries
; n
++ )
314 UnoControlModelEntry
* pEntry
= maControls
[ n
];
315 if ( pEntry
->bGroup
)
321 void StdTabControllerModel::getGroup( sal_Int32 nGroup
, css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> >& rGroup
, OUString
& rName
)
323 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
325 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > aSeq
;
327 size_t nEntries
= maControls
.size();
328 for ( size_t n
= 0; n
< nEntries
; n
++ )
330 UnoControlModelEntry
* pEntry
= maControls
[ n
];
331 if ( pEntry
->bGroup
)
333 if ( nG
== static_cast<sal_uInt32
>(nGroup
) )
335 sal_uInt32 nCount
= ImplGetControlCount( *pEntry
->pGroup
);
336 aSeq
= css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> >( nCount
);
337 css::uno::Reference
< css::awt::XControlModel
> * pRefs
= aSeq
.getArray();
338 ImplGetControlModels( &pRefs
, *pEntry
->pGroup
);
339 rName
= pEntry
->pGroup
->GetName();
348 void StdTabControllerModel::getGroupByName( const OUString
& rName
, css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> >& rGroup
)
350 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
352 sal_uInt32 nGroup
= 0;
353 size_t nEntries
= maControls
.size();
354 for ( size_t n
= 0; n
< nEntries
; n
++ )
356 UnoControlModelEntry
* pEntry
= maControls
[ n
];
357 if ( pEntry
->bGroup
)
359 if ( pEntry
->pGroup
->GetName() == rName
)
362 getGroup( nGroup
, rGroup
, Dummy
);
371 // css::io::XPersistObject
372 OUString
StdTabControllerModel::getServiceName( )
374 return OUString::createFromAscii( szServiceName_TabControllerModel
);
377 void StdTabControllerModel::write( const css::uno::Reference
< css::io::XObjectOutputStream
>& OutStream
)
379 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
381 css::uno::Reference
< css::io::XMarkableStream
> xMark( OutStream
, css::uno::UNO_QUERY
);
382 DBG_ASSERT( xMark
.is(), "write: no XMarkableStream!" );
384 OutStream
->writeShort( UNOCONTROL_STREAMVERSION
);
386 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > aCtrls
= getControlModels();
387 ImplWriteControls( OutStream
, aCtrls
);
389 sal_uInt32 nGroups
= getGroupCount();
390 OutStream
->writeLong( nGroups
);
391 for ( sal_uInt32 n
= 0; n
< nGroups
; n
++ )
393 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > aGroupCtrls
;
395 getGroup( n
, aGroupCtrls
, aGroupName
);
396 OutStream
->writeUTF( aGroupName
);
397 ImplWriteControls( OutStream
, aGroupCtrls
);
401 void StdTabControllerModel::read( const css::uno::Reference
< css::io::XObjectInputStream
>& InStream
)
403 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
405 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > aSeq
= ImplReadControls( InStream
);
406 setControlModels( aSeq
);
408 sal_uInt32 nGroups
= InStream
->readLong();
409 for ( sal_uInt32 n
= 0; n
< nGroups
; n
++ )
411 OUString aGroupName
= InStream
->readUTF();
412 css::uno::Sequence
< css::uno::Reference
< css::awt::XControlModel
> > aCtrlSeq
= ImplReadControls( InStream
);
413 setGroup( aCtrlSeq
, aGroupName
);
417 OUString
StdTabControllerModel::getImplementationName()
419 return OUString("stardiv.Toolkit.StdTabControllerModel");
422 sal_Bool
StdTabControllerModel::supportsService(OUString
const & ServiceName
)
424 return cppu::supportsService(this, ServiceName
);
427 css::uno::Sequence
<OUString
> StdTabControllerModel::getSupportedServiceNames()
429 return css::uno::Sequence
<OUString
>{
430 OUString::createFromAscii(szServiceName2_TabControllerModel
),
431 "stardiv.vcl.controlmodel.TabController"};
434 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
435 stardiv_Toolkit_StdTabControllerModel_get_implementation(
436 css::uno::XComponentContext
*,
437 css::uno::Sequence
<css::uno::Any
> const &)
439 return cppu::acquire(new StdTabControllerModel());
442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */