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