xref: /AOO41X/main/svtools/source/dialogs/wizardmachine.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include <svtools/wizardmachine.hxx>
27 #include <svtools/helpid.hrc>
28 #include <tools/debug.hxx>
29 #include <tools/diagnose_ex.h>
30 #include <vcl/msgbox.hxx>
31 #include <svtools/svtdata.hxx>
32 #ifndef _SVTOOLS_HRC
33 #include <svtools/svtools.hrc>
34 #endif
35 
36 //.........................................................................
37 namespace svt
38 {
39 //.........................................................................
40 
41     //=====================================================================
42     //= WizardPageImplData
43     //=====================================================================
44     struct WizardPageImplData
45     {
WizardPageImplDatasvt::WizardPageImplData46         WizardPageImplData()
47         {
48         }
49     };
50 
51     //=====================================================================
52     //= OWizardPage
53     //=====================================================================
54     //---------------------------------------------------------------------
OWizardPage(Window * _pParent,WinBits _nStyle)55     OWizardPage::OWizardPage( Window* _pParent, WinBits _nStyle )
56         :TabPage( _pParent, _nStyle )
57         ,m_pImpl( new WizardPageImplData )
58     {
59     }
60 
61     //---------------------------------------------------------------------
OWizardPage(Window * _pParent,const ResId & _rResId)62     OWizardPage::OWizardPage( Window* _pParent, const ResId& _rResId )
63         :TabPage( _pParent, _rResId )
64         ,m_pImpl( new WizardPageImplData )
65     {
66     }
67 
68     //---------------------------------------------------------------------
~OWizardPage()69     OWizardPage::~OWizardPage()
70     {
71         delete m_pImpl;
72     }
73 
74     //---------------------------------------------------------------------
initializePage()75     void OWizardPage::initializePage()
76     {
77     }
78 
79     //---------------------------------------------------------------------
ActivatePage()80     void OWizardPage::ActivatePage()
81     {
82         TabPage::ActivatePage();
83         updateDialogTravelUI();
84     }
85 
86     //---------------------------------------------------------------------
updateDialogTravelUI()87     void OWizardPage::updateDialogTravelUI()
88     {
89         OWizardMachine* pWizardMachine = dynamic_cast< OWizardMachine* >( GetParent() );
90         if ( pWizardMachine )
91             pWizardMachine->updateTravelUI();
92     }
93 
94     //---------------------------------------------------------------------
canAdvance() const95     bool OWizardPage::canAdvance() const
96     {
97         return true;
98     }
99 
100     //---------------------------------------------------------------------
commitPage(WizardTypes::CommitPageReason)101     sal_Bool OWizardPage::commitPage( WizardTypes::CommitPageReason )
102     {
103         return sal_True;
104     }
105 
106     //=====================================================================
107     //= WizardMachineImplData
108     //=====================================================================
109     struct WizardMachineImplData : public WizardTypes
110     {
111         String                          sTitleBase;         // the base for the title
112         ::std::stack< WizardState >     aStateHistory;      // the history of all states (used for implementing "Back")
113 
114         WizardState                     nFirstUnknownPage;
115             // the WizardDialog does not allow non-linear transitions (e.g. it's
116             // not possible to add pages in a non-linear order), so we need some own maintainance data
117 
118         sal_Bool                        m_bAutoNextButtonState;
119 
120         bool                            m_bTravelingSuspended;
121 
WizardMachineImplDatasvt::WizardMachineImplData122         WizardMachineImplData()
123             :nFirstUnknownPage( 0 )
124             ,m_bAutoNextButtonState( sal_False )
125             ,m_bTravelingSuspended( false )
126         {
127         }
128     };
129 
calcRightHelpOffset(sal_uInt32 _nButtonFlags)130     long OWizardMachine::calcRightHelpOffset(sal_uInt32 _nButtonFlags)
131     {
132         sal_Int32 nMask = 1;
133         sal_Int32 nRightAlignedButtonCount = -1;
134         for (unsigned int i = 0; i < 8*sizeof(_nButtonFlags); i++ )
135         {
136             if( ( _nButtonFlags & nMask ) != 0 )
137                 nRightAlignedButtonCount++;
138             nMask <<= 1;
139         }
140         Size aSize = GetPageSizePixel();
141         sal_Int32 nTotButtonWidth = nRightAlignedButtonCount * LogicalCoordinateToPixel(50);
142         sal_Int32 nTotRightButtonSpaceOffset = (nRightAlignedButtonCount) * WIZARDDIALOG_BUTTON_STDOFFSET_X;
143         if ((_nButtonFlags & WZB_NEXT) && (_nButtonFlags & WZB_NEXT))
144             nTotRightButtonSpaceOffset = (nTotRightButtonSpaceOffset - WIZARDDIALOG_BUTTON_STDOFFSET_X) + WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X;
145         return aSize.Width() - nTotButtonWidth - nTotRightButtonSpaceOffset;
146     }
147 
148     //=====================================================================
149     //= OWizardMachine
150     //=====================================================================
151     //---------------------------------------------------------------------
OWizardMachine(Window * _pParent,const ResId & _rRes,sal_uInt32 _nButtonFlags)152     OWizardMachine::OWizardMachine(Window* _pParent, const ResId& _rRes, sal_uInt32 _nButtonFlags )
153         :WizardDialog( _pParent, _rRes )
154         ,m_pFinish(NULL)
155         ,m_pCancel(NULL)
156         ,m_pNextPage(NULL)
157         ,m_pPrevPage(NULL)
158         ,m_pHelp(NULL)
159         ,m_pImpl( new WizardMachineImplData )
160     {
161         implConstruct( _nButtonFlags );
162     }
163 
164     //---------------------------------------------------------------------
OWizardMachine(Window * _pParent,const WinBits i_nStyle,sal_uInt32 _nButtonFlags)165     OWizardMachine::OWizardMachine(Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags )
166         :WizardDialog( _pParent, i_nStyle )
167         ,m_pFinish(NULL)
168         ,m_pCancel(NULL)
169         ,m_pNextPage(NULL)
170         ,m_pPrevPage(NULL)
171         ,m_pHelp(NULL)
172         ,m_pImpl( new WizardMachineImplData )
173     {
174         implConstruct( _nButtonFlags );
175     }
176 
177     //---------------------------------------------------------------------
implConstruct(const sal_uInt32 _nButtonFlags)178     void OWizardMachine::implConstruct( const sal_uInt32 _nButtonFlags )
179     {
180         m_pImpl->sTitleBase = GetText();
181 
182         // create the buttons according to the wizard button flags
183         // the help button
184         if (_nButtonFlags & WZB_HELP)
185         {
186             m_pHelp= new HelpButton(this, WB_TABSTOP);
187             m_pHelp->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
188             m_pHelp->Show();
189             AddButton( m_pHelp, WIZARDDIALOG_BUTTON_STDOFFSET_X);
190         }
191 
192         // the previous button
193         if (_nButtonFlags & WZB_PREVIOUS)
194         {
195             m_pPrevPage = new PushButton(this, WB_TABSTOP);
196             m_pPrevPage->SetHelpId( HID_WIZARD_PREVIOUS );
197             m_pPrevPage->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
198             m_pPrevPage->SetText(String(SvtResId(STR_WIZDLG_PREVIOUS)));
199             m_pPrevPage->Show();
200 
201             if (_nButtonFlags & WZB_NEXT)
202                 AddButton( m_pPrevPage, ( WIZARDDIALOG_BUTTON_SMALLSTDOFFSET_X) );      // half x-offset to the next button
203             else
204                 AddButton( m_pPrevPage, WIZARDDIALOG_BUTTON_STDOFFSET_X );
205             SetPrevButton( m_pPrevPage );
206             m_pPrevPage->SetClickHdl( LINK( this, OWizardMachine, OnPrevPage ) );
207         }
208 
209         // the next button
210         if (_nButtonFlags & WZB_NEXT)
211         {
212             m_pNextPage = new PushButton(this, WB_TABSTOP);
213             m_pNextPage->SetHelpId( HID_WIZARD_NEXT );
214             m_pNextPage->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
215             m_pNextPage->SetText(String(SvtResId(STR_WIZDLG_NEXT)));
216             m_pNextPage->Show();
217 
218             AddButton( m_pNextPage, WIZARDDIALOG_BUTTON_STDOFFSET_X );
219             SetNextButton( m_pNextPage );
220             m_pNextPage->SetClickHdl( LINK( this, OWizardMachine, OnNextPage ) );
221         }
222 
223         // the finish button
224         if (_nButtonFlags & WZB_FINISH)
225         {
226             m_pFinish = new OKButton(this, WB_TABSTOP);
227             m_pFinish->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
228             m_pFinish->SetText(String(SvtResId(STR_WIZDLG_FINISH)));
229             m_pFinish->Show();
230 
231             AddButton( m_pFinish, WIZARDDIALOG_BUTTON_STDOFFSET_X );
232             m_pFinish->SetClickHdl( LINK( this, OWizardMachine, OnFinish ) );
233         }
234 
235         // the cancel button
236         if (_nButtonFlags & WZB_CANCEL)
237         {
238             m_pCancel = new CancelButton(this, WB_TABSTOP);
239             m_pCancel->SetSizePixel( LogicToPixel( Size( 50, 14 ), MAP_APPFONT ) );
240             m_pCancel->Show();
241 
242             AddButton( m_pCancel, WIZARDDIALOG_BUTTON_STDOFFSET_X );
243         }
244     }
245 
246     //---------------------------------------------------------------------
~OWizardMachine()247     OWizardMachine::~OWizardMachine()
248     {
249         delete m_pFinish;
250         delete m_pCancel;
251         delete m_pNextPage;
252         delete m_pPrevPage;
253         delete m_pHelp;
254 
255         for (WizardState i=0; i<m_pImpl->nFirstUnknownPage; ++i)
256             delete GetPage(i);
257 
258         delete m_pImpl;
259     }
260 
261     //---------------------------------------------------------------------
implUpdateTitle()262     void OWizardMachine::implUpdateTitle()
263     {
264         String sCompleteTitle(m_pImpl->sTitleBase);
265 
266         // append the page title
267         TabPage* pCurrentPage = GetPage(getCurrentState());
268         if ( pCurrentPage && pCurrentPage->GetText().Len() )
269         {
270             sCompleteTitle += String::CreateFromAscii(" - ");
271             sCompleteTitle += pCurrentPage->GetText();
272         }
273 
274         SetText(sCompleteTitle);
275     }
276 
277     //---------------------------------------------------------------------
getTitleBase() const278     const String& OWizardMachine::getTitleBase() const
279     {
280         return m_pImpl->sTitleBase;
281     }
282 
283     //---------------------------------------------------------------------
setTitleBase(const String & _rTitleBase)284     void OWizardMachine::setTitleBase(const String& _rTitleBase)
285     {
286         m_pImpl->sTitleBase = _rTitleBase;
287         implUpdateTitle();
288     }
289 
290     //---------------------------------------------------------------------
GetOrCreatePage(const WizardState i_nState)291     TabPage* OWizardMachine::GetOrCreatePage( const WizardState i_nState )
292     {
293         if ( NULL == GetPage( i_nState ) )
294         {
295             TabPage* pNewPage = createPage( i_nState );
296             DBG_ASSERT( pNewPage, "OWizardMachine::GetOrCreatePage: invalid new page (NULL)!" );
297 
298             // fill up the page sequence of our base class (with dummies)
299             while ( m_pImpl->nFirstUnknownPage < i_nState )
300             {
301                 AddPage( NULL );
302                 ++m_pImpl->nFirstUnknownPage;
303             }
304 
305             if ( m_pImpl->nFirstUnknownPage == i_nState )
306             {
307                 // encountered this page number the first time
308                 AddPage( pNewPage );
309                 ++m_pImpl->nFirstUnknownPage;
310             }
311             else
312                 // already had this page - just change it
313                 SetPage( i_nState, pNewPage );
314         }
315         return GetPage( i_nState );
316     }
317 
318     //---------------------------------------------------------------------
ActivatePage()319     void OWizardMachine::ActivatePage()
320     {
321         WizardDialog::ActivatePage();
322 
323         WizardState nCurrentLevel = GetCurLevel();
324         GetOrCreatePage( nCurrentLevel );
325 
326         enterState( nCurrentLevel );
327     }
328 
329     //---------------------------------------------------------------------
DeactivatePage()330     long OWizardMachine::DeactivatePage()
331     {
332         WizardState nCurrentState = getCurrentState();
333         if (!leaveState(nCurrentState) || !WizardDialog::DeactivatePage())
334             return sal_False;
335         return sal_True;
336     }
337 
338     //---------------------------------------------------------------------
defaultButton(sal_uInt32 _nWizardButtonFlags)339     void OWizardMachine::defaultButton(sal_uInt32 _nWizardButtonFlags)
340     {
341         // the new default button
342         PushButton* pNewDefButton = NULL;
343         if (m_pFinish && (_nWizardButtonFlags & WZB_FINISH))
344             pNewDefButton = m_pFinish;
345         if (m_pNextPage && (_nWizardButtonFlags & WZB_NEXT))
346             pNewDefButton = m_pNextPage;
347         if (m_pPrevPage && (_nWizardButtonFlags & WZB_PREVIOUS))
348             pNewDefButton = m_pPrevPage;
349         if (m_pHelp && (_nWizardButtonFlags & WZB_HELP))
350             pNewDefButton = m_pHelp;
351         if (m_pCancel && (_nWizardButtonFlags & WZB_CANCEL))
352             pNewDefButton = m_pCancel;
353 
354         if ( pNewDefButton )
355             defaultButton( pNewDefButton );
356         else
357             implResetDefault( this );
358     }
359 
360     //---------------------------------------------------------------------
implResetDefault(Window * _pWindow)361     void OWizardMachine::implResetDefault(Window* _pWindow)
362     {
363         Window* pChildLoop = _pWindow->GetWindow(WINDOW_FIRSTCHILD);
364         while (pChildLoop)
365         {
366             // does the window participate in the tabbing order?
367             if (pChildLoop->GetStyle() & WB_DIALOGCONTROL)
368                 implResetDefault(pChildLoop);
369 
370             // is it a button?
371             WindowType eType = pChildLoop->GetType();
372             if  (   (WINDOW_BUTTON == eType)
373                 ||  (WINDOW_PUSHBUTTON == eType)
374                 ||  (WINDOW_OKBUTTON == eType)
375                 ||  (WINDOW_CANCELBUTTON == eType)
376                 ||  (WINDOW_HELPBUTTON == eType)
377                 ||  (WINDOW_IMAGEBUTTON == eType)
378                 ||  (WINDOW_MENUBUTTON == eType)
379                 ||  (WINDOW_MOREBUTTON == eType)
380                 )
381             {
382                 pChildLoop->SetStyle(pChildLoop->GetStyle() & ~WB_DEFBUTTON);
383             }
384 
385             // the next one ...
386             pChildLoop = pChildLoop->GetWindow(WINDOW_NEXT);
387         }
388     }
389 
390     //---------------------------------------------------------------------
defaultButton(PushButton * _pNewDefButton)391     void OWizardMachine::defaultButton(PushButton* _pNewDefButton)
392     {
393         // loop through all (direct and indirect) descendants which participate in our tabbing order, and
394         // reset the WB_DEFBUTTON for every window which is a button
395         implResetDefault(this);
396 
397         // set it's new style
398         if (_pNewDefButton)
399             _pNewDefButton->SetStyle(_pNewDefButton->GetStyle() | WB_DEFBUTTON);
400     }
401 
402     //---------------------------------------------------------------------
enableButtons(sal_uInt32 _nWizardButtonFlags,sal_Bool _bEnable)403     void OWizardMachine::enableButtons(sal_uInt32 _nWizardButtonFlags, sal_Bool _bEnable)
404     {
405         if (m_pFinish && (_nWizardButtonFlags & WZB_FINISH))
406             m_pFinish->Enable(_bEnable);
407         if (m_pNextPage && (_nWizardButtonFlags & WZB_NEXT))
408             m_pNextPage->Enable(_bEnable);
409         if (m_pPrevPage && (_nWizardButtonFlags & WZB_PREVIOUS))
410             m_pPrevPage->Enable(_bEnable);
411         if (m_pHelp && (_nWizardButtonFlags & WZB_HELP))
412             m_pHelp->Enable(_bEnable);
413         if (m_pCancel && (_nWizardButtonFlags & WZB_CANCEL))
414             m_pCancel->Enable(_bEnable);
415     }
416 
417     //---------------------------------------------------------------------
enterState(WizardState _nState)418     void OWizardMachine::enterState(WizardState _nState)
419     {
420         // tell the page
421         IWizardPageController* pController = getPageController( GetPage( _nState ) );
422         OSL_ENSURE( pController, "OWizardMachine::enterState: no controller for the given page!" );
423         if ( pController )
424             pController->initializePage();
425 
426         if ( isAutomaticNextButtonStateEnabled() )
427             enableButtons( WZB_NEXT, canAdvance() );
428 
429         enableButtons( WZB_PREVIOUS, !m_pImpl->aStateHistory.empty() );
430 
431         // set the new title - it depends on the current page (i.e. state)
432         implUpdateTitle();
433     }
434 
435     //---------------------------------------------------------------------
leaveState(WizardState)436     sal_Bool OWizardMachine::leaveState(WizardState)
437     {
438         // no need to ask the page here.
439         // If we reach this point, we already gave the current page the chance to commit it's data,
440         // and it was allowed to commit it's data
441 
442         return sal_True;
443     }
444 
445     //---------------------------------------------------------------------
onFinish()446     sal_Bool OWizardMachine::onFinish()
447     {
448         return Finnish( RET_OK );
449     }
450 
451     //---------------------------------------------------------------------
IMPL_LINK(OWizardMachine,OnFinish,PushButton *,EMPTYARG)452     IMPL_LINK(OWizardMachine, OnFinish, PushButton*, EMPTYARG)
453     {
454         if ( isTravelingSuspended() )
455             return 0;
456         WizardTravelSuspension aTravelGuard( *this );
457         if ( !prepareLeaveCurrentState( eFinish ) )
458         {
459             return 0L;
460         }
461         return onFinish() ? 1L : 0L;
462     }
463 
464     //---------------------------------------------------------------------
determineNextState(WizardState _nCurrentState) const465     OWizardMachine::WizardState OWizardMachine::determineNextState( WizardState _nCurrentState ) const
466     {
467         return _nCurrentState + 1;
468     }
469 
470     //---------------------------------------------------------------------
prepareLeaveCurrentState(CommitPageReason _eReason)471     sal_Bool OWizardMachine::prepareLeaveCurrentState( CommitPageReason _eReason )
472     {
473         IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
474         ENSURE_OR_RETURN( pController != NULL, "OWizardMachine::prepareLeaveCurrentState: no controller for the current page!", sal_True );
475         return pController->commitPage( _eReason );
476     }
477 
478     //---------------------------------------------------------------------
skipBackwardUntil(WizardState _nTargetState)479     sal_Bool OWizardMachine::skipBackwardUntil( WizardState _nTargetState )
480     {
481         // alowed to leave the current page?
482         if ( !prepareLeaveCurrentState( eTravelBackward ) )
483             return sal_False;
484 
485         // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong
486         ::std::stack< WizardState > aTravelVirtually = m_pImpl->aStateHistory;
487         ::std::stack< WizardState > aOldStateHistory = m_pImpl->aStateHistory;
488 
489         WizardState nCurrentRollbackState = getCurrentState();
490         while ( nCurrentRollbackState != _nTargetState )
491         {
492             DBG_ASSERT( !aTravelVirtually.empty(), "OWizardMachine::skipBackwardUntil: this target state does not exist in the history!" );
493             nCurrentRollbackState = aTravelVirtually.top();
494             aTravelVirtually.pop();
495         }
496         m_pImpl->aStateHistory = aTravelVirtually;
497         if ( !ShowPage( _nTargetState ) )
498         {
499             m_pImpl->aStateHistory = aOldStateHistory;
500             return sal_False;
501         }
502         return sal_True;
503     }
504 
505     //---------------------------------------------------------------------
skipUntil(WizardState _nTargetState)506     sal_Bool OWizardMachine::skipUntil( WizardState _nTargetState )
507     {
508         WizardState nCurrentState = getCurrentState();
509 
510         // alowed to leave the current page?
511         if ( !prepareLeaveCurrentState( nCurrentState < _nTargetState ? eTravelForward : eTravelBackward ) )
512             return sal_False;
513 
514         // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong
515         ::std::stack< WizardState > aTravelVirtually = m_pImpl->aStateHistory;
516         ::std::stack< WizardState > aOldStateHistory = m_pImpl->aStateHistory;
517         while ( nCurrentState != _nTargetState )
518         {
519             WizardState nNextState = determineNextState( nCurrentState );
520             if ( WZS_INVALID_STATE == nNextState )
521             {
522                 DBG_ERROR( "OWizardMachine::skipUntil: the given target state does not exist!" );
523                 return sal_False;
524             }
525 
526             // remember the skipped state in the history
527             aTravelVirtually.push( nCurrentState );
528 
529             // get the next state
530             nCurrentState = nNextState;
531         }
532         m_pImpl->aStateHistory = aTravelVirtually;
533         // show the target page
534         if ( !ShowPage( nCurrentState ) )
535         {
536             // argh! prepareLeaveCurrentPage succeeded, determineNextState succeeded,
537             // but ShowPage doesn't? Somebody behaves very strange here ....
538             DBG_ERROR( "OWizardMachine::skipUntil: very unpolite ...." );
539             m_pImpl->aStateHistory = aOldStateHistory;
540             return sal_False;
541         }
542         return sal_True;
543     }
544 
545     //---------------------------------------------------------------------
skip(sal_Int32 _nSteps)546     sal_Bool OWizardMachine::skip(sal_Int32 _nSteps)
547     {
548         DBG_ASSERT(_nSteps > 0, "OWizardMachine::skip: invalid number of steps!");
549         // alowed to leave the current page?
550         if ( !prepareLeaveCurrentState( eTravelForward ) )
551             return sal_False;
552 
553         WizardState nCurrentState = getCurrentState();
554         WizardState nNextState = determineNextState(nCurrentState);
555         // loop _nSteps steps
556         while (_nSteps-- > 0)
557         {
558             if (WZS_INVALID_STATE == nNextState)
559                 return sal_False;
560 
561             // remember the skipped state in the history
562             m_pImpl->aStateHistory.push(nCurrentState);
563 
564             // get the next state
565             nCurrentState = nNextState;
566             nNextState = determineNextState(nCurrentState);
567         }
568 
569         // show the (n+1)th page
570         if (!ShowPage(nCurrentState))
571         {
572             // TODO: this leaves us in a state where we have no current page and an inconsistent state history.
573             // Perhaps we should rollback the skipping here ....
574             DBG_ERROR("OWizardMachine::skip: very unpolite ....");
575                 // if somebody does a skip and then does not allow to leave ...
576                 // (can't be a commit error, as we've already committed the current page. So if ShowPage fails here,
577                 // somebody behaves really strange ...)
578             return sal_False;
579         }
580 
581         // all fine
582         return sal_True;
583     }
584 
585     //---------------------------------------------------------------------
travelNext()586     sal_Bool OWizardMachine::travelNext()
587     {
588         // allowed to leave the current page?
589         if ( !prepareLeaveCurrentState( eTravelForward ) )
590             return sal_False;
591 
592         // determine the next state to travel to
593         WizardState nCurrentState = getCurrentState();
594         WizardState nNextState = determineNextState(nCurrentState);
595         if (WZS_INVALID_STATE == nNextState)
596             return sal_False;
597 
598         // the state history is used by the enterState method
599         // all fine
600         m_pImpl->aStateHistory.push(nCurrentState);
601         if (!ShowPage(nNextState))
602         {
603             m_pImpl->aStateHistory.pop();
604             return sal_False;
605         }
606 
607         return sal_True;
608     }
609 
610     //---------------------------------------------------------------------
travelPrevious()611     sal_Bool OWizardMachine::travelPrevious()
612     {
613         DBG_ASSERT(m_pImpl->aStateHistory.size() > 0, "OWizardMachine::travelPrevious: have no previous page!");
614 
615         // alowed to leave the current page?
616         if ( !prepareLeaveCurrentState( eTravelBackward ) )
617             return sal_False;
618 
619         // the next state to switch to
620         WizardState nPreviousState = m_pImpl->aStateHistory.top();
621 
622         // the state history is used by the enterState method
623         m_pImpl->aStateHistory.pop();
624         // show this page
625         if (!ShowPage(nPreviousState))
626         {
627             m_pImpl->aStateHistory.push(nPreviousState);
628             return sal_False;
629         }
630 
631         // all fine
632         return sal_True;
633     }
634 
635     //---------------------------------------------------------------------
removePageFromHistory(WizardState nToRemove)636     void  OWizardMachine::removePageFromHistory( WizardState nToRemove )
637     {
638 
639         ::std::stack< WizardState > aTemp;
640         while(!m_pImpl->aStateHistory.empty())
641         {
642             WizardState nPreviousState = m_pImpl->aStateHistory.top();
643             m_pImpl->aStateHistory.pop();
644             if(nPreviousState != nToRemove)
645                 aTemp.push( nPreviousState );
646             else
647                 break;
648         }
649         while(!aTemp.empty())
650         {
651             m_pImpl->aStateHistory.push( aTemp.top() );
652             aTemp.pop();
653         }
654     }
655 
656     //---------------------------------------------------------------------
enableAutomaticNextButtonState(bool _bEnable)657     void OWizardMachine::enableAutomaticNextButtonState( bool _bEnable )
658     {
659         m_pImpl->m_bAutoNextButtonState = _bEnable;
660     }
661 
662     //---------------------------------------------------------------------
isAutomaticNextButtonStateEnabled() const663     bool OWizardMachine::isAutomaticNextButtonStateEnabled() const
664     {
665         return m_pImpl->m_bAutoNextButtonState;
666     }
667 
668     //---------------------------------------------------------------------
IMPL_LINK(OWizardMachine,OnPrevPage,PushButton *,EMPTYARG)669     IMPL_LINK(OWizardMachine, OnPrevPage, PushButton*, EMPTYARG)
670     {
671         if ( isTravelingSuspended() )
672             return 0;
673         WizardTravelSuspension aTravelGuard( *this );
674         sal_Int32 nRet = travelPrevious();
675         return nRet;
676     }
677 
678     //---------------------------------------------------------------------
IMPL_LINK(OWizardMachine,OnNextPage,PushButton *,EMPTYARG)679     IMPL_LINK(OWizardMachine, OnNextPage, PushButton*, EMPTYARG)
680     {
681         if ( isTravelingSuspended() )
682             return 0;
683         WizardTravelSuspension aTravelGuard( *this );
684         sal_Int32 nRet = travelNext();
685         return nRet;
686     }
687 
688     //---------------------------------------------------------------------
getPageController(TabPage * _pCurrentPage) const689     IWizardPageController* OWizardMachine::getPageController( TabPage* _pCurrentPage ) const
690     {
691         IWizardPageController* pController = dynamic_cast< IWizardPageController* >( _pCurrentPage );
692         return pController;
693     }
694 
695     //---------------------------------------------------------------------
getStateHistory(::std::vector<WizardState> & _out_rHistory)696     void OWizardMachine::getStateHistory( ::std::vector< WizardState >& _out_rHistory )
697     {
698         ::std::stack< WizardState > aHistoryCopy( m_pImpl->aStateHistory );
699         while ( !aHistoryCopy.empty() )
700         {
701             _out_rHistory.push_back( aHistoryCopy.top() );
702             aHistoryCopy.pop();
703         }
704     }
705 
706     //---------------------------------------------------------------------
canAdvance() const707     bool OWizardMachine::canAdvance() const
708     {
709         return WZS_INVALID_STATE != determineNextState( getCurrentState() );
710     }
711 
712     //---------------------------------------------------------------------
updateTravelUI()713     void OWizardMachine::updateTravelUI()
714     {
715         const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
716         OSL_ENSURE( pController != NULL, "RoadmapWizard::updateTravelUI: no controller for the current page!" );
717 
718         bool bCanAdvance =
719                 ( !pController || pController->canAdvance() )   // the current page allows to advance
720             &&  canAdvance();                                   // the dialog as a whole allows to advance
721         enableButtons( WZB_NEXT, bCanAdvance );
722     }
723 
724     //---------------------------------------------------------------------
isTravelingSuspended() const725     bool OWizardMachine::isTravelingSuspended() const
726     {
727         return m_pImpl->m_bTravelingSuspended;
728     }
729 
730     //---------------------------------------------------------------------
suspendTraveling(AccessGuard)731     void OWizardMachine::suspendTraveling( AccessGuard )
732     {
733         DBG_ASSERT( !m_pImpl->m_bTravelingSuspended, "OWizardMachine::suspendTraveling: already suspended!" );
734        m_pImpl->m_bTravelingSuspended = true;
735     }
736 
737     //---------------------------------------------------------------------
resumeTraveling(AccessGuard)738     void OWizardMachine::resumeTraveling( AccessGuard )
739     {
740         DBG_ASSERT( m_pImpl->m_bTravelingSuspended, "OWizardMachine::resumeTraveling: nothing to resume!" );
741        m_pImpl->m_bTravelingSuspended = false;
742     }
743 
744 //.........................................................................
745 }   // namespace svt
746 //.........................................................................
747