Added wxShadowObject for imitating a VMT with
virtual functions without changing the C++ interface etc. of the class. Added test to it to the dynamic sample. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34763 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		@@ -18,6 +18,67 @@
 | 
			
		||||
 | 
			
		||||
#include "wx/defs.h"
 | 
			
		||||
#include "wx/string.h"
 | 
			
		||||
#include "wx/hashmap.h"
 | 
			
		||||
 | 
			
		||||
typedef int (*wxShadowObjectMethod)(void*, void*);
 | 
			
		||||
WX_DECLARE_STRING_HASH_MAP( wxShadowObjectMethod, wxShadowObjectMethods );
 | 
			
		||||
WX_DECLARE_STRING_HASH_MAP( void*, wxShadowObjectFields );
 | 
			
		||||
 | 
			
		||||
class WXDLLIMPEXP_BASE wxShadowObject
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wxShadowObject() { }
 | 
			
		||||
    
 | 
			
		||||
    void AddMethod( const wxString &name, wxShadowObjectMethod method )
 | 
			
		||||
    { 
 | 
			
		||||
        wxShadowObjectMethods::iterator it = m_methods.find( name );
 | 
			
		||||
        if (it == m_methods.end())
 | 
			
		||||
            m_methods[ name ] = method;
 | 
			
		||||
        else
 | 
			
		||||
            it->second = method;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    bool InvokeMethod( const wxString &name, void* window, void* param, int* returnValue )
 | 
			
		||||
    { 
 | 
			
		||||
        wxShadowObjectMethods::iterator it = m_methods.find( name );
 | 
			
		||||
        if (it == m_methods.end())
 | 
			
		||||
            return false;
 | 
			
		||||
        wxShadowObjectMethod method = it->second;
 | 
			
		||||
        int ret = (*method)(window, param);
 | 
			
		||||
        if (returnValue)
 | 
			
		||||
            *returnValue = ret;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void AddField( const wxString &name, void* initialValue = NULL )
 | 
			
		||||
    {
 | 
			
		||||
        wxShadowObjectFields::iterator it = m_fields.find( name );
 | 
			
		||||
        if (it == m_fields.end())
 | 
			
		||||
            m_fields[ name ] = initialValue;
 | 
			
		||||
        else
 | 
			
		||||
            it->second = initialValue;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void SetField( const wxString &name, void* value )
 | 
			
		||||
    {
 | 
			
		||||
        wxShadowObjectFields::iterator it = m_fields.find( name );
 | 
			
		||||
        if (it == m_fields.end())
 | 
			
		||||
            return;
 | 
			
		||||
        it->second = value;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void* GetField( const wxString &name, void *defaultValue = NULL )
 | 
			
		||||
    {
 | 
			
		||||
        wxShadowObjectFields::iterator it = m_fields.find( name );
 | 
			
		||||
        if (it == m_fields.end())
 | 
			
		||||
            return defaultValue;
 | 
			
		||||
        return it->second;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
private:
 | 
			
		||||
    wxShadowObjectMethods   m_methods;
 | 
			
		||||
    wxShadowObjectFields    m_fields;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,29 +25,44 @@
 | 
			
		||||
#include "wx/wx.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "wx/clntdata.h"
 | 
			
		||||
 | 
			
		||||
#if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXCOCOA__)
 | 
			
		||||
#include "mondrian.xpm"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Define a new application type
 | 
			
		||||
class MyApp: public wxApp
 | 
			
		||||
{ public:
 | 
			
		||||
{ 
 | 
			
		||||
public:
 | 
			
		||||
    bool OnInit(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Define a new frame type
 | 
			
		||||
class MyFrame: public wxFrame
 | 
			
		||||
{ public:
 | 
			
		||||
{ 
 | 
			
		||||
public:
 | 
			
		||||
    MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
public:
 | 
			
		||||
    void OnQuit(wxCommandEvent& event);
 | 
			
		||||
    void OnTest(wxCommandEvent& event);
 | 
			
		||||
    void OnAbout(wxCommandEvent& event);
 | 
			
		||||
    
 | 
			
		||||
protected:
 | 
			
		||||
    wxShadowObject m_shadow;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Define another new frame type
 | 
			
		||||
class MySecondFrame: public MyFrame
 | 
			
		||||
{ 
 | 
			
		||||
public:
 | 
			
		||||
    MySecondFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ID for the menu commands
 | 
			
		||||
#define DYNAMIC_QUIT   wxID_EXIT
 | 
			
		||||
#define DYNAMIC_TEXT   101
 | 
			
		||||
#define DYNAMIC_TEST   101
 | 
			
		||||
#define DYNAMIC_ABOUT  wxID_ABOUT
 | 
			
		||||
 | 
			
		||||
// Create a new application object
 | 
			
		||||
@@ -56,60 +71,110 @@ IMPLEMENT_APP  (MyApp)
 | 
			
		||||
// `Main program' equivalent, creating windows and returning main app frame
 | 
			
		||||
bool MyApp::OnInit(void)
 | 
			
		||||
{
 | 
			
		||||
  // Create the main frame window
 | 
			
		||||
  MyFrame *frame = new MyFrame(NULL, _T("Dynamic wxWidgets App"), 50, 50, 450, 340);
 | 
			
		||||
    // Create the main frame window
 | 
			
		||||
    MyFrame *frame = new MyFrame(NULL, _T("Dynamic wxWidgets App"), 50, 50, 450, 340);
 | 
			
		||||
 | 
			
		||||
  // You used to have to do some casting for param 4, but now there are type-safe handlers
 | 
			
		||||
  frame->Connect( DYNAMIC_QUIT,  wxID_ANY,
 | 
			
		||||
                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnQuit) );
 | 
			
		||||
  frame->Connect( DYNAMIC_ABOUT, wxID_ANY,
 | 
			
		||||
                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnAbout) );
 | 
			
		||||
    // Show the frame
 | 
			
		||||
    frame->Show(true);
 | 
			
		||||
     
 | 
			
		||||
    // Create the main frame window
 | 
			
		||||
    MySecondFrame *frame2 = new MySecondFrame(NULL, _T("Dynamic wxWidgets App"), 150, 150, 450, 340);
 | 
			
		||||
    
 | 
			
		||||
    // Show the frame
 | 
			
		||||
    frame2->Show(true);
 | 
			
		||||
 | 
			
		||||
  // Give it an icon
 | 
			
		||||
#ifdef __WXMSW__
 | 
			
		||||
  frame->SetIcon(wxIcon(_T("mondrian")));
 | 
			
		||||
#else
 | 
			
		||||
  frame->SetIcon(wxIcon(mondrian_xpm));
 | 
			
		||||
#endif
 | 
			
		||||
    SetTopWindow(frame);
 | 
			
		||||
 | 
			
		||||
  // Make a menubar
 | 
			
		||||
  wxMenu *file_menu = new wxMenu;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  file_menu->Append(DYNAMIC_ABOUT, _T("&About"));
 | 
			
		||||
  file_menu->Append(DYNAMIC_QUIT, _T("E&xit"));
 | 
			
		||||
  wxMenuBar *menu_bar = new wxMenuBar;
 | 
			
		||||
  menu_bar->Append(file_menu, _T("&File"));
 | 
			
		||||
  frame->SetMenuBar(menu_bar);
 | 
			
		||||
// -------------------------------------
 | 
			
		||||
// MyFrame
 | 
			
		||||
// -------------------------------------
 | 
			
		||||
 | 
			
		||||
  // Make a panel with a message
 | 
			
		||||
  wxPanel *panel = new wxPanel(frame, wxID_ANY, wxPoint(0, 0), wxSize(400, 200), wxTAB_TRAVERSAL);
 | 
			
		||||
// Callback from wxShadowObject
 | 
			
		||||
 | 
			
		||||
  (void)new wxStaticText(panel, 311, _T("Hello!"), wxPoint(10, 10), wxDefaultSize, 0);
 | 
			
		||||
 | 
			
		||||
  // Show the frame
 | 
			
		||||
  frame->Show(true);
 | 
			
		||||
 | 
			
		||||
  SetTopWindow(frame);
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
int cb_MyFrame_InitStatusbar( void* window, void* param )
 | 
			
		||||
{
 | 
			
		||||
    MyFrame *frame = (MyFrame*) window;
 | 
			
		||||
    frame->SetStatusText( wxT("Hello from MyFrame"), 0 );
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// My frame constructor
 | 
			
		||||
MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
 | 
			
		||||
  wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
 | 
			
		||||
{}
 | 
			
		||||
{
 | 
			
		||||
    // Give it an icon
 | 
			
		||||
#ifdef __WXMSW__
 | 
			
		||||
    SetIcon(wxIcon(_T("mondrian")));
 | 
			
		||||
#else
 | 
			
		||||
    SetIcon(wxIcon(mondrian_xpm));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // Make a menubar
 | 
			
		||||
    wxMenu *file_menu = new wxMenu;
 | 
			
		||||
 | 
			
		||||
    file_menu->Append(DYNAMIC_ABOUT, _T("&About"));
 | 
			
		||||
    file_menu->Append(DYNAMIC_TEST, _T("&Test"));
 | 
			
		||||
    file_menu->Append(DYNAMIC_QUIT, _T("E&xit"));
 | 
			
		||||
    wxMenuBar *menu_bar = new wxMenuBar;
 | 
			
		||||
    menu_bar->Append(file_menu, _T("&File"));
 | 
			
		||||
    SetMenuBar(menu_bar);
 | 
			
		||||
 | 
			
		||||
    // Make a panel with a message
 | 
			
		||||
    wxPanel *panel = new wxPanel(this, wxID_ANY, wxPoint(0, 0), wxSize(400, 200), wxTAB_TRAVERSAL);
 | 
			
		||||
 | 
			
		||||
    (void)new wxStaticText(panel, 311, _T("Hello!"), wxPoint(10, 10), wxDefaultSize, 0);
 | 
			
		||||
 | 
			
		||||
    // You used to have to do some casting for param 4, but now there are type-safe handlers
 | 
			
		||||
    Connect( DYNAMIC_QUIT,  wxID_ANY,
 | 
			
		||||
                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnQuit) );
 | 
			
		||||
    Connect( DYNAMIC_TEST, wxID_ANY,
 | 
			
		||||
                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnTest) );
 | 
			
		||||
    Connect( DYNAMIC_ABOUT, wxID_ANY,
 | 
			
		||||
                    wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnAbout) );
 | 
			
		||||
                    
 | 
			
		||||
    CreateStatusBar();
 | 
			
		||||
    m_shadow.AddMethod( wxT("OnTest"), &cb_MyFrame_InitStatusbar );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
 | 
			
		||||
{
 | 
			
		||||
  Close(true);
 | 
			
		||||
    Close(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MyFrame::OnTest(wxCommandEvent& WXUNUSED(event) )
 | 
			
		||||
{
 | 
			
		||||
    m_shadow.InvokeMethod( wxT("OnTest"), this, NULL, NULL );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
 | 
			
		||||
{
 | 
			
		||||
  wxMessageDialog dialog(this, _T("This demonstrates dynamic event handling"),
 | 
			
		||||
    _T("About Dynamic"), wxYES_NO|wxCANCEL);
 | 
			
		||||
    wxMessageDialog dialog(this, _T("This demonstrates dynamic event handling"),
 | 
			
		||||
        _T("About Dynamic"), wxYES_NO|wxCANCEL);
 | 
			
		||||
 | 
			
		||||
  dialog.ShowModal();
 | 
			
		||||
    dialog.ShowModal();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// -------------------------------------
 | 
			
		||||
// MySecondFrame
 | 
			
		||||
// -------------------------------------
 | 
			
		||||
 | 
			
		||||
// Callback from wxShadowObject
 | 
			
		||||
 | 
			
		||||
int cb_MySecondFrame_InitStatusbar( void* window, void* param )
 | 
			
		||||
{
 | 
			
		||||
    MySecondFrame *frame = (MySecondFrame*) window;
 | 
			
		||||
    frame->SetStatusText( wxT("Hello from MySecondFrame"), 0 );
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// My frame constructor
 | 
			
		||||
MySecondFrame::MySecondFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
 | 
			
		||||
  MyFrame(frame, title, x, y, w, h )
 | 
			
		||||
{
 | 
			
		||||
    m_shadow.AddMethod( wxT("OnTest"), &cb_MySecondFrame_InitStatusbar );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user