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 : typedef ::std::vector< ::connectivity::ORowSetValue > ValueList;
98 :
99 : class OListBoxModel :public OBoundControlModel
100 : ,public OEntryListHelper
101 : ,public OErrorBroadcaster
102 : {
103 :
104 : CachedRowSet m_aListRowSet; // the row set to fill the list
105 : ::connectivity::ORowSetValue m_aSaveValue;
106 :
107 : // <properties>
108 : ::com::sun::star::form::ListSourceType m_eListSourceType; // type der list source
109 : ::com::sun::star::uno::Any m_aBoundColumn;
110 : ValueList m_aListSourceValues;
111 : ValueList m_aBoundValues; // do not write directly; use setBoundValues()
112 : mutable ValueList m_aConvertedBoundValues;
113 : mutable sal_Int32 m_nConvertedBoundValuesType;
114 : ::com::sun::star::uno::Sequence<sal_Int16> m_aDefaultSelectSeq; // DefaultSelected
115 : // </properties>
116 :
117 : sal_Int16 m_nNULLPos; // position of the NULL value in our list
118 : sal_Int32 m_nBoundColumnType;
119 :
120 : private:
121 : ::connectivity::ORowSetValue getFirstSelectedValue() const;
122 :
123 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes() SAL_OVERRIDE;
124 :
125 : public:
126 : DECLARE_DEFAULT_LEAF_XTOR( OListBoxModel );
127 :
128 : // XServiceInfo
129 14 : IMPLEMENTATION_NAME(OListBoxModel);
130 : virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
131 :
132 : // UNO Anbindung
133 206012 : DECLARE_UNO3_AGG_DEFAULTS(OListBoxModel, OBoundControlModel)
134 : 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;
135 :
136 : // OComponentHelper
137 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
138 :
139 : // OPropertySetHelper
140 : virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const SAL_OVERRIDE;
141 : virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
142 : throw (::com::sun::star::uno::Exception, std::exception) SAL_OVERRIDE;
143 : virtual sal_Bool SAL_CALL convertFastPropertyValue(
144 : ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue )
145 : throw (::com::sun::star::lang::IllegalArgumentException) SAL_OVERRIDE;
146 :
147 : protected:
148 : // XMultiPropertySet
149 : 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;
150 :
151 : // XPersistObject
152 : virtual OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
153 : virtual void SAL_CALL
154 : 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;
155 : virtual void SAL_CALL
156 : 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;
157 :
158 : // OControlModel's property handling
159 : virtual void describeFixedProperties(
160 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
161 : ) const SAL_OVERRIDE;
162 : virtual void describeAggregateProperties(
163 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps
164 : ) const SAL_OVERRIDE;
165 :
166 : // XEventListener
167 : virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
168 :
169 : // OPropertyChangeListener
170 : virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& _rEvt ) throw ( ::com::sun::star::uno::RuntimeException ) SAL_OVERRIDE;
171 :
172 : // prevent method hiding
173 : using OBoundControlModel::getFastPropertyValue;
174 : using OBoundControlModel::setPropertyValues;
175 :
176 : protected:
177 : // OBoundControlModel overridables
178 : virtual ::com::sun::star::uno::Any
179 : translateDbColumnToControlValue( ) SAL_OVERRIDE;
180 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type >
181 : getSupportedBindingTypes() SAL_OVERRIDE;
182 : virtual ::com::sun::star::uno::Any
183 : translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const SAL_OVERRIDE;
184 : virtual ::com::sun::star::uno::Any
185 : translateControlValueToExternalValue( ) const SAL_OVERRIDE;
186 : virtual ::com::sun::star::uno::Any
187 : translateControlValueToValidatableValue( ) const SAL_OVERRIDE;
188 : virtual bool commitControlValueToDbColumn( bool _bPostReset ) SAL_OVERRIDE;
189 :
190 : virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ) SAL_OVERRIDE;
191 : virtual void onDisconnectedDbColumn() SAL_OVERRIDE;
192 :
193 : virtual ::com::sun::star::uno::Any
194 : getDefaultForReset() const SAL_OVERRIDE;
195 : virtual void resetNoBroadcast() SAL_OVERRIDE;
196 :
197 : virtual ::com::sun::star::uno::Any
198 : getCurrentFormComponentValue() const SAL_OVERRIDE;
199 :
200 : // OEntryListHelper overridables
201 : virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ) SAL_OVERRIDE;
202 : virtual void connectedExternalListSource( ) SAL_OVERRIDE;
203 : virtual void disconnectedExternalListSource( ) SAL_OVERRIDE;
204 : virtual void refreshInternalEntryList() SAL_OVERRIDE;
205 :
206 : protected:
207 : virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
208 :
209 : void init();
210 : ::com::sun::star::uno::Any getCurrentSingleValue() const;
211 : ::com::sun::star::uno::Any getCurrentMultiValue() const;
212 : ::com::sun::star::uno::Sequence< sal_Int16 > translateBindingValuesToControlValue(
213 : const ::com::sun::star::uno::Sequence< const ::com::sun::star::uno::Any > &i_aValues)
214 : const;
215 : ::com::sun::star::uno::Sequence< sal_Int16 > translateDbValueToControlValue(
216 : const ::connectivity::ORowSetValue &aValue)
217 : const;
218 :
219 :
220 : private:
221 : void loadData( bool _bForce );
222 :
223 : /** refreshes the list boxes list data
224 : @precond we don't actually have an external list source
225 : */
226 : void impl_refreshDbEntryList( bool _bForce );
227 :
228 : void setBoundValues(const ValueList&);
229 : void clearBoundValues();
230 :
231 : ValueList impl_getValues() const;
232 :
233 : sal_Int32 getValueType() const;
234 :
235 : void convertBoundValues(sal_Int32 nType) const;
236 :
237 426 : bool impl_hasBoundComponent() const { return m_nBoundColumnType != ::com::sun::star::sdbc::DataType::SQLNULL; }
238 : };
239 :
240 :
241 : //= OListBoxControl
242 :
243 : typedef ::cppu::ImplHelper4 < ::com::sun::star::awt::XFocusListener
244 : , ::com::sun::star::awt::XItemListener
245 : , ::com::sun::star::awt::XListBox
246 : , ::com::sun::star::form::XChangeBroadcaster
247 : > OListBoxControl_BASE;
248 :
249 : class OListBoxControl :public OBoundControl
250 : ,public OListBoxControl_BASE
251 : ,public IEventProcessor
252 : {
253 : private:
254 : ::cppu::OInterfaceContainerHelper m_aChangeListeners;
255 : ::cppu::OInterfaceContainerHelper m_aItemListeners;
256 :
257 : ::com::sun::star::uno::Any m_aCurrentSelection;
258 : Timer m_aChangeTimer;
259 :
260 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox >
261 : m_xAggregateListBox;
262 :
263 : ::rtl::Reference< ::comphelper::AsyncEventNotifier >
264 : m_pItemBroadcaster;
265 :
266 : protected:
267 : // UNO Anbindung
268 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes() SAL_OVERRIDE;
269 :
270 : public:
271 : OListBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext>& _rxFactory);
272 : virtual ~OListBoxControl();
273 :
274 : // UNO Anbindung
275 66543 : DECLARE_UNO3_AGG_DEFAULTS(OListBoxControl, OBoundControl)
276 : 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;
277 :
278 : // XServiceInfo
279 0 : IMPLEMENTATION_NAME(OListBoxControl);
280 : virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
281 :
282 : // XChangeBroadcaster
283 : 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;
284 : 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;
285 :
286 : // XFocusListener
287 : virtual void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
288 : virtual void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
289 :
290 : // XItemListener
291 : virtual void SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
292 :
293 : // XEventListener
294 : virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
295 :
296 : // OComponentHelper
297 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
298 :
299 : // XListBox
300 : 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;
301 : 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;
302 : 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;
303 : 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;
304 : virtual void SAL_CALL addItem( const OUString& aItem, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
305 : 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;
306 : virtual void SAL_CALL removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
307 : virtual ::sal_Int16 SAL_CALL getItemCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
308 : virtual OUString SAL_CALL getItem( ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
309 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getItems( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
310 : virtual ::sal_Int16 SAL_CALL getSelectedItemPos( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
311 : virtual ::com::sun::star::uno::Sequence< ::sal_Int16 > SAL_CALL getSelectedItemsPos( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
312 : virtual OUString SAL_CALL getSelectedItem( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
313 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSelectedItems( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
314 : virtual void SAL_CALL selectItemPos( ::sal_Int16 nPos, sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
315 : 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;
316 : virtual void SAL_CALL selectItem( const OUString& aItem, sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
317 : virtual sal_Bool SAL_CALL isMutipleMode( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
318 : virtual void SAL_CALL setMultipleMode( sal_Bool bMulti ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
319 : virtual ::sal_Int16 SAL_CALL getDropDownLineCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
320 : virtual void SAL_CALL setDropDownLineCount( ::sal_Int16 nLines ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
321 : virtual void SAL_CALL makeVisible( ::sal_Int16 nEntry ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
322 :
323 : protected:
324 : // IEventProcessor
325 : virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ) SAL_OVERRIDE;
326 :
327 : private:
328 : DECL_LINK( OnTimeout, void* );
329 : };
330 :
331 :
332 : }
333 :
334 :
335 : #endif // INCLUDED_FORMS_SOURCE_COMPONENT_LISTBOX_HXX
336 :
337 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|