]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/wxPIA_book/Chapter-06/example7.py
fixed deadlock when calling wxPostEvent() from worker thread
[wxWidgets.git] / wxPython / samples / wxPIA_book / Chapter-06 / example7.py
CommitLineData
be05b434
RD
1import wx
2import wx.html
3import cPickle
4import os
5from wx.lib import buttons
6
7from example1 import SketchWindow
8
9class SketchFrame(wx.Frame):
10 def __init__(self, parent):
11 self.title = "Sketch Frame"
12 wx.Frame.__init__(self, parent, -1, self.title,
13 size=(800,600))
14 self.filename = ""
15 self.sketch = SketchWindow(self, -1)
16 wx.EVT_MOTION(self.sketch, self.OnSketchMotion)
17 self.initStatusBar()
18 self.createMenuBar()
19 self.createToolBar()
20 self.createPanel()
21
22 def createPanel(self):
23 controlPanel = ControlPanel(self, -1, self.sketch)
24 box = wx.BoxSizer(wx.HORIZONTAL)
25 box.Add(controlPanel, 0, wx.EXPAND)
26 box.Add(self.sketch, 1, wx.EXPAND)
27 self.SetSizer(box)
28
29 def initStatusBar(self):
30 self.statusbar = self.CreateStatusBar()
31 self.statusbar.SetFieldsCount(3)
32 self.statusbar.SetStatusWidths([-1, -2, -3])
33
34 def OnSketchMotion(self, event):
35 self.statusbar.SetStatusText("Pos: %s" %
36 str(event.GetPositionTuple()), 0)
37 self.statusbar.SetStatusText("Current Pts: %s" %
38 len(self.sketch.curLine), 1)
39 self.statusbar.SetStatusText("Line Count: %s" %
40 len(self.sketch.lines), 2)
41 event.Skip()
42
43 def menuData(self):
44 return [("&File", (
45 ("&New", "New Sketch file", self.OnNew),
46 ("&Open", "Open sketch file", self.OnOpen),
47 ("&Save", "Save sketch file", self.OnSave),
48 ("", "", ""),
49 ("&Color", (
50 ("&Black", "", self.OnColor, wx.ITEM_RADIO),
51 ("&Red", "", self.OnColor, wx.ITEM_RADIO),
52 ("&Green", "", self.OnColor, wx.ITEM_RADIO),
53 ("&Blue", "", self.OnColor, wx.ITEM_RADIO),
54 ("&Other...", "", self.OnOtherColor, wx.ITEM_RADIO))),
55 ("", "", ""),
56 ("About...", "Show about window", self.OnAbout),
57 ("&Quit", "Quit", self.OnCloseWindow)))]
58
59 def createMenuBar(self):
60 menuBar = wx.MenuBar()
61 for eachMenuData in self.menuData():
62 menuLabel = eachMenuData[0]
63 menuItems = eachMenuData[1]
64 menuBar.Append(self.createMenu(menuItems), menuLabel)
65 self.SetMenuBar(menuBar)
66
67 def createMenu(self, menuData):
68 menu = wx.Menu()
69 for eachItem in menuData:
70 if len(eachItem) == 2:
71 label = eachItem[0]
72 subMenu = self.createMenu(eachItem[1])
73 menu.AppendMenu(wx.NewId(), label, subMenu)
74 else:
75 self.createMenuItem(menu, *eachItem)
76 return menu
77
78 def createMenuItem(self, menu, label, status, handler, kind=wx.ITEM_NORMAL):
79 if not label:
80 menu.AppendSeparator()
81 return
82 menuItem = menu.Append(-1, label, status, kind)
83 self.Bind(wx.EVT_MENU, handler, menuItem)
84
85 def createToolBar(self):
86 toolbar = self.CreateToolBar()
87 for each in self.toolbarData():
88 self.createSimpleTool(toolbar, *each)
89 toolbar.AddSeparator()
90 for each in self.toolbarColorData():
91 self.createColorTool(toolbar, each)
92 toolbar.Realize()
93
94 def createSimpleTool(self, toolbar, label, filename, help, handler):
95 if not label:
96 toolbar.AddSeparator()
97 return
98 bmp = wx.Image(filename, wx.BITMAP_TYPE_BMP).ConvertToBitmap()
99 tool = toolbar.AddSimpleTool(-1, bmp, label, help)
100 self.Bind(wx.EVT_MENU, handler, tool)
101
102 def toolbarData(self):
103 return (("New", "new.bmp", "Create new sketch", self.OnNew),
104 ("", "", "", ""),
105 ("Open", "open.bmp", "Open existing sketch", self.OnOpen),
106 ("Save", "save.bmp", "Save existing sketch", self.OnSave))
107
108 def createColorTool(self, toolbar, color):
109 bmp = self.MakeBitmap(color)
110 tool = toolbar.AddRadioTool(-1, bmp, shortHelp=color)
111 self.Bind(wx.EVT_MENU, self.OnColor, tool)
112
113 def MakeBitmap(self, color):
114 bmp = wx.EmptyBitmap(16, 15)
115 dc = wx.MemoryDC()
116 dc.SelectObject(bmp)
117 dc.SetBackground(wx.Brush(color))
118 dc.Clear()
119 dc.SelectObject(wx.NullBitmap)
120 return bmp
121
122 def toolbarColorData(self):
123 return ("Black", "Red", "Green", "Blue")
124
125 def OnNew(self, event): pass
126
127 def OnColor(self, event):
128 menubar = self.GetMenuBar()
129 itemId = event.GetId()
130 item = menubar.FindItemById(itemId)
131 if not item:
132 toolbar = self.GetToolBar()
133 item = toolbar.FindById(itemId)
134 color = item.GetShortHelp()
135 else:
136 color = item.GetLabel()
137 self.sketch.SetColor(color)
138
139 def OnCloseWindow(self, event):
140 self.Destroy()
141
142 def SaveFile(self):
143 if self.filename:
144 data = self.sketch.GetLinesData()
145 f = open(self.filename, 'w')
146 cPickle.dump(data, f)
147 f.close()
148
149 def ReadFile(self):
150 if self.filename:
151 try:
152 f = open(self.filename, 'r')
153 data = cPickle.load(f)
154 f.close()
155 self.sketch.SetLinesData(data)
156 except cPickle.UnpicklingError:
157 wx.MessageBox("%s is not a sketch file." % self.filename,
158 "oops!", style=wx.OK|wx.ICON_EXCLAMATION)
159
160 wildcard = "Sketch files (*.sketch)|*.sketch|All files (*.*)|*.*"
161
162 def OnOpen(self, event):
163 dlg = wx.FileDialog(self, "Open sketch file...", os.getcwd(),
164 style=wx.OPEN, wildcard=self.wildcard)
165 if dlg.ShowModal() == wx.ID_OK:
166 self.filename = dlg.GetPath()
167 self.ReadFile()
168 self.SetTitle(self.title + ' -- ' + self.filename)
169 dlg.Destroy()
170
171 def OnSave(self, event):
172 if not self.filename:
173 self.OnSaveAs(event)
174 else:
175 self.SaveFile()
176
177 def OnSaveAs(self, event):
178 dlg = wx.FileDialog(self, "Save sketch as...", os.getcwd(),
179 style=wx.SAVE | wx.OVERWRITE_PROMPT,
180 wildcard = self.wildcard)
181 if dlg.ShowModal() == wx.ID_OK:
182 filename = dlg.GetPath()
183 if not os.path.splitext(filename)[1]:
184 filename = filename + '.sketch'
185 self.filename = filename
186 self.SaveFile()
187 self.SetTitle(self.title + ' -- ' + self.filename)
188 dlg.Destroy()
189
190 def OnOtherColor(self, event):
e1944ad8 191 dlg = wx.ColourDialog(self)
be05b434
RD
192 dlg.GetColourData().SetChooseFull(True)
193 if dlg.ShowModal() == wx.ID_OK:
194 self.sketch.SetColor(dlg.GetColourData().GetColour())
195 dlg.Destroy()
196
197 def OnAbout(self, event):
198 dlg = SketchAbout(self)
199 dlg.ShowModal()
200 dlg.Destroy()
201
202
203class SketchAbout(wx.Dialog):
204 text = '''
205<html>
206<body bgcolor="#ACAA60">
207<center><table bgcolor="#455481" width="100%" cellspacing="0"
208cellpadding="0" border="1">
209<tr>
210 <td align="center"><h1>Sketch!</h1></td>
211</tr>
212</table>
213</center>
214<p><b>Sketch</b> is a demonstration program for <b>wxPython In Action</b>
215Chapter 7. It is based on the SuperDoodle demo included with wxPython,
216available at http://www.wxpython.org/
217</p>
218
219<p><b>SuperDoodle</b> and <b>wxPython</b> are brought to you by
220<b>Robin Dunn</b> and <b>Total Control Software</b>, Copyright
221&copy; 1997-2006.</p>
222</body>
223</html>
224'''
225
226 def __init__(self, parent):
227 wx.Dialog.__init__(self, parent, -1, 'About Sketch',
228 size=(440, 400) )
229
230 html = wx.html.HtmlWindow(self)
231 html.SetPage(self.text)
232 button = wx.Button(self, wx.ID_OK, "Okay")
233
234 sizer = wx.BoxSizer(wx.VERTICAL)
235 sizer.Add(html, 1, wx.EXPAND|wx.ALL, 5)
236 sizer.Add(button, 0, wx.ALIGN_CENTER|wx.ALL, 5)
237
238 self.SetSizer(sizer)
239 self.Layout()
240
241
242
243class ControlPanel(wx.Panel):
244
245 BMP_SIZE = 16
246 BMP_BORDER = 3
247 NUM_COLS = 4
248 SPACING = 4
249
250 colorList = ('Black', 'Yellow', 'Red', 'Green', 'Blue', 'Purple',
251 'Brown', 'Aquamarine', 'Forest Green', 'Light Blue',
252 'Goldenrod', 'Cyan', 'Orange', 'Navy', 'Dark Grey',
253 'Light Grey')
254 maxThickness = 16
255
256 def __init__(self, parent, ID, sketch):
257 wx.Panel.__init__(self, parent, ID, style=wx.RAISED_BORDER)
258 self.sketch = sketch
259 buttonSize = (self.BMP_SIZE + 2 * self.BMP_BORDER,
260 self.BMP_SIZE + 2 * self.BMP_BORDER)
261 colorGrid = self.createColorGrid(parent, buttonSize)
262 thicknessGrid = self.createThicknessGrid(buttonSize)
263 self.layout(colorGrid, thicknessGrid)
264
265 def createColorGrid(self, parent, buttonSize):
266 self.colorMap = {}
267 self.colorButtons = {}
268 colorGrid = wx.GridSizer(cols=self.NUM_COLS, hgap=2, vgap=2)
269 for eachColor in self.colorList:
270 bmp = parent.MakeBitmap(eachColor)
271 b = buttons.GenBitmapToggleButton(self, -1, bmp, size=buttonSize)
272 b.SetBezelWidth(1)
273 b.SetUseFocusIndicator(False)
274 self.Bind(wx.EVT_BUTTON, self.OnSetColour, b)
275 colorGrid.Add(b, 0)
276 self.colorMap[b.GetId()] = eachColor
277 self.colorButtons[eachColor] = b
278 self.colorButtons[self.colorList[0]].SetToggle(True)
279 return colorGrid
280
281 def createThicknessGrid(self, buttonSize):
282 self.thicknessIdMap = {}
283 self.thicknessButtons = {}
284 thicknessGrid = wx.GridSizer(cols=self.NUM_COLS, hgap=2, vgap=2)
285 for x in range(1, self.maxThickness + 1):
286 b = buttons.GenToggleButton(self, -1, str(x), size=buttonSize)
287 b.SetBezelWidth(1)
288 b.SetUseFocusIndicator(False)
289 self.Bind(wx.EVT_BUTTON, self.OnSetThickness, b)
290 thicknessGrid.Add(b, 0)
291 self.thicknessIdMap[b.GetId()] = x
292 self.thicknessButtons[x] = b
293 self.thicknessButtons[1].SetToggle(True)
294 return thicknessGrid
295
296 def layout(self, colorGrid, thicknessGrid):
297 box = wx.BoxSizer(wx.VERTICAL)
298 box.Add(colorGrid, 0, wx.ALL, self.SPACING)
299 box.Add(thicknessGrid, 0, wx.ALL, self.SPACING)
300 self.SetSizer(box)
301 box.Fit(self)
302
303 def OnSetColour(self, event):
304 color = self.colorMap[event.GetId()]
e1944ad8 305 if color != self.sketch.color and self.sketch.color in self.colorButtons:
be05b434
RD
306 self.colorButtons[self.sketch.color].SetToggle(False)
307 self.sketch.SetColor(color)
308
309 def OnSetThickness(self, event):
310 thickness = self.thicknessIdMap[event.GetId()]
311 if thickness != self.sketch.thickness:
312 self.thicknessButtons[self.sketch.thickness].SetToggle(False)
313 self.sketch.SetThickness(thickness)
314
315
316class SketchApp(wx.App):
317
318 def OnInit(self):
319 bmp = wx.Image("splash.png").ConvertToBitmap()
320 wx.SplashScreen(bmp, wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
321 1000, None, -1)
322 wx.Yield()
323
324 frame = SketchFrame(None)
325 frame.Show(True)
326 self.SetTopWindow(frame)
327 return True
328
329if __name__ == '__main__':
330 app = SketchApp(False)
331 app.MainLoop()