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