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