~ubuntu-dev/wxwidgets2.6/upstream-debian

« back to all changes in this revision

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

  • Committer: Daniel T Chen
  • Date: 2006-06-26 10:15:11 UTC
  • Revision ID: crimsun@ubuntu.com-20060626101511-a4436cec4c6d9b35
ImportĀ DebianĀ 2.6.3.2.1

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,v 1.13 2005/03/09 22:28:52 RD Exp $
 
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
//---------------------------------------------------------------------------