Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / svx / source / fmcomp / fmgridif.cxx
blob343ad110a2a582a12c480f3839a05b7b01e44e1e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
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/lang/NoSupportException.hpp>
40 #include <com/sun/star/sdbc/ResultSetType.hpp>
41 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
42 #include <com/sun/star/util/URLTransformer.hpp>
43 #include <com/sun/star/util/XURLTransformer.hpp>
44 #include <com/sun/star/view/XSelectionSupplier.hpp>
45 #include <com/sun/star/sdbcx/XRowLocate.hpp>
47 #include <comphelper/container.hxx>
48 #include <comphelper/enumhelper.hxx>
49 #include <comphelper/processfactory.hxx>
50 #include <comphelper/property.hxx>
51 #include <comphelper/sequence.hxx>
52 #include <comphelper/servicehelper.hxx>
53 #include <comphelper/types.hxx>
54 #include <cppuhelper/supportsservice.hxx>
55 #include <cppuhelper/typeprovider.hxx>
56 #include <cppuhelper/queryinterface.hxx>
57 #include <vcl/unohelp.hxx>
58 #include <tools/diagnose_ex.h>
59 #include <sal/macros.h>
61 using namespace ::svxform;
62 using namespace ::com::sun::star::container;
63 using namespace ::com::sun::star::sdb;
64 using namespace ::com::sun::star::sdbc;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::view;
67 using namespace ::com::sun::star::beans;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::form;
70 using namespace ::com::sun::star::util;
71 using namespace ::com::sun::star;
73 using ::com::sun::star::sdbcx::XColumnsSupplier;
74 using ::com::sun::star::frame::XDispatchProviderInterceptor;
75 using ::com::sun::star::frame::XDispatchProvider;
76 using ::com::sun::star::accessibility::XAccessible;
77 using ::com::sun::star::accessibility::XAccessibleContext;
78 using ::com::sun::star::sdb::XRowSetSupplier;
79 using ::com::sun::star::awt::XVclWindowPeer;
82 css::awt::FontDescriptor ImplCreateFontDescriptor( const vcl::Font& rFont )
84 css::awt::FontDescriptor aFD;
85 aFD.Name = rFont.GetFamilyName();
86 aFD.StyleName = rFont.GetStyleName();
87 aFD.Height = (sal_Int16)rFont.GetFontSize().Height();
88 aFD.Width = (sal_Int16)rFont.GetFontSize().Width();
89 aFD.Family = (sal_Int16)rFont.GetFamilyType();
90 aFD.CharSet = rFont.GetCharSet();
91 aFD.Pitch = (sal_Int16)rFont.GetPitch();
92 aFD.CharacterWidth = vcl::unohelper::ConvertFontWidth( rFont.GetWidthType() );
93 aFD.Weight= vcl::unohelper::ConvertFontWeight( rFont.GetWeight() );
94 aFD.Slant = vcl::unohelper::ConvertFontSlant( rFont.GetItalic() );
95 aFD.Underline = (sal_Int16)rFont.GetUnderline();
96 aFD.Strikeout = (sal_Int16)rFont.GetStrikeout();
97 aFD.Orientation = rFont.GetOrientation();
98 aFD.Kerning = rFont.IsKerning();
99 aFD.WordLineMode = rFont.IsWordLineMode();
100 aFD.Type = 0; // ??? => only to metric...
101 return aFD;
105 vcl::Font ImplCreateFont( const css::awt::FontDescriptor& rDescr )
107 vcl::Font aFont;
108 aFont.SetFamilyName( rDescr.Name );
109 aFont.SetStyleName( rDescr.StyleName );
110 aFont.SetFontSize( ::Size( rDescr.Width, rDescr.Height ) );
111 aFont.SetFamily( (FontFamily)rDescr.Family );
112 aFont.SetCharSet( (rtl_TextEncoding)rDescr.CharSet );
113 aFont.SetPitch( (FontPitch)rDescr.Pitch );
114 aFont.SetWidthType( vcl::unohelper::ConvertFontWidth( rDescr.CharacterWidth ) );
115 aFont.SetWeight( vcl::unohelper::ConvertFontWeight( rDescr.Weight ) );
116 aFont.SetItalic( (FontItalic)rDescr.Slant );
117 aFont.SetUnderline( (::FontLineStyle)rDescr.Underline );
118 aFont.SetStrikeout( (::FontStrikeout)rDescr.Strikeout );
119 aFont.SetOrientation( (sal_Int16)rDescr.Orientation );
120 aFont.SetKerning( static_cast<FontKerning>(rDescr.Kerning) );
121 aFont.SetWordLineMode( rDescr.WordLineMode );
122 return aFont;
125 FmXModifyMultiplexer::FmXModifyMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
126 :OWeakSubObject( rSource )
127 ,OInterfaceContainerHelper2( _rMutex )
132 Any SAL_CALL FmXModifyMultiplexer::queryInterface(const Type& _rType)
134 Any aReturn;
135 aReturn = ::cppu::queryInterface(_rType,
136 static_cast< css::util::XModifyListener*>(this),
137 static_cast< XEventListener*>(this)
140 if (!aReturn.hasValue())
141 aReturn = OWeakSubObject::queryInterface( _rType );
143 return aReturn;
147 void FmXModifyMultiplexer::disposing(const EventObject& )
152 void FmXModifyMultiplexer::modified(const EventObject& e)
154 EventObject aMulti( e);
155 aMulti.Source = &m_rParent;
156 notifyEach( &XModifyListener::modified, aMulti );
159 FmXUpdateMultiplexer::FmXUpdateMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
160 :OWeakSubObject( rSource )
161 ,OInterfaceContainerHelper2( _rMutex )
166 Any SAL_CALL FmXUpdateMultiplexer::queryInterface(const Type& _rType)
168 Any aReturn;
169 aReturn = ::cppu::queryInterface(_rType,
170 static_cast< XUpdateListener*>(this),
171 static_cast< XEventListener*>(this)
174 if (!aReturn.hasValue())
175 aReturn = OWeakSubObject::queryInterface( _rType );
177 return aReturn;
181 void FmXUpdateMultiplexer::disposing(const EventObject& )
186 sal_Bool FmXUpdateMultiplexer::approveUpdate(const EventObject &e)
188 EventObject aMulti( e );
189 aMulti.Source = &m_rParent;
191 bool bResult = true;
192 if (getLength())
194 ::comphelper::OInterfaceIteratorHelper2 aIter(*this);
195 while ( bResult && aIter.hasMoreElements() )
196 bResult = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aMulti );
199 return bResult;
203 void FmXUpdateMultiplexer::updated(const EventObject &e)
205 EventObject aMulti( e );
206 aMulti.Source = &m_rParent;
207 notifyEach( &XUpdateListener::updated, aMulti );
210 FmXSelectionMultiplexer::FmXSelectionMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
211 :OWeakSubObject( rSource )
212 ,OInterfaceContainerHelper2( _rMutex )
217 Any SAL_CALL FmXSelectionMultiplexer::queryInterface(const Type& _rType)
219 Any aReturn;
220 aReturn = ::cppu::queryInterface(_rType,
221 static_cast< XSelectionChangeListener*>(this),
222 static_cast< XEventListener*>(this)
225 if (!aReturn.hasValue())
226 aReturn = OWeakSubObject::queryInterface( _rType );
228 return aReturn;
232 void FmXSelectionMultiplexer::disposing(const EventObject& )
237 void SAL_CALL FmXSelectionMultiplexer::selectionChanged( const EventObject& _rEvent )
239 EventObject aMulti(_rEvent);
240 aMulti.Source = &m_rParent;
241 notifyEach( &XSelectionChangeListener::selectionChanged, aMulti );
244 FmXContainerMultiplexer::FmXContainerMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
245 :OWeakSubObject( rSource )
246 ,OInterfaceContainerHelper2( _rMutex )
251 Any SAL_CALL FmXContainerMultiplexer::queryInterface(const Type& _rType)
253 Any aReturn;
254 aReturn = ::cppu::queryInterface(_rType,
255 static_cast< XContainerListener*>(this),
256 static_cast< XEventListener*>(this)
259 if (!aReturn.hasValue())
260 aReturn = OWeakSubObject::queryInterface( _rType );
262 return aReturn;
266 void FmXContainerMultiplexer::disposing(const EventObject& )
270 void FmXContainerMultiplexer::elementInserted(const ContainerEvent& e)
272 ContainerEvent aMulti( e );
273 aMulti.Source = &m_rParent;
274 notifyEach( &XContainerListener::elementInserted, aMulti );
278 void FmXContainerMultiplexer::elementRemoved(const ContainerEvent& e)
280 ContainerEvent aMulti( e );
281 aMulti.Source = &m_rParent;
282 notifyEach( &XContainerListener::elementRemoved, aMulti );
286 void FmXContainerMultiplexer::elementReplaced(const ContainerEvent& e)
288 ContainerEvent aMulti( e );
289 aMulti.Source = &m_rParent;
290 notifyEach( &XContainerListener::elementReplaced, aMulti );
293 FmXGridControlMultiplexer::FmXGridControlMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
294 :OWeakSubObject( rSource )
295 ,OInterfaceContainerHelper2( _rMutex )
300 Any SAL_CALL FmXGridControlMultiplexer::queryInterface(const Type& _rType)
302 Any aReturn;
303 aReturn = ::cppu::queryInterface( _rType,
304 static_cast< XGridControlListener*>(this)
307 if (!aReturn.hasValue())
308 aReturn = OWeakSubObject::queryInterface( _rType );
310 return aReturn;
314 void FmXGridControlMultiplexer::disposing( const EventObject& )
319 void SAL_CALL FmXGridControlMultiplexer::columnChanged( const EventObject& _event )
321 EventObject aForwardedEvent( _event );
322 aForwardedEvent.Source = &m_rParent;
323 notifyEach( &XGridControlListener::columnChanged, aForwardedEvent );
327 //= FmXGridControl
330 Reference< XInterface > SAL_CALL FmXGridControl_NewInstance_Impl(const Reference< XMultiServiceFactory>& _rxFactory)
332 return *(new FmXGridControl( comphelper::getComponentContext(_rxFactory) ));
335 FmXGridControl::FmXGridControl(const Reference< XComponentContext >& _rxContext)
336 :UnoControl()
337 ,m_aModifyListeners(*this, GetMutex())
338 ,m_aUpdateListeners(*this, GetMutex())
339 ,m_aContainerListeners(*this, GetMutex())
340 ,m_aSelectionListeners(*this, GetMutex())
341 ,m_aGridControlListeners(*this, GetMutex())
342 ,m_bInDraw(false)
343 ,m_xContext(_rxContext)
348 FmXGridControl::~FmXGridControl()
353 Any SAL_CALL FmXGridControl::queryAggregation(const Type& _rType)
355 Any aReturn = FmXGridControl_BASE::queryInterface(_rType);
357 if (!aReturn.hasValue())
358 aReturn = UnoControl::queryAggregation( _rType );
359 return aReturn;
363 Sequence< Type> SAL_CALL FmXGridControl::getTypes( )
365 return comphelper::concatSequences(UnoControl::getTypes(),FmXGridControl_BASE::getTypes());
369 Sequence<sal_Int8> SAL_CALL FmXGridControl::getImplementationId( )
371 return css::uno::Sequence<sal_Int8>();
374 // XServiceInfo
375 sal_Bool SAL_CALL FmXGridControl::supportsService(const OUString& ServiceName)
377 return cppu::supportsService(this, ServiceName);
380 OUString SAL_CALL FmXGridControl::getImplementationName()
382 return OUString("com.sun.star.form.FmXGridControl");
385 css::uno::Sequence<OUString> SAL_CALL FmXGridControl::getSupportedServiceNames()
387 Sequence< OUString > aServiceNames(2);
388 aServiceNames[0] = FM_SUN_CONTROL_GRIDCONTROL;
389 aServiceNames[1] = "com.sun.star.awt.UnoControl";
390 return aServiceNames;
394 void SAL_CALL FmXGridControl::dispose()
396 SolarMutexGuard aGuard;
398 EventObject aEvt;
399 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
400 m_aModifyListeners.disposeAndClear(aEvt);
401 m_aUpdateListeners.disposeAndClear(aEvt);
402 m_aContainerListeners.disposeAndClear(aEvt);
404 UnoControl::dispose();
408 OUString FmXGridControl::GetComponentServiceName()
410 OUString aName("DBGrid");
411 return aName;
415 sal_Bool SAL_CALL FmXGridControl::setModel(const Reference< css::awt::XControlModel >& rModel)
417 SolarMutexGuard aGuard;
419 if (!UnoControl::setModel(rModel))
420 return false;
422 Reference< XGridPeer > xGridPeer(getPeer(), UNO_QUERY);
423 if (xGridPeer.is())
425 Reference< XIndexContainer > xCols(mxModel, UNO_QUERY);
426 xGridPeer->setColumns(xCols);
428 return true;
432 FmXGridPeer* FmXGridControl::imp_CreatePeer(vcl::Window* pParent)
434 FmXGridPeer* pReturn = new FmXGridPeer(m_xContext);
436 // translate properties into WinBits
437 WinBits nStyle = WB_TABSTOP;
438 Reference< XPropertySet > xModelSet(getModel(), UNO_QUERY);
439 if (xModelSet.is())
443 if (::comphelper::getINT16(xModelSet->getPropertyValue(FM_PROP_BORDER)))
444 nStyle |= WB_BORDER;
446 catch(const Exception&)
448 OSL_FAIL("Can not get style");
452 pReturn->Create(pParent, nStyle);
453 return pReturn;
457 void SAL_CALL FmXGridControl::createPeer(const Reference< css::awt::XToolkit >& /*rToolkit*/, const Reference< css::awt::XWindowPeer >& rParentPeer)
459 if ( !mxModel.is() )
460 throw DisposedException( OUString(), *this );
462 DBG_ASSERT(/*(0 == m_nPeerCreationLevel) && */!mbCreatingPeer, "FmXGridControl::createPeer : recursion!");
463 // I think this should never assert, now that we're using the base class' mbCreatingPeer in addition to
464 // our own m_nPeerCreationLevel
465 // But I'm not sure as I don't _fully_ understand the underlying toolkit implementations ....
466 // (if this asserts, we still need m_nPeerCreationLevel. If not, we could omit it ....)
467 // 14.05.2001 - 86836 - frank.schoenheit@germany.sun.com
469 // TODO: why the hell this whole class does not use any mutex?
471 if (!getPeer().is())
473 mbCreatingPeer = true;
474 // mbCreatingPeer is virtually the same as m_nPeerCreationLevel, but it's the base class' method
475 // to prevent recursion.
477 vcl::Window* pParentWin = nullptr;
478 if (rParentPeer.is())
480 VCLXWindow* pParent = VCLXWindow::GetImplementation(rParentPeer);
481 if (pParent)
482 pParentWin = pParent->GetWindow().get();
485 FmXGridPeer* pPeer = imp_CreatePeer(pParentWin);
486 DBG_ASSERT(pPeer != nullptr, "FmXGridControl::createPeer : imp_CreatePeer didn't return a peer !");
487 setPeer( pPeer );
489 // reading the properties from the model
490 // ++m_nPeerCreationLevel;
491 updateFromModel();
493 // consider the following ugly scenario: updateFromModel leads to a propertiesChanges on the Control,
494 // which determines, dat a "critical" property has changed (e.g. "Border") and therefore starts a new
495 // Peer, which lands again here in createPeer we also start a second FmXGridPeer and initialise it.
496 // Then we exit from the first incarnation's updateFromModel and continue working with the pPeer,
497 // that is in fact now already obsolete (as another peer is being started in the second incarnation).
498 // Therefore the effort with the PeerCreationLevel, which ensures that we really use the Peer
499 // created at the deepest level, but first initialise it in the top-level.
500 // if (--m_nPeerCreationLevel == 0)
502 DBG_ASSERT(getPeer().is(), "FmXGridControl::createPeer : something went wrong ... no top level peer !");
503 pPeer = FmXGridPeer::getImplementation(getPeer());
505 setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, css::awt::PosSize::POSSIZE );
507 Reference< XIndexContainer > xColumns(getModel(), UNO_QUERY);
508 if (xColumns.is())
509 pPeer->setColumns(xColumns);
511 if (maComponentInfos.bVisible)
512 pPeer->setVisible(true);
514 if (!maComponentInfos.bEnable)
515 pPeer->setEnable(false);
517 if (maWindowListeners.getLength())
518 pPeer->addWindowListener( &maWindowListeners );
520 if (maFocusListeners.getLength())
521 pPeer->addFocusListener( &maFocusListeners );
523 if (maKeyListeners.getLength())
524 pPeer->addKeyListener( &maKeyListeners );
526 if (maMouseListeners.getLength())
527 pPeer->addMouseListener( &maMouseListeners );
529 if (maMouseMotionListeners.getLength())
530 pPeer->addMouseMotionListener( &maMouseMotionListeners );
532 if (maPaintListeners.getLength())
533 pPeer->addPaintListener( &maPaintListeners );
535 if (m_aModifyListeners.getLength())
536 pPeer->addModifyListener( &m_aModifyListeners );
538 if (m_aUpdateListeners.getLength())
539 pPeer->addUpdateListener( &m_aUpdateListeners );
541 if (m_aContainerListeners.getLength())
542 pPeer->addContainerListener( &m_aContainerListeners );
544 // forward the design mode
545 bool bForceAlivePeer = m_bInDraw && !maComponentInfos.bVisible;
546 // (we force an alive-mode peer if we're in "draw", cause in this case the peer will be used for drawing in
547 // foreign devices. We ensure this with the visibility check as an living peer is assumed to be noncritical
548 // only if invisible)
549 Any aOldCursorBookmark;
550 if (!mbDesignMode || bForceAlivePeer)
552 Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
553 if (xComp.is())
555 Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY);
556 // is the form alive?
557 // we can see that if the form contains columns
558 Reference< css::sdbcx::XColumnsSupplier > xColumnsSupplier(xForm, UNO_QUERY);
559 if (xColumnsSupplier.is())
561 if (Reference< XIndexAccess > (xColumnsSupplier->getColumns(),UNO_QUERY)->getCount())
563 // we get only a new bookmark if the resultset is not forwardonly
564 if (::comphelper::getINT32(Reference< XPropertySet > (xForm, UNO_QUERY)->getPropertyValue(FM_PROP_RESULTSET_TYPE)) != ResultSetType::FORWARD_ONLY)
566 // as the FmGridControl touches the data source it is connected to we have to remember the current
567 // cursor position (and restore afterwards)
568 // OJ: but only when we stand on a valid row
569 Reference< XResultSet > xResultSet(xForm, UNO_QUERY);
570 if ( !xResultSet->isBeforeFirst() && !xResultSet->isAfterLast() )
574 aOldCursorBookmark = Reference< css::sdbcx::XRowLocate > (xForm, UNO_QUERY)->getBookmark();
576 catch( const Exception& e )
578 DBG_UNHANDLED_EXCEPTION();
579 (void)e;
585 pPeer->setRowSet(xForm);
588 pPeer->setDesignMode(mbDesignMode && !bForceAlivePeer);
592 if (aOldCursorBookmark.hasValue())
593 { // we have a valid bookmark, so we have to restore the cursor's position
594 Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
595 Reference< css::sdbcx::XRowLocate > xLocate(xComp->getParent(), UNO_QUERY);
596 xLocate->moveToBookmark(aOldCursorBookmark);
599 catch( const Exception& e )
601 DBG_UNHANDLED_EXCEPTION();
602 (void)e;
605 Reference< css::awt::XView > xPeerView(getPeer(), UNO_QUERY);
606 xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY );
607 xPeerView->setGraphics( mxGraphics );
609 mbCreatingPeer = false;
614 void FmXGridControl::addModifyListener(const Reference< css::util::XModifyListener >& l)
616 m_aModifyListeners.addInterface( l );
617 if( getPeer().is() && m_aModifyListeners.getLength() == 1 )
619 Reference< css::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY);
620 xGrid->addModifyListener( &m_aModifyListeners);
625 sal_Bool SAL_CALL FmXGridControl::select( const Any& _rSelection )
627 SolarMutexGuard aGuard;
628 Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY);
629 return xPeer->select(_rSelection);
633 Any SAL_CALL FmXGridControl::getSelection( )
635 SolarMutexGuard aGuard;
636 Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY);
637 return xPeer->getSelection();
641 void SAL_CALL FmXGridControl::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener )
643 m_aSelectionListeners.addInterface( _rxListener );
644 if( getPeer().is() && 1 == m_aSelectionListeners.getLength() )
646 Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY);
647 xGrid->addSelectionChangeListener( &m_aSelectionListeners);
652 void SAL_CALL FmXGridControl::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener )
654 if( getPeer().is() && 1 == m_aSelectionListeners.getLength() )
656 Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY);
657 xGrid->removeSelectionChangeListener( &m_aSelectionListeners);
659 m_aSelectionListeners.removeInterface( _rxListener );
663 Sequence< sal_Bool > SAL_CALL FmXGridControl::queryFieldDataType( const Type& xType )
665 if (getPeer().is())
667 Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY);
668 if (xPeerSupplier.is())
669 return xPeerSupplier->queryFieldDataType(xType);
672 return Sequence<sal_Bool>();
676 Sequence< Any > SAL_CALL FmXGridControl::queryFieldData( sal_Int32 nRow, const Type& xType )
678 if (getPeer().is())
680 Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY);
681 if (xPeerSupplier.is())
682 return xPeerSupplier->queryFieldData(nRow, xType);
685 return Sequence< Any>();
689 void SAL_CALL FmXGridControl::removeModifyListener(const Reference< css::util::XModifyListener >& l)
691 if( getPeer().is() && m_aModifyListeners.getLength() == 1 )
693 Reference< css::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY);
694 xGrid->removeModifyListener( &m_aModifyListeners);
696 m_aModifyListeners.removeInterface( l );
700 void SAL_CALL FmXGridControl::draw( sal_Int32 x, sal_Int32 y )
702 SolarMutexGuard aGuard;
703 m_bInDraw = true;
704 UnoControl::draw(x, y);
705 m_bInDraw = false;
709 void SAL_CALL FmXGridControl::setDesignMode(sal_Bool bOn)
711 css::util::ModeChangeEvent aModeChangeEvent;
713 // --- <mutex_lock> ---
715 SolarMutexGuard aGuard;
717 Reference< XRowSetSupplier > xGrid(getPeer(), UNO_QUERY);
719 if (xGrid.is() && (bool(bOn) != mbDesignMode || (!bOn && !xGrid->getRowSet().is())))
721 if (bOn)
723 xGrid->setRowSet(Reference< XRowSet > ());
725 else
727 Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
728 if (xComp.is())
730 Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY);
731 xGrid->setRowSet(xForm);
735 mbDesignMode = bOn;
737 Reference< XVclWindowPeer > xVclWindowPeer( getPeer(), UNO_QUERY );
738 if (xVclWindowPeer.is())
739 xVclWindowPeer->setDesignMode(bOn);
741 mbDesignMode = bOn;
743 // dispose our current AccessibleContext, if we have one
744 // (changing the design mode implies having a new implementation for this context,
745 // so the old one must be declared DEFUNC)
746 DisposeAccessibleContext(
747 Reference<XComponent>(maAccessibleContext, UNO_QUERY));
748 maAccessibleContext.clear();
750 // prepare firing an event
751 aModeChangeEvent.Source = *this;
752 aModeChangeEvent.NewMode = mbDesignMode ? OUString( "design" ) : OUString( "alive" );
755 // --- </mutex_lock> ---
756 maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
759 // XBoundComponent
761 void SAL_CALL FmXGridControl::addUpdateListener(const Reference< XUpdateListener >& l)
763 m_aUpdateListeners.addInterface( l );
764 if( getPeer().is() && m_aUpdateListeners.getLength() == 1 )
766 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
767 xBound->addUpdateListener( &m_aUpdateListeners);
772 void SAL_CALL FmXGridControl::removeUpdateListener(const Reference< XUpdateListener >& l)
774 if( getPeer().is() && m_aUpdateListeners.getLength() == 1 )
776 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
777 xBound->removeUpdateListener( &m_aUpdateListeners);
779 m_aUpdateListeners.removeInterface( l );
783 sal_Bool SAL_CALL FmXGridControl::commit()
785 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
786 if (xBound.is())
787 return xBound->commit();
788 else
789 return true;
792 // XContainer
794 void SAL_CALL FmXGridControl::addContainerListener(const Reference< XContainerListener >& l)
796 m_aContainerListeners.addInterface( l );
797 if( getPeer().is() && m_aContainerListeners.getLength() == 1 )
799 Reference< XContainer > xContainer(getPeer(), UNO_QUERY);
800 xContainer->addContainerListener( &m_aContainerListeners);
805 void SAL_CALL FmXGridControl::removeContainerListener(const Reference< XContainerListener >& l)
807 if( getPeer().is() && m_aContainerListeners.getLength() == 1 )
809 Reference< XContainer > xContainer(getPeer(), UNO_QUERY);
810 xContainer->removeContainerListener( &m_aContainerListeners);
812 m_aContainerListeners.removeInterface( l );
816 Reference< css::frame::XDispatch > SAL_CALL FmXGridControl::queryDispatch(const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags)
818 Reference< css::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY);
819 if (xPeerProvider.is())
820 return xPeerProvider->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
821 else
822 return Reference< css::frame::XDispatch > ();
826 Sequence< Reference< css::frame::XDispatch > > SAL_CALL FmXGridControl::queryDispatches(const Sequence< css::frame::DispatchDescriptor>& aDescripts)
828 Reference< css::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY);
829 if (xPeerProvider.is())
830 return xPeerProvider->queryDispatches(aDescripts);
831 else
832 return Sequence< Reference< css::frame::XDispatch > >();
836 void SAL_CALL FmXGridControl::registerDispatchProviderInterceptor(const Reference< css::frame::XDispatchProviderInterceptor >& _xInterceptor)
838 Reference< css::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY);
839 if (xPeerInterception.is())
840 xPeerInterception->registerDispatchProviderInterceptor(_xInterceptor);
844 void SAL_CALL FmXGridControl::releaseDispatchProviderInterceptor(const Reference< css::frame::XDispatchProviderInterceptor >& _xInterceptor)
846 Reference< css::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY);
847 if (xPeerInterception.is())
848 xPeerInterception->releaseDispatchProviderInterceptor(_xInterceptor);
852 void SAL_CALL FmXGridControl::addGridControlListener( const Reference< XGridControlListener >& _listener )
854 ::osl::MutexGuard aGuard( GetMutex() );
856 m_aGridControlListeners.addInterface( _listener );
857 if ( getPeer().is() && 1 == m_aGridControlListeners.getLength() )
859 Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY );
860 if ( xPeerGrid.is() )
861 xPeerGrid->addGridControlListener( &m_aGridControlListeners );
866 void SAL_CALL FmXGridControl::removeGridControlListener( const Reference< XGridControlListener >& _listener )
868 ::osl::MutexGuard aGuard( GetMutex() );
870 if( getPeer().is() && 1 == m_aGridControlListeners.getLength() )
872 Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY );
873 if ( xPeerGrid.is() )
874 xPeerGrid->removeGridControlListener( &m_aGridControlListeners );
877 m_aGridControlListeners.removeInterface( _listener );
881 sal_Int16 SAL_CALL FmXGridControl::getCurrentColumnPosition()
883 Reference< XGridControl > xGrid( getPeer(), UNO_QUERY );
884 return xGrid.is() ? xGrid->getCurrentColumnPosition() : -1;
888 void SAL_CALL FmXGridControl::setCurrentColumnPosition(sal_Int16 nPos)
890 Reference< XGridControl > xGrid( getPeer(), UNO_QUERY );
891 if ( xGrid.is() )
893 SolarMutexGuard aGuard;
894 xGrid->setCurrentColumnPosition( nPos );
898 // XElementAccess
900 sal_Bool SAL_CALL FmXGridControl::hasElements()
902 Reference< XElementAccess > xPeer(getPeer(), UNO_QUERY);
903 return xPeer.is() && xPeer->hasElements();
907 Type SAL_CALL FmXGridControl::getElementType( )
909 return cppu::UnoType<css::awt::XTextComponent>::get();
912 // XEnumerationAccess
914 Reference< XEnumeration > SAL_CALL FmXGridControl::createEnumeration()
916 Reference< XEnumerationAccess > xPeer(getPeer(), UNO_QUERY);
917 if (xPeer.is())
918 return xPeer->createEnumeration();
919 else
920 return new ::comphelper::OEnumerationByIndex(this);
923 // XIndexAccess
925 sal_Int32 SAL_CALL FmXGridControl::getCount()
927 Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY);
928 return xPeer.is() ? xPeer->getCount() : 0;
932 Any SAL_CALL FmXGridControl::getByIndex(sal_Int32 _nIndex)
934 Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY);
935 if (!xPeer.is())
936 throw IndexOutOfBoundsException();
938 return xPeer->getByIndex(_nIndex);
941 // css::util::XModeSelector
943 void SAL_CALL FmXGridControl::setMode(const OUString& Mode)
945 Reference< css::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
946 if (!xPeer.is())
947 throw NoSupportException();
949 xPeer->setMode(Mode);
953 OUString SAL_CALL FmXGridControl::getMode()
955 Reference< css::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
956 return xPeer.is() ? xPeer->getMode() : OUString();
960 css::uno::Sequence<OUString> SAL_CALL FmXGridControl::getSupportedModes()
962 Reference< css::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
963 return xPeer.is() ? xPeer->getSupportedModes() : css::uno::Sequence<OUString>();
967 sal_Bool SAL_CALL FmXGridControl::supportsMode(const OUString& Mode)
969 Reference< css::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
970 return xPeer.is() && xPeer->supportsMode(Mode);
973 // helper class which prevents that in the peer's header the FmGridListener must be known
974 class FmXGridPeer::GridListenerDelegator : public FmGridListener
976 protected:
977 FmXGridPeer* m_pPeer;
979 public:
980 explicit GridListenerDelegator( FmXGridPeer* _pPeer );
981 virtual ~GridListenerDelegator();
983 protected:
984 virtual void selectionChanged() override;
985 virtual void columnChanged() override;
989 FmXGridPeer::GridListenerDelegator::GridListenerDelegator(FmXGridPeer* _pPeer)
990 :m_pPeer(_pPeer)
992 DBG_ASSERT(m_pPeer, "GridListenerDelegator::GridListenerDelegator");
995 FmXGridPeer::GridListenerDelegator::~GridListenerDelegator()
1000 void FmXGridPeer::GridListenerDelegator::selectionChanged()
1002 m_pPeer->selectionChanged();
1006 void FmXGridPeer::GridListenerDelegator::columnChanged()
1008 m_pPeer->columnChanged();
1011 void FmXGridPeer::selectionChanged()
1013 EventObject aSource;
1014 aSource.Source = static_cast< ::cppu::OWeakObject* >(this);
1015 m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aSource);
1019 void FmXGridPeer::columnChanged()
1021 EventObject aEvent( *this );
1022 m_aGridControlListeners.notifyEach( &XGridControlListener::columnChanged, aEvent );
1026 namespace fmgridif
1028 const OUString getDataModeIdentifier()
1030 return OUString("DataMode");
1033 using namespace fmgridif;
1036 FmXGridPeer::FmXGridPeer(const Reference< XComponentContext >& _rxContext)
1037 :m_aModifyListeners(m_aMutex)
1038 ,m_aUpdateListeners(m_aMutex)
1039 ,m_aContainerListeners(m_aMutex)
1040 ,m_aSelectionListeners(m_aMutex)
1041 ,m_aGridControlListeners(m_aMutex)
1042 ,m_aMode( getDataModeIdentifier() )
1043 ,m_nCursorListening(0)
1044 ,m_bInterceptingDispatch(false)
1045 ,m_pStateCache(nullptr)
1046 ,m_pDispatchers(nullptr)
1047 ,m_pGridListener(nullptr)
1048 ,m_xContext(_rxContext)
1050 // Create must be called after this constructor
1051 m_pGridListener = new GridListenerDelegator( this );
1055 VclPtr<FmGridControl> FmXGridPeer::imp_CreateControl(vcl::Window* pParent, WinBits nStyle)
1057 return VclPtr<FmGridControl>::Create(m_xContext, pParent, this, nStyle);
1061 void FmXGridPeer::Create(vcl::Window* pParent, WinBits nStyle)
1063 VclPtr<FmGridControl> pWin = imp_CreateControl(pParent, nStyle);
1064 DBG_ASSERT(pWin != nullptr, "FmXGridPeer::Create : imp_CreateControl didn't return a control !");
1066 pWin->SetStateProvider(LINK(this, FmXGridPeer, OnQueryGridSlotState));
1067 pWin->SetSlotExecutor(LINK(this, FmXGridPeer, OnExecuteGridSlot));
1069 // want to hear about row selections
1070 pWin->setGridListener( m_pGridListener );
1072 // Init must always be called
1073 pWin->Init();
1074 pWin->SetComponentInterface(this);
1076 getSupportedURLs();
1080 FmXGridPeer::~FmXGridPeer()
1082 setRowSet(Reference< XRowSet > ());
1083 setColumns(Reference< XIndexContainer > ());
1085 delete m_pGridListener;
1088 namespace
1090 class theFmXGridPeerImplementationId : public rtl::Static< UnoTunnelIdInit, theFmXGridPeerImplementationId > {};
1093 const Sequence< sal_Int8 >& FmXGridPeer::getUnoTunnelImplementationId() throw()
1095 return theFmXGridPeerImplementationId::get().getSeq();
1099 FmXGridPeer* FmXGridPeer::getImplementation( const Reference< XInterface >& _rxIFace ) throw()
1101 FmXGridPeer* pReturn = nullptr;
1102 Reference< XUnoTunnel > xTunnel(_rxIFace, UNO_QUERY);
1103 if (xTunnel.is())
1104 pReturn = reinterpret_cast<FmXGridPeer*>(xTunnel->getSomething(getUnoTunnelImplementationId()));
1106 return pReturn;
1110 sal_Int64 SAL_CALL FmXGridPeer::getSomething( const Sequence< sal_Int8 >& _rIdentifier )
1112 sal_Int64 nReturn(0);
1114 if ( (_rIdentifier.getLength() == 16)
1115 && (0 == memcmp( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ))
1118 nReturn = reinterpret_cast<sal_Int64>(this);
1120 else
1121 nReturn = VCLXWindow::getSomething(_rIdentifier);
1123 return nReturn;
1126 // XEventListener
1128 void FmXGridPeer::disposing(const EventObject& e)
1130 using namespace ::com::sun::star::util;
1131 bool bKnownSender = false;
1133 Reference< XIndexContainer > xCols( e.Source, UNO_QUERY );
1134 if ( xCols.is() )
1136 setColumns(Reference< XIndexContainer > ());
1137 bKnownSender = true;
1140 Reference< XRowSet > xCursor(e.Source, UNO_QUERY);
1141 if (xCursor.is())
1143 setRowSet( m_xCursor );
1144 m_xCursor = nullptr;
1145 bKnownSender = true;
1149 if ( !bKnownSender && m_pDispatchers )
1151 const Sequence< URL>& aSupportedURLs = getSupportedURLs();
1152 const URL* pSupportedURLs = aSupportedURLs.getConstArray();
1153 for ( sal_Int32 i=0; i < ( aSupportedURLs.getLength() ) && !bKnownSender; ++i, ++pSupportedURLs )
1155 if ( m_pDispatchers[i] == e.Source )
1157 m_pDispatchers[i]->removeStatusListener( static_cast< css::frame::XStatusListener* >( this ), *pSupportedURLs );
1158 m_pDispatchers[i] = nullptr;
1159 m_pStateCache[i] = false;
1160 bKnownSender = true;
1165 if ( !bKnownSender )
1166 VCLXWindow::disposing(e);
1170 void FmXGridPeer::addModifyListener(const Reference< css::util::XModifyListener >& l)
1172 m_aModifyListeners.addInterface( l );
1176 void FmXGridPeer::removeModifyListener(const Reference< css::util::XModifyListener >& l)
1178 m_aModifyListeners.removeInterface( l );
1182 #define LAST_KNOWN_TYPE FormComponentType::PATTERNFIELD
1183 Sequence< sal_Bool > SAL_CALL FmXGridPeer::queryFieldDataType( const Type& xType )
1185 // a 'conversion table'
1186 static const bool bCanConvert[LAST_KNOWN_TYPE][4] =
1188 { false, false, false, false }, // FormComponentType::CONTROL
1189 { false, false, false, false }, // FormComponentType::COMMANDBUTTON
1190 { false, false, false, false }, // FormComponentType::RADIOBUTTON
1191 { false, false, false, false }, // FormComponentType::IMAGEBUTTON
1192 { false, false, false, true }, // FormComponentType::CHECKBOX
1193 { false, false, false, false }, // FormComponentType::LISTBOX
1194 { false, false, false, false }, // FormComponentType::COMBOBOX
1195 { false, false, false, false }, // FormComponentType::GROUPBOX
1196 { true , false, false, false }, // FormComponentType::TEXTFIELD
1197 { false, false, false, false }, // FormComponentType::FIXEDTEXT
1198 { false, false, false, false }, // FormComponentType::GRIDCONTROL
1199 { false, false, false, false }, // FormComponentType::FILECONTROL
1200 { false, false, false, false }, // FormComponentType::HIDDENCONTROL
1201 { false, false, false, false }, // FormComponentType::IMAGECONTROL
1202 { true , true , true , false }, // FormComponentType::DATEFIELD
1203 { true , true , false, false }, // FormComponentType::TIMEFIELD
1204 { true , true , false, false }, // FormComponentType::NUMERICFIELD
1205 { true , true , false, false }, // FormComponentType::CURRENCYFIELD
1206 { true , false, false, false } // FormComponentType::PATTERNFIELD
1210 sal_Int16 nMapColumn = -1;
1211 switch (xType.getTypeClass())
1213 case TypeClass_STRING : nMapColumn = 0; break;
1214 case TypeClass_FLOAT:
1215 case TypeClass_DOUBLE : nMapColumn = 1; break;
1216 case TypeClass_SHORT:
1217 case TypeClass_LONG:
1218 case TypeClass_UNSIGNED_LONG:
1219 case TypeClass_UNSIGNED_SHORT : nMapColumn = 2; break;
1220 case TypeClass_BOOLEAN : nMapColumn = 3; break;
1221 default:
1222 break;
1225 Reference< XIndexContainer > xColumns = getColumns();
1227 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1228 sal_Int32 nColumns = pGrid->GetViewColCount();
1230 DbGridColumns aColumns = pGrid->GetColumns();
1232 Sequence<sal_Bool> aReturnSequence(nColumns);
1233 sal_Bool* pReturnArray = aReturnSequence.getArray();
1235 bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY);
1237 DbGridColumn* pCol;
1238 Reference< css::sdb::XColumn > xFieldContent;
1239 Reference< XPropertySet > xCurrentColumn;
1240 for (sal_Int32 i=0; i<nColumns; ++i)
1242 if (bRequestedAsAny)
1244 pReturnArray[i] = true;
1245 continue;
1248 pReturnArray[i] = false;
1250 sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i));
1251 DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldDataType : no model pos !");
1253 pCol = aColumns[ nModelPos ];
1254 const DbGridRowRef xRow = pGrid->GetSeekRow();
1255 xFieldContent = (xRow.is() && xRow->HasField(pCol->GetFieldPos())) ? xRow->GetField(pCol->GetFieldPos()).getColumn() : Reference< css::sdb::XColumn > ();
1256 if (!xFieldContent.is())
1257 // can't supply anything without a field content
1258 // FS - 07.12.99 - 54391
1259 continue;
1261 xColumns->getByIndex(nModelPos) >>= xCurrentColumn;
1262 if (!::comphelper::hasProperty(FM_PROP_CLASSID, xCurrentColumn))
1263 continue;
1265 sal_Int16 nClassId = sal_Int16();
1266 xCurrentColumn->getPropertyValue(FM_PROP_CLASSID) >>= nClassId;
1267 if (nClassId>LAST_KNOWN_TYPE)
1268 continue;
1269 DBG_ASSERT(nClassId>0, "FmXGridPeer::queryFieldDataType : somebody changed the definition of the FormComponentType enum !");
1271 if (nMapColumn != -1)
1272 pReturnArray[i] = bCanConvert[nClassId-1][nMapColumn];
1275 return aReturnSequence;
1279 Sequence< Any > SAL_CALL FmXGridPeer::queryFieldData( sal_Int32 nRow, const Type& xType )
1281 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1282 DBG_ASSERT(pGrid && pGrid->IsOpen(), "FmXGridPeer::queryFieldData : have no valid grid window !");
1283 if (!pGrid || !pGrid->IsOpen())
1284 return Sequence< Any>();
1286 // move the control to the specified row
1287 if (!pGrid->SeekRow(nRow))
1289 throw IllegalArgumentException();
1292 // don't use GetCurrentRow as this isn't affected by the above SeekRow
1293 // FS - 30.09.99 - 68644
1294 DbGridRowRef xPaintRow = pGrid->GetPaintRow();
1295 ENSURE_OR_THROW( xPaintRow.is(), "invalid paint row" );
1297 // I need the columns of the control for GetFieldText
1298 DbGridColumns aColumns = pGrid->GetColumns();
1300 // and through all the columns
1301 sal_Int32 nColumnCount = pGrid->GetViewColCount();
1303 Sequence< Any> aReturnSequence(nColumnCount);
1304 Any* pReturnArray = aReturnSequence.getArray();
1306 bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY);
1307 Reference< css::sdb::XColumn > xFieldContent;
1308 for (sal_Int32 i=0; i < nColumnCount; ++i)
1310 sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i));
1311 DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldData : invalid model pos !");
1313 // don't use GetCurrentFieldValue to determine the field content as this isn't affected by the above SeekRow
1314 // FS - 30.09.99 - 68644
1315 DbGridColumn* pCol = aColumns[ nModelPos ];
1316 xFieldContent = xPaintRow->HasField( pCol->GetFieldPos() )
1317 ? xPaintRow->GetField( pCol->GetFieldPos() ).getColumn()
1318 : Reference< XColumn > ();
1320 if ( !xFieldContent.is() )
1321 continue;
1323 if (bRequestedAsAny)
1325 Reference< XPropertySet > xFieldSet(xFieldContent, UNO_QUERY);
1326 pReturnArray[i] = xFieldSet->getPropertyValue(FM_PROP_VALUE);
1328 else
1330 switch (xType.getTypeClass())
1332 // Strings are dealt with directly by the GetFieldText
1333 case TypeClass_STRING :
1335 OUString sText = aColumns[ nModelPos ]->GetCellText( xPaintRow.get(), pGrid->getNumberFormatter() );
1336 pReturnArray[i] <<= sText;
1338 break;
1339 // everything else is requested in the DatabaseVariant
1340 case TypeClass_FLOAT : pReturnArray[i] <<= xFieldContent->getFloat(); break;
1341 case TypeClass_DOUBLE : pReturnArray[i] <<= xFieldContent->getDouble(); break;
1342 case TypeClass_SHORT : pReturnArray[i] <<= (sal_Int16)xFieldContent->getShort(); break;
1343 case TypeClass_LONG : pReturnArray[i] <<= (sal_Int32)xFieldContent->getLong(); break;
1344 case TypeClass_UNSIGNED_SHORT : pReturnArray[i] <<= (sal_uInt16)xFieldContent->getShort(); break;
1345 case TypeClass_UNSIGNED_LONG : pReturnArray[i] <<= (sal_uInt32)xFieldContent->getLong(); break;
1346 case TypeClass_BOOLEAN : pReturnArray[i] <<= xFieldContent->getBoolean(); break;
1347 default:
1349 throw IllegalArgumentException();
1354 return aReturnSequence;
1358 void FmXGridPeer::CellModified()
1360 EventObject aEvt;
1361 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
1362 m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
1365 // XPropertyChangeListener
1367 void FmXGridPeer::propertyChange(const PropertyChangeEvent& evt)
1369 SolarMutexGuard aGuard;
1370 // want to do a lot of VCL stuff here ...
1371 // this should not be (deadlock) critical, as by definition, every component should release
1372 // any own mutexes before notifying
1374 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1375 if (!pGrid)
1376 return;
1378 // Database event
1379 if (evt.PropertyName == FM_PROP_VALUE || m_xCursor == evt.Source)
1380 pGrid->propertyChange(evt);
1381 else if (pGrid && m_xColumns.is() && m_xColumns->hasElements())
1383 // next find which column has changed
1384 css::uno::Reference<css::uno::XInterface> xCurrent;
1385 sal_Int32 i;
1387 for ( i = 0; i < m_xColumns->getCount(); i++)
1389 xCurrent.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
1390 if (evt.Source == xCurrent)
1391 break;
1394 if (i >= m_xColumns->getCount())
1395 // this is valid because we are listening at the cursor, too (RecordCount, -status, edit mode)
1396 return;
1398 sal_uInt16 nId = pGrid->GetColumnIdFromModelPos((sal_uInt16)i);
1399 bool bInvalidateColumn = false;
1401 if (evt.PropertyName == FM_PROP_LABEL)
1403 OUString aName = ::comphelper::getString(evt.NewValue);
1404 if (aName != pGrid->GetColumnTitle(nId))
1405 pGrid->SetColumnTitle(nId, aName);
1407 else if (evt.PropertyName == FM_PROP_WIDTH)
1409 sal_Int32 nWidth = 0;
1410 if (evt.NewValue.getValueType().getTypeClass() == TypeClass_VOID)
1411 nWidth = pGrid->GetDefaultColumnWidth(pGrid->GetColumnTitle(nId));
1412 // GetDefaultColumnWidth already considered the zoom factor
1413 else
1415 sal_Int32 nTest = 0;
1416 if (evt.NewValue >>= nTest)
1418 nWidth = pGrid->LogicToPixel(Point(nTest,0),MapUnit::Map10thMM).X();
1419 // take the zoom factor into account
1420 nWidth = pGrid->CalcZoom(nWidth);
1423 if (nWidth != (sal_Int32(pGrid->GetColumnWidth(nId))))
1425 if (pGrid->IsEditing())
1427 pGrid->DeactivateCell();
1428 pGrid->ActivateCell();
1430 pGrid->SetColumnWidth(nId, nWidth);
1433 else if (evt.PropertyName == FM_PROP_HIDDEN)
1435 DBG_ASSERT(evt.NewValue.getValueType().getTypeClass() == TypeClass_BOOLEAN,
1436 "FmXGridPeer::propertyChange : the property 'hidden' should be of type boolean !");
1437 if (::comphelper::getBOOL(evt.NewValue))
1438 pGrid->HideColumn(nId);
1439 else
1440 pGrid->ShowColumn(nId);
1442 else if (evt.PropertyName == FM_PROP_ALIGN)
1444 // in design mode it doesn't matter
1445 if (!isDesignMode())
1447 DbGridColumn* pCol = pGrid->GetColumns().at( i );
1449 pCol->SetAlignmentFromModel(-1);
1450 bInvalidateColumn = true;
1453 else if (evt.PropertyName == FM_PROP_FORMATKEY)
1455 if (!isDesignMode())
1456 bInvalidateColumn = true;
1459 // need to invalidate the affected column ?
1460 if (bInvalidateColumn)
1462 bool bWasEditing = pGrid->IsEditing();
1463 if (bWasEditing)
1464 pGrid->DeactivateCell();
1466 ::tools::Rectangle aColRect = pGrid->GetFieldRect(nId);
1467 aColRect.Top() = 0;
1468 aColRect.Bottom() = pGrid->GetSizePixel().Height();
1469 pGrid->Invalidate(aColRect);
1471 if (bWasEditing)
1472 pGrid->ActivateCell();
1477 // XBoundComponent
1479 void FmXGridPeer::addUpdateListener(const Reference< XUpdateListener >& l)
1481 m_aUpdateListeners.addInterface(l);
1485 void FmXGridPeer::removeUpdateListener(const Reference< XUpdateListener >& l)
1487 m_aUpdateListeners.removeInterface(l);
1491 sal_Bool FmXGridPeer::commit()
1493 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1494 if (!m_xCursor.is() || !pGrid)
1495 return true;
1497 EventObject aEvt(static_cast< ::cppu::OWeakObject* >(this));
1498 ::comphelper::OInterfaceIteratorHelper2 aIter(m_aUpdateListeners);
1499 bool bCancel = false;
1500 while (aIter.hasMoreElements() && !bCancel)
1501 if ( !static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvt ) )
1502 bCancel = true;
1504 if (!bCancel)
1505 bCancel = !pGrid->commit();
1507 if (!bCancel)
1508 m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvt );
1509 return !bCancel;
1513 void FmXGridPeer::cursorMoved(const EventObject& _rEvent)
1515 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1516 // we are not interested in move to insert row only in the resetted event
1517 // which is fired after positioning an the insert row
1518 if (pGrid && pGrid->IsOpen() && !::comphelper::getBOOL(Reference< XPropertySet > (_rEvent.Source, UNO_QUERY)->getPropertyValue(FM_PROP_ISNEW)))
1519 pGrid->positioned();
1523 void FmXGridPeer::rowChanged(const EventObject& /*_rEvent*/)
1525 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1526 if (pGrid && pGrid->IsOpen())
1528 if (m_xCursor->rowUpdated() && !pGrid->IsCurrentAppending())
1529 pGrid->RowModified(pGrid->GetCurrentPos());
1530 else if (m_xCursor->rowInserted())
1531 pGrid->inserted();
1536 void FmXGridPeer::rowSetChanged(const EventObject& /*event*/)
1538 // not interested in ...
1539 // (our parent is a form which means we get a loaded or reloaded after this rowSetChanged)
1542 // XLoadListener
1544 void FmXGridPeer::loaded(const EventObject& /*rEvent*/)
1546 updateGrid(m_xCursor);
1550 void FmXGridPeer::unloaded(const EventObject& /*rEvent*/)
1552 updateGrid( Reference< XRowSet > (nullptr) );
1556 void FmXGridPeer::reloading(const EventObject& /*aEvent*/)
1558 // empty the grid
1559 updateGrid( Reference< XRowSet > (nullptr) );
1563 void FmXGridPeer::unloading(const EventObject& /*aEvent*/)
1565 // empty the grid
1566 updateGrid( Reference< XRowSet > (nullptr) );
1570 void FmXGridPeer::reloaded(const EventObject& aEvent)
1573 const sal_Int32 cnt = m_xColumns->getCount();
1574 for(sal_Int32 i=0; i<cnt; ++i)
1576 Reference< XLoadListener> xll(m_xColumns->getByIndex(i), UNO_QUERY);
1577 if(xll.is())
1579 xll->reloaded(aEvent);
1583 updateGrid(m_xCursor);
1586 // XGridPeer
1588 Reference< XIndexContainer > FmXGridPeer::getColumns()
1590 return m_xColumns;
1594 void FmXGridPeer::addColumnListeners(const Reference< XPropertySet >& xCol)
1596 static const OUStringLiteral aPropsListenedTo[] =
1598 FM_PROP_LABEL, FM_PROP_WIDTH, FM_PROP_HIDDEN, FM_PROP_ALIGN,
1599 FM_PROP_FORMATKEY
1602 // as not all properties have to be supported by all columns we have to check this
1603 // before adding a listener
1604 Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo();
1605 for (unsigned i=0; i<SAL_N_ELEMENTS(aPropsListenedTo); ++i)
1607 if ( xInfo->hasPropertyByName( aPropsListenedTo[i] ) )
1609 Property aPropDesc = xInfo->getPropertyByName( aPropsListenedTo[i] );
1610 if ( 0 != ( aPropDesc.Attributes & PropertyAttribute::BOUND ) )
1611 xCol->addPropertyChangeListener( aPropsListenedTo[i], this );
1617 void FmXGridPeer::removeColumnListeners(const Reference< XPropertySet >& xCol)
1619 // the same props as in addColumnListeners ... linux has problems with global static UStrings, so
1620 // we have to do it this way ....
1621 static const OUStringLiteral aPropsListenedTo[] =
1623 FM_PROP_LABEL, FM_PROP_WIDTH, FM_PROP_HIDDEN, FM_PROP_ALIGN,
1624 FM_PROP_FORMATKEY
1627 Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo();
1628 for (const auto & i : aPropsListenedTo)
1629 if (xInfo->hasPropertyByName(i))
1630 xCol->removePropertyChangeListener(i, this);
1634 void FmXGridPeer::setColumns(const Reference< XIndexContainer >& Columns)
1636 SolarMutexGuard aGuard;
1638 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1640 if (m_xColumns.is())
1642 Reference< XPropertySet > xCol;
1643 for (sal_Int32 i = 0; i < m_xColumns->getCount(); i++)
1645 xCol.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
1646 removeColumnListeners(xCol);
1648 Reference< XContainer > xContainer(m_xColumns, UNO_QUERY);
1649 xContainer->removeContainerListener(this);
1651 Reference< XSelectionSupplier > xSelSupplier(m_xColumns, UNO_QUERY);
1652 xSelSupplier->removeSelectionChangeListener(this);
1654 Reference< XReset > xColumnReset(m_xColumns, UNO_QUERY);
1655 if (xColumnReset.is())
1656 xColumnReset->removeResetListener(static_cast<XResetListener*>(this));
1658 if (Columns.is())
1660 Reference< XContainer > xContainer(Columns, UNO_QUERY);
1661 xContainer->addContainerListener(this);
1663 Reference< XSelectionSupplier > xSelSupplier(Columns, UNO_QUERY);
1664 xSelSupplier->addSelectionChangeListener(this);
1666 Reference< XPropertySet > xCol;
1667 for (sal_Int32 i = 0; i < Columns->getCount(); i++)
1669 xCol.set(Columns->getByIndex(i), css::uno::UNO_QUERY);
1670 addColumnListeners(xCol);
1673 Reference< XReset > xColumnReset(Columns, UNO_QUERY);
1674 if (xColumnReset.is())
1675 xColumnReset->addResetListener(static_cast<XResetListener*>(this));
1677 m_xColumns = Columns;
1678 if (pGrid)
1680 pGrid->InitColumnsByModels(m_xColumns);
1682 if (m_xColumns.is())
1684 EventObject aEvt(m_xColumns);
1685 selectionChanged(aEvt);
1691 void FmXGridPeer::setDesignMode(sal_Bool bOn)
1693 if (bOn != isDesignMode())
1695 VclPtr<vcl::Window> pWin = GetWindow();
1696 if (pWin)
1697 static_cast<FmGridControl*>(pWin.get())->SetDesignMode(bOn);
1700 if (bOn)
1701 DisConnectFromDispatcher();
1702 else
1703 UpdateDispatches(); // will connect if not already connected and just update else
1707 sal_Bool FmXGridPeer::isDesignMode()
1709 VclPtr<vcl::Window> pWin = GetWindow();
1710 if (pWin)
1711 return static_cast<FmGridControl*>(pWin.get())->IsDesignMode();
1712 else
1713 return false;
1717 void FmXGridPeer::elementInserted(const ContainerEvent& evt)
1719 SolarMutexGuard aGuard;
1721 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1722 // take handle column into account
1723 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount()))
1724 return;
1726 Reference< XPropertySet > xNewColumn(evt.Element, css::uno::UNO_QUERY);
1727 addColumnListeners(xNewColumn);
1729 OUString aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL));
1730 Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH);
1731 sal_Int32 nWidth = 0;
1732 if (aWidth >>= nWidth)
1733 nWidth = pGrid->LogicToPixel(Point(nWidth,0),MapUnit::Map10thMM).X();
1735 pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor));
1737 // now set the column
1738 DbGridColumn* pCol = pGrid->GetColumns().at( ::comphelper::getINT32(evt.Accessor) );
1739 pCol->setModel(xNewColumn);
1741 Any aHidden = xNewColumn->getPropertyValue(FM_PROP_HIDDEN);
1742 if (::comphelper::getBOOL(aHidden))
1743 pGrid->HideColumn(pCol->GetId());
1745 FormControlFactory( m_xContext ).initializeTextFieldLineEnds( xNewColumn );
1749 void FmXGridPeer::elementReplaced(const ContainerEvent& evt)
1751 SolarMutexGuard aGuard;
1753 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1755 // take handle column into account
1756 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove())
1757 return;
1759 Reference< XPropertySet > xNewColumn(evt.Element, css::uno::UNO_QUERY);
1760 Reference< XPropertySet > xOldColumn(
1761 evt.ReplacedElement, css::uno::UNO_QUERY);
1763 bool bWasEditing = pGrid->IsEditing();
1764 if (bWasEditing)
1765 pGrid->DeactivateCell();
1767 pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor)));
1769 removeColumnListeners(xOldColumn);
1770 addColumnListeners(xNewColumn);
1772 OUString aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL));
1773 Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH);
1774 sal_Int32 nWidth = 0;
1775 if (aWidth >>= nWidth)
1776 nWidth = pGrid->LogicToPixel(Point(nWidth,0),MapUnit::Map10thMM).X();
1777 sal_uInt16 nNewId = pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor));
1778 sal_uInt16 nNewPos = pGrid->GetModelColumnPos(nNewId);
1780 // set the model of the new column
1781 DbGridColumn* pCol = pGrid->GetColumns().at( nNewPos );
1783 // for initializing this grid column, we need the fields of the grid's data source
1784 Reference< XColumnsSupplier > xSuppColumns;
1785 CursorWrapper* pGridDataSource = pGrid->getDataSource();
1786 if ( pGridDataSource )
1787 xSuppColumns.set(Reference< XInterface >( *pGridDataSource ), css::uno::UNO_QUERY);
1788 Reference< XNameAccess > xColumnsByName;
1789 if ( xSuppColumns.is() )
1790 xColumnsByName = xSuppColumns->getColumns();
1791 Reference< XIndexAccess > xColumnsByIndex( xColumnsByName, UNO_QUERY );
1793 if ( xColumnsByIndex.is() )
1794 FmGridControl::InitColumnByField( pCol, xNewColumn, xColumnsByName, xColumnsByIndex );
1795 else
1796 // the simple version, applies when the grid is not yet connected to a data source
1797 pCol->setModel(xNewColumn);
1799 if (bWasEditing)
1800 pGrid->ActivateCell();
1804 void FmXGridPeer::elementRemoved(const ContainerEvent& evt)
1806 SolarMutexGuard aGuard;
1808 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1810 // take handle column into account
1811 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount()))
1812 return;
1814 pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor)));
1816 Reference< XPropertySet > xOldColumn(evt.Element, css::uno::UNO_QUERY);
1817 removeColumnListeners(xOldColumn);
1821 void FmXGridPeer::setProperty( const OUString& PropertyName, const Any& Value)
1823 SolarMutexGuard aGuard;
1825 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
1827 bool bVoid = !Value.hasValue();
1829 if ( PropertyName == FM_PROP_TEXTLINECOLOR )
1831 ::Color aTextLineColor( bVoid ? COL_TRANSPARENT : ::comphelper::getINT32( Value ) );
1832 if (bVoid)
1834 pGrid->SetTextLineColor();
1835 pGrid->GetDataWindow().SetTextLineColor();
1837 else
1839 pGrid->SetTextLineColor(aTextLineColor);
1840 pGrid->GetDataWindow().SetTextLineColor(aTextLineColor);
1843 // need to forward this to the columns
1844 DbGridColumns& rColumns = const_cast<DbGridColumns&>(pGrid->GetColumns());
1845 for (DbGridColumn* pLoop : rColumns)
1847 FmXGridCell* pXCell = pLoop->GetCell();
1848 if (pXCell)
1850 if (bVoid)
1851 pXCell->SetTextLineColor();
1852 else
1853 pXCell->SetTextLineColor(aTextLineColor);
1857 if (isDesignMode())
1858 pGrid->Invalidate();
1860 else if ( PropertyName == FM_PROP_FONTEMPHASISMARK )
1862 vcl::Font aGridFont = pGrid->GetControlFont();
1863 sal_Int16 nValue = ::comphelper::getINT16(Value);
1864 aGridFont.SetEmphasisMark( (FontEmphasisMark)nValue );
1865 pGrid->SetControlFont( aGridFont );
1867 else if ( PropertyName == FM_PROP_FONTRELIEF )
1869 vcl::Font aGridFont = pGrid->GetControlFont();
1870 sal_Int16 nValue = ::comphelper::getINT16(Value);
1871 aGridFont.SetRelief( (FontRelief)nValue );
1872 pGrid->SetControlFont( aGridFont );
1874 else if ( PropertyName == FM_PROP_HELPURL )
1876 OUString sHelpURL;
1877 OSL_VERIFY( Value >>= sHelpURL );
1878 INetURLObject aHID( sHelpURL );
1879 if ( aHID.GetProtocol() == INetProtocol::Hid )
1880 sHelpURL = aHID.GetURLPath();
1881 pGrid->SetHelpId( OUStringToOString( sHelpURL, RTL_TEXTENCODING_UTF8 ) );
1883 else if ( PropertyName == FM_PROP_DISPLAYSYNCHRON )
1885 pGrid->setDisplaySynchron(::comphelper::getBOOL(Value));
1887 else if ( PropertyName == FM_PROP_CURSORCOLOR )
1889 if (bVoid)
1890 pGrid->SetCursorColor(COL_TRANSPARENT);
1891 else
1892 pGrid->SetCursorColor( ::Color(::comphelper::getINT32(Value)));
1893 if (isDesignMode())
1894 pGrid->Invalidate();
1896 else if ( PropertyName == FM_PROP_ALWAYSSHOWCURSOR )
1898 pGrid->EnablePermanentCursor(::comphelper::getBOOL(Value));
1899 if (isDesignMode())
1900 pGrid->Invalidate();
1902 else if ( PropertyName == FM_PROP_FONT )
1904 if ( bVoid )
1905 pGrid->SetControlFont( vcl::Font() );
1906 else
1908 css::awt::FontDescriptor aFont;
1909 if (Value >>= aFont)
1911 vcl::Font aNewVclFont;
1912 if (aFont != ::comphelper::getDefaultFont()) // is this the default
1913 aNewVclFont = ImplCreateFont( aFont );
1915 // need to add relief and emphasis (they're stored in a VCL-Font, but not in a FontDescriptor
1916 vcl::Font aOldVclFont = pGrid->GetControlFont();
1917 aNewVclFont.SetRelief( aOldVclFont.GetRelief() );
1918 aNewVclFont.SetEmphasisMark( aOldVclFont.GetEmphasisMark() );
1920 // now set it ...
1921 pGrid->SetControlFont( aNewVclFont );
1923 // if our row-height property is void (which means "calculate it font-dependent") we have
1924 // to adjust the control's row height
1925 Reference< XPropertySet > xModelSet(getColumns(), UNO_QUERY);
1926 if (xModelSet.is() && ::comphelper::hasProperty(FM_PROP_ROWHEIGHT, xModelSet))
1928 Any aHeight = xModelSet->getPropertyValue(FM_PROP_ROWHEIGHT);
1929 if (!aHeight.hasValue())
1930 pGrid->SetDataRowHeight(0);
1936 else if ( PropertyName == FM_PROP_BACKGROUNDCOLOR )
1938 if ( bVoid )
1940 pGrid->SetControlBackground();
1942 else
1944 ::Color aColor( ::comphelper::getINT32(Value) );
1945 pGrid->SetBackground( aColor );
1946 pGrid->SetControlBackground( aColor );
1949 else if ( PropertyName == FM_PROP_TEXTCOLOR )
1951 if ( bVoid )
1953 pGrid->SetControlForeground();
1955 else
1957 ::Color aColor( ::comphelper::getINT32(Value) );
1958 pGrid->SetTextColor( aColor );
1959 pGrid->SetControlForeground( aColor );
1962 else if ( PropertyName == FM_PROP_ROWHEIGHT )
1964 sal_Int32 nLogHeight(0);
1965 if (Value >>= nLogHeight)
1967 sal_Int32 nHeight = pGrid->LogicToPixel(Point(0,nLogHeight),MapUnit::Map10thMM).Y();
1968 // take the zoom factor into account
1969 nHeight = pGrid->CalcZoom(nHeight);
1970 pGrid->SetDataRowHeight(nHeight);
1972 else if (bVoid)
1973 pGrid->SetDataRowHeight(0);
1975 else if ( PropertyName == FM_PROP_HASNAVIGATION )
1977 bool bValue( true );
1978 OSL_VERIFY( Value >>= bValue );
1979 pGrid->EnableNavigationBar( bValue );
1981 else if ( PropertyName == FM_PROP_RECORDMARKER )
1983 bool bValue( true );
1984 OSL_VERIFY( Value >>= bValue );
1985 pGrid->EnableHandle( bValue );
1987 else if ( PropertyName == FM_PROP_ENABLED )
1989 bool bValue( true );
1990 OSL_VERIFY( Value >>= bValue );
1992 // In design mode, disable only the data window.
1993 // Else the control cannot be configured anymore.
1994 if (isDesignMode())
1995 pGrid->GetDataWindow().Enable( bValue );
1996 else
1997 pGrid->Enable( bValue );
1999 else
2000 VCLXWindow::setProperty( PropertyName, Value );
2004 Reference< XAccessibleContext > FmXGridPeer::CreateAccessibleContext()
2006 Reference< XAccessibleContext > xContext;
2008 // use the AccessibleContext provided by the VCL window
2009 VclPtr<vcl::Window> pGrid = GetWindow();
2010 if ( pGrid )
2012 Reference< XAccessible > xAcc( pGrid->GetAccessible() );
2013 if ( xAcc.is() )
2014 xContext = xAcc->getAccessibleContext();
2015 // TODO: this has a slight conceptual problem:
2017 // We know that the XAccessible and XAccessibleContext implementation of the browse
2018 // box is the same (the class implements both interfaces), which, speaking strictly,
2019 // is bad here (means when a browse box acts as UnoControl): We (the FmXGridPeer) are
2020 // the XAccessible here, and the browse box should be able to provide us an XAccessibleContext,
2021 // but it should _not_ be the XAccessible itself.
2022 // However, as long as no client implementation uses dirty hacks such as querying an
2023 // XAccessibleContext for XAccessible, this should not be a problem.
2026 if ( !xContext.is() )
2027 xContext = VCLXWindow::CreateAccessibleContext( );
2029 return xContext;
2033 Any FmXGridPeer::getProperty( const OUString& _rPropertyName )
2035 Any aProp;
2036 if (GetWindow())
2038 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2039 vcl::Window* pDataWindow = &pGrid->GetDataWindow();
2041 if ( _rPropertyName == FM_PROP_NAME )
2043 vcl::Font aFont = pDataWindow->GetControlFont();
2044 aProp <<= ImplCreateFontDescriptor( aFont );
2046 else if ( _rPropertyName == FM_PROP_TEXTCOLOR )
2048 aProp <<= (sal_Int32)pDataWindow->GetControlForeground().GetColor();
2050 else if ( _rPropertyName == FM_PROP_BACKGROUNDCOLOR )
2052 aProp <<= (sal_Int32)pDataWindow->GetControlBackground().GetColor();
2054 else if ( _rPropertyName == FM_PROP_ROWHEIGHT )
2056 sal_Int32 nPixelHeight = pGrid->GetDataRowHeight();
2057 // take the zoom factor into account
2058 nPixelHeight = pGrid->CalcReverseZoom(nPixelHeight);
2059 aProp <<= (sal_Int32)pGrid->PixelToLogic(Point(0,nPixelHeight),MapUnit::Map10thMM).Y();
2061 else if ( _rPropertyName == FM_PROP_HASNAVIGATION )
2063 bool bHasNavBar = pGrid->HasNavigationBar();
2064 aProp <<= bHasNavBar;
2066 else if ( _rPropertyName == FM_PROP_RECORDMARKER )
2068 bool bHasHandle = pGrid->HasHandle();
2069 aProp <<= bHasHandle;
2071 else if ( _rPropertyName == FM_PROP_ENABLED )
2073 aProp <<= pDataWindow->IsEnabled();
2075 else
2076 aProp = VCLXWindow::getProperty( _rPropertyName );
2078 return aProp;
2082 void FmXGridPeer::dispose()
2084 EventObject aEvt;
2085 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
2086 m_aModifyListeners.disposeAndClear(aEvt);
2087 m_aUpdateListeners.disposeAndClear(aEvt);
2088 m_aContainerListeners.disposeAndClear(aEvt);
2089 VCLXWindow::dispose();
2091 // release all interceptors
2092 Reference< XDispatchProviderInterceptor > xInterceptor( m_xFirstDispatchInterceptor );
2093 m_xFirstDispatchInterceptor.clear();
2094 while ( xInterceptor.is() )
2096 // tell the interceptor it has a new (means no) predecessor
2097 xInterceptor->setMasterDispatchProvider( nullptr );
2099 // ask for its successor
2100 Reference< XDispatchProvider > xSlave = xInterceptor->getSlaveDispatchProvider();
2101 // and give it the new (means no) successoert
2102 xInterceptor->setSlaveDispatchProvider( nullptr );
2104 // start over with the next chain element
2105 xInterceptor.set(xSlave, css::uno::UNO_QUERY);
2108 DisConnectFromDispatcher();
2109 setRowSet(Reference< XRowSet > ());
2112 // XContainer
2114 void FmXGridPeer::addContainerListener(const Reference< XContainerListener >& l)
2116 m_aContainerListeners.addInterface( l );
2119 void FmXGridPeer::removeContainerListener(const Reference< XContainerListener >& l)
2121 m_aContainerListeners.removeInterface( l );
2124 // css::data::XDatabaseCursorSupplier
2126 void FmXGridPeer::startCursorListening()
2128 if (!m_nCursorListening)
2130 Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY);
2131 if (xRowSet.is())
2132 xRowSet->addRowSetListener(this);
2134 Reference< XReset > xReset(m_xCursor, UNO_QUERY);
2135 if (xReset.is())
2136 xReset->addResetListener(this);
2138 // register all listeners
2139 Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY);
2140 if (xSet.is())
2142 xSet->addPropertyChangeListener(FM_PROP_ISMODIFIED, this);
2143 xSet->addPropertyChangeListener(FM_PROP_ROWCOUNT, this);
2146 m_nCursorListening++;
2150 void FmXGridPeer::stopCursorListening()
2152 if (!--m_nCursorListening)
2154 Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY);
2155 if (xRowSet.is())
2156 xRowSet->removeRowSetListener(this);
2158 Reference< XReset > xReset(m_xCursor, UNO_QUERY);
2159 if (xReset.is())
2160 xReset->removeResetListener(this);
2162 Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY);
2163 if (xSet.is())
2165 xSet->removePropertyChangeListener(FM_PROP_ISMODIFIED, this);
2166 xSet->removePropertyChangeListener(FM_PROP_ROWCOUNT, this);
2172 void FmXGridPeer::updateGrid(const Reference< XRowSet >& _rxCursor)
2174 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2175 if (pGrid)
2176 pGrid->setDataSource(_rxCursor);
2180 Reference< XRowSet > FmXGridPeer::getRowSet()
2182 return m_xCursor;
2186 void FmXGridPeer::setRowSet(const Reference< XRowSet >& _rDatabaseCursor)
2188 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2189 if (!pGrid || !m_xColumns.is() || !m_xColumns->getCount())
2190 return;
2191 // unregister all listeners
2192 if (m_xCursor.is())
2194 Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY);
2195 // only if the form is loaded we set the rowset
2196 if (xLoadable.is())
2198 stopCursorListening();
2199 xLoadable->removeLoadListener(this);
2203 m_xCursor = _rDatabaseCursor;
2205 if (pGrid)
2207 Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY);
2208 // only if the form is loaded we set the rowset
2209 if (xLoadable.is() && xLoadable->isLoaded())
2210 pGrid->setDataSource(m_xCursor);
2211 else
2212 pGrid->setDataSource(Reference< XRowSet > ());
2214 if (xLoadable.is())
2216 startCursorListening();
2217 xLoadable->addLoadListener(this);
2223 void SAL_CALL FmXGridPeer::addGridControlListener( const Reference< XGridControlListener >& _listener )
2225 m_aGridControlListeners.addInterface( _listener );
2229 void SAL_CALL FmXGridPeer::removeGridControlListener( const Reference< XGridControlListener >& _listener )
2231 m_aGridControlListeners.removeInterface( _listener );
2235 sal_Int16 FmXGridPeer::getCurrentColumnPosition()
2237 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2238 return pGrid ? pGrid->GetViewColumnPos(pGrid->GetCurColumnId()) : -1;
2242 void FmXGridPeer::setCurrentColumnPosition(sal_Int16 nPos)
2244 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2245 if (pGrid)
2246 pGrid->GoToColumnId(pGrid->GetColumnIdFromViewPos(nPos));
2250 void FmXGridPeer::selectionChanged(const EventObject& evt)
2252 SolarMutexGuard aGuard;
2254 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2255 if (pGrid)
2257 Reference< css::view::XSelectionSupplier > xSelSupplier(evt.Source, UNO_QUERY);
2258 Any aSelection = xSelSupplier->getSelection();
2259 DBG_ASSERT(aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE, "FmXGridPeer::selectionChanged : invalid selection !");
2260 Reference< XPropertySet > xSelection;
2261 aSelection >>= xSelection;
2262 if (xSelection.is())
2264 Reference< XPropertySet > xCol;
2265 sal_Int32 i = 0;
2266 sal_Int32 nColCount = m_xColumns->getCount();
2268 for (; i < nColCount; ++i)
2270 m_xColumns->getByIndex(i) >>= xCol;
2271 if ( xCol == xSelection )
2273 pGrid->markColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)i));
2274 break;
2277 // The columns have to be 1-based for the VCL control.
2278 // If necessary, pass on the selection to the VCL control
2279 if ( i != pGrid->GetSelectedColumn() )
2280 { // (if this does not take effect, the selectionChanged was implicitly triggered by the control itself)
2281 if ( i < nColCount )
2283 pGrid->SelectColumnPos(pGrid->GetViewColumnPos(pGrid->GetColumnIdFromModelPos( (sal_uInt16)i )) + 1);
2284 // SelectColumnPos has led to an implicit ActivateCell again
2285 if (pGrid->IsEditing())
2286 pGrid->DeactivateCell();
2288 else
2289 pGrid->SetNoSelection();
2292 else
2293 pGrid->markColumn(USHRT_MAX);
2297 // XElementAccess
2299 sal_Bool FmXGridPeer::hasElements()
2301 return getCount() != 0;
2305 Type SAL_CALL FmXGridPeer::getElementType( )
2307 return cppu::UnoType<css::awt::XControl>::get();
2310 // XEnumerationAccess
2312 Reference< XEnumeration > FmXGridPeer::createEnumeration()
2314 return new ::comphelper::OEnumerationByIndex(this);
2317 // XIndexAccess
2319 sal_Int32 FmXGridPeer::getCount()
2321 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2322 if (pGrid)
2323 return pGrid->GetViewColCount();
2324 else
2325 return 0;
2329 Any FmXGridPeer::getByIndex(sal_Int32 _nIndex)
2331 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2332 if (_nIndex < 0 ||
2333 _nIndex >= getCount() || !pGrid)
2334 throw IndexOutOfBoundsException();
2336 Any aElement;
2337 // get the columnid
2338 sal_uInt16 nId = pGrid->GetColumnIdFromViewPos((sal_uInt16)_nIndex);
2339 // get the list position
2340 sal_uInt16 nPos = pGrid->GetModelColumnPos(nId);
2342 if ( nPos == GRID_COLUMN_NOT_FOUND )
2343 return aElement;
2345 DbGridColumn* pCol = pGrid->GetColumns().at( nPos );
2346 Reference< css::awt::XControl > xControl(pCol->GetCell());
2347 aElement <<= xControl;
2349 return aElement;
2352 // css::util::XModeSelector
2354 void FmXGridPeer::setMode(const OUString& Mode)
2356 if (!supportsMode(Mode))
2357 throw NoSupportException();
2359 if (Mode == m_aMode)
2360 return;
2362 m_aMode = Mode;
2364 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2365 if ( Mode == "FilterMode" )
2366 pGrid->SetFilterMode(true);
2367 else
2369 pGrid->SetFilterMode(false);
2370 pGrid->setDataSource(m_xCursor);
2375 OUString FmXGridPeer::getMode()
2377 return m_aMode;
2381 css::uno::Sequence<OUString> FmXGridPeer::getSupportedModes()
2383 static css::uno::Sequence<OUString> aModes;
2384 if (!aModes.getLength())
2386 aModes.realloc(2);
2387 OUString* pModes = aModes.getArray();
2388 pModes[0] = "DataMode";
2389 pModes[1] = "FilterMode";
2391 return aModes;
2395 sal_Bool FmXGridPeer::supportsMode(const OUString& Mode)
2397 css::uno::Sequence<OUString> aModes(getSupportedModes());
2398 const OUString* pModes = aModes.getConstArray();
2399 for (sal_Int32 i = aModes.getLength(); i > 0; )
2401 if (pModes[--i] == Mode)
2402 return true;
2404 return false;
2408 void FmXGridPeer::columnVisible(DbGridColumn* pColumn)
2410 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2412 sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId());
2413 Reference< css::awt::XControl > xControl(pColumn->GetCell());
2414 ContainerEvent aEvt;
2415 aEvt.Source = static_cast<XContainer*>(this);
2416 aEvt.Accessor <<= _nIndex;
2417 aEvt.Element <<= xControl;
2419 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt );
2423 void FmXGridPeer::columnHidden(DbGridColumn* pColumn)
2425 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2427 sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId());
2428 Reference< css::awt::XControl > xControl(pColumn->GetCell());
2429 ContainerEvent aEvt;
2430 aEvt.Source = static_cast<XContainer*>(this);
2431 aEvt.Accessor <<= _nIndex;
2432 aEvt.Element <<= xControl;
2434 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt );
2438 void FmXGridPeer::draw( sal_Int32 x, sal_Int32 y )
2440 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2441 EditBrowseBoxFlags nOldFlags = pGrid->GetBrowserFlags();
2442 pGrid->SetBrowserFlags(nOldFlags | EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT);
2444 VCLXWindow::draw(x, y);
2446 pGrid->SetBrowserFlags(nOldFlags);
2450 Reference< css::frame::XDispatch > FmXGridPeer::queryDispatch(const css::util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags)
2452 Reference< css::frame::XDispatch > xResult;
2454 // first ask our interceptor chain
2455 if (m_xFirstDispatchInterceptor.is() && !m_bInterceptingDispatch)
2457 m_bInterceptingDispatch = true;
2458 // safety against recursion : as we are master of the first chain element and slave of the last one we would
2459 // have an infinite loop without this if no dispatcher can fulfill the request
2460 xResult = m_xFirstDispatchInterceptor->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
2461 m_bInterceptingDispatch = false;
2464 // then ask ourself : we don't have any dispatches
2465 return xResult;
2469 Sequence< Reference< css::frame::XDispatch > > FmXGridPeer::queryDispatches(const Sequence< css::frame::DispatchDescriptor>& aDescripts)
2471 if (m_xFirstDispatchInterceptor.is())
2472 return m_xFirstDispatchInterceptor->queryDispatches(aDescripts);
2474 // then ask ourself : we don't have any dispatches
2475 return Sequence< Reference< css::frame::XDispatch > >();
2479 void FmXGridPeer::registerDispatchProviderInterceptor(const Reference< css::frame::XDispatchProviderInterceptor >& _xInterceptor)
2481 if (_xInterceptor.is())
2483 if (m_xFirstDispatchInterceptor.is())
2485 Reference< css::frame::XDispatchProvider > xFirstProvider(m_xFirstDispatchInterceptor, UNO_QUERY);
2486 // there is already an interceptor; the new one will become its master
2487 _xInterceptor->setSlaveDispatchProvider(xFirstProvider);
2488 m_xFirstDispatchInterceptor->setMasterDispatchProvider(xFirstProvider);
2490 else
2492 // it is the first interceptor; set ourself as slave
2493 _xInterceptor->setSlaveDispatchProvider(static_cast<css::frame::XDispatchProvider*>(this));
2496 // we are the master of the chain's first interceptor
2497 m_xFirstDispatchInterceptor = _xInterceptor;
2498 m_xFirstDispatchInterceptor->setMasterDispatchProvider(static_cast<css::frame::XDispatchProvider*>(this));
2500 // we have a new interceptor and we're alive ?
2501 if (!isDesignMode())
2502 // -> check for new dispatchers
2503 UpdateDispatches();
2508 void FmXGridPeer::releaseDispatchProviderInterceptor(const Reference< css::frame::XDispatchProviderInterceptor >& _xInterceptor)
2510 if (!_xInterceptor.is())
2511 return;
2513 Reference< css::frame::XDispatchProviderInterceptor > xChainWalk(m_xFirstDispatchInterceptor);
2515 if (m_xFirstDispatchInterceptor == _xInterceptor)
2516 { // our chain will have a new first element
2517 Reference< css::frame::XDispatchProviderInterceptor > xSlave(m_xFirstDispatchInterceptor->getSlaveDispatchProvider(), UNO_QUERY);
2518 m_xFirstDispatchInterceptor = xSlave;
2520 // do this before removing the interceptor from the chain as we won't know it's slave afterwards)
2522 while (xChainWalk.is())
2524 // walk along the chain of interceptors and look for the interceptor that has to be removed
2525 Reference< css::frame::XDispatchProviderInterceptor > xSlave(xChainWalk->getSlaveDispatchProvider(), UNO_QUERY);
2527 if (xChainWalk == _xInterceptor)
2529 // old master may be an interceptor too
2530 Reference< css::frame::XDispatchProviderInterceptor > xMaster(xChainWalk->getMasterDispatchProvider(), UNO_QUERY);
2532 // unchain the interceptor that has to be removed
2533 xChainWalk->setSlaveDispatchProvider(Reference< css::frame::XDispatchProvider > ());
2534 xChainWalk->setMasterDispatchProvider(Reference< css::frame::XDispatchProvider > ());
2536 // reconnect the chain
2537 if (xMaster.is())
2539 if (xSlave.is())
2540 xMaster->setSlaveDispatchProvider(Reference< css::frame::XDispatchProvider >::query(xSlave));
2541 else
2542 // it's the first interceptor of the chain, set ourself as slave
2543 xMaster->setSlaveDispatchProvider(static_cast<css::frame::XDispatchProvider*>(this));
2545 else
2547 // the chain's first element was removed, set ourself as new master of the second one
2548 if (xSlave.is())
2549 xSlave->setMasterDispatchProvider(static_cast<css::frame::XDispatchProvider*>(this));
2553 xChainWalk = xSlave;
2555 // our interceptor chain has changed and we're alive ?
2556 if (!isDesignMode())
2557 // -> check the dispatchers
2558 UpdateDispatches();
2562 void FmXGridPeer::statusChanged(const css::frame::FeatureStateEvent& Event)
2564 DBG_ASSERT(m_pStateCache, "FmXGridPeer::statusChanged : invalid call !");
2565 DBG_ASSERT(m_pDispatchers, "FmXGridPeer::statusChanged : invalid call !");
2567 Sequence< css::util::URL>& aUrls = getSupportedURLs();
2568 const css::util::URL* pUrls = aUrls.getConstArray();
2570 const std::vector<DbGridControlNavigationBarState>& aSlots = getSupportedGridSlots();
2572 sal_Int32 i;
2573 for (i=0; i<aUrls.getLength(); ++i, ++pUrls)
2575 if (pUrls->Main == Event.FeatureURL.Main)
2577 DBG_ASSERT(m_pDispatchers[i] == Event.Source, "FmXGridPeer::statusChanged : the event source is a little bit suspect !");
2578 m_pStateCache[i] = Event.IsEnabled;
2579 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2580 if (aSlots[i] != DbGridControlNavigationBarState::Undo)
2581 pGrid->GetNavigationBar().InvalidateState(aSlots[i]);
2582 break;
2585 DBG_ASSERT(i<aUrls.getLength(), "FmXGridPeer::statusChanged : got a call for an unknown url !");
2589 sal_Bool FmXGridPeer::approveReset(const EventObject& /*rEvent*/)
2591 return true;
2595 sal_Bool SAL_CALL FmXGridPeer::select( const Any& _rSelection )
2597 Sequence< Any > aBookmarks;
2598 if ( !( _rSelection >>= aBookmarks ) )
2599 throw IllegalArgumentException();
2601 return GetAs< FmGridControl >()->selectBookmarks(aBookmarks);
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.
2612 Any SAL_CALL FmXGridPeer::getSelection( )
2614 VclPtr< FmGridControl > pVclControl = GetAs< FmGridControl >();
2615 Sequence< Any > aSelectionBookmarks = pVclControl->getSelectionBookmarks();
2616 return makeAny(aSelectionBookmarks);
2620 void SAL_CALL FmXGridPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener )
2622 m_aSelectionListeners.addInterface( _rxListener );
2626 void SAL_CALL FmXGridPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener )
2628 m_aSelectionListeners.removeInterface( _rxListener );
2632 void FmXGridPeer::resetted(const EventObject& rEvent)
2634 if (m_xColumns == rEvent.Source)
2635 { // my model was reset -> refresh the grid content
2636 SolarMutexGuard aGuard;
2637 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2638 if (!pGrid)
2639 return;
2640 pGrid->resetCurrentRow();
2642 // if the cursor fired a reset event we seem to be on the insert row
2643 else if (m_xCursor == rEvent.Source)
2645 SolarMutexGuard aGuard;
2646 VclPtr< FmGridControl > pGrid = GetAs< FmGridControl >();
2647 if (pGrid && pGrid->IsOpen())
2648 pGrid->positioned();
2653 const std::vector<DbGridControlNavigationBarState>& FmXGridPeer::getSupportedGridSlots()
2655 static const std::vector<DbGridControlNavigationBarState> aSupported {
2656 DbGridControlNavigationBarState::First,
2657 DbGridControlNavigationBarState::Prev,
2658 DbGridControlNavigationBarState::Next,
2659 DbGridControlNavigationBarState::Last,
2660 DbGridControlNavigationBarState::New,
2661 DbGridControlNavigationBarState::Undo
2663 return aSupported;
2667 Sequence< css::util::URL>& FmXGridPeer::getSupportedURLs()
2669 static Sequence< css::util::URL> aSupported;
2670 if (aSupported.getLength() == 0)
2672 static const char* sSupported[] = {
2673 FMURL_RECORD_MOVEFIRST,
2674 FMURL_RECORD_MOVEPREV,
2675 FMURL_RECORD_MOVENEXT,
2676 FMURL_RECORD_MOVELAST,
2677 FMURL_RECORD_MOVETONEW,
2678 FMURL_RECORD_UNDO
2680 aSupported.realloc(SAL_N_ELEMENTS(sSupported));
2681 css::util::URL* pSupported = aSupported.getArray();
2683 for ( sal_Int32 i = 0; i < aSupported.getLength(); ++i, ++pSupported)
2684 pSupported->Complete = OUString::createFromAscii(sSupported[i]);
2686 // let an css::util::URL-transformer normalize the URLs
2687 Reference< css::util::XURLTransformer > xTransformer(
2688 util::URLTransformer::create(::comphelper::getProcessComponentContext()) );
2689 pSupported = aSupported.getArray();
2690 for (sal_Int32 i=0; i<aSupported.getLength(); ++i)
2691 xTransformer->parseStrict(pSupported[i]);
2694 return aSupported;
2698 void FmXGridPeer::UpdateDispatches()
2700 if (!m_pStateCache)
2701 { // we don't have any dispatchers yet -> do the initial connect
2702 ConnectToDispatcher();
2703 return;
2706 sal_uInt16 nDispatchersGot = 0;
2707 const Sequence< css::util::URL>& aSupportedURLs = getSupportedURLs();
2708 const css::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2709 Reference< css::frame::XDispatch > xNewDispatch;
2710 for (sal_Int32 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2712 xNewDispatch = queryDispatch(*pSupportedURLs, OUString(), 0);
2713 if (xNewDispatch != m_pDispatchers[i])
2715 if (m_pDispatchers[i].is())
2716 m_pDispatchers[i]->removeStatusListener(static_cast<css::frame::XStatusListener*>(this), *pSupportedURLs);
2717 m_pDispatchers[i] = xNewDispatch;
2718 if (m_pDispatchers[i].is())
2719 m_pDispatchers[i]->addStatusListener(static_cast<css::frame::XStatusListener*>(this), *pSupportedURLs);
2721 if (m_pDispatchers[i].is())
2722 ++nDispatchersGot;
2725 if (!nDispatchersGot)
2727 delete[] m_pStateCache;
2728 delete[] m_pDispatchers;
2729 m_pStateCache = nullptr;
2730 m_pDispatchers = nullptr;
2735 void FmXGridPeer::ConnectToDispatcher()
2737 DBG_ASSERT((m_pStateCache != nullptr) == (m_pDispatchers != nullptr), "FmXGridPeer::ConnectToDispatcher : inconsistent !");
2738 if (m_pStateCache)
2739 { // already connected -> just do an update
2740 UpdateDispatches();
2741 return;
2744 const Sequence< css::util::URL>& aSupportedURLs = getSupportedURLs();
2746 // _before_ adding the status listeners (as the add should result in a statusChanged-call) !
2747 m_pStateCache = new bool[aSupportedURLs.getLength()];
2748 m_pDispatchers = new Reference< css::frame::XDispatch > [aSupportedURLs.getLength()];
2750 sal_uInt16 nDispatchersGot = 0;
2751 const css::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2752 for (sal_Int32 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2754 m_pStateCache[i] = false;
2755 m_pDispatchers[i] = queryDispatch(*pSupportedURLs, OUString(), 0);
2756 if (m_pDispatchers[i].is())
2758 m_pDispatchers[i]->addStatusListener(static_cast<css::frame::XStatusListener*>(this), *pSupportedURLs);
2759 ++nDispatchersGot;
2763 if (!nDispatchersGot)
2765 delete[] m_pStateCache;
2766 delete[] m_pDispatchers;
2767 m_pStateCache = nullptr;
2768 m_pDispatchers = nullptr;
2773 void FmXGridPeer::DisConnectFromDispatcher()
2775 if (!m_pStateCache || !m_pDispatchers)
2776 return;
2777 // we're not connected
2779 const Sequence< css::util::URL>& aSupportedURLs = getSupportedURLs();
2780 const css::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2781 for (sal_Int32 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2783 if (m_pDispatchers[i].is())
2784 m_pDispatchers[i]->removeStatusListener(static_cast<css::frame::XStatusListener*>(this), *pSupportedURLs);
2787 delete[] m_pStateCache;
2788 delete[] m_pDispatchers;
2789 m_pStateCache = nullptr;
2790 m_pDispatchers = nullptr;
2794 IMPL_LINK(FmXGridPeer, OnQueryGridSlotState, DbGridControlNavigationBarState, nSlot, int)
2796 if (!m_pStateCache)
2797 return -1; // unspecified
2799 // search the given slot with our supported sequence
2800 const std::vector<DbGridControlNavigationBarState>& aSupported = getSupportedGridSlots();
2801 for (size_t i=0; i<aSupported.size(); ++i)
2803 if (aSupported[i] == nSlot)
2805 if (!m_pDispatchers[i].is())
2806 return -1; // nothing known about this slot
2807 else
2808 return m_pStateCache[i] ? 1 : 0;
2812 return -1;
2816 IMPL_LINK(FmXGridPeer, OnExecuteGridSlot, DbGridControlNavigationBarState, nSlot, bool)
2818 if (!m_pDispatchers)
2819 return false; // not handled
2821 Sequence< css::util::URL>& aUrls = getSupportedURLs();
2822 const css::util::URL* pUrls = aUrls.getConstArray();
2824 const std::vector<DbGridControlNavigationBarState>& aSlots = getSupportedGridSlots();
2826 DBG_ASSERT((sal_Int32)aSlots.size() == aUrls.getLength(), "FmXGridPeer::OnExecuteGridSlot : inconsistent data returned by getSupportedURLs/getSupportedGridSlots!");
2828 for (size_t i=0; i<aSlots.size(); ++i, ++pUrls)
2830 if (aSlots[i] == nSlot)
2832 if (m_pDispatchers[i].is())
2834 // commit any changes done so far, if it's not the undoRecord URL
2835 if ( pUrls->Complete == FMURL_RECORD_UNDO || commit() )
2836 m_pDispatchers[i]->dispatch(*pUrls, Sequence< PropertyValue>());
2838 return true; // handled
2843 return false; // not handled
2846 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */