Why Cant I Edit The Generated Code

Why Can't I Edit the Generated Code?

What is wrong with editing generated code?

The most common approach to generating GUI code is to separate generated code from user-entered code with specialized comments. Consider this example of using specialized comments to indicate where code will be generated. (Note: the //(* and //*)):

MyFrame::MyFrame(wxWindow* parent,wxWindowID id)
{
    //(*Initialize(MyFrame)
    wxMenuBar* MenuBar1;
    wxMenu* Menu1;
    wxMenuItem* MenuItem1;
    wxMenu* Menu2;
    wxMenuItem* MenuItem2;

    Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
    MenuBar1 = new wxMenuBar();
    Menu1 = new wxMenu();
    MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
    Menu1->Append(MenuItem1);
    MenuBar1->Append(Menu1, _("&File"));
    Menu2 = new wxMenu();
    MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
    Menu2->Append(MenuItem2);
    MenuBar1->Append(Menu2, _("Help"));
    SetMenuBar(MenuBar1);
    StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
    int StatusBar1__widths[1] = { -1 };
    int StatusBar1__styles[1] = { wxSB_NORMAL };
    StatusBar1->SetFieldsCount(1,StatusBar1__widths);
    StatusBar1->SetStatusStyles(1,StatusBar1__styles);
    SetStatusBar(StatusBar1);
    Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxsmithtestFrame::OnQuit);
    Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxsmithtestFrame::OnAbout);
    //*)

    wxMessageBox( _("Hello World!") );
}

This approach has two big problems:

  • It is error prone.
    What would happen if the user deleted one of the specialized comments?
    The GUI generator would have to try to determine where the generated code should go, but it would probably be wrong. The worst-case scenario is that user-entered code is destroyed; the best-case is that the application is broken.

    The code generated by wxFormBuilder is in a different file, which the user never edits. So there is no need for specialized comments, and no chance of a mistake.
  • It is messy.
    In the above example, 27 lines of the constructor of MyFrame were generated GUI code that the user does not care about. Why should that code clutter the user-entered code? The implementation of the GUI is what the user cares about, not the creation of the GUI.

    The code generated by wxFormBuilder is completely separate from user-entered code. The user can focus on coding the functionality of the GUI without needing to work around the code which creates the GUI.

If I can't edit the code, how do I add functionality to my GUI?

The disadvantage to wxFormBuilder's approach is that it becomes slightly more difficult to implement the GUI.

The correct way to implement a GUI generated by wxFormBuilder is by using inheritance. The generated classes which create the GUI are intended to be used as base classes for the user-entered classes which implement the GUI.

For example, suppose a user wanted to create a class named MyFrame. He would setup wxFormBuilder to generate a class named MyFrameBase, and the generated code might look something like this:

Generated Header File: MyFrameBase.h


class MyFrameBase : public wxFrame 
{
	private:

	protected:
		wxPanel* m_mainPanel;

	public:
		MyFrameBase( wxWindow* parent, int id = wxID_ANY, wxString title = wxT("MyFrame"), wxPoint pos = wxDefaultPosition, wxSize size = wxSize( 500,300 ), int style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );

};

Generated Source File: MyFrameBase.cpp


MyFrameBase::MyFrameBase( wxWindow* parent, int id, wxString title, wxPoint pos, wxSize size, int style ) : wxFrame( parent, id, title, pos, size, style )
{
	this->SetSizeHints( wxDefaultSize, wxDefaultSize );

	wxBoxSizer* mainSizer;
	mainSizer = new wxBoxSizer( wxVERTICAL );

	m_mainPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
	mainSizer->Add( m_mainPanel, 1, wxEXPAND, 5 );

	this->SetSizer( mainSizer );
	this->Layout();
}

These generated files contain nothing but tedious GUI creation code.

The user would then hand-code a new class named MyFrame that inherited from MyFrameBase. All functionality for the GUI would be hand-coded in the MyFrame class.

Hand-coded Header File: MyFrame.h


#include "MyFrameBase.h"

class MyFrame : public MyFrameBase
{
public:
    MyFrame( wxWindow* parent );    
}

Hand-coded Source File: MyFrame.cpp


MyFrame::MyFrame( wxWindow* parent ) : MyFrameBase( parent )
{
   wxMessageBox( _("Hello World, this code is clearly separate from the generated code!") );
}

wxFormBuilder can even do a one-time generation of a bare-bones inherited class with it's useful "Generate Inherited Class" dialog.

Conclusion

wxFormBuilder's read-only generation approach was chosen to provide a error-free, organized GUI creation experience. The developers have come to love this approach, and, with time, you will too.