Bump version to 5.0-14
[LibreOffice.git] / svtools / source / uno / wizard / unowizard.cxx
blob7b9cade8d85a15b5aac3d66ab664eb3e75f0a05d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "wizardshell.hxx"
23 #include <com/sun/star/lang/XInitialization.hpp>
24 #include <com/sun/star/beans/XPropertySetInfo.hpp>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
27 #include <com/sun/star/ui/dialogs/XWizard.hpp>
28 #include <com/sun/star/ui/dialogs/XWizardController.hpp>
29 #include <com/sun/star/ui/dialogs/WizardButton.hpp>
31 #include <cppuhelper/implbase1.hxx>
32 #include <svtools/genericunodialog.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <rtl/ref.hxx>
35 #include <rtl/strbuf.hxx>
36 #include <osl/mutex.hxx>
37 #include <vcl/svapp.hxx>
38 #include <tools/urlobj.hxx>
40 using namespace ::com::sun::star;
41 using namespace ::svt::uno;
43 namespace {
45 using ::com::sun::star::uno::Reference;
46 using ::com::sun::star::uno::XInterface;
47 using ::com::sun::star::uno::UNO_QUERY;
48 using ::com::sun::star::uno::UNO_QUERY_THROW;
49 using ::com::sun::star::uno::UNO_SET_THROW;
50 using ::com::sun::star::uno::Exception;
51 using ::com::sun::star::uno::RuntimeException;
52 using ::com::sun::star::uno::Any;
53 using ::com::sun::star::uno::makeAny;
54 using ::com::sun::star::uno::Sequence;
55 using ::com::sun::star::uno::Type;
56 using ::com::sun::star::lang::XServiceInfo;
57 using ::com::sun::star::ui::dialogs::XWizard;
58 using ::com::sun::star::lang::XInitialization;
59 using ::com::sun::star::beans::XPropertySetInfo;
60 using ::com::sun::star::uno::XComponentContext;
61 using ::com::sun::star::beans::Property;
62 using ::com::sun::star::lang::IllegalArgumentException;
63 using ::com::sun::star::ucb::AlreadyInitializedException;
64 using ::com::sun::star::ui::dialogs::XWizardController;
65 using ::com::sun::star::ui::dialogs::XWizardPage;
66 using ::com::sun::star::container::NoSuchElementException;
67 using ::com::sun::star::util::InvalidStateException;
68 using ::com::sun::star::awt::XWindow;
70 namespace WizardButton = ::com::sun::star::ui::dialogs::WizardButton;
73 namespace
75 WizardButtonFlags lcl_convertWizardButtonToWZB( const sal_Int16 i_nWizardButton )
77 switch ( i_nWizardButton )
79 case WizardButton::NONE: return WizardButtonFlags::NONE;
80 case WizardButton::NEXT: return WizardButtonFlags::NEXT;
81 case WizardButton::PREVIOUS: return WizardButtonFlags::PREVIOUS;
82 case WizardButton::FINISH: return WizardButtonFlags::FINISH;
83 case WizardButton::CANCEL: return WizardButtonFlags::CANCEL;
84 case WizardButton::HELP: return WizardButtonFlags::HELP;
86 OSL_FAIL( "lcl_convertWizardButtonToWZB: invalid WizardButton constant!" );
87 return WizardButtonFlags::NONE;
91 typedef ::cppu::ImplInheritanceHelper1 < ::svt::OGenericUnoDialog
92 , ui::dialogs::XWizard
93 > Wizard_Base;
94 class Wizard;
95 typedef ::comphelper::OPropertyArrayUsageHelper< Wizard > Wizard_PBase;
96 class Wizard : public Wizard_Base
97 , public Wizard_PBase
99 public:
100 Wizard( const uno::Reference< uno::XComponentContext >& i_rContext );
102 // lang::XServiceInfo
103 virtual OUString SAL_CALL getImplementationName() throw(uno::RuntimeException, std::exception) SAL_OVERRIDE;
104 virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(uno::RuntimeException, std::exception) SAL_OVERRIDE;
106 // beans::XPropertySet
107 virtual uno::Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(uno::RuntimeException, std::exception) SAL_OVERRIDE;
108 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE;
110 // OPropertyArrayUsageHelper
111 virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const SAL_OVERRIDE;
113 // ui::dialogs::XWizard
114 virtual OUString SAL_CALL getHelpURL() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
115 virtual void SAL_CALL setHelpURL( const OUString& _helpurl ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
116 virtual uno::Reference< awt::XWindow > SAL_CALL getDialogWindow() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
117 virtual uno::Reference< ui::dialogs::XWizardPage > SAL_CALL getCurrentPage( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
118 virtual void SAL_CALL enableButton( ::sal_Int16 WizardButton, sal_Bool Enable ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
119 virtual void SAL_CALL setDefaultButton( ::sal_Int16 WizardButton ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
120 virtual sal_Bool SAL_CALL travelNext( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
121 virtual sal_Bool SAL_CALL travelPrevious( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
122 virtual void SAL_CALL enablePage( ::sal_Int16 PageID, sal_Bool Enable ) throw (container::NoSuchElementException, util::InvalidStateException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
123 virtual void SAL_CALL updateTravelUI( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
124 virtual sal_Bool SAL_CALL advanceTo( ::sal_Int16 PageId ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
125 virtual sal_Bool SAL_CALL goBackTo( ::sal_Int16 PageId ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
126 virtual void SAL_CALL activatePath( ::sal_Int16 PathIndex, sal_Bool Final ) throw (container::NoSuchElementException, util::InvalidStateException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
128 // ui::dialogs::XExecutableDialog
129 virtual void SAL_CALL setTitle( const OUString& aTitle ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
130 virtual ::sal_Int16 SAL_CALL execute( ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
132 // lang::XInitialization
133 virtual void SAL_CALL initialize( const uno::Sequence< uno::Any >& aArguments ) throw (uno::Exception, uno::RuntimeException, std::exception) SAL_OVERRIDE;
135 protected:
136 virtual ~Wizard();
138 protected:
139 virtual VclPtr<Dialog> createDialog( vcl::Window* _pParent ) SAL_OVERRIDE;
140 virtual void destroyDialog() SAL_OVERRIDE;
142 private:
143 uno::Sequence< uno::Sequence< sal_Int16 > > m_aWizardSteps;
144 uno::Reference< ui::dialogs::XWizardController > m_xController;
145 OUString m_sHelpURL;
148 Wizard::Wizard( const Reference< XComponentContext >& _rxContext )
149 :Wizard_Base( _rxContext )
154 Wizard::~Wizard()
156 // we do this here cause the base class' call to destroyDialog won't reach us anymore : we're within an dtor,
157 // so this virtual-method-call the base class does does not work, we're already dead then ...
158 if ( m_pDialog )
160 ::osl::MutexGuard aGuard( m_aMutex );
161 if ( m_pDialog )
162 destroyDialog();
167 namespace
169 static void lcl_checkPaths( const Sequence< Sequence< sal_Int16 > >& i_rPaths, const Reference< XInterface >& i_rContext )
171 // need at least one path
172 if ( i_rPaths.getLength() == 0 )
173 throw IllegalArgumentException( OUString(), i_rContext, 2 );
175 // each path must be of length 1, at least
176 for ( sal_Int32 i = 0; i < i_rPaths.getLength(); ++i )
178 if ( i_rPaths[i].getLength() == 0 )
179 throw IllegalArgumentException( OUString(), i_rContext, 2 );
181 // page IDs must be in ascending order
182 sal_Int16 nPreviousPageID = i_rPaths[i][0];
183 for ( sal_Int32 j=1; j<i_rPaths[i].getLength(); ++j )
185 if ( i_rPaths[i][j] <= nPreviousPageID )
187 OStringBuffer message;
188 message.append( "Path " );
189 message.append( i );
190 message.append( ": invalid page ID sequence - each page ID must be greater than the previous one." );
191 throw IllegalArgumentException(
192 OStringToOUString( message.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ),
193 i_rContext, 2 );
195 nPreviousPageID = i_rPaths[i][j];
199 // if we have one path, that's okay
200 if ( i_rPaths.getLength() == 1 )
201 return;
203 // if we have multiple paths, they must start with the same page id
204 const sal_Int16 nFirstPageId = i_rPaths[0][0];
205 for ( sal_Int32 i = 0; i < i_rPaths.getLength(); ++i )
207 if ( i_rPaths[i][0] != nFirstPageId )
208 throw IllegalArgumentException(
209 "All paths must start with the same page id.",
210 i_rContext, 2 );
216 void SAL_CALL Wizard::initialize( const Sequence< Any >& i_Arguments ) throw (Exception, RuntimeException, std::exception)
218 ::osl::MutexGuard aGuard( m_aMutex );
219 if ( m_bInitialized )
220 throw AlreadyInitializedException( OUString(), *this );
222 if ( i_Arguments.getLength() != 2 )
223 throw IllegalArgumentException( OUString(), *this, -1 );
225 // the second argument must be a XWizardController, for each constructor
226 m_xController.set( i_Arguments[1], UNO_QUERY );
227 if ( !m_xController.is() )
228 throw IllegalArgumentException( OUString(), *this, 2 );
230 // the first arg is either a single path (short[]), or multiple paths (short[][])
231 Sequence< sal_Int16 > aSinglePath;
232 i_Arguments[0] >>= aSinglePath;
233 Sequence< Sequence< sal_Int16 > > aMultiplePaths;
234 i_Arguments[0] >>= aMultiplePaths;
236 if ( !aMultiplePaths.getLength() )
238 aMultiplePaths.realloc(1);
239 aMultiplePaths[0] = aSinglePath;
241 lcl_checkPaths( aMultiplePaths, *this );
242 // if we survived this, the paths are valid, and we're done here ...
243 m_aWizardSteps = aMultiplePaths;
245 m_bInitialized = true;
248 static OString lcl_getHelpId( const OUString& _rHelpURL )
250 INetURLObject aHID( _rHelpURL );
251 if ( aHID.GetProtocol() == INetProtocol::Hid )
252 return OUStringToOString( aHID.GetURLPath(), RTL_TEXTENCODING_UTF8 );
253 else
254 return OUStringToOString( _rHelpURL, RTL_TEXTENCODING_UTF8 );
258 static OUString lcl_getHelpURL( const OString& sHelpId )
260 OUStringBuffer aBuffer;
261 OUString aTmp(
262 OStringToOUString( sHelpId, RTL_TEXTENCODING_UTF8 ) );
263 INetURLObject aHID( aTmp );
264 if ( aHID.GetProtocol() == INetProtocol::NotValid )
265 aBuffer.appendAscii( INET_HID_SCHEME );
266 aBuffer.append( aTmp.getStr() );
267 return aBuffer.makeStringAndClear();
271 VclPtr<Dialog> Wizard::createDialog( vcl::Window* i_pParent )
273 VclPtrInstance<WizardShell> pDialog( i_pParent, m_xController, m_aWizardSteps );
274 pDialog->SetHelpId( lcl_getHelpId( m_sHelpURL ) );
275 pDialog->setTitleBase( m_sTitle );
276 return pDialog.get();
280 void Wizard::destroyDialog()
282 if ( m_pDialog )
283 m_sHelpURL = lcl_getHelpURL( m_pDialog->GetHelpId() );
285 Wizard_Base::destroyDialog();
289 OUString SAL_CALL Wizard::getImplementationName() throw(RuntimeException, std::exception)
291 return OUString("com.sun.star.comp.svtools.uno.Wizard");
295 Sequence< OUString > SAL_CALL Wizard::getSupportedServiceNames() throw(RuntimeException, std::exception)
297 Sequence< OUString > aServices(1);
298 aServices[0] = "com.sun.star.ui.dialogs.Wizard";
299 return aServices;
303 Reference< XPropertySetInfo > SAL_CALL Wizard::getPropertySetInfo() throw(RuntimeException, std::exception)
305 return createPropertySetInfo( getInfoHelper() );
309 ::cppu::IPropertyArrayHelper& SAL_CALL Wizard::getInfoHelper()
311 return *getArrayHelper();
315 ::cppu::IPropertyArrayHelper* Wizard::createArrayHelper( ) const
317 Sequence< Property > aProps;
318 describeProperties( aProps );
319 return new ::cppu::OPropertyArrayHelper( aProps );
323 OUString SAL_CALL Wizard::getHelpURL() throw (RuntimeException, std::exception)
325 SolarMutexGuard aSolarGuard;
326 ::osl::MutexGuard aGuard( m_aMutex );
328 if ( !m_pDialog )
329 return m_sHelpURL;
331 return lcl_getHelpURL( m_pDialog->GetHelpId() );
335 void SAL_CALL Wizard::setHelpURL( const OUString& i_HelpURL ) throw (RuntimeException, std::exception)
337 SolarMutexGuard aSolarGuard;
338 ::osl::MutexGuard aGuard( m_aMutex );
340 if ( !m_pDialog )
341 m_sHelpURL = i_HelpURL;
342 else
343 m_pDialog->SetHelpId( lcl_getHelpId( i_HelpURL ) );
347 Reference< XWindow > SAL_CALL Wizard::getDialogWindow() throw (RuntimeException, std::exception)
349 SolarMutexGuard aSolarGuard;
350 ::osl::MutexGuard aGuard( m_aMutex );
352 ENSURE_OR_RETURN( m_pDialog, "Wizard::getDialogWindow: illegal call (execution did not start, yet)!", NULL );
353 return Reference< XWindow >( m_pDialog->GetComponentInterface(), UNO_QUERY );
357 void SAL_CALL Wizard::enableButton( ::sal_Int16 i_WizardButton, sal_Bool i_Enable ) throw (RuntimeException, std::exception)
359 SolarMutexGuard aSolarGuard;
360 ::osl::MutexGuard aGuard( m_aMutex );
362 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
363 ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::enableButtons: invalid dialog implementation!" );
365 pWizardImpl->enableButtons( lcl_convertWizardButtonToWZB( i_WizardButton ), i_Enable );
369 void SAL_CALL Wizard::setDefaultButton( ::sal_Int16 i_WizardButton ) throw (RuntimeException, std::exception)
371 SolarMutexGuard aSolarGuard;
372 ::osl::MutexGuard aGuard( m_aMutex );
374 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
375 ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::setDefaultButton: invalid dialog implementation!" );
377 pWizardImpl->defaultButton( lcl_convertWizardButtonToWZB( i_WizardButton ) );
381 sal_Bool SAL_CALL Wizard::travelNext( ) throw (RuntimeException, std::exception)
383 SolarMutexGuard aSolarGuard;
384 ::osl::MutexGuard aGuard( m_aMutex );
386 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
387 ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::travelNext: invalid dialog implementation!" );
389 return pWizardImpl->travelNext();
393 sal_Bool SAL_CALL Wizard::travelPrevious( ) throw (RuntimeException, std::exception)
395 SolarMutexGuard aSolarGuard;
396 ::osl::MutexGuard aGuard( m_aMutex );
398 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
399 ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::travelPrevious: invalid dialog implementation!" );
401 return pWizardImpl->travelPrevious();
405 void SAL_CALL Wizard::enablePage( ::sal_Int16 i_PageID, sal_Bool i_Enable ) throw (NoSuchElementException, InvalidStateException, RuntimeException, std::exception)
407 SolarMutexGuard aSolarGuard;
408 ::osl::MutexGuard aGuard( m_aMutex );
410 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
411 ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::enablePage: invalid dialog implementation!" );
413 if ( !pWizardImpl->knowsPage( i_PageID ) )
414 throw NoSuchElementException( OUString(), *this );
416 if ( i_PageID == pWizardImpl->getCurrentPage() )
417 throw InvalidStateException( OUString(), *this );
419 pWizardImpl->enablePage( i_PageID, i_Enable );
423 void SAL_CALL Wizard::updateTravelUI( ) throw (RuntimeException, std::exception)
425 SolarMutexGuard aSolarGuard;
426 ::osl::MutexGuard aGuard( m_aMutex );
428 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
429 ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::updateTravelUI: invalid dialog implementation!" );
431 pWizardImpl->updateTravelUI();
435 sal_Bool SAL_CALL Wizard::advanceTo( ::sal_Int16 i_PageId ) throw (RuntimeException, std::exception)
437 SolarMutexGuard aSolarGuard;
438 ::osl::MutexGuard aGuard( m_aMutex );
440 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
441 ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::advanceTo: invalid dialog implementation!" );
443 return pWizardImpl->advanceTo( i_PageId );
447 sal_Bool SAL_CALL Wizard::goBackTo( ::sal_Int16 i_PageId ) throw (RuntimeException, std::exception)
449 SolarMutexGuard aSolarGuard;
450 ::osl::MutexGuard aGuard( m_aMutex );
452 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
453 ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::goBackTo: invalid dialog implementation!" );
455 return pWizardImpl->goBackTo( i_PageId );
459 Reference< XWizardPage > SAL_CALL Wizard::getCurrentPage( ) throw (RuntimeException, std::exception)
461 SolarMutexGuard aSolarGuard;
462 ::osl::MutexGuard aGuard( m_aMutex );
464 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
465 ENSURE_OR_RETURN( pWizardImpl, "Wizard::getCurrentPage: invalid dialog implementation!", Reference< XWizardPage >() );
467 return pWizardImpl->getCurrentWizardPage();
471 void SAL_CALL Wizard::activatePath( ::sal_Int16 i_PathIndex, sal_Bool i_Final ) throw (NoSuchElementException, InvalidStateException, RuntimeException, std::exception)
473 SolarMutexGuard aSolarGuard;
474 ::osl::MutexGuard aGuard( m_aMutex );
476 if ( ( i_PathIndex < 0 ) || ( i_PathIndex >= m_aWizardSteps.getLength() ) )
477 throw NoSuchElementException( OUString(), *this );
479 WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog.get() );
480 ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::activatePath: invalid dialog implementation!" );
482 pWizardImpl->activatePath( i_PathIndex, i_Final );
486 void SAL_CALL Wizard::setTitle( const OUString& i_Title ) throw (RuntimeException, std::exception)
488 // simply disambiguate
489 Wizard_Base::OGenericUnoDialog::setTitle( i_Title );
493 ::sal_Int16 SAL_CALL Wizard::execute( ) throw (RuntimeException, std::exception)
495 return Wizard_Base::OGenericUnoDialog::execute();
500 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
501 com_sun_star_comp_svtools_uno_Wizard_get_implementation(
502 css::uno::XComponentContext *context,
503 css::uno::Sequence<css::uno::Any> const &)
505 return cppu::acquire(new Wizard(context));
508 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */