Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / svx / source / fmcomp / fmgridif.cxx
blob902c821ab8d6aca951255d40925f3c49a8f048b1
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/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>
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 <toolkit/helper/vclunohelper.hxx>
56 #include <tools/diagnose_ex.h>
57 #include <sal/macros.h>
59 using namespace ::svxform;
60 using namespace ::com::sun::star::container;
61 using namespace ::com::sun::star::sdb;
62 using namespace ::com::sun::star::sdbc;
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::view;
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::lang;
67 using namespace ::com::sun::star::form;
68 using namespace ::com::sun::star::util;
69 using namespace ::com::sun::star;
71 using ::com::sun::star::sdbcx::XColumnsSupplier;
72 using ::com::sun::star::frame::XDispatchProviderInterceptor;
73 using ::com::sun::star::frame::XDispatchProvider;
74 using ::com::sun::star::accessibility::XAccessible;
75 using ::com::sun::star::accessibility::XAccessibleContext;
76 using ::com::sun::star::sdb::XRowSetSupplier;
77 using ::com::sun::star::awt::XVclWindowPeer;
81 ::com::sun::star::awt::FontDescriptor ImplCreateFontDescriptor( const Font& rFont )
83 ::com::sun::star::awt::FontDescriptor aFD;
84 aFD.Name = rFont.GetName();
85 aFD.StyleName = rFont.GetStyleName();
86 aFD.Height = (sal_Int16)rFont.GetSize().Height();
87 aFD.Width = (sal_Int16)rFont.GetSize().Width();
88 aFD.Family = (sal_Int16)rFont.GetFamily();
89 aFD.CharSet = rFont.GetCharSet();
90 aFD.Pitch = (sal_Int16)rFont.GetPitch();
91 aFD.CharacterWidth = VCLUnoHelper::ConvertFontWidth( rFont.GetWidthType() );
92 aFD.Weight= VCLUnoHelper::ConvertFontWeight( rFont.GetWeight() );
93 aFD.Slant = (::com::sun::star::awt::FontSlant)rFont.GetItalic();
94 aFD.Underline = (sal_Int16)rFont.GetUnderline();
95 aFD.Strikeout = (sal_Int16)rFont.GetStrikeout();
96 aFD.Orientation = rFont.GetOrientation();
97 aFD.Kerning = rFont.IsKerning();
98 aFD.WordLineMode = rFont.IsWordLineMode();
99 aFD.Type = 0; // ??? => Nur an Metric...
100 return aFD;
104 Font ImplCreateFont( const ::com::sun::star::awt::FontDescriptor& rDescr )
106 Font aFont;
107 aFont.SetName( rDescr.Name );
108 aFont.SetStyleName( rDescr.StyleName );
109 aFont.SetSize( ::Size( rDescr.Width, rDescr.Height ) );
110 aFont.SetFamily( (FontFamily)rDescr.Family );
111 aFont.SetCharSet( (rtl_TextEncoding)rDescr.CharSet );
112 aFont.SetPitch( (FontPitch)rDescr.Pitch );
113 aFont.SetWidthType( VCLUnoHelper::ConvertFontWidth( rDescr.CharacterWidth ) );
114 aFont.SetWeight( VCLUnoHelper::ConvertFontWeight( rDescr.Weight ) );
115 aFont.SetItalic( (FontItalic)rDescr.Slant );
116 aFont.SetUnderline( (::FontUnderline)rDescr.Underline );
117 aFont.SetStrikeout( (::FontStrikeout)rDescr.Strikeout );
118 aFont.SetOrientation( (sal_Int16)rDescr.Orientation );
119 aFont.SetKerning( rDescr.Kerning );
120 aFont.SetWordLineMode( rDescr.WordLineMode );
121 return aFont;
125 //= FmXModifyMultiplexer
128 FmXModifyMultiplexer::FmXModifyMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
129 :OWeakSubObject( rSource )
130 ,OInterfaceContainerHelper( _rMutex )
135 Any SAL_CALL FmXModifyMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
137 Any aReturn;
138 aReturn = ::cppu::queryInterface(_rType,
139 static_cast< ::com::sun::star::util::XModifyListener*>(this),
140 static_cast< XEventListener*>(this)
143 if (!aReturn.hasValue())
144 aReturn = OWeakSubObject::queryInterface( _rType );
146 return aReturn;
150 void FmXModifyMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
155 void FmXModifyMultiplexer::modified(const EventObject& e) throw( RuntimeException, std::exception )
157 EventObject aMulti( e);
158 aMulti.Source = &m_rParent;
159 notifyEach( &XModifyListener::modified, aMulti );
163 //= FmXUpdateMultiplexer
166 FmXUpdateMultiplexer::FmXUpdateMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
167 :OWeakSubObject( rSource )
168 ,OInterfaceContainerHelper( _rMutex )
173 Any SAL_CALL FmXUpdateMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
175 Any aReturn;
176 aReturn = ::cppu::queryInterface(_rType,
177 static_cast< XUpdateListener*>(this),
178 static_cast< XEventListener*>(this)
181 if (!aReturn.hasValue())
182 aReturn = OWeakSubObject::queryInterface( _rType );
184 return aReturn;
188 void FmXUpdateMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
193 sal_Bool FmXUpdateMultiplexer::approveUpdate(const EventObject &e) throw( RuntimeException, std::exception )
195 EventObject aMulti( e );
196 aMulti.Source = &m_rParent;
198 bool bResult = true;
199 if (getLength())
201 ::cppu::OInterfaceIteratorHelper aIter(*this);
202 while ( bResult && aIter.hasMoreElements() )
203 bResult = static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aMulti );
206 return bResult;
210 void FmXUpdateMultiplexer::updated(const EventObject &e) throw( RuntimeException, std::exception )
212 EventObject aMulti( e );
213 aMulti.Source = &m_rParent;
214 notifyEach( &XUpdateListener::updated, aMulti );
219 //= FmXSelectionMultiplexer
222 FmXSelectionMultiplexer::FmXSelectionMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
223 :OWeakSubObject( rSource )
224 ,OInterfaceContainerHelper( _rMutex )
229 Any SAL_CALL FmXSelectionMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
231 Any aReturn;
232 aReturn = ::cppu::queryInterface(_rType,
233 static_cast< XSelectionChangeListener*>(this),
234 static_cast< XEventListener*>(this)
237 if (!aReturn.hasValue())
238 aReturn = OWeakSubObject::queryInterface( _rType );
240 return aReturn;
244 void FmXSelectionMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
249 void SAL_CALL FmXSelectionMultiplexer::selectionChanged( const EventObject& _rEvent ) throw (RuntimeException, std::exception)
251 EventObject aMulti(_rEvent);
252 aMulti.Source = &m_rParent;
253 notifyEach( &XSelectionChangeListener::selectionChanged, aMulti );
257 //= FmXContainerMultiplexer
260 FmXContainerMultiplexer::FmXContainerMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
261 :OWeakSubObject( rSource )
262 ,OInterfaceContainerHelper( _rMutex )
267 Any SAL_CALL FmXContainerMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
269 Any aReturn;
270 aReturn = ::cppu::queryInterface(_rType,
271 static_cast< XContainerListener*>(this),
272 static_cast< XEventListener*>(this)
275 if (!aReturn.hasValue())
276 aReturn = OWeakSubObject::queryInterface( _rType );
278 return aReturn;
282 void FmXContainerMultiplexer::disposing(const EventObject& ) throw( RuntimeException, std::exception )
286 void FmXContainerMultiplexer::elementInserted(const ContainerEvent& e) throw( RuntimeException, std::exception )
288 ContainerEvent aMulti( e );
289 aMulti.Source = &m_rParent;
290 notifyEach( &XContainerListener::elementInserted, aMulti );
294 void FmXContainerMultiplexer::elementRemoved(const ContainerEvent& e) throw( RuntimeException, std::exception )
296 ContainerEvent aMulti( e );
297 aMulti.Source = &m_rParent;
298 notifyEach( &XContainerListener::elementRemoved, aMulti );
303 void FmXContainerMultiplexer::elementReplaced(const ContainerEvent& e) throw( RuntimeException, std::exception )
305 ContainerEvent aMulti( e );
306 aMulti.Source = &m_rParent;
307 notifyEach( &XContainerListener::elementReplaced, aMulti );
311 //= FmXGridControlMultiplexer
314 FmXGridControlMultiplexer::FmXGridControlMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
315 :OWeakSubObject( rSource )
316 ,OInterfaceContainerHelper( _rMutex )
321 Any SAL_CALL FmXGridControlMultiplexer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
323 Any aReturn;
324 aReturn = ::cppu::queryInterface( _rType,
325 static_cast< XGridControlListener*>(this)
328 if (!aReturn.hasValue())
329 aReturn = OWeakSubObject::queryInterface( _rType );
331 return aReturn;
335 void FmXGridControlMultiplexer::disposing( const EventObject& ) throw( RuntimeException, std::exception )
340 void SAL_CALL FmXGridControlMultiplexer::columnChanged( const EventObject& _event ) throw (RuntimeException, std::exception)
342 EventObject aForwardedEvent( _event );
343 aForwardedEvent.Source = &m_rParent;
344 notifyEach( &XGridControlListener::columnChanged, aForwardedEvent );
348 //= FmXGridControl
352 Reference< XInterface > SAL_CALL FmXGridControl_NewInstance_Impl(const Reference< XMultiServiceFactory>& _rxFactory)
353 throw (css::uno::Exception)
355 return *(new FmXGridControl( comphelper::getComponentContext(_rxFactory) ));
358 FmXGridControl::FmXGridControl(const Reference< XComponentContext >& _rxContext)
359 :UnoControl()
360 ,m_aModifyListeners(*this, GetMutex())
361 ,m_aUpdateListeners(*this, GetMutex())
362 ,m_aContainerListeners(*this, GetMutex())
363 ,m_aSelectionListeners(*this, GetMutex())
364 ,m_aGridControlListeners(*this, GetMutex())
365 ,m_nPeerCreationLevel(0)
366 ,m_bInDraw(false)
367 ,m_xContext(_rxContext)
372 FmXGridControl::~FmXGridControl()
377 Any SAL_CALL FmXGridControl::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
379 Any aReturn = FmXGridControl_BASE::queryInterface(_rType);
381 if (!aReturn.hasValue())
382 aReturn = UnoControl::queryAggregation( _rType );
383 return aReturn;
387 Sequence< Type> SAL_CALL FmXGridControl::getTypes( ) throw(RuntimeException, std::exception)
389 return comphelper::concatSequences(UnoControl::getTypes(),FmXGridControl_BASE::getTypes());
393 Sequence<sal_Int8> SAL_CALL FmXGridControl::getImplementationId( ) throw(RuntimeException, std::exception)
395 return css::uno::Sequence<sal_Int8>();
398 // XServiceInfo
399 sal_Bool SAL_CALL FmXGridControl::supportsService(const OUString& ServiceName) throw(std::exception)
401 return cppu::supportsService(this, ServiceName);
404 OUString SAL_CALL FmXGridControl::getImplementationName() throw(std::exception)
406 return OUString("com.sun.star.form.FmXGridControl");
409 ::comphelper::StringSequence SAL_CALL FmXGridControl::getSupportedServiceNames() throw(std::exception)
411 Sequence< OUString > aServiceNames(2);
412 aServiceNames[0] = FM_SUN_CONTROL_GRIDCONTROL;
413 aServiceNames[1] = "com.sun.star.awt.UnoControl";
414 return aServiceNames;
418 void SAL_CALL FmXGridControl::dispose() throw( RuntimeException, std::exception )
420 SolarMutexGuard aGuard;
422 EventObject aEvt;
423 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
424 m_aModifyListeners.disposeAndClear(aEvt);
425 m_aUpdateListeners.disposeAndClear(aEvt);
426 m_aContainerListeners.disposeAndClear(aEvt);
428 UnoControl::dispose();
432 OUString FmXGridControl::GetComponentServiceName()
434 OUString aName("DBGrid");
435 return aName;
439 sal_Bool SAL_CALL FmXGridControl::setModel(const Reference< ::com::sun::star::awt::XControlModel >& rModel) throw( RuntimeException, std::exception )
441 SolarMutexGuard aGuard;
443 if (!UnoControl::setModel(rModel))
444 return sal_False;
446 Reference< XGridPeer > xGridPeer(getPeer(), UNO_QUERY);
447 if (xGridPeer.is())
449 Reference< XIndexContainer > xCols(mxModel, UNO_QUERY);
450 xGridPeer->setColumns(xCols);
452 return sal_True;
456 FmXGridPeer* FmXGridControl::imp_CreatePeer(Window* pParent)
458 FmXGridPeer* pReturn = new FmXGridPeer(m_xContext);
460 // translate properties into WinBits
461 WinBits nStyle = WB_TABSTOP;
462 Reference< XPropertySet > xModelSet(getModel(), UNO_QUERY);
463 if (xModelSet.is())
467 if (::comphelper::getINT16(xModelSet->getPropertyValue(FM_PROP_BORDER)))
468 nStyle |= WB_BORDER;
470 catch(const Exception&)
472 OSL_FAIL("Can not get style");
476 pReturn->Create(pParent, nStyle);
477 return pReturn;
481 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 )
483 if ( !mxModel.is() )
484 throw DisposedException( OUString(), *this );
486 DBG_ASSERT(/*(0 == m_nPeerCreationLevel) && */!mbCreatingPeer, "FmXGridControl::createPeer : recursion!");
487 // I think this should never assert, now that we're using the base class' mbCreatingPeer in addition to
488 // our own m_nPeerCreationLevel
489 // But I'm not sure as I don't _fully_ understand the underlying toolkit implementations ....
490 // (if this asserts, we still need m_nPeerCreationLevel. If not, we could omit it ....)
491 // 14.05.2001 - 86836 - frank.schoenheit@germany.sun.com
493 // TODO: why the hell this whole class does not use any mutex?
495 if (!getPeer().is())
497 mbCreatingPeer = true;
498 // mbCreatingPeer is virtually the same as m_nPeerCreationLevel, but it's the base class' method
499 // to prevent recursion.
501 Window* pParentWin = NULL;
502 if (rParentPeer.is())
504 VCLXWindow* pParent = VCLXWindow::GetImplementation(rParentPeer);
505 if (pParent)
506 pParentWin = pParent->GetWindow();
509 FmXGridPeer* pPeer = imp_CreatePeer(pParentWin);
510 DBG_ASSERT(pPeer != NULL, "FmXGridControl::createPeer : imp_CreatePeer didn't return a peer !");
511 setPeer( pPeer );
513 // reading the properties from the model
514 // ++m_nPeerCreationLevel;
515 updateFromModel();
517 // consider the following ugly scenario: updateFromModel leads to a propertiesChanges on the Control,
518 // which determines, dat a "critical" property has changed (e.g. "Border") and therefore starts a new
519 // Peer, which lands again here in createPeerm we also start a second FmXGridPeer and initialise it.
520 // Then we exit from the first incarnation's updateFromModel and continue working with the pPeer,
521 // that is in fact now already obsolete (as another peer is being started in the second incarnation).
522 // Therefore the effort with the PeerCreationLevel, which ensures that we really use the Peer
523 // created at the deepest level, but first initialise it in the top-level.
524 // if (--m_nPeerCreationLevel == 0)
526 DBG_ASSERT(getPeer().is(), "FmXGridControl::createPeer : something went wrong ... no top level peer !");
527 pPeer = FmXGridPeer::getImplementation(getPeer());
529 setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, ::com::sun::star::awt::PosSize::POSSIZE );
531 Reference< XIndexContainer > xColumns(getModel(), UNO_QUERY);
532 if (xColumns.is())
533 pPeer->setColumns(xColumns);
535 if (maComponentInfos.bVisible)
536 pPeer->setVisible(sal_True);
538 if (!maComponentInfos.bEnable)
539 pPeer->setEnable(sal_False);
541 if (maWindowListeners.getLength())
542 pPeer->addWindowListener( &maWindowListeners );
544 if (maFocusListeners.getLength())
545 pPeer->addFocusListener( &maFocusListeners );
547 if (maKeyListeners.getLength())
548 pPeer->addKeyListener( &maKeyListeners );
550 if (maMouseListeners.getLength())
551 pPeer->addMouseListener( &maMouseListeners );
553 if (maMouseMotionListeners.getLength())
554 pPeer->addMouseMotionListener( &maMouseMotionListeners );
556 if (maPaintListeners.getLength())
557 pPeer->addPaintListener( &maPaintListeners );
559 if (m_aModifyListeners.getLength())
560 pPeer->addModifyListener( &m_aModifyListeners );
562 if (m_aUpdateListeners.getLength())
563 pPeer->addUpdateListener( &m_aUpdateListeners );
565 if (m_aContainerListeners.getLength())
566 pPeer->addContainerListener( &m_aContainerListeners );
568 // forward the design mode
569 bool bForceAlivePeer = m_bInDraw && !maComponentInfos.bVisible;
570 // (we force an alive-mode peer if we're in "draw", cause in this case the peer will be used for drawing in
571 // foreign devices. We ensure this with the visibility check as an living peer is assumed to be noncritical
572 // only if invisible)
573 Any aOldCursorBookmark;
574 if (!mbDesignMode || bForceAlivePeer)
576 Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
577 if (xComp.is())
579 Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY);
580 // is the form alive?
581 // we can see that if the form contains columns
582 Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xColumnsSupplier(xForm, UNO_QUERY);
583 if (xColumnsSupplier.is())
585 if (Reference< XIndexAccess > (xColumnsSupplier->getColumns(),UNO_QUERY)->getCount())
587 // we get only a new bookmark if the resultset is not forwardonly
588 if (::comphelper::getINT32(Reference< XPropertySet > (xForm, UNO_QUERY)->getPropertyValue(FM_PROP_RESULTSET_TYPE)) != ResultSetType::FORWARD_ONLY)
590 // as the FmGridControl touches the data source it is connected to we have to remember the current
591 // cursor position (and restore afterwards)
592 // OJ: but only when we stand on a valid row
593 Reference< XResultSet > xResultSet(xForm, UNO_QUERY);
594 if ( !xResultSet->isBeforeFirst() && !xResultSet->isAfterLast() )
598 aOldCursorBookmark = Reference< ::com::sun::star::sdbcx::XRowLocate > (xForm, UNO_QUERY)->getBookmark();
600 catch( const Exception& e )
602 DBG_UNHANDLED_EXCEPTION();
603 (void)e;
609 pPeer->setRowSet(xForm);
612 pPeer->setDesignMode(mbDesignMode && !bForceAlivePeer);
616 if (aOldCursorBookmark.hasValue())
617 { // we have a valid bookmark, so we have to restore the cursor's position
618 Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
619 Reference< ::com::sun::star::sdbcx::XRowLocate > xLocate(xComp->getParent(), UNO_QUERY);
620 xLocate->moveToBookmark(aOldCursorBookmark);
623 catch( const Exception& e )
625 DBG_UNHANDLED_EXCEPTION();
626 (void)e;
629 Reference< ::com::sun::star::awt::XView > xPeerView(getPeer(), UNO_QUERY);
630 xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY );
631 xPeerView->setGraphics( mxGraphics );
633 mbCreatingPeer = false;
638 void FmXGridControl::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
640 m_aModifyListeners.addInterface( l );
641 if( getPeer().is() && m_aModifyListeners.getLength() == 1 )
643 Reference< ::com::sun::star::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY);
644 xGrid->addModifyListener( &m_aModifyListeners);
649 sal_Bool SAL_CALL FmXGridControl::select( const Any& _rSelection ) throw (IllegalArgumentException, RuntimeException, std::exception)
651 SolarMutexGuard aGuard;
652 Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY);
653 return xPeer->select(_rSelection);
657 Any SAL_CALL FmXGridControl::getSelection( ) throw (RuntimeException, std::exception)
659 SolarMutexGuard aGuard;
660 Reference< XSelectionSupplier > xPeer(getPeer(), UNO_QUERY);
661 return xPeer->getSelection();
665 void SAL_CALL FmXGridControl::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
667 m_aSelectionListeners.addInterface( _rxListener );
668 if( getPeer().is() && 1 == m_aSelectionListeners.getLength() )
670 Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY);
671 xGrid->addSelectionChangeListener( &m_aSelectionListeners);
676 void SAL_CALL FmXGridControl::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
678 if( getPeer().is() && 1 == m_aSelectionListeners.getLength() )
680 Reference< XSelectionSupplier > xGrid(getPeer(), UNO_QUERY);
681 xGrid->removeSelectionChangeListener( &m_aSelectionListeners);
683 m_aSelectionListeners.removeInterface( _rxListener );
687 Sequence< sal_Bool > SAL_CALL FmXGridControl::queryFieldDataType( const Type& xType ) throw(RuntimeException, std::exception)
689 if (getPeer().is())
691 Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY);
692 if (xPeerSupplier.is())
693 return xPeerSupplier->queryFieldDataType(xType);
696 return Sequence<sal_Bool>();
700 Sequence< Any > SAL_CALL FmXGridControl::queryFieldData( sal_Int32 nRow, const Type& xType ) throw(RuntimeException, std::exception)
702 if (getPeer().is())
704 Reference< XGridFieldDataSupplier > xPeerSupplier(getPeer(), UNO_QUERY);
705 if (xPeerSupplier.is())
706 return xPeerSupplier->queryFieldData(nRow, xType);
709 return Sequence< Any>();
713 void SAL_CALL FmXGridControl::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
715 if( getPeer().is() && m_aModifyListeners.getLength() == 1 )
717 Reference< ::com::sun::star::util::XModifyBroadcaster > xGrid(getPeer(), UNO_QUERY);
718 xGrid->removeModifyListener( &m_aModifyListeners);
720 m_aModifyListeners.removeInterface( l );
724 void SAL_CALL FmXGridControl::draw( sal_Int32 x, sal_Int32 y ) throw( RuntimeException, std::exception )
726 SolarMutexGuard aGuard;
727 m_bInDraw = true;
728 UnoControl::draw(x, y);
729 m_bInDraw = false;
733 void SAL_CALL FmXGridControl::setDesignMode(sal_Bool bOn) throw( RuntimeException, std::exception )
735 ::com::sun::star::util::ModeChangeEvent aModeChangeEvent;
737 // --- <mutex_lock> ---
739 SolarMutexGuard aGuard;
741 Reference< XRowSetSupplier > xGrid(getPeer(), UNO_QUERY);
743 if (xGrid.is() && (bool(bOn) != mbDesignMode || (!bOn && !xGrid->getRowSet().is())))
745 if (bOn)
747 xGrid->setRowSet(Reference< XRowSet > ());
749 else
751 Reference< XFormComponent > xComp(getModel(), UNO_QUERY);
752 if (xComp.is())
754 Reference< XRowSet > xForm(xComp->getParent(), UNO_QUERY);
755 xGrid->setRowSet(xForm);
759 mbDesignMode = bOn;
761 Reference< XVclWindowPeer > xVclWindowPeer( getPeer(), UNO_QUERY );
762 if (xVclWindowPeer.is())
763 xVclWindowPeer->setDesignMode(bOn);
765 mbDesignMode = bOn;
767 // dispose our current AccessibleContext, if we have one
768 // (changing the design mode implies having a new implementation for this context,
769 // so the old one must be declared DEFUNC)
770 DisposeAccessibleContext(
771 Reference<XComponent>(maAccessibleContext, UNO_QUERY));
772 maAccessibleContext.clear();
774 // prepare firing an event
775 aModeChangeEvent.Source = *this;
776 aModeChangeEvent.NewMode = mbDesignMode ? OUString( "design" ) : OUString( "alive" );
779 // --- </mutex_lock> ---
780 maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
783 // XBoundComponent
785 void SAL_CALL FmXGridControl::addUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
787 m_aUpdateListeners.addInterface( l );
788 if( getPeer().is() && m_aUpdateListeners.getLength() == 1 )
790 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
791 xBound->addUpdateListener( &m_aUpdateListeners);
796 void SAL_CALL FmXGridControl::removeUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
798 if( getPeer().is() && m_aUpdateListeners.getLength() == 1 )
800 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
801 xBound->removeUpdateListener( &m_aUpdateListeners);
803 m_aUpdateListeners.removeInterface( l );
807 sal_Bool SAL_CALL FmXGridControl::commit() throw( RuntimeException, std::exception )
809 Reference< XBoundComponent > xBound(getPeer(), UNO_QUERY);
810 if (xBound.is())
811 return xBound->commit();
812 else
813 return sal_True;
816 // XContainer
818 void SAL_CALL FmXGridControl::addContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
820 m_aContainerListeners.addInterface( l );
821 if( getPeer().is() && m_aContainerListeners.getLength() == 1 )
823 Reference< XContainer > xContainer(getPeer(), UNO_QUERY);
824 xContainer->addContainerListener( &m_aContainerListeners);
829 void SAL_CALL FmXGridControl::removeContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
831 if( getPeer().is() && m_aContainerListeners.getLength() == 1 )
833 Reference< XContainer > xContainer(getPeer(), UNO_QUERY);
834 xContainer->removeContainerListener( &m_aContainerListeners);
836 m_aContainerListeners.removeInterface( l );
840 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 )
842 Reference< ::com::sun::star::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY);
843 if (xPeerProvider.is())
844 return xPeerProvider->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
845 else
846 return Reference< ::com::sun::star::frame::XDispatch > ();
850 Sequence< Reference< ::com::sun::star::frame::XDispatch > > SAL_CALL FmXGridControl::queryDispatches(const Sequence< ::com::sun::star::frame::DispatchDescriptor>& aDescripts) throw( RuntimeException, std::exception )
852 Reference< ::com::sun::star::frame::XDispatchProvider > xPeerProvider(getPeer(), UNO_QUERY);
853 if (xPeerProvider.is())
854 return xPeerProvider->queryDispatches(aDescripts);
855 else
856 return Sequence< Reference< ::com::sun::star::frame::XDispatch > >();
860 void SAL_CALL FmXGridControl::registerDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
862 Reference< ::com::sun::star::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY);
863 if (xPeerInterception.is())
864 xPeerInterception->registerDispatchProviderInterceptor(_xInterceptor);
868 void SAL_CALL FmXGridControl::releaseDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
870 Reference< ::com::sun::star::frame::XDispatchProviderInterception > xPeerInterception(getPeer(), UNO_QUERY);
871 if (xPeerInterception.is())
872 xPeerInterception->releaseDispatchProviderInterceptor(_xInterceptor);
876 void SAL_CALL FmXGridControl::addGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
878 ::osl::MutexGuard aGuard( GetMutex() );
880 m_aGridControlListeners.addInterface( _listener );
881 if ( getPeer().is() && 1 == m_aGridControlListeners.getLength() )
883 Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY );
884 if ( xPeerGrid.is() )
885 xPeerGrid->addGridControlListener( &m_aGridControlListeners );
890 void SAL_CALL FmXGridControl::removeGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
892 ::osl::MutexGuard aGuard( GetMutex() );
894 if( getPeer().is() && 1 == m_aGridControlListeners.getLength() )
896 Reference< XGridControl > xPeerGrid( getPeer(), UNO_QUERY );
897 if ( xPeerGrid.is() )
898 xPeerGrid->removeGridControlListener( &m_aGridControlListeners );
901 m_aGridControlListeners.removeInterface( _listener );
905 sal_Int16 SAL_CALL FmXGridControl::getCurrentColumnPosition() throw( RuntimeException, std::exception )
907 Reference< XGridControl > xGrid( getPeer(), UNO_QUERY );
908 return xGrid.is() ? xGrid->getCurrentColumnPosition() : -1;
912 void SAL_CALL FmXGridControl::setCurrentColumnPosition(sal_Int16 nPos) throw( RuntimeException, std::exception )
914 Reference< XGridControl > xGrid( getPeer(), UNO_QUERY );
915 if ( xGrid.is() )
917 SolarMutexGuard aGuard;
918 xGrid->setCurrentColumnPosition( nPos );
922 // XElementAccess
924 sal_Bool SAL_CALL FmXGridControl::hasElements() throw( RuntimeException, std::exception )
926 Reference< XElementAccess > xPeer(getPeer(), UNO_QUERY);
927 return xPeer.is() ? xPeer->hasElements() : 0;
931 Type SAL_CALL FmXGridControl::getElementType( ) throw(RuntimeException, std::exception)
933 return cppu::UnoType<com::sun::star::awt::XTextComponent>::get();
936 // XEnumerationAccess
938 Reference< XEnumeration > SAL_CALL FmXGridControl::createEnumeration() throw( RuntimeException, std::exception )
940 Reference< XEnumerationAccess > xPeer(getPeer(), UNO_QUERY);
941 if (xPeer.is())
942 return xPeer->createEnumeration();
943 else
944 return new ::comphelper::OEnumerationByIndex(this);
947 // XIndexAccess
949 sal_Int32 SAL_CALL FmXGridControl::getCount() throw( RuntimeException, std::exception )
951 Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY);
952 return xPeer.is() ? xPeer->getCount() : 0;
956 Any SAL_CALL FmXGridControl::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
958 Reference< XIndexAccess > xPeer(getPeer(), UNO_QUERY);
959 if (!xPeer.is())
960 throw IndexOutOfBoundsException();
962 return xPeer->getByIndex(_nIndex);
965 // ::com::sun::star::util::XModeSelector
967 void SAL_CALL FmXGridControl::setMode(const OUString& Mode) throw( NoSupportException, RuntimeException, std::exception )
969 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
970 if (!xPeer.is())
971 throw NoSupportException();
973 xPeer->setMode(Mode);
977 OUString SAL_CALL FmXGridControl::getMode() throw( RuntimeException, std::exception )
979 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
980 return xPeer.is() ? xPeer->getMode() : OUString();
984 ::comphelper::StringSequence SAL_CALL FmXGridControl::getSupportedModes() throw( RuntimeException, std::exception )
986 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
987 return xPeer.is() ? xPeer->getSupportedModes() : ::comphelper::StringSequence();
991 sal_Bool SAL_CALL FmXGridControl::supportsMode(const OUString& Mode) throw( RuntimeException, std::exception )
993 Reference< ::com::sun::star::util::XModeSelector > xPeer(getPeer(), UNO_QUERY);
994 return xPeer.is() ? xPeer->supportsMode(Mode) : sal_False;
998 //= FmXGridPeer
1000 // helper class which prevents that in the peer's header the FmGridListener must be known
1001 class FmXGridPeer::GridListenerDelegator : public FmGridListener
1003 protected:
1004 FmXGridPeer* m_pPeer;
1006 public:
1007 GridListenerDelegator( FmXGridPeer* _pPeer );
1008 virtual ~GridListenerDelegator();
1010 protected:
1011 virtual void selectionChanged() SAL_OVERRIDE;
1012 virtual void columnChanged() SAL_OVERRIDE;
1016 FmXGridPeer::GridListenerDelegator::GridListenerDelegator(FmXGridPeer* _pPeer)
1017 :m_pPeer(_pPeer)
1019 DBG_ASSERT(m_pPeer, "GridListenerDelegator::GridListenerDelegator");
1022 FmXGridPeer::GridListenerDelegator::~GridListenerDelegator()
1027 void FmXGridPeer::GridListenerDelegator::selectionChanged()
1029 m_pPeer->selectionChanged();
1033 void FmXGridPeer::GridListenerDelegator::columnChanged()
1035 m_pPeer->columnChanged();
1038 Sequence< Type> SAL_CALL FmXGridPeer::getTypes( ) throw(RuntimeException, std::exception)
1040 return comphelper::concatSequences( VCLXWindow::getTypes(), FmXGridPeer_BASE::getTypes() );
1044 Sequence<sal_Int8> SAL_CALL FmXGridPeer::getImplementationId( ) throw(RuntimeException, std::exception)
1046 return css::uno::Sequence<sal_Int8>();
1050 Any SAL_CALL FmXGridPeer::queryInterface(const Type& _rType) throw (RuntimeException, std::exception)
1052 Any aReturn = FmXGridPeer_BASE::queryInterface(_rType);
1054 if (!aReturn.hasValue())
1055 aReturn = VCLXWindow::queryInterface( _rType );
1057 return aReturn;
1061 void FmXGridPeer::selectionChanged()
1063 EventObject aSource;
1064 aSource.Source = static_cast< ::cppu::OWeakObject* >(this);
1065 m_aSelectionListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aSource);
1069 void FmXGridPeer::columnChanged()
1071 EventObject aEvent( *this );
1072 m_aGridControlListeners.notifyEach( &XGridControlListener::columnChanged, aEvent );
1076 namespace fmgridif
1078 const OUString getDataModeIdentifier()
1080 return OUString("DataMode");
1083 using namespace fmgridif;
1086 FmXGridPeer::FmXGridPeer(const Reference< XComponentContext >& _rxContext)
1087 :m_aModifyListeners(m_aMutex)
1088 ,m_aUpdateListeners(m_aMutex)
1089 ,m_aContainerListeners(m_aMutex)
1090 ,m_aSelectionListeners(m_aMutex)
1091 ,m_aGridControlListeners(m_aMutex)
1092 ,m_aMode( getDataModeIdentifier() )
1093 ,m_nCursorListening(0)
1094 ,m_bInterceptingDispatch(false)
1095 ,m_pStateCache(NULL)
1096 ,m_pDispatchers(NULL)
1097 ,m_pGridListener(NULL)
1098 ,m_xContext(_rxContext)
1100 // Create must be called after this constructure
1101 m_pGridListener = new GridListenerDelegator( this );
1105 FmGridControl* FmXGridPeer::imp_CreateControl(Window* pParent, WinBits nStyle)
1107 return new FmGridControl(m_xContext, pParent, this, nStyle);
1111 void FmXGridPeer::Create(Window* pParent, WinBits nStyle)
1113 FmGridControl* pWin = imp_CreateControl(pParent, nStyle);
1114 DBG_ASSERT(pWin != NULL, "FmXGridPeer::Create : imp_CreateControl didn't return a control !");
1116 pWin->SetStateProvider(LINK(this, FmXGridPeer, OnQueryGridSlotState));
1117 pWin->SetSlotExecutor(LINK(this, FmXGridPeer, OnExecuteGridSlot));
1119 // want to hear about row selections
1120 pWin->setGridListener( m_pGridListener );
1122 // Init must always be called
1123 pWin->Init();
1124 pWin->SetComponentInterface(this);
1126 getSupportedURLs();
1130 FmXGridPeer::~FmXGridPeer()
1132 setRowSet(Reference< XRowSet > ());
1133 setColumns(Reference< XIndexContainer > ());
1135 delete m_pGridListener;
1138 namespace
1140 class theFmXGridPeerImplementationId : public rtl::Static< UnoTunnelIdInit, theFmXGridPeerImplementationId > {};
1143 const Sequence< sal_Int8 >& FmXGridPeer::getUnoTunnelImplementationId() throw()
1145 return theFmXGridPeerImplementationId::get().getSeq();
1149 FmXGridPeer* FmXGridPeer::getImplementation( const Reference< XInterface >& _rxIFace ) throw()
1151 FmXGridPeer* pReturn = NULL;
1152 Reference< XUnoTunnel > xTunnel(_rxIFace, UNO_QUERY);
1153 if (xTunnel.is())
1154 pReturn = reinterpret_cast<FmXGridPeer*>(xTunnel->getSomething(getUnoTunnelImplementationId()));
1156 return pReturn;
1160 sal_Int64 SAL_CALL FmXGridPeer::getSomething( const Sequence< sal_Int8 >& _rIdentifier ) throw(RuntimeException, std::exception)
1162 sal_Int64 nReturn(0);
1164 if ( (_rIdentifier.getLength() == 16)
1165 && (0 == memcmp( getUnoTunnelImplementationId().getConstArray(), _rIdentifier.getConstArray(), 16 ))
1168 nReturn = reinterpret_cast<sal_Int64>(this);
1170 else
1171 nReturn = VCLXWindow::getSomething(_rIdentifier);
1173 return nReturn;
1176 // XEventListener
1178 void FmXGridPeer::disposing(const EventObject& e) throw( RuntimeException, std::exception )
1180 using namespace ::com::sun::star::util;
1181 bool bKnownSender = false;
1183 Reference< XIndexContainer > xCols( e.Source, UNO_QUERY );
1184 if ( xCols.is() )
1186 setColumns(Reference< XIndexContainer > ());
1187 bKnownSender = true;
1190 Reference< XRowSet > xCursor(e.Source, UNO_QUERY);
1191 if (xCursor.is())
1193 setRowSet( m_xCursor );
1194 m_xCursor = NULL;
1195 bKnownSender = true;
1199 if ( !bKnownSender && m_pDispatchers )
1201 const Sequence< URL>& aSupportedURLs = getSupportedURLs();
1202 const URL* pSupportedURLs = aSupportedURLs.getConstArray();
1203 for ( sal_uInt16 i=0; i < ( aSupportedURLs.getLength() ) && !bKnownSender; ++i, ++pSupportedURLs )
1205 if ( m_pDispatchers[i] == e.Source )
1207 m_pDispatchers[i]->removeStatusListener( static_cast< ::com::sun::star::frame::XStatusListener* >( this ), *pSupportedURLs );
1208 m_pDispatchers[i] = NULL;
1209 m_pStateCache[i] = false;
1210 bKnownSender = true;
1215 if ( !bKnownSender )
1216 VCLXWindow::disposing(e);
1220 void FmXGridPeer::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
1222 m_aModifyListeners.addInterface( l );
1226 void FmXGridPeer::removeModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException, std::exception )
1228 m_aModifyListeners.removeInterface( l );
1232 #define LAST_KNOWN_TYPE FormComponentType::PATTERNFIELD
1233 Sequence< sal_Bool > SAL_CALL FmXGridPeer::queryFieldDataType( const Type& xType ) throw(RuntimeException, std::exception)
1235 // eine 'Konvertierungstabelle'
1236 static const sal_Bool bCanConvert[LAST_KNOWN_TYPE][4] =
1238 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::CONTROL
1239 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::COMMANDBUTTON
1240 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::RADIOBUTTON
1241 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::IMAGEBUTTON
1242 { sal_False, sal_False, sal_False, sal_True }, // FormComponentType::CHECKBOX
1243 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::LISTBOX
1244 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::COMBOBOX
1245 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::GROUPBOX
1246 { sal_True , sal_False, sal_False, sal_False }, // FormComponentType::TEXTFIELD
1247 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::FIXEDTEXT
1248 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::GRIDCONTROL
1249 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::FILECONTROL
1250 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::HIDDENCONTROL
1251 { sal_False, sal_False, sal_False, sal_False }, // FormComponentType::IMAGECONTROL
1252 { sal_True , sal_True , sal_True , sal_False }, // FormComponentType::DATEFIELD
1253 { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::TIMEFIELD
1254 { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::NUMERICFIELD
1255 { sal_True , sal_True , sal_False, sal_False }, // FormComponentType::CURRENCYFIELD
1256 { sal_True , sal_False, sal_False, sal_False } // FormComponentType::PATTERNFIELD
1260 sal_Int16 nMapColumn = -1;
1261 switch (xType.getTypeClass())
1263 case TypeClass_STRING : nMapColumn = 0; break;
1264 case TypeClass_FLOAT:
1265 case TypeClass_DOUBLE : nMapColumn = 1; break;
1266 case TypeClass_SHORT:
1267 case TypeClass_LONG:
1268 case TypeClass_UNSIGNED_LONG:
1269 case TypeClass_UNSIGNED_SHORT : nMapColumn = 2; break;
1270 case TypeClass_BOOLEAN : nMapColumn = 3; break;
1271 default:
1272 break;
1275 Reference< XIndexContainer > xColumns = getColumns();
1277 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1278 sal_Int32 nColumns = pGrid->GetViewColCount();
1280 DbGridColumns aColumns = pGrid->GetColumns();
1282 Sequence<sal_Bool> aReturnSequence(nColumns);
1283 sal_Bool* pReturnArray = aReturnSequence.getArray();
1285 bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY);
1287 DbGridColumn* pCol;
1288 Reference< ::com::sun::star::sdb::XColumn > xFieldContent;
1289 Reference< XPropertySet > xCurrentColumn;
1290 for (sal_Int32 i=0; i<nColumns; ++i)
1292 if (bRequestedAsAny)
1294 pReturnArray[i] = sal_True;
1295 continue;
1298 pReturnArray[i] = sal_False;
1300 sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i));
1301 DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldDataType : no model pos !");
1303 pCol = aColumns[ nModelPos ];
1304 const DbGridRowRef xRow = pGrid->GetSeekRow();
1305 xFieldContent = (xRow.Is() && xRow->HasField(pCol->GetFieldPos())) ? xRow->GetField(pCol->GetFieldPos()).getColumn() : Reference< ::com::sun::star::sdb::XColumn > ();
1306 if (!xFieldContent.is())
1307 // can't supply anything without a field content
1308 // FS - 07.12.99 - 54391
1309 continue;
1311 xColumns->getByIndex(nModelPos) >>= xCurrentColumn;
1312 if (!::comphelper::hasProperty(FM_PROP_CLASSID, xCurrentColumn))
1313 continue;
1315 sal_Int16 nClassId = sal_Int16();
1316 xCurrentColumn->getPropertyValue(FM_PROP_CLASSID) >>= nClassId;
1317 if (nClassId>LAST_KNOWN_TYPE)
1318 continue;
1319 DBG_ASSERT(nClassId>0, "FmXGridPeer::queryFieldDataType : somebody changed the definition of the FormComponentType enum !");
1321 if (nMapColumn != -1)
1322 pReturnArray[i] = bCanConvert[nClassId-1][nMapColumn];
1325 return aReturnSequence;
1329 Sequence< Any > SAL_CALL FmXGridPeer::queryFieldData( sal_Int32 nRow, const Type& xType ) throw(RuntimeException, std::exception)
1331 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1332 DBG_ASSERT(pGrid && pGrid->IsOpen(), "FmXGridPeer::queryFieldData : have no valid grid window !");
1333 if (!pGrid || !pGrid->IsOpen())
1334 return Sequence< Any>();
1336 // das Control zur angegebenen Row fahren
1337 if (!pGrid->SeekRow(nRow))
1339 throw IllegalArgumentException();
1342 // don't use GetCurrentRow as this isn't affected by the above SeekRow
1343 // FS - 30.09.99 - 68644
1344 DbGridRowRef xPaintRow = pGrid->GetPaintRow();
1345 ENSURE_OR_THROW( xPaintRow.Is(), "invalid paint row" );
1347 // I need the columns of the control for GetFieldText
1348 DbGridColumns aColumns = pGrid->GetColumns();
1350 // und durch alle Spalten durch
1351 sal_Int32 nColumnCount = pGrid->GetViewColCount();
1353 Sequence< Any> aReturnSequence(nColumnCount);
1354 Any* pReturnArray = aReturnSequence.getArray();
1356 bool bRequestedAsAny = (xType.getTypeClass() == TypeClass_ANY);
1357 Reference< ::com::sun::star::sdb::XColumn > xFieldContent;
1358 DbGridColumn* pCol;
1359 for (sal_Int32 i=0; i < nColumnCount; ++i)
1361 sal_uInt16 nModelPos = pGrid->GetModelColumnPos(pGrid->GetColumnIdFromViewPos((sal_uInt16)i));
1362 DBG_ASSERT(nModelPos != (sal_uInt16)-1, "FmXGridPeer::queryFieldData : invalid model pos !");
1364 // don't use GetCurrentFieldValue to determine the field content as this isn't affected by the above SeekRow
1365 // FS - 30.09.99 - 68644
1366 pCol = aColumns[ nModelPos ];
1367 xFieldContent = xPaintRow->HasField( pCol->GetFieldPos() )
1368 ? xPaintRow->GetField( pCol->GetFieldPos() ).getColumn()
1369 : Reference< XColumn > ();
1371 if ( !xFieldContent.is() )
1372 continue;
1374 if (bRequestedAsAny)
1376 Reference< XPropertySet > xFieldSet(xFieldContent, UNO_QUERY);
1377 pReturnArray[i] = xFieldSet->getPropertyValue(FM_PROP_VALUE);
1379 else
1381 switch (xType.getTypeClass())
1383 // Strings are dealt with directly by the GetFieldText
1384 case TypeClass_STRING :
1386 OUString sText = aColumns[ nModelPos ]->GetCellText( xPaintRow, pGrid->getNumberFormatter() );
1387 pReturnArray[i] <<= sText;
1389 break;
1390 // everything else is requested in the DatabaseVariant
1391 case TypeClass_FLOAT : pReturnArray[i] <<= xFieldContent->getFloat(); break;
1392 case TypeClass_DOUBLE : pReturnArray[i] <<= xFieldContent->getDouble(); break;
1393 case TypeClass_SHORT : pReturnArray[i] <<= (sal_Int16)xFieldContent->getShort(); break;
1394 case TypeClass_LONG : pReturnArray[i] <<= (sal_Int32)xFieldContent->getLong(); break;
1395 case TypeClass_UNSIGNED_SHORT : pReturnArray[i] <<= (sal_uInt16)xFieldContent->getShort(); break;
1396 case TypeClass_UNSIGNED_LONG : pReturnArray[i] <<= (sal_uInt32)xFieldContent->getLong(); break;
1397 case TypeClass_BOOLEAN : ::comphelper::setBOOL(pReturnArray[i],xFieldContent->getBoolean()); break;
1398 default:
1400 throw IllegalArgumentException();
1405 return aReturnSequence;
1409 void FmXGridPeer::CellModified()
1411 EventObject aEvt;
1412 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
1413 m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
1416 // XPropertyChangeListener
1418 void FmXGridPeer::propertyChange(const PropertyChangeEvent& evt) throw( RuntimeException, std::exception )
1420 SolarMutexGuard aGuard;
1421 // want to do a lot of VCL stuff here ...
1422 // this should not be (deadlock) critical, as by definition, every component should release
1423 // any own mutexes before notifying
1425 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1426 if (!pGrid)
1427 return;
1429 // Database event
1430 Reference< XRowSet > xCursor(evt.Source, UNO_QUERY);
1431 if (evt.PropertyName == FM_PROP_VALUE || m_xCursor == evt.Source)
1432 pGrid->propertyChange(evt);
1433 else if (pGrid && m_xColumns.is() && m_xColumns->hasElements())
1435 // next find which column has changed
1436 ::comphelper::InterfaceRef xCurrent;
1437 sal_Int32 i;
1439 for ( i = 0; i < m_xColumns->getCount(); i++)
1441 xCurrent.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
1442 if (evt.Source == xCurrent)
1443 break;
1446 if (i >= m_xColumns->getCount())
1447 // this is valid because we are listening at the cursor, too (RecordCount, -status, edit mode)
1448 return;
1450 sal_uInt16 nId = pGrid->GetColumnIdFromModelPos((sal_uInt16)i);
1451 bool bInvalidateColumn = false;
1453 if (evt.PropertyName == FM_PROP_LABEL)
1455 OUString aName = ::comphelper::getString(evt.NewValue);
1456 if (aName != pGrid->GetColumnTitle(nId))
1457 pGrid->SetColumnTitle(nId, aName);
1459 else if (evt.PropertyName == FM_PROP_WIDTH)
1461 sal_Int32 nWidth = 0;
1462 if (evt.NewValue.getValueType().getTypeClass() == TypeClass_VOID)
1463 nWidth = pGrid->GetDefaultColumnWidth(pGrid->GetColumnTitle(nId));
1464 // GetDefaultColumnWidth already considered the zoom factor
1465 else
1467 sal_Int32 nTest = 0;
1468 if (evt.NewValue >>= nTest)
1470 nWidth = pGrid->LogicToPixel(Point(nTest,0),MAP_10TH_MM).X();
1471 // take the zoom factor into account
1472 nWidth = pGrid->CalcZoom(nWidth);
1475 if (nWidth != (sal_Int32(pGrid->GetColumnWidth(nId))))
1477 if (pGrid->IsEditing())
1479 pGrid->DeactivateCell();
1480 pGrid->ActivateCell();
1482 pGrid->SetColumnWidth(nId, nWidth);
1485 else if (evt.PropertyName == FM_PROP_HIDDEN)
1487 DBG_ASSERT(evt.NewValue.getValueType().getTypeClass() == TypeClass_BOOLEAN,
1488 "FmXGridPeer::propertyChange : the property 'hidden' should be of type boolean !");
1489 if (::comphelper::getBOOL(evt.NewValue))
1490 pGrid->HideColumn(nId);
1491 else
1492 pGrid->ShowColumn(nId);
1494 else if (evt.PropertyName == FM_PROP_ALIGN)
1496 // in design mode it doesn't matter
1497 if (!isDesignMode())
1499 DbGridColumn* pCol = pGrid->GetColumns().at( i );
1501 pCol->SetAlignmentFromModel(-1);
1502 bInvalidateColumn = true;
1505 else if (evt.PropertyName == FM_PROP_FORMATKEY)
1507 if (!isDesignMode())
1508 bInvalidateColumn = true;
1511 // need to invalidate the affected column ?
1512 if (bInvalidateColumn)
1514 bool bWasEditing = pGrid->IsEditing();
1515 if (bWasEditing)
1516 pGrid->DeactivateCell();
1518 ::Rectangle aColRect = pGrid->GetFieldRect(nId);
1519 aColRect.Top() = 0;
1520 aColRect.Bottom() = pGrid->GetSizePixel().Height();
1521 pGrid->Invalidate(aColRect);
1523 if (bWasEditing)
1524 pGrid->ActivateCell();
1529 // XBoundComponent
1531 void FmXGridPeer::addUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
1533 m_aUpdateListeners.addInterface(l);
1537 void FmXGridPeer::removeUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException, std::exception )
1539 m_aUpdateListeners.removeInterface(l);
1543 sal_Bool FmXGridPeer::commit() throw( RuntimeException, std::exception )
1545 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1546 if (!m_xCursor.is() || !pGrid)
1547 return sal_True;
1549 EventObject aEvt(static_cast< ::cppu::OWeakObject* >(this));
1550 ::cppu::OInterfaceIteratorHelper aIter(m_aUpdateListeners);
1551 bool bCancel = false;
1552 while (aIter.hasMoreElements() && !bCancel)
1553 if ( !static_cast< XUpdateListener* >( aIter.next() )->approveUpdate( aEvt ) )
1554 bCancel = true;
1556 if (!bCancel)
1557 bCancel = !pGrid->commit();
1559 if (!bCancel)
1560 m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvt );
1561 return !bCancel;
1566 void FmXGridPeer::cursorMoved(const EventObject& _rEvent) throw( RuntimeException, std::exception )
1568 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1569 // we are not interested in move to insert row only in the resetted event
1570 // which is fired after positioning an the insert row
1571 if (pGrid && pGrid->IsOpen() && !::comphelper::getBOOL(Reference< XPropertySet > (_rEvent.Source, UNO_QUERY)->getPropertyValue(FM_PROP_ISNEW)))
1572 pGrid->positioned(_rEvent);
1576 void FmXGridPeer::rowChanged(const EventObject& _rEvent) throw( RuntimeException, std::exception )
1578 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1579 if (pGrid && pGrid->IsOpen())
1581 if (m_xCursor->rowUpdated() && !pGrid->IsCurrentAppending())
1582 pGrid->RowModified(pGrid->GetCurrentPos());
1583 else if (m_xCursor->rowInserted())
1584 pGrid->inserted(_rEvent);
1589 void FmXGridPeer::rowSetChanged(const EventObject& /*event*/) throw( RuntimeException, std::exception )
1591 // not interested in ...
1592 // (our parent is a form which means we get a loaded or reloaded after this rowSetChanged)
1595 // XLoadListener
1597 void FmXGridPeer::loaded(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
1599 updateGrid(m_xCursor);
1603 void FmXGridPeer::unloaded(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
1605 updateGrid( Reference< XRowSet > (NULL) );
1609 void FmXGridPeer::reloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
1611 // empty the grid
1612 updateGrid( Reference< XRowSet > (NULL) );
1616 void FmXGridPeer::unloading(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
1618 // empty the grid
1619 updateGrid( Reference< XRowSet > (NULL) );
1623 void FmXGridPeer::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException, std::exception )
1625 updateGrid(m_xCursor);
1628 // XGridPeer
1630 Reference< XIndexContainer > FmXGridPeer::getColumns() throw( RuntimeException, std::exception )
1632 return m_xColumns;
1636 void FmXGridPeer::addColumnListeners(const Reference< XPropertySet >& xCol)
1638 static const OUString aPropsListenedTo[] =
1640 OUString(FM_PROP_LABEL), OUString(FM_PROP_WIDTH), OUString(FM_PROP_HIDDEN), OUString(FM_PROP_ALIGN), OUString(FM_PROP_FORMATKEY)
1643 // as not all properties have to be supported by all columns we have to check this
1644 // before adding a listener
1645 Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo();
1646 Property aPropDesc;
1647 const OUString* pProps = aPropsListenedTo;
1648 const OUString* pPropsEnd = pProps + sizeof( aPropsListenedTo ) / sizeof( aPropsListenedTo[ 0 ] );
1649 for (; pProps != pPropsEnd; ++pProps)
1651 if ( xInfo->hasPropertyByName( *pProps ) )
1653 aPropDesc = xInfo->getPropertyByName( *pProps );
1654 if ( 0 != ( aPropDesc.Attributes & PropertyAttribute::BOUND ) )
1655 xCol->addPropertyChangeListener( *pProps, this );
1661 void FmXGridPeer::removeColumnListeners(const Reference< XPropertySet >& xCol)
1663 // the same props as in addColumnListeners ... linux has problems with global static UStrings, so
1664 // we have to do it this way ....
1665 static OUString aPropsListenedTo[] =
1667 OUString(FM_PROP_LABEL), OUString(FM_PROP_WIDTH), OUString(FM_PROP_HIDDEN), OUString(FM_PROP_ALIGN), OUString(FM_PROP_FORMATKEY)
1670 Reference< XPropertySetInfo > xInfo = xCol->getPropertySetInfo();
1671 for (sal_uInt16 i=0; i<sizeof(aPropsListenedTo)/sizeof(aPropsListenedTo[0]); ++i)
1672 if (xInfo->hasPropertyByName(aPropsListenedTo[i]))
1673 xCol->removePropertyChangeListener(aPropsListenedTo[i], this);
1677 void FmXGridPeer::setColumns(const Reference< XIndexContainer >& Columns) throw( RuntimeException, std::exception )
1679 SolarMutexGuard aGuard;
1681 FmGridControl* pGrid = static_cast< FmGridControl* >( GetWindow() );
1683 if (m_xColumns.is())
1685 Reference< XPropertySet > xCol;
1686 for (sal_Int32 i = 0; i < m_xColumns->getCount(); i++)
1688 xCol.set(m_xColumns->getByIndex(i), css::uno::UNO_QUERY);
1689 removeColumnListeners(xCol);
1691 Reference< XContainer > xContainer(m_xColumns, UNO_QUERY);
1692 xContainer->removeContainerListener(this);
1694 Reference< XSelectionSupplier > xSelSupplier(m_xColumns, UNO_QUERY);
1695 xSelSupplier->removeSelectionChangeListener(this);
1697 Reference< XReset > xColumnReset(m_xColumns, UNO_QUERY);
1698 if (xColumnReset.is())
1699 xColumnReset->removeResetListener((XResetListener*)this);
1701 if (Columns.is())
1703 Reference< XContainer > xContainer(Columns, UNO_QUERY);
1704 xContainer->addContainerListener(this);
1706 Reference< XSelectionSupplier > xSelSupplier(Columns, UNO_QUERY);
1707 xSelSupplier->addSelectionChangeListener(this);
1709 Reference< XPropertySet > xCol;
1710 for (sal_Int32 i = 0; i < Columns->getCount(); i++)
1712 xCol.set(Columns->getByIndex(i), css::uno::UNO_QUERY);
1713 addColumnListeners(xCol);
1716 Reference< XReset > xColumnReset(Columns, UNO_QUERY);
1717 if (xColumnReset.is())
1718 xColumnReset->addResetListener((XResetListener*)this);
1720 m_xColumns = Columns;
1721 if (pGrid)
1723 pGrid->InitColumnsByModels(m_xColumns);
1725 if (m_xColumns.is())
1727 EventObject aEvt(m_xColumns);
1728 selectionChanged(aEvt);
1734 void FmXGridPeer::setDesignMode(sal_Bool bOn) throw( RuntimeException, std::exception )
1736 if (bOn != isDesignMode())
1738 Window* pWin = GetWindow();
1739 if (pWin)
1740 ((FmGridControl*) pWin)->SetDesignMode(bOn);
1743 if (bOn)
1744 DisConnectFromDispatcher();
1745 else
1746 UpdateDispatches(); // will connect if not already connected and just update else
1750 sal_Bool FmXGridPeer::isDesignMode() throw( RuntimeException, std::exception )
1752 Window* pWin = GetWindow();
1753 if (pWin)
1754 return ((FmGridControl*) pWin)->IsDesignMode();
1755 else
1756 return sal_False;
1760 void FmXGridPeer::elementInserted(const ContainerEvent& evt) throw( RuntimeException, std::exception )
1762 SolarMutexGuard aGuard;
1764 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1765 // Handle Column beruecksichtigen
1766 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount()))
1767 return;
1769 Reference< XPropertySet > xSet(evt.Element, css::uno::UNO_QUERY);
1770 addColumnListeners(xSet);
1772 Reference< XPropertySet > xNewColumn(xSet);
1773 OUString aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL));
1774 Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH);
1775 sal_Int32 nWidth = 0;
1776 if (aWidth >>= nWidth)
1777 nWidth = pGrid->LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X();
1779 pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor));
1781 // jetzt die Spalte setzen
1782 DbGridColumn* pCol = pGrid->GetColumns().at( ::comphelper::getINT32(evt.Accessor) );
1783 pCol->setModel(xNewColumn);
1785 Any aHidden = xNewColumn->getPropertyValue(FM_PROP_HIDDEN);
1786 if (::comphelper::getBOOL(aHidden))
1787 pGrid->HideColumn(pCol->GetId());
1789 FormControlFactory( m_xContext ).initializeTextFieldLineEnds( xNewColumn );
1793 void FmXGridPeer::elementReplaced(const ContainerEvent& evt) throw( RuntimeException, std::exception )
1795 SolarMutexGuard aGuard;
1797 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1799 // Handle Column beruecksichtigen
1800 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove())
1801 return;
1803 Reference< XPropertySet > xNewColumn(evt.Element, css::uno::UNO_QUERY);
1804 Reference< XPropertySet > xOldColumn(
1805 evt.ReplacedElement, css::uno::UNO_QUERY);
1807 bool bWasEditing = pGrid->IsEditing();
1808 if (bWasEditing)
1809 pGrid->DeactivateCell();
1811 pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor)));
1813 removeColumnListeners(xOldColumn);
1814 addColumnListeners(xNewColumn);
1816 OUString aName = ::comphelper::getString(xNewColumn->getPropertyValue(FM_PROP_LABEL));
1817 Any aWidth = xNewColumn->getPropertyValue(FM_PROP_WIDTH);
1818 sal_Int32 nWidth = 0;
1819 if (aWidth >>= nWidth)
1820 nWidth = pGrid->LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X();
1821 sal_uInt16 nNewId = pGrid->AppendColumn(aName, (sal_uInt16)nWidth, (sal_Int16)::comphelper::getINT32(evt.Accessor));
1822 sal_uInt16 nNewPos = pGrid->GetModelColumnPos(nNewId);
1824 // set the model of the new column
1825 DbGridColumn* pCol = pGrid->GetColumns().at( nNewPos );
1827 // for initializong this grid column, we need the fields of the grid's data source
1828 Reference< XColumnsSupplier > xSuppColumns;
1829 CursorWrapper* pGridDataSource = pGrid->getDataSource();
1830 if ( pGridDataSource )
1831 xSuppColumns = xSuppColumns.query( (Reference< XInterface >)( *pGridDataSource ) );
1832 Reference< XNameAccess > xColumnsByName;
1833 if ( xSuppColumns.is() )
1834 xColumnsByName = xSuppColumns->getColumns();
1835 Reference< XIndexAccess > xColumnsByIndex( xColumnsByName, UNO_QUERY );
1837 if ( xColumnsByIndex.is() )
1838 pGrid->InitColumnByField( pCol, xNewColumn, xColumnsByName, xColumnsByIndex );
1839 else
1840 // the simple version, applies when the grid is not yet connected to a data source
1841 pCol->setModel(xNewColumn);
1843 if (bWasEditing)
1844 pGrid->ActivateCell();
1848 void FmXGridPeer::elementRemoved(const ContainerEvent& evt) throw( RuntimeException, std::exception )
1850 SolarMutexGuard aGuard;
1852 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1854 // Handle Column beruecksichtigen
1855 if (!pGrid || !m_xColumns.is() || pGrid->IsInColumnMove() || m_xColumns->getCount() == ((sal_Int32)pGrid->GetModelColCount()))
1856 return;
1858 pGrid->RemoveColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)::comphelper::getINT32(evt.Accessor)));
1860 Reference< XPropertySet > xOldColumn(evt.Element, css::uno::UNO_QUERY);
1861 removeColumnListeners(xOldColumn);
1865 void FmXGridPeer::setProperty( const OUString& PropertyName, const Any& Value) throw( RuntimeException, std::exception )
1867 SolarMutexGuard aGuard;
1869 FmGridControl* pGrid = (FmGridControl*) GetWindow();
1871 bool bVoid = !Value.hasValue();
1873 if ( PropertyName == FM_PROP_TEXTLINECOLOR )
1875 ::Color aTextLineColor( bVoid ? COL_TRANSPARENT : ::comphelper::getINT32( Value ) );
1876 if (bVoid)
1878 pGrid->SetTextLineColor();
1879 pGrid->GetDataWindow().SetTextLineColor();
1881 else
1883 pGrid->SetTextLineColor(aTextLineColor);
1884 pGrid->GetDataWindow().SetTextLineColor(aTextLineColor);
1887 // need to forward this to the columns
1888 DbGridColumns& rColumns = const_cast<DbGridColumns&>(pGrid->GetColumns());
1889 for ( size_t i = 0, n = rColumns.size(); i < n; ++i )
1891 DbGridColumn* pLoop = rColumns[ i ];
1892 FmXGridCell* pXCell = pLoop->GetCell();
1893 if (pXCell)
1895 if (bVoid)
1896 pXCell->SetTextLineColor();
1897 else
1898 pXCell->SetTextLineColor(aTextLineColor);
1902 if (isDesignMode())
1903 pGrid->Invalidate();
1905 else if ( PropertyName == FM_PROP_FONTEMPHASISMARK )
1907 Font aGridFont = pGrid->GetControlFont();
1908 sal_Int16 nValue = ::comphelper::getINT16(Value);
1909 aGridFont.SetEmphasisMark( nValue );
1910 pGrid->SetControlFont( aGridFont );
1912 else if ( PropertyName == FM_PROP_FONTRELIEF )
1914 Font aGridFont = pGrid->GetControlFont();
1915 sal_Int16 nValue = ::comphelper::getINT16(Value);
1916 aGridFont.SetRelief( (FontRelief)nValue );
1917 pGrid->SetControlFont( aGridFont );
1919 else if ( PropertyName == FM_PROP_HELPURL )
1921 OUString sHelpURL;
1922 OSL_VERIFY( Value >>= sHelpURL );
1923 INetURLObject aHID( sHelpURL );
1924 if ( aHID.GetProtocol() == INET_PROT_HID )
1925 sHelpURL = aHID.GetURLPath();
1926 pGrid->SetHelpId( OUStringToOString( sHelpURL, RTL_TEXTENCODING_UTF8 ) );
1928 else if ( PropertyName == FM_PROP_DISPLAYSYNCHRON )
1930 pGrid->setDisplaySynchron(::comphelper::getBOOL(Value));
1932 else if ( PropertyName == FM_PROP_CURSORCOLOR )
1934 if (bVoid)
1935 pGrid->SetCursorColor(COL_TRANSPARENT);
1936 else
1937 pGrid->SetCursorColor( ::Color(::comphelper::getINT32(Value)));
1938 if (isDesignMode())
1939 pGrid->Invalidate();
1941 else if ( PropertyName == FM_PROP_ALWAYSSHOWCURSOR )
1943 pGrid->EnablePermanentCursor(::comphelper::getBOOL(Value));
1944 if (isDesignMode())
1945 pGrid->Invalidate();
1947 else if ( PropertyName == FM_PROP_FONT )
1949 if ( bVoid )
1950 pGrid->SetControlFont( Font() );
1951 else
1953 ::com::sun::star::awt::FontDescriptor aFont;
1954 if (Value >>= aFont)
1956 Font aNewVclFont;
1957 if (::comphelper::operator!=(aFont, ::comphelper::getDefaultFont())) // ist das der Default
1958 aNewVclFont = ImplCreateFont( aFont );
1960 // need to add relief and emphasis (they're stored in a VCL-Font, but not in a FontDescriptor
1961 Font aOldVclFont = pGrid->GetControlFont();
1962 aNewVclFont.SetRelief( aOldVclFont.GetRelief() );
1963 aNewVclFont.SetEmphasisMark( aOldVclFont.GetEmphasisMark() );
1965 // now set it ...
1966 pGrid->SetControlFont( aNewVclFont );
1968 // if our row-height property is void (which means "calculate it font-dependent") we have
1969 // to adjust the control's row height
1970 Reference< XPropertySet > xModelSet(getColumns(), UNO_QUERY);
1971 if (xModelSet.is() && ::comphelper::hasProperty(FM_PROP_ROWHEIGHT, xModelSet))
1973 Any aHeight = xModelSet->getPropertyValue(FM_PROP_ROWHEIGHT);
1974 if (!aHeight.hasValue())
1975 pGrid->SetDataRowHeight(0);
1981 else if ( PropertyName == FM_PROP_BACKGROUNDCOLOR )
1983 if ( bVoid )
1985 pGrid->SetControlBackground();
1987 else
1989 ::Color aColor( ::comphelper::getINT32(Value) );
1990 pGrid->SetBackground( aColor );
1991 pGrid->SetControlBackground( aColor );
1994 else if ( PropertyName == FM_PROP_TEXTCOLOR )
1996 if ( bVoid )
1998 pGrid->SetControlForeground();
2000 else
2002 ::Color aColor( ::comphelper::getINT32(Value) );
2003 pGrid->SetTextColor( aColor );
2004 pGrid->SetControlForeground( aColor );
2007 else if ( PropertyName == FM_PROP_ROWHEIGHT )
2009 sal_Int32 nLogHeight(0);
2010 if (Value >>= nLogHeight)
2012 sal_Int32 nHeight = pGrid->LogicToPixel(Point(0,nLogHeight),MAP_10TH_MM).Y();
2013 // take the zoom factor into account
2014 nHeight = pGrid->CalcZoom(nHeight);
2015 pGrid->SetDataRowHeight(nHeight);
2017 else if (bVoid)
2018 pGrid->SetDataRowHeight(0);
2020 else if ( PropertyName == FM_PROP_HASNAVIGATION )
2022 bool bValue( true );
2023 OSL_VERIFY( Value >>= bValue );
2024 pGrid->EnableNavigationBar( bValue );
2026 else if ( PropertyName == FM_PROP_RECORDMARKER )
2028 bool bValue( true );
2029 OSL_VERIFY( Value >>= bValue );
2030 pGrid->EnableHandle( bValue );
2032 else if ( PropertyName == FM_PROP_ENABLED )
2034 bool bValue( true );
2035 OSL_VERIFY( Value >>= bValue );
2037 // In design mode, disable only the data window.
2038 // Else the control cannot be configured anymore.
2039 if (isDesignMode())
2040 pGrid->GetDataWindow().Enable( bValue );
2041 else
2042 pGrid->Enable( bValue );
2044 else
2045 VCLXWindow::setProperty( PropertyName, Value );
2049 Reference< XAccessibleContext > FmXGridPeer::CreateAccessibleContext()
2051 Reference< XAccessibleContext > xContext;
2053 // use the AccessibleContext provided by the VCL window
2054 Window* pGrid = GetWindow();
2055 if ( pGrid )
2057 Reference< XAccessible > xAcc( pGrid->GetAccessible( true ) );
2058 if ( xAcc.is() )
2059 xContext = xAcc->getAccessibleContext();
2060 // TODO: this has a slight conceptual problem:
2062 // We know that the XAccessible and XAccessibleContext implementation of the browse
2063 // box is the same (the class implements both interfaces), which, speaking strictly,
2064 // is bad here (means when a browse box acts as UnoControl): We (the FmXGridPeer) are
2065 // the XAccessible here, and the browse box should be able to provide us an XAccessibleContext,
2066 // but it should _not_ be the XAccessible itself.
2067 // However, as long as no client implementation uses dirty hacks such as querying an
2068 // XAccessibleContext for XAccessible, this should not be a problem.
2071 if ( !xContext.is() )
2072 xContext = VCLXWindow::CreateAccessibleContext( );
2074 return xContext;
2078 Any FmXGridPeer::getProperty( const OUString& _rPropertyName ) throw( RuntimeException, std::exception )
2080 Any aProp;
2081 if (GetWindow())
2083 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2084 Window* pDataWindow = &pGrid->GetDataWindow();
2086 if ( _rPropertyName == FM_PROP_NAME )
2088 Font aFont = pDataWindow->GetControlFont();
2089 aProp <<= ImplCreateFontDescriptor( aFont );
2091 else if ( _rPropertyName == FM_PROP_TEXTCOLOR )
2093 aProp <<= (sal_Int32)pDataWindow->GetControlForeground().GetColor();
2095 else if ( _rPropertyName == FM_PROP_BACKGROUNDCOLOR )
2097 aProp <<= (sal_Int32)pDataWindow->GetControlBackground().GetColor();
2099 else if ( _rPropertyName == FM_PROP_ROWHEIGHT )
2101 sal_Int32 nPixelHeight = pGrid->GetDataRowHeight();
2102 // take the zoom factor into account
2103 nPixelHeight = pGrid->CalcReverseZoom(nPixelHeight);
2104 aProp <<= (sal_Int32)pGrid->PixelToLogic(Point(0,nPixelHeight),MAP_10TH_MM).Y();
2106 else if ( _rPropertyName == FM_PROP_HASNAVIGATION )
2108 bool bHasNavBar = pGrid->HasNavigationBar();
2109 aProp <<= bHasNavBar;
2111 else if ( _rPropertyName == FM_PROP_RECORDMARKER )
2113 bool bHasHandle = pGrid->HasHandle();
2114 aProp <<= bHasHandle;
2116 else if ( _rPropertyName == FM_PROP_ENABLED )
2118 aProp <<= pDataWindow->IsEnabled();
2120 else
2121 aProp = VCLXWindow::getProperty( _rPropertyName );
2123 return aProp;
2127 void FmXGridPeer::dispose() throw( RuntimeException, std::exception )
2129 EventObject aEvt;
2130 aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
2131 m_aModifyListeners.disposeAndClear(aEvt);
2132 m_aUpdateListeners.disposeAndClear(aEvt);
2133 m_aContainerListeners.disposeAndClear(aEvt);
2134 VCLXWindow::dispose();
2136 // release all interceptors
2137 Reference< XDispatchProviderInterceptor > xInterceptor( m_xFirstDispatchInterceptor );
2138 m_xFirstDispatchInterceptor.clear();
2139 while ( xInterceptor.is() )
2141 // tell the interceptor it has a new (means no) predecessor
2142 xInterceptor->setMasterDispatchProvider( NULL );
2144 // ask for it's successor
2145 Reference< XDispatchProvider > xSlave = xInterceptor->getSlaveDispatchProvider();
2146 // and give it the new (means no) successoert
2147 xInterceptor->setSlaveDispatchProvider( NULL );
2149 // start over with the next chain element
2150 xInterceptor = xInterceptor.query( xSlave );
2153 DisConnectFromDispatcher();
2154 setRowSet(Reference< XRowSet > ());
2157 // XContainer
2159 void FmXGridPeer::addContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
2161 m_aContainerListeners.addInterface( l );
2164 void FmXGridPeer::removeContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException, std::exception )
2166 m_aContainerListeners.removeInterface( l );
2169 // ::com::sun::star::data::XDatabaseCursorSupplier
2171 void FmXGridPeer::startCursorListening()
2173 if (!m_nCursorListening)
2175 Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY);
2176 if (xRowSet.is())
2177 xRowSet->addRowSetListener(this);
2179 Reference< XReset > xReset(m_xCursor, UNO_QUERY);
2180 if (xReset.is())
2181 xReset->addResetListener(this);
2183 // register all listeners
2184 Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY);
2185 if (xSet.is())
2187 xSet->addPropertyChangeListener(FM_PROP_ISMODIFIED, this);
2188 xSet->addPropertyChangeListener(FM_PROP_ROWCOUNT, this);
2191 m_nCursorListening++;
2195 void FmXGridPeer::stopCursorListening()
2197 if (!--m_nCursorListening)
2199 Reference< XRowSet > xRowSet(m_xCursor, UNO_QUERY);
2200 if (xRowSet.is())
2201 xRowSet->removeRowSetListener(this);
2203 Reference< XReset > xReset(m_xCursor, UNO_QUERY);
2204 if (xReset.is())
2205 xReset->removeResetListener(this);
2207 Reference< XPropertySet > xSet(m_xCursor, UNO_QUERY);
2208 if (xSet.is())
2210 xSet->removePropertyChangeListener(FM_PROP_ISMODIFIED, this);
2211 xSet->removePropertyChangeListener(FM_PROP_ROWCOUNT, this);
2217 void FmXGridPeer::updateGrid(const Reference< XRowSet >& _rxCursor)
2219 FmGridControl* pGrid = (FmGridControl*)GetWindow();
2220 if (pGrid)
2221 pGrid->setDataSource(_rxCursor);
2225 Reference< XRowSet > FmXGridPeer::getRowSet() throw( RuntimeException, std::exception )
2227 return m_xCursor;
2231 void FmXGridPeer::setRowSet(const Reference< XRowSet >& _rDatabaseCursor) throw( RuntimeException, std::exception )
2233 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2234 if (!pGrid || !m_xColumns.is() || !m_xColumns->getCount())
2235 return;
2236 // unregister all listeners
2237 if (m_xCursor.is())
2239 Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY);
2240 // only if the form is loaded we set the rowset
2241 if (xLoadable.is())
2243 stopCursorListening();
2244 xLoadable->removeLoadListener(this);
2248 m_xCursor = _rDatabaseCursor;
2250 if (pGrid)
2252 Reference< XLoadable > xLoadable(m_xCursor, UNO_QUERY);
2253 // only if the form is loaded we set the rowset
2254 if (xLoadable.is() && xLoadable->isLoaded())
2255 pGrid->setDataSource(m_xCursor);
2256 else
2257 pGrid->setDataSource(Reference< XRowSet > ());
2259 if (xLoadable.is())
2261 startCursorListening();
2262 xLoadable->addLoadListener(this);
2268 void SAL_CALL FmXGridPeer::addGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
2270 m_aGridControlListeners.addInterface( _listener );
2274 void SAL_CALL FmXGridPeer::removeGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException, std::exception )
2276 m_aGridControlListeners.removeInterface( _listener );
2280 sal_Int16 FmXGridPeer::getCurrentColumnPosition() throw( RuntimeException, std::exception )
2282 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2283 return pGrid ? pGrid->GetViewColumnPos(pGrid->GetCurColumnId()) : -1;
2287 void FmXGridPeer::setCurrentColumnPosition(sal_Int16 nPos) throw( RuntimeException, std::exception )
2289 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2290 if (pGrid)
2291 pGrid->GoToColumnId(pGrid->GetColumnIdFromViewPos(nPos));
2295 void FmXGridPeer::selectionChanged(const EventObject& evt) throw( RuntimeException, std::exception )
2297 SolarMutexGuard aGuard;
2299 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2300 if (pGrid)
2302 Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(evt.Source, UNO_QUERY);
2303 Any aSelection = xSelSupplier->getSelection();
2304 DBG_ASSERT(aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE, "FmXGridPeer::selectionChanged : invalid selection !");
2305 Reference< XPropertySet > xSelection;
2306 aSelection >>= xSelection;
2307 if (xSelection.is())
2309 Reference< XPropertySet > xCol;
2310 sal_Int32 i = 0;
2311 sal_Int32 nColCount = m_xColumns->getCount();
2313 for (; i < nColCount; ++i)
2315 m_xColumns->getByIndex(i) >>= xCol;
2316 if ( xCol == xSelection )
2318 pGrid->markColumn(pGrid->GetColumnIdFromModelPos((sal_uInt16)i));
2319 break;
2322 // The columns have to be 1-based for the VCL control.
2323 // If necessary, pass on the selection to the VCL control
2324 if ( i != pGrid->GetSelectedColumn() )
2325 { // (wenn das nicht greift, wurde das selectionChanged implizit von dem Control selber ausgeloest
2326 // if this does not ?hold?catch?, the selectionChanged is cleared by the Control itself
2327 if ( i < nColCount )
2329 pGrid->SelectColumnPos(pGrid->GetViewColumnPos(pGrid->GetColumnIdFromModelPos( (sal_uInt16)i )) + 1, true);
2330 // SelectColumnPos has led to an implicit ActivateCell again
2331 if (pGrid->IsEditing())
2332 pGrid->DeactivateCell();
2334 else
2335 pGrid->SetNoSelection();
2338 else
2339 pGrid->markColumn(USHRT_MAX);
2343 // XElementAccess
2345 sal_Bool FmXGridPeer::hasElements() throw( RuntimeException, std::exception )
2347 return getCount() != 0;
2351 Type SAL_CALL FmXGridPeer::getElementType( ) throw(RuntimeException, std::exception)
2353 return cppu::UnoType<com::sun::star::awt::XControl>::get();
2356 // XEnumerationAccess
2358 Reference< XEnumeration > FmXGridPeer::createEnumeration() throw( RuntimeException, std::exception )
2360 return new ::comphelper::OEnumerationByIndex(this);
2363 // XIndexAccess
2365 sal_Int32 FmXGridPeer::getCount() throw( RuntimeException, std::exception )
2367 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2368 if (pGrid)
2369 return pGrid->GetViewColCount();
2370 else
2371 return 0;
2375 Any FmXGridPeer::getByIndex(sal_Int32 _nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
2377 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2378 if (_nIndex < 0 ||
2379 _nIndex >= getCount() || !pGrid)
2380 throw IndexOutOfBoundsException();
2382 Any aElement;
2383 // get the columnid
2384 sal_uInt16 nId = pGrid->GetColumnIdFromViewPos((sal_uInt16)_nIndex);
2385 // get the list position
2386 sal_uInt16 nPos = pGrid->GetModelColumnPos(nId);
2388 if ( nPos == GRID_COLUMN_NOT_FOUND )
2389 return aElement;
2391 DbGridColumn* pCol = pGrid->GetColumns().at( nPos );
2392 Reference< ::com::sun::star::awt::XControl > xControl(pCol->GetCell());
2393 aElement <<= xControl;
2395 return aElement;
2398 // ::com::sun::star::util::XModeSelector
2400 void FmXGridPeer::setMode(const OUString& Mode) throw( NoSupportException, RuntimeException, std::exception )
2402 if (!supportsMode(Mode))
2403 throw NoSupportException();
2405 if (Mode == m_aMode)
2406 return;
2408 m_aMode = Mode;
2410 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2411 if ( Mode == "FilterMode" )
2412 pGrid->SetFilterMode(true);
2413 else
2415 pGrid->SetFilterMode(false);
2416 pGrid->setDataSource(m_xCursor);
2421 OUString FmXGridPeer::getMode() throw( RuntimeException, std::exception )
2423 return m_aMode;
2427 ::comphelper::StringSequence FmXGridPeer::getSupportedModes() throw( RuntimeException, std::exception )
2429 static ::comphelper::StringSequence aModes;
2430 if (!aModes.getLength())
2432 aModes.realloc(2);
2433 OUString* pModes = aModes.getArray();
2434 pModes[0] = "DataMode";
2435 pModes[1] = "FilterMode";
2437 return aModes;
2441 sal_Bool FmXGridPeer::supportsMode(const OUString& Mode) throw( RuntimeException, std::exception )
2443 ::comphelper::StringSequence aModes(getSupportedModes());
2444 const OUString* pModes = aModes.getConstArray();
2445 for (sal_Int32 i = aModes.getLength(); i > 0; )
2447 if (pModes[--i] == Mode)
2448 return sal_True;
2450 return sal_False;
2454 void FmXGridPeer::columnVisible(DbGridColumn* pColumn)
2456 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2458 sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId());
2459 Reference< ::com::sun::star::awt::XControl > xControl(pColumn->GetCell());
2460 ContainerEvent aEvt;
2461 aEvt.Source = (XContainer*)this;
2462 aEvt.Accessor <<= _nIndex;
2463 aEvt.Element <<= xControl;
2465 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvt );
2469 void FmXGridPeer::columnHidden(DbGridColumn* pColumn)
2471 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2473 sal_Int32 _nIndex = pGrid->GetModelColumnPos(pColumn->GetId());
2474 Reference< ::com::sun::star::awt::XControl > xControl(pColumn->GetCell());
2475 ContainerEvent aEvt;
2476 aEvt.Source = (XContainer*)this;
2477 aEvt.Accessor <<= _nIndex;
2478 aEvt.Element <<= xControl;
2480 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvt );
2484 void FmXGridPeer::draw( sal_Int32 x, sal_Int32 y ) throw( RuntimeException, std::exception )
2486 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2487 sal_Int32 nOldFlags = pGrid->GetBrowserFlags();
2488 pGrid->SetBrowserFlags(nOldFlags | EBBF_NOROWPICTURE);
2490 VCLXWindow::draw(x, y);
2492 pGrid->SetBrowserFlags(nOldFlags);
2496 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 )
2498 Reference< ::com::sun::star::frame::XDispatch > xResult;
2500 // first ask our interceptor chain
2501 if (m_xFirstDispatchInterceptor.is() && !m_bInterceptingDispatch)
2503 m_bInterceptingDispatch = true;
2504 // safety against recursion : as we are master of the first chain element and slave of the last one we would
2505 // have an infinite loop without this if no dispatcher can fullfill the request
2506 xResult = m_xFirstDispatchInterceptor->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
2507 m_bInterceptingDispatch = false;
2510 // then ask ourself : we don't have any dispatches
2511 return xResult;
2515 Sequence< Reference< ::com::sun::star::frame::XDispatch > > FmXGridPeer::queryDispatches(const Sequence< ::com::sun::star::frame::DispatchDescriptor>& aDescripts) throw( RuntimeException, std::exception )
2517 if (m_xFirstDispatchInterceptor.is())
2518 return m_xFirstDispatchInterceptor->queryDispatches(aDescripts);
2520 // then ask ourself : we don't have any dispatches
2521 return Sequence< Reference< ::com::sun::star::frame::XDispatch > >();
2525 void FmXGridPeer::registerDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
2527 if (_xInterceptor.is())
2529 if (m_xFirstDispatchInterceptor.is())
2531 Reference< ::com::sun::star::frame::XDispatchProvider > xFirstProvider(m_xFirstDispatchInterceptor, UNO_QUERY);
2532 // there is already an interceptor; the new one will become its master
2533 _xInterceptor->setSlaveDispatchProvider(xFirstProvider);
2534 m_xFirstDispatchInterceptor->setMasterDispatchProvider(xFirstProvider);
2536 else
2538 // it is the first interceptor; set ourself as slave
2539 _xInterceptor->setSlaveDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this);
2542 // we are the master of the chain's first interceptor
2543 m_xFirstDispatchInterceptor = _xInterceptor;
2544 m_xFirstDispatchInterceptor->setMasterDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this);
2546 // we have a new interceptor and we're alive ?
2547 if (!isDesignMode())
2548 // -> check for new dispatchers
2549 UpdateDispatches();
2554 void FmXGridPeer::releaseDispatchProviderInterceptor(const Reference< ::com::sun::star::frame::XDispatchProviderInterceptor >& _xInterceptor) throw( RuntimeException, std::exception )
2556 if (!_xInterceptor.is())
2557 return;
2559 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xChainWalk(m_xFirstDispatchInterceptor);
2561 if (m_xFirstDispatchInterceptor == _xInterceptor)
2562 { // our chain will have a new first element
2563 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xSlave(m_xFirstDispatchInterceptor->getSlaveDispatchProvider(), UNO_QUERY);
2564 m_xFirstDispatchInterceptor = xSlave;
2566 // do this before removing the interceptor from the chain as we won't know it's slave afterwards)
2568 while (xChainWalk.is())
2570 // walk along the chain of interceptors and look for the interceptor that has to be removed
2571 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xSlave(xChainWalk->getSlaveDispatchProvider(), UNO_QUERY);
2573 if (xChainWalk == _xInterceptor)
2575 // old master may be an interceptor too
2576 Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xMaster(xChainWalk->getMasterDispatchProvider(), UNO_QUERY);
2578 // unchain the interceptor that has to be removed
2579 xChainWalk->setSlaveDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider > ());
2580 xChainWalk->setMasterDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider > ());
2582 // reconnect the chain
2583 if (xMaster.is())
2585 if (xSlave.is())
2586 xMaster->setSlaveDispatchProvider(Reference< ::com::sun::star::frame::XDispatchProvider >::query(xSlave));
2587 else
2588 // it's the first interceptor of the chain, set ourself as slave
2589 xMaster->setSlaveDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this);
2591 else
2593 // the chain's first element was removed, set ourself as new master of the second one
2594 if (xSlave.is())
2595 xSlave->setMasterDispatchProvider((::com::sun::star::frame::XDispatchProvider*)this);
2599 xChainWalk = xSlave;
2601 // our interceptor chain has changed and we're alive ?
2602 if (!isDesignMode())
2603 // -> check the dispatchers
2604 UpdateDispatches();
2608 void FmXGridPeer::statusChanged(const ::com::sun::star::frame::FeatureStateEvent& Event) throw( RuntimeException, std::exception )
2610 DBG_ASSERT(m_pStateCache, "FmXGridPeer::statusChanged : invalid call !");
2611 DBG_ASSERT(m_pDispatchers, "FmXGridPeer::statusChanged : invalid call !");
2613 Sequence< ::com::sun::star::util::URL>& aUrls = getSupportedURLs();
2614 const ::com::sun::star::util::URL* pUrls = aUrls.getConstArray();
2616 Sequence<sal_uInt16> aSlots = getSupportedGridSlots();
2617 const sal_uInt16* pSlots = aSlots.getConstArray();
2619 sal_uInt16 i;
2620 for (i=0; i<aUrls.getLength(); ++i, ++pUrls, ++pSlots)
2622 if (pUrls->Main == Event.FeatureURL.Main)
2624 DBG_ASSERT(m_pDispatchers[i] == Event.Source, "FmXGridPeer::statusChanged : the event source is a little bit suspect !");
2625 m_pStateCache[i] = Event.IsEnabled;
2626 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2627 if (*pSlots != SID_FM_RECORD_UNDO)
2628 pGrid->GetNavigationBar().InvalidateState(*pSlots);
2629 break;
2632 DBG_ASSERT(i<aUrls.getLength(), "FmXGridPeer::statusChanged : got a call for an unknown url !");
2636 sal_Bool FmXGridPeer::approveReset(const EventObject& /*rEvent*/) throw( RuntimeException, std::exception )
2638 return sal_True;
2642 sal_Bool SAL_CALL FmXGridPeer::select( const Any& _rSelection ) throw (IllegalArgumentException, RuntimeException, std::exception)
2644 Sequence< Any > aBookmarks;
2645 if ( !( _rSelection >>= aBookmarks ) )
2646 throw IllegalArgumentException();
2648 FmGridControl* pVclControl = static_cast<FmGridControl*>(GetWindow());
2649 return pVclControl->selectBookmarks(aBookmarks);
2651 // TODO:
2652 // speaking strictly, we would have to adjust our model, as our ColumnSelection may have changed.
2653 // Our model is a XSelectionSupplier, too, it handles the selection of single columns.
2654 // This is somewhat strange, as selection should be a view (not a model) aspect.
2655 // So for a clean solution, we should handle column selection ourself, and the model shouldn't
2656 // deal with selection at all.
2660 Any SAL_CALL FmXGridPeer::getSelection( ) throw (RuntimeException, std::exception)
2662 FmGridControl* pVclControl = static_cast<FmGridControl*>(GetWindow());
2663 Sequence< Any > aSelectionBookmarks = pVclControl->getSelectionBookmarks();
2664 return makeAny(aSelectionBookmarks);
2668 void SAL_CALL FmXGridPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
2670 m_aSelectionListeners.addInterface( _rxListener );
2674 void SAL_CALL FmXGridPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException, std::exception)
2676 m_aSelectionListeners.removeInterface( _rxListener );
2680 void FmXGridPeer::resetted(const EventObject& rEvent) throw( RuntimeException, std::exception )
2682 if (m_xColumns == rEvent.Source)
2683 { // my model was reset -> refresh the grid content
2684 FmGridControl* pGrid = (FmGridControl*)GetWindow();
2685 if (!pGrid)
2686 return;
2687 SolarMutexGuard aGuard;
2688 pGrid->resetCurrentRow();
2690 // if the cursor fired a reset event we seem to be on the insert row
2691 else if (m_xCursor == rEvent.Source)
2693 SolarMutexGuard aGuard;
2694 FmGridControl* pGrid = (FmGridControl*) GetWindow();
2695 if (pGrid && pGrid->IsOpen())
2696 pGrid->positioned(rEvent);
2701 Sequence<sal_uInt16>& FmXGridPeer::getSupportedGridSlots()
2703 static Sequence<sal_uInt16> aSupported;
2704 if (aSupported.getLength() == 0)
2706 sal_uInt16 nSupported[] = {
2707 DbGridControl::NavigationBar::RECORD_FIRST,
2708 DbGridControl::NavigationBar::RECORD_PREV,
2709 DbGridControl::NavigationBar::RECORD_NEXT,
2710 DbGridControl::NavigationBar::RECORD_LAST,
2711 DbGridControl::NavigationBar::RECORD_NEW,
2712 SID_FM_RECORD_UNDO
2714 aSupported.realloc(sizeof(nSupported)/sizeof(nSupported[0]));
2715 sal_uInt16* pSupported = aSupported.getArray();
2716 for (sal_uInt16 i=0; i<aSupported.getLength(); ++i, ++pSupported)
2717 *pSupported = nSupported[i];
2719 return aSupported;
2723 Sequence< ::com::sun::star::util::URL>& FmXGridPeer::getSupportedURLs()
2725 static Sequence< ::com::sun::star::util::URL> aSupported;
2726 if (aSupported.getLength() == 0)
2728 static const OUString sSupported[] = {
2729 FMURL_RECORD_MOVEFIRST,
2730 FMURL_RECORD_MOVEPREV,
2731 FMURL_RECORD_MOVENEXT,
2732 FMURL_RECORD_MOVELAST,
2733 FMURL_RECORD_MOVETONEW,
2734 FMURL_RECORD_UNDO
2736 aSupported.realloc(sizeof(sSupported)/sizeof(sSupported[0]));
2737 ::com::sun::star::util::URL* pSupported = aSupported.getArray();
2738 sal_uInt16 i;
2740 for ( i = 0; i < aSupported.getLength(); ++i, ++pSupported)
2741 pSupported->Complete = sSupported[i];
2743 // let an ::com::sun::star::util::URL-transformer normalize the URLs
2744 Reference< ::com::sun::star::util::XURLTransformer > xTransformer(
2745 util::URLTransformer::create(::comphelper::getProcessComponentContext()) );
2746 pSupported = aSupported.getArray();
2747 for (i=0; i<aSupported.getLength(); ++i)
2748 xTransformer->parseStrict(pSupported[i]);
2751 return aSupported;
2755 void FmXGridPeer::UpdateDispatches()
2757 if (!m_pStateCache)
2758 { // we don't have any dispatchers yet -> do the initial connect
2759 ConnectToDispatcher();
2760 return;
2763 sal_uInt16 nDispatchersGot = 0;
2764 const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs();
2765 const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2766 Reference< ::com::sun::star::frame::XDispatch > xNewDispatch;
2767 for (sal_uInt16 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2769 xNewDispatch = queryDispatch(*pSupportedURLs, OUString(), 0);
2770 if (xNewDispatch != m_pDispatchers[i])
2772 if (m_pDispatchers[i].is())
2773 m_pDispatchers[i]->removeStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs);
2774 m_pDispatchers[i] = xNewDispatch;
2775 if (m_pDispatchers[i].is())
2776 m_pDispatchers[i]->addStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs);
2778 if (m_pDispatchers[i].is())
2779 ++nDispatchersGot;
2782 if (!nDispatchersGot)
2784 delete[] m_pStateCache;
2785 delete[] m_pDispatchers;
2786 m_pStateCache = NULL;
2787 m_pDispatchers = NULL;
2792 void FmXGridPeer::ConnectToDispatcher()
2794 DBG_ASSERT((m_pStateCache != NULL) == (m_pDispatchers != NULL), "FmXGridPeer::ConnectToDispatcher : inconsistent !");
2795 if (m_pStateCache)
2796 { // already connected -> just do an update
2797 UpdateDispatches();
2798 return;
2801 const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs();
2803 // _before_ adding the status listeners (as the add should result in a statusChanged-call) !
2804 m_pStateCache = new bool[aSupportedURLs.getLength()];
2805 m_pDispatchers = new Reference< ::com::sun::star::frame::XDispatch > [aSupportedURLs.getLength()];
2807 sal_uInt16 nDispatchersGot = 0;
2808 const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2809 for (sal_uInt16 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2811 m_pStateCache[i] = false;
2812 m_pDispatchers[i] = queryDispatch(*pSupportedURLs, OUString(), 0);
2813 if (m_pDispatchers[i].is())
2815 m_pDispatchers[i]->addStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs);
2816 ++nDispatchersGot;
2820 if (!nDispatchersGot)
2822 delete[] m_pStateCache;
2823 delete[] m_pDispatchers;
2824 m_pStateCache = NULL;
2825 m_pDispatchers = NULL;
2830 void FmXGridPeer::DisConnectFromDispatcher()
2832 if (!m_pStateCache || !m_pDispatchers)
2833 return;
2834 // we're not connected
2836 const Sequence< ::com::sun::star::util::URL>& aSupportedURLs = getSupportedURLs();
2837 const ::com::sun::star::util::URL* pSupportedURLs = aSupportedURLs.getConstArray();
2838 for (sal_uInt16 i=0; i<aSupportedURLs.getLength(); ++i, ++pSupportedURLs)
2840 if (m_pDispatchers[i].is())
2841 m_pDispatchers[i]->removeStatusListener((::com::sun::star::frame::XStatusListener*)this, *pSupportedURLs);
2844 delete[] m_pStateCache;
2845 delete[] m_pDispatchers;
2846 m_pStateCache = NULL;
2847 m_pDispatchers = NULL;
2851 IMPL_LINK(FmXGridPeer, OnQueryGridSlotState, void*, pSlot)
2853 if (!m_pStateCache)
2854 return -1; // unspecified
2856 sal_uInt16 nSlot = (sal_uInt16)(sal_uIntPtr)pSlot;
2858 // search the given slot with our supported sequence
2859 Sequence<sal_uInt16>& aSupported = getSupportedGridSlots();
2860 const sal_uInt16* pSlots = aSupported.getConstArray();
2861 for (sal_uInt16 i=0; i<aSupported.getLength(); ++i)
2863 if (pSlots[i] == nSlot)
2865 if (!m_pDispatchers[i].is())
2866 return -1; // nothing known about this slot
2867 else
2868 return m_pStateCache[i] ? 1 : 0;
2872 return -1;
2876 IMPL_LINK(FmXGridPeer, OnExecuteGridSlot, void*, pSlot)
2878 if (!m_pDispatchers)
2879 return 0; // not handled
2881 Sequence< ::com::sun::star::util::URL>& aUrls = getSupportedURLs();
2882 const ::com::sun::star::util::URL* pUrls = aUrls.getConstArray();
2884 Sequence<sal_uInt16> aSlots = getSupportedGridSlots();
2885 const sal_uInt16* pSlots = aSlots.getConstArray();
2887 DBG_ASSERT(aSlots.getLength() == aUrls.getLength(), "FmXGridPeer::OnExecuteGridSlot : inconstent data returned by getSupportedURLs/getSupportedGridSlots !");
2889 sal_uInt16 nSlot = (sal_uInt16)(sal_uIntPtr)pSlot;
2890 for (sal_uInt16 i=0; i<aSlots.getLength(); ++i, ++pUrls, ++pSlots)
2892 if (*pSlots == nSlot)
2894 if (m_pDispatchers[i].is())
2896 // commit any changes done so far, if it's not the undoRecord URL
2897 if ( pUrls->Complete == FMURL_RECORD_UNDO || commit() )
2898 m_pDispatchers[i]->dispatch(*pUrls, Sequence< PropertyValue>());
2900 return 1; // handled
2905 return 0; // not handled
2908 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */