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