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 #include "Columns.hxx"
21 #include "findpos.hxx"
22 #include "Grid.hxx"
23 #include <property.hxx>
24 #include <services.hxx>
25 #include <com/sun/star/form/FormComponentType.hpp>
26 #include <com/sun/star/io/XMarkableStream.hpp>
27 #include <com/sun/star/text/WritingMode2.hpp>
28 #include <comphelper/basicio.hxx>
29 #include <comphelper/property.hxx>
30 #include <comphelper/servicehelper.hxx>
31 #include <comphelper/types.hxx>
32 #include <vcl/unohelp.hxx>
33 #include <vcl/svapp.hxx>
34 #include <tools/diagnose_ex.h>
35 
36 using namespace ::com::sun::star::uno;
37 
38 namespace frm
39 {
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::sdb;
42 using namespace ::com::sun::star::sdbc;
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::container;
45 using namespace ::com::sun::star::form;
46 using namespace ::com::sun::star::awt;
47 using namespace ::com::sun::star::io;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::util;
50 using namespace ::com::sun::star::view;
51 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
52 const sal_uInt16 ROWHEIGHT          =   0x0001;
53 const sal_uInt16 FONTTYPE           =   0x0002;
54 const sal_uInt16 FONTSIZE           =   0x0004;
55 const sal_uInt16 FONTATTRIBS        =   0x0008;
56 const sal_uInt16 TABSTOP            =   0x0010;
57 const sal_uInt16 TEXTCOLOR          =   0x0020;
58 const sal_uInt16 FONTDESCRIPTOR     =   0x0040;
59 const sal_uInt16 RECORDMARKER       =   0x0080;
60 const sal_uInt16 BACKGROUNDCOLOR    =   0x0100;
61 
OGridControlModel(const Reference<XComponentContext> & _rxFactory)62 OGridControlModel::OGridControlModel(const Reference<XComponentContext>& _rxFactory)
63     :OControlModel(_rxFactory, OUString())
64     ,OInterfaceContainer(_rxFactory, m_aMutex, cppu::UnoType<XPropertySet>::get())
65     ,OErrorBroadcaster( OComponentHelper::rBHelper )
66     ,FontControlModel( false )
67     ,m_aSelectListeners(m_aMutex)
68     ,m_aResetListeners(m_aMutex)
69     ,m_aRowSetChangeListeners(m_aMutex)
70     ,m_aDefaultControl( FRM_SUN_CONTROL_GRIDCONTROL )
71     ,m_nBorder(1)
72     ,m_nWritingMode( WritingMode2::CONTEXT )
73     ,m_nContextWritingMode( WritingMode2::CONTEXT )
74     ,m_bEnableVisible(true)
75     ,m_bEnable(true)
76     ,m_bNavigation(true)
77     ,m_bRecordMarker(true)
78     ,m_bPrintable(true)
79     ,m_bAlwaysShowCursor(false)
80     ,m_bDisplaySynchron(true)
81 {
82     m_nClassId = FormComponentType::GRIDCONTROL;
83 }
84 
OGridControlModel(const OGridControlModel * _pOriginal,const Reference<XComponentContext> & _rxFactory)85 OGridControlModel::OGridControlModel( const OGridControlModel* _pOriginal, const Reference< XComponentContext >& _rxFactory )
86     :OControlModel( _pOriginal, _rxFactory )
87     ,OInterfaceContainer( _rxFactory, m_aMutex, cppu::UnoType<XPropertySet>::get() )
88     ,OErrorBroadcaster( OComponentHelper::rBHelper )
89     ,FontControlModel( _pOriginal )
90     ,m_aSelectListeners( m_aMutex )
91     ,m_aResetListeners( m_aMutex )
92     ,m_aRowSetChangeListeners( m_aMutex )
93 {
94     m_aDefaultControl = _pOriginal->m_aDefaultControl;
95     m_bEnable = _pOriginal->m_bEnable;
96     m_bEnableVisible = _pOriginal->m_bEnableVisible;
97     m_bNavigation = _pOriginal->m_bNavigation;
98     m_nBorder = _pOriginal->m_nBorder;
99     m_nWritingMode = _pOriginal->m_nWritingMode;
100     m_nContextWritingMode = _pOriginal->m_nContextWritingMode;
101     m_bRecordMarker = _pOriginal->m_bRecordMarker;
102     m_bPrintable = _pOriginal->m_bPrintable;
103     m_bAlwaysShowCursor = _pOriginal->m_bAlwaysShowCursor;
104     m_bDisplaySynchron = _pOriginal->m_bDisplaySynchron;
105     // clone the columns
106     cloneColumns( _pOriginal );
107     // TODO: clone the events?
108 }
109 
~OGridControlModel()110 OGridControlModel::~OGridControlModel()
111 {
112     if (!OComponentHelper::rBHelper.bDisposed)
113     {
114         acquire();
115         dispose();
116     }
117 }
118 
119 // XCloneable
createClone()120 Reference< XCloneable > SAL_CALL OGridControlModel::createClone( )
121 {
122     rtl::Reference<OGridControlModel> pClone = new OGridControlModel( this, getContext() );
123     pClone->OControlModel::clonedFrom( this );
124     // do not call OInterfaceContainer::clonedFrom, it would clone the elements aka columns, which is
125     // already done in the ctor
126     //pClone->OInterfaceContainer::clonedFrom( *this );
127     return static_cast< XCloneable* >( static_cast< OControlModel* >( pClone.get() ) );
128 }
129 
cloneColumns(const OGridControlModel * _pOriginalContainer)130 void OGridControlModel::cloneColumns( const OGridControlModel* _pOriginalContainer )
131 {
132     try
133     {
134         Reference< XCloneable > xColCloneable;
135         sal_Int32 nIndex = 0;
136         for (auto const& column : _pOriginalContainer->m_aItems)
137         {
138             // ask the col for a factory for the clone
139             xColCloneable.set(column, css::uno::UNO_QUERY);
140             DBG_ASSERT( xColCloneable.is(), "OGridControlModel::cloneColumns: column is not cloneable!" );
141             if ( xColCloneable.is() )
142             {
143                 // create a clone of the column
144                 Reference< XCloneable > xColClone( xColCloneable->createClone() );
145                 DBG_ASSERT( xColClone.is(), "OGridControlModel::cloneColumns: invalid column clone!" );
146                 if ( xColClone.is() )
147                 {
148                     // insert this clone into our own container
149                     insertByIndex( nIndex, xColClone->queryInterface( m_aElementType ) );
150                 }
151             }
152             ++nIndex;
153         }
154     }
155     catch( const Exception& )
156     {
157         TOOLS_WARN_EXCEPTION( "forms.component", "OGridControlModel::cloneColumns: caught an exception while cloning the columns!" );
158     }
159 }
160 
161 // XServiceInfo
getSupportedServiceNames()162 css::uno::Sequence<OUString> OGridControlModel::getSupportedServiceNames()
163 {
164     css::uno::Sequence<OUString> aSupported = OControlModel::getSupportedServiceNames();
165     aSupported.realloc(aSupported.getLength() + 4);
166     aSupported[aSupported.getLength()-4] = "com.sun.star.awt.UnoControlModel";
167     aSupported[aSupported.getLength()-3] = FRM_SUN_COMPONENT_GRIDCONTROL;
168     aSupported[aSupported.getLength()-2] = FRM_COMPONENT_GRID;
169     aSupported[aSupported.getLength()-1] = FRM_COMPONENT_GRIDCONTROL;
170     return aSupported;
171 }
queryAggregation(const Type & _rType)172 Any SAL_CALL OGridControlModel::queryAggregation( const Type& _rType )
173 {
174     Any aReturn = OGridControlModel_BASE::queryInterface(_rType);
175     if ( !aReturn.hasValue() )
176     {
177         aReturn = OControlModel::queryAggregation( _rType );
178         if ( !aReturn.hasValue() )
179         {
180             aReturn = OInterfaceContainer::queryInterface( _rType );
181             if ( !aReturn.hasValue() )
182                 aReturn = OErrorBroadcaster::queryInterface( _rType );
183         }
184     }
185     return aReturn;
186 }
187 
188 // XSQLErrorListener
errorOccured(const SQLErrorEvent & _rEvent)189 void SAL_CALL OGridControlModel::errorOccured( const SQLErrorEvent& _rEvent )
190 {
191     // forward the errors which happened to my columns to my own listeners
192     onError( _rEvent );
193 }
194 
195 // XRowSetSupplier
getRowSet()196 Reference< XRowSet > SAL_CALL OGridControlModel::getRowSet(  )
197 {
198     return Reference< XRowSet >( getParent(), UNO_QUERY );
199 }
200 
setRowSet(const Reference<XRowSet> &)201 void SAL_CALL OGridControlModel::setRowSet( const Reference< XRowSet >& /*_rxDataSource*/ )
202 {
203     OSL_FAIL( "OGridControlModel::setRowSet: not supported!" );
204 }
205 
addRowSetChangeListener(const Reference<XRowSetChangeListener> & i_Listener)206 void SAL_CALL OGridControlModel::addRowSetChangeListener( const Reference< XRowSetChangeListener >& i_Listener )
207 {
208     if ( i_Listener.is() )
209         m_aRowSetChangeListeners.addInterface( i_Listener );
210 }
211 
removeRowSetChangeListener(const Reference<XRowSetChangeListener> & i_Listener)212 void SAL_CALL OGridControlModel::removeRowSetChangeListener( const Reference< XRowSetChangeListener >& i_Listener )
213 {
214     m_aRowSetChangeListeners.removeInterface( i_Listener );
215 }
216 
217 // XChild
setParent(const css::uno::Reference<css::uno::XInterface> & i_Parent)218 void SAL_CALL OGridControlModel::setParent( const css::uno::Reference<css::uno::XInterface>& i_Parent )
219 {
220     ::osl::ClearableMutexGuard aGuard( m_aMutex );
221     if ( i_Parent == getParent() )
222         return;
223     OControlModel::setParent( i_Parent );
224     EventObject aEvent( *this );
225     aGuard.clear();
226     m_aRowSetChangeListeners.notifyEach( &XRowSetChangeListener::onRowSetChanged, aEvent );
227 }
getTypes()228 Sequence< Type > SAL_CALL OGridControlModel::getTypes(  )
229 {
230     return concatSequences(
231         concatSequences(
232             OControlModel::getTypes(),
233             OInterfaceContainer::getTypes(),
234             OErrorBroadcaster::getTypes()
235         ),
236         OGridControlModel_BASE::getTypes()
237     );
238 }
239 
240 // OComponentHelper
disposing()241 void OGridControlModel::disposing()
242 {
243     OControlModel::disposing();
244     OErrorBroadcaster::disposing();
245     OInterfaceContainer::disposing();
246     setParent(nullptr);
247     EventObject aEvt(static_cast<XWeak*>(this));
248     m_aSelectListeners.disposeAndClear(aEvt);
249     m_aResetListeners.disposeAndClear(aEvt);
250     m_aRowSetChangeListeners.disposeAndClear(aEvt);
251 }
252 
253 // XEventListener
disposing(const EventObject & _rEvent)254 void OGridControlModel::disposing(const EventObject& _rEvent)
255 {
256     OControlModel::disposing( _rEvent );
257     OInterfaceContainer::disposing( _rEvent );
258 }
259 
260 // XSelectionSupplier
select(const Any & rElement)261 sal_Bool SAL_CALL OGridControlModel::select(const Any& rElement)
262 {
263     ::osl::ClearableMutexGuard aGuard( m_aMutex );
264     Reference<XPropertySet> xSel;
265     if (rElement.hasValue())
266     {
267         xSel.set(rElement, css::uno::UNO_QUERY);
268         if (!xSel.is())
269         {
270             throw IllegalArgumentException();
271         }
272     }
273     css::uno::Reference<css::uno::XInterface> xMe = static_cast<XWeak*>(this);
274     if (xSel.is())
275     {
276         Reference<XChild> xAsChild(xSel, UNO_QUERY);
277         if (!xAsChild.is() || (xAsChild->getParent() != xMe))
278         {
279             throw IllegalArgumentException();
280         }
281     }
282     if ( xSel != m_xSelection )
283     {
284         m_xSelection = xSel;
285         aGuard.clear();
286         m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, EventObject( *this ) );
287         return true;
288     }
289     return false;
290 }
getSelection()291 Any SAL_CALL OGridControlModel::getSelection()
292 {
293     return makeAny(m_xSelection);
294 }
295 
addSelectionChangeListener(const Reference<XSelectionChangeListener> & _rxListener)296 void OGridControlModel::addSelectionChangeListener(const Reference< XSelectionChangeListener >& _rxListener)
297 {
298     m_aSelectListeners.addInterface(_rxListener);
299 }
300 
removeSelectionChangeListener(const Reference<XSelectionChangeListener> & _rxListener)301 void OGridControlModel::removeSelectionChangeListener(const Reference< XSelectionChangeListener >& _rxListener)
302 {
303     m_aSelectListeners.removeInterface(_rxListener);
304 }
305 
306 // XGridColumnFactory
createColumn(const OUString & ColumnType)307 Reference<XPropertySet> SAL_CALL OGridControlModel::createColumn(const OUString& ColumnType)
308 {
309     SolarMutexGuard g;
310     const Sequence< OUString >& rColumnTypes = frm::getColumnTypes();
311     return createColumnById( ::detail::findPos( ColumnType, rColumnTypes ) );
312 }
createColumnById(sal_Int32 nTypeId) const313 Reference<XPropertySet>  OGridControlModel::createColumnById(sal_Int32 nTypeId) const
314 {
315     Reference<XPropertySet>  xReturn;
316     switch (nTypeId)
317     {
318         case TYPE_CHECKBOX:         xReturn = new CheckBoxColumn( getContext() ); break;
319         case TYPE_COMBOBOX:         xReturn = new ComboBoxColumn( getContext() ); break;
320         case TYPE_CURRENCYFIELD:    xReturn = new CurrencyFieldColumn( getContext() ); break;
321         case TYPE_DATEFIELD:        xReturn = new DateFieldColumn( getContext() ); break;
322         case TYPE_LISTBOX:          xReturn = new ListBoxColumn( getContext() ); break;
323         case TYPE_NUMERICFIELD:     xReturn = new NumericFieldColumn( getContext() ); break;
324         case TYPE_PATTERNFIELD:     xReturn = new PatternFieldColumn( getContext() ); break;
325         case TYPE_TEXTFIELD:        xReturn = new TextFieldColumn( getContext() ); break;
326         case TYPE_TIMEFIELD:        xReturn = new TimeFieldColumn( getContext() ); break;
327         case TYPE_FORMATTEDFIELD:   xReturn = new FormattedFieldColumn( getContext() ); break;
328         default:
329             OSL_FAIL("OGridControlModel::createColumn: Unknown Column");
330             break;
331     }
332     return xReturn;
333 }
getColumnTypes()334 css::uno::Sequence<OUString> SAL_CALL OGridControlModel::getColumnTypes()
335 {
336     return frm::getColumnTypes();
337 }
338 
339 // XReset
reset()340 void SAL_CALL OGridControlModel::reset()
341 {
342     ::comphelper::OInterfaceIteratorHelper2 aIter(m_aResetListeners);
343     EventObject aEvt(static_cast<XWeak*>(this));
344     bool bContinue = true;
345     while (aIter.hasMoreElements() && bContinue)
346         bContinue = static_cast<XResetListener*>(aIter.next())->approveReset(aEvt);
347     if (bContinue)
348     {
349         _reset();
350         m_aResetListeners.notifyEach( &XResetListener::resetted, aEvt );
351     }
352 }
addResetListener(const Reference<XResetListener> & _rxListener)353 void SAL_CALL OGridControlModel::addResetListener(const Reference<XResetListener>& _rxListener)
354 {
355     m_aResetListeners.addInterface(_rxListener);
356 }
removeResetListener(const Reference<XResetListener> & _rxListener)357 void SAL_CALL OGridControlModel::removeResetListener(const Reference<XResetListener>& _rxListener)
358 {
359     m_aResetListeners.removeInterface(_rxListener);
360 }
_reset()361 void OGridControlModel::_reset()
362 {
363     Reference<XReset> xReset;
364     sal_Int32 nCount = getCount();
365     for (sal_Int32 nIndex=0; nIndex < nCount; nIndex++)
366     {
367         getByIndex( nIndex ) >>= xReset;
368         if (xReset.is())
369             xReset->reset();
370     }
371 }
372 
373 // XPropertySet
describeFixedProperties(Sequence<Property> & _rProps) const374 void OGridControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
375 {
376     BEGIN_DESCRIBE_BASE_PROPERTIES( 37 )
377         DECL_PROP1(NAME,                OUString,    BOUND);
378         DECL_PROP2(CLASSID,             sal_Int16,          READONLY, TRANSIENT);
379         DECL_PROP1(TAG,                 OUString,    BOUND);
380         DECL_PROP1(TABINDEX,            sal_Int16,          BOUND);
381         DECL_PROP3(TABSTOP,             sal_Bool,           BOUND, MAYBEDEFAULT, MAYBEVOID);
382         DECL_PROP2(HASNAVIGATION,       sal_Bool,           BOUND, MAYBEDEFAULT);
383         DECL_PROP1(ENABLED,             sal_Bool,           BOUND);
384         DECL_PROP2(ENABLEVISIBLE,       sal_Bool,           BOUND, MAYBEDEFAULT);
385         DECL_PROP1(BORDER,              sal_Int16,          BOUND);
386         DECL_PROP2(BORDERCOLOR,         sal_Int16,          BOUND, MAYBEVOID);
387         DECL_PROP1(DEFAULTCONTROL,      OUString,    BOUND);
388         DECL_PROP3(TEXTCOLOR,           sal_Int32,          BOUND, MAYBEDEFAULT, MAYBEVOID);
389         DECL_PROP3(BACKGROUNDCOLOR,     sal_Int32,          BOUND, MAYBEDEFAULT, MAYBEVOID);
390         DECL_PROP2(FONT,                FontDescriptor,     BOUND, MAYBEDEFAULT);
391         DECL_PROP3(ROWHEIGHT,           sal_Int32,          BOUND, MAYBEDEFAULT, MAYBEVOID);
392         DECL_PROP1(HELPTEXT,            OUString,    BOUND);
393         DECL_PROP1(FONT_NAME,           OUString,    MAYBEDEFAULT);
394         DECL_PROP1(FONT_STYLENAME,      OUString,    MAYBEDEFAULT);
395         DECL_PROP1(FONT_FAMILY,         sal_Int16,          MAYBEDEFAULT);
396         DECL_PROP1(FONT_CHARSET,        sal_Int16,          MAYBEDEFAULT);
397         DECL_PROP1(FONT_HEIGHT,         float,              MAYBEDEFAULT);
398         DECL_PROP1(FONT_WEIGHT,         float,              MAYBEDEFAULT);
399         DECL_PROP1(FONT_SLANT,          sal_Int16,          MAYBEDEFAULT);
400         DECL_PROP1(FONT_UNDERLINE,      sal_Int16,          MAYBEDEFAULT);
401         DECL_BOOL_PROP1(FONT_WORDLINEMODE,                  MAYBEDEFAULT);
402         DECL_PROP3(TEXTLINECOLOR,       sal_Int32,          BOUND, MAYBEDEFAULT, MAYBEVOID);
403         DECL_PROP2(FONTEMPHASISMARK,    sal_Int16,          BOUND, MAYBEDEFAULT);
404         DECL_PROP2(FONTRELIEF,          sal_Int16,          BOUND, MAYBEDEFAULT);
405         DECL_PROP1(FONT_STRIKEOUT,      sal_Int16,          MAYBEDEFAULT);
406         DECL_PROP2(RECORDMARKER,        sal_Bool,           BOUND, MAYBEDEFAULT );
407         DECL_PROP2(PRINTABLE,           sal_Bool,           BOUND, MAYBEDEFAULT );
408         DECL_PROP4(CURSORCOLOR,         sal_Int32,          BOUND, MAYBEDEFAULT, MAYBEVOID , TRANSIENT);
409         DECL_PROP3(ALWAYSSHOWCURSOR,    sal_Bool,           BOUND, MAYBEDEFAULT, TRANSIENT);
410         DECL_PROP3(DISPLAYSYNCHRON,     sal_Bool,           BOUND, MAYBEDEFAULT, TRANSIENT);
411         DECL_PROP2(HELPURL,             OUString,    BOUND, MAYBEDEFAULT);
412         DECL_PROP2(WRITING_MODE,        sal_Int16,          BOUND, MAYBEDEFAULT);
413         DECL_PROP3(CONTEXT_WRITING_MODE,sal_Int16,          BOUND, MAYBEDEFAULT, TRANSIENT);
414     END_DESCRIBE_PROPERTIES();
415 }
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const416 void OGridControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const
417 {
418     switch (nHandle)
419     {
420         case PROPERTY_ID_CONTEXT_WRITING_MODE:
421             rValue <<= m_nContextWritingMode;
422             break;
423         case PROPERTY_ID_WRITING_MODE:
424             rValue <<= m_nWritingMode;
425             break;
426         case PROPERTY_ID_HELPTEXT:
427             rValue <<= m_sHelpText;
428             break;
429         case PROPERTY_ID_HELPURL:
430             rValue <<= m_sHelpURL;
431             break;
432         case PROPERTY_ID_DISPLAYSYNCHRON:
433             rValue <<= m_bDisplaySynchron;
434             break;
435         case PROPERTY_ID_ALWAYSSHOWCURSOR:
436             rValue <<= m_bAlwaysShowCursor;
437             break;
438         case PROPERTY_ID_CURSORCOLOR:
439             rValue = m_aCursorColor;
440             break;
441         case PROPERTY_ID_PRINTABLE:
442             rValue <<= m_bPrintable;
443             break;
444         case PROPERTY_ID_TABSTOP:
445             rValue = m_aTabStop;
446             break;
447         case PROPERTY_ID_HASNAVIGATION:
448             rValue <<= m_bNavigation;
449             break;
450         case PROPERTY_ID_RECORDMARKER:
451             rValue <<= m_bRecordMarker;
452             break;
453         case PROPERTY_ID_ENABLED:
454             rValue <<= m_bEnable;
455             break;
456         case PROPERTY_ID_ENABLEVISIBLE:
457             rValue <<= m_bEnableVisible;
458             break;
459         case PROPERTY_ID_BORDER:
460             rValue <<= m_nBorder;
461             break;
462         case PROPERTY_ID_BORDERCOLOR:
463             rValue = m_aBorderColor;
464             break;
465         case PROPERTY_ID_DEFAULTCONTROL:
466             rValue <<= m_aDefaultControl;
467             break;
468         case PROPERTY_ID_BACKGROUNDCOLOR:
469             rValue = m_aBackgroundColor;
470             break;
471         case PROPERTY_ID_ROWHEIGHT:
472             rValue = m_aRowHeight;
473             break;
474         default:
475             if ( isFontRelatedProperty( nHandle ) )
476                 FontControlModel::getFastPropertyValue( rValue, nHandle );
477             else
478                 OControlModel::getFastPropertyValue( rValue, nHandle );
479     }
480 }
481 
convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)482 sal_Bool OGridControlModel::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue,
483                                                     sal_Int32 nHandle, const Any& rValue )
484 {
485     bool bModified(false);
486     switch (nHandle)
487     {
488         case PROPERTY_ID_CONTEXT_WRITING_MODE:
489             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_nContextWritingMode );
490             break;
491         case PROPERTY_ID_WRITING_MODE:
492             bModified = tryPropertyValue( rConvertedValue, rOldValue, rValue, m_nWritingMode );
493             break;
494         case PROPERTY_ID_HELPTEXT:
495             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sHelpText);
496             break;
497         case PROPERTY_ID_HELPURL:
498             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_sHelpURL);
499             break;
500         case PROPERTY_ID_DISPLAYSYNCHRON:
501             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bDisplaySynchron);
502             break;
503         case PROPERTY_ID_ALWAYSSHOWCURSOR:
504             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAlwaysShowCursor);
505             break;
506         case PROPERTY_ID_CURSORCOLOR:
507             if (!rValue.hasValue() || !m_aCursorColor.hasValue())
508             {
509                 if (rValue.hasValue() && (TypeClass_LONG != rValue.getValueType().getTypeClass()))
510                 {
511                     throw IllegalArgumentException();
512                 }
513                 rOldValue = m_aCursorColor;
514                 rConvertedValue = rValue;
515                 bModified = rOldValue != rConvertedValue;
516             }
517             else
518                 bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, getINT32(m_aCursorColor));
519             break;
520         case PROPERTY_ID_PRINTABLE:
521             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bPrintable);
522             break;
523         case PROPERTY_ID_TABSTOP:
524             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aTabStop, cppu::UnoType<bool>::get());
525             break;
526         case PROPERTY_ID_HASNAVIGATION:
527             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bNavigation);
528             break;
529         case PROPERTY_ID_RECORDMARKER:
530             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bRecordMarker);
531             break;
532         case PROPERTY_ID_ENABLED:
533             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEnable);
534             break;
535         case PROPERTY_ID_ENABLEVISIBLE:
536             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEnableVisible);
537             break;
538         case PROPERTY_ID_BORDER:
539             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_nBorder);
540             break;
541         case PROPERTY_ID_BORDERCOLOR:
542             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aBorderColor, cppu::UnoType<sal_Int32>::get());
543             break;
544         case PROPERTY_ID_DEFAULTCONTROL:
545             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aDefaultControl);
546             break;
547         case PROPERTY_ID_BACKGROUNDCOLOR:
548             bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aBackgroundColor, cppu::UnoType<sal_Int32>::get());
549             break;
550         case PROPERTY_ID_ROWHEIGHT:
551             {
552                 bModified = tryPropertyValue(rConvertedValue, rOldValue, rValue, m_aRowHeight, cppu::UnoType<sal_Int32>::get());
553                 sal_Int32 nNewVal( 0 );
554                 if ( ( rConvertedValue >>= nNewVal ) && ( nNewVal <= 0 ) )
555                 {
556                     rConvertedValue.clear();
557                     bModified = m_aRowHeight.hasValue();
558                 }
559             }
560             break;
561         default:
562             if ( isFontRelatedProperty( nHandle ) )
563                 bModified = FontControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
564             else
565                 bModified = OControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue);
566     }
567     return bModified;
568 }
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)569 void OGridControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
570 {
571     switch (nHandle)
572     {
573         case PROPERTY_ID_CONTEXT_WRITING_MODE:
574             rValue >>= m_nContextWritingMode;
575             break;
576         case PROPERTY_ID_WRITING_MODE:
577             rValue >>= m_nWritingMode;
578             break;
579         case PROPERTY_ID_HELPTEXT:
580             rValue >>= m_sHelpText;
581             break;
582         case PROPERTY_ID_HELPURL:
583             rValue >>= m_sHelpURL;
584             break;
585         case PROPERTY_ID_DISPLAYSYNCHRON:
586             m_bDisplaySynchron = getBOOL(rValue);
587             break;
588         case PROPERTY_ID_ALWAYSSHOWCURSOR:
589             m_bAlwaysShowCursor = getBOOL(rValue);
590             break;
591         case PROPERTY_ID_CURSORCOLOR:
592             m_aCursorColor = rValue;
593             break;
594         case PROPERTY_ID_PRINTABLE:
595             m_bPrintable = getBOOL(rValue);
596             break;
597         case PROPERTY_ID_TABSTOP:
598             m_aTabStop = rValue;
599             break;
600         case PROPERTY_ID_HASNAVIGATION:
601             m_bNavigation = getBOOL(rValue);
602             break;
603         case PROPERTY_ID_ENABLED:
604             m_bEnable = getBOOL(rValue);
605             break;
606         case PROPERTY_ID_ENABLEVISIBLE:
607             m_bEnableVisible = getBOOL(rValue);
608             break;
609         case PROPERTY_ID_RECORDMARKER:
610             m_bRecordMarker = getBOOL(rValue);
611             break;
612         case PROPERTY_ID_BORDER:
613             rValue >>= m_nBorder;
614             break;
615         case PROPERTY_ID_BORDERCOLOR:
616             m_aBorderColor = rValue;
617             break;
618         case PROPERTY_ID_DEFAULTCONTROL:
619             rValue >>= m_aDefaultControl;
620             break;
621         case PROPERTY_ID_BACKGROUNDCOLOR:
622             m_aBackgroundColor = rValue;
623             break;
624         case PROPERTY_ID_ROWHEIGHT:
625             m_aRowHeight = rValue;
626             break;
627         default:
628             if ( isFontRelatedProperty( nHandle ) )
629             {
630                 FontControlModel::setFastPropertyValue_NoBroadcast_impl(
631                     *this, &OGridControlModel::setDependentFastPropertyValue,
632                     nHandle, rValue);
633             }
634             else
635                 OControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
636     }
637 }
638 
639 //XPropertyState
getPropertyDefaultByHandle(sal_Int32 nHandle) const640 Any OGridControlModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
641 {
642     Any aReturn;
643     switch (nHandle)
644     {
645         case PROPERTY_ID_CONTEXT_WRITING_MODE:
646         case PROPERTY_ID_WRITING_MODE:
647             aReturn <<= WritingMode2::CONTEXT;
648             break;
649         case PROPERTY_ID_DEFAULTCONTROL:
650             aReturn <<= OUString( STARDIV_ONE_FORM_CONTROL_GRID  );
651             break;
652         case PROPERTY_ID_PRINTABLE:
653         case PROPERTY_ID_HASNAVIGATION:
654         case PROPERTY_ID_RECORDMARKER:
655         case PROPERTY_ID_DISPLAYSYNCHRON:
656         case PROPERTY_ID_ENABLED:
657         case PROPERTY_ID_ENABLEVISIBLE:
658             aReturn <<= true;
659             break;
660         case PROPERTY_ID_ALWAYSSHOWCURSOR:
661             aReturn <<= false;
662             break;
663         case PROPERTY_ID_HELPURL:
664         case PROPERTY_ID_HELPTEXT:
665             aReturn <<= OUString();
666             break;
667         case PROPERTY_ID_BORDER:
668             aReturn <<= sal_Int16(1);
669             break;
670         case PROPERTY_ID_BORDERCOLOR:
671         case PROPERTY_ID_TABSTOP:
672         case PROPERTY_ID_BACKGROUNDCOLOR:
673         case PROPERTY_ID_ROWHEIGHT:
674         case PROPERTY_ID_CURSORCOLOR:
675             // void
676             break;
677         default:
678             if ( isFontRelatedProperty( nHandle ) )
679                 aReturn = FontControlModel::getPropertyDefaultByHandle( nHandle );
680             else
681                 aReturn = OControlModel::getPropertyDefaultByHandle(nHandle);
682     }
683     return aReturn;
684 }
685 
gotColumn(const Reference<XInterface> & _rxColumn)686 void OGridControlModel::gotColumn( const Reference< XInterface >& _rxColumn )
687 {
688     Reference< XSQLErrorBroadcaster > xBroadcaster( _rxColumn, UNO_QUERY );
689     if ( xBroadcaster.is() )
690         xBroadcaster->addSQLErrorListener( this );
691 }
692 
lostColumn(const Reference<XInterface> & _rxColumn)693 void OGridControlModel::lostColumn(const Reference< XInterface >& _rxColumn)
694 {
695     if ( m_xSelection == _rxColumn )
696     {   // the currently selected element was replaced
697         m_xSelection.clear();
698         EventObject aEvt( static_cast< XWeak* >( this ) );
699         m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, aEvt );
700     }
701     Reference< XSQLErrorBroadcaster > xBroadcaster( _rxColumn, UNO_QUERY );
702     if ( xBroadcaster.is() )
703         xBroadcaster->removeSQLErrorListener( this );
704 }
705 
implRemoved(const css::uno::Reference<css::uno::XInterface> & _rxObject)706 void OGridControlModel::implRemoved(const css::uno::Reference<css::uno::XInterface>& _rxObject)
707 {
708     OInterfaceContainer::implRemoved(_rxObject);
709     lostColumn(_rxObject);
710 }
711 
implInserted(const ElementDescription * _pElement)712 void OGridControlModel::implInserted( const ElementDescription* _pElement )
713 {
714     OInterfaceContainer::implInserted( _pElement );
715     gotColumn( _pElement->xInterface );
716 }
717 
impl_replacedElement(const ContainerEvent & _rEvent,::osl::ClearableMutexGuard & _rInstanceLock)718 void OGridControlModel::impl_replacedElement( const ContainerEvent& _rEvent, ::osl::ClearableMutexGuard& _rInstanceLock )
719 {
720     Reference< XInterface > xOldColumn( _rEvent.ReplacedElement, UNO_QUERY );
721     Reference< XInterface > xNewColumn( _rEvent.Element, UNO_QUERY );
722     bool bNewSelection = ( xOldColumn == m_xSelection );
723     lostColumn( xOldColumn );
724     gotColumn( xNewColumn );
725     if ( bNewSelection )
726         m_xSelection.set( xNewColumn, UNO_QUERY );
727     OInterfaceContainer::impl_replacedElement( _rEvent, _rInstanceLock );
728     // < SYNCHRONIZED
729     if ( bNewSelection )
730     {
731         m_aSelectListeners.notifyEach( &XSelectionChangeListener::selectionChanged, EventObject( *this ) );
732     }
733 }
734 
createElementMetaData()735 ElementDescription* OGridControlModel::createElementMetaData( )
736 {
737     return new ElementDescription;
738 }
739 
approveNewElement(const Reference<XPropertySet> & _rxObject,ElementDescription * _pElement)740 void OGridControlModel::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement )
741 {
742     OGridColumn* pCol = comphelper::getUnoTunnelImplementation<OGridColumn>( _rxObject );
743     if ( !pCol )
744         throw IllegalArgumentException();
745     OInterfaceContainer::approveNewElement( _rxObject, _pElement );
746 }
747 
748 // XPersistObject
getServiceName()749 OUString SAL_CALL OGridControlModel::getServiceName()
750 {
751     return FRM_COMPONENT_GRID;  // old (non-sun) name for compatibility!
752 }
753 
write(const Reference<XObjectOutputStream> & _rxOutStream)754 void OGridControlModel::write(const Reference<XObjectOutputStream>& _rxOutStream)
755 {
756     OControlModel::write(_rxOutStream);
757     Reference<XMarkableStream>  xMark(_rxOutStream, UNO_QUERY);
758     // 1. Version
759     _rxOutStream->writeShort(0x0008);
760     // 2. Columns
761     sal_Int32 nLen = getCount();
762     _rxOutStream->writeLong(nLen);
763     for (sal_Int32 i = 0; i < nLen; i++)
764     {
765         // first the service name for the underlying model
766         OGridColumn* pCol = comphelper::getUnoTunnelImplementation<OGridColumn>(m_aItems[i]);
767         DBG_ASSERT(pCol != nullptr, "OGridControlModel::write : such items should never reach it into my container !");
768         _rxOutStream << pCol->getModelName();
769         // then the object itself
770         sal_Int32 nMark = xMark->createMark();
771         sal_Int32 nObjLen = 0;
772         _rxOutStream->writeLong(nObjLen);
773         // writing the column
774         pCol->write(_rxOutStream);
775         // determining the length
776         nObjLen = xMark->offsetToMark(nMark) - 4;
777         xMark->jumpToMark(nMark);
778         _rxOutStream->writeLong(nObjLen);
779         xMark->jumpToFurthest();
780         xMark->deleteMark(nMark);
781     }
782     // 3. Events
783     writeEvents(_rxOutStream);
784     // 4. Attributes
785     // Masking for all 'any' types
786     sal_uInt16 nAnyMask = 0;
787     if (m_aRowHeight.getValueType().getTypeClass() == TypeClass_LONG)
788         nAnyMask |= ROWHEIGHT;
789     if ( getFont() != getDefaultFont() )
790         nAnyMask |= FONTATTRIBS | FONTSIZE | FONTTYPE | FONTDESCRIPTOR;
791     if (m_aTabStop.getValueType().getTypeClass() == TypeClass_BOOLEAN)
792         nAnyMask |= TABSTOP;
793     if ( hasTextColor() )
794         nAnyMask |= TEXTCOLOR;
795     if (m_aBackgroundColor.getValueType().getTypeClass() == TypeClass_LONG)
796         nAnyMask |= BACKGROUNDCOLOR;
797     if (!m_bRecordMarker)
798         nAnyMask |= RECORDMARKER;
799     _rxOutStream->writeShort(nAnyMask);
800     if (nAnyMask & ROWHEIGHT)
801         _rxOutStream->writeLong(getINT32(m_aRowHeight));
802     // old structures
803     const FontDescriptor& aFont = getFont();
804     if ( nAnyMask & FONTDESCRIPTOR )
805     {
806         // Attrib
807         _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( vcl::unohelper::ConvertFontWeight( aFont.Weight ) ) );
808         _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( aFont.Slant ) );
809         _rxOutStream->writeShort( aFont.Underline );
810         _rxOutStream->writeShort( aFont.Strikeout );
811         _rxOutStream->writeShort( sal_Int16(aFont.Orientation * 10) );
812         _rxOutStream->writeBoolean( aFont.Kerning );
813         _rxOutStream->writeBoolean( aFont.WordLineMode );
814         // Size
815         _rxOutStream->writeLong( aFont.Width );
816         _rxOutStream->writeLong( aFont.Height );
817         _rxOutStream->writeShort( sal::static_int_cast< sal_Int16 >( vcl::unohelper::ConvertFontWidth( aFont.CharacterWidth ) ) );
818         // Type
819         _rxOutStream->writeUTF( aFont.Name );
820         _rxOutStream->writeUTF( aFont.StyleName );
821         _rxOutStream->writeShort( aFont.Family );
822         _rxOutStream->writeShort( aFont.CharSet );
823         _rxOutStream->writeShort( aFont.Pitch );
824     }
825     _rxOutStream << m_aDefaultControl;
826     _rxOutStream->writeShort(m_nBorder);
827     _rxOutStream->writeBoolean(m_bEnable);
828     if (nAnyMask & TABSTOP)
829         _rxOutStream->writeBoolean(getBOOL(m_aTabStop));
830     _rxOutStream->writeBoolean(m_bNavigation);
831     if (nAnyMask & TEXTCOLOR)
832         _rxOutStream->writeLong( sal_Int32(getTextColor()) );
833     // new since version 6
834     _rxOutStream << m_sHelpText;
835     if (nAnyMask & FONTDESCRIPTOR)
836         _rxOutStream << getFont();
837     if (nAnyMask & RECORDMARKER)
838         _rxOutStream->writeBoolean(m_bRecordMarker);
839     // new since version 7
840     _rxOutStream->writeBoolean(m_bPrintable);
841     // new since version 8
842     if (nAnyMask & BACKGROUNDCOLOR)
843         _rxOutStream->writeLong(getINT32(m_aBackgroundColor));
844 }
845 
read(const Reference<XObjectInputStream> & _rxInStream)846 void OGridControlModel::read(const Reference<XObjectInputStream>& _rxInStream)
847 {
848     SolarMutexGuard g;
849     OControlModel::read(_rxInStream);
850     Reference<XMarkableStream>  xMark(_rxInStream, UNO_QUERY);
851     // 1. version
852     sal_Int16 nVersion = _rxInStream->readShort();
853     // 2. reading the columns
854     sal_Int32 nLen = _rxInStream->readLong();
855     if (nLen)
856     {
857         for (sal_Int32 i = 0; i < nLen; i++)
858         {
859             // reading the model names
860             OUString sModelName;
861             _rxInStream >> sModelName;
862             Reference<XPropertySet>  xCol(createColumnById(getColumnTypeByModelName(sModelName)));
863             DBG_ASSERT(xCol.is(), "OGridControlModel::read : unknown column type !");
864             sal_Int32 nObjLen = _rxInStream->readLong();
865             if (nObjLen)
866             {
867                 sal_Int32 nMark = xMark->createMark();
868                 if (xCol.is())
869                 {
870                     OGridColumn* pCol = comphelper::getUnoTunnelImplementation<OGridColumn>(xCol);
871                     pCol->read(_rxInStream);
872                 }
873                 xMark->jumpToMark(nMark);
874                 _rxInStream->skipBytes(nObjLen);
875                 xMark->deleteMark(nMark);
876             }
877             if ( xCol.is() )
878                 implInsert( i, xCol, false, nullptr, false );
879         }
880     }
881     // In the base implementation events are only read, elements in the container exist
882     // but since before TF_ONE for the GridControl events were always written, so they
883     // need to be read, too
884     sal_Int32 nObjLen = _rxInStream->readLong();
885     if (nObjLen)
886     {
887         sal_Int32 nMark = xMark->createMark();
888         Reference<XPersistObject>  xObj(m_xEventAttacher, UNO_QUERY);
889         if (xObj.is())
890             xObj->read(_rxInStream);
891         xMark->jumpToMark(nMark);
892         _rxInStream->skipBytes(nObjLen);
893         xMark->deleteMark(nMark);
894     }
895     // reading the attachment
896     for (sal_Int32 i = 0; i < nLen; i++)
897     {
898         css::uno::Reference<css::uno::XInterface>  xIfc(m_aItems[i], UNO_QUERY);
899         Reference<XPropertySet>  xSet(xIfc, UNO_QUERY);
900         Any aHelper;
901         aHelper <<= xSet;
902         m_xEventAttacher->attach( i, xIfc, aHelper );
903     }
904     // 4. reading the attributes
905     if (nVersion == 1)
906         return;
907     // Masking for any
908     sal_uInt16 nAnyMask = _rxInStream->readShort();
909     if (nAnyMask & ROWHEIGHT)
910     {
911         sal_Int32 nValue = _rxInStream->readLong();
912         m_aRowHeight <<= nValue;
913     }
914     FontDescriptor aFont( getFont() );
915     if ( nAnyMask & FONTATTRIBS )
916     {
917         aFont.Weight = static_cast<float>(vcl::unohelper::ConvertFontWeight( _rxInStream->readShort() ));
918         aFont.Slant = static_cast<FontSlant>(_rxInStream->readShort());
919         aFont.Underline = _rxInStream->readShort();
920         aFont.Strikeout = _rxInStream->readShort();
921         aFont.Orientation = static_cast<float>(_rxInStream->readShort()) / 10;
922         aFont.Kerning = _rxInStream->readBoolean() != 0;
923         aFont.WordLineMode = _rxInStream->readBoolean() != 0;
924     }
925     if ( nAnyMask & FONTSIZE )
926     {
927         aFont.Width = static_cast<sal_Int16>(_rxInStream->readLong());
928         aFont.Height = static_cast<sal_Int16>(_rxInStream->readLong());
929         aFont.CharacterWidth = static_cast<float>(vcl::unohelper::ConvertFontWidth( _rxInStream->readShort() ));
930     }
931     if ( nAnyMask & FONTTYPE )
932     {
933         aFont.Name = _rxInStream->readUTF();
934         aFont.StyleName = _rxInStream->readUTF();
935         aFont.Family = _rxInStream->readShort();
936         aFont.CharSet = _rxInStream->readShort();
937         aFont.Pitch = _rxInStream->readShort();
938     }
939     if ( nAnyMask & ( FONTATTRIBS | FONTSIZE | FONTTYPE ) )
940         setFont( aFont );
941     // Name
942     _rxInStream >> m_aDefaultControl;
943     m_nBorder = _rxInStream->readShort();
944     m_bEnable = _rxInStream->readBoolean();
945     if (nAnyMask & TABSTOP)
946     {
947         m_aTabStop <<= (_rxInStream->readBoolean() != 0);
948     }
949     if (nVersion > 3)
950         m_bNavigation = _rxInStream->readBoolean();
951     if (nAnyMask & TEXTCOLOR)
952     {
953         sal_Int32 nValue = _rxInStream->readLong();
954         setTextColor( ::Color(ColorTransparency, nValue) );
955     }
956     // new since version 6
957     if (nVersion > 5)
958         _rxInStream >> m_sHelpText;
959     if (nAnyMask & FONTDESCRIPTOR)
960     {
961         FontDescriptor aUNOFont;
962         _rxInStream >> aUNOFont;
963         setFont( aFont );
964     }
965     if (nAnyMask & RECORDMARKER)
966         m_bRecordMarker = _rxInStream->readBoolean();
967     // new since version 7
968     if (nVersion > 6)
969         m_bPrintable = _rxInStream->readBoolean();
970     if (nAnyMask & BACKGROUNDCOLOR)
971     {
972         sal_Int32 nValue = _rxInStream->readLong();
973         m_aBackgroundColor <<= nValue;
974     }
975 }
976 
977 }
978 
979 extern "C" SAL_DLLPUBLIC_EXPORT XInterface*
com_sun_star_form_OGridControlModel_get_implementation(XComponentContext * component,Sequence<Any> const &)980 com_sun_star_form_OGridControlModel_get_implementation(XComponentContext* component,
981         Sequence<Any> const &)
982 {
983     return cppu::acquire(new frm::OGridControlModel(component));
984 }
985 
986 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
987