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