~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to wxPython/contrib/activex/activex.i

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: activex.i 39219 2006-05-19 01:10:46Z RD $
 
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
//---------------------------------------------------------------------------