diff --git a/utils/wxPython/CHANGES.txt b/utils/wxPython/CHANGES.txt index c52bc4f584..1e64e58800 100644 --- a/utils/wxPython/CHANGES.txt +++ b/utils/wxPython/CHANGES.txt @@ -24,7 +24,13 @@ new classes are not documented yet, (however the methods are more consistent with each other now so you may be able to guess pretty good...) +Updated filebrowsebutton.py and calendar.py with changes from their +authors. There is now a FileBrowseButtonWithhistory class (what a +mouthful!) and wxCalendar has printing support. +Added ActiveXWrapper to the library, and some good demos of it too. +It works great for embedding a COM (a.k.a OCX, a.k.a Activex) control +in a window and calling its methods. diff --git a/utils/wxPython/demo/ActiveXWrapper_Acrobat.py b/utils/wxPython/demo/ActiveXWrapper_Acrobat.py index 4d21673314..a232a05a19 100644 --- a/utils/wxPython/demo/ActiveXWrapper_Acrobat.py +++ b/utils/wxPython/demo/ActiveXWrapper_Acrobat.py @@ -1,40 +1,15 @@ """ -ActiveXControl sample usage. - -Based on original code by Willy Heineman, wheineman@uconect.net, 14 February 2000 - -ActiveXControl provides a simplified wrapper for creating activeX -controls within wxPython GUIs. It allows you to include the activeX -control in a sizer, and includes a flag to prevent redrawing the -background behind the control (reduces the annoying flicker on -Win32 systems). """ + from wxPython.wx import * -from wxPython.lib.activexwrapper import ActiveXWrapper +from wxPython.lib.activexwrapper import MakeActiveXClass -import pythoncom -import pywin.mfc.activex import win32com.client.gencache -import win32con -import win32ui -acrobatOCX = win32com.client.gencache.EnsureModule('{CA8A9783-280D-11CF-A24D-444553540000}', 0x0, 1, 3) -if acrobatOCX is None: - win32ui.MessageBox("Can't load PDF.OCX, install Acrobat 4.0", - 'ActiveX Demo', - win32con.MB_OK | win32con.MB_ICONSTOP) - raise ImportError - - -#---------------------------------------------------------------------- -# NOTE: -# Your ActiveX control _must_ be an instance of pywin.mfc.activex.Control, -# as we use the CreateControl method to bind the GUI systems. - -class PDFControl(pywin.mfc.activex.Control, acrobatOCX.Pdf): - def __init__(self): - pywin.mfc.activex.Control.__init__(self) - acrobatOCX.Pdf.__init__(self) +try: + acrobat = win32com.client.gencache.EnsureModule('{CA8A9783-280D-11CF-A24D-444553540000}', 0x0, 1, 3) +except: + raise ImportError("Can't load PDF.OCX, install Acrobat 4.0") #---------------------------------------------------------------------- @@ -47,12 +22,14 @@ class TestPanel(wxPanel): sizer = wxBoxSizer(wxVERTICAL) btnSizer = wxBoxSizer(wxHORIZONTAL) - # Build the wxPython wrapper window and put the Acrobat - # control in it - self.axw = ActiveXWrapper( self, -1, style=wxSUNKEN_BORDER, eraseBackground=0) - self.axw.SetControl( PDFControl() ) + # this function creates a new class that can be used as + # a wxWindow, but contains the given ActiveX control. + ActiveXWrapper = MakeActiveXClass(acrobat.Pdf) - sizer.Add(self.axw, 1, wxEXPAND) + # create an instance of the new class + self.pdf = ActiveXWrapper( self, -1, style=wxSUNKEN_BORDER) + + sizer.Add(self.pdf, 1, wxEXPAND) btn = wxButton(self, wxNewId(), "Open PDF File") EVT_BUTTON(self, btn.GetId(), self.OnOpenButton) @@ -74,24 +51,26 @@ class TestPanel(wxPanel): self.SetAutoLayout(true) def __del__(self): - self.axw.Cleanup() - self.axw = None + self.pdf.Cleanup() + self.pdf = None def OnOpenButton(self, event): dlg = wxFileDialog(self, wildcard="*.pdf") if dlg.ShowModal() == wxID_OK: - self.axw.control.LoadFile(dlg.GetPath()) + wxBeginBusyCursor() + self.pdf.LoadFile(dlg.GetPath()) + wxEndBusyCursor() dlg.Destroy() def OnPrevPageButton(self, event): - self.axw.control.gotoPreviousPage() + self.pdf.gotoPreviousPage() def OnNextPageButton(self, event): - self.axw.control.gotoNextPage() + self.pdf.gotoNextPage() @@ -110,11 +89,12 @@ overview = __doc__ if __name__ == '__main__': class TestFrame(wxFrame): def __init__(self): - wxFrame.__init__(self, None, -1, "ActiveX test -- Acrobat", size=(640, 480)) + wxFrame.__init__(self, None, -1, "ActiveX test -- Acrobat", size=(640, 480), + style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE) self.tp = TestPanel(self, sys.stdout) def OnCloseWindow(self, event): - self.tp.axw.Cleanup() + self.tp.pdf.Cleanup() self.Destroy() diff --git a/utils/wxPython/demo/ActiveXWrapper_IE.py b/utils/wxPython/demo/ActiveXWrapper_IE.py index c24f35e641..4a797acc8a 100644 --- a/utils/wxPython/demo/ActiveXWrapper_IE.py +++ b/utils/wxPython/demo/ActiveXWrapper_IE.py @@ -1,85 +1,73 @@ """ -ActiveXControl sample usage. - -Based on original code by Willy Heineman, wheineman@uconect.net, 14 February 2000 - -ActiveXControl provides a simplified wrapper for creating activeX -controls within wxPython GUIs. """ from wxPython.wx import * -from wxPython.lib.activexwrapper import ActiveXWrapper +from wxPython.lib.activexwrapper import MakeActiveXClass -import pythoncom -import pywin.mfc.activex import win32com.client.gencache -import win32con -import win32ui - -browserModule = win32com.client.gencache.EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1) -if browserModule is None: - win32ui.MessageBox("IE4 or greater does not appear to be installed.", - 'ActiveX Demo', - win32con.MB_OK | win32con.MB_ICONSTOP) - raise ImportError - - -#---------------------------------------------------------------------- -# NOTE: -# Your ActiveX control _must_ be an instance of pywin.mfc.activex.Control, -# as we use the CreateControl method to bind the GUI systems. - -class WebBrowserControl(pywin.mfc.activex.Control, - browserModule.WebBrowser): - - def __init__(self): - pywin.mfc.activex.Control.__init__(self) - browserModule.WebBrowser.__init__(self) +try: + browserModule = win32com.client.gencache.EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1) +except: + raise ImportError("IE4 or greater does not appear to be installed.") #---------------------------------------------------------------------- class TestPanel(wxPanel): def __init__(self, parent, log): - wxPanel.__init__(self, parent, -1) + wxPanel.__init__(self, parent, -1)#, style=wxCLIP_CHILDREN) self.log = log self.current = "http://alldunn.com/" sizer = wxBoxSizer(wxVERTICAL) btnSizer = wxBoxSizer(wxHORIZONTAL) - # Build the wxPython wrapper window and put the Acrobat - # control in it - self.axw = ActiveXWrapper( self, -1, style=wxSUNKEN_BORDER, eraseBackground=0) - self.axw.SetControl( WebBrowserControl() ) - sizer.Add(self.axw, 1, wxEXPAND) + # Make a new class that derives from the WebBrowser class in the + # COM module imported above. This class also drives from wxWindow and + # implements the machinery needed to integrate the two things. + theClass = MakeActiveXClass(browserModule.WebBrowser, + eventObj = self) - self.axw.control.Navigate(self.current) + # Create an instance of that class + self.ie = theClass(self, -1, style=wxSUNKEN_BORDER) - btn = wxButton(self, wxNewId(), "Open Location") + + btn = wxButton(self, wxNewId(), " Open ") EVT_BUTTON(self, btn.GetId(), self.OnOpenButton) - btnSizer.Add(btn, 1, wxEXPAND|wxALL, 5) + btnSizer.Add(btn, 0, wxEXPAND|wxALL, 5) - btn = wxButton(self, wxNewId(), "<-- Back Page") + btn = wxButton(self, wxNewId(), " <-- ") EVT_BUTTON(self, btn.GetId(), self.OnPrevPageButton) - btnSizer.Add(btn, 1, wxEXPAND|wxALL, 5) + btnSizer.Add(btn, 0, wxEXPAND|wxALL, 5) - btn = wxButton(self, wxNewId(), "Forward Page -->") + btn = wxButton(self, wxNewId(), " --> ") EVT_BUTTON(self, btn.GetId(), self.OnNextPageButton) - btnSizer.Add(btn, 1, wxEXPAND|wxALL, 5) + btnSizer.Add(btn, 0, wxEXPAND|wxALL, 5) + + txt = wxStaticText(self, -1, "Location:") + btnSizer.Add(txt, 0, wxCENTER|wxALL, 5) + + self.location = wxComboBox(self, wxNewId(), "", style=wxCB_DROPDOWN) + EVT_COMBOBOX(self, self.location.GetId(), self.OnLocationSelect) + btnSizer.Add(self.location, 1, wxEXPAND|wxALL, 5) - btnSizer.Add(50, -1, 2, wxEXPAND) sizer.Add(btnSizer, 0, wxEXPAND) + sizer.Add(self.ie, 1, wxEXPAND) + + self.ie.Navigate(self.current) + self.SetSizer(sizer) self.SetAutoLayout(true) def __del__(self): - self.axw.Cleanup() - self.axw = None + self.ie.Cleanup() + self.ie = None + def OnLocationSelect(self, evt): + pass def OnOpenButton(self, event): dlg = wxTextEntryDialog(self, "Open Location", @@ -88,16 +76,29 @@ class TestPanel(wxPanel): dlg.CentreOnParent() if dlg.ShowModal() == wxID_OK: self.current = dlg.GetValue() - self.axw.control.Navigate(self.current) + self.ie.Navigate(self.current) dlg.Destroy() def OnPrevPageButton(self, event): - self.axw.control.GoBack() + self.ie.GoBack() def OnNextPageButton(self, event): - self.axw.control.GoForward() + self.ie.GoForward() + + + # The following event handlers are called by the web browser COM + # control since we passed self to MakeActiveXClass. It will look + # here for matching attributes and call them if they exist. See the + # module generated by makepy for details of method names, etc. + def OnBeforeNavigate2(self, pDisp, URL, *args): + self.log.write('OnBeforeNavigate2: %s\n' % URL) + + def OnNavigateComplete2(self, pDisp, URL): + self.log.write('OnNavigateComplete2: %s\n' % URL) + self.current = URL + self.location.SetValue(URL) #---------------------------------------------------------------------- @@ -116,11 +117,13 @@ overview = __doc__ if __name__ == '__main__': class TestFrame(wxFrame): def __init__(self): - wxFrame.__init__(self, None, -1, "ActiveX test -- Internet Explorer", size=(640, 480)) + wxFrame.__init__(self, None, -1, "ActiveX test -- Internet Explorer", + size=(640, 480), + style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE) self.tp = TestPanel(self, sys.stdout) def OnCloseWindow(self, event): - self.tp.axw.Cleanup() + self.tp.ie.Cleanup() self.Destroy() diff --git a/utils/wxPython/demo/Main.py b/utils/wxPython/demo/Main.py index e3c4b5d371..8305df58f2 100644 --- a/utils/wxPython/demo/Main.py +++ b/utils/wxPython/demo/Main.py @@ -63,7 +63,8 @@ _treeList = [ class wxPythonDemo(wxFrame): def __init__(self, parent, id, title): - wxFrame.__init__(self, parent, -1, title, size = (725, 550)) + wxFrame.__init__(self, parent, -1, title, size = (725, 550), + style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE) self.cwd = os.getcwd() diff --git a/utils/wxPython/demo/wxCalendar.py b/utils/wxPython/demo/wxCalendar.py index eda9cd341a..4a9772fa6b 100644 --- a/utils/wxPython/demo/wxCalendar.py +++ b/utils/wxPython/demo/wxCalendar.py @@ -1,18 +1,16 @@ -#! /usr/local/bin/python #---------------------------------------------------------------------------- -# Name: CalendPanel.py -# Purpose: Calendar control display testing on panel +# Name: wxCalendar.py +# Purpose: Calendar control display testing on panel for wxPython demo # # Author: Lorne White (email: lwhite1@planet.eon.net) # # Created: -# Version 0.5 1999/11/03 +# Version 0.7 200/03/30 # Licence: wxWindows license #---------------------------------------------------------------------------- from wxPython.wx import * -from wxPython.lib.calendar import wxCalendar, Month - +from wxPython.lib.calendar import wxCalendar, Month, PrtCalDraw import os dir_path = os.getcwd() @@ -45,10 +43,11 @@ def GetMonthList(): return monthlist class TestPanel(wxPanel): - def __init__(self, parent, log): + def __init__(self, parent, log, frame): wxPanel.__init__(self, parent, -1) self.log = log + self.frame = frame self.calend = wxCalendar(self, -1, wxPoint(100, 50), wxSize(200, 180)) @@ -69,7 +68,7 @@ class TestPanel(wxPanel): # set attributes of calendar - self.calend.HideTitle() + self.calend.hide_title = TRUE self.calend.HideGrid() # display routine @@ -98,7 +97,7 @@ class TestPanel(wxPanel): # button for calendar dialog test - wxStaticText(self, -1, "Test Calendar Dialog", wxPoint(350, 50)).SetBackgroundColour(wxNamedColour('Red')) + wxStaticText(self, -1, "Test Calendar Dialog", wxPoint(350, 50), wxSize(150, -1)) bmp = wxBitmap('bitmaps/Calend.bmp', wxBITMAP_TYPE_BMP) self.but = wxBitmapButton(self, 60, bmp, wxPoint(380, 80))#, wxSize(30, 30)) @@ -106,12 +105,18 @@ class TestPanel(wxPanel): # button for calendar window test - wxStaticText(self, -1, "Test Calendar Window", wxPoint(350, 150)).SetBackgroundColour(wxNamedColour('Blue')) + wxStaticText(self, -1, "Test Calendar Window", wxPoint(350, 150), wxSize(150, -1)) bmp = wxBitmap('bitmaps/Calend.bmp', wxBITMAP_TYPE_BMP) self.but = wxBitmapButton(self, 160, bmp, wxPoint(380, 180))#, wxSize(30, 30)) EVT_BUTTON(self, 160, self.TestFrame) + wxStaticText(self, -1, "Test Calendar Print", wxPoint(350, 250), wxSize(150, -1)) + + bmp = wxBitmap('bitmaps/Calend.bmp', wxBITMAP_TYPE_BMP) + self.but = wxBitmapButton(self, 170, bmp, wxPoint(380, 280))#, wxSize(30, 30)) + EVT_BUTTON(self, 170, self.OnPreview) + # calendar dialog def TestDlg(self, event): @@ -127,6 +132,15 @@ class TestPanel(wxPanel): frame.Show(true) return true +# calendar print preview + + def OnPreview(self, event): + month = self.calend.GetMonth() + year = self.calend.GetYear() + + prt = PrintCalend(self.frame, month, year) + prt.Preview() + # month and year control events def OnSpin(self, event): @@ -219,7 +233,7 @@ class CalenDlg(wxDialog): # alternate spin button to control the month h = self.date.GetSize().height - self.m_spin = wxSpinButton(self, 120, wxPoint(130, 20), wxSize(h*2, h), wxSP_VERTICAL) + self.m_spin = wxSpinButton(self, 120, wxPoint(120, 20), wxSize(h*2, h), wxSP_VERTICAL) self.m_spin.SetRange(1, 12) self.m_spin.SetValue(start_month) @@ -260,9 +274,10 @@ class CalenDlg(wxDialog): def OnMonthSpin(self, event): month = event.GetPosition() - self.date.SetValue(Month[month]) - self.calend.SetMonth(month) - self.calend.Refresh() + if month >= 0 and month <= 12: + self.date.SetValue(Month[month]) + self.calend.SetMonth(month) + self.calend.Refresh() def OnYrSpin(self, event): year = event.GetPosition() @@ -392,11 +407,257 @@ class CalendFrame(wxFrame): tb.Realize() +#--------------------------------------------------------------------------- + +# example class for printing/previewing calendars + +class PrintCalend: + def __init__(self, parent, month, year): + self.frame = parent + self.month = month + self.year = year + + self.SetParms() + self.SetCal() + self.printData = wxPrintData() + + def SetCal(self): + self.grid_color = 'BLUE' + self.back_color = 'WHITE' + self.sel_color = 'RED' + self.high_color = 'LIGHT BLUE' + self.font = wxSWISS + self.bold = wxNORMAL + + self.sel_key = None # last used by + self.sel_lst = [] # highlighted selected days + + self.size = None + self.hide_title = FALSE + self.hide_grid = FALSE + self.set_day = None + + def SetParms(self): + self.ymax = 1 + self.xmax = 1 + self.page = 1 + self.total_pg = 1 + + self.preview = None + self.scale = 1.0 + + self.pagew = 8.5 + self.pageh = 11.0 + + self.txt_marg = 0.1 + self.lf_marg = 0 + self.top_marg = 0 + + self.page = 0 + + def SetDates(self, month, year): + self.month = month + self.year = year + + def SetStyleDef(self, desc): + self.style = desc + + def SetCopies(self, copies): # number of copies of label + self.copies = copies + + def SetStart(self, start): # start position of label + self.start = start + + def Preview(self): + printout = SetPrintout(self) + printout2 = SetPrintout(self) + self.preview = wxPrintPreview(printout, printout2, self.printData) + if not self.preview.Ok(): + wxMessageBox("There was a problem printing!", "Printing", wxOK) + return + + self.preview.SetZoom(60) # initial zoom value + + frame = wxPreviewFrame(self.preview, self.frame, "Print preview") + + frame.Initialize() + frame.SetPosition(self.frame.GetPosition()) + frame.SetSize(self.frame.GetSize()) + frame.Show(true) + + def Print(self): + pdd = wxPrintDialogData() + pdd.SetPrintData(self.printData) + printer = wxPrinter(pdd) + printout = SetPrintout(self) + frame = wxFrame(NULL, -1, "Test") + if not printer.Print(frame, printout): + wxMessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wxOK) + else: + self.printData = printer.GetPrintDialogData().GetPrintData() + printout.Destroy() + + def DoDrawing(self, DC): + size = DC.GetSizeTuple() + DC.BeginDrawing() + + cal = PrtCalDraw(self) + + if self.preview is None: + cal.SetPSize(size[0]/self.pagew, size[1]/self.pageh) + cal.SetPreview(FALSE) + + else: + if self.preview == 1: + cal.SetPSize(size[0]/self.pagew, size[1]/self.pageh) + else: + cal.SetPSize(self.pwidth, self.pheight) + + cal.SetPreview(self.preview) + + cal.hide_title = self.hide_title # set the calendar parameters + cal.hide_grid = self.hide_grid + + cal.grid_color = self.grid_color + cal.high_color = self.high_color + cal.back_color = self.back_color + cal.outer_border = FALSE + cal.font = self.font + cal.bold = self.bold + + cal_size = wxSize(3.0, 2.0) + cal.SetSize(cal_size) + + year, month = self.year, self.month + x = 1.0 + for i in range(2): + y = 0.5 + for j in range(3): + cal.SetCal(year, month) # current month + cal.SetPos(x, y) + cal.DrawCal(DC, self.sel_lst) + + year, month = self.IncMonth(year, month) + y = y + 2.5 + x = x + 4.0 # next colum + + DC.EndDrawing() + + self.ymax = DC.MaxY() + self.xmax = DC.MaxX() + + def IncMonth(self, year, month): # next month + month = month + 1 + if month > 12: + month = 1 + year = year + 1 + + return year, month + + def OnCloseWindow(self, event): + self.Destroy() + + def GetTotalPages(self): + self.pg_cnt = 1 + return self.pg_cnt + + def SetPage(self, page): + self.page = page + + def SetPageSize(self, width, height): + self.pwidth, self.pheight = width, height + + def SetTotalSize(self, width, height): + self.ptwidth, self.ptheight = width, height + + def SetPreview(self, preview, scale): + self.preview = preview + self.scale = scale + + def SetTotalSize(self, width, height): + self.ptwidth = width + self.ptheight = height + def SetToolPath(self, tb, id, bmp, title): global dir_path tb.AddSimpleTool(id, wxBitmap(os.path.join(dir_path, bmp), wxBITMAP_TYPE_BMP), title, title) +class SetPrintout(wxPrintout): + def __init__(self, canvas): + wxPrintout.__init__(self) + self.canvas = canvas + self.end_pg = 1 + + def OnBeginDocument(self, start, end): + return self.base_OnBeginDocument(start, end) + + def OnEndDocument(self): + self.base_OnEndDocument() + + def HasPage(self, page): + if page <= self.end_pg: + return true + else: + return false + + def GetPageInfo(self): + self.end_pg = self.canvas.GetTotalPages() + str_pg = 1 + try: + end_pg = self.end_pg + except: + end_pg = 1 + return (str_pg, end_pg, str_pg, end_pg) + + def OnPreparePrinting(self): + self.base_OnPreparePrinting() + + def OnBeginPrinting(self): + dc = self.GetDC() + + self.preview = self.IsPreview() + if (self.preview): + self.pixelsPerInch = self.GetPPIScreen() + else: + self.pixelsPerInch = self.GetPPIPrinter() + + (w, h) = dc.GetSizeTuple() + scaleX = float(w) / 1000 + scaleY = float(h) / 1000 + self.printUserScale = min(scaleX, scaleY) + + self.base_OnBeginPrinting() + + def GetSize(self): + self.psizew, self.psizeh = self.GetPPIPrinter() + return self.psizew, self.psizeh + + def GetTotalSize(self): + self.ptsizew, self.ptsizeh = self.GetPageSizePixels() + return self.ptsizew, self.ptsizeh + + def OnPrintPage(self, page): + dc = self.GetDC() + (w, h) = dc.GetSizeTuple() + scaleX = float(w) / 1000 + scaleY = float(h) / 1000 + self.printUserScale = min(scaleX, scaleY) + dc.SetUserScale(self.printUserScale, self.printUserScale) + + self.preview = self.IsPreview() + + self.canvas.SetPreview(self.preview, self.printUserScale) + self.canvas.SetPage(page) + + self.ptsizew, self.ptsizeh = self.GetPageSizePixels() + self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh) + + self.psizew, self.psizeh = self.GetPPIPrinter() + self.canvas.SetPageSize(self.psizew, self.psizeh) + + self.canvas.DoDrawing(dc) + return true class MyApp(wxApp): def OnInit(self): @@ -426,14 +687,14 @@ if __name__ == '__main__': #--------------------------------------------------------------------------- def runTest(frame, nb, log): - win = TestPanel(nb, log) + win = TestPanel(nb, log, frame) return win #--------------------------------------------------------------------------- overview = """\ -This control provides a calendar control class for displaying and selecting dates. +This control provides a calendar control class for displaying and selecting dates. In addition, the class is extended and can now be used for printing/previewing. See example for various methods used to set display month, year, and highlighted dates (different colour).