xref: /AOO41X/main/svx/source/fmcomp/fmgridif.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
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 //------------------------------------------------------------------
ImplCreateFontDescriptor(const Font & rFont)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 //------------------------------------------------------------------
ImplCreateFont(const::com::sun::star::awt::FontDescriptor & rDescr)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 //------------------------------------------------------------------
FmXModifyMultiplexer(::cppu::OWeakObject & rSource,::osl::Mutex & _rMutex)133 FmXModifyMultiplexer::FmXModifyMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
134                     :OWeakSubObject( rSource )
135                     ,OInterfaceContainerHelper( _rMutex )
136 {
137 }
138 
139 //------------------------------------------------------------------
queryInterface(const Type & _rType)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 //------------------------------------------------------------------
disposing(const EventObject &)155 void FmXModifyMultiplexer::disposing(const EventObject& ) throw( RuntimeException )
156 {
157 }
158 
159 //------------------------------------------------------------------
modified(const EventObject & e)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 //------------------------------------------------------------------
FmXUpdateMultiplexer(::cppu::OWeakObject & rSource,::osl::Mutex & _rMutex)171 FmXUpdateMultiplexer::FmXUpdateMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
172                     :OWeakSubObject( rSource )
173                     ,OInterfaceContainerHelper( _rMutex )
174 {
175 }
176 
177 //------------------------------------------------------------------
queryInterface(const Type & _rType)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 //------------------------------------------------------------------
disposing(const EventObject &)193 void FmXUpdateMultiplexer::disposing(const EventObject& ) throw( RuntimeException )
194 {
195 }
196 
197 //------------------------------------------------------------------
approveUpdate(const EventObject & e)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 //------------------------------------------------------------------
updated(const EventObject & e)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 //------------------------------------------------------------------
FmXSelectionMultiplexer(::cppu::OWeakObject & rSource,::osl::Mutex & _rMutex)227 FmXSelectionMultiplexer::FmXSelectionMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
228     :OWeakSubObject( rSource )
229     ,OInterfaceContainerHelper( _rMutex )
230 {
231 }
232 
233 //------------------------------------------------------------------
queryInterface(const Type & _rType)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 //------------------------------------------------------------------
disposing(const EventObject &)249 void FmXSelectionMultiplexer::disposing(const EventObject& ) throw( RuntimeException )
250 {
251 }
252 
253 //------------------------------------------------------------------
selectionChanged(const EventObject & _rEvent)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 //------------------------------------------------------------------
FmXContainerMultiplexer(::cppu::OWeakObject & rSource,::osl::Mutex & _rMutex)265 FmXContainerMultiplexer::FmXContainerMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
266                         :OWeakSubObject( rSource )
267                         ,OInterfaceContainerHelper( _rMutex )
268 {
269 }
270 
271 //------------------------------------------------------------------
queryInterface(const Type & _rType)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 //------------------------------------------------------------------
disposing(const EventObject &)287 void FmXContainerMultiplexer::disposing(const EventObject& ) throw( RuntimeException )
288 {
289 }
290 //------------------------------------------------------------------
elementInserted(const ContainerEvent & e)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 //------------------------------------------------------------------
elementRemoved(const ContainerEvent & e)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 //------------------------------------------------------------------
elementReplaced(const ContainerEvent & e)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 //------------------------------------------------------------------
FmXGridControlMultiplexer(::cppu::OWeakObject & rSource,::osl::Mutex & _rMutex)319 FmXGridControlMultiplexer::FmXGridControlMultiplexer( ::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex )
320     :OWeakSubObject( rSource )
321     ,OInterfaceContainerHelper( _rMutex )
322 {
323 }
324 
325 //------------------------------------------------------------------
queryInterface(const Type & _rType)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 //------------------------------------------------------------------
disposing(const EventObject &)340 void FmXGridControlMultiplexer::disposing( const EventObject& ) throw( RuntimeException )
341 {
342 }
343 
344 //------------------------------------------------------------------
columnChanged(const EventObject & _event)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 //------------------------------------------------------------------
FmXGridControl_NewInstance_Impl(const Reference<XMultiServiceFactory> & _rxFactory)357 Reference< XInterface > SAL_CALL FmXGridControl_NewInstance_Impl(const Reference< XMultiServiceFactory>& _rxFactory)
358 {
359     return *(new FmXGridControl(_rxFactory));
360 }
DBG_NAME(FmXGridControl)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 //------------------------------------------------------------------------------
~FmXGridControl()378 FmXGridControl::~FmXGridControl()
379 {
380     DBG_DTOR(FmXGridControl ,NULL);
381 }
382 
383 //------------------------------------------------------------------
queryAggregation(const Type & _rType)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 //------------------------------------------------------------------
getTypes()394 Sequence< Type> SAL_CALL FmXGridControl::getTypes(  ) throw(RuntimeException)
395 {
396     return comphelper::concatSequences(UnoControl::getTypes(),FmXGridControl_BASE::getTypes());
397 }
398 
399 //------------------------------------------------------------------
getImplementationId()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 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & ServiceName)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 //------------------------------------------------------------------------------
getImplementationName()428 ::rtl::OUString SAL_CALL FmXGridControl::getImplementationName() throw()
429 {
430     return ::rtl::OUString::createFromAscii("com.sun.star.form.FmXGridControl");
431 }
432 
433 //------------------------------------------------------------------------------
getSupportedServiceNames()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 //------------------------------------------------------------------------------
dispose()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 //------------------------------------------------------------------------------
GetComponentServiceName()457 ::rtl::OUString FmXGridControl::GetComponentServiceName()
458 {
459     ::rtl::OUString aName = ::rtl::OUString::createFromAscii("DBGrid");
460     return aName;
461 }
462 
463 //------------------------------------------------------------------------------
setModel(const Reference<::com::sun::star::awt::XControlModel> & rModel)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 //------------------------------------------------------------------------------
imp_CreatePeer(Window * pParent)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 //------------------------------------------------------------------------------
createPeer(const Reference<::com::sun::star::awt::XToolkit> &,const Reference<::com::sun::star::awt::XWindowPeer> & rParentPeer)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 //------------------------------------------------------------------------------
addModifyListener(const Reference<::com::sun::star::util::XModifyListener> & l)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 //------------------------------------------------------------------------------
select(const Any & _rSelection)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 //------------------------------------------------------------------------------
getSelection()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 //------------------------------------------------------------------------------
addSelectionChangeListener(const Reference<XSelectionChangeListener> & _rxListener)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 //------------------------------------------------------------------------------
removeSelectionChangeListener(const Reference<XSelectionChangeListener> & _rxListener)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 //------------------------------------------------------------------------------
queryFieldDataType(const Type & xType)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 //------------------------------------------------------------------------------
queryFieldData(sal_Int32 nRow,const Type & xType)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 //------------------------------------------------------------------------------
removeModifyListener(const Reference<::com::sun::star::util::XModifyListener> & l)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 //------------------------------------------------------------------------------
draw(sal_Int32 x,sal_Int32 y)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 //------------------------------------------------------------------------------
setDesignMode(sal_Bool bOn)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 //------------------------------------------------------------------------------
addUpdateListener(const Reference<XUpdateListener> & l)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 //------------------------------------------------------------------------------
removeUpdateListener(const Reference<XUpdateListener> & l)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 //------------------------------------------------------------------------------
commit()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 //------------------------------------------------------------------------------
addContainerListener(const Reference<XContainerListener> & l)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 //------------------------------------------------------------------------------
removeContainerListener(const Reference<XContainerListener> & l)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 //------------------------------------------------------------------------------
queryDispatch(const::com::sun::star::util::URL & aURL,const::rtl::OUString & aTargetFrameName,sal_Int32 nSearchFlags)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 //------------------------------------------------------------------------------
queryDispatches(const Sequence<::com::sun::star::frame::DispatchDescriptor> & aDescripts)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 //------------------------------------------------------------------------------
registerDispatchProviderInterceptor(const Reference<::com::sun::star::frame::XDispatchProviderInterceptor> & _xInterceptor)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 //------------------------------------------------------------------------------
releaseDispatchProviderInterceptor(const Reference<::com::sun::star::frame::XDispatchProviderInterceptor> & _xInterceptor)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 //------------------------------------------------------------------------------
addGridControlListener(const Reference<XGridControlListener> & _listener)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 //------------------------------------------------------------------------------
removeGridControlListener(const Reference<XGridControlListener> & _listener)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 //------------------------------------------------------------------------------
getCurrentColumnPosition()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 //------------------------------------------------------------------------------
setCurrentColumnPosition(sal_Int16 nPos)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 //------------------------------------------------------------------------------
hasElements()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 //------------------------------------------------------------------------------
getElementType()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 //------------------------------------------------------------------------------
createEnumeration()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 //------------------------------------------------------------------------------
getCount()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 //------------------------------------------------------------------------------
getByIndex(sal_Int32 _nIndex)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 //------------------------------------------------------------------------------
setMode(const::rtl::OUString & Mode)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 //------------------------------------------------------------------------------
getMode()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 //------------------------------------------------------------------------------
getSupportedModes()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 //------------------------------------------------------------------------------
supportsMode(const::rtl::OUString & Mode)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 //------------------------------------------------------------------
GridListenerDelegator(FmXGridPeer * _pPeer)1040 FmXGridPeer::GridListenerDelegator::GridListenerDelegator(FmXGridPeer* _pPeer)
1041     :m_pPeer(_pPeer)
1042 {
1043     DBG_ASSERT(m_pPeer, "GridListenerDelegator::GridListenerDelegator");
1044 }
1045 
1046 //------------------------------------------------------------------
selectionChanged()1047 void FmXGridPeer::GridListenerDelegator::selectionChanged()
1048 {
1049     m_pPeer->selectionChanged();
1050 }
1051 
1052 //------------------------------------------------------------------
columnChanged()1053 void FmXGridPeer::GridListenerDelegator::columnChanged()
1054 {
1055     m_pPeer->columnChanged();
1056 }
1057 
1058 //==============================================================================
1059 //------------------------------------------------------------------
FmXGridPeer_CreateInstance(const Reference<XMultiServiceFactory> & _rxFactory)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 //------------------------------------------------------------------
getTypes()1068 Sequence< Type> SAL_CALL FmXGridPeer::getTypes(  ) throw(RuntimeException)
1069 {
1070     return comphelper::concatSequences( VCLXWindow::getTypes(), FmXGridPeer_BASE::getTypes() );
1071 }
1072 
1073 //------------------------------------------------------------------
getImplementationId()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 //------------------------------------------------------------------
queryInterface(const Type & _rType)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 //------------------------------------------------------------------
selectionChanged()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 //------------------------------------------------------------------
columnChanged()1109 void FmXGridPeer::columnChanged()
1110 {
1111     EventObject aEvent( *this );
1112     m_aGridControlListeners.notifyEach( &XGridControlListener::columnChanged, aEvent );
1113 }
1114 
1115 //------------------------------------------------------------------
1116 namespace fmgridif
1117 {
getDataModeIdentifier()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 //------------------------------------------------------------------
FmXGridPeer(const Reference<XMultiServiceFactory> & _rxFactory)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 //------------------------------------------------------------------------------
imp_CreateControl(Window * pParent,WinBits nStyle)1146 FmGridControl* FmXGridPeer::imp_CreateControl(Window* pParent, WinBits nStyle)
1147 {
1148     return new FmGridControl(m_xServiceFactory, pParent, this, nStyle);
1149 }
1150 
1151 //------------------------------------------------------------------------------
Create(Window * pParent,WinBits nStyle)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 //------------------------------------------------------------------------------
~FmXGridPeer()1171 FmXGridPeer::~FmXGridPeer()
1172 {
1173     setRowSet(Reference< XRowSet > ());
1174     setColumns(Reference< XIndexContainer > ());
1175 
1176     delete m_pGridListener;
1177 }
1178 
1179 //------------------------------------------------------------------------------
getUnoTunnelImplementationId()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 //------------------------------------------------------------------------------
getImplementation(const Reference<XInterface> & _rxIFace)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 //------------------------------------------------------------------------------
getSomething(const Sequence<sal_Int8> & _rIdentifier)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 //------------------------------------------------------------------------------
disposing(const EventObject & e)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 //------------------------------------------------------------------------------
addModifyListener(const Reference<::com::sun::star::util::XModifyListener> & l)1268 void FmXGridPeer::addModifyListener(const Reference< ::com::sun::star::util::XModifyListener >& l) throw( RuntimeException )
1269 {
1270     m_aModifyListeners.addInterface( l );
1271 }
1272 
1273 //------------------------------------------------------------------------------
removeModifyListener(const Reference<::com::sun::star::util::XModifyListener> & l)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
queryFieldDataType(const Type & xType)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 //------------------------------------------------------------------------------
queryFieldData(sal_Int32 nRow,const Type & xType)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 //------------------------------------------------------------------------------
CellModified()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 //------------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)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 //------------------------------------------------------------------------------
addUpdateListener(const Reference<XUpdateListener> & l)1579 void FmXGridPeer::addUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException )
1580 {
1581     m_aUpdateListeners.addInterface(l);
1582 }
1583 
1584 //------------------------------------------------------------------------------
removeUpdateListener(const Reference<XUpdateListener> & l)1585 void FmXGridPeer::removeUpdateListener(const Reference< XUpdateListener >& l) throw( RuntimeException )
1586 {
1587     m_aUpdateListeners.removeInterface(l);
1588 }
1589 
1590 //------------------------------------------------------------------------------
commit()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 //------------------------------------------------------------------------------
cursorMoved(const EventObject & _rEvent)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 //------------------------------------------------------------------------------
rowChanged(const EventObject & _rEvent)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 //------------------------------------------------------------------------------
rowSetChanged(const EventObject &)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 //------------------------------------------------------------------------------
loaded(const EventObject &)1645 void FmXGridPeer::loaded(const EventObject& /*rEvent*/) throw( RuntimeException )
1646 {
1647     updateGrid(m_xCursor);
1648 }
1649 
1650 //------------------------------------------------------------------------------
unloaded(const EventObject &)1651 void FmXGridPeer::unloaded(const EventObject& /*rEvent*/) throw( RuntimeException )
1652 {
1653     updateGrid( Reference< XRowSet > (NULL) );
1654 }
1655 
1656 //------------------------------------------------------------------------------
reloading(const EventObject &)1657 void FmXGridPeer::reloading(const EventObject& /*aEvent*/) throw( RuntimeException )
1658 {
1659     // empty the grid
1660     updateGrid( Reference< XRowSet > (NULL) );
1661 }
1662 
1663 //------------------------------------------------------------------------------
unloading(const EventObject &)1664 void FmXGridPeer::unloading(const EventObject& /*aEvent*/) throw( RuntimeException )
1665 {
1666     // empty the grid
1667     updateGrid( Reference< XRowSet > (NULL) );
1668 }
1669 
1670 //------------------------------------------------------------------------------
reloaded(const EventObject &)1671 void FmXGridPeer::reloaded(const EventObject& /*aEvent*/) throw( RuntimeException )
1672 {
1673     updateGrid(m_xCursor);
1674 }
1675 
1676 // XGridPeer
1677 //------------------------------------------------------------------------------
getColumns()1678 Reference< XIndexContainer >  FmXGridPeer::getColumns() throw( RuntimeException )
1679 {
1680     return m_xColumns;
1681 }
1682 
1683 //------------------------------------------------------------------------------
addColumnListeners(const Reference<XPropertySet> & xCol)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 //------------------------------------------------------------------------------
removeColumnListeners(const Reference<XPropertySet> & xCol)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 //------------------------------------------------------------------------------
setColumns(const Reference<XIndexContainer> & Columns)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 //------------------------------------------------------------------------------
setDesignMode(sal_Bool bOn)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 //------------------------------------------------------------------------------
isDesignMode()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 //------------------------------------------------------------------------------
elementInserted(const ContainerEvent & evt)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 //------------------------------------------------------------------------------
elementReplaced(const ContainerEvent & evt)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 //------------------------------------------------------------------------------
elementRemoved(const ContainerEvent & evt)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 //------------------------------------------------------------------------------
setProperty(const::rtl::OUString & PropertyName,const Any & Value)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 //------------------------------------------------------------------------------
CreateAccessibleContext()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 //------------------------------------------------------------------------------
getProperty(const::rtl::OUString & _rPropertyName)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 //------------------------------------------------------------------------------
dispose()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 //------------------------------------------------------------------------------
addContainerListener(const Reference<XContainerListener> & l)2214 void FmXGridPeer::addContainerListener(const Reference< XContainerListener >& l) throw( RuntimeException )
2215 {
2216     m_aContainerListeners.addInterface( l );
2217 }
2218 //------------------------------------------------------------------------------
removeContainerListener(const Reference<XContainerListener> & l)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 //------------------------------------------------------------------------------
startCursorListening()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 //------------------------------------------------------------------------------
stopCursorListening()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 //------------------------------------------------------------------------------
updateGrid(const Reference<XRowSet> & _rxCursor)2272 void FmXGridPeer::updateGrid(const Reference< XRowSet >& _rxCursor)
2273 {
2274     FmGridControl* pGrid = (FmGridControl*)GetWindow();
2275     if (pGrid)
2276         pGrid->setDataSource(_rxCursor);
2277 }
2278 
2279 //------------------------------------------------------------------------------
getRowSet()2280 Reference< XRowSet >  FmXGridPeer::getRowSet() throw( RuntimeException )
2281 {
2282     return m_xCursor;
2283 }
2284 
2285 //------------------------------------------------------------------------------
setRowSet(const Reference<XRowSet> & _rDatabaseCursor)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 //------------------------------------------------------------------------------
addGridControlListener(const Reference<XGridControlListener> & _listener)2323 void SAL_CALL FmXGridPeer::addGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException )
2324 {
2325     m_aGridControlListeners.addInterface( _listener );
2326 }
2327 
2328 //------------------------------------------------------------------------------
removeGridControlListener(const Reference<XGridControlListener> & _listener)2329 void SAL_CALL FmXGridPeer::removeGridControlListener( const Reference< XGridControlListener >& _listener ) throw( RuntimeException )
2330 {
2331     m_aGridControlListeners.removeInterface( _listener );
2332 }
2333 
2334 //------------------------------------------------------------------------------
getCurrentColumnPosition()2335 sal_Int16 FmXGridPeer::getCurrentColumnPosition() throw( RuntimeException )
2336 {
2337     FmGridControl* pGrid = (FmGridControl*) GetWindow();
2338     return pGrid ? pGrid->GetViewColumnPos(pGrid->GetCurColumnId()) : -1;
2339 }
2340 
2341 //------------------------------------------------------------------------------
setCurrentColumnPosition(sal_Int16 nPos)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 //------------------------------------------------------------------------------
selectionChanged(const EventObject & evt)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 //------------------------------------------------------------------------------
hasElements()2399 sal_Bool FmXGridPeer::hasElements() throw( RuntimeException )
2400 {
2401     return getCount() != 0;
2402 }
2403 
2404 //------------------------------------------------------------------------------
getElementType()2405 Type SAL_CALL FmXGridPeer::getElementType(  ) throw(RuntimeException)
2406 {
2407     return ::getCppuType((Reference< ::com::sun::star::awt::XControl> *)NULL);
2408 }
2409 
2410 // XEnumerationAccess
2411 //------------------------------------------------------------------------------
createEnumeration()2412 Reference< XEnumeration >  FmXGridPeer::createEnumeration() throw( RuntimeException )
2413 {
2414     return new ::comphelper::OEnumerationByIndex(this);
2415 }
2416 
2417 // XIndexAccess
2418 //------------------------------------------------------------------------------
getCount()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 //------------------------------------------------------------------------------
getByIndex(sal_Int32 _nIndex)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 //------------------------------------------------------------------------------
setMode(const::rtl::OUString & Mode)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 //------------------------------------------------------------------------------
getMode()2473 ::rtl::OUString FmXGridPeer::getMode() throw( RuntimeException )
2474 {
2475     return m_aMode;
2476 }
2477 
2478 //------------------------------------------------------------------------------
getSupportedModes()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 //------------------------------------------------------------------------------
supportsMode(const::rtl::OUString & Mode)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 //------------------------------------------------------------------------------
columnVisible(DbGridColumn * pColumn)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 //------------------------------------------------------------------------------
columnHidden(DbGridColumn * pColumn)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 //------------------------------------------------------------------------------
draw(sal_Int32 x,sal_Int32 y)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 //------------------------------------------------------------------------------
queryDispatch(const::com::sun::star::util::URL & aURL,const::rtl::OUString & aTargetFrameName,sal_Int32 nSearchFlags)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 //------------------------------------------------------------------------------
queryDispatches(const Sequence<::com::sun::star::frame::DispatchDescriptor> & aDescripts)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 //------------------------------------------------------------------------------
registerDispatchProviderInterceptor(const Reference<::com::sun::star::frame::XDispatchProviderInterceptor> & _xInterceptor)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 //------------------------------------------------------------------------------
releaseDispatchProviderInterceptor(const Reference<::com::sun::star::frame::XDispatchProviderInterceptor> & _xInterceptor)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 //------------------------------------------------------------------------------
statusChanged(const::com::sun::star::frame::FeatureStateEvent & Event)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 //------------------------------------------------------------------------------
approveReset(const EventObject &)2688 sal_Bool FmXGridPeer::approveReset(const EventObject& /*rEvent*/) throw( RuntimeException )
2689 {
2690     return sal_True;
2691 }
2692 
2693 //------------------------------------------------------------------------------
select(const Any & _rSelection)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 //------------------------------------------------------------------------------
getSelection()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 //------------------------------------------------------------------------------
addSelectionChangeListener(const Reference<XSelectionChangeListener> & _rxListener)2720 void SAL_CALL FmXGridPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException)
2721 {
2722     m_aSelectionListeners.addInterface( _rxListener );
2723 }
2724 
2725 //------------------------------------------------------------------------------
removeSelectionChangeListener(const Reference<XSelectionChangeListener> & _rxListener)2726 void SAL_CALL FmXGridPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& _rxListener ) throw (RuntimeException)
2727 {
2728     m_aSelectionListeners.removeInterface( _rxListener );
2729 }
2730 
2731 //------------------------------------------------------------------------------
resetted(const EventObject & rEvent)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 //------------------------------------------------------------------------------
getSupportedGridSlots()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 //------------------------------------------------------------------------------
getSupportedURLs()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 //------------------------------------------------------------------------------
UpdateDispatches()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 //------------------------------------------------------------------------------
ConnectToDispatcher()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 //------------------------------------------------------------------------------
DisConnectFromDispatcher()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 //------------------------------------------------------------------------------
IMPL_LINK(FmXGridPeer,OnQueryGridSlotState,void *,pSlot)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 //------------------------------------------------------------------------------
IMPL_LINK(FmXGridPeer,OnExecuteGridSlot,void *,pSlot)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