]> git.saurik.com Git - wxWidgets.git/blame - wxPython/contrib/activex/activex.i
GetClientAreaOrigin should be public
[wxWidgets.git] / wxPython / contrib / activex / activex.i
CommitLineData
b7c75283
RD
1/////////////////////////////////////////////////////////////////////////////
2// Name: activex.i
3// Purpose: ActiveX controls (such as Internet Explorer) in a wxWindow
4//
5// Author: Robin Dunn
6//
7// Created: 18-Mar-2004
8// RCS-ID: $Id$
9// Copyright: (c) 2004 by Total Control Software
10// Licence: wxWindows license
11/////////////////////////////////////////////////////////////////////////////
12
13
14%module activex
15
16%{
17#include "wx/wxPython/wxPython.h"
18#include "wx/wxPython/pyclasses.h"
19#include "wx/wxPython/pyistream.h"
20
21#include "wxactivex.h"
22%}
23
24//---------------------------------------------------------------------------
25
26%import core.i
54f9ee45 27%pythoncode { wx = _core }
99109c0f 28%pythoncode { __docfilter__ = wx.__DocFilter(globals()) }
b7c75283
RD
29
30MAKE_CONST_WXSTRING_NOSWIG(PanelNameStr);
31
32%include _activex_rename.i
33
34
35//---------------------------------------------------------------------------
36
37typedef unsigned short USHORT;
38typedef long DISPID;
39typedef long MEMBERID;
40typedef unsigned short VARTYPE;
41
42
43%{
44// Since SWIG doesn't support nested classes, we need to fool it a bit
45// and make them look like global classes. These defines make the C++ code
46// know what we are doing.
47#define wxParamX wxActiveX::ParamX
48#define wxFuncX wxActiveX::FuncX
49#define wxPropX wxActiveX::PropX
50#define wxParamXArray wxActiveX::ParamXArray
51#define wxFuncXArray wxActiveX::FuncXArray
52#define wxPropXArray wxActiveX::PropXArray
53%}
54
55
56%{
57// Some conversion helpers
58static wxVariant _PyObj2Variant(PyObject* value);
0dabb2a2 59static bool _PyObj2Variant(PyObject* value, wxVariant& wv);
b7c75283
RD
60static PyObject* _Variant2PyObj(wxVariant& value, bool useNone=False);
61static wxString _VARTYPEname(VARTYPE vt);
62
63// Check if an exception has been raised (blocking threads)
64inline bool wxPyErr_Occurred()
65{
66 bool rval;
0dabb2a2 67 bool blocked = wxPyBeginBlockThreads();
b7c75283 68 rval = PyErr_Occurred() != NULL;
0dabb2a2 69 wxPyEndBlockThreads(blocked);
b7c75283
RD
70 return rval;
71}
72
73%}
74
75//---------------------------------------------------------------------------
76%newgroup
77
78DocStr(CLSID,
79"This class wraps the Windows CLSID structure and is used to
80specify the class of the ActiveX object that is to be created. A
81CLSID can be constructed from either a ProgID string, (such as
82'WordPad.Document.1') or a classID string, (such as
6cfd7f95 83'{CA8A9783-280D-11CF-A24D-444553540000}').", "");
b7c75283
RD
84
85class CLSID {
86public:
87 %extend {
88 CLSID(const wxString& id)
89 {
90 int result;
91 CLSID* self = new CLSID;
92 memset(self, 0, sizeof(CLSID));
93
94 if (id[0] == _T('{')) {
95 // Looks like a classID string
96 result =
97 CLSIDFromString(
98 (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
99 self);
100 } else {
101 // Try a progID
102 result =
103 CLSIDFromProgID(
104 (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
105 self);
106 }
107 if (result != NOERROR) {
108 wxPyErr_SetString(PyExc_ValueError, "Not a recognized classID or progID");
109 delete self;
110 return NULL;
111 }
112 return self;
113 }
114
115 ~CLSID() { delete self; }
116
117 wxString GetCLSIDString()
118 {
119 LPOLESTR s;
120 wxString str;
121 if (StringFromCLSID(*self, &s) == S_OK) {
122 str = s;
123 CoTaskMemFree(s);
124 }
125 else {
126 str = _T("Error!"); // TODO: raise exception?
127 }
128 return str;
129 }
130 wxString GetProgIDString()
131 {
132 LPOLESTR s;
133 wxString str;
134 if (ProgIDFromCLSID(*self, &s) == S_OK) {
135 str = s;
136 CoTaskMemFree(s);
137 }
138 else {
139 str = _T("Error!"); // TODO: raise exception?
140 }
141 return str;
142 }
143 }
144 %pythoncode { def __str__(self): return self.GetCLSIDString() }
145};
146
147
148//---------------------------------------------------------------------------
149%newgroup
150
151%define MAKE_ARRAY_WRAPPER(basetype, arrayname)
152class arrayname
153{
154public:
155 %extend {
156 bool __nonzero__() { return self->size() > 0; }
157 int __len__() { return self->size(); }
158
159 const basetype& __getitem__(int idx) {
160 if ( idx >= 0 && idx < self->size() )
161 return (*self)[idx];
162 else {
163 static basetype BadVal;
164 wxPyErr_SetString(PyExc_IndexError, "Index out of range");
165 return BadVal;
166 }
167 }
168 // TODO __iter__??
169 }
170};
171%enddef
172
173//---------------------------------------------------------------------------
174
175%immutable;
176
177class wxParamX
178{
179public:
180 USHORT flags;
181 bool isPtr;
182 bool isSafeArray;
183 bool isOptional;
184 VARTYPE vt;
185 wxString name;
186
187 %feature("shadow") vt_type_get "vt_type = property(_activex.ParamX_vt_type_get)";
188 %extend { wxString vt_type_get() { return _VARTYPEname(self->vt); } }
189
190 %feature("shadow") IsIn "isIn = property(_activex.ParamX_IsIn)";
191 %feature("shadow") IsOut "isOut = property(_activex.ParamX_IsOut)";
192 %feature("shadow") IsRetVal "isRetVal = property(_activex.ParamX_IsRetVal)";
193 bool IsIn() const;
194 bool IsOut() const;
195 bool IsRetVal() const;
196
197};
198
199
200class wxFuncX
201{
202public:
203 wxString name;
204 MEMBERID memid;
205 bool hasOut;
206
207 wxParamX retType;
208 wxParamXArray params;
209};
210
211
212class wxPropX
213{
214public:
215 wxString name;
216 MEMBERID memid;
217 wxParamX type;
218 wxParamX arg;
219 bool putByRef;
220
221 %feature("shadow") CanGet "canGet = property(_activex.PropX_CanGet)";
222 %feature("shadow") CanSet "canSet = property(_activex.PropX_CanSet)";
223 bool CanGet() const;
224 bool CanSet() const;
225};
226%mutable;
227
228
229MAKE_ARRAY_WRAPPER(wxParamX, wxParamXArray);
230MAKE_ARRAY_WRAPPER(wxFuncX, wxFuncXArray);
231MAKE_ARRAY_WRAPPER(wxPropX, wxPropXArray);
232
233
234//---------------------------------------------------------------------------
235%newgroup
236
237%{
238// C++ version of a Python-aware wxActiveX
239class wxActiveXWindow : public wxActiveX
240{
241private:
242 CLSID m_CLSID;
243public:
244 wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
245 const wxPoint& pos = wxDefaultPosition,
246 const wxSize& size = wxDefaultSize,
247 long style = 0,
248 const wxString& name = wxPyPanelNameStr)
249 : wxActiveX(parent, clsId, id, pos, size, style, name)
250 {
251 m_CLSID = clsId;
252 }
253
254 const CLSID& GetCLSID() const { return m_CLSID; }
255
256
257 // Renamed versions of some base class methods that delegate
258 // to the base where appropriate, and raise Python exceptions
259 // when needed.
260 int GetAXEventCount() const { return wxActiveX::GetEventCount(); }
261 int GetAXPropCount() const { return wxActiveX::GetPropCount(); }
262 int GetAXMethodCount() const { return wxActiveX::GetMethodCount(); }
263
264 const wxFuncX& GetAXEventDesc(int idx) const
265 {
266 static wxFuncX BadVal;
267 if (idx < 0 || idx >= GetAXEventCount()) {
268 wxPyErr_SetString(PyExc_IndexError, "Index out of range");
269 return BadVal;
270 }
271 return m_events[idx];
272 }
273 const wxFuncX& GetAXMethodDesc(int idx) const
274 {
275 static wxFuncX BadVal;
276 if (idx < 0 || idx >= GetAXMethodCount()) {
277 wxPyErr_SetString(PyExc_IndexError, "Index out of range");
278 return BadVal;
279 }
280 return m_methods[idx];
281 }
282 const wxPropX& GetAXPropDesc(int idx) const
283 {
284 static wxPropX BadVal;
285 if (idx < 0 || idx >= GetAXPropCount()) {
286 wxPyErr_SetString(PyExc_IndexError, "Index out of range");
287 return BadVal;
288 }
289 return m_props[idx];
290 }
291
292 const wxFuncX& GetAXMethodDesc(const wxString& name) const
293 {
294 NameMap::const_iterator it = m_methodNames.find(name);
295 if (it == m_methodNames.end()) {
296 wxString msg;
0dabb2a2 297 msg << _T("method <") << name << _T("> not found");
b7c75283
RD
298 wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
299 static wxFuncX BadVal;
300 return BadVal;
301 };
302 return GetAXMethodDesc(it->second);
303 }
304 const wxPropX& GetAXPropDesc(const wxString& name) const
305 {
306 NameMap::const_iterator it = m_propNames.find(name);
307 if (it == m_propNames.end()) {
308 wxString msg;
0dabb2a2 309 msg << _T("property <") << name << _T("> not found");
b7c75283
RD
310 wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
311 static wxPropX BadVal;
312 return BadVal;
313 };
314 return GetAXPropDesc(it->second);
315 }
316
317 // Accessors for the internal vectors of events, methods and
318 // proprties. Can be used as sequence like objects from
319 // Python.
320 const wxFuncXArray& GetAXEvents() { return m_events; }
321 const wxFuncXArray& GetAXMethods() { return m_methods; }
322 const wxPropXArray& GetAXProperties() { return m_props; }
323
324
325 // Set a property from a Python object
326 void SetAXProp(const wxString& name, PyObject* value)
327 {
328 const wxPropX& prop = GetAXPropDesc(name);
0dabb2a2 329 bool blocked = wxPyBeginBlockThreads();
b7c75283
RD
330 if (! PyErr_Occurred() ) {
331 if (! prop.CanSet()) {
332 wxString msg;
0dabb2a2 333 msg << _T("property <") << name << _T("> is readonly");
b7c75283
RD
334 PyErr_SetString(PyExc_TypeError, msg.mb_str());
335 goto done;
336 } else {
337 wxVariant wxV = _PyObj2Variant(value);
338 if (PyErr_Occurred())
339 goto done;
340 VARIANT v = {prop.arg.vt};
341 if (!VariantToMSWVariant(wxV, v) || PyErr_Occurred()) {
342 wxString msg;
0dabb2a2
RD
343 msg << _T("Unable to convert value to expected type: (")
344 << _VARTYPEname(prop.arg.vt) << _T(") for property <")
345 << name << _T(">");
b7c75283
RD
346 PyErr_SetString(PyExc_TypeError, msg.mb_str());
347 goto done;
348 }
349 PyThreadState* tstate = wxPyBeginAllowThreads();
350 SetProp(prop.memid, v);
351 VariantClear(&v);
352 wxPyEndAllowThreads(tstate);
353 }
354 }
355 done:
0dabb2a2 356 wxPyEndBlockThreads(blocked);
b7c75283
RD
357 }
358
359
360 // Get a property and convert it to a Python object
361 PyObject* GetAXProp(const wxString& name)
362 {
363 PyObject* rval = NULL;
364 const wxPropX& prop = GetAXPropDesc(name);
0dabb2a2 365 bool blocked = wxPyBeginBlockThreads();
b7c75283
RD
366 if (! PyErr_Occurred() ) {
367 if (! prop.CanGet()) {
368 wxString msg;
0dabb2a2 369 msg << _T("property <") << name << _T("> is writeonly");
b7c75283
RD
370 PyErr_SetString(PyExc_TypeError, msg.mb_str());
371 goto done;
372 } else {
373 PyThreadState* tstate = wxPyBeginAllowThreads();
374 VARIANT v = GetPropAsVariant(prop.memid);
375 wxPyEndAllowThreads(tstate);
376 wxVariant wv;
377 if (!MSWVariantToVariant(v, wv) || PyErr_Occurred()) {
378 wxString msg;
0dabb2a2
RD
379 msg << _T("Unable to convert value to expected type: (")
380 << _VARTYPEname(prop.arg.vt) << _T(") for property <")
381 << name << _T(">");
b7c75283
RD
382 PyErr_SetString(PyExc_TypeError, msg.mb_str());
383 goto done;
384 }
385 rval = _Variant2PyObj(wv);
386 VariantClear(&v);
387 }
388 }
389 done:
0dabb2a2 390 wxPyEndBlockThreads(blocked);
b7c75283
RD
391 return rval;
392 }
393
394
395 // If both IsIn and isOut are false, assume it is actually an
396 // input param
397 bool paramIsIn(const wxParamX& p)
398 {
399 return p.IsIn() || (!p.IsIn() && !p.IsOut());
400 }
401
402
403 // Call a method of the ActiveX object
404 PyObject* _CallAXMethod(const wxString& name, PyObject* args)
405 {
406 VARIANTARG *vargs = NULL;
407 int nargs = 0;
408 PyObject* rval = NULL;
409 const wxFuncX& func = GetAXMethodDesc(name);
410
0dabb2a2 411 bool blocked = wxPyBeginBlockThreads();
b7c75283
RD
412 if (! PyErr_Occurred() ) {
413 nargs = func.params.size();
414 if (nargs > 0)
415 vargs = new VARIANTARG[nargs];
416
417 if (vargs) {
418 // init type of vargs, in reverse order
419 int i;
420 for (i = 0; i < nargs; i++)
421 vargs[nargs - i - 1].vt = func.params[i].vt;
422
423 // Map the args coming from Python to the input parameters in vargs
424 int pi = 0;
425 i = 0;
426 while ( i<nargs && pi<PyTuple_Size(args) ) {
427 // Move to the next input param.
428 if (! paramIsIn(func.params[i])) {
429 i += 1;
430 continue;
431 }
432 // convert the python object
433 PyObject* obj = PyTuple_GetItem(args, pi);
434 if (obj == Py_None) // special-case None?
435 vargs[nargs - i - 1].vt = VT_EMPTY;
436 else {
437 wxVariant wxV = _PyObj2Variant(obj);
438 if (PyErr_Occurred())
439 goto done;
440 if (!VariantToMSWVariant(wxV, vargs[nargs - i - 1]) || PyErr_Occurred()) {
441 wxString msg;
0dabb2a2 442 msg << _T("Unable to convert value to expected type: (")
b7c75283 443 << _VARTYPEname(vargs[nargs - i - 1].vt)
0dabb2a2 444 << _T(") for parameter ") << i;
b7c75283
RD
445 PyErr_SetString(PyExc_TypeError, msg.mb_str());
446 goto done;
447 }
448 }
449 i += 1;
450 pi += 1;
451 }
452 }
453
454 // call the method
455 PyThreadState* tstate = wxPyBeginAllowThreads();
456 VARIANT rv = CallMethod(func.memid, vargs, nargs);
457 wxPyEndAllowThreads(tstate);
458
459 // Convert the return value and any out-params, ignoring
460 // conversion errors for now
461 wxVariant wv;
462 MSWVariantToVariant(rv, wv);
463 rval = _Variant2PyObj(wv, True);
464 VariantClear(&rv);
465
466 if (func.hasOut) {
467 // make a list and put the rval in it if it is not None
468 PyObject* lst = PyList_New(0);
469 if (rval != Py_None)
470 PyList_Append(lst, rval);
471 else
472 Py_DECREF(rval);
473
474 // find the out params and convert them
475 for (int i = 0; i < nargs; i++) {
476 VARIANTARG& va = vargs[nargs - i - 1];
477 const wxParamX &px = func.params[i];
478 if (px.IsOut()) {
479 MSWVariantToVariant(va, wv);
480 PyObject* obj = _Variant2PyObj(wv, True);
481 PyList_Append(lst, obj);
482 }
483 }
484 rval = PyList_AsTuple(lst);
485 Py_DECREF(lst);
486 }
487 if (PyErr_Occurred())
488 PyErr_Clear();
489 }
490 done:
0dabb2a2 491 wxPyEndBlockThreads(blocked);
b7c75283
RD
492 if (vargs) {
493 for (int i = 0; i < nargs; i++)
494 VariantClear(&vargs[i]);
495 delete [] vargs;
496 }
497 return rval;
498 }
499};
500%}
501
502
503
504// Now tell SWIG about this new class that is implemented above.
505
506DocStr(wxActiveXWindow,
507"ActiveXWindow derives from wxWindow and the constructor accepts a
508CLSID for the ActiveX Control that should be created. The
509ActiveXWindow class simply adds methods that allow you to query
510some of the TypeInfo exposed by the ActiveX object, and also to
511get/set properties or call methods by name. The Python
512implementation automatically handles converting parameters and
513return values to/from the types expected by the ActiveX code as
514specified by the TypeInfo.
6cfd7f95 515", "");
b7c75283
RD
516
517
518class wxActiveXWindow : public wxWindow
519{
520public:
521 %pythonAppend wxActiveXWindow "self._setOORInfo(self)"
522
523 DocCtorStr(
524 wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
525 const wxPoint& pos = wxDefaultPosition,
526 const wxSize& size = wxDefaultSize,
527 long style = 0,
528 const wxString& name = wxPyPanelNameStr),
529 "Creates an ActiveX control from the clsID given and makes it act
6cfd7f95 530as much like a regular wx.Window as possible.", "");
b7c75283
RD
531
532 DocDeclStr(
533 const CLSID& , GetCLSID() const,
6cfd7f95 534 "Return the CLSID used to construct this ActiveX window", "");
b7c75283
RD
535
536
537 DocDeclStr(
538 int , GetAXEventCount() const,
6cfd7f95 539 "Number of events defined for this control", "");
b7c75283
RD
540
541 DocDeclStr(
542 const wxFuncX& , GetAXEventDesc(int idx) const,
6cfd7f95 543 "Returns event description by index", "");
b7c75283
RD
544
545
546 DocDeclStr(
547 int , GetAXPropCount() const,
6cfd7f95 548 "Number of properties defined for this control", "");
b7c75283
RD
549
550 %nokwargs GetAXPropDesc;
6cfd7f95 551 DocStr(GetPropDesc, "Returns property description by index or by name", "");
b7c75283
RD
552 const wxPropX& GetAXPropDesc(int idx) const;
553 const wxPropX& GetAXPropDesc(const wxString& name) const;
554
555
556
557 DocDeclStr(
558 int , GetAXMethodCount() const,
6cfd7f95 559 "Number of methods defined for this control", "");
b7c75283
RD
560
561 %nokwargs GetAXMethodDesc;
6cfd7f95 562 DocStr(GetMethodDesc, "Returns method description by index or name", "");
b7c75283
RD
563 const wxFuncX& GetAXMethodDesc(int idx) const;
564 const wxFuncX& GetAXMethodDesc(const wxString& name) const;
565
566
567 DocDeclStr(
568 const wxFuncXArray& , GetAXEvents(),
569 "Returns a sequence of FuncX objects describing the events
6cfd7f95 570available for this ActiveX object.", "");
b7c75283
RD
571
572 DocDeclStr(
573 const wxFuncXArray& , GetAXMethods(),
574 "Returns a sequence of FuncX objects describing the methods
6cfd7f95 575available for this ActiveX object.", "");
b7c75283
RD
576
577 DocDeclStr(
578 const wxPropXArray& , GetAXProperties(),
579 "Returns a sequence of PropX objects describing the properties
6cfd7f95 580available for this ActiveX object.", "");
b7c75283
RD
581
582
583
584 DocDeclStr(
585 void , SetAXProp(const wxString& name, PyObject* value),
6cfd7f95 586 "Set a property of the ActiveX object by name.", "");
b7c75283
RD
587
588
589 DocDeclStr(
590 PyObject* , GetAXProp(const wxString& name),
6cfd7f95 591 "Get the value of an ActiveX property by name.", "");
b7c75283
RD
592
593
594 %nokwargs _CallAXMethod;
595 DocDeclStr(
596 PyObject* , _CallAXMethod(const wxString& name, PyObject* args),
597 "The implementation for CallMethod. Calls an ActiveX method, by
6cfd7f95 598name passing the parameters given in args.", "");
b7c75283
RD
599 %pythoncode {
600 def CallAXMethod(self, name, *args):
601 """
602 Front-end for _CallMethod. Simply passes all positional args
603 after the name as a single tuple to _CallMethod.
604 """
605 return self._CallAXMethod(name, args)
606 }
607};
608
609//---------------------------------------------------------------------------
610%newgroup
611
612DocDeclStr(
613 wxEventType , RegisterActiveXEvent(const wxString& eventName),
6cfd7f95 614 "Creates a standard wx event ID for the given eventName.", "");
b7c75283
RD
615
616
617
618DocStr(wxActiveXEvent,
619"An instance of ActiveXEvent is sent to the handler for all bound
620ActiveX events. Any event parameters from the ActiveX cntrol are
621turned into attributes of the Python proxy for this event object.
622Additionally, there is a property called eventName that will
6cfd7f95 623return (surprisingly <wink>) the name of the ActiveX event.", "");
b7c75283
RD
624
625class wxActiveXEvent : public wxCommandEvent
626{
627public:
628 %feature("shadow") EventName "eventName = property(_activex.ActiveXEvent_EventName)";
629 wxString EventName();
630
631 %extend {
0dabb2a2
RD
632
633 // This is called by the EventThunker before calling the
634 // handler. We'll convert and load the ActiveX event parameters into
635 // attributes of the Python event object.
636 void _preCallInit(PyObject* pyself) {
637 bool blocked = wxPyBeginBlockThreads();
b7c75283
RD
638 PyObject* pList = PyList_New(0);
639 PyObject_SetAttrString(pyself, "paramList", pList);
640 Py_DECREF(pList);
641 for (int i=0; i<self->ParamCount(); i+=1) {
0dabb2a2 642 PyObject* name = PyString_FromString((char*)(const char*)self->ParamName(i).mb_str());
b7c75283
RD
643 PyObject* val = _Variant2PyObj((*self)[i], True);
644 PyObject_SetAttr(pyself, name, val);
645 PyList_Append(pList, name);
646 Py_DECREF(val);
647 Py_DECREF(name);
648 }
0dabb2a2
RD
649 wxPyEndBlockThreads(blocked);
650 }
651
652 // This one is called by the EventThunker after calling the
653 // handler. It reloads any "out" parameters from the python attributes
654 // back into the wxVariant they came from.
655 void _postCallCleanup(PyObject* pyself) {
656 bool blocked = wxPyBeginBlockThreads();
657 for (int i=0; i<self->ParamCount(); i+=1) {
658 PyObject* val = PyObject_GetAttrString(
659 pyself, (char*)(const char*)self->ParamName(i).mb_str());
660 _PyObj2Variant(val, (*self)[i]);
661 Py_DECREF(val);
662 }
663 wxPyEndBlockThreads(blocked);
b7c75283 664 }
0dabb2a2
RD
665
666
b7c75283
RD
667 }
668};
669
670//---------------------------------------------------------------------------
671
672%{
673
674// Caller should already have the GIL!
675wxVariant _PyObj2Variant(PyObject* value)
676{
677 wxVariant rval;
678
679 if (value == Py_None)
680 return rval;
681
0dabb2a2 682#if PYTHON_API_VERSION >= 1012 // Python 2.3+
b7c75283
RD
683 else if (PyBool_Check(value))
684 rval = (value == Py_True) ? true : false;
0dabb2a2
RD
685#endif
686
b7c75283
RD
687 else if (PyInt_Check(value))
688 rval = PyInt_AS_LONG(value);
689
690 else if (PyFloat_Check(value))
691 rval = PyFloat_AS_DOUBLE(value);
692
693 else if (PyString_Check(value) || PyUnicode_Check(value))
694 rval = Py2wxString(value);
695
696 // TODO: PyList of strings --> wxArrayString
697 // wxDateTime
698 // list of objects
0dabb2a2 699 // etc.
b7c75283
RD
700
701 else {
702 PyErr_SetString(PyExc_TypeError, "Unsupported object type in _PyObj2Variant");
703 rval = (long)0;
704 }
705
706 return rval;
707}
708
0dabb2a2
RD
709// This one uses the type of the variant to try and force the conversion
710bool _PyObj2Variant(PyObject* value, wxVariant& wv)
711{
712 wxString type = wv.GetType();
713
714 if ( type == _T("long") || type == _T("bool") || type == _T("char") )
715 wv = PyInt_AsLong(value);
716
717 else if ( type == _T("string") )
718 wv = Py2wxString(value);
719
720 else if ( type == _T("double") )
721 wv = PyFloat_AsDouble(value);
722
723 else {
724 // it's some other type that we dont' handle yet. Log it?
725 return false;
726 }
727 return true;
728}
b7c75283
RD
729
730// Caller should already have the GIL!
731PyObject* _Variant2PyObj(wxVariant& value, bool useNone)
732{
733 PyObject* rval = NULL;
734
735 if (value.IsNull()) {
736 rval = Py_None;
737 Py_INCREF(rval);
738 }
739
740 // should "char" be treated as an int or as a string?
741 else if (value.IsType(_T("char")) || value.IsType(_T("long")))
742 rval = PyInt_FromLong(value);
743
744 else if (value.IsType(_T("double")))
745 rval = PyFloat_FromDouble(value);
746
0dabb2a2
RD
747 else if (value.IsType(_T("bool"))) {
748 rval = (bool)value ? Py_True : Py_False;
749 Py_INCREF(rval);
750 }
b7c75283
RD
751
752 else if (value.IsType(_T("string")))
753 rval = wx2PyString(value);
754
755 else {
756 if (useNone) {
757 rval = Py_None;
758 Py_INCREF(rval);
759 }
760 else {
761 PyErr_SetString(PyExc_TypeError, "Unsupported object type in _Variant2PyObj");
762 }
763 }
764 return rval;
765}
766
767
768wxString _VARTYPEname(VARTYPE vt)
769{
770 if (vt & VT_BYREF)
771 vt &= ~(VT_BYREF);
772
773 switch(vt) {
774 case VT_VARIANT:
775 return _T("VT_VARIANT");
776
777 // 1 byte chars
778 case VT_I1:
779 case VT_UI1:
780 // 2 byte shorts
781 case VT_I2:
782 case VT_UI2:
783 // 4 bytes longs
784 case VT_I4:
785 case VT_UI4:
786 case VT_INT:
787 case VT_UINT:
788 case VT_ERROR:
789 return _T("int");
790
791 // 4 byte floats
792 case VT_R4:
793 // 8 byte doubles
794 case VT_R8:
795 // decimals are converted from doubles too
796 case VT_DECIMAL:
797 return _T("double");
798
799 case VT_BOOL:
800 return _T("bool");
801
802 case VT_DATE:
803 return _T("wx.DateTime");
804
805 case VT_BSTR:
806 return _T("string");
807
808 case VT_UNKNOWN:
809 return _T("VT_UNKNOWN");
810
811 case VT_DISPATCH:
812 return _T("VT_DISPATCH");
813
814 case VT_EMPTY:
815 return _T("VT_EMPTY");
816
817 case VT_NULL:
818 return _T("VT_NULL");
819
820 case VT_VOID:
821 return _T("VT_VOID");
822
823 default:
824 wxString msg;
825 msg << _T("unsupported type ") << vt;
826 return msg;
827 }
828}
829
830%}
831
832//---------------------------------------------------------------------------
833//---------------------------------------------------------------------------
834%newgroup
835
836
837%{
838// A class derived from out wxActiveXWindow for the IE WebBrowser
839// control that will serve as a base class for a Python
840// implementation. This is done so we can "eat our own dog food"
841// and use a class at least mostly generated by genaxmodule, but
842// also get some of the extra stuff like loading a document from
843// a string or a stream, getting text contents, etc. that
844// Lindsay's version gives us.
845//
846
847#include <wx/mstream.h>
848#include <oleidl.h>
849#include <winerror.h>
850#include <exdispid.h>
851#include <exdisp.h>
852#include <olectl.h>
853#include <Mshtml.h>
854#include <sstream>
855
856#include "IEHtmlStream.h"
857
858class wxIEHtmlWindowBase : public wxActiveXWindow {
859private:
860 wxAutoOleInterface<IWebBrowser2> m_webBrowser;
861
862public:
863
864 wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
865 const wxPoint& pos = wxDefaultPosition,
866 const wxSize& size = wxDefaultSize,
867 long style = 0,
868 const wxString& name = wxPyPanelNameStr)
869 : wxActiveXWindow(parent, clsId, id, pos, size, style, name)
870 {
871 HRESULT hret;
872
873 // Get IWebBrowser2 Interface
874 hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
83cbb9e9
RD
875 wxASSERT(SUCCEEDED(hret));
876
877 // web browser setup
878 m_webBrowser->put_MenuBar(VARIANT_FALSE);
879 m_webBrowser->put_AddressBar(VARIANT_FALSE);
880 m_webBrowser->put_StatusBar(VARIANT_FALSE);
881 m_webBrowser->put_ToolBar(VARIANT_FALSE);
882
883 m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
884 m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
885
886 m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
b7c75283
RD
887 }
888
889
890 void SetCharset(const wxString& charset)
891 {
892 HRESULT hret;
893
894 // HTML Document ?
895 IDispatch *pDisp = NULL;
896 hret = m_webBrowser->get_Document(&pDisp);
897 wxAutoOleInterface<IDispatch> disp(pDisp);
898
899 if (disp.Ok())
900 {
901 wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
902 if (doc.Ok())
903 doc->put_charset((BSTR) (const wchar_t *) charset.wc_str(wxConvUTF8));
904 //doc->put_charset((BSTR) wxConvUTF8.cMB2WC(charset).data());
905 }
906 }
907
908
909 bool LoadString(const wxString& html)
910 {
911 char *data = NULL;
912 size_t len = html.length();
913 len *= sizeof(wxChar);
914 data = (char *) malloc(len);
915 memcpy(data, html.c_str(), len);
916 return LoadStream(new wxOwnedMemInputStream(data, len));
917 }
918
919
920 bool LoadStream(IStreamAdaptorBase *pstrm)
921 {
922 // need to prepend this as poxy MSHTML will not recognise a HTML comment
923 // as starting a html document and treats it as plain text
924 // Does nayone know how to force it to html mode ?
0dabb2a2
RD
925#if wxUSE_UNICODE
926 // TODO: What to do in this case???
927#else
928 pstrm->prepend = _T("<html>");
929#endif
b7c75283
RD
930
931 // strip leading whitespace as it can confuse MSHTML
932 wxAutoOleInterface<IStream> strm(pstrm);
933
934 // Document Interface
935 IDispatch *pDisp = NULL;
936 HRESULT hret = m_webBrowser->get_Document(&pDisp);
937 if (! pDisp)
938 return false;
939 wxAutoOleInterface<IDispatch> disp(pDisp);
940
941
942 // get IPersistStreamInit
943 wxAutoOleInterface<IPersistStreamInit>
944 pPersistStreamInit(IID_IPersistStreamInit, disp);
945
946 if (pPersistStreamInit.Ok())
947 {
948 HRESULT hr = pPersistStreamInit->InitNew();
949 if (SUCCEEDED(hr))
950 hr = pPersistStreamInit->Load(strm);
951
952 return SUCCEEDED(hr);
953 }
954 else
955 return false;
956 }
957
958 bool LoadStream(wxInputStream *is)
959 {
960 // wrap reference around stream
961 IwxStreamAdaptor *pstrm = new IwxStreamAdaptor(is);
962 pstrm->AddRef();
963
964 return LoadStream(pstrm);
965 }
966
967
968 wxString GetStringSelection(bool asHTML)
969 {
970 wxAutoOleInterface<IHTMLTxtRange> tr(wxieGetSelRange(m_oleObject));
971 if (! tr)
972 return wxEmptyString;
973
974 BSTR text = NULL;
975 HRESULT hr = E_FAIL;
976
977 if (asHTML)
978 hr = tr->get_htmlText(&text);
979 else
980 hr = tr->get_text(&text);
981 if (hr != S_OK)
982 return wxEmptyString;
983
984 wxString s = text;
985 SysFreeString(text);
986
987 return s;
988 };
989
990 wxString GetText(bool asHTML)
991 {
992 if (! m_webBrowser.Ok())
993 return wxEmptyString;
994
995 // get document dispatch interface
996 IDispatch *iDisp = NULL;
997 HRESULT hr = m_webBrowser->get_Document(&iDisp);
998 if (hr != S_OK)
999 return wxEmptyString;
1000
1001 // Query for Document Interface
1002 wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
1003 iDisp->Release();
1004
1005 if (! hd.Ok())
1006 return wxEmptyString;
1007
1008 // get body element
1009 IHTMLElement *_body = NULL;
1010 hd->get_body(&_body);
1011 if (! _body)
1012 return wxEmptyString;
1013 wxAutoOleInterface<IHTMLElement> body(_body);
1014
1015 // get inner text
1016 BSTR text = NULL;
1017 hr = E_FAIL;
1018
1019 if (asHTML)
1020 hr = body->get_innerHTML(&text);
1021 else
1022 hr = body->get_innerText(&text);
1023 if (hr != S_OK)
1024 return wxEmptyString;
1025
1026 wxString s = text;
1027 SysFreeString(text);
1028
1029 return s;
1030 }
1031
1032
1033// void wxIEHtmlWin::SetEditMode(bool seton)
1034// {
1035// m_bAmbientUserMode = ! seton;
1036// AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
1037// };
1038
1039// bool wxIEHtmlWin::GetEditMode()
1040// {
1041// return ! m_bAmbientUserMode;
1042// };
1043};
1044%}
1045
1046
1047// we'll document it in the derived Python class
1048%feature("noautodoc") wxIEHtmlWindowBase;
1049%feature("noautodoc") wxIEHtmlWindowBase::SetCharset;
1050%feature("noautodoc") wxIEHtmlWindowBase::LoadString;
1051%feature("noautodoc") wxIEHtmlWindowBase::LoadStream;
1052%feature("noautodoc") wxIEHtmlWindowBase::GetStringSelection;
1053%feature("noautodoc") wxIEHtmlWindowBase::GetText;
1054
1055
1056class wxIEHtmlWindowBase : public wxActiveXWindow {
1057public:
1058
1059 wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
1060 const wxPoint& pos = wxDefaultPosition,
1061 const wxSize& size = wxDefaultSize,
1062 long style = 0,
1063 const wxString& name = wxPyPanelNameStr);
1064
1065 void SetCharset(const wxString& charset);
1066 bool LoadString(const wxString& html);
1067 bool LoadStream(wxInputStream *is);
1068 wxString GetStringSelection(bool asHTML);
1069 wxString GetText(bool asHTML);
1070};
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082#if 0
1083enum wxIEHtmlRefreshLevel
1084{
1085 wxIEHTML_REFRESH_NORMAL = 0,
1086 wxIEHTML_REFRESH_IFEXPIRED = 1,
1087 wxIEHTML_REFRESH_CONTINUE = 2,
1088 wxIEHTML_REFRESH_COMPLETELY = 3
1089};
1090
1091DocStr(wxIEHtmlWin,
1092"");
1093class wxIEHtmlWin : public wxWindow
1094{
1095public:
1096 %pythonAppend wxIEHtmlWin "self._setOORInfo(self)"
1097
1098 wxIEHtmlWin(wxWindow * parent, wxWindowID id = -1,
1099 const wxPoint& pos = wxDefaultPosition,
1100 const wxSize& size = wxDefaultSize,
1101 long style = 0,
1102 const wxString& name = wxPyPanelNameStr);
1103
1104 void LoadUrl(const wxString& url);
1105 bool LoadString(wxString html);
1106 bool LoadStream(wxInputStream *is);
1107
1108 %pythoncode { Navigate = LoadUrl }
1109
1110 void SetCharset(wxString charset);
1111 void SetEditMode(bool seton);
1112 bool GetEditMode();
1113 wxString GetStringSelection(bool asHTML = false);
1114 wxString GetText(bool asHTML = false);
1115
1116 bool GoBack();
1117 bool GoForward();
1118 bool GoHome();
1119 bool GoSearch();
1120 %name(RefreshPage)bool Refresh(wxIEHtmlRefreshLevel level);
1121 bool Stop();
1122};
1123
1124
1125
1126%pythoncode {
1127wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2 = RegisterActiveXEvent('BeforeNavigate2')
1128wxEVT_COMMAND_MSHTML_NEWWINDOW2 = RegisterActiveXEvent('NewWindow2')
1129wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE = RegisterActiveXEvent('DocumentComplete')
1130wxEVT_COMMAND_MSHTML_PROGRESSCHANGE = RegisterActiveXEvent('ProgressChange')
1131wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE = RegisterActiveXEvent('StatusTextChange')
1132wxEVT_COMMAND_MSHTML_TITLECHANGE = RegisterActiveXEvent('TitleChange')
1133
1134EVT_MSHTML_BEFORENAVIGATE2 = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2, 1)
1135EVT_MSHTML_NEWWINDOW2 = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_NEWWINDOW2, 1)
1136EVT_MSHTML_DOCUMENTCOMPLETE = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE, 1)
1137EVT_MSHTML_PROGRESSCHANGE = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE, 1)
1138EVT_MSHTML_STATUSTEXTCHANGE = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE, 1)
1139EVT_MSHTML_TITLECHANGE = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_TITLECHANGE, 1)
1140}
1141
1142#endif
1143
1144//---------------------------------------------------------------------------
1145// Include some extra Python code into the proxy module
1146
1147%pythoncode "_activex_ex.py"
1148
1149//---------------------------------------------------------------------------