Search code examples
c++memory-managementwxwidgets

Why is wxBLACK_PEN a wxPen*?


This is quite ugly:

wxPaintDC dc(this);
dc.SetPen(*wxBLACK_PEN);
dc.SetBrush(*wxBLACK_BRUSH);

This is because dc.SetPen takes a const wxPen& - as you'd expect. I usually create pens on the stack, why does this macro expand to a pointer? (I'd expect a const wxPen&)

The macro expands to:

wxStockGDI::GetPen(wxStockGDI::PEN_BLACK)

Is this a factory? It is named "Get" not "Make"....

Should I delete the pen? That'd make its use even messier!

It's not a const wxPen* this supports the "factory" hypothesis. I could change it!

Why does it return a pointer? Should I delete it?

Just so I don't seem silly:
my reason for thinking I should delete it is that it is not const, if I change this pen I don't want to change the black pen itself! So it must be a copy!

I've just tried it (I don't like such experiments) deleting the pen is not a good idea! (crash)


Solution

  • I've googled and found code of GetPen.

    const wxPen* wxStockGDI::GetPen(Item item)
    {
        wxPen* pen = static_cast<wxPen*>(ms_stockObject[item]);
        if (pen == NULL)
        {
            switch (item)
            {
            case PEN_BLACK:
                pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_BLACKDASHED:
                pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxPENSTYLE_SHORT_DASH);
                break;
            case PEN_BLUE:
                pen = new wxPen(*GetColour(COLOUR_BLUE), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_CYAN:
                pen = new wxPen(*GetColour(COLOUR_CYAN), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_GREEN:
                pen = new wxPen(*GetColour(COLOUR_GREEN), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_YELLOW:
                pen = new wxPen(*GetColour(COLOUR_YELLOW), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_GREY:
                pen = new wxPen(wxColour(wxT("GREY")), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_LIGHTGREY:
                pen = new wxPen(*GetColour(COLOUR_LIGHTGREY), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_MEDIUMGREY:
                pen = new wxPen(wxColour(wxT("MEDIUM GREY")), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_RED:
                pen = new wxPen(*GetColour(COLOUR_RED), 1, wxPENSTYLE_SOLID);
                break;
            case PEN_TRANSPARENT:
                pen = new wxPen(*GetColour(COLOUR_BLACK), 1, wxPENSTYLE_TRANSPARENT);
                break;
            case PEN_WHITE:
                pen = new wxPen(*GetColour(COLOUR_WHITE), 1, wxPENSTYLE_SOLID);
                break;
            default:
                wxFAIL;
            }
            ms_stockObject[item] = pen;
        }
        return pen;
    }
    

    (from here)

    I guess it was in order to report failing in new to caller. In ancient times, new returned NULL. (As you know, now new throws std::bad_alloc if allocation is failed.)

    ..and the return type of it is const wxPen*. Didn't you see wrong?