Branch data 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 : : #include <vbahelper/helperdecl.hxx>
20 : : #include "vbauserform.hxx"
21 : : #include <com/sun/star/awt/XControl.hpp>
22 : : #include <com/sun/star/awt/XControlContainer.hpp>
23 : : #include <com/sun/star/awt/XWindow2.hpp>
24 : : #include <com/sun/star/awt/PosSize.hpp>
25 : : #include <com/sun/star/beans/PropertyConcept.hpp>
26 : : #include <com/sun/star/container/XNameContainer.hpp>
27 : : #include <com/sun/star/util/MeasureUnit.hpp>
28 : : #include <basic/sbx.hxx>
29 : : #include <basic/sbstar.hxx>
30 : : #include <basic/sbmeth.hxx>
31 : : #include "vbacontrols.hxx"
32 : :
33 : : using namespace ::ooo::vba;
34 : : using namespace ::com::sun::star;
35 : :
36 : : // some little notes
37 : : // XDialog implementation has the following interesting bits
38 : : // a Controls property ( which is an array of the container controls )
39 : : // each item in the controls array is a XControl, where the model is
40 : : // basically a property bag
41 : : // additionally the XDialog instance has itself a model
42 : : // this model has a ControlModels ( array of models ) property
43 : : // the models in ControlModels can be accessed by name
44 : : // also the XDialog is a XControl ( to access the model above
45 : :
46 : 0 : ScVbaUserForm::ScVbaUserForm( uno::Sequence< uno::Any > const& aArgs, uno::Reference< uno::XComponentContext >const& xContext ) throw ( lang::IllegalArgumentException ) : ScVbaUserForm_BASE( getXSomethingFromArgs< XHelperInterface >( aArgs, 0 ), xContext, getXSomethingFromArgs< uno::XInterface >( aArgs, 1 ), getXSomethingFromArgs< frame::XModel >( aArgs, 2 ), static_cast< ooo::vba::AbstractGeometryAttributes* >(0) ), mbDispose( true )
47 : : {
48 : 0 : m_xDialog.set( m_xControl, uno::UNO_QUERY_THROW );
49 : 0 : uno::Reference< awt::XControl > xControl( m_xDialog, uno::UNO_QUERY_THROW );
50 : 0 : m_xProps.set( xControl->getModel(), uno::UNO_QUERY_THROW );
51 : 0 : setGeometryHelper( new UserFormGeometryHelper( xContext, xControl, 0.0, 0.0 ) );
52 : 0 : if ( aArgs.getLength() >= 4 )
53 : 0 : aArgs[ 3 ] >>= m_sLibName;
54 : 0 : }
55 : :
56 : 0 : ScVbaUserForm::~ScVbaUserForm()
57 : : {
58 : 0 : }
59 : :
60 : : void SAL_CALL
61 : 0 : ScVbaUserForm::Show( ) throw (uno::RuntimeException)
62 : : {
63 : : OSL_TRACE("ScVbaUserForm::Show( )");
64 : 0 : short aRet = 0;
65 : 0 : mbDispose = true;
66 : :
67 : 0 : if ( m_xDialog.is() )
68 : : {
69 : : // try to center dialog on model window
70 : 0 : if( m_xModel.is() ) try
71 : : {
72 : 0 : uno::Reference< frame::XController > xController( m_xModel->getCurrentController(), uno::UNO_SET_THROW );
73 : 0 : uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_SET_THROW );
74 : 0 : uno::Reference< awt::XWindow > xWindow( xFrame->getContainerWindow(), uno::UNO_SET_THROW );
75 : 0 : awt::Rectangle aPosSize = xWindow->getPosSize(); // already in pixel
76 : :
77 : 0 : uno::Reference< awt::XControl > xControl( m_xDialog, uno::UNO_QUERY_THROW );
78 : 0 : uno::Reference< awt::XWindow > xControlWindow( xControl->getPeer(), uno::UNO_QUERY_THROW );
79 : 0 : xControlWindow->setPosSize(static_cast<sal_Int32>((aPosSize.Width - getWidth()) / 2.0), static_cast<sal_Int32>((aPosSize.Height - getHeight()) / 2.0), 0, 0, awt::PosSize::POS );
80 : : }
81 : 0 : catch( uno::Exception& )
82 : : {
83 : : }
84 : :
85 : 0 : aRet = m_xDialog->execute();
86 : : }
87 : : OSL_TRACE("ScVbaUserForm::Show() execute returned %d", aRet);
88 : 0 : if ( mbDispose )
89 : : {
90 : : try
91 : : {
92 : 0 : uno::Reference< lang::XComponent > xComp( m_xDialog, uno::UNO_QUERY_THROW );
93 : 0 : m_xDialog = NULL;
94 : 0 : xComp->dispose();
95 : 0 : mbDispose = false;
96 : : }
97 : 0 : catch( uno::Exception& )
98 : : {
99 : : }
100 : : }
101 : 0 : }
102 : :
103 : : rtl::OUString SAL_CALL
104 : 0 : ScVbaUserForm::getCaption() throw (uno::RuntimeException)
105 : : {
106 : 0 : rtl::OUString sCaption;
107 : 0 : m_xProps->getPropertyValue( "Title" ) >>= sCaption;
108 : 0 : return sCaption;
109 : : }
110 : : void
111 : 0 : ScVbaUserForm::setCaption( const ::rtl::OUString& _caption ) throw (uno::RuntimeException)
112 : : {
113 : 0 : m_xProps->setPropertyValue( "Title", uno::makeAny( _caption ) );
114 : 0 : }
115 : :
116 : 0 : double SAL_CALL ScVbaUserForm::getInnerWidth() throw (uno::RuntimeException)
117 : : {
118 : 0 : return mpGeometryHelper->getInnerWidth();
119 : : }
120 : :
121 : 0 : void SAL_CALL ScVbaUserForm::setInnerWidth( double fInnerWidth ) throw (uno::RuntimeException)
122 : : {
123 : 0 : mpGeometryHelper->setInnerWidth( fInnerWidth );
124 : 0 : }
125 : :
126 : 0 : double SAL_CALL ScVbaUserForm::getInnerHeight() throw (uno::RuntimeException)
127 : : {
128 : 0 : return mpGeometryHelper->getInnerHeight();
129 : : }
130 : :
131 : 0 : void SAL_CALL ScVbaUserForm::setInnerHeight( double fInnerHeight ) throw (uno::RuntimeException)
132 : : {
133 : 0 : mpGeometryHelper->setInnerHeight( fInnerHeight );
134 : 0 : }
135 : :
136 : : void SAL_CALL
137 : 0 : ScVbaUserForm::Hide( ) throw (uno::RuntimeException)
138 : : {
139 : 0 : mbDispose = false; // hide not dispose
140 : 0 : if ( m_xDialog.is() )
141 : 0 : m_xDialog->endExecute();
142 : 0 : }
143 : :
144 : 0 : sal_Bool SAL_CALL ScVbaUserForm::getVisible() throw (uno::RuntimeException)
145 : : {
146 : 0 : uno::Reference< awt::XWindow2 > xWindow2( getWindowPeer(), uno::UNO_QUERY_THROW );
147 : 0 : return xWindow2->isVisible();
148 : : }
149 : :
150 : 0 : void SAL_CALL ScVbaUserForm::setVisible( sal_Bool bVisible ) throw (uno::RuntimeException)
151 : : {
152 : 0 : if ( bVisible )
153 : 0 : Show();
154 : : else
155 : 0 : Hide();
156 : 0 : }
157 : :
158 : : void SAL_CALL
159 : 0 : ScVbaUserForm::RePaint( ) throw (uno::RuntimeException)
160 : : {
161 : : // do nothing
162 : 0 : }
163 : :
164 : : void SAL_CALL
165 : 0 : ScVbaUserForm::UnloadObject( ) throw (uno::RuntimeException)
166 : : {
167 : 0 : mbDispose = true;
168 : 0 : if ( m_xDialog.is() )
169 : 0 : m_xDialog->endExecute();
170 : 0 : }
171 : :
172 : : rtl::OUString
173 : 0 : ScVbaUserForm::getServiceImplName()
174 : : {
175 : 0 : return rtl::OUString("ScVbaUserForm");
176 : : }
177 : :
178 : : uno::Sequence< rtl::OUString >
179 : 0 : ScVbaUserForm::getServiceNames()
180 : : {
181 : 0 : static uno::Sequence< rtl::OUString > aServiceNames;
182 : 0 : if ( aServiceNames.getLength() == 0 )
183 : : {
184 : 0 : aServiceNames.realloc( 1 );
185 : 0 : aServiceNames[ 0 ] = "ooo.vba.excel.UserForm";
186 : : }
187 : 0 : return aServiceNames;
188 : : }
189 : :
190 : : uno::Reference< beans::XIntrospectionAccess > SAL_CALL
191 : 0 : ScVbaUserForm::getIntrospection( ) throw (uno::RuntimeException)
192 : : {
193 : 0 : return uno::Reference< beans::XIntrospectionAccess >();
194 : : }
195 : :
196 : : uno::Any SAL_CALL
197 : 0 : ScVbaUserForm::invoke( const ::rtl::OUString& /*aFunctionName*/, const uno::Sequence< uno::Any >& /*aParams*/, uno::Sequence< ::sal_Int16 >& /*aOutParamIndex*/, uno::Sequence< uno::Any >& /*aOutParam*/ ) throw (lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException)
198 : : {
199 : 0 : throw uno::RuntimeException(); // unsupported operation
200 : : }
201 : :
202 : : void SAL_CALL
203 : 0 : ScVbaUserForm::setValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue ) throw (beans::UnknownPropertyException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException)
204 : : {
205 : 0 : uno::Any aObject = getValue( aPropertyName );
206 : :
207 : : // in case the dialog is already closed the VBA implementation should not throw exceptions
208 : 0 : if ( aObject.hasValue() )
209 : : {
210 : : // The Object *must* support XDefaultProperty here because getValue will
211 : : // only return properties that are Objects ( e.g. controls )
212 : : // e.g. Userform1.aControl = something
213 : : // 'aControl' has to support XDefaultProperty to make sense here
214 : 0 : uno::Reference< script::XDefaultProperty > xDfltProp( aObject, uno::UNO_QUERY_THROW );
215 : 0 : rtl::OUString aDfltPropName = xDfltProp->getDefaultPropertyName();
216 : 0 : uno::Reference< beans::XIntrospectionAccess > xUnoAccess( getIntrospectionAccess( aObject ) );
217 : 0 : uno::Reference< beans::XPropertySet > xPropSet( xUnoAccess->queryAdapter( ::getCppuType( (const uno::Reference< beans::XPropertySet > *)0 ) ), uno::UNO_QUERY_THROW );
218 : 0 : xPropSet->setPropertyValue( aDfltPropName, aValue );
219 : 0 : }
220 : 0 : }
221 : :
222 : : uno::Reference< awt::XControl >
223 : 0 : ScVbaUserForm::nestedSearch( const rtl::OUString& aPropertyName, uno::Reference< awt::XControlContainer >& xContainer )
224 : : {
225 : 0 : uno::Reference< awt::XControl > xControl = xContainer->getControl( aPropertyName );
226 : 0 : if ( !xControl.is() )
227 : : {
228 : 0 : uno::Sequence< uno::Reference< awt::XControl > > aControls = xContainer->getControls();
229 : 0 : const uno::Reference< awt::XControl >* pCtrl = aControls.getConstArray();
230 : 0 : const uno::Reference< awt::XControl >* pCtrlsEnd = pCtrl + aControls.getLength();
231 : :
232 : 0 : for ( ; pCtrl < pCtrlsEnd; ++pCtrl )
233 : : {
234 : 0 : uno::Reference< awt::XControlContainer > xC( *pCtrl, uno::UNO_QUERY );
235 : 0 : if ( xC.is() )
236 : : {
237 : 0 : xControl.set( nestedSearch( aPropertyName, xC ) );
238 : 0 : if ( xControl.is() )
239 : : break;
240 : : }
241 : 0 : }
242 : : }
243 : 0 : return xControl;
244 : : }
245 : :
246 : : uno::Any SAL_CALL
247 : 0 : ScVbaUserForm::getValue( const ::rtl::OUString& aPropertyName ) throw (beans::UnknownPropertyException, uno::RuntimeException)
248 : : {
249 : 0 : uno::Any aResult;
250 : :
251 : : // in case the dialog is already closed the VBA implementation should not throw exceptions
252 : 0 : if ( m_xDialog.is() )
253 : : {
254 : 0 : uno::Reference< awt::XControl > xDialogControl( m_xDialog, uno::UNO_QUERY_THROW );
255 : 0 : uno::Reference< awt::XControlContainer > xContainer( m_xDialog, uno::UNO_QUERY_THROW );
256 : 0 : uno::Reference< awt::XControl > xControl = nestedSearch( aPropertyName, xContainer );
257 : 0 : xContainer->getControl( aPropertyName );
258 : 0 : if ( xControl.is() )
259 : : {
260 : 0 : uno::Reference< msforms::XControl > xVBAControl = ScVbaControlFactory::createUserformControl( mxContext, xControl, xDialogControl, m_xModel, mpGeometryHelper->getOffsetX(), mpGeometryHelper->getOffsetY() );
261 : 0 : ScVbaControl* pControl = dynamic_cast< ScVbaControl* >( xVBAControl.get() );
262 : 0 : if ( !m_sLibName.isEmpty() )
263 : 0 : pControl->setLibraryAndCodeName( m_sLibName.concat( rtl::OUString( "." ) ).concat( getName() ) );
264 : 0 : aResult = uno::makeAny( xVBAControl );
265 : 0 : }
266 : : }
267 : :
268 : 0 : return aResult;
269 : : }
270 : :
271 : : ::sal_Bool SAL_CALL
272 : 0 : ScVbaUserForm::hasMethod( const ::rtl::OUString& /*aName*/ ) throw (uno::RuntimeException)
273 : : {
274 : 0 : return sal_False;
275 : : }
276 : : uno::Any SAL_CALL
277 : 0 : ScVbaUserForm::Controls( const uno::Any& index ) throw (uno::RuntimeException)
278 : : {
279 : : // if the dialog already closed we should do nothing, but the VBA will call methods of the Controls objects
280 : : // thus we have to provide a dummy object in this case
281 : 0 : uno::Reference< awt::XControl > xDialogControl( m_xDialog, uno::UNO_QUERY );
282 : 0 : uno::Reference< XCollection > xControls( new ScVbaControls( this, mxContext, xDialogControl, m_xModel, mpGeometryHelper->getOffsetX(), mpGeometryHelper->getOffsetY() ) );
283 : 0 : if ( index.hasValue() )
284 : 0 : return uno::makeAny( xControls->Item( index, uno::Any() ) );
285 : 0 : return uno::makeAny( xControls );
286 : : }
287 : :
288 : : ::sal_Bool SAL_CALL
289 : 0 : ScVbaUserForm::hasProperty( const ::rtl::OUString& aName ) throw (uno::RuntimeException)
290 : : {
291 : 0 : uno::Reference< awt::XControl > xControl( m_xDialog, uno::UNO_QUERY );
292 : :
293 : : OSL_TRACE("ScVbaUserForm::hasProperty(%s) %d", rtl::OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ).getStr(), xControl.is() );
294 : 0 : if ( xControl.is() )
295 : : {
296 : 0 : uno::Reference< beans::XPropertySet > xDlgProps( xControl->getModel(), uno::UNO_QUERY );
297 : 0 : if ( xDlgProps.is() )
298 : : {
299 : 0 : uno::Reference< container::XNameContainer > xAllChildren( xDlgProps->getPropertyValue( rtl::OUString("AllDialogChildren") ), uno::UNO_QUERY_THROW );
300 : 0 : sal_Bool bRes = xAllChildren->hasByName( aName );
301 : : OSL_TRACE("ScVbaUserForm::hasProperty(%s) %d ---> %d", rtl::OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ).getStr(), xAllChildren.is(), bRes );
302 : 0 : return bRes;
303 : 0 : }
304 : : }
305 : 0 : return sal_False;
306 : : }
307 : :
308 : : namespace userform
309 : : {
310 : : namespace sdecl = comphelper::service_decl;
311 : 0 : sdecl::vba_service_class_<ScVbaUserForm, sdecl::with_args<true> > serviceImpl;
312 : 0 : extern sdecl::ServiceDecl const serviceDecl(
313 : : serviceImpl,
314 : : "ScVbaUserForm",
315 : : "ooo.vba.msforms.UserForm" );
316 : 0 : }
317 : :
318 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|