1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
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
;
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
95 typedef ::comphelper::OPropertyArrayUsageHelper
< Wizard
> Wizard_PBase
;
96 class Wizard
: public Wizard_Base
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
;
139 virtual VclPtr
<Dialog
> createDialog( vcl::Window
* _pParent
) SAL_OVERRIDE
;
140 virtual void destroyDialog() SAL_OVERRIDE
;
143 uno::Sequence
< uno::Sequence
< sal_Int16
> > m_aWizardSteps
;
144 uno::Reference
< ui::dialogs::XWizardController
> m_xController
;
148 Wizard::Wizard( const Reference
< XComponentContext
>& _rxContext
)
149 :Wizard_Base( _rxContext
)
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 ...
160 ::osl::MutexGuard
aGuard( m_aMutex
);
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 " );
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
),
195 nPreviousPageID
= i_rPaths
[i
][j
];
199 // if we have one path, that's okay
200 if ( i_rPaths
.getLength() == 1 )
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.",
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
);
254 return OUStringToOString( _rHelpURL
, RTL_TEXTENCODING_UTF8
);
258 static OUString
lcl_getHelpURL( const OString
& sHelpId
)
260 OUStringBuffer aBuffer
;
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()
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";
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
);
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
);
341 m_sHelpURL
= i_HelpURL
;
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: */