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 : #include <vcl/idle.hxx>
43 :
44 : #include <vector>
45 :
46 : /** ListBox is a bit confusing / different from other form components,
47 : so here are a few notes:
48 :
49 : The general design philosophy is that a ListBox is a mechanism
50 : to translate back and forth between:
51 : 1) *display* values (strings that the user sees and chooses)
52 : 2) *binding* values, which is what the program (for a dialog),
53 : the database, ... cares about.
54 :
55 : A non-data aware ListBox exposes this mechanism through
56 : com.sun.star.awt.XItemList (get|set)ItemData.
57 :
58 : In a data-aware ListBox, this is naturally embodied by the
59 : StringItemList on the one hand, and the ValueList on the other
60 : hand (where, depending on ListSourceType, the ValueList is
61 : possibly automatically filled from the BoundColumn of the
62 : ListSource).
63 :
64 : This source file implements data-aware ListBox, and the rest
65 : of this comment applies to data-aware ListBox (only).
66 :
67 : In all public APIs of the *model* (OListBoxModel),
68 : the value of the control is the *binding* value.
69 : That is what the bound database field gets,
70 : that is what a validator validates,
71 : that is what an external value binding
72 : (com.sun.star.form.binding.XValueBinding)
73 : exchanges with the control.
74 :
75 : As an *implementation* choice, we keep the current value of the
76 : ListBox as a sequence of *indices* in the value list, and do the
77 : lookup on demand:
78 :
79 : - ListBox's content propery (or value property, sorry the
80 : terminology is not always consistent) is SelectedItems which is
81 : a sequence of *indices* in the value list.
82 :
83 : - That is used to synchronise with our peer (UnoControlListBoxModel).
84 :
85 : In particular, note that getCurrentValue() is a public API (and
86 : deals with bound values), but getControlValue and
87 : (do)setControlValue are *internal* implementation helpers that
88 : deal with *indices*.
89 :
90 : Note that the *view* (OListBoxControl) presents a different story
91 : than the model. E.g. the "SelectedItems" property is *display* *values*.
92 : */
93 :
94 :
95 : namespace frm
96 : {
97 :
98 : typedef ::std::vector< ::connectivity::ORowSetValue > ValueList;
99 :
100 : class OListBoxModel :public OBoundControlModel
101 : ,public OEntryListHelper
102 : ,public OErrorBroadcaster
103 : {
104 :
105 : CachedRowSet m_aListRowSet; // the row set to fill the list
106 : ::connectivity::ORowSetValue m_aSaveValue;
107 :
108 : // <properties>
109 : ::com::sun::star::form::ListSourceType m_eListSourceType; // type der list source
110 : ::com::sun::star::uno::Any m_aBoundColumn;
111 : ValueList m_aListSourceValues;
112 : ValueList m_aBoundValues; // do not write directly; use setBoundValues()
113 : mutable ValueList m_aConvertedBoundValues;
114 : mutable sal_Int32 m_nConvertedBoundValuesType;
115 : ::com::sun::star::uno::Sequence<sal_Int16> m_aDefaultSelectSeq; // DefaultSelected
116 : // </properties>
117 :
118 : mutable sal_Int16 m_nNULLPos; // position of the NULL value in our list
119 : sal_Int32 m_nBoundColumnType;
120 :
121 : private:
122 : ::connectivity::ORowSetValue getFirstSelectedValue() const;
123 :
124 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes() SAL_OVERRIDE;
125 :
126 : public:
127 : DECLARE_DEFAULT_LEAF_XTOR( OListBoxModel );
128 :
129 : // XServiceInfo
130 8 : OUString SAL_CALL getImplementationName()
131 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
132 8 : { return OUString("com.sun.star.form.OListBoxModel"); }
133 :
134 : virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
135 :
136 : // UNO Anbindung
137 123095 : DECLARE_UNO3_AGG_DEFAULTS(OListBoxModel, OBoundControlModel)
138 : 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;
139 :
140 : // OComponentHelper
141 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
142 :
143 : // OPropertySetHelper
144 : virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const SAL_OVERRIDE;
145 : virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
146 : throw (::com::sun::star::uno::Exception, std::exception) SAL_OVERRIDE;
147 : virtual sal_Bool SAL_CALL convertFastPropertyValue(
148 : ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue )
149 : throw (::com::sun::star::lang::IllegalArgumentException) SAL_OVERRIDE;
150 :
151 : protected:
152 : static const ::connectivity::ORowSetValue s_aEmptyValue;
153 : static const ::connectivity::ORowSetValue s_aEmptyStringValue;
154 :
155 : // XMultiPropertySet
156 : 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;
157 :
158 : // XPersistObject
159 : virtual OUString SAL_CALL getServiceName() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
160 : virtual void SAL_CALL
161 : 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;
162 : virtual void SAL_CALL
163 : 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;
164 :
165 : // OControlModel's property handling
166 : virtual void describeFixedProperties(
167 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
168 : ) const SAL_OVERRIDE;
169 : virtual void describeAggregateProperties(
170 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps
171 : ) const SAL_OVERRIDE;
172 :
173 : // XEventListener
174 : virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
175 :
176 : // OPropertyChangeListener
177 : virtual void _propertyChanged( const ::com::sun::star::beans::PropertyChangeEvent& _rEvt ) throw ( ::com::sun::star::uno::RuntimeException ) SAL_OVERRIDE;
178 :
179 : // prevent method hiding
180 : using OBoundControlModel::getFastPropertyValue;
181 : using OBoundControlModel::setPropertyValues;
182 :
183 : protected:
184 : // OBoundControlModel overridables
185 : virtual ::com::sun::star::uno::Any
186 : translateDbColumnToControlValue( ) SAL_OVERRIDE;
187 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type >
188 : getSupportedBindingTypes() SAL_OVERRIDE;
189 : virtual ::com::sun::star::uno::Any
190 : translateExternalValueToControlValue( const ::com::sun::star::uno::Any& _rExternalValue ) const SAL_OVERRIDE;
191 : virtual ::com::sun::star::uno::Any
192 : translateControlValueToExternalValue( ) const SAL_OVERRIDE;
193 : virtual ::com::sun::star::uno::Any
194 : translateControlValueToValidatableValue( ) const SAL_OVERRIDE;
195 : virtual bool commitControlValueToDbColumn( bool _bPostReset ) SAL_OVERRIDE;
196 :
197 : virtual void onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm ) SAL_OVERRIDE;
198 : virtual void onDisconnectedDbColumn() SAL_OVERRIDE;
199 :
200 : virtual ::com::sun::star::uno::Any
201 : getDefaultForReset() const SAL_OVERRIDE;
202 : virtual void resetNoBroadcast() SAL_OVERRIDE;
203 :
204 : virtual ::com::sun::star::uno::Any
205 : getCurrentFormComponentValue() const SAL_OVERRIDE;
206 :
207 : // OEntryListHelper overridables
208 : virtual void stringItemListChanged( ControlModelLock& _rInstanceLock ) SAL_OVERRIDE;
209 : virtual void connectedExternalListSource( ) SAL_OVERRIDE;
210 : virtual void disconnectedExternalListSource( ) SAL_OVERRIDE;
211 : virtual void refreshInternalEntryList() SAL_OVERRIDE;
212 :
213 : protected:
214 : virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
215 :
216 : void init();
217 : ::com::sun::star::uno::Any getCurrentSingleValue() const;
218 : ::com::sun::star::uno::Any getCurrentMultiValue() const;
219 : ::com::sun::star::uno::Sequence< sal_Int16 > translateBindingValuesToControlValue(
220 : const ::com::sun::star::uno::Sequence< const ::com::sun::star::uno::Any > &i_aValues)
221 : const;
222 : ::com::sun::star::uno::Sequence< sal_Int16 > translateDbValueToControlValue(
223 : const ::connectivity::ORowSetValue &aValue)
224 : const;
225 :
226 :
227 : private:
228 : void loadData( bool _bForce );
229 :
230 : /** refreshes the list boxes list data
231 : @precond we don't actually have an external list source
232 : */
233 : void impl_refreshDbEntryList( bool _bForce );
234 :
235 : void setBoundValues(const ValueList&);
236 : void clearBoundValues();
237 :
238 : ValueList impl_getValues() const;
239 :
240 : sal_Int32 getValueType() const;
241 :
242 : void convertBoundValues(sal_Int32 nType) const;
243 :
244 213 : bool impl_hasBoundComponent() const { return m_nBoundColumnType != ::com::sun::star::sdbc::DataType::SQLNULL; }
245 : };
246 :
247 :
248 : //= OListBoxControl
249 :
250 : typedef ::cppu::ImplHelper4 < ::com::sun::star::awt::XFocusListener
251 : , ::com::sun::star::awt::XItemListener
252 : , ::com::sun::star::awt::XListBox
253 : , ::com::sun::star::form::XChangeBroadcaster
254 : > OListBoxControl_BASE;
255 :
256 : class OListBoxControl :public OBoundControl
257 : ,public OListBoxControl_BASE
258 : ,public IEventProcessor
259 : {
260 : private:
261 : ::cppu::OInterfaceContainerHelper m_aChangeListeners;
262 : ::cppu::OInterfaceContainerHelper m_aItemListeners;
263 :
264 : ::com::sun::star::uno::Any m_aCurrentSelection;
265 : Idle m_aChangeIdle;
266 :
267 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox >
268 : m_xAggregateListBox;
269 :
270 : ::rtl::Reference< ::comphelper::AsyncEventNotifier >
271 : m_pItemBroadcaster;
272 :
273 : protected:
274 : // UNO Anbindung
275 : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes() SAL_OVERRIDE;
276 :
277 : public:
278 : OListBoxControl(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext>& _rxFactory);
279 : virtual ~OListBoxControl();
280 :
281 : // UNO Anbindung
282 65299 : DECLARE_UNO3_AGG_DEFAULTS(OListBoxControl, OBoundControl)
283 : 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;
284 :
285 : // XServiceInfo
286 1 : OUString SAL_CALL getImplementationName()
287 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
288 1 : { return OUString("com.sun.star.form.OListBoxControl"); }
289 :
290 : virtual StringSequence SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
291 :
292 : // XChangeBroadcaster
293 : 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;
294 : 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;
295 :
296 : // XFocusListener
297 : virtual void SAL_CALL focusGained(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
298 : virtual void SAL_CALL focusLost(const ::com::sun::star::awt::FocusEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
299 :
300 : // XItemListener
301 : virtual void SAL_CALL itemStateChanged(const ::com::sun::star::awt::ItemEvent& _rEvent) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
302 :
303 : // XEventListener
304 : virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
305 :
306 : // OComponentHelper
307 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
308 :
309 : // XListBox
310 : 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;
311 : 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;
312 : 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;
313 : 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;
314 : virtual void SAL_CALL addItem( const OUString& aItem, ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
315 : 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;
316 : virtual void SAL_CALL removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
317 : virtual ::sal_Int16 SAL_CALL getItemCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
318 : virtual OUString SAL_CALL getItem( ::sal_Int16 nPos ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
319 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getItems( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
320 : virtual ::sal_Int16 SAL_CALL getSelectedItemPos( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
321 : virtual ::com::sun::star::uno::Sequence< ::sal_Int16 > SAL_CALL getSelectedItemsPos( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
322 : virtual OUString SAL_CALL getSelectedItem( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
323 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSelectedItems( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
324 : virtual void SAL_CALL selectItemPos( ::sal_Int16 nPos, sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
325 : 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;
326 : virtual void SAL_CALL selectItem( const OUString& aItem, sal_Bool bSelect ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
327 : virtual sal_Bool SAL_CALL isMutipleMode( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
328 : virtual void SAL_CALL setMultipleMode( sal_Bool bMulti ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
329 : virtual ::sal_Int16 SAL_CALL getDropDownLineCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
330 : virtual void SAL_CALL setDropDownLineCount( ::sal_Int16 nLines ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
331 : virtual void SAL_CALL makeVisible( ::sal_Int16 nEntry ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
332 :
333 : protected:
334 : // IEventProcessor
335 : virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ) SAL_OVERRIDE;
336 :
337 : private:
338 : DECL_LINK_TYPED( OnTimeout, Idle*, void );
339 : };
340 :
341 :
342 : }
343 :
344 :
345 : #endif // INCLUDED_FORMS_SOURCE_COMPONENT_LISTBOX_HXX
346 :
347 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|