You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
(45) |
May
(185) |
Jun
|
Jul
(36) |
Aug
(205) |
Sep
(98) |
Oct
(107) |
Nov
(6) |
Dec
(3) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(1) |
Feb
(2) |
Mar
(19) |
Apr
(26) |
May
(18) |
Jun
|
Jul
(12) |
Aug
(16) |
Sep
(22) |
Oct
(7) |
Nov
(11) |
Dec
(74) |
2006 |
Jan
(14) |
Feb
(1) |
Mar
(3) |
Apr
(3) |
May
(14) |
Jun
(5) |
Jul
(20) |
Aug
(10) |
Sep
(1) |
Oct
|
Nov
(4) |
Dec
(1) |
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(3) |
Jul
(14) |
Aug
|
Sep
|
Oct
(6) |
Nov
(1) |
Dec
|
From: Alex T. <ale...@us...> - 2005-11-03 00:23:00
|
Update of /cvsroot/pythoncard/PythonCard/tools/oneEditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26331 Modified Files: tabcodeEditor.py Log Message: Update the tab text when a file has been modified (like we already do the title bar). Index: tabcodeEditor.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/oneEditor/tabcodeEditor.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** tabcodeEditor.py 24 Oct 2004 23:35:40 -0000 1.11 --- tabcodeEditor.py 3 Nov 2005 00:22:52 -0000 1.12 *************** *** 245,248 **** --- 245,249 ---- def updateTitleBar(self): title = self.title + pageText = self.components.notebook.GetPageText(self.currentPageNumber) if self.currentPage: modified = self.currentDocument.GetModify() *************** *** 251,257 **** if modified and title[0] != '*': self.title = '* ' + title + ' *' elif not modified and title[0] == '*': self.title = title[2:-2] ! # these are event handlers bound above --- 252,261 ---- if modified and title[0] != '*': self.title = '* ' + title + ' *' + self.components.notebook.SetPageText(self.currentPageNumber, '* ' + pageText + ' *') + self.panel.Refresh() elif not modified and title[0] == '*': self.title = title[2:-2] ! self.components.notebook.SetPageText(self.currentPageNumber, pageText[2:-2]) ! self.panel.Refresh() # these are event handlers bound above |
From: Alex T. <ale...@us...> - 2005-11-02 13:25:52
|
Update of /cvsroot/pythoncard/PythonCard/samples/sudoku In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3277 Modified Files: sudoku.py Log Message: Now that helpful.py is in PythonCard, use the pop-up menus fom there, rather than using the local copy. Index: sudoku.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/sudoku/sudoku.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** sudoku.py 29 Sep 2005 22:05:23 -0000 1.1 --- sudoku.py 2 Nov 2005 13:25:35 -0000 1.2 *************** *** 10,14 **** import wx from wx.html import HtmlEasyPrinting ! from PythonCard import configuration, dialog, model import copy --- 10,14 ---- import wx from wx.html import HtmlEasyPrinting ! from PythonCard import configuration, dialog, model, helpful import copy *************** *** 16,75 **** 'i': (200,255,200), 'o': (200,200,255), } ! # copied from helpful.py ! # This function will, I hope, at some point become part of PythonCard ! ! import types ! ! VERSION = "0.1" ! ! class PopUpMenu: ! def __init__(self, aBg, items, pos): ! # Yet another alternate way to do IDs. Some prefer them up top to ! # avoid clutter, some prefer them close to the object of interest ! # for clarity. ! self.popup = {} ! self.reverse = {} ! self.selected = None ! # make a menu ! self.menu = wx.Menu() ! # add the items ! for it in items: ! if type(it) == types.StringType: ! Id = wx.NewId() ! self.popup[it] = Id ! self.reverse[Id] = it ! aBg.Bind(wx.EVT_MENU, self.OnPopup, id=self.popup[it]) ! self.menu.Append(self.popup[it], it) ! else: ! # make a menu ! submenu = wx.Menu() ! Id = wx.NewId() ! aBg.Bind(wx.EVT_MENU, self.OnPopup, id=Id) ! for that in it: ! if type(that) == types.StringType: ! Id = wx.NewId() ! self.popup[that] = Id ! self.reverse[Id] = that ! aBg.Bind(wx.EVT_MENU, self.OnPopup, id=self.popup[that]) ! submenu.Append(self.popup[that], that) ! ! self.menu.AppendMenu(Id, "Test Submenu", submenu) ! ! # Popup the menu. If an item is selected then its handler ! # will be called before PopupMenu returns. ! aBg.PopupMenu(self.menu, pos) ! self.menu.Destroy() ! ! ! def OnPopup(self, event): ! self.selected = self.reverse[event.GetId()] ! ! def popUpMenu(aBg, items, pos): ! menu = PopUpMenu(aBg, items, pos) ! ! return menu.selected ! ! # end of section from helpful.py ! def textToHtml(txt): --- 16,20 ---- 'i': (200,255,200), 'o': (200,200,255), } ! VERSION = "0.2" def textToHtml(txt): *************** *** 641,651 **** if selected == 0: # Popup the menu. ! selected = popUpMenu(self, items, comp.position) ! ###selected = helpful.popUpMenu(self, items, comp.position) if selected: selected = int(selected) else: selected = 0 - #rint "comp, val", comp.name, selected, type(selected) if selected > 0: --- 586,594 ---- if selected == 0: # Popup the menu. ! selected = helpful.popUpMenu(self, items, comp.position) if selected: selected = int(selected) else: selected = 0 if selected > 0: |
From: Alex T. <ale...@us...> - 2005-11-02 12:14:43
|
Update of /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13330 Modified Files: backgroundInfoDialog.py backgroundInfoDialog.rsrc.py Log Message: Added support for custom window styles. Index: backgroundInfoDialog.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules/backgroundInfoDialog.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** backgroundInfoDialog.py 24 Aug 2004 19:01:37 -0000 1.16 --- backgroundInfoDialog.py 2 Nov 2005 12:14:33 -0000 1.17 *************** *** 5,11 **** """ ! from PythonCard import dialog, model, util import os class BackgroundInfoDialog(model.CustomDialog): def __init__(self, aBg, rsrc): --- 5,25 ---- """ ! from PythonCard import dialog, model, util, helpful import os + import wx + + ### map wxWindowStyle constants to nice strings + styleNames = [ ('wx.MINIMIZE_BOX', 'Include Minimize box'), + ('wx.CAPTION', 'Include Caption'), + ('wx.MAXIMIZE_BOX', 'Include Maximize box'), + ('wx.CLOSE_BOX', 'Include Close box'), + ('wx.STAY_ON_TOP', 'Stay on top'), + ('wx.SYSTEM_MENU', 'Include System Menu'), + ('wx.RESIZE_BORDER', 'Include resize border'), + ('wx.FRAME_TOOL_WINDOW', 'Toolbar size frame'), + ('wx.FRAME_SHAPED', 'Frame can be shaped') ] + + class BackgroundInfoDialog(model.CustomDialog): def __init__(self, aBg, rsrc): *************** *** 30,38 **** self.components.chkTiled.checked = rsrc.tiled self.components.chkVisible.checked = rsrc.visible ! self.components.chkResizeable.checked = (rsrc.style != []) ! if rsrc.icon is not None: self.components.fldIcon.text = rsrc.icon def on_btnForegroundColor_mouseClick(self, event): result = dialog.colorDialog(self, color=util.colorFromString(self.components.fldForegroundColor.text)) --- 44,82 ---- self.components.chkTiled.checked = rsrc.tiled self.components.chkVisible.checked = rsrc.visible ! self.components.btnCustomize.visible = False ! self.components.btnCustomize.enabled = False ! if rsrc.style == []: ! self.components.windowStyle.stringSelection = 'Static' ! elif rsrc.style == ['resizeable']: ! self.components.windowStyle.stringSelection = 'Resizeable' ! else: ! self.components.windowStyle.stringSelection = 'Custom' ! self.components.btnCustomize.visible = True ! self.components.btnCustomize.enabled = True ! self.style = rsrc.style ! if rsrc.icon is not None: self.components.fldIcon.text = rsrc.icon + def on_windowStyle_select(self, event): + if self.components.windowStyle.stringSelection <> 'Custom': + self.components.btnCustomize.visible = False + self.components.btnCustomize.enabled = False + return + self.components.btnCustomize.visible = True + self.components.btnCustomize.enabled = True + self.on_btnCustomize_mouseClick(event) + + def on_btnCustomize_mouseClick(self, event): + styleBoxes = [] + for s,text in styleNames: + styleBoxes.append( (s, s in self.style, text) ) + + result = helpful.multiCheckBoxDialog(self, styleBoxes, "Define Custom Window Styles") + if result.accepted: + self.style = [] + for s,val in result.boxes.iteritems(): + if val: self.style.append( s ) + def on_btnForegroundColor_mouseClick(self, event): result = dialog.colorDialog(self, color=util.colorFromString(self.components.fldForegroundColor.text)) *************** *** 78,85 **** result.tiled = dlg.components.chkTiled.checked result.visible = dlg.components.chkVisible.checked ! if dlg.components.chkResizeable.checked: result.style = ['resizeable'] else: ! result.style = [] if dlg.components.fldIcon.text != '': result.icon = dlg.components.fldIcon.text --- 122,131 ---- result.tiled = dlg.components.chkTiled.checked result.visible = dlg.components.chkVisible.checked ! if dlg.components.windowStyle.stringSelection == 'Static': ! result.style = [] ! elif dlg.components.windowStyle.stringSelection == 'Resizeable': result.style = ['resizeable'] else: ! result.style = dlg.style if dlg.components.fldIcon.text != '': result.icon = dlg.components.fldIcon.text Index: backgroundInfoDialog.rsrc.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules/backgroundInfoDialog.rsrc.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** backgroundInfoDialog.rsrc.py 9 Aug 2004 23:04:19 -0000 1.2 --- backgroundInfoDialog.rsrc.py 2 Nov 2005 12:14:33 -0000 1.3 *************** *** 1,7 **** {'type':'CustomDialog', ! 'name':'backgroundInfo', ! 'title':'Background Info', ! 'size':(370, 380), ! 'components': [ {'type':'StaticText', --- 1,25 ---- {'type':'CustomDialog', ! 'name':'backgroundInfo', ! 'title':'Background Info', ! 'position':(53, 94), ! 'size':(370, 563), ! 'components': [ ! ! {'type':'Button', ! 'name':'btnCustomize', ! 'position':(247, 333), ! 'label':'Customize', ! }, ! ! {'type':'RadioGroup', ! 'name':'windowStyle', ! 'position':(76, 279), ! 'size':(281, -1), ! 'items':['Static', 'Resizeable', 'Custom'], ! 'label':'Window Style', ! 'layout':'horizontal', ! 'max':1, ! 'stringSelection':'Static', ! }, {'type':'StaticText', *************** *** 38,42 **** 'name':'stcBackgroundColor', 'position':(10, 135), - #'size':(90, -1), 'text':'Background color:', }, --- 56,59 ---- *************** *** 80,84 **** 'name':'fldForegroundColor', 'position':(130, 110), - 'size':(100, -1), }, --- 97,100 ---- *************** *** 86,90 **** 'name':'btnForegroundColor', 'position':(250, 110), ! 'label':'Color...', }, --- 102,106 ---- 'name':'btnForegroundColor', 'position':(250, 110), ! 'label':'Color...', }, *************** *** 92,96 **** 'name':'fldBackgroundColor', 'position':(130, 135), - 'size':(100, -1), }, --- 108,111 ---- *************** *** 98,102 **** 'name':'btnBackgroundColor', 'position':(250, 135), ! 'label':'Color...', }, --- 113,117 ---- 'name':'btnBackgroundColor', 'position':(250, 135), ! 'label':'Color...', }, *************** *** 104,108 **** 'name':'fldImage', 'position':(130, 160), - 'size':(100, -1), }, --- 119,122 ---- *************** *** 110,114 **** 'name':'btnFile', 'position':(250, 160), ! 'label':'File...', }, --- 124,128 ---- 'name':'btnFile', 'position':(250, 160), ! 'label':'File...', }, *************** *** 117,121 **** 'position':(130, 185), 'size':(135, -1), - 'checked':0, 'label':'Tile image', }, --- 131,134 ---- *************** *** 124,128 **** 'name':'fldIcon', 'position':(130, 210), - 'size':(100, -1), }, --- 137,140 ---- *************** *** 130,134 **** 'name':'btnIconFile', 'position':(250, 210), ! 'label':'File...', }, --- 142,146 ---- 'name':'btnIconFile', 'position':(250, 210), ! 'label':'File...', }, *************** *** 136,140 **** 'name':'chkStatusBar', 'position':(130, 235), - 'checked':0, 'label':'Status bar on window', }, --- 148,151 ---- *************** *** 144,172 **** 'position':(130, 260), 'size':(135, -1), ! 'checked':1, 'label':'Visible at startup', }, - {'type':'CheckBox', - 'name':'chkResizeable', - 'position':(130, 285), - 'size':(135, -1), - 'checked':0, - 'label':'Resizeable', - }, - {'type':'Button', 'name':'btnOK', ! 'position':(10, 320), ! 'label':'OK', ! 'default':1, ! 'id':5100, }, {'type':'Button', 'name':'btnCancel', ! 'position':(115, 320), ! 'label':'Cancel', ! 'id':5101, }, --- 155,175 ---- 'position':(130, 260), 'size':(135, -1), ! 'checked':True, 'label':'Visible at startup', }, {'type':'Button', + 'id':5100, 'name':'btnOK', ! 'position':(9, 405), ! 'default':1, ! 'label':'OK', }, {'type':'Button', + 'id':5101, 'name':'btnCancel', ! 'position':(114, 405), ! 'label':'Cancel', }, |
From: Alex T. <ale...@us...> - 2005-11-02 12:09:00
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11310 Modified Files: model.py Log Message: Support for Window styles other than the two basic ones. Index: model.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/model.py,v retrieving revision 1.193 retrieving revision 1.194 diff -C2 -d -r1.193 -r1.194 *** model.py 18 Sep 2005 03:59:21 -0000 1.193 --- model.py 2 Nov 2005 12:08:52 -0000 1.194 *************** *** 642,648 **** # KEA 2004-01-18 # have to explicitly declare the close box in wxPython 2.5 ! style = wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX ! if aBgRsrc.style == ['resizeable']: style = wx.DEFAULT_FRAME_STYLE # First, call the base class' __init__ method to create the frame wx.Frame.__init__(self, aParent, --- 642,657 ---- # KEA 2004-01-18 # have to explicitly declare the close box in wxPython 2.5 ! if aBgRsrc.style == []: ! style = wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX ! elif aBgRsrc.style == ['resizeable']: style = wx.DEFAULT_FRAME_STYLE + else: + style = 0 + for i in aBgRsrc.style: + try: # intended to catch all errors ! + style |= eval(i) + except: + pass + # First, call the base class' __init__ method to create the frame wx.Frame.__init__(self, aParent, |
From: Alex T. <ale...@us...> - 2005-11-02 11:26:06
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31999 Modified Files: helpful.py Log Message: Oops - remove debugging print stmt. Index: helpful.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/helpful.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** helpful.py 2 Nov 2005 11:16:57 -0000 1.2 --- helpful.py 2 Nov 2005 11:25:56 -0000 1.3 *************** *** 142,146 **** startx, starty = self.components.box.position sx,sy = self.components.box.GetBestSize() ! print starty, len(boxes), sy, (len(boxes)-1) * (sy+20), owy wy = (len(boxes)+1) * (sy+20) + 30 self.size = (owx, wy) --- 142,146 ---- startx, starty = self.components.box.position sx,sy = self.components.box.GetBestSize() ! #rint starty, len(boxes), sy, (len(boxes)-1) * (sy+20), owy wy = (len(boxes)+1) * (sy+20) + 30 self.size = (owx, wy) |
From: Alex T. <ale...@us...> - 2005-11-02 11:17:55
|
Update of /cvsroot/pythoncard/PythonCard/samples/helpfulWrappers In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30560 Modified Files: helpfulWrappers.py Log Message: Added test cases for tooltip support (buttons and checkboxes). Added test case for wide checkbox. Index: helpfulWrappers.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/helpfulWrappers/helpfulWrappers.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** helpfulWrappers.py 2 Nov 2005 01:10:40 -0000 1.1 --- helpfulWrappers.py 2 Nov 2005 11:17:46 -0000 1.2 *************** *** 22,25 **** --- 22,26 ---- 'position':(100,10), 'label':'Test pop-ups!', + 'toolTip':'try this', }, *************** *** 45,49 **** def on_initialize(self, event): ! self.boxes = [ ("already", False), ("later", True), ("a", True), ("b", True), ("c", True), ("d", True), ("a1", True), ("a2", True), ("a3", True) ] pass --- 46,50 ---- def on_initialize(self, event): ! self.boxes = [ ("already", False, 'already has a tooltip'), ("later", True), ("a long string to check sizing", True), "just a string", ("c", True), ("d", True), ("a1", True), ("a2", True), ("a3", True) ] pass *************** *** 63,67 **** result = helpful.multiButtonDialog(self, 'Dad, can I go to the movies tonight', \ ! ['Yes', 'No', 'Maybe', 'Ask me later', 'Ask your mum'], "Movies Dialog Title") print "Dialog result:\naccepted: %s\ntext: %s" % (result.accepted, result.text) --- 64,68 ---- result = helpful.multiButtonDialog(self, 'Dad, can I go to the movies tonight', \ ! ['Yes', 'No', 'Maybe', ('Ask me later', 'procrastination will be better tomorrow'), 'Ask your mum'], "Movies Dialog Title") print "Dialog result:\naccepted: %s\ntext: %s" % (result.accepted, result.text) |
From: Alex T. <ale...@us...> - 2005-11-02 11:17:10
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30257 Modified Files: helpful.py Log Message: Added support for optional tooltips. Made checkboxes wider. Index: helpful.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/helpful.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** helpful.py 2 Nov 2005 00:51:37 -0000 1.1 --- helpful.py 2 Nov 2005 11:16:57 -0000 1.2 *************** *** 49,53 **** bx, by = self.components.Button.size for b in buttons: ! self.components.Button.label = b newx, newy = self.components.Button.GetBestSize() bx = max(bx, newx) --- 49,57 ---- bx, by = self.components.Button.size for b in buttons: ! if type(b) == types.StringType: ! self.components.Button.label = b ! else: ! self.components.Button.label = b[0] ! newx, newy = self.components.Button.GetBestSize() bx = max(bx, newx) *************** *** 68,75 **** count = 0 for b in localbuttons: ! n = copyControl(self, "Button", "Button"+str(count), b) self.components[n.name].position = startx-count*dx, starty self.components[n.name].visible = True self.components[n.name].enabled = True count += 1 self.accepted = False --- 72,86 ---- count = 0 for b in localbuttons: ! if type(b) == types.StringType: ! theName = b ! theToolTip = '' ! else: ! theName = b[0] ! theToolTip = b[1] ! n = copyControl(self, "Button", "Button"+str(count), theName) self.components[n.name].position = startx-count*dx, starty self.components[n.name].visible = True self.components[n.name].enabled = True + self.components[n.name].toolTip = theToolTip count += 1 self.accepted = False *************** *** 120,123 **** --- 131,136 ---- class MultiCheckBoxDialog(model.CustomDialog): + # boxes is a list of (name, value) paris, not a dictionary + # because a dictionary didn't allow th ecaller to control the order of presentatino def __init__(self, parent, boxes, rsrc): model.CustomDialog.__init__(self, parent, rsrc) *************** *** 135,140 **** count = 0 self.boxes = {} ! for key, val in boxes: ! n = copyControl(self, "box", "Box"+str(count), key) self.components[n.name].position = startx, starty+count*(sy+20) --- 148,160 ---- count = 0 self.boxes = {} ! for b in boxes: ! val = False ! toolTip = '' ! if type(b) == types.StringType: ! key = b ! else: ! key = b[0] ! if len(b) > 1: val = b[1] ! if len(b) > 2: toolTip = b[2] n = copyControl(self, "box", "Box"+str(count), key) self.components[n.name].position = startx, starty+count*(sy+20) *************** *** 142,150 **** self.components[n.name].enabled = True self.components[n.name].checked = val self.boxes[key] = val count += 1 self.components.btnOK.position = (150, starty+count*(sy+20)) self.components.btnCancel.position = (250, starty+count*(sy+20)) - starty+count*(sy+20) self.accepted = False --- 162,170 ---- self.components[n.name].enabled = True self.components[n.name].checked = val + self.components[n.name].toolTip = toolTip self.boxes[key] = val count += 1 self.components.btnOK.position = (150, starty+count*(sy+20)) self.components.btnCancel.position = (250, starty+count*(sy+20)) self.accepted = False *************** *** 173,176 **** --- 193,197 ---- 'name':'box', 'position':(50, 15), + 'size':(250,20), 'actionBindings':{}, 'label':'template', |
From: Alex T. <ale...@us...> - 2005-11-02 01:10:50
|
Update of /cvsroot/pythoncard/PythonCard/samples/helpfulWrappers In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25199 Added Files: helpfulWrappers.py readme.txt Log Message: Added a sample program to demo usage of the wrappers in "helpful.py" --- NEW FILE: helpfulWrappers.py --- #!/usr/bin/python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2005/11/02 01:10:40 $" """ # sample to demonstrate usage of the "helpful" wrappers in helpful.py from PythonCard import model, helpful rsrc = {'application':{'type':'Application', 'name':'testmultibuttondialog', 'backgrounds': [ {'type':'Background', 'name':'bgMin', 'title':'Demo of Helpful wrappers', 'size':(300, 100), 'components': [ {'type':'Button', 'name':'popup', 'position':(100,10), 'label':'Test pop-ups!', }, {'type':'Button', 'name':'buttons', 'position':(50,50), 'label':'Test buttons!', }, {'type':'Button', 'name':'boxes', 'position':(150,50), 'label':'Test boxes!', }, ] # end components } # end background ] # end backgrounds } } class MyBackground(model.Background): def on_initialize(self, event): self.boxes = [ ("already", False), ("later", True), ("a", True), ("b", True), ("c", True), ("d", True), ("a1", True), ("a2", True), ("a3", True) ] pass def on_popup_mouseClick(self, event): print self.boxes def on_popup_mouseContextDown(self, event): selected = helpful.popUpMenu(self, ['this', 'set', 'of', 'strings'], self.components.popup.position) if selected: print "Selected item was '"+selected+"'" else: print "Nothing selected." def on_buttons_mouseClick(self, event): result = helpful.multiButtonDialog(self, 'some question', ['OK', 'Not OK', "Cancel"], "Test Dialog Title") print "Dialog result:\naccepted: %s\ntext: %s" % (result.accepted, result.text) result = helpful.multiButtonDialog(self, 'Dad, can I go to the movies tonight', \ ['Yes', 'No', 'Maybe', 'Ask me later', 'Ask your mum'], "Movies Dialog Title") print "Dialog result:\naccepted: %s\ntext: %s" % (result.accepted, result.text) def on_boxes_mouseClick(self, event): boxes = [ ("already", False), ("later", True) ] result = helpful.multiCheckBoxDialog(self, boxes, "Test Boxes Dialog Title") print "Dialog result:\naccepted: %s\n" % (result.accepted), result.boxes result = helpful.multiCheckBoxDialog(self, self.boxes, "Test Boxes Dialog Title") print "Dialog result:\naccepted: %s\n" % (result.accepted), result.boxes self.boxes = result.boxes if __name__ == '__main__': app = model.Application(MyBackground, None, rsrc) app.MainLoop() --- NEW FILE: readme.txt --- helpfulWrappers demonstrates the usage of the wrapper functions in PythonCard/helpful |
From: Alex T. <ale...@us...> - 2005-11-02 01:08:44
|
Update of /cvsroot/pythoncard/PythonCard/samples/helpfulWrappers In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24606/helpfulWrappers Log Message: Directory /cvsroot/pythoncard/PythonCard/samples/helpfulWrappers added to the repository |
From: Alex T. <ale...@us...> - 2005-11-02 00:51:49
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19750 Added Files: helpful.py Log Message: Added a file for helpful wrappers for dialogs, pop-up menus, etc. --- NEW FILE: helpful.py --- """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2005/11/02 00:51:37 $" """ # Assorted helpful wrappers. from PythonCard import model import wx import string, copy from types import * # AGT This could probably be generalized some more - butit handles the current needs # within this wrapper collection of cloning buttons and checkboxes. # utility functions to manipulate controls at run time class copyControl: def __init__(self, aBg, Name, newname, Text=""): Flds = ['position', 'size', 'backgroundColor', 'foregroundColor', 'command', 'font'] aWidget = aBg.components[Name] d = {} d['type'] = aWidget.__class__.__name__ for key in Flds: # attributes # I'm not exactly sure why I have to special-case these tuples if key == 'bitmap': # this should get recreated from the file attribute pass elif key in ['position', 'size']: d[key] = getattr(aWidget, key) elif getattr(aWidget, key) is not None: d[key] = getattr(aWidget, key) if Text == "": Text = newname d['label'] = Text d['name'] = newname aBg.components[newname] = d self.name = newname # dialog to present a block of text and a number of alternative buttons class MultiButtonDialog(model.CustomDialog): def __init__(self, parent, txt, buttons, rsrc): model.CustomDialog.__init__(self, parent, rsrc) self.components.Text.text = txt self.components.Button.visible = False self.components.Button.enabled = False if len(buttons) == 0: buttons = ["OK"] bx, by = self.components.Button.size for b in buttons: self.components.Button.label = b newx, newy = self.components.Button.GetBestSize() bx = max(bx, newx) by = max(by, newy) self.components.Button.size = (bx, newy) dx = bx + 20 # check if all buttons will fit in window owx, owy = self.size startx, starty = self.components.Button.position if len(buttons)*dx + bx + 40 > owx: wx = len(buttons)*dx + bx + 40 self.size = (wx, owy) startx, starty = (wx-bx-20, owy-by-30) # AGT - why 30 ?? tsx, tsy = self.components.Text.size self.components.Text.size = (wx-20, tsy) localbuttons = buttons localbuttons.reverse() count = 0 for b in localbuttons: n = copyControl(self, "Button", "Button"+str(count), b) self.components[n.name].position = startx-count*dx, starty self.components[n.name].visible = True self.components[n.name].enabled = True count += 1 self.accepted = False self.text = "" def on_mouseClick(self, event): self.text = event.target.label if self.text == "Cancel": self.accepted = False else: self.accepted = True self.Close() def multiButtonDialog(parent, txt, buttons, title=""): rsrc = {'type':'CustomDialog', 'name':'Template', 'title':'Template', 'position':(176, 176), 'size':(367, 230), 'components': [ {'type':'StaticText', 'name':'Text', 'position':(10, 10), 'size':(341, 123), 'actionBindings':{}, }, {'type':'Button', 'name':'Button', 'position':(269, 145), 'actionBindings':{}, 'label':'template', }, ] # end components } # end CustomDialog rsrc["title"] = title dlg = MultiButtonDialog(parent, txt, buttons, rsrc) result = dlg.showModal() result.accepted = dlg.accepted result.text = dlg.text dlg.destroy() return result # dialog to present a number of on/off checkboxes class MultiCheckBoxDialog(model.CustomDialog): def __init__(self, parent, boxes, rsrc): model.CustomDialog.__init__(self, parent, rsrc) self.components.box.visible = False self.components.box.enabled = False self.components.box.checked = False # check if all buttons will fit in window owx, owy = self.size startx, starty = self.components.box.position sx,sy = self.components.box.GetBestSize() print starty, len(boxes), sy, (len(boxes)-1) * (sy+20), owy wy = (len(boxes)+1) * (sy+20) + 30 self.size = (owx, wy) count = 0 self.boxes = {} for key, val in boxes: n = copyControl(self, "box", "Box"+str(count), key) self.components[n.name].position = startx, starty+count*(sy+20) self.components[n.name].visible = True self.components[n.name].enabled = True self.components[n.name].checked = val self.boxes[key] = val count += 1 self.components.btnOK.position = (150, starty+count*(sy+20)) self.components.btnCancel.position = (250, starty+count*(sy+20)) starty+count*(sy+20) self.accepted = False def on_btnOK_mouseClick(self, event): self.accepted = True for count in range(len(self.boxes)): name = "Box"+str(count) self.boxes[self.components[name].label] = self.components[name].checked self.Close() def on_btnCancel_mouseClick(self, event): self.accepted = False self.Close() def multiCheckBoxDialog(parent, boxes, title=""): rsrc = {'type':'CustomDialog', 'name':'Template', 'title':'Template', 'position':(176, 176), 'size':(340, 230), 'components': [ {'type':'CheckBox', 'name':'box', 'position':(50, 15), 'actionBindings':{}, 'label':'template', }, {'type':'Button', 'name':'btnOK', 'position':(250, 0), 'actionBindings':{}, 'label':'OK', }, {'type':'Button', 'name':'btnCancel', 'position':(320, 0), 'actionBindings':{}, 'label':'Cancel', }, ] # end components } # end CustomDialog rsrc["title"] = title dlg = MultiCheckBoxDialog(parent, boxes, rsrc) result = dlg.showModal() result.accepted = dlg.accepted result.boxes = dlg.boxes dlg.destroy() return result # wrapper to help with pop up menus import types class PopUpMenu: def __init__(self, aBg, items, pos): # Yet another alternate way to do IDs. Some prefer them up top to # avoid clutter, some prefer them close to the object of interest # for clarity. self.popup = {} self.reverse = {} self.selected = None # make a menu self.menu = wx.Menu() # add the items for it in items: if type(it) == types.StringType: Id = wx.NewId() self.popup[it] = Id self.reverse[Id] = it aBg.Bind(wx.EVT_MENU, self.OnPopup, id=self.popup[it]) self.menu.Append(self.popup[it], it) else: # make a menu submenu = wx.Menu() Id = wx.NewId() aBg.Bind(wx.EVT_MENU, self.OnPopup, id=Id) for that in it: if type(that) == types.StringType: Id = wx.NewId() self.popup[that] = Id self.reverse[Id] = that aBg.Bind(wx.EVT_MENU, self.OnPopup, id=self.popup[that]) submenu.Append(self.popup[that], that) self.menu.AppendMenu(Id, "Test Submenu", submenu) # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. aBg.PopupMenu(self.menu, pos) self.menu.Destroy() def OnPopup(self, event): self.selected = self.reverse[event.GetId()] def popUpMenu(aBg, items, pos): menu = PopUpMenu(aBg, items, pos) return menu.selected |
From: Alex T. <ale...@us...> - 2005-10-27 23:51:25
|
Update of /cvsroot/pythoncard/PythonCard/components In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18022 Modified Files: floatcanvas.py Log Message: wx.lib.FloatCanvas doesn't accept a position parameter, so set the position after the vanvas and widget have been initialized. Index: floatcanvas.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/components/floatcanvas.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** floatcanvas.py 2 Oct 2004 15:49:57 -0000 1.2 --- floatcanvas.py 27 Oct 2005 23:51:14 -0000 1.3 *************** *** 49,52 **** --- 49,53 ---- widget.Widget.__init__( self, aParent, aResource ) + widget.Widget._setPosition(self, aResource.position) # if there are any events to bind this is where we would do it |
From: Alex T. <ale...@us...> - 2005-10-27 22:58:10
|
Update of /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4304/modules Modified Files: multiresourceOutput.py resourceOutput.py Log Message: Added FloatCanvas to the list of components which always need their size written out. Index: multiresourceOutput.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules/multiresourceOutput.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** multiresourceOutput.py 27 Jul 2005 21:51:30 -0000 1.1 --- multiresourceOutput.py 27 Oct 2005 22:58:00 -0000 1.2 *************** *** 50,54 **** if aWidget.__class__.__name__ in imgWidgets: width, height = aWidget._size ! elif aWidget.__class__.__name__ not in ['BitmapCanvas', 'HtmlWindow', 'IEHtmlWindow', 'Gauge', 'StaticBox']: bestWidth, bestHeight = aWidget.GetBestSize() if bestWidth == width: --- 50,54 ---- if aWidget.__class__.__name__ in imgWidgets: width, height = aWidget._size ! elif aWidget.__class__.__name__ not in ['BitmapCanvas', 'HtmlWindow', 'IEHtmlWindow', 'Gauge', 'StaticBox', 'FloatCanvas']: bestWidth, bestHeight = aWidget.GetBestSize() if bestWidth == width: Index: resourceOutput.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules/resourceOutput.py,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** resourceOutput.py 24 Oct 2004 23:52:37 -0000 1.32 --- resourceOutput.py 27 Oct 2005 22:58:00 -0000 1.33 *************** *** 50,54 **** if aWidget.__class__.__name__ in imgWidgets: width, height = aWidget._size ! elif aWidget.__class__.__name__ not in ['BitmapCanvas', 'HtmlWindow', 'IEHtmlWindow', 'Gauge', 'StaticBox']: bestWidth, bestHeight = aWidget.GetBestSize() if bestWidth == width: --- 50,54 ---- if aWidget.__class__.__name__ in imgWidgets: width, height = aWidget._size ! elif aWidget.__class__.__name__ not in ['BitmapCanvas', 'HtmlWindow', 'IEHtmlWindow', 'Gauge', 'StaticBox', 'FloatCanvas']: bestWidth, bestHeight = aWidget.GetBestSize() if bestWidth == width: |
From: Alex T. <ale...@us...> - 2005-10-27 22:54:49
|
Update of /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3840/modules Modified Files: multipropertyEditor.py multipropertyEditor.rsrc.py Log Message: Add option of alphabetizing component list. Index: multipropertyEditor.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules/multipropertyEditor.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** multipropertyEditor.py 1 Aug 2005 11:18:14 -0000 1.4 --- multipropertyEditor.py 27 Oct 2005 22:54:41 -0000 1.5 *************** *** 43,46 **** --- 43,50 ---- self.standardPrefixes = ["txt", "fld", "btn", "chk", "pop", "clr", "fnt"] + self.compOrderControls = ['SendToBack', 'MoveBack', + 'reLayer', 'MoveTogether', + 'MoveForward', 'SendToFront'] + self.multiCompControls = ['stbAlign', 'alignRight', 'alignLeft', 'alignTop', 'alignBottom', *************** *** 204,207 **** --- 208,212 ---- if not self._parent.multipleSelected: return + self.components.alphabetizeComponents.enabled = False ###### multicol ###### lastList = self.components.wComponentList.getStringSelection() *************** *** 773,776 **** --- 778,784 ---- def clearPropertyList(self): self.PropertyListClear() + + def on_alphabetizeComponents_mouseClick(self, event): + self.displayComponents(self._comp) *************** *** 779,794 **** self.components.wComponentList.Clear() if self._parent.multipleSelected: for c in self.multiCompControls: self.components[c].visible = True for c,pref in self._parent.multipleComponents: ! self.addWidgetToComponentList(self._comp[c]) else: for c in self.multiCompControls: self.components[c].visible = False self._comp = components ! for c in components.order: ! #print "display", c, self._parent.isSizingHandle(c) ! if c not in self._parent.sizingHandleNames and not self._parent.isSizingHandle(c): ! self.addWidgetToComponentList(components[c]) self.components.wComponentList.Thaw() self.components.wComponentList.Refresh() --- 787,820 ---- self.components.wComponentList.Clear() if self._parent.multipleSelected: + self.components.alphabetizeComponents.enabled = False for c in self.multiCompControls: self.components[c].visible = True for c,pref in self._parent.multipleComponents: ! self.addWidgetToComponentList(self._comp[c]) ! else: + self.components.alphabetizeComponents.enabled = True for c in self.multiCompControls: self.components[c].visible = False self._comp = components ! #rint "here ", self.components.alphabetizeComponents.checked ! if self.components.alphabetizeComponents.checked: ! for c in self.compOrderControls: ! self.components[c].enabled = False ! xxx = [] ! for c in components.order: ! #print "display", c, self._parent.isSizingHandle(c) ! if c not in self._parent.sizingHandleNames and not self._parent.isSizingHandle(c): ! xxx.append(components[c]) ! xxx.sort() ! for c in xxx: ! self.addWidgetToComponentList(c) ! else: ! for c in self.compOrderControls: ! self.components[c].enabled = True ! for c in components.order: ! #print "display", c, self._parent.isSizingHandle(c) ! if c not in self._parent.sizingHandleNames and not self._parent.isSizingHandle(c): ! self.addWidgetToComponentList(components[c]) self.components.wComponentList.Thaw() self.components.wComponentList.Refresh() Index: multipropertyEditor.rsrc.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/resourceEditor/modules/multipropertyEditor.rsrc.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** multipropertyEditor.rsrc.py 27 Jul 2005 21:47:51 -0000 1.1 --- multipropertyEditor.rsrc.py 27 Oct 2005 22:54:41 -0000 1.2 *************** *** 12,15 **** --- 12,21 ---- {'type':'CheckBox', + 'name':'alphabetizeComponents', + 'position':(5, 231), + 'label':'Alphabetize Components', + }, + + {'type':'CheckBox', 'name':'chkallowNameLabelVariation', 'position':(149, 24), *************** *** 20,24 **** {'type':'ImageButton', 'name':'SendToBack', ! 'position':(8, 244), 'size':(24, 32), 'border':'3d', --- 26,30 ---- {'type':'ImageButton', 'name':'SendToBack', ! 'position':(8, 301), 'size':(24, 32), 'border':'3d', *************** *** 30,34 **** {'type':'ImageButton', 'name':'MoveBack', ! 'position':(32, 244), 'size':(24, 32), 'border':'3d', --- 36,40 ---- {'type':'ImageButton', 'name':'MoveBack', ! 'position':(32, 301), 'size':(24, 32), 'border':'3d', *************** *** 40,44 **** {'type':'ImageButton', 'name':'reLayer', ! 'position':(56, 276), 'size':(32, 32), 'border':'3d', --- 46,50 ---- {'type':'ImageButton', 'name':'reLayer', ! 'position':(56, 333), 'size':(32, 32), 'border':'3d', *************** *** 50,54 **** {'type':'ImageButton', 'name':'MoveTogether', ! 'position':(56, 244), 'size':(32, 32), 'border':'3d', --- 56,60 ---- {'type':'ImageButton', 'name':'MoveTogether', ! 'position':(56, 301), 'size':(32, 32), 'border':'3d', *************** *** 60,64 **** {'type':'ImageButton', 'name':'MoveForward', ! 'position':(88, 244), 'size':(24, 32), 'border':'3d', --- 66,70 ---- {'type':'ImageButton', 'name':'MoveForward', ! 'position':(88, 301), 'size':(24, 32), 'border':'3d', *************** *** 70,74 **** {'type':'ImageButton', 'name':'SendToFront', ! 'position':(112, 244), 'size':(24, 32), 'border':'3d', --- 76,80 ---- {'type':'ImageButton', 'name':'SendToFront', ! 'position':(112, 301), 'size':(24, 32), 'border':'3d', *************** *** 255,260 **** 'position':(356, 135), 'size':(35, -1), ! 'command':'color', ! 'label':'...', }, --- 261,266 ---- 'position':(356, 135), 'size':(35, -1), ! 'command':'color', ! 'label':'...', }, *************** *** 264,268 **** 'size':(35, -1), 'command':'color', ! 'label':'...', }, --- 270,274 ---- 'size':(35, -1), 'command':'color', ! 'label':'...', }, *************** *** 301,305 **** 'name':'fldfont', 'position':(250, 234), - 'size':(100, -1), }, --- 307,310 ---- *************** *** 489,493 **** {'type':'List', 'name':'wComponentList', ! 'position':(5, 20), 'size':(134, 204), 'items':[], --- 494,498 ---- {'type':'List', 'name':'wComponentList', ! 'position':(7, 21), 'size':(134, 204), 'items':[], |
From: Andy T. <an...@us...> - 2005-10-27 12:16:15
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9371 Modified Files: LICENSE.txt Log Message: Added 2005 to the copyright notice Index: LICENSE.txt =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/LICENSE.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** LICENSE.txt 15 Aug 2004 17:34:55 -0000 1.4 --- LICENSE.txt 27 Oct 2005 12:16:02 -0000 1.5 *************** *** 1,3 **** ! Copyright (c) 2001-2004 PythonCard developers All rights reserved. --- 1,3 ---- ! Copyright (c) 2001-2005 PythonCard developers All rights reserved. |
From: Andy T. <an...@us...> - 2005-10-14 11:43:28
|
Update of /cvsroot/pythoncard/PythonCard/samples/dbBrowser In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10256 Modified Files: dbBrowser.rsrc.py Log Message: Made the background resizeable Index: dbBrowser.rsrc.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/dbBrowser/dbBrowser.rsrc.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** dbBrowser.rsrc.py 19 Aug 2004 15:41:40 -0000 1.15 --- dbBrowser.rsrc.py 14 Oct 2005 11:43:20 -0000 1.16 *************** *** 11,15 **** 'statusBar':1, 'icon':'dbBrowser.ico', ! 'menubar': { 'type':'MenuBar', --- 11,15 ---- 'statusBar':1, 'icon':'dbBrowser.ico', ! 'style':['resizeable'], 'menubar': { 'type':'MenuBar', |
From: Alex T. <ale...@us...> - 2005-10-12 22:27:47
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32754 Modified Files: simpleSizer.py Log Message: Add Revision and Date keywords. Index: simpleSizer.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/simpleSizer.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** simpleSizer.py 12 Oct 2005 22:11:49 -0000 1.1 --- simpleSizer.py 12 Oct 2005 22:27:39 -0000 1.2 *************** *** 1,3 **** ! #!/usr/bin/python """ --- 1,6 ---- ! """ ! __version__ = "$Revision$" ! __date__ = "$Date$" ! """ """ |
From: Alex T. <ale...@us...> - 2005-10-12 22:11:57
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27593 Added Files: simpleSizer.py Log Message: Initial version of the simple (positional grid) based sizer. --- NEW FILE: simpleSizer.py --- #!/usr/bin/python """ Simple sizer for PythonCard Uses a simple method for sizing: - each component type is defined to be fixed or stretchable - uses GetBestSize() to get a min size for each component - each component is placed by its centre point as laid out - centre locations are scaled by "current window size / min size" This will adjust component sizes for differences between OS's, but will not move components to make space. """ import wx DEBUG = False DEBUG1 = False #---------------------------------------------------------------------- class simpleSizer(wx.PySizer): def __init__(self, minsize, border=0): wx.PySizer.__init__(self) self.minsize = minsize self.border = border #-------------------------------------------------- def Add(self, item, option=0, flag=0, border=0, pos=None, size=None, growX = False, growY = False ): if DEBUG: print "adding", item.name, pos, size, growX, growY wx.PySizer.Add(self, item, option, flag, border, userData=(pos, size, growX, growY)) #-------------------------------------------------- def CalcMin( self ): x,y = self.minsize return wx.Size(x, y) #-------------------------------------------------- def RecalcSizes( self ): # save current dimensions, etc. curWidth, curHeight = self.GetSize() px, py = self.GetPosition() minWidth, minHeight = self.CalcMin() if DEBUG: print minWidth, minHeight, curWidth, curHeight if minWidth == 0 or minHeight == 0: return scaleX = 100 * curWidth / minWidth scaleY = 100 * curHeight / minHeight # iterate children and set dimensions... for item in self.GetChildren(): pos, size, growX, growY = item.GetUserData() if DEBUG: print "in recalc", pos, size, growX, growY cx,cy = pos sx,sy = size cx = (cx * scaleX + sx*scaleX/2) / 100 cy = (cy * scaleY + sy*scaleY/2) / 100 if growX: sx = sx * scaleX / 100 if growY: sy = sy * scaleY / 100 self.SetItemBounds( item, cx-sx/2, cy-sy/2, sx, sy ) #-------------------------------------------------- def SetItemBounds(self, item, x, y, w, h): # calculate the item's actual size and position within # its grid cell ipt = wx.Point(x, y) isz = wx.Size(w,h) if DEBUG: print "in itembounds", x,y,w,h item.SetDimension(ipt, isz) #-------------------------------------------------- # AGT fill this list heightGrowableTypes = ["BitmapCanvas", "CodeEditor", "HtmlWindow", \ "Image", "List", "MultiColumnList", "Notebook", \ "RadioGroup", "StaticBox", "TextArea", \ "Tree"] widthGrowableTypes = ["BitmapCanvas", "CheckBox", "Choice", \ "CodeEditor", "ComboBox", "HtmlWindow", \ "Image", "List", "MultiColumnList", \ "Notebook", \ "PasswordField", "RadioGroup", "Spinner", \ "StaticBox", "StaticText", "TextArea", \ "TextField", "Tree"] growableTypes = ["Gauge", "Slider", "StaticLine"] def autoSizer(aBg): winX, winY = aBg.size # make list of all components, make a simpleSizer to hold them complist = [] for compName in aBg.components.iterkeys(): comp = aBg.components[compName] complist.append( comp ) sizer = simpleSizer(aBg.panel.size) # add the components to the grid for comp in complist: tx, ty = comp.position dx, dy = comp.size # AGT Must be an easier way to get a component's type ?? compType = comp._resource.__dict__['type'] dx1, dy1 = comp.GetBestSize() if dx1 > dx: dx = dx1 if dy1 > dy: # hack to deal with the fact that GetBestSize() comes up with too # large heights for textareas. if compType <> "TextArea": dy = dy1 # AGT FUTURE this checks contents of the component's userdata # extend resourceEditor to allow a way to set this if "HEIGHT_GROWABLE" in comp.userdata or \ compType in heightGrowableTypes or \ (compType in growableTypes and comp.layout == "vertical"): compGrowableY = True else: compGrowableY = False if "WIDTH_GROWABLE" in comp.userdata or \ compType in widthGrowableTypes or \ (compType in growableTypes and comp.layout == "horizontal"): compGrowableX = True else: compGrowableX = False sizer.Add(comp, pos=(tx,ty), size=(dx,dy), growX = compGrowableX, growY = compGrowableY ) if DEBUG1: print "adding ", comp.name, (tx, ty), (dx, dy), compGrowableX, compGrowableY sizer.SetSizeHints(aBg) aBg.panel.SetSizer(sizer) aBg.panel.SetAutoLayout(1) aBg.panel.Layout() #-------------------------------------------------- |
From: Alex T. <ale...@us...> - 2005-09-29 22:08:46
|
Update of /cvsroot/pythoncard/PythonCard/samples In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31770 Modified Files: samples.rsrc.py Log Message: Added sudoku sample. Index: samples.rsrc.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/samples.rsrc.py,v retrieving revision 1.61 retrieving revision 1.62 diff -C2 -d -r1.61 -r1.62 *** samples.rsrc.py 16 Oct 2004 17:04:11 -0000 1.61 --- samples.rsrc.py 29 Sep 2005 22:08:38 -0000 1.62 *************** *** 64,68 **** 'samples', 'saveClipboardBitmap', 'searchexplorer', \ 'simpleBrowser', 'simpleIEBrowser', 'slideshow', 'sounds', 'SourceForgeTracker', \ ! 'spirograph', 'spirographInteractive', 'stockprice', 'textIndexer', 'textRouter', \ 'tictactoe', 'turtle', 'twistedEchoClient', \ 'webgrabber', 'webserver', 'widgets', 'worldclock'], --- 64,68 ---- 'samples', 'saveClipboardBitmap', 'searchexplorer', \ 'simpleBrowser', 'simpleIEBrowser', 'slideshow', 'sounds', 'SourceForgeTracker', \ ! 'spirograph', 'spirographInteractive', 'stockprice', 'sudoku', 'textIndexer', 'textRouter', \ 'tictactoe', 'turtle', 'twistedEchoClient', \ 'webgrabber', 'webserver', 'widgets', 'worldclock'], |
From: Alex T. <ale...@us...> - 2005-09-29 22:05:30
|
Update of /cvsroot/pythoncard/PythonCard/samples/sudoku In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30655 Added Files: about.txt readme.txt sudoku.py sudoku.rsrc.py Log Message: Add new sample for Suodku Solver. --- NEW FILE: about.txt --- Sudoku Solver 0.1 (c) 2005 Alex Tweedly. --- NEW FILE: sudoku.py --- #!/usr/bin/python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2005/09/29 22:05:23 $" """ import os, sys import wx from wx.html import HtmlEasyPrinting from PythonCard import configuration, dialog, model import copy COLOR = { 'a': (255,200,200), 'f': (255,255,255), 'p': (255,255,255), 'u': (255,255,255), 'z': (255,0,0), 'i': (200,255,200), 'o': (200,200,255), } # copied from helpful.py # This function will, I hope, at some point become part of PythonCard import types VERSION = "0.1" class PopUpMenu: def __init__(self, aBg, items, pos): # Yet another alternate way to do IDs. Some prefer them up top to # avoid clutter, some prefer them close to the object of interest # for clarity. self.popup = {} self.reverse = {} self.selected = None # make a menu self.menu = wx.Menu() # add the items for it in items: if type(it) == types.StringType: Id = wx.NewId() self.popup[it] = Id self.reverse[Id] = it aBg.Bind(wx.EVT_MENU, self.OnPopup, id=self.popup[it]) self.menu.Append(self.popup[it], it) else: # make a menu submenu = wx.Menu() Id = wx.NewId() aBg.Bind(wx.EVT_MENU, self.OnPopup, id=Id) for that in it: if type(that) == types.StringType: Id = wx.NewId() self.popup[that] = Id self.reverse[Id] = that aBg.Bind(wx.EVT_MENU, self.OnPopup, id=self.popup[that]) submenu.Append(self.popup[that], that) self.menu.AppendMenu(Id, "Test Submenu", submenu) # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. aBg.PopupMenu(self.menu, pos) self.menu.Destroy() def OnPopup(self, event): self.selected = self.reverse[event.GetId()] def popUpMenu(aBg, items, pos): menu = PopUpMenu(aBg, items, pos) return menu.selected # end of section from helpful.py def textToHtml(txt): # the wxHTML classes don't require valid HTML # so this is enough html = txt.replace('\n\n', '<P>') html = html.replace('\n', '<BR>') return html class square: def __init__(self, x,y, comp): self.x = x self.y = y self.comp = comp self.state = None self.values = [1,2,3,4,5,6,7,8,9] self.color = (255,255,255) class undosquare: def __init__(self, val, state): self.state = state self.values = val class MyBackground(model.Background): def on_initialize(self, event): # if you have any initialization # including sizer setup, do it here self.readme = None self.hideUndecided = False self.hideChoices = False self.squares = {} for i in range(9): for j in range(9): self.squares[i,j] = square(i,j, self.components["B%d%d" % (i,j)]) self.peer = {} for i in range(3): for j in range(3): self.peer[3*i+j] = [] for x in range(3): for y in range(3): self.peer[3*i+j].append( (3*i+x, 3*j+y) ) self.sizerLayout() self.startTitle = self.title self.newFile() self.components.solveIt.SetFocus() def sizerLayout(self): # Need this nonsense because we are using list components in an unusual way # We want them to be entirely visible - and Mac OSX doesn't record an adequate # minimum size (GetBestSize()) for list controls if wx.Platform == '__WXMSW__': minListSize = (45,44) elif wx.Platform <> '__WXMAC__': minListSize = (66,66) else: minListSize = (66,66) for i in range(9): for j in range(9): self.components["B%d%d" % (i,j)].SetMinSize( minListSize ) sizer1 = wx.BoxSizer(wx.VERTICAL) sizer2 = wx.BoxSizer(wx.HORIZONTAL) ## There is no sizer 3 !! sizer4 = wx.GridSizer(9, 9, 2, 2) sizer5 = wx.BoxSizer(wx.HORIZONTAL) stcSizerAttrs = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL fldSizerAttrs = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL vertFlags = wx.LEFT | wx.TOP | wx.ALIGN_LEFT chkSizerAttrs = wx.RIGHT | wx.ALIGN_CENTER_VERTICAL C = self.components sizer2.Add(C.solveIt, flag=fldSizerAttrs) sizer2.Add((5, 5), 0) sizer2.Add(C.Singles, flag=fldSizerAttrs) sizer2.Add((5, 5), 0) sizer2.Add(C.Soles, flag=fldSizerAttrs) sizer2.Add((45, 5), 0) sizer2.Add(C.Blank, flag=fldSizerAttrs) sizer2.Add((25, 5), 0) sizer2.Add(C.Undo, flag=fldSizerAttrs) sizer2.Add((5, 5), 0) sizer2.Add(C.Redo, flag=fldSizerAttrs) for i in range(9): for j in range(9): sizer4.Add(C["B"+str(i)+str(j)]) sizer5.Add(C.hideUndecided, flag=fldSizerAttrs) sizer5.Add((5, 5), 0) sizer5.Add(C.hideChoices, flag=fldSizerAttrs) sizer1.Add(sizer2, 0, vertFlags) sizer1.Add((5, 15), 0) # spacer sizer1.Add(sizer4, 0, vertFlags) sizer1.Add((5, 15), 0) # spacer sizer1.Add(sizer5, 0, vertFlags) sizer1.Fit(self) sizer1.SetSizeHints(self) self.panel.SetSizer(sizer1) self.panel.SetAutoLayout(1) self.panel.Layout() self.visible = True def reset(self): for i in range(9): for j in range(9): self.squares[i,j].values = [1,2,3,4,5,6,7,8,9] self.squares[i,j].color = (255,255,255) self.squares[i,j].state = 'u' self.undo = [] self.redo = [] def loadConfig(self): pass def saveConfig(self): pass def saveChanges(self): # save configuration info in the app directory #filename = os.path.basename(self.documentPath) if self.documentPath is None: filename = "Untitled" else: filename = self.documentPath msg = "The text in the %s file has changed.\n\nDo you want to save the changes?" % filename result = dialog.messageDialog(self, msg, 'textEditor', wx.ICON_EXCLAMATION | wx.YES_NO | wx.CANCEL) return result.returnedString def doExit(self): return 1 def on_close(self, event): if self.doExit(): # self.saveConfig() self.fileHistory = None self.printer = None event.skip() def on_menuFileSave_select(self, event): if self.documentPath is None: # this a "new" document and needs to go through Save As... self.on_menuFileSaveAs_select(None) else: self.saveFile(self.documentPath) def on_menuFileSaveAs_select(self, event): wildcard = "Text files (*.txt)|*.TXT;*.txt|All files (*.*)|*.*" if self.documentPath is None: dir = '' filename = '*.txt' else: dir = os.path.dirname(self.documentPath) filename = os.path.basename(self.documentPath) result = dialog.saveFileDialog(None, "Save As", dir, filename, wildcard) if result.accepted: path = result.paths[0] self.saveFile(path) return True else: return False def newFile(self): self.documentPath = None self.documentChanged = 0 self.title = 'Untitled - ' + self.startTitle self.statusBar.text = 'Untitled' self.reset() for i in range(9): for j in range(9): self.updateList(self.squares[i,j]) def setUpPuzzle(self, definition): self.reset() y = 0 for line in definition: if line.strip() == "": continue if y == 9: # must be the optional title self.title = line self.statusBar.text = line break x = 0 for c in line.strip(): sqr = self.squares[x,y] if c == " ": continue if c == "x": sqr.state = 'u' else: sqr.state = 'p' sqr.values = [int(c),] self.updateList(sqr) x += 1 y += 1 def on_builtInPuzzle_command(self, event): self.documentPath = None self.documentChanged = 0 self.title = 'Untitled - ' + self.startTitle self.statusBar.text = 'Untitled' tname = event.target.name.replace("menuFilePuzzle", "P") self.setUpPuzzle(self.components[tname].userdata.split("\n")) def openFile(self, path): # change the code below for # opening an existing document # the commented lines are from the textEditor tool # may be overridden if file includesthe optinoal title on last line self.title = os.path.split(path)[-1] + ' - ' + self.startTitle f = open(path) self.setUpPuzzle(f) f.close() self.documentPath = path self.documentChanged = 0 self.statusBar.text = path def saveFile(self, path): # change the code below for # saving an existing document f = open(path, 'w') for y in range(9): s = [] for x in range(9): tList = self.squares[x,y].values if len(tList) == 1: s.append(str(tList[0])) else: s.append('x') if x == 2 or x == 5: s.append(' ') s.append("\n") f.write(''.join(s)) if y == 2 or y == 5: f.write("\n") f.close() self.documentPath = path self.documentChanged = False self.title = os.path.split(path)[-1] + ' - ' + self.startTitle self.statusBar.text = path def on_menuFileNew_select(self, event): if self.documentChanged: save = self.saveChanges() if save == "Cancel": # don't do anything, just go back to editing pass elif save == "No": # any changes will be lost self.newFile() else: if self.documentPath is None: if self.on_menuFileSaveAs_select(None): self.newFile() else: self.saveFile(self.documentPath) self.newFile() else: # don't need to save self.newFile() def on_menuFileOpen_select(self, event): # split this method into several pieces to make it more flexible wildcard = "Text files (*.txt)|*.txt;*.TXT|All files (*.*)|*.*" result = dialog.openFileDialog(wildcard=wildcard) if result.accepted: path = result.paths[0] # an error will probably occur here if the text is too large # to fit in the wxTextCtrl (TextArea) or the file is actually # binary. Not sure what happens with CR/LF versus CR versus LF # line endings either self.openFile(path) def on_menuFilePrint_select(self, event): # put your code here for print # the commented code below is from the textEditor tool # and is simply an example #source = textToHtml(self.components.fldDocument.text) #self.printer.PrintText(source) pass def on_menuFilePrintPreview_select(self, event): # put your code here for print preview # the commented code below is from the textEditor tool # and is simply an example #source = textToHtml(self.components.fldDocument.text) #self.printer.PreviewText(source) pass def on_menuFilePageSetup_select(self, event): self.printer.PageSetup() def saveUndoPosition(self): st = {} for i in range(9): for j in range(9): sqr = self.squares[i,j] st[i,j] = undosquare(copy.copy(sqr.values), sqr.state) self.undo.append(st) self.redo = [] def on_Blank_mouseClick(self, event): self.on_menuFileNew_select(event) def on_Undo_command(self, event): # if we are at the end - i.e. no redo info yet, then we should take a snapshot # right now so that we can get back to this point if len(self.redo) == 0: self.saveUndoPosition() st = self.undo[-1] self.redo.append(st) del self.undo[-1] ## print "undo", len(self.undo), len(self.redo) if len(self.undo) == 0: result = dialog.alertDialog(self, 'No more to Undo', 'Undo Alert') return st = self.undo[-1] ## for k,v in self.undo[-1].iteritems(): ## print k, v.state, v.values for i in range(9): for j in range(9): sqr = self.squares[i,j] sqr.values = copy.copy(st[i,j].values) sqr.state = st[i,j].state self.updateList(sqr) self.redo.append(st) del self.undo[-1] t = self.count() self.statusBar.text = "Possible choices left %d" % t ## print "undo", len(self.undo), len(self.redo) def on_Redo_command(self, event): ## print "redo", len(self.undo), len(self.redo) if len(self.redo) == 0: result = dialog.alertDialog(self, 'No more to Redo', 'Redo Alert') return st = self.redo[-1] for i in range(9): for j in range(9): sqr = self.squares[i,j] sqr.values = copy.copy(st[i,j].values) sqr.state = st[i,j].state self.updateList(sqr) self.undo.append(st) del self.redo[-1] t = self.count() self.statusBar.text = "Possible choices left %d" % t ## print "redo", len(self.undo), len(self.redo) def on_hideUndecided_mouseClick(self, event): self.hideUndecided = self.components.hideUndecided.checked for i in range(9): for j in range(9): self.updateList(self.squares[i,j]) def on_hideChoices_mouseClick(self, event): self.hideChoices = self.components.hideChoices.checked def on_doHelpAbout_command(self, event): dialog.messageDialog(self, "Sudoku Solver" + "\n\n" + \ "Version %s" % VERSION + "\n\n" + \ "(c) 2005 Alex Tweedly", "About Sudoku Solver", wx.ICON_INFORMATION | wx.OK) pass def on_doHelpHelp_command(self, event): if not self.readme: self.readme = open('readme.txt').read() dialog.scrolledMessageDialog(self, self.readme, 'Help') pass def singles(self): self.saveUndoPosition() for i in range(9): for j in range(9): sqr = self.squares[i,j] if len(sqr.values) == 1 and (sqr.state == 'p' or sqr.state == 'a' or sqr.state == 'f'): sqr.state = 'i' self.fillin(sqr, i,j) wx.SafeYield(self) def soles(self): self.saveUndoPosition() for i in range(9): # check the col used = {1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0} last = {1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0} for j in range(9): sqr = self.squares[i,j] for c in sqr.values: used[c] += 1 last[c] = j for c,val in used.iteritems(): if val == 1: ss = self.squares[i, last[c]] if len(ss.values) <> 1: ss.values = [c,] ss.state = 'o' #rint "col", i, last[c], c self.fillin(ss,i,last[c]) # check the row used = {1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0} last = {1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0} for j in range(9): sqr = self.squares[j,i] for c in sqr.values: used[c] += 1 last[c] = j for c,val in used.iteritems(): if val == 1: ss = self.squares[last[c], i] if len(ss.values) <> 1: ss.values = [c,] ss.state = 'o' #rint "row", last[c], i, c self.fillin(ss,last[c],i) # check the square used = {1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0} last = {1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0} for j in range(9): sqr = self.squares[self.peer[i][j]] #rint i,j,self.peer[i][j] for c in sqr.values: used[c] += 1 last[c] = self.peer[i][j] for c,val in used.iteritems(): if val == 1: x,y = last[c] ss = self.squares[x,y] #rint i,c,val,ss.values if len(ss.values) <> 1: ss.values = [c,] ss.state = 'o' #rint "3x3", x, y, c self.fillin(ss,x,y) def fillin(self, sqr, i, j): if len(sqr.values) <> 1: print "help - bad values list", i,j, ss value = sqr.values[0] for d in range(9): if d == j: continue ss = self.squares[i,d] if value in ss.values: self.delValue(ss, value) ss.state = 'f' self.updateList(ss) #if len(ss.values) == 1: self.fillin(ss,i,d) for d in range(9): if d == i: continue ss = self.squares[d,j] if value in ss.values: self.delValue(ss, value) #if len(ss.values) == 1: self.fillin(ss,d,j) for d,e in self.peer[3*(i/3) + j/3]: if d == i and e == j: continue ss = self.squares[d,e] if value in ss.values: self.delValue(ss, value) ss.state = 'f' #if len(ss.values) == 1: self.fillin(ss,d,e) self.updateList(sqr) t = self.count() self.statusBar.text = "Possible choices left %d" % t def count(self): t = 1 for i in range(9): for j in range(9): t *= len(self.squares[i,j].values) if t == 0: return 0 return t def on_Singles_mouseClick(self, event): self.singles() def on_Soles_mouseClick(self, event): self.soles() def on_solveIt_mouseClick(self, event): last = -1 t = self.count() while last <> t and t > 1: last = t self.singles() t = self.count() if t == last: self.soles() t = self.count() def updateList(self, sqr): if len(sqr.values) == 0: items = [" ", " ", " "] sqr.state = 'z' elif len(sqr.values) == 1: items = [" ", " "+str(sqr.values[0])+" ", " "] else: s = [] for c in xrange(1,10): if c in sqr.values: s.append(str(c)) else: s.append(" ") all = " ".join(s) items = [all[:5], all[6:11], all[12:]] if self.hideUndecided and (sqr.state == 'u' or sqr.state == 'f'): items = [' ', ' ', ' '] sqr.comp.items = items sqr.comp.backgroundColor = COLOR[sqr.state] def delValue(self, sqr, value): if value in sqr.values: del sqr.values[sqr.values.index(value)] self.updateList(sqr) def on_popup_command(self, event): comp = event.target selected = 0 x = int(comp.name[1]) y = int(comp.name[2]) sqr = self.squares[x,y] if len(sqr.values) == 1: if self.hideChoices and (sqr.state == 'u' or sqr.state == 'f'): items = ['1','2','3','4','5','6','7','8','9'] else: selected = sqr.values[0] else: # make a menu self.menu = wx.Menu() # add the items items = [] if self.hideChoices: items = ['1','2','3','4','5','6','7','8','9'] else: for c in sqr.values: items.append(str(c)) if selected == 0: # Popup the menu. selected = popUpMenu(self, items, comp.position) ###selected = helpful.popUpMenu(self, items, comp.position) if selected: selected = int(selected) else: selected = 0 #rint "comp, val", comp.name, selected, type(selected) if selected > 0: self.saveUndoPosition() sqr.values = [selected,] sqr.state = 'a' self.updateList(sqr) comp.backgroundColor = (200,100,100) self.fillin(sqr, int(comp.name[1]), int(comp.name[2])) if __name__ == '__main__': app = model.Application(MyBackground) app.MainLoop() --- NEW FILE: sudoku.rsrc.py --- {'application':{'type':'Application', 'name':'Template', 'backgrounds': [ {'type':'Background', 'name':'Sudoku', 'title':'Standard Template with full menus', 'size':(565, 647), 'statusBar':1, 'style':['resizeable'], 'menubar': {'type':'MenuBar', 'menus': [ {'type':'Menu', 'name':'menuFile', 'label':'&File', 'items': [ {'type':'MenuItem', 'name':'menuFileNew', 'label':'&New\tCtrl+N', }, {'type':'MenuItem', 'name':'menuFileOpen', 'label':'&Open\tCtrl+O', }, {'type':'MenuItem', 'name':'menuFileSave', 'label':'&Save\tCtrl+S', 'enabled':0, }, {'type':'MenuItem', 'name':'menuFileSaveAs', 'label':'Save &As...', 'command':'saveas', }, {'type':'MenuItem', 'name':'fileSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuFilePuzzle1', 'label':'Puzzle1\tCtrl+1', 'command':'builtInPuzzle', }, {'type':'MenuItem', 'name':'menuFilePuzzle2', 'label':'Puzzle2\tCtrl+2', 'command':'builtInPuzzle', }, {'type':'MenuItem', 'name':'menuFilePuzzle3', 'label':'Puzzle3\tCtrl+3', 'command':'builtInPuzzle', }, {'type':'MenuItem', 'name':'menuFilePuzzle4', 'label':'Puzzle4\tCtrl+4', 'command':'builtInPuzzle', }, {'type':'MenuItem', 'name':'fileSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuFilePageSetup', 'label':'Page Set&up...', }, {'type':'MenuItem', 'name':'menuFilePrint', 'label':'&Print...\tCtrl+P', }, {'type':'MenuItem', 'name':'menuFilePrintPreview', 'label':'Print Pre&view', }, {'type':'MenuItem', 'name':'fileSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuFileExit', 'label':'E&xit\tAlt+X', 'command':'exit', }, ] }, {'type':'Menu', 'name':'Edit', 'label':'&Edit', 'items': [ {'type':'MenuItem', 'name':'menuEditUndo', 'label':'&Undo\tCtrl+Z', 'command':'Undo', }, {'type':'MenuItem', 'name':'menuEditRedo', 'label':'&Redo\tCtrl+Y', 'command':'Redo', }, {'type':'MenuItem', 'name':'editSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditMode', 'label':'&Mode and Preferences\tCtrl+M', 'command':'doMode', }, ] }, {'type':'Menu', 'name':'menuHelp', 'label':'&Help', 'items': [ {'type':'MenuItem', 'name':'menuHelpHelp', 'label':'&Help', 'command':'doHelpHelp', }, {'type':'MenuItem', 'name':'menuHelpAbout', 'label':'&About ...', 'command':'doHelpAbout', }, ] }, ] }, 'components': [ {'type':'ToggleButton', 'name':'hideChoices', 'position':(347, 540), 'size':(85, -1), 'label':'Hide Choices', }, {'type':'ToggleButton', 'name':'hideUndecided', 'position':(49, 540), 'label':'Hide Undecided', }, {'type':'Button', 'name':'Redo', 'position':(223, 65), 'size':(60, -1), 'command':'Redo', 'label':'Redo', }, {'type':'Button', 'name':'Undo', 'position':(135, 65), 'size':(60, -1), 'command':'Undo', 'label':'Undo', }, {'type':'Button', 'name':'Blank', 'position':(48, 65), 'size':(60, -1), 'label':'Blank', }, {'type':'Button', 'name':'P4', 'position':(526, 99), 'size':(20, -1), 'enabled':False, 'label':'P4', 'userdata':'42x xxx x1x\nxxx 54x x3x\nxx6 xx7 xxx\n\nxxx xxx 279\nx1x xxx x6x\n342 xxx xxx\n\nxxx 9xx 3xx\nx6x x38 xxx\nx8x xxx x57\nNine-by-Nine Puzzle 3\n', 'visible':False, }, {'type':'Button', 'name':'P3', 'position':(523, 65), 'size':(20, -1), 'enabled':False, 'label':'P3', 'userdata':'9x4 xxx 3x1\nx1x xxx xx9\nxx2 xxx 68x\n\nx5x xxx xxx\nx93 1x5 4x6\nxx7 x24 8xx\n\n34x 79x xx8\n8xx 3x1 94x\n6xx xx8 21x\n\nNine-by-Nine Puzzle 3\n', 'visible':False, }, {'type':'Button', 'name':'P2', 'position':(524, 30), 'size':(20, -1), 'enabled':False, 'label':'P2', 'userdata':'52x xxx xx4\nxxx xxx 5xx\nxx7 6xx xxx\n\nx15 x6x xxx\n4xx 8x3 x6x\nxxx xx2 9x5\n\nxx1 xxx 8xx\nxxx xx1 x42\n674 9xx xx3\n\nNine-by-Nine Puzzle 2', 'visible':False, }, {'type':'Button', 'name':'P1', 'position':(524, 2), 'size':(20, -1), 'enabled':False, 'label':'P1', 'userdata':'98x 354 xxx\n41x xx2 8xx\nx32 x1x 7xx\n\n29x 1x5 xxx\nxxx x6x xxx\n643 xx7 21x\n\nxxx 8xx x2x\nx5x x2x 6x7\nxxx x3x x9x\nNine-by-Nine Puzzle 1\n ', 'visible':False, }, {'type':'Button', 'name':'Soles', 'position':(235, 20), 'size':(53, -1), 'label':'Soles', }, {'type':'Button', 'name':'Singles', 'position':(128, 20), 'size':(53, -1), 'label':'Singles', }, {'type':'Button', 'name':'solveIt', 'position':(26, 20), 'size':(53, -1), 'label':'Solve It !', }, {'type':'List', 'name':'B00', 'position':(50, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'stringSelection':'3', 'userdata':'123456789', }, {'type':'List', 'name':'B01', 'position':(50, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B02', 'position':(50, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B03', 'position':(50, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B04', 'position':(50, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B05', 'position':(50, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B06', 'position':(50, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B07', 'position':(50, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B08', 'position':(50, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B10', 'position':(95, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'stringSelection':'2', 'userdata':'123456789', }, {'type':'List', 'name':'B11', 'position':(95, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B12', 'position':(95, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B13', 'position':(95, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B14', 'position':(95, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B15', 'position':(95, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B16', 'position':(95, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B17', 'position':(95, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B18', 'position':(95, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B20', 'position':(140, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B21', 'position':(140, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B22', 'position':(140, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B23', 'position':(140, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B24', 'position':(140, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B25', 'position':(140, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B26', 'position':(140, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B27', 'position':(140, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B28', 'position':(140, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B30', 'position':(191, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B31', 'position':(191, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B32', 'position':(191, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B33', 'position':(191, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B34', 'position':(191, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B35', 'position':(191, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B36', 'position':(191, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B37', 'position':(191, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B38', 'position':(191, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B40', 'position':(236, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B41', 'position':(236, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B42', 'position':(236, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B43', 'position':(236, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B44', 'position':(236, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B45', 'position':(236, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B46', 'position':(236, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B47', 'position':(236, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B48', 'position':(236, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B50', 'position':(281, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B51', 'position':(281, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B52', 'position':(281, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B53', 'position':(281, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B54', 'position':(281, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B55', 'position':(281, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B56', 'position':(281, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B57', 'position':(281, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B58', 'position':(281, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B60', 'position':(332, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B61', 'position':(332, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B62', 'position':(332, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B63', 'position':(332, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B64', 'position':(332, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B65', 'position':(332, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B66', 'position':(332, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B67', 'position':(332, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B68', 'position':(332, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B70', 'position':(377, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B71', 'position':(377, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B72', 'position':(377, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B73', 'position':(377, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B74', 'position':(377, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B75', 'position':(377, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B76', 'position':(377, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B77', 'position':(377, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B78', 'position':(377, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B80', 'position':(422, 100), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B81', 'position':(422, 145), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B82', 'position':(422, 190), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B83', 'position':(422, 241), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B84', 'position':(422, 286), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B85', 'position':(422, 331), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B86', 'position':(422, 382), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B87', 'position':(422, 427), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, {'type':'List', 'name':'B88', 'position':(422, 472), 'size':(66, 66), 'command':'popup', 'items':['1', '2', '3'], 'userdata':'123456789', }, ] # end components } # end background ] # end backgrounds } } --- NEW FILE: readme.txt --- Sudoku Solver can solve, or help you solve, Sudoku puzzles. The rules of Sudoku are very simple: - each digit 1-9 must appear exactly once in each row, column or 3x3 square Solving a puzzle. ================= The basic step to solve a puzzle is to select a value for a square. If you click in a square which has only one possible value available, that square will be coloured in, and that value is removed from all the other squares in the same row, column and 3x3 square (because it has now been assigned to the square you clicked in, it cannot be also put in the other squares in the same row, column and 3x3 square). If there are still multiple values possible for the square you click in, you will be presented with a pop-up menu of the possible values. Selecting any one of these will assign that value to the square (as above). Of course, you can also choose to not select on of the values, but releasing the mouse button while outside the pop-up menu. When you assign a value like this, the "mechanical" work of removing that value from the row, column and 3x3 square is done for you. Note that the status bar at the bottom of the window will show the number of possible combinations left: this will decrease as the solution progresses, and should eventually reach 1. There are three buttons which further automate the solving of a puzzle. Two of these (Singles and Soles) implement the two basic solution strategies, while the third (Solve it) simply applies the two strategies in turn until it succeeds (or goes as far as it can). Singles. -------- Any square for which there is only a single remaining value allowed is called a "single". Obviously, the initial values assigned as part of the puzzle definition are one example of this. The "single" value can be assigned to that square, and then that digit can be eliminate from the other squares in the same row, the same column and the same 3x3 square. This elimination of values may generate additional "singles" - they are not immediately taken, but clicking the button again will do them. Soles. ------ There may be only one square in a row which can still contain one of the digits, and this will be called the "sole" place that digit can go. Note this square may not be a "single" - it may have any number of still-valid possibilities, but if a particular digit can only be in the one place in that row, then it can be assigned as the "sole" place for it to go. Obviously, this can be applied to columns, and to 3x3 squares as well. Solve It -------- As we said above, this simply applies each of the two methods (Singles and Soles) above in turn, until neither produces any progress. There are three further buttons for use in solving puzzles. Blank ----- This produces a new, blank puzzle (i.e. equivalent to selecting File / New from the menu). Undo and Redo ---- ---- These are fairly self-explanatory - each click will undo (or redo) one step of the solution so far. Simple, Moderate and Complex Puzzles. ==================================== The four built-in puzzles are in order of simple to more difficult. You will find that many puzzles, like the first three here, can be solved simply by applying the strategies described above (either by clicking the buttons, or more satisfyingly by working through the puzzle one square at a time). However, some puzzles, such as the fourth built-in example, will not be fully resolved by using these techniques. While there are other analytical methods possible, the usual method to tackle these is simply to "postulate" (i.e. guess !!) one of the remaining values and see whether that leads to a solution or not. Well constructed Sudoku puzzles should have only a single solution, so this method will work. The easiest way to use this Sudoku Solver to do this is to simply choose the top, left square which still has multiple values possible, and do a trial assignment of the first value to it. Then click on "Solve it", and see what happens. If this value-assignment is incorrect, it will usually lead to some square(s) having no possible values left, and it (they) will be coloured bright red, so will be easy to spot. You can then click "Undo" multiple times, until you reach the point at which you made the guess. Then try the next possible value, and again click "Solve it". If the assignment is correct, then clicking "Solve it" will usually lead to a complete solution. Occasionally, the first guessed value will lead to neither a complete solution nor a complete conflict. In this case, you may need to move on to the next square which is not yet decided, and make a guess there. But do make sure that you remember to click on "Solve it" (or that you do the equivalent effort yourself) or you risk the possibility of not detecting the complete conflict or solution. (I have not actually found a puzzle that requires this multi-step postulation, but it's theoretically possible - if you do find one, please send it to me.) Defining or selecting a puzzle. =============================== A puzzle definition sets the initial values for some of the squares assignments. There are four puzzles built-in, and you can add as many new puzzles as you like. The quickest way to create a new puzzle is to edit a text definition file, and the solve that puzzle by selecting File / Open from the menu. The format for these files is simple; each row of the puzzle is a line in the file, each character is a single square, containing either a digit or 'x'. Extra spaces or blank lines are ignored. So the file to define the first built-in puzzle could look like: 98x 354 xxx 41x xx2 8xx x32 x1x 7xx 29x 1x5 xxx xxx x6x xxx 643 xx7 21x xxx 8xx x2x x5x x2x 6x7 xxx x3x x9x You can also create a puzzle by starting with a blank puzzle (i.e. immediately after starting the program, or by clicking the "Blank" button), then specifying values for your initial squares (by clicking in a square, then selecting the value from the pop-up menu), and finally selecting menu File / Save as ... and storing the puzzle definition in a file. You could also add more 'built-in' puzzles using the resource editor, by adding invisible buttons (similar to P1, P2, P3 P4) and adding menu entries (similar to File / Puzzle1 (the actual puzzle definition goes in the "userdata" of the invisible buttons). You can save a puzzle at any time, using the File / Save As .... menu selection. This will save the puzzle in the format described above, i.e. the only info saved is which squares have a single possible value assigned. All other squares will be simply marked as 'unknown' so if you later re-open this puzzle, you will be in an equivalent position, but will not see exactly the possibilities as you had seen before saving the puzzle state. The File / Save menu item is currently disabled, because it rarely, if ever, makes sense to save the current state so as to overwrite the state in the file. Further options =============== The two buttons at the bottom of the window give you further options on how much help you are given. Toggling both of these will let you solve the puzzle with no help at all - equivalent to solving it on paper, but without any easy way to mark-up your partial solutions or ideas. Hide Undecided -------------- Normally, any square for which there are multiple values still possible will show all of those choices (and only those choices). [Remember that until you have assigned a value to a square (and the square background has been coloured in), the assignment has not happened, so even though there is only a single possible value showing, that value will continue to be available in the other squares in the row, column and 3x3 square).] Toggling this button down will hide the multiple values in such undecided squares (but if you click in the square, the pop-up menu will present only the valid choices). Hide choices ------------ This controls which values are presented in the pop-up menu; when it is toggled, all values (1-9) are in the menu - whereas in the other case, only the values known to be valid are shown. |
From: Alex T. <ale...@us...> - 2005-09-29 22:03:39
|
Update of /cvsroot/pythoncard/PythonCard/samples/sudoku In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30180/sudoku Log Message: Directory /cvsroot/pythoncard/PythonCard/samples/sudoku added to the repository |
From: Alex T. <ale...@us...> - 2005-09-29 16:38:17
|
Update of /cvsroot/pythoncard/PythonCard/tools/oneEditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16653 Modified Files: readme.txt Log Message: Update to match the update previously made in codeEditor. Index: readme.txt =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/tools/oneEditor/readme.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** readme.txt 3 Oct 2004 23:58:01 -0000 1.1 --- readme.txt 29 Sep 2005 16:37:49 -0000 1.2 *************** *** 1,20 **** ! Last updated: 2002-04-13 ! This represents the beginnings of a GUI resource (layout) editor for PythonCard. ! You can view the attributes for all components and menus by selecting the Resource... menu item in the View menu prior to doing a Save or Save As... under the File menu to output a new file. ! Known Bugs and Issues: ! There are no constraints applied when the shift key is held down, but there is there a grid for the widgets to "snap to". ! You can only select one widget at a time. ! Sizers and anchors are not supported. It is likely anchors will be supported before sizers. ! Some of the components don't move or resize correctly all the time, you should report problems to the mailing list. The Choice component seems prone to this movement problem. If a component is difficult to select or move, you can always select it via the Property Editor and then change its position attribute via the Property Editor rather than trying to drag the control itself; the sizing handles should also work. ! There is a bug that causes the top three sizing handles to appear incorrectly, usually when the widget y position is at -1. I am trying to determine if this is actually a problem with wxPython or some rare interaction in the resourceEditor code. [I think this is fixed as of release 0.6.2 -ka] ! When editing a dialog or other window that doesn't have a menubar, you'll probably need to increase the vertical size of the window by 20 or 30 pixels to compensate for the resourceEditor menubar. Once your layout looks the way you want it you can subtract the pixel padding you added earlier. On Microsoft Windows, the menubar may wrap if the width of the window is not wide enough, in which case you'll need to add even more padding. ! The next revision of the resourceEditor will use a separate window for doing layout so that the size of a window is always accurate and shows the menubar of the app you're editing. --- 1,54 ---- ! Python Source Code Editor ! The codeEditor sample in PythonCard is focused on being a simple to use Python source code editor. It is not intended to be a generic editor or replace vi(m), Emacs, etc. If you are already happy with your existing editing environment for Python source code, there is no particular reason you have to switch. codeEditor and the resourceEditor and shell will be more tightly integrated as the project progresses so that the user has a simple Integrated Development Environment (IDE) for building desktop applications without needing to use an external program for editing. ! Based on textEditor sample, but using wxStyledTextCtrl (wxSTC) ! For more information, see: ! PythonCard Editor (codeEditor) wiki page ! http://wiki.wxpython.org/index.cgi/PythonCardEditor ! wxStyledTextCtrl documentation ! http://wiki.wxpython.org/index.cgi/wxStyledTextCtrl ! If you use this sample as a real text editor then you should be careful to always work on backup copies of documents in case there are bugs that might corrupt your text. ! You can change the style used to display the source code; the style is also used by the PythonCard shell. ! The last position and size of the window will be saved in a user.config.txt file. ! The About dialog displays the current filename, character, word, and line count. ! ! Scriptlets ! See the following message in the archive for more info. ! http://aspn.activestate.com/ASPN/Mail/Message/PythonCard/1181106 ! ! ! ! Associating Python files with codeEditor on Windows ! ! These instructions are for Windows 2000. They may be slightly different on other versions of Windows. ! ! 1. Open the Explorer and choose "Folder Options..." under the "Tools" menu ! 2. Click on the "File Types" tab ! 3. Scroll down in the "Registered file types" list and select extension "PY Python File" ! 4. Click on the "Advanced" button ! 4a. You should be looking at an "Edit File Type" dialog with a list of Actions such as Edit and Open. Open is probably in bold since it is the default action usually associated with .py files. ! 5. Click on the "New..." button ! 5a. You should be looking at a "New Action" dialog ! 6. In the "Action:" field type in a label such as "Edit with PythonCard". This is the label that will show up in the context menu when you right-click on a .py file in the Explorer ! 7. in the "Application used to perform action:" field you need to specify the path to the Python executable as well as the location of the codeEditor.py file. On a Python 2.3.3 installation using the default installer this will look like: ! ! C:\Python23\pythonw.exe C:\Python23\Lib\site-packages\PythonCard\tools\codeEditor\codeEditor.py "%1" ! ! Substitute your own paths for the ones above and put quotes (") around the paths with spaces in them, if any. If you want a console when codeEditor.py runs, then use python.exe instead of pythonw.exe ! ! 8. Click "OK" ! 8a. You should now have an "Edit with PythonCard" item in your "Edit File Type" dialog ! 8b. The item in bold is the default action; Open will be the default if nothing is showing up in bold. Whether you want to "Edit with PythonCard" or "Open" (run) a script when you double-click a file in the Explorer is of course a personal preference. If you want "Edit with PythonCard" as the default action, then select "Edit with PythonCard" in the list, and click the "Set Default" button. ! 9. Click "OK" ! 10. Click "Close" in the "Folder Options" dialog ! 11. Open a directory in the explorer that contains a .py file, then right-click on the file and choose "Edit with PythonCard" and the file should be opened with codeEditor.py ! 11a. If it doesn't work, double-check the steps above ! 12. Repeat the process for .pyw files, using the same name and path. |
From: Andy T. <an...@us...> - 2005-09-18 03:59:39
|
Update of /cvsroot/pythoncard/PythonCard/samples/spirograph In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9735/samples/spirograph Modified Files: spirograph.py Log Message: Making blanket except clauses more specific Index: spirograph.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/spirograph/spirograph.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** spirograph.py 12 Aug 2004 19:19:02 -0000 1.22 --- spirograph.py 18 Sep 2005 03:59:22 -0000 1.23 *************** *** 164,168 **** bmp = graphic.Bitmap(self.filename) self.components.bufOff.drawBitmap(bmp, (0, 0)) ! except: pass --- 164,168 ---- bmp = graphic.Bitmap(self.filename) self.components.bufOff.drawBitmap(bmp, (0, 0)) ! except IOError, msg: pass *************** *** 197,201 **** bmp.SaveFile(path, fileType) return True ! except: return False else: --- 197,201 ---- bmp.SaveFile(path, fileType) return True ! except IOError, msg: return False else: |
From: Andy T. <an...@us...> - 2005-09-18 03:59:39
|
Update of /cvsroot/pythoncard/PythonCard/samples/webserver/html/cgi-bin In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9735/samples/webserver/html/cgi-bin Modified Files: contacts.py file_upload.py webservices.py Log Message: Making blanket except clauses more specific Index: contacts.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/webserver/html/cgi-bin/contacts.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** contacts.py 24 Oct 2004 19:27:41 -0000 1.7 --- contacts.py 18 Sep 2005 03:59:22 -0000 1.8 *************** *** 30,34 **** #self.displayRecord(0) pass ! except: pass --- 30,34 ---- #self.displayRecord(0) pass ! except Exception, msg: pass *************** *** 59,63 **** s = s.replace('\n', '<BR>') print "<b>%s:</b> %s<br>" % (k, s) ! except: pass print "<hr>" --- 59,63 ---- s = s.replace('\n', '<BR>') print "<b>%s:</b> %s<br>" % (k, s) ! except Exception, msg: pass print "<hr>" Index: webservices.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/webserver/html/cgi-bin/webservices.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** webservices.py 11 Jun 2002 05:22:15 -0000 1.2 --- webservices.py 18 Sep 2005 03:59:22 -0000 1.3 *************** *** 79,83 **** result = dispatch(method, params) response = xmlrpclib.dumps(result, methodresponse=1) ! except: response = xmlrpclib.dumps(xmlrpclib.Fault(1, "%s: %s" % sys.exc_info()[:2])) print 'Content-type: text/xml' --- 79,83 ---- result = dispatch(method, params) response = xmlrpclib.dumps(result, methodresponse=1) ! except Exception, msg: # Should test for a particular Exception response = xmlrpclib.dumps(xmlrpclib.Fault(1, "%s: %s" % sys.exc_info()[:2])) print 'Content-type: text/xml' Index: file_upload.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/webserver/html/cgi-bin/file_upload.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** file_upload.py 28 Jul 2004 16:04:18 -0000 1.2 --- file_upload.py 18 Sep 2005 03:59:22 -0000 1.3 *************** *** 36,40 **** print "Upload of file %s was successful." % filename ! except: print "Upload of file %s failed." % filename --- 36,40 ---- print "Upload of file %s was successful." % filename ! except Exception, msg: # Should check for a particular Exception print "Upload of file %s failed." % filename |
From: Andy T. <an...@us...> - 2005-09-18 03:59:39
|
Update of /cvsroot/pythoncard/PythonCard/samples/textRouter In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9735/samples/textRouter Modified Files: textRouter.py Log Message: Making blanket except clauses more specific Index: textRouter.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/textRouter/textRouter.py,v retrieving revision 1.84 retrieving revision 1.85 diff -C2 -d -r1.84 -r1.85 *** textRouter.py 17 Aug 2004 19:11:51 -0000 1.84 --- textRouter.py 18 Sep 2005 03:59:22 -0000 1.85 *************** *** 504,511 **** else: ins = widget.getInsertionPoint() ! try: ! widget.replace(ins, ins + 1, '') ! except: ! pass self.saveState() --- 504,508 ---- else: ins = widget.getInsertionPoint() ! widget.replace(ins, ins + 1, '') self.saveState() |
From: Andy T. <an...@us...> - 2005-09-18 03:59:39
|
Update of /cvsroot/pythoncard/PythonCard/samples/testSplitter In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9735/samples/testSplitter Modified Files: doodle.py testSplitter.py Log Message: Making blanket except clauses more specific Index: doodle.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/testSplitter/doodle.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** doodle.py 28 Sep 2004 21:23:55 -0000 1.1 --- doodle.py 18 Sep 2005 03:59:22 -0000 1.2 *************** *** 79,83 **** bmp.SaveFile(path, fileType) return 1 ! except: return 0 else: --- 79,83 ---- bmp.SaveFile(path, fileType) return 1 ! except IOError, msg: return 0 else: Index: testSplitter.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/samples/testSplitter/testSplitter.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** testSplitter.py 28 Sep 2004 21:23:55 -0000 1.1 --- testSplitter.py 18 Sep 2005 03:59:22 -0000 1.2 *************** *** 141,145 **** bmp.SaveFile(path, fileType) return 1 ! except: return 0 else: --- 141,145 ---- bmp.SaveFile(path, fileType) return 1 ! except Exception, msg: # Should check for a particular exception return 0 else: |