]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/embedded/embedded.cpp
Added wxRTTI for the new wxVScrolledWindow, wxVListBox, and
[wxWidgets.git] / wxPython / samples / embedded / embedded.cpp
CommitLineData
a2426843
RD
1//----------------------------------------------------------------------
2// Name: embedded.cpp
248834a0 3// Purpose: To serve as an example of how to use wxPython from
a2426843
RD
4// within a C++ wxWindows program.
5//
6// Author: Robin Dunn
7//
8// Created: 1-May-2002
9// RCS-ID: $Id$
10// Copyright: (c) 2002 by Total Control Software
11// Licence: wxWindows license
12//----------------------------------------------------------------------
13
14// For compilers that support precompilation, includes "wx/wx.h".
15#include <wx/wxprec.h>
16
17#ifdef __BORLANDC__
18 #pragma hdrstop
19#endif
20
21#ifndef WX_PRECOMP
22 #include <wx/wx.h>
23#endif
24
25#include <wx/splitter.h>
26
27#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__)
28 #include "mondrian.xpm"
29#endif
30
31// Import Python and wxPython headers
32#include <Python.h>
33#include <wxPython.h>
34
35//----------------------------------------------------------------------
36// Class definitions
37
38class MyApp : public wxApp
39{
40public:
41 virtual bool OnInit();
42 virtual ~MyApp();
43 void Init_wxPython();
44private:
45 PyThreadState* main_tstate;
46};
47
48
49class MyFrame : public wxFrame
50{
51public:
52 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
53 void RedirectStdio();
54 wxWindow* DoPythonStuff(wxWindow* parent);
55 void OnExit(wxCommandEvent& event);
56 void OnPyFrame(wxCommandEvent& event);
57
58private:
59 DECLARE_EVENT_TABLE()
60};
61
62//----------------------------------------------------------------------
63// MyApp methods
64
65
66bool MyApp::OnInit()
67{
68 Init_wxPython();
69 MyFrame *frame = new MyFrame(_T("Embedded wxPython Test"),
70 wxPoint(50, 50), wxSize(700, 600));
71 frame->Show(TRUE);
72 return TRUE;
73}
74
75
76void MyApp::Init_wxPython()
77{
78 // Initialize Python
79 Py_Initialize();
80 PyEval_InitThreads();
81
82 // Load the wxPython core API. Imports the wxPython.wxc
83 // module and sets a pointer to a function table located there.
84 wxPyCoreAPI_IMPORT();
85
86 // Save the current Python thread state and release the
87 // Global Interpreter Lock.
88 main_tstate = wxPyBeginAllowThreads();
89}
90
91
92MyApp::~MyApp()
93{
94 // Restore the thread state and tell Python to cleanup after itself.
95 wxPyEndAllowThreads(main_tstate);
96 Py_Finalize();
97}
98
99IMPLEMENT_APP(MyApp)
100
101//----------------------------------------------------------------------
102
103enum
104{
105 ID_EXIT=1001,
106 ID_PYFRAME
107};
108
109
110BEGIN_EVENT_TABLE(MyFrame, wxFrame)
5d26a7e6
RD
111 EVT_MENU(ID_EXIT, MyFrame::OnExit)
112 EVT_MENU(ID_PYFRAME, MyFrame::OnPyFrame)
a2426843
RD
113END_EVENT_TABLE()
114
115
116
117MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
118 : wxFrame(NULL, -1, title, pos, size,
119 wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
120{
121 SetIcon(wxICON(mondrian));
122
123 wxMenuBar* mbar = new wxMenuBar;
124 wxMenu* menu = new wxMenu;
125 menu->Append(ID_PYFRAME, "Make wx&Python frame");
126 menu->AppendSeparator();
127 menu->Append(ID_EXIT, "&Close Frame\tAlt-X");
128 mbar->Append(menu, "&File");
129 SetMenuBar(mbar);
130
131 CreateStatusBar();
132 RedirectStdio();
133
134 // Make some child windows from C++
135 wxSplitterWindow* sp = new wxSplitterWindow(this, -1);
136 wxPanel* p1 = new wxPanel(sp, -1);
137 p1->SetFont(wxFont(12, wxSWISS, wxNORMAL, wxBOLD));
138 new wxStaticText(p1, -1,
139 wxT("The frame, menu, splitter, this panel and this text were created in C++..."),
140 wxPoint(10,10));
141
142 // And get a panel from Python
143 wxWindow* p2 = DoPythonStuff(sp);
144
145 sp->SplitHorizontally(p1, p2, GetClientSize().y/4);
146}
147
148void MyFrame::OnExit(wxCommandEvent& event)
149{
150 Close();
151}
152
153
154//----------------------------------------------------------------------
155// This is were the fun begins...
156
157
158char* python_code1 = "\
159from wxPython.wx import wxFrame\n\
160f = wxFrame(None, -1, 'Hello from wxPython!', size=(250, 150))\n\
161f.Show()\n\
162";
163
164void MyFrame::OnPyFrame(wxCommandEvent& event)
165{
166 // For simple Python code that doesn't have to interact with the
167 // C++ code in any way, you can execute it with PyRun_SimpleString.
168
169
170 // First, whenever you do anyting with Python objects or code, you
171 // *MUST* aquire the Global Interpreter Lock and block other
172 // Python threads from running.
173 wxPyBeginBlockThreads();
174
175 // Execute the code in the __main__ module
176 PyRun_SimpleString(python_code1);
177
178 // Finally, release the GIL and let other Python threads run.
179 wxPyEndBlockThreads();
180}
181
182
183void MyFrame::RedirectStdio()
184{
185 // This is a helpful little tidbit to help debugging and such. It
186 // redirects Python's stdout and stderr to a window that will popup
187 // only on demand when something is printed, like a traceback.
188 char* python_redirect = "\
189import sys\n\
190from wxPython.wx import wxPyOnDemandOutputWindow\n\
191output = wxPyOnDemandOutputWindow()\n\
192sys.stdin = sys.stderr = output\n\
193";
194 wxPyBeginBlockThreads();
195 PyRun_SimpleString(python_redirect);
196 wxPyEndBlockThreads();
197}
198
199
200
201
202char* python_code2 = "\
203import embedded_sample\n\
204\n\
205def makeWindow(parent):\n\
206 win = embedded_sample.MyPanel(parent)\n\
207 return win\n\
208";
209
210wxWindow* MyFrame::DoPythonStuff(wxWindow* parent)
211{
212 // More complex embedded situations will require passing C++ objects to
213 // Python and/or returning objects from Python to be used in C++. This
214 // sample shows one way to do it. NOTE: The above code could just have
a9f4542f 215 // easily come from a file, or the whole thing could be in the Python
a2426843
RD
216 // module that is imported and manipulated directly in this C++ code. See
217 // the Python API for more details.
218
219 wxWindow* window = NULL;
220 PyObject* result;
221
222 // As always, first grab the GIL
223 wxPyBeginBlockThreads();
224
225 // Now make a dictionary to serve as the global namespace when the code is
226 // executed. Put a reference to the builtins module in it. (Yes, the
227 // names are supposed to be different, I don't know why...)
228 PyObject* globals = PyDict_New();
229 PyObject* builtins = PyImport_ImportModule("__builtin__");
230 PyDict_SetItemString(globals, "__builtins__", builtins);
231 Py_DECREF(builtins);
232
233 // Execute the code to make the makeWindow function
234 result = PyRun_String(python_code2, Py_file_input, globals, globals);
235 // Was there an exception?
236 if (! result) {
237 PyErr_Print();
238 wxPyEndBlockThreads();
239 return NULL;
240 }
241 Py_DECREF(result);
242
243 // Now there should be an object named 'makeWindow' in the dictionary that
244 // we can grab a pointer to:
245 PyObject* func = PyDict_GetItemString(globals, "makeWindow");
246 wxASSERT(PyCallable_Check(func));
247
248 // Now build an argument tuple and call the Python function. Notice the
249 // use of another wxPython API to take a wxWindows object and build a
250 // wxPython object that wraps it.
251 PyObject* arg = wxPyMake_wxObject(parent);
252 wxASSERT(arg != NULL);
253
254 PyObject* tuple = PyTuple_New(1);
255 PyTuple_SET_ITEM(tuple, 0, arg);
256 result = PyEval_CallObject(func, tuple);
257
258 // Was there an exception?
259 if (! result)
260 PyErr_Print();
261 else {
262 // Otherwise, get the returned window out of Python-land and
263 // into C++-ville...
264 bool error = SWIG_GetPtrObj(result, (void**)&window, "_wxWindow_p");
265 wxASSERT_MSG(!error, wxT("Returned object was not a wxWindow!"));
266 Py_DECREF(result);
267 }
268
269 // Release the python objects we still have
270 Py_DECREF(globals);
271 Py_DECREF(tuple);
272
273 // Finally, after all Python stuff is done, release the GIL
274 wxPyEndBlockThreads();
275
276 return window;
277}
278
279
280//----------------------------------------------------------------------
281
282
283
284
285
286