1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "EditBase.hxx"
21 #include <property.hxx>
22 #include <tools/debug.hxx>
23 #include <comphelper/basicio.hxx>
24 #include <comphelper/property.hxx>
25 #include <comphelper/types.hxx>
26 #include <tools/time.hxx>
27 #include <tools/date.hxx>
28 #include <com/sun/star/io/XMarkableStream.hpp>
29 #include <com/sun/star/util/Time.hpp>
30 #include <com/sun/star/util/Date.hpp>
35 using namespace ::com::sun::star
;
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::sdb
;
38 using namespace ::com::sun::star::sdbc
;
39 using namespace ::com::sun::star::beans
;
40 using namespace ::com::sun::star::container
;
41 using namespace ::com::sun::star::form
;
42 using namespace ::com::sun::star::awt
;
43 using namespace ::com::sun::star::io
;
44 using namespace ::com::sun::star::lang
;
45 using namespace ::com::sun::star::util
;
49 const sal_uInt16 DEFAULT_LONG
= 0x0001;
50 const sal_uInt16 DEFAULT_DOUBLE
= 0x0002;
51 const sal_uInt16 FILTERPROPOSAL
= 0x0004;
52 const sal_uInt16 DEFAULT_TIME
= 0x0008;
53 const sal_uInt16 DEFAULT_DATE
= 0x0010;
57 OEditBaseModel::OEditBaseModel( const Reference
< XComponentContext
>& _rxFactory
, const OUString
& rUnoControlModelName
,
58 const OUString
& rDefault
, const bool _bSupportExternalBinding
, const bool _bSupportsValidation
)
59 :OBoundControlModel( _rxFactory
, rUnoControlModelName
, rDefault
, true, _bSupportExternalBinding
, _bSupportsValidation
)
60 ,m_nLastReadVersion(0)
62 ,m_bFilterProposal(false)
67 OEditBaseModel::OEditBaseModel( const OEditBaseModel
* _pOriginal
, const Reference
< XComponentContext
>& _rxFactory
)
68 :OBoundControlModel( _pOriginal
, _rxFactory
)
69 ,m_nLastReadVersion(0)
72 m_bFilterProposal
= _pOriginal
->m_bFilterProposal
;
73 m_bEmptyIsNull
= _pOriginal
->m_bEmptyIsNull
;
74 m_aDefault
= _pOriginal
->m_aDefault
;
75 m_aDefaultText
= _pOriginal
->m_aDefaultText
;
79 OEditBaseModel::~OEditBaseModel( )
85 void OEditBaseModel::write(const Reference
<XObjectOutputStream
>& _rxOutStream
)
87 OBoundControlModel::write(_rxOutStream
);
90 sal_uInt16 nVersionId
= 0x0006;
91 DBG_ASSERT((getPersistenceFlags() & ~PF_SPECIAL_FLAGS
) == 0,
92 "OEditBaseModel::write : invalid special version flags !");
93 // please don't use other flags, older versions can't interpret them !
95 nVersionId
|= getPersistenceFlags();
96 _rxOutStream
->writeShort(nVersionId
);
99 _rxOutStream
->writeShort(0); // obsolete
100 _rxOutStream
<< m_aDefaultText
;
103 sal_uInt16 nAnyMask
= 0;
104 if (m_aDefault
.getValueType().getTypeClass() == TypeClass_LONG
)
105 nAnyMask
|= DEFAULT_LONG
;
106 else if (m_aDefault
.getValueType().getTypeClass() == TypeClass_DOUBLE
)
107 nAnyMask
|= DEFAULT_DOUBLE
;
108 else if (m_aDefault
.getValueType() == cppu::UnoType
<util::Time
>::get())
109 nAnyMask
|= DEFAULT_TIME
;
110 else if (m_aDefault
.getValueType() == cppu::UnoType
<util::Date
>::get())
111 nAnyMask
|= DEFAULT_DATE
;
113 if (m_bFilterProposal
) // Don't save a value, because it's boolean
114 nAnyMask
|= FILTERPROPOSAL
;
116 _rxOutStream
->writeBoolean(m_bEmptyIsNull
);
117 _rxOutStream
->writeShort(nAnyMask
);
119 if ((nAnyMask
& DEFAULT_LONG
) == DEFAULT_LONG
)
120 _rxOutStream
->writeLong(getINT32(m_aDefault
));
121 else if ((nAnyMask
& DEFAULT_DOUBLE
) == DEFAULT_DOUBLE
)
122 _rxOutStream
->writeDouble(getDouble(m_aDefault
));
123 else if ((nAnyMask
& DEFAULT_TIME
) == DEFAULT_TIME
)
126 OSL_VERIFY(m_aDefault
>>= aTime
);
127 _rxOutStream
->writeHyper(::tools::Time(aTime
).GetTime());
129 else if ((nAnyMask
& DEFAULT_DATE
) == DEFAULT_DATE
)
132 OSL_VERIFY(m_aDefault
>>= aDate
);
133 _rxOutStream
->writeLong(::Date(aDate
).GetDate());
136 // since version 5 we write the help text
137 writeHelpTextCompatibly(_rxOutStream
);
138 // (that's potentially bad : at the time I added the above line we had two derived classes : OEditModel and
139 // OFormattedModel. The first one does not have an own version handling, so it can't write the help text itself,
140 // the second one does its own writing (reading) after calling our method, so normally we shouldn't write any
141 // additional members as this is not compatible to older office versions.
142 // We decided to place the writing of the help text here as it seems the less worse alternative. There is no delivered
143 // office version including formatted controls (and thus the OFormattedModel), and the OFormattedModel::read seems
144 // robust against this change (as it will read a wrong and unknown file version and thus set its members to defaults).
146 if ((nVersionId
& PF_HANDLE_COMMON_PROPS
) != 0)
147 writeCommonEditProperties(_rxOutStream
);
149 // !!! properties common to all OEditBaseModel derived classes should be written in writeCommonEditProperties !!!
153 sal_uInt16
OEditBaseModel::getPersistenceFlags() const
155 return PF_HANDLE_COMMON_PROPS
;
159 void OEditBaseModel::read(const Reference
<XObjectInputStream
>& _rxInStream
)
161 OBoundControlModel::read(_rxInStream
);
162 ::osl::MutexGuard
aGuard(m_aMutex
);
164 // Version's own version number
165 sal_uInt16 nVersion
= _rxInStream
->readShort();
166 m_nLastReadVersion
= nVersion
;
168 bool bHandleCommonProps
= (nVersion
& PF_HANDLE_COMMON_PROPS
) != 0;
169 nVersion
= nVersion
& ~PF_SPECIAL_FLAGS
;
172 _rxInStream
->readShort();
174 _rxInStream
>> m_aDefaultText
;
176 if (nVersion
>= 0x0003)
178 m_bEmptyIsNull
= _rxInStream
->readBoolean();
180 sal_uInt16 nAnyMask
= _rxInStream
->readShort();
181 if ((nAnyMask
& DEFAULT_LONG
) == DEFAULT_LONG
)
183 sal_Int32 nValue
= _rxInStream
->readLong();
184 m_aDefault
<<= nValue
;
186 else if ((nAnyMask
& DEFAULT_DOUBLE
) == DEFAULT_DOUBLE
)
188 double fValue
= _rxInStream
->readDouble();
189 m_aDefault
<<= fValue
;
191 else if ((nAnyMask
& DEFAULT_TIME
) == DEFAULT_TIME
)
193 m_aDefault
<<= ::tools::Time(_rxInStream
->readHyper()).GetUNOTime();
195 else if ((nAnyMask
& DEFAULT_DATE
) == DEFAULT_DATE
)
197 m_aDefault
<<= ::Date(_rxInStream
->readLong()).GetUNODate();
200 if ((nAnyMask
& FILTERPROPOSAL
) == FILTERPROPOSAL
)
201 m_bFilterProposal
= true;
205 readHelpTextCompatibly(_rxInStream
);
207 if (bHandleCommonProps
)
208 readCommonEditProperties(_rxInStream
);
210 // After reading, display default values
211 if ( !getControlSource().isEmpty() )
212 // (not if we don't have a control source - the "State" property acts like it is persistent, then)
217 void OEditBaseModel::defaultCommonEditProperties()
219 OBoundControlModel::defaultCommonProperties();
220 // no own common properties at the moment
224 void OEditBaseModel::readCommonEditProperties(const Reference
<XObjectInputStream
>& _rxInStream
)
226 sal_Int32 nLen
= _rxInStream
->readLong();
228 Reference
<XMarkableStream
> xMark(_rxInStream
, UNO_QUERY
);
229 DBG_ASSERT(xMark
.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
230 sal_Int32 nMark
= xMark
->createMark();
232 // read properties common to all OBoundControlModels
233 OBoundControlModel::readCommonProperties(_rxInStream
);
235 // read properties common to all OEditBaseModels
237 // skip the remaining bytes
238 xMark
->jumpToMark(nMark
);
239 _rxInStream
->skipBytes(nLen
);
240 xMark
->deleteMark(nMark
);
244 void OEditBaseModel::writeCommonEditProperties(const Reference
<XObjectOutputStream
>& _rxOutStream
)
246 Reference
<XMarkableStream
> xMark(_rxOutStream
, UNO_QUERY
);
247 DBG_ASSERT(xMark
.is(), "OEditBaseModel::writeCommonProperties : can only work with markable streams !");
248 sal_Int32 nMark
= xMark
->createMark();
250 // a placeholder where we will write the overall length (later in this method)
252 _rxOutStream
->writeLong(nLen
);
254 // write properties common to all OBoundControlModels
255 OBoundControlModel::writeCommonProperties(_rxOutStream
);
257 // write properties common to all OEditBaseModels
259 // close the block - write the correct length at the beginning
260 nLen
= xMark
->offsetToMark(nMark
) - sizeof(nLen
);
261 xMark
->jumpToMark(nMark
);
262 _rxOutStream
->writeLong(nLen
);
263 xMark
->jumpToFurthest();
264 xMark
->deleteMark(nMark
);
268 void OEditBaseModel::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
272 case PROPERTY_ID_EMPTY_IS_NULL
:
273 rValue
<<= m_bEmptyIsNull
;
275 case PROPERTY_ID_FILTERPROPOSAL
:
276 rValue
<<= m_bFilterProposal
;
278 case PROPERTY_ID_DEFAULT_TEXT
:
279 rValue
<<= m_aDefaultText
;
281 case PROPERTY_ID_DEFAULT_VALUE
:
282 case PROPERTY_ID_DEFAULT_DATE
:
283 case PROPERTY_ID_DEFAULT_TIME
:
287 OBoundControlModel::getFastPropertyValue(rValue
, nHandle
);
291 sal_Bool
OEditBaseModel::convertFastPropertyValue( Any
& rConvertedValue
, Any
& rOldValue
,
292 sal_Int32 nHandle
, const Any
& rValue
)
294 bool bModified(false);
297 case PROPERTY_ID_EMPTY_IS_NULL
:
298 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bEmptyIsNull
);
300 case PROPERTY_ID_FILTERPROPOSAL
:
301 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bFilterProposal
);
303 case PROPERTY_ID_DEFAULT_TEXT
:
304 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefaultText
);
306 case PROPERTY_ID_DEFAULT_VALUE
:
307 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<double>::get());
309 case PROPERTY_ID_DEFAULT_DATE
:
310 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<util::Date
>::get());
312 case PROPERTY_ID_DEFAULT_TIME
:
313 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<util::Time
>::get());
316 bModified
= OBoundControlModel::convertFastPropertyValue(
325 void OEditBaseModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
, const Any
& rValue
)
329 case PROPERTY_ID_EMPTY_IS_NULL
:
330 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_BOOLEAN
, "invalid type" );
331 m_bEmptyIsNull
= getBOOL(rValue
);
333 case PROPERTY_ID_FILTERPROPOSAL
:
334 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_BOOLEAN
, "invalid type" );
335 m_bFilterProposal
= getBOOL(rValue
);
337 // Changing the default values causes a reset
338 case PROPERTY_ID_DEFAULT_TEXT
:
339 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_STRING
, "invalid type" );
340 rValue
>>= m_aDefaultText
;
343 case PROPERTY_ID_DEFAULT_VALUE
:
344 case PROPERTY_ID_DEFAULT_DATE
:
345 case PROPERTY_ID_DEFAULT_TIME
:
350 OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle
, rValue
);
356 Any
OEditBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle
) const
360 case PROPERTY_ID_DEFAULT_TEXT
:
361 return makeAny(OUString());
362 case PROPERTY_ID_FILTERPROPOSAL
:
363 return makeAny(false);
364 case PROPERTY_ID_DEFAULT_VALUE
:
365 case PROPERTY_ID_DEFAULT_DATE
:
366 case PROPERTY_ID_DEFAULT_TIME
:
369 return OBoundControlModel::getPropertyDefaultByHandle(nHandle
);
377 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */