Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef INCLUDED_FORMS_SOURCE_COMPONENT_LISTBOX_HXX
21 : #define INCLUDED_FORMS_SOURCE_COMPONENT_LISTBOX_HXX
22 :
23 : #include "FormComponent.hxx"
24 : #include "cachedrowset.hxx"
25 : #include "errorbroadcaster.hxx"
26 : #include "entrylisthelper.hxx"
27 :
28 : #include <com/sun/star/util/XNumberFormatter.hpp>
29 : #include <com/sun/star/sdb/XSQLErrorBroadcaster.hpp>
30 : #include <com/sun/star/form/ListSourceType.hpp>
31 : #include <com/sun/star/awt/XItemListener.hpp>
32 : #include <com/sun/star/awt/XFocusListener.hpp>
33 : #include <com/sun/star/awt/XListBox.hpp>
34 : #include <com/sun/star/form/XChangeBroadcaster.hpp>
35 : #include <com/sun/star/sdbc/DataType.hpp>
36 :
37 : #include <comphelper/asyncnotification.hxx>
38 : #include <connectivity/FValue.hxx>
39 : #include <cppuhelper/interfacecontainer.hxx>
40 : #include <cppuhelper/implbase1.hxx>
41 : #include <vcl/timer.hxx>
42 :
43 : #include <vector>
44 :
45 : /** ListBox is a bit confusing / different from other form components,
46 : so here are a few notes:
47 :
48 : The general design philosophy is that a ListBox is a mechanism
49 : to translate back and forth between:
50 : 1) *display* values (strings that the user sees and chooses)
51 : 2) *binding* values, which is what the program (for a dialog),
52 : the database, ... cares about.
53 :
54 : A non-data aware ListBox exposes this mechanism through
55 : com.sun.star.awt.XItemList (get|set)ItemData.
56 :
57 : In a data-aware ListBox, this is naturally embodied by the
58 : StringItemList on the one hand, and the ValueList on the other
59 : hand (where, depending on ListSourceType, the ValueList is
60 : possibly automatically filled from the BoundColumn of the
61 : ListSource).
62 :
63 : This source file implements data-aware ListBox, and the rest
64 : of this comment applies to data-aware ListBox (only).
65 :
66 : In all public APIs of the *model* (OListBoxModel),
67 : the value of the control is the *binding* value.
68 : That is what the bound database field gets,
69 : that is what a validator validates,
70 : that is what an external value binding
71 : (com.sun.star.form.binding.XValueBinding)
72 : exchanges with the control.
73 :
74 : As an *implementation* choice, we keep the current value of the
75 : ListBox as a sequence of *indices* in the value list, and do the
76 : lookup on demand:
77 :
78 : - ListBox's content propery (or value property, sorry the
79 : terminology is not always consistent) is SelectedItems which is
80 : a sequence of *indices* in the value list.
81 :
82 : - That is used to synchronise with our peer (UnoControlListBoxModel).
83 :
84 : In particular, note that getCurrentValue() is a public API (and
85 : deals with bound values), but getControlValue and
86 : (do)setControlValue are *internal* implementation helpers that
87 : deal with *indices*.
88 :
89 : Note that the *view* (OListBoxControl) presents a different story
90 : than the model. E.g. the "SelectedItems" property is *display* *values*.
91 : */
92 :
93 :
94 : namespace frm
95 : {
96 :
97 :
98 : //= OListBoxModel
99 :
100 : typedef ::std::vector< ::connectivity::ORowSetValue > ValueList;
101 :
102 : class OListBoxModel :public OBoundControlModel
103 : ,public OEntryListHelper
104 : ,public OErrorBroadcaster
105 : {
106 :
107 : CachedRowSet m_aListRowSet; // the row set to fill the list
108 : ::connectivity::ORowSetValue m_aSaveValue;
109 :
110 : // <properties>
111 : ::com::sun::star::form::ListSourceType m_eListSourceType; // type der list source
112 : ::com::sun::star::uno::Any m_aBoundColumn;
113 : ValueList m_aListSourceValues;
114 : ValueList m_aBoundValues; // do not write directly; use setBoundValues()
115 : mutable ValueList m_aConvertedBoundValues;
116 : mutable sal_Int32 m_nConvertedBoundValuesType;
117 : ::com::sun::star::uno::Sequence<sal_Int16> m_aDefaultSelectSeq; // DefaultSelected
118 : // </properties>
119 :
120 : sal_Int16 m_nNULLPos; // position of the NULL value in our list
121 : sal_Int32 m_nBoundColumnType;
122 :
123 : private:
124 : ::connectivity::ORowSetValue getFirstSelectedValue() const;
125 :
126 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes() SAL_OVERRIDE;
127 :
128 : public:
129 : DECLARE_DEFAULT_LEAF_XTOR( OListBoxModel );
130 :
131 : // XServiceInfo
132 0 : IMPLEMENTATION_NAME(OListBoxModel);
133 : virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
134 :
135 : // UNO Anbindung
136 0 : DECLARE_UNO3_AGG_DEFAULTS(OListBoxModel, OBoundControlModel)
137 : virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
138 :
139 : // OComponentHelper
140 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
141 :
142 : // OPropertySetHelper
143 : virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const SAL_OVERRIDE;
144 : virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
145 : throw (::com::sun::star::uno::Exception, std::exception) SAL_OVERRIDE;
146 : virtual sal_Bool SAL_CALL convertFastPropertyValue(
147 : ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue )
148 : throw (::com::sun::star::lang::IllegalArgumentException) SAL_OVERRIDE;
149 :
150 : protected:
151 : // XMultiPropertySet
152 : virtual void SAL_CALL setPropertyValues(const ::com::sun::star::uno::Sequence< OUString >& PropertyNames, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& Values) throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
153 :
154 : // XPersistObject
155 : virtual OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
156 : virtual void SAL_CALL
157 : write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
158 : virtual void SAL_CALL
159 : read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
160 :
161 : // OControlModel's property handling
162 : virtual void describeFixedProperties(
163 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
164 : ) const SAL_OVERRIDE;
165 : virtual void describeAggregateProperties(
166 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps
167 : ) const SAL_OVERRIDE;
168 :
169 : // XEventListener
170 : virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
171 :
172 : // OPropertyChangeListener
173 : virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& _rEvt ) throw ( ::com::sun::star::uno::RuntimeException ) SAL_OVERRIDE;
174 :
175 : // prevent method hiding
176 : using OBoundControlModel::getFastPropertyValue;
177 : using OBoundControlModel::setPropertyValues;
178 :
179 : protected:
180 : // OBoundControlModel overridables
181 : virtual ::com::sun::star::uno::Any
182 : translateDbColumnToControlValue( ) SAL_OVERRIDE;
183 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type >
184 : getSupportedBindingTypes() SAL_OVERRIDE;
185 : virtual ::com::sun::star::uno::Any
186 : translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const SAL_OVERRIDE;
187 : virtual ::com::sun::star::uno::Any
188 : translateControlValueToExternalValue( ) const SAL_OVERRIDE;
189 : virtual ::com::sun::star::uno::Any
190 : translateControlValueToValidatableValue( ) const SAL_OVERRIDE;
191 : virtual sal_Bool commitControlValueToDbColumn( bool _bPostReset ) SAL_OVERRIDE;
192 :
193 : virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ) SAL_OVERRIDE;
194 : virtual void onDisconnectedDbColumn() SAL_OVERRIDE;
195 :
196 : virtual ::com::sun::star::uno::Any
197 : getDefaultForReset() const SAL_OVERRIDE;
198 : virtual void resetNoBroadcast() SAL_OVERRIDE;
199 :
200 : virtual ::com::sun::star::uno::Any
201 : getCurrentFormComponentValue() const SAL_OVERRIDE;
202 :
203 : // OEntryListHelper overridables
204 : virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ) SAL_OVERRIDE;
205 : virtual void connectedExternalListSource( ) SAL_OVERRIDE;
206 : virtual void disconnectedExternalListSource( ) SAL_OVERRIDE;
207 : virtual void refreshInternalEntryList() SAL_OVERRIDE;
208 :
209 : protected:
210 : DECLARE_XCLONEABLE();
211 :
212 : void init();
213 : ::com::sun::star::uno::Any getCurrentSingleValue() const;
214 : ::com::sun::star::uno::Any getCurrentMultiValue() const;
215 : ::com::sun::star::uno::Sequence< sal_Int16 > translateBindingValuesToControlValue(
216 : const ::com::sun::star::uno::Sequence< const ::com::sun::star::uno::Any > &i_aValues)
217 : const;
218 : ::com::sun::star::uno::Sequence< sal_Int16 > translateDbValueToControlValue(
219 : const ::connectivity::ORowSetValue &aValue)
220 : const;
221 :
222 :
223 : private:
224 : void loadData( bool _bForce );
225 :
226 : /** refreshes the list boxes list data
227 : @precond we don't actually have an external list source
228 : */
229 : void impl_refreshDbEntryList( bool _bForce );
230 :
231 : void setBoundValues(const ValueList&);
232 : void clearBoundValues();
233 :
234 : ValueList impl_getValues() const;
235 :
236 : sal_Int32 getValueType() const;
237 :
238 : void convertBoundValues(sal_Int32 nType) const;
239 :
240 0 : bool impl_hasBoundComponent() const { return m_nBoundColumnType != ::com::sun::star::sdbc::DataType::SQLNULL; }
241 : };
242 :
243 :
244 : //= OListBoxControl
245 :
246 : typedef ::cppu::ImplHelper4 < ::com::sun::star::awt::XFocusListener
247 : , ::com::sun::star::awt::XItemListener
248 : , ::com::sun::star::awt::XListBox
249 : , ::com::sun::star::form::XChangeBroadcaster
250 : > OListBoxControl_BASE;
251 :
252 : class OListBoxControl :public OBoundControl
253 : ,public OListBoxControl_BASE
254 : ,public IEventProcessor
255 : {
256 : private:
257 : ::cppu::OInterfaceContainerHelper m_aChangeListeners;
258 : ::cppu::OInterfaceContainerHelper m_aItemListeners;
259 :
260 : ::com::sun::star::uno::Any m_aCurrentSelection;
261 : Timer m_aChangeTimer;
262 :
263 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox >
264 : m_xAggregateListBox;
265 :
266 : ::rtl::Reference< ::comphelper::AsyncEventNotifier >
267 : m_pItemBroadcaster;
268 :
269 : protected:
270 : // UNO Anbindung
271 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes() SAL_OVERRIDE;
272 :
273 : public:
274 : OListBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext>& _rxFactory);
275 : virtual ~OListBoxControl();
276 :
277 : // UNO Anbindung
278 0 : DECLARE_UNO3_AGG_DEFAULTS(OListBoxControl, OBoundControl)
279 : virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
280 :
281 : // XServiceInfo
282 0 : IMPLEMENTATION_NAME(OListBoxControl);
283 : virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
284 :
285 : // XChangeBroadcaster
286 : virtual void SAL_CALL addChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
287 : virtual void SAL_CALL removeChangeListener(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XChangeListener>& _rxListener) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
288 :
289 : // XFocusListener
290 : virtual void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
291 : virtual void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
292 :
293 : // XItemListener
294 : virtual void SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
295 :
296 : // XEventListener
297 : virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
298 :
299 : // OComponentHelper
300 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
301 :
302 : // XListBox
303 : virtual void SAL_CALL addItemListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XItemListener >& l ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
304 : virtual void SAL_CALL removeItemListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XItemListener >& l ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
305 : virtual void SAL_CALL addActionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener >& l ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
306 : virtual void SAL_CALL removeActionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XActionListener >& l ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
307 : virtual void SAL_CALL addItem( const OUString& aItem, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
308 : virtual void SAL_CALL addItems( const ::com::sun::star::uno::Sequence< OUString >& aItems, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
309 : virtual void SAL_CALL removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
310 : virtual ::sal_Int16 SAL_CALL getItemCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
311 : virtual OUString SAL_CALL getItem( ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
312 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getItems( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
313 : virtual ::sal_Int16 SAL_CALL getSelectedItemPos( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
314 : virtual ::com::sun::star::uno::Sequence< ::sal_Int16 > SAL_CALL getSelectedItemsPos( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
315 : virtual OUString SAL_CALL getSelectedItem( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
316 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSelectedItems( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
317 : virtual void SAL_CALL selectItemPos( ::sal_Int16 nPos, sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
318 : virtual void SAL_CALL selectItemsPos( const ::com::sun::star::uno::Sequence< ::sal_Int16 >& aPositions, sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
319 : virtual void SAL_CALL selectItem( const OUString& aItem, sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
320 : virtual sal_Bool SAL_CALL isMutipleMode( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
321 : virtual void SAL_CALL setMultipleMode( sal_Bool bMulti ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
322 : virtual ::sal_Int16 SAL_CALL getDropDownLineCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
323 : virtual void SAL_CALL setDropDownLineCount( ::sal_Int16 nLines ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
324 : virtual void SAL_CALL makeVisible( ::sal_Int16 nEntry ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
325 :
326 : protected:
327 : // IEventProcessor
328 : virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ) SAL_OVERRIDE;
329 :
330 : private:
331 : DECL_LINK( OnTimeout, void* );
332 : };
333 :
334 :
335 : }
336 :
337 :
338 : #endif // INCLUDED_FORMS_SOURCE_COMPONENT_LISTBOX_HXX
339 :
340 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|