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