From: Alex T. <ale...@us...> - 2004-10-03 23:58:10
|
Update of /cvsroot/pythoncard/PythonCard/tools/oneEditor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10092 Added Files: Info.plist codePage.py codePage.rsrc.py macbuild.py readme.txt resourceEditor.py resourceEditor.rsrc.py restEditor.py restEditor.rsrc.py snippet.py tabcodeEditor.py tabcodeEditor.rsrc.py todo.txt Log Message: Initial version of a tabbed code editor, with associated (future) resource editor --- NEW FILE: snippet.py --- from docutils import core from docutils.writers.html4css1 import Writer,HTMLTranslator from docutils.utils import SystemMessage class NoHeaderHTMLTranslator(HTMLTranslator): def __init__(self, document): HTMLTranslator.__init__(self,document) self.head_prefix = ['','','','',''] self.body_prefix = [] self.body_suffix = [] self.stylesheet = [] _w = Writer() _w.translator_class = NoHeaderHTMLTranslator def restify(string): # return core.publish_string(string,writer=_w) try: result = core.publish_string(string,writer=_w, settings_overrides={'traceback': True}) except SystemMessage, e: result = None print "barf" return result if __name__ == '__main__': test = """ Test example of reST__ document. __ http://docutils.sf.net/rst.html - item 1 - item 2 - item 3 """ print restify(test) --- NEW FILE: Info.plist --- <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeExtensions</key> <array> <string>c</string> <string>cgi</string> <string>c++</string> <string>cp</string> <string>cpp</string> <string>cs</string> <string>css</string> <string>csv</string> <string>dtd</string> <string>h</string> <string>htm</string> <string>html</string> <string>log</string> <string>plist</string> <string>py</string> <string>python</string> <string>pyw</string> <string>sgml</string> <string>sh</string> <string>shtm</string> <string>shtml</string> <string>text</string> <string>txt</string> <string>xhtml</string> <string>xml</string> <string>xsl</string> <string>xslt</string> <string>yaml</string> <string>*</string> </array> <key>CFBundleTypeMIMETypes</key> <array> <string>text/plain</string> </array> <key>CFBundleTypeName</key> <string>Python Module</string> <key>CFBundleTypeOSTypes</key> <array> <string>TEXT</string> <string>****</string> </array> <key>CFBundleTypeRole</key> <string>Editor</string> </dict> </array> <key>CFBundleExecutable</key> <string>CodeEditor</string> <key>CFBundleName</key> <string>CodeEditor</string> <key>CFBundleIdentifier</key> <string>CodeEditor</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleGetInfoString</key> <string>0.8</string> <key>CFBundleShortVersionString</key> <string>0.8</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleVersion</key> <string>0.8 (v1.124)</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> </dict> </plist> --- NEW FILE: todo.txt --- - figure out initial sizing issues - close button / menu item to close current page - add menu and command items to drop-downs - key / shortcut to take you to the drop-down (if possible) ? --- NEW FILE: resourceEditor.rsrc.py --- {'application':{'type':'Application', 'name':'ResEdit', 'backgrounds': [ {'type':'Background', 'name':'bgDrag', 'title':'Resource Editor', 'size':(316, 166), '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', }, {'type':'MenuItem', 'name':'menuFileSaveAs', 'label':'Save &As...', }, {'type':'MenuItem', 'name':'menuFileRevert', 'label':'Revert', }, {'type':'MenuItem', 'name':'fileSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuFileRun', 'label':'&Run\tCtrl+R', 'command':'fileRun', }, {'type':'MenuItem', 'name':'menuFileRunWithInterpreter', 'label':'Run with &interpreter\tCtrl+Shift+R', 'command':'fileRunWithInterpreter', }, {'type':'MenuItem', 'name':'menuFileRunOptions', 'label':'Run Options...', 'command':'fileRunOptions', }, {'type':'MenuItem', 'name':'menuFilePreviewDialog', 'label':'Preview Dialog', 'command':'filePreviewDialog', }, {'type':'MenuItem', 'name':'fileSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuFileExit', 'label':'E&xit\tAlt+X', 'command':'exit', }, ] }, {'type':'Menu', 'name':'menuEdit', 'label':'&Edit', 'items': [ {'type':'MenuItem', 'name':'menuEditCut', 'label':'Cu&t\tCtrl+X', }, {'type':'MenuItem', 'name':'menuEditCopy', 'label':'&Copy\tCtrl+C', }, {'type':'MenuItem', 'name':'menuEditPaste', 'label':'&Paste\tCtrl+V', }, {'type':'MenuItem', 'name':'editSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuComponentDuplicate', 'label':'&Duplicate', 'command':'componentDuplicate', }, {'type':'MenuItem', 'name':'menuComponentDelete', 'label':'Delete\tDel', 'command':'componentDelete', }, {'type':'MenuItem', 'name':'componentSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditBackgroundInfo', 'label':'Background Info...', 'command':'editBackgroundInfo', }, {'type':'MenuItem', 'name':'menuEditMenubar', 'label':'Menu Editor...', 'command':'editMenubar', }, {'type':'MenuItem', 'name':'menuEditStrings', 'label':'String Editor...', 'command':'editStrings', }, {'type':'MenuItem', 'name':'menuEditDialogInfo', 'label':'Dialog Info...', 'command':'editDialogInfo', }, ] }, {'type':'Menu', 'name':'menuComponent', 'label':'&Component', 'items': [] }, {'type':'Menu', 'name':'menuOptions', 'label':'&Options', 'items': [ {'type':'MenuItem', 'name':'menuOptionsGridSize', 'label':'Grid Size...', 'command':'optionGridSize', }, {'type':'MenuItem', 'name':'menuOptionsAlignToGrid', 'label':'Align Components to Grid\tCtrl+G', 'checkable':1, }, {'type':'MenuItem', 'name':'menuOptionsShowGridLines', 'label':'Show Grid Lines', 'checkable':1, 'checked':0, }, {'type':'MenuItem', 'name':'componentSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuComponentSendBack', 'label':'Send to Back\tCtrl+1', 'command':'componentSendBack', }, {'type':'MenuItem', 'name':'menuComponentMoveBack', 'label':'Move Backward\tCtrl+2', 'command':'componentMoveBack', }, {'type':'MenuItem', 'name':'menuComponentMoveForward', 'label':'Move Forward\tCtrl+3', 'command':'componentMoveForward', }, {'type':'MenuItem', 'name':'menuComponentBringFront', 'label':'Bring to Front\tCtrl+4', 'command':'componentBringFront', }, ] }, {'type':'Menu', 'name':'menuView', 'label':'&View', 'items': [ {'type':'MenuItem', 'name':'menuViewAttributes', 'label':'&Resource...', 'command':'displayAttributes', }, {'type':'MenuItem', 'name':'menuViewSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuViewPropertyEditor', 'label':'Property Editor\tCtrl+P', 'checkable':1, 'checked':1, }, ] }, {'type':'Menu', 'name':'menuHelp', 'label':'&Help', 'items': [ {'type':'MenuItem', 'name':'menuResourceEditorDocumentation', 'label':'&resourceEditor Documentation...\tF1', 'command':'showResourceEditorDocumentation', }, {'type':'MenuItem', 'name':'menuPythonCardDocumentation', 'label':'&PythonCard Documentation...', 'command':'showPythonCardDocumentation', }, {'type':'MenuItem', 'name':'helpSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuHelpAbout', 'label':'&About resourceEditor...', }, {'type':'MenuItem', 'name':'menuHelpAboutPythonCard', 'label':'About PythonCard...', 'command':'doHelpAboutPythonCard', }, ] }, ] }, 'components': [ ] # end components } # end background ] # end backgrounds } } --- NEW FILE: tabcodeEditor.rsrc.py --- {'application':{'type':'Application', 'name':'codeEditor', 'backgrounds': [ {'type':'Background', 'name':'bgCodeEditor', 'title':'tabbed Code Editor PythonCard Application', 'position':(22, 22), 'size':(400, 300), 'statusBar':1, 'visible':0, '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', }, {'type':'MenuItem', 'name':'menuFileSaveAs', 'label':'Save &As...', }, {'type':'MenuItem', 'name':'fileSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuFileCheckSyntax', 'label':'&Check Syntax (Module)\tAlt+F5', 'command':'checkSyntax', }, {'type':'MenuItem', 'name':'menuFileRun', 'label':'&Run\tCtrl+R', 'command':'fileRun', }, {'type':'MenuItem', 'name':'menuFileRunWithInterpreter', 'label':'Run with &interpreter\tCtrl+Shift+R', 'command':'fileRunWithInterpreter', }, {'type':'MenuItem', 'name':'menuFileRunOptions', 'label':'Run Options...', 'command':'fileRunOptions', }, {'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', }, {'type':'MenuItem', 'name':'menuEditRedo', 'label':'&Redo\tCtrl+Y', }, {'type':'MenuItem', 'name':'editSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditCut', 'label':'Cu&t\tCtrl+X', }, {'type':'MenuItem', 'name':'menuEditCopy', 'label':'&Copy\tCtrl+C', }, {'type':'MenuItem', 'name':'menuEditPaste', 'label':'&Paste\tCtrl+V', }, {'type':'MenuItem', 'name':'editSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditFind', 'label':'&Find...\tCtrl+F', 'command':'doEditFind', }, {'type':'MenuItem', 'name':'menuEditFindNext', 'label':'&Find Next\tF3', 'command':'doEditFindNext', }, {'type':'MenuItem', 'name':'menuEditFindFiles', 'label':'Find in Files...\tAlt+F3', 'command':'findFiles', }, {'type':'MenuItem', 'name':'menuEditReplace', 'label':'&Replace...\tCtrl+H', 'command':'doEditFindReplace', }, {'type':'MenuItem', 'name':'menuEditGoTo', 'label':'&Go To...\tCtrl+G', 'command':'doEditGoTo', }, {'type':'MenuItem', 'name':'editSep3', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditReplaceTabs', 'label':'&Replace tabs with spaces', 'command':'doEditReplaceTabs', }, {'type':'MenuItem', 'name':'editSep3', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditClear', 'label':'Cle&ar\tDel', }, {'type':'MenuItem', 'name':'menuEditSelectAll', 'label':'Select A&ll\tCtrl+A', }, {'type':'MenuItem', 'name':'editSep4', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditIndentRegion', 'label':'&Indent Region', 'command':'indentRegion', }, {'type':'MenuItem', 'name':'menuEditDedentRegion', 'label':'&Dedent Region', 'command':'dedentRegion', }, {'type':'MenuItem', 'name':'menuEditCommentRegion', 'label':'Comment &out region\tAlt+3', 'command':'commentRegion', }, {'type':'MenuItem', 'name':'menuEditUncommentRegion', 'label':'U&ncomment region\tShift+Alt+3', 'command':'uncommentRegion', }, ] }, {'type':'Menu', 'name':'menuView', 'label':'&View', 'items': [ {'type':'MenuItem', 'name':'menuViewWhitespace', 'label':'&Whitespace', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewIndentationGuides', 'label':'Indentation &guides', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewRightEdgeIndicator', 'label':'&Right edge indicator', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewEndOfLineMarkers', 'label':'&End-of-line markers', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewFixedFont', 'label':'&Fixed Font', 'enabled':0, 'checkable':1, }, {'type':'MenuItem', 'name':'viewSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuViewLineNumbers', 'label':'&Line Numbers', 'checkable':1, 'checked':1, }, {'type':'MenuItem', 'name':'menuViewCodeFolding', 'label':'&Code Folding', 'checkable':1, }, ] }, {'type':'Menu', 'name':'menuFormat', 'label':'F&ormat', 'items': [ {'type':'MenuItem', 'name':'menuFormatStyles', 'label':'&Styles...', 'command':'doSetStyles', }, {'type':'MenuItem', 'name':'menuFormatWrap', 'label':'&Wrap Lines', 'checkable':1, }, ] }, {'type':'Menu', 'name':'menuScriptlet', 'label':'&Shell', 'items': [ {'type':'MenuItem', 'name':'menuScriptletShell', 'label':'&Shell Window\tF5', }, {'type':'MenuItem', 'name':'menuScriptletNamespace', 'label':'&Namespace Window\tF6', }, {'type':'MenuItem', 'name':'menuScriptletSaveUserConfiguration', 'label':'Save &Configuration', }, {'type':'MenuItem', 'name':'menuShellChangeDirectory', 'label':'Change &Directory...', }, {'type':'MenuItem', 'name':'scriptletSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuScriptletSaveShellSelection', 'label':'Save Shell Selection...', }, {'type':'MenuItem', 'name':'menuScriptletRunScriptlet', 'label':'Run Scriptlet...', }, ] }, {'type':'Menu', 'name':'menuHelp', 'label':'&Help', 'items': [ {'type':'MenuItem', 'name':'menuShellDocumentation', 'label':'&Shell Documentation...', 'command':'showShellDocumentation', }, {'type':'MenuItem', 'name':'menuPythonCardDocumentation', 'label':'&PythonCard Documentation...\tF1', 'command':'showPythonCardDocumentation', }, {'type':'MenuItem', 'name':'menuPythonDocumentation', 'label':'Python &Documentation...', 'command':'showPythonDocumentation', }, {'type':'MenuItem', 'name':'helpSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuHelpAbout', 'label':'&About codeEditor...', 'command':'doHelpAbout', }, {'type':'MenuItem', 'name':'menuHelpAboutPythonCard', 'label':'About PythonCard...', 'command':'doHelpAboutPythonCard', }, ] }, ] }, 'strings': { 'saveAs':'Save As', 'openFile':'Open file', 'chars':'chars', 'gotoLine':'Goto line', 'gotoLineNumber':'Goto line number:', 'sample':'codeEditor sample', 'codeEditor':'codeEditor', 'words':'words', 'documentChangedPrompt':'The text in the %s file has changed.\n\nDo you want to save the changes?', 'saveAsWildcard':'All files (*.*)|*.*|Python scripts (*.py;*.pyw)|*.pyw;*.PY;*.PYW;*.py|Text files (*.txt;*.text)|*.text;*.TXT;*.TEXT;*.txt|HTML and XML files (*.htm;*.html;*.xml)|*.htm;*.xml;*.HTM;*.HTML;*.XML;*.html', 'about':'About codeEditor...', 'document':'Document', 'lines':'lines', 'untitled':'Untitled', 'replaced':'Replaced %d occurances', 'scriptletWildcard':'Python files (*.py)|*.py|All Files (*.*)|*.*', }, 'components': [ {'type':'Notebook', 'name':'notebook', 'position':(10, 30), 'size':(274, 105), }, {'type':'Choice', 'name':'popComponentNames', 'position':(6, 6), 'items':[], }, {'type':'Choice', 'name':'popComponentEvents', 'position':(152, 6), 'items':[], }, ] # end components } # end background ] # end backgrounds } } --- NEW FILE: codePage.rsrc.py --- {'application':{'type':'Application', 'name':'codeEditor', 'backgrounds': [ {'type':'Background', 'name':'bgCodeEditor', 'title':'Code Page PythonCard Application', 'position':(132, 132), 'size':(407, 308), 'statusBar':1, 'visible':0, 'style':['resizeable'], 'strings': { 'saveAs':'Save As', 'openFile':'Open file', 'chars':'chars', 'gotoLine':'Goto line', 'gotoLineNumber':'Goto line number:', 'sample':'codeEditor sample', 'codeEditor':'codeEditor', 'words':'words', 'documentChangedPrompt':'The text in the %s file has changed.\n\nDo you want to save the changes?', 'saveAsWildcard':'All files (*.*)|*.*|Python scripts (*.py;*.pyw)|*.pyw;*.PY;*.PYW;*.py|Text files (*.txt;*.text)|*.text;*.TXT;*.TEXT;*.txt|HTML and XML files (*.htm;*.html;*.xml)|*.htm;*.xml;*.HTM;*.HTML;*.XML;*.html', 'about':'About codeEditor...', 'document':'Document', 'lines':'lines', 'untitled':'Untitled', 'replaced':'Replaced %d occurances', 'scriptletWildcard':'Python files (*.py)|*.py|All Files (*.*)|*.*', }, 'components': [ {'type':'CodeEditor', 'name':'document', 'position':(2, 2), 'size':(386, 246), 'backgroundColor':(255, 255, 255), }, ] # end components } # end background ] # end backgrounds } } --- NEW FILE: codePage.py --- #!/usr/bin/env python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2004/10/03 23:58:01 $" PythonCard Editor (codeEditor) wiki page http://wiki.wxpython.org/index.cgi/PythonCardEditor wxStyledTextCtrl documentation http://wiki.wxpython.org/index.cgi/wxStyledTextCtrl """ from PythonCard import about, configuration, dialog, log, menu, model, resource, util, registry from PythonCard.templates.dialogs import runOptionsDialog from modules import scriptutils import os, sys import wx from wx import stc from wx.html import HtmlEasyPrinting import pprint from PythonCard import STCStyleEditor from modules import colorizer import cStringIO import webbrowser class CodePage(model.PageBackground): def on_initialize(self, event): self.initSizers() self.setDefaultStyles() self.lastStatus = None self.lastPos = None def initSizers(self): sizer1 = wx.BoxSizer(wx.VERTICAL) sizer1.Add(self.components.document, 1, wx.EXPAND) sizer1.Fit(self) sizer1.SetSizeHints(self) self.panel.SetSizer(sizer1) self.panel.SetAutoLayout(1) self.panel.Layout() def setDefaultStyles(self): config = configuration.getStyleConfigPath() # KEA 2002-05-28 # STCStyleEditor doesn't work yet on OS X if config is not None: STCStyleEditor.initSTC(self.components.document, config, 'python') if self.application.shell is not None: STCStyleEditor.initSTC(self.application.shell, config, 'python') def setEditorStyle(self): try: self.components.document.setEditorStyle(os.path.splitext(self.documentPath)[-1]) except: self.components.document.setEditorStyle('python') def newFile(self): self.components.document.text = '' self.documentPath = None self.setEditorStyle() self.components.document.SetSavePoint() self.statusBar.text = self.resource.strings.untitled self.lastStatus = None # KEA 2003-07-26 # reset EOL to match platform # this may not actually be what the user expects # so perhaps this should be an option in a dialog?! self.autoSetEOL() self.topLevelParent.setTitleBar(self.resource.strings.untitled) def openFile(self, path): try: self.components.document.SetUndoCollection(0) self.components.document.ClearAll() f = open(path, 'rb') try: self.components.document.text = f.read() finally: f.close() self.documentPath = path os.chdir(os.path.dirname(self.documentPath)) self.components.document.EmptyUndoBuffer() self.components.document.SetUndoCollection(1) self.components.document.SetSavePoint() #self.statusBar.text = path self.lastStatus = None self.topLevelParent.fileHistory.AddFileToHistory(path) # KEA 2002-06-29 # just as a test, let's see how the XML and/or HTML styles # look self.setEditorStyle() self.autoSetEOL() self.topLevelParent.setTitleBar(os.path.split(path)[-1]) except: pass def saveFile(self, path): try: f = open(path, 'wb') try: f.write(self.components.document.text) finally: f.close() self.documentPath = path os.chdir(os.path.dirname(self.documentPath)) self.components.document.SetSavePoint() self.title = os.path.split(path)[-1] + ' - ' + self.startTitle #self.statusBar.text = path self.lastStatus = None self.setEditorStyle() except: pass # KEA 2003-07-26 def autoSetEOL(self): """ when opening an existing file automatically set the EOL mode to match the current line endings for the file if the document is empty then set EOL to the original EOL state """ doc = self.components.document if doc.GetLength(): line = doc.GetLine(0) else: line = os.linesep if line.endswith('\r\n'): doc.SetEOLMode(stc.STC_EOL_CRLF) elif line.endswith('\n'): doc.SetEOLMode(stc.STC_EOL_LF) elif line.endswith('\r'): doc.SetEOLMode(stc.STC_EOL_CR) # Edit menu def on_menuEditUndo_select(self, event): widget = self.findFocus() if hasattr(widget, 'editable') and widget.CanUndo(): widget.Undo() def on_menuEditRedo_select(self, event): widget = self.findFocus() if hasattr(widget, 'editable') and widget.CanRedo(): widget.Redo() def on_menuEditCut_select(self, event): widget = self.findFocus() # KEA 2002-05-03 # no CanCut() method? if hasattr(widget, 'editable'): widget.Cut() def on_menuEditCopy_select(self, event): widget = self.findFocus() # KEA 2002-05-03 # no CanCopy() method? if hasattr(widget, 'editable'): widget.Copy() def on_menuEditPaste_select(self, event): widget = self.findFocus() if hasattr(widget, 'editable') and widget.CanPaste(): widget.Paste() def on_menuEditClear_select(self, event): widget = self.findFocus() if hasattr(widget, 'editable'): widget.ClearSelection() def on_menuEditSelectAll_select(self, event): widget = self.findFocus() if hasattr(widget, 'editable'): widget.SelectAll() def on_document_keyDown(self, event): #print "keyPress", event.keyCode, event.shiftDown, event.controlDown, event.altDown # smart auto-indent on Return # this is brute force and currently assumes 4 space # Guido indentation style keyCode = event.keyCode target = event.target if keyCode == wx.WXK_RETURN: # since we won't be calling skip, insert a newline manually self.components.document.CmdKeyExecute(stc.STC_CMD_NEWLINE) # why isn't GetCurrentLine 0 based? line = target.GetCurrentLine() - 1 txt = target.GetLine(line) stripped = txt.rstrip() # auto-indent block indent = target.GetLineIndentation(line) padding = " " * indent pos = target.GetCurrentPos() if len(stripped) > 0 and stripped[-1] == ':': # KEA 2002-05-06 to do # should use GetStyleAt() on the actual pos of # the : to make sure the style is not wxSTC_P_COMMENTLINE... # actually this is more complex and really when the style # we need to walk backwards until we find a colon not in # one of the comment styles before doing an auto-indent # but I don't feel like getting it all working before 0.6.6 # so this is left as an exercise for the reader ;-) ## whitespace = len(txt) - len(stripped) ## colonPos = target.GetLineEndPosition(line) - whitespace + 1 ## if target.GetStyleAt(colonPos) not in \ ## [stc.STC_P_COMMENTLINE, ## stc.STC_P_COMMENTBLOCK, ## stc.STC_P_TRIPLEDOUBLE ]: padding += " " * 4 target.InsertText(pos, padding) newpos = pos + len(padding) target.SetCurrentPos(newpos) target.SetSelection(newpos, newpos) else: event.skip() # AGT 2004/10/03 # why have this here - just do in top level ??? # but keep this here as a placeholder to remind me to change it def becomeFocus(self): if self.documentPath: self.topLevelParent.setTitleBar(self.documentPath) else: self.topLevelParent.setTitleBar("") # This is no longer a stand-alone - need to add a simple wrapper to test #if __name__ == '__main__': #app = model.Application(CodePage) #app.MainLoop() --- NEW FILE: macbuild.py --- import os, sys import bundlebuilder import plistlib # I set this to make adding subfolders into the package easier # KEA 2004-07-22 # rather than hard-coding the path # we'll just get the path from this module ##packageroot = "/Users/kevino/oss/eclass/eclass_builder" packageroot = os.path.abspath(os.path.dirname(__file__)) # for the purposes of building the standalone # change to the directory the build script is in to simplify imports os.chdir(packageroot) # Create the AppBuilder myapp = bundlebuilder.AppBuilder(verbosity=1) # Tell it where to find the main script - the one that loads on startup myapp.mainprogram = os.path.join(packageroot, "codeEditor.py") # drag&dropped filenames show up in sys.argv # this doesn't seem to work, need to add additional # import argvemulator in my code? #myapp.argv_emulation=1 # make this app self contained myapp.standalone = 1 myapp.name = "CodeEditor" myapp.plist = plistlib.Plist.fromFile(os.path.join(packageroot, "Info.plist")) # includePackages forces certain packages to be added to the app bundle ##myapp.includePackages.append("encodings") ##myapp.includePackages.append("_xmlplus") # Here you add supporting files and/or folders to your bundle myapp.resources.append(os.path.join(packageroot, "scriptlets")) myapp.resources.append(os.path.join(packageroot, "codeEditor.rsrc.py")) myapp.resources.append(os.path.join(packageroot, "..", "..", "templates", "dialogs", "runOptionsDialog.rsrc.py")) myapp.resources.append(os.path.join(packageroot, "..", "..", "pythoncard_config.txt")) myapp.resources.append(os.path.join(packageroot, "..", "..", "stc-styles.cfg")) # bundlebuilder does not yet have the capability to detect what shared libraries # are needed by your app - so in this case I am adding the wxPython libs manually myapp.libs.append("/usr/local/lib/wxPython-2.5.2.7/lib/libwx_macd-2.5.2.dylib") myapp.libs.append("/usr/local/lib/wxPython-2.5.2.7/lib/libwx_macd-2.5.2.rsrc") myapp.libs.append("/usr/local/lib/wxPython-2.5.2.7/lib/libwx_macd_stc-2.5.2.dylib") # Here we build the app! myapp.setup() myapp.build() --- NEW FILE: tabcodeEditor.py --- #!/usr/bin/env python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2004/10/03 23:58:01 $" PythonCard Editor (codeEditor) wiki page http://wiki.wxpython.org/index.cgi/PythonCardEditor wxStyledTextCtrl documentation http://wiki.wxpython.org/index.cgi/wxStyledTextCtrl """ from PythonCard import about, configuration, dialog, log, menu, model, resource, util, registry from PythonCard.templates.dialogs import runOptionsDialog import codePage from modules import scriptutils import os, sys import wx [...1172 lines suppressed...] self.currentPage.becomeFocus() self.updateStatusBar() self.updateTitleBar() self.setResourceFile() event.skip() # KEA 2004-08-18 # I'll probably move this functionality into model.Application # and just call a macOpenFile method in the current background class MyApplication(model.Application): # support drag and drop on the application icon on the Mac def MacOpenFile(self, filename): # code to load filename goes here self.backgrounds[0].openFile(filename) if __name__ == '__main__': app = MyApplication(TabCodeEditor) app.MainLoop() --- NEW FILE: restEditor.rsrc.py --- {'application':{'type':'Application', 'name':'codeEditor', 'backgrounds': [ {'type':'Background', 'name':'bgCodeEditor', 'title':'Code Editor PythonCard Application', 'size':(400, 300), 'statusBar':1, 'visible':0, 'style':['resizeable'], 'visible':0, 'menubar': {'type':'MenuBar', 'menus': [ {'type':'Menu', 'name':'menuFile', 'label':'&File', 'items': [ {'type':'MenuItem', 'name':'menuFileNewWindow', 'label':'New Window', }, {'type':'MenuItem', 'name':'menuFileNew', 'label':'&New\tCtrl+N', }, {'type':'MenuItem', 'name':'menuFileOpen', 'label':'&Open\tCtrl+O', }, {'type':'MenuItem', 'name':'menuFileSave', 'label':'&Save\tCtrl+S', }, {'type':'MenuItem', 'name':'menuFileSaveAs', 'label':'Save &As...', }, {'type':'MenuItem', 'name':'menuFileSaveHtml', 'label':'Save HTML As...', 'command':'saveHtml', }, {'type':'MenuItem', 'name':'fileSep1', 'label':'-', }, ## {'type':'MenuItem', ## 'name':'menuFileCheckSyntax', ## 'label':'&Check Syntax (Module)\tAlt+F5', ## 'command':'checkSyntax', ## }, ## {'type':'MenuItem', ## 'name':'menuFileRun', ## 'label':'&Run\tCtrl+R', ## 'command':'fileRun', ## }, ## {'type':'MenuItem', ## 'name':'menuFileRunWithInterpreter', ## 'label':'Run with &interpreter\tCtrl+Shift+R', ## 'command':'fileRunWithInterpreter', ## }, ## {'type':'MenuItem', ## 'name':'menuFileRunOptions', ## 'label':'Run Options...', ## 'command':'fileRunOptions', ## }, ## {'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', }, {'type':'MenuItem', 'name':'menuEditRedo', 'label':'&Redo\tCtrl+Y', }, {'type':'MenuItem', 'name':'editSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditCut', 'label':'Cu&t\tCtrl+X', }, {'type':'MenuItem', 'name':'menuEditCopy', 'label':'&Copy\tCtrl+C', }, {'type':'MenuItem', 'name':'menuEditPaste', 'label':'&Paste\tCtrl+V', }, {'type':'MenuItem', 'name':'editSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditFind', 'label':'&Find...\tCtrl+F', 'command':'doEditFind', }, {'type':'MenuItem', 'name':'menuEditFindNext', 'label':'&Find Next\tF3', 'command':'doEditFindNext', }, {'type':'MenuItem', 'name':'menuEditFindFiles', 'label':'Find in Files...\tAlt+F3', 'command':'findFiles', }, {'type':'MenuItem', 'name':'menuEditReplace', 'label':'&Replace...\tCtrl+H', 'command':'doEditFindReplace', }, {'type':'MenuItem', 'name':'menuEditGoTo', 'label':'&Go To...\tCtrl+G', 'command':'doEditGoTo', }, {'type':'MenuItem', 'name':'editSep3', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditReplaceTabs', 'label':'&Replace tabs with spaces', 'command':'doEditReplaceTabs', }, {'type':'MenuItem', 'name':'editSep3', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditClear', 'label':'Cle&ar\tDel', }, {'type':'MenuItem', 'name':'menuEditSelectAll', 'label':'Select A&ll\tCtrl+A', }, {'type':'MenuItem', 'name':'editSep4', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditIndentRegion', 'label':'&Indent Region', 'command':'indentRegion', }, {'type':'MenuItem', 'name':'menuEditDedentRegion', 'label':'&Dedent Region', 'command':'dedentRegion', }, {'type':'MenuItem', 'name':'menuEditCommentRegion', 'label':'Comment &out region\tAlt+3', 'command':'commentRegion', }, {'type':'MenuItem', 'name':'menuEditUncommentRegion', 'label':'U&ncomment region\tShift+Alt+3', 'command':'uncommentRegion', }, ] }, {'type':'Menu', 'name':'menuView', 'label':'&View', 'items': [ {'type':'MenuItem', 'name':'menuViewWhitespace', 'label':'&Whitespace', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewIndentationGuides', 'label':'Indentation &guides', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewRightEdgeIndicator', 'label':'&Right edge indicator', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewEndOfLineMarkers', 'label':'&End-of-line markers', 'checkable':1, }, {'type':'MenuItem', 'name':'menuViewFixedFont', 'label':'&Fixed Font', 'enabled':0, 'checkable':1, }, {'type':'MenuItem', 'name':'viewSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuViewLineNumbers', 'label':'&Line Numbers', 'checkable':1, 'checked':1, }, {'type':'MenuItem', 'name':'menuViewCodeFolding', 'label':'&Code Folding', 'checkable':1, 'checked':0, }, {'type':'MenuItem', 'name':'viewSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuViewPreviewHTML', 'label':'&Preview HTML\tCtrl+1', 'command':'previewPost', }, {'type':'MenuItem', 'name':'menuViewSourceIsHtml', 'label':'Source is HTML', 'checkable':1, 'checked':0, }, ] }, {'type':'Menu', 'name':'menuFormat', 'label':'F&ormat', 'items': [ {'type':'MenuItem', 'name':'menuFormatStyles', 'label':'&Styles...', 'command':'doSetStyles', }, {'type':'MenuItem', 'name':'menuFormatWrap', 'label':'&Wrap Lines', 'checkable':1, }, {'type':'MenuItem', 'name':'formatSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuFormatRender', 'label':'Render Page\tCtrl+R', 'command':'previewPost', }, {'type':'MenuItem', 'name':'menuFormatRenderOnReturn', 'label':'Render on Return', 'checkable':1, 'checked':1, }, ] }, {'type':'Menu', 'name':'menuScriptlet', 'label':'&Shell', 'items': [ {'type':'MenuItem', 'name':'menuScriptletShell', 'label':'&Shell Window\tF5', }, {'type':'MenuItem', 'name':'menuScriptletNamespace', 'label':'&Namespace Window\tF6', }, {'type':'MenuItem', 'name':'menuScriptletSaveUserConfiguration', 'label':'Save &Configuration', }, {'type':'MenuItem', 'name':'menuShellChangeDirectory', 'label':'Change &Directory...', }, {'type':'MenuItem', 'name':'scriptletSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuScriptletSaveShellSelection', 'label':'Save Shell Selection...', }, {'type':'MenuItem', 'name':'menuScriptletRunScriptlet', 'label':'Run Scriptlet...', }, ] }, {'type':'Menu', 'name':'menuHelp', 'label':'&Help', 'items': [ {'type':'MenuItem', 'name':'menuShellDocumentation', 'label':'&Shell Documentation...', 'command':'showShellDocumentation', }, {'type':'MenuItem', 'name':'menuPythonCardDocumentation', 'label':'&PythonCard Documentation...\tF1', 'command':'showPythonCardDocumentation', }, {'type':'MenuItem', 'name':'menuPythonDocumentation', 'label':'Python &Documentation...', 'command':'showPythonDocumentation', }, {'type':'MenuItem', 'name':'helpSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuHelpRest', 'label':'reStructuredText Home Page', 'command':'doHelpRest', }, {'type':'MenuItem', 'name':'menuHelpRestQuickReference', 'label':'reStructuredText Quick Reference', 'command':'doHelpRestQuickReference', }, {'type':'MenuItem', 'name':'helpSep2', 'label':'-', }, {'type':'MenuItem', 'name':'menuHelpAbout', 'label':'&About codeEditor...', 'command':'doHelpAbout', }, {'type':'MenuItem', 'name':'menuHelpAboutPythonCard', 'label':'About PythonCard...', 'command':'doHelpAboutPythonCard', }, ] }, ] }, 'strings': { 'saveAs':'Save As', 'about':'About codeEditor...', 'saveAsWildcard':'All files (*.*)|*.*|Python scripts (*.py;*.pyw)|*.pyw;*.PY;*.PYW;*.py|Text files (*.txt;*.text)|*.text;*.TXT;*.TEXT;*.txt|HTML and XML files (*.htm;*.html;*.xml)|*.htm;*.xml;*.HTM;*.HTML;*.XML;*.html', 'chars':'chars', 'gotoLine':'Goto line', 'lines':'lines', 'gotoLineNumber':'Goto line number:', 'documentChangedPrompt':'The text in the %s file has changed.\n\nDo you want to save the changes?', 'untitled':'Untitled', 'sample':'codeEditor sample', 'codeEditor':'codeEditor', 'replaced':'Replaced %d occurances', 'words':'words', 'openFile':'Open file', 'scriptletWildcard':'Python files (*.py)|*.py|All Files (*.*)|*.*', 'document':'Document', }, 'components': [ {'type':'CodeEditor', 'name':'document', 'position':(0, 0), 'size':(250, 100), }, ] # end components } # end background ] # end backgrounds } } --- NEW FILE: resourceEditor.py --- #!/usr/bin/python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2004/10/03 23:58:01 $" """ # TODO: Start using exceptions! import os, sys import pprint import webbrowser import wx from PythonCard import about, clipboard, configuration, dialog, graphic, log from PythonCard import menu, model, registry, resource, util from PythonCard.templates.dialogs import runOptionsDialog [...1652 lines suppressed...] event.skip() except: event.skip() def on_showPythonCardDocumentation_command(self, event): global pythoncard_url webbrowser.open(pythoncard_url) def on_showResourceEditorDocumentation_command(self, event): global resourceeditor_url webbrowser.open(resourceeditor_url) if __name__ == '__main__': # now force the property editor to be enabled #configuration('showPropertyEditor', 1) #configuration('showShell', 1) app = model.Application(ResourceEditor) app.MainLoop() --- NEW FILE: restEditor.py --- #!/usr/bin/env python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2004/10/03 23:58:01 $" """ import os from PythonCard import dialog, model from codeEditor import CodeEditor from wx import stc import webbrowser # reST from PythonCard.templates.htmlpreview import HtmlPreview from snippet import restify class RestEditor(CodeEditor): def on_initialize(self, event): super(RestEditor, self).on_initialize(event) self.renderOnReturn = self.menuBar.getChecked('menuFormatRenderOnReturn') self.previewWindow = model.childWindow(self, HtmlPreview) #self.previewWindow.position = (425, -1) self.previewWindow.visible = True self.html = '' # reST def on_previewPost_command(self, event): self.previewWindow.Show() txt = self.components.document.text if self.menuBar.getChecked('menuViewSourceIsHtml'): firstLine = txt[:10].lower() if firstLine.startswith('<!doctype') or firstLine.startswith('<html'): # assume full HTML document html = txt else: html = '<html>\n<head>\n</head>\n<body>\n' + txt + '\n</body>\n</html>\n' else: # KEA 2004-08-15 # snippet.restify is returning None when there is a reST error # what's a better way to provide feedback to the user without barfing # all over the output? rest = restify(txt) if rest: html = '<html>\n<head>\n</head>\n<body>\n' + rest + '\n</body>\n</html>\n' else: html = self.previewWindow.components.html.text # do make sure stylesheets and relative image references can be found # might need to chdir here # won't work until there is a document path curdir = os.getcwd() self.previewWindow.components.html.text = html self.html = html os.chdir(curdir) def on_document_keyDown(self, event): if event.keyCode == 13 and self.renderOnReturn: # since we won't be calling skip, insert a newline manually self.components.document.CmdKeyExecute(stc.STC_CMD_NEWLINE) self.on_previewPost_command(None) else: event.skip() def saveHtmlFile(self, path): try: f = open(path, 'wb') try: f.write(self.html) finally: f.close() except: pass def on_saveHtml_command(self, event): wildcard = "HTML files (*.html)|*.html|All files (*.*)|*.*" #wildcard = self.resource.strings.saveAsWildcard if self.documentPath is None: dir = '' filename = '*.html' else: dir = os.path.dirname(self.documentPath) filename = os.path.splitext(os.path.basename(self.documentPath))[0] + '.html' result = dialog.saveFileDialog(None, self.resource.strings.saveAs, dir, filename, wildcard) if result.accepted: path = result.paths[0] self.saveHtmlFile(path) def on_menuFormatRenderOnReturn_select(self, event): self.renderOnReturn = self.menuBar.getChecked('menuFormatRenderOnReturn') def on_doHelpRest_command(self, event): webbrowser.open('http://docutils.sourceforge.net/rst.html') def on_doHelpRestQuickReference_command(self, event): webbrowser.open('http://docutils.sourceforge.net/docs/user/rst/quickref.html') if __name__ == '__main__': app = model.Application(RestEditor) app.MainLoop() --- NEW FILE: readme.txt --- 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. |