Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <com/sun/star/beans/XPropertySet.hpp>
30 : : #include <com/sun/star/awt/XVclContainerPeer.hpp>
31 : :
32 : : #include <toolkit/controls/stdtabcontroller.hxx>
33 : : #include <toolkit/controls/stdtabcontrollermodel.hxx>
34 : : #include <toolkit/awt/vclxwindow.hxx>
35 : : #include <toolkit/helper/macros.hxx>
36 : : #include <cppuhelper/typeprovider.hxx>
37 : : #include <rtl/memory.h>
38 : : #include <rtl/uuid.h>
39 : :
40 : : #include <tools/debug.hxx>
41 : : #include <vcl/window.hxx>
42 : : #include <comphelper/sequence.hxx>
43 : :
44 : : using namespace ::com::sun::star;
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 : :
50 : : // ----------------------------------------------------
51 : : // class StdTabController
52 : : // ----------------------------------------------------
53 [ + - ][ + - ]: 30 : StdTabController::StdTabController()
54 : : {
55 : 30 : }
56 : :
57 [ + - ][ + - ]: 21 : StdTabController::~StdTabController()
58 : : {
59 [ - + ]: 42 : }
60 : :
61 : 50 : sal_Bool StdTabController::ImplCreateComponentSequence(
62 : : Sequence< Reference< XControl > >& rControls,
63 : : const Sequence< Reference< XControlModel > >& rModels,
64 : : Sequence< Reference< XWindow > >& rComponents,
65 : : Sequence< Any>* pTabStops,
66 : : sal_Bool bPeerComponent ) const
67 : : {
68 : 50 : sal_Bool bOK = sal_True;
69 : :
70 : : // Get only the requested controls
71 : 50 : sal_Int32 nModels = rModels.getLength();
72 [ + + ]: 50 : if (nModels != rControls.getLength())
73 : : {
74 [ + - ]: 18 : Sequence< Reference< XControl > > aSeq( nModels );
75 : 18 : const Reference< XControlModel >* pModels = rModels.getConstArray();
76 : 18 : Reference< XControl > xCurrentControl;
77 : :
78 : 18 : sal_Int32 nRealControls = 0;
79 [ + + ]: 52 : for (sal_Int32 n = 0; n < nModels; ++n, ++pModels)
80 : : {
81 [ + - ][ + - ]: 34 : xCurrentControl = FindControl(rControls, *pModels);
82 [ - + ]: 34 : if (xCurrentControl.is())
83 [ # # ][ # # ]: 0 : aSeq.getArray()[nRealControls++] = xCurrentControl;
84 : : }
85 [ + - ]: 18 : aSeq.realloc(nRealControls);
86 [ + - ][ + - ]: 18 : rControls = aSeq;
87 : : }
88 : : #ifdef DBG_UTIL
89 : : DBG_ASSERT( rControls.getLength() <= rModels.getLength(), "StdTabController:ImplCreateComponentSequence: inconsistence!" );
90 : : // there may be less controls than models, but never more controls than models
91 : : #endif
92 : :
93 : :
94 : 50 : const Reference< XControl > * pControls = rControls.getConstArray();
95 : 50 : sal_uInt32 nCtrls = rControls.getLength();
96 : 50 : rComponents.realloc( nCtrls );
97 : 50 : Reference< XWindow > * pComps = rComponents.getArray();
98 : 50 : Any* pTabs = NULL;
99 : :
100 : :
101 [ + + ]: 50 : if ( pTabStops )
102 : : {
103 [ + - ]: 42 : *pTabStops = Sequence< Any>( nCtrls );
104 : 42 : pTabs = pTabStops->getArray();
105 : : }
106 : :
107 [ + - ][ + + ]: 114 : for ( sal_uInt32 n = 0; bOK && ( n < nCtrls ); n++ )
[ + + ]
108 : : {
109 : : // Get the matching control for this model
110 : 64 : Reference< XControl > xCtrl(pControls[n]);
111 [ + - ]: 64 : if ( xCtrl.is() )
112 : : {
113 [ + + ]: 64 : if (bPeerComponent)
114 [ + - ][ + - ]: 62 : pComps[n] = Reference< XWindow > (xCtrl->getPeer(), UNO_QUERY);
[ + - ][ + - ]
115 : : else
116 [ + - ][ + - ]: 2 : pComps[n] = Reference< XWindow > (xCtrl, UNO_QUERY);
117 : :
118 : : // TabStop-Property
119 [ + + ]: 64 : if ( pTabs )
120 : : {
121 : : // opt: Constant String for TabStop name
122 [ + + ][ + - ]: 46 : static const ::rtl::OUString aTabStopName( "Tabstop" );
123 : :
124 [ + - ][ + - ]: 46 : Reference< XPropertySet > xPSet( xCtrl->getModel(), UNO_QUERY );
[ + - ]
125 [ + - ][ + - ]: 46 : Reference< XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
126 [ + - ][ + - ]: 46 : if( xInfo->hasPropertyByName( aTabStopName ) )
[ + - ]
127 [ + - ][ + - ]: 46 : *pTabs++ = xPSet->getPropertyValue( aTabStopName );
128 : : else
129 : 46 : ++pTabs;
130 : : }
131 : : }
132 : : else
133 : : {
134 : : OSL_TRACE( "ImplCreateComponentSequence: Control not found" );
135 : 0 : bOK = sal_False;
136 : : }
137 : 64 : }
138 : 50 : return bOK;
139 : : }
140 : :
141 : 4 : void StdTabController::ImplActivateControl( sal_Bool bFirst ) const
142 : : {
143 : : // HACK due to bug #53688#, map controls onto an interface if remote controls may occur
144 [ + - ]: 4 : Reference< XTabController > xTabController(const_cast< ::cppu::OWeakObject* >(static_cast< const ::cppu::OWeakObject* >(this)), UNO_QUERY);
145 [ + - ][ + - ]: 4 : Sequence< Reference< XControl > > aCtrls = xTabController->getControls();
146 : 4 : const Reference< XControl > * pControls = aCtrls.getConstArray();
147 : 4 : sal_uInt32 nCount = aCtrls.getLength();
148 : :
149 [ + + ][ + - ]: 4 : for ( sal_uInt32 n = bFirst ? 0 : nCount; bFirst ? ( n < nCount ) : n; )
[ + + ]
150 : : {
151 [ + + ]: 4 : sal_uInt32 nCtrl = bFirst ? n++ : --n;
152 : : DBG_ASSERT( pControls[nCtrl].is(), "Control nicht im Container!" );
153 [ + - ]: 4 : if ( pControls[nCtrl].is() )
154 : : {
155 [ + - ][ + - ]: 4 : Reference< XWindowPeer > xCP = pControls[nCtrl]->getPeer();
156 [ + - ]: 4 : if ( xCP.is() )
157 : : {
158 : 4 : VCLXWindow* pC = VCLXWindow::GetImplementation( xCP );
159 [ + - ][ + - ]: 4 : if ( pC && pC->GetWindow() && ( pC->GetWindow()->GetStyle() & WB_TABSTOP ) )
[ + - ][ + - ]
[ + - ]
160 : : {
161 [ + - ]: 4 : pC->GetWindow()->GrabFocus();
162 : : break;
163 : : }
164 [ - + ]: 4 : }
165 : : }
166 [ + - ]: 4 : }
167 : 4 : }
168 : :
169 : : // XInterface
170 : 62 : Any StdTabController::queryAggregation( const Type & rType ) throw(RuntimeException)
171 : : {
172 : : Any aRet = ::cppu::queryInterface( rType,
173 : : (static_cast< XTabController* >(this)),
174 : : (static_cast< XServiceInfo* >(this)),
175 [ + - ]: 62 : (static_cast< XTypeProvider* >(this)) );
176 [ + + ][ + - ]: 62 : return (aRet.hasValue() ? aRet : OWeakAggObject::queryAggregation( rType ));
177 : : }
178 : :
179 : : // XTypeProvider
180 [ # # ][ # # ]: 0 : IMPL_XTYPEPROVIDER_START( StdTabController )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
181 [ # # ]: 0 : getCppuType( ( Reference< XTabController>* ) NULL ),
182 [ # # ]: 0 : getCppuType( ( Reference< XServiceInfo>* ) NULL )
183 [ # # ][ # # ]: 0 : IMPL_XTYPEPROVIDER_END
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
184 : :
185 : 49 : void StdTabController::setModel( const Reference< XTabControllerModel >& Model ) throw(RuntimeException)
186 : : {
187 [ + - ]: 49 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
188 : :
189 [ + - ][ + - ]: 49 : mxModel = Model;
190 : 49 : }
191 : :
192 : 121 : Reference< XTabControllerModel > StdTabController::getModel( ) throw(RuntimeException)
193 : : {
194 [ + - ]: 121 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
195 : :
196 [ + - ]: 121 : return mxModel;
197 : : }
198 : :
199 : 41 : void StdTabController::setContainer( const Reference< XControlContainer >& Container ) throw(RuntimeException)
200 : : {
201 [ + - ]: 41 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
202 : :
203 [ + - ][ + - ]: 41 : mxControlContainer = Container;
204 : 41 : }
205 : :
206 : 37 : Reference< XControlContainer > StdTabController::getContainer( ) throw(RuntimeException)
207 : : {
208 [ + - ]: 37 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
209 : :
210 [ + - ]: 37 : return mxControlContainer;
211 : : }
212 : :
213 : 12 : Sequence< Reference< XControl > > StdTabController::getControls( ) throw(RuntimeException)
214 : : {
215 [ + - ]: 12 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
216 : :
217 [ + - ]: 12 : Sequence< Reference< XControl > > aSeq;
218 : :
219 [ + - ]: 12 : if ( mxControlContainer.is() )
220 : : {
221 [ + - ][ + - ]: 12 : Sequence< Reference< XControlModel > > aModels = mxModel->getControlModels();
222 : 12 : const Reference< XControlModel > * pModels = aModels.getConstArray();
223 : :
224 [ + - ][ + - ]: 12 : Sequence< Reference< XControl > > xCtrls = mxControlContainer->getControls();
225 : :
226 : 12 : sal_uInt32 nCtrls = aModels.getLength();
227 [ + - ][ + - ]: 12 : aSeq = Sequence< Reference< XControl > >( nCtrls );
[ + - ]
228 [ + + ]: 22 : for ( sal_uInt32 n = 0; n < nCtrls; n++ )
229 : : {
230 : 10 : Reference< XControlModel > xCtrlModel = pModels[n];
231 : : // Search matching Control for this Model
232 [ + - ]: 10 : Reference< XControl > xCtrl = FindControl( xCtrls, xCtrlModel );
233 [ + - ][ + - ]: 10 : aSeq.getArray()[n] = xCtrl;
234 [ + - ][ + - ]: 22 : }
235 : : }
236 [ + - ]: 12 : return aSeq;
237 : : }
238 : :
239 : 2 : void StdTabController::autoTabOrder( ) throw(RuntimeException)
240 : : {
241 [ + - ]: 2 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
242 : :
243 : : DBG_ASSERT( mxControlContainer.is(), "autoTabOrder: No ControlContainer!" );
244 [ - + ]: 2 : if ( !mxControlContainer.is() )
245 : : return;
246 : :
247 [ + - ][ + - ]: 2 : Sequence< Reference< XControlModel > > aSeq = mxModel->getControlModels();
248 [ + - ]: 2 : Sequence< Reference< XWindow > > aCompSeq;
249 : :
250 : : // This may return a TabController, which returns desired list of controls faster
251 [ + - ]: 2 : Reference< XTabController > xTabController(static_cast< ::cppu::OWeakObject* >(this), UNO_QUERY);
252 [ + - ][ + - ]: 2 : Sequence< Reference< XControl > > aControls = xTabController->getControls();
253 : :
254 : : // #58317# Some Models may be missing from the Container. Plus there is a
255 : : // autoTabOrder call later on.
256 [ + - ][ - + ]: 2 : if( !ImplCreateComponentSequence( aControls, aSeq, aCompSeq, NULL, sal_False ) )
257 : : return;
258 : :
259 : 2 : sal_uInt32 nCtrls = aCompSeq.getLength();
260 [ + - ]: 2 : Reference< XWindow > * pComponents = aCompSeq.getArray();
261 : :
262 : : // insert sort algorithm
263 [ + - ]: 2 : ComponentEntryList aCtrls;
264 : : size_t n;
265 [ + + ]: 4 : for ( n = 0; n < nCtrls; n++ )
266 : : {
267 [ + - ]: 2 : XWindow* pC = (XWindow*)pComponents[n].get();
268 [ + - ]: 2 : ComponentEntry* pE = new ComponentEntry;
269 : 2 : pE->pComponent = pC;
270 [ + - ]: 2 : awt::Rectangle aPosSize = pC->getPosSize();
271 : 2 : pE->aPos.X() = aPosSize.X;
272 : 2 : pE->aPos.Y() = aPosSize.Y;
273 : :
274 : : sal_uInt16 nPos;
275 [ - + ]: 2 : for ( nPos = 0; nPos < aCtrls.size(); nPos++ )
276 : : {
277 : 0 : ComponentEntry* pEntry = aCtrls[ nPos ];
278 [ # # ][ # # : 0 : if ( ( pEntry->aPos.Y() > pE->aPos.Y() ) ||
# # # # ]
279 : 0 : ( ( pEntry->aPos.Y() == pE->aPos.Y() ) && ( pEntry->aPos.X() > pE->aPos.X() ) ) )
280 : 0 : break;
281 : : }
282 [ - + ]: 2 : if ( nPos < aCtrls.size() ) {
283 : 0 : ComponentEntryList::iterator it = aCtrls.begin();
284 [ # # ]: 0 : ::std::advance( it, nPos );
285 [ # # ]: 0 : aCtrls.insert( it, pE );
286 : : } else {
287 [ + - ]: 2 : aCtrls.push_back( pE );
288 : : }
289 : : }
290 : :
291 [ + - ]: 2 : Sequence< Reference< XControlModel > > aNewSeq( nCtrls );
292 [ + + ]: 4 : for ( n = 0; n < nCtrls; n++ )
293 : : {
294 : 2 : ComponentEntry* pE = aCtrls[ n ];
295 [ + - ]: 2 : Reference< XControl > xUC( pE->pComponent, UNO_QUERY );
296 [ + - ][ + - ]: 2 : aNewSeq.getArray()[n] = xUC->getModel();
[ + - ][ + - ]
297 : 2 : delete pE;
298 : 2 : }
299 : 2 : aCtrls.clear();
300 : :
301 [ + - ][ + - ]: 2 : mxModel->setControlModels( aNewSeq );
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ + - ]
[ - + ][ + - ]
[ + - ][ + - ]
302 : : }
303 : :
304 : 62 : void StdTabController::activateTabOrder( ) throw(RuntimeException)
305 : : {
306 [ + - ]: 62 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
307 : :
308 : : // Activate tab order for the control container
309 : :
310 [ + - ]: 62 : Reference< XControl > xC( mxControlContainer, UNO_QUERY );
311 : 62 : Reference< XVclContainerPeer > xVclContainerPeer;
312 [ + + ]: 62 : if ( xC.is() )
313 [ + - ][ + - ]: 42 : xVclContainerPeer = xVclContainerPeer.query( xC->getPeer() );
[ + - ][ + - ]
314 [ + + ][ - + ]: 62 : if ( !xC.is() || !xVclContainerPeer.is() )
[ + + ]
315 : : return;
316 : :
317 : : // This may return a TabController, which returns desired list of controls faster
318 [ + - ]: 42 : Reference< XTabController > xTabController(static_cast< ::cppu::OWeakObject* >(this), UNO_QUERY);
319 : :
320 : : // Get a flattened list of controls sequences
321 [ + - ][ + - ]: 42 : Sequence< Reference< XControlModel > > aModels = mxModel->getControlModels();
322 [ + - ]: 42 : Sequence< Reference< XWindow > > aCompSeq;
323 [ + - ]: 42 : Sequence< Any> aTabSeq;
324 : :
325 : : // DG: For the sake of optimization, retrieve Controls from getControls(),
326 : : // this may sound counterproductive, but leads to performance improvements
327 : : // in practical scenarios (Forms)
328 [ + - ][ + - ]: 42 : Sequence< Reference< XControl > > aControls = xTabController->getControls();
329 : :
330 : : // #58317# Some Models may be missing from the Container. Plus there is a
331 : : // autoTabOrder call later on.
332 [ + - ][ - + ]: 42 : if( !ImplCreateComponentSequence( aControls, aModels, aCompSeq, &aTabSeq, sal_True ) )
333 : : return;
334 : :
335 [ + - ][ + - ]: 42 : xVclContainerPeer->setTabOrder( aCompSeq, aTabSeq, mxModel->getGroupControl() );
[ + - ][ + - ]
336 : :
337 : 42 : ::rtl::OUString aName;
338 [ + - ]: 42 : Sequence< Reference< XControlModel > > aThisGroupModels;
339 [ + - ]: 42 : Sequence< Reference< XWindow > > aControlComponents;
340 : :
341 [ + - ][ + - ]: 42 : sal_uInt32 nGroups = mxModel->getGroupCount();
342 [ + + ]: 48 : for ( sal_uInt32 nG = 0; nG < nGroups; nG++ )
343 : : {
344 [ + - ][ + - ]: 6 : mxModel->getGroup( nG, aThisGroupModels, aName );
345 : :
346 [ + - ][ + - ]: 6 : aControls = xTabController->getControls();
[ + - ][ + - ]
347 : : // ImplCreateComponentSequence has a really strange semantics regarding it's first parameter:
348 : : // upon method entry, it expects a super set of the controls which it returns
349 : : // this means we need to completely fill this sequence with all available controls before
350 : : // calling into ImplCreateComponentSequence
351 : :
352 [ + - ]: 6 : aControlComponents.realloc( 0 );
353 : :
354 [ + - ]: 6 : ImplCreateComponentSequence( aControls, aThisGroupModels, aControlComponents, NULL, sal_True );
355 [ + - ][ + - ]: 6 : xVclContainerPeer->setGroup( aControlComponents );
356 [ + - ][ + - ]: 62 : }
[ + - ][ - + ]
[ + - ][ - + ]
[ + - ][ - + ]
[ + - ][ - + ]
[ - + ][ + + ]
[ + + ][ + - ]
[ + + ]
357 : : }
358 : :
359 : 2 : void StdTabController::activateFirst( ) throw(RuntimeException)
360 : : {
361 [ + - ]: 2 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
362 : :
363 [ + - ][ + - ]: 2 : ImplActivateControl( sal_True );
364 : 2 : }
365 : :
366 : 2 : void StdTabController::activateLast( ) throw(RuntimeException)
367 : : {
368 [ + - ]: 2 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
369 : :
370 [ + - ][ + - ]: 2 : ImplActivateControl( sal_False );
371 : 2 : }
372 : :
373 : :
374 : 58 : Reference< XControl > StdTabController::FindControl( Sequence< Reference< XControl > >& rCtrls,
375 : : const Reference< XControlModel > & rxCtrlModel )
376 : : {
377 : : DBG_ASSERT( rxCtrlModel.is(), "ImplFindControl - welches ?!" );
378 : :
379 : 58 : const Reference< XControl > * pCtrls = rCtrls.getConstArray();
380 : 58 : sal_Int32 nCtrls = rCtrls.getLength();
381 [ + + ]: 102 : for ( sal_Int32 n = 0; n < nCtrls; n++ )
382 : : {
383 [ + - ][ + - ]: 44 : Reference< XControlModel > xModel(pCtrls[n].is() ? pCtrls[n]->getModel() : Reference< XControlModel > ());
[ + - ]
384 [ + - ][ + - ]: 44 : if ( (XControlModel*)xModel.get() == (XControlModel*)rxCtrlModel.get() )
[ + + ]
385 : : {
386 : 24 : Reference< XControl > xCtrl( pCtrls[n] );
387 [ + - ]: 24 : ::comphelper::removeElementAt( rCtrls, n );
388 : 44 : return xCtrl;
389 : : }
390 [ + + ]: 44 : }
391 : 58 : return Reference< XControl > ();
392 : : }
393 : :
394 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|