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