You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
720 lines
19 KiB
720 lines
19 KiB
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include <vgui/IVGui.h>
|
|
#include <KeyValues.h>
|
|
|
|
#include <vgui_controls/BuildGroup.h>
|
|
#include <vgui_controls/Button.h>
|
|
#include <vgui_controls/Controls.h>
|
|
#include <vgui_controls/WizardPanel.h>
|
|
#include <vgui_controls/WizardSubPanel.h>
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
using namespace vgui;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Constructor
|
|
//-----------------------------------------------------------------------------
|
|
WizardPanel::WizardPanel(Panel *parent, const char *panelName) : Frame(parent, panelName)
|
|
{
|
|
_currentSubPanel = NULL;
|
|
_currentData = new KeyValues("WizardData");
|
|
_showButtons = true;
|
|
|
|
|
|
SetSizeable(false);
|
|
|
|
CreateButtons();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Destructor
|
|
//-----------------------------------------------------------------------------
|
|
WizardPanel::~WizardPanel()
|
|
{
|
|
if (_currentData)
|
|
{
|
|
_currentData->deleteThis();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::PerformLayout()
|
|
{
|
|
BaseClass::PerformLayout();
|
|
|
|
// resize the sub panel to fit in the Client area
|
|
int x, y, wide, tall;
|
|
GetClientArea(x, y, wide, tall);
|
|
|
|
if (_currentSubPanel && _currentSubPanel->isNonWizardPanel())
|
|
{
|
|
// just have the subpanel cover the full size
|
|
_currentSubPanel->SetBounds(x, y, wide, tall);
|
|
_cancelButton->SetVisible(false);
|
|
_prevButton->SetVisible(false);
|
|
_nextButton->SetVisible(false);
|
|
_finishButton->SetVisible(false);
|
|
}
|
|
else
|
|
{
|
|
// make room for the buttons at bottom
|
|
if (_currentSubPanel)
|
|
{
|
|
if( _showButtons )
|
|
{
|
|
_currentSubPanel->SetBounds(x, y, wide, tall - 35);
|
|
}
|
|
else
|
|
{
|
|
_currentSubPanel->SetBounds(x, y, wide, tall);
|
|
}
|
|
}
|
|
|
|
// align the buttons to the right hand side
|
|
GetSize(wide, tall);
|
|
|
|
|
|
int bwide, btall;
|
|
_cancelButton->GetSize(bwide, btall);
|
|
|
|
x = wide - (20 + bwide);
|
|
y = tall - (12 + btall);
|
|
|
|
_cancelButton->SetPos(x, y);
|
|
x -= (20 + bwide);
|
|
|
|
// only display one of the next or finish buttons (and only if both are visible)
|
|
if ( _showButtons )
|
|
{
|
|
if (_finishButton->IsEnabled() )
|
|
{
|
|
_nextButton->SetVisible(false);
|
|
_finishButton->SetVisible(true);
|
|
_finishButton->SetPos(x, y);
|
|
}
|
|
else
|
|
{
|
|
_nextButton->SetVisible(true);
|
|
_finishButton->SetVisible(false);
|
|
_nextButton->SetPos(x, y);
|
|
}
|
|
}
|
|
|
|
x -= (1 + bwide);
|
|
_prevButton->SetPos(x, y);
|
|
|
|
ResetDefaultButton();
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: if we don't show buttons then let the sub panel occupy the whole screen
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::GetClientArea(int &x, int &y, int &wide, int &tall)
|
|
{
|
|
if( _showButtons )
|
|
{
|
|
BaseClass::GetClientArea( x, y, wide, tall );
|
|
}
|
|
else
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
GetSize( wide, tall );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ApplySchemeSettings(IScheme *pScheme)
|
|
{
|
|
BaseClass::ApplySchemeSettings(pScheme);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::Run(WizardSubPanel *startPanel)
|
|
{
|
|
// skip over sub panels if they don't want to be displayed
|
|
startPanel = FindNextValidSubPanel(startPanel);
|
|
|
|
// show it
|
|
ActivateNextSubPanel(startPanel);
|
|
|
|
// make sure we're set up and Run the first panel
|
|
Activate();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ActivateBuildMode()
|
|
{
|
|
// no subpanel, no build mode
|
|
if (!_currentSubPanel)
|
|
return;
|
|
|
|
_currentSubPanel->ActivateBuildMode();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ResetDefaultButton()
|
|
{
|
|
// work out which is the default button
|
|
if (_nextButton->IsEnabled())
|
|
{
|
|
_nextButton->SetAsDefaultButton(true);
|
|
}
|
|
else if (_finishButton->IsEnabled())
|
|
{
|
|
_finishButton->SetAsDefaultButton(true);
|
|
}
|
|
else if (_prevButton->IsEnabled())
|
|
{
|
|
_prevButton->SetAsDefaultButton(true);
|
|
}
|
|
/* Don't ever set the cancel button as the default, as it is too easy for users to quit the wizard without realizing
|
|
else if (_cancelButton->IsEnabled())
|
|
{
|
|
_cancelButton->SetAsDefaultButton(true);
|
|
}
|
|
*/
|
|
|
|
// reset them all (this may not be necessary)
|
|
_nextButton->InvalidateLayout();
|
|
_prevButton->InvalidateLayout();
|
|
_cancelButton->InvalidateLayout();
|
|
_finishButton->InvalidateLayout();
|
|
|
|
Repaint();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ResetKeyFocus()
|
|
{
|
|
// set the focus on the default
|
|
FocusNavGroup &navGroup = GetFocusNavGroup();
|
|
Panel *def = navGroup.GetDefaultPanel();
|
|
if (def)
|
|
{
|
|
if (def->IsEnabled() && def->IsVisible())
|
|
{
|
|
def->RequestFocus();
|
|
}
|
|
else
|
|
{
|
|
def->RequestFocusNext();
|
|
}
|
|
}
|
|
|
|
ResetDefaultButton();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::CreateButtons()
|
|
{
|
|
_prevButton = new Button(this, "PrevButton", "");
|
|
_nextButton = new Button(this, "NextButton", "");
|
|
_cancelButton = new Button(this, "CancelButton", "");
|
|
_finishButton = new Button(this, "FinishButton", "");
|
|
|
|
_prevButton->SetCommand(new KeyValues("PrevButton"));
|
|
_nextButton->SetCommand(new KeyValues("NextButton"));
|
|
_cancelButton->SetCommand(new KeyValues("CancelButton"));
|
|
_finishButton->SetCommand(new KeyValues("FinishButton"));
|
|
|
|
SetNextButtonText(NULL);
|
|
SetPrevButtonText(NULL);
|
|
SetFinishButtonText(NULL);
|
|
SetCancelButtonText(NULL);
|
|
|
|
_prevButton->SetSize(82, 24);
|
|
_nextButton->SetSize(82, 24);
|
|
_cancelButton->SetSize(82, 24);
|
|
_finishButton->SetSize(82, 24);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: clears all previous history
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ResetHistory()
|
|
{
|
|
_subPanelStack.RemoveAll();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ActivateNextSubPanel(WizardSubPanel *subPanel)
|
|
{
|
|
// get rid of previous panel
|
|
WizardSubPanel *prevPanel = _currentSubPanel;
|
|
if (prevPanel && prevPanel->ShouldDisplayPanel())
|
|
{
|
|
// hide
|
|
prevPanel->SetVisible(false);
|
|
|
|
// push onto history stack
|
|
_subPanelStack.AddElement(_currentSubPanel);
|
|
}
|
|
|
|
// reenable all buttons, returning them to their default state
|
|
_prevButton->SetEnabled(true);
|
|
_nextButton->SetEnabled(true);
|
|
_cancelButton->SetEnabled(true);
|
|
_finishButton->SetEnabled(true);
|
|
if ( _showButtons )
|
|
{
|
|
_prevButton->SetVisible(true);
|
|
_cancelButton->SetVisible(true);
|
|
}
|
|
|
|
// set up new subpanel
|
|
_currentSubPanel = subPanel;
|
|
_currentSubPanel->SetParent(this);
|
|
_currentSubPanel->SetVisible(true);
|
|
|
|
_currentSubPanel->SetWizardPanel(this);
|
|
_currentSubPanel->OnDisplayAsNext();
|
|
_currentSubPanel->OnDisplay();
|
|
_currentSubPanel->InvalidateLayout(false);
|
|
|
|
SETUP_PANEL( _currentSubPanel );
|
|
int wide, tall;
|
|
if ( _currentSubPanel->GetDesiredSize(wide, tall) )
|
|
{
|
|
SetSize(wide, tall);
|
|
}
|
|
|
|
if (!prevPanel)
|
|
{
|
|
// no previous panel, so disable the back button
|
|
_prevButton->SetEnabled(false);
|
|
}
|
|
|
|
_currentSubPanel->RequestFocus();
|
|
|
|
RecalculateTabOrdering();
|
|
InvalidateLayout(false);
|
|
Repaint();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Pops the last panel off the stack and runs it
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ActivatePrevSubPanel()
|
|
{
|
|
_currentSubPanel->SetVisible(false);
|
|
|
|
WizardSubPanel *prevPanel = NULL;
|
|
if (_subPanelStack.GetCount())
|
|
{
|
|
// check to see if we need to jump back to a previous sub panel
|
|
WizardSubPanel *searchPanel = _currentSubPanel->GetPrevSubPanel();
|
|
if (searchPanel && _subPanelStack.HasElement(searchPanel))
|
|
{
|
|
// keep poping the stack till we find it
|
|
while (_subPanelStack.GetCount() && prevPanel != searchPanel)
|
|
{
|
|
prevPanel = _subPanelStack[_subPanelStack.GetCount() - 1];
|
|
_subPanelStack.RemoveElementAt(_subPanelStack.GetCount() - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// just get the last one
|
|
prevPanel = _subPanelStack[_subPanelStack.GetCount() - 1];
|
|
_subPanelStack.RemoveElementAt(_subPanelStack.GetCount() - 1);
|
|
}
|
|
}
|
|
|
|
if (!prevPanel)
|
|
{
|
|
ivgui()->DPrintf2("Error: WizardPanel::ActivatePrevSubPanel(): no previous panel to go back to\n");
|
|
return;
|
|
}
|
|
|
|
// hide old panel
|
|
_currentSubPanel->SetVisible(false);
|
|
|
|
// reenable all buttons, returning them to their default state
|
|
_prevButton->SetEnabled(true);
|
|
_nextButton->SetEnabled(true);
|
|
_cancelButton->SetEnabled(true);
|
|
_finishButton->SetEnabled(true);
|
|
|
|
// Activate new panel
|
|
_currentSubPanel = prevPanel;
|
|
_currentSubPanel->RequestFocus();
|
|
_currentSubPanel->SetWizardPanel(this);
|
|
_currentSubPanel->OnDisplayAsPrev();
|
|
_currentSubPanel->OnDisplay();
|
|
_currentSubPanel->InvalidateLayout(false);
|
|
|
|
SETUP_PANEL( _currentSubPanel );
|
|
int wide, tall;
|
|
if ( _currentSubPanel->GetDesiredSize(wide, tall) )
|
|
{
|
|
SetSize(wide, tall);
|
|
}
|
|
|
|
// show the previous panel, but don't Activate it (since it should show just what it was previously)
|
|
_currentSubPanel->SetVisible(true);
|
|
|
|
if (!_subPanelStack.GetCount())
|
|
{
|
|
// no previous panel, so disable the back button
|
|
_prevButton->SetEnabled(false);
|
|
}
|
|
|
|
RecalculateTabOrdering();
|
|
InvalidateLayout(false);
|
|
Repaint();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Sets up the new tab ordering
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::RecalculateTabOrdering()
|
|
{
|
|
if (_currentSubPanel)
|
|
{
|
|
_currentSubPanel->SetTabPosition(1);
|
|
}
|
|
_prevButton->SetTabPosition(2);
|
|
_nextButton->SetTabPosition(3);
|
|
_finishButton->SetTabPosition(4);
|
|
_cancelButton->SetTabPosition(5);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetNextButtonEnabled(bool state)
|
|
{
|
|
if (_nextButton->IsEnabled() != state)
|
|
{
|
|
_nextButton->SetEnabled(state);
|
|
InvalidateLayout(false);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetPrevButtonEnabled(bool state)
|
|
{
|
|
if (_prevButton->IsEnabled() != state)
|
|
{
|
|
_prevButton->SetEnabled(state);
|
|
InvalidateLayout(false);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetFinishButtonEnabled(bool state)
|
|
{
|
|
if (_finishButton->IsEnabled() != state)
|
|
{
|
|
_finishButton->SetEnabled(state);
|
|
InvalidateLayout(false);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetCancelButtonEnabled(bool state)
|
|
{
|
|
if (_cancelButton->IsEnabled() != state)
|
|
{
|
|
_cancelButton->SetEnabled(state);
|
|
InvalidateLayout(false);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetNextButtonVisible(bool state)
|
|
{
|
|
_nextButton->SetVisible(state);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetPrevButtonVisible(bool state)
|
|
{
|
|
_prevButton->SetVisible(state);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetFinishButtonVisible(bool state)
|
|
{
|
|
_finishButton->SetVisible(state);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetCancelButtonVisible(bool state)
|
|
{
|
|
_cancelButton->SetVisible(state);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetNextButtonText(const char *text)
|
|
{
|
|
if (text)
|
|
{
|
|
_nextButton->SetText(text);
|
|
}
|
|
else
|
|
{
|
|
_nextButton->SetText("#WizardPanel_Next");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetPrevButtonText(const char *text)
|
|
{
|
|
if (text)
|
|
{
|
|
_prevButton->SetText(text);
|
|
}
|
|
else
|
|
{
|
|
_prevButton->SetText("#WizardPanel_Back");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetFinishButtonText(const char *text)
|
|
{
|
|
if (text)
|
|
{
|
|
_finishButton->SetText(text);
|
|
}
|
|
else
|
|
{
|
|
_finishButton->SetText("#WizardPanel_Finish");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::SetCancelButtonText(const char *text)
|
|
{
|
|
if (text)
|
|
{
|
|
_cancelButton->SetText(text);
|
|
}
|
|
else
|
|
{
|
|
_cancelButton->SetText("#WizardPanel_Cancel");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Finds the next panel that wants to be shown
|
|
//-----------------------------------------------------------------------------
|
|
WizardSubPanel *WizardPanel::FindNextValidSubPanel(WizardSubPanel *currentPanel)
|
|
{
|
|
// skip over sub panels if they don't want to be displayed
|
|
while (currentPanel)
|
|
{
|
|
currentPanel->SetWizardPanel(this);
|
|
if (currentPanel->ShouldDisplayPanel())
|
|
break;
|
|
|
|
// ok the panel wants to be skipped, so skip ahead
|
|
currentPanel = currentPanel->GetNextSubPanel();
|
|
}
|
|
|
|
return currentPanel;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Advances to the next panel
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::OnNextButton()
|
|
{
|
|
if (_currentSubPanel)
|
|
{
|
|
bool shouldAdvance = _currentSubPanel->OnNextButton();
|
|
if (shouldAdvance)
|
|
{
|
|
WizardSubPanel *nextPanel = FindNextValidSubPanel(_currentSubPanel->GetNextSubPanel());
|
|
|
|
if (nextPanel)
|
|
{
|
|
KeyValues *kv = new KeyValues("ActivateNextSubPanel");
|
|
kv->SetPtr("panel", nextPanel);
|
|
ivgui()->PostMessage(GetVPanel(), kv, GetVPanel());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Retreats to the previous panel
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::OnPrevButton()
|
|
{
|
|
bool shouldRetreat = true;
|
|
if (_currentSubPanel)
|
|
{
|
|
shouldRetreat = _currentSubPanel->OnPrevButton();
|
|
}
|
|
|
|
if (shouldRetreat)
|
|
{
|
|
ActivatePrevSubPanel();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::OnFinishButton()
|
|
{
|
|
if (_currentSubPanel && _currentSubPanel->OnFinishButton())
|
|
{
|
|
// hide ourselves away
|
|
BaseClass::OnClose();
|
|
|
|
// automatically delete ourselves if marked to do so
|
|
if (IsAutoDeleteSet())
|
|
{
|
|
MarkForDeletion();
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::OnCancelButton()
|
|
{
|
|
if (_currentSubPanel && _currentSubPanel->OnCancelButton())
|
|
{
|
|
// hide ourselves away
|
|
BaseClass::OnClose();
|
|
if (IsAutoDeleteSet())
|
|
{
|
|
MarkForDeletion();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: command handler for catching escape key presses
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::OnCommand(const char *command)
|
|
{
|
|
if (!stricmp(command, "Cancel"))
|
|
{
|
|
if (_cancelButton->IsEnabled())
|
|
{
|
|
_cancelButton->DoClick();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BaseClass::OnCommand(command);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Maps close button to cancel button
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::OnClose()
|
|
{
|
|
if (_cancelButton->IsEnabled())
|
|
{
|
|
_cancelButton->DoClick();
|
|
}
|
|
else if (_finishButton->IsEnabled())
|
|
{
|
|
_finishButton->DoClick();
|
|
}
|
|
|
|
// don't chain back
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
KeyValues *WizardPanel::GetWizardData()
|
|
{
|
|
return _currentData;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: whether to show the next,prev,finish and cancel buttons
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::ShowButtons(bool state)
|
|
{
|
|
_showButtons = state; // hide the wizard panel buttons
|
|
SetNextButtonVisible( state );
|
|
SetPrevButtonVisible( state );
|
|
SetFinishButtonVisible( state );
|
|
SetCancelButtonVisible( state );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: filters close buttons
|
|
//-----------------------------------------------------------------------------
|
|
void WizardPanel::OnCloseFrameButtonPressed()
|
|
{
|
|
// only allow close if the cancel button is enabled
|
|
if (_cancelButton->IsEnabled())
|
|
{
|
|
BaseClass::OnCloseFrameButtonPressed();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: returns a page by name
|
|
//-----------------------------------------------------------------------------
|
|
WizardSubPanel *WizardPanel::GetSubPanelByName(const char *pageName)
|
|
{
|
|
return dynamic_cast<WizardSubPanel *>(FindChildByName(pageName));
|
|
}
|