diff --git a/etg/_html2.py b/etg/_html2.py
new file mode 100644
index 00000000..8b518fa5
--- /dev/null
+++ b/etg/_html2.py
@@ -0,0 +1,67 @@
+#---------------------------------------------------------------------------
+# Name: etg/_html2.py
+# Author: Robin Dunn
+#
+# Created: 20-Nov-2012
+# Copyright: (c) 2012 by Total Control Software
+# License: wxWindows License
+#---------------------------------------------------------------------------
+
+import etgtools
+import etgtools.tweaker_tools as tools
+from etgtools import PyFunctionDef, PyCodeDef, PyPropertyDef
+
+PACKAGE = "wx"
+MODULE = "_html2"
+NAME = "_html2" # Base name of the file to generate to for this script
+DOCSTRING = ""
+
+# The classes and/or the basename of the Doxygen XML files to be processed by
+# this script.
+ITEMS = [ ]
+
+
+# The list of other ETG scripts and back-end generator modules that are
+# included as part of this module. These should all be items that are put in
+# the wxWidgets "webview" library in a multi-lib build.
+INCLUDES = [ 'webview',
+ ]
+
+
+# Separate the list into those that are generated from ETG scripts and the
+# rest. These lists can be used from the build scripts to get a list of
+# sources and/or additional dependencies when building this extension module.
+ETGFILES = ['etg/%s.py' % NAME] + tools.getEtgFiles(INCLUDES)
+DEPENDS = tools.getNonEtgFiles(INCLUDES)
+OTHERDEPS = [ ]
+
+
+#---------------------------------------------------------------------------
+
+def run():
+ # Parse the XML file(s) building a collection of Extractor objects
+ module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING)
+ etgtools.parseDoxyXML(module, ITEMS)
+ module.check4unittest = False
+
+ #-----------------------------------------------------------------
+ # Tweak the parsed meta objects in the module object as needed for
+ # customizing the generated code and docstrings.
+
+ module.addHeaderCode('#include ')
+ module.addImport('_core')
+ module.addPyCode('import wx', order=10)
+ module.addInclude(INCLUDES)
+
+
+ #-----------------------------------------------------------------
+ #-----------------------------------------------------------------
+ tools.doCommonTweaks(module)
+ tools.runGenerators(module)
+
+
+
+#---------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ run()
diff --git a/etg/webview.py b/etg/webview.py
new file mode 100644
index 00000000..bb631cab
--- /dev/null
+++ b/etg/webview.py
@@ -0,0 +1,124 @@
+#---------------------------------------------------------------------------
+# Name: etg/webview.py
+# Author: Robin Dunn
+#
+# Created: 20-Nov-2012
+# Copyright: (c) 2012 by Total Control Software
+# License: wxWindows License
+#---------------------------------------------------------------------------
+
+import etgtools
+import etgtools.tweaker_tools as tools
+
+PACKAGE = "wx"
+MODULE = "_html2"
+NAME = "webview" # Base name of the file to generate to for this script
+DOCSTRING = ""
+
+# The classes and/or the basename of the Doxygen XML files to be processed by
+# this script.
+ITEMS = [ 'wxWebViewHistoryItem',
+ 'wxWebViewHandler',
+ 'wxWebViewArchiveHandler',
+ 'wxWebViewFSHandler',
+ 'wxWebView',
+ 'wxWebViewEvent',
+ ]
+
+#---------------------------------------------------------------------------
+
+def run():
+ # Parse the XML file(s) building a collection of Extractor objects
+ module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING)
+ etgtools.parseDoxyXML(module, ITEMS)
+
+ #-----------------------------------------------------------------
+ # Tweak the parsed meta objects in the module object as needed for
+ # customizing the generated code and docstrings.
+
+ module.addHeaderCode('#include ')
+
+ c = module.find('wxWebView')
+ assert isinstance(c, etgtools.ClassDef)
+ tools.fixWindowClass(c)
+ c.abstract = True
+
+ module.addGlobalStr('wxWebViewNameStr', c)
+ module.addGlobalStr('wxWebViewDefaultURLStr', c)
+
+ for m in c.find('New').all():
+ m.factory = True
+ c.find('New.id').default = 'wxID_ANY'
+ c.find('New.parent').transferThis = True
+
+
+ c.find('RegisterHandler.handler').type = 'wxWebViewHandler*'
+ c.find('RegisterHandler.handler').transfer = True
+ c.find('RegisterHandler').setCppCode_sip(
+ "sipCpp->RegisterHandler(wxSharedPtr(handler));")
+
+
+ # Custom code to deal with the
+ # wxVector> return type of these two
+ # methods. We'll just convert them to a Python list of history items.
+ code = """\
+ wxPyThreadBlocker blocker;
+ PyObject* result = PyList_New(0);
+ wxVector > vector = self->{method}();
+ for (size_t idx=0; idx < vector.size(); idx++) {{
+ PyObject* obj;
+ wxWebViewHistoryItem* item = new wxWebViewHistoryItem(*vector[idx].get());
+ obj = wxPyConstructObject((void*)item, "wxWebViewHistoryItem", true);
+ PyList_Append(result, obj);
+ Py_DECREF(obj);
+ }}
+ return result;
+ """
+ c.find('GetBackwardHistory').type = 'PyObject*'
+ c.find('GetBackwardHistory').setCppCode(code.format(method='GetBackwardHistory'))
+ c.find('GetForwardHistory').type = 'PyObject*'
+ c.find('GetForwardHistory').setCppCode(code.format(method='GetForwardHistory'))
+
+
+ # Since LoadHistoryItem expects to get an actual item in the history
+ # list, and since we make copies of the items in the cppCode above, then
+ # this won't be possible to do from the Python wrappers. However, it's
+ # just as easy to use LoadURL to reload a history item so it's not a
+ # great loss.
+ c.find('LoadHistoryItem').ignore()
+ ##c.find('LoadHistoryItem.item').type = 'wxWebViewHistoryItem*'
+ ##c.find('LoadHistoryItem.item').transfer = True
+ ##c.find('LoadHistoryItem').setCppCode_sip(
+ ## "sipCpp->LoadHistoryItem(wxSharedPtr(item));")
+
+
+
+
+
+ c = module.find('wxWebViewEvent')
+ tools.fixEventClass(c)
+
+ module.addPyCode("""\
+ EVT_WEB_VIEW_NAVIGATING = wx.PyEventBinder( wxEVT_COMMAND_WEB_VIEW_NAVIGATING, 1 )
+ EVT_WEB_VIEW_NAVIGATED = wx.PyEventBinder( wxEVT_COMMAND_WEB_VIEW_NAVIGATED, 1 )
+ EVT_WEB_VIEW_LOADED = wx.PyEventBinder( wxEVT_COMMAND_WEB_VIEW_LOADED, 1 )
+ EVT_WEB_VIEW_ERROR = wx.PyEventBinder( wxEVT_COMMAND_WEB_VIEW_ERROR, 1 )
+ EVT_WEB_VIEW_NEWWINDOW = wx.PyEventBinder( wxEVT_COMMAND_WEB_VIEW_NEWWINDOW, 1 )
+ EVT_WEB_VIEW_TITLE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED, 1 )
+ """)
+
+
+
+ c = module.find('wxWebViewHistoryItem')
+ tools.addAutoProperties(c)
+
+
+ #-----------------------------------------------------------------
+ tools.doCommonTweaks(module)
+ tools.runGenerators(module)
+
+
+#---------------------------------------------------------------------------
+if __name__ == '__main__':
+ run()
+
diff --git a/samples/html2/HTML2_WebView.py b/samples/html2/HTML2_WebView.py
new file mode 100644
index 00000000..07de949c
--- /dev/null
+++ b/samples/html2/HTML2_WebView.py
@@ -0,0 +1,161 @@
+import sys
+import wx
+import wx.html2 as webview
+
+#----------------------------------------------------------------------
+
+class TestPanel(wx.Panel):
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent)
+
+ self.current = "http://wxPython.org"
+ self.frame = self.GetTopLevelParent()
+ self.titleBase = self.frame.GetTitle()
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.wv = webview.WebView.New(self)
+ self.Bind(webview.EVT_WEB_VIEW_NAVIGATING, self.OnWebViewNavigating, self.wv)
+ self.Bind(webview.EVT_WEB_VIEW_NAVIGATED, self.OnWebViewNavigated, self.wv)
+ self.Bind(webview.EVT_WEB_VIEW_LOADED, self.OnWebViewLoaded, self.wv)
+ self.Bind(webview.EVT_WEB_VIEW_TITLE_CHANGED, self.OnWebViewTitleChanged, self.wv)
+
+ btn = wx.Button(self, -1, "Open", style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)
+ btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
+
+ btn = wx.Button(self, -1, "<--", style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)
+ btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoBack, btn)
+
+ btn = wx.Button(self, -1, "-->", style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)
+ btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanGoForward, btn)
+
+ btn = wx.Button(self, -1, "Stop", style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnStopButton, btn)
+ btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
+
+ btn = wx.Button(self, -1, "Refresh", style=wx.BU_EXACTFIT)
+ self.Bind(wx.EVT_BUTTON, self.OnRefreshPageButton, btn)
+ btnSizer.Add(btn, 0, wx.EXPAND|wx.ALL, 2)
+
+ txt = wx.StaticText(self, -1, "Location:")
+ btnSizer.Add(txt, 0, wx.CENTER|wx.ALL, 2)
+
+ self.location = wx.ComboBox(
+ self, -1, "", style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
+ self.location.AppendItems(['http://wxPython.org',
+ 'http://wxwidgets.org',
+ 'http://google.com'])
+
+ #for url in ['http://wxPython.org',
+ # 'http://wxwidgets.org',
+ # 'http://google.com']:
+ # item = webview.WebViewHistoryItem(url, url)
+ # self.wv.LoadHistoryItem(item)
+
+ self.Bind(wx.EVT_COMBOBOX, self.OnLocationSelect, self.location)
+ self.location.Bind(wx.EVT_TEXT_ENTER, self.OnLocationEnter)
+ btnSizer.Add(self.location, 1, wx.EXPAND|wx.ALL, 2)
+
+
+ sizer.Add(btnSizer, 0, wx.EXPAND)
+ sizer.Add(self.wv, 1, wx.EXPAND)
+ self.SetSizer(sizer)
+
+ self.wv.LoadURL(self.current)
+
+
+
+ # WebView events
+ def OnWebViewNavigating(self, evt):
+ # this event happens prior to trying to get a resource
+ if evt.GetURL() == 'http://www.microsoft.com/':
+ if wx.MessageBox("Are you sure you want to visit Microsoft?",
+ style=wx.YES_NO|wx.ICON_QUESTION) == wx.NO:
+ # This is how you can cancel loading a page.
+ evt.Veto()
+
+
+ def OnWebViewNavigated(self, evt):
+ self.frame.SetStatusText("Loading %s..." % evt.GetURL())
+
+
+ def OnWebViewLoaded(self, evt):
+ # The full document has loaded
+ self.current = evt.GetURL()
+ self.location.SetValue(self.current)
+ self.frame.SetStatusText("Loaded")
+
+
+ def OnWebViewTitleChanged(self, evt):
+ # Set the frame's title to include the document's title
+ self.frame.SetTitle("%s -- %s" % (self.titleBase, evt.GetString()))
+
+
+ # Control bar events
+ def OnLocationSelect(self, evt):
+ url = self.location.GetStringSelection()
+ print('OnLocationSelect: %s\n' % url)
+ self.wv.LoadURL(url)
+
+ def OnLocationEnter(self, evt):
+ url = self.location.GetValue()
+ self.location.Append(url)
+ self.wv.LoadURL(url)
+
+
+ def OnOpenButton(self, event):
+ dlg = wx.TextEntryDialog(self, "Open Location",
+ "Enter a full URL or local path",
+ self.current, wx.OK|wx.CANCEL)
+ dlg.CentreOnParent()
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.current = dlg.GetValue()
+ self.wv.LoadURL(self.current)
+
+ dlg.Destroy()
+
+ def OnPrevPageButton(self, event):
+ for i in self.wv.GetBackwardHistory():
+ print i.Url, i.Title
+ self.wv.GoBack()
+
+ def OnNextPageButton(self, event):
+ for i in self.wv.GetForwardHistory():
+ print i.URL, i.Title
+ self.wv.GoForward()
+
+ def OnCheckCanGoBack(self, event):
+ event.Enable(self.wv.CanGoBack())
+
+ def OnCheckCanGoForward(self, event):
+ event.Enable(self.wv.CanGoForward())
+
+ def OnStopButton(self, evt):
+ self.wv.Stop()
+
+ def OnRefreshPageButton(self, evt):
+ self.wv.Reload()
+
+
+#----------------------------------------------------------------------
+
+
+def main():
+ app = wx.App()
+ frm = wx.Frame(None, title="html2.WebView sample", size=(700,500))
+ frm.CreateStatusBar()
+ pnl = TestPanel(frm)
+ frm.Show()
+ app.MainLoop()
+
+
+#----------------------------------------------------------------------
+
+if __name__ == '__main__':
+ main()
diff --git a/setup.py b/setup.py
index 06d27ee5..be26bdb9 100644
--- a/setup.py
+++ b/setup.py
@@ -229,6 +229,22 @@ extensions.append(ext)
cfg.CLEANUP.append(opj(cfg.PKGDIR, 'glcanvas.py'))
+etg = loadETG('etg/_html2.py')
+tgDepends = etg.DEPENDS + etg.OTHERDEPS
+ext = Extension('_html2', getEtgSipCppFiles(etg),
+ depends = getEtgSipHeaders(etg),
+ include_dirs = cfg.includes,
+ define_macros = cfg.defines,
+ library_dirs = cfg.libdirs,
+ libraries = cfg.libs + cfg.makeLibName('webview', True),
+ extra_compile_args = cfg.cflags,
+ extra_link_args = cfg.lflags,
+ )
+extensions.append(ext)
+cfg.CLEANUP.append(opj(cfg.PKGDIR, 'html2.py'))
+
+
+
#----------------------------------------------------------------------
if __name__ == '__main__':
diff --git a/unittests/test_pi_import.py b/unittests/test_pi_import.py
index 7912d8dd..e8f2997c 100644
--- a/unittests/test_pi_import.py
+++ b/unittests/test_pi_import.py
@@ -43,6 +43,9 @@ class PIImportTest(unittest.TestCase):
def test_html_pi(self):
self.runPI('html.pi')
+ def test_html2_pi(self):
+ self.runPI('html2.pi')
+
def test_dataview_pi(self):
self.runPI('dataview.pi')
diff --git a/unittests/test_webview.py b/unittests/test_webview.py
new file mode 100644
index 00000000..de8cdb42
--- /dev/null
+++ b/unittests/test_webview.py
@@ -0,0 +1,78 @@
+import imp_unittest, unittest
+import wtc
+import wx
+import wx.html2 as webview
+
+#---------------------------------------------------------------------------
+
+class webview_Tests(wtc.WidgetTestCase):
+
+ def test_webview1(self):
+ wv = webview.WebView.New()
+ wv.Create(self.frame)
+
+ def test_webview2(self):
+ wv = webview.WebView.New(self.frame)
+
+ def test_webview3(self):
+ wv = webview.WebView.New(self.frame)
+ self.frame.SendSizeEvent()
+ wv.LoadURL('file://' + __file__)
+ while wv.IsBusy():
+ self.myYield()
+ h = wv.GetBackwardHistory()
+ self.assertTrue(isinstance(h, list))
+ if len(h):
+ self.assertTrue(isinstance(h[0], webview.WebViewHistoryItem))
+
+
+ def test_webview5(self):
+ webview.WEB_VIEW_ZOOM_TINY
+ webview.WEB_VIEW_ZOOM_SMALL
+ webview.WEB_VIEW_ZOOM_MEDIUM
+ webview.WEB_VIEW_ZOOM_LARGE
+ webview.WEB_VIEW_ZOOM_LARGEST
+ webview.WEB_VIEW_ZOOM_TYPE_LAYOUT
+ webview.WEB_VIEW_ZOOM_TYPE_TEXT
+ webview.WEB_NAV_ERR_CONNECTION
+ webview.WEB_NAV_ERR_CERTIFICATE
+ webview.WEB_NAV_ERR_AUTH
+ webview.WEB_NAV_ERR_SECURITY
+ webview.WEB_NAV_ERR_NOT_FOUND
+ webview.WEB_NAV_ERR_REQUEST
+ webview.WEB_NAV_ERR_USER_CANCELLED
+ webview.WEB_NAV_ERR_OTHER
+ webview.WEB_VIEW_RELOAD_DEFAULT
+ webview.WEB_VIEW_RELOAD_NO_CACHE
+ webview.WEB_VIEW_FIND_WRAP
+ webview.WEB_VIEW_FIND_ENTIRE_WORD
+ webview.WEB_VIEW_FIND_MATCH_CASE
+ webview.WEB_VIEW_FIND_HIGHLIGHT_RESULT
+ webview.WEB_VIEW_FIND_BACKWARDS
+ webview.WEB_VIEW_FIND_DEFAULT
+ webview.WEB_VIEW_BACKEND_DEFAULT
+ webview.WEB_VIEW_BACKEND_WEBKIT
+ webview.WEB_VIEW_BACKEND_IE
+
+
+ def test_webview6(self):
+ webview.wxEVT_COMMAND_WEB_VIEW_NAVIGATING
+ webview.wxEVT_COMMAND_WEB_VIEW_NAVIGATED
+ webview.wxEVT_COMMAND_WEB_VIEW_LOADED
+ webview.wxEVT_COMMAND_WEB_VIEW_ERROR
+ webview.wxEVT_COMMAND_WEB_VIEW_NEWWINDOW
+ webview.wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED
+
+ webview.EVT_WEB_VIEW_NAVIGATING
+ webview.EVT_WEB_VIEW_NAVIGATED
+ webview.EVT_WEB_VIEW_LOADED
+ webview.EVT_WEB_VIEW_ERROR
+ webview.EVT_WEB_VIEW_NEWWINDOW
+ webview.EVT_WEB_VIEW_TITLE_CHANGED
+
+
+
+#---------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/wscript b/wscript
index c8cb9257..39acd96e 100644
--- a/wscript
+++ b/wscript
@@ -90,6 +90,8 @@ def configure(conf):
_copyEnvGroup(conf.env, '_WX', '_WXGL')
conf.env.LIB_WXGL += cfg.makeLibName('gl')
+ _copyEnvGroup(conf.env, '_WX', '_WXWEBVIEW')
+ conf.env.LIB_WXWEBVIEW += cfg.makeLibName('webview')
@@ -142,6 +144,10 @@ def configure(conf):
args='--cxxflags --libs gl,core,net',
uselib_store='WXGL', mandatory=True)
+ conf.check_cfg(path=conf.options.wx_config, package='',
+ args='--cxxflags --libs webview,core,net',
+ uselib_store='WXWEBVIEW', mandatory=True)
+
# NOTE: This assumes that if the platform is not win32 (from
# the test above) and not darwin then we must be using the
@@ -314,6 +320,16 @@ def build(bld):
makeExtCopyRule(bld, '_glcanvas')
+ etg = loadETG('etg/_html2.py')
+ adv = bld(
+ features = 'c cxx cxxshlib pyext',
+ target = makeTargetName(bld, '_html2'),
+ source = getEtgSipCppFiles(etg) + rc,
+ uselib = 'WXWEBVIEW WXPY',
+ )
+ makeExtCopyRule(bld, '_html2')
+
+
#-----------------------------------------------------------------------------
# helpers