From 6157b2bc35d45de38b90b0e47b7cebb11913e435 Mon Sep 17 00:00:00 2001 From: Andrea Gavana Date: Tue, 4 Dec 2012 20:58:27 +0000 Subject: [PATCH] Phoenix: `sizers_overview.rst` expanded; added a bunch of "contributed" snippets on various classes/methods; many fixes on strange doxygen layouts and XML hierarchies; fixed many cross-references between classes/methods/functions in the `etg` files. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@73128 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- .../_downloads/ArtProvider.GetBitmap.1.py | 43 ++ docs/sphinx/_downloads/CloseEvent.Veto.1.py | 34 ++ docs/sphinx/_downloads/Colour.1.py | 32 ++ docs/sphinx/_downloads/EvtHandler.Bind.1.py | 36 ++ docs/sphinx/_downloads/Font.1.py | 63 +++ .../_downloads/Frame.SetStatusWidths.1.py | 35 ++ docs/sphinx/_downloads/MenuBar.1.py | 40 ++ docs/sphinx/_downloads/MoveEvent.1.py | 36 ++ docs/sphinx/_downloads/Notebook.1.py | 75 +++ docs/sphinx/_downloads/PaintDC.1.py | 44 ++ docs/sphinx/_downloads/Process.1.py | 73 +++ docs/sphinx/_downloads/SplitterWindow.1.py | 43 ++ .../_downloads/StatusBar.SetStatusWidths.1.py | 35 ++ docs/sphinx/_downloads/TreeCtrl.1.py | 51 +++ .../_downloads/functions.CallAfter.1.py | 57 +++ docs/sphinx/_downloads/functions.Execute.1.py | 73 +++ docs/sphinx/_static/css/tables.css | 28 ++ .../_static/images/overviews/boxsizer1.png | Bin 0 -> 7910 bytes .../_static/images/overviews/boxsizer2.png | Bin 0 -> 6880 bytes .../_static/images/overviews/boxsizer3.png | Bin 0 -> 7195 bytes .../_static/images/overviews/boxsizer31.png | Bin 0 -> 7603 bytes .../_static/images/overviews/boxsizer32.png | Bin 0 -> 7293 bytes .../_static/images/overviews/boxsizer33.png | Bin 0 -> 7474 bytes .../_static/images/overviews/boxsizer34.png | Bin 0 -> 7966 bytes .../_static/images/overviews/boxsizer4.png | Bin 0 -> 10727 bytes .../_static/images/overviews/boxsizer41.png | Bin 0 -> 8419 bytes .../_static/images/overviews/boxsizer5.png | Bin 0 -> 8920 bytes .../_static/images/overviews/boxsizer51.png | Bin 0 -> 8215 bytes .../_static/images/overviews/boxsizer52.png | Bin 0 -> 8713 bytes .../_static/images/overviews/boxsizer53.png | Bin 0 -> 8844 bytes .../_static/images/overviews/boxsizer54.png | Bin 0 -> 9062 bytes .../_static/images/overviews/boxsizer55.png | Bin 0 -> 8822 bytes .../_static/images/overviews/boxsizer56.png | Bin 0 -> 9284 bytes .../overviews/sizers_overview.rst | 428 +++++++++++++++++- .../python/contrib/ArtProvider.GetBitmap.1.py | 43 ++ .../python/contrib/CloseEvent.Veto.1.py | 34 ++ .../snippets/python/contrib/Colour.1.py | 32 ++ .../python/contrib/EvtHandler.Bind.1.py | 36 ++ .../snippets/python/contrib/Font.1.py | 63 +++ .../python/contrib/Frame.SetStatusWidths.1.py | 35 ++ .../snippets/python/contrib/MenuBar.1.py | 40 ++ .../snippets/python/contrib/MoveEvent.1.py | 36 ++ .../snippets/python/contrib/Notebook.1.py | 75 +++ .../snippets/python/contrib/PaintDC.1.py | 44 ++ .../snippets/python/contrib/Process.1.py | 73 +++ .../python/contrib/SplitterWindow.1.py | 43 ++ .../contrib/StatusBar.SetStatusWidths.1.py | 35 ++ .../snippets/python/contrib/TreeCtrl.1.py | 51 +++ .../python/contrib/functions.CallAfter.1.py | 57 +++ .../python/contrib/functions.Execute.1.py | 73 +++ .../python/converted/ArtProvider.1.py | 2 +- .../python/converted/ArtProvider.2.py | 2 + .../snippets/python/converted/LogNull.2.py | 3 +- etg/_xrc.py | 2 +- etg/app.py | 4 +- etg/bitmap.py | 16 +- etg/event.py | 4 +- etg/icon.py | 4 +- etg/image.py | 38 +- etg/pyevent.py | 16 +- etg/rawbmp.py | 4 +- etg/toolbar.py | 8 +- etg/wxdatetime.py | 16 +- etgtools/sphinx_generator.py | 25 +- sphinxtools/postprocess.py | 4 +- sphinxtools/utilities.py | 16 +- 66 files changed, 2085 insertions(+), 75 deletions(-) create mode 100644 docs/sphinx/_downloads/ArtProvider.GetBitmap.1.py create mode 100644 docs/sphinx/_downloads/CloseEvent.Veto.1.py create mode 100644 docs/sphinx/_downloads/Colour.1.py create mode 100644 docs/sphinx/_downloads/EvtHandler.Bind.1.py create mode 100644 docs/sphinx/_downloads/Font.1.py create mode 100644 docs/sphinx/_downloads/Frame.SetStatusWidths.1.py create mode 100644 docs/sphinx/_downloads/MenuBar.1.py create mode 100644 docs/sphinx/_downloads/MoveEvent.1.py create mode 100644 docs/sphinx/_downloads/Notebook.1.py create mode 100644 docs/sphinx/_downloads/PaintDC.1.py create mode 100644 docs/sphinx/_downloads/Process.1.py create mode 100644 docs/sphinx/_downloads/SplitterWindow.1.py create mode 100644 docs/sphinx/_downloads/StatusBar.SetStatusWidths.1.py create mode 100644 docs/sphinx/_downloads/TreeCtrl.1.py create mode 100644 docs/sphinx/_downloads/functions.CallAfter.1.py create mode 100644 docs/sphinx/_downloads/functions.Execute.1.py create mode 100644 docs/sphinx/_static/images/overviews/boxsizer1.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer2.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer3.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer31.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer32.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer33.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer34.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer4.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer41.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer5.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer51.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer52.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer53.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer54.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer55.png create mode 100644 docs/sphinx/_static/images/overviews/boxsizer56.png create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/ArtProvider.GetBitmap.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/CloseEvent.Veto.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/Colour.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/EvtHandler.Bind.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/Font.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/Frame.SetStatusWidths.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/MenuBar.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/MoveEvent.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/Notebook.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/PaintDC.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/Process.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/SplitterWindow.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/StatusBar.SetStatusWidths.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/TreeCtrl.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/functions.CallAfter.1.py create mode 100644 docs/sphinx/rest_substitutions/snippets/python/contrib/functions.Execute.1.py diff --git a/docs/sphinx/_downloads/ArtProvider.GetBitmap.1.py b/docs/sphinx/_downloads/ArtProvider.GetBitmap.1.py new file mode 100644 index 00000000..1b7aea11 --- /dev/null +++ b/docs/sphinx/_downloads/ArtProvider.GetBitmap.1.py @@ -0,0 +1,43 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to retrieve default platform's +# bitmaps using wx.ArtProvider + +import wx + +class BitmapFrame(wx.Frame): + + def __init__(self): + + wx.Frame.__init__(self, None, -1, title='ArtProvider example') + + panel = wx.Panel(self) + + main_sizer = wx.BoxSizer(wx.VERTICAL) + bitmap_sizer = wx.BoxSizer(wx.HORIZONTAL) + + bitmap_sizer.Add((0, 0), 1, wx.EXPAND) + + # Show a few bitmaps retrieved via wx.ArtProvider + for kind in [wx.ART_INFORMATION, wx.ART_WARNING, wx.ART_CDROM, wx.ART_CUT]: + bmp = wx.ArtProvider.GetBitmap(kind, wx.ART_OTHER, (32, 32)) + static_bitmap = wx.StaticBitmap(panel, -1, bmp) + bitmap_sizer.Add(static_bitmap, 0, wx.ALL, 5) + + # Layout everything in a nice sizer + bitmap_sizer.Add((0, 0), 1, wx.EXPAND) + main_sizer.Add((0, 0), 1, wx.EXPAND) + main_sizer.Add(bitmap_sizer, 0, wx.EXPAND) + main_sizer.Add((0, 0), 1, wx.EXPAND) + + panel.SetSizer(main_sizer) + main_sizer.SetSizeHints(panel) + main_sizer.Layout() + + +if __name__ == '__main__': + app = wx.App(0) + frame = BitmapFrame() + frame.Show() + app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/_downloads/CloseEvent.Veto.1.py b/docs/sphinx/_downloads/CloseEvent.Veto.1.py new file mode 100644 index 00000000..c7e8cb84 --- /dev/null +++ b/docs/sphinx/_downloads/CloseEvent.Veto.1.py @@ -0,0 +1,34 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample makes the main frame "immortal", i.e., non-closable +# by the user. The main window can not be close by pressing Alt+F4 +# or by clicking on the "X" button in the titlebar + +import wx + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Bind the "close window" event to the OnClose handler + self.Bind(wx.EVT_CLOSE, self.OnClose) + + self.Show() + self.close_attempts = 0 + + + def OnClose(self, event): + + # Veto the event the user can not close the main + # window in any way + self.close_attempts += 1 + print('I am immortal %d'%self.close_attempts) + event.Veto() + + +app = wx.App(False) +frame = MainWindow(None, 'Immortal Frame') +app.MainLoop() diff --git a/docs/sphinx/_downloads/Colour.1.py b/docs/sphinx/_downloads/Colour.1.py new file mode 100644 index 00000000..deb012df --- /dev/null +++ b/docs/sphinx/_downloads/Colour.1.py @@ -0,0 +1,32 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to assign different fonts to various +# wx.StaticTexts + +import wx + +app = wx.App(0) +frame = wx.Frame(None, -1, 'Colour settings') + +text_ctrl_1 = wx.TextCtrl(frame, -1, 'Some text') +text_ctrl_1.SetBackgroundColour(wx.Colour(0, 0, 255)) +# OR +text_ctrl_2 = wx.TextCtrl(frame, -1, 'Other text') +text_ctrl_2.SetBackgroundColour('BLUE') +# OR +text_ctrl_3 = wx.TextCtrl(frame, -1, 'Another text') +text_ctrl_3.SetBackgroundColour('#0000FF') + +# Size up everything in a nice vertical box sizer +sizer = wx.BoxSizer(wx.VERTICAL) +sizer.Add(text_ctrl_1, 0, wx.EXPAND|wx.ALL, 10) +sizer.Add(text_ctrl_2, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 10) +sizer.Add(text_ctrl_3, 0, wx.EXPAND|wx.ALL, 10) +frame.SetSizer(sizer) +sizer.SetSizeHints(frame) + +frame.Show() + +# Enter the application main loop +app.MainLoop() diff --git a/docs/sphinx/_downloads/EvtHandler.Bind.1.py b/docs/sphinx/_downloads/EvtHandler.Bind.1.py new file mode 100644 index 00000000..e9073b4f --- /dev/null +++ b/docs/sphinx/_downloads/EvtHandler.Bind.1.py @@ -0,0 +1,36 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows a simple example of how to use the +# "Bind" method to handle an event + +import wx + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Bind the "close window" event to the OnClose handler + self.Bind(wx.EVT_CLOSE, self.OnClose) + + self.Show() + + + def OnClose(self, event): + + # This displays a message box asking the user to confirm + # she wants to quit the application + dlg = wx.MessageDialog(self, 'Are you sure you want to quit?', 'Question', + wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) + + if dlg.ShowModal() == wx.ID_YES: + self.Destroy() + else: + event.Veto() + + +app = wx.App(False) +frame = MainWindow(None, 'Bind example') +app.MainLoop() diff --git a/docs/sphinx/_downloads/Font.1.py b/docs/sphinx/_downloads/Font.1.py new file mode 100644 index 00000000..fc01b220 --- /dev/null +++ b/docs/sphinx/_downloads/Font.1.py @@ -0,0 +1,63 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to assign different fonts to various +# wx.StaticTexts + +import wx + +class FontFrame(wx.Frame): + + def __init__(self, parent): + + wx.Frame.__init__(self, parent, title='Font sample') + + panel = wx.Panel(self, -1) + + text1 = '''Lasciatemi cantare +con la chitarra in mano +lasciatemi cantare +sono un italiano''' + + text2 = '''Buongiorno Italia gli spaghetti al dente +e un partigiano come Presidente +con l'autoradio sempre nella mano destra +e un canarino sopra la finestra''' + + text3 = '''Buongiorno Italia con i tuoi artisti +con troppa America sui manifesti +con le canzoni con amore con il cuore +con piu' donne sempre meno suore''' + + # Construct 2 font objects from the wx.Font constructor + font1 = wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_ITALIC, wx.FONTWEIGHT_NORMAL) + font2 = wx.Font(10, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) + + # A font can be retrieved from the OS default font + # and modified + font3 = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) + font3.SetStyle(wx.FONTSTYLE_ITALIC) + font3.SetPointSize(12) + + lyrics1 = wx.StaticText(panel, -1, text1, style=wx.ALIGN_CENTRE) + lyrics1.SetFont(font1) + lyrics2 = wx.TextCtrl(panel, -1, text2, style=wx.TE_CENTER|wx.TE_MULTILINE) + lyrics2.SetFont(font2) + lyrics3 = wx.StaticText(panel, -1, text3, style=wx.ALIGN_CENTRE) + lyrics3.SetFont(font3) + + # Size up everything in a nice vertical box sizer + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(lyrics1, 0, wx.EXPAND|wx.ALL, 10) + sizer.Add(lyrics2, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 10) + sizer.Add(lyrics3, 0, wx.EXPAND|wx.ALL, 10) + panel.SetSizer(sizer) + sizer.SetSizeHints(panel) + self.Center() + + +app = wx.App(0) +frame = FontFrame(None) +frame.Show() +# Enter the application main loop +app.MainLoop() diff --git a/docs/sphinx/_downloads/Frame.SetStatusWidths.1.py b/docs/sphinx/_downloads/Frame.SetStatusWidths.1.py new file mode 100644 index 00000000..fe3ac595 --- /dev/null +++ b/docs/sphinx/_downloads/Frame.SetStatusWidths.1.py @@ -0,0 +1,35 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a wx.StatusBar with 2 fields, +# set the second field to have double width with respect to the +# first and and display the date of today in the second field. + +import wx +import datetime + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # A Statusbar in the bottom of the window + # Set it up so it has two fields + self.CreateStatusBar(2) + + # Set the second field to be double in width wrt the first + self.SetStatusWidths([-1, -2]) + + # Get today date via datetime + today = datetime.datetime.today() + today = today.strftime('%d-%b-%Y') + + # Set today date in the second field + self.SetStatusText(today, 1) + + self.Show() + +app = wx.App(False) +frame = MainWindow(None, 'SetStatusWidths example') +app.MainLoop() diff --git a/docs/sphinx/_downloads/MenuBar.1.py b/docs/sphinx/_downloads/MenuBar.1.py new file mode 100644 index 00000000..1a84b406 --- /dev/null +++ b/docs/sphinx/_downloads/MenuBar.1.py @@ -0,0 +1,40 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a simple wx.MenuBar +# and a simple wx.StatusBar + +import wx + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # A Statusbar in the bottom of the window + self.CreateStatusBar() + + # Setting up the menu + file_menu = wx.Menu() + + # wx.ID_ABOUT and wx.ID_EXIT are standard IDs provided + # by wxWidgets. + file_menu.Append(wx.ID_ABOUT, '&About', + 'Information about this application') + file_menu.AppendSeparator() + file_menu.Append(wx.ID_EXIT, 'E&xit', 'Exit the application') + + # Creating the menubar + menu_bar = wx.MenuBar() + + # Adding the 'file_menu' to the menu bar + menu_bar.Append(file_menu, '&File') + + # Adding the menu bar to the frame content + self.SetMenuBar(menu_bar) + self.Show() + +app = wx.App(False) +frame = MainWindow(None, 'MenuBar and StatusBar') +app.MainLoop() diff --git a/docs/sphinx/_downloads/MoveEvent.1.py b/docs/sphinx/_downloads/MoveEvent.1.py new file mode 100644 index 00000000..3251ae86 --- /dev/null +++ b/docs/sphinx/_downloads/MoveEvent.1.py @@ -0,0 +1,36 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to listen to a move change event for a +# top-level window (wx.Frame, wx.Dialog). This is MSW-specific + +import wx + +class MovingFrame(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + wx.StaticText(self, label='x:', pos=(10, 10)) + wx.StaticText(self, label='y:', pos=(10, 30)) + + self.st1 = wx.StaticText(self, label='', pos=(30, 10)) + self.st2 = wx.StaticText(self, label='', pos=(30, 30)) + + self.Bind(wx.EVT_MOVE, self.OnMove) + + self.Show() + + def OnMove(self, event): + + # Capture the mouse position (in screen coordinates) and + # assign its x, y values to the statictexts + x, y = event.GetPosition() + self.st1.SetLabel('%d'%x) + self.st2.SetLabel('%d'%y) + + +app = wx.App(False) +frame = MovingFrame(None, 'MoveEvent example') +app.MainLoop() diff --git a/docs/sphinx/_downloads/Notebook.1.py b/docs/sphinx/_downloads/Notebook.1.py new file mode 100644 index 00000000..e8e37507 --- /dev/null +++ b/docs/sphinx/_downloads/Notebook.1.py @@ -0,0 +1,75 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample creates a "File->Open" menu, and lets the user select +# a Python file. Upon selection, the file is read in memory and a new +# wx.TextCtrl showing the file content is added as a page of a wx.Notebook + +import wx +import os + +class NotebookFrame(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Create the notebook + self.notebook = wx.Notebook(self, style=wx.NB_BOTTOM) + + # Setting up the menu + file_menu = wx.Menu() + + # wx.ID_OPEN + menu_item = file_menu.Append(wx.ID_OPEN, '&Open...', 'Open and read a new Python file') + # Bind the "select menu item" event to the OnOpen event handler + self.Bind(wx.EVT_MENU, self.OnOpen, menu_item) + + # Creating the menubar + menu_bar = wx.MenuBar() + + # Adding the 'file_menu' to the menu bar + menu_bar.Append(file_menu, '&File') + + # Adding the menu bar to the frame content + self.SetMenuBar(menu_bar) + + self.Show() + + + def OnOpen(self, event): + + # This is how you pre-establish a file filter so that the dialog + # only shows the extension(s) you want it to. + wildcard = 'Python source (*.py)|*.py' + + dlg = wx.FileDialog(None, message="Choose a Python file", defaultDir=os.getcwd(), + defaultFile="", wildcard=wildcard, style=wx.FD_OPEN) + + # Show the dialog and retrieve the user response. If it is the OK response, + # process the data. + if dlg.ShowModal() == wx.ID_OK: + # This returns the file that was selected + path = dlg.GetPath() + + # Open the file as read-only and slurp its content + fid = open(path, 'rt') + text = fid.read() + fid.close() + + # Create the notebook page as a wx.TextCtrl and + # add it as a page of the wx.Notebook + text_ctrl = wx.TextCtrl(self.notebook, style=wx.TE_MULTILINE) + text_ctrl.SetValue(text) + + filename = os.path.split(os.path.splitext(path)[0])[1] + self.notebook.AddPage(text_ctrl, filename, select=True) + + # Destroy the dialog. Don't do this until you are done with it! + # BAD things can happen otherwise! + dlg.Destroy() + + +app = wx.App(False) +frame = NotebookFrame(None, 'Notebook example') +app.MainLoop() diff --git a/docs/sphinx/_downloads/PaintDC.1.py b/docs/sphinx/_downloads/PaintDC.1.py new file mode 100644 index 00000000..2833c4d5 --- /dev/null +++ b/docs/sphinx/_downloads/PaintDC.1.py @@ -0,0 +1,44 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample uses the random module to draw 100 random lines iinside +# a wx.Frame client area, as a demonstration of how to handle a wx.PaintDC + +import wx +import random + +class PaintFrame(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Bind a "paint" event for the frame to the + # "OnPaint" method + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Show() + + + def OnPaint(self, event): + + dc = wx.PaintDC(self) + w, h = self.GetClientSize() + + # Use a blue pen, for example... + + dc.SetPen(wx.Pen('BLUE')) + + # Remember the signature of wx.DC.DrawLine: + # DrawLine(x1, y1, x2, y2) + + for i in range(100): + x1 = random.randint(1, w-1) + y1 = random.randint(1, h-1) + x2 = random.randint(1, w-1) + y2 = random.randint(1, h-1) + dc.DrawLine(x1, y1, x2, y2) + + +app = wx.App(False) +frame = PaintFrame(None, 'PaintDC example') +app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/_downloads/Process.1.py b/docs/sphinx/_downloads/Process.1.py new file mode 100644 index 00000000..bc24996a --- /dev/null +++ b/docs/sphinx/_downloads/Process.1.py @@ -0,0 +1,73 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample demonstrates a simple use of wx.Process/wx.Execute to +# monitor an external program stdout + +import wx + +class ProcessFrame(wx.Frame): + + def __init__(self, parent): + wx.Frame.__init__(self, parent, title='Process/Execute example') + + panel = wx.Panel(self) + self.label = wx.TextCtrl(panel, style=wx.TE_MULTILINE) + self.btn = wx.Button(panel, label="Start") + + self.process = None + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.label, proportion=1, flag=wx.EXPAND) + sizer.Add(self.btn, proportion=0, flag=wx.EXPAND) + + panel.SetSizerAndFit(sizer) + self.Bind(wx.EVT_BUTTON, self.OnButton) + + self.Bind(wx.EVT_IDLE, self.OnIdle) + self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded) + + def OnButton(self, event): + self.btn.Enable(False) + self.label.SetValue('') + self.LongRunning() + + def LongRunning(self): + """ + This runs in the GUI thread but uses wx.Process and + wx.Execute to start and monitor a separate process. + """ + + cmd = 'python -u external_program.py' + + self.process = wx.Process(self) + self.process.Redirect() + + wx.Execute(cmd, wx.EXEC_ASYNC, self.process) + + def OnIdle(self, event): + """ This event handler catches the process stdout. """ + + if self.process is not None: + stream = self.process.GetInputStream() + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + def OnProcessEnded(self, event): + + stream = self.process.GetInputStream() + + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + self.btn.Enable(True) + self.label.AppendText('Finished') + + +if __name__ == "__main__": + app = wx.App(0) + frame = ProcessFrame(None) + frame.Show() + app.MainLoop() diff --git a/docs/sphinx/_downloads/SplitterWindow.1.py b/docs/sphinx/_downloads/SplitterWindow.1.py new file mode 100644 index 00000000..b24dc057 --- /dev/null +++ b/docs/sphinx/_downloads/SplitterWindow.1.py @@ -0,0 +1,43 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a "spli-split" window, i.e. a +# window split verticall which contains two windows split horizontally + +import wx + +class SplitterFrame(wx.Frame): + + def __init__(self): + + wx.Frame.__init__(self, None, title='SplitterWindow example') + + # Create the main splitter window (to be split vertically) + splitter = wx.SplitterWindow(self, -1, style=wx.SP_LIVE_UPDATE) + splitter.SetMinimumPaneSize(100) + + panel1 = wx.Panel(splitter, -1) + + static = wx.StaticText(panel1, -1, 'Hello World', pos=(10, 100)) + panel1.SetBackgroundColour(wx.WHITE) + + # Create the second splitter window (to be split horizontally) + splitter2 = wx.SplitterWindow(splitter, -1, style=wx.SP_LIVE_UPDATE) + splitter2.SetMinimumPaneSize(100) + + panel2 = wx.Panel(splitter2, -1) + panel2.SetBackgroundColour(wx.BLUE) + + panel3 = wx.Panel(splitter2, -1) + panel3.SetBackgroundColour(wx.RED) + + splitter2.SplitHorizontally(panel2, panel3) + splitter.SplitVertically(panel1, splitter2) + self.Centre() + + +if __name__ == '__main__': + app = wx.App(0) + frame = SplitterFrame() + frame.Show() + app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/_downloads/StatusBar.SetStatusWidths.1.py b/docs/sphinx/_downloads/StatusBar.SetStatusWidths.1.py new file mode 100644 index 00000000..fe3ac595 --- /dev/null +++ b/docs/sphinx/_downloads/StatusBar.SetStatusWidths.1.py @@ -0,0 +1,35 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a wx.StatusBar with 2 fields, +# set the second field to have double width with respect to the +# first and and display the date of today in the second field. + +import wx +import datetime + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # A Statusbar in the bottom of the window + # Set it up so it has two fields + self.CreateStatusBar(2) + + # Set the second field to be double in width wrt the first + self.SetStatusWidths([-1, -2]) + + # Get today date via datetime + today = datetime.datetime.today() + today = today.strftime('%d-%b-%Y') + + # Set today date in the second field + self.SetStatusText(today, 1) + + self.Show() + +app = wx.App(False) +frame = MainWindow(None, 'SetStatusWidths example') +app.MainLoop() diff --git a/docs/sphinx/_downloads/TreeCtrl.1.py b/docs/sphinx/_downloads/TreeCtrl.1.py new file mode 100644 index 00000000..a5dc6658 --- /dev/null +++ b/docs/sphinx/_downloads/TreeCtrl.1.py @@ -0,0 +1,51 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample classifies the Python keywords alphabetically, using the +# first letter of the keyword (i.e., ``and`` goes into ``a``, ``for`` +# goes into ``f`` and so on): +# +# * For each letter, adds a child to the treectrl root +# * In each child of the root item, adds its corresponding keyword(s) +# + +import wx +import keyword +import string + +class TreeFrame(wx.Frame): + + def __init__(self): + + wx.Frame.__init__(self, None, title='TreeCtrl example') + + tree_ctrl = wx.TreeCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | \ + wx.TR_FULL_ROW_HIGHLIGHT | \ + wx.TR_EDIT_LABELS) + + # Add the tree root + root = tree_ctrl.AddRoot('Python keywords') + + letters = [] + + for kwd in keyword.kwlist: + first = kwd[0] + if first not in letters: + letters.append(first) + + for letter in letters: + item = tree_ctrl.AppendItem(root, letter) + for kwd in keyword.kwlist: + first = kwd[0] + if first == letter: + sub_item = tree_ctrl.AppendItem(item, kwd) + + tree_ctrl.ExpandAll() + self.Centre() + + +if __name__ == '__main__': + app = wx.App(0) + frame = TreeFrame() + frame.Show() + app.MainLoop() diff --git a/docs/sphinx/_downloads/functions.CallAfter.1.py b/docs/sphinx/_downloads/functions.CallAfter.1.py new file mode 100644 index 00000000..01e4a684 --- /dev/null +++ b/docs/sphinx/_downloads/functions.CallAfter.1.py @@ -0,0 +1,57 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows hot to take advantage of wx.CallAfter when running a +# separate thread and updating the GUI in the main thread + +import wx +import threading +import time + +class MainFrame(wx.Frame): + + def __init__(self, parent): + wx.Frame.__init__(self, parent, title='CallAfter example') + + panel = wx.Panel(self) + self.label = wx.StaticText(panel, label="Ready") + self.btn = wx.Button(panel, label="Start") + self.gauge = wx.Gauge(panel) + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.label, proportion=1, flag=wx.EXPAND) + sizer.Add(self.btn, proportion=0, flag=wx.EXPAND) + sizer.Add(self.gauge, proportion=0, flag=wx.EXPAND) + + panel.SetSizerAndFit(sizer) + self.Bind(wx.EVT_BUTTON, self.OnButton) + + def OnButton(self, event): + """ This event handler starts the separate thread. """ + self.btn.Enable(False) + self.gauge.SetValue(0) + self.label.SetLabel("Running") + + thread = threading.Thread(target=self.LongRunning) + thread.start() + + def OnLongRunDone(self): + self.gauge.SetValue(100) + self.label.SetLabel("Done") + self.btn.Enable(True) + + def LongRunning(self): + """This runs in a different thread. Sleep is used to + simulate a long running task.""" + time.sleep(3) + wx.CallAfter(self.gauge.SetValue, 20) + time.sleep(5) + wx.CallAfter(self.gauge.SetValue, 70) + time.sleep(4) + wx.CallAfter(self.OnLongRunDone) + +if __name__ == "__main__": + app = wx.App(0) + frame = MainFrame(None) + frame.Show() + app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/_downloads/functions.Execute.1.py b/docs/sphinx/_downloads/functions.Execute.1.py new file mode 100644 index 00000000..bc24996a --- /dev/null +++ b/docs/sphinx/_downloads/functions.Execute.1.py @@ -0,0 +1,73 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample demonstrates a simple use of wx.Process/wx.Execute to +# monitor an external program stdout + +import wx + +class ProcessFrame(wx.Frame): + + def __init__(self, parent): + wx.Frame.__init__(self, parent, title='Process/Execute example') + + panel = wx.Panel(self) + self.label = wx.TextCtrl(panel, style=wx.TE_MULTILINE) + self.btn = wx.Button(panel, label="Start") + + self.process = None + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.label, proportion=1, flag=wx.EXPAND) + sizer.Add(self.btn, proportion=0, flag=wx.EXPAND) + + panel.SetSizerAndFit(sizer) + self.Bind(wx.EVT_BUTTON, self.OnButton) + + self.Bind(wx.EVT_IDLE, self.OnIdle) + self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded) + + def OnButton(self, event): + self.btn.Enable(False) + self.label.SetValue('') + self.LongRunning() + + def LongRunning(self): + """ + This runs in the GUI thread but uses wx.Process and + wx.Execute to start and monitor a separate process. + """ + + cmd = 'python -u external_program.py' + + self.process = wx.Process(self) + self.process.Redirect() + + wx.Execute(cmd, wx.EXEC_ASYNC, self.process) + + def OnIdle(self, event): + """ This event handler catches the process stdout. """ + + if self.process is not None: + stream = self.process.GetInputStream() + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + def OnProcessEnded(self, event): + + stream = self.process.GetInputStream() + + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + self.btn.Enable(True) + self.label.AppendText('Finished') + + +if __name__ == "__main__": + app = wx.App(0) + frame = ProcessFrame(None) + frame.Show() + app.MainLoop() diff --git a/docs/sphinx/_static/css/tables.css b/docs/sphinx/_static/css/tables.css index 38ebf751..ecacc3d7 100644 --- a/docs/sphinx/_static/css/tables.css +++ b/docs/sphinx/_static/css/tables.css @@ -55,3 +55,31 @@ { background: #E0E0E0 url('../images/sphinxdocs/cell-grey.jpg'); } + +.centertable +{ + margin-bottom: 2em; +} + +.centertable th.head +{ + font-weight: bold; + text-align: left; + border-bottom: 1px solid black; + padding-right: .5em; +} + +.centertable th.field-name +{ + font-weight: bold; + text-align: left; + padding-right: 1em; +} + +.centertable th { + background-color: #ede; +} + +.centertable td { + vertical-align: middle; +} diff --git a/docs/sphinx/_static/images/overviews/boxsizer1.png b/docs/sphinx/_static/images/overviews/boxsizer1.png new file mode 100644 index 0000000000000000000000000000000000000000..6597887634adde2e95667d0c2b5727f3e815466f GIT binary patch literal 7910 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 literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer2.png b/docs/sphinx/_static/images/overviews/boxsizer2.png new file mode 100644 index 0000000000000000000000000000000000000000..ed838551d3149b4a5c600c92c4b694f628f36b17 GIT binary patch literal 6880 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 IS`HfVf5BrDP5=M^ literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer3.png b/docs/sphinx/_static/images/overviews/boxsizer3.png new file mode 100644 index 0000000000000000000000000000000000000000..428b9d6ed311b15b45e064cd4a8ba28f3508b81b GIT binary patch literal 7195 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 W>U8*J6Q%z9$0sihld6<33j80XcHOH0 literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer31.png b/docs/sphinx/_static/images/overviews/boxsizer31.png new file mode 100644 index 0000000000000000000000000000000000000000..fd2050d1ed0a1897648737e8ce6d3ca0eb7a656c GIT binary patch literal 7603 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 literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer32.png b/docs/sphinx/_static/images/overviews/boxsizer32.png new file mode 100644 index 0000000000000000000000000000000000000000..cdb14b2c08cc7eb947a3f70710c1d8a494dbebbb GIT binary patch literal 7293 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 TdPeVm{vxU>f)#4y%)|a4OJHeY literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer33.png b/docs/sphinx/_static/images/overviews/boxsizer33.png new file mode 100644 index 0000000000000000000000000000000000000000..003ef776ad1ef945ecafe715e1e73c3fc33f09de GIT binary patch literal 7474 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 Q=Qp>aoSJO8v}w?P0JM}$4gdfE literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer4.png b/docs/sphinx/_static/images/overviews/boxsizer4.png new file mode 100644 index 0000000000000000000000000000000000000000..e5e8edb0a30f87e9280d289f647aff2cabba74fc GIT binary patch literal 10727 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 Qn!o{2lvM>nq)kKr5AR%3Jpcdz literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer51.png b/docs/sphinx/_static/images/overviews/boxsizer51.png new file mode 100644 index 0000000000000000000000000000000000000000..7ad41822b6ab3d6c7f1c5ca03a0407f5891e9f77 GIT binary patch literal 8215 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 nNHpZmu3wBX4Yd&nxN`879sx!Qf&Z% literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer52.png b/docs/sphinx/_static/images/overviews/boxsizer52.png new file mode 100644 index 0000000000000000000000000000000000000000..8a8fd630677fd1628a046d32976ad6df5fa9e9a4 GIT binary patch literal 8713 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%0A{Cf3OY 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 XOyyK?U%lS8R{+4$%2E{)CPDuPyO-zW literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/images/overviews/boxsizer56.png b/docs/sphinx/_static/images/overviews/boxsizer56.png new file mode 100644 index 0000000000000000000000000000000000000000..74d1eacca4d29d71b3d25107bb8cb674a42f6d3b GIT binary patch literal 9284 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 + +.. method:: Add(window, proportion=0, flag=0, border=0, userData=None) + + Appends a child to the sizer. + + :param `window`: a window, a spacer or another sizer to be added to the sizer. Its initial size + (either set explicitly by the user or calculated internally) is interpreted as the minimal and + in many cases also the initial size. + :param int proportion: this parameter is used in :class:`BoxSizer` to indicate if a child of a sizer + can change its size in the main orientation of the :class:`BoxSizer` - where 0 stands for not changeable + and a value of more than zero is interpreted relative to the value of other children of the same + :class:`BoxSizer`. For example, you might have a horizontal :class:`BoxSizer` with three children, two + of which are supposed to change their size with the sizer. Then the two stretchable windows would + get a value of 1 each to make them grow and shrink equally with the sizer's horizontal dimension. + :param int flag: OR-combination of flags affecting sizer's behaviour. + :param int border: determines the border width, if the flag parameter is set to include any border flag. + :param object userData: allows an extra object to be attached to the sizer item, for use in derived + classes when sizing information is more complex than the proportion and flag will allow for. + + :rtype: :class:`SizerItem` + +.. raw:: html + +
+ + +Let's create a vertical sizer (children will be placed on top of each other) and place two buttons in it. +All the "extra" parameters are set to 0; we'll worry about them later. + +.. figure:: _static/images/overviews/boxsizer1.png + :class: floatright + +:: + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 0, 0, 0) + sizer.Add(wx.Button(self, -1, 'Small button'), 0, 0, 0) + self.SetSizer(sizer) + + +You'll notice a couple of things about this: + +* The buttons are just big enough to accommodate the text in them. In fact, any control placed + into a sizer this way will appear at its minimum size unless we change the parameters. +* The window size is not changed to fit the sizer. This results in a lot of ugly empty space. + + +Let's worry about the second issue first. To make the window size more appropriate, we can set +the size hints to tell the enclosing window to adjust to the size of the sizer: + +.. figure:: _static/images/overviews/boxsizer2.png + :class: floatright + +.. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 0, 0, 0) + sizer.Add(wx.Button(self, -1, 'Small button'), 0, 0, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + +This is particularly useful in circumstances like this one, in which the :class:`Frame`'s default size +would otherwise be much too big or small to show most layouts in an aesthetically pleasing manner. + +-------------------------- +The `proportion` parameter +-------------------------- + +The first parameter to :meth:`BoxSizer.Add` +is obviously the :class:`Window` or :class:`Sizer` that you are adding. The second one (the `proportion`) +defines how large the sizer's children are in relation to each other. In a vertical sizer, this changes +the height; in a horizontal sizer, this changes the width. Here are some examples: + +.. list-table:: + :header-rows: 1 + :widths: 40 10 + :class: centertable + + * - Code + + - Resulting Image + + * - .. code-block:: python + :emphasize-lines: 3,4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Second button is three times as tall as first button + sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 1, 0, 0) + sizer.Add(wx.Button(self, -1, 'Small button'), 3, 0, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + - .. figure:: _static/images/overviews/boxsizer3.png + :align: left + + * - Same code as above, with window resized. Notice that the bottom button is still three times as tall as the top button. + + - .. figure:: _static/images/overviews/boxsizer31.png + :align: left + + * - .. code-block:: python + :emphasize-lines: 3,4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # First button is 3/2 the height of the second button + sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 3, 0, 0) + sizer.Add(wx.Button(self, -1, 'Small button'), 2, 0, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + - .. figure:: _static/images/overviews/boxsizer32.png + :align: left + + +| + +If one of the `proportion` parameters is 0, that :class:`Window` will be the minimum size, and the others +will resize proportionally: + +.. list-table:: + :header-rows: 1 + :widths: 40 10 + :class: centertable + + * - Code + + - Resulting Image + + * - .. code-block:: python + :emphasize-lines: 4,5 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Third button is twice the size of the second button + sizer.Add(wx.Button(self, -1, 'An extremely long button text'), 0, 0, 0) + sizer.Add(wx.Button(self, -1, 'Small button'), 1, 0, 0) + sizer.Add(wx.Button(self, -1, 'Another button'), 2, 0, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + - .. figure:: _static/images/overviews/boxsizer33.png + :align: left + + * - Same code as above, with window resized. The top button (proportion 0) is still the minimum height, + and the third button is still twice the height of the second. + + - .. figure:: _static/images/overviews/boxsizer34.png + :align: left + + +This is especially useful when you want, for example, a button at the bottom which is only +as big as necessary, and some other control that occupies the rest of the frame. To do so, +give the button proportion 0 and the other control a number greater than 0. Mac users in +particular will appreciate you for not creating huge aqua-styled buttons. + + +----------------------------------- +The `flags` and `border` parameters +----------------------------------- + +The `flag` argument accepted by :meth:`Sizer.Add` +is a ``OR``-combination of the following flags. Two main behaviours are defined using these flags. One is +the border around a window: the `border` parameter determines the border width whereas the flags given here +determine which side(s) of the item that the border will be added. The other flags determine how the sizer +item behaves when the space allotted to the sizer changes, and is somewhat dependent on the specific kind +of sizer used. + ++---------------------------------------------------------------------+-----------------------------------------------------------------------------+ +| Sizer Flag | Description | ++=====================================================================+=============================================================================+ +| ``TOP`` | These flags are used to specify which side(s) of the sizer | ++---------------------------------------------------------------------+ item the border width will apply to. | +| ``BOTTOM`` | | ++---------------------------------------------------------------------+ | +| ``LEFT`` | | ++---------------------------------------------------------------------+ | +| ``RIGHT`` | | ++---------------------------------------------------------------------+ | +| ``ALL`` | | ++---------------------------------------------------------------------+-----------------------------------------------------------------------------+ +| ``EXPAND`` | The item will be expanded to fill the space assigned to | +| | the item. | ++---------------------------------------------------------------------+-----------------------------------------------------------------------------+ +| ``SHAPED`` | The item will be expanded as much as possible while also | +| | maintaining its aspect ratio | ++---------------------------------------------------------------------+-----------------------------------------------------------------------------+ +| ``FIXED_MINSIZE`` | If you would rather have a window item stay the size it started with then | +| | use ``FIXED_MINSIZE`` | ++---------------------------------------------------------------------+-----------------------------------------------------------------------------+ +| ``RESERVE_SPACE_EVEN_IF_HIDDEN`` | Normally `Sizers` don't allocate space for hidden windows or other items. | +| | This flag overrides this behavior so that sufficient space is allocated for | +| | the window even if it isn't visible. This makes it possible to dynamically | +| | show and hide controls without resizing parent dialog, for example. | ++---------------------------------------------------------------------+-----------------------------------------------------------------------------+ +| ``ALIGN_CENTER`` **or** ``ALIGN_CENTRE`` | The ``ALIGN*`` flags allow you to specify the alignment of the item | ++---------------------------------------------------------------------+ within the space allotted to it by the sizer, adjusted for the border if | +| ``ALIGN_LEFT`` | any. | ++---------------------------------------------------------------------+ | +| ``ALIGN_RIGHT`` | | ++---------------------------------------------------------------------+ | +| ``ALIGN_TOP`` | | ++---------------------------------------------------------------------+ | +| ``ALIGN_BOTTOM`` | | ++---------------------------------------------------------------------+ | +| ``ALIGN_CENTER_VERTICAL`` **or** ``ALIGN_CENTRE_VERTICAL`` | | ++---------------------------------------------------------------------+ | +| ``ALIGN_CENTER_HORIZONTAL`` **or** ``ALIGN_CENTRE_HORIZONTAL`` | | ++---------------------------------------------------------------------+-----------------------------------------------------------------------------+ + +| + + +Let's start with the simplest case: the alignment flags. These are pretty self-explanatory. + +.. list-table:: + :header-rows: 1 + :widths: 40 10 + :class: centertable + + * - Code + + - Resulting Image + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Second button is right aligned + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.ALIGN_RIGHT, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer4.png + :align: left + + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Second button is center-aligned + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.ALIGN_CENTER, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer41.png + :align: left + + + +Next is the ``EXPAND`` flag. This is synonymous with ``GROW``. + +.. list-table:: + :header-rows: 1 + :widths: 40 10 + :class: centertable + + * - Code + + - Resulting Image + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Second button expands to the whole parent's width + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer5.png + :align: left + + + +You can see that the first button takes its minimum size, and the second one grows to match it. This affects +controls in the opposite manner of the second parameter; ``EXPAND`` in a vertical sizer causes horizontal +expansion, and in a horizontal sizer it causes vertical expansion. + +Next is ``SHAPED``. This flag ensures that the width and height of the object stay proportional to each other. +It doesn't make much sense for buttons, but can be excellent for bitmaps, which would be contorted or clipped +if not scaled proportionally. + + +.. list-table:: + :header-rows: 1 + :widths: 30 10 + :class: centertable + + * - Code + + - Resulting Image + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Second button will scale proportionally + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 1, wx.SHAPED, 0) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer51.png + :align: left + + * - Same code as above, with window resized. The width grew dramatically with the height. In fact, it didn't + quite grow vertically the whole way because it couldn't maintain the correct ratio while doing so. + + - .. figure:: _static/images/overviews/boxsizer52.png + :align: left + + +Finally, we have the border flags. These only make sense when the `border` parameter is greater than 0, and describe +the sides of the control on which the border should appear. In order to demonstrate this most clearly, we'll keep +the ``EXPAND`` flag. + + +.. list-table:: + :header-rows: 1 + :widths: 40 10 + :class: centertable + + * - Code + + - Resulting Image + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Border size effects + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.LEFT, 20) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer53.png + :align: left + + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Border size effects + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer54.png + :align: left + + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Border size effects + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 20) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer55.png + :align: left + + * - .. code-block:: python + :emphasize-lines: 4 + + sizer = wx.BoxSizer(wx.VERTICAL) + # Border size effects + sizer.Add(wx.Button(self, -1, "An extremely long button text"), 0, 0, 0) + sizer.Add(wx.Button(self, -1, "Small Button"), 0, wx.EXPAND | wx.ALL, 20) + sizer.SetSizeHints(self) + self.SetSizer(sizer) + + + - .. figure:: _static/images/overviews/boxsizer56.png + :align: left + + +You can see that the button is offset from the specified edges of the sizer by the number of pixels that we +specified in the `border` parameter. + + Hiding Controls Using Sizers ---------------------------- @@ -118,9 +530,9 @@ This is useful when hiding parts of the interface, since you can avoid removing .. note:: This is supported only by :ref:`BoxSizer` and :ref:`FlexGridSizer`. - +-------- BoxSizer -^^^^^^^^ +-------- :ref:`BoxSizer` can lay out its children either vertically or horizontally, depending on what flag is being used in its constructor. When using a vertical sizer, each child can be centered, aligned to the right or aligned to the left. Correspondingly, when using a @@ -132,9 +544,9 @@ be stretched horizontally. The following sample shows the same dialog as in the :align: center - +-------------- StaticBoxSizer -^^^^^^^^^^^^^^ +-------------- :class:`StaticBoxSixer` is the same as a :class:`BoxSizer`, but surrounded by a static box. Here is a sample: @@ -143,9 +555,9 @@ StaticBoxSizer :align: center - +--------- GridSizer -^^^^^^^^^ +--------- :ref:`GridSizer` is a two-dimensional sizer. All children are given the same size, which is the minimal size required by the biggest child, in this case the text control in the left bottom border. Either the number of columns or the number or rows is fixed and the grid @@ -158,9 +570,9 @@ sizer will grow in the respectively other orientation if new children are added: For programming information, see :ref:`GridSizer`. - +------------- FlexGridSizer -^^^^^^^^^^^^^ +------------- Another two-dimensional sizer derived from :ref:`GridSizer`. The width of each column and the height of each row are calculated individually according to the minimal requirements from the respectively biggest child. Additionally, columns and rows can be declared to be stretchable diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/ArtProvider.GetBitmap.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/ArtProvider.GetBitmap.1.py new file mode 100644 index 00000000..1b7aea11 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/ArtProvider.GetBitmap.1.py @@ -0,0 +1,43 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to retrieve default platform's +# bitmaps using wx.ArtProvider + +import wx + +class BitmapFrame(wx.Frame): + + def __init__(self): + + wx.Frame.__init__(self, None, -1, title='ArtProvider example') + + panel = wx.Panel(self) + + main_sizer = wx.BoxSizer(wx.VERTICAL) + bitmap_sizer = wx.BoxSizer(wx.HORIZONTAL) + + bitmap_sizer.Add((0, 0), 1, wx.EXPAND) + + # Show a few bitmaps retrieved via wx.ArtProvider + for kind in [wx.ART_INFORMATION, wx.ART_WARNING, wx.ART_CDROM, wx.ART_CUT]: + bmp = wx.ArtProvider.GetBitmap(kind, wx.ART_OTHER, (32, 32)) + static_bitmap = wx.StaticBitmap(panel, -1, bmp) + bitmap_sizer.Add(static_bitmap, 0, wx.ALL, 5) + + # Layout everything in a nice sizer + bitmap_sizer.Add((0, 0), 1, wx.EXPAND) + main_sizer.Add((0, 0), 1, wx.EXPAND) + main_sizer.Add(bitmap_sizer, 0, wx.EXPAND) + main_sizer.Add((0, 0), 1, wx.EXPAND) + + panel.SetSizer(main_sizer) + main_sizer.SetSizeHints(panel) + main_sizer.Layout() + + +if __name__ == '__main__': + app = wx.App(0) + frame = BitmapFrame() + frame.Show() + app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/CloseEvent.Veto.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/CloseEvent.Veto.1.py new file mode 100644 index 00000000..c7e8cb84 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/CloseEvent.Veto.1.py @@ -0,0 +1,34 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample makes the main frame "immortal", i.e., non-closable +# by the user. The main window can not be close by pressing Alt+F4 +# or by clicking on the "X" button in the titlebar + +import wx + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Bind the "close window" event to the OnClose handler + self.Bind(wx.EVT_CLOSE, self.OnClose) + + self.Show() + self.close_attempts = 0 + + + def OnClose(self, event): + + # Veto the event the user can not close the main + # window in any way + self.close_attempts += 1 + print('I am immortal %d'%self.close_attempts) + event.Veto() + + +app = wx.App(False) +frame = MainWindow(None, 'Immortal Frame') +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/Colour.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/Colour.1.py new file mode 100644 index 00000000..deb012df --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/Colour.1.py @@ -0,0 +1,32 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to assign different fonts to various +# wx.StaticTexts + +import wx + +app = wx.App(0) +frame = wx.Frame(None, -1, 'Colour settings') + +text_ctrl_1 = wx.TextCtrl(frame, -1, 'Some text') +text_ctrl_1.SetBackgroundColour(wx.Colour(0, 0, 255)) +# OR +text_ctrl_2 = wx.TextCtrl(frame, -1, 'Other text') +text_ctrl_2.SetBackgroundColour('BLUE') +# OR +text_ctrl_3 = wx.TextCtrl(frame, -1, 'Another text') +text_ctrl_3.SetBackgroundColour('#0000FF') + +# Size up everything in a nice vertical box sizer +sizer = wx.BoxSizer(wx.VERTICAL) +sizer.Add(text_ctrl_1, 0, wx.EXPAND|wx.ALL, 10) +sizer.Add(text_ctrl_2, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 10) +sizer.Add(text_ctrl_3, 0, wx.EXPAND|wx.ALL, 10) +frame.SetSizer(sizer) +sizer.SetSizeHints(frame) + +frame.Show() + +# Enter the application main loop +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/EvtHandler.Bind.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/EvtHandler.Bind.1.py new file mode 100644 index 00000000..e9073b4f --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/EvtHandler.Bind.1.py @@ -0,0 +1,36 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows a simple example of how to use the +# "Bind" method to handle an event + +import wx + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Bind the "close window" event to the OnClose handler + self.Bind(wx.EVT_CLOSE, self.OnClose) + + self.Show() + + + def OnClose(self, event): + + # This displays a message box asking the user to confirm + # she wants to quit the application + dlg = wx.MessageDialog(self, 'Are you sure you want to quit?', 'Question', + wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) + + if dlg.ShowModal() == wx.ID_YES: + self.Destroy() + else: + event.Veto() + + +app = wx.App(False) +frame = MainWindow(None, 'Bind example') +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/Font.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/Font.1.py new file mode 100644 index 00000000..fc01b220 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/Font.1.py @@ -0,0 +1,63 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to assign different fonts to various +# wx.StaticTexts + +import wx + +class FontFrame(wx.Frame): + + def __init__(self, parent): + + wx.Frame.__init__(self, parent, title='Font sample') + + panel = wx.Panel(self, -1) + + text1 = '''Lasciatemi cantare +con la chitarra in mano +lasciatemi cantare +sono un italiano''' + + text2 = '''Buongiorno Italia gli spaghetti al dente +e un partigiano come Presidente +con l'autoradio sempre nella mano destra +e un canarino sopra la finestra''' + + text3 = '''Buongiorno Italia con i tuoi artisti +con troppa America sui manifesti +con le canzoni con amore con il cuore +con piu' donne sempre meno suore''' + + # Construct 2 font objects from the wx.Font constructor + font1 = wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_ITALIC, wx.FONTWEIGHT_NORMAL) + font2 = wx.Font(10, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) + + # A font can be retrieved from the OS default font + # and modified + font3 = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) + font3.SetStyle(wx.FONTSTYLE_ITALIC) + font3.SetPointSize(12) + + lyrics1 = wx.StaticText(panel, -1, text1, style=wx.ALIGN_CENTRE) + lyrics1.SetFont(font1) + lyrics2 = wx.TextCtrl(panel, -1, text2, style=wx.TE_CENTER|wx.TE_MULTILINE) + lyrics2.SetFont(font2) + lyrics3 = wx.StaticText(panel, -1, text3, style=wx.ALIGN_CENTRE) + lyrics3.SetFont(font3) + + # Size up everything in a nice vertical box sizer + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(lyrics1, 0, wx.EXPAND|wx.ALL, 10) + sizer.Add(lyrics2, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 10) + sizer.Add(lyrics3, 0, wx.EXPAND|wx.ALL, 10) + panel.SetSizer(sizer) + sizer.SetSizeHints(panel) + self.Center() + + +app = wx.App(0) +frame = FontFrame(None) +frame.Show() +# Enter the application main loop +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/Frame.SetStatusWidths.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/Frame.SetStatusWidths.1.py new file mode 100644 index 00000000..fe3ac595 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/Frame.SetStatusWidths.1.py @@ -0,0 +1,35 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a wx.StatusBar with 2 fields, +# set the second field to have double width with respect to the +# first and and display the date of today in the second field. + +import wx +import datetime + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # A Statusbar in the bottom of the window + # Set it up so it has two fields + self.CreateStatusBar(2) + + # Set the second field to be double in width wrt the first + self.SetStatusWidths([-1, -2]) + + # Get today date via datetime + today = datetime.datetime.today() + today = today.strftime('%d-%b-%Y') + + # Set today date in the second field + self.SetStatusText(today, 1) + + self.Show() + +app = wx.App(False) +frame = MainWindow(None, 'SetStatusWidths example') +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/MenuBar.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/MenuBar.1.py new file mode 100644 index 00000000..1a84b406 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/MenuBar.1.py @@ -0,0 +1,40 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a simple wx.MenuBar +# and a simple wx.StatusBar + +import wx + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # A Statusbar in the bottom of the window + self.CreateStatusBar() + + # Setting up the menu + file_menu = wx.Menu() + + # wx.ID_ABOUT and wx.ID_EXIT are standard IDs provided + # by wxWidgets. + file_menu.Append(wx.ID_ABOUT, '&About', + 'Information about this application') + file_menu.AppendSeparator() + file_menu.Append(wx.ID_EXIT, 'E&xit', 'Exit the application') + + # Creating the menubar + menu_bar = wx.MenuBar() + + # Adding the 'file_menu' to the menu bar + menu_bar.Append(file_menu, '&File') + + # Adding the menu bar to the frame content + self.SetMenuBar(menu_bar) + self.Show() + +app = wx.App(False) +frame = MainWindow(None, 'MenuBar and StatusBar') +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/MoveEvent.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/MoveEvent.1.py new file mode 100644 index 00000000..3251ae86 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/MoveEvent.1.py @@ -0,0 +1,36 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to listen to a move change event for a +# top-level window (wx.Frame, wx.Dialog). This is MSW-specific + +import wx + +class MovingFrame(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + wx.StaticText(self, label='x:', pos=(10, 10)) + wx.StaticText(self, label='y:', pos=(10, 30)) + + self.st1 = wx.StaticText(self, label='', pos=(30, 10)) + self.st2 = wx.StaticText(self, label='', pos=(30, 30)) + + self.Bind(wx.EVT_MOVE, self.OnMove) + + self.Show() + + def OnMove(self, event): + + # Capture the mouse position (in screen coordinates) and + # assign its x, y values to the statictexts + x, y = event.GetPosition() + self.st1.SetLabel('%d'%x) + self.st2.SetLabel('%d'%y) + + +app = wx.App(False) +frame = MovingFrame(None, 'MoveEvent example') +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/Notebook.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/Notebook.1.py new file mode 100644 index 00000000..e8e37507 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/Notebook.1.py @@ -0,0 +1,75 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample creates a "File->Open" menu, and lets the user select +# a Python file. Upon selection, the file is read in memory and a new +# wx.TextCtrl showing the file content is added as a page of a wx.Notebook + +import wx +import os + +class NotebookFrame(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Create the notebook + self.notebook = wx.Notebook(self, style=wx.NB_BOTTOM) + + # Setting up the menu + file_menu = wx.Menu() + + # wx.ID_OPEN + menu_item = file_menu.Append(wx.ID_OPEN, '&Open...', 'Open and read a new Python file') + # Bind the "select menu item" event to the OnOpen event handler + self.Bind(wx.EVT_MENU, self.OnOpen, menu_item) + + # Creating the menubar + menu_bar = wx.MenuBar() + + # Adding the 'file_menu' to the menu bar + menu_bar.Append(file_menu, '&File') + + # Adding the menu bar to the frame content + self.SetMenuBar(menu_bar) + + self.Show() + + + def OnOpen(self, event): + + # This is how you pre-establish a file filter so that the dialog + # only shows the extension(s) you want it to. + wildcard = 'Python source (*.py)|*.py' + + dlg = wx.FileDialog(None, message="Choose a Python file", defaultDir=os.getcwd(), + defaultFile="", wildcard=wildcard, style=wx.FD_OPEN) + + # Show the dialog and retrieve the user response. If it is the OK response, + # process the data. + if dlg.ShowModal() == wx.ID_OK: + # This returns the file that was selected + path = dlg.GetPath() + + # Open the file as read-only and slurp its content + fid = open(path, 'rt') + text = fid.read() + fid.close() + + # Create the notebook page as a wx.TextCtrl and + # add it as a page of the wx.Notebook + text_ctrl = wx.TextCtrl(self.notebook, style=wx.TE_MULTILINE) + text_ctrl.SetValue(text) + + filename = os.path.split(os.path.splitext(path)[0])[1] + self.notebook.AddPage(text_ctrl, filename, select=True) + + # Destroy the dialog. Don't do this until you are done with it! + # BAD things can happen otherwise! + dlg.Destroy() + + +app = wx.App(False) +frame = NotebookFrame(None, 'Notebook example') +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/PaintDC.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/PaintDC.1.py new file mode 100644 index 00000000..2833c4d5 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/PaintDC.1.py @@ -0,0 +1,44 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample uses the random module to draw 100 random lines iinside +# a wx.Frame client area, as a demonstration of how to handle a wx.PaintDC + +import wx +import random + +class PaintFrame(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # Bind a "paint" event for the frame to the + # "OnPaint" method + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Show() + + + def OnPaint(self, event): + + dc = wx.PaintDC(self) + w, h = self.GetClientSize() + + # Use a blue pen, for example... + + dc.SetPen(wx.Pen('BLUE')) + + # Remember the signature of wx.DC.DrawLine: + # DrawLine(x1, y1, x2, y2) + + for i in range(100): + x1 = random.randint(1, w-1) + y1 = random.randint(1, h-1) + x2 = random.randint(1, w-1) + y2 = random.randint(1, h-1) + dc.DrawLine(x1, y1, x2, y2) + + +app = wx.App(False) +frame = PaintFrame(None, 'PaintDC example') +app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/Process.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/Process.1.py new file mode 100644 index 00000000..bc24996a --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/Process.1.py @@ -0,0 +1,73 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample demonstrates a simple use of wx.Process/wx.Execute to +# monitor an external program stdout + +import wx + +class ProcessFrame(wx.Frame): + + def __init__(self, parent): + wx.Frame.__init__(self, parent, title='Process/Execute example') + + panel = wx.Panel(self) + self.label = wx.TextCtrl(panel, style=wx.TE_MULTILINE) + self.btn = wx.Button(panel, label="Start") + + self.process = None + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.label, proportion=1, flag=wx.EXPAND) + sizer.Add(self.btn, proportion=0, flag=wx.EXPAND) + + panel.SetSizerAndFit(sizer) + self.Bind(wx.EVT_BUTTON, self.OnButton) + + self.Bind(wx.EVT_IDLE, self.OnIdle) + self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded) + + def OnButton(self, event): + self.btn.Enable(False) + self.label.SetValue('') + self.LongRunning() + + def LongRunning(self): + """ + This runs in the GUI thread but uses wx.Process and + wx.Execute to start and monitor a separate process. + """ + + cmd = 'python -u external_program.py' + + self.process = wx.Process(self) + self.process.Redirect() + + wx.Execute(cmd, wx.EXEC_ASYNC, self.process) + + def OnIdle(self, event): + """ This event handler catches the process stdout. """ + + if self.process is not None: + stream = self.process.GetInputStream() + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + def OnProcessEnded(self, event): + + stream = self.process.GetInputStream() + + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + self.btn.Enable(True) + self.label.AppendText('Finished') + + +if __name__ == "__main__": + app = wx.App(0) + frame = ProcessFrame(None) + frame.Show() + app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/SplitterWindow.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/SplitterWindow.1.py new file mode 100644 index 00000000..b24dc057 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/SplitterWindow.1.py @@ -0,0 +1,43 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a "spli-split" window, i.e. a +# window split verticall which contains two windows split horizontally + +import wx + +class SplitterFrame(wx.Frame): + + def __init__(self): + + wx.Frame.__init__(self, None, title='SplitterWindow example') + + # Create the main splitter window (to be split vertically) + splitter = wx.SplitterWindow(self, -1, style=wx.SP_LIVE_UPDATE) + splitter.SetMinimumPaneSize(100) + + panel1 = wx.Panel(splitter, -1) + + static = wx.StaticText(panel1, -1, 'Hello World', pos=(10, 100)) + panel1.SetBackgroundColour(wx.WHITE) + + # Create the second splitter window (to be split horizontally) + splitter2 = wx.SplitterWindow(splitter, -1, style=wx.SP_LIVE_UPDATE) + splitter2.SetMinimumPaneSize(100) + + panel2 = wx.Panel(splitter2, -1) + panel2.SetBackgroundColour(wx.BLUE) + + panel3 = wx.Panel(splitter2, -1) + panel3.SetBackgroundColour(wx.RED) + + splitter2.SplitHorizontally(panel2, panel3) + splitter.SplitVertically(panel1, splitter2) + self.Centre() + + +if __name__ == '__main__': + app = wx.App(0) + frame = SplitterFrame() + frame.Show() + app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/StatusBar.SetStatusWidths.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/StatusBar.SetStatusWidths.1.py new file mode 100644 index 00000000..fe3ac595 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/StatusBar.SetStatusWidths.1.py @@ -0,0 +1,35 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows how to create a wx.StatusBar with 2 fields, +# set the second field to have double width with respect to the +# first and and display the date of today in the second field. + +import wx +import datetime + +class MainWindow(wx.Frame): + + def __init__(self, parent, title): + + wx.Frame.__init__(self, parent, title=title) + + # A Statusbar in the bottom of the window + # Set it up so it has two fields + self.CreateStatusBar(2) + + # Set the second field to be double in width wrt the first + self.SetStatusWidths([-1, -2]) + + # Get today date via datetime + today = datetime.datetime.today() + today = today.strftime('%d-%b-%Y') + + # Set today date in the second field + self.SetStatusText(today, 1) + + self.Show() + +app = wx.App(False) +frame = MainWindow(None, 'SetStatusWidths example') +app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/TreeCtrl.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/TreeCtrl.1.py new file mode 100644 index 00000000..a5dc6658 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/TreeCtrl.1.py @@ -0,0 +1,51 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample classifies the Python keywords alphabetically, using the +# first letter of the keyword (i.e., ``and`` goes into ``a``, ``for`` +# goes into ``f`` and so on): +# +# * For each letter, adds a child to the treectrl root +# * In each child of the root item, adds its corresponding keyword(s) +# + +import wx +import keyword +import string + +class TreeFrame(wx.Frame): + + def __init__(self): + + wx.Frame.__init__(self, None, title='TreeCtrl example') + + tree_ctrl = wx.TreeCtrl(self, -1, style=wx.TR_DEFAULT_STYLE | \ + wx.TR_FULL_ROW_HIGHLIGHT | \ + wx.TR_EDIT_LABELS) + + # Add the tree root + root = tree_ctrl.AddRoot('Python keywords') + + letters = [] + + for kwd in keyword.kwlist: + first = kwd[0] + if first not in letters: + letters.append(first) + + for letter in letters: + item = tree_ctrl.AppendItem(root, letter) + for kwd in keyword.kwlist: + first = kwd[0] + if first == letter: + sub_item = tree_ctrl.AppendItem(item, kwd) + + tree_ctrl.ExpandAll() + self.Centre() + + +if __name__ == '__main__': + app = wx.App(0) + frame = TreeFrame() + frame.Show() + app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/functions.CallAfter.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/functions.CallAfter.1.py new file mode 100644 index 00000000..01e4a684 --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/functions.CallAfter.1.py @@ -0,0 +1,57 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample shows hot to take advantage of wx.CallAfter when running a +# separate thread and updating the GUI in the main thread + +import wx +import threading +import time + +class MainFrame(wx.Frame): + + def __init__(self, parent): + wx.Frame.__init__(self, parent, title='CallAfter example') + + panel = wx.Panel(self) + self.label = wx.StaticText(panel, label="Ready") + self.btn = wx.Button(panel, label="Start") + self.gauge = wx.Gauge(panel) + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.label, proportion=1, flag=wx.EXPAND) + sizer.Add(self.btn, proportion=0, flag=wx.EXPAND) + sizer.Add(self.gauge, proportion=0, flag=wx.EXPAND) + + panel.SetSizerAndFit(sizer) + self.Bind(wx.EVT_BUTTON, self.OnButton) + + def OnButton(self, event): + """ This event handler starts the separate thread. """ + self.btn.Enable(False) + self.gauge.SetValue(0) + self.label.SetLabel("Running") + + thread = threading.Thread(target=self.LongRunning) + thread.start() + + def OnLongRunDone(self): + self.gauge.SetValue(100) + self.label.SetLabel("Done") + self.btn.Enable(True) + + def LongRunning(self): + """This runs in a different thread. Sleep is used to + simulate a long running task.""" + time.sleep(3) + wx.CallAfter(self.gauge.SetValue, 20) + time.sleep(5) + wx.CallAfter(self.gauge.SetValue, 70) + time.sleep(4) + wx.CallAfter(self.OnLongRunDone) + +if __name__ == "__main__": + app = wx.App(0) + frame = MainFrame(None) + frame.Show() + app.MainLoop() \ No newline at end of file diff --git a/docs/sphinx/rest_substitutions/snippets/python/contrib/functions.Execute.1.py b/docs/sphinx/rest_substitutions/snippets/python/contrib/functions.Execute.1.py new file mode 100644 index 00000000..bc24996a --- /dev/null +++ b/docs/sphinx/rest_substitutions/snippets/python/contrib/functions.Execute.1.py @@ -0,0 +1,73 @@ +##Andrea Gavana +#!/usr/bin/env python + +# This sample demonstrates a simple use of wx.Process/wx.Execute to +# monitor an external program stdout + +import wx + +class ProcessFrame(wx.Frame): + + def __init__(self, parent): + wx.Frame.__init__(self, parent, title='Process/Execute example') + + panel = wx.Panel(self) + self.label = wx.TextCtrl(panel, style=wx.TE_MULTILINE) + self.btn = wx.Button(panel, label="Start") + + self.process = None + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.label, proportion=1, flag=wx.EXPAND) + sizer.Add(self.btn, proportion=0, flag=wx.EXPAND) + + panel.SetSizerAndFit(sizer) + self.Bind(wx.EVT_BUTTON, self.OnButton) + + self.Bind(wx.EVT_IDLE, self.OnIdle) + self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded) + + def OnButton(self, event): + self.btn.Enable(False) + self.label.SetValue('') + self.LongRunning() + + def LongRunning(self): + """ + This runs in the GUI thread but uses wx.Process and + wx.Execute to start and monitor a separate process. + """ + + cmd = 'python -u external_program.py' + + self.process = wx.Process(self) + self.process.Redirect() + + wx.Execute(cmd, wx.EXEC_ASYNC, self.process) + + def OnIdle(self, event): + """ This event handler catches the process stdout. """ + + if self.process is not None: + stream = self.process.GetInputStream() + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + def OnProcessEnded(self, event): + + stream = self.process.GetInputStream() + + if stream.CanRead(): + text = stream.read() + self.label.AppendText(text) + + self.btn.Enable(True) + self.label.AppendText('Finished') + + +if __name__ == "__main__": + app = wx.App(0) + frame = ProcessFrame(None) + frame.Show() + app.MainLoop() diff --git a/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.1.py b/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.1.py index 5f117e7b..d514966c 100644 --- a/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.1.py +++ b/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.1.py @@ -7,7 +7,7 @@ pass - # optionally override this one as well + # optionally override this one as well def CreateIconBundle(self, id, client): # Your implementation of CreateIconBundle here diff --git a/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.2.py b/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.2.py index dd0d985c..78186c29 100644 --- a/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.2.py +++ b/docs/sphinx/rest_substitutions/snippets/python/converted/ArtProvider.2.py @@ -2,3 +2,5 @@ if wx.Platform == '__WXGTK__': bmp = wx.ArtProvider.GetBitmap("gtk-cdrom", wx.ART_MENU) + + diff --git a/docs/sphinx/rest_substitutions/snippets/python/converted/LogNull.2.py b/docs/sphinx/rest_substitutions/snippets/python/converted/LogNull.2.py index d8da7307..d0e05cbc 100644 --- a/docs/sphinx/rest_substitutions/snippets/python/converted/LogNull.2.py +++ b/docs/sphinx/rest_substitutions/snippets/python/converted/LogNull.2.py @@ -4,4 +4,5 @@ if os.path.exists('bogus.png'): bmp = wx.Bitmap('bogus.png') else: - ... + pass + # ... do something else here... diff --git a/etg/_xrc.py b/etg/_xrc.py index f35c0a41..374c7b34 100644 --- a/etg/_xrc.py +++ b/etg/_xrc.py @@ -122,7 +122,7 @@ def run(): module.addPyFunction('EmptyXmlResource', '(flags=XRC_USE_LOCALE, domain="")', - deprecated="Use XmlResource instead", + deprecated="Use :class:`xrc.XmlResource` instead", doc='A compatibility wrapper for the XmlResource(flags, domain) constructor', body='return XmlResource(flags, domain)') diff --git a/etg/app.py b/etg/app.py index 7ffd6222..5c6f1368 100644 --- a/etg/app.py +++ b/etg/app.py @@ -508,8 +508,8 @@ def run(): - module.addPyClass('PySimpleApp', ['App'], deprecated="Use wx.App instead.", - doc="""This class is deprecated. Please use wx.App instead.""", + module.addPyClass('PySimpleApp', ['App'], deprecated="Use :class:`App` instead.", + doc="""This class is deprecated. Please use :class:`App` instead.""", items=[ PyFunctionDef('__init__', '(self, *args, **kw)', body="App.__init__(self, *args, **kw)") diff --git a/etg/bitmap.py b/etg/bitmap.py index f8400ad4..36171b10 100644 --- a/etg/bitmap.py +++ b/etg/bitmap.py @@ -264,8 +264,8 @@ def run(): """) module.addPyFunction('BitmapFromBuffer', '(width, height, dataBuffer, alphaBuffer=None)', - deprecated="Use Bitmap.FromBuffer or Bitmap.FromBufferAndAlpha instead.", - doc='A compatibility wrapper for Bitmap.FromBuffer and Bitmap.FromBufferAndAlpha', + deprecated="Use :meth:`Bitmap.FromBuffer` or :meth:`Bitmap.FromBufferAndAlpha` instead.", + doc='A compatibility wrapper for :meth:`Bitmap.FromBuffer` and :meth:`Bitmap.FromBufferAndAlpha`', body="""\ if alphaBuffer is not None: return Bitmap.FromBufferAndAlpha(width, height, dataBuffer, alphaBuffer) @@ -306,8 +306,8 @@ def run(): """) module.addPyFunction('BitmapFromBufferRGBA', '(width, height, dataBuffer)', - deprecated="Use Bitmap.FromBufferRGBA instead.", - doc='A compatibility wrapper for Bitmap.FromBufferRGBA', + deprecated="Use :meth:`Bitmap.FromBufferRGBA` instead.", + doc='A compatibility wrapper for :meth:`Bitmap.FromBufferRGBA`', body='return Bitmap.FromBufferRGBA(width, height, dataBuffer)') @@ -351,20 +351,20 @@ def run(): """) module.addPyFunction('EmptyBitmapRGBA', '(width, height, red=0, green=0, blue=0, alpha=0)', - deprecated="Use Bitmap.FromRGBA instead.", - doc='A compatibility wrapper for Bitmap.FromRGBA', + deprecated="Use :meth:`Bitmap.FromRGBA` instead.", + doc='A compatibility wrapper for :meth:`Bitmap.FromRGBA`', body='return Bitmap.FromRGBA(width, height, red, green, blue, alpha)') #----------------------------------------------------------------------- # For compatibility: module.addPyFunction('EmptyBitmap', '(width, height, depth=BITMAP_SCREEN_DEPTH)', - deprecated="Use wx.Bitmap instead", + deprecated="Use :class:`Bitmap` instead", doc='A compatibility wrapper for the wx.Bitmap(width, height, depth) constructor', body='return Bitmap(width, height, depth)') module.addPyFunction('BitmapFromImage', '(image)', - deprecated="Use wx.Bitmap instead", + deprecated="Use :class:`Bitmap` instead", doc='A compatibility wrapper for the wx.Bitmap(wx.Image) constructor', body='return Bitmap(image)') diff --git a/etg/event.py b/etg/event.py index 997d2c6b..da0c431c 100644 --- a/etg/event.py +++ b/etg/event.py @@ -142,7 +142,7 @@ def run(): PyPropertyDef('typeId', '_getEvtType'), PyFunctionDef('__call__', '(self, *args)', - deprecated="Use wx.EvtHandler.Bind() instead.", + deprecated="Use :meth:`EvtHandler.Bind` instead.", doc="""\ For backwards compatibility with the old EVT_* functions. Should be called with either (window, func), (window, ID, @@ -330,7 +330,7 @@ def run(): return event.Unbind(self, id, id2, handler) """) - module.addPyCode('PyEvtHandler = wx.deprecated(EvtHandler, "Use EvtHandler instead.")') + module.addPyCode('PyEvtHandler = wx.deprecated(EvtHandler, "Use :class:`EvtHandler` instead.")') #--------------------------------------- diff --git a/etg/icon.py b/etg/icon.py index 49f112fc..5c3fe0cb 100644 --- a/etg/icon.py +++ b/etg/icon.py @@ -61,8 +61,8 @@ def run(): # For compatibility: module.addPyFunction('EmptyIcon', '()', - deprecated="Use wx.Icon instead", - doc='A compatibility wrapper for the wx.Icon() constructor', + deprecated="Use :class:`Icon` instead", + doc='A compatibility wrapper for the :class:`Icon` constructor', body='return Icon()') #----------------------------------------------------------------- diff --git a/etg/image.py b/etg/image.py index a5f308f2..96c7aab4 100644 --- a/etg/image.py +++ b/etg/image.py @@ -222,7 +222,7 @@ def run(): c.addCppMethod('PyObject*', 'GetDataBuffer', '()', doc="""\ Returns a writable Python buffer object that is pointing at the RGB - image data buffer inside the wx.Image. You need to ensure that you do + image data buffer inside the :class:`Image`. You need to ensure that you do not use this buffer object after the image has been destroyed.""", body="""\ byte* data = self->GetData(); @@ -236,7 +236,7 @@ def run(): c.addCppMethod('PyObject*', 'GetAlphaBuffer', '()', doc="""\ Returns a writable Python buffer object that is pointing at the Alpha - data buffer inside the wx.Image. You need to ensure that you do + data buffer inside the :class:`Image`. You need to ensure that you do not use this buffer object after the image has been destroyed.""", body="""\ byte* data = self->GetAlpha(); @@ -254,7 +254,7 @@ def run(): Sets the internal image data pointer to point at a Python buffer object. This can save making an extra copy of the data but you must ensure that the buffer object lives lives at least as long as the - wx.Image does.""", + :class:`Image` does.""", body="""\ if (!data->checkSize(self->GetWidth() * self->GetHeight() * 3)) return; @@ -266,7 +266,7 @@ def run(): Sets the internal image data pointer to point at a Python buffer object. This can save making an extra copy of the data but you must ensure that the buffer object lives lives at least as long as the - wx.Image does.""", + :class:`Image` does.""", body="""\ if (!data->checkSize(new_width * new_height * 3)) return; @@ -280,7 +280,7 @@ def run(): Sets the internal image alpha pointer to point at a Python buffer object. This can save making an extra copy of the data but you must ensure that the buffer object lives lives at least as long as the - wx.Image does.""", + :class:`Image` does.""", body="""\ if (!alpha->checkSize(self->GetWidth() * self->GetHeight())) return; @@ -349,7 +349,7 @@ def run(): c.addPyMethod('ConvertToBitmap', '(self, depth=-1)', doc="""\ ConvertToBitmap(depth=-1) -> Bitmap\n - Convert the image to a wx.Bitmap.""", + Convert the image to a :class:`Bitmap`.""", body="""\ bmp = wx.Bitmap(self, depth) return bmp @@ -358,7 +358,7 @@ def run(): c.addPyMethod('ConvertToMonoBitmap', '(self, red, green, blue)', doc="""\ ConvertToMonoBitmap(red, green, blue) -> Bitmap\n - Creates a monochrome version of the image and returns it as a wx.Bitmap.""", + Creates a monochrome version of the image and returns it as a :class:`Bitmap`.""", body="""\ mono = self.ConvertToMono( red, green, blue ) bmp = wx.Bitmap( mono, 1 ) @@ -483,27 +483,27 @@ def run(): # For compatibility: module.addPyFunction('EmptyImage', '(width=0, height=0, clear=True)', - deprecated="Use wx.Image instead.", + deprecated="Use :class:`Image` instead.", doc='A compatibility wrapper for the wx.Image(width, height) constructor', body='return Image(width, height, clear)') module.addPyFunction('ImageFromBitmap', '(bitmap)', - deprecated="Use wx.Image instead.", - doc='Create a wx.Image from a wx.Bitmap', + deprecated="Use :class:`Image` instead.", + doc='Create a :class:`Image` from a :class:`Bitmap`', body='return bitmap.ConvertToImage()') module.addPyFunction('ImageFromStream', '(stream, type=BITMAP_TYPE_ANY, index=-1)', - deprecated="Use wx.Image instead.", + deprecated="Use :class:`Image` instead.", doc='Load an image from a stream (file-like object)', body='return wx.Image(stream, type, index)') module.addPyFunction('ImageFromData', '(width, height, data)', - deprecated="Use wx.Image instead.", + deprecated="Use :class:`Image` instead.", doc='Compatibility wrapper for creating an image from RGB data', body='return Image(width, height, data)') module.addPyFunction('ImageFromDataWithAlpha', '(width, height, data, alpha)', - deprecated="Use wx.Image instead.", + deprecated="Use :class:`Image` instead.", doc='Compatibility wrapper for creating an image from RGB and Alpha data', body='return Image(width, height, data, alpha)') @@ -511,24 +511,24 @@ def run(): module.addPyFunction('ImageFromBuffer', '(width, height, dataBuffer, alphaBuffer=None)', doc="""\ - Creates a `wx.Image` from the data in dataBuffer. The dataBuffer + Creates a :class:`Image` from the data in `dataBuffer`. The `dataBuffer` parameter must be a Python object that implements the buffer interface, - such as a string, array, etc. The dataBuffer object is expected to + such as a string, array, etc. The `dataBuffer` object is expected to contain a series of RGB bytes and be width*height*3 bytes long. A buffer object can optionally be supplied for the image's alpha channel data, and it is expected to be width*height bytes long. - The wx.Image will be created with its data and alpha pointers initialized + The :class:`Image` will be created with its data and alpha pointers initialized to the memory address pointed to by the buffer objects, thus saving the - time needed to copy the image data from the buffer object to the wx.Image. + time needed to copy the image data from the buffer object to the :class:`Image`. While this has advantages, it also has the shoot-yourself-in-the-foot risks associated with sharing a C pointer between two objects. To help alleviate the risk a reference to the data and alpha buffer - objects are kept with the wx.Image, so that they won't get deleted until + objects are kept with the :class:`Image`, so that they won't get deleted until after the wx.Image is deleted. However please be aware that it is not guaranteed that an object won't move its memory buffer to a new location - when it needs to resize its contents. If that happens then the wx.Image + when it needs to resize its contents. If that happens then the :class:`Image` will end up referring to an invalid memory location and could cause the application to crash. Therefore care should be taken to not manipulate the objects used for the data and alpha buffers in a way that would cause diff --git a/etg/pyevent.py b/etg/pyevent.py index df88dbe5..ff02f53f 100644 --- a/etg/pyevent.py +++ b/etg/pyevent.py @@ -33,16 +33,16 @@ def run(): cls = ClassDef(name='wxPyEvent', bases=['wxEvent'], briefDoc="""\ - wx.PyEvent can be used as a base class for implementing custom + :class:`PyEvent` can be used as a base class for implementing custom event types in Python. You should derive from this class instead - of `wx.Event` because this class is Python-aware and is able to + of :class:`Event` because this class is Python-aware and is able to transport its Python bits safely through the wxWidgets event system and have them still be there when the event handler is - invoked. Note that since wx.PyEvent is taking care of preserving + invoked. Note that since :class:`PyEvent` is taking care of preserving the extra attributes that have been set then you do not need to override the Clone method in your derived classes. - :see: `wx.PyCommandEvent`""", + :see: :class:`PyCommandEvent`""", items=[ MethodDef(name='wxPyEvent', isCtor=True, items=[ ParamDef(type='int', name='id', default='0'), @@ -74,17 +74,17 @@ def run(): cls = ClassDef(name='wxPyCommandEvent', bases=['wxCommandEvent'], briefDoc="""\ - wx.PyCommandEvent can be used as a base class for implementing + :class:`PyCommandEvent` can be used as a base class for implementing custom event types in Python. You should derive from this class - instead of `wx.CommandEvent` because this class is Python-aware + instead of :class:`CommandEvent` because this class is Python-aware and is able to transport its Python bits safely through the wxWidgets event system and have them still be there when the - event handler is invoked. Note that since wx.PyCommandEvent is + event handler is invoked. Note that since :class:`PyCommandEvent` is taking care of preserving the extra attributes that have been set then you do not need to override the Clone method in your derived classes. - :see: `wx.PyEvent`""", + :see: :class:`PyEvent`""", items=[ MethodDef(name='wxPyCommandEvent', isCtor=True, items=[ ParamDef(type='wxEventType', name='evenType', default='wxEVT_NULL'), diff --git a/etg/rawbmp.py b/etg/rawbmp.py index 135a38f5..b850a38a 100644 --- a/etg/rawbmp.py +++ b/etg/rawbmp.py @@ -44,12 +44,12 @@ def run(): addPixelDataClass(module, 'wxNativePixelData', 'wxBitmap', bpp=24, doc="""\ - NativePixelData: A class providing direct access to a wx.Bitmap's + A class providing direct access to a :class:`Bitmap`'s internal data without alpha channel (RGB). """) addPixelDataClass(module, 'wxAlphaPixelData', 'wxBitmap', bpp=32, doc="""\ - AlphaPixelData: A class providing direct access to a wx.Bitmap's + A class providing direct access to a :class:`wx.Bitmap`'s internal data including the alpha channel (RGBA). """) #addPixelDataClass(module, 'wxImagePixelData', 'wxImage', bpp=32, diff --git a/etg/toolbar.py b/etg/toolbar.py index 046dfaed..087e9c57 100644 --- a/etg/toolbar.py +++ b/etg/toolbar.py @@ -81,7 +81,7 @@ def run(): # TODO: Which others are commonly enough used that they should be here too? c.addPyMethod('AddSimpleTool', '(self, toolId, bitmap, shortHelpString="", longHelpString="", isToggle=0)', doc='Old style method to add a tool to the toolbar.', - deprecated='Use AddTool instead.', + deprecated='Use :meth:`AddTool` instead.', body="""\ kind = wx.ITEM_NORMAL if isToggle: kind = wx.ITEM_CHECK @@ -92,7 +92,7 @@ def run(): '(self, id, label, bitmap, bmpDisabled=wx.NullBitmap, kind=wx.ITEM_NORMAL,' ' shortHelp="", longHelp="", clientData=None)', doc='Old style method to add a tool in the toolbar.', - deprecated='Use AddTool instead.', + deprecated='Use :meth:`AddTool` instead.', body="""\ return self.AddTool(id, label, bitmap, bmpDisabled, kind, shortHelp, longHelp, clientData) @@ -100,7 +100,7 @@ def run(): c.addPyMethod('InsertSimpleTool', '(self, pos, toolId, bitmap, shortHelpString="", longHelpString="", isToggle=0)', doc='Old style method to insert a tool in the toolbar.', - deprecated='Use InsertTool instead.', + deprecated='Use :meth:`InsertTool` instead.', body="""\ kind = wx.ITEM_NORMAL if isToggle: kind = wx.ITEM_CHECK @@ -111,7 +111,7 @@ def run(): '(self, pos, id, label, bitmap, bmpDisabled=wx.NullBitmap, kind=wx.ITEM_NORMAL,' ' shortHelp="", longHelp="", clientData=None)', doc='Old style method to insert a tool in the toolbar.', - deprecated='Use InsertTool instead.', + deprecated='Use :meth:`InsertTool` instead.', body="""\ return self.InsertTool(pos, id, label, bitmap, bmpDisabled, kind, shortHelp, longHelp, clientData) diff --git a/etg/wxdatetime.py b/etg/wxdatetime.py index 30dc945f..b4bed899 100644 --- a/etg/wxdatetime.py +++ b/etg/wxdatetime.py @@ -113,21 +113,21 @@ def run(): # and give them some simple wrappers for Classic compatibility module.addPyFunction('DateTimeFromTimeT', '(timet)', - doc="Compatibility wrapper for DateTime.FromTimeT", + doc="Compatibility wrapper for :meth:`DateTime.FromTimeT`", body="return DateTime.FromTimeT(timet)", - deprecated='Use DateTime.FromTimeT instead.') + deprecated='Use :meth:`DateTime.FromTimeT` instead.') module.addPyFunction('DateTimeFromJDN', '(jdn)', - doc="Compatibility wrapper for DateTime.FromJDN", + doc="Compatibility wrapper for :meth:`DateTime.FromJDN`", body="return DateTime.FromJDN(jdn)", - deprecated='Use DateTime.FromJDN instead.') + deprecated='Use :meth:`DateTime.FromJDN` instead.') module.addPyFunction('DateTimeFromHMS', '(hour, minute=0, second=0, millisecond=0)', - doc="Compatibility wrapper for DateTime.FromHMS", + doc="Compatibility wrapper for :meth:`DateTime.FromHMS`", body="return DateTime.FromHMS(hour, minute, second, millisecond)", - deprecated='DateTime.FromHMS instead.') + deprecated='Use :meth:`DateTime.FromHMS` instead.') module.addPyFunction('DateTimeFromDMY', '(day, month, year=DateTime.Inv_Year, hour=0, minute=0, second=0, millisecond=0)', - doc="Compatibility wrapper for DateTime.FromDMY", + doc="Compatibility wrapper for :meth:`DateTime.FromDMY`", body="return DateTime.FromDMY(day, month, year, hour, minute, second, millisecond)", - deprecated='Use DateTime.FromDMY instead.') + deprecated='Use :meth:`DateTime.FromDMY` instead.') # Fixup similar conflicts in the Set method overloads diff --git a/etgtools/sphinx_generator.py b/etgtools/sphinx_generator.py index fdd0dce7..17bcff50 100644 --- a/etgtools/sphinx_generator.py +++ b/etgtools/sphinx_generator.py @@ -1460,7 +1460,7 @@ class Snippet(Node): hierarchy = self.GetHierarchy() spacer = '' if 'Section' in hierarchy: - spacer = ' '*4 + spacer = ' '*3 elif 'Parameter' in hierarchy: spacer = ' ' @@ -1942,7 +1942,7 @@ class XMLDocString(object): else: raise Exception('Unhandled docstring kind for %s'%xml_item.__class__.__name__) - if hasattr(xml_item, 'deprecated') and xml_item.deprecated: + if hasattr(xml_item, 'deprecated') and xml_item.deprecated and isinstance(xml_item.deprecated, basestring): element = et.Element('deprecated', kind='deprecated') element.text = VERSION @@ -2267,7 +2267,16 @@ class XMLDocString(object): fullname = self.GetFullName() contrib_folder = os.path.join(SNIPPETROOT, 'python', 'contrib') - possible_py = glob.glob(os.path.normpath(contrib_folder + '/' + fullname + '*.py')) + possible_py = [] + + for suffix in range(1, 101): + + sample = os.path.join(contrib_folder, '%s.%d.py'%(fullname, suffix)) + + if not os.path.isfile(sample): + break + + possible_py.append(sample) return possible_py @@ -2579,6 +2588,12 @@ class XMLDocString(object): self.Reformat(stream) + if hasattr(method, 'deprecated') and method.deprecated: + text = method.deprecated + if isinstance(text, basestring): + text = '%s %s\n%s%s\n\n'%(' .. deprecated::', VERSION, ' '*9, text.replace('\n', ' ')) + stream.write(text) + possible_py = self.HuntContributedSnippets() if possible_py: @@ -2623,6 +2638,10 @@ class XMLDocString(object): self.Reformat(stream) + if hasattr(function, 'deprecated') and function.deprecated: + text = '%s %s\n%s%s\n\n'%(' .. deprecated::', VERSION, ' '*6, function.deprecated.replace('\n', ' ')) + stream.write(text) + possible_py = self.HuntContributedSnippets() if possible_py: diff --git a/sphinxtools/postprocess.py b/sphinxtools/postprocess.py index 957fd763..cee3043d 100644 --- a/sphinxtools/postprocess.py +++ b/sphinxtools/postprocess.py @@ -165,8 +165,10 @@ def BuildEnumsAndMethods(sphinxDir): # Avoid Sphinx warnings on wx.TreeCtrl text = text.replace('**( `', '** ( `') + # Replace EmptyString stuff - text = text.replace('EmptyString', "''") + for item in ['wx.EmptyString', 'EmptyString']: + text = text.replace(item, '""') # Replace ArrayXXX stuff... for cpp in ['ArrayString()', 'ArrayInt()', 'ArrayDouble()', 'ArrayString']: diff --git a/sphinxtools/utilities.py b/sphinxtools/utilities.py index 306f5302..3985bdee 100644 --- a/sphinxtools/utilities.py +++ b/sphinxtools/utilities.py @@ -560,6 +560,7 @@ def WriteSphinxOutput(stream, filename, append=False): fid = codecs.open(text_file, mode, encoding='utf-8') if mode == 'w': fid.write('.. include:: headings.inc\n\n') + fid.write(text) fid.close() @@ -761,7 +762,7 @@ def FormatContributedSnippets(kind, contrib_snippets): if kind == 'class': text = TEMPLATE_CONTRIB else: - text = spacer + '\n**Contributed Examples:**\n\n' + text = '\n' + spacer + '**Contributed Examples:**\n\n' for indx, snippet in enumerate(contrib_snippets): fid = open(snippet, 'rt') @@ -771,14 +772,19 @@ def FormatContributedSnippets(kind, contrib_snippets): onlyfile = os.path.split(snippet)[1] text += RAW_1%(spacer, spacer) - text += '\n' + spacer + 'Example %d - %s (:download:`download <_downloads/%s>`)::\n\n'%(indx+1, user, onlyfile) + text += '\n' + spacer + 'Example %d - %s (:download:`download <_downloads/%s>`):\n\n'%(indx+1, user, onlyfile) - for line in lines[1:]: - text += 4*' '+ spacer + line + text += spacer + '.. literalinclude:: %s\n'%snippet + text += spacer + ' :lines: 2-\n\n' - text += '\n' text += RAW_2%(spacer, spacer) + text += '\n\n%s|\n\n'%spacer + + download = os.path.join(SPHINXROOT, '_downloads', onlyfile) + if not os.path.isfile(download): + shutil.copyfile(snippet, download) + return text