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