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 :
21 : #include "svx/fmgridif.hxx"
22 : #include "fmprop.hrc"
23 : #include "fmservs.hxx"
24 : #include "svx/fmtools.hxx"
25 : #include "fmurl.hxx"
26 : #include "formcontrolfactory.hxx"
27 : #include "gridcell.hxx"
28 : #include "sdbdatacolumn.hxx"
29 : #include "svx/fmgridcl.hxx"
30 : #include "svx/svxids.hrc"
31 : #include <tools/urlobj.hxx>
32 :
33 : #include <com/sun/star/awt/PosSize.hpp>
34 : #include <com/sun/star/beans/PropertyAttribute.hpp>
35 : #include <com/sun/star/form/FormComponentType.hpp>
36 : #include <com/sun/star/form/XFormComponent.hpp>
37 : #include <com/sun/star/form/XLoadable.hpp>
38 : #include <com/sun/star/lang/DisposedException.hpp>
39 : #include <com/sun/star/sdbc/ResultSetType.hpp>
40 : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
41 : #include <com/sun/star/util/URLTransformer.hpp>
42 : #include <com/sun/star/util/XURLTransformer.hpp>
43 : #include <com/sun/star/view/XSelectionSupplier.hpp>
44 : #include <com/sun/star/sdbcx/XRowLocate.hpp>
45 :
46 : #include <comphelper/container.hxx>
47 : #include <comphelper/enumhelper.hxx>
48 : #include <comphelper/processfactory.hxx>
49 : #include <comphelper/property.hxx>
50 : #include <comphelper/sequence.hxx>
51 : #include <comphelper/servicehelper.hxx>
52 : #include <comphelper/types.hxx>
53 : #include <cppuhelper/supportsservice.hxx>
54 : #include <cppuhelper/typeprovider.hxx>
55 : #include <cppuhelper/queryinterface.hxx>
56 : #include <toolkit/helper/vclunohelper.hxx>
57 : #include <tools/diagnose_ex.h>
58 : #include <sal/macros.h>
59 :
60 : using namespace ::svxform;
61 : using namespace ::com::sun::star::container;
62 : using namespace ::com::sun::star::sdb;
63 : using namespace ::com::sun::star::sdbc;
64 : using namespace ::com::sun::star::uno;
65 : using namespace ::com::sun::star::view;
66 : using namespace ::com::sun::star::beans;
67 : using namespace ::com::sun::star::lang;
68 : using namespace ::com::sun::star::form;
69 : using namespace ::com::sun::star::util;
70 : using namespace ::com::sun::star;
71 :
72 : using ::com::sun::star::sdbcx::XColumnsSupplier;
73 : using ::com::sun::star::frame::XDispatchProviderInterceptor;
74 : using ::com::sun::star::frame::XDispatchProvider;
75 : using ::com::sun::star::accessibility::XAccessible;
76 : using ::com::sun::star::accessibility::XAccessibleContext;
77 : using ::com::sun::star::sdb::XRowSetSupplier;
78 : using ::com::sun::star::awt::XVclWindowPeer;
79 :
80 :
81 :
82 0 : ::com::sun::star::awt::FontDescriptor ImplCreateFontDescriptor( const vcl::Font& rFont )
83 : {
84 0 : ::com::sun::star::awt::FontDescriptor aFD;
85 0 : aFD.Name = rFont.GetName();
86 0 : aFD.StyleName = rFont.GetStyleName();
87 0 : aFD.Height = (sal_Int16)rFont.GetSize().Height();
88 0 : aFD.Width = (sal_Int16)rFont.GetSize().Width();
89 0 : aFD.Family = (sal_Int16)rFont.GetFamily();
90 0 : aFD.CharSet = rFont.GetCharSet();
91 0 : aFD.Pitch = (sal_Int16)rFont.GetPitch();
92 0 : aFD.CharacterWidth = VCLUnoHelper::ConvertFontWidth( rFont.GetWidthType() );
93 0 : aFD.Weight= VCLUnoHelper::ConvertFontWeight( rFont.GetWeight() );
94 0 : aFD.Slant = VCLUnoHelper::ConvertFontSlant( rFont.GetItalic() );
95 0 : aFD.Underline = (sal_Int16)rFont.GetUnderline();
96 0 : aFD.Strikeout = (sal_Int16)rFont.GetStrikeout();
97 0 : aFD.Orientation = rFont.GetOrientation();
98 0 : aFD.Kerning = rFont.IsKerning();
99 0 : aFD.WordLineMode = rFont.IsWordLineMode();
100 0 : aFD.Type = 0; // ??? => Nur an Metric...
101 0 : return aFD;
102 : }
103 :
104 :
105 45 : vcl::Font ImplCreateFont( const ::com::sun::star::awt::FontDescriptor& rDescr )
106 : {
107 45 : vcl::Font aFont;
108 45 : aFont.SetName( rDescr.Name );
109 45 : aFont.SetStyleName( rDescr.StyleName );
110 45 : aFont.SetSize( ::Size( rDescr.Width, rDescr.Height ) );
111 45 : aFont.SetFamily( (FontFamily)rDescr.Family );
112 45 : aFont.SetCharSet( (rtl_TextEncoding)rDescr.CharSet );
113 45 : aFont.SetPitch( (FontPitch)rDescr.Pitch );
114 45 : aFont.SetWidthType( VCLUnoHelper::ConvertFontWidth( rDescr.CharacterWidth ) );
115 45 : aFont.SetWeight( VCLUnoHelper::ConvertFontWeight( rDescr.Weight ) );
116 45 : aFont.SetItalic( (FontItalic)rDescr.Slant );
117 45 : aFont.SetUnderline( (::FontUnderline)rDescr.Underline );
118 45 : aFont.SetStrikeout( (::FontStrikeout)rDescr.Strikeout );
119 45 : aFont.SetOrientation( (sal_Int16)rDescr.Orientation );
120 45 : aFont.SetKerning( static_cast<FontKerning>(rDescr.Kerning) );
121 45 : aFont.SetWordLineMode( rDescr.WordLineMode );
122 45 : return aFont;
123 : }
124 :
125 12 : FmXModifyMultiplexer::FmXModifyMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
126 : :OWeakSubObject( rSource )
127 12 : ,OInterfaceContainerHelper( _rMutex )
128 : {
129 12 : }
130 :
131 :
132 0 : Any SAL_CALL FmXModifyMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
133 : {
134 0 : Any aReturn;
135 0 : aReturn = ::cppu::queryInterface(_rType,
136 : static_cast< ::com::sun::star::util::XModifyListener*>(this),
137 : static_cast< XEventListener*>(this)
138 0 : );
139 :
140 0 : if (!aReturn.hasValue())
141 0 : aReturn = OWeakSubObject::queryInterface( _rType );
142 :
143 0 : return aReturn;
144 : }
145 :
146 :
147 0 : void FmXModifyMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
148 : {
149 0 : }
150 :
151 :
152 0 : void FmXModifyMultiplexer::modified(const EventObject& e) throw( RuntimeException, std::exception )
153 : {
154 0 : EventObject aMulti( e);
155 0 : aMulti.Source = &m_rParent;
156 0 : notifyEach( &XModifyListener::modified, aMulti );
157 0 : }
158 :
159 12 : FmXUpdateMultiplexer::FmXUpdateMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
160 : :OWeakSubObject( rSource )
161 12 : ,OInterfaceContainerHelper( _rMutex )
162 : {
163 12 : }
164 :
165 :
166 0 : Any SAL_CALL FmXUpdateMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
167 : {
168 0 : Any aReturn;
169 0 : aReturn = ::cppu::queryInterface(_rType,
170 : static_cast< XUpdateListener*>(this),
171 : static_cast< XEventListener*>(this)
172 0 : );
173 :
174 0 : if (!aReturn.hasValue())
175 0 : aReturn = OWeakSubObject::queryInterface( _rType );
176 :
177 0 : return aReturn;
178 : }
179 :
180 :
181 0 : void FmXUpdateMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
182 : {
183 0 : }
184 :
185 :
186 0 : sal_Bool FmXUpdateMultiplexer::approveUpdate(const EventObject &e) throw( RuntimeException, std::exception )
187 : {
188 0 : EventObject aMulti( e );
189 0 : aMulti.Source = &m_rParent;
190 :
191 0 : bool bResult = true;
192 0 : if (getLength())
193 : {
194 0 : ::cppu::OInterfaceIteratorHelper aIter(*this);
195 0 : while ( bResult && aIter.hasMoreElements() )
196 0 : bResult = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aMulti );
197 : }
198 :
199 0 : return bResult;
200 : }
201 :
202 :
203 0 : void FmXUpdateMultiplexer::updated(const EventObject &e) throw( RuntimeException, std::exception )
204 : {
205 0 : EventObject aMulti( e );
206 0 : aMulti.Source = &m_rParent;
207 0 : notifyEach( &XUpdateListener::updated, aMulti );
208 0 : }
209 :
210 12 : FmXSelectionMultiplexer::FmXSelectionMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
211 : :OWeakSubObject( rSource )
212 12 : ,OInterfaceContainerHelper( _rMutex )
213 : {
214 12 : }
215 :
216 :
217 0 : Any SAL_CALL FmXSelectionMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
218 : {
219 0 : Any aReturn;
220 0 : aReturn = ::cppu::queryInterface(_rType,
221 : static_cast< XSelectionChangeListener*>(this),
222 : static_cast< XEventListener*>(this)
223 0 : );
224 :
225 0 : if (!aReturn.hasValue())
226 0 : aReturn = OWeakSubObject::queryInterface( _rType );
227 :
228 0 : return aReturn;
229 : }
230 :
231 :
232 0 : void FmXSelectionMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
233 : {
234 0 : }
235 :
236 :
237 0 : void SAL_CALL FmXSelectionMultiplexer::selectionChanged( const EventObject& _rEvent ) throw (RuntimeException, std::exception)
238 : {
239 0 : EventObject aMulti(_rEvent);
240 0 : aMulti.Source = &m_rParent;
241 0 : notifyEach( &XSelectionChangeListener::selectionChanged, aMulti );
242 0 : }
243 :
244 12 : FmXContainerMultiplexer::FmXContainerMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
245 : :OWeakSubObject( rSource )
246 12 : ,OInterfaceContainerHelper( _rMutex )
247 : {
248 12 : }
249 :
250 :
251 0 : Any SAL_CALL FmXContainerMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
252 : {
253 0 : Any aReturn;
254 0 : aReturn = ::cppu::queryInterface(_rType,
255 : static_cast< XContainerListener*>(this),
256 : static_cast< XEventListener*>(this)
257 0 : );
258 :
259 0 : if (!aReturn.hasValue())
260 0 : aReturn = OWeakSubObject::queryInterface( _rType );
261 :
262 0 : return aReturn;
263 : }
264 :
265 :
266 0 : void FmXContainerMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
267 : {
268 0 : }
269 :
270 0 : void FmXContainerMultiplexer::elementInserted(const ContainerEvent& e) throw( RuntimeException, std::exception )
271 : {
272 0 : ContainerEvent aMulti( e );
273 0 : aMulti.Source = &m_rParent;
274 0 : notifyEach( &XContainerListener::elementInserted, aMulti );
275 0 : }
276 :
277 :
278 0 : void FmXContainerMultiplexer::elementRemoved(const ContainerEvent& e) throw( RuntimeException, std::exception )
279 : {
280 0 : ContainerEvent aMulti( e );
281 0 : aMulti.Source = &m_rParent;
282 0 : notifyEach( &XContainerListener::elementRemoved, aMulti );
283 0 : }
284 :
285 :
286 :
287 0 : void FmXContainerMultiplexer::elementReplaced(const ContainerEvent& e) throw( RuntimeException, std::exception )
288 : {
289 0 : ContainerEvent aMulti( e );
290 0 : aMulti.Source = &m_rParent;
291 0 : notifyEach( &XContainerListener::elementReplaced, aMulti );
292 0 : }
293 :
294 12 : FmXGridControlMultiplexer::FmXGridControlMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
295 : :OWeakSubObject( rSource )
296 12 : ,OInterfaceContainerHelper( _rMutex )
297 : {
298 12 : }
299 :
300 :
301 0 : Any SAL_CALL FmXGridControlMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
302 : {
303 0 : Any aReturn;
304 0 : aReturn = ::cppu::queryInterface( _rType,
305 : static_cast< XGridControlListener*>(this)
306 0 : );
307 :
308 0 : if (!aReturn.hasValue())
309 0 : aReturn = OWeakSubObject::queryInterface( _rType );
310 :
311 0 : return aReturn;
312 : }
313 :
314 :
315 0 : void FmXGridControlMultiplexer::disposing( const EventObject& ) throw( RuntimeException, std::exception )
316 : {
317 0 : }
318 :
319 :
320 0 : void SAL_CALL FmXGridControlMultiplexer::columnChanged( const EventObject& _event ) throw (RuntimeException, std::exception)
321 : {
322 0 : EventObject aForwardedEvent( _event );
323 0 : aForwardedEvent.Source = &m_rParent;
324 0 : notifyEach( &XGridControlListener::columnChanged, aForwardedEvent );
325 0 : }
326 :
327 :
328 : //= FmXGridControl
329 :
330 :
331 :
332 0 : Reference< XInterface > SAL_CALL FmXGridControl_NewInstance_Impl(const Reference< XMultiServiceFactory>& _rxFactory)
333 : throw (css::uno::Exception)
334 : {
335 0 : return *(new FmXGridControl( comphelper::getComponentContext(_rxFactory) ));
336 : }
337 :
338 12 : FmXGridControl::FmXGridControl(const Reference< XComponentContext >& _rxContext)
339 : :UnoControl()
340 12 : ,m_aModifyListeners(*this, GetMutex())
341 12 : ,m_aUpdateListeners(*this, GetMutex())
342 12 : ,m_aContainerListeners(*this, GetMutex())
343 12 : ,m_aSelectionListeners(*this, GetMutex())
344 12 : ,m_aGridControlListeners(*this, GetMutex())
345 : ,m_nPeerCreationLevel(0)
346 : ,m_bInDraw(false)
347 72 : ,m_xContext(_rxContext)
348 : {
349 12 : }
350 :
351 :
352 12 : FmXGridControl::~FmXGridControl()
353 : {
354 12 : }
355 :
356 :
357 512 : Any SAL_CALL FmXGridControl::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
358 : {
359 512 : Any aReturn = FmXGridControl_BASE::queryInterface(_rType);
360 :
361 512 : if (!aReturn.hasValue())
362 465 : aReturn = UnoControl::queryAggregation( _rType );
363 512 : return aReturn;
364 : }
365 :
366 :
367 0 : Sequence< Type> SAL_CALL FmXGridControl::getTypes( ) throw(RuntimeException, std::exception)
368 : {
369 0 : return comphelper::concatSequences(UnoControl::getTypes(),FmXGridControl_BASE::getTypes());
370 : }
371 :
372 :
373 0 : Sequence<sal_Int8> SAL_CALL FmXGridControl::getImplementationId( ) throw(RuntimeException, std::exception)
374 : {
375 0 : return css::uno::Sequence<sal_Int8>();
376 : }
377 :
378 : // XServiceInfo
379 0 : sal_Bool SAL_CALL FmXGridControl::supportsService(const OUString& ServiceName) throw(std::exception)
380 : {
381 0 : return cppu::supportsService(this, ServiceName);
382 : }
383 :
384 0 : OUString SAL_CALL FmXGridControl::getImplementationName() throw(std::exception)
385 : {
386 0 : return OUString("com.sun.star.form.FmXGridControl");
387 : }
388 :
389 0 : ::comphelper::StringSequence SAL_CALL FmXGridControl::getSupportedServiceNames() throw(std::exception)
390 : {
391 0 : Sequence< OUString > aServiceNames(2);
392 0 : aServiceNames[0] = FM_SUN_CONTROL_GRIDCONTROL;
393 0 : aServiceNames[1] = "com.sun.star.awt.UnoControl";
394 0 : return aServiceNames;
395 : }
396 :
397 :
398 13 : void SAL_CALL FmXGridControl::dispose() throw( RuntimeException, std::exception )
399 : {
400 13 : SolarMutexGuard aGuard;
401 :
402 26 : EventObject aEvt;
403 13 : aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
404 13 : m_aModifyListeners.disposeAndClear(aEvt);
405 13 : m_aUpdateListeners.disposeAndClear(aEvt);
406 13 : m_aContainerListeners.disposeAndClear(aEvt);
407 :
408 26 : UnoControl::dispose();
409 13 : }
410 :
411 :
412 0 : OUString FmXGridControl::GetComponentServiceName()
413 : {
414 0 : OUString aName("DBGrid");
415 0 : return aName;
416 : }
417 :
418 :
419 24 : sal_Bool SAL_CALL FmXGridControl::setModel(const Reference< ::com::sun::star::awt::XControlModel >& rModel) throw( RuntimeException, std::exception )
420 : {
421 24 : SolarMutexGuard aGuard;
422 :
423 24 : if (!UnoControl::setModel(rModel))
424 13 : return sal_False;
425 :
426 22 : Reference< XGridPeer > xGridPeer(getPeer(), UNO_QUERY);
427 11 : if (xGridPeer.is())
428 : {
429 0 : Reference< XIndexContainer > xCols(mxModel, UNO_QUERY);
430 0 : xGridPeer->setColumns(xCols);
431 : }
432 35 : return sal_True;
433 : }
434 :
435 :
436 0 : FmXGridPeer* FmXGridControl::imp_CreatePeer(vcl::Window* pParent)
437 : {
438 0 : FmXGridPeer* pReturn = new FmXGridPeer(m_xContext);
439 :
440 : // translate properties into WinBits
441 0 : WinBits nStyle = WB_TABSTOP;
442 0 : Reference< XPropertySet > xModelSet(getModel(), UNO_QUERY);
443 0 : if (xModelSet.is())
444 : {
445 : try
446 : {
447 0 : if (::comphelper::getINT16(xModelSet->getPropertyValue(FM_PROP_BORDER)))
448 0 : nStyle |= WB_BORDER;
449 : }
450 0 : catch(const Exception&)
451 : {
452 : OSL_FAIL("Can not get style");
453 : }
454 : }
455 :
456 0 : pReturn->Create(pParent, nStyle);
457 0 : return pReturn;
458 : }
459 :
460 :
461 20 : void SAL_CALL FmXGridControl::createPeer(const Reference< ::com::sun::star::awt::XToolkit >& /*rToolkit*/, const Reference< ::com::sun::star::awt::XWindowPeer >& rParentPeer) throw( RuntimeException, std::exception )
462 : {
463 20 : if ( !mxModel.is() )
464 0 : throw DisposedException( OUString(), *this );
465 :
466 : DBG_ASSERT(/*(0 == m_nPeerCreationLevel) && */!mbCreatingPeer, "FmXGridControl::createPeer : recursion!");
467 : // I think this should never assert, now that we're using the base class' mbCreatingPeer in addition to
468 : // our own m_nPeerCreationLevel
469 : // But I'm not sure as I don't _fully_ understand the underlying toolkit implementations ....
470 : // (if this asserts, we still need m_nPeerCreationLevel. If not, we could omit it ....)
471 : // 14.05.2001 - 86836 - frank.schoenheit@germany.sun.com
472 :
473 : // TODO: why the hell this whole class does not use any mutex?
474 :
475 20 : if (!getPeer().is())
476 : {
477 20 : mbCreatingPeer = true;
478 : // mbCreatingPeer is virtually the same as m_nPeerCreationLevel, but it's the base class' method
479 : // to prevent recursion.
480 :
481 20 : vcl::Window* pParentWin = NULL;
482 20 : if (rParentPeer.is())
483 : {
484 20 : VCLXWindow* pParent = VCLXWindow::GetImplementation(rParentPeer);
485 20 : if (pParent)
486 20 : pParentWin = pParent->GetWindow();
487 : }
488 :
489 20 : FmXGridPeer* pPeer = imp_CreatePeer(pParentWin);
490 : DBG_ASSERT(pPeer != NULL, "FmXGridControl::createPeer : imp_CreatePeer didn't return a peer !");
491 20 : setPeer( pPeer );
492 :
493 : // reading the properties from the model
494 : // ++m_nPeerCreationLevel;
495 20 : updateFromModel();
496 :
497 : // consider the following ugly scenario: updateFromModel leads to a propertiesChanges on the Control,
498 : // which determines, dat a "critical" property has changed (e.g. "Border") and therefore starts a new
499 : // Peer, which lands again here in createPeerm we also start a second FmXGridPeer and initialise it.
500 : // Then we exit from the first incarnation's updateFromModel and continue working with the pPeer,
501 : // that is in fact now already obsolete (as another peer is being started in the second incarnation).
502 : // Therefore the effort with the PeerCreationLevel, which ensures that we really use the Peer
503 : // created at the deepest level, but first initialise it in the top-level.
504 : // if (--m_nPeerCreationLevel == 0)
505 : {
506 : DBG_ASSERT(getPeer().is(), "FmXGridControl::createPeer : something went wrong ... no top level peer !");
507 20 : pPeer = FmXGridPeer::getImplementation(getPeer());
508 :
509 20 : setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, ::com::sun::star::awt::PosSize::POSSIZE );
510 :
511 20 : Reference< XIndexContainer > xColumns(getModel(), UNO_QUERY);
512 20 : if (xColumns.is())
513 20 : pPeer->setColumns(xColumns);
514 :
515 20 : if (maComponentInfos.bVisible)
516 20 : pPeer->setVisible(sal_True);
517 :
518 20 : if (!maComponentInfos.bEnable)
519 0 : pPeer->setEnable(sal_False);
520 :
521 20 : if (maWindowListeners.getLength())
522 9 : pPeer->addWindowListener( &maWindowListeners );
523 :
524 20 : if (maFocusListeners.getLength())
525 0 : pPeer->addFocusListener( &maFocusListeners );
526 :
527 20 : if (maKeyListeners.getLength())
528 0 : pPeer->addKeyListener( &maKeyListeners );
529 :
530 20 : if (maMouseListeners.getLength())
531 0 : pPeer->addMouseListener( &maMouseListeners );
532 :
533 20 : if (maMouseMotionListeners.getLength())
534 0 : pPeer->addMouseMotionListener( &maMouseMotionListeners );
535 :
536 20 : if (maPaintListeners.getLength())
537 0 : pPeer->addPaintListener( &maPaintListeners );
538 :
539 20 : if (m_aModifyListeners.getLength())
540 0 : pPeer->addModifyListener( &m_aModifyListeners );
541 :
542 20 : if (m_aUpdateListeners.getLength())
543 0 : pPeer->addUpdateListener( &m_aUpdateListeners );
544 :
545 20 : if (m_aContainerListeners.getLength())
546 0 : pPeer->addContainerListener( &m_aContainerListeners );
547 :
548 : // forward the design mode
549 20 : bool bForceAlivePeer = m_bInDraw && !maComponentInfos.bVisible;
550 : // (we force an alive-mode peer if we're in "draw", cause in this case the peer will be used for drawing in
551 : // foreign devices. We ensure this with the visibility check as an living peer is assumed to be noncritical
552 : // only if invisible)
553 40 : Any aOldCursorBookmark;
554 20 : if (!mbDesignMode || bForceAlivePeer)
555 : {
556 0 : Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
557 0 : if (xComp.is())
558 : {
559 0 : Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY);
560 : // is the form alive?
561 : // we can see that if the form contains columns
562 0 : Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xColumnsSupplier(xForm, UNO_QUERY);
563 0 : if (xColumnsSupplier.is())
564 : {
565 0 : if (Reference< XIndexAccess > (xColumnsSupplier->getColumns(),UNO_QUERY)->getCount())
566 : {
567 : // we get only a new bookmark if the resultset is not forwardonly
568 0 : if (::comphelper::getINT32(Reference< XPropertySet > (xForm, UNO_QUERY)->getPropertyValue(FM_PROP_RESULTSET_TYPE)) != ResultSetType::FORWARD_ONLY)
569 : {
570 : // as the FmGridControl touches the data source it is connected to we have to remember the current
571 : // cursor position (and restore afterwards)
572 : // OJ: but only when we stand on a valid row
573 0 : Reference< XResultSet > xResultSet(xForm, UNO_QUERY);
574 0 : if ( !xResultSet->isBeforeFirst() && !xResultSet->isAfterLast() )
575 : {
576 : try
577 : {
578 0 : aOldCursorBookmark = Reference< ::com::sun::star::sdbcx::XRowLocate > (xForm, UNO_QUERY)->getBookmark();
579 : }
580 0 : catch( const Exception& e )
581 : {
582 : DBG_UNHANDLED_EXCEPTION();
583 : (void)e;
584 : }
585 0 : }
586 : }
587 : }
588 : }
589 0 : pPeer->setRowSet(xForm);
590 0 : }
591 : }
592 20 : pPeer->setDesignMode(mbDesignMode && !bForceAlivePeer);
593 :
594 : try
595 : {
596 20 : if (aOldCursorBookmark.hasValue())
597 : { // we have a valid bookmark, so we have to restore the cursor's position
598 0 : Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
599 0 : Reference< ::com::sun::star::sdbcx::XRowLocate > xLocate(xComp->getParent(), UNO_QUERY);
600 0 : xLocate->moveToBookmark(aOldCursorBookmark);
601 : }
602 : }
603 0 : catch( const Exception& e )
604 : {
605 : DBG_UNHANDLED_EXCEPTION();
606 : (void)e;
607 : }
608 :
609 40 : Reference< ::com::sun::star::awt::XView > xPeerView(getPeer(), UNO_QUERY);
610 20 : xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY );
611 40 : xPeerView->setGraphics( mxGraphics );
612 : }
613 20 : mbCreatingPeer = false;
614 : }
615 20 : }
616 :
617 :
618 1 : void FmXGridControl::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
619 : {
620 1 : m_aModifyListeners.addInterface( l );
621 1 : if( getPeer().is() && m_aModifyListeners.getLength() == 1 )
622 : {
623 1 : Reference< ::com::sun::star::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY);
624 1 : xGrid->addModifyListener( &m_aModifyListeners);
625 : }
626 1 : }
627 :
628 :
629 0 : sal_Bool SAL_CALL FmXGridControl::select( const Any& _rSelection ) throw (IllegalArgumentException, RuntimeException, std::exception)
630 : {
631 0 : SolarMutexGuard aGuard;
632 0 : Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY);
633 0 : return xPeer->select(_rSelection);
634 : }
635 :
636 :
637 0 : Any SAL_CALL FmXGridControl::getSelection( ) throw (RuntimeException, std::exception)
638 : {
639 0 : SolarMutexGuard aGuard;
640 0 : Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY);
641 0 : return xPeer->getSelection();
642 : }
643 :
644 :
645 0 : void SAL_CALL FmXGridControl::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
646 : {
647 0 : m_aSelectionListeners.addInterface( _rxListener );
648 0 : if( getPeer().is() && 1 == m_aSelectionListeners.getLength() )
649 : {
650 0 : Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY);
651 0 : xGrid->addSelectionChangeListener( &m_aSelectionListeners);
652 : }
653 0 : }
654 :
655 :
656 0 : void SAL_CALL FmXGridControl::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
657 : {
658 0 : if( getPeer().is() && 1 == m_aSelectionListeners.getLength() )
659 : {
660 0 : Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY);
661 0 : xGrid->removeSelectionChangeListener( &m_aSelectionListeners);
662 : }
663 0 : m_aSelectionListeners.removeInterface( _rxListener );
664 0 : }
665 :
666 :
667 0 : Sequence< sal_Bool > SAL_CALL FmXGridControl::queryFieldDataType( const Type& xType ) throw(RuntimeException, std::exception)
668 : {
669 0 : if (getPeer().is())
670 : {
671 0 : Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY);
672 0 : if (xPeerSupplier.is())
673 0 : return xPeerSupplier->queryFieldDataType(xType);
674 : }
675 :
676 0 : return Sequence<sal_Bool>();
677 : }
678 :
679 :
680 0 : Sequence< Any > SAL_CALL FmXGridControl::queryFieldData( sal_Int32 nRow, const Type& xType ) throw(RuntimeException, std::exception)
681 : {
682 0 : if (getPeer().is())
683 : {
684 0 : Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY);
685 0 : if (xPeerSupplier.is())
686 0 : return xPeerSupplier->queryFieldData(nRow, xType);
687 : }
688 :
689 0 : return Sequence< Any>();
690 : }
691 :
692 :
693 1 : void SAL_CALL FmXGridControl::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
694 : {
695 1 : if( getPeer().is() && m_aModifyListeners.getLength() == 1 )
696 : {
697 1 : Reference< ::com::sun::star::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY);
698 1 : xGrid->removeModifyListener( &m_aModifyListeners);
699 : }
700 1 : m_aModifyListeners.removeInterface( l );
701 1 : }
702 :
703 :
704 57 : void SAL_CALL FmXGridControl::draw( sal_Int32 x, sal_Int32 y ) throw( RuntimeException, std::exception )
705 : {
706 57 : SolarMutexGuard aGuard;
707 57 : m_bInDraw = true;
708 57 : UnoControl::draw(x, y);
709 57 : m_bInDraw = false;
710 57 : }
711 :
712 :
713 13 : void SAL_CALL FmXGridControl::setDesignMode(sal_Bool bOn) throw( RuntimeException, std::exception )
714 : {
715 13 : ::com::sun::star::util::ModeChangeEvent aModeChangeEvent;
716 :
717 : // --- <mutex_lock> ---
718 : {
719 13 : SolarMutexGuard aGuard;
720 :
721 26 : Reference< XRowSetSupplier > xGrid(getPeer(), UNO_QUERY);
722 :
723 13 : if (xGrid.is() && (bool(bOn) != mbDesignMode || (!bOn && !xGrid->getRowSet().is())))
724 : {
725 1 : if (bOn)
726 : {
727 0 : xGrid->setRowSet(Reference< XRowSet > ());
728 : }
729 : else
730 : {
731 1 : Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
732 1 : if (xComp.is())
733 : {
734 1 : Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY);
735 1 : xGrid->setRowSet(xForm);
736 1 : }
737 : }
738 :
739 1 : mbDesignMode = bOn;
740 :
741 1 : Reference< XVclWindowPeer > xVclWindowPeer( getPeer(), UNO_QUERY );
742 1 : if (xVclWindowPeer.is())
743 1 : xVclWindowPeer->setDesignMode(bOn);
744 : }
745 13 : mbDesignMode = bOn;
746 :
747 : // dispose our current AccessibleContext, if we have one
748 : // (changing the design mode implies having a new implementation for this context,
749 : // so the old one must be declared DEFUNC)
750 : DisposeAccessibleContext(
751 13 : Reference<XComponent>(maAccessibleContext, UNO_QUERY));
752 13 : maAccessibleContext.clear();
753 :
754 : // prepare firing an event
755 13 : aModeChangeEvent.Source = *this;
756 26 : aModeChangeEvent.NewMode = mbDesignMode ? OUString( "design" ) : OUString( "alive" );
757 : }
758 :
759 : // --- </mutex_lock> ---
760 13 : maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
761 13 : }
762 :
763 : // XBoundComponent
764 :
765 0 : void SAL_CALL FmXGridControl::addUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
766 : {
767 0 : m_aUpdateListeners.addInterface( l );
768 0 : if( getPeer().is() && m_aUpdateListeners.getLength() == 1 )
769 : {
770 0 : Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
771 0 : xBound->addUpdateListener( &m_aUpdateListeners);
772 : }
773 0 : }
774 :
775 :
776 0 : void SAL_CALL FmXGridControl::removeUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
777 : {
778 0 : if( getPeer().is() && m_aUpdateListeners.getLength() == 1 )
779 : {
780 0 : Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
781 0 : xBound->removeUpdateListener( &m_aUpdateListeners);
782 : }
783 0 : m_aUpdateListeners.removeInterface( l );
784 0 : }
785 :
786 :
787 0 : sal_Bool SAL_CALL FmXGridControl::commit() throw( RuntimeException, std::exception )
788 : {
789 0 : Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
790 0 : if (xBound.is())
791 0 : return xBound->commit();
792 : else
793 0 : return sal_True;
794 : }
795 :
796 : // XContainer
797 :
798 0 : void SAL_CALL FmXGridControl::addContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
799 : {
800 0 : m_aContainerListeners.addInterface( l );
801 0 : if( getPeer().is() && m_aContainerListeners.getLength() == 1 )
802 : {
803 0 : Reference< XContainer > xContainer(getPeer(), UNO_QUERY);
804 0 : xContainer->addContainerListener( &m_aContainerListeners);
805 : }
806 0 : }
807 :
808 :
809 0 : void SAL_CALL FmXGridControl::removeContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
810 : {
811 0 : if( getPeer().is() && m_aContainerListeners.getLength() == 1 )
812 : {
813 0 : Reference< XContainer > xContainer(getPeer(), UNO_QUERY);
814 0 : xContainer->removeContainerListener( &m_aContainerListeners);
815 : }
816 0 : m_aContainerListeners.removeInterface( l );
817 0 : }
818 :
819 :
820 0 : Reference< ::com::sun::star::frame::XDispatch > SAL_CALL FmXGridControl::queryDispatch(const ::com::sun::star::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException, std::exception )
821 : {
822 0 : Reference< ::com::sun::star::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY);
823 0 : if (xPeerProvider.is())
824 0 : return xPeerProvider->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
825 : else
826 0 : return Reference< ::com::sun::star::frame::XDispatch > ();
827 : }
828 :
829 :
830 0 : Sequence< Reference< ::com::sun::star::frame::XDispatch > > SAL_CALL FmXGridControl::queryDispatches(const Sequence< ::com::sun::star::frame::DispatchDescriptor>& aDescripts) throw( RuntimeException, std::exception )
831 : {
832 0 : Reference< ::com::sun::star::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY);
833 0 : if (xPeerProvider.is())
834 0 : return xPeerProvider->queryDispatches(aDescripts);
835 : else
836 0 : return Sequence< Reference< ::com::sun::star::frame::XDispatch > >();
837 : }
838 :
839 :
840 1 : void SAL_CALL FmXGridControl::registerDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
841 : {
842 1 : Reference< ::com::sun::star::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY);
843 1 : if (xPeerInterception.is())
844 1 : xPeerInterception->registerDispatchProviderInterceptor(_xInterceptor);
845 1 : }
846 :
847 :
848 1 : void SAL_CALL FmXGridControl::releaseDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
849 : {
850 1 : Reference< ::com::sun::star::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY);
851 1 : if (xPeerInterception.is())
852 1 : xPeerInterception->releaseDispatchProviderInterceptor(_xInterceptor);
853 1 : }
854 :
855 :
856 0 : void SAL_CALL FmXGridControl::addGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
857 : {
858 0 : ::osl::MutexGuard aGuard( GetMutex() );
859 :
860 0 : m_aGridControlListeners.addInterface( _listener );
861 0 : if ( getPeer().is() && 1 == m_aGridControlListeners.getLength() )
862 : {
863 0 : Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY );
864 0 : if ( xPeerGrid.is() )
865 0 : xPeerGrid->addGridControlListener( &m_aGridControlListeners );
866 0 : }
867 0 : }
868 :
869 :
870 0 : void SAL_CALL FmXGridControl::removeGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
871 : {
872 0 : ::osl::MutexGuard aGuard( GetMutex() );
873 :
874 0 : if( getPeer().is() && 1 == m_aGridControlListeners.getLength() )
875 : {
876 0 : Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY );
877 0 : if ( xPeerGrid.is() )
878 0 : xPeerGrid->removeGridControlListener( &m_aGridControlListeners );
879 : }
880 :
881 0 : m_aGridControlListeners.removeInterface( _listener );
882 0 : }
883 :
884 :
885 15 : sal_Int16 SAL_CALL FmXGridControl::getCurrentColumnPosition() throw( RuntimeException, std::exception )
886 : {
887 15 : Reference< XGridControl > xGrid( getPeer(), UNO_QUERY );
888 15 : return xGrid.is() ? xGrid->getCurrentColumnPosition() : -1;
889 : }
890 :
891 :
892 0 : void SAL_CALL FmXGridControl::setCurrentColumnPosition(sal_Int16 nPos) throw( RuntimeException, std::exception )
893 : {
894 0 : Reference< XGridControl > xGrid( getPeer(), UNO_QUERY );
895 0 : if ( xGrid.is() )
896 : {
897 0 : SolarMutexGuard aGuard;
898 0 : xGrid->setCurrentColumnPosition( nPos );
899 0 : }
900 0 : }
901 :
902 : // XElementAccess
903 :
904 0 : sal_Bool SAL_CALL FmXGridControl::hasElements() throw( RuntimeException, std::exception )
905 : {
906 0 : Reference< XElementAccess > xPeer(getPeer(), UNO_QUERY);
907 0 : return xPeer.is() && xPeer->hasElements();
908 : }
909 :
910 :
911 0 : Type SAL_CALL FmXGridControl::getElementType( ) throw(RuntimeException, std::exception)
912 : {
913 0 : return cppu::UnoType<com::sun::star::awt::XTextComponent>::get();
914 : }
915 :
916 : // XEnumerationAccess
917 :
918 0 : Reference< XEnumeration > SAL_CALL FmXGridControl::createEnumeration() throw( RuntimeException, std::exception )
919 : {
920 0 : Reference< XEnumerationAccess > xPeer(getPeer(), UNO_QUERY);
921 0 : if (xPeer.is())
922 0 : return xPeer->createEnumeration();
923 : else
924 0 : return new ::comphelper::OEnumerationByIndex(this);
925 : }
926 :
927 : // XIndexAccess
928 :
929 0 : sal_Int32 SAL_CALL FmXGridControl::getCount() throw( RuntimeException, std::exception )
930 : {
931 0 : Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY);
932 0 : return xPeer.is() ? xPeer->getCount() : 0;
933 : }
934 :
935 :
936 0 : Any SAL_CALL FmXGridControl::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
937 : {
938 0 : Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY);
939 0 : if (!xPeer.is())
940 0 : throw IndexOutOfBoundsException();
941 :
942 0 : return xPeer->getByIndex(_nIndex);
943 : }
944 :
945 : // ::com::sun::star::util::XModeSelector
946 :
947 0 : void SAL_CALL FmXGridControl::setMode(const OUString& Mode) throw( NoSupportException, RuntimeException, std::exception )
948 : {
949 0 : Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
950 0 : if (!xPeer.is())
951 0 : throw NoSupportException();
952 :
953 0 : xPeer->setMode(Mode);
954 0 : }
955 :
956 :
957 0 : OUString SAL_CALL FmXGridControl::getMode() throw( RuntimeException, std::exception )
958 : {
959 0 : Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
960 0 : return xPeer.is() ? xPeer->getMode() : OUString();
961 : }
962 :
963 :
964 0 : ::comphelper::StringSequence SAL_CALL FmXGridControl::getSupportedModes() throw( RuntimeException, std::exception )
965 : {
966 0 : Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
967 0 : return xPeer.is() ? xPeer->getSupportedModes() : ::comphelper::StringSequence();
968 : }
969 :
970 :
971 0 : sal_Bool SAL_CALL FmXGridControl::supportsMode(const OUString& Mode) throw( RuntimeException, std::exception )
972 : {
973 0 : Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
974 0 : return xPeer.is() ? xPeer->supportsMode(Mode) : sal_False;
975 : }
976 :
977 : // helper class which prevents that in the peer's header the FmGridListener must be known
978 : class FmXGridPeer::GridListenerDelegator : public FmGridListener
979 : {
980 : protected:
981 : FmXGridPeer* m_pPeer;
982 :
983 : public:
984 : explicit GridListenerDelegator( FmXGridPeer* _pPeer );
985 : virtual ~GridListenerDelegator();
986 :
987 : protected:
988 : virtual void selectionChanged() SAL_OVERRIDE;
989 : virtual void columnChanged() SAL_OVERRIDE;
990 : };
991 :
992 :
993 20 : FmXGridPeer::GridListenerDelegator::GridListenerDelegator(FmXGridPeer* _pPeer)
994 20 : :m_pPeer(_pPeer)
995 : {
996 : DBG_ASSERT(m_pPeer, "GridListenerDelegator::GridListenerDelegator");
997 20 : }
998 :
999 40 : FmXGridPeer::GridListenerDelegator::~GridListenerDelegator()
1000 : {
1001 40 : }
1002 :
1003 :
1004 0 : void FmXGridPeer::GridListenerDelegator::selectionChanged()
1005 : {
1006 0 : m_pPeer->selectionChanged();
1007 0 : }
1008 :
1009 :
1010 0 : void FmXGridPeer::GridListenerDelegator::columnChanged()
1011 : {
1012 0 : m_pPeer->columnChanged();
1013 0 : }
1014 :
1015 0 : void FmXGridPeer::selectionChanged()
1016 : {
1017 0 : EventObject aSource;
1018 0 : aSource.Source = static_cast< ::cppu::OWeakObject* >(this);
1019 0 : m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aSource);
1020 0 : }
1021 :
1022 :
1023 0 : void FmXGridPeer::columnChanged()
1024 : {
1025 0 : EventObject aEvent( *this );
1026 0 : m_aGridControlListeners.notifyEach( &XGridControlListener::columnChanged, aEvent );
1027 0 : }
1028 :
1029 :
1030 : namespace fmgridif
1031 : {
1032 20 : const OUString getDataModeIdentifier()
1033 : {
1034 20 : return OUString("DataMode");
1035 : }
1036 : }
1037 : using namespace fmgridif;
1038 :
1039 :
1040 20 : FmXGridPeer::FmXGridPeer(const Reference< XComponentContext >& _rxContext)
1041 : :m_aModifyListeners(m_aMutex)
1042 : ,m_aUpdateListeners(m_aMutex)
1043 : ,m_aContainerListeners(m_aMutex)
1044 : ,m_aSelectionListeners(m_aMutex)
1045 : ,m_aGridControlListeners(m_aMutex)
1046 : ,m_aMode( getDataModeIdentifier() )
1047 : ,m_nCursorListening(0)
1048 : ,m_bInterceptingDispatch(false)
1049 : ,m_pStateCache(NULL)
1050 : ,m_pDispatchers(NULL)
1051 : ,m_pGridListener(NULL)
1052 20 : ,m_xContext(_rxContext)
1053 : {
1054 : // Create must be called after this constructure
1055 20 : m_pGridListener = new GridListenerDelegator( this );
1056 20 : }
1057 :
1058 :
1059 0 : VclPtr<FmGridControl> FmXGridPeer::imp_CreateControl(vcl::Window* pParent, WinBits nStyle)
1060 : {
1061 0 : return VclPtr<FmGridControl>::Create(m_xContext, pParent, this, nStyle);
1062 : }
1063 :
1064 :
1065 20 : void FmXGridPeer::Create(vcl::Window* pParent, WinBits nStyle)
1066 : {
1067 20 : FmGridControl* pWin = imp_CreateControl(pParent, nStyle);
1068 : DBG_ASSERT(pWin != NULL, "FmXGridPeer::Create : imp_CreateControl didn't return a control !");
1069 :
1070 20 : pWin->SetStateProvider(LINK(this, FmXGridPeer, OnQueryGridSlotState));
1071 20 : pWin->SetSlotExecutor(LINK(this, FmXGridPeer, OnExecuteGridSlot));
1072 :
1073 : // want to hear about row selections
1074 20 : pWin->setGridListener( m_pGridListener );
1075 :
1076 : // Init must always be called
1077 20 : pWin->Init();
1078 20 : pWin->SetComponentInterface(this);
1079 :
1080 20 : getSupportedURLs();
1081 20 : }
1082 :
1083 :
1084 40 : FmXGridPeer::~FmXGridPeer()
1085 : {
1086 20 : setRowSet(Reference< XRowSet > ());
1087 20 : setColumns(Reference< XIndexContainer > ());
1088 :
1089 20 : delete m_pGridListener;
1090 20 : }
1091 :
1092 : namespace
1093 : {
1094 : class theFmXGridPeerImplementationId : public rtl::Static< UnoTunnelIdInit, theFmXGridPeerImplementationId > {};
1095 : }
1096 :
1097 253 : const Sequence< sal_Int8 >& FmXGridPeer::getUnoTunnelImplementationId() throw()
1098 : {
1099 253 : return theFmXGridPeerImplementationId::get().getSeq();
1100 : }
1101 :
1102 :
1103 20 : FmXGridPeer* FmXGridPeer::getImplementation( const Reference< XInterface >& _rxIFace ) throw()
1104 : {
1105 20 : FmXGridPeer* pReturn = NULL;
1106 20 : Reference< XUnoTunnel > xTunnel(_rxIFace, UNO_QUERY);
1107 20 : if (xTunnel.is())
1108 20 : pReturn = reinterpret_cast<FmXGridPeer*>(xTunnel->getSomething(getUnoTunnelImplementationId()));
1109 :
1110 20 : return pReturn;
1111 : }
1112 :
1113 :
1114 233 : sal_Int64 SAL_CALL FmXGridPeer::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException, std::exception)
1115 : {
1116 233 : sal_Int64 nReturn(0);
1117 :
1118 466 : if ( (_rIdentifier.getLength() == 16)
1119 233 : && (0 == memcmp( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ))
1120 : )
1121 : {
1122 20 : nReturn = reinterpret_cast<sal_Int64>(this);
1123 : }
1124 : else
1125 213 : nReturn = VCLXWindow::getSomething(_rIdentifier);
1126 :
1127 233 : return nReturn;
1128 : }
1129 :
1130 : // XEventListener
1131 :
1132 137 : void FmXGridPeer::disposing(const EventObject& e) throw( RuntimeException, std::exception )
1133 : {
1134 : using namespace ::com::sun::star::util;
1135 137 : bool bKnownSender = false;
1136 :
1137 137 : Reference< XIndexContainer > xCols( e.Source, UNO_QUERY );
1138 137 : if ( xCols.is() )
1139 : {
1140 24 : setColumns(Reference< XIndexContainer > ());
1141 24 : bKnownSender = true;
1142 : }
1143 :
1144 274 : Reference< XRowSet > xCursor(e.Source, UNO_QUERY);
1145 137 : if (xCursor.is())
1146 : {
1147 5 : setRowSet( m_xCursor );
1148 5 : m_xCursor = NULL;
1149 5 : bKnownSender = true;
1150 : }
1151 :
1152 :
1153 137 : if ( !bKnownSender && m_pDispatchers )
1154 : {
1155 1 : const Sequence< URL>& aSupportedURLs = getSupportedURLs();
1156 1 : const URL* pSupportedURLs = aSupportedURLs.getConstArray();
1157 7 : for ( sal_uInt16 i=0; i < ( aSupportedURLs.getLength() ) && !bKnownSender; ++i, ++pSupportedURLs )
1158 : {
1159 6 : if ( m_pDispatchers[i] == e.Source )
1160 : {
1161 1 : m_pDispatchers[i]->removeStatusListener( static_cast< ::com::sun::star::frame::XStatusListener* >( this ), *pSupportedURLs );
1162 1 : m_pDispatchers[i] = NULL;
1163 1 : m_pStateCache[i] = false;
1164 1 : bKnownSender = true;
1165 : }
1166 : }
1167 : }
1168 :
1169 137 : if ( !bKnownSender )
1170 249 : VCLXWindow::disposing(e);
1171 137 : }
1172 :
1173 :
1174 1 : void FmXGridPeer::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
1175 : {
1176 1 : m_aModifyListeners.addInterface( l );
1177 1 : }
1178 :
1179 :
1180 1 : void FmXGridPeer::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
1181 : {
1182 1 : m_aModifyListeners.removeInterface( l );
1183 1 : }
1184 :
1185 :
1186 : #define LAST_KNOWN_TYPE FormComponentType::PATTERNFIELD
1187 0 : Sequence< sal_Bool > SAL_CALL FmXGridPeer::queryFieldDataType( const Type& xType ) throw(RuntimeException, std::exception)
1188 : {
1189 : // eine 'Konvertierungstabelle'
1190 : static const sal_Bool bCanConvert[LAST_KNOWN_TYPE][4] =
1191 : {
1192 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::CONTROL
1193 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::COMMANDBUTTON
1194 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::RADIOBUTTON
1195 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::IMAGEBUTTON
1196 : { sal_False, sal_False, sal_False, sal_True }, // FormComponentType::CHECKBOX
1197 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::LISTBOX
1198 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::COMBOBOX
1199 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::GROUPBOX
1200 : { sal_True , sal_False, sal_False, sal_False }, // FormComponentType::TEXTFIELD
1201 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::FIXEDTEXT
1202 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::GRIDCONTROL
1203 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::FILECONTROL
1204 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::HIDDENCONTROL
1205 : { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::IMAGECONTROL
1206 : { sal_True , sal_True , sal_True , sal_False }, // FormComponentType::DATEFIELD
1207 : { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::TIMEFIELD
1208 : { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::NUMERICFIELD
1209 : { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::CURRENCYFIELD
1210 : { sal_True , sal_False, sal_False, sal_False } // FormComponentType::PATTERNFIELD
1211 : };
1212 :
1213 :
1214 0 : sal_Int16 nMapColumn = -1;
1215 0 : switch (xType.getTypeClass())
1216 : {
1217 0 : case TypeClass_STRING : nMapColumn = 0; break;
1218 : case TypeClass_FLOAT:
1219 0 : case TypeClass_DOUBLE : nMapColumn = 1; break;
1220 : case TypeClass_SHORT:
1221 : case TypeClass_LONG:
1222 : case TypeClass_UNSIGNED_LONG:
1223 0 : case TypeClass_UNSIGNED_SHORT : nMapColumn = 2; break;
1224 0 : case TypeClass_BOOLEAN : nMapColumn = 3; break;
1225 : default:
1226 0 : break;
1227 : }
1228 :
1229 0 : Reference< XIndexContainer > xColumns = getColumns();
1230 :
1231 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1232 0 : sal_Int32 nColumns = pGrid->GetViewColCount();
1233 :
1234 0 : DbGridColumns aColumns = pGrid->GetColumns();
1235 :
1236 0 : Sequence<sal_Bool> aReturnSequence(nColumns);
1237 0 : sal_Bool* pReturnArray = aReturnSequence.getArray();
1238 :
1239 0 : bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY);
1240 :
1241 : DbGridColumn* pCol;
1242 0 : Reference< ::com::sun::star::sdb::XColumn > xFieldContent;
1243 0 : Reference< XPropertySet > xCurrentColumn;
1244 0 : for (sal_Int32 i=0; i<nColumns; ++i)
1245 : {
1246 0 : if (bRequestedAsAny)
1247 : {
1248 0 : pReturnArray[i] = sal_True;
1249 0 : continue;
1250 : }
1251 :
1252 0 : pReturnArray[i] = sal_False;
1253 :
1254 0 : sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i));
1255 : DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldDataType : no model pos !");
1256 :
1257 0 : pCol = aColumns[ nModelPos ];
1258 0 : const DbGridRowRef xRow = pGrid->GetSeekRow();
1259 0 : xFieldContent = (xRow.Is() && xRow->HasField(pCol->GetFieldPos())) ? xRow->GetField(pCol->GetFieldPos()).getColumn() : Reference< ::com::sun::star::sdb::XColumn > ();
1260 0 : if (!xFieldContent.is())
1261 : // can't supply anything without a field content
1262 : // FS - 07.12.99 - 54391
1263 0 : continue;
1264 :
1265 0 : xColumns->getByIndex(nModelPos) >>= xCurrentColumn;
1266 0 : if (!::comphelper::hasProperty(FM_PROP_CLASSID, xCurrentColumn))
1267 0 : continue;
1268 :
1269 0 : sal_Int16 nClassId = sal_Int16();
1270 0 : xCurrentColumn->getPropertyValue(FM_PROP_CLASSID) >>= nClassId;
1271 0 : if (nClassId>LAST_KNOWN_TYPE)
1272 0 : continue;
1273 : DBG_ASSERT(nClassId>0, "FmXGridPeer::queryFieldDataType : somebody changed the definition of the FormComponentType enum !");
1274 :
1275 0 : if (nMapColumn != -1)
1276 0 : pReturnArray[i] = bCanConvert[nClassId-1][nMapColumn];
1277 0 : }
1278 :
1279 0 : return aReturnSequence;
1280 : }
1281 :
1282 :
1283 0 : Sequence< Any > SAL_CALL FmXGridPeer::queryFieldData( sal_Int32 nRow, const Type& xType ) throw(RuntimeException, std::exception)
1284 : {
1285 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1286 : DBG_ASSERT(pGrid && pGrid->IsOpen(), "FmXGridPeer::queryFieldData : have no valid grid window !");
1287 0 : if (!pGrid || !pGrid->IsOpen())
1288 0 : return Sequence< Any>();
1289 :
1290 : // das Control zur angegebenen Row fahren
1291 0 : if (!pGrid->SeekRow(nRow))
1292 : {
1293 0 : throw IllegalArgumentException();
1294 : }
1295 :
1296 : // don't use GetCurrentRow as this isn't affected by the above SeekRow
1297 : // FS - 30.09.99 - 68644
1298 0 : DbGridRowRef xPaintRow = pGrid->GetPaintRow();
1299 0 : ENSURE_OR_THROW( xPaintRow.Is(), "invalid paint row" );
1300 :
1301 : // I need the columns of the control for GetFieldText
1302 0 : DbGridColumns aColumns = pGrid->GetColumns();
1303 :
1304 : // und durch alle Spalten durch
1305 0 : sal_Int32 nColumnCount = pGrid->GetViewColCount();
1306 :
1307 0 : Sequence< Any> aReturnSequence(nColumnCount);
1308 0 : Any* pReturnArray = aReturnSequence.getArray();
1309 :
1310 0 : bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY);
1311 0 : Reference< ::com::sun::star::sdb::XColumn > xFieldContent;
1312 0 : for (sal_Int32 i=0; i < nColumnCount; ++i)
1313 : {
1314 0 : sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i));
1315 : DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldData : invalid model pos !");
1316 :
1317 : // don't use GetCurrentFieldValue to determine the field content as this isn't affected by the above SeekRow
1318 : // FS - 30.09.99 - 68644
1319 0 : DbGridColumn* pCol = aColumns[ nModelPos ];
1320 0 : xFieldContent = xPaintRow->HasField( pCol->GetFieldPos() )
1321 0 : ? xPaintRow->GetField( pCol->GetFieldPos() ).getColumn()
1322 0 : : Reference< XColumn > ();
1323 :
1324 0 : if ( !xFieldContent.is() )
1325 0 : continue;
1326 :
1327 0 : if (bRequestedAsAny)
1328 : {
1329 0 : Reference< XPropertySet > xFieldSet(xFieldContent, UNO_QUERY);
1330 0 : pReturnArray[i] = xFieldSet->getPropertyValue(FM_PROP_VALUE);
1331 : }
1332 : else
1333 : {
1334 0 : switch (xType.getTypeClass())
1335 : {
1336 : // Strings are dealt with directly by the GetFieldText
1337 : case TypeClass_STRING :
1338 : {
1339 0 : OUString sText = aColumns[ nModelPos ]->GetCellText( xPaintRow, pGrid->getNumberFormatter() );
1340 0 : pReturnArray[i] <<= sText;
1341 : }
1342 0 : break;
1343 : // everything else is requested in the DatabaseVariant
1344 0 : case TypeClass_FLOAT : pReturnArray[i] <<= xFieldContent->getFloat(); break;
1345 0 : case TypeClass_DOUBLE : pReturnArray[i] <<= xFieldContent->getDouble(); break;
1346 0 : case TypeClass_SHORT : pReturnArray[i] <<= (sal_Int16)xFieldContent->getShort(); break;
1347 0 : case TypeClass_LONG : pReturnArray[i] <<= (sal_Int32)xFieldContent->getLong(); break;
1348 0 : case TypeClass_UNSIGNED_SHORT : pReturnArray[i] <<= (sal_uInt16)xFieldContent->getShort(); break;
1349 0 : case TypeClass_UNSIGNED_LONG : pReturnArray[i] <<= (sal_uInt32)xFieldContent->getLong(); break;
1350 0 : case TypeClass_BOOLEAN : ::comphelper::setBOOL(pReturnArray[i],xFieldContent->getBoolean()); break;
1351 : default:
1352 : {
1353 0 : throw IllegalArgumentException();
1354 : }
1355 : }
1356 : }
1357 : }
1358 0 : return aReturnSequence;
1359 : }
1360 :
1361 :
1362 0 : void FmXGridPeer::CellModified()
1363 : {
1364 0 : EventObject aEvt;
1365 0 : aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
1366 0 : m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
1367 0 : }
1368 :
1369 : // XPropertyChangeListener
1370 :
1371 0 : void FmXGridPeer::propertyChange(const PropertyChangeEvent& evt) throw( RuntimeException, std::exception )
1372 : {
1373 0 : SolarMutexGuard aGuard;
1374 : // want to do a lot of VCL stuff here ...
1375 : // this should not be (deadlock) critical, as by definition, every component should release
1376 : // any own mutexes before notifying
1377 :
1378 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1379 0 : if (!pGrid)
1380 0 : return;
1381 :
1382 : // Database event
1383 0 : Reference< XRowSet > xCursor(evt.Source, UNO_QUERY);
1384 0 : if (evt.PropertyName == FM_PROP_VALUE || m_xCursor == evt.Source)
1385 0 : pGrid->propertyChange(evt);
1386 0 : else if (pGrid && m_xColumns.is() && m_xColumns->hasElements())
1387 : {
1388 : // next find which column has changed
1389 0 : ::comphelper::InterfaceRef xCurrent;
1390 : sal_Int32 i;
1391 :
1392 0 : for ( i = 0; i < m_xColumns->getCount(); i++)
1393 : {
1394 0 : xCurrent.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
1395 0 : if (evt.Source == xCurrent)
1396 0 : break;
1397 : }
1398 :
1399 0 : if (i >= m_xColumns->getCount())
1400 : // this is valid because we are listening at the cursor, too (RecordCount, -status, edit mode)
1401 0 : return;
1402 :
1403 0 : sal_uInt16 nId = pGrid->GetColumnIdFromModelPos((sal_uInt16)i);
1404 0 : bool bInvalidateColumn = false;
1405 :
1406 0 : if (evt.PropertyName == FM_PROP_LABEL)
1407 : {
1408 0 : OUString aName = ::comphelper::getString(evt.NewValue);
1409 0 : if (aName != pGrid->GetColumnTitle(nId))
1410 0 : pGrid->SetColumnTitle(nId, aName);
1411 : }
1412 0 : else if (evt.PropertyName == FM_PROP_WIDTH)
1413 : {
1414 0 : sal_Int32 nWidth = 0;
1415 0 : if (evt.NewValue.getValueType().getTypeClass() == TypeClass_VOID)
1416 0 : nWidth = pGrid->GetDefaultColumnWidth(pGrid->GetColumnTitle(nId));
1417 : // GetDefaultColumnWidth already considered the zoom factor
1418 : else
1419 : {
1420 0 : sal_Int32 nTest = 0;
1421 0 : if (evt.NewValue >>= nTest)
1422 : {
1423 0 : nWidth = pGrid->LogicToPixel(Point(nTest,0),MAP_10TH_MM).X();
1424 : // take the zoom factor into account
1425 0 : nWidth = pGrid->CalcZoom(nWidth);
1426 : }
1427 : }
1428 0 : if (nWidth != (sal_Int32(pGrid->GetColumnWidth(nId))))
1429 : {
1430 0 : if (pGrid->IsEditing())
1431 : {
1432 0 : pGrid->DeactivateCell();
1433 0 : pGrid->ActivateCell();
1434 : }
1435 0 : pGrid->SetColumnWidth(nId, nWidth);
1436 : }
1437 : }
1438 0 : else if (evt.PropertyName == FM_PROP_HIDDEN)
1439 : {
1440 : DBG_ASSERT(evt.NewValue.getValueType().getTypeClass() == TypeClass_BOOLEAN,
1441 : "FmXGridPeer::propertyChange : the property 'hidden' should be of type boolean !");
1442 0 : if (::comphelper::getBOOL(evt.NewValue))
1443 0 : pGrid->HideColumn(nId);
1444 : else
1445 0 : pGrid->ShowColumn(nId);
1446 : }
1447 0 : else if (evt.PropertyName == FM_PROP_ALIGN)
1448 : {
1449 : // in design mode it doesn't matter
1450 0 : if (!isDesignMode())
1451 : {
1452 0 : DbGridColumn* pCol = pGrid->GetColumns().at( i );
1453 :
1454 0 : pCol->SetAlignmentFromModel(-1);
1455 0 : bInvalidateColumn = true;
1456 : }
1457 : }
1458 0 : else if (evt.PropertyName == FM_PROP_FORMATKEY)
1459 : {
1460 0 : if (!isDesignMode())
1461 0 : bInvalidateColumn = true;
1462 : }
1463 :
1464 : // need to invalidate the affected column ?
1465 0 : if (bInvalidateColumn)
1466 : {
1467 0 : bool bWasEditing = pGrid->IsEditing();
1468 0 : if (bWasEditing)
1469 0 : pGrid->DeactivateCell();
1470 :
1471 0 : ::Rectangle aColRect = pGrid->GetFieldRect(nId);
1472 0 : aColRect.Top() = 0;
1473 0 : aColRect.Bottom() = pGrid->GetSizePixel().Height();
1474 0 : pGrid->Invalidate(aColRect);
1475 :
1476 0 : if (bWasEditing)
1477 0 : pGrid->ActivateCell();
1478 0 : }
1479 0 : }
1480 : }
1481 :
1482 : // XBoundComponent
1483 :
1484 0 : void FmXGridPeer::addUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
1485 : {
1486 0 : m_aUpdateListeners.addInterface(l);
1487 0 : }
1488 :
1489 :
1490 0 : void FmXGridPeer::removeUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
1491 : {
1492 0 : m_aUpdateListeners.removeInterface(l);
1493 0 : }
1494 :
1495 :
1496 0 : sal_Bool FmXGridPeer::commit() throw( RuntimeException, std::exception )
1497 : {
1498 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1499 0 : if (!m_xCursor.is() || !pGrid)
1500 0 : return sal_True;
1501 :
1502 0 : EventObject aEvt(static_cast< ::cppu::OWeakObject* >(this));
1503 0 : ::cppu::OInterfaceIteratorHelper aIter(m_aUpdateListeners);
1504 0 : bool bCancel = false;
1505 0 : while (aIter.hasMoreElements() && !bCancel)
1506 0 : if ( !static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvt ) )
1507 0 : bCancel = true;
1508 :
1509 0 : if (!bCancel)
1510 0 : bCancel = !pGrid->commit();
1511 :
1512 0 : if (!bCancel)
1513 0 : m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvt );
1514 0 : return !bCancel;
1515 : }
1516 :
1517 :
1518 :
1519 0 : void FmXGridPeer::cursorMoved(const EventObject& _rEvent) throw( RuntimeException, std::exception )
1520 : {
1521 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1522 : // we are not interested in move to insert row only in the resetted event
1523 : // which is fired after positioning an the insert row
1524 0 : if (pGrid && pGrid->IsOpen() && !::comphelper::getBOOL(Reference< XPropertySet > (_rEvent.Source, UNO_QUERY)->getPropertyValue(FM_PROP_ISNEW)))
1525 0 : pGrid->positioned(_rEvent);
1526 0 : }
1527 :
1528 :
1529 0 : void FmXGridPeer::rowChanged(const EventObject& _rEvent) throw( RuntimeException, std::exception )
1530 : {
1531 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1532 0 : if (pGrid && pGrid->IsOpen())
1533 : {
1534 0 : if (m_xCursor->rowUpdated() && !pGrid->IsCurrentAppending())
1535 0 : pGrid->RowModified(pGrid->GetCurrentPos());
1536 0 : else if (m_xCursor->rowInserted())
1537 0 : pGrid->inserted(_rEvent);
1538 0 : }
1539 0 : }
1540 :
1541 :
1542 0 : void FmXGridPeer::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException, std::exception )
1543 : {
1544 : // not interested in ...
1545 : // (our parent is a form which means we get a loaded or reloaded after this rowSetChanged)
1546 0 : }
1547 :
1548 : // XLoadListener
1549 :
1550 0 : void FmXGridPeer::loaded(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
1551 : {
1552 0 : updateGrid(m_xCursor);
1553 0 : }
1554 :
1555 :
1556 1 : void FmXGridPeer::unloaded(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
1557 : {
1558 1 : updateGrid( Reference< XRowSet > (NULL) );
1559 1 : }
1560 :
1561 :
1562 0 : void FmXGridPeer::reloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
1563 : {
1564 : // empty the grid
1565 0 : updateGrid( Reference< XRowSet > (NULL) );
1566 0 : }
1567 :
1568 :
1569 1 : void FmXGridPeer::unloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
1570 : {
1571 : // empty the grid
1572 1 : updateGrid( Reference< XRowSet > (NULL) );
1573 1 : }
1574 :
1575 :
1576 0 : void FmXGridPeer::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
1577 : {
1578 0 : updateGrid(m_xCursor);
1579 0 : }
1580 :
1581 : // XGridPeer
1582 :
1583 67 : Reference< XIndexContainer > FmXGridPeer::getColumns() throw( RuntimeException, std::exception )
1584 : {
1585 67 : return m_xColumns;
1586 : }
1587 :
1588 :
1589 69 : void FmXGridPeer::addColumnListeners(const Reference< XPropertySet >& xCol)
1590 : {
1591 : static const OUString aPropsListenedTo[] =
1592 : {
1593 : OUString(FM_PROP_LABEL), OUString(FM_PROP_WIDTH), OUString(FM_PROP_HIDDEN), OUString(FM_PROP_ALIGN), OUString(FM_PROP_FORMATKEY)
1594 71 : };
1595 :
1596 : // as not all properties have to be supported by all columns we have to check this
1597 : // before adding a listener
1598 69 : Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo();
1599 138 : Property aPropDesc;
1600 69 : const OUString* pProps = aPropsListenedTo;
1601 69 : const OUString* pPropsEnd = pProps + sizeof( aPropsListenedTo ) / sizeof( aPropsListenedTo[ 0 ] );
1602 414 : for (; pProps != pPropsEnd; ++pProps)
1603 : {
1604 345 : if ( xInfo->hasPropertyByName( *pProps ) )
1605 : {
1606 305 : aPropDesc = xInfo->getPropertyByName( *pProps );
1607 305 : if ( 0 != ( aPropDesc.Attributes & PropertyAttribute::BOUND ) )
1608 290 : xCol->addPropertyChangeListener( *pProps, this );
1609 : }
1610 69 : }
1611 69 : }
1612 :
1613 :
1614 41 : void FmXGridPeer::removeColumnListeners(const Reference< XPropertySet >& xCol)
1615 : {
1616 : // the same props as in addColumnListeners ... linux has problems with global static UStrings, so
1617 : // we have to do it this way ....
1618 : static OUString aPropsListenedTo[] =
1619 : {
1620 : OUString(FM_PROP_LABEL), OUString(FM_PROP_WIDTH), OUString(FM_PROP_HIDDEN), OUString(FM_PROP_ALIGN), OUString(FM_PROP_FORMATKEY)
1621 43 : };
1622 :
1623 41 : Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo();
1624 246 : for (sal_uInt16 i=0; i<sizeof(aPropsListenedTo)/sizeof(aPropsListenedTo[0]); ++i)
1625 205 : if (xInfo->hasPropertyByName(aPropsListenedTo[i]))
1626 220 : xCol->removePropertyChangeListener(aPropsListenedTo[i], this);
1627 41 : }
1628 :
1629 :
1630 64 : void FmXGridPeer::setColumns(const Reference< XIndexContainer >& Columns) throw( RuntimeException, std::exception )
1631 : {
1632 64 : SolarMutexGuard aGuard;
1633 :
1634 128 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1635 :
1636 64 : if (m_xColumns.is())
1637 : {
1638 20 : Reference< XPropertySet > xCol;
1639 51 : for (sal_Int32 i = 0; i < m_xColumns->getCount(); i++)
1640 : {
1641 31 : xCol.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
1642 31 : removeColumnListeners(xCol);
1643 : }
1644 40 : Reference< XContainer > xContainer(m_xColumns, UNO_QUERY);
1645 20 : xContainer->removeContainerListener(this);
1646 :
1647 40 : Reference< XSelectionSupplier > xSelSupplier(m_xColumns, UNO_QUERY);
1648 20 : xSelSupplier->removeSelectionChangeListener(this);
1649 :
1650 40 : Reference< XReset > xColumnReset(m_xColumns, UNO_QUERY);
1651 20 : if (xColumnReset.is())
1652 40 : xColumnReset->removeResetListener(static_cast<XResetListener*>(this));
1653 : }
1654 64 : if (Columns.is())
1655 : {
1656 20 : Reference< XContainer > xContainer(Columns, UNO_QUERY);
1657 20 : xContainer->addContainerListener(this);
1658 :
1659 40 : Reference< XSelectionSupplier > xSelSupplier(Columns, UNO_QUERY);
1660 20 : xSelSupplier->addSelectionChangeListener(this);
1661 :
1662 40 : Reference< XPropertySet > xCol;
1663 38 : for (sal_Int32 i = 0; i < Columns->getCount(); i++)
1664 : {
1665 18 : xCol.set(Columns->getByIndex(i), css::uno::UNO_QUERY);
1666 18 : addColumnListeners(xCol);
1667 : }
1668 :
1669 40 : Reference< XReset > xColumnReset(Columns, UNO_QUERY);
1670 20 : if (xColumnReset.is())
1671 40 : xColumnReset->addResetListener(static_cast<XResetListener*>(this));
1672 : }
1673 64 : m_xColumns = Columns;
1674 64 : if (pGrid)
1675 : {
1676 22 : pGrid->InitColumnsByModels(m_xColumns);
1677 :
1678 22 : if (m_xColumns.is())
1679 : {
1680 20 : EventObject aEvt(m_xColumns);
1681 20 : selectionChanged(aEvt);
1682 : }
1683 64 : }
1684 64 : }
1685 :
1686 :
1687 78 : void FmXGridPeer::setDesignMode(sal_Bool bOn) throw( RuntimeException, std::exception )
1688 : {
1689 78 : if (bOn != isDesignMode())
1690 : {
1691 21 : vcl::Window* pWin = GetWindow();
1692 21 : if (pWin)
1693 21 : static_cast<FmGridControl*>(pWin)->SetDesignMode(bOn);
1694 : }
1695 :
1696 78 : if (bOn)
1697 77 : DisConnectFromDispatcher();
1698 : else
1699 1 : UpdateDispatches(); // will connect if not already connected and just update else
1700 78 : }
1701 :
1702 :
1703 232 : sal_Bool FmXGridPeer::isDesignMode() throw( RuntimeException, std::exception )
1704 : {
1705 232 : vcl::Window* pWin = GetWindow();
1706 232 : if (pWin)
1707 232 : return static_cast<FmGridControl*>(pWin)->IsDesignMode();
1708 : else
1709 0 : return sal_False;
1710 : }
1711 :
1712 :
1713 45 : void FmXGridPeer::elementInserted(const ContainerEvent& evt) throw( RuntimeException, std::exception )
1714 : {
1715 45 : SolarMutexGuard aGuard;
1716 :
1717 90 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1718 : // Handle Column beruecksichtigen
1719 45 : if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount()))
1720 45 : return;
1721 :
1722 90 : Reference< XPropertySet > xSet(evt.Element, css::uno::UNO_QUERY);
1723 45 : addColumnListeners(xSet);
1724 :
1725 90 : Reference< XPropertySet > xNewColumn(xSet);
1726 90 : OUString aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL));
1727 90 : Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH);
1728 45 : sal_Int32 nWidth = 0;
1729 45 : if (aWidth >>= nWidth)
1730 10 : nWidth = pGrid->LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X();
1731 :
1732 45 : pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor));
1733 :
1734 : // jetzt die Spalte setzen
1735 45 : DbGridColumn* pCol = pGrid->GetColumns().at( ::comphelper::getINT32(evt.Accessor) );
1736 45 : pCol->setModel(xNewColumn);
1737 :
1738 90 : Any aHidden = xNewColumn->getPropertyValue(FM_PROP_HIDDEN);
1739 45 : if (::comphelper::getBOOL(aHidden))
1740 0 : pGrid->HideColumn(pCol->GetId());
1741 :
1742 90 : FormControlFactory( m_xContext ).initializeTextFieldLineEnds( xNewColumn );
1743 : }
1744 :
1745 :
1746 6 : void FmXGridPeer::elementReplaced(const ContainerEvent& evt) throw( RuntimeException, std::exception )
1747 : {
1748 6 : SolarMutexGuard aGuard;
1749 :
1750 12 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1751 :
1752 : // Handle Column beruecksichtigen
1753 6 : if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove())
1754 6 : return;
1755 :
1756 12 : Reference< XPropertySet > xNewColumn(evt.Element, css::uno::UNO_QUERY);
1757 : Reference< XPropertySet > xOldColumn(
1758 12 : evt.ReplacedElement, css::uno::UNO_QUERY);
1759 :
1760 6 : bool bWasEditing = pGrid->IsEditing();
1761 6 : if (bWasEditing)
1762 0 : pGrid->DeactivateCell();
1763 :
1764 6 : pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor)));
1765 :
1766 6 : removeColumnListeners(xOldColumn);
1767 6 : addColumnListeners(xNewColumn);
1768 :
1769 12 : OUString aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL));
1770 12 : Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH);
1771 6 : sal_Int32 nWidth = 0;
1772 6 : if (aWidth >>= nWidth)
1773 0 : nWidth = pGrid->LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X();
1774 6 : sal_uInt16 nNewId = pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor));
1775 6 : sal_uInt16 nNewPos = pGrid->GetModelColumnPos(nNewId);
1776 :
1777 : // set the model of the new column
1778 6 : DbGridColumn* pCol = pGrid->GetColumns().at( nNewPos );
1779 :
1780 : // for initializong this grid column, we need the fields of the grid's data source
1781 12 : Reference< XColumnsSupplier > xSuppColumns;
1782 6 : CursorWrapper* pGridDataSource = pGrid->getDataSource();
1783 6 : if ( pGridDataSource )
1784 0 : xSuppColumns.set(Reference< XInterface >( *pGridDataSource ), css::uno::UNO_QUERY);
1785 12 : Reference< XNameAccess > xColumnsByName;
1786 6 : if ( xSuppColumns.is() )
1787 0 : xColumnsByName = xSuppColumns->getColumns();
1788 12 : Reference< XIndexAccess > xColumnsByIndex( xColumnsByName, UNO_QUERY );
1789 :
1790 6 : if ( xColumnsByIndex.is() )
1791 0 : FmGridControl::InitColumnByField( pCol, xNewColumn, xColumnsByName, xColumnsByIndex );
1792 : else
1793 : // the simple version, applies when the grid is not yet connected to a data source
1794 6 : pCol->setModel(xNewColumn);
1795 :
1796 6 : if (bWasEditing)
1797 6 : pGrid->ActivateCell();
1798 : }
1799 :
1800 :
1801 4 : void FmXGridPeer::elementRemoved(const ContainerEvent& evt) throw( RuntimeException, std::exception )
1802 : {
1803 4 : SolarMutexGuard aGuard;
1804 :
1805 8 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1806 :
1807 : // Handle Column beruecksichtigen
1808 4 : if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount()))
1809 4 : return;
1810 :
1811 4 : pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor)));
1812 :
1813 8 : Reference< XPropertySet > xOldColumn(evt.Element, css::uno::UNO_QUERY);
1814 8 : removeColumnListeners(xOldColumn);
1815 : }
1816 :
1817 :
1818 884 : void FmXGridPeer::setProperty( const OUString& PropertyName, const Any& Value) throw( RuntimeException, std::exception )
1819 : {
1820 884 : SolarMutexGuard aGuard;
1821 :
1822 1768 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1823 :
1824 884 : bool bVoid = !Value.hasValue();
1825 :
1826 884 : if ( PropertyName == FM_PROP_TEXTLINECOLOR )
1827 : {
1828 20 : ::Color aTextLineColor( bVoid ? COL_TRANSPARENT : ::comphelper::getINT32( Value ) );
1829 20 : if (bVoid)
1830 : {
1831 20 : pGrid->SetTextLineColor();
1832 20 : pGrid->GetDataWindow().SetTextLineColor();
1833 : }
1834 : else
1835 : {
1836 0 : pGrid->SetTextLineColor(aTextLineColor);
1837 0 : pGrid->GetDataWindow().SetTextLineColor(aTextLineColor);
1838 : }
1839 :
1840 : // need to forward this to the columns
1841 20 : DbGridColumns& rColumns = const_cast<DbGridColumns&>(pGrid->GetColumns());
1842 20 : for ( size_t i = 0, n = rColumns.size(); i < n; ++i )
1843 : {
1844 0 : DbGridColumn* pLoop = rColumns[ i ];
1845 0 : FmXGridCell* pXCell = pLoop->GetCell();
1846 0 : if (pXCell)
1847 : {
1848 0 : if (bVoid)
1849 0 : pXCell->SetTextLineColor();
1850 : else
1851 0 : pXCell->SetTextLineColor(aTextLineColor);
1852 : }
1853 : }
1854 :
1855 20 : if (isDesignMode())
1856 0 : pGrid->Invalidate();
1857 : }
1858 864 : else if ( PropertyName == FM_PROP_FONTEMPHASISMARK )
1859 : {
1860 23 : vcl::Font aGridFont = pGrid->GetControlFont();
1861 23 : sal_Int16 nValue = ::comphelper::getINT16(Value);
1862 23 : aGridFont.SetEmphasisMark( nValue );
1863 23 : pGrid->SetControlFont( aGridFont );
1864 : }
1865 841 : else if ( PropertyName == FM_PROP_FONTRELIEF )
1866 : {
1867 23 : vcl::Font aGridFont = pGrid->GetControlFont();
1868 23 : sal_Int16 nValue = ::comphelper::getINT16(Value);
1869 23 : aGridFont.SetRelief( (FontRelief)nValue );
1870 23 : pGrid->SetControlFont( aGridFont );
1871 : }
1872 818 : else if ( PropertyName == FM_PROP_HELPURL )
1873 : {
1874 23 : OUString sHelpURL;
1875 23 : OSL_VERIFY( Value >>= sHelpURL );
1876 46 : INetURLObject aHID( sHelpURL );
1877 23 : if ( aHID.GetProtocol() == INetProtocol::Hid )
1878 0 : sHelpURL = aHID.GetURLPath();
1879 46 : pGrid->SetHelpId( OUStringToOString( sHelpURL, RTL_TEXTENCODING_UTF8 ) );
1880 : }
1881 795 : else if ( PropertyName == FM_PROP_DISPLAYSYNCHRON )
1882 : {
1883 27 : pGrid->setDisplaySynchron(::comphelper::getBOOL(Value));
1884 : }
1885 768 : else if ( PropertyName == FM_PROP_CURSORCOLOR )
1886 : {
1887 20 : if (bVoid)
1888 20 : pGrid->SetCursorColor(COL_TRANSPARENT);
1889 : else
1890 0 : pGrid->SetCursorColor( ::Color(::comphelper::getINT32(Value)));
1891 20 : if (isDesignMode())
1892 0 : pGrid->Invalidate();
1893 : }
1894 748 : else if ( PropertyName == FM_PROP_ALWAYSSHOWCURSOR )
1895 : {
1896 27 : pGrid->EnablePermanentCursor(::comphelper::getBOOL(Value));
1897 27 : if (isDesignMode())
1898 7 : pGrid->Invalidate();
1899 : }
1900 721 : else if ( PropertyName == FM_PROP_FONT )
1901 : {
1902 46 : if ( bVoid )
1903 0 : pGrid->SetControlFont( vcl::Font() );
1904 : else
1905 : {
1906 46 : ::com::sun::star::awt::FontDescriptor aFont;
1907 46 : if (Value >>= aFont)
1908 : {
1909 46 : vcl::Font aNewVclFont;
1910 46 : if (::comphelper::operator!=(aFont, ::comphelper::getDefaultFont())) // ist das der Default
1911 45 : aNewVclFont = ImplCreateFont( aFont );
1912 :
1913 : // need to add relief and emphasis (they're stored in a VCL-Font, but not in a FontDescriptor
1914 92 : vcl::Font aOldVclFont = pGrid->GetControlFont();
1915 46 : aNewVclFont.SetRelief( aOldVclFont.GetRelief() );
1916 46 : aNewVclFont.SetEmphasisMark( aOldVclFont.GetEmphasisMark() );
1917 :
1918 : // now set it ...
1919 46 : pGrid->SetControlFont( aNewVclFont );
1920 :
1921 : // if our row-height property is void (which means "calculate it font-dependent") we have
1922 : // to adjust the control's row height
1923 92 : Reference< XPropertySet > xModelSet(getColumns(), UNO_QUERY);
1924 46 : if (xModelSet.is() && ::comphelper::hasProperty(FM_PROP_ROWHEIGHT, xModelSet))
1925 : {
1926 26 : Any aHeight = xModelSet->getPropertyValue(FM_PROP_ROWHEIGHT);
1927 26 : if (!aHeight.hasValue())
1928 26 : pGrid->SetDataRowHeight(0);
1929 46 : }
1930 :
1931 46 : }
1932 : }
1933 : }
1934 675 : else if ( PropertyName == FM_PROP_BACKGROUNDCOLOR )
1935 : {
1936 20 : if ( bVoid )
1937 : {
1938 20 : pGrid->SetControlBackground();
1939 : }
1940 : else
1941 : {
1942 0 : ::Color aColor( ::comphelper::getINT32(Value) );
1943 0 : pGrid->SetBackground( aColor );
1944 0 : pGrid->SetControlBackground( aColor );
1945 : }
1946 : }
1947 655 : else if ( PropertyName == FM_PROP_TEXTCOLOR )
1948 : {
1949 20 : if ( bVoid )
1950 : {
1951 20 : pGrid->SetControlForeground();
1952 : }
1953 : else
1954 : {
1955 0 : ::Color aColor( ::comphelper::getINT32(Value) );
1956 0 : pGrid->SetTextColor( aColor );
1957 0 : pGrid->SetControlForeground( aColor );
1958 : }
1959 : }
1960 635 : else if ( PropertyName == FM_PROP_ROWHEIGHT )
1961 : {
1962 20 : sal_Int32 nLogHeight(0);
1963 20 : if (Value >>= nLogHeight)
1964 : {
1965 0 : sal_Int32 nHeight = pGrid->LogicToPixel(Point(0,nLogHeight),MAP_10TH_MM).Y();
1966 : // take the zoom factor into account
1967 0 : nHeight = pGrid->CalcZoom(nHeight);
1968 0 : pGrid->SetDataRowHeight(nHeight);
1969 : }
1970 20 : else if (bVoid)
1971 20 : pGrid->SetDataRowHeight(0);
1972 : }
1973 615 : else if ( PropertyName == FM_PROP_HASNAVIGATION )
1974 : {
1975 27 : bool bValue( true );
1976 27 : OSL_VERIFY( Value >>= bValue );
1977 27 : pGrid->EnableNavigationBar( bValue );
1978 : }
1979 588 : else if ( PropertyName == FM_PROP_RECORDMARKER )
1980 : {
1981 27 : bool bValue( true );
1982 27 : OSL_VERIFY( Value >>= bValue );
1983 27 : pGrid->EnableHandle( bValue );
1984 : }
1985 561 : else if ( PropertyName == FM_PROP_ENABLED )
1986 : {
1987 28 : bool bValue( true );
1988 28 : OSL_VERIFY( Value >>= bValue );
1989 :
1990 : // In design mode, disable only the data window.
1991 : // Else the control cannot be configured anymore.
1992 28 : if (isDesignMode())
1993 8 : pGrid->GetDataWindow().Enable( bValue );
1994 : else
1995 20 : pGrid->Enable( bValue );
1996 : }
1997 : else
1998 1417 : VCLXWindow::setProperty( PropertyName, Value );
1999 884 : }
2000 :
2001 :
2002 0 : Reference< XAccessibleContext > FmXGridPeer::CreateAccessibleContext()
2003 : {
2004 0 : Reference< XAccessibleContext > xContext;
2005 :
2006 : // use the AccessibleContext provided by the VCL window
2007 0 : vcl::Window* pGrid = GetWindow();
2008 0 : if ( pGrid )
2009 : {
2010 0 : Reference< XAccessible > xAcc( pGrid->GetAccessible( true ) );
2011 0 : if ( xAcc.is() )
2012 0 : xContext = xAcc->getAccessibleContext();
2013 : // TODO: this has a slight conceptual problem:
2014 :
2015 : // We know that the XAccessible and XAccessibleContext implementation of the browse
2016 : // box is the same (the class implements both interfaces), which, speaking strictly,
2017 : // is bad here (means when a browse box acts as UnoControl): We (the FmXGridPeer) are
2018 : // the XAccessible here, and the browse box should be able to provide us an XAccessibleContext,
2019 : // but it should _not_ be the XAccessible itself.
2020 : // However, as long as no client implementation uses dirty hacks such as querying an
2021 : // XAccessibleContext for XAccessible, this should not be a problem.
2022 : }
2023 :
2024 0 : if ( !xContext.is() )
2025 0 : xContext = VCLXWindow::CreateAccessibleContext( );
2026 :
2027 0 : return xContext;
2028 : }
2029 :
2030 :
2031 0 : Any FmXGridPeer::getProperty( const OUString& _rPropertyName ) throw( RuntimeException, std::exception )
2032 : {
2033 0 : Any aProp;
2034 0 : if (GetWindow())
2035 : {
2036 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2037 0 : vcl::Window* pDataWindow = &pGrid->GetDataWindow();
2038 :
2039 0 : if ( _rPropertyName == FM_PROP_NAME )
2040 : {
2041 0 : vcl::Font aFont = pDataWindow->GetControlFont();
2042 0 : aProp <<= ImplCreateFontDescriptor( aFont );
2043 : }
2044 0 : else if ( _rPropertyName == FM_PROP_TEXTCOLOR )
2045 : {
2046 0 : aProp <<= (sal_Int32)pDataWindow->GetControlForeground().GetColor();
2047 : }
2048 0 : else if ( _rPropertyName == FM_PROP_BACKGROUNDCOLOR )
2049 : {
2050 0 : aProp <<= (sal_Int32)pDataWindow->GetControlBackground().GetColor();
2051 : }
2052 0 : else if ( _rPropertyName == FM_PROP_ROWHEIGHT )
2053 : {
2054 0 : sal_Int32 nPixelHeight = pGrid->GetDataRowHeight();
2055 : // take the zoom factor into account
2056 0 : nPixelHeight = pGrid->CalcReverseZoom(nPixelHeight);
2057 0 : aProp <<= (sal_Int32)pGrid->PixelToLogic(Point(0,nPixelHeight),MAP_10TH_MM).Y();
2058 : }
2059 0 : else if ( _rPropertyName == FM_PROP_HASNAVIGATION )
2060 : {
2061 0 : bool bHasNavBar = pGrid->HasNavigationBar();
2062 0 : aProp <<= bHasNavBar;
2063 : }
2064 0 : else if ( _rPropertyName == FM_PROP_RECORDMARKER )
2065 : {
2066 0 : bool bHasHandle = pGrid->HasHandle();
2067 0 : aProp <<= bHasHandle;
2068 : }
2069 0 : else if ( _rPropertyName == FM_PROP_ENABLED )
2070 : {
2071 0 : aProp <<= pDataWindow->IsEnabled();
2072 : }
2073 : else
2074 0 : aProp = VCLXWindow::getProperty( _rPropertyName );
2075 : }
2076 0 : return aProp;
2077 : }
2078 :
2079 :
2080 40 : void FmXGridPeer::dispose() throw( RuntimeException, std::exception )
2081 : {
2082 40 : EventObject aEvt;
2083 40 : aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
2084 40 : m_aModifyListeners.disposeAndClear(aEvt);
2085 40 : m_aUpdateListeners.disposeAndClear(aEvt);
2086 40 : m_aContainerListeners.disposeAndClear(aEvt);
2087 40 : VCLXWindow::dispose();
2088 :
2089 : // release all interceptors
2090 80 : Reference< XDispatchProviderInterceptor > xInterceptor( m_xFirstDispatchInterceptor );
2091 40 : m_xFirstDispatchInterceptor.clear();
2092 80 : while ( xInterceptor.is() )
2093 : {
2094 : // tell the interceptor it has a new (means no) predecessor
2095 0 : xInterceptor->setMasterDispatchProvider( NULL );
2096 :
2097 : // ask for it's successor
2098 0 : Reference< XDispatchProvider > xSlave = xInterceptor->getSlaveDispatchProvider();
2099 : // and give it the new (means no) successoert
2100 0 : xInterceptor->setSlaveDispatchProvider( NULL );
2101 :
2102 : // start over with the next chain element
2103 0 : xInterceptor.set(xSlave, css::uno::UNO_QUERY);
2104 0 : }
2105 :
2106 40 : DisConnectFromDispatcher();
2107 80 : setRowSet(Reference< XRowSet > ());
2108 40 : }
2109 :
2110 : // XContainer
2111 :
2112 0 : void FmXGridPeer::addContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
2113 : {
2114 0 : m_aContainerListeners.addInterface( l );
2115 0 : }
2116 :
2117 0 : void FmXGridPeer::removeContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
2118 : {
2119 0 : m_aContainerListeners.removeInterface( l );
2120 0 : }
2121 :
2122 : // ::com::sun::star::data::XDatabaseCursorSupplier
2123 :
2124 2 : void FmXGridPeer::startCursorListening()
2125 : {
2126 2 : if (!m_nCursorListening)
2127 : {
2128 1 : Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY);
2129 1 : if (xRowSet.is())
2130 1 : xRowSet->addRowSetListener(this);
2131 :
2132 2 : Reference< XReset > xReset(m_xCursor, UNO_QUERY);
2133 1 : if (xReset.is())
2134 1 : xReset->addResetListener(this);
2135 :
2136 : // register all listeners
2137 2 : Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY);
2138 1 : if (xSet.is())
2139 : {
2140 1 : xSet->addPropertyChangeListener(FM_PROP_ISMODIFIED, this);
2141 1 : xSet->addPropertyChangeListener(FM_PROP_ROWCOUNT, this);
2142 1 : }
2143 : }
2144 2 : m_nCursorListening++;
2145 2 : }
2146 :
2147 :
2148 1 : void FmXGridPeer::stopCursorListening()
2149 : {
2150 1 : if (!--m_nCursorListening)
2151 : {
2152 0 : Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY);
2153 0 : if (xRowSet.is())
2154 0 : xRowSet->removeRowSetListener(this);
2155 :
2156 0 : Reference< XReset > xReset(m_xCursor, UNO_QUERY);
2157 0 : if (xReset.is())
2158 0 : xReset->removeResetListener(this);
2159 :
2160 0 : Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY);
2161 0 : if (xSet.is())
2162 : {
2163 0 : xSet->removePropertyChangeListener(FM_PROP_ISMODIFIED, this);
2164 0 : xSet->removePropertyChangeListener(FM_PROP_ROWCOUNT, this);
2165 0 : }
2166 : }
2167 1 : }
2168 :
2169 :
2170 2 : void FmXGridPeer::updateGrid(const Reference< XRowSet >& _rxCursor)
2171 : {
2172 2 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2173 2 : if (pGrid)
2174 2 : pGrid->setDataSource(_rxCursor);
2175 2 : }
2176 :
2177 :
2178 0 : Reference< XRowSet > FmXGridPeer::getRowSet() throw( RuntimeException, std::exception )
2179 : {
2180 0 : return m_xCursor;
2181 : }
2182 :
2183 :
2184 66 : void FmXGridPeer::setRowSet(const Reference< XRowSet >& _rDatabaseCursor) throw( RuntimeException, std::exception )
2185 : {
2186 66 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2187 66 : if (!pGrid || !m_xColumns.is() || !m_xColumns->getCount())
2188 131 : return;
2189 : // unregister all listeners
2190 1 : if (m_xCursor.is())
2191 : {
2192 0 : Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY);
2193 : // only if the form is loaded we set the rowset
2194 0 : if (xLoadable.is())
2195 : {
2196 0 : stopCursorListening();
2197 0 : xLoadable->removeLoadListener(this);
2198 0 : }
2199 : }
2200 :
2201 1 : m_xCursor = _rDatabaseCursor;
2202 :
2203 1 : if (pGrid)
2204 : {
2205 1 : Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY);
2206 : // only if the form is loaded we set the rowset
2207 1 : if (xLoadable.is() && xLoadable->isLoaded())
2208 1 : pGrid->setDataSource(m_xCursor);
2209 : else
2210 0 : pGrid->setDataSource(Reference< XRowSet > ());
2211 :
2212 1 : if (xLoadable.is())
2213 : {
2214 1 : startCursorListening();
2215 1 : xLoadable->addLoadListener(this);
2216 1 : }
2217 1 : }
2218 : }
2219 :
2220 :
2221 0 : void SAL_CALL FmXGridPeer::addGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
2222 : {
2223 0 : m_aGridControlListeners.addInterface( _listener );
2224 0 : }
2225 :
2226 :
2227 0 : void SAL_CALL FmXGridPeer::removeGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
2228 : {
2229 0 : m_aGridControlListeners.removeInterface( _listener );
2230 0 : }
2231 :
2232 :
2233 15 : sal_Int16 FmXGridPeer::getCurrentColumnPosition() throw( RuntimeException, std::exception )
2234 : {
2235 15 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2236 15 : return pGrid ? pGrid->GetViewColumnPos(pGrid->GetCurColumnId()) : -1;
2237 : }
2238 :
2239 :
2240 0 : void FmXGridPeer::setCurrentColumnPosition(sal_Int16 nPos) throw( RuntimeException, std::exception )
2241 : {
2242 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2243 0 : if (pGrid)
2244 0 : pGrid->GoToColumnId(pGrid->GetColumnIdFromViewPos(nPos));
2245 0 : }
2246 :
2247 :
2248 20 : void FmXGridPeer::selectionChanged(const EventObject& evt) throw( RuntimeException, std::exception )
2249 : {
2250 20 : SolarMutexGuard aGuard;
2251 :
2252 40 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2253 20 : if (pGrid)
2254 : {
2255 20 : Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(evt.Source, UNO_QUERY);
2256 40 : Any aSelection = xSelSupplier->getSelection();
2257 : DBG_ASSERT(aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE, "FmXGridPeer::selectionChanged : invalid selection !");
2258 40 : Reference< XPropertySet > xSelection;
2259 20 : aSelection >>= xSelection;
2260 20 : if (xSelection.is())
2261 : {
2262 0 : Reference< XPropertySet > xCol;
2263 0 : sal_Int32 i = 0;
2264 0 : sal_Int32 nColCount = m_xColumns->getCount();
2265 :
2266 0 : for (; i < nColCount; ++i)
2267 : {
2268 0 : m_xColumns->getByIndex(i) >>= xCol;
2269 0 : if ( xCol == xSelection )
2270 : {
2271 0 : pGrid->markColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)i));
2272 0 : break;
2273 : }
2274 : }
2275 : // The columns have to be 1-based for the VCL control.
2276 : // If necessary, pass on the selection to the VCL control
2277 0 : if ( i != pGrid->GetSelectedColumn() )
2278 : { // (wenn das nicht greift, wurde das selectionChanged implizit von dem Control selber ausgeloest
2279 : // if this does not ?hold?catch?, the selectionChanged is cleared by the Control itself
2280 0 : if ( i < nColCount )
2281 : {
2282 0 : pGrid->SelectColumnPos(pGrid->GetViewColumnPos(pGrid->GetColumnIdFromModelPos( (sal_uInt16)i )) + 1, true);
2283 : // SelectColumnPos has led to an implicit ActivateCell again
2284 0 : if (pGrid->IsEditing())
2285 0 : pGrid->DeactivateCell();
2286 : }
2287 : else
2288 0 : pGrid->SetNoSelection();
2289 0 : }
2290 : }
2291 : else
2292 40 : pGrid->markColumn(USHRT_MAX);
2293 20 : }
2294 20 : }
2295 :
2296 : // XElementAccess
2297 :
2298 0 : sal_Bool FmXGridPeer::hasElements() throw( RuntimeException, std::exception )
2299 : {
2300 0 : return getCount() != 0;
2301 : }
2302 :
2303 :
2304 0 : Type SAL_CALL FmXGridPeer::getElementType( ) throw(RuntimeException, std::exception)
2305 : {
2306 0 : return cppu::UnoType<com::sun::star::awt::XControl>::get();
2307 : }
2308 :
2309 : // XEnumerationAccess
2310 :
2311 0 : Reference< XEnumeration > FmXGridPeer::createEnumeration() throw( RuntimeException, std::exception )
2312 : {
2313 0 : return new ::comphelper::OEnumerationByIndex(this);
2314 : }
2315 :
2316 : // XIndexAccess
2317 :
2318 0 : sal_Int32 FmXGridPeer::getCount() throw( RuntimeException, std::exception )
2319 : {
2320 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2321 0 : if (pGrid)
2322 0 : return pGrid->GetViewColCount();
2323 : else
2324 0 : return 0;
2325 : }
2326 :
2327 :
2328 0 : Any FmXGridPeer::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
2329 : {
2330 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2331 0 : if (_nIndex < 0 ||
2332 0 : _nIndex >= getCount() || !pGrid)
2333 0 : throw IndexOutOfBoundsException();
2334 :
2335 0 : Any aElement;
2336 : // get the columnid
2337 0 : sal_uInt16 nId = pGrid->GetColumnIdFromViewPos((sal_uInt16)_nIndex);
2338 : // get the list position
2339 0 : sal_uInt16 nPos = pGrid->GetModelColumnPos(nId);
2340 :
2341 0 : if ( nPos == GRID_COLUMN_NOT_FOUND )
2342 0 : return aElement;
2343 :
2344 0 : DbGridColumn* pCol = pGrid->GetColumns().at( nPos );
2345 0 : Reference< ::com::sun::star::awt::XControl > xControl(pCol->GetCell());
2346 0 : aElement <<= xControl;
2347 :
2348 0 : return aElement;
2349 : }
2350 :
2351 : // ::com::sun::star::util::XModeSelector
2352 :
2353 0 : void FmXGridPeer::setMode(const OUString& Mode) throw( NoSupportException, RuntimeException, std::exception )
2354 : {
2355 0 : if (!supportsMode(Mode))
2356 0 : throw NoSupportException();
2357 :
2358 0 : if (Mode == m_aMode)
2359 0 : return;
2360 :
2361 0 : m_aMode = Mode;
2362 :
2363 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2364 0 : if ( Mode == "FilterMode" )
2365 0 : pGrid->SetFilterMode(true);
2366 : else
2367 : {
2368 0 : pGrid->SetFilterMode(false);
2369 0 : pGrid->setDataSource(m_xCursor);
2370 0 : }
2371 : }
2372 :
2373 :
2374 0 : OUString FmXGridPeer::getMode() throw( RuntimeException, std::exception )
2375 : {
2376 0 : return m_aMode;
2377 : }
2378 :
2379 :
2380 0 : ::comphelper::StringSequence FmXGridPeer::getSupportedModes() throw( RuntimeException, std::exception )
2381 : {
2382 0 : static ::comphelper::StringSequence aModes;
2383 0 : if (!aModes.getLength())
2384 : {
2385 0 : aModes.realloc(2);
2386 0 : OUString* pModes = aModes.getArray();
2387 0 : pModes[0] = "DataMode";
2388 0 : pModes[1] = "FilterMode";
2389 : }
2390 0 : return aModes;
2391 : }
2392 :
2393 :
2394 0 : sal_Bool FmXGridPeer::supportsMode(const OUString& Mode) throw( RuntimeException, std::exception )
2395 : {
2396 0 : ::comphelper::StringSequence aModes(getSupportedModes());
2397 0 : const OUString* pModes = aModes.getConstArray();
2398 0 : for (sal_Int32 i = aModes.getLength(); i > 0; )
2399 : {
2400 0 : if (pModes[--i] == Mode)
2401 0 : return sal_True;
2402 : }
2403 0 : return sal_False;
2404 : }
2405 :
2406 :
2407 0 : void FmXGridPeer::columnVisible(DbGridColumn* pColumn)
2408 : {
2409 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2410 :
2411 0 : sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId());
2412 0 : Reference< ::com::sun::star::awt::XControl > xControl(pColumn->GetCell());
2413 0 : ContainerEvent aEvt;
2414 0 : aEvt.Source = static_cast<XContainer*>(this);
2415 0 : aEvt.Accessor <<= _nIndex;
2416 0 : aEvt.Element <<= xControl;
2417 :
2418 0 : m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt );
2419 0 : }
2420 :
2421 :
2422 0 : void FmXGridPeer::columnHidden(DbGridColumn* pColumn)
2423 : {
2424 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2425 :
2426 0 : sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId());
2427 0 : Reference< ::com::sun::star::awt::XControl > xControl(pColumn->GetCell());
2428 0 : ContainerEvent aEvt;
2429 0 : aEvt.Source = static_cast<XContainer*>(this);
2430 0 : aEvt.Accessor <<= _nIndex;
2431 0 : aEvt.Element <<= xControl;
2432 :
2433 0 : m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt );
2434 0 : }
2435 :
2436 :
2437 57 : void FmXGridPeer::draw( sal_Int32 x, sal_Int32 y ) throw( RuntimeException, std::exception )
2438 : {
2439 57 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2440 57 : EditBrowseBoxFlags nOldFlags = pGrid->GetBrowserFlags();
2441 57 : pGrid->SetBrowserFlags(nOldFlags | EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT);
2442 :
2443 57 : VCLXWindow::draw(x, y);
2444 :
2445 57 : pGrid->SetBrowserFlags(nOldFlags);
2446 57 : }
2447 :
2448 :
2449 21 : Reference< ::com::sun::star::frame::XDispatch > FmXGridPeer::queryDispatch(const ::com::sun::star::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags) throw( RuntimeException, std::exception )
2450 : {
2451 21 : Reference< ::com::sun::star::frame::XDispatch > xResult;
2452 :
2453 : // first ask our interceptor chain
2454 21 : if (m_xFirstDispatchInterceptor.is() && !m_bInterceptingDispatch)
2455 : {
2456 8 : m_bInterceptingDispatch = true;
2457 : // safety against recursion : as we are master of the first chain element and slave of the last one we would
2458 : // have an infinite loop without this if no dispatcher can fulfill the request
2459 8 : xResult = m_xFirstDispatchInterceptor->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
2460 8 : m_bInterceptingDispatch = false;
2461 : }
2462 :
2463 : // then ask ourself : we don't have any dispatches
2464 21 : return xResult;
2465 : }
2466 :
2467 :
2468 0 : Sequence< Reference< ::com::sun::star::frame::XDispatch > > FmXGridPeer::queryDispatches(const Sequence< ::com::sun::star::frame::DispatchDescriptor>& aDescripts) throw( RuntimeException, std::exception )
2469 : {
2470 0 : if (m_xFirstDispatchInterceptor.is())
2471 0 : return m_xFirstDispatchInterceptor->queryDispatches(aDescripts);
2472 :
2473 : // then ask ourself : we don't have any dispatches
2474 0 : return Sequence< Reference< ::com::sun::star::frame::XDispatch > >();
2475 : }
2476 :
2477 :
2478 1 : void FmXGridPeer::registerDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
2479 : {
2480 1 : if (_xInterceptor.is())
2481 : {
2482 1 : if (m_xFirstDispatchInterceptor.is())
2483 : {
2484 0 : Reference< ::com::sun::star::frame::XDispatchProvider > xFirstProvider(m_xFirstDispatchInterceptor, UNO_QUERY);
2485 : // there is already an interceptor; the new one will become its master
2486 0 : _xInterceptor->setSlaveDispatchProvider(xFirstProvider);
2487 0 : m_xFirstDispatchInterceptor->setMasterDispatchProvider(xFirstProvider);
2488 : }
2489 : else
2490 : {
2491 : // it is the first interceptor; set ourself as slave
2492 1 : _xInterceptor->setSlaveDispatchProvider(static_cast<com::sun::star::frame::XDispatchProvider*>(this));
2493 : }
2494 :
2495 : // we are the master of the chain's first interceptor
2496 1 : m_xFirstDispatchInterceptor = _xInterceptor;
2497 1 : m_xFirstDispatchInterceptor->setMasterDispatchProvider(static_cast<com::sun::star::frame::XDispatchProvider*>(this));
2498 :
2499 : // we have a new interceptor and we're alive ?
2500 1 : if (!isDesignMode())
2501 : // -> check for new dispatchers
2502 0 : UpdateDispatches();
2503 : }
2504 1 : }
2505 :
2506 :
2507 1 : void FmXGridPeer::releaseDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
2508 : {
2509 1 : if (!_xInterceptor.is())
2510 1 : return;
2511 :
2512 1 : Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xChainWalk(m_xFirstDispatchInterceptor);
2513 :
2514 1 : if (m_xFirstDispatchInterceptor == _xInterceptor)
2515 : { // our chain will have a new first element
2516 1 : Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xSlave(m_xFirstDispatchInterceptor->getSlaveDispatchProvider(), UNO_QUERY);
2517 1 : m_xFirstDispatchInterceptor = xSlave;
2518 : }
2519 : // do this before removing the interceptor from the chain as we won't know it's slave afterwards)
2520 :
2521 3 : while (xChainWalk.is())
2522 : {
2523 : // walk along the chain of interceptors and look for the interceptor that has to be removed
2524 1 : Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xSlave(xChainWalk->getSlaveDispatchProvider(), UNO_QUERY);
2525 :
2526 1 : if (xChainWalk == _xInterceptor)
2527 : {
2528 : // old master may be an interceptor too
2529 1 : Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xMaster(xChainWalk->getMasterDispatchProvider(), UNO_QUERY);
2530 :
2531 : // unchain the interceptor that has to be removed
2532 1 : xChainWalk->setSlaveDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider > ());
2533 1 : xChainWalk->setMasterDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider > ());
2534 :
2535 : // reconnect the chain
2536 1 : if (xMaster.is())
2537 : {
2538 0 : if (xSlave.is())
2539 0 : xMaster->setSlaveDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider >::query(xSlave));
2540 : else
2541 : // it's the first interceptor of the chain, set ourself as slave
2542 0 : xMaster->setSlaveDispatchProvider(static_cast<com::sun::star::frame::XDispatchProvider*>(this));
2543 : }
2544 : else
2545 : {
2546 : // the chain's first element was removed, set ourself as new master of the second one
2547 1 : if (xSlave.is())
2548 0 : xSlave->setMasterDispatchProvider(static_cast<com::sun::star::frame::XDispatchProvider*>(this));
2549 1 : }
2550 : }
2551 :
2552 1 : xChainWalk = xSlave;
2553 1 : }
2554 : // our interceptor chain has changed and we're alive ?
2555 1 : if (!isDesignMode())
2556 : // -> check the dispatchers
2557 1 : UpdateDispatches();
2558 : }
2559 :
2560 :
2561 10 : void FmXGridPeer::statusChanged(const ::com::sun::star::frame::FeatureStateEvent& Event) throw( RuntimeException, std::exception )
2562 : {
2563 : DBG_ASSERT(m_pStateCache, "FmXGridPeer::statusChanged : invalid call !");
2564 : DBG_ASSERT(m_pDispatchers, "FmXGridPeer::statusChanged : invalid call !");
2565 :
2566 10 : Sequence< ::com::sun::star::util::URL>& aUrls = getSupportedURLs();
2567 10 : const ::com::sun::star::util::URL* pUrls = aUrls.getConstArray();
2568 :
2569 10 : Sequence<sal_uInt16> aSlots = getSupportedGridSlots();
2570 10 : const sal_uInt16* pSlots = aSlots.getConstArray();
2571 :
2572 : sal_uInt16 i;
2573 60 : for (i=0; i<aUrls.getLength(); ++i, ++pUrls, ++pSlots)
2574 : {
2575 60 : if (pUrls->Main == Event.FeatureURL.Main)
2576 : {
2577 : DBG_ASSERT(m_pDispatchers[i] == Event.Source, "FmXGridPeer::statusChanged : the event source is a little bit suspect !");
2578 10 : m_pStateCache[i] = Event.IsEnabled;
2579 10 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2580 10 : if (*pSlots != SID_FM_RECORD_UNDO)
2581 0 : pGrid->GetNavigationBar().InvalidateState(*pSlots);
2582 10 : break;
2583 : }
2584 : }
2585 10 : DBG_ASSERT(i<aUrls.getLength(), "FmXGridPeer::statusChanged : got a call for an unknown url !");
2586 10 : }
2587 :
2588 :
2589 2 : sal_Bool FmXGridPeer::approveReset(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
2590 : {
2591 2 : return sal_True;
2592 : }
2593 :
2594 :
2595 0 : sal_Bool SAL_CALL FmXGridPeer::select( const Any& _rSelection ) throw (IllegalArgumentException, RuntimeException, std::exception)
2596 : {
2597 0 : Sequence< Any > aBookmarks;
2598 0 : if ( !( _rSelection >>= aBookmarks ) )
2599 0 : throw IllegalArgumentException();
2600 :
2601 0 : return GetAs< FmGridControl >()->selectBookmarks(aBookmarks);
2602 :
2603 : // TODO:
2604 : // speaking strictly, we would have to adjust our model, as our ColumnSelection may have changed.
2605 : // Our model is a XSelectionSupplier, too, it handles the selection of single columns.
2606 : // This is somewhat strange, as selection should be a view (not a model) aspect.
2607 : // So for a clean solution, we should handle column selection ourself, and the model shouldn't
2608 : // deal with selection at all.
2609 : }
2610 :
2611 :
2612 0 : Any SAL_CALL FmXGridPeer::getSelection( ) throw (RuntimeException, std::exception)
2613 : {
2614 0 : VclPtr< FmGridControl > pVclControl = GetAs< FmGridControl >();
2615 0 : Sequence< Any > aSelectionBookmarks = pVclControl->getSelectionBookmarks();
2616 0 : return makeAny(aSelectionBookmarks);
2617 : }
2618 :
2619 :
2620 0 : void SAL_CALL FmXGridPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
2621 : {
2622 0 : m_aSelectionListeners.addInterface( _rxListener );
2623 0 : }
2624 :
2625 :
2626 0 : void SAL_CALL FmXGridPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
2627 : {
2628 0 : m_aSelectionListeners.removeInterface( _rxListener );
2629 0 : }
2630 :
2631 :
2632 2 : void FmXGridPeer::resetted(const EventObject& rEvent) throw( RuntimeException, std::exception )
2633 : {
2634 2 : if (m_xColumns == rEvent.Source)
2635 : { // my model was reset -> refresh the grid content
2636 2 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2637 2 : if (!pGrid)
2638 2 : return;
2639 4 : SolarMutexGuard aGuard;
2640 4 : pGrid->resetCurrentRow();
2641 : }
2642 : // if the cursor fired a reset event we seem to be on the insert row
2643 0 : else if (m_xCursor == rEvent.Source)
2644 : {
2645 0 : SolarMutexGuard aGuard;
2646 0 : VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2647 0 : if (pGrid && pGrid->IsOpen())
2648 0 : pGrid->positioned(rEvent);
2649 : }
2650 : }
2651 :
2652 :
2653 10 : Sequence<sal_uInt16>& FmXGridPeer::getSupportedGridSlots()
2654 : {
2655 10 : static Sequence<sal_uInt16> aSupported;
2656 10 : if (aSupported.getLength() == 0)
2657 : {
2658 : sal_uInt16 nSupported[] = {
2659 : DbGridControl::NavigationBar::RECORD_FIRST,
2660 : DbGridControl::NavigationBar::RECORD_PREV,
2661 : DbGridControl::NavigationBar::RECORD_NEXT,
2662 : DbGridControl::NavigationBar::RECORD_LAST,
2663 : DbGridControl::NavigationBar::RECORD_NEW,
2664 : SID_FM_RECORD_UNDO
2665 1 : };
2666 1 : aSupported.realloc(sizeof(nSupported)/sizeof(nSupported[0]));
2667 1 : sal_uInt16* pSupported = aSupported.getArray();
2668 7 : for (sal_Int32 i=0; i<aSupported.getLength(); ++i, ++pSupported)
2669 6 : *pSupported = nSupported[i];
2670 : }
2671 10 : return aSupported;
2672 : }
2673 :
2674 :
2675 33 : Sequence< ::com::sun::star::util::URL>& FmXGridPeer::getSupportedURLs()
2676 : {
2677 33 : static Sequence< ::com::sun::star::util::URL> aSupported;
2678 33 : if (aSupported.getLength() == 0)
2679 : {
2680 : static const char* sSupported[] = {
2681 : FMURL_RECORD_MOVEFIRST,
2682 : FMURL_RECORD_MOVEPREV,
2683 : FMURL_RECORD_MOVENEXT,
2684 : FMURL_RECORD_MOVELAST,
2685 : FMURL_RECORD_MOVETONEW,
2686 : FMURL_RECORD_UNDO
2687 : };
2688 2 : aSupported.realloc(sizeof(sSupported)/sizeof(sSupported[0]));
2689 2 : ::com::sun::star::util::URL* pSupported = aSupported.getArray();
2690 : sal_uInt16 i;
2691 :
2692 14 : for ( i = 0; i < aSupported.getLength(); ++i, ++pSupported)
2693 12 : pSupported->Complete = OUString::createFromAscii(sSupported[i]);
2694 :
2695 : // let an ::com::sun::star::util::URL-transformer normalize the URLs
2696 : Reference< ::com::sun::star::util::XURLTransformer > xTransformer(
2697 2 : util::URLTransformer::create(::comphelper::getProcessComponentContext()) );
2698 2 : pSupported = aSupported.getArray();
2699 14 : for (i=0; i<aSupported.getLength(); ++i)
2700 14 : xTransformer->parseStrict(pSupported[i]);
2701 : }
2702 :
2703 33 : return aSupported;
2704 : }
2705 :
2706 :
2707 2 : void FmXGridPeer::UpdateDispatches()
2708 : {
2709 2 : if (!m_pStateCache)
2710 : { // we don't have any dispatchers yet -> do the initial connect
2711 1 : ConnectToDispatcher();
2712 3 : return;
2713 : }
2714 :
2715 1 : sal_uInt16 nDispatchersGot = 0;
2716 1 : const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs();
2717 1 : const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2718 1 : Reference< ::com::sun::star::frame::XDispatch > xNewDispatch;
2719 7 : for (sal_Int32 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2720 : {
2721 6 : xNewDispatch = queryDispatch(*pSupportedURLs, OUString(), 0);
2722 6 : if (xNewDispatch != m_pDispatchers[i])
2723 : {
2724 0 : if (m_pDispatchers[i].is())
2725 0 : m_pDispatchers[i]->removeStatusListener(static_cast<com::sun::star::frame::XStatusListener*>(this), *pSupportedURLs);
2726 0 : m_pDispatchers[i] = xNewDispatch;
2727 0 : if (m_pDispatchers[i].is())
2728 0 : m_pDispatchers[i]->addStatusListener(static_cast<com::sun::star::frame::XStatusListener*>(this), *pSupportedURLs);
2729 : }
2730 6 : if (m_pDispatchers[i].is())
2731 0 : ++nDispatchersGot;
2732 : }
2733 :
2734 1 : if (!nDispatchersGot)
2735 : {
2736 1 : delete[] m_pStateCache;
2737 1 : delete[] m_pDispatchers;
2738 1 : m_pStateCache = NULL;
2739 1 : m_pDispatchers = NULL;
2740 1 : }
2741 : }
2742 :
2743 :
2744 1 : void FmXGridPeer::ConnectToDispatcher()
2745 : {
2746 : DBG_ASSERT((m_pStateCache != NULL) == (m_pDispatchers != NULL), "FmXGridPeer::ConnectToDispatcher : inconsistent !");
2747 1 : if (m_pStateCache)
2748 : { // already connected -> just do an update
2749 0 : UpdateDispatches();
2750 1 : return;
2751 : }
2752 :
2753 1 : const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs();
2754 :
2755 : // _before_ adding the status listeners (as the add should result in a statusChanged-call) !
2756 1 : m_pStateCache = new bool[aSupportedURLs.getLength()];
2757 1 : m_pDispatchers = new Reference< ::com::sun::star::frame::XDispatch > [aSupportedURLs.getLength()];
2758 :
2759 1 : sal_uInt16 nDispatchersGot = 0;
2760 1 : const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2761 7 : for (sal_Int32 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2762 : {
2763 6 : m_pStateCache[i] = false;
2764 6 : m_pDispatchers[i] = queryDispatch(*pSupportedURLs, OUString(), 0);
2765 6 : if (m_pDispatchers[i].is())
2766 : {
2767 1 : m_pDispatchers[i]->addStatusListener(static_cast<com::sun::star::frame::XStatusListener*>(this), *pSupportedURLs);
2768 1 : ++nDispatchersGot;
2769 : }
2770 : }
2771 :
2772 1 : if (!nDispatchersGot)
2773 : {
2774 0 : delete[] m_pStateCache;
2775 0 : delete[] m_pDispatchers;
2776 0 : m_pStateCache = NULL;
2777 0 : m_pDispatchers = NULL;
2778 : }
2779 : }
2780 :
2781 :
2782 117 : void FmXGridPeer::DisConnectFromDispatcher()
2783 : {
2784 117 : if (!m_pStateCache || !m_pDispatchers)
2785 234 : return;
2786 : // we're not connected
2787 :
2788 0 : const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs();
2789 0 : const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2790 0 : for (sal_Int32 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2791 : {
2792 0 : if (m_pDispatchers[i].is())
2793 0 : m_pDispatchers[i]->removeStatusListener(static_cast<com::sun::star::frame::XStatusListener*>(this), *pSupportedURLs);
2794 : }
2795 :
2796 0 : delete[] m_pStateCache;
2797 0 : delete[] m_pDispatchers;
2798 0 : m_pStateCache = NULL;
2799 0 : m_pDispatchers = NULL;
2800 : }
2801 :
2802 :
2803 18 : IMPL_LINK(FmXGridPeer, OnQueryGridSlotState, void*, pSlot)
2804 : {
2805 9 : if (!m_pStateCache)
2806 9 : return -1; // unspecified
2807 :
2808 0 : sal_uInt16 nSlot = (sal_uInt16)reinterpret_cast<sal_uIntPtr>(pSlot);
2809 :
2810 : // search the given slot with our supported sequence
2811 0 : Sequence<sal_uInt16>& aSupported = getSupportedGridSlots();
2812 0 : const sal_uInt16* pSlots = aSupported.getConstArray();
2813 0 : for (sal_Int32 i=0; i<aSupported.getLength(); ++i)
2814 : {
2815 0 : if (pSlots[i] == nSlot)
2816 : {
2817 0 : if (!m_pDispatchers[i].is())
2818 0 : return -1; // nothing known about this slot
2819 : else
2820 0 : return m_pStateCache[i] ? 1 : 0;
2821 : }
2822 : }
2823 :
2824 0 : return -1;
2825 : }
2826 :
2827 :
2828 0 : IMPL_LINK(FmXGridPeer, OnExecuteGridSlot, void*, pSlot)
2829 : {
2830 0 : if (!m_pDispatchers)
2831 0 : return 0; // not handled
2832 :
2833 0 : Sequence< ::com::sun::star::util::URL>& aUrls = getSupportedURLs();
2834 0 : const ::com::sun::star::util::URL* pUrls = aUrls.getConstArray();
2835 :
2836 0 : Sequence<sal_uInt16> aSlots = getSupportedGridSlots();
2837 0 : const sal_uInt16* pSlots = aSlots.getConstArray();
2838 :
2839 : DBG_ASSERT(aSlots.getLength() == aUrls.getLength(), "FmXGridPeer::OnExecuteGridSlot : inconstent data returned by getSupportedURLs/getSupportedGridSlots !");
2840 :
2841 0 : sal_uInt16 nSlot = (sal_uInt16)reinterpret_cast<sal_uIntPtr>(pSlot);
2842 0 : for (sal_Int32 i=0; i<aSlots.getLength(); ++i, ++pUrls, ++pSlots)
2843 : {
2844 0 : if (*pSlots == nSlot)
2845 : {
2846 0 : if (m_pDispatchers[i].is())
2847 : {
2848 : // commit any changes done so far, if it's not the undoRecord URL
2849 0 : if ( pUrls->Complete == FMURL_RECORD_UNDO || commit() )
2850 0 : m_pDispatchers[i]->dispatch(*pUrls, Sequence< PropertyValue>());
2851 :
2852 0 : return 1; // handled
2853 : }
2854 : }
2855 : }
2856 :
2857 0 : return 0; // not handled
2858 435 : }
2859 :
2860 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|