1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "vbalistbox.hxx"
25 #include "vbanewfont.hxx"
26 #include <comphelper/anytostring.hxx>
27 #include <com/sun/star/script/ArrayWrapper.hpp>
28 #include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
29 
30 using namespace com::sun::star;
31 using namespace ooo::vba;
32 
33 const static rtl::OUString TEXT( RTL_CONSTASCII_USTRINGPARAM("Text") );
34 const static rtl::OUString SELECTEDITEMS( RTL_CONSTASCII_USTRINGPARAM("SelectedItems") );
35 const static rtl::OUString ITEMS( RTL_CONSTASCII_USTRINGPARAM("StringItemList") );
36 
37 
ScVbaListBox(const uno::Reference<XHelperInterface> & xParent,const uno::Reference<uno::XComponentContext> & xContext,const uno::Reference<css::uno::XInterface> & xControl,const uno::Reference<frame::XModel> & xModel,AbstractGeometryAttributes * pGeomHelper)38 ScVbaListBox::ScVbaListBox( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< css::uno::XInterface >& xControl, const uno::Reference< frame::XModel >& xModel, AbstractGeometryAttributes* pGeomHelper ) : ListBoxImpl_BASE( xParent, xContext, xControl, xModel, pGeomHelper )
39 {
40     mpListHelper.reset( new ListControlHelper( m_xProps ) );
41 }
42 
43 // Attributes
44 void SAL_CALL
setListIndex(const uno::Any & _value)45 ScVbaListBox::setListIndex( const uno::Any& _value ) throw (uno::RuntimeException)
46 {
47     sal_Int32 nIndex = 0;
48     _value >>= nIndex;
49     uno::Reference< XPropValue > xPropVal( Selected( nIndex ), uno::UNO_QUERY_THROW );
50     xPropVal->setValue( uno::makeAny( sal_True ) );
51 }
52 
53 uno::Any SAL_CALL
getListIndex()54 ScVbaListBox::getListIndex() throw (uno::RuntimeException)
55 {
56     uno::Sequence< sal_Int16 > sSelection;
57     m_xProps->getPropertyValue( SELECTEDITEMS ) >>= sSelection;
58     if ( sSelection.getLength() == 0 )
59         return uno::Any( sal_Int32( -1 ) );
60     return uno::Any( sSelection[ 0 ] );
61 }
62 
63 uno::Any SAL_CALL
getValue()64 ScVbaListBox::getValue() throw (uno::RuntimeException)
65 {
66     uno::Sequence< sal_Int16 > sSelection;
67     uno::Sequence< rtl::OUString > sItems;
68     m_xProps->getPropertyValue( SELECTEDITEMS ) >>= sSelection;
69     m_xProps->getPropertyValue( ITEMS ) >>= sItems;
70     if( getMultiSelect() )
71         throw uno::RuntimeException( rtl::OUString::createFromAscii(
72                     "Attribute use invalid." ), uno::Reference< uno::XInterface >() );
73     uno::Any aRet;
74     if ( sSelection.getLength() )
75         aRet = uno::makeAny( sItems[ sSelection[ 0 ] ] );
76     return aRet;
77 }
78 
79 void SAL_CALL
setValue(const uno::Any & _value)80 ScVbaListBox::setValue( const uno::Any& _value ) throw (uno::RuntimeException)
81 {
82     if( getMultiSelect() )
83     {
84         throw uno::RuntimeException( rtl::OUString::createFromAscii(
85                     "Attribute use invalid." ), uno::Reference< uno::XInterface >() );
86     }
87     rtl::OUString sValue = getAnyAsString( _value );
88     uno::Sequence< rtl::OUString > sList;
89     m_xProps->getPropertyValue( ITEMS ) >>= sList;
90     uno::Sequence< sal_Int16 > nList;
91     sal_Int16 nLength = static_cast<sal_Int16>( sList.getLength() );
92     sal_Int16 nValue = -1;
93     sal_Int16 i = 0;
94     for( i = 0; i < nLength; i++ )
95     {
96         if( sList[i].equals( sValue ) )
97         {
98             nValue = i;
99             break;
100         }
101     }
102     if( nValue == -1 )
103         throw uno::RuntimeException( rtl::OUString::createFromAscii(
104                     "Attribute use invalid." ), uno::Reference< uno::XInterface >() );
105 
106     uno::Sequence< sal_Int16 > nSelectedIndices(1);
107     nSelectedIndices[ 0 ] = nValue;
108     m_xProps->setPropertyValue( SELECTEDITEMS, uno::makeAny( nSelectedIndices ) );
109     m_xProps->setPropertyValue( TEXT, uno::makeAny( sValue ) );
110 }
111 
112 ::rtl::OUString SAL_CALL
getText()113 ScVbaListBox::getText() throw (uno::RuntimeException)
114 {
115 	rtl::OUString result;
116 	getValue() >>= result;
117 	return result;
118 }
119 
120 void SAL_CALL
setText(const::rtl::OUString & _text)121 ScVbaListBox::setText( const ::rtl::OUString& _text ) throw (uno::RuntimeException)
122 {
123 	setValue( uno::makeAny( _text ) ); // seems the same
124 }
125 
126 sal_Bool SAL_CALL
getMultiSelect()127 ScVbaListBox::getMultiSelect() throw (css::uno::RuntimeException)
128 {
129     sal_Bool bMultiSelect = sal_False;
130     m_xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MultiSelection" ) ) ) >>= bMultiSelect;
131     return bMultiSelect;
132 }
133 
134 void SAL_CALL
setMultiSelect(sal_Bool _multiselect)135 ScVbaListBox::setMultiSelect( sal_Bool _multiselect ) throw (css::uno::RuntimeException)
136 {
137     m_xProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MultiSelection" ) ), uno::makeAny( _multiselect ) );
138 }
139 
140 css::uno::Any SAL_CALL
Selected(sal_Int32 index)141 ScVbaListBox::Selected( sal_Int32 index ) throw (css::uno::RuntimeException)
142 {
143     uno::Sequence< rtl::OUString > sList;
144     m_xProps->getPropertyValue( ITEMS ) >>= sList;
145     sal_Int16 nLength = static_cast< sal_Int16 >( sList.getLength() );
146     // no choice but to do a horror cast as internally
147     // the indices are but sal_Int16
148     sal_Int16 nIndex = static_cast< sal_Int16 >( index );
149     if( nIndex < 0 || nIndex >= nLength )
150         throw uno::RuntimeException( rtl::OUString::createFromAscii(
151                     "Error Number." ), uno::Reference< uno::XInterface >() );
152     m_nIndex = nIndex;
153     return uno::makeAny( uno::Reference< XPropValue > ( new ScVbaPropValue( this ) ) );
154 }
155 
156 // Methods
157 void SAL_CALL
AddItem(const uno::Any & pvargItem,const uno::Any & pvargIndex)158 ScVbaListBox::AddItem( const uno::Any& pvargItem, const uno::Any& pvargIndex ) throw (uno::RuntimeException)
159 {
160 	mpListHelper->AddItem( pvargItem, pvargIndex );
161 		}
162 
163 void SAL_CALL
removeItem(const uno::Any & index)164 ScVbaListBox::removeItem( const uno::Any& index ) throw (uno::RuntimeException)
165 {
166 	mpListHelper->removeItem( index );
167 }
168 
169 void SAL_CALL
Clear()170 ScVbaListBox::Clear(  ) throw (uno::RuntimeException)
171 {
172 	mpListHelper->Clear();
173 }
174 
175 // this is called when something like the following vba code is used
176 // to set the selected state of particular entries in the Listbox
177 // ListBox1.Selected( 3 ) = false
178 //PropListener
179 void
setValueEvent(const uno::Any & value)180 ScVbaListBox::setValueEvent( const uno::Any& value )
181 {
182     sal_Bool bValue = sal_False;
183     if( !(value >>= bValue) )
184         throw uno::RuntimeException( rtl::OUString::createFromAscii(
185                     "Invalid type\n. need boolean." ), uno::Reference< uno::XInterface >() );
186     uno::Sequence< sal_Int16 > nList;
187     m_xProps->getPropertyValue( SELECTEDITEMS ) >>= nList;
188     sal_Int16 nLength = static_cast<sal_Int16>( nList.getLength() );
189     sal_Int16 nIndex = m_nIndex;
190     for( sal_Int16 i = 0; i < nLength; i++ )
191     {
192         if( nList[i] == nIndex )
193         {
194             if( bValue )
195                 return;
196             else
197             {
198                 for( ; i < nLength - 1; i++ )
199                 {
200                     nList[i] = nList[i + 1];
201                 }
202                 nList.realloc( nLength - 1 );
203                 //m_xProps->setPropertyValue( sSourceName, uno::makeAny( nList ) );
204 		m_xProps->setPropertyValue( SELECTEDITEMS, uno::makeAny( nList ) );
205                 return;
206             }
207         }
208     }
209     if( bValue )
210     {
211         if( getMultiSelect() )
212         {
213             nList.realloc( nLength + 1 );
214             nList[nLength] = nIndex;
215         }
216         else
217         {
218             nList.realloc( 1 );
219             nList[0] = nIndex;
220         }
221         //m_xProps->setPropertyValue( sSourceName, uno::makeAny( nList ) );
222         m_xProps->setPropertyValue( SELECTEDITEMS, uno::makeAny( nList ) );
223     }
224 }
225 
226 // this is called when something like the following vba code is used
227 // to determine the selected state of particular entries in the Listbox
228 // msgbox ListBox1.Selected( 3 )
229 
230 css::uno::Any
getValueEvent()231 ScVbaListBox::getValueEvent()
232 {
233     uno::Sequence< sal_Int16 > nList;
234     m_xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SelectedItems" ) ) ) >>= nList;
235     sal_Int32 nLength = nList.getLength();
236     sal_Int32 nIndex = m_nIndex;
237 
238     for( sal_Int32 i = 0; i < nLength; i++ )
239     {
240         if( nList[i] == nIndex )
241             return uno::makeAny( sal_True );
242     }
243 
244     return uno::makeAny( sal_False );
245 }
246 
247 void SAL_CALL
setRowSource(const rtl::OUString & _rowsource)248 ScVbaListBox::setRowSource( const rtl::OUString& _rowsource ) throw (uno::RuntimeException)
249 {
250 	ScVbaControl::setRowSource( _rowsource );
251 	mpListHelper->setRowSource( _rowsource );
252 }
253 
254 sal_Int32 SAL_CALL
getListCount()255 ScVbaListBox::getListCount() throw (uno::RuntimeException)
256 {
257 	return mpListHelper->getListCount();
258 }
259 
260 uno::Any SAL_CALL
List(const::uno::Any & pvargIndex,const uno::Any & pvarColumn)261 ScVbaListBox::List( const ::uno::Any& pvargIndex, const uno::Any& pvarColumn ) throw (uno::RuntimeException)
262 {
263 	return mpListHelper->List( pvargIndex, pvarColumn );
264 }
265 
getFont()266 uno::Reference< msforms::XNewFont > SAL_CALL ScVbaListBox::getFont() throw (uno::RuntimeException)
267 {
268     return new VbaNewFont( this, mxContext, m_xProps );
269 }
270 
271 rtl::OUString&
getServiceImplName()272 ScVbaListBox::getServiceImplName()
273 {
274 	static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaListBox") );
275 	return sImplName;
276 }
277 
278 uno::Sequence< rtl::OUString >
getServiceNames()279 ScVbaListBox::getServiceNames()
280 {
281 	static uno::Sequence< rtl::OUString > aServiceNames;
282 	if ( aServiceNames.getLength() == 0 )
283 	{
284 		aServiceNames.realloc( 1 );
285 		aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.msforms.ScVbaListBox" ) );
286 	}
287 	return aServiceNames;
288 }
289