]> git.saurik.com Git - wxWidgets.git/blob - wxPython/samples/embedded/embedded.cpp
Typo fixed
[wxWidgets.git] / wxPython / samples / embedded / embedded.cpp
1 //----------------------------------------------------------------------
2 // Name: embedded.cpp
3 // Purpose: To serve as an example of how to use wxPython from
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
38 class MyApp : public wxApp
39 {
40 public:
41 virtual bool OnInit();
42 virtual ~MyApp();
43 void Init_wxPython();
44 private:
45 PyThreadState* main_tstate;
46 };
47
48
49 class MyFrame : public wxFrame
50 {
51 public:
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
58 private:
59 DECLARE_EVENT_TABLE()
60 };
61
62 //----------------------------------------------------------------------
63 // MyApp methods
64
65
66 bool 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
76 void 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
92 MyApp::~MyApp()
93 {
94 // Restore the thread state and tell Python to cleanup after itself.
95 wxPyEndAllowThreads(main_tstate);
96 Py_Finalize();
97 }
98
99 IMPLEMENT_APP(MyApp)
100
101 //----------------------------------------------------------------------
102
103 enum
104 {
105 ID_EXIT=1001,
106 ID_PYFRAME
107 };
108
109
110 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
111 EVT_MENU(ID_EXIT, MyFrame::OnExit)
112 EVT_MENU(ID_PYFRAME, MyFrame::OnPyFrame)
113 END_EVENT_TABLE()
114
115
116
117 MyFrame::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
148 void MyFrame::OnExit(wxCommandEvent& event)
149 {
150 Close();
151 }
152
153
154 //----------------------------------------------------------------------
155 // This is were the fun begins...
156
157
158 char* python_code1 = "\
159 from wxPython.wx import wxFrame\n\
160 f = wxFrame(None, -1, 'Hello from wxPython!', size=(250, 150))\n\
161 f.Show()\n\
162 ";
163
164 void 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
183 void 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 = "\
189 import sys\n\
190 from wxPython.wx import wxPyOnDemandOutputWindow\n\
191 output = wxPyOnDemandOutputWindow()\n\
192 sys.stdin = sys.stderr = output\n\
193 ";
194 wxPyBeginBlockThreads();
195 PyRun_SimpleString(python_redirect);
196 wxPyEndBlockThreads();
197 }
198
199
200
201
202 char* python_code2 = "\
203 import embedded_sample\n\
204 \n\
205 def makeWindow(parent):\n\
206 win = embedded_sample.MyPanel(parent)\n\
207 return win\n\
208 ";
209
210 wxWindow* 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
215 // easily come from a file, or the whole thing could be in the Python
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