diwhyyyyy
diwhyyyyy

Reputation: 6372

wxWidgets C++ - dynamically wrapping wxStaticText in dialog

I am having trouble with getting a wxStaticText label to wrap dynamically in a dialog, using wxWidgets 3.0.2. I followed ideas for other questions like this one, bit I still have strange effects.

I am using the Wrap(int) function on the text, in a callback on the wxEVT_SIZE event, but it seems to have an unexpected effect on the text, and also seems to only "ratchet" down the size, and won't wrap again as the window expands.

The main part of the binding is:

CTOR(...) {
    ....
    m_text->Bind(wxEVT_SIZE, &DIALOG_WRAPTEXT::onResize, this);
}

void CLASS::onResize( wxSizeEvent& event )
{
    m_text->Wrap( event.GetSize().GetWidth() );
    event.Skip();
}

The result looks OK when the dialog is first shown, but when you resize narrower and back up, you get this result:

After making narrower After making wide again

A minimum reproducible example is:

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif
class DIALOG_WRAPTEXT: public wxDialog
{
public:

    DIALOG_WRAPTEXT( wxWindow* parent,
            const wxString& aTitle, const wxSize aSize );

private:

    void onResize( wxSizeEvent& evt );

    wxBoxSizer* m_itemBoxSizer;
    wxStaticText* m_text;
};

DIALOG_WRAPTEXT::DIALOG_WRAPTEXT(
        wxWindow* parent, const wxString& aTitle, const wxSize aSize ):
                    wxDialog( parent, wxID_ANY, aTitle,
                                 wxPoint( -1, -1 ), aSize,
                                 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
    m_itemBoxSizer = new wxBoxSizer( wxVERTICAL );
    SetSizer( m_itemBoxSizer );

    wxString msg("Lots and lots of text to wrap hopefully. "
                "Lots and lots of text to wrap hopefully. "
                "Lots and lots of text to wrap hopefully. "
                "Lots and lots of text to wrap hopefully. "
                "Lots and lots of text to wrap hopefully. "
                "Lots and lots of text to wrap hopefully. "
                );

    m_text = new wxStaticText( this, wxID_ANY, msg );
    // wxEXPAND makes no difference
    m_itemBoxSizer->Add( m_text, 1, wxALIGN_TOP | wxALL | wxEXPAND, 5 );

    // Bind to m_text or this, same effect
    m_text->Bind(wxEVT_SIZE, &DIALOG_WRAPTEXT::onResize, this);

}

void DIALOG_WRAPTEXT::onResize( wxSizeEvent& event )
{
    //m_text->Freeze(); // makes no difference
    const auto w = event.GetSize().GetWidth();
    wxLogDebug( "Wrap to width: %d",w ); // produces sensible values
    m_text->Wrap( w );
    //m_text->Thaw();
    event.Skip();
}


class MyApp: public wxApp
{
public:

    bool OnInit() override
    {
        auto d = new DIALOG_WRAPTEXT(NULL, "Dialog title", wxSize(200, 200));

        d->ShowModal();
        d->Destroy();
    }
};

wxIMPLEMENT_APP(MyApp);

What is the right way to dynamically wrap static text in a dialog?

Upvotes: 1

Views: 3569

Answers (2)

flyaway
flyaway

Reputation: 27

Encountered similar problem. I have to store the unwrapped message somewhere, when wxStaticText is resized, set the message and call wrap. otherwise the line may not be wrapped nicely.

void MyFrame::onResize(wxSizeEvent& evt)
{
const auto w = evt.GetSize().GetWidth();
m_text->SetLabel(m_msg); // unwrapped message
m_text->Wrap(w);
evt.Skip();
}

Upvotes: 1

erg
erg

Reputation: 1652

Without any wrap(), the wxStaticText displays the text correctly (wrapping at word boundaries) using the follwing minimal code on windows with wx 3.0.2. I can resize the dialog (shrink, grow) and the wxStaticText will update itself correctly. This is not enough for your use case? Are you sure you need to use the wrap function?

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class DIALOG_WRAPTEXT : public wxDialog
{
public:

    DIALOG_WRAPTEXT(wxWindow* parent,
        const wxString& aTitle, const wxSize aSize);

private:

    void onResize(wxSizeEvent& evt);

    wxBoxSizer* m_itemBoxSizer;
    wxStaticText* m_text;
};

DIALOG_WRAPTEXT::DIALOG_WRAPTEXT(
    wxWindow* parent, const wxString& aTitle, const wxSize aSize) :
    wxDialog(parent, wxID_ANY, aTitle,
        wxPoint(-1, -1), aSize,
        wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
    m_itemBoxSizer = new wxBoxSizer(wxVERTICAL);
    SetSizer(m_itemBoxSizer);

    wxString msg("Lots and lots of text to wrap hopefully. "
        "Lots and lots of text to wrap hopefully. "
        "Lots and lots of text to wrap hopefully. "
        "Lots and lots of text to wrap hopefully. "
        "Lots and lots of text to wrap hopefully. "
        "Lots and lots of text to wrap hopefully. "
    );

    m_text = new wxStaticText(this, wxID_ANY, msg);
    // wxEXPAND makes no difference
    m_itemBoxSizer->Add(m_text, 1, wxALIGN_TOP | wxALL | wxEXPAND, 5);

    // Act on dialog resize
    Bind(wxEVT_SIZE, &DIALOG_WRAPTEXT::onResize, this);

}

void DIALOG_WRAPTEXT::onResize(wxSizeEvent& event)
{
    // layout everything in the dialog
    Layout();
    event.Skip();
}


class MyApp : public wxApp
{
public:

    bool OnInit() override
    {
        auto d = new DIALOG_WRAPTEXT(NULL, "Dialog title", wxSize(200, 200));

        d->ShowModal();
        d->Destroy();

        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

Upvotes: 2

Related Questions