added sizers support; allow resizeable wizards (Robert Vazan)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@22170 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
// 1) Added capability for wxWizardPage to accept resources
|
||||
// 2) Added "Help" button handler stub
|
||||
// 3) Fixed ShowPage() bug on displaying bitmaps
|
||||
// Robert Vazan (sizers)
|
||||
// Created: 15.08.99
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
||||
@@ -41,6 +42,7 @@
|
||||
#endif //WX_PRECOMP
|
||||
|
||||
#include "wx/statline.h"
|
||||
#include "wx/sizer.h"
|
||||
|
||||
#include "wx/wizard.h"
|
||||
|
||||
@@ -132,6 +134,126 @@ wxWizardPage *wxWizardPageSimple::GetNext() const
|
||||
{
|
||||
return m_next;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxWizardSizer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxWizardSizer : public wxSizer
|
||||
{
|
||||
public:
|
||||
wxWizardSizer(wxWizard *owner);
|
||||
|
||||
void RecalcSizes();
|
||||
wxSize CalcMin();
|
||||
|
||||
wxSize GetMaxChildSize();
|
||||
int Border() const;
|
||||
|
||||
private:
|
||||
wxSize SiblingSize(wxSizerItem *child);
|
||||
|
||||
wxWizard *m_owner;
|
||||
bool m_childSizeValid;
|
||||
wxSize m_childSize;
|
||||
|
||||
DECLARE_CLASS(wxWizardSizer);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(wxWizardSizer, wxSizer)
|
||||
|
||||
wxWizardSizer::wxWizardSizer(wxWizard *owner)
|
||||
: m_owner(owner)
|
||||
{
|
||||
m_childSizeValid = false;
|
||||
}
|
||||
|
||||
void wxWizardSizer::RecalcSizes()
|
||||
{
|
||||
// Effect of this function depends on m_owner->m_page and
|
||||
// it should be called whenever it changes (wxWizard::ShowPage)
|
||||
if ( m_owner->m_page )
|
||||
{
|
||||
m_owner->m_page->SetSize(m_position.x,m_position.y, m_size.x,m_size.y);
|
||||
}
|
||||
}
|
||||
|
||||
wxSize wxWizardSizer::CalcMin()
|
||||
{
|
||||
return m_owner->GetPageSize();
|
||||
}
|
||||
|
||||
wxSize wxWizardSizer::GetMaxChildSize()
|
||||
{
|
||||
#if !defined(__WXDEBUG__)
|
||||
if ( m_childSizeValid )
|
||||
return m_childSize;
|
||||
#endif
|
||||
|
||||
wxSize maxOfMin;
|
||||
wxSizerItemList::Node *childNode;
|
||||
|
||||
for(childNode = m_children.GetFirst(); childNode;
|
||||
childNode = childNode->GetNext())
|
||||
{
|
||||
wxSizerItem *child = childNode->GetData();
|
||||
maxOfMin.IncTo(child->CalcMin());
|
||||
maxOfMin.IncTo(SiblingSize(child));
|
||||
}
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
if ( m_childSizeValid && m_childSize != maxOfMin )
|
||||
{
|
||||
wxFAIL_MSG( _T("Size changed in wxWizard::GetPageAreaSizer()")
|
||||
_T("after RunWizard().\n")
|
||||
_T("Did you forget to call GetSizer()->Fit(this) ")
|
||||
_T("for some page?")) ;
|
||||
|
||||
return m_childSize;
|
||||
}
|
||||
#endif // __WXDEBUG__
|
||||
|
||||
if ( m_owner->m_started )
|
||||
{
|
||||
m_childSizeValid = true;
|
||||
m_childSize = maxOfMin;
|
||||
}
|
||||
|
||||
return maxOfMin;
|
||||
}
|
||||
|
||||
int wxWizardSizer::Border() const
|
||||
{
|
||||
if ( m_owner->m_calledSetBorder )
|
||||
return m_owner->m_border;
|
||||
|
||||
return m_children.IsEmpty() ? 5 : 0;
|
||||
}
|
||||
|
||||
wxSize wxWizardSizer::SiblingSize(wxSizerItem *child)
|
||||
{
|
||||
wxSize maxSibling;
|
||||
|
||||
if ( child->IsWindow() )
|
||||
{
|
||||
wxWizardPage *page = wxDynamicCast(child->GetWindow(), wxWizardPage);
|
||||
if ( page )
|
||||
{
|
||||
for ( wxWizardPage *sibling = page->GetNext();
|
||||
sibling;
|
||||
sibling = sibling->GetNext() )
|
||||
{
|
||||
if ( sibling->GetSizer() )
|
||||
{
|
||||
maxSibling.IncTo(sibling->GetSizer()->CalcMin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxSibling;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// generic wxWizard implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -142,52 +264,84 @@ void wxWizard::Init()
|
||||
m_page = (wxWizardPage *)NULL;
|
||||
m_btnPrev = m_btnNext = NULL;
|
||||
m_statbmp = NULL;
|
||||
m_sizerPage = NULL;
|
||||
m_calledSetBorder = false;
|
||||
m_border = 0;
|
||||
m_started = false;
|
||||
}
|
||||
|
||||
bool wxWizard::Create(wxWindow *parent,
|
||||
int id,
|
||||
const wxString& title,
|
||||
const wxBitmap& bitmap,
|
||||
const wxPoint& pos)
|
||||
const wxPoint& pos,
|
||||
long style)
|
||||
{
|
||||
bool result = wxDialog::Create(parent,id,title,pos,wxDefaultSize,style);
|
||||
|
||||
m_posWizard = pos;
|
||||
m_bitmap = bitmap ;
|
||||
|
||||
// just create the dialog itself here, the controls will be created in
|
||||
// DoCreateControls() called later when we know our final size
|
||||
m_page = (wxWizardPage *)NULL;
|
||||
m_btnPrev = m_btnNext = NULL;
|
||||
m_statbmp = NULL;
|
||||
|
||||
return wxDialog::Create(parent, id, title, pos);
|
||||
DoCreateControls();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void wxWizard::DoCreateControls()
|
||||
void wxWizard::AddBitmapRow(wxBoxSizer *mainColumn)
|
||||
{
|
||||
// do nothing if the controls were already created
|
||||
if ( WasCreated() )
|
||||
return;
|
||||
m_sizerBmpAndPage = new wxBoxSizer(wxHORIZONTAL);
|
||||
mainColumn->Add(
|
||||
m_sizerBmpAndPage,
|
||||
1, // Vertically stretchable
|
||||
wxEXPAND // Horizonal stretching, no border
|
||||
);
|
||||
mainColumn->Add(0,5,
|
||||
0, // No vertical stretching
|
||||
wxEXPAND // No border, (mostly useless) horizontal stretching
|
||||
);
|
||||
|
||||
// constants defining the dialog layout
|
||||
// ------------------------------------
|
||||
if ( m_bitmap.Ok() )
|
||||
{
|
||||
m_statbmp = new wxStaticBitmap(this, -1, m_bitmap);
|
||||
m_sizerBmpAndPage->Add(
|
||||
m_statbmp,
|
||||
0, // No horizontal stretching
|
||||
wxALL, // Border all around, top alignment
|
||||
5 // Border width
|
||||
);
|
||||
m_sizerBmpAndPage->Add(
|
||||
5,0,
|
||||
0, // No horizontal stretching
|
||||
wxEXPAND // No border, (mostly useless) vertical stretching
|
||||
);
|
||||
}
|
||||
else
|
||||
m_statbmp = (wxStaticBitmap *)NULL;
|
||||
|
||||
// these constants define the position of the upper left corner of the
|
||||
// bitmap or the page in the wizard
|
||||
static const int X_MARGIN = 10;
|
||||
static const int Y_MARGIN = 10;
|
||||
// Added to m_sizerBmpAndPage in FinishLayout
|
||||
m_sizerPage = new wxWizardSizer(this);
|
||||
}
|
||||
|
||||
// margin between the bitmap and the panel
|
||||
static const int BITMAP_X_MARGIN = 15;
|
||||
|
||||
// margin between the bitmap and the static line
|
||||
static const int BITMAP_Y_MARGIN = 15;
|
||||
|
||||
// margin between the static line and the buttons
|
||||
static const int SEPARATOR_LINE_MARGIN = 15;
|
||||
|
||||
// margin between "Next >" and "Cancel" buttons
|
||||
static const int BUTTON_MARGIN = 10;
|
||||
void wxWizard::AddStaticLine(wxBoxSizer *mainColumn)
|
||||
{
|
||||
#if wxUSE_STATLINE
|
||||
mainColumn->Add(
|
||||
new wxStaticLine(this, -1),
|
||||
0, // Vertically unstretchable
|
||||
wxEXPAND | wxALL, // Border all around, horizontally stretchable
|
||||
5 // Border width
|
||||
);
|
||||
mainColumn->Add(0,5,
|
||||
0, // No vertical stretching
|
||||
wxEXPAND // No border, (mostly useless) horizontal stretching
|
||||
);
|
||||
#else
|
||||
(void)mainColumn;
|
||||
#endif // wxUSE_STATLINE
|
||||
}
|
||||
|
||||
void wxWizard::AddBackNextPair(wxBoxSizer *buttonRow)
|
||||
{
|
||||
// margin between Back and Next buttons
|
||||
#ifdef __WXMAC__
|
||||
static const int BACKNEXT_MARGIN = 10;
|
||||
@@ -195,122 +349,109 @@ void wxWizard::DoCreateControls()
|
||||
static const int BACKNEXT_MARGIN = 0;
|
||||
#endif
|
||||
|
||||
// default width and height of the page
|
||||
static const int DEFAULT_PAGE_WIDTH = 270;
|
||||
static const int DEFAULT_PAGE_HEIGHT = 290;
|
||||
wxBoxSizer *backNextPair = new wxBoxSizer(wxHORIZONTAL);
|
||||
buttonRow->Add(
|
||||
backNextPair,
|
||||
0, // No horizontal stretching
|
||||
wxALL, // Border all around
|
||||
5 // Border width
|
||||
);
|
||||
|
||||
m_btnPrev = new wxButton(this, wxID_BACKWARD, _("< &Back"));
|
||||
backNextPair->Add(m_btnPrev);
|
||||
backNextPair->Add(BACKNEXT_MARGIN,0,
|
||||
0, // No horizontal stretching
|
||||
wxEXPAND // No border, (mostly useless) vertical stretching
|
||||
);
|
||||
m_btnNext = new wxButton(this, wxID_FORWARD, _("&Next >"));
|
||||
backNextPair->Add(m_btnNext);
|
||||
}
|
||||
|
||||
// create controls
|
||||
// ---------------
|
||||
|
||||
wxSize sizeBtn = wxButton::GetDefaultSize();
|
||||
|
||||
// the global dialog layout is: a row of buttons at the bottom (aligned to
|
||||
// the right), the static line above them, the bitmap (if any) on the left
|
||||
// of the upper part of the dialog and the panel in the remaining space
|
||||
m_x = X_MARGIN;
|
||||
m_y = Y_MARGIN;
|
||||
|
||||
int defaultHeight;
|
||||
if ( m_bitmap.Ok() )
|
||||
{
|
||||
m_statbmp = new wxStaticBitmap(this, -1, m_bitmap, wxPoint(m_x, m_y));
|
||||
|
||||
m_x += m_bitmap.GetWidth() + BITMAP_X_MARGIN;
|
||||
|
||||
defaultHeight = m_bitmap.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_statbmp = (wxStaticBitmap *)NULL;
|
||||
|
||||
defaultHeight = DEFAULT_PAGE_HEIGHT;
|
||||
}
|
||||
|
||||
// use default size if none given and also make sure that the dialog is
|
||||
// not less than the default size
|
||||
m_height = m_sizePage.y == -1 ? defaultHeight : m_sizePage.y;
|
||||
m_width = m_sizePage.x == -1 ? DEFAULT_PAGE_WIDTH : m_sizePage.x;
|
||||
if ( m_height < defaultHeight )
|
||||
m_height = defaultHeight;
|
||||
if ( m_width < DEFAULT_PAGE_WIDTH )
|
||||
m_width = DEFAULT_PAGE_WIDTH;
|
||||
|
||||
int x = X_MARGIN;
|
||||
int y = m_y + m_height + BITMAP_Y_MARGIN;
|
||||
|
||||
#if wxUSE_STATLINE
|
||||
(void)new wxStaticLine(this, -1, wxPoint(x, y),
|
||||
wxSize(m_x + m_width - x, 2));
|
||||
#endif // wxUSE_STATLINE
|
||||
|
||||
x = m_x + m_width - 3*sizeBtn.x - BUTTON_MARGIN - BACKNEXT_MARGIN;
|
||||
y += SEPARATOR_LINE_MARGIN;
|
||||
void wxWizard::AddButtonRow(wxBoxSizer *mainColumn)
|
||||
{
|
||||
wxBoxSizer *buttonRow = new wxBoxSizer(wxHORIZONTAL);
|
||||
mainColumn->Add(
|
||||
buttonRow,
|
||||
0, // Vertically unstretchable
|
||||
wxALIGN_RIGHT // Right aligned, no border
|
||||
);
|
||||
|
||||
if (GetExtraStyle() & wxWIZARD_EX_HELPBUTTON)
|
||||
{
|
||||
x -= sizeBtn.x;
|
||||
x -= BUTTON_MARGIN ;
|
||||
buttonRow->Add(
|
||||
new wxButton(this, wxID_HELP, _("&Help")),
|
||||
0, // Horizontally unstretchable
|
||||
wxALL, // Border all around, top aligned
|
||||
5 // Border width
|
||||
);
|
||||
|
||||
(void)new wxButton(this, wxID_HELP, _("&Help"), wxPoint(x, y), sizeBtn);
|
||||
x += sizeBtn.x;
|
||||
x += BUTTON_MARGIN ;
|
||||
}
|
||||
AddBackNextPair(buttonRow);
|
||||
|
||||
buttonRow->Add(
|
||||
new wxButton(this, wxID_CANCEL, _("&Cancel")),
|
||||
0, // Horizontally unstretchable
|
||||
wxALL, // Border all around, top aligned
|
||||
5 // Border width
|
||||
);
|
||||
}
|
||||
|
||||
m_btnPrev = new wxButton(this, wxID_BACKWARD, _("< &Back"), wxPoint(x, y), sizeBtn);
|
||||
|
||||
x += sizeBtn.x;
|
||||
x += BACKNEXT_MARGIN;
|
||||
|
||||
m_btnNext = new wxButton(this, wxID_FORWARD, _("&Next >"), wxPoint(x, y), sizeBtn);
|
||||
|
||||
x += sizeBtn.x + BUTTON_MARGIN;
|
||||
(void)new wxButton(this, wxID_CANCEL, _("&Cancel"), wxPoint(x, y), sizeBtn);
|
||||
|
||||
// position and size the dialog
|
||||
// ----------------------------
|
||||
|
||||
SetClientSize(m_x + m_width + X_MARGIN,
|
||||
m_y + m_height + BITMAP_Y_MARGIN +
|
||||
SEPARATOR_LINE_MARGIN + sizeBtn.y + Y_MARGIN);
|
||||
|
||||
if ( m_posWizard == wxDefaultPosition )
|
||||
{
|
||||
CentreOnScreen();
|
||||
}
|
||||
void wxWizard::DoCreateControls()
|
||||
{
|
||||
// do nothing if the controls were already created
|
||||
if ( WasCreated() )
|
||||
return;
|
||||
|
||||
// wxWindow::SetSizer will be called at end
|
||||
wxBoxSizer *windowSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxBoxSizer *mainColumn = new wxBoxSizer(wxVERTICAL);
|
||||
windowSizer->Add(
|
||||
mainColumn,
|
||||
1, // Vertical stretching
|
||||
wxALL | wxEXPAND, // Border all around, horizontal stretching
|
||||
5 // Border width
|
||||
);
|
||||
|
||||
AddBitmapRow(mainColumn);
|
||||
AddStaticLine(mainColumn);
|
||||
AddButtonRow(mainColumn);
|
||||
|
||||
// wxWindow::SetSizer should be followed by wxWindow::Fit, but
|
||||
// this is done in FinishLayout anyway so why duplicate it
|
||||
SetSizer(windowSizer);
|
||||
}
|
||||
|
||||
void wxWizard::SetPageSize(const wxSize& size)
|
||||
{
|
||||
// otherwise it will have no effect now as it's too late...
|
||||
wxASSERT_MSG( !WasCreated(), _T("should be called before RunWizard()!") );
|
||||
|
||||
wxCHECK_RET(!m_started,wxT("wxWizard::SetPageSize after RunWizard"));
|
||||
m_sizePage = size;
|
||||
}
|
||||
|
||||
void wxWizard::FinishLayout()
|
||||
{
|
||||
m_sizerBmpAndPage->Add(
|
||||
m_sizerPage,
|
||||
1, // Horizontal stretching
|
||||
wxEXPAND | wxALL, // Vertically stretchable
|
||||
m_sizerPage->Border()
|
||||
);
|
||||
|
||||
GetSizer()->SetSizeHints(this);
|
||||
if ( m_posWizard == wxDefaultPosition )
|
||||
CentreOnScreen();
|
||||
}
|
||||
|
||||
void wxWizard::FitToPage(const wxWizardPage *page)
|
||||
{
|
||||
// otherwise it will have no effect now as it's too late...
|
||||
wxASSERT_MSG( !WasCreated(), _T("should be called before RunWizard()!") );
|
||||
|
||||
wxSize sizeMax;
|
||||
wxCHECK_RET(!m_started,wxT("wxWizard::FitToPage after RunWizard"));
|
||||
|
||||
while ( page )
|
||||
{
|
||||
wxSize size = page->GetBestSize();
|
||||
|
||||
if ( size.x > sizeMax.x )
|
||||
sizeMax.x = size.x;
|
||||
|
||||
if ( size.y > sizeMax.y )
|
||||
sizeMax.y = size.y;
|
||||
m_sizePage.IncTo(size);
|
||||
|
||||
page = page->GetNext();
|
||||
}
|
||||
|
||||
if ( sizeMax.x > m_sizePage.x )
|
||||
m_sizePage.x = sizeMax.x;
|
||||
|
||||
if ( sizeMax.y > m_sizePage.y )
|
||||
m_sizePage.y = sizeMax.y;
|
||||
}
|
||||
|
||||
bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
|
||||
@@ -373,7 +514,9 @@ bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
|
||||
|
||||
// position and show the new page
|
||||
(void)m_page->TransferDataToWindow();
|
||||
m_page->SetSize(m_x, m_y, m_width, m_height);
|
||||
|
||||
// wxWizardSizer::RecalcSizes wants to be called when m_page changes
|
||||
m_sizerPage->RecalcSizes();
|
||||
|
||||
// check if bitmap needs to be updated
|
||||
// update default flag as well
|
||||
@@ -425,9 +568,14 @@ bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
|
||||
bool wxWizard::RunWizard(wxWizardPage *firstPage)
|
||||
{
|
||||
wxCHECK_MSG( firstPage, FALSE, wxT("can't run empty wizard") );
|
||||
|
||||
DoCreateControls();
|
||||
|
||||
|
||||
// Set before FinishLayout to enable wxWizardSizer::GetMaxChildSize
|
||||
m_started = true;
|
||||
|
||||
// This cannot be done sooner, because user can change layout options
|
||||
// up to this moment
|
||||
FinishLayout();
|
||||
|
||||
// can't return FALSE here because there is no old page
|
||||
(void)ShowPage(firstPage, TRUE /* forward */);
|
||||
|
||||
@@ -441,11 +589,37 @@ wxWizardPage *wxWizard::GetCurrentPage() const
|
||||
|
||||
wxSize wxWizard::GetPageSize() const
|
||||
{
|
||||
// make sure that the controls are created because otherwise m_width and
|
||||
// m_height would be both still -1
|
||||
wxConstCast(this, wxWizard)->DoCreateControls();
|
||||
wxSize pageSize(GetManualPageSize());
|
||||
pageSize.IncTo(m_sizerPage->GetMaxChildSize());
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
return wxSize(m_width, m_height);
|
||||
wxSizer *wxWizard::GetPageAreaSizer() const
|
||||
{
|
||||
return m_sizerPage;
|
||||
}
|
||||
|
||||
void wxWizard::SetBorder(int border)
|
||||
{
|
||||
wxCHECK_RET(!m_started,wxT("wxWizard::SetBorder after RunWizard"));
|
||||
m_calledSetBorder = true;
|
||||
m_border = border;
|
||||
}
|
||||
|
||||
wxSize wxWizard::GetManualPageSize() const
|
||||
{
|
||||
// default width and height of the page
|
||||
static const int DEFAULT_PAGE_WIDTH = 270;
|
||||
static const int DEFAULT_PAGE_HEIGHT = 290;
|
||||
|
||||
wxSize totalPageSize(DEFAULT_PAGE_WIDTH,DEFAULT_PAGE_HEIGHT);
|
||||
|
||||
totalPageSize.IncTo(m_sizePage);
|
||||
|
||||
if(m_statbmp)
|
||||
totalPageSize.IncTo(wxSize(0,m_bitmap.GetHeight()));
|
||||
|
||||
return totalPageSize;
|
||||
}
|
||||
|
||||
void wxWizard::OnCancel(wxCommandEvent& WXUNUSED(eventUnused))
|
||||
|
Reference in New Issue
Block a user