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