/*************************************************************************
 *
 *  $RCSfile: wizardmachine.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2003/03/27 14:36:41 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVTOOLS_WIZARDMACHINE_HXX_
#define _SVTOOLS_WIZARDMACHINE_HXX_

#ifndef _SVT_WIZDLG_HXX
#include <svtools/wizdlg.hxx>
#endif
#ifndef _SV_BUTTON_HXX 
#include <vcl/button.hxx>
#endif
#ifndef _SV_TABPAGE_HXX 
#include <vcl/tabpage.hxx>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif

class Bitmap;
//.........................................................................
namespace svt
{
//.........................................................................

// wizard buttons
#define WZB_NEXT				0x0001
#define WZB_PREVIOUS			0x0002
#define WZB_FINISH				0x0004
#define WZB_CANCEL				0x0008
#define WZB_HELP				0x0010

// wizard states
#define WZS_INVALID_STATE		((sal_uInt16)-1)

	//=====================================================================
	//= OWizardPage
	//=====================================================================
	class OWizardMachine;
	struct WizardPageImplData;
	class OWizardPage : public TabPage
	{
	private:
		WizardPageImplData*		m_pImpl;

	public:
		// access control
		struct GrantAccess
		{
			friend class OWizardMachine;
		private:
			GrantAccess() { }
		};

	public:
		OWizardPage( OWizardMachine* _pParent, WinBits _nStyle = 0 );
		OWizardPage( OWizardMachine* _pParent, const ResId& _rResId );
		~OWizardPage();

		enum COMMIT_REASON
		{
			CR_TRAVEL_NEXT,			// the page is to be left because of a travel to the next state
			CR_TRAVEL_PREVIOUS,		// the page is to be left because of a travel to the previous state
			CR_FINISH,				// the wizard should be finished
			CR_VALIDATE,			// the data should be validated only, no traveling wll happen
			CR_VALIDATE_NOUI		// the data should be validated only, without displaying error messages and such
		};
		// This methods  behave somewhat different than ActivatePage/DeactivatePage
		// The latter are handled by the base class itself whenever changing the pages is in the offing,
		// i.e., when it's already decided which page is the next.
		// We may have situations where the next page depends on the state of the current, which needs
		// to be committed for this.
		// So initializePage and commitPage are designated to initialitzing/committing data on the page.
		virtual void		initializePage();
		virtual sal_Bool	commitPage(COMMIT_REASON _eReason);

		//-----------------------------------------------------------------
		// methods which, though public, are acessible for the OWizardMachine only
		void				enableHeader( const Bitmap& _rBitmap, sal_Int32 _nPixelHeight, GrantAccess );

	protected:
		// TabPage overridables
		virtual void	ActivatePage();

		/** checks whether or not the header is enabled
			<p>The header can only be enabled by the OWizardMachine the page belongs to. This way, it is ensured
			that <em>all</em> or <em>none</em> of the pages have a header.</p>
		*/
		sal_Bool		isHeaderEnabled( ) const;

		/** sets the text of the header.
			<p>To be called if the header is enabled only.</p>
			@see isHeaderEnabled
		*/
		void			setHeaderText( const String& _rHeaderText );

	protected:
		// called from within ActivatePage, enables the wizards "Next" button depending on the return value of
		// determineNextButtonState();
		void implCheckNextButton();
		// return sal_True if the NEXT button should be enabled
		virtual sal_Bool determineNextButtonState();
	};

	//=====================================================================
	//= OWizardMachine
	//=====================================================================
	struct WizardMachineImplData;
	/** at the moment, this is a state machine with n states and at most 1 transition per state ...
		So this means the pages are in a linear order :) ... This is to be changed in the future
	*/
	class OWizardMachine : public WizardDialog
	{
	private:
		// restrict access to some aspects of our base class
		void				AddPage( TabPage* pPage ) { WizardDialog::AddPage(pPage); }
		void				RemovePage( TabPage* pPage ) { WizardDialog::RemovePage(pPage); }
		void				SetPage( USHORT nLevel, TabPage* pPage ) { WizardDialog::SetPage(nLevel, pPage); }
		TabPage*			GetPage( USHORT nLevel ) const { return WizardDialog::GetPage(nLevel); }
		// TODO: probably the complete page handling (next, previous etc.) should be prohibited ...

		// IMPORTANT:
		// traveling pages should not be done by calling these base class member, some mechanisms of this class
		// here (e.g. committing page data) depend on having full control over page traveling.
		// So use the travelXXX methods if you need to travel

	protected:
		OKButton*		m_pFinish;
		CancelButton*	m_pCancel;
		PushButton*		m_pNextPage;
		PushButton*		m_pPrevPage;
		HelpButton*		m_pHelp;

	private:
		WizardMachineImplData*
						m_pImpl;
			// hold members in this structure to allow keeping compatible when members are added

	public:
		/** ctor
			<p>The ctor does not call FreeResource, this is the resposibility of the derived class.</p>
			<p>For the button flags, use any combination of the WZB_NEXT flags. For every button which's presence
			is specified, the resource of the dialog <em>must</em> contain an appropriate button with the id as
			specified in the .hrc file for this class.</p>
		*/
		OWizardMachine(Window* _pParent, const ResId& _rRes, sal_uInt32 _nButtonFlags);
		~OWizardMachine();

		/// enable (or disable) buttons
		void	enableButtons(sal_uInt32 _nWizardButtonFlags, sal_Bool _bEnable);
		/// set the default style for a button
		void	defaultButton(sal_uInt32 _nWizardButtonFlags);
		/// set the default style for a button
		void	defaultButton(PushButton* _pNewDefButton);

		/// set the base of the title to use - the title of the current page is appended
		void			setTitleBase(const String& _rTitleBase);
		const String&	getTitleBase() const;

	protected:
		// WizardDialog overridables
		virtual void		ActivatePage();
		virtual long		DeactivatePage();

		// our own overridables

		/// to override to create new pages
		virtual OWizardPage*	createPage(sal_uInt16 _nState) = 0;
		/// will be called when a new page is about to be displayed
		virtual	void			enterState(sal_uInt16 _nState);
		/** will be called when a page is about to be left
			return <FALSE/>
				if the page should be kept
		*/
		virtual	sal_Bool		leaveState(sal_uInt16 _nState);
		/** determine the next state to travel from the given one
			<p>The default behaviour is linear traveling, override this to change it</p>
			<p>Return WZS_INVALID_STATE to prevent traveling.</p>
		*/
		virtual sal_uInt16		determineNextState(sal_uInt16 _nCurrentState);

		/** called when the finish button is pressed
			<p>By default, only the base class' Finnish method (which is not virtual) is called</p>
		*/
		virtual sal_Bool onFinish(sal_Int32 _nResult);

		/** enables a header bitmap
			<p>Usually, wizards contain a header. This header is as wide as the dialog and positioned at the very top.
			In addition, it contains a (rather small) bitmap on the left side, and right next to this bitmap, a short
			text describing the current page.</p>
			<p>If you call this method, this header is automatically created on every page. In addition, all
			other controls on the pages are moved below the header. The title of every page is used as text
			for the header.</p>
			<p>This method must not be called if there there are already pages created.</p>
			@param _rBitmap
				the bitmap to use for the header
			@param _nPixelHeight
				the height of the header in pixels.<br/>
				If -1 is passed, the default of 30 APPFONT units will be used.
		*/
		void	enableHeader( const Bitmap& _rBitmap, sal_Int32 _nPixelHeight = -1 );

		/// travel to the next state
		sal_Bool	travelNext();
		/// travel to the previous state
		sal_Bool	travelPrevious();
		/** skip a state
			<p>The method behaves as if from the current state, <arg>_nSteps</arg> <method>travelNext</method>s were
			called, but without actually creating or displaying the íntermediate pages. Only the
			(<arg>_nSteps</arg> + 1)th page is created</p>
			<p>The skipped states appear in the state history, so <method>travelPrevious</method> will make use of them.</p>
			<p>A very essential precondition for using this method is that your <method>determineNextState</method>
			method is able to determine the next state without actually having the page of the current state.</p>
		*/
		sal_Bool	skip(sal_Int32 _nSteps = 1);

		sal_uInt16		getCurrentState() const { return WizardDialog::GetCurLevel(); }

		OWizardPage*	getPage(sal_uInt16 _nState) const { return static_cast<OWizardPage*>(WizardDialog::GetPage(_nState)); }

		OWizardPage*	getCurrentPage() const { return getPage(getCurrentState()); }

	private:
		DECL_LINK(OnNextPage, PushButton*);
		DECL_LINK(OnPrevPage, PushButton*);
		DECL_LINK(OnFinish, PushButton*);

		void		implResetDefault(Window* _pWindow);
		void		implUpdateTitle();
		sal_Bool	implCommitCurrentPage(OWizardPage::COMMIT_REASON _eReason);
	};

//.........................................................................
}	// namespace svty
//.........................................................................

#endif // _SVTOOLS_WIZARDMACHINE_HXX_

