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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_toolkit.hxx"
26 #include <com/sun/star/io/XMarkableStream.hpp>
27 
28 #include <toolkit/controls/stdtabcontrollermodel.hxx>
29 #include <toolkit/helper/macros.hxx>
30 #include <toolkit/helper/servicenames.hxx>
31 #include <toolkit/helper/property.hxx>
32 #include <cppuhelper/typeprovider.hxx>
33 #include <rtl/memory.h>
34 #include <rtl/uuid.h>
35 
36 #include <tools/debug.hxx>
37 
38 #define UNOCONTROL_STREAMVERSION	(short)2
39 
40 //	----------------------------------------------------
41 //	class UnoControlModelEntryList
42 //	----------------------------------------------------
UnoControlModelEntryList()43 UnoControlModelEntryList::UnoControlModelEntryList()
44 {
45 }
46 
~UnoControlModelEntryList()47 UnoControlModelEntryList::~UnoControlModelEntryList()
48 {
49 	Reset();
50 }
51 
Reset()52 void UnoControlModelEntryList::Reset()
53 {
54 	for ( sal_uInt32 n = Count(); n; )
55 		DestroyEntry( --n );
56 }
57 
DestroyEntry(sal_uInt32 nEntry)58 void UnoControlModelEntryList::DestroyEntry( sal_uInt32 nEntry )
59 {
60 	UnoControlModelEntry* pEntry = GetObject( nEntry );
61 
62 	if ( pEntry->bGroup )
63 		delete pEntry->pGroup;
64 	else
65 		delete pEntry->pxControl;
66 
67 	Remove( nEntry );
68 	delete pEntry;
69 }
70 
71 //	----------------------------------------------------
72 //	class StdTabControllerModel
73 //	----------------------------------------------------
StdTabControllerModel()74 StdTabControllerModel::StdTabControllerModel()
75 {
76 	mbGroupControl = sal_True;
77 }
78 
~StdTabControllerModel()79 StdTabControllerModel::~StdTabControllerModel()
80 {
81 }
82 
ImplGetControlCount(const UnoControlModelEntryList & rList) const83 sal_uInt32 StdTabControllerModel::ImplGetControlCount( const UnoControlModelEntryList& rList ) const
84 {
85 	sal_uInt32 nCount = 0;
86 	sal_uInt32 nEntries = rList.Count();
87 	for ( sal_uInt32 n = 0; n < nEntries; n++ )
88 	{
89 		UnoControlModelEntry* pEntry = rList.GetObject( n );
90 		if ( pEntry->bGroup )
91 			nCount += ImplGetControlCount( *pEntry->pGroup );
92 		else
93 			nCount++;
94 	}
95 	return nCount;
96 }
97 
ImplGetControlModels(::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel> ** ppRefs,const UnoControlModelEntryList & rList) const98 void StdTabControllerModel::ImplGetControlModels( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > ** ppRefs, const UnoControlModelEntryList& rList ) const
99 {
100 	sal_uInt32 nEntries = rList.Count();
101 	for ( sal_uInt32 n = 0; n < nEntries; n++ )
102 	{
103 		UnoControlModelEntry* pEntry = rList.GetObject( n );
104 		if ( pEntry->bGroup )
105 			ImplGetControlModels( ppRefs, *pEntry->pGroup );
106 		else
107 		{
108 			**ppRefs = *pEntry->pxControl;
109 			(*ppRefs)++;
110 		}
111 	}
112 }
113 
ImplSetControlModels(UnoControlModelEntryList & rList,const::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel>> & Controls) const114 void StdTabControllerModel::ImplSetControlModels( UnoControlModelEntryList& rList, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& Controls ) const
115 {
116 	const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > * pRefs = Controls.getConstArray();
117 	sal_uInt32 nControls = Controls.getLength();
118 	for ( sal_uInt32 n = 0; n < nControls; n++ )
119 	{
120 		UnoControlModelEntry* pNewEntry = new UnoControlModelEntry;
121 		pNewEntry->bGroup = sal_False;
122 		pNewEntry->pxControl = new ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > ;
123 		*pNewEntry->pxControl = pRefs[n];
124 		rList.Insert( pNewEntry, LIST_APPEND );
125 	}
126 }
127 
ImplGetControlPos(const::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel> xCtrl,const UnoControlModelEntryList & rList) const128 sal_uInt32 StdTabControllerModel::ImplGetControlPos( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >  xCtrl, const UnoControlModelEntryList& rList ) const
129 {
130 	for ( sal_uInt32 n = rList.Count(); n; )
131 	{
132 		UnoControlModelEntry* pEntry = rList.GetObject( --n );
133 		if ( !pEntry->bGroup && ( *pEntry->pxControl == xCtrl ) )
134 			return n;
135 	}
136 	return CONTROLPOS_NOTFOUND;
137 }
138 
ImplWriteControls(const::com::sun::star::uno::Reference<::com::sun::star::io::XObjectOutputStream> & OutStream,const::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel>> & rCtrls)139 void ImplWriteControls( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream > & OutStream, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& rCtrls )
140 {
141 	::com::sun::star::uno::Reference< ::com::sun::star::io::XMarkableStream >  xMark( OutStream, ::com::sun::star::uno::UNO_QUERY );
142 	DBG_ASSERT( xMark.is(), "write: no XMarkableStream!" );
143 
144 	sal_uInt32 nStoredControls = 0;
145 	sal_Int32 nDataBeginMark = xMark->createMark();
146 
147 	OutStream->writeLong( 0L );	// DataLen
148 	OutStream->writeLong( 0L );	// nStoredControls
149 
150 	sal_uInt32 nCtrls = rCtrls.getLength();
151 	for ( sal_uInt32 n = 0; n < nCtrls; n++ )
152 	{
153 		const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >  xI = rCtrls.getConstArray()[n];
154 		::com::sun::star::uno::Reference< ::com::sun::star::io::XPersistObject >  xPO( xI, ::com::sun::star::uno::UNO_QUERY );
155 		DBG_ASSERT( xPO.is(), "write: Control doesn't support XPersistObject" );
156 		if ( xPO.is() )
157 		{
158 			OutStream->writeObject( xPO );
159 			nStoredControls++;
160 		}
161 	}
162 	sal_Int32 nDataLen = xMark->offsetToMark( nDataBeginMark );
163 	xMark->jumpToMark( nDataBeginMark );
164 	OutStream->writeLong( nDataLen );
165 	OutStream->writeLong( nStoredControls );
166 	xMark->jumpToFurthest();
167 	xMark->deleteMark(nDataBeginMark);
168 }
169 
ImplReadControls(const::com::sun::star::uno::Reference<::com::sun::star::io::XObjectInputStream> & InStream)170 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > ImplReadControls( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream > & InStream )
171 {
172 	::com::sun::star::uno::Reference< ::com::sun::star::io::XMarkableStream >  xMark( InStream, ::com::sun::star::uno::UNO_QUERY );
173 	DBG_ASSERT( xMark.is(), "write: no XMarkableStream!" );
174 
175 	sal_Int32 nDataBeginMark = xMark->createMark();
176 
177 	sal_Int32 nDataLen = InStream->readLong();
178 	sal_uInt32 nCtrls = InStream->readLong();
179 
180 	::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > aSeq( nCtrls );
181 	for ( sal_uInt32 n = 0; n < nCtrls; n++ )
182 	{
183 		::com::sun::star::uno::Reference< ::com::sun::star::io::XPersistObject >  xObj = InStream->readObject();
184 		::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >  xI( xObj, ::com::sun::star::uno::UNO_QUERY );
185 		aSeq.getArray()[n] = xI;
186 	}
187 
188 	// Falls bereits mehr drinsteht als diese Version kennt:
189 	xMark->jumpToMark( nDataBeginMark );
190 	InStream->skipBytes( nDataLen );
191 	xMark->deleteMark(nDataBeginMark);
192 	return aSeq;
193 }
194 
195 
196 // ::com::sun::star::uno::XInterface
queryAggregation(const::com::sun::star::uno::Type & rType)197 ::com::sun::star::uno::Any StdTabControllerModel::queryAggregation( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException)
198 {
199 	::com::sun::star::uno::Any aRet = ::cppu::queryInterface( rType,
200 										SAL_STATIC_CAST( ::com::sun::star::awt::XTabControllerModel*, this ),
201 										SAL_STATIC_CAST( ::com::sun::star::lang::XServiceInfo*, this ),
202 										SAL_STATIC_CAST( ::com::sun::star::io::XPersistObject*, this ),
203 										SAL_STATIC_CAST( ::com::sun::star::lang::XTypeProvider*, this ) );
204 	return (aRet.hasValue() ? aRet : OWeakAggObject::queryAggregation( rType ));
205 }
206 
207 // ::com::sun::star::lang::XTypeProvider
208 IMPL_XTYPEPROVIDER_START( StdTabControllerModel )
209 	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTabControllerModel>* ) NULL ),
210 	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XServiceInfo>* ) NULL ),
211 	getCppuType( ( ::com::sun::star::uno::Reference< ::com::sun::star::io::XPersistObject>* ) NULL )
212 IMPL_XTYPEPROVIDER_END
213 
214 sal_Bool StdTabControllerModel::getGroupControl(  ) throw(::com::sun::star::uno::RuntimeException)
215 {
216 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
217 
218 	return mbGroupControl;
219 }
220 
setGroupControl(sal_Bool GroupControl)221 void StdTabControllerModel::setGroupControl( sal_Bool GroupControl ) throw(::com::sun::star::uno::RuntimeException)
222 {
223 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
224 
225 	mbGroupControl = GroupControl;
226 }
227 
setControlModels(const::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel>> & Controls)228 void StdTabControllerModel::setControlModels( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& Controls ) throw(::com::sun::star::uno::RuntimeException)
229 {
230 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
231 
232 	maControls.Reset();
233 	ImplSetControlModels( maControls, Controls );
234 }
235 
getControlModels()236 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > StdTabControllerModel::getControlModels(  ) throw(::com::sun::star::uno::RuntimeException)
237 {
238 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
239 
240 	::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > aSeq( ImplGetControlCount( maControls ) );
241 	::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > * pRefs = aSeq.getArray();
242 	ImplGetControlModels( &pRefs, maControls );
243 	return aSeq;
244 }
245 
setGroup(const::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel>> & Group,const::rtl::OUString & GroupName)246 void StdTabControllerModel::setGroup( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& Group, const ::rtl::OUString& GroupName ) throw(::com::sun::star::uno::RuntimeException)
247 {
248 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
249 
250 	// Die Controls stehen eventuel flach in der Liste und werden jetzt gruppiert.
251 	// Verschachtelte Gruppen sind erstmal nicht moeglich...
252 	// Das erste Element der Gruppe welches auch schon in der flachen Liste
253 	// stand bestimmt die Position der Gruppe.
254 
255 	UnoControlModelEntry* pNewEntry = new UnoControlModelEntry;
256 	pNewEntry->bGroup = sal_True;
257 	pNewEntry->pGroup = new UnoControlModelEntryList;
258 	pNewEntry->pGroup->SetName( GroupName );
259 	ImplSetControlModels( *pNewEntry->pGroup, Group );
260 
261 	sal_Bool bInserted = sal_False;
262 	sal_uInt32 nElements = pNewEntry->pGroup->Count();
263 	for ( sal_uInt32 n = 0; n < nElements; n++ )
264 	{
265 		UnoControlModelEntry* pEntry = pNewEntry->pGroup->GetObject( n );
266 		if ( !pEntry->bGroup )
267 		{
268 			sal_uInt32 nPos = ImplGetControlPos( *pEntry->pxControl, maControls );
269 			// Eigentlich sollten alle Controls vorher in der flachen Liste stehen
270 			DBG_ASSERT( nPos != CONTROLPOS_NOTFOUND, "setGroup - Element not found" );
271 			if ( nPos != CONTROLPOS_NOTFOUND )
272 			{
273 				maControls.DestroyEntry( nPos );
274 				if ( !bInserted )
275 				{
276 					maControls.Insert( pNewEntry, nPos );
277 					bInserted = sal_True;
278 				}
279 			}
280 		}
281 	}
282 	if ( !bInserted )
283 		maControls.Insert( pNewEntry, LIST_APPEND );
284 }
285 
getGroupCount()286 sal_Int32 StdTabControllerModel::getGroupCount(  ) throw(::com::sun::star::uno::RuntimeException)
287 {
288 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
289 
290 	// erstmal nur eine Ebene...
291 	// Das Model und die Impl-Methoden arbeiten zwar rekursiv, aber das wird
292 	// erstmal nich nach aussen gegeben.
293 
294 	sal_Int32 nGroups = 0;
295 	sal_uInt32 nEntries = maControls.Count();
296 	for ( sal_uInt32 n = 0; n < nEntries; n++ )
297 	{
298 		UnoControlModelEntry* pEntry = maControls.GetObject( n );
299 		if ( pEntry->bGroup )
300 			nGroups++;
301 	}
302 	return nGroups;
303 }
304 
getGroup(sal_Int32 nGroup,::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel>> & rGroup,::rtl::OUString & rName)305 void StdTabControllerModel::getGroup( sal_Int32 nGroup, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& rGroup, ::rtl::OUString& rName ) throw(::com::sun::star::uno::RuntimeException)
306 {
307 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
308 
309 	::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > aSeq;
310 	sal_uInt32 nG = 0;
311 	sal_uInt32 nEntries = maControls.Count();
312 	for ( sal_uInt32 n = 0; n < nEntries; n++ )
313 	{
314 		UnoControlModelEntry* pEntry = maControls.GetObject( n );
315 		if ( pEntry->bGroup )
316 		{
317 			if ( nG == (sal_uInt32)nGroup )
318 			{
319 				sal_uInt32 nCount = ImplGetControlCount( *pEntry->pGroup );
320 				aSeq = ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >( nCount );
321 				::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > * pRefs = aSeq.getArray();
322 				ImplGetControlModels( &pRefs, *pEntry->pGroup );
323 				rName = pEntry->pGroup->GetName();
324 				break;
325 			}
326 			nG++;
327 		}
328 	}
329 	rGroup = aSeq;
330 }
331 
getGroupByName(const::rtl::OUString & rName,::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel>> & rGroup)332 void StdTabControllerModel::getGroupByName( const ::rtl::OUString& rName, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > >& rGroup ) throw(::com::sun::star::uno::RuntimeException)
333 {
334 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
335 
336 	sal_uInt32 nGroup = 0;
337 	sal_uInt32 nEntries = maControls.Count();
338 	for ( sal_uInt32 n = 0; n < nEntries; n++ )
339 	{
340 		UnoControlModelEntry* pEntry = maControls.GetObject( n );
341 		if ( pEntry->bGroup )
342 		{
343 			if ( pEntry->pGroup->GetName() == rName )
344 			{
345 				::rtl::OUString Dummy;
346 				getGroup( nGroup, rGroup, Dummy );
347 				break;
348 			}
349 			nGroup++;
350 		}
351 	}
352 }
353 
354 
355 // ::com::sun::star::io::XPersistObject
getServiceName()356 ::rtl::OUString StdTabControllerModel::getServiceName(  ) throw(::com::sun::star::uno::RuntimeException)
357 {
358 	return ::rtl::OUString::createFromAscii( szServiceName_TabControllerModel );
359 }
360 
write(const::com::sun::star::uno::Reference<::com::sun::star::io::XObjectOutputStream> & OutStream)361 void StdTabControllerModel::write( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream >& OutStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
362 {
363 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
364 
365 	::com::sun::star::uno::Reference< ::com::sun::star::io::XMarkableStream >  xMark( OutStream, ::com::sun::star::uno::UNO_QUERY );
366 	DBG_ASSERT( xMark.is(), "write: no XMarkableStream!" );
367 
368 	OutStream->writeShort( UNOCONTROL_STREAMVERSION );
369 
370 	::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > aCtrls = getControlModels();
371 	ImplWriteControls( OutStream, aCtrls );
372 
373 	sal_uInt32 nGroups = getGroupCount();
374 	OutStream->writeLong( nGroups );
375 	for ( sal_uInt32 n = 0; n < nGroups; n++ )
376 	{
377 		::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > aGroupCtrls;
378 		::rtl::OUString aGroupName;
379 		getGroup( n, aGroupCtrls, aGroupName );
380 		OutStream->writeUTF( aGroupName );
381 		ImplWriteControls( OutStream, aGroupCtrls );
382 	}
383 }
384 
read(const::com::sun::star::uno::Reference<::com::sun::star::io::XObjectInputStream> & InStream)385 void StdTabControllerModel::read( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream >& InStream ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
386 {
387 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
388 
389 	::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > aSeq = ImplReadControls( InStream );
390 	setControlModels( aSeq );
391 
392 	sal_uInt32 nGroups = InStream->readLong();
393 	for ( sal_uInt32 n = 0; n < nGroups; n++ )
394 	{
395 		::rtl::OUString aGroupName = InStream->readUTF();
396 		::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel > > aCtrlSeq = ImplReadControls( InStream );
397 		setGroup( aCtrlSeq, aGroupName );
398 	}
399 }
400 
401 
402 
403 
404 
405