wizard.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 860 行 · 第 1/2 页

CPP
860
字号
#ifndef __WXMAC__
    if (GetExtraStyle() & wxWIZARD_EX_HELPBUTTON)
        btnHelp=new wxButton(this, wxID_HELP, _("&Help"), wxDefaultPosition, wxDefaultSize, buttonStyle);
#endif
    m_btnPrev = new wxButton(this, wxID_BACKWARD, _("< &Back"), wxDefaultPosition, wxDefaultSize, buttonStyle);

    if (btnHelp)
    {
        buttonRow->Add(
            btnHelp,
            0, // Horizontally unstretchable
            wxALL, // Border all around, top aligned
            5 // Border width
            );
#ifdef __WXMAC__
        // Put stretchable space between help button and others
        buttonRow->Add(0, 0, 1, wxALIGN_CENTRE, 0);
#endif
    }

    AddBackNextPair(buttonRow);

    buttonRow->Add(
        btnCancel,
        0, // Horizontally unstretchable
        wxALL, // Border all around, top aligned
        5 // Border width
    );
}

void wxWizard::DoCreateControls()
{
    // do nothing if the controls were already created
    if ( WasCreated() )
        return;

    bool isPda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
    
    // Horizontal stretching, and if not PDA, border all around
    int mainColumnSizerFlags = isPda ? wxEXPAND : wxALL|wxEXPAND ;
    
    // wxWindow::SetSizer will be called at end
    wxBoxSizer *windowSizer = new wxBoxSizer(wxVERTICAL);

    wxBoxSizer *mainColumn = new wxBoxSizer(wxVERTICAL);
    windowSizer->Add(
        mainColumn,
        1, // Vertical stretching
        mainColumnSizerFlags,
        5 // Border width
    );

    AddBitmapRow(mainColumn);
    
    if (!isPda)
        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)
{
    wxCHECK_RET(!m_started,wxT("wxWizard::SetPageSize after RunWizard"));
    m_sizePage = size;
}

void wxWizard::FinishLayout()
{
    bool isPda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
    
    // Set to enable wxWizardSizer::GetMaxChildSize
    m_started = true;

    m_sizerBmpAndPage->Add(
        m_sizerPage,
        1, // Horizontal stretching
        wxEXPAND | wxALL, // Vertically stretchable
        m_sizerPage->Border()
    );

    if (!isPda)
    {
        GetSizer()->SetSizeHints(this);
        if ( m_posWizard == wxDefaultPosition )
            CentreOnScreen();
    }
}

void wxWizard::FitToPage(const wxWizardPage *page)
{
    wxCHECK_RET(!m_started,wxT("wxWizard::FitToPage after RunWizard"));

    while ( page )
    {
        wxSize size = page->GetBestSize();

        m_sizePage.IncTo(size);

        page = page->GetNext();
    }
}

bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
{
    wxASSERT_MSG( page != m_page, wxT("this is useless") );

    // we'll use this to decide whether we have to change the label of this
    // button or not (initially the label is "Next")
    bool btnLabelWasNext = true;

    // Modified 10-20-2001 Robert Cavanaugh.
    // Fixed bug for displaying a new bitmap
    // in each *consecutive* page

    // flag to indicate if this page uses a new bitmap
    bool bmpIsDefault = true;

    // use these labels to determine if we need to change the bitmap
    // for this page
    wxBitmap bmpPrev, bmpCur;

    // check for previous page
    if ( m_page )
    {
        // send the event to the old page
        wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGING, GetId(), goingForward, m_page);
        if ( m_page->GetEventHandler()->ProcessEvent(event) &&
             !event.IsAllowed() )
        {
            // vetoed by the page
            return false;
        }

        m_page->Hide();

        btnLabelWasNext = HasNextPage(m_page);

        // Get the bitmap of the previous page (if it exists)
        if ( m_page->GetBitmap().Ok() )
        {
            bmpPrev = m_page->GetBitmap();
        }
    }

    // set the new page
    m_page = page;

    // is this the end?
    if ( !m_page )
    {
        // terminate successfully
        if(IsModal())
        {
            EndModal(wxID_OK);
        }
        else
        {
            SetReturnCode(wxID_OK);
            Hide();
        }

        // and notify the user code (this is especially useful for modeless
        // wizards)
        wxWizardEvent event(wxEVT_WIZARD_FINISHED, GetId(), false, 0);
        (void)GetEventHandler()->ProcessEvent(event);

        return true;
    }

    // position and show the new page
    (void)m_page->TransferDataToWindow();

    // 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
    if ( m_page->GetBitmap().Ok() )
    {
        bmpCur = m_page->GetBitmap();
        bmpIsDefault = false;
    }

#if wxUSE_STATBMP
    // change the bitmap if:
    // 1) a default bitmap was selected in constructor
    // 2) this page was constructed with a bitmap
    // 3) this bitmap is not the previous bitmap
    if ( m_statbmp && (bmpCur != bmpPrev) )
    {
        wxBitmap bmp;
        if ( bmpIsDefault )
            bmp = m_bitmap;
        else
            bmp = m_page->GetBitmap();
        m_statbmp->SetBitmap(bmp);
    }
#endif

    // and update the buttons state
    m_btnPrev->Enable(HasPrevPage(m_page));

    bool hasNext = HasNextPage(m_page);
    if ( btnLabelWasNext != hasNext )
    {
        // need to update
        if (btnLabelWasNext)
            m_btnNext->SetLabel(_("&Finish"));
        else
            m_btnNext->SetLabel(_("&Next >"));
    }
    m_btnNext->SetDefault();
    // nothing to do: the label was already correct

    // send the change event to the new page now
    wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGED, GetId(), goingForward, m_page);
    (void)m_page->GetEventHandler()->ProcessEvent(event);

    // and finally show it
    m_page->Show();
    m_page->SetFocus();

    return true;
}

bool wxWizard::RunWizard(wxWizardPage *firstPage)
{
    wxCHECK_MSG( firstPage, false, wxT("can't run empty wizard") );

    // 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 */);

    modelessWizards.Remove(this);

    return ShowModal() == wxID_OK;
}

wxWizardPage *wxWizard::GetCurrentPage() const
{
    return m_page;
}

wxSize wxWizard::GetPageSize() const
{
    wxSize pageSize(GetManualPageSize());
    pageSize.IncTo(m_sizerPage->GetMaxChildSize());
    return pageSize;
}

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
    int DEFAULT_PAGE_WIDTH = 270;
    int DEFAULT_PAGE_HEIGHT = 270;
    bool isPda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);
    if (isPda)
    {
        // Make the default page size small enough to fit on screen
        DEFAULT_PAGE_WIDTH = wxSystemSettings::GetMetric(wxSYS_SCREEN_X) / 2;
        DEFAULT_PAGE_HEIGHT = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) / 2;
    }
    
    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))
{
    // this function probably can never be called when we don't have an active
    // page, but a small extra check won't hurt
    wxWindow *win = m_page ? (wxWindow *)m_page : (wxWindow *)this;

    wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId(), false, m_page);
    if ( !win->GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
    {
        // no objections - close the dialog
        if(IsModal())
        {
            EndModal(wxID_CANCEL);
        }
        else
        {
            SetReturnCode(wxID_CANCEL);
            Hide();
        }
    }
    //else: request to Cancel ignored
}

void wxWizard::OnBackOrNext(wxCommandEvent& event)
{
    wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
                  (event.GetEventObject() == m_btnPrev),
                  wxT("unknown button") );

    // ask the current page first: notice that we do it before calling
    // GetNext/Prev() because the data transfered from the controls of the page
    // may change the value returned by these methods
    if ( m_page && (!m_page->Validate() || !m_page->TransferDataFromWindow()) )
    {
        // the page data is incorrect, don't do anything
        return;
    }

    bool forward = event.GetEventObject() == m_btnNext;

    wxWizardPage *page;
    if ( forward )
    {
        page = m_page->GetNext();
    }
    else // back
    {
        page = m_page->GetPrev();

        wxASSERT_MSG( page, wxT("\"<Back\" button should have been disabled") );
    }

    // just pass to the new page (or may be not - but we don't care here)
    (void)ShowPage(page, forward);
}

void wxWizard::OnHelp(wxCommandEvent& WXUNUSED(event))
{
    // this function probably can never be called when we don't have an active
    // page, but a small extra check won't hurt
    if(m_page != NULL)
    {
        // Create and send the help event to the specific page handler
        // event data contains the active page so that context-sensitive
        // help is possible
        wxWizardEvent eventHelp(wxEVT_WIZARD_HELP, GetId(), true, m_page);
        (void)m_page->GetEventHandler()->ProcessEvent(eventHelp);
    }
}

void wxWizard::OnWizEvent(wxWizardEvent& event)
{
    // the dialogs have wxWS_EX_BLOCK_EVENTS style on by default but we want to
    // propagate wxEVT_WIZARD_XXX to the parent (if any), so do it manually
    if ( !(GetExtraStyle() & wxWS_EX_BLOCK_EVENTS) )
    {
        // the event will be propagated anyhow
        event.Skip();
    }
    else
    {
        wxWindow *parent = GetParent();

        if ( !parent || !parent->GetEventHandler()->ProcessEvent(event) )
        {
            event.Skip();
        }
    }

    if ( ( modelessWizards.Index(this) != wxNOT_FOUND ) &&
         event.IsAllowed() &&
         ( event.GetEventType() == wxEVT_WIZARD_FINISHED ||
           event.GetEventType() == wxEVT_WIZARD_CANCEL
         )
       )
    {
        modelessWizards.Remove(this);
        Destroy();
    }
}

// ----------------------------------------------------------------------------
// our public interface
// ----------------------------------------------------------------------------

#if WXWIN_COMPATIBILITY_2_2

/* static */
wxWizard *wxWizardBase::Create(wxWindow *parent,
                               int id,
                               const wxString& title,
                               const wxBitmap& bitmap,
                               const wxPoint& pos,
                               const wxSize& WXUNUSED(size))
{
    return new wxWizard(parent, id, title, bitmap, pos);
}

#endif // WXWIN_COMPATIBILITY_2_2

// ----------------------------------------------------------------------------
// wxWizardEvent
// ----------------------------------------------------------------------------

wxWizardEvent::wxWizardEvent(wxEventType type, int id, bool direction, wxWizardPage* page)
             : wxNotifyEvent(type, id)
{
    // Modified 10-20-2001 Robert Cavanaugh
    // add the active page to the event data
    m_direction = direction;
    m_page = page;
}

#endif // wxUSE_WIZARDDLG

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?