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