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