diff options
author | rahulp13 | 2020-03-17 14:55:41 +0530 |
---|---|---|
committer | rahulp13 | 2020-03-17 14:55:41 +0530 |
commit | 296443137f4288cb030e92859ccfbe3204bc1088 (patch) | |
tree | ca4798c2da1e7244edc3bc108d81b462b537aea2 /lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra | |
parent | 0db48f6533517ecebfd9f0693f89deca28408b76 (diff) | |
download | KiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.tar.gz KiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.tar.bz2 KiCad-eSim-296443137f4288cb030e92859ccfbe3204bc1088.zip |
initial commit
Diffstat (limited to 'lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra')
452 files changed, 76912 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/AUTHORS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/AUTHORS new file mode 100644 index 0000000..37722bb --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/AUTHORS @@ -0,0 +1,35 @@ +Editra +Developer's Text Editor + +Author: +Cody Precord <cprecord@editra.org> + +Translations: +Angelo (Italian) +Anri Ito (Japanese) +Cody Precord (English/Japanese) +DR0ID (German) +gasolin (Traditional Chinese) +Gerard Petersen (Dutch) +heccj (Simplified Chinese) +Igor Chomko (Ukrainian) +Janis.sl (Latvian) +JoNNeMaNN (Norwegian Nynorsk) +mustafa (Turkish) +Raul Gonzalez Duque (Spanish) +Sergei Zivukov (Russian) +shaohao (Simplified Chinese) +slavOnic (Russian) +Peter Magnusson (Swedish) +Tomas Fryda (Czech) +Vladimir Lazic (Serbian) +And many more, see the launchpad site for a full list of contributors! + +Contributors: +DR0ID (Comment Browser) +Kevin Smith (Projects Plugin) +Laurent Dufrenchou (IPyShell) +Kurt Schelin (App Icon Design) +shaohao (Statusbar improvement patch) +Giuseppe "Cowo" Corbelli (various patches) +quode (OCaml support for Launch plugin) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/CHANGELOG b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/CHANGELOG new file mode 100644 index 0000000..89cc7ab --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/CHANGELOG @@ -0,0 +1,163 @@ +# encoding: utf-8 +Editra +Author: Cody Precord +Copyright: (c) Cody Precord 2005-2013 +License: wxWindows + +Change Log: + +#-----------------------------------------------------------------------------# +Changes since last release: + +VERSION 0.7.xx +DATE xx/xx/2013 +54th Alpha Release + +NEW: [features/enhancements] + +BUG FIXES: ++Fix some keyboard issues on OSX when Shift key has been held down. ++Fix issue with characters incorrectly getting inserted into buffer when +invoking a Redo action with nothing left to redo left in stack (OSX). ++Fix text alignment issue with PlateButton control when the button is expanded +beyond its intended best size. + +#-----------------------------------------------------------------------------# + +VERSION 0.7.20 +DATE 01/05/2013 +53rd Alpha Release + +NEW: [features/enhancements] ++Extended CSS highlighting support. Near complete support for CSS3. ++Updated FileBrowser plugin to version 2.2 (bug fixes) + +BUG FIXES: ++Handle error in style manager when default font face name is unknown. ++Fix unwanted/invalid completion issue in HTML autocompletion for open brackets +on lines with tabs in them. ++Fix PyDeadObject that could occur during reload file request. ++Fix crash that could occur during formatting of log messages. ++Handle PyDeadObject error that could occur when changing tab icons ++Don't handle Shift+Delete as forward delete on OSX (issue 721) ++Fix caret bouncing in TextCtrls on Windows (issue 664) ++Fix PyDeadObject errors related to notebook in multiple windows. ++Fix assertions caused by right clicks in certain areas of tree controls. ++Fix Line End command not working correctly in some cases on OSX. + +#-----------------------------------------------------------------------------# + +VERSION 0.7.12 +DATE 08/12/2012 +52nd Alpha Release + +NEW: [features/enhancements] + +BUG FIXES: ++Fix unable to edit file extension associations on Linux systems (issue 745). ++Fix issue with duplicated @ symbols inserted by generic completer (issue 743). ++Fix some Unicode handling issues in log handler. ++Fix bug in Tango art provider fallback code which could end up looking in +Default theme instead of Tango theme directory for mime icons. ++Fix PyDeadObject errors related to failed destruction calls by AuiManger. + +#-----------------------------------------------------------------------------# + +VERSION 0.7.08 +DATE 07/15/2012 +51st Alpha Release + +NEW: [features/enhancements] ++New version of FileBrowser Plugin version 2.0. Nearly a complete re-write of +the main part of the plugin to use a new file view. Adds ability to turn editor +tab synchronization on and off. Adds configuration for filtering files out of the +view and new configuration for showing hidden files. ++Choose directory dialog from Find Dialog will now automatically expand to the directory of the +current file. ++Update embedded aui + +BUG FIXES: ++Fix major and apparently very long standing issue on Windows systems where +application profiles were not getting updated correctly and settings would get +lost between updates. ++Fix issues with sessions not getting updated properly under some use cases. ++Fix crash condition that could occur when reload of file fails. ++Fix file encoding detection issue that some systems experienced. ++Fix UTF-16 decoding issues / regressions due to change in behavior between +python2.6 and 2.7. ++Fix error caused by empty file names getting into the file history which +could cause startup failures. ++Fix crash in Find in Directory that could occur due to threaded access to GetTranslation. + +#-----------------------------------------------------------------------------# + +VERSION 0.7.01 +DATE 04/23/2012 +50th Alpha Release + +NEWS: +Update to fix issue with translations. + +BUG FIXES: ++Fix localizations not loading correctly. + +#-----------------------------------------------------------------------------# +VERSION 0.7.00 +DATE 04/22/2012 +49th Alpha Release + +NEWS: +This is a stabilization and maintenance release targeting bugs that have been reported over the +last several months. Biggest fix is to try to correct some utf-8 handling errors +that were observed by some users of the 0.6.99 release. See release notes below +for specific changes in this release. + +NEW: [features/enhancements] ++New version of CodeBrowser plugin (bug fixes for Python / XML / HTML) ++New version of Launch (configurable line buffering, bug fixes) ++Update all translations with current launchpad. + +BUG FIXES: ++Fix error that could occur when selecting text in some environments under +certain cases. ++Fix crash that could occur during shutdown during page load. ++Fix crash that could occur when trying to retrieve binary data from clipboard to +update clipboard ring. ++Fix crash that could happen when replace in selection action finds no matches. ++Fix crash that could occur when starting Editra again immediately after closing +another running instance due to zombie IPC thread. ++Fix crash that could occur in vi emulation due to bad command mapping. ++Fix crashes that could occur when loading plugins that throw errors during +creation. ++Fix crash when system fails to return control reference when print is requested. ++Ensure requested locale is available prior to trying to create it. ++Fix incorrect line getting deleted by line delete action with some encodings. + + +#-----------------------------------------------------------------------------# + +For Alpha 0.6 Release Series Changelog see docs/CHANGELOG_7 + +#-----------------------------------------------------------------------------# + +For Alpha 0.5 Release Series Changelog see docs/CHANGELOG_6 + +#-----------------------------------------------------------------------------# + +For Alpha 0.4 Release Series Changelog see docs/CHANGELOG_5 + +#-----------------------------------------------------------------------------# + +For Alpha 0.3 Release Series Changelog see docs/CHANGELOG_4 + +#-----------------------------------------------------------------------------# + +For Alpha 0.2 Release Series Changelog see docs/CHANGELOG_3 + +#-----------------------------------------------------------------------------# + +For Alpha 0.1 Release Series Changelog see docs/CHANGELOG_2 + +#-----------------------------------------------------------------------------# + +For Pre-Alpha Changelog see docs/CHANGELOG_1
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/COPYING b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/COPYING new file mode 100644 index 0000000..e530475 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/COPYING @@ -0,0 +1,54 @@ + wxWindows Library Licence, Version 3.1 + ====================================== + + Copyright (C) 1998-2005 Julian Smart, Robert Roebling et al + + Everyone is permitted to copy and distribute verbatim copies + of this licence document, but changing it is not allowed. + + WXWINDOWS LIBRARY LICENCE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public Licence + along with this software, usually in a file named COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301, USA. + + EXCEPTION NOTICE + + 1. As a special exception, the copyright holders of this library give + permission for additional uses of the text contained in this release of + the library as licenced under the wxWindows Library Licence, applying + either version 3.1 of the Licence, or (at your option) any later version of + the Licence as published by the copyright holders of version + 3.1 of the Licence document. + + 2. The exception is that you may use, copy, link, modify and distribute + under your own terms, binary object code versions of works based + on the Library. + + 3. If you copy code from files distributed under the terms of the GNU + General Public Licence or the GNU Library General Public Licence into a + copy of this library, as this licence permits, the exception does not + apply to the code that you add in this way. To avoid misleading anyone as + to the status of such modified files, you must delete this exception + notice from such code and/or adjust the licensing conditions notice + accordingly. + + 4. If you write modifications of your own for this library, it is your + choice whether to permit this exception to apply to your modifications. + If you do not wish that, you must delete the exception notice from such + code and/or adjust the licensing conditions notice accordingly. + + + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Editra.pyw b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Editra.pyw new file mode 100644 index 0000000..e70b17a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Editra.pyw @@ -0,0 +1,79 @@ +#!/usr/bin/env python2 +############################################################################### +# Name: Editra.pyw # +# Purpose: Editra's main launch script # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + + +""" +Main launch script for the Editor. It first tries to look for Editra on the +local path and if it is not there it tries to import the Main method +from where Editra would be installed if it was installed using distutils + +@summary: Editra's main launch script for Windows + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: Editra.pyw 63538 2010-02-23 03:39:03Z CJP $" +__revision__ = "$Revision: 63538 $" + +#--------------------------------------------------------------------------# +# Dependencies +import sys +import os + +try: + import src as esrc + IS_LOCAL = True +except ImportError: + try: + import Editra as esrc + IS_LOCAL = False + except ImportError, msg: + print "There was an error while tring to import Editra" + print ("Make sure that Editra is on your PYTHONPATH and that " + "you have wxPython installed.") + print "ERROR MSG: " + print str(msg) + os._exit(1) + +#--------------------------------------------------------------------------# +# There are currently some necessary hacks for launching editra from this +# script that will hopefully be removed in the not so distance future once +# the plugin managers meta registry is redesigned. + +def main(): + # The initial import above is necessary to get the path of where + # Editra is installed so that the src package can be put on the path. + # If the src module is not on the path the plugins are unable to import + # things from inside editras namespace properly. It also causes problems + # with recongnizing plugins in Extension registry of the Plugins metaclass. + SRC_DIR = os.path.dirname(esrc.__file__) + if not IS_LOCAL: + SRC_DIR = os.path.join(SRC_DIR, 'src') + + # Cleanup any of Editras modules that are already present before + # importing Editra again so that the modules are imported with the + # correct signature (i.e ed_theme vs src.ed_theme). As the plugin + # manager currently registers the class objects metadata by using + # the classes module signature for identification. + if not IS_LOCAL: + torem = [ key for key in sys.modules.keys() + if key.startswith('Editra') ] + for key in torem: + del sys.modules[key] + else: + if 'src' in sys.modules: + del sys.modules['src'] + + sys.path.insert(0, SRC_DIR) + import Editra + Editra.Main() + + +if __name__ == '__main__': + main() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/FAQ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/FAQ new file mode 100644 index 0000000..fd3b5ac --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/FAQ @@ -0,0 +1,6 @@ +Frequently Asked Questions: + +Most common questions are answered in the project documentation please see +http://editra.org/?page=docs for a listing of how to's and other tips and tricks +about how to use Editra. + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/INSTALL b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/INSTALL new file mode 100644 index 0000000..669a7c0 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/INSTALL @@ -0,0 +1,63 @@ +Editra Installation Instructions for installing from source + +Base Dependencies: +python 2.6 or higher (http://www.python.org) +wxPython 2.8.6 or higher (http://www.wxpython.org) (Unicode build suggested) +setuptools 0.6 or higher (http://peak.telecommunity.com/DevCenter/setuptools) + +#--------------------------------------------------------------------------# +Option 1) Install Editra as a source package: [Linux/Macintosh/Unix/Windows] + +When using the source scripts Editra doesn't actually need to be installed it +can be run by un-tarring the source package and executing the script called +"Editra" in the the root of the un-tarred directory. Alternatively however, if +you want the setup.py script will allow you to install it using distutils. + +To install Editra using distutils just do the usual python thing and type: + +python setup.py install + +at your shells command prompt. + +#--------------------------------------------------------------------------# +Option 2) Installing from Pypi: [Linux/Macintosh/Unix/Windows] + +Editra is also available in the python package index and can be installed +from source using easy_install (bundled with setuptools). + +easy_install editra + +#--------------------------------------------------------------------------# +Option 3) Build a Windows exe: [Windows] + +To build an exe of Editra for Windows, py2exe (http://www.py2exe.org) must +be installed. After installing py2exe just do the following. + +python setup.py py2exe --bundle 2 + +This will build an exe and place it in .\dist\ + +#--------------------------------------------------------------------------# +Option 4) Build a MacOSX app: [Macintosh OSX] + +This requires having py2app (http://cheeseshop.python.org/pypi/py2app/) +installed. If they are installed just issue the following command to +build an applet. + +python setup.py py2app + +This will create a self contained applet in the ./dist/ directory + +#--------------------------------------------------------------------------# +Option 5) Build as an egg: [Linux/Macintosh/Unix/Windows] + +To make an Python Egg from Editra, setuptools is required. If setuptools is +installed the following command will build an egg that can be installed with +easy install (ez_install.py). + +python setup.py bdist_egg + +The Egg will be placed in ./dist/ and can be installed by doing the following + +cd dist/ +ez_install Editra-x.x.xx-pyXX.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/MANIFEST.in b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/MANIFEST.in new file mode 100644 index 0000000..2f8b2c6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/MANIFEST.in @@ -0,0 +1,25 @@ +include *.py *.pyw *.cfg +include AUTHORS +include CHANGELOG +include COPYING +include editra +include FAQ +include INSTALL +include MANIFEST +include NEWS +include README +include THANKS +include TODO +include docs/*.txt +include plugins/*.egg +include tests/controls/*.py +include tests/syntax/* +recursive-include tests/unittests *.py *.txt *.png +recursive-include include *.h +recursive-include ekeys *.ekeys +recursive-include locale *.mo +recursive-include pixmaps *.png *.ico *.icns [A-Z] +recursive-include scripts *.sh *.po *.py +recursive-include src *.py [A-Z] +recursive-include styles *.ess +recursive-include templates * diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Makefile b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Makefile new file mode 100644 index 0000000..12ea6e7 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/Makefile @@ -0,0 +1,85 @@ +# Editra Makefile +# +# Instructions: +# To make source bundle: make sdist +# To make eggs: make egg +# To make plugins: make plugin +# + +# Variables +PYVERSION = 2.5 +EGGFILTER = *py2.4.egg *py2.6.egg + +# Paths +PLUGINS = ./plugins +FILEBROWSER = $(PLUGINS)/filebrowser +PYSHELL = $(PLUGINS)/PyShell +CODEBROWSER = $(PLUGINS)/codebrowser +LAUNCH = $(PLUGINS)/Launch +I18NDIR = ./scripts/i18n + +# Generated Paths +OSXAPP = ./dist/Editra.app/ +OSXRESOURCES = $(OSXAPP)/Contents/Resources/ + +# Commands +PYTHON = python$(PYVERSION) +MAKE_PLUGIN24 = python2.4 ./setup.py bdist_egg --dist-dir=../ +MAKE_PLUGIN25 = python2.5 ./setup.py bdist_egg --dist-dir=../ +MAKE_PLUGIN26 = python2.6 ./setup.py bdist_egg --dist-dir=../ +MAKE_EGG24 = python2.4 ./setup.py bdist_egg +MAKE_EGG25 = python2.5 ./setup.py bdist_egg +MAKE_EGG26 = python2.6 ./setup.py bdist_egg + +#---- Plugins ----# + +filebrowser: + cd $(FILEBROWSER) && $(MAKE_PLUGIN24) + cd $(FILEBROWSER) && $(MAKE_PLUGIN25) + cd $(FILEBROWSER) && $(MAKE_PLUGIN26) + +pyshell: + cd $(PYSHELL) && $(MAKE_PLUGIN24) + cd $(PYSHELL) && $(MAKE_PLUGIN25) + cd $(PYSHELL) && $(MAKE_PLUGIN26) + +codebrowser: + cd $(CODEBROWSER) && $(MAKE_PLUGIN24) + cd $(CODEBROWSER) && $(MAKE_PLUGIN25) + cd $(CODEBROWSER) && $(MAKE_PLUGIN26) + +launch: + cd $(LAUNCH) && $(MAKE_PLUGIN24) + cd $(LAUNCH) && $(MAKE_PLUGIN25) + cd $(LAUNCH) && $(MAKE_PLUGIN26) + +plugins: filebrowser codebrowser pyshell launch + +docs: + cd ./scripts/gendocs && ./gen_api_docs.sh + +i18n: + cd $(I18NDIR) && ./gen_lang.sh -all + +depfiles: plugins i18n + +sdist: depfiles + $(PYTHON) ./setup.py sdist + +osx_applet: depfiles osx_app_nodeps + +osx_app_nodeps: + $(PYTHON) ./setup.py py2app + cd $(OSXRESOURCES)/plugins && rm -f $(EGGFILTER) + cd $(OSXRESOURCES)/pixmaps && rm -f *.ico + +egg: depfiles + $(MAKE_EGG24) + $(MAKE_EGG25) + $(MAKE_EGG26) + +install: depfiles + python ./setup.py install + +clean: + rm -rf *.pyc build dist src/*.pyc src/*.pyo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/NEWS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/NEWS new file mode 100644 index 0000000..19bf19e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/NEWS @@ -0,0 +1,7 @@ +Editra Project News: + +This file contains general project news and announcements. News related to +releases and current versions are contained in the CHANGELOG. + +@see CHANGELOG or docs CHANGELOG_* for latest release information + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/README new file mode 100644 index 0000000..61647da --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/README @@ -0,0 +1,40 @@ +Project Name: Editra +Author: Cody Precord +Email: cprecord@editra.org +Licence: wxWindows (see COPYING) + +#----------------------------------------------------------------------------# + +Info: + +#----------------------------------------------------------------------------# + +Compatibility: +It has been tested on the following systems, but it should run on any system +that supports python and wxpython. + +Linux: +Tested on Gentoo, Suse, and Ubuntu +Receives testing when ever my vm doesn't eat my install + +Macintosh OS X: +Primary development is on OS X so it receives the most direct testing. + +Windows XP / Windows 7 +Receives regression testing for before each release + +Dependencies: +If you wish to run the source code you will need to have the following +libraries installed. + +Required for all systems: +Python 2.6 and higher ( http://python.org ) +wxPython 2.8.6 ( http://wxpython.org ) (Unicode version) +setuptools 0.6 or higher (http://peak.telecommunity.com/DevCenter/setuptools) +#----------------------------------------------------------------------------# + +INSTALLATION: + +see INSTALL + +#----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/THANKS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/THANKS new file mode 100644 index 0000000..3729d17 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/THANKS @@ -0,0 +1,12 @@ +Editra is made possible by the following "free" technologies and +the communities that develop them. + +Python Programming Language (http://www.python.org) +wxPython Class Library (http://www.wxpython.org) +setuptools (http://peak.telecommunity.com/DevCenter/setuptools) +py2app (http://undefined.org/python/#py2app) +py2exe (http://py2exe.org) +pygments (http://pygments.org) + +The primary icon theme 'Tango' is derived from the Tango set of icons +http://tango.freedesktop.org diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/TODO b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/TODO new file mode 100644 index 0000000..c7509ad --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/TODO @@ -0,0 +1,17 @@ +This file serves as a scratch place for some ideas about things that are wanted +in the editor or that would be nice to have. A more formal listing is available +on the projects issue tracker page http://code.google.com/p/editra/issues/list + +This is a partial list of planned features that are yet to be implemented. + +Planned Features: + +Core: +- Full command mode to remove need for mouse interaction (initial basic version to be available after 0.1.78) +- Builtin help/documentation browser +- Extensions to current syntax stylesheet language to allow for per language style definitions +- Runtime loading/unloading of plugins (works for some plugins) + +Plugin: +- Terminal, builtin system shell control (partially implemented osx/gtk) + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/__init__.py new file mode 100644 index 0000000..c5efd18 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/__init__.py @@ -0,0 +1,13 @@ +############################################################################### +# Name: __init__.py # +# Purpose: Put the src package in the Editra packages namespace # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +"""Main package initializer""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: __init__.py 49807 2007-11-10 07:08:33Z CJP $" +__revision__ = "$Revision: 49807 $" diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/docs/editra_style_sheets.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/docs/editra_style_sheets.txt new file mode 100644 index 0000000..4d861ad --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/docs/editra_style_sheets.txt @@ -0,0 +1,180 @@ +SPECIFICATION: Editra Style Sheet +REVISION: 1.6 + +PURPOSE: Define the format for writing custom style sheets that allow for the + customization of the color scheme used to highlight text in the editor + when Syntax Highlighting is enabled. + +VERSION INFO: In this initial incarnation the style sheets will only allow you + use the "Standard Tags" and "Standard Attributes" all other + definitions will be ignored by the parser. There are however + plans to make the style sheets extensible in the future to allow + for the setting of custom tags and subclassing styles to only + apply to a particular lexer. These features will likely be + introduced in the version 2 of this specification. + +FILE EXTENSION: ess + +SYNTAX: The syntax of an Editra Style Sheet is very similar to that of a + Cascading Style Sheet (CSS). It uses "tags" followed by the style + definition enclosed in {}'s. Attribute keywords are followed by a + colon and then the attribute values. A semicolon is used at the end of + each attribute definition as a delimiter between definitions. Comments + can be specified by placing text in between '/* */'. + +BEHAVIOR: The 'default_style' tag must be defined and must define all four of + the default attributes (fore, back, face, size). All other tags with + undefined values will inherit them from this style definition. + +STATEMENT FORMAT: + + tag_name { + attribute1: value; + attribute2: value modifier; + } + +STYLE GUIDELINES: + Although the parser is rather flexible and will allow you to define + your entire set of style definitions on one line this is very poor for + readability, so the following specifications are suggested. + + Tags should be un-indented and all in lower case. Following the tag + should be 1 space and an opening curly bracket '{'. The following + line should contain the first attribute definition. This definition + should start indented 1-4 spaces past the opening curly bracket and + be all in lower case. All following attribute definitions should be + on their own line and indented to the same level as first attribute + definition. The line immediately following the last attribute definition + contains the closing curly bracket '}' which should be unindented and + lined up with the beginning of the Tag definition. + +STANDARD TAGS: + - brace_good: This tag defines the style for highlighting matching braces + - brace_bad: This tag defines the style for highlighting unmatched braces + - calltip: Style to color calltip windows in + - ctrl_char: Style for control characters (Tabs, Spaces, ect...) + - line_num: Style of the line numbers in the outer left margin + - array_style: Style of arrays (currently used in perl documents) + - btick_style: Style of Back Ticks + - default_style: Style of all text not styled by other definitions + - caret_line: Sets caret line background highlight color + - char_style: Style of characters (i.e 'c') + - class_style: Style of class defs (i.e def MyClass) + - class2_style: Currently unused + - clear: Sets foreground to black, background to white + - comment_style: Style of code comment blocs + - decor_style: Style for decorators + - directive_style: Style of directives + - dockey_style: Style of documentation keywords + - error_style: Style of errors + - foldmargin_style: Style of code folding margin and markers + - funct_style: Style of Functions + - global_style: Style of global variables + - guide_style: indentation guide style + - here_style: Used to highlight HERE statements + - ideol_style: Id End of Line (used in Makefiles) + - keyword_style: Style of Primary Keywords + - keyword2_style: Style of Secondary/Type Keywords + - keyword3_style: Style of extra keywords + - keyword4_style: Style of extra/user defined keywords + - marker_style: Style for bookmarks/margin markers + - number_style: Style of numbers + - number2_style: Alternate style for numbers/verbatim defs + - operator_style: Style of Operators (i.e + = *) + - pre_style: Style of Preprocessor + - pre2_style: Alternate Preprocessor style + - regex_style: Style of Regular Expressions + - scalar_style: Style of Scalar Variables + - scalar2_style: Alternate style for Scalar Variables + - select_style: Style of text selection background + - string_style: Style of Strings (i.e "hello") + - stringeol_style: Style of unclosed strings (i.e "hello ) + - unknown_style: Style of unknown statements + - userkw_style: Style for some builins and user defined keywords + +STANDARD ATTRIBUTES: + - back: Defines the style of the background for the tags text area. The + acceptable values are any 6 digit HEX color code (i.e #123456) + optionally followed by a modifier (see MODIFIERS). + - face: Defines the Font used by a fonts face name. The values accepted + by this attribute are either a Face name (i.e Monaco) or a + format expression (recommended) (i.e %(mono)s). The use of + format expressions is recommended because it will allow your + style sheet to work on all platforms, as it will let Editra's + Style Manager look up an appropriate/available system font. + See FONT KEYS for more information on available format + expressions. + - fore: Defines the foreground/face color/style of the tags text area. + The acceptable values are any 6 digit HEX color code (i.e #123456) + optionally followed by a modifier (see MODIFIERS). + - size: Defines the Point Size of the font in the tags text area. The + acceptable values are any system supported font size (i.e 12) + or a format expression (i.e %(size)d). See FONT KEYS for more + information on available format expressions. + - modifiers: Defines style modifiers 'bold underline italic eol' + +FONT KEYS: + The listed values below are used in format expressions to define what + font is used. To use these keys use the following expression in your + face definitions and substitute the 'xxx' with your chosen key. + + Standard Expression: %(xxx)s + + - primary: Users prefered primary font + - secondary: Users prefered secondary font + + The next set of values are used in font size format expressions. To + use these values replace the 'xxx' in the following expression with + the chosen value. + + Standard Expression: %(xxx)d + + - size: The point size of the primary font + - size2: The point size of the secondary font + - size3: 2 point sizes smaller than "size" + +MODIFIERS: + These keywords are used to modify style attributes. + + - bold: Makes the text in the tags text area bold + - italic: Makes the text in the tags text area italicized + - eol: Extends the given attributes style to the end of the line + - underline: Enables underlining for a text area + + Modifiers can be either appended to the values defined in a standard + attribute or specifed in the _modifiers_ attribute. + +SPECIAL TAGS: + These tags are part of the standard tags but behave differently than + a typical tag. The differences in behavior are mostly transparent but + here is an explanation of each. + + - calltip: Only Foreground and Background attributes are used + - caret_line: Only Background attribute is used + - clear: Used internally any definitions will be ignored + - foldmargin_style: Only Foreground and Background attributes are used + - marker_style: Only Foreground and Background attributes are used + - select_style: When defined only the Background attribute is used. If + this style is not defined then the default system colour + for selection highlight is used in its place. + +EXAMPLES: + + /* Comment about this style */ + default_style { + fore: #000000; + back: #FFFFFF; /* use a white background */ + face: %(primary)s; + size: %(size)d; + } + + keyword_style { + fore: #A52B2B bold; + face: Courier; + size: 14; + } + + keyword2_style { + fore: #F0F660; + modifiers: italic underline; + } diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra new file mode 100644 index 0000000..7bbf80e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra @@ -0,0 +1,79 @@ +#!/usr/bin/env python2 +############################################################################### +# Name: Editra # +# Purpose: Editra's main launch script # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + + +""" +Main launch script for the Editor. It first tries to look for Editra on the +local path and if it is not there it tries to import the Main method +from where Editra would be installed if it was installed using disutils + +@summary: Editra's main launch script + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: Exp $" +__revision__ = "$Revision: $" + +#--------------------------------------------------------------------------# +# Dependencies +import sys +import os + +try: + import src as esrc + IS_LOCAL = True +except ImportError: + try: + import Editra as esrc + IS_LOCAL = False + except ImportError, msg: + print "There was an error while tring to import Editra" + print ("Make sure that Editra is on your PYTHONPATH and that " + "you have wxPython installed.") + print "ERROR MSG: " + print str(msg) + os._exit(1) + +#--------------------------------------------------------------------------# +# There are currently some necessary hacks for launching editra from this +# script that will hopefully be removed in the not so distance future once +# the plugin managers meta registry is redesigned. + +def main(): + # The initial import above is necessary to get the path of where + # Editra is installed so that the src package can be put on the path. + # If the src module is not on the path the plugins are unable to import + # things from inside editras namespace properly. It also causes problems + # with recognizing plugins in Extension registry of the Plugins metaclass. + SRC_DIR = os.path.dirname(esrc.__file__) + if not IS_LOCAL: + SRC_DIR = os.path.join(SRC_DIR, 'src') + + # Cleanup any of Editras modules that are already present before + # importing Editra again so that the modules are imported with the + # correct signature (i.e ed_theme vs src.ed_theme). As the plugin + # manager currently registers the class objects metadata by using + # the classes module signature for identification. + if not IS_LOCAL: + torem = [ key for key in sys.modules.keys() + if key.startswith('Editra') ] + for key in torem: + del sys.modules[key] + else: + if 'src' in sys.modules: + del sys.modules['src'] + + sys.path.insert(0, SRC_DIR) + import Editra + Editra.Main() + + +if __name__ == '__main__': + main() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra-installer.nsi b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra-installer.nsi new file mode 100644 index 0000000..1201779 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra-installer.nsi @@ -0,0 +1,232 @@ +;------------------------------------------------------------------------------ +; Editra Windows Installer Build Script +; Author: Cody Precord +; Language: NSIS +; Licence: wxWindows License +;------------------------------------------------------------------------------ + + +;------------------------------ Start MUI Setup ------------------------------- + +; Global Variables +!define PRODUCT_NAME "Editra" +!define PRODUCT_VERSION "0.7.20" +!define PRODUCT_PUBLISHER "Cody Precord" +!define PRODUCT_WEB_SITE "http://editra.org" +!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${PRODUCT_NAME}.exe" +!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +!define PRODUCT_UNINST_ROOT_KEY "HKLM" + +SetCompressor lzma + +; MUI 1.67 compatible ------ +!include "MUI.nsh" + +; MUI Settings +!define MUI_ABORTWARNING +!define MUI_ICON "pixmaps\editra.ico" +!define MUI_UNICON "pixmaps\editra.ico" +!define MUI_FILEICON "pixmaps\editra_doc.png" + +; Welcome page +!insertmacro MUI_PAGE_WELCOME +; License page (Read the Licence) +!insertmacro MUI_PAGE_LICENSE "COPYING" +; Components Page (Select what parts to install) +!insertmacro MUI_PAGE_COMPONENTS +; Directory page (Set Where to Install) +!insertmacro MUI_PAGE_DIRECTORY +; Instfiles page (Do the installation) +!insertmacro MUI_PAGE_INSTFILES +; Finish page (Post installation tasks) +!define MUI_FINISHPAGE_RUN +!define MUI_FINISHPAGE_RUN_TEXT "Run Editra" +!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchEditra" +!insertmacro MUI_PAGE_FINISH + +; Un-Installer pages +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_COMPONENTS +!insertmacro MUI_UNPAGE_INSTFILES +!insertmacro MUI_UNPAGE_FINISH + +; Language files +!insertmacro MUI_LANGUAGE "English" + +; Reserve files +!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +;------------------------------- End MUI Setup -------------------------------- + + +;------------------------------ Start Installer ------------------------------- + +;---- Constants +Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" +OutFile "editra.win32.${PRODUCT_VERSION}.exe" +InstallDir "$PROGRAMFILES\${PRODUCT_NAME}" +InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "" +ShowInstDetails show +ShowUnInstDetails show + +RequestExecutionLevel admin + +;---- !defines for use with SHChangeNotify +!ifdef SHCNE_ASSOCCHANGED +!undef SHCNE_ASSOCCHANGED +!endif +!define SHCNE_ASSOCCHANGED 0x08000000 + +!ifdef SHCNF_FLUSH +!undef SHCNF_FLUSH +!endif +!define SHCNF_FLUSH 0x1000 + +; Prepare for installation +Function .onInit + ; prevent running multiple instances of the installer + System::Call 'kernel32::CreateMutexA(i 0, i 0, t "editra_installer") i .r1 ?e' + Pop $R0 + StrCmp $R0 0 +3 + MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running." + Abort + + ; Check for existing installation warn before installing new one + ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" + StrCmp $R0 "" done + + MessageBox MB_YESNO|MB_ICONEXCLAMATION \ + "An existing installation of Editra has been found. $\nDo you want to remove the previous version before installing $(^Name) ?" \ + IDNO done + + ; Run the uninstaller + ClearErrors + ExecWait '$R0 _?=$INSTDIR' ; Do not copy the uninstaller to a temp file + + done: +FunctionEnd + +; Extract the files from the installer to the install location +Section "Editra Core" SEC01 + SectionIn RO 1 2 + + ; Check that Editra is not running before starting to copy the files + FindProcDLL::FindProc "${PRODUCT_NAME}.exe" + StrCmp $R0 0 continueInstall + MessageBox MB_ICONSTOP|MB_OK "${PRODUCT_NAME} is still running please close all running instances and try to install again" + Abort + continueInstall: + + ; Extract the files and make shortcuts + SetOverwrite try + SetOutPath "$INSTDIR\" + File /r ".\*.*" + + ; Add the shortcuts to the start menu and desktop + SetShellVarContext all + CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe" "" "$INSTDIR\${MUI_ICON}" + CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe" "" "$INSTDIR\${MUI_ICON}" +SectionEnd + +; Enabled if Add openwith entry is checked +Section "Context Menus" SEC02 + SectionIn 1 + WriteRegStr HKCR "*\shell\OpenWithEditra" "" "Edit with ${PRODUCT_NAME}" + WriteRegStr HKCR "*\shell\OpenWithEditra\command" "" '$INSTDIR\${PRODUCT_NAME}.exe "%1"' +; WriteRegStr HKCR "*\shell\OpenWithEditra\DefaultIcon" "" "${MUI_FILEICON}" + + ; Notify of the shell extension changes + System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_FLUSH}, i 0, i 0)' +SectionEnd + +; Add QuickLaunch Icon (That small icon bar next to the start button) +Section "Add Quick Launch Icon" SEC03 + SectionIn 1 + CreateShortCut "$QUICKLAUNCH\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_NAME}.exe" +SectionEnd + +; Make/Install Shortcut links +Section -AdditionalIcons + WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}" + SetShellVarContext all + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url" + CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe" "" "$INSTDIR\${MUI_UNICON}" +SectionEnd + +; Post installation setup +Section -Post + ;---- Write registry keys for uninstaller + WriteUninstaller "$INSTDIR\uninst.exe" + WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${PRODUCT_NAME}.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\${MUI_UNICON}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" +SectionEnd + +; Called if Run Editra is checked on the last page of installer +Function LaunchEditra + Exec '"$INSTDIR\${PRODUCT_NAME}.exe" "$INSTDIR\CHANGELOG" ' +FunctionEnd + +; Description Texts for Component page +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "Required core program files" + !insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "Add context menu item 'Edit with ${PRODUCT_NAME}'" + !insertmacro MUI_DESCRIPTION_TEXT ${SEC03} "Add shortcut to Quick Launch Bar" +!insertmacro MUI_FUNCTION_DESCRIPTION_END + +;------------------------------- End Installer -------------------------------- + +;----------------------------- Start Uninstaller ------------------------------ + +;Function un.onInit +;FunctionEnd + +; Cleans up registry, links, and main program files +Section "un.Program Data" UNSEC01 + SectionIn RO 1 + + ; Ensure shortcuts are removed from user directory as well + RmDir /r "$SMPROGRAMS\${PRODUCT_NAME}" + Delete "$DESKTOP\${PRODUCT_NAME}.lnk" + Delete "$QUICKLAUNCH\${PRODUCT_NAME}.lnk" + + ; Remove all shortcuts from All Users directory + SetShellVarContext all + RmDir /r "$SMPROGRAMS\${PRODUCT_NAME}" + Delete "$DESKTOP\${PRODUCT_NAME}.lnk" + Delete "$QUICKLAUNCH\${PRODUCT_NAME}.lnk" + + ; Cleanup Registry + DeleteRegKey HKCR "*\shell\OpenWithEditra" + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" + DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" + + ; Remove all Files + RmDir /r "$INSTDIR\" + + SetAutoClose false +SectionEnd + +; Optionally cleans up user data/plugins +Section /o "un.User settings and plugins" UNSEC02 + SectionIn 1 + SetShellVarContext current ; Current user only + RmDir /r "$APPDATA\${PRODUCT_NAME}" ; Remove app generated config data/plugins + RmDir /r "$LOCALAPPDATA\${PRODUCT_NAME}" ; Remove app generated config data/plugins +SectionEnd + +;Function un.onUninstSuccess +;FunctionEnd + +; Description Texts for Component page +!insertmacro MUI_UNFUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${UNSEC01} "Core program files" + !insertmacro MUI_DESCRIPTION_TEXT ${UNSEC02} "User settings and plugins" +!insertmacro MUI_UNFUNCTION_DESCRIPTION_END + +;------------------------------ End Uninstaller ------------------------------- diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra_pylintrc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra_pylintrc new file mode 100644 index 0000000..8da2463 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/editra_pylintrc @@ -0,0 +1,26 @@ +# Pylint Configuration File for Editra +# Allow for CamelCase nameing convention used for functions and other +# conventions used in Editra. + +# To use this file either: +# 1) Copy it to $HOME/.pylintrc and run pylint normally +# +# OR +# +# 2) When running pylint use the following command +# pylint --rcfile=editra_pylintrc +# + +[BASIC] +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z_][a-zA-Z0-9_]+))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-zA-Z_][a-zA-Z0-9]*$ + +# Regular expression which should only match correct method names +method-rgx=[a-zA-Z_][a-zA-Z0-9]*|(__.*__)$ + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/launcher.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/launcher.py new file mode 100644 index 0000000..dffb818 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/launcher.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python2 + +# This module provides an importable module that can do the same +# things as the Editra script, namely, set up the sys.path and +# sys.modules for Editra and then start Editra running. This is done +# by using execfile() to execute the code in the Editra script as if +# it was in this module, and then the importer of this module can call +# the main() function defined there. + +import os +launcher = os.path.join(os.path.dirname(__file__), 'Editra') +execfile(launcher) + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ca_ES@valencia/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ca_ES@valencia/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..c62fe72 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ca_ES@valencia/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/cs_CZ/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/cs_CZ/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..f506f91 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/cs_CZ/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/da_DK/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/da_DK/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..3e9a4d1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/da_DK/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/de_DE/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/de_DE/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..e6568f1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/de_DE/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/en_US/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/en_US/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..ca8d266 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/en_US/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/es_ES/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/es_ES/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..ad56138 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/es_ES/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/fr_FR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/fr_FR/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..3f9c709 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/fr_FR/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/gl_ES/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/gl_ES/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..37720ac --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/gl_ES/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hr_HR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hr_HR/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..77d9cab --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hr_HR/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hu_HU/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hu_HU/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..0bdf474 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/hu_HU/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/it_IT/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/it_IT/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..ea92d3a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/it_IT/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ja_JP/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ja_JP/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..71c50de --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ja_JP/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/lv_LV/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/lv_LV/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..0e5c298 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/lv_LV/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nl_NL/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nl_NL/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..1ef3e60 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nl_NL/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nn_NO/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nn_NO/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..8b5468c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/nn_NO/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pl_PL/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pl_PL/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..c2babb2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pl_PL/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pt_BR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pt_BR/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..f046296 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/pt_BR/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ro_RO/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ro_RO/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..84b6e0e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ro_RO/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ru_RU/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ru_RU/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..11ef554 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/ru_RU/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sk_SK/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sk_SK/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..0f3ca66 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sk_SK/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sl_SI/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sl_SI/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..f4ee2ad --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sl_SI/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sr_RS/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sr_RS/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..e5ab0e5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sr_RS/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sv_SE/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sv_SE/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..3c562b8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/sv_SE/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/tr_TR/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/tr_TR/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..02b4c5a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/tr_TR/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/uk_UA/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/uk_UA/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..414df4b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/uk_UA/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_CN/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_CN/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..fee93b9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_CN/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_TW/LC_MESSAGES/Editra.mo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_TW/LC_MESSAGES/Editra.mo Binary files differnew file mode 100644 index 0000000..5f29fa2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/locale/zh_TW/LC_MESSAGES/Editra.mo diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/Editra.icns b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/Editra.icns Binary files differnew file mode 100644 index 0000000..177778a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/Editra.icns diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.ico b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.ico Binary files differnew file mode 100644 index 0000000..ce7555e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.ico diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.png Binary files differnew file mode 100644 index 0000000..47e4894 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra256.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra256.png Binary files differnew file mode 100644 index 0000000..67b2cd5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra256.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra64.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra64.png Binary files differnew file mode 100644 index 0000000..1a5d33c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra64.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icns b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icns Binary files differnew file mode 100644 index 0000000..a1f76a9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.icns diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.ico b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.ico Binary files differnew file mode 100644 index 0000000..cf44d48 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.ico diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.png Binary files differnew file mode 100644 index 0000000..1809a83 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/editra_doc.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/splashwarn.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/splashwarn.png Binary files differnew file mode 100644 index 0000000..c11633b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/splashwarn.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Default/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Default/README new file mode 100644 index 0000000..2b1ce62 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Default/README @@ -0,0 +1,2 @@ +The Default theme is provided by the host operating system this directory is +just here to provide uniformity in organizing the themes. diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/AUTHORS b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/AUTHORS new file mode 100644 index 0000000..c54ec5b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/AUTHORS @@ -0,0 +1,9 @@ +Ulisse Perusin <uli.peru@gmail.com> +Steven Garrity <sgarrity@silverorange.com> +Lapo Calamandrei <calamandrei@gmail.com> +Ryan Collier <rcollier@novell.com> +Rodney Dawes <dobey@novell.com> +Andreas Nilsson <nisses.mail@home.se> +Tuomas Kuosmanen <tigert@tigert.com> +Garrett LeSage <garrett@novell.com> +Jakub Steiner <jimmac@novell.com> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/COPYING b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/COPYING new file mode 100644 index 0000000..e709d0c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/COPYING @@ -0,0 +1,67 @@ +Creative Commons Attribution-ShareAlike 2.5 License Agreement + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. + +1. Definitions + + 1. "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License. + 2. "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License. + 3. "Licensor" means the individual or entity that offers the Work under the terms of this License. + 4. "Original Author" means the individual or entity who created the Work. + 5. "Work" means the copyrightable work of authorship offered under the terms of this License. + 6. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. + 7. "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike. + +2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: + + 1. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works; + 2. to create and reproduce Derivative Works; + 3. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works; + 4. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works. + 5. + + For the avoidance of doubt, where the work is a musical composition: + 1. Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work. + 2. Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights society or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions). + 6. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions). + +The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved. + +4. Restrictions.The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: + + 1. You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(c), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(c), as requested. + 2. You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License. + 3. If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + 1. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. + 2. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. + +8. Miscellaneous + + 1. Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. + 2. Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. + 3. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. + 4. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. + 5. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. + +Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. + +Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, neither party will use the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. + +Creative Commons may be contacted at http://creativecommons.org/. diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/about.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/about.png Binary files differnew file mode 100644 index 0000000..f1f7e17 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/about.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/add.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/add.png Binary files differnew file mode 100644 index 0000000..68cf2db --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/add.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/advanced.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/advanced.png Binary files differnew file mode 100644 index 0000000..b4bce31 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/advanced.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/attribute.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/attribute.png Binary files differnew file mode 100644 index 0000000..1c570d2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/attribute.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/backward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/backward.png Binary files differnew file mode 100644 index 0000000..a1604e7 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/backward.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bin_file.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bin_file.png Binary files differnew file mode 100644 index 0000000..eafb0e1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bin_file.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_add.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_add.png Binary files differnew file mode 100644 index 0000000..ac8981c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_add.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_next.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_next.png Binary files differnew file mode 100644 index 0000000..5cdc0b4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_next.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_pre.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_pre.png Binary files differnew file mode 100644 index 0000000..b8a2414 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/bmark_pre.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cdrom.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cdrom.png Binary files differnew file mode 100644 index 0000000..8881f4f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cdrom.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/class.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/class.png Binary files differnew file mode 100644 index 0000000..34d7f0e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/class.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/computer.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/computer.png Binary files differnew file mode 100644 index 0000000..be87e5a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/computer.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/copy.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/copy.png Binary files differnew file mode 100644 index 0000000..94dd2f7 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/copy.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cut.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cut.png Binary files differnew file mode 100644 index 0000000..268aeff --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/cut.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete.png Binary files differnew file mode 100644 index 0000000..7bf849a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete_all.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete_all.png Binary files differnew file mode 100644 index 0000000..57b9a8b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/delete_all.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/doc_props.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/doc_props.png Binary files differnew file mode 100644 index 0000000..c20a00e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/doc_props.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/docs.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/docs.png Binary files differnew file mode 100644 index 0000000..01dc4b6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/docs.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/down.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/down.png Binary files differnew file mode 100644 index 0000000..e9ba46b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/down.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/element.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/element.png Binary files differnew file mode 100644 index 0000000..5ae6644 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/element.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/file.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/file.png Binary files differnew file mode 100644 index 0000000..7999cd8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/file.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/find.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/find.png Binary files differnew file mode 100644 index 0000000..54c6257 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/find.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/findr.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/findr.png Binary files differnew file mode 100644 index 0000000..f5ab368 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/findr.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/floppy.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/floppy.png Binary files differnew file mode 100644 index 0000000..9f26ed9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/floppy.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/folder.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/folder.png Binary files differnew file mode 100644 index 0000000..a185148 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/folder.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/font.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/font.png Binary files differnew file mode 100644 index 0000000..9008b0f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/font.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/forward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/forward.png Binary files differnew file mode 100644 index 0000000..58da8ed --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/forward.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/function.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/function.png Binary files differnew file mode 100644 index 0000000..d04c1a0 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/function.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/harddisk.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/harddisk.png Binary files differnew file mode 100644 index 0000000..968a61d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/harddisk.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/html_gen.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/html_gen.png Binary files differnew file mode 100644 index 0000000..c5173fe --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/html_gen.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/indent.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/indent.png Binary files differnew file mode 100644 index 0000000..5162a2e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/indent.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/log.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/log.png Binary files differnew file mode 100644 index 0000000..9ad202b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/log.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/mail.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/mail.png Binary files differnew file mode 100644 index 0000000..9987021 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/mail.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/method.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/method.png Binary files differnew file mode 100644 index 0000000..d04c1a0 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/method.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/new.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/new.png Binary files differnew file mode 100644 index 0000000..55ffb50 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/new.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newfolder.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newfolder.png Binary files differnew file mode 100644 index 0000000..e2f46a4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newfolder.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newwin.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newwin.png Binary files differnew file mode 100644 index 0000000..5b9171b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/newwin.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/open.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/open.png Binary files differnew file mode 100644 index 0000000..c66fc78 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/open.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/outdent.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/outdent.png Binary files differnew file mode 100644 index 0000000..103011e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/outdent.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/package.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/package.png Binary files differnew file mode 100644 index 0000000..14d2c07 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/package.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/paste.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/paste.png Binary files differnew file mode 100644 index 0000000..87183f1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/paste.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/plugin.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/plugin.png Binary files differnew file mode 100644 index 0000000..0f66d8d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/plugin.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pref.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pref.png Binary files differnew file mode 100644 index 0000000..66e456e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pref.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/print.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/print.png Binary files differnew file mode 100644 index 0000000..5482803 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/print.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/printpre.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/printpre.png Binary files differnew file mode 100644 index 0000000..9ace126 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/printpre.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/property.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/property.png Binary files differnew file mode 100644 index 0000000..e10cea8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/property.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pyshell.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pyshell.png Binary files differnew file mode 100644 index 0000000..178852e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/pyshell.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/quit.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/quit.png Binary files differnew file mode 100644 index 0000000..88dc4e6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/quit.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/readonly.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/readonly.png Binary files differnew file mode 100644 index 0000000..0055c1e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/readonly.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/redo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/redo.png Binary files differnew file mode 100644 index 0000000..ade0639 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/redo.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/refresh.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/refresh.png Binary files differnew file mode 100644 index 0000000..16c1259 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/refresh.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/remove.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/remove.png Binary files differnew file mode 100644 index 0000000..84234d4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/remove.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/rtf_gen.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/rtf_gen.png Binary files differnew file mode 100644 index 0000000..8d12869 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/rtf_gen.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/save.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/save.png Binary files differnew file mode 100644 index 0000000..0909f37 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/save.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/saveas.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/saveas.png Binary files differnew file mode 100644 index 0000000..49d8c19 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/saveas.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/selectall.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/selectall.png Binary files differnew file mode 100644 index 0000000..1aebeba --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/selectall.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/stop.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/stop.png Binary files differnew file mode 100644 index 0000000..a993581 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/stop.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/style_edit.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/style_edit.png Binary files differnew file mode 100644 index 0000000..edc9815 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/style_edit.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/tex_gen.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/tex_gen.png Binary files differnew file mode 100644 index 0000000..90ae6a3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/tex_gen.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/theme.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/theme.png Binary files differnew file mode 100644 index 0000000..8df60d8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/theme.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/undo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/undo.png Binary files differnew file mode 100644 index 0000000..835da89 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/undo.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/up.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/up.png Binary files differnew file mode 100644 index 0000000..50afa18 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/up.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/usb.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/usb.png Binary files differnew file mode 100644 index 0000000..70ba6e3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/usb.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/variable.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/variable.png Binary files differnew file mode 100644 index 0000000..7d35962 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/variable.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/web.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/web.png Binary files differnew file mode 100644 index 0000000..e25daf1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/menu/web.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/boo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/boo.png Binary files differnew file mode 100644 index 0000000..1256cdf --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/boo.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/css.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/css.png Binary files differnew file mode 100644 index 0000000..8df50ac --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/css.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/html.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/html.png Binary files differnew file mode 100644 index 0000000..8df50ac --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/html.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/java.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/java.png Binary files differnew file mode 100644 index 0000000..4dc6e8b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/java.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/php.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/php.png Binary files differnew file mode 100644 index 0000000..3367c85 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/php.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/python.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/python.png Binary files differnew file mode 100644 index 0000000..9ee9e1b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/python.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/ruby.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/ruby.png Binary files differnew file mode 100644 index 0000000..4ffeb64 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/ruby.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/shell.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/shell.png Binary files differnew file mode 100644 index 0000000..8b45d61 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/shell.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/text.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/text.png Binary files differnew file mode 100644 index 0000000..7999cd8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/mime/text.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/other/doc_props.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/other/doc_props.png Binary files differnew file mode 100644 index 0000000..f04c55c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/other/doc_props.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/advanced.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/advanced.png Binary files differnew file mode 100644 index 0000000..5e98ae2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/advanced.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/backward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/backward.png Binary files differnew file mode 100644 index 0000000..71bc112 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/backward.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/copy.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/copy.png Binary files differnew file mode 100644 index 0000000..618fa52 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/copy.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/cut.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/cut.png Binary files differnew file mode 100644 index 0000000..0496a6b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/cut.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/doc_props.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/doc_props.png Binary files differnew file mode 100644 index 0000000..b71d771 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/doc_props.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/find.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/find.png Binary files differnew file mode 100644 index 0000000..424708f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/find.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/findr.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/findr.png Binary files differnew file mode 100644 index 0000000..38bb117 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/findr.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/forward.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/forward.png Binary files differnew file mode 100644 index 0000000..bccdbbd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/forward.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/new.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/new.png Binary files differnew file mode 100644 index 0000000..2ab0d6f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/new.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/open.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/open.png Binary files differnew file mode 100644 index 0000000..db1cae6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/open.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/package.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/package.png Binary files differnew file mode 100644 index 0000000..6c618c6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/package.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/paste.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/paste.png Binary files differnew file mode 100644 index 0000000..a8b1d49 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/paste.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/pref.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/pref.png Binary files differnew file mode 100644 index 0000000..4272f55 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/pref.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/print.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/print.png Binary files differnew file mode 100644 index 0000000..bd24def --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/print.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/redo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/redo.png Binary files differnew file mode 100644 index 0000000..5668316 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/redo.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/save.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/save.png Binary files differnew file mode 100644 index 0000000..70b950e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/save.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/theme.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/theme.png Binary files differnew file mode 100644 index 0000000..aaa8229 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/theme.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/undo.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/undo.png Binary files differnew file mode 100644 index 0000000..34dd7e6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/undo.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/web.png b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/web.png Binary files differnew file mode 100644 index 0000000..ec8246b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/pixmaps/theme/Tango/toolbar/web.png diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.6.egg Binary files differnew file mode 100644 index 0000000..c13ca10 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.6.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.7.egg Binary files differnew file mode 100644 index 0000000..47b5d90 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/CodeBrowser-1.5-py2.7.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.6.egg Binary files differnew file mode 100644 index 0000000..39b7606 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.6.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.7.egg Binary files differnew file mode 100644 index 0000000..2228cb5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/FileBrowser-2.2-py2.7.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.6.egg Binary files differnew file mode 100644 index 0000000..5604b7d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.6.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.7.egg Binary files differnew file mode 100644 index 0000000..ff2a455 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/Launch-1.13-py2.7.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.6.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.6.egg Binary files differnew file mode 100644 index 0000000..7b7f8c1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.6.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.7.egg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.7.egg Binary files differnew file mode 100644 index 0000000..90c8cfe --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/plugins/PyShell-0.8-py2.7.egg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.cfg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.cfg new file mode 100644 index 0000000..ee24731 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.cfg @@ -0,0 +1,5 @@ +[easy_install] + +find_links = http://editra.org/uploads/src/ + http://editra.org/uploads/egg/ + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.py new file mode 100644 index 0000000..dd49ac9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/setup.py @@ -0,0 +1,640 @@ +#!/usr/bin/env python2 +############################################################################### +# Name: setup.py # +# Purpose: Setup/build script for Editra # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008-2013 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" + Editra Setup Script + + USAGE: + + 1) Windows: + - python setup.py py2exe + + 2) MacOSX: + - python setup.py py2app + + 3) Boil an Egg + - python setup.py bdist_egg + + 4) Install as a python package + - python setup.py install + - '--no-clean' can be specified to skip old file cleanup + + @summary: Used for building the editra distribution files and installations + +""" +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: setup.py 73347 2013-01-05 19:58:31Z CJP $" +__revision__ = "$Revision: 73347 $" + +#---- Imports ----# +import os +import sys +import glob +import shutil +import zipfile +import time +import src.info as info +import src.syntax.synextreg as synextreg # So we can get file extensions + +# Version Check(s) +if sys.version_info < (2, 5): + sys.stderr.write("[ERROR] Not a supported Python version. Need 2.5+\n") + sys.exit(1) + +try: + import wx +except ImportError: + if 'bdist_egg' not in sys.argv: + sys.stderr.write("[ERROR] wxPython2.8 is required.\n") + sys.exit(1) +else: + if wx.VERSION < (2, 8, 8): + sys.stderr.write("[ERROR] wxPython 2.8.8+ is required.\n") + sys.exit(1) + +#---- System Platform ----# +__platform__ = os.sys.platform + +#---- Global Settings ----# +APP = ['src/Editra.py'] +AUTHOR = "Cody Precord" +AUTHOR_EMAIL = "staff@editra.org" +YEAR = 2013 + +CLASSIFIERS = [ + 'Development Status :: 3 - Alpha', + 'Environment :: MacOS X', + 'Environment :: Win32 (MS Windows)', + 'Environment :: X11 Applications :: GTK', + 'Intended Audience :: Developers', + 'Intended Audience :: Information Technology', + 'Intended Audience :: End Users/Desktop', + 'License :: OSI Approved', + 'Natural Language :: English', + 'Natural Language :: Chinese (Simplified)', + 'Natural Language :: Chinese (Traditional)', + 'Natural Language :: Croatian', + 'Natural Language :: Czech', + 'Natural Language :: Danish', + 'Natural Language :: Dutch', + 'Natural Language :: French', + 'Natural Language :: Hungarian', + 'Natural Language :: German', + 'Natural Language :: Italian', + 'Natural Language :: Latvian', + 'Natural Language :: Japanese', + 'Natural Language :: Norwegian', + 'Natural Language :: Polish', + 'Natural Language :: Portuguese (Brazilian)', + 'Natural Language :: Romanian', + 'Natural Language :: Russian', + 'Natural Language :: Serbian', + 'Natural Language :: Slovak', + 'Natural Language :: Slovenian', + 'Natural Language :: Spanish', + 'Natural Language :: Swedish', + 'Natural Language :: Turkish', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX', + 'Programming Language :: Python', + 'Topic :: Software Development', + 'Topic :: Text Editors' + ] + +def GenerateBinPackageFiles(): + """Generate the list of files needed for py2exe/py2app package files""" + data = [("include/python2.5", + glob.glob("include/python2.5/%s/*" % __platform__)), + ("pixmaps/theme/Default", ["pixmaps/theme/Default/README"]), + ("pixmaps/theme/Tango",["pixmaps/theme/Tango/AUTHORS", + "pixmaps/theme/Tango/COPYING"]), + ("pixmaps/theme/Tango/toolbar", + glob.glob("pixmaps/theme/Tango/toolbar/*.png")), + ("pixmaps/theme/Tango/menu", + glob.glob("pixmaps/theme/Tango/menu/*.png")), + ("pixmaps/theme/Tango/mime", + glob.glob("pixmaps/theme/Tango/mime/*.png")), + ("pixmaps/theme/Tango/other", + glob.glob("pixmaps/theme/Tango/other/*.png")), + ("styles", glob.glob("styles/*.ess")), + ("ekeys", glob.glob("ekeys/*.ekeys")), + ("tests/syntax", glob.glob("tests/syntax/*")), + ("docs", glob.glob("docs/*.txt")), "AUTHORS", "FAQ", "INSTALL", + "README","CHANGELOG","COPYING", "NEWS", "THANKS", "TODO", + "setup.cfg" + ] + + # Get the locale files + for loc_dir in os.listdir("locale"): + tmp = "locale/" + loc_dir + "/LC_MESSAGES" + if os.path.isdir(tmp): + tmp2 = tmp + "/Editra.mo" + if os.path.exists(tmp2): + data.append((tmp, [tmp2])) + + # Only bundle the plugins for the running version of python being used for + # the build. + data.append(("plugins", + glob.glob("plugins/*py%d.%d.egg" % sys.version_info[:2]))) + + # Get platform specific icons + pixlist = ["pixmaps/editra.png", "pixmaps/editra_doc.png"] + + if "darwin" in sys.platform: + data.append("pixmaps/editra_doc.icns") + pixlist.extend(["pixmaps/editra.icns", "pixmaps/editra_doc.icns"]) + elif sys.platform.startswith("win"): + data.extend(glob.glob("include/windows/*.*")) + pixlist.append("pixmaps/editra.ico") + + data.append(("pixmaps", pixlist)) + + return data + +def GenerateSrcPackageFiles(): + """Generate the list of files to include in a source package dist/install""" + data = [ "src/*.py", "src/syntax/*.py", "src/autocomp/*.py", + "src/eclib/*.py", "docs/*.txt", "pixmaps/*.png", "pixmaps/*.ico", + "src/ebmlib/*.py", + "ekeys/*.ekeys", + "Editra", + "src/extern/*.py", + "src/extern/aui/*.py", + "src/extern/dexml/*.py", + "src/extern/pygments/*.py", + "src/extern/pygments/formatters/*.py", + "src/extern/pygments/filters/*.py", + "src/extern/pygments/lexers/*.py", + "src/extern/pygments/styles/*.py", + "pixmaps/*.icns", + "pixmaps/theme/Default/README", + "pixmaps/theme/Tango/AUTHOR", + "pixmaps/theme/Tango/COPYING", + "pixmaps/theme/Tango/toolbar/*.png", + "pixmaps/theme/Tango/menu/*.png", + "pixmaps/theme/Tango/mime/*.png", + "pixmaps/theme/Default/README", + "pixmaps/theme/Tango/other/*.png", + "styles/*.ess", "tests/syntax/*", + "AUTHORS", "CHANGELOG","COPYING", "FAQ", "INSTALL", "NEWS", + "README", "THANKS", "TODO", "setup.cfg" ] + + # Get the local files + for loc_dir in os.listdir("locale"): + tmp = "locale/" + loc_dir + if os.path.isdir(tmp): + tmp = tmp + "/LC_MESSAGES/Editra.mo" + if os.path.exists(tmp): + data.append(tmp) + + # NOTE: plugins selected to package in build step + + return data + + +DESCRIPTION = "Developer's Text Editor" + +LONG_DESCRIPT = \ +r""" +======== +Overview +======== +Editra is a multi-platform text editor with an implementation that focuses on +creating an easy to use interface and features that aid in code development. +Currently it supports syntax highlighting and variety of other useful features +for over 70 programing languages. For a more complete list of features and +screenshots visit the projects homepage at `Editra.org +<http://www.editra.org/>`_. + +============ +Dependencies +============ + * Python 2.6+ + * wxPython 2.8.3+ (Unicode build suggested) + * setuptools 0.6+ + +""" + +ICON = { 'Win' : "pixmaps/editra.ico", + 'WinDoc' : "pixmaps/editra_doc.ico", + 'Mac' : "pixmaps/Editra.icns" +} + +# Explicitly include some libraries that are either loaded dynamically +# or otherwise not able to be found by py2app/exe +INCLUDES = ['syntax.*', 'ed_bookmark', 'ed_log', 'shutil', 'subprocess', 'zipfile', + 'pygments.*', 'pygments.lexers.*', 'pygments.formatters.*', + 'pygments.filters.*', 'pygments.styles.*', 'ftplib', 'xmlrpclib', + 'hmac', 'SimpleXMLRPCServer', 'SocketServer', 'commands', + 'BaseHTTPServer', 'wx.gizmos', 'wx.lib.intctrl', + 'extern.flatnotebook'] # temporary till all references can be removed +if sys.platform.startswith('win'): + INCLUDES.extend(['ctypes', 'ctypes.wintypes']) +else: + INCLUDES.extend(['pty', 'tty']) + +LICENSE = "wxWindows" + +NAME = "Editra" + +URL = "http://editra.org" + +VERSION = info.VERSION + +MANIFEST_TEMPLATE = """ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity + version="5.0.0.0" + processorArchitecture="x86" + name="%(prog)s" + type="win32" + /> + <description>%(prog)s</description> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel + level="asInvoker" + uiAccess="false"> + </requestedExecutionLevel> + </requestedPrivileges> + </security> + </trustInfo> + <dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.VC90.CRT" + version="9.0.21022.8" + processorArchitecture="x86" + publicKeyToken="1fc8b3b9a1e18e3b"> + </assemblyIdentity> + </dependentAssembly> + </dependency> + <dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="X86" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + </dependency> +</assembly> +""" + +RT_MANIFEST = 24 +#---- End Global Settings ----# + + +#---- Packaging Functions ----# + +def BuildPy2Exe(): + """Generate the Py2exe files""" + from distutils.core import setup + try: + import py2exe + except ImportError: + print "\n!! You dont have py2exe installed. !!\n" + exit() + + # put package on path for py2exe + sys.path.append(os.path.abspath('src/')) + sys.path.append(os.path.abspath('src/extern')) + + DATA_FILES = GenerateBinPackageFiles() + try: + import enchant + except ImportError: + pass + else: + from enchant import utils as enutil + DATA_FILES += enutil.win32_data_files() + + setup( + name = NAME, + version = VERSION, + options = {"py2exe" : {"compressed" : 1, + "optimize" : 1, + "bundle_files" : 2, + "includes" : INCLUDES, + "excludes" : ["Tkinter", "Tkconstants", "tcl"], + "dll_excludes": [ "MSVCP90.dll", + "tk85.dll", + "tcl85.dll" ] }}, + windows = [{"script": "src/Editra.py", + "icon_resources": [(1, ICON['Win'])], + "other_resources" : [(RT_MANIFEST, 1, + MANIFEST_TEMPLATE % dict(prog=NAME))], + }], + description = NAME, + author = AUTHOR, + author_email = AUTHOR_EMAIL, + maintainer = AUTHOR, + maintainer_email = AUTHOR_EMAIL, + license = LICENSE, + url = URL, + data_files = DATA_FILES, + ) + shutil.copy2(".\\editra-installer.nsi", ".\\dist\\editra-installer.nsi") + +def BuildOSXApp(): + """Build the OSX Applet""" + # Check for setuptools and ask to download if it is not available + import src.extern.ez_setup as ez_setup + ez_setup.use_setuptools() + from setuptools import setup + + CleanBuild() + fextents = synextreg.GetFileExtensions() + fextents.append("*") + PLIST = dict(CFBundleName = info.PROG_NAME, + CFBundleIconFile = 'Editra.icns', + CFBundleShortVersionString = info.VERSION, + CFBundleGetInfoString = info.PROG_NAME + " " + info.VERSION, + CFBundleExecutable = info.PROG_NAME, + CFBundleIdentifier = "org.editra.%s" % info.PROG_NAME.title(), + CFBundleDocumentTypes = [dict(CFBundleTypeExtensions=fextents, + CFBundleTypeIconFile='editra_doc', + CFBundleTypeRole="Editor" + ), + ], + CFBundleTypeMIMETypes = ['text/plain',], + CFBundleDevelopmentRegion = 'English', +# TODO Causes errors with the system menu translations and text rendering +# CFBundleLocalizations = ['English', 'Spanish', 'French', 'Japanese'], +# ['de_DE', 'en_US', 'es_ES', 'fr_FR', +# 'it_IT', 'ja_JP', 'nl_NL', 'nn_NO', +# 'pt_BR', 'ru_RU', 'sr_SR', 'tr_TR', +# 'uk_UA', 'zh_CN'], + # NSAppleScriptEnabled="YES", + NSHumanReadableCopyright = u"Copyright %s 2005-%d" % (AUTHOR, YEAR) + ) + + PY2APP_OPTS = dict(iconfile = ICON['Mac'], + argv_emulation = True, + optimize = True, + includes = INCLUDES, + plist = PLIST) + + # Add extra mac specific files + DATA_FILES = GenerateBinPackageFiles() + DATA_FILES.append("scripts/editramac.sh") + + # Put extern package on path for py2app + sys.path.append(os.path.abspath('src/extern')) + + setup( + app = APP, + version = VERSION, + options = dict( py2app = PY2APP_OPTS), + description = DESCRIPTION, + author = AUTHOR, + author_email = AUTHOR_EMAIL, + maintainer = AUTHOR, + maintainer_email = AUTHOR_EMAIL, + license = LICENSE, + url = URL, + data_files = DATA_FILES, + setup_requires = ['py2app'], + ) + + CreateDMG(VERSION) + +def CreateDMG(version): + """Create an OSX DMG + @param version: version number string + @todo: cleanup and generalize + + """ + Log("Creating DMG for osx installer...") + + assert os.path.exists('dist') + os.chdir('dist') + vname = "Editra-%s" % version + fname = vname + ".dmg" + mpath = "/Volumes/Editra-%s" % version + comp = "Editra-%s_2.dmg" % version + + if os.path.exists("dist/%s" % fname): + Log("Found image from previous running") + os.remove("dist/%s" % fname) + + # Create the temporary image + Log("Creating disk image...") + os.system("hdiutil create -size 75m -fs HFS+ -volname %s %s" % (vname, fname)) + Log("Mounting disk image...") + os.system("hdiutil mount %s" % fname) # Mount the image + + # Move installation files to the new image + Log("Copying installation files to installer image...") + if not os.path.exists(mpath + "/.bk"): + os.mkdir(mpath + "/.bk") + shutil.copy2("../pixmaps/installer/inst_bk.png", mpath + "/.bk/inst_bk.png") + os.system("ditto -rsrcFork Editra.app %s/Editra.app" % mpath) + + Log("Configuring Finder View Options...") +# shutil.copy2("../scripts/installer/INSTALLER_DS_Store", mpath + "/.DS_Store") +# os.chmod(mpath + "/.DS_Store", 777) + f = open("tmpscript", 'w') + f.write(APPLE_SCRIPT % vname) + f.close() + status = os.system("osascript tmpscript") + os.remove("tmpscript") + Log("Applescript return status: %d" % status) + + # Unmount the image + Log("Unmounting the installer image...") + os.system("hdiutil eject %s" % mpath) + + # Create the compressed image + Log("Converting the disk image to a compressed format...") + os.system("hdiutil convert %s -format UDZO -imagekey zlib-level=9 -o %s" % (fname, comp)) + + # Cleanup + Log("Cleaning up temporary installer build files...") + os.remove(fname) + os.rename(comp, fname) + +# Template for controlling some finder options via apple script +APPLE_SCRIPT = """ +tell application "Finder" + tell disk ("%s" as string) + open + + tell container window + set current view to icon view + set toolbar visible to false + set statusbar visible to false + set the bounds to {10, 60, 522, 402} + set statusbar visible to false + end tell + + set opts to the icon view options of container window + tell opts + set icon size to 128 + end tell + set background picture of opts to file ".bk:inst_bk.png" + set position of item "Editra.app" to {260, 145} + + update without registering applications + end tell +end tell +""" + +def DoSourcePackage(): + """Build a source package or do a source install""" + # Get the package data + DATA = GenerateSrcPackageFiles() + + # Force optimization + if 'install' in sys.argv and ('O1' not in sys.argv or '02' not in sys.argv): + sys.argv.append('-O2') + + # Install the plugins for this version of Python + DATA.append("plugins/*py%d.%d.egg" % sys.version_info[:2]) + + # Import proper setup function + if 'bdist_egg' in sys.argv: + try: + from setuptools import setup + + # Only bundle eggs for the given python version + DATA.append("plugins/*py%d.%d.egg" % sys.version_info[:2]) + except ImportError: + print "To build an egg setuptools must be installed" + else: + from distutils.core import setup + + # Try to remove possibly conflicting files from an old install + if '--no-clean' not in sys.argv: + try: + import Editra + path = Editra.__file__ + if '__init__' in path: + path = os.path.dirname(path) + path = os.path.join(path, 'src') + del sys.modules['Editra'] + shutil.rmtree(path) + except (ImportError, OSError): + pass + except: + sys.stderr.write("[ERROR] Failed to remove old source files") + else: + sys.argv.remove('--no-clean') + + # Make sure to delete any existing MANIFEST file beforehand to + # prevent stale file lists + if os.path.exists('MANIFEST'): + try: + os.remove('MANIFEST') + except OSError: + pass + + setup( + name = NAME, + scripts = ['editra',], + version = VERSION, + description = DESCRIPTION, + long_description = LONG_DESCRIPT, + author = AUTHOR, + author_email = AUTHOR_EMAIL, + maintainer = AUTHOR, + maintainer_email = AUTHOR_EMAIL, + url = URL, + download_url = "http://editra.org/download", + license = LICENSE, + platforms = [ "Many" ], + packages = [ NAME ], + package_dir = { NAME : '.' }, + package_data = { NAME : DATA }, + classifiers= CLASSIFIERS, + install_requires = ['wxPython',] + ) + +def BuildECLibDemo(): + """Build the Editra Control Library Demo package""" + assert 'eclib' in sys.argv, "Should only be called for eclib build" + + DATA = [ "../src/eclib/*.py", "../tests/controls/*.py"] + OUT = 'dist/eclibdemo' + + Log("Cleaning up files") + if not os.path.exists('dist'): + os.mkdir('dist') + + if os.path.exists('dist/eclibdemo.zip'): + os.remove('dist/eclibdemo.zip') + + if os.path.exists(OUT): + shutil.rmtree(OUT) + + # Copy the Files + Log("Preparing output package...") + os.mkdir(OUT) + shutil.copytree('src/eclib', 'dist/eclibdemo/eclib') + shutil.copytree('tests/controls', 'dist/eclibdemo/demo') + shutil.copy('COPYING', 'dist/eclibdemo/') + f = open(os.path.abspath('./dist/eclibdemo/__init__.py'), 'wb') + f.close() + + # Make the launcher + f = open(os.path.abspath('./dist/eclibdemo/RunDemo.py'), 'wb') + f.write("import os\nos.chdir('demo')\n" + "import demo.demo as demo\n" + "demo.Main()\nos.chdir('..')") + f.close() + + # Zip it up + Log("Create zip file") + os.chdir('dist') + zfile = zipfile.ZipFile('eclibdemo.zip', 'w', + compression=zipfile.ZIP_DEFLATED) + files = list() + for dpath, dname, fnames in os.walk('eclibdemo'): + files.extend([ os.path.join(dpath, fname).\ + lstrip(os.path.sep) + for fname in fnames]) + for fname in files: + zfile.write(fname.encode(sys.getfilesystemencoding())) + os.chdir('../') + Log("ECLIB Demo build is complete") + +def CleanBuild(): + """Cleanup all build related files""" + if os.path.exists('MANIFEST'): + os.remove('MANIFEST') + for path in ('dist', 'build', 'tmp'): + if os.path.exists(path): + Log("Cleaning %s..." % path) + shutil.rmtree(path) + +def Log(msg): + """Write to the build log""" + # TODO add log file, just write to console for now + print(msg) + +#----------------------------------------------------------------------------# + +if __name__ == '__main__': + if __platform__ == "win32" and 'py2exe' in sys.argv: + BuildPy2Exe() + elif __platform__ == "darwin" and 'py2app' in sys.argv: + BuildOSXApp() + elif 'eclib' in sys.argv: + BuildECLibDemo() + elif 'clean' in sys.argv: + CleanBuild() + else: + DoSourcePackage() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/Editra.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/Editra.py new file mode 100644 index 0000000..db648de --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/Editra.py @@ -0,0 +1,1188 @@ +#!/usr/bin/env python2 +############################################################################### +# Name: Editra.py # +# Purpose: Implements Editras App object and the Main method # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module defines the Editra Application object and the Main method for +running Editra. + +@summary: Editra's main application object and MainLoop + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: Editra.py 71718 2012-06-12 13:25:48Z CJP $" +__revision__ = "$Revision: 71718 $" + +#--------------------------------------------------------------------------# +# Dependencies +import os +import sys + +# Due to some methods that were added in 2.8.3 being used in a large number +# of places Editra has become incompatible with wxPython 2.8.1.1 and earlier. +# So ensure correct version of wxPython can be loaded +if not hasattr(sys, 'frozen') and 'wx' not in sys.modules: + import wxversion + wxversion.ensureMinimal('2.8') + +import codecs +import base64 +import locale +import getopt +import shutil +import wx + +# The event handler mixin is now part of wxPython proper, but there hasn't +# been an official release with it yet, so try to import the official module +# but fallback to our own copy if it fails. +try: + import wx.lib.eventStack as events +except: + import extern.events as events + +# Try and import a system installed version of pkg_resources else fallback to +# the one bundled with Editra's source. +try: + from pkg_resources import resource_filename +except ImportError: + from extern.pkg_resources import resource_filename + +# Editra Libraries +import ed_glob +import ed_i18n +import profiler +import util +import dev_tool +import ed_main +import ed_art +import ed_txt +import ed_event +import updater +import plugin +import ed_ipc +import ed_session +import ebmlib +from syntax import synglob + +#--------------------------------------------------------------------------# +# Global Variables +ID_UPDATE_CHECK = wx.NewId() + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# + +class Editra(wx.App, events.AppEventHandlerMixin): + """The Editra Application Object + @deprecated: L{GetMainWindow} + + """ + def __init__(self, *args, **kargs): + """Initialize that main app and its attributes + @postcondition: application is created and ready to be run in mainloop + + """ + wx.App.__init__(self, *args, **kargs) + events.AppEventHandlerMixin.__init__(self) + + # Attributes + self._log = dev_tool.DEBUGP + self._lock = False + self._windows = dict() + self._isexiting = False + + # Disable debug popups + wx.Log.EnableLogging(False) + # XXX: Temporary - disable assertions on OSX to work around + # upstream bug in drawing code "couldnt draw the rotated text" + if wx.Platform == '__WXMAC__': + self.SetAssertMode(wx.PYAPP_ASSERT_SUPPRESS) + + # Purge old logs + logfile = dev_tool.EdLogFile() + logfile.PurgeOldLogs(7) + + if ed_glob.SINGLE: + # Setup the instance checker + instance_name = u"%s-%s" % (self.GetAppName(), wx.GetUserId()) + lockpath = wx.StandardPaths.Get().GetTempDir() + self._instance = wx.SingleInstanceChecker(instance_name, path=lockpath) + if self._instance.IsAnotherRunning(): + try: + opts, args = ProcessCommandLine() + except getopt.GetoptError, msg: + self._log("[app][err] %s" % str(msg)) + args = list() + opts = dict() + + exml = ed_ipc.IPCCommand() + if len(args): + nargs = list() + for p in args: + try: + p = ebmlib.GetAbsPath(p) + except: + pass + fxml = ed_ipc.IPCFile() + fxml.value = p + nargs.append(fxml) + exml.filelist = nargs + arglist = list() + for arg, val in opts.items(): + axml = ed_ipc.IPCArg() + axml.name = arg + axml.value = val + arglist.append(axml) + exml.arglist = arglist + + # TODO: need to process other command line options as well i.e) -g + self._log("[app][info] Sending: %s" % exml.Xml) + key = profiler.Profile_Get('SESSION_KEY') + if ebmlib.IsUnicode(key): + key = key.encode(sys.getfilesystemencoding(), 'replace') + rval = ed_ipc.SendCommands(exml, key) + # If sending the command failed then let the editor startup + # a new instance + if not rval: + self._isfirst = True + else: + self._log("[app][info] Starting Ipc server...") + # Set the session key and save it to the users profile so + # that other instances can access the server + key = base64.b64encode(os.urandom(8), 'zZ') + uname = wx.GetUserName() + if ebmlib.IsUnicode(uname): + uname = uname.encode(sys.getfilesystemencoding(), 'replace') + key = uname + key + profiler.Profile_Set('SESSION_KEY', key) + profiler.Profile_Set('ISBINARY', hasattr(sys, 'frozen')) + path = profiler.Profile_Get('MYPROFILE') + profiler.TheProfile.Write(path) + try: + self._server = ed_ipc.EdIpcServer(self, key) + self._server.start() + except Exception, msg: + self._log("[app][err] Failed to start ipc server") + self._log("[app][err] %s" % str(msg)) + self._server = None + self._isfirst = True + else: + self._isfirst = True + + # Setup Plugins after locale as they may have resource that need to + # be loaded. + if self._isfirst: + self._pluginmgr = plugin.PluginManager() + + self._log("[app][info] Registering Editra's ArtProvider") + wx.ArtProvider.PushProvider(ed_art.EditraArt()) + + # Check if libenchant has been loaded or need to be + import extern.stcspellcheck as stcspellcheck + checker = stcspellcheck.STCSpellCheck + if not checker.isEnchantOk(): + spref = profiler.Profile_Get('SPELLCHECK', default=dict()) + libpath = spref.get('epath', u'') + checker.reloadEnchant(libpath) + # TODO: log if load fails here + + def AddMessageCatalog(self, name, path): + """Add a catalog lookup path to the app + @param name: name of catalog (i.e 'projects') + @param path: catalog lookup path + + """ + if self.locale is not None: + path = resource_filename(path, 'locale') + self.locale.AddCatalogLookupPathPrefix(path) + self.locale.AddCatalog(name) + + def OnInit(self): + """Initialize the Editor + @note: this gets called before __init__ + @postcondition: custom artprovider and plugins are loaded + + """ + self.SetAppName(ed_glob.PROG_NAME) + + self._log = dev_tool.DEBUGP + self._log("[app][info] Editra is Initializing") + + # Load user preferences + self.profile_updated = InitConfig() + self._isfirst = False # Is the first instance + self._instance = None + + # Setup Locale + locale.setlocale(locale.LC_ALL, '') + langId = ed_i18n.GetLangId(profiler.Profile_Get('LANG')) + if wx.Locale.IsAvailable(langId): + self.locale = wx.Locale(langId) + if self.locale.GetCanonicalName() in ed_i18n.GetAvailLocales(): + self._log("[app][info] Loaded Locale '%s'" % self.locale.CanonicalName) + self.locale.AddCatalogLookupPathPrefix(ed_glob.CONFIG['LANG_DIR']) + self.locale.AddCatalog(ed_glob.PROG_NAME) + else: + self._log("[app][err] Unknown Locale '%s'" % self.locale.CanonicalName) + del self.locale + self.locale = None + else: + self._log("[app][err] The locale %s is not available!" % profiler.Profile_Get('LANG')) + self.locale = None + + # Check and set encoding if necessary + d_enc = profiler.Profile_Get('ENCODING') + if not d_enc: + profiler.Profile_Set('ENCODING', ed_txt.DEFAULT_ENCODING) + else: + # Ensure the default encoding is valid + # Fixes up older installs on some systems that may have an + # invalid encoding set. + try: + codecs.lookup(d_enc) + except (LookupError, TypeError): + self._log("[app][err] Resetting bad encoding: %s" % d_enc) + profiler.Profile_Set('ENCODING', ed_txt.DEFAULT_ENCODING) + + # Setup the Error Reporter + if profiler.Profile_Get('REPORTER', 'bool', True): + sys.excepthook = dev_tool.ExceptionHook + + #---- Bind Events ----# + self.Bind(wx.EVT_ACTIVATE_APP, self.OnActivate) + self.Bind(wx.EVT_MENU, self.OnNewWindow, id=ed_glob.ID_NEW_WINDOW) + self.Bind(wx.EVT_MENU, self.OnCloseWindow) + self.Bind(ed_event.EVT_NOTIFY, self.OnNotify) + self.Bind(ed_ipc.EVT_COMMAND_RECV, self.OnCommandReceived) + + # Splash a warning if version is not a final version + if profiler.Profile_Get('APPSPLASH'): + import edimage + splash_img = edimage.splashwarn.GetBitmap() + self.splash = wx.SplashScreen(splash_img, wx.SPLASH_CENTRE_ON_PARENT | \ + wx.SPLASH_NO_TIMEOUT, 0, None, wx.ID_ANY) + self.splash.Show() + + return True + + def Destroy(self): + """Destroy the application""" + try: + # Cleanup the instance checker + del self._instance + except AttributeError: + pass + wx.App.Destroy(self) + + def DestroySplash(self): + """Destroy the splash screen""" + # If is created and not dead already + if getattr(self, 'splash', None) is not None and \ + isinstance(self.splash, wx.SplashScreen): + self.splash.Destroy() + self.splash = None + + def Exit(self, force=False): + """Exit the program + @postcondition: If no toplevel windows are present program will exit. + @postcondition: Program may remain open if an open window is locking. + + """ + self._isexiting = True + self._pluginmgr.WritePluginConfig() + profiler.TheProfile.Write(profiler.Profile_Get('MYPROFILE')) + if not self._lock or force: + if getattr(self, '_server', None): + self._server.Shutdown() + + try: + # Cleanup the instance checker + del self._instance + except AttributeError: + pass + + # Exit the app + wx.App.ExitMainLoop(self) + + def GetLocaleObject(self): + """Get the locale object owned by this app. Use this method to add + extra catalogs for lookup. + @return: wx.Locale or None + + """ + return self.locale + + def GetLog(self): + """Returns the logging function used by the app + @return: the logging function of this program instance + + """ + return self._log + + def GetMainWindow(self): + """Returns reference to the instance of the MainWindow + that is running if available, and None if not. + @return: the L{MainWindow} of this app if it is open + + """ + self._log("[app][warn] Editra::GetMainWindow is deprecated") + for window in self._windows: + if isinstance(self._windows[window][0], ed_main.MainWindow): + return self._windows[window][0] + return None + + def GetActiveWindow(self): + """Returns the active main window if there is one else it will + just return some main window or none if there are no main windows + @return: frame instance or None + + """ + awin = None + for win in self.GetMainWindows(): + if win.IsActive(): + awin = win + break + + if awin is None: + awin = self.GetTopWindow() + if not isinstance(awin, ed_main.MainWindow): + if len(self.GetMainWindows()): + awin = self.GetMainWindows()[0] + + return awin + + def GetCurrentBuffer(self): + """Get the current buffer from the active window or None + @return: EditraStc + + """ + win = self.GetTopWindow() + if not isinstance(win, ed_main.MainWindow): + win = self.GetActiveWindow() + if win is None: + return None # UI dead? + + if isinstance(win, ed_main.MainWindow): + nbook = win.GetNotebook() + if nbook: + return nbook.GetCurrentCtrl() + return None + + def GetMainWindows(self): + """Returns a list of all open main windows + @return: list of L{MainWindow} instances of this app (list may be empty) + + """ + mainw = list() + for window in self._windows: + try: + if isinstance(self._windows[window][0], ed_main.MainWindow): + mainw.append(self._windows[window][0]) + except AttributeError: + continue + return mainw + + def GetOpenWindows(self): + """Returns a list of open windows + @return: list of all open windows owned by app + + """ + return self._windows + + def GetPluginManager(self): + """Returns the plugin manager used by this application + @return: Apps plugin manager + @see: L{plugin} + + """ + return self._pluginmgr + + def GetProfileUpdated(self): + """Was the profile updated + @return: bool + + """ + return self.profile_updated + + def GetWindowInstance(self, wintype): + """Get an instance of an open window if one exists + @param wintype: Class type of window to look for + @precondition: Window must have called L{RegisterWindow} + @return: Instance of window or None + + """ + for win in self._windows: + if isinstance(self._windows[win][0], wintype): + return self._windows[win][0] + return None + + def IsLocked(self): + """Returns whether the application is locked or not + @return: whether a window has locked the app from closing or not + + """ + return self._lock + + def IsOnlyInstance(self): + """Check if this app is the the first instance that is running + @return: bool + + """ + return self._isfirst + + def Lock(self): + """Locks the app from exiting + @postcondition: program is locked from exiting + + """ + self._lock = True + + def OpenFile(self, filename, line=-1): + """Open a file in the currently active window + @param filename: file path + @keyword line: int + + """ + window = self.GetTopWindow() + if not isinstance(window, ed_main.MainWindow): + window = None + + try: + encoding = sys.getfilesystemencoding() + fname = ed_txt.DecodeString(filename, encoding) + + if profiler.Profile_Get('OPEN_NW', default=False): + self.OpenNewWindow(fname, window) + elif window: + window.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, fname, line) + + # Make sure the window is brought to the front + if window.IsIconized(): + window.Iconize(False) + window.Raise() + else: + # Some unlikely error condition + self._log("[app][err] OpenFile unknown error: %s" % filename) + + except Exception, msg: + self._log("[app][err] Failed to open file: %s" % str(msg)) + + def MacNewFile(self): + """Stub for future use""" + pass + + def MacOpenFile(self, filename): + """Macintosh Specific code for opening files that are associated + with the editor and double clicked on after the editor is already + running. + @param filename: file path string + @postcondition: if L{MainWindow} is open file will be opened in notebook + + """ + self._log("[app][info] MacOpenFile Fired") + self.OpenFile(filename, line=-1) + + def MacPrintFile(self, filename): + """Stub for future use + @param filename: file to print + + """ + pass + + def MacReopenApp(self): + """Handle kAEReopenApplication when dock icons is clicked on""" + frame = self.GetTopWindow() + if frame is not None: + if frame.IsIconized(): + frame.Iconize(False) + frame.Raise() + + def OnActivate(self, evt): + """Activation Event Handler + @param evt: wx.ActivateEvent + + """ + if evt.GetActive(): + self._log("[app][info] I'm Awake!!") + # Refresh Clipboard Ring + ed_main.MainWindow.UpdateClipboardRing() + +# frame = self.GetTopWindow() +# if frame is not None: +# if frame.IsIconized(): +# frame.Iconize(False) +# frame.Raise() + else: + self._log("[app][info] Going to sleep") + evt.Skip() + + def OnExit(self, evt=None, force=False): + """Handle application exit request + @keyword evt: event that called this handler + @keyword force: Force an exit + + """ + e_id = -1 + if evt: + e_id = evt.GetId() + + if e_id == ed_glob.ID_EXIT: + self._isexiting = True + # First loop is to ensure current top window is + # closed first + for win in self.GetMainWindows(): + if win.IsActive(): + result = win.Close() + if result: + self._isexiting = False + break + return + for win in self.GetMainWindows(): + win.Raise() + result = win.Close() + if not result: + self._isexiting = False + break + self.Exit(force) + else: + if evt: + evt.Skip() + + def OnNewWindow(self, evt): + """Create a new editing window + @param evt: wx.EVT_MENU + + """ + if evt.GetId() == ed_glob.ID_NEW_WINDOW: + frame = evt.GetEventObject().GetMenuBar().GetFrame() + self.OpenNewWindow(caller=frame) + else: + evt.Skip() + + def OnCommandReceived(self, evt): + """Receive commands from the IPC server + @todo: move command processing into own module + + """ + # Guard against events that come in after shutdown + # from server thread. + if not self or self._isexiting or not self.IsMainLoopRunning(): + return + + self._log("[app][info] IN OnCommandReceived") + cmds = evt.GetCommands() + if isinstance(cmds, ed_ipc.IPCCommand): + self._log("[app][info] OnCommandReceived %s" % cmds.Xml) + if not len(cmds.filelist): + self.OpenNewWindow() + else: + # TODO: change goto line handling to require one + # arg per file specified on the command line + # i.e) -g 23,44,100 + line = -1 + for argobj in cmds.arglist: + arg = argobj.name + if arg == '-g': + line = int(argobj.value) + if line > 0: + line -= 1 + break + + for fname in cmds.filelist: + self.OpenFile(fname.value, line) + + def OnCloseWindow(self, evt): + """Close the currently active window + @param evt: wx.MenuEvent + + """ + if evt.GetId() in [ed_glob.ID_CLOSE, ed_glob.ID_CLOSE_WINDOW]: + for window in wx.GetTopLevelWindows(): + if hasattr(window, 'IsActive') and window.IsActive(): + if hasattr(window, 'Close'): + window.Close() + break + else: + evt.Skip() + + def OpenNewWindow(self, fname=u'', caller=None): + """Open a new window + @keyword fname: Open a file in the new window + @keyword caller: MainWindow that called to open this one + @return: the new window + + """ + frame = ed_main.MainWindow(None, wx.ID_ANY, + profiler.Profile_Get('WSIZE'), + ed_glob.PROG_NAME) + if caller: + pos = caller.GetPosition() + frame.SetPosition((pos.x + 22, pos.y + 22)) + + self.RegisterWindow(repr(frame), frame, True) + self.SetTopWindow(frame) + if isinstance(fname, basestring) and fname != u'': + frame.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, fname) + frame.Show(True) + + # Ensure frame gets an Activate event when shown + # this doesn't happen automatically on windows + if wx.Platform == '__WXMSW__': + wx.PostEvent(frame, wx.ActivateEvent(wx.wxEVT_ACTIVATE, True)) + return frame + + def OnNotify(self, evt): + """Handle notification events + @param evt: L{ed_event.NotificationEvent} + + """ + e_val = evt.GetValue() + if evt.GetId() == ID_UPDATE_CHECK and \ + isinstance(e_val, tuple) and e_val[0]: + self.DestroySplash() + mdlg = wx.MessageDialog(self.GetActiveWindow(), + _("An updated version of Editra is available\n" + "Would you like to download Editra %s now?") %\ + e_val[1], _("Update Available"), + wx.YES_NO|wx.YES_DEFAULT|wx.CENTER|wx.ICON_INFORMATION) + if mdlg.ShowModal() == wx.ID_YES: + dl_dlg = updater.DownloadDialog(None, wx.ID_ANY, + _("Downloading Update")) + dp_sz = wx.GetDisplaySize() + dl_dlg.SetPosition(((dp_sz[0] - (dl_dlg.GetSize()[0] + 5)), 25)) + dl_dlg.Show() + mdlg.Destroy() + else: + evt.Skip() + + def RegisterWindow(self, name, window, can_lock=False): + """Registers winows with the app. The name should be the + repr of window. The can_lock parameter is a boolean stating + whether the window can keep the main app running after the + main frame has exited. + @param name: name of window + @param window: reference to window object + @keyword can_lock: whether window can lock exit or not + + """ + self._windows[name] = (window, can_lock) + + def ReloadArtProvider(self): + """Reloads the custom art provider onto the artprovider stack + @postcondition: artprovider is removed and reloaded + + """ + try: + wx.ArtProvider.PopProvider() + finally: + wx.ArtProvider.PushProvider(ed_art.EditraArt()) + + def UnLock(self): + """Unlocks the application + @postcondition: application is unlocked so it can exit + + """ + self._lock = False + + def UnRegisterWindow(self, name): + """Unregisters a named window with the app if the window + was the top window and if other windows that can lock are + registered in the window stack it will promote the next one + it finds to be the top window. If no windows that fit this + criteria are found it will close the application. + @param name: name of window to unregister + + """ + if name in self._windows: + self._windows.pop(name) + + if not len(self._windows): + self._log("[app][info] No more open windows shutting down") + self.Exit() + return + + # TODO: WXBUG? calling GetTopWindow when there are no more top + # level windows causes a crash under MSW. Moving this line + # above the previous check can reproduce the error. + cur_top = self.GetTopWindow() + if name == repr(cur_top): + found = False + for key in self._windows: + if self._windows[key][1]: + self._log("[app][info] Promoting %s to top" % key) + try: + self.SetTopWindow(self._windows[key][0]) + except Exception: + continue + found = True + break + + if not found: + self._log("[app][info] No more top windows exiting app") + self.UnLock() + self.Exit() + else: + self._log("[app][info] UnRegistered %s" % name) + else: + self._log("[app][warn] The window %s is not registered" % name) + + def WindowCanLock(self, winname): + """Checks if a named window can lock the application or + not. The window must have been previously registered with + a call to RegisterWindow for this function to have any + real usefullness. + @param winname: name of window to query + + """ + if winname in self._windows: + return self._windows[winname][1] + else: + self._log("[app][warn] the window %s has " + "not been registered" % winname) + return False + +#--------------------------------------------------------------------------# + +def InitConfig(): + """Initializes the configuration data + @postcondition: all configuration data is set + + """ + # Check if a custom config directory was specified on the commandline + if ed_glob.CONFIG['CONFIG_BASE'] is not None: + # TODO: there is a bug when the first time the config is created + # where the settings will not be saved until second launching. + config_base = os.path.abspath(ed_glob.CONFIG['CONFIG_BASE']) + else: + # Look for a profile directory on the system level. If this directory + # exists Use it instead of the user one. This will allow for running + # Editra from a portable drive or for system administrators to enforce + # settings on a system installed version. + config_base = util.ResolvConfigDir(u'.Editra', True) + + if os.path.exists(config_base): + ed_glob.CONFIG['CONFIG_BASE'] = config_base + ed_glob.CONFIG['PROFILE_DIR'] = os.path.join(config_base, u"profiles") + ed_glob.CONFIG['PROFILE_DIR'] += os.sep + ed_glob.CONFIG['ISLOCAL'] = True + else: + config_base = wx.StandardPaths.Get().GetUserDataDir() + ed_glob.CONFIG['PROFILE_DIR'] = util.ResolvConfigDir(u"profiles") + + # Check for if config directory exists and if profile is from the current + # running version of Editra. + profile_updated = False + if util.HasConfigDir() and os.path.exists(ed_glob.CONFIG['PROFILE_DIR']): + if profiler.ProfileIsCurrent(): + pstr = profiler.GetProfileStr() + # If using local(portable) config the profile string is stored + # as a relative path that just names the config file. + if ed_glob.CONFIG['ISLOCAL']: + pstr = os.path.join(ed_glob.CONFIG['PROFILE_DIR'], pstr) + pstr = util.RepairConfigState(pstr) + dev_tool.DEBUGP("[InitConfig][info] Loading profile: %s" % repr(pstr)) + profiler.TheProfile.Load(pstr) + else: + dev_tool.DEBUGP("[InitConfig][info] Updating Profile to current version") + + # When upgrading from an older version make sure all + # config directories are available. + for cfg in ("cache", "styles", "plugins", "profiles", "sessions"): + if not util.HasConfigDir(cfg): + util.MakeConfigDir(cfg) + + # Load and update profile + pstr = profiler.GetProfileStr() + pstr = util.RepairConfigState(pstr) + profiler.TheProfile.Load(pstr) + profiler.TheProfile.Update() + + #---- Temporary Profile Adaption ----# + + # Added after 0.5.32 + mconfig = profiler.Profile_Get('LEXERMENU', default=None) + if mconfig is None: + mconfig = [ synglob.LANG_C, synglob.LANG_CPP, + synglob.LANG_BASH, synglob.LANG_CSS, + synglob.LANG_HTML, synglob.LANG_JAVA, + synglob.LANG_LISP, synglob.LANG_PERL, + synglob.LANG_PHP, synglob.LANG_PYTHON, + synglob.LANG_RUBY, synglob.LANG_SQL, + synglob.LANG_XML] + mconfig.sort() + profiler.Profile_Set('LEXERMENU', mconfig) + + # GUI_DEBUG mode removed in 0.2.5 + mode = profiler.Profile_Get('MODE') + if mode == 'GUI_DEBUG': + profiler.Profile_Set('MODE', 'DEBUG') + + # This key has been removed so clean it from old profiles + profiler.Profile_Del('LASTCHECK') + + # Print modes don't use strings anymore + if isinstance(profiler.Profile_Get('PRINT_MODE'), basestring): + profiler.Profile_Set('PRINT_MODE', ed_glob.PRINT_BLACK_WHITE) + + # Simplifications to eol mode persistence (0.4.28) + # Keep for now till plugins are updated + #profiler.Profile_Del('EOL') # changed to EOL_MODE + + # After 0.4.65 LAST_SESSION now points a session file and not + # to a list of files to open. + ed_glob.CONFIG['SESSION_DIR'] = util.ResolvConfigDir(u"sessions") + smgr = ed_session.EdSessionMgr() + sess = profiler.Profile_Get('LAST_SESSION') + if isinstance(sess, list) or not sess: + profiler.Profile_Set('LAST_SESSION', smgr.DefaultSession) + else: + # After 0.6.58 session is reduced to a name instead of path + if sess and os.path.sep in sess: + name = smgr.SessionNameFromPath(sess) + profiler.Profile_Set('LAST_SESSION', name) + + #---- End Temporary Profile Adaption ----# + + # Write out updated profile + profiler.TheProfile.Write(pstr) + + profile_updated = True + else: + # Fresh install + util.CreateConfigDir() + + # Check and upgrade installs from old location + success = True + try: + success = UpgradeOldInstall() + except Exception, msg: + dev_tool.DEBUGP("[InitConfig][err] %s" % msg) + success = False + + if not success: + old_cdir = u"%s%s.%s%s" % (wx.GetHomeDir(), os.sep, + ed_glob.PROG_NAME, os.sep) + msg = ("Failed to upgrade your old installation\n" + "To retain your old settings you may need to copy some files:\n" + "\nFrom: %s\n\nTo: %s") % (old_cdir, config_base) + wx.MessageBox(msg, "Upgrade Failed", style=wx.ICON_WARNING|wx.OK) + + # Set default eol for windows + if wx.Platform == '__WXMSW__': + profiler.Profile_Set('EOL_MODE', ed_glob.EOL_MODE_CRLF) + profiler.Profile_Set('ICONSZ', (16, 16)) + elif wx.Platform == '__WXMAC__': + # Default to 32x32 toolbar icons on OSX + profiler.Profile_Set('ICONSZ', (32, 32)) + + #---- Profile Loaded / Installed ----# + + # Set debug mode + emode = profiler.Profile_Get('MODE') + if 'DEBUG' in emode: + ed_glob.DEBUG = True + if emode.startswith('VERBOSE'): + ed_glob.VDEBUG = True + + # Resolve resource locations + ed_glob.CONFIG['CONFIG_DIR'] = util.ResolvConfigDir(u"") + ed_glob.CONFIG['INSTALL_DIR'] = util.ResolvConfigDir(u"", True) + ed_glob.CONFIG['KEYPROF_DIR'] = util.ResolvConfigDir(u"ekeys", True) + ed_glob.CONFIG['SYSPIX_DIR'] = util.ResolvConfigDir(u"pixmaps", True) + ed_glob.CONFIG['PLUGIN_DIR'] = util.ResolvConfigDir(u"plugins") + ed_glob.CONFIG['THEME_DIR'] = util.ResolvConfigDir(os.path.join(u"pixmaps", u"theme")) + ed_glob.CONFIG['LANG_DIR'] = util.ResolvConfigDir(u"locale", True) + ed_glob.CONFIG['STYLES_DIR'] = util.ResolvConfigDir(u"styles") + ed_glob.CONFIG['SYS_PLUGIN_DIR'] = util.ResolvConfigDir(u"plugins", True) + ed_glob.CONFIG['SYS_STYLES_DIR'] = util.ResolvConfigDir(u"styles", True) + ed_glob.CONFIG['TEST_DIR'] = util.ResolvConfigDir(os.path.join(u"tests", u"syntax"), True) + + # Make sure all standard config directories are there + for cfg in ("cache", "styles", "plugins", "profiles", "sessions"): + if not util.HasConfigDir(cfg): + util.MakeConfigDir(cfg) + ed_glob.CONFIG['CACHE_DIR'] = util.ResolvConfigDir(u"cache") + ed_glob.CONFIG['SESSION_DIR'] = util.ResolvConfigDir(u"sessions") + + return profile_updated + +#--------------------------------------------------------------------------# + +def UpgradeOldInstall(): + """Upgrade an old installation and transfer all files if they exist + @note: FOR INTERNAL USE ONLY + @return: bool (True if success, False if failure) + + """ + old_cdir = u"%s%s.%s%s" % (wx.GetHomeDir(), os.sep, + ed_glob.PROG_NAME, os.sep) + base = ed_glob.CONFIG['CONFIG_BASE'] + if base is None: + base = wx.StandardPaths.Get().GetUserDataDir() + os.sep + + err = 0 + if os.path.exists(old_cdir) and \ + base.lower().rstrip(os.sep) != old_cdir.lower().rstrip(os.sep): + for item in os.listdir(old_cdir): + try: + dest = os.path.join(base, item) + item = os.path.join(old_cdir, item) + if os.path.exists(dest): + if os.path.isdir(dest): + shutil.rmtree(dest, True) + else: + os.remove(dest) + + shutil.move(item, dest) + except Exception, msg: + util.Log("[Upgrade][err] %s" % msg) + err += 1 + continue + + os.rmdir(old_cdir) + + # Load the copied over profile + pstr = profiler.GetProfileStr() + prof = os.path.basename(pstr) + pstr = os.path.join(base, u"profiles", prof) + if os.path.exists(pstr): + profiler.TheProfile.Load(pstr) + profiler.TheProfile.Update() + profiler.UpdateProfileLoader() + + if not err: + wx.MessageBox(_("Your profile has been updated to the latest " + "version") + u"\n" + \ + _("Please check the preferences dialog to check " + "your preferences"), + _("Profile Updated")) + + return not err + +#--------------------------------------------------------------------------# + +def PrintHelp(err=None): + """Print command line help + @postcondition: Help is printed and program exits + + """ + if err is not None: + sys.stderr.write(err + os.linesep) + + print(("Editra - %s - Developers Text Editor\n" + "Cody Precord (2005-2012)\n\n" + "usage: Editra [arguments] [files... ]\n\n" + "Short Arguments:\n" + " -c Set custom configuration directory at runtime\n" + " -d Turn on console debugging (-dd for verbose debug)\n" + " -D Turn off console debugging (overrides preferences)\n" + " -g Open file to line (i.e Editra -g 10 file.txt)\n" + " -h Show this help message\n" + " -p Run Editra in the profiler (outputs to editra.prof).\n" + " -v Print version number and exit\n" + " -S Disable single instance checker\n" + "\nLong Arguments:\n" + " --confdir arg Set custom configuration directory at runtime\n" + " --debug Turn on console debugging\n" + " --help Show this help message\n" + " --auth Print the ipc server info\n" + " --version Print version number and exit\n" + " --profileOut arg Run Editra in the profiler (arg is output file)\n" + ) % ed_glob.VERSION) + + if err is None: + os._exit(0) + else: + os._exit(1) + +#--------------------------------------------------------------------------# + +def ProcessCommandLine(): + """Process the command line switches + @return: tuple ({switches,}, [args,]) + + """ + try: + items, args = getopt.getopt(sys.argv[1:], "dg:hp:vDSc:", + ['debug', 'help', 'version', 'auth', + 'confdir=', 'profileOut=']) + except getopt.GetoptError, msg: + # Raise error to console and exit + PrintHelp(str(msg)) + + # Process command line options + opts = dict(items) + for opt, value in dict(opts).items(): + if opt in ['-h', '--help']: + PrintHelp() + elif opt in ['-v', '--version']: + print(ed_glob.VERSION) + os._exit(0) + elif opt in ['-d', '--debug'] and '-D' not in opts.keys(): + # If the debug flag is set more than once go into verbose mode + if ed_glob.DEBUG: + ed_glob.VDEBUG = True + ed_glob.DEBUG = True + opts.pop(opt) + elif opt == '-D': + ed_glob.DEBUG = False + ed_glob.VDEBUG = False + opts.pop('-D') + elif opt == '-S': + # Disable single instance checker + ed_glob.SINGLE = False + opts.pop(opt) + elif opt in ['-c', '--confdir']: + ed_glob.CONFIG['CONFIG_BASE'] = value + opts.pop(opt) + elif opt == '--profileOut': + opts['-p'] = value + opts.pop('--profileOut') + elif opt == '-g': + # Validate argument passed to -g + if not value.isdigit(): + PrintHelp("error: -g requires a number as an argument!") + else: + pass + + # Return any unprocessed arguments + return opts, args + +#--------------------------------------------------------------------------# + +def Main(): + """Configures and Runs an instance of Editra + @summary: Parses command line options, loads the user profile, creates + an instance of Editra and starts the main loop. + + """ + opts, args = ProcessCommandLine() + + if '-p' in opts: + p_file = opts['-p'] + opts.pop('-p') + + if not len(p_file): + # Fall back to default output file + p_file = "editra.prof" + + import hotshot + prof = hotshot.Profile(p_file) + prof.runcall(_Main, opts, args) + prof.close() + else: + _Main(opts, args) + +def _Main(opts, args): + """Main method + @param opts: Commandline options + @param args: Commandline arguments + + """ + # Put extern subpackage on path so that bundled external dependencies + # can be found if needed. + if not hasattr(sys, 'frozen'): + epath = os.path.join(os.path.dirname(__file__), 'extern') + if os.path.exists(epath): + sys.path.append(epath) + + # Create Application + dev_tool.DEBUGP("[main][app] Initializing application...") + editra_app = Editra(False) + + # Print ipc server authentication info + if '--auth' in opts: + opts.pop('--auth') + print "port=%d,key=%s" % (ed_ipc.EDPORT, + profiler.Profile_Get('SESSION_KEY')) + + # Check if this is the only instance, if its not exit since + # any of the opening commands have already been passed to the + # master instance + if not editra_app.IsOnlyInstance(): + dev_tool.DEBUGP("[main][info] Second instance exiting...") + editra_app.Destroy() + os._exit(0) + + # Set the timeout on destroying the splash screen + wx.CallLater(2300, editra_app.DestroySplash) + + if profiler.Profile_Get('SET_WSIZE'): + wsize = profiler.Profile_Get('WSIZE') + else: + wsize = (700, 450) + frame = ed_main.MainWindow(None, wx.ID_ANY, wsize, ed_glob.PROG_NAME) + frame.Maximize(profiler.Profile_Get('MAXIMIZED')) + editra_app.RegisterWindow(repr(frame), frame, True) + editra_app.SetTopWindow(frame) + frame.Show(True) + + # Load Session Data + # But not if there are command line args for files to open + if profiler.Profile_Get('SAVE_SESSION', 'bool', False) and not len(args): + smgr = ed_session.EdSessionMgr() + session = profiler.Profile_Get('LAST_SESSION', default=u'') + if isinstance(session, list): + # Check for format conversion from previous versions + profiler.Profile_Set('LAST_SESSION', smgr.DefaultSession) + session = smgr.DefaultSession + frame.GetNotebook().LoadSessionFile(session) + del session + + # Unlike wxMac/wxGTK Windows doesn't post an activate event when a window + # is first shown, so do it manually to make sure all event handlers get + # pushed. + if wx.Platform == '__WXMSW__': + wx.PostEvent(frame, wx.ActivateEvent(wx.wxEVT_ACTIVATE, True)) + + # Do update check if preferences say its ok to do so + isadmin = os.access(ed_glob.CONFIG['INSTALL_DIR'], os.R_OK|os.W_OK) + if isadmin and profiler.Profile_Get('CHECKUPDATE', default=True): + uthread = updater.UpdateThread(editra_app, ID_UPDATE_CHECK) + uthread.start() + + if len(args): + line = -1 + if '-g' in opts: + line = max(0, int(opts.pop('-g')) - 1) + + # TODO: should line arg only be applied to the first file name or all? + # currently apply to all. + for arg in args: + try: + fname = ed_txt.DecodeString(arg, sys.getfilesystemencoding()) + fname = ebmlib.GetAbsPath(fname) + frame.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, fname, line) + except IndexError: + dev_tool.DEBUGP("[main][err] IndexError on commandline args") + + # Notify that profile was updated + if editra_app.GetProfileUpdated(): + editra_app.DestroySplash() + # Make sure window iniliazes to default position + profiler.Profile_Del('WPOS') + wx.MessageBox(_("Your profile has been updated to the latest " + "version") + u"\n" + \ + _("Please check the preferences dialog to verify " + "your preferences"), + _("Profile Updated")) + + # 3. Start Applications Main Loop + dev_tool.DEBUGP("[main][info] Starting MainLoop...") + wx.CallAfter(frame.Raise) + + # Install handlers to exit app if os is shutting down/restarting + ebmlib.InstallTermHandler(editra_app.Exit, force=True) + + editra_app.MainLoop() + dev_tool.DEBUGP("[main][info] MainLoop finished exiting application") + os._exit(0) + +#-----------------------------------------------------------------------------# +if __name__ == '__main__': + Main() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/__init__.py new file mode 100644 index 0000000..7902bda --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/__init__.py @@ -0,0 +1,13 @@ +############################################################################### +# Name: __init__.py # +# Purpose: Import the required base modules needed for launching Editra into # +# into the namespace. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### +"""Main package module""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: __init__.py 49807 2007-11-10 07:08:33Z CJP $" +__revision__ = "$Revision: 49807 $" diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/__init__.py new file mode 100644 index 0000000..edf32b7 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/__init__.py @@ -0,0 +1,22 @@ +############################################################################### +# Name: __init__.py # +# Purpose: Initializes the autocomp package # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +"""Autocomp sub package +@note: this may be removed when the autocomp system becomes part of the plugin + system + +""" +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: __init__.py 62467 2009-10-22 02:10:51Z CJP $" +__revision__ = "$Revision: 62467 $" + +#-----------------------------------------------------------------------------# +# Setup Public Namespace + +from autocomp import * +from completer import * diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/autocomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/autocomp.py new file mode 100644 index 0000000..8913aba --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/autocomp.py @@ -0,0 +1,112 @@ +############################################################################### +# Name: autocomp.py # +# Purpose: Provides the front end interface for autocompletion services for # +# the editor. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides an interface/service for getting autocompletion/calltip data +into an stc control. This is a data provider only it does not do provide +any UI functionality or calls. The user called object from this library +is intended to be the AutoCompService. This service provides the generic +interface into the various language specific autocomplete services, and +makes the calls to the other support objects/functions in this library. + +@summary: Autocompletion support interface implementation + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: autocomp.py 66207 2010-11-18 15:56:19Z CJP $" +__revision__ = "$Revision: 66207 $" +__all__ = ['AutoCompService',] + +#--------------------------------------------------------------------------# +# Dependencies +import wx +import wx.stc as stc + +# Local imports +import simplecomp + +#--------------------------------------------------------------------------# + +class AutoCompService(object): + """Interface to retrieve and provide autocompletion and + calltip information to an stc control. The plain text + (empty) completion provider is built in. All other providers + are loaded from external modules on request. + + """ + def __init__(self): + """Initializes the autocompletion service""" + super(AutoCompService, self).__init__() + + @staticmethod + def GetCompleter(buff, extended=False): + """Get the appropriate completer object for the given buffer. + @todo: implement dynamic loading mechanism for each comp class + + """ + lex_value = buff.GetLexer() + if lex_value == stc.STC_LEX_PYTHON: + import pycomp + compl = pycomp.Completer + elif lex_value in (stc.STC_LEX_HTML, stc.STC_LEX_XML): + import htmlcomp + compl = htmlcomp.Completer + elif lex_value == stc.STC_LEX_CSS: + import csscomp + compl = csscomp.Completer + else: + return simplecomp.Completer(buff) + + if extended: + compl = CompleterFactory(compl, buff) + else: + compl = compl(buff) + + return compl + +#--------------------------------------------------------------------------# + +class MetaCompleter(type): + """Meta class for creating custom completer classes at runtime""" + def __call__(mcs, base, buff): + """Modify the base class with our new methods at time of + instantiation. + + """ + obj = type.__call__(mcs, base, buff) + + # Set/override attributes on the new completer object. + setattr(obj, 'BaseGetAutoCompList', obj.GetAutoCompList) + setattr(obj, 'GetAutoCompList', lambda cmd: GetAutoCompList(obj, cmd)) + setattr(obj, 'scomp', simplecomp.Completer(buff)) + + # Return the new augmented completer + return obj + +def GetAutoCompList(self, command): + """Apply SimpleCompleter results to base results from the + 'smart' completer. + + """ + baseList = self.BaseGetAutoCompList(command) + scompList = self.scomp.GetAutoCompList(command) + # Wipeout duplicates by creating a set, then sort data alphabetically + baseList.extend(scompList) + rlist = list(set(baseList)) + rlist.sort() + return rlist + +class CompleterFactory(object): + """Factory for creating composite completer objects""" + __metaclass__ = MetaCompleter + def __new__(cls, base, buff): + """Return an instance of the passed in class type""" + self = base(buff) + return self diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/completer.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/completer.py new file mode 100644 index 0000000..77ad5cf --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/completer.py @@ -0,0 +1,304 @@ +############################################################################### +# Name: completer.py # +# Purpose: Autcompleter interface base class. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Base class for autocompletion providers to implement the completion interface. + +@summary: Autocompleter base class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: completer.py 70211 2011-12-31 02:23:54Z CJP $" +__revision__ = "$Revision: 70211 $" + +__all__ = [ 'TYPE_FUNCTION', 'TYPE_METHOD', 'TYPE_CLASS', 'TYPE_ATTRIBUTE', + 'TYPE_VARIABLE', 'TYPE_ELEMENT', 'TYPE_PROPERTY', 'TYPE_UNKNOWN', + 'BaseCompleter', 'Symbol', 'CreateSymbols' ] + +#--------------------------------------------------------------------------# +# Imports +import wx + +#--------------------------------------------------------------------------# + +# Image Type Ids +TYPE_FUNCTION, \ +TYPE_METHOD, \ +TYPE_CLASS, \ +TYPE_ATTRIBUTE, \ +TYPE_PROPERTY, \ +TYPE_VARIABLE, \ +TYPE_ELEMENT, \ +TYPE_UNKNOWN = range(1, 9) + +#--------------------------------------------------------------------------# +class Symbol(object): + """ Defines a symbol as parsed by the autocompleter. + Symbols with the same name and different type are EQUAL + Symbol hash is based on symbol NAME + + """ + # we create lots of these so use slots as a performance tweak + __slots__ = ('_name', '_type') + + def __init__(self, name, symtype): + """ Constructor + @param name: Symbol name + @param symtype: Symbol type, one of the TYPE_FUNCTION ... TYPE_UNKNOWN range + + """ + super(Symbol, self).__init__() + + # Attributes + self._name = unicode(name) + self._type = symtype + + def __eq__(self, other): + return (self.Name == other.Name) + + def __lt__(self, other): + return (self.Name < other.Name) + + def __le__(self, other): + return (self.Name <= other.Name) + + def __ne__(self, other): + return (self.Name != other.Name) + + def __gt__(self, other): + return (self.Name > other.Name) + + def __ge__(self, other): + return (self.Name >= other.Name) + + # TODO: this task should probably be delegated to the ui + def __str__(self): + if self.Type != TYPE_UNKNOWN: + return u'?'.join([self.Name, unicode(self.Type)]) + else: + return self.Name + + def __hash__(self): + return hash(self.Name) + + Name = property(lambda self: self._name, + lambda self, n: setattr(self, '_name', n)) + Type = property(lambda self: self._type, + lambda self, t: setattr(self, '_type', t)) + +#--------------------------------------------------------------------------# + +def CreateSymbols(arglst, symtype=TYPE_UNKNOWN): + """Convert a list of strings to a list of Symbol objects + @param arglst: list of strings + @keyword symtype: TYPE_FOO + @return: list of Symbols + + """ + return [ Symbol(obj, symtype) for obj in arglst ] + +#--------------------------------------------------------------------------# + +class BaseCompleter(object): + """Base Autocomp provider class""" + def __init__(self, parent): + """Initializes the auto-completion service + @param parent: parent of this service object + + """ + super(BaseCompleter, self).__init__() + + # Attributes + self._buffer = parent + self._log = wx.GetApp().GetLog() + self._case_sensitive = False + self._autocomp_after = False + self._choose_single = True + + self._autocomp_keys = list() + self._autocomp_stop = u'' + self._autocomp_fillup = u'' + self._calltip_keys = list() + self._calltip_cancel = list() + + #--- Override in subclass ----# + + def GetAutoCompList(self, command): + """Retrieves the sorted autocomplete list for a command + @param command: command string to do lookup on + @return: list of strings + + """ + return list() + + def GetCallTip(self, command): + """Returns the calltip string for a command + @param command: command to get calltip for (string) + @return: string + + """ + return u'' + + def OnCompletionInserted(self, pos, text): + """Called by the buffer when an autocomp selection has been inserted. + The completer can override this method to + @param pos: Position the caret was at before the insertion + @param text: text that was inserted at pos + + """ + pass + + #--- End override in subclass ----# + + def GetCommandString(self, stc, line, col): + """Get the command string found at the current location to use + for lookups. + @param stc: EditraStc + @param line: line text + @param col: position in line (column) + + """ + line = line.expandtabs(stc.GetTabWidth()) + line = line[:col] + if line and ord(line[-1]) in (self.GetAutoCompKeys() + self.GetCallTipKeys()): + line = line[:-1] + cmd_lmt = list(self.GetAutoCompStops() + self.GetAutoCompFillups()) + for key in self.GetAutoCompKeys(): + kval = unichr(key) + if kval in cmd_lmt: + cmd_lmt.remove(kval) + + cmd = u'' + curr_pos = len(line) - 1 + while curr_pos > -1: + cmd = line[curr_pos:] + if len(cmd) and cmd[0] not in cmd_lmt: + curr_pos -= 1 + else: + break + + for char in cmd_lmt: + cmd = cmd.replace(char, u'') + + return cmd.strip() + + def GetAutoCompKeys(self): + """Returns the list of key codes for activating the auto-completion. + @return: list of characters used for activating auto-completion + + """ + return self._autocomp_keys + + def SetAutoCompKeys(self, key_list): + """Set the keys to provide completions on + @param key_list: List of key codes + + """ + self._autocomp_keys = key_list + + def GetAutoCompStops(self): + """Returns a string of characters that should cancel + the auto-completion lookup. + @return: string of characters that will hide the autocomp/calltip + + """ + return self._autocomp_stop + + def SetAutoCompStops(self, stops): + """Set the keys to cancel auto-completions on. + @param stops: string + + """ + self._autocomp_stop = stops + + def GetAutoCompFillups(self): + """Get the list of characters to do a fillup on + @return: string + + """ + return self._autocomp_fillup + + def SetAutoCompFillups(self, fillups): + """Set the list of characters to do a fillup on + @param fillups: string + + """ + self._autocomp_fillup = fillups + + def GetCallTipKeys(self): + """Returns the list of keys to activate a calltip on + @return: list of calltip activation keys + + """ + return self._calltip_keys + + def SetCallTipKeys(self, keys): + """Set the list of keys to activate calltips on + @return: list of calltip activation keys + + """ + self._calltip_keys = keys + + def GetCallTipCancel(self): + """Get the list of key codes that should stop a calltip""" + return self._calltip_cancel + + def SetCallTipCancel(self, key_list): + """Set the list of key codes that should stop a calltip""" + self._calltip_cancel = key_list + + def GetBuffer(self): + """Get the reference to the buffer this autocomp object is owned by + @return: EditraStc + + """ + return self._buffer + + def GetCaseSensitive(self): + """Are commands case sensitive or not + @return: bool + + """ + return self._case_sensitive + + def SetCaseSensitive(self, sensitive): + """Set whether this completer is case sensitive or not + @param sensitive: bool + + """ + self._case_sensitive = sensitive + + def GetChooseSingle(self): + """Get whether the completer should automatically choose a selection + when there is only one symbol in the completion list. + @return: bool + + """ + return self._choose_single + + def SetChooseSingle(self, single): + """Set whether the completer should automatically choose a selection + when there is only one symbol in the completion list. + @param single: bool + + """ + self._choose_single = single + + def ShouldCheck(self, cpos): + """Should completions be attempted + @param cpos: current buffer position + @return: bool + + """ + buff = self.GetBuffer() + rval = True + if buff is not None: + if buff.IsString(cpos) or buff.IsComment(cpos): + rval = False + return rval diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/csscomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/csscomp.py new file mode 100644 index 0000000..f28b693 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/csscomp.py @@ -0,0 +1,169 @@ +############################################################################### +# Name: csscomp.py # +# Purpose: Simple input assistant for CSS # +# Author: Cody Precord # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Simple autocompletion support for Cascading Style Sheets. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: csscomp.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Imports +import re +import wx +import wx.stc + +# Local Imports +import completer + +#--------------------------------------------------------------------------# + +# Regular Expressions +RE_LINK_PSEUDO = re.compile("a:(link|visited|active|hover|focus)*") +RE_CSS_COMMENT = re.compile("\/\*[^*]*\*+([^/][^*]*\*+)*\/") +RE_CSS_BLOCK = re.compile("\{[^}]*\}") + +PSUEDO_SYMBOLS = completer.CreateSymbols([ u'active', u'focus', u'hover', + u'link', u'visited' ], + ) + +#--------------------------------------------------------------------------# + +class Completer(completer.BaseCompleter): + """CSS Code completion provider""" + def __init__(self, stc_buffer): + super(Completer, self).__init__(stc_buffer) + + # Setup + self.SetAutoCompKeys([ord(':'), ord('.') ]) + self.SetAutoCompStops(' {}#') + self.SetAutoCompFillups('') + self.SetCallTipKeys([ord('('), ]) + self.SetCallTipCancel([ord(')'), wx.WXK_RETURN]) + + def GetAutoCompList(self, command): + """Returns the list of possible completions for a command string. + @param command: command lookup is done on + + """ + buff = self.GetBuffer() + keywords = buff.GetKeywords() + if command in [None, u'']: + return completer.CreateSymbols(keywords, completer.TYPE_UNKNOWN) + + cpos = buff.GetCurrentPos() + cline = buff.GetCurrentLine() + lstart = buff.PositionFromLine(cline) + tmp = buff.GetTextRange(lstart, cpos).rstrip() + + # Check for the case of a pseudo class + if IsPsuedoClass(command, tmp): + return PSUEDO_SYMBOLS + + # Give some help on some common properties + if tmp.endswith(u':'): + word = GetWordLeft(tmp.rstrip().rstrip(u':')) + comps = PROP_OPTS.get(word, list()) + comps = list(set(comps)) + comps.sort() + return completer.CreateSymbols(comps, completer.TYPE_PROPERTY) + + # Look for if we are completing a tag class + if tmp.endswith(u'.'): + classes = list() + if not buff.IsString(cpos): + txt = buff.GetText() + txt = RE_CSS_COMMENT.sub(u'', txt) + txt = RE_CSS_BLOCK.sub(u' ', txt) + for token in txt.split(): + if u'.' in token: + classes.append(token.split(u'.', 1)[-1]) + + classes = list(set(classes)) + classes.sort() + return completer.CreateSymbols(classes, completer.TYPE_CLASS) + + return completer.CreateSymbols(keywords, completer.TYPE_UNKNOWN) + + def GetCallTip(self, command): + """Returns the formated calltip string for the command.""" + if command == u'url': + return u'url(\'../path\')' + else: + return u'' + + def ShouldCheck(self, cpos): + """Should completions be attempted + @param cpos: current buffer position + @return: bool + + """ + buff = self.GetBuffer() + rval = True + if buff is not None: + if buff.IsComment(cpos): + rval = False + return rval + +#--------------------------------------------------------------------------# + +def IsPsuedoClass(cmd, line): + """Check the line to see if its a link pseudo class + @param cmd: current command + @param line: line of the command + @return: bool + + """ + if cmd.endswith(u':'): + token = line.split()[-1] + pieces = token.split(u":") + if pieces[0] == 'a' or pieces[0].startswith('a.'): + return True + return False + +def GetWordLeft(line): + """Get the first valid word to the left of the end of line + @param line: Line text + @return: string + + """ + for idx in range(1, len(line)+1): + ch = line[idx*-1] + if ch.isspace() or ch in u'{;': + return line[-1*idx:].strip() + else: + return u'' + +#--------------------------------------------------------------------------# + +# Properties to provide some input help on +PROP_OPTS = { u'border-style' : [u'none', u'hidden', u'dotted', u'dashed', + u'solid', u'double', u'groove', u'ridge', + u'inset', u'outset'], + u'float' : [u'left', u'right', u'none'], + u'font-style' : [u'normal', u'italic', u'oblique'], + u'font-weight' : [u'normal', u'bold', u'lighter', u'bolder'], + u'list-style-type' : [u'none', u'disc', u'circle', u'square', + u'decimal', u'decimal-leading-zero', + u'lower-roman', u'upper-roman', + u'lower-alpha', u'upper-alpha', + u'lower-greek', u'lower-latin', u'hebrew', + u'armenian', u'georgian', u'cjk-ideographic', + u'hiragana', u'katakana', + u'hiragana-iroha', u'katakana-iroha'], + u'text-decoration' : [u'none', u'underline', u'line-through', + u'overline', u'blink'], + u'text-align' : [u'left', u'right', u'center', u'justify'], + u'vertical-align' : [u'baseline', u'sub', u'super', u'top', + u'text-top', u'middle', u'bottom', + u'text-bottom', ] + } + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/htmlcomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/htmlcomp.py new file mode 100644 index 0000000..4ca4dcd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/htmlcomp.py @@ -0,0 +1,192 @@ +############################################################################### +# Name: htmlcomp.py # +# Purpose: Simple input assistant for html and xml. # +# Author: Cody Precord # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Simple autocompletion support for HTML and XML documents. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: htmlcomp.py 72389 2012-08-28 16:53:09Z CJP $" +__revision__ = "$Revision: 72389 $" + +#--------------------------------------------------------------------------# +# Imports +import re +import wx +import wx.stc + +# Local Imports +import completer + +#--------------------------------------------------------------------------# +# Standard Html Tags +TAGS = ['!--', 'a', 'abbr', 'accept', 'accesskey', 'acronym', 'action', + 'address', 'align', 'alink', 'alt', 'applet', 'archive', 'area', + 'article', 'aside', 'audio', 'axis', 'b', 'background', 'base', + 'basefont', 'bdo', 'bgcolor', 'big', 'blockquote', 'body', 'border', + 'bordercolor', 'br', 'button', 'canvas', 'caption', 'cellpadding', + 'cellspacing', 'center', 'char', 'charoff', 'charset', 'checked', + 'cite', 'cite', 'class', 'classid', 'clear', 'code', 'codebase', + 'codetype', 'col', 'colgroup', 'color', 'cols', 'colspan', 'command', + 'compact', 'content', 'coords', 'data', 'datetime', 'datalist', 'dd', + 'declare', 'defer', 'del', 'details', 'dfn', 'dialog', 'dir', 'dir', + 'disabled', 'div', 'dl', 'dt', 'dtml-call', 'dtml-comment', 'dtml-if', + 'dtml-in', 'dtml-let', 'dtml-raise', 'dtml-tree', 'dtml-try', + 'dtml-unless', 'dtml-var', 'dtml-with', 'em', 'embed', 'enctype', + 'face', 'fieldset', 'figcaption', 'figure', 'font', 'for', 'form', + 'footer', 'frame', 'gutter', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', + 'header', 'headers', 'height', 'hgroup', 'hr', 'href', 'hreflang', + 'hspace', 'html', 'http-equiv', 'i', 'id', 'iframe', 'img', 'input', + 'ins', 'isindex', 'ismap', 'kbd', 'keygen', 'label', 'lang', 'language', + 'legend', 'li', 'link', 'link', 'longdesc', 'lowsrc', 'map', + 'marginheight', 'marginwidth', 'mark', 'maxlength', 'menu', 'meta', + 'meter', 'method', 'multiple', 'name', 'nav', 'nohref', 'noscript', + 'nowrap', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', + 'pre', 'profile', 'progress', 'prompt', 'q', 'readonly', 'rel', 'rev', + 'rows', 'rowspan', 'rp', 'rt', 'ruby', 'rules', 's', 'samp', 'scheme', + 'scope', 'script', 'scrolling', 'section', 'select', 'selected', + 'shape', 'size', 'small', 'source', 'span', 'src', 'standby', 'start', + 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'tabindex', + 'table', 'target', 'tbody', 'td', 'text', 'textarea', 'tfoot', 'th', + 'thead', 'time', 'title', 'tr', 'tt', 'type', 'u', 'ul', 'url', + 'usemap', 'valign', 'value', 'valuetype', 'var', 'version', 'video', + 'vlink', 'vspace', 'width', 'wrap', 'xmp'] + +# Tags that usually have a new line inbetween them +NLINE_TAGS = ('body', 'head', 'html', 'ol', 'style', 'table', 'tbody', 'ul') + +TAG_RE = re.compile("\<\s*([a-zA-Z][a-zA-Z0-9]*)") + +PHP_AREA = [wx.stc.STC_HPHP_COMMENT, wx.stc.STC_HPHP_COMMENTLINE, + wx.stc.STC_HPHP_COMPLEX_VARIABLE, wx.stc.STC_HPHP_DEFAULT, + wx.stc.STC_HPHP_HSTRING, wx.stc.STC_HPHP_HSTRING_VARIABLE, + wx.stc.STC_HPHP_NUMBER, wx.stc.STC_HPHP_OPERATOR, + wx.stc.STC_HPHP_SIMPLESTRING, + wx.stc.STC_HPHP_VARIABLE, wx.stc.STC_HPHP_WORD] + +HTML_AREA = [wx.stc.STC_H_ASP, wx.stc.STC_H_ASPAT, wx.stc.STC_H_ATTRIBUTE, + wx.stc.STC_H_ATTRIBUTEUNKNOWN, wx.stc.STC_H_CDATA, + wx.stc.STC_H_COMMENT, wx.stc.STC_H_DEFAULT, + wx.stc.STC_H_DOUBLESTRING, wx.stc.STC_H_ENTITY, + wx.stc.STC_H_NUMBER, wx.stc.STC_H_OTHER, wx.stc.STC_H_QUESTION, + wx.stc.STC_H_SCRIPT, wx.stc.STC_H_SGML_1ST_PARAM, + wx.stc.STC_H_SGML_1ST_PARAM_COMMENT, + wx.stc.STC_H_SGML_BLOCK_DEFAULT, wx.stc.STC_H_SGML_COMMAND, + wx.stc.STC_H_SGML_COMMENT, wx.stc.STC_H_SGML_DEFAULT, + wx.stc.STC_H_SGML_DOUBLESTRING, wx.stc.STC_H_SGML_ENTITY, + wx.stc.STC_H_SGML_ERROR, wx.stc.STC_H_SGML_SIMPLESTRING, + wx.stc.STC_H_SGML_SPECIAL, wx.stc.STC_H_SINGLESTRING, + wx.stc.STC_H_TAG, wx.stc.STC_H_TAGEND, + wx.stc.STC_H_TAGUNKNOWN, wx.stc.STC_H_VALUE, + wx.stc.STC_H_XCCOMMENT, wx.stc.STC_H_XMLEND, + wx.stc.STC_H_XMLSTART] + +#--------------------------------------------------------------------------# + +class Completer(completer.BaseCompleter): + """HTML/XML Code completion provider""" + def __init__(self, stc_buffer): + super(Completer, self).__init__(stc_buffer) + + # Setup + self.SetAutoCompKeys([ord('>'), ord('<')]) + self.SetAutoCompStops(' ') + self.SetAutoCompFillups('') + + def GetAutoCompList(self, command): + """Returns the list of possible completions for a + command string. + @param command: command lookup is done on + + """ + if command in [None, u'', u'<']: + return list() + + buff = self.GetBuffer() + cpos = buff.GetCurrentPos() + + # Check if we are in a php region or not + if buff.GetStyleAt(cpos) not in HTML_AREA: + return list() + + # Get current context + cline = buff.GetCurrentLine() + ccol = buff.GetColumn(cpos) + tmp = buff.GetLine(cline).rstrip() + if ccol < len(tmp): + tmp = tmp[:ccol].rstrip() + + # Check if we are completing an open tag (i.e < was typed) + if tmp.endswith('<'): + if buff.GetLexer() == wx.stc.STC_LEX_XML: + taglst = _FindXmlTags(buff.GetText()) + else: + taglst = TAGS + return completer.CreateSymbols(taglst, completer.TYPE_ELEMENT) + + # Check for a self closing tag (i.e />) + endchk = tmp.strip().replace(u" ", u"").replace(u"\t", u"") + if endchk.endswith(u"/>"): + return list() + + # Try to autocomplete a closing tag (if necessary) + tmp = tmp.rstrip('>').rstrip() + if len(tmp) and (tmp[-1] in '"\' \t' or tmp[-1].isalpha()): + # Walk backwards from the current line + for line in range(cline, -1, -1): + txt = buff.GetLine(line) + if line == cline: + txt = txt[:buff.GetColumn(cpos)] + + idx = txt.rfind('<') + if idx != -1: + parts = txt[idx:].lstrip('<').strip().split() + if len(parts): + tag = parts[0].rstrip('>') + if len(tag) and \ + tag not in ('img', 'br', '?php', '?xml', '?') and \ + not tag[0] in ('!', '/'): + rtag = u"</" + tag + u">" + + if not parts[-1].endswith('>'): + rtag = u">" + rtag + return [ completer.Symbol(rtag, completer.TYPE_ELEMENT) ] + break + + return list() + + def OnCompletionInserted(self, pos, text): + """Handle adjusting caret position after some insertions. + @param pos: position caret was at before insertion + @param text: text that was inserted + + """ + buff = self.GetBuffer() + if text.strip().startswith(u"</"): + buff.SetCurrentPos(pos) # move caret back between the tags + # HACK: SetCurrentPos causes text to be selected + buff.SetSelection(pos, pos) + +#--------------------------------------------------------------------------# + +def _FindXmlTags(text): + """Dynamically generate a list of possible xml tags based on tags found in + the given text. + @param text: string + @return: sorted list + + """ + matches = TAG_RE.findall(text) + if len(matches): + matches.append(u'!--') + matches = list(set(matches)) + matches.sort() + else: + matches = [u'!--', ] + return matches diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/pycomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/pycomp.py new file mode 100644 index 0000000..e76ca32 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/pycomp.py @@ -0,0 +1,1039 @@ +############################################################################### +# Name: pycomp.py # +# Purpose: Provides python autocompletion lists and calltips for the editor # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides completion and calltip support for python documents. To provide the +completion lists and calltips a mix of parsing and introspection is used to +deduct the requested information. + +@summary: Python autocompletion support + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: pycomp.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Dependancies +import os +import sys +import time +import tokenize +import types +from token import NAME, DEDENT, STRING + +import wx +from wx.py import introspect + +from StringIO import StringIO + +# Local imports +import completer + +#--------------------------------------------------------------------------# + +class Completer(completer.BaseCompleter): + """Python Code completion provider""" + def __init__(self, stc_buffer): + """Initializes the completer + @param stc_buffer: buffer that contains code + + """ + super(Completer, self).__init__(stc_buffer) + + # Setup + self.SetAutoCompKeys([ord('.'), ]) + self.SetAutoCompStops(' \'"\\`):') + self.SetAutoCompFillups('.,;([]}<>%^&+-=*/|') + self.SetCallTipKeys([ord('('), ]) + self.SetCallTipCancel([ord(')'), wx.WXK_RETURN]) + + # Needed for introspect to run + try: + sys.ps1 + except AttributeError: + sys.ps1 = '>>>' + + try: + sys.ps2 + except AttributeError: + sys.ps2 = '...' + + def _GetCompletionInfo(self, command, calltip=False): + """Get Completion list or Calltip + @return: list or string + + """ + if command is None or (len(command) and command[0].isdigit()): + if calltip: + return u"" + return list() + + try: + cmpl = PyCompleter() + + # Put the files directory on the path so eval has a better + # chance of getting the proper completions + fname = self._buffer.GetFileName() + if fname: + fpath = os.path.dirname(fname) + sys.path.insert(0, fpath) + snapshot = list(sys.modules.keys()) + + t1 = time.time() + cmpl.evalsource(self._buffer.GetText(), + self._buffer.GetCurrentLine()) + dbg("[pycomp][info] Completion eval time: %f" % (time.time() - t1)) + + if fname: + sys.path.pop(0) + + # Dump any other modules that got brought in during eval + # so that they get properly updated on next pass through. + nsnapshot = sys.modules.keys() + nimport = list(set(nsnapshot).difference(set(snapshot))) + for k in nimport: + del sys.modules[k] + + if calltip: + return cmpl.get_completions(command + u'(', u'', calltip) + else: + # Get Auto-completion List + complst = cmpl.get_completions(command) + sigs = list() + tmap = {"function" : completer.TYPE_FUNCTION, + "method" : completer.TYPE_METHOD, + "class" : completer.TYPE_CLASS, + "attribute" : completer.TYPE_ATTRIBUTE, + "property" : completer.TYPE_PROPERTY} + for sig in complst: + word = sig['word'].rstrip(u'(.') + tval = tmap.get(sig['type'], completer.TYPE_UNKNOWN) + sigs.append(completer.Symbol(word, tval)) + sigs.sort(key=lambda x: x.Name.upper()) + return sigs + + except BaseException, msg: + self._log("[pycomp][err] _GetCompletionInfo: %s, %s" % \ + (sys.exc_info()[0], sys.exc_info()[1])) + if calltip: + return u"" + else: + return list() + + def GetAutoCompList(self, command): + """Returns the list of possible completions for a command string. + @param command: command lookup is done on + + """ + return self._GetCompletionInfo(command) + + def GetCallTip(self, command): + """Returns the formatted calltip string for the command. + @param command: command to get calltip for + + """ + # get the relevant text + alltext = self._GetCompletionInfo(command, calltip=True) + + # split the text into natural paragraphs (a blank line separated) + paratext = alltext.split("\n\n") + + # add text by paragraph until text limit or all paragraphs + textlimit = 800 + if len(paratext[0]) < textlimit: + numpara = len(paratext) + calltiptext = paratext[0] + ii = 1 + while ii < numpara and \ + (len(calltiptext) + len(paratext[ii])) < textlimit: + calltiptext = calltiptext + "\n\n" + paratext[ii] + ii = ii + 1 + + # if not all texts are added, add "[...]" + if ii < numpara: + calltiptext = calltiptext + "\n[...]" + # present the function signature only (first newline) + else: + calltiptext = alltext.split("\n")[0] + + if type(calltiptext) != types.UnicodeType: + # Ensure it is unicode + try: + stcbuff = self.GetBuffer() + encoding = stcbuff.GetEncoding() + calltiptext = calltiptext.decode(encoding) + except Exception, msg: + dbg("%s" % msg) + + return calltiptext + +#-----------------------------------------------------------------------------# +# This code below is a modified and adapted version of the pythoncomplete +# Omni completion script for vim. The original vimscript can be found at the +# following address: http://www.vim.org/scripts/script.php?script_id=1542 +def dbg(msg): + wx.GetApp().GetLog()(msg) + +class PyCompleter(object): + """Python code completion provider""" + def __init__(self): + self.compldict = {} + self.parser = PyParser() + + def evalsource(self, text, line=0): + """Evaluate source for introspection + @param text: Text to evaluate + @keyword line: current line of cursor + + """ + scope = self.parser.parse(text.replace('\r\n', '\n'), line) + src = scope.get_code() + # Test +# f = open('pycompout.py', 'w') +# f.write(src) +# f.close() + # NOTE: keep commented out in production code can cause slow down + # when running in editra with DEBUG output. +# dbg("[pycomp][info] Generated source: %s" % src) + try: + exec src in self.compldict + except Exception, msg: + dbg("[pycomp][err] src exec: %s" % msg) + else: + dbg("[pycomp][info] Successfully executed source code") + + for loc in [ l[1] for l in scope.locals]: + try: + exec loc in self.compldict + except Exception, msg: + dbg("[pycomp][err] local exec %s [%s]" % (msg, loc)) + else: + dbg("[pycomp][info] Successfully executed: %s" % loc) + + def get_arguments(self, func_obj): + """Get the arguments of a given function obj + @param func_obj: function object to get parameters for + + """ + def _ctor(obj): + """Get the constructor for an object""" + try: + return obj.__init__.im_func + except AttributeError: + for base in obj.__bases__: + constructor = getattr(base, '__init__', None) + if constructor is not None: + return constructor + return None + + arg_offset = 1 + if type(func_obj) == types.ClassType: + func_obj = _ctor(func_obj) + elif type(func_obj) == types.MethodType: + func_obj = func_obj.im_func + else: + arg_offset = 0 + + arg_text = '' + if type(func_obj) in [types.FunctionType, types.LambdaType]: + try: + fcode = func_obj.func_code + real_args = fcode.co_varnames[arg_offset:fcode.co_argcount] + defaults = func_obj.func_defaults or '' + defaults = [ "=%s" % name for name in defaults ] + defaults = [""] * (len(real_args) - len(defaults)) + defaults + items = [ arg + default + for arg, default in zip(real_args, defaults) ] + if fcode.co_flags & 0x4: + items.append("...") + if fcode.co_flags & 0x8: + items.append("***") + arg_text = (','.join(items)) + ')' + + except Exception, msg: + dbg("[pycomp][err] get_arguments: %s" % msg) + + if len(arg_text) == 0: + # The doc string sometimes contains the function signature + # this works for alot of C modules that are part of the + # standard library + doc = getattr(func_obj, '__doc__', False) + if doc: + doc = str(doc) + doc = doc.lstrip() + pos = doc.find('\n') + if pos > 0: + sigline = doc[:pos] + lidx = sigline.find('(') + ridx = sigline.find(')') + if lidx > 0 and ridx > 0: + arg_text = sigline[lidx + 1 : ridx] + ')' + + if len(arg_text) == 0: + arg_text = ')' + + return arg_text + + def get_completions(self, context, match='', ctip=False): + """Get the completions for the given context + @param context: command string to get completions for + @keyword match: for matching an incomplete command string + @keyword ctip: Get a calltip for the context instead of completion list + @return: list of dictionaries + + """ + dbg("[pycomp] get_completions('%s','%s')" % (context, match)) + stmt = context + match + + try: + result = None + compdict = {} + ridx = stmt.rfind('.') + if len(stmt) > 0 and stmt[-1] == '(': + if ctip: + # Try introspect.getCallTip since it is generally + # better at getting tips for c modules + tip = introspect.getCallTip(_sanitize(stmt), + self.compldict)[2] + if not isinstance(tip, basestring): + tip = u"" + if not tip: + # Internal calltip code + result = eval(_sanitize(stmt.rstrip('(')), self.compldict) + doc = max(getattr(result, '__doc__', ''), ' ') + argval = context + _cleanstr(self.get_arguments(result)) + tip = '\n'.join([argval, _cleanstr(doc)]) + dbg("[pycomp][info] Used internal calltips") + return tip + + elif ridx == -1: + match = stmt + compdict = self.compldict + else: + match = stmt[ridx+1:] + stmt = _sanitize(stmt[:ridx]) + result = eval(stmt, self.compldict) + compdict = dir(result) + + dbg("[pycomp] completing: stmt:%s" % stmt) + completions = [] + isdict = isinstance(compdict, dict) + for meth in compdict: + if meth == "_PyCmplNoType": + continue #this is internal + + try: +# dbg('[pycomp] possible completion: %s' % meth) + if meth.find(match) == 0: + if result is None: + # NOTE: when result is none compdict is a list + inst = meth #compdict[meth] + else: + inst = getattr(result, meth, None) + + # TODO: necessary check to handle some odd swig related + # errors. Find out why type 'swigvarlink' causes + # the exception Unknown C global variable. + if len(dir(inst)): + doc = getattr(inst, '__doc__', None) + if doc is None: + doc = max(getattr(result, '__doc__', ' '), ' ') + else: + doc = ' ' + + if isdict: + typestr = str(compdict[inst]) + else: + typestr = str(inst) + + comp = {'word' : meth, + 'abbr' : meth, + 'info' : _cleanstr(str(doc)), + 'type' : typestr} + + if "function" in typestr: + comp['word'] += '(' + comp['abbr'] += '(' + _cleanstr(self.get_arguments(inst)) + comp['type'] = "function" + elif "method" in typestr or "slot wrapper" in typestr: + comp['word'] += '(' + comp['abbr'] += '(' + _cleanstr(self.get_arguments(inst)) + comp['type'] = "method" + elif "module" in typestr: + comp['word'] += '.' + comp['type'] = "module" + elif "class" in typestr: + comp['word'] += '(' + comp['abbr'] += '(' + comp['type'] = "class" + elif "attribute" in typestr or \ + (not typestr.startswith('__') and \ + not typestr.startswith('<')): + comp['type'] = "attribute" + elif "property" in typestr: + comp['type'] = "property" +# else: +# print typestr, meth + + completions.append(comp) + except Exception, msg: + dbg("[pycomp][err] inner completion: %s [stmt='%s']:" % (msg, stmt)) + + return completions + except Exception, msg: + dbg("[pycomp][err] get_completions: %s [stmt='%s']" % (msg, stmt)) + if ctip: + return u"" + return list() + +#-----------------------------------------------------------------------------# +# Code objects + +class Scope(object): + """Base class for representing code objects""" + def __init__(self, name, indent): + """Initialize the scope + @param name: name of this object + @param indent: the indentation/level of this scope + + """ + super(Scope, self).__init__() + + # Attributes + self.subscopes = list() + self.docstr = u'' + self.locals = list() + self.parent = None + self.name = name + self.indent = indent + self.objid = -1 # Tracks order of declaration + + DocStr = property(lambda self: self.docstr, + lambda self, dstr: setattr(self, 'docstr', dstr)) + Locals = property(lambda self: self.locals, + lambda self, loc: setattr(self, 'locals', loc)) + Parent = property(lambda self: self.parent, + lambda self, parent: setattr(self, 'parent', parent)) + + def Clone(self, indent=0): + """Clone this scope object""" + obj = Scope(self.name, indent) + obj.DocStr = self.DocStr + obj.Locals = list(self.Locals) + obj.Parent = self.Parent + for scope in self.subscopes: + obj.subscopes.append((scope[0], scope[1].Clone(indent + 1))) + obj.objid = self.objid + return obj + + def NextObjId(self): + self.objid += 1 + return self.objid + + def add(self, sub): + """Push a subscope into this scope + @param sub: sub scope to push + + """ + sub.parent = self + self.subscopes.append((self.NextObjId(), sub)) + return sub + + def doc(self, docstr): + """Format and set the doc string for this scope + @param docstr: Docstring to format and set + + """ + dstr = docstr + if len(dstr): + while len(dstr) and dstr[0] in '"\' ': + dstr = dstr[1:] + + while len(dstr) and dstr[-1] in '"\' ': + dstr = dstr[:-1] + dstr = '\n'.join([d.lstrip() for d in dstr.split('\n')]) + self.docstr = dstr.rstrip() + + def local(self, loc): + """Add an object to the scopes locals + @param loc: local object to add to locals + + """ + self._checkexisting(loc) + self.locals.append((self.NextObjId(), loc)) + + def _checkexisting(self, test): + """Convenience function... keep out duplicates + @param test: assignment statement to check for existence of + variable in the scopes locals + + """ + if '=' in test: + var = test.split('=')[0].strip() + for loc in self.locals: + if '=' in loc[1] and var == loc[1].split('=')[0].strip(): + self.locals.remove(loc) + + def get_code(self): + """Get a string of code that represents this scope + @return: string + + """ + cstr = '"""' + self.docstr + '"""\n' + nonimport = list() + for loc in self.locals: + if loc[1].startswith('import') or loc[1].startswith('from'): + cstr += ("try:\n %s\nexcept ImportError:\n pass\n" % loc[1]) + else: + nonimport.append(loc) + + # we need to start with this, to fix up broken completions + # hopefully this name is unique enough... + cstr += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n' + + decls = self.subscopes + nonimport + decls.sort(key=lambda x: x[0]) + for decl in [d[1] for d in decls]: + if isinstance(decl, Scope): + cstr += decl.get_code() + else: + cstr += decl + '\n' + + return cstr + + def pop(self, indent): + """Pop the scope until it is at the level of the given + indent. + @param indent: indent level to pop scope to + @return: scope of given indent level + + """ + outer = self + while outer.parent != None and outer.indent >= indent: + outer = outer.parent + return outer + + def currentindent(self): + """Return string of current scopes indent level + @return: string of spaces + + """ + return ' ' * self.indent + + def childindent(self): + """Return string the next scopes indentation level + @return: string of spaces + + """ + return ' ' * (self.indent + 1) + +class Class(Scope): + """Class for representing a python class object for the parser""" + def __init__(self, name, supers, indent): + """initialize the class object + @param name: name of class + @param supers: classes super classes + @param indent: scope of indentation + + """ + super(Class, self).__init__(name, indent) + self.supers = supers + + def Clone(self, indent=0): + """Create a clone of this object""" + obj = Class(self.name, self.supers, indent) + obj.DocStr = self.DocStr + obj.Locals = list(self.Locals) + obj.Parent = self.Parent + obj.objid = self.objid + for scope in self.subscopes: + obj.subscopes.append((scope[0], scope[1].Clone(indent + 1))) + return obj + + def get_code(self): + """Get the code string representation of the Class object + @return: string + + """ + cstr = '%sclass %s' % (self.currentindent(), self.name) + if len(self.supers) > 0: + cstr += '(%s)' % ','.join(self.supers) + + cstr += ':\n' + if len(self.docstr) > 0: + cstr += self.childindent() + '"""' + self.docstr + '"""\n' + need_pass = True + decls = self.locals + self.subscopes + decls.sort(key=lambda x: x[0]) + for decl in [d[1] for d in decls]: + need_pass = False + if isinstance(decl, Scope): + cstr += decl.get_code() + else: + cstr += ('%s%s\n' % (self.childindent(), decl)) + + if need_pass: + cstr += '%spass\n' % self.childindent() + return cstr + + def local(self, loc): + """Add an object to the scopes locals + @param loc: local object to add to locals + + """ + if loc and '.' not in loc: + super(Class, self).local(loc) + +class Function(Scope): + """Create a function object for representing a python function + definition in the parser. + + """ + def __init__(self, name, params, indent): + """Create the function object + @param name: name of function + @param params: the functions parameters + @param indent: indentation level of functions declaration (scope) + + """ + super(Function, self).__init__(name, indent) + self.params = params + + def Clone(self, indent=0): + """Create a copy of the functions declaration at the given + scope of indentation. + @keyword indent: indentation level of the declaration + + """ + obj = Function(self.name, self.params, indent) + obj.DocStr = self.DocStr + obj.Locals = list(self.Locals) + obj.Parent = self.Parent + for scope in self.subscopes: + obj.subscopes.append((scope[0], scope[1].Clone(indent + 1))) + obj.objid = self.objid + return obj + + def get_code(self): + """Get code string representation of the function object + @return: string + + """ + cstr = "%sdef %s(%s):\n" % \ + (self.currentindent(), self.name, ','.join(self.params)) + if len(self.docstr) > 0: + cstr += self.childindent() + '"""' + self.docstr + '"""\n' + cstr += "%spass\n" % self.childindent() + return cstr + +#-----------------------------------------------------------------------------# +# Main Parser + +class PyParser(object): + """Python parsing class""" + def __init__(self): + """Initialize and create the PyParser""" + super(PyParser, self).__init__() + + # Attributes + self.top = Scope('global', 0) + self.scope = self.top + self.gen = None # Token Generator + self.curline = 0 # Current parse line + self.currentscope = None # Current scope in parse + + def _parsedotname(self, pre=None): + """Parse a dotted name string + @return: tuple of (dottedname, nexttoken) + + """ + name = list() + if pre is None: + tokentype, token = self.next()[:2] + if token == '(': + self._parenparse() + if tokentype != NAME and token != '*': + return ('', token) + else: + token = pre + + name.append(token) + while True: + tokentype, token = self.next()[:2] + if token == '(': + # Handle 'self.foo(a,b,c)' + self._parenparse() + break + + if token != '.': + break + + tokentype, token = self.next()[:2] + if tokentype != NAME: + break + name.append(token) + return (".".join(name), token) + + def _parseimportlist(self): + """Parse and collect import statements + @return: list of imports + + """ + imports = [] + while True: + name, token = self._parsedotname() + if not name: + break + + name2 = '' + if token == 'as': + name2, token = self._parsedotname() + + imports.append((name, name2)) + while token != "," and "\n" not in token: + token = self.next()[1] + + if token != ",": + break + + return imports + + def _parenparse(self): + """Parse paren enclosed statement + @return: list of named items enclosed in the parens + + """ + name = '' + names = [] + level = 1 + while True: + token = self.next()[1] + if token in (')', ',') and level == 1: + # Remove keyword assignments as they can + # cause eval breakage when using undefined + # vars. + if '=' in name: + name = name.split('=')[0].strip() + names.append(name) + name = '' + + if token == '(': + level += 1 + elif token == ')': + level -= 1 + if level == 0: + break + elif token == ',' and level == 1: + pass + else: + name += str(token) + + return names + + def _parsefunction(self, indent): + """Parse a function definition at the given scope of + indentation and create a class token object from the + results. + @param indent: scope of functions declaration + + """ + self.scope = self.scope.pop(indent) + tokentype, fname, findent = self.next() + if tokentype != NAME: + return None + + tokentype, open_paren, tindent = self.next() + if open_paren != '(': + return None + + params = self._parenparse() + tokentype, colon, tindent = self.next() + if colon != ':': + return None + + return Function(fname, params, indent) + + def _parseclass(self, indent): + """Parse a class definition at the given scope of + indentation and create a class token object from the + results. + @param indent: scope of classes declaration + + """ + self.scope = self.scope.pop(indent) + tokentype, cname = self.next()[:-1] + if tokentype != NAME: + return None + + super_cls = [] + tokentype, next = self.next()[:-1] + if next == '(': + super_cls = self._parenparse() + elif next != ':': + return None + + return Class(cname, super_cls, indent) + + def _parseassignment(self): + """Parse a variable assignment to resolve the variables type + for introspection. + @return: string of objects type + + """ + assign = '' + tokentype, token = self.next()[:-1] + tokens = { + # Dict + '{' : '{}', 'dict' : '{}', + 'locals' : '{}', 'globals' : '{}', + # File + 'open' : 'file', 'file' : 'file', + # List + '[' : '[]', 'list' : '[]', + 'dir' : '["",""]', 'zip' : '[]', 'map' : '[]', + 'sorted' : '[]', 'range' : '[]', + # NoneType + 'None' : '_PyCmplNoType()', + # Number + tokenize.NUMBER : '0', 'ord' : '0', 'id' : '0', + 'abs' : '0', 'sum' : '0', 'pow' : '0', 'len' : '0', + 'hash' : '0', + # Property + 'property' : 'property()', + # String + tokenize.STRING : '""', 'str' : '""', + 'repr' : '""', 'chr' : '""', 'unichr' : '""', + 'hex' : '""', 'oct' : '""', "'" : '""', '"' : '""', + # Type + 'type' : 'type(_PyCmplNoType)', + # Tuple + '(' : '()', 'tuple' : '()', 'coerce' : '()' + } + + if tokentype == tokenize.NUMBER or tokentype == tokenize.STRING: + return token #token = tokentype + + if token in tokens: + return tokens[token] + else: + # NOTE: This part of the parse is where the problem is happening + assign += token + level = 0 + while True: + tokentype, token = self.next()[:-1] + if token in ('(', '{', '['): + level = level + 1 + elif token in (']', '}', ')'): + level = level - 1 + if level == 0 or level == -1: + break + elif level == 0: + # end of line + if token in (';', '\n', '='): + break + elif token in ('+', '*'): + # Attempt simple type deduction based on + # operator statement. + if assign.endswith('"') or assign.endswith("'"): + assign = '""' + else: + assign = '0' + break + elif token in ('/', '-'): + # assignment most likely returns an digit type + # this is the best guess we can make + assign = '0' + break + elif token in ('and', 'or', 'in', '==', + '<', '>', '!=', 'not', '>=', '<='): + # right side of assignment likely evaluates to bool + assign = 'bool' + break +# elif token == ',': +# assign = '' + else: + if token == '.' or assign.endswith('.'): + assign += token + else: + assign += (" %s" % token) + + # Check syntax to filter out bad tokens + try: + compile(assign, '_pycomp', 'eval') + except: + dbg("[pycomp][err] parseassignment bad token: %s" % assign) + return '_PyCmplNoType()' + else: + return assign + + def next(self): + """Get tokens of next line in parse + @return: tuple of (type, token, indent) + + """ + ttype, token, (lineno, indent) = self.gen.next()[:3] + if lineno == self.curline: + self.currentscope = self.scope + return (ttype, token, indent) + + def _adjustvisibility(self): + """Adjust the visibility of the current contexts scope + @return: current scope + + """ + newscope = Scope('result', 0) + scopes = list() + tscp = self.currentscope.parent + while tscp != None: + scopes.append(tscp) + tscp = tscp.parent + scopes.append(self.currentscope) + + for scp in scopes: + if type(scp) == Function: + cut = 0 + # Handle 'self' params + if scp.parent != None and type(scp.parent) == Class: + cut = 1 + params = scp.params[0] + ind = params.find('=') + if ind != -1: + params = params[:ind] + newscope.local('%s = %s' % (_sanitizeParam(scp.params[0]), scp.parent.name)) + + for param in scp.params[cut:]: + ind = param.find('=') + if len(param) == 0: + continue + if ind == -1: + newscope.local('%s = _PyCmplNoType()' % _sanitizeParam(param)) + else: + newscope.local('%s = %s' % (_sanitizeParam(param[:ind]), + _sanitize(param[ind+1:]))) + + decls = scp.subscopes + scp.locals + decls.sort(key=lambda x: x[0]) + for decl in [d[1] for d in decls]: + if isinstance(decl, Scope): + newscope.add(decl.Clone(0)) + else: + newscope.local(decl) + + self.currentscope = newscope + return self.currentscope + + def parse(self, text, curline=0): + """Parse the given text + @param text: python code text to parse + @keyword curline: current line of cursor for context + + """ + self.curline = curline + buf = StringIO(text) + self.gen = tokenize.generate_tokens(buf.readline) + self.currentscope = self.scope + + try: + freshscope = True + while True: + tokentype, token, indent = self.next() + if tokentype == DEDENT or token == "pass": + self.scope = self.scope.pop(indent) + elif token == 'def': + func = self._parsefunction(indent) + if func == None: + continue + freshscope = True + self.scope = self.scope.add(func) + elif token == 'class': + cls = self._parseclass(indent) + if cls == None: + continue + freshscope = True + self.scope = self.scope.add(cls) + + elif token == 'import': + imports = self._parseimportlist() + for mod, alias in imports: + loc = "import %s" % mod + if len(alias) > 0: + loc += " as %s" % alias + self.scope.local(loc) + freshscope = False + elif token == 'from': + mod, token = self._parsedotname() + if not mod or token != "import": + continue + names = self._parseimportlist() + for name, alias in names: + loc = "from %s import %s" % (mod, name) + if len(alias) > 0: + loc += " as %s" % alias + self.scope.local(loc) + freshscope = False + + elif tokentype == STRING: + if freshscope: + self.scope.doc(token) + elif tokentype == NAME: + name, token = self._parsedotname(token) + if token == '=': + stmt = self._parseassignment() + dbg("[pycomp] parseassignment: %s = %s" % (name, stmt)) + if stmt != None: + # XXX Safety Check don't allow assignments to + # item attributes unless the attribute is self + if u'.' not in name or name.startswith('self.'): + self.scope.local("%s = %s" % (name, stmt)) + freshscope = False + except StopIteration: #thrown on EOF + pass + except: + dbg("[pycomp][err] Pyparser.parse: %s, %s" % + (sys.exc_info()[0], sys.exc_info()[1])) + return self._adjustvisibility() + +#-----------------------------------------------------------------------------# +# Utility Functions +def _cleanstr(doc): + """Clean up a docstring by removing quotes + @param doc: docstring to clean up + + """ + return doc.replace('"', ' ').replace("'", ' ') + +def _sanitize(cstr): + """Sanitize a command string for namespace lookup + @param cstr: command string to cleanup + + """ + val = '' + level = 0 + for char in cstr: + if char in ('(', '{', '['): + level += 1 + elif char in (']', '}', ')'): + level -= 1 + elif level == 0: + val += char + return val + +def _sanitizeParam(param): + """Cleanup a value string + value = foo + to ensure that 'value' is syntactically correct. + + """ + for i, c in enumerate(param): + if c.isalpha() or c == '_': + return param[i:] + else: + return param # something is wrong so let it bomb + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/simplecomp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/simplecomp.py new file mode 100644 index 0000000..c2e0bdd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/autocomp/simplecomp.py @@ -0,0 +1,120 @@ +############################################################################### +# Name: simplecomp.py # +# Purpose: Simple autocompletion based on buffer words (SciTE docet) # +# Author: Giuseppe "Cowo" Corbelli # +# Copyright: (c) 2009 Giuseppe "Cowo" Corbelli # +# License: wxWindows License # +############################################################################### + +""" +Simple Generic autocompleter for completing words found in the current buffer. + +""" + +__author__ = "Giuseppe \"Cowo\" Corbelli" +__cvsid__ = "$Id: simplecomp.py 72222 2012-07-28 15:43:38Z CJP $" +__revision__ = "$Revision: 72222 $" + +#--------------------------------------------------------------------------# +# Imports +import string +import wx.stc as stc + +# Local Imports +import completer + +#--------------------------------------------------------------------------# + +class Completer(completer.BaseCompleter): + """Generic word completer provider""" + wordCharacters = "".join(['_', string.letters]) + + def __init__(self, stc_buffer): + super(Completer, self).__init__(stc_buffer) + + # Setup + self.SetAutoCompKeys([]) + self.SetAutoCompStops(' \'"\\`):') + self.SetAutoCompFillups('.,:;([]){}<>%^&+-=*/|$@') + self.SetCallTipKeys([]) + self.SetCallTipCancel([]) + self.SetCaseSensitive(False) + + def _GetCompletionInfo(self, command, calltip=False): + """Get Completion list or Calltip + @return: list or string + + """ + bf = self.GetBuffer() + # A list of Symbol(keyword, TYPE_UNKNOWN) + kwlst = map( + lambda kw: completer.Symbol(kw, completer.TYPE_UNKNOWN), + bf.GetKeywords() + ) + + if command in (None, u''): + return kwlst + + fillups = self.GetAutoCompFillups() + if command[0].isdigit() or (command[-1] in fillups): + return list() + + currentPos = bf.GetCurrentPos() + + # Get the real word: segment using autocompFillup + tmp = command + for ch in fillups: + tmp = command.strip(ch) + ls = list(tmp) + ls.reverse() + + idx = 0 + for c in ls: + if c in fillups: + break + idx += 1 + ls2 = ls[:idx] + ls2.reverse() + command = u"".join(ls2) + + # Available completions so far + wordsNear = [] + maxWordLength = 0 + nWords = 0 + minPos = 0 + maxPos = bf.GetLength() + flags = stc.STC_FIND_WORDSTART + if self.GetCaseSensitive(): + flags |= stc.STC_FIND_MATCHCASE + + posFind = bf.FindText(minPos, maxPos, command, flags) + while posFind >= 0 and posFind < maxPos: + wordEnd = posFind + len(command) + if posFind != currentPos: + while -1 != Completer.wordCharacters.find(chr(bf.GetCharAt(wordEnd))): + wordEnd += 1 + + wordLength = wordEnd - posFind + if wordLength > len(command): + word = bf.GetTextRange(posFind, wordEnd) + sym = completer.Symbol(word, completer.TYPE_UNKNOWN) + if not wordsNear.count(sym): + wordsNear.append(sym) + maxWordLength = max(maxWordLength, wordLength) + nWords += 1 + + minPos = wordEnd + posFind = bf.FindText(minPos, maxPos, command, flags) + + if len(wordsNear) > 0 and (maxWordLength > len(command)): + return wordsNear + + return kwlst + + def GetAutoCompList(self, command): + """Returns the list of possible completions for a command string. + @param command: command lookup is done on + + """ + rlist = self._GetCompletionInfo(command) + return sorted(list(set(rlist))) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/dev_tool.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/dev_tool.py new file mode 100644 index 0000000..c572d80 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/dev_tool.py @@ -0,0 +1,343 @@ +############################################################################### +# Name: dev_tool.py # +# Purpose: Provides logging and error tracking utilities # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" Editra Development Tools +Tools and Utilities for debugging and helping with development of Editra. +@summary: Utility function for debugging the editor + +""" +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: dev_tool.py 72623 2012-10-06 19:33:06Z CJP $" +__revision__ = "$Revision: 72623 $" + +#-----------------------------------------------------------------------------# +# Imports +import os +import sys +import re +import traceback +import time +import urllib2 +import webbrowser +import codecs +import locale +import wx + +# Editra Libraries +import ed_glob +import ed_msg +import eclib +from ebmlib import IsUnicode, LogFile + +#-----------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation +RE_LOG_LBL = re.compile(r"\[(.+?)\]") + +# The default fallback encoding +DEFAULT_ENCODING = locale.getpreferredencoding() +try: + codecs.lookup(DEFAULT_ENCODING) +except (LookupError, TypeError): + DEFAULT_ENCODING = 'utf-8' + +PYTHONW = 'pythonw' in sys.executable.lower() + +#-----------------------------------------------------------------------------# +# General Debugging Helper Functions +def DEBUGP(statement, *args): + """Prints debug messages and broadcasts them on the log message channel. + Subscribing a listener with any of the EDMSG_LOG_* types will recieve its + messages from this method. + + 1. Formatting + - [object/module name][msg_type] message string + + 2. Message Type: + - [err] : Notes an exception or error condition (high priority) + - [warn] : Notes a error that is not severe (medium priority) + - [info] : General information message (normal priority) + - [evt] : Event related message (normal priority) + + Example: + >>> DEBUGP("[ed_main][err] File failed to open") + + @param statement: Should be a formatted string that starts with two + identifier blocks. The first is used to indicate the + source of the message and is used as the primary means + of filtering. The second block is the type of message, + this is used to indicate the priority of the message and + is used as the secondary means of filtering. + + """ + # Check if formatting should be done here + if len(args): + try: + statement = statement % args + except: + pass + + # Create a LogMsg object from the statement string + lbls = [lbl.strip() for lbl in RE_LOG_LBL.findall(statement)] + info = RE_LOG_LBL.sub('', statement, 2).rstrip() + if len(lbls) > 1: + msg = LogMsg(info, lbls[0], lbls[1]) + elif len(lbls) == 1: + msg = LogMsg(info, lbls[0]) + else: + msg = LogMsg(info) + + # Only print to stdout when DEBUG is active + # Cant print to stdio if using pythonw + msg_type = msg.Type + if ed_glob.DEBUG: + mstr = unicode(msg) + mstr = mstr.encode('utf-8', 'replace') + if not PYTHONW: + print(mstr) + + # Write to log file + logfile = EdLogFile() + logfile.WriteMessage(mstr) + + # Check for trapped exceptions to print + if ed_glob.VDEBUG and msg_type in ('err', 'error'): + traceback.print_exc() + logfile.WriteMessage(traceback.format_exc()) + + # Dispatch message to all observers + if msg_type in ('err', 'error'): + mtype = ed_msg.EDMSG_LOG_ERROR + if ed_glob.VDEBUG: + msg = LogMsg(msg.Value + os.linesep + traceback.format_exc(), + msg.Origin, msg.Type) + elif msg_type in ('warn', 'warning'): + mtype = ed_msg.EDMSG_LOG_WARN + elif msg_type in ('evt', 'event'): + mtype = ed_msg.EDMSG_LOG_EVENT + elif msg.Type in ('info', 'information'): + mtype = ed_msg.EDMSG_LOG_INFO + else: + mtype = ed_msg.EDMSG_LOG_ALL + + ed_msg.PostMessage(mtype, msg) + +#-----------------------------------------------------------------------------# + +class LogMsg(object): + """LogMsg is a container class for representing log messages. Converting + it to a string will yield a formatted log message with timestamp. Once a + message has been displayed once (converted to a string) it is marked as + being expired. + + """ + def __init__(self, msg, msrc=u"unknown", level=u"info"): + """Create a LogMsg object + @param msg: the log message string + @keyword msrc: Source of message + @keyword level: Priority of the message + + """ + assert isinstance(msg, basestring) + assert isinstance(msrc, basestring) + assert isinstance(level, basestring) + super(LogMsg, self).__init__() + + # Attributes + self._msg = dict(mstr=DecodeString(msg), + msrc=DecodeString(msrc), + lvl=DecodeString(level), + tstamp=time.time()) + self._ok = True + + def __eq__(self, other): + """Define the equal to operation""" + return self.TimeStamp == other.TimeStamp + + def __ge__(self, other): + """Define the greater than or equal to operation""" + return self.TimeStamp >= other.TimeStamp + + def __gt__(self, other): + """Define the greater than operation""" + return self.TimeStamp > other.TimeStamp + + def __le__(self, other): + """Define the less than or equal to operation""" + return self.TimeStamp <= other.TimeStamp + + def __lt__(self, other): + """Define the less than operation""" + return self.TimeStamp < other.TimeStamp + + def __repr__(self): + """String representation of the object""" + return '<LogMsg %s:%d>' % (self._msg['lvl'], self._msg['tstamp']) + + def __str__(self): + """Returns a nice formatted string version of the message""" + s_lst = [u"[%s][%s][%s]%s" % (self.ClockTime, self.Origin, + self.Type, msg.rstrip()) + for msg in self.Value.split(u"\n") + if len(msg.strip())] + try: + sys_enc = sys.getfilesystemencoding() + out = os.linesep.join([val.encode(sys_enc, 'replace') + for val in s_lst]) + except UnicodeEncodeError: + out = repr(self) + + # Mark Message as have being fetched (expired) + self._ok = False + + return out + + def __unicode__(self): + """Convert to unicode""" + rval = u"" + try: + sval = str(self) + rval = sval.decode(sys.getfilesystemencoding(), 'replace') + except UnicodeDecodeError, msg: + pass + return rval + + @property + def ClockTime(self): + """Formatted timestring of the messages timestamp""" + ltime = time.localtime(self._msg['tstamp']) + tstamp = u"%s:%s:%s" % (str(ltime[3]).zfill(2), + str(ltime[4]).zfill(2), + str(ltime[5]).zfill(2)) + return tstamp + + @property + def Expired(self): + """Has this message already been retrieved""" + return not self._ok + + @property + def Origin(self): + """Where the message came from""" + return self._msg['msrc'] + + @property + def TimeStamp(self): + """Property for accessing timestamp""" + return self._msg['tstamp'] + + @property + def Type(self): + """The messages level type""" + return self._msg['lvl'] + + @property + def Value(self): + """Returns the message part of the log string""" + return self._msg['mstr'] + +#-----------------------------------------------------------------------------# + +class EdLogFile(LogFile): + """Transient log file object""" + def __init__(self): + super(EdLogFile, self).__init__("editra") + + def PurgeOldLogs(self, days): + try: + super(EdLogFile, self).PurgeOldLogs(days) + except OSError, msg: + DEBUGP("[dev_tool][err] PurgeOldLogs: %s" % msg) + +#-----------------------------------------------------------------------------# + +def DecodeString(string, encoding=None): + """Decode the given string to Unicode using the provided + encoding or the DEFAULT_ENCODING if None is provided. + @param string: string to decode + @keyword encoding: encoding to decode string with + + """ + if encoding is None: + encoding = DEFAULT_ENCODING + + if not IsUnicode(string): + try: + rtxt = codecs.getdecoder(encoding)(string)[0] + except Exception, msg: + rtxt = string + return rtxt + else: + # The string is already Unicode so just return it + return string + +#-----------------------------------------------------------------------------# + +class EdErrorDialog(eclib.ErrorDialog): + """Error reporter dialog""" + def __init__(self, msg): + super(EdErrorDialog, self).__init__(None, title="Error Report", + message=msg) + + # Setup + self.SetDescriptionLabel(_("Error: Something unexpected hapend\n" + "Help improve Editra by clicking on " + "Report Error\nto send the Error " + "Traceback shown below.")) + + def Abort(self): + """Abort the application""" + # Try a nice shutdown first time through + wx.CallLater(500, wx.GetApp().OnExit, + wx.MenuEvent(wx.wxEVT_MENU_OPEN, ed_glob.ID_EXIT), + True) + + def GetProgramName(self): + """Get the program name to display in error report""" + return "%s Version: %s" % (ed_glob.PROG_NAME, ed_glob.VERSION) + + def Send(self): + """Send the error report""" + msg = "mailto:%s?subject=Error Report&body=%s" + addr = "bugs@%s" % (ed_glob.HOME_PAGE.replace("http://", '', 1)) + if wx.Platform != '__WXMAC__': + body = urllib2.quote(self.err_msg) + else: + body = self.err_msg + msg = msg % (addr, body) + msg = msg.replace("'", '') + webbrowser.open(msg) + +#-----------------------------------------------------------------------------# + +def ExceptionHook(exctype, value, trace): + """Handler for all unhandled exceptions + @param exctype: Exception Type + @param value: Error Value + @param trace: Trace back info + + """ + # Format the traceback + exc = traceback.format_exception(exctype, value, trace) + exc.insert(0, u"*** %s ***%s" % (eclib.TimeStamp(), os.linesep)) + ftrace = u"".join(exc) + + # Ensure that error gets raised to console as well + print ftrace + + # If abort has been set and we get here again do a more forcefull shutdown + if EdErrorDialog.ABORT: + os._exit(1) + + # Prevent multiple reporter dialogs from opening at once + if not EdErrorDialog.REPORTER_ACTIVE and not EdErrorDialog.ABORT: + dlg = EdErrorDialog(ftrace) + dlg.ShowModal() + dlg.Destroy() + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/doctools.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/doctools.py new file mode 100644 index 0000000..ae08f5a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/doctools.py @@ -0,0 +1,244 @@ +############################################################################### +# Name: doctools.py # +# Purpose: Tools for managing document services # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides helper functions and classes for managing documents and their services. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: doctools.py 70230 2012-01-01 01:47:42Z CJP $" +__revision__ = "$Revision: 70230 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import sys + +# Editra Libraries +import util +from profiler import Profile_Get +import ebmlib + +#--------------------------------------------------------------------------# + +class DocPositionMgr(object): + """Object for managing the saving and setting of a collection of + documents positions between sessions. Through the use of an in memory + dictionary during run time and on disk dictionary to use when starting + and stopping the editor. + @note: saves config to ~/.Editra/cache/ + + """ + _poscache = ebmlib.HistoryCache(100) + + def __init__(self): + """Creates the position manager object""" + super(DocPositionMgr, self).__init__() + + # Attributes + self._init = False + self._book = None + self._records = dict() + + def InitPositionCache(self, book_path): + """Initialize and load the on disk document position cache. + @param book_path: path to on disk cache + + """ + self._init = True + self._book = book_path + if Profile_Get('SAVE_POS'): + self.LoadBook(book_path) + + @classmethod + def AddNaviPosition(cls, fname, pos): + """Add a new position to the navigation cache + @param fname: file name + @param pos: position + + """ + # Don't put two identical positions in the cache next to each other + pre = cls._poscache.PeekPrevious() + next = cls._poscache.PeekNext() + if (fname, pos) in (pre, next): + return + + cls._poscache.PutItem((fname, pos)) + + def AddRecord(self, vals): + """Adds a record to the dictionary from a list of the + filename vals[0] and the position value vals[1]. + @param vals: (file path, cursor position) + + """ + if len(vals) == 2: + self._records[vals[0]] = vals[1] + return True + else: + return False + + @classmethod + def CanNavigateNext(cls): + """Are there more cached navigation positions? + @param cls: Class + @return: bool + + """ + return cls._poscache.HasNext() + + @classmethod + def CanNavigatePrev(cls): + """Are there previous cached navigation positions? + @param cls: Class + @return: bool + + """ + return cls._poscache.HasPrevious() + + @classmethod + def FlushNaviCache(cls): + """Clear the navigation cache""" + cls._poscache.Clear() + + @classmethod + def GetNaviCacheSize(cls): + return cls._poscache.GetSize() + + def GetBook(self): + """Returns the current book used by this object + @return: path to book used by this manager + + """ + return self._book + + @classmethod + def GetNextNaviPos(cls, fname=None): + """Get the next stored navigation position + The optional fname parameter will get the next found position for + the given file. + @param cls: Class + @param fname: filename (note currently not supported) + @return: int or None + @note: fname is currently not used + + """ + item = cls._poscache.GetNextItem() + return item + + @classmethod + def GetPreviousNaviPos(cls, fname=None): + """Get the last stored navigation position + The optional fname parameter will get the last found position for + the given file. + @param cls: Class + @param fname: filename (note currently not supported) + @return: int or None + @note: fname is currently not used + + """ + item = cls._poscache.GetPreviousItem() + return item + + def GetPos(self, name): + """Get the position record for a given filename + returns 0 if record is not found. + @param name: file name + @return: position value for the given filename + + """ + return self._records.get(name, 0) + + def IsInitialized(self): + """Has the cache been initialized + @return: bool + + """ + return self._init + + def LoadBook(self, book): + """Loads a set of records from an on disk dictionary + the entries are formated as key=value with one entry + per line in the file. + @param book: path to saved file + @return: whether book was loaded or not + + """ + # If file does not exist create it and return + if not os.path.exists(book): + try: + tfile = util.GetFileWriter(book) + tfile.close() + except (IOError, OSError): + util.Log("[docpositionmgr][err] failed to load book: %s" % book) + return False + except AttributeError: + util.Log("[docpositionmgr][err] Failed to create: %s" % book) + return False + + reader = util.GetFileReader(book, sys.getfilesystemencoding()) + if reader != -1: + lines = list() + try: + lines = reader.readlines() + except: + reader.close() + return False + else: + reader.close() + + for line in lines: + line = line.strip() + vals = line.rsplit(u'=', 1) + if len(vals) != 2 or not os.path.exists(vals[0]): + continue + + try: + vals[1] = int(vals[1]) + except (TypeError, ValueError), msg: + util.Log("[docpositionmgr][err] %s" % str(msg)) + continue + else: + self._records[vals[0]] = vals[1] + + util.Log("[docpositionmgr][info] successfully loaded book") + return True + + @classmethod + def PeekNavi(cls, pre=False): + """Peek into the navigation cache + @param cls: Class + @keyword pre: bool + + """ + if pre: + if cls._poscache.HasPrevious(): + return cls._poscache.PeekPrevious() + else: + if cls._poscache.HasNext(): + return cls._poscache.PeekNext() + return None, None + + def WriteBook(self): + """Writes the collection of files=pos to the config file + @postcondition: in memory doc data is written out to disk + + """ + writer = util.GetFileWriter(self.GetBook(), sys.getfilesystemencoding()) + if writer != -1: + try: + for key, val in self._records.iteritems(): + try: + writer.write(u"%s=%d\n" % (key, val)) + except UnicodeDecodeError: + continue + writer.close() + except IOError, msg: + util.Log("[docpositionmgr][err] %s" % str(msg)) + else: + util.Log("[docpositionmgr][err] Failed to open %s" % self.GetBook()) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/__init__.py new file mode 100644 index 0000000..4b64463 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/__init__.py @@ -0,0 +1,46 @@ +############################################################################### +# Name: __init__.py # +# Purpose: Editra Business Model Library # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: __init__.py 69798 2011-11-23 02:59:40Z CJP $" +__revision__ = "$Revision: 69798 $" + +#-----------------------------------------------------------------------------# + +# Text Utils +from searcheng import * +from fchecker import * +from fileutil import * +from _dirmon import * +from fileimpl import * +from txtutil import * +from logfile import * + +from backupmgr import * +from calllock import * + +# Storage Classes +from histcache import * +from clipboard import * + +# Networking utilities +from e_weblib import * + +# Misc +from miscutil import * +from _efactory import * +from cmenumgr import * +from efilehist import * +from osutil import * +from _threads import * +from _trash import * diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_dirmon.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_dirmon.py new file mode 100644 index 0000000..f5b3bb9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_dirmon.py @@ -0,0 +1,331 @@ +############################################################################### +# Name: _dirmon.py # +# Purpose: Directory monitor object. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: DirectoryMonitor + + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: _dirmon.py 73166 2012-12-12 04:31:53Z CJP $" +__revision__ = "$Revision: 73166 $" + +__all__ = ['DirectoryMonitor',] + +#-----------------------------------------------------------------------------# +# Imports +import wx +import os +import time +import threading + +# Local imports +import fileutil + +#-----------------------------------------------------------------------------# + +class DirectoryMonitor(object): + """Object to manage monitoring file system changes""" + def __init__(self, checkFreq=1000.0): + """@keyword checkFreq: check frequency in milliseconds""" + super(DirectoryMonitor, self).__init__() + + # Attributes + self._watcher = WatcherThread(self._ThreadNotifier, checkFreq=checkFreq) + self._callbacks = list() + self._cbackLock = threading.Lock() + self._running = False + + def __del__(self): + if self._running: + self._watcher.Shutdown() + self._watcher.join() + + def _ThreadNotifier(self, added, deleted, modified): + """Notifier callback from background L{WatcherThread} + to call notifiers on main thread. + @note: this method is invoked from a background thread and + is not safe to make direct UI calls from. + + """ + with self._cbackLock: + for cback in self._callbacks: + wx.CallAfter(cback, added, deleted, modified) + + #---- Properties ----# + + # Is the monitor currently watching any directories + Monitoring = property(lambda self: self._running) + Frequency = property(lambda self: self._watcher.GetFrequency(), + lambda self, freq: self._watcher.SetFrequency(freq)) + + #---- End Properties ----# + + def AddDirectory(self, dname): + """Add a directory to the monitor + @param dname: directory path + @return: bool - True if added, False if failed to add + + """ + return self._watcher.AddWatchDirectory(dname) + + def SubscribeCallback(self, callback): + """Subscribe a callback method to be called when changes are + detected in one of the watched directories. + @param callback: callable([added,], [deleted,], [modified,]) + + """ + with self._cbackLock: + if callback not in self._callbacks: + self._callbacks.append(callback) + + def UnsubscribeCallback(self, callback): + """Remove a callback method from the monitor""" + with self._cbackLock: + if callback in self._callbacks: + self._callbacks.remove(callback) + + def RemoveDirectory(self, dname): + """Remove a directory from the watch list + @param dname: directory path + + """ + self._watcher.RemoveWatchDirectory(dname) + + def StartMonitoring(self): + """Start monitoring the directories in the watch list and + notifying target of changes. + + """ + self._running = True + self._watcher.start() + + def Suspend(self, pause=True): + """Suspend background processing + @keyword pause: True (suspend) False (resume) + + """ + if pause: + self._watcher.Suspend() + else: + self._watcher.Continue() + + def Refresh(self, paths=None): + """Force a recheck of the monitored directories. This method + is useful for doing manual control of the refresh cycle. It is + ignored and does nothing when WatcherThread is set up for automatic + refresh cycles. + @keyword paths: specific paths to refresh or None for all. + + """ + self._watcher.Refresh(paths) + +#-----------------------------------------------------------------------------# + +class WatcherThread(threading.Thread): + """Background thread to monitor a directory""" + def __init__(self, notifier, checkFreq=1000.0): + """Create the WatcherThread. Provide a callback notifier method + that will be called when changes are detected in the directory. + The notifier will be called in the context of this thread. Notifier + will be called with three lists of ebmlib.File objects to indicate + the changes that have occurred. + @param notifier: callable([added,], [deleted,], [modified,]) + @keyword checkFreq: check frequency in milliseconds. If value is set + to zero or less update checks must be manually + controlled via the Refresh interface. + + """ + super(WatcherThread, self).__init__() + + # Attributes + assert callable(notifier) + self._notifier = notifier + self._dirs = list() # Directories being monitored + self._refreshDirs = None + + self._freq = checkFreq # Monitoring frequency in milliseconds + self._continue = True + self._changePending = False + self._lock = threading.Lock() + self._suspend = False + self._suspendcond = threading.Condition() + self._listEmptyCond = threading.Condition() + self._refreshCond = threading.Condition() + + def run(self): + """Run the watcher""" + while self._continue: + deleted = list() + added = list() + modified = list() + + # Watch is empty so wait on things to monitor before continuing + if not self._dirs: + with self._listEmptyCond: + self._listEmptyCond.wait() + + # Suspend processing if requested + if self._suspend: + with self._suspendcond: + self._suspendcond.wait() + + with self._lock: + for dobj in self._PendingRefresh: + if not self._continue: + return + elif self._changePending: + break + + # Check if a watched directory has been deleted + if not os.path.exists(dobj.Path): + deleted.append(dobj) + self._dirs.remove(dobj) + continue + + snapshot = fileutil.GetDirectoryObject(dobj.Path, + False, True) + + # Check for deletions + dobjFiles = dobj.Files # optimization + dobjIndex = dobjFiles.index # optimization + snapFiles = snapshot.Files # optimization + for tobj in dobjFiles: + if not self._continue: + return + elif self._changePending: + break + if tobj not in snapFiles: + deleted.append(tobj) + dobjFiles.remove(tobj) + + # Check for additions and modifications + for tobj in snapFiles: + if not self._continue: + return + elif self._changePending: + break + if tobj not in dobjFiles: + # new object was added + added.append(tobj) + dobjFiles.append(tobj) + else: + idx = dobjIndex(tobj) + existing = dobjFiles[idx] + # object was modified + if existing.ModTime < tobj.ModTime: + modified.append(tobj) + existing.ModTime = tobj.ModTime + + # Call Notifier if anything changed + if any((added, deleted, modified)): + self._notifier(added, deleted, modified) + + # Wait till next check + if self._freq > 0: + # Automatic updates + time.sleep(self._freq / 1000.0) + else: + # Manually controlled updates + with self._refreshCond: + self._refreshDirs = None + self._refreshCond.wait() + + #---- Implementation ----# + + @property + def _PendingRefresh(self): + """Get the list of directories pending refresh""" + if self._refreshDirs is None: + return self._dirs + else: + return self._refreshDirs + + def AddWatchDirectory(self, dpath): + """Add a directory to the watch list + @param dpath: directory path (unicode) + @return: bool - True means watch was added, False means unable to list directory + + """ + assert os.path.isdir(dpath) + dobj = fileutil.Directory(dpath) + self._changePending = True + with self._lock: + if dobj not in self._dirs and os.access(dobj.Path, os.R_OK): + # Get current snapshot of the directory + try: + dobj = fileutil.GetDirectoryObject(dpath, False, True) + except OSError: + self._changePending = False + return False + self._dirs.append(dobj) + with self._listEmptyCond: + self._listEmptyCond.notify() + self._changePending = False + return True + + def RemoveWatchDirectory(self, dpath): + """Remove a directory from the watch + @param dpath: directory path to remove (unicode) + + """ + dobj = fileutil.Directory(dpath) + self._changePending = True + with self._lock: + if dobj in self._dirs: + self._dirs.remove(dobj) + # Also remove any subpaths of dpath + toremove = list() + for d in self._dirs: + if fileutil.IsSubPath(d.Path, dpath): + toremove.append(d) + for todel in toremove: + self._dirs.remove(todel) + self._changePending = False + + def GetFrequency(self): + """Get the update frequency + @return: int (milliseconds) + + """ + return self._freq + + def SetFrequency(self, milli): + """Set the update frequency + @param milli: int (milliseconds) + + """ + self._freq = float(milli) + + def Refresh(self, paths=None): + """Recheck the monitored directories + only useful when manually controlling refresh cycle of the monitor. + @keyword paths: if None refresh all, else list of specific directories + + """ + with self._refreshCond: + if paths is not None: + self._refreshDirs = list() + for dobj in paths: + self._refreshDirs.append(dobj) + self._refreshCond.notify() + + def Shutdown(self): + """Shut the thread down""" + self._continue = False + + def Suspend(self): + """Suspend the thread""" + self._suspend = True + + def Continue(self): + """Continue the thread""" + self._suspend = False + with self._suspendcond: + self._suspendcond.notify() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_efactory.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_efactory.py new file mode 100644 index 0000000..ff5b880 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_efactory.py @@ -0,0 +1,124 @@ +############################################################################### +# Name: _efactory.py # +# Purpose: Generic Factory Pattern implementation. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: Factory + +Provides base functionality for implementing class factories. + +class FactoryMixin: + +class Meta: + - Don't use directly is used by classes that use the MetaData metaclass + +class MetaData: + - Meta data class - allows classes to be created with nested meta data + dynamically. + Example: + class FooBar(object): + __metaclass__ = MetaData + class MyFoo(FooBar): + class meta: + name = 'MyFoo' + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: _efactory.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +__all__ = [ 'FactoryMixin', 'MetaData' ] + +#-----------------------------------------------------------------------------# +# imports +import copy + +#-----------------------------------------------------------------------------# + +class Meta: + """Metadata namespace, acts as a container object for meta attributes + for classes using the FactoryMeta metaclass. + @see: FactoryMeta + + """ + def __init__(self, cls, meta_attrs): + assert hasattr(cls, 'GetMetaDefaults') + for (attr,default) in cls.GetMetaDefaults().items(): + attr_val = meta_attrs.get(attr, default) + setattr(self, attr, copy.copy(attr_val)) + +class MetaData(type): + """Metaclass for applying meta data to a class""" + def __new__(mcls,name,bases,attrs): + cls = super(MetaData,mcls).__new__(mcls,name,bases,attrs) + meta_attrs = { 'id' : None } + if hasattr(cls, 'meta'): + for attr in dir(cls.meta): + if not attr.startswith("_"): + meta_attrs[attr] = getattr(cls.meta,attr) + cls.meta = Meta(cls, meta_attrs) + return cls + +class FactoryMixin: + """Factory implementation. + All classes derived from classes using this mixin should declare a nested + subclass 'meta' that has at least one member 'id' that is used to identify + and instantiate the class in the factory. + + Example: + class Foo(MyFactoryClass): + class meta: + id = 'foo' + + Any arbitrary identifier may be specified. Additional meta data attributes + can be specified as well to suit the needs of the implementation. When + adding additional meta data to a class it is necessary that the base class + overrides the GetMetaDefaults method to return the appropriate default + values for each supported meta field. + + Example: + class meta: + id = 'foo' + size = 100 + + In order to properly support the size meta field the factory base class must + override GetMetaDefaults and return a dictionary object as follows. + + Example: + \@classmethod + def GetMetaDefaults(cls): + return dict(id=None, size=0) + + """ + __metaclass__ = MetaData + @classmethod + def FactoryCreate(cls, identifier, *args, **kwargs): + """Create an object of the appropriate type + @param identifier: id value (see meta) + @param args: Arguments to pass to object constructor + @param kwargs: Keyword arguments to pass to object constructor + @return: Subclass instance of cls or None if no appropriate constructor + is found in the factory. + + """ + obj = None + for scls in cls.__subclasses__(): + if scls.meta.id == identifier: + obj = scls(*args, **kwargs) + break + else: + obj = cls(*args, **kwargs) # Return base class + return obj + + @classmethod + def GetMetaDefaults(cls): + """Get all default meta values for this classes meta data. + @return: dict(string=value,...) + + """ + return dict() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_threads.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_threads.py new file mode 100644 index 0000000..41609a9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_threads.py @@ -0,0 +1,110 @@ +############################################################################### +# Name: _threads.py # +# Purpose: Threadpool implementation # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: ThreadPool + + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _threads.py 67422 2011-04-09 17:23:27Z CJP $" +__revision__ = "$Revision: 67422 $" + +__all__ = [ 'ThreadPool', ] + +#-----------------------------------------------------------------------------# +# Imports +import threading +import Queue + +#-----------------------------------------------------------------------------# + +class ThreadPool(object): + """Object for managing a collection of threads and dispatching jobs + to them. + + """ + def __init__(self, tcount, qsize=-1): + """Create the ThreadPool + @param tcount: max number of threads to keep in the pool + @keyword qsize: size of job queue (-1 for unlimited) + + """ + super(ThreadPool, self).__init__() + + # Attributes + self._poolsize = tcount + self._jobs = Queue.Queue(qsize) + self._threads = [ _WorkerThread(self._jobs) for t in range(self._poolsize) ] + + ThreadCount = property(lambda self: self._poolsize) + JobCount = property(lambda self: self._jobs.qsize()) + + def QueueJob(self, funct, *args, **kwargs): + """Add a job to be processed + @param funct: callable + @param args: list of any positional arguments to funct + @param kwargs: map of any keyword arguments to funct + + """ + assert callable(funct) + self._jobs.put((funct, args, kwargs)) + + def Shutdown(self): + """Shutdown the ThreadPool + @note: Blocking call until all threads have exited + + """ + self._jobs.join() + +#-----------------------------------------------------------------------------# + +class _WorkerThread(threading.Thread): + """Worker thread class to be used by the ThreadPool""" + def __init__(self, jobs): + """Create the Thread object + @param jobs: Queue object + + """ + super(_WorkerThread, self).__init__() + + # Attributes + self._jobs = jobs + self.daemon = True + self.start() + + def run(self): + """Run and process jobs until requested to exit""" + while True: + funct, args, kwargs = self._jobs.get() + try: + funct(*args, **kwargs) + except Exception, msg: + pass # TODO add error to result data? + finally: + self._jobs.task_done() + +#-----------------------------------------------------------------------------# +# Unittest +if __name__ == '__main__': + pool = ThreadPool(5) + import time + import random + def Job(id_, length): + print "JOB: %d, begin" % id_ + time.sleep(length) + print "JOB: %d, end" % id_ + + print "Start Jobs" + for x in range(8): + pool.QueueJob(Job, x, random.randint(1, 20)) + print "All Jobs Queued" + + pool.Shutdown() # blocks till pool is shutdown + print "All Done!" diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_trash.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_trash.py new file mode 100644 index 0000000..e8e68b3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_trash.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python2 +############################################################################### +# Name: _trash.py # +# Purpose: Multiplatform recycle/trash implementation # +# Author: Kevin D. Smith <Kevin.Smith@sixquickrun.com> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Platform independent Recycle Bin / Trash implementation + +The moveToTrash function in this module takes a path or list of +paths and moves them to the Recycle Bin / Trash directory depending +on the platform. For UNIX platforms, the FreeDesktop specification +of Trash <http://www.ramendik.ru/docs/trashspec.html> is implemented. + +Any errors while moving files results in some form of TrashException. + +""" + +__author__ = "Kevin D. Smith <Kevin.Smith@sixquickrun.com>" +__revision__ = "$Revision: 58361 $" +__scid__ = "$Id: Trash.py 58361 2009-01-24 19:43:27Z CJP $" + +__all__ = ['MoveToTrash'] + +#-----------------------------------------------------------------------------# +# Imports +import os +import time +import platform +import shutil +import stat + +OSX = WIN = False + +# Determine platform, if it's not one of these assume UNIX/Linux +if platform.system().lower() in ['windows', 'microsoft']: + WIN = True + # Install recycle.exe binary + import _winrecycle + env = os.environ + recycleexe = os.path.join(env.get('TEMP', env.get('TMP', env.get('windir','.'))),'recycle.exe') + exe = open(recycleexe,'wb') + exe.write(_winrecycle.recycle) + exe.close() + del exe + del _winrecycle +elif platform.mac_ver()[0]: + OSX = True + +#-----------------------------------------------------------------------------# + +class TrashError(Exception): + pass + +class TrashDirectoryError(TrashError): + pass + +class TrashMoveError(TrashError): + pass + +class TrashPermissionsError(TrashMoveError): + pass + +def MoveToTrash(paths): + """ + Move the given paths to the trash can + + Required Arguments: + paths -- path or list of paths to move to the trash can + + """ + # Make sure that we are always dealing with a list + if isinstance(paths, basestring): + paths = [paths] + + # Get absolute paths and make sure files exist + paths = [os.path.abspath(x) for x in paths + if os.path.exists(os.path.abspath(x))] + + # Run the correct trash function + if OSX: + return _osxTrash(paths) + elif WIN: + return _winTrash(paths) + else: + return _unixTrash(paths) + +def _ensurePermissions(path): + """ Make sure we have permissions to read and delete path """ + if not os.access(path, os.R_OK|os.W_OK): + try: os.chmod(path, stat.S_IWRITE|stat.S_IREAD) + except (IOError, OSError): pass + if not os.access(path, os.R_OK): + raise TrashPermissionsError, ('You do not have permissions to read this path', path) + if not os.access(path, os.W_OK): + raise TrashPermissionsError, ('You do not have permissions to remove this path', path) + +def _winTrash(paths): + """ Move to windows recycle bin if possible """ + for path in paths: + # See if we can even do this + _ensurePermissions(path) + try: + rc = os.spawnv(os.P_WAIT, recycleexe, + [os.path.basename(recycleexe)] + ['"%s"'%path]) + if rc: + raise TrashMoveError, ('Could not move path', path, '%s' % rc) + except (IOError, OSError), msg: + raise TrashMoveError, ('Could not move path', path, msg) + +def _osxTrash(paths): + """ Move paths to OS X Trash can """ + trashdir = os.path.join(os.path.expanduser('~'),'.Trash') + if not os.path.isdir(trashdir): + raise TrashDirectoryError, ('Could not locate trash directory', trashdir) + + for path in paths: + # See if we can even do this + _ensurePermissions(path) + + # Generate new filename in trash + origpath = newpath = os.path.join(trashdir, os.path.basename(path)) + while os.path.exists(newpath): + newpath = origpath + base, ext = os.path.splitext(newpath) + newpath = '%s %s%s' % (base, time.strftime('%H-%M-%S'), ext) + + # Move the path + try: + shutil.move(path, newpath) + except (OSError, IOError), msg: + raise TrashMoveError, ('Could not move path', path, msg) + +def _unixTrash(paths): + """ + Move paths to FreeDesktop Trash can + + See <http://www.ramendik.ru/docs/trashspec.html> + + """ + trashdir = os.path.join(os.environ.get('XDG_DATA_HOME', + os.path.join(os.path.expanduser('~'),'.local','share')), 'Trash') + + # Create trash directories as needed + try: + os.makedirs(os.path.join(trashdir, 'files')) + except (IOError, OSError): + pass + + try: + os.makedirs(os.path.join(trashdir, 'info')) + except (IOError, OSError): + pass + + # Make sure that directories got created + if not os.path.isdir(os.path.join(trashdir, 'files')): + raise TrashDirectoryError, ('Could not locate trash directory', trashdir) + if not os.path.isdir(os.path.join(trashdir, 'info')): + raise TrashDirectoryError, ('Could not locate trash directory', trashdir) + + for path in paths: + # See if we can even do this + _ensurePermissions(path) + + # Create unique filename + origpath = newpath = os.path.join(trashdir, 'files', + os.path.basename(path)) + while os.path.exists(newpath): + newpath = origpath + base, ext = os.path.splitext(newpath) + newpath = '%s %s%s' % (base, time.strftime('%H-%M-%S'), ext) + + # Write info file + try: + root, base = os.path.split(newpath) + infopath = os.path.join(os.path.dirname(root), + 'info', base + '.trashinfo') + info = open(infopath,'w') + info.write('[Trash Info]\n') + info.write('Path=%s\n' % path) + info.write(time.strftime('DeletionDate=%Y%m%dT%H:%M:%S\n')) + info.close() + except (OSError, IOError), msg: + try: + os.remove(infopath) + except: + pass + raise TrashMoveError, ('Could not move path', path, msg) + + # Move file + try: + shutil.move(path, newpath) + except (OSError, IOError), msg: + raise TrashMoveError, ('Could not move path', path, msg) + +#-----------------------------------------------------------------------------# + +if __name__ == '__main__': + import sys + args = sys.argv[1:] + if args: + moveToTrash(args) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_winrecycle.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_winrecycle.py new file mode 100644 index 0000000..0c25d42 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/_winrecycle.py @@ -0,0 +1,338 @@ +#!/usr/bin/env python2 +############################################################################### +# Name: _winrecycle.py # +# Purpose: Windows recycle bin implementation. # +# Author: Kevin D. Smith <Kevin.Smith@sixquickrun.com> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" This is a self generating file. Run it to refresh the recycle.exe data. """ + +__author__ = "Kevin D. Smith <Kevin.Smith@sixquickrun.com>" +__revision__ = "$Revision: 50825 $" +__scid__ = "$Id: Recycle.py 50825 2007-12-19 07:57:23Z CJP $" + +import base64, re + +recycle = base64.b64decode( +"TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZG" +"UuDQ0KJAAAAAAAAABQRQAATAEFAJHDw0YAGAAADAIAAOAABwMLAQI4AAwAAAAUAAAAAgAAgBIAAAA" +"QAAAAIAAAAABAAAAQAAAAAgAABAAAAAEAAAAEAAAAAAAAAABgAAAABAAAyEMBAAMAAAAAACAAABAA" +"AAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAAABQAAAUAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAA9AoAAAAQAAAADAAAAAQAAAAAAAA" +"AAAAAAAAAAGAAAGAuZGF0YQAAAEAAAAAAIAAAAAIAAAAQAAAAAAAAAAAAAAAAAABAAADALnJkYXRh" +"AADwAAAAADAAAAACAAAAEgAAAAAAAAAAAAAAAAAAQAAAQC5ic3MAAAAAwAAAAABAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAIAAAMAuaWRhdGEAABQDAAAAUAAAAAQAAAAUAAAAAAAAAAAAAAAAAABAAADAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWJ5YPsGIld+ItFCDHbiX" +"X8iwAx9osAPZEAAMB3Qz2NAADAclu+AQAAAMcEJAgAAAAx0olUJATodAkAAIP4AXR6hcB0DscEJAg" +"AAAD/0Lv/////idiLdfyLXfiJ7F3CBAA9lAAAwHTCd0o9kwAAwHS0idiLdfyLXfiJ7F3CBACQPQUA" +"AMB0Wz0dAADAdcXHBCQEAAAAMfaJdCQE6BAJAACD+AF0aoXAdKrHBCQEAAAA/9Drmj2WAADA69HHB" +"CQIAAAAuAEAAACJRCQE6OAIAACF9g+Edv///+gjBQAA6Wz////HBCQLAAAAMcCJRCQE6LwIAACD+A" +"F0MIXAD4RS////xwQkCwAAAP/Q6T/////HBCQEAAAAuQEAAACJTCQE6IwIAADpJf///8cEJAsAAAC" +"4AQAAAIlEJATocggAAOkL////jbYAAAAAjbwnAAAAAFWJ5VOD7CTHBCQAEEAA6A0JAACD7ATolQMA" +"AOiQBAAAx0X4AAAAAI1F+IlEJBChACBAAMcEJARAQACJRCQMjUX0iUQkCLgAQEAAiUQkBOg9CAAAo" +"RBAQACFwHRkoxAgQACLFfxQQACF0g+FoQAAAIP64HQfoRBAQACJRCQEofxQQACLQDCJBCTo8wcAAI" +"sV/FBAAIP6wHQooRBAQACJRCQEofxQQACLQFCJBCTozwcAAOsNkJCQkJCQkJCQkJCQkOirBwAAixU" +"QIEAAiRDorgIAAIPk8OiGAgAA6HEHAACLAIlEJAihAEBAAIlEJAShBEBAAIkEJOilAAAAicPoPgcA" +"AIkcJOgmCAAAjbYAAAAAiUQkBKH8UEAAi0AQiQQk6FwHAACLFfxQQADpQP///5BVieWD7AjHBCQBA" +"AAA/xX0UEAA6Lj+//+QjbQmAAAAAFWJ5YPsCMcEJAIAAAD/FfRQQADomP7//5CNtCYAAAAAVYsNDF" +"FAAInlXf/hjXQmAFWLDQBRQACJ5V3/4ZCQkJBVieVd6dcDAACQkJCQkJCQVYnlV1OB7FAIAACD5PC" +"4AAAAAIPAD4PAD8HoBMHgBImFxPf//4uFxPf//+jgBQAA6IsBAACNlfj3//+4AAgAAIlEJAjHRCQE" +"AAAAAIkUJOisBgAAjb3Y9////LkeAAAAsADzqoN9CAB1D8eF1Pf//wAAAADpqQAAAItFDIPABIsAi" +"QQk6JcGAAA9AAgAAHYPx4XU9///AAAAAOmDAAAAx4XY9///AAAAAMeF3Pf//wMAAACNhfj3//+Jhe" +"D3//9mx4Xo9///VAaLRQyDwASLAIlEJASNhfj3//+JBCToLgYAAI2d+Pf//4tFDIPABIsAiQQk6Cg" +"GAACNBAPHRCQEADBAAIkEJOgFBgAAjYXY9///iQQk6LcGAACD7ASJhdT3//+LhdT3//+NZfhbX13D" +"kFWJ5YPsCKEgIEAAgzgAdBf/EIsVICBAAI1CBItSBKMgIEAAhdJ16cnDjbQmAAAAAFWJ5VOD7ASh4" +"BpAAIP4/3QphcCJw3QTifaNvCcAAAAA/xSd4BpAAEt19scEJCAUQADoOv7//1lbXcMxwIM95BpAAA" +"DrCkCLHIXkGkAAhdt19Ou+jbYAAAAAjbwnAAAAAFWhIEBAAInlhcB0BF3DZpBduAEAAACjIEBAAOu" +"DkJCQVbnwMEAAieXrFI22AAAAAItRBIsBg8EIAYIAAEAAgfnwMEAAcupdw5CQkJCQkJCQVYnlU5yc" +"WInDNQAAIABQnZxYnTHYqQAAIAAPhMAAAAAxwA+ihcAPhLQAAAC4AQAAAA+i9sYBD4WnAAAAidAlA" +"IAAAGaFwHQHgw0wQEAAAvfCAACAAHQHgw0wQEAABPfCAAAAAXQHgw0wQEAACPfCAAAAAnQHgw0wQE" +"AAEIHiAAAABHQHgw0wQEAAIPbBAXQHgw0wQEAAQPbFIHQKgQ0wQEAAgAAAALgAAACAD6I9AAAAgHY" +"suAEAAIAPoqEwQEAAicGByQABAACB4gAAAEB0Hw0AAwAAozBAQACNtgAAAABbXcODDTBAQAAB6U3/" +"//9biQ0wQEAAXcOQkJCQkJCQkFWJ5dvjXcOQkJCQkJCQkJBVoYBAQACJ5V2LSAT/4Yn2VbpCAAAAi" +"eVTD7fAg+xkiVQkCI1VqDHbiVQkBIkEJP8V2FBAALofAAAAuQEAAACD7AyFwHUH60YByUp4DoB8Kq" +"hBdfQJywHJSnnygzs8dQeJ2Itd/MnDuTQwQAC66gAAAIlMJAyJVCQIxwQkYTBAALiAMEAAiUQkBOi" +"SAgAAuKwwQAC75AAAAIlEJAyJXCQI69eNtCYAAAAAjbwnAAAAAFWJ5VdWU4HszAAAAIsNgEBAAIXJ" +"dAiNZfRbXl9dw8dFmEFBQUGhEDBAAI11mMdFnEFBQUHHRaBBQUFBiUW4oRQwQADHRaRBQUFBx0WoQ" +"UFBQYlFvKEYMEAAx0WsQUFBQcdFsEFBQUGJRcChHDBAAMdFtEFBQUGJRcShIDBAAIlFyKEkMEAAiU" +"XMoSgwQACJRdChLDBAAIlF1A+3BTAwQABmiUXYiTQk/xXUUEAAD7fAg+wEhcCJhUT///8PhTsBAAD" +"HBCQ8AAAA6KMCAACFwInDD4RZAQAA/InHi4VE////uQ8AAADzq8dDBEAaQAC5AQAAAMdDCBAWQACh" +"UEBAAMcDPAAAAIsVVEBAAMdDKAAAAACJQxShMCBAAIlTGIsVNCBAAIlDHKFgQEAAiVMgx0Mw/////" +"4lDLIsVPCBAAKE4IEAAiVM4uh8AAACJQzSJ9onYIciD+AEZwCQgAckEQYiEKkj///9KeeehEDBAAI" +"mFaP///6EUMEAAiYVs////oRgwQACJhXD///+hHDBAAImFdP///6EgMEAAiYV4////oSQwQACJhXz" +"///+hKDBAAIlFgKEsMEAAiUWED7cFMDBAAGaJRYiNhUj///+JBCT/FcxQQAAPt/iD7ASF/3VCMdKF" +"0nUeiRwk6HMBAACJNCT/FdRQQACD7AQPt8DoX/3//4nDiR2AQEAAjUMEo3BAQACNQwijkEBAAI1l9" +"FteX13DifjoOP3//znYifp1seux6EsBAACQkJCQkJCQkJCQkFGJ4YPBCD0AEAAAchCB6QAQAACDCQ" +"AtABAAAOvpKcGDCQCJ4InMiwiLQAT/4JCQkFWJ5YPsGItFFIlEJBCLRRCJRCQMi0UMiUQkCItFCIl" +"EJASh/FBAAIPAQIkEJOj+AAAAofxQQACDwECJBCTo3gAAAOjJAAAAkJCQkJCQkJCQ/yX0UEAAkJAA" +"AAAAAAAAAP8l+FBAAJCQAAAAAAAAAAD/JexQQACQkAAAAAAAAAAA/yUkUUAAkJAAAAAAAAAAAP8l8" +"FBAAJCQAAAAAAAAAAD/JQRRQACQkAAAAAAAAAAA/yXoUEAAkJAAAAAAAAAAAP8lIFFAAJCQAAAAAA" +"AAAAD/JShRQACQkAAAAAAAAAAA/yUsUUAAkJAAAAAAAAAAAP8lGFFAAJCQAAAAAAAAAAD/JRxRQAC" +"QkAAAAAAAAAAA/yUIUUAAkJAAAAAAAAAAAP8lEFFAAJCQAAAAAAAAAAD/JRRRQACQkAAAAAAAAAAA" +"/yXcUEAAkJAAAAAAAAAAAP8l0FBAAJCQAAAAAAAAAAD/JdhQQACQkAAAAAAAAAAA/yXUUEAAkJAAA" +"AAAAAAAAP8lzFBAAJCQAAAAAAAAAAD/JThRQACQkAAAAAAAAAAAVYnlXekH+P//kJCQkJCQkP////" +"/QGkAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8" +"AAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAA8BpAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAP//" +"//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAC1MSUJHQ0NXMzItRUgtMi1TSkxKLUdUSFItTUlOR1czMgAAAHczMl9zaGFyZWRwdHItPnNpe" +"mUgPT0gc2l6ZW9mKFczMl9FSF9TSEFSRUQpACVzOiV1OiBmYWlsZWQgYXNzZXJ0aW9uIGAlcycKAA" +"AuLi8uLi9nY2MvZ2NjL2NvbmZpZy9pMzg2L3czMi1zaGFyZWQtcHRyLmMAAEdldEF0b21OYW1lQSA" +"oYXRvbSwgcywgc2l6ZW9mKHMpKSAhPSAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUUAAAAAAAAAAAAACgUgAAzFAAA" +"HBQAAAAAAAAAAAAAPhSAADoUAAAwFAAAAAAAAAAAAAACFMAADhRAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAABAUQAATFEAAFxRAABoUQAAeFEAAAAAAAAAAAAAmFEAAKhRAAC4UQAAyFEAANxRAADoUQA" +"A8FEAAPxRAAAIUgAAEFIAABxSAAAoUgAANFIAADxSAABIUgAAVFIAAGBSAABsUgAAAAAAAAAAAAB4" +"UgAAAAAAAAAAAABAUQAATFEAAFxRAABoUQAAeFEAAAAAAAAAAAAAmFEAAKhRAAC4UQAAyFEAANxRA" +"ADoUQAA8FEAAPxRAAAIUgAAEFIAABxSAAAoUgAANFIAADxSAABIUgAAVFIAAGBSAABsUgAAAAAAAA" +"AAAAB4UgAAAAAAAAEAQWRkQXRvbUEAAJwARXhpdFByb2Nlc3MAAACwAEZpbmRBdG9tQQDdAEdldEF" +"0b21OYW1lQQAA4wJTZXRVbmhhbmRsZWRFeGNlcHRpb25GaWx0ZXIAAAAnAF9fZ2V0bWFpbmFyZ3MA" +"PABfX3BfX2Vudmlyb24AAD4AX19wX19mbW9kZQAAAABQAF9fc2V0X2FwcF90eXBlAAAAAHkAX2Nle" +"Gl0AAAAAOkAX2lvYgAAXgFfb25leGl0AAAAhAFfc2V0bW9kZQAAFQJhYm9ydAAcAmF0ZXhpdAAAAA" +"AwAmZmbHVzaAAAAAA5AmZwcmludGYAAAA/AmZyZWUAAHICbWFsbG9jAAAAAHoCbWVtc2V0AAAAAJA" +"Cc2lnbmFsAAAAAJsCc3RyY3B5AAAAAJ8Cc3RybGVuAAAAAEoAU0hGaWxlT3BlcmF0aW9uQQAAAFAA" +"AABQAAAAUAAAAFAAAABQAABLRVJORUwzMi5kbGwAAAAAFFAAABRQAAAUUAAAFFAAABRQAAAUUAAAF" +"FAAABRQAAAUUAAAFFAAABRQAAAUUAAAFFAAABRQAAAUUAAAFFAAABRQAAAUUAAAbXN2Y3J0LmRsbA" +"AAKFAAAFNIRUxMMzIuRExMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAAPAAAA/v8AAGcBY3J0MS5jAAAAAAAAAAAAAAA" +"AAAAAAAQAAAAAAAAAAQAgAAMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAABQAQAAAQAgAAMAAAAA" +"ADIAAACAAgAAAQAgAAIAAAAAAEIAAACgAgAAAQAgAAIAX2F0ZXhpdADAAgAAAQAgAAIAX19vbmV4a" +"XTQAgAAAQAgAAIALnRleHQAAAAAAAAAAQAAAAMB3AIAACoAAAAAAAAAAAAAAAAALmRhdGEAAAAAAA" +"AAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAAAAAABAAAAAMBCAAAAAAAAAAAAAAAAAA" +"AAAAALmZpbGUAAAAZAAAA/v8AAGcBY3J0c3R1ZmYuYwAAAAAAAAAAAAAAAFUAAADgAgAAAQAgAAIB" +"AAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADgAgAAAQAAAAMBCQAAAAEAAAAAAAAAAAAAAAAALmRhd" +"GEAAAAAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAQAAAABAAAAAMBAAAAAAAAAA" +"AAAAAAAAAAAAAALmZpbGUAAAAkAAAA/v8AAGcBcmVjeWNsZS5jAAAAAAAAAAAAX21haW4AAADwAgA" +"AAQAgAAIALnRleHQAAADwAgAAAQAAAAMBLwEAAAkAAAAAAAAAAAAAAAAALmRhdGEAAAAAAAAAAgAA" +"AAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAQAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAAL" +"nJkYXRhAAAAAAAAAwAAAAMBAwAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAAsAAAA/v8AAGcBQ1JUZ2" +"xvYi5jAAAAAAAAAAAALnRleHQAAAAgBAAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAA" +"AAAAAAgAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAQAAAABAAAAAMBAAAAAAAAAAAAAAAA" +"AAAAAAAALmZpbGUAAAA0AAAA/v8AAGcBQ1JUZm1vZGUuYwAAAAAAAAAALnRleHQAAAAgBAAAAQAAA" +"AMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAAQAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALm" +"JzcwAAAAAQAAAABAAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAA8AAAA/v8AAGcBdHh0bW9" +"kZS5jAAAAAAAAAAAALnRleHQAAAAgBAAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAAQ" +"AAAAAgAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAAAgAAAABAAAAAMBAAAAAAAAAAAAAAAAA" +"AAAAAAALmZpbGUAAABKAAAA/v8AAGcBZ2NjbWFpbi5jAAAAAAAAAAAAAAAAAGUAAAAgAAAABAAAAA" +"MAcC4wAAAAAAAgAAAAAgAAAAMAAAAAAHIAAAAgBAAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"AAIUAAABQBAAAAQAgAAIAX19fbWFpbgCwBAAAAQAgAAIALnRleHQAAAAgBAAAAQAAAAMBrQAAAAsA" +"AAAAAAAAAAAAAAAALmRhdGEAAAAgAAAAAgAAAAMBBAAAAAEAAAAAAAAAAAAAAAAALmJzcwAAAAAgA" +"AAABAAAAAMBEAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAABUAAAA/v8AAGcBcHNldWRvLXJlbG9jLm" +"MAAAAAAAAAAJgAAADQBAAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADQBAAAAQAAAAM" +"BKAAAAAMAAAAAAAAAAAAAAAAALmRhdGEAAAAwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJz" +"cwAAAAAwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAABeAAAA/v8AAGcBY3B1X2ZlY" +"XR1cmVzLmMAAAAAAAAAALMAAAAABQAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAABQ" +"AAAQAAAAMB+AAAAAsAAAAAAAAAAAAAAAAALmRhdGEAAAAwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAA" +"AAAAALmJzcwAAAAAwAAAABAAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAABpAAAA/v8AAGcB" +"Q1JUX2ZwMTAuYwAAAAAAAAAAX2ZwcmVzZXQABgAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +"MgAAAAABgAAAQAgAAIALnRleHQAAAAABgAAAQAAAAMBBwAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAA" +"AwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABAAAAABAAAAAMBAAAAAAAAAAAAAAA" +"AAAAAAAAALmZpbGUAAAAWAQAA/v8AAGcBAAAAANIAAAAAAAAAAAAAAAAALnRleHQAAAAQBgAAAQAA" +"AAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAAAwAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAAL" +"mJzcwAAAABAAAAABAAAAAMBAgAAAAAAAAAAAAAAAAAAAAAAAAAAAOYAAAAQAAAAAwAAAAMAAAAAAP" +"cAAAAQBgAAAQAgAAMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsBAAAgBgAAAQAgAAMAAAAAADABAAB" +"QAAAABAAAAAMAAAAAAEMBAAAwAAAAAgAAAAMAAAAAAE4BAABgAAAABAAAAAMAAAAAAFsBAAA4AAAA" +"AgAAAAMAAAAAAGYBAADABgAAAQAgAAIALnRleHQAAAAQBgAAAQAAAAMB5QIAACwAAAAAAAAAAAAAA" +"AAALmRhdGEAAAAwAAAAAgAAAAMBEAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABQAAAABAAAAAMBIA" +"AAAAAAAAAAAAAAAAAAAAAALnJkYXRhAAAQAAAAAwAAAAMBwwAAAAAAAAAAAAAAAAAAAAAAcHJvYmU" +"AAAAGCQAAAQAAAAYAZG9uZQAAAAAdCQAAAQAAAAYALnRleHQAAAAACQAAAQAAAAMBLQAAAAAAAAAA" +"AAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAAB" +"AAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAwCQAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAA" +"AALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAA" +"AAAAAAAAAAAAAAAAAAAAAAAAAAIIBAAAwCQAAAQAgAAIBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQA" +"AAAwCQAAAQAAAAMBRwAAAAUAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAA" +"AAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAACACQAAAQ" +"AAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfEAgAABQAAAAM" +"ALmlkYXRhJDX8AAAABQAAAAMALmlkYXRhJDSEAAAABQAAAAMALmlkYXRhJDboAQAABQAAAAMALnRl" +"eHQAAACACQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJ" +"De8AgAABQAAAAMALmlkYXRhJDX0AAAABQAAAAMALmlkYXRhJDR8AAAABQAAAAMALmlkYXRhJDbIAQ" +"AABQAAAAMALnRleHQAAACQCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAA" +"AAAMALmlkYXRhJDfUAgAABQAAAAMALmlkYXRhJDUMAQAABQAAAAMALmlkYXRhJDSUAAAABQAAAAMA" +"LmlkYXRhJDYQAgAABQAAAAMALnRleHQAAACQCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzc" +"wAAAABwAAAABAAAAAMALmlkYXRhJDfIAgAABQAAAAMALmlkYXRhJDUAAQAABQAAAAMALmlkYXRhJD" +"SIAAAABQAAAAMALmlkYXRhJDbwAQAABQAAAAMALnRleHQAAACQCQAAAQAAAAMALmRhdGEAAABAAAA" +"AAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfAAgAABQAAAAMALmlkYXRhJDX4AAAABQAA" +"AAMALmlkYXRhJDSAAAAABQAAAAMALmlkYXRhJDbcAQAABQAAAAMALnRleHQAAACgCQAAAQAAAAMAL" +"mRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDe0AgAABQAAAAMALmlkYX" +"RhJDXsAAAABQAAAAMALmlkYXRhJDR0AAAABQAAAAMALmlkYXRhJDaoAQAABQAAAAMALnRleHQAAAC" +"wCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfsAgAA" +"BQAAAAMALmlkYXRhJDUkAQAABQAAAAMALmlkYXRhJDSsAAAABQAAAAMALmlkYXRhJDZUAgAABQAAA" +"AMALnRleHQAAADACQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALm" +"lkYXRhJDe4AgAABQAAAAMALmlkYXRhJDXwAAAABQAAAAMALmlkYXRhJDR4AAAABQAAAAMALmlkYXR" +"hJDa4AQAABQAAAAMALnRleHQAAADQCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABw" +"AAAABAAAAAMALmlkYXRhJDfMAgAABQAAAAMALmlkYXRhJDUEAQAABQAAAAMALmlkYXRhJDSMAAAAB" +"QAAAAMALmlkYXRhJDb8AQAABQAAAAMALnRleHQAAADgCQAAAQAAAAMALmRhdGEAAABAAAAAAgAAAA" +"MALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDewAgAABQAAAAMALmlkYXRhJDXoAAAABQAAAAMALml" +"kYXRhJDRwAAAABQAAAAMALmlkYXRhJDaYAQAABQAAAAMALnRleHQAAADwCQAAAQAAAAMALmRhdGEA" +"AABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfoAgAABQAAAAMALmlkYXRhJDUgA" +"QAABQAAAAMALmlkYXRhJDSoAAAABQAAAAMALmlkYXRhJDZIAgAABQAAAAMALnRleHQAAAAACgAAAQ" +"AAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfwAgAABQAAAAM" +"ALmlkYXRhJDUoAQAABQAAAAMALmlkYXRhJDSwAAAABQAAAAMALmlkYXRhJDZgAgAABQAAAAMALnRl" +"eHQAAAAQCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJ" +"Df0AgAABQAAAAMALmlkYXRhJDUsAQAABQAAAAMALmlkYXRhJDS0AAAABQAAAAMALmlkYXRhJDZsAg" +"AABQAAAAMALnRleHQAAAAgCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAA" +"AAAMALmlkYXRhJDfgAgAABQAAAAMALmlkYXRhJDUYAQAABQAAAAMALmlkYXRhJDSgAAAABQAAAAMA" +"LmlkYXRhJDY0AgAABQAAAAMALnRleHQAAAAwCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzc" +"wAAAABwAAAABAAAAAMALmlkYXRhJDfkAgAABQAAAAMALmlkYXRhJDUcAQAABQAAAAMALmlkYXRhJD" +"SkAAAABQAAAAMALmlkYXRhJDY8AgAABQAAAAMALnRleHQAAABACgAAAQAAAAMALmRhdGEAAABAAAA" +"AAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfQAgAABQAAAAMALmlkYXRhJDUIAQAABQAA" +"AAMALmlkYXRhJDSQAAAABQAAAAMALmlkYXRhJDYIAgAABQAAAAMALnRleHQAAABQCgAAAQAAAAMAL" +"mRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfYAgAABQAAAAMALmlkYX" +"RhJDUQAQAABQAAAAMALmlkYXRhJDSYAAAABQAAAAMALmlkYXRhJDYcAgAABQAAAAMALnRleHQAAAB" +"gCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDfcAgAA" +"BQAAAAMALmlkYXRhJDUUAQAABQAAAAMALmlkYXRhJDScAAAABQAAAAMALmlkYXRhJDYoAgAABQAAA" +"AMALmZpbGUAAAAmAQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAAaG5hbWUAAABwAAAABQAAAAMAZn" +"RodW5rAADoAAAABQAAAAMALnRleHQAAABwCgAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGE" +"AAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAA" +"AAAAAAAAAAAALmlkYXRhJDIUAAAABQAAAAMBFAAAAAMAAAAAAAAAAAAAAAAALmlkYXRhJDXkAAAAB" +"QAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDRsAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAA" +"AALmZpbGUAAABXAQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAALnRleHQAAABwCgAAAQAAAAMBAAA" +"AAAAAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAA" +"AABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDS4AAAABQAAAAMBBAAAAAAAAAAAA" +"AAAAAAAAAAALmlkYXRhJDUwAQAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDf4AgAABQ" +"AAAAMBCwAAAAAAAAAAAAAAAAAAAAAALnRleHQAAABwCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAM" +"ALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDecAgAABQAAAAMALmlkYXRhJDXcAAAABQAAAAMALmlk" +"YXRhJDRkAAAABQAAAAMALmlkYXRhJDZ4AQAABQAAAAMALnRleHQAAACACgAAAQAAAAMALmRhdGEAA" +"ABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDeQAgAABQAAAAMALmlkYXRhJDXQAA" +"AABQAAAAMALmlkYXRhJDRYAAAABQAAAAMALmlkYXRhJDZMAQAABQAAAAMALnRleHQAAACQCgAAAQA" +"AAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDeYAgAABQAAAAMA" +"LmlkYXRhJDXYAAAABQAAAAMALmlkYXRhJDRgAAAABQAAAAMALmlkYXRhJDZoAQAABQAAAAMALnRle" +"HQAAACgCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJD" +"eUAgAABQAAAAMALmlkYXRhJDXUAAAABQAAAAMALmlkYXRhJDRcAAAABQAAAAMALmlkYXRhJDZcAQA" +"ABQAAAAMALnRleHQAAACwCgAAAQAAAAMALmRhdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAA" +"AAMALmlkYXRhJDeMAgAABQAAAAMALmlkYXRhJDXMAAAABQAAAAMALmlkYXRhJDRUAAAABQAAAAMAL" +"mlkYXRhJDZAAQAABQAAAAMALmZpbGUAAABnAQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAAaG5hbW" +"UAAABUAAAABQAAAAMAZnRodW5rAADMAAAABQAAAAMALnRleHQAAADACgAAAQAAAAMBAAAAAAAAAAA" +"AAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAA" +"BAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDIAAAAABQAAAAMBFAAAAAMAAAAAAAAAAAAAA" +"AAALmlkYXRhJDXIAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDRQAAAABQAAAAMBBA" +"AAAAAAAAAAAAAAAAAAAAAALmZpbGUAAAB8AQAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAALnRleHQ" +"AAADACgAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAA" +"AAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDRoAAAAB" +"QAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDXgAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAA" +"AALmlkYXRhJDegAgAABQAAAAMBDQAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADACgAAAQAAAAMALmR" +"hdGEAAABAAAAAAgAAAAMALmJzcwAAAABwAAAABAAAAAMALmlkYXRhJDcEAwAABQAAAAMALmlkYXRh" +"JDU4AQAABQAAAAMALmlkYXRhJDTAAAAABQAAAAMALmlkYXRhJDZ4AgAABQAAAAMALmZpbGUAAACMA" +"QAA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAAaG5hbWUAAADAAAAABQAAAAMAZnRodW5rAAA4AQAABQ" +"AAAAMALnRleHQAAADQCgAAAQAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmRhdGEAAABAAAAAAgAAAAM" +"BAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmlk" +"YXRhJDIoAAAABQAAAAMBFAAAAAMAAAAAAAAAAAAAAAAALmlkYXRhJDU0AQAABQAAAAMBBAAAAAAAA" +"AAAAAAAAAAAAAAALmlkYXRhJDS8AAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmZpbGUAAACaAQ" +"AA/v8AAGcBZmFrZQAAAAAAAAAAAAAAAAAALnRleHQAAADQCgAAAQAAAAMBAAAAAAAAAAAAAAAAAAA" +"AAAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMB" +"AAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDTEAAAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkY" +"XRhJDU8AQAABQAAAAMBBAAAAAAAAAAAAAAAAAAAAAAALmlkYXRhJDcIAwAABQAAAAMBDAAAAAAAAA" +"AAAAAAAAAAAAAALmZpbGUAAACmAQAA/v8AAGcBY3J0c3R1ZmYuYwAAAAAAAAAAAAAAAI0BAADQCgA" +"AAQAgAAMBAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADQCgAAAQAAAAMBCQAAAAEAAAAAAAAAAAAA" +"AAAALmRhdGEAAABAAAAAAgAAAAMBAAAAAAAAAAAAAAAAAAAAAAAALmJzcwAAAABwAAAABAAAAAMBA" +"AAAAAAAAAAAAAAAAAAAAAAALmN0b3JzAADkCgAAAQAAAAMBBAAAAAEAAAAAAAAAAAAAAAAAX19jZX" +"hpdACQCQAAAQAgAAIAAAAAAJ8BAADwAAAAAwAAAAIAAAAAAL4BAAAEAQAABQAAAAIAAAAAAM4BAAA" +"AAAAAAgAAAAIAAAAAAN0BAADsCgAAAQAAAAIAX2ZyZWUAAAAgCgAAAQAgAAIAAAAAAOwBAAAAAQAA" +"BQAAAAIAAAAAAPsBAADACQAAAQAgAAIAAAAAAAcCAABwCgAAAQAAAAIAAAAAACYCAABwAAAABAAAA" +"AIAAAAAAEECAAAAYEAA//8AAAIAAAAAAFACAAD4AgAABQAAAAIAAAAAAGQCAADUAAAABQAAAAIAAA" +"AAAHcCAAAIAQAABQAAAAIAAAAAAIQCAAAAEAAA//8AAAIAAAAAAJ0CAAAAACAA//8AAAIAAAAAALc" +"CAAAEAAAA//8AAAIAAAAAANMCAAAAYEAA//8AAAIAAAAAAOUCAACwCgAAAQAAAAIAAAAAAPECAAAA" +"YEAA//8AAAIAAAAAAAMDAAAACQAAAQAAAAIAAAAAAA0DAAAAYEAA//8AAAIAAAAAAB0DAADsAAAAB" +"QAAAAIAAAAAADEDAAD8AAAABQAAAAIAAAAAAD0DAAAAAAAABAAAAAIAAAAAAEsDAADwAAAAAwAAAA" +"IAAAAAAG4DAAAAEAAA//8AAAIAAAAAAIYDAAA4AQAABQAAAAIAAAAAAKADAACgCQAAAQAgAAIAAAA" +"AAK4DAAAAYEAA//8AAAIAAAAAAMADAAAAYEAA//8AAAIAAAAAANADAAAkAQAABQAAAAIAX19kbGxf" +"XwAAAAAA//8AAAIAAAAAAN4DAAAAAAAA//8AAAIAAAAAAPMDAAAMAQAABQAAAAIAAAAAAAEEAAAUA" +"AAABQAAAAIAAAAAABQEAAAAAEAA//8AAAIAAAAAACMEAAAoAAAABQAAAAIAAAAAADcEAAAAEAAA//" +"8AAAIAAAAAAE0EAADwAAAAAwAAAAIAX21lbXNldADwCQAAAQAgAAIAAAAAAGsEAADwAAAABQAAAAI" +"AX19hcmdjAAAEAAAABAAAAAIAAAAAAH0EAACACgAAAQAAAAIAAAAAAIwEAABAAAAAAgAAAAIAAAAA" +"AJkEAADgCQAAAQAgAAIAAAAAAKgEAACAAAAABAAAAAIAAAAAALkEAADgCgAAAQAAAAIAAAAAAMcEA" +"ACACQAAAQAAAAIAX2ZmbHVzaABQCgAAAQAgAAIAAAAAANcEAADAAAAABAAAAAIAAAAAAOMEAAAQAA" +"AABAAAAAIAAAAAAO8EAAAAYEAA//8AAAIAX2ZwcmludGZgCgAAAQAgAAIAX19hbGxvY2EACQAAAQA" +"AAAIAAAAAAP8EAAAAYEAA//8AAAIAX19hcmd2AAAAAAAABAAAAAIAAAAAABEFAADgCgAAAQAAAAIA" +"AAAAACAFAADYAAAABQAAAAIAX19mbW9kZQAQAAAAAgAAAAIAAAAAADcFAAAAAgAA//8AAAIAAAAAA" +"EoFAAAcAQAABQAAAAIAAAAAAFgFAAAEAAAA//8AAAIAX19lbmRfXwAAYEAA//8AAAIAX3NpZ25hbA" +"CwCQAAAQAgAAIAX21hbGxvYwAwCgAAAQAgAAIAAAAAAG0FAADsCgAAAQAAAAIAAAAAAHsFAAAUAQA" +"ABQAAAAIAX3N0cmNweQAACgAAAQAgAAIAAAAAAIoFAAAgAQAABQAAAAIAAAAAAJgFAAAAABAA//8A" +"AAIAAAAAALEFAAAAYEAA//8AAAIAAAAAAMMFAAADAAAA//8AAAIAAAAAANEFAAAsAQAABQAAAAIAA" +"AAAAN8FAAAQAQAABQAAAAIAAAAAAO0FAAAoAQAABQAAAAIAX2Fib3J0AABACgAAAQAgAAIAAAAAAP" +"sFAACQAAAABAAAAAIAAAAAABcGAADoAAAABQAAAAIAAAAAACwGAAAAYEAA//8AAAIAAAAAADkGAAD" +"QAAAABQAAAAIAAAAAAE4GAAAwAAAABAAAAAIAAAAAAF4GAAAYAQAABQAAAAIAAAAAAGoGAADcAAAA" +"BQAAAAIAAAAAAI8GAAABAAAA//8AAAIAAAAAAKcGAAAAAAAA//8AAAIAAAAAALgGAAAAAAAAAgAAA" +"AIAAAAAAMMGAADQCQAAAQAgAAIAAAAAAM0GAADMAAAABQAAAAIAAAAAAN8GAAAAAAAABQAAAAIAAA" +"AAAPQGAAD4AAAABQAAAAIAAAAAAAIHAAAAAAAA//8AAAIAAAAAAB4HAAAAAAAA//8AAAIAX3N0cmx" +"lbgAQCgAAAQAgAAIAAAAAADYHAAD0AAAABQAAAAIAAAAAAEwHAADACgAAAQAAAAIAAAAAAGAHAACg" +"CgAAAQAAAAIAAAAAAG0HAAAIAwAABQAAAAIAAAAAAIIHAACQCgAAAQAAAAIAAAAAAJMHAADwAAAAA" +"wAAAAIAAAAAALUHAACgAgAABQAAAAIAAAAAAMsHAAAAYEAA//8AAAIA2wcAAF9fZ251X2V4Y2VwdG" +"lvbl9oYW5kbGVyQDQAX19fbWluZ3dfQ1JUU3RhcnR1cABfbWFpbkNSVFN0YXJ0dXAAX1dpbk1haW5" +"DUlRTdGFydHVwAF9fX2RvX3NqbGpfaW5pdABfaW5pdGlhbGl6ZWQAX19fZG9fZ2xvYmFsX2R0b3Jz" +"AF9fX2RvX2dsb2JhbF9jdG9ycwBfX3BlaTM4Nl9ydW50aW1lX3JlbG9jYXRvcgBfX19jcHVfZmVhd" +"HVyZXNfaW5pdABfX2ZwcmVzZXQAcHNldWRvLXJlbG9jLWxpc3QuYwBfdzMyX2F0b21fc3VmZml4AF" +"9fX3czMl9zaGFyZWRwdHJfZGVmYXVsdF91bmV4cGVjdGVkAF9fX3czMl9zaGFyZWRwdHJfZ2V0AGR" +"3Ml9vYmplY3RfbXV0ZXguMABkdzJfb25jZS4xAHNqbF9mY19rZXkuMgBzamxfb25jZS4zAF9fX3cz" +"Ml9zaGFyZWRwdHJfaW5pdGlhbGl6ZQBfX19lcHJpbnRmAF9fX3NqbGpfaW5pdF9jdG9yAF9fX1JVT" +"lRJTUVfUFNFVURPX1JFTE9DX0xJU1RfXwBfX2ltcF9fX3NldG1vZGUAX19kYXRhX3N0YXJ0X18AX1" +"9fRFRPUl9MSVNUX18AX19pbXBfX19vbmV4aXQAX19fcF9fZm1vZGUAX1NldFVuaGFuZGxlZEV4Y2V" +"wdGlvbkZpbHRlckA0AF9fX3czMl9zaGFyZWRwdHJfdGVybWluYXRlAF9fX3Rsc19zdGFydF9fAF9f" +"bGlibXN2Y3J0X2FfaW5hbWUAX19pbXBfX0ZpbmRBdG9tQUA0AF9faW1wX19hYm9ydABfX3NpemVfb" +"2Zfc3RhY2tfY29tbWl0X18AX19zaXplX29mX3N0YWNrX3Jlc2VydmVfXwBfX21ham9yX3N1YnN5c3" +"RlbV92ZXJzaW9uX18AX19fY3J0X3hsX3N0YXJ0X18AX0FkZEF0b21BQDQAX19fY3J0X3hpX3N0YXJ" +"0X18AX19fY2hrc3RrAF9fX2NydF94aV9lbmRfXwBfX2ltcF9fX19wX19lbnZpcm9uAF9faW1wX19f" +"aW9iAF9fYnNzX3N0YXJ0X18AX19fUlVOVElNRV9QU0VVRE9fUkVMT0NfTElTVF9FTkRfXwBfX3Npe" +"mVfb2ZfaGVhcF9jb21taXRfXwBfX2ltcF9fU0hGaWxlT3BlcmF0aW9uQUA0AF9fX3BfX2Vudmlyb2" +"4AX19fY3J0X3hwX3N0YXJ0X18AX19fY3J0X3hwX2VuZF9fAF9faW1wX19zaWduYWwAX19taW5vcl9" +"vc192ZXJzaW9uX18AX19pbXBfX2F0ZXhpdABfX2hlYWRfbGlibXN2Y3J0X2EAX19pbWFnZV9iYXNl" +"X18AX19oZWFkX2xpYnNoZWxsMzJfYQBfX3NlY3Rpb25fYWxpZ25tZW50X18AX19SVU5USU1FX1BTR" +"VVET19SRUxPQ19MSVNUX18AX19pbXBfX19fcF9fZm1vZGUAX0V4aXRQcm9jZXNzQDQAX19kYXRhX2" +"VuZF9fAF9fX2dldG1haW5hcmdzAF9fX3czMl9zaGFyZWRwdHIAX19DVE9SX0xJU1RfXwBfX19zZXR" +"fYXBwX3R5cGUAX19ic3NfZW5kX18AX19DUlRfZm1vZGUAX19fY3J0X3hjX2VuZF9fAF9fX2NydF94" +"Y19zdGFydF9fAF9fX0NUT1JfTElTVF9fAF9faW1wX19HZXRBdG9tTmFtZUFAMTIAX19maWxlX2Fsa" +"WdubWVudF9fAF9faW1wX19tYWxsb2MAX19tYWpvcl9vc192ZXJzaW9uX18AX19EVE9SX0xJU1RfXw" +"BfX2ltcF9fZnByaW50ZgBfX2ltcF9fbWVtc2V0AF9fc2l6ZV9vZl9oZWFwX3Jlc2VydmVfXwBfX19" +"jcnRfeHRfc3RhcnRfXwBfX3N1YnN5c3RlbV9fAF9faW1wX19zdHJsZW4AX19pbXBfX2ZmbHVzaABf" +"X2ltcF9fc3RyY3B5AF9fX3czMl9zaGFyZWRwdHJfdW5leHBlY3RlZABfX2ltcF9fX19nZXRtYWluY" +"XJncwBfX190bHNfZW5kX18AX19pbXBfX0V4aXRQcm9jZXNzQDQAX19fY3B1X2ZlYXR1cmVzAF9faW" +"1wX19mcmVlAF9faW1wX19TZXRVbmhhbmRsZWRFeGNlcHRpb25GaWx0ZXJANABfX21ham9yX2ltYWd" +"lX3ZlcnNpb25fXwBfX2xvYWRlcl9mbGFnc19fAF9fQ1JUX2dsb2IAX19zZXRtb2RlAF9faW1wX19B" +"ZGRBdG9tQUA0AF9faGVhZF9saWJrZXJuZWwzMl9hAF9faW1wX19fY2V4aXQAX19taW5vcl9zdWJze" +"XN0ZW1fdmVyc2lvbl9fAF9fbWlub3JfaW1hZ2VfdmVyc2lvbl9fAF9faW1wX19fX3NldF9hcHBfdH" +"lwZQBfU0hGaWxlT3BlcmF0aW9uQUA0AF9GaW5kQXRvbUFANABfX2xpYnNoZWxsMzJfYV9pbmFtZQB" +"fR2V0QXRvbU5hbWVBQDEyAF9fUlVOVElNRV9QU0VVRE9fUkVMT0NfTElTVF9FTkRfXwBfX2xpYmtl" +"cm5lbDMyX2FfaW5hbWUAX19fY3J0X3h0X2VuZF9fAA==") + +# Embed the recycle program for windows into this module +if __name__ == '__main__': + s = base64.b64encode(open('recycle.exe').read()) + lines = list() + for piece in xrange(0, (len(s)/77)): + lines.append(s[(piece*77):(piece*77)+77]) + lines.append(s[(len(s)/77)*77:]) + line = [ "\"%s\"" % x for x in lines ] + prog = "\n".join(line) + module = open('_winrecycle.py').read() + module = re.compile(r'^recycle = .+$\)', re.M).sub(r"recycle = base64.b64decode(\n%s)" % prog, module) + open('_winrecycle.py','w').write(module) + print "Embedding was ok?", ''.join(lines) == s + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/backupmgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/backupmgr.py new file mode 100644 index 0000000..069bb6d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/backupmgr.py @@ -0,0 +1,179 @@ +############################################################################### +# Name: backupmgr.py # +# Purpose: File Backup Manager # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: FileBackupMgr + +Helper class for managing and creating backups of files. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: backupmgr.py 67646 2011-04-29 03:07:20Z CJP $" +__revision__ = "$Revision: 67646 $" + +__all__ = [ 'FileBackupMgr', ] + +#-----------------------------------------------------------------------------# +# Imports +import os +import shutil + +# Local Imports +import fileutil +import fchecker + +#-----------------------------------------------------------------------------# + +class FileBackupMgr(object): + """File backup creator and manager""" + def __init__(self, header=None, template=u"%s~"): + """Create a BackupManager + @keyword header: header to id backups with (Text files only!!) + @keyword template: template string for naming backup file with + + """ + super(FileBackupMgr, self).__init__() + + # Attributes + self.checker = fchecker.FileTypeChecker() + self.header = header # Backup id header + self.template = template # Filename template + self.bkupdir = u"" + + def _CheckHeader(self, fname): + """Check if the backup file has a header that matches the + header used to identify backup files. + @param fname: name of file to check + @return: bool (True if header is ok, False otherwise) + + """ + isok = False + handle = None + try: + handle = open(fname, 'r') + line = handle.readline() + handle.close() + isok = line.startswith(self.header) + except Exception, msg: + isok = False + if handle: + handle.close() + return isok + + def GetBackupFilename(self, fname): + """Get the unique name for the files backup copy + @param fname: string (file path) + @return: string + + """ + if self.bkupdir: + tmp = fileutil.GetFileName(fname) + fname = os.path.join(self.bkupdir, tmp) + + rname = self.template % fname + if self.header is not None and \ + not self.checker.IsBinary(fname) and \ + os.path.exists(rname): + # Make sure that the template backup name does not match + # an existing file that is not a backup file. + while os.path.exists(rname): + if not self._CheckHeader(rname): + rname = self.template % rname + else: + break + + return rname + + def GetBackupWriter(self, fileobj): + """Create a backup filewriter method to backup a files contents + with. + @param fileobj: object implementing fileimpl.FileObjectImpl interface + @return: callable(text) to create backup with + + """ + nfile = fileobj.Clone() + fname = self.GetBackupFilename(nfile.GetPath()) + nfile.SetPath(fname) + # Write the header if it is enabled + if self.header and not self.checker.IsBinary(fname): + nfile.Write(self.header + os.linesep) + return nfile.Write + + def HasBackup(self, fname): + """Check if a given file has a backup file available or not + @param fname: string (file path) + + """ + backup = self.GetBackupFilename(fname) + return os.path.exists(backup) + + def IsBackupNewer(self, fname): + """Is the backup of this file newer than the saved version + of the file? + @param fname: string (file path) + @return: bool + + """ + backup = self.GetBackupFilename(fname) + if os.path.exists(fname) and os.path.exists(backup): + mod1 = fileutil.GetFileModTime(backup) + mod2 = fileutil.GetFileModTime(fname) + return mod1 > mod2 + else: + return False + + def MakeBackupCopy(self, fname): + """Create a backup copy of the given filename + @param fname: string (file path) + @return: bool (True == Success) + + """ + backup = self.GetBackupFilename(fname) + try: + if os.path.exists(backup): + os.remove(backup) + + shutil.copy2(fname, backup) + if self.header: + handle = open(backup, 'r') + txt = handle.read() + handle.close() + handle = open(backup, 'w') + handle.write(self.header + os.linesep) + handle.write(txt) + handle.close() + except: + return False + else: + return True + + def SetBackupDirectory(self, path): + """Set the backup directory to use for all backups created by this + manager instance. Setting the path to an empty string will set the + default behavior to write the backup to the same directory as the + where the file that is being backedup is located. + + """ + self.bkupdir = path + + def SetBackupFileTemplate(self, tstr): + """Set the filename template for generating the backupfile name + @param tstr: template string i.e) %s~ + + """ + assert tstr.count("%s") == 1, "Format statment must only have one arg" + self.template = tstr + + def SetHeader(self, header): + """Set the header string for identifying a file as a backup + @param header: string (single line only) + + """ + assert '\n' not in header, "Header must only be a single line" + self.header = header diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/calllock.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/calllock.py new file mode 100644 index 0000000..b644b8e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/calllock.py @@ -0,0 +1,95 @@ +############################################################################### +# Name: calllock.py # +# Purpose: Manager to lock the context of a function call. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: CallLock + +Provides a Lock class for managing a lock during the duration of a function +call. + +Example: + +lock = CallLock(DoSomething) +lock.Lock() # Executes DoSomething + + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: calllock.py 65794 2010-10-13 14:10:09Z CJP $" +__revision__ = "$Revision: 65794 $" + +__all__ = [ 'CallLock', 'StaticCallLock', 'LockCall'] + +#-----------------------------------------------------------------------------# + +class CallLock(object): + """Class to lock a context around a function call""" + def __init__(self, callable=None, args=[], kwargs={}): + super(CallLock, self).__init__() + + # Attributes + self._locked = False + self.funct = callable + self.args = args + self.kwargs = kwargs + + def Discard(self): + """Clear callable""" + assert not self.IsLocked(), "Failed to obtain lock!" + self.funct = None + self.args = [] + self.kwargs = {} + + def IsLocked(self): + return self._locked + + def Lock(self): + assert not self.IsLocked(), "Failed to obtain lock!" + assert callable(self.funct), "No Callable to Lock!" + self._locked = True + rval = self.funct(*self.args, **self.kwargs) + self._locked = False + return rval + + def SetManagedCall(self, callable, args=[], kwargs={}): + """Set the call that will be managed by this lock""" + assert not self.IsLocked(), "Failed to obtain lock!" + self.funct = callable + self.args = args + self.kwargs = kwargs + +#-----------------------------------------------------------------------------# + +class StaticCallLock(CallLock): + """Provides a static lock around a function call""" + _staticlock = False + + def IsLocked(self): + return StaticCallLock._staticlock + + def Lock(self): + """Lock the static class member""" + StaticCallLock._staticlock = True + super(StaticCallLock, self).Lock() + StaticCallLock._staticlock = False + +#-----------------------------------------------------------------------------# + +def LockCall(lock, callable, args=[], kwargs={}): + """Convenience function for locking an function call with + the provided CallLock object. + + """ + if not isinstance(lock, CallLock): + raise TypeError("lock is not of type CallLock") + + lock.SetManagedCall(callable, args, kwargs) + rval = lock.Lock() + lock.Discard() + return rval diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/clipboard.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/clipboard.py new file mode 100644 index 0000000..199837a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/clipboard.py @@ -0,0 +1,151 @@ +############################################################################### +# Name: clipboard.py # +# Purpose: Vim like clipboard # +# Author: Hasan Aljudy # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: Clipboard + +Clipboard helper class + +""" + +__author__ = "Hasan Aljudy" +__cvsid__ = "$Id: clipboard.py 67123 2011-03-04 00:02:35Z CJP $" +__revision__ = "$Revision: 67123 $" + +__all__ = [ 'Clipboard', 'ClipboardException'] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +#-----------------------------------------------------------------------------# + +class ClipboardException(Exception): + """Thrown for errors in the Clipboard class""" + pass + +#-----------------------------------------------------------------------------# + +class Clipboard(object): + """Multiple clipboards as named registers (as per vim) + + " is an alias for system clipboard and is also the default clipboard. + + @note: The only way to access multiple clipboards right now is through + Normal mode when Vi(m) emulation is enabled. + + """ + NAMES = list(u'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_') + registers = {} + current = u'"' + + @classmethod + def ClearAll(cls): + """Clear all registers""" + for reg in cls.registers: + cls.registers[reg] = u'' + + @classmethod + def DeleteAll(cls): + """Delete all registers""" + cls.registers.clear() + + @classmethod + def Switch(cls, reg): + """Switch to register + @param reg: char + + """ + if reg in cls.NAMES or reg == u'"': + cls.current = reg + else: + raise ClipboardException(u"Switched to invalid register name") + + @classmethod + def NextFree(cls): + """Switch to the next free register. If current register is free, no + switching happens. + + A free register is one that's either unused or has no content + + @note: This is not used yet. + + """ + if cls.Get() == u'': + return + + for name in cls.NAMES: + if cls.registers.get(name, u'') == u'': + cls.Switch(name) + break + + @classmethod + def AllUsed(cls): + """Get a dictionary mapping all used clipboards (plus the system + clipboard) to their content. + @note: This is not used yet. + @return: dict + + """ + cmd_map = { u'"': cls.SystemGet() } + for name in cls.NAMES: + if cls.registers.get(name, u''): + cmd_map[name] = cls.registers[name] + return cmd_map + + @classmethod + def Get(cls): + """Get the content of the current register. Used for pasting""" + if cls.current == u'"': + return cls.SystemGet() + else: + return cls.registers.get(cls.current, u'') + + @classmethod + def Set(cls, text): + """Set the content of the current register + @param text: string + + """ + if cls.current == u'"': + return cls.SystemSet(text) + else: + cls.registers[cls.current] = text + + @classmethod + def SystemGet(cls): + """Get text from the system clipboard + @return: string + + """ + text = None + if wx.TheClipboard.Open(): + if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)): + text = wx.TextDataObject() + wx.TheClipboard.GetData(text) + + wx.TheClipboard.Close() + + if text is not None: + return text.GetText() + else: + return u'' + + @classmethod + def SystemSet(cls, text): + """Set text into the system clipboard + @param text: string + @return: bool + + """ + ok = False + if wx.TheClipboard.Open(): + wx.TheClipboard.SetData(wx.TextDataObject(text)) + wx.TheClipboard.Close() + ok = True + return ok diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/cmenumgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/cmenumgr.py new file mode 100644 index 0000000..57c8095 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/cmenumgr.py @@ -0,0 +1,114 @@ +############################################################################### +# Name: cmenumgr.py # +# Purpose: ContextMenu Manager # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: ContextMenuManager + +Helper class for managing context menu callbacks + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: cmenumgr.py 69118 2011-09-17 18:46:15Z CJP $" +__revision__ = "$Revision: 69118 $" + +__all__ = [ 'ContextMenuManager', ] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +#-----------------------------------------------------------------------------# + +class ContextMenuManager(object): + """Class for registering and managing context menu callbacks""" + def __init__(self): + super(ContextMenuManager, self).__init__() + + # Attributes + self._menu = None # Context Menu + self._pos = (0, 0) # Menu position + self._handlers = dict() # {ID : callable(event)} + self._userdata = dict() + + Menu = property(lambda self: self.GetMenu(), + lambda self, menu: self.SetMenu(menu)) + + Position = property(lambda self: self.GetPosition(), + lambda self, pos: self.SetPosition(pos)) + + def __del__(self): + """Cleanup when it goes out of scope""" + self.Clear() + + def AddHandler(self, evt_id, handler): + """Add an event handler + @param evt_id: int + @param handler: callable(event) + + """ + self._handlers[evt_id] = handler + + def Clear(self): + """Clear all handlers and destroy the menu""" + self._handlers.clear() + self._userdata.clear() + if self._menu: + self._menu.Destroy() + + def GetHandler(self, evt_id): + """Get the event handler for the provided ID or None + @param evt_id: int + @return: callable or None + + """ + return self._handlers.get(evt_id, None) + + def GetMenu(self): + """Get the menu that is being managed by this manager + @return: wxMenu + + """ + return self._menu + + def GetPosition(self): + """Get the menu position + @return: tuple (int, int) + + """ + return self._pos + + def GetUserData(self, key): + """Get user data + @param key: data id key + + """ + return self._userdata.get(key, None) + + def SetMenu(self, menu): + """Set the menu that this manager should manage + @param menu: wxMenu + + """ + assert isinstance(menu, wx.Menu), "menu must be a wxMenu" + self._menu = menu + + def SetPosition(self, pos): + """Set the menu position + @param pos: tuple (int, int) + + """ + self._pos = pos + + def SetUserData(self, key, data): + """Add custom user data to the manager + @param key: unique key used to retrieve the data later + @param data: user data + + """ + self._userdata[key] = data diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/e_weblib.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/e_weblib.py new file mode 100644 index 0000000..a079479 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/e_weblib.py @@ -0,0 +1,100 @@ +############################################################################### +# Name: weblib.py # +# Purpose: Web an network utilties # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Buisness Model Library: Web Utilities + +Utility functions for working with web and other networking protocols + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: e_weblib.py 66131 2010-11-13 05:22:48Z CJP $" +__revision__ = "$Revision: 66131 $" + +__all__ = ['SOAP12Message',] + +#-----------------------------------------------------------------------------# +# imports +import urllib2 +import httplib + +#-----------------------------------------------------------------------------# +_SOAP_TPL = """<?xml version=\"1.0\" encoding=\"utf-8\"?> +<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\"> +<soap12:Body> + %(msg)s +</soap12:Body> +</soap12:Envelope> + +""" + +_SM_TPL = """<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope +SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" +xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> +<SOAP-ENV:Body> + %(msg)s +</SOAP-ENV:Body> +</SOAP-ENV:Envelope> +""" + +#-----------------------------------------------------------------------------# + +class SOAP12Message(object): + """Class for creating and sending a message + using the SOAP protocol. + + """ + def __init__(self, host, request, msg, action=""): + """Create the message object + @param host: host the message will be sent to (url) + @param request: POST request + @param msg: XML Body text + @keyword action: SoapAction + + """ + assert len(host), "Must specify a valid host" + super(SOAP12Message, self).__init__() + + # Attributes + self._host = host + self._request = request + self._msg = msg + self._action = action + self._http = httplib.HTTP(self._host, 80) + + @property + def MessageBody(self): + soapmsg = _SOAP_TPL % dict(msg=self._msg) + soapmsg = soapmsg.replace("\n", "\r\n") + return soapmsg + + def Send(self): + """Send the message""" + # Create the SOAP message + soapmsg = self.MessageBody + + # Setup Headers + self._http.putrequest("POST", self._request) + self._http.putheader("Host", self._host) +# self._http.putheader("User-Agent", "Python post") + self._http.putheader("Content-Type", "application/soap+xml; charset=utf-8") + self._http.putheader("Content-Length", "%d" % len(soapmsg)) + self._http.putheader("SOAPAction", '"%s"' % self._action) + self._http.endheaders() + + # Send it + self._http.send(soapmsg) + + def GetReply(self): + """Get the reply (may block for a long time) + @return: (statuscode, statusmessage, header) + + """ + return self._http.getreply() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/efilehist.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/efilehist.py new file mode 100644 index 0000000..8684697 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/efilehist.py @@ -0,0 +1,135 @@ +############################################################################### +# Name: efilehist.py # +# Purpose: Enhanced FileHistory # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model: EFileHistory + +Enhanced File History - Provides more consistent behavior than wxFileHistory + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: efilehist.py 71668 2012-06-06 18:32:07Z CJP $" +__revision__ = "$Revision: 71668 $" + +__all__ = ['EFileHistory',] + +#-----------------------------------------------------------------------------# +# Imports +import os +import wx + +# Local Imports +import txtutil + +#-----------------------------------------------------------------------------# + +class EFileHistory(object): + """FileHistory Menu Manager""" + def __init__(self, maxFile=9): + assert maxFile <= 9, "supports at most 9 files" + super(EFileHistory, self).__init__() + + # Attributes + self._history = list() + self._maxFiles = maxFile + self._menu = None + + def _UpdateMenu(self): + """Update the filehistory menu""" + menu = self.Menu # optimization + assert menu is not None + for item in menu.GetMenuItems(): + menu.RemoveItem(item) + + # Validate and cleanup any bad entries + to_remove = list() + for item in self.History: + if not item: + to_remove.append(item) + elif not os.path.exists(item): + to_remove.append(item) + for item in to_remove: + self.History.remove(item) + + for index, histfile in enumerate(self.History): + menuid = wx.ID_FILE1 + index + if menuid <= wx.ID_FILE9: + menu.Append(menuid, histfile) + else: + break + + Count = property(lambda self: self.GetCount()) + History = property(lambda self: self._history, + lambda self, hist: self.SetHistory(hist)) + MaxFiles = property(lambda self: self._maxFiles) + Menu = property(lambda self: self._menu, + lambda self, menu: self.UseMenu(menu)) + + def AddFileToHistory(self, fname): + """Add a file to the history + @param fname: Unicode + + """ + if not fname: + return + assert txtutil.IsUnicode(fname) + assert self.Menu is not None + # Shuffle to top of history if already in there + if fname in self.History: + self.History.remove(fname) + self.History.insert(0, fname) + # Maintain set length + if self.Count > self.MaxFiles: + self._history.pop() + # Update menu object for new history list + self._UpdateMenu() + + def GetCount(self): + """Get the number of files in the history + @return: int + + """ + return len(self._history) + + def GetHistoryFile(self, index): + """Get the history file at the given index + @param index: int + @return: Unicode + + """ + assert self.MaxFiles > index, "Index out of range" + return self.History[index] + + def RemoveFileFromHistory(self, index): + """Remove a file from the history""" + assert self.MaxFiles > index, "Index out of range" + self.History.pop(index) + self._UpdateMenu() + + def SetHistory(self, hist): + """Set the file history from a list + @param hist: list of Unicode + + """ + # Ensure list is unique + hist = list(set(hist)) + assert len(hist) <= self.MaxFiles + self._history = hist + self._UpdateMenu() + + def UseMenu(self, menu): + """Set the menu for the file history to use + @param menu: wx.Menu + + """ + assert isinstance(menu, wx.Menu) + if self.Menu is not None: + self._menu.Destroy() + self._menu = menu + self._UpdateMenu() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fchecker.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fchecker.py new file mode 100644 index 0000000..4786cf5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fchecker.py @@ -0,0 +1,89 @@ +############################################################################### +# Name: fchecker.py # +# Purpose: Filetype checker object. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Buisness Model Library: FileTypeChecker + +Helper class for checking what kind of a content a file contains. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: fchecker.py 65147 2010-07-31 05:59:58Z CJP $" +__revision__ = "$Revision: 65147 $" + +__all__ = [ 'FileTypeChecker', ] + +#-----------------------------------------------------------------------------# +# Imports +import os + +#-----------------------------------------------------------------------------# + +class FileTypeChecker(object): + """File type checker and recognizer""" + TXTCHARS = ''.join(map(chr, [7, 8, 9, 10, 12, 13, 27] + range(0x20, 0x100))) + ALLBYTES = ''.join(map(chr, range(256))) + + def __init__(self, preread=4096): + """Create the FileTypeChecker + @keyword preread: number of bytes to read for checking file type + + """ + super(FileTypeChecker, self).__init__() + + # Attributes + self._preread = preread + + @staticmethod + def _GetHandle(fname): + """Get a file handle for reading + @param fname: filename + @return: file object or None + + """ + try: + handle = open(fname, 'rb') + except: + handle = None + return handle + + def IsBinary(self, fname): + """Is the file made up of binary data + @param fname: filename to check + @return: bool + + """ + handle = self._GetHandle(fname) + if handle is not None: + bytes = handle.read(self._preread) + handle.close() + return self.IsBinaryBytes(bytes) + else: + return False + + def IsBinaryBytes(self, bytes): + """Check if the given string is composed of binary bytes + @param bytes: string + + """ + nontext = bytes.translate(FileTypeChecker.ALLBYTES, + FileTypeChecker.TXTCHARS) + return bool(nontext) + + def IsReadableText(self, fname): + """Is the given path readable as text. Will return True if the + file is accessable by current user and is plain text. + @param fname: filename + @return: bool + + """ + f_ok = False + if os.access(fname, os.R_OK): + f_ok = not self.IsBinary(fname) + return f_ok diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileimpl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileimpl.py new file mode 100644 index 0000000..0130dfa --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileimpl.py @@ -0,0 +1,226 @@ +############################################################################### +# Name: Cody Precord # +# Purpose: File Object Interface Implementation # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Business Model Library: FileObjectImpl + +Implementation of a file object interface class. Objects and methods inside +of this library expect a file object that derives from this interface. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: fileimpl.py 70309 2012-01-10 00:09:26Z CJP $" +__revision__ = "$Revision: 70309 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import sys + +# Editra Business Model Imports +import txtutil +import fileutil + +#--------------------------------------------------------------------------# + +class FileObjectImpl(object): + """File Object Interface implementation base class""" + def __init__(self, path=u'', modtime=0): + super(FileObjectImpl, self).__init__() + + # Attributes + self._path = fileutil.GetPathFromURI(path) + self._modtime = modtime + + self._handle = None + self.open = False + + self.last_err = None + + # Properties + Path = property(lambda self: self.GetPath(), + lambda self, path: self.SetPath(path)) + Handle = property(lambda self: self._handle) + ModTime = property(lambda self: self.GetModTime(), + lambda self, tstamp: self.SetModTime(tstamp)) + ReadOnly = property(lambda self: self.IsReadOnly()) + + def ClearLastError(self): + """Reset the error marker on this file""" + del self.last_err + self.last_err = None + + def Clone(self): + """Clone the file object + @return: FileObject + + """ + fileobj = FileObjectImpl(self._path, self._modtime) + fileobj.SetLastError(self.last_err) + return fileobj + + def Close(self): + """Close the file handle + @note: this is normally done automatically after a read/write operation + + """ + try: + self._handle.close() + except: + pass + + self.open = False + + def DoOpen(self, mode): + """Opens and creates the internal file object + @param mode: mode to open file in + @return: True if opened, False if not + @postcondition: self._handle is set to the open handle + + """ + if not len(self._path): + return False + + try: + file_h = open(self._path, mode) + except (IOError, OSError), msg: + self.SetLastError(unicode(msg)) + return False + else: + self._handle = file_h + self.open = True + return True + + def Exists(self): + """Does the file exist on disk? + @return: bool + + """ + if self._path: + return fileutil.PathExists(self._path) + else: + return False + + def GetExtension(self): + """Get the files extension if it has one else simply return the + filename minus the path. + @return: string file extension (no dot) + + """ + fname = os.path.split(self._path) + return fname[-1].split(os.extsep)[-1].lower() + + def GetHandle(self): + """Get this files handle""" + return self._handle + + def GetLastError(self): + """Return the last error that occurred when using this file + @return: err traceback or None + + """ + errstr = u"None" + if self.last_err: + if not txtutil.IsUnicode(self.last_err): + errstr = unicode(self.last_err) + else: + errstr = self.last_err + return errstr + + def GetModTime(self): + """Get the timestamp of this files last modification""" + return self._modtime + + def GetPath(self): + """Get the path of the file + @return: string + + """ + return self._path + + def GetSize(self): + """Get the size of the file + @return: int + + """ + if self._path: + return fileutil.GetFileSize(self._path) + else: + return 0 + + def IsOpen(self): + """Check if file is open or not + @return: bool + + """ + return self.open + + def IsReadOnly(self): + """Is the file Read Only + @return: bool + + """ + if os.path.exists(self._path): + return not os.access(self._path, os.R_OK|os.W_OK) + else: + return False + + def ResetAll(self): + """Reset all file attributes""" + self._handle = None + self.open = False + self._path = u'' + self._modtime = 0 + self.last_err = None + + def SetLastError(self, err): + """Set the last error + @param err: exception object / msg + + """ + self.last_err = err + + def SetPath(self, path): + """Set the path of the file + @param path: absolute path to file + + """ + self._path = fileutil.GetPathFromURI(path) + + def SetModTime(self, mtime): + """Set the modtime of this file + @param mtime: long int to set modtime to + + """ + self._modtime = mtime + + #--- SHould be overridden by subclass ---# + + def Read(self): + """Open/Read the file + @return: string (file contents) + + """ + txt = u'' + if self.DoOpen('rb'): + try: + txt = self._handle.read() + except: + pass + + return txt + + def Write(self, value): + """Open/Write the value to disk + @param value: string + + """ + if self.DoOpen('wb'): + self._handle.write(value) + self._handle.close() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileutil.py new file mode 100644 index 0000000..cc0b43f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/fileutil.py @@ -0,0 +1,453 @@ +############################################################################### +# Name: fileutil.py # +# Purpose: File Management Utilities. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: File Utilities + +Utility functions for managing and working with files. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: fileutil.py 71689 2012-06-07 18:55:45Z CJP $" +__revision__ = "$Revision: 71689 $" + +__all__ = [ 'GetAbsPath', 'GetFileExtension', 'GetFileModTime', 'GetFileName', + 'GetFileSize', 'GetPathName', 'GetPathFromURI', 'GetUniqueName', + 'IsLink', 'MakeNewFile', 'MakeNewFolder', 'PathExists', + 'ResolveRealPath', 'IsExecutable', 'Which', 'ComparePaths', + 'AddFileExtension', 'GetDirectoryObject', 'File', 'Directory', + 'GetFileManagerCmd', 'OpenWithFileManager', 'IsHidden', 'IsSubPath' ] + +#-----------------------------------------------------------------------------# +# Imports +import wx +import ctypes +import os +import platform +import urllib2 +import stat +import subprocess + +UNIX = WIN = False +if wx.Platform == '__WXMSW__': + WIN = True + try: + # Check for if win32 extensions are available + import win32com.client as win32client + except ImportError: + win32client = None + + try: + # Check for win32api + import win32api + except ImportError: + win32api = None +else: + UNIX = True + +#-----------------------------------------------------------------------------# + +def uri2path(func): + """Decorator method to convert path arguments that may be uri's to + real file system paths. Arg 0 must be a file path or uri. + + """ + def WrapURI(*args, **kwargs): + args = list(args) + args[0] = GetPathFromURI(args[0]) + return func(*args, **kwargs) + + WrapURI.__name__ = func.__name__ + WrapURI.__doc__ = func.__doc__ + return WrapURI + +#-----------------------------------------------------------------------------# + +def AddFileExtension(path, ext): + """Add a file extension to a path if it doesn't already exist + @param path: file path + @param ext: file extension + + """ + assert isinstance(ext, basestring) + if not ext.startswith('.'): + ext = '.' + ext + if not path.endswith(ext): + path = path + ext + return path + +def ComparePaths(path1, path2): + """Determine whether the two given paths are equivalent + @param path1: unicode + @param path2: unicode + @return: bool + + """ + path1 = GetAbsPath(path1) + path2 = GetAbsPath(path2) + if WIN: + path1 = path1.lower() + path2 = path2.lower() + return path1 == path2 + +def CopyFile(orig, dest): + """Copy the given file to the destination + @param orig: file to copy (full path) + @param dest: where to copy to + + """ + raise NotImplementedError + +@uri2path +def GetAbsPath(path): + """Get the absolute path of a file of a file. + @param path: string + @return: string + @note: on windows if win32api is available short notation paths will be + converted to the proper long name. + + """ + rpath = os.path.abspath(path) + # Resolve short path notation on Windows when possible + if WIN and win32api is not None and u"~" in rpath: + try: + rpath = win32api.GetLongPathNameW(rpath) + except Exception: + # Ignore errors from win32api calls + pass + return rpath + +def GetFileExtension(file_str): + """Gets last atom at end of string as extension if + no extension whole string is returned + @param file_str: path or file name to get extension from + + """ + return file_str.split('.')[-1] + +def GetFileModTime(file_name): + """Returns the time that the given file was last modified on + @param file_name: path of file to get mtime of + + """ + try: + mod_time = os.path.getmtime(file_name) + except (OSError, EnvironmentError): + mod_time = 0 + return mod_time + +def GetFileName(path): + """Gets last atom on end of string as filename + @param path: full path to get filename from + + """ + return os.path.split(path)[-1] + +@uri2path +def GetFileSize(path): + """Get the size of the file at a given path + @param path: Path to file + @return: long + + """ + try: + return os.stat(path)[stat.ST_SIZE] + except: + return 0 + +def GetPathFromURI(path): + """Get a local path from a file:// uri + @return: normalized path + + """ + if path.startswith(u"file:"): + path = path.replace(u"file:", u"") + path = path.lstrip(u"/") + if platform.system().lower() in ('windows', 'microsoft'): + path = path.replace(u"/", u"\\") + if len(path) >= 2 and path[1] != u':': + # A valid windows file uri should start with the drive + # letter. If not make the assumption that it should be + # the C: drive. + path = u"C:\\\\" + path + else: + path = u"/" + path + path = urllib2.unquote(path) + + return path + +@uri2path +def GetPathName(path): + """Gets the path minus filename + @param path: full path to get base of + + """ + return os.path.split(path)[0] + +@uri2path +def IsLink(path): + """Is the file a link + @return: bool + + """ + if WIN: + return path.endswith(".lnk") or os.path.islink(path) + else: + return os.path.islink(path) + +def IsSubPath(path1, path2): + """Is path1 a subpath of path2 + i.e) /usr/bin/foo is a subpath of /usr/bin + @return: bool + + """ + if WIN: + path1 = path1.lower() + path2 = path2.lower() + path1 = GetAbsPath(path1) + path2 = GetAbsPath(path2) + return path1.startswith(path2) + +@uri2path +def IsHidden(path): + """Is the path a hidden path + @param path: path to check + @return: bool + + """ + bHidden = False + if PathExists(path): + if WIN: + try: + attrs = ctypes.windll.kernel32.GetFileAttributesW(path) + assert attrs != -1 + bHidden = bool(attrs & 2) + except (AttributeError, AssertionError): + bHidden = False + else: + dname = GetFileName(path) + bHidden = dname.startswith('.') + return bHidden + +@uri2path +def PathExists(path): + """Does the path exist. + @param path: file path or uri + @return: bool + + """ + return os.path.exists(path) + +@uri2path +def IsExecutable(path): + """Is the file at the given path an executable file + @param path: file path + @return: bool + + """ + return os.path.isfile(path) and os.access(path, os.X_OK) + +@uri2path +def ResolveRealPath(link): + """Return the real path of the link file + @param link: path of link file + @return: string + + """ + assert IsLink(link), "ResolveRealPath expects a link file!" + realpath = link + if WIN and win32client is not None: + shell = win32client.Dispatch("WScript.Shell") + shortcut = shell.CreateShortCut(link) + realpath = shortcut.Targetpath + else: + realpath = os.path.realpath(link) + return realpath + +def GetFileManagerCmd(): + """Get the file manager open command for the current os. Under linux + it will check for xdg-open, nautilus, konqueror, and Thunar, it will then + return which one it finds first or 'nautilus' it finds nothing. + @return: string + + """ + if wx.Platform == '__WXMAC__': + return 'open' + elif wx.Platform == '__WXMSW__': + return 'explorer' + else: + # Check for common linux filemanagers returning first one found + # Gnome/ubuntu KDE/kubuntu xubuntu + for cmd in ('xdg-open', 'nautilus', 'konqueror', 'Thunar'): + result = os.system("which %s > /dev/null" % cmd) + if result == 0: + return cmd + else: + return 'nautilus' + +def OpenWithFileManager(path): + """Open the given path with the systems file manager + @param path: file/directory path + + """ + cmd = GetFileManagerCmd() + subprocess.call([cmd, path]) + +def Which(program): + """Find the path of the given executable + @param program: executable name (i.e 'python') + @return: executable path or None + + """ + # Check local directory first + if IsExecutable(program): + return program + else: + # Start looking on the $PATH + for path in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(path, program) + if IsExecutable(exe_file): + return exe_file + return None + +def GetDirectoryObject(path, recurse=True, includedot=False): + """Gets a L{Directory} object representing the filesystem of the + given path. + @param path: base path to list + @keyword recurse: recurse into subdirectories + @keyword includedot: include '.' files + @return: L{Directory} object instance + + """ + assert os.path.isdir(path) + def _BuildDir(thedir): + dirAddFile = thedir.Files.append + isdir = os.path.isdir + pjoin = os.path.join + for fname in os.listdir(thedir.Path): + if not includedot and fname.startswith('.'): + continue + fpath = pjoin(thedir.Path, fname) + if isdir(fpath): + newobj = Directory(fpath) + if recurse: + _BuildDir(newobj) + else: + newobj = File(fpath) + dirAddFile(newobj) + + dobj = Directory(path) + _BuildDir(dobj) + return dobj + +#-----------------------------------------------------------------------------# + +class File(object): + """Basic file data structure""" + __slots__ = ('path', 'modtime') + def __init__(self, path): + super(File, self).__init__() + + self.path = path + self.modtime = GetFileModTime(self.path) + + Path = property(lambda self: self.path) + Name = property(lambda self: os.path.basename(self.Path)) + ModTime = property(lambda self: self.modtime, + lambda self, mod: setattr(self, 'modtime', mod)) + + def __str__(self): + return self.Path + + def __eq__(self, other): + assert isinstance(other, File) + return ComparePaths(self.Path, other.Path) + +class Directory(File): + """Basic directory data structure. + Is a container class that provides a simple in memory representation of + a file system. + + """ + __slots__ = ('files',) + def __init__(self, path): + super(Directory, self).__init__(path) + + self.files = list() + + Files = property(lambda self: self.files) + +#-----------------------------------------------------------------------------# + +def GetUniqueName(path, name): + """Make a file name that will be unique in case a file of the + same name already exists at that path. + @param path: Root path to folder of files destination + @param name: desired file name base + @return: string + + """ + tmpname = os.path.join(path, name) + if os.path.exists(tmpname): + if '.' not in name: + ext = '' + fbase = name + else: + ext = '.' + name.split('.')[-1] + fbase = name[:-1 * len(ext)] + + inc = len([x for x in os.listdir(path) if x.startswith(fbase)]) + tmpname = os.path.join(path, "%s-%d%s" % (fbase, inc, ext)) + while os.path.exists(tmpname): + inc = inc + 1 + tmpname = os.path.join(path, "%s-%d%s" % (fbase, inc, ext)) + + return tmpname + + +#-----------------------------------------------------------------------------# + +def MakeNewFile(path, name): + """Make a new file at the given path with the given name. + If the file already exists, the given name will be changed to + a unique name in the form of name + -NUMBER + .extension + @param path: path to directory to create file in + @param name: desired name of file + @return: Tuple of (success?, Path of new file OR Error message) + + """ + if not os.path.isdir(path): + path = os.path.dirname(path) + fname = GetUniqueName(path, name) + + try: + open(fname, 'w').close() + except (IOError, OSError), msg: + return (False, str(msg)) + + return (True, fname) + +def MakeNewFolder(path, name): + """Make a new folder at the given path with the given name. + If the folder already exists, the given name will be changed to + a unique name in the form of name + -NUMBER. + @param path: path to create folder on + @param name: desired name for folder + @return: Tuple of (success?, new dirname OR Error message) + + """ + if not os.path.isdir(path): + path = os.path.dirname(path) + folder = GetUniqueName(path, name) + try: + os.mkdir(folder) + except (OSError, IOError), msg: + return (False, str(msg)) + + return (True, folder) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/histcache.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/histcache.py new file mode 100644 index 0000000..3bb0736 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/histcache.py @@ -0,0 +1,262 @@ +############################################################################### +# Name: histcache.py # +# Purpose: History Cache # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Buisness Model Library: HistoryCache + +History cache that acts as a stack for managing a history list o + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: histcache.py 67123 2011-03-04 00:02:35Z CJP $" +__revision__ = "$Revision: 67123 $" + +__all__ = [ 'HistoryCache', 'HIST_CACHE_UNLIMITED', + 'CycleCache'] + +#-----------------------------------------------------------------------------# +# Imports + +#-----------------------------------------------------------------------------# +# Globals +HIST_CACHE_UNLIMITED = -1 + +#-----------------------------------------------------------------------------# + +class HistoryCache(object): + """Data management cache. + Maintains a positional list of objects that remembers the last access + position in the cache. + + """ + def __init__(self, max_size=HIST_CACHE_UNLIMITED): + """@param max_size: size of history cache (int)""" + super(HistoryCache, self).__init__() + + # Attributes + self._list = list() + self.cpos = -1 + self.max_size = max_size + + def _Resize(self): + """Adjust cache size based on max size setting""" + if self.max_size != HIST_CACHE_UNLIMITED: + lsize = len(self._list) + if lsize: + adj = self.max_size - lsize + if adj < 0: + self._list.pop(0) + self.cpos = len(self._list) - 1 + + def Clear(self): + """Clear the history cache""" + del self._list + self._list = list() + self.cpos = -1 + + def GetSize(self): + """Get the current size of the cache + @return: int (number of items in the cache) + + """ + return len(self._list) + + def GetMaxSize(self): + """Get the max size of the cache + @return: int + + """ + return self.max_size + + def GetNextItem(self): + """Get the next item in the history cache, moving the + current position towards the end of the cache. + @return: object or None if at end of list + + """ + item = None + if self.cpos < len(self._list) - 1: + self.cpos += 1 + item = self._list[self.cpos] + return item + + def GetPreviousItem(self): + """Get the previous item in the history cache, moving the + current position towards the beginning of the cache. + @return: object or None if at start of list + + """ + item = None + if self.cpos >= 0 and len(self._list) > 0: + if self.cpos == len(self._list): + self.cpos -= 1 + item = self._list[self.cpos] + self.cpos -= 1 + return item + + def HasPrevious(self): + """Are there more items to the left of the current position + @return: bool + + """ + llen = len(self._list) + more = ((self.cpos >= 0) and llen and (self.cpos < llen)) + return more + + def HasNext(self): + """Are there more items to the right of the current position + @return: bool + + """ + if self.cpos == -1 and len(self._list): + more = True + else: + more = self.cpos >= 0 and self.cpos < (len(self._list) - 1) + return more + + def PeekNext(self): + """Return the next item in the cache without modifying the + currently managed position. + @return: cache object + + """ + if self.HasNext(): + return self._list[self.cpos+1] + else: + return None + + def PeekPrevious(self): + """Return the previous item in the cache without modifying the + currently managed position. + @return: cache object + + """ + if self.HasPrevious(): + return self._list[self.cpos] + else: + return None + + def PutItem(self, item): + """Put an item on the top of the cache + @param item: object + + """ + if self.cpos != len(self._list) - 1: + self._list = self._list[:self.cpos] + self._list.append(item) + self.cpos += 1 + self._Resize() + + def SetMaxSize(self, max_size): + """Set the maximum size of the cache + @param max_size: int (HIST_CACHE_UNLIMITED for unlimited size) + + """ + assert max_size > 0 or max_size == 1, "Invalid max size" + self.max_size = max_size + self._Resize() + +#-----------------------------------------------------------------------------# + +class CycleCache(object): + """A simple circular cache. All items are added to the end of the cache + regardless of the current reference position. As items are accessed from + the cache the cache reference pointer is incremented, if it passes the + end it will go back to the beginning. + + """ + def __init__(self, size): + """Initialize the cache. + @param size: cache size + + """ + super(CycleCache, self).__init__() + + # Attributes + self._list = list() + self._cpos = -1 + self._size = size + + def __len__(self): + return len(self._list) + + def NextIndex(self): + """Get the next index in the cache + @return: int + + """ + idx = self._cpos + idx -= 1 + if abs(idx) > len(self._list): + idx = -1 + return idx + + def Clear(self): + """Clear the cache""" + del self._list + self._list = list() + + def GetCurrentSize(self): + """Get the size of the cache + @return: int + + """ + return len(self._list) + + def GetNext(self): + """Get the next item in the cache and increment the + current position. + @return: object + + """ + item = None + if len(self._list): + item = self._list[self._cpos] + self._cpos = self.NextIndex() + return item + + def PeekNext(self): + """Look the next item in the cache + @return: object + + """ + item = None + if abs(self._cpos) < len(self._list): + item = self._list[self._cpos] + return item + + def PeekPrev(self): + """Look the next item in the cache + @return: object + + """ + idx = self._cpos + 1 + if idx == 0: + idx = -1 * len(self._list) + + llen = len(self._list) + if llen and abs(idx) <= llen: + item = self._list[idx] + else: + item = None + return item + + def PutItem(self, item): + """Put an item in the cache + @param item: object + + """ + llen = len(self._list) + if llen and (llen == self._size): + del self._list[0] + self._list.append(item) + + def Reset(self): + """Reset the list reference pointer""" + self._cpos = -1 diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/logfile.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/logfile.py new file mode 100644 index 0000000..ce5f4a4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/logfile.py @@ -0,0 +1,104 @@ +############################################################################### +# Name: Cody Precord # +# Purpose: Log File # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Business Model Library: LogFile + +Log file class for managing log files or other transient files that should +be purged after a given period of time. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: logfile.py 66868 2011-02-09 16:01:49Z CJP $" +__revision__ = "$Revision: 66868 $" + +__all__ = ['LogFile',] + +#--------------------------------------------------------------------------# +# Imports +import os +import time +import datetime +import re +import tempfile + +#--------------------------------------------------------------------------# + +class LogFile(object): + """Log file class""" + def __init__(self, prefix, logdir=None): + """Create a log file + @param prefix: filename prefix + @keyword logdir: abs path to log output dir + @note: if logdir is None then the system temp directory will be used + + """ + super(LogFile, self).__init__() + + # Attributes + self.prefix = prefix + self.logdir = logdir + + # Setup + if self.logdir is None: + self.logdir = tempfile.gettempdir() + + #---- Properties ----# + LogDirectory = property(lambda self: self.logdir, + lambda self, dname: setattr(self, 'logdir', dname)) + Prefix = property(lambda self: self.prefix, + lambda self, prefix: setattr(self, 'prefix', prefix)) + + #---- Public Interface ----# + def WriteMessage(self, msg): + """Append the message to the current log file + @param msg: string object + + """ + # Files are named as prefix_YYYY_MM_DD.log + logstamp = "%d_%d_%d" % time.localtime()[:3] + logname = "%s_%s.log" % (self.prefix, logstamp) + logpath = os.path.join(self.logdir, logname) + if os.path.exists(logpath): + opencmd = "ab" + else: + opencmd = "wb" + +# with open(logpath, opencmd) as handle: +# handle.write(msg.rstrip() + os.linesep) + try: + handle = open(logpath, opencmd) + handle.write(msg.rstrip() + os.linesep) + handle.close() + except IOError: + pass + + def PurgeOldLogs(self, days): + """Purge all log files older than n days + @param days: number of days + + """ + logpattern = re.compile("%s_[0-9]{4}_[0-9]{1,2}_[0-9]{1,2}.log" % self.prefix) + paths = list() + cdate = datetime.date(*time.localtime()[:3]) + for path in os.listdir(self.logdir): + if logpattern.match(path): + ymd = [int(x) for x in path[len(self.prefix)+1:-4].split('_')] + fdate = datetime.date(*ymd) + span = cdate - fdate + if span.days > days: + fpath = os.path.join(self.logdir, path) + paths.append(fpath) + + # Attempt to cleanup the old files + for log in paths: + try: + os.remove(log) + except OSError: + pass diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/miscutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/miscutil.py new file mode 100644 index 0000000..88e9349 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/miscutil.py @@ -0,0 +1,52 @@ +############################################################################### +# Name: miscutil.py # +# Purpose: Various helper functions. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: MiscUtil + +Various helper functions + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: miscutil.py 67329 2011-03-28 23:40:48Z CJP $" +__revision__ = "$Revision: 67329 $" + +__all__ = [ 'MinMax', 'Singleton'] + +#-----------------------------------------------------------------------------# +# Imports + +#-----------------------------------------------------------------------------# + +class Singleton(type): + """Singleton metaclass for creating singleton classes + @note: class being applied to must have a SetupWindow method + + """ + def __init__(cls, name, bases, dict): + super(Singleton, cls).__init__(name, bases, dict) + cls.instance = None + + def __call__(cls, *args, **kw): + if not cls.instance: + # Not created or has been Destroyed + obj = super(Singleton, cls).__call__(*args, **kw) + cls.instance = obj + + return cls.instance + +#-----------------------------------------------------------------------------# + +def MinMax(arg1, arg2): + """Return an ordered tuple of the minimum and maximum value + of the two args. + @return: tuple + + """ + return min(arg1, arg2), max(arg1, arg2) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/osutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/osutil.py new file mode 100644 index 0000000..e6d98a3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/osutil.py @@ -0,0 +1,129 @@ +############################################################################### +# Name: osutil.py # +# Purpose: Text Utilities. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: Operating System Utilities + +Utilities for handling OS related interactions. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: $" +__revision__ = "$Revision: $" + +__all__ = ['InstallTermHandler', + 'GetWindowsDrives', 'GetWindowsDriveType', + 'GenericDrive', 'FixedDrive', 'CDROMDrive', 'RamDiskDrive', 'RemoteDrive', + 'RemovableDrive' ] + +#-----------------------------------------------------------------------------# +# Imports +import wx +import ctypes +import signal +import collections + +HASWIN32 = False +if wx.Platform == '__WXMSW__': + try: + import win32api + except ImportError: + HASWIN32 = False + else: + HASWIN32 = True + +#-----------------------------------------------------------------------------# +# Windows Drive Utilities + +class GenericDrive(object): + def __init__(self, name): + super(GenericDrive, self).__init__() + + # Attributes + self._name = name + + Name = property(lambda self: self._name, + lambda self, v: setattr(self, '_name', v)) + +class RemovableDrive(GenericDrive): + pass +class FixedDrive(GenericDrive): + pass +class RemoteDrive(GenericDrive): + pass +class CDROMDrive(GenericDrive): + pass +class RamDiskDrive(GenericDrive): + pass + +def GetWindowsDrives(): + """Get a list of all available windows drives + @return: list of strings + + """ + assert wx.Platform == '__WXMSW__', "Windows Only API Method" + drives = list() + try: + dletters = list() + bmask = ctypes.windll.kernel32.GetLogicalDrives() + for dletter in u"ABCDEFGHIJKLMNOPQRSTUVWXYZ": + if bmask & 1: + dletters.append(dletter) + bmask >>= 1 + + for dletter in dletters: + dname = dletter + u":\\" + dtype = GetWindowsDriveType(dname) + if type(dtype) != GenericDrive: + drives.append(dtype) + except Exception, err: + pass + return drives + +def GetWindowsDriveType(dname): + """Get the drive type for the given letter""" + assert wx.Platform == '__WXMSW__', "Windows Only API Method" + dtype = GenericDrive(dname) + try: + dtypes = [None, None, RemovableDrive, FixedDrive, RemoteDrive, CDROMDrive, RamDiskDrive] + idx = ctypes.windll.kernel32.GetDriveTypeW(dname) + if idx < len(dtypes): + drive = dtypes[idx] + if drive: + dtype = drive(dname) + except: + pass + return dtype + +#-----------------------------------------------------------------------------# + +def InstallTermHandler(callback, *args, **kwargs): + """Install exit app handler for sigterm (unix/linux) + and uses SetConsoleCtrlHandler on Windows. + @param callback: callable(*args, **kwargs) + @param args: positional arguments to pass to callback + @param kwargs: keyword arguments to pass to callback + @return: bool (installed or not) + + """ + assert isinstance(callback, collections.Callable), "callback must be callable!" + + installed = True + if wx.Platform == '__WXMSW__': + if HASWIN32: + win32api.SetConsoleCtrlHandler(lambda dummy : callback(*args, **kwargs), + True) + else: + installed = False + else: + signal.signal(signal.SIGTERM, + lambda signum, frame : callback(*args, **kwargs)) + + return installed + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/searcheng.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/searcheng.py new file mode 100644 index 0000000..cecf67c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/searcheng.py @@ -0,0 +1,418 @@ +############################################################################### +# Name: searcheng.py # +# Purpose: Text search engine and utilities # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: SearchEngine + +Text Search Engine for finding text and grepping files + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: searcheng.py 70206 2011-12-30 20:41:02Z CJP $" +__revision__ = "$Revision: 70206 $" + +__all__ = [ 'SearchEngine', ] + +#-----------------------------------------------------------------------------# +# Imports +import os +import re +import fnmatch +import types +import unicodedata +from StringIO import StringIO + +# Local imports +import fchecker + +#-----------------------------------------------------------------------------# + +class SearchEngine(object): + """Text Search Engine + All Search* methods are iterable generators + All Find* methods do a complete search and return the match collection + @summary: Text Search Engine + @todo: Add file filter support + + """ + def __init__(self, query, regex=True, down=True, + matchcase=True, wholeword=False): + """Initialize a search engine object + @param query: search string + @keyword regex: Is a regex search + @keyword down: Search down or up + @keyword matchcase: Match case + @keyword wholeword: Match whole word + + """ + super(SearchEngine, self).__init__() + + # Attributes + self._isregex = regex + self._next = down + self._matchcase = matchcase + self._wholeword = wholeword + self._query = query + self._regex = u'' + self._pool = u'' + self._lmatch = None # Last match object + self._filters = None # File Filters + self._formatter = lambda f, l, m: u"%s %d: %s" % (f, l+1, m) + self._CompileRegex() + + def _CompileRegex(self): + """Prepare and compile the regex object based on the current state + and settings of the engine. + @postcondition: the engines regular expression is created + + """ + tmp = self._query + + uquery = type(tmp) is types.UnicodeType + upool = type(self._pool) is types.UnicodeType + if uquery and upool: + tmp = unicodedata.normalize("NFC", tmp) + + if not self._isregex: + tmp = re.escape(tmp) + + if self._wholeword: + if uquery: + tmp = u"\\b%s\\b" % tmp + else: + tmp = "\\b%s\\b" % tmp + + flags = re.MULTILINE + if not self._matchcase: + flags |= re.IGNORECASE + + if upool: + flags |= re.UNICODE + # Normalize + self._pool = unicodedata.normalize("NFC", self._pool) + else: + # If the pools is not Unicode also make sure that the + # query is a string too. + if uquery: + try: + tmp = tmp.encode('utf-8') + except UnicodeEncodeError: + # TODO: better error reporting about encoding issue + self._regex = None + return + try: + self._regex = re.compile(tmp, flags) + except: + self._regex = None + self._data = (tmp, self._pool) + + def ClearPool(self): + """Clear the search pool""" + del self._pool + self._pool = u"" + + def Find(self, spos=0): + """Find the next match based on the state of the search engine + @keyword spos: search start position + @return: tuple (match start pos, match end pos) or None if no match + @note: L{SetSearchPool} has been called to set search string + + """ + if self._regex is None: + return None + + if self._next: + return self.FindNext(spos) + else: + if spos == 0: + spos = -1 + return self.FindPrev(spos) + + def FindAll(self): + """Find all the matches in the current context + @return: list of tuples [(start1, end1), (start2, end2), ] + + """ + if self._regex is None: + return list() + + matches = [match for match in self._regex.finditer(self._pool)] + return matches + + def FindAllLines(self): + """Find all the matches in the current context + @return: list of strings + + """ + rlist = list() + if self._regex is None: + return rlist + + for lnum, line in enumerate(StringIO(self._pool)): + if self._regex.search(line) is not None: + rlist.append(self._formatter(u"Untitled", lnum, line)) + + return rlist + + def FindNext(self, spos=0): + """Find the next match of the query starting at spos + @keyword spos: search start position in string + @return: tuple (match start pos, match end pos) or None if no match + @note: L{SetSearchPool} has been called to set the string to search in. + + """ + if self._regex is None: + return None + + if spos < len(self._pool): + match = self._regex.search(self._pool[spos:]) + if match is not None: + self._lmatch = match + return match.span() + return None + + def FindPrev(self, spos=-1): + """Find the previous match of the query starting at spos + @keyword spos: search start position in string + @return: tuple (match start pos, match end pos) + + """ + if self._regex is None: + return None + + if spos+1 < len(self._pool): + matches = [match for match in + self._regex.finditer(self._pool[:spos])] + if len(matches): + lmatch = matches[-1] + self._lmatch = lmatch + return (lmatch.start(), lmatch.end()) + return None + + def GetLastMatch(self): + """Get the last found match object from the previous L{FindNext} or + L{FindPrev} action. + @return: match object or None + + """ + return self._lmatch + + def GetOptionsString(self): + """Get a string describing the search engines options""" + rstring = u"\"%s\" [ " % self._query + for desc, attr in (("regex: %s", self._isregex), + ("match case: %s", self._matchcase), + ("whole word: %s", self._wholeword)): + if attr: + rstring += (desc % u"on; ") + else: + rstring += (desc % u"off; ") + rstring += u"]" + + return rstring + + def GetQuery(self): + """Get the raw query string used by the search engine + @return: string + + """ + return self._query + + def GetQueryObject(self): + """Get the regex object used for the search. Will return None if + there was an error in creating the object. + @return: pattern object + + """ + return self._regex + + def GetSearchPool(self): + """Get the search pool string for this L{SearchEngine}. + @return: string + + """ + return self._pool + + def IsMatchCase(self): + """Is the engine set to a case sensitive search + @return: bool + + """ + return self._matchcase + + def IsRegEx(self): + """Is the engine searching with the query as a regular expression + @return: bool + + """ + return self._isregex + + def IsWholeWord(self): + """Is the engine set to search for wholeword matches + @return: bool + + """ + return self._wholeword + + def SearchInBuffer(self, sbuffer): + """Search in the buffer + @param sbuffer: buffer like object + @todo: implement + + """ + raise NotImplementedError + + def SearchInDirectory(self, directory, recursive=True): + """Search in all the files found in the given directory + @param directory: directory path + @keyword recursive: search recursivly + + """ + if self._regex is None: + return + + # Get all files in the directories + paths = [os.path.join(directory, fname) + for fname in os.listdir(directory) if not fname.startswith('.')] + + # Filter out files that don't match the current filter(s) + if self._filters is not None and len(self._filters): + filtered = list() + for fname in paths: + if os.path.isdir(fname): + filtered.append(fname) + continue + + for pat in self._filters: + if fnmatch.fnmatch(fname, pat): + filtered.append(fname) + paths = filtered + + # Begin searching in the paths + for path in paths: + if recursive and os.path.isdir(path): + # Recursive call to decend into directories + for match in self.SearchInDirectory(path, recursive): + yield match + else: + for match in self.SearchInFile(path): + yield match + return + + def SearchInFile(self, fname): + """Search in a file for all lines with matches of the set query and + yield the results as they are found. + @param fname: filename + @todo: unicode handling + + """ + if self._regex is None: + return + + checker = fchecker.FileTypeChecker() + if checker.IsReadableText(fname): + try: + fobj = open(fname, 'rb') + except (IOError, OSError): + return + else: + # Special token to signify start of a search + yield (None, fname) + + for lnum, line in enumerate(fobj): + if self._regex.search(line) is not None: + yield self._formatter(fname, lnum, line) + fobj.close() + return + + def SearchInFiles(self, flist): + """Search in a list of files and yield results as they are found. + @param flist: list of file names + + """ + if self._regex is None: + return + + for fname in flist: + for match in self.SearchInFile(fname): + yield match + return + + def SearchInString(self, sstring, startpos=0): + """Search in a string + @param sstring: string to search in + @keyword startpos: search start position + + """ + raise NotImplementedError + + def SetFileFilters(self, filters): + """Set the file filters to specify what type of files to search in + the filter should be a list of wild card patterns to match. + @param filters: list of strings ['*.py', '*.pyw'] + + """ + self._filters = filters + + def SetFlags(self, isregex=None, matchcase=None, wholeword=None, down=None): + """Set the search engine flags. Leaving the parameter set to None + will not change the flag. Setting it to non None will change the value. + @keyword isregex: is regex search + @keyword matchcase: matchcase search + @keyword wholeword: wholeword search + @keyword down: search down or up + + """ + for attr, val in (('_isregex', isregex), ('_matchcase', matchcase), + ('_wholeword', wholeword), ('_next', down)): + if val is not None: + setattr(self, attr, val) + self._CompileRegex() + + def SetMatchCase(self, case=True): + """Set whether the engine will use case sensative searches + @keyword case: bool + + """ + self._matchcase = case + self._CompileRegex() + + def SetResultFormatter(self, funct): + """Set the result formatter function + @param funct: callable(filename, linenum, matchstr) + + """ + assert callable(funct) + self._formatter = funct + + def SetSearchPool(self, pool): + """Set the search pool used by the Find methods + @param pool: string to search in + + """ + del self._pool + self._pool = pool + self._CompileRegex() + + def SetQuery(self, query): + """Set the search query + @param query: string + + """ + self._query = query + self._CompileRegex() + + def SetUseRegex(self, use=True): + """Set whether the engine is using regular expresion searches or + not. + @keyword use: bool + + """ + self._isregex = use + self._CompileRegex() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/txtutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/txtutil.py new file mode 100644 index 0000000..1d10e60 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ebmlib/txtutil.py @@ -0,0 +1,46 @@ +############################################################################### +# Name: txtutil.py # +# Purpose: Text Utilities. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Business Model Library: Text Utilities + +Utility functions for managing and working with text. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: txtutil.py 67991 2011-06-20 23:48:01Z CJP $" +__revision__ = "$Revision: 67991 $" + +__all__ = [ 'IsUnicode', 'DecodeString'] + +#-----------------------------------------------------------------------------# +# Imports +import types + +#-----------------------------------------------------------------------------# + +def IsUnicode(txt): + """Is the given string a unicode string + @param txt: object + @return: bool + + """ + return isinstance(txt, types.UnicodeType) + +def DecodeString(txt, enc): + """Decode the given string with the given encoding, + only attempts to decode if the given txt is not already Unicode + @param txt: string + @param enc: encoding 'utf-8' + @return: unicode + + """ + if IsUnicode(txt): + txt = txt.decode(enc) + return txt diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/__init__.py new file mode 100644 index 0000000..8f52d56 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/__init__.py @@ -0,0 +1,50 @@ +############################################################################### +# Name: __init__.py # +# Purpose: Editra Control Library # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Control Library + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: __init__.py 70469 2012-01-27 19:27:02Z CJP $" +__revision__ = "$Revision: 70469 $" + + +__all__ = ['auinavi', 'choicedlg', 'colorsetter', 'ctrlbox', 'eclutil', + 'ecpickers', 'elistmix', 'encdlg', 'errdlg', 'finddlg', 'infodlg', + 'panelbox', 'outbuff', 'platebtn', 'pstatbar', 'segmentbk', + 'txtentry'] + +#-----------------------------------------------------------------------------# +from ecbasewin import * + +from auinavi import * +from choicedlg import * +from colorsetter import * +from ctrlbox import * +from eclutil import * +from ecpickers import * +from elistmix import * +from encdlg import * +from errdlg import * +from filterdlg import * +from finddlg import * +from infodlg import * +from outbuff import * +from panelbox import * +from platebtn import * +from pstatbar import * +from segmentbk import * +from txtentry import * +from elistctrl import * +from _filetree import * +from _infobar import * + +# TODO: Delete module entries once all plugins have been updated to not +# import them separately. diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_filetree.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_filetree.py new file mode 100644 index 0000000..0b84547 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_filetree.py @@ -0,0 +1,458 @@ +############################################################################### +# Name: _dirtree.py # +# Purpose: Directory Tree # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011-2013 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Control Library: FileTree + +Base class control for displaying a file system in a hierarchical manor. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _filetree.py 73347 2013-01-05 19:58:31Z CJP $" +__revision__ = "$Revision: 73347 $" + +__all__ = ['FileTree',] + +#-----------------------------------------------------------------------------# +# Imports +import sys +import os +import types +import wx + +#-----------------------------------------------------------------------------# + +class FileTree(wx.TreeCtrl): + """Simple base control for displaying directories and files in a + hierarchical view. + + """ + def __init__(self, parent): + super(FileTree, self).__init__(parent, + style=wx.TR_HIDE_ROOT| + wx.TR_FULL_ROW_HIGHLIGHT| + wx.TR_LINES_AT_ROOT| + wx.TR_HAS_BUTTONS| + wx.TR_MULTIPLE| + wx.TR_EDIT_LABELS) + + # Attributes + self._watch = list() # Root directories to watch + self._il = None + self._editlabels = True + + # Setup + self.SetupImageList() + self.AddRoot('root') + self.SetPyData(self.RootItem, "root") + + # Event Handlers + self.Bind(wx.EVT_TREE_ITEM_GETTOOLTIP, self._OnGetToolTip) + self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self._OnItemActivated) + self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self._OnItemCollapsed) + self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self._OnItemExpanding) + self.Bind(wx.EVT_TREE_ITEM_MENU, self._OnMenu) + self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self._OnBeginEdit) + self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self._OnEndEdit) + + def _OnBeginEdit(self, evt): + if not self._editlabels: + evt.Veto() + else: + item = evt.GetItem() + if self.DoBeginEdit(item): + evt.Skip() + else: + evt.Veto() + + def _OnEndEdit(self, evt): + if self._editlabels: + item = evt.GetItem() + newlabel = evt.GetLabel() + if self.DoEndEdit(item, newlabel): + evt.Skip() + return + evt.Veto() + + def _OnGetToolTip(self, evt): + item = evt.GetItem() + tt = self.DoGetToolTip(item) + if tt: + evt.ToolTip = tt + else: + evt.Skip() + + def _OnItemActivated(self, evt): + item = evt.GetItem() + self.DoItemActivated(item) + evt.Skip() + + def _OnItemCollapsed(self, evt): + item = evt.GetItem() + self.DoItemCollapsed(item) + evt.Skip() + + def _OnItemExpanding(self, evt): + item = evt.GetItem() + self.DoItemExpanding(item) + evt.Skip() + + def _OnMenu(self, evt): + try: + item = evt.GetItem() + self.DoShowMenu(item) + except: + pass + + #---- Properties ----# + + SelectedFiles = property(lambda self: self.GetSelectedFiles()) + + #---- Overridable methods ----# + + def DoBeginEdit(self, item): + """Overridable method that will be called when + a user has started to edit an item. + @param item: TreeItem + return: bool (True == Allow Edit) + + """ + return False + + def DoEndEdit(self, item, newlabel): + """Overridable method that will be called when + a user has finished editing an item. + @param item: TreeItem + @param newlabel: unicode (newly entered value) + return: bool (True == Change Accepted) + + """ + return False + + def DoGetToolTip(self, item): + """Get the tooltip to show for an item + @return: string or None + + """ + data = self.GetItemPyData(item) + return data + + def DoItemActivated(self, item): + """Override to handle item activation + @param item: TreeItem + + """ + pass + + def DoItemCollapsed(self, item): + """Handle when an item is collapsed + @param item: TreeItem + + """ + self.DeleteChildren(item) + + def DoItemExpanding(self, item): + """Handle when an item is expanding + @param item: TreeItem + + """ + d = self.GetPyData(item) + if d and os.path.exists(d): + contents = FileTree.GetDirContents(d) + for p in contents: + self.AppendFileNode(item, p) + + def DoShowMenu(self, item): + """Context menu has been requested for the given item. + @param item: wx.TreeItem + + """ + pass + + def DoSetupImageList(self): + """Add the images to the control's ImageList. It is guaranteed + that self.ImageList is valid and empty when this is called. + + """ + bmp = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_MENU, (16,16)) + self.ImageList.Add(bmp) + bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_MENU, (16,16)) + self.ImageList.Add(bmp) + bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_MENU, (16,16)) + self.ImageList.Add(bmp) + + def DoGetFileImage(self, path): + """Get the index of the image from the image list to use + for the file. + @param path: Absolute path of file + @return: long + + """ + # TODO: image handling + if not os.access(path, os.R_OK): + img = 2 + else: + if os.path.isdir(path): + img = 0 # Directory image + else: + img = 1 # Normal file image + return img + + #---- End Overrides ----# + + #---- Properties ----# + + WatchDirs = property(lambda self: self._watch) + + #---- FileTree Api ---# + + def AddWatchDirectory(self, dname): + """Add a directory to the controls top level view + @param dname: directory path + @return: TreeItem or None + @todo: add additional api for getting already existing nodes based + on path. + + """ + assert os.path.exists(dname), "Path(%s) doesn't exist!" % dname + if dname not in self._watch: + self._watch.append(dname) + return self.AppendFileNode(self.RootItem, dname) + + def RemoveWatchDirectory(self, dname): + """Remove a directory from the watch list + @param dname: directory path + + """ + if dname in self._watch: + self._watch.remove(dname) + nodes = self.GetChildNodes(self.RootItem) + for node in nodes: + data = self.GetPyData(node) + if dname == data: + self.Delete(node) + break + + def SetupImageList(self): + """Setup/Refresh the control's ImageList. + Override DoSetupImageList to customize the behavior of this method. + + """ + if self._il: + self._il.Destroy() + self._il = None + self._il = wx.ImageList(16, 16) + self.SetImageList(self._il) + self.DoSetupImageList() + + def AppendFileNode(self, item, path): + """Append a child node to the tree + @param item: TreeItem parent node + @param path: path to add to node + @return: new node + + """ + img = self.DoGetFileImage(path) + name = os.path.basename(path) + if not name: + name = path + child = self.AppendItem(item, name, img) + self.SetPyData(child, path) + if os.path.isdir(path): + self.SetItemHasChildren(child, True) + return child + + def AppendFileNodes(self, item, paths): + """Append a list of child node to the tree. This + method can be used instead of looping on AppendFileNode + to get slightly better performance for large sets. + @param item: TreeItem parent node + @param paths: list of file paths + @return: None + + """ + getBaseName = os.path.basename + isDir = os.path.isdir + getImg = self.DoGetFileImage + appendNode = self.AppendItem + setData = self.SetPyData + for path in paths: + img = getImg(path) + name = getBaseName(path) + if not name: + name = path + child = appendNode(item, name, img) + setData(child, path) + if isDir(path): + self.SetItemHasChildren(child, True) + + def GetChildNodes(self, parent): + """Get all the TreeItemIds under the given parent + @param parent: TreeItem + @return: list of TreeItems + + """ + rlist = list() + child, cookie = self.GetFirstChild(parent) + if not child or not child.IsOk(): + return rlist + + rlist.append(child) + while True: + child, cookie = self.GetNextChild(parent, cookie) + if not child or not child.IsOk(): + return rlist + rlist.append(child) + return rlist + + def GetExpandedNodes(self): + """Get all nodes that are currently expanded in the view + this logically corresponds to all parent directory nodes which + are expanded. + @return: list of TreeItems + + """ + + def NodeWalker(parent, rlist): + """Recursively find expanded nodes + @param parent: parent node + @param rlist: list (outparam) + + """ + children = self.GetChildNodes(parent) + for node in children: + if self.IsExpanded(node): + rlist.append(node) + NodeWalker(node, rlist) + + nodes = list() + NodeWalker(self.RootItem, nodes) + return nodes + + def GetSelectedFiles(self): + """Get a list of the selected files + @return: list of strings + + """ + nodes = self.GetSelections() + files = [ self.GetPyData(node) for node in nodes ] + return files + + def EnableLabelEditing(self, enable=True): + """Enable/Disable label editing. This functionality is + enabled by default. + @keyword enable: bool + + """ + self._editlabels = enable + + def SelectFile(self, filename): + """Select the given path + @param filename: full path to select + @return: bool + + """ + bSelected = False + # Find the root + for node in self.GetChildNodes(self.RootItem): + dname = self.GetPyData(node) + if not os.path.isdir(dname): + dname = os.path.dirname(dname) + if not dname.endswith(os.sep): + dname += os.sep + if filename.startswith(dname): + filename = filename[len(dname):].split(os.sep) + if not self.IsExpanded(node): + self.Expand(node) + folder = node + try: + while filename: + name = filename.pop(0) + for item in self.GetChildNodes(folder): + if self.GetItemText(item) == name: + if not self.IsExpanded(item): + self.Expand(item) + folder = item + continue + except: + pass + + self.UnselectAll() + self.EnsureVisible(folder) + self.SelectItem(folder) + break + + #---- Static Methods ----# + + @staticmethod + def GetDirContents(directory): + """Get the list of files contained in the given directory""" + assert os.path.isdir(directory) + files = list() + try: + joinPath = os.path.join + fappend = files.append + fs_encoding = sys.getfilesystemencoding() + for p in os.listdir(directory): + fullpath = joinPath(directory, p) + if type(fullpath) != types.UnicodeType: + fullpath = fullpath.decode(fs_encoding) + fappend(fullpath) + except OSError: + pass + return files + + def GetNodePaths(self, dirNode): + """Get a list of paths contained below the given + directory node. + @param dirNode: wx.TreeItemId + @return: list of paths + + """ + paths = list() + if self.ItemHasChildren(dirNode): + append = paths.append + getData = self.GetPyData + for node in self.GetChildNodes(dirNode): + try: + append(getData(node)) + except wx.PyAssertionError: + pass + return paths + + def GetPyData(self, item): + """Get data from given tree item + @param item: TreeItemId + + """ + data = None + # avoid assertions in base class when retrieving data... + if item and item.IsOk(): + try: + data = super(FileTree, self).GetPyData(item) + except wx.PyAssertionError: + pass + return data + + def SortParentDirectory(self, item): + """Sort the parent directory of the given item""" + parent = self.GetItemParent(item) + if parent.IsOk(): + self.SortChildren(parent) + +#-----------------------------------------------------------------------------# +# Test +if __name__ == '__main__': + app = wx.App(False) + f = wx.Frame(None) + ft = FileTree(f) + d = wx.GetUserHome() + ft.AddWatchDirectory(d) + f.Show() + app.MainLoop() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_infobar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_infobar.py new file mode 100644 index 0000000..f3cd4c8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/_infobar.py @@ -0,0 +1,148 @@ +############################################################################### +# Name: _infobar.py # +# Purpose: Information Panel Class # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2012 Cody Precord <staff@editra.org> # +# Licence: wxWindows License # +############################################################################### + +""" +Editra Control Library: InfoBar + +Small information panel that can be used to replace popup modal dialogs. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: $" +__revision__ = "$Revision: $" + +__all__ = [ 'InfoBar', 'INFOBAR_INFO', 'INFOBAR_WARN', 'INFOBAR_ERROR' ] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +# Local Imports +import eclutil + +#-----------------------------------------------------------------------------# + +INFOBAR_INFO, \ +INFOBAR_WARN, \ +INFOBAR_ERROR = range(3) + +#-----------------------------------------------------------------------------# + +class InfoBar(wx.PyPanel): + """Information popup panel""" + def __init__(self, parent, title=u"", message=u"", + msgType=INFOBAR_INFO, + style=wx.TAB_TRAVERSAL|wx.NO_BORDER): + """Create the InfoBar""" + super(InfoBar, self).__init__(parent, style=style) + self.Hide() # Initially hidden + + # Attributes + self._msgType = msgType + + # Controls + self._bmp = wx.StaticBitmap(self) + self._title = wx.StaticText(self, label=title) + self._msg = wx.StaticText(self, label=message) + self._okBtn = wx.Button(self, wx.ID_OK) + self._cancelBtn = wx.Button(self, wx.ID_CANCEL) + + # Setup + self.SetMessageType(msgType) + tfont = self._title.Font + tfont.SetWeight(wx.FONTWEIGHT_BOLD) + tfont.SetPointSize(tfont.PointSize + 1) + self._title.SetFont(tfont) + self.__DoLayout() + + # Events + self.Bind(wx.EVT_BUTTON, self.OnButton) + + def __DoLayout(self): + """Layout the panel""" + sizer = wx.BoxSizer(wx.HORIZONTAL) + # Bitmap + sizer.Add(self.Bitmap, 0, wx.ALL|wx.ALIGN_CENTER, 8) + # Text + txt_sz = wx.BoxSizer(wx.VERTICAL) + txt_sz.Add(self.Title, 0, wx.ALL, 3) + txt_sz.Add(self.Message, 0, wx.ALL, 3) + sizer.Add(txt_sz, 0) + # Padding + sizer.AddStretchSpacer() + # Buttons + btnsz = wx.BoxSizer(wx.VERTICAL) + btnsz.Add(self._okBtn, 0, wx.ALL|wx.ALIGN_CENTER, 3) + btnsz.Add(self._cancelBtn, 0, wx.ALL|wx.ALIGN_CENTER, 3) + sizer.Add(btnsz, 0, wx.ALIGN_RIGHT) + + self.SetSizer(sizer) + + def _UpdateParent(self): + """Update parent for layout changes""" + self.Parent.Layout() + self.Parent.SendSizeEvent() + + #---- Properties ----# + + Bitmap = property(lambda self: self._bmp) + Title = property (lambda self: self._title) + Message = property(lambda self: self._msg) + MessageType = property(lambda self: self._msgType, + lambda self, mtype: self.SetMessageType(mtype)) + ButtonOk = property(lambda self: self._okBtn) + ButtonCancel = property(lambda self: self._cancelBtn) + + #---- Event Handlers ---# + + def OnButton(self, evt): + """Handle button clicks""" + self.Show(False) + evt.Skip() + + #---- Implementation ----# + + def SetMessageType(self, msgType): + """Set the message type + @param msgType: INFOBAR_FOO identifier + + """ + bmp = wx.NullBitmap + if msgType == INFOBAR_INFO: + bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_CMN_DIALOG) + self.SetBackgroundColour(wx.BLUE) + elif msgType == INFOBAR_ERROR: + bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_CMN_DIALOG) + self.SetBackgroundColour(wx.Colour(230, 43, 29)) + elif msgType == INFOBAR_WARN: + bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_CMN_DIALOG) + self.SetBackgroundColour(wx.Colour(228, 165, 40)) + else: + raise TypeError("Unknown message type: %s" % repr(msgType)) + self._msgType = msgType + self.Bitmap.SetBitmap(bmp) + + tcolour = eclutil.BestLabelColour(self.BackgroundColour) + self.Title.SetOwnForegroundColour(tcolour) + self.Message.SetOwnForegroundColour(tcolour) + + self.Refresh() + + def Show(self, show=True): + """Override to handle parent update""" + super(InfoBar, self).Show(show) + self._UpdateParent() + self.Refresh() + + def ShowMessage(self, title=u"", message=u"", msgType=INFOBAR_INFO): + """Update the message and show the bar""" + self.Title.SetLabel(title) + self.Message.SetLabel(message) + self.MessageType = msgType + self.Show(True) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/auinavi.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/auinavi.py new file mode 100644 index 0000000..a213d5b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/auinavi.py @@ -0,0 +1,231 @@ +############################################################################### +# Name: auinavi.py # +# Purpose: AuiMgr Pane navigator # +# Author: Giuseppe "Cowo" Corbelli # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Control Library: AuiPaneNavigator + +Popup navigation window for quickly navigating through AuiPanes in an AuiMgr. +Activating the dialog will cause a modal popup dialog with a list of all panes +managed by the aui manager. Changing the selection in the dialog will highlight +the pane in the managed frame. Selecting the choice in the list will move the +focus to that pane. + ++---------------------+ +| bmp title | ++---------------------+ +| pane list | +| | +| | +| | +| | +| | ++---------------------+ + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: auinavi.py 65794 2010-10-13 14:10:09Z CJP $" +__revision__ = "$Revision: 65794 $" + +__all__ = ['AuiPaneNavigator',] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +# Editra Control Libray Imports +import ctrlbox + +#-----------------------------------------------------------------------------# + +class AuiPaneNavigator(wx.Dialog): + """Navigate through Aui Panes""" + def __init__(self, parent, auiMgr, icon=None, title=''): + """Initialize the navigator window + @param parent: parent window + @param auiMgr: wx.aui.AuiManager + @keyword icon: wx.Bitmap or None + @keyword title: string (dialog title) + + """ + super(AuiPaneNavigator, self).__init__(parent, wx.ID_ANY, + "", style=wx.STAY_ON_TOP) + + # Attributes + self._auimgr = auiMgr + self._selectedItem = -1 + self._indexMap = list() + self._sel = 0 + self._tabed = 0 + self._close_keys = [wx.WXK_ALT, wx.WXK_CONTROL, wx.WXK_RETURN] + self._navi_keys = [wx.WXK_TAB, ord('1')] # <- TEMP + self._listBox = None + self._panel = None + + # Setup + self.__DoLayout(icon, title) + + # Get the panes + self.PopulateListControl() + + # Event Handlers + self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey) + self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected) + self._listBox.Bind(wx.EVT_LISTBOX, lambda evt: self.HighlightPane()) + + def __del__(self): + self._auimgr.HideHint() + + def __DoLayout(self, icon, title): + """Layout the dialog controls + @param icon: wx.Bitmap or None + @param title: string + + """ + sz = wx.BoxSizer(wx.VERTICAL) + self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, + wx.Size(200, 150), list(), + wx.LB_SINGLE | wx.NO_BORDER) + + self._panel = ctrlbox.ControlBar(self, + style=ctrlbox.CTRLBAR_STYLE_GRADIENT) + self._panel.SetVMargin(2, 2) + + if icon is not None: + bmp = wx.StaticBitmap(self._panel, bitmap=icon) + self._panel.AddControl(bmp, wx.ALIGN_LEFT) + + txt = wx.StaticText(self._panel, label=title) + self._panel.AddControl(txt, wx.ALIGN_LEFT) + + sz.Add(self._panel, 0, wx.EXPAND) + sz.Add(self._listBox, 1, wx.EXPAND) + sz.Fit(self) + sz.SetSizeHints(self) + sz.Layout() + self.Centre() + self.SetSizer(sz) + self.SetAutoLayout(True) + + def OnKeyUp(self, event): + """Handles wx.EVT_KEY_UP""" + self._auimgr.HideHint() + key_code = event.GetKeyCode() + # TODO: add setter method for setting the navigation key + if key_code in self._navi_keys: + self._tabed += 1 + + # Don't move selection on initial show + if self._tabed == 1: + self.HighlightPane() + event.Skip() + return + + selected = self._listBox.GetSelection() + 1 + if selected >= self._listBox.GetCount(): + selected = 0 + + self._listBox.SetSelection(selected) + self.HighlightPane() + event.Skip() + elif key_code in self._close_keys: + self.CloseDialog() + elif key_code == wx.WXK_ESCAPE: + self.CloseDialog() + else: + event.Skip() + + def OnNavigationKey(self, event): + """Handles wx.EVT_NAVIGATION_KEY""" + selected = self._listBox.GetSelection() + maxItems = self._listBox.GetCount() + + if event.GetDirection(): + # Select next pane + if selected == maxItems - 1: + itemToSelect = 0 + else: + itemToSelect = selected + 1 + else: + # Previous pane + if selected == 0: + itemToSelect = maxItems - 1 + else: + itemToSelect = selected - 1 + + self._listBox.SetSelection(itemToSelect) + self.HighlightPane() + + def PopulateListControl(self): + """Populates the L{AuiPaneNavigator} with the panes in the AuiMgr""" + self._panes = self._auimgr.GetAllPanes() + names = [pane.name for pane in self._panes] + self._listBox.AppendItems(sorted(names)) + + def OnItemSelected(self, event): + """Handles the wx.EVT_LISTBOX_DCLICK event""" + self.CloseDialog() + + def CloseDialog(self): + """Closes the L{AuiPaneNavigator} dialog""" + self._selectedItem = self._listBox.GetStringSelection() + self._auimgr.HideHint() + self.EndModal(wx.ID_OK) + + def GetCloseKeys(self): + """Get the list of keys that can dismiss the dialog + @return: list of long (wx.WXK_*) + + """ + return self._close_keys + + def GetNavigationKeys(self): + """Get the list of navigation key(s) + @return: list of long (wx.WXK_*) + + """ + return self._navi_keys + + def GetSelection(self): + """Get the index of the selected page""" + return self._selectedItem + + def HighlightPane(self): + """Highlight the currently selected pane""" + sel = self._listBox.GetStringSelection() + pane = self._auimgr.GetPane(sel) + if pane.IsOk(): + self._auimgr.ShowHint(pane.window.GetScreenRect()) + # NOTE: this is odd but it is the only way for the focus to + # work correctly on wxMac... + wx.CallAfter(self._listBox.SetFocus) + self._listBox.SetFocus() + + def SetCloseKeys(self, keylist): + """Set the keys that can be used to dismiss the L{AuiPaneNavigator} + window. + @param keylist: list of key codes + + """ + self._close_keys = keylist + + def SetNavigationKeys(self, keylist): + """Set the key(s) to advance the selection in the pane list + @param keylist: list of key codes + + """ + self._navi_keys = keylist + + def ShowModal(self): + # Set focus on the list box to avoid having to click on it to change + # the tab selection under GTK. + self._listBox.SetFocus() + self._listBox.SetSelection(0) + return super(AuiPaneNavigator, self).ShowModal()
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/choicedlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/choicedlg.py new file mode 100644 index 0000000..6c4e219 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/choicedlg.py @@ -0,0 +1,249 @@ +############################################################################### +# Name: choicedlg.py # +# Purpose: Generic Choice Dialog # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: Choice Dialog + +A generic choice dialog that uses a wx.Choice control to display its choices. + +@summary: Generic Choice Dialog + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: choicedlg.py 70230 2012-01-01 01:47:42Z CJP $" +__revision__ = "$Revision: 70230 $" + +__all__ = ['ChoiceDialog',] + +#--------------------------------------------------------------------------# +# Imports +import wx + +import ecbasewin + +#--------------------------------------------------------------------------# +# Globals +ChoiceDialogNameStr = u"ChoiceDialog" + +#--------------------------------------------------------------------------# + +class ChoiceDialog(ecbasewin.ECBaseDlg): + """Dialog with a wx.Choice control for showing a list of choices""" + def __init__(self, parent, id=wx.ID_ANY, + msg=u'', title=u'', + choices=None, default=u'', + pos=wx.DefaultPosition, + size=wx.DefaultSize, + style=0, + name=ChoiceDialogNameStr): + """Create the choice dialog + @param parent: Parent Window + @keyword id: Dialog ID + @keyword msg: Dialog Message + @keyword title: Dialog Title + @keyword choices: list of strings + @keyword default: Default selection + @keyword pos: Dialog Position + @keyword size: Dialog Size + @keyword style: Dialog Style bitmask + @keyword name: Dialog Name + + """ + super(ChoiceDialog, self).__init__(parent, id, title, + style=wx.CAPTION, pos=pos, + size=size, name=name) + + # Attributes + panel = ChoicePanel(self, msg=msg, + choices=choices, + default=default, + style=style) + self.SetPanel(panel) + self.SetInitialSize() + +#--------------------------------------------------------------------------# + +class ChoicePanel(wx.Panel): + """Generic Choice dialog panel""" + def __init__(self, parent, msg=u'', choices=list(), + default=u'', style=wx.OK|wx.CANCEL): + """Create the panel + @param parent: Parent Window + @keyword msg: Display message + @keyword choices: list of strings + @keyword default: default selection + @keyword style: panel style + + """ + super(ChoicePanel, self).__init__(parent) + + # Attributes + self._msg = msg + self._choices = wx.Choice(self, wx.ID_ANY) + self._selection = default + self._selidx = 0 + self._bmp = None + self._buttons = list() + + # Setup + self._choices.SetItems(choices) + if default in choices: + self._choices.SetStringSelection(default) + self._selidx = self._choices.GetSelection() + else: + self._choices.SetSelection(0) + self._selidx = 0 + self._selection = self._choices.GetStringSelection() + + # Setup Buttons + for btn, id_ in ((wx.OK, wx.ID_OK), (wx.CANCEL, wx.ID_CANCEL), + (wx.YES, wx.ID_YES), (wx.NO, wx.ID_NO)): + if btn & style: + button = wx.Button(self, id_) + self._buttons.append(button) + + if not len(self._buttons): + self._buttons.append(wx.Button(self, wx.ID_OK)) + self._buttons.append(wx.Button(self, wx.ID_CANCEL)) + + # Layout + self.__DoLayout(style) + + # Event Handlers + self.Bind(wx.EVT_CHOICE, self.OnChoice, self._choices) + self.Bind(wx.EVT_BUTTON, self.OnButton) + + def __DoLayout(self, style): + """Layout the panel""" + hsizer = wx.BoxSizer(wx.HORIZONTAL) + vsizer = wx.BoxSizer(wx.VERTICAL) + caption = wx.StaticText(self, label=self._msg) + + # Layout the buttons + bsizer = wx.StdDialogButtonSizer() + for button in self._buttons: + bsizer.AddButton(button) + bid = button.GetId() + if bid in (wx.ID_NO, wx.ID_YES): + if wx.NO_DEFAULT & style: + if bid == wx.ID_NO: + button.SetDefault() + else: + if bid == wx.ID_YES: + button.SetDefault() + elif bid == wx.ID_OK: + button.SetDefault() + + bsizer.Realize() + + vsizer.AddMany([((10, 10), 0), (caption, 0), ((20, 20), 0), + (self._choices, 1, wx.EXPAND), ((10, 10), 0), + (bsizer, 1, wx.EXPAND), + ((10, 10), 0)]) + + icon_id = wx.ART_INFORMATION + for i_id, a_id in ((wx.ICON_ERROR, wx.ART_ERROR), + (wx.ICON_WARNING, wx.ART_WARNING)): + if i_id & style: + icon_id = a_id + break + + icon = wx.ArtProvider.GetBitmap(icon_id, wx.ART_MESSAGE_BOX, (64, 64)) + self._bmp = wx.StaticBitmap(self, bitmap=icon) + bmpsz = wx.BoxSizer(wx.VERTICAL) + bmpsz.AddMany([((10, 10), 0), (self._bmp, 0, wx.ALIGN_CENTER_VERTICAL), + ((10, 30), 0, wx.EXPAND)]) + hsizer.AddMany([((10, 10), 0), (bmpsz, 0, wx.ALIGN_TOP), + ((10, 10), 0), (vsizer, 1), ((10, 10), 0)]) + + self.SetSizer(hsizer) + self.SetInitialSize() + self.SetAutoLayout(True) + + def GetChoiceControl(self): + """Get the dialogs choice control + @return: wx.Choice + + """ + return self._choices + + @ecbasewin.expose(ChoiceDialog) + def GetSelection(self): + """Get the chosen index + @return: int + + """ + return self._selidx + + @ecbasewin.expose(ChoiceDialog) + def GetStringSelection(self): + """Get the chosen string + @return: string + + """ + return self._selection + + def OnButton(self, evt): + """Handle button events + @param evt: wx.EVT_BUTTON + + """ + self.GetParent().EndModal(evt.GetId()) + + def OnChoice(self, evt): + """Update the selection + @param evt: wx.EVT_CHOICE + + """ + if evt.GetEventObject() == self._choices: + self._selection = self._choices.GetStringSelection() + self._selidx = self._choices.GetSelection() + else: + evt.Skip() + + @ecbasewin.expose(ChoiceDialog) + def SetBitmap(self, bmp): + """Set the dialogs bitmap + @param bmp: wx.Bitmap + + """ + self._bmp.SetBitmap(bmp) + self.Layout() + + @ecbasewin.expose(ChoiceDialog) + def SetChoices(self, choices): + """Set the dialogs choices + @param choices: list of strings + + """ + self._choices.SetItems(choices) + self._choices.SetSelection(0) + self._selection = self._choices.GetStringSelection() + + @ecbasewin.expose(ChoiceDialog) + def SetSelection(self, sel): + """Set the selected choice + @param sel: int + + """ + self._choices.SetSelection(sel) + self._selection = self._choices.GetStringSelection() + self._selidx = self._choices.GetSelection() + + @ecbasewin.expose(ChoiceDialog) + def SetStringSelection(self, sel): + """Set the selected choice + @param sel: string + + """ + self._choices.SetStringSelection(sel) + self._selection = self._choices.GetStringSelection() + self._selidx = self._choices.GetSelection() + +#--------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/colorsetter.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/colorsetter.py new file mode 100644 index 0000000..5bb555a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/colorsetter.py @@ -0,0 +1,263 @@ +############################################################################### +# Name: colorsetter.py # +# Purpose: Color Picker/Setter Control # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: ColorSetter + +Color picker control that has a text entry section for entering hex color codes, +there is also a button that previews the color and can be used to open a color +choice dialog. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: colorsetter.py 70230 2012-01-01 01:47:42Z CJP $" +__revision__ = "$Revision: 70230 $" + +__all__ = ["ColorSetter", "ColorSetterEvent", + "EVT_COLORSETTER", "csEVT_COLORSETTER"] + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.lib.colourselect as csel + +from eclutil import HexToRGB, Freezer + +#-----------------------------------------------------------------------------# +# Globals +# NOTE: # is expected at end +HEX_CHARS = "0123456789ABCDEFabcdef#" + +_ = wx.GetTranslation +#-----------------------------------------------------------------------------# + +csEVT_COLORSETTER = wx.NewEventType() +EVT_COLORSETTER = wx.PyEventBinder(csEVT_COLORSETTER, 1) +class ColorSetterEvent(wx.PyCommandEvent): + """Event to signal that text needs updating""" + def __init__(self, etype, eid, value=None): + """Creates the event object""" + wx.PyCommandEvent.__init__(self, etype, eid) + self._value = value + + def GetValue(self): + """Returns the value from the event. + @return: the value of this event + + """ + return self._value + +#-----------------------------------------------------------------------------# + +class ColorSetter(wx.Panel): + """Control for setting a hex color value or selecting it from a + Color Dialog. + + """ + def __init__(self, parent, id_, color=wx.NullColour): + """Create the control, it is a composite of a colourSelect and + and a text control. + @param parent: Parent Window + @param id_: Control ID + @keyword color: Initial Colour + + """ + super(ColorSetter, self).__init__(parent, id_) + + if isinstance(color, tuple): + color = wx.Colour(*color) + + # Attributes + self._label = color.GetAsString(wx.C2S_HTML_SYNTAX) + self._txt = wx.TextCtrl(self, + value=self._label, + style=wx.TE_CENTER, + validator=HexValidator()) + txtheight = self._txt.GetTextExtent('#000000')[1] + self._txt.SetMaxSize((-1, txtheight + 4)) + self._txt.SetToolTip(wx.ToolTip(_("Enter a hex color value"))) + self._cbtn = csel.ColourSelect(self, colour=color, size=(20, 20)) + self._preval = color + self._DoLayout() + + # Event Handlers + self.Bind(csel.EVT_COLOURSELECT, self.OnColour) + self._txt.Bind(wx.EVT_KEY_UP, self.OnTextChange) + self._txt.Bind(wx.EVT_TEXT_PASTE, self.OnTextChange) + self._txt.Bind(wx.EVT_KEY_DOWN, self.OnValidateTxt) + + def __PostEvent(self): + """Notify the parent window of any value changes to the control""" + value = self._cbtn.GetValue() + if not isinstance(value, wx.Colour): + value = wx.Colour(*value) + + # Don't post update if value hasn't changed + if value == self._preval: + return + + self._preval = value + evt = ColorSetterEvent(csEVT_COLORSETTER, self.GetId(), value) + evt.SetEventObject(self) + wx.PostEvent(self.GetParent(), evt) + + def __UpdateValues(self): + """Update the values based on the current state of the text control""" + with Freezer(self._txt) as _tmp: + cpos = self._txt.GetInsertionPoint() + hexstr = self._txt.GetValue().replace('#', '').strip() + valid = '' + for char in hexstr: + if char in HEX_CHARS[:-1]: + valid = valid + char + + if len(valid) > 6: + valid = valid[:6] + + valid = '#' + valid + self._txt.SetValue(valid) + self._txt.SetInsertionPoint(cpos) + valid = valid + (u'0' * (6 - len(valid))) + self._cbtn.SetValue(HexToRGB(valid)) + + def _DoLayout(self): + """Layout the controls""" + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self._txt, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL) + sizer.Add((5, 5), 0) + sizer.Add(self._cbtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) + self.SetSizer(sizer) + + def GetColour(self): + """Returns the colour value of the control + @return: wxColour object + + """ + return self._cbtn.GetValue() + + def GetLabel(self): + """Gets the hex value from the text control + @return: string '#123456' + @note: ensures a full 6 digit hex value is returned, padding + with zero's where necessary + + """ + hexstr = self._txt.GetValue() + hexstr = hexstr.replace('#', '').replace(' ', '') + hexstr = '#' + hexstr + ('0' * (6 - len(hexstr))) + return hexstr + + def OnColour(self, evt): + """Update the button and text control value + when a choice is made in the colour dialog. + @param evt: EVT_COLOURSELECT + + """ + e_val = evt.GetValue()[0:3] + red, green, blue = (hex(val)[2:].upper() for val in e_val) + hex_str = u"#%s%s%s" % (red.zfill(2), green.zfill(2), blue.zfill(2)) + self._txt.SetValue(hex_str) + self._cbtn.SetValue(wx.Colour(*e_val)) + self.__PostEvent() + + def OnTextChange(self, evt=None): + """Catch when text changes in the text control and update + button accordingly. + @keyword evt: event that called this handler + + """ + self.__UpdateValues() + self.__PostEvent() + + def OnValidateTxt(self, evt): + """Validate text to ensure only valid hex characters are entered + @param evt: wxEVT_KEY_DOWN + + """ + code = evt.GetKeyCode() + if code in (wx.WXK_DELETE, wx.WXK_BACK, wx.WXK_LEFT, + wx.WXK_RIGHT, wx.WXK_TAB) or evt.CmdDown(): + evt.Skip() + return + + key = unichr(code) + if (key.isdigit() and evt.ShiftDown()) or \ + evt.AltDown() or evt.MetaDown(): + return + + if key in HEX_CHARS and \ + (len(self._txt.GetValue().lstrip(u"#")) < 6 or \ + self._txt.GetStringSelection()): + evt.Skip() + + def SetLabel(self, label): + """Set the label value of the text control + @param label: hex string to set label to + + """ + self._txt.SetValue(label) + self.__UpdateValues() + + def SetValue(self, colour): + """Set the color value of the button + @param colour: wxColour or 3 tuple to set color value to + + """ + self._cbtn.SetValue(colour) + self._preval = colour + red, green, blue = (hex(val)[2:].zfill(2).upper() for val in colour[0:3]) + hex_str = u"#%s%s%s" % (red, green, blue) + self._txt.SetValue(hex_str) + +#-----------------------------------------------------------------------------# + +class HexValidator(wx.PyValidator): + """Validate Hex strings for the color setter""" + def __init__(self): + """Initialize the validator + + """ + super(HexValidator, self).__init__() + + # Event Handlers + self.Bind(wx.EVT_CHAR, self.OnChar) + + def Clone(self): + """Clones the current validator + @return: clone of this object + + """ + return HexValidator() + + def Validate(self, win): + """Validate an window value + @param win: window to validate + + """ + for char in val: + if char not in HEX_CHARS: + return False + else: + return True + + def OnChar(self, event): + """Process values as they are entered into the control + @param event: event that called this handler + + """ + key = event.GetKeyCode() + if event.CmdDown() or key < wx.WXK_SPACE or key == wx.WXK_DELETE or \ + key > 255 or chr(key) in HEX_CHARS[:-1]: + event.Skip() + return + + if not wx.Validator_IsSilent(): + wx.Bell() + + return diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ctrlbox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ctrlbox.py new file mode 100644 index 0000000..9b1678b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ctrlbox.py @@ -0,0 +1,1186 @@ +############################################################################### +# Name: ctrlbox.py # +# Purpose: Container Window helper class # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: ControlBox + +Sizer managed panel class with support for a toolbar like control that can be +placed on the top/bottom of the main window area, multiple control bars are also +possible. + +Class ControlBar: + +Toolbar like control with automatic item spacing and layout. + +Styles: + - CTRLBAR_STYLE_DEFAULT: Plain background + - CTRLBAR_STYLE_GRADIENT: Draw the bar with a vertical gradient. + - CTRLBAR_STYLE_BORDER_BOTTOM: add a border to the bottom + - CTRLBAR_STYLE_BORDER: add a border to the top + - CTRLBAR_STYLE_VERTICAL = Vertical ControlBar tool layout + +Class ControlBox: + +The ControlBox is a sizer managed panel that supports easy creation of windows +that require a sandwich like layout. + ++---------------------------------------+ +| ControlBar | ++---------------------------------------+ +| | +| | +| MainWindow Area | +| | +| | +| | ++---------------------------------------+ +| ControlBar | ++---------------------------------------+ + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ctrlbox.py 71187 2012-04-11 23:38:30Z CJP $" +__revision__ = "$Revision: 71187 $" + +__all__ = ["ControlBox", "CTRLBOX_NAME_STR", + + "ControlBar", "ControlBarEvent", + "CTRLBAR_STYLE_DEFAULT", "CTRLBAR_STYLE_GRADIENT", + "CTRLBAR_STYLE_BORDER_TOP", "CTRLBAR_STYLE_BORDER_BOTTOM", + "CTRLBAR_STYLE_VERTICAL", + "EVT_CTRLBAR", "edEVT_CTRLBAR", "CTRLBAR_NAME_STR", + + "SegmentBar", "SegmentBarEvent", + "EVT_SEGMENT_SELECTED", "edEVT_SEGMENT_SELECTED", + "EVT_SEGMENT_CLOSE", "edEVT_SEGMENT_CLOSE", + "CTRLBAR_STYLE_LABELS", "CTRLBAR_STYLE_NO_DIVIDERS", + "SEGBTN_OPT_CLOSEBTNL", "SEGBTN_OPT_CLOSEBTNR", + "SEGBAR_NAME_STR", "SEGMENT_HT_NOWHERE", + "SEGMENT_HT_SEG", "SEGMENT_HT_X_BTN" +] + +#--------------------------------------------------------------------------# +# Dependencies +import wx + +# Local Imports +from eclutil import AdjustColour, DrawCircleCloseBmp + +#--------------------------------------------------------------------------# +# Globals + +#-- Control Name Strings --# +CTRLBAR_NAME_STR = u'EditraControlBar' +CTRLBOX_NAME_STR = u'EditraControlBox' +SEGBAR_NAME_STR = u'EditraSegmentBar' + +#-- Control Style Flags --# + +# ControlBar / SegmentBar Style Flags +CTRLBAR_STYLE_DEFAULT = 0 +CTRLBAR_STYLE_GRADIENT = 1 # Paint the bar with a gradient +CTRLBAR_STYLE_BORDER_BOTTOM = 2 # Add a border to the bottom +CTRLBAR_STYLE_BORDER_TOP = 4 # Add a border to the top +CTRLBAR_STYLE_LABELS = 8 # Draw labels under the icons (SegmentBar) +CTRLBAR_STYLE_NO_DIVIDERS = 16 # Don't draw dividers between segments +CTRLBAR_STYLE_VERTICAL = 32 # Control bar in vertical orientation + +# Segment Button Options +SEGBTN_OPT_NONE = 1 # No options set. +SEGBTN_OPT_CLOSEBTNL = 2 # Close button on the segments left side. +SEGBTN_OPT_CLOSEBTNR = 4 # Close button on the segment right side. + +# Hit test locations +SEGMENT_HT_NOWHERE = 0 +SEGMENT_HT_SEG = 1 +SEGMENT_HT_X_BTN = 2 + +# Segment States +SEGMENT_STATE_NONE = 0 # Hover no where +SEGMENT_STATE_SEG = 1 # Hover on segment +SEGMENT_STATE_X = 2 # Hover on segment x button + +# ControlBar event for items added by AddTool +edEVT_CTRLBAR = wx.NewEventType() +EVT_CTRLBAR = wx.PyEventBinder(edEVT_CTRLBAR, 1) +class ControlBarEvent(wx.PyCommandEvent): + """ControlBar Button Event""" + +edEVT_SEGMENT_SELECTED = wx.NewEventType() +EVT_SEGMENT_SELECTED = wx.PyEventBinder(edEVT_SEGMENT_SELECTED, 1) +edEVT_SEGMENT_CLOSE = wx.NewEventType() +EVT_SEGMENT_CLOSE = wx.PyEventBinder(edEVT_SEGMENT_CLOSE, 1) +class SegmentBarEvent(wx.PyCommandEvent): + """SegmentBar Button Event""" + def __init__(self, etype, id=0): + super(SegmentBarEvent, self).__init__(etype, id) + + # Attributes + self.notify = wx.NotifyEvent(etype, id) + self._pre = -1 + self._cur = -1 + + def GetPreviousSelection(self): + """Get the previously selected segment + @return: int + + """ + return self._pre + + def GetCurrentSelection(self): + """Get the currently selected segment + @return: int + + """ + return self._cur + + def IsAllowed(self): + """Is the event allowed to propagate + @return: bool + + """ + return self.notify.IsAllowed() + + def SetSelections(self, previous=-1, current=-1): + """Set the events selection + @keyword previous: previously selected button index (int) + @keyword current: currently selected button index (int) + + """ + self._pre = previous + self._cur = current + + def Veto(self): + """Veto the event""" + self.notify.Veto() + +#--------------------------------------------------------------------------# + +class ControlBox(wx.PyPanel): + """Simple managed panel helper class that allows for adding and + managing the position of a small toolbar like panel. + @see: L{ControlBar} + + """ + def __init__(self, parent, id=wx.ID_ANY, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.TAB_TRAVERSAL|wx.NO_BORDER, + name=CTRLBOX_NAME_STR): + super(ControlBox, self).__init__(parent, id, pos, size, style, name) + + # Attributes + self._vsizer = wx.BoxSizer(wx.VERTICAL) + self._hsizer = wx.BoxSizer(wx.HORIZONTAL) + self._cbars = dict() + self._main = None + + # Layout + self._hsizer.Add(self._vsizer, 1, wx.EXPAND) + self.SetSizer(self._hsizer) + + #---- Properties ----# + Window = property(lambda self: self.GetWindow()) + + def _GetCtrlBarSizer(self, pos): + """Get the correct sizer for the ControlBar at the given pos + @param pos: wx.TOP/LEFT/RIGHT/BOTTOM + + """ + if pos in (wx.TOP, wx.BOTTOM): + sizer = self._vsizer + else: + sizer = self._hsizer + return sizer + + def ChangeWindow(self, window): + """Change the main window area, and return the current window + @param window: Any window/panel like object + @return: the old window or None + + """ + rwindow = None + if self.GetWindow() is None or not isinstance(self._main, wx.Window): + del self._main + topb = self.GetControlBar(wx.TOP) + if topb is None: + self._vsizer.Add(window, 1, wx.EXPAND) + else: + self._vsizer.Insert(1, window, 1, wx.EXPAND) + else: + self._vsizer.Replace(self._main, window) + rwindow = self._main + + self._main = window + return rwindow + + def CreateControlBar(self, pos=wx.TOP): + """Create a ControlBar at the given position if one does not + already exist. + @keyword pos: wx.TOP (default), BOTTOM, LEFT, RIGHT + @postcondition: A top aligned L{ControlBar} is created. + @return: ControlBar + + """ + cbar = self.GetControlBar(pos) + if cbar is None: + style=CTRLBAR_STYLE_GRADIENT + if pos in (wx.LEFT, wx.RIGHT): + style |= CTRLBAR_STYLE_VERTICAL + cbar = ControlBar(self, style=style) + self.SetControlBar(cbar, pos) + return cbar + + def GetControlBar(self, pos=wx.TOP): + """Get the L{ControlBar} used by this window + @param pos: wx.TOP, BOTTOM, LEFT, RIGHT + @return: ControlBar or None + + """ + assert pos in (wx.TOP, wx.LEFT, wx.BOTTOM, wx.RIGHT) + cbar = self._cbars.get(pos, None) + return cbar + + def GetWindow(self): + """Get the main display window + @return: Window or None + + """ + return self._main + + def ReplaceControlBar(self, ctrlbar, pos=wx.TOP): + """Replace the L{ControlBar} at the given position + with the given ctrlbar and return the bar that was + replaced or None. + @param ctrlbar: L{ControlBar} + @keyword pos: Position + @return: L{ControlBar} or None + + """ + assert isinstance(ctrlbar, ControlBar) + assert pos in (wx.TOP, wx.BOTTOM, wx.LEFT, wx.RIGHT) + tbar = self.GetControlBar(pos) + rbar = None + sizer = self._GetCtrlBarSizer(pos) + if tbar is None and pos in (wx.TOP, wx.LEFT): + sizer.Insert(0, ctrlbar, 0, wx.EXPAND) + elif tbar is None and pos in (wx.BOTTOM, wx.RIGHT): + sizer.Add(ctrlbar, 0, wx.EXPAND) + else: + sizer.Replace(tbar, ctrlbar) + rbar = tbar + + self._cbars[pos] = ctrlbar + + return rbar + + def SetControlBar(self, ctrlbar, pos=wx.TOP): + """Set the ControlBar used by this ControlBox + @param ctrlbar: L{ControlBar} + @keyword pos: wx.TOP/wx.BOTTOM/wx.LEFT/wx.RIGHT + + """ + assert isinstance(ctrlbar, ControlBar) + assert pos in (wx.TOP, wx.BOTTOM, wx.LEFT, wx.RIGHT) + tbar = self.GetControlBar(pos) + if tbar is ctrlbar: + return # ignore setting same bar again + sizer = self._GetCtrlBarSizer(pos) + if tbar is None and pos in (wx.TOP, wx.LEFT): + sizer.Insert(0, ctrlbar, 0, wx.EXPAND) + elif tbar is None and pos in (wx.BOTTOM, wx.RIGHT): + sizer.Add(ctrlbar, 0, wx.EXPAND) + else: + sizer.Replace(tbar, ctrlbar) + + try: + tbar.Destroy() + except wx.PyDeadObjectError: + pass + + self._cbars[pos] = ctrlbar + + def SetWindow(self, window): + """Set the main window control portion of the box. This will be the + main central item shown in the box + @param window: Any window/panel like object + + """ + if self.GetWindow() is None: + topb = self.GetControlBar(wx.TOP) + botb = self.GetControlBar(wx.BOTTOM) + if (topb and botb is None) or (topb is None and botb is None): + self._vsizer.Add(window, 1, wx.EXPAND) + elif botb and topb is None: + self._vsizer.Insert(0, window, 1, wx.EXPAND) + else: + self._vsizer.Insert(1, window, 1, wx.EXPAND) + else: + self._vsizer.Replace(self._main, window) + + try: + self._main.Destroy() + except wx.PyDeadObjectError: + pass + + self._main = window + +#--------------------------------------------------------------------------# + +class ControlBar(wx.PyPanel): + """Toolbar like control container for use with a L{ControlBox}. It + uses a panel with a managed sizer as a convenient way to add a small + bar with various controls in it to any window. + + """ + def __init__(self, parent, id=wx.ID_ANY, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=CTRLBAR_STYLE_DEFAULT, + name=CTRLBAR_NAME_STR): + super(ControlBar, self).__init__(parent, id, pos, size, + wx.TAB_TRAVERSAL|wx.NO_BORDER, name) + + tsz_orient = wx.HORIZONTAL + msz_orient = wx.VERTICAL + if style & CTRLBAR_STYLE_VERTICAL: + tsz_orient = wx.VERTICAL + msz_orient = wx.HORIZONTAL + + # Attributes + self._style = style + self._sizer = wx.BoxSizer(tsz_orient) + self._tools = dict(simple=list()) + self._spacing = (5, 5) + + # Drawing related + color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) + if wx.Platform != '__WXMAC__': + self._color2 = AdjustColour(color, 15) + self._color = AdjustColour(color, -10) + else: + self._color2 = AdjustColour(color, 15) + self._color = AdjustColour(color, -20) + + pcolor = tuple([min(190, x) for x in AdjustColour(self._color, -25)]) + self._pen = wx.Pen(pcolor, 1) + + # Setup + msizer = wx.BoxSizer(msz_orient) + spacer = (0, 0) + msizer.Add(spacer, 0) + msizer.Add(self._sizer, 1, wx.EXPAND) + msizer.Add(spacer, 0) + self.SetSizer(msizer) + + # Event Handlers + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_BUTTON, self._DispatchEvent) + + def _DispatchEvent(self, evt): + """Translate the button events generated by the controls added by + L{AddTool} to L{ControlBarEvent}'s. + + """ + e_id = evt.GetId() + if e_id in self._tools['simple']: + cb_evt = ControlBarEvent(edEVT_CTRLBAR, e_id) + self.GetEventHandler().ProcessEvent(cb_evt) + else: + # Allow to propagate + evt.Skip() + + def _GetAlignment(self): + """Verify and get the proper secondary alignment based on the + control bar alignment. + + """ + if not self.IsVerticalMode(): + align2 = wx.ALIGN_CENTER_VERTICAL + else: + align2 = wx.ALIGN_CENTER_HORIZONTAL + return align2 + + def AddControl(self, control, align=-1, stretch=0): + """Add a control to the bar + @param control: The control to add to the bar + @keyword align: wx.ALIGN_** + @keyword stretch: The controls proportions 0 for normal, 1 for expand + + """ + if wx.Platform == '__WXMAC__': + if hasattr(control, 'SetWindowVariant'): + control.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + + # Default to proper alignment when -1 specified + if align not in (wx.ALIGN_LEFT, wx.ALIGN_RIGHT, + wx.ALIGN_BOTTOM, wx.ALIGN_TOP): + if self.IsVerticalMode(): + align = wx.ALIGN_TOP + else: + align = wx.ALIGN_LEFT + + align2 = self._GetAlignment() + if align in (wx.ALIGN_LEFT, wx.ALIGN_TOP): + self._sizer.Add(self._spacing, 0) + self._sizer.Add(control, stretch, align|align2) + else: + self._sizer.Add(control, stretch, align|align2) + self._sizer.Add(self._spacing, 0) + + self.Layout() + + def AddSpacer(self, width, height): + """Add a fixed size spacer to the control bar + @param width: width of the spacer + @param height: height of the spacer + + """ + self._sizer.Add((width, height), 0) + + def AddStretchSpacer(self): + """Add an expanding spacer to the bar that will stretch and + contract when the window changes size. + + """ + self._sizer.AddStretchSpacer(2) + + def AddTool(self, tid, bmp, help=u'', align=-1): + """Add a simple bitmap button tool to the control bar + @param tid: Tool Id + @param bmp: Tool bitmap + @keyword help: Short help string + @keyword align: wx.ALIGN_** + + """ + tool = wx.BitmapButton(self, tid, bmp, style=wx.NO_BORDER) + if wx.Platform == '__WXGTK__': + # SetMargins not available in wxPython 2.9+ + getattr(tool, 'SetMargins', lambda x,y: False)(0, 0) + spacer = (0, 0) + else: + spacer = self._spacing + tool.SetToolTipString(help) + + # Default to proper alignment when unknown is specified + if align not in (wx.ALIGN_LEFT, wx.ALIGN_RIGHT, + wx.ALIGN_BOTTOM, wx.ALIGN_TOP): + if self.IsVerticalMode(): + align = wx.ALIGN_TOP + else: + align = wx.ALIGN_LEFT + + align2 = self._GetAlignment() + self._tools['simple'].append(tool.GetId()) + if align in (wx.ALIGN_TOP, wx.ALIGN_LEFT): + self._sizer.Add(spacer, 0) + self._sizer.Add(tool, 0, align|align2) + else: + self._sizer.Add(spacer, 0) + self._sizer.Add(tool, 0, align|align2) + + def GetControlSizer(self): + """Get the sizer that is used to layout the contols (horizontal sizer) + @return: wx.BoxSizer + + """ + return self._sizer + + def GetControlSpacing(self): + """Get the spacing used between controls + @return: size tuple + + """ + return self._spacing + + def IsVerticalMode(self): + """Is the ControlBar in vertical orientation + @return: bool + + """ + return self._style & CTRLBAR_STYLE_VERTICAL + + def DoPaintBackground(self, dc, rect, color, color2): + """Paint the background of the given rect based on the style of + the control bar. + @param dc: DC to draw on + @param rect: wx.Rect + @param color: Pen/Base gradient color + @param color2: Gradient end color + + """ + # Paint the gradient + if self._style & CTRLBAR_STYLE_GRADIENT: + if isinstance(dc, wx.GCDC): + gc = dc.GetGraphicsContext() + else: + gc = wx.GraphicsContext.Create(dc) + + if gc is None: + return + + if not self.IsVerticalMode(): + grad = gc.CreateLinearGradientBrush(rect.x, rect.y, rect.x, + rect.x+rect.height, + color2, color) + else: + grad = gc.CreateLinearGradientBrush(rect.x, rect.y, + rect.x+rect.width, + rect.y, + color2, color) + + gc.SetPen(gc.CreatePen(self._pen)) + gc.SetBrush(grad) + gc.DrawRectangle(rect.x, rect.y, rect.Width - 0.5, rect.Height - 0.5) + + dc.SetPen(wx.Pen(color, 1)) + + # TODO: handle vertical mode + if not self.IsVerticalMode(): + # Add a border to the bottom + if self._style & CTRLBAR_STYLE_BORDER_BOTTOM: + dc.DrawLine(rect.x, rect.GetHeight() - 1, + rect.GetWidth(), rect.GetHeight() - 1) + + # Add a border to the top + if self._style & CTRLBAR_STYLE_BORDER_TOP: + dc.DrawLine(rect.x, 1, rect.GetWidth(), 1) + + def OnPaint(self, evt): + """Paint the background to match the current style + @param evt: wx.PaintEvent + + """ + dc = wx.AutoBufferedPaintDCFactory(self) + gc = wx.GCDC(dc) + rect = self.GetClientRect() + + self.DoPaintBackground(gc, rect, self._color, self._color2) + + evt.Skip() + + def SetToolSpacing(self, px): + """Set the spacing to use between tools/controls. + @param px: int (number of pixels) + @todo: dynamically update existing layouts + + """ + self._spacing = (px, px) + + def SetVMargin(self, top, bottom): + """WARNING this method is Deprecated use SetMargins instead!! + @param top: Top margin in pixels + @param bottom: Bottom margin in pixels + + """ + # TODO: Remove all usage of this method + self.SetMargins(top, bottom) + + def SetMargins(self, param1, param2): + """Setup the margins on the edges of the ControlBar + @param param1: left/top margin depending on orientation + @param param2: right/bottom margin depending on orientation + + """ + sizer = self.GetSizer() + if wx.VERSION < (2, 9, 0, 0, ''): + sizer.GetItem(0).SetSpacer((param1, param1)) + sizer.GetItem(2).SetSpacer((param2, param2)) + else: + sizer.GetItem(0).AssignSpacer((param1, param1)) + sizer.GetItem(2).AssignSpacer((param2, param2)) + sizer.Layout() + + def SetWindowStyle(self, style): + """Set the style flags of this window + @param style: long + + """ + if self.IsVerticalMode() and not (CTRLBAR_STYLE_VERTICAL & style): + # Switching from vertical to HORIZONTAL + self._sizer.SetOrientation(wx.HORIZONTAL) + elif not self.IsVerticalMode() and (CTRLBAR_STYLE_VERTICAL & style): + # Switching from horizontal to vertical + self._sizer.SetOrientation(wx.VERTICAL) + self._style = style + self.Layout() + self.Refresh() + +#--------------------------------------------------------------------------# + +class _SegmentButton(object): + """Class for managing segment button data""" + def __init__(self, id_, bmp, label, lbl_size): + super(_SegmentButton, self).__init__() + + # Attributes + self._id = id_ + self._bmp = bmp + self._lbl = label + self._lbl_size = lbl_size + self._rect = wx.Rect() + self._bx1 = 0 + self._bx2 = 0 + self._opts = 0 + self._selected = False + self._x_button = wx.Rect() + self._x_state = SEGMENT_STATE_NONE + + Id = property(lambda self: self._id, + lambda self, id_: setattr(self, '_id', id_)) + Bitmap = property(lambda self: self._bmp, + lambda self, bmp: setattr(self, '_bmp', bmp)) + Label = property(lambda self: self._lbl, + lambda self, label: setattr(self, '_lbl', label)) + LabelSize = property(lambda self: self._lbl_size, + lambda self, size: setattr(self, '_lbl_size', size)) + Rect = property(lambda self: self._rect, + lambda self, rect: setattr(self, '_rect', rect)) + Selected = property(lambda self: self._selected, + lambda self, sel: setattr(self, '_selected', sel)) + XState = property(lambda self: self._x_state, + lambda self, state: setattr(self, '_x_state', state)) + XButton = property(lambda self: self._x_button, + lambda self, rect: setattr(self, '_x_button', rect)) + BX1 = property(lambda self: self._bx1, + lambda self, x1: setattr(self, '_bx1', x1)) + BX2 = property(lambda self: self._bx2, + lambda self, x2: setattr(self, '_bx2', x2)) + Options = property(lambda self: self._opts, + lambda self, opt: setattr(self, '_opts', opt)) + +class SegmentBar(ControlBar): + """Simple toolbar like control that displays bitmaps and optionally + labels below each bitmap. The bitmaps are turned into a toggle button + where only one segment in the bar can be selected at one time. + + """ + HPAD = 5 + VPAD = 3 + def __init__(self, parent, id=wx.ID_ANY, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=CTRLBAR_STYLE_DEFAULT, + name=SEGBAR_NAME_STR): + super(SegmentBar, self).__init__(parent, id, pos, size, style, name) + + # Attributes + self._buttons = list() # list of _SegmentButtons + self._segsize = (0, 0) + self._selected = -1 + self._scolor1 = AdjustColour(self._color, -20) + self._scolor2 = AdjustColour(self._color2, -20) + self._spen = wx.Pen(AdjustColour(self._pen.GetColour(), -25)) + self._x_clicked_before = False + self._tip_timer = wx.Timer(self) + + if wx.Platform == '__WXMAC__': + self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + + # Event Handlers + self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter) + self.Bind(wx.EVT_ENTER_WINDOW, self.OnLeave) + self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_MOTION, self.OnMouseMove) + self.Bind(wx.EVT_TIMER, self.OnTipTimer, self._tip_timer) + self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) + + def _RestartTimer(self): + """Reset the tip timer for showing tooltips when + the segments have their labels hidden. + + """ + if not (self._style & CTRLBAR_STYLE_LABELS): + if self._tip_timer.IsRunning(): + self._tip_timer.Stop() + self._tip_timer.Start(1000, True) + + def OnDestroy(self, evt): + """Cleanup on Destroy""" + if evt.GetEventObject() is self: + if self._tip_timer.IsRunning(): + self._tip_timer.Stop() + evt.Skip() + + def AddSegment(self, id, bmp, label=u''): + """Add a segment to the bar + @param id: button id + @param bmp: wx.Bitmap + @param label: string + + """ + assert bmp.IsOk() + lsize = self.GetTextExtent(label) + segment = _SegmentButton(id, bmp, label, lsize) + self._buttons.append(segment) + self.InvalidateBestSize() + self.Refresh() + + def DoDrawButton(self, dc, pos, bidx, selected=False, draw_label=False): + """Draw a button + @param dc: DC to draw on + @param pos: X coordinate (horizontal mode) / Y coordinate (vertical mode) + @param bidx: button dict + @keyword selected: is this the selected button (bool) + @keyword draw_label: draw the label (bool) + return: int (next xpos) + + """ + button = self._buttons[bidx] + height = self.Rect.height + bVertical = self.IsVerticalMode() + + # Draw the background of the button + if not bVertical: + rside = pos + self._segsize[0] + brect = wx.Rect(pos, 0, rside - pos, height) + else: + rside = pos + self._segsize[1] + brect = wx.Rect(0, pos, self.Rect.Width, rside - pos) + + button.Rect = brect + if selected: + self.DoPaintBackground(dc, brect, self._scolor1, self._scolor2) + + # Draw the bitmap + bmp = button.Bitmap + bsize = button.Bitmap.Size + if not bVertical: + bxpos = ((self._segsize[0] / 2) - (bsize.width / 2)) + pos + bpos = (bxpos, SegmentBar.VPAD) + else: + bxpos = ((self._segsize[0] / 2) - (bsize.width / 2)) + bpos = (bxpos, pos + SegmentBar.VPAD) + dc.DrawBitmap(bmp, bpos[0], bpos[1], bmp.Mask != None) + + if draw_label: + lcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) + dc.SetTextForeground(lcolor) + twidth, theight = button.LabelSize + if not bVertical: + lxpos = pos + typos = height - theight - 2 + else: + lxpos = 0 + typos = pos + (self._segsize[1] - theight - 2) + trect = wx.Rect(lxpos, typos, self._segsize[0], theight + 3) + dc.DrawLabel(button.Label, trect, wx.ALIGN_CENTER) + + if not selected: + if not (self._style & CTRLBAR_STYLE_NO_DIVIDERS): + dc.SetPen(self._pen) + if not bVertical: + dc.DrawLine(pos, 0, pos, height) + dc.DrawLine(rside, 0, rside, height) + else: + dc.DrawLine(0, pos, self.Rect.Width, pos) + dc.DrawLine(0, rside, self.Rect.Width, rside) + else: + dc.SetPen(self._spen) + tmpx = pos + 1 + trside = rside - 1 + if not bVertical: + dc.DrawLine(tmpx, 0, tmpx, height) + dc.DrawLine(trside, 0, trside, height) + else: + dc.DrawLine(0, tmpx, self.Rect.Width, tmpx) + dc.DrawLine(0, trside, self.Rect.Width, trside) + + tpen = wx.Pen(self._spen.Colour) + tpen.SetJoin(wx.JOIN_BEVEL) + if not bVertical: + mpoint = height / 2 + dc.DrawLine(tmpx + 1, mpoint, tmpx, 0) + dc.DrawLine(tmpx + 1, mpoint, tmpx, height) + dc.DrawLine(trside - 1, mpoint, trside, 0) + dc.DrawLine(trside - 1, mpoint, trside, height) + else: + mpoint = self.Rect.Width / 2 + dc.DrawLine(mpoint, tmpx + 1, 0, tmpx) + dc.DrawLine(mpoint, tmpx + 1, self.Rect.Width, tmpx) + dc.DrawLine(mpoint, trside - 1, 0, trside) + dc.DrawLine(mpoint, trside - 1, self.Rect.Width, trside) + + # Update derived button data + button.BX1 = pos + 1 + button.BX2 = rside - 1 + button.Selected = selected + + # Draw delete button if button has one + if self.SegmentHasCloseButton(bidx): + if not bVertical: + brect = wx.Rect(button.BX1, 0, button.BX2 - (pos - 1), height) + else: + brect = wx.Rect(0, button.BX1, self.Rect.Width, + button.BX2 - (pos - 1)) + self.DoDrawCloseBtn(dc, button, brect) + return rside # right/bottom of button just drawn + + def DoDrawCloseBtn(self, gcdc, button, rect): + """Draw the close button on the segment + @param gcdc: Device Context + @param button: Segment Dict + @param rect: Segment Rect + + """ + if button.Options & SEGBTN_OPT_CLOSEBTNL: + x = rect.x + 8 + y = rect.y + 6 + else: + x = (rect.x + rect.Width) - 8 + y = rect.y + 6 + + color = self._scolor2 + if button.Selected: + color = AdjustColour(color, -25) + + if button.XState == SEGMENT_STATE_X: + color = AdjustColour(color, -20) + + gcdc.SetPen(wx.Pen(AdjustColour(color, -30))) + + brect = wx.Rect(x-3, y-3, 8, 8) + bmp = DrawCircleCloseBmp(color, wx.WHITE) + gcdc.DrawBitmap(bmp, brect.x, brect.y) + button.XButton = brect + return + + # Square style button +# gcdc.DrawRectangleRect(brect) +# gcdc.SetPen(wx.BLACK_PEN) +# gcdc.DrawLine(brect.x+1, brect.y+1, +# brect.x + brect.GetWidth() - 1, brect.y + brect.GetHeight() - 1) +# gcdc.DrawLine(brect.x + brect.GetWidth() - 1, brect.y + 1, +# brect.x + 1, brect.y + brect.GetHeight() - 1) +# gcdc.SetBrush(brush) +# gcdc.SetPen(pen) +# button['xbtn'] = brect + + def DoGetBestSize(self): + """Get the best size for the control""" + mwidth, mheight = 0, 0 + draw_label = self._style & CTRLBAR_STYLE_LABELS + for btn in self._buttons: + bwidth, bheight = btn.Bitmap.Size + twidth = btn.LabelSize[0] + if bheight > mheight: + mheight = bheight + + if bwidth > mwidth: + mwidth = bwidth + + if draw_label: + if twidth > mwidth: + mwidth = twidth + + # Adjust for label text + if draw_label and len(self._buttons): + mheight += self._buttons[0].LabelSize[1] + + if self.IsVerticalMode(): + height = (mheight + (SegmentBar.VPAD * 2) * len(self._buttons)) + width = mwidth + else: + width = (mwidth + (SegmentBar.HPAD * 2)) * len(self._buttons) + height = mheight + + size = wx.Size(width + (SegmentBar.HPAD * 2), + height + (SegmentBar.VPAD * 2)) + self.CacheBestSize(size) + self._segsize = (mwidth + (SegmentBar.HPAD * 2), + mheight + (SegmentBar.VPAD * 2)) + return size + + def GetIndexFromPosition(self, pos): + """Get the segment index closest to the given position""" + if not self.IsVerticalMode(): + cur_x = pos[0] + else: + cur_x = pos[1] + for idx, button in enumerate(self._buttons): + xpos = button.BX1 + xpos2 = button.BX2 + if cur_x >= xpos and cur_x <= xpos2 + 1: + return idx + else: + return wx.NOT_FOUND + + def GetSegmentCount(self): + """Get the number segments in the control + @return: int + + """ + return len(self._buttons) + + def GetSegmentLabel(self, index): + """Get the label of the given segment + @param index: segment index + @return: string + + """ + return self._buttons[index].Label + + def GetSelection(self): + """Get the currently selected index""" + return self._selected + + def HitTest(self, pos): + """Find where the position is in the window + @param pos: (x, y) in client cords + @return: int + + """ + index = self.GetIndexFromPosition(pos) + where = SEGMENT_HT_NOWHERE + if index != wx.NOT_FOUND: + button = self._buttons[index] + if self.SegmentHasCloseButton(index): + brect = button.XButton + trect = wx.Rect(brect.x, brect.y, brect.Width+4, brect.Height+4) + if trect.Contains(pos): + where = SEGMENT_HT_X_BTN + else: + where = SEGMENT_HT_SEG + else: + where = SEGMENT_HT_SEG + + return where, index + + def OnEraseBackground(self, evt): + """Handle the erase background event""" + pass + + def OnLeftDown(self, evt): + """Handle clicks on the bar + @param evt: wx.MouseEvent + + """ + epos = evt.GetPosition() + index = self.GetIndexFromPosition(epos) + if index != wx.NOT_FOUND: + button = self._buttons[index] + pre = self._selected + self._selected = index + + if self._selected != pre: + self.Refresh() + sevt = SegmentBarEvent(edEVT_SEGMENT_SELECTED, button.Id) + sevt.SetSelections(pre, index) + sevt.SetEventObject(self) + self.GetEventHandler().ProcessEvent(sevt) + + self._x_clicked_before = False + + # Check for click on close btn + if self.SegmentHasCloseButton(index): + if self.HitTest(epos)[0] == SEGMENT_HT_X_BTN: + self._x_clicked_before = True + + evt.Skip() + + def OnLeftUp(self, evt): + """Handle clicks on the bar + @param evt: wx.MouseEvent + + """ + epos = evt.GetPosition() + where, index = self.HitTest(epos) + + # Check for click on close btn + if self.SegmentHasCloseButton(index) and self._x_clicked_before: + if where == SEGMENT_HT_X_BTN: + event = SegmentBarEvent(edEVT_SEGMENT_CLOSE, self.GetId()) + event.SetSelections(index, index) + event.SetEventObject(self) + self.GetEventHandler().ProcessEvent(event) + if not event.IsAllowed(): + return False + removed = self.RemoveSegment(index) + + evt.Skip() + + def OnEnter(self, evt): + """Mouse has entered the SegmentBar, update state info""" + evt.Skip() + + def OnLeave(self, evt): + """Mouse has left the SegmentBar, update state info""" + if self._tip_timer.IsRunning(): + self._tip_timer.Stop() + evt.Skip() + + def OnMouseMove(self, evt): + """Handle when the mouse moves over the bar""" + epos = evt.GetPosition() + where, index = self.HitTest(epos) + if index == -1: + return + if not self.SegmentHasCloseButton(index): + self._RestartTimer() + return + + # Update button state + button = self._buttons[index] + x_state = button.XState + button.XState = SEGMENT_STATE_NONE + + if where != SEGMENT_HT_NOWHERE: + if where == SEGMENT_HT_X_BTN: + button.XState = SEGMENT_STATE_X + elif where == SEGMENT_HT_SEG: + # TODO: add highlight option for hover on segment + pass + else: + self._RestartTimer() + evt.Skip() + return + + # If the hover state over a segments close button + # has changed redraw the close button to reflect the + # proper state. + if button.XState != x_state: + crect = self.GetClientRect() + if not self.IsVerticalMode(): + brect = wx.Rect(button.BX1, 0, + button.BX2 - (button.BX1 - 2), + crect.Height) + else: + brect = wx.Rect(button.BX1, 0, + crect.Width, + button.BX2 - (button.BX1 - 2)) + self.Refresh(False, brect) + self._RestartTimer() + evt.Skip() + + def OnTipTimer(self, evt): + """Show the tooltip for the current SegmentButton""" + pos = self.ScreenToClient(wx.GetMousePosition()) + where, index = self.HitTest(pos) + if index != -1: + button = self._buttons[index] + if button.Label: + rect = button.Rect + x,y = self.ClientToScreenXY(rect.x, rect.y) + rect.x = x + rect.y = y + wx.TipWindow(self, button.Label, rectBound=rect) # Transient + + def OnPaint(self, evt): + """Paint the control""" + dc = wx.AutoBufferedPaintDCFactory(self) + gc = wx.GCDC(dc) + + # Setup + dc.SetBrush(wx.TRANSPARENT_BRUSH) + gc.SetBrush(wx.TRANSPARENT_BRUSH) + gc.SetFont(self.GetFont()) + gc.SetBackgroundMode(wx.TRANSPARENT) + gc.Clear() + + # Paint the background + rect = self.GetClientRect() + self.DoPaintBackground(gc, rect, self._color, self._color2) + + # Draw the buttons + # TODO: would be more efficient to just redraw the buttons that + # need redrawing. + npos = SegmentBar.HPAD + if self.IsVerticalMode(): + npos = SegmentBar.VPAD + use_labels = self._style & CTRLBAR_STYLE_LABELS + for idx, button in enumerate(self._buttons): + npos = self.DoDrawButton(gc, npos, idx, + self._selected == idx, + use_labels) + + def RemoveSegment(self, index): + """Remove a segment from the bar + @param index: int + @return: bool + + """ + button = self._buttons[index] + + # TODO: wxPython 2.8.9.2 this causes a crash... +# if button['bmp']: +# button['bmp'].Destroy() + del self._buttons[index] + + if self.GetSelection() == index: + count = self.GetSegmentCount() + if index >= count: + self.SetSelection(count-1) + + self.Refresh() + return True + + def SegmentHasCloseButton(self, index): + """Does the segment at index have a close button + @param index: int + + """ + button = self._buttons[index] + if button.Options & SEGBTN_OPT_CLOSEBTNL or \ + button.Options & SEGBTN_OPT_CLOSEBTNR: + return True + return False + + def SetSegmentImage(self, index, bmp): + """Set the image to use on the given segment + @param index: int + @param bmp: Bitmap + + """ + assert bmp.IsOk() + segment = self._buttons[index] + if segment.Bitmap.IsOk(): + segment.Bitmap.Destroy() + segment.Bitmap = None + segment.Bitmap = bmp + self.InvalidateBestSize() + self.Refresh() + + def SetSegmentLabel(self, index, label): + """Set the label for a given segment + @param index: segment index + @param label: string + + """ + segment = self._buttons[index] + lsize = self.GetTextExtent(label) + segment.Label = label + segment.LabelSize = lsize + self.InvalidateBestSize() + self.Refresh() + + def SetSegmentOption(self, index, option): + """Set an option on a given segment + @param index: segment index + @param option: option to set + + """ + button = self._buttons[index] + button.Options = button.Options|option + self.Refresh() + + def SetSelection(self, index): + """Set the selection + @param index: int + + """ + self._selected = index + self.Refresh() + +# Cleanup namespace +#del SegmentBar.__dict__['AddControl'] +#del SegmentBar.__dict__['AddSpacer'] +#del SegmentBar.__dict__['AddTool'] +#del SegmentBar.__dict__['SetToolSpacing'] +#del SegmentBar.__dict__['SetVMargin'] + +#--------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecbasewin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecbasewin.py new file mode 100644 index 0000000..cff2c23 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecbasewin.py @@ -0,0 +1,78 @@ +############################################################################### +# Name: ecbasewin.py # +# Purpose: Eclib Base Window Classes # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: Base Window Classes + + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ecbasewin.py 69410 2011-10-13 14:20:12Z CJP $" +__revision__ = "$Revision: 69410 $" + +__all__ = ["ECBaseDlg", "expose"] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +#-----------------------------------------------------------------------------# +# Decorators + +class expose(object): + """Expose a panels method to a to a specified class + The specified class must have a GetPanel method + + """ + def __init__(self, cls): + """@param cls: class to expose the method to""" + super(expose, self).__init__() + self.cls = cls + + def __call__(self, funct): + fname = funct.func_name + def parentmeth(*args, **kwargs): + self = args[0] + return getattr(self.GetPanel(), fname)(*args[1:], **kwargs) + parentmeth.__name__ = funct.__name__ + parentmeth.__doc__ = funct.__doc__ + setattr(self.cls, fname, parentmeth) + + return funct + +#-----------------------------------------------------------------------------# + +class ECBaseDlg(wx.Dialog): + """Editra Control Library Base Dialog Class""" + def __init__(self, parent, id=wx.ID_ANY, title=u"", + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_DIALOG_STYLE, name=u"ECBaseDialog"): + super(ECBaseDlg, self).__init__(parent, id, title, pos, + size, style, name) + + # Attributes + self._panel = None + + # Setup + self.SetSizer(wx.BoxSizer(wx.VERTICAL)) + + Panel = property(lambda self: self.GetPanel(), + lambda self, val: self.SetPanel(val)) + + def GetPanel(self): + """Get the dialogs main panel""" + return self._panel + + def SetPanel(self, panel): + """Set the dialogs main panel""" + assert isinstance(panel, wx.Panel) + if self._panel is not None: + self._panel.Destroy() + self._panel = panel + self.Sizer.Add(self._panel, 1, wx.EXPAND) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/eclutil.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/eclutil.py new file mode 100644 index 0000000..8c5f958 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/eclutil.py @@ -0,0 +1,221 @@ +############################################################################### +# Name: eclutil.py # +# Purpose: Common library utilities. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Control Library: Editra Control Library Utility + +Miscellaneous utility functions and gui helpers + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: eclutil.py 71178 2012-04-11 22:42:28Z CJP $" +__revision__ = "$Revision: 71178 $" + +__all__ = ['AdjustAlpha', 'AdjustColour', 'BestLabelColour', 'HexToRGB', + 'GetHighlightColour', 'EmptyBitmapRGBA', 'Freezer', + + 'DRAW_CIRCLE_SMALL', 'DRAW_CIRCLE_NORMAL', 'DRAW_CIRCLE_LARGE', + 'DrawCircleCloseBmp' ] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +if wx.Platform == '__WXMAC__': + try: + import Carbon.Appearance + except ImportError: + CARBON = False + else: + CARBON = True + +#-----------------------------------------------------------------------------# + +# DrawCircleCloseBmp options +DRAW_CIRCLE_SMALL = 0 +DRAW_CIRCLE_NORMAL = 1 +DRAW_CIRCLE_LARGE = 2 + +__CircleDefs = { DRAW_CIRCLE_SMALL : dict(size=(8, 8), + xpath=((1.75, 2), (4.75, 5), + (1.75, 5), (4.75, 2))), + DRAW_CIRCLE_NORMAL : dict(size=(16, 16), + xpath=((4.5, 4), (10.5, 10), + (4.5, 10), (10.5, 4))), + DRAW_CIRCLE_LARGE : dict(size=(32, 32), + xpath=((8, 8), (20, 20), + (8, 20), (20, 8))) } + +#-----------------------------------------------------------------------------# +# Colour Utilities + +def AdjustAlpha(colour, alpha): + """Adjust the alpha of a given colour""" + return wx.Colour(colour.Red(), colour.Green(), colour.Blue(), alpha) + +def AdjustColour(color, percent, alpha=wx.ALPHA_OPAQUE): + """ Brighten/Darken input colour by percent and adjust alpha + channel if needed. Returns the modified color. + @param color: color object to adjust + @param percent: percent to adjust +(brighten) or -(darken) + @keyword alpha: amount to adjust alpha channel + + """ + radj, gadj, badj = [ int(val * (abs(percent) / 100.0)) + for val in color.Get() ] + + if percent < 0: + radj, gadj, badj = [ val * -1 for val in [radj, gadj, badj] ] + else: + radj, gadj, badj = [ val or 255 for val in [radj, gadj, badj] ] + + red = min(color.Red() + radj, 255) + green = min(color.Green() + gadj, 255) + blue = min(color.Blue() + badj, 255) + return wx.Colour(red, green, blue, alpha) + +def BestLabelColour(color): + """Get the best color to use for the label that will be drawn on + top of the given color. + @param color: background color that text will be drawn on + + """ + avg = sum(color.Get()) // 3 + if avg > 128: + txt_color = wx.BLACK + else: + txt_color = wx.WHITE + return txt_color + +def GetHighlightColour(): + """Get the default highlight color + @return: wx.Colour + + """ + if wx.Platform == '__WXMAC__': + if CARBON: + if hasattr(wx, 'MacThemeColour'): + color = wx.MacThemeColour(Carbon.Appearance.kThemeBrushFocusHighlight) + return color + else: + # kThemeBrushButtonPressedLightHighlight + brush = wx.Brush(wx.BLACK) + brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight) + return brush.GetColour() + + # Fallback to text highlight color + return wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) + +def HexToRGB(hex_str): + """Returns a list of red/green/blue values from a + hex string. + @param hex_str: hex string to convert to rgb + + """ + hexval = hex_str + if hexval[0] == u"#": + hexval = hexval[1:] + ldiff = 6 - len(hexval) + hexval += ldiff * u"0" + # Convert hex values to integer + red = int(hexval[0:2], 16) + green = int(hexval[2:4], 16) + blue = int(hexval[4:], 16) + return [red, green, blue] + +#-----------------------------------------------------------------------------# + +def EmptyBitmapRGBA(width, height): + """Create an empty bitmap with an alpha channel""" + if hasattr(wx, 'EmptyBitmapRGBA'): + bmp = wx.EmptyBitmapRGBA(width, height, alpha=0) + else: + bmp = wx.EmptyBitmap(width, height, -1) + if hasattr(bmp, 'UseAlpha'): + bmp.UseAlpha() + return bmp + +#-----------------------------------------------------------------------------# + +class Freezer(object): + """Context manager for freezing window redraws""" + def __init__(self, window): + super(Freezer, self).__init__() + + # Attributes + self.window = window + + def __enter__(self): + if self.window: + self.window.Freeze() + + def __exit__( self, type, value, tb): + if self.window: + self.window.Thaw() + +#-----------------------------------------------------------------------------# +# Drawing helpers + +def DrawCircleCloseBmp(colour, backColour=None, option=DRAW_CIRCLE_SMALL): + """ + Draws a small circular close button. + @param colour: Circle's background colour + @keyword backColour: pen colour for border and X + @keyword option: DRAW_CIRCLE_* value + @return: wxBitmap + + """ + assert option in __CircleDefs, "Invalid DRAW option!" + + defs = __CircleDefs.get(option) + size = defs['size'] + if option != DRAW_CIRCLE_SMALL: + # Adjust for border + diameter = size[0] - 1 + else: + diameter = size[0] + radius = float(diameter) / 2.0 + xpath = defs['xpath'] + + bmp = EmptyBitmapRGBA(size[0], size[1]) + dc = wx.MemoryDC() + dc.SelectObject(bmp) + dc.Clear() + + gc = wx.GraphicsContext.Create(dc) + gc.SetBrush(wx.Brush(colour)) + if option > DRAW_CIRCLE_SMALL: + gc.SetPen(wx.Pen(AdjustColour(colour, -30))) + else: + gc.SetPen(wx.TRANSPARENT_PEN) + + path = gc.CreatePath() + path.AddCircle(radius, radius, radius) + path.CloseSubpath() + gc.FillPath(path) + gc.StrokePath(path) + + path = gc.CreatePath() + if backColour is not None: + pen = wx.Pen(backColour, 1) + else: + pen = wx.Pen("white", 1) + + pen.SetCap(wx.CAP_BUTT) + pen.SetJoin(wx.JOIN_BEVEL) + gc.SetPen(pen) + path.MoveToPoint(*xpath[0]) + path.AddLineToPoint(*xpath[1]) + path.MoveToPoint(*xpath[2]) + path.AddLineToPoint(*xpath[3]) + path.CloseSubpath() + gc.DrawPath(path) + + dc.SelectObject(wx.NullBitmap) + return bmp diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecpickers.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecpickers.py new file mode 100644 index 0000000..cc587fa --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/ecpickers.py @@ -0,0 +1,154 @@ +############################################################################### +# Name: ecpickers.py # +# Purpose: Custom picker controls # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: Editra Control Pickers + +Collection of various custom picker controls + +Class: PyFontPicker +Custom font picker control + +@summary: Various custom picker controls + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ecpickers.py 70230 2012-01-01 01:47:42Z CJP $" +__revision__ = "$Revision: 70230 $" + +__all__ = ['PyFontPicker', 'FontChangeEvent', + 'EVT_FONT_CHANGED', 'edEVT_FONT_CHANGED'] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +_ = wx.GetTranslation +#-----------------------------------------------------------------------------# + +edEVT_FONT_CHANGED = wx.NewEventType() +EVT_FONT_CHANGED = wx.PyEventBinder(edEVT_FONT_CHANGED, 1) +class FontChangeEvent(wx.PyCommandEvent): + """General notification event""" + def __init__(self, etype, eid, value=None, obj=None): + super(FontChangeEvent, self).__init__(etype, eid) + + # Attributes + self._value = value + + # Setup + self.SetEventObject(obj) + + def GetValue(self): + """Returns the value from the event. + @return: the value of this event + + """ + return self._value + +#-----------------------------------------------------------------------------# + +class PyFontPicker(wx.Panel): + """A slightly enhanced wx.FontPickerCtrl that displays the choosen font in + the label text using the choosen font as well as the font's size using + nicer formatting. + + """ + def __init__(self, parent, id_=wx.ID_ANY, default=wx.NullFont): + """Initializes the PyFontPicker + @param parent: Parent Window + @keyword id_: Control ID + @keyword default: The font to initialize as selected in the control + + """ + super(PyFontPicker, self).__init__(parent, id_, style=wx.NO_BORDER) + + # Attributes + if default == wx.NullFont: + self._font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) + else: + self._font = default + + self._text = wx.StaticText(self) + self._text.SetFont(default) + self._text.SetLabel(u"%s - %dpt" % (self._font.GetFaceName(), \ + self._font.GetPointSize())) + self._button = wx.Button(self, label=_("Set Font") + u'...') + + # Layout + vsizer = wx.BoxSizer(wx.VERTICAL) + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.AddStretchSpacer() + sizer.Add(self._text, 0, wx.ALIGN_CENTER_VERTICAL) + sizer.AddStretchSpacer() + sizer.Add(self._button, 0, wx.ALIGN_CENTER_VERTICAL) + vsizer.AddMany([((1, 1), 0), (sizer, 0, wx.EXPAND), ((1, 1), 0)]) + self.SetSizer(vsizer) + self.SetAutoLayout(True) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, lambda evt: self.ShowFontDlg(), self._button) + self.Bind(wx.EVT_FONTPICKER_CHANGED, self.OnChange) + + def GetFontValue(self): + """Gets the currently choosen font + @return: wx.Font + + """ + return self._font + + def GetTextCtrl(self): + """Gets the widgets text control + @return: wx.StaticText + + """ + return self._text + + def OnChange(self, evt): + """Updates the text control using our custom stylings after + the font is changed. + @param evt: The event that called this handler + + """ + font = evt.GetFont() + if font.IsNull(): + return + self._font = font + self._text.SetFont(self._font) + self._text.SetLabel(u"%s - %dpt" % (font.GetFaceName(), \ + font.GetPointSize())) + self.Layout() + evt = FontChangeEvent(edEVT_FONT_CHANGED, self.GetId(), self._font, self) + wx.PostEvent(self.GetParent(), evt) + + def SetButtonLabel(self, label): + """Sets the buttons label""" + self._button.SetLabel(label) + self._button.Refresh() + self.Layout() + + def SetToolTipString(self, tip): + """Sets the tooltip of the window + @param tip: string + + """ + self._text.SetToolTipString(tip) + self._button.SetToolTipString(tip) + wx.Panel.SetToolTipString(self, tip) + + def ShowFontDlg(self): + """Opens the FontDialog and processes the result""" + fdata = wx.FontData() + fdata.SetInitialFont(self._font) + fdlg = wx.FontDialog(self.GetParent(), fdata) + if fdlg.ShowModal() == wx.ID_OK: + fdata = fdlg.GetFontData() + wx.PostEvent(self, wx.FontPickerEvent(self, self.GetId(), + fdata.GetChosenFont())) + fdlg.Destroy() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistctrl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistctrl.py new file mode 100644 index 0000000..143e3fc --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistctrl.py @@ -0,0 +1,198 @@ +############################################################################### +# Name: elistctrl.py # +# Purpose: Base ListCtrl # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: EListCtrl + +Class EBaseListCtrl: +Base Report mode ListCtrl class that highlights alternate rows + +Class ECheckListCtrl: +Child class of L{EBaseListCtrl} that also provides CheckBoxes in the first +column of the control. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: elistctrl.py 72221 2012-07-28 15:28:31Z CJP $" +__revision__ = "$Revision: 72221 $" + +__all__ = ["EBaseListCtrl", "ECheckListCtrl", "EEditListCtrl", + "EToggleEditListCtrl"] + +#--------------------------------------------------------------------------# +# Dependencies +import wx +import wx.lib.mixins.listctrl as listmix + +# Local Imports +import elistmix + +#--------------------------------------------------------------------------# + +class EBaseListCtrl(elistmix.ListRowHighlighter, + listmix.ListCtrlAutoWidthMixin, + wx.ListCtrl): + """Base listctrl class that provides automatic row highlighting""" + def __init__(self, parent, _id=wx.ID_ANY, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.LC_REPORT, validator=wx.DefaultValidator, + name="EListCtrl"): + wx.ListCtrl.__init__(self, parent, _id, pos, size, + style, validator, name) + elistmix.ListRowHighlighter.__init__(self) + listmix.ListCtrlAutoWidthMixin.__init__(self) + + def EnableRow(self, idx, enable=True): + """Enable/Disable a row in the ListCtrl + @param idx: row index + @keyword enable: bool + + """ + state = 0 + txtcolour = wx.SYS_COLOUR_LISTBOXTEXT + if not enable: + state = wx.LIST_STATE_DISABLED + txtcolour = wx.SYS_COLOUR_GRAYTEXT + self.SetItemState(idx, state, wx.LIST_STATE_DONTCARE) + colour = wx.SystemSettings.GetColour(txtcolour) + self.SetItemTextColour(idx, colour) + + def GetRowData(self, idx): + """Get the values from each cell in the given row + @param idx: row index + @return: tuple + + """ + data = list() + if idx >= 0 and idx < self.GetItemCount(): + for col in range(self.GetColumnCount()): + item = self.GetItem(idx, col) + data.append(item.Text) + return tuple(data) + + def GetSelections(self): + """Get a list of all the selected items in the list + @return: list of ints + + """ + items = [ idx for idx in range(self.GetItemCount()) + if self.IsSelected(idx) ] + return items + + def HasSelection(self): + """Are any items selected in the list""" + return bool(len(self.GetSelections())) + +class ECheckListCtrl(listmix.CheckListCtrlMixin, + EBaseListCtrl): + """ListCtrl with CheckBoxes in the first column""" + def __init__(self, *args, **kwargs): + EBaseListCtrl.__init__(self, *args, **kwargs) + listmix.CheckListCtrlMixin.__init__(self) + +class EEditListCtrl(listmix.TextEditMixin, + EBaseListCtrl): + """ListCtrl with Editable cells""" + def __init__(self, *args, **kwargs): + EBaseListCtrl.__init__(self, *args, **kwargs) + listmix.TextEditMixin.__init__(self) + + def OpenEditor(self, col, row): + """Work around limitation of TextEditMixin on Linux + where if the horizontal scroll bar is present it is not + possible to open the editor. + @param col: column to open editor at + @param row: row to pen editor at + + """ + # give the derived class a chance to Allow/Veto this edit. + evt = wx.ListEvent(wx.wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, self.Id) + evt.m_itemIndex = row + evt.m_col = col + item = self.GetItem(row, col) + evt.m_item.SetId(item.GetId()) + evt.m_item.SetColumn(item.GetColumn()) + evt.m_item.SetData(item.GetData()) + evt.m_item.SetText(item.GetText()) + ret = self.GetEventHandler().ProcessEvent(evt) + if ret and not evt.IsAllowed(): + return # user code doesn't allow the edit. + + if self.GetColumn(col).m_format != self.col_style: + self.make_editor(self.GetColumn(col).m_format) + + x0 = self.col_locs[col] + x1 = self.col_locs[col+1] - x0 + + scrolloffset = self.GetScrollPos(wx.HORIZONTAL) + + # scroll forward + if wx.Platform == "__WXMSW__" and x0+x1-scrolloffset > self.GetSize()[0]: + # don't start scrolling unless we really need to + offset = x0+x1-self.GetSize()[0]-scrolloffset + # scroll a bit more than what is minimum required + # so we don't have to scroll everytime the user presses TAB + # which is very tireing to the eye + addoffset = self.GetSize()[0]/4 + # but be careful at the end of the list + if addoffset + scrolloffset < self.GetSize()[0]: + offset += addoffset + + self.ScrollList(offset, 0) + scrolloffset = self.GetScrollPos(wx.HORIZONTAL) + + y0 = self.GetItemRect(row)[1] + + editor = self.editor + editor.SetDimensions(x0-scrolloffset,y0, x1,-1) + + editor.SetValue(self.GetItem(row, col).GetText()) + editor.Show() + editor.Raise() + editor.SetSelection(-1,-1) + editor.SetFocus() + + self.curRow = row + self.curCol = col + +class EToggleEditListCtrl(listmix.CheckListCtrlMixin, + listmix.TextEditMixin, + EBaseListCtrl): + """ListCtrl with Editable cells and images that can be toggled in the + the first column. + + """ + def __init__(self, *args, **kwargs): + EBaseListCtrl.__init__(self, *args, **kwargs) + listmix.TextEditMixin.__init__(self) + listmix.CheckListCtrlMixin.__init__(self) + self.Unbind(wx.EVT_LEFT_DCLICK) + + def GetCheckedItems(self): + """Get the list of checked indexes""" + count = self.GetItemCount() + return [item for item in range(count) if self.IsChecked(item)] + + def SetCheckedBitmap(self, bmp): + """Set the bitmap to use for the Checked state + @param bmp: wx.Bitmap + + """ + assert isinstance(bmp, wx.Bitmap) and bmp.IsOk() + imgl = self.GetImageList(wx.IMAGE_LIST_SMALL) + imgl.Replace(self.check_image, bmp) + + def SetUnCheckedBitmap(self, bmp): + """Set the bitmap to use for the un-Checked state + @param bmp: wx.Bitmap + + """ + assert isinstance(bmp, wx.Bitmap) and bmp.IsOk() + imgl = self.GetImageList(wx.IMAGE_LIST_SMALL) + imgl.Replace(self.uncheck_image, bmp) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistmix.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistmix.py new file mode 100644 index 0000000..5f1eb85 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/elistmix.py @@ -0,0 +1,103 @@ +############################################################################### +# Name: elistmix.py # +# Purpose: Custom Mixins for a wxListCtrl # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: EListMixins + +Class ListRowHighlighter: +This mixin class can be used to add automatic highlighting of alternate rows +in a ListCtrl. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: elistmix.py 66204 2010-11-18 14:00:28Z CJP $" +__revision__ = "$Revision: 66204 $" + +__all__ = ["ListRowHighlighter", "HIGHLIGHT_EVEN", "HIGHLIGHT_ODD"] + +#--------------------------------------------------------------------------# +# Dependencies +import wx + +#--------------------------------------------------------------------------# +# Globals +HIGHLIGHT_ODD = 1 # Highlight the Odd rows +HIGHLIGHT_EVEN = 2 # Highlight the Even rows + +#--------------------------------------------------------------------------# + +class ListRowHighlighter: + """This mixin can be used to add automatic highlighting of alternate rows + in a list control. + + """ + def __init__(self, color=None, mode=HIGHLIGHT_EVEN): + """Initialize the highlighter + @keyword color: Set a custom highlight color (default uses system color) + @keyword mode: HIGHLIGHT_EVEN (default) or HIGHLIGHT_ODD + + """ + # Attributes + self._color = color + self._defaultb = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOX) + self._mode = mode + self._refresh_timer = wx.Timer(self) + + # Event Handlers + self.Bind(wx.EVT_LIST_INSERT_ITEM, lambda evt: self._RestartTimer()) + self.Bind(wx.EVT_LIST_DELETE_ITEM, lambda evt: self._RestartTimer()) + self.Bind(wx.EVT_TIMER, + lambda evt: self.RefreshRows(), + self._refresh_timer) + + def _RestartTimer(self): + if self._refresh_timer.IsRunning(): + self._refresh_timer.Stop() + self._refresh_timer.Start(100, oneShot=True) + + def RefreshRows(self): + """Re-color all the rows""" + for row in range(self.GetItemCount()): + if self._defaultb is None: + self._defaultb = self.GetItemBackgroundColour(row) + + if self._mode & HIGHLIGHT_EVEN: + dohlight = not row % 2 + else: + dohlight = row % 2 + + if dohlight: + if self._color is None: + if wx.Platform in ['__WXGTK__', '__WXMSW__']: + color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DLIGHT) + else: + color = wx.Colour(237, 243, 254) + else: + color = self._color + else: + color = self._defaultb + + self.SetItemBackgroundColour(row, color) + + def SetHighlightColor(self, color): + """Set the color used to highlight the rows. Call L{RefreshRows} after + this if you wish to update all the rows highlight colors. + @param color: wx.Colour or None to set default + + """ + self._color = color + + def SetHighlightMode(self, mode): + """Set the highlighting mode to either HIGHLIGHT_EVEN or to + HIGHLIGHT_ODD. Call L{RefreshRows} afterwards to update the list + state. + @param mode: HIGHLIGHT_* mode value + + """ + self._mode = mode diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/encdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/encdlg.py new file mode 100644 index 0000000..a738840 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/encdlg.py @@ -0,0 +1,97 @@ +############################################################################### +# Name: encdlg.py # +# Purpose: Encoding Dialog # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: Encoding Dialog + +A simple choice dialog for selecting a file encoding type from. The dialog +can work with either a passed in list of choices to display or by default will +list all encodings found on the system using their normalized names. + +@summary: Encoding choice dialog + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: encdlg.py 70230 2012-01-01 01:47:42Z CJP $" +__revision__ = "$Revision: 70230 $" + +__all__ = ['EncodingDialog', 'GetAllEncodings'] + +#--------------------------------------------------------------------------# +# Imports +import locale +import encodings +import wx + +# Editra Control Library Imports +import choicedlg + +#--------------------------------------------------------------------------# +# Globals +EncodingDialogNameStr = u"EncodingDialog" + +#--------------------------------------------------------------------------# + +class EncodingDialog(choicedlg.ChoiceDialog): + """Dialog for choosing an file encoding from the list of available + encodings on the system. + + """ + def __init__(self, parent, id=wx.ID_ANY, msg=u'', title=u'', + elist=list(), default=u'', + style=wx.CAPTION, pos=wx.DefaultPosition, + size=wx.DefaultSize, + name=EncodingDialogNameStr): + """Create the encoding dialog + @param parent: Parent Window + @keyword id: Dialog ID + @keyword msg: Dialog Message + @keyword title: Dialog Title + @keyword elist: list of encodings to use or None to use all + @keyword default: Default selected encoding + @keyword style: Dialog Style bitmask + @keyword pos: Dialog Postion + @keyword size: Dialog Size + @keyword name: Dialog Name + + """ + if not len(elist): + elist = GetAllEncodings() + + default = encodings.normalize_encoding(default) + if default and default.lower() in elist: + sel = default.lower() + else: + sel = locale.getpreferredencoding(False) + + super(EncodingDialog, self).__init__(parent, id, msg, title, + elist, sel, pos, size, style) + + def GetEncoding(self): + """Get the selected encoding + @return: string + + """ + return self.GetStringSelection() + +#--------------------------------------------------------------------------# +# Utilities + +def GetAllEncodings(): + """Get all encodings found on the system + @return: list of strings + + """ + elist = encodings.aliases.aliases.values() + elist = list(set(elist)) + elist.sort() + elist = [ enc for enc in elist if not enc.endswith('codec') ] + return elist + +#--------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/errdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/errdlg.py new file mode 100644 index 0000000..e4d78ca --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/errdlg.py @@ -0,0 +1,370 @@ +############################################################################### +# Name: errdlg.py # +# Purpose: Error Reporter Dialog # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: Error Reporter Dialog + +Dialog for displaying exceptions and reporting errors to application maintainer. +This dialog is intended as a base class and should be subclassed to fit the +applications needs. + +This dialog should be initiated inside of a sys.excepthook handler. + +Example: + +sys.excepthook = ExceptHook +... +def ExceptionHook(exctype, value, trace): + # Format the traceback + ftrace = ErrorDialog.FormatTrace(exctype, value, trace) + + # Ensure that error gets raised to console as well + print ftrace + + # If abort has been set and we get here again do a more forceful shutdown + if ErrorDialog.ABORT: + os._exit(1) + + # Prevent multiple reporter dialogs from opening at once + if not ErrorDialog.REPORTER_ACTIVE and not ErrorDialog.ABORT: + dlg = ErrorDialog(ftrace) + dlg.ShowModal() + dlg.Destroy() + +@summary: Error Reporter Dialog + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: errdlg.py 70230 2012-01-01 01:47:42Z CJP $" +__revision__ = "$Revision: 70230 $" + +__all__ = [# Classes + 'ErrorDialog', 'ErrorReporter', + # Functions + 'TimeStamp'] + +#----------------------------------------------------------------------------# +# Dependencies +import os +import sys +import platform +import time +import traceback +import wx + +# Local Imports +import ecbasewin + +#----------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation + +#----------------------------------------------------------------------------# + +class ErrorReporter(object): + """Crash/Error Reporter Service + @summary: Stores all errors caught during the current session. + @note: singleton class + + """ + instance = None + _first = True + def __init__(self): + """Initialize the reporter + @note: The ErrorReporter is a singleton. + + """ + # Ensure init only happens once + if self._first: + super(ErrorReporter, self).__init__() + self._first = False + self._sessionerr = list() + else: + pass + + def __new__(cls, *args, **kargs): + """Maintain only a single instance of this object + @return: instance of this class + + """ + if not cls.instance: + cls.instance = object.__new__(cls, *args, **kargs) + return cls.instance + + def AddMessage(self, msg): + """Adds a message to the reporters list of session errors + @param msg: The Error Message to save + + """ + if msg not in self._sessionerr: + self._sessionerr.append(msg) + + def GetErrorStack(self): + """Returns all the errors caught during this session + @return: formatted log message of errors + + """ + return (os.linesep * 2).join(self._sessionerr) + + def GetLastError(self): + """Gets the last error from the current session + @return: Error Message String + + """ + if len(self._sessionerr): + return self._sessionerr[-1] + +#-----------------------------------------------------------------------------# + +class ErrorDialog(ecbasewin.ECBaseDlg): + """Dialog for showing errors and and notifying Editra.org should the + user choose so. + + """ + ID_SEND = wx.NewId() + ABORT = False + REPORTER_ACTIVE = False + def __init__(self, parent, id=wx.ID_ANY, title=u'', + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, + name="ErrorReporterDlg", message=u''): + """Initialize the dialog + @param parent: Parent Window + @keyword id: Dialog ID + @keyword title: Dialog Title + @keyword pos: Dialog Postion + @keyword size: Dialog Size + @keyword style: Dialog Style bitmask + @keyword name: Dialog Name + @param message: Error message to display + + """ + ErrorDialog.REPORTER_ACTIVE = True + super(ErrorDialog, self).__init__(parent, id, title, pos, + size, style, name) + + # Give message to ErrorReporter + ErrorReporter().AddMessage(message) + + # Attributes + self.err_msg = os.linesep.join((self.GetEnvironmentInfo(), + "#---- Traceback Info ----#", + ErrorReporter().GetErrorStack(), + "#---- End Traceback Info ----#")) + + # Layout + self.SetPanel(ErrorPanel(self, self.err_msg)) + self.SetMinSize(wx.Size(450, 300)) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_CLOSE, self.OnClose) + + # Auto show at end of init + self.CenterOnParent() + + #---- Override in Subclass ----# + + def Abort(self): + """Called to abort the application + @note: needs to be overridden in subclasses + + """ + raise NotImplementedError("Abort must be implemented!") + + def GetEnvironmentInfo(self): + """Get the environmental info / Header of error report + @return: string + + """ + info = list() + info.append("#---- Notes ----#") + info.append("Please provide additional information about the crash here") + info.extend(["", ""]) + info.append("#---- System Information ----#") + info.append(self.GetProgramName()) + info.append("Operating System: %s" % wx.GetOsDescription()) + if sys.platform == 'darwin': + info.append("Mac OSX: %s" % platform.mac_ver()[0]) + info.append("Python Version: %s" % sys.version) + info.append("wxPython Version: %s" % wx.version()) + info.append("wxPython Info: (%s)" % ", ".join(wx.PlatformInfo)) + info.append("Python Encoding: Default=%s File=%s" % \ + (sys.getdefaultencoding(), sys.getfilesystemencoding())) + info.append("wxPython Encoding: %s" % wx.GetDefaultPyEncoding()) + info.append("System Architecture: %s %s" % (platform.architecture()[0], \ + platform.machine())) + info.append("Byte order: %s" % sys.byteorder) + info.append("Frozen: %s" % str(getattr(sys, 'frozen', 'False'))) + info.append("#---- End System Information ----#") + info.append("") + return os.linesep.join(info) + + def GetProgramName(self): + """Get the program name/version info to include in error report + @return: string + + """ + return wx.GetApp().GetAppName() + + def Send(self): + """Called to send error report + @note: needs to be overridden in subclasses + + """ + raise NotImplementedError("Send must be implemented!") + + #---- End Required overrides ----# + + @staticmethod + def FormatTrace(exctype, value, trace): + """Format the traceback + @return: string + + """ + exc = traceback.format_exception(exctype, value, trace) + exc.insert(0, u"*** %s ***%s" % (TimeStamp(), os.linesep)) + ftrace = u"".join(exc) + return ftrace + + def SetDescriptionLabel(self, label): + """Set the dialogs main description text + @param label: string + + """ + self._panel.SetDescriptionText(label) + + def ShowAbortButton(self, show=True): + """Show/Hide the Abort button + @keyword show: bool + + """ + btn = self._panel.FindWindowById(wx.ID_ABORT) + if btn is not None: + btn.Show(show) + self._panel.Layout() + + def ShowSendButton(self, show=True): + """Show/Hide the Send button + @keyword show: bool + + """ + btn = self._panel.FindWindowById(ErrorDialog.ID_SEND) + if btn is not None: + btn.Show(show) + self._panel.Layout() + + #---- Event Handlers ----# + + def OnButton(self, evt): + """Handles button events + @param evt: event that called this handler + @postcondition: Dialog is closed + @postcondition: If Report Event then email program is opened + + """ + e_id = evt.GetId() + if e_id == wx.ID_CLOSE: + self.Close() + elif e_id == ErrorDialog.ID_SEND: + self.Send() + self.Close() + elif e_id == wx.ID_ABORT: + ErrorDialog.ABORT = True + self.Abort() + self.Close() + else: + evt.Skip() + + def OnClose(self, evt): + """Cleans up the dialog when it is closed + @param evt: Event that called this handler + + """ + ErrorDialog.REPORTER_ACTIVE = False + evt.Skip() + +#-----------------------------------------------------------------------------# + +class ErrorPanel(wx.Panel): + """Error Reporter panel""" + def __init__(self, parent, msg): + """Create the panel + @param parent: wx.Window + @param msg: Error message to display + + """ + super(ErrorPanel, self).__init__(parent) + + # Attributes + self.err_msg = msg + self.desc = wx.StaticText(self, label=u'') + + # Layout + self.__DoLayout() + + def __DoLayout(self): + """Layout the control""" + icon = wx.StaticBitmap(self, + bitmap=wx.ArtProvider.GetBitmap(wx.ART_ERROR)) + t_lbl = wx.StaticText(self, label=_("Error Traceback:")) + tctrl = wx.TextCtrl(self, value=self.err_msg, style=wx.TE_MULTILINE | + wx.TE_READONLY) + + abort_b = wx.Button(self, wx.ID_ABORT, _("Abort")) + abort_b.SetToolTipString(_("Exit the application")) + send_b = wx.Button(self, ErrorDialog.ID_SEND, _("Report Error")) + send_b.SetDefault() + close_b = wx.Button(self, wx.ID_CLOSE) + + # Layout + vsizer = wx.BoxSizer(wx.VERTICAL) + + hsizer1 = wx.BoxSizer(wx.HORIZONTAL) + hsizer1.AddMany([((5, 5), 0), (icon, 0, wx.ALIGN_CENTER_VERTICAL), + ((12, 5), 0), (self.desc, 0, wx.EXPAND), ((5, 5), 0)]) + + hsizer2 = wx.BoxSizer(wx.HORIZONTAL) + hsizer2.AddMany([((5, 5), 0), (tctrl, 1, wx.EXPAND), ((5, 5), 0)]) + + bsizer = wx.BoxSizer(wx.HORIZONTAL) + bsizer.AddMany([((5, 5), 0), (abort_b, 0), ((-1, -1), 1, wx.EXPAND), + (send_b, 0), ((5, 5), 0), (close_b, 0), ((5, 5), 0)]) + + vsizer.AddMany([((5, 5), 0), + (hsizer1, 0), + ((10, 10), 0), + (t_lbl, 0, wx.ALIGN_LEFT|wx.LEFT, 5), + ((3, 3), 0), + (hsizer2, 1, wx.EXPAND), + ((8, 8), 0), + (bsizer, 0, wx.EXPAND), + ((8, 8), 0)]) + + self.SetSizer(vsizer) + self.SetAutoLayout(True) + + def SetDescriptionText(self, text): + """Set the description label text + @param text: string + + """ + self.desc.SetLabel(text) + self.Layout() + +#-----------------------------------------------------------------------------# + +def TimeStamp(): + """Create a formatted time stamp of current time + @return: Time stamp of the current time (Day Month Date HH:MM:SS Year) + + """ + now = time.localtime(time.time()) + now = time.asctime(now) + return now diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filemgrdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filemgrdlg.py new file mode 100644 index 0000000..1d8dda5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filemgrdlg.py @@ -0,0 +1,259 @@ +############################################################################### +# Name: filemgrdlg.py # +# Purpose: Simple File Management Dialog # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: FileMgrDialog + + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: filemgrdlg.py 63361 2010-02-03 04:03:45Z CJP $" +__revision__ = "$Revision: 63361 $" + +__all__ = ["FileMgrDialog", + "FMD_DEFAULT_STYLE", "FMD_NO_DELETE"] + +#-----------------------------------------------------------------------------# +# Imports +import os +import fnmatch +import wx +import wx.lib.mixins.listctrl as listmix + +# Eclib Imports +import ecbasewin +import elistmix + +#-----------------------------------------------------------------------------# +# Globals + +# Style Flags +FMD_DEFAULT_STYLE = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER +FMD_NO_DELETE = 1 + + +_ = wx.GetTranslation + +#-----------------------------------------------------------------------------# + +class FileMgrDialog(ecbasewin.ECBaseDlg): + def __init__(self, parent, id=wx.ID_ANY, title=u"", + defaultPath=os.curdir, defaultFile=u'', filter="*", + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=FMD_DEFAULT_STYLE, + name=u"FileMgrDialog"): + ecbasewin.ECBaseDlg.__init__(self, parent, id, title, + pos, size, style, name) + + # Attributes + + # Setup + panel = FileMgrPanel(self, defaultPath, defaultFile, filter) + self.SetPanel(panel) + panel.EnableDeleteOption(not (FMD_NO_DELETE & style)) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnSave, id=wx.ID_SAVE) + + def OnSave(self, evt): + """Exit the dialog""" + self.EndModal(wx.ID_OK) + +#-----------------------------------------------------------------------------# + +class FileMgrPanel(wx.Panel): + def __init__(self, parent, path, fname, filter): + wx.Panel.__init__(self, parent) + + # Attributes + self._entry = wx.TextCtrl(self) + self._flist = None + self._path = path + self._filter = filter + + # Setup + self.__DoLayout(fname) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnDelete, id=wx.ID_DELETE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_SAVE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=wx.ID_DELETE) + self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnFileSelected) + + def __DoLayout(self, fname): + """Layout the panel + @param fname: default filename + + """ + vsizer = wx.BoxSizer(wx.VERTICAL) + statbox = wx.StaticBox(self) + sbsizer = wx.StaticBoxSizer(statbox, wx.VERTICAL) + + # File List + self._flist = FileList(self) + self._flist.LoadFiles(self._path, self._filter) + sbsizer.Add(self._flist, 1, wx.EXPAND) + item = self._flist.FindItem(0, fname) + if item != wx.NOT_FOUND: + self._flist.Select(item) + + fbtnsz = wx.BoxSizer(wx.HORIZONTAL) + dbtn = wx.Button(self, wx.ID_DELETE) + if wx.Platform == '__WXMAC__': + dbtn.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + fbtnsz.AddStretchSpacer() + fbtnsz.Add(dbtn, 0, wx.ALIGN_RIGHT|wx.RIGHT, 5) + sbsizer.Add((5, 5), 0) + sbsizer.Add(fbtnsz, 0, wx.EXPAND) + + vsizer.Add((10, 10), 0) + vsizer.Add(sbsizer, 1, wx.EXPAND|wx.ALL, 5) + vsizer.Add((10, 10), 0) + + # File Name + hsizer = wx.BoxSizer(wx.HORIZONTAL) + sa_lbl = wx.StaticText(self, label=_("Save As")) + hsizer.AddMany([(sa_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), + (self._entry, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL)]) + self._entry.SetValue(fname) + vsizer.Add(hsizer, 0, wx.EXPAND|wx.ALL, 10) + vsizer.Add((10, 10), 0) + + # Buttons + save = wx.Button(self, wx.ID_SAVE) + cancel = wx.Button(self, wx.ID_CANCEL) + cancel.SetDefault() + bsizer = wx.StdDialogButtonSizer() + bsizer.AddButton(save) + bsizer.AddButton(cancel) + bsizer.Realize() + vsizer.Add(bsizer, 0, wx.EXPAND|wx.BOTTOM, 8) + + self.SetSizer(vsizer) + + def EnableDeleteOption(self, enable=True): + """Enable/Disable the Delete Option + @keyword enable: bool + + """ + del_btn = self.FindWindowById(wx.ID_DELETE) + del_btn.Show(enable) + self.Layout() + + @ecbasewin.expose(FileMgrDialog) + def GetSelectedFile(self): + """Get the selected filename + @return: string + + """ + item = self._flist.GetFocusedItem() + if item != -1: + item = self._flist.GetItem(item, 0) + fname = item.GetText() + return fname + return u"" + + def OnDelete(self, evt): + """Prompt to delete file the selected file""" + fname = self.GetSelectedFile() + if fname and os.path.exists(fname): + if wx.MessageBox(_("Are you sure want to delete %s?") % fname, + _("Delete File?"), + wx.ICON_WARNING|wx.OK|wx.CANCEL|wx.CENTER, + self) == wx.OK: + try: + os.remove(fname) + except OSError: + wx.MessageBox(_("Unable to delete %s") % fname, + _("Delete Error"), + wx.ICON_ERROR|wx.OK|wx.CENTER) + else: + # Refresh the list + self._flist.DeleteAllItems() + self._flist.LoadFiles(self._path, self._filter) + + def OnFileSelected(self, evt): + """Update the name in the save as field when a selection is made + in the list control. + + """ + fname = self.GetSelectedFile() + self._entry.SetValue(fname) + + def OnUpdateUI(self, evt): + """Enable/Disable the Save button depending on what is entered in the + filename dialog. + + """ + e_id = evt.GetId() + if e_id == wx.ID_SAVE: + evt.Enable(bool(self._entry.GetValue())) + elif e_id == wx.ID_DELETE: + evt.Enable(self._flist.GetFirstSelected() != -1) + +#-----------------------------------------------------------------------------# + +class FileList(wx.ListCtrl, + listmix.ListCtrlAutoWidthMixin, + elistmix.ListRowHighlighter): + def __init__(self, parent): + wx.ListCtrl.__init__(self, parent, + style=wx.LC_REPORT| + wx.LC_SORT_ASCENDING| + wx.LC_VRULES| + wx.LC_SINGLE_SEL) + listmix.ListCtrlAutoWidthMixin.__init__(self) + elistmix.ListRowHighlighter.__init__(self) + + # Attributes + + # Setup + self.InsertColumn(0, _("Files")) + il = wx.ImageList(16, 16) + self.imgidx = il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_MENU, (16, 16))) + self.AssignImageList(il, wx.IMAGE_LIST_SMALL) + self.setResizeColumn(0) + + def LoadFiles(self, path, wildcards="*"): + """Load all files from the given path + @param path: directory to list + @keyword wildcards: ; separated string of wildcard patterns + + """ + assert os.path.exists(path), "Invalid Path" + flist = list() + patterns = wildcards.split(';') + for fname in os.listdir(path): + for pattern in patterns: + if fnmatch.fnmatchcase(fname, pattern): + flist.append(fname) + break + flist.sort() + self.SetFiles(flist) + + def SetFiles(self, files): + """Set the files in the list + @param files: list of files + + """ + for idx, fname in enumerate(files): + self.Append((fname,)) + self.SetItemImage(self.GetItemCount() - 1, self.imgidx) + +#-----------------------------------------------------------------------------# + +if __name__ == '__main__': + app = wx.App(False) + frame = wx.Frame(None) + dlg = FileMgrDialog(frame, title="HELLO", defaultFile=u'eclutil.py', + style=FMD_DEFAULT_STYLE) + dlg.ShowModal() + frame.Destroy() + app.MainLoop() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filterdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filterdlg.py new file mode 100644 index 0000000..05a7ddf --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/filterdlg.py @@ -0,0 +1,179 @@ +############################################################################### +# Name: filterdlg.py # +# Purpose: Filter dialog # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: FilterDialog + + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: filterdlg.py 65202 2010-08-06 15:49:23Z CJP $" +__revision__ = "$Revision: 65202 $" + +__all__ = ["FilterDialog",] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +# Eclib Imports +import ecbasewin + +#-----------------------------------------------------------------------------# +# Globals + +_ = wx.GetTranslation + +#-----------------------------------------------------------------------------# + +class FilterDialog(ecbasewin.ECBaseDlg): + """Dialog that allows adding and removing items from a filter list""" + def __init__(self, parent, id=wx.ID_ANY, title=u"", + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_DIALOG_STYLE, name=u"FilterDialog"): + super(FilterDialog, self).__init__(parent, id, title, + pos, size, style, name) + + # Attributes + self.SetPanel(FilterPanel(self)) + + # Event Handlers + +#-----------------------------------------------------------------------------# + +class FilterPanel(wx.Panel): + """Filter dialog panel""" + def __init__(self, parent): + super(FilterPanel, self).__init__(parent) + + # Attributes + self._left = wx.ListBox(self, style=wx.LB_EXTENDED|wx.LB_SORT) + self._right = wx.ListBox(self, style=wx.LB_EXTENDED) + + self.__DoLayout() + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateButton, id=wx.ID_ADD) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateButton, id=wx.ID_REMOVE) + + def __DoLayout(self): + """Layout the panel""" + vsizer = wx.BoxSizer(wx.VERTICAL) + hsizer = wx.BoxSizer(wx.HORIZONTAL) + + hsizer.Add(self._left, 1, wx.EXPAND|wx.ALL, 10) + + # Add buttons + bvsizer = wx.BoxSizer(wx.VERTICAL) + addb = wx.Button(self, wx.ID_ADD, label=_("Add >>")) + removeb = wx.Button(self, wx.ID_REMOVE, label=_("<< Remove")) + bvsizer.AddStretchSpacer() + bvsizer.AddMany([(addb, 0, wx.EXPAND), + ((10, 15), 0), + (removeb, 0, wx.EXPAND)]) + bvsizer.AddStretchSpacer() + + hsizer.Add(bvsizer, 0, wx.ALIGN_CENTER) + hsizer.Add(self._right, 1, wx.EXPAND|wx.ALL, 10) + + vsizer.Add(hsizer, 1, wx.EXPAND) + + # Add main dialog buttons + bsizer = wx.StdDialogButtonSizer() + bsizer.AddButton(wx.Button(self, wx.ID_OK)) + btn = wx.Button(self, wx.ID_CANCEL) + bsizer.AddButton(btn) + btn.SetDefault() + bsizer.Realize() + vsizer.Add(bsizer, 0, wx.ALIGN_RIGHT) + vsizer.AddSpacer(8) + + self.SetSizer(vsizer) + self.SetAutoLayout(True) + + @ecbasewin.expose(FilterDialog) + def GetIncludes(self): + """Get the items from the includes list + @return: list of strings + + """ + return self._right.GetItems() + + @ecbasewin.expose(FilterDialog) + def SetIncludes(self, items): + """Set the items in the includes list + @param items: list of strings + + """ + return self._right.SetItems(items) + + @ecbasewin.expose(FilterDialog) + def GetExcludes(self): + """Get the items from the excludes list + @return: list of strings + + """ + return self._left.GetItems() + + @ecbasewin.expose(FilterDialog) + def SetExcludes(self, items): + """set the items in the excludes list + @param items: list of strings + + """ + return self._left.SetItems(items) + + @ecbasewin.expose(FilterDialog) + def SetListValues(self, valuemap): + """Set the values of the filter lists + @param valuemap: dict(item=bool) + + """ + includes = list() + excludes = list() + for item, include in valuemap.iteritems(): + if include: + includes.append(item) + else: + excludes.append(item) + includes.sort() + excludes.sort() + self.SetIncludes(includes) + self.SetExcludes(excludes) + + def OnButton(self, evt): + e_id = evt.GetId() + if e_id in (wx.ID_ADD, wx.ID_REMOVE): + cmap = { wx.ID_ADD : (self._left, self._right), + wx.ID_REMOVE : (self._right, self._left) } + idxs = list() + for sel in cmap[e_id][0].GetSelections(): + selstr = cmap[e_id][0].GetString(sel) + cmap[e_id][1].Append(selstr) + idxs.append(sel) + idxs.sort() + idxs.reverse() + for idx in idxs: + cmap[e_id][0].Delete(idx) + else: + evt.Skip() + + def OnUpdateButton(self, evt): + """Enable/Disable the Add/Remove buttons based on + selections in the list. + + """ + e_id = evt.GetId() + if e_id == wx.ID_ADD: + evt.Enable(len(self._left.GetSelections())) + elif e_id == wx.ID_REMOVE: + evt.Enable(len(self._right.GetSelections())) + else: + evt.Skip() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/finddlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/finddlg.py new file mode 100644 index 0000000..8e1f73d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/finddlg.py @@ -0,0 +1,1347 @@ +############################################################################### +# Name: finddlg.py # +# Purpose: Custom advanced find dialog # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: Advanced Find Replace Dialog + +The AdvancedFindReplaceDialog is a custom FindReplaceDlg that functions +similarly to the standard wx.FindReplaceDialog but provides more search +configuration and presentation options. + +The following items are the options that the AdvancedFindReplaceDialog offers +over the basic FindReplaceDialog. + + * Hide/Show each option or section individually (basic dialog only disables them) + * Multi-Find/Replace event action for Find All / Replace All actions + * Switch dialog from Find mode to Replace mode or visa-versa once its already + been created. + * Options for specifying the location to look in. + * Regular Expression option + * Use standard dialog or a floating MiniFrame (default) + +Requirements: +python 2.4+ +wxPython 2.8+ +eclib.platebtn +eclib.ctrlbox + +@todo: Make Look In location strings configurable + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: finddlg.py 71666 2012-06-06 17:55:42Z CJP $" +__revision__ = "$Revision: 71666 $" + +__all__ = ["FindBox", "FindEvent", "FindPanel", "FindReplaceDlg", + "MiniFindReplaceDlg", "AdvFindReplaceDlg", + + "AFR_STYLE_FINDDIALOG", "AFR_STYLE_REPLACEDIALOG", + "AFR_STYLE_NON_FLOATING", "AFR_STYLE_NO_MODE_SELECT", + + "AFR_UP", "AFR_WHOLEWORD", + "AFR_MATCHCASE", "AFR_REGEX", "AFR_RECURSIVE", "AFR_NOLOOKIN", + "AFR_NOUPDOWN", "AFR_NOWHOLEWORD", "AFR_NOMATCHCASE", "AFR_NOREGEX", + "AFR_NOFILTER", "AFR_NOOPTIONS", "AFR_NO_COUNT", "AFR_NO_ALL_BTN", + "AFR_SIMPLE", + + "LOCATION_CURRENT_DOC", "LOCATION_IN_SELECTION", + "LOCATION_OPEN_DOCS", "LOCATION_IN_CURRENT_DIR", + "LOCATION_IN_FILES", "LOCATION_MAX", + + "edEVT_FIND_CLOSE", "EVT_FIND_CLOSE", "edEVT_FIND", "EVT_FIND", + "edEVT_FIND_NEXT", "EVT_FIND_NEXT", "edEVT_FIND_ALL", "EVT_FIND_ALL", + "edEVT_REPLACE", "EVT_REPLACE", "edEVT_REPLACE_ALL", + "EVT_REPLACE_ALL", "EVT_OPTION_CHANGED", "edEVT_OPTION_CHANGED", + "EVT_COUNT", "edEVT_COUNT"] + +#--------------------------------------------------------------------------# +# Imports +import os +import wx + +# Local Imports +import ctrlbox +import platebtn + +#--------------------------------------------------------------------------# +# Globals + +# Style Flags +AFR_STYLE_FINDDIALOG = 0 # Start dialog in Find mode +AFR_STYLE_REPLACEDIALOG = 1 # Start dialog in Replace mode +AFR_STYLE_NON_FLOATING = 2 # Use a standard dialog as the tlw +AFR_STYLE_NO_MODE_SELECT = 4 # Hide the mode selector buttons + +# FindReplaceData Flags +AFR_UP = 1 # Set dialogs Search Up flag +AFR_WHOLEWORD = 2 # Set dialogs whole word search flag +AFR_MATCHCASE = 4 # Set dialogs match case search flag +AFR_REGEX = 8 # Set dialogs use regular expression flag +AFR_RECURSIVE = 16 # Set dialogs recursive directory search flag +AFR_NOLOOKIN = 32 # Hide the Looking combobox in the dialog +AFR_NOUPDOWN = 64 # Hide the Direction options in the dialog +AFR_NOWHOLEWORD = 128 # Hide the Whole Word option in the dialog +AFR_NOMATCHCASE = 256 # Hide the Match Case option in the dialog +AFR_NOREGEX = 512 # Hide the Regular Expression option +AFR_NOFILTER = 1024 # Hide the File Filter option +AFR_NOOPTIONS = 2048 # Hide all options in the dialog +AFR_NO_COUNT = 4096 # Hide Count Button +AFR_NO_ALL_BTN = 8192 # Hide Find All / Replace All buttons + +# Convenience Flags +AFR_SIMPLE = (AFR_NOLOOKIN | AFR_NOOPTIONS | AFR_NOUPDOWN | \ + AFR_NO_COUNT | AFR_NO_ALL_BTN) + +# Search Location Parameters (NOTE: must be kept in sync with Lookin List) +LOCATION_CURRENT_DOC = 0 +LOCATION_IN_SELECTION = 1 +LOCATION_OPEN_DOCS = 2 +LOCATION_IN_CURRENT_DIR = 3 +LOCATION_IN_FILES = 4 +LOCATION_MAX = LOCATION_IN_CURRENT_DIR + +# Control Names +FindBoxName = "EdFindBox" +FindPanelName = "EdFindPanel" + +# Find Panel Control Ids +ID_LOOKIN = wx.NewId() +ID_FIND_LBL = wx.NewId() +ID_REPLACE_LBL = wx.NewId() +ID_MATCH_CASE = wx.NewId() +ID_WHOLE_WORD = wx.NewId() +ID_REGEX = wx.NewId() +ID_RECURSE = wx.NewId() +ID_COUNT = wx.NewId() +ID_FIND_ALL = wx.NewId() +ID_REPLACE_ALL = wx.NewId() +ID_OPTION_CHANGE = wx.NewId() +ID_CHOOSE_DIR = wx.NewId() +ID_DIR_BOX = wx.NewId() + +_ = wx.GetTranslation + +#--------------------------------------------------------------------------# + +# Events Definitions + +# Find dialog has been closed +edEVT_FIND_CLOSE = wx.NewEventType() +EVT_FIND_CLOSE = wx.PyEventBinder(edEVT_FIND_CLOSE, 1) + +# Find cutton clicked +edEVT_FIND = wx.NewEventType() +EVT_FIND = wx.PyEventBinder(edEVT_FIND, 1) + +# Find cutton clicked again with the same search string +edEVT_FIND_NEXT = wx.NewEventType() +EVT_FIND_NEXT = wx.PyEventBinder(edEVT_FIND_NEXT, 1) + +# Find All button clicked +edEVT_FIND_ALL = wx.NewEventType() +EVT_FIND_ALL = wx.PyEventBinder(edEVT_FIND_ALL, 1) + +# Replace button clicked +edEVT_REPLACE = wx.NewEventType() +EVT_REPLACE = wx.PyEventBinder(edEVT_REPLACE, 1) + +# Replace button clicked +edEVT_COUNT = wx.NewEventType() +EVT_COUNT = wx.PyEventBinder(edEVT_COUNT, 1) + +# Replace All button clicked +edEVT_REPLACE_ALL = wx.NewEventType() +EVT_REPLACE_ALL = wx.PyEventBinder(edEVT_REPLACE_ALL, 1) + +# Find option has changed +edEVT_OPTION_CHANGED = wx.NewEventType() +EVT_OPTION_CHANGED = wx.PyEventBinder(edEVT_OPTION_CHANGED, 1) + +# Convenience for generating events +_EVENT_MAP = { wx.ID_FIND : edEVT_FIND, + wx.ID_REPLACE : edEVT_REPLACE, + ID_COUNT : edEVT_COUNT, + ID_FIND_ALL : edEVT_FIND_ALL, + ID_REPLACE_ALL : edEVT_REPLACE_ALL, + ID_OPTION_CHANGE : edEVT_OPTION_CHANGED } + +class FindEvent(wx.PyCommandEvent): + """Event sent by the FindReplaceDialog that contains all + options of the FindReplaceData and requested action of the + find dialog + + """ + def __init__(self, etype, eid=wx.ID_ANY, flags=0): + """Creates the event object + @param etype: Event Type + @keyword eid: Event ID + @keyword flags: Find/Replace flags + + """ + super(FindEvent, self).__init__(etype, eid) + + # Attributes + self._flags = flags + self._loc = 0 + self._find = u'' + self._replace = u'' + self._dir = u'' + self._filters = None + self._count = 0 + + def GetCount(self): + """Get the number of matches + @return: int + + """ + return self._count + + def GetDirectory(self): + """Get the directory of files to search in + @return: string + + """ + return self._dir + + def GetFileFilters(self): + """Get the filter to search with + @return: list or None + + """ + return self._filters + + def GetFindString(self): + """Get the find string + @return: string + + """ + return self._find + + def GetFlags(self): + """Get the search flags + @return: long + + """ + return self._flags + + def GetReplaceString(self): + """Set the find String + @return: string + + """ + return self._replace + + def GetSearchType(self): + """Get the type of search (current buffer, open documents, ect...) + @return: int (see LOCATION_* flags) + + """ + return self._loc + + def SetCount(self, count): + """Set the count + @param count: int + + """ + self._count = count + + def SetDirectory(self, directory): + """Set the directory of files to search in + @param directory: string + + """ + self._dir = directory + + def SetFileFilters(self, filters): + """Set the file filters to use for a Search In Files event + @param filters: string or list of strings + + """ + if isinstance(filters, basestring): + self._filters = filters.split() + else: + self._filters = filters + + if self._filters is not None: + self._filters = [ f.strip() for f in self._filters ] + + def SetFindString(self, find): + """Set the find String + @param find: string + + """ + self._find = find + + def SetFlags(self, flags): + """Returns the value from the event. + @return: the value of this event + + """ + self._flags = flags + + def SetReplaceString(self, rstring): + """Set the find String + @param rstring: string + + """ + self._replace = rstring + + def SetSearchType(self, stype): + """Set the type of search (current buffer, open documents, ect...) + @param stype: int (see LOCATION_* flags) + + """ + self._loc = stype + + def IsMatchCase(self): + """Is this a match case search + @return: bool + + """ + return bool(self._flags & AFR_MATCHCASE) + + def IsRecursive(self): + """Is the search option for recursive directory search enabled + @return: bool + + """ + return bool(self._flags & AFR_RECURSIVE) + + def IsRegEx(self): + """Is RegEx enabled in the dialog + @return: bool + + """ + return bool(self._flags & AFR_REGEX) + + def IsWholeWord(self): + """Is this a whole word search + @return: bool + + """ + return bool(self._flags & AFR_WHOLEWORD) + + def IsUp(self): + """Is the search searching up + @return: bool + + """ + return bool(self._flags & AFR_UP) + +#--------------------------------------------------------------------------# + +def AdvFindReplaceDlg(parent, fdata, title, style=AFR_STYLE_FINDDIALOG): + """Advanced FindReplaceDialog. Create and return the requested dialog type + @param parent: parent + @param fdata: FindReplaceData + @param title: Dialog Title. Pass a single string to set the title for both + modes of the dialog or a tuple of two strings to set the title + for (find, replace) modes. + @keyword style: Dialog Style and type + @note: this is a function not a class + + """ + if style & AFR_STYLE_NON_FLOATING: + dlg = FindReplaceDlg(parent, fdata, title, style) + else: + dlg = MiniFindReplaceDlg(parent, fdata, title, style) + + return dlg + +#--------------------------------------------------------------------------# + +class FindReplaceDlgBase: + """Delegate mixin base class for deriving FindReplaceDialogs, delegates + calls to the widgets and containers that make up the dialog. + @note: The mixin must be initialized after the class its being mixed into + + """ + def __init__(self, parent, fdata, title, style=AFR_STYLE_FINDDIALOG): + """Create the base object + @param title: string or tuple (findstr, replacestr) + + """ + # Attributes + if isinstance(title, basestring): + self._ftitle = title + self._rtitle = title + else: + self._ftitle, self._rtitle = title[:2] + + self._box = FindBox(self, fdata, style=style) + self._panel = self._box.GetWindow() + self._accl = wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CLOSE),]) + self.SetAcceleratorTable(self._accl) + + # Layout + self.__DoLayout() + tmp_title = self._ftitle + if style & AFR_STYLE_REPLACEDIALOG: + tmp_title = self._rtitle + self.SetTitle(tmp_title) + + # Event handlers + self.Bind(_EVT_MODE_CHANGE, self._OnModeChange) + self.Bind(_EVT_DO_CLOSE_DLG, lambda evt: self._SendCloseEvent()) + self.Bind(wx.EVT_MENU, lambda evt: self._SendCloseEvent(), id=wx.ID_CLOSE) + self.Bind(wx.EVT_SET_FOCUS, self._OnSetFocus) + self.Bind(wx.EVT_SHOW, self._OnShow) + + def __DoLayout(self): + """Layout the dialog""" + vsizer = wx.BoxSizer(wx.VERTICAL) + vsizer.Add(self._box, 1, wx.EXPAND) + self.SetSizer(vsizer) + self.SetAutoLayout(True) + self.Fit() + + def _SendCloseEvent(self): + """Send a dialog close event and hide the dialog""" + data = self._panel.GetData() + data.SetFindString(self._panel._ftxt.GetValue()) + data.SetReplaceString(self._panel._rtxt.GetValue()) + evt = FindEvent(edEVT_FIND_CLOSE, self.GetId()) + self.Hide() + wx.PostEvent(self.GetParent(), evt) + + def _OnModeChange(self, evt): + """Update the the dialog when the mode changes""" + self.Fit() + title = self._ftitle + if self.GetDialogMode() != AFR_STYLE_FINDDIALOG: + title = self._rtitle + self.SetTitle(title) + + def _OnSetFocus(self, evt): + if self and self._panel: + self._panel.SetFocus() + evt.Skip() + + def _OnShow(self, evt): + if self and self._panel: + self._panel.SetFocus() + + def GetData(self): + """Get the FindReplaceData used by this dialog""" + return self._panel.GetData() + + def GetDialogMode(self): + """Get the current mode of the dialog + @return: AFR_STYLE_FINDDIALOG or AFR_STYLE_REPLACEDIALOG + + """ + return self._panel.GetPanelMode() + + def GetFileFilters(self): + """Get the file filters field value + @return: string + + """ + return self._panel.GetFileFilters() + + def GetLookinChoices(self): + """Get the set choices from the looking choice list + @return: list of strings + + """ + return self._panel.GetLookinChoices() + + def GetLookinSelection(self): + """Get the index of the selected item in the lookin choice list + @return: int + + """ + return self._panel.GetLookinSelection() + + def RefreshFindReplaceFields(self): + """Refresh the values of the Find and Replace fields with the + values that are currently in the FindReplaceData. + + """ + data = self.GetData() + self._panel.SetFindString(data.GetFindString()) + self._panel.SetReplaceString(data.GetReplaceString()) + + def RefreshFindOptions(self): + """Refresh the find options controls based on the current + values of the FindData owned by this window. + + """ + self._panel.RefreshControls() + + def SetData(self, data): + """Set the dialogs FindReplaceData + @param data: FindReplaceData + @note: causes updates in dialog + + """ + self._panel.SetData(data) + + def SetDialogMode(self, mode): + """Set the dialog mode between find and find/replace + @param mode: AFR_STYLE_FINDDIALOG or AFR_STYLE_REPLACEDIALOG + + """ + self._box.SetBoxMode(mode == AFR_STYLE_FINDDIALOG) + + def SetDirectoryGetter(self, dgetter): + """Set a callback for retrieving the current directory. This method + is used for providing context when popping up dialogs such as the + Choose Directory dialog. + @param dgetter: callable() => unicode + + """ + self._panel.SetDirectoryGetter(dgetter) + + def SetFileFilters(self, filters): + """Set the file filters field value + @param filters: string + + """ + self._panel.SetFileFilters(filters) + + def SetFindBitmap(self, bmp): + """Set the find Bitmap + @param bmp: wx.Bitmap + + """ + self._box.SetFindBitmap(bmp) + + def SetFlag(self, flags): + """Set a search dialog flag. + @param flags: AFR_* + + """ + self._panel.SetFlag(flags) + + def SetFlags(self, flags): + """Set the search dialog flags. + @param flags: bitmask of AFR_ values + + """ + self._panel.SetFlags(flags) + + def SetLookinChoices(self, paths): + """Set the looking choices + @param paths: list of strings + + """ + self._panel.SetLookinChoices(paths) + + def SetLookinPath(self, path): + """Set the lookin path, adding it to the collection if it is + not in there. + @param path: string (path of directory) + + """ + idx = self._panel.AddLookinPath(path) + self.SetLookinSelection(idx) + + def SetLookinSelection(self, sel): + """Set the looking choices selection + @param sel: int + + """ + self._panel.SetLookinSelection(sel) + + def SetReplaceBitmap(self, bmp): + """Set the replace bitmap + @param bmp: wx.Bitmap + + """ + self._box.SetReplaceBitmap(bmp) + + def SetFindDirectory(self, path): + """Set the directory selection for find in files + @param path: path to set for lookin data + + """ + self._panel.SetLookinSelection(path) + + def SetFindString(self, query): + """Set the find controls search string + @param query: string + + """ + self._panel.SetFindString(query) + + def SetReplaceString(self, rstring): + """Set the replace controls search string + @param rstring: string + + """ + self._panel.SetReplaceString(rstring) + +#--------------------------------------------------------------------------# + +class MiniFindReplaceDlg(wx.MiniFrame, FindReplaceDlgBase): + """Advanced Find Replace Dialog this version of the dialog uses a + MiniFrame that will float on top of its parent + + """ + def __init__(self, parent, fdata, title, style=AFR_STYLE_FINDDIALOG): + """Create the Dialog + @param parent: Parent Window + @param fdata: wx.FindReplaceData + @param title: Dialog Title. Pass a single string to set the title for + both modes of the dialog or a tuple of two strings to set + the title for (find, replace) modes. + @keyword style: Dialog Style + + """ + wx.MiniFrame.__init__(self, parent, wx.ID_ANY, u'', + style=wx.DEFAULT_DIALOG_STYLE) + FindReplaceDlgBase.__init__(self, parent, fdata, title, style) + + # Event handlers + self.Bind(wx.EVT_CLOSE, lambda evt: self._SendCloseEvent()) + +#--------------------------------------------------------------------------# + +class FindReplaceDlg(wx.Dialog, FindReplaceDlgBase): + """Advanced Find Replace Dialog this version of the dialog uses a standard + dialog window. + + """ + def __init__(self, parent, fdata, title, style=AFR_STYLE_FINDDIALOG): + """Create the Dialog + @param parent: Parent Window + @param fdata: wx.FindReplaceData + @param title: Dialog Title can be a string to set the title for both + modes or a tuple of two strings to set the (find, replace) + mode titles. + @keyword style: Dialog Style + + """ + wx.Dialog.__init__(self, parent, wx.ID_ANY, u'', + style=wx.DEFAULT_DIALOG_STYLE) + FindReplaceDlgBase.__init__(self, parent, fdata, title, style) + + # Event handlers + self.Bind(wx.EVT_CLOSE, lambda evt: self._SendCloseEvent()) + +#--------------------------------------------------------------------------# + +class FindBox(ctrlbox.ControlBox): + """Container box that allows for switching the L{FindPanel}'s mode + through the ui. Contains a L{FindPanel} and two PlateButtons for switching + the mode. + + """ + def __init__(self, parent, fdata, id=wx.ID_ANY, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=AFR_STYLE_FINDDIALOG, + name=FindBoxName): + """Create the container box + @param fdata: wx.FindReplaceData + + """ + super(FindBox, self).__init__(parent, id, pos, size, + wx.TAB_TRAVERSAL|wx.NO_BORDER, name) + + # Attributes + self._fpanel = FindPanel(self, fdata, style=style) + ctrlbar = ctrlbox.ControlBar(self, style=ctrlbox.CTRLBAR_STYLE_GRADIENT) + bmp = wx.ArtProvider.GetBitmap(wx.ART_FIND, wx.ART_MENU) + self.find = platebtn.PlateButton(ctrlbar, label=_("Find"), bmp=bmp, + style=platebtn.PB_STYLE_NOBG) + bmp = wx.ArtProvider.GetBitmap(wx.ART_FIND_AND_REPLACE, wx.ART_MENU) + self.replace = platebtn.PlateButton(ctrlbar, label=_("Replace"), + bmp=bmp, + style=platebtn.PB_STYLE_NOBG) + + # Setup + if wx.Platform == '__WXGTK__': + ctrlbar.SetWindowStyle(ctrlbox.CTRLBAR_STYLE_BORDER_BOTTOM) + + ctrlbar.SetVMargin(2, 2) + ctrlbar.AddControl(self.find, wx.ALIGN_LEFT) + ctrlbar.AddControl(self.replace, wx.ALIGN_LEFT) + self.SetControlBar(ctrlbar) + self.SetWindow(self._fpanel) + + if style & AFR_STYLE_NO_MODE_SELECT: + self.GetControlBar().Hide() + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + + def OnButton(self, evt): + """Change the mode + @param evt: wx.EVT_BUTTON + + """ + eobj = evt.GetEventObject() + if eobj in (self.find, self.replace): + self.SetBoxMode(eobj == self.find) + else: + evt.Skip() + + def SetFindBitmap(self, bmp): + """Set the bitmap of the Find Button + @param bmp: wx.Bitmap + + """ + self.find.SetBitmap(bmp) + self.GetControlBar().Layout() + + def SetBoxMode(self, find=True): + """Set the box to find or find/replace mode + @keyword find: set to find mode + + """ + self._fpanel.SetFindMode(find) + self.Layout() + evt = _AdvFindDlgInternalEvent(self.GetId(), _edEVT_MODE_CHANGE) + wx.PostEvent(self.GetParent(), evt) + + def SetReplaceBitmap(self, bmp): + """Set the bitmap of the Replace Button + @param bmp: wx.Bitmap + + """ + self.replace.SetBitmap(bmp) + self.GetControlBar().Layout() + +#--------------------------------------------------------------------------# + +class FindPanel(wx.Panel): + """Find controls panel""" + def __init__(self, parent, fdata, id=wx.ID_ANY, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=AFR_STYLE_FINDDIALOG, name=FindPanelName): + """Create the panel + @param fdata: wx.FindReplaceData + + """ + super(FindPanel, self).__init__(parent, id, pos, size, + wx.TAB_TRAVERSAL|wx.NO_BORDER, name) + + # Attributes + # TODO: change to editable combo box when wxMac has native widget + # so that we can set a search history to choose from. + self._mode = style + self._ftxt = wx.TextCtrl(self, value=fdata.GetFindString()) + self._rtxt = wx.TextCtrl(self, value=fdata.GetReplaceString()) + locations = [_("Current Document"), _("Selected Text"), + _("Open Documents"), _("Current Directory")] + self._lookin = wx.Choice(self, ID_LOOKIN, choices=locations) + self._lookin.SetSelection(0) + self._filterlbl = wx.StaticText(self, label=_("File Filters:")) + self._filters = None # Created in __DoLayout + self._sizers = dict() + self._paths = dict() + self._fdata = fdata + self._dgetter = lambda : u"" + self._lastSearch = u'' + + # Layout + self.__DoLayout() + self.SetInitialSize() + self._ConfigureControls() + + # Setup + self.SetFindMode(not (self._mode & AFR_STYLE_REPLACEDIALOG)) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnChooseDir, id=ID_CHOOSE_DIR) + self.Bind(wx.EVT_BUTTON, + lambda evt: self.FireEvent(evt.GetId()) or evt.Skip()) + self.Bind(wx.EVT_CHECKBOX, self.OnOption) + self.Bind(wx.EVT_RADIOBUTTON, self.OnOption) + self.Bind(wx.EVT_CHOICE, self.OnChoice, id=ID_LOOKIN) + for bid in (wx.ID_FIND, wx.ID_REPLACE, ID_COUNT, + ID_FIND_ALL, ID_REPLACE_ALL): + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=bid) + self.Bind(wx.EVT_SET_FOCUS, lambda evt: self.__SetFocus()) + self._ftxt.Bind(wx.EVT_SET_FOCUS, lambda evt: self._ftxt.SelectAll()) + self._rtxt.Bind(wx.EVT_SET_FOCUS, lambda evt: self._rtxt.SelectAll()) + + # Key handling HACK for windows + if wx.Platform == '__WXMSW__': + for child in self.GetChildren(): + child.Bind(wx.EVT_KEY_UP, self._OnKeyUp) + + def __SetFocus(self): + """Set the focus to the find box""" + self._ftxt.SetFocus() + self._ftxt.SelectAll() + + def __DoLayout(self): + """Layout the panel""" + hsizer = wx.BoxSizer(wx.HORIZONTAL) + vsizer = wx.BoxSizer(wx.VERTICAL) + + # Top Section + topvsizer = wx.BoxSizer(wx.VERTICAL) + + # Platform dependant labels + if wx.Platform == '__WXMSW__': + findlbl = wx.StaticText(self, ID_FIND_LBL, _("Find what") + u":") + else: + findlbl = wx.StaticText(self, ID_FIND_LBL, _("Find") + u":") + + # Search Field + fhsizer = wx.BoxSizer(wx.HORIZONTAL) + fhsizer.Add(self._ftxt, 1, wx.EXPAND) + topvsizer.AddMany([(findlbl, 0, wx.ALIGN_LEFT), ((3, 3), 0), + (fhsizer, 0, wx.EXPAND)]) + + # Replace field + rhsizer = wx.BoxSizer(wx.HORIZONTAL) + rhsizer.Add(self._rtxt, 1, wx.EXPAND) + rlbl = wx.StaticText(self, ID_REPLACE_LBL, _("Replace with") + u":") + self._sizers[ID_REPLACE_LBL] = wx.BoxSizer(wx.VERTICAL) + self._sizers[ID_REPLACE_LBL].AddMany([((5, 5), 0), + (rlbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((3, 3), 0), (rhsizer, 0, wx.EXPAND)]) + topvsizer.AddMany([(self._sizers[ID_REPLACE_LBL], 0, wx.EXPAND), + ((5, 5), 0)]) + + # Look in field + self._sizers['look'] = wx.BoxSizer(wx.VERTICAL) + li_sz = wx.BoxSizer(wx.HORIZONTAL) + dirbtn = wx.Button(self, ID_CHOOSE_DIR, u"...", style=wx.BU_EXACTFIT) + dirbtn.SetToolTipString(_("Choose Folder")) + li_sz.AddMany([(self._lookin, 1, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (dirbtn, 0, wx.ALIGN_CENTER_VERTICAL)]) + li_lbl = wx.StaticText(self, label=_("Look in") + u":") + self._sizers['look'].AddMany([(li_lbl, 0, wx.ALIGN_LEFT), + ((3, 3), 0), + (li_sz, 0, wx.EXPAND), + ((5, 5), 0)]) + topvsizer.Add(self._sizers['look'], 0, wx.EXPAND) + + # Search Direction Box + self._sizers['dir'] = wx.BoxSizer(wx.VERTICAL) + dbox = wx.StaticBox(self, id=ID_DIR_BOX, label=_("Direction")) + dboxsz = wx.StaticBoxSizer(dbox, wx.HORIZONTAL) + dboxsz.AddMany([(wx.RadioButton(self, wx.ID_UP, _("Up")), 0), + ((20, 5), 0), + (wx.RadioButton(self, wx.ID_DOWN, _("Down")), 0), + ((5, 5), 1)]) + self._sizers['dir'].AddMany([((5, 5), 0), (dboxsz, 0, wx.EXPAND)]) + + # Search Options Box + self._sizers['opt'] = wx.BoxSizer(wx.VERTICAL) + statbox = wx.StaticBox(self, label=_("Find Options")) + sboxsz = wx.StaticBoxSizer(statbox, wx.VERTICAL) + for cid, clbl in [(ID_MATCH_CASE, _("Match case")), + (ID_WHOLE_WORD, _("Whole word")), + (ID_REGEX, _("Regular expression")), + (ID_RECURSE, _("Search Recursively"))]: + sboxsz.AddMany([((3, 3), 0), (wx.CheckBox(self, cid, clbl), 0)]) + + # File Filters + self._sizers['filter'] = wx.BoxSizer(wx.VERTICAL) + self._filters = wx.TextCtrl(self) + tt_txt = _("Wildcard shell patterns for matching files (*.txt *.html).") + self._filters.SetToolTipString(tt_txt) + + # Disable spell checking on mac for this control + if wx.Platform == '__WXMAC__': + self._filters.MacCheckSpelling(False) + + f_sz = wx.BoxSizer(wx.HORIZONTAL) + f_sz.Add(self._filters, 1, wx.EXPAND) + self._sizers['filter'].AddMany([(self._filterlbl, 0, wx.ALIGN_LEFT), + ((3, 3), 0), (f_sz, 0, wx.EXPAND), + ((5, 5), 0)]) + sboxsz.AddMany([((3, 3), 0), (self._sizers['filter'], 0, wx.EXPAND)]) + + self._sizers['opt'].AddMany([((5, 5), 0), (sboxsz, 0, wx.EXPAND)]) + + # Buttons + bsizer = wx.BoxSizer(wx.HORIZONTAL) + self._sizers['fspacer'] = bsizer.Add((100, 1), 1) + self._sizers['frspacer'] = bsizer.Add((50, 1), 1) + for bid, blbl in [(wx.ID_FIND, _("Find")), + (wx.ID_REPLACE, _("Replace")), + (ID_COUNT, _("Count")), + (ID_FIND_ALL, _("Find All")), + (ID_REPLACE_ALL, _("Replace All"))]: + self._sizers[bid] = wx.BoxSizer(wx.HORIZONTAL) + self._sizers[bid].Add((3, 3), 0) + self._sizers[bid].Add(wx.Button(self, bid, blbl), 0, wx.ALIGN_RIGHT) + bsizer.Add(self._sizers[bid], 0) + self.FindWindowById(wx.ID_FIND).SetDefault() + + # Final Layout + vsizer.AddMany([((5, 5), 0), (topvsizer, 0, wx.EXPAND), + (self._sizers['dir'], 0, wx.EXPAND), + (self._sizers['opt'], 0, wx.EXPAND), ((10, 10), 0), + (bsizer, 0), ((10, 10), 0)]) + hsizer.AddMany([((10, 10), 0), (vsizer, 0, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(hsizer) + self.SetAutoLayout(True) + + def _ConfigureControls(self): + """Configure the state of the controls based on the FindReplaceData""" + flags = self._fdata.GetFlags() + self._ftxt.SelectAll() + self.FindWindowById(ID_MATCH_CASE).SetValue(flags & AFR_MATCHCASE) + self.FindWindowById(ID_WHOLE_WORD).SetValue(flags & AFR_WHOLEWORD) + self.FindWindowById(ID_REGEX).SetValue(flags & AFR_REGEX) + self.FindWindowById(wx.ID_DOWN).SetValue(not (flags & AFR_UP)) + self.FindWindowById(wx.ID_UP).SetValue(flags & AFR_UP) + self.ShowLookinCombo(not (flags & AFR_NOLOOKIN)) + self.ShowDirectionBox(not (flags & AFR_NOUPDOWN)) + self.ShowOptionsBox(not (flags & AFR_NOOPTIONS)) + self.FindWindowById(ID_WHOLE_WORD).Enable(not (flags & AFR_NOWHOLEWORD)) + self.FindWindowById(ID_MATCH_CASE).Enable(not (flags & AFR_NOMATCHCASE)) + self.FindWindowById(ID_REGEX).Enable(not (flags & AFR_NOREGEX)) + in_files = bool(self._lookin.GetSelection() >= LOCATION_MAX) + recurse = self.FindWindowById(ID_RECURSE) + recurse.SetValue(flags & AFR_RECURSIVE) + recurse.Enable(in_files) + self.ShowFileFilters(in_files and not (flags & AFR_NOFILTER)) + + def _OnKeyUp(self, evt): + """Check if the dialog should be closed + @note: msw only + + """ + if evt.GetKeyCode() == wx.WXK_ESCAPE: + evt = _AdvFindDlgInternalEvent(self.GetId(), _edEVT_DO_CLOSE_DLG) + wx.PostEvent(self.GetTopLevelParent(), evt) + evt.Skip() + + def _ShowButtons(self, find=True): + """Toggle the visiblity of a button set + @param find: Show Find Buttons or Show Replace Buttons + + """ + if find: + show = [wx.ID_FIND, ID_COUNT, ID_FIND_ALL, 'fspacer'] + hide = [wx.ID_REPLACE, ID_REPLACE_ALL, 'frspacer'] + else: + show = [wx.ID_REPLACE, ID_REPLACE_ALL, 'frspacer'] + hide = [ID_FIND_ALL, ID_COUNT, 'fspacer'] + + # Hide extra buttons as per configured preference + flags = self._fdata.GetFlags() + if flags & AFR_NO_COUNT and ID_COUNT in show: + show.remove(ID_COUNT) + hide.append(ID_COUNT) + + if flags & AFR_NO_ALL_BTN: + if ID_FIND_ALL in show: + show.remove(ID_FIND_ALL) + hide.append(ID_FIND_ALL) + if ID_REPLACE_ALL in show: + show.remove(ID_REPLACE_ALL) + hide.append(ID_REPLACE_ALL) + + for ctrl in show: + if isinstance(ctrl, basestring): + self._sizers[ctrl].Show(True) + else: + self._sizers[ctrl].ShowItems(True) + + for ctrl in hide: + if isinstance(ctrl, basestring): + self._sizers[ctrl].Show(False) + else: + self._sizers[ctrl].ShowItems(False) + + def _UpdateContext(self): + """Update available dialog options based on the selected search context + + """ + self._UpdateDefaultBtn() + in_files = bool(self._lookin.GetSelection() >= LOCATION_MAX) + self.FindWindowById(ID_RECURSE).Enable(in_files) + flags = self._fdata.GetFlags() + + # Disable direction settings when searcing in file since they + # are ignored anyway. + for cid in (wx.ID_UP, wx.ID_DOWN, ID_DIR_BOX): + self.FindWindowById(cid).Enable(not in_files) + + # Only update visibility of file filter field if it is enabled + if not (flags & AFR_NOFILTER): + self.ShowFileFilters(in_files) + + def _UpdateDefaultBtn(self): + """Change the default button depending on what the search context + has been changed to. + + """ + find = self.FindWindowById(wx.ID_FIND) + find_all = self.FindWindowById(ID_FIND_ALL) + replace = self.FindWindowById(wx.ID_REPLACE) + replace_all = self.FindWindowById(ID_REPLACE_ALL) + count = self.FindWindowById(ID_COUNT) + + lookin = self._lookin.GetSelection() + if lookin > LOCATION_IN_SELECTION: + if self._mode == AFR_STYLE_FINDDIALOG: + find_all.SetDefault() + else: + replace_all.SetDefault() + find.Disable() + replace.Disable() + count.Disable() + elif lookin == LOCATION_IN_SELECTION: + find.Disable() + replace.Disable() + replace_all.SetDefault() + else: + find.SetDefault() + find.Enable() + replace.Enable() + count.Enable() + + #------------------------------------------------------# + + def AddLookinPath(self, path): + """Add a path to the lookin path collection + @param path: string + @return: index of the items location + + """ + if not len(path): + return None + + # If its a path we already have then just return its index + if path in self._paths.values(): + for idx, pname in self._paths.iteritems(): + if path == pname: + return idx + + # Get the short directory name + the_dir = u'' + for dname in reversed(path.split(os.sep)): + if len(dname): + the_dir = dname + break + + self._paths[self._lookin.GetCount()] = path + self._lookin.Append(the_dir) + rval = self._lookin.GetCount() - 1 + + return rval + + def ClearFlag(self, flag): + """Clear a search flag + @param flag: AFR_* + + """ + flags = self._fdata.GetFlags() + flags &= ~flag + self.SetFlags(flags) + + def FireEvent(self, eid): + """Fire an event + @param eid: Event id + + """ + etype = _EVENT_MAP.get(eid, None) + query = self._ftxt.GetValue() + if eid == wx.ID_FIND: + if self._lastSearch == query: + etype = edEVT_FIND_NEXT + self._lastSearch = query + self._fdata.SetFindString(query) + + if etype is not None: + evt = FindEvent(etype, eid, self._fdata.GetFlags()) + evt.SetEventObject(self) + lookin_idx = self._lookin.GetSelection() + stype = min(LOCATION_IN_FILES, max(LOCATION_CURRENT_DOC, lookin_idx)) + evt.SetSearchType(stype) + evt.SetFindString(query) + + if self._mode & AFR_STYLE_REPLACEDIALOG: + rstring = self._rtxt.GetValue() + self._fdata.SetReplaceString(rstring) + evt.SetReplaceString(rstring) + else: + evt.SetReplaceString(None) + + if stype >= LOCATION_IN_FILES or stype == LOCATION_IN_CURRENT_DIR: + evt.SetFileFilters(self.GetFileFilters()) + if stype >= LOCATION_IN_FILES: + # For IN_CURRENT_DIR it is up to client to determine directory + # based on what current means to the application. + evt.SetDirectory(self._paths.get(lookin_idx, u'')) + + wx.PostEvent(self.GetParent(), evt) + return True + else: + return False + + def GetData(self): + """Get the FindReplaceData used by this panel + @return: wx.FindReplaceData + + """ + return self._fdata + + def GetFileFilters(self): + """Get the currently set file filters + @return: string + + """ + return self._filters.GetValue() + + def GetLookinChoices(self): + """Get the looking choices + @return: list of strings + + """ + choices = list() + for key in sorted(self._paths.keys()): + choices.append(self._paths[key]) + return choices + + def GetLookinSelection(self): + """Get the index of the currently selected lookin choice + @return: int + + """ + return self._lookin.GetSelection() + + def GetPanelMode(self): + """Get the current display mode of the panel + @return: AFR_STYLE_FINDDIALOG or AFR_STYLE_REPLACEDIALOG + + """ + return self._mode + + def OnChoice(self, evt): + """Handle choice control events + @param evt: wx.EVT_CHOICE + + """ + e_id = evt.Id + if e_id == ID_LOOKIN: + self._UpdateContext() + choice = self._lookin.GetSelection() + if choice >= LOCATION_IN_FILES: + tts = self._paths.get(choice, u'') + self._lookin.SetToolTipString(tts) + else: + self._lookin.SetToolTipString(u'') + else: + evt.Skip() + + def OnChooseDir(self, evt): + """Open the choose directory dialog for selecting what + path to do a search in files in. + @param evt: wx.EVT_BUTTON + + """ + if evt.Id == ID_CHOOSE_DIR: + dname = self._dgetter() + dlg = wx.DirDialog(self, _("Choose Search Folder"), defaultPath=dname) + if dlg.ShowModal() == wx.ID_OK: + path = dlg.GetPath() + if path is not None and len(path): + idx = self.AddLookinPath(path) + self.SetLookinSelection(idx) + self._UpdateContext() + dlg.Destroy() + else: + evt.Skip() + + def OnOption(self, evt): + """Update search flags + @param evt: wx.EVT_CHECKBOX + + """ + fmap = { ID_MATCH_CASE : AFR_MATCHCASE, + ID_WHOLE_WORD : AFR_WHOLEWORD, + ID_REGEX : AFR_REGEX, + ID_RECURSE : AFR_RECURSIVE, + wx.ID_UP : AFR_UP } + eid = evt.Id + eobj = evt.EventObject + if eid in fmap: + if eobj.GetValue(): + self.SetFlag(fmap[eid]) + else: + self.ClearFlag(fmap[eid]) + self.FireEvent(ID_OPTION_CHANGE) + elif eid == wx.ID_DOWN: + self.ClearFlag(fmap[wx.ID_UP]) + self.FireEvent(ID_OPTION_CHANGE) + else: + evt.Skip() + + def OnUpdateUI(self, evt): + """Enable and disable buttons depending on state of find entry box. + @param evt: wx.UpdateUIEvent + + """ + # TODO: support count in files? + if evt.Id in (wx.ID_FIND, ID_COUNT, wx.ID_REPLACE) and \ + self._lookin.GetSelection() > LOCATION_CURRENT_DOC: + evt.Enable(False) + else: + txt = len(self._ftxt.GetValue()) + evt.Enable(txt) + + def SetFindMode(self, find=True): + """Set the mode of the dialog Replace + @param find: Set Find Mode or Replace Mode + + """ + self._rtxt.Show(not find) + self._sizers[ID_REPLACE_LBL].ShowItems(not find) + if find: + self._mode = AFR_STYLE_FINDDIALOG + else: + self._mode = AFR_STYLE_REPLACEDIALOG + + self._UpdateDefaultBtn() + self._ShowButtons(find) + self.Layout() + + def SetFindString(self, query): + """Set the find fields string + @param query: string + + """ + self._ftxt.SetValue(query) + self._fdata.SetFindString(query) + + def RefreshControls(self): + """Refresh the state of the controls from the current FindData.""" + self._ConfigureControls() + + def SetData(self, data): + """Set the FindReplaceData and update the dialog with that data + @param data: wxFindReplaceData + + """ + self._fdata.Destroy() + self._fdata = None + self._fdata = data + self._ConfigureControls() + + def SetDirectoryGetter(self, dgetter): + """Set a callback for retrieving the current directory. This method + is used for providing context when popping up dialogs such as the + Choose Directory dialog. + @param dgetter: callable() => unicode + + """ + if not callable(dgetter): + dgetter = lambda : u"" + self._dgetter = dgetter + + def SetFileFilters(self, filters): + """Set the file filters field values + @param filters: string + + """ + self._filters.SetValue(filters) + + def SetFlag(self, flag): + """Set a search flag + @param flag: AFR_* flag value + + """ + flags = self._fdata.GetFlags() + flags |= flag + self.SetFlags(flags) + + def SetFlags(self, flags): + """Set the search flags + @param flags: Bitmask of AFR_* values + + """ + self._fdata.SetFlags(flags) + self._ConfigureControls() + + def SetLookinChoices(self, paths): + """Set the looking choices + @param paths: list of strings + + """ + for path in paths: + self.AddLookinPath(path) + + def SetLookinSelection(self, idx): + """Set the selection of the lookin control. + @param idx: int + + """ + if idx <= self._lookin.GetCount(): + self._lookin.SetSelection(idx) + + # If the selection is a Look in Files make sure the filter + # field is shown + flags = self._fdata.GetFlags() + in_files = bool(idx >= LOCATION_MAX) + self.ShowFileFilters(in_files and not (flags & AFR_NOFILTER)) + + def SetReplaceString(self, rstring): + """Set the replace fields string + @param rstring: string + + """ + self._rtxt.SetValue(rstring) + self._fdata.SetReplaceString(rstring) + + def ShowDirectionBox(self, show=True): + """Show or hide the Direction group box + @keyword show: bool + + """ + if 'dir' in self._sizers: + self._sizers['dir'].ShowItems(show) + self.Layout() + + def ShowFileFilters(self, show=True): + """Show or hide the File Filters filed + @keyword show: bool + + """ + if 'filter' in self._sizers: + self._sizers['filter'].ShowItems(show) + self.Layout() + + # Require additional resizing + evt = _AdvFindDlgInternalEvent(self.GetId(), _edEVT_MODE_CHANGE) + wx.PostEvent(self.GetTopLevelParent(), evt) + + def ShowLookinCombo(self, show=True): + """Show the lookin choice and directory chooser control + @keyword show: bool + + """ + if 'look' in self._sizers: + self._sizers['look'].ShowItems(show) + self.Layout() + + def ShowOptionsBox(self, show=True): + """Show the find options group box + @keyword show: bool + + """ + if 'opt' in self._sizers: + self._sizers['opt'].ShowItems(show) + self.Layout() + +#--------------------------------------------------------------------------# +# Private Module Api + +_edEVT_MODE_CHANGE = wx.NewEventType() +_EVT_MODE_CHANGE = wx.PyEventBinder(_edEVT_MODE_CHANGE, 1) + +_edEVT_DO_CLOSE_DLG = wx.NewEventType() +_EVT_DO_CLOSE_DLG = wx.PyEventBinder(_edEVT_DO_CLOSE_DLG, 1) + +class _AdvFindDlgInternalEvent(wx.PyEvent): + def __init__(self, winid=wx.ID_ANY, etype=wx.wxEVT_NULL): + """Create the Event""" + wx.PyEvent.__init__(self, winid, etype) + +#--------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/infodlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/infodlg.py new file mode 100644 index 0000000..c450468 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/infodlg.py @@ -0,0 +1,299 @@ +############################################################################### +# Name: FileInfo.py # +# Purpose: Display information about files/folders # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FileInfo.py + +Dialog for displaying file information. + +Displays information on: + * Filename and Path + * File Size + * Read/Write/Execute permissions + * Creation/Modification times + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: infodlg.py 66025 2010-11-05 19:18:08Z CJP $" +__revision__ = "$Revision: 66025 $" + +__all__ = ["FileInfoDlg", "CalcSize", "GetFileType"] + +#--------------------------------------------------------------------------# +# Imports +import os +import time +import stat +import mimetypes +import wx + +#--------------------------------------------------------------------------# +# Globals + +_ = wx.GetTranslation + +PERM_MAP = { '0' : '---', '1' : '--x', '2' : '-w-', '3' : '-wx', + '4' : 'r--', '5' : 'r-x', '6' : 'rw-', '7' : 'rwx'} + +#--------------------------------------------------------------------------# + +class FileInfoDlg(wx.MiniFrame): + """Dialog for displaying information about a file""" + def __init__(self, parent, fname='', ftype=None, bmp=wx.NullBitmap): + """Create the dialog with the information of the given file + @param parent: Parent Window + @keyword fname: File Path + @keyword ftype: Filetype label (leave None to automatically determine) + @keyword bmp: wxBitmap + + """ + self._fname = fname.split(os.path.sep)[-1] + super(FileInfoDlg, self).__init__(parent, + title="%s %s" % (self._fname, _("Info")), + style=wx.DEFAULT_DIALOG_STYLE) + + # Attributes + self._file = fname + self._ftype = ftype + self.panel = wx.Panel(self) + if bmp.IsNull(): + bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_CMN_DIALOG) + self._bmp = wx.StaticBitmap(self.panel, bitmap=bmp) + self._ftxt = wx.StaticText(self.panel) + + try: + fstat = os.stat(fname) + perm = oct(stat.S_IMODE(fstat[stat.ST_MODE])).lstrip('0') + permstr = '' + for bit in perm: + permstr += (PERM_MAP.get(bit, '---') + " ") + self._fstat = dict(mtime=time.asctime(time.localtime(fstat[stat.ST_MTIME])), + ctime=time.asctime(time.localtime(fstat[stat.ST_CTIME])), + size=CalcSize(fstat[stat.ST_SIZE]), + perm=permstr) + except Exception, msg: + self.__DoErrorLayout(str(msg)) + else: + self.__DoLayout() + + self.panel.SetAutoLayout(True) + fsizer = wx.BoxSizer(wx.VERTICAL) + fsizer.Add(self.panel, 1, wx.EXPAND) + self.SetSizer(fsizer) + self.SetAutoLayout(True) + self.SetInitialSize() + + # Event Handlers + self.Bind(wx.EVT_CLOSE, self.OnClose) + + def __DoErrorLayout(self, msg): + """Set the dialogs display up for when an error happened in + the stat call. + + """ + # Top Info + top = wx.BoxSizer(wx.HORIZONTAL) + head = wx.BoxSizer(wx.VERTICAL) + err = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_CMN_DIALOG) + bmp = wx.StaticBitmap(self.panel, bitmap=err) + lbl = wx.StaticText(self.panel, label=self._fname) + font = self.GetFont() + font.SetWeight(wx.FONTWEIGHT_BOLD) + if wx.Platform == '__WXMSW__': + font.SetPointSize(12) + else: + font.SetPointSize(13) + lbl.SetFont(font) + head.Add(lbl, 0, wx.ALIGN_LEFT) + + errlbl = wx.StaticText(self.panel, label=_("File Stat Failed")) + if wx.Platform == '__WXMSW__': + font.SetPointSize(10) + else: + font.SetPointSize(11) + font.SetWeight(wx.FONTWEIGHT_LIGHT) + errlbl.SetFont(font) + head.Add((5, 5), 0) + head.Add(errlbl, 0, wx.ALIGN_LEFT) + top.AddMany([((5, 5),), (bmp, 0, wx.ALIGN_LEFT), ((12, 12),), + (head, 0, wx.ALIGN_LEFT), ((5, 5),)]) + + # Central Area + csizer = wx.BoxSizer(wx.VERTICAL) + errbmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_CMN_DIALOG) + errbmp = wx.StaticBitmap(self.panel, bitmap=errbmp) + errmsg = wx.StaticText(self.panel, label=msg) + errmsg.SetFont(font) + errmsg.Wrap(225) + errsz = wx.BoxSizer(wx.HORIZONTAL) + errsz.AddMany([((8, 8)), (errmsg, 0, wx.ALIGN_LEFT), ((8, 8))]) + csizer.AddMany([((10, 10)), (top, 1, wx.EXPAND), ((10, 10)), + (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 0, wx.EXPAND), + ((20, 20)), (errbmp, 0, wx.ALIGN_CENTER), + ((10, 10)), (errsz, 0, wx.ALIGN_CENTER), ((10, 10)), + (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 0, wx.EXPAND), + ((10, 10))]) + self.panel.SetSizer(csizer) + + def __DoLayout(self): + """Layout the dialog""" + # Top Info + top = wx.BoxSizer(wx.HORIZONTAL) + head = wx.BoxSizer(wx.HORIZONTAL) + lbl = wx.StaticText(self.panel, label=self._fname) + fszlbl = wx.StaticText(self.panel, label=self._fstat['size']) + font = self.GetFont() + font.SetWeight(wx.FONTWEIGHT_BOLD) + if wx.Platform == '__WXMSW__': + font.SetPointSize(12) + else: + font.SetPointSize(13) + lbl.SetFont(font) + fszlbl.SetFont(font) + head.Add(lbl, 0, wx.ALIGN_LEFT) + head.AddStretchSpacer(2) + head.Add(fszlbl, 1, wx.ALIGN_RIGHT) + + modlbl = wx.StaticText(self.panel, label="%s: %s" % (_("Modified"), + self._fstat['mtime'])) + if wx.Platform == '__WXMSW__': + font.SetPointSize(10) + else: + font.SetPointSize(11) + + font.SetWeight(wx.FONTWEIGHT_LIGHT) + modlbl.SetFont(font) + lblsize = wx.BoxSizer(wx.VERTICAL) + lblsize.AddMany([(head, 1, wx.ALIGN_LEFT), ((3, 3),), + (modlbl, 0, wx.ALIGN_LEFT | wx.ALIGN_BOTTOM)]) + + top.AddMany([((5, 5)), + (self._bmp, 0, wx.ALIGN_LEFT), + ((12, 12)), (lblsize, 0, wx.ALIGN_LEFT), ((5, 5))]) + + # Central Info + center = wx.FlexGridSizer(6, 2, 3, 5) + tlbl = wx.StaticText(self.panel, label=_("Kind") + ":") + + if self._ftype is None: + self._ftxt.SetLabel(GetFileType(self._file)) + else: + self._ftxt.SetLabel(self._ftype) + + szlbl = wx.StaticText(self.panel, label=_("Size") + ":") + szval = wx.StaticText(self.panel, label=self._fstat['size']) + loclbl = wx.StaticText(self.panel, label=_("Where") + ":") + locval = wx.StaticText(self.panel, label=self._FormatLabel(self._file)) + ctime = wx.StaticText(self.panel, label=_("Created") + ":") + cval = wx.StaticText(self.panel, label=self._fstat['ctime']) + mtime = wx.StaticText(self.panel, label=_("Modified") + ":") + mval = wx.StaticText(self.panel, label=self._fstat['mtime']) + perm = wx.StaticText(self.panel, label=_("Permissions") + ":") + pval = wx.StaticText(self.panel, label=self._fstat['perm']) + for lbl in (tlbl, self._ftxt, szlbl, szval, loclbl, + locval, ctime, cval, mtime, mval, perm, pval): + lbl.SetFont(font) + lbl.Wrap(200) + center.AddMany([(tlbl, 0, wx.ALIGN_RIGHT), (self._ftxt, 0, wx.ALIGN_LEFT), + (szlbl, 0, wx.ALIGN_RIGHT), (szval, 0, wx.ALIGN_LEFT), + (loclbl, 0, wx.ALIGN_RIGHT), (locval, 0, wx.ALIGN_LEFT), + (ctime, 0, wx.ALIGN_RIGHT), (cval, 0, wx.ALIGN_LEFT), + (mtime, 0, wx.ALIGN_RIGHT), (mval, 0, wx.ALIGN_LEFT), + (perm, 0, wx.ALIGN_RIGHT), (pval, 0, wx.ALIGN_LEFT)]) + cmain = wx.BoxSizer(wx.HORIZONTAL) + cmain.AddMany([((8, 8),), (center, 0, wx.ALIGN_CENTER), ((8, 8),)]) + + # Main Layout + msizer = wx.BoxSizer(wx.VERTICAL) + msizer.AddMany([((10, 10)), (top, 0, wx.ALIGN_CENTER), ((10, 10),), + (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 1, + wx.EXPAND|wx.ALIGN_CENTER), + ((10, 10),), (cmain, 0, wx.ALIGN_TOP|wx.ALIGN_CENTER), + ((10, 10),), + (wx.StaticLine(self.panel, style=wx.LI_HORIZONTAL), 1, + wx.EXPAND|wx.ALIGN_CENTER), + ((10, 10),), + ]) + self.panel.SetSizer(msizer) + + def _FormatLabel(self, lbl): + """Format the label to a suitable width wrapping as necessary""" + lbl_len = len(lbl) + part = self.GetTextExtent(lbl)[0] / 200 + if part > 1: + split = lbl_len / part + pieces = list() + for chunk in xrange(part): + if chunk == part - 1: + pieces.append(lbl[chunk * split:]) + else: + pieces.append(lbl[chunk * split:(chunk * split + split)]) + return os.linesep.join(pieces) + return lbl + + def OnClose(self, evt): + """Destroy ourselves on closer""" + self.Destroy() + evt.Skip() + + def SetBitmap(self, bmp): + """Set the dialog bitmap + @param bmp: wxBitmap + + """ + self._bmp.SetBitmap(bmp) + self._bmp.Refresh() + self.panel.Layout() + + def SetFileTypeLabel(self, lbl): + """Set the file type label + @param lbl: string + + """ + self._ftype = lbl + self._ftxt.SetLabel(lbl) + self.panel.Layout() + +#-----------------------------------------------------------------------------# +# Utility Functions + +def CalcSize(bits): + """Calculate the best display version of the size of a given file + 1024 = 1KB, 1024KB = 1MB, ... + @param bits: size of file returned by stat + @return: formatted string representation of value + + """ + val = ('bytes', 'KB', 'MB', 'GB', 'TB') + ind = 0 + while bits > 1024: + bits = float(bits) / 1024.0 + ind += 1 + + rval = "%.2f" % bits + rval = rval.rstrip('.0') + if not rval: + rval = '0' + rval = "%s %s" % (rval, val[min(ind, 4)]) + return rval + +def GetFileType(fname): + """Get what the type of the file is + @param fname: file path + + """ + if os.path.isdir(fname): + return _("Folder") + + mtype = mimetypes.guess_type(fname)[0] + if mtype is not None: + return mtype + else: + return _("Unknown") + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/outbuff.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/outbuff.py new file mode 100644 index 0000000..6b708fe --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/outbuff.py @@ -0,0 +1,1077 @@ +############################################################################### +# Name: outbuff.py # +# Purpose: Gui and helper classes for running processes and displaying output # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: OutputBuffer + +This module contains classes that are useful for displaying output from running +tasks and processes. The classes are divided into three main categories, gui +classes, mixins, and thread classes. All the classes can be used together to +easily create multithreaded gui display classes without needing to worry about +the details and thread safety of the gui. + +For example usage of these classes see ed_log and the Editra's Launch plugin + +Class OutputBuffer: +This is the main class exported by this module. It provides a readonly output +display buffer that when used with the other classes in this module provides an +easy way to display continuous output from other processes and threads. It +provides two methods for subclasses to override if they wish to perform custom +handling. + + - Override the ApplyStyles method to do any processing and coloring of the + text as it is put in the buffer. + - Override the DoHotSpotClicked method to handle any actions to take when a + hotspot has been clicked in the buffer. + - Override the DoUpdatesEmpty method to perform any idle processing when no + new text is waiting to be processed. + +Class ProcessBufferMixin: +Mixin class for the L{OutputBuffer} class that provides handling for when an +OutputBuffer is used with a L{ProcessThread}. It provides three methods that can +be overridden in subclasses to perform extra processing. + + - DoProcessStart: Called as the process is being started in the ProcessThread, + it receives the process command string as an argument. + - DoFilterInput: Called as each chunk of output comes from the running process + use it to filter the results before displaying them in the + buffer. + - DoProcessExit: Called when the running process has exited. It receives the + processes exit code as a parameter. + +Class ProcessThread: +Thread class for running subprocesses and posting the output to an +L{OutputBuffer} via events. + +Class TaskThread: +Thread class for running a callable. For optimal performance and responsiveness +the callable should be a generator object. All results are directed to an +L{OutputBuffer} through its AppendUpdate method. + +Requirements: + * wxPython 2.8 + * Macintosh/Linux/Unix Python 2.4+ + * Windows Python 2.5+ (ctypes is needed) + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: outbuff.py 69743 2011-11-12 20:22:48Z CJP $" +__revision__ = "$Revision: 69743 $" + +__all__ = ["OutputBuffer", "OutputBufferEvent", "ProcessBufferMixin", + "ProcessThreadBase", "ProcessThread", "TaskThread", "TaskObject", + "OPB_STYLE_DEFAULT", "OPB_STYLE_INFO", + "OPB_STYLE_WARN", "OPB_STYLE_ERROR", "OPB_STYLE_MAX", + + "OPB_ERROR_NONE", "OPB_ERROR_INVALID_COMMAND", + + "edEVT_PROCESS_START", "EVT_PROCESS_START", "edEVT_TASK_START", + "EVT_TASK_START", "edEVT_UPDATE_TEXT", "EVT_UPDATE_TEXT", + "edEVT_PROCESS_EXIT", "EVT_PROCESS_EXIT", "edEVT_TASK_COMPLETE", + "EVT_TASK_COMPLETE", "edEVT_PROCESS_ERROR", "EVT_PROCESS_ERROR"] + +#--------------------------------------------------------------------------# +# Imports +import os +import sys +import time +import errno +import signal +import threading +import types +import subprocess +import wx +import wx.stc + +# Platform specific modules needed for killing processes +if subprocess.mswindows: + import msvcrt + import ctypes +else: + import shlex + import select + import fcntl + +#--------------------------------------------------------------------------# +# Globals +OUTPUTBUFF_NAME_STR = u'EditraOutputBuffer' +THREADEDBUFF_NAME_STR = u'EditraThreadedBuffer' + +# Style Codes +OPB_STYLE_DEFAULT = 0 # Default Black text styling +OPB_STYLE_INFO = 1 # Default Blue text styling +OPB_STYLE_WARN = 2 # Default Red text styling +OPB_STYLE_ERROR = 3 # Default Red/Hotspot text styling +OPB_STYLE_MAX = 3 # Highest style byte used by outputbuffer + +# All Styles +OPB_ALL_STYLES = (wx.stc.STC_STYLE_DEFAULT, wx.stc.STC_STYLE_CONTROLCHAR, + OPB_STYLE_DEFAULT, OPB_STYLE_ERROR, OPB_STYLE_INFO, + OPB_STYLE_WARN) + +# Error Codes +OPB_ERROR_NONE = 0 +OPB_ERROR_INVALID_COMMAND = -1 + +#--------------------------------------------------------------------------# + +# Event for notifying that the process has started running +# GetValue will return the command line string that started the process +edEVT_PROCESS_START = wx.NewEventType() +EVT_PROCESS_START = wx.PyEventBinder(edEVT_PROCESS_START, 1) + +# Event for notifying that a task is starting to run +edEVT_TASK_START = wx.NewEventType() +EVT_TASK_START = wx.PyEventBinder(edEVT_TASK_START, 1) + +# Event for passing output data to buffer +# GetValue returns the output text retrieved from the process +edEVT_UPDATE_TEXT = wx.NewEventType() +EVT_UPDATE_TEXT = wx.PyEventBinder(edEVT_UPDATE_TEXT, 1) + +# Event for notifying that the the process has finished and no more update +# events will be sent. GetValue will return the processes exit code +edEVT_PROCESS_EXIT = wx.NewEventType() +EVT_PROCESS_EXIT = wx.PyEventBinder(edEVT_PROCESS_EXIT, 1) + +# Event to notify that a process has completed +edEVT_TASK_COMPLETE = wx.NewEventType() +EVT_TASK_COMPLETE = wx.PyEventBinder(edEVT_TASK_COMPLETE, 1) + +# Event to notify that an error occurred in the process +edEVT_PROCESS_ERROR = wx.NewEventType() +EVT_PROCESS_ERROR = wx.PyEventBinder(edEVT_PROCESS_ERROR, 1) + +class OutputBufferEvent(wx.PyCommandEvent): + """Event for data transfer and signaling actions in the L{OutputBuffer}""" + def __init__(self, etype, eid=wx.ID_ANY, value=''): + """Creates the event object""" + super(OutputBufferEvent, self).__init__(etype, eid) + + # Attributes + self._value = value + self._errmsg = None + + #---- Properties ----# + Value = property(lambda self: self.GetValue(), + lambda self, v: setattr(self, '_value', v)) + ErrorMessage = property(lambda self: self.GetErrorMessage(), + lambda self, msg: self.SetErrorMessage(msg)) + + def GetValue(self): + """Returns the value from the event. + @return: the value of this event + + """ + return self._value + + def GetErrorMessage(self): + """Get the error message value + @return: Exception traceback string or None + + """ + return self._errmsg + + def SetErrorMessage(self, msg): + """Set the error message value + @param msg: Exception traceback string + + """ + try: + tmsg = unicode(msg) + except: + tmsg = None + self._errmsg = msg + +#--------------------------------------------------------------------------# + +class OutputBuffer(wx.stc.StyledTextCtrl): + """OutputBuffer is a general purpose output display for showing text. It + provides an easy interface for the buffer to interact with multiple threads + that may all be sending updates to the buffer at the same time. Methods for + styling and filtering output are also available. + + """ + def __init__(self, parent, id=wx.ID_ANY, + pos=wx.DefaultPosition, + size=wx.DefaultSize, + style=wx.BORDER_SUNKEN, + name=OUTPUTBUFF_NAME_STR): + super(OutputBuffer, self).__init__(parent, id, pos, + size, style, name) + + # Attributes + self._mutex = threading.Lock() + self._updating = threading.Condition(self._mutex) + self._updates = list() + self._timer = wx.Timer(self) + self._line_buffer = -1 + self._colors = dict(defaultb=(255, 255, 255), defaultf=(0, 0, 0), + errorb=(255, 255, 255), errorf=(255, 0, 0), + infob=(255, 255, 255), infof=(0, 0, 255), + warnb=(255, 255, 255), warnf=(255, 0, 0)) + + # Setup + self.__ConfigureSTC() + + # Event Handlers + self.Bind(wx.EVT_TIMER, self.OnTimer) + self.Bind(wx.stc.EVT_STC_HOTSPOT_CLICK, self._OnHotSpot) + + def __del__(self): + """Ensure timer is cleaned up when we are deleted""" + if self._timer.IsRunning(): + self._timer.Stop() + + def __ConfigureSTC(self): + """Setup the stc to behave/appear as we want it to + and define all styles used for giving the output context. + @todo: make more of this configurable + + """ + self.SetMargins(3, 3) + self.SetMarginWidth(0, 0) + self.SetMarginWidth(1, 0) + + # To improve performance at cost of memory cache the document layout + self.SetLayoutCache(wx.stc.STC_CACHE_DOCUMENT) + self.SetUndoCollection(False) # Don't keep undo history + self.SetReadOnly(True) + self.SetCaretWidth(0) + + if wx.Platform == '__WXMSW__': + self.SetEOLMode(wx.stc.STC_EOL_CRLF) + else: + self.SetEOLMode(wx.stc.STC_EOL_LF) + + #self.SetEndAtLastLine(False) + self.SetVisiblePolicy(1, wx.stc.STC_VISIBLE_STRICT) + + # Define Styles + highlight = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) + self.SetSelBackground(True, highlight) + if sum(highlight.Get()) < 384: + self.SetSelForeground(True, wx.WHITE) + else: + self.SetSelForeground(True, wx.BLACK) + self.__SetupStyles() + + def FlushBuffer(self): + """Flush the update buffer + @postcondition: The update buffer is empty + + """ + self._updating.acquire() + self.SetReadOnly(False) + txt = u''.join(self._updates[:]) + start = self.GetLength() + if u'\0' in txt: + # HACK: handle displaying NULLs in the STC + self.AddStyledText('\0'.join(txt.encode('utf-8'))+'\0') + else: + self.AppendText(txt) + self.GotoPos(self.GetLength()) + self._updates = list() + self.ApplyStyles(start, txt) + self.SetReadOnly(True) + self.RefreshBufferedLines() + self._updating.release() + + def __SetupStyles(self, font=None): + """Setup the default styles of the text in the buffer + @keyword font: wx.Font to use or None to use default + + """ + if font is None: + if wx.Platform == '__WXMAC__': + fsize = 11 + else: + fsize = 10 + + font = wx.Font(fsize, wx.FONTFAMILY_MODERN, + wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) + style = (font.GetFaceName(), font.GetPointSize(), "#FFFFFF") + wx.stc.StyledTextCtrl.SetFont(self, font) + + # Custom Styles + self.StyleSetSpec(OPB_STYLE_DEFAULT, + "face:%s,size:%d,fore:#000000,back:%s" % style) + self.StyleSetSpec(OPB_STYLE_INFO, + "face:%s,size:%d,fore:#0000FF,back:%s" % style) + self.StyleSetSpec(OPB_STYLE_WARN, + "face:%s,size:%d,fore:#FF0000,back:%s" % style) + self.StyleSetSpec(OPB_STYLE_ERROR, + "face:%s,size:%d,fore:#FF0000,back:%s" % style) + self.StyleSetHotSpot(OPB_STYLE_ERROR, True) + + # Default Styles + self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, \ + "face:%s,size:%d,fore:#000000,back:%s" % style) + self.StyleSetSpec(wx.stc.STC_STYLE_CONTROLCHAR, \ + "face:%s,size:%d,fore:#000000,back:%s" % style) + self.Colourise(0, -1) + + def _OnHotSpot(self, evt): + """Handle hotspot clicks""" + pos = evt.GetPosition() + self.DoHotSpotClicked(pos, self.LineFromPosition(pos)) + + #---- Public Member Functions ----# + + def AppendUpdate(self, value): + """Buffer output before adding to window. This method can safely be + called from non gui threads to add updates to the buffer, that will + be displayed during the next idle period. + @param value: update string to append to stack + + """ + self._updating.acquire() + if not (type(value) is types.UnicodeType): + value = value.decode(sys.getfilesystemencoding()) + self._updates.append(value) + self._updating.release() + + def ApplyStyles(self, start, txt): + """Apply coloring to text starting at start position. + Override this function to do perform any styling that you want + done on the text. + @param start: Start position of text that needs styling in the buffer + @param txt: The string of text that starts at the start position in the + buffer. + + """ + pass + + def CanCopy(self): + """Is it possible to copy text right now + @return: bool + + """ + sel = self.GetSelection() + return sel[0] != sel[1] + + def CanCut(self): + """Is it possible to Cut + @return: bool + + """ + return not self.GetReadOnly() + + def Clear(self): + """Clear the Buffer""" + self.SetReadOnly(False) + self.ClearAll() + self.EmptyUndoBuffer() + self.SetReadOnly(True) + + def DoHotSpotClicked(self, pos, line): + """Action to perform when a hotspot region is clicked in the buffer. + Override this function to provide handling of hotspots. + @param pos: Position in buffer of where the click occurred. + @param line: Line in which the click occurred (zero based index) + + """ + pass + + def DoUpdatesEmpty(self): + """Called when update stack is empty + Override this function to perform actions when there are no updates + to process. It can be used for things such as temporarily stopping + the timer or performing idle processing. + + """ + pass + + def GetDefaultBackground(self): + """Get the default text style background color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['defaultb']) + + def GetDefaultForeground(self): + """Get the default text style foreground color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['defaultf']) + + def GetErrorBackground(self): + """Get the error text style background color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['errorb']) + + def GetErrorForeground(self): + """Get the error text style foreground color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['errorf']) + + def GetInfoBackground(self): + """Get the info text style background color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['infob']) + + def GetInfoForeground(self): + """Get the info text style foreground color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['infof']) + + def GetWarningBackground(self): + """Get the warning text style background color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['warnb']) + + def GetWarningForeground(self): + """Get the warning text style foreground color + @return: wx.Colour + + """ + return wx.Colour(*self._colors['warnf']) + + def GetUpdateQueue(self): + """Gets a copy of the current update queue""" + self._updating.acquire() + val = list(self._updates) + self._updating.release() + return val + + def IsRunning(self): + """Return whether the buffer is running and ready for output + @return: bool + + """ + return self._timer.IsRunning() + + def OnTimer(self, evt): + """Process and display text from the update buffer + @note: this gets called many times while running thus needs to + return quickly to avoid blocking the ui. + + """ + if len(self._updates): + self.FlushBuffer() + elif evt is not None: + self.DoUpdatesEmpty() + else: + pass + + def RefreshBufferedLines(self): + """Refresh and readjust the lines in the buffer to fit the current + line buffering limits. + @postcondition: Oldest lines are removed until we are back within the + buffer limit bounds. + + """ + if self._line_buffer < 0: + return + + self.SetReadOnly(False) + while self.GetLineCount() > self._line_buffer: + self.SetCurrentPos(0) + self.LineDelete() + self.SetReadOnly(True) + self.SetCurrentPos(self.GetLength()) + + def SetDefaultColor(self, fore=None, back=None): + """Set the colors for the default text style + @keyword fore: Foreground Color + @keyword back: Background Color + + """ + if fore is not None: + self.StyleSetForeground(wx.stc.STC_STYLE_DEFAULT, fore) + self.StyleSetForeground(wx.stc.STC_STYLE_CONTROLCHAR, fore) + self.StyleSetForeground(OPB_STYLE_DEFAULT, fore) + self._colors['defaultf'] = fore.Get() + + if back is not None: + self.StyleSetBackground(wx.stc.STC_STYLE_DEFAULT, back) + self.StyleSetBackground(wx.stc.STC_STYLE_CONTROLCHAR, back) + self.StyleSetBackground(OPB_STYLE_DEFAULT, back) + self._colors['defaultb'] = back.Get() + + def SetErrorColor(self, fore=None, back=None): + """Set color for error text + @keyword fore: Foreground Color + @keyword back: Background Color + + """ + if fore is not None: + self.StyleSetForeground(OPB_STYLE_ERROR, fore) + self._colors['errorf'] = fore.Get() + + if back is not None: + self.StyleSetBackground(OPB_STYLE_ERROR, back) + self._colors['errorb'] = back.Get() + + def SetInfoColor(self, fore=None, back=None): + """Set color for info text + @keyword fore: Foreground Color + @keyword back: Background Color + + """ + if fore is not None: + self.StyleSetForeground(OPB_STYLE_INFO, fore) + self._colors['infof'] = fore.Get() + + if back is not None: + self.StyleSetBackground(OPB_STYLE_INFO, back) + self._colors['infob'] = back.Get() + + def SetWarningColor(self, fore=None, back=None): + """Set color for warning text + @keyword fore: Foreground Color + @keyword back: Background Color + + """ + if fore is not None: + self.StyleSetForeground(OPB_STYLE_WARN, fore) + self._colors['warnf'] = fore.Get() + + if back is not None: + self.StyleSetBackground(OPB_STYLE_WARN, back) + self._colors['warnb'] = back.Get() + + def SetFont(self, font): + """Set the font used by all text in the buffer + @param font: wxFont + + """ + for style in OPB_ALL_STYLES: + self.StyleSetFont(style, font) + + def SetLineBuffering(self, num): + """Set how many lines the buffer should keep for display. + @param num: int (-1 == unlimited) + + """ + self._line_buffer = num + self.RefreshBufferedLines() + + def SetText(self, text): + """Set the text that is shown in the buffer + @param text: text string to set as buffers current value + + """ + self.SetReadOnly(False) + wx.stc.StyledTextCtrl.SetText(self, text) + self.SetReadOnly(True) + + def Start(self, interval): + """Start the window's timer to check for updates + @param interval: interval in milliseconds to do updates + + """ + self._timer.Start(interval) + + def Stop(self): + """Stop the update process of the buffer""" + # Dump any output still left in tmp buffer before stopping + self.OnTimer(None) + self._timer.Stop() + self.SetReadOnly(True) + +#-----------------------------------------------------------------------------# + +class ProcessBufferMixin: + """Mixin class for L{OutputBuffer} to handle events + generated by a L{ProcessThread}. + + """ + def __init__(self, update=100): + """Initialize the mixin + @keyword update: The update interval speed in msec + + """ + # Attributes + self._rate = update + + # Event Handlers + self.Bind(EVT_PROCESS_START, self._OnProcessStart) + self.Bind(EVT_UPDATE_TEXT, self._OnProcessUpdate) + self.Bind(EVT_PROCESS_EXIT, self._OnProcessExit) + self.Bind(EVT_PROCESS_ERROR, self._OnProcessError) + + def _OnProcessError(self, evt): + """Handle EVT_PROCESS_ERROR""" + self.DoProcessError(evt.GetValue(), evt.GetErrorMessage()) + + def _OnProcessExit(self, evt): + """Handles EVT_PROCESS_EXIT""" + self.DoProcessExit(evt.GetValue()) + + def _OnProcessStart(self, evt): + """Handles EVT_PROCESS_START""" + self.DoProcessStart(evt.GetValue()) + self.Start(self._rate) + + def _OnProcessUpdate(self, evt): + """Handles EVT_UPDATE_TEXT""" + txt = self.DoFilterInput(evt.GetValue()) + self.AppendUpdate(txt) + + def DoFilterInput(self, txt): + """Override this method to do an filtering on input that is sent to + the buffer from the process text. The return text is what is put in + the buffer. + @param txt: incoming update text + @return: string + + """ + return txt + + def DoProcessError(self, code, excdata=None): + """Override this method to do any ui notification of when errors happen + in running the process. + @param code: an OBP error code + @keyword excdata: Exception Data from process error + @return: None + + """ + pass + + def DoProcessExit(self, code=0): + """Override this method to do any post processing after the running + task has exited. Typically this is a good place to call + L{OutputBuffer.Stop} to stop the buffers timer. + @keyword code: Exit code of program + @return: None + + """ + self.Stop() + + def DoProcessStart(self, cmd=''): + """Override this method to do any pre-processing before starting + a processes output. + @keyword cmd: Command used to start program + @return: None + + """ + pass + + def SetUpdateInterval(self, value): + """Set the rate at which the buffer outputs update messages. Set to + a higher number if the process outputs large amounts of text at a very + high rate. + @param value: rate in milliseconds to do updates on + + """ + self._rate = value + +#-----------------------------------------------------------------------------# + +class ProcessThreadBase(threading.Thread): + """Base Process Thread + Override DoPopen in subclasses. + + """ + def __init__(self, parent): + super(ProcessThreadBase, self).__init__() + + # Attributes + self.abort = False # Abort Process + self._proc = None + self._parent = parent # Parent Window/Event Handler + self._sig_abort = signal.SIGTERM # default signal to kill process + self._last_cmd = u"" # Last run command + + #---- Properties ----# + LastCommand = property(lambda self: self._last_cmd, + lambda self, val: setattr(self, '_last_cmd', val)) + Parent = property(lambda self: self._parent) + Process = property(lambda self: self._proc) + + def __DoOneRead(self): + """Read one line of output and post results. + @return: bool (True if more), (False if not) + + """ + if subprocess.mswindows: + # Windows nonblocking pipe read implementation + read = u'' + try: + handle = msvcrt.get_osfhandle(self._proc.stdout.fileno()) + avail = ctypes.c_long() + ctypes.windll.kernel32.PeekNamedPipe(handle, None, 0, 0, + ctypes.byref(avail), None) + if avail.value > 0: + read = self._proc.stdout.read(avail.value) + if read.endswith(os.linesep): + read = read[:-1 * len(os.linesep)] + else: + if self._proc.poll() is None: + time.sleep(1) + return True + else: + # Process has Exited + return False + except ValueError, msg: + return False + except (subprocess.pywintypes.error, Exception), msg: + if msg[0] in (109, errno.ESHUTDOWN): + return False + else: + # OSX and Unix nonblocking pipe read implementation + if self._proc.stdout is None: + return False + + flags = fcntl.fcntl(self._proc.stdout, fcntl.F_GETFL) + if not self._proc.stdout.closed: + fcntl.fcntl(self._proc.stdout, + fcntl.F_SETFL, + flags|os.O_NONBLOCK) + + try: + try: + if not select.select([self._proc.stdout], [], [], 1)[0]: + return True + + read = self._proc.stdout.read(4096) + if read == '': + return False + except IOError, msg: + return False + finally: + if not self._proc.stdout.closed: + fcntl.fcntl(self._proc.stdout, fcntl.F_SETFL, flags) + + # Ignore encoding errors and return an empty line instead + try: + result = read.decode(sys.getfilesystemencoding()) + except UnicodeDecodeError: + result = os.linesep + + if self.Parent: + evt = OutputBufferEvent(edEVT_UPDATE_TEXT, self.Parent.GetId(), result) + wx.PostEvent(self.Parent, evt) + return True + else: + return False # Parent is dead no need to keep running + + def __KillPid(self, pid): + """Kill a process by process id, causing the run loop to exit + @param pid: Id of process to kill + + """ + # Dont kill if the process if it is the same one we + # are running under (i.e we are running a shell command) + if pid == os.getpid(): + return + + if wx.Platform != '__WXMSW__': + # Close output pipe(s) + try: + try: + self._proc.stdout.close() + except Exception, msg: + pass + finally: + self._proc.stdout = None + + # Try to kill the group + try: + os.kill(pid, self._sig_abort) + except OSError, msg: + pass + + # If still alive shoot it again + if self._proc.poll() is not None: + try: + os.kill(-pid, signal.SIGKILL) + except OSError, msg: + pass + + # Try and wait for it to cleanup + try: + os.waitpid(pid, os.WNOHANG) + except OSError, msg: + pass + + else: + # 1 == PROCESS_TERMINATE + handle = ctypes.windll.kernel32.OpenProcess(1, False, pid) + ctypes.windll.kernel32.TerminateProcess(handle, -1) + ctypes.windll.kernel32.CloseHandle(handle) + + #---- Public Member Functions ----# + def Abort(self, sig=signal.SIGTERM): + """Abort the running process and return control to the main thread""" + self._sig_abort = sig + self.abort = True + + def DoPopen(self): + """Open the process + Override in a subclass to implement custom process opening + @return: subprocess.Popen instance + + """ + raise NotImplementedError("Must implement DoPopen in subclasses!") + + def run(self): + """Run the process until finished or aborted. Don't call this + directly instead call self.start() to start the thread else this will + run in the context of the current thread. + @note: overridden from Thread + + """ + err = None + try: + self._proc = self.DoPopen() + except OSError, msg: + # NOTE: throws WindowsError on Windows which is a subclass of + # OSError, so it will still get caught here. + if self.Parent: + err = OutputBufferEvent(edEVT_PROCESS_ERROR, + self.Parent.GetId(), + OPB_ERROR_INVALID_COMMAND) + err.SetErrorMessage(msg) + + if self.Parent: + evt = OutputBufferEvent(edEVT_PROCESS_START, + self.Parent.GetId(), + self.LastCommand) + wx.PostEvent(self.Parent, evt) + + # Read from stdout while there is output from process + while not err and True: + if self.abort: + self.__KillPid(self.Process.pid) + self.__DoOneRead() + more = False + break + else: + more = False + try: + more = self.__DoOneRead() + except wx.PyDeadObjectError: + # Our parent window is dead so kill process and return + self.__KillPid(self.Process.pid) + return + + if not more: + break + + # Notify of error in running the process + if err is not None: + if self.Parent: + wx.PostEvent(self.Parent, err) + result = -1 + else: + try: + result = self.Process.wait() + except OSError: + result = -1 + + # Notify that process has exited + # Pack the exit code as the events value + if self.Parent: + evt = OutputBufferEvent(edEVT_PROCESS_EXIT, self.Parent.GetId(), result) + wx.PostEvent(self.Parent, evt) + +class ProcessThread(ProcessThreadBase): + """Run a subprocess in a separate thread. Thread posts events back + to parent object on main thread for processing in the ui. + @see: EVT_PROCESS_START, EVT_PROCESS_END, EVT_UPDATE_TEXT + + """ + def __init__(self, parent, command, fname='', + args=list(), cwd=None, env=dict(), + use_shell=True): + """Initialize the ProcessThread object + Example: + >>> myproc = ProcessThread(myframe, '/usr/local/bin/python', + 'hello.py', '--version', '/Users/me/home/') + >>> myproc.start() + + @param parent: Parent Window/EventHandler to receive the events + generated by the process. + @param command: Command string to execute as a subprocess. + @keyword fname: Filename or path to file to run command on. + @keyword args: Argument list or string to pass to use with fname arg. + @keyword cwd: Directory to execute process from or None to use current + @keyword env: Environment to run the process in (dictionary) or None to + use default. + @keyword use_shell: Specify whether a shell should be used to launch + program or run directly + + """ + super(ProcessThread, self).__init__(parent) + + if isinstance(args, list): + args = u' '.join([arg.strip() for arg in args]) + + # Attributes + self._cwd = cwd # Path at which to run from + self._cmd = dict(cmd=command, file=fname, args=args) + self._use_shell = use_shell + + # Make sure the environment is sane it must be all strings + nenv = dict(env) # make a copy to manipulate + for k, v in env.iteritems(): + if isinstance(v, types.UnicodeType): + nenv[k] = v.encode(sys.getfilesystemencoding()) + elif not isinstance(v, basestring): + nenv.pop(k) + self._env = nenv + + # Setup + self.setDaemon(True) + + def DoPopen(self): + """Open the process + @return: subprocess.Popen instance + + """ + # using shell, Popen will need a string, else it must be a sequence + # use shlex for complex command line tokenization/parsing + command = u' '.join([item.strip() for item in [self._cmd['cmd'], + self._cmd['file'], + self._cmd['args']]]) + command = command.strip() + # TODO: exception handling and notification to main thread + # when encoding fails. + command = command.encode(sys.getfilesystemencoding()) + if not self._use_shell and not subprocess.mswindows: + # Note: shlex does not support Unicode + command = shlex.split(command) + + # TODO: if a file path to the exe has any spaces in it on Windows + # and use_shell is True then the command will fail. Must force + # to False under this condition. + use_shell = self._use_shell + # TODO: See about supporting use_shell on Windows it causes lots of + # issues with gui apps and killing processes when it is True. + if use_shell and subprocess.mswindows: + suinfo = subprocess.STARTUPINFO() + # Don't set this flag if we are not using the shell on + # Windows as it will cause any gui app to not show on the + # display! + #TODO: move this into common library as it is needed + # by most code that uses subprocess + if hasattr(subprocess, 'STARTF_USESHOWWINDOW'): + suinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + else: + try: + from win32process import STARTF_USESHOWWINDOW + suinfo.dwFlags |= STARTF_USESHOWWINDOW + except ImportError: + # Give up and try hard coded value from Windows.h + suinfo.dwFlags |= 0x00000001 + else: + suinfo = None + + proc = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + shell=use_shell, + cwd=self._cwd, + env=self._env, + startupinfo=suinfo) + self.LastCommand = command # Set last run command + return proc + + def SetArgs(self, args): + """Set the args to pass to the command + @param args: list or string of program arguments + + """ + if isinstance(args, list): + u' '.join(item.strip() for item in args) + self._cmd['args'] = args.strip() + + def SetCommand(self, cmd): + """Set the command to execute + @param cmd: Command string + + """ + self._cmd['cmd'] = cmd + + def SetFilename(self, fname): + """Set the filename to run the command on + @param fname: string or Unicode + + """ + self._cmd['file'] = fname + +#-----------------------------------------------------------------------------# + +class TaskThread(threading.Thread): + """Run a task in its own thread.""" + def __init__(self, parent, task, *args, **kwargs): + """Initialize the TaskThread. All *args and **kwargs are passed + to the task. + + @param parent: Parent Window/EventHandler to receive the events + generated by the process. + @param task: callable should be a generator object and must be iterable + + """ + super(TaskThread, self).__init__() + assert isinstance(parent, OutputBuffer) + + self._task = TaskObject(parent, task, *args, **kwargs) + + def run(self): + self._task.DoTask() + + def Cancel(self): + self._task.Cancel() + +class TaskObject(object): + """Run a task in its own thread.""" + def __init__(self, parent, task, *args, **kwargs): + """Initialize the TaskObject. All *args and **kwargs are passed + to the task. + + @param parent: Parent Window/EventHandler to receive the events + generated by the process. + @param task: callable should be a generator object and must be iterable + + """ + super(TaskObject, self).__init__() + + assert isinstance(parent, OutputBuffer) + + # Attributes + self.cancel = False # Abort task + self._parent = parent # Parent Window/Event Handler + self.task = task # Task method to run + self._args = args + self._kwargs = kwargs + + def DoTask(self): + """Start running the task""" + # Notify that task is beginning + evt = OutputBufferEvent(edEVT_TASK_START, self._parent.GetId()) + wx.PostEvent(self._parent, evt) + time.sleep(.5) # Give the event a chance to be processed + + # Run the task and post the results + for result in self.task(*self._args, **self._kwargs): + self._parent.AppendUpdate(result) + if self.cancel: + break + + # Notify that the task is finished + evt = OutputBufferEvent(edEVT_TASK_COMPLETE, self._parent.GetId()) + wx.PostEvent(self._parent, evt) + + def Cancel(self): + """Cancel the running task""" + self.cancel = True diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/panelbox.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/panelbox.py new file mode 100644 index 0000000..c3f421a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/panelbox.py @@ -0,0 +1,445 @@ +############################################################################### +# Name: panelbox.py # +# Purpose: Advanced listbox control # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: PanelBox + +Class PanelBox: + +ListBox like container class that accepts custom panels as items in the list. + +Class PanelBoxItemBase: + +Base class for all PanelBoxItems. Provides the basic functionality for a custom +subclass to interact with the PanelBox container list. + +Class PanelBoxItem: + +Simple PanelBoxItem that has support for displaying an Icon, Main text, and a +a user defined sub item. + ++-------------------------+ +| | +| ICON label | +| sub item | ++-------------------------+ + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: panelbox.py 67123 2011-03-04 00:02:35Z CJP $" +__revision__ = "$Revision: 67123 $" + +#--------------------------------------------------------------------------# +# Imports +import wx +import wx.lib.scrolledpanel as scrolled + +#--------------------------------------------------------------------------# + +edEVT_ITEM_SELECTED = wx.NewEventType() +EVT_ITEM_SELECTED = wx.PyEventBinder(edEVT_ITEM_SELECTED, 1) + +class PanelBoxEventEvent(wx.PyCommandEvent): + """Panel Box Event Object""" + pass + +#--------------------------------------------------------------------------# + +class PanelBox(scrolled.ScrolledPanel): + """Scrolled container window for managing and displaying PanelBox items""" + def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=wx.HSCROLL|wx.VSCROLL, + name=u"PanelBox"): + super(PanelBox, self).__init__(parent, id, pos, size, style, name) + + # Attributes + self._items = list() + self._last_sel = -1 + self._sizer = wx.BoxSizer(wx.VERTICAL) + + # Setup + bkgrnd = wx.SystemSettings.GetColour(wx.SYS_COLOUR_LISTBOX) + self.SetBackgroundColour(bkgrnd) + + self.SetSizer(self._sizer) + self.SetAutoLayout(True) + + self.SetupScrolling() + + # Event Handlers +# self.Bind(wx.EVT_KEY_UP, self.OnNavigate) + self.GetParent().Bind(wx.EVT_KEY_UP, self.OnNavigate) + + #---- Event Handlers ----# + + def OnItemClicked(self, evt): + """Callback from when children are clicked on + @param evt: wx.MouseEvent + + """ + item = evt.GetEventObject() + selected = item.IsSelected() + idx = self.FindIndex(item) + if idx == -1: + return + + if evt.CmdDown(): + # Add/Remove from selection + item.SetSelection(not selected) + elif evt.ShiftDown(): + # Select all items between this item and the next selected one + if idx < self._last_sel: + inc = -1 + else: + inc = 1 + + for index in range(self._last_sel, idx + inc, inc): + self.SetSelection(index, True) + else: + # Move selection to this item + self.ClearSelections() + + if not selected: + item.SetSelection(True) + + if not selected: + self._last_sel = idx + else: + self._last_sel = -1 + + def OnNavigate(self, evt): + """Handle navigation key events""" + key_code = evt.GetKeyCode() + nsel = None + isup = False + if key_code == wx.WXK_UP: + if self._last_sel in (0, -1): + nsel = len(self._items) - 1 + else: + nsel = self._last_sel - 1 + isup = True + elif key_code == wx.WXK_DOWN: + if self._last_sel in (-1, len(self._items) - 1): + nsel = 0 + else: + nsel = self._last_sel + 1 + else: + evt.Skip() + return + + if evt.ShiftDown(): + self.SetSelection(nsel, True) + else: + self.ClearSelections() + self.SetSelection(nsel, True) + + evt.Skip() + + #---- Public Api ----# + def AppendItem(self, item): + """Append an item to the list + @param item: PanelBoxItem + + """ + self._items.append(item) + self._sizer.Add(item, 0, wx.EXPAND) + item.Realize() + + def ClearSelections(self): + """Unselect all items""" + for item in self._items: + item.SetSelection(False) + + def DeleteAllItems(self): + """Delete all the items in the list""" + for item in self._items: + self._sizer.Remove(item) + try: + item.Destroy() + except wx.PyDeadObjectError: + pass + + del self._items + self._items = list() + self.Layout() + + def FindIndex(self, item): + """Find the index of a given L{PanelBoxItem} + @param item: instance of PanelBoxItemBase + @return: int (-1 on failure) + + """ + for idx, pbitem in enumerate(self._items): + if pbitem is item: + return idx + else: + return -1 + + def GetItemCount(self): + """Get the number of items in the control + @return: int + + """ + return len(self._items) + + def GetItems(self): + """Get the list of items held by this control + @return: list of PanelBoxItems + @todo: should probably return a list of shadow items so that orignals + are not modified. + + """ + return self._items + + def GetSelection(self): + """Get the (first) selected item""" + for item in self._items: + if item.IsSelected(): + return item + else: + return None + + def GetSelections(self): + """Get the list of selected items + @return: list + + """ + return [item for item in self._items if item.IsSelected()] + + def InsertItem(self, index, item): + """Insert an item into the list + @param index: index to insert at + @param item: PanelBoxItem + + """ + if index <= len(self._items): + self._items.insert(index, item) + self._sizer.Insert(index, item, 0, wx.EXPAND) + else: + raise IndexError, "Index %d: out of range" % index + + def Remove(self, index): + """Remove an item from the list + @param index: item index + + """ + if index < len(self._items): + item = self._items.pop(index) + self._sizer.Remove(item) + self.Layout() + else: + raise IndexError, "Index %d: out of range" % index + + def RemoveAll(self): + """Remove all items from the list""" + for item in self._items: + self._sizer.Remove(item) + + del self._items + self._items = list() + + self.Layout() + + def SetSelection(self, idx, select=True): + """Set the selection on a given index + @param idx: int + @keyword select: bool + + """ + if idx < len(self._items): + item = self._items[idx] + item.SetSelection(select) + self._last_sel = idx + else: + raise IndexError, "Index out of range: %d > %d" (idx, len(self._items)) + +#--------------------------------------------------------------------------# + +class PanelBoxItemBase(wx.PyPanel): + """Base L{PanelBox} Item""" + def __init__(self, parent): + """Create a PanelBoxItem""" + super(PanelBoxItemBase, self).__init__(parent, + style=wx.NO_BORDER|wx.TAB_TRAVERSAL) + + # Attributes + self._selected = False + + # Event Handlers + self.Bind(wx.EVT_PAINT, self.OnPaint) +# self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) + + def _UpdateForeground(self, color): + """Update foreground colors when selection changes + @param color: selection color + @todo: should cache text's original color to restore + on de-selection. + + """ + if sum(color.Get()[:3]) < (127 * 3): + ncolor = wx.WHITE + else: + ncolor = wx.BLACK + + for child in self.GetChildren(): + if hasattr(child, 'SetForegroundColour') and \ + not isinstance(child, wx.Button): + child.SetForegroundColour(ncolor) + + def OnKeyUp(self, evt): + """Handle key navigation events""" + self.GetParent().OnNavigate(evt) + evt.Skip() + + def OnLeftUp(self, evt): + """Handle when the item is clicked on""" + e_obj = evt.GetEventObject() + evt.SetEventObject(self) + self.GetParent().OnItemClicked(evt) + evt.SetEventObject(e_obj) + evt.Skip() + + def OnMouseWheel(self, evt): + """Relay the mouse wheel events to the panel box""" + self.GetParent().GetEventHandler().ProcessEvent(evt) + evt.Skip() + + def OnPaint(self, evt): + """Paint the items background""" + dc = wx.PaintDC(self) + rect = self.GetClientRect() + +# if self.IsSelected(): +# color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) +# dc.SetBrush(wx.Brush(color)) +# dc.SetPen(wx.TRANSPARENT_PEN) +# dc.DrawRectangle(*rect) +# else: +# col2 = wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX) +# dc.SetBackground(wx.Brush(col2)) +# dc.SetBrush(wx.Brush(col2)) +# dc.SetPen(wx.TRANSPARENT_PEN) +# dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height - 1) + + pcolor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE) + dc.SetPen(wx.Pen(pcolor)) + dc.DrawLine(rect.x, rect.bottom, rect.right, rect.bottom) + + def IsSelected(self): + """Is this item selected + @return: bool + + """ + return self._selected + + def Realize(self): + """Finalize initialization of the panel item""" + for child in self.GetChildren(): + child.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + + def SetSelection(self, select=False): + """Set the selection state on this item + @keyword select: bool + + """ + self._selected = select + if self._selected: + color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) + else: + color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_LISTBOX) + self.SetBackgroundColour(color) + self._UpdateForeground(color) + self.Refresh() + +#--------------------------------------------------------------------------# + +class PanelBoxItem(PanelBoxItemBase): + """L{PanelBox} Item that has an icon, main label text and sub label + +-------------------------+ + | | + | ICON label | + | sub item | + +-------------------------+ + + """ + def __init__(self, parent, bmp=None, label=u'', sub=None): + """Create teh PanelBoxItem + @param parent: L{PanelBox} + @keyword bmp: wx.Bitmap + @keyword label: string + @keyword sub: Window object or None + + """ + super(PanelBoxItem, self).__init__(parent) + + # Attributes + self._bmp = bmp + self._label = label + self._sub = sub + + # Layout + self.__DoLayout() + self.SetAutoLayout(True) + + def __DoLayout(self): + """Layout the control""" + vsizer = wx.BoxSizer(wx.VERTICAL) + hsizer = wx.BoxSizer(wx.HORIZONTAL) + + hsizer.Add((8, 8), 0) + if self._bmp is not None: + self._bmp = wx.StaticBitmap(self, bitmap=self._bmp) + hsizer.Add(self._bmp, 0, wx.ALIGN_CENTER_VERTICAL) + hsizer.Add((5, 5), 0) + + # Add Label Text + isizer = wx.BoxSizer(wx.VERTICAL) + self._label = wx.StaticText(self, label=self._label) + isizer.Add(self._label, 0, wx.ALIGN_LEFT) + if self._sub is not None: + isizer.Add((3, 3), 0) + + # Add Subwindow if one is defined + if self._sub is not None: + self._sub.Reparent(self) + s_sizer = wx.BoxSizer(wx.HORIZONTAL) + s_sizer.Add(self._sub, 1, wx.EXPAND) + isizer.Add(s_sizer, 1, wx.EXPAND) + + hsizer.Add(isizer, 1, wx.ALIGN_CENTER_VERTICAL) + hsizer.Add((8, 8), 0) + vsizer.AddMany([((8, 8), 0), (hsizer, 0, wx.EXPAND), ((8, 8), 0)]) + self.SetSizer(vsizer) + + def SetBitmap(self, bmp): + """Set the items image + param bmp: wx.Bitmap + + """ + self._bmp.SetBitmap(bmp) + self._bmp.Refresh() + self.Layout() + + def SetLabel(self, lbl): + """Set the label text + @param lbl: string + + """ + self._lbl.SetLabel(lbl) + self._lbl.Refresh() + self.Layout() + + def SetSecondaryCtrl(self, ctrl): + """Set the secondary control + @param ctrl: wxWindow + + """ + pass diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/platebtn.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/platebtn.py new file mode 100644 index 0000000..8577c5d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/platebtn.py @@ -0,0 +1,724 @@ +############################################################################### +# Name: platebtn.py # +# Purpose: PlateButton is a flat label button with support for bitmaps and # +# drop menu. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Control Library: PlateButton + +The PlateButton is a custom owner drawn flat button, that in many ways emulates +the buttons found the bookmark bar of the Safari browser. It can be used as a +drop in replacement for wx.Button/wx.BitmapButton under most circumstances. It +also offers a wide range of options for customizing its appearance, a +description of each of the main style settings is listed below. + +Main Button Styles: +Any combination of the following values may be passed to the constructor's style +keyword parameter. + +PB_STYLE_DEFAULT: +Creates a flat label button with rounded corners, the highlight for mouse over +and press states is based off of the hightlight color from the systems current +theme. + +PB_STYLE_GRADIENT: +The highlight and press states are drawn with gradient using the current +highlight color. + +PB_STYLE_SQUARE: +Instead of the default rounded shape use a rectangular shaped button with +square edges. + +PB_STYLE_NOBG: +This style only has an effect on Windows but does not cause harm to use on the +platforms. It should only be used when the control is shown on a panel or other +window that has a non solid color for a background. i.e a gradient or image is +painted on the background of the parent window. If used on a background with +a solid color it may cause the control to loose its transparent appearance. + +PB_STYLE_DROPARROW: +Add a drop button arrow to the button that will send a separate event when +clicked on. + +Other attributes can be configured after the control has been created. The +settings that are currently available are as follows: + + - SetBitmap: Change/Add the bitmap at any time and the control will resize and + refresh to display it. + - SetLabelColor: Explicitly set text colors + - SetMenu: Set the button to have a popupmenu. When a menu is set a small drop + arrow will be drawn on the button that can then be clicked to show + a menu. + - SetPressColor: Use a custom highlight color + + +Overridden Methods Inherited from PyControl: + + - SetFont: Changing the font is one way to set the size of the button, by + default the control will inherit its font from its parent. + + - SetWindowVariant: Setting the window variant will cause the control to + resize to the corresponding variant size. However if the + button is using a bitmap the bitmap will remain unchanged + and only the font will be adjusted. + +Requirements: + - python2.4 or higher + - wxPython2.8 or higher + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: platebtn.py 74797 2013-09-12 14:40:48Z CJP $" +__revision__ = "$Revision: 74797 $" + +__all__ = ["PlateButton", + "PLATE_NORMAL", "PLATE_PRESSED", "PLATE_HIGHLIGHT", + + "PB_STYLE_DEFAULT", "PB_STYLE_GRADIENT", "PB_STYLE_SQUARE", + "PB_STYLE_NOBG", "PB_STYLE_DROPARROW", "PB_STYLE_TOGGLE", + + "EVT_PLATEBTN_DROPARROW_PRESSED"] + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.lib.newevent + +# Local Imports +from eclutil import * + +#-----------------------------------------------------------------------------# +# Button States +PLATE_NORMAL = 0 +PLATE_PRESSED = 1 +PLATE_HIGHLIGHT = 2 + +# Button Styles +PB_STYLE_DEFAULT = 1 # Normal Flat Background +PB_STYLE_GRADIENT = 2 # Gradient Filled Background +PB_STYLE_SQUARE = 4 # Use square corners instead of rounded +PB_STYLE_NOBG = 8 # Usefull on Windows to get a transparent appearance + # when the control is shown on a non solid background +PB_STYLE_DROPARROW = 16 # Draw drop arrow and fire EVT_PLATEBTN_DROPRROW_PRESSED event +PB_STYLE_TOGGLE = 32 # Stay pressed untill clicked again + +#-----------------------------------------------------------------------------# + +# EVT_BUTTON used for normal event notification +# EVT_TOGGLE_BUTTON used for toggle button mode notification +PlateBtnDropArrowPressed, EVT_PLATEBTN_DROPARROW_PRESSED = wx.lib.newevent.NewEvent() + +#-----------------------------------------------------------------------------# + +class PlateButton(wx.PyControl): + """PlateButton is a custom type of flat button with support for + displaying bitmaps and having an attached dropdown menu. + + """ + def __init__(self, parent, id=wx.ID_ANY, label='', bmp=None, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=PB_STYLE_DEFAULT, name=wx.ButtonNameStr): + """Create a PlateButton + @keyword label: Buttons label text + @keyword bmp: Buttons bitmap + @keyword style: Button style + + """ + super(PlateButton, self).__init__(parent, id, pos, size, + wx.BORDER_NONE|wx.TRANSPARENT_WINDOW, + name=name) + + # Attributes + self.InheritAttributes() + self._bmp = dict(enable=None, disable=None) + if bmp is not None: + assert isinstance(bmp, wx.Bitmap) and bmp.IsOk() + self._bmp['enable'] = bmp + img = bmp.ConvertToImage() + img = img.ConvertToGreyscale(.795, .073, .026) #(.634, .224, .143) + self._bmp['disable'] = wx.BitmapFromImage(img) + + self._menu = None + self.SetLabel(label) + self._style = style + self._state = dict(pre=PLATE_NORMAL, cur=PLATE_NORMAL) + self._color = self.__InitColors() + self._pressed = False + + # Setup Initial Size + self.SetInitialSize(size) + + # Event Handlers + self.Bind(wx.EVT_PAINT, lambda evt: self.__DrawButton()) + self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase) + self.Bind(wx.EVT_SET_FOCUS, self.OnFocus) + self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + + # Mouse Events + self.Bind(wx.EVT_LEFT_DCLICK, lambda evt: self._ToggleState()) + self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_ENTER_WINDOW, + lambda evt: self._SetState(PLATE_HIGHLIGHT)) + self.Bind(wx.EVT_LEAVE_WINDOW, + lambda evt: wx.CallLater(80, self.__LeaveWindow)) + + # Other events + self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + self.Bind(wx.EVT_CONTEXT_MENU, lambda evt: self.ShowMenu()) + + def __DrawBitmap(self, gc): + """Draw the bitmap if one has been set + @param gc: GCDC to draw with + @return: x cordinate to draw text at + + """ + if self.IsEnabled(): + bmp = self._bmp['enable'] + else: + bmp = self._bmp['disable'] + + if bmp is not None and bmp.IsOk(): + bw, bh = bmp.GetSize() + ypos = (self.GetSize()[1] - bh) // 2 + gc.DrawBitmap(bmp, 6, ypos, bmp.GetMask() != None) + return bw + 6 + else: + return 6 + + def __DrawDropArrow(self, gc, xpos, ypos): + """Draw a drop arrow if needed and restore pen/brush after finished + @param gc: GCDC to draw with + @param xpos: x cord to start at + @param ypos: y cord to start at + + """ + if self._menu is not None or self._style & PB_STYLE_DROPARROW: + # Positioning needs a little help on Windows + if wx.Platform == '__WXMSW__': + xpos -= 2 + tripoints = [(xpos, ypos), (xpos + 6, ypos), (xpos + 3, ypos + 5)] + brush_b = gc.GetBrush() + pen_b = gc.GetPen() + gc.SetPen(wx.TRANSPARENT_PEN) + gc.SetBrush(wx.Brush(gc.GetTextForeground())) + gc.DrawPolygon(tripoints) + gc.SetBrush(brush_b) + gc.SetPen(pen_b) + else: + pass + + def __DrawHighlight(self, gc, width, height): + """Draw the main highlight/pressed state + @param gc: GCDC to draw with + @param width: width of highlight + @param height: height of highlight + + """ + if self._state['cur'] == PLATE_PRESSED: + color = self._color['press'] + else: + color = self._color['hlight'] + + if self._style & PB_STYLE_SQUARE: + rad = 0 + else: + rad = (height - 3) / 2 + + if self._style & PB_STYLE_GRADIENT: + gc.SetBrush(wx.TRANSPARENT_BRUSH) + rgc = gc.GetGraphicsContext() + brush = rgc.CreateLinearGradientBrush(0, 1, 0, height, + color, AdjustAlpha(color, 55)) + rgc.SetBrush(brush) + else: + gc.SetBrush(wx.Brush(color)) + + gc.DrawRoundedRectangle(1, 1, width - 2, height - 2, rad) + + def __PostEvent(self): + """Post a button event to parent of this control""" + if self._style & PB_STYLE_TOGGLE: + etype = wx.wxEVT_COMMAND_TOGGLEBUTTON_CLICKED + else: + etype = wx.wxEVT_COMMAND_BUTTON_CLICKED + bevt = wx.CommandEvent(etype, self.GetId()) + bevt.SetEventObject(self) + bevt.SetString(self.GetLabel()) + self.GetEventHandler().ProcessEvent(bevt) + + def __DrawButton(self): + """Draw the button""" + dc = wx.PaintDC(self) + gc = wx.GCDC(dc) + + # Setup + dc.SetBrush(wx.TRANSPARENT_BRUSH) + gc.SetBrush(wx.TRANSPARENT_BRUSH) + gc.SetFont(self.Font) + dc.SetFont(self.Font) + gc.SetBackgroundMode(wx.TRANSPARENT) + + # The background needs some help to look transparent on + # on Gtk and Windows + if wx.Platform in ['__WXGTK__', '__WXMSW__']: + gc.SetBackground(self.GetBackgroundBrush(gc)) + gc.Clear() + + # Calc Object Positions + width, height = self.GetSize() + if wx.Platform == '__WXGTK__': + tw, th = dc.GetTextExtent(self.Label) + else: + tw, th = gc.GetTextExtent(self.Label) + txt_y = max((height - th) // 2, 1) + + if self._state['cur'] == PLATE_HIGHLIGHT: + gc.SetTextForeground(self._color['htxt']) + gc.SetPen(wx.TRANSPARENT_PEN) + self.__DrawHighlight(gc, width, height) + + elif self._state['cur'] == PLATE_PRESSED: + gc.SetTextForeground(self._color['htxt']) + if wx.Platform == '__WXMAC__': + pen = wx.Pen(GetHighlightColour(), 1, wx.SOLID) + else: + pen = wx.Pen(AdjustColour(self._color['press'], -80, 220), 1) + gc.SetPen(pen) + + self.__DrawHighlight(gc, width, height) + txt_x = self.__DrawBitmap(gc) + t_x = max((width - tw - (txt_x + 2)) // 2, txt_x + 2) + if wx.Platform == '__WXGTK__': + dc.DrawText(self.Label, t_x, txt_y) + else: + gc.DrawText(self.Label, t_x, txt_y) + self.__DrawDropArrow(gc, width - 10, (height // 2) - 2) + + else: + if self.IsEnabled(): + gc.SetTextForeground(self.GetForegroundColour()) + else: + txt_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT) + gc.SetTextForeground(txt_c) + + # Draw bitmap and text + if self._state['cur'] != PLATE_PRESSED: + txt_x = self.__DrawBitmap(gc) + t_x = max((width - tw - (txt_x + 2)) // 2, txt_x + 2) + if wx.Platform == '__WXGTK__': + dc.DrawText(self.Label, t_x, txt_y) + else: + gc.DrawText(self.Label, t_x, txt_y) + self.__DrawDropArrow(gc, width - 10, (height // 2) - 2) + + def __InitColors(self): + """Initialize the default colors""" + color = GetHighlightColour() + pcolor = AdjustColour(color, -12) + colors = dict(default=True, + hlight=color, + press=pcolor, + htxt=BestLabelColour(self.GetForegroundColour())) + return colors + + def __LeaveWindow(self): + """Handle updating the buttons state when the mouse cursor leaves""" + # Invoked via CallLater so possible that the C++ object may + # may have been yanked out from under us in the meantime. + if self: + if (self._style & PB_STYLE_TOGGLE) and self._pressed: + self._SetState(PLATE_PRESSED) + else: + self._SetState(PLATE_NORMAL) + self._pressed = False + + def _SetState(self, state): + """Manually set the state of the button + @param state: one of the PLATE_* values + @note: the state may be altered by mouse actions + @note: Internal use only! + + """ + if self: + self._state['pre'] = self._state['cur'] + self._state['cur'] = state + if wx.Platform == '__WXMSW__': + self.Parent.RefreshRect(self.Rect, False) + else: + self.Refresh() + + def _ToggleState(self): + """Toggle button state + @note: Internal Use Only! + + """ + if self._state['cur'] != PLATE_PRESSED: + self._SetState(PLATE_PRESSED) + else: + self._SetState(PLATE_HIGHLIGHT) + + #---- End Private Member Function ----# + + #---- Public Member Functions ----# + + BitmapDisabled = property(lambda self: self.GetBitmapDisabled(), + lambda self, bmp: self.SetBitmapDisabled(bmp)) + BitmapLabel = property(lambda self: self.GetBitmapLabel(), + lambda self, bmp: self.SetBitmap(bmp)) + + # Aliases + BitmapFocus = BitmapLabel + BitmapHover = BitmapLabel + BitmapSelected = BitmapLabel + + LabelText = property(lambda self: self.GetLabel(), + lambda self, lbl: self.SetLabel(lbl)) + + def AcceptsFocus(self): + """Can this window have the focus?""" + return self.IsEnabled() + + def Disable(self): + """Disable the control""" + super(PlateButton, self).Disable() + self.Refresh() + + def DoGetBestSize(self): + """Calculate the best size of the button + @return: wx.Size + + """ + width = 4 + height = 6 + if self.Label: + # NOTE: Should measure with a GraphicsContext to get right + # size, but due to random segfaults on linux special + # handling is done in the drawing instead... + lsize = self.GetFullTextExtent(self.Label) + width += lsize[0] + height += lsize[1] + + if self._bmp['enable'] is not None: + bsize = self._bmp['enable'].Size + width += (bsize[0] + 10) + if height <= bsize[1]: + height = bsize[1] + 6 + else: + height += 3 + else: + width += 10 + + if self._menu is not None or self._style & PB_STYLE_DROPARROW: + width += 12 + + best = wx.Size(width, height) + self.CacheBestSize(best) + return best + + def Enable(self, enable=True): + """Enable/Disable the control""" + super(PlateButton, self).Enable(enable) + self.Refresh() + + def GetBackgroundBrush(self, dc): + """Get the brush for drawing the background of the button + @return: wx.Brush + @note: used internally when on gtk + + """ + if wx.Platform == '__WXMAC__' or self._style & PB_STYLE_NOBG: + return wx.TRANSPARENT_BRUSH + + bkgrd = self.GetBackgroundColour() + brush = wx.Brush(bkgrd, wx.SOLID) + my_attr = self.GetDefaultAttributes() + p_attr = self.Parent.GetDefaultAttributes() + my_def = bkgrd == my_attr.colBg + p_def = self.Parent.GetBackgroundColour() == p_attr.colBg + if my_def and not p_def: + bkgrd = self.Parent.GetBackgroundColour() + brush = wx.Brush(bkgrd, wx.SOLID) + return brush + + def GetBitmapDisabled(self): + """Get the bitmap of the disable state + @return: wx.Bitmap or None + + """ + return self.BitmapDisabled + + def GetBitmapLabel(self): + """Get the label bitmap + @return: wx.Bitmap or None + + """ + return self.BitmapLabel + + # GetBitmap Aliases for BitmapButton api + GetBitmapFocus = GetBitmapLabel + GetBitmapHover = GetBitmapLabel + + # Alias for GetLabel + GetLabelText = wx.PyControl.GetLabel + + def GetMenu(self): + """Return the menu associated with this button or None if no + menu is associated with it. + + """ + return self._menu + + def GetState(self): + """Get the current state of the button + @return: int + @see: PLATE_NORMAL, PLATE_HIGHLIGHT, PLATE_PRESSED + + """ + return self._state['cur'] + + def HasTransparentBackground(self): + """Override setting of background fill""" + return True + + def IsPressed(self): + """Return if button is pressed (PB_STYLE_TOGGLE) + @return: bool + + """ + return self._pressed + + #---- Event Handlers ----# + + def OnErase(self, evt): + """Trap the erase event to keep the background transparent + on windows. + @param evt: wx.EVT_ERASE_BACKGROUND + + """ + if not (PB_STYLE_NOBG & self._style): + evt.Skip() + + def OnFocus(self, evt): + """Set the visual focus state if need be""" + if self._state['cur'] == PLATE_NORMAL: + self._SetState(PLATE_HIGHLIGHT) + + def OnKeyUp(self, evt): + """Execute a single button press action when the Return key is pressed + and this control has the focus. + @param evt: wx.EVT_KEY_UP + + """ + if evt.GetKeyCode() == wx.WXK_SPACE: + self._SetState(PLATE_PRESSED) + self.__PostEvent() + wx.CallLater(100, self._SetState, PLATE_HIGHLIGHT) + else: + evt.Skip() + + def OnKillFocus(self, evt): + """Set the visual state back to normal when focus is lost + unless the control is currently in a pressed state. + + """ + # Note: this delay needs to be at least as much as the on in the KeyUp + # handler to prevent ghost highlighting from happening when + # quickly changing focus and activating buttons + if self._state['cur'] != PLATE_PRESSED: + self._SetState(PLATE_NORMAL) + + def OnLeftDown(self, evt): + """Sets the pressed state and depending on the click position will + show the popup menu if one has been set. + + """ + if (self._style & PB_STYLE_TOGGLE): + self._pressed = not self._pressed + + pos = evt.GetPositionTuple() + self._SetState(PLATE_PRESSED) + size = self.GetSizeTuple() + if pos[0] >= size[0] - 16: + if self._menu is not None: + self.ShowMenu() + elif self._style & PB_STYLE_DROPARROW: + event = PlateBtnDropArrowPressed() + event.SetEventObject(self) + self.EventHandler.ProcessEvent(event) + + self.SetFocus() + + def OnLeftUp(self, evt): + """Post a button event if the control was previously in a + pressed state. + @param evt: wx.MouseEvent + + """ + if self._state['cur'] == PLATE_PRESSED: + pos = evt.GetPositionTuple() + size = self.GetSizeTuple() + if not (self._style & PB_STYLE_DROPARROW and pos[0] >= size[0] - 16): + self.__PostEvent() + + if self._pressed: + self._SetState(PLATE_PRESSED) + else: + self._SetState(PLATE_HIGHLIGHT) + + def OnMenuClose(self, evt): + """Refresh the control to a proper state after the menu has been + dismissed. + @param evt: wx.EVT_MENU_CLOSE + + """ + mpos = wx.GetMousePosition() + if self.HitTest(self.ScreenToClient(mpos)) != wx.HT_WINDOW_OUTSIDE: + self._SetState(PLATE_HIGHLIGHT) + else: + self._SetState(PLATE_NORMAL) + evt.Skip() + + #---- End Event Handlers ----# + + def SetBitmap(self, bmp): + """Set the bitmap displayed in the button + @param bmp: wx.Bitmap + + """ + self._bmp['enable'] = bmp + img = bmp.ConvertToImage() + img = img.ConvertToGreyscale(.795, .073, .026) #(.634, .224, .143) + self._bmp['disable'] = img.ConvertToBitmap() + self.InvalidateBestSize() + + def SetBitmapDisabled(self, bmp): + """Set the bitmap for the disabled state + @param bmp: wx.Bitmap + + """ + self._bmp['disable'] = bmp + + # Aliases for SetBitmap* functions from BitmapButton + SetBitmapFocus = SetBitmap + SetBitmapHover = SetBitmap + SetBitmapLabel = SetBitmap + SetBitmapSelected = SetBitmap + + def SetFocus(self): + """Set this control to have the focus""" + if self._state['cur'] != PLATE_PRESSED: + self._SetState(PLATE_HIGHLIGHT) + super(PlateButton, self).SetFocus() + + def SetFont(self, font): + """Adjust size of control when font changes""" + super(PlateButton, self).SetFont(font) + self.InvalidateBestSize() + + def SetLabel(self, label): + """Set the label of the button + @param label: lable string + + """ + super(PlateButton, self).SetLabel(label) + self.InvalidateBestSize() + + def SetLabelColor(self, normal, hlight=wx.NullColour): + """Set the color of the label. The optimal label color is usually + automatically selected depending on the button color. In some + cases the colors that are chosen may not be optimal. + + The normal state must be specified, if the other two params are left + Null they will be automatically guessed based on the normal color. To + prevent this automatic color choices from happening either specify + a color or None for the other params. + + @param normal: Label color for normal state (wx.Colour) + @keyword hlight: Color for when mouse is hovering over + + """ + assert isinstance(normal, wx.Colour), "Must supply a colour object" + self._color['default'] = False + self.SetForegroundColour(normal) + + if hlight is not None: + if hlight.IsOk(): + self._color['htxt'] = hlight + else: + self._color['htxt'] = BestLabelColour(normal) + + if wx.Platform == '__WXMSW__': + self.Parent.RefreshRect(self.GetRect(), False) + else: + self.Refresh() + + def SetMenu(self, menu): + """Set the menu that can be shown when clicking on the + drop arrow of the button. + @param menu: wxMenu to use as a PopupMenu + @note: Arrow is not drawn unless a menu is set + + """ + if self._menu is not None: + self.Unbind(wx.EVT_MENU_CLOSE) + + self._menu = menu + self.Bind(wx.EVT_MENU_CLOSE, self.OnMenuClose) + self.InvalidateBestSize() + + def SetPressColor(self, color): + """Set the color used for highlighting the pressed state + @param color: wx.Colour + @note: also resets all text colours as necessary + + """ + self._color['default'] = False + if color.Alpha() == 255: + self._color['hlight'] = AdjustAlpha(color, 200) + else: + self._color['hlight'] = color + self._color['press'] = AdjustColour(color, -10, 160) + self._color['htxt'] = BestLabelColour(self._color['hlight']) + self.Refresh() + + def SetWindowStyle(self, style): + """Sets the window style bytes, the updates take place + immediately no need to call refresh afterwards. + @param style: bitmask of PB_STYLE_* values + + """ + self._style = style + self.Refresh() + + def SetWindowVariant(self, variant): + """Set the variant/font size of this control""" + super(PlateButton, self).SetWindowVariant(variant) + self.InvalidateBestSize() + + def ShouldInheritColours(self): + """Overridden base class virtual. If the parent has non-default + colours then we want this control to inherit them. + + """ + return True + + def ShowMenu(self): + """Show the dropdown menu if one is associated with this control""" + if self._menu is not None: + size = self.GetSizeTuple() + adj = wx.Platform == '__WXMAC__' and 3 or 0 + + if self._style & PB_STYLE_SQUARE: + xpos = 1 + else: + xpos = size[1] / 2 + + self.PopupMenu(self._menu, (xpos, size[1] + adj)) + + #---- End Public Member Functions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/pstatbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/pstatbar.py new file mode 100644 index 0000000..4fda8fb --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/pstatbar.py @@ -0,0 +1,299 @@ +############################################################################### +# Name: pstatbar.py # +# Purpose: Custom statusbar with builtin progress indicator # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: ProgressStatusBar + +Custom StatusBar that has a builtin progress gauge to indicate busy status and +progress of long running tasks in a window. + +The Progress Gauge is only shown when it is active. When shown it is shown in +the far rightmost field of the StatusBar. The size of the progress Guage is +also determined by the size of the right most field.When created the StatusBar +will creates two fields by default, field 0 is expanding, field 1 is set as a +small fixed field on the right. To change this behavior simply call SetFields +after creating the bar to change it. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: pstatbar.py 66840 2011-02-03 21:05:28Z CJP $" +__revision__ = "$Revision: 66840 $" + +__all__ = ["ProgressStatusBar",] + +#--------------------------------------------------------------------------# +# Dependancies +import wx + +#--------------------------------------------------------------------------# +# Globals + +#--------------------------------------------------------------------------# +class ProgressStatusBar(wx.StatusBar): + """Custom StatusBar with a built-in progress bar""" + def __init__(self, parent, id_=wx.ID_ANY, + style=wx.SB_FLAT, + name="ProgressStatusBar"): + """Creates a status bar that can hide and show a progressbar + in the far right section. The size of the progressbar is also + determined by the size of the right most section. + @param parent: Frame this status bar belongs to + + """ + super(ProgressStatusBar, self).__init__(parent, id_, style, name) + + # Attributes + self._changed = False # position has changed ? + self.busy = False # Bar in busy mode ? + self.stop = False # Stop flag to stop progress from other threads + self.progress = 0 # Current progress value of the bar + self.range = 0 # Range of progress indicator + self.tmp = None # Temp for text that may be pushed when busy + self.timer = wx.Timer(self) + self.prog = wx.Gauge(self, style=wx.GA_HORIZONTAL) + self.prog.Hide() + + # Layout + self.SetFieldsCount(2) + self.SetStatusWidths([-1, 155]) + + # Event Handlers + self.Bind(wx.EVT_IDLE, lambda evt: self.__Reposition()) + self.Bind(wx.EVT_TIMER, self.OnTimer) + self.Bind(wx.EVT_SIZE, self.OnSize) + + def __del__(self): + """Make sure the timer is stopped + @postcondition: timer is cleaned up + + """ + if self.timer.IsRunning(): + self.timer.Stop() + + def __Reposition(self): + """Does the actual repositioning of progress bar + @postcondition: Progress bar is repostioned inside right most field + + """ + if self._changed: + rect = self.GetFieldRect(self.GetFieldsCount() - 1) + self.prog.SetPosition((rect.x + 2, rect.y + 2)) + self.prog.SetSize((rect.width - 8, rect.height - 4)) + self._changed = False + + def _UpdateRange(self, range): + """Update the internal progress gauges range + @param range: int + + """ + self.range = range + try: + self.prog.SetRange(range) + except OverflowError: + # range too large, scale everything to 100 + self.prog.SetRange(100) + + def _UpdateValue(self, value): + """Update the internal progress gauges value + @param range: int + + """ + # Ensure value is within range + range = self.prog.GetRange() + if range != self.range: # need to scale value + value = int((float(value) / float(range)) * 100) + self.progress = value + self.prog.SetValue(value) + + #---- Public Methods ----# + + def Destroy(self): + """Destroy the control""" + if self.timer.IsRunning(): + self.timer.Stop() + del self.timer + super(ProgressStatusBar, self).Destroy() + + def DoStop(self): + """Stop any progress indication action and hide the bar""" + self.timer.Stop() + self.ShowProgress(False) + self.prog.SetValue(0) # Reset progress value + self.busy = False + self.stop = False + + # Restore any status text that was sent while busy + if self.tmp is not None: + self.SetStatusText(self.tmp, self.GetFieldsCount() - 1) + self.tmp = None + + def GetGauge(self): + """Return the wx.Gauge used by this window + @return: wx.Gauge + + """ + return self.prog + + def GetProgress(self): + """Get the progress of the progress bar + @return: int + + """ + return self.prog.GetValue() + + def GetRange(self): + """Get the what the range of the progress bar is + @return: int + + """ + return self.prog.GetRange() + + def IsBusy(self): + """Is the progress indicator busy or not + @return: bool + + """ + return self.timer.IsRunning() + + def OnSize(self, evt): + """Reposition progress bar on resize + @param evt: wx.EVT_SIZE + + """ + self.__Reposition() + self._changed = True + evt.Skip() + + def OnTimer(self, evt): + """Update the progress bar while the timer is running + @param evt: wx.EVT_TIMER + + """ + # Check stop flag that can be set from non main thread + if self.stop: + self.DoStop() + return + + if not self.prog.IsShown(): + self.Stop() + + if self.busy or self.progress < 0: + self.prog.Pulse() + else: + # Update the Range if it has changed + if self.range >= 0 and self.range != self.prog.GetRange(): + self._UpdateRange(self.range) + + # Update the progress value if it is less than the range + if self.progress <= self.range: + self._UpdateValue(self.progress) + + def Run(self, rate=100): + """Start the bar's timer to check for updates to progress + @keyword rate: rate at which to check for updates in msec + + """ + if not self.timer.IsRunning(): + self.timer.Start(rate) + + def SetProgress(self, val): + """Set the controls internal progress value that is reflected in the + progress bar when the timer next updates. Be sure to call Start before + calling this method if you want the changes to be visible. This method + can be called from non gui threads. + @param val: int + + """ + self.progress = val + if val > 0 and wx.Thread_IsMain(): + self._UpdateValue(val) + + def SetRange(self, val): + """Set the what the range of the progress bar is. This method can safely + be called from non gui threads. + @param val: int + + """ + self.range = val + if val > 0 and wx.Thread_IsMain(): + self._UpdateRange(val) + + def ShowProgress(self, show=True): + """Manually show or hide the progress bar + @keyword show: bool + + """ + # If showing make sure bar is positioned properly + if show: + self.__Reposition() + self.prog.Show(show) + wx.GetApp().ProcessPendingEvents() + + def SetStatusText(self, txt, number=0): + """Override wx.StatusBar method to prevent text from being + put in when the progress indicator is running. Any text that + comes when it is running is buffered to be displayed afterwords. + @param txt: Text to put on status bar + @keyword number: Section number to put text in + + """ + if number == self.GetFieldsCount() - 1 and self.IsBusy(): + if self.tmp is None: + self.tmp = txt + else: + try: + super(ProgressStatusBar, self).SetStatusText(txt, number) + except wx.PyAssertionError: + pass + + # Alias for SetStatusText + PushStatusText = SetStatusText + + def Start(self, rate=100): + """Show and the progress indicator and start the timer + @keyword rate: rate to update progress bar in msec + + """ + self.__Reposition() + bfield = self.GetFieldsCount() - 1 + self.tmp = self.GetStatusText(bfield) + # Clear the progress field so the text doesn't show behind + # the progress indicator. + super(ProgressStatusBar, self).SetStatusText(u'', bfield) + self.stop = False + self.ShowProgress(True) + self.Run(rate) + + def StartBusy(self, rate=100): + """Show and start the progress indicator in pulse mode + @keyword rate: interval to pulse indicator at in msec + + """ + self.busy = True + self.Start(rate) + + def Stop(self): + """Stop and hide the progress bar. This method may safely be called + from background threads. + @precondition: Bar is already running + + """ + if wx.Thread_IsMain(): + self.DoStop() + else: + self.stop = True # Set flag from non main thread + self.progress = 0 + + def StopBusy(self): + """Stop and hide the progress indicator + @postcondition: Progress bar is hidden from view + + """ + self.busy = False + self.Stop() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/segmentbk.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/segmentbk.py new file mode 100644 index 0000000..9612609 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/segmentbk.py @@ -0,0 +1,438 @@ +############################################################################### +# Name: segmentbk.py # +# Purpose: SegmentBook Implementation # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Editra Control Library: SegmentBook + +A L{SegmentBook} is a Toolbook like class derived from a ControlBox and +SegmentBar. Allows for a multi page control with Icons w/ optional text as +page buttons. + ++-----------------------------------------+ +| @^@ *> | +| <-> /|D | +| frog bird | ++-----------------------------------------+ +| | +| Main Page Area | +| | +| | +| | +| | +| | +| | +| | +| | ++-----------------------------------------+ + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: segmentbk.py 69065 2011-09-11 19:18:25Z CJP $" +__revision__ = "$Revision: 69065 $" + +__all__ = ['SegmentBook', 'SegmentBookEvent', 'SEGBOOK_STYLE_DEFAULT', + 'SEGBOOK_STYLE_NO_DIVIDERS', 'SEGBOOK_STYLE_LABELS', + 'SEGBOOK_STYLE_LEFT', 'SEGBOOK_STYLE_RIGHT', + 'SEGBOOK_STYLE_TOP', 'SEGBOOK_STYLE_BOTTOM', + 'SEGBOOK_NAME_STR', + 'edEVT_SB_PAGE_CHANGING', 'EVT_SB_PAGE_CHANGING', + 'edEVT_SB_PAGE_CHANGED', 'EVT_SB_PAGE_CHANGED', + 'edEVT_SB_PAGE_CLOSED', 'EVT_SB_PAGE_CLOSED', + 'edEVT_SB_PAGE_CONTEXT_MENU', 'EVT_SB_PAGE_CONTEXT_MENU', + 'edEVT_SB_PAGE_CLOSING', 'EVT_SB_PAGE_CLOSING' ] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +# Local Imports +import ctrlbox +from eclutil import Freezer + +#-----------------------------------------------------------------------------# +# Events +edEVT_SB_PAGE_CHANGING = wx.NewEventType() +EVT_SB_PAGE_CHANGING = wx.PyEventBinder(edEVT_SB_PAGE_CHANGING, 1) + +edEVT_SB_PAGE_CHANGED = wx.NewEventType() +EVT_SB_PAGE_CHANGED = wx.PyEventBinder(edEVT_SB_PAGE_CHANGED, 1) + +edEVT_SB_PAGE_CLOSING = wx.NewEventType() +EVT_SB_PAGE_CLOSING = wx.PyEventBinder(edEVT_SB_PAGE_CLOSING, 1) + +edEVT_SB_PAGE_CLOSED = wx.NewEventType() +EVT_SB_PAGE_CLOSED = wx.PyEventBinder(edEVT_SB_PAGE_CLOSED, 1) + +edEVT_SB_PAGE_CONTEXT_MENU = wx.NewEventType() +EVT_SB_PAGE_CONTEXT_MENU = wx.PyEventBinder(edEVT_SB_PAGE_CONTEXT_MENU, 1) +class SegmentBookEvent(wx.NotebookEvent): + """SegmentBook event""" + def __init__(self, etype=wx.wxEVT_NULL, id=-1, sel=-1, old_sel=-1): + super(SegmentBookEvent, self).__init__(etype, id, sel, old_sel) + +#-----------------------------------------------------------------------------# +# Global constants + +# Styles +SEGBOOK_STYLE_NO_DIVIDERS = 1 # Don't put dividers between segments +SEGBOOK_STYLE_LABELS = 2 # Use labels below the icons +SEGBOOK_STYLE_TOP = 4 # Segments at top +SEGBOOK_STYLE_BOTTOM = 8 # Segments at top +SEGBOOK_STYLE_LEFT = 16 # Segments at top +SEGBOOK_STYLE_RIGHT = 32 # Segments at top +SEGBOOK_STYLE_DEFAULT = SEGBOOK_STYLE_TOP # Default Style + +# Misc +SEGBOOK_NAME_STR = u"EditraSegmentBook" + +#-----------------------------------------------------------------------------# + +class SegmentBook(ctrlbox.ControlBox): + """Notebook Class""" + def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=SEGBOOK_STYLE_DEFAULT, + name=SEGBOOK_NAME_STR): + """Initialize the SegmentBook""" + super(SegmentBook, self).__init__(parent, id, pos, size, + wx.TAB_TRAVERSAL|wx.NO_BORDER, name) + + # Attributes + self._pages = list() + self._imglist = None + self._use_pylist = False + self._style = style + + # Setup + bstyle = ctrlbox.CTRLBAR_STYLE_BORDER_BOTTOM + + # Disable gradient on GTK due to coloring issues and having + # to deal with various themes. + if wx.Platform != '__WXGTK__': + bstyle |= ctrlbox.CTRLBAR_STYLE_GRADIENT + + if style & SEGBOOK_STYLE_NO_DIVIDERS: + bstyle |= ctrlbox.CTRLBAR_STYLE_NO_DIVIDERS + if style & SEGBOOK_STYLE_LABELS: + bstyle |= ctrlbox.CTRLBAR_STYLE_LABELS + if style & SEGBOOK_STYLE_LEFT or style & SEGBOOK_STYLE_RIGHT: + bstyle |= ctrlbox.CTRLBAR_STYLE_VERTICAL + + self._segbar = ctrlbox.SegmentBar(self, style=bstyle) + self.SetControlBar(self._segbar, self._GetSegBarPos()) + + # Event Handlers + self.Bind(ctrlbox.EVT_SEGMENT_SELECTED, self._OnSegmentSel) + self._segbar.Bind(wx.EVT_RIGHT_DOWN, self._OnRightDown) + self._segbar.Bind(ctrlbox.EVT_SEGMENT_CLOSE, self._OnSegClose) + + def _GetSegBarPos(self): + pos = wx.TOP + if self._style & SEGBOOK_STYLE_LEFT: + pos = wx.LEFT + elif self._style & SEGBOOK_STYLE_RIGHT: + pos = wx.RIGHT + elif self._style & SEGBOOK_STYLE_BOTTOM: + pos = wx.BOTTOM + return pos + + def _DoPageChange(self, psel, csel): + """Change the page and post events + @param psel: previous selection (int) + @param csel: current selection (int) + + """ + # Post page changing event + event = SegmentBookEvent(edEVT_SB_PAGE_CHANGING, + self.GetId(), csel, psel) + event.SetEventObject(self) + handler = self.GetEventHandler() + if not handler.ProcessEvent(event) or event.IsAllowed(): + # Do the actual page change + with Freezer(self) as _tmp: + self.ChangePage(csel) + + # Post page changed event + event.SetEventType(edEVT_SB_PAGE_CHANGED) + handler.ProcessEvent(event) + changed = True + else: + # Reset the segment selection + self._segbar.SetSelection(max(psel, 0)) + changed = False + return changed + + def _OnRightDown(self, evt): + """Handle right click events""" + pos = evt.GetPosition() + where, index = self._segbar.HitTest(pos) + print where, index + if where in (ctrlbox.SEGMENT_HT_SEG, ctrlbox.SEGMENT_HT_X_BTN): + if where == ctrlbox.SEGMENT_HT_SEG: + self._segbar.SetSelection(index) + changed = self._DoPageChange(self.GetSelection(), index) + if changed: + # Send Context Menu Event + event = SegmentBookEvent(edEVT_SB_PAGE_CONTEXT_MENU, + self.GetId()) + event.SetSelection(index) + event.SetOldSelection(index) + event.SetEventObject(self) + self.GetEventHandler().ProcessEvent(event) + else: + # TODO: Handle other right clicks + pass + + evt.Skip() + + def _OnSegClose(self, evt): + """Handle clicks on segment close buttons""" + index = evt.GetPreviousSelection() + change = -1 + segcnt = self._segbar.GetSegmentCount() - 1 + if index == 0 and segcnt: + change = 1 + elif index > 0 and segcnt > 1: + change = index - 1 + + if change != -1: + self._DoPageChange(index, change) + + self._pages[index]['page'].Destroy() + del self._pages[index] + + def _OnSegmentSel(self, evt): + """Change the page in the book""" + psel = evt.GetPreviousSelection() + csel = evt.GetCurrentSelection() + self._DoPageChange(psel, csel) + + def AddPage(self, page, text, select=False, img_id=-1): + """Add a page to the notebook + @param page: wxWindow object + @param text: Page text + @keyword select: should the page be selected + @keyword img_id: Image to use + + """ + page.Hide() + self._pages.append(dict(page=page, img=img_id)) + segbar = self.GetControlBar(self._GetSegBarPos()) + if self._use_pylist: + bmp = self._imglist[img_id] + else: + bmp = self._imglist.GetBitmap(img_id) + segbar.AddSegment(wx.ID_ANY, bmp, text) + idx = len(self._pages) - 1 + + if select or idx == 0: + segbar.SetSelection(idx) + self._DoPageChange(segbar.GetSelection(), idx) + + def ChangePage(self, index): + """Change the page to the given index""" + cpage = self._pages[index]['page'] + page = self.ChangeWindow(cpage) + if page is not None: + page.Hide() + cpage.Show() + self.Layout() + + def DeleteAllPages(self): + """Remove all pages from the control""" + for page in reversed(range(len(self._pages))): + self.DeletePage() + + def DeletePage(self, index): + """Delete the page at the given index + @param index: int + + """ + cpage = self._segbar.GetSelection() + self._segbar.RemoveSegment(index) + npage = self._segbar.GetSelection() + self._DoPageChange(cpage, npage) + + self._pages[index]['page'].Destroy() + del self._pages[index] + + def CurrentPage(self): + """Get the currently selected page + @return: wxWindow or None + + """ + idx = self._segbar.GetSelection() + if idx != -1: + return self._pages[idx]['page'] + else: + return None + + def GetImageList(self): + """Get the notebooks image list + @return: wxImageList or None + + """ + return self._imglist + + def GetPage(self, index): + """Get the page at the given index + @param index: int + + """ + return self._pages[index]['page'] + + def GetPageCount(self): + """Get the number of pages in the book + @return: int + + """ + return len(self._pages) + + def GetPageImage(self, index): + """Get the image index of the current page + @param index: page index + @return: int + + """ + return self._pages[index]['img'] + + def SetPageCloseButton(self, index): + """Set the property of a page + @param index: Segment index + + """ + if wx.Platform != '__WXMAC__': + self._segbar.SetSegmentOption(index, ctrlbox.SEGBTN_OPT_CLOSEBTNR) + else: + self._segbar.SetSegmentOption(index, ctrlbox.SEGBTN_OPT_CLOSEBTNL) + + def GetPageText(self, index): + """Get the text of the current page + @param index: page index + @return: string + + """ + return self._segbar.GetSegmentLabel(index) + + def SetSegmentCanClose(self, index, can_close=True): + """Add a close button to the given segment + @param index: segment index + @keyword can_close: Enable/Disable + + """ + if not can_close: + opt = ctrlbox.SEGBTN_OPT_NONE + + elif wx.Platform == '__WXMAC__': + opt = ctrlbox.SEGBTN_OPT_CLOSEBTNL + else: + opt = ctrlbox.SEGBTN_OPT_CLOSEBTNR + self._segbar.SetSegmentOption(index, opt) + + def GetSelection(self): + """Get the current selection + @return: int + + """ + return self._segbar.GetSelection() + + def GetSegmentBar(self): + """Get the segment bar used by this control + @return: SegmentBar + + """ + return self._segbar + + def HasMultiplePages(self): + """Does the book have multiple pages + @return: bool + + """ + return bool(self.GetPageCount()) + + def HitTest(self, pt): + """Find if/where the given point is in the window + @param pt: wxPoint + @return: where, index + + """ + where, index = (SEGBOOK_NO_WHERE, -1) + index = self._segbar.GetIndexFromPosition(pt) + if index != wx.NOT_FOUND: + where = SEGBOOK_ON_SEGMENT + + # TOOD check for clicks elsewhere on bar + return where, index + + def InsertPage(self, index, page, text, select=False, image_id=-1): + """Insert a page a the given index + @param index: index to insert page at + @param page: page to add to book + @param text: page text + @keyword select: bool + @keyword image_id: image list index + + """ + raise NotImplementedError + + def Refresh(self): + """Refresh the segmentbar + @todo: temporary HACK till rework of SegmentBar class image handling + + """ + segbar = self.GetSegmentBar() + for page in range(self.GetPageCount()): + idx = self.GetPageImage(page) + bmp = self._imglist[idx] + segbar.SetSegmentImage(page, bmp) + segbar.Refresh() + super(SegmentBook, self).Refresh() + + def SetImageList(self, imglist): + """Set the notebooks image list + @param imglist: wxImageList + + """ + self._imglist = imglist + + def SetPageImage(self, index, img_id): + """Set the image to use on the given page + @param index: page index + @param img_id: image list index + + """ + page = self._pages[index] + page['img'] = img_id + self._segbar.SetSegmentImage(self._imglst.GetBitmap(img_id)) + self.Layout() + + def SetPageText(self, index, text): + """Set the text to use on the given page + @param index: page index + @param text: string + + """ + self._segbar.SetSegmentLabel(index, text) + + def SetSelection(self, index): + """Set the selected page + @param index: index of page to select + + """ + csel = self._segbar.GetSelection() + if csel != index: + self._segbar.SetSelection(index) + self._DoPageChange(csel, index) + + def SetUsePyImageList(self, use_pylist): + """Set whether the control us using a regular python list for + storing images or a wxImageList. + @param use_pylist: bool + + """ + self._use_pylist = use_pylist diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/txtentry.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/txtentry.py new file mode 100644 index 0000000..bd296be --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/eclib/txtentry.py @@ -0,0 +1,96 @@ +############################################################################### +# Name: txtentry.py # +# Purpose: Text entry control base clases # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra Control Library: TextEntry + +Text entry base and helper classes. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: txtentry.py 67500 2011-04-15 22:51:55Z CJP $" +__revision__ = "$Revision: 67500 $" + +__all__ = ["CommandEntryBase",] + +#-----------------------------------------------------------------------------# +# Imports +import wx + +#-----------------------------------------------------------------------------# + +class CommandEntryBase(wx.SearchCtrl): + """Base single line text control with key event handling callbacks.""" + def __init__(self, parent, id=wx.ID_ANY, value='', pos=wx.DefaultPosition, + size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, + name="CommandEntryBase"): + + clone = None + if validator != wx.DefaultValidator: + clone = validator.Clone() + + super(CommandEntryBase, self).__init__(parent, id, value, pos, + size, style, validator, name) + + # Attributes + self._txtctrl = None # For msw/gtk + self._enterhook = None + + # Hide the search button and text by default + self.ShowSearchButton(False) + self.ShowCancelButton(False) + self.SetDescriptiveText(wx.EmptyString) + + # MSW/GTK HACK need to bind directly to the text control component + if wx.Platform in ['__WXGTK__', '__WXMSW__']: + for child in self.GetChildren(): + if isinstance(child, wx.TextCtrl): + if clone is not None: + child.SetValidator(clone) + self._txtctrl = child + child.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) + child.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + break + else: + self._txtctrl = self + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) + self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + + # Event management + self.Bind(wx.EVT_TEXT_ENTER, self.OnEnter) + + EnterCallback = property(lambda self: self._enterhook, + lambda self, cback: setattr(self, '_enterhook', cback)) + + def GetTextControl(self): + """Get the wx.TextCtrl window. + @note: only for msw/gtk + + """ + return self._txtctrl + + def OnKeyDown(self, evt): + """Handle KeyDown events""" + evt.Skip() + + def OnKeyUp(self, evt): + """Handle KeyUp events""" + evt.Skip() + + def OnEnter(self, evt): + """Handle the Enter key event""" + if self.EnterCallback: + self.EnterCallback() + else: + evt.Skip() + + def SetFocus(self): + """Set the focus and select the text in the field""" + super(CommandEntryBase, self).SetFocus() + self.SelectAll() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_art.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_art.py new file mode 100644 index 0000000..00aef7a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_art.py @@ -0,0 +1,148 @@ +############################################################################### +# Name: ed_art.py # +# Purpose: Provides artwork for Editra based on object ids # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides and ArtProvider class that works off of object ID's to return an +associated art resource. The provider works hand in hand with Editra's theme +framework that allows for themes to be provided as plugins that act as the +resource providers for the ArtProvider. + +@summary: Editra's ArtProvider, supplies icons based off of object ids + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: ed_art.py 66815 2011-01-29 20:46:20Z CJP $" +__revision__ = "$Revision: 66815 $" + +#--------------------------------------------------------------------------# +# Dependancies +import wx +import ed_glob +from profiler import Profile_Get +import syntax.syntax as syntax +import ed_theme + +#--------------------------------------------------------------------------# + +# Map for default system/wx provided graphic resources. +# For toolbar ones fall back to ones provided by the default Tango theme +DEFAULT = { + ed_glob.ID_ADD_BM : wx.ART_ADD_BOOKMARK, + ed_glob.ID_BIN_FILE : wx.ART_EXECUTABLE_FILE, + ed_glob.ID_CDROM : wx.ART_CDROM, + ed_glob.ID_COPY : wx.ART_COPY, + ed_glob.ID_CUT : wx.ART_CUT, + ed_glob.ID_DELETE : wx.ART_DELETE, + ed_glob.ID_DEL_BM : wx.ART_DEL_BOOKMARK, +# ed_glob.ID_DOCPROP : wx.ART_NORMAL_FILE, # Bad match + ed_glob.ID_DOWN : wx.ART_GO_DOWN, + ed_glob.ID_EXIT : wx.ART_QUIT, + ed_glob.ID_FILE : wx.ART_NORMAL_FILE, + ed_glob.ID_FIND : wx.ART_FIND, + ed_glob.ID_FIND_REPLACE : wx.ART_FIND_AND_REPLACE, + ed_glob.ID_FLOPPY : wx.ART_FLOPPY, + ed_glob.ID_FOLDER : wx.ART_FOLDER, + ed_glob.ID_HARDDISK : wx.ART_HARDDISK, + ed_glob.ID_NEW : wx.ART_NEW, + ed_glob.ID_NEXT_MARK : wx.ART_GO_FORWARD, + ed_glob.ID_OPEN : wx.ART_FILE_OPEN, +# ed_glob.ID_PACKAGE : wx.ART_HARDDISK, # Poor match + ed_glob.ID_PASTE : wx.ART_PASTE, +# ed_glob.ID_PREF : wx.ART_EXECUTABLE_FILE, # Bad match + ed_glob.ID_PRE_MARK : wx.ART_GO_BACK, + ed_glob.ID_PRINT : wx.ART_PRINT, + ed_glob.ID_REDO : wx.ART_REDO, + ed_glob.ID_SAVE : wx.ART_FILE_SAVE, + ed_glob.ID_SAVEAS : wx.ART_FILE_SAVE_AS, + ed_glob.ID_STOP : wx.ART_ERROR, +# ed_glob.ID_THEME : wx.ART_INFORMATION, # Bad match + ed_glob.ID_UNDO : wx.ART_UNDO, + ed_glob.ID_UP : wx.ART_GO_UP, + ed_glob.ID_USB : wx.ART_REMOVABLE, +# ed_glob.ID_WEB : wx.ART_HARDDISK # Bad match +} + +#--------------------------------------------------------------------------# + +class EditraArt(wx.ArtProvider): + """Editras Art Provider. Provides the mimetype images and loads any custom + user defined icon sets as well. Editra theme specific icons are looked up + by passing an objects related id as a string to this providers CreateBitmap + function for it to talk to the theme resource provider. If the id is not + a defined object ID it is simply ignored or passed to the the next + ArtProvider in the chain to handle. + + """ + def __init__(self): + """Initializes Editra's art provider""" + super(EditraArt, self).__init__() + self._library = ed_theme.BitmapProvider(wx.GetApp().GetPluginManager()) + + def CreateBitmap(self, art_id, client, size): + """Lookup and return an associated bitmap from the current theme if + one exisists. If the art_id is not a theme defined id and is a wx + defined art resource then it is passed to the next ArtProvider in the + stack to evaluate. + + @return: Requested bitmap from current theme if one exists + @rtype: wx.Bitmap + + """ + # All art ids we can handle can be converted to int + try: + art_id = int(art_id) + except ValueError: + return wx.NullBitmap + + # If using default theme let the system provide the art when possible + # this is mostly for GTK where there is a native art provider that can + # provide theme icons. + if Profile_Get('ICONS', 'str').lower() == u'default' and art_id in DEFAULT: + if client == wx.ART_MENU: + size = (16, 16) + elif client == wx.ART_TOOLBAR: + size = Profile_Get('ICON_SZ', default=(24, 24)) + return wx.ArtProvider.GetBitmap(DEFAULT[art_id], client, size) + + # If a custom theme is set fetch the requested bitmap + bmp = self._library.GetBitmap(art_id, client) + if not bmp.IsNull() and bmp.IsOk(): + # Dont scale toolbar icons on wxMac as the toolbar handles it + # internally and produces much nicer results. + if client == wx.ART_TOOLBAR and not wx.Platform == '__WXMAC__': + if size == wx.DefaultSize: + size = Profile_Get('ICON_SZ', default=(24, 24)) + + img_sz = bmp.GetSize() + if size[0] < img_sz[0]: + img = wx.ImageFromBitmap(bmp) + img.Rescale(size[0], size[1], wx.IMAGE_QUALITY_HIGH) + bmp = wx.BitmapFromImage(img) + + elif client == wx.ART_MENU and bmp.GetSize() != (16, 16): + img = wx.ImageFromBitmap(bmp) + img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH) + bmp = wx.BitmapFromImage(img) + elif client == wx.ART_TOOLBAR: + # Dont fail on a toolbar icon return a warning icon when nothing is + # found in the bitmap provider. + bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, client, size) + elif art_id in syntax.SYNTAX_IDS: + # Dont fail when requesting mime type icons, fallback to the system + # icon for a normal file in this case. + bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, + wx.ART_MENU, (16, 16)) + + if bmp.IsOk() and not bmp.IsNull(): + return bmp + + # All failed so return a Null + return wx.NullBitmap + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basestc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basestc.py new file mode 100644 index 0000000..029f30e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basestc.py @@ -0,0 +1,1337 @@ +############################################################################### +# Name: ed_basestc.py # +# Purpose: Editra's base StyledTextCtrl. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +The EditraBaseStc is the base StyledTextCtrl that provides automatic styling and +syntax highlighting of all supported filetypes. + +@summary: Editra's base styled text ctrl. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_basestc.py 73711 2013-03-23 14:19:01Z CJP $" +__revision__ = "$Revision: 73711 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc + +# Editra Imports +import ed_glob +import ed_style +import eclib +import ebmlib +import ed_msg +import ed_txt +from syntax import syntax +from syntax import synglob +import autocomp +from extern import vertedit +from profiler import Profile_Get +import plugin +import iface +import util +import ed_marker + +#-----------------------------------------------------------------------------# + +# Margins +MARK_MARGIN = 0 +NUM_MARGIN = 1 +FOLD_MARGIN = 2 + +# Markers (3rd party) +MARKER_VERT_EDIT = ed_marker.NewMarkerId() + +# Key code additions +ALT_SHIFT = wx.stc.STC_SCMOD_ALT|wx.stc.STC_SCMOD_SHIFT +CTRL_SHIFT = wx.stc.STC_SCMOD_CTRL|wx.stc.STC_SCMOD_SHIFT + +#-----------------------------------------------------------------------------# + +class EditraBaseStc(wx.stc.StyledTextCtrl, ed_style.StyleMgr): + """Base StyledTextCtrl that provides all the base code editing + functionality. + + """ + ED_STC_MASK_MARKERS = ~wx.stc.STC_MASK_FOLDERS + def __init__(self, parent, id_=wx.ID_ANY, + pos=wx.DefaultPosition, size=wx.DefaultSize, style=0): + wx.stc.StyledTextCtrl.__init__(self, parent, id_, pos, size, style) + ed_style.StyleMgr.__init__(self, self.GetStyleSheet()) + + # Attributes + self.file = ed_txt.EdFile() + self._code = dict(compsvc=autocomp.AutoCompService.GetCompleter(self), + synmgr=syntax.SyntaxMgr(ed_glob.CONFIG['CACHE_DIR']), + keywords=[ ' ' ], + comment=list(), + clexer=None, # Container lexer method + indenter=None, # Auto indenter + lang_id=0) # Language ID from syntax module + + self.vert_edit = vertedit.VertEdit(self, markerNumber=MARKER_VERT_EDIT) + self._line_num = True # Show line numbers + self._last_cwidth = 1 # one pixel + + # Set Up Margins + ## Outer Left Margin Bookmarks + self.SetMarginType(MARK_MARGIN, wx.stc.STC_MARGIN_SYMBOL) + self.SetMarginMask(MARK_MARGIN, EditraBaseStc.ED_STC_MASK_MARKERS) + self.SetMarginSensitive(MARK_MARGIN, True) + self.SetMarginWidth(MARK_MARGIN, 16) + + ## Middle Left Margin Line Number Indication + self.SetMarginType(NUM_MARGIN, wx.stc.STC_MARGIN_NUMBER) + self.SetMarginMask(NUM_MARGIN, 0) + + ## Inner Left Margin Setup Folders + self.SetMarginType(FOLD_MARGIN, wx.stc.STC_MARGIN_SYMBOL) + self.SetMarginMask(FOLD_MARGIN, wx.stc.STC_MASK_FOLDERS) + self.SetMarginSensitive(FOLD_MARGIN, True) + + # Set Mac specific keybindings + if wx.Platform == '__WXMAC__': + for keys in _GetMacKeyBindings(): + self.CmdKeyAssign(*keys) + + # Set default EOL format + if wx.Platform != '__WXMSW__': + self.SetEOLMode(wx.stc.STC_EOL_LF) + + # Setup Auto-comp images + # TODO: should be called on theme change messages + self.RegisterImages() + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(wx.stc.EVT_STC_CHANGE, self.OnChanged) + self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified) + self.Bind(wx.stc.EVT_STC_AUTOCOMP_SELECTION, self.OnAutoCompSel) + + def OnDestroy(self, evt): + if evt.GetId() == self.GetId(): + # Cleanup the file object callbacks + self.file.RemoveModifiedCallback(self.FireModified) + self.file.CleanUp() + evt.Skip() + + #---- Public Methods ----# + + # General marker api + def AddMarker(self, marker, line=-1): + """Add a bookmark and return its handle + @param marker: ed_marker.Marker instance + @keyword line: if < 0 bookmark will be added to current line + + """ + assert isinstance(marker, ed_marker.Marker) + if line < 0: + line = self.GetCurrentLine() + marker.Set(self, line) + return marker.Handle + + def RemoveMarker(self, marker, line): + """Remove the book mark from the given line + @param marker: ed_marker.Marker instance + @param line: int + + """ + assert isinstance(marker, ed_marker.Marker) + marker.Set(self, line, delete=True) + + def RemoveAllMarkers(self, marker): + """Remove all the bookmarks in the buffer + @param marker: ed_marker.Marker instance + + """ + assert isinstance(marker, ed_marker.Marker) + marker.DeleteAll(self) + + #-- Breakpoint marker api --# + def DeleteAllBreakpoints(self): + """Delete all the breakpoints in the buffer""" + ed_marker.Breakpoint().DeleteAll(self) + ed_marker.BreakpointDisabled().DeleteAll(self) + ed_marker.BreakpointStep().DeleteAll(self) + + def DeleteBreakpoint(self, line): + """Delete the breakpoint from the given line""" + ed_marker.Breakpoint().Set(self, line, delete=True) + ed_marker.BreakpointDisabled().Set(self, line, delete=True) + + def _SetBreakpoint(self, mobj, line=-1): + """Set the breakpoint state + @param mtype: Marker object + @return: int (-1 if already set) + + """ + handle = -1 + if line < 0: + line = self.GetCurrentLine() + if not mobj.IsSet(self, line): + # Clear other set breakpoint marker states on same line + ed_marker.Breakpoint().Set(self, line, delete=True) + ed_marker.BreakpointDisabled().Set(self, line, delete=True) + mobj.Set(self, line, delete=False) + handle = mobj.Handle + return handle + + def SetBreakpoint(self, line=-1, disabled=False): + """Set a breakpoint marker on the given line + @keyword line: line number + @keyword disabled: bool + @return: breakpoint handle + + """ + if not disabled: + handle = self._SetBreakpoint(ed_marker.Breakpoint(), line) + else: + handle = self._SetBreakpoint(ed_marker.BreakpointDisabled(), line) + return handle + + def ShowStepMarker(self, line=-1, show=True): + """Show the step (arrow) marker to the given line.""" + if line < 0: + line = self.GetCurrentLine() + mark = ed_marker.BreakpointStep() + if show: + mark.Set(self, line, delete=False) + else: + mark.DeleteAll(self) + + def AddLine(self, before=False, indent=False): + """Add a new line to the document + @keyword before: whether to add the line before current pos or not + @keyword indent: autoindent the new line + @postcondition: a new line is added to the document + + """ + if before: + self.LineUp() + + self.LineEnd() + + if indent: + self.AutoIndent() + else: + self.InsertText(self.GetCurrentPos(), self.GetEOLChar()) + self.LineDown() + + def AutoIndent(self): + """Indent from the current position to match the indentation + of the previous line. Unless the current file type has registered + a custom AutoIndenter in which case it will implement its own + behavior. + + """ + cpos = self.GetCurrentPos() + + # Check if a special purpose indenter has been registered + if self._code['indenter'] is not None: + self.BeginUndoAction() + self._code['indenter'](self, cpos, self.GetIndentChar()) + self.EndUndoAction() + else: + # Default Indenter + line = self.GetCurrentLine() + text = self.GetTextRange(self.PositionFromLine(line), cpos) + if text.strip() == u'': + self.AddText(self.GetEOLChar() + text) + self.EnsureCaretVisible() + return + indent = self.GetLineIndentation(line) + i_space = indent / self.GetTabWidth() + ndent = self.GetEOLChar() + self.GetIndentChar() * i_space + txt = ndent + ((indent - (self.GetTabWidth() * i_space)) * u' ') + self.AddText(txt) + + self.EnsureCaretVisible() + + def BackTab(self): + """Unindent or remove excess whitespace to left of cursor""" + sel = self.GetSelection() + if sel[0] == sel[1]: + # There is no selection + cpos = self.GetCurrentPos() + cline = self.GetCurrentLine() + cipos = self.GetLineIndentPosition(cline) + if cpos <= cipos: + # In indentation so simply backtab + super(EditraBaseStc, self).BackTab() + else: + # In middle of line somewhere + text = self.GetLine(cline) + column = max(0, self.GetColumn(cpos) - 1) + if len(text) > column and text[column].isspace(): + + # Find the end of the whitespace + end = column + while end < len(text) and \ + text[end].isspace() and \ + text[end] not in '\r\n': + end += 1 + + # Find the start of the whitespace + end -= 1 + start = end + while end > 0 and text[start].isspace(): + start -= 1 + + diff = end - start + if diff > 1: + # There is space to compress + isize = self.GetIndent() + if isize < diff: + # More space than indent to remove + repeat = isize + else: + # Less than one indent width to remove + repeat = end - (start + 1) + + # Update the control + self.BeginUndoAction() + self.SetCurrentPos(cpos + (end - column)) + for x in range(repeat): + self.DeleteBack() + self.EndUndoAction() + + else: + # There is a selection + super(EditraBaseStc, self).BackTab() + + def SetBlockCaret(self): + """Change caret style to block""" + if hasattr(self, 'SetCaretStyle'): # wxPython 2.9 or greater + self.SetCaretStyle(wx.stc.STC_CARETSTYLE_BLOCK) + else: + # Alternatively, just make the caret a bit thicker! + # best we can do on 2.8 + self.SetCaretWidth(3) + + def SetLineCaret(self): + """Change caret style to line""" + if hasattr(self, 'SetCaretStyle'): + self.SetCaretStyle(wx.stc.STC_CARETSTYLE_LINE) + else: + pwidth = Profile_Get('CARETWIDTH', default=1) + self.SetCaretWidth(pwidth) + + def BraceBadLight(self, pos): + """Highlight the character at the given position + @param pos: position of character to highlight with STC_STYLE_BRACEBAD + + """ + # Check if we are still alive or not, as this may be called + # after we have been deleted. + if self: + super(EditraBaseStc, self).BraceBadLight(pos) + + def BraceHighlight(self, pos1, pos2): + """Highlight characters at pos1 and pos2 + @param pos1: position of char 1 + @param pos2: position of char 2 + + """ + # Check if we are still alive or not, as this may be called + # after we have been deleted. + if self: + super(EditraBaseStc, self).BraceHighlight(pos1, pos2) + + def CanCopy(self): + """Check if copy/cut is possible""" + return self.HasSelection() + + CanCut = CanCopy + + def Comment(self, start, end, uncomment=False): + """(Un)Comments a line or a selected block of text + in a document. + @param start: beginning line (int) + @param end: end line (int) + @keyword uncomment: uncomment selection + + """ + if len(self._code['comment']): + sel = self.GetSelection() + c_start = self._code['comment'][0] + c_end = u'' + if len(self._code['comment']) > 1: + c_end = self._code['comment'][1] + + # Modify the selected line(s) + self.BeginUndoAction() + try: + nchars = 0 + lines = range(start, end+1) + lines.reverse() + for line_num in lines: + lstart = self.PositionFromLine(line_num) + lend = self.GetLineEndPosition(line_num) + text = self.GetTextRange(lstart, lend) + tmp = text.strip() + if len(tmp): + if uncomment: + if tmp.startswith(c_start): + text = text.replace(c_start, u'', 1) + if c_end and tmp.endswith(c_end): + text = text.replace(c_end, u'', 1) + nchars = nchars - len(c_start + c_end) + else: + text = c_start + text + c_end + nchars = nchars + len(c_start + c_end) + + self.SetTargetStart(lstart) + self.SetTargetEnd(lend) + self.ReplaceTarget(text) + finally: + self.EndUndoAction() + if sel[0] != sel[1]: + self.SetSelection(sel[0], sel[1] + nchars) + else: + if len(self._code['comment']) > 1: + nchars = nchars - len(self._code['comment'][1]) + self.GotoPos(sel[0] + nchars) + + def ConfigureAutoComp(self): + """Sets up the Autocompleter, the autocompleter + configuration depends on the currently set lexer + @postcondition: autocomp is configured + + """ + self.AutoCompSetAutoHide(False) + self.InitCompleter() + self.AutoCompSetChooseSingle(self._code['compsvc'].GetChooseSingle()) + self.AutoCompSetIgnoreCase(not self._code['compsvc'].GetCaseSensitive()) + self.AutoCompStops(self._code['compsvc'].GetAutoCompStops()) + # TODO: come back to this it can cause some annoying behavior where + # it automatically completes strings that you don't want to be + # inserted in the buffer. (i.e typing self._value will bring up + # the autocomp list but if self._value is not in the list and you + # hit space it will automatically insert something from the list.) +# self.AutoCompSetFillUps(self._code['compsvc'].GetAutoCompFillups()) + + def ConfigureLexer(self, file_ext): + """Sets Lexer and Lexer Keywords for the specified file extension + @param file_ext: a file extension to configure the lexer from + + """ + syn_data = self._code['synmgr'].GetSyntaxData(file_ext) + + # Set the ID of the selected lexer + self._code['lang_id'] = syn_data.LangId + + lexer = syn_data.Lexer + # Check for special cases + # TODO: add fetch method to check if container lexer requires extra + # style bytes beyond the default 5. + if lexer in [ wx.stc.STC_LEX_HTML, wx.stc.STC_LEX_XML]: + self.SetStyleBits(7) + elif lexer == wx.stc.STC_LEX_NULL: + self.SetStyleBits(5) + self.SetLexer(lexer) + self.ClearDocumentStyle() + self.UpdateBaseStyles() + return True + else: + self.SetStyleBits(5) + + # Set Lexer + self.SetLexer(lexer) + # Set Keywords + self.SetKeyWords(syn_data.Keywords) + # Set Lexer/Syntax Specifications + self.SetSyntax(syn_data.SyntaxSpec) + # Set Extra Properties + self.SetProperties(syn_data.Properties) + # Set Comment Pattern + self._code['comment'] = syn_data.CommentPattern + + # Get Extension Features + clexer = syn_data.GetFeature(synglob.FEATURE_STYLETEXT) + indenter = syn_data.GetFeature(synglob.FEATURE_AUTOINDENT) + + # Set the Container Lexer Method + self._code['clexer'] = clexer + # Auto-indenter function + self._code['indenter'] = indenter + + def DefineMarkers(self): + """Defines the folder and bookmark icons for this control + @postcondition: all margin markers are defined + + """ + # Get the colours for the various markers + style = self.GetItemByName('foldmargin_style') + back = style.GetFore() + rgb = eclib.HexToRGB(back[1:]) + back = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2]) + + fore = style.GetBack() + rgb = eclib.HexToRGB(fore[1:]) + fore = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2]) + + # Buffer background highlight + caret_line = self.GetItemByName('caret_line').GetBack() + rgb = eclib.HexToRGB(caret_line[1:]) + clback = wx.Colour(*rgb) + + # Code Folding markers + folder = ed_marker.FoldMarker() + folder.Foreground = fore + folder.Background = back + folder.RegisterWithStc(self) + + # Bookmarks + ed_marker.Bookmark().RegisterWithStc(self) + + # Breakpoints + ed_marker.Breakpoint().RegisterWithStc(self) + ed_marker.BreakpointDisabled().RegisterWithStc(self) + step = ed_marker.BreakpointStep() + step.Background = clback + step.RegisterWithStc(self) + ed_marker.StackMarker().RegisterWithStc(self) + + # Other markers + errmk = ed_marker.ErrorMarker() + errsty = self.GetItemByName('error_style') + rgb = eclib.HexToRGB(errsty.GetBack()[1:]) + errmk.Background = wx.Colour(*rgb) + rgb = eclib.HexToRGB(errsty.GetFore()[1:]) + errmk.Foreground = wx.Colour(*rgb) + errmk.RegisterWithStc(self) + # Lint Marker + ed_marker.LintMarker().RegisterWithStc(self) + ed_marker.LintMarkerWarning().RegisterWithStc(self) + ed_marker.LintMarkerError().RegisterWithStc(self) + + def DoZoom(self, mode): + """Zoom control in or out + @param mode: either zoom in or out + + """ + id_type = mode + zoomlevel = self.GetZoom() + if id_type == ed_glob.ID_ZOOM_OUT: + if zoomlevel > -9: + self.ZoomOut() + elif id_type == ed_glob.ID_ZOOM_IN: + if zoomlevel < 19: + self.ZoomIn() + else: + self.SetZoom(0) + return self.GetZoom() + + def EnableLineNumbers(self, enable=True): + """Enable/Disable line number margin + @keyword enable: bool + + """ + if enable: + self.SetMarginWidth(NUM_MARGIN, 30) + else: + self.SetMarginWidth(NUM_MARGIN, 0) + self._line_num = enable + + def FindChar(self, char, repeat=1, reverse=False, extra_offset=0): + """Find the position of the next (ith) 'char' character + on the current line and move caret to it + + @note: used by vim motions for finding a character on a line (f,F,t,T) + @param char: the character to be found + @keyword repeat: how many times to repeat the search + @keyword reverse: whether to search backwards + @keyword extra_offset: extra offset to be applied to the movement + + """ + text, pos = self.GetCurLine() + oldpos = pos + if not reverse: + # search forward + for i in range(repeat): + pos = text.find(char, pos+1) + if pos == -1: + return + else: + # search backward + for i in range(repeat): + pos = text.rfind(char, 0, pos) + if pos == -1: + return + + newpos = pos + extra_offset + if newpos in range(len(text)): + self.MoveCaretPos(newpos - oldpos) + + @property + def File(self): + """Reference to this buffers file object""" + return self.file + + def FindLexer(self, set_ext=u''): + """Sets Text Controls Lexer Based on File Extension + @param set_ext: explicit extension to use in search + @postcondition: lexer is configured for file + + """ + if set_ext != u'': + ext = set_ext.lower() + else: + ext = self.file.GetExtension().lower() + + if ext == u'': + fname = self.GetFileName() + ext = ebmlib.GetFileName(fname).lower() + + self.ClearDocumentStyle() + + # Configure Lexer from File Extension + self.ConfigureLexer(ext) + + # If syntax auto detection fails from file extension try to + # see if there is an interpreter line that can be parsed. + if self.GetLexer() == wx.stc.STC_LEX_NULL: + interp = self.GetLine(0) + if interp != wx.EmptyString: + interp = interp.split(u"/")[-1] + interp = interp.strip().split() + if len(interp) and interp[-1][0] != u"-": + interp = interp[-1] + elif len(interp): + interp = interp[0] + else: + interp = u'' + # TODO: should check user config to ensure the explict + # extension is still associated with the expected + # file type. + ex_map = { "python" : "py", "wish" : "tcl", "ruby" : "rb", + "bash" : "sh", "csh" : "csh", "perl" : "pl", + "ksh" : "ksh", "php" : "php", "booi" : "boo", + "pike" : "pike"} + self.ConfigureLexer(ex_map.get(interp, interp)) + self.Colourise(0, -1) + + def FireModified(self): + """Fire a modified event""" + self.OnChanged(wx.stc.StyledTextEvent(wx.stc.wxEVT_STC_CHANGE, + self.GetId())) + + def GetCommandStr(self, line=None, col=None): + """Gets the command string to the left of the autocomp + activation character. + @keyword line: optional if None current cursor position used + @keyword col: optional if None current cursor position used + @return: the command string to the left of the autocomp char + + """ + if None in (line, col): + # NOTE: the column position returned by GetCurLine is not correct + # for multibyte characters. + line, col = self.GetCurLine() + col = self.GetColumn(self.GetCurrentPos()) + cmd = self._code['compsvc'].GetCommandString(self, line, col) + return cmd + + def GetCommentChars(self): + """Return the list of characters used to comment a string in the + current language. + @return: list of strings + + """ + return self._code['comment'] + + def GetCompleter(self): + """Get this buffers completer object + @return: Completer + + """ + return self._code['compsvc'] + + def GetDocument(self): + """Return a reference to the document object represented in this buffer. + @return: EdFile + @see: L{ed_txt.EdFile} + + """ + return self.file + + def GetEOLChar(self): + """Gets the eol character used in document + @return: the character used for eol in this document + + """ + m_id = self.GetEOLMode() + if m_id == wx.stc.STC_EOL_CR: + return u'\r' + elif m_id == wx.stc.STC_EOL_CRLF: + return u'\r\n' + else: + return u'\n' + + def GetFileName(self): + """Returns the full path name of the current file + @return: full path name of document + + """ + return self.file.GetPath() + + def GetIndentChar(self): + """Gets the indentation char used in document + @return: indentation char used either space or tab + + """ + if self.GetUseTabs(): + return u'\t' + else: + return u' ' * self.GetIndent() + + def GetKeywords(self): + """Get the keyword set for the current document. + @return: list of strings + + """ + return self._code['keywords'] + + def GetLangId(self): + """Returns the language identifier of this control + @return: language identifier of document + + """ + return self._code['lang_id'] + + def GetModTime(self): + """Get the value of the buffers file last modtime""" + return self.file.ModTime + + def GetPos(self): + """Update Line/Column information + @return: tuple (line, column) + + """ + return (self.GetCurrentLine() + 1, self.GetColumn(self.GetCurrentPos())) + + GetRange = wx.stc.StyledTextCtrl.GetTextRange + + def GetWordFromPosition(self, pos): + """Get the word at the given position + @param pos: int + @return: (string, int_start, int_end) + + """ + end = self.WordEndPosition(pos, True) + start = self.WordStartPosition(pos, True) + word = self.GetTextRange(start, end) + return (word, start, end) + + def IsColumnMode(self): + """Is the buffer in column edit mode + @return: bool + + """ + return self.VertEdit.Enabled + + def IsComment(self, pos): + """Is the given position in a comment region of the current buffer + @param pos: int position in buffer + @return: bool + + """ + pos = max(0, pos-1) + return 'comment' in self.FindTagById(self.GetStyleAt(pos)) + + def IsString(self, pos): + """Is the given position in a string region of the current buffer + @param pos: int position in buffer + @return: bool + + """ + style = self.GetStyleAt(pos) + return self.FindTagById(style) in ('string_style', 'char_style') + + def IsNonCode(self, pos): + """Is the passed in position in a non code region + @param pos: buffer position + @return: bool + + """ + return self.IsComment(pos) or self.IsString(pos) + + def HasMarker(self, line, marker): + """Check if the given line has the given marker set + @param line: line number + @param marker: marker id + + """ + mask = self.MarkerGet(line) + return bool(1<<marker & mask) + + def HasSelection(self): + """Check if there is a selection in the buffer + @return: bool + + """ + sel = super(EditraBaseStc, self).GetSelection() + return sel[0] != sel[1] + + def HasMultilineSelection(self): + """Is the selection over multiple lines? + @return: bool + + """ + bMulti = False + sel = super(EditraBaseStc, self).GetSelection() + if sel[0] != sel[1]: + sline = self.LineFromPosition(sel[0]) + eline = self.LineFromPosition(sel[1]) + bMulti = sline != eline + return bMulti + + def CallTipCancel(self): + """Cancel any active calltip(s)""" + if self.CallTipActive(): + super(EditraBaseStc, self).CallTipCancel() + + def CallTipShow(self, position, tip): + """Show a calltip at the given position in the control + @param position: int + @param tip: unicode + + """ + self.CallTipCancel() + super(EditraBaseStc, self).CallTipShow(position, tip) + + def HidePopups(self): + """Hide autocomp/calltip popup windows if any are active""" + if self.AutoCompActive(): + self.AutoCompCancel() + + self.CallTipCancel() + + def InitCompleter(self): + """(Re)Initialize a completer object for this buffer + @todo: handle extended autocomp for plugins? + + """ + # Check for plugins that may extend or override functionality for this + # file type. + autocomp_ext = AutoCompExtension(wx.GetApp().GetPluginManager()) + completer = autocomp_ext.GetCompleter(self) + if completer is not None: + self._code['compsvc'] = completer + else: + extend = Profile_Get('AUTO_COMP_EX') # Using extended autocomp? + self._code['compsvc'] = autocomp.AutoCompService.GetCompleter(self, extend) + + def LoadFile(self, path): + """Load the file at the given path into the buffer. Returns + True if no errors and False otherwise. To retrieve the errors + check the last error that was set in the file object returned by + L{GetDocument}. + @param path: path to file + + """ + # Post notification that a file load is starting + ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENING, path) + self.file.SetPath(path) + txt = self.file.Read() + if txt is not None: + if self.file.IsRawBytes() and not ebmlib.IsUnicode(txt): + self.AddStyledText(txt) + self.SetReadOnly(True) # Don't allow editing of raw bytes + else: + self.SetText(txt) + else: + self.file.SetPath('') + return False + + if self.file.GetLastError() != 'None': + # Return false if there was an encoding error and a fallback + # was used. So the caller knows to check the error status + return False + else: + return True + + def MoveCaretPos(self, offset): + """Move caret by the given offset + @param offset: int (+ move right, - move left) + + """ + pos = max(self.GetCurrentPos() + offset, 0) + pos = min(pos, self.GetLength()) + self.GotoPos(pos) + self.ChooseCaretX() + + def OnAutoCompSel(self, evt): + """Handle when an item is inserted from the autocomp list""" + text = evt.GetText() + cpos = evt.GetPosition() + self._code['compsvc'].OnCompletionInserted(cpos, text) + + def OnChanged(self, evt): + """Handles updates that need to take place after + the control has been modified. + @param evt: wx.stc.StyledTextEvent + + """ + if self._line_num: + # Adjust line number margin width to expand as needed when line + # number width over fills the area. + lines = self.GetLineCount() + mwidth = self.GetTextExtent(str(lines))[0] + + adj = 8 + if wx.Platform == '__WXMAC__': + adj = 2 + + nwidth = max(15, mwidth + adj) + if self.GetMarginWidth(NUM_MARGIN) != nwidth: + self.SetMarginWidth(NUM_MARGIN, nwidth) + + wx.PostEvent(self.GetParent(), evt) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_CHANGED, context=self) + + def OnModified(self, evt): + """Handle modify events, includes style changes!""" + if self.VertEdit.Enabled: + self.VertEdit.OnModified(evt) + else: + evt.Skip() + + def OnStyleNeeded(self, evt): + """Perform custom styling when registered for a container lexer""" + if self._code['clexer'] is not None: + self._code['clexer'](self, self.GetEndStyled(), evt.GetPosition()) + else: + evt.Skip() + + def PutText(self, text): + """Put text in the buffer. Like AddText but does the right thing + depending upon the input mode and buffer state. + @param text: string + + """ + if not self.HasSelection(): + cpos = self.GetCurrentPos() + lepos = self.GetLineEndPosition(self.GetCurrentLine()) + if self.GetOvertype() and cpos != lepos: + self.CharRight() + self.DeleteBack() + self.AddText(text) + else: + self.ReplaceSelection(text) + + def RegisterImages(self): + """Register the images for the autocomp popup list""" + images = [(autocomp.TYPE_FUNCTION, ed_glob.ID_FUNCT_TYPE), + (autocomp.TYPE_METHOD, ed_glob.ID_METHOD_TYPE), + (autocomp.TYPE_PROPERTY, ed_glob.ID_PROPERTY_TYPE), + (autocomp.TYPE_ATTRIBUTE, ed_glob.ID_ATTR_TYPE), + (autocomp.TYPE_CLASS, ed_glob.ID_CLASS_TYPE), + (autocomp.TYPE_VARIABLE, ed_glob.ID_VARIABLE_TYPE), + (autocomp.TYPE_ELEMENT, ed_glob.ID_ELEM_TYPE)] + for idx, img in images: + bmp = wx.ArtProvider.GetBitmap(str(img), wx.ART_MENU) + if bmp.IsOk(): + self.RegisterImage(idx, bmp) + + def SearchText(self, text, regex=False, back=False): + """Search for text forward or backward + @param text: string + @keyword regex: bool + @keyword back: bool + + """ + flags = wx.stc.STC_FIND_MATCHCASE + if regex: + flags = flags | wx.stc.STC_FIND_REGEXP + + self.SearchAnchor() + if not back: + # Search forward + res = self.SearchNext(flags, text) + if res == -1: + # Nothing found, search from top + self.DocumentStart() + self.SearchAnchor() + res = self.SearchNext(flags, text) + else: + # Search backward + res = self.SearchPrev(flags, text) + if res == -1: + # Nothing found, search from bottom + self.DocumentEnd() + self.SearchAnchor() + res = self.SearchPrev(flags, text) + return res # returns -1 if nothing found even after wrapping around + + def SetDocument(self, doc): + """Change the document object used. + @param doc: an L{ed_txt.EdFile} instance + + """ + del self.file + self.file = doc + + def SetEncoding(self, enc): + """Sets the encoding of the document + @param enc: encoding to set for document + + """ + self.file.SetEncoding(enc) + + def GetEncoding(self): + """Get the document objects encoding + @return: string + + """ + return self.file.GetEncoding() + + def SetFileName(self, path): + """Set the buffers filename attributes from the given path""" + self.file.SetPath(path) + + def SetKeyWords(self, kw_lst): + """Sets the keywords from a list of keyword sets + @param kw_lst: [ (KWLVL, "KEWORDS"), (KWLVL2, "KEYWORDS2"), ect...] + + """ + # Parse Keyword Settings List simply ignoring bad values and badly + # formed lists + self._code['keywords'] = list() + kwlist = "" + for keyw in kw_lst: + if len(keyw) != 2: + continue + else: + if not isinstance(keyw[0], int) or \ + not isinstance(keyw[1], basestring): + continue + else: + kwlist += keyw[1] + super(EditraBaseStc, self).SetKeyWords(keyw[0], keyw[1]) + + # Can't have ? in scintilla autocomp list unless specifying an image + # TODO: this should be handled by the autocomp service + if '?' in kwlist: + kwlist.replace('?', '') + + kwlist = kwlist.split() # Split into a list of words + kwlist = list(set(kwlist)) # Remove duplicates from the list + kwlist.sort() # Sort into alphabetical order + + self._code['keywords'] = kwlist + + def SetLexer(self, lexer): + """Set the buffers lexer + @param lexer: lexer to use + @note: Overrides StyledTextCtrl.SetLexer + + """ + if lexer == wx.stc.STC_LEX_CONTAINER: + # If setting a container lexer only bind the event if it hasn't + # been done yet. + if self._code['clexer'] is None: + self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyleNeeded) + else: + # If changing from a container lexer to a non container + # lexer we need to unbind the event. + if self._code['clexer'] is not None: + self.Unbind(wx.stc.EVT_STC_STYLENEEDED) + self._code['clexer'] = None + + super(EditraBaseStc, self).SetLexer(lexer) + + def SetModTime(self, modtime): + """Set the value of the files last modtime""" + self.file.SetModTime(modtime) + + def SetProperties(self, prop_lst): + """Sets the Lexer Properties from a list of specifications + @param prop_lst: [ ("PROPERTY", "VAL"), ("PROPERTY2", "VAL2) ] + + """ + # Parses Property list, ignoring all bad values + for prop in prop_lst: + if len(prop) != 2: + continue + else: + if not isinstance(prop[0], basestring) or not \ + isinstance(prop[1], basestring): + continue + else: + self.SetProperty(prop[0], prop[1]) + return True + + def BaseSetSelection(self, start, end): + """Call base STC SetSelection method, for use with internal utf-8 + indexes in use by derived classes, STC hell... + + """ + super(EditraBaseStc, self).SetSelection(start, end) + + def SetSelection(self, start, end): + """Override base method to make it work correctly using + Unicode character positions instead of UTF-8. + + """ + # STC HELL - some methods require UTF-8 offsets while others work + # with Unicode... + # Calculate UTF-8 offsets in buffer + unicode_txt = self.GetText() + if start != 0: + start = len(ed_txt.EncodeString(unicode_txt[0:start], 'utf-8')) + if end != 0: + end = len(ed_txt.EncodeString(unicode_txt[0:end], 'utf-8')) + del unicode_txt + super(EditraBaseStc, self).SetSelection(start, end) + + def GetSelection(self): + """Get the selection positions in Unicode instead of UTF-8""" + # STC HELL + # Translate the UTF8 byte offsets to unicode + start, end = super(EditraBaseStc, self).GetSelection() + utf8_txt = self.GetTextUTF8() + if start != 0: + start = len(ed_txt.DecodeString(utf8_txt[0:start], 'utf-8')) + if end != 0: + end = len(ed_txt.DecodeString(utf8_txt[0:end], 'utf-8')) + del utf8_txt + return start, end + + def ShowAutoCompOpt(self, command): + """Shows the autocompletion options list for the command + @param command: command to look for autocomp options for + + """ + pos = self.GetCurrentPos() + # symList is a list(completer.Symbol) + symList = self._code['compsvc'].GetAutoCompList(command) + + # Build a list that can be feed to Scintilla + lst = map(unicode, symList) + if lst is not None and len(lst): + self.BeginUndoAction() + lst = u' '.join(lst) + if lst.isspace(): + return + self.AutoCompShow(pos - self.WordStartPosition(pos, True), lst) + + # Check if something was inserted due to there only being a + # single choice returned from the completer and allow the completer + # to adjust caret position as necessary. + curpos = self.GetCurrentPos() + if curpos != pos: + text = self.GetTextRange(pos, curpos) + self._code['compsvc'].OnCompletionInserted(pos, text) + self.EndUndoAction() + self.SetFocus() + + def GetViewWhiteSpace(self): + """Get if view whitespace is turned on + @return: bool + + """ + val = super(EditraBaseStc, self).GetViewWhiteSpace() + return val != wx.stc.STC_WS_INVISIBLE + + def SetViewWhiteSpace(self, viewws): + """Overrides base method to make it a simple bool toggle""" + if viewws: + val = wx.stc.STC_WS_VISIBLEALWAYS + else: + val = wx.stc.STC_WS_INVISIBLE + super(EditraBaseStc, self).SetViewWhiteSpace(val) + + def GetWrapMode(self): + """Get if word wrap is turned on + @return: bool + + """ + val = super(EditraBaseStc, self).GetWrapMode() + return val != wx.stc.STC_WRAP_NONE + + def SetWrapMode(self, wrap): + """Overrides base method to make it a simple toggle operation + @param wrap: bool + + """ + if wrap: + val = wx.stc.STC_WRAP_WORD + else: + val = wx.stc.STC_WRAP_NONE + super(EditraBaseStc, self).SetWrapMode(val) + + def ShowCallTip(self, command): + """Shows call tip for given command + @param command: command to look for calltips for + + """ + self.CallTipCancel() + + tip = self._code['compsvc'].GetCallTip(command) + if len(tip): + curr_pos = self.GetCurrentPos() + tip_pos = curr_pos - (len(command.split('.')[-1]) + 1) + fail_safe = curr_pos - self.GetColumn(curr_pos) + self.CallTipShow(max(tip_pos, fail_safe), tip) + + def ToggleColumnMode(self): + """Toggle the column edit mode""" + self.VertEdit.enable(not self.VertEdit.Enabled) + + def ToggleComment(self): + """Toggle the comment of the selected region""" + if len(self._code['comment']): + sel = self.GetSelection() + start = self.LineFromPosition(sel[0]) + end = self.LineFromPosition(sel[1]) + c_start = self._code['comment'][0] + + if end > start and self.GetColumn(sel[1]) == 0: + end = end - 1 + + # Analyze the selected line(s) + comment = 0 + for line in range(start, end+1): + txt = self.GetLine(line) + if txt.lstrip().startswith(c_start): + comment += 1 + + lcount = end - start + mod = 1 + if lcount == 0: + mod = 0 + + if comment > (lcount / 2) + mod: + # Uncomment + self.Comment(start, end, True) + else: + self.Comment(start, end, False) + + def ToggleLineNumbers(self, switch=None): + """Toggles the visibility of the line number margin + @keyword switch: force a particular setting + + """ + if (switch is None and \ + not self.GetMarginWidth(NUM_MARGIN)) or switch: + self.EnableLineNumbers(True) + else: + self.EnableLineNumbers(False) + + @property + def VertEdit(self): + """Vertical edit mode accessor.""" + return self.vert_edit + + #---- Style Function Definitions ----# + + def RefreshStyles(self): + """Refreshes the colorization of the window by reloading any + style tags that may have been modified. + @postcondition: all style settings are refreshed in the control + + """ + with eclib.Freezer(self) as _tmp: + self.StyleClearAll() + self.SetSyntax(self.GetSyntaxParams()) + self.DefineMarkers() + self.Refresh() + + def UpdateBaseStyles(self): + """Update the controls basic styles""" + super(EditraBaseStc, self).UpdateBaseStyles() + + # Set control specific styles + sback = self.GetItemByName('select_style') + if not sback.IsNull(): + sback = sback.GetBack() + else: + sback = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) + self.VertEdit.SetBlockColor(sback) + self.DefineMarkers() + +#-----------------------------------------------------------------------------# + +class AutoCompExtension(plugin.Plugin): + """Plugin that Extends the autocomp feature""" + observers = plugin.ExtensionPoint(iface.AutoCompI) + def GetCompleter(self, buff): + """Get the completer for the specified file type id + @param buff: EditraStc instance + + """ + ftypeid = buff.GetLangId() + for observer in self.observers: + try: + if observer.GetFileTypeId() == ftypeid: + return observer.GetCompleter(buff) + except Exception, msg: + util.Log("[ed_basestc][err] GetCompleter Extension: %s" % str(msg)) + else: + return None + +#-----------------------------------------------------------------------------# + +def _GetMacKeyBindings(): + """Returns a list of 3-element tuples defining the standard key + bindings for Mac text editors -- i.e., the behavior of option-arrow, + shift-delete, and so on. + + @return: list of (key code, modifier keys, STC action) + + """ + # A good reference for these: http://www.yellowbrain.com/stc/keymap.html + return [ + # Move/select/delete by word + (wx.stc.STC_KEY_LEFT, wx.stc.STC_SCMOD_ALT, + wx.stc.STC_CMD_WORDLEFT), + (wx.stc.STC_KEY_RIGHT, wx.stc.STC_SCMOD_ALT, + wx.stc.STC_CMD_WORDRIGHT), + (wx.stc.STC_KEY_LEFT, ALT_SHIFT, wx.stc.STC_CMD_WORDLEFTEXTEND), + (wx.stc.STC_KEY_RIGHT, ALT_SHIFT, wx.stc.STC_CMD_WORDRIGHTEXTEND), + (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_ALT, + wx.stc.STC_CMD_DELWORDLEFT), + (wx.stc.STC_KEY_DELETE, wx.stc.STC_SCMOD_ALT, + wx.stc.STC_CMD_DELWORDRIGHT), + (wx.stc.STC_KEY_BACK, ALT_SHIFT, wx.stc.STC_CMD_DELWORDRIGHT), + (wx.stc.STC_KEY_DELETE, ALT_SHIFT, wx.stc.STC_CMD_DELWORDLEFT), + + # Move/select/delete by line + (wx.stc.STC_KEY_LEFT, wx.stc.STC_SCMOD_CTRL, + wx.stc.STC_CMD_VCHOME), + (wx.stc.STC_KEY_LEFT, CTRL_SHIFT, wx.stc.STC_CMD_VCHOMEEXTEND), + (wx.stc.STC_KEY_RIGHT, wx.stc.STC_SCMOD_CTRL, + wx.stc.STC_CMD_LINEEND), + (wx.stc.STC_KEY_RIGHT, CTRL_SHIFT, wx.stc.STC_CMD_LINEENDEXTEND), + (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_CTRL, + wx.stc.STC_CMD_DELLINELEFT), + (wx.stc.STC_KEY_DELETE, wx.stc.STC_SCMOD_CTRL, + wx.stc.STC_CMD_DELLINERIGHT), + (wx.stc.STC_KEY_BACK, CTRL_SHIFT, wx.stc.STC_CMD_DELLINERIGHT), + (wx.stc.STC_KEY_DELETE, CTRL_SHIFT, wx.stc.STC_CMD_DELLINELEFT), + + # By-character deletion behavior + (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_NORM, + wx.stc.STC_CMD_DELETEBACK), + (wx.stc.STC_KEY_DELETE, wx.stc.STC_SCMOD_SHIFT, + wx.stc.STC_CMD_DELETEBACK), + + # NOTE: The following two are a special case, since Scintilla + # doesn't have a forward-delete action. So here we just cancel any + # tip our auto-completion display, and then implement forward + # delete in OnKeyDown. + #(wx.stc.STC_KEY_DELETE, 0, wx.stc.STC_CMD_CANCEL), + # Disabled as it breaks some keyboard functionality + # NOTE: forward delete on mac is Fn+Delete and works fine + # (wx.stc.STC_KEY_BACK, wx.stc.STC_SCMOD_SHIFT, + # wx.stc.STC_CMD_CANCEL), + ] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basewin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basewin.py new file mode 100644 index 0000000..f3775bc --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_basewin.py @@ -0,0 +1,200 @@ +############################################################################### +# Name: ed_basewin.py # +# Purpose: Common window base class(es) # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module provides base classes for windows and dialogs to be used within +Editra. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_basewin.py 71697 2012-06-08 15:20:22Z CJP $" +__revision__ = "$Revision: 71697 $" + +#--------------------------------------------------------------------------# +# Imports +import wx + +# Local Imports +import ed_msg +import eclib +import util + +#--------------------------------------------------------------------------# + +def FindMainWindow(window): + """Find the MainWindow of the given window + @return: MainWindow or None + + """ + def IsMainWin(win): + """Check if the given window is a main window""" + return getattr(win, '__name__', '') == 'MainWindow' + + if IsMainWin(window): + return window + # else start looking up the parent hierarchy + tlw = window.GetTopLevelParent() + if IsMainWin(tlw): + return tlw + elif hasattr(tlw, 'GetParent'): + tlw = tlw.GetParent() + if IsMainWin(tlw): + return tlw + + return None + +#--------------------------------------------------------------------------# + +class EDBaseFileTree(eclib.FileTree): + """Base file view control. Contains some common functionality + that should not be included in the low level control. + + """ + def __init__(self, parent): + super(EDBaseFileTree, self).__init__(parent) + + # Message Handlers + ed_msg.Subscribe(self.OnActivateMsg, ed_msg.EDMSG_UI_MW_ACTIVATE) + + # Events + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) + + def OnDestroy(self, event): + """Cleanup message handlers""" + if self: + ed_msg.Unsubscribe(self.OnActivateMsg) + self.DoOnDestroy() + event.Skip() + + def OnActivateMsg(self, msg): + """Handle activation messages""" + mw = FindMainWindow(self) + if mw and msg.Context == mw.Id: + self.DoOnActivate(msg.Data['active']) + + #---- Interface ----# + + def DoOnActivate(self, active): + """Handle activation event + @param active: bool - window active or inactive + + """ + pass + + def DoOnDestroy(self): + """Handle window destruction""" + pass + +#--------------------------------------------------------------------------# + +class EdBaseDialog(eclib.ECBaseDlg): + """Editra Dialog Base Class""" + def __init__(self, parent, id=wx.ID_ANY, title=u"", + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_DIALOG_STYLE, name=u"EdBaseDialog"): + super(EdBaseDialog, self).__init__(parent, id, title, pos, + size, style, name) + +#--------------------------------------------------------------------------# + +class EdBaseFrame(wx.Frame): + """Editra Frame Base Class""" + def __init__(self, parent, id=wx.ID_ANY, title=u"", + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=wx.DEFAULT_FRAME_STYLE, name=u"EdBaseFrame"): + super(EdBaseFrame, self).__init__(parent, id, title, pos, + size, style, name) + + # Setup + util.SetWindowIcon(self) + + # Register with App + wx.GetApp().RegisterWindow(repr(self), self) + + # Event Handlers + self.Bind(wx.EVT_CLOSE, self.OnClose) + + def OnClose(self, event): + """Handle frame closure event""" + wx.GetApp().UnRegisterWindow(repr(self)) + event.Skip() + +#--------------------------------------------------------------------------# + +class EdBaseCtrlBox(eclib.ControlBox): + """ControlBox base class to be used by all common components""" + def __init__(self, parent): + super(EdBaseCtrlBox, self).__init__(parent) + + ed_msg.Subscribe(self._OnFontChange, ed_msg.EDMSG_DSP_FONT) + self.Bind(wx.EVT_WINDOW_DESTROY, self._OnDestroy) + + def _OnDestroy(self, evt): + if self and evt.GetEventObject is self: + ed_msg.Unsubscribe(self._OnFontChange) + + def _OnFontChange(self, msg): + """Update font of all controls""" + if not self: + return + font = msg.GetData() + if isinstance(font, wx.Font): + for pos in (wx.TOP, wx.BOTTOM, wx.LEFT, wx.RIGHT): + cbar = self.GetControlBar(pos) + if cbar: + for child in cbar.GetChildren(): + child.SetFont(font) + + def AddPlateButton(self, lbl=u"", bmp=-1, + align=wx.ALIGN_LEFT, cbarpos=wx.TOP): + """Add an eclib.PlateButton to the ControlBar specified by + cbarpos. + @keyword lbl: Button Label + @keyword bmp: Bitmap or EditraArtProvider ID + @keyword align: button alignment + @keyword cbarpos: ControlBar position + @return: PlateButton instance + + """ + ctrlbar = self.GetControlBar(cbarpos) + assert ctrlbar is not None, "No ControlBar at cbarpos" + return ctrlbar.AddPlateButton(lbl, bmp, align) + + def CreateControlBar(self, pos=wx.TOP): + """Override for CreateControlBar to automatically set the + flat non-gradient version of the control under GTK. + + """ + cbar = super(EdBaseCtrlBox, self).CreateControlBar(pos) + cbar.__class__ = EdBaseCtrlBar + if wx.Platform == '__WXGTK__': + cbar.SetWindowStyle(eclib.CTRLBAR_STYLE_DEFAULT|\ + eclib.CTRLBAR_STYLE_BORDER_TOP|\ + eclib.CTRLBAR_STYLE_BORDER_BOTTOM) + cbar.SetMargins(2,2) + return cbar + +class EdBaseCtrlBar(eclib.ControlBar): + def AddPlateButton(self, lbl=u"", bmp=-1, align=wx.ALIGN_LEFT): + """Add an eclib.PlateButton + @keyword lbl: Button Label + @keyword bmp: Bitmap or EditraArtProvider ID + @keyword align: button alignment + @return: PlateButton instance + + """ + if not isinstance(bmp, wx.Bitmap): + assert isinstance(bmp, int) + bmp = wx.ArtProvider.GetBitmap(str(bmp), wx.ART_MENU) + if bmp.IsNull() or not bmp.IsOk(): + bmp = None + btn = eclib.PlateButton(self, wx.ID_ANY, lbl, bmp, + style=eclib.PB_STYLE_NOBG) + self.AddControl(btn, align) + return btn diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_book.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_book.py new file mode 100644 index 0000000..cfd2bac --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_book.py @@ -0,0 +1,123 @@ +############################################################################### +# Name: ed_book.py # +# Purpose: Editra notebook base class # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Base class for the main tab controls + +@summary: Tabbed book control base classes + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_book.py 69245 2011-09-30 17:52:23Z CJP $" +__revision__ = "$Revision: 69245 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx + +# Editra Imports +import extern.aui as aui +import ed_msg +from profiler import Profile_Get + +#-----------------------------------------------------------------------------# + +class EdBaseBook(aui.AuiNotebook): + """Base notebook control""" + def __init__(self, parent, style=0): + style |= self.GetBaseStyles() + super(EdBaseBook, self).__init__(parent, agwStyle=style) + if wx.Platform == '__WXGTK__': + self.SetArtProvider(GtkTabArt()) + + # Setup + self.UpdateFontSetting() + font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + font.PointSize += 2 + self.NavigatorProps.Font = font + self.NavigatorProps.MinSize = wx.Size(300, 250) + self.SetSashDClickUnsplit(True) + + # Message Handlers + ed_msg.Subscribe(self.OnUpdateFont, ed_msg.EDMSG_DSP_FONT) + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self._OnDestroy, self) + + def _OnDestroy(self, evt): + """Unsubscribe message handlers on delete""" + if self and evt.GetEventObject() is self: + ed_msg.Unsubscribe(self.OnUpdateFont) + evt.Skip() + + @staticmethod + def GetBaseStyles(): + """Get the common base style flags + @return: bitmask + + """ + style = aui.AUI_NB_NO_TAB_FOCUS + if wx.Platform == '__WXMAC__': + style |= aui.AUI_NB_CLOSE_ON_TAB_LEFT + return style + + def OnUpdateFont(self, msg): + """Update the font settings for the control in response to + user settings change. + + """ + if self: + self.UpdateFontSetting() + + def SetPageBitmap(self, pg, bmp): + """Set a tabs bitmap + @param pg: page index + @param bmp: Bitmap + @note: no action if user prefs have turned off bmp + + """ + if not self.UseIcons(): + bmp = wx.NullBitmap + super(EdBaseBook, self).SetPageBitmap(pg, bmp) + + def UpdateFontSetting(self): + """Update font setting using latest profile data""" + font = Profile_Get('FONT3', 'font', None) + if font: + self.SetFont(font) + + def UseIcons(self): + """Is the book using tab icons?""" + bUseIcons = Profile_Get('TABICONS', default=True) + return bUseIcons + +#-----------------------------------------------------------------------------# + +class GtkTabArt(aui.VC71TabArt): + """Simple tab art with no gradients""" + def __init__(self): + super(GtkTabArt, self).__init__() + + def DrawBackground(self, dc, wnd, rect): + """ + Draws the tab area background. + + :param `dc`: a `wx.DC` device context; + :param `wnd`: a `wx.Window` instance object; + :param `rect`: the tab control rectangle. + """ + self._buttonRect = wx.Rect() + + # draw background + r = wx.Rect(rect.x, rect.y, rect.width+2, rect.height) + + # draw base lines + dc.SetPen(self._border_pen) + dc.SetBrush(self._base_colour_brush) + dc.DrawRectangleRect(r) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_bookmark.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_bookmark.py new file mode 100644 index 0000000..782caae --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_bookmark.py @@ -0,0 +1,296 @@ +############################################################################### +# Name: Cody Precord # +# Purpose: Bookmark Manager window and plugin interface # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Bookmark manager + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_bookmark.py 69115 2011-09-17 16:51:49Z CJP $" +__revision__ = "$Revision: 69115 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import re +import wx + +# Editra Libraries +import ed_msg +import iface +import plugin +from profiler import Profile_Get, Profile_Set +import ed_glob +import util +import eclib +import ebmlib +import ed_basewin +from ed_marker import Bookmark + +#-----------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation + +#-----------------------------------------------------------------------------# + +# Interface Implementation +class EdBookmarks(plugin.Plugin): + """Shelf interface implementation for the bookmark manager""" + plugin.Implements(iface.ShelfI) + + __name__ = u'Bookmarks' + + @staticmethod + def AllowMultiple(): + """EdBookmark only allows one instance""" + return False + + @staticmethod + def CreateItem(parent): + """Returns a bookmark panel""" + return BookmarkWindow(parent) + + def GetBitmap(self): + """Get the log viewers tab icon + @return: wx.Bitmap + + """ + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_ADD_BM), wx.ART_MENU) + return bmp + + @staticmethod + def GetId(): + """Plugin menu identifier ID""" + return ed_glob.ID_BOOKMARK_MGR + + @staticmethod + def GetMenuEntry(menu): + """Get the menu entry for the bookmark viewer + @param menu: the menu items parent menu + + """ + item = wx.MenuItem(menu, ed_glob.ID_BOOKMARK_MGR, + _("Bookmarks"), + _("View all bookmarks")) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_ADD_BM), wx.ART_MENU) + item.SetBitmap(bmp) + return item + + def GetName(self): + """Return the name of this control""" + return self.__name__ + + @staticmethod + def IsStockable(): + """EdBookmark can be saved in the shelf preference stack""" + return True + + # Bookmark storage + _marks = list() + @classmethod + def OnStoreBM(cls, msg): + data = msg.GetData() + buf = data.get('stc') + line = data.get('line') + mark = Bookmark() + mark.Filename = buf.GetFileName() + mark.Line = line + if data.get('added', False): + if mark not in cls._marks: + # Store the stc bookmark handle + mark.Handle = data.get('handle', None) + # Store an alias for the bookmark + name = u"" + cline = buf.GetCurrentLine() + if line == cline: + name = buf.GetSelectedText() + if not name: + name = buf.GetLine(line) + mark.Name = name.strip() + cls._marks.append(mark) + else: + if mark in cls._marks: + idx = cls._marks.index(mark) + cls._marks.pop(idx) + + @classmethod + def GetMarks(cls): + return cls._marks + +ed_msg.Subscribe(EdBookmarks.OnStoreBM, ed_msg.EDMSG_UI_STC_BOOKMARK) + +#-----------------------------------------------------------------------------# + +class BookmarkWindow(ed_basewin.EdBaseCtrlBox): + """Shelf window for managing bookmarks""" + def __init__(self, parent): + super(BookmarkWindow, self).__init__(parent) + + # Attributes + self._list = BookmarkList(self) + + #Setup + self.SetWindow(self._list) + ctrlbar = self.CreateControlBar(wx.TOP) + ctrlbar.AddStretchSpacer() + self._delbtn = self.AddPlateButton(_("Delete"), ed_glob.ID_DELETE, + wx.ALIGN_RIGHT) + self._delbtn.ToolTip = wx.ToolTip(_("Delete Bookmark")) + self._delallbtn = self.AddPlateButton(_("Delete All"), + ed_glob.ID_DELETE_ALL, + wx.ALIGN_RIGHT) + self._delallbtn.ToolTip = wx.ToolTip(_("Delete all bookmarks")) + + # Message Handlers + ed_msg.Subscribe(self.OnBookmark, ed_msg.EDMSG_UI_STC_BOOKMARK) + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivate, self._list) + self.Bind(wx.EVT_BUTTON, self.OnDelBm, self._delbtn) + self.Bind(wx.EVT_BUTTON, self.OnDelAllBm, self._delallbtn) + # BUG in wxAUI UpdateUI events not processed when docked + # TODO: renable when switch to agw aui +# self.Bind(wx.EVT_UPDATE_UI, +# lambda evt: evt.Enable(bool(len(self._list.GetSelections()))), +# self._delbtn) + + def OnDestroy(self, evt): + """Unsubscribe message handlers on delete""" + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.OnBookmark) + evt.Skip() + + def OnBookmark(self, msg): + """Bookmark added or removed callback""" + # Update on next iteration to ensure that handler + # in the singleton data store have been updated. + wx.CallAfter(self.DoUpdateListCtrl) + + def OnDelAllBm(self, evt): + """Delete all bookmarks""" + items = range(self._list.ItemCount) + self.DeleteBookmarks(items) + + def OnDelBm(self, evt): + """Remove the selected bookmark(s) from the list and the buffer""" + items = self._list.GetSelections() + self.DeleteBookmarks(items) + + def DeleteBookmarks(self, items): + """Delete the bookmarks from the passed in list + @param items: list of indexes in BookmarkList + + """ + assert isinstance(items, list) + if len(items): + items.reverse() + marks = EdBookmarks.GetMarks() + for item in items: + if item < len(marks): + mark = marks.pop(item) + app = wx.GetApp() + mw = app.GetActiveWindow() + if mw: + nb = mw.GetNotebook() + buf = nb.FindBuffer(mark.Filename) + if buf: + buf.MarkerDeleteHandle(mark.Handle) + self.DoUpdateListCtrl() + + def DoUpdateListCtrl(self): + """Update the listctrl for changes in the cache""" + nMarks = len(EdBookmarks.GetMarks()) + self._list.SetItemCount(nMarks) + # Refresh everything + # XXX: if optimization is needed only refresh visible items + self._list.RefreshItems(0, nMarks) + self._list.Refresh() + + def OnItemActivate(self, evt): + """Handle double clicks on items to navigate to the + selected bookmark. + + """ + index = evt.m_itemIndex + marks = EdBookmarks.GetMarks() + if index < len(marks): + mark = marks[index] + self.GotoBookmark(mark) + + def GotoBookmark(self, mark): + """Goto the bookmark in the editor + @param mark: BookMark + + """ + app = wx.GetApp() + mw = app.GetActiveWindow() + if mw: + nb = mw.GetNotebook() + buf = nb.FindBuffer(mark.Filename) + use_handle = True + if not buf: + nb.OpenPage(ebmlib.GetPathName(mark.Filename), + ebmlib.GetFileName(mark.Filename)) + buf = nb.GetCurrentPage() + use_handle = False # Handle is invalid so use line number + + if buf: + # Ensure the tab is the current one + nb.GotoPage(mark.Filename) + # Jump to the bookmark line + if use_handle: + lnum = buf.MarkerLineFromHandle(mark.Handle) + else: + lnum = mark.Line + buf.GotoLine(lnum) + else: + util.Log("[ed_bookmark][err] Failed to locate mainwindow") + +#-----------------------------------------------------------------------------# + +class BookmarkList(eclib.EBaseListCtrl): + """ListCtrl for displaying the bookmarks in""" + BOOKMARK = 0 + FILE_NAME = 1 + LINE_NUM = 2 + def __init__(self, parent): + super(BookmarkList, self).__init__(parent, + style=wx.LC_REPORT|\ + wx.LC_EDIT_LABELS|\ + wx.LC_VIRTUAL) + + # Setup + self._il = wx.ImageList(16,16) + self._idx = self._il.Add(Bookmark().Bitmap) + self.SetImageList(self._il, wx.IMAGE_LIST_SMALL) + self.InsertColumn(BookmarkList.BOOKMARK, _("Bookmark")) + self.InsertColumn(BookmarkList.FILE_NAME, _("File Location")) + self.InsertColumn(BookmarkList.LINE_NUM, _("Line Number")) + self.setResizeColumn(BookmarkList.FILE_NAME+1) #NOTE: +1 bug in mixin + self.SetItemCount(len(EdBookmarks.GetMarks())) + + def OnGetItemImage(self, item): + return 0 + + def OnGetItemText(self, item, column): + """Override for virtual control""" + marks = EdBookmarks.GetMarks() + val = u"" + if item < len(marks): + mark = marks[item] + if column == BookmarkList.BOOKMARK: + val = mark.Name + if not val: + val = _("Bookmark%d") % item + elif column == BookmarkList.FILE_NAME: + val = mark.Filename + elif column == BookmarkList.LINE_NUM: + val = unicode(mark.Line + 1) + return val diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_cmdbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_cmdbar.py new file mode 100644 index 0000000..0bf9944 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_cmdbar.py @@ -0,0 +1,1314 @@ +############################################################################### +# Name: ed_cmdbar.py # +# Purpose: Creates a small slit panel that holds small controls for searching # +# and other actions. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This class creates a custom panel that can hide and show different controls +based an id value. The panel is generally between 24-32 pixels in height but +can grow to fit the controls inserted in it. The the background is painted with +a gradient using system defined colors. + +@summary: The buffers CommandBar control with search/goto line/command entry + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_cmdbar.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import sys +import re +import wx + +# Local Imports +import util +import ed_glob +import ed_search +import ed_event +import ed_msg +import ebmlib +import eclib +import ed_basewin +from profiler import Profile_Get + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# +# Close Button Bitmap +from extern.embeddedimage import PyEmbeddedImage + +XButton = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAAA3NCSVQICAjb4U/gAAAB6UlE" + "QVQokW2SvWsTYRjAn7tcctdLc7kmxtJqj8ZECIqi7eJHhywVxLWLSBctXQKFOhSE0IJKB0EH" + "wf/BwUkEBxEFFR0cSoei1ZaSJjQ56Zn0vDd3977v8zrcUTr0mZ6PH8+39Onxw97Xz0FnL2w1" + "4DhJnbLU4ZHs1Snpza0bk1cum0MFLvwoJmg/pmjs6bW7a5u7StDZM8Zu0v0W3W/HAGMAgJxF" + "pmYaxumc+nNLDlsNUBKceNJAKj27KI2OIWfImWKVcnMPuKr53QOmJsVfWz7sSZ+pqZWJ7L26" + "YpUUq5SfX1YrE4XZRR+pwikAKAAgBBMQkPevkuMVWdPz88sAIGs6+sR5+/IwlwIA0CXBrsM2" + "toPm/ZMrz2RNBwD0SaO+4G/9AACeG41R9o8wL6CuLwXs6Jow5Mz1OSJ3XMG4DAAiZIgidfb8" + "yOrzqC76RNb08Scv9HMXAAAoFyGNx0Kk2dt3I25nqbazVIvo/J05ABAsAMTETEYrX7pIbNv7" + "8iFZLLeePiKbG7TT9ta+y7lCY7UuM6oNGZ1mW3p9fXKqeq3/xz6wm8yNz8MRIyWRSg6amfTg" + "wHqzp+hW0XUcI3NCy6QBQGAYNRfVZYgJztxeH3LDilmd/vXxHVn/5m3/PvZd0mfKulU0q9P/" + "AeP28JG84F5KAAAAAElFTkSuQmCC") + +#-----------------------------------------------------------------------------# +# Globals +ID_CLOSE_BUTTON = wx.NewId() +ID_SEARCH_NEXT = wx.NewId() +ID_SEARCH_PRE = wx.NewId() +ID_FIND_ALL = wx.NewId() +ID_MATCH_CASE = wx.NewId() +ID_WHOLE_WORD = wx.NewId() +ID_REGEX = wx.NewId() + +#-----------------------------------------------------------------------------# + +class CommandBarBase(ed_basewin.EdBaseCtrlBar, + ebmlib.FactoryMixin): + """Base class for control bars""" + def __init__(self, parent): + super(CommandBarBase, self).__init__(parent, + style=eclib.CTRLBAR_STYLE_GRADIENT) + + if wx.Platform == '__WXGTK__': + self.SetWindowStyle(eclib.CTRLBAR_STYLE_DEFAULT) + + self.SetVMargin(2, 2) + + # Attributes + self._parent = parent + self._menu = None + self._menu_enabled = True + self.ctrl = None + self.close_b = eclib.PlateButton(self, ID_CLOSE_BUTTON, + bmp=XButton.GetBitmap(), + style=eclib.PB_STYLE_NOBG) + + # Setup + self.AddControl(self.close_b, wx.ALIGN_LEFT) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnClose, self.close_b) + self.Bind(wx.EVT_CONTEXT_MENU, self.OnContext) + self.Bind(wx.EVT_MENU, self.OnContextMenu) + self.Bind(wx.EVT_SHOW, self.OnShowBar) + + @classmethod + def GetMetaDefaults(cls): + return dict(id=-1, config_key=None) + + #---- Properties ----# + + MainControl = property(lambda self: self.ctrl, + lambda self, ctrl: self.SetControl(ctrl)) + + #---- Implementation ----# + + def OnClose(self, evt): + """Handles events from the buttons on the bar + @param evt: Event that called this handler + + """ + if evt.Id == ID_CLOSE_BUTTON: + self.Hide() + else: + evt.Skip() + + def OnContext(self, evt): + """Show the custom menu""" + if self._menu_enabled: + if self._menu is None: + # Lazy init the menu + self._menu = wx.Menu(_("Customize")) + # Ensure the label is disabled (wxMSW Bug) + if len(self._menu.MenuItems): + item = self._menu.MenuItems[0] + self._menu.Enable(item.GetId(), False) + + to_menu = list() + for child in self.GetChildren(): + if self.IsCustomizable(child): + to_menu.append(child) + + if len(to_menu): + to_menu.sort(key=wx.Window.GetLabel) + for item in to_menu: + if not item.GetLabel(): + continue + + self._menu.Append(item.Id, + item.GetLabel(), + kind=wx.ITEM_CHECK) + self._menu.Check(item.Id, item.IsShown()) + + self.PopupMenu(self._menu) + else: + evt.Skip() + + def OnContextMenu(self, evt): + """Hide and Show controls""" + ctrl = self.FindWindowById(evt.Id) + if ctrl is not None: + self.ShowControl(ctrl.GetName(), not ctrl.IsShown()) + self.Layout() + + # Update the persistent configuration + key = self.GetConfigKey() + if key is not None: + cfg = Profile_Get('CTRLBAR', default=dict()) + state = self.GetControlStates() + cfg[key] = state + + def OnShowBar(self, evt): + """Update the session list""" + if evt.IsShown(): + if self and evt.EventObject is self: + self.OnBarShown() + evt.Skip() + + def OnBarShown(self): + """virtual override for subclasses that wish to receive window show + event callbacks. + + """ + pass + + def EnableMenu(self, enable=True): + """Enable the popup customization menu + @keyword enable: bool + + """ + self._menu_enabled = enable + if not enable and self._menu is not None: + self._menu.Destroy() + self._menu = None + + def GetConfigKey(self): + """Get the key to use for the layout config persistence. This value + is set in the class definitions meta class. + @return: string + + """ + return self.meta.config_key + + def GetControlStates(self): + """Get the map of control name id's to their shown state True/False + @return: dict() + + """ + state = dict() + for child in self.GetChildren(): + if self.IsCustomizable(child): + state[child.GetName()] = child.IsShown() + return state + + def SetControlStates(self, state): + """Set visibility state of the customizable controls + @param state: dict(ctrl_name=bool) + + """ + for name, show in state.iteritems(): + self.ShowControl(name, show) + self.Layout() + + def Hide(self): + """Hides the control and notifies the parent + @postcondition: CommandBar is hidden + @todo: don't reference nb directly here + + """ + super(CommandBarBase, self).Hide() + self._parent.SendSizeEvent() + nb = self._parent.GetNotebook() + ctrl = nb.GetCurrentCtrl() + if ctrl: + ctrl.SetFocus() + return True + + def ShowControl(self, ctrl_name, show=True): + """Show/Hide a control + @param ctrl_name: string + @note: assumes all left aligned controls + + """ + sizer = self.GetControlSizer() + gonext = False + for item in sizer.GetChildren(): + if gonext: + if item.IsSpacer(): + item.Show(show) + break + + if item.Window and item.Window.GetName() == ctrl_name: + item.Show(show) + gonext = True + + def IsCustomizable(self, ctrl): + """Is the control of a type that can be customized + @param ctrl: wx.Window + @return: bool + + """ + ok = (ctrl is not self.close_b) + ok = ok and (isinstance(ctrl, wx.CheckBox) or \ + isinstance(ctrl, eclib.PlateButton)) + return ok + + def SetControl(self, ctrl): + """Set the main control of this command bar + @param ctrl: window + + """ + self.ctrl = ctrl + + def SetFocus(self): + """Set the focus to the bar and its main control""" + super(CommandBarBase, self).SetFocus() + if self.MainControl: + self.MainControl.SetFocus() + +#-----------------------------------------------------------------------------# + +class SearchBar(CommandBarBase): + """Commandbar for searching text in the current buffer.""" + class meta: + id = ed_glob.ID_QUICK_FIND + config_key = 'SearchBar' + + def __init__(self, parent): + super(SearchBar, self).__init__(parent) + + # Attributes + self.SetControl(ed_search.EdSearchCtrl(self, wx.ID_ANY, + menulen=5, size=(180, -1))) + self._sctrl = self.MainControl.GetSearchController() + + # Setup + f_lbl = wx.StaticText(self, label=_("Find") + u": ") + t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOWN), wx.ART_MENU) + next_btn = eclib.PlateButton(self, ID_SEARCH_NEXT, _("Next"), + t_bmp, style=eclib.PB_STYLE_NOBG, + name="NextBtn") + self.AddControl(f_lbl, wx.ALIGN_LEFT) + self.AddControl(self.ctrl, wx.ALIGN_LEFT) + self.AddControl(next_btn, wx.ALIGN_LEFT) + + t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_UP), wx.ART_MENU) + pre_btn = eclib.PlateButton(self, ID_SEARCH_PRE, _("Previous"), + t_bmp, style=eclib.PB_STYLE_NOBG, + name="PreBtn") + self.AddControl(pre_btn, wx.ALIGN_LEFT) + + t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND), wx.ART_MENU) + fa_btn = eclib.PlateButton(self, ID_FIND_ALL, _("Find All"), + t_bmp, style=eclib.PB_STYLE_NOBG, + name="FindAllBtn") + self.AddControl(fa_btn) + fa_btn.Show(False) # Hide this button by default + + match_case = wx.CheckBox(self, ID_MATCH_CASE, _("Match Case"), + name="MatchCase") + match_case.SetValue(self.ctrl.IsMatchCase()) + self.AddControl(match_case, wx.ALIGN_LEFT) + match_case.Show(False) # Hide by default + + ww_cb = wx.CheckBox(self, ID_WHOLE_WORD, + _("Whole Word"), name="WholeWord") + ww_cb.SetValue(self.ctrl.IsWholeWord()) + self.AddControl(ww_cb, wx.ALIGN_LEFT) + + regex_cb = wx.CheckBox(self, ID_REGEX, _("Regular Expression"), + name="RegEx") + regex_cb.SetValue(self.ctrl.IsRegEx()) + self.AddControl(regex_cb, wx.ALIGN_LEFT) + + # HACK: workaround bug in mac control that resets size to + # that of the default variant after any text has been + # typed in it. Note it reports the best size as the default + # variant and causes layout issues. wxBUG + if wx.Platform == '__WXMAC__': + self.ctrl.SetSizeHints(180, 16, 180, 16) + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_CHECKBOX, self.OnCheck) + ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED) + self._sctrl.RegisterClient(self) + + # Set user customizable layout + state = Profile_Get('CTRLBAR', default=dict()) + cfg = state.get(self.GetConfigKey(), dict()) + self.SetControlStates(cfg) + + def OnDestroy(self, evt): + """Cleanup message handlers on destroy""" + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.OnThemeChange) + self._sctrl.RemoveClient(self) + + def OnButton(self, evt): + """Handle button clicks for the next/previous buttons + @param evt: wx.CommandEvent + + """ + e_id = evt.GetId() + if e_id in [ID_SEARCH_NEXT, ID_SEARCH_PRE]: + self.ctrl.DoSearch(e_id == ID_SEARCH_NEXT) + elif e_id == ID_FIND_ALL: + self.ctrl.FindAll() + else: + evt.Skip() + + def OnCheck(self, evt): + """Set search options for match case, regex, ect... + @param evt: wx.CommandEvent + + """ + e_id = evt.GetId() + if e_id in (ID_MATCH_CASE, ID_REGEX, ID_WHOLE_WORD): + ctrl = self.FindWindowById(e_id) + if ctrl != None: + if e_id == ID_MATCH_CASE: + flag = eclib.AFR_MATCHCASE + elif e_id == ID_WHOLE_WORD: + flag = eclib.AFR_WHOLEWORD + else: + flag = eclib.AFR_REGEX + + if self.ctrl != None: + if ctrl.GetValue(): + self.ctrl.SetSearchFlag(flag) + else: + self.ctrl.ClearSearchFlag(flag) + else: + evt.Skip() + + def NotifyOptionChanged(self, evt): + """Callback for L{ed_search.SearchController} to notify of update + to the find options. + @param evt: eclib.finddlg.FindEvent + + """ + self.FindWindowById(ID_MATCH_CASE).SetValue(evt.IsMatchCase()) + self.FindWindowById(ID_REGEX).SetValue(evt.IsRegEx()) + self.FindWindowById(ID_WHOLE_WORD).SetValue(evt.IsWholeWord()) + + def OnThemeChange(self, msg): + """Update icons when the theme has changed + @param msg: Message Object + + """ + next_btn = self.FindWindowById(ID_SEARCH_NEXT) + if next_btn: + t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOWN), wx.ART_MENU) + next_btn.SetBitmapLabel(t_bmp) + next_btn.SetBitmapHover(t_bmp) + next_btn.Update() + next_btn.Refresh() + + pre_btn = self.FindWindowById(ID_SEARCH_PRE) + if pre_btn: + t_bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_UP), wx.ART_MENU) + pre_btn.SetBitmapLabel(t_bmp) + pre_btn.SetBitmapHover(t_bmp) + pre_btn.Update() + pre_btn.Refresh() + +#-----------------------------------------------------------------------------# + +class CommandEntryBar(CommandBarBase): + """Commandbar for editor command entry and execution.""" + class meta: + id = ed_glob.ID_COMMAND + + def __init__(self, parent): + super(CommandEntryBar, self).__init__(parent) + + # Attributes + self.SetControl(CommandExecuter(self, wx.ID_ANY, size=(150, -1))) + + # Setup + cmd_lbl = wx.StaticText(self, label=_("Command") + ": ") + self.info_lbl = wx.StaticText(self, label="") + self.AddControl(cmd_lbl, wx.ALIGN_LEFT) + self.AddControl(self.ctrl, 1, wx.ALIGN_LEFT) + self.AddControl(self.info_lbl, wx.ALIGN_RIGHT) + + # HACK: workaround bug in mac control that resets size to + # that of the default variant after any text has been + # typed in it. Note it reports the best size as the default + # variant and causes layout issues. wxBUG + if wx.Platform == '__WXMAC__': + self.ctrl.SetSizeHints(200, 16, -1, 16) + + # Setup + self.EnableMenu(False) + +#-----------------------------------------------------------------------------# + +class GotoLineBar(CommandBarBase): + """Commandbar for Goto Line function""" + class meta: + id = ed_glob.ID_GOTO_LINE + + def __init__(self, parent): + super(GotoLineBar, self).__init__(parent) + + # Attributes + self.SetControl(LineCtrl(self, wx.ID_ANY, + self._parent.nb.GetCurrentCtrl, + size=(100, -1))) + + # Setup + self.EnableMenu(False) + go_lbl = wx.StaticText(self, label=_("Goto Line") + ": ") + self.AddControl(go_lbl, wx.ALIGN_LEFT) + self.AddControl(self.ctrl, wx.ALIGN_LEFT) + + # HACK: workaround bug in mac control that resets size to + # that of the default variant after any text has been + # typed in it. Note it reports the best size as the default + # variant and causes layout issues. wxBUG + if wx.Platform == '__WXMAC__': + self.ctrl.SetSizeHints(100, 16, 100, 16) + +#-----------------------------------------------------------------------------# + +class CommandExecuter(eclib.CommandEntryBase): + """Part of the Vi emulation, opens a minibuffer to execute EX commands. + @note: based on search ctrl so we get the nice rounded edges on wxmac. + + """ + RE_GO_BUFFER = re.compile('[0-9]*[nN]{1,1}') + RE_GO_WIN = re.compile('[0-9]*n[wW]{1,1}') + RE_WGO_BUFFER = re.compile('w[0-9]*[nN]') + RE_NGO_LINE = re.compile('[+-][0-9]+') + + def __init__(self, parent, id_, size=wx.DefaultSize): + """Initializes the CommandExecuter""" + super(CommandExecuter, self).__init__(parent, id_, size=size, + style=wx.TE_PROCESS_ENTER|wx.WANTS_CHARS) + + # Attributes + self._history = dict(cmds=[''], index=-1, lastval='') + if not hasattr(sys, 'frozen'): + self._curdir = os.path.abspath(os.curdir) + os.sep + else: + self._curdir = wx.GetHomeDir() + os.sep + + if wx.Platform == '__WXMAC__': + self._popup = PopupList(self) + self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) + self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + else: + self._popup = PopupWinList(self) + + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(ed_event.EVT_NOTIFY, self.OnPopupNotify) + + # Message handlers + ed_msg.Subscribe(self._UpdateCwd, ed_msg.EDMSG_UI_NB_CHANGED) + ed_msg.Subscribe(self._UpdateCwd, ed_msg.EDMSG_FILE_SAVED) + + def OnDestroy(self, evt): + """Clean up message handlers on destroy""" + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self._UpdateCwd) + evt.Skip() + + def _AdjustSize(self): + """Checks width of text as its added and dynamically resizes + the control as needed. + @todo: re-enable after resizing issue can be resolved + + """ + pass +# ext = self.GetTextExtent(self.GetValue())[0] +# curr_w, curr_h = self.GetClientSizeTuple() +# if ext > curr_w * .5: +# max_w = self.GetParent().GetClientSize().GetWidth() * .8 +# nwidth = min(ext * 1.3, max_w) +# pwidth = self._popup.GetBestSize()[0] +# if pwidth > nwidth: +# nwidth = pwidth +# self.SetClientSize((nwidth, curr_h)) +# self._popup.SetSize((nwidth, -1)) +# self.GetParent().Layout() +# elif ((curr_w > ext * 1.18) and curr_w > 150): +# nwidth = max(ext * 1.18, 150) +# self.SetClientSize((nwidth, curr_h)) +# self.GetParent().Layout() +# else: +# pass + + def _AdjustValue(self, val): + """Adjust value of input string as autocomp provides new values + @param val: val to use as base for adjustment + + """ + cval = self.GetValue().split(' ', 1) + if val.startswith(cval[-1]) or val.startswith('~'): + self.AppendText(val.replace(cval[-1], '', 1)) + else: + self.SetValue(" ".join([cval[0], val])) + self.SetInsertionPoint(self.GetLastPosition()) + + def _UpdateCwd(self, msg): + """Update the current working directory to that of the current + buffer. + @param msg: Message Object + + """ + # Only Update if we are the currently active window + tlp = self.GetTopLevelParent() + if tlp.IsActive(): + ctrl = tlp.GetNotebook().GetCurrentCtrl() + fname = ctrl.GetFileName() + if len(fname): + self._curdir = os.path.dirname(fname) + + def ChangeDir(self, cmd): + """Change to a directory based on cd command + @param cmd: cd path + + """ + path = cmd.replace('cd', '', 1).strip() + if not os.path.isabs(path): + if path.startswith('..'): + path = os.path.abspath(path) + elif path.startswith('~'): + path = path.replace('~', wx.GetHomeDir(), 1) + else: + path = os.path.join(self._curdir, path) + + if os.path.exists(path) and os.path.isdir(path): + if os.access(path, os.R_OK): + os.chdir(path) + self._curdir = os.path.abspath(os.path.curdir) + os.sep + else: + # Doesn't have permissions + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, + _("Can't change directory to: %s") % path)) + wx.Bell() + self.Clear() + else: + # Invalid path + self.Clear() + wx.Bell() + + def CommandPush(self, cmd): + """Push a command to the stack popping as necessary to + keep stack size less than MAX (currently 25 commands). + @param cmd: command string to push + @todo: redo this to be more like the code in my terminal project + + """ + cmd = cmd.strip() + if not len(cmd): + return + + if len(self._history['cmds']) > 25: + self._history['cmds'].pop() + + if cmd != self._history['cmds'][0]: + self._history['cmds'].insert(0, cmd) + + self._history['index'] = -1 + + def EditCommand(self, cmd): + """Perform an edit related command + @param cmd: command string to execute + + """ + # e fname: edit file + cmd = cmd[1:].strip() + frame = self.GetTopLevelParent() + cmd = ebmlib.GetPathFromURI(cmd) + if not os.path.isabs(cmd): + cmd = os.path.join(self._curdir, cmd) + + if ebmlib.PathExists(cmd): + frame.DoOpen(ed_glob.ID_COMMAND_LINE_OPEN, cmd) + else: + frame.nb.OpenPage(ebmlib.GetPathName(cmd), ebmlib.GetFileName(cmd)) + + def ExecuteCommand(self, cmd_str): + """Interprets and executes a command then hides the control + @param cmd_str: Command string to execute + + """ + frame = self.GetTopLevelParent() + cmd = cmd_str.strip().lstrip(':') + if cmd in ['x', 'ZZ']: + cmd = 'wq' + + if cmd.startswith(u'w'): + frame.OnSave(wx.MenuEvent(wx.wxEVT_COMMAND_MENU_SELECTED, + ed_glob.ID_SAVE)) + if self.RE_WGO_BUFFER.match(cmd): + self.GoBuffer(cmd[1:]) + elif cmd == 'wq': + self.Quit() + elif cmd.startswith(u'e '): + self.EditCommand(cmd) + elif cmd.rstrip() == u'e!': + ctrl = frame.nb.GetCurrentCtrl() + ctrl.RevertToSaved() + elif self.RE_GO_WIN.match(cmd): + self.GoWindow(cmd) + elif re.match(self.RE_GO_BUFFER, cmd): + self.GoBuffer(cmd) + elif cmd.isdigit() or self.RE_NGO_LINE.match(cmd): + ctrl = frame.nb.GetCurrentCtrl() + cline = ctrl.GetCurrentLine() + if cmd[0] in '+-': + line = eval("%s %s %s" % (str(cline), cmd[0], cmd[1:])) + else: + line = int(cmd) - 1 + ctrl.GotoLine(line) + elif cmd.startswith('cd '): + self.ChangeDir(cmd) + elif cmd == 'q': + self.Quit() + else: + wx.Bell() + return + + self.CommandPush(cmd_str) + self.GetParent().Hide() + + def GetHistCommand(self, pre=True): + """Look up a command from the history of recent commands + @param pre: Get previous (default) or get Next + @note: pre moves right in stack, next moves left in stack + + """ + val = self.GetValue().strip() + if val not in self._history['cmds']: + self._history['lastval'] = val + + if pre: + if self._history['index'] < len(self._history['cmds']) - 1\ + and self._history['index'] < 25: + self._history['index'] += 1 + + index = self._history['index'] + cmd = self._history['cmds'][index] + else: + if self._history['index'] > -1: + self._history['index'] -= 1 + + index = self._history['index'] + if index == -1: + cmd = self._history['lastval'] + else: + cmd = self._history['cmds'][index] + + self.SetValue(cmd) + self.SelectAll() + + def GoBuffer(self, cmd): + """Go to next/previous buffer in notebook + @param cmd: cmd string [0-9]*[nN] + + """ + count = cmd[0:-1] + cmd = cmd[-1] + if count.isdigit(): + count = int(count) + else: + count = 1 + + frame = self.GetTopLevelParent() + numpage = frame.nb.GetPageCount() + for x in range(min(count, numpage)): + cpage = frame.nb.GetPageIndex(frame.nb.GetCurrentPage()) + if (cpage == 0 and cmd == 'N') or \ + (cpage + 1 == numpage and cmd == 'n'): + break + frame.nb.AdvanceSelection(cmd == 'n') + + def GoWindow(self, cmd): + """Go to next/previous open window + @param cmd: cmd string [0-9]*n[wW] + + """ + count = cmd[0:-1] + cmd = cmd[-1] + if count.isdigit(): + count = int(count) + else: + count = 1 + wins = wx.GetApp().GetMainWindows() + pid = self.GetTopLevelParent().GetId() + widx = 0 + win = 0 + for nwin in xrange(len(wins)): + if pid == wins[nwin].GetId(): + widx = pid + win = nwin + break + + if cmd == 'W': + widx = win + count + else: + widx = win - count + + if widx < 0: + widx = 0 + elif widx >= len(wins): + widx = len(wins) - 1 + self.GetParent().Hide() + wins[widx].Raise() + wx.CallAfter(wins[widx].nb.GetCurrentCtrl().SetFocus) + + def GetPaths(self, path, files=False): + """Get a list of paths that are part of the given path by + default it will only return directories. + @param path: Path to enumerate + @keyword files: Get list of files too + + """ + def append_slash(path): + """Helper function that appends a slash to the path + if it's a directory. + + """ + if os.path.isdir(path) and not path.endswith(os.sep): + return path + os.sep + return path + + curdir = self._curdir + head, tail = os.path.split(path) + head = os.path.expanduser(head) + head = os.path.expandvars(head) + head = os.path.join(curdir, head) + if not os.path.isdir(head): + return [] + + # Return empty list of user does not have + # read access to the directory + if not os.access(head, os.R_OK): + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, + _("Access Denied: %s") % head)) + wx.Bell() # Beep to alert + return list() + + # We expanded head, so trim the suggestion list of its head + # so we can add the tail of the suggestion back to the original head + try: + candidates = [os.path.basename(p) for p in os.listdir(head) + if p.startswith(tail)] + candidates = [append_slash(os.path.join(os.path.dirname(path), cand)) + for cand in candidates] + if not files: + candidates = [cand for cand in candidates if os.path.isdir(cand)] + except OSError: + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, _("Invalid Path"))) + candidates = list() + + return sorted(list(set(candidates))) + + def ListDir(self): + """List the next directory from the current cmd path""" + cmd = self.GetValue() + if cmd.startswith('cd '): + cstr = 'cd ' + elif cmd.startswith('e '): + cstr = 'e ' + else: + return + + cmd = cmd.replace(cstr, u'', 1).strip() + paths = self.GetPaths(cmd, cstr == 'e ') + self._popup.SetChoices(paths) + if len(paths): + self._popup.SetupPosition(self) + if not self._popup.IsShown(): + self._popup.Show() + + self.SetInsertionPoint(self.GetLastPosition()) + + def OnEnter(self, evt): + """Get the currently entered command string and execute it. + @postcondition: ctrl is cleared and command is executed + + """ + if self._popup.HasSuggestions() and self._popup.HasSelection(): + psel = self._popup.GetSelection() + if self.GetValue().split(' ', 1)[-1].strip() != psel: + self._AdjustValue(psel) + self._popup.Hide() + return + + cmd = self.GetValue() + self.Clear() + self.ExecuteCommand(cmd) + if self._popup.IsShown(): + self._popup.Hide() + + def OnKeyDown(self, evt): + """Records the key sequence that has been entered and + performs actions based on that key sequence. + @param evt: event that called this handler + + """ + e_key = evt.GetKeyCode() + cmd = self.GetValue() + + if e_key == wx.WXK_UP: + if self._popup.HasSuggestions(): + self._popup.AdvanceSelection(False) + else: + self.GetHistCommand(pre=True) + elif e_key == wx.WXK_DOWN: + if self._popup.HasSuggestions(): + self._popup.AdvanceSelection(True) + else: + self.GetHistCommand(pre=False) + elif e_key == wx.WXK_SPACE and not len(cmd): + # Swallow space key when command is empty + pass + elif e_key == wx.WXK_TAB: + # Provide Tab Completion or swallow key + if cmd.startswith('cd ') or cmd.startswith('e '): + if self._popup.HasSuggestions(): + self._AdjustValue(self._popup.GetSelection()) + self.ListDir() + else: + pass + elif e_key == wx.WXK_ESCAPE: + if self._popup.IsShown(): + self._popup.Hide() + else: + self.Clear() + self.GetParent().Hide() + else: + evt.Skip() + + def OnKeyUp(self, evt): + """Adjust size as needed when characters are entered + @param evt: event that called this handler + + """ + e_key = evt.GetKeyCode() + if e_key == wx.WXK_ESCAPE: + evt.Skip() + return + + val = self.GetValue() + cwd_info = "" + if val.strip() in ['cwd', 'e', 'cd']: + cwd_info = " " + _(u"cwd: ") + self._curdir + self.Parent.info_lbl.SetLabel(cwd_info) + if self._popup.IsShown(): + if not len(val): + self._popup.Hide() + else: + wx.CallAfter(self.UpdateAutoComp) + else: + if self._popup.HasSuggestions(): + self._AdjustValue(self._popup.GetSelection()) + self.ListDir() + self._AdjustSize() + evt.Skip() + + def OnPopupNotify(self, evt): + """Receive the selections from the popup list + @param evt: event that called this handler + + """ + val = evt.GetValue() + self._AdjustValue(val) + + def OnKillFocus(self, evt): + """Hide the popup when we look focus + @param evt: event that called this handler + + """ + self._popup.Hide() + evt.Skip() + + def OnSetFocus(self, evt): + """Ensure caret is at end when focus is reset + @param evt: event that called this handler + + """ + self.SetInsertionPoint(self.GetLastPosition()) + evt.Skip() + + def RestoreFocus(self): + """Restore focus and cursor position + @postcondition: ctrl has focus and cursor is moved to last position + + """ + self.SetInsertionPoint(self.GetLastPosition()) + self.SetFocus() + + def Quit(self): + """Tell the editor to exit + @postcondition: Editor begins exit, confirming file saves + + """ + wx.PostEvent(self.GetTopLevelParent(), + wx.CloseEvent(wx.wxEVT_CLOSE_WINDOW)) + + def SetValue(self, value): + """Overrides the controls default function to allow for automatic + resizing of the control when text is added. + @param value: string to set value of control to + + """ + super(CommandExecuter, self).SetValue(value) + self._AdjustSize() + + def UpdateAutoComp(self): + """Update the autocomp list for paths that best match current value""" + self.ListDir() + + def WriteCommand(self, cstr): + """Perform a file write related command + @param cstr: The command string to execute + + """ + # wn: write and edit next + # wN: write and edit previous + # wq: write and quit + +#-----------------------------------------------------------------------------# + +class LineCtrl(eclib.CommandEntryBase): + """A custom int control for providing a go To line control + for the Command Bar. + + """ + def __init__(self, parent, id_, get_doc, size=wx.DefaultSize): + """Initializes the LineCtrl control and its attributes. + @param parent: Parent Window + @param id_: Control ID + @param get_doc: callback method for retrieving a reference to the + current document. + @keyword size: Control Size (tuple) + + """ + super(LineCtrl, self).__init__(parent, id_, u"", size=size, + style=wx.TE_PROCESS_ENTER, + validator=util.IntValidator(0, 65535)) + + # Attributes + self._last = 0 + self.GetDoc = get_doc + + def OnEnter(self, evt): + """Processes the entered line number + @param evt: wx.EVT_TEXT_ENTER + + """ + val = self.GetValue() + if not val.isdigit(): + return + + val = int(val) - 1 + doc = self.GetDoc() + lines = doc.GetLineCount() + if val > lines: + val = lines + doc.GotoLine(val) + doc.SetFocus() + self.GetParent().Hide() + + def OnKeyUp(self, evt): + """Handle keyup events""" + if evt.GetEventType() != wx.wxEVT_KEY_UP: + evt.Skip() + return + + e_key = evt.GetKeyCode() + if e_key == wx.WXK_ESCAPE: + # TODO change to more safely determine the context + # Currently control is only used in command bar + self.GetParent().Hide() + else: + evt.Skip() + +#-----------------------------------------------------------------------------# +# TODO: merge the common parts of these two classes into a single base class + +class PopupListBase(object): + """Common functionality between Popuplist GTK and Mac""" + + def AdvanceSelection(self, next=True): + """Advance the list selection + @keyword next: goto the next or previous selection + + """ + sel = self._list.GetSelection() + if next: + count = self._list.GetCount() + sel += 1 + if sel < count: + self._list.SetSelection(sel) + else: + sel -= 1 + if sel >= 0: + self._list.SetSelection(sel) + + def GetSelection(self): + """Get the string that is currently selected in the list + @return: string selection + + """ + return self._list.GetStringSelection() + + def HasSelection(self): + """Tells whether anything in the list is selected""" + return self._list.GetSelection() != wx.NOT_FOUND + + def HasSuggestions(self): + """Tell whether the list is showing suggestions""" + return self.IsShown() and self.ListCount() > 0 + + def ListCount(self): + """return the number of elements in the popup list""" + return self._list.GetCount() + + def GetListCtrl(self): + """Get the ListBox control of the popupwindow""" + return self._list + + def GetChoices(self): + """Get the items as a list + @return: list of strings + + """ + return self._list.GetStrings() + + def SetSelection(self, index): + """Set the selection in the list by index + @param index: zero based index to set selection by + + """ + self._list.SetSelection(index) + +class PopupList(wx.MiniFrame, PopupListBase): + """Popup window with a listbox in it""" + def __init__(self, parent, choices=list(), pos=wx.DefaultPosition): + + style = wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT + if wx.Platform == '__WXMAC__': + style = style | wx.BORDER_NONE | wx.POPUP_WINDOW + else: + style = style | wx.SIMPLE_BORDER + + wx.MiniFrame.__init__(self, parent, pos=pos, style=style) + PopupListBase.__init__(self) + + # Attributes + self._list = wx.ListBox(self, choices=choices, + style=wx.LC_REPORT | wx.LC_SINGLE_SEL | + wx.LC_NO_HEADER | wx.NO_BORDER) + + # Layout + self._list.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self._list, 1, wx.EXPAND) + self.SetSizer(sizer) + txt_h = self.GetTextExtent('/')[1] + self.SetMaxSize((-1, txt_h * 6)) + self.SetAutoLayout(True) + + # Event Handlers + self.Bind(wx.EVT_CHAR, lambda evt: parent.GetEventHandler().ProcessEvent(evt)) + self.Bind(wx.EVT_SET_FOCUS, self.OnFocus) + self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnSelection) + self.Bind(wx.EVT_SIZE, self.OnSize) + self._list.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + + self._list.SetFocus() + self.Hide() + + def __PostEvent(self): + """Post notification of selection to parent + @postcondition: selected string is posted to parent + + """ + val = self._list.GetStringSelection() + evt = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY, + self.GetId(), val, self._list) + wx.PostEvent(self.GetParent(), evt) + self.ActivateParent() + + def ActivateParent(self): + """Activate the parent window + @postcondition: parent window is raised + + """ + parent = self.GetParent() + parent.Raise() + parent.SetFocus() + + def OnFocus(self, evt): + """Raise and reset the focus to the parent window whenever + we get focus. + @param evt: event that called this handler + + """ + self.ActivateParent() + self.GetParent().SetFocus() + evt.Skip() + + def OnKeyUp(self, evt): + """Process key up events in the control + @param evt: event that called this handler + + """ + if evt.GetKeyCode() == wx.WXK_RETURN: + self.__PostEvent() + else: + evt.Skip() + + def OnSelection(self, evt): + """Handle a selection in list by posting the result to + the parent. + @param evt: Event that called this handler + + """ + self.__PostEvent() + + def OnSize(self, evt): + """Resize the listbox""" + csz = self.GetClientSize() + csz.SetWidth(csz.x + wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)) + self._list.SetSize(csz) + evt.Skip() + + def Show(self, show=True): + """Adjust size of popup and then show it + @keyword show: Should the window be shown or not + + """ + res = super(PopupList, self).Show(show) + + if res and show: + self.ActivateParent() + + if wx.Platform == '__WXMAC__': + self.GetParent().Refresh(False) + + return res + + def SetChoices(self, choices): + """Set the available choices that are shown in the list + @param choices: list of strings + + """ + selection = self._list.GetSelection() + self._list.SetItems(choices) + count = self._list.GetCount() + if selection == wx.NOT_FOUND or selection >= count: + selection = 0 + if count > 0: + self._list.SetSelection(selection) + + def SetStringSelection(self, text): + """Set the list selection by using a string value + @param text: string to select in list + + """ + self._list.SetStringSelection(text) + + def SetupPosition(self, cmd_ex): + """Sets size and position of widget + @param cmd_ex: CommandExecuter window + + """ + cmd = cmd_ex.GetValue() + cmd = cmd.split(u' ', 1)[0] + xpos = cmd_ex.GetTextExtent(cmd + u' ')[0] + pos = cmd_ex.GetScreenPosition().Get() + csize = cmd_ex.GetSize() + self.SetPosition((pos[0] + xpos, pos[1] + csize[1])) + self.ActivateParent() + +#----------------------------------------------------------------------------# + +class PopupWinList(wx.PopupWindow, PopupListBase): + """Popuplist for Windows/GTK""" + def __init__(self, parent, choices=list(), pos=wx.DefaultPosition): + """Create the popup window and its list control""" + wx.PopupWindow.__init__(self, parent) + PopupListBase.__init__(self) + + # Attributes + self._list = wx.ListBox(self, choices=choices, pos=(0, 0), + style=wx.LC_REPORT | wx.LC_SINGLE_SEL | + wx.LC_NO_HEADER) + + # Layout + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self._list, 0, wx.EXPAND) + self.SetSizer(sizer) + txt_h = self.GetTextExtent('/')[1] + self.SetMaxSize((-1, txt_h * 6)) + self.SetAutoLayout(True) + + # Event Handlers + self.Bind(wx.EVT_SIZE, self.OnSize) + + def OnSize(self, evt): + """Resize the list box to the correct size to fit.""" + csz = self.GetClientSize() + csz.SetWidth(csz.x + wx.SystemSettings.GetMetric(wx.SYS_VSCROLL_X)) + self._list.SetSize(csz) + evt.Skip() + + def SetupPosition(self, cmd_ex): + """Sets size and position of widget + @param cmd_ex: CommandExecuter window + + """ + cmd = cmd_ex.GetValue() + cmd = cmd.split(u' ', 1)[0] + pos = cmd_ex.GetScreenPosition().Get() + csize = cmd_ex.GetSize() + xpos = cmd_ex.GetTextExtent(cmd)[0] + self._list.SetInitialSize() + self.SetInitialSize() + self.SetPosition((pos[0] + xpos, pos[1] + csize[1])) + + def SetChoices(self, choices): + """Set the available choices that are shown in the list + @param choices: list of strings + + """ + selection = self._list.GetSelection() + self._list.SetItems(choices) + count = self._list.GetCount() + if selection == wx.NOT_FOUND or selection >= count: + selection = 0 + if count > 0: + self._list.SetSelection(selection) + + def Show(self, show=True): + """Adjust size of popup and then show it + @keyword show: Should the window be shown or not + + """ + res = super(PopupWinList, self).Show(show) + + self._list.Show() + self._list.SetInitialSize() + self.SetInitialSize() + + return res diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_crypt.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_crypt.py new file mode 100644 index 0000000..cec2215 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_crypt.py @@ -0,0 +1,120 @@ +############################################################################### +# Name: ed_crypt.py # +# Purpose: Cryptography Library for encrypting/decrypting saved data # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module provides utilities for encrypting and decrypting data. It is mostly +used for saving passwords and other sensitive data in config files. The code in +this file uses a fairly simple string transformation algorithm combined with a +random salt for the encryption/decryption, and I also threw in a little code +obfustication just for fun ;-). + +USAGE: + +Encrypt: + 1. Get the password string to encrypt + 2. Generate a new random salt with os.urandom() or some other randomly + generated string for each password to use as an encryption key + 3. Encrypt the password by calling Encrypt(password, salt) + 4. Save the salt somewhere else + 5. Write out the encrypted password to your config file + +Decrypt: + 1. Get the encrypted password string + 2. Get the associated salt + 3. Decrypt and get the orignal password by calling + Decrypt(encrypted_passwd, salt) + +EXAMPLE: + + >>> salt = os.urandom(8) + >>> passwd = "HelloWorld" + >>> encrypted_passwd = Encrypt(passwd, salt) + >>> print encrypted_passwd + eNoNysERADAIArCVUAFx/8XauzyTqTEtdKEXoQIWCbCZjaM74qhPlhK4f+BVPKTTyQP7JQ5i + >>> decrypted_passwd = Decrypt(passwd, salt) + >>> print decrypted_passwd + HelloWorld + +Finally: +This message will self destruct in 5 seconds ... + +@summary: Cryptographic routines for encrypting/decrypting text + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_crypt.py 52855 2008-03-27 14:53:06Z CJP $" +__revision__ = "$Revision: 52855 $" + +__all__ = [ 'Encrypt', 'Decrypt' ] + +#-----------------------------------------------------------------------------# +# Import +import os +import zlib +import random +import base64 + +#-----------------------------------------------------------------------------# +# Private Functions + +def _Encode(text): + g = lambda y: (y!='\\' and [y] or [str(8+(random.randint(0,100)%2))])[0] + return ''.join([g(y) for y in ''.join(['\\%o'%ord(x) for x in text])]) + +def _Decode(text): + exec 's="'+text.replace('8','\\').replace('9','\\')+'"' + return s + +#-----------------------------------------------------------------------------# +# Public Functions + +def Encrypt(passwd, salt): + """Encrypt the given password string using the supplied salt as the + cryptographic key. If either the passwd or salt strings are empty the + return value will be the same as the passwd parameter. + @param passwd: String to encrypt + @param salt: key to encrypt string with + + """ + if not len(passwd.strip()) or not len(salt.strip()): + return passwd + else: + return base64.b64encode(zlib.compress(str(long(_Encode(passwd))*\ + long(_Encode(salt).replace('8','9'))),9)) + +def Decrypt(passwd, salt): + """Decrypt the given password string using the supplied salt as a key + If either the passwd or salt strings are empty the return value will be + the same as the passwd parameter. + @param passwd: a non empty string + @param salt: a non empty string + + """ + if not len(passwd.strip()) or not len(salt.strip()): + return passwd + else: + return _Decode(str(long(zlib.decompress(base64.b64decode(passwd)))/\ + long(str.replace(_Encode(salt),'8','9')))) + +#-----------------------------------------------------------------------------# +# Test +if __name__ == '__main__': + TEST_FILE = "TEST_passwd.crypt" + PASSWD = 'HelloWorld' + salt = os.urandom(8) + print "PASSWORD STR: ", PASSWD + es = Encrypt(PASSWD, salt) + print "ENCRYPTED STR: ", es + print "DECRYPTED STR: ", Decrypt(es, salt) + + print "Empty String Test" + salt2 = os.urandom(8) + es = Encrypt('', salt2) + print "Encrypted String", es + print "Decrypted String", Decrypt(es, salt) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_editv.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_editv.py new file mode 100644 index 0000000..9d7a024 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_editv.py @@ -0,0 +1,641 @@ +############################################################################### +# Name: ed_editv.py # +# Purpose: Editor view notebook tab implementation # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Text editor buffer view control for the main notebook + +@summary: Editor view + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_editv.py 72901 2012-11-05 15:19:28Z CJP $" +__revision__ = "$Revision: 72901 $" + +#--------------------------------------------------------------------------# +# Imports +import wx +import os + +# Editra Libraries +import ed_glob +import ed_menu +import ed_msg +import ed_stc +import ed_tab +from doctools import DocPositionMgr +from profiler import Profile_Get +from util import Log, SetClipboardText +import syntax.synglob as synglob +from ebmlib import GetFileModTime, ContextMenuManager, GetFileName + +# External libs +from extern.stcspellcheck import STCSpellCheck + +#--------------------------------------------------------------------------# + +ID_SPELL_1 = wx.NewId() +ID_SPELL_2 = wx.NewId() +ID_SPELL_3 = wx.NewId() + +_ = wx.GetTranslation + +def modalcheck(func): + """Decorator method to add extra modality guards to functions that + show modal dialogs. Arg 0 must be a Window instance. + + """ + def WrapModal(*args, **kwargs): + """Wrapper method to guard against multiple dialogs being shown""" + self = args[0] + self._has_dlg = True + func(*args, **kwargs) + self._has_dlg = False + + WrapModal.__name__ = func.__name__ + WrapModal.__doc__ = func.__doc__ + return WrapModal + +#--------------------------------------------------------------------------# + +class EdEditorView(ed_stc.EditraStc, ed_tab.EdTabBase): + """Tab editor view for main notebook control.""" + ID_NO_SUGGEST = wx.NewId() + ID_ADD_TO_DICT = wx.NewId() + ID_IGNORE = wx.NewId() + ID_SPELLING_MENU = wx.NewId() + ID_CLOSE_TAB = wx.NewId() + ID_CLOSE_ALL_TABS = wx.NewId() + DOCMGR = DocPositionMgr() + + def __init__(self, parent, id_=wx.ID_ANY, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=0, use_dt=True): + """Initialize the editor view""" + ed_stc.EditraStc.__init__(self, parent, id_, pos, size, style, use_dt) + ed_tab.EdTabBase.__init__(self) + + # Attributes + self._ro_img = False + self._ignore_del = False + self._has_dlg = False + self._lprio = 0 # Idle event priority counter + self._menu = ContextMenuManager() + self._spell = STCSpellCheck(self, check_region=self.IsNonCode) + self._caret_w = 1 + self._focused = True + spref = Profile_Get('SPELLCHECK', default=dict()) + self._spell_data = dict(choices=list(), + word=('', -1, -1), + enabled=spref.get('auto', False)) + + # Initialize the classes position manager for the first control + # that is created only. + if not EdEditorView.DOCMGR.IsInitialized(): + EdEditorView.DOCMGR.InitPositionCache(ed_glob.CONFIG['CACHE_DIR'] + \ + os.sep + u'positions') + + self._spell.clearAll() + self._spell.setDefaultLanguage(spref.get('dict', 'en_US')) + self._spell.startIdleProcessing() + + # Context Menu Events + self.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu) + + # Need to relay the menu events from the context menu to the top level + # window to be handled on gtk. Other platforms don't require this. + self.Bind(wx.EVT_MENU, self.OnMenuEvent) + + # Hide autocomp/calltips when window looses focus + # TODO: decide on whether this belongs in base class or not + self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + self.Bind(wx.EVT_LEFT_UP, self.OnSetFocus) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + + # Subscribe for configuration updates + for opt in ('AUTOBACKUP', 'SYNTHEME', 'SYNTAX', 'BRACKETHL', 'GUIDES', + 'SHOW_EDGE', 'EDGE', 'CODE_FOLD', 'AUTO_COMP', + 'AUTO_INDENT', 'HLCARETLINE', 'SPELLCHECK', 'VI_EMU', + 'VI_NORMAL_DEFAULT', 'USETABS', 'TABWIDTH', 'INDENTWIDTH', + 'BSUNINDENT', 'EOL_MODE', 'AALIASING', 'SHOW_EOL', 'SHOW_LN', + 'SHOW_WS', 'WRAP', 'VIEWVERTSPACE'): + ed_msg.Subscribe(self.OnConfigMsg, + ed_msg.EDMSG_PROFILE_CHANGE + (opt,)) + + def OnDestroy(self, evt): + """Cleanup message handlers on destroy""" + if evt.Id == self.Id: + ed_msg.Unsubscribe(self.OnConfigMsg) + evt.Skip() + + #---- EdTab Methods ----# + + def DoDeactivateTab(self): + """Deactivate any active popups when the tab is no longer + the active tab. + + """ + self._menu.Clear() + self.HidePopups() + + def DoOnIdle(self): + """Check if the file has been modified and prompt a warning""" + # Don't check while the file is loading + if self.IsLoading(): + return + + # Handle hiding and showing the caret when the window gets loses focus + cfocus = self.FindFocus() + if not self._focused and cfocus is self: + # Focus has just returned to the window + self.RestoreCaret() + self._focused = True + elif self._focused and cfocus is not self: + self.HideCaret() # Hide the caret when not active + self._focused = False + self.CallTipCancel() + + # Check for changes to on disk file + if not self._has_dlg and Profile_Get('CHECKMOD'): + cfile = self.GetFileName() + lmod = GetFileModTime(cfile) + mtime = self.GetModTime() + if mtime and not lmod and not os.path.exists(cfile): + # File was deleted since last check + wx.CallAfter(self.PromptToReSave, cfile) + elif mtime < lmod: + # Check if we should automatically reload the file or not + if Profile_Get('AUTO_RELOAD', default=False) and \ + not self.GetModify(): + wx.CallAfter(self.DoReloadFile) + else: + wx.CallAfter(self.AskToReload, cfile) + + # Check for changes to permissions + if self.File.IsReadOnly() != self._ro_img: + self._nb.SetPageBitmap(self.GetTabIndex(), self.GetTabImage()) + self._nb.Refresh() + else: + pass + + # Handle Low(er) priority idle events + self._lprio += 1 + if self._lprio == 2: + self._lprio = 0 # Reset counter + # Do spell checking + # TODO: Add generic subscriber hook and move spell checking and + # and other low priority idle handling there + if self.IsShown(): + if self._spell_data['enabled']: + self._spell.processCurrentlyVisibleBlock() + else: + # Ensure calltips are not shown when this is a background tab. + self.CallTipCancel() + + @modalcheck + def DoReloadFile(self): + """Reload the current file""" + cfile = self.GetFileName() + ret = True + rmsg = u"" + try: + ret, rmsg = self.ReloadFile() + except Exception, msg: + # Unexpected error + wx.MessageBox(_("Failed to reload file\n\nError:\n%s") % msg, + _("File read error"), wx.ICON_ERROR|wx.OK|wx.CENTER) + # Set modtime to prevent re-prompting of dialog regardless of error cases + self.SetModTime(GetFileModTime(cfile)) + return + + # Check for expected errors + if not ret: + errmap = dict(filename=cfile, errmsg=rmsg) + mdlg = wx.MessageDialog(self, + _("Failed to reload %(filename)s:\n" + "Error: %(errmsg)s") % errmap, + _("Error"), + wx.OK | wx.ICON_ERROR) + mdlg.ShowModal() + mdlg.Destroy() + + # Set modtime to prevent re-prompting of dialog regardless of error cases + self.SetModTime(GetFileModTime(cfile)) + + def DoTabClosing(self): + """Save the current position in the buffer to reset on next load""" + if len(self.GetFileName()) > 1: + EdEditorView.DOCMGR.AddRecord([self.GetFileName(), + self.GetCurrentPos()]) + + def DoTabOpen(self, ): + """Called to open a new tab""" + pass + + def DoTabSelected(self): + """Performs updates that need to happen when this tab is selected""" + Log("[ed_editv][info] Tab has file: %s" % self.GetFileName()) + self.PostPositionEvent() + + def GetName(self): + """Gets the unique name for this tab control. + @return: (unicode) string + + """ + return u"EditraTextCtrl" + + def GetTabImage(self): + """Get the Bitmap to use for the tab + @return: wx.Bitmap (16x16) + + """ + if self.GetDocument().ReadOnly: + self._ro_img = True + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_READONLY), wx.ART_MENU) + else: + self._ro_img = False + lang_id = str(self.GetLangId()) + bmp = wx.ArtProvider.GetBitmap(lang_id, wx.ART_MENU) + if bmp.IsNull(): + bmp = wx.ArtProvider.GetBitmap(str(synglob.ID_LANG_TXT), wx.ART_MENU) + return bmp + + def GetTabMenu(self): + """Get the tab menu + @return: wx.Menu + @todo: move logic from notebook to here + @todo: generalize generic actions to base class (close, new, etc..) + + """ + ptxt = self.GetTabLabel() + + menu = ed_menu.EdMenu() + menu.Append(ed_glob.ID_NEW, _("New Tab")) + menu.Append(ed_glob.ID_MOVE_TAB, _("Move Tab to New Window")) + menu.AppendSeparator() + menu.Append(ed_glob.ID_SAVE, _("Save \"%s\"") % ptxt) + menu.Append(EdEditorView.ID_CLOSE_TAB, _("Close \"%s\"") % ptxt) + menu.Append(ed_glob.ID_CLOSE_OTHERS, _("Close Other Tabs")) + menu.Append(EdEditorView.ID_CLOSE_ALL_TABS, _("Close All")) + menu.AppendSeparator() + menu.Append(ed_glob.ID_COPY_FILE, _("Copy Filename")) + menu.Append(ed_glob.ID_COPY_PATH, _("Copy Full Path")) + return menu + + def GetTitleString(self): + """Get the title string to display in the MainWindows title bar + @return: (unicode) string + + """ + fname = self.GetFileName() + title = os.path.split(fname)[-1] + + # Its an unsaved buffer + if not len(title): + title = fname = self.GetTabLabel() + + if self.GetModify() and not title.startswith(u'*'): + title = u"*" + title + return u"%s - file://%s" % (title, fname) + + def CanCloseTab(self): + """Called when checking if tab can be closed or not + @return: bool + + """ + if self._ignore_del: + self._ignore_del = False + return True + + result = True + if self.GetModify(): + result = self.ModifySave() + result = result in (wx.ID_YES, wx.ID_OK, wx.ID_NO) + if result: + self._ignore_del = True + + return result + + def OnSetFocus(self, evt): + """Make sure that the currently selected tab is this one""" + evt.Skip() + parent = self.GetParent() + csel = parent.GetSelection() + idx = self.GetTabIndex() + if csel != idx: + parent.SetSelection(idx) + + def OnSpelling(self, buff, evt): + """Context menu subscriber callback + @param buff: buffer menu event happened in + @param evt: MenuEvent + + """ + e_id = evt.Id + spelld = self._spell.getSpellingDictionary() + if e_id == EdEditorView.ID_ADD_TO_DICT: + # Permanently add to users spelling dictionary + if spelld: + spelld.add(self._spell_data['word'][0]) + self.RefreshSpellcheck() + elif e_id == EdEditorView.ID_IGNORE: + # Ignore spelling for this session + if spelld: + spelld.add_to_session(self._spell_data['word'][0]) + self.RefreshSpellcheck() + else: + replace = None + for choice in self._spell_data['choices']: + if e_id == choice[0]: + replace = choice[1] + break + + if replace is not None: + buff.SetTargetStart(self._spell_data['word'][1]) + buff.SetTargetEnd(self._spell_data['word'][2]) + buff.ReplaceTarget(replace) + + def RefreshSpellcheck(self): + """Refresh the visible text area for spellchecking""" + fline = self.GetFirstVisibleLine() + first = self.GetLineStartPosition(fline) + lline = self.GetLastVisibleLine() + last = self.GetLineEndPosition(lline) + self._spell.addDirtyRange(first, last, 0, False) + + def OnTabMenu(self, evt): + """Tab menu event handler""" + e_id = evt.GetId() + if e_id in (ed_glob.ID_COPY_PATH, ed_glob.ID_COPY_FILE): + path = self.GetFileName() + if path is not None: + if e_id == ed_glob.ID_COPY_FILE: + path = GetFileName(path) + SetClipboardText(path) + elif e_id == ed_glob.ID_MOVE_TAB: + frame = wx.GetApp().OpenNewWindow() + nbook = frame.GetNotebook() + parent = self.GetParent() + pg_txt = parent.GetRawPageText(parent.GetSelection()) + nbook.OpenDocPointer(self.GetDocPointer(), + self.GetDocument(), pg_txt) + self._ignore_del = True + wx.CallAfter(parent.ClosePage) + elif e_id == ed_glob.ID_CLOSE_OTHERS: + parent = self.GetParent() + if hasattr(parent, 'CloseOtherPages'): + parent.CloseOtherPages() + elif e_id in (EdEditorView.ID_CLOSE_TAB, EdEditorView.ID_CLOSE_ALL_TABS): + # Need to relay events up to toplevel window on GTK for them to + # be processed. On other platforms the propagate by themselves. + evt.SetId({ EdEditorView.ID_CLOSE_TAB : ed_glob.ID_CLOSE, + EdEditorView.ID_CLOSE_ALL_TABS : ed_glob.ID_CLOSEALL}.get(e_id)) + wx.PostEvent(self.GetTopLevelParent(), evt) + else: + evt.Skip() + + #---- End EdTab Methods ----# + + def OnKillFocus(self, evt): + """Hide popups when focus is lost + @note: call to skip is necessary + + """ + self.HidePopups() + evt.Skip() + + def OnConfigMsg(self, msg): + """Update config based on profile changes""" + mtype = msg.GetType()[-1] + mdata = msg.GetData() + if mtype == 'SPELLCHECK': + self._spell_data['enabled'] = mdata.get('auto', False) + self._spell.setDefaultLanguage(mdata.get('dict', 'en_US')) + if not self._spell_data['enabled']: + self._spell.clearAll() + return + elif mtype == 'AUTO_COMP_EX': + self.ConfigureAutoComp() + return + elif mtype == 'CARETWIDTH': + if self.GetCaretWidth(): # check that it is not hidden + self.RestoreCaret() + return + elif mtype in ('VI_EMU', 'VI_NORMAL_DEFAULT'): + self.SetViEmulationMode(Profile_Get('VI_EMU'), + Profile_Get('VI_NORMAL_DEFAULT')) + return + elif mtype == 'VIEWVERTSPACE': + self.SetEndAtLastLine(not Profile_Get('VIEWVERTSPACE')) + + # Update other settings + cfgmap = { 'AUTOBACKUP' : self.EnableAutoBackup, + 'SYNTHEME' : self.UpdateAllStyles, + 'SYNTAX' : self.SyntaxOnOff, + 'BRACKETHL' : self.ToggleBracketHL, + 'GUIDES' : self.SetIndentationGuides, + 'SHOW_EDGE' : self.SetViewEdgeGuide, + 'EDGE' : self.SetViewEdgeGuide, + 'CODE_FOLD' : self.FoldingOnOff, + 'AUTO_COMP' : self.SetAutoComplete, + 'AUTO_INDENT': self.ToggleAutoIndent, + 'HLCARETLINE': self.SetCaretLineVisible, + 'USETABS' : self.SetUseTabs, + 'BSUNINDENT' : self.SetBackSpaceUnIndents, + 'EOL_MODE' : self.SetEOLMode, + 'AALIASING' : self.SetUseAntiAliasing, + 'SHOW_EOL' : self.SetViewEOL, + 'SHOW_LN' : self.ToggleLineNumbers, + 'SHOW_WS' : self.SetViewWhiteSpace, + 'WRAP' : self.SetWrapMode } + + if mtype in cfgmap: + cfgmap[mtype](Profile_Get(mtype)) + return + + cfgmap2 = { 'TABWIDTH' : self.SetTabWidth, + 'INDENTWIDTH': self.SetIndent } + if mtype in cfgmap2: + cfgmap2[mtype](Profile_Get(mtype, 'int')) + + def OnContextMenu(self, evt): + """Handle right click menu events in the buffer""" + self._menu.Clear() + + menu = ed_menu.EdMenu() + menu.Append(ed_glob.ID_UNDO, _("Undo")) + menu.Append(ed_glob.ID_REDO, _("Redo")) + menu.AppendSeparator() + menu.Append(ed_glob.ID_CUT, _("Cut")) + menu.Append(ed_glob.ID_COPY, _("Copy")) + menu.Append(ed_glob.ID_PASTE, _("Paste")) + menu.AppendSeparator() + menu.Append(ed_glob.ID_TO_UPPER, _("To Uppercase")) + menu.Append(ed_glob.ID_TO_LOWER, _("To Lowercase")) + menu.AppendSeparator() + menu.Append(ed_glob.ID_SELECTALL, _("Select All")) + + # Allow clients to customize the context menu + self._menu.SetMenu(menu) + pos = evt.GetPosition() + bpos = self.PositionFromPoint(self.ScreenToClient(pos)) + self._menu.SetPosition(bpos) + self._menu.SetUserData('buffer', self) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_CONTEXT_MENU, + self._menu, self.GetId()) + + #### Spell checking #### + # TODO: de-couple to the forthcoming buffer service interface + menu.InsertSeparator(0) + words = self.GetWordFromPosition(bpos) + self._spell_data['word'] = words + sugg = self._spell.getSuggestions(words[0]) + + # Don't give suggestions if the selected word is in the suggestions list + if words[0] in sugg: + sugg = list() + + if not len(sugg): + item = menu.Insert(0, EdEditorView.ID_NO_SUGGEST, _("No Suggestions")) + item.Enable(False) + else: + sugg = reversed(sugg[:min(len(sugg), 3)]) + ids = (ID_SPELL_1, ID_SPELL_2, ID_SPELL_3) + del self._spell_data['choices'] + self._spell_data['choices'] = list() + pos = 0 + for idx, sug in enumerate(sugg): + id_ = ids[idx] + self._menu.AddHandler(id_, self.OnSpelling) + self._spell_data['choices'].append((id_, sug)) + menu.Insert(0, id_, sug) + pos += 1 + # Add spelling settings menu + smenu = wx.Menu() + smenu.Append(EdEditorView.ID_IGNORE, _("Ignore")) + self._menu.AddHandler(EdEditorView.ID_IGNORE, self.OnSpelling) + smenu.Append(EdEditorView.ID_ADD_TO_DICT, + _("Add '%s' to dictionary") % self._spell_data['word'][0]) + self._menu.AddHandler(EdEditorView.ID_ADD_TO_DICT, self.OnSpelling) + menu.InsertSeparator(pos) + menu.InsertMenu(pos+1, EdEditorView.ID_SPELLING_MENU, + _("Spelling"), smenu) + #### End Spell Checking #### + + self.PopupMenu(self._menu.Menu) + evt.Skip() + + def OnMenuEvent(self, evt): + """Handle context menu events""" + e_id = evt.GetId() + handler = self._menu.GetHandler(e_id) + + # Handle custom menu items + if handler is not None: + handler(self, evt) + else: + self.ControlDispatch(evt) + if evt.GetSkipped(): + evt.Skip() + + def OnModified(self, evt): + """Overrides EditraBaseStc.OnModified""" + super(EdEditorView, self).OnModified(evt) + + # Handle word changes to update spell checking + # TODO: limit via preferences and move to buffer service once + # implemented. + mod = evt.GetModificationType() + if mod & wx.stc.STC_MOD_INSERTTEXT or mod & wx.stc.STC_MOD_DELETETEXT: + pos = evt.GetPosition() + last = pos + evt.GetLength() + self._spell.addDirtyRange(pos, last, evt.GetLinesAdded(), + mod & wx.stc.STC_MOD_DELETETEXT) + + @modalcheck + def PromptToReSave(self, cfile): + """Show a dialog prompting to resave the current file + @param cfile: the file in question + + """ + mdlg = wx.MessageDialog(self, + _("%s has been deleted since its " + "last save point.\n\nWould you " + "like to save it again?") % cfile, + _("Resave File?"), + wx.YES_NO | wx.ICON_INFORMATION) + mdlg.CenterOnParent() + result = mdlg.ShowModal() + mdlg.Destroy() + if result == wx.ID_YES: + result = self.SaveFile(cfile) + else: + self.SetModTime(0) + + @modalcheck + def AskToReload(self, cfile): + """Show a dialog asking if the file should be reloaded + @param cfile: the file to prompt for a reload of + + """ + if not self: + return + mdlg = wx.MessageDialog(self, + _("%s has been modified by another " + "application.\n\nWould you like " + "to reload it?") % cfile, + _("Reload File?"), + wx.YES_NO | wx.ICON_INFORMATION) + mdlg.CenterOnParent() + result = mdlg.ShowModal() + mdlg.Destroy() + if result == wx.ID_YES: + self.DoReloadFile() + else: + # Set modtime to prevent re-prompting of dialog + self.SetModTime(GetFileModTime(cfile)) + + def SetLexer(self, lexer): + """Override to toggle spell check context""" + super(EdEditorView, self).SetLexer(lexer) + + if lexer == wx.stc.STC_LEX_NULL: + self._spell.setCheckRegion(lambda p: True) + else: + self._spell.setCheckRegion(self.IsNonCode) + +#-----------------------------------------------------------------------------# + + def ModifySave(self): + """Called when document has been modified prompting + a message dialog asking if the user would like to save + the document before closing. + @return: Result value of whether the file was saved or not + + """ + name = self.GetFileName() + if name == u"": + name = self.GetTabLabel() + + dlg = wx.MessageDialog(self, + _("The file: \"%s\" has been modified since " + "the last save point.\n\nWould you like to " + "save the changes?") % name, + _("Save Changes?"), + wx.YES_NO | wx.YES_DEFAULT | wx.CANCEL | \ + wx.ICON_INFORMATION) + result = dlg.ShowModal() + dlg.Destroy() + + # HACK + if result == wx.ID_YES: + evt = wx.MenuEvent(wx.wxEVT_COMMAND_MENU_SELECTED, ed_glob.ID_SAVE) + tlw = self.GetTopLevelParent() + if hasattr(tlw, 'OnSave'): + tlw.OnSave(evt) + + return result diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_event.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_event.py new file mode 100644 index 0000000..c30f92b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_event.py @@ -0,0 +1,89 @@ +############################################################################### +# Name: ed_event.py # +# Purpose: Custom events used by Editra # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides custom events for the editors controls/objects to utilize + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_event.py 63789 2010-03-30 02:25:17Z CJP $" +__revision__ = "$Revision: 63789 $" + +#-----------------------------------------------------------------------------# +# Dependencies +import wx + +#-----------------------------------------------------------------------------# + +edEVT_UPDATE_TEXT = wx.NewEventType() +EVT_UPDATE_TEXT = wx.PyEventBinder(edEVT_UPDATE_TEXT, 1) +class UpdateTextEvent(wx.PyCommandEvent): + """Event to signal that text needs updating""" + def __init__(self, etype, eid, value=None): + """Creates the event object""" + wx.PyCommandEvent.__init__(self, etype, eid) + self._value = value + + def GetValue(self): + """Returns the value from the event. + @return: the value of this event + + """ + return self._value + +#--------------------------------------------------------------------------# + +edEVT_NOTIFY = wx.NewEventType() +EVT_NOTIFY = wx.PyEventBinder(edEVT_NOTIFY, 1) +class NotificationEvent(UpdateTextEvent): + """General notification event""" + def __init__(self, etype, eid, value=None, obj=None): + UpdateTextEvent.__init__(self, etype, eid, value) + self.SetEventObject(obj) + +#--------------------------------------------------------------------------# + +edEVT_MAINWINDOW_EXIT = wx.NewEventType() +EVT_MAINWINDOW_EXIT = wx.PyEventBinder(edEVT_MAINWINDOW_EXIT, 1) +class MainWindowExitEvent(wx.PyCommandEvent): + """Event to signal that the main window is exiting""" + pass + +#--------------------------------------------------------------------------# + +edEVT_STATUS = wx.NewEventType() +EVT_STATUS = wx.PyEventBinder(edEVT_STATUS, 1) +class StatusEvent(wx.PyCommandEvent): + """Event for posting status events""" + def __init__(self, etype, eid, msg=None, sec=0): + """Create an event that can be used to post status messages + to the main windows status bar. + @param etype: The type of event to create + @param eid: The event id + @keyword msg: The status message to post with the event + @keyword sec: The section of the status bar to post message to + + """ + wx.PyCommandEvent.__init__(self, etype, eid) + self._msg = msg + self._sec = sec + + def GetMessage(self): + """Returns the value from the event. + @return: the value of this event + + """ + return self._msg + + def GetSection(self): + """Returns the messages posting section + @return: int zero based index of where to post to statusbar + + """ + return self._sec diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_fmgr.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_fmgr.py new file mode 100644 index 0000000..9aeaa79 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_fmgr.py @@ -0,0 +1,81 @@ +############################################################################### +# Name: ed_fmgr.py # +# Purpose: Editra's Main Window Frame Manager # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" + + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: $" +__revision__ = "$Revision: $" + +#--------------------------------------------------------------------------# +# Dependencies +import wx +#import wx.lib.agw.aui as aui +import wx.aui as aui + +#--------------------------------------------------------------------------# +# Events + +EVT_AUI_PANE_CLOSE = aui.EVT_AUI_PANE_CLOSE +EVT_AUI_PANE_RESTORE = aui.EVT_AUI_PANE_RESTORE + +#--------------------------------------------------------------------------# + +class EdFrameManager(aui.AuiManager): + """Frame manager for external components to abstract underlying manager""" + def __init__(self, wnd=None, flags=0): + """Create the frame manager object + @param wnd: Frame to manage + @param flags: frame manager flags + + """ + super(EdFrameManager, self).__init__(wnd, flags) + self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPaneClose) + self.Bind(aui.EVT_AUI_PANE_RESTORE, self.OnPaneRestore) + + def OnPaneClose(self, evt): + """Notify pane it is being closed""" +# pane = evt.GetPane() +# print "Close", pane.window +# nevt = wx.ShowEvent(pane.window.Id, False) +# wx.PostEvent(pane.window, nevt) + evt.Skip() + + def OnPaneRestore(self, evt): + """Notify pane it is being opened""" +# pane = evt.GetPane() +# print "Restore:", pane.window +# nevt = wx.ShowEvent(pane.window.Id, True) +# wx.PostEvent(pane.window, nevt) + evt.Skip() + + def AddPane(self, wnd, info=None, caption=None): + return super(EdFrameManager, self).AddPane(wnd, info, caption) + + def IsEditorMaximized(self): + """Is the editor pane maximized? + return: bool + + """ + bEditMax = True + # If any other pane is open then the editor is not maximized + for pane in self.GetAllPanes(): + if pane.IsShown() and pane.name != "EditPane": + bEditMax = False + break + return bEditMax + +#--------------------------------------------------------------------------# + +EdPaneInfo = aui.AuiPaneInfo +# """Frame manager panel info""" +# def __init__(self): +# super(EdPaneInfo, self).__init__() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_glob.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_glob.py new file mode 100644 index 0000000..5126b17 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_glob.py @@ -0,0 +1,403 @@ +############################################################################### +# Name: ed_glob.py # +# Purpose: Global IDs/objects used throughout Editra # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This file contains variables that are or may be used in multiple files and +libraries within the project. Its purpose is to create a globally accessible +access point for all common variables in the project. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_glob.py 70747 2012-02-29 01:33:35Z CJP $" +__revision__ = "$Revision: 70747 $" + +__all__ = [ 'CONFIG', 'SB_INFO', 'VERSION', 'PROG_NAME', 'ID_NEW', 'ID_OPEN', + 'ID_CLOSE', 'ID_CLOSEALL', 'ID_SAVE', 'ID_SAVEAS', 'ID_SAVEALL', + 'ID_SAVE_PROFILE', 'ID_LOAD_PROFILE', 'ID_PRINT', 'ID_PRINT_PRE', + 'ID_PRINT_SU', 'ID_EXIT', 'ID_UNDO', 'ID_REDO', 'ID_CUT', + 'ID_COPY', 'ID_PASTE', 'ID_SELECTALL', 'ID_ADD_BM', + 'ID_DEL_ALL_BM', 'ID_LINE_AFTER', 'ID_LINE_BEFORE', 'ID_CUT_LINE', + 'ID_COPY_LINE', 'ID_JOIN_LINES', 'ID_TRANSPOSE', 'ID_DELETE_LINE', + 'ID_LINE_MOVE_UP', 'ID_LINE_MOVE_DOWN', + 'ID_QUICK_FIND', 'ID_PREF', 'ID_ZOOM_OUT', + 'HOME_PAGE', 'CONTACT_MAIL', 'ID_ZOOM_IN', 'ID_ZOOM_NORMAL', + 'ID_SHOW_EDGE', 'ID_SHOW_EOL', 'ID_SHOW_LN', 'ID_SHOW_WS', + 'ID_PERSPECTIVES', 'ID_INDENT_GUIDES', 'ID_VIEW_TOOL', + 'ID_GOTO_LINE', 'ID_NEXT_MARK', 'ID_PRE_MARK', 'ID_FONT', + 'ID_EOL_MAC', 'ID_EOL_UNIX', 'ID_EOL_WIN', 'ID_WORD_WRAP', + 'ID_INDENT', 'ID_UNINDENT', 'ID_TO_UPPER', 'ID_TO_LOWER', + 'ID_SPACE_TO_TAB', 'ID_TAB_TO_SPACE', 'ID_TRIM_WS', + 'ID_TOGGLECOMMENT', 'ID_AUTOCOMP', 'ID_AUTOINDENT', 'ID_SYNTAX', + 'ID_FOLDING', 'ID_BRACKETHL', 'ID_LEXER', + 'ID_PLUGMGR', 'ID_STYLE_EDIT', 'ID_MACRO_START', 'ID_MACRO_STOP', + 'ID_MACRO_PLAY', 'ID_ABOUT', 'ID_HOMEPAGE', 'ID_CONTACT', + 'ID_BUG_TRACKER', 'ID_DOCUMENTATION', 'ID_COMMAND', + 'ID_USE_SOFTTABS', 'ID_DUP_LINE', 'ID_TRANSLATE', + 'I18N_PAGE', 'ID_GOTO_MBRACE', 'ID_HLCARET_LINE', 'ID_SHOW_SB', + 'ID_REVERT_FILE', 'ID_RELOAD_ENC', 'ID_DOCPROP', 'ID_PASTE_AFTER', + 'ID_COLUMN_MODE', 'ID_PANELIST', 'ID_MAXIMIZE_EDITOR', + 'ID_NEW_WINDOW', 'ID_TOGGLE_FOLD', 'ID_TOGGLE_ALL_FOLDS', + 'ID_SAVE_SESSION', 'ID_LOAD_SESSION', 'ID_NEXT_POS', 'ID_PRE_POS', + 'ID_CYCLE_CLIPBOARD', 'ID_LEXER_CUSTOM', 'ID_SHOW_AUTOCOMP', + 'ID_SHOW_CALLTIP', 'ID_SESSION_BAR', 'ID_PREF_CARET_WIDTH' ] + +#---- Project Info ----# +# The project info was moved to another module so it could be accessed +# externally without needing to import anything else. It's imported +# here with a * until there isn't anyplace left that expects to find +# these values in this module. +from info import * + +#---- End Project Info ----# + +#---- Imported Libs/Objects ----# +import wx + +_ = wx.GetTranslation + +#---- WX Compatibility Hacks ----# +import wxcompat + +#---- Configuration Locations ----# +# Values set when main loads +CONFIG = { + 'ISLOCAL' : False, # Using local config (no abs path) + 'CONFIG_BASE' : None, # Set if config base is in nonstandard location + 'INSTALL_DIR' : "", # Instal directory + 'CONFIG_DIR' : "", # Root configration directory + 'CACHE_DIR' : "", # Holds temp data about documents + 'KEYPROF_DIR' : "", # System Keybinding + 'PROFILE_DIR' : "", # User Profile Directory + 'PLUGIN_DIR' : "", # User Plugin Dir + 'SYSPIX_DIR' : "", # Editras non user graphics + 'THEME_DIR' : "", # Theme Directory + 'LANG_DIR' : "", # Locale Data Directory + 'SYS_PLUGIN_DIR' : "", # Editra base plugin dir + 'SYS_STYLES_DIR' : "", # Editra base style sheets + 'TEST_DIR' : "", # Test data files dir +} + +# Global logging/application variables +DEBUG = False +VDEBUG = False +SINGLE = True + +#---- Object ID's ----# +# File Menu IDs +ID_NEW = wx.ID_NEW +ID_NEW_WINDOW = wx.NewId() +ID_OPEN = wx.ID_OPEN +ID_FHIST = wx.NewId() +ID_CLOSE = wx.ID_CLOSE +ID_CLOSEALL = wx.ID_CLOSE_ALL +ID_CLOSE_OTHERS = wx.NewId() +ID_CLOSE_WINDOW = wx.NewId() +ID_SAVE = wx.ID_SAVE +ID_SAVEAS = wx.ID_SAVEAS +ID_SAVEALL = wx.NewId() +ID_REVERT_FILE = wx.ID_REVERT_TO_SAVED +ID_RELOAD_ENC = wx.NewId() +ID_SAVE_PROFILE = wx.NewId() +ID_LOAD_PROFILE = wx.NewId() +ID_SAVE_SESSION = wx.NewId() +ID_LOAD_SESSION = wx.NewId() +ID_SESSION_BAR = wx.NewId() +ID_PRINT = wx.ID_PRINT +ID_PRINT_PRE = wx.ID_PREVIEW +ID_PRINT_SU = wx.NewId() +ID_EXIT = wx.ID_EXIT + +# Edit Menu IDs +ID_UNDO = wx.ID_UNDO +ID_REDO = wx.ID_REDO +ID_CUT = wx.ID_CUT +ID_COPY = wx.ID_COPY +ID_PASTE = wx.ID_PASTE +ID_CYCLE_CLIPBOARD = wx.NewId() +ID_PASTE_AFTER = wx.NewId() +ID_SELECTALL = wx.ID_SELECTALL +ID_COLUMN_MODE = wx.NewId() +ID_LINE_EDIT = wx.NewId() +ID_BOOKMARK = wx.NewId() +ID_ADD_BM = wx.NewId() +ID_DEL_BM = wx.NewId() # Not used in menu anymore +ID_DEL_ALL_BM = wx.NewId() +ID_LINE_AFTER = wx.NewId() +ID_LINE_BEFORE = wx.NewId() +ID_CUT_LINE = wx.NewId() +ID_DELETE_LINE = wx.NewId() +ID_COPY_LINE = wx.NewId() +ID_DUP_LINE = wx.NewId() +ID_JOIN_LINES = wx.NewId() +ID_TRANSPOSE = wx.NewId() +ID_LINE_MOVE_UP = wx.NewId() +ID_LINE_MOVE_DOWN= wx.NewId() +ID_SHOW_AUTOCOMP = wx.NewId() +ID_SHOW_CALLTIP = wx.NewId() +ID_FIND = wx.ID_FIND +ID_FIND_PREVIOUS = wx.NewId() +ID_FIND_NEXT = wx.NewId() +ID_FIND_REPLACE = wx.ID_REPLACE +ID_FIND_SELECTED = wx.NewId() + +# Using the system ids automatically disables the menus items +# when the dialog is open which is not wanted +if wx.Platform == '__WXMAC__': + ID_FIND = wx.NewId() + ID_FIND_REPLACE = wx.NewId() +ID_QUICK_FIND = wx.NewId() +ID_PREF = wx.ID_PREFERENCES + +# Preference Dlg Ids +ID_PREF_LANG = wx.NewId() +ID_PREF_AALIAS = wx.NewId() +ID_PREF_AUTOBKUP = wx.NewId() +ID_PREF_AUTO_RELOAD = wx.NewId() +ID_PREF_AUTOCOMPEX = wx.NewId() +ID_PREF_AUTOTRIM = wx.NewId() +ID_PREF_CHKMOD = wx.NewId() +ID_PREF_CHKUPDATE = wx.NewId() +ID_PREF_DLEXER = wx.NewId() +ID_PREF_EDGE = wx.NewId() +ID_PREF_ENCODING = wx.NewId() +ID_PREF_SYNTHEME = wx.NewId() +ID_PREF_TABS = wx.NewId() +ID_PREF_UNINDENT = wx.NewId() +ID_PREF_TABW = wx.NewId() +ID_PREF_INDENTW = wx.NewId() +ID_PREF_FHIST = wx.NewId() +ID_PREF_WSIZE = wx.NewId() +ID_PREF_WPOS = wx.NewId() +ID_PREF_ICON = wx.NewId() +ID_PREF_ICONSZ = wx.NewId() +ID_PREF_MODE = wx.NewId() +ID_PREF_TABICON = wx.NewId() +ID_PRINT_MODE = wx.NewId() +ID_TRANSPARENCY = wx.NewId() +ID_PREF_SPOS = wx.NewId() +ID_PREF_UPDATE_BAR = wx.NewId() +ID_PREF_VIRT_SPACE = wx.NewId() +ID_PREF_CARET_WIDTH = wx.NewId() +ID_PREF_WARN_EOL = wx.NewId() +ID_SESSION = wx.NewId() + +# View Menu IDs +ID_ZOOM_OUT = wx.ID_ZOOM_OUT +ID_ZOOM_IN = wx.ID_ZOOM_IN +ID_ZOOM_NORMAL = wx.ID_ZOOM_100 +ID_HLCARET_LINE = wx.NewId() +ID_SHOW_EDGE = wx.NewId() +ID_SHOW_EOL = wx.NewId() +ID_SHOW_LN = wx.NewId() +ID_SHOW_WS = wx.NewId() +ID_SHOW_SHELF = wx.NewId() +ID_PERSPECTIVES = wx.NewId() +ID_INDENT_GUIDES = wx.NewId() +ID_SHOW_SB = wx.NewId() +ID_VIEW_TOOL = wx.NewId() +ID_SHELF = wx.NewId() +ID_PANELIST = wx.NewId() +ID_GOTO_LINE = wx.NewId() +ID_GOTO_MBRACE = wx.NewId() +ID_TOGGLE_FOLD = wx.NewId() +ID_TOGGLE_ALL_FOLDS = wx.NewId() +ID_NEXT_POS = wx.NewId() +ID_PRE_POS = wx.NewId() +ID_NEXT_MARK = wx.ID_FORWARD +ID_PRE_MARK = wx.ID_BACKWARD +ID_MAXIMIZE_EDITOR = wx.NewId() + +# Format Menu IDs +ID_FONT = wx.NewId() +ID_EOL_MODE = wx.NewId() +ID_EOL_MAC = wx.NewId() +ID_EOL_UNIX = wx.NewId() +ID_EOL_WIN = wx.NewId() +ID_USE_SOFTTABS = wx.NewId() +ID_WORD_WRAP = wx.NewId() +ID_INDENT = wx.ID_INDENT +ID_UNINDENT = wx.ID_UNINDENT +ID_TO_UPPER = wx.NewId() +ID_TO_LOWER = wx.NewId() +ID_WS_FORMAT = wx.NewId() +ID_SPACE_TO_TAB = wx.NewId() +ID_TAB_TO_SPACE = wx.NewId() +ID_TRIM_WS = wx.NewId() +ID_TOGGLECOMMENT = wx.NewId() + +# Settings Menu IDs +ID_AUTOCOMP = wx.NewId() +ID_AUTOINDENT = wx.NewId() +ID_SYNTAX = wx.NewId() +ID_SYN_ON = wx.NewId() +ID_SYN_OFF = wx.NewId() +ID_FOLDING = wx.NewId() +ID_BRACKETHL = wx.NewId() +ID_LEXER = wx.NewId() +ID_LEXER_CUSTOM = wx.NewId() + +# Tool Menu IDs +ID_COMMAND = wx.NewId() +ID_PLUGMGR = wx.NewId() +ID_STYLE_EDIT = wx.ID_EDIT +ID_MACRO_START = wx.NewId() +ID_MACRO_STOP = wx.NewId() +ID_MACRO_PLAY = wx.NewId() +ID_GENERATOR = wx.NewId() +ID_HTML_GEN = wx.NewId() +ID_TEX_GEN = wx.NewId() +ID_RTF_GEN = wx.NewId() +ID_RUN_LAUNCH = wx.NewId() +ID_LAUNCH_LAST = wx.NewId() + +# Help Menu IDs +ID_ABOUT = wx.ID_ABOUT +ID_HOMEPAGE = wx.ID_HOME +ID_DOCUMENTATION = wx.NewId() +ID_TRANSLATE = wx.NewId() +ID_CONTACT = wx.NewId() +ID_BUG_TRACKER = wx.NewId() + +# Misc IDs +ID_ADD = wx.ID_ADD +ID_ADVANCED = wx.NewId() +ID_APP_SPLASH = wx.NewId() +ID_BACKWARD = wx.ID_BACKWARD +ID_BIN_FILE = ID_COMMAND +ID_CDROM = wx.NewId() +ID_COMMAND_LINE_OPEN = wx.NewId() +ID_COMPUTER = wx.NewId() +ID_COPY_PATH = wx.NewId() +ID_COPY_FILE = wx.NewId() +ID_DELETE = wx.NewId() +ID_DELETE_ALL = wx.NewId() +ID_DOCPROP = wx.NewId() +ID_DOWN = wx.ID_DOWN +ID_DOWNLOAD_DLG = wx.NewId() +ID_FILE = wx.ID_FILE +ID_FIND_RESULTS = wx.NewId() +ID_FLOPPY = wx.NewId() +ID_FOLDER = wx.NewId() +ID_FORWARD = wx.ID_FORWARD +ID_HARDDISK = wx.NewId() +ID_KEY_PROFILES = wx.NewId() +ID_LOGGER = wx.NewId() +ID_BOOKMARK_MGR = wx.NewId() +ID_MOVE_TAB = wx.NewId() +ID_PACKAGE = wx.NewId() +ID_PYSHELL = wx.NewId() +ID_REFRESH = wx.ID_REFRESH +ID_REMOVE = wx.ID_REMOVE +ID_REPORTER = wx.NewId() +ID_STOP = wx.ID_STOP +ID_THEME = wx.NewId() +ID_USB = wx.NewId() +ID_UP = wx.ID_UP +ID_VI_MODE = wx.NewId() +ID_VI_NORMAL_DEFAULT = wx.NewId() +ID_WEB = wx.NewId() +ID_READONLY = wx.NewId() +ID_NEW_FOLDER = wx.NewId() + +# Code Elements (ids for art provider) +ID_CLASS_TYPE = wx.NewId() +ID_FUNCT_TYPE = wx.NewId() +ID_ELEM_TYPE = wx.NewId() +ID_VARIABLE_TYPE = wx.NewId() +ID_ATTR_TYPE = wx.NewId() +ID_PROPERTY_TYPE = wx.NewId() +ID_METHOD_TYPE = wx.NewId() + +# Statusbar IDs +SB_INFO = 0 +SB_BUFF = 1 +SB_LEXER = 2 +SB_ENCODING = 3 +SB_EOL = 4 +SB_ROWCOL = 5 + +# Print Mode Identifiers +PRINT_BLACK_WHITE = 0 +PRINT_COLOR_WHITE = 1 +PRINT_COLOR_DEF = 2 +PRINT_INVERT = 3 +PRINT_NORMAL = 4 + +#---- Objects ----# + +# Dictionary to map object ids to Profile keys +ID_2_PROF = { + ID_PREF_AALIAS : 'AALIASING', + ID_TRANSPARENCY : 'ALPHA', + ID_PREF_UNINDENT : 'BSUNINDENT', + ID_APP_SPLASH : 'APPSPLASH', + ID_PREF_AUTOBKUP : 'AUTOBACKUP', + ID_AUTOCOMP : 'AUTO_COMP', + ID_PREF_AUTOCOMPEX : 'AUTO_COMP_EX', + ID_AUTOINDENT : 'AUTO_INDENT', + ID_PREF_AUTO_RELOAD : 'AUTO_RELOAD', + ID_PREF_AUTOTRIM : 'AUTO_TRIM_WS', + ID_BRACKETHL : 'BRACKETHL', + ID_PREF_CHKMOD : 'CHECKMOD', + ID_PREF_CHKUPDATE : 'CHECKUPDATE', + ID_FOLDING : 'CODE_FOLD', + ID_PREF_DLEXER : 'DEFAULT_LEX', + ID_PERSPECTIVES : 'DEFAULT_VIEW', + ID_PREF_EDGE : 'EDGE', + ID_PREF_ENCODING : 'ENCODING', + ID_EOL_MODE : 'EOL_MODE', + ID_PREF_FHIST : 'FHIST_LVL', + ID_INDENT_GUIDES : 'GUIDES', + ID_HLCARET_LINE : 'HLCARETLINE', + ID_PREF_ICON : 'ICONS', + ID_PREF_ICONSZ : 'ICON_SZ', + ID_PREF_INDENTW : 'INDENTWIDTH', + ID_KEY_PROFILES : 'KEY_PROFILE', + ID_PREF_LANG : 'LANG', + ID_PREF_MODE : 'MODE', + ID_NEW_WINDOW : 'OPEN_NW', + ID_PRINT_MODE : 'PRINT_MODE', + ID_REPORTER : 'REPORTER', + ID_PREF_SPOS : 'SAVE_POS', + ID_SESSION : 'SAVE_SESSION', + ID_PREF_WPOS : 'SET_WPOS', + ID_PREF_WSIZE : 'SET_WSIZE', + ID_SHOW_EDGE : 'SHOW_EDGE', + ID_SHOW_EOL : 'SHOW_EOL', + ID_SHOW_LN : 'SHOW_LN', + ID_SHOW_WS : 'SHOW_WS', + ID_SHOW_SB : 'STATBAR', + ID_SYNTAX : 'SYNTAX', + ID_PREF_SYNTHEME : 'SYNTHEME', + ID_PREF_TABICON : 'TABICONS', + ID_PREF_TABW : 'TABWIDTH', + ID_VIEW_TOOL : 'TOOLBAR', + ID_PREF_TABS : 'USETABS', + ID_PREF_VIRT_SPACE : 'VIEWVERTSPACE', + ID_PREF_CARET_WIDTH : 'CARETWIDTH', + ID_VI_MODE : 'VI_EMU', + ID_VI_NORMAL_DEFAULT : 'VI_NORMAL_DEFAULT', + ID_PREF_WARN_EOL : 'WARN_EOL', + ID_WORD_WRAP : 'WRAP', +} + +EOL_MODE_CR = 0 +EOL_MODE_LF = 1 +EOL_MODE_CRLF = 2 +def EOLModeMap(): + """Get the eol mode map""" + # Maintenance Note: ints must be kept in sync with EDSTC_EOL_* in edstc + return { EOL_MODE_CR : _("Old Machintosh (\\r)"), + EOL_MODE_LF : _("Unix (\\n)"), + EOL_MODE_CRLF : _("Windows (\\r\\n)")} + +# Default Plugins +DEFAULT_PLUGINS = ("generator.Html", "generator.LaTeX", "generator.Rtf", + "iface.Shelf", "ed_theme.TangoTheme", "ed_log.EdLogViewer", + "ed_search.EdFindResults", "ed_bookmark.EdBookmarks") diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_i18n.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_i18n.py new file mode 100644 index 0000000..62ee00c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_i18n.py @@ -0,0 +1,136 @@ +############################################################################### +# Name: ed_i18n.py # +# Purpose: I18n utilities and services # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This file is a module for managing translations and the internationalization of +the program. + +METHODS: + - L{GetAvailLocales}: Returns a list of canonical names of available locales + - L{GetLocaleDict}: Returns a dictionary consisting of canonical names for + keys and language ids for values. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_i18n.py 71189 2012-04-12 00:37:04Z CJP $" +__revision__ = "$Revision: 71189 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import wx +import wx.lib.langlistctrl as langlist +import wx.combo +import glob + +# Editra Imports +import ed_glob + +#----------------------------------------------------------------------------# +# Global Variables +OPT_NO_OP = 0 +OPT_DESCRIPT = 1 + +#----------------------------------------------------------------------------# + +#---- Helper Functions used by the classes in this module ----# +def GetAvailLocales(): + """Gets a list of the available locales that have been installed + for the editor. Returning a list of strings that represent the + canonical names of each language. + @return: list of all available local/languages available + + """ + avail_loc = list() + loc = glob.glob(os.path.join(ed_glob.CONFIG['LANG_DIR'], "*")) + for path in loc: + the_path = os.path.join(path, "LC_MESSAGES", ed_glob.PROG_NAME + ".mo") + if os.path.exists(the_path): + avail_loc.append(os.path.basename(path)) + return avail_loc + +def GetLocaleDict(loc_list, opt=OPT_NO_OP): + """Takes a list of cannonical locale names and by default returns a + dictionary of available language values using the canonical name as + the key. Supplying the Option OPT_DESCRIPT will return a dictionary + of language id's with languages description as the key. + @param loc_list: list of locals + @keyword opt: option for configuring return data + @return: dict of locales mapped to wx.LANGUAGE_*** values + + """ + lang_dict = dict() + for lang in [x for x in dir(wx) if x.startswith("LANGUAGE_")]: + langId = getattr(wx, lang) + langOk = False + try: + langOk = wx.Locale.IsAvailable(langId) + except wx.PyAssertionError: + continue + + if langOk: + loc_i = wx.Locale.GetLanguageInfo(langId) + if loc_i: + if loc_i.CanonicalName in loc_list: + if opt == OPT_DESCRIPT: + lang_dict[loc_i.Description] = langId + else: + lang_dict[loc_i.CanonicalName] = langId + return lang_dict + +def GetLangId(lang_n): + """Gets the ID of a language from the description string. If the + language cannot be found the function simply returns the default language + @param lang_n: Canonical name of a language + @return: wx.LANGUAGE_*** id of language + + """ + if lang_n == "Default": + # No language set, default to English + return wx.LANGUAGE_ENGLISH_US + lang_desc = GetLocaleDict(GetAvailLocales(), OPT_DESCRIPT) + return lang_desc.get(lang_n, wx.LANGUAGE_DEFAULT) + +#---- Language List Combo Box----# +class LangListCombo(wx.combo.BitmapComboBox): + """Combines a langlist and a BitmapComboBox""" + def __init__(self, parent, id_, default=None): + """Creates a combobox with a list of all translations for the + editor as well as displaying the countries flag next to the item + in the list. + + @param default: The default item to show in the combo box + + """ + lang_ids = GetLocaleDict(GetAvailLocales()).values() + lang_items = langlist.CreateLanguagesResourceLists(langlist.LC_ONLY, \ + lang_ids) + wx.combo.BitmapComboBox.__init__(self, parent, id_, + size=wx.Size(250, 26), + style=wx.CB_READONLY) + for lang_d in lang_items[1]: + bit_m = lang_items[0].GetBitmap(lang_items[1].index(lang_d)) + self.Append(lang_d, bit_m) + + if default: + self.SetValue(default) + +#-----------------------------------------------------------------------------# +if __name__ == '__main__': + APP = wx.PySimpleApp(False) + # Print a list of Canonical names useful for seeing what codes to + # use when naming po files + OUT = list() + for LANG in [x for x in dir(wx) if x.startswith("LANGUAGE")]: + LOC_I = wx.Locale.GetLanguageInfo(getattr(wx, LANG)) + if LOC_I: + OUT.append((LOC_I.Description, LOC_I.CanonicalName)) + + for LANG in sorted(OUT): + print LANG diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_ipc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_ipc.py new file mode 100644 index 0000000..d772f4b --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_ipc.py @@ -0,0 +1,273 @@ +############################################################################### +# Name: ed_ipc.py # +# Purpose: Editra IPC client/server # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008-2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +"""@package Editra.src.ed_ipc + +Classes and utilities for handling IPC between running instances of Editra. The +IPC is done through sockets using the TCP protocol. Message packets have a +specified format and authentication method that is described in L{EdIpcServer}. + +@section protocol Remote Control Protocol: + +This server and its relationship with the main application object allows for +some limited remote control of Editra. The server's basic message protocol +requirements are as follows. + +@verbatim +SESSION_KEY;xml;MSGEND +@endverbatim + +Where the SESSION_KEY is the unique authentication key created by the app that +started the server. This key is stored in the user profile and only valid for +the current running session of Editra. The MSGEND indicator is the L{MSGEND} +string defined in this file (*EDEND*). If both of these parts of the message +are found and correct the server will forward the messages that are packed in +between to the app. + +@section format Message Format: +@verbatim +<edipc> + <filelist> + <file name="absolute_filepath"/> + </filelist> + <arglist> + <arg name="g" value="2"/> + </arglist> +</edipc> +@endverbatim + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_ipc.py 72623 2012-10-06 19:33:06Z CJP $" +__revision__ = "$Revision: 72623 $" + +#-----------------------------------------------------------------------------# +# Imports +import sys +import wx +import threading +import socket +import time +#import select + +# Editra Libs +import util +import ed_xml +import ebmlib + +#-----------------------------------------------------------------------------# +# Globals + +# Port choosing algorithm ;) +EDPORT = (10 * int('ed', 16) + sum(ord(x) for x in "itr") + int('a', 16)) * 10 +MSGEND = "*EDEND*" + +# Xml Implementation +EDXML_IPC = "edipc" +EDXML_FILELIST = "filelist" +EDXML_FILE = "file" +EDXML_ARGLIST = "arglist" +EDXML_ARG = "arg" + +#-----------------------------------------------------------------------------# + +edEVT_COMMAND_RECV = wx.NewEventType() +EVT_COMMAND_RECV = wx.PyEventBinder(edEVT_COMMAND_RECV, 1) +class IpcServerEvent(wx.PyCommandEvent): + """Event to signal the server has recieved some commands""" + def __init__(self, etype, eid, values=None): + """Creates the event object""" + wx.PyCommandEvent.__init__(self, etype, eid) + self._value = values + + def GetCommands(self): + """Returns the list of commands sent to the server + @return: the value of this event + + """ + return self._value + +#-----------------------------------------------------------------------------# + +class EdIpcServer(threading.Thread): + """Create an instance of IPC server for Editra. IPC is handled through + a socket connection to an instance of this server listening on L{EDPORT}. + The server will receive commands and dispatch them to the app. + Messages sent to the server must be in the following format. + + AuthenticationKey;Message Data;MSGEND + + The _AuthenticationKey_ is the same as the key that started the server it + is used to validate that messages are coming from a legitimate source. + + _Message Data_ is a string of data where items are separated by a single + ';' character. If you use L{SendCommands} to communicate with the server + then this message separators are handled internally by that method. + + L{MSGEND} is the token to signify that the client is finished sending + commands to the server. When using L{SendCommands} this is also + automatically handled. + + @todo: investigate possible security issues + + """ + def __init__(self, app, key, port=EDPORT): + """Create the server thread + @param app: Application object the server belongs to + @param key: Unique user authentication key (string) + @keyword port: TCP port to attempt to connect to + + """ + super(EdIpcServer, self).__init__() + + # Attributes + self._exit = False + self.__key = key + self.app = app + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + # Setup + ## Try new ports till we find one that we can use + while True: + try: + self.socket.bind(('127.0.0.1', port)) + break + except: + port += 1 + + global EDPORT + EDPORT = port + self.socket.listen(5) + + def Shutdown(self): + """Tell the server to exit""" + self._exit = True + # Wake up the server in case its waiting + # TODO: should add a specific exit event message + SendCommands(IPCCommand(), self.__key) + + def run(self): + """Start the server. The server runs in blocking mode, this + shouldn't be an issue as it should rarely need to respond to + anything. + + """ + while not self._exit: + try: + client, addr = self.socket.accept() + + if self._exit: + break + + # Block for up to 2 seconds while reading + start = time.time() + recieved = '' + while time.time() < start + 2: + recieved += client.recv(4096) + if recieved.endswith(MSGEND): + break + + # If message key is correct and the message is ended, process + # the input and dispatch to the app. + if recieved.startswith(self.__key) and recieved.endswith(MSGEND): + # Strip the key + recieved = recieved.replace(self.__key, '', 1) + # Strip the end token + xmlstr = recieved.rstrip(MSGEND).strip(";") + + # Parse the xml + exml = IPCCommand() + try: + # Well formed xml must be utf-8 string not Unicode + if not ebmlib.IsUnicode(xmlstr): + xmlstr = unicode(xmlstr, sys.getfilesystemencoding()) + xmlstr = xmlstr.encode('utf-8') + exml = IPCCommand.parse(xmlstr) + except Exception, msg: + # Log and ignore parsing errors + logmsg = "[ed_ipc][err] Parsing failed: %s\n" % msg + xmlstr = xmlstr.replace('\n', '').strip() + logmsg += "Bad xml was: %s" % repr(xmlstr) + util.Log(logmsg) + continue + + evt = IpcServerEvent(edEVT_COMMAND_RECV, wx.ID_ANY, exml) + wx.CallAfter(wx.PostEvent, self.app, evt) + except socket.error: + # TODO: Better error handling + self._exit = True + + # Shutdown Server + try: + self.socket.shutdown(socket.SHUT_RDWR) + except: + pass + + self.socket.close() + +#-----------------------------------------------------------------------------# + +def SendCommands(xmlobj, key): + """Send commands to the running instance of Editra + @param xmlobj: EditraXml Object + @param key: Server session authentication key + @return: bool + + """ + assert isinstance(xmlobj, ed_xml.EdXml), "SendCommands expects an xml object" + + # Build the edipc protocol msg + cmds = list() + cmds.insert(0, key) + cmds.append(xmlobj.GetXml()) + cmds.append(MSGEND) + try: + # Setup the client socket + client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + client.connect(('127.0.0.1', EDPORT)) + + # Server expects commands delimited by ; + message = ";".join(cmds) + client.send(message) + client.shutdown(socket.SHUT_RDWR) + client.close() + except Exception, msg: + util.Log("[ed_ipc][err] Failed in SendCommands: %s" % msg) + return False + else: + return True + +#-----------------------------------------------------------------------------# +# Command Serialization + +class IPCFile(ed_xml.EdXml): + """Xml object for holding the list of files + @verbatim <file value="/path/to/file"/> @endverbatim + + """ + class meta: + tagname = EDXML_FILE + value = ed_xml.String(required=True) + +class IPCArg(ed_xml.EdXml): + """Xml object for holding the list of args + @verbatim <arg name="test" value="x"/> @endverbatim + + """ + class meta: + tagname = EDXML_ARG + name = ed_xml.String(required=True) + value = ed_xml.String(required=True) + +class IPCCommand(ed_xml.EdXml): + """IPC XML Command""" + class meta: + tagname = EDXML_IPC + filelist = ed_xml.List(ed_xml.Model(IPCFile)) + arglist = ed_xml.List(ed_xml.Model(IPCArg)) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_keyh.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_keyh.py new file mode 100644 index 0000000..00f88b7 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_keyh.py @@ -0,0 +1,286 @@ +############################################################################### +# Name: ed_keyh.py # +# Purpose: Editra's Vi Emulation Key Handler # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +KeyHandler interface for implementing extended key action handling in Editra's +main text editting buffer. + +@summary: Custom keyhandler interface + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_keyh.py 70747 2012-02-29 01:33:35Z CJP $" +__revision__ = "$Revision: 70747 $" + +#-------------------------------------------------------------------------# +# Imports +import re +import wx +import wx.stc + +# Editra Libraries +import ed_event +import ed_glob +import ed_basestc +import ed_stc +import string +import ed_vim + +#-------------------------------------------------------------------------# +# Use this base class to derive any new keyhandlers from. The keyhandler is +# called upon by the active buffer when ever a key press event happens. The +# handler then has the responsibility of deciding what to do with the key. +# +class KeyHandler(object): + """KeyHandler base class""" + def __init__(self, stc): + super(KeyHandler, self).__init__() + + # Attributes + self.stc = stc + self._blockmode = False + + STC = property(lambda self: self.stc) + BlockMode = property(lambda self: self._blockmode, + lambda self,m:setattr(self,'_blockmode', m)) + + def ClearMode(self): + """Clear any key input modes to normal input mode""" + evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.stc.Id, + '', ed_glob.SB_BUFF) + wx.PostEvent(self.stc.TopLevelParent, evt) + + def GetHandlerName(self): + """Get the name of this handler + @return: string + + """ + return u'NULL' + + def PreProcessKey(self, key_code, ctrldown=False, + cmddown=False, shiftdown=False, altdown=False): + """Pre process any keys before they get to the char handler + @param key_code: Raw keycode + @keyword ctrldown: Is the control key down + @keyword cmddown: Is the Command key down (Mac osx) + @keyword shiftdown: Is the Shift key down + @keyword altdown: Is the Alt key down + @return: bool + + """ + return False + + def ProcessKey(self, key_code, ctrldown=False, + cmddown=False, shiftdown=False, altdown=False): + """Process the key and return True if it was processed and + false if it was not. The key is recieved at EVT_CHAR. + @param key_code: Raw keycode + @keyword ctrldown: Is the control key down + @keyword cmddown: Is the Command key down (Mac osx) + @keyword shiftdown: Is the Shift key down + @keyword altdown: Is the Alt key down + @return: bool + + """ + return False + +#-------------------------------------------------------------------------# + +class ViKeyHandler(KeyHandler): + """Defines a key handler for Vi emulation + @summary: Handles key presses according to Vi emulation. + + """ + + # Vi Mode declarations + NORMAL, \ + INSERT, \ + VISUAL, \ + = range(3) + + def __init__(self, stc, use_normal_default=False): + super(ViKeyHandler, self).__init__(stc) + + # Attributes + self.mode = 0 + self.last = u'' + self.last_find = u'' + self.commander = ed_vim.EditraCommander(self) + self.buffer = u'' + + # Insert mode by default + if use_normal_default: + self.NormalMode() + else: + self.InsertMode() + + def ClearMode(self): + """Clear the mode back to default input mode""" + # TODO:CJP when newer scintilla is available in 2.9 use + # blockcaret methods. + self.STC.SetLineCaret() + self.BlockMode = False + self.last = self.cmdcache = u'' + super(ViKeyHandler, self).ClearMode() + + def GetHandlerName(self): + """Get the name of this handler""" + return u'VI' + + def _SetMode(self, newmode, msg): + """Set the keyhandlers mode + @param newmode: New mode name to change to + + """ + self.buffer = u'' # Clear buffer from last mode + self.mode = newmode + # Update status bar + evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.stc.GetId(), + msg, ed_glob.SB_BUFF) + wx.PostEvent(self.stc.GetTopLevelParent(), evt) + + def InsertMode(self): + """Change to insert mode""" + self.stc.SetLineCaret() + self.stc.SetOvertype(False) + self.BlockMode = False + self._SetMode(ViKeyHandler.INSERT, u"INSERT") + + def ReplaceMode(self): + """Change to replace mode + This really just insert mode with overtype set to true + + """ + self.stc.SetLineCaret() + self.stc.SetOvertype(True) + self._SetMode(ViKeyHandler.INSERT, u"REPLACE") + + def NormalMode(self): + """Change to normal (command) mode""" + if self.IsInsertMode(): + self.commander.SetLastInsertedText(self.buffer) + + self.stc.SetOvertype(False) + self.stc.SetBlockCaret() + self.BlockMode = True + self.commander.Deselect() + self.commander.InsertRepetition() + self._SetMode(ViKeyHandler.NORMAL, u'NORMAL') + + def VisualMode(self): + """Change to visual (selection) mode""" + self.stc.SetBlockCaret() + self.BlockMode = True + self.stc.SetOvertype(False) + self._SetMode(ViKeyHandler.VISUAL, u'VISUAL') + self.commander.StartSelection() + + def IsInsertMode(self): + """Test if we are in insert mode""" + return self.mode == ViKeyHandler.INSERT + + def IsNormalMode(self): + """Test if we are in normal mode""" + return self.mode == ViKeyHandler.NORMAL + + def IsVisualMode(self): + """Test if we are in visual mode""" + return self.mode == ViKeyHandler.VISUAL + + def PreProcessKey(self, key_code, ctrldown=False, + cmddown=False, shiftdown=False, altdown=False): + """Pre process any keys before they get to the char handler + @param key_code: Raw keycode + @keyword ctrldown: Is the control key down + @keyword cmddown: Is the Command key down (Mac osx) + @keyword shiftdown: Is the Shift key down + @keyword altdown: Is the Alt key down + @return: bool + + """ + if not shiftdown and key_code == wx.WXK_ESCAPE: + # If Vi emulation is active go into Normal mode and + # pass the key event to the char handler by not processing + # the key. + self.NormalMode() + return False + elif (ctrldown or cmddown) and key_code == ord('['): + self.NormalMode() + return True + elif key_code in (wx.WXK_RETURN, wx.WXK_BACK, + wx.WXK_RIGHT, wx.WXK_LEFT) and \ + not self.IsInsertMode(): + # swallow enter key in normal and visual modes + # HACK: we have to do it form here because ProcessKey + # is only called on Char events, not Key events, + # and the Enter key does not generate a Char event. + self.ProcessKey(key_code) + return True + else: + return False + + def ProcessKey(self, key_code, ctrldown=False, + cmddown=False, shiftdown=False, altdown=False): + """Processes keys and decided whether to interpret them as vim commands + or normal insert text + + @param key_code: Raw key code + @keyword cmddown: Command/Ctrl key is down + @keyword shiftdown: Shift Key is down + @keyword altdown : Alt key is down + + """ + if ctrldown or cmddown or altdown: + return False + + # Mode may change after processing the key, so we need to remember + # whether this was a command or not + f_cmd = self.IsNormalMode() or self.IsVisualMode() + + self._ProcessKey(key_code) + + # Update status bar + if self.IsNormalMode(): + if self.stc.GetTopLevelParent(): + evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, + self.stc.GetId(), + u"NORMAL %s" % self.buffer, + ed_glob.SB_BUFF) + wx.PostEvent(self.stc.GetTopLevelParent(), evt) + + if f_cmd: + return True + else: + # If we're in insert mode we must return False + # so the text gets inserted into the editor + return False + + def _ProcessKey(self, key_code): + """The real processing of keys""" + char = unichr(key_code) + if self.IsNormalMode() or self.IsVisualMode(): + self.buffer += char + if ed_vim.Parse(self.buffer, self.commander): + # command was handled (or invalid) so clear buffer + self.buffer = u'' + + if self.IsVisualMode(): + self.commander.ExtendSelection() + + elif self.IsInsertMode(): + self.buffer += char + + def InsertText(self, pos, text): + """Insert text and store it in the buffer if we're in insert mode + i.e. as if it was typed in + + """ + self.stc.InsertText(pos, text) + if self.IsInsertMode(): + self.buffer += text
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_log.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_log.py new file mode 100644 index 0000000..28ec57a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_log.py @@ -0,0 +1,277 @@ +############################################################################### +# Name: Cody Precord # +# Purpose: Log output viewer for the shelf # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra LogViewer + +This module provides classes for managing the log display and filtering of its +messages. The module also exports an implementation of a shelf plugin for +displaying a L{LogViewer} in the Shelf. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_log.py 72223 2012-07-28 17:35:57Z CJP $" +__revision__ = "$Revision: 72223 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import re +import wx + +# Editra Libraries +import ed_msg +import eclib +import iface +import plugin +from profiler import Profile_Get +import ed_glob +import ed_basewin + +#-----------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation + +SHOW_ALL_MSG = 'ALL' +#-----------------------------------------------------------------------------# + +# Interface Implementation +class EdLogViewer(plugin.Plugin): + """Shelf interface implementation for the log viewer""" + plugin.Implements(iface.ShelfI) + + __name__ = u'Editra Log' + + @staticmethod + def AllowMultiple(): + """EdLogger allows multiple instances""" + return True + + @staticmethod + def CreateItem(parent): + """Returns a log viewr panel""" + return LogViewer(parent) + + def GetBitmap(self): + """Get the log viewers tab icon + @return: wx.Bitmap + + """ + bmp = wx.ArtProvider.GetBitmap(str(self.GetId()), wx.ART_MENU) + return bmp + + @staticmethod + def GetId(): + """Plugin menu identifier ID""" + return ed_glob.ID_LOGGER + + @staticmethod + def GetMenuEntry(menu): + """Get the menu entry for the log viewer + @param menu: the menu items parent menu + + """ + return wx.MenuItem(menu, ed_glob.ID_LOGGER, _("Editra Log"), + _("View Editra's console log")) + + def GetName(self): + """Return the name of this control""" + return self.__name__ + + @staticmethod + def IsStockable(): + """EdLogViewer can be saved in the shelf preference stack""" + return True + +#-----------------------------------------------------------------------------# + +# LogViewer Ui Implementation +class LogViewer(ed_basewin.EdBaseCtrlBox): + """LogViewer is a control for displaying and working with output + from Editra's log. + + """ + def __init__(self, parent): + super(LogViewer, self).__init__(parent) + + # Attributes + self._buffer = LogBuffer(self) + self.SetWindow(self._buffer) + self._srcfilter = None + self._clear = None + + # Layout + self.__DoLayout() + + # Event Handlers + self.Bind(wx.EVT_BUTTON, + lambda evt: self._buffer.Clear(), self._clear) + self.Bind(wx.EVT_CHOICE, self.OnChoice, self._srcfilter) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) + + # Message Handlers + ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED) + + def OnDestroy(self, evt): + """Cleanup and unsubscribe from messages""" + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.OnThemeChange) + + def __DoLayout(self): + """Layout the log viewer window""" + # Setup ControlBar + ctrlbar = self.CreateControlBar(wx.TOP) + + # View Choice + self._srcfilter = wx.Choice(ctrlbar, wx.ID_ANY, choices=[]) + ctrlbar.AddControl(wx.StaticText(ctrlbar, + label=_("Show output from") + ":")) + ctrlbar.AddControl(self._srcfilter) + + # Clear Button + ctrlbar.AddStretchSpacer() + self._clear = self.AddPlateButton(_("Clear"), ed_glob.ID_DELETE, + wx.ALIGN_RIGHT) + + def OnChoice(self, evt): + """Set the filter based on the choice controls value + @param evt: wx.CommandEvent + + """ + self._buffer.SetFilter(self._srcfilter.GetStringSelection()) + + def OnThemeChange(self, msg): + """Update the buttons icon when the icon theme changes + @param msg: Message Object + + """ + cbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DELETE), wx.ART_MENU) + self._clear.SetBitmap(cbmp) + self._clear.Refresh() + + def SetSources(self, srclist): + """Set the list of available log sources in the choice control + @param srclist: list of log sources + + """ + choice = self._srcfilter.GetStringSelection() + lst = sorted(srclist) + lst.insert(0, _("All")) + self._srcfilter.SetItems(lst) + if not self._srcfilter.SetStringSelection(choice): + self._srcfilter.SetSelection(0) + +#-----------------------------------------------------------------------------# +class LogBuffer(eclib.OutputBuffer): + """Buffer for displaying log messages that are sent on Editra's + log channel. + @todo: make line buffering configurable through interface + + """ + RE_WARN_MSG = re.compile(r'\[err\]|\[error\]|\[warn\]') + ERROR_STYLE = eclib.OPB_STYLE_MAX + 1 + + def __init__(self, parent): + super(LogBuffer, self).__init__(parent) + + # Attributes + self._filter = SHOW_ALL_MSG + self._srcs = list() + self.SetLineBuffering(2000) + + # Setup + font = Profile_Get('FONT1', 'font', wx.Font(11, wx.FONTFAMILY_MODERN, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL)) + self.SetFont(font) + style = (font.GetFaceName(), font.GetPointSize(), "#FF0000") + self.StyleSetSpec(LogBuffer.ERROR_STYLE, + "face:%s,size:%d,fore:#FFFFFF,back:%s" % style) + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + + # Subscribe to Editra's Log + ed_msg.Subscribe(self.UpdateLog, ed_msg.EDMSG_LOG_ALL) + + def OnDestroy(self, evt): + """Unregister from receiving any more log messages""" + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.UpdateLog) + evt.Skip() + + def AddFilter(self, src): + """Add a new filter source + @param src: filter source string + @postcondition: if src is new the parent window is updated + + """ + if src not in self._srcs: + self._srcs.append(src) + self.Parent.SetSources(self._srcs) + + def ApplyStyles(self, start, txt): + """Apply coloring to error and warning messages + @note: overridden from L{outbuff.OutputBuffer} + @param start: Start position of text that needs styling in the buffer + @param txt: The string of text that starts at the start position in the + buffer. + + """ + for group in LogBuffer.RE_WARN_MSG.finditer(txt): + sty_s = start + group.start() + sty_e = start + group.end() + self.StartStyling(sty_s, 0xff) + + # Highlight error messages with ERROR_STYLE + self.SetStyling(sty_e - sty_s, LogBuffer.ERROR_STYLE) + + def SetFilter(self, src): + """Set the level of what is shown in the display + @param src: Only show messages from src + @return: bool + + """ + if src in self._srcs: + self._filter = src + return True + elif src == _("All"): + self._filter = SHOW_ALL_MSG + return True + else: + return False + + def UpdateLog(self, msg): + """Add a new log message + @param msg: Message Object containing a LogMsg + + """ + if wx.Thread_IsMain(): + self.DoUpdateLog(msg) + else: + # Delegate to main thread + wx.CallAfter(self.DoUpdateLog, msg) + + def DoUpdateLog(self, msg): + if not self.IsRunning(): + self.Start(200) + + # Check filters + logmsg = msg.GetData() + org = logmsg.Origin + if org not in self._srcs: + self.AddFilter(org) + + if self._filter == SHOW_ALL_MSG: + self.AppendUpdate(unicode(logmsg) + unicode(os.linesep)) + elif self._filter == logmsg.Origin: + msg = u"[%s][%s]%s" % (logmsg.ClockTime, logmsg.Type, logmsg.Value) + self.AppendUpdate(msg + unicode(os.linesep)) + else: + pass diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_main.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_main.py new file mode 100644 index 0000000..2e7807d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_main.py @@ -0,0 +1,1659 @@ +############################################################################### +# Name: ed_main.py # +# Purpose: Editra's Main Window # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +"""@package Editra.src.ed_main + +This module provides the L{MainWindow} class for Editra. The MainWindow is +main Ui component of the editor that contains all the other components. + +@summary: MainWindow Component + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_main.py 72388 2012-08-28 16:06:31Z CJP $" +__revision__ = "$Revision: 72388 $" + +#--------------------------------------------------------------------------# +# Dependencies +import os +import sys +import time +import wx + +# Editra Libraries +from ed_glob import * +import util +import profiler +import ed_toolbar +import ed_mpane +import ed_event +import ed_msg +import ed_menu +import ed_print +import ed_shelf +import ed_statbar +import ed_mdlg +import prefdlg +import syntax.syntax as syntax +import generator +import plugin +import ed_fmgr +import perspective as viewmgr +import ed_session +import iface +import ebmlib +import eclib + +# Function Aliases +_ = wx.GetTranslation +_PGET = profiler.Profile_Get +_PSET = profiler.Profile_Set + +#--------------------------------------------------------------------------# + +class MainWindow(wx.Frame, viewmgr.PerspectiveManager): + """Editras Main Window""" + # Clipboard ring is limited to 25 entries + CLIPBOARD = util.EdClipboard(25) + PRINTER = None + + def __init__(self, parent, id_, wsize, title): + """Initialize the Frame and Event Handlers. + @param wsize: Windows initial size + @param title: Windows Title + + """ + wx.Frame.__init__(self, parent, id_, title, size=wsize, + style=wx.DEFAULT_FRAME_STYLE) + viewmgr.PerspectiveManager.__init__(self, CONFIG['CACHE_DIR']) + + # Setup app icon and title + util.SetWindowIcon(self) + + # Attributes + self._loaded = False + self._initialized = False # for GTK OnActivate HACK + self._mlock = ebmlib.CallLock() + self._last_save = u'' + self.LOG = wx.GetApp().GetLog() + self._exiting = False + self._handlers = dict(menu=list(), ui=list()) + + #---- Setup File History ----# + self.filehistory = ebmlib.EFileHistory(_PGET('FHIST_LVL', 'int', 9)) + + #---- Status bar on bottom of window ----# + self.SetStatusBar(ed_statbar.EdStatBar(self)) + self.GetStatusBar().Show(_PGET('STATBAR', default=True)) + #---- End Statusbar Setup ----# + + #---- Notebook that contains the editing buffers ----# + self._mpane = ed_mpane.MainPanel(self) + self.nb = self._mpane.GetWindow() + self.PanelMgr.AddPane(self._mpane, ed_fmgr.EdPaneInfo(). \ + Name("EditPane").Center().Layer(1).Dockable(False). \ + CloseButton(False).MaximizeButton(False). \ + CaptionVisible(False)) + + #---- Command Bar ----# + self._mpane.HideCommandBar() + + #---- Pane Navigator ----# + self._paneNavi = None + + # Printer Setup + if MainWindow.PRINTER is None: + MainWindow.PRINTER = ed_print.EdPrinter(self) + + #---- Setup Toolbar ----# + self.SetupToolBar() + #---- End Toolbar Setup ----# + + #---- Menus ----# + menbar = ed_menu.EdMenuBar() + + # Todo this should not be hard coded + menbar.GetMenuByName("view").InsertMenu(5, ID_PERSPECTIVES, + _("Perspectives"), self.GetPerspectiveControls()) + + ## Setup additional menu items + self.filehistory.UseMenu(menbar.GetMenuByName("filehistory")) + + # On mac, do this to make help menu appear in correct location + # Note it must be done before setting the menu bar and after the + # menus have been created. + if wx.Platform == '__WXMAC__': + wx.GetApp().SetMacHelpMenuTitleName(_("&Help")) + + #---- Menu Bar ----# + self.SetMenuBar(menbar) + + #---- Actions to take on menu events ----# + + # Collect Menu Event handler pairs + self._handlers['menu'].extend([# File Menu + (ID_NEW, self.OnNew), + (ID_OPEN, self.OnOpen), + (ID_CLOSE, self.OnClosePage), + (ID_CLOSEALL, self.OnClosePage), + (ID_SAVE, self.OnSave), + (ID_SAVEAS, self.OnSaveAs), + (ID_SAVEALL, self.OnSave), + (ID_REVERT_FILE, self.DispatchToControl), + (ID_RELOAD_ENC, self.OnReloadWithEnc), + (ID_SAVE_PROFILE, self.OnSaveProfile), + (ID_LOAD_PROFILE, self.OnLoadProfile), + (ID_SAVE_SESSION, self.OnSaveSession), + (ID_LOAD_SESSION, self.OnLoadSession), + (ID_EXIT, wx.GetApp().OnExit), + (ID_PRINT, self.OnPrint), + (ID_PRINT_PRE, self.OnPrint), + (ID_PRINT_SU, self.OnPrint), + + # Edit Menu + (ID_PASTE_AFTER, self.DispatchToControl), + (ID_CYCLE_CLIPBOARD, self.DispatchToControl), + (ID_COLUMN_MODE, self.DispatchToControl), + (ID_TOGGLE_FOLD, self.DispatchToControl), + (ID_TOGGLE_ALL_FOLDS, self.DispatchToControl), + (ID_SHOW_AUTOCOMP, self.DispatchToControl), + (ID_SHOW_CALLTIP, self.DispatchToControl), + (ID_QUICK_FIND, self.OnCommandBar), + (ID_PREF, OnPreferences), + + # View Menu + (ID_GOTO_LINE, self.OnCommandBar), + (ID_GOTO_MBRACE, self.DispatchToControl), + (ID_SHOW_SB, self.OnShowStatusBar), + (ID_VIEW_TOOL, self.OnViewTb), + (ID_PANELIST, self.OnPaneList), + (ID_MAXIMIZE_EDITOR, self.OnMaximizeEditor), + + # Format Menu + (ID_FONT, self.OnFont), + + # Settings menu + (ID_LEXER_CUSTOM, self.OnCustomizeLangMenu), + + # Tool Menu + (ID_COMMAND, self.OnCommandBar), + (ID_STYLE_EDIT, self.OnStyleEdit), + (ID_PLUGMGR, self.OnPluginMgr), + (ID_SESSION_BAR, self.OnCommandBar), + + # Help Menu + (ID_ABOUT, OnAbout), + (ID_HOMEPAGE, self.OnHelp), + (ID_DOCUMENTATION, self.OnHelp), + (ID_TRANSLATE, self.OnHelp), + (ID_CONTACT, self.OnHelp), + (ID_BUG_TRACKER, self.OnHelp)]) + + self._handlers['menu'].extend([(l_id, self.DispatchToControl) + for l_id in syntax.SYNTAX_IDS]) + + # Extra menu handlers (need to work these into above system yet) + self.Bind(wx.EVT_MENU, self.DispatchToControl) + self.Bind(wx.EVT_MENU, self.OnGenerate) + self.Bind(wx.EVT_MENU_RANGE, self.OnFileHistory, + id=wx.ID_FILE1, id2=wx.ID_FILE9) + + # Update UI Handlers + self._handlers['ui'].extend([# File Menu + (ID_REVERT_FILE, self.OnUpdateFileUI), + (ID_RELOAD_ENC, self.OnUpdateFileUI), + # Edit Menu + (ID_COPY, self.OnUpdateClipboardUI), + (ID_CUT, self.OnUpdateClipboardUI), + (ID_PASTE, self.OnUpdateClipboardUI), + (ID_PASTE_AFTER, self.OnUpdateClipboardUI), + (ID_CYCLE_CLIPBOARD, self.OnUpdateClipboardUI), + (ID_UNDO, self.OnUpdateClipboardUI), + (ID_REDO, self.OnUpdateClipboardUI), + (ID_COLUMN_MODE, self.OnUpdateClipboardUI), + # Format Menu + (ID_INDENT, self.OnUpdateFormatUI), + (ID_USE_SOFTTABS, self.OnUpdateFormatUI), + (ID_TO_UPPER, self.OnUpdateFormatUI), + (ID_TO_LOWER, self.OnUpdateFormatUI), + (ID_WORD_WRAP, self.OnUpdateFormatUI), + (ID_EOL_MAC, self.OnUpdateFormatUI), + (ID_EOL_WIN, self.OnUpdateFormatUI), + (ID_EOL_UNIX, self.OnUpdateFormatUI), + # Settings Menu + (ID_AUTOCOMP, self.OnUpdateSettingsUI), + (ID_AUTOINDENT, self.OnUpdateSettingsUI), + (ID_SYNTAX, self.OnUpdateSettingsUI), + (ID_FOLDING, self.OnUpdateSettingsUI), + (ID_BRACKETHL, self.OnUpdateSettingsUI)]) + + # View Menu + self._handlers['ui'].extend([(m_id, self.OnUpdateViewUI) + for m_id in [ID_ZOOM_NORMAL, ID_ZOOM_IN, + ID_ZOOM_OUT, ID_GOTO_MBRACE, + ID_HLCARET_LINE, ID_SHOW_SB, + ID_VIEW_TOOL, ID_SHOW_WS, + ID_SHOW_EDGE, ID_SHOW_EOL, + ID_SHOW_LN, ID_INDENT_GUIDES, + ID_MAXIMIZE_EDITOR]]) + + # Lexer Menu + self._handlers['ui'].extend([(l_id, self.OnUpdateLexerUI) + for l_id in syntax.SYNTAX_IDS]) + + # Perspectives + self._handlers['ui'].extend(self.GetPersectiveHandlers()) + + #---- End Menu Setup ----# + + #---- Other Event Handlers ----# + # Frame + self.Bind(wx.EVT_ACTIVATE, self.OnActivate) + self.Bind(wx.EVT_CLOSE, self.OnClose) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(ed_event.EVT_STATUS, self.OnStatus) + + # Find Dialog + self._handlers['menu'].extend(self.nb.GetMenuHandlers()) + self._handlers['ui'].extend(self.nb.GetUiHandlers()) + + #---- End other event actions ----# + + #---- Final Setup Calls ----# + self.LoadFileHistory(_PGET('FHIST_LVL', fmt='int')) + + # Call add on plugins + self.LOG("[ed_main][info] Loading MainWindow Plugins") + plgmgr = wx.GetApp().GetPluginManager() + addons = MainWindowAddOn(plgmgr) + addons.Init(self) + self._handlers['menu'].extend(addons.GetEventHandlers()) + self._handlers['ui'].extend(addons.GetEventHandlers(ui_evt=True)) + shelf = ed_shelf.Shelf(plgmgr) + self._shelf = shelf.Init(self) + self._handlers['ui'].extend(shelf.GetUiHandlers(self._shelf)) + + self.LOG("[ed_main][info] Loading Generator plugins") + generator.Generator(plgmgr).InstallMenu(menbar.GetMenuByName("tools")) + + # Set Perspective and other UI settings + self.SetPerspective(_PGET('DEFAULT_VIEW')) + self.PanelMgr.Update() + # Make sure all clients are updated to user specified display font. + ed_msg.PostMessage(ed_msg.EDMSG_DSP_FONT, + _PGET('FONT3', 'font', wx.NORMAL_FONT)) + + # Message Handlers + ed_msg.Subscribe(self.OnUpdateFileHistory, ed_msg.EDMSG_ADD_FILE_HISTORY) + ed_msg.Subscribe(self.OnDoSessionSave, ed_msg.EDMSG_SESSION_DO_SAVE) + ed_msg.Subscribe(self.OnDoSessionLoad, ed_msg.EDMSG_SESSION_DO_LOAD) + + # HACK: for gtk as most linux window managers manage the windows alpha + # and set it when its created. + wx.CallAfter(self.InitWindowAlpha) + + __name__ = u"MainWindow" + + def OnDestroy(self, evt): + """Disconnect Message Handlers""" + if self and evt.Id == self.Id: + ed_msg.Unsubscribe(self.OnUpdateFileHistory) + ed_msg.Unsubscribe(self.OnDoSessionSave) + ed_msg.Unsubscribe(self.OnDoSessionLoad) + evt.Skip() + + #---- End Private Member Functions/Variables ----# + + #---- Begin Public Member Function ----# + def OnActivate(self, evt): + """Activation Event Handler + @param evt: wx.ActivateEvent + + """ + if self._mlock.IsLocked(): + # Deactivated for popup, leave handlers hooked up + wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL) + evt.Skip() + return + + app = wx.GetApp() + active = evt.GetActive() + + # Add or remove handlers from the event stack + if active and not self._loaded: + self._loaded = True + app.SetTopWindow(self) + + # Slow the update interval to reduce overhead + wx.UpdateUIEvent.SetUpdateInterval(215) + wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_SPECIFIED) + self.SetExtraStyle(wx.WS_EX_PROCESS_UI_UPDATES) + + for handler in self._handlers['menu']: + app.AddHandlerForID(*handler) + + for handler in self._handlers['ui']: + app.AddUIHandlerForID(*handler) + + # HACK find better way to do this later. It seems that on gtk the + # window doesn't get activated until later than it does on the + # other platforms. So for panels that depend on updating their + # initial state we need to send out a fake update message here. + if wx.Platform == '__WXGTK__' and not self._initialized: + self._initialized = True + nb = self.GetNotebook() + ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED, + (nb, nb.GetSelection())) + elif not active: + self._loaded = False + self.DeActivate() + + # Notify that window has become active/inactive + ed_msg.PostMessage(ed_msg.EDMSG_UI_MW_ACTIVATE, + dict(active=active), self.Id) + + evt.Skip() + + def OnUpdateFileHistory(self, msg): + """Update filehistory menu for new files that were opened + @param msg: Message object (data == filename) + + """ + # May get notified after/during delete + if self: + try: + self.filehistory.AddFileToHistory(msg.GetData()) + except wx.PyAssertionError: + # ignore errors that wxMac sometimes raises about unicode data + pass + + def AddFileToHistory(self, fname): + """Add a file to the windows file history as well as any + other open windows history. + @param fname: name of file to add + @todo: change the file history to a centrally managed object that + all windows pull from to avoid this quick solution. + + """ + if _PGET('FHIST_LVL', 'int', 9) > 0: + ed_msg.PostMessage(ed_msg.EDMSG_ADD_FILE_HISTORY, fname) + + def AddMenuHandler(self, menu_id, handler): + """Add a menu event handler to the handler stack + @param menu_id: Menu item id + @param handler: Handler callable + @postcondition: handler is added only if its not already in the set + + """ + for item in self._handlers['menu']: + if item[0] == menu_id: + return + else: + self._handlers['menu'].append((menu_id, handler)) + + def AddUIHandler(self, menu_id, handler): + """Add a UpdateUI event handler to the handler stack + @param menu_id: Menu item id + @param handler: Handler callable + @postcondition: handler is added only if its not already in the set + + """ + for item in self._handlers['ui']: + if item[0] == menu_id: + return + else: + self._handlers['ui'].append((menu_id, handler)) + + def DoOpen(self, evt, fname=u'', lnum=-1): + """ Do the work of opening a file and placing it + in a new notebook page. + @keyword fname: can be optionally specified to open + a file without opening a FileDialog + @keyword lnum: Explicitly set the line number to open the file to + + """ + try: + e_id = evt.GetId() + except AttributeError: + e_id = evt + + if e_id == ID_OPEN: + fdir = self.GetNotebook().GetCurrentCtrl().GetFileName() + if len(fdir): + fdir = os.path.dirname(fdir) + elif not hasattr(sys, 'frozen'): + fdir = os.curdir + + dlg = wx.FileDialog(self, _("Editra: Open"), fdir, "", + ''.join(syntax.GenFileFilters()), + wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR) + dlg.SetFilterIndex(_PGET('FFILTER', 'int', 0)) + + if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK: + _PSET('FFILTER', dlg.GetFilterIndex()) + for path in dlg.GetPaths(): + if _PGET('OPEN_NW', default=False): + wx.GetApp().OpenNewWindow(path) + else: + self.nb.OpenPage(ebmlib.GetPathName(path), + ebmlib.GetFileName(path)) + self.nb.GoCurrentPage() + + dlg.Destroy() + else: + self.LOG("[ed_main][info] CMD Open File: %s" % fname) + self.nb.OpenPage(ebmlib.GetPathName(fname), + ebmlib.GetFileName(fname), quiet=True) + self.nb.GoCurrentPage() + + # lnum arg is only used with command line open + if lnum >= 0: + buff = self.nb.GetCurrentCtrl() + buff.GotoLine(lnum) + + self.Raise() + + def DeActivate(self): + """Helper method for the App to tell this window to remove + all its event handlers. + + """ + self.SetExtraStyle(0) + + # HACK set update ui events back to process all here in case + # opened dialog needs them. Not sure why this is necessary but it + # is the only solution I could find to fix the external find + # dialogs so that their buttons become enabled when typing in the + # text control. + # + # If the windows that took the active position is another mainwindow + # it will set the events back to UPDATE_UI_PROCESS_SPECIFIED to + # prevent all the toolbars/menu items of each window from updating + # when they dont need to. + wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL) + self.FlushEventStack() + + def FlushEventStack(self): + """Clear the Menu and UpdateUI event handler stack + @note: only unregisters this frames handlers from the app + + """ + app = wx.GetApp() + for handler in self._handlers['menu']: + app.RemoveHandlerForID(handler[0]) + + for handler in self._handlers['ui']: + app.RemoveUIHandlerForID(handler[0]) + + def GetCommandbar(self): + """Get this windows command bar + @return: ed_cmdbar.CommandBarBase + + """ + return self._mpane.GetControlBar(wx.BOTTOM) + + def GetEditPane(self): + """Get the editor notebook/command bar control + @return: ed_mpane.MainPane + + """ + return self._mpane + + def GetNotebook(self): + """Get the windows main notebook that contains the editing buffers + @return: reference to L{extern.flatnotebook.FlatNotebook} instance + + """ + return getattr(self, 'nb', None) + + def GetShelf(self): + """Get this windows Shelf + @return: reference to L{iface.Shelf} instance + @note: returns the plugin instance not the actual notebook, if + a reference to the notebook is needed for parenting call + GetWindow on the object returned by this function. + + """ + return self._shelf + + def IsExiting(self): + """Returns whether the windows is in the process of exiting + or not. + @return: boolean stating if the window is exiting or not + + """ + return self._exiting + + def IsTopWindow(self): + """Is this main window 'the' current top window + @return: bool + + """ + return wx.GetApp().GetTopWindow() == self + + def LoadFileHistory(self, size): + """Loads file history from profile + @return: None + + """ + try: + hist_list = _PGET('FHIST', default=list()) + if len(hist_list) > size: + hist_list = hist_list[:size] + self.filehistory.History = hist_list + except (Exception, wx.PyAssertionError), msg: + self.LOG("[ed_main][err] Filehistory load failed: %s" % msg) + + def OnNew(self, evt): + """Start a New File in a new tab + @param evt: wx.MenuEvent + + """ + if evt.GetId() == ID_NEW: + self.nb.NewPage() + self.nb.GoCurrentPage() + else: + evt.Skip() + + def OnOpen(self, evt): + """Open a File + @param evt: wx.MenuEvent + + """ + if evt.GetId() == ID_OPEN: + self.DoOpen(evt) + else: + evt.Skip() + + def OnFileHistory(self, evt): + """Open a File from the File History + @param evt: wx.MenuEvent + + """ + fnum = evt.GetId() - wx.ID_FILE1 + fname = self.filehistory.GetHistoryFile(fnum) + + # Check if file still exists + if not os.path.exists(fname): + mdlg = wx.MessageDialog(self, _("%s could not be found.\nPerhaps " + "it's been moved or deleted.") % \ + fname, _("File Not Found"), + wx.OK | wx.ICON_WARNING) + mdlg.CenterOnParent() + ebmlib.LockCall(self._mlock, mdlg.ShowModal) + mdlg.Destroy() + # Remove offending file from history + self.filehistory.RemoveFileFromHistory(fnum) + else: + self.DoOpen(evt, fname) + + def OnClosePage(self, evt): + """Close a page + @param evt: wx.MenuEvent + + """ + if not self.IsActive(): + evt.Skip() + return + + e_id = evt.Id + if e_id == ID_CLOSE: + self.nb.ClosePage() + elif e_id == ID_CLOSEALL: + self.nb.CloseAllPages() + else: + evt.Skip() + + def SaveFile(self, tablbl, buf): + """Save the given page in the notebook + @param tablbl: main notebook tab label + @param buf: EdEditView instance + @note: intended for internal use! method signature may change + + """ + fname = ebmlib.GetFileName(buf.GetFileName()) + if fname != u'': + fpath = buf.GetFileName() + result = buf.SaveFile(fpath) + self._last_save = fpath + if result: + self.PushStatusText(_("Saved File: %s") % fname, SB_INFO) + else: + err = buf.GetDocument().GetLastError() + self.PushStatusText(_("ERROR: %s") % err, SB_INFO) + ed_mdlg.SaveErrorDlg(self, fname, err) + buf.GetDocument().ResetAll() + else: + self.OnSaveAs(ID_SAVEAS, tablbl, buf) + + def SaveCurrentBuffer(self): + """Save the file in the currently selected editor buffer""" + page = self.nb.GetSelection() + self.SaveFile(self.nb.GetPageText(page), self.nb.GetCurrentCtrl()) + + def SaveAllBuffers(self): + """Save all open editor buffers""" + for page in range(self.nb.GetPageCount()): + buff = self.nb.GetPage(page) + if isinstance(buff, wx.stc.StyledTextCtrl): + if buff.GetModify(): + self.SaveFile(self.nb.GetPageText(page), buff) + + def OnSave(self, evt): + """Save Current or All Buffers + @param evt: wx.MenuEvent + + """ + e_id = evt.Id + if e_id == ID_SAVE: + self.SaveCurrentBuffer() + elif e_id == ID_SAVEALL: + self.SaveAllBuffers() + else: + evt.Skip() + return + + def OnSaveAs(self, evt, title=u'', page=None): + """Save File Using a new/different name + @param evt: wx.MenuEvent + + """ + if page: + ctrl = page + else: + ctrl = self.nb.GetCurrentCtrl() + + if title == u'': + title = os.path.split(ctrl.GetFileName())[1] + + sdir = ctrl.GetFileName() + if sdir is None or not len(sdir): + sdir = self._last_save + + dlg = wx.FileDialog(self, _("Choose a Save Location"), + os.path.dirname(sdir), + title.lstrip(u"*"), + u''.join(syntax.GenFileFilters()), + wx.SAVE | wx.OVERWRITE_PROMPT) + + if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK: + path = dlg.GetPath() + dlg.Destroy() + + result = ctrl.SaveFile(path) + fname = ebmlib.GetFileName(ctrl.GetFileName()) + if not result: + err = ctrl.GetDocument().GetLastError() + ed_mdlg.SaveErrorDlg(self, fname, err) + ctrl.GetDocument().ResetAll() + self.PushStatusText(_("ERROR: Failed to save %s") % fname, SB_INFO) + else: + self._last_save = path + self.PushStatusText(_("Saved File As: %s") % fname, SB_INFO) + self.SetTitle("%s - file://%s" % (fname, ctrl.GetFileName())) + self.nb.SetPageText(self.nb.GetSelection(), fname) + self.nb.GetCurrentCtrl().FindLexer() + self.nb.UpdatePageImage() + self.AddFileToHistory(ctrl.GetFileName()) + else: + dlg.Destroy() + + def OnSaveProfile(self, evt): + """Saves current settings as a profile + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_SAVE_PROFILE: + dlg = wx.FileDialog(self, _("Where to Save Profile?"), \ + CONFIG['PROFILE_DIR'], "default.ppb", \ + _("Profile") + " (*.ppb)|*.ppb", + wx.SAVE | wx.OVERWRITE_PROMPT) + + if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK: + profiler.TheProfile.Write(dlg.GetPath()) + self.PushStatusText(_("Profile Saved as: %s") % \ + dlg.GetFilename(), SB_INFO) + dlg.Destroy() + else: + evt.Skip() + + def OnLoadProfile(self, evt): + """Loads a profile and refreshes the editors state to match + the settings found in the profile file. + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_LOAD_PROFILE: + dlg = wx.FileDialog(self, _("Load a Custom Profile"), + CONFIG['PROFILE_DIR'], "default.ppb", + _("Profile") + " (*.ppb)|*.ppb", wx.OPEN) + + if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK: + profiler.TheProfile.Load(dlg.GetPath()) + self.PushStatusText(_("Loaded Profile: %s") % \ + dlg.GetFilename(), SB_INFO) + dlg.Destroy() + + # Update editor to reflect loaded profile + for win in wx.GetApp().GetMainWindows(): + win.nb.UpdateTextControls() + else: + evt.Skip() + + def OnDoSessionSave(self, msg): + """ed_msg interface for initiating a session save""" + if msg.Context == self.Id: + self.DoSaveSessionAs() + + def OnSaveSession(self, evt): + """Save the current session of open files.""" + if evt.Id == ID_SAVE_SESSION: + self.DoSaveSessionAs() + else: + evt.Skip() + + def DoSaveSessionAs(self): + """Prompt the user to save the current session""" + mgr = ed_session.EdSessionMgr() + cses = _PGET('LAST_SESSION', default=u"") + if cses == mgr.DefaultSession: + cses = u"" + fname = ebmlib.LockCall(self._mlock, wx.GetTextFromUser, + (_("Session Name"), _("Save Session"), cses)) + fname = fname.strip() + if fname: + rval = self.nb.SaveSessionFile(fname) + if rval is not None: + wx.MessageBox(rval[1], rval[0], wx.OK|wx.ICON_ERROR) + return + + _PSET('LAST_SESSION', fname) + self.PushStatusText(_("Session Saved as: %s") % fname, SB_INFO) + + def OnDoSessionLoad(self, msg): + """Initiate the loading of a session""" + if msg.Context == self.Id: + ses = msg.GetData() + if ses: + self.DoLoadSession(ses) + + def OnLoadSession(self, evt): + """Load a saved session.""" + if evt.Id == ID_LOAD_SESSION: + mgr = ed_session.EdSessionMgr() + sessions = mgr.GetSavedSessions() + cses = _PGET('LAST_SESSION') + if cses in sessions: + sessions.remove(cses) + if len(sessions) and (sessions[0] == mgr.DefaultSession): + sessions[0] = _("Default") + if cses == mgr.DefaultSession: + cses = _("Default") + fname = ebmlib.LockCall(self._mlock, wx.GetSingleChoice, + (_("Session to Load:\nCurrent Session: '%s'") % cses, + _("Load Session"), + sessions)) + if fname: + self.DoLoadSession(fname) + else: + evt.Skip() + + def DoLoadSession(self, fname): + """Load the specified session + @param fname: session name + + """ + if fname: + mgr = ed_session.EdSessionMgr() + if fname == _("Default"): + fname = mgr.DefaultSession + nbook = self.GetNotebook() + rval = nbook.LoadSessionFile(fname) + + # Check for an error during load + if rval is not None: + wx.MessageBox(rval[1], rval[0], wx.OK|wx.ICON_WARNING) + return + + _PSET('LAST_SESSION', fname) + if fname == mgr.DefaultSession: + fname = _("Default") + self.PushStatusText(_("Loaded Session: %s") % fname, SB_INFO) + + def OnStatus(self, evt): + """Update status text with messages from other controls + @param evt: event that called this handler + + """ + self.SetStatusText(evt.GetMessage(), evt.GetSection()) + + def OnPrint(self, evt): + """Handles sending the current document to the printer, + showing print previews, and opening the printer settings + dialog. + @todo: is any manual cleanup required for the printer objects? + @param evt: wxMenuEvent + + """ + e_id = evt.Id + printer = MainWindow.PRINTER + ctrl = self.nb.GetCurrentCtrl() + if not ctrl: + util.Log("[ed_main][warn] invalid control reference for printing: %s" % repr(ctrl)) + wx.MessageBox(_("Failed to get control reference for printing"), + _("Print failure"), wx.CENTER|wx.ICON_ERROR|wx.OK) + return + + printer.SetStc(ctrl) + printer.SetColourMode(_PGET('PRINT_MODE')) + if e_id == ID_PRINT: + printer.Print() + elif e_id == ID_PRINT_PRE: + printer.Preview() + elif e_id == ID_PRINT_SU: + printer.PageSetup() + else: + evt.Skip() + + def Close(self, force=False): + """Close the window + @param force: force the closer by vetoing the event handler + + """ + if force: + return super(MainWindow, self).Close(True) + else: + result = self.OnClose() + return not result + + def OnClose(self, evt=None): + """Close this frame and unregister it from the applications + mainloop. + @note: Closing the frame will write out all session data to the + users configuration directory. + @keyword evt: wx.MenuEvent + @return: None on destroy, or True on cancel + + """ + # Only auto-save session file if not using default session + mgr = ed_session.EdSessionMgr() + if _PGET('LAST_SESSION') == mgr.DefaultSession: + self.nb.SaveCurrentSession() + + # Cleanup Controls + self._exiting = True + controls = self.nb.GetPageCount() + self.LOG("[ed_main][evt] OnClose: Number of controls: %d" % controls) + with eclib.Freezer(self) as _tmp: + while controls: + if controls <= 0: + self.Close(True) # Force exit since there is a problem + + self.LOG("[ed_main][evt] OnClose: Requesting Page Close") + if not self.nb.ClosePage(): + self._exiting = False + ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED, + (self.nb, self.nb.GetSelection())) + return True + controls -= 1 + + ### If we get to here there is no turning back so cleanup + ### additional items and save user settings + + # Write out saved document information + self.nb.DocMgr.WriteBook() + syntax.SyntaxMgr().SaveState() + + # Save Shelf contents + _PSET('SHELF_ITEMS', self._shelf.GetItemStack()) + _PSET('SHELF_LAYOUT', self._shelf.GetPerspective()) + _PSET('SHELF_SELECTION', self._shelf.GetSelection()) + + # Save Window Size/Position for next launch + self.UpdateAutoPerspective() + + # XXX On wxMac the window size doesnt seem to take the toolbar + # into account so destroy it so that the window size is accurate. + if wx.Platform == '__WXMAC__' and self.GetToolBar(): + self.ToolBar.Destroy() + + # Raise the window from being iconized so that the size and position is + # correct for the next launch (msw). + if self.IsIconized(): + self.Iconize(False) + + _PSET('WSIZE', self.GetSizeTuple()) + _PSET('MAXIMIZED', self.IsMaximized()) + _PSET('WPOS', self.GetPositionTuple()) + + self.LOG("[ed_main][evt] OnClose: Closing editor at pos=%s size=%s" % \ + (_PGET('WPOS', 'str'), _PGET('WSIZE', 'str'))) + + # Cleanup file history + # TODO: Find out why filehistory can be undefined by this point + # sometimes. + try: + _PSET('FHIST', self.filehistory.History) + except AttributeError: + self.LOG("[ed_main][err] OnClose: Trapped AttributeError OnExit") + + # Update profile + ppath = _PGET('MYPROFILE') + profiler.TheProfile.Write(ppath) + self.LOG("[ed_main][info] Saving profile to %s" % ppath) + + # Post exit notice to all aui panes + panes = self.PanelMgr.GetAllPanes() + exit_evt = ed_event.MainWindowExitEvent(ed_event.edEVT_MAINWINDOW_EXIT, + wx.ID_ANY) + for pane in panes: + if pane.window: + wx.PostEvent(pane.window, exit_evt) + + # Finally close the window + self.LOG("[ed_main][evt] OnClose: Closing Main Frame") + wx.GetApp().UnRegisterWindow(repr(self)) + + # Ensure that event handlers have been un registered from the app + wx.UpdateUIEvent.SetMode(wx.UPDATE_UI_PROCESS_ALL) + + # Cleanup + mpane = None + for pane in self.PanelMgr.AllPanes: + if pane and pane.window: + win = pane.window + if isinstance(win, ed_mpane.MainPanel): + mpane = win + continue + elif self.PanelMgr.DetachPane(win): + win.Destroy() + + # NOTE: wxBUG? calling destroy on the center pane results in + # a pure virtual function call error. So just destroy + # the child Notebook. + if mpane: + if mpane.Book: + mpane.Book.Destroy() + + self.PanelMgr.UnInit() + self.Destroy() + + #---- End File Menu Functions ----# + + #---- View Menu Functions ----# + def OnShowStatusBar(self, evt): + """Toggles visibility of status bar + @param evt: wxMenuEvent + + """ + if evt.Id == ID_SHOW_SB: + show = not self.GetStatusBar().IsShown() + _PSET('STATBAR', show) + self.GetStatusBar().Show(show) + self.SendSizeEvent() + else: + evt.Skip() + + def OnViewTb(self, evt): + """Toggles visibility of toolbar + @param evt: wxMenuEvent + + """ + if evt.Id == ID_VIEW_TOOL: + size = self.GetSize() + toolbar = self.GetToolBar() + if _PGET('TOOLBAR', 'bool', False) or toolbar.IsShown(): + _PSET('TOOLBAR', False) + toolbar.Hide() + if wx.Platform != '__WXMAC__': + self.SetSize((size[0], size[1] - toolbar.GetSize()[1])) + else: + _PSET('TOOLBAR', True) + toolbar.Show() + if wx.Platform != '__WXMAC__': + self.SetSize((size[0], size[1] + toolbar.GetSize()[1])) + + self.SendSizeEvent() + self.Refresh() + self.Update() + else: + evt.Skip() + + def OnMaximizeEditor(self, evt): + """Maximize the editor and hide the other panes. If the editor + is already maximized, it is un-maximized and the other panes are restored + @param evt: CommandEvent instance + + """ + paneInfo = self.PanelMgr.GetPane("EditPane") + if self.PanelMgr.IsEditorMaximized(): + self.PanelMgr.RestorePane(paneInfo) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_RESTORE, context=self.GetId()) + else: + self.PanelMgr.MaximizePane(paneInfo) + self.PanelMgr.Update() + + #---- End View Menu Functions ----# + + #---- Format Menu Functions ----# + def OnFont(self, evt): + """Open Font Settings Dialog for changing fonts on a per document + basis. + @note: This currently does not allow for font settings to stick + from one session to the next. + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_FONT: + ctrl = self.nb.GetCurrentCtrl() + fdata = wx.FontData() + fdata.SetInitialFont(ctrl.GetDefaultFont()) + dlg = wx.FontDialog(self, fdata) + result = ebmlib.LockCall(self._mlock, dlg.ShowModal) + data = dlg.GetFontData() + dlg.Destroy() + if result == wx.ID_OK: + font = data.GetChosenFont() + ctrl.SetGlobalFont(self.nb.control.FONT_PRIMARY, \ + font.GetFaceName(), font.GetPointSize()) + ctrl.SetGlobalFont(self.nb.control.FONT_SECONDARY, \ + font.GetFaceName(), font.GetPointSize()) + ctrl.UpdateAllStyles() + else: + evt.Skip() + + #---- End Format Menu Functions ----# + + #---- Tools Menu Functions ----# + def OnStyleEdit(self, evt): + """Opens the style editor + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_STYLE_EDIT: + import style_editor + dlg = style_editor.StyleEditor(self) + dlg.CenterOnParent() + ebmlib.LockCall(self._mlock, dlg.ShowModal) + dlg.Destroy() + else: + evt.Skip() + + def OnPluginMgr(self, evt): + """Opens and shows Plugin Manager window + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_PLUGMGR: + import plugdlg + win = wx.GetApp().GetWindowInstance(plugdlg.PluginDialog) + if win is not None: + win.Raise() + return + dlg = plugdlg.PluginDialog(self, wx.ID_ANY, PROG_NAME + " " \ + + _("Plugin Manager"), \ + size=wx.Size(550, 450)) + dlg.CenterOnParent() + dlg.Show() + else: + evt.Skip() + + def OnGenerate(self, evt): + """Generates a given document type + @pre: PluginMgr must be initialized and have active + plugins that implement the Generator Interface + @param evt: wx.MenuEvent + + """ + gen = generator.Generator(wx.GetApp().GetPluginManager()) + doc = gen.GenerateText(evt.Id, self.nb.GetCurrentCtrl()) + if doc: + self.nb.NewPage() + ctrl = self.nb.GetCurrentCtrl() + ctrl.SetText(doc[1]) + ctrl.FindLexer(doc[0]) + else: + evt.Skip() + + #---- Misc Function Definitions ----# + def DispatchToControl(self, evt): + """Catches events that need to be passed to the current + text control for processing. + @param evt: wx.MenuEvent + + """ + if not self.IsActive(): + evt.Skip() + return + + e_id = evt.Id + ctrl = self.nb.GetCurrentCtrl() + active_only = [ ID_ZOOM_IN, ID_ZOOM_OUT, ID_ZOOM_NORMAL, + ID_JOIN_LINES, ID_CUT_LINE, ID_COPY_LINE, ID_INDENT, + ID_UNINDENT, ID_TRANSPOSE, ID_TOGGLECOMMENT, + ID_LINE_MOVE_UP, ID_LINE_MOVE_DOWN, + ID_SELECTALL, ID_UNDO, ID_REDO, ID_CUT, ID_COPY, + ID_PASTE, ID_LINE_BEFORE, ID_LINE_AFTER, ID_DUP_LINE, + ID_PASTE_AFTER, ID_COLUMN_MODE, ID_TOGGLE_FOLD, + ID_CYCLE_CLIPBOARD, + ID_TOGGLE_ALL_FOLDS, ID_DELETE_LINE, + ID_SHOW_AUTOCOMP, ID_SHOW_CALLTIP ] + + # Special handling for common clipboard related actions + has_focus = self.FindFocus() + is_stc = isinstance(has_focus, wx.stc.StyledTextCtrl) + if has_focus is not None: + if e_id == ID_PASTE and hasattr(has_focus, 'Paste'): + has_focus.Paste() + return + elif e_id == ID_CYCLE_CLIPBOARD: + start, end = has_focus.GetSelection() + start, end = min(start, end), max(start, end) + + if is_stc: + txt = has_focus.GetTextRange(start, end) + elif hasattr(has_focus, 'GetRange'): + txt = has_focus.GetRange(start, end) + else: + self.LOG("[ed_main][warn] no range meth in cycle clipboard") + return + + if not MainWindow.CLIPBOARD.IsAtIndex(txt): + MainWindow.CLIPBOARD.Reset() + + next = MainWindow.CLIPBOARD.GetNext() + if is_stc: + has_focus.ReplaceSelection(next) + elif hasattr(has_focus, 'Replace'): + has_focus.Replace(start, end, next) + else: + return + + has_focus.SetSelection(start, start+len(next)) + return + elif e_id == ID_CUT and hasattr(has_focus, 'Cut'): + start, end = has_focus.GetSelection() + if is_stc: + txt = has_focus.GetTextRange(start, end) + elif hasattr(has_focus, 'GetRange'): + txt = has_focus.GetRange(start, end) + MainWindow.CLIPBOARD.Put(txt) + has_focus.Cut() + return + elif e_id == ID_COPY and hasattr(has_focus, 'Copy'): + start, end = has_focus.GetSelection() + if is_stc: + txt = has_focus.GetTextRange(start, end) + elif hasattr(has_focus, 'GetRange'): + txt = has_focus.GetRange(start, end) + MainWindow.CLIPBOARD.Put(txt) + has_focus.Copy() + return + elif e_id == ID_REDO and hasattr(has_focus, 'Redo'): + has_focus.Redo() + return + elif e_id == ID_UNDO and hasattr(has_focus, 'Undo'): + has_focus.Undo() + return + elif e_id == ID_SELECTALL and hasattr(has_focus, 'SelectAll'): + has_focus.SelectAll() + return + + menu_ids = list(syntax.SYNTAX_IDS) + menu_ids.extend([ID_SHOW_EOL, ID_SHOW_WS, ID_INDENT_GUIDES, ID_SYNTAX, + ID_WORD_WRAP, ID_BRACKETHL, ID_EOL_MAC, ID_EOL_UNIX, + ID_EOL_WIN, ID_NEXT_MARK, ID_PRE_MARK, ID_ADD_BM, + ID_DEL_ALL_BM, ID_FOLDING, ID_AUTOCOMP, ID_SHOW_LN, + ID_AUTOINDENT, ID_TAB_TO_SPACE, ID_SPACE_TO_TAB, + ID_TRIM_WS, ID_SHOW_EDGE, ID_MACRO_START, + ID_MACRO_STOP, ID_MACRO_PLAY, ID_TO_LOWER, + ID_TO_UPPER, ID_USE_SOFTTABS, + ID_GOTO_MBRACE, ID_HLCARET_LINE, ID_REVERT_FILE, + ]) + menu_ids.extend(active_only) + + if e_id in menu_ids: + ctrl.ControlDispatch(evt) + else: + evt.Skip() + return + + def OnReloadWithEnc(self, evt): + """Reload the current file with a specified encoding + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_RELOAD_ENC: + ctrl = self.nb.GetCurrentCtrl() + doc = ctrl.GetDocument() + cenc = doc.GetEncoding() + dlg = eclib.EncodingDialog(self.GetNotebook(), + msg=_("Select an encoding to reload the file with"), + title=_("Reload with Encoding"), + default=cenc) + bmp = wx.ArtProvider.GetBitmap(str(ID_DOCPROP), wx.ART_OTHER) + if bmp.IsOk(): + dlg.SetBitmap(bmp) + dlg.CenterOnParent() + + if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK: + nenc = dlg.GetEncoding() + doc.SetEncoding(nenc) + success = ctrl.ReloadFile()[0] + if not success: + msg = _("Failed to reload the file with: %(encoding)s") % dict(encoding=nenc) + wx.MessageBox(msg, style=wx.OK|wx.ICON_ERROR) + # Revert to previous encoding + doc.SetEncoding(cenc) + ctrl.ReloadFile() + dlg.Destroy() + else: + evt.Skip() + + def OnPaneList(self, evt): + """Navigates through panes + @param evt: CommandEvent instance + + """ + if evt.Id == ID_PANELIST: + if self._paneNavi is not None: + return + + bmp = wx.ArtProvider.GetBitmap(str(ID_NEW_WINDOW), wx.ART_MENU) + self._paneNavi = eclib.AuiPaneNavigator(self, self.PanelMgr, bmp, + _("Aui Pane Navigator")) + self._paneNavi.SetReturnCode(wx.ID_OK) + ebmlib.LockCall(self._mlock, self._paneNavi.ShowModal) + + sel = self._paneNavi.GetSelection() + self._paneNavi.Destroy() + self._paneNavi = None + + if isinstance(sel, basestring): + paneInfo = self.PanelMgr.GetPane(sel) + if paneInfo.IsOk(): + if not paneInfo.IsShown(): + paneInfo.Show() + self.PanelMgr.Update() + # Notify activation if the window supports it + if hasattr(paneInfo.window, "OnShowAUIPane"): + paneInfo.window.OnShowAUIPane() + paneInfo.window.SetFocus() + else: + evt.Skip() + + # Menu Update Handlers + def OnUpdateFileUI(self, evt): + """Update filemenu items + @param evt: EVT_UPDATE_UI + + """ + if not self.IsActive(): + return + + e_id = evt.Id + ctrl = self.nb.GetCurrentCtrl() + if e_id == ID_REVERT_FILE: + evt.Enable(ctrl.GetModify()) + elif e_id == ID_RELOAD_ENC: + evt.Enable(len(ctrl.GetFileName())) + else: + evt.Skip() + + def OnUpdateClipboardUI(self, evt): + """Update clipboard related menu/toolbar items + @param evt: EVT_UPDATE_UI + + """ + if not self.IsActive(): + return + + e_id = evt.Id + focus = self.FindFocus() + enable = False + if e_id == ID_UNDO: + if hasattr(focus, 'CanUndo'): + enable = focus.CanUndo() + evt.Enable(enable) + elif e_id == ID_REDO: + if hasattr(focus, 'CanRedo'): + enable = focus.CanRedo() + evt.Enable(enable) + elif e_id in (ID_PASTE, ID_PASTE_AFTER, ID_CYCLE_CLIPBOARD): + if hasattr(focus, 'CanPaste'): + enable = focus.CanPaste() + evt.Enable(enable) + elif e_id == ID_COPY: + if hasattr(focus, 'CanCopy'): + enable = focus.CanCopy() + evt.Enable(enable) + elif e_id == ID_CUT: + if hasattr(focus, 'CanCut'): + enable = focus.CanCut() + evt.Enable(enable) + elif e_id == ID_COLUMN_MODE: + if hasattr(focus, 'IsColumnMode'): + evt.Enable(True) + else: + evt.Enable(False) + evt.Check(enable) + else: + evt.Skip() + + def OnUpdateFormatUI(self, evt): + """Update status of format menu items + @param evt: wxEVT_UPDATE_UI + + """ + if not self.IsActive(): + return + + e_id = evt.Id + ctrl = self.nb.GetCurrentCtrl() + if e_id == ID_USE_SOFTTABS: + evt.Check(not bool(ctrl.GetUseTabs())) + elif e_id == ID_WORD_WRAP: + evt.Check(bool(ctrl.GetWrapMode())) + elif e_id in [ID_EOL_MAC, ID_EOL_WIN, ID_EOL_UNIX]: + evt.Check(ctrl.GetEOLModeId() == e_id) + elif e_id in [ID_INDENT, ID_TO_UPPER, ID_TO_LOWER]: + evt.Enable(ctrl.GetSelectionStart() != ctrl.GetSelectionEnd()) + else: + evt.Skip() + + def OnUpdateLexerUI(self, evt): + """Update status of lexer menu + @param evt: wxEVT_UPDATE_UI + + """ + if not self.IsActive(): + return + + e_id = evt.Id + if e_id in syntax.SYNTAX_IDS: + lang = self.nb.GetCurrentCtrl().GetLangId() + evt.Check(lang == e_id) + else: + evt.Skip() + + def OnUpdateSettingsUI(self, evt): + """Update settings menu items + @param evt: wxEVT_UPDATE_UI + + """ + if not self.IsActive(): + return + + e_id = evt.Id + ctrl = self.nb.GetCurrentCtrl() + if e_id == ID_AUTOCOMP: + evt.Check(ctrl.GetAutoComplete()) + elif e_id == ID_AUTOINDENT: + evt.Check(ctrl.GetAutoIndent()) + elif e_id == ID_SYNTAX: + evt.Check(ctrl.IsHighlightingOn()) + elif e_id == ID_FOLDING: + evt.Check(ctrl.IsFoldingOn()) + elif e_id == ID_BRACKETHL: + evt.Check(ctrl.IsBracketHlOn()) + else: + evt.Skip() + + def OnUpdateViewUI(self, evt): + """Update status of view menu items + @param evt: wxEVT_UPDATE_UI + + """ + if not self.IsActive(): + return + + e_id = evt.Id + ctrl = self.nb.GetCurrentCtrl() + zoom = ctrl.GetZoom() + if e_id == ID_ZOOM_NORMAL: + evt.Enable(zoom) + elif e_id == ID_ZOOM_IN: + evt.Enable(zoom < 18) + elif e_id == ID_ZOOM_OUT: + evt.Enable(zoom > -8) + elif e_id == ID_GOTO_MBRACE: + evt.Enable(-1 not in ctrl.GetBracePair()) + elif e_id == ID_HLCARET_LINE: + evt.Check(ctrl.GetCaretLineVisible()) + elif e_id == ID_SHOW_SB: + evt.Check(self.GetStatusBar().IsShown()) + elif e_id == ID_VIEW_TOOL: + evt.Check(self.GetToolBar().IsShown()) + elif e_id == ID_SHOW_WS: + evt.Check(bool(ctrl.GetViewWhiteSpace())) + elif e_id == ID_SHOW_EDGE: + evt.Check(bool(ctrl.GetEdgeMode())) + elif e_id == ID_SHOW_EOL: + evt.Check(bool(ctrl.GetViewEOL())) + elif e_id == ID_SHOW_LN: + evt.Check(bool(ctrl.GetMarginWidth(1))) + elif e_id == ID_INDENT_GUIDES: + evt.Check(bool(ctrl.GetIndentationGuides())) + elif e_id == ID_MAXIMIZE_EDITOR: + binder = self.MenuBar.GetKeyBinder() + binding = binder.GetBinding(ID_MAXIMIZE_EDITOR) + txt = _("Maximize Editor") + if self.PanelMgr.IsEditorMaximized(): + txt = _("Restore Editor") + evt.SetText(txt + binding) + else: + evt.Skip() + + def OnCommandBar(self, evt): + """Open the Commandbar + @param evt: wx.MenuEvent + + """ + e_id = evt.Id + if e_id in (ID_QUICK_FIND, ID_GOTO_LINE, ID_COMMAND, ID_SESSION_BAR): + self._mpane.ShowCommandControl(e_id) + else: + evt.Skip() + + def OnCustomizeLangMenu(self, evt): + """Show the lexer menu customization dialog""" + if evt.Id == ID_LEXER_CUSTOM: + dlg = eclib.FilterDialog(self, title=_("Customize Menu"), + style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) + mconfig = _PGET("LEXERMENU", default=list()) + flters = dict() + for item in syntax.SyntaxNames(): + if item in mconfig: + flters[item] = True + else: + flters[item] = False + dlg.SetListValues(flters) + dlg.SetInitialSize() + dlg.CenterOnParent() + + if ebmlib.LockCall(self._mlock, dlg.ShowModal) == wx.ID_OK: + includes = dlg.GetIncludes() + includes.sort() + _PSET("LEXERMENU", includes) + ed_msg.PostMessage(ed_msg.EDMSG_CREATE_LEXER_MENU) + dlg.Destroy() + else: + evt.Skip() + + def OnHelp(self, evt): + """Handles help related menu events + @param evt: wx.MenuEvent + + """ + import webbrowser + e_id = evt.Id + if e_id == ID_HOMEPAGE: + page = HOME_PAGE + elif e_id == ID_DOCUMENTATION: + page = HOME_PAGE + "/documentation" + elif e_id == ID_TRANSLATE: + page = I18N_PAGE + elif e_id == ID_CONTACT: + webbrowser.open("mailto:%s" % CONTACT_MAIL) + return + elif e_id == ID_BUG_TRACKER: + page = "http://code.google.com/p/editra/issues/list" + else: + evt.Skip() + return + + # It seems under some cases when running under windows the call to + # subprocess in webbrowser will fail and raise an exception here. So + # simply trap and ignore it. + try: + self.PushStatusText(_("Opening %s") % page, SB_INFO) + webbrowser.open(page, 1) + except: + self.PushStatusText(_("Error: Unable to open %s") % page, SB_INFO) + + def PushStatusText(self, txt, field): + """Override so that our custom status bar's method gets called + do to these wxFrame methods not being exposed as virtuals. + + """ + sb = self.GetStatusBar() + if sb: + sb.PushStatusText(txt, field) + + SetStatusText = PushStatusText + + def SetTitle(self, title=u''): + """Sets the windows title + @param title: The text to tag on to the default frame title + + """ + name = u"%s v%s" % (PROG_NAME, VERSION) + if len(title): + name = u" - " + name + super(MainWindow, self).SetTitle(title + name) + + def SetupToolBar(self): + """Setup or reinitialize the windows ToolBar""" + tb = self.GetToolBar() + if tb: + tb.Destroy() + self.SetToolBar(ed_toolbar.EdToolBar(self)) + self.ToolBar.Realize() + self.GetToolBar().Show(_PGET('TOOLBAR')) + self.Layout() + + @classmethod + def UpdateClipboardRing(cls): + """Update the clipboard ring to sync it with the + system clipboard. + @note: for internal use only + + """ + try: + txt = util.GetClipboardText() + except wx.PyAssertionError: + txt = None + + if txt is None or cls.CLIPBOARD.IsAtIndex(txt): + return + + # Something new has come in from an external program + cls.CLIPBOARD.Reset() + cls.CLIPBOARD.Put(txt) + +#-----------------------------------------------------------------------------# +# Event handlers that don't need to be part of the class + +def OnAbout(evt): + """Show the About Dialog + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_ABOUT: + info = wx.AboutDialogInfo() + year = time.localtime() + desc = [_("Editra is a programmers text editor."), + _("Written in 100%% Python."), + _("Homepage") + ": " + HOME_PAGE + "\n", + _("Platform Info") + ": (%s,%s)", + _("License: wxWindows (see COPYING.txt for full license)")] + desc = "\n".join(desc) + py_version = sys.platform + ", python " + sys.version.split()[0] + platform = list(wx.PlatformInfo[1:]) + platform[0] += (" " + wx.VERSION_STRING) + wx_info = ", ".join(platform) + info.SetCopyright(_("Copyright") + "(C) 2005-%d Cody Precord" % year[0]) + info.SetName(PROG_NAME.title()) + info.SetDescription(desc % (py_version, wx_info)) + info.SetVersion(VERSION) + wx.AboutBox(info) + else: + evt.Skip() + +def OnPreferences(evt): + """Open the Preference Panel + @param evt: wx.MenuEvent + + """ + if evt.Id == ID_PREF: + cursor = wx.BusyCursor() + win = wx.GetApp().GetWindowInstance(prefdlg.PreferencesDialog) + if win is not None: + win.Raise() + else: + dlg = prefdlg.PreferencesDialog(None) + dlg.CenterOnParent() + dlg.Show() + del cursor + else: + evt.Skip() + +#-----------------------------------------------------------------------------# +# Plugin interface to the MainWindow + +class MainWindowAddOn(plugin.Plugin): + """Plugin that Extends the L{MainWindowI}""" + observers = plugin.ExtensionPoint(iface.MainWindowI) + def Init(self, window): + """Call all observers once to initialize + @param window: window that observers become children of + + """ + for observer in self.observers: + try: + observer.PlugIt(window) + except Exception, msg: + util.Log("[ed_main][err] MainWindowAddOn.Init: %s" % msg) + + def GetEventHandlers(self, ui_evt=False): + """Get Event handlers and Id's from all observers + @keyword ui_evt: Get Update Ui handlers (default get menu handlers) + @return: list [(ID_FOO, foo.OnFoo), (ID_BAR, bar.OnBar)] + + """ + handlers = list() + for observer in self.observers: + try: + items = None + if ui_evt: + if hasattr(observer, 'GetUIHandlers'): + items = observer.GetUIHandlers() + assert isinstance(items, list), "Must be a list()!" + else: + if hasattr(observer, 'GetMenuHandlers'): + items = observer.GetMenuHandlers() + assert isinstance(items, list), "Must be a list()!" + except Exception, msg: + util.Log("[ed_main][err] MainWindowAddOn.GetEventHandlers: %s" % str(msg)) + continue + + if items is not None: + handlers.extend(items) + + return handlers diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_marker.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_marker.py new file mode 100644 index 0000000..3f7fbff --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_marker.py @@ -0,0 +1,377 @@ +############################################################################### +# Name: ed_marker.py # +# Purpose: StyledTextCtrl Markers # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Classes to represent Markers and associated data in a StyledTextCtrl + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_marker.py 67626 2011-04-27 02:51:39Z CJP $" +__revision__ = "$Revision: 67626 $" + +#-----------------------------------------------------------------------------# +import wx +import wx.stc +from extern.embeddedimage import PyEmbeddedImage + +# NOTE: Must be 1 char per pixel for Scintilla to display +_BookmarkBmp = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDAQA0GON3MFgAAAEG" + "SURBVDjL7ZK9SgNBFIW/nd1SO1EbBUHQgD+g+AKSN9E2nY+RztfxOSwCAUEIFlHUsLPB7L3H" + "YjdjTBqxFG91mLnzzTlzB/4rA+j2+vpJ893tTba8VszF/dU1uQRWg2cU7uAiyMFgfTig2+tr" + "GRLmIjeDmVGYKGojmBHMoXawmsnuHs8n5ytuE4AyEqoSjxGmEY8VXpUQI0wrqCLvW9uMD4+4" + "XICkCDZ6BAQmXI19JILUaBMB5y0PTDrHKU4C+OgB97bZmwuCOyaBQ46n/YOX1/SgCfAxHIAc" + "1LpzgQA5OWJmgMTp2sa3aXxFGD81Qu1BFzlqUzkIznY6K6NMgIvN/V/9gz9Qn2ObnTkNCjcr" + "AAAAAElFTkSuQmCC") + +_ArrowBmp = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAQCAYAAADJViUEAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDAQEBO+Lj6asAAADR" + "SURBVCjPpZItEgIxDIUfTA+B3CNEItsbrOAQDIojLA6J4hSI3KDBIeOwOygEzOwNFgP7A/2B" + "Ia5pvte+eQH+qEmoycytqgIAiAhlWQbnpillEYGqgpnbn+GcgGHmtmmaUXN49n4H59adnaEF" + "o6oQkeTrMQEzHIgXwXv9EDDvQ2kBwLk+kRF8P+ezPewFi9XT8/DidsnDy62FtRZE1MPHTfzL" + "szlwPQGV9ODIcyU2CFZWgiAAGCJCURQfUF3XXYQhMLvbLzgEfrWeMTALp0AAeAAUy3GCxymX" + "vQAAAABJRU5ErkJggg==") + +_BreakpointBmp = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEgMQBqh6qrUAAAEf" + "SURBVDjLpZPNTsJQEIW/CxgJUStWJTRqEBZEiZqY6AOY2FdiaVz2Adz6IiY+gHFHGn82yI9V" + "UjUWFkKh1lUx1VKvYZZzc76cOzMHpiwR1axWND+qb5iW+BNQrWj+qrLE/maZQnYFgNeew63V" + "oGY9/IKIn+Kj3UP0wlak3fvnFudXlyGICIl3DtDzxdg/t95szq6/IalAnF9U0bMa9PuxgPXM" + "PMcbZQDfMC2RCh6214q89Bypye+peS6ad4wdAKhzCgnXl9vdaMTCzGwYMHCHdPsjaUAwvDGg" + "030n4yWlAc5wEAbU7UeU9LKUvvPRJXKNpVxJCvBkNzmpNUTkIeWS8S4cr8epWRexp4yXnpAc" + "F+OmLf4RpgT4gPicGKap6ws0jWfqOADTLwAAAABJRU5ErkJggg==") + +_BreakpointDisabledBmp = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dE" + "AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEgMRGEtuppcAAABy" + "SURBVDjLY2TAAcq1pf4j8zuvPmPEpo6RGM2EDMHQjM0AXOIkKcIrT5QNuNQRqxmbekYYg6gA" + "whLQTAwUgoE3gOJAJCsaG3Xl/5OdkOq1FYlIjbqqmElZQ+l/uabMfxIzExMDw38GBgbGfzgz" + "EyOl2RkAwXRPWcN07zMAAAAASUVORK5CYII=") + +_StackMarker = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAd1J" + "REFUOI2Fk09rE1EUxX930jSZJIaBkGJcKBilC0uxG+kkuIhKKdn5EfoREvwO7jprV+LahSuL" + "CKEQqCO6cJNFQ1qEFBJJKYSaPx1Br4sx00xG64EH79377rnnHe4TMWLMw66LChKKqSquo+Hg" + "H8iMwK6JrtxNkMvluJ3eJF9chqFF99sxrX6T06MffNj9FSERMWJB1+qjp+RzK2ANaU8aAGST" + "eQrGOnv7bxh0vIgSw9cI+TvLfO6+5dXrF3QPz1hNPQbg/OKU9qRBdWOHVDKDXRMNEZTqhooI" + "o5M4g46HqtLqN+kenpFN5i9vWkNu3c8iEn6FMds0nn8X11FxHZVBx6PVb1Iw1um1xwC0Jw0K" + "y/ciJhqqihJSheuojE7iANxYTQckZvxalADxPVjE1BuHzr322Dd4AUvuru+qXRNNJTPhwqFF" + "7+s4UlSqG0FLmR8kuyYqIlQePuHm9SIAe19eBvnqxg5AMBuDjhcmmFey+cDmeHrAdPgzyJlW" + "jLXsNvsH75lcjHAdFYMFuI7KxBvx8ZPLWnYb07psUDTLfrE3CgYqoiBQUhdNJTJUylu0zt9R" + "NMu+7COPmW9XEszMMhNpKuWtkOz5O1cSzHsy9cZ//UyIEfvvKj1b0n/lfgPWHMMhVFXV8gAA" + "AABJRU5ErkJggg==") + +_ErrorBmp = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAc5J" + "REFUOI11kzFP20AUx3/nEBGLRFUr5CEIieoGhkRtVJVI3uIROiBgYWLzxgco3SulysjIF8iC" + "UJaspjOtRIEODKZZihBClcABW0I5d2h8shP3P53e6f977929J4RRIK3PahQLIciTEcd8NAqZ" + "S5EGtNUorklJy3VzAccHB/z0/QxEA9Lm3ycnPPt+xjxvmpTX16cgxqR50O3mZr8LQ4a9Hk3b" + "piYlbTWKAYzJzEUpebm/T1FKbS5KidXvc1+tonyflutqiKGEoOW6DHs9nn2fhZUVAMzNTYpS" + "amASuwtDBt0uTdtGCcFMusTkod4sLlJyHEqOo6uIPI+HTmf6ZyYDS5UKD50Okedl4nnmXEDS" + "czo7wNL2tj4PggA1/qUMYN40Mz1HnqcredrZwarXGQQBszc32jMD8HRxAcCv01MWdne1OV12" + "yXGIVleZPTqirJSOiy8Q16Skadv4h4cAvFpb40+/D8DQMCgrhdza4sfYXFleJri85DiK/k1i" + "W43iD40GVr2uIYkSQKLE/DUM2TMKIjPK7+bmeLuxMQVJ9LrR4PzsjO+Pj+yNRzl3md5bFvfV" + "Ki+urzOAb7e3nF9d8UkY08uUhqj/rLOIY5050V9UfNMzpyji5gAAAABJRU5ErkJggg==") + +_LintBmpGreen = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAZNJ" + "REFUOI3Fk00ow2Ecxz/P/ogtYxNRaDIvlykvO4yThHJzUBx3lLujg6O75OQkB4lSJKSUVsMO" + "qI1lW15aJv5/85KXbX8na48R5eBbz+H5Pd/ft2/f3+8RwqDwFxj+1P2TQMd8q94y1qgDdM+5" + "9F8JOGeaJGKBw5SufYhlIudzoTjfhHPSoSev3jAm8njKecWWW0m/vZfVuw18BCS++CrED7tu" + "+yAAi8draIpKf0kfs3dLAOwM7AtJoHvOpd/4VQzPOpZmKz3l7QBEosG0sFcNk7x6wzceEFkZ" + "rA95RIHDhKXZits+SCQaxHvpJ5ZKYKuoo6OuCwClJk9yK4X4svtAcdLCxXWYWCoBQGeZi0g0" + "iKbGuT3SuPWq1A5XpcOUQkzlCzRFTd+d1no8IS9ms2DxZgVLoZG9iWOR2SM58I0HhPb8yHx4" + "k84yF4dnpziqa4nHdULbFwgla2jZe7DrPhAYBVsxD2azYHp5AX/ohNOpcwHQNtog7cKXY8wk" + "qvdPFJWapOQlCIPy47GP2PRv3//9N74DHQaLgsqg1M8AAAAASUVORK5CYII=") + +_LintBmpRed = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAXJJ" + "REFUOI3Fk79Lw0AYhp9LhA4tFIyQQSg2oq2zRTPYrtLJjpLRVf8AxVnwD9C1o4OTBcVdC42i" + "jtpWjCIVGq1xsYiEek4NptQf0MEPDj7uvve9l+c4IRSVQUoZSP2bQbmwILdnZ2S3/5PBQS4b" + "DLZcl1FFYcVI9hUDDPVuxIeHKWam5ZuqMqLrACzqOgnLothoyKWzc/F1XvSD2I2bsCwA7nd2" + "ANBMk6ejI7yXFwoVW4QMyoUFeVirAZBPpdBMk/fHR14dh5hh8Oo4tFyXh48Plk9OgxQBg7m9" + "kphPJsmnUiQsKxB3SzNNAMYikVDaEMTdahUAz7YDsWaaQe/5PsfNJsXMdAA1BDHe4x4zDJ5t" + "G4BaqcRNu81m/ToEMZRg46oq9i8vuatUgptjhkHLdfF8n06nQ2/1fYWDXFb6vs+IrlNvNLjw" + "PLacW7E6OSFVVWXjqip+NABYn0pLgPFolJt2OyQKR1DUX9daOi2/Pf/33/gJL9aOTtHLtUIA" + "AAAASUVORK5CYII=") + +_LintBmpYellow = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAblJ" + "REFUOI3FkzFIG2EUx39frmCStgpqIw0pJKGEpErViEIHoYtQcOjSTkJ1ky7irLM6ScVFbBeL" + "FBxEBAUHl6IirVMKFdseXE5yjSVGCzW53ImXr0Mh9DRiwaEPvuG9773/e/y+9wnhUbiOea5V" + "fZXA7FibHB6ISoD5yQ75TwLPntytJOpGEZ9PYag/Ik3LqdrkxvnA054gj5INMpM1CYduUiie" + "8eB+LV3dfYwYphyf+Sb+zhfVIM5PdkjTcnjc8wKAnc13AMQTrWxs7ZD/aTMxowqXwOxYm9xT" + "f1GWks6H9cQTrZxax2jpDIHGGgDefzikVHKYmtMqU1QYDI6mxL2gn+ZYHV3dfRwffkFLZwC4" + "dTtA/Z04AMaP0uUQ978X8XsV8sYGumFiWg6xeAuf93TK0kHVCyBg5GWsAtoF0SMEuSObaOSP" + "Hw75SaU+4fcqLK9uEwx4mX6bFnBQfYKpOU181U5YXd8l2Z4kl7dpSYTJHdmoegHLLl8AfmEP" + "Xi/sCzVdYGllk0BjDa/efCSTNVlcOxAAQ/0R10JVfUaA4YGoLEtJNmcRavK5yLtMeJQrz/Pe" + "kLz0/r//xt8H26DcJVZnmgAAAABJRU5ErkJggg==") + +#-----------------------------------------------------------------------------# + +__markerId = -1 +def NewMarkerId(): + """Get a new marker id + @note: limited by stc to 16 possible ids. will assert when this threshold + is passed. + + """ + global __markerId + __markerId += 1 + assert __markerId < 24, "No more marker Ids available!" + return __markerId + +#-----------------------------------------------------------------------------# + +class Marker(object): + """Marker Base class""" + _ids = list() + _symbols = list() + def __init__(self): + super(Marker, self).__init__() + + # Attributes + self._line = -1 + self._handle = -1 + self._bmp = wx.NullBitmap + self._fore = wx.NullColour # Foreground colour + self._back = wx.NullColour # Background colour + + Line = property(lambda self: self._line, + lambda self, line: setattr(self, '_line', line)) + Handle = property(lambda self: self._handle, + lambda self, handle: setattr(self, '_handle', handle)) + Bitmap = property(lambda self: self._bmp, + lambda self, bmp: setattr(self, '_bmp', bmp)) + Foreground = property(lambda self: self._fore, + lambda self, fore: setattr(self, '_fore', fore)) + Background = property(lambda self: self._back, + lambda self, back: setattr(self, '_back', back)) + + @classmethod + def AnySet(cls, stc, line): + """Is any breakpoint set on the line""" + if not cls.IsSet(stc, line): + # Check subclasses + for bpoint in cls.__subclasses__(): + if bpoint.IsSet(stc, line): + return True + return False + else: + return True + + @classmethod + def GetIds(cls): + """Get the list of marker IDs.""" + return cls._ids + + @classmethod + def GetSymbols(cls): + """Get the list of symbols""" + return cls._symbols + + @classmethod + def IsSet(cls, stc, line): + """Is the marker set on the given line""" + mask = stc.MarkerGet(line) + return True in [ bool(1<<marker & mask) for marker in cls.GetIds() ] + + def Set(self, stc, line, delete=False): + """Add/Delete the marker to the stc at the given line""" + for marker in self.GetIds(): + if delete: + mask = stc.MarkerGet(line) + if (1<<marker & mask): + stc.MarkerDelete(line, marker) + else: + handle = stc.MarkerAdd(line, marker) + if self.Handle < 0: + self.Line = line + self.Handle = handle + + def DeleteAll(self, stc): + """Remove all instances of this bookmark from the stc""" + for marker in self.GetIds(): + stc.MarkerDeleteAll(marker) + + def RegisterWithStc(self, stc): + """Setup the STC to use this marker""" + ids = self.GetIds() + if self.Bitmap.IsNull(): + symbols = self.GetSymbols() + if len(ids) == len(symbols): + markers = zip(ids, symbols) + for marker, symbol in markers: + stc.MarkerDefine(marker, symbol, + self.Foreground, self.Background) + elif len(ids) == 1 and not self.Bitmap.IsNull(): + stc.MarkerDefineBitmap(ids[0], self.Bitmap) + else: + assert False, "Invalid Marker!" + +#-----------------------------------------------------------------------------# + +class Bookmark(Marker): + """Class to store bookmark data""" + _ids = [NewMarkerId(),] + def __init__(self): + super(Bookmark, self).__init__() + + # Attributes + self._name = u"" # Bookmark alias name + self._fname = u"" # Filename + self.Bitmap = _BookmarkBmp.Bitmap + + def __eq__(self, other): + return (self.Filename, self.Line) == (other.Filename, other.Line) + + #---- Properties ----# + Name = property(lambda self: self._name, + lambda self, name: setattr(self, '_name', name)) + Filename = property(lambda self: self._fname, + lambda self, name: setattr(self, '_fname', name)) + +#-----------------------------------------------------------------------------# + +class Breakpoint(Marker): + """Marker object to represent a breakpoint in the EditraBaseStc""" + _ids = [NewMarkerId(),] + def __init__(self): + super(Breakpoint, self).__init__() + self.Bitmap = _BreakpointBmp.Bitmap + +class BreakpointDisabled(Breakpoint): + """Marker object to represent a disabled breakpoint in the EditraBaseStc""" + _ids = [NewMarkerId(),] + def __init__(self): + super(BreakpointDisabled, self).__init__() + self.Bitmap = _BreakpointDisabledBmp.Bitmap + +class BreakpointStep(Breakpoint): + """Marker object to represent debugger step breakpoint in the EditraBaseStc""" + _ids = [NewMarkerId(), NewMarkerId()] + def __init__(self): + super(BreakpointStep, self).__init__() + self.Bitmap = _ArrowBmp.Bitmap + + def DeleteAll(self, stc): + """Overrode to handle refresh issue""" + super(BreakpointStep, self).DeleteAll(stc) + stc.Colourise(0, stc.GetLength()) + + def RegisterWithStc(self, stc): + """Register this compound marker with the given StyledTextCtrl""" + ids = self.GetIds() + stc.MarkerDefineBitmap(ids[0], self.Bitmap) + stc.MarkerDefine(ids[1], wx.stc.STC_MARK_BACKGROUND, + background=self.Background) + + def Set(self, stc, line, delete=False): + """Add/Delete the marker to the stc at the given line + @note: overrode to ensure only one is set in a buffer at a time + + """ + self.DeleteAll(stc) + super(BreakpointStep, self).Set(stc, line, delete) + start = stc.GetLineEndPosition(max(line-1, 0)) + end = stc.GetLineEndPosition(line) + if start == end: + start = 0 + stc.Colourise(start, end) # Refresh for background marker + +class StackMarker(Marker): + """Marker object to mark a line in a callstack in the EditraBaseStc""" + _ids = [NewMarkerId(),] + def __init__(self): + super(StackMarker, self).__init__() + self.Bitmap = _StackMarker.Bitmap + +#-----------------------------------------------------------------------------# + +class FoldMarker(Marker): + """Marker object class for managing the code folding markers""" + _ids = [wx.stc.STC_MARKNUM_FOLDEROPEN, wx.stc.STC_MARKNUM_FOLDER, + wx.stc.STC_MARKNUM_FOLDERSUB, wx.stc.STC_MARKNUM_FOLDERTAIL, + wx.stc.STC_MARKNUM_FOLDEREND, wx.stc.STC_MARKNUM_FOLDEROPENMID, + wx.stc.STC_MARKNUM_FOLDERMIDTAIL] + _symbols = [wx.stc.STC_MARK_BOXMINUS, wx.stc.STC_MARK_BOXPLUS, + wx.stc.STC_MARK_VLINE, wx.stc.STC_MARK_LCORNER, + wx.stc.STC_MARK_BOXPLUSCONNECTED, + wx.stc.STC_MARK_BOXMINUSCONNECTED, wx.stc.STC_MARK_TCORNER] + + def RegisterWithStc(self, stc): + super(FoldMarker, self).RegisterWithStc(stc) + stc.SetFoldMarginHiColour(True, self.Foreground) + stc.SetFoldMarginColour(True, self.Foreground) + +#-----------------------------------------------------------------------------# + +class ErrorMarker(Marker): + """Marker object to indicate an error line in the EditraBaseStc""" + _ids = [NewMarkerId(), NewMarkerId()] + def __init__(self): + super(ErrorMarker, self).__init__() + self.Bitmap = _ErrorBmp.Bitmap + + def DeleteAll(self, stc): + """Overrode to handle refresh issue""" + super(ErrorMarker, self).DeleteAll(stc) + stc.Colourise(0, stc.GetLength()) + + def RegisterWithStc(self, stc): + """Register this compound marker with the given StyledTextCtrl""" + ids = self.GetIds() + stc.MarkerDefineBitmap(ids[0], self.Bitmap) + stc.MarkerDefine(ids[1], wx.stc.STC_MARK_BACKGROUND, + # foreground=self.Foreground, #TODO + background=self.Foreground) + + def Set(self, stc, line, delete=False): + """Add/Delete the marker to the stc at the given line + @note: overrode to ensure only one is set in a buffer at a time + + """ + super(ErrorMarker, self).Set(stc, line, delete) + start = stc.GetLineEndPosition(max(line-1, 0)) + end = stc.GetLineEndPosition(line) + if start == end: + start = 0 + stc.Colourise(start, end) # Refresh for background marker + +#-----------------------------------------------------------------------------# + +class LintMarker(Marker): + """Marker object to represent a marker for coding issue in the EditraBaseStc""" + _ids = [NewMarkerId(),] + def __init__(self): + super(LintMarker, self).__init__() + self.Bitmap = _LintBmpGreen.Bitmap + +class LintMarkerWarning(Marker): + """Marker object to represent a marker for moderate severity + coding issue in the EditraBaseStc + + """ + _ids = [NewMarkerId(),] + def __init__(self): + super(LintMarkerWarning, self).__init__() + self.Bitmap = _LintBmpYellow.Bitmap + +class LintMarkerError(Marker): + """Marker object to represent a marker for a high severity + coding issue in the EditraBaseStc + + """ + _ids = [NewMarkerId(),] + def __init__(self): + super(LintMarkerError, self).__init__() + self.Bitmap = _LintBmpRed.Bitmap diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mdlg.py new file mode 100644 index 0000000..a0ad749 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mdlg.py @@ -0,0 +1,158 @@ +############################################################################### +# Name: ed_mdlg.py # +# Purpose: Commonly used message dialogs # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module provides a number of message dialogs that are commonly used +throughout Editra. Its purpose is to promote reuse of the common dialogs for +consistancy and reduction in redundant code. + +@summary: Common dialogs and related convenience functions + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_mdlg.py 66817 2011-01-29 21:32:20Z CJP $" +__revision__ = "$Revision: 66817 $" + +#--------------------------------------------------------------------------# +# Imports +import wx +import wx.stc +from extern.embeddedimage import PyEmbeddedImage + +# Editra Library +import ed_glob +import util +import eclib + +#--------------------------------------------------------------------------# +# Globals + +_ = wx.GetTranslation + +FileIcon = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAABthJ" + "REFUWIW9l21sVFkZgJ/7Pd8zLdOWQloiIA2WbiqBLWhhdw3IAhuyRqMxq64uv1B/GMJqYvzK" + "qqkmfqx/3UiC7q4QN5o1UnbRPyVLgdYtCAjdju2Uwhbabmd6O9PpdO7H8Ud7h2lnaLv+8E1u" + "zj3vnXPe57znfd9zRqJcIseOHXsxGo1W5fP5nOu6xQ+OIwAXT+e6LrZtUygUdE3T3O7u7pP9" + "/f03K8y5egkGgy2maTpiBXEcR1iWJXK5nBgbGxPJZFJ0d3eL3bt3H/4w9qSlinA43NbT03O5" + "oaGBdDoNgBAC13WLreM4xb4QAtu2SaVSzMzMEI/HOX78+KGLFy+eWw2AXEYkSWKhLdWhKAqy" + "LCPLMoqiFPuSJKFpGrFYjImJCUzTpLOzs7O1tfXg/wTgGaz0eIZVVS2+eyC6rhOLxRgaGiIS" + "idDV1dXZ0tKyIkQZgGVZopJxb/XeqksBvCcQCCCEIJPJEIlEuHLlSueOHTuWhajogVJjnkG3" + "JA48AE3Tit7wtsHv99Pf38/g4CCWZXH27NnOtra2R0KoSxXV1dWKruvFrXDd+bRzhUC47iJv" + "2LZDKGigqgqTqSy1tbVks1nOnDnDyMgIwWCQXbt20dHR0XnixImn+/r63l5qrywLDh48uP/0" + "6dPnFUXBNE0cy0Lz+9Grq3EdB5jPfyc7Q33cRyo1zcR4hnhjPXmhUJjLk0gkGLpxA3t2ltm5" + "ORobGzEMI3306NHHUqnUvWU9sHXr1ng4HMY0TRRFwRcIYOdymAMDyJqGNZmm1nCItGzm0nWT" + "F37Yx8c32Jz8js34/TkwdOK2Q9W2baiBAIV8nkwmQ01NTVVTU9OnL126dHJZgLVr18a91DIM" + "A7/fz8TwMOaXn6chGmBNewsDH32Cb/xxlOvvJWleU8vVbD2dL/+Zw9fOM2FaCOHi/OznRJub" + "sSYmiMViyLJMLpfzrxgDmqb5AAzDQFEUAHyFAi2BAsqhw5xSW3n5wizbxACnmsdpbdV4IxNk" + "w2QM4wOTUP8gbjhM1tBxFgqVYRgEAgE0TVtqrhzAsqwcgKIoxYj3r1vLXz73I875d3H15k1+" + "teMuTwUNHiR0JmerOLAlTu+4Rr69HXfGxhEOuqZh6Dr5hSzy+/0YhlEWc2UAyWTyfXhYjKYn" + "U3z/lb9zJRVAQqLev4XaDQ5EFLJOlM0HdnI7rfLcrx/Q9ewetoyNku4fJuTzEfL7wedDCIGq" + "qchyedaXabq7uycymUyxPxeuYn+Dj4vSGxwI/pO3bmn8picMbU1sfuEQd2b8dLzyHx70K7yU" + "qIP9e1nf+jFq6msxAJ/Ph67rqIpK6cn6SIBkMlnI5/MAFCyLGl2ifUcz6X/0ccT3Lvvb5kik" + "6/nbhTR/Opei7bnXyZq3ee17Phx5kluBOq637OHUhQQaYPh8xYIFiBW3AJA8V3kb5kQi3Pv8" + "19i+r4Uv3XufjrONvPhbhTX2X3n1x4+z75Nb4NYgz1h3MXqv8qrSzC97E3zxQDPBUDXZhQJW" + "Sco8oKqqJMnzP/ZAFKDRdWBgki80zrK+apzEgxDPf7aVffubYFzCHpki2NWLoZnkwptI3A0x" + "en9s0TyVYqDMA7ZtC89RHrWwHXJ3htHyc4RrdL7ZrnAnHeP1y2v5RPRdmqU8qgY8+yl+/2+D" + "H/TYfGWPReO6mkXzrMoDpeIFjSRc3A8mcadSzF4e4EhdhiNtGW6PxXjtXzroM1ybinKgt56X" + "+mf5ae0Ffnd8O1owTi6XWxagUgwgxOJYEbYNd+8iWRZzcwX87wi++pEC4ztruJbaxTPnrzI2" + "PcxeaZQ3Iwl8l3sxx48SqlvsyVUBWJZVBChts/k8SiaDpRuEJoM0PxnDvHqf0fvDtFfd5CfG" + "NVpHhsjcGGFQ1YjrKhEe1hOgWFlX9IAnkiThAqFNm1j/1jkkSSJSFeK9xCjf+sXbhKI+/vDt" + "x2nZ+BnE0JOkbBc34KdOUQisW4dtO4sAVuWBpeLaNqphEN24sagbJc2e9ga++/XDoEQQgPtY" + "I1EPHLALBWyrgFR+4q8M4BF7rXcT9t73bt/EUzu3AGDbNm5Jnns3ZSHmxwtAkh4d66sCmL+O" + "C2D+WlawCsj24vshzOe5Bzs/VEIIgbxQV7xFfGiA+VYsTCYX/x94xh+CLh7vSaUCVPz2yC9L" + "JvBWWwq5VCfLi2/SlWCWSpkHVFWVFg6ORYMrXSaWg60kmqatfB+wbduZmpoiHA4zPT1d1Jf+" + "PxBCIFyBK9zyolXS9941TSMUClEoFMrO40r+qQ6FQk/Islznuq5NyREaCARkwzBk27ZFPp93" + "LcsqO14fIaokSblMJvMOkFzlmP+P/BeZah5l10evBAAAAABJRU5ErkJggg==") + +#--------------------------------------------------------------------------# + +def OpenErrorDlg(parent, fname, err): + """Show a file open error dialog + @param parent: parent window + @param fname: file that failed to open + @param err: error message + + """ + argmap = dict(filename=fname, errormsg=err) + dlg = wx.MessageDialog(parent, + _("Editra could not open %(filename)s\n\n" + "Error:\n%(errormsg)s") % \ + argmap, _("Error Opening File"), + style=wx.OK|wx.CENTER|wx.ICON_ERROR) + dlg.CenterOnParent() + result = dlg.ShowModal() + dlg.Destroy() + return result + +def SaveErrorDlg(parent, fname, err): + """Show a file save error modal dialog + @param parent: window that the dialog is the child of + @param fname: name of file that error occured + @param err: the err message/description + @return: wxID_OK if dialog was shown and dismissed properly + + """ + argmap = dict(filename=fname, errormsg=err) + dlg = wx.MessageDialog(parent, + _("Failed to save file: %(filename)s\n\n" + "Error:\n%(errormsg)s") % argmap, + _("Save Error"), wx.OK|wx.ICON_ERROR) + dlg.CenterOnParent() + result = dlg.ShowModal() + dlg.Destroy() + return result + +#--------------------------------------------------------------------------# + +class EdFileInfoDlg(eclib.FileInfoDlg): + """File information dialog""" + def __init__(self, parent, fname): + """General file information dialog + @param parent: parent window + @param fname: file path + + """ + super(EdFileInfoDlg, self).__init__(parent, fname=fname, ftype=None, + bmp=FileIcon.GetBitmap()) + + # Setup + self.SetFileTypeLabel(util.GetFileType(fname)) + +#--------------------------------------------------------------------------# + +class EdFormatEOLDlg(eclib.ChoiceDialog): + """Dialog for selecting EOL format""" + def __init__(self, parent, msg=u'', title=u'', selection=0): + """Create the dialog + @keyword selection: default selection (wx.stc.STC_EOL_*) + + """ + choices = [_("Old Machintosh (\\r)"), _("Unix (\\n)"), + _("Windows (\\r\\n)")] + self._eol = [wx.stc.STC_EOL_CR, wx.stc.STC_EOL_LF, wx.stc.STC_EOL_CRLF] + idx = self._eol.index(selection) + super(EdFormatEOLDlg, self).__init__(parent, msg=msg, title=title, + choices=choices, + style=wx.YES_NO|wx.YES_DEFAULT) + self.SetSelection(idx) + + # Setup + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOCPROP), wx.ART_OTHER) + if bmp.IsOk(): + self.SetBitmap(bmp) + self.CenterOnParent() + + def GetSelection(self): + """Get the selected eol mode + @return: wx.stc.STC_EOL_* + + """ + sel = super(EdFormatEOLDlg, self).GetSelection() + return self._eol[sel] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_menu.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_menu.py new file mode 100644 index 0000000..f0255c2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_menu.py @@ -0,0 +1,1228 @@ +############################################################################### +# Name: ed_menu.py # +# Purpose: Editra's Menubar and Menu related classes # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007-2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +@package: Editra.src.ed_menu + +Provides an advanced menu class for easily creating menus and setting their +related bitmaps when available from Editra's ArtProvider. The Keybinder class +for managing keybindings and profiles is also provided by this module. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_menu.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Dependencies +import os +import wx + +# Editra Libraries +import ed_glob +import ed_msg +import profiler +import util +from syntax import syntax +from syntax import synglob + +#--------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation + +#--------------------------------------------------------------------------# + +class EdMenu(wx.Menu): + """Custom wxMenu class that makes it easier to customize and access items. + + """ + def __init__(self, title=wx.EmptyString, style=0): + """Initialize a Menu Object + @param title: menu title string + @param style: type of menu to create + + """ + super(EdMenu, self).__init__(title, style) + + def Append(self, id_, text=u'', helpstr=u'', \ + kind=wx.ITEM_NORMAL, use_bmp=True): + """Append a MenuItem + @param id_: New MenuItem ID + @keyword text: Menu Label + @keyword helpstr: Help String + @keyword kind: MenuItem type + @keyword use_bmp: try and set a bitmap if an appropriate one is + available in the ArtProvider + + """ + item = wx.MenuItem(self, id_, text, helpstr, kind) + self.AppendItem(item, use_bmp) + return item + + def AppendEx(self, id_, text=u'', helpstr=u'', + kind=wx.ITEM_NORMAL, use_bmp=True): + """Like L{Append} but automatically applies keybindings to text + based on item id. + + """ + binding = EdMenuBar.keybinder.GetBinding(id_) + item = self.Append(id_, text+binding, helpstr, kind, use_bmp) + return item + + def AppendItem(self, item, use_bmp=True): + """Appends a MenuItem to the menu and adds an associated + bitmap if one is available, unless use_bmp is set to false. + @param item: wx.MenuItem + @keyword use_bmp: try and set a bitmap if an appropriate one is + available in the ArtProvider + + """ + if use_bmp and item.GetKind() == wx.ITEM_NORMAL: + self.SetItemBitmap(item) + super(EdMenu, self).AppendItem(item) + + def Insert(self, pos, id_, text=u'', helpstr=u'', \ + kind=wx.ITEM_NORMAL, use_bmp=True): + """Insert an item at position and attach a bitmap + if one is available. + @param pos: Position to insert new item at + @param id_: New MenuItem ID + @keyword label: Menu Label + @keyword helpstr: Help String + @keyword kind: MenuItem type + @keyword use_bmp: try and set a bitmap if an appropriate one is + available in the ArtProvider + + """ + item = super(EdMenu, self).Insert(pos, id_, text, helpstr, kind) + if use_bmp and kind == wx.ITEM_NORMAL: + self.SetItemBitmap(item) + return item + + def InsertAfter(self, item_id, id_, label=u'', helpstr=u'', + kind=wx.ITEM_NORMAL, use_bmp=True): + """Inserts the given item after the specified item id in + the menu. If the id cannot be found then the item will appended + to the end of the menu. + @param item_id: Menu ID to insert after + @param id_: New MenuItem ID + @keyword label: Menu Label + @keyword helpstr: Help String + @keyword kind: MenuItem type + @keyword use_bmp: try and set a bitmap if an appropriate one is + available in the ArtProvider + @return: the inserted menu item + + """ + pos = None + for item in xrange(self.GetMenuItemCount()): + mitem = self.FindItemByPosition(item) + if mitem.GetId() == item_id: + pos = item + break + if pos: + mitem = self.Insert(pos + 1, id_, label, helpstr, kind, use_bmp) + else: + mitem = self.Append(id_, label, helpstr, kind, use_bmp) + return mitem + + def InsertBefore(self, item_id, id_, label=u'', helpstr=u'', + kind=wx.ITEM_NORMAL, use_bmp=True): + """Inserts the given item before the specified item id in + the menu. If the id cannot be found then the item will appended + to the end of the menu. + @param item_id: Menu ID to insert new item before + @param id_: New MenuItem ID + @keyword label: Menu Label + @keyword helpstr: Help String + @keyword kind: MenuItem type + @keyword use_bmp: try and set a bitmap if an appropriate one is + available in the ArtProvider + @return: menu item that was inserted + + """ + pos = None + for item in xrange(self.GetMenuItemCount()): + mitem = self.FindItemByPosition(item) + if mitem.GetId() == item_id: + pos = item + break + if pos: + mitem = self.Insert(pos, id_, label, helpstr, kind, use_bmp) + else: + mitem = self.Append(id_, label, helpstr, kind, use_bmp) + return mitem + + def InsertAlpha(self, id_, label=u'', helpstr=u'', + kind=wx.ITEM_NORMAL, after=0, use_bmp=True): + """Attempts to insert the new menuitem into the menu + alphabetically. The optional parameter 'after' is used + specify an item id to start the alphabetical lookup after. + Otherwise the lookup begins from the first item in the menu. + @param id_: New MenuItem ID + @keyword label: Menu Label + @keyword helpstr: Help String + @keyword kind: MenuItem type + @keyword after: id of item to start alpha lookup after + @keyword use_bmp: try and set a bitmap if an appropriate one is + available in the ArtProvider + @return: menu item that was inserted + + """ + if after: + start = False + else: + start = True + last_ind = self.GetMenuItemCount() - 1 + pos = last_ind + for item in range(self.GetMenuItemCount()): + mitem = self.FindItemByPosition(item) + if mitem.IsSeparator(): + continue + + mlabel = mitem.GetItemLabel() + if after and mitem.GetId() == after: + start = True + continue + if after and not start: + continue + if label < mlabel: + pos = item + break + + l_item = self.FindItemByPosition(last_ind) + if pos == last_ind and (l_item.IsSeparator() or label > mlabel): + mitem = self.Append(id_, label, helpstr, kind, use_bmp) + else: + mitem = self.Insert(pos, id_, label, helpstr, kind, use_bmp) + return mitem + + def RemoveItemByName(self, name): + """Removes an item by the label. It will remove the first + item matching the given name in the menu, the matching is + case sensitive. The return value is the either the id of the + removed item or None if the item was not found. + @param name: name of item to remove + @return: id of removed item or None if not found + + """ + menu_id = None + for pos in range(self.GetMenuItemCount()): + item = self.FindItemByPosition(pos) + if name == item.GetLabel(): + menu_id = item.GetId() + self.Remove(menu_id) + break + return menu_id + + def SetItemBitmap(self, item): + """Sets the MenuItems bitmap by getting the id from the + artprovider if one exists. + @param item: item to set bitmap for + + """ + bmp = wx.ArtProvider.GetBitmap(str(item.GetId()), wx.ART_MENU) + if not bmp.IsNull(): + item.SetBitmap(bmp) + +#-----------------------------------------------------------------------------# + +class KeyBinder(object): + """Class for managing keybinding configurations""" + cprofile = None # Current Profile Name String + keyprofile = dict() # Active Profile (dict) + + def __init__(self): + """Create the KeyBinder object""" + super(KeyBinder, self).__init__() + + # Attributes + self.cache = ed_glob.CONFIG['CACHE_DIR'] # Resource Directory + + def GetBinding(self, item_id): + """Get the keybinding string for use in a menu + @param item_id: Menu Item Id + @return: string + + """ + rbind = self.GetRawBinding(item_id) + shortcut = u'' + if rbind is not None: + shortcut = u"+".join(rbind) + if len(shortcut): + shortcut = u"\t" + shortcut + return unicode(shortcut) + + @classmethod + def GetCurrentProfile(cls): + """Get the name of the currently set key profile if one exists + @param cls: Class Object + @return: string or None + + """ + return cls.cprofile + + @classmethod + def GetCurrentProfileDict(cls): + """Get the dictionary of keybindings + @param cls: Class Object + @return: dict + + """ + return cls.keyprofile + + @staticmethod + def GetKeyProfiles(): + """Get the list of available key profiles + @return: list of strings + + """ + recs = util.GetResourceFiles(u'cache', trim=True, get_all=False, + suffix='.ekeys', title=False) + if recs == -1: + recs = list() + + tmp = util.GetResourceFiles(u'ekeys', True, True, '.ekeys', False) + if tmp != -1: + recs.extend(tmp) + + return recs + + def GetProfilePath(self, pname): + """Get the full path to the given keyprofile + @param pname: profile name + @return: string or None + @note: expects unique name for each profile in the case that + a name exists in both the user and system paths the one + found on the user path will be returned. + + """ + if pname is None: + return None + + rname = None + for rec in self.GetKeyProfiles(): + if rec.lower() == pname.lower(): + rname = rec + break + + # Must be a new profile + if rname is None: + rname = pname + + kprof = u"%s%s.ekeys" % (ed_glob.CONFIG['CACHE_DIR'], rname) + if not os.path.exists(kprof): + # Must be a system supplied keyprofile + rname = u"%s%s.ekeys" % (ed_glob.CONFIG['KEYPROF_DIR'], rname) + if not os.path.exists(rname): + # Doesn't exist at syspath either so instead assume it is a new + # custom user defined key profile. + rname = kprof + else: + rname = kprof + + return rname + + @classmethod + def GetRawBinding(cls, item_id): + """Get the raw key binding tuple + @param cls: Class Object + @param item_id: MenuItem Id + @return: tuple + + """ + return cls.keyprofile.get(item_id, None) + + @classmethod + def FindMenuId(cls, keyb): + """Find the menu item ID that the + keybinding is currently associated with. + @param cls: Class Object + @param keyb: tuple of unicode (u'Ctrl', u'C') + @return: int (-1 if not found) + + """ + menu_id = -1 + for key, val in cls.keyprofile.iteritems(): + if val == keyb: + menu_id = key + break + return menu_id + + @classmethod + def LoadDefaults(cls): + """Load the default key profile""" + cls.keyprofile = dict(_DEFAULT_BINDING) + cls.cprofile = None + + def LoadKeyProfile(self, pname): + """Load a key profile from profile directory into the binder + by name. + @param pname: name of key profile to load + + """ + if pname is None: + ppath = None + else: + ppath = self.GetProfilePath(pname) + self.LoadKeyProfileFile(ppath) + + def LoadKeyProfileFile(self, path): + """Load a key profile from the given path + @param path: full path to file + + """ + keydict = dict() + pname = None + if path: + pname = os.path.basename(path) + pname = pname.rsplit('.', 1)[0] + + if pname is not None and os.path.exists(path): + reader = util.GetFileReader(path) + if reader != -1: + util.Log("[keybinder][info] Loading KeyProfile: %s" % path) + for line in reader: + parts = line.split(u'=', 1) + # Check that the line was formatted properly + if len(parts) == 2: + # Try to find the ID value + item_id = _GetValueFromStr(parts[0]) + if item_id is not None: + tmp = [ part.strip() + for part in parts[1].split(u'+') + if len(part.strip()) ] + + # Do some checking if the binding is valid + nctrl = len([key for key in tmp + if key not in (u'Ctrl', u'Alt', u'Shift')]) + if nctrl: + if parts[1].strip().endswith(u'++'): + tmp.append(u'+') + kb = tuple(tmp) + if kb in keydict.values(): + for mid, b in keydict.iteritems(): + if kb == b: + del keydict[mid] + break + keydict[item_id] = tuple(tmp) + else: + # Invalid key binding + continue + + reader.close() + KeyBinder.keyprofile = keydict + KeyBinder.cprofile = pname + return + else: + util.Log("[keybinder][err] Couldn't read %s" % path) + elif pname is not None: + # Fallback to default keybindings + util.Log("[keybinder][err] Failed to load bindings from %s" % pname) + + util.Log("[keybinder][info] Loading Default Keybindings") + KeyBinder.LoadDefaults() + + def SaveKeyProfile(self): + """Save the current key profile to disk""" + if KeyBinder.cprofile is None: + util.Log("[keybinder][warn] No keyprofile is set, cant save") + else: + ppath = self.GetProfilePath(KeyBinder.cprofile) + writer = util.GetFileWriter(ppath) + if writer != -1: + itemlst = list() + for item in KeyBinder.keyprofile.keys(): + itemlst.append(u"%s=%s%s" % (_FindStringRep(item), + self.GetBinding(item).lstrip(), + os.linesep)) + writer.writelines(sorted(itemlst)) + writer.close() + else: + util.Log("[keybinder][err] Failed to open %s for writing" % ppath) + + @classmethod + def SetBinding(cls, item_id, keys): + """Set the keybinding of a menu id + @param cls: Class Object + @param item_id: item to set + @param keys: string or list of key strings ['Ctrl', 'S'] + + """ + if isinstance(keys, basestring): + keys = [ key.strip() for key in keys.split(u'+') + if len(key.strip())] + keys = tuple(keys) + + if len(keys): + # Check for an existing binding + menu_id = cls.FindMenuId(keys) + if menu_id != -1: + del cls.keyprofile[menu_id] + # Set the binding + cls.keyprofile[item_id] = keys + elif item_id in cls.keyprofile: + # Clear the binding + del cls.keyprofile[item_id] + else: + pass + + @classmethod + def SetProfileName(cls, pname): + """Set the name of the current profile + @param cls: Class Object + @param pname: name to set profile to + + """ + cls.cprofile = pname + + @classmethod + def SetProfileDict(cls, keyprofile): + """Set the keyprofile using a dictionary of id => bindings + @param cls: Class Object + @param keyprofile: { menu_id : (u'Ctrl', u'C'), } + + """ + cls.keyprofile = keyprofile + +#-----------------------------------------------------------------------------# + +class EdMenuBar(wx.MenuBar): + """Custom menubar to allow for easier access and updating + of menu components. + @todo: redo all of this + + """ + keybinder = KeyBinder() + + def __init__(self, style=0): + """Initializes the Menubar + @keyword style: style to set for menu bar + + """ + super(EdMenuBar, self).__init__(style) + + # Setup + if EdMenuBar.keybinder.GetCurrentProfile() is None: + kprof = profiler.Profile_Get('KEY_PROFILE', default='default') + EdMenuBar.keybinder.LoadKeyProfile(kprof) + + # Attributes + self._menus = dict() + self.GenFileMenu() + self.GenEditMenu() + self.GenViewMenu() + self.GenFormatMenu() + self.GenSettingsMenu() + self.GenToolsMenu() + self.GenHelpMenu() + + # Message handlers + ed_msg.Subscribe(self.OnRebind, ed_msg.EDMSG_MENU_REBIND) + ed_msg.Subscribe(self.OnLoadProfile, ed_msg.EDMSG_MENU_LOADPROFILE) + ed_msg.Subscribe(self.OnCreateLexerMenu, ed_msg.EDMSG_CREATE_LEXER_MENU) + + def GenLexerMenu(self): + """Create the Lexer menu""" + settingsmenu = self._menus['settings'] + item = settingsmenu.FindItemById(ed_glob.ID_LEXER) + if item: + settingsmenu.Remove(ed_glob.ID_LEXER) + + # Create the menu + langmenu = wx.Menu() + langmenu.Append(ed_glob.ID_LEXER_CUSTOM, _("Customize..."), + _("Customize the items shown in this menu.")) + langmenu.AppendSeparator() + EdMenuBar.PopulateLexerMenu(langmenu) + settingsmenu.AppendMenu(ed_glob.ID_LEXER, _("Lexers"), + langmenu, + _("Manually Set a Lexer/Syntax")) + + @staticmethod + def PopulateLexerMenu(langmenu): + """Create a menu with all the lexer options + @return: wx.Menu + + """ + mconfig = profiler.Profile_Get('LEXERMENU', default=list()) + mconfig.sort() + for label in mconfig: + lid = synglob.GetIdFromDescription(label) + langmenu.Append(lid, label, + _("Switch Lexer to %s") % label, wx.ITEM_CHECK) + + @classmethod + def DeleteKeyProfile(cls, pname): + """Remove named keyprofile + @param cls: Class Object + @param pname: keyprofile name + @return: True if removed, False otherwise + + """ + ppath = cls.keybinder.GetProfilePath(pname) + if ppath is not None and os.path.exists(ppath): + try: + os.remove(ppath) + except: + return False + else: + return True + else: + return False + + # TODO these Gen* functions should be broken up to the components + # that supply the functionality and inserted in the menus on + # init when the editor loads an associated widget. + def GenFileMenu(self): + """Makes and attaches the file menu + @return: None + + """ + filemenu = EdMenu() + filehist = self._menus['filehistory'] = EdMenu() + filemenu.AppendEx(ed_glob.ID_NEW, _("&New Tab"), + _("Start a new file in a new tab")) + filemenu.AppendEx(ed_glob.ID_NEW_WINDOW, _("New &Window"), + _("Start a new file in a new window")) + filemenu.AppendSeparator() + filemenu.AppendEx(ed_glob.ID_OPEN, _("&Open"), _("Open")) + ## Setup File History in the File Menu + filemenu.AppendMenu(ed_glob.ID_FHIST, _("Open &Recent"), + filehist, _("Recently Opened Files")) + filemenu.AppendSeparator() + filemenu.AppendEx(ed_glob.ID_CLOSE, _("&Close Tab"), + _("Close Current Tab")) + filemenu.AppendEx(ed_glob.ID_CLOSE_WINDOW, + _("Close Window") , _("Close the current window")) + filemenu.AppendEx(ed_glob.ID_CLOSEALL, _("Close All Tabs"), + _("Close all open tabs")) + filemenu.AppendSeparator() + filemenu.AppendEx(ed_glob.ID_SAVE, _("&Save"), _("Save Current File")) + filemenu.AppendEx(ed_glob.ID_SAVEAS, _("Save &As"), _("Save As")) + filemenu.AppendEx(ed_glob.ID_SAVEALL, _("Save All"), + _("Save all open pages")) + filemenu.AppendSeparator() + filemenu.AppendEx(ed_glob.ID_REVERT_FILE, _("Revert to Saved"), + _("Revert file to last save point")) + filemenu.AppendEx(ed_glob.ID_RELOAD_ENC, _("Reload with Encoding..."), + _("Reload the file with a specified encoding")) + filemenu.AppendSeparator() + + # Profile + pmenu = EdMenu() + pmenu.AppendEx(ed_glob.ID_SAVE_PROFILE, _("Save Profile"), + _("Save Current Settings to a New Profile")) + pmenu.AppendEx(ed_glob.ID_LOAD_PROFILE, _("Load Profile"), + _("Load a Custom Profile")) + filemenu.AppendSubMenu(pmenu, _("Profile"), + _("Load and save custom Profiles")) + + # Sessions + smenu = EdMenu() + smenu.AppendEx(ed_glob.ID_SAVE_SESSION, _("Save Session"), + _("Save the current session.")) + smenu.AppendEx(ed_glob.ID_LOAD_SESSION, _("Load Session"), + _("Load a saved session.")) + filemenu.AppendSubMenu(smenu, _("Sessions"), + _("Load and save custom sessions.")) + + filemenu.AppendSeparator() + filemenu.AppendEx(ed_glob.ID_PRINT_SU, _("Page Set&up"), + _("Configure Printer")) + filemenu.AppendEx(ed_glob.ID_PRINT_PRE, _("Print Pre&view"), + _("Preview Printout")) + filemenu.AppendEx(ed_glob.ID_PRINT, _("&Print"), _("Print Current File")) + filemenu.AppendSeparator() + filemenu.AppendEx(ed_glob.ID_EXIT, _("E&xit"), _("Exit the Program")) + + # Attach to menubar and save reference + self.Append(filemenu, _("&File")) + self._menus['file'] = filemenu + + def GenEditMenu(self): + """Makes and attaches the edit menu + @return: None + + """ + editmenu = EdMenu() + editmenu.AppendEx(ed_glob.ID_UNDO, _("&Undo"), _("Undo Last Action")) + editmenu.AppendEx(ed_glob.ID_REDO, _("Redo"), _("Redo Last Undo")) + editmenu.AppendSeparator() + editmenu.AppendEx(ed_glob.ID_CUT, _("Cu&t"), + _("Cut Selected Text from File")) + editmenu.AppendEx(ed_glob.ID_COPY, _("&Copy"), + _("Copy Selected Text to Clipboard")) + editmenu.AppendEx(ed_glob.ID_PASTE, _("&Paste"), + _("Paste Text from Clipboard to File")) + editmenu.AppendEx(ed_glob.ID_PASTE_AFTER, _("P&aste After"), + _("Paste Text from Clipboard to File after the cursor")) + editmenu.AppendEx(ed_glob.ID_CYCLE_CLIPBOARD, _("Cycle Clipboard"), + _("Cycle through recent clipboard text")) + editmenu.AppendSeparator() + editmenu.AppendEx(ed_glob.ID_SELECTALL, _("Select &All"), + _("Select All Text in Document")) + editmenu.AppendEx(ed_glob.ID_COLUMN_MODE, _("Column Edit"), + _("Enable column edit mode."), wx.ITEM_CHECK) + editmenu.AppendSeparator() + linemenu = EdMenu() + linemenu.AppendEx(ed_glob.ID_LINE_AFTER, _("New Line After"), + _("Add a new line after the current line")) + linemenu.AppendEx(ed_glob.ID_LINE_BEFORE, _("New Line Before"), + _("Add a new line before the current line")) + linemenu.AppendSeparator() + linemenu.AppendEx(ed_glob.ID_CUT_LINE, _("Cut Line"), + _("Cut Current Line")) + linemenu.AppendEx(ed_glob.ID_DELETE_LINE, _("Delete Line"), + _("Delete the selected line(s)")) + linemenu.AppendEx(ed_glob.ID_COPY_LINE, _("Copy Line"), + _("Copy Current Line")) + linemenu.AppendEx(ed_glob.ID_DUP_LINE, _("Duplicate Line"), + _("Duplicate the current line")) + linemenu.AppendSeparator() + linemenu.AppendEx(ed_glob.ID_JOIN_LINES, _("Join Lines"), + _("Join the Selected Lines")) + linemenu.AppendEx(ed_glob.ID_TRANSPOSE, _("Transpose Line"), + _("Transpose the current line with the previous one")) + linemenu.AppendEx(ed_glob.ID_LINE_MOVE_UP, _("Move Current Line Up"), + _("Move the current line up")) + linemenu.AppendEx(ed_glob.ID_LINE_MOVE_DOWN, + _("Move Current Line Down"), + _("Move the current line down")) + editmenu.AppendMenu(ed_glob.ID_LINE_EDIT, _("Line Edit"), linemenu, + _("Commands that affect an entire line")) + bookmenu = EdMenu() + bookmenu.AppendEx(ed_glob.ID_ADD_BM, _("Toggle Bookmark"), + _("Toggle bookmark of the current line")) + bookmenu.AppendEx(ed_glob.ID_DEL_ALL_BM, _("Remove All Bookmarks"), + _("Remove all bookmarks from the current document")) + editmenu.AppendMenu(ed_glob.ID_BOOKMARK, _("Bookmarks"), bookmenu, + _("Add and remove bookmarks")) + editmenu.AppendSeparator() + # Autocompletion shortcuts + editmenu.AppendEx(ed_glob.ID_SHOW_AUTOCOMP, _("Word Completion"), + _("Show autocompletion hints.")) + editmenu.AppendEx(ed_glob.ID_SHOW_CALLTIP, _("Show Calltip"), + _("Show a calltip for the current word.")) + editmenu.AppendSeparator() + editmenu.AppendEx(ed_glob.ID_FIND, _("&Find"), _("Find Text")) + editmenu.AppendEx(ed_glob.ID_FIND_REPLACE, _("Find/R&eplace"), + _("Find and Replace Text")) + editmenu.AppendEx(ed_glob.ID_QUICK_FIND, _("&Quick Find"), + _("Open the Quick Find Bar")) + editmenu.AppendEx(ed_glob.ID_FIND_PREVIOUS, _("Find Previous"), + _("Goto previous match")) + editmenu.AppendEx(ed_glob.ID_FIND_NEXT, _("Find Next"), + _("Goto the next match")) + editmenu.AppendEx(ed_glob.ID_FIND_SELECTED, _("Find Selected"), + _("Search for the currently selected phrase")) + editmenu.AppendSeparator() + editmenu.AppendEx(ed_glob.ID_PREF, _("Pr&eferences"), + _("Edit Preferences / Settings")) + + # Attach to menubar and save ref + self.Append(editmenu, _("&Edit")) + self._menus['edit'] = editmenu + + def GenViewMenu(self): + """Makes and attaches the view menu + @return: None + + """ + viewmenu = EdMenu() + viewmenu.AppendEx(ed_glob.ID_ZOOM_OUT, _("Zoom Out"), _("Zoom Out")) + viewmenu.AppendEx(ed_glob.ID_ZOOM_IN, _("Zoom In"), _("Zoom In")) + viewmenu.AppendEx(ed_glob.ID_ZOOM_NORMAL, _("Zoom Default"), + _("Zoom Default")) + viewmenu.AppendSeparator() + viewedit = self._menus['viewedit'] = EdMenu() + viewedit.AppendEx(ed_glob.ID_HLCARET_LINE, _("Highlight Caret Line"), + _("Highlight the background of the current line"), + wx.ITEM_CHECK) + viewedit.AppendEx(ed_glob.ID_INDENT_GUIDES, _("Indentation Guides"), + _("Show Indentation Guides"), wx.ITEM_CHECK) + viewedit.AppendEx(ed_glob.ID_SHOW_EDGE, _("Show Edge Guide"), + _("Show the edge column guide"), wx.ITEM_CHECK) + viewedit.AppendEx(ed_glob.ID_SHOW_EOL, _("Show EOL Markers"), + _("Show EOL Markers"), wx.ITEM_CHECK) + viewedit.AppendEx(ed_glob.ID_SHOW_LN, _("Show Line Numbers"), + _("Show Line Number Margin"), wx.ITEM_CHECK) + viewedit.AppendEx(ed_glob.ID_SHOW_WS, _("Show Whitespace"), + _("Show Whitespace Markers"), wx.ITEM_CHECK) + viewmenu.AppendSubMenu(self._menus['viewedit'], _("Editor"), \ + _("Toggle Editor View Options")) + viewfold = self._menus['viewfold'] = EdMenu() + viewfold.AppendEx(ed_glob.ID_TOGGLE_FOLD, _("Toggle fold"), + _("Toggle current fold")) + viewfold.AppendEx(ed_glob.ID_TOGGLE_ALL_FOLDS, _("Toggle all folds"), + _("Toggle all folds")) + viewmenu.AppendSubMenu(self._menus['viewfold'], _("Code Folding"), \ + _("Code folding toggle actions")) + + viewmenu.AppendSeparator() + viewmenu.AppendEx(ed_glob.ID_PANELIST, _("Pane Navigator"), + _("View pane selection list")) + viewmenu.AppendEx(ed_glob.ID_MAXIMIZE_EDITOR, _("Maximize Editor"), + _("Toggle Editor Maximization")) + viewmenu.AppendSeparator() + viewmenu.AppendEx(ed_glob.ID_GOTO_LINE, _("&Goto Line"), + _("Goto Line Number")) + viewmenu.AppendEx(ed_glob.ID_GOTO_MBRACE, _("Goto Matching Brace"), + _("Move caret matching brace")) + viewmenu.AppendSeparator() + viewmenu.AppendEx(ed_glob.ID_NEXT_POS, _("Next Position"), + _("Goto next position in history.")) + viewmenu.AppendEx(ed_glob.ID_PRE_POS, _("Previous Position"), + _("Goto previous position in history.")) + viewmenu.AppendSeparator() + viewmenu.AppendEx(ed_glob.ID_NEXT_MARK, _("Next Bookmark"), + _("View Line of Next Bookmark")) + viewmenu.AppendEx(ed_glob.ID_PRE_MARK, _("Previous Bookmark"), + _("View Line of Previous Bookmark")) + viewmenu.AppendSeparator() + viewmenu.AppendEx(ed_glob.ID_SHOW_SB, ("Status &Bar"), + _("Show Status Bar"), wx.ITEM_CHECK) + viewmenu.AppendEx(ed_glob.ID_VIEW_TOOL, _("&Toolbar"), + _("Show Toolbar"), wx.ITEM_CHECK) + + # Attach to menubar + self.Append(viewmenu, _("&View")) + self._menus['view'] = viewmenu + + def GenFormatMenu(self): + """Makes and attaches the format menu + @return: None + + """ + formatmenu = EdMenu() + formatmenu.AppendEx(ed_glob.ID_FONT, _("&Font"), + _("Change Font Settings")) + formatmenu.AppendSeparator() + formatmenu.AppendEx(ed_glob.ID_TOGGLECOMMENT, _("Toggle Comment"), + _("Toggle comment on the selected line(s)")) + formatmenu.AppendSeparator() + + formatmenu.AppendEx(ed_glob.ID_INDENT, _("Indent Lines"), + _("Indent the selected lines")) + formatmenu.AppendEx(ed_glob.ID_UNINDENT, _("Unindent Lines"), + _("Unindent the selected lines")) + formatmenu.AppendSeparator() + formatmenu.AppendEx(ed_glob.ID_TO_UPPER, _("Uppercase"), + _("Convert selected text to all uppercase letters")) + formatmenu.AppendEx(ed_glob.ID_TO_LOWER, _("Lowercase"), + _("Convert selected text to all lowercase letters")) + formatmenu.AppendSeparator() + formatmenu.AppendEx(ed_glob.ID_USE_SOFTTABS, _("Use Soft Tabs"), + _("Insert spaces instead of tab " + "characters with tab key"), wx.ITEM_CHECK) + formatmenu.AppendEx(ed_glob.ID_WORD_WRAP, _("Word Wrap"), + _("Wrap Text Horizontally"), wx.ITEM_CHECK) + formatmenu.AppendSeparator() + + # Whitespace submenu + whitespace = self._menus['whitespaceformat'] = EdMenu() + whitespace.AppendEx(ed_glob.ID_SPACE_TO_TAB, _("Spaces to Tabs"), + _("Convert spaces to tabs in selected/all text")) + whitespace.AppendEx(ed_glob.ID_TAB_TO_SPACE, _("Tabs to Spaces"), + _("Convert tabs to spaces in selected/all text")) + whitespace.AppendEx(ed_glob.ID_TRIM_WS, _("Trim Trailing Whitespace"), + _("Remove trailing whitespace")) + formatmenu.AppendMenu(ed_glob.ID_WS_FORMAT, _("Whitespace"), whitespace, + _("Whitespace formating commands")) + + # Line EOL formatting submenu + lineformat = self._menus['lineformat'] = EdMenu() + lineformat.AppendEx(ed_glob.ID_EOL_MAC, _("Old Macintosh (\\r)"), + _("Format all EOL characters to %s Mode") % \ + _(u"Old Macintosh (\\r)"), wx.ITEM_CHECK) + lineformat.AppendEx(ed_glob.ID_EOL_UNIX, _("Unix (\\n)"), + _("Format all EOL characters to %s Mode") % \ + _(u"Unix (\\n)"), wx.ITEM_CHECK) + lineformat.AppendEx(ed_glob.ID_EOL_WIN, _("Windows (\\r\\n)"), + _("Format all EOL characters to %s Mode") % \ + _("Windows (\\r\\n)"), wx.ITEM_CHECK) + formatmenu.AppendMenu(ed_glob.ID_EOL_MODE, _("EOL Mode"), lineformat, + _("End of line character formatting")) + + # Attach to menubar + self.Append(formatmenu, _("F&ormat")) + self._menus['format'] = formatmenu + + def GenSettingsMenu(self): + """Makes and attaches the settings menu + @return: None + + """ + settingsmenu = EdMenu() + settingsmenu.AppendEx(ed_glob.ID_AUTOCOMP, _("Auto-Completion"), + _("Use Auto Completion when available"), wx.ITEM_CHECK) + settingsmenu.AppendEx(ed_glob.ID_AUTOINDENT, _("Auto-Indent"), + _("Toggle Auto-Indentation functionality"), + wx.ITEM_CHECK) + settingsmenu.AppendEx(ed_glob.ID_BRACKETHL, _("Bracket Highlighting"), + _("Highlight Brackets/Braces"), wx.ITEM_CHECK) + settingsmenu.AppendEx(ed_glob.ID_FOLDING, _("Code Folding"), + _("Toggle Code Folding"), wx.ITEM_CHECK) + settingsmenu.AppendEx(ed_glob.ID_SYNTAX, _("Syntax Highlighting"), + _("Color Highlight Code Syntax"), wx.ITEM_CHECK) + + settingsmenu.AppendSeparator() + + # Lexer Menu Appended later by main frame + self.Append(settingsmenu, _("&Settings")) + self._menus['settings'] = settingsmenu + + self.GenLexerMenu() + + def GenToolsMenu(self): + """Makes and attaches the tools menu + @return: None + + """ + toolsmenu = EdMenu() + toolsmenu.AppendEx(ed_glob.ID_COMMAND, _("Editor Command"), + _("Goto command buffer")) + toolsmenu.AppendEx(ed_glob.ID_SESSION_BAR, _("Session Manager"), + _("Show the session manager bar")) + toolsmenu.AppendEx(ed_glob.ID_PLUGMGR, _("Plugin Manager"), + _("Manage, Download, and Install plugins")) + toolsmenu.AppendEx(ed_glob.ID_STYLE_EDIT, _("Style Editor"), + _("Edit the way syntax is highlighted")) + toolsmenu.AppendSeparator() +# macro = EdMenu() +# macro.Append(ed_glob.ID_MACRO_START, _("Record Macro"), +# _("Start macro recording")) +# macro.Append(ed_glob.ID_MACRO_STOP, _("Stop Recording"), +# _("Stop macro recording")) +# macro.Append(ed_glob.ID_MACRO_PLAY, "Play Macro", "Play Macro") +# toolsmenu.AppendMenu(wx.NewId(), _("Macros"), macro, _("Macro Tools")) + + # Attach to menubar + self.Append(toolsmenu, _("&Tools")) + self._menus['tools'] = toolsmenu + + def GenHelpMenu(self): + """Makes and attaches the help menu + @return: None + + """ + helpmenu = EdMenu() + helpmenu.AppendEx(ed_glob.ID_ABOUT, _("&About..."), + _("About") + u"...") + helpmenu.AppendEx(ed_glob.ID_HOMEPAGE, _("Project Homepage..."), + _("Visit the project homepage %s") % ed_glob.HOME_PAGE) + helpmenu.AppendEx(ed_glob.ID_DOCUMENTATION, + _("Online Documentation..."), + _("Online project documentation and help guides")) + helpmenu.AppendEx(ed_glob.ID_TRANSLATE, _("Translate Editra..."), + _("Editra translations project")) + helpmenu.AppendEx(ed_glob.ID_BUG_TRACKER, _("Bug Tracker...")) + helpmenu.AppendEx(ed_glob.ID_CONTACT, _("Feedback"), + _("Send bug reports and suggestions")) + + # Attach to menubar + self.Append(helpmenu, _("&Help")) + self._menus['help'] = helpmenu + + @classmethod + def GetKeyBinder(cls): + """Return the classes keybinder object + @param cls: Class Object + @return: KeyBinder + + """ + return cls.keybinder + + def GetMenuByName(self, namestr): + """Find and return a menu by name + @param namestr: menuitems label + @return: menuitem or None if not found + + """ + return self._menus.get(namestr.lower(), None) + + def GetMenuMap(self): + """Get a mapping of all menus to (menu id, menu label) + @return: list of dict + + """ + menumap = list() + for menu in self.GetMenus(): + menumap.append(WalkMenu(menu[0], menu[1], dict())) + return menumap + + @classmethod + def NewKeyProfile(cls, pname): + """Make a new key profile that is a clone of the current one + @param cls: Class Object + @param pname: Name to give new profile + + """ + cls.keybinder.SetProfileName(pname) + cls.keybinder.SaveKeyProfile() + + def OnCreateLexerMenu(self, msg): + """Recreate the lexer menu""" + self.GenLexerMenu() + + def OnLoadProfile(self, msg): + """Load and set the current key profile + @param msg: ed_msg.EDMSG_MENU_LOADPROFILE + @note: if message data is None the default bindings will be set + + """ + keyprof = msg.GetData() + if keyprof is not None: + self.SetKeyProfile(keyprof) + else: + EdMenuBar.keybinder.LoadDefaults() + + def OnRebind(self, msg): + """Rebind all menu shortcuts when a rebind message is recieved + @param msg: ed_msg.EDMSG_MENU_REBIND + + """ + self.RebindKeys() + + def RebindKeys(self): + """Reset all key bindings based on current binder profile""" + for menu in self.GetMenus(): + for item in IterateMenuItems(menu[0]): + item_id = item.GetId() + binding = EdMenuBar.keybinder.GetBinding(item_id) + empty_binding = not len(binding) + if not empty_binding: + # Verify binding and clear invalid ones from binder + tmp = [key.title() for key in binding.strip().split(u'+')] + nctrl = len([key for key in tmp + if key not in (u'Ctrl', u'Alt', u'Shift')]) + if len(tmp) > 3 or not nctrl: + EdMenuBar.keybinder.SetBinding(item_id, u'') + continue + + # Reset the binding in the binder to ensure it is + # correctly formatted. + binding = u"\t" + u"+".join(tmp) + EdMenuBar.keybinder.SetBinding(item_id, binding) + + clbl = item.GetText() + # Update the item if the shortcut has changed + if ('\t' in clbl and (not clbl.endswith(binding) or empty_binding)) or \ + ('\t' not in clbl and not empty_binding): + # wxBug? Getting the text of a menuitem is supposed to + # return it with the accelerators but under gtk the string + # has underscores '_' where it was supposed to have '&' + if wx.Platform == '__WXGTK__': + clbl = clbl.replace('_', '&', 1) + item.SetText(clbl.split('\t')[0].strip() + binding) + + def ResetIcons(self): + """Walk through each menu item in all of the bars menu and + reapply icons where possible. + @note: Don't use, sort of works on mac, does nothing on gtk, and causes + graphical glitches on msw. + + """ + for menu in self.GetMenus(): + WalkAndSetBitmaps(menu[0]) + + @classmethod + def SaveKeyProfile(cls): + """Save the current key profile""" + cls.keybinder.SaveKeyProfile() + + def SetKeyProfile(self, pname): + """Set the current key profile and update the bindings + @param pname: Name of keyprofile to load + + """ + EdMenuBar.keybinder.LoadKeyProfile(pname) + self.RebindKeys() + +#-----------------------------------------------------------------------------# + +#---- Private Objects/Functions ----# + +_DEFAULT_BINDING = { # File Menu + ed_glob.ID_NEW : (u"Ctrl", u"N"), + ed_glob.ID_NEW_WINDOW : (u"Ctrl", u"Shift", u"N"), + ed_glob.ID_OPEN : (u"Ctrl", u"O"), + ed_glob.ID_CLOSE : (u"Ctrl", u"W"), + ed_glob.ID_CLOSE_WINDOW : (u"Ctrl", u"Shift", u"W"), + ed_glob.ID_SAVE : (u"Ctrl", u"S"), + ed_glob.ID_SAVEAS : (u"Ctrl", u"Shift", u"S"), + ed_glob.ID_PRINT_SU : (u"Ctrl", u"Shift", u"P"), + ed_glob.ID_PRINT : (u"Ctrl", u"P"), + ed_glob.ID_EXIT : (u"Ctrl", u"Q"), + + # Edit Menu + ed_glob.ID_UNDO : (u"Ctrl", u"Z"), + ed_glob.ID_REDO : (u"Ctrl", u"Shift", u"Z"), + ed_glob.ID_CUT : (u"Ctrl", u"X"), + ed_glob.ID_COPY : (u"Ctrl", u"C"), + ed_glob.ID_PASTE : (u"Ctrl", u"V"), + ed_glob.ID_PASTE_AFTER : (u"Ctrl", u"Shift", u"V"), + ed_glob.ID_CYCLE_CLIPBOARD : (u"Ctrl", u"I"), + ed_glob.ID_SELECTALL : (u"Ctrl", u"A"), + ed_glob.ID_COLUMN_MODE : (u"Ctrl", u"Shift", u"|"), + ed_glob.ID_LINE_AFTER : (u"Ctrl", u"L"), + ed_glob.ID_LINE_BEFORE : (u"Ctrl", u"Shift", u"L"), + ed_glob.ID_CUT_LINE : (u"Ctrl", u"D"), + ed_glob.ID_DELETE_LINE : (u"Ctrl", u"Shift", "D"), + ed_glob.ID_COPY_LINE : (u"Ctrl", u"Y"), + ed_glob.ID_DUP_LINE : (u"Ctrl", u"Shift", u"C"), + ed_glob.ID_JOIN_LINES : (u"Ctrl", u"J"), + ed_glob.ID_TRANSPOSE : (u"Ctrl", u"T"), + ed_glob.ID_LINE_MOVE_UP : (u"Ctrl", u"Shift", u"Up"), + ed_glob.ID_LINE_MOVE_DOWN : (u"Ctrl", u"Shift", u"Down"), + ed_glob.ID_ADD_BM : (u"Ctrl", u"B"), + ed_glob.ID_SHOW_AUTOCOMP : (u"Ctrl", u"Space"), + ed_glob.ID_SHOW_CALLTIP : (u"Ctrl", u"9"), + ed_glob.ID_FIND : (u"Ctrl", u"Shift", u"F"), + ed_glob.ID_FIND_PREVIOUS : (u"Shift", u"F3"), + ed_glob.ID_FIND_NEXT : (u"F3",), + ed_glob.ID_FIND_REPLACE : (u"Ctrl", u"R"), + ed_glob.ID_QUICK_FIND : (u"Ctrl", u"F"), + ed_glob.ID_FIND_SELECTED : (u"Ctrl", u"F3"), + + # View Menu + ed_glob.ID_ZOOM_IN : (u"Ctrl", u"+"), + ed_glob.ID_ZOOM_OUT : (u"Ctrl", u"-"), + ed_glob.ID_ZOOM_NORMAL : (u"Ctrl", u"0"), + ed_glob.ID_GOTO_LINE : (u"Ctrl", u"G"), + ed_glob.ID_GOTO_MBRACE : (u"Ctrl", u"Shift", u"B"), + ed_glob.ID_TOGGLE_FOLD : (u"Ctrl", u"Shift", u"T"), + ed_glob.ID_NEXT_POS : (u"Ctrl", u"Shift", u">"), + ed_glob.ID_PRE_POS : (u"Ctrl", u"Shift", u"<"), + ed_glob.ID_NEXT_MARK : (u"Alt", u"Right"), # Win/Linux + ed_glob.ID_PRE_MARK : (u"Alt", u"Left"), # Win/Linux + ed_glob.ID_SHOW_SHELF : (u"Ctrl", u"Alt", u"S"), + ed_glob.ID_PANELIST : (u"Alt", u"1"), # Win/Linux + ed_glob.ID_MAXIMIZE_EDITOR : (u"Ctrl", u"M"), + + # Format Menu + ed_glob.ID_TOGGLECOMMENT : (u"Ctrl", u"1"), + ed_glob.ID_INDENT : (u"Tab",), + ed_glob.ID_UNINDENT : (u"Shift", u"Tab"), + ed_glob.ID_USE_SOFTTABS : (u"Ctrl", u"Shift", u"I"), + + # Tools Menu + ed_glob.ID_COMMAND : (u"Ctrl", u"E"), + ed_glob.ID_SESSION_BAR : (u"Ctrl", u"K"), + ed_glob.ID_RUN_LAUNCH : (u"F5",), + ed_glob.ID_LAUNCH_LAST : (u"Shift", u"F5") + } + +# Set some platform specific keybindings +if wx.Platform == '__WXMAC__': + _DEFAULT_BINDING[ed_glob.ID_NEXT_MARK] = (u"Ctrl", u"Down") + _DEFAULT_BINDING[ed_glob.ID_PRE_MARK] = (u"Ctrl", u"Up") + _DEFAULT_BINDING[ed_glob.ID_FIND_PREVIOUS] = (u"Ctrl", u"Shift", u"G") + _DEFAULT_BINDING[ed_glob.ID_FIND_NEXT] = (u"Ctrl", u"G") + _DEFAULT_BINDING[ed_glob.ID_GOTO_LINE] = (u"Ctrl", u"Shift", u"E") + _DEFAULT_BINDING[ed_glob.ID_PANELIST] = (u"Alt", u"Tab") + _DEFAULT_BINDING[ed_glob.ID_MAXIMIZE_EDITOR] = (u"Alt", u"M") + _DEFAULT_BINDING[ed_glob.ID_FIND_SELECTED] = (u"Ctrl", u"3") +elif wx.Platform == '__WXMSW__': + # FIXME: On Windows if Tab is bound to a menu item it is no longer + # usable elsewhere such as in the stc control. On Mac/Gtk there + # are not problems with it. + _DEFAULT_BINDING[ed_glob.ID_INDENT] = (u"",) +else: + pass + +def _FindStringRep(item_id): + """Find the string representation of the given id value + @param item_id: int + @return: string or None + + """ + for obj in dir(ed_glob): + if getattr(ed_glob, obj) == item_id: + return obj + else: + return None + +def _GetValueFromStr(item_str): + """Get the id value from the string representation of the object + @param item_str: items variable string + @return: int or None + + """ + return getattr(ed_glob, item_str, None) + +#---- Public Functions ----# + +def IterateMenuItems(menu): + """Recursively walk and yield menu items as the are found. Only menu + items are yielded, not submenus or separators. + @param menu: menu to iterate + + """ + for item in menu.GetMenuItems(): + if item.IsSubMenu(): + for subitem in IterateMenuItems(item.GetSubMenu()): + yield subitem + if not item.IsSeparator(): + yield item + else: + continue + +def WalkAndSetBitmaps(menu): + """Recursively walk a menu and its submenus setting bitmaps + as necessary/available, using the the current theme. + + """ + for item in menu.GetMenuItems(): + if item.IsSubMenu(): + WalkAndSetBitmaps(item.GetSubMenu()) + else: + bmp = wx.ArtProvider.GetBitmap(str(item.GetId()), wx.ART_MENU) + if bmp.IsOk(): + item.SetBitmap(bmp) + elif not item.GetBitmap().IsNull(): + item.SetBitmap(wx.NullBitmap) + else: + continue + +def WalkMenu(menu, label, collection): + """Recursively walk a menu and collect all its sub items + @param menu: wxMenu to walk + @param label: the menu's label + @param collection: dictionary to collect results in + @return: dict {menulabel : [menu id, (item1 id, label1),]} + + """ + if label not in collection: + collection[label] = list() + + for item in menu.GetMenuItems(): + i_id = item.GetId() + if item.IsSubMenu(): + # Ignore dynamically generated menus + if i_id not in (ed_glob.ID_FHIST, ed_glob.ID_LEXER, + ed_glob.ID_PERSPECTIVES): + ilbl = item.GetItemLabelText() + collection[ilbl] = [i_id, ] + WalkMenu(item.GetSubMenu(), ilbl, collection) + else: + continue + elif item.IsSeparator(): + continue + elif _FindStringRep(i_id) is not None: + lbl = item.GetItemLabelText().split('\t')[0].strip() + # wxBug? Even the methods that are supposed to return the text + # without mnemonics or accelerators on gtk return the string with + # underscores where the mnemonics '&' are in the original strings + if wx.Platform == '__WXGTK__': + lbl = lbl.replace('_', '', 1) + collection[label].append((i_id, lbl)) + else: + continue + return collection diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mpane.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mpane.py new file mode 100644 index 0000000..2e27c90 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_mpane.py @@ -0,0 +1,100 @@ +############################################################################### +# Name: ed_mpane.py # +# Purpose: Main panel containing notebook and command bar. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module provides the L{MainPanel} component. That contains the editors main +notebook and command bar. + +@summary: Main Panel + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_mpane.py 72278 2012-08-02 14:24:23Z CJP $" +__revision__ = "$Revision: 72278 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx + +# Editra Libraries +import ed_glob +import ed_pages +import ed_cmdbar +import eclib + +#-----------------------------------------------------------------------------# + +class MainPanel(eclib.ControlBox): + """Main panel view + @todo: Add interface for registering additional commandbars. + + """ + def __init__(self, parent): + """Initialize the panel""" + super(MainPanel, self).__init__(parent) + + # Attributes + self.nb = ed_pages.EdPages(self) + self._bars = dict() + + # Layout + self.SetWindow(self.nb) + + self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEB) + + def OnEB(self, evt): + """Empty method to fix notebook flashing issue on MSW""" + pass + + Book = property(lambda self: self.nb) + + def GetNotebook(self): + """Get the main notebook control + @return: EdPages instance + + """ + return self.nb + + def HideCommandBar(self): + """Hide the command bar""" + bar = self.GetControlBar(wx.BOTTOM) + if bar: + bar.Hide() + self.Layout() + + def ShowCommandControl(self, ctrlid): + """Change the mode of the commandbar + @param ctrlid: CommandBar control id + + """ + cur_bar = self.GetControlBar(wx.BOTTOM) + if ctrlid in self._bars: + nbar = self._bars[ctrlid] + else: + nbar = ed_cmdbar.CommandBarBase.FactoryCreate(ctrlid, self) + if nbar: + self._bars[ctrlid] = nbar + + if nbar and nbar is not cur_bar: + if cur_bar is None: + self.SetControlBar(nbar, wx.BOTTOM) + else: + cur_bar = self.ReplaceControlBar(nbar, wx.BOTTOM) + + if cur_bar: + if cur_bar is not nbar: + cur_bar.Hide() + + cbar = self.GetControlBar(wx.BOTTOM) + if cbar is not None: + cbar.Show() + cbar.Layout() + cbar.SetFocus() + + self.Layout() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_msg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_msg.py new file mode 100644 index 0000000..a59c119 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_msg.py @@ -0,0 +1,496 @@ +############################################################################### +# Name: ed_msg.py # +# Purpose: Provide a messaging/notification system for actions performed in # +# the editor. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module provides a light wrapping of a slightly modified pubsub module +to give it a lighter and simpler syntax for usage. It exports three main +methods. The first L{PostMessage} which is used to post a message for all +interested listeners. The second L{Subscribe} which allows an object to +subscribe its own listener function for a particular message type, all of +Editra's core message types are defined in this module using a naming +convention that starts each identifier with I{EDMSG_}. These identifier +constants can be used to identify the message type by comparing them with the +value of msg.GetType in a listener method. The third method is L{Unsubscribe} +which can be used to remove a listener from recieving messages. + +@summary: Message system api and message type definitions + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_msg.py 71697 2012-06-08 15:20:22Z CJP $" +__revision__ = "$Revision: 71697 $" + +__all__ = ['PostMessage', 'Subscribe', 'Unsubscribe'] + +#--------------------------------------------------------------------------# +# Imports +from wx import PyDeadObjectError +from extern.pubsub import Publisher + +#--------------------------------------------------------------------------# +# Message Type Definitions + +#---- General Messages ----# + +# Listen to all messages +EDMSG_ALL = ('editra',) + +#---- End General Messages ----# + +#---- Log Messages ----# +# Used internally by the log system. Listed by priority lowest -> highest +# All message data from these functions are a LogMsg object which is a +# container object for the message string / timestamp / type +# +# Using these message types with the PostMessage method is not suggested for +# use in user code instead use the logging facilities (wx.GetApp().GetLog() or +# util.Getlog() ) as they will handle the formatting that is expected by the +# log messaging listeners. + +# Recieve all log messages (i.e anything put on the logging system) +EDMSG_LOG_ALL = EDMSG_ALL + ('log',) + +# Recieve all messages that have been labled (info, events, warnings, errors) +EDMSG_LOG_INFO = EDMSG_LOG_ALL + ('info',) + +# Messages generated by ui events +EDMSG_LOG_EVENT = EDMSG_LOG_INFO + ('evt',) + +# Recieve only warning messages +EDMSG_LOG_WARN = EDMSG_LOG_INFO + ('warn',) + +# Recieve only error messages +EDMSG_LOG_ERROR = EDMSG_LOG_INFO + ('err',) + +#---- End Log Messages ----# + +#---- Configuration Messages ----# + +# These messages will be sent when there are configuration +# changes in the current user profile. Messages will be in +# the format of (editra,config,PROFILE_KEY) +# mdata == Profile[PROFILE_KEY] +EDMSG_PROFILE_CHANGE = EDMSG_ALL + ('config',) + +#---- End Configuration Messages ----# + +#---- File Action Messages ----# + +# Recieve notification of all file actions +EDMSG_FILE_ALL = EDMSG_ALL + ('file',) + +# File open was just requested / msgdata == file path +EDMSG_FILE_OPENING = EDMSG_FILE_ALL + ('opening',) + +# File was just opened / msgdata == file path +# context == MainWindows ID +EDMSG_FILE_OPENED = EDMSG_FILE_ALL + ('opened',) + +# Get a list of all opened files +# msgdata == list of file paths (out param) +EDMSG_FILE_GET_OPENED = EDMSG_FILE_ALL + ('allopened',) + +# TODO: using MainWindow as context for now, but may make more sense to use +# the buffer instead. + +# File save requested / msgdata == (filename, filetypeId) +# context == MainWindows ID +# Note: All listeners of this message are processed *before* the save takes +# place. Meaning the listeners block the save action until they are +# finished. +EDMSG_FILE_SAVE = EDMSG_FILE_ALL + ('save',) + +# File just written to disk / msgdata == (filename, filetypeId) +# context == MainWindows ID +EDMSG_FILE_SAVED = EDMSG_FILE_ALL + ('saved',) + +#---- End File Action Messages ----# + +#---- UI Action Messages ----# + +# Recieve notification of all ui typed messages +EDMSG_UI_ALL = EDMSG_ALL + ('ui',) + +#- Receive all Main Notebook Messages +EDMSG_UI_NB = EDMSG_UI_ALL + ('mnotebook',) + +# MainWindow Activated +# msgdata == dict(active=bool) +# context = MainWindow ID +EDMSG_UI_MW_ACTIVATE = EDMSG_UI_ALL + ('mwactivate',) + +# Notebook page changing +# msgdata == (ref to notebook, +# index of previous selection, +# index of current selection) +# context == MainWindow ID +EDMSG_UI_NB_CHANGING = EDMSG_UI_NB + ('pgchanging',) + +# Notebook page changed +# msgdata == (ref to notebook, index of currently selected page) +# context == MainWindow ID +EDMSG_UI_NB_CHANGED = EDMSG_UI_NB + ('pgchanged',) + +# Page is about to close +# msgdata == (ref to notebook, index of page that is closing) +# context == MainWindow ID +EDMSG_UI_NB_CLOSING = EDMSG_UI_NB + ('pgclosing',) + +# Page has just been closed +# msgdata == (ref to notebook, index of page that is now selected) +# context == MainWindow ID +EDMSG_UI_NB_CLOSED = EDMSG_UI_NB + ('pgclosed',) + +# Tab Menu requested +# msgdata == ContextMenuManager +# menu = ContextMenuManager.GetMenu() +# ContextMenuManager.AddHandler(ID_MENU_ID, handler(buffer, event)) +# page = ContextMenuManager.GetUserData("page") +EDMSG_UI_NB_TABMENU = EDMSG_UI_NB + ('tabmenu',) + +# Post message to show the progress indicator of the MainWindow +# msgdata == (frame id, True / False) +EDMSG_PROGRESS_SHOW = EDMSG_UI_ALL + ('statbar', 'progbar', 'show') + +# Post this message to manipulate the state of the MainWindows status bar +# progress indicator. The message data should be a three tuple of the recipient +# frames id, current progress and the total range (current, total). If both +# values are 0 then the bar will be hidden. If both are negative the bar will +# be set into pulse mode. This message can safely be sent from background +# threads. +EDMSG_PROGRESS_STATE = EDMSG_UI_ALL + ('statbar', 'progbar', 'state') + +# Set the status text +# msgdata == (field id, text) +EDMSG_UI_SB_TXT = EDMSG_UI_ALL + ('statbar', 'text') + +## Text Buffer ## + +# Root message for the text buffer +EDMSG_UI_STC_ALL = EDMSG_UI_ALL + ('stc',) + +# msgdata == ((x, y), keycode) +# context == MainWindows ID +EDMSG_UI_STC_KEYUP = EDMSG_UI_STC_ALL + ('keyup',) + +# msgdata == dict(lnum=line, cnum=column) +# context == MainWindows ID +EDMSG_UI_STC_POS_CHANGED = EDMSG_UI_STC_ALL + ('position',) + +# msgdata == dict(fname=fname, +# prepos=pos, preline=line, +# lnum=cline, pos=cpos) +# context == MainWindow ID +EDMSG_UI_STC_POS_JUMPED = EDMSG_UI_STC_ALL + ('jump',) + +# Editor control size restored (msgdata == None) +EDMSG_UI_STC_RESTORE = EDMSG_UI_STC_ALL + ('restore',) + +# Lexer Changed +# msgdata == (filename, filetype id) +# context == MainWindows ID +EDMSG_UI_STC_LEXER = EDMSG_UI_STC_ALL + ('lexer',) + +# Buffer Changed +# NOTE: this gets called ALOT so be very efficient in any handlers of it! +# msgdata == None +EDMSG_UI_STC_CHANGED = EDMSG_UI_STC_ALL + ('changed',) + +# Customize Context Menu +# Add custom menu items and handlers to the buffers right click menu +# msgdata = ContextMenuManager +# ContextMenuManager.AddHandler(menu_id, handler) +# menu = ContextMenuManager.GetMenu() +# def handler(buffer, event_obj) +# ContextMenuManager.GetData('buffer') +EDMSG_UI_STC_CONTEXT_MENU = EDMSG_UI_STC_ALL + ('custommenu',) + +# UserList Selection +# msgdata == dict(ltype=int, text=string, stc=EditraStc) +EDMSG_UI_STC_USERLIST_SEL = EDMSG_UI_STC_ALL + ('userlistsel',) + +# Mouse Dwell Start +# mdata = dict(stc=self, pos=position, +# line=line_number, +# word=word_under_cursor +# rdata="") +# If the handler for this method wants to show a calltip +# it should set the rdata value +EDMSG_UI_STC_DWELL_START = EDMSG_UI_STC_ALL + ('dwellstart',) + +# Mouse Dwell End +# mdata = None +EDMSG_UI_STC_DWELL_END = EDMSG_UI_STC_ALL + ('dwellend',) + +# Bookmark (added/deleted) +# mdata = dict(stc=EditraStc, added=bool, line=line, handle=bookmarkhandle) +# NOTE: if line < 0, then all bookmarks removed +EDMSG_UI_STC_BOOKMARK = EDMSG_UI_STC_ALL + ('bookmark',) + +# Margin Click +# mdata = dict(stc=EditraStc, line=line, handled=bool) +# handled is an out param in the message data. Set to True +# to indicate that the click was handled. +EDMSG_UI_STC_MARGIN_CLICK = EDMSG_UI_STC_ALL + ('marginclick',) + +#---- End UI Action Messages ----# + +#---- Menu Messages ----# +EDMSG_MENU = EDMSG_ALL + ('menu',) + +# Signal to all windows to update keybindings (msgdata == None) +EDMSG_MENU_REBIND = EDMSG_MENU + ('rebind',) + +# Message to set key profile +# msgdata == keyprofile name +EDMSG_MENU_LOADPROFILE = EDMSG_MENU + ('load',) + +# Message to recreate the lexer menu +# msgdata == None +EDMSG_CREATE_LEXER_MENU = EDMSG_MENU + ('lexer',) + +#---- End Menu Messages ----# + +#---- Find Actions ----# + +EDMSG_FIND_ALL = EDMSG_ALL + ('find',) + +# Show or modify an existing find dialog +# msgdata = dict(mw, lookin, searchtxt, replacetxt) +EDMSG_FIND_SHOW_DLG = EDMSG_FIND_ALL + ('show',) + +# Message to request a search job +# msgdata == (callable, args, kwargs) +# msgdata == (callable) +EDMSG_START_SEARCH = EDMSG_FIND_ALL + ('results',) + +#---- End Find Actions ----# + +#---- Session Related Actions ----# + +# Root Session Message +EDMSG_SESSION_ALL = ('session',) + +# Initiate a Session Save to save current session under new name. +# Note: This invokes a UI action to prompt the user on what to name +# the session. DO NOT call from background threads. +# send(msgdata == None) | context - MainWindow +EDMSG_SESSION_DO_SAVE = EDMSG_SESSION_ALL + ('dosave',) + +# Initiate loading a session +# Causes all currently open files to be closed and the files from the +# specified session to be loaded. Not thread safe. +# send(msgdata == session_name) +EDMSG_SESSION_DO_LOAD = EDMSG_SESSION_ALL + ('doload',) + +#---- End Session Related Actions ----# + +#---- Misc Messages ----# +# Signal that the icon theme has changed. Respond to this to update icon +# resources from the ArtProvider. +EDMSG_THEME_CHANGED = EDMSG_ALL + ('theme',) # All theme listeners + +# Update the theme the notebook specifically to the current preferences +EDMSG_THEME_NOTEBOOK = EDMSG_ALL + ('nb', 'theme') + +# Signal that the font preferences for the ui have changed (msgdata == font) +EDMSG_DSP_FONT = EDMSG_ALL + ('dfont',) + +# Add file to file history +# msgdata == filename +EDMSG_ADD_FILE_HISTORY = EDMSG_ALL + ('filehistory',) + +#---- End Misc Messages ----# + +#--------------------------------------------------------------------------# +# Public Api +_ThePublisher = Publisher() + +def PostMessage(msgtype, msgdata=None, context=None): + """Post a message containing the msgdata to all listeners that are + interested in the given msgtype from the given context. If context + is None than default context is assumed. + Message is always propagated to the default context. + @param msgtype: Message Type EDMSG_* + @keyword msgdata: Message data to pass to listener (can be anything) + @keyword context: Context of the message. + + """ + _ThePublisher.sendMessage(msgtype, msgdata, context=context) + +def Subscribe(callback, msgtype=EDMSG_ALL): + """Subscribe your listener function to listen for an action of type msgtype. + The callback must be a function or a _bound_ method that accepts one + parameter for the actions message. The message that is sent to the callback + is a class object that has two attributes, one for the message type and the + other for the message data. See below example for how these two values can + be accessed. + >>> def MyCallback(msg): + print "Msg Type: ", msg.GetType(), "Msg Data: ", msg.GetData() + + >>> class Foo: + def MyCallbackMeth(self, msg): + print "Msg Type: ", msg.GetType(), "Msg Data: ", msg.GetData() + + >>> Subscribe(MyCallback, EDMSG_SOMETHING) + >>> myfoo = Foo() + >>> Subscribe(myfoo.MyCallBackMeth, EDMSG_SOMETHING) + + @param callback: Callable function or bound method + @keyword msgtype: Message to subscribe to (default to all) + + """ + _ThePublisher.subscribe(callback, msgtype) + +def Unsubscribe(callback, messages=None): + """Remove a listener so that it doesn't get sent messages for msgtype. If + msgtype is not specified the listener will be removed for all msgtypes that + it is associated with. + @param callback: Function or bound method to remove subscription for + @keyword messages: EDMSG_* val or list of EDMSG_* vals + + """ + Publisher().unsubscribe(callback, messages) + + +#---- Helper Decorators ----# + +def mwcontext(func): + """Helper decorator for checking if the message is in context of the + main window. Class that uses this to wrap its message handlers must + have a GetMainWindow method that returns a reference to the MainWindow + instance that owns the object. + @param funct: callable(self, msg) + + """ + def ContextWrap(self, msg): + """Check and only call the method if the message is in the + context of the main window or no context was specified. + + """ + if hasattr(self, 'GetMainWindow'): + mw = self.GetMainWindow() + elif hasattr(self, 'MainWindow'): + mw = self.MainWindow + else: + assert False, "Must declare a GetMainWindow method" + context = msg.GetContext() + if context is None or mw.GetId() == context: + func(self, msg) + + ContextWrap.__name__ = func.__name__ + ContextWrap.__doc__ = func.__doc__ + return ContextWrap + +def wincontext(funct): + """Decorator to filter messages based on a window. Class must declare + a GetWindow method that returns the window that the messages context + should be filtered on. + @param funct: callable(self, msg) + + """ + def ContextWrap(self, msg): + assert hasattr(self, 'GetWindow'), "Must define a GetWindow method" + context = msg.GetContext() + if isinstance(context, wx.Window) and context is self.GetWindow(): + funct(self, msg) + + ContextWrap.__name__ = funct.__name__ + ContextWrap.__doc__ = funct.__doc__ + return ContextWrap + +#-----------------------------------------------------------------------------# + +# Request Messages +EDREQ_ALL = ('editra', 'req') + +EDREQ_DOCPOINTER = EDREQ_ALL + ('docpointer',) + +#-----------------------------------------------------------------------------# + +class NullValue: + """Null value to signify that a callback method should be skipped or that + no callback could answer the request. + + """ + def __int__(self): + return 0 + + def __nonzero__(self): + return False + +def RegisterCallback(callback, msgtype): + """Register a callback method for the given message type + @param callback: callable + @param msgtype: message type + + """ + if isinstance(msgtype, tuple): + mtype = '.'.join(msgtype) + else: + mtype = msgtype + + if mtype not in _CALLBACK_REGISTRY: + _CALLBACK_REGISTRY[mtype] = list() + + if callback not in _CALLBACK_REGISTRY[mtype]: + _CALLBACK_REGISTRY[mtype].append(callback) + +def RequestResult(msgtype, args=list()): + """Request a return value result from a registered function/method. + If multiple callbacks have been registered for the given msgtype, the + first callback to return a non-NullValue will be used for the return + value. If L{NullValue} is returned then no callback could answer the + call. + @param msgtype: Request message + @keyword args: Arguments to pass to the callback + + """ + if isinstance(msgtype, tuple): + mtype = '.'.join(msgtype) + else: + mtype = msgtype + + to_remove = list() + rval = NullValue() + for idx, meth in enumerate(_CALLBACK_REGISTRY.get(mtype, list())): + try: + if len(args): + rval = meth(args) + else: + rval = meth() + except PyDeadObjectError: + to_remove.append(meth) + + if not isinstance(rval, NullValue): + break + + # Remove any dead objects that may have been found + for val in reversed(to_remove): + try: + _CALLBACK_REGISTRY.get(mtype, list()).pop(val) + except: + pass + + return rval + +def UnRegisterCallback(callback): + """Un-Register a callback method + @param callback: callable + + """ + for key, val in _CALLBACK_REGISTRY.iteritems(): + if callback in val: + _CALLBACK_REGISTRY[key].remove(callback) + +# Callback Registry for storing the methods sent in with RegisterCallback +_CALLBACK_REGISTRY = {} + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_pages.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_pages.py new file mode 100644 index 0000000..7c8662f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_pages.py @@ -0,0 +1,1286 @@ +############################################################################### +# Name: ed_pages.py # +# Purpose: The main editor notebook # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This class implements Editra's main notebook control. +@summary: Editra's main notebook class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_pages.py 72278 2012-08-02 14:24:23Z CJP $" +__revision__ = "$Revision: 72278 $" + +#--------------------------------------------------------------------------# +# Dependencies +import os +import sys +import glob +import wx + +# Editra Libraries +import ed_glob +from profiler import Profile_Get, Profile_Set +import ed_editv +import syntax.synglob as synglob +import syntax.syntax as syntax +import ed_search +import util +import ed_msg +import ed_txt +import ed_mdlg +import ed_session +import ebmlib +import eclib +from extern import aui +import ed_book + +#--------------------------------------------------------------------------# +# Globals +ID_IDLE_TIMER = wx.NewId() +SIMULATED_EVT_ID = -1 +_ = wx.GetTranslation + +#--------------------------------------------------------------------------# + +class EdPages(ed_book.EdBaseBook): + """Editra's editor buffer notebook + @todo: allow for tab styles to be configurable (maybe) + + """ + def __init__(self, parent): + """Initialize a notebook with a blank text control in it + @param parent: parent window of the notebook + + """ + style = aui.AUI_NB_DEFAULT_STYLE | \ + aui.AUI_NB_WINDOWLIST_BUTTON | \ + aui.AUI_NB_SMART_TABS | \ + aui.AUI_NB_USE_IMAGES_DROPDOWN | \ + aui.AUI_NB_TAB_EXTERNAL_MOVE | \ + aui.AUI_NB_TAB_FIXED_WIDTH | \ + aui.AUI_NB_ORDER_BY_ACCESS + super(EdPages, self).__init__(parent, style=style) + + # Notebook attributes + self.LOG = wx.GetApp().GetLog() + self._idletimer = wx.Timer(self, ID_IDLE_TIMER) + self.DocMgr = ed_editv.EdEditorView.DOCMGR + self._searchctrl = ed_search.SearchController(self, self.GetCurrentCtrl) + self._searchctrl.SetLookinChoices(Profile_Get('SEARCH_LOC', + default=list())) + self._searchctrl.SetFileFilters(Profile_Get('SEARCH_FILTER', default=u'')) + + self.pg_num = -1 # Track new pages (aka untitled docs) + self.mdown = -1 + self.control = None + self.frame = self.GetTopLevelParent() # MainWindow + self._ses_load = False + self._menu = ebmlib.ContextMenuManager() + + # Setup Tab Navigator + ed_icon = ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.png" + bmp = wx.Bitmap(ed_icon, wx.BITMAP_TYPE_PNG) + if bmp.IsOk(): + self.SetNavigatorIcon(bmp) + else: + util.Log("[ed_pages][warn] Bad bitmap: %s" % ed_icon) + + # Set custom options + self.SetMinMaxTabWidth(125, 135) + + # Notebook Events + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGING, self.OnPageChanging) + self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnPageChanged) + self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnPageClosing) + self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSED, self.OnPageClosed) + self.Bind(aui.EVT_AUINOTEBOOK_TAB_DCLICK, self.OnTabLeftDClick) + self.Bind(aui.EVT_AUINOTEBOOK_BG_DCLICK, self.OnBGLeftDClick) + self.Bind(aui.EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN, self.OnMClickDown) + self.Bind(aui.EVT_AUINOTEBOOK_TAB_MIDDLE_UP, self.OnMClickUp) + self.Bind(aui.EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabMenu) + self.Bind(aui.EVT_AUINOTEBOOK_ALLOW_DND, self.OnAllowDnD) + self.Bind(aui.EVT_AUINOTEBOOK_END_DRAG, self.OnDragFinished) + self.Bind(aui.EVT_AUINOTEBOOK_DRAG_DONE, self.OnDragFinished) + + self.Bind(wx.stc.EVT_STC_CHANGE, self.OnUpdatePageText) + self.Bind(wx.EVT_MENU, self.OnMenu) + self.Bind(wx.EVT_TIMER, self.OnIdle, id=ID_IDLE_TIMER) + + # Message handlers + ed_msg.Subscribe(self.OnThemeChanged, ed_msg.EDMSG_THEME_CHANGED) + ed_msg.Subscribe(self.OnThemeChanged, ed_msg.EDMSG_THEME_NOTEBOOK) + ed_msg.Subscribe(self.OnUpdatePosCache, ed_msg.EDMSG_UI_STC_POS_JUMPED) + ed_msg.Subscribe(self.OnGetOpenFiles, ed_msg.EDMSG_FILE_GET_OPENED) + ed_msg.RegisterCallback(self.OnDocPointerRequest, + ed_msg.EDREQ_DOCPOINTER) + + # Add a blank page + self.NewPage() + self._idletimer.Start(400) + + #---- End Init ----# + + #---- Implementation ----# + + def OnDestroy(self, evt): + if self and evt.Id == self.Id: + ed_msg.Unsubscribe(self.OnThemeChanged) + ed_msg.Unsubscribe(self.OnUpdatePosCache) + ed_msg.Unsubscribe(self.OnGetOpenFiles) + ed_msg.UnRegisterCallback(self.OnDocPointerRequest) + + def _HandleEncodingError(self, control): + """Handle trying to reload the file the file with a different encoding + Until it succeeds or gives up. + @param control: stc + @return: bool + + """ + # Loop while the load fails prompting to try a new encoding + tried = None + fname = control.GetFileName().strip(os.sep) + fname = fname.split(os.sep)[-1] + while True: + doc = control.GetDocument() + doc.ClearLastError() + if tried is None: + enc = doc.GetEncoding() + if enc is None: + enc = ed_txt.DEFAULT_ENCODING + else: + enc = tried + + msg = _("The correct encoding of '%s' could not be determined.\n\n" + "Choose an encoding and select Ok to open the file with the chosen encoding.\n" + "Click Cancel to abort opening the file") % fname + + # On some systems it seems that default encoding ends up being + # None so default to utf-8 for choices. + if enc is None: + enc = 'utf_8' + + dlg = eclib.EncodingDialog(self, msg=msg, + title=_("Choose an Encoding"), + default=enc) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOCPROP), + wx.ART_OTHER) + if bmp.IsOk(): + dlg.SetBitmap(bmp) + dlg.CenterOnParent() + result = dlg.ShowModal() + if dlg: + enc = dlg.GetEncoding() + dlg.Destroy() + else: + result = wx.ID_CANCEL + + # Don't want to open it in another encoding + if result == wx.ID_CANCEL: + return False + else: + control.SetEncoding(enc) + tried = enc + ok = control.LoadFile(control.GetFileName()) + if ok: + return True + else: + # Artificially add a short pause, because if its not there + # the dialog will be shown again so fast it wont seem + # like reloading the file was even tried. + wx.Sleep(1) + + def _NeedOpen(self, path): + """Check if a file needs to be opened. If the file is already open in + the notebook a dialog will be opened to ask if the user wants to reopen + the file again. If the file is not open and exists or the user chooses + to reopen the file again the function will return True else it will + return False. + @param path: file to check for + @return: bool + + """ + result = wx.ID_YES + if self.HasFileOpen(path): + mdlg = wx.MessageDialog(self, + _("File is already open in an existing " + "page.\nDo you wish to open it again?"), + _("Open File") + u"?", + wx.YES_NO | wx.NO_DEFAULT | \ + wx.ICON_INFORMATION) + result = mdlg.ShowModal() + mdlg.Destroy() + if result == wx.ID_NO: + self.GotoPage(path) + elif os.path.exists(path) and not os.path.isfile(path): + result = wx.ID_NO + else: + pass + + return result == wx.ID_YES + + def AddPage(self, page, text=u'', select=True, imgId=-1): + """Add a page to the notebook""" + bNewPage = False + if not len(text): + self.pg_num += 1 + if self.pg_num != 0: + text = _("untitled %d") % self.pg_num + else: + text = _("untitled") + bNewPage = True + page.SetTabLabel(text) + bmp = wx.NullBitmap + if Profile_Get('TABICONS'): + bmp = page.GetTabImage() + super(EdPages, self).AddPage(page, text, select, bitmap=bmp) + self.UpdateIndexes() + if not self._ses_load and not bNewPage: + # Only auto save session when using default session + mgr = ed_session.EdSessionMgr() + if Profile_Get('LAST_SESSION') == mgr.DefaultSession: + self.SaveCurrentSession() + + def DocDuplicated(self, path): + """Check for if the given path is open elsewhere and duplicate the + docpointer. + @param path: string + + """ + doc = ed_msg.RequestResult(ed_msg.EDREQ_DOCPOINTER, [self, path]) + if hasattr(doc, 'GetDocPointer'): + self.OpenDocPointer(doc.GetDocPointer(), doc.GetDocument()) + return True + else: + return False + + def GetCurrentCtrl(self): + """Returns the control of the currently selected + page in the notebook. + @return: window object contained in current page or None + + """ + return self.control + + def GetFileNames(self): + """Gets the name of all open files in the notebook + @return: list of file names + + """ + rlist = list() + for buff in self.GetTextControls(): + fname = buff.GetFileName() + if fname != wx.EmptyString: + rlist.append(fname) + return rlist + + def GetFindDialog(self): + """Get the active find dialog or None if one is not active + @return: FindDialog or None + + """ + return self._searchctrl.GetDialog() + + def GetMenuHandlers(self): + """Get the (id, evt_handler) tuples that this window should + handle. + @return: list of tuples + + """ + rlist = [(ed_glob.ID_FIND, self._searchctrl.OnShowFindDlg), + (ed_glob.ID_FIND_REPLACE, self._searchctrl.OnShowFindDlg), + (ed_glob.ID_FIND_NEXT, self._searchctrl.OnFind), + (ed_glob.ID_FIND_PREVIOUS, self._searchctrl.OnFind), + (ed_glob.ID_FIND_SELECTED, self._searchctrl.OnFindSelected), + (ed_glob.ID_NEXT_POS, self.OnNavigateToPos), + (ed_glob.ID_PRE_POS, self.OnNavigateToPos)] + + return rlist + + def GetUiHandlers(self): + """Get the update ui handlers that this window supplies + @return: list of tuples + + """ + return [(ed_glob.ID_FIND_NEXT, self._searchctrl.OnUpdateFindUI), + (ed_glob.ID_FIND_PREVIOUS, self._searchctrl.OnUpdateFindUI), + (ed_glob.ID_NEXT_POS, self.OnUpdateNaviUI), + (ed_glob.ID_PRE_POS, self.OnUpdateNaviUI)] + + def InsertPage(self, index, page, text, select=False, + bitmap=wx.NullBitmap, disabled_bitmap=wx.NullBitmap, + control=None): + """Insert a page into the notebook""" + super(EdPages, self).InsertPage(index, page, text, select, + bitmap, disabled_bitmap, control) + self.UpdateIndexes() + + def SaveCurrentSession(self): + """Save the current session""" + if self._ses_load: + return + + session = Profile_Get('LAST_SESSION') + # Compatibility with older session data + if not isinstance(session, basestring) or not len(session): + mgr = ed_session.EdSessionMgr() + session = mgr.DefaultSession + Profile_Set('LAST_SESSION', session) + self.SaveSessionFile(session) + + def SaveSessionFile(self, session): + """Save the current open files to the given session file + @param session: path to session file + @return: tuple (error desc, error msg) or None + + """ + if self._ses_load: + return + + try: + mgr = ed_session.EdSessionMgr() + flist = self.GetFileNames() + bSaved = mgr.SaveSession(session, flist) + except Exception, msg: + self.LOG("[ed_pages][err] SaveSession error %s" % msg) + return None + + def LoadSessionFile(self, session): + """Load files from saved session data in profile + @param session: session filename + @return: tuple (error desc, error msg), or None if no error + + """ + self._ses_load = True + + mgr = ed_session.EdSessionMgr() + flist = list() + try: + flist = mgr.LoadSession(session) + except Exception, msg: + self._ses_load = False + errdict = dict(sessionname=session, error=msg) + return (_("Session Load Error"), + _("Failed to load the session: %(sessionname)s\n\nError: %(error)s") % errdict) + + if not len(flist): + self._ses_load = False + return (_("Empty File"), _("Session file is empty.")) + + # Close current files + self.CloseAllPages() + + missingfns = [] + for loadfn in flist: + if os.path.exists(loadfn) and os.access(loadfn, os.R_OK): + if not ebmlib.IsUnicode(loadfn): + try: + loadfn = loadfn.decode(sys.getfilesystemencoding()) + except UnicodeDecodeError: + self.LOG("[ed_pages][err] LoadSessionFile: Failed to decode file name") + self.OpenPage(os.path.dirname(loadfn), + os.path.basename(loadfn)) + else: + missingfns.append(loadfn) + + if missingfns: + rmsg = (_("Missing session files"), + _("Some files in saved session could not be found on disk:\n")+ + u'\n'.join(missingfns)) + self._ses_load = False + return rmsg + + self._ses_load = False + + if self.GetPageCount() == 0: + self.NewPage() + + self.Refresh() + return None + + def NewPage(self): + """Create a new notebook page with a blank text control + @postcondition: a new page with an untitled document is opened + + """ + frame = self.TopLevelParent + with eclib.Freezer(frame) as _tmp: + self.control = ed_editv.EdEditorView(self) + self.LOG("[ed_pages][evt] New Page Created") + self.AddPage(self.control) + + # Set the control up the the preferred default lexer + dlexer = Profile_Get('DEFAULT_LEX', 'str', synglob.LANG_TXT) + ext_reg = syntax.ExtensionRegister() + ext_lst = ext_reg.get(dlexer, ['txt', ]) + self.control.FindLexer(ext_lst[0]) + self.SetPageBitmap(self.GetSelection(), self.control.GetTabImage()) + + # Set the modified callback notifier + doc = self.control.GetDocument() + doc.AddModifiedCallback(self.control.FireModified) + + def OnAllowDnD(self, evt): + """Handle allowing tab drag and drop events""" + dsource = evt.GetDragSource() + if isinstance(dsource, EdPages): + evt.Allow() + wx.CallAfter(self.UpdateIndexes) + + def OnDragFinished(self, evt): + self.UpdateIndexes() + evt.Skip() + + def OnMenu(self, evt): + """Handle context menu events + @param evt: wx.MenuEvent + + """ + ctab = self.GetCurrentPage() + handler = self._menu.GetHandler(evt.Id) + if handler is not None: + handler(ctab, evt) + elif ctab is not None: + ctab.OnTabMenu(evt) + else: + evt.Skip() + + def OnDocPointerRequest(self, args): + """Get a buffer that has the same file open as the requested path. + @param args: [sender, path] + @return: EdEditorView reference or ed_msg.NullValue + + """ + sender, path = args + for buf in self.GetTextControls(): + if buf.GetFileName() == path: + return buf + else: + return ed_msg.NullValue() + + def OnTabLeftDClick(self, evt): + """Handle left double clicks and open new tab when in empty area. + @param evt: aui.EVT_AUINOTEBOOK_TAB_DCLICK + + """ + tlw = self.GetTopLevelParent() + if hasattr(tlw, 'OnMaximizeEditor'): + tlw.OnMaximizeEditor(None) + + def OnBGLeftDClick(self, evt): + """Handle clicks on tab background area + @param evt: aui.EVT_AUINOTEBOOK_BG_DCLICK + + """ + self.NewPage() + + def OnMClickDown(self, evt): + """Handle tab middle mouse button down click event + @param evt: aui.EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN + + """ + self.mdown = evt.Page + idx = self.GetPageIndex(self.mdown) + self.SetSelection(idx) + self.LOG("[ed_pages][evt] OnMClickDown: %d" % idx) + + def OnMClickUp(self, evt): + """Handle tab middle click event + @param evt: aui.EVT_AUINOTEBOOK_TAB_MIDDLE_UP + + """ + sel = self.GetPageIndex(evt.Page) + self.LOG("[ed_pages][evt] OnMClickUp: %d" % sel) + if evt.Page is self.mdown: + self.ClosePage() + self.mdown = None + + def OnNavigateToPos(self, evt): + """Handle buffer position history navigation events""" + e_id = evt.GetId() + fname, pos = (None, None) + cname = self.control.GetFileName() + cpos = self.control.GetCurrentPos() + if e_id == ed_glob.ID_NEXT_POS: + if self.DocMgr.CanNavigateNext(): + fname, pos = self.DocMgr.GetNextNaviPos() + if (fname, pos) == (cname, cpos): + fname, pos = (None, None) + tmp = self.DocMgr.GetNextNaviPos() + if tmp is not None: + fname, pos = tmp + elif e_id == ed_glob.ID_PRE_POS: + if self.DocMgr.CanNavigatePrev(): + fname, pos = self.DocMgr.GetPreviousNaviPos() + if (fname, pos) == (cname, cpos): + fname, pos = (None, None) + tmp = self.DocMgr.GetPreviousNaviPos() + if tmp is not None: + fname, pos = tmp + else: + evt.Skip() + return + + ctrl = self.FindBuffer(fname) + if ctrl is None: + # Open the file in the editor + if fname is not None: + self.OpenPage(ebmlib.GetPathName(fname), + ebmlib.GetFileName(fname)) + self.control.SetCaretPos(pos) + else: + # Raise page to top and goto position + pages = [self.GetPage(page) for page in range(self.GetPageCount())] + idx = pages.index(ctrl) + self.ChangePage(idx) + ctrl.SetCaretPos(pos) + + def OnTabMenu(self, evt): + """Show the tab context menu""" + self._menu.Clear() + + # Construct the menu + tab = self.GetPageIndex(evt.Page) + if tab != self.GetSelection(): + self.SetSelection(tab) + + ctab = self.GetCurrentPage() + if ctab is not None: + menu = ctab.GetTabMenu() + if menu is None: + return # Tab has no menu + + self._menu.SetMenu(menu) + self._menu.SetUserData("page", ctab) + + # Allow clients to customize the menu prior to showing it + ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_TABMENU, self._menu) + + # Show the menu + self.PopupMenu(self._menu.Menu) + + def GetMainWindow(self): + return self.TopLevelParent + + @ed_msg.mwcontext + def OnGetOpenFiles(self, msg): + """Report all opened files""" + if not self: + return + + data = msg.GetData() + if not isinstance(data, list): + return + flist = self.GetFileNames() + data.extend(flist) + + def OnThemeChanged(self, msg): + """Update icons when the theme has changed + @param msg: Message Object + + """ + self.UpdateAllImages() + + def OnUpdatePosCache(self, msg): + """Update the position cache for buffer position changes + @param msg: message data + + """ + if not self or self._ses_load: + return + + if self.TopLevelParent.Id == msg.GetContext(): + data = msg.GetData() + self.DocMgr.AddNaviPosition(data['fname'], data['prepos']) + self.DocMgr.AddNaviPosition(data['fname'], data['pos']) + + def OnUpdateNaviUI(self, evt): + """UpdateUI handler for position navigator""" + e_id = evt.Id + if e_id == ed_glob.ID_NEXT_POS: + evt.Enable(self.DocMgr.CanNavigateNext()) + elif e_id == ed_glob.ID_PRE_POS: + evt.Enable(self.DocMgr.CanNavigatePrev()) + else: + evt.Skip() + + def OpenDocPointer(self, ptr, doc, title=u''): + """Open a page using an stc document poiner + @param ptr: EdEditorView document Pointer + @param doc: EdFile instance + @keyword title: tab title + + """ + with eclib.Freezer(self.TopLevelParent) as _tmp: + nbuff = self.GetCurrentPage() + need_add = False + if nbuff.GetFileName() or nbuff.GetLength(): + need_add = True + nbuff = ed_editv.EdEditorView(self) + + nbuff.SetDocPointer(ptr) + nbuff.SetDocument(doc) + doc.AddModifiedCallback(nbuff.FireModified) + nbuff.FindLexer() + + path = nbuff.GetFileName() + if Profile_Get('SAVE_POS'): + pos = self.DocMgr.GetPos(path) + nbuff.SetCaretPos(pos) + nbuff.ScrollToColumn(0) + + if title: + filename = title + else: + filename = ebmlib.GetFileName(path) + + if need_add: + self.AddPage(nbuff, filename) + else: + self.SetPageText(self.GetSelection(), filename) + + self.LOG("[ed_pages][evt] Opened Page: %s" % filename) + + # Set tab image + self.SetPageBitmap(self.GetSelection(), nbuff.GetTabImage()) + + # Refocus on selected page + self.control = nbuff + self.GoCurrentPage() + ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED, + nbuff.GetFileName(), + context=self.frame.Id) + + def OpenFileObject(self, fileobj): + """Open a new text editor page with the given file object. The file + object must be an instance of ed_txt.EdFile. + @param fileobj: File Object + + """ + # Create the control + with eclib.Freezer(self.TopLevelParent) as _tmp: + control = ed_editv.EdEditorView(self) + control.Hide() + + # Load the files data + path = fileobj.GetPath() + filename = ebmlib.GetFileName(path) + control.SetDocument(fileobj) + result = control.ReloadFile() + + # Setup the buffer + fileobj.AddModifiedCallback(control.FireModified) + + # Setup the notebook + self.control = control + self.control.FindLexer() + self.control.EmptyUndoBuffer() + self.control.Show() + self.AddPage(self.control, filename) + + self.frame.AddFileToHistory(path) + self.SetPageText(self.GetSelection(), filename) + self.LOG("[ed_pages][evt] Opened Page: %s" % filename) + + # Set tab image + cpage = self.GetSelection() + self.SetPageBitmap(cpage, self.control.GetTabImage()) + + # Refocus on selected page + self.GoCurrentPage() + ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED, + self.control.GetFileName(), + context=self.frame.Id) + + if Profile_Get('WARN_EOL', default=True) and not fileobj.IsRawBytes(): + self.control.CheckEOL() + + def OpenPage(self, path, filename, quiet=False): + """Open a File Inside of a New Page + @param path: files base path + @param filename: name of file to open + @keyword quiet: Open/Switch to the file quietly if + it is already open. + + """ + path2file = os.path.join(path, filename) + + # Resolve links to real file + if ebmlib.IsLink(path2file): + path2file = ebmlib.ResolveRealPath(path2file) + path = ebmlib.GetPathName(path2file) + filename = ebmlib.GetFileName(path2file) + + if self.DocDuplicated(path2file): + return + + # Check if file needs to be opened + # TODO: these steps could be combined together with some + # refactoring of the _NeedOpen method. Requires extra + # testing though to check for dependencies on current + # behavior. + if quiet and self.HasFileOpen(path2file): + self.GotoPage(path2file) + return + elif not self._NeedOpen(path2file): + return + + # Create new control to place text on if necessary + with eclib.Freezer(self.TopLevelParent) as _tmp: + new_pg = True + if self.GetPageCount(): + if self.control.GetModify() or self.control.GetLength() or \ + self.control.GetFileName() != u'': + control = ed_editv.EdEditorView(self, wx.ID_ANY) + control.Hide() + else: + new_pg = False + control = self.control + else: + control = ed_editv.EdEditorView(self, wx.ID_ANY) + control.Hide() + + # Open file and get contents + result = False + if os.path.exists(path2file): + try: + result = control.LoadFile(path2file) + except Exception, msg: + self.LOG("[ed_pages][err] Failed to open file %s\n" % path2file) + self.LOG("[ed_pages][err] %s" % msg) + + # File could not be opened/read give up + # Don't raise a dialog during a session load error as if the + # dialog is shown before the mainwindow is ready it can cause + # the app to freeze. + if not self._ses_load: + ed_mdlg.OpenErrorDlg(self, path2file, msg) + control.GetDocument().ClearLastError() + control.SetFileName('') # Reset the file name + + if new_pg: + control.Destroy() + + return + else: + control.SetFileName(path2file) + result = True + + # Check if there was encoding errors + if not result and not self._ses_load: + result = self._HandleEncodingError(control) + + # Cleanup after errors + if not result: + if new_pg: + # We created a new one so destroy it + control.Destroy() + else: + # We where using an existing buffer so reset it + control.SetText('') + control.SetDocument(ed_txt.EdFile()) + control.SetSavePoint() + + return + + # Put control into page an place page in notebook + if new_pg: + control.Show() + self.control = control + + # Setup Document + self.control.FindLexer() + self.control.EmptyUndoBuffer() + doc = self.control.GetDocument() + doc.AddModifiedCallback(self.control.FireModified) + + # Add the buffer to the notebook + if new_pg: + self.AddPage(self.control, filename) + else: + self.frame.SetTitle(self.control.GetTitleString()) + + self.frame.AddFileToHistory(path2file) + self.SetPageText(self.GetSelection(), filename) + + # Set tab image + cpage = self.GetSelection() + self.SetPageBitmap(cpage, self.control.GetTabImage()) + + if Profile_Get('WARN_EOL', default=True) and not doc.IsRawBytes(): + self.control.CheckEOL() + + if not control.IsLoading(): + self.DoPostLoad() + + # Refocus on selected page + self.GoCurrentPage() + self.LOG("[ed_pages][evt] Opened Page: %s" % filename) + + def DoPostLoad(self): + """Perform post file open actions""" + # Ensure that document buffer is writable after an editable + # document is opened in the buffer. + doc = self.control.GetDocument() + if not doc.IsReadOnly() and not doc.IsRawBytes(): + self.control.SetReadOnly(False) + + # Set last known caret position if the user setting is enabled + # and the caret position has not been changed during a threaded + # file loading operation. + if Profile_Get('SAVE_POS') and self.control.GetCurrentPos() <= 0: + pos = self.DocMgr.GetPos(self.control.GetFileName()) + self.control.SetCaretPos(pos) + self.control.ScrollToColumn(0) + + ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED, + self.control.GetFileName(), + context=self.frame.Id) + + def GoCurrentPage(self): + """Move Focus to Currently Selected Page. + @postcondition: focus is set to current page + + """ + current_page = self.GetSelection() + if current_page >= 0: + control = self.GetPage(current_page) + self.control = control + return current_page + + def GotoPage(self, fname): + """Go to the page containing the buffer with the given file. + @param fname: file path (string) + + """ + for page in xrange(self.GetPageCount()): + ctrl = self.GetPage(page) + if fname == ctrl.GetFileName(): + self.ChangePage(page) + break + + def GetPageText(self, pg_num): + """Gets the tab text from the given page number, stripping + the * mark if there is one. + @param pg_num: index of page to get tab text from + @return: the tabs text + + """ + # Used to be needed with flatnotebook under certain cases + # TODO: may not be necessary anymore + try: + txt = super(EdPages, self).GetPageText(pg_num) + except Exception: + txt = '' + + if not txt or txt[0] != u"*": + return txt + return txt[1:] + + def GetRawPageText(self, pg_num): + """Get the unformatted raw page text + @param pg_num: int + @return: string + + """ + try: + txt = super(EdPages, self).GetPageText(pg_num) + except Exception: + txt = '' + return txt + + def ImageIsReadOnly(self, index): + """Does the given page currently have a ReadOnly Image + shown on it? + @return: bool + + """ + bReadOnly = False + try: + if index < self.GetPageCount(): + bReadOnly = self.GetPageImage(index) == self._index[ed_glob.ID_READONLY] + else: + self.LOG("[ed_pages][warn] ImageIsReadOnly: Bad index: %d" % index) + except Exception, msg: + # TODO: investigate possible upstream issue + self.LOG("[ed_pages][err] ImageIsReadOnly: %s" % msg) + return bReadOnly + + def SetPageText(self, pg_num, txt): + """Set the pages tab text + @param pg_num: page index + @param txt: string + + """ + super(EdPages, self).SetPageText(pg_num, txt) + page = self.GetPage(pg_num) + page.SetTabLabel(txt) + + def GetTextControls(self): + """Gets all the currently opened text controls + @return: list containing reference to all stc controls opened in the + notebook. + + """ + pages = [self.GetPage(page) for page in xrange(self.GetPageCount())] + return [page for page in pages if page.GetName() == "EditraTextCtrl"] + + def HasFileOpen(self, fpath): + """Checks if one of the currently active buffers has + the named file in it. + @param fpath: full path of file to check + @return: bool indicating whether file is currently open or not + + """ + for ctrl in self.GetTextControls(): + if fpath == ctrl.GetFileName(): + return True + return False + + def FindBuffer(self, fpath): + """Find the buffer containing the given file + @param fpath: full path of file to look for + @return: EdStc or None + @todo: handle matching based on the buffer control itself + + """ + for ctrl in self.GetTextControls(): + if fpath == ctrl.GetFileName(): + return ctrl + return None + + #---- Event Handlers ----# + def OnDrop(self, files): + """Opens dropped files + @param files: list of file paths + @postcondition: all files that could be properly opend are added to + the notebook + + """ + # Check file properties and make a "clean" list of file(s) to open + valid_files = list() + for fname in files: + self.LOG("[ed_pages][evt] File(s) Dropped: %s" % fname) + if not os.path.exists(fname): + self.frame.PushStatusText(_("Invalid file: %s") % fname, \ + ed_glob.SB_INFO) + elif os.path.isdir(fname): + dcnt = glob.glob(os.path.join(fname, '*')) + dcnt = util.FilterFiles(dcnt) + dlg = None + if not len(dcnt): + dlg = wx.MessageDialog(self, + _("There are no files that Editra" + " can open in %s") % fname, + _("No Valid Files to Open"), + style=wx.OK | wx.CENTER | \ + wx.ICON_INFORMATION) + elif len(dcnt) > 5: + # Warn when the folder contains many files + dlg = wx.MessageDialog(self, + _("Do you wish to open all %d files" + " in this directory?\n\nWarning:" + " opening many files at once may" + " cause the editor to temporarily " + " freeze.") % len(dcnt), + _("Open Directory?"), + style=wx.YES | wx.NO | \ + wx.ICON_INFORMATION) + if dlg is not None: + result = dlg.ShowModal() + dlg.Destroy() + else: + result = wx.ID_YES + + if result == wx.ID_YES: + valid_files.extend(dcnt) + else: + pass + else: + valid_files.append(fname) + + for fname in valid_files: + pathname = ebmlib.GetPathName(fname) + the_file = ebmlib.GetFileName(fname) + self.OpenPage(pathname, the_file) + self.frame.PushStatusText(_("Opened file: %s") % fname, \ + ed_glob.SB_INFO) + return + + def OnIdle(self, evt): + """Update tabs and check if files have been modified + @param evt: wx.TimerEvent + + """ + if wx.GetApp().IsActive(): + for idx in range(self.GetPageCount()): + page = self.GetPage(idx) + if page is not None and page.IsShown(): + page.DoOnIdle() + + def OnPageChanging(self, evt): + """Page changing event handler. + @param evt: aui.EVT_AUINOTEBOOK_PAGE_CHANGING + + """ + evt.Skip() + pages = (evt.GetOldSelection(), evt.GetSelection()) + self.LOG("[ed_pages][evt] Control Changing from Page: " + "%d to Page: %d\n" % pages) + + # Check if it has been destroyed already + if self.control: + self.control.DoDeactivateTab() + + ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGING, + (self,) + pages, + context=self.frame.Id) + + def ChangePage(self, pg_num, old=-2): + """Change the page and focus to the the given page id + @param pg_num: Page number to change + @keyword old: previous selection + + """ + cpage = self.GetSelection() + if cpage != pg_num: + self.SetSelection(pg_num) + + # Get the window that is the current page + window = self.GetPage(pg_num) + self.control = window + + # Update Frame Title + self.frame.SetTitle(self.control.GetTitleString()) + + # Only post page changes when the change is not from the app exiting + # NOTE: -2 is used as default value, cant use -1 as it comes from + # page close events. + if old > -2: + cpage = old + + if not self.frame.IsExiting() and cpage != pg_num: + ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CHANGED, + (self, pg_num), + context=self.frame.Id) + + def OnPageChanged(self, evt): + """Actions to do after a page change + @param evt: aui.EVT_AUINOTEBOOK_PAGE_CHANGED + + """ + cpage = evt.GetSelection() + self.ChangePage(cpage, old=evt.GetOldSelection()) + self.LOG("[ed_pages][evt] Page Changed to %d" % cpage) + + # Call the tab specific selection handler + page = self.GetCurrentPage() + if page: + page.DoTabSelected() + self.GoCurrentPage() + + def OnPageClosing(self, evt): + """Checks page status to flag warnings before closing + @param evt: aui.EVT_AUINOTEBOOK_PAGE_CLOSE + + """ + page = self.GetPage(evt.GetSelection()) + if page and page.CanCloseTab(): + sel = self.GetSelection() + self.LOG("[ed_pages][evt] Closing Page: #%d" % sel) + + # Call the tab specific close handler + page.DoTabClosing() + + evt.Skip() + ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CLOSING, + (self, sel), + context=self.frame.Id) + else: + evt.Veto() + + def OnPageClosed(self, evt): + """Handles Paged Closed Event + @param evt: aui.EVT_AUINOTEBOOK_PAGE_CLOSED + + """ + frame = self.TopLevelParent + with eclib.Freezer(frame) as _tmp: + cpage = evt.GetSelection() + evt.Skip() + self.LOG("[ed_pages][evt] Closed Page: #%d" % cpage) + self.UpdateIndexes() + ed_msg.PostMessage(ed_msg.EDMSG_UI_NB_CLOSED, + (self, cpage), + context=self.frame.Id) + + if not self.GetPageCount() and \ + hasattr(frame, 'IsExiting') and not frame.IsExiting(): + self.NewPage() + elif not self.frame.IsExiting(): + self.SaveCurrentSession() + + #---- End Event Handlers ----# + + def _ClosePageNum(self, idx, deletepg=True): + """Close the given page + @param idx: int + @keyword deletepg: bool (Internal Use Only!) + @return bool: was page deleted? + + """ + result = True + try: + page = self.GetPage(idx) + result = page.CanCloseTab() + + # TODO: this makes very little sense, why did this deletepg + # value get added, this function is useless when it + # is not true... + if result and deletepg: + evt = aui.AuiNotebookEvent(aui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, + SIMULATED_EVT_ID) + evt.SetSelection(idx) + self.OnPageClosing(evt) + with eclib.Freezer(self.TopLevelParent) as _tmp: + self.DeletePage(idx) + evt = aui.AuiNotebookEvent(aui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, + SIMULATED_EVT_ID) + evt.SetSelection(idx) + self.OnPageClosed(evt) + except Exception: + # TODO: workaround for crash in base on destruction + pass + + return result + + def CloseAllPages(self): + """Closes all open pages""" + for page in range(self.GetPageCount()): + if not self.ClosePage(): + break + + def CloseOtherPages(self): + """Close all but the currently selected tab""" + cpage = self.GetCurrentPage() + to_del = list() + for pnum in range(self.GetPageCount()): + page = self.GetPage(pnum) + if not page: + break + if not (page == cpage): + if page.CanCloseTab(): + to_del.append(pnum) + + if len(to_del): + to_del.sort() + to_del.reverse() + for pnum in to_del: + self._ClosePageNum(pnum) + + def ClosePage(self, deletepg=True): + """Closes currently selected page + @keyword deletepg: bool (actually delete the page) internal use only + @return: bool + + """ + pnum = self.GetSelection() + result = self._ClosePageNum(pnum, deletepg) + return result + + def CanClosePage(self): + """Can the current page be closed? + @return: bool + + """ + self.GoCurrentPage() + page = self.GetCurrentPage() + if page: + return page.CanCloseTab() + return False + + def UpdateAllImages(self): + """Reload and Reset all images in the notebook pages and + the corresponding imagelist to match those of the current theme + @postcondition: all images in control are updated + + """ + bUseIcons = Profile_Get('TABICONS') + for page in range(self.GetPageCount()): + if bUseIcons: + tab = self.GetPage(page) + self.SetPageBitmap(page, tab.GetTabImage()) + else: + self.SetPageBitmap(page, wx.NullBitmap) + self.Refresh() + + def UpdateIndexes(self): + """Update all page indexes""" + pages = [self.GetPage(page) for page in range(self.GetPageCount())] + for idx, page in enumerate(pages): + page.SetTabIndex(idx) + + def UpdatePageImage(self): + """Updates the page tab image + @postcondition: page image is updated to reflect any changes in ctrl + + """ + tab = self.GetCurrentPage() + self.SetPageBitmap(self.GetSelection(), tab.GetTabImage()) + + def OnUpdatePageText(self, evt): + """Update the title text of the current page + @param evt: stc.EVT_STC_MODIFY (unused) + @note: this method must complete its work very fast it gets + called every time a character is entered or removed from + the document. + + """ + try: + if self.control.Id == evt.Id: + # Wait till file is completely loaded before updating ui based + # on modification events. + if self.control.IsLoading(): + return + + pg_num = self.GetSelection() + title = self.GetPageText(pg_num) + if self.control.GetModify(): + title = u"*" + title + + # Only Update if the text has changed + if title != super(EdPages, self).GetPageText(pg_num): + self.SetPageText(pg_num, title) + ftitle = self.control.GetTitleString() + self.frame.SetTitle(ftitle) + else: + # A background page has changed + for page in range(self.GetPageCount()): + control = self.GetPage(page) + if control.Id == evt.Id: + title = self.GetPageText(page) + if control.GetModify(): + title = u"*" + title + if title != super(EdPages, self).GetPageText(page): + self.SetPageText(page, title) + except wx.PyDeadObjectError: + pass + + def UpdateTextControls(self): + """Updates all text controls to use any new settings that have + been changed since initialization. + @postcondition: all stc controls in the notebook are reconfigured + to match profile settings + + """ + for control in self.GetTextControls(): + control.UpdateAllStyles() + control.Configure() + +#---- End Function Definitions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_print.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_print.py new file mode 100644 index 0000000..701f6c2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_print.py @@ -0,0 +1,163 @@ +############################################################################### +# Name: ed_print.py # +# Purpose: Editra's printer class # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Printer class for creating and managing printouts from a StyledTextCtrl. + +Classes: + - L{EdPrinter}: Class for managing printing and providing print dialogs + - L{EdPrintout}: Scales and renders the given document to a printer. + +@summary: Printer Classes for printing text from an STC + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: ed_print.py 67499 2011-04-15 20:33:40Z CJP $" +__revision__ = "$Revision: 67499 $" + +#--------------------------------------------------------------------------# +# Imports +import wx +import wx.stc + +# Editra Imports +import ed_glob +import util +import extern.stcprint as stcprint + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# + +# Globals +COLOURMODES = { ed_glob.PRINT_BLACK_WHITE : wx.stc.STC_PRINT_BLACKONWHITE, + ed_glob.PRINT_COLOR_WHITE : wx.stc.STC_PRINT_COLOURONWHITE, + ed_glob.PRINT_COLOR_DEF : wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG, + ed_glob.PRINT_INVERT : wx.stc.STC_PRINT_INVERTLIGHT, + ed_glob.PRINT_NORMAL : wx.stc.STC_PRINT_NORMAL } + +#--------------------------------------------------------------------------# +class EdPrinter(object): + """Printer Class for the editor + @note: current font size is fixed at 12 point for printing + + """ + def __init__(self, parent, mode=ed_glob.PRINT_NORMAL): + """Initializes the Printer + @param parent: parent window + @keyword mode: printer mode + + """ + super(EdPrinter, self).__init__() + + # Attributes + self.stc = None + self.title = wx.EmptyString + self.parent = parent + self.print_mode = mode + self.print_data = wx.PrintData() + self.margins = (wx.Point(15,15), wx.Point(15,15)) + + def CreatePrintout(self): + """Creates a printout of the current stc window + @return: a printout object + + """ + colour = COLOURMODES[self.print_mode] + dlg_data = wx.PageSetupDialogData(self.print_data) + dlg_data.SetPrintData(self.print_data) + dlg_data.SetMarginTopLeft(self.margins[0]) + dlg_data.SetMarginBottomRight(self.margins[1]) + fname = self.stc.GetFileName() + printout = stcprint.STCPrintout(self.stc, page_setup_data=dlg_data, + print_mode=colour, title=self.title, + job_title=fname) + return printout + + def PageSetup(self): + """Opens a print setup dialog and save print settings. + @return: None + + """ + dlg_data = wx.PageSetupDialogData(self.print_data) + dlg_data.SetPrintData(self.print_data) + + dlg_data.SetDefaultMinMargins(True) + dlg_data.SetMarginTopLeft(self.margins[0]) + dlg_data.SetMarginBottomRight(self.margins[1]) + + print_dlg = wx.PageSetupDialog(self.parent, dlg_data) + if print_dlg.ShowModal() == wx.ID_OK: + self.print_data = wx.PrintData(dlg_data.GetPrintData()) + self.print_data.SetPaperId(dlg_data.GetPaperId()) + self.margins = (dlg_data.GetMarginTopLeft(), + dlg_data.GetMarginBottomRight()) + print_dlg.Destroy() + + def Preview(self): + """Preview the Print + @return: None + + """ + printout = self.CreatePrintout() + printout2 = self.CreatePrintout() + preview = wx.PrintPreview(printout, printout2, self.print_data) + preview.SetZoom(150) + if preview.IsOk(): + pre_frame = wx.PreviewFrame(preview, self.parent, + _("Print Preview")) + dsize = wx.GetDisplaySize() + pre_frame.SetInitialSize((self.stc.GetSize()[0], + dsize.GetHeight() - 100)) + pre_frame.Initialize() + pre_frame.Show() + else: + wx.MessageBox(_("Failed to create print preview"), + _("Print Error"), + style=wx.ICON_ERROR|wx.OK) + + def Print(self): + """Prints the document + @postcondition: the current document is printed + + """ + pdd = wx.PrintDialogData(self.print_data) + printer = wx.Printer(pdd) + printout = self.CreatePrintout() + result = printer.Print(self.parent, printout) + if result: + dlg_data = printer.GetPrintDialogData() + self.print_data = wx.PrintData(dlg_data.GetPrintData()) + elif printer.GetLastError() == wx.PRINTER_ERROR: + wx.MessageBox(_("There was an error when printing.\n" + "Check that your printer is properly connected."), + _("Printer Error"), + style=wx.ICON_ERROR|wx.OK) + printout.Destroy() + + def SetColourMode(self, mode): + """Sets the color mode that the text is to be rendered with + @param mode: mode to set the printer to use + @return: whether mode was set or not + @rtype: boolean + + """ + if mode in COLOURMODES: + self.print_mode = mode + ret = True + else: + ret = False + return ret + + def SetStc(self, stc): + """Set the stc we are printing for + @param stc: instance of wx.stc.StyledTextCtrl + @note: MUST be called prior to any other print operations + + """ + self.stc = stc diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_search.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_search.py new file mode 100644 index 0000000..b076022 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_search.py @@ -0,0 +1,1550 @@ +############################################################################### +# Name: ed_search.py # +# Purpose: Text searching services and utilities # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007,2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +"""@package Editra.src.ed_search + +Provides text searching services, utilities, and ui components for searching +text documents and files. + +@summary: Text searching and results presentation ui + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_search.py 71673 2012-06-06 20:12:42Z CJP $" +__revision__ = "$Revision: 71673 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import sys +import re +import unicodedata +import wx + +# Local imports +import ed_glob +import ed_txt +import ed_msg +import plugin +import iface +from profiler import Profile_Get, Profile_Set +import eclib +import ebmlib +import ed_basewin +import ed_thread + +#--------------------------------------------------------------------------# +# Globals + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# + +class EdSearchEngine(ebmlib.SearchEngine): + """Text searching engine""" + def __init__(self, query, regex=True, down=True, + matchcase=True, wholeword=False): + super(EdSearchEngine, self).__init__(query, regex, down, + matchcase, wholeword) + # Attributes + self._offset = 0 + + def FormatResult(self, fname, lnum, match): + """Format the search result string for find all action that is performed + on a selection. + @return: string + @todo: better unicode handling + + """ + fname = ed_txt.DecodeString(fname, sys.getfilesystemencoding()) + if not ebmlib.IsUnicode(fname): + fname = _("DECODING ERROR") + + match = ed_txt.DecodeString(match) + if not ebmlib.IsUnicode(match): + match = _("DECODING ERROR") + else: + match = u" " + match.lstrip() + + rstring = u"%(fname)s (%(lnum)d): %(match)s" + lnum = lnum + self._offset + 1 + return rstring % dict(fname=fname, lnum=lnum, match=match) + + def SetOffset(self, offset): + """Set the offset for a search in selection action + @param offset: int + + """ + self._offset = offset + + def SetQuery(self, query): + """Set the query string""" + if not ebmlib.IsUnicode(query): + query = query.decode('utf-8') + query = unicodedata.normalize('NFC', query) + super(EdSearchEngine, self).SetQuery(query) + + def SetSearchPool(self, pool): + """Set the search pool""" + if not ebmlib.IsUnicode(pool): + pool = pool.decode('utf-8') + pool = unicodedata.normalize('NFC', pool) + super(EdSearchEngine, self).SetSearchPool(pool) + +#--------------------------------------------------------------------------# + +class SearchController(object): + """Controls the interface to the text search engine""" + def __init__(self, owner, getstc): + """Create the controller + @param owner: View that owns this controller + @param getstc: Callable to get the current buffer with + + """ + super(SearchController, self).__init__() + + # Attributes + self._parent = owner + self._stc = getstc + self._finddlg = None + self._posinfo = dict(scroll=0, start=0, found=-1, ldir=None) + self._data = self._InitFindData() + self._li_choices = list() + self._li_sel = 0 + self._filters = None + self._clients = list() + self._engine = EdSearchEngine(u"") # For incremental searches + + # Setup + self._engine.SetResultFormatter(self._engine.FormatResult) + + # Event handlers + self._parent.Bind(eclib.EVT_FIND, self.OnFind) + self._parent.Bind(eclib.EVT_FIND_NEXT, self.OnFind) + self._parent.Bind(eclib.EVT_FIND_ALL, self.OnFindAll) + self._parent.Bind(eclib.EVT_COUNT, self.OnCount) + self._parent.Bind(eclib.EVT_REPLACE, self.OnReplace) + self._parent.Bind(eclib.EVT_REPLACE_ALL, self.OnReplaceAll) + self._parent.Bind(eclib.EVT_FIND_CLOSE, self.OnFindClose) + self._parent.Bind(eclib.EVT_OPTION_CHANGED, self.OnOptionChanged) + + # Editra message handlers + ed_msg.Subscribe(self._OnShowFindMsg, ed_msg.EDMSG_FIND_SHOW_DLG) + + def __del__(self): + """Cleanup message handlers""" + ed_msg.Unsubscribe(self._OnShowFindMsg) + if self._finddlg: + self._finddlg.Destroy() + + def _CreateNewDialog(self, e_id): + """Create and set the controllers find dialog + @param e_id: Dialog Type Id + + """ + # TODO: find out why parent is not a Window in some cases... + if not isinstance(self._parent, wx.Window): + parent = wx.GetApp().GetActiveWindow() + self._parent = parent + else: + parent = self._parent + + labels = (_("Find"), _("Find/Replace")) + if e_id == ed_glob.ID_FIND_REPLACE: + dlg = eclib.AdvFindReplaceDlg(parent, self._data, labels, + eclib.AFR_STYLE_REPLACEDIALOG) + elif e_id == ed_glob.ID_FIND: + dlg = eclib.AdvFindReplaceDlg(parent, self._data, labels) + else: + dlg = None + + # Change the icons to use ones from Editra's ArtProvider + # Customize current context / state + if dlg is not None: + find = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND), wx.ART_MENU) + replace = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND_REPLACE), + wx.ART_MENU) + if find is not None and find.IsOk(): + dlg.SetFindBitmap(find) + + if replace is not None and replace.IsOk(): + dlg.SetReplaceBitmap(replace) + + # Set the persisted data from the last time the dialog was shown + def GetCurrentDir(): + """Get current directory for dialog context + @return: unicode + + """ + fname = u"" + if self: + cbuff = self._stc() + fname = getattr(cbuff, 'GetFileName', lambda: u"")() + return os.path.dirname(fname) + + dlg.SetDirectoryGetter(GetCurrentDir) + dlg.SetLookinChoices(self._li_choices) + dlg.SetLookinSelection(self._li_sel) + dlg.SetFileFilters(self._filters) + + return dlg + + def _OnShowFindMsg(self, msg): + """Message handler for clients to request and setup the find dialog + with. + @param msg: dict(mainw, lookin, findtxt) + + """ + data = msg.GetData() + if data.get('mainw', None) == self._parent.TopLevelParent: + + if 'findtxt' in data: + self.SetQueryString(data.get('findtxt')) + else: + query = self.GetClientString() + if len(query): + self.SetQueryString(query) + + # Dialog is not currently open + if self._finddlg is None: + self._finddlg = self._CreateNewDialog(ed_glob.ID_FIND) + if self._finddlg is None: + return + self._finddlg.CenterOnParent() + self._finddlg.SetTransparent(240) + # self._finddlg.SetExtraStyle(wx.WS_EX_PROCESS_UI_UPDATES) + else: + # Dialog has been created already so just update it + self._UpdateDialogState(ed_glob.ID_FIND) + + if 'lookin' in data: + self._finddlg.SetLookinPath(data.get('lookin')) + + self._finddlg.Show() + self._finddlg.Raise() + self._finddlg.SetFocus() + else: + return + + def _UpdateDialogState(self, e_id): + """Update the state of the existing dialog""" + if self._finddlg is None: + self._finddlg = self._CreateNewDialog(e_id) + self._finddlg.CenterOnParent() + else: + mode = self._finddlg.GetDialogMode() + if e_id == ed_glob.ID_FIND and mode != eclib.AFR_STYLE_FINDDIALOG: + self._finddlg.SetDialogMode(eclib.AFR_STYLE_FINDDIALOG) + elif e_id == ed_glob.ID_FIND_REPLACE and \ + mode != eclib.AFR_STYLE_REPLACEDIALOG: + self._finddlg.SetDialogMode(eclib.AFR_STYLE_REPLACEDIALOG) + else: + pass + + # Update the text that should be shown in the find replace fields + self._finddlg.RefreshFindReplaceFields() + self._finddlg.SetFocus() + + def _InitFindData(self): + """Get the intial find data + @return: wx.FindReplaceData + + """ + fdata = Profile_Get('SEARCH_SETTINGS', default=None) + if fdata is not None: + fmap = dict(matchcase=eclib.AFR_MATCHCASE, + wholeword=eclib.AFR_WHOLEWORD, + regex=eclib.AFR_REGEX, + recurse=eclib.AFR_RECURSIVE) + flags = 0 + for flag in fdata: + if fdata.get(flag, False): + flags |= fmap.get(flag, 0) + fdata = wx.FindReplaceData(flags) + else: + fdata = wx.FindReplaceData(eclib.AFR_RECURSIVE) + return fdata + + def _StoreFindData(self): + """Serialize the find/replace settings into the user profile""" + fmap = dict(matchcase=eclib.AFR_MATCHCASE, + wholeword=eclib.AFR_WHOLEWORD, + regex=eclib.AFR_REGEX, + recurse=eclib.AFR_RECURSIVE) + tostore = dict() + flags = self._data.GetFlags() + for fname in fmap: + flag = fmap[fname] + tostore[fname] = False + if flags & flag: + tostore[fname] = True + Profile_Set('SEARCH_SETTINGS', tostore) + + #---- Public Interface ----# + + def GetClientString(self, multiline=False): + """Get the selected text in the current client buffer. By default + it will only return the selected text if its on a single line. + @keyword multiline: Return text if it is multiple lines + @return: string + + """ + cbuff = self._stc() + if cbuff is None: + return u'' + + start, end = cbuff.GetSelection() + rtext = cbuff.GetSelectedText() + if start != end: + sline = cbuff.LineFromPosition(start) + eline = cbuff.LineFromPosition(end) + if not multiline and (sline != eline): + rtext = u'' + return rtext + + def GetData(self): + """Get the controllers FindReplaceData + @return: wx.FindReplaceData + + """ + return self._data + + def GetDialog(self): + """Return the active find dialog if one exists else return None + @return: FindDialog or None + + """ + return self._finddlg + + def GetLastFound(self): + """Returns the position value of the last found search item + if the last search resulted in nothing being found then the + return value will -1. + @return: position of last search operation + + """ + return self._posinfo['found'] + + def OnUpdateFindUI(self, evt): + """Update ui handler for find related controls + @param evt: updateui event + + """ + if evt.GetId() in (ed_glob.ID_FIND_PREVIOUS, ed_glob.ID_FIND_NEXT): + evt.Enable(len(self.GetData().GetFindString())) + else: + evt.Skip() + + def OnCount(self, evt): + """Count the number of matches""" + stc = self._stc() + + # Create the search engine + query = evt.GetFindString() + mode = evt.GetSearchType() + engine = ebmlib.SearchEngine(query, evt.IsRegEx(), + True, evt.IsMatchCase(), evt.IsWholeWord()) + + if mode == eclib.LOCATION_CURRENT_DOC: + engine.SetSearchPool(stc.GetText()) + elif mode == eclib.LOCATION_IN_SELECTION: + engine.SetSearchPool(stc.GetSelectedText()) + else: + # TODO: report that this is not supported yet + # this case should not happen as the count button is currently + # disabled for any conditions that fall into this case. + return + + matches = engine.FindAll() + if matches: + count = len(matches) + else: + count = 0 + + rmap = dict(term=query, count=count) + wx.MessageBox(_("The search term \'%(term)s\' was found %(count)d times.") % rmap, + _("Find Count"), + wx.ICON_INFORMATION|wx.OK) + + def OnFind(self, evt, findnext=False, incremental=False): + """Do an incremental search in the currently buffer + @param evt: EVT_FIND, EVT_FIND_NEXT + @keyword findnext: force a find next action + @keyword incremental: perform an incremental search + + """ + data = self.GetData() + + # Find next from menu event or called internally by replace + if findnext or evt.GetEventType() == wx.wxEVT_COMMAND_MENU_SELECTED: + + # Adjust flags + flags = data.GetFlags() + if not findnext and evt.GetId() == ed_glob.ID_FIND_PREVIOUS: + flags |= eclib.AFR_UP + elif eclib.AFR_UP & flags: + # Not a find previous request so make sure that + # the search up flag is cleared. + flags ^= eclib.AFR_UP + + evt = eclib.FindEvent(eclib.edEVT_FIND_NEXT, flags=flags) + evt.SetFindString(data.GetFindString()) + + stc = self._stc() + data.SetFindString(evt.GetFindString()) + + # Create the search engine + isdown = not evt.IsUp() + self._engine.SetQuery(data.GetFindString()) + self._engine.SetFlags(isregex=evt.IsRegEx(), + matchcase=evt.IsMatchCase(), + wholeword=evt.IsWholeWord(), + down=isdown) + + # Check if expression was valid or not + if self._engine.GetQueryObject() is None: + fail = ed_txt.DecodeString(self._engine.GetQuery(), 'utf-8') + wx.MessageBox(_("Invalid expression \"%s\"") % fail, + _("Regex Compile Error"), + style=wx.OK|wx.CENTER|wx.ICON_ERROR) + return + + # XXX: may be inefficient to copy whole buffer each time for files + # that are large. + self._engine.SetSearchPool(stc.GetText()) + + # Get the search start position + if evt.GetEventType() == eclib.edEVT_FIND: + if not incremental: + spos = stc.CurrentPos + else: + # For incremental search redo search starting from last found + # position. + spos = self._posinfo['found'] + if spos < 0: + spos = stc.CurrentPos + else: + spos = stc.CurrentPos + start, end = stc.GetSelection() + if start != end: + if isdown: + spos = max(start, end) + else: + spos = min(start, end) + + # Do the find + match = self._engine.Find(spos) + if match is not None: + start, end = match + if isdown: + start = start + spos + end = end + spos + stc.SetSelection(start, end) + else: + stc.SetSelection(start, end) + + # Ensure caret and the line its in is exposed + stc.EnsureCaretVisible() + line = stc.LineFromPosition(start) + stc.EnsureVisible(line) + + self._posinfo['found'] = start + + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, u"")) + else: + # try search from top again + if isdown: + match = self._engine.Find(0) + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, _("Search wrapped to top"))) + else: + match = self._engine.Find(-1) + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, + _("Search wrapped to bottom"))) + + if match is not None: + start, end = match + self._posinfo['found'] = start + stc.SetSelection(start, end) + + # Ensure caret and the line its in is exposed + stc.EnsureCaretVisible() + line = stc.LineFromPosition(start) + stc.EnsureVisible(line) + else: + self._posinfo['found'] = -1 + fail = ed_txt.DecodeString(self._engine.GetQuery(), 'utf-8') + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, + _("\"%s\" was not found") % fail)) + + def OnFindAll(self, evt): + """Find all results for the given query and display results in a + L{SearchResultScreen} in the Shelf. + + """ + smode = evt.GetSearchType() + query = evt.GetFindString() + if not query: + return + + # Create a new search engine object + engine = EdSearchEngine(query, evt.IsRegEx(), True, + evt.IsMatchCase(), evt.IsWholeWord()) + engine.SetResultFormatter(engine.FormatResult) + + # Send the search function over to any interested parties that wish + # to process the results. + if smode == eclib.LOCATION_CURRENT_DOC: + stc = self._stc() + fname = stc.GetFileName() + if len(fname): + ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, + (engine.SearchInFile, [fname,], dict())) + else: + engine.SetSearchPool(stc.GetText()) + ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, + (engine.FindAllLines,)) + if smode == eclib.LOCATION_IN_SELECTION: + stc = self._stc() + sel_s = min(stc.GetSelection()) + offset = stc.LineFromPosition(sel_s) + engine.SetOffset(offset) + engine.SetSearchPool(stc.GetSelectedText()) + ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, + (engine.FindAllLines,)) + elif smode == eclib.LOCATION_OPEN_DOCS: + files = [fname.GetFileName() + for fname in self._parent.GetTextControls()] + ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, + (engine.SearchInFiles, [files,], dict())) + elif smode == eclib.LOCATION_IN_CURRENT_DIR: + stc = self._stc() + path = ebmlib.GetPathName(stc.GetFileName()) + engine.SetFileFilters(evt.GetFileFilters()) + ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, + (engine.SearchInDirectory, + [path,], dict(recursive=evt.IsRecursive()))) + elif smode == eclib.LOCATION_IN_FILES: + path = evt.GetDirectory() + engine.SetFileFilters(evt.GetFileFilters()) + ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, + (engine.SearchInDirectory, + [path,], dict(recursive=evt.IsRecursive()))) + + def OnFindSelected(self, evt): + """Set the search query to the selected text and progress the search + to the next match. + + """ + stc = self._stc() + + fstring = stc.GetSelectedText() + if fstring: + data = self.GetData() + data.SetFindString(fstring) + self.OnFind(evt) + else: + evt.Skip() + + def OnFindClose(self, evt): + """Process storing search dialog state when it is closed + @param evt: findlg.EVT_FIND_CLOSE + + """ + if self._finddlg is not None: + # Save the lookin values for next time dialog is shown + self._li_choices = self._finddlg.GetLookinChoices() + self._li_sel = self._finddlg.GetLookinSelection() + self._filters = self._finddlg.GetFileFilters() + + # Store in profile. Only save most recent 8 in history + if len(self._li_choices) > 8: + choices = self._li_choices[-8:] + else: + choices = self._li_choices + + # Save the most recent choices of search locations + Profile_Set('SEARCH_LOC', choices) + Profile_Set('SEARCH_FILTER', self._filters) + self._StoreFindData() + self._finddlg.Destroy() + self._finddlg = None + buff = wx.GetApp().GetCurrentBuffer() + if buff: + buff.SetFocus() + + def OnOptionChanged(self, evt): + """Handle when the find options are changed in the dialog""" + self._StoreFindData() # Persist new search settings from find dialog + dead = list() + for idx, client in enumerate(self._clients): + try: + client.NotifyOptionChanged(evt) + except wx.PyDeadObjectError: + dead.append(idx) + + def OnReplace(self, evt): + """Replace the selected text in the current buffer + @param evt: finddlg.EVT_REPLACE + + """ + replacestring = evt.GetReplaceString() + if evt.IsRegEx() and self._engine is not None: + match = self._engine.GetLastMatch() + if match is not None: + try: + value = match.expand(replacestring) + except re.error, err: + msg = _("Error in regular expression expansion." + "The replace action cannot be completed.\n\n" + "Error Message: %s") % err.message + wx.MessageBox(msg, _("Replace Error"), wx.OK|wx.ICON_ERROR) + return + else: + value = replacestring + else: + value = replacestring + + sel = self._stc().GetSelection() + if sel[0] == sel[1]: + return + + self._stc().ReplaceSelection(value) + + # Go to the next match + eid = ed_glob.ID_FIND_NEXT + if evt.IsUp(): + eid = ed_glob.ID_FIND_PREVIOUS + tevt = eclib.FindEvent(eclib.edEVT_FIND_NEXT, eid) + tevt.SetFlags(evt.GetFlags()) + tevt.SetFindString(evt.GetFindString()) + self.OnFind(tevt) + + def OnReplaceAll(self, evt): + """Replace all instance of the search string with the given + replace string for the given search context. + + """ + smode = evt.GetSearchType() + rstring = evt.GetReplaceString() + engine = EdSearchEngine(evt.GetFindString(), evt.IsRegEx(), + True, evt.IsMatchCase(), evt.IsWholeWord()) + engine.SetResultFormatter(engine.FormatResult) + + results = 0 + if smode == eclib.LOCATION_CURRENT_DOC: + stc = self._stc() + engine.SetSearchPool(stc.GetText()) + matches = engine.FindAll() + if matches is not None: + self.ReplaceInStc(stc, matches, rstring, evt.IsRegEx()) + results = len(matches) + elif smode == eclib.LOCATION_IN_SELECTION: + stc = self._stc() + engine.SetSearchPool(stc.GetSelectedText()) + matches = engine.FindAll() + if matches is not None: + self.ReplaceInStcSelection(stc, matches, rstring, evt.IsRegEx()) + results = len(matches) +# regex = engine.GetQueryObject() +# if regex is not None: +# text = engine.GetSearchPool() +# def replaceString(match): +# if evt.IsRegEx(): +# value = match.expand(rstring.encode('utf-8')).decode('utf-8') +# else: +# value = rstring +# return value +# text = regex.sub(replaceString, text) +# stc.ReplaceSelection(text) + else: + pass # TODO: notify of no matches? + elif smode == eclib.LOCATION_OPEN_DOCS: + for ctrl in self._parent.GetTextControls(): + engine.SetSearchPool(ctrl.GetText()) + matches = engine.FindAll() + if matches is not None: + self.ReplaceInStc(ctrl, matches, rstring, evt.IsRegEx()) + results += len(matches) + elif smode in (eclib.LOCATION_IN_CURRENT_DIR, eclib.LOCATION_IN_FILES): + dlg = wx.MessageDialog(self._parent, + _("Sorry will be ready for future version"), + _("Not implemented"), +# _("Warning this cannot be undone!"), +# _("Do Replace All?"), + style=wx.ICON_WARNING|wx.OK|wx.CANCEL|wx.CENTER) + result = dlg.ShowModal() + dlg.Destroy() + + if result == wx.ID_OK: + pass +# path = evt.GetDirectory() +# ed_msg.PostMessage(ed_msg.EDMSG_START_SEARCH, +# (engine.SearchInDirectory, +# [path,], dict(recursive=evt.IsRecursive()))) + else: + return + + # Post number of matches that were replaced to the status bar + if results > 0: + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, + _("%d matches were replaced.") % results)) + + def OnShowFindDlg(self, evt): + """Catches the Find events and shows the appropriate find dialog + @param evt: event that called this handler + @postcondition: find dialog is shown + + """ + # Check for a selection in the buffer and load that text if + # there is any and it is at most one line. + query = self.GetClientString() + if len(query): + self.SetQueryString(query) + + eid = evt.GetId() + # Dialog is not currently open + if self._finddlg is None: + self._finddlg = self._CreateNewDialog(eid) + if self._finddlg is None: + evt.Skip() + return + self._finddlg.CenterOnParent() + self._finddlg.SetTransparent(240) +# self._finddlg.SetExtraStyle(wx.WS_EX_PROCESS_UI_UPDATES) + self._finddlg.Show() + else: + # Dialog is open already so just update it + self._UpdateDialogState(eid) + self._finddlg.Show() + self._finddlg.Raise() + self._finddlg.SetFocus() + + def RegisterClient(self, client): + """Register a client object of this search controller. The client object + must implement a method called NotifyOptionChanged to be called when + search options are changed. + + >>> def NotifyOptionChanged(self, evt) + + @param client: object + + """ + if client not in self._clients: + self._clients.append(client) + + def RemoveClient(self, client): + """Remove a client from this controller + @param client: object + + """ + if client in self._clients: + self._clients.remove(client) + + @staticmethod + def ReplaceInStc(stc, matches, rstring, isregex=True): + """Replace the strings at the position in the given StyledTextCtrl + @param stc: StyledTextCtrl + @param matches: list of match objects + @param rstring: Replace string + @keyword isregex: Is it a regular expression operation (bool) + + """ + if not len(matches): + return + def GetSub(match): + """replace substitution callable for re.sub""" + value = rstring + if isregex: + try: + value = match.expand(rstring) + except: + pass + return value + text = re.sub(matches[0].re, GetSub, stc.GetText()) + # Update the view + with eclib.Freezer(stc) as _tmp: + stc.BeginUndoAction() + cpos = stc.CurrentPos + stc.ClearAll() + stc.SetText(text) + stc.GotoPos(cpos) + stc.EndUndoAction() + + @staticmethod + def ReplaceInStcSelection(stc, matches, rstring, isregex=True): + """Replace all the matches in the selection""" + if not len(matches): + return + def GetSub(match): + """replace substitution callable for re.sub""" + value = rstring + if isregex: + try: + value = match.expand(rstring) + except: + pass + return value + text = re.sub(matches[0].re, GetSub, stc.GetSelectedText()) + # Update the view + with eclib.Freezer(stc) as _tmp: + stc.BeginUndoAction() + start, end = stc.GetSelection() + stc.ReplaceSelection(text) + stc.SetSelection(start, start+len(text)) + stc.EndUndoAction() + + def SetFileFilters(self, filters): + """Set the file filter to use + @param filters: string '*.py *.pyw' + + """ + self._filters = filters + + def SetLookinChoices(self, choices): + """Set the list of locations to use for the recent search + locations. + @param choices: list of strings + + """ + self._li_choices = choices + + def SetQueryString(self, query): + """Sets the search query value + @param query: string to search for + + """ + self._data.SetFindString(query) + + def SetSearchFlags(self, flags): + """Set the find services search flags + @param flags: bitmask of parameters to set + + """ + self._data.SetFlags(flags) + if self._finddlg is not None: + self._finddlg.SetData(self._data) + self._StoreFindData() # Update persistence + + def RefreshControls(self): + """Refresh controls that are associated with this controllers data.""" + if self._finddlg is not None: + self._finddlg.RefreshFindOptions() + self._StoreFindData() # Update persistence + +#-----------------------------------------------------------------------------# + +class EdSearchCtrl(wx.SearchCtrl): + """Creates a simple search control for use in the toolbar + or a statusbar and the such. Supports incremental search, + and uses L{SearchController} to do the actual searching of the + document. + + """ + def __init__(self, parent, id_, value="", menulen=0, \ + pos=wx.DefaultPosition, size=wx.DefaultSize, \ + style=wx.TE_RICH2|wx.TE_PROCESS_ENTER): + """Initializes the Search Control + @param parent: parent window + @param id_: control id + @keyword value: default value + @keyword menulen: max length of history menu + @keyword pos: control position (tuple) + @keyword size: control size (tuple) + @keyword style: control style bitmask + + """ + super(EdSearchCtrl, self).__init__(parent, id_, value, pos, size, style) + + # Attributes + self._parent = parent + # TEMP HACK + self.FindService = self.GetTopLevelParent().GetNotebook()._searchctrl + self._recent = list() # The History List + self._last = None + self.rmenu = wx.Menu() + self.max_menu = menulen + 2 # Max menu length + descript/separator + self._txtctrl = None # msw/gtk only + + # Setup Recent Search Menu + lbl = self.rmenu.Append(wx.ID_ANY, _("Recent Searches")) + lbl.Enable(False) + self.rmenu.AppendSeparator() + self.SetMenu(self.rmenu) + + # Bind Events + if wx.Platform in ['__WXMSW__', '__WXGTK__']: + for child in self.GetChildren(): + if isinstance(child, wx.TextCtrl): + child.Bind(wx.EVT_KEY_UP, self.ProcessEvent) + child.Bind(wx.EVT_KEY_DOWN, self.ProcessEvent) + self._txtctrl = child + break + else: + self.Bind(wx.EVT_KEY_UP, self.ProcessEvent) + self.Bind(wx.EVT_KEY_DOWN, self.ProcessEvent) + self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnCancel) + self.Bind(wx.EVT_MENU, self.OnHistMenu) + + #---- Properties ----# + def __GetFlags(self): + flags = 0 + data = self.GetSearchData() + if data: + flags = data.GetFlags() + return flags + def __SetFlags(self, flags): + data = self.GetSearchData() + if data: + data.SetFlags(flags) + SearchFlags = property(lambda self: self.__GetFlags(), + lambda self, flags: self.__SetFlags(flags)) + + #---- Functions ----# + def AutoSetQuery(self, multiline=False): + """Autoload a selected string from the controls client buffer""" + query = self.FindService.GetClientString(multiline) + if len(query): + self.FindService.SetQueryString(query) + self.SetValue(query) + + def ClearSearchFlag(self, flag): + """Clears a previously set search flag + @param flag: flag to clear from search data + + """ + data = self.GetSearchData() + if data is not None: + c_flags = data.GetFlags() + c_flags ^= flag + self.SearchFlags = c_flags + self.FindService.RefreshControls() + + def FindAll(self): + """Fire off a FindAll job in the current buffer""" + evt = eclib.FindEvent(eclib.edEVT_FIND_ALL, flags=self.SearchFlags) + evt.SetFindString(self.GetValue()) + self.FindService.OnFindAll(evt) + + def DoSearch(self, next=True, incremental=False): + """Do the search and move the selection + @keyword next: search next or previous + @keyword incremental: is this an incremental search + + """ + s_cmd = eclib.edEVT_FIND + if not next: + self.SetSearchFlag(eclib.AFR_UP) + else: + if eclib.AFR_UP & self.SearchFlags: + self.ClearSearchFlag(eclib.AFR_UP) + + if self.GetValue() == self._last: + s_cmd = eclib.edEVT_FIND_NEXT + + evt = eclib.FindEvent(s_cmd, flags=self.SearchFlags) + self._last = self.GetValue() + evt.SetFindString(self.GetValue()) + self.FindService.OnFind(evt, incremental=incremental) + + # Give feedback on whether text was found or not + if self.FindService.GetLastFound() < 0 and len(self.GetValue()) > 0: + if self._txtctrl is None: + self.SetForegroundColour(wx.RED) + else: + self._txtctrl.SetForegroundColour(wx.RED) + wx.Bell() + else: + # ?wxBUG? cant set text back to black after changing color + # But setting it to this almost black color works. Most likely its + # due to bit masking but I haven't looked at the source so I am not + # sure + if self._txtctrl is None: + self.SetForegroundColour(wx.ColourRGB(0 | 1 | 0)) + else: + self._txtctrl.SetForegroundColour(wx.ColourRGB(0 | 1 | 0)) + self.Refresh() + + def GetSearchController(self): + """Get the L{SearchController} used by this control. + @return: L{SearchController} + + """ + return self.FindService + + def GetSearchData(self): + """Gets the find data from the controls FindService + @return: wx.FindReplaceData + + """ + if hasattr(self.FindService, "GetData"): + return self.FindService.GetData() + else: + return None + + def GetHistory(self): + """Gets and returns the history list of the control + @return: list of recent search items + + """ + return getattr(self, "_recent", list()) + + def InsertHistoryItem(self, value): + """Inserts a search query value into the top of the history stack + @param value: search string + @postcondition: the value is added to the history menu + + """ + if value == wx.EmptyString: + return + + # Make sure menu only has unique items + m_items = list(self.rmenu.GetMenuItems()) + for menu_i in m_items: + if value == menu_i.GetLabel(): + self.rmenu.RemoveItem(menu_i) + + # Create and insert the new item + n_item = wx.MenuItem(self.rmenu, wx.NewId(), value) + self.rmenu.InsertItem(2, n_item) + + # Update History list + self._recent.insert(0, value) + if len(self._recent) > self.max_menu: + self._recent.pop() + + # Check Menu Length + m_len = self.rmenu.GetMenuItemCount() + if m_len > self.max_menu: + try: + self.rmenu.RemoveItem(m_items[-1]) + except IndexError, msg: + wx.GetApp().GetLog()("[ed_search][err] menu error: %s" % str(msg)) + + def IsMatchCase(self): + """Returns True if the search control is set to search + in Match Case mode. + @return: whether search is using match case or not + + """ + data = self.GetSearchData() + if data is not None: + return bool(eclib.AFR_MATCHCASE & data.GetFlags()) + return False + + def IsRegEx(self): + """Returns True if the search control is set to search + in regular expression mode. + @return: whether search is using regular expressions or not + + """ + data = self.GetSearchData() + if data is not None: + return bool(eclib.AFR_REGEX & data.GetFlags()) + return False + + def IsSearchPrevious(self): + """Returns True if the search control is set to search + in Previous mode. + @return: whether search is searching up or not + + """ + data = self.GetSearchData() + if data is not None: + return bool(eclib.AFR_UP & data.GetFlags()) + return False + + def IsWholeWord(self): + """Returns True if the search control is set to search + in Whole Word mode. + @return: whether search is using match whole word or not + + """ + data = self.GetSearchData() + if data is not None: + return bool(eclib.AFR_WHOLEWORD & data.GetFlags()) + return False + + def SetFocus(self): + """Set the focus and select the text""" + super(EdSearchCtrl, self).SetFocus() + self.AutoSetQuery() + self.SelectAll() + + def SetHistory(self, hist_list): + """Populates the history list from a list of + string values. + @param hist_list: list of search items + + """ + hist_list.reverse() + for item in hist_list: + self.InsertHistoryItem(item) + + def SetSearchFlag(self, flags): + """Sets the search data flags + @param flags: search flag to add + + """ + data = self.GetSearchData() + if data is not None: + c_flags = data.GetFlags() + c_flags |= flags + self.SearchFlags = c_flags + self.FindService.RefreshControls() + + #---- End Functions ----# + + #---- Event Handlers ----# + def ProcessEvent(self, evt): + """Processes Events for the Search Control + @param evt: the event that called this handler + + """ + e_key = evt.GetKeyCode() + if evt.GetEventType() != wx.wxEVT_KEY_UP: + if e_key in (wx.WXK_UP, wx.WXK_DOWN): + buff = wx.GetApp().GetCurrentBuffer() + if isinstance(buff, wx.stc.StyledTextCtrl): + val = -1 + if e_key == wx.WXK_DOWN: + val = 1 + buff.ScrollLines(val) + else: + evt.Skip() + return + + if e_key == wx.WXK_ESCAPE: + # TODO change to more safely determine the context + # Currently control is only used in command bar + self.GetParent().Hide() + evt.Skip() + return + elif e_key == wx.WXK_SHIFT: + self.ClearSearchFlag(eclib.AFR_UP) + return + else: + pass + + tmp = self.GetValue() + self.ShowCancelButton(len(tmp) > 0) + + # Don't do search for navigation keys + if tmp == wx.EmptyString or evt.CmdDown() or evt.ControlDown() or \ + e_key in [wx.WXK_COMMAND, wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_CONTROL, + wx.WXK_ALT, wx.WXK_UP, wx.WXK_DOWN, wx.WXK_F1, wx.WXK_F2, + wx.WXK_F3, wx.WXK_F4, wx.WXK_F5, wx.WXK_F6, wx.WXK_F7, + wx.WXK_F8, wx.WXK_F9, wx.WXK_F10, wx.WXK_F11, wx.WXK_F12]: + return + + if e_key == wx.WXK_RETURN or e_key == wx.WXK_F3: + if evt.ShiftDown(): + self.DoSearch(next=False) + else: + self.DoSearch(next=True) + + # Add to search history + if e_key == wx.WXK_RETURN: + self.InsertHistoryItem(self.GetValue()) + else: + # Don't do incremental searches when the RegEx flag is set in order + # to avoid errors in compiling the expression + if not self.IsRegEx(): + self.DoSearch(next=True, incremental=True) + + def OnCancel(self, evt): + """Cancels the Search Query + @param evt: SearchCtrl event + + """ + self.SetValue(u"") + self.ShowCancelButton(False) + evt.Skip() + + def OnHistMenu(self, evt): + """Sets the search controls value to the selected menu item + @param evt: wx.MenuEvent + + """ + item_id = evt.GetId() + item = self.rmenu.FindItemById(item_id) + if item != None: + self.SetValue(item.GetLabel()) + else: + evt.Skip() + + #---- End Event Handlers ----# + +#-----------------------------------------------------------------------------# + +class EdFindResults(plugin.Plugin): + """Shelf interface implementation for the find results""" + plugin.Implements(iface.ShelfI) + SUBSCRIBED = False + RESULT_SCREENS = list() + + def __init__(self, pmgr): + """Create the FindResults plugin + @param pmgr: This plugins manager + + """ + if not EdFindResults.SUBSCRIBED: + ed_msg.Subscribe(EdFindResults.StartResultsScreen, + ed_msg.EDMSG_START_SEARCH) + EdFindResults.SUBSCRIBED = True + +# def __del__(self): +# if EdFindResults.SUBSCRIBED: +# print "UNSUBSCRIBE" +# ed_msg.Unsubscribe(self.StartResultsScreen) + + @property + def __name__(self): + return u'Find Results' + + def AllowMultiple(self): + """Find Results allows multiple instances""" + return True + + def CreateItem(self, parent): + """Returns a log viewr panel""" + screen = SearchResultScreen(parent) + EdFindResults.RESULT_SCREENS.append(screen) + return screen + + def GetBitmap(self): + """Get the find results bitmap + @return: wx.Bitmap + + """ + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_FIND), wx.ART_MENU) + return bmp + + def GetId(self): + """Plugin menu identifier ID""" + return ed_glob.ID_FIND_RESULTS + + def GetMenuEntry(self, menu): + """Get the menu entry for the log viewer + @param menu: the menu items parent menu + + """ + return None + + def GetName(self): + """Return the name of this control""" + return self.__name__ + + def IsStockable(self): + """EdFindResults can be saved in the shelf preference stack""" + return False + + @classmethod + def StartResultsScreen(cls, msg): + """Start a search in an existing window or open a new one + @param cls: this class + @param msg: message object + + """ + win = wx.GetApp().GetActiveWindow() + + # Cleanup window list for dead objects + to_pop = list() + for idx, item in enumerate(list(EdFindResults.RESULT_SCREENS)): + if not isinstance(item, SearchResultScreen): + to_pop.append(idx) + + for idx in reversed(to_pop): + EdFindResults.RESULT_SCREENS.pop(idx) + + # Try to find an empty existing window to use for the new search + screen = None + if win is not None: + shelf = win.GetShelf() + s_mw = shelf.GetOwnerWindow() + shelf_nb = shelf.GetWindow() + for item in EdFindResults.RESULT_SCREENS: + if item.GetDisplayedLines() < 3 and \ + s_mw is win and item.GetParent() is shelf_nb: + screen = shelf.RaiseWindow(item) + break + + if screen is None: + shelf.PutItemOnShelf(ed_glob.ID_FIND_RESULTS) + screen = shelf_nb.GetCurrentPage() + + # Fire off the search job + data = msg.GetData() + if len(data) > 1: + # Doing a file search operation + screen.StartSearch(data[0], *data[1], **data[2]) + else: + # Doing a buffer find operation (in memory) + screen.StartSearch(data[0]) + +#-----------------------------------------------------------------------------# + +class SearchResultScreen(ed_basewin.EdBaseCtrlBox): + """Screen for displaying search results and navigating to them""" + def __init__(self, parent): + """Create the result screen + @param parent: parent window + + """ + super(SearchResultScreen, self).__init__(parent) + + # Attributes + self._meth = None + self._job = None + self._list = SearchResultList(self) + self._cancelb = None + self._clearb = None + + # Layout + self.__DoLayout() + self._cancelb.Disable() + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(wx.EVT_BUTTON, + lambda evt: self._list.Clear(), self._clearb) + self.Bind(wx.EVT_BUTTON, + lambda evt: self.CancelSearch(), self._cancelb) + self._list.Bind(eclib.EVT_TASK_START, self.OnTaskStart) + self._list.Bind(eclib.EVT_TASK_COMPLETE, self.OnTaskComplete) + + # Message Handlers + ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED) + + def OnDestroy(self, evt): + if evt.Id == self.Id: + ed_msg.Unsubscribe(self.OnThemeChange) + evt.Skip() + + def __DoLayout(self): + """Layout and setup the results screen ui""" + ctrlbar = self.CreateControlBar(wx.TOP) + ctrlbar.AddStretchSpacer() + + # Cancel Button + cancel = self.AddPlateButton(_("Cancel"), ed_glob.ID_STOP, wx.ALIGN_RIGHT) + self._cancelb = cancel + + # Clear Button + clear = self.AddPlateButton(_("Clear"), ed_glob.ID_DELETE, wx.ALIGN_RIGHT) + self._clearb = clear + + self.SetWindow(self._list) + + def GetDisplayedLines(self): + """Get the number of lines displayed in the output window""" + return self._list.GetLineCount() + + def OnTaskStart(self, evt): + """Start accepting results from the search thread + @param evt: UpdateBufferEvent + + """ + start = u">>> %s" % _("Search Started") + if self._meth is not None: + start += (u": " + self._meth.im_self.GetOptionsString()) + self._list.SetStartEndText(start + os.linesep) + self._list.Start(250) + + def OnTaskComplete(self, evt): + """Update when task is complete + @param evt: UpdateBufferEvent + + """ + self._meth = None + + # Stop the timer + self._list.Stop() + self._cancelb.Disable() + + # Update statusbar to show search is complete + ed_msg.PostMessage(ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, _("Search complete"))) + + # Flush any remaining text to the output buffer + self._list.FlushBuffer() + + # Add our end message + lines = max(0, self._list.GetLineCount() - 2) + msg = _("Search Complete: %d matching lines where found.") % lines + msg2 = _("Files Searched: %d" % self._list.GetFileCount()) + end = u">>> %s \t%s" % (msg, msg2) + self._list.SetStartEndText(end + os.linesep) + + def OnThemeChange(self, msg): + """Update the button icons after the theme has changed + @param msg: Message Object + + """ + cbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DELETE), wx.ART_MENU) + self._clearb.SetBitmap(cbmp) + self._clearb.Refresh() + + cbmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_STOP), wx.ART_MENU) + self._cancelb.SetBitmap(cbmp) + self._cancelb.Refresh() + + def CancelSearch(self): + """Cancel the currently running search""" + if self._job is not None: + self._job.Cancel() + self._cancelb.Disable() + + def StartSearch(self, searchmeth, *args, **kwargs): + """Start a search with the given method and display the results + @param searchmeth: callable + @param *args: positional arguments to pass to searchmeth + @param **kwargs: keyword arguments to pass to searchmeth + + """ + self._meth = searchmeth + + if self._job is not None: + self._job.Cancel() + + self._list.Clear() + self._job = eclib.TaskObject(self._list, searchmeth, *args, **kwargs) + ed_thread.EdThreadPool().QueueJob(self._job.DoTask) + self._cancelb.Enable() + +#-----------------------------------------------------------------------------# + +class SearchResultList(eclib.OutputBuffer): + """Outputbuffer for listing matching lines from the search results that + a L{ebmlib.SearchEngine} dispatches. The matching lines are turned into + hotspots that allow them to be clicked on for instant navigation to the + matching line. + + """ + STY_SEARCH_MATCH = eclib.OPB_STYLE_MAX + 1 + RE_FIND_MATCH = re.compile('(.+) \(([0-9]+)\)\: .+') + def __init__(self, parent): + super(SearchResultList, self).__init__(parent) + + # Attributes + self._files = 0 + + # Setup + font = Profile_Get('FONT1', 'font', wx.Font(11, wx.FONTFAMILY_MODERN, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL)) + self.SetFont(font) + style = (font.GetFaceName(), font.GetPointSize(), "#FFFFFF") + self.StyleSetSpec(SearchResultList.STY_SEARCH_MATCH, + "face:%s,size:%d,fore:#000000,back:%s" % style) + self.StyleSetHotSpot(SearchResultList.STY_SEARCH_MATCH, True) + + def AppendUpdate(self, value): + """Do a little filtering of updates as they arrive + @param value: search result from search method + + """ + if isinstance(value, basestring): + # Regular search result + super(SearchResultList, self).AppendUpdate(value) + else: + # Search in a new file has started + self._files += 1 + + # Only updated status bar for every 10 files to reduce the overhead + # of updating the status bar and to improve performance of search. + if self._files == 1 or \ + ((self._files / 10) > ((self._files-1) / 10)): + wx.CallAfter(ed_msg.PostMessage, ed_msg.EDMSG_UI_SB_TXT, + (ed_glob.SB_INFO, + value[1])) # GetTranslation not thread safe (_("Searching in: %s") % ) + + def ApplyStyles(self, start, txt): + """Set a hotspot for each search result + Search matches strings should be formatted as follows + /file/name (line) match string + @param start: long + @param txt: string + + """ + self.StartStyling(start, 0x1f) + if re.match(SearchResultList.RE_FIND_MATCH, txt): + self.SetStyling(len(txt), SearchResultList.STY_SEARCH_MATCH) + else: + self.SetStyling(len(txt), eclib.OPB_STYLE_DEFAULT) + + def Clear(self): + """Override OutputBuffer.Clear""" + self._files = 0 + super(SearchResultList, self).Clear() + + def DoHotSpotClicked(self, pos, line): + """Handle a click on a hotspot and open the file to the matched line + @param pos: long + @param line: int + + """ + txt = self.GetLine(line) + match = re.match(SearchResultList.RE_FIND_MATCH, txt) + if match is not None: + groups = match.groups() + if len(groups) == 2: + fname, lnum = groups + if lnum.isdigit(): + lnum = int(lnum) - 1 + else: + lnum = 0 + self._OpenToLine(fname, lnum) + + def GetFileCount(self): + """Get the number of files searched in the previous/current search job. + @return: int + + """ + return self._files + + def SetStartEndText(self, txt): + """Add a start task or end task message to the output. Styled in + Info style. + @param txt: text to add + + """ + self.SetReadOnly(False) + cpos = self.GetLength() + self.AppendText(txt) + self.StartStyling(cpos, 0x1f) + self.SetStyling(self.GetLength() - cpos, eclib.OPB_STYLE_INFO) + self.SetReadOnly(True) + + @staticmethod + def _OpenToLine(fname, line): + """Open the given filename to the given line number + @param fname: File name to open, relative paths will be converted to abs + paths. + @param line: Line number to set the cursor to after opening the file + + """ + mainw = wx.GetApp().GetActiveWindow() + nbook = mainw.GetNotebook() + buffers = [ page.GetFileName() for page in nbook.GetTextControls() ] + if fname in buffers: + page = buffers.index(fname) + nbook.ChangePage(page) + cpage = nbook.GetPage(page) + else: + nbook.OnDrop([fname]) + cpage = nbook.GetPage(nbook.GetSelection()) + + cpage.GotoLine(line) + cpage.SetFocus() + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_session.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_session.py new file mode 100644 index 0000000..4f8e930 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_session.py @@ -0,0 +1,290 @@ +############################################################################### +# Name: ed_session.py # +# Purpose: Object to help manage editor sessions # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Editra session file manager. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_session.py 70097 2011-12-22 21:36:43Z CJP $" +__revision__ = "$Revision: 70097 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import os +import cPickle + +# Editra Imports +import util +import ed_cmdbar +import ed_glob +import profiler +import ed_msg +import ebmlib + +#-----------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation + +#-----------------------------------------------------------------------------# + +class SessionManager(object): + """Simple editing session manager helper class""" + def __init__(self, savedir): + """@param savedir: directory to load/save session files at""" + super(SessionManager, self).__init__() + + # Attributes + self.__default = '__default' # default session file name + self._sessiondir = savedir + self._sessionext = '.session' + + #---- Properties ----# + DefaultSession = property(lambda self: self.__default) + + SessionDir = property(lambda self: self._sessiondir, + lambda self, dpath: setattr(self, '_sessiondir', dpath)) + + def _SetExtension(self, ext): + assert ext.startswith('.') + self._sessionext = ext + SessionExtension = property(lambda self: self._sessionext, + lambda self, ext: self._SetExtension(ext)) + Sessions = property(lambda self: self.GetSavedSessions()) + + #---- Implementation ----# + + def DeleteSession(self, name): + """Delete the specified session name + @param name: session name + @return: bool + + """ + rval = True + session = self.PathFromSessionName(name) + if os.path.exists(session): + try: + os.remove(session) + except OSError: + rval = False + return rval + + def GetSavedSessions(self): + """Get the list of available saved sessions by display name + @return: list of strings + + """ + sessions = list() + defaultSession = None + for session in os.listdir(self.SessionDir): + if session.endswith(self.SessionExtension): + path = os.path.join(self.SessionDir, session) + sName = self.SessionNameFromPath(path) + if session.startswith(self.__default): + defaultSession = sName + else: + sessions.append(sName) + sessions.sort() + if defaultSession: + sessions.insert(0, defaultSession) + return sessions + + def LoadSession(self, name): + """Load a named session + @param name: session name + @return: list of paths + + """ + session = self.PathFromSessionName(name) + assert os.path.exists(session) + flist = list() + with open(session, 'rb') as f_handle: + # Load and validate file + try: + flist = cPickle.load(f_handle) + # TODO: Extend in future to support loading sessions + # for multiple windows. + flist = flist.get('win1', list()) + for item in flist: + if type(item) not in (unicode, str): + raise TypeError("Invalid item in unpickled sequence") + except (cPickle.UnpicklingError, TypeError, EOFError), e: + util.Log("[ed_session][err] %s" % e) + raise e # Re throw + return flist + + def SaveSession(self, name, paths): + """Save the given list of files as a session with the given name + @param name: session name + @param paths: list of file paths + @return: bool + + """ + session = self.PathFromSessionName(name) + bOk = False + with open(session, 'wb') as f_handle: + try: + # TODO multi window support + sdata = dict(win1=paths) + cPickle.dump(sdata, f_handle) + bOk = True + except Exception, msg: + util.Log("[ed_session][err] Failed to SaveSessionFile: %s" % msg) + + return bOk + + def PathFromSessionName(self, session): + """Get the full path to store a session file + @param session: string base name (no extension) + + """ + name = session + self.SessionExtension + path = os.path.join(self.SessionDir, name) + return path + + def SessionNameFromPath(self, path): + """Get the sessions display name from its path""" + assert path.endswith(self.SessionExtension) + name = os.path.basename(path) + name = name.rsplit('.', 1)[0] + return name + +#-----------------------------------------------------------------------------# + +class EdSessionMgr(SessionManager): + """Editra specific session manager implementation""" + __metaclass__ = ebmlib.Singleton + def __init__(self): + super(EdSessionMgr, self).__init__(ed_glob.CONFIG['SESSION_DIR']) + +#-----------------------------------------------------------------------------# + +class EdSessionBar(ed_cmdbar.CommandBarBase): + """Command bar for managing editing sessions""" + class meta: + id = ed_glob.ID_SESSION_BAR + + def __init__(self, parent): + super(EdSessionBar, self).__init__(parent) + + # Attributes + self._sch = wx.Choice(self) + + # Setup + self.__DoLayout() + self._saveb = self.AddPlateButton(_("Save"), ed_glob.ID_SAVE) + self._saveb.Name = "SaveButton" + self._saveasb = self.AddPlateButton(_("Save As"), ed_glob.ID_SAVEAS) + self._saveasb.Name = "SaveAsButton" + self._delb = self.AddPlateButton(_("Delete"), ed_glob.ID_DELETE) + self._delb.Name = "DeleteButton" + self.UpdateSessionList() + + # Event Handlers + self._saveb.Bind(wx.EVT_BUTTON, self.OnSaveSession) + self._saveasb.Bind(wx.EVT_BUTTON, self.OnSaveSession) + self._delb.Bind(wx.EVT_BUTTON, self.OnDeleteSession) + self._sch.Bind(wx.EVT_CHOICE, self.OnChangeSession) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, self._delb) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) + + # Message Handlers + ed_msg.Subscribe(self.OnConfigMsg, + ed_msg.EDMSG_PROFILE_CHANGE + ('LAST_SESSION',)) + + def __DoLayout(self): + self.AddControl(wx.StaticText(self, label=_("Session:")), wx.ALIGN_LEFT) + self.AddControl(self._sch, wx.ALIGN_LEFT) + + def OnDestroy(self, evt): + """Cleanup message handlers""" + if self: + ed_msg.Unsubscribe(self.OnConfigMsg) + evt.Skip() + + def GetSelectedSession(self): + """Get the currently selected session + @return: string (internal session name) + + """ + if self._sch.Selection == 0: + return EdSessionMgr().DefaultSession + else: + return self._sch.StringSelection + + def OnChangeSession(self, evt): + """Current session changed in choice control""" + util.Log(u"[ed_session][info] OnChangeSession: %s" % self._sch.StringSelection) + ed_msg.PostMessage(ed_msg.EDMSG_SESSION_DO_LOAD, + self.GetSelectedSession(), + self.TopLevelParent.Id) + + def OnConfigMsg(self, msg): + """Configuration update callback""" + if self: + self.UpdateSessionList() + + def OnSaveSession(self, evt): + """Save the current session""" + ofiles = list() + util.Log("[ed_session][info] OnSaveSession") + if evt.EventObject is self._saveb: + ed_msg.PostMessage(ed_msg.EDMSG_FILE_GET_OPENED, ofiles, + self.TopLevelParent.Id) + util.Log("[ed_session][info] OnSaveSession: %d files" % len(ofiles)) + EdSessionMgr().SaveSession(self.GetSelectedSession(), ofiles) + elif evt.EventObject is self._saveasb: + ed_msg.PostMessage(ed_msg.EDMSG_SESSION_DO_SAVE, + context=self.TopLevelParent.Id) + # Bar will be updated by config change if the save succeeds + else: + evt.Skip() + + def OnDeleteSession(self, evt): + """Delete the current session""" + if evt.EventObject is self._delb: + ses = self.GetSelectedSession() + if ses != EdSessionMgr().DefaultSession: + EdSessionMgr().DeleteSession(ses) + # Switch back to default session + profiler.Profile_Set('LAST_SESSION', + EdSessionMgr().DefaultSession) + else: + evt.Skip() + + def OnBarShown(self): + """Update the session list""" + self.UpdateSessionList() + + def OnUpdateUI(self, evt): + """Handle UpdateUI events""" + if evt.EventObject is self._delb: + evt.Enable(self._sch.Selection > 0) + else: + evt.Skip() + + def UpdateSessionList(self): + """Update the session list""" + sessions = EdSessionMgr().Sessions + if len(sessions): + sessions[0] = _("Default") + self._sch.Items = sessions + self.UpdateSelectedSession() + self.Layout() + self.Refresh() + + def UpdateSelectedSession(self): + """Select the currently configured session""" + ses = profiler.Profile_Get('LAST_SESSION') + if ses: + if ses == EdSessionMgr().DefaultSession: + self._sch.SetSelection(0) + elif ses in self._sch.Items: + self._sch.SetStringSelection(ses) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_shelf.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_shelf.py new file mode 100644 index 0000000..75b587c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_shelf.py @@ -0,0 +1,677 @@ +############################################################################### +# Name: ed_shelf.py # +# Purpose: Editra Shelf container # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Shelf plugin and control implementation + +@summary: Shelf Implementation + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_shelf.py 72821 2012-10-29 22:48:49Z CJP $" +__revision__ = "$Revision: 72821 $" + +#-----------------------------------------------------------------------------# +# Imports +import re +import wx + +# Editra Imports +import ed_menu +import ed_glob +from profiler import Profile_Get +import ed_msg +import plugin +import iface +import ed_fmgr +from extern import aui +import ed_book +import ebmlib + +#--------------------------------------------------------------------------# +# Globals +PGNUM_PAT = re.compile(' - [0-9]+') +_ = wx.GetTranslation + +#-----------------------------------------------------------------------------# + +class Shelf(plugin.Plugin): + """Plugin that creates a notebook for holding the various Shelf items + implemented by L{ShelfI}. + + """ + SHELF_NAME = u'Shelf' + observers = plugin.ExtensionPoint(iface.ShelfI) + + def GetUiHandlers(self, delegate): + """Gets the update ui handlers for the shelf's menu + @param delegate: L{EdShelfDelegate} instance + @return: [(ID, handler),] + + """ + handlers = [ (item.GetId(), delegate.UpdateShelfMenuUI) + for item in self.observers ] + return handlers + + def Init(self, parent): + """Mixes the shelf into the parent window + @param parent: Reference to MainWindow + @return: L{EdShelfDelegate} + + """ + # First check if the parent has an instance already + mgr = parent.GetFrameManager() + if mgr.GetPane(Shelf.SHELF_NAME).IsOk(): + return + + # HACK - fixes mouse event issues that result in wrong + # tab indexes being reported in the notebook. + wrapper = ShelfWrapper(parent) + shelf = wrapper.GetShelf() + mgr.AddPane(wrapper, + ed_fmgr.EdPaneInfo().Name(Shelf.SHELF_NAME).\ + Caption(_("Shelf")).Bottom().Layer(0).\ + CloseButton(True).MaximizeButton(True).\ + BestSize(wx.Size(500,250))) + + # Hide the pane and let the perspective manager take care of it + mgr.GetPane(Shelf.SHELF_NAME).Hide() + mgr.Update() + + # Create the delegate + delegate = EdShelfDelegate(shelf, self) + + # Install Shelf menu under View and bind event handlers + view = parent.GetMenuBar().GetMenuByName("view") + menu = delegate.GetMenu() + pos = 0 + for pos in range(view.GetMenuItemCount()): + mitem = view.FindItemByPosition(pos) + if mitem.GetId() == ed_glob.ID_PERSPECTIVES: + break + + view.InsertMenu(pos + 1, ed_glob.ID_SHELF, _("Shelf"), + menu, _("Put an item on the Shelf")) + + for item in menu.GetMenuItems(): + if item.IsSeparator(): + continue + parent.Bind(wx.EVT_MENU, delegate.OnGetShelfItem, item) + + if menu.GetMenuItemCount() < 3: + view.Enable(ed_glob.ID_SHELF, False) + + # Check for any other plugin specific install needs + for observer in self.observers: + if not observer.IsInstalled() and \ + hasattr(observer, 'InstallComponents'): + observer.InstallComponents(parent) + + # Only Load Perspective if all items are loaded + if delegate.StockShelf(Profile_Get('SHELF_ITEMS', 'list', [])): + delegate.SetPerspective(Profile_Get('SHELF_LAYOUT', 'str', u"")) + delegate.SetSelection(Profile_Get('SHELF_SELECTION', 'int', -1)) + return delegate + +#--------------------------------------------------------------------------# + +class EdShelfBook(ed_book.EdBaseBook): + ID_SHELF_SUBMENU = wx.NewId() + ID_CLOSE_LIKE_TABS = wx.NewId() + """Shelf notebook control""" + def __init__(self, parent): + style = aui.AUI_NB_BOTTOM | \ + aui.AUI_NB_TAB_SPLIT | \ + aui.AUI_NB_SCROLL_BUTTONS | \ + aui.AUI_NB_CLOSE_ON_ACTIVE_TAB | \ + aui.AUI_NB_TAB_MOVE | \ + aui.AUI_NB_DRAW_DND_TAB + super(EdShelfBook, self).__init__(parent, style=style) + + # Attributes + self._open = dict() + self._name2idx = dict() # For settings maintenance + self._menu = ebmlib.ContextMenuManager() + self._mcback = None + self._mw = None + + # Event Handlers + # HACK: binding to self works differently than parent catching it + # binding here causes incorrect mouse coords to be sent to + # event handler during click events! +# self.Bind(aui.EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabRightUp) + self.Bind(aui.EVT_AUINOTEBOOK_BG_RIGHT_UP, self.OnBgRightUp) + self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnItemClose) + self.Bind(wx.EVT_MENU, self.OnTabMenu) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + + # Message handlers + ed_msg.Subscribe(self.OnUpdateTabs, ed_msg.EDMSG_THEME_NOTEBOOK) + ed_msg.Subscribe(self.OnUpdateTabs, ed_msg.EDMSG_THEME_CHANGED) + + def OnDestroy(self, evt): + if evt.GetId() == self.GetId(): + self._menu.Clear() + ed_msg.Unsubscribe(self.OnUpdateTabs) + evt.Skip() + + def OnTabRightUp(self, evt): + """Tab right click handler""" + self._menu.Clear() + if self.MenuCallback: + sel = self.GetPageIndex(evt.Page) + s_lbl = self.GetPageText(sel) + s_lbl = s_lbl.rsplit('-')[0].strip() + tab_menu = ed_menu.EdMenu() + tab_menu.Append(EdShelfBook.ID_CLOSE_LIKE_TABS, + _("Close All '%s'") % s_lbl) + self._menu.AddHandler(EdShelfBook.ID_CLOSE_LIKE_TABS, + lambda tab, evt: self.CloseAll(s_lbl)) + tab_menu.AppendSeparator() + shelf_menu = self.MenuCallback() + tab_menu.AppendMenu(EdShelfBook.ID_SHELF_SUBMENU, + _("Open"), shelf_menu) + self._menu.Menu = tab_menu + self.PopupMenu(self._menu.Menu) + + def OnBgRightUp(self, evt): + """Show context menu""" + self._menu.Clear() + if self.MenuCallback: + self._menu.Menu = self.MenuCallback() + self.PopupMenu(self._menu.Menu) + + def OnTabMenu(self, evt): + """Handle tab menu events""" + handler = self._menu.GetHandler(evt.Id) + if handler is not None: + handler(self.GetCurrentPage(), evt) + else: + evt.Skip() + + MainWindow = property(lambda self: self._mw, + lambda self, mw: setattr(self, '_mw', mw)) + BitmapCallbacks = property(lambda self: self._name2idx) + MenuCallback = property(lambda self: self._mcback, + lambda self, funct: setattr(self, '_mcback', funct)) + + def AddItem(self, item, name, bmp=wx.NullBitmap): + """Add an item to the shelf's notebook. This is useful for interacting + with the Shelf from outside its interface. It may be necessary to + call L{EnsureShelfVisible} before or after adding an item if you wish + the shelf to be shown when the item is added. + @param item: A panel like instance to add to the shelf's notebook + @param name: Items name used for page text in notebook + @keyword bmp: Tab bitmap to display + + """ + self.AddPage(item, + u"%s - %d" % (name, self._open.get(name, 0)), + select=True) + + # Set the tab icon + self.SetPageBitmap(self.GetPageCount()-1, bmp) + self._open[name] = self._open.get(name, 0) + 1 + + def OnItemClose(self, evt): + """Callback for when pages are closed""" +# name = self.GetPageText(evt.GetSelection()) +# name = name.rsplit('-')[0].strip() +# self._open[name] = self._open.get(name, 1) - 1 + evt.Skip() + + def CloseAll(self, name): + """Close all of 'name' shelf items + @param name: shelf item name (string) + + """ + idxs = self.GetAllIndexes(name) + idxs.reverse() + for idx in idxs: + self.DeletePage(idx) + + def GetAllIndexes(self, name): + """Get all the indexes of pages of the item identified + by 'name'. + @param name: shelf item name (string) + + """ + idxs = list() + for pg in range(self.GetPageCount()): + lbl = self.GetPageText(pg) + lbl = PGNUM_PAT.sub(u"", lbl) + if lbl == name: + idxs.append(pg) + return idxs + + def EnsureShelfVisible(self): + """Make sure the Shelf is visible + @precondition: Shelf.Init has been called + @postcondition: Shelf is shown + + """ + mgr = self.MainWindow.GetFrameManager() + pane = mgr.GetPane(Shelf.SHELF_NAME) + if not pane.IsShown(): + pane.Show() + mgr.Update() + + def GetCount(self, item_name): + """Get the number of open instances of a given Shelf Item + @param item_name: Name of the Shelf item + @return: number of instances on the Shelf + + """ + count = 0 + for page in range(self.GetPageCount()): + if self.GetPageText(page).startswith(item_name): + count = count + 1 + return count + + def GetMainWindow(self): + """Get the main window that this shelf instance was created for + @return: ed_main.MainWindow + + """ + return self.MainWindow + + def GetOpen(self): + """Get the list of open shelf items + @return: list + + """ + return self._open + + def Hide(self): + """Hide the shelf + @postcondition: Shelf is hidden by aui manager + + """ + mgr = self.MainWindow.GetFrameManager() + pane = mgr.GetPane(Shelf.SHELF_NAME) + if pane.IsOk(): + pane.Hide() + mgr.Update() + + def ItemIsOnShelf(self, item_name): + """Check if at least one instance of a given item + is currently on the Shelf. + @param item_name: name of Item to look for + + """ + for page in range(self.GetPageCount()): + if self.GetPageText(page).startswith(item_name): + return True + return False + + def IsShown(self): + """Is the shelf visible? + @return: bool + + """ + mgr = self.MainWindow.GetFrameManager() + pane = mgr.GetPane(Shelf.SHELF_NAME) + if pane.IsOk(): + return pane.IsShown() + else: + return False + + def OnUpdateTabs(self, msg): + """Update all tab images depending upon current settings""" + if not self: + return + + if not Profile_Get('TABICONS', default=True): + for page in range(self.GetPageCount()): + self.SetPageBitmap(page, wx.NullBitmap) + else: + # Show the icons + for pnum in range(self.GetPageCount()): + page = self.GetPage(pnum) + bmp = self.BitmapCallbacks.get(repr(page.__class__), lambda:wx.NullBitmap)() + self.SetPageBitmap(pnum, bmp) + +#--------------------------------------------------------------------------# + +class EdShelfDelegate(object): + """Delegate class to mediate between the plugin singleton object and the + UI implementation. + + """ + def __init__(self, shelf, pobject): + """Create the delegate object + @param shelf: Ui component instance + @param pobject: Reference to the plugin object + + """ + super(EdShelfDelegate, self).__init__() + + # Attributes + self._log = wx.GetApp().GetLog() + self._shelf = shelf + self._pin = pobject + + # Setup + self._shelf.MenuCallback = getattr(self, 'GetShelfObjectMenu') + + @property + def observers(self): + return self._pin.observers + + def AddItem(self, item, name, bmp=wx.NullBitmap): + """Add an item to the shelf""" + self._shelf.AddItem(item, name, bmp) + + def CanStockItem(self, item_name): + """See if a named item can be stocked or not, meaning if it + can be saved and opened in the next session or not. + @param item_name: name of item to check + @return: bool whether item can be stocked or not + + """ + for item in self.observers: + if item_name == item.GetName(): + if hasattr(item, 'IsStockable'): + return item.IsStockable() + else: + break + return False + + def EnsureShelfVisible(self): + """Ensure the shelf is visible""" + self._shelf.EnsureShelfVisible() + + def GetItemById(self, itemid): + """Get the shelf item by its id + @param itemid: Shelf item id + @return: reference to a ShelfI object + + """ + for item in self.observers: + if item.GetId() == itemid: + return item + return None + + def GetItemId(self, item_name): + """Get the id that identifies a given item + @param item_name: name of item to get ID for + @return: integer id or None if not found + + """ + for item in self.observers: + if item_name == item.GetName(): + return item.GetId() + return None + + def GetItemStack(self): + """Returns a list of ordered named items that are open in the shelf + @return: list of strings + + """ + rval = list() + if self._shelf is not None: + for page in range(self._shelf.GetPageCount()): + rval.append(re.sub(PGNUM_PAT, u'', + self._shelf.GetPageText(page), 1)) + return rval + + def GetSelection(self): + """Get the index of the currently selected tab""" + if self._shelf: + return self._shelf.GetSelection() + return -1 + + def GetPerspective(self): + """Get the auinotebook perspective data + @return: string + + """ + return self._shelf.SavePerspective() + + def SetPerspective(self, pdata): + """Set the aui notebooks perspective and layout + @param pdata: perspective data string + + """ + if pdata: + try: + self._shelf.LoadPerspective(pdata) + self._shelf.Update() + except Exception, msg: + self._log("[shelf][err] Failed LoadPerspective: %s" % msg) + + def GetShelfObjectMenu(self): + """Get the minimal menu that lists all Shelf objects + without the 'Show Shelf' item. + @return: ed_menu.EdMenu + + """ + menu = ed_menu.EdMenu() + menu_items = list() + open_items = self._shelf.GetOpen() + for observer in self.observers: + # Register Observers + open_items[observer.GetName()] = 0 + try: + menu_i = observer.GetMenuEntry(menu) + if menu_i is not None: + menu_items.append((menu_i.GetItemLabel(), menu_i)) + except Exception, msg: + self._log("[shelf][err] %s" % str(msg)) + menu_items.sort() + + combo = 0 + for item in menu_items: + combo += 1 + shortcut = u"" + if combo < 10: + shortcut = u"\tCtrl+Alt+" + unicode(combo) + nitem = menu.Append(item[1].Id, item[1].GetText() + shortcut) + if item[1].Bitmap.IsOk(): + nitem.SetBitmap(item[1].Bitmap) + item[1].Destroy() + return menu + + def GetMenu(self): + """Return the menu of this object + @return: ed_menu.EdMenu() + + """ + menu = self.GetShelfObjectMenu() + menu.Insert(0, wx.ID_SEPARATOR) + menu.Insert(0, ed_glob.ID_SHOW_SHELF, _("Show Shelf") + \ + ed_menu.EdMenuBar.keybinder.GetBinding(ed_glob.ID_SHOW_SHELF), + _("Show the Shelf")) + return menu + + def GetOwnerWindow(self): + """Return the L{ed_main.MainWindow} instance that owns/created + this Shelf. + @return: reference to ed_main.MainWindow or None + + """ + return self._shelf.GetMainWindow() + + def GetWindow(self): + """Return reference to the Shelfs window component + @return: AuiNotebook + + """ + return self._shelf + + def OnGetShelfItem(self, evt): + """Handles menu events that have been registered + by the Shelf Items on the Shelf. + @param evt: Event that called this handler + + """ + e_id = evt.GetId() + if e_id == ed_glob.ID_SHOW_SHELF: + parent = self.GetOwnerWindow() + if self._shelf.IsShown(): + self._shelf.Hide() + nb = parent.GetNotebook() + nb.GetCurrentCtrl().SetFocus() + else: + self._shelf.EnsureShelfVisible() + mgr = parent.GetFrameManager() + pane = mgr.GetPane(Shelf.SHELF_NAME) + if pane is not None: + page = pane.window.Book.GetCurrentPage() + if hasattr(page, 'SetFocus'): + page.SetFocus() + else: + self.PutItemOnShelf(evt.GetId()) + + def OnPutShelfItemAway(self, evt): + """Handles when an item is closed + @param evt: event that called this handler + @todo: is this needed? + + """ + raise NotImplementedError + + def PutItemOnShelf(self, shelfid): + """Put an item on the shelf by using its unique shelf id. + This is only for use with loading items implementing the + L{ShelfI} interface. See L{AddItem} if you wish to pass + a panel to the shelf to add. + @param shelfid: id of the ShelfItem to open + + """ + item = None + for shelfi in self.observers: + if shelfi.GetId() == shelfid: + item = shelfi + break + + if item is None: + return + + name = item.GetName() + if self._shelf.ItemIsOnShelf(name) and \ + not item.AllowMultiple() or self._shelf is None: + return + else: + self.EnsureShelfVisible() + # Guard against crashes in creating plugin derived objects + # log error to log and continue running. + window = None + try: + window = item.CreateItem(self._shelf) + except Exception, msg: + self._log("[shelf][err] CreateItem failed: %s" % msg) + return + + bmp = wx.NullBitmap + if hasattr(item, 'GetBitmap'): + self._shelf.BitmapCallbacks[repr(window.__class__)] = item.GetBitmap + bmp = item.GetBitmap() + else: + self._shelf.BitmapCallbacks[repr(window.__class__)] = lambda:wx.NullBitmap + self.AddItem(window, name, bmp) + + def RaiseItem(self, item_name): + """Set the selection in the notebook to be the that of the first + instance of item_name that is found in the shelf. + @param item_name: ShelfI name + @return: reference to the selected page or None if no instance is + + """ + for page in range(self._shelf.GetPageCount()): + if self._shelf.GetPageText(page).startswith(item_name): + self._shelf.SetSelection(page) + return self._shelf.GetPage(page) + else: + return None + + def RaiseWindow(self, window): + """Set the selection in the notebook to be the that of the given + window. Mostly used internally by items implementing L{ShelfI}. + @param window: Window object + @return: reference to the selected page or None if no instance is + + """ + for page in range(self._shelf.GetPageCount()): + ctrl = self._shelf.GetPage(page) + if window == ctrl: + self._shelf.SetSelection(page) + return ctrl + else: + return None + + def SetSelection(self, index): + """Select an item in the Shelf window + @param index: shelf tab index + + """ + if self._shelf and index > 0 and index < self._shelf.GetPageCount(): + try: + self._shelf.SetSelection(index) + except Exception, msg: + self._log("[shelf][err] Failed SetSelection: %s" % msg) + + def StockShelf(self, i_list): + """Fill the shelf by opening an ordered list of items + @param i_list: List of named L{ShelfI} instances + @return: bool (True if all loaded / False otherwise) + + """ + bLoaded = True + for item in i_list: + if self.CanStockItem(item): + itemid = self.GetItemId(item) + if itemid: + self.PutItemOnShelf(itemid) + else: + bLoaded = False + else: + bLoaded = False + return bLoaded + + def UpdateShelfMenuUI(self, evt): + """Enable/Disable shelf items based on whether they support + muliple instances or not. + @param evt: wxEVT_UPDATEUI + + """ + item = self.GetItemById(evt.GetId()) + if item is None: + evt.Skip() + return + + count = self._shelf.GetCount(item.GetName()) + if count and not item.AllowMultiple(): + evt.Enable(False) + else: + evt.Enable(True) + +#-----------------------------------------------------------------------------# + +class ShelfWrapper(wx.Panel): + def __init__(self, parent): + super(ShelfWrapper, self).__init__(parent) + + self._shelf = EdShelfBook(self) + self._shelf.MainWindow = parent + + # Setup + sizer = wx.BoxSizer() + sizer.Add(self._shelf, 1, wx.EXPAND) + self.SetSizer(sizer) + + self.Bind(aui.EVT_AUINOTEBOOK_TAB_RIGHT_UP, self.OnTabRightUp) + + Book = property(lambda self: self._shelf) + + def GetShelf(self): + return self._shelf + + def OnTabRightUp(self, evt): + self._shelf.OnTabRightUp(evt) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_statbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_statbar.py new file mode 100644 index 0000000..3aef323 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_statbar.py @@ -0,0 +1,326 @@ +############################################################################### +# Name: ed_statbar.py # +# Purpose: Custom statusbar with builtin progress indicator # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Custom StatusBar for Editra that contains a progress bar that responds to +messages from ed_msg to display progress of different actions. + +@summary: Editra's StatusBar class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_statbar.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Imports +import wx +import wx.stc + +# Editra Libraries +import ed_glob +import util +import ed_msg +import ed_menu +from syntax.synglob import GetDescriptionFromId +from eclib import ProgressStatusBar, EncodingDialog +from extern.decorlib import anythread + +#--------------------------------------------------------------------------# + +_ = wx.GetTranslation + +#--------------------------------------------------------------------------# + +class EdStatBar(ProgressStatusBar): + """Custom status bar that handles dynamic field width adjustment and + automatic expiration of status messages. + + """ + ID_CLEANUP_TIMER = wx.NewId() + def __init__(self, parent): + super(EdStatBar, self).__init__(parent, style=wx.ST_SIZEGRIP) + + # Attributes + self._pid = parent.GetId() # Save parents id for filtering msgs + self._widths = list() + self._cleanup_timer = wx.Timer(self, EdStatBar.ID_CLEANUP_TIMER) + self._eolmenu = wx.Menu() + self._lexmenu = None + self._log = wx.GetApp().GetLog() + + # Setup + self.SetFieldsCount(6) # Info, vi stuff, line/progress + self.SetStatusWidths([-1, 90, 40, 40, 40, 155]) + self._eolmenu.Append(ed_glob.ID_EOL_MAC, u"CR", + _("Change line endings to %s") % u"CR", + kind=wx.ITEM_CHECK) + self._eolmenu.Append(ed_glob.ID_EOL_WIN, u"CRLF", + _("Change line endings to %s") % u"CRLF", + kind=wx.ITEM_CHECK) + self._eolmenu.Append(ed_glob.ID_EOL_UNIX, u"LF", + _("Change line endings to %s") % u"LF", + kind=wx.ITEM_CHECK) + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_TIMER, self.OnExpireMessage, + id=EdStatBar.ID_CLEANUP_TIMER) + + # Messages + ed_msg.Subscribe(self.OnProgress, ed_msg.EDMSG_PROGRESS_SHOW) + ed_msg.Subscribe(self.OnProgress, ed_msg.EDMSG_PROGRESS_STATE) + ed_msg.Subscribe(self.OnUpdateText, ed_msg.EDMSG_UI_SB_TXT) + ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_UI_NB_CHANGED) + ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_FILE_SAVED) + ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_FILE_OPENED) + ed_msg.Subscribe(self.OnUpdateDoc, ed_msg.EDMSG_UI_STC_LEXER) + + def OnDestroy(self, evt): + """Unsubscribe from messages""" + if self._lexmenu: + self._lexmenu.Destroy() + if self._eolmenu: + self._eolmenu.Destroy() + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.OnProgress) + ed_msg.Unsubscribe(self.OnUpdateText) + ed_msg.Unsubscribe(self.OnUpdateDoc) + evt.Skip() + + def __SetStatusText(self, txt, field): + """Safe method to use for setting status text with CallAfter. + @param txt: string + @param field: int + + """ + try: + super(EdStatBar, self).SetStatusText(txt, field) + self.AdjustFieldWidths() + + if field == ed_glob.SB_INFO and txt != u'': + # Start the expiration countdown + if self._cleanup_timer.IsRunning(): + self._cleanup_timer.Stop() + self._cleanup_timer.Start(10000, True) + except wx.PyDeadObjectError, wx.PyAssertionError: + # Getting some odd assertion errors on wxMac so just trap + # and ignore them for now + # glyphCount == (text.length()+1)" failed at graphics.cpp(2048) + # in GetPartialTextExtents() + pass + except TypeError, err: + self._log("[edstatbar][err] Bad status message: %s" % str(txt)) + self._log("[edstatbar][err] %s" % err) + + def AdjustFieldWidths(self): + """Adjust each field width of status bar basing on the field text + @return: None + + """ + widths = [-1] + # Calculate required widths + # NOTE: Order of fields is important + for field in [ed_glob.SB_BUFF, + ed_glob.SB_LEXER, + ed_glob.SB_ENCODING, + ed_glob.SB_EOL, + ed_glob.SB_ROWCOL]: + width = self.GetTextExtent(self.GetStatusText(field))[0] + 20 + if width == 20: + width = 0 + widths.append(width) + + # Adjust widths + if widths[-1] < 155: + widths[-1] = 155 + + # Only update if there are changes + if widths != self._widths: + self._widths = widths + self.SetStatusWidths(self._widths) + + def GetMainWindow(self): + """Method required for L{ed_msg.mwcontext}""" + return self.TopLevelParent + + def OnExpireMessage(self, evt): + """Handle Expiring the status message when the oneshot timer + tells us it has expired. + + """ + if evt.GetId() == EdStatBar.ID_CLEANUP_TIMER: + wx.CallAfter(self.__SetStatusText, u'', ed_glob.SB_INFO) + else: + evt.Skip() + + def OnLeftDClick(self, evt): + """Handlers mouse left double click on status bar + @param evt: wx.MouseEvent + @note: Assumes parent is MainWindow instance + + """ + pt = evt.GetPosition() + if self.GetFieldRect(ed_glob.SB_ROWCOL).Contains(pt): + mw = self.GetParent() + mpane = mw.GetEditPane() + mpane.ShowCommandControl(ed_glob.ID_GOTO_LINE) + else: + evt.Skip() + + def OnLeftUp(self, evt): + """Handle left clicks on the status bar + @param evt: wx.MouseEvent + + """ + pt = evt.GetPosition() + if self.GetFieldRect(ed_glob.SB_EOL).Contains(pt): + rect = self.GetFieldRect(ed_glob.SB_EOL) + self.PopupMenu(self._eolmenu, (rect.x, rect.y)) + elif self.GetFieldRect(ed_glob.SB_ENCODING).Contains(pt): + nb = self.GetTopLevelParent().GetNotebook() + buff = nb.GetCurrentCtrl() + dlg = EncodingDialog(nb, + msg=_("Change the encoding of the current document."), + title=_("Change Encoding"), + default=buff.GetEncoding()) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DOCPROP), + wx.ART_OTHER) + if bmp.IsOk(): + dlg.SetBitmap(bmp) + dlg.CenterOnParent() + + # TODO: should add EdFile callbacks for modification events instead + # of using explicit statusbar refresh. + if dlg.ShowModal() == wx.ID_OK: + buff.SetEncoding(dlg.GetEncoding()) + self.UpdateFields() + + # NOTE: Got an error report about a PyDeadObject error here. The + # error does not make any sense since the dialog is not + # destroyed or deleted by anything before this. Add validity + # check to ensure reference is still valid. + if dlg: + dlg.Destroy() + elif self.GetFieldRect(ed_glob.SB_LEXER).Contains(pt): + # Change Lexer popup menu + if self._lexmenu: + self._lexmenu.Destroy() + self._lexmenu = wx.Menu() + ed_menu.EdMenuBar.PopulateLexerMenu(self._lexmenu) + rect = self.GetFieldRect(ed_glob.SB_LEXER) + self.PopupMenu(self._lexmenu, (rect.x, rect.y)) + else: + evt.Skip() + + def OnProgress(self, msg): + """Set the progress bar's state + @param msg: Message Object + + """ + mdata = msg.GetData() + # Don't do anything if the message is not for this frame + if self._pid != mdata[0]: + return + + mtype = msg.GetType() + if mtype == ed_msg.EDMSG_PROGRESS_STATE: + # May be called from non gui thread so don't do anything with + # the gui here. + self.SetProgress(mdata[1]) + self.range = mdata[2] + if sum(mdata[1:]) == 0: + self.Stop() + elif mtype == ed_msg.EDMSG_PROGRESS_SHOW: + if mdata[1]: + self.Start(75) + else: + # TODO: findout where stray stop event is coming from... + self.Stop() + + @ed_msg.mwcontext + def OnUpdateDoc(self, msg): + """Update document related fields + @param msg: Message Object + + """ + self.UpdateFields() + if msg.GetType() == ed_msg.EDMSG_UI_NB_CHANGED: + wx.CallAfter(self.__SetStatusText, u'', ed_glob.SB_INFO) + + @anythread + def DoUpdateText(self, msg): + """Thread safe update of status text. Proxy for OnUpdateText because + pubsub seems to have issues with passing decorator methods for + listeners. + @param msg: Message Object + + """ + # Only process if this status bar is in the active window and shown + parent = self.GetTopLevelParent() + if (parent.IsActive() or wx.GetApp().GetTopWindow() == parent): + field, txt = msg.GetData() + self.UpdateFields() + wx.CallAfter(self.__SetStatusText, txt, field) + + def OnUpdateText(self, msg): + """Update the status bar text based on the received message + @param msg: Message Object + + """ + self.DoUpdateText(msg) + + def PushStatusText(self, txt, field): + """Set the status text + @param txt: Text to put in bar + @param field: int + + """ + wx.CallAfter(self.__SetStatusText, txt, field) + + def SetStatusText(self, txt, field): + """Set the status text + @param txt: Text to put in bar + @param field: int + + """ + wx.CallAfter(self.__SetStatusText, txt, field) + + def UpdateFields(self): + """Update document fields based on the currently selected + document in the editor. + @postcondition: encoding and lexer fields are updated + @todo: update when readonly hooks are implemented + + """ + nb = self.GetParent().GetNotebook() + if nb is None: + return + + try: + cbuff = nb.GetCurrentCtrl() + doc = cbuff.GetDocument() + wx.CallAfter(self.__SetStatusText, doc.GetEncoding(), + ed_glob.SB_ENCODING) + wx.CallAfter(self.__SetStatusText, + GetDescriptionFromId(cbuff.GetLangId()), + ed_glob.SB_LEXER) + + eol = { wx.stc.STC_EOL_CR : u"CR", + wx.stc.STC_EOL_LF : u"LF", + wx.stc.STC_EOL_CRLF : u"CRLF" } + wx.CallAfter(self.__SetStatusText, + eol[cbuff.GetEOLMode()], + ed_glob.SB_EOL) + + except wx.PyDeadObjectError: + # May be called asyncronasly after the control is already dead + return diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_stc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_stc.py new file mode 100644 index 0000000..1ee2178 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_stc.py @@ -0,0 +1,1969 @@ +############################################################################### +# Name: ed_stc.py # +# Purpose: Editra's styled editing buffer # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This is the main component of the editor that manages all the information +of the on disk file that it represents in memory. It works with the StyleManager +and SyntaxManager to provide an editing pane that auto detects and configures +itself for type of file that is in buffer to do highlighting and other language +specific options such as commenting code. + +@summary: Editra's main text buffer class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_stc.py 73712 2013-03-23 14:46:09Z CJP $" +__revision__ = "$Revision: 73712 $" + +#-------------------------------------------------------------------------# +# Imports + +import os +import wx, wx.stc + +# Local Imports +import ed_event +import ed_glob +from profiler import Profile_Get as _PGET +from syntax import syntax +import util +import ed_basestc +import ed_marker +import ed_msg +import ed_mdlg +import ed_txt +from ed_keyh import KeyHandler, ViKeyHandler +import eclib +import ebmlib +import ed_thread + +#-------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation + +# EOL Constants +EDSTC_EOL_CR = ed_glob.EOL_MODE_CR +EDSTC_EOL_LF = ed_glob.EOL_MODE_LF +EDSTC_EOL_CRLF = ed_glob.EOL_MODE_CRLF + +# Character sets +SPACECHARS = " \t\r\n" +NONSPACE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" +OPERATORS = "./\?[]{}<>!@#$%^&*():=-+\"';," + +#-------------------------------------------------------------------------# + +def jumpaction(func): + """Decorator method to notify clients about jump actions""" + def WrapJump(*args, **kwargs): + """Wrapper for capturing before/after pos of a jump action""" + try: + stc = args[0] + pos = stc.GetCurrentPos() + line = stc.GetCurrentLine() + func(*args, **kwargs) + cpos = stc.GetCurrentPos() + cline = stc.GetCurrentLine() + fname = stc.GetFileName() + + mdata = dict(fname=fname, + prepos=pos, preline=line, + lnum=cline, pos=cpos) + tlw = stc.TopLevelParent + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_POS_JUMPED, mdata, tlw.Id) + except wx.PyDeadObjectError: + pass + + WrapJump.__name__ = func.__name__ + WrapJump.__doc__ = func.__doc__ + return WrapJump + + +#-------------------------------------------------------------------------# + +class EditraStc(ed_basestc.EditraBaseStc): + """Defines a styled text control for editing text + @summary: Subclass of wx.stc.StyledTextCtrl and L{ed_style.StyleMgr}. + Manages the documents display and input. + + """ + def __init__(self, parent, id_, + pos=wx.DefaultPosition, size=wx.DefaultSize, + style=0, use_dt=True): + """Initializes a control and sets the default objects for + Tracking events that occur in the control. + @param parent: Parent Window + @param id_: Control ID + @keyword pos: Control position + @keyword size: Control size + @keyword style: Control style bitmask + @keyword use_dt: whether to use a drop target or not + + """ + super(EditraStc, self).__init__(parent, id_, pos, size, style) + + self.SetModEventMask(wx.stc.STC_PERFORMED_UNDO | \ + wx.stc.STC_PERFORMED_REDO | \ + wx.stc.STC_MOD_DELETETEXT | \ + wx.stc.STC_MOD_INSERTTEXT) + + self.CmdKeyAssign(ord('-'), wx.stc.STC_SCMOD_CTRL, \ + wx.stc.STC_CMD_ZOOMOUT) + self.CmdKeyAssign(ord('+'), wx.stc.STC_SCMOD_CTRL | \ + wx.stc.STC_SCMOD_SHIFT, wx.stc.STC_CMD_ZOOMIN) + + #---- Drop Target ----# + if use_dt and hasattr(parent, 'OnDrop'): + self.SetDropTarget(util.DropTargetFT(self, None, parent.OnDrop)) + + # Attributes + self.LOG = wx.GetApp().GetLog() + self._loading = None + self.key_handler = KeyHandler(self) + self._backup_done = True + self._bktimer = wx.Timer(self) + self._dwellsent = False + + # Macro Attributes + self._macro = list() + self.recording = False + + # Command/Settings Attributes + self._config = dict(autocomp=_PGET('AUTO_COMP'), + autoindent=_PGET('AUTO_INDENT'), + brackethl=_PGET('BRACKETHL'), + folding=_PGET('CODE_FOLD'), + highlight=_PGET('SYNTAX'), + autobkup=_PGET('AUTOBACKUP')) + + # Set Default Styles used by all documents + self.Configure() + self.UpdateBaseStyles() + + # Other Settings + self.SetMouseDwellTime(900) + self.UsePopUp(False) + + #self.Bind(wx.stc.EVT_STC_MACRORECORD, self.OnRecordMacro) + self.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick) + self.Bind(wx.stc.EVT_STC_UPDATEUI, self.OnUpdateUI) + self.Bind(wx.stc.EVT_STC_USERLISTSELECTION, self.OnUserListSel) + self.Bind(wx.stc.EVT_STC_DWELLSTART, self.OnDwellStart) + self.Bind(wx.stc.EVT_STC_DWELLEND, self.OnDwellEnd) + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) + self.Bind(wx.EVT_CHAR, self.OnChar) + self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_TIMER, self.OnBackupTimer) + + # Async file load events + self.Bind(ed_txt.EVT_FILE_LOAD, self.OnLoadProgress) + + #---- End Init ----# + + __name__ = u"EditraTextCtrl" + + #---- Protected Member Functions ----# + + def _BuildMacro(self): + """Constructs a macro script from items in the macro + record list. + @status: in limbo + + """ + if not len(self._macro): + return + + # Get command mappings + cmds = list() + for x in dir(wx.stc): + if x.startswith('STC_CMD_'): + cmds.append(x) + cmdvals = [getattr(wx.stc, x) for x in cmds] + cmds = [x.replace('STC_CMD_', u'') for x in cmds] + + # Get the commands names used in the macro + named = list() + for x in self._macro: + if x[0] in cmdvals: + named.append(cmds[cmdvals.index(x[0])]) + code = list() + + stc_dict = wx.stc.StyledTextCtrl.__dict__ + for cmd in named: + for attr in stc_dict: + if attr.upper() == cmd: + code.append(attr) + break + + code_txt = u'' + for fun in code: + code_txt += " ctrl.%s()\n" % fun + code_txt += " print \"Executed\"" #TEST + code_txt = "def macro(ctrl):\n" + code_txt + self.Parent.NewPage() + self.Parent.GetCurrentPage().SetText(code_txt) + self.Parent.GetCurrentPage().FindLexer('py') +# code = compile(code_txt, self.__module__, 'exec') +# exec code in self.__dict__ # Inject new code into this namespace + + def _MacHandleKey(self, k_code, shift_down, alt_down, ctrl_down, cmd_down): + """Handler for mac specific actions""" + handled = False + if alt_down: + return handled + + if cmd_down and not ctrl_down: + # Jump line/start end are special on OSX and need to be + # white space aware. + line = self.GetCurrentLine() + if k_code == wx.WXK_RIGHT: + handled = True + pos = self.GetLineStartPosition(line) + # end pos is absolute end which includes NUL term + lpos = self.GetLineEndPosition(line) - 1 + endsSpace = False + if lpos > 0: + endsSpace = unichr(self.GetCharAt(lpos)).isspace() + + if not shift_down: + self.LineEnd() + if endsSpace: + self.WordLeftEnd() + else: + self.LineEndExtend() + if endsSpace: + self.WordLeftEndExtend() + elif k_code == wx.WXK_LEFT: + handled = True + cpos = self.GetCurrentPos() + self.GotoIndentPos(line) + if shift_down: + self.SetSelection(cpos, self.CurrentPos) + + return handled + + #---- Public Member Functions ----# + + def AddBookmark(self, line=-1): + """Add a bookmark and return its handle + Sends notifications for bookmark added + @keyword line: if < 0 bookmark will be added to current line + + """ + rval = self.AddMarker(ed_marker.Bookmark(), line) + mdata = dict(stc=self, added=True, line=line, handle=rval) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_BOOKMARK, mdata) + return rval + + def RemoveBookmark(self, line): + """Remove the book mark from the given line + Sends notifications for bookmark removal. + @param line: int + + """ + self.RemoveMarker(ed_marker.Bookmark(), line) + mdata = dict(stc=self, added=False, line=line) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_BOOKMARK, mdata) + + def RemoveAllBookmarks(self): + """Remove all the bookmarks in the buffer + Sends notifications for bookmark removal. + + """ + self.RemoveAllMarkers(ed_marker.Bookmark()) + mdata = dict(stc=self, added=False, line=-1) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_BOOKMARK, mdata) + + def PlayMacro(self): + """Send the list of built up macro messages to the editor + to be played back. + @postcondition: the macro of this control has been played back + + """ + self.BeginUndoAction() + for msg in self._macro: + if msg[0] == 2170: + self.AddText(msg[2]) + elif msg[0] == 2001: + self.AddText(self.GetEOLChar() + u' ' * (msg[1] - 1)) + else: + self.SendMsg(msg[0], msg[1], msg[2]) + self.EndUndoAction() + + #---- Begin Function Definitions ----# + + def Bookmark(self, action): + """Handles bookmark actions + @param action: An event ID that describes what is to be done + @return: None + + """ + lnum = self.GetCurrentLine() + mark = -1 + if action == ed_glob.ID_ADD_BM: + if self.MarkerGet(lnum): + self.RemoveBookmark(lnum) + else: + self.AddBookmark(lnum) + elif action == ed_glob.ID_DEL_ALL_BM: + self.RemoveAllBookmarks() + elif action == ed_glob.ID_NEXT_MARK: + if self.MarkerGet(lnum): + lnum += 1 + mark = self.MarkerNext(lnum, 1) + if mark == -1: + mark = self.MarkerNext(0, 1) + elif action == ed_glob.ID_PRE_MARK: + if self.MarkerGet(lnum): + lnum -= 1 + mark = self.MarkerPrevious(lnum, 1) + if mark == -1: + mark = self.MarkerPrevious(self.GetLineCount(), 1) + + if mark != -1: + self.GotoLine(mark) + + # TODO: DO NOT use these methods anywhere new they will be removed soon + def ShowCommandBar(self): + """Open the command bar""" + self.TopLevelParent.GetEditPane().ShowCommandControl(ed_glob.ID_COMMAND) + + def ShowFindBar(self): + """Open the quick-find bar""" + self.TopLevelParent.GetEditPane().ShowCommandControl(ed_glob.ID_QUICK_FIND) + # END TODO + + def GetBookmarks(self): + """Gets a list of all lines containing bookmarks + @return: list of line numbers + + """ + MarkIsSet = ed_marker.Bookmark.IsSet + return [line for line in range(self.GetLineCount()) + if MarkIsSet(self, line)] + + def DoBraceHighlight(self): + """Perform a brace matching highlight + @note: intended for internal use only + """ + brace_at_caret, brace_opposite = self.GetBracePair() + # CallAfter necessary to reduce CG warnings on Mac + if brace_at_caret != -1 and brace_opposite == -1: + wx.CallAfter(self.BraceBadLight, brace_at_caret) + else: + wx.CallAfter(self.BraceHighlight, brace_at_caret, brace_opposite) + + def GetBracePair(self, pos=-1): + """Get a tuple of the positions in the buffer where the brace at the + current caret position and its match are. if a brace doesn't have a + match it will return -1 for the missing brace. + @keyword pos: -1 to use current cursor pos, else use to specify brace pos + @return: tuple (brace_at_caret, brace_opposite) + + """ + brace_at_caret = -1 + brace_opposite = -1 + char_before = None + if pos < 0: + # use current position + caret_pos = self.GetCurrentPos() + else: + caret_pos = pos + + if caret_pos > 0: + char_before = self.GetCharAt(caret_pos - 1) + + # check before + if char_before and unichr(char_before) in "[]{}()<>": + brace_at_caret = caret_pos - 1 + + # check after + if brace_at_caret < 0: + char_after = self.GetCharAt(caret_pos) + if char_after and chr(char_after) in "[]{}()<>": + brace_at_caret = caret_pos + + if brace_at_caret >= 0: + brace_opposite = self.BraceMatch(brace_at_caret) + + return (brace_at_caret, brace_opposite) + + def Configure(self): + """Configures the editors settings by using profile values + @postcondition: all profile dependent attributes are configured + + """ +# self.SetControlCharSymbol(172) + self.SetWrapMode(_PGET('WRAP', 'bool')) + self.SetViewWhiteSpace(_PGET('SHOW_WS', 'bool')) + self.SetUseAntiAliasing(_PGET('AALIASING')) + self.SetUseTabs(_PGET('USETABS')) + self.SetBackSpaceUnIndents(_PGET('BSUNINDENT')) + self.SetCaretLineVisible(_PGET('HLCARETLINE')) + self.SetIndent(_PGET('INDENTWIDTH', 'int')) + self.SetTabWidth(_PGET('TABWIDTH', 'int')) +# self.SetTabIndents(True) # Add option for this too? + self.SetIndentationGuides(_PGET('GUIDES')) + self.SetEOLMode(_PGET('EOL_MODE')) + self.SetViewEOL(_PGET('SHOW_EOL')) + self.SetAutoComplete(_PGET('AUTO_COMP')) + self.FoldingOnOff(_PGET('CODE_FOLD')) + self.ToggleAutoIndent(_PGET('AUTO_INDENT')) + self.ToggleBracketHL(_PGET('BRACKETHL')) + self.ToggleLineNumbers(_PGET('SHOW_LN')) + self.SetViEmulationMode(_PGET('VI_EMU'), _PGET('VI_NORMAL_DEFAULT')) + self.SetViewEdgeGuide(_PGET('SHOW_EDGE')) + self.EnableAutoBackup(_PGET('AUTOBACKUP')) + self.SetEndAtLastLine(not _PGET('VIEWVERTSPACE', default=False)) + self.SetCaretWidth(_PGET('CARETWIDTH', default=1)) + + def ConvertCase(self, upper=False): + """Converts the case of the selected text to either all lower + case(default) or all upper case. + @keyword upper: Flag whether conversion is to upper case or not. + + """ + sel = self.GetSelectedText() + if upper: + sel = sel.upper() + else: + sel = sel.lower() + self.ReplaceSelection(sel) + + def EnableAutoBackup(self, enable): + """Enable automatic backups + @param enable: bool + + """ + if enable: + # TODO: make backup interval configurable + if not self._bktimer.IsRunning(): + self._bktimer.Start(30000) # every 30 seconds + else: + if self._bktimer.IsRunning(): + self._bktimer.Stop() + + def InvertCase(self): + """Invert the case of the selected text + @postcondition: all text in selection has case inverted + + """ + text = self.GetSelectedText() + if len(text): + self.BeginUndoAction() + self.ReplaceSelection(text.swapcase()) + self.EndUndoAction() + + def GetAutoIndent(self): + """Returns whether auto-indent is being used + @return: whether autoindent is active or not + + """ + return self._config['autoindent'] + + def GetLineStartPosition(self, line): + """Get the starting position of the given line + @param line: int + @return: int + + """ + if line > 0: + spos = self.GetLineEndPosition(line-1) + if self.GetLine(line).endswith("\r\n"): + spos += 2 + else: + spos += 1 + else: + spos = 0 + return spos + + def GetLastVisibleLine(self): + """Return what the last visible line is + @return: int + + """ + return self.GetFirstVisibleLine() + self.LinesOnScreen() - 1 + + def GetMiddleVisibleLine(self): + """Return the number of the line that is in the middle of the display + @return: int + + """ + fline = self.GetFirstVisibleLine() + if self.LinesOnScreen() < self.GetLineCount(): + mid = (fline + (self.LinesOnScreen() / 2)) + else: + mid = (fline + (self.GetLineCount() / 2)) + return mid + + def GotoBraceMatch(self): + """Jump the caret to the brace opposite of the one the caret is + currently at. If there is no match or the caret currently is not next + to a brace no action is taken. + @return: bool + + """ + cbrace, brace_opposite = self.GetBracePair() + if -1 in (cbrace, brace_opposite): + return False + else: + self.GotoPos(brace_opposite) + return True + + def GotoColumn(self, column): + """Move caret to column of current line + @param column: Column to move to + + """ + cline = self.GetCurrentLineNum() + lstart = self.PositionFromLine(cline) + lend = self.GetLineEndPosition(cline) + linelen = lend - lstart + if column > linelen: + column = linelen + self.GotoPos(lstart + column) + + @jumpaction + def GotoLine(self, line): + """Move caret to beginning given line number + @param line: line to go to (int) + + """ + if line > self.GetLineCount(): + line = self.GetLineCount() + elif line < 0: + line = 0 + else: + pass + + self.SetYCaretPolicy(wx.stc.STC_CARET_STRICT, 0) + super(EditraStc, self).GotoLine(line) + self.SetYCaretPolicy(wx.stc.STC_CARET_EVEN, 0) + self.PostPositionEvent() + + @jumpaction + def GotoPos(self, pos): + """Override StyledTextCtrl.GotoPos + @param pos: position in buffer to move caret to (int) + + """ + super(EditraStc, self).GotoPos(pos) + self.PostPositionEvent() + + def SetCaretPos(self, pos): + """Set the caret position without posting jump events + @param pos: position to go to + + """ + try: + super(EditraStc, self).GotoPos(pos) + self.PostPositionEvent() + except wx.PyAssertionError: + util.Log("[ed_stc][err] SetCaretPos - invalid position %s" % pos) + + def GotoIndentPos(self, line=None): + """Move the caret to the end of the indentation + on the given line. + @param line: line to go to + + """ + if line is None: + line = self.GetCurrentLine() + self.GotoPos(self.GetLineIndentPosition(line)) + + def SetCurrentCol(self, column): + """Set the current column position on the currently line + extending the selection. + @param column: Column to move to + + """ + cline = self.GetCurrentLineNum() + lstart = self.PositionFromLine(cline) + lend = self.GetLineEndPosition(cline) + linelen = lend - lstart + if column > linelen: + column = linelen + self.SetCurrentPos(lstart + column) + + def DeleteForward(self): + """Delete the selection, or if there is no selection, then + delete the character to the right of the cursor. + + """ + if self.GetSelectionStart() == self.GetSelectionEnd(): + self.SetCurrentPos(self.GetCurrentPos() + 1) + self.DeleteBack() + + def EnableKeyProcessor(self, enable=True): + """Enable specialized key handling + @keyword enable: bool + + """ + self.key_handler.EnableProcessing(enable) + + def GetAutoComplete(self): + """Is Autocomplete being used by this instance + @return: whether autocomp is active or not + + """ + return self._config['autocomp'] + + def OnBackupTimer(self, evt): + """Backup the buffer to a backup file. + @param evt: wx.TimerEvent + + """ + fname = self.GetFileName() + # If the file is loading or is over 5MB don't do automatic backups. + if self.IsLoading() or ebmlib.GetFileSize(fname) > 5242880: + return + + # If the file is different than the last save point make the backup. + suffix = _PGET('AUTOBACKUP_SUFFIX', default=u'.edbkup') + bkupmgr = ebmlib.FileBackupMgr(None, u"%s" + suffix) + path = _PGET('AUTOBACKUP_PATH', default=u"") + if path and os.path.exists(path): + bkupmgr.SetBackupDirectory(path) + + if not self._backup_done and \ + (not bkupmgr.HasBackup(fname) or bkupmgr.IsBackupNewer(fname)): + msg = _("File backup performed: %s") % fname + idval = self.Id + target = self.TopLevelParent + def BackupJob(fobj, text): + writer = bkupmgr.GetBackupWriter(fobj) + try: + writer(text) + except Exception, msg: + return + nevt = ed_event.StatusEvent(ed_event.edEVT_STATUS, idval, + msg, ed_glob.SB_INFO) + wx.PostEvent(target, nevt) + ed_thread.EdThreadPool().QueueJob(BackupJob, self.File, self.GetText()) + self._backup_done = True + + def OnModified(self, evt): + """Overrides base modified handler""" + super(EditraStc, self).OnModified(evt) + if not self.IsLoading(): + self._backup_done = False + + def OnKeyDown(self, evt): + """Handles keydown events, currently only deals with + auto indentation. + @param evt: event that called this handler + + """ + k_code = evt.GetKeyCode() + shift_down = evt.ShiftDown() + alt_down = evt.AltDown() + ctrl_down = evt.ControlDown() + cmd_down = evt.CmdDown() + if self.key_handler.PreProcessKey(k_code, ctrl_down, + cmd_down, shift_down, + alt_down): + return + + if wx.Platform == '__WXMAC__' and self._MacHandleKey(k_code, shift_down, + alt_down, ctrl_down, + cmd_down): + pass + elif k_code == wx.WXK_RETURN: + if self._config['autoindent'] and not self.AutoCompActive(): + if self.GetSelectedText(): + self.CmdKeyExecute(wx.stc.STC_CMD_NEWLINE) + else: + self.AutoIndent() + else: + evt.Skip() + + self.CallTipCancel() + + elif self.VertEdit.Enabled: + # XXX: handle column mode + self.VertEdit.OnKeyDown(evt) + else: + evt.Skip() + + def OnChar(self, evt): + """Handles Char events that aren't caught by the + KEY_DOWN event. + @param evt: event that called this handler + @todo: autocomp/calltip lookup can be very cpu intensive it may + be better to try and process it on a separate thread to + prevent a slow down in the input of text into the buffer + + """ + key_code = evt.GetKeyCode() + cpos = self.GetCurrentPos() + cmpl = self.GetCompleter() + if self.key_handler.ProcessKey(key_code, evt.ControlDown(), + evt.CmdDown(), evt.ShiftDown(), + evt.AltDown()): + # The key handler handled this keypress, we don't need to insert + # the character into the buffer. + pass + + elif not self._config['autocomp'] or not cmpl.ShouldCheck(cpos): + evt.Skip() + return + + elif key_code in cmpl.GetAutoCompKeys(): + self.HidePopups() + + uchr = unichr(key_code) + command = self.GetCommandStr() + uchr + self.PutText(uchr) + + if self._config['autocomp']: + self.ShowAutoCompOpt(command) + + elif key_code in cmpl.GetCallTipKeys(): + self.HidePopups() + uchr = unichr(key_code) + command = self.GetCommandStr() + uchr + self.PutText(uchr) + + if self._config['autocomp']: + self.ShowCallTip(command) + + elif key_code in cmpl.GetCallTipCancel(): + evt.Skip() + self.CallTipCancel() +# elif key_code == wx.WXK_TAB and \ +# True not in (evt.ControlDown(), evt.CmdDown(), +# evt.ShiftDown(), evt.AltDown()): +# self.Tab() # <- So action can be overridden + elif wx.Platform == '__WXMAC__' and evt.CmdDown(): + pass # Hack for issue on OSX where char events are received here + else: +# print "IS TAB", key_code, wx.WXK_TAB + evt.Skip() + + def DoAutoComplete(self): + """Attempt to perform an autocompletion event.""" + self.HidePopups() + command = self.GetCommandStr() + self.ShowAutoCompOpt(command) + + def DoCallTip(self): + """Attempt to show a calltip for the current cursor position""" + self.HidePopups() + command = self.GetCommandStr() + # TODO: GetCommandStr seems to be inadequate under some cases + self.ShowCallTip(command) + + + def OnKeyUp(self, evt): + """Update status bar of window + @param evt: wxEVT_KEY_UP + + """ + evt.Skip() + self.PostPositionEvent() + tlw = self.TopLevelParent + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_KEYUP, + (evt.GetPositionTuple(), evt.GetKeyCode()), tlw.Id) + + def PostPositionEvent(self): + """Post an event to update the status of the line/column""" + line, column = self.GetPos() + pinfo = dict(lnum=line, cnum=column) + msg = _("Line: %(lnum)d Column: %(cnum)d") % pinfo + nevt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.GetId(), + msg, ed_glob.SB_ROWCOL) + tlw = self.TopLevelParent + wx.PostEvent(tlw, nevt) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_POS_CHANGED, pinfo, tlw.Id) + + def OnRecordMacro(self, evt): + """Records macro events + @param evt: wx.stc.StyledTextEvent + + """ + if self.IsRecording(): + msg = evt.GetMessage() + if msg == 2170: + lparm = self.GetTextRange(self.GetCurrentPos()-1, \ + self.GetCurrentPos()) + else: + lparm = evt.GetLParam() + mac = (msg, evt.GetWParam(), lparm) + self._macro.append(mac) +# if mac[0] != 2170: +# self._macro.append(mac) + else: + evt.Skip() + + def ParaDown(self): # pylint: disable-msg=W0221 + """Move the caret one paragraph down + @note: overrides the default function to set caret at end + of paragraph instead of jumping to start of next + + """ + self.WordPartRight() + super(EditraStc, self).ParaDown() + if self.GetCurrentPos() != self.GetLength(): + self.WordPartLeft() + self.GotoPos(self.GetCurrentPos() + len(self.GetEOLChar())) + + def ParaDownExtend(self): # pylint: disable-msg=W0221 + """Extend the selection a paragraph down + @note: overrides the default function to set selection at end + of paragraph instead of jumping to start of next so that + extra blank lines don't get swallowed. + + """ + self.WordRightExtend() + super(EditraStc, self).ParaDownExtend() + if self.GetCurrentPos() != self.GetLength(): + self.WordLeftExtend() + self.SetCurrentPos(self.GetCurrentPos() + len(self.GetEOLChar())) + + @jumpaction + def OnLeftUp(self, evt): + """Set primary selection and inform mainwindow that cursor position + has changed. + @param evt: wx.MouseEvent() + + """ + evt.Skip() + # FIXME: there is problems with using the primary selection. Setting + # the primary selection causes anything else on the clipboard + # to get killed. +# stxt = self.GetSelectedText() +# if len(stxt): +# util.SetClipboardText(stxt, primary=True) + self.PostPositionEvent() + + def OnLoadProgress(self, evt): + """Receives file loading events from asynchronous file loading""" + pid = self.TopLevelParent.Id + if evt.GetState() == ed_txt.FL_STATE_READING: + if evt.HasText(): + # TODO: get gauge updates working properly +# sb = self.GetTopLevelParent().GetStatusBar() +# gauge = sb.GetGauge() +# gauge.SetValue(evt.GetProgress()) +# gauge.Show() +# gauge.ProcessPendingEvents() +# sb.ProcessPendingEvents() + self.SetReadOnly(False) + self.AppendText(evt.GetValue()) + self.SetSavePoint() + self.SetReadOnly(True) + # wx.GetApp().Yield(True) # Too slow on windows... + elif evt.GetState() == ed_txt.FL_STATE_END: + self.SetReadOnly(False) + ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, 0, 0)) + self.SetSavePoint() + self.SetUndoCollection(True) + del self._loading + self._loading = None + parent = self.GetParent() + if hasattr(parent, 'DoPostLoad'): + parent.DoPostLoad() + elif evt.GetState() == ed_txt.FL_STATE_START: + ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_SHOW, (pid, True)) + ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, 0, self.File.GetSize())) + self.SetReadOnly(True) + self.SetUndoCollection(False) + elif evt.GetState() == ed_txt.FL_STATE_ABORTED: + self.SetReadOnly(False) + self.ClearAll() + + def OnUpdateUI(self, evt): + """Check for matching braces + @param evt: wx.stc.StyledTextEvent + + """ + # If disabled just skip the event + if self._config['brackethl']: + self.DoBraceHighlight() + + # XXX: handle when column mode is enabled + if self.VertEdit.Enabled: + self.VertEdit.OnUpdateUI(evt) + evt.Skip() + + def OnUserListSel(self, evt): + """Callback hook for userlist selections""" + mdata = dict(ltype=evt.GetListType(), + text=evt.GetText(), + stc=self) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_USERLIST_SEL, mdata, + context=self.TopLevelParent.Id) + evt.Skip() + + def OnDwellStart(self, evt): + """Callback hook for mouse dwell start""" + # Workaround issue where this event in incorrectly sent + # when the mouse has not dwelled within the buffer area + mpoint = wx.GetMousePosition() + brect = self.GetScreenRect() + if not brect.Contains(mpoint) or \ + not self.IsShown() or \ + not self.TopLevelParent.IsActive(): + return + + position = evt.Position + if not self._dwellsent and position >= 0: + dwellword = self.GetWordFromPosition(position)[0] + line_num = self.LineFromPosition(position) + 1 + mdata = dict(stc=self, pos=position, + line=line_num, + word=dwellword) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_DWELL_START, mdata) + + tip = mdata.get('rdata', None) + if tip: + self.CallTipShow(position, tip) + else: + # Clients did not need to make use of the calltip + # so check if auto-completion provider has anything to display. + if not self.IsNonCode(position): + endpos = self.WordEndPosition(position, True) + col = self.GetColumn(endpos) + line = self.GetLine(line_num-1) + command = self.GetCommandStr(line, col) + tip = self._code['compsvc'].GetCallTip(command) + if len(tip): + tip_pos = position - (len(dwellword.split('.')[-1]) + 1) + fail_safe = position - self.GetColumn(position) + self.CallTipShow(max(tip_pos, fail_safe), tip) + evt.Skip() + + def OnDwellEnd(self, evt): + """Callback hook for mouse dwell end""" + self._dwellsent = False + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_DWELL_END) + self.CallTipCancel() + evt.Skip() + + def OnMarginClick(self, evt): + """Open and Close Folders as Needed + @param evt: wx.stc.StyledTextEvent + + """ + margin_num = evt.GetMargin() + if margin_num == ed_basestc.FOLD_MARGIN: + if evt.GetShift() and \ + (evt.GetControl() or (wx.Platform == '__WXMAC__' and evt.GetAlt())): + self.FoldAll() + else: + line_clicked = self.LineFromPosition(evt.GetPosition()) + level = self.GetFoldLevel(line_clicked) + if level & wx.stc.STC_FOLDLEVELHEADERFLAG: + + # Expand node and all Subnodes + if evt.GetShift(): + self.SetFoldExpanded(line_clicked, True) + self.Expand(line_clicked, True, True, 100, level) + elif evt.GetControl() or \ + (wx.Platform == '__WXMAC__' and evt.GetAlt()): + # Contract all subnodes of clicked one + # Note: using Alt as Ctrl can not be received for + # clicks on mac (Scintilla Bug). + if self.GetFoldExpanded(line_clicked): + self.SetFoldExpanded(line_clicked, False) + self.Expand(line_clicked, False, True, 0, level) + else: + # Expand all subnodes + self.SetFoldExpanded(line_clicked, True) + self.Expand(line_clicked, True, True, 100, level) + else: + self.ToggleFold(line_clicked) + elif margin_num == ed_basestc.MARK_MARGIN: + # Bookmarks ect... + line_clicked = self.LineFromPosition(evt.GetPosition()) + # Hook for client code to interact with margin clicks + data = dict(stc=self, line=line_clicked) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_MARGIN_CLICK, msgdata=data) + if not data.get('handled', False): + # Default to internal bookmark handling + if ed_marker.Bookmark().IsSet(self, line_clicked): + self.RemoveBookmark(line_clicked) + else: + self.AddBookmark(line_clicked) + + def FoldAll(self): + """Fold Tree In or Out + @postcondition: code tree is folded open or closed + + """ + line_count = self.GetLineCount() + expanding = True + + # find out if we are folding or unfolding + for line_num in range(line_count): + if self.GetFoldLevel(line_num) & wx.stc.STC_FOLDLEVELHEADERFLAG: + expanding = not self.GetFoldExpanded(line_num) + break + line_num = 0 + + while line_num < line_count: + level = self.GetFoldLevel(line_num) + + if level & wx.stc.STC_FOLDLEVELHEADERFLAG and \ + (level & wx.stc.STC_FOLDLEVELNUMBERMASK) == \ + wx.stc.STC_FOLDLEVELBASE: + + if expanding: + self.SetFoldExpanded(line_num, True) + line_num = self.Expand(line_num, True) - 1 + else: + last_child = self.GetLastChild(line_num, -1) + self.SetFoldExpanded(line_num, False) + + if last_child > line_num: + self.HideLines(line_num + 1, last_child) + line_num = line_num + 1 + + def Expand(self, line, do_expand, force=False, vis_levels=0, level=-1): + """Open the Margin Folder + @postcondition: the selected folder is expanded + + """ + last_child = self.GetLastChild(line, level) + line = line + 1 + + while line <= last_child: + if force: + if vis_levels > 0: + self.ShowLines(line, line) + else: + self.HideLines(line, line) + else: + if do_expand: + self.ShowLines(line, line) + + if level == -1: + level = self.GetFoldLevel(line) + + if level & wx.stc.STC_FOLDLEVELHEADERFLAG: + if force: + self.SetFoldExpanded(line, vis_levels > 1) + line = self.Expand(line, do_expand, force, vis_levels - 1) + else: + if do_expand: + if self.GetFoldExpanded(line): + self.SetFoldExpanded(line, True) + line = self.Expand(line, do_expand, force, vis_levels - 1) + else: + line = line + 1 + return line + + def ExpandAll(self): + """Expand all folded code blocks""" + line_count = self.GetLineCount() + for line_num in xrange(line_count): + if self.GetFoldLevel(line_num) & wx.stc.STC_FOLDLEVELHEADERFLAG: + if not self.GetFoldExpanded(line_num): + self.Expand(line_num, True) + + def FindLexer(self, set_ext=u''): + """Sets Text Controls Lexer Based on File Extension + @param set_ext: explicit extension to use in search + @postcondition: lexer is configured for file + + """ + if not self._config['highlight']: + return 2 + + super(EditraStc, self).FindLexer(set_ext) + + # Configure Autocompletion + # NOTE: must be done after syntax configuration + if self._config['autocomp']: + self.ConfigureAutoComp() + return 0 + + def ControlDispatch(self, evt): + """Dispatches events caught from the mainwindow to the + proper functions in this module. + @param evt: event that was posted to this handler + + """ + e_id = evt.GetId() + e_obj = evt.GetEventObject() + e_map = { ed_glob.ID_COPY : self.Copy, ed_glob.ID_CUT : self.Cut, + ed_glob.ID_PASTE : self.Paste, ed_glob.ID_UNDO : self.Undo, + ed_glob.ID_REDO : self.Redo, ed_glob.ID_INDENT : self.Tab, + ed_glob.ID_REVERT_FILE : self.RevertToSaved, + ed_glob.ID_CUT_LINE : self.LineCut, + ed_glob.ID_DELETE_LINE : self.LineDelete, + ed_glob.ID_COLUMN_MODE : self.ToggleColumnMode, + ed_glob.ID_COPY_LINE : self.LineCopy, + ed_glob.ID_DUP_LINE : self.LineDuplicate, + ed_glob.ID_BRACKETHL : self.ToggleBracketHL, + ed_glob.ID_SYNTAX : self.SyntaxOnOff, + ed_glob.ID_UNINDENT : self.BackTab, + ed_glob.ID_TRANSPOSE : self.LineTranspose, + ed_glob.ID_LINE_MOVE_UP : self.LineMoveUp, + ed_glob.ID_LINE_MOVE_DOWN : self.LineMoveDown, + ed_glob.ID_SELECTALL: self.SelectAll, + ed_glob.ID_FOLDING : self.FoldingOnOff, + ed_glob.ID_SHOW_LN : self.ToggleLineNumbers, + ed_glob.ID_TOGGLECOMMENT : self.ToggleComment, + ed_glob.ID_AUTOINDENT : self.ToggleAutoIndent, + ed_glob.ID_LINE_AFTER : self.AddLine, + ed_glob.ID_TOGGLE_FOLD : self.ToggleFold, + ed_glob.ID_TOGGLE_ALL_FOLDS : self.FoldAll, + ed_glob.ID_TRIM_WS : self.TrimWhitespace, + ed_glob.ID_MACRO_START : self.StartRecord, + ed_glob.ID_MACRO_STOP : self.StopRecord, + ed_glob.ID_MACRO_PLAY : self.PlayMacro, + ed_glob.ID_GOTO_MBRACE : self.GotoBraceMatch, + ed_glob.ID_SHOW_AUTOCOMP : self.DoAutoComplete, + ed_glob.ID_SHOW_CALLTIP : self.DoCallTip + } + + e_idmap = { ed_glob.ID_ZOOM_OUT : self.DoZoom, + ed_glob.ID_ZOOM_IN : self.DoZoom, + ed_glob.ID_ZOOM_NORMAL : self.DoZoom, + ed_glob.ID_EOL_MAC : self.ConvertLineMode, + ed_glob.ID_EOL_UNIX : self.ConvertLineMode, + ed_glob.ID_EOL_WIN : self.ConvertLineMode, + ed_glob.ID_SPACE_TO_TAB : self.ConvertWhitespace, + ed_glob.ID_TAB_TO_SPACE : self.ConvertWhitespace, + ed_glob.ID_NEXT_MARK : self.Bookmark, + ed_glob.ID_PRE_MARK : self.Bookmark, + ed_glob.ID_ADD_BM : self.Bookmark, + ed_glob.ID_DEL_ALL_BM : self.Bookmark} + + # Hide autocomp popups + self.HidePopups() + + if e_obj.GetClassName() == "wxToolBar" or e_id in e_map: + if e_id in e_map: + e_map[e_id]() + return + + if e_id in e_idmap: + e_idmap[e_id](e_id) + elif e_id == ed_glob.ID_SHOW_EDGE: + self.SetViewEdgeGuide(not self.GetEdgeMode()) + elif e_id == ed_glob.ID_SHOW_EOL: + self.SetViewEOL(not self.GetViewEOL()) + elif e_id == ed_glob.ID_PASTE_AFTER: + cpos = self.GetCurrentPos() + self.Paste() + self.SetCurrentPos(cpos) + self.SetSelection(cpos, cpos) + elif e_id == ed_glob.ID_SHOW_WS: + self.SetViewWhiteSpace(not self.GetViewWhiteSpace()) + elif e_id == ed_glob.ID_WORD_WRAP: + self.SetWrapMode(not self.GetWrapMode()) + elif e_id == ed_glob.ID_JOIN_LINES: + self.LinesJoinSelected() + elif e_id == ed_glob.ID_INDENT_GUIDES: + self.SetIndentationGuides(not bool(self.GetIndentationGuides())) + elif e_id == ed_glob.ID_HLCARET_LINE: + self.SetCaretLineVisible(not self.GetCaretLineVisible()) + elif e_id in syntax.SYNTAX_IDS: + f_ext = syntax.GetExtFromId(e_id) + self.LOG("[ed_stc][evt] Manually Setting Lexer to %s" % str(f_ext)) + self.FindLexer(f_ext) + elif e_id == ed_glob.ID_AUTOCOMP: + self.SetAutoComplete(not self.GetAutoComplete()) + elif e_id == ed_glob.ID_LINE_BEFORE: + self.AddLine(before=True) + elif e_id in [ed_glob.ID_TO_UPPER, ed_glob.ID_TO_LOWER]: + self.ConvertCase(e_id == ed_glob.ID_TO_UPPER) + elif e_id == ed_glob.ID_USE_SOFTTABS: + self.SetUseTabs(not self.GetUseTabs()) + else: + evt.Skip() + + def CheckEOL(self): + """Checks the EOL mode of the opened document. If the mode + that the document was saved in is different than the editors + current mode the editor will switch modes to preserve the eol + type of the file, if the eol chars are mixed then the editor + will toggle on eol visibility. + @postcondition: eol mode is configured to best match file + @todo: Is showing line endings the best way to show mixed? + + """ + mixed = diff = False + eol_map = {u"\n" : wx.stc.STC_EOL_LF, + u"\r\n" : wx.stc.STC_EOL_CRLF, + u"\r" : wx.stc.STC_EOL_CR} + + eol = unichr(self.GetCharAt(self.GetLineEndPosition(0))) + if eol == u"\r": + tmp = unichr(self.GetCharAt(self.GetLineEndPosition(0) + 1)) + if tmp == u"\n": + eol += tmp + + # Is the eol used in the document the same as what is currently set. + if eol != self.GetEOLChar(): + diff = True + + # Check the lines to see if they are all matching or not. + LEPFunct = self.GetLineEndPosition + GCAFunct = self.GetCharAt + for line in range(self.GetLineCount() - 1): + end = LEPFunct(line) + tmp = unichr(GCAFunct(end)) + if tmp == u"\r": + tmp2 = unichr(GCAFunct(LEPFunct(0) + 1)) + if tmp2 == u"\n": + tmp += tmp2 + if tmp != eol: + mixed = True + break + + if mixed or diff: + if mixed: + # Warn about mixed end of line characters and offer to convert + msg = _("Mixed EOL characters detected.\n\n" + "Would you like to format them to all be the same?") + dlg = ed_mdlg.EdFormatEOLDlg(self.TopLevelParent, msg, + _("Format EOL?"), + eol_map.get(eol, self.GetEOLMode())) + + if dlg.ShowModal() == wx.ID_YES: + sel = dlg.GetSelection() + self.ConvertEOLs(sel) + super(EditraStc, self).SetEOLMode(sel) + dlg.Destroy() + else: + # The end of line character is different from the preferred + # user setting for end of line. So change our eol mode to + # preserve that of what the document is using. + mode = eol_map.get(eol, wx.stc.STC_EOL_LF) + super(EditraStc, self).SetEOLMode(mode) + else: + pass + + def ConvertLineMode(self, mode_id): + """Converts all line endings in a document to a specified + format. + @param mode_id: (menu) id of eol mode to set + + """ + eol_map = { ed_glob.ID_EOL_MAC : wx.stc.STC_EOL_CR, + ed_glob.ID_EOL_UNIX : wx.stc.STC_EOL_LF, + ed_glob.ID_EOL_WIN : wx.stc.STC_EOL_CRLF + } + self.ConvertEOLs(eol_map[mode_id]) + super(EditraStc, self).SetEOLMode(eol_map[mode_id]) + + def ConvertWhitespace(self, mode_id): + """Convert whitespace from using tabs to spaces or visa versa + @param mode_id: id of conversion mode + + """ + if mode_id not in (ed_glob.ID_TAB_TO_SPACE, ed_glob.ID_SPACE_TO_TAB): + return + tabw = self.GetIndent() + pos = self.GetCurrentPos() + sel = self.GetSelectedText() + if mode_id == ed_glob.ID_TAB_TO_SPACE: + cmd = (u"\t", u" " * tabw) + tabs = False + else: + cmd = (" " * tabw, u"\t") + tabs = True + + if sel != wx.EmptyString: + self.ReplaceSelection(sel.replace(cmd[0], cmd[1])) + else: + self.BeginUndoAction() + part1 = self.GetTextRange(0, pos).replace(cmd[0], cmd[1]) + tmptxt = self.GetTextRange(pos, self.GetLength()).replace(cmd[0], \ + cmd[1]) + self.SetText(part1 + tmptxt) + self.GotoPos(len(part1)) + self.SetUseTabs(tabs) + self.EndUndoAction() + + def GetCurrentLineNum(self): + """Return the number of the line that the caret is currently at + @return: Line number (int) + + """ + return self.LineFromPosition(self.GetCurrentPos()) + + def GetEOLModeId(self): + """Gets the id of the eol format. Convenience for updating + menu ui. + @return: id of the eol mode of this document + + """ + eol_map = { wx.stc.STC_EOL_CR : ed_glob.ID_EOL_MAC, + wx.stc.STC_EOL_LF : ed_glob.ID_EOL_UNIX, + wx.stc.STC_EOL_CRLF : ed_glob.ID_EOL_WIN + } + return eol_map.get(self.GetEOLMode(), ed_glob.ID_EOL_UNIX) + + def IsBracketHlOn(self): + """Returns whether bracket highlighting is being used by this + control or not. + @return: status of bracket highlight activation + + """ + return self._config['brackethl'] + + def IsFoldingOn(self): + """Returns whether code folding is being used by this + control or not. + @return: whether folding is on or not + + """ + return self._config['folding'] + + def IsHighlightingOn(self): + """Returns whether syntax highlighting is being used by this + control or not. + @return: whether syntax highlighting is on or not + + """ + return self._config['highlight'] + + def IsLoading(self): + """Is a background thread loading the text into the file + @return: bool + + """ + # NOTE: keep the getattr check here some cases + # are reporting a yet unexplainable AttributeError here + return getattr(self, '_loading', None) is not None + + def IsRecording(self): + """Returns whether the control is in the middle of recording + a macro or not. + @return: whether recording macro or not + + """ + return self.recording + + def GetSelectionLineStartEnd(self): + """Get the start and end positions of the lines in the current + fuzzy selection. + @return: tuple (int, int) + + """ + sline = self.LineFromPosition(self.GetSelectionStart()) + eline = self.LineFromPosition(self.GetSelectionEnd()) + last_line = self.GetLineCount() - 1 + eol_len = len(self.GetEOLChar()) + if sline < eline: + tstart = self.GetLineStartPosition(sline) + tend = self.GetLineEndPosition(eline) + else: + tstart = self.GetLineStartPosition(eline) + tend = self.GetLineEndPosition(sline) + + if eline == last_line and tstart != 0: + tstart -= eol_len + else: + tend += eol_len + + return (max(tstart, 0), min(tend, self.GetLength())) + + def LineCut(self): # pylint: disable-msg=W0221 + """Cut the selected lines into the clipboard""" + start, end = self.GetSelectionLineStartEnd() + self.BeginUndoAction() + self.BaseSetSelection(start, end) + self.Cut() + self.EndUndoAction() + + def LineDelete(self): # pylint: disable-msg=W0221 + """Delete the selected lines without modifying the clipboard""" + start, end = self.GetSelectionLineStartEnd() + self.BeginUndoAction() + self.SetTargetStart(start) + self.SetTargetEnd(end) + self.ReplaceTarget(u'') + self.EndUndoAction() + + def LinesJoin(self): # pylint: disable-msg=W0221 + """Join lines in target and compress whitespace + @note: overrides default function to allow for leading + whitespace in joined lines to be compressed to 1 space + + """ + sline = self.LineFromPosition(self.GetTargetStart()) + eline = self.LineFromPosition(self.GetTargetEnd()) + if not eline: + eline = 1 + lines = list() + for line in xrange(sline, eline + 1): + if line != sline: + tmp = self.GetLine(line).strip() + else: + tmp = self.GetLine(line) + if not tmp.isspace(): + tmp = tmp.rstrip() + else: + tmp = tmp.replace("\n", u'').replace("\r", u'') + if len(tmp): + lines.append(tmp) + self.SetTargetStart(self.PositionFromLine(sline)) + self.SetTargetEnd(self.GetLineEndPosition(eline)) + self.ReplaceTarget(u' '.join(lines)) + + def LinesJoinSelected(self): + """Similar to LinesJoin, but operates on selection + @see: LinesJoin + + """ + self.SetTargetStart(self.GetSelectionStart()) + self.SetTargetEnd(self.GetSelectionEnd()) + self.LinesJoin() + + def LineMoveUp(self): + """Move the current line up""" + linenum = self.GetCurrentLine() + if linenum > 0 : + self.BeginUndoAction() + self.LineTranspose() + self.LineUp() + self.EndUndoAction() + + def LineMoveDown(self): + """Move the current line down""" + linenum = self.GetCurrentLine() + col = self.GetColumn(self.GetCurrentPos()) + if linenum < self.GetLineCount() - 1: + self.BeginUndoAction() + self.LineDown() + self.LineTranspose() + self.GotoColumn(col) + self.EndUndoAction() + + def LineTranspose(self): # pylint: disable-msg=W0221 + """Switch the current line with the previous one + @note: overrides base stc method to do transpose in single undo action + + """ + self.BeginUndoAction() + super(EditraStc, self).LineTranspose() + self.EndUndoAction() + + def SetAutoComplete(self, value): + """Turns Autocompletion on and off + @param value: use autocomp or not + + """ + if isinstance(value, bool): + self._config['autocomp'] = value + if value: + self.InitCompleter() + + def SetEOLMode(self, mode): + """Sets the EOL mode from a string description + @param mode: eol mode to set + @note: overrides StyledTextCtrl.SetEOLMode + + """ + mode_map = { EDSTC_EOL_CR : wx.stc.STC_EOL_CR, + EDSTC_EOL_LF : wx.stc.STC_EOL_LF, + EDSTC_EOL_CRLF : wx.stc.STC_EOL_CRLF + } + + mode = mode_map.get(mode, wx.stc.STC_EOL_LF) + super(EditraStc, self).SetEOLMode(mode) + + def SetViEmulationMode(self, use_vi, use_normal=False): + """Activate/Deactivate Vi emulation mode + @param use_vi: Turn vi emulation on/off + @keyword use_normal: Start in normal mode + + """ + self.key_handler.ClearMode() + if use_vi: + self.key_handler = ViKeyHandler(self, use_normal) + else: + self.key_handler = KeyHandler(self) + + def SetViewEdgeGuide(self, switch=None): + """Toggles the visibility of the edge guide + @keyword switch: force a particular setting + + """ + if (switch is None and not self.GetEdgeMode()) or switch: + self.SetEdgeColumn(_PGET("EDGE", 'int', 80)) + self.SetEdgeMode(wx.stc.STC_EDGE_LINE) + else: + self.SetEdgeMode(wx.stc.STC_EDGE_NONE) + + def StartRecord(self): # pylint: disable-msg=W0221 + """Starts recording all events + @return: None + + """ + self.recording = True + evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.GetId(), + _("Recording Macro") + u"...", + ed_glob.SB_INFO) + wx.PostEvent(self.TopLevelParent, evt) + super(EditraStc, self).StartRecord() + + def StopRecord(self): # pylint: disable-msg=W0221 + """Stops the recording and builds the macro script + @postcondition: macro recording is stopped + + """ + self.recording = False + super(EditraStc, self).StopRecord() + evt = ed_event.StatusEvent(ed_event.edEVT_STATUS, self.GetId(), + _("Recording Finished"), + ed_glob.SB_INFO) + wx.PostEvent(self.TopLevelParent, evt) + self._BuildMacro() + + def TrimWhitespace(self): + """Trims trailing whitespace from all lines in the document. + @postcondition: all trailing whitespace is removed from document + + """ + cpos = self.GetCurrentPos() + cline = self.GetCurrentLine() + cline_len = len(self.GetLine(cline)) + epos = cline_len - (self.GetLineEndPosition(cline) - cpos) + + # Begin stripping trailing whitespace + self.BeginUndoAction() + for line in xrange(self.GetLineCount()): + eol = u'' + tmp = self.GetLine(line) + + # Scintilla stores text in utf8 internally so we need to + # encode to utf8 to get the correct length of the text. + try: + tlen = len(tmp.encode('utf-8')) + except: + tlen = len(tmp) + + if tlen: + if "\r\n" in tmp: + eol = "\r\n" + elif "\n" in tmp: + eol = "\n" + else: + eol = tmp[-1] + + if not eol.isspace(): + continue + elif eol in u' \t': + eol = u'' + else: + continue + + # Strip the extra whitespace from the line + end = self.GetLineEndPosition(line) + len(eol) + start = max(end - tlen, 0) + self.SetTargetStart(start) + self.SetTargetEnd(end) + rtxt = tmp.rstrip() + eol + if rtxt != self.GetTextRange(start, end): + self.ReplaceTarget(tmp.rstrip() + eol) + self.EndUndoAction() + + # Restore carat position + cline_len = len(self.GetLine(cline)) + end = self.GetLineEndPosition(cline) + if epos >= cline_len: + epos = end + else: + start = max(end - cline_len, 0) + epos += start + + if epos != cpos: + self.GotoPos(epos) + + def FoldingOnOff(self, switch=None): + """Turn code folding on and off + @keyword switch: force a particular setting + + """ + if (switch is None and not self._config['folding']) or switch: + self.LOG("[ed_stc][evt] Code Folding Turned On") + self._config['folding'] = True + self.SetMarginWidth(ed_basestc.FOLD_MARGIN, 12) + self.SetProperty("fold", "1") + else: + self.LOG("[ed_stc][evt] Code Folding Turned Off") + self._config['folding'] = False + + # Ensure all code blocks have been expanded + self.ExpandAll() + + self.SetMarginWidth(ed_basestc.FOLD_MARGIN, 0) + self.SetProperty("fold", "0") + + def SyntaxOnOff(self, switch=None): + """Turn Syntax Highlighting on and off + @keyword switch: force a particular setting + + """ + if (switch is None and not self._config['highlight']) or switch: + self.LOG("[ed_stc][evt] Syntax Highlighting Turned On") + self._config['highlight'] = True + self.FindLexer() + else: + self.LOG("[ed_stc][evt] Syntax Highlighting Turned Off") + self._config['highlight'] = False + self.SetLexer(wx.stc.STC_LEX_NULL) + self.ClearDocumentStyle() + self.UpdateBaseStyles() + return 0 + + def Tab(self): # pylint: disable-msg=W0221 + """Override base method to ensure that folded blocks get unfolded + prior to changing the indentation. + + """ + # TODO: unfolding of folded blocks during block indent +# lines = list() +# if self.HasSelection(): +# sel = self.GetSelection() +# sline = self.LineFromPosition(sel[0]) +# eline = self.LineFromPosition(sel[1]) +# lines = range(sline, eline+1) +# else: +# cline = self.GetCurrentLine() +# lines = [cline, cline+1] + +# for line_num in lines: +# if self.GetFoldLevel(line_num) & wx.stc.STC_FOLDLEVELHEADERFLAG: +# if not self.GetFoldExpanded(line_num): +# self.Expand(line_num, True) + super(EditraStc, self).Tab() + + def ToggleAutoIndent(self, switch=None): + """Toggles Auto-indent On and Off + @keyword switch: force a particular setting + + """ + if (switch is None and not self._config['autoindent']) or switch: + self._config['autoindent'] = True + else: + self._config['autoindent'] = False + + def ToggleBracketHL(self, switch=None): + """Toggle Bracket Highlighting On and Off + @keyword switch: force a particular setting + + """ + if (switch is None and not self._config['brackethl']) or switch: + self.LOG("[ed_stc][evt] Bracket Highlighting Turned On") + self._config['brackethl'] = True + # Make sure to highlight a brace if next to on when turning it on + self.DoBraceHighlight() + else: + self.LOG("[ed_stc][evt] Bracket Highlighting Turned Off") + self._config['brackethl'] = False + # Make sure that if there was a highlighted brace it gets cleared + wx.CallAfter(self.BraceHighlight, -1, -1) + + def ToggleFold(self, lineNum=None): + """Toggle the fold at the given line number. If lineNum is + None then the fold closest cursors current postions. + @keyword lineNum: int + + """ + if lineNum is None: + lineNum = self.GetCurrentLine() + super(EditraStc, self).ToggleFold(lineNum) + + @jumpaction + def WordLeft(self): # pylint: disable-msg=W0221 + """Move caret to beginning of previous word + @note: override builtin to include extra characters in word + + """ + self.SetWordChars(NONSPACE) + super(EditraStc, self).WordLeft() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordLeft() + self.SetWordChars('') + + def WordLeftExtend(self): # pylint: disable-msg=W0221 + """Extend selection to beginning of previous word + @note: override builtin to include extra characters in word + + """ + self.SetWordChars(NONSPACE) + super(EditraStc, self).WordLeftExtend() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordLeftExtend() + self.SetWordChars('') + + @jumpaction + def WordPartLeft(self): # pylint: disable-msg=W0221 + """Move the caret left to the next change in capitalization/punctuation + @note: overrides default function to not count whitespace as words + + """ + super(EditraStc, self).WordPartLeft() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordPartLeft() + + def WordPartLeftExtend(self): # pylint: disable-msg=W0221 + """Extend selection left to the next change in c + apitalization/punctuation. + @note: overrides default function to not count whitespace as words + + """ + super(EditraStc, self).WordPartLeftExtend() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordPartLeftExtend() + + @jumpaction + def WordPartRight(self): # pylint: disable-msg=W0221 + """Move the caret to the start of the next word part to the right + @note: overrides default function to exclude white space + + """ + super(EditraStc, self).WordPartRight() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordPartRight() + + @jumpaction + def WordPartRightEnd(self): # pylint: disable-msg=W0221 + """Move caret to end of next change in capitalization/punctuation + @postcondition: caret is moved + + """ + super(EditraStc, self).WordPartRight() + super(EditraStc, self).WordPartRight() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos - 1) in SPACECHARS: + self.CharLeft() + + def WordPartRightEndExtend(self): # pylint: disable-msg=W0221 + """Extend selection to end of next change in capitalization/punctuation + @postcondition: selection is extended + + """ + super(EditraStc, self).WordPartRightExtend() + super(EditraStc, self).WordPartRightExtend() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos - 1) in SPACECHARS: + self.CharLeftExtend() + + def WordPartRightExtend(self): # pylint: disable-msg=W0221 + """Extend selection to start of next change in + capitalization/punctuation + @postcondition: selection is extended + + """ + super(EditraStc, self).WordPartRightExtend() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordPartRightExtend() + + @jumpaction + def WordRight(self): # pylint: disable-msg=W0221 + """Move caret to beginning of next word + @note: override builtin to include extra characters in word + + """ + self.SetWordChars(NONSPACE) + super(EditraStc, self).WordRight() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordRight() + self.SetWordChars('') + + @jumpaction + def WordRightEnd(self): # pylint: disable-msg=W0221 + """Move caret to end of next change in word + @note: override builtin to include extra characters in word + + """ + self.SetWordChars(NONSPACE) + super(EditraStc, self).WordRightEnd() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos - 1) in SPACECHARS: + super(EditraStc, self).WordRightEnd() + self.SetWordChars('') + + def WordRightExtend(self): # pylint: disable-msg=W0221 + """Extend selection to beginning of next word + @note: override builtin to include extra characters in word + + """ + self.SetWordChars(NONSPACE) + super(EditraStc, self).WordRightExtend() + cpos = self.GetCurrentPos() + if self.GetTextRange(cpos, cpos + 1) in SPACECHARS: + super(EditraStc, self).WordRightExtend() + self.SetWordChars('') + + def LoadFile(self, path): + """Load the file at the given path into the buffer. Returns + True if no errors and False otherwise. To retrieve the errors + check the last error that was set in the file object returned by + L{GetDocument}. + @param path: path to file + + """ + fsize = ebmlib.GetFileSize(path) + if fsize < 1048576: # 1MB + return super(EditraStc, self).LoadFile(path) + else: + ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENING, path) + self.file.SetPath(path) + self._loading = wx.BusyCursor() + self.file.ReadAsync(self) + return True + + def ReloadFile(self): + """Reloads the current file, returns True on success and + False if there is a failure. + @return: whether file was reloaded or not + + """ + cfile = self.GetFileName() + if os.path.exists(cfile): + try: + self.BeginUndoAction() + marks = self.GetBookmarks() + cpos = self.GetCurrentPos() + # TODO: Handle async re-loads of large files + txt = self.File.Read() + self.SetReadOnly(False) + if txt is not None: + if self.File.IsRawBytes() and not ebmlib.IsUnicode(txt): + self.AddStyledText(txt) + self.SetReadOnly(True) # Don't allow editing of raw bytes + else: + self.SetText(txt) + else: + return False, _("Failed to reload: %s") % cfile + + self.SetModTime(ebmlib.GetFileModTime(cfile)) + for mark in marks: + self.AddBookmark(mark) + self.EndUndoAction() + self.SetSavePoint() + except (UnicodeDecodeError, AttributeError, OSError, IOError), msg: + self.LOG("[ed_stc][err] Failed to Reload %s" % cfile) + return False, msg + else: + self.GotoPos(cpos) + context = self.TopLevelParent.Id + ed_msg.PostMessage(ed_msg.EDMSG_FILE_OPENED, + self.GetFileName(), context) + return True, '' + else: + self.LOG("[ed_stc][err] %s does not exists, cant reload." % cfile) + return False, _("%s does not exist") % cfile + + def RevertFile(self): + """Revert all the changes made to the file since it was opened + @postcondition: undo history is re-wound to initial state and file + is re-saved if it has an on disk file. + + """ + with eclib.Freezer(self) as _tmp: + while self.CanUndo(): + self.Undo() + + fname = self.GetFileName() + if len(fname): + self.SaveFile(fname) + + def RevertToSaved(self): + """Revert the current buffer back to the last save point""" + with eclib.Freezer(self) as _tmp: + while self.CanUndo(): + if self.GetModify(): + self.Undo() + else: + break + + def SaveFile(self, path): + """Save buffers contents to disk + @param path: path of file to save + @return: whether file was written or not + + """ + result = True + try: + tlw_id = self.TopLevelParent.Id + ed_msg.PostMessage(ed_msg.EDMSG_FILE_SAVE, + (path, self.GetLangId()), tlw_id) + self.File.SetPath(path) + self.LOG("[ed_stc][info] Writing file %s, with encoding %s" % \ + (path, self.File.GetEncoding())) + + if _PGET('AUTO_TRIM_WS', 'bool', False): + self.TrimWhitespace() + + if self.File.IsReadOnly(): + wx.MessageBox(_("File is Read Only and cannot be saved"), + _("Read Only"), + style=wx.OK|wx.CENTER|wx.ICON_WARNING) + return True + else: + if not self.File.IsRawBytes(): + self.File.Write(self.GetText()) + else: + nchars = self.GetTextLength() + txt = self.GetStyledText(0, nchars)[0:nchars*2:2] + self.File.Write(txt) + except Exception, msg: + result = False + self.LOG("[ed_stc][err] There was an error saving %s" % path) + self.LOG("[ed_stc][err] ERROR: %s" % str(msg)) + + if result: + self.SetSavePoint() + self.SetModTime(ebmlib.GetFileModTime(path)) + self.File.FireModified() + self.SetFileName(path) + + wx.CallAfter(ed_msg.PostMessage, + ed_msg.EDMSG_FILE_SAVED, + (path, self.GetLangId()), + tlw_id) + + return result + + def ConfigureLexer(self, file_ext): + """Sets Lexer and Lexer Keywords for the specified file extension + @param file_ext: a file extension to configure the lexer from + + """ + super(EditraStc, self).ConfigureLexer(file_ext) + + if not self._config['folding']: + self.SetProperty("fold", "0") + + # Notify that lexer has changed + pid = self.TopLevelParent.Id + self.LOG("[ed_stc][info] Lexer change notification for context %d" % pid) + ed_msg.PostMessage(ed_msg.EDMSG_UI_STC_LEXER, + (self.GetFileName(), self.GetLangId()), pid) + return True + + def HideCaret(self): + if hasattr(self, 'SetCaretStyle'): + self.SetCaretStyle(wx.stc.STC_CARETSTYLE_INVISIBLE) + else: + self.SetCaretWidth(0) + + def RestoreCaret(self): + if self.key_handler.BlockMode: + self.SetBlockCaret() + else: + self.SetLineCaret() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_style.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_style.py new file mode 100644 index 0000000..6e8f60d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_style.py @@ -0,0 +1,1087 @@ +############################################################################### +# Name: ed_style.py # +# Purpose: Editra's style management system. Implements the interpretation of # +# Editra Style Sheets to the StyledTextCtrl. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008-2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides a system for managing styles in the text control. Compiles the data +in an Editra Style Sheet to a format that Scintilla can understand. The +specification of Editra Style Sheets that this module implements can be found +either in the _docs_ folder of the source distribution or on Editra's home page +U{http://editra.org/editra_style_sheets}. + +@summary: Style management system for managing the syntax highlighting of all + buffers + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_style.py 72388 2012-08-28 16:06:31Z CJP $" +__revision__ = "$Revision: 72388 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import re +import wx + +# Editra Libraries +import ed_glob +import util +from profiler import Profile_Get, Profile_Set +import eclib +import ebmlib + +# Globals +STY_ATTRIBUTES = (u"face", u"fore", u"back", u"size", u"modifiers") +STY_EX_ATTRIBUTES = (u"eol", u"bold", u"italic", u"underline") + +# Parser Values +RE_ESS_COMMENT = re.compile("\/\*[^*]*\*+([^/][^*]*\*+)*\/") +RE_ESS_SCALAR = re.compile("\%\([a-zA-Z0-9]+\)") +RE_HEX_STR = re.compile("#[0-9a-fA-F]{3,6}") + +#--------------------------------------------------------------------------# + +class StyleItem(object): + """A storage class for holding styling information """ + __slots__ = ('null', 'fore', 'face', 'back', 'size', '_exattr') + def __init__(self, fore=u"", back=u"", face=u"", size=u"", ex=None): + """Initializes the Style Object. + + @keyword fore: Specifies the foreground color (hex string) + @keyword face: Specifies the font face (string face name) + @keyword back: Specifies the background color (hex string) + @keyword size: Specifies font point size (int/formatted string) + @keyword ex: Specify modifiers + + SPECIFICATION: + - DATA FORMATS: + - #123456 = hex color code + - Monaco = Font Face Name + - %(primary)s = Format string to be swapped at runtime + - 10 = A font point size + - %(size)s = Format string to be swapped at runtime + - ex = bold underline italic eol + + """ + super(StyleItem, self).__init__() + + if ex is None: + ex = list() + + # Attributes + self.null = False + self.fore = fore # Foreground color hex code + self.face = face # Font face name + self.back = back # Background color hex code + self.size = size # Font point size + self._exattr = ex # Extra attributes + + def __eq__(self, other): + """Defines the == operator for the StyleItem Class + @param other: style item to compare to + @return: whether the two items are equal + + """ + return unicode(self) == unicode(other) + + def __ne__(self, other): + """Defines != operator for the StyleItem Class""" + return unicode(self) != unicode(other) + + def __str__(self): + """Convert StyleItem to string""" + uni = unicode(self) + return uni.encode('utf-8') + + def __unicode__(self): + """Converts StyleItem to Unicode + @note: This return string is in a format that can be accepted by + Scintilla. No spaces may be in the string after the ':'. + @return: Unicode representation of the StyleItem + + """ + style_str = list() + if self.fore: + style_str.append(u"fore:%s" % self.fore) + if self.back: + style_str.append(u"back:%s" % self.back) + if self.face: + style_str.append(u"face:%s" % self.face) + if self.size: + style_str.append(u"size:%s" % unicode(self.size)) + if len(self._exattr): + style_str.append(u"modifiers:" + u','.join(self._exattr)) + + style_str = u",".join(style_str) + return style_str.rstrip(u",") + + def Clone(self): + """Make and return a copy of this object""" + nitem = StyleItem(self.fore, self.back, + self.face, self.size, + self._exattr) + if self.null: + nitem.Nullify() + return nitem + + #---- Get Functions ----# + def GetAsList(self): + """Returns a list of attr:value strings + this style item. + @return: list attribute values usable for building stc or ess values + + """ + retval = list() + for attr in ('fore', 'back', 'face', 'size'): + val = getattr(self, attr, None) + if val not in ( None, wx.EmptyString ): + retval.append(attr + ':' + val) + + if len(self._exattr): + retval.append("modifiers:" + u",".join(self._exattr)) + return retval + + def GetBack(self): + """Returns the value of the back attribute + @return: style items background attribute + + """ + return self.back + + def GetFace(self): + """Returns the value of the face attribute + @return: style items font face attribute + + """ + return self.face + + def GetFore(self): + """Returns the value of the fore attribute + @return: style items foreground attribute + + """ + return self.fore + + def GetSize(self): + """Returns the value of the size attribute as a string + @return: style items font size attribute + + """ + return self.size + + def GetModifiers(self): + """Get the modifiers string + @return: string + + """ + return u",".join(self.GetModifierList()) + + def GetModifierList(self): + """Get the list of modifiers + @return: list + + """ + return self._exattr + + def GetNamedAttr(self, attr): + """Get the value of the named attribute + @param attr: named attribute to get value of + + """ + return getattr(self, attr, None) + + #---- Utilities ----# + def IsNull(self): + """Return whether the item is null or not + @return: bool + + """ + return self.null + + def IsOk(self): + """Check if the style item is ok or not, if it has any of its + attributes set it is perceived as ok. + @return: bool + + """ + return len(unicode(self)) + + def Nullify(self): + """Clear all values and set item as Null + @postcondition: item is turned into a NullStyleItem + + """ + self.null = True + for attr in ('fore', 'face', 'back', 'size'): + setattr(self, attr, u'') + self._exattr = list() + + #---- Set Functions ----# + def SetAttrFromStr(self, style_str): + """Takes style string and sets the objects attributes + by parsing the string for the values. Only sets or + overwrites values does not zero out previously set values. + Returning True if value(s) are set or false otherwise. + @param style_str: style information string (i.e fore:#888444) + + """ + self.null = False + last_set = wx.EmptyString + for atom in style_str.split(u','): + attrib = atom.split(u':') + if len(attrib) == 2 and attrib[0] in STY_ATTRIBUTES: + last_set = attrib[0] + if last_set == u"modifiers": + self.SetExAttr(attrib[1]) + else: + setattr(self, attrib[0], attrib[1]) + else: + for attr in attrib: + if attr in STY_EX_ATTRIBUTES: + self.SetExAttr(attr) + + return last_set != wx.EmptyString + + def SetBack(self, back, ex=wx.EmptyString): + """Sets the Background Value + @param back: hex color string, or None to clear attribute + @keyword ex: extra attribute (i.e bold, italic, underline) + + """ + self.null = False + if back is None: + back = u'' + self.back = back + if ex and ex not in self._exattr: + self._exattr.append(ex) + + def SetFace(self, face, ex=wx.EmptyString): + """Sets the Face Value + @param face: font name string, or None to clear attribute + @keyword ex: extra attribute (i.e bold, italic, underline) + + """ + self.null = False + if face is None: + face = u'' + self.face = face + if ex and ex not in self._exattr: + self._exattr.append(ex) + + def SetFore(self, fore, ex=wx.EmptyString): + """Sets the Foreground Value + @param fore: hex color string, or None to clear attribute + @keyword ex: extra attribute (i.e bold, italic, underline) + + """ + self.null = False + if fore is None: + fore = u'' + self.fore = fore + if ex and ex not in self._exattr: + self._exattr.append(ex) + + def SetSize(self, size, ex=wx.EmptyString): + """Sets the Font Size Value + @param size: font point size, or None to clear attribute + @keyword ex: extra attribute (i.e bold, italic, underline) + + """ + self.null = False + if size is None: + size = u'' + self.size = unicode(size) + if ex and ex not in self._exattr: + self._exattr.append(ex) + + def SetExAttr(self, ex_attr, add=True): + """Adds an extra text attribute to a StyleItem. Currently + (bold, eol, italic, underline) are supported. If the optional + add value is set to False the attribute will be removed from + the StyleItem. + @param ex_attr: extra style attribute (bold, eol, italic, underline) + @keyword add: Add a style (True) or remove a style (False) + + """ + # Get currently set attributes + self.null = False + if ex_attr not in STY_EX_ATTRIBUTES: + return + + if add and ex_attr not in self._exattr: + self._exattr.append(ex_attr) + elif not add and ex_attr in self._exattr: + self._exattr.remove(ex_attr) + else: + pass + + def SetNamedAttr(self, attr, value): + """Sets a StyleItem attribute by named string. + @note: This is not intended to be used for setting extra + attributes such as bold, eol, ect.. + @param attr: a particular attribute to set (i.e fore, face, back, size) + @param value: value to set the attribute to contain. None to clear the + value. + + """ + self.null = False + if value is None: + value = u'' + cur_val = getattr(self, attr, None) + if cur_val is not None: + if u"," in value: + modifiers = value.split(u",") + value = modifiers.pop(0) + for ex in modifiers: + self.SetExAttr(ex) + setattr(self, attr, value) + +#-----------------------------------------------------------------------------# + +class StyleMgr(object): + """Manages style definitions and provides them on request. + Also provides functionality for loading custom style sheets and + modifying styles during run time. + + """ + STYLES = dict() # Static cache for loaded style set(s) + FONT_PRIMARY = u"primary" + FONT_SECONDARY = u"secondary" + FONT_SIZE = u"size" + FONT_SIZE2 = u"size2" + FONT_SIZE3 = u"size3" + + def __init__(self, custom=wx.EmptyString): + """Initializes the Style Manager + @keyword custom: path to custom style sheet to use + + """ + super(StyleMgr, self).__init__() + + # Attributes + self.fonts = self.GetFontDictionary() + self.style_set = custom + self.syntax_set = list() + self.LOG = wx.GetApp().GetLog() + + # Get the Style Set + if custom != wx.EmptyString and self.LoadStyleSheet(custom): + self.LOG("[ed_style][info] Loaded custom style sheet %s" % custom) + elif custom == wx.EmptyString: + self.SetStyles('default', DEF_STYLE_DICT) + else: + self.LOG("[ed_style][err] Failed to import styles from %s" % custom) + + def BlankStyleDictionary(self): + """Returns a dictionary of unset style items based on the + tags defined in the current dictionary. + @return: dictionary of unset style items using the current tag set + as keys. + + """ + sty_dict = dict() + for key in DEF_STYLE_DICT.keys(): + if key in ('select_style',): # special styles + sty_dict[key] = NullStyleItem() + else: + sty_dict[key] = StyleItem("#000000", "#FFFFFF", + "%(primary)s", "%(size)d") + return sty_dict + + def FindTagById(self, style_id): + """Find the style tag that is associated with the given + Id. Return value defaults to default_style . + @param style_id: id of tag to look for + @return: style tag string + + """ + for data in self.syntax_set: + if style_id == data[0]: + return data[1] + return 'default_style' + + def GetFontDictionary(self, default=True): + """Does a system lookup to build a default set of fonts using + ten point fonts as the standard size. + @keyword default: return the default dictionary of fonts, else return + the current running dictionary of fonts if it exists. + @return: font dictionary (primary, secondary) + (size, size2) + + """ + if hasattr(self, 'fonts') and not default: + return self.fonts + + font = Profile_Get('FONT1', 'font', None) + if font is not None: + mfont = font + else: + mfont = wx.Font(10, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL) + Profile_Set('FONT1', mfont, 'font') + primary = mfont.GetFaceName() + + font = Profile_Get('FONT2', 'font', None) + if font is None: + font = wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL) + Profile_Set('FONT2', font, 'font') + secondary = font.GetFaceName() + faces = { + self.FONT_PRIMARY : primary, + self.FONT_SECONDARY : secondary, + self.FONT_SIZE : mfont.GetPointSize(), + self.FONT_SIZE2 : font.GetPointSize(), + self.FONT_SIZE3 : mfont.GetPointSize() - 2 + } + return faces + + def GetDefaultFont(self): + """Constructs and returns a wxFont object from the settings + of the default_style object. + @return: wx.Font object of default style + + """ + if self.HasNamedStyle('default_style'): + style_item = self.GetItemByName('default_style') + face = style_item.GetFace() + if face and face[0] == u"%": + face = face % self.fonts + size = style_item.GetSize() + if isinstance(size, basestring): + size = size % self.fonts + font = wx.FFont(int(size), wx.MODERN, face=face) + else: + font = wx.FFont(self.fonts[self.FONT_SIZE], wx.MODERN) + return font + + def GetDefaultForeColour(self, as_hex=False): + """Gets the foreground color of the default style and returns + a Colour object. Otherwise returns Black if the default + style is not found. + @keyword as_hex: return a hex string or colour object + @return: wx.Colour of default style foreground or hex value + + """ + fore = self.GetItemByName('default_style').GetFore() + if not fore: + fore = u"#000000" + + if not as_hex: + rgb = eclib.HexToRGB(fore[1:]) + fore = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2]) + return fore + + def GetCurrentStyleSetName(self): + """Get the name of the currently set style + @return: string + + """ + return self.style_set + + def GetDefaultBackColour(self, as_hex=False): + """Gets the background color of the default style and returns + a Colour object. Otherwise returns white if the default + style is not found. + @keyword as_hex: return a hex string or colour object + @return: wx.Colour of default style background or hex value + + """ + back = self.GetItemByName('default_style').GetBack() + if not back: + back = u"#FFFFFF" + + if not as_hex: + rgb = eclib.HexToRGB(back[1:]) + back = wx.Colour(red=rgb[0], green=rgb[1], blue=rgb[2]) + return back + + def GetItemByName(self, name): + """Gets and returns a style item using its name for the search + @param name: tag name of style item to get + @return: style item (may be empty/null style item) + + """ + scheme = self.GetStyleSet() + if name in scheme: + item = scheme[name] + + # Set font value if need be + ival = unicode(item) + if u"%" in ival: + val = ival % self.fonts + item = StyleItem() + item.SetAttrFromStr(val) + + return item + else: + return StyleItem() + + def GetStyleFont(self, primary=True): + """Returns the primary font facename by default + @keyword primary: Get Primary(default) or Secondary Font + @return face name of current font in use + + """ + if primary: + font = wx.FFont(self.fonts[self.FONT_SIZE], wx.DEFAULT, + face=self.fonts[self.FONT_PRIMARY]) + else: + font = wx.FFont(self.fonts[self.FONT_SIZE2], wx.DEFAULT, + face=self.fonts[self.FONT_SECONDARY]) + return font + + def GetStyleByName(self, name): + """Gets and returns a style string using its name for the search + @param name: tag name of style to get + @return: style item in string form + + """ + if self.HasNamedStyle(name): + stystr = unicode(self.GetItemByName(name)) + return stystr.replace("modifiers:", "") + else: + return u"" + + def GetStyleSet(self): + """Returns the current set of styles or the default set if + there is no current set. + @return: current style set dictionary + + """ + return StyleMgr.STYLES.get(self.style_set, DEF_STYLE_DICT) + + @staticmethod + def GetStyleSheet(sheet_name=None): + """Finds the current style sheet and returns its path. The + lookup is done by first looking in the users config directory + and if it is not found there it looks for one on the system + level and if that fails it returns None. + @param sheet_name: style sheet to look for + @return: full path to style sheet + + """ + if sheet_name: + style = sheet_name + else: + style = Profile_Get('SYNTHEME', 'str') + style = ebmlib.AddFileExtension(style, u'.ess').lower() + + # Get Correct Filename if it exists + for sheet in util.GetResourceFiles(u'styles', trim=False, + get_all=True, title=False): + if sheet.lower() == style: + style = sheet + break + + user = os.path.join(ed_glob.CONFIG['STYLES_DIR'], style) + sysp = os.path.join(ed_glob.CONFIG['SYS_STYLES_DIR'], style) + if os.path.exists(user): + return user + elif os.path.exists(sysp): + return sysp + else: + return None + + def GetSyntaxParams(self): + """Get the set of syntax parameters + @return: list + + """ + return self.syntax_set + + def HasNamedStyle(self, name): + """Checks if a style has been set/loaded or not + @param name: tag name of style to look for + @return: whether item is in style set or not + + """ + return name in self.GetStyleSet() + + def LoadStyleSheet(self, style_sheet, force=False): + """Loads a custom style sheet and returns True on success + @param style_sheet: path to style sheet to load + @keyword force: Force re-parse of style sheet, default is to use cached + data when available + @return: whether style sheet was loaded or not + + """ + if isinstance(style_sheet, basestring) and \ + os.path.exists(style_sheet) and \ + ((force or style_sheet not in StyleMgr.STYLES) or \ + style_sheet != self.style_set): + reader = util.GetFileReader(style_sheet) + if reader == -1: + self.LOG("[ed_style][err] Failed to open style sheet: %s" % style_sheet) + return False + style_data = None + try: + style_data = self.ParseStyleData(reader.read()) + except Exception, msg: + self.LOG("[ed_style][err] Failed to parse style data for %s:" % style_sheet) + return False + ret_val = self.SetStyles(style_sheet, style_data) + reader.close() + return ret_val + elif style_sheet not in StyleMgr.STYLES: + self.LOG("[ed_style][warn] Style sheet %s does not exists" % style_sheet) + # Reset to default style + if Profile_Get('SYNTHEME') != 'default': + Profile_Set('SYNTHEME', 'default') + self.SetStyles('default', DEF_STYLE_DICT) + return False + else: + self.LOG("[ed_style][info] Using cached style data") + return True + + def PackStyleSet(self, style_set): + """Checks the difference of each item in the style set as + compared to the default_style tag and packs any unset value + in the item to be equal to the default style. + @param style_set: style set to pack + @return: style_set with all unset attributes set to match default style + + """ + if isinstance(style_set, dict) and 'default_style' in style_set: + default = style_set['default_style'] + for tag in style_set: + if style_set[tag].IsNull(): + continue + if not style_set[tag].GetFace(): + style_set[tag].SetFace(default.GetFace()) + if not style_set[tag].GetFore(): + style_set[tag].SetFore(default.GetFore()) + if not style_set[tag].GetBack(): + style_set[tag].SetBack(default.GetBack()) + if not style_set[tag].GetSize(): + style_set[tag].SetSize(default.GetSize()) + + # Now need to pack in undefined styles that are part of + # the standard set. + for tag in DEF_STYLE_DICT.keys(): + if tag not in style_set: + if tag == 'select_style': + style_set[tag] = NullStyleItem() + else: + style_set[tag] = default.Clone() + else: + pass + return style_set + + def ParseStyleData(self, style_data): + """Parses a string style definitions read from an Editra Style Sheet. + @param style_data: style sheet data string + @return: dictionary of StyleItems constructed from the style sheet data. + + """ + # Remove all comments + style_data = RE_ESS_COMMENT.sub(u'', style_data) + + # Compact data into a contiguous string + style_data = style_data.replace(u"\r\n", u"").replace(u"\n", u"") + style_data = style_data.replace(u"\t", u"") +# style_data = style_data.replace(u" ", u"") # support old style + + ## Build style data tree + # Tree Level 1 split tag from data + style_tree = [style.split(u"{") for style in style_data.split(u'}')] + if len(style_tree) and len(style_tree[-1]) and not style_tree[-1][0]: + style_tree.pop() + + # Tree Level 2 Build small trees of tag and style attributes + # Tree Level 3 Branch tree into TAG => Attr => Value String + ttree = list(style_tree) + for branch in ttree: + # Check for level 1 syntax errors + if len(branch) != 2: + self.LOG("[ed_style][err] There was an error parsing " + "the syntax data from " + self.style_set) + self.LOG("[ed_style][err] Missing a { or } in Def: " + repr(branch[0])) + ttree.remove(branch) + continue + + tmp2 = [leaf.strip().split(u":") + for leaf in branch[1].strip().split(u";")] + if len(tmp2) and not tmp2[-1][0]: + tmp2.pop() + branch[1] = tmp2 + style_tree = ttree + + # Check for L2/L3 Syntax errors and build a clean dictionary + # of Tags => Valid Attributes + style_dict = dict() + for branch in style_tree: + value = list() + tag = branch[0].replace(u" ", u"") + for leaf in branch[1]: + # Remove any remaining whitespace + leaf = [part.strip() for part in leaf] + if len(leaf) != 2: + self.LOG("[ed_style][err] Missing a : or ; in the " + "declaration of %s" % tag) + elif leaf[0] not in STY_ATTRIBUTES: + self.LOG(("[ed_style][warn] Unknown style attribute: %s" + ", In declaration of %s") % (leaf[0], tag)) + else: + value.append(leaf) + + # Skip all leafless branches + if len(value) != 0: + style_dict[tag] = value + + # Validate leaf values and format into style string + rdict = dict() + for style_def in style_dict: + if not style_def[0][0].isalpha(): + self.LOG("[ed_style][err] The style def %s is not a " + "valid name" % style_def[0]) + else: + style_str = u"" + # Check each definition and validate its items + for attrib in style_dict[style_def]: + values = [ val for val in attrib[1].split() + if val != u"" ] + + v1ok = v2ok = False + # Check that colors are a hex string + n_values = len(values) + if n_values and \ + attrib[0] in "fore back" and RE_HEX_STR.match(values[0]): + v1ok = True + elif n_values and attrib[0] == "size": + if RE_ESS_SCALAR.match(values[0]) or values[0].isdigit(): + v1ok = True + else: + self.LOG("[ed_style][warn] Bad value in %s" + " the value %s is invalid." % \ + (attrib[0], values[0])) + elif n_values and attrib[0] == "face": + # Font names may have spaces in them so join the + # name of the font into one item. + if n_values > 1 and values[1] not in STY_EX_ATTRIBUTES: + tmp = list() + for val in list(values): + if val not in STY_EX_ATTRIBUTES: + tmp.append(val) + values.remove(val) + else: + break + values = [u' '.join(tmp),] + values + v1ok = True + elif n_values and attrib[0] == "modifiers": + v1ok = True + + # Check extra attributes + if len(values) > 1: + for value in values[1:]: + if value not in STY_EX_ATTRIBUTES: + self.LOG("[ed_style][warn] Unknown extra " + \ + "attribute '" + values[1] + \ + "' in attribute: " + attrib[0]) + break + else: + v2ok = True + + if v1ok and v2ok: + value = u",".join(values) + elif v1ok: + value = values[0] + else: + continue + + style_str = u",".join([style_str, + u":".join([attrib[0], value])]) + + # Build up the StyleItem Dictionary + if style_str != u"": + new_item = StyleItem() + value = style_str.strip(u",") + if isinstance(value, basestring): + new_item.SetAttrFromStr(value) + rdict[style_def] = new_item + + return rdict + + def SetGlobalFont(self, fonttag, fontface, size=-1): + """Sets one of the fonts in the global font set by tag + and sets it to the named font. Returns true on success. + @param fonttag: font type identifier key + @param fontface: face name to set global font to + + """ + if hasattr(self, 'fonts'): + self.fonts[fonttag] = fontface + if size > 0: + self.fonts[self.FONT_SIZE] = size + return True + else: + return False + + def SetStyleFont(self, wx_font, primary=True): + """Sets the primary or secondary font and their respective + size values. + @param wx_font: font object to set styles font info from + @keyword primary: Set primary(default) or secondary font + + """ + if primary: + self.fonts[self.FONT_PRIMARY] = wx_font.GetFaceName() + self.fonts[self.FONT_SIZE] = wx_font.GetPointSize() + else: + self.fonts[self.FONT_SECONDARY] = wx_font.GetFaceName() + self.fonts[self.FONT_SIZE2] = wx_font.GetPointSize() + + def SetStyleTag(self, style_tag, value): + """Sets the value of style tag by name + @param style_tag: desired tag name of style definition + @param value: style item to set tag to + @return: bool + + """ + if not isinstance(value, StyleItem): + self.LOG("[ed_style][warn] Bad data in SetStyleTag(%s)" % repr(value)) + return False + + StyleMgr.STYLES[self.style_set][style_tag] = value + return True + + def SetStyles(self, name, style_dict, nomerge=False): + """Sets the managers style data and returns True on success. + @param name: name to store dictionary in cache under + @param style_dict: dictionary of style items to use as managers style + set. + @keyword nomerge: merge against default set or not + + """ + if nomerge: + self.style_set = name + StyleMgr.STYLES[name] = self.PackStyleSet(style_dict) + return True + + # Merge the given style set with the default set to fill in any + # unset attributes/tags + if isinstance(style_dict, dict): + # Check for bad data + for style in style_dict.values(): + if not isinstance(style, StyleItem): + self.LOG("[ed_style][err] Invalid data in style dictionary") + self.style_set = 'default' + return False + + self.style_set = name + defaultd = DEF_STYLE_DICT + dstyle = style_dict.get('default_style', None) + if dstyle is None: + self.LOG("[ed_style][warn] default_style is undefined") + style_dict['default_style'] = defaultd['default_style'].Clone() + + # Set any undefined styles to match the default_style + for tag in defaultd: + if tag not in style_dict: + if tag in ('select_style',): + style_dict[tag] = NullStyleItem() + else: + style_dict[tag] = style_dict['default_style'].Clone() + + StyleMgr.STYLES[name] = self.PackStyleSet(style_dict) + return True + else: + self.LOG("[ed_style][err] SetStyles expects a " \ + "dictionary of StyleItems") + return False + + def SetSyntax(self, synlst): + """Sets the Syntax Style Specs from a list of specifications + @param synlst: [(STYLE_ID, "STYLE_TYPE"), (STYLE_ID2, "STYLE_TYPE2)] + + """ + # Parses Syntax Specifications list, ignoring all bad values + self.UpdateBaseStyles() + valid_settings = list() + for syn in synlst: + if len(syn) != 2: + self.LOG("[ed_style][warn] Bogus Syntax Spec %s" % repr(syn)) + continue + else: + self.StyleSetSpec(syn[0], self.GetStyleByName(syn[1])) + valid_settings.append(syn) + + self.syntax_set = valid_settings + return True + + def StyleDefault(self): + """Clears the editor styles to default + @postcondition: style is reset to default + + """ + self.StyleClearAll() + self.SetCaretForeground(wx.BLACK) + self.Colourise(0, -1) + + def UpdateAllStyles(self, spec_style=None): + """Refreshes all the styles and attributes of the control + @param spec_style: style scheme name + @postcondition: style scheme is set to specified style + + """ + if spec_style and (spec_style != self.style_set): + self.LoadStyleSheet(self.GetStyleSheet(spec_style), force=True) + self.SetSyntax(self.GetSyntaxParams()) + self.Refresh() + + def UpdateBaseStyles(self): + """Updates the base styles of editor to the current settings + @postcondition: base style info is updated + + """ + self.StyleDefault() + self.SetMargins(4, 0) + + # Global default styles for all languages + self.StyleSetSpec(0, self.GetStyleByName('default_style')) + self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, \ + self.GetStyleByName('default_style')) + self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER, \ + self.GetStyleByName('line_num')) + self.StyleSetSpec(wx.stc.STC_STYLE_CONTROLCHAR, \ + self.GetStyleByName('ctrl_char')) + self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT, \ + self.GetStyleByName('brace_good')) + self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD, \ + self.GetStyleByName('brace_bad')) + self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, \ + self.GetStyleByName('guide_style')) + + # wx.stc.STC_STYLE_CALLTIP doesn't seem to do anything + calltip = self.GetItemByName('calltip') + self.CallTipSetBackground(calltip.GetBack()) + self.CallTipSetForeground(calltip.GetFore()) + + sback = self.GetItemByName('select_style') + if not sback.IsNull() and len(sback.GetBack()): + sback = sback.GetBack() + sback = eclib.HexToRGB(sback) + sback = wx.Colour(*sback) + else: + sback = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT) + + # If selection colour is dark make the foreground white + # else use the default settings. + if sum(sback.Get()) < 384: + self.SetSelForeground(True, wx.WHITE) + else: + self.SetSelForeground(True, wx.BLACK) + self.SetSelBackground(True, sback) + + # Causes issues with selecting text when view whitespace is on +# wspace = self.GetItemByName('whitespace_style') +# self.SetWhitespaceBackground(True, wspace.GetBack()) +# self.SetWhitespaceForeground(True, wspace.GetFore()) + + default_fore = self.GetDefaultForeColour() + edge_colour = self.GetItemByName('edge_style') + self.SetEdgeColour(edge_colour.GetFore()) + self.SetCaretForeground(default_fore) + self.SetCaretLineBack(self.GetItemByName('caret_line').GetBack()) + self.Colourise(0, -1) + +#-----------------------------------------------------------------------------# +# Utility Functions + +def NullStyleItem(): + """Create a null style item + @return: empty style item that cannot be merged + + """ + item = StyleItem() + item.null = True + return item + +DEF_STYLE_DICT = \ + {'brace_good' : StyleItem("#FFFFFF", "#0000FF", ex=["bold",]), + 'brace_bad' : StyleItem(back="#FF0000", ex=["bold",]), + 'calltip' : StyleItem("#404040", "#FFFFB8"), + 'caret_line' : StyleItem(back="#D8F8FF"), + 'ctrl_char' : StyleItem(), + 'line_num' : StyleItem(back="#C0C0C0", face="%(secondary)s", \ + size="%(size3)d"), + 'array_style': StyleItem("#EE8B02", + face="%(secondary)s", + ex=["bold",]), + 'btick_style': StyleItem("#8959F6", size="%(size)d", ex=["bold",]), + 'default_style': StyleItem("#000000", "#F6F6F6", \ + "%(primary)s", "%(size)d"), + 'char_style' : StyleItem("#FF3AFF"), + 'class_style' : StyleItem("#2E8B57", ex=["bold",]), + 'class2_style' : StyleItem("#2E8B57", ex=["bold",]), + 'comment_style' : StyleItem("#838383"), + 'decor_style' : StyleItem("#BA0EEA", face="%(secondary)s", + ex=["italic",]), + 'directive_style' : StyleItem("#0000FF", face="%(secondary)s", + ex=["bold",]), + 'dockey_style' : StyleItem("#0000FF"), + 'edge_style' : StyleItem(), # inherit from default + 'error_style' : StyleItem("#DD0101", face="%(secondary)s", + ex=["bold",]), + 'foldmargin_style' : StyleItem(back="#D1D1D1"), + 'funct_style' : StyleItem("#008B8B", ex=["italic",]), + 'global_style' : StyleItem("#007F7F", face="%(secondary)s", + ex=["bold",]), + 'guide_style' : StyleItem("#838383"), + 'here_style' : StyleItem("#CA61CA", face="%(secondary)s", + ex=["bold",]), + 'ideol_style' : StyleItem("#E0C0E0", face="%(secondary)s"), + 'keyword_style' : StyleItem("#A52B2B", ex=["bold",]), + 'keyword2_style' : StyleItem("#2E8B57", ex=["bold",]), + 'keyword3_style' : StyleItem("#008B8B", ex=["bold",]), + 'keyword4_style' : StyleItem("#9D2424"), + 'marker_style' : StyleItem("#FFFFFF", "#000000"), + 'number_style' : StyleItem("#DD0101"), + 'number2_style' : StyleItem("#DD0101", ex=["bold",]), + 'operator_style' : StyleItem("#000000", face="%(primary)s", + ex=["bold",]), + 'pre_style' : StyleItem("#AB39F2", ex=["bold",]), + 'pre2_style' : StyleItem("#AB39F2", "#FFFFFF", ex=["bold",]), + 'regex_style' : StyleItem("#008B8B"), + 'scalar_style' : StyleItem("#AB37F2", face="%(secondary)s", + ex=["bold",]), + 'scalar2_style' : StyleItem("#AB37F2", face="%(secondary)s"), + 'select_style' : NullStyleItem(), # Use system default colour + 'string_style' : StyleItem("#FF3AFF", ex=["bold",]), + 'stringeol_style' : StyleItem("#000000", "#EEC0EE", + "%(secondary)s", ex=["bold", "eol"]), + 'unknown_style' : StyleItem("#FFFFFF", "#DD0101", ex=["bold", "eol"]), + 'userkw_style' : StyleItem() + } + +def MergeFonts(style_dict, font_dict): + """Does any string substitution that the style dictionary + may need to have fonts and their sizes set. + @param style_dict: dictionary of L{StyleItem} + @param font_dict: dictionary of font data + @return: style dictionary with all font format strings substituted in + + """ + for style in style_dict: + st_str = unicode(style_dict[style]) + if u'%' in st_str: + style_dict[style].SetAttrFromStr(st_str % font_dict) + return style_dict + +def MergeStyles(styles1, styles2): + """Merges the styles from styles2 into styles1 overwriting + any duplicate values already set in styles1 with the new + data from styles2. + @param styles1: dictionary of StyleItems to receive merge + @param styles2: dictionary of StyleItems to merge from + @return: style1 with all values from styles2 merged into it + + """ + for style in styles2: + styles1[style] = styles2[style] + return styles1 diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_tab.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_tab.py new file mode 100644 index 0000000..c2de86e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_tab.py @@ -0,0 +1,157 @@ +############################################################################### +# Name: ed_tab.py # +# Purpose: Notebook tab inteface class # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Base class for all views that want to be able to be viewable in the main +notebook. + +@summary: Main notebook tab base class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_tab.py 67542 2011-04-19 00:26:29Z CJP $" +__revision__ = "$Revision: 67542 $" + +#--------------------------------------------------------------------------# +# Imports +import wx + +#--------------------------------------------------------------------------# + +class EdTabBase(object): + """Base class for all tab views to derive from, this class just defines + the abstract interface and some common basic methods. Initialize this + base class after initializing the wx control instance of the subclass. + + """ + def __init__(self): + """Initialize the tab base class""" + super(EdTabBase, self).__init__() + + # Attributes + self._lbl = u'' + self._idx = -1 + + @property + def _nb(self): + """Get the notebook that owns this tab""" + return self.GetParent() + + #---- Methods to override in subclasses ----# + + def DoDeactivateTab(self): + """Called when the tab is moved from the foreground to background""" + pass + + def DoOnIdle(self): + """Called when the notebook is idle and this instance is the active + tab. + + """ + pass + + def DoTabClosing(self): + """Called when the tab has been selected to be closed in the notebook""" + pass + + def DoTabOpen(self, ): + """Called to open a new tab""" + pass + + def DoTabSelected(self): + """Called when the page is selected in the notebook""" + pass + + def GetName(self): + """Get the unique name for this tab control. + @return: (unicode) string + + """ + raise NotImplementedError, "GetName Must be implemented!!" + + def GetTabImage(self): + """Get the Bitmap to use for the tab + @return: wx.Bitmap (16x16) + + """ + return wx.NullBitmap + + def GetTabMenu(self): + """Get the context menu to show on the tab + @return: wx.Menu or None + + """ + return None + + def GetTitleString(self): + """Get the title string to display in the MainWindows title bar + @return: (unicode) string + + """ + return u'' + + def CanCloseTab(self): + """Called when checking if tab can be closed or not + @return: bool + + """ + return True + + def OnTabMenu(self, evt): + """Handle events from this tabs menu + @param evt: menu event + + """ + evt.Skip() + + #---- Common Base Methods ----# + + def GetTabIndex(self): + """Return the index of the tab in the notebook + @return: int + + """ + return self._idx + + def GetTabLabel(self): + """Get the tabs label + @return: string + + """ + return self._lbl + + def SetTabIndex(self, idx): + """Set the tab index + @param idx: int + + """ + self._idx = idx + + def SetTabLabel(self, lbl): + """Set the tabs label + @param lbl: string + + """ + self._lbl = lbl + + def SetTabTitle(self, title): + """Set the notebooks title text for this tab""" + obj_id = self.GetId() + + # Find which page we are and update the text + for page in range(self._nb.GetPageCount()): + ctrl = self._nb.GetPage(page) + if ctrl.GetId() == obj_id: + self._nb.SetPageText(page, title) + break + else: + # TODO: notify of error? + pass + +#--------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_theme.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_theme.py new file mode 100644 index 0000000..73310a5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_theme.py @@ -0,0 +1,418 @@ +############################################################################### +# Name: ed_theme.py # +# Purpose: Icon theme management for Editra # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provide an interface for creating icon themes for Editra. This will allow for +themes to be created, installed, and managed as plugins, which means that they +can be installed as single file instead of dozens of individual image files. + +@summary: Editra's theme interface and implementation + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_theme.py 72247 2012-07-28 22:32:37Z CJP $" +__revision__ = "$Revision: 72247 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import wx + +# Local Imports +import ed_glob +import util +import plugin +from profiler import Profile_Get, Profile_Set +import syntax.synglob as synglob +from syntax.syntax import SYNTAX_IDS + +#--------------------------------------------------------------------------# + +class ThemeI(plugin.Interface): + """Interface for defining an icon theme in Editra + When a icon theme is active Editra's ArtProvider will ask the active + theme that implements this interface to give it a bitmap. The requests + for bitmaps will be numerical ID values that come from ed_glob. These + ID's are associated with different objects in the interface. The names + are descriptive of the object they represent, for reference however + see the implementation of the two main themes (Tango and Nuovo). + + @see: L{ed_glob} + @see: L{syntax.synglob} + + """ + def GetName(self): + """Return the name of this theme. This is used to identify the + theme when the provider looks for resources based on user preferences + + @return: name string + + """ + + def GetMenuBitmap(self, bmp_id): + """Get the menu bitmap associated with the object id + If this theme does not have a resource to provide for this + object return a wx.NullBitmap. + + @return: 16x16 pixel bitmap + + """ + return wx.NullBitmap + + def GetFileBitmap(self, bmp_id): + """Get the filetype bitmap associated with the object id, the + valid object ids are defined in the module syntax.synglob and + are used to request images for menu's and page tabs. The theme + implimenting this interface should at least be able to + provide an image for plain text files and return that for any + unmapped types. + + If this theme does not have a resource to provide for this + object return a wx.NullBitmap. + + @return: 16x16 pixel bitmap + + """ + return wx.NullBitmap + + def GetOtherBitmap(self, bmp_id): + """Get the bitmap from the 'other' icon resources. Valid id's are + identified by a mapping in the ART dictionary. + + If this theme does not have a resource to provide for this + object return a wx.NullBitmap. + + @return: wx.Bitmap + + """ + return wx.NullBitmap + + def GetToolbarBitmap(self, bmp_id): + """Get the toolbar bitmap associated with the object id. The + toolbar icons must be returned as a 32x32 pixel bitmap any + scaling that is needed will be handled by the art provider that + requests the resource. + + If this theme does not have a resource to provide for this + object return a wx.NullBitmap. + + @return: 32x32 pixel bitmap + + """ + return wx.NullBitmap + +#-----------------------------------------------------------------------------# + +class BitmapProvider(plugin.Plugin): + """Plugin that fetches requested icons from the current active theme. + + """ + observers = plugin.ExtensionPoint(ThemeI) + + def __GetCurrentProvider(self): + """Gets the provider of the current theme resources + @return: ThemeI object + + """ + theme = Profile_Get('ICONS', 'str', u'') + for prov in self.observers: + if theme == prov.GetName(): + return prov + + # Case if a theme was deleted while it was the active theme + if theme.lower() != u'default': + Profile_Set('ICONS', u'Default') + + return None + + def _GetTango(self, bmp_id, client): + """Try to get the icon from the default tango theme""" + theme = None + bmp = wx.NullBitmap + for prov in self.observers: + if prov.GetName() == TangoTheme.name: + theme = prov + break + else: + return bmp + + if client == wx.ART_TOOLBAR: + bmp = theme.GetToolbarBitmap(bmp_id) + elif client == wx.ART_MENU: + bmp = theme.GetMenuBitmap(bmp_id) + elif client == wx.ART_OTHER: + bmp = theme.GetOtherBitmap(bmp_id) + else: + pass + + return bmp + + def GetThemes(self): + """Gets a list of the installed and activated themes + @return: list of strings + + """ + return [ name.GetName() for name in self.observers ] + + def GetBitmap(self, bmp_id, client): + """Gets a 16x16 or 32x32 pixel bitmap depending on client value. + May return a NullBitmap if no suitable bitmap can be + found. + + @param bmp_id: id of bitmap to lookup + @param client: wxART_MENU, wxART_TOOLBAR + @see: L{ed_glob} + + """ + prov = self.__GetCurrentProvider() + if prov is not None: + if client == wx.ART_MENU: + bmp = prov.GetMenuBitmap(bmp_id) + elif client == wx.ART_OTHER: + # Backwards compatibility for older interface + if hasattr(prov, 'GetOtherBitmap'): + bmp = prov.GetOtherBitmap(bmp_id) + else: + bmp = wx.NullBitmap + else: + bmp = prov.GetToolbarBitmap(bmp_id) + + if bmp.IsOk(): + return bmp + + # Try to fallback to tango theme when icon lookup fails + bmp = self._GetTango(bmp_id, client) + if bmp.IsOk(): + return bmp + + return wx.NullBitmap + +#-----------------------------------------------------------------------------# +# Default theme data maps +ART = { ed_glob.ID_ABOUT : u'about.png', + ed_glob.ID_ADD : u'add.png', + ed_glob.ID_ADD_BM : u'bmark_add.png', + ed_glob.ID_ADVANCED : u'advanced.png', + ed_glob.ID_BACKWARD : u'backward.png', + ed_glob.ID_BIN_FILE : u'bin_file.png', + ed_glob.ID_CDROM : u'cdrom.png', + ed_glob.ID_CONTACT : u'mail.png', + ed_glob.ID_COPY : u'copy.png', + ed_glob.ID_COMPUTER : u'computer.png', + ed_glob.ID_CUT : u'cut.png', + ed_glob.ID_DELETE : u'delete.png', + ed_glob.ID_DELETE_ALL : u'delete_all.png', + ed_glob.ID_DOCPROP : u'doc_props.png', + ed_glob.ID_DOCUMENTATION : u'docs.png', + ed_glob.ID_DOWN : u'down.png', + ed_glob.ID_EXIT : u'quit.png', + ed_glob.ID_FILE : u'file.png', + ed_glob.ID_FIND : u'find.png', + ed_glob.ID_FIND_REPLACE : u'findr.png', + ed_glob.ID_FIND_RESULTS : u'find.png', + ed_glob.ID_FLOPPY : u'floppy.png', + ed_glob.ID_FOLDER : u'folder.png', + ed_glob.ID_FONT : u'font.png', + ed_glob.ID_FORWARD : u'forward.png', + ed_glob.ID_HARDDISK : u'harddisk.png', + ed_glob.ID_HOMEPAGE : u'web.png', + ed_glob.ID_HTML_GEN : u'html_gen.png', + ed_glob.ID_INDENT : u'indent.png', + ed_glob.ID_LOGGER : u'log.png', + ed_glob.ID_NEW : u'new.png', + ed_glob.ID_NEW_FOLDER : u'newfolder.png', + ed_glob.ID_NEW_WINDOW: u'newwin.png', + ed_glob.ID_NEXT_MARK : u'bmark_next.png', + ed_glob.ID_NEXT_POS : u'forward.png', + ed_glob.ID_OPEN : u'open.png', + ed_glob.ID_PACKAGE : u'package.png', + ed_glob.ID_PASTE : u'paste.png', + ed_glob.ID_PLUGMGR : u'plugin.png', + ed_glob.ID_PRE_MARK : u'bmark_pre.png', + ed_glob.ID_PRE_POS : u'backward.png', + ed_glob.ID_PREF : u'pref.png', + ed_glob.ID_PRINT : u'print.png', + ed_glob.ID_PRINT_PRE : u'printpre.png', + ed_glob.ID_PYSHELL : u'pyshell.png', + ed_glob.ID_REDO : u'redo.png', + ed_glob.ID_REFRESH : u'refresh.png', + ed_glob.ID_REMOVE : u'remove.png', + ed_glob.ID_RTF_GEN : u'rtf_gen.png', + ed_glob.ID_SAVE : u'save.png', + ed_glob.ID_SAVEALL : u'saveall.png', + ed_glob.ID_SAVEAS : u'saveas.png', + ed_glob.ID_SELECTALL : u'selectall.png', + ed_glob.ID_STOP : u'stop.png', + ed_glob.ID_STYLE_EDIT : u'style_edit.png', + ed_glob.ID_TEX_GEN : u'tex_gen.png', + ed_glob.ID_THEME : u'theme.png', + ed_glob.ID_UNDO : u'undo.png', + ed_glob.ID_UNINDENT : u'outdent.png', + ed_glob.ID_UP : u'up.png', + ed_glob.ID_USB : u'usb.png', + ed_glob.ID_WEB : u'web.png', + ed_glob.ID_ZOOM_IN : u'zoomi.png', + ed_glob.ID_ZOOM_OUT : u'zoomo.png', + ed_glob.ID_ZOOM_NORMAL : u'zoomd.png', + ed_glob.ID_READONLY : u'readonly.png', + + # code elements + ed_glob.ID_CLASS_TYPE : u'class.png', + ed_glob.ID_FUNCT_TYPE : u'function.png', + ed_glob.ID_ELEM_TYPE : u'element.png', + ed_glob.ID_VARIABLE_TYPE : u'variable.png', + ed_glob.ID_ATTR_TYPE : u'attribute.png', + ed_glob.ID_PROPERTY_TYPE : u'property.png', + ed_glob.ID_METHOD_TYPE : u'method.png' +} + +# File Type Art +MIME_ART = { synglob.ID_LANG_ADA : u'ada.png', + synglob.ID_LANG_BASH : u'shell.png', + synglob.ID_LANG_BOO : u'boo.png', + synglob.ID_LANG_BOURNE : u'shell.png', + synglob.ID_LANG_C : u'c.png', + synglob.ID_LANG_CPP : u'cpp.png', + synglob.ID_LANG_CSH : u'shell.png', + synglob.ID_LANG_CSS : u'css.png', + synglob.ID_LANG_DIFF : u'diff.png', + synglob.ID_LANG_HTML : u'html.png', + synglob.ID_LANG_JAVA : u'java.png', + synglob.ID_LANG_KSH : u'shell.png', + synglob.ID_LANG_LATEX : u'tex.png', + synglob.ID_LANG_MAKE : u'makefile.png', + synglob.ID_LANG_PASCAL : u'pascal.png', + synglob.ID_LANG_PERL : u'perl.png', + synglob.ID_LANG_PHP : u'php.png', + synglob.ID_LANG_PS : u'postscript.png', + synglob.ID_LANG_PYTHON : u'python.png', + synglob.ID_LANG_RUBY : u'ruby.png', + synglob.ID_LANG_TCL : u'tcl.png', + synglob.ID_LANG_TEX : u'tex.png', + synglob.ID_LANG_TXT : u'text.png', + synglob.ID_LANG_XML : u'xml.png' + } + +#-----------------------------------------------------------------------------# + +class TangoTheme(plugin.Plugin): + """Represents the Tango Icon theme for Editra""" + plugin.Implements(ThemeI) + + name = u'Tango' + + def __GetArtPath(self, client, mime=False): + """Gets the path of the resource directory to get + the bitmaps from. + @param client: wx.ART_MENU/wx.ART_TOOLBAR + @keyword mime: is this a filetype icon lookup + @return: path of art resource + @rtype: string + + """ + clients = { wx.ART_MENU : u"menu", + wx.ART_TOOLBAR : u"toolbar", + wx.ART_OTHER : u"other" } + + # Get the path + if ed_glob.CONFIG['THEME_DIR'] == u'': + theme = util.ResolvConfigDir(os.path.join(u"pixmaps", u"theme")) + ed_glob.CONFIG['THEME_DIR'] = theme + + if mime: + path = os.path.join(ed_glob.CONFIG['THEME_DIR'], + self.GetName(), u'mime') + else: + path = os.path.join(ed_glob.CONFIG['THEME_DIR'], + self.GetName(), + clients.get(client, u"menu")) + + path += os.sep + if os.path.exists(path): + return path + else: + return None + + def GetName(self): + """Get the name of this theme + @return: string + + """ + return TangoTheme.name + + def GetMenuBitmap(self, bmp_id): + """Get a menu bitmap + @param bmp_id: Id of bitmap to look for + + """ + if bmp_id in ART: + path = self.__GetArtPath(wx.ART_MENU, mime=False) + if path is not None: + path = path + ART[bmp_id] + if os.path.exists(path): + return wx.Bitmap(path, wx.BITMAP_TYPE_PNG) + else: + return self.GetFileBitmap(bmp_id) + + return wx.NullBitmap + + def GetFileBitmap(self, bmp_id): + """Get a mime type bitmap from the theme + @param bmp_id: Id of filetype bitmap to look up + @see: L{syntax.synglob} + + """ + path = self.__GetArtPath(wx.ART_MENU, mime=True) + if path is not None and bmp_id in SYNTAX_IDS: + if bmp_id in MIME_ART: + req = path + MIME_ART[bmp_id] + if os.path.exists(req): + return wx.Bitmap(req, wx.BITMAP_TYPE_PNG) + + # Try to fall back to bmp for plain text when above is not found + bkup = path + MIME_ART[synglob.ID_LANG_TXT] + if os.path.exists(bkup): + return wx.Bitmap(bkup, wx.BITMAP_TYPE_PNG) + + return wx.NullBitmap + + def GetOtherBitmap(self, bmp_id): + """Get a other catagory bitmap. + @param bmp_id: Id of art resource + + """ + if bmp_id in ART: + path = self.__GetArtPath(wx.ART_OTHER, mime=False) + if path is not None: + path = path + ART[bmp_id] + if os.path.exists(path): + return wx.Bitmap(path, wx.BITMAP_TYPE_PNG) + + return wx.NullBitmap + + def GetToolbarBitmap(self, bmp_id): + """Get a toolbar bitmap + @param bmp_id: Id of bitmap to look for + @return: wx.NullBitmap or a 32x32 bitmap + + """ + if bmp_id in ART: +# size = Profile_Get('ICON_SZ', default=(24, 24)) + path = self.__GetArtPath(wx.ART_TOOLBAR, mime=False) + if path is not None: +# tpath = os.path.join(path, '24', ART[bmp_id]) +# if size[0] == 24 and os.path.exists(tpath): +# path = tpath +# else: + path = path + ART[bmp_id] + + if os.path.exists(path): + return wx.Bitmap(path, wx.BITMAP_TYPE_PNG) + + return wx.NullBitmap diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_thread.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_thread.py new file mode 100644 index 0000000..e4c0cec --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_thread.py @@ -0,0 +1,35 @@ +############################################################################### +# Name: ed_thread.py # +# Purpose: Provides Thread Pool interface and access # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Implements and provides the interface for dispatching asynchronous jobs through +the Editra Threadpool. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_thread.py 67397 2011-04-05 20:46:23Z CJP $" +__revision__ = "$Revision: 67397 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx + +# Local Imports +import ebmlib + +#-----------------------------------------------------------------------------# + +class EdThreadPool(ebmlib.ThreadPool): + """Singleton ThreadPool""" + __metaclass__ = ebmlib.Singleton + def __init__(self): + super(EdThreadPool, self).__init__(5) # 5 Threads + +#-----------------------------------------------------------------------------# +
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_toolbar.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_toolbar.py new file mode 100644 index 0000000..91a18e4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_toolbar.py @@ -0,0 +1,149 @@ +############################################################################### +# Name: ed_toolbar.py # +# Purpose: Editra's Toolbar # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module creates Editra's toolbar. This toolbar is very simple and only adds +automatic icon theming to whats already available in the base toolbar class. + +@summary: Editra's ToolBar class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_toolbar.py 68340 2011-07-23 14:33:07Z CJP $" +__revision__ = "$Revision: 68340 $" + +#--------------------------------------------------------------------------# +# Dependencies +import wx +import ed_glob +import ed_msg +from profiler import Profile_Get + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# +# Global Variables +TOOL_ID = [ ed_glob.ID_NEW, ed_glob.ID_OPEN, ed_glob.ID_SAVE, ed_glob.ID_PRINT, + ed_glob.ID_UNDO, ed_glob.ID_REDO, ed_glob.ID_COPY, ed_glob.ID_CUT, + ed_glob.ID_PASTE, ed_glob.ID_FIND, ed_glob.ID_FIND_REPLACE ] + +#--------------------------------------------------------------------------# + +class EdToolBar(wx.ToolBar): + """Toolbar wrapper class + @todo: make it more dynamic/configurable + + """ + def __init__(self, parent): + """Initializes the toolbar + @param parent: parent window of this toolbar + + """ + sstyle = wx.TB_HORIZONTAL | wx.NO_BORDER + if wx.Platform == '__WXGTK__': + sstyle = sstyle | wx.TB_DOCKABLE + super(EdToolBar, self).__init__(parent, style=sstyle) + + # Attributes + self._theme = Profile_Get('ICONS') + self.SetToolBitmapSize(Profile_Get('ICON_SZ', 'size_tuple')) + self._PopulateTools() + + # Event Handlers + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + + # Message Handlers + ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED) + + def OnDestroy(self, evt): + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.OnThemeChange) + evt.Skip() + + #---- End Init ----# + + #---- Function Definitions----# + def _PopulateTools(self): + """Sets the tools in the toolbar + @postcondition: all default tools are added to toolbar + + """ + # Place Icons in toolbar + self.AddSimpleTool(ed_glob.ID_NEW, _("New"), _("Start a New File")) + self.AddSimpleTool(ed_glob.ID_OPEN, _("Open"), _("Open")) + self.AddSimpleTool(ed_glob.ID_SAVE, _("Save"), _("Save Current File")) + self.AddSimpleTool(ed_glob.ID_PRINT, _("Print"), + _("Print Current File")) + self.AddSeparator() + self.AddSimpleTool(ed_glob.ID_UNDO, _("Undo"), _("Undo Last Action")) + self.AddSimpleTool(ed_glob.ID_REDO, _("Redo"), _("Redo Last Undo")) + self.AddSeparator() + self.AddSimpleTool(ed_glob.ID_CUT, _("Cut"), + _("Cut Selected Text from File")) + self.AddSimpleTool(ed_glob.ID_COPY, _("Copy"), + _("Copy Selected Text to Clipboard")) + self.AddSimpleTool(ed_glob.ID_PASTE, _("Paste"), + _("Paste Text from Clipboard to File")) + self.AddSeparator() + self.AddSimpleTool(ed_glob.ID_FIND, _("Find"), _("Find Text")) + self.AddSimpleTool(ed_glob.ID_FIND_REPLACE, _("Find/Replace"), + _("Find and Replace Text")) + self.AddSeparator() + + def AddSimpleTool(self, tool_id, lbl, helpstr): + """Overides the default function to allow for easier tool + generation/placement by automatically getting an appropriate icon from + the art provider. + @param tool_id: Id of tool to add + @param lbl: tool label + @param helpstr: tool help string + + """ + if self.GetToolBitmapSize() == (16, 16): + client = wx.ART_MENU + else: + client = wx.ART_TOOLBAR + tool_bmp = wx.ArtProvider.GetBitmap(str(tool_id), client) + wx.ToolBar.AddSimpleTool(self, tool_id, tool_bmp, _(lbl), _(helpstr)) + + def GetToolTheme(self): + """Returns the name of the current toolsets theme + @return: name of icon theme used by this toolbar + + """ + return self._theme + + def OnThemeChange(self, msg): + """Update the icons when the icon theme has changed + @param msg: Message object + + """ + self.ReInit() + + def ReInit(self): + """Re-Initializes the tools in the toolbar + @postcondition: all tool icons are changed to match current theme + + """ + self._theme = Profile_Get('ICONS') + csize = self.GetToolBitmapSize() + nsize = Profile_Get('ICON_SZ', 'size_tuple') + if nsize != csize: + # Size changed must recreate toolbar + wx.CallAfter(self.GetParent().SetupToolBar) + return + + # Change Bitmaps + if self.GetToolBitmapSize() == (16, 16): + client = wx.ART_MENU + else: + client = wx.ART_TOOLBAR + + for tool_id in TOOL_ID: + bmp = wx.ArtProvider.GetBitmap(str(tool_id), client) + self.SetToolNormalBitmap(tool_id, bmp) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_txt.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_txt.py new file mode 100644 index 0000000..a7994f4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_txt.py @@ -0,0 +1,836 @@ +############################################################################### +# Name: Cody Precord # +# Purpose: File abstraction layer and text utilities # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Text/Unicode handling functions and File wrapper class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_txt.py 72103 2012-07-15 15:02:42Z CJP $" +__revision__ = "$Revision: 72103 $" + +#--------------------------------------------------------------------------# +# Imports +import sys +import re +import time +import wx +import codecs +import encodings as enclib +import locale +from StringIO import StringIO + +# Local Imports +from util import Log +from profiler import Profile_Get +import ed_msg +import ebmlib +import ed_thread + +#--------------------------------------------------------------------------# +# Globals + +# The default fallback encoding +DEFAULT_ENCODING = locale.getpreferredencoding() +try: + codecs.lookup(DEFAULT_ENCODING) +except (LookupError, TypeError): + DEFAULT_ENCODING = 'utf-8' + +# File Helper Functions +# NOTE: keep in synch with CheckBom function +BOM = { 'utf-8' : codecs.BOM_UTF8, + 'utf-16' : codecs.BOM, + 'utf-32' : codecs.BOM_UTF32 } + +# Regex for extracting magic comments from source files +# i.e *-* coding: utf-8 *-*, encoding=utf-8, ect... +# The first group from this expression will be the encoding. +RE_MAGIC_COMMENT = re.compile("coding[:=]\s*\"*([-\w.]+)\"*") + +# File Load States +FL_STATE_START = 0 +FL_STATE_READING = 1 +FL_STATE_PAUSED = 2 +FL_STATE_END = 3 +FL_STATE_ABORTED = 4 + +#--------------------------------------------------------------------------# + +class ReadError(Exception): + """Error happened while trying to read the file""" + pass + +class WriteError(Exception): + """Error happened while trying to write the file""" + pass + +#--------------------------------------------------------------------------# + +class EdFile(ebmlib.FileObjectImpl): + """Wrapper for representing a file object that stores data + about the file encoding and path. + + """ + _Checker = ebmlib.FileTypeChecker() + + def __init__(self, path=u'', modtime=0): + """Create the file wrapper object + @keyword path: the absolute path to the file + @keyword modtime: file modification time + + """ + super(EdFile, self).__init__(path, modtime) + + # Attributes + self._magic = dict(comment=None, bad=False) + self.encoding = None + self.bom = None + self._mcallback = list() + self.__buffer = None + self._raw = False # Raw bytes? + self._fuzzy_enc = False + self._job = None # async file read job + + def _SanitizeBOM(self, bstring): + """Remove byte order marks that get automatically added by some codecs""" + for enc in ('utf-8', 'utf-32', 'utf-16'): + bmark = BOM.get(enc) + if bstring.startswith(bmark): + bstring = bstring.lstrip(bmark) + break + return bstring + + def _HandleRawBytes(self, bytes_value): + """Handle prepping raw bytes for return to the buffer + @param bytes_value: raw read bytes + @return: string + + """ + Log("[ed_txt][info] HandleRawBytes called") + if self._magic['comment']: + self._magic['bad'] = True + # Return the raw bytes to put into the buffer + self._raw = True + return '\0'.join(bytes_value)+'\0' + + def _ResetBuffer(self): + Log("[ed_txt][info] Resetting buffer") + if self.__buffer is not None: + self.__buffer.close() + del self.__buffer + self.__buffer = StringIO() + + Encoding = property(lambda self: self.GetEncoding()) + + def AddModifiedCallback(self, callback): + """Set modified callback method + @param callback: callable + + """ + self._mcallback.append(callback) + + def CleanUp(self): + """Cleanup callback""" + pass + + def Clone(self): + """Clone the file object + @return: EdFile + + """ + fileobj = EdFile(self.Path, self.ModTime) + fileobj.SetLastError(self.last_err) + fileobj.SetEncoding(self.encoding) + fileobj.bom = self.bom + fileobj._magic = dict(self._magic) + fileobj._fuzzy_enc = self._fuzzy_enc + for cback in self._mcallback: + fileobj.AddModifiedCallback(cback) + return fileobj + + def DecodeText(self): + """Decode the text in the buffer and return a unicode string. + @return: unicode or str + + """ + assert self.__buffer is not None, "No buffer!" + assert self.encoding is not None, "Encoding Not Set!" + + bytes_value = self.__buffer.getvalue() + ustr = u"" + try: + if not self._fuzzy_enc or not EdFile._Checker.IsBinaryBytes(bytes_value): + if self.bom is not None: + Log("[ed_txt][info] Stripping %s BOM from text" % self.encoding) + bytes_value = bytes_value.replace(self.bom, '', 1) + + Log("[ed_txt][info] Attempting to decode with: %s" % self.encoding) + ustr = bytes_value.decode(self.encoding) + # TODO: temporary...maybe + # Check for utf-16 encodings which use double bytes + # can result in NULLs in the string if decoded with + # other encodings. + if str('\0') in ustr: + Log("[ed_txt][info] NULL terminators found in decoded str") + Log("[ed_txt][info] Attempting UTF-16/32 detection...") + for utf_encoding in ('utf_16', 'utf_32'): + try: + tmpstr = bytes_value.decode(utf_encoding) + except UnicodeDecodeError: + pass + else: + self.encoding = utf_encoding + ustr = tmpstr + Log("[ed_txt][info] %s detected" % utf_encoding) + break + else: + Log("[ed_txt][info] No valid UTF-16/32 bytes detected") + else: + # Binary data was read + Log("[ed_txt][info] Binary bytes where read") + ustr = self._HandleRawBytes(bytes_value) + except (UnicodeDecodeError, LookupError), msg: + Log("[ed_txt][err] Error while reading with %s" % self.encoding) + Log("[ed_txt][err] %s" % msg) + self.SetLastError(unicode(msg)) + self.Close() + # Decoding failed so convert to raw bytes for display + ustr = self._HandleRawBytes(bytes_value) + else: + # Log success + if not self._raw: + Log("[ed_txt][info] Decoded %s with %s" % \ + (self.GetPath(), self.encoding)) + + # Scintilla bug, SetText will quit at first null found in the + # string. So join the raw bytes and stuff them in the buffer instead. + # TODO: are there other control characters that need to be checked + # for besides NUL? + if not self._raw and '\0' in ustr: + # Return the raw bytes to put into the buffer + Log("[ed_txt][info] DecodeText - joining nul terminators") + ustr = '\0'.join(bytes_value)+'\0' + self._raw = True + + if self._raw: + # TODO: wx/Scintilla Bug? + # Replace \x05 with a space as it causes the buffer + # to crash when its inserted. + Log("[ed_txt][info] DecodeText - raw - set encoding to binary") + ustr = ustr.replace('\x05', ' ') + self.SetEncoding('binary') + self._raw = True + + return ustr + + def DetectEncoding(self): + """Try to determine the files encoding + @precondition: File handle has been opened and is valid + @postcondition: encoding and bom attributes will be set + + """ + if self.encoding != None: + msg = ("[ed_txt][info] DetectEncoding, skipping do to user set " + "encoding: %s") % self.encoding + Log(msg) + return + + assert self.Handle is not None, "File handle not initialized" + lines = [ self.Handle.readline() for x in range(2) ] + self.Handle.seek(0) + enc = None + if len(lines): + # First check for a Byte Order Mark + enc = CheckBom(lines[0]) + + # If no byte-order mark check for an encoding comment + if enc is None: + Log("[ed_txt][info] DetectEncoding - Check magic comment") + self.bom = None + if not self._magic['bad']: + enc = CheckMagicComment(lines) + if enc: + self._magic['comment'] = enc + else: + Log("[ed_txt][info] File Has %s BOM" % enc) + self.bom = BOM.get(enc, None) + + if enc is None: + Log("[ed_txt][info] Doing brute force encoding check") + enc = GuessEncoding(self.GetPath(), 4096) + + if enc is None: + self._fuzzy_enc = True + enc = Profile_Get('ENCODING', default=DEFAULT_ENCODING) + + Log("[ed_txt][info] DetectEncoding - Set Encoding to %s" % enc) + self.encoding = enc + + def EncodeText(self): + """Do a trial run of encoding all the text to ensure that we can + determine an encoding that will correctly be able to write the data + to disk. + @return: bool + + """ + bOk = True + txt = self.__buffer.read(8) + self.__buffer.seek(0) + if not ebmlib.IsUnicode(txt): + # Already a string so nothing to do + return bOk + + encs = GetEncodings() + if self.encoding is None: + self.encoding = Profile_Get('ENCODING', default=DEFAULT_ENCODING) + encs.insert(0, self.encoding) + cenc = self.encoding + + readsize = min(self.__buffer.len, 4096) + for enc in encs: + self.__buffer.seek(0) + try: + tmpchars = self.__buffer.read(readsize) + while len(tmpchars): + tmpchars.encode(enc) + tmpchars = self.__buffer.read(readsize) + self.encoding = enc + self.__buffer.seek(0) + self.ClearLastError() + except LookupError, msg: + Log("[ed_txt][err] Invalid encoding: %s" % enc) + Log("[ed_txt][err] %s" % msg) + self.SetLastError(unicode(msg)) + except UnicodeEncodeError, msg: + Log("[ed_txt][err] Failed to encode text with %s" % enc) + Log("[ed_txt][err] %s" % msg) + self.SetLastError(unicode(msg)) + else: + break + else: + bOk = False + raise WriteError("Failed to encode text to byte string") + + # Log if the encoding changed due to encoding errors + if self.encoding != cenc: + Log("[ed_txt][warn] Used encoding %s differs from original %s" %\ + (self.encoding, cenc)) + + self.__buffer.seek(0) + return bOk + + def FireModified(self): + """Fire the modified callback(s)""" + remove = list() + for idx, mcallback in enumerate(self._mcallback): + try: + mcallback() + except: + remove.append(idx) + + # Cleanup any bad callbacks + if len(remove): + remove.reverse() + for idx in remove: + self._mcallback.pop(idx) + + def GetEncoding(self): + """Get the encoding used by the file it may not be the + same as the encoding requested at construction time + @return: string encoding name + + """ + if self.encoding is None: + # Guard against early entry + return Profile_Get('ENCODING', default=DEFAULT_ENCODING) + return self.encoding + + def GetMagic(self): + """Get the magic comment if one was present + @return: string or None + + """ + return self._magic['comment'] + + def HasBom(self): + """Return whether the file has a bom byte or not + @return: bool + + """ + return self.bom is not None + + def IsRawBytes(self): + """Were only raw bytes read during the last read operation? + @return: bool + + """ + return self._raw + + def IsReadOnly(self): + """Return as read only when file is read only or if raw bytes""" + return super(EdFile, self).IsReadOnly() or self.IsRawBytes() + + def Read(self, chunk=512): + """Get the contents of the file as a string, automatically handling + any decoding that may be needed. + @keyword chunk: read size + @return: unicode str + @throws: ReadError Failed to open file for reading + + """ + if self.DoOpen('rb'): + self.DetectEncoding() + + if self.encoding is None: + # fall back to user setting + self.encoding = Profile_Get('ENCODING', default=DEFAULT_ENCODING) + Log(("[ed_txt][warn] Failed to detect encoding " + "falling back to default: %s") % self.encoding) + + self._ResetBuffer() + self._raw = False + + Log("[ed_txt][info] Read - Start reading") + tmp = self.Handle.read(chunk) + while len(tmp): + self.__buffer.write(tmp) + tmp = self.Handle.read(chunk) + Log("[ed_txt][info] Read - End reading") + + self.Close() + txt = self.DecodeText() + self.SetModTime(ebmlib.GetFileModTime(self.GetPath())) + self._ResetBuffer() + return txt + else: + Log("[ed_txt][err] Read Error: %s" % self.GetLastError()) + raise ReadError, self.GetLastError() + + def ReadAsync(self, control): + """Read the file asynchronously on a separate thread + @param control: text control to send text to + + """ + Log("[ed_txt][info] EdFile.ReadAsync()") + pid = control.GetTopLevelParent().Id + filesize = ebmlib.GetFileSize(self.GetPath()) + ed_msg.PostMessage(ed_msg.EDMSG_PROGRESS_STATE, (pid, 1, filesize)) + # Fork off async job to threadpool + self._job = FileReadJob(control, self.ReadGenerator, 4096) + ed_thread.EdThreadPool().QueueJob(self._job.run) + + def ReadGenerator(self, chunk=512): + """Get the contents of the file as a string, automatically handling + any decoding that may be needed. + + @keyword chunk: read size + @return: unicode (generator) + @throws: ReadError Failed to open file for reading. + + """ + if self.DoOpen('rb'): + # Throttle yielded text to reduce event over head + filesize = ebmlib.GetFileSize(self.Path) + throttle = max(chunk, filesize/100) + + self.DetectEncoding() + try: + # Must use codec reader to ensure correct number of + # bytes are read in to be decoded. + reader = codecs.getreader(self.Encoding)(self.Handle) + buffered_data = StringIO() + while True: + tmp = reader.read(chunk) + if not len(tmp): + if buffered_data.len: + yield buffered_data.getvalue() + buffered_data.close() + break + + buffered_data.write(tmp) + if buffered_data.len >= throttle: + yield buffered_data.getvalue() + buffered_data.close() + buffered_data = StringIO() + except Exception, msg: + Log("[ed_txt][err] Error while reading with %s" % self.Encoding) + Log("[ed_txt][err] %s" % msg) + self.SetLastError(unicode(msg)) + self.Close() + if self._magic['comment']: + self._magic['bad'] = True + + Log("[ed_txt][info] Decoded %s with %s" % (self.Path, self.Encoding)) + self.SetModTime(ebmlib.GetFileModTime(self.Path)) + else: + raise ReadError, self.GetLastError() + + def RemoveModifiedCallback(self, callback): + """Remove a registered callback + @param callback: callable to remove + + """ + if callback in self._mcallback: + self._mcallback.remove(callback) + + def ResetAll(self): + """Reset all attributes of this file""" + super(EdFile, self).ResetAll() + self._ResetBuffer() + self._magic = dict(comment=None, bad=False) + self.encoding = Profile_Get('ENCODING', default=DEFAULT_ENCODING) + self.bom = None + + def SetEncoding(self, enc): + """Explicitly set/change the encoding of the file + @param enc: encoding to change to + + """ + if enc is None: + enc = DEFAULT_ENCODING + self.encoding = enc + + def ReadLines(self): + """Get the contents of the file as a list of lines + @return: list of strings + + """ + raise NotImplementedError + + def Write(self, value): + """Write the given value to the file + @param value: (Unicode) String of text to write to disk + @note: exceptions are allowed to be raised for the writing + @throws: WriteError Failed to open file for writing + @throws: UnicodeEncodeError Failed to encode text using set encoding + + """ + ctime = time.time() + Log("[ed_txt][info] Write - Called: %s - Time: %d" % (self.Path, ctime)) + + # Check if a magic comment was added or changed + self._ResetBuffer() + self.__buffer.write(value) + self.__buffer.seek(0) + enc = CheckMagicComment([ self.__buffer.readline() for x in range(2) ]) + self.__buffer.seek(0) + + # Update encoding if necessary + if enc is not None: + Log("[ed_txt][info] Write: found magic comment: %s" % enc) + self.encoding = enc + + # Encode to byte string + # Do before opening file so that encoding failures don't cause file + # data to get lost! + if self.EncodeText(): + Log("[ed_txt][info] Write Successful test encode with %s" % self.Encoding) + + # Open and write the file + if self.DoOpen('wb'): + Log("[ed_txt][info] Opened %s, writing as %s" % (self.Path, self.Encoding)) + + if self.HasBom(): + Log("[ed_txt][info] Adding BOM back to text") + self.Handle.write(self.bom) + + # Write the file to disk + chunk = min(self.__buffer.len, 4096) + buffer_read = self.__buffer.read + filewrite = self.Handle.write + fileflush = self.Handle.flush + sanitize = self._SanitizeBOM + tmp = buffer_read(chunk) + while len(tmp): + tmp_bytes = sanitize(tmp.encode(self.Encoding)) + filewrite(tmp_bytes) + fileflush() + tmp = buffer_read(chunk) + + self._ResetBuffer() # Free buffer + self.Close() + Log("[ed_txt][info] %s was written successfully" % self.Path) + else: + self._ResetBuffer() + raise WriteError, self.GetLastError() + + Log("[ed_txt][info] Write - Complete: %s - Time: %d" % + (self.Path, time.time() - ctime)) + +#-----------------------------------------------------------------------------# + +class FileReadJob(object): + """Job for running an async file read in a background thread""" + def __init__(self, receiver, task, *args, **kwargs): + """Create the thread + @param receiver: Window to receive events + @param task: generator method to call + @param *args: positional arguments to pass to task + @param **kwargs: keyword arguments to pass to task + + """ + super(FileReadJob, self).__init__() + + # Attributes + self.cancel = False + self._task = task + self.receiver = receiver + self._args = args + self._kwargs = kwargs + self.pid = receiver.TopLevelParent.Id + + def run(self): + """Read the text""" + evt = FileLoadEvent(edEVT_FILE_LOAD, wx.ID_ANY, None, FL_STATE_START) + wx.PostEvent(self.receiver, evt) + time.sleep(.75) # give ui a chance to get ready + + count = 1 + for txt in self._task(*self._args, **self._kwargs): + if self.cancel: + break + + evt = FileLoadEvent(edEVT_FILE_LOAD, wx.ID_ANY, txt) + evt.SetProgress(count * self._args[0]) + wx.PostEvent(self.receiver, evt) + count += 1 + + evt = FileLoadEvent(edEVT_FILE_LOAD, wx.ID_ANY, None, FL_STATE_END) + wx.PostEvent(self.receiver, evt) + + def Cancel(self): + """Cancel the running task""" + self.cancel = True + +#-----------------------------------------------------------------------------# + +edEVT_FILE_LOAD = wx.NewEventType() +EVT_FILE_LOAD = wx.PyEventBinder(edEVT_FILE_LOAD, 1) +class FileLoadEvent(wx.PyEvent): + """Event to signal that a chunk of text haes been read""" + def __init__(self, etype, eid, value=None, state=FL_STATE_READING): + """Creates the event object""" + super(FileLoadEvent, self).__init__(eid, etype) + + # Attributes + self._state = state + self._value = value + self._prog = 0 + + def HasText(self): + """Returns true if the event has text + @return: bool whether the event contains text + + """ + return self._value is not None + + def GetProgress(self): + """Get the current progress of the load""" + return self._prog + + def GetState(self): + """Get the state of the file load action + @return: int (FL_STATE_FOO) + + """ + return self._state + + def GetValue(self): + """Returns the value from the event. + @return: the value of this event + + """ + return self._value + + def SetProgress(self, progress): + """Set the number of bytes that have been read + @param progress: int + + """ + self._prog = progress + +#-----------------------------------------------------------------------------# +# Utility Function +def CheckBom(line): + """Try to look for a bom byte at the beginning of the given line + @param line: line (first line) of a file + @return: encoding or None + + """ + Log("[ed_txt][info] CheckBom called") + has_bom = None + # NOTE: MUST check UTF-32 BEFORE utf-16 + for enc in ('utf-8', 'utf-32', 'utf-16'): + bom = BOM[enc] + if line.startswith(bom): + has_bom = enc + break + return has_bom + +def CheckMagicComment(lines): + """Try to decode the given text on the basis of a magic + comment if one is present. + @param lines: list of lines to check for a magic comment + @return: encoding or None + + """ + Log("[ed_txt][info] CheckMagicComment: %s" % str(lines)) + enc = None + for line in lines: + match = RE_MAGIC_COMMENT.search(line) + if match: + enc = match.group(1) + try: + codecs.lookup(enc) + except LookupError: + enc = None + break + + Log("[ed_txt][info] MagicComment is %s" % enc) + return enc + +def DecodeString(string, encoding=None): + """Decode the given string to Unicode using the provided + encoding or the DEFAULT_ENCODING if None is provided. + @param string: string to decode + @keyword encoding: encoding to decode string with + + """ + if encoding is None: + encoding = DEFAULT_ENCODING + + if not ebmlib.IsUnicode(string): + try: + rtxt = string.decode(encoding) + except Exception, msg: + Log("[ed_txt][err] DecodeString with %s failed" % encoding) + Log("[ed_txt][err] %s" % msg) + rtxt = string + return rtxt + else: + # The string is already unicode so just return it + return string + +def EncodeString(string, encoding=None): + """Try and encode a given unicode object to a string + with the provided encoding returning that string. The + default encoding will be used if None is given for the + encoding. + @param string: unicode object to encode into a string + @keyword encoding: encoding to use for conversion + + """ + if not encoding: + encoding = DEFAULT_ENCODING + + if ebmlib.IsUnicode(string): + try: + rtxt = string.encode(encoding) + except LookupError: + rtxt = string + return rtxt + else: + return string + +def FallbackReader(fname): + """Guess the encoding of a file by brute force by trying one + encoding after the next until something succeeds. + @param fname: file path to read from + @todo: deprecate this method + + """ + txt = None + with open(fname, 'rb') as handle: + byte_str = handle.read() + for enc in GetEncodings(): + try: + txt = byte_str.decode(enc) + except Exception, msg: + continue + else: + return (enc, txt) + + return (None, None) + +def GuessEncoding(fname, sample): + """Attempt to guess an encoding + @param fname: filename + @param sample: pre-read amount + @return: encoding or None + + """ + for enc in GetEncodings(): + try: + with open(fname, 'rb') as handle: + with codecs.getreader(enc)(handle) as reader: + value = reader.read(sample) + if str('\0') in value: + continue + else: + return enc + except Exception, msg: + continue + return None + +def GetEncodings(): + """Get a list of possible encodings to try from the locale information + @return: list of strings + + """ + encodings = list() + encodings.append(Profile_Get('ENCODING', None)) + + try: + encodings.append(locale.getpreferredencoding()) + except: + pass + + encodings.append('utf-8') + + try: + if hasattr(locale, 'nl_langinfo'): + encodings.append(locale.nl_langinfo(locale.CODESET)) + except: + pass + try: + encodings.append(locale.getlocale()[1]) + except: + pass + try: + encodings.append(locale.getdefaultlocale()[1]) + except: + pass + encodings.append(sys.getfilesystemencoding()) + encodings.append('utf-16') + encodings.append('utf-16-le') # for files without BOM... + encodings.append('latin-1') + + # Normalize all names + normlist = [ enclib.normalize_encoding(enc) for enc in encodings if enc] + + # Clean the list for duplicates and None values + rlist = list() + codec_list = list() + for enc in normlist: + if enc is not None and len(enc): + enc = enc.lower() + if enc not in rlist: + # Ascii is useless so ignore it (ascii, us_ascii, ...) + if 'ascii' in enc: + continue + + try: + ctmp = codecs.lookup(enc) + if ctmp.name not in codec_list: + codec_list.append(ctmp.name) + rlist.append(enc) + except LookupError: + pass + return rlist diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_vim.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_vim.py new file mode 100644 index 0000000..2fea948 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_vim.py @@ -0,0 +1,1421 @@ +############################################################################### +# Name: ed_vim.py # +# Purpose: Vim emulation # +# Author: Hasan Aljudy # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +Vim emulation class and helper methods to implement vim emulation in Editra's +text buffer. + +""" + +__author__ = "Hasan Aljudy" +__cvsid__ = "$Id: ed_vim.py 71184 2012-04-11 23:17:52Z CJP $" +__revision__ = "$Revision: 71184 $" + +# ---------------------------------------------------------------------------- # +# Imports +import wx +import re +import string + +# Local Imports +import ebmlib + +# ---------------------------------------------------------------------------- # + +# TODO:CJP maybe replace all repeatable methods with this decorator to reduce +# repeated code. NOTE: may need to name different as the word repeat +# is used in this module in many places. +#def repeat(funct, count=1): +# def rwrap(*args, **kwargs): +# for i in range(count): +# funct() +# return rwrap + +# ---------------------------------------------------------------------------- # + +def Parse(cmd, editor): + """Parses a command and (if applicable) executes it on an editor + @param cmd: the command string + @param editor: a proxy object used to issue commands to the editor + @return: boolean as a signal to the caller as to whether it should + clear its command buffer. + i.e. True if command is handled or invalid + False if we need more input before we can execute the command + + """ + handled = True + handler = GetHandler(cmd) + if handler is None: + if cmd.isdigit(): + handled = False + else: + need_more = DoHandle(handler, cmd, editor) + if need_more: + handled = False + return handled + +# ---------------------------------------------------------------------------- # + +class EditraCommander(object): + """Proxy object that sends commands to the editor + + The purpose of this class is to make vim support more abstract and portable + so in theory one could add Vim Emulation to another editor using this module + by just creating a commander object for it and re-implementing all of these + methods defined below. + + The methods are based on turtle geometry. Everything is relative to the + position of the cursor. Commands shouldn't take a position argument; they + should all work on the current position of the cursor. + + """ + def __init__(self, keyprocessor): + super(EditraCommander, self).__init__() + + # Attributes + self.keyprocessor = keyprocessor + self.stc = keyprocessor.stc + self.LastChangeCommand = None + self.LastInsertedText = None + self.InsertRepeat = 1 + self.CaretStack = [] + self.ColumnStack = [] + self.ScrollStack = [] + self.LastFindChar = None + self._Bookmarks = {} + + @property + def STC(self): + return self.stc + + def InsertMode(self): + """Put editor in insert mode""" + self.keyprocessor.InsertMode() + + def ReplaceMode(self): + """Put editor in replace mode""" + self.keyprocessor.ReplaceMode() + + def VisualMode(self): + """Put editor in visual (selection) mode""" + self.keyprocessor.VisualMode() + + def NormalMode(self): + """Put editor in normal (command) mode""" + self.keyprocessor.NormalMode() + + def IsNormalMode(self): + return self.keyprocessor.IsNormalMode() + + def IsInsertMode(self): + return self.keyprocessor.IsInsertMode() + + def InsertRepetition(self): + """Repeat last inserted text according to the value that was set + in SetInsertRepeat + + """ + if self.InsertRepeat > 1: + self.RepeatChangeCommand(self.InsertRepeat - 1) + self.InsertRepeat = 1 + + def IsAtLineEnd(self): + lnum = self.stc.GetCurrentLine() + epos = self.stc.GetLineEndPosition(lnum) + return epos == self._GetPos() + + def IsAtLineStart(self): + """Is the cursor currently at the start of a line + @return: bool + + """ + return self._GetCol() == 0 + + def Undo(self, repeat): + """Undo actions in the buffer + @param repeat: int + + """ + for i in range(repeat): + self.stc.Undo() + + def Redo(self, repeat): + """Redo actions in the buffer + @param repeat: int + + """ + for i in range(repeat): + self.stc.Redo() + + def _GetPos(self): + """Get caret position""" + return self.stc.GetCurrentPos() + + def _SetPos(self, pos): + """Set caret position""" + self.stc.GotoPos(pos) + + def SelectLines(self, repeat): + """Select specified number of lines starting with current line + and going down + @param repeat: int + + """ + cline = self.stc.GetCurrentLine() + lline = self.stc.GetLineCount() - 1 + self.GotoLineStart() + if cline == lline: + cpos = self.stc.GetCurrentPos() - len(self.stc.GetEOLChar()) + cpos = max(0, cpos) + self.stc.GotoPos(cpos) + self.PushCaret() + self.MoveDown(repeat) + self.StartSelection() + self.PopCaret() + self.EndSelection() + + def PushCaret(self): + """Pushes caret position for later restoration""" + self.CaretStack += [self._GetPos()] + + def PopCaret(self, restore=True): + """If no parameters are sent, restores caret position. If on the + other hand, the restore keyword is set to false, the caret is not + restored, but the last pushed value is discarded + @keyword restore: bool + + """ + pos = self.CaretStack[-1] + self.CaretStack = self.CaretStack[:-1] + if restore: + self._SetPos(pos) + + def PushColumn(self): + """Push column position for later restoration""" + self.ColumnStack += [self._GetCol()] + + def PopColumn(self, restore=True): + """Pop caret position, and optionally discard it + @keyword restore: if set to False, column will be discarded + + """ + column = self.ColumnStack[-1] + self.ColumnStack = self.ColumnStack[:-1] + if restore: + self.GotoColumn(column) + + def PushScroll(self): + """Push current scrolling state for later restoration""" + self.ScrollStack += [self.stc.GetFirstVisibleLine()] + + def PopScroll(self, restore=True): + """If not parameters are sent, restores the scrolling state. If on the + other hadn, the restore keywords it set to false, then the last pushed + scroll state is discarded + @keyword restore: bool + + """ + line = self.ScrollStack[-1] + self.ScrollStack[:-1] + if restore: + self.stc.ScrollToLine(line) + + def _IsLine(self, text): + """Check if text ends with EOL + @param text: string + + """ + eol = self.stc.GetEOLChar() + eol_len = len(eol) + if len(text) > eol_len: + return text[-len(eol):] == eol + else: + return False + + def _GetCol(self): + """Get the X position of the caret, aka column""" + return self.stc.GetColumn(self._GetPos()) + + def _SetCol(self, col): + """Set the X position of the caret + @param col: int + + """ + self.stc.GotoColumn(col) + + def GotoColumn(self, column): + """Goto the specified column number on the current line""" + self._SetCol(column) + self.stc.ChooseCaretX() + + def StartSelection(self): + """Record the starting place for selection + Nothing is sent to the actual text control, just some internal + state is recorded. + @see: EndSelection + + """ + self._Anchor = self._GetPos() + + def EndSelection(self): + """Set the selection to start from the starting position as it was set + by StartSelection to the current caret position + + It doesn't matter whether the starting position is before or after the + ending position + + """ + self.stc.SetSelection(self._Anchor, self._GetPos()) + + def ExtendSelection(self): + """If the selection was already ended, and the caret moved, this method + will extend the selection to the new caret position. + + """ + self.EndSelection() # happens to be the same implementation .. + + def Deselect(self): + """Unselect. Puts caret to the (visual) start of selection""" + start, end = self._GetSelectionRange() + self._SetPos(start) + self.StartSelection() + self.EndSelection() + + def GotoLine(self, line): + """Goto the start of indentation of given line""" + # PostionFromLine returns the position past the last character on the + # line. So need to look at previous line to get the correct position. + pos = self.stc.PositionFromLine(max(0,line-1)) + self._SetPos(pos) + self.GotoIndentStart() + + def GotoLastLine(self): + self.GotoLine(self.stc.GetLineCount()) + + def GotoLineStart(self): + """Goto the beginning of the current line""" + self.stc.Home() + + def GotoIndentStart(self): + """Goto to the first non-space character on the current line""" + self.stc.GotoIndentPos() + + def GotoLineEnd(self): + """Goto the end of the current line""" + self.stc.LineEnd() + + def OpenLine(self): + """Open a new line below the current line""" + # TODO: watch out if AutoIndent gets "fixed" so that it doesn't + # open a new line by itself! + self.GotoLineEnd() + self.stc.AutoIndent() + + def OpenLineUp(self): + """Open a new line above the current line""" + self.MoveUp() + self.OpenLine() + + def BeginUndoAction(self): + self.stc.BeginUndoAction() + + def EndUndoAction(self): + self.stc.EndUndoAction() + + def MoveUp(self, repeat=1): + """Move caret up + @keyword repeat: int + + """ + for i in range(repeat): + self.stc.LineUp() + + def MoveDown(self, repeat=1): + """Move caret down + @keyword repeat: int + + """ + for i in range(repeat): + self.stc.LineDown() + + def MoveRight(self, repeat=1): + """Move position to the right + @keyword repeat: int + + """ + self.stc.MoveCaretPos(repeat) + + def MoveLeft(self, repeat=1): + """Move the caret postion to the left + @keyword repeat: int + + """ + self.stc.MoveCaretPos(-repeat) + + def MoveForward(self, repeat=1): + """Move the caret position to the right""" + self.MoveRight(repeat) + + def MoveBack(self, repeat=1): + """Move the caret position to the left""" + self.MoveLeft(repeat) + + def NextWord(self, repeat=1): + """Move to beginning of next word""" + for i in range(repeat): + self.stc.WordRight() + + def NextWordBig(self, repeat=1): + """Move to beginning of next Word (words are separated by space)""" + # TODO:CJP Test on empty document, possible error condition + for i in range(repeat): + self.stc.WordRight() + while self.GetChar(-1) and not self.GetChar(-1).isspace(): + self.stc.WordRight() + + def WordEnd(self, repeat=1): + """Move to end of this word""" + for i in range(repeat): + self.stc.WordRightEnd() + + def WordEndBig(self, repeat=1): + """Move to end of this Word (words are separated by space)""" + # TODO:CJP Test on empty document, possible error condition + for i in range(repeat): + self.stc.WordRightEnd() + while self.GetChar() and not self.GetChar().isspace(): + self.stc.WordRightEnd() + + def BackWord(self, repeat=1): + """Move back to start of word""" + for i in range(repeat): + self.stc.WordLeft() + + def BackWordBig(self, repeat=1): + """Move back to start of Word (words are separated by space)""" + # TODO:CJP Test on empty document, possible error condition + for i in range(repeat): + self.stc.WordLeft() + while self.GetChar(-1) and not self.GetChar(-1).isspace(): + self.stc.WordLeft() + + def BackWordPart(self, repeat=1): + """Move back to start of word part""" + for i in range(repeat): + self.stc.WordPartLeft() + + def WordPartEnd(self, repeat=1): + """Move to the end of the word part""" + for i in range(repeat): + self.stc.WordPartRight() + + def ParaUp(self, repeat=1): + """Move the caret one paragraph up""" + for i in range(repeat): + self.stc.ParaUp() + + def ParaDown(self, repeat=1): + """Move the caret one paragraph down""" + for i in range(repeat): + self.stc.ParaDown() + + def RegexSearch(self, text, back=False): + """Search for a regex expression + @param text: search string + @keyword back: seach in reverse + + """ + # TODO:CJP using the StyledTextCtrl's regex searching is not as + # powerful as using Editras SearchEngine. + self.stc.SearchText(text, regex=True, back=back) + if back and self.HasSelection(): + # Let the caret pos be at the end of the selection + start, end = self._GetSelectionRange() + self.stc.SetSelection(start, end) + + def GotoScreenTop(self): + """Goto first visible line""" + self.stc.GotoIndentPos(self.stc.GetFirstVisibleLine()) + + def GotoScreenMiddle(self): + """Goto to the middle line on the screen""" + self.stc.GotoIndentPos(self.stc.GetMiddleVisibleLine()) + + def GotoScreenLast(self): + """Goto last visible line""" + self.stc.GotoIndentPos(self.stc.GetLastVisibleLine()) + + def _EnsureCaretVisible(self): + """Smartly scroll view to make caret visible if it's out of view""" + first = self.stc.GetFirstVisibleLine() + lines = self.stc.LinesOnScreen() + current = self.stc.GetCurrentLine() + if current in range(first, first + lines): + # supposedly visible! XXX: doesn't account for folding + # TODO:CJP to ensure caret is visible call EnsureCaretVisible + return None + + if current < first: + amt = 0.7 + else: + amt = 0.3 + self._Scroll(amt) + + def _Scroll(self, amt): + """Scroll to the current line. For example _Scroll(0.5) scrolls the + current line to the middle of the screen + @param amt: number between 0 and 1 signifying percentage + + """ + lines = self.stc.LinesOnScreen() - 1 + current = self.stc.GetCurrentLine() + diff = int(lines * amt) + self.stc.ScrollToLine(current - diff) + + def ScrollTop(self): + """Scroll such that the current line is the first visible line""" + self._Scroll(0) + + def ScrollMiddle(self): + """Scroll such that the current line is in the middle of the screen""" + self._Scroll(0.5) + + def ScrollBottom(self): + """Scroll such that the current line is the last visible line""" + self._Scroll(1) + + def _SelectIdentifierUnderCaret(self): + """If nothing is selected, select the identifier under caret, otherwise + keeps selection as is. + @return: selected text + + """ + ident = self.GetSelectedText() + if ident: + return ident + + self.WordEnd() + self.StartSelection() + self.BackWord() + self.EndSelection() + ident = self.GetSelectedText() + return ident + + def _NextIdent(self, repeat=1, back=False): + """Jump to the next (or previous) occurance of identifier + under caret or selected text. + + @note: Holds common code between NextIdent and PrevIdent + @see: NextIdent + @see: PrevIdent + + """ + ident = self._SelectIdentifierUnderCaret() + self.PushCaret() + self.PushScroll() + if not ident: + return + + for i in range(repeat): + if back: + self._GotoSelectionStart() + else: + self._GotoSelectionEnd() + + result = self.stc.SearchText(ident, back=back) + if result == -1: + break + + self.PopCaret(result == -1) + self.PopScroll() + self._EnsureCaretVisible() + + def NextIdent(self, repeat=1): + """Find next occurance of identifier under cursor""" + self._NextIdent(repeat) + + def PrevIdent(self, repeat=1): + """Find the previous occurrence of identifier under cursor""" + self._NextIdent(repeat, back=True) + + def InsertText(self, text): + """Insert some text at the current caret position and advance caret + The inserted text is remembered so it can be repeated. + @param text: string + + """ + self.keyprocessor.InsertText(self._GetPos(), text) + self.MoveForward(len(text)) + + def SetInsertRepeat(self, repeat): + """Set how many times to repeat the last inserted text when + InsertRepetition is called. + + """ + self.InsertRepeat = repeat + + def SetLastChangeCommand(self, cmd): + """Rememer this command as the last change cmmand so that it gets + repeated when RepeatChangeCommand is called. + + """ + self.LastChangeCommand = cmd + + def SetLastInsertedText(self, text): + """Set this as the last inserted text so it gets repeated when + InsertRepetition is called. + + """ + self.LastInsertedText = text + + def RepeatChangeCommand(self, repeat=1): + """Repeat the last change command as set by SetLastChangeCommand""" + if not self.LastChangeCommand: + return + + self.BeginUndoAction() + for i in range(repeat): + self.LastChangeCommand() + self.InsertText(self.LastInsertedText) + self.EndUndoAction() + + def GetChar(self, dist=1): + """Get the character (or text) under caret + @param dist: length of text to get, negative values can be used to get + the text before the caret + + """ + pos = self._GetPos() + start, end = minmax(pos, pos + dist) + start = max(0, start) + end = min(end, self.stc.GetLength()) + return self.stc.GetTextRange(start, end) + + def GetSelectedText(self): + """Get the selected text + @return: Unicode + + """ + return self.stc.GetSelectedText() + + def HasSelection(self): + """Detects if there's anything selected + @return: bool + + """ + return len(self.GetSelectedText()) > 0 + + def SetRegister(self, reg='"'): + """Set the current working clipboard (aka register) to given name""" + ebmlib.Clipboard.Switch(reg) + + def YankSelection(self): + """Copy the current selection to the clipboard""" + ebmlib.Clipboard.Set(self.GetSelectedText()) + + def DeleteSelection(self): + """Yank selection and delete it""" + start, end = self._GetSelectionRange() + self.stc.BeginUndoAction() + self.YankSelection() + self.stc.Clear() + self._SetPos(start) + self.stc.EndUndoAction() + + def ChangeSelection(self): + """Yank selection, delete it, and enter insert mode""" + # HACK: need to adjust selection behavior for change command + # to better match vi behavior by not including trailing + # whitespace in the selection from the motion. + stext = self.STC.GetSelectedText() + clen = len(stext) + slen = len(stext.rstrip()) + if slen < clen and slen > 0: + start, end = self._GetSelectionRange() + new_end = end - (clen - slen) + self.STC.SetSelectionStart(start) + self.STC.SetSelectionEnd(new_end) + self.DeleteSelection() + self.InsertMode() + + def Put(self, before=False, repeat=1): + """Paste text + + If there's selection, the pasted text replaces it + + If text to be pasted ends with EOL it's assumed to be a line, and is + pasted on a new line below the current line, or if the before keyword + is set to True, then it's pasted on a new line above the current line + + """ + text = ebmlib.Clipboard.Get() + if not text: + return + + bIsLine = self._IsLine(text) + if bIsLine: + self.GotoLineStart() + if not before: + self.MoveDown() + + self.BeginUndoAction() + if self.HasSelection(): + # paste over selection, if any + self.stc.Clear() + elif not bIsLine: + self.stc.CharRight() + + for i in range(repeat): + self.InsertText(text) + self.EndUndoAction() + + def InvertCase(self, repeat): + """Invert the case of the following characters""" + if not self.HasSelection(): + for i in range(repeat): + self.StartSelection() + self.MoveForward() + self.EndSelection() + self.stc.InvertCase() + self.Deselect() + + def JoinLines(self, repeat): + """Join lines into a single line. + @param repeat: number of lines below the current line to join with + + """ + self.SelectLines(repeat) + self.stc.LinesJoinSelected() + + def _DeleteChars(self, repeat, back=False): + """Delete characters under caret. + @keyword back: If set to true, delete character before the caret + + """ + if back: + move = self.MoveBack + else: + move = self.MoveForward + + self.BeginUndoAction() + self.StartSelection() + move(repeat) + self.EndSelection() + self.DeleteSelection() + self.EndUndoAction() + + def DeleteForward(self, repeat): + """Delete characters after the caret""" + self._DeleteChars(repeat) + + def DeleteBackward(self, repeat): + """Delete characters before the caret""" + self._DeleteChars(repeat, back=True) + + def ReplaceChar(self, char, repeat): + """Replace the next character under cursor with the given char""" + self.BeginUndoAction() + self.DeleteForward(repeat) + for i in range(repeat): + self.InsertText(char) + self.EndUndoAction() + + def FindNextChar(self, char, repeat): + """Find next occurance of char on the current line""" + self.stc.FindChar(char, repeat) + + def FindPrevChar(self, char, repeat): + """Find the previos occurance of char on the current line""" + self.stc.FindChar(char, repeat, reverse=True) + + def FindTillNextChar(self, char, repeat): + """Similar to FindNextChar, but stop one character short""" + self.stc.FindChar(char, repeat, extra_offset=-1) + + def FindTillPrevChar(self, char, repeat): + """Similar to FindPrevChar, but stop one character short""" + self.stc.FindChar(char, repeat, reverse=True, extra_offset=1) + + def SetFindCharCmd(self, *args): + """Remember last find-char command (raw unparsed command, e.g. 'f') + for repeating later on. + + """ + self.LastFindChar = args + + def GetFindCharCmd(self): + """@see SetFindCharCmd""" + return self.LastFindChar + + def Mark(self, mark): + """Create a bookmark on current line and give it a char label + @param mark: the character label of the bookmark. + + """ + #TODO: handle global bookmarks + bm_handle, column = self.stc.AddBookmark(), self._GetCol() + if mark in string.ascii_lowercase: + # Local bookmarks + self._Bookmarks[mark] = (bm_handle, column) + elif mark in string.ascii_uppercase: + # Global bookmarks + pass + + def GotoMark(self, mark): + """Goto the position of the bookmark associated with the given + character label. + @param mark: the character label of the book mark + @todo: hook into Bookmark Manager ed_bookmark? + + """ + if not mark in self._Bookmarks: + return + + bm_handle, col = self._Bookmarks[mark] + #TODO: handle global bookmarks + line = self.stc.MarkerLineFromHandle(bm_handle) + if line != -1: + pos = self.stc.FindColumn(line, col) + self.stc.GotoPos(pos) + else: #line == -1 means the bookmark was deleted by the user + del self._Bookmarks[mark] + + def _GetSelectionRange(self): + """Get the range of selection such that the start is the visual start + of the selection, not the logical start. + + """ + start, end = minmax(self.stc.GetSelectionStart(), + self.stc.GetSelectionEnd()) + return start, end + + def _GotoSelectionStart(self): + """Goto the visual start of the current selection and deselect""" + start, end = self._GetSelectionRange() + self._SetPos(start) + self.StartSelection() + self.EndSelection() + + def _GotoSelectionEnd(self): + """Goto the visual end of the current selection and deselect""" + start, end = self._GetSelectionRange() + self._SetPos(end) + self.StartSelection() + self.EndSelection() + + def _GetSelectedLines(self): + """Get the first and last line (exclusive) of selection""" + start, end = self._GetSelectionRange() + start_line, end_line = (self.stc.LineFromPosition(start), + self.stc.LineFromPosition(end - 1) + 1) + return start_line, end_line + + def SelectFullLines(self): + """Extends selection so it covers entire lines""" + start, end = self._GetSelectedLines() + self.GotoLine(start) + self.StartSelection() + self.GotoLine(end) + self.EndSelection() + + def IndentSelection(self, forward=True): + """Indent the lines of the current selection forward (or backward)""" + if not self.GetSelectedText(): + return + + self.PushScroll() + self.PushCaret() + self.BeginUndoAction() + if forward: + indent = self.stc.Tab + else: + indent = self.stc.BackTab + + for line in range(*self._GetSelectedLines()): + self.stc.GotoLine(line) + indent() + self.EndUndoAction() + self.PopCaret() + self.PopScroll() + + def DedentSelection(self): + """Indent lines of current selection backward""" + self.IndentSelection(forward=False) + + def ShowCommandBar(self): + """Open the command bar for the user to enter commands""" + self.stc.ShowCommandBar() + + def ShowFindBar(self): + """Open the find bar""" + self.stc.ShowFindBar() + +# ---------------------------------------------------------------------------- # + +def minmax(a,b): + return min(a,b), max(a,b) +# Internal functions, other modules should not bother with any of this + +REPEAT_RE = re.compile("([1-9][0-9]*)*(.*)") + +def SplitRepeat(cmd): + """Split the command strings into a pair (repeat, rest) + + >>>SplitRepeat( '3ab' ) + (3, 'ab') + >>>SplitRepeat( '13ab' ) + (13, 'ab') + >>>SplitRepeat( 'abc' ) + (None, 'abc') + >>>SplitRepeat( 'ab2' ) + (None, 'ab2') + >>>SplitRepeat( '0' ) + (None, '0') + >>>SplitRepeat( '0ab' ) + (None, '0ab') + >>>SplitRepeat('8') + (8, '') + + """ + repeat, rest = re.match( REPEAT_RE, cmd ).groups() + if repeat: + repeat = int(repeat) + return (repeat, rest) + +def GetHandler(cmd, h_list=None): + """Finds the function that handles command cmd + @param cmd: the command string + @keyword h_list: alternative list of handler functions + + """ + if h_list is None: + h_list = HANDLERS + + repeat, cmd = SplitRepeat(cmd) + if not cmd: + return None + + for handler in h_list: + if cmd[0] in handler.start_chars: + return handler + +def DoHandle(handler, cmd, editor): + """Call handler for command + It's necessary to use this function instead of calling the handler + directly. + + """ + repeat, cmd = SplitRepeat(cmd) + if handler.generic_repeat: # generic_repeat means that if no repeat + repeat = repeat or 1 # parameter is supplied, use 1 + return handler(editor, repeat, cmd) + +def GetMotion(editor, cmd): + """Move cursor of editor to a new location according to motion + Returns a method that handles this motion, or None + + """ + if not cmd: + return None + + handler = GetHandler(cmd, MOTION_HANDLERS) + if handler is None: + return None + + def motion_function(): + return DoHandle(handler, cmd, editor) + return motion_function + +# ---------------------------------------------------------------------------- # +# Vim commands + +def vim_parser(start_chars, generic_repeat=True, is_motion=False): + """Decorator for function that handle vim commands + + Command Handling functions must follow the signature: + + function( editor, repeat, cmd ) + + These functions should never be called directly, but instead + be called through the GetHandler and DoHandle functions. + + The handler functions should always decorate themselves with this + decorator. + + The purpose of this decorator is to indicate: + * What is the first char of commands that the handler can handle + - So that GetHandler can find the correct handler for a vim command + * Whether it's a motion + - Some commands operate on motions + * How to handle the repeat parameter + - For most command, no repeat is the same as 1 repeat, but for + some commands, this is not the case + + """ + def decorator(handler): + handler.is_parser = True + handler.start_chars = start_chars + handler.generic_repeat = generic_repeat + handler.is_motion = is_motion + return handler + return decorator + +# TODO replace with a special objects +# TODO:CJP ok if these become classes but, if they remain as flags then they +# need to be uppercase. +NeedMore = True +InvalidOp = False + +@vim_parser( u'iIaAoO' ) +def InsertMode(editor, repeat, cmd): + """Handler for basic commands that put vim in INSERT mode""" + cmd_map = { + u'i': (lambda:None), + u'I': editor.GotoIndentStart, + u'A': editor.GotoLineEnd, + u'a': editor.MoveForward, + u'o': editor.OpenLine, + u'O': editor.OpenLineUp + } + func = cmd_map[cmd] + func() + editor.SetLastChangeCommand(func) # Let the editor remember to repeat + editor.SetInsertRepeat(repeat) # insertion if and when needed + editor.InsertMode() + +#TODO:CJP Documentation for below methods please +@vim_parser( u'v' ) +def VisualMode(editor, repeat, cmd): + """Enter visual mode + @see: vim_parser + + """ + editor.VisualMode() + +@vim_parser('.') +def Dot(editor, repeat, cmd): + """Repeat last insert command + @see: vim_parser + + """ + editor.RepeatChangeCommand(repeat) + if editor.IsInsertMode(): + editor.NormalMode() # in case it was a 'c' command + +@vim_parser(u'hjkl\r \x08\u013c\u013a', is_motion=True) +def Arrows(editor, repeat, cmd): + """Basic arrow movement in vim. + @see: vim_parser + + """ + cmd_map = { + u'h': editor.MoveLeft, + u'j': editor.MoveDown, + u'k': editor.MoveUp, + u'l': editor.MoveRight, + u'\r': editor.MoveDown, + u' ' : editor.MoveRight, + u'\x08' : editor.MoveLeft + } + if cmd in cmd_map: + cmd_map[cmd](repeat) + else: + # Handle motion for actual arrow keys + if cmd == u'\u013c' and not editor.IsAtLineEnd(): + # Right arrow + editor.MoveRight() + elif cmd == u'\u013a' and not editor.IsAtLineStart(): + # Left Arrow + editor.MoveLeft() + +@vim_parser('wbeWBE[]', is_motion=True) +def Words(editor,repeat, cmd): + """Word motions. + @note: [] is based on what scintilla calls "word parts", these motions + are not in vim + @see: vim_parser + + """ + cmd_map = { + u'w': editor.NextWord, + u'e': editor.WordEnd, + u'b': editor.BackWord, + u'W': editor.NextWordBig, + u'E': editor.WordEndBig, + u'B': editor.BackWordBig, + u'[': editor.BackWordPart, + u']': editor.WordPartEnd, + } + cmd_map.get(cmd, lambda x: None)(repeat) + +@vim_parser(u'$^0', is_motion=True) +def Line(editor, repeat, cmd): + """Motions to beginning/end of a line. + @see: vim_parser + + """ + cmd_map = { u'0': editor.GotoLineStart, + u'^': editor.GotoIndentStart, + u'$': editor.GotoLineEnd, + } + cmd_map.get(cmd, lambda:None)() + +@vim_parser(u'{}', is_motion=True) +def Para(editor, repeat, cmd): + """Paragraph motions. + @see: vim_parser + + """ + cmd_map = { u'{': editor.ParaUp, + u'}': editor.ParaDown, + } + cmd_map.get(cmd, lambda x: None)(repeat) + +@vim_parser(u'uU') +def Undo(editor, repeat, cmd): + """Undo/Redo commands. + @note: unlike vim, U is used for redo. + @see: vim_parser + + """ + if cmd == u'u': + editor.Undo(repeat) + elif cmd == u'U': + editor.Redo(repeat) + +# TODO:CJP Scintilla lexing bug, check if fixed in 2.9 +@vim_parser(u'*#', is_motion=True) +def FindIdent(editor, repeat, cmd): + """Find the next/previous occurance of identifier under caret + @note: There's a sublte difference from vim: if some text is already + selected, it's used as the search term instead of the identifier + under the caret + @see: vim_parser + + """ + cmd_map = { u'#': editor.PrevIdent, + u'*': editor.NextIdent, + } + cmd_map.get(cmd, lambda x: None)(repeat) + +@vim_parser(u'~') +def Tilde(editor, repeat, cmd): + """Invert case of character(s) under caret. Also operates on selection. + @see: vim_parser + + """ + editor.InvertCase(repeat) + editor.NormalMode() # In case this command was applied in visual mode + +@vim_parser(u'J') +def Join(editor, repeat, cmd): + """Join lines command. + @see: vim_parser + + """ + editor.PushCaret() + editor.JoinLines(repeat) + editor.PopCaret() + +@vim_parser(u'xXsSCDY') +def Delete(editor, repeat, cmd): + """Simple delete/change commands that are implemented in terms of more + advanced c/d commands. + @see: vim_parser + + """ + cmd_map = { + u'x': u'dl', u'X': u'dh', + u's': u'cl', u'S': u'cc', + u'C': u'c$', u'D': u'd$', u'Y': u'y$', + } + if cmd in cmd_map: + Change(editor, repeat, cmd_map[cmd]) + +@vim_parser(u'cdy<>') +def Change(editor, repeat, cmd): + """Implementations for c/d/y commands. Also for <> (indentation) commands. + @todo: This method is quite larger than other methods in this module, + needs to be simplified. + @see: vim_parser + + """ + editor.PushColumn() + editor.PushCaret() + def ret(return_value, restore=True): + """Needed because we have to pop what we pushed before we return""" + editor.PopCaret(restore) + editor.PopColumn(restore) + return return_value + pre_selected = False + line_motion = False + if editor.HasSelection(): + pre_selected = True + if len(cmd) > 1: + motion = cmd[1:] + else: + motion = '' + cmd = cmd[0] + else: + if len(cmd) == 1: + return ret(NeedMore, False) + + cmd, motion = cmd[0], cmd[1:] + if motion.isdigit(): + return ret(NeedMore) + + motion_repeat, motion_cmd = SplitRepeat(motion) + if motion_repeat: + repeat = repeat * motion_repeat + + if motion_cmd == cmd: + # Operate on whole line + line_motion = True + editor.PushColumn() + editor.SelectLines(repeat) + else: + motion_function = GetMotion(editor, motion_cmd) + if motion_function is None: + # Invalid motion; cancel operation + return ret(InvalidOp) + + editor.PushCaret() + editor.PushColumn() + for i in range(repeat): + if motion_function() == NeedMore: + # This motion is incomplete .. (catch on first iteration) + editor.Deselect() + return ret(NeedMore) + editor.StartSelection() + editor.PopCaret() + editor.EndSelection() + + if motion_cmd[0] in LINE_MOTION_PREFIXES: + line_motion = True + editor.SelectFullLines() + + cmd_map = { + u'y': editor.YankSelection, + u'd': editor.DeleteSelection, + u'c': editor.ChangeSelection, + u'<': editor.DedentSelection, + u'>': editor.IndentSelection, + } + + cmd_map[cmd]() + + restore_x = cmd in (u'y', u'<', u'>') or cmd == u'd' and line_motion + editor.PopColumn(restore_x) + + # XXX: Some special case handling + # Not the most elegant way though .. + if cmd == u'c': + pass + else: + # Repeating delete/yank/indent commands doesn't insert any text + editor.SetLastInsertedText(u'') + # Applying them in visual mode ends visual mode + editor.NormalMode() + + if not pre_selected: + # Remember this command as last change + # However, if we're operating on a selection, then remembering + # doesn't make much sense + editor.SetLastChangeCommand(lambda : Change(editor, repeat, cmd+motion)) + +@vim_parser(u'pP') +def Put(editor, repeat, cmd): + """Paste commands. + @see: vim_parser + + """ + before = cmd == u'P' + editor.Put(before, repeat) + editor.NormalMode() # for pasting in visual mode + +@vim_parser(u'"') +def Reg(editor, repeat, cmd): + """Switch register (clipboard) command + @note: This command is stand-alone, not prefix to other commands. + @see: vim_parser + + """ + if len(cmd) == 1: + return NeedMore + + cmd, char = cmd + try: + editor.SetRegister(char) + except ebmlib.ClipboardException: + # Attempted to switch to invalid register + wx.Bell() + +@vim_parser(u'r') +def ReplaceChar(editor, repeat, cmd): + """Replace character under caret with another one. + @note: Does not enter into Insert mode. + @see: vim_parser + + """ + if len(cmd) == 1: + return NeedMore + + r, char = cmd + f = lambda: editor.ReplaceChar(char, repeat) + f() + editor.SetLastChangeCommand(f) + editor.SetLastInsertedText(u'') + +@vim_parser(u'R') +def ReplaceMode(editor, repeat, cmd): + """Enter into Replace Mode. + @see: vim_parser + + """ + # TODO handle repetition + editor.ReplaceMode() + +@vim_parser(u'fFtT', is_motion=True) +def FindChar(editor, repeat, cmd): + """Find character on current line and move the caret to it (if found). + @see: vim_parser + + """ + if len(cmd) == 1: + return NeedMore + + cmd, char = cmd + cmd_map = { + u'f' : editor.FindNextChar, + u'F' : editor.FindPrevChar, + u't' : editor.FindTillNextChar, + u'T' : editor.FindTillPrevChar, + } + if cmd in cmd_map: + cmd_map[cmd](char, repeat) + editor.SetFindCharCmd(cmd, char) + +@vim_parser(u',;', is_motion=True) +def RepeatFindChar(editor, repeat, cmd): + """Repeat the last FindChar motion. + @see: vim_parser + + """ + prev_cmd = editor.GetFindCharCmd() + if not prev_cmd: + return + + pcmd, char = prev_cmd + if cmd == u',': + pcmd = pcmd.swapcase() + + FindChar(editor, repeat, pcmd+char) + editor.SetFindCharCmd(*prev_cmd) + +@vim_parser(u'm') +def Mark(editor, repeat, cmd): + """Create a bookmark and associate it with a character label. + @see: vim_parser + + """ + if len(cmd) == 1: + return NeedMore + + cmd, mark = cmd + editor.Mark(mark) + +@vim_parser(u"`'", is_motion=True) +def Jump(editor, repeat, cmd): + """Jump to a bookmark specified by a character label. + @see: vim_parser + + """ + if len(cmd) == 1: + return NeedMore + + cmd, mark = cmd + editor.GotoMark(mark) + if cmd == u"'": + editor.GotoIndentStart() + +@vim_parser(u'HLMGgz', is_motion=True, generic_repeat=False) +def NavExtra(editor, repeat, cmd): + """Commands for navigating visible lines or scrolling. + @see: vim_parser + + """ + if cmd == u'H': + editor.GotoScreenTop() + if repeat: + editor.MoveDown(repeat) + elif cmd == u'M': + editor.GotoScreenMiddle() + elif cmd == u'L': + editor.GotoScreenLast() + if repeat: + editor.MoveUp(repeat) + elif cmd == u'G': + if repeat: + editor.GotoLine(repeat) + else: + editor.GotoLastLine() + else: # g or z command + if len(cmd) < 2: + return NeedMore + + if cmd == u'gg': + editor.GotoLine(0) + elif cmd == u'zz': + editor.ScrollMiddle() + elif cmd == u'zt': + editor.ScrollTop() + elif cmd == u'zb': + editor.ScrollBottom() + +@vim_parser(u'/?', is_motion=True) +def RegexSearch(editor, repeat, cmd): + """Incremental search commands. + @note: Uses the find bar in editra. + @see: vim_parser + + """ + # XXX: findbar is not regex! + # TODO:CJP it is if you set the regex search flag or the user's previous + # search was done using regular expressions. + editor.ShowFindBar() + +@vim_parser(u'|', is_motion=True) +def Column(editor, repeat, cmd): + """Goto specified column, with 1 being the default. + @see: vim_parser + + """ + editor.GotoColumn(repeat) + +@vim_parser(u':') +def Ex(editor, repeat, cmd): + """Command for opening the command bar. + @see: vim_parser + + """ + editor.ShowCommandBar() + +# Cannonical list of handlers +HANDLERS = ( + InsertMode, ReplaceMode, VisualMode, Dot, Undo, + Arrows, Words, Line, Para, Column, FindChar, RepeatFindChar, + FindIdent, Change, Delete, Tilde, ReplaceChar, Put, Join, + Mark, Jump, Ex, Reg, NavExtra, RegexSearch, + ) +MOTION_HANDLERS = [h for h in HANDLERS if h.is_motion] +# HACK: The following is a sign of improper design! but doing it properly +# would probably require yet another huge rewrite of this module. +# So watch out if things get out of control with many such hacks. +# These are motions that, if operated on, the operation should happen +# on whole lines. +LINE_MOTION_PREFIXES = [u'\'', u'G', u'{', u'}', u'H', u'L', u'M'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_xml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_xml.py new file mode 100644 index 0000000..266b246 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/ed_xml.py @@ -0,0 +1,108 @@ +############################################################################### +# Name: ed_thread.py # +# Purpose: Provides a base class for managing XML files and data. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +XML base class + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: ed_xml.py 72624 2012-10-06 19:38:14Z CJP $" +__revision__ = "$Revision: 72624 $" + +#-----------------------------------------------------------------------------# +# Imports +import types +from xml.dom import minidom +import extern.dexml as dexml +from extern.dexml.fields import * + +import util + +#-----------------------------------------------------------------------------# + +class EdXml(dexml.Model): + """XML base class""" + def __init__(self, **kwds): + super(EdXml, self).__init__(**kwds) + + Xml = property(lambda self: self.GetXml(), + lambda self, xstr: self.parse(xstr)) + PrettyXml = property(lambda self: self.GetPrettyXml(), + lambda self, xstr: self.parse(xstr)) + + def GetPrettyXml(self): + """Get a nicely formatted version of the rendered xml string + @return: string + + """ + txt = "" + try: + txt = self.render() + txt = minidom.parseString(txt).toprettyxml() + txt = txt.replace('\t', ' ') # DeTabify + except UnicodeEncodeError, err: + util.Log("[EdXml][err] GetPrettyXml %s" % err) + return txt + + def GetXml(self): + """Get the XML string for this object + @return: string + + """ + xstr = "" + try: + xstr = self.render() + except UnicodeEncodeError, err: + util.Log("[EdXml][err] GetXml %s" % err) + return xstr + + def Write(self, path): + """Write the xml to a file + @param path: string + @return: success (bool) + + """ + suceeded = True + try: + xmlstr = self.PrettyXml + if isinstance(xmlstr, types.UnicodeType): + xmlstr = xmlstr.encode('utf-8') + handle = open(path, 'wb') + handle.write(xmlstr) + handle.close() + except (IOError, OSError, UnicodeEncodeError): + suceeded = False + return suceeded + + @classmethod + def Load(cls, path): + """Load this object from a file + @param path: path to xml file + @return: instance + + """ + instance = None + try: + handle = open(path, 'rb') + xmlstr = handle.read() + handle.close() + instance = cls.parse(xmlstr) + except (IOError, OSError): + instance = None + return instance + + @classmethod + def LoadString(cls, xmlstr): + """Load an object from an XML string + @param cls: Class object + @param xmlstr: string + + """ + instance = cls.parse(xmlstr) + return instance diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/edimage.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/edimage.py new file mode 100644 index 0000000..e86fd74 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/edimage.py @@ -0,0 +1,923 @@ +############################################################################### +# Name: ed_image.py # +# Purpose: Encoded art resources for Editra # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +"""This file is an image data file that provides some of the base icons +@note: image data generated with img2py + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: edimage.py 54209 2008-06-14 04:57:51Z CJP $" +__revision__ = "$Revision: 54209 $" + +#-----------------------------------------------------------------------------# +from extern.embeddedimage import PyEmbeddedImage + +catalog = {} +index = [] + +splashwarn = PyEmbeddedImage( + "iVBORw0KGgoAAAANSUhEUgAAASwAAADICAYAAABS39xVAAAABHNCSVQICAgIfAhkiAAAIABJ" + "REFUeJzsvWmMbdl1HvatPZzpTjW/sedm020O4iDJkqAxkOAEdhQDAZIfTmwEzoAkCPwjiIIg" + "P5IYcaAYsGRBkKzYlixLESHHlKGBhCKZEtUUx261mqTIZotkT+zhdfcbq+pO55w95Mdea99T" + "jyKLMoWnfkptoPBe3Tr33nP22nsN3/rW2gTgN3E2zsbZOBt3wVB/3jdwNs7G2Tgb3+g4U1hn" + "42ycjbtmnCmss3E2zsZdM84U1tk4G2fjrhlnCutsnI2zcdeMM4V1Ns7G2bhrxpnCOhtn42zc" + "NcOcdsHrL7/8HX3bonMOighGawBAjBE+BJRlCe8cYoww1sL1PWxZgpRCDAGkFIL36NsWRARb" + "logxAjHCFgWs1vAhoOt7+L6HMgZaa4QQ8vvlehCBiNLvQP6/sRYEIISAEAJ836Pve/gYURgD" + "W5ZQSsF7D8QIpXW+P/msGAKU1gjewzsHbS36tkXVNOkaImi+l77rELyHrSoE56C0xnw+R2lt" + "vh8ACN6nefIeEUBZlnB9jxACyrqG6zoQEUgpaGPS9w+emwAs53NYa6G0Bojg+x7O+ywHeRal" + "VHp+59LrxkAbgxgjgvcAANd1af75uddtC02ECMBoDSKC0hrKGATv070R4Uz+Z/K/U/K/9OCD" + "n/ymFJZMZsE3icG/IkAiytcHniAKIV2jNUxRADGiXa+h+h6aBdu1LaiqQAC0MVnIXd+DiGCK" + "AiEEKKUAohMLTL5TKQXECB8jAk8cAFhrUcrkhgDP96OMScL1Pi0YpWDLEt1qBe8cTFFAaY0Y" + "Aoqqgut7FDzJXdvm62OMaYPxgil4cfS8OOQefQhpsfPCNEWByPcynLu8KWNMr8eIONignjcG" + "EUENXo8hnNzEg2fzfQ9TFOk9SiEagxgCurZNcx0CtNbpe/ke5DMRIyJviDP5n8n/Tsn/tHHq" + "VYoIkT9MtLXcpFIqaeGBtjcsQNHO8lAggrUWpFSazBBgtEbXdTBsVYuyRO892tUK3nsQWwvw" + "58V0E/nz8wQPhIXBBCpj4HiRiSXD4BmUMSiKAs77bIV7tnrGWnTrdVoAvOjy9/LGIaWwXq2g" + "WanHEKB4wYYYYZRKz0wE79zGavHnGJ6P9IhpU4oXAaSNZozJi1DmmJRKr/EGlcUushgu4Lw5" + "lEpWWr4LQMHfFQZKIM8T/34m/zP530n5nzZOVVgRAMliYG0+1KiOrWG+fjhRSsGLxSBKmjWE" + "7CKLJfMsSK01rNagukbbtvDObb6PJx4sDJkwDP4eeZKDXCv3xPcytCSKF1nXdVBaw3sP731y" + "h51Du1ohxggtC4oIZG2yXn2fBWTZ/bdFkeaCF5YPIbnQ7OoDyXsAu/qy4OV+vPeA92kz8IYY" + "hhfDIfMtMrn9dXCIkDcKbxbF9yJWPnssg41/YrEqdSb/M/nfUfmfNk73w4YuuFIZpb/dPfSD" + "hxm6q67vodlKeH64sq7z30Qgfd/DOYeiKGC0RuBJFVyB2EJIbCwCKzgG7kX7i+uvNQhAWdfo" + "uw6u79MitTZPTOSYfxhKAMkyy/d553Lc3vV9jsvFUhtr00Jnq2e0TjgA/+66DqYooNm6yPfI" + "M2W8RhaOPBuHE3KdWDeZ2zwvty2W4QIUdx4cUkhoFBnryYsvRgQOq7Ks+Ufk/Wchf+ccKSJU" + "o1HGmrTW8Uz+//+Q/zey/08b31DgGAc3Jq6xaHYRvriVsqjCQGvKZBFRxhDESgnAKZPqlEoL" + "hjYAIMTFF5dcLCvwVZgBSSzMVsvwZ8iDijUT17esa6yXS2gGGru2RVlVqNk9dewyO3kGsYr8" + "fX3bJiyAn4vKMoctngHW4Fx27aNz2SuQhS33FWOEEs8BAPF3npDFIAQCkDZLjAkj0Tp5Gre5" + "+IrxFSAtDM3zqHmxKH6PGn62bB6t/8zkz14NaaXgQkAgiiEEUkTxTP5/8eX/jez/08aptAbR" + "lPlf1vriPor7HWNMVpMtlmQOFFtEsZbipgLI4OUQTA0hwLF7r9g6GGNgJOMhC5+F2vd9miye" + "SGNMjpV936PjidHW5s87YcW8R1nX4gFAEcF1HY6Pj9O9DYQh2EGevEGGRj5PEWW8Yd11STgy" + "XwPBk1JQbEU9z5dnCy7POdwg8vm3/wwXPHi+xbJqDj8UUZYBYkx/s/bkffNzaH4mURJ/JvKP" + "kaCUssYoY4wiIm2KQldVpSndhAop8jiT/19E+f8p9v9p41QPSyZOXFIv2ng4aVpD80LiGcgT" + "13ddnhzvHPrVCtqY5AoOXMe+6/IikActrMViuYQuSxBRchljhNEaRin0Yin5PgO75pq/W2md" + "3FC1AV01g6BDADHGiLosobXGernMQmydQ7tcYjydQhuDVdsiOJczGpK5iQMhiIsuFrpdr+EG" + "1iYDxbwxlQCaIrQQkgchi0VAXAl1brPItiwRvM8/2RsBEIlgtUbnPRx/TsQmk9SLlRuEFrcD" + "2t+0/PuerLVktKZIpGKMSmlNJlnuCKVC33UhOBeFInAm/79A8v9T7v/TBuGUfljXrlz5jqE7" + "HGPMKL+ilOlYrdcAEpdDrBtiTDfKEyGTslouM1Cpjcn8jKEbK24jEaEwBo5jbwKy0P1QkByv" + "A4lrIsCiYnc+hyRaJ9ecEjDrnMv8HKIEkMr14O/y3qcMBr+vZ3BWJtoWBVaLRRa4xOsxRjRV" + "heVqla19UVUIIaBvWxRVlZ9B8JAslIFVlfsGEu4h1loyU33XJbC6LDMuEbzP4YZ3DmVZAkQ4" + "unUrP1fZNJgfH0MLVnGbtc5WmBXFv438DSsqaK0QoyKtleudGo0bRaTQrtfRud6H3vneex+9" + "j4gxnsn/L4b8/232/+WHHvrmeFgS0xulsGrbTHYrmN/hnUNVFCmF3HXoOU2pjAEBWC+X2dqR" + "SmleAf36vkdRFBvLMrA+kunwMcJy9kisBAGZlzO0ljm+RspexBBgWLtHnkRZpIoIhbUIMWUw" + "HIN+VVEgKIW26+CdS9kf57Bmzo6iTTbDOYf1cpm5O+1yiXa5RGEtTFGg9x62KEBAIhbWdZov" + "JiMaYzLQKFZvaFVzpmbgLisiBAwyRYPnF4svCxaMU/Tew7M1Favmug4xBOiiyJ8ji1X+lQ3y" + "p5G/63vSCTgnrRT1fa80oLTRqndezbZG6ur1uTo6XuPcbhN8RARRIIAiUcyhy5n870r5f7P7" + "/7RxKoYlLvq675P1UgpFVUFpnYGzGBNpLzD2AADBufz3zPjlLIG4/DT4HsnKAMiclTCwpAAQ" + "kDS1LDJxX0Eb/orgDDlL0/cJD1GbVK/gEs57WH4+WeirtkVg6ygWRX6IEq/Eap1dYiHmec5C" + "FUyKg9wrz8loNAIBKMoSjtP1w2cfPn+IMXkVvGAkyyX3cHsINHThhylxsdqRsQXZaGKFc8pe" + "sm/xJKAr1v0blT+IiJKiUgSoSKS1tRpEOkbore2pfvIzz6u/9d/+FP03P/Jz9NobN1XfdeSc" + "VyAQKUVQis7kf3fK/89q/3+9cTpxlN1iyYQAyDciv6/bFgrJ1RR324cAw66lZ+xhmMaU2P0E" + "Ec0YaNqQ7EAEzSFB5PeDF5cxBkZrrNilHApG7k3AwxhCBmZloTnnkmvLLrNnK0tK5RRrXZaY" + "z+cn7teFkN3ywBY0hIBuvU5EQF4M8i8AkLWoyxI+RhgitEPBySKKEQEbjIJY+BJ+aK2hGS8g" + "DkuEfAfgxAaQBSPzWlQVIs97u1xu8IdBOJRT54xFyGvfiPy7riOlNRljSGlNSilFRBRJKWuU" + "qppCrZZL9X/8+Afp//6VT2K+6tF3HT73+S/j2979AIVoqCosKVKktY6Szj+T/90h/z/L/X/a" + "OPUKTQSHDbYUvIdngExbm1K2SsEWRbJ0srCAzGPx4qLyyKCj39REgYUl1kaEWWidFgk/dAbq" + "RBgcMwsmIYIL3oMSjpKtEZAYvzKxYiX6rkM9GqGpa6zaNrvKbd+japq8SQBsSjxYmOvlElXT" + "pDKOrsucHKtUivM5W9P2Pawx6HyqQRuCwcPnUcZAMY7iQ8iYjZLFymGJ8JHEIgZeVABO/Cs1" + "ZgKEEpBCK8Z+xFuRlLaPXBYSY84wOf6OLP++T3hSUVBIYVcC1q1VREpFgup6r2aVVtoo+sjH" + "vkj/60/8Dr34yjF2t2bY2rF49bU5Pvbki3TxfKO2ZzvBaK1Kq6NSCfWIMUZSCobDQgnxSBQQ" + "h43CJA+DdQcgk06lvCfLX+u/UPI/sadu+xH5iwcpoXAQBR5TPaBSA37VYO8T0R3f/6eNUxWW" + "ZyVBwAlSnixcxfiCFG4CSLVDHM/KTQytjiw6wibkzBkHtqoyYVljDwUcEukMRLDyGgvUSAaH" + "syY5pKANQ1fuU7g3Simsl0u4okBZluidQ79e5xqogGTxxIYJ6CvWwUkKl59FvkMbk65jjyDE" + "lOFywsURN1xwG75H4fgQC1EWoJcMlTyLUidif8+LMCsn3rCRX9dao2katBz2CCAqi1RCniGe" + "EXixU9yUf+j0LMS1aGSMUaYoVCRSFKNSitRk2qgvfvlV+vn3P0X/6oN/jNGowWjrPiyCQfA9" + "RtMGv/NEix/8zmtU1xM1BoIpS+gYEZSKw/txfY/g3AmPyTuHnhUDEcHxfAugK/IRWdPguTKz" + "+m6WP++rYXbRhQDZ/oJ/icKOrDxrriIIMULxdYGNlLwvyz4EeKXu6P4/bZwOuq9WsGWZ2Mes" + "PW+va7qdmzGMq4k26VzJyAjXw4j2Zwwi8ubJWp6FIFoa/F7wNa7v4YCT1f2cmcgu70DbDxnD" + "YAWnrd0UgzqHNcftZV2f8D5OVKknySKGgKKu0a1WeQMMuSWK3WHvPaqiwLrrYLVGy5tEFkDG" + "DWLM9XIyL3GwkEIIIO+z6zw/PKQbL72kFCsf1/e5rktquLQxOXskVq5r28wBuv07ZKOkFcoZ" + "I2vz8wfvCUQwhSVrCzJVRbYoSFe1qse1msxGqnU9/eTPPU7v/8Cn8dwVYDy5gGUoURiLUVNh" + "3QYU9QJufRPPvniLpuNbynqvVzdvAl0XfNuGvutiVsTOZXBacBcAUEoDhBPepjYmP1uMAcFt" + "MnHQGrOLF8NkZycKz+uulX/cMN+F36SZRwYgkztzaEqbzhau72FV4odZVliS9RODJUrUc/eF" + "O7X/TxunKixpodF5n6q2yxKhKCQjBMOov+JsjLSSiDGiappcHJqti/cnmLBDljBviKx8An9n" + "ZEGK+ypcmqHGlolznCkBkL0tN9D2Ur8k17SrVW7f4Z1DFAsAoBSOTNxkTnoOpbRSMGWJlrMm" + "EqtrY3JmKYTUfiPEmMBc7+G0RlkUaNmtlufIwoonU9xSUS/WR+lNdf1zjz1mn/jRH20OJlPY" + "w0NE50CKQPGka4/bDVfM+mjz9zi4bvB/AoGMhi4rmMkYxWyGcmsb1d4uyr09VPsHMAfncOnR" + "BwG1g9/41HP4qV96Ak8/vwb0DOfOTXDPxR10DvjB77oXz710hI88dYi6HGMVPT76mSUePf+K" + "uv6CV/jKC3b15S9j8fzzWL/+Ovr5Asjha+DnphMPEvl3Gj4Lv55CS6Ss2/4+Xlut8Lb/8r9Y" + "ffvf/ttt5I1/N8pflIH3PjPotdYwvLdy6AygW68TRcGYjNERpexhhgycg4+DUh5ssKU7vf9P" + "G6cqLNe2MGWZ+vD0fb4ZW5YwtCGIZfaxMfDsCscQUFZVztA453I1t1YKq9UKFffnCdikLEVZ" + "ycQBybIWnIJ1XZf7BwHIFfbDUgcpp/B9n3oPMZckfx57HjK6tk28mxASKbFt4ZRCU1WZ6ax5" + "ggVDscagqSqsaAOwxhixXi7hvcd4OkXX9ykcYEERETyHZ1KWIKAk2NIQLyJhfYt775xD6HuU" + "xkAXBUpj4n1K462XLuH83/27QNciesdb9WsN0US3a7XBiJtLSSmQ0SBTQNUVVFNDNSOoUfqx" + "swnGezN88vOv4p/+5MfxKx96BaPRCJcunMfBwXlMx4SibFA1W/jKG8Bzr3R48CLhpTdG0LbD" + "zfkahz3hvsuXsH/fPSje8x7Q4RHC8TFC2yYFAg51459ww6LD4uBXAhAJ7K9ATca49sEP4ulP" + "fxqNNtnTiHep/KuyzPCHcw4qpFpK8VykQFtwtSFlAjFmmCB3mFAK5ZB1zoa/KMs/l/3/9cbp" + "GJb3UAOuyAmwl+PqPBmyzkV5sDWQh9QDj4cokQLlvcLMHX5GXpMxZrZwtjAhoHcut+jI+JRY" + "w4G77dxXF7gKLmCMSYxfIqy7DlVRYLlYoLAWWiksVys0dZ0WtfcwDKBqa+G8zxZWsI/gfUp1" + "9z2W8znq0Qg9c15sWcIxrmatBaxNz601AnDi/nIafpC61loDPjGUhXG8VVUYXbuG+stfxuQ/" + "+GHA2OSN5LgOoIEn8icN8USy6wX2WCnV5pHWiNaCCotYlgi2RDVtQE2BWzeP8SM//Rje9+vP" + "oOsCHn14F9vbB+i9wa054ait8dq1DkVxDfvbEUftFnZHhIcvtejdFK4nfO6FJe6/h4DpAcYX" + "DYregboW6B0Q/EZZ/UkK6+sNDotWH/oQFs8+h1lRwvA0CNfrrpQ/f2cIIfGa4gBsD5si5CCR" + "hChcY1BydNLzOiKlcu8qYLPHRTH8ee3/rzVOzxJy/Bm8P+EBRb55DMIrsTwZ6CRCwR0JhxZG" + "AMoMUsrDyg0PXHAJCaVAMwN0A8BZDSfS+6/+nAEwnZUeZ0aIeTQAciMxzVkNudfDw0OMp1MU" + "WuP4+DiRApndO5lMsFyt0Epzt6JAYQw6ziD1bOGG4LEpS1it0Xv/VQs112uFTabPhZCATbHQ" + "nAHTRClDowjtv/k3cB95LFnoP2lfn4gBv8YgAhUWVFZAXYPGI9BsBpptQe3vARcvIhycx+6j" + "9+Ha6wv8yodfwI/97CdwvGwx2znAg5cnOFpqvPRGAJFD6xWsJdx/PqL1JTpXYFYeYdVV+EsP" + "1vjUZ1eYHxuMtMO3P/gaipevw16/Bvvii6Dnn0d8/XWExTwpLu+B4BE9h4e3hYZf/Ts/NAGh" + "d8kjUAoUmfIA3oB3ofwFk5TWNZI4AJBJoxnYln0hmBoD7MM9KviWXC+wSWC86Y7v/68zTudh" + "sdsoNySTSCEkgJfdQhpM2LBIsmMtrolOcEMA5Ja4cqNDoG64t5TWMDIhEtJJZsJvQFVRTJkJ" + "LZ91O7jJ/1dKYbVYJMvHGNdyuURZFOgkzOR7Wc7nKKoKk8kEt27dQlFVaFerRBFgDEOA777r" + "UJQlptMpOn5mwRuUtWjbFkvn0NQ11l2XFTGATVlGSFwWO8Aa5Hk1z7sMIgU9qtPrxpyQe966" + "vKfz1o4nryGtQWUBqhvQbAqazkBbM9DODmh3Dzh3gPKeiygv7uMDH30BP/kvHscf/tGLmG3v" + "473fchEeEzx/ZY0QIrSJMNrh0uwGQlBwbQPSBxjXEQ/fW+ILzwf85kcdHrk34MHzGsu5wfNX" + "O5y/p0I/naLY2YE6OgK6Ls1/t0Z0AeRDUlrBD+7/dmV123MhgqoayntQ3+cHj4xD3a3yv53C" + "MCzfyQmnrkvJAuJODhyuyndJ58/8nUTZk5XXhvSJO7H/TxunN/DjLxatLWPYQTFfO7gZeYC+" + "bZOLrFSykoO/hRAQBviTxPASx+eU/UCY8m1ZualBtTq/PhRAGCwGYeLGGKFjTBlFtaluFwuT" + "M2UxZcikKVvftlgvl9ja2kqlFlWVQEXmo3i+H0LqIiDtTUinTozDRen7HusBbyjfO1F2jYmt" + "kh4sBoAJe7KgJK/KiQlCBLTNqej0tzwdkJfSe4FICspqoKpAozHUbAu0uwO1twvs7iLu7WN8" + "7wWoc7t45uVj/L0f+QB+6/dfwLgCvuUdD6MZbeH5V1u07SE6V2Br3OIvnfsSKrNCXSpMm4De" + "G3iM8fzRW/Hk0/sg9HjnW0ocbCs8+3yL164Cz+yu8bYLI4zKEvV4DDWegJpDxNUK8B4Uk7Lh" + "4AHwA+M0fKjb12+ihW8Y2DFluiiEXJR7t8lfDUKrTE4VL0miECBjS1KWpLROYWtM3VANG3Np" + "5yMeUmQ8LCqV9/kd2/+njG+op7vEuGH4hbd5LcN/iQjR+696AMtV94G9IcmsiFs6ePI8eYYt" + "g0yshIjEGntYa5UV1fDeBy40iIDApDm36ZHdr9epFqzvYbXGsm0zv8dYi57vRVK/12/exO72" + "NtbMlB4+NxGha9vEiVGpoVtZ1ymdzcDlqGngiwKL+RxW2sKymy4KV8JWP1jUw/B3g9vJDz8z" + "KE0l85FuXwKbbBoBWkMVNnlV0yloewu0tws6OIe4swva28XsvvN4+ajHz/3sk/i/3vck6rLH" + "pYvn8eB953Dj5hyvvngDvbfYGS9xz/bLuGf3CJNxja3pDkb1GIUpoShg3a1xef5FfP61OV68" + "OoFrCzz1OYd7LxhsjzQ++2zA972jxXQ0xmg8hp5NQEdj0HIJcFlKUsJ+8ySe8a0hDwP01Zgd" + "xU2YHBO3DJyNvhvlL+HfMLMmYVsQ+ITXyDCxpNhjFAWYQz0OkeXz/ABW+XPZ/19nnI5hMecD" + "SM3SCIAZTNQJ7TgA/iIvDMMupQ+banm5jlQithE2zevz56pEVhyCfGL5JAiQWHuIa2USnnyG" + "Sk3TMptXXGeJ6/WmH3XhPbS1KMImlRxCgCnLtKhZqAUR3rh2Dfu7u5ktvW5bFMbAFEUqP+j7" + "BM4qlcFXseadc4gAqqbZtPZQCtH7zNAXIUpzs+ECk8zPMMRNskj/Zk/LFgnGGSYEFYEUh451" + "BWpGKQTc3QXt7QF7+6D9PYwvHcCPRvinv/Z5/Nz7H8czz97E3sFFPHL/Nuoi4PFnjjCrHUrj" + "8dZzb+De/UMcbJeYjC5hUtcYj8fYrmvUiqAi0HqPo+0O53Zv4Nc+1eHmfILLBwWid/jj51d4" + "7WqPD/3hHH/nhyZYuwblZII4GgFVBayWadMI/i7PG4EYOMMG2qzBnAjlzBvrtDTNie3dA3e1" + "/GUND0/oCaxQY4z5NB/Xbw7KkH0m/CcJ0YL3iIKJiZLj1/+89v/XGqeHhGLZBpqZiHIRqmUe" + "COFkXZA2BhobjTvsOilaNw5cdXlQABvy2W2bMvhN3x9TFCnDI9k/VnDCgs9cE+8zzkDYxMku" + "BKi+R+89mqbJfJBuvUZRlug4s5NbktR1ZvY6ziYdHx+j7XvMZjNszWZo2xZHR0fQWmM0GmX3" + "3HBXgMDWROgWVdNAsj8EwLFFlQyWzGluWicHGgguwJst2ybezEPQncwgPNQaZC1QlqCmAo0n" + "Cava3QXOHYD29zG+dA6YjPCJz7+KH/2ZX8cfPv06ujjBD33PI7g+r/HKGyt0XYum0Ngf38RD" + "567h0p7B9ngfu80EO1YjdD1KRJzTCmMiUPDojcZ2Oca4bvCf/tBN/PonjvCRzxCs0eh7j+A7" + "fPqZQyx+8CKaokBoRtB1DZQlYG2y2PJMgkMBICSjJUorZTxZS2f8gNfXYF17Xid3o/wFwJbO" + "B0O8Vtj7QneQxJVSibHuWOmA93NGCcKGOJrnSbJ/d3j/f71xegM/jl8ds4FtWaLnljPL1Qpt" + "36MZAGcAcgkFcQhm2erIhCxXq5xpGWYMhrVq4v4CKWa3VbVhM6vEK1l3XWIkM84mcTyQygPE" + "ElXsdkt8TpSya13foyyKzCHpGADtui5ldWLMvX7kuTop2WBF2XCL3RAjtmYzlFWFmzduZP6X" + "CEGySnJfxlqsl8t0WstgoYShl8gKe2hFM87xNYQ7YDMAiImaUJUgW6R/R2NgPAKNUgZQ7eyg" + "395Fcek8Rhd28NyrN/C///jj+O3HPgOlazz8wCVs7ZzDS29cR9+vcf2oxLmZw3vvfwEHs4id" + "2Q526wn2rcZ2iLDzBa7dugkQUNsCIyLoGOC1Rq0UyqKEVvv49771Jl545Sa+8HyPGAmVXuO9" + "by2xXq0RVYGgCNAWZDSiNoA27F1H9hj9JvFJEh4yZpU1d56G/EsGnO9m+QsQLgaLjbNwpZRK" + "2Ur5btf3qKxF3/epFQxzwHK7ZL5uzSRTOaOQ+D13cv+fNk69wrCXMhqNQJS6ME4mE8znc+zt" + "7MBxJsD3qdm8nDoSmBQnNypV77PZLH+meFIC7EsIJ6drxBCSqy1C59SqNAkLIXUqzATSts3N" + "/5bLZT7YUvCHIXiv2XLGGBMbmHsYgTEIaa1rjUHbtqlvj/coGGiVwwZWqxVG4zH6tsUb16+j" + "Lgrs7e6iY2vaD4p2hcBqubslgFzy4MXdthaerahYVwF9RbgZLwhfg6fAODxIgYyBqmtgOoOa" + "TUGzKTCdgSYTYGsb2NnG9n3ncX3l8BM/+wTe96tP4uqNNe6/7xIunZ/i+pHC8y9ewevHMzyw" + "dwPf/dbXcf/eMbanW9iZbGG/qrGHiFnfo14u4Y6P8PrVq/BNAzWZwGgNDUCzoTEmgKoCttzH" + "f/7DGv/8176CdevwzocI3/ZIDVp00NaD2hYI3ONb69SrPYe8G8wj66SIxNk6MQ8bT0u8zhyq" + "EEEzgfKuk7+EXBxpiGKSVjdyrRzt5ZlnJtnKTIsQJ4FJqgghdyGVvvZpWu/c/j9tfENZQiGb" + "rTkrsXQulTX0fS5Mbvse5Bxq7pUzzPpJZ0LvXGomxoWs+TQNdhclnUq0aVLWjEYpGxJCPqxy" + "3XUAu6MxBMxXK4xGowScrtdpkyiuleLJyZkWdj27EE6ceosY0a1WWVjBeywHRz0RbdqP5FIO" + "Zh3LQQQ1M/Ffv3oV5/b304LXm2r0W4eH2JrNcPPWLVR1nTouunRAgSbu7z0ANomtE8SjChvW" + "M2kNpXIecJAB5FDI2nRI5XgM2t6G2tsD7e2DdncQpzPorSnKvS2oSYP3/+6X8BP//OP4wvNH" + "GE/28O/+wAN47grhuVfWWKw8mqrEdzz0Ii5vH+LyfolRcxkXplPsFQbbMWK8WqFcLqEXcyyP" + "j9EfHgKc3YPSiVoQAlSfsMSpMSBTgPZ38Xd+WGG1vAkbPEYosO06VGu0EMmuAAAgAElEQVQP" + "fTwH1olwCK0BazaKJ+NYw9AQAEXmaQ3ToBhcieyd9iHAMpZ0t8lf6kWHe0fC19vJ1/JsCgAZ" + "g8ilNiFs+m3FyG2nB5Uk7WqFbr1G1TR3dP+fNr4hpvuy71PrjeUSBbvQvu95c9CJ03JlCLjp" + "Q4AH0NR1bhPj+h4lt+3IoZ/66mZpsgsD4w+5zoktjLE2g50iBMtKzXuPsiiSSzsQoqLBySo8" + "ur6Hcg7loGkbkPpyt7woPQP3cny5F6GHVH4gKfHFYgGlFN64dg0729sIAAoGWieTCQBgPJnk" + "tiTiAUZWnpnARwTD/bqHWVMBRE9gDUCShSKgKKBGTcKmZlPQ1hbU3j7o3D7o3Hn0s22MDrZR" + "zGo8/rkr+N9++nfx2c89i3K0g+98zwPQ5Q7+4OmrqMsIFwu868EjHIxew8GMsDPdx+54hoOm" + "wo42mHiPul3DrlYwqxXiugW6Dr7rEuCtNcia9P+QOFS671EpORxBoZqNcKwi4nqNcQyY9g7V" + "eg3Vdwmr4gQBImf+WDsTh363s7ASED9c/OKJbWgvxqQWLrkY/C6TfyY/y5pmD3SI92amPFLk" + "seIOEbIH5O9SSO36HuvVKpFnB9HHnd7/p41v6FzCGAKOj48xnkyyi7tq29S4n8M3Uiqf3Nq1" + "LYJKdVg+JKZunizWrIgxa1pZSJkFO7j5GGNeEB1T/EklXsl8sUinpPAhliI81/co2AqWEj46" + "lw7nDIkqIf2+1eC+JFSUfkERqX6s4x7WTV0jsnAF5/Bh06N7Pp+nlLVLvYwOj44wnU5xfHyc" + "BGptxgma0ShliooCq7bdVMWb1Kdb5iF3ljAGFDZV8SKbvDG1BpUVFNMT1O4uaHsHtLMD7O+D" + "zp+D2t/D9oUdfOmlI/zUz3wUH/zQZ6CLBt/3PW/Dcm1x88jh1ZeuYjyZ4vzkdTxwcAXTYo6t" + "yTb2JzMcNA12C4uZVmj6HsW6hV2tQOsW1PcIiACp5FVpk3Aza1OygwuL4T1016EMAYoUCu8w" + "VQRYCxsCCh1QEEDBQ/Wpdi5KrR0/s/iVyZnceJkb2D2x4uW4d7kWEbnxHeKmQ8HdJv/N1oxZ" + "aeTfeS/FGNH3PdrVKhdsS7mROAUhhKyQC8bbAntA3nv4GFFzFHOn9v9p4xs6l7CqaywXi8zp" + "WCyXqfd1CIiDqvN+IHjEiLbv8031PBmWSWTDm80ZAtowhsVllT5IXirKkVx4VRQoYjyxgXNs" + "TISirlNFedtmz0yxOy34Q+RJKwWI5NYZpihS47J+0xmyKgr0XQfLhaBFUcA7h8IY+BBwxIvT" + "9316fwhYrlaJk+McSrNp8xK8x6rr4JzDZDqFtTZzUobkRbGu4EwSzKZ7o7jbubxkNGZFtQc6" + "2Ic6dw60t4e4tYPi/D6qC7tYKIsf/4Un8P984I/w2i2Dhx84h+lkgtbVeOHVBTw07rvUYL/6" + "Ei5tH2I6arC/fR/OsaLaJoVRDKjbFrbtoNo1qG0R+z7djtZQ1iYP1qQwjqzlXkusWrwH9S4x" + "pZWGUYRQlkDTQGkLbXT62+EtRG2ggge6HiH4TObMyum20HBDeUnUhijzx4OY1pC7dHKYctfJ" + "fzCEQwWk7iSigF1I5yFaa2HipmdXx99RMhBuZA+FDYFUPEeBUe7k/j9tnB4SOoc2RkynU1y/" + "cQNVVWE6m23+zmCbKBcwaziw5ZFDHDO4lvEFyqUGw/Dv9vRzUVX54IBSgHbnoLzP3UQLxhza" + "9Ro1nyrccgZms1gpnSzC1qNnULRgDGLY/VCKM01RZExMYnbN/BY9WDyKKFvS8XgMrTWOl0s0" + "dX2CbHf1jTdw8eJFzI+PYYsinbiyXKIejVAohRWzh/Ww3UncHEowJAqKRTKTCfT2NtTuDvTB" + "AdT5C1AXL4IuXEA3nWL7nn2sSONXPvYq/tkvfxzPv9rjXX95HzvnG8xm2/DO4eUr1/HAffuo" + "43PY0V/EzqzB3vZFHMy2cFAV2FYa4xBQ9x0K56D7HtR2qUBZwFIyid9VeqCwiedlbeKCIYLI" + "JQycCJEApS2oKBLPqiwQihKuKNDMRmgXLcLVOoWR6xVouUwe2sCDGFIWuGQww3fyMiDhYcjK" + "TXoy9c7BAHel/MUTCT7VIopRV1rD8/0LFULKeww2nlfHe6DrezSjEbxz6PoeNiRqx/DI+Du9" + "/08bpzfw63sUAJbrNWp2iY1SWHFNUuZYxEERMpiIZy0i0tlsxKCeZEIUZ1CATS9o6eUtgDsR" + "5cp0Ulw8ylo+xIh126K0Fh0zlVUIuWWHgKvapNM8QhxUi3sPRZQXjID0kbEWOTJpzSCsZwpF" + "xW1zC16shrOQXddhvVqh4dDV9X0ORcHAf7taYWs2S2HDZIIVYx0A0v9N6pYp3QOEa6U4XS3x" + "PvN2iJSKdjQiv7cPe+E89ME+1MVLUJcvgS5dBvb3sHNxC5946gp+6deexGNPXMFbHjqP++61" + "+NQzBS5d3MZkVqFqPFRh0B4/i3tnT2H/4F5c3t3HuckYu2WBaQQa71CyotJ9D/Q9yDPDm0mJ" + "iewUQMElZcW4SvawGHeKxCz9qgSNx8B4jFg3aLbGMDtjPPXpV3Df+S1YCnDzOejwCDieA20H" + "GnCxBlTYE8oqDtZ9viIAiXWKLH/ECGvt3Sl/9qqGvpYkY1zfY9V1sEqhHo/R8jmLopBNUeRS" + "Gde2+Zgta1JH1Mi0iJxBv8P7/7RxOtOdtbRbrVA1Dawx6H06LbfnrIFoyhhjzhhI75vJbJb7" + "7+SfQRyu+AHF/ZbPyinbmOqahF/iQupXFAEUanPqR991GzDU++S6O5f7bNuiwHK1QmFMCgGM" + "SdaBP7PgrGLJRa1lXSchcmhqxFrpTdsMSTsLbwVAZgfLsUfCMi7YYiqkpoGGwcvgfcYsEBOv" + "xzJIK8+c69uI4L2nEAJZa6meTInuuwfm8mWoi5cQL19C9cC9sAd7uLZc4f/88Q/jgx95GUYB" + "Dz70MK7ctLhyU+PbvmULF89v48OP30BTW1zcVdhqX8Du3iXcd3AO90wn2LUWEwBl38P0PXTX" + "gbhrAqVJ36ShhWgeY8oMFgWiMYjGpuxeREoIgDk6WoOqGhiN4CdTjM/v4JmvXMP//D/+Mj7+" + "xBfxX/2t78N//Te+BRg1sJMx6GgEWq8BDodPAO0DsmwUx2sYKoo3FkImkJZFkfGgu07+4oUN" + "WOnCYRKqQ10U2VALGD6sR5TSGm1t6h/f97kTqTT6M6wo7/T+/+YVltZYdR1q5nv0XZcYs22b" + "aoPUpqdQy4dG1lWVFkrc9Mu57ejy3DYDSN7SdDKBZQ+oB6CsxXqxSBPnPYqyRLtapZ7kq1VS" + "YuLGy+fwIlRIRlWyFiL0kgl4ADLXJpP2IvNz+B5kM8qicCGkDUOEAptTWSomrgpWImFL8B6d" + "c9C8WGTBibcYnMt9yOvRCMvFAhrA0dERqqZJpxeXZU40KGuJP4cIUMZa1FszZR99FOryPVD3" + "XML0wXvw2sLjsQ99Dv/o55/CqDGYznbR+glevqpx76UG7333Ft776B5+/SNHeOByhYMdjTdu" + "rGGqA+xtR+xvbWG3LDALAVXvYJxLRbiRe45rA+i4cV8G0RlCBDkPMjbhWcYw0x4gxyG/0iCj" + "E3vdWoz3ZnjfB57C//D3fgl1ZVHYiF94/xP46999L7a0xng8RjmdAut18uwGvb4yMsZh4aBQ" + "chNhkE94VuCEAF+07vuEid4t8jcm467DH+Dk4SBDvqEpikz4PDEG79fGpCwse2iSoczK2Jg7" + "vv+/3jhdYVkL1XWJSMcgo/A1uvUazXiMxfFxag5W11gsFqmHdVVhtV5ja2sLQW9awQjpbZip" + "KIsC8/k8N0eryxLaGIwmEzjnMitZW4vlYpHIfF068VawBOcT2VDc0aG3BiCfVutDQF1VMEAG" + "9wXs1ww6GmNQaI1+kKXRDCQG8CEWjF945zJJsLQWpizTBuAFJq593koCltPm6PTlfI56PIbr" + "utQjfL1OBwaUpbTbpeA949qatDGKjKF6d0+Ft70du4/cj2XR4Bd/+3P40Mefw+N/dBMwU5hm" + "H0cLg3e9fYa2DXj4vgP89e+/B194scWiW8C1CoXpsVxF2POPoKhfQtU0qK1F2Xcw3kMR9zDS" + "GqR0DruGYVjWDTHNC9m0CaJl4F2wKwBQiZsFzbQMrfD5P34RN48dvvXdj+DWAjg6WuB3Pvks" + "/up7LkAXJcx4BL0cA4KZZSL7AO+McUAO3XCzok8F06QDSFGuabMqnS94N8i/Z/BaQHvBmG6v" + "hwWYiMpeofInqz8GN5G+n+9fJk1aSYnSlgMv7uT+P22cjmGt12g41Mqkza7DqGlSecxqtTl9" + "BOnAyK5tsVqvUVdVehghkgE57rXWolAq12xpInTOYXd3N58Zd/PGDYzGY0QkTowPAdPZLB3P" + "zVp9wYz2pmlSXM5uqiwI+M0RQ9raFLPzdc57bG9vY3F8nEPQXCSN1CJEOjqKyZbz4uSYpJLj" + "emlj49oWfTx5gMDQBZZFm1tsOJfY04tFyjKFkLCJGGUOiYyhGCORUoq0VgFQpVJq5+K+jjtj" + "/P4zV/FP3vdBfPZLR1isa+zsX0AzmuG737OLm8eEv/Luy7C2woVz2/Ah4rc++ixm4xpqtoeH" + "LnRA/wY+/pRFERs8en9AryvAJuUkSoDU5gi1E3h33OBGFCLIuURa1RqkbfKwgNw9Qco2oFKf" + "b7+a49L5XTx0/yVAFbh4oHDjMOC3P/YavuvtUyhVohmNoMeJPhF7l7AyAIHThUQDRhanCgeU" + "2nRzIeTTpCVrFWN808u/ZOMt2eEYY+6/rlQ6Ak0iiXyiDitUUWYSrg05XrkxgHiEnEzo+x6W" + "M6BAwu/u5P4/bZyqsKqmwXq5xLrrMG6aRCBbrTbxNYPX3qfm8yQuML9/qN0ja36hJ0AEz+5j" + "U1W4evUqRrwISCksFwsAgOPUsyx4ab4v59KBKBenDosrJVWbFwoLS1GqJ1xx2GnZaqwWCyzX" + "a4zHY4zZw8ukvZi4O8KOFgxCahOl9Q3CphXOarHIR5fJIhZmct68PM+LxQIxRtSjUQIqlaJV" + "21JZVcpaqyKg2rbX00mlQF498ZkX6Rf/9eP4yOOv4Gg9wqWLB3j72/exahVeuqrw4SdbjMcj" + "XLy0wktXFvj45w/x8KUF/vIjF/GWy4Q/eLrFk08voELEG7cMfudGhXe/ZY33PDBFhxK2USBS" + "gFaA85l8efvYhIQB5PqUHeQ0fPKwCHBJRlFRagDDQP2twyXuOT/Cwf4Mz77cw9gCpGu88IbH" + "7z15A//+t5/HwtfQkzFM14Jcx1Y6R4ZAz4RS0EZ5UmRP0COCkvenNUixZ8NK800tfyKslkvY" + "qko91zlDLokpOdZMuFEZAtE6JQ4kQynfGzedRkVxyIlBPgQUMZ04bVghSkuYO7n/TxunKqz5" + "8TGqssTOeIzj42M45zAejdKXMbbUdR2MMSibBovj4/TwxmC5WmXmuWh5WxQoOEYWMLPrexit" + "0XYdZtNp7tET2zaDfkJU69drNJMJNLvgvfeZY+K9hzWbtrGSCYo8Wa7vc2mOUB7E45ofH6cM" + "Blup5XKZ4+2cneHFJaGlZ8sKwT544mVRBsbYNr2reDOpzdHkwbmcBpZ2IfPjY0wmEzjvs2cV" + "QtRak97e3VZPPfUF+ulf+Ch99PEvQ9ld1M0e3v3wNrpe4+XXljhuR9BG452PlHj92hpP/NEK" + "IQY01QzvefsBKrPG7z7e4vkrCn3foO+A6djjlVcLfPyzN/CWSyNU1TaqSkETQFqB+tT0LsZh" + "R1dg6MVQCKmrJyssMjrjI4nOMCAH8hFd3kfs75RYdQpdKNH2WyACVm6Bzz63xve+aw1rRxiN" + "J9Ad0ymcB2LY1DTLfUjfK/G8onAePGJMTQ9lLRS2ABX2TS1/6UQS2euS+4vs0cSQWORyBDxJ" + "CDtQEEprQG2aAOaQjPdjwYdPaFa8CoMwEYklcCf3/2njVIU1mc1weHiYOiNYi4o1t/zeMqXA" + "MUlte2sLi+USy9Uqu425YJetQERKs/Yu1XLVnC4mAEs+4y20LUZcR9hyStlxdqLjLMtysciY" + "13g8xlrSozzhxlpYrfMpJdlFF7DPD9phsEAdu7aaKGdZAE4bGwPFm7JnUDJiY0X0AHiNIZ0E" + "IpX1YfC34eIXEh0A1KMR1lz+sFgsaDweI6ZT3ykgquC8+qmf/Jfqp37+EyAzxlseugerdY/x" + "eIRX3ujgo8HBdsCD545xc7WFzzxD2Ntp0NQejzywhRdfC3jh5TmOl4RXb1QACD50KC2w0zgc" + "zGrcWE/wyrU5mgtjNHUNzVgPdQnDIOmnPlBc2d0JAeiLpKR0wrHIcMvmgZcbYgBIgZRGCMD+" + "dgUyY7TO4J5zQBcrXDqw+KPnb+GpL8/xA28foaUGZtJBt2uQ61Ohc9jQRjd6i0AkrzPni5Bb" + "+mrOmoUYcmPAN6P858fHGI3HOWyTziOWMTLiz2p5vwz7et2eiTuRfVObTr5DSoJ0XJUQWPpw" + "lU1zR/f/aeP0Y77YFWzX63SYJWviqigwXy4xbppMIej71LHRWAvVtui7LqWMJRsxcKHlSCBr" + "LVYy6RLXx1SMOV8sMKprGO/hGCwPzuU0qdyHcw7Hx8dYdx0m0+lXuZaCQTgpedA6lxHICb5F" + "VYGIUu9ua3OpxXgyyQtQhC8hgAdQsjs8XLiyQPJJvdgcOjnENkSYMnpmSUv7ka7ryBQFRaVo" + "1DT0o//oX9H/8vd/Fe94z1sQ0OArr64wGRl4dwNvOdfjvv0VSt0BpHCxdnh47xKu03tQ2hU+" + "+8cEHxSuz0foQ42yABADzu+nUGO/GaH3I7z+Wovf+tQNXP5rxzjSJcq6yG1+ybnbWhMPKQYc" + "dnUdyFpErVJGMXtYPoP3uYjXaBAIijS2pwbKFFiGHVzYWeOVqwakGnz0M3N8y0MzlNUE5XgM" + "3fWA84DnHu9Zxqw7aZi2TDcXiRjD0llOtiwTteVNKn/LfeXBeA8xruT6HoG9s8IYtEAuj5Hu" + "nQLOF1WFfpAlHIZnJ7iNMUJjc1q16/vMaYwx3vH9//XGqQpLyF3W2sQw5w+W8Ms5B88dFYP3" + "aJ1LBaKDJmhinYRlrgaC67ruRL+qzGcJIWVqui53SOwlM6jT8dgrbFjJAFAYg/nxMVbsAnd9" + "j54XzYiPahJy2mI+R+8calm4zqGqKjSTSeZvNU2zqYKXlK9SuQTI9z1WbQurdcrmcCaybprc" + "vlmeJTiHajSC4xBEGM3y+zCTJKcHh5h4LUk99PHgYBu6aXDl9QUunLd454MKD1zosFW3KEyB" + "wk5RFyXKwiKQhg9H+PQLn8PvP30fdBER9QSjUY/9WcTRusb9l2ooFTEbKTz9zBwqLtD1AZ/8" + "gsG7Hj7E9717jGUwMEViXsvpNeT9BtweKofgE3vdMGnSqORpqYQXgZWVihGBCFAahY547mUH" + "pQwO5xaqDFi5CbYmS9zCCJ//SosvfGWO2aNjNPUIduqhXQ/qO8D1yVOSTTjcmFEoD6zAfAC0" + "Slk+7zFfrRCAN6385T2yJ6y18KJw2PhSUaBsmpQBd5sDhKVjqefvABL04UPIDfeCT+RpUdS5" + "n5x4Way87vT+P22c3g9L63xCSMVdF4FU0qAGhLOeewqJ5hY3t5SeQ6tVVhZDQWp2JzMQxyGG" + "5u9dLhYpFGThxLBpXyuEt65tE+dFpeOvJU09qesE8klNGBIRVhuDyM/RO4eKS3xanmAAJ6wh" + "EaEuSxweHmbCnCkKxLZFxc8nYH/JFlIssWAGxhg45tQ4zj4pvTkzDoPFmP5JFEilVETw8fr1" + "o/hD3/2W8D/9dz+gb928ifsvqkhuAaw8jcstbFUFJtai4RAuFhZLexGzt8/x5TeO8MI1g9GI" + "4PsG73i4wWu3gO0thU8/fYyD2QKtL1HpDlFv46g1+MAnr+PRBw5R7FSorIVmpUWisCRFx+QC" + "kuyUbZNXpTSgTKI4MCUgdWxINIIQASoUJrXCx379NXzu2Q6PPDjCjXnE7vYIh4fplOVlH/D+" + "3zvCOx9ZYl7soByPoPoOqu0Qu+6El5WnT2hiksYkStdpk8tqNHsWb2b5C8dJQP+CW81ICxpF" + "6VDWfPJMPHmCjrid4TYlIR6uY4Ne2M1J6vm9fP0d3/+n6aPTLlBaYzGfo26adCQSx7iSJRCC" + "Wddz50Egx8Nl0+DWzZupET+zbzOBjF+TmikKIT9I51xq+qY1dnd2AACrts1dG13XQXPBqBDr" + "NFsh4b7IhJ0osJQsD5f4yNHZOQvEC02a5ccYcyX+uutQVBW69Rq2KBBcKprt2BUeq8SULqoK" + "br1Oi4DpE+KI986lolm21LdX3scQhgdKRiIiH0JUREERESlNf+Ovvh03blylw+NlPL56A/Xq" + "dX0Aj0nXolmtUPikuGMzQjubYTbdxt/83jn+5cev4/x5A1PNsOpK9Os5Xnv1Ju4/UJivFEAW" + "t5YTBE+4sN/i8y8U+NTTh9j69gnKokxpaFMmJrv3Ob0PDKgPMYBsAWUTw11Zm0pzRGHxz7r3" + "aMYFyET841/+DP7Jr7yAS+e2ceVwAhdKXD8ucGsxQVkuURqLq4fAb37yEP/RvzPBAhXMeJwa" + "/K3XqcYw+A0H64TnJ+Eh37PR+dQcH+ObXf7JaA0UWcLoYj66q+M9qDnr7Zzb4Ip8rQDeooxk" + "/xFRqqccUA6kS4OE+dJZ4U7v/683Tsew+h4lpzbr0Qh922ZATrJxhTGIoky47sl5j5Io86oE" + "4D5x6otocU4pS42U7jZntc15sobM3J5j7FHT5GLNGGP2oLzWqa1G16HijEa2rGHTYF9pDcXu" + "tLSaGWaF2tUqufrc8UGwj46zl0Tp9Nps2diiIsaT9VXYuLtKaxS8EKUUQqwbBgLj1yLze6LS" + "OhTWUlM3Mcz2aLJF8RhE8Utf1HtGYxICbNencElpYDZFSYCqSjywO8H3v7PHY0+vUFbX8Pmv" + "9HjHgx2ianBjXuLGvGYgnNCUBmNLmC/H+NXfv4p3vfUIVTVBXZYw2uTThxEiA/AQIlTynsoS" + "pqmhqgpKiqCVRowJeA4xYrZV4yuvXMeP/exH8cHHrsDUF3BjOYIuDIqywNWbAaUlnNvxuHqr" + "xHw5xe/9wXX8lbfdwiPnD9BWNXTTQDUN0LaAk97jfDtxo7jSxiXAp8JcU/IhESEdLvFmlr94" + "R5D3x5jZ50DKDkZh5tNtxcQsF3kW2WtDpXB75lBItIrvR/CsO7n/TxunH/PFrmPBh02WzMQt" + "uBK9Xa9TfB24Olsl9q7lPkiZsMYWxLN1lhtvua+QlAUIf8VL2pOP9waSxl+tVohIXSEBoLQW" + "LoTMRQG3n62ZSKqJsAZSVksplDwp0gJXrCbxs7Zc3lCWJdZdh9F4jA6DI454sQ1b6BZsdWQh" + "5cZsbL2NtSmMYAFrY3LRaQwnD6SM4omwwrJao+u6GIFQFgUwGpHVGqqqIl59Va+uXEFtDUof" + "krLyIbV3cT2UsZiMRuiqPbz7AcIHP3YNV/0SW43Bazca9CjRhwrWBDy4P0fvAl56o0HXO5zb" + "6fHCyzV+51M38Df/2gzHrkJR2MR8F+A8SuYLyZkJEaquUE4mMONxWojGwHNrmaoyAAX8xm89" + "ib//j5/Ac6/02Nk9j62tGbStcLQkxEiwBqjKgDeOG+xObiH4AvMF4X2/eRX//X8ygdUVirqG" + "HTWpY0QQj09OVYqZiZ+wMwUiQDUNyjJxmpDoIvHNLH+lUn+ubr1O/bK4pUu7Wm04iTGewIXk" + "M8EKLDKOJUpJDk+NIWRKgjzXkOAp5TR3ev9/0wqr41hfJuXo8BDNaISjw0OU1qKQeiLv0Xuf" + "PBiktOWaewEZY1CVZUp/clYGQHZlpV6rdw5FjKmfELuPhA1JD9amODqEXP/V9n0SqPf5lFxp" + "5mesRcfaPS82Y3K3RaN15roILibWodY6NSCLqbPpsm1Tdwdm/q9Xqw0gWlUnwVSxgAy8yuk9" + "UqQtgivKEo5T69JSVha6pIKJCMbaELwnANEYQ0VZorA2YLmg8MorUFUKYRA4e1cWIK1SL/ej" + "KSbjCcLWCP/h963xMx9wUL4FdSWapsPB1ONgy+FwWUFRwM4s4LWrDWZVjXvPzfH/Pq7xjkeu" + "4b1vH2PpbMIpFIE012XGTXdYioCOAaPtbdjJJIHKMcLqZD0/9enn8GP/7BN44jMvo41TXL58" + "Hy5f2MayJbxyrcOosXDBYW+2gPcKC29xvCpAWKPDNn7vqWv4zne8jh9892XYosJ4MoHxKZyI" + "4bYTw5UGFVagHWiXcFAzGhFiJK01FUWBNsk/vlnlb7jcJ/hhpwqe+hAyPhiwoTRIgbPU09Jt" + "r0uEoa3NuFgUkN9v+scDyAev3qn9/00rLCBl33qXuiiWRYEl9/pZrlawkgUYxN1R8AHnsLW1" + "lTCDgdttpBVtCCjrOnVhcC6RE+VzwL2LXCo4nTNpTQqYlVIo+L3GWti0ieFDQMsgPAGp86ja" + "HPMd2dPKJ6XEDUcrxohKiHRaA5yuRUyEt47b2cQQMgC5HJyqIiRAz1hF5IVGQD4dWCmFno3A" + "cL5ylkawNrZuMYQohwvExB6FTeB17BeL4G7eQGxGgEm1flHrBGGs18B8AXV0hGprhn7c4Fsf" + "HuOB88d49rVbGFUau6Meq26GWwuL3ekaL16dYG98jKPa4KgtcWHvPFS5wKe/fIiH7rmJ0lQo" + "jYHCxqWPIJCSbBxBEzBmhaWUwmRc4OhoiX/w07+JX/zXn8XNZYHZ9gW88/59+Kjx8pU5ls7C" + "2gLrXsOaHldulGiKFuNijnVLWDuNEDR2p8BvPHYV73zLFvRoinI0hg4ByoUB3SJy99XIveAt" + "ojbQiGiWW7Db2wpEWmtNyphAfR+1tYjexzep/PPhEgKeQxQiY15Dr0gymcJ8F88mUykGSmFI" + "OPXO5SygZgdB8b6/k/v/m1ZYgvIX3DVBaosCKw+ZiGGzvK7vc8x1RBIAACAASURBVObBcaim" + "FJ8byO6u1mlzrebzrDDkRA+J/4WPFbxP2pzTqFprlExKE9hSWs+4roNSCiN2y4cLQt6rgNT2" + "ljldhnGK3jmMJpN8bc8V6aBUnZ7dYQb2bVnCcjpZW4t2uQQRJfIrA64S3go/xhQFOi436roO" + "BTcVlHkcFmwDiVYSvIcPIdZNkyrj1+vU4imk/kXR9cyOVLm9CroecbUCHR/DHB2hHk8w3R7j" + "P/7eJf7h+49RU4HD+Q6qeo2Xru5he9xif3KEzhXQpoAyO/C0xt5Wj4/8YYv7Dq7hB79rhpWz" + "sCbNYdTcSxxMkOSQZLI1w87eFopC48O//zn8g5/5PXzqszcx297D2x49h7Iscf1mi1sLgo8F" + "xk2PvfoKZvZVTKslQAWutffi2WuXEKNCXXRoqg4maHzppTl+47FX8J/98ARLlLDjEahjmoNP" + "B4JSDKmGsa5ATYNY1dBaYewcyksXlSlL063XqaDemGCJYrdavdnlD5H/mj2h3F6GcTA5Hk+b" + "1I9MMDLhg0mXCAAZn5IwUhuTS48kstGcWLiT+/+bVlhSLqC0Tr2plULHjfjFdfUclgmoVzGP" + "BCy8pq5zvdHx8THGUu3NDdLEVRblIv2r4Fwmtwk4Z6tqA2ry5Eo8LNlDJRuIPSrJAoFSgWXk" + "UgANoF0u0+dKkSlX198eTyv+fCllCCGg4w6n3WqVF5B3LvF3Bm6+504TluvBpKeQ4eSAZDe/" + "qoiVCGoQzopCl1YjOX/PP7mODpy6blvQfA51eIRiMkFVV3j08gTf9bYOH/7MAju7DTQIB5Ob" + "uHlsQHqMdzy6g++ZRHz2mSNcuXIDpIGLF/fw9Iu38LaHr0OfL1FaA6UNiNLhATAGURH63qOs" + "CzTjCl96/gr+4T/7FH77sS/C0wgPPfQW7O2McetoiTeuO8zXFjuTHiN7HW89eBG7kw6TyRhN" + "vcXW+SouvrbA41/eh40Rq46w6hX2ZoT3//aLeNvD2/j+d1xG5wvougItq2Shk2sOqmtgNktH" + "mU0n2Luwiy2l4CbbqlUwAYiaKHZtGxUR2bKMd438OYEkBGOtdTpoom1hjcmnSYUYUbAyExKn" + "1Xw6DjsExOB/BuqRcGFRdHd6/3/TCsuH1LdZ2K2iBbvVKgNluYdO5MJP4XywZ+Qdn0hChJ2d" + "HRwfHsIxZiBZC0nZghg45QkHu5Ka8QWxRpnfwpOfMy3yXqSMRT4dmVKdFBj7Ehd22FJEcUjp" + "/j/q3izIsiwr0/v23me+k/v1ITyGjIwcKwdqoqCgqqhuxFQmGkyYJDPJWg964En9qDfJTDJD" + "kslM6gce6JbUtEmgbiQVjZqWgBZQdAFFQUENSVZmZWZVzlNkRmREuIf7Hc+4tx72cI9HAZ5m" + "1RZkHDMP9/Dx3LPPXmetf/3r/10ZmuS5DWiuRS3ZtJ/9hTbaSjQDlKsVrdanjCWVW1BvboCw" + "w6KNV7M0xg6bui6Rf92m95p8O9xfHw++9qVsrYAehIlgY2w3ryoRiwXRfE42HJJGY376kwXP" + "vrpA6Nu8cyPlYK+hGG7z4JUJb19bc+vmHINkurPDE1c6vvXtQ7727Rn37d7iZ6djlnXq3FPE" + "ZoBXwHiac/XqIf/sX/wFv/avvsnVW5L777vMpfNbrEvNG1eXVI1EKsN92zd5cPca9+8vGYz2" + "2Znusj2ZkOc5kYooq4r7Lx+xMznmt/5MIiWM0prbJx1V1XB8MrdqBkbaQerISTJjrCzzcATb" + "U5L7LlANx/zm11/l2W+/xdvXDuU/+PmfFJcv7uu6aaWS0hgwkVJCxrG5J9bfZTtRkoSZPCEl" + "scvmlosFWZoyHI38EL3VUnelqB/z8a42voSL4xjlHvK+yrnr+/+M430RR310T/Lccl+ElTcV" + "QoS6XUkZNIICYNx1QTKicyL9SkoyJ8JXjEahW6Kk3NT1vb/vyWv+aRUCln/z8se+XevTTreh" + "S9ed8UL/sNERgg22ULvWtf/etm3D3+rL1fj2s7jj4kopSbIMWdes12s6Y8hcWuxlbTwW0Tgs" + "pOs668QbbVxEfPtbuTKjc21lL/1stGY1n5M4UmxIsLTByB7b275QaBpYLRGzOcl4TJEXXNoZ" + "86MfX/GFvzQ8fkXSkPPkQ5J3rl8jiwXLKufKhYxWw58+dZVIaC5fHPPajTVvXbtFfLkgyzMb" + "G6QgSyXadPz6b36FX/rVr/Lcyyu2t7f4zCcvsSw17x1WHJ20tCazgWrvXc5vN+xOJ0x3H2Rv" + "d8rO1hajoiCLE5SAqm2ZLXbY3roJXOfzv3/CsTZsD2v+vZ8ec2lHsV6s2bIdP5Bu7MdYnXgx" + "KFBbE+rBmP/xV/6A//mf/SHrNmN965jJZCz+wX/6IyKOU5lnqdZai85NUdwT679YEPe6dl5R" + "InYgets0G/lhR8cwEByk+1WHx5rMHa/Hn7fHle/m/v8b49FZ39Bnv3ZNQ9tZWVmNJXjGvQym" + "z6PwWYv/zHK9pnSkuziKqIUbL/BcDNdJCT8vpXULjnpqiKY3XOrS8r6Coa+Z/UVSQgRrJuNS" + "+P5r8tPyIRh2HbXr8viFTiA8xei6kNUYY22UurJkOBpZb0RjSLKMzOEQUinaurZgbZYFMmvs" + "1FM9kBvR44mxGcr2oGjbOLMA1wENpUWS0GCojX2TaKtJZZwprdZQN8j1GjE7Qd4ekAwGJPk2" + "P/6JKd++umQ+nxPnipdenvPqexP+g5/cYTiQfOErCzI1RyYjnriS8M6Ngm+8cBuhb/Kf/YeH" + "aJFy/zgD0fGn33iD/+F/+RpPfettomTCk08+ymSYcf3mgvlasFxLLu+tubT1Old25+zsTJnu" + "nGN3d4+96TZb4zHDPCNVCiUsY77ThkGWcrxI+KlPpUTqXd6+PuOjD0SMB0OGUWQdwasqgLpe" + "BllKZzSbxhwt1zz/8jVkssP9F88x3y35k2+8y8/91Ltid++cUEqKNI6FkVJoranr2twr618M" + "BtYrMMtCddC5+1e4bpzXnfd7KgD7YqPJFbIcD6A7ysSp/XGX9/9fd5wdsHwJ5WtmZfWm/Xyf" + "F66/k8Ph1RR9rV1kmR1mdl2MNM8tb0NZ+QuvUeXTXowJc1A+NfYGqv5z2gUl6YOQ6zb0SaRL" + "JxMSu86H6C1O08O/8E8dT3BzmaU/h+CUq62XneeY5HluSapVReQY0uVyGcQGOyktl6eqgtxz" + "6W4y3zXyKbh/Xf3DlwNrh7UZbaV2BsMh67rh3eUS2pYiju2TWlmFBGKvlhAjlgvUakXSNNbz" + "TwjG0xGffdLwa//mJoOthAsPT7jYaX79C0t+4JE5B9sFFw52kUrx1HMz3ny7ZG9ieP3mmOde" + "PuSHPp7zZ3+54Etfvcpv/O7LHM0jHnv4EYaDlHVpeOnNOU2nGGclD126yUMHtzm/mzGZPszu" + "7i7j8ZjhsCBNMhrTcbJcOhZ9C51xXSqFkoIkG/PZHxTMT4as1jWZVERCsFiuaFqbQerFGtPY" + "hkuKtaYaNTVrI2kZkeYr0iSiajKOjte8e+0GaZaLPE1lrJQWQgijtfFZ1Qd5/VdlSTEYULms" + "zQXaoElfFAV111G785KOymOMCTOFkcvg6rI8RSb1AL7RmsYpMdzV/f9vI2C1tfVji/wJLBaB" + "KlCWZchwItMbugSE60T4lDqN46DiqJRCudTQE0bpBSPTC1T9OSjj+TJCIO/gbXj5j9gFvDhJ" + "rHqAu+F8RqYcaO0zq8aP97jPdW1L47qNaVEESV3ZNMGeO3Y3QeVSWgm07ubwppSeTFeu18HH" + "DiECsXAwGFC50qOp64BLhXOMIlIhgmmBb1kXrlvVjUe898QTdIMhkdFO5VPZdr5UCOVMTSOF" + "SlLSomAoBIOmJW3hyUdG/J3DE24uG9brmsPDFZ98LOJgf5vJeMi3Xu147e0l61Lx8cdi5osx" + "126s+ZUvwJ996y2eeaXl7Wsr9nYu8cTjYw6P19y63XLjqCaKEx7cfYdH9t/j/K5ksn2e7e1d" + "JqOBBYLLNYvZCcdlSbde06zXtKsVXVli2o4kicmLgnQwQKQJTWfQ6zVquaBerzlalxwu5nQn" + "M5rjY7qVDdxxljO6cJ6tBx/iwLSsdw+oGsmwSFi3GUWhaSrBsy8di/Pn90XdtCJWjUDY1vy9" + "sP55UVCXpcXFHJ8qShJkZ+dmFw7kz4qC2r0OYDMn6YJtf2QnZJFsOpVaW6OKu73/v6eA1fkh" + "UcdiBTYAIi6ddFlRUDP0F8R/TxSFafXlfA5AU9cWuHVf82S2IKWqdYi8yr0ZetHbtUV9Bhg4" + "JcJqDbWdZep6QT8Pgvq/UzveSZFl4eL7jk7tOkWxoxD4dF261q1vHSMEMVC6oBg5jKFpmuCl" + "mGQZqZSn2MHLxYI0SZg73Ew4IBZ383gg07fXjTH2qeye4P0b6IH77uOhhx5mcvkSpnKdFhe0" + "hJRW4VPYoCXimKgokHmOTlIWbcUnn9D8439xle3dfR65coH7DiLeuBHxh08tkGgevliBTLh6" + "PaNaQ5Joqkrw1Zdj2q7jsUfPMczh6nsnnMwNWsPDB3Pu23qXy/st0+k+093znNvbYWsypshz" + "UimQXk65tkPMuq4xzpSVpnXNPmt8i5R0bUc7HNCNR9ZpuqoQ5RpWa8x6jWkqRGeQSUI83SY5" + "f55iOuWaVCQxdGLAdBxzNM+IYsnRcclqMRfVdi2KLBWxUkIIIdq6Nh/09feUir7Uku6s9rwn" + "mequo3Z0BLDgPlqHsrPP9fKvqc8Bw72eu73/v+eAJYQItHyw3JHMuSr7J00QKetlMT6t9NFa" + "usXP89wOTioV0t36DmxK+MDkampPlAtBzV61QHgzZjOXBZyaGvdehr5M9MzaSKlTowOV44v4" + "CXmMoSxLS3aT1glExXEoEWCjZ5S4p23jBl2zPCdKkhBEO/d9Qlj+iR/lCOMIsmeQaTZcFf8z" + "ouvCQG5fBiRRir0s40BJzj/yKOnDj4D03VIRjEu9FIwREoNN46um5dbxCY8lhh988oQ/+uaa" + "tKj4468vOVkseeKhjHPTiDdvJDRVSdkkTMc1qzJn3WTEWUNiSjo0r1xd0umc3fEtzg2u8ujB" + "ETvTMdPdBzk4d479/T2m0ynj0ZA8z0niOEwvWCkU1+F0NA0/j+ebJ1obtO4w2qrIWgEG1/V1" + "AznCbEZatBBoKTGR4a2Xr7OuBUmSsCozdieG+TLj2lFD1y2pqoa2a9HGCOzfFVEUmXth/ZWb" + "7PAVh98jQthALx2QnTgsqYLA1fKYU13XFkOTloDtH9q+LPYjPHdr/3/vAUu6MRbX4fBt7LKu" + "UULQdF3Qs/GyLXEvygfwrsfk9UBicNZ17VnZy5j6ZZsSgtZhCOGJ4tJtqaxwftT/G1pbCzBc" + "KQhWRdI9KT2O5dNd32UU0lk6OWAxdSqnGGO7iO6J5iUxtDsfT62oy5KhGxCN0zTMbUmlQjtZ" + "RVHoGvkAKoyxnm9K0fgnpVJWc95hH75c0FqTDQbuZ6W9GZuG5R9/ifpb3woGpkhl2e++RFTK" + "kinTBJHnmCyjiBSlTvjpT0/5g6/f5unnD5nuwg89kfHKe4quXSO0YlhINB03jicYWjoadzMb" + "DmcNcZrx6Oib3Dd5l/N7OaOtB9jd3eVgf5/dnR22tiYUaUoqJaqqEMulVdRoGmuQ2tSYusHU" + "NaaxJgemqqwiaNNC29ivVxXUFaaqMVUJlf2YxmZptJ01aN3bhfsuEz/+CO1Ksi5bBkXO+Qvb" + "zGczxltTTpY3WC1LmroWuuuEctIz3oHpA73+RbGhPkAISnVdW5zJ7RHglOtUnqY0YsN17FyW" + "40H8ruuCDhZChDnBu7n/v+eAVZYleVHYRXAn3Tr5YrCuOh6o9hPsuuvsMLKP0mx0omNXb3eu" + "do+cTrsPTt5IwpsC+DS0KstTCo4+lRVSkrqyrnKaO4lrTQuXsuMCl8/EfAno8THtblJcOekB" + "RT8IGysVPNOqsgRjB139hRbCSs3macpitSLrDcO2oXu1Od/IpdGNI/7FSRK6Ld7qSGtNYwx5" + "mlK1bXgqF1lGWVWWfd1YN2QpLKlWzBf2hoojhIqsprpSQa6YSCFaKxGjtCbNMkYqYm8y4T/5" + "yRO+8I1jtqYZL7yqaZAcz8c8ef+C2TpjXqZorEKoEZI46ejamP3JnEvRF7gwbdg7d4mDg4tM" + "xkOGg4KD/T3LrcoyYqWshHBjteG9TI3pWkzbQlMj6tpaeVW9t7LC1BWirFyAKq20jAtaoqox" + "tf0/WkNR2LemRSpBZzqqBvbPbTPIFSo6x2pdUTfw3lEnzl+sqJsOqbpgwPNBX//K7S2vnCCE" + "CFZbHoQXQrBaLsmczHWepqzKEt22DAaDMIurlKJcLq2YpVM/8eoUg+GQ2cnJXd3/33PAyrKM" + "rmnIBgMaR0IDWC2XJO5i9zV2QpprLBlutV5baZLYCX35ut11EUJnQDjyplIhrVUOk2ocHnXn" + "4dvGfjDa1+dCSpqypHY3kYpjG4QcLuAP35pGWB5IZ0zQKpJCoNwF7rSmapowrGmw0srG2Da2" + "kJI0TanqmpEDR2P3N0Ng9ek+NghLp3QpIOjOe9zDuI/BjmZUZblRinQCcVGWOakXjWlbTFsj" + "4sQRb72RqDhtNGosN4aug9qW0FmSMEgKPvPRbf702Zu8+OoRW9NzbE+WyBiO5inXjgcoKYgi" + "Q9sqdsYlio7ZUiLr2+xPl5y78CGuXL6Pc/v7aN2hBAyShDyOSYTDrIRBSuFkjO0coscpvaoC" + "vYzQqAgRdaA7TGwhArSblzOWpa3N5rUCiKJADIaYQYFOU4ysqdqIm7c1J8s1IkopVxVtnXKy" + "WFHXlei6DmHsL9JaYxwA/4Fd/x5zfr1cBva9v7+1KyE976l0FYjfMytHWs0c4VWnaTBnQakg" + "99LU9V3f/2cdZypmBbat6wb4ujlNksAIlq5eNsaEFDBJU+I0pcjzYKPtf5d/A2vbDXYos23b" + "YG66Xi5ZV5WVXHX6WMAGjGyakFb6WttzOjqXRQ2KgtKlyf4p4H+HH+tRSpEkCUma2u6Vb/F6" + "ANJ1e/yW8K1cv/h+gZaLBYvlMphflqsVx8fH1sDBZW2RUrZz1FjB/cxhOZ2xypee8OeJgF5d" + "NXedKhXHQdq5XC4x3SZTEa125ZPNWEzTYtrGkh9b//nOfo/LVGRVEbctuZFsFRN+9tMJwlTE" + "zLh5LFmXHW/dzBB0SGmzhA5JkRqqJiZSHSftOYrxfZzf3+bg3Dl2trds8K9qlNbWjLVtEW3r" + "3G7c5e13sE2g6IdNbTymhcN0jMEYTfii/z+eBGwQSmLiGJIEkSRopXj7RuXGtwSLaojQaxpd" + "kMZwNDPorqLTRvgn/D2x/k1DuVyiu458MCDwmFwm50vO/kCycsHEy0G3TUNZlizmc6IoYjIe" + "27lGny2pjQb93dz/Zx1nOz9HG6mMTutgBxQ5uQgPLPaDBmz4W/25LI8R1E4Dx9f43oixrb3n" + "nKuxtUY1G6kY32qld+NUZRmY8KazThxtZ0cCQvrtLkifw+Xft227GboUtvXqHXDbxkrA+uzO" + "d3T864uiiHK1YuSMCrKioHIdj7ZtGYzHNC49bpWyhLuuQ7vujLdJrxweEpQ5/fXTltUcub8r" + "HaNY+YzE8jVc1tS6ssO4jMMZRLhYYBAQMm73SSlRUpCnOSkxn3h8j08/8QZfe2lNFzdUbcbu" + "9oLGFJRtagHluOPaccHB+Jiq1CyE4Km3H+H7P1wSxylZmln1y7q2+FJa21IU6c4DF3DcJQ/q" + "VYTP2c/7SyFOf65vjooItl52PCdGZinkGeQ5lRa8+MZtyjZnNxbOvCEhSzXlKmGxXtI1JXVd" + "h3Z7nCQhCH1Q1z+QQYWwYzhZZoFxhxX5zqI/10gpNFa7S0lJ7UwfVus1aRwzm80wWjMYDoOB" + "i9ePN27/3K39f9ZxtkSylGgpGY1GoQZWDvFX0UY9QTnAWvrtYE63TZUboOxcJBVRRCSsCH4Y" + "omxbG4CiiMSlov0g48mjob3qQDzPShZSkiQJqWsUtHUdDFfv7KScUoT0Tx+lwjCpBHSWYYyh" + "lhtHaY99Ga2tKUYcs3LGkh58lVFEmmWhc+nnw6I0tU8mVwr4Gcn+hvByJrBhHtetlfhYLhZB" + "sSJ2Wkrozg55OwwOlDMO3exy09pIEazdBdDUtqMoFUoqRlFMo3J+6lM7/PGzSzK1QJiIIpao" + "WPPeTJEmgkHWEcmGo1lOKlrKOuOl2wXPv1Hz4JWSVltJn05KG0TbxhpASNc+d3+eEEg3nzuV" + "dfnzNBuvweAejTmVgSGwzYUshTyHwQCKHFLFXzx7xM4kRkWC/VHN8bJgXCy5dTvjeKHouppO" + "G4QUIlJKJA5a+ECvf7PxMvBcrOPjY/I0JclzC4Goja0dLoPzJZfPhgxspkLc96/Wa2onC11k" + "mbUzu4v7/6zjzIC1WizIh0OqtrV1uruQifMHVK4DInolV9t1SJcpJXlOW1XhqZLmOWme2+6d" + "I73125naWAG1Pj+kaq2wnyeAGuxQthIi2HWtnQtK4gB7Iza8ED+Q6f9W21hfOeO6K/7veMKg" + "X1QVRcGbTydJkPj13Rnf7fCYgcfH6vU6tKExJoCVHpPzr9N3W8Jr950U9/9gQuADt7+R3XvP" + "N6N1paGw5qZh33scy9jMxIh+lmIDPMpiColSDJOUhy5u83M/suDffOMGgyTi5Xf2uHyg2R2t" + "2Js0VF3C4SxhXStm7YDt0RHbWccffEPw8ceOeSjfsuTJOLZyIk0HonO4lfDMBRtkTNAGDefk" + "jxCPPP7W/3zvP8aCQnbwOc8RoxGMRjAa8Mp7DddvrihG+5ysByzbjHHRcrLMgTVKNKzLRmjd" + "CaPt2pZlKYzW5l5Y//6MbeoAbm9lp6S1IWuahixJEFJSrlaAVURtO+st6NUctNYhQTDGdjTn" + "jhJ0N/f/Wcf7wrD8RWgdkzbxwmZgRfTEZmwmpIKuru5nSZ0D3bp+QHJtVOFap4PhECWtyJnX" + "a/csXOkWUPnUWVjZDN11JHHMwImBrcsygPH9NL4vauado6W0lkVlXVvRPyEC/QGXNs/nc2az" + "mR2vkDIMtfobIHFibp44GCWJZfC6IBgra0vWak3VttQOp/DaX34+zTuSKMfriZLE6iFhQd5i" + "MAhZoQ+sFsdqra55a0tD09rum2g7i2e5r9O2DvPS9v+OVkBVEbUtOZJhNuLHP7nF9lBQlzOG" + "yZKThWGUrjiax7x6bcjtZYySkCeG6VgjoiFXbwl+7yszVqtjtCEAt3TuHJomkERx5aJuGgue" + "u6hkeinWncmWCWmZ/6rLrKIIkeUwHCImW4jplGa8Rb63xRe/fhUVpzQmp9EpnYk4XOR0nWSY" + "1czXkrbt0J2mbVsROsX3yPr7vVa5bMcfscOX2tYSpys3a+mzHOVw3uFwGGg82uFTSZaFDnug" + "INzF/X/W8X6cdVitViwXC44ODxmNRoAV9vPpnNeTilwtqs1GoH7tB46lpOyB58vlkrqqNoC4" + "i7h98T4vHzudTqmbJvx87WeXeqVcYKsDuUvl/eGZy967zT/xjEvfoygijeMQwDxz2NfeWVFY" + "eQwpabqOVVmGdF93HdVqFTI36W6cNM/DojSdlY/t3Gv0zGmtNbP5nMY9gTyW1rVt0PHGYR1C" + "SpbLZSAyhmFw7agBXWuDlcezWidFGz7XoxGEANe6oFUhm5rEdGQy4sL+Lp/74YSTWckoOUbq" + "incPFa+/l6M7p3Ipoe5SyjZhsY547KFt3r4lee2tW7RtY01UhcAYbf9+0+NR1Z5P5ZjtHnfz" + "DSPwTNJTGVXA5DAYYTErkWeI0cgGq90d2N0jPrfLrVbw1WevcbScEMcRRRoKTwZZRdsZlGhp" + "O/tL3bypuCfWvwf2CyGCoornSLVtz1DVlWp9oLvpnMW8g1+UlIG2sV6tQgfPf//d3P9nHe8L" + "w0IIsjSl05qbh4dB+tTzQsCmqbWr1/2TZVWWjIZDK3TvTsaXe34Y2bvHyijacLBS63nWdtas" + "MXFBJVIqqBnWbYtyT0P/Qr2yoT98TZ044FRrHTSno9g6zvoMSykVwHaf7gcbbxfItNa0Tqfa" + "Bw1fdvrF9d0lhG3fex5KCMb+JnMEwt3dXWYnJ0ghSJ1Tr+jX9qJfD20s0AN47TMmlx0EsFoI" + "rByrwqI+7l9jN71RvkITCCURZYVKUnIVszQpn/34Dl9//i1euramizRxC9PxkpaMdZ2ilCSS" + "LS0TfuJTCZKYL35lxf/xuyf8lz8/oDEDe54Ga1Huszt7cq4/4EpCj1WxaQKeArRM783elIg0" + "BhI77J1nsLUF+/vICweMruzyD3/5Gf7yJTg4yEgTA9IwLw1dp4llxWItGKY1sRoZaxgkNpQa" + "FwA+sOvvmk8ed3InsBnr6T2s57MZsWOwG9jwD4VgPB5TtS3lakVVVeRsnHR8Ceex37u1/886" + "zp4l7LqA8/hSzE9gqzjm1uEheZ6TZplNNd1C+lksL0TvxzE8fyVOU/tUq+ugpIhbWONulKjH" + "Cdnb2eHW4aH1gmsam0VpHcA6z6mKHKCZuCec56n4i+EX0xsAAIG5XLoyMomiwEj2N2MwgXRj" + "Dv3ux52tWv93POaGf8L1Oi79mcjCsaPrqrKYhTF2Ot8tqj/6uJ5x+EigNrSd3fzGgDIhCPQx" + "Lf+xPTMHcBrsvKGyTPhIKYZxQpuN+Zkf2eYXfrVia3uGNILtoqQ2ms4oYgWpWvFjPzTmuVcE" + "335pxaIa0QrNl5+6xd/9RErZJQwjY6+X1puSlDuwKHonCKfrQQ9mCSxtIYkRsVMUiBNEmsJw" + "gJ5OYf8cowfP84//1Uv8yv/zBgfndtge1szqgkWZcm5rybrsuHYY8cDONR65VCPiAWkaGcBU" + "Vn3UPgg/6OvvPhekYHygcRwo474vjuOgg+X3Xtd1dEIEt5o0y1CuxNRtG/wZvaPQ3dz/Zx1n" + "0xrURsEgdgCbMsaChXWNdDiSDx5pmhIVRViYxlEMoiiyL8jFjgAAIABJREFUYJxwUsdRZNUZ" + "XV0uhAjkOD+47Dt4jbvJhZRBCN/X0F4uWCqFqGs7QV5VyKqicdlS5FLwrttYFwkhyAcD5vM5" + "eZZtiIDu9/mU/866Ovwt9/o8SOnf/FPOfrPsbUK7CYxrBde1tTUvioI8TQMT2WeJ4Rx67N+Q" + "+kNQs/BdQktrAIPafJ3T3Tf/segvvcBiSlIhojUqjsiEYCBjnnxwix/7+Lt885WbxGnM829O" + "eeBCy954ycVdw9Wbkt//8zWTYczF82MeOIh46ls1X/rLYz76yJxsO6M2ELtztoKCLeg7U39/" + "xv1Pmc1XpLe8l8g0C7LMZCkUA8x4TH5hn2465r/935/llz7/ElcujkBFHK8KlDLsj2ecLBSx" + "rNnN3uETD7zD/s4FUxQDnaWpkVIaYw0/jAfTP6jrL6W0jST3f7DBSff4W31eWesgEQ+DeEWI" + "xo3rGClZOg6Yx87auqZcr4N4wN3a/2cd78v5uW/4OJvPiePYjgy4TMeTzeq6DguTRhHFcBgu" + "aO3qV+lOvn+hgaALLaU8pa/ugbzC6fw0VWWF07QO1kG+c9N2HcpYy+skTUkdaFp5xq7WdK6D" + "UlcVSZJQFIWdl4oiIjfqEEUR2s1j+fkvv9idG5JWLs32T99OW50kZTb8F7Q+ler6JyoudfYY" + "XOeaAHmaWo9FB6hng0HgpvSf3qHscCWCxamcDngonQTgraF8p3BzCDccDQKhDcjK+vdFEZFU" + "ZGnCKBnwM58e8MzLJ+jqhMlgwJVL25zfVXz1eU2UjDg4UDx4QfDSay3ffr1Ba8NTrxR89blD" + "/t1PD1l3MalyBEQDQjuwX5s7XJp75+fKRoTARApEYln8UlpOV2wdaUxRMNjfJtrf4uVbNf/F" + "f/Nl/uhr13jg8h7T7RFHi5y2hTRuqGuBbtZc3Hqexy7cZu/cZXNw4ZLZ29k2o9FIp2lq0Nqo" + "SBGpD/b6Cxew/PkFsmv/6w4u8TOPwgc4F7iUEGilKJuGLI5tRVJVrMvSTntACFZ3c/+fdbwv" + "52fYqCBGruMhpCSNY9YuZVRxjKnrMGulJpNA2gRIkoTMtYY7t+FihxvV3UaHxxinJOpSaOOI" + "dgBZkhBFEbOTk8D70I5tq6KIzOkQ+fLQGEOeZVazxz31lJQuqbAXN3IaPf4JWa5WpE5RoHak" + "uL6kch8v83wY5QNH/6bplQD+d3ujAvzXtGY2m7G1tQXSaitFrpXedJ01zIyi0BH1N5turc69" + "7rrNqI0vCVUvM2HzsT3MHeWhjWImUoimsVmWKlEqIlWSXEU8eGGHn/iBFb/79YqPPbpCMuT3" + "vtIw2Zrwo58c8/Rzt3jltTnXbymOTobsD0sun6/5vb9Y8pFHjonP5eQysWUWJgDwtB3eotls" + "TtgeUtjh7cSJEgrsJo9jyDJMmtFlGVsXdri+avn8b73EL/7zF+i05KOP71EMt/nO2xEHW0uU" + "TCgrwSi6yUfue53zu4rdc4+aSxcvmP39vW57e9pFSmlhjNbGmHK5Mh/09fdNKeErD3c+p77e" + "trTu87ETC9RdF8oyT5SNhKBsmqDllbvmgm43BjB3c/+fdbwveRlvg7WuKvI0pes61k4fp3Aa" + "P57xGjsyWdM01HrjQBtJK1urhB2O9Axfz/6N45jYBay165ogRNC1ns/noUOxM50ym82smJrD" + "Cqr1GtzTLnYdRN/p8KWmF13zIwC115N2qbWKIlIIg6F+zMBjDr6741OCrrMStP539EsDIaz8" + "SX8kCNjIgWC5OEWec3x8zKAoKPLcjml0nR2GdfLOfSa+kHa8QrWtpQNo3QPdNyVhWD8HuNt/" + "IozwPswbHGRTYtYYZYenVRKTRRGRyPncp6dcPTzk+ZdOaFXKdDphOT/huRcW5JHmeD7giQda" + "nn4pomwL9qcLnv7ONv/XF+b8539/yKyZEBlDYox1gWkdoVS7gOrBdyksoI6CWCKSHIQr/9LE" + "8qyKgnR7RDwu+I0/eI5f/LXnePbFYx69MkamO4g458ZRzSitma8TMnnMY7tvcnG6ZH93n53d" + "A3Ph4nmzvbXVjUYjnWeZTuJYqygyxhiTpukHfv0FoLqNuoHnbhntTFP1xo/Qd8bvLF0xdtav" + "cY2QyL3uyrHgPdTiu4B3a/+fdZxtQuFS4yhJiFzrVbvugH9qtA40MxCkYBJXzwN2ENnYQVEP" + "agOcHB+HIOTdSnwKnqSptZn3AGCe2/NxUXswHJJ0XXDcbTyrvW3DoKXuOuqmsd5qvQ6ir6vr" + "tiVydfyqLGmc9LCnTniAX/SCn+4sZiQdR6yPY3hft8BDURv9b7A1vd8EcZIQxTEn7gnbNg03" + "Dw8p8pyBwwA8d8dnnf5n/YaRSmI6RxvQHXQuFAlbDvbDkce0wONbtnsoXOkopLBBpJZQVkg3" + "pjJMU7rJNj/w2JwvPdPw4JWa7UHJYql5+e0xP/KxlNoobh3X7E00N2/nvHO8S5TO+OoLK77x" + "wk0++5GcVYstl5xwn6kbSzZ05xiAf2GDFh5QzzJIM3SeMdjdQhQpz7x6nf/6v/p9/vyZ94jj" + "hE9+7CG0abh1Irh13LA1bDFG8+DOy1yazjnYK9jZfpTdPGV6bt9Mzx20gyzVKoq0EEJnSWLW" + "VWXulfUXgPF4r9sfntvUVz3wEk2+M+lpGL7zV7m95oNd5/5O5MjYlZNyvpv7/8x4dNY3+FZv" + "uVqROiKbFILavUdsHC8KV8+mDtTz9bUPel6KuHUSE7u7u2htB0cTt4Cdxwo6a5Lq6/7w1Os9" + "nXx7N3G8qsVyGYA7f5PlbhA0imOWqxWxUtapRCkGaUpVltaaPE1Di7Z2Ed/fbF6HSCoVps19" + "YMUttncR8cCkEJaFHrkmgpTSmiv42SvXSZlub7N0fm+j8Zi2qlgsFqR5TiRl6FhpCMQ9n2W1" + "db0ZzWl9903aiOQ1DwEhekB86L6b3ueM5ziAqJ1jckSUpuRJSh0P+OSH9/l7b17n6Zeu8fqy" + "4+NPbNNFY64fVhTxguMOlnVKoxWGlofvyyiyA559/ZAHLx5x/2hCgnWJlsYg2g7d2mthZa+t" + "Hj1JYmcBiwGmGNBlGXI0ZLg34Y3rx/xPv/wVPv87z7FqMh64/xIPXhrx0lsN85UijQ1F2rJb" + "3OTRc9fY30nY3brE3nDMbixRszmD/X29vbfbyqYxcRzrpmlMq7XJ09TcK+svIyuf7K22gI1o" + "nguOYbg/3mhygZNxdnvSkz2llEGZFCFCEhC7fXI39//3HLDK5TIMhPoXGVqQrvujtSaJNg6z" + "Ko5ZzedkDiT3AaQPtLV1TWMMSZoyGA6t0aPvZrg6f7VYMByNrMRG01A5EfwkTa3YfpZRRxHz" + "2YxiMGA4HFpNrLYNEsja1coAuQPp67pGaE3rh0CXS6I4DjIdoW53C96/KTtth41DG7nbWEDh" + "rkXn/qaf1JdaB+zs1OFurjDY3XWhBK7Wa9o4JnY3a+LKkRr7xJJxTJSkVJ1GdE52xcFCKJ9d" + "bWgCxvRKPwDU6dk90SsUHZZFkhCnGYPBgHY84bMfO+Zbry25eGDIcoVub/D6dYGWOUeLgrrW" + "JBFc2B/w4Ycirl074Q++CrvD2+x+JidRlk8XUn9tLB9MSkySILJsMws4GiFGQ8Z7W8ybll/6" + "/Ff5lf/7aV58o+KhBy7x+ME269Lw1HfWKKmJpGRveIsru4dc3m3ZmuyzN95iL47Z7loGt2fM" + "rl1DXbyoI2O6tusom0YbMOt7bP39PkmL4hRdp0++9PstWNM73MmrioaGQdNglMJIeWp/+p9r" + "6vqu7v+zjjMDVmD9epDX/eHIXxBHYKvb1ioPio19j9E6RM1TSgvaysLqrrM4kuOC9JUT1ssl" + "aZaxmM9txyJJSJPELlpVBR5LnKbsTKdh4j11YxKep+Wdaz1r3ncTB0URsrbG3YB9kNAAjdYb" + "lchoo+HdeKY9GzUL5X53J8Qpz7qu6+zkuyt/lHtSG1ff+/LXs37jXlANXao4RkAgKyZZZtP4" + "tsEYDbqFTm1OnH425fQQIjCd/X/4OgIROomudDEKIWqrTbWKkak1TU2TlEfu3+FzP1zzh08v" + "uHUMWo5Q8YBZlSHQ/NCTiscfSHjh9ZoX3pBcf+c9Lp/Peerlho8/eky6t0eapqg0RVU1GG3x" + "qTyHokAMB+h8QLQ9Id/bZmHg17/4PP/080/z7ItHpMWEv/PpR1iXLTcOS24caYYFnBve5sH9" + "99jbEuxPh2wPdjiXp0yNYbJcUMzmiKMjjt+5SvPgg7pcrbo8SYRRytyT6+/A679pg/erkTAu" + "AwHE9ziXp0Y0rtRryjIQqft77W7t/7OOMwNW7PCfTmuradQDGFvfdXCBQUURdVkG2dTgoeYA" + "TL+QQYJCWL5LnCR2yHowsJ0H5+PWVFUwkdSdNY5IsBiUnzxfLRasjGFra4tOWinYrCjshdbW" + "yqsPhBpjiNzF8gvru4pl09inojs3f2N5DWqv5tA41rzHFnDnpFx67Al5xhha1yLG38i+JvNP" + "uNa64uo4tpmfu0F9MPWKqEtHwIuUIs0ykiSxT/9OWxyr7Xrguqvw2g3nytAFBYcwaGzsx2Kz" + "v9znassqkBKR2PS9iBRFOuRjDw/40tevs6gFrRpSdS0X9xd86mMDplsRoOjaOccLwZMf2ue9" + "6+/w1AsD/vWfl1z42RKpMsvT8dlLliFGQ8xwSJ0P2L6wQ6UU/9/XXue//+Wv89Zb7xBlUy5f" + "eZgr5zNu3Drm6u2UpjZc3FnxwO51ruyX7GxtMR1OmKYZu6ZjvFwyXCxIj49Rx7dpjm7TvHed" + "bjYzbv2N6IHR99L6Z0VhG0lJEigQAfvzQcG9Lo+99buUAXh3wcO4ElX5TNc93P3evJv7/6zj" + "7AyrTwdw3QOfLnZdR+pUDzOXLnpzxbKy7rbebcMLkOE7Ff5FKmWVDYuCqiypwArvuVrfj9QY" + "LAgZJUmYTO9c2RcpxeHt20zGY/I0ZenmoYQQpMnG1t3fYMqdn/96FMc0dW0VFV1bVxongxtF" + "YcC6a1viLAs4WdO2bq5OBjVKrTWtKwGC0au7kftjP31eTeOeXN4Kqu8AVLqU2muMe+qFlSFh" + "0yXUncXZ+8EnwhLae1kX9AiloV+4eY8A2YIRNZQSsVwiXGlSJClXLm7zqY/O+dXfa0nyJZ/4" + "voS6WfPm9TFVNePFNzWXzsX8nU/kvPmO4aQ+4LGHl7w7O+HpV475zON7LMkYju0JqWGBGU9I" + "d7bIhgV//M3X+T9/5zv86y9+mzgZ88DDj7sbX/Hym8ecrFOKpOT77r/Bo+dPmG6NmE7uZ68o" + "2AEmVcngZE52ckx0coy6fQzzOfXshOb4mLixw8alGxi+V9e/jSKLc8Vx0GKHDTUgdCeN2Yxx" + "sWkA4M9DbqRmJBtqUddYpQZ5l/f/WceZActf9DAU6qfAXYnWOdq956p40LE/Y+UxKd9+FWBd" + "PVzbNHbT7dIBlJ7CECkVOFLr1Qqh1Ebky/0+31FZr9fcPj5ma2uLLMtYLZfEWUZbVfbGEiKY" + "UeSDgcUsksTiV+4pUbdtYOPK3gJFSWJr9a4L+tNCCNuihyDNDBuCHBBYykrY2a1OiNPll/ue" + "ptcZrbF0C+maDf4m9efnX4d9YrpRF925krAnL+MahcZzMFu4E9MK5aJwbPjWfca/GFFjVmuE" + "siXRYCSpVcqP/8A2f/7sNaIsI0slaQLPv7omftjwuc9MuXar4yvP1CgZ8fhDBbKreOYF+PU/" + "FFzen/HA7jbDrW3SNMWkBdFkwHNvHPK//cs/5rf+8CoRFQ9eucTe/jnevVkSseLt64JVU/Dh" + "S1d5eP+Ig92ErfEl9odjduOIadsyWC3Jjo+JDw9Rx8cwm8F8jlmXUK4xTYPuWtutMoZsOLwn" + "19//fKc1qStV26bZYGR+zzngHTYzhJtvcbm3e+3GmNAlxGzkju/2/j/rOJsL37u4teNNdFqT" + "iI1NUOzFxByDt6kqy8foOpIkCWmwj/j+ovoUe7lYhMgbOwmMwPlQisgFqthNmEspretKZ3V3" + "PBkvjawCZJymjEYjDo+OrBpjbHW5E2k5WNV6Td22rMuSPMtAiCDyD7bFKt35rlYriqKwAc7Z" + "G+HATCklVdMgmo3qYuxmplRsFU+bsrRP2Ciy/CM4NfsVuQ6UX0ipVJgn8+fi2+O4j4W7ySpH" + "iA1qDOBZVxtlg8hACyYCuh4vK7AjVKCTCmV1qTzKZWoQotww4FXEoMiZDob8/c+N+eI3a159" + "/RZb2xM++5GG1mT80VM1b17r+MiHcsYDQSI0f/aNmNF4C91V/JPfvs3PfOaEhy5FRBLm5ZLf" + "/tJT/OlT15Fmxfm9Ibt7DwOaN9++zqwcYEzGfdMjnrjwHnvThO2tA6aDLc5lMVNjGFUl+XxO" + "fHyCun2EuH0bZnPEaoWprDGrx3DAGpOWVUWl9T25/p59vpzPkePxKRD8zn3bJ74KtTF58ZlV" + "3WwUfX1W2LatLd965eXd2v9nHe9r+NmT1aS7wP6Pe3ut1XrNYDAgUoqybW3k1Rvd9P5IgOd8" + "eAa71laa1WsDCSFCZ8EvrhKWkZ74FNNhC/1WrlcfBWwHQikmkwknsxmpS5u92J8xhixJTn0/" + "YFU86/pU+qykZOV0j7YmE/s7jKF055p5wf62tWNB7kb0AbV1Tyx/LQEibRUXwCoxZklC4/A2" + "IdykvmuBx66D1LnfU7dtGJVI4pja2C6h0V0vVG06gnaXdojQOOxRyj2Tgf69LjDCBz9h5wyV" + "FchTaUIaKYZpwmOXx3z5mevU64YHntxGCvjmizXFIOHn//1dvvLMkm+/VvPeTc3f+8yUG4cr" + "3nrrFjfnUz7/RxWz2dvsjGrKqub4pCTJd9kedWwP4aW31whTUrYDtvITnrj4Hg8ctAxG59jb" + "2mY3S5kimNQ1g7IkWcxRt2+jjk8wsxOYz6FcQ9vacSBs8DZm0/7PosiqlN6D69950qZzTvbB" + "MkxCuI5j13VWrM8PNncdVdMQax2cpGVvP3ssSghr7JqkKYvZ7K7u/7OOMwNWmudBtrhuW5S7" + "sFme09Q1ZV3baOoGIJMso1qv7XwftjWcio3xo++6eECQ1qp8+tTRk0Q9e9YYQ7lckua5JaTl" + "OWkUsVwuw3yTn3L3voV1WYK7iFtbWyxmM/v0aK2vnJQyyHjUjhsSRRGr5dJ2Il36XDuMIs8y" + "ajcM6s/b1/r+iKMotHxDd0aI4NlW1/UpX0RPVl0sFiR5TrVahZ+TSpFnGYvaWlcFfXtheT6R" + "u1Zd27qZsm7TJRQ+ixJ/RRsdTCQQ3UYqOcgPCxu9/M/0J2WoG1iXiNRapmcqYrso+JEPD6ia" + "klffOObtQ81HHp/yfY8ofv33jjiaC4pM8HM/sc+168dcvVby0EPnefOdJSdHN/noE7u8816N" + "Mku2pttsjRXXbrTcODwmjgXrSvHh86/y4PmS/b1tJuNzHIwKplIyrmuK5ZJsuSBerpDLJWI2" + "w8xmiNXaGm147MburtA1VUrae9rZrd+L6x/3Am2nrZlp67K8JMsCTcLAqQd853hhwnXyuq6z" + "Wu8u0wmZn7S8Kt22d33/n3WcXRL26tEsscaSRZ6zXi5RSjFwL6hx0Rwh7BPJGIqiCM7LnngX" + "uXnA1g2Rap/munTSc0k8ftA1DflwaPkmrjw8Oj5murXFcrkEaVVIA33BAXhNVbF0gW4ymdjp" + "cpfK13VN2uOIpI61W7ha2ge/1NXmQHjvVVA7x3j27Vvf0bkT1PTzZk3bkrjSwj9pPZGuWyzC" + "oCrCKqFWTROegsp1lwQbCWncExRtu4SBe2WZCe7DO7KtwMVSoTyy3+sE9FQfne+l57XY0Bzi" + "hDSKieOUT3xowjOvVDz9zTX/zqemRKnmT772HoNsxI//8DnyeMWrb97mK89pPv2RC9w6XvPa" + "1YZL+1OSpAGpGY8LBpnitTcPOZwpJqlhb3CDJz90yM50zM72BfaGE/ZixbhrGc7npPMF0WJO" + "tFgg1mtMaQUB6eku0Q/Xmy6DLYOcbbyXjLnX1t8ri/hRmL7PQbVeBy6UPxfP7/J0Cd/di+ON" + "c3RfV95nRJ7Jfzf3/1nH2aM5ccwwiljM55YNawzr9To8OTxYJpViPpuROoBSRZHt1glBEkWB" + "NetdPeD0sGMguPU6KEFudrUKC1K3LTvb2yxXK6I0JZKSk9nMpqtJYv3jPG8GS3zDDV4ClK7F" + "6stPf5F16yy/HA8GJ1Xjb4wgY9ubK4vdXFXQRfJApwu4UWxVTOuyDM4qWmvbWXFC/4vFwmJ0" + "TYMSFg33zsFeAsS30HHgrbcji6OIWmuE7jAuw+p50Hx3hqU2JaAxnKYz0DlKg3CAvUXhjREI" + "02JkZeWI4wQZxwwjRS0LfvT7c24sNMv5bb75TMv+uW0un5McH99mhubG7RaIWawMlw4yFqsx" + "tw+Pqao1Fw5GvPPujLKsmC9rHtm9zn07t7lvP2Jrcpm9yYTdNGXatYzmK7L5nGh2YgPVYgll" + "aQ1Y2w5jNMJoN5a0ef2hM2pZHBsCZF0jouieXH9PZvX7KVAUXDDrj+gIIajrmspNeZwqMdl0" + "/0T/vSsBzd/G/j/jeF/Dz13XMRqPA5mzruvwNGi1psgy5vM5k8mExXzOcDRi4cYNlBBWcN8F" + "CB+QtNZ0jnOCMYEI6kcWPLHO4wtRmloxe605OTkJ7Nv1asXW1hZaa27dusWwKOwTj40Vfde2" + "xG5mKQSuug5+aa2Tlenc06PTOmBcret8JEkSPOQ6rYndAjdS0ti75VSZ4GVmkygiGQ7tzW4M" + "VVWxXi6DHXrmgqx/D7arVK7XFIOBtVPqrAVS07Z0wg7VCixugnYifmoD3G5oCr11/K4P7BF+" + "phflLOCMnTcUAiMM1ICqEPEKmcREacJgUHD/uTGFeo8X31L82A9uc1xFvPDKMZcPJHmW0nVw" + "sJtT5JJbtyuOj1eMxzlxqnj97QU3b83Zzd7hh6+8xaX9mPFkn93xNvtpyrYxjBZzivmcZDZD" + "nZwgFkvEemVdoTunotAv/zCnAxXYrqqLw0pFthxzD7Z7cf29KmjVNEFs0ttwJc78ws8Y+mwK" + "s/FT7LTVcc+z7LswppAsuDd5l/f/Wcf7YrpHURRam+DccN0Fil3nYZDnVOs1QzcPVRSF5a8Y" + "69DbF6fvKzXinhw+hQ0loYvanplbuhQ0imPKqiIWgtnxMcPRiHK9ZlAU7O7u0mlNuVpZh163" + "aDKKWK3XFG6AGjbpbaQUpkeuA6sB75VLO1d69blgRlhmcNu2YQjUQLC4B0KZcOPwMNzwUm18" + "3Jq2hcjKPo/HY05OTkIwXa7XjNyYUeTmrqIoQrq5R+Vek/TX0ji1hh7hqp9p9aB1+7/oNChv" + "OtddjMwG3+KOFMxgAfiyhDRF1TVpnjNMC77/sYyjKuL27RlPv6r5/g/vU67X3Lq2ZjDZ4Yce" + "y3nxlWMOb93k3KRiPB7w9Hdq7t96m8sXXmQ6bNnf2WNnPGUvT5kazXgxp5gvSGYzopMTxNzi" + "U6IqrdyyNo6IuXl1m1M1pz4S4ZpsjjTLMELck+sf+QDj9mfgYLlg0C9LfQLgYZPOdfp80AtU" + "B2NOUyB6VIa7uf/POt4XDytLEpZucrtcreykeY8Ri7twfiDZp69KqdDi9JHUXxgVx6FsC3pD" + "PgK7C+g5IQirDooQLFzauVqtyNKUcrWyNtoBu7DdnNV6fUrUXkgrZyEdcAk2Q1ksFrZV6/gg" + "vvNRl2XQefcL6gdc+1ydum2DxI3uXXDdWXfqIk2tjrUnDgpBXhSUVRXa39oY0jg+9dQNrjjG" + "hKe5yHNws5Kmdf512rWftd7UevjykJAxWW6DAaEsmdSvvNgEL/vjjsDlvii8lLIytuxsO0Tb" + "ITqNAoZFyqWDEe/+/hHDIuVznxljpODFWcql+0a89EbN4eFVlquWv/vxjC8/k1AuXuFDW6+z" + "m73D7nSHva0d9vOCXQzj5ZJisSCdzYhOZsj5DLFcWC5V09hskk2gsqnTJhoFKzNX3vpMwUc0" + "bTY4yb26/l522ZjNYHZoQDkVUG+26s1efcCpmoY0ju28nysT+3skaMK7/ec7oXdt/59xnE1r" + "aFuWrruWRhGtGxJdzGZBHXSxWFiziCShyDJuLBbkECRh2ralriowhtQZPfq0NUrTTfvTpdG4" + "KOy7ekFCo2kYjkb2RshzKjfCM3fUhfF4bOcRtVNwkNKmr3UdjFm1tIxkL+rnp/LbO9jCbdva" + "lNt3MxzO0QjbNo7S1FqCu8DR+bZs76I3XYd0dAr/BNWAKEtyLzbozrWGQNYzxgSjzJULUHGa" + "ntJnAmcQYtzN62SHrVOvDnZIBhfD3Eb2wcq0IBwTftNNs5vcl4T2Ux74ctiGGwkRaYrKMtIi" + "o24laSLY2hry/CsLHrws+fijKbdnNZG+yZULkrZTPPfiMY8Mv8kkuspkoNjdeoCDPGNXSbbL" + "NYPFgvRkRjzzgWqJWK2grp3N/abbZzub9BoJftf513say/LJosdvVosFIoruyfX3ILgfTzuV" + "UfmyzmUv3u7OBzCtNauyJNM6NBX6A9x9+SKjrQHs3dz/Zx3vS16ma6yvWeeeCMHYoW1ZLpcU" + "ec5qvSYfDDg5OWE4GLAuS0RZbqKttCx2P+Lg26it65T0sasAdLoL6tPF4HYMpybq09gK7S8W" + "CwaDQXCzTZUiT1PW2JnDNMsQQlC5Vq92iyKkJMtz+1SVTvlRKdA6zC8G77Qosq7GLq33Drta" + "u5kzB+qKOCZ2C+7b254tLYSgKsvgZtJpTZrnrBYLjLRtd2/BlKcpjRuMTbLMAsbuqe7uKpt1" + "SINx7B6LSTn0RjhMy7PeERvdrM6WiZYF7z7uWhsIXKmIB2HjGLIcMRoitiawvYUZDGmV4OkX" + "F0Rxyp987QaPPDAmT4Z85akjVuuax64ojo5r6uNvsRs9x8Vtyc5kj/1izJ4wbFcVo3JNPl8Q" + "z05QszliPof1ylrdeyZ/qO3EpuQLAvW+iPUlhn9q/HETAAAgAElEQVQ97tt634Fbf6WsQsG9" + "uP6mV77BxjH6Tg5XAN+jyHYkgSLPKcuSsq4ZDofguoC1C7yRcjZ4UoYmxd3c/99zwPJ8CeP4" + "F0Agp3XaynoslktbwzqW+Xw+D26zUkpwnQ6f9SjX1sRdENhYcnnKvq/N++3OznVnjLHOHcJh" + "C15GJlLK8rNiqxtdNg2pW3RvBlmXJdoY8qKwN5prT+uus1SHsqQYDlnN58FaDAiMZ9+FqV3K" + "XnfWxFUphXQgZrlehye37GEKUkpSl/X5VvpisWA8mZDFMZ1z+qndnFtfoE0qFUh32m0Euz7a" + "Ba2esYMAo52VlraBywLxrmwUTs9ddJt93XW9ja4tbC8lQthgJYocRkPE1jZMd2jHE7YvTPjN" + "L77Er/3OOzx0eUwcbdN0EX/5rWso0VHWBcc3XiMqX+DxvRnT7QP2xlvsK8m0qRnPF+SzGcls" + "jlrMkfM5YrmEsoKmsU47/nX2Y9MdHYV+yWevyZ03MS5rsJ59dV2TxnFQDLjn1t/d9z4ba5zs" + "Ur+7/td14BrHB0udhpyQ0noguPPUWoeA7YPj3dz/Zx3vO8PyEi3+aVSu16H2D+qD2jramMGA" + "uqpo6toqh7rg4uty5S5Gn7fST2v7Eq/9ye7+4RcR2KS7btN6c0aplJ2il5LYSdXkWYZuGtar" + "Vci40jynXK3CPd+UJZkLaP4JAlC5etyXZb4u9zNYPqVO3Ll5YqoPkh73iNzTpC5LxpMJbVWx" + "cuWELweAwAkCm1FKx6eJkoTWMam1dgxloTdlH7hSyYSa0KI5/ia2AL3HCgP/CoNQxr23CqCk" + "KWIwQIzHyJ0d2t0dsnO7DM9N+F//5fP8wj/6Gp/5xC5H85huVfPK67e5/9KI3eGSovpzzseH" + "nL80YWfyGOeymB3dMZkvKU6OSRw7Xc4XsFqiy/WGS7WpScEzXO9se5q/4r37WsgmXT7WaY1m" + "w0RfrdfBJOFeXH/jzFhSd25+f/gSL0g5O8A7ctmkf9j1wXr/8/7NuK83VXXK1fpu7f+/6Tgb" + "dHcL4/kmopfCtm1LtVjQOmDes4VVHFMMh9RlaXEmV+93nZWI6YyxhqbGBBfmOwE3IeyG8eVh" + "f0Ewp+UxkHJjne0unmfeek5LnqYwHHL79m3Go1GYigf71ImSZMNhiTZSsoPBwNbeTourqioi" + "Y1vYbV1bImBr7ZWU78Y4ENaDov3XtK4qlJQM05TM3QyeZ9NnAgtXGqyd0mPArtyQq9MqEjer" + "mlQIchW5tFqAkKGU8zrp9v/Kfqxc+S2V+1jZ8Rul7AhOntuNJQRRmhAPhyTTKWJ7yvTSAbrI" + "+If/9Mv8o3/+TfLhAW9eE1bSKq340HlJs3iOdP4dHryUszM5YJoWbDdripMj4tmc6vZt6pNj" + "zMkMs1hgytJa2HedxeTuvHfv5Gi8j8Pc8XFlNDeahtHhkfhQHGPu4fUP2vJsHtw+6/F7w89O" + "+jJVKjuDKqRE+kTAUwzcvsRsAjrGAgzR39L+/+uO9+Wak7qyzBMuu7alGAysHEaakuY5TdOE" + "sku69DFKEqrl0j41lCLJMpRnvjqgUvQvqM+merXsX5mB9boR3jfOd0n8DeKfFNrNXZWNtf3e" + "39vj1uFheCp4NnLszFY907f1ZWaSEMcxq8ZqxCeuk7T23Q+zUWcUDtDHbDgvxWBgMQPHBu6z" + "k417+uWDAevlMshrxK67IoQgd2NKXmYkdx2erm2ZPv54V//H/1EppKKTEi1ASgfKCpuVGETY" + "hL4LG94QiMiObWis/buKYqIsJSqGQo4GQk4mMpruiGg4ENP9LfHauyfiF/67/5cvf/0qly9N" + "qXXCu7cMF/Yatgc1o+477OwcMd25xN50x0yHAzNJUlMoqaO6NmaxMO18brqypKsqaFqED1Ji" + "s7E3a+3vZfsNvoPlqQRSKvCZpLCjNyDQ2g5y665DqQiFYbpei0s/+qPtYrkkc1n5vbj+PsMO" + "MuGumgikTxeEvmvv9LIof3E95BI52obPAn3Q+9vY/3/TIYDf/Zu+4Z3XXvvhruuCdXYfzc+K" + "guV8TuwGQj2d32NFYaP0bkIviOaF9byWdHhSSHnqht3cuH3QYqPn7hfA6/SUbng1iePQxWib" + "hiRNQ0pa5Dnv3bxJkWWBEewJqp6Nm+a5rbPduQhhp9OXs1mYCVut14HPJYQIk/T+fPubQQg7" + "1N06Xo9SitwNr8aOpuFvmGIwCDdh6xjX/tr51Fu6MteTaT1oqeLYGmq6my12jGR/3fy5eQyi" + "z4kJ1zKOpVJKRkmikixTSRSpKI7Fb/z2X4hf/CdfEFffq9k/uIxw3daqG/DE+Ws8cO6Y/Z0R" + "u3uXzLn9Hb2zu6snW9vdcDzSeVHoWGvdta1p69r8ba5/mqbhoXWvrr9S6hSZ+t/m+gNB1ytz" + "mefd2v8Xrlz5i+9a/N5xNtNdWvF8fwFD17DrKFcrJpNJ+N7OWDNFo+2QMu7i+sgbudRWOD4U" + "rgb2h3QL4Vur4UW6p2r4nBDfBdBJpQInxT/d/EUBgqGkH985t7fHcrXazC26tDrY3rsJ9/Vq" + "xc50Clh2vL9ZddeROKa0Ngbl/oaXuzGubAhPK3djZM66yUvPJk5ZNXLnX9Z14Mf4823rOgij" + "RXG8aTaUpTWg0BojZfCqCxtZa1tquWvouzFA+LnOWAVWAUJIKZRSMlFKyiRRBlSeSnX92v/f" + "3pcHV3Hd6X693FVX+4YALWgDIVYBYsesZjO7sQ2243gZ25PEdubVJM9TU5l6NZVUZqYmmZfn" + "LJPEsZMJGGICAWOD2cUiFoEkhASShSS0S2hf73673x/dfdR9tdzWgpCgvypV6d7bffrsfc7v" + "9zvf10z9759+iZy8e3ByZiyYk4i7pR1wuRmkxliRPLEeIUEGBAXF8eHhUXxoSCAXEhzssfhZ" + "OL1ex1FuN+/u6OAhBiDyHg/Fc4LGl1PGzCFn66S82t/bNCDFnkkeQIlEj+V5eABwLhecPA+P" + "xMjpEbX4TCa4PZ4nov0lQRISmCmfgMTJg0CqQ6luOY54kxmvl4Q0OUuSEKM5/n1BFR+WTnSt" + "StzSbp4nVBwPGxvhb7HAIMq9mwwGQW3ZaiWnxj0eD4kF0TOMsCQW99hdnZ3E3sDxPHi3SNPB" + "iPYWsbLllU4qlhbOWknfMzodDGKHcDkcRJJIxzDo6OhASEgIWJpGZ2cnbN3dCAoKQrfVKhxQ" + "ldkJdAYDuru7YRJliax2uxBxzDCwcRwgumXddjsRLpCil3kI21NpQpA6iOTdlBwDjOj+Bs/D" + "KosBMsuMqE6nIAdO3OK0IH3uFtPQ6/XgpS0wLbBRgGEAj0fgr5I9T9quSNsGmuPAiG9MiqJE" + "tgYePE2DMRhommUZP4uJOfJlNvWjfz8MN6fDpKjJcLk9yL7bgElhPFKinYif6ILJL4yPiJjA" + "h4eG8qGhIZzZaPTojUbOoNdzNEXxvMfD0zTN64xGXs+yAiVwH+0PCMdoKFqwp0ntT/HyqH0B" + "tPi91P4e0SBtCggg7e92OuGmhEDhTrv9iWt/yZBO+K24HvIAoiso266SVZT0P91zppYX65Cw" + "N0iTk1gfozX+fUHVCkuaMaWlps5gIG8HkilOkNhmxGWp2WSCXewIjLTSESubA8iKSfJySMFj" + "0lEIqVNKjSfc0kOeL30nr1jO7SarM4ZlYRaNmICgmONyOsFJB6PdbtQ3NCAsNBScXo/Ojg74" + "BwQQg6dRPCnPSm8UlwtmPz/4WSwkfybxjJjU2Xiv/AJQCmCI19EsC3g8gkwTwwjxMBQFW3c3" + "2UZQfbz5pHv1ACmv1EbyOvLIJikAimBA8SKSH8n2h576pHiKokwmPfX1+Xzqze//BmHBBvgH" + "xaKmkQdLO5CWBKTGehAabISfZRI/ITKcCw0N4fwtFi4wIJBjdSxnNhh4t8fD0TTNeziOh/hG" + "92jtPzbbHyCrQcmOR9M0uFEe/76g2ksoxUQZWIEXR35YkTUYwHEcdHq9oBACgVWBoijxwClD" + "jKRSRLC0IpIq1uNyCZLa4hEAl+i2ZcU3rVSp0ol4qXGcbjeMotHO7RLYH1kx3kPyuHR2dSEw" + "MJB0XolC2aDTCVHyRiMCAgOFYwoUBXt3N2lAAOTtyYlbKj0rsCnyEGWQxPgbMyvwAnVbrQKT" + "JN+jByd1HJplhXNcPE8MmHq9Hk4ploYWWB/1siBZ6W3r4QQ5JaPZDEYMBpRiZaT2kTqbtITn" + "5V4fTw8tieSCd4kBicTtzjDgOB4OhxMTwsy8yaij2rpoOLgWxE/2w4LpOkSF0jBbwvjg4FAu" + "PCyEDwkO8fhbLJzRaOB1ej1HAzzH8zxF0zxF0zxLUUKQptb+Y7b9SewWRSkmwtEe/77gOw6L" + "ZYl4o46m4eI4EsAJ9JyZkmZK6fS3NMtL/ONkW4c+JH8gBoV6PMJxBsk4Ktvfg6LAezwkeI0V" + "bQl6ADa7HUa9nnh6OI8QzCedT/K3WAQSMvFNzJhMcLpcxAPjFJkbJMoNvckEu/i2AwTaGqPZ" + "LNgoGAZWu52IW5iMRjg9Ahm/5OUx6vVwOJ3Qi+e19Dqd8FbihIPZjNhZpDSlYDrJ7sGKHj3p" + "qJJTzDsjXtfd2Qm9wUBCOCiaJgyW8npWgOqJW5Mbks0Wi0CAqNPxbrebcjgcvMFo5KzdNi56" + "YgD1g79fTZ3OyENKUiQSJ/E8eJa3BATx4eFhfEhQMGex+HFGo5HzM5s5lmF4HuBpmubF9uUl" + "vnCt/cd8+wvbaLcbenEFJQm2jub49wVVgaNOux16sdO47HYSWk8KBcGrYDIY4OCFGCiDwSAc" + "gRD3vVKMCABiKJQHrklMDDqGgdvjIft0ctZJms1F4yjP84QJkRUriDQ8x8HpEuSDJKOudDqd" + "1ethd7nAQwgeNBmN0LMsidJlWRZutxsmPz84xahnGj1vBo4TzjjyeoGrmgNgEDu7XozVcbsE" + "mXOPOHCkRpK2GJLtwCa+haTfJIpcAIRtlRdjfYgcks0mHM4VjcJSKIckGMDL6ljoET0ubYh2" + "KuItgmAoljxYBpOJ97jdPOfxcCzLejo6rFj3zHRMTwyF3doGq53jLX5mLjAggA8KCuTMJhNn" + "MBo5HcvyDE3zRr2ed7jdcLtcvNb+46/99SYTeVlYLBZYbTZBYXoUx78v+J6wxAoBJfDieMSl" + "seQ2Nfr5wWmzCVqA4hKXoihCTCbJH3loWiE9JNknpOWry+UCbDbCP8SIRjppWSwVTrIxeFwu" + "QWFXdCcT6gy251wVw7Iwi8cdurq6oBMPSgcEBMAsuq0pcQnM6gTFXYnKleM46AwGwhVvFxtP" + "2ma4XC7oxMEBhhGknagetRUSjSxGMCsMnuLAkuwVkquY43vOiEmePuKe1uuJaIbLKdDSSkGF" + "UicgnkCGIZ1I+l4O0qnF+nS6XNALy3EeFMXTNM15hPAA3qgzcmGhwZTD4ge9XsczNM0Z9XrO" + "bDbzFEXxJoOBd7lcPGsw8E7RrqK1//hsf0pMh2FZ2BwOOBwO+InHjkZr/PuCKnoZKThT6jxy" + "Inqe4+Dv7w+H2w0Dy0LPssKSWVJelvbM8sqSz7S0QPIldUopcA0AKby0/HS7XISCQ+qMAAin" + "O0XTsIvLZ73RKBwYFbng/fz80NbeLhgDrVYEBASgU6xgjuNAcaJYpOQWpoRIe7v4JpMqF+g5" + "wAqKAkvTsIlBflYx9oTV64VtickExuWCy+kkCsCsOBAlSGWlWRasuKqQKHAhDkaKomCz24Wz" + "bOLy22m3E3klyuMROoC8Y8qW/QpIb1lZeaQBKg4SzuPxwOlweCiOQ3BQIIICA0i5pcFF0TTh" + "4g6wWIT21+kAnU5r//Hd/kKslBjPNtrj3xd8hpZKvOc8L7iQyaFb0T7gtNuFpSNFwSG+Hcxi" + "ZyGRseKeVR55K++IOpaFn9kMo8kEg9FIgs0km4HcHSwVXBo88kA2TurMMld/t8gv7RR/AwTP" + "jU1crkqxSXbpyIuYZ3I8Q7yH0engtAkiDPLB4hI7l8vhELYNHg85FsSJ9gCdXhA20DEMyZvL" + "6YTNbodDYpIUtyk8L0YA0zKCNp6HSeQiomiaHDeSB+N5B1ZKniCJa0hubKXESYGmaSGoUq8n" + "b3YpCpsRAy+19tfafzTb3xd8TlgeWWGlBpceLH1mxH0/LZvNzX5+QoXyPMkw0BNRCwjbTVZc" + "CrtkdguaFs5RWQICSFiFNPtLDe52u+EU9/ms+IbweHok7KWK1ukFySGaEqhaadHGQDOMEOlM" + "03A4nTCKbz0pwM1ltwuzv1fHISyoEOJGnOLbVWKCZBhG8JDQgiKLrbsbnMcDncEg8HSLS2AA" + "0LOscHBWrCNp5cDQtMBQSQsacJJdhKJp2EQWSqkTyjmEpPNh5E+sb8mASzMMaSNpC2USPTNG" + "kZ/JKW6TrN3dxKujtb/W/qPZ/gPBtwiFuCSVaFKdoidEcoFK8RMULYiU8jwvRABLBRMzLe2n" + "pX056RysQAND3qCULIhNNOoBAC2+Zd0eD/Gs6MVzdRI7pE50D0v5dtrtxEWuN5kIEylFieRh" + "DENc5/LO7hDpQXieF9RBxA5i8feHQ1wqdzkcJDhPSkvi4dKJ7mLpVLpLPLEvvVVohoHD5RI8" + "YmLDeTiuZzByHHQ8D4fLJfB7iXXOsoI6MDlGInZCed1JHYGiKHCUcG5NOvIhiWBKB1l5CF4c" + "hqLQbbXC7nAIAZlUjzyVlK7W/lr7j0b7+4LPCSt9+fKA6MmThQcA5G3Ta28sK5yUGYiZo6R7" + "pXtkBYE8He89uFQw8bny7+SQ54cE7/WdOeWz+knP+/nSZwo90bje6RNDJtUjR44+viN7efTU" + "pTx9yH5HP+Xi0Uf5+mkPkg/pjStLW8q3tzyV9L23p0lrf639H2X7h4hHoAaCKl3C7Tt2qOHW" + "0qBBg4Yh4+yZMz6t7j4nIu+ZV4MGDRoeBdTMNT4nrP6Wfho0aNAwkhiRCUtbX2nQoGE0oGZx" + "5HuFNSJZ0aBBg4aBoWZxpBnTNWjQMCagZkuoisBvpNDS1ASHeEbJ6XBAp9NhSmKiqnvramrQ" + "3taGxORkVYckH1eaGgaH5sZGOJ1O0icYlkVCUtLjztZThbEyDtTs5oY8YTU3NiroTX2BYRhk" + "XryIe/n55AT9pOhovKliwrp75w4Of/YZACB2yhS89s47Q8v0I05Tw+Bx4fRpfFNYSI6GREZF" + "IeGDDx5zrp4ejLdx4FtItZ/v9/3hD2hva4PZzw+ToqMBAPeLisjvSdOmAQBqqqpg7e5GYFAQ" + "PvjwQ0yOicGXR44MKpPlZWXk/8ryckLiPxw8ijQ1DB7Pv/wycm/exPHDhx93Vp5KjKVxoMbo" + "7psieYDf/AMC8HfvvQeLvz9ampoUE9b6555DSFgYujo78dtf/IJ8HyAjrVeLBYsXo6SoCJ0d" + "HVixZs2IVOijSHMkcL+oCAf/9CcAQEJyMva+/voT9by+EKwiwlnDo8FYGgcjY8MaYNZ7dvNm" + "WPz9B7zd4u+PZzdvxvlTp3w+qj9EREbigw8/HNHZ/1GkORKQDtkC6ug2xtvzNIwtjNVx0B+G" + "bMOaM38+ps+cqera1Nmz0dzU1O/vHe3tKLt/H06HA1GTJyM6Npb8ZrfZYLVa4RSN9S6XC4nJ" + "yYr73S4XHpSWoqW5GQzDICwiAv4BAeju6kJMXFyv5z2KNOWora5GfW0t7DYb9AYDwiMjERMX" + "53PJ21Bfj/a2NvLZ6XSiob4eABAYHAyDeCDVYbejrKQE7a2tYFgWERMm9Jm+rzKofZ4Eh90O" + "a3c3cZy4XS4kJCeju6sLpcXFMBiNSE5JUeRDbV4HwmDSGEzdq23jwZbB4XCgubGx1/cBgYGw" + "+PujuamJ0CkDgt1Omix8PWuwbTBQGSMiI32OA0DoFxVlZWhtbgYPIDAoCHEJCTDKONj7y5fd" + "ZkNJcTG6OzsREh6OxKSk/gVTR2JL2N/h0GfWrvV5qwSaprFy3bo+f8u6ehWnv/pKcVp7+erV" + "WPXsswCA7KwsZGZkwC6yEVIUhR/99Kfk2qqKChzatw82qxUr1qyBn8WCC6dPo7qiAulLlvQ5" + "uTyKNAFhwjly8CAa6uuxZuNGBAUH4+svvkB3VxeiY2PxyptvQieSofWFw599BodMp6++tpYY" + "RDds3YopiYm4df06zp48iaDgYKxYswbZ16/j5LFjiIyKwouvvoogcXulpgxqnifHvfx8nPv6" + "a1hFkQaGYbBzzx4c+/xzwpKwct06rFizBgBU53UgqE1jsHWvto2HUgZbdzdOffklqsrLyXeT" + "Y2KwdtMmWPz9UVFWhkvnz6ND9MztevllMAyj6lmDaQNfZayqqBhwHEjlP3/qFDiOw9qNG8Ew" + "DI4fPgy3y4Vlq1Zh2apVoCiqz3y9+NprOHLgAEkfAJJTUvDit77V92SvYkvIAHhloAsC/P0T" + "Fi5c6HPqs1mtyLp6lXxOX7IEJrO513Utzc3Iv30bAIRZfsIE7HjxRUycPBlFBQUAhM60YNEi" + "6PR6xMTFIXHaNGRfFwRhKYoikyXPcfjkN79BV2cn4pOS8NzOnYiaNAmz09JQV1MDmmEwdfr0" + "Xnl4FGkCwKH9+1FbXQ0AWLR8OaalpqK7qwvVFRXoaG+HxWLBpJiYfutwweLFCAgKwr38fACC" + "1+bN730PCxYvRnBICG7fuoUvjxyBx+PBzpdeQnJKCsIjI5GTlSU8p7ISaenpqsvg63neiJo0" + "CfFJSci+cUOoK56H0WhE0rRpKC8tFb4DMGfePNV5BYC21lbk5eQAEEwI8xctAoBBpTGYuldb" + "P4N5vhxGkwlz0tJwv6gIXZ2dAIC09HTMSksj9cjzgkrR3jfeAMuyqp+ltg1mz53rs4zrNm3q" + "dxwAwmR14uhRuN1urN6wAQuXLkXUpEkwm80oLChAeWkpeJ7HlISEPvPF8zx2vPgiZs6di7t5" + "efB4PGhuakJcQgKCgoN71VtpaSn/oLy8tN8BgsccOBoxYQLWbNiAwKAgzJwzBwFBQQCEDtUk" + "W1IH91E4ALBarejs6AAgeDuyrl6FzWoFTdPYtH07wsLD+332o0gzdsoUAILai9Qg8km7sY9t" + "glq43W6cOXGCfJY8syGhoeS7mqoqtDQ1DasMviDvaAzD4LmdOxEbH0+W80nTpg0qryNRXmBw" + "da+mfoZbBoqmsfSZZ8jnW9evK8KA8nNz8Yy46xjss9S0gdo+0N84cLlcOPf11+SzfKsYL4uT" + "y7x4Ed1dXb3yRTMMtr/wAkLDwzE5JkZxT6NodvDGiHgJHyW8jXwG2ZJdDaGX2WyGxd8fXZ2d" + "8Ljd+PqLL3Dqyy8RGxeH+YsXY4msw6jFcNJc9eyzWLZyJWiaRsPDh7h49ixuZ2eT34dj1K6p" + "rITNaiWf/7p/P2HZlKO9vR1xISEjXi8DISYuDu//8Iewdndj4uTJqCgrU53XkLCwPtMcTHlD" + "wsIGVfdq2ngkyjBtxgwEhYSgraUFXZ2duJuXh1lpaaiqqIDRaCQT02DL2he820AiHBxqH6ip" + "rFTY2eTONf+AAPI/5/Gg4sGDXvZsClCwoepl9lDPMMbBsLyEjxsUTWP7iy/i0L59pHJ5jkN5" + "WRnKy8qweMUKrNu0adTSdNjtuHrpEvJycuBxu7F6/XrMmjsXl8+fB9B7gh4MrLIODQDbXnih" + "zzeSwWh8JPXiC0HBweQNO5i89ofBpjGYuldTP5O9tu5DKQNN01i0bBm+/uILAMDVS5cwKy0N" + "N65cUUwYI1FfgLINhtsHbF4KNgpBWJEPXqI9tqtQuxkpjOuzhG0tLQgJCcF7P/gBNmzZgimJ" + "iQoPxPXLl2GXvSUeZZqcx4M//va3uCwaU195803MXbBAMVAYdugLWvlbDRBEDMx+fr3+GIZ5" + "JPXyqPI6EmkMtu7V1I+3c2QoZQAEb7okrtBQX4+crCy0NDcjcerUEa0vbwy3D3jnSS4jLxdC" + "BQSv4WjB94Q1hgn8qquqcOLoUZj9/JC+dClefestvP/DHxKDsaSdNhpp1tbU4GFdHQCBezsy" + "KopcL4FVMWHJ36wu2XOiJk2Cn8VCPt+9c6fXvQV5eairqRlUGfp73nAwmLyORBqDrXs19RMe" + "ETHsMgCAXq8nTgQA+OroUSxevnzIZVWL4Y6NiZMnE5syIDhG+vrf7OdH7IejgRFbYbW3tys+" + "NzY09HmdfFDIXeoAFKoZ8tlfctcCQkVLrlOWZVFSXIyLZ8+S3wODghAWEQFAMF72F9g60mnK" + "B4Tb7UZOVhYqy8tRKHo+ASHezBfk3rn62lqUl5aiq7MTTocDG7duJb9lnD2LW9evo7OjA+1t" + "bbh07hwyTp9GQGDgoMrQ3/NsXtsUCfJ64ziOnAuVg2EY1XkFlH3CbrMJMlODSGOwda+mfgKD" + "ggZVhoGQvmQJ2VJZLBakzpo1rPpS0wZq+0B/44CmaWzZuZOsyu7JJlFSrxSFzTt2kAPTvfIl" + "++yWrdAc/azs1CyNhh3W0Nbaij9//DGuX7miMGzezcvD3Tt3kDR1KlkSZ168iHNff01mdmt3" + "N+4XFSEtPR3/8/vfo172BikuKoJer0dHezsOf/aZYgK7nZ2N8AkTwDIM6mtq0PjwIe7k5KCj" + "vR13cnNxLz8fCUlJ2LlnT6/gR0CIJxrpNC3+/mhva0N9ba2Q/8JCNDc2Yu3GjSguLITb7cbD" + "ujrk3rqF1Fmz+kxDSqezowN1NTXgOA55OTnIy8nBxMmTMS01FRMnT0ZdTQ26u7pwv6gI1y9f" + "xo3MTJjNZjz/8ss9+VBZhoGeF+pl4L2Xn4/DBw4oOtzt7Gx0d3UpvEAAEB4ZqSqv1y9fxpkT" + "J8ik5bDbUXD7NpJTUhAdF6cqjcHWvd1mU1U/asvgC3qDAS3NzXhYV4cFixcjoY/gTLXPUtsG" + "avpAaXFxv+MgNCwMIaGhiIuPx8O6OhTdvYvu7m6UlZQg8+JFREZFYcdLL5Ezw33lqyAvD9NS" + "U3H+1Cnk5+aSFW9leTm6OzvJvRLKysr4B0tMTvAAABxqSURBVA8eDBjWQAE4OdAFkyZOfPa9" + "998fk7YuSQnYaDSipakJzc3NoGka4RERQzqzOBJpNjU2oqOtDQGBgeRtZrfbUV9TA4qiEDlx" + "oiJCuD+0tbaio70dRpMJYeHhCo8LIFD1tIlR6hGRkYqBM5Qy+HrecDBQXkcyDbV1P5T6GW4Z" + "3G43nA4HDAaDT1vmSNTXSI+NtpYWtLS0gAIQEhb2SOxWZ06f5s6dP396oGvG9YSlQYOGJwen" + "T53izl+4MOCE5XsiGsNhDRo0aHi6oK2cNGjQMCagiVBo0KBh3GBEJqyxG4WlQYOGpw3allCD" + "Bg1jAmNONWc0cOTgQRSI9DUStuzahbkLFjymHGnQoEENxv2Etf+TT/CgpKTXuSWD0YjWlhaB" + "QTE8HCkzZ2LBokVgdTrsfOklzJw7Fwc+/ZTco6YixhP2ffwxHpSVKQJ1A4OCoNfr0dLSApZl" + "ER4RgekzZ2L+4sWqjgQ9yfjs009RVlKiYAAJDAqC0WQix0yCQ0KQOHUqFi9f3iePm4axgSEz" + "jo4GXn7jDTQ+fIjf/Nd/ke+Wr16NtPR0OBwOHN6/HyXFxaiurMT9oiK8+uaboGi6T5rXJwmv" + "vPUWGh4+xH/3US/dXV346/79qHjwgNTLK2K9PAnIycpSqC79y7/9m8979r7+OhobGvCbn/+c" + "fCfVl8vlwrHPP8e9/HzU19aisKAAb7//PnTjRKdyKPUxnuHbS/iY47DCIyP7/N5gMGDV+vXk" + "c3lpKSpFStrHnefRQEQ/9eJnsWCD7FzaA1m9PM0IFyPfvaHT6bBu82byubmxEWX3749WtjQM" + "Er69hGN4O+U9mckFFZ5meA9O+el6Db1hkTElABg0w4eG0cO4Nm54M3j6qzwjxfM88rKzkX3j" + "Bhx2O7q6uhAUHIx5Cxdi3sKFimtbW1pw9eJFPCgtBcuyaG5qQkBgIFJmzMDKtWt7SXvfvXMH" + "t65dQ31dHSwWC/QGA/wDAtDR3o7V69cTHqTB5GGwkJ+SBwCLF7eRmmefP3UKVy5cUNy3duNG" + "tDQ3o7CgAC6XC3Hx8Vi/ZUuvQ9KAcAA5+8YN1NfWwuznB2t3NyZMnIi09HQFJ37GmTO4dO6c" + "4t4tu3aB4zhcyciAzWrFhi1bMGf+fPz+o48Im4CE33/0EQDg7957b5C11IMakQseEPjYpUPE" + "NzIzcfbECQXz55ZduxAZFYX9n3yiYLTwduzYrFZkZmSg6N49OOx2uN1ucjBYp9cjLDwcQcHB" + "2P2KwD2gtt94l11tfahtj8cKFTsj32wNAQGqRCgeJeQUGckpKYiaNAmAsN3Jz80FILAtPrtp" + "E7HV9HcPABz9/HNcPn8eRpMJ73zwAYKCg3Hr2jXcLyqCy+kkHba1uRm/++gjVFVUIGriRLzx" + "ne+go60ND0pKUFVRAavViuSUFJLulYwMnPjb39De1oZ5Cxdi7+uvIy09HXarFbdv3cLMuXMJ" + "xa3aPAylXkqKiwmnklQv8sPMap49JTERsfHxyJPRDDscDixcuhQBgYEou39fmLzy8zF73jwF" + "4d1XR4/izFdfoaOtDd9+9108s2YN4hMTcU48td/e1kYGSVxCAkLDwhRUMO1tbWhvbUV9bS08" + "Hg8qy8ux9JlnMG/hQuj1ehQXFpJr/9c//7PqCb6v+qqrqcGxQ4dgs1oxYeJE7H7lFQSLXOqT" + "Y2KQOHUqcrKyFPclp6RgxuzZuHHlSp/173Q68Ydf/QrFhYWwWa349jvvYFpqKhHaAM/jje98" + "hwhYDKbfyKG2PgbTHo8TZaWlPtkaxm2ke2V5Ob76298ACOyIL7z6qoLGtT/k5+aSSW5aaioY" + "hkG8TM7q2uXLhLy/rraWvBWrKioAQDHxeROtXbt0qeeDuJWmKAoLlizBgsWLh5SHwaK2uhqn" + "jh8HAISFh2PP668r2AEG8+y4+HhF2nMXLMCUxEQsX72akLZ1dXbiqqzcednZRIVl2owZxNYW" + "GRWFZJFO5PatW7h96xa5J3X2bMVzEqdOxcy5c4dUfrW4kpGBX/3nf+LjX/4SzY2NSJkxA9te" + "eEHRvoBAZNcXBmIrKPnmG4UuYWRUlEItieM4VD54QD6r7TdDwVDaYyzD55ZwrFmwrly4gOtX" + "rgA8j4jISCxetgxzFiyAfgC9PzluXrtG/pdoYE0iXxcgbJeqKiowfeZMTJ0+HSvWrEFzUxOm" + "paYCAFEIAXpzWcvDL7KuXkVNVRVSZ89GyowZ2Lht25DyoBaXL1zA2ZMnSZ6mTp+O3S+/3GsS" + "H6lnx8bHo0IcdPcLC7F248Ze6UvMnxIiJkwgK6nsGzcwZ/58AL2dJFKIwcTJk9Hw8CFWy5wr" + "I4VlK1cKqxi7HZkZGcjMyEBhQQGmz5yJbS+8MCwvofe9bre7VxnllDFq+81QMJT2GMsY02EN" + "fWHZqlV9asGpRb1IpQsIogDSlkehBCJ2IIZhsHLdOtRUVeFefj4yzpwZkCdq/qJFyMzIIJ9r" + "qqpQU1WF0199hTnz5mHTtm1gdbpB5UEtlq9ahcryctwRtx3FhYWoqqzsRV87Us+WD7jWlhby" + "f8PDh+R/b94vOQ3ww36knuTXvvW97/nMx3BhNBqxZsMGPKytRUlxMe7l58MSEIANW7YMOc3E" + "5GSkzJhBJoPysjLQsgkrNj5esXpV22+GgpFqj7GCca2aM1wsXr58wCV3S3Mz/nbwIGqqqmDx" + "98erb72FqooKRdyLHKvXr4fZbMa1y5eJgCYAgOdx+9YtmMzmXkolvvIwGGzesQP1tbVoqK8H" + "z/M4cuAA3n7/fUXHfBTPlr/S1PYWeoz1q/ikJJQUFwMACm7fHtaERdE0dr/yCr65dw9fHjmC" + "r7/4AjRFYXJMDKalpiJ9yRJFXNxQ+o3qvKi8bqy1R38Ydyus4SI8IoKQ+fviWD/6l7+gpqoK" + "gMDLHR4ZSWxZfeH//vSneP+HP8Si5ctRX1uL4sJC5GRlEZuQFN8zmDwMBjqdDrv27MHvP/oI" + "brcbnR0dOPqXv2DvG2+QLclIPVvunZILs0ZMmEDqzJuzX35Pf7ahwYLn+RGJu5Nvnb29rENB" + "SXExjh8+jIjISHzr7bcHvFZtv1ED7/oY7fZ41Hjq2BrmzJtH/i8V36hy1FRVkUmpVubulo63" + "DLRd6uzowJWMDFAUhahJk/DM2rV487vfJb9LK53B5GGwCI+MxJoNG3rSv39fETYwnGfL3fty" + "BZfZsjTlKzaJY11Cg2zbsWDJkgHL0R+87UPebv2hQt7WE70M7/KjOi5xMpOLKvSFS2fPwtrd" + "jbbWVlRXVqKpoUH4a2xU2EEB9f2mL/iqj0fdHiMJNXPNmPcSekuB11ZX+wxm9dZbk3vc5i1a" + "RMjv62trcfXiRZLew/p6nDh6lAg0yOOLrmdm4vypUwoXNyB4YeQrlYvnzuHqpUtkYpOCWWmZ" + "dPlg8tAfvFWJHspsU+lLlyI6Lq4nT2fPEi/QcJ6dl51NBB3uf/MNAEFxOF02KGalpZHOX1hQ" + "QAbFw/p6fHPvHgBgyYoVSJkxg9zjrdDjLSwqx6SYGIWZ4uSxY7hx5YpPMU9vr6vctlNcVIR8" + "8cC8wWjEs889p7hWHgN1Lz8fzU1NOPPVV4pr5F5BAJgiel7bWlvxya9/jV///OfC389+hp/9" + "+Mf47NNPFXlW02/6gq/6GEp7PC6omWuGrZrzKPHpb36D86dPKyaoupoa3Lx2DRGRkX0GLJYW" + "F+OzTz5RLH8ryspIrAlFUUidNQt+FgtsVivu5efj1vXrqCgrQ2dHBzZt306kr2Li4lBbXY3u" + "ri6id7d19250dnSgtbkZHM+job4egUFBiIyKwqVz57Dt+edRWlyMy+fPI+fmTeRlZyMhKQnb" + "du9GjDiJDCYPfeEPv/oVLpw5o9iu11ZXI+vqVSRPmwY/iwXRMTHIycoidffNvXvIy85GWno6" + "ZqWlqX62PHaps6MDWVev4tb16zCbzUhbuBBbnn++l0E4aepUTJg4EdauLly9dAn5ubnIvXkT" + "sVOmYOPWrZgn0+krLizEgT/+USFVVV5Who5+YoNMZjP8AwJQV1MDl8sFp9MJ/4AAxCcn9ys0" + "+tf9+3H25ElFBHtNVRVu37qF7Bs3UHD7NsIjIjArLQ3bdu8mAhYSYuLi0FBXh/b2dmHV1NKC" + "5atX4+bVq+Sa6spKlBYXk+DRuClToNPrUV1ZqTh0LaGluRk2mw3JKSmq+01fUFMfg2mPxwk1" + "cViaCIWGAfGvH35I/n9u585heWifFuRkZeHc11/DZrUiISmJ2BA5jweFBQU4fOAAACHM4J0P" + "PnjMuR07OH36NHfeh2rOuD6ao0HDWMTXx4+T1VxSSgoxgtMMg2TZqlHurNCgbkuoqeZo6Bfe" + "BlxvY7GGvhEr28Ll5+YqbHRS1HlgcLDCOaJBHbQVloY+cfXSJVy9eFHx3YUzZ3D3zh28/MYb" + "ikBTDUrsfvVV3LhyBfeLitDc1IT/9x//geCQEPA8Lxj1N29GWno69D4cK08b1HgJn7o4LA3q" + "sGTFCixZseJxZ2NcQq/XY/nq1Vi+evXjzsq4grYl1KBBwxMFzfunQYOGMYERCRzVtoQaNGgY" + "DajZyz2xRvd9H3+MspISxXex8fF4zce5Lg1DR0FeHo6IMUZy9FXv0sFgQIjvGgsEchrGPp7Y" + "LeErb72Fbbt3K7/UVouPFKkzZ+K7//iPmJWWpvyhj3o/fvgwuru60N3V1S/7hQYN3nhiV1gA" + "MHPuXBw7dOhxZ2PU0NnRgbycHJQWF6OlqQk0TcPj8cBgNCIuPp4wTjwqUDSN0LAwbNy6lfBy" + "9Xut5szRMAT4Zhwdx6uSgcj2niS43W5cPHsWNzIzMS01FSvXrUN0TAyhTOnu6kJxYSH+un8/" + "kqdPx+r16x/phGHwIorrC5t37MCXR46Aoihs3rGj1+/yI0GxU6bgtXfeGdE8ahifeKJXWE8D" + "bFYrPvv0U7S2tGDvt7+NuISEXtf4WSyYu2ABZs6Zg2OHDuHsyZNDJoQbKUxLTSW00xo0qMWY" + "F1LV0D/cbjc++/RTNDc14bW33+5zspKD1emw/YUXUFpcrOCz0qBhTEDFXPPUrbDqampw9sQJ" + "VFZUwGg0YvrMmVi9fj3Zxhz9/PNe9hfJy5Vx5gwuX7ig0EPsywPmcrmQfeMGCvPz0fDwIViW" + "VZ7DoygEihqKH8i2PqX37+P6pUuoqa6Gx+1GYFAQQsPD4bDbMW3GDKR7kaxlnD6Nmqoq7Nqz" + "h9imnE4nLp07h/zcXHAch6nTp6OyvBxNDQ2YFB2NN7/7XSxevhw3r13D1uef71U/rc3NuHr5" + "Mkq/+QYejwc2mw1h4eGYOXcu0hcvVijwAAKtzeXz51Hx4AE4jwfBoaG9xA7keFhXh9/+4he9" + "vpck1n/Rh9R6dWUl+f6DDz/EX/fvx738fMU1sfHx2LJzJ059+SUelJYiMDAQu199lajENDc1" + "4ea1a3hQUgKb1QqHwwGWZREeGYm58+crSAjVoLmpCVmZmSi7fx82mw0URcFoNCI+KQnpS5cq" + "qI+Gkt+h9qHxDG+d0b7gkw/L32JJWLho0bhdZsn5nNxuN+pqauBnsaCxoQFOhwO11dUoLy3F" + "nHnzQNE0pqWmIjwyUtHBgoKCMGf+fMQlJCA+MVEhiST9JsHa3Y1Pfv1r5OfmoqO9HWs3bMDu" + "V14BTdMoL+2h+tm1dy82yRRR7uTk4NC+fWhtaYHBaMT3fvADLFq+HDVVVbh75w4Sp07FpOho" + "cn1HezsOHzyIqEmTiDR9R3s7Pv3v/0bxvXtYt2kTdu3di7t37pDnLn3mGUyKiYHZzw8ZZ89i" + "4dKliroqLCjA/3z8MWoqK7F+yxZsf/FF8DyPgrw8lN2/j6rycsyYM4fYBu/k5ODAn/6EpoYG" + "REZF4e/eew/pS5eiqqIC1ZWVPXUUHEzqyOLvj4TkZNzJzVV00GfWrgUALFq2DIuWLVO0W0xc" + "HN75/vexaNkyAEDKjBkwGI1K6mCRm+xBaSncLhdsVius3d2YPmsWigsL8T+/+x2qKypA0zS+" + "/+GHmD1vHq5fuYLW5mZ8c+8e9Ho9omNj++lFShTcvo39f/gDqisrMSUhAa+/+y4WLVuGqspK" + "5GVnIycrC8HBwWTiHmx+h9qHxjtKSkr48vLyYeoSPkGGaz+LBd96+23s2rsXz8kMvTVVVciV" + "TUIDsS9OlunL9YVL58+jScYGKrn45arAAJDnpQN34cwZRT7Nfn6gaRrPbt7c54rl9q1b4Dwe" + "wk/FcRw+//Of0dzYiITkZCKm6efnB0DY2k+fNYuk3+nF597U2IgjBw/C43bDz2IhKw75yqO8" + "rIyo7NTX1uKLv/6VTDobt22DyWwGTdNYuW7dgHU0OSamFw3xYEDRNBZ6rTYpmsbze/fCI6Mu" + "ltg7s2/cIPTOVqsVNMMIpIsTJpBr5XJYA6GupgZHP/+cpPfsc8+BYVkwLEvsgh63G0cPHSLb" + "7sHmd6h9aLxDjfnJN6f7IOWmxjJMJhOplJlz5hCedkB4a0oYqOJ8VWqTF3WxRDdsFicOCd6C" + "AHIK34b6ehw5eBD1tbWgabpPZZtS8W0dK8pF5efmEl5y+fWS1NSUhAQizeV2uXqxc2ZmZJDB" + "I2cclct5AT088FcyMsgAM/v5KUQM1GhEDteD6623GBgYCIZlsXz1augNBgQGB2PFmjUAgDnz" + "58NoMgEUhdmyGDF5+0uUxL6QKSt3UEgIAsRtGSCIq0r1xXMcMmVsF4PJ71D70HjHiLA1PEkr" + "LDkYlkVIWJiC43okEB0bq1j6d7S3IygkpBe3lFxtGRCED+TbqILbt1Fw+zYiJkzAM2vX9lr1" + "NYqc5NLkcluSlKcoYnyvrqwkA3HGnDnk3uampl7S53JBirqaGoUtSR6mIIkvyLcmQcHBvSvi" + "MeGZtWvJ9lJCyowZSJkxAxzHgeM4FBcVoTA/H9WimgygPnynQqbYbOlDHMI/IIBIdVWUlQ0p" + "v0PtQ08Dnmp6Gbmw5Ei9rZatXIm21laydcq6dg3rNm1SbDniEhJ6qZRs3rEDf/74416dsqG+" + "Hof27cOWXbsUWwK73Q6apslKRVpd+fv7kxXO3bw8AIIgrHzCu19UhOSUFMVz5M+dMHGiQrWl" + "L9hkAgosO/Z9N3U1Nbh+5Qq+uXsXeoMBazZsQHNjo+IloQZyMj7vVROgVLHxFtdQi6H2ofGO" + "ETlL+OROV0rZKrlc+3DAsCy27d6NRcuW4dTx48i9eRP5ubmgaRpTEhMxY/ZszJ43r9eWKDIq" + "Cn//D/+A7Bs3cPfOHbKCknDp/HnFhKXT6eByOuF2u4UJQ3yxSFs9juOI4yA6Npaskrq7ulBw" + "+za+/e67ivTNfn5kZdDW2uqznGazmXitbD4Uax437uTk4OihQwDPg2YYvP3uuwgJDVU4T9RC" + "Xk99iUvI5b+8t9NqMdQ+9DTA95ZwNHLxmCC3G3krk1A0PWT7XUFeHs6ePAmX04kf/Mu/qOpY" + "//5//g++/0//hBVr1mDFmjVobmrChVOnyKTjLVMVGhaG+tpatDQ1IWLCBCQkJ6Po7l20tbbi" + "1vXrqCwvJyEILpcLHrcb9XV1OHnsGNZv2dJL6y4mLo48q7urC+VlZQo5dQCw22zIy87GwmXL" + "EB0bi6K7dwGAaO0NpJ83HAykBakGF06fJhP6hKgohISG+rzn3p07+PJvf4PZzw8vvfYa4V+f" + "kpiI/NxcAH1TRsvbKT4pach5Hkofehow9tfyIwiXTOapo71doSe4aPlyxbVBwcFobW4GAIV8" + "uEJKvB8cO3SIGLB/9uMfwywT4gRFITg4GItXrCDadQDgsNtx7uRJbNq+HYAwIW19/nkyiXgL" + "FkxJSEB9bS3K7t9HxIQJ2LR9O9wuF8ofPEDmxYvYsGULVq1bh6+PH0dleTl+9pOfIDo2Fpt3" + "7EBUHx66xStWoLCggNhyvjh0CM+//DIxpjc1NODIwYOIED1rCxYvJhMWz3E4cfQodrz0EliW" + "xf2iIp915AsGoxEOUV9SzYpvIMgnEZvVKpSR53utDDmOIxPDiWPHYLfZYLfZkHHmDJ7fuxeA" + "sF27e+cOOI8HrS0taG9rQ2BQkJDPlhbyLJZlsWQAPUFfGEofehrw1GwJWZZFbXU1KsvLER0b" + "q4jzWbtpU68V1qy5c8k1zU1NuHHlCkLCwnq5vxsbGnqtLmanpRHBVZvV2suW0dzYiJL79/HS" + "t76lsCXdun4dDMNg5bPPwmAwEHociqKwev16RRrzFi7E9cxM3Lx2DelLl8Li74+9b7zRq9x7" + "vv1tVfUzKToam3fswFdHj4LnOLS1tuLjX/4SfhYLWJZFe1sbkqZNI+f+piQmYvGKFbh26RIA" + "wRtZ+q//CqPJ1Gs12NTYCGt3N/FycRyHTq+Jv7y0VBGpn5icjLt37gAQJpyDf/oTzH5+JNjV" + "26vX0dEBj8fTpzZhdFwcMYC3trTgT7/7XZ+r54wzZ5A4dSpi4uKURnjZ/+GRkdjx4os49vnn" + "cLvdOHPiBHa88AJ4AGdPCop5Or0eu/bsUbxkBpNfYOh9aDxDTVjDmBZSHQlcOncOG7ZuxYat" + "W+FyuXDt0iVkZmSgvq4OMVOmYPP27QpXt4To2Fg4HQ60NDfD43ajsbEROp0O6597TiHO4HK5" + "kJWZCf+AALJySU5JQWBQEBobGgY0vDY2NGC+KGJ58exZ7NyzB00NDTh/6hSuXryIort3EZ+Y" + "iC27dvXaXpjMZnjcbhQXFoKmaRLeMBxETZqElNRUuN1u2O12spUMCQ3Fmg0bsGbDBsUAS0hK" + "QlBwMDra22Gz2cCyLKJjY7Ft927k3rzZU0dOJ65fuQKHw4GEpCT86mc/66XonZeTA4qiSDli" + "p0xBc2Mj2tvbQdE0dDodEpOTMSkmBtcuX8ahffsUW0W7zYacrCwkTZtGYs8kxCcmoqmxEe1t" + "bWBYFsEhIVi3aRPS0tPxsK4OXV1d4AF0dXTAz98f0bGxCAwKwoPSUgQEBmLzzp2KNCMiIzF9" + "1ixwHg+qKipw+cIFZGVmwul0YuacOdjx0kuKIN/B5hcYWh8a7ygdCSHViVFRz77/wQfjdgNt" + "s1phki+nHzEelJTg+JEjaGtpgd5gwA9+9CNiS3I6ncgSJe8BwUD+zz/5yZCfxXEcjhw4gHsF" + "BVj/3HO9Ite9UVNVhTs5Odj4BEVHP4kYzT40lnD61Cnu/IULAwqpjtuJSC1Gc7ICgCMHD6Kt" + "pQUAEB4RoTh7p9frFbay4Upl0TSNXXv2YNW6dTh78iT++NvforiwUCH77nK5UF5aisMHDuDk" + "sWO9ziNqGHsYzT403uDbS6ixNQwKimW/aDSWQ27fkZ9BHCoomsby1asxZ/585N68iUvnzuHQ" + "vn3QibFYHo8Hk2NikJaejukzZ2rtOQ4w2n1oPOGpMbqPFpatWoUzX30FQDCMXjh9GivWrAHD" + "MLBZrTh1/DgAIfJ86cqVI/Zc/4AAEhLBc1wPg4DsOJKG8YHH1YfGA554G9bjwIOSEuTeuoXa" + "6mrhkDFFwWKxgKIoTIyOxpz585/KYxUa1ONp7ENqbFjalvARYEpi4lMXH6NhZKH1ob6hrZw0" + "aNAwbqBNWBo0aBgTGBE+LA0aNGgYDYyMVL0GDRo0jAZUUFlpE5YGDRrGDXyGNQAY+pFzDRo0" + "aFAJk8kEm812caBr1ExYGjRo0DAmoG0JNWjQMG6gTVgaNGgYN9AmLA0aNIwbaBOWBg0axg20" + "CUuDBg3jBtqEpUGDhnGD/w8mANBHiJ4GhAAAAABJRU5ErkJggg==") + +index.append('splashwarn') +catalog['splashwarn'] = splashwarn diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/README new file mode 100644 index 0000000..c17a088 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/README @@ -0,0 +1,11 @@ +This directory contains python modules that are distributed as part of Editra +but were not originally written as part of this project. + +See each module for their individual licensing and other related information. + + +pygments 1.0 (BSD) + +# Modifications notes for updates + +1) In lexers/web.py remove + from (r'[{}\[\]();.]+', Punctuation), diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/__init__.py new file mode 100644 index 0000000..b641bb1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/__init__.py @@ -0,0 +1,22 @@ +############################################################################### +# Name: __init__.py # +# Purpose: Puts external modules in the namespace # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### +"""External Module Package +Modules that Editra depends on that are where not developed for the project but +are distributed with it, either because of slight customizations made to them +or to reduce what is needed to be installed when installing Editra. + +@note: modules in this directory are dependancies and addons that are not + part of the core code. + +""" +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: __init__.py 52855 2008-03-27 14:53:06Z CJP $" +__revision__ = "$Revision: 52855 $" + +__all__ = ['ez_setup', 'pkg_resources', 'events', 'flatnotebook'] + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/decorlib.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/decorlib.py new file mode 100644 index 0000000..de0d06c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/decorlib.py @@ -0,0 +1,105 @@ +""" +Collection of helpful decorator methods + +""" + +__all__ = ['anythread',] + +#-----------------------------------------------------------------------------# +# Imports +import wx +import threading + +#-----------------------------------------------------------------------------# + +# +# <Found on PyPi: License: Public Domain> +# Author: Ryan Kelly +# +# wxAnyThread: allow methods on wxPython objects to be called from any thread +# +# In wxPython, methods that alter the state of the GUI are only safe to call from +# the thread running the main event loop. Other threads must typically post +# events to the GUI thread instead of invoking methods directly. +# +# While there are builtin shortcuts for this (e.g. wx.CallAfter) they do not +# capture the full semantics of a function call. This module provides an easy +# way to invoke methods from any thread *transparently*, propagating return +# values and exceptions back to the calling thread. +# +# The main interface is a decorator named "anythread", which can be applied +# to methods to make them safe to call from any thread, like so: +# +# class MyFrame(wx.Frame): +# +# @anythread +# def ShowFancyStuff(): +# dlg = MyQueryDialog(self,"Enter some data") +# if dlg.ShowModal() == wx.ID_OK: +# resp = dlg.GetResponse() +# return int(resp) +# else: +# raise NoDataEnteredError() +# +# The ShowFancyStuff method can now be directly invoked from any thread. +# The calling thread will block while the main GUI thread shows the dialog, +# and will then receive a return value or exception as appropriate. +# + +_EVT_INVOKE_METHOD = wx.NewEventType() + +class MethodInvocationEvent(wx.PyEvent): + """Event fired to the GUI thread indicating a method invocation.""" + def __init__(self, func, args, kwds): + wx.PyEvent.__init__(self) + self.SetEventType(_EVT_INVOKE_METHOD) + self.func = func + self.args = args + self.kwds = kwds + # The calling thread will block on this semaphore, which the GUI + # thread will release when the results are available. + # TODO: how expensive are these to create? Should we re-use them? + self.blocker = threading.Semaphore(0) + + def invoke(self): + wx.PostEvent(self.args[0], self) + self.blocker.acquire() + try: + return self.result + except AttributeError: + raise self.exception + + def process(self): + try: + self.result = self.func(*self.args, **self.kwds) + except Exception, e: + self.exception = e + self.blocker.release() + +def handler(evt): + evt.process() + +def anythread(func): + """Method decorator allowing call from any thread. + The method is replaced by one that posts a MethodInvocationEvent to the + object, then blocks waiting for it to be completed. The target object + if automatically connected to the _EVT_INVOKE_METHOD event if it wasn't + alread connected. + + """ + def invoker(*args, **kwds): + if wx.Thread_IsMain(): + return func(*args, **kwds) + else: + self = args[0] + if not hasattr(self, "_AnyThread__connected"): + self.Connect(-1, -1, _EVT_INVOKE_METHOD,handler) + self._AnyThread__connected = True + evt = MethodInvocationEvent(func, args, kwds) + return evt.invoke() + + invoker.__name__ = func.__name__ + invoker.__doc__ = func.__doc__ + return invoker + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/embeddedimage.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/embeddedimage.py new file mode 100644 index 0000000..8fb9cc6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/embeddedimage.py @@ -0,0 +1,69 @@ +#---------------------------------------------------------------------- +# Name: wx.lib.embeddedimage +# Purpose: Defines a class used for embedding PNG images in Python +# code. The primary method of using this module is via +# the code generator in wx.tools.img2py. +# +# Author: Anthony Tuininga +# +# Created: 26-Nov-2007 +# RCS-ID: $Id: embeddedimage.py 51067 2008-01-07 09:01:14Z CJP $ +# Copyright: (c) 2007 by Anthony Tuininga +# Licence: wxWindows license +#---------------------------------------------------------------------- + +import base64 +import cStringIO +import wx + +class PyEmbeddedImage(object): + """ + PyEmbeddedImage is primarily intended to be used by code generated + by img2py as a means of embedding image data in a python module so + the image can be used at runtime without needing to access the + image from an image file. This makes distributing icons and such + that an application uses simpler since tools like py2exe will + automatically bundle modules that are imported, and the + application doesn't have to worry about how to locate the image + files on the user's filesystem. + + The class can also be used for image data that may be acquired + from some other source at runtime, such as over the network or + from a database. In this case pass False for isBase64 (unless the + data actually is base64 encoded.) Any image type that + wx.ImageFromStream can handle should be okay. + """ + + def __init__(self, data, isBase64=True): + self.data = data + self.isBase64 = isBase64 + + def GetBitmap(self): + return wx.BitmapFromImage(self.GetImage()) + + def GetData(self): + return self.data + + def GetIcon(self): + icon = wx.EmptyIcon() + icon.CopyFromBitmap(self.GetBitmap()) + return icon + + def GetImage(self): + data = self.data + if self.isBase64: + data = base64.b64decode(self.data) + stream = cStringIO.StringIO(data) + return wx.ImageFromStream(stream) + + # added for backwards compatibility + getBitmap = GetBitmap + getData = GetData + getIcon = GetIcon + getImage = GetImage + + # define properties, for convenience + Bitmap = property(GetBitmap) + Icon = property(GetIcon) + Image = property(GetImage) + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/events.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/events.py new file mode 100644 index 0000000..f0312ad --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/events.py @@ -0,0 +1,128 @@ +#---------------------------------------------------------------------- +# Name: wxblox/events.py +# Purpose: These mixins implement a push and pop menu/UI update event +# handler system at the wx.App level. This is useful for resolving +# cases where multiple views may want to respond to an event +# (say, wx.ID_COPY) and where you also want a "default" handler +# for the event (and UI update status) when there is no active +# view which wishes to handle the event. +# +# Author: Kevin Ollivier +# +# Created: -Mar- +# Copyright: (c) Kevin Ollivier +# Licence: wxWindows license +#---------------------------------------------------------------------- + +import sys, os +import wx + +class AppEventManager: + ui_events = [ + wx.ID_NEW, wx.ID_OPEN, wx.ID_CLOSE_ALL, wx.ID_CLOSE, + wx.ID_REVERT, wx.ID_SAVE, wx.ID_SAVEAS, wx.ID_UNDO, + wx.ID_REDO, wx.ID_PRINT, wx.ID_PRINT_SETUP, wx.ID_PREVIEW, + wx.ID_EXIT + ] + + def __init__(self): + pass + + def RegisterEvents(self): + app = wx.GetApp() + #app.AddHandlerForID(wx.ID_EXIT, self.OnExit) + #app.AddHandlerForID(wx.ID_ABOUT, self.OnAbout) + + for eventID in self.ui_events: + app.AddHandlerForID(eventID, self.ProcessEvent) + app.AddUIHandlerForID(eventID, self.ProcessUpdateUIEvent) + +class AppEventHandlerMixin: + """ + The purpose of the AppEventHandlerMixin is to provide a centralized + location to manage menu and toolbar events. In an IDE which may have + any number of file editors and services open that may want to respond + to certain menu and toolbar events (e.g. copy, paste, select all), + we need this to efficiently make sure that the right handler is handling + the event. + + To work with this system, views must call + Add(UI)HandlerForID(ID, handlerFunc) + in their EVT_SET_FOCUS handler, and call Remove(UI)HandlerForID(ID) in their + EVT_KILL_FOCUS handler. + """ + + def __init__(self): + self.handlers = {} + self.uihandlers = {} + + # When a view changes the handler, move the old one here. + # Then "pop" the handler when the view loses the focus + self.pushed_handlers = {} + self.pushed_uihandlers = {} + + def AddHandlerForIDs(self, eventID_list, handlerFunc): + for eventID in eventID_list: + self.AddHandlerForID(eventID, handlerFunc) + + def AddHandlerForID(self, eventID, handlerFunc): + self.Bind(wx.EVT_MENU, self.HandleEvent, id=eventID) + + if eventID in self.handlers: + self.pushed_handlers[eventID] = self.handlers[eventID] + + self.handlers[eventID] = handlerFunc + + def AddUIHandlerForID(self, eventID, handlerFunc): + self.Bind(wx.EVT_UPDATE_UI, self.HandleUpdateUIEvent, id=eventID) + + if eventID in self.uihandlers: + self.pushed_uihandlers[eventID] = self.uihandlers[eventID] + + self.uihandlers[eventID] = handlerFunc + + def RemoveHandlerForIDs(self, eventID_list): + for eventID in eventID_list: + self.RemoveHandlerForID(eventID) + + def RemoveHandlerForID(self, eventID): + self.Unbind(wx.EVT_MENU, id=eventID) + self.handlers[eventID] = None + + if eventID in self.pushed_handlers: + self.handlers[eventID] = self.pushed_handlers[eventID] + + def RemoveUIHandlerForID(self, eventID): + self.Unbind(wx.EVT_UPDATE_UI, id=eventID) + self.uihandlers[eventID] = None + + if eventID in self.pushed_uihandlers: + self.uihandlers[eventID] = self.pushed_uihandlers[eventID] + + def HandleEvent(self, event): + e_id = event.GetId() + if e_id in self.handlers: + handler = self.handlers[e_id] + try: + if handler: + return handler(event) + except wx.PyDeadObjectError: + self.RemoveHandlerForID(e_id) + else: + event.Skip() + + return False + + def HandleUpdateUIEvent(self, event): + e_id = event.GetId() + if e_id in self.uihandlers: + handler = self.uihandlers[e_id] + try: + if handler: + return handler(event) + except wx.PyDeadObjectError: + self.RemoveUIHandlerForID(e_id) + else: + event.Skip() + + return False diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/ez_setup.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/ez_setup.py new file mode 100644 index 0000000..38c09c6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/ez_setup.py @@ -0,0 +1,228 @@ +#!python +"""Bootstrap setuptools installation + +If you want to use setuptools in your package's setup.py, just include this +file in the same directory with it, and add this to the top of your setup.py:: + + from ez_setup import use_setuptools + use_setuptools() + +If you want to require a specific version of setuptools, set a download +mirror, or use an alternate download directory, you can do so by supplying +the appropriate options to ``use_setuptools()``. + +This file can also be run as a script to install or upgrade setuptools. +""" +import sys +DEFAULT_VERSION = "0.6c5" +DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3] + +md5_data = { + 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', + 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', + 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', + 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', + 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', + 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', + 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', + 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', + 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', + 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', + 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', + 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', + 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', + 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', + 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', + 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f', + 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2', + 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc', + 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167', + 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64', + 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d', +} + +import sys, os + +def _validate_md5(egg_name, data): + if egg_name in md5_data: + from md5 import md5 + digest = md5(data).hexdigest() + if digest != md5_data[egg_name]: + print >>sys.stderr, ( + "md5 validation of %s failed! (Possible download problem?)" + % egg_name + ) + sys.exit(2) + return data + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + download_delay=15 +): + """Automatically find/download setuptools and make it available on sys.path + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end with + a '/'). `to_dir` is the directory where setuptools will be downloaded, if + it is not already available. If `download_delay` is specified, it should + be the number of seconds that will be paused before initiating a download, + should one be required. If an older version of setuptools is installed, + this routine will print a message to ``sys.stderr`` and raise SystemExit in + an attempt to abort the calling script. + """ + try: + import setuptools + if setuptools.__version__ == '0.0.1': + print >>sys.stderr, ( + "You have an obsolete version of setuptools installed. Please\n" + "remove it from your system entirely before rerunning this script." + ) + sys.exit(2) + except ImportError: + egg = download_setuptools(version, download_base, to_dir, download_delay) + sys.path.insert(0, egg) + import setuptools; setuptools.bootstrap_install_from = egg + + import pkg_resources + try: + pkg_resources.require("setuptools>="+version) + + except pkg_resources.VersionConflict, e: + # XXX could we install in a subprocess here? + print >>sys.stderr, ( + "The required version of setuptools (>=%s) is not available, and\n" + "can't be installed while this script is running. Please install\n" + " a more recent version first.\n\n(Currently using %r)" + ) % (version, e.args[0]) + sys.exit(2) + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, + delay = 15 +): + """Download setuptools from a specified location and return its filename + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download attempt. + """ + import urllib2, shutil + egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) + url = download_base + egg_name + saveto = os.path.join(to_dir, egg_name) + src = dst = None + if not os.path.exists(saveto): # Avoid repeated downloads + try: + from distutils import log + if delay: + log.warn(""" +--------------------------------------------------------------------------- +This script requires setuptools version %s to run (even to display +help). I will attempt to download it for you (from +%s), but +you may need to enable firewall access for this script first. +I will start the download in %d seconds. + +(Note: if this machine does not have network access, please obtain the file + + %s + +and place it in this directory before rerunning this script.) +---------------------------------------------------------------------------""", + version, download_base, delay, url + ); from time import sleep; sleep(delay) + log.warn("Downloading %s", url) + src = urllib2.urlopen(url) + # Read/write all in one block, so we don't create a corrupt file + # if the download is interrupted. + data = _validate_md5(egg_name, src.read()) + dst = open(saveto,"wb"); dst.write(data) + finally: + if src: src.close() + if dst: dst.close() + return os.path.realpath(saveto) + +def main(argv, version=DEFAULT_VERSION): + """Install or upgrade setuptools and EasyInstall""" + + try: + import setuptools + except ImportError: + egg = None + try: + egg = download_setuptools(version, delay=0) + sys.path.insert(0,egg) + from setuptools.command.easy_install import main + return main(list(argv)+[egg]) # we're done here + finally: + if egg and os.path.exists(egg): + os.unlink(egg) + else: + if setuptools.__version__ == '0.0.1': + # tell the user to uninstall obsolete version + use_setuptools(version) + + req = "setuptools>="+version + import pkg_resources + try: + pkg_resources.require(req) + except pkg_resources.VersionConflict: + try: + from setuptools.command.easy_install import main + except ImportError: + from easy_install import main + main(list(argv)+[download_setuptools(delay=0)]) + sys.exit(0) # try to force an exit + else: + if argv: + from setuptools.command.easy_install import main + main(argv) + else: + print "Setuptools version",version,"or greater has been installed." + print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' + + + +def update_md5(filenames): + """Update our built-in md5 registry""" + + import re + from md5 import md5 + + for name in filenames: + base = os.path.basename(name) + f = open(name,'rb') + md5_data[base] = md5(f.read()).hexdigest() + f.close() + + data = [" %r: %r,\n" % it for it in md5_data.items()] + data.sort() + repl = "".join(data) + + import inspect + srcfile = inspect.getsourcefile(sys.modules[__name__]) + f = open(srcfile, 'rb'); src = f.read(); f.close() + + match = re.search("\nmd5_data = {\n([^}]+)}", src) + if not match: + print >>sys.stderr, "Internal error!" + sys.exit(2) + + src = src[:match.start(1)] + repl + src[match.end(1):] + f = open(srcfile,'w') + f.write(src) + f.close() + + +if __name__=='__main__': + if len(sys.argv)>2 and sys.argv[1]=='--md5update': + update_md5(sys.argv[2:]) + else: + main(sys.argv[1:]) + + + + + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/flatnotebook.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/flatnotebook.py new file mode 100644 index 0000000..bf22bc9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/flatnotebook.py @@ -0,0 +1,4987 @@ +# --------------------------------------------------------------------------- # +# FLATNOTEBOOK Widget wxPython IMPLEMENTATION +# +# Original C++ Code From Eran. You Can Find It At: +# +# http://wxforum.shadonet.com/viewtopic.php?t=5761&start=0 +# +# License: wxWidgets license +# +# +# Python Code By: +# +# Andrea Gavana, @ 02 Oct 2006 +# Latest Revision: 22 Nov 2007, 14.00 GMT +# +# +# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please +# Write To Me At: +# +# andrea.gavana@gmail.com +# gavana@kpo.kz +# +# Or, Obviously, To The wxPython Mailing List!!! +# +# +# End Of Comments +# --------------------------------------------------------------------------- # + +""" +The FlatNotebook is a full implementation of the wx.Notebook, and designed to be +a drop-in replacement for wx.Notebook. The API functions are similar so one can +expect the function to behave in the same way. + +Some features: + + - The buttons are highlighted a la Firefox style + - The scrolling is done for bulks of tabs (so, the scrolling is faster and better) + - The buttons area is never overdrawn by tabs (unlike many other implementations I saw) + - It is a generic control + - Currently there are 5 differnt styles - VC8, VC 71, Standard, Fancy and Firefox 2; + - Mouse middle click can be used to close tabs + - A function to add right click menu for tabs (simple as SetRightClickMenu) + - All styles has bottom style as well (they can be drawn in the bottom of screen) + - An option to hide 'X' button or navigation buttons (separately) + - Gradient coloring of the selected tabs and border + - Support for drag 'n' drop of tabs, both in the same notebook or to another notebook + - Possibility to have closing button on the active tab directly + - Support for disabled tabs + - Colours for active/inactive tabs, and captions + - Background of tab area can be painted in gradient (VC8 style only) + - Colourful tabs - a random gentle colour is generated for each new tab (very cool, VC8 style only) + + +And much more. + + +License And Version: + +FlatNotebook Is Freeware And Distributed Under The wxPython License. + +Latest Revision: Andrea Gavana @ 22 Nov 2007, 14.00 GMT + +Version 2.4. + +@undocumented: FNB_HEIGHT_SPACER, VERTICAL_BORDER_PADDING, VC8_SHAPE_LEN, + wxEVT*, left_arrow_*, right_arrow*, x_button*, down_arrow*, + FNBDragInfo, FNBDropTarget, GetMondrian* +""" + +__docformat__ = "epytext" + + +#---------------------------------------------------------------------- +# Beginning Of FLATNOTEBOOK wxPython Code +#---------------------------------------------------------------------- + +import wx +import random +import math +import weakref +import cPickle + +# Used on OSX to get access to carbon api constants +if wx.Platform == '__WXMAC__': + import Carbon.Appearance + +# Check for the new method in 2.7 (not present in 2.6.3.3) +if wx.VERSION_STRING < "2.7": + wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point) + +FNB_HEIGHT_SPACER = 10 + +# Use Visual Studio 2003 (VC7.1) style for tabs +FNB_VC71 = 1 +"""Use Visual Studio 2003 (VC7.1) style for tabs""" + +# Use fancy style - square tabs filled with gradient coloring +FNB_FANCY_TABS = 2 +"""Use fancy style - square tabs filled with gradient coloring""" + +# Draw thin border around the page +FNB_TABS_BORDER_SIMPLE = 4 +"""Draw thin border around the page""" + +# Do not display the 'X' button +FNB_NO_X_BUTTON = 8 +"""Do not display the 'X' button""" + +# Do not display the Right / Left arrows +FNB_NO_NAV_BUTTONS = 16 +"""Do not display the right/left arrows""" + +# Use the mouse middle button for cloing tabs +FNB_MOUSE_MIDDLE_CLOSES_TABS = 32 +"""Use the mouse middle button for cloing tabs""" + +# Place tabs at bottom - the default is to place them +# at top +FNB_BOTTOM = 64 +"""Place tabs at bottom - the default is to place them at top""" + +# Disable dragging of tabs +FNB_NODRAG = 128 +"""Disable dragging of tabs""" + +# Use Visual Studio 2005 (VC8) style for tabs +FNB_VC8 = 256 +"""Use Visual Studio 2005 (VC8) style for tabs""" + +# Firefox 2 tabs style +FNB_FF2 = 131072 +"""Use Firefox 2 style for tabs""" + +# Place 'X' on a tab +FNB_X_ON_TAB = 512 +"""Place 'X' close button on the active tab""" + +FNB_BACKGROUND_GRADIENT = 1024 +"""Use gradients to paint the tabs background""" + +FNB_COLORFUL_TABS = 2048 +"""Use colourful tabs (VC8 style only)""" + +# Style to close tab using double click - styles 1024, 2048 are reserved +FNB_DCLICK_CLOSES_TABS = 4096 +"""Style to close tab using double click""" + +FNB_SMART_TABS = 8192 +"""Use Smart Tabbing, like Alt+Tab on Windows""" + +FNB_DROPDOWN_TABS_LIST = 16384 +"""Use a dropdown menu on the left in place of the arrows""" + +FNB_ALLOW_FOREIGN_DND = 32768 +"""Allows drag 'n' drop operations between different L{FlatNotebook}s""" + +FNB_HIDE_ON_SINGLE_TAB = 65536 +"""Hides the Page Container when there is one or fewer tabs""" + +VERTICAL_BORDER_PADDING = 4 + +# Button size is a 16x16 xpm bitmap +BUTTON_SPACE = 16 +"""Button size is a 16x16 xpm bitmap""" + +VC8_SHAPE_LEN = 16 + +MASK_COLOR = wx.Colour(0, 128, 128) +"""Mask colour for the arrow bitmaps""" + +# Button status +FNB_BTN_PRESSED = 2 +"""Navigation button is pressed""" +FNB_BTN_HOVER = 1 +"""Navigation button is hovered""" +FNB_BTN_NONE = 0 +"""No navigation""" + +# Hit Test results +FNB_TAB = 1 # On a tab +"""Indicates mouse coordinates inside a tab""" +FNB_X = 2 # On the X button +"""Indicates mouse coordinates inside the I{X} region""" +FNB_TAB_X = 3 # On the 'X' button (tab's X button) +"""Indicates mouse coordinates inside the I{X} region in a tab""" +FNB_LEFT_ARROW = 4 # On the rotate left arrow button +"""Indicates mouse coordinates inside the left arrow region""" +FNB_RIGHT_ARROW = 5 # On the rotate right arrow button +"""Indicates mouse coordinates inside the right arrow region""" +FNB_DROP_DOWN_ARROW = 6 # On the drop down arrow button +"""Indicates mouse coordinates inside the drop down arrow region""" +FNB_NOWHERE = 0 # Anywhere else +"""Indicates mouse coordinates not on any tab of the notebook""" + +FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB +"""L{FlatNotebook} default style""" + +# FlatNotebook Events: +# wxEVT_FLATNOTEBOOK_PAGE_CHANGED: Event Fired When You Switch Page; +# wxEVT_FLATNOTEBOOK_PAGE_CHANGING: Event Fired When You Are About To Switch +# Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call +# event.Skip() In Your Event Handler; +# wxEVT_FLATNOTEBOOK_PAGE_CLOSING: Event Fired When A Page Is Closing, But +# You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip() +# In Your Event Handler; +# wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed. +# wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab. + +wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED +wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING +wxEVT_FLATNOTEBOOK_PAGE_CLOSING = wx.NewEventType() +wxEVT_FLATNOTEBOOK_PAGE_CLOSED = wx.NewEventType() +wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType() + +#-----------------------------------# +# FlatNotebookEvent +#-----------------------------------# + +EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED +"""Notify client objects when the active page in L{FlatNotebook} +has changed.""" +EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING +"""Notify client objects when the active page in L{FlatNotebook} +is about to change.""" +EVT_FLATNOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, 1) +"""Notify client objects when a page in L{FlatNotebook} is closing.""" +EVT_FLATNOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, 1) +"""Notify client objects when a page in L{FlatNotebook} has been closed.""" +EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, 1) +"""Notify client objects when a pop-up menu should appear next to a tab.""" + + +# Some icons in XPM format + +left_arrow_disabled_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "````````````````", + "````````````````", + "````````.```````", + "```````..```````", + "``````.`.```````", + "`````.``.```````", + "````.```.```````", + "`````.``.```````", + "``````.`.```````", + "```````..```````", + "````````.```````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + ] + +x_button_pressed_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #9e9ede", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.############.`", + "`.###aa####aa#.`", + "`.####aa##aa##.`", + "`.#####aaaa###.`", + "`.######aa####.`", + "`.#####aaaa###.`", + "`.####aa##aa##.`", + "`.###aa####aa#.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + ] + + +left_arrow_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "````````````````", + "````````````````", + "````````.```````", + "```````..```````", + "``````...```````", + "`````....```````", + "````.....```````", + "`````....```````", + "``````...```````", + "```````..```````", + "````````.```````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + ] + +x_button_hilite_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #c9dafb", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.##aa####aa##.`", + "`.###aa##aa###.`", + "`.####aaaa####.`", + "`.#####aa#####.`", + "`.####aaaa####.`", + "`.###aa##aa###.`", + "`.##aa####aa##.`", + "`.############.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + ] + +x_button_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````..````..````", + "`````..``..`````", + "``````....``````", + "```````..```````", + "``````....``````", + "`````..``..`````", + "````..````..````", + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + ] + +left_arrow_pressed_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #9e9ede", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.#######a####.`", + "`.######aa####.`", + "`.#####aaa####.`", + "`.####aaaa####.`", + "`.###aaaaa####.`", + "`.####aaaa####.`", + "`.#####aaa####.`", + "`.######aa####.`", + "`.#######a####.`", + "`..............`", + "````````````````", + "````````````````" + ] + +left_arrow_hilite_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #c9dafb", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "`..............`", + "`.############.`", + "`.######a#####.`", + "`.#####aa#####.`", + "`.####aaa#####.`", + "`.###aaaa#####.`", + "`.##aaaaa#####.`", + "`.###aaaa#####.`", + "`.####aaa#####.`", + "`.#####aa#####.`", + "`.######a#####.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + ] + +right_arrow_disabled_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "````````````````", + "````````````````", + "```````.````````", + "```````..```````", + "```````.`.``````", + "```````.``.`````", + "```````.```.````", + "```````.``.`````", + "```````.`.``````", + "```````..```````", + "```````.````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + ] + +right_arrow_hilite_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #c9dafb", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "`..............`", + "`.############.`", + "`.####a#######.`", + "`.####aa######.`", + "`.####aaa#####.`", + "`.####aaaa####.`", + "`.####aaaaa###.`", + "`.####aaaa####.`", + "`.####aaa#####.`", + "`.####aa######.`", + "`.####a#######.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + ] + +right_arrow_pressed_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #9e9ede", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.#####a######.`", + "`.#####aa#####.`", + "`.#####aaa####.`", + "`.#####aaaa###.`", + "`.#####aaaaa##.`", + "`.#####aaaa###.`", + "`.#####aaa####.`", + "`.#####aa#####.`", + "`.#####a######.`", + "`..............`", + "````````````````", + "````````````````" + ] + + +right_arrow_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "````````````````", + "````````````````", + "```````.````````", + "```````..```````", + "```````...``````", + "```````....`````", + "```````.....````", + "```````....`````", + "```````...``````", + "```````..```````", + "```````.````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + ] + +down_arrow_hilite_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #c9dafb", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "``.............`", + "``.###########.`", + "``.###########.`", + "``.###########.`", + "``.#aaaaaaaaa#.`", + "``.##aaaaaaa##.`", + "``.###aaaaa###.`", + "``.####aaa####.`", + "``.#####a#####.`", + "``.###########.`", + "``.###########.`", + "``.###########.`", + "``.............`", + "````````````````", + "````````````````" + ] + +down_arrow_pressed_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #4766e0", + "# c #9e9ede", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "``.............`", + "``.###########.`", + "``.###########.`", + "``.###########.`", + "``.###########.`", + "``.###########.`", + "``.#aaaaaaaaa#.`", + "``.##aaaaaaa##.`", + "``.###aaaaa###.`", + "``.####aaa####.`", + "``.#####a#####.`", + "``.###########.`", + "``.............`", + "````````````````", + "````````````````" + ] + + +down_arrow_xpm = [ + " 16 16 8 1", + "` c #008080", + ". c #000000", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````.........```", + "`````.......````", + "``````.....`````", + "```````...``````", + "````````.```````", + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + ] + + +#---------------------------------------------------------------------- +def GetMondrianData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\ +\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\ +ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\ +o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\ +\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\ +\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\ +\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82' + + +def GetMondrianBitmap(): + return wx.BitmapFromImage(GetMondrianImage().Scale(16, 16)) + + +def GetMondrianImage(): + import cStringIO + stream = cStringIO.StringIO(GetMondrianData()) + return wx.ImageFromStream(stream) + + +def GetMondrianIcon(): + icon = wx.EmptyIcon() + icon.CopyFromBitmap(GetMondrianBitmap()) + return icon +#---------------------------------------------------------------------- + + +def LightColour(color, percent): + """ Brighten input colour by percent. """ + + end_color = wx.WHITE + + rd = end_color.Red() - color.Red() + gd = end_color.Green() - color.Green() + bd = end_color.Blue() - color.Blue() + + high = 100 + + # We take the percent way of the color from color -. white + i = percent + r = color.Red() + ((i*rd*100)/high)/100 + g = color.Green() + ((i*gd*100)/high)/100 + b = color.Blue() + ((i*bd*100)/high)/100 + return wx.Colour(r, g, b) + + +def RandomColour(): + """ Creates a random colour. """ + + r = random.randint(0, 255) # Random value betweem 0-255 + g = random.randint(0, 255) # Random value betweem 0-255 + b = random.randint(0, 255) # Random value betweem 0-255 + + return wx.Colour(r, g, b) + + +def PaintStraightGradientBox(dc, rect, startColor, endColor, vertical=True): + """ Draws a gradient colored box from startColor to endColor. """ + rd = endColor.Red() - startColor.Red() + gd = endColor.Green() - startColor.Green() + bd = endColor.Blue() - startColor.Blue() + + # Save the current pen and brush + savedPen = dc.GetPen() + savedBrush = dc.GetBrush() + if vertical: + high = rect.GetHeight()-1 + else: + high = rect.GetWidth()-1 + + if high < 1: + return + + for i in xrange(high+1): + + r = startColor.Red() + ((i*rd*100)/high)/100 + g = startColor.Green() + ((i*gd*100)/high)/100 + b = startColor.Blue() + ((i*bd*100)/high)/100 + + p = wx.Pen(wx.Colour(r, g, b)) + dc.SetPen(p) + + if vertical: + # TODO: Serious problem and potentially bug in wxPython2.8.9.2 + # some odd cases can cause the width attribute to be an + # empty tuple!! The repr and GetWidth however have the + # correct value. + dc.DrawLine(rect.x, rect.y+i, rect.x+rect.GetWidth(), rect.y+i) + else: + dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height) + + # Restore the pen and brush + dc.SetPen(savedPen) + dc.SetBrush(savedBrush) + +# ----------------------------------------------------------------------------- +# Util functions +# ----------------------------------------------------------------------------- + +def DrawButton(dc, rect, focus, upperTabs): + + # Define the rounded rectangle base on the given rect + # we need an array of 9 points for it + regPts = [wx.Point() for indx in xrange(9)] + + if focus: + if upperTabs: + leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8) + rightPt = wx.Point(rect.x + rect.GetWidth() - 2, rect.y + (rect.height / 10)*8) + else: + leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5) + rightPt = wx.Point(rect.x + rect.GetWidth() - 2, rect.y + (rect.height / 10)*5) + else: + leftPt = wx.Point(rect.x, rect.y + (rect.height / 2)) + rightPt = wx.Point(rect.x + rect.GetWidth() - 2, rect.y + (rect.height / 2)) + + # Define the top region + top = wx.RectPP(rect.GetTopLeft(), rightPt) + bottom = wx.RectPP(leftPt, rect.GetBottomRight()) + + topEndColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) + + if wx.Platform != '__WXGTK__': + # This type of gradient causes visibility issues with some dark + # GTK themes so don't use on GTK for now. + topStartColor = wx.WHITE + if not focus: + topStartColor = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50) + + bottomStartColor = topEndColor + bottomEndColor = topEndColor + else: + # Make whole tab same color on gtk + if not focus: + topEndColour = LightColour(topEndColor, 30) + bottomEndColor = bottomStartColor = topStartColor = topEndColor + + # Incase we use bottom tabs, switch the colors + if upperTabs: + if focus: + PaintStraightGradientBox(dc, top, topStartColor, topEndColor) + PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor) + else: + PaintStraightGradientBox(dc, top, topEndColor , topStartColor) + PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor) + + else: + if focus: + PaintStraightGradientBox(dc, bottom, topEndColor, bottomEndColor) + PaintStraightGradientBox(dc, top,topStartColor, topStartColor) + else: + PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor) + PaintStraightGradientBox(dc, top, topEndColor, topStartColor) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + + +# ---------------------------------------------------------------------------- # +# Class FNBDropSource +# Gives Some Custom UI Feedback during the DnD Operations +# ---------------------------------------------------------------------------- # + +class FNBDropSource(wx.DropSource): + """ + Give some custom UI feedback during the drag and drop operation in this + function. It is called on each mouse move, so your implementation must + not be too slow. + """ + + def __init__(self, win): + """ Default class constructor. Used internally. """ + + wx.DropSource.__init__(self, win) + self._win = win + + + def GiveFeedback(self, effect): + """ Provides user with a nice feedback when tab is being dragged. """ + + self._win.DrawDragHint() + return False + + +# ---------------------------------------------------------------------------- # +# Class FNBDragInfo +# Stores All The Information To Allow Drag And Drop Between Different +# FlatNotebooks. +# ---------------------------------------------------------------------------- # + +class FNBDragInfo: + + _map = weakref.WeakValueDictionary() + + def __init__(self, container, pageindex): + """ Default class constructor. """ + + self._id = id(container) + FNBDragInfo._map[self._id] = container + self._pageindex = pageindex + + + def GetContainer(self): + """ Returns the L{FlatNotebook} page (usually a panel). """ + + return FNBDragInfo._map.get(self._id, None) + + + def GetPageIndex(self): + """ Returns the page index associated with a page. """ + + return self._pageindex + + +# ---------------------------------------------------------------------------- # +# Class FNBDropTarget +# Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between +# Different FlatNotebooks. +# ---------------------------------------------------------------------------- # + +class FNBDropTarget(wx.DropTarget): + + def __init__(self, parent): + """ Default class constructor. """ + + wx.DropTarget.__init__(self) + + self._parent = parent + self._dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook")) + self.SetDataObject(self._dataobject) + + + def OnData(self, x, y, dragres): + """ Handles the OnData() method to call the real DnD routine. """ + try: + if not self.GetData(): + return wx.DragNone + + draginfo = self._dataobject.GetData() + drginfo = cPickle.loads(draginfo) + + return self._parent.OnDropTarget(x, y, drginfo.GetPageIndex(), drginfo.GetContainer()) + except wx.PyAssertionError: + return wx.DragCancel + + +# ---------------------------------------------------------------------------- # +# Class PageInfo +# Contains parameters for every FlatNotebook page +# ---------------------------------------------------------------------------- # + +class PageInfo: + """ + This class holds all the information (caption, image, etc...) belonging to a + single tab in L{FlatNotebook}. + """ + + def __init__(self, caption="", imageindex=-1, tabangle=0, enabled=True): + """ + Default Class Constructor. + + Parameters: + @param caption: the tab caption; + @param imageindex: the tab image index based on the assigned (set) wx.ImageList (if any); + @param tabangle: the tab angle (only on standard tabs, from 0 to 15 degrees); + @param enabled: sets enabled or disabled the tab. + """ + + self._strCaption = caption + self._TabAngle = tabangle + self._ImageIndex = imageindex + self._bEnabled = enabled + self._pos = wx.Point(-1, -1) + self._size = wx.Size(-1, -1) + self._region = wx.Region() + self._xRect = wx.Rect() + self._color = None + self._hasFocus = False + + + def SetCaption(self, value): + """ Sets the tab caption. """ + + self._strCaption = value + + + def GetCaption(self): + """ Returns the tab caption. """ + + return self._strCaption + + + def SetPosition(self, value): + """ Sets the tab position. """ + + self._pos = value + + + def GetPosition(self): + """ Returns the tab position. """ + + return self._pos + + + def SetSize(self, value): + """ Sets the tab size. """ + + self._size = value + + + def GetSize(self): + """ Returns the tab size. """ + + return self._size + + + def SetTabAngle(self, value): + """ Sets the tab header angle (0 <= tab <= 15 degrees). """ + + self._TabAngle = min(45, value) + + + def GetTabAngle(self): + """ Returns the tab angle. """ + + return self._TabAngle + + + def SetImageIndex(self, value): + """ Sets the tab image index. """ + + self._ImageIndex = value + + + def GetImageIndex(self): + """ Returns the tab umage index. """ + + return self._ImageIndex + + + def GetEnabled(self): + """ Returns whether the tab is enabled or not. """ + + return self._bEnabled + + + def EnableTab(self, enabled): + """ Sets the tab enabled or disabled. """ + + self._bEnabled = enabled + + + def SetRegion(self, points=[]): + """ Sets the tab region. """ + + self._region = wx.RegionFromPoints(points) + + + def GetRegion(self): + """ Returns the tab region. """ + + return self._region + + + def SetXRect(self, xrect): + """ Sets the button 'X' area rect. """ + + self._xRect = xrect + + + def GetXRect(self): + """ Returns the button 'X' area rect. """ + + return self._xRect + + + def GetColour(self): + """ Returns the tab colour. """ + + return self._color + + + def SetColour(self, color): + """ Sets the tab colour. """ + + self._color = color + + +# ---------------------------------------------------------------------------- # +# Class FlatNotebookEvent +# ---------------------------------------------------------------------------- # + +class FlatNotebookEvent(wx.PyCommandEvent): + """ + This events will be sent when a EVT_FLATNOTEBOOK_PAGE_CHANGED, + EVT_FLATNOTEBOOK_PAGE_CHANGING, EVT_FLATNOTEBOOK_PAGE_CLOSING, + EVT_FLATNOTEBOOK_PAGE_CLOSED and EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU is + mapped in the parent. + """ + + def __init__(self, eventType, id=1, nSel=-1, nOldSel=-1): + """ Default class constructor. """ + + wx.PyCommandEvent.__init__(self, eventType, id) + self._eventType = eventType + + self.notify = wx.NotifyEvent(eventType, id) + + + def GetNotifyEvent(self): + """Returns the actual wx.NotifyEvent.""" + + return self.notify + + + def IsAllowed(self): + """Returns whether the event is allowed or not.""" + + return self.notify.IsAllowed() + + + def Veto(self): + """Vetos the event.""" + + self.notify.Veto() + + + def Allow(self): + """The event is allowed.""" + + self.notify.Allow() + + + def SetSelection(self, nSel): + """ Sets event selection. """ + + self._selection = nSel + + + def SetOldSelection(self, nOldSel): + """ Sets old event selection. """ + + self._oldselection = nOldSel + + + def GetSelection(self): + """ Returns event selection. """ + + return self._selection + + + def GetOldSelection(self): + """ Returns old event selection """ + + return self._oldselection + + +# ---------------------------------------------------------------------------- # +# Class TabNavigatorWindow +# ---------------------------------------------------------------------------- # + +class TabNavigatorWindow(wx.Dialog): + """ + This class is used to create a modal dialog that enables "Smart Tabbing", + similar to what you would get by hitting Alt+Tab on Windows. + """ + + def __init__(self, parent=None, icon=None): + """ Default class constructor. Used internally.""" + + wx.Dialog.__init__(self, parent, wx.ID_ANY, "", style=0) + + self._selectedItem = -1 + self._indexMap = [] + self._sel = 0 + + if icon is None: + self._bmp = GetMondrianBitmap() + else: + self._bmp = icon + + sz = wx.BoxSizer(wx.VERTICAL) + + self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, 150), [], wx.LB_SINGLE | wx.NO_BORDER) + + mem_dc = wx.MemoryDC() + mem_dc.SelectObject(wx.EmptyBitmap(1,1)) + font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + font.SetWeight(wx.BOLD) + mem_dc.SetFont(font) + + panelHeight = mem_dc.GetCharHeight() + panelHeight += 4 # Place a spacer of 2 pixels + + # Out signpost bitmap is 24 pixels + if panelHeight < 24: + panelHeight = 24 + + self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, panelHeight)) + + sz.Add(self._panel) + sz.Add(self._listBox, 1, wx.EXPAND) + + self.SetSizer(sz) + + # Connect events to the list box + self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey) + self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected) + + # Connect paint event to the panel + self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint) + self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg) + + self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)) + self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)) + self.PopulateListControl(parent) + + self.GetSizer().Fit(self) + self.GetSizer().SetSizeHints(self) + self.GetSizer().Layout() + self.Centre() + + # Set focus on the list box to avoid having to click on it to change + # the tab selection under GTK. + self._listBox.SetFocus() + + + def OnKeyUp(self, event): + """Handles the wx.EVT_KEY_UP for the L{TabNavigatorWindow}.""" + + if event.GetKeyCode() == wx.WXK_CONTROL: + self.CloseDialog() + + + def OnNavigationKey(self, event): + """Handles the wx.EVT_NAVIGATION_KEY for the L{TabNavigatorWindow}. """ + + selected = self._listBox.GetSelection() + bk = self.GetParent() + maxItems = bk.GetPageCount() + + if event.GetDirection(): + + # Select next page + if selected == maxItems - 1: + itemToSelect = 0 + else: + itemToSelect = selected + 1 + + else: + + # Previous page + if selected == 0: + itemToSelect = maxItems - 1 + else: + itemToSelect = selected - 1 + + self._listBox.SetSelection(itemToSelect) + + + def PopulateListControl(self, book): + """Populates the L{TabNavigatorWindow} listbox with a list of tabs.""" + + selection = book.GetSelection() + count = book.GetPageCount() + + self._listBox.Append(book.GetPageText(selection)) + self._indexMap.append(selection) + + prevSel = book.GetPreviousSelection() + + if prevSel != wx.NOT_FOUND: + + # Insert the previous selection as second entry + self._listBox.Append(book.GetPageText(prevSel)) + self._indexMap.append(prevSel) + + for c in xrange(count): + + # Skip selected page + if c == selection: + continue + + # Skip previous selected page as well + if c == prevSel: + continue + + self._listBox.Append(book.GetPageText(c)) + self._indexMap.append(c) + + # Select the next entry after the current selection + self._listBox.SetSelection(0) + dummy = wx.NavigationKeyEvent() + dummy.SetDirection(True) + self.OnNavigationKey(dummy) + + + def OnItemSelected(self, event): + """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """ + + self.CloseDialog() + + + def CloseDialog(self): + """Closes the L{TabNavigatorWindow} dialog, setting selection in L{FlatNotebook}.""" + + bk = self.GetParent() + self._selectedItem = self._listBox.GetSelection() + self._sel = self._indexMap[self._selectedItem] + self.EndModal(wx.ID_OK) + + + def GetSelection(self): + """Get the index of the selected page""" + return self._sel + + + def OnPanelPaint(self, event): + """Handles the wx.EVT_PAINT event for L{TabNavigatorWindow} top panel. """ + + dc = wx.PaintDC(self._panel) + rect = self._panel.GetClientRect() + + bmp = wx.EmptyBitmap(rect.GetWidth(), rect.height) + + mem_dc = wx.MemoryDC() + mem_dc.SelectObject(bmp) + + endColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW) + startColour = LightColour(endColour, 50) + PaintStraightGradientBox(mem_dc, rect, startColour, endColour) + + # Draw the caption title and place the bitmap + # get the bitmap optimal position, and draw it + bmpPt, txtPt = wx.Point(), wx.Point() + bmpPt.y = (rect.height - self._bmp.GetHeight())/2 + bmpPt.x = 3 + mem_dc.DrawBitmap(self._bmp, bmpPt.x, bmpPt.y, True) + + # get the text position, and draw it + font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + font.SetWeight(wx.BOLD) + mem_dc.SetFont(font) + fontHeight = mem_dc.GetCharHeight() + + txtPt.x = bmpPt.x + self._bmp.GetWidth() + 4 + txtPt.y = (rect.height - fontHeight)/2 + mem_dc.SetTextForeground(wx.WHITE) + mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y) + mem_dc.SelectObject(wx.NullBitmap) + + dc.DrawBitmap(bmp, 0, 0) + + + def OnPanelEraseBg(self, event): + """Handles the wx.EVT_ERASE_BACKGROUND event for L{TabNavigatorWindow} top panel. """ + + pass + + +# ---------------------------------------------------------------------------- # +# Class FNBRenderer +# ---------------------------------------------------------------------------- # + +class FNBRenderer: + """ + Parent class for the 4 renderers defined: I{Standard}, I{VC71}, I{Fancy} + and I{VC8}. This class implements the common methods of all 4 renderers. + """ + + def __init__(self): + """Default class constructor. """ + + self._tabHeight = None + + if wx.Platform == "__WXMAC__": + # Hack to get proper highlight color for focus rectangle from + # current theme by creating a theme brush and getting its color. + # kThemeBrushFocusHighlight is available on Mac OS 8.5 and higher + brush = wx.Brush(wx.BLACK) + brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight) + self._focusPen = wx.Pen(brush.GetColour(), 2, wx.SOLID) + else: + self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH) + self._focusPen.SetDashes([1, 1]) + self._focusPen.SetCap(wx.CAP_BUTT) + + + def GetLeftButtonPos(self, pageContainer): + """ Returns the left button position in the navigation area. """ + return 2 + + + def GetRightButtonPos(self, pageContainer): + """ Returns the right button position in the navigation area. """ + + pc = pageContainer + style = pc.GetParent().GetWindowStyleFlag() + rect = pc.GetClientRect() + clientWidth = rect.GetWidth() + + if style & FNB_NO_X_BUTTON: + return clientWidth - 20 + else: + return clientWidth - 36 + + + def GetDropArrowButtonPos(self, pageContainer): + """ Returns the drop down button position in the navigation area. """ + pc = pageContainer + style = pc.GetParent().GetWindowStyleFlag() + rect = pc.GetClientRect() + clientWidth = rect.GetWidth() + + if style & FNB_NO_X_BUTTON and style & FNB_NO_NAV_BUTTONS: + return clientWidth - 20 + elif style & FNB_NO_X_BUTTON or style & FNB_NO_NAV_BUTTONS: + return clientWidth - 36 + else: + return clientWidth - 52 + + + def GetXPos(self, pageContainer): + """ Returns the 'X' button position in the navigation area. """ + + pc = pageContainer + style = pc.GetParent().GetWindowStyleFlag() + rect = pc.GetClientRect() + clientWidth = rect.GetWidth() + + if style & FNB_NO_X_BUTTON: + return clientWidth + else: + return clientWidth - 20 + + + def GetButtonsAreaLength(self, pageContainer): + """ Returns the navigation area width. """ + + pc = pageContainer + style = pc.GetParent().GetWindowStyleFlag() + + # '' + if style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST: + return 0 + + # 'x' + elif style & FNB_NO_NAV_BUTTONS and not style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST: + return 22 + + # '<>' + if not style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST: + return 53 - 16 + + # 'vx' + if style & FNB_DROPDOWN_TABS_LIST and not style & FNB_NO_X_BUTTON: + return 22 + 16 + + # 'v' + if style & FNB_DROPDOWN_TABS_LIST and style & FNB_NO_X_BUTTON: + return 22 + + # '<>x' + return 53 + + def DrawArrowAccordingToState(self, dc, pc, rect): + lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0] + PaintStraightGradientBox(dc, rect, pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor)) + + def DrawLeftArrow(self, pageContainer, dc): + """ Draw the left navigation arrow. """ + + pc = pageContainer + + style = pc.GetParent().GetWindowStyleFlag() + if style & FNB_NO_NAV_BUTTONS: + return + + # Make sure that there are pages in the container + if not pc._pagesInfoVec: + return + + # Set the bitmap according to the button status + if pc._nLeftButtonStatus == FNB_BTN_HOVER: + arrowBmp = wx.BitmapFromXPMData(left_arrow_hilite_xpm) + elif pc._nLeftButtonStatus == FNB_BTN_PRESSED: + arrowBmp = wx.BitmapFromXPMData(left_arrow_pressed_xpm) + else: + arrowBmp = wx.BitmapFromXPMData(left_arrow_xpm) + + if pc._nFrom == 0: + # Handle disabled arrow + arrowBmp = wx.BitmapFromXPMData(left_arrow_disabled_xpm) + + arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR)) + + # Erase old bitmap + posx = self.GetLeftButtonPos(pc) + self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14)) + + # Draw the new bitmap + dc.DrawBitmap(arrowBmp, posx + 2, 6, True) + + + def DrawRightArrow(self, pageContainer, dc): + """ Draw the right navigation arrow. """ + + pc = pageContainer + + style = pc.GetParent().GetWindowStyleFlag() + if style & FNB_NO_NAV_BUTTONS: + return + + # Make sure that there are pages in the container + if not pc._pagesInfoVec: + return + + # Set the bitmap according to the button status + if pc._nRightButtonStatus == FNB_BTN_HOVER: + arrowBmp = wx.BitmapFromXPMData(right_arrow_hilite_xpm) + elif pc._nRightButtonStatus == FNB_BTN_PRESSED: + arrowBmp = wx.BitmapFromXPMData(right_arrow_pressed_xpm) + else: + arrowBmp = wx.BitmapFromXPMData(right_arrow_xpm) + + # Check if the right most tab is visible, if it is + # don't rotate right anymore + if pc._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1): + arrowBmp = wx.BitmapFromXPMData(right_arrow_disabled_xpm) + + arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR)) + + # erase old bitmap + posx = self.GetRightButtonPos(pc) + self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14)) + + # Draw the new bitmap + dc.DrawBitmap(arrowBmp, posx, 6, True) + + + def DrawDropDownArrow(self, pageContainer, dc): + """ Draws the drop-down arrow in the navigation area. """ + + pc = pageContainer + + # Check if this style is enabled + style = pc.GetParent().GetWindowStyleFlag() + if not style & FNB_DROPDOWN_TABS_LIST: + return + + # Make sure that there are pages in the container + if not pc._pagesInfoVec: + return + + if pc._nArrowDownButtonStatus == FNB_BTN_HOVER: + downBmp = wx.BitmapFromXPMData(down_arrow_hilite_xpm) + elif pc._nArrowDownButtonStatus == FNB_BTN_PRESSED: + downBmp = wx.BitmapFromXPMData(down_arrow_pressed_xpm) + else: + downBmp = wx.BitmapFromXPMData(down_arrow_xpm) + + downBmp.SetMask(wx.Mask(downBmp, MASK_COLOR)) + + # erase old bitmap + posx = self.GetDropArrowButtonPos(pc) + self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14)) + + # Draw the new bitmap + dc.DrawBitmap(downBmp, posx, 6, True) + + + def DrawX(self, pageContainer, dc): + """ Draw the 'X' navigation button in the navigation area. """ + + pc = pageContainer + + # Check if this style is enabled + style = pc.GetParent().GetWindowStyleFlag() + if style & FNB_NO_X_BUTTON: + return + + # Make sure that there are pages in the container + if not pc._pagesInfoVec: + return + + # Set the bitmap according to the button status + if pc._nXButtonStatus == FNB_BTN_HOVER: + xbmp = wx.BitmapFromXPMData(x_button_hilite_xpm) + elif pc._nXButtonStatus == FNB_BTN_PRESSED: + xbmp = wx.BitmapFromXPMData(x_button_pressed_xpm) + else: + xbmp = wx.BitmapFromXPMData(x_button_xpm) + + xbmp.SetMask(wx.Mask(xbmp, MASK_COLOR)) + + # erase old bitmap + posx = self.GetXPos(pc) + self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14)) + + # Draw the new bitmap + dc.DrawBitmap(xbmp, posx, 6, True) + + + def DrawTabX(self, pageContainer, dc, rect, tabIdx, btnStatus): + """ Draws the 'X' in the selected tab. """ + + pc = pageContainer + if not pc.HasFlag(FNB_X_ON_TAB): + return + + # We draw the 'x' on the active tab only + if tabIdx != pc.GetSelection() or tabIdx < 0: + return + + # Set the bitmap according to the button status + + if btnStatus == FNB_BTN_HOVER: + xBmp = wx.BitmapFromXPMData(x_button_hilite_xpm) + elif btnStatus == FNB_BTN_PRESSED: + xBmp = wx.BitmapFromXPMData(x_button_pressed_xpm) + else: + xBmp = wx.BitmapFromXPMData(x_button_xpm) + + # Set the masking + xBmp.SetMask(wx.Mask(xBmp, MASK_COLOR)) + + # Draw the new bitmap + dc.DrawBitmap(xBmp, rect.x, rect.y, True) + + # Update the vector + rr = wx.Rect(rect.x, rect.y, 14, 13) + pc._pagesInfoVec[tabIdx].SetXRect(rr) + + + def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1): + """ Draws a line over the tabs. """ + + pc = pageContainer + + clntRect = pc.GetClientRect() + clientRect3 = wx.Rect(0, 0, clntRect.GetWidth(), clntRect.height) + + if pc.HasFlag(FNB_FF2): + if not pc.HasFlag(FNB_BOTTOM): + fillColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) + else: + fillColor = wx.WHITE + + dc.SetPen(wx.Pen(fillColor)) + + if pc.HasFlag(FNB_BOTTOM): + + dc.DrawLine(1, 0, clntRect.GetWidth()-1, 0) + dc.DrawLine(1, 1, clntRect.GetWidth()-1, 1) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) + dc.DrawLine(1, 2, clntRect.GetWidth()-1, 2) + + dc.SetPen(wx.Pen(fillColor)) + dc.DrawLine(selTabX1 + 2, 2, selTabX2 - 1, 2) + + else: + + dc.DrawLine(1, clntRect.height, clntRect.GetWidth()-1, clntRect.height) + dc.DrawLine(1, clntRect.height-1, clntRect.GetWidth()-1, clntRect.height-1) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) + dc.DrawLine(1, clntRect.height-2, clntRect.GetWidth()-1, clntRect.height-2) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))) + dc.DrawLine(selTabX1 + 2, clntRect.height-2, selTabX2-1, clntRect.height-2) + + else: + + if pc.HasFlag(FNB_BOTTOM): + + clientRect = wx.Rect(0, 2, clntRect.GetWidth(), clntRect.height - 2) + clientRect2 = wx.Rect(0, 1, clntRect.GetWidth(), clntRect.height - 1) + + else: + + clientRect = wx.Rect(0, 0, clntRect.GetWidth(), clntRect.height - 2) + clientRect2 = wx.Rect(0, 0, clntRect.GetWidth(), clntRect.height - 1) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour())) + dc.DrawRectangleRect(clientRect2) + dc.DrawRectangleRect(clientRect3) + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))) + dc.DrawRectangleRect(clientRect) + + if not pc.HasFlag(FNB_TABS_BORDER_SIMPLE): + + dc.SetPen(wx.Pen((pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColor])[0])) + dc.DrawLine(0, 0, 0, clientRect.height+1) + + if pc.HasFlag(FNB_BOTTOM): + + dc.DrawLine(0, clientRect.height+1, clientRect.GetWidth(), clientRect.height+1) + + else: + + dc.DrawLine(0, 0, clientRect.GetWidth(), 0) + + dc.DrawLine(clientRect.GetWidth() - 1, 0, clientRect.GetWidth() - 1, clientRect.height+1) + + + def CalcTabWidth(self, pageContainer, tabIdx, tabHeight): + """ Calculates the width of the input tab. """ + + pc = pageContainer + dc = wx.MemoryDC() + dc.SelectObject(wx.EmptyBitmap(1,1)) + + boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + boldFont.SetWeight(wx.FONTWEIGHT_BOLD) + + if pc.IsDefaultTabs(): + shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi)) + + # Calculate the text length using the bold font, so when selecting a tab + # its width will not change + dc.SetFont(boldFont) + width, pom = dc.GetTextExtent(pc.GetPageText(tabIdx)) + + # Set a minimum size to a tab + if width < 20: + width = 20 + + tabWidth = 2*pc._pParent.GetPadding() + width + + # Style to add a small 'x' button on the top right + # of the tab + if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection(): + # The xpm image that contains the 'x' button is 9 pixels + spacer = 9 + if pc.HasFlag(FNB_VC8): + spacer = 4 + + tabWidth += pc._pParent.GetPadding() + spacer + + if pc.IsDefaultTabs(): + # Default style + tabWidth += 2*shapePoints + + hasImage = pc._ImageList != None and pc._pagesInfoVec[tabIdx].GetImageIndex() != -1 + + # For VC71 style, we only add the icon size (16 pixels) + if hasImage: + + if not pc.IsDefaultTabs(): + tabWidth += 16 + pc._pParent.GetPadding() + else: + # Default style + tabWidth += 16 + pc._pParent.GetPadding() + shapePoints/2 + + return tabWidth + + + def CalcTabHeight(self, pageContainer): + """ Calculates the height of the input tab. """ + + if self._tabHeight: + return self._tabHeight + + pc = pageContainer + dc = wx.MemoryDC() + dc.SelectObject(wx.EmptyBitmap(1,1)) + + # For GTK it seems that we must do this steps in order + # for the tabs will get the proper height on initialization + # on MSW, preforming these steps yields wierd results + normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + boldFont = normalFont + +# if "__WXGTK__" in wx.PlatformInfo: +# boldFont.SetWeight(wx.FONTWEIGHT_BOLD) +# dc.SetFont(boldFont) + + height = dc.GetCharHeight() + + tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding + + self._tabHeight = tabHeight + + return tabHeight + + + def DrawTabs(self, pageContainer, dc): + """ Actually draws the tabs in L{FlatNotebook}.""" + + pc = pageContainer + if "__WXMAC__" in wx.PlatformInfo: + # Works well on MSW & GTK, however this lines should be skipped on MAC + if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec): + pc.Hide() + return + + # Get the text hight + tabHeight = self.CalcTabHeight(pageContainer) + style = pc.GetParent().GetWindowStyleFlag() + + # Calculate the number of rows required for drawing the tabs + rect = pc.GetClientRect() + clientWidth = rect.GetWidth() + + # Set the maximum client size + pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight) + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + + if style & FNB_VC71: + backBrush = wx.Brush(wx.Colour(247, 243, 233)) + else: + backBrush = wx.Brush(pc._tabAreaColor) + + noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)) + selBrush = wx.Brush(pc._activeTabColor) + + size = pc.GetSize() + + # Background + dc.SetTextBackground((style & FNB_VC71 and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0]) + dc.SetTextForeground(pc._activeTextColor) + dc.SetBrush(backBrush) + + # If border style is set, set the pen to be border pen + if pc.HasFlag(FNB_TABS_BORDER_SIMPLE): + dc.SetPen(borderPen) + else: + colr = (pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0] + dc.SetPen(wx.Pen(colr)) + + if pc.HasFlag(FNB_FF2): + lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0] + rect = pc.GetClientRect() + PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor)) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + + dc.DrawRectangle(0, 0, size.x, size.y) + + # We always draw the bottom/upper line of the tabs + # regradless the style + dc.SetPen(borderPen) + + if not pc.HasFlag(FNB_FF2): + self.DrawTabsLine(pc, dc) + + # Restore the pen + dc.SetPen(borderPen) + + if pc.HasFlag(FNB_VC71): + + greyLineYVal = (pc.HasFlag(FNB_BOTTOM) and [0] or [size.y - 2])[0] + whiteLineYVal = (pc.HasFlag(FNB_BOTTOM) and [3] or [size.y - 3])[0] + + pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)) + dc.SetPen(pen) + + # Draw thik grey line between the windows area and + # the tab area + for num in xrange(3): + dc.DrawLine(0, greyLineYVal + num, size.x, greyLineYVal + num) + + wbPen = (pc.HasFlag(FNB_BOTTOM) and [wx.BLACK_PEN] or [wx.WHITE_PEN])[0] + dc.SetPen(wbPen) + dc.DrawLine(1, whiteLineYVal, size.x - 1, whiteLineYVal) + + # Restore the pen + dc.SetPen(borderPen) + + # Draw labels + normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + boldFont.SetWeight(wx.FONTWEIGHT_BOLD) + dc.SetFont(boldFont) + + posx = pc._pParent.GetPadding() + + # Add padding for LeftArrow button if necessary + if not pc.HasFlag(FNB_NO_NAV_BUTTONS): + posx += 12 + + # Update all the tabs from 0 to 'pc._nFrom' to be non visible + for i in xrange(pc._nFrom): + + pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1)) + pc._pagesInfoVec[i].GetRegion().Clear() + + count = pc._nFrom + + #---------------------------------------------------------- + # Go over and draw the visible tabs + #---------------------------------------------------------- + x1 = x2 = -1 + for i in xrange(pc._nFrom, len(pc._pagesInfoVec)): + + dc.SetPen(borderPen) + + if not pc.HasFlag(FNB_FF2): + dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0]) + + # Now set the font to the correct font + dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0]) + + # Add the padding to the tab width + # Tab width: + # +-----------------------------------------------------------+ + # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING | + # +-----------------------------------------------------------+ + tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight) + + # Check if we can draw more + if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth: + break + + count = count + 1 + + # By default we clean the tab region + pc._pagesInfoVec[i].GetRegion().Clear() + + # Clean the 'x' buttn on the tab. + # A 'Clean' rectangle, is a rectangle with width or height + # with values lower than or equal to 0 + pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1)) + + # Draw the tab (border, text, image & 'x' on tab) + self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus) + + if pc.GetSelection() == i: + x1 = posx + x2 = posx + tabWidth + 2 + + # Restore the text forground + dc.SetTextForeground(pc._activeTextColor) + + # Update the tab position & size + posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0] + + pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy)) + pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight)) + self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[i]) + + posx += tabWidth + + # Update all tabs that can not fit into the screen as non-visible + for i in xrange(count, len(pc._pagesInfoVec)): + pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1)) + pc._pagesInfoVec[i].GetRegion().Clear() + + # Draw the left/right/close buttons + # Left arrow + self.DrawLeftArrow(pc, dc) + self.DrawRightArrow(pc, dc) + self.DrawX(pc, dc) + self.DrawDropDownArrow(pc, dc) + + if pc.HasFlag(FNB_FF2): + self.DrawTabsLine(pc, dc, x1, x2) + + + def DrawFocusRectangle(self, dc, pageContainer, page): + """ Draws a focus rectangle like the native Notebooks. """ + + if not page._hasFocus: + return + + tabPos = page.GetPosition() + if pageContainer.GetParent().GetWindowStyleFlag() & FNB_VC8: + vc8ShapeLen = self.CalcTabHeight(pageContainer) - VERTICAL_BORDER_PADDING - 2 + tabPos.x += vc8ShapeLen + + rect = wx.RectPS(tabPos, page.GetSize()) + rect = wx.Rect(rect.x+5, rect.y+2, rect.GetWidth()-6, rect.height-8) + + if wx.Platform == '__WXMAC__': + rect.SetWidth(rect.GetWidth() + 3) + rect.SetX(rect.GetX() - 2) + + if pageContainer.GetParent().GetWindowStyleFlag() & FNB_BOTTOM: + rect.SetY(rect.GetY() + 3) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.SetPen(self._focusPen) + dc.DrawRoundedRectangleRect(rect, 2) + + + def DrawDragHint(self, pc, tabIdx): + """ + Draws tab drag hint, the default implementation is to do nothing. + You can override this function to provide a nice feedback to user. + """ + + pass + + + def NumberTabsCanFit(self, pageContainer, fr=-1): + + pc = pageContainer + + rect = pc.GetClientRect() + clientWidth = rect.GetWidth() + + vTabInfo = [] + + tabHeight = self.CalcTabHeight(pageContainer) + + # The drawing starts from posx + posx = pc._pParent.GetPadding() + + if fr < 0: + fr = pc._nFrom + + for i in xrange(fr, len(pc._pagesInfoVec)): + + tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight) + if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth: + break; + + # Add a result to the returned vector + tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight) + vTabInfo.append(tabRect) + + # Advance posx + posx += tabWidth + FNB_HEIGHT_SPACER + + return vTabInfo + + +# ---------------------------------------------------------------------------- # +# Class FNBRendererMgr +# A manager that handles all the renderers defined below and calls the +# appropriate one when drawing is needed +# ---------------------------------------------------------------------------- # + +class FNBRendererMgr: + """ + This class represents a manager that handles all the 4 renderers defined + and calls the appropriate one when drawing is needed. + """ + + def __init__(self): + """ Default class constructor. """ + + # register renderers + + self._renderers = {} + self._renderers.update({-1: FNBRendererDefault()}) + self._renderers.update({FNB_VC71: FNBRendererVC71()}) + self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()}) + self._renderers.update({FNB_VC8: FNBRendererVC8()}) + self._renderers.update({FNB_FF2: FNBRendererFirefox2()}) + + + def GetRenderer(self, style): + """ Returns the current renderer based on the style selected. """ + + if style & FNB_VC71: + return self._renderers[FNB_VC71] + + if style & FNB_FANCY_TABS: + return self._renderers[FNB_FANCY_TABS] + + if style & FNB_VC8: + return self._renderers[FNB_VC8] + + if style & FNB_FF2: + return self._renderers[FNB_FF2] + + # the default is to return the default renderer + return self._renderers[-1] + + +#------------------------------------------ +# Default renderer +#------------------------------------------ + +class FNBRendererDefault(FNBRenderer): + """ + This class handles the drawing of tabs using the I{Standard} renderer. + """ + + def __init__(self): + """ Default class constructor. """ + + FNBRenderer.__init__(self) + + + def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus): + """ Draws a tab using the I{Standard} style. """ + + # Default style + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + pc = pageContainer + + tabPoints = [wx.Point() for ii in xrange(7)] + tabPoints[0].x = posx + tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0] + + tabPoints[1].x = int(posx+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi)) + tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0] + + tabPoints[2].x = tabPoints[1].x+2 + tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[3].x = int(posx+tabWidth-(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))-2 + tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[4].x = tabPoints[3].x+2 + tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0] + + tabPoints[5].x = int(tabPoints[4].x+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi)) + tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0] + + tabPoints[6].x = tabPoints[0].x + tabPoints[6].y = tabPoints[0].y + + if tabIdx == pc.GetSelection(): + + # Draw the tab as rounded rectangle + dc.DrawPolygon(tabPoints) + + else: + + if tabIdx != pc.GetSelection() - 1: + + # Draw a vertical line to the right of the text + pt1x = tabPoints[5].x + pt1y = (pc.HasFlag(FNB_BOTTOM) and [4] or [tabHeight - 6])[0] + pt2x = tabPoints[5].x + pt2y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 4] or [4])[0] + dc.DrawLine(pt1x, pt1y, pt2x, pt2y) + + if tabIdx == pc.GetSelection(): + + savePen = dc.GetPen() + whitePen = wx.Pen(wx.WHITE) + whitePen.SetWidth(1) + dc.SetPen(whitePen) + + secPt = wx.Point(tabPoints[5].x + 1, tabPoints[5].y) + dc.DrawLine(tabPoints[0].x, tabPoints[0].y, secPt.x, secPt.y) + + # Restore the pen + dc.SetPen(savePen) + + # ----------------------------------- + # Text and image drawing + # ----------------------------------- + + # Text drawing offset from the left border of the + # rectangle + + # The width of the images are 16 pixels + padding = pc.GetParent().GetPadding() + shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi)) + hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1 + imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0] + + if hasImage: + textOffset = 2*pc._pParent._nPadding + 16 + shapePoints/2 + else: + textOffset = pc._pParent._nPadding + shapePoints/2 + + textOffset += 2 + + if tabIdx != pc.GetSelection(): + + # Set the text background to be like the vertical lines + dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour()) + + if hasImage: + + imageXOffset = textOffset - 16 - padding + pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc, + posx + imageXOffset, imageYCoord, + wx.IMAGELIST_DRAW_TRANSPARENT, True) + + dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord) + + # draw 'x' on tab (if enabled) + if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection(): + + textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx)) + tabCloseButtonXCoord = posx + textOffset + textWidth + 1 + + # take a bitmap from the position of the 'x' button (the x on tab button) + # this bitmap will be used later to delete old buttons + tabCloseButtonYCoord = imageYCoord + x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16) + + # Draw the tab + self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) + + +#------------------------------------------ +# Firefox2 renderer +#------------------------------------------ +class FNBRendererFirefox2(FNBRenderer): + """ + This class handles the drawing of tabs using the I{Firefox 2} renderer. + """ + + def __init__(self): + """ Default class constructor. """ + + FNBRenderer.__init__(self) + + + def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus): + """ Draws a tab using the I{Firefox 2} style. """ + + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + pc = pageContainer + + tabPoints = [wx.Point() for indx in xrange(7)] + tabPoints[0].x = posx + 2 + tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0] + + tabPoints[1].x = tabPoints[0].x + tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0] + + tabPoints[2].x = tabPoints[1].x+2 + tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[3].x = posx + tabWidth - 2 + tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[4].x = tabPoints[3].x + 2 + tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0] + + tabPoints[5].x = tabPoints[4].x + tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0] + + tabPoints[6].x = tabPoints[0].x + tabPoints[6].y = tabPoints[0].y + + #------------------------------------ + # Paint the tab with gradient + #------------------------------------ + rr = wx.RectPP(tabPoints[2], tabPoints[5]) + DrawButton(dc, rr, pc.GetSelection() == tabIdx , not pc.HasFlag(FNB_BOTTOM)) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.SetPen(borderPen) + + # Draw the tab as rounded rectangle + dc.DrawPolygon(tabPoints) + + # ----------------------------------- + # Text and image drawing + # ----------------------------------- + + # The width of the images are 16 pixels + padding = pc.GetParent().GetPadding() + shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi)) + hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1 + imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0] + + if hasImage: + textOffset = 2*padding + 16 + shapePoints/2 + else: + textOffset = padding + shapePoints/2 + + textOffset += 2 + + if tabIdx != pc.GetSelection(): + + # Set the text background to be like the vertical lines + dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour()) + + if hasImage: + imageXOffset = textOffset - 16 - padding + pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc, + posx + imageXOffset, imageYCoord, + wx.IMAGELIST_DRAW_TRANSPARENT, True) + + dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord) + + # draw 'x' on tab (if enabled) + if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection(): + + textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx)) + tabCloseButtonXCoord = posx + textOffset + textWidth + 1 + + # take a bitmap from the position of the 'x' button (the x on tab button) + # this bitmap will be used later to delete old buttons + tabCloseButtonYCoord = imageYCoord + x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16) + + # Draw the tab + self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) + + +#------------------------------------------------------------------ +# Visual studio 7.1 +#------------------------------------------------------------------ + +class FNBRendererVC71(FNBRenderer): + """ + This class handles the drawing of tabs using the I{VC71} renderer. + """ + + def __init__(self): + """ Default class constructor. """ + + FNBRenderer.__init__(self) + + + def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus): + """ Draws a tab using the I{VC71} style. """ + + # Visual studio 7.1 style + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + pc = pageContainer + + dc.SetPen((tabIdx == pc.GetSelection() and [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [borderPen])[0]) + dc.SetBrush((tabIdx == pc.GetSelection() and [wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [wx.Brush(wx.Colour(247, 243, 233))])[0]) + + if tabIdx == pc.GetSelection(): + + posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0] + tabH = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 5] or [tabHeight - 3])[0] + dc.DrawRectangle(posx, posy, tabWidth, tabH) + + # Draw a black line on the left side of the + # rectangle + dc.SetPen(wx.BLACK_PEN) + + blackLineY1 = VERTICAL_BORDER_PADDING + blackLineY2 = tabH + dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2) + + # To give the tab more 3D look we do the following + # Incase the tab is on top, + # Draw a thik white line on topof the rectangle + # Otherwise, draw a thin (1 pixel) black line at the bottom + + pen = wx.Pen((pc.HasFlag(FNB_BOTTOM) and [wx.BLACK] or [wx.WHITE])[0]) + dc.SetPen(pen) + whiteLinePosY = (pc.HasFlag(FNB_BOTTOM) and [blackLineY2] or [VERTICAL_BORDER_PADDING ])[0] + dc.DrawLine(posx , whiteLinePosY, posx + tabWidth + 1, whiteLinePosY) + + # Draw a white vertical line to the left of the tab + dc.SetPen(wx.WHITE_PEN) + if not pc.HasFlag(FNB_BOTTOM): + blackLineY2 += 1 + + dc.DrawLine(posx, blackLineY1, posx, blackLineY2) + + else: + + # We dont draw a rectangle for non selected tabs, but only + # vertical line on the left + + blackLineY1 = (pc.HasFlag(FNB_BOTTOM) and [VERTICAL_BORDER_PADDING + 2] or [VERTICAL_BORDER_PADDING + 1])[0] + blackLineY2 = pc.GetSize().y - 5 + dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2) + + # ----------------------------------- + # Text and image drawing + # ----------------------------------- + + # Text drawing offset from the left border of the + # rectangle + + # The width of the images are 16 pixels + padding = pc.GetParent().GetPadding() + hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1 + imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [5] or [8])[0] + + if hasImage: + textOffset = 2*pc._pParent._nPadding + 16 + else: + textOffset = pc._pParent._nPadding + + if tabIdx != pc.GetSelection(): + + # Set the text background to be like the vertical lines + dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour()) + + if hasImage: + + imageXOffset = textOffset - 16 - padding + pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc, + posx + imageXOffset, imageYCoord, + wx.IMAGELIST_DRAW_TRANSPARENT, True) + + dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord) + + # draw 'x' on tab (if enabled) + if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection(): + + textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx)) + tabCloseButtonXCoord = posx + textOffset + textWidth + 1 + + # take a bitmap from the position of the 'x' button (the x on tab button) + # this bitmap will be used later to delete old buttons + tabCloseButtonYCoord = imageYCoord + x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16) + + # Draw the tab + self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) + + +#------------------------------------------------------------------ +# Fancy style +#------------------------------------------------------------------ + +class FNBRendererFancy(FNBRenderer): + """ + This class handles the drawing of tabs using the I{Fancy} renderer. + """ + + def __init__(self): + """ Default class constructor. """ + + FNBRenderer.__init__(self) + + + def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus): + """ Draws a tab using the I{Fancy} style, similar to VC71 but with gradients. """ + + # Fancy tabs - like with VC71 but with the following differences: + # - The Selected tab is colored with gradient color + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + pc = pageContainer + + pen = (tabIdx == pc.GetSelection() and [wx.Pen(pc._pParent.GetBorderColour())] or [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))])[0] + + if tabIdx == pc.GetSelection(): + + posy = (pc.HasFlag(FNB_BOTTOM) and [2] or [VERTICAL_BORDER_PADDING])[0] + th = tabHeight - 5 + + rect = wx.Rect(posx, posy, tabWidth, th) + + col2 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourTo()] or [pc._pParent.GetGradientColourFrom()])[0] + col1 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourFrom()] or [pc._pParent.GetGradientColourTo()])[0] + + PaintStraightGradientBox(dc, rect, col1, col2) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.SetPen(pen) + dc.DrawRectangleRect(rect) + + # erase the bottom/top line of the rectangle + dc.SetPen(wx.Pen(pc._pParent.GetGradientColourFrom())) + if pc.HasFlag(FNB_BOTTOM): + dc.DrawLine(rect.x, 2, rect.x + rect.GetWidth(), 2) + else: + dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.GetWidth(), rect.y + rect.height - 1) + + else: + + # We dont draw a rectangle for non selected tabs, but only + # vertical line on the left + dc.SetPen(borderPen) + dc.DrawLine(posx + tabWidth, VERTICAL_BORDER_PADDING + 3, posx + tabWidth, tabHeight - 4) + + + # ----------------------------------- + # Text and image drawing + # ----------------------------------- + + # Text drawing offset from the left border of the + # rectangle + + # The width of the images are 16 pixels + padding = pc.GetParent().GetPadding() + hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1 + imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0] + + if hasImage: + textOffset = 2*pc._pParent._nPadding + 16 + else: + textOffset = pc._pParent._nPadding + + textOffset += 2 + + if tabIdx != pc.GetSelection(): + + # Set the text background to be like the vertical lines + dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour()) + + if hasImage: + + imageXOffset = textOffset - 16 - padding + pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc, + posx + imageXOffset, imageYCoord, + wx.IMAGELIST_DRAW_TRANSPARENT, True) + + dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord) + + # draw 'x' on tab (if enabled) + if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection(): + + textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx)) + tabCloseButtonXCoord = posx + textOffset + textWidth + 1 + + # take a bitmap from the position of the 'x' button (the x on tab button) + # this bitmap will be used later to delete old buttons + tabCloseButtonYCoord = imageYCoord + x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16) + + # Draw the tab + self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) + + +#------------------------------------------------------------------ +# Visual studio 2005 (VS8) +#------------------------------------------------------------------ +class FNBRendererVC8(FNBRenderer): + """ + This class handles the drawing of tabs using the I{VC8} renderer. + """ + + def __init__(self): + """ Default class constructor. """ + + FNBRenderer.__init__(self) + self._first = True + self._factor = 1 + + + def DrawTabs(self, pageContainer, dc): + """ Draws all the tabs using VC8 style. Overloads The DrawTabs method in parent class. """ + + pc = pageContainer + + if "__WXMAC__" in wx.PlatformInfo: + # Works well on MSW & GTK, however this lines should be skipped on MAC + if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec): + pc.Hide() + return + + # Get the text hight + tabHeight = self.CalcTabHeight(pageContainer) + + # Set the font for measuring the tab height + normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + boldFont.SetWeight(wx.FONTWEIGHT_BOLD) + + # Calculate the number of rows required for drawing the tabs + rect = pc.GetClientRect() + + # Set the maximum client size + pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight) + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + + # Create brushes + backBrush = wx.Brush(pc._tabAreaColor) + noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)) + selBrush = wx.Brush(pc._activeTabColor) + size = pc.GetSize() + + # Background + dc.SetTextBackground(pc.GetBackgroundColour()) + dc.SetTextForeground(pc._activeTextColor) + + # If border style is set, set the pen to be border pen + if pc.HasFlag(FNB_TABS_BORDER_SIMPLE): + dc.SetPen(borderPen) + else: + dc.SetPen(wx.TRANSPARENT_PEN) + + lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0] + + # For VC8 style, we color the tab area in gradient coloring + lightcolour = LightColour(pc._tabAreaColor, lightFactor) + PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, lightcolour) + + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.DrawRectangle(0, 0, size.x, size.y) + + # We always draw the bottom/upper line of the tabs + # regradless the style + dc.SetPen(borderPen) + self.DrawTabsLine(pc, dc) + + # Restore the pen + dc.SetPen(borderPen) + + # Draw labels + dc.SetFont(boldFont) + + # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible + for i in xrange(pc._nFrom): + + pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1)) + pc._pagesInfoVec[i].GetRegion().Clear() + + # Draw the visible tabs, in VC8 style, we draw them from right to left + vTabsInfo = self.NumberTabsCanFit(pc) + + activeTabPosx = 0 + activeTabWidth = 0 + activeTabHeight = 0 + + for cur in xrange(len(vTabsInfo)-1, -1, -1): + + # 'i' points to the index of the currently drawn tab + # in pc.GetPageInfoVector() vector + i = pc._nFrom + cur + dc.SetPen(borderPen) + dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0]) + + # Now set the font to the correct font + dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0]) + + # Add the padding to the tab width + # Tab width: + # +-----------------------------------------------------------+ + # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING | + # +-----------------------------------------------------------+ + + tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight) + posx = vTabsInfo[cur].x + + # By default we clean the tab region + # incase we use the VC8 style which requires + # the region, it will be filled by the function + # drawVc8Tab + pc._pagesInfoVec[i].GetRegion().Clear() + + # Clean the 'x' buttn on the tab + # 'Clean' rectanlge is a rectangle with width or height + # with values lower than or equal to 0 + pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1)) + + # Draw the tab + # Incase we are drawing the active tab + # we need to redraw so it will appear on top + # of all other tabs + + # when using the vc8 style, we keep the position of the active tab so we will draw it again later + if i == pc.GetSelection() and pc.HasFlag(FNB_VC8): + + activeTabPosx = posx + activeTabWidth = tabWidth + activeTabHeight = tabHeight + + else: + + self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus) + + # Restore the text forground + dc.SetTextForeground(pc._activeTextColor) + + # Update the tab position & size + pc._pagesInfoVec[i].SetPosition(wx.Point(posx, VERTICAL_BORDER_PADDING)) + pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight)) + + # Incase we are in VC8 style, redraw the active tab (incase it is visible) + if pc.GetSelection() >= pc._nFrom and pc.GetSelection() < pc._nFrom + len(vTabsInfo): + + self.DrawTab(pc, dc, activeTabPosx, pc.GetSelection(), activeTabWidth, activeTabHeight, pc._nTabXButtonStatus) + + # Update all tabs that can not fit into the screen as non-visible + for xx in xrange(pc._nFrom + len(vTabsInfo), len(pc._pagesInfoVec)): + + pc._pagesInfoVec[xx].SetPosition(wx.Point(-1, -1)) + pc._pagesInfoVec[xx].GetRegion().Clear() + + # Draw the left/right/close buttons + # Left arrow + self.DrawLeftArrow(pc, dc) + self.DrawRightArrow(pc, dc) + self.DrawX(pc, dc) + self.DrawDropDownArrow(pc, dc) + + + def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus): + """ Draws a tab using VC8 style. """ + + pc = pageContainer + borderPen = wx.Pen(pc._pParent.GetBorderColour()) + tabPoints = [wx.Point() for ii in xrange(8)] + + # If we draw the first tab or the active tab, + # we draw a full tab, else we draw a truncated tab + # + # X(2) X(3) + # X(1) X(4) + # + # X(5) + # + # X(0),(7) X(6) + # + # + + tabPoints[0].x = (pc.HasFlag(FNB_BOTTOM) and [posx] or [posx+self._factor])[0] + tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 3])[0] + + tabPoints[1].x = tabPoints[0].x + tabHeight - VERTICAL_BORDER_PADDING - 3 - self._factor + tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0] + + tabPoints[2].x = tabPoints[1].x + 4 + tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[3].x = tabPoints[2].x + tabWidth - 2 + tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0] + + tabPoints[4].x = tabPoints[3].x + 1 + tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabPoints[3].y - 1] or [tabPoints[3].y + 1])[0] + + tabPoints[5].x = tabPoints[4].x + 1 + tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [(tabPoints[4].y - 1)] or [tabPoints[4].y + 1])[0] + + tabPoints[6].x = tabPoints[2].x + tabWidth + tabPoints[6].y = tabPoints[0].y + + tabPoints[7].x = tabPoints[0].x + tabPoints[7].y = tabPoints[0].y + + pc._pagesInfoVec[tabIdx].SetRegion(tabPoints) + + # Draw the polygon + br = dc.GetBrush() + dc.SetBrush(wx.Brush((tabIdx == pc.GetSelection() and [pc._activeTabColor] or [pc._colorTo])[0])) + dc.SetPen(wx.Pen((tabIdx == pc.GetSelection() and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0])) + dc.DrawPolygon(tabPoints) + + # Restore the brush + dc.SetBrush(br) + rect = pc.GetClientRect() + + if tabIdx != pc.GetSelection() and not pc.HasFlag(FNB_BOTTOM): + + # Top default tabs + dc.SetPen(wx.Pen(pc._pParent.GetBorderColour())) + lineY = rect.height + curPen = dc.GetPen() + curPen.SetWidth(1) + dc.SetPen(curPen) + dc.DrawLine(posx, lineY, posx+rect.GetWidth(), lineY) + + # Incase we are drawing the selected tab, we draw the border of it as well + # but without the bottom (upper line incase of wxBOTTOM) + if tabIdx == pc.GetSelection(): + + borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)) + dc.SetPen(borderPen) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.DrawPolygon(tabPoints) + + # Delete the bottom line (or the upper one, incase we use wxBOTTOM) + dc.SetPen(wx.WHITE_PEN) + dc.DrawLine(tabPoints[0].x, tabPoints[0].y, tabPoints[6].x, tabPoints[6].y) + + self.FillVC8GradientColour(pc, dc, tabPoints, tabIdx == pc.GetSelection(), tabIdx) + + # Draw a thin line to the right of the non-selected tab + if tabIdx != pc.GetSelection(): + + dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))) + dc.DrawLine(tabPoints[4].x-1, tabPoints[4].y, tabPoints[5].x-1, tabPoints[5].y) + dc.DrawLine(tabPoints[5].x-1, tabPoints[5].y, tabPoints[6].x-1, tabPoints[6].y) + + # Text drawing offset from the left border of the + # rectangle + + # The width of the images are 16 pixels + vc8ShapeLen = tabHeight - VERTICAL_BORDER_PADDING - 2 + if pc.TabHasImage(tabIdx): + textOffset = 2*pc._pParent.GetPadding() + 16 + vc8ShapeLen + else: + textOffset = pc._pParent.GetPadding() + vc8ShapeLen + + # Draw the image for the tab if any + imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0] + + if pc.TabHasImage(tabIdx): + + imageXOffset = textOffset - 16 - pc._pParent.GetPadding() + pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc, + posx + imageXOffset, imageYCoord, + wx.IMAGELIST_DRAW_TRANSPARENT, True) + + boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) + + # if selected tab, draw text in bold + if tabIdx == pc.GetSelection(): + boldFont.SetWeight(wx.FONTWEIGHT_BOLD) + + dc.SetFont(boldFont) + dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord) + + # draw 'x' on tab (if enabled) + if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection(): + + textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx)) + tabCloseButtonXCoord = posx + textOffset + textWidth + 1 + + # take a bitmap from the position of the 'x' button (the x on tab button) + # this bitmap will be used later to delete old buttons + tabCloseButtonYCoord = imageYCoord + x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16) + + # Draw the tab + self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus) + + self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[tabIdx]) + + + def FillVC8GradientColour(self, pageContainer, dc, tabPoints, bSelectedTab, tabIdx): + """ Fills a tab with a gradient shading. """ + + # calculate gradient coefficients + pc = pageContainer + + if self._first: + self._first = False + pc._colorTo = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 0) + pc._colorFrom = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 60) + + col2 = pc._pParent.GetGradientColourTo() + col1 = pc._pParent.GetGradientColourFrom() + + # If colorful tabs style is set, override the tab color + if pc.HasFlag(FNB_COLORFUL_TABS): + + if not pc._pagesInfoVec[tabIdx].GetColour(): + + # First time, generate color, and keep it in the vector + tabColor = RandomColour() + pc._pagesInfoVec[tabIdx].SetColour(tabColor) + + if pc.HasFlag(FNB_BOTTOM): + + col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50) + col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80) + + else: + + col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50) + col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80) + + size = abs(tabPoints[2].y - tabPoints[0].y) - 1 + + rf, gf, bf = 0, 0, 0 + rstep = float(col2.Red() - col1.Red())/float(size) + gstep = float(col2.Green() - col1.Green())/float(size) + bstep = float(col2.Blue() - col1.Blue())/float(size) + + y = tabPoints[0].y + + # If we are drawing the selected tab, we need also to draw a line + # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this + # by drawing the rectangle with transparent brush + # the line under the selected tab will be deleted by the drwaing loop + if bSelectedTab: + self.DrawTabsLine(pc, dc) + + while 1: + + if pc.HasFlag(FNB_BOTTOM): + + if y > tabPoints[0].y + size: + break + + else: + + if y < tabPoints[0].y - size: + break + + currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf) + + dc.SetPen((bSelectedTab and [wx.Pen(pc._activeTabColor)] or [wx.Pen(currCol)])[0]) + startX = self.GetStartX(tabPoints, y, pc.GetParent().GetWindowStyleFlag()) + endX = self.GetEndX(tabPoints, y, pc.GetParent().GetWindowStyleFlag()) + dc.DrawLine(startX, y, endX, y) + + # Draw the border using the 'edge' point + dc.SetPen(wx.Pen((bSelectedTab and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0])) + + dc.DrawPoint(startX, y) + dc.DrawPoint(endX, y) + + # Progress the color + rf += rstep + gf += gstep + bf += bstep + + if pc.HasFlag(FNB_BOTTOM): + y = y + 1 + else: + y = y - 1 + + + def GetStartX(self, tabPoints, y, style): + """ Returns the x start position of a tab. """ + + x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0 + + # We check the 3 points to the left + + bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0] + match = False + + if bBottomStyle: + + for i in xrange(3): + + if y >= tabPoints[i].y and y < tabPoints[i+1].y: + + x1 = tabPoints[i].x + x2 = tabPoints[i+1].x + y1 = tabPoints[i].y + y2 = tabPoints[i+1].y + match = True + break + + else: + + for i in xrange(3): + + if y <= tabPoints[i].y and y > tabPoints[i+1].y: + + x1 = tabPoints[i].x + x2 = tabPoints[i+1].x + y1 = tabPoints[i].y + y2 = tabPoints[i+1].y + match = True + break + + if not match: + return tabPoints[2].x + + # According to the equation y = ax + b => x = (y-b)/a + # We know the first 2 points + + if x2 == x1: + return x2 + else: + a = (y2 - y1)/(x2 - x1) + + b = y1 - ((y2 - y1)/(x2 - x1))*x1 + + if a == 0: + return int(x1) + + x = (y - b)/a + + return int(x) + + + def GetEndX(self, tabPoints, y, style): + """ Returns the x end position of a tab. """ + + x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0 + + # We check the 3 points to the left + bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0] + match = False + + if bBottomStyle: + + for i in xrange(7, 3, -1): + + if y >= tabPoints[i].y and y < tabPoints[i-1].y: + + x1 = tabPoints[i].x + x2 = tabPoints[i-1].x + y1 = tabPoints[i].y + y2 = tabPoints[i-1].y + match = True + break + + else: + + for i in xrange(7, 3, -1): + + if y <= tabPoints[i].y and y > tabPoints[i-1].y: + + x1 = tabPoints[i].x + x2 = tabPoints[i-1].x + y1 = tabPoints[i].y + y2 = tabPoints[i-1].y + match = True + break + + if not match: + return tabPoints[3].x + + # According to the equation y = ax + b => x = (y-b)/a + # We know the first 2 points + + # Vertical line + if x1 == x2: + return int(x1) + + a = (y2 - y1)/(x2 - x1) + b = y1 - ((y2 - y1)/(x2 - x1))*x1 + + if a == 0: + return int(x1) + + x = (y - b)/a + + return int(x) + + + def NumberTabsCanFit(self, pageContainer, fr=-1): + """ Returns the number of tabs that can fit in the visible area. """ + + pc = pageContainer + + rect = pc.GetClientRect() + clientWidth = rect.GetWidth() + + # Empty results + vTabInfo = [] + tabHeight = self.CalcTabHeight(pageContainer) + + # The drawing starts from posx + posx = pc._pParent.GetPadding() + + if fr < 0: + fr = pc._nFrom + + for i in xrange(fr, len(pc._pagesInfoVec)): + + vc8glitch = tabHeight + FNB_HEIGHT_SPACER + tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight) + + if posx + tabWidth + vc8glitch + self.GetButtonsAreaLength(pc) >= clientWidth: + break + + # Add a result to the returned vector + tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth, tabHeight) + vTabInfo.append(tabRect) + + # Advance posx + posx += tabWidth + FNB_HEIGHT_SPACER + + return vTabInfo + + +# ---------------------------------------------------------------------------- # +# Class FlatNotebook +# ---------------------------------------------------------------------------- # + +class FlatNotebook(wx.PyPanel): + """ + Display one or more windows in a notebook. + + B{Events}: + - B{EVT_FLATNOTEBOOK_PAGE_CHANGING}: sent when the active + page in the notebook is changing + - B{EVT_FLATNOTEBOOK_PAGE_CHANGED}: sent when the active + page in the notebook has changed + - B{EVT_FLATNOTEBOOK_PAGE_CLOSING}: sent when a page in the + notebook is closing + - B{EVT_FLATNOTEBOOK_PAGE_CLOSED}: sent when a page in the + notebook has been closed + - B{EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU}: sent when the user + clicks a tab in the notebook with the right mouse + button + """ + + def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, + style=0, name="FlatNotebook"): + """ + Default class constructor. + + All the parameters are as in wxPython class construction, except the + 'style': this can be assigned to whatever combination of FNB_* styles. + + """ + + self._bForceSelection = False + self._nPadding = 6 + self._nFrom = 0 + style |= wx.TAB_TRAVERSAL + self._pages = None + self._windows = [] + self._popupWin = None + self._naviIcon = None + + wx.PyPanel.__init__(self, parent, id, pos, size, style) + + self._pages = PageContainer(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style) + + self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey) + + self.Init() + + + def Init(self): + """ Initializes all the class attributes. """ + + self._pages._colorBorder = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW) + + self._mainSizer = wx.BoxSizer(wx.VERTICAL) + self.SetSizer(self._mainSizer) + + # The child panels will inherit this bg color, so leave it at the default value + #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE)) + + # Set default page height + dc = wx.ClientDC(self) + +# if "__WXGTK__" in wx.PlatformInfo: +# # For GTK it seems that we must do this steps in order +# # for the tabs will get the proper height on initialization +# # on MSW, preforming these steps yields wierd results +# boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) +# boldFont.SetWeight(wx.FONTWEIGHT_BOLD) +# dc.SetFont(boldFont) + + height = dc.GetCharHeight() + + tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding + + self._pages.SetSizeHints(-1, tabHeight) + # Add the tab container to the sizer + self._mainSizer.Insert(0, self._pages, 0, wx.EXPAND) + self._mainSizer.Layout() + + self._pages._nFrom = self._nFrom + self._pDropTarget = FNBDropTarget(self) + self.SetDropTarget(self._pDropTarget) + + + def DoGetBestSize(self): + """ Overrides DoGetBestSize to handle sizers nicely. """ + + if not self._windows: + # Something is better than nothing... no pages! + return wx.Size(20, 20) + + maxWidth = maxHeight = 0 + tabHeight = self.GetPageBestSize().height + + for win in self._windows: + # Loop over all the windows to get their best size + width, height = win.GetBestSize() + maxWidth, maxHeight = max(maxWidth, width), max(maxHeight, height) + + return wx.Size(maxWidth, maxHeight+tabHeight) + + + def SetActiveTabTextColour(self, textColour): + """ Sets the text colour for the active tab. """ + + self._pages._activeTextColor = textColour + + + def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer): + """ Handles the drop action from a DND operation. """ + + return self._pages.OnDropTarget(x, y, nTabPage, wnd_oldContainer) + + + def GetPreviousSelection(self): + """ Returns the previous selection. """ + + return self._pages._iPreviousActivePage + + + def AddPage(self, page, text, select=True, imageId=-1): + """ + Add a page to the L{FlatNotebook}. + + @param page: Specifies the new page. + @param text: Specifies the text for the new page. + @param select: Specifies whether the page should be selected. + @param imageId: Specifies the optional image index for the new page. + + Return value: + True if successful, False otherwise. + """ + + # sanity check + if not page: + return False + + # reparent the window to us + page.Reparent(self) + + # Add tab + bSelected = select or len(self._windows) == 0 + + if bSelected: + + bSelected = False + + # Check for selection and send events + oldSelection = self._pages._iActivePage + tabIdx = len(self._windows) + + event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId()) + event.SetSelection(tabIdx) + event.SetOldSelection(oldSelection) + event.SetEventObject(self) + + if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0: + bSelected = True + + curSel = self._pages.GetSelection() + + if not self._pages.IsShown(): + self._pages.Show() + + self._pages.AddPage(text, bSelected, imageId) + self._windows.append(page) + + self.Freeze() + + # Check if a new selection was made + if bSelected: + + if curSel >= 0: + + # Remove the window from the main sizer + self._mainSizer.Detach(self._windows[curSel]) + self._windows[curSel].Hide() + + if self.GetWindowStyleFlag() & FNB_BOTTOM: + + self._mainSizer.Insert(0, page, 1, wx.EXPAND) + + else: + + # We leave a space of 1 pixel around the window + self._mainSizer.Add(page, 1, wx.EXPAND) + + # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event + event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED) + event.SetOldSelection(oldSelection) + self.GetEventHandler().ProcessEvent(event) + + else: + + # Hide the page + page.Hide() + + self.Thaw() + self._mainSizer.Layout() + self.Refresh() + + return True + + + def SetImageList(self, imageList): + """ Sets the image list for the page control. """ + + self._pages.SetImageList(imageList) + + + def AssignImageList(self, imageList): + """ Assigns the image list for the page control. """ + + self._pages.AssignImageList(imageList) + + + def GetImageList(self): + """ Returns the associated image list. """ + + return self._pages.GetImageList() + + + def InsertPage(self, indx, page, text, select=True, imageId=-1): + """ + Inserts a new page at the specified position. + + @param indx: Specifies the position of the new page. + @param page: Specifies the new page. + @param text: Specifies the text for the new page. + @param select: Specifies whether the page should be selected. + @param imageId: Specifies the optional image index for the new page. + + Return value: + True if successful, False otherwise. + """ + + # sanity check + if not page: + return False + + # reparent the window to us + page.Reparent(self) + + if not self._windows: + + self.AddPage(page, text, select, imageId) + return True + + # Insert tab + bSelected = select or not self._windows + curSel = self._pages.GetSelection() + + indx = max(0, min(indx, len(self._windows))) + + if indx <= len(self._windows): + + self._windows.insert(indx, page) + + else: + + self._windows.append(page) + + if bSelected: + + bSelected = False + + # Check for selection and send events + oldSelection = self._pages._iActivePage + + event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId()) + event.SetSelection(indx) + event.SetOldSelection(oldSelection) + event.SetEventObject(self) + + if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0: + bSelected = True + + self._pages.InsertPage(indx, text, bSelected, imageId) + + if indx <= curSel: + curSel = curSel + 1 + + self.Freeze() + + # Check if a new selection was made + if bSelected: + + if curSel >= 0: + + # Remove the window from the main sizer + self._mainSizer.Detach(self._windows[curSel]) + self._windows[curSel].Hide() + + self._pages.SetSelection(indx) + + # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event + event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED) + event.SetOldSelection(oldSelection) + self.GetEventHandler().ProcessEvent(event) + + else: + + # Hide the page + page.Hide() + + self.Thaw() + self._mainSizer.Layout() + self.Refresh() + + return True + + + def SetSelection(self, page): + """ + Sets the selection for the given page. + The call to this function generates the page changing events + """ + + if page >= len(self._windows) or not self._windows: + return + + # Support for disabed tabs + if not self._pages.GetEnabled(page) and len(self._windows) > 1 and not self._bForceSelection: + return + + curSel = self._pages.GetSelection() + + # program allows the page change + self.Freeze() + if curSel >= 0: + + # Remove the window from the main sizer + self._mainSizer.Detach(self._windows[curSel]) + self._windows[curSel].Hide() + + if self.GetWindowStyleFlag() & FNB_BOTTOM: + + self._mainSizer.Insert(0, self._windows[page], 1, wx.EXPAND) + + else: + + # We leave a space of 1 pixel around the window + self._mainSizer.Add(self._windows[page], 1, wx.EXPAND) + + self._windows[page].Show() + self.Thaw() + + self._mainSizer.Layout() + + if page != self._pages._iActivePage: + # there is a real page changing + self._pages._iPreviousActivePage = self._pages._iActivePage + + self._pages._iActivePage = page + self._pages.DoSetSelection(page) + + + def DeletePage(self, page): + """ + Deletes the specified page, and the associated window. + The call to this function generates the page changing events. + """ + + if page >= len(self._windows) or page < 0: + return + + # Fire a closing event + event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId()) + event.SetSelection(page) + event.SetEventObject(self) + self.GetEventHandler().ProcessEvent(event) + + # The event handler allows it? + if not event.IsAllowed(): + return + + self.Freeze() + + # Delete the requested page + pageRemoved = self._windows[page] + + # If the page is the current window, remove it from the sizer + # as well + if page == self._pages.GetSelection(): + self._mainSizer.Detach(pageRemoved) + + # Remove it from the array as well + self._windows.pop(page) + + # Now we can destroy it in wxWidgets use Destroy instead of delete + pageRemoved.Destroy() + + self.Thaw() + + self._pages.DoDeletePage(page) + self.Refresh() + self.Update() + + # Fire a closed event + closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId()) + closedEvent.SetSelection(page) + closedEvent.SetEventObject(self) + self.GetEventHandler().ProcessEvent(closedEvent) + + + def DeleteAllPages(self): + """ Deletes all the pages. """ + + if not self._windows: + return False + + self.Freeze() + + for page in self._windows: + page.Destroy() + + self._windows = [] + self.Thaw() + + # Clear the container of the tabs as well + self._pages.DeleteAllPages() + return True + + + def GetCurrentPage(self): + """ Returns the currently selected notebook page or None. """ + + sel = self._pages.GetSelection() + if sel < 0 or sel >= len(self._windows): + return None + + return self._windows[sel] + + + def GetPage(self, page): + """ Returns the window at the given page position, or None. """ + + if page >= len(self._windows): + return None + + return self._windows[page] + + + def GetPageIndex(self, win): + """ Returns the index at which the window is found. """ + + try: + return self._windows.index(win) + except: + return -1 + + + def GetSelection(self): + """ Returns the currently selected page, or -1 if none was selected. """ + + return self._pages.GetSelection() + + + def AdvanceSelection(self, forward=True): + """ + Cycles through the tabs. + The call to this function generates the page changing events. + """ + + self._pages.AdvanceSelection(forward) + + + def GetPageCount(self): + """ Returns the number of pages in the L{FlatNotebook} control. """ + + return self._pages.GetPageCount() + + def SetNavigatorIcon(self, bmp): + """ Set the icon used by the L{TabNavigatorWindow} """ + if isinstance(bmp, wx.Bitmap) and bmp.IsOk(): + # Make sure image is proper size + if bmp.GetSize() != (16, 16): + img = bmp.ConvertToImage() + img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH) + bmp = wx.BitmapFromImage(img) + self._naviIcon = bmp + else: + raise TypeError, "SetNavigatorIcon requires a valid bitmap" + + def OnNavigationKey(self, event): + """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """ + + if event.IsWindowChange(): + if len(self._windows) == 0: + return + # change pages + if self.HasFlag(FNB_SMART_TABS): + if not self._popupWin: + self._popupWin = TabNavigatorWindow(self, self._naviIcon) + self._popupWin.SetReturnCode(wx.ID_OK) + self._popupWin.ShowModal() + self._pages.FireEvent(self._popupWin.GetSelection()) + self._popupWin.Destroy() + self._popupWin = None + else: + # a dialog is already opened + self._popupWin.OnNavigationKey(event) + return + else: + # change pages + self.AdvanceSelection(event.GetDirection()) + + else: + event.Skip() + + + def GetPageShapeAngle(self, page_index): + """ Returns the angle associated to a tab. """ + + if page_index < 0 or page_index >= len(self._pages._pagesInfoVec): + return None, False + + result = self._pages._pagesInfoVec[page_index].GetTabAngle() + return result, True + + + def SetPageShapeAngle(self, page_index, angle): + """ Sets the angle associated to a tab. """ + + if page_index < 0 or page_index >= len(self._pages._pagesInfoVec): + return + + if angle > 15: + return + + self._pages._pagesInfoVec[page_index].SetTabAngle(angle) + + + def SetAllPagesShapeAngle(self, angle): + """ Sets the angle associated to all the tab. """ + + if angle > 15: + return + + for ii in xrange(len(self._pages._pagesInfoVec)): + self._pages._pagesInfoVec[ii].SetTabAngle(angle) + + self.Refresh() + + + def GetPageBestSize(self): + """ Return the page best size. """ + + return self._pages.GetClientSize() + + + def SetPageText(self, page, text): + """ Sets the text for the given page. """ + + bVal = self._pages.SetPageText(page, text) + self._pages.Refresh() + + return bVal + + + def SetPadding(self, padding): + """ + Sets the amount of space around each page's icon and label, in pixels. + NB: only the horizontal padding is considered. + """ + + self._nPadding = padding.GetWidth() + + + def GetTabArea(self): + """ Returns the associated page. """ + + return self._pages + + + def GetPadding(self): + """ Returns the amount of space around each page's icon and label, in pixels. """ + + return self._nPadding + + + def SetWindowStyleFlag(self, style): + """ Sets the L{FlatNotebook} window style flags. """ + + wx.PyPanel.SetWindowStyleFlag(self, style) + renderer = self._pages._mgr.GetRenderer(self.GetWindowStyleFlag()) + renderer._tabHeight = None + + if self._pages: + + # For changing the tab position (i.e. placing them top/bottom) + # refreshing the tab container is not enough + self.SetSelection(self._pages._iActivePage) + + if not self._pages.HasFlag(FNB_HIDE_ON_SINGLE_TAB): + #For Redrawing the Tabs once you remove the Hide tyle + self._pages._ReShow() + + + def RemovePage(self, page): + """ Deletes the specified page, without deleting the associated window. """ + + if page >= len(self._windows): + return False + + # Fire a closing event + event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId()) + event.SetSelection(page) + event.SetEventObject(self) + self.GetEventHandler().ProcessEvent(event) + + # The event handler allows it? + if not event.IsAllowed(): + return False + + self.Freeze() + + # Remove the requested page + pageRemoved = self._windows[page] + + # If the page is the current window, remove it from the sizer + # as well + if page == self._pages.GetSelection(): + self._mainSizer.Detach(pageRemoved) + + # Remove it from the array as well + self._windows.pop(page) + self.Thaw() + + self._pages.DoDeletePage(page) + + return True + + + def SetRightClickMenu(self, menu): + """ Sets the popup menu associated to a right click on a tab. """ + + self._pages._pRightClickMenu = menu + + + def GetPageText(self, nPage): + """ Returns the tab caption. """ + + return self._pages.GetPageText(nPage) + + + def SetGradientColours(self, fr, to, border): + """ Sets the gradient colours for the tab. """ + + self._pages._colorFrom = fr + self._pages._colorTo = to + self._pages._colorBorder = border + + + def SetGradientColourFrom(self, fr): + """ Sets the starting colour for the gradient. """ + + self._pages._colorFrom = fr + + + def SetGradientColourTo(self, to): + """ Sets the ending colour for the gradient. """ + + self._pages._colorTo = to + + + def SetGradientColourBorder(self, border): + """ Sets the tab border colour. """ + + self._pages._colorBorder = border + + + def GetGradientColourFrom(self): + """ Gets first gradient colour. """ + + return self._pages._colorFrom + + + def GetGradientColourTo(self): + """ Gets second gradient colour. """ + + return self._pages._colorTo + + + def GetGradientColourBorder(self): + """ Gets the tab border colour. """ + + return self._pages._colorBorder + + + def GetBorderColour(self): + """ Returns the border colour. """ + + return self._pages._colorBorder + + + def GetActiveTabTextColour(self): + """ Get the active tab text colour. """ + + return self._pages._activeTextColor + + + def SetPageImage(self, page, image): + """ + Sets the image index for the given page. Image is an index into the + image list which was set with SetImageList. + """ + + self._pages.SetPageImage(page, image) + + + def GetPageImage(self, nPage): + """ + Returns the image index for the given page. Image is an index into the + image list which was set with SetImageList. + """ + + return self._pages.GetPageImage(nPage) + + + def GetEnabled(self, page): + """ Returns whether a tab is enabled or not. """ + + return self._pages.GetEnabled(page) + + + def EnableTab(self, page, enabled=True): + """ Enables or disables a tab. """ + + if page >= len(self._windows): + return + + self._windows[page].Enable(enabled) + self._pages.EnableTab(page, enabled) + + + def GetNonActiveTabTextColour(self): + """ Returns the non active tabs text colour. """ + + return self._pages._nonActiveTextColor + + + def SetNonActiveTabTextColour(self, color): + """ Sets the non active tabs text colour. """ + + self._pages._nonActiveTextColor = color + + + def SetTabAreaColour(self, color): + """ Sets the area behind the tabs colour. """ + + self._pages._tabAreaColor = color + + + def GetTabAreaColour(self): + """ Returns the area behind the tabs colour. """ + + return self._pages._tabAreaColor + + + def SetActiveTabColour(self, color): + """ Sets the active tab colour. """ + + self._pages._activeTabColor = color + + + def GetActiveTabColour(self): + """ Returns the active tab colour. """ + + return self._pages._activeTabColor + + def EnsureVisible(self, page): + """ Ensures that a tab is visible. """ + self._pages.DoSetSelection(page) + +# ---------------------------------------------------------------------------- # +# Class PageContainer +# Acts as a container for the pages you add to FlatNotebook +# ---------------------------------------------------------------------------- # + +class PageContainer(wx.Panel): + """ + This class acts as a container for the pages you add to L{FlatNotebook}. + """ + + def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=0): + """ Default class constructor. """ + + self._ImageList = None + self._iActivePage = -1 + self._pDropTarget = None + self._nLeftClickZone = FNB_NOWHERE + self._iPreviousActivePage = -1 + + self._pRightClickMenu = None + self._nXButtonStatus = FNB_BTN_NONE + self._nArrowDownButtonStatus = FNB_BTN_NONE + self._pParent = parent + self._nRightButtonStatus = FNB_BTN_NONE + self._nLeftButtonStatus = FNB_BTN_NONE + self._nTabXButtonStatus = FNB_BTN_NONE + + self._setCursor = False + + self._pagesInfoVec = [] + + self._colorTo = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION) + self._colorFrom = wx.WHITE + self._activeTabColor = wx.WHITE + self._activeTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT) + self._nonActiveTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT) + self._tabAreaColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE) + + self._nFrom = 0 + self._isdragging = False + + # Set default page height, this is done according to the system font + memDc = wx.MemoryDC() + memDc.SelectObject(wx.EmptyBitmap(1,1)) + +# if "__WXGTK__" in wx.PlatformInfo: +# boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT) +# boldFont.SetWeight(wx.BOLD) +# memDc.SetFont(boldFont) + + height = memDc.GetCharHeight() + tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding + + wx.Panel.__init__(self, parent, id, pos, wx.Size(size.x, tabHeight), + style|wx.NO_BORDER|wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS) + + self._pDropTarget = FNBDropTarget(self) + self.SetDropTarget(self._pDropTarget) + self._mgr = FNBRendererMgr() + + self.Bind(wx.EVT_PAINT, self.OnPaint) + self.Bind(wx.EVT_SIZE, self.OnSize) + self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) + self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) + self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown) + self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) + self.Bind(wx.EVT_MOTION, self.OnMouseMove) + self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) + self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) + self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow) + self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) + self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) + self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) + + + def OnEraseBackground(self, event): + """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing).""" + + pass + + + def _ReShow(self): + """ Handles the Redraw of the tabs when the FNB_HIDE_ON_SINGLE_TAB has been removed """ + self.Show() + self.GetParent()._mainSizer.Layout() + self.Refresh() + + + def OnPaint(self, event): + """ Handles the wx.EVT_PAINT event for L{PageContainer}.""" + + dc = wx.BufferedPaintDC(self) + renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()) + renderer.DrawTabs(self, dc) + + if self.HasFlag(FNB_HIDE_ON_SINGLE_TAB) and len(self._pagesInfoVec) <= 1: + self.Hide() + self.GetParent()._mainSizer.Layout() + self.Refresh() + + + def AddPage(self, caption, selected=True, imgindex=-1): + """ + Add a page to the L{FlatNotebook}. + + @param window: Specifies the new page. + @param caption: Specifies the text for the new page. + @param selected: Specifies whether the page should be selected. + @param imgindex: Specifies the optional image index for the new page. + + Return value: + True if successful, False otherwise. + """ + + if selected: + + self._iPreviousActivePage = self._iActivePage + self._iActivePage = len(self._pagesInfoVec) + + # Create page info and add it to the vector + pageInfo = PageInfo(caption, imgindex) + self._pagesInfoVec.append(pageInfo) + self.Refresh() + + + def InsertPage(self, indx, text, selected=True, imgindex=-1): + """ + Inserts a new page at the specified position. + + @param indx: Specifies the position of the new page. + @param page: Specifies the new page. + @param text: Specifies the text for the new page. + @param select: Specifies whether the page should be selected. + @param imgindex: Specifies the optional image index for the new page. + + Return value: + True if successful, False otherwise. + """ + + if selected: + + self._iPreviousActivePage = self._iActivePage + self._iActivePage = len(self._pagesInfoVec) + + self._pagesInfoVec.insert(indx, PageInfo(text, imgindex)) + + self.Refresh() + return True + + + def OnSize(self, event): + """ Handles the wx.EVT_SIZE events for L{PageContainer}. """ + + # When resizing the control, try to fit to screen as many tabs as we can + style = self.GetParent().GetWindowStyleFlag() + renderer = self._mgr.GetRenderer(style) + + fr = 0 + page = self.GetSelection() + + for fr in xrange(self._nFrom): + vTabInfo = renderer.NumberTabsCanFit(self, fr) + if page - fr >= len(vTabInfo): + continue + break + + self._nFrom = fr + + self.Refresh() # Call on paint + event.Skip() + + + def OnMiddleDown(self, event): + """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """ + + # Test if this style is enabled + style = self.GetParent().GetWindowStyleFlag() + + if not style & FNB_MOUSE_MIDDLE_CLOSES_TABS: + return + + where, tabIdx = self.HitTest(event.GetPosition()) + + if where == FNB_TAB: + self.DeletePage(tabIdx) + + event.Skip() + + + def OnMouseWheel(self, event): + """ Scroll tabs when the mouse whee """ + delta = event.GetWheelRotation() + for tab in range(abs(delta/event.GetWheelDelta())): + if delta > 0: + before = self._nLeftButtonStatus + self._nLeftButtonStatus = FNB_BTN_PRESSED + self.RotateLeft() + self._nLeftButtonStatus = before + else: + before = self._nRightButtonStatus + self._nRightButtonStatus = FNB_BTN_PRESSED + self.RotateRight() + self._nRightButtonStatus = before + + event.Skip() + + + def OnRightDown(self, event): + """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """ + + where, tabIdx = self.HitTest(event.GetPosition()) + + if where in [FNB_TAB, FNB_TAB_X] and tabIdx < len(self._pagesInfoVec): + + if self._pagesInfoVec[tabIdx].GetEnabled(): + # Fire events and eventually (if allowed) change selection + self.FireEvent(tabIdx) + + # send a message to popup a custom menu + event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, self.GetParent().GetId()) + event.SetSelection(tabIdx) + event.SetOldSelection(self._iActivePage) + event.SetEventObject(self.GetParent()) + self.GetParent().GetEventHandler().ProcessEvent(event) + + if self._pRightClickMenu: + self.PopupMenu(self._pRightClickMenu) + + event.Skip() + + + def OnLeftDown(self, event): + """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """ + + # Reset buttons status + self._nXButtonStatus = FNB_BTN_NONE + self._nLeftButtonStatus = FNB_BTN_NONE + self._nRightButtonStatus = FNB_BTN_NONE + self._nTabXButtonStatus = FNB_BTN_NONE + self._nArrowDownButtonStatus = FNB_BTN_NONE + + self._nLeftClickZone, tabIdx = self.HitTest(event.GetPosition()) + + if self._nLeftClickZone == FNB_DROP_DOWN_ARROW: + self._nArrowDownButtonStatus = FNB_BTN_PRESSED + self.Refresh() + elif self._nLeftClickZone == FNB_LEFT_ARROW: + self._nLeftButtonStatus = FNB_BTN_PRESSED + self.Refresh() + elif self._nLeftClickZone == FNB_RIGHT_ARROW: + self._nRightButtonStatus = FNB_BTN_PRESSED + self.Refresh() + elif self._nLeftClickZone == FNB_X: + self._nXButtonStatus = FNB_BTN_PRESSED + self.Refresh() + elif self._nLeftClickZone == FNB_TAB_X: + self._nTabXButtonStatus = FNB_BTN_PRESSED + self.Refresh() + + elif self._nLeftClickZone == FNB_TAB: + + if self._iActivePage != tabIdx: + + # In case the tab is disabled, we dont allow to choose it + if len(self._pagesInfoVec) > tabIdx and \ + self._pagesInfoVec[tabIdx].GetEnabled(): + self.FireEvent(tabIdx) + + + def RotateLeft(self): + + if self._nFrom == 0: + return + + # Make sure that the button was pressed before + if self._nLeftButtonStatus != FNB_BTN_PRESSED: + return + + self._nLeftButtonStatus = FNB_BTN_HOVER + + # We scroll left with bulks of 5 + scrollLeft = self.GetNumTabsCanScrollLeft() + + self._nFrom -= scrollLeft + if self._nFrom < 0: + self._nFrom = 0 + + self.Refresh() + + + def RotateRight(self): + + if self._nFrom >= len(self._pagesInfoVec) - 1: + return + + # Make sure that the button was pressed before + if self._nRightButtonStatus != FNB_BTN_PRESSED: + return + + self._nRightButtonStatus = FNB_BTN_HOVER + + # Check if the right most tab is visible, if it is + # don't rotate right anymore + if self._pagesInfoVec[len(self._pagesInfoVec)-1].GetPosition() != wx.Point(-1, -1): + return + + self._nFrom += 1 + self.Refresh() + + + def OnLeftUp(self, event): + """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """ + + # forget the zone that was initially clicked + self._nLeftClickZone = FNB_NOWHERE + + where, tabIdx = self.HitTest(event.GetPosition()) + + # Make sure selected tab has focus +# self.SetFocus() + + if where == FNB_LEFT_ARROW: + self.RotateLeft() + + elif where == FNB_RIGHT_ARROW: + self.RotateRight() + + elif where == FNB_X: + + # Make sure that the button was pressed before + if self._nXButtonStatus != FNB_BTN_PRESSED: + return + + self._nXButtonStatus = FNB_BTN_HOVER + + self.DeletePage(self._iActivePage) + + elif where == FNB_TAB_X: + + # Make sure that the button was pressed before + if self._nTabXButtonStatus != FNB_BTN_PRESSED: + return + + self._nTabXButtonStatus = FNB_BTN_HOVER + + self.DeletePage(self._iActivePage) + + elif where == FNB_DROP_DOWN_ARROW: + + # Make sure that the button was pressed before + if self._nArrowDownButtonStatus != FNB_BTN_PRESSED: + return + + self._nArrowDownButtonStatus = FNB_BTN_NONE + + # Refresh the button status + renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()) + dc = wx.ClientDC(self) + renderer.DrawDropDownArrow(self, dc) + + self.PopupTabsMenu() + + event.Skip() + + + def HitTest(self, pt): + """ + HitTest method for L{PageContainer}. + Returns the flag (if any) and the hit page (if any). + """ + + style = self.GetParent().GetWindowStyleFlag() + render = self._mgr.GetRenderer(style) + + fullrect = self.GetClientRect() + btnLeftPos = render.GetLeftButtonPos(self) + btnRightPos = render.GetRightButtonPos(self) + btnXPos = render.GetXPos(self) + + tabIdx = -1 + + if len(self._pagesInfoVec) == 0: + return FNB_NOWHERE, tabIdx + + rect = wx.Rect(btnXPos, 8, 16, 16) + if rect.Contains(pt): + return (style & FNB_NO_X_BUTTON and [FNB_NOWHERE] or [FNB_X])[0], tabIdx + + rect = wx.Rect(btnRightPos, 8, 16, 16) + if style & FNB_DROPDOWN_TABS_LIST: + ddrect = wx.Rect(render.GetDropArrowButtonPos(self), 8, 16, 16) + if ddrect.Contains(pt): + return FNB_DROP_DOWN_ARROW, tabIdx + + if rect.Contains(pt): + return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_RIGHT_ARROW])[0], tabIdx + + rect = wx.Rect(btnLeftPos, 8, 16, 16) + if rect.Contains(pt): + return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_LEFT_ARROW])[0], tabIdx + + # Test whether a left click was made on a tab + bFoundMatch = False + + for cur in xrange(self._nFrom, len(self._pagesInfoVec)): + + pgInfo = self._pagesInfoVec[cur] + + if pgInfo.GetPosition() == wx.Point(-1, -1): + continue + + if style & FNB_X_ON_TAB and cur == self.GetSelection(): + # 'x' button exists on a tab + if self._pagesInfoVec[cur].GetXRect().Contains(pt): + return FNB_TAB_X, cur + + if style & FNB_VC8: + + if self._pagesInfoVec[cur].GetRegion().Contains(pt.x, pt.y): + if bFoundMatch or cur == self.GetSelection(): + return FNB_TAB, cur + + tabIdx = cur + bFoundMatch = True + + else: + + tabRect = wx.Rect(pgInfo.GetPosition().x, pgInfo.GetPosition().y, + pgInfo.GetSize().x, pgInfo.GetSize().y) + + if tabRect.Contains(pt): + # We have a match + return FNB_TAB, cur + + if bFoundMatch: + return FNB_TAB, tabIdx + + if self._isdragging: + # We are doing DND, so check also the region outside the tabs + # try before the first tab + pgInfo = self._pagesInfoVec[0] + tabRect = wx.Rect(0, pgInfo.GetPosition().y, pgInfo.GetPosition().x, self.GetParent().GetSize().y) + if tabRect.Contains(pt): + return FNB_TAB, 0 + + # try after the last tab + pgInfo = self._pagesInfoVec[-1] + startpos = pgInfo.GetPosition().x+pgInfo.GetSize().x + tabRect = wx.Rect(startpos, pgInfo.GetPosition().y, fullrect.GetWidth()-startpos, self.GetParent().GetSize().y) + + if tabRect.Contains(pt): + return FNB_TAB, len(self._pagesInfoVec) + + # Default + return FNB_NOWHERE, -1 + + + def SetSelection(self, page): + """ Sets the selected page. """ + + book = self.GetParent() + book.SetSelection(page) + self.DoSetSelection(page) + + + def DoSetSelection(self, page): + """ Does the actual selection of a page. """ + + if page < len(self._pagesInfoVec): + #! fix for tabfocus + da_page = self._pParent.GetPage(page) + + if da_page != None: + da_page.SetFocus() + + if not self.IsTabVisible(page): + # Try to remove one tab from start and try again + + if not self.CanFitToScreen(page): + + if self._nFrom > page: + self._nFrom = page + else: + while self._nFrom < page: + self._nFrom += 1 + if self.CanFitToScreen(page): + break + + self.Refresh() + + + def DeletePage(self, page): + """ Delete the specified page from L{FlatNotebook}. """ + + book = self.GetParent() + book.DeletePage(page) + book.Refresh() + + + def IsTabVisible(self, page): + """ Returns whether a tab is visible or not. """ + + iLastVisiblePage = self.GetLastVisibleTab() + return page <= iLastVisiblePage and page >= self._nFrom + + + def DoDeletePage(self, page): + """ Does the actual page deletion. """ + + # Remove the page from the vector + book = self.GetParent() + self._pagesInfoVec.pop(page) + + # Thanks to Yiaanis AKA Mandrav + if self._iActivePage >= page: + self._iActivePage = self._iActivePage - 1 + self._iPreviousActivePage = -1 + + # The delete page was the last first on the array, + # but the book still has more pages, so we set the + # active page to be the first one (0) + if self._iActivePage < 0 and len(self._pagesInfoVec) > 0: + self._iActivePage = 0 + self._iPreviousActivePage = -1 + + # Refresh the tabs + if self._iActivePage >= 0: + + book._bForceSelection = True + + # Check for selection and send event + event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId()) + event.SetSelection(self._iActivePage) + event.SetOldSelection(self._iPreviousActivePage) + event.SetEventObject(self.GetParent()) + self.GetParent().GetEventHandler().ProcessEvent(event) + + book.SetSelection(self._iActivePage) + book._bForceSelection = False + + # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event + event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED) + event.SetOldSelection(self._iPreviousActivePage) + self.GetParent().GetEventHandler().ProcessEvent(event) + +# if not self._pagesInfoVec: +# # Erase the page container drawings +# dc = wx.ClientDC(self) +# dc.Clear() + + + def DeleteAllPages(self): + """ Deletes all the pages. """ + + self._iActivePage = -1 + self._iPreviousActivePage = -1 + self._nFrom = 0 + self._pagesInfoVec = [] + + # Erase the page container drawings + dc = wx.ClientDC(self) + dc.Clear() + + + def OnMouseMove(self, event): + """ Handles the wx.EVT_MOTION for L{PageContainer}. """ + + if self._pagesInfoVec and self.IsShown(): + + xButtonStatus = self._nXButtonStatus + xTabButtonStatus = self._nTabXButtonStatus + rightButtonStatus = self._nRightButtonStatus + leftButtonStatus = self._nLeftButtonStatus + dropDownButtonStatus = self._nArrowDownButtonStatus + + style = self.GetParent().GetWindowStyleFlag() + + self._nXButtonStatus = FNB_BTN_NONE + self._nRightButtonStatus = FNB_BTN_NONE + self._nLeftButtonStatus = FNB_BTN_NONE + self._nTabXButtonStatus = FNB_BTN_NONE + self._nArrowDownButtonStatus = FNB_BTN_NONE + + where, tabIdx = self.HitTest(event.GetPosition()) + + if where == FNB_X: + if event.LeftIsDown(): + + self._nXButtonStatus = (self._nLeftClickZone==FNB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0] + + else: + + self._nXButtonStatus = FNB_BTN_HOVER + + elif where == FNB_DROP_DOWN_ARROW: + if event.LeftIsDown(): + + self._nArrowDownButtonStatus = (self._nLeftClickZone==FNB_DROP_DOWN_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0] + + else: + + self._nArrowDownButtonStatus = FNB_BTN_HOVER + + elif where == FNB_TAB_X: + if event.LeftIsDown(): + + self._nTabXButtonStatus = (self._nLeftClickZone==FNB_TAB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0] + + else: + + self._nTabXButtonStatus = FNB_BTN_HOVER + + elif where == FNB_RIGHT_ARROW: + if event.LeftIsDown(): + + self._nRightButtonStatus = (self._nLeftClickZone==FNB_RIGHT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0] + + else: + + self._nRightButtonStatus = FNB_BTN_HOVER + + elif where == FNB_LEFT_ARROW: + if event.LeftIsDown(): + + self._nLeftButtonStatus = (self._nLeftClickZone==FNB_LEFT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0] + + else: + + self._nLeftButtonStatus = FNB_BTN_HOVER + + elif where == FNB_TAB: + # Call virtual method for showing tooltip + self.ShowTabTooltip(tabIdx) + + if not self.GetEnabled(tabIdx): + # Set the cursor to be 'No-entry' + wx.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY)) + self._setCursor = True + else: + if self._setCursor: + wx.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) + self._setCursor = False + + # Support for drag and drop + if event.Dragging() and not (style & FNB_NODRAG): + + self._isdragging = True + draginfo = FNBDragInfo(self, tabIdx) + drginfo = cPickle.dumps(draginfo) + dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook")) + dataobject.SetData(drginfo) + dragSource = FNBDropSource(self) + dragSource.SetData(dataobject) + dragSource.DoDragDrop(wx.Drag_DefaultMove) + + bRedrawX = self._nXButtonStatus != xButtonStatus + bRedrawRight = self._nRightButtonStatus != rightButtonStatus + bRedrawLeft = self._nLeftButtonStatus != leftButtonStatus + bRedrawTabX = self._nTabXButtonStatus != xTabButtonStatus + bRedrawDropArrow = self._nArrowDownButtonStatus != dropDownButtonStatus + + render = self._mgr.GetRenderer(style) + + if (bRedrawX or bRedrawRight or bRedrawLeft or bRedrawTabX or bRedrawDropArrow): + + dc = wx.ClientDC(self) + + if bRedrawX: + + render.DrawX(self, dc) + + if bRedrawLeft: + + render.DrawLeftArrow(self, dc) + + if bRedrawRight: + + render.DrawRightArrow(self, dc) + + if bRedrawTabX: + + self.Refresh() + + if bRedrawDropArrow: + + render.DrawDropDownArrow(self, dc) + + event.Skip() + + + def GetLastVisibleTab(self): + """ Returns the last visible tab. """ + + if self._nFrom < 0: + return -1 + + ii = 0 + + for ii in xrange(self._nFrom, len(self._pagesInfoVec)): + + if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1): + break + + return ii-1 + + + def GetNumTabsCanScrollLeft(self): + """ Returns the number of tabs than can be scrolled left. """ + + if self._nFrom - 1 >= 0: + return 1 + + return 0 + + + def IsDefaultTabs(self): + """ Returns whether a tab has a default style. """ + + style = self.GetParent().GetWindowStyleFlag() + res = (style & FNB_VC71) or (style & FNB_FANCY_TABS) or (style & FNB_VC8) + return not res + + + def AdvanceSelection(self, bForward=True): + """ + Cycles through the tabs. + The call to this function generates the page changing events. + """ + + nSel = self.GetSelection() + + if nSel < 0: + return + + nMax = self.GetPageCount() - 1 + + if bForward: + newSelection = (nSel == nMax and [0] or [nSel + 1])[0] + else: + newSelection = (nSel == 0 and [nMax] or [nSel - 1])[0] + + if not self._pagesInfoVec[newSelection].GetEnabled(): + return + + self.FireEvent(newSelection) + + + def OnMouseLeave(self, event): + """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """ + + self._nLeftButtonStatus = FNB_BTN_NONE + self._nXButtonStatus = FNB_BTN_NONE + self._nRightButtonStatus = FNB_BTN_NONE + self._nTabXButtonStatus = FNB_BTN_NONE + self._nArrowDownButtonStatus = FNB_BTN_NONE + + style = self.GetParent().GetWindowStyleFlag() + render = self._mgr.GetRenderer(style) + + dc = wx.ClientDC(self) + + render.DrawX(self, dc) + render.DrawLeftArrow(self, dc) + render.DrawRightArrow(self, dc) + + selection = self.GetSelection() + + if selection == -1: + event.Skip() + return + + if not self.IsTabVisible(selection): + if selection == len(self._pagesInfoVec) - 1: + if not self.CanFitToScreen(selection): + event.Skip() + return + else: + event.Skip() + return + + render.DrawTabX(self, dc, self._pagesInfoVec[selection].GetXRect(), selection, self._nTabXButtonStatus) + render.DrawFocusRectangle(dc, self, self._pagesInfoVec[selection]) + + event.Skip() + + + def OnMouseEnterWindow(self, event): + """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """ + + self._nLeftButtonStatus = FNB_BTN_NONE + self._nXButtonStatus = FNB_BTN_NONE + self._nRightButtonStatus = FNB_BTN_NONE + self._nLeftClickZone = FNB_BTN_NONE + self._nArrowDownButtonStatus = FNB_BTN_NONE + + event.Skip() + + + def ShowTabTooltip(self, tabIdx): + """ Shows a tab tooltip. """ + + pWindow = self._pParent.GetPage(tabIdx) + + if pWindow: + pToolTip = pWindow.GetToolTip() + if pToolTip and pToolTip.GetWindow() == pWindow: + self.SetToolTipString(pToolTip.GetTip()) + + + def SetPageImage(self, page, imgindex): + """ Sets the image index associated to a page. """ + + if page < len(self._pagesInfoVec): + + self._pagesInfoVec[page].SetImageIndex(imgindex) + self.Refresh() + + + def GetPageImage(self, page): + """ Returns the image index associated to a page. """ + + if page < len(self._pagesInfoVec): + + return self._pagesInfoVec[page].GetImageIndex() + + return -1 + + + def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer): + """ Handles the drop action from a DND operation. """ + + # Disable drag'n'drop for disabled tab + if len(wnd_oldContainer._pagesInfoVec) > nTabPage and \ + not wnd_oldContainer._pagesInfoVec[nTabPage].GetEnabled(): + return wx.DragCancel + + self._isdragging = True + oldContainer = wnd_oldContainer + nIndex = -1 + + where, nIndex = self.HitTest(wx.Point(x, y)) + + oldNotebook = oldContainer.GetParent() + newNotebook = self.GetParent() + + if oldNotebook == newNotebook: + + if nTabPage >= 0: + + if where == FNB_TAB: + self.MoveTabPage(nTabPage, nIndex) + + elif self.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND: + + if wx.Platform in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]: + if nTabPage >= 0: + + window = oldNotebook.GetPage(nTabPage) + + if window: + where, nIndex = newNotebook._pages.HitTest(wx.Point(x, y)) + caption = oldContainer.GetPageText(nTabPage) + imageindex = oldContainer.GetPageImage(nTabPage) + oldNotebook.RemovePage(nTabPage) + window.Reparent(newNotebook) + + if imageindex >= 0: + + bmp = oldNotebook.GetImageList().GetBitmap(imageindex) + newImageList = newNotebook.GetImageList() + + if not newImageList: + xbmp, ybmp = bmp.GetWidth(), bmp.GetHeight() + newImageList = wx.ImageList(xbmp, ybmp) + imageindex = 0 + else: + imageindex = newImageList.GetImageCount() + + newImageList.Add(bmp) + newNotebook.SetImageList(newImageList) + + newNotebook.InsertPage(nIndex, window, caption, True, imageindex) + + self._isdragging = False + + return wx.DragMove + + + def MoveTabPage(self, nMove, nMoveTo): + """ Moves a tab inside the same L{FlatNotebook}. """ + + if nMove == nMoveTo: + return + + elif nMoveTo < len(self._pParent._windows): + nMoveTo = nMoveTo + 1 + + self._pParent.Freeze() + + # Remove the window from the main sizer + nCurSel = self._pParent._pages.GetSelection() + self._pParent._mainSizer.Detach(self._pParent._windows[nCurSel]) + self._pParent._windows[nCurSel].Hide() + + pWindow = self._pParent._windows[nMove] + self._pParent._windows.pop(nMove) + self._pParent._windows.insert(nMoveTo-1, pWindow) + + pgInfo = self._pagesInfoVec[nMove] + + self._pagesInfoVec.pop(nMove) + self._pagesInfoVec.insert(nMoveTo - 1, pgInfo) + + # Add the page according to the style + pSizer = self._pParent._mainSizer + style = self.GetParent().GetWindowStyleFlag() + + if style & FNB_BOTTOM: + + pSizer.Insert(0, pWindow, 1, wx.EXPAND) + + else: + + # We leave a space of 1 pixel around the window + pSizer.Add(pWindow, 1, wx.EXPAND) + + pWindow.Show() + + pSizer.Layout() + self._iActivePage = nMoveTo - 1 + self._iPreviousActivePage = -1 + self.DoSetSelection(self._iActivePage) + self.Refresh() + self._pParent.Thaw() + + + def CanFitToScreen(self, page): + """ Returns wheter a tab can fit in the left space in the screen or not. """ + + # Incase the from is greater than page, + # we need to reset the self._nFrom, so in order + # to force the caller to do so, we return false + if self._nFrom > page: + return False + + style = self.GetParent().GetWindowStyleFlag() + render = self._mgr.GetRenderer(style) + + vTabInfo = render.NumberTabsCanFit(self) + + if page - self._nFrom >= len(vTabInfo): + return False + + return True + + + def GetNumOfVisibleTabs(self): + """ Returns the number of visible tabs. """ + + count = 0 + for ii in xrange(self._nFrom, len(self._pagesInfoVec)): + if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1): + break + count = count + 1 + + return count + + + def GetEnabled(self, page): + """ Returns whether a tab is enabled or not. """ + + if page >= len(self._pagesInfoVec): + return True # Seems strange, but this is the default + + return self._pagesInfoVec[page].GetEnabled() + + + def EnableTab(self, page, enabled=True): + """ Enables or disables a tab. """ + + if page >= len(self._pagesInfoVec): + return + + self._pagesInfoVec[page].EnableTab(enabled) + + + def GetSingleLineBorderColour(self): + """ Returns the colour for the single line border. """ + + if self.HasFlag(FNB_FANCY_TABS): + return self._colorFrom + + return wx.WHITE + + + def HasFlag(self, flag): + """ Returns whether a flag is present in the L{FlatNotebook} style. """ + + style = self.GetParent().GetWindowStyleFlag() + res = (style & flag and [True] or [False])[0] + return res + + + def ClearFlag(self, flag): + """ Deletes a flag from the L{FlatNotebook} style. """ + + style = self.GetParent().GetWindowStyleFlag() + style &= ~flag + self.SetWindowStyleFlag(style) + + + def TabHasImage(self, tabIdx): + """ Returns whether a tab has an associated image index or not. """ + + if self._ImageList: + return self._pagesInfoVec[tabIdx].GetImageIndex() != -1 + + return False + + + def OnLeftDClick(self, event): + """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """ + + where, tabIdx = self.HitTest(event.GetPosition()) + + if where == FNB_RIGHT_ARROW: + self._nRightButtonStatus = FNB_BTN_PRESSED + self.RotateRight() + + elif where == FNB_LEFT_ARROW: + self._nLeftButtonStatus = FNB_BTN_PRESSED + self.RotateLeft() + + elif self.HasFlag(FNB_DCLICK_CLOSES_TABS): + + if where == FNB_TAB: + self.DeletePage(tabIdx) + + else: + + event.Skip() + + + def OnSetFocus(self, event): + """ Handles the wx.EVT_SET_FOCUS event for L{PageContainer}. """ + + if self._iActivePage < 0: + event.Skip() + return + + self.SetFocusedPage(self._iActivePage) + + + def OnKillFocus(self, event): + """ Handles the wx.EVT_KILL_FOCUS event for L{PageContainer}. """ + + self.SetFocusedPage() + + + def OnKeyDown(self, event): + """ + When the PageContainer has the focus tabs can be changed with + the left/right arrow keys. + """ + key = event.GetKeyCode() + if key == wx.WXK_LEFT: + self.GetParent().AdvanceSelection(False) + self.SetFocus() + elif key == wx.WXK_RIGHT: + self.GetParent().AdvanceSelection(True) + self.SetFocus() + elif key == wx.WXK_TAB and not event.ControlDown(): + flags = 0 + if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward + if event.CmdDown(): flags |= wx.NavigationKeyEvent.WinChange + self.Navigate(flags) + else: + event.Skip() + + + def SetFocusedPage(self, pageIndex=-1): + """ + Sets/Unsets the focus on the appropriate page. + If pageIndex is defaulted, we have lost focus and no focus indicator is drawn. + """ + + for indx, page in enumerate(self._pagesInfoVec): + if indx == pageIndex: + page._hasFocus = True + else: + page._hasFocus = False + + self.Refresh() + + + def PopupTabsMenu(self): + """ Pops up the menu activated with the drop down arrow in the navigation area. """ + + popupMenu = wx.Menu() + + longest = 0 + has_bmp = False + for i in xrange(len(self._pagesInfoVec)): + pi = self._pagesInfoVec[i] + caption = pi.GetCaption() + item = wx.MenuItem(popupMenu, i+1, caption, caption, wx.ITEM_NORMAL) + + # Save longest caption width for calculating menu width with + width = self.GetTextExtent(caption)[0] + if width > longest: + longest = width + + self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item) + + # There is an alignment problem with wx2.6.3 & Menus so only use + # images for versions above 2.6.3 + if wx.VERSION > (2, 6, 3, 0) and self.TabHasImage(i): + has_bmp = True + item.SetBitmap(self.GetImageList().GetBitmap(pi.GetImageIndex())) + + popupMenu.AppendItem(item) + item.Enable(pi.GetEnabled()) + + # Calculate the approximate size of the popupmenu for setting the + # position of the menu when its shown. + # Account for extra padding on left/right of text on mac menus + if wx.Platform in ['__WXMAC__', '__WXMSW__']: + longest += 32 + + # Bitmap width + padding + if has_bmp: + longest += 20 + + if not self.HasFlag(FNB_NO_X_BUTTON) or \ + not self.HasFlag(FNB_NO_NAV_BUTTONS): + longest += 16 + + rect = self.GetClientRect() + self.PopupMenu(popupMenu, + wx.Point(rect.x + rect.GetWidth() - longest, + rect.y + rect.height)) + + + def OnTabMenuSelection(self, event): + """ Handles the wx.EVT_MENU event for L{PageContainer}. """ + + selection = event.GetId() - 1 + self.FireEvent(selection) + + + def FireEvent(self, selection): + """ + Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events + called from other methods (from menu selection or Smart Tabbing). + Utility function. + """ + + if selection == self._iActivePage: + # No events for the same selection + return + + oldSelection = self._iActivePage + + event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId()) + event.SetSelection(selection) + event.SetOldSelection(oldSelection) + event.SetEventObject(self.GetParent()) + + if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed(): + + self.SetSelection(selection) + + # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event + event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED) + event.SetOldSelection(oldSelection) + self.GetParent().GetEventHandler().ProcessEvent(event) +# self.SetFocus() + + + def SetImageList(self, imglist): + """ Sets the image list for the page control. """ + + self._ImageList = imglist + + + def AssignImageList(self, imglist): + """ Assigns the image list for the page control. """ + + self._ImageList = imglist + + + def GetImageList(self): + """ Returns the image list for the page control. """ + + return self._ImageList + + + def GetSelection(self): + """ Returns the current selected page. """ + + return self._iActivePage + + + def GetPageCount(self): + """ Returns the number of tabs in the L{FlatNotebook} control. """ + + return len(self._pagesInfoVec) + + + def GetPageText(self, page): + """ Returns the tab caption of the page. """ + if page < len(self._pagesInfoVec): + return self._pagesInfoVec[page].GetCaption() + else: + return u'' + + + def SetPageText(self, page, text): + """ Sets the tab caption of the page. """ + if page < len(self._pagesInfoVec): + self._pagesInfoVec[page].SetCaption(text) + return True + else: + return False + + + def DrawDragHint(self): + """ Draws small arrow at the place that the tab will be placed. """ + + # get the index of tab that will be replaced with the dragged tab + pt = wx.GetMousePosition() + client_pt = self.ScreenToClient(pt) + where, tabIdx = self.HitTest(client_pt) + self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx) + + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pkg_resources.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pkg_resources.py new file mode 100644 index 0000000..1cbfec4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pkg_resources.py @@ -0,0 +1,2507 @@ +"""Package resource API +-------------------- + +A resource is a logical file contained within a package, or a logical +subdirectory thereof. The package resource API expects resource names +to have their path parts separated with ``/``, *not* whatever the local +path separator is. Do not use os.path operations to manipulate resource +names being passed into the API. + +The package resource API is designed to work with normal filesystem packages, +.egg files, and unpacked .egg files. It can also work in a limited way with +.zip files and with custom PEP 302 loaders that support the ``get_data()`` +method. +""" + +import sys, os, zipimport, time, re, imp, new + +# Fix for Python 2.6 deprecation warning +try: + ImmutableSet = frozenset +except NameError: + from sets import ImmutableSet + +from os import utime, rename, unlink # capture these to bypass sandboxing +from os import open as os_open + +def get_supported_platform(): + """Return this platform's maximum compatible version. + + distutils.util.get_platform() normally reports the minimum version + of Mac OS X that would be required to *use* extensions produced by + distutils. But what we want when checking compatibility is to know the + version of Mac OS X that we are *running*. To allow usage of packages that + explicitly require a newer version of Mac OS X, we must also know the + current version of the OS. + + If this condition occurs for any other platform with a version in its + platform strings, this function should be extended accordingly. + """ + plat = get_build_platform(); m = macosVersionString.match(plat) + if m is not None and sys.platform == "darwin": + try: + plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) + except ValueError: + pass # not Mac OS X + return plat + +__all__ = [ + # Basic resource access and distribution/entry point discovery + 'require', 'run_script', 'get_provider', 'get_distribution', + 'load_entry_point', 'get_entry_map', 'get_entry_info', 'iter_entry_points', + 'resource_string', 'resource_stream', 'resource_filename', + 'resource_listdir', 'resource_exists', 'resource_isdir', + + # Environmental control + 'declare_namespace', 'working_set', 'add_activation_listener', + 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'get_default_cache', + + # Primary implementation classes + 'Environment', 'WorkingSet', 'ResourceManager', + 'Distribution', 'Requirement', 'EntryPoint', + + # Exceptions + 'ResolutionError','VersionConflict','DistributionNotFound','UnknownExtra', + 'ExtractionError', + + # Parsing functions and string utilities + 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', + 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + 'safe_extra', 'to_filename', + + # filesystem utilities + 'ensure_directory', 'normalize_path', + + # Distribution "precedence" constants + 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', + + # "Provider" interfaces, implementations, and registration/lookup APIs + 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', + 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', + 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', + 'register_finder', 'register_namespace_handler', 'register_loader_type', + 'fixup_namespace_packages', 'get_importer', + + # Deprecated/backward compatibility only + 'run_main', 'AvailableDistributions', +] +class ResolutionError(Exception): + """Abstract base for dependency resolution errors""" + def __repr__(self): return self.__class__.__name__+repr(self.args) + +class VersionConflict(ResolutionError): + """An already-installed version conflicts with the requested version""" + +class DistributionNotFound(ResolutionError): + """A requested distribution was not found""" + +class UnknownExtra(ResolutionError): + """Distribution doesn't have an "extra feature" of the given name""" +_provider_factories = {} +PY_MAJOR = sys.version[:3] +EGG_DIST = 3 +BINARY_DIST = 2 +SOURCE_DIST = 1 +CHECKOUT_DIST = 0 +DEVELOP_DIST = -1 + +def register_loader_type(loader_type, provider_factory): + """Register `provider_factory` to make providers for `loader_type` + + `loader_type` is the type or class of a PEP 302 ``module.__loader__``, + and `provider_factory` is a function that, passed a *module* object, + returns an ``IResourceProvider`` for that module. + """ + _provider_factories[loader_type] = provider_factory + +def get_provider(moduleOrReq): + """Return an IResourceProvider for the named module or requirement""" + if isinstance(moduleOrReq,Requirement): + return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] + try: + module = sys.modules[moduleOrReq] + except KeyError: + __import__(moduleOrReq) + module = sys.modules[moduleOrReq] + loader = getattr(module, '__loader__', None) + return _find_adapter(_provider_factories, loader)(module) + +def _macosx_vers(_cache=[]): + if not _cache: + info = os.popen('/usr/bin/sw_vers').read().splitlines() + for line in info: + key, value = line.split(None, 1) + if key == 'ProductVersion:': + _cache.append(value.strip().split(".")) + break + else: + raise ValueError, "What?!" + return _cache[0] + +def _macosx_arch(machine): + return {'PowerPC':'ppc', 'Power_Macintosh':'ppc'}.get(machine,machine) + +def get_build_platform(): + """Return this platform's string for platform-specific distributions + + XXX Currently this is the same as ``distutils.util.get_platform()``, but it + needs some hacks for Linux and Mac OS X. + """ + from distutils.util import get_platform + plat = get_platform() + if sys.platform == "darwin" and not plat.startswith('macosx-'): + try: + version = _macosx_vers() + machine = os.uname()[4].replace(" ", "_") + return "macosx-%d.%d-%s" % (int(version[0]), int(version[1]), + _macosx_arch(machine)) + except ValueError: + # if someone is running a non-Mac darwin system, this will fall + # through to the default implementation + pass + return plat + +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") +darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") +get_platform = get_build_platform # XXX backward compat + + + +def compatible_platforms(provided,required): + """Can code for the `provided` platform run on the `required` platform? + + Returns true if either platform is ``None``, or the platforms are equal. + + XXX Needs compatibility checks for Linux and other unixy OSes. + """ + if provided is None or required is None or provided==required: + return True # easy case + + # Mac OS X special cases + reqMac = macosVersionString.match(required) + if reqMac: + provMac = macosVersionString.match(provided) + + # is this a Mac package? + if not provMac: + # this is backwards compatibility for packages built before + # setuptools 0.6. All packages built after this point will + # use the new macosx designation. + provDarwin = darwinVersionString.match(provided) + if provDarwin: + dversion = int(provDarwin.group(1)) + macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + if dversion == 7 and macosversion >= "10.3" or \ + dversion == 8 and macosversion >= "10.4": + + #import warnings + #warnings.warn("Mac eggs should be rebuilt to " + # "use the macosx designation instead of darwin.", + # category=DeprecationWarning) + return True + return False # egg isn't macosx or legacy darwin + + # are they the same major version and machine type? + if provMac.group(1) != reqMac.group(1) or \ + provMac.group(3) != reqMac.group(3): + return False + + + + # is the required OS major update >= the provided one? + if int(provMac.group(2)) > int(reqMac.group(2)): + return False + + return True + + # XXX Linux and other platforms' special cases should go here + return False + + +def run_script(dist_spec, script_name): + """Locate distribution `dist_spec` and run its `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + require(dist_spec)[0].run_script(script_name, ns) + +run_main = run_script # backward compatibility + +def get_distribution(dist): + """Return a current distribution object for a Requirement or string""" + if isinstance(dist,basestring): dist = Requirement.parse(dist) + if isinstance(dist,Requirement): dist = get_provider(dist) + if not isinstance(dist,Distribution): + raise TypeError("Expected string, Requirement, or Distribution", dist) + return dist + +def load_entry_point(dist, group, name): + """Return `name` entry point of `group` for `dist` or raise ImportError""" + return get_distribution(dist).load_entry_point(group, name) + +def get_entry_map(dist, group=None): + """Return the entry point map for `group`, or the full entry map""" + return get_distribution(dist).get_entry_map(group) + +def get_entry_info(dist, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(group, name) + + +class IMetadataProvider: + + def has_metadata(name): + """Does the package's distribution contain the named metadata?""" + + def get_metadata(name): + """The named metadata resource as a string""" + + def get_metadata_lines(name): + """Yield named metadata resource as list of non-blank non-comment lines + + Leading and trailing whitespace is stripped from each line, and lines + with ``#`` as the first non-blank character are omitted.""" + + def metadata_isdir(name): + """Is the named metadata a directory? (like ``os.path.isdir()``)""" + + def metadata_listdir(name): + """List of metadata names in the directory (like ``os.listdir()``)""" + + def run_script(script_name, namespace): + """Execute the named script in the supplied namespace dictionary""" + + + + + + + + + + + + + + + + + + + +class IResourceProvider(IMetadataProvider): + """An object that provides access to package resources""" + + def get_resource_filename(manager, resource_name): + """Return a true filesystem path for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_stream(manager, resource_name): + """Return a readable file-like object for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_string(manager, resource_name): + """Return a string containing the contents of `resource_name` + + `manager` must be an ``IResourceManager``""" + + def has_resource(resource_name): + """Does the package contain the named resource?""" + + def resource_isdir(resource_name): + """Is the named resource a directory? (like ``os.path.isdir()``)""" + + def resource_listdir(resource_name): + """List of resource names in the directory (like ``os.listdir()``)""" + + + + + + + + + + + + + + + +class WorkingSet(object): + """A collection of active distributions on sys.path (or a similar list)""" + + def __init__(self, entries=None): + """Create working set from list of path entries (default=sys.path)""" + self.entries = [] + self.entry_keys = {} + self.by_key = {} + self.callbacks = [] + + if entries is None: + entries = sys.path + + for entry in entries: + self.add_entry(entry) + + + def add_entry(self, entry): + """Add a path item to ``.entries``, finding any distributions on it + + ``find_distributions(entry,False)`` is used to find distributions + corresponding to the path entry, and they are added. `entry` is + always appended to ``.entries``, even if it is already present. + (This is because ``sys.path`` can contain the same value more than + once, and the ``.entries`` of the ``sys.path`` WorkingSet should always + equal ``sys.path``.) + """ + self.entry_keys.setdefault(entry, []) + self.entries.append(entry) + for dist in find_distributions(entry, True): + self.add(dist, entry, False) + + + def __contains__(self,dist): + """True if `dist` is the active distribution for its project""" + return self.by_key.get(dist.key) == dist + + + + + + def find(self, req): + """Find a distribution matching requirement `req` + + If there is an active distribution for the requested project, this + returns it as long as it meets the version requirement specified by + `req`. But, if there is an active distribution for the project and it + does *not* meet the `req` requirement, ``VersionConflict`` is raised. + If there is no active distribution for the requested project, ``None`` + is returned. + """ + dist = self.by_key.get(req.key) + if dist is not None and dist not in req: + raise VersionConflict(dist,req) # XXX add more info + else: + return dist + + def iter_entry_points(self, group, name=None): + """Yield entry point objects from `group` matching `name` + + If `name` is None, yields all entry points in `group` from all + distributions in the working set, otherwise only ones matching + both `group` and `name` are yielded (in distribution order). + """ + for dist in self: + entries = dist.get_entry_map(group) + if name is None: + for ep in entries.values(): + yield ep + elif name in entries: + yield entries[name] + + def run_script(self, requires, script_name): + """Locate distribution for `requires` and run `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + self.require(requires)[0].run_script(script_name, ns) + + + + def __iter__(self): + """Yield distributions for non-duplicate projects in the working set + + The yield order is the order in which the items' path entries were + added to the working set. + """ + seen = {} + for item in self.entries: + for key in self.entry_keys[item]: + if key not in seen: + seen[key]=1 + yield self.by_key[key] + + def add(self, dist, entry=None, insert=True): + """Add `dist` to working set, associated with `entry` + + If `entry` is unspecified, it defaults to the ``.location`` of `dist`. + On exit from this routine, `entry` is added to the end of the working + set's ``.entries`` (if it wasn't already present). + + `dist` is only added to the working set if it's for a project that + doesn't already have a distribution in the set. If it's added, any + callbacks registered with the ``subscribe()`` method will be called. + """ + if insert: + dist.insert_on(self.entries, entry) + + if entry is None: + entry = dist.location + keys = self.entry_keys.setdefault(entry,[]) + keys2 = self.entry_keys.setdefault(dist.location,[]) + if dist.key in self.by_key: + return # ignore hidden distros + + self.by_key[dist.key] = dist + if dist.key not in keys: + keys.append(dist.key) + if dist.key not in keys2: + keys2.append(dist.key) + self._added_new(dist) + + def resolve(self, requirements, env=None, installer=None): + """List all distributions needed to (recursively) meet `requirements` + + `requirements` must be a sequence of ``Requirement`` objects. `env`, + if supplied, should be an ``Environment`` instance. If + not supplied, it defaults to all distributions available within any + entry or distribution in the working set. `installer`, if supplied, + will be invoked with each requirement that cannot be met by an + already-installed distribution; it should return a ``Distribution`` or + ``None``. + """ + + requirements = list(requirements)[::-1] # set up the stack + processed = {} # set of processed requirements + best = {} # key -> dist + to_activate = [] + + while requirements: + req = requirements.pop(0) # process dependencies breadth-first + if req in processed: + # Ignore cyclic or redundant dependencies + continue + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = self.by_key.get(req.key) + if dist is None: + if env is None: + env = Environment(self.entries) + dist = best[req.key] = env.best_match(req, self, installer) + if dist is None: + raise DistributionNotFound(req) # XXX put more info here + to_activate.append(dist) + if dist not in req: + # Oops, the "best" so far conflicts with a dependency + raise VersionConflict(dist,req) # XXX put more info here + requirements.extend(dist.requires(req.extras)[::-1]) + processed[req] = True + + return to_activate # return list of distros to activate + + def find_plugins(self, + plugin_env, full_env=None, installer=None, fallback=True + ): + """Find all activatable distributions in `plugin_env` + + Example usage:: + + distributions, errors = working_set.find_plugins( + Environment(plugin_dirlist) + ) + map(working_set.add, distributions) # add plugins+libs to sys.path + print "Couldn't load", errors # display errors + + The `plugin_env` should be an ``Environment`` instance that contains + only distributions that are in the project's "plugin directory" or + directories. The `full_env`, if supplied, should be an ``Environment`` + contains all currently-available distributions. If `full_env` is not + supplied, one is created automatically from the ``WorkingSet`` this + method is called on, which will typically mean that every directory on + ``sys.path`` will be scanned for distributions. + + `installer` is a standard installer callback as used by the + ``resolve()`` method. The `fallback` flag indicates whether we should + attempt to resolve older versions of a plugin if the newest version + cannot be resolved. + + This method returns a 2-tuple: (`distributions`, `error_info`), where + `distributions` is a list of the distributions found in `plugin_env` + that were loadable, along with any other distributions that are needed + to resolve their dependencies. `error_info` is a dictionary mapping + unloadable plugin distributions to an exception instance describing the + error that occurred. Usually this will be a ``DistributionNotFound`` or + ``VersionConflict`` instance. + """ + + plugin_projects = list(plugin_env) + plugin_projects.sort() # scan project names in alphabetic order + + error_info = {} + distributions = {} + + if full_env is None: + env = Environment(self.entries) + env += plugin_env + else: + env = full_env + plugin_env + + shadow_set = self.__class__([]) + map(shadow_set.add, self) # put all our entries in shadow_set + + for project_name in plugin_projects: + + for dist in plugin_env[project_name]: + + req = [dist.as_requirement()] + + try: + resolvees = shadow_set.resolve(req, env, installer) + + except ResolutionError,v: + error_info[dist] = v # save error info + if fallback: + continue # try the next older version of project + else: + break # give up on this project, keep going + + else: + map(shadow_set.add, resolvees) + distributions.update(dict.fromkeys(resolvees)) + + # success, no need to try any more versions of this project + break + + distributions = list(distributions) + distributions.sort() + + return distributions, error_info + + + + + + def require(self, *requirements): + """Ensure that distributions matching `requirements` are activated + + `requirements` must be a string or a (possibly-nested) sequence + thereof, specifying the distributions and versions required. The + return value is a sequence of the distributions that needed to be + activated to fulfill the requirements; all relevant distributions are + included, even if they were already activated in this working set. + """ + + needed = self.resolve(parse_requirements(requirements)) + + for dist in needed: + self.add(dist) + + return needed + + + def subscribe(self, callback): + """Invoke `callback` for all distributions (including existing ones)""" + if callback in self.callbacks: + return + self.callbacks.append(callback) + for dist in self: + callback(dist) + + + def _added_new(self, dist): + for callback in self.callbacks: + callback(dist) + + + + + + + + + + + +class Environment(object): + """Searchable snapshot of distributions on a search path""" + + def __init__(self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR): + """Snapshot distributions available on a search path + + Any distributions found on `search_path` are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. + + `platform` is an optional string specifying the name of the platform + that platform-specific distributions must be compatible with. If + unspecified, it defaults to the current platform. `python` is an + optional string naming the desired version of Python (e.g. ``'2.4'``); + it defaults to the current version. + + You may explicitly set `platform` (and/or `python`) to ``None`` if you + wish to map *all* distributions, not just those compatible with the + running platform or Python version. + """ + self._distmap = {} + self._cache = {} + self.platform = platform + self.python = python + self.scan(search_path) + + def can_add(self, dist): + """Is distribution `dist` acceptable for this environment? + + The distribution must match the platform and python version + requirements specified when this environment was created, or False + is returned. + """ + return (self.python is None or dist.py_version is None + or dist.py_version==self.python) \ + and compatible_platforms(dist.platform,self.platform) + + def remove(self, dist): + """Remove `dist` from the environment""" + self._distmap[dist.key].remove(dist) + + def scan(self, search_path=None): + """Scan `search_path` for distributions usable in this environment + + Any distributions found are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. Only distributions conforming to + the platform/python version defined at initialization are added. + """ + if search_path is None: + search_path = sys.path + + for item in search_path: + for dist in find_distributions(item): + self.add(dist) + + def __getitem__(self,project_name): + """Return a newest-to-oldest list of distributions for `project_name` + """ + try: + return self._cache[project_name] + except KeyError: + project_name = project_name.lower() + if project_name not in self._distmap: + return [] + + if project_name not in self._cache: + dists = self._cache[project_name] = self._distmap[project_name] + _sort_dists(dists) + + return self._cache[project_name] + + def add(self,dist): + """Add `dist` if we ``can_add()`` it and it isn't already added""" + if self.can_add(dist) and dist.has_version(): + dists = self._distmap.setdefault(dist.key,[]) + if dist not in dists: + dists.append(dist) + if dist.key in self._cache: + _sort_dists(self._cache[dist.key]) + + + def best_match(self, req, working_set, installer=None): + """Find distribution best matching `req` and usable on `working_set` + + This calls the ``find(req)`` method of the `working_set` to see if a + suitable distribution is already active. (This may raise + ``VersionConflict`` if an unsuitable version of the project is already + active in the specified `working_set`.) If a suitable distribution + isn't active, this method returns the newest distribution in the + environment that meets the ``Requirement`` in `req`. If no suitable + distribution is found, and `installer` is supplied, then the result of + calling the environment's ``obtain(req, installer)`` method will be + returned. + """ + dist = working_set.find(req) + if dist is not None: + return dist + for dist in self[req.key]: + if dist in req: + return dist + return self.obtain(req, installer) # try and download/install + + def obtain(self, requirement, installer=None): + """Obtain a distribution matching `requirement` (e.g. via download) + + Obtain a distro that matches requirement (e.g. via download). In the + base ``Environment`` class, this routine just returns + ``installer(requirement)``, unless `installer` is None, in which case + None is returned instead. This method is a hook that allows subclasses + to attempt other ways of obtaining a distribution before falling back + to the `installer` argument.""" + if installer is not None: + return installer(requirement) + + def __iter__(self): + """Yield the unique project names of the available distributions""" + for key in self._distmap.keys(): + if self[key]: yield key + + + + + def __iadd__(self, other): + """In-place addition of a distribution or environment""" + if isinstance(other,Distribution): + self.add(other) + elif isinstance(other,Environment): + for project in other: + for dist in other[project]: + self.add(dist) + else: + raise TypeError("Can't add %r to environment" % (other,)) + return self + + def __add__(self, other): + """Add an environment or distribution to an environment""" + new = self.__class__([], platform=None, python=None) + for env in self, other: + new += env + return new + + +AvailableDistributions = Environment # XXX backward compatibility + + +class ExtractionError(RuntimeError): + """An error occurred extracting a resource + + The following attributes are available from instances of this exception: + + manager + The resource manager that raised this exception + + cache_path + The base directory for resource extraction + + original_error + The exception instance that caused extraction to fail + """ + + + + +class ResourceManager: + """Manage resource extraction and packages""" + extraction_path = None + + def __init__(self): + self.cached_files = {} + + def resource_exists(self, package_or_requirement, resource_name): + """Does the named resource exist?""" + return get_provider(package_or_requirement).has_resource(resource_name) + + def resource_isdir(self, package_or_requirement, resource_name): + """Is the named resource an existing directory?""" + return get_provider(package_or_requirement).resource_isdir( + resource_name + ) + + def resource_filename(self, package_or_requirement, resource_name): + """Return a true filesystem path for specified resource""" + return get_provider(package_or_requirement).get_resource_filename( + self, resource_name + ) + + def resource_stream(self, package_or_requirement, resource_name): + """Return a readable file-like object for specified resource""" + return get_provider(package_or_requirement).get_resource_stream( + self, resource_name + ) + + def resource_string(self, package_or_requirement, resource_name): + """Return specified resource as a string""" + return get_provider(package_or_requirement).get_resource_string( + self, resource_name + ) + + def resource_listdir(self, package_or_requirement, resource_name): + """List the contents of the named resource directory""" + return get_provider(package_or_requirement).resource_listdir( + resource_name + ) + + def extraction_error(self): + """Give an error message for problems extracting file(s)""" + + old_exc = sys.exc_info()[1] + cache_path = self.extraction_path or get_default_cache() + + err = ExtractionError("""Can't extract file(s) to egg cache + +The following error occurred while trying to extract file(s) to the Python egg +cache: + + %s + +The Python egg cache directory is currently set to: + + %s + +Perhaps your account does not have write access to this directory? You can +change the cache directory by setting the PYTHON_EGG_CACHE environment +variable to point to an accessible directory. +""" % (old_exc, cache_path) + ) + err.manager = self + err.cache_path = cache_path + err.original_error = old_exc + raise err + + + + + + + + + + + + + + + + def get_cache_path(self, archive_name, names=()): + """Return absolute location in cache for `archive_name` and `names` + + The parent directory of the resulting path will be created if it does + not already exist. `archive_name` should be the base filename of the + enclosing egg (which may not be the name of the enclosing zipfile!), + including its ".egg" extension. `names`, if provided, should be a + sequence of path name parts "under" the egg's extraction location. + + This method should only be called by resource providers that need to + obtain an extraction location, and only for names they intend to + extract, as it tracks the generated names for possible cleanup later. + """ + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name+'-tmp', *names) + try: + ensure_directory(target_path) + except: + self.extraction_error() + + self.cached_files[target_path] = 1 + return target_path + + + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` + + This is where Mac header rewrites should be done; other platforms don't + have anything special they should do. + + Resource providers should call this method ONLY after successfully + extracting a compressed resource. They must NOT call it on resources + that are already in the filesystem. + + `tempname` is the current (temporary) name of the file, and `filename` + is the name it will be renamed to by the caller after this routine + returns. + """ + # XXX + + + def set_extraction_path(self, path): + """Set the base path where resources will be extracted to, if needed. + + If you do not call this routine before any extractions take place, the + path defaults to the return value of ``get_default_cache()``. (Which + is based on the ``PYTHON_EGG_CACHE`` environment variable, with various + platform-specific fallbacks. See that routine's documentation for more + details.) + + Resources are extracted to subdirectories of this path based upon + information given by the ``IResourceProvider``. You may set this to a + temporary directory, but then you must call ``cleanup_resources()`` to + delete the extracted files when done. There is no guarantee that + ``cleanup_resources()`` will be able to remove all extracted files. + + (Note: you may not change the extraction path for a given resource + manager once resources have been extracted, unless you first call + ``cleanup_resources()``.) + """ + if self.cached_files: + raise ValueError( + "Can't change extraction path, files already extracted" + ) + + self.extraction_path = path + + def cleanup_resources(self, force=False): + """ + Delete all extracted resource files and directories, returning a list + of the file and directory names that could not be successfully removed. + This function does not have any concurrency protection, so it should + generally only be called when the extraction path is a temporary + directory exclusive to a single process. This method is not + automatically called; you must call it explicitly or register it as an + ``atexit`` function if you wish to ensure cleanup of a temporary + directory used for extractions. + """ + # XXX + + + +def get_default_cache(): + """Determine the default cache location + + This returns the ``PYTHON_EGG_CACHE`` environment variable, if set. + Otherwise, on Windows, it returns a "Python-Eggs" subdirectory of the + "Application Data" directory. On all other systems, it's "~/.python-eggs". + """ + try: + return os.environ['PYTHON_EGG_CACHE'] + except KeyError: + pass + + if os.name!='nt': + return os.path.expanduser('~/.python-eggs') + + app_data = 'Application Data' # XXX this may be locale-specific! + app_homes = [ + (('APPDATA',), None), # best option, should be locale-safe + (('USERPROFILE',), app_data), + (('HOMEDRIVE','HOMEPATH'), app_data), + (('HOMEPATH',), app_data), + (('HOME',), None), + (('WINDIR',), app_data), # 95/98/ME + ] + + for keys, subdir in app_homes: + dirname = '' + for key in keys: + if key in os.environ: + dirname = os.path.join(os.environ[key]) + else: + break + else: + if subdir: + dirname = os.path.join(dirname,subdir) + return os.path.join(dirname, 'Python-Eggs') + else: + raise RuntimeError( + "Please set the PYTHON_EGG_CACHE enviroment variable" + ) + +def safe_name(name): + """Convert an arbitrary string to a standard distribution name + + Any runs of non-alphanumeric/. characters are replaced with a single '-'. + """ + return re.sub('[^A-Za-z0-9.]+', '-', name) + + +def safe_version(version): + """Convert an arbitrary string to a standard version string + + Spaces become dots, and all other non-alphanumeric characters become + dashes, with runs of multiple dashes condensed to a single dash. + """ + version = version.replace(' ','.') + return re.sub('[^A-Za-z0-9.]+', '-', version) + + +def safe_extra(extra): + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + """ + return re.sub('[^A-Za-z0-9.]+', '_', extra).lower() + + +def to_filename(name): + """Convert a project or version name to its filename-escaped form + + Any '-' characters are currently replaced with '_'. + """ + return name.replace('-','_') + + + + + + + + +class NullProvider: + """Try to implement resources and metadata for arbitrary PEP 302 loaders""" + + egg_name = None + egg_info = None + loader = None + + def __init__(self, module): + self.loader = getattr(module, '__loader__', None) + self.module_path = os.path.dirname(getattr(module, '__file__', '')) + + def get_resource_filename(self, manager, resource_name): + return self._fn(self.module_path, resource_name) + + def get_resource_stream(self, manager, resource_name): + return StringIO(self.get_resource_string(manager, resource_name)) + + def get_resource_string(self, manager, resource_name): + return self._get(self._fn(self.module_path, resource_name)) + + def has_resource(self, resource_name): + return self._has(self._fn(self.module_path, resource_name)) + + def has_metadata(self, name): + return self.egg_info and self._has(self._fn(self.egg_info,name)) + + def get_metadata(self, name): + if not self.egg_info: + return "" + return self._get(self._fn(self.egg_info,name)) + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + def resource_isdir(self,resource_name): + return self._isdir(self._fn(self.module_path, resource_name)) + + def metadata_isdir(self,name): + return self.egg_info and self._isdir(self._fn(self.egg_info,name)) + + + def resource_listdir(self,resource_name): + return self._listdir(self._fn(self.module_path,resource_name)) + + def metadata_listdir(self,name): + if self.egg_info: + return self._listdir(self._fn(self.egg_info,name)) + return [] + + def run_script(self,script_name,namespace): + script = 'scripts/'+script_name + if not self.has_metadata(script): + raise ResolutionError("No script named %r" % script_name) + script_text = self.get_metadata(script).replace('\r\n','\n') + script_text = script_text.replace('\r','\n') + script_filename = self._fn(self.egg_info,script) + namespace['__file__'] = script_filename + if os.path.exists(script_filename): + execfile(script_filename, namespace, namespace) + else: + from linecache import cache + cache[script_filename] = ( + len(script_text), 0, script_text.split('\n'), script_filename + ) + script_code = compile(script_text,script_filename,'exec') + exec script_code in namespace, namespace + + def _has(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _isdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _listdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _fn(self, base, resource_name): + return os.path.join(base, *resource_name.split('/')) + + def _get(self, path): + if hasattr(self.loader, 'get_data'): + return self.loader.get_data(path) + raise NotImplementedError( + "Can't perform this operation for loaders without 'get_data()'" + ) + +register_loader_type(object, NullProvider) + + +class EggProvider(NullProvider): + """Provider based on a virtual filesystem""" + + def __init__(self,module): + NullProvider.__init__(self,module) + self._setup_prefix() + + def _setup_prefix(self): + # we assume here that our metadata may be nested inside a "basket" + # of multiple eggs; that's why we use module_path instead of .archive + path = self.module_path + old = None + while path!=old: + if path.lower().endswith('.egg'): + self.egg_name = os.path.basename(path) + self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path + break + old = path + path, base = os.path.split(path) + + + + + + + + +class DefaultProvider(EggProvider): + """Provides access to package resources in the filesystem""" + + def _has(self, path): + return os.path.exists(path) + + def _isdir(self,path): + return os.path.isdir(path) + + def _listdir(self,path): + return os.listdir(path) + + def get_resource_stream(self, manager, resource_name): + return open(self._fn(self.module_path, resource_name), 'rb') + + def _get(self, path): + stream = open(path, 'rb') + try: + return stream.read() + finally: + stream.close() + +register_loader_type(type(None), DefaultProvider) + + +class EmptyProvider(NullProvider): + """Provider that returns nothing for all requests""" + + _isdir = _has = lambda self,path: False + _get = lambda self,path: '' + _listdir = lambda self,path: [] + module_path = None + + def __init__(self): + pass + +empty_provider = EmptyProvider() + + + + +class ZipProvider(EggProvider): + """Resource support for zips and eggs""" + + eagers = None + + def __init__(self, module): + EggProvider.__init__(self,module) + self.zipinfo = zipimport._zip_directory_cache[self.loader.archive] + self.zip_pre = self.loader.archive+os.sep + + def _zipinfo_name(self, fspath): + # Convert a virtual filename (full path to file) into a zipfile subpath + # usable with the zipimport directory cache for our target archive + if fspath.startswith(self.zip_pre): + return fspath[len(self.zip_pre):] + raise AssertionError( + "%s is not a subpath of %s" % (fspath,self.zip_pre) + ) + + def _parts(self,zip_path): + # Convert a zipfile subpath into an egg-relative path part list + fspath = self.zip_pre+zip_path # pseudo-fs path + if fspath.startswith(self.egg_root+os.sep): + return fspath[len(self.egg_root)+1:].split(os.sep) + raise AssertionError( + "%s is not a subpath of %s" % (fspath,self.egg_root) + ) + + def get_resource_filename(self, manager, resource_name): + if not self.egg_name: + raise NotImplementedError( + "resource_filename() only supported for .egg, not .zip" + ) + # no need to lock for extraction, since we use temp names + zip_path = self._resource_to_zip(resource_name) + eagers = self._get_eager_resources() + if '/'.join(self._parts(zip_path)) in eagers: + for name in eagers: + self._extract_resource(manager, self._eager_to_zip(name)) + return self._extract_resource(manager, zip_path) + + def _extract_resource(self, manager, zip_path): + + if zip_path in self._index(): + for name in self._index()[zip_path]: + last = self._extract_resource( + manager, os.path.join(zip_path, name) + ) + return os.path.dirname(last) # return the extracted directory name + + zip_stat = self.zipinfo[zip_path] + t,d,size = zip_stat[5], zip_stat[6], zip_stat[3] + date_time = ( + (d>>9)+1980, (d>>5)&0xF, d&0x1F, # ymd + (t&0xFFFF)>>11, (t>>5)&0x3F, (t&0x1F) * 2, 0, 0, -1 # hms, etc. + ) + timestamp = time.mktime(date_time) + + try: + real_path = manager.get_cache_path( + self.egg_name, self._parts(zip_path) + ) + + if os.path.isfile(real_path): + stat = os.stat(real_path) + if stat.st_size==size and stat.st_mtime==timestamp: + # size and stamp match, don't bother extracting + return real_path + + outf, tmpnam = _mkstemp(".$extract", dir=os.path.dirname(real_path)) + os.write(outf, self.loader.get_data(zip_path)) + os.close(outf) + utime(tmpnam, (timestamp,timestamp)) + manager.postprocess(tmpnam, real_path) + + try: + rename(tmpnam, real_path) + + except os.error: + if os.path.isfile(real_path): + stat = os.stat(real_path) + + if stat.st_size==size and stat.st_mtime==timestamp: + # size and stamp match, somebody did it just ahead of + # us, so we're done + return real_path + elif os.name=='nt': # Windows, del old file and retry + unlink(real_path) + rename(tmpnam, real_path) + return real_path + raise + + except os.error: + manager.extraction_error() # report a user-friendly error + + return real_path + + def _get_eager_resources(self): + if self.eagers is None: + eagers = [] + for name in ('native_libs.txt', 'eager_resources.txt'): + if self.has_metadata(name): + eagers.extend(self.get_metadata_lines(name)) + self.eagers = eagers + return self.eagers + + def _index(self): + try: + return self._dirindex + except AttributeError: + ind = {} + for path in self.zipinfo: + parts = path.split(os.sep) + while parts: + parent = os.sep.join(parts[:-1]) + if parent in ind: + ind[parent].append(parts[-1]) + break + else: + ind[parent] = [parts.pop()] + self._dirindex = ind + return ind + + def _has(self, fspath): + zip_path = self._zipinfo_name(fspath) + return zip_path in self.zipinfo or zip_path in self._index() + + def _isdir(self,fspath): + return self._zipinfo_name(fspath) in self._index() + + def _listdir(self,fspath): + return list(self._index().get(self._zipinfo_name(fspath), ())) + + def _eager_to_zip(self,resource_name): + return self._zipinfo_name(self._fn(self.egg_root,resource_name)) + + def _resource_to_zip(self,resource_name): + return self._zipinfo_name(self._fn(self.module_path,resource_name)) + +register_loader_type(zipimport.zipimporter, ZipProvider) + + + + + + + + + + + + + + + + + + + + + + + + +class FileMetadata(EmptyProvider): + """Metadata handler for standalone PKG-INFO files + + Usage:: + + metadata = FileMetadata("/path/to/PKG-INFO") + + This provider rejects all data and metadata requests except for PKG-INFO, + which is treated as existing, and will be the contents of the file at + the provided location. + """ + + def __init__(self,path): + self.path = path + + def has_metadata(self,name): + return name=='PKG-INFO' + + def get_metadata(self,name): + if name=='PKG-INFO': + return open(self.path,'rU').read() + raise KeyError("No metadata except PKG-INFO is available") + + def get_metadata_lines(self,name): + return yield_lines(self.get_metadata(name)) + + + + + + + + + + + + + + + + +class PathMetadata(DefaultProvider): + """Metadata provider for egg directories + + Usage:: + + # Development eggs: + + egg_info = "/path/to/PackageName.egg-info" + base_dir = os.path.dirname(egg_info) + metadata = PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + dist = Distribution(basedir,project_name=dist_name,metadata=metadata) + + # Unpacked egg directories: + + egg_path = "/path/to/PackageName-ver-pyver-etc.egg" + metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) + dist = Distribution.from_filename(egg_path, metadata=metadata) + """ + + def __init__(self, path, egg_info): + self.module_path = path + self.egg_info = egg_info + + +class EggMetadata(ZipProvider): + """Metadata provider for .egg files""" + + def __init__(self, importer): + """Create a metadata provider from a zipimporter""" + + self.zipinfo = zipimport._zip_directory_cache[importer.archive] + self.zip_pre = importer.archive+os.sep + self.loader = importer + if importer.prefix: + self.module_path = os.path.join(importer.archive, importer.prefix) + else: + self.module_path = importer.archive + self._setup_prefix() + + +class ImpWrapper: + """PEP 302 Importer that wraps Python's "normal" import algorithm""" + + def __init__(self, path=None): + self.path = path + + def find_module(self, fullname, path=None): + subname = fullname.split(".")[-1] + if subname != fullname and self.path is None: + return None + if self.path is None: + path = None + else: + path = [self.path] + try: + file, filename, etc = imp.find_module(subname, path) + except ImportError: + return None + return ImpLoader(file, filename, etc) + + +class ImpLoader: + """PEP 302 Loader that wraps Python's "normal" import algorithm""" + + def __init__(self, file, filename, etc): + self.file = file + self.filename = filename + self.etc = etc + + def load_module(self, fullname): + try: + mod = imp.load_module(fullname, self.file, self.filename, self.etc) + finally: + if self.file: self.file.close() + # Note: we don't set __loader__ because we want the module to look + # normal; i.e. this is just a wrapper for standard import machinery + return mod + + + + +def get_importer(path_item): + """Retrieve a PEP 302 "importer" for the given path item + + If there is no importer, this returns a wrapper around the builtin import + machinery. The returned importer is only cached if it was created by a + path hook. + """ + try: + importer = sys.path_importer_cache[path_item] + except KeyError: + for hook in sys.path_hooks: + try: + importer = hook(path_item) + except ImportError: + pass + else: + break + else: + importer = None + + sys.path_importer_cache.setdefault(path_item,importer) + if importer is None: + try: + importer = ImpWrapper(path_item) + except ImportError: + pass + return importer + +try: + from pkgutil import get_importer, ImpImporter +except ImportError: + pass # Python 2.3 or 2.4, use our own implementation +else: + ImpWrapper = ImpImporter # Python 2.5, use pkgutil's implementation + del ImpLoader, ImpImporter + + + + + + +_distribution_finders = {} + +def register_finder(importer_type, distribution_finder): + """Register `distribution_finder` to find distributions in sys.path items + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `distribution_finder` is a callable that, passed a path + item and the importer instance, yields ``Distribution`` instances found on + that path item. See ``pkg_resources.find_on_path`` for an example.""" + _distribution_finders[importer_type] = distribution_finder + + +def find_distributions(path_item, only=False): + """Yield distributions accessible via `path_item`""" + importer = get_importer(path_item) + finder = _find_adapter(_distribution_finders, importer) + return finder(importer, path_item, only) + +def find_in_zip(importer, path_item, only=False): + metadata = EggMetadata(importer) + if metadata.has_metadata('PKG-INFO'): + yield Distribution.from_filename(path_item, metadata=metadata) + if only: + return # don't yield nested distros + for subitem in metadata.resource_listdir('/'): + if subitem.endswith('.egg'): + subpath = os.path.join(path_item, subitem) + for dist in find_in_zip(zipimport.zipimporter(subpath), subpath): + yield dist + +register_finder(zipimport.zipimporter, find_in_zip) + +def StringIO(*args, **kw): + """Thunk to load the real StringIO on demand""" + global StringIO + try: + from cStringIO import StringIO + except ImportError: + from StringIO import StringIO + return StringIO(*args,**kw) + +def find_nothing(importer, path_item, only=False): + return () +register_finder(object,find_nothing) + +def find_on_path(importer, path_item, only=False): + """Yield distributions accessible on a sys.path directory""" + path_item = _normalize_cached(path_item) + + if os.path.isdir(path_item): + if path_item.lower().endswith('.egg'): + # unpacked egg + yield Distribution.from_filename( + path_item, metadata=PathMetadata( + path_item, os.path.join(path_item,'EGG-INFO') + ) + ) + else: + # scan for .egg and .egg-info in directory + for entry in os.listdir(path_item): + lower = entry.lower() + if lower.endswith('.egg-info'): + fullpath = os.path.join(path_item, entry) + if os.path.isdir(fullpath): + # egg-info directory, allow getting metadata + metadata = PathMetadata(path_item, fullpath) + else: + metadata = FileMetadata(fullpath) + yield Distribution.from_location( + path_item,entry,metadata,precedence=DEVELOP_DIST + ) + elif not only and lower.endswith('.egg'): + for dist in find_distributions(os.path.join(path_item, entry)): + yield dist + elif not only and lower.endswith('.egg-link'): + for line in file(os.path.join(path_item, entry)): + if not line.strip(): continue + for item in find_distributions(line.rstrip()): + yield item + +register_finder(ImpWrapper,find_on_path) + +_namespace_handlers = {} +_namespace_packages = {} + +def register_namespace_handler(importer_type, namespace_handler): + """Register `namespace_handler` to declare namespace packages + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `namespace_handler` is a callable like this:: + + def namespace_handler(importer,path_entry,moduleName,module): + # return a path_entry to use for child packages + + Namespace handlers are only called if the importer object has already + agreed that it can handle the relevant path item, and they should only + return a subpath if the module __path__ does not already contain an + equivalent subpath. For an example namespace handler, see + ``pkg_resources.file_ns_handler``. + """ + _namespace_handlers[importer_type] = namespace_handler + +def _handle_ns(packageName, path_item): + """Ensure that named package includes a subpath of path_item (if needed)""" + importer = get_importer(path_item) + if importer is None: + return None + loader = importer.find_module(packageName) + if loader is None: + return None + module = sys.modules.get(packageName) + if module is None: + module = sys.modules[packageName] = new.module(packageName) + module.__path__ = []; _set_parent_ns(packageName) + elif not hasattr(module,'__path__'): + raise TypeError("Not a package:", packageName) + handler = _find_adapter(_namespace_handlers, importer) + subpath = handler(importer,path_item,packageName,module) + if subpath is not None: + path = module.__path__; path.append(subpath) + loader.load_module(packageName); module.__path__ = path + return subpath + +def declare_namespace(packageName): + """Declare that package 'packageName' is a namespace package""" + + imp.acquire_lock() + try: + if packageName in _namespace_packages: + return + + path, parent = sys.path, None + if '.' in packageName: + parent = '.'.join(packageName.split('.')[:-1]) + declare_namespace(parent) + __import__(parent) + try: + path = sys.modules[parent].__path__ + except AttributeError: + raise TypeError("Not a package:", parent) + + # Track what packages are namespaces, so when new path items are added, + # they can be updated + _namespace_packages.setdefault(parent,[]).append(packageName) + _namespace_packages.setdefault(packageName,[]) + + for path_item in path: + # Ensure all the parent's path items are reflected in the child, + # if they apply + _handle_ns(packageName, path_item) + + finally: + imp.release_lock() + +def fixup_namespace_packages(path_item, parent=None): + """Ensure that previously-declared namespace packages include path_item""" + imp.acquire_lock() + try: + for package in _namespace_packages.get(parent,()): + subpath = _handle_ns(package, path_item) + if subpath: fixup_namespace_packages(subpath,package) + finally: + imp.release_lock() + +def file_ns_handler(importer, path_item, packageName, module): + """Compute an ns-package subpath for a filesystem or zipfile importer""" + + subpath = os.path.join(path_item, packageName.split('.')[-1]) + normalized = _normalize_cached(subpath) + for item in module.__path__: + if _normalize_cached(item)==normalized: + break + else: + # Only return the path if it's not already there + return subpath + +register_namespace_handler(ImpWrapper,file_ns_handler) +register_namespace_handler(zipimport.zipimporter,file_ns_handler) + + +def null_ns_handler(importer, path_item, packageName, module): + return None + +register_namespace_handler(object,null_ns_handler) + + +def normalize_path(filename): + """Normalize a file/dir name for comparison purposes""" + return os.path.normcase(os.path.realpath(filename)) + +def _normalize_cached(filename,_cache={}): + try: + return _cache[filename] + except KeyError: + _cache[filename] = result = normalize_path(filename) + return result + +def _set_parent_ns(packageName): + parts = packageName.split('.') + name = parts.pop() + if parts: + parent = '.'.join(parts) + setattr(sys.modules[parent], name, sys.modules[packageName]) + + +def yield_lines(strs): + """Yield non-empty/non-comment lines of a ``basestring`` or sequence""" + if isinstance(strs,basestring): + for s in strs.splitlines(): + s = s.strip() + if s and not s.startswith('#'): # skip blank lines/comments + yield s + else: + for ss in strs: + for s in yield_lines(ss): + yield s + +LINE_END = re.compile(r"\s*(#.*)?$").match # whitespace and comment +CONTINUE = re.compile(r"\s*\\\s*(#.*)?$").match # line continuation +DISTRO = re.compile(r"\s*((\w|[-.])+)").match # Distribution or extra +VERSION = re.compile(r"\s*(<=?|>=?|==|!=)\s*((\w|[-.])+)").match # ver. info +COMMA = re.compile(r"\s*,").match # comma between items +OBRACKET = re.compile(r"\s*\[").match +CBRACKET = re.compile(r"\s*\]").match +MODULE = re.compile(r"\w+(\.\w+)*$").match +EGG_NAME = re.compile( + r"(?P<name>[^-]+)" + r"( -(?P<ver>[^-]+) (-py(?P<pyver>[^-]+) (-(?P<plat>.+))? )? )?", + re.VERBOSE | re.IGNORECASE +).match + +component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE) +replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c'}.get + +def _parse_version_parts(s): + for part in component_re.split(s): + part = replace(part,part) + if not part or part=='.': + continue + if part[:1] in '0123456789': + yield part.zfill(8) # pad for numeric comparison + else: + yield '*'+part + + yield '*final' # ensure that alpha/beta/candidate are before final + +def parse_version(s): + """Convert a version string to a chronologically-sortable key + + This is a rough cross between distutils' StrictVersion and LooseVersion; + if you give it versions that would work with StrictVersion, then it behaves + the same; otherwise it acts like a slightly-smarter LooseVersion. It is + *possible* to create pathological version coding schemes that will fool + this parser, but they should be very rare in practice. + + The returned value will be a tuple of strings. Numeric portions of the + version are padded to 8 digits so they will compare numerically, but + without relying on how numbers compare relative to strings. Dots are + dropped, but dashes are retained. Trailing zeros between alpha segments + or dashes are suppressed, so that e.g. "2.4.0" is considered the same as + "2.4". Alphanumeric parts are lower-cased. + + The algorithm assumes that strings like "-" and any alpha string that + alphabetically follows "final" represents a "patch level". So, "2.4-1" + is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is + considered newer than "2.4-1", whic in turn is newer than "2.4". + + Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that + come before "final" alphabetically) are assumed to be pre-release versions, + so that the version "2.4" is considered newer than "2.4a1". + + Finally, to handle miscellaneous cases, the strings "pre", "preview", and + "rc" are treated as if they were "c", i.e. as though they were release + candidates, and therefore are not as new as a version string that does not + contain them. + """ + parts = [] + for part in _parse_version_parts(s.lower()): + if part.startswith('*'): + if part<'*final': # remove '-' before a prerelease tag + while parts and parts[-1]=='*final-': parts.pop() + # remove trailing zeros from each series of numeric parts + while parts and parts[-1]=='00000000': + parts.pop() + parts.append(part) + return tuple(parts) + +class EntryPoint(object): + """Object representing an advertised importable object""" + + def __init__(self, name, module_name, attrs=(), extras=(), dist=None): + if not MODULE(module_name): + raise ValueError("Invalid module name", module_name) + self.name = name + self.module_name = module_name + self.attrs = tuple(attrs) + self.extras = Requirement.parse(("x[%s]" % ','.join(extras))).extras + self.dist = dist + + def __str__(self): + s = "%s = %s" % (self.name, self.module_name) + if self.attrs: + s += ':' + '.'.join(self.attrs) + if self.extras: + s += ' [%s]' % ','.join(self.extras) + return s + + def __repr__(self): + return "EntryPoint.parse(%r)" % str(self) + + def load(self, require=True, env=None, installer=None): + if require: self.require(env, installer) + entry = __import__(self.module_name, globals(),globals(), ['__name__']) + for attr in self.attrs: + try: + entry = getattr(entry,attr) + except AttributeError: + raise ImportError("%r has no %r attribute" % (entry,attr)) + return entry + + def require(self, env=None, installer=None): + if self.extras and not self.dist: + raise UnknownExtra("Can't require() without a distribution", self) + map(working_set.add, + working_set.resolve(self.dist.requires(self.extras),env,installer)) + + + + #@classmethod + def parse(cls, src, dist=None): + """Parse a single entry point from string `src` + + Entry point syntax follows the form:: + + name = some.module:some.attr [extra1,extra2] + + The entry name and module name are required, but the ``:attrs`` and + ``[extras]`` parts are optional + """ + try: + attrs = extras = () + name,value = src.split('=',1) + if '[' in value: + value,extras = value.split('[',1) + req = Requirement.parse("x["+extras) + if req.specs: raise ValueError + extras = req.extras + if ':' in value: + value,attrs = value.split(':',1) + if not MODULE(attrs.rstrip()): + raise ValueError + attrs = attrs.rstrip().split('.') + except ValueError: + raise ValueError( + "EntryPoint must be in 'name=module:attrs [extras]' format", + src + ) + else: + return cls(name.strip(), value.strip(), attrs, extras, dist) + + parse = classmethod(parse) + + + + + + + + + #@classmethod + def parse_group(cls, group, lines, dist=None): + """Parse an entry point group""" + if not MODULE(group): + raise ValueError("Invalid group name", group) + this = {} + for line in yield_lines(lines): + ep = cls.parse(line, dist) + if ep.name in this: + raise ValueError("Duplicate entry point", group, ep.name) + this[ep.name]=ep + return this + + parse_group = classmethod(parse_group) + + #@classmethod + def parse_map(cls, data, dist=None): + """Parse a map of entry point groups""" + if isinstance(data,dict): + data = data.items() + else: + data = split_sections(data) + maps = {} + for group, lines in data: + if group is None: + if not lines: + continue + raise ValueError("Entry points must be listed in groups") + group = group.strip() + if group in maps: + raise ValueError("Duplicate group name", group) + maps[group] = cls.parse_group(group, lines, dist) + return maps + + parse_map = classmethod(parse_map) + + + + + + +class Distribution(object): + """Wrap an actual or potential sys.path entry w/metadata""" + def __init__(self, + location=None, metadata=None, project_name=None, version=None, + py_version=PY_MAJOR, platform=None, precedence = EGG_DIST + ): + self.project_name = safe_name(project_name or 'Unknown') + if version is not None: + self._version = safe_version(version) + self.py_version = py_version + self.platform = platform + self.location = location + self.precedence = precedence + self._provider = metadata or empty_provider + + #@classmethod + def from_location(cls,location,basename,metadata=None,**kw): + project_name, version, py_version, platform = [None]*4 + basename, ext = os.path.splitext(basename) + if ext.lower() in (".egg",".egg-info"): + match = EGG_NAME(basename) + if match: + project_name, version, py_version, platform = match.group( + 'name','ver','pyver','plat' + ) + return cls( + location, metadata, project_name=project_name, version=version, + py_version=py_version, platform=platform, **kw + ) + from_location = classmethod(from_location) + + hashcmp = property( + lambda self: ( + getattr(self,'parsed_version',()), self.precedence, self.key, + -len(self.location or ''), self.location, self.py_version, + self.platform + ) + ) + def __cmp__(self, other): return cmp(self.hashcmp, other) + def __hash__(self): return hash(self.hashcmp) + + # These properties have to be lazy so that we don't have to load any + # metadata until/unless it's actually needed. (i.e., some distributions + # may not know their name or version without loading PKG-INFO) + + #@property + def key(self): + try: + return self._key + except AttributeError: + self._key = key = self.project_name.lower() + return key + key = property(key) + + #@property + def parsed_version(self): + try: + return self._parsed_version + except AttributeError: + self._parsed_version = pv = parse_version(self.version) + return pv + + parsed_version = property(parsed_version) + + #@property + def version(self): + try: + return self._version + except AttributeError: + for line in self._get_metadata('PKG-INFO'): + if line.lower().startswith('version:'): + self._version = safe_version(line.split(':',1)[1].strip()) + return self._version + else: + raise ValueError( + "Missing 'Version:' header and/or PKG-INFO file", self + ) + version = property(version) + + + + + #@property + def _dep_map(self): + try: + return self.__dep_map + except AttributeError: + dm = self.__dep_map = {None: []} + for name in 'requires.txt', 'depends.txt': + for extra,reqs in split_sections(self._get_metadata(name)): + if extra: extra = safe_extra(extra) + dm.setdefault(extra,[]).extend(parse_requirements(reqs)) + return dm + _dep_map = property(_dep_map) + + def requires(self,extras=()): + """List of Requirements needed for this distro if `extras` are used""" + dm = self._dep_map + deps = [] + deps.extend(dm.get(None,())) + for ext in extras: + try: + deps.extend(dm[safe_extra(ext)]) + except KeyError: + raise UnknownExtra( + "%s has no such extra feature %r" % (self, ext) + ) + return deps + + def _get_metadata(self,name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): + yield line + + def activate(self,path=None): + """Ensure distribution is importable on `path` (default=sys.path)""" + if path is None: path = sys.path + self.insert_on(path) + if path is sys.path: + fixup_namespace_packages(self.location) + map(declare_namespace, self._get_metadata('namespace_packages.txt')) + + + def egg_name(self): + """Return what this distribution's standard .egg filename should be""" + filename = "%s-%s-py%s" % ( + to_filename(self.project_name), to_filename(self.version), + self.py_version or PY_MAJOR + ) + + if self.platform: + filename += '-'+self.platform + return filename + + def __repr__(self): + if self.location: + return "%s (%s)" % (self,self.location) + else: + return str(self) + + def __str__(self): + try: version = getattr(self,'version',None) + except ValueError: version = None + version = version or "[unknown version]" + return "%s %s" % (self.project_name,version) + + def __getattr__(self,attr): + """Delegate all unrecognized public attributes to .metadata provider""" + if attr.startswith('_'): + raise AttributeError,attr + return getattr(self._provider, attr) + + #@classmethod + def from_filename(cls,filename,metadata=None, **kw): + return cls.from_location( + _normalize_cached(filename), os.path.basename(filename), metadata, + **kw + ) + from_filename = classmethod(from_filename) + + def as_requirement(self): + """Return a ``Requirement`` that matches this distribution exactly""" + return Requirement.parse('%s==%s' % (self.project_name, self.version)) + + def load_entry_point(self, group, name): + """Return the `name` entry point of `group` or raise ImportError""" + ep = self.get_entry_info(group,name) + if ep is None: + raise ImportError("Entry point %r not found" % ((group,name),)) + return ep.load() + + def get_entry_map(self, group=None): + """Return the entry point map for `group`, or the full entry map""" + try: + ep_map = self._ep_map + except AttributeError: + ep_map = self._ep_map = EntryPoint.parse_map( + self._get_metadata('entry_points.txt'), self + ) + if group is not None: + return ep_map.get(group,{}) + return ep_map + + def get_entry_info(self, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return self.get_entry_map(group).get(name) + + + + + + + + + + + + + + + + + + + + def insert_on(self, path, loc = None): + """Insert self.location in path before its nearest parent directory""" + + loc = loc or self.location + if not loc: + return + + if path is sys.path: + self.check_version_conflict() + + nloc = _normalize_cached(loc) + bdir = os.path.dirname(nloc) + npath= map(_normalize_cached, path) + + bp = None + for p, item in enumerate(npath): + if item==nloc: + break + elif item==bdir: + path.insert(p, loc) + npath.insert(p, nloc) + break + else: + path.append(loc) + return + + # p is the spot where we found or inserted loc; now remove duplicates + while 1: + try: + np = npath.index(nloc, p+1) + except ValueError: + break + else: + del npath[np], path[np] + p = np # ha! + + return + + + + + def check_version_conflict(self): + if self.key=='setuptools': + return # ignore the inevitable setuptools self-conflicts :( + + nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) + loc = normalize_path(self.location) + for modname in self._get_metadata('top_level.txt'): + if (modname not in sys.modules or modname in nsp + or modname in _namespace_packages + ): + continue + + fn = getattr(sys.modules[modname], '__file__', None) + if fn and normalize_path(fn).startswith(loc): + continue + issue_warning( + "Module %s was already imported from %s, but %s is being added" + " to sys.path" % (modname, fn, self.location), + ) + + def has_version(self): + try: + self.version + except ValueError: + issue_warning("Unbuilt egg for "+repr(self)) + return False + return True + + def clone(self,**kw): + """Copy this distribution, substituting in any changed keyword args""" + for attr in ( + 'project_name', 'version', 'py_version', 'platform', 'location', + 'precedence' + ): + kw.setdefault(attr, getattr(self,attr,None)) + kw.setdefault('metadata', self._provider) + return self.__class__(**kw) + + + + + #@property + def extras(self): + return [dep for dep in self._dep_map if dep] + extras = property(extras) + + +def issue_warning(*args,**kw): + level = 1 + g = globals() + try: + # find the first stack frame that is *not* code in + # the pkg_resources module, to use for the warning + while sys._getframe(level).f_globals is g: + level += 1 + except ValueError: + pass + from warnings import warn + warn(stacklevel = level+1, *args, **kw) + + + + + + + + + + + + + + + + + + + + + + + +def parse_requirements(strs): + """Yield ``Requirement`` objects for each specification in `strs` + + `strs` must be an instance of ``basestring``, or a (possibly-nested) + iterable thereof. + """ + # create a steppable iterator, so we can handle \-continuations + lines = iter(yield_lines(strs)) + + def scan_list(ITEM,TERMINATOR,line,p,groups,item_name): + + items = [] + + while not TERMINATOR(line,p): + if CONTINUE(line,p): + try: + line = lines.next(); p = 0 + except StopIteration: + raise ValueError( + "\\ must not appear on the last nonblank line" + ) + + match = ITEM(line,p) + if not match: + raise ValueError("Expected "+item_name+" in",line,"at",line[p:]) + + items.append(match.group(*groups)) + p = match.end() + + match = COMMA(line,p) + if match: + p = match.end() # skip the comma + elif not TERMINATOR(line,p): + raise ValueError( + "Expected ',' or end-of-list in",line,"at",line[p:] + ) + + match = TERMINATOR(line,p) + if match: p = match.end() # skip the terminator, if any + return line, p, items + + for line in lines: + match = DISTRO(line) + if not match: + raise ValueError("Missing distribution spec", line) + project_name = match.group(1) + p = match.end() + extras = [] + + match = OBRACKET(line,p) + if match: + p = match.end() + line, p, extras = scan_list( + DISTRO, CBRACKET, line, p, (1,), "'extra' name" + ) + + line, p, specs = scan_list(VERSION,LINE_END,line,p,(1,2),"version spec") + specs = [(op,safe_version(val)) for op,val in specs] + yield Requirement(project_name, specs, extras) + + +def _sort_dists(dists): + tmp = [(dist.hashcmp,dist) for dist in dists] + tmp.sort() + dists[::-1] = [d for hc,d in tmp] + + + + + + + + + + + + + + + + + +class Requirement: + def __init__(self, project_name, specs, extras): + """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" + self.unsafe_name, project_name = project_name, safe_name(project_name) + self.project_name, self.key = project_name, project_name.lower() + index = [(parse_version(v),state_machine[op],op,v) for op,v in specs] + index.sort() + self.specs = [(op,ver) for parsed,trans,op,ver in index] + self.index, self.extras = index, tuple(map(safe_extra,extras)) + self.hashCmp = ( + self.key, tuple([(op,parsed) for parsed,trans,op,ver in index]), + ImmutableSet(self.extras) + ) + self.__hash = hash(self.hashCmp) + + def __str__(self): + specs = ','.join([''.join(s) for s in self.specs]) + extras = ','.join(self.extras) + if extras: extras = '[%s]' % extras + return '%s%s%s' % (self.project_name, extras, specs) + + def __eq__(self,other): + return isinstance(other,Requirement) and self.hashCmp==other.hashCmp + + def __contains__(self,item): + if isinstance(item,Distribution): + if item.key <> self.key: return False + if self.index: item = item.parsed_version # only get if we need it + elif isinstance(item,basestring): + item = parse_version(item) + last = None + for parsed,trans,op,ver in self.index: + action = trans[cmp(item,parsed)] + if action=='F': return False + elif action=='T': return True + elif action=='+': last = True + elif action=='-' or last is None: last = False + if last is None: last = True # no rules encountered + return last + + + def __hash__(self): + return self.__hash + + def __repr__(self): return "Requirement.parse(%r)" % str(self) + + #@staticmethod + def parse(s): + reqs = list(parse_requirements(s)) + if reqs: + if len(reqs)==1: + return reqs[0] + raise ValueError("Expected only one requirement", s) + raise ValueError("No requirements found", s) + + parse = staticmethod(parse) + +state_machine = { + # =>< + '<' : '--T', + '<=': 'T-T', + '>' : 'F+F', + '>=': 'T+F', + '==': 'T..', + '!=': 'F++', +} + + +def _get_mro(cls): + """Get an mro for a type or classic class""" + if not isinstance(cls,type): + class cls(cls,object): pass + return cls.__mro__[1:] + return cls.__mro__ + +def _find_adapter(registry, ob): + """Return an adapter factory for `ob` from `registry`""" + for t in _get_mro(getattr(ob, '__class__', type(ob))): + if t in registry: + return registry[t] + + +def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + os.makedirs(dirname) + +def split_sections(s): + """Split a string or iterable thereof into (section,content) pairs + + Each ``section`` is a stripped version of the section header ("[section]") + and each ``content`` is a list of stripped lines excluding blank lines and + comment-only lines. If there are any such lines before the first section + header, they're returned in a first ``section`` of ``None``. + """ + section = None + content = [] + for line in yield_lines(s): + if line.startswith("["): + if line.endswith("]"): + if section or content: + yield section, content + section = line[1:-1].strip() + content = [] + else: + raise ValueError("Invalid section heading", line) + else: + content.append(line) + + # wrap up last segment + yield section, content + +def _mkstemp(*args,**kw): + from tempfile import mkstemp + old_open = os.open + try: + os.open = os_open # temporarily bypass sandboxing + return mkstemp(*args,**kw) + finally: + os.open = old_open # and then put it back + + +# Set up global resource manager +_manager = ResourceManager() +def _initialize(g): + for name in dir(_manager): + if not name.startswith('_'): + g[name] = getattr(_manager, name) +_initialize(globals()) + +# Prepare the master working set and make the ``require()`` API available +working_set = WorkingSet() +try: + # Does the main program list any requirements? + from __main__ import __requires__ +except ImportError: + pass # No: just use the default working set based on sys.path +else: + # Yes: ensure the requirements are met, by prefixing sys.path if necessary + try: + working_set.require(__requires__) + except VersionConflict: # try it without defaults already on sys.path + working_set = WorkingSet([]) # by starting with an empty path + for dist in working_set.resolve( + parse_requirements(__requires__), Environment() + ): + working_set.add(dist) + for entry in sys.path: # add any missing entries from sys.path + if entry not in working_set.entries: + working_set.add_entry(entry) + sys.path[:] = working_set.entries # then copy back to sys.path + +require = working_set.require +iter_entry_points = working_set.iter_entry_points +add_activation_listener = working_set.subscribe +run_script = working_set.run_script +run_main = run_script # backward compatibility +# Activate all distributions already on sys.path, and ensure that +# all distributions added to the working set in the future (e.g. by +# calling ``require()``) will get activated as well. +add_activation_listener(lambda dist: dist.activate()) +working_set.entries=[]; map(working_set.add_entry,sys.path) # match order + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pubsub.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pubsub.py new file mode 100644 index 0000000..ed17e19 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/pubsub.py @@ -0,0 +1,1263 @@ + +#--------------------------------------------------------------------------- +""" +This module provides a publish-subscribe component that allows +listeners to subcribe to messages of a given topic. Contrary to the +original wxPython.lib.pubsub module (which it is based on), it uses +weak referencing to the subscribers so the lifetime of subscribers +is not affected by Publisher. Also, callable objects can be used in +addition to functions and bound methods. See Publisher class docs for +more details. + +Thanks to Robb Shecter and Robin Dunn for having provided +the basis for this module (which now shares most of the concepts but +very little design or implementation with the original +wxPython.lib.pubsub). + +The publisher is a singleton instance of the PublisherClass class. You +access the instance via the Publisher object available from the module:: + + from wx.lib.pubsub import Publisher + Publisher().subscribe(...) + Publisher().sendMessage(...) + ... + +:Author: Oliver Schoenborn +:Since: Apr 2004 +:Version: $Id: pubsub.py 69063 2011-09-11 18:19:32Z CJP $ +:Copyright: \(c) 2004 Oliver Schoenborn +:License: wxWidgets +""" + +_implNotes = """ +Implementation notes +-------------------- + +In class Publisher, I represent the topics-listener set as a tree +where each node is a topic, and contains a list of listeners of that +topic, and a dictionary of subtopics of that topic. When the Publisher +is told to send a message for a given topic, it traverses the tree +down to the topic for which a message is being generated, all +listeners on the way get sent the message. + +Publisher currently uses a weak listener topic tree to store the +topics for each listener, and if a listener dies before being +unsubscribed, the tree is notified, and the tree eliminates the +listener from itself. + +Ideally, _TopicTreeNode would be a generic _TreeNode with named +subnodes, and _TopicTreeRoot would be a generic _Tree with named +nodes, and Publisher would store listeners in each node and a topic +tuple would be converted to a path in the tree. This would lead to a +much cleaner separation of concerns. But time is over, time to move on. +""" +#--------------------------------------------------------------------------- + +# for function and method parameter counting: +from types import InstanceType +from inspect import getargspec, ismethod, isfunction +# for weakly bound methods: +from new import instancemethod as InstanceMethod +from weakref import ref as WeakRef + +# ----------------------------------------------------------------------------- + +def _isbound(method): + """Return true if method is a bound method, false otherwise""" + assert ismethod(method) + return method.im_self is not None + + +def _paramMinCountFunc(function): + """Given a function, return pair (min,d) where min is minimum # of + args required, and d is number of default arguments.""" + assert isfunction(function) + (args, va, kwa, dflt) = getargspec(function) + lenDef = len(dflt or ()) + lenArgs = len(args or ()) + lenVA = int(va is not None) + return (lenArgs - lenDef + lenVA, lenDef) + + +def _paramMinCount(callableObject): + """ + Given a callable object (function, method or callable instance), + return pair (min,d) where min is minimum # of args required, and d + is number of default arguments. The 'self' parameter, in the case + of methods, is not counted. + """ + if type(callableObject) is InstanceType: + min, d = _paramMinCountFunc(callableObject.__call__.im_func) + return min-1, d + elif ismethod(callableObject): + min, d = _paramMinCountFunc(callableObject.im_func) + return min-1, d + elif isfunction(callableObject): + return _paramMinCountFunc(callableObject) + else: + raise 'Cannot determine type of callable: '+repr(callableObject) + + +def _tupleize(items): + """Convert items to tuple if not already one, + so items must be a list, tuple or non-sequence""" + if isinstance(items, list): + raise TypeError, 'Not allowed to tuple-ize a list' + elif isinstance(items, (str, unicode)) and items.find('.') != -1: + items = tuple(items.split('.')) + elif not isinstance(items, tuple): + items = (items,) + return items + + +def _getCallableName(callable): + """Get name for a callable, ie function, bound + method or callable instance""" + if ismethod(callable): + return '%s.%s ' % (callable.im_self, callable.im_func.func_name) + elif isfunction(callable): + return '%s ' % callable.__name__ + else: + return '%s ' % callable + + +def _removeItem(item, fromList): + """Attempt to remove item from fromList, return true + if successful, false otherwise.""" + try: + fromList.remove(item) + return True + except ValueError: + return False + + +# ----------------------------------------------------------------------------- + +class _WeakMethod: + """Represent a weak bound method, i.e. a method doesn't keep alive the + object that it is bound to. It uses WeakRef which, used on its own, + produces weak methods that are dead on creation, not very useful. + Typically, you will use the getRef() function instead of using + this class directly. """ + + def __init__(self, method, notifyDead = None): + """The method must be bound. notifyDead will be called when + object that method is bound to dies. """ + assert ismethod(method) + if method.im_self is None: + raise ValueError, "We need a bound method!" + if notifyDead is None: + self.objRef = WeakRef(method.im_self) + else: + self.objRef = WeakRef(method.im_self, notifyDead) + self.fun = method.im_func + self.cls = method.im_class + + def __call__(self): + """Returns a new.instancemethod if object for method still alive. + Otherwise return None. Note that instancemethod causes a + strong reference to object to be created, so shouldn't save + the return value of this call. Note also that this __call__ + is required only for compatibility with WeakRef.ref(), otherwise + there would be more efficient ways of providing this functionality.""" + if self.objRef() is None: + return None + else: + return InstanceMethod(self.fun, self.objRef(), self.cls) + + def __eq__(self, method2): + """Two WeakMethod objects compare equal if they refer to the same method + of the same instance. Thanks to Josiah Carlson for patch and clarifications + on how dict uses eq/cmp and hashing. """ + if not isinstance(method2, _WeakMethod): + return False + return self.fun is method2.fun \ + and self.objRef() is method2.objRef() \ + and self.objRef() is not None + + def __hash__(self): + """Hash is an optimization for dict searches, it need not + return different numbers for every different object. Some objects + are not hashable (eg objects of classes derived from dict) so no + hash(objRef()) in there, and hash(self.cls) would only be useful + in the rare case where instance method was rebound. """ + return hash(self.fun) + + def __repr__(self): + dead = '' + if self.objRef() is None: + dead = '; DEAD' + obj = '<%s at %s%s>' % (self.__class__, id(self), dead) + return obj + + def refs(self, weakRef): + """Return true if we are storing same object referred to by weakRef.""" + return self.objRef == weakRef + + +def _getWeakRef(obj, notifyDead=None): + """Get a weak reference to obj. If obj is a bound method, a _WeakMethod + object, that behaves like a WeakRef, is returned, if it is + anything else a WeakRef is returned. If obj is an unbound method, + a ValueError will be raised.""" + if ismethod(obj): + createRef = _WeakMethod + else: + createRef = WeakRef + + if notifyDead is None: + return createRef(obj) + else: + return createRef(obj, notifyDead) + + +# ----------------------------------------------------------------------------- + +def getStrAllTopics(): + """Function to call if, for whatever reason, you need to know + explicitely what is the string to use to indicate 'all topics'.""" + return '' + + +# alias, easier to see where used +ALL_TOPICS = getStrAllTopics() + +# ----------------------------------------------------------------------------- + + +class _NodeCallback: + """Encapsulate a weak reference to a method of a TopicTreeNode + in such a way that the method can be called, if the node is + still alive, but the callback does not *keep* the node alive. + Also, define two methods, preNotify() and noNotify(), which can + be redefined to something else, very useful for testing. + """ + + def __init__(self, obj): + self.objRef = _getWeakRef(obj) + + def __call__(self, weakCB): + notify = self.objRef() + if notify is not None: + self.preNotify(weakCB) + notify(weakCB) + else: + self.noNotify() + + def preNotify(self, dead): + """'Gets called just before our callback (self.objRef) is called""" + pass + + def noNotify(self): + """Gets called if the TopicTreeNode for this callback is dead""" + pass + + +class _TopicTreeNode: + """A node in the topic tree. This contains a list of callables + that are interested in the topic that this node is associated + with, and contains a dictionary of subtopics, whose associated + values are other _TopicTreeNodes. The topic of a node is not stored + in the node, so that the tree can be implemented as a dictionary + rather than a list, for ease of use (and, likely, performance). + + Note that it uses _NodeCallback to encapsulate a callback for + when a registered listener dies, possible thanks to WeakRef. + Whenever this callback is called, the onDeadListener() function, + passed in at construction time, is called (unless it is None). + """ + + def __init__(self, topicPath, onDeadListenerWeakCB): + self.__subtopics = {} + self.__callables = [] + self.__topicPath = topicPath + self.__onDeadListenerWeakCB = onDeadListenerWeakCB + + def getPathname(self): + """The complete node path to us, ie., the topic tuple that would lead to us""" + return self.__topicPath + + def createSubtopic(self, subtopic, topicPath): + """Create a child node for subtopic""" + return self.__subtopics.setdefault(subtopic, + _TopicTreeNode(topicPath, self.__onDeadListenerWeakCB)) + + def hasSubtopic(self, subtopic): + """Return true only if topic string is one of subtopics of this node""" + return self.__subtopics.has_key(subtopic) + + def getNode(self, subtopic): + """Return ref to node associated with subtopic""" + return self.__subtopics[subtopic] + + def addCallable(self, callable): + """Add a callable to list of callables for this topic node""" + try: + id = self.__callables.index(_getWeakRef(callable)) + return self.__callables[id] + except ValueError: + wrCall = _getWeakRef(callable, _NodeCallback(self.__notifyDead)) + self.__callables.append(wrCall) + return wrCall + + def getCallables(self): + """Get callables associated with this topic node""" + return [cb() for cb in self.__callables if cb() is not None] + + def hasCallable(self, callable): + """Return true if callable in this node""" + try: + self.__callables.index(_getWeakRef(callable)) + return True + except ValueError: + return False + + def sendMessage(self, message): + """Send a message to our callables""" + deliveryCount = 0 + for cb in self.__callables: + listener = cb() + if listener is not None: + listener(message) + deliveryCount += 1 + return deliveryCount + + def removeCallable(self, callable): + """Remove weak callable from our node (and return True). + Does nothing if not here (and returns False).""" + try: + self.__callables.remove(_getWeakRef(callable)) + return True + except ValueError: + return False + + def clearCallables(self): + """Abandon list of callables to caller. We no longer have + any callables after this method is called.""" + tmpList = [cb for cb in self.__callables if cb() is not None] + self.__callables = [] + return tmpList + + def __notifyDead(self, dead): + """Gets called when a listener dies, thanks to WeakRef""" + #print 'TreeNODE', `self`, 'received death certificate for ', dead + self.__cleanupDead() + if self.__onDeadListenerWeakCB is not None: + cb = self.__onDeadListenerWeakCB() + if cb is not None: + cb(dead) + + def __cleanupDead(self): + """Remove all dead objects from list of callables""" + self.__callables = [cb for cb in self.__callables if cb() is not None] + + def __str__(self): + """Print us in a not-so-friendly, but readable way, good for debugging.""" + strVal = [] + for callable in self.getCallables(): + strVal.append(_getCallableName(callable)) + for topic, node in self.__subtopics.iteritems(): + strVal.append(' (%s: %s)' %(topic, node)) + return ''.join(strVal) + + +class _TopicTreeRoot(_TopicTreeNode): + """ + The root of the tree knows how to access other node of the + tree and is the gateway of the tree user to the tree nodes. + It can create topics, and and remove callbacks, etc. + + For efficiency, it stores a dictionary of listener-topics, + so that unsubscribing a listener just requires finding the + topics associated to a listener, and finding the corresponding + nodes of the tree. Without it, unsubscribing would require + that we search the whole tree for all nodes that contain + given listener. Since Publisher is a singleton, it will + contain all topics in the system so it is likely to be a large + tree. However, it is possible that in some runs, unsubscribe() + is called very little by the user, in which case most unsubscriptions + are automatic, ie caused by the listeners dying. In this case, + a flag is set to indicate that the dictionary should be cleaned up + at the next opportunity. This is not necessary, it is just an + optimization. + """ + + def __init__(self): + self.__callbackDict = {} + self.__callbackDictCleanup = 0 + # all child nodes will call our __rootNotifyDead method + # when one of their registered listeners dies + _TopicTreeNode.__init__(self, (ALL_TOPICS,), + _getWeakRef(self.__rootNotifyDead)) + + def addTopic(self, topic, listener): + """Add topic to tree if doesnt exist, and add listener to topic node""" + assert isinstance(topic, tuple) + topicNode = self.__getTreeNode(topic, make=True) + weakCB = topicNode.addCallable(listener) + assert topicNode.hasCallable(listener) + + theList = self.__callbackDict.setdefault(weakCB, []) + assert self.__callbackDict.has_key(weakCB) + # add it only if we don't already have it + try: + weakTopicNode = WeakRef(topicNode) + theList.index(weakTopicNode) + except ValueError: + theList.append(weakTopicNode) + assert self.__callbackDict[weakCB].index(weakTopicNode) >= 0 + + def getTopics(self, listener): + """Return the list of topics for given listener""" + weakNodes = self.__callbackDict.get(_getWeakRef(listener), []) + return [weakNode().getPathname() for weakNode in weakNodes + if weakNode() is not None] + + def isSubscribed(self, listener, topic=None): + """Return true if listener is registered for topic specified. + If no topic specified, return true if subscribed to something. + Use topic=getStrAllTopics() to determine if a listener will receive + messages for all topics.""" + weakCB = _getWeakRef(listener) + if topic is None: + return self.__callbackDict.has_key(weakCB) + else: + topicPath = _tupleize(topic) + for weakNode in self.__callbackDict[weakCB]: + if topicPath == weakNode().getPathname(): + return True + return False + + def unsubscribe(self, listener, topicList): + """Remove listener from given list of topics. If topicList + doesn't have any topics for which listener has subscribed, + nothing happens.""" + weakCB = _getWeakRef(listener) + if not self.__callbackDict.has_key(weakCB): + return + + cbNodes = self.__callbackDict[weakCB] + if topicList is None: + for weakNode in cbNodes: + weakNode().removeCallable(listener) + del self.__callbackDict[weakCB] + return + + for weakNode in cbNodes: + node = weakNode() + if node is not None and node.getPathname() in topicList: + success = node.removeCallable(listener) + assert success == True + cbNodes.remove(weakNode) + assert not self.isSubscribed(listener, node.getPathname()) + + def unsubAll(self, topicList, onNoSuchTopic): + """Unsubscribe all listeners registered for any topic in + topicList. If a topic in the list does not exist, and + onNoSuchTopic is not None, a call + to onNoSuchTopic(topic) is done for that topic.""" + for topic in topicList: + node = self.__getTreeNode(topic) + if node is not None: + weakCallables = node.clearCallables() + for callable in weakCallables: + weakNodes = self.__callbackDict[callable] + success = _removeItem(WeakRef(node), weakNodes) + assert success == True + if weakNodes == []: + del self.__callbackDict[callable] + elif onNoSuchTopic is not None: + onNoSuchTopic(topic) + + def sendMessage(self, topic, message, onTopicNeverCreated): + """Send a message for given topic to all registered listeners. If + topic doesn't exist, call onTopicNeverCreated(topic).""" + # send to the all-toipcs listeners + deliveryCount = _TopicTreeNode.sendMessage(self, message) + # send to those who listen to given topic or any of its supertopics + node = self + for topicItem in topic: + assert topicItem != '' + if node.hasSubtopic(topicItem): + node = node.getNode(topicItem) + deliveryCount += node.sendMessage(message) + else: # topic never created, don't bother continuing + if onTopicNeverCreated is not None: + onTopicNeverCreated(topic) + break + return deliveryCount + + def numListeners(self): + """Return a pair (live, dead) with count of live and dead listeners in tree""" + dead, live = 0, 0 + for cb in self.__callbackDict: + if cb() is None: + dead += 1 + else: + live += 1 + return live, dead + + # clean up the callback dictionary after how many dead listeners + callbackDeadLimit = 10 + + def __rootNotifyDead(self, dead): + #print 'TreeROOT received death certificate for ', dead + self.__callbackDictCleanup += 1 + if self.__callbackDictCleanup > _TopicTreeRoot.callbackDeadLimit: + self.__callbackDictCleanup = 0 + oldDict = self.__callbackDict + self.__callbackDict = {} + for weakCB, weakNodes in oldDict.iteritems(): + if weakCB() is not None: + self.__callbackDict[weakCB] = weakNodes + + def __getTreeNode(self, topic, make=False): + """Return the tree node for 'topic' from the topic tree. If it + doesnt exist and make=True, create it first.""" + # if the all-topics, give root; + if topic == (ALL_TOPICS,): + return self + + # not root, so traverse tree + node = self + path = () + for topicItem in topic: + path += (topicItem,) + if topicItem == ALL_TOPICS: + raise ValueError, 'Topic tuple must not contain ""' + if make: + node = node.createSubtopic(topicItem, path) + elif node.hasSubtopic(topicItem): + node = node.getNode(topicItem) + else: + return None + # done + return node + + def printCallbacks(self): + strVal = ['Callbacks:\n'] + for listener, weakTopicNodes in self.__callbackDict.iteritems(): + topics = [topic() for topic in weakTopicNodes if topic() is not None] + strVal.append(' %s: %s\n' % (_getCallableName(listener()), topics)) + return ''.join(strVal) + + def __str__(self): + return 'all: %s' % _TopicTreeNode.__str__(self) + + +# ----------------------------------------------------------------------------- + +class _SingletonKey: pass + +class PublisherClass: + """ + The publish/subscribe manager. It keeps track of which listeners + are interested in which topics (see subscribe()), and sends a + Message for a given topic to listeners that have subscribed to + that topic, with optional user data (see sendMessage()). + + The three important concepts for Publisher are: + + - listener: a function, bound method or + callable object that can be called with one parameter + (not counting 'self' in the case of methods). The parameter + will be a reference to a Message object. E.g., these listeners + are ok:: + + class Foo: + def __call__(self, a, b=1): pass # can be called with only one arg + def meth(self, a): pass # takes only one arg + def meth2(self, a=2, b=''): pass # can be called with one arg + + def func(a, b=''): pass + + Foo foo + Publisher().subscribe(foo) # functor + Publisher().subscribe(foo.meth) # bound method + Publisher().subscribe(foo.meth2) # bound method + Publisher().subscribe(func) # function + + The three types of callables all have arguments that allow a call + with only one argument. In every case, the parameter 'a' will contain + the message. + + - topic: a single word, a tuple of words, or a string containing a + set of words separated by dots, for example: 'sports.baseball'. + A tuple or a dotted notation string denotes a hierarchy of + topics from most general to least. For example, a listener of + this topic:: + + ('sports','baseball') + + would receive messages for these topics:: + + ('sports', 'baseball') # because same + ('sports', 'baseball', 'highscores') # because more specific + + but not these:: + + 'sports' # because more general + ('sports',) # because more general + () or ('') # because only for those listening to 'all' topics + ('news') # because different topic + + - message: this is an instance of Message, containing the topic for + which the message was sent, and any data the sender specified. + + :note: This class is visible to importers of pubsub only as a + Singleton. I.e., every time you execute 'Publisher()', it's + actually the same instance of PublisherClass that is + returned. So to use, just do'Publisher().method()'. + + """ + + __ALL_TOPICS_TPL = (ALL_TOPICS, ) + + def __init__(self, singletonKey): + """Construct a Publisher. This can only be done by the pubsub + module. You just use pubsub.Publisher().""" + if not isinstance(singletonKey, _SingletonKey): + raise invalid_argument("Use Publisher() to get access to singleton") + self.__messageCount = 0 + self.__deliveryCount = 0 + self.__topicTree = _TopicTreeRoot() + + # + # Public API + # + + def getDeliveryCount(self): + """How many listeners have received a message since beginning of run""" + return self.__deliveryCount + + def getMessageCount(self): + """How many times sendMessage() was called since beginning of run""" + return self.__messageCount + + def subscribe(self, listener, topic = ALL_TOPICS): + """ + Subscribe listener for given topic. If topic is not specified, + listener will be subscribed for all topics (that listener will + receive a Message for any topic for which a message is generated). + + This method may be called multiple times for one listener, + registering it with many topics. It can also be invoked many + times for a particular topic, each time with a different + listener. See the class doc for requirements on listener and + topic. + + :note: The listener is held by Publisher() only by *weak* + reference. This means you must ensure you have at + least one strong reference to listener, otherwise it + will be DOA ("dead on arrival"). This is particularly + easy to forget when wrapping a listener method in a + proxy object (e.g. to bind some of its parameters), + e.g.:: + + class Foo: + def listener(self, event): pass + class Wrapper: + def __init__(self, fun): self.fun = fun + def __call__(self, *args): self.fun(*args) + foo = Foo() + Publisher().subscribe( Wrapper(foo.listener) ) # whoops: DOA! + wrapper = Wrapper(foo.listener) + Publisher().subscribe(wrapper) # good! + + :note: Calling this method for the same listener, with two + topics in the same branch of the topic hierarchy, will + cause the listener to be notified twice when a message + for the deepest topic is sent. E.g. + subscribe(listener, 't1') and then subscribe(listener, + ('t1','t2')) means that when calling sendMessage('t1'), + listener gets one message, but when calling + sendMessage(('t1','t2')), listener gets message twice. + + """ + self.validate(listener) + + if topic is None: + raise TypeError, 'Topic must be either a word, tuple of '\ + 'words, or getStrAllTopics()' + + self.__topicTree.addTopic(_tupleize(topic), listener) + + def isSubscribed(self, listener, topic=None): + """Return true if listener has subscribed to topic specified. + If no topic specified, return true if subscribed to something. + Use topic=getStrAllTopics() to determine if a listener will receive + messages for all topics.""" + return self.__topicTree.isSubscribed(listener, topic) + + def validate(self, listener): + """Similar to isValid(), but raises a TypeError exception if not valid""" + # check callable + if not callable(listener): + raise TypeError, 'Listener '+`listener`+' must be a '\ + 'function, bound method or instance.' + # ok, callable, but if method, is it bound: + elif ismethod(listener) and not _isbound(listener): + raise TypeError, 'Listener '+`listener`+\ + ' is a method but it is unbound!' + + # check that it takes the right number of parameters + min, d = _paramMinCount(listener) + if min > 1: + raise TypeError, 'Listener '+`listener`+" can't"\ + ' require more than one parameter!' + if min <= 0 and d == 0: + raise TypeError, 'Listener '+`listener`+' lacking arguments!' + + assert (min == 0 and d>0) or (min == 1) + + def isValid(self, listener): + """Return true only if listener will be able to subscribe to + Publisher.""" + try: + self.validate(listener) + return True + except TypeError: + return False + + def unsubAll(self, topics=None, onNoSuchTopic=None): + """Unsubscribe all listeners subscribed for topics. Topics can + be a single topic (string or tuple) or a list of topics (ie + list containing strings and/or tuples). If topics is not + specified, all listeners for all topics will be unsubscribed, + ie. the Publisher singleton will have no topics and no listeners + left. If onNoSuchTopic is given, it will be called as + onNoSuchTopic(topic) for each topic that is unknown. + """ + if topics is None: + del self.__topicTree + self.__topicTree = _TopicTreeRoot() + return + + # make sure every topics are in tuple form + if isinstance(topics, list): + topicList = [_tupleize(x) for x in topics] + else: + topicList = [_tupleize(topics)] + + # unsub every listener of topics + self.__topicTree.unsubAll(topicList, onNoSuchTopic) + + def unsubscribe(self, listener, topics=None): + """Unsubscribe listener. If topics not specified, listener is + completely unsubscribed. Otherwise, it is unsubscribed only + for the topic (the usual tuple) or list of topics (ie a list + of tuples) specified. Nothing happens if listener is not actually + subscribed to any of the topics. + + Note that if listener subscribed for two topics (a,b) and (a,c), + then unsubscribing for topic (a) will do nothing. You must + use getAssociatedTopics(listener) and give unsubscribe() the returned + list (or a subset thereof). + """ + self.validate(listener) + topicList = None + if topics is not None: + if isinstance(topics, list): + topicList = [_tupleize(x) for x in topics] + else: + topicList = [_tupleize(topics)] + + self.__topicTree.unsubscribe(listener, topicList) + + def getAssociatedTopics(self, listener): + """Return a list of topics the given listener is registered with. + Returns [] if listener never subscribed. + + :attention: when using the return of this method to compare to + expected list of topics, remember that topics that are + not in the form of a tuple appear as a one-tuple in + the return. E.g. if you have subscribed a listener to + 'topic1' and ('topic2','subtopic2'), this method + returns:: + + associatedTopics = [('topic1',), ('topic2','subtopic2')] + """ + return self.__topicTree.getTopics(listener) + + def sendMessage(self, topic=ALL_TOPICS, + data=None, onTopicNeverCreated=None, + context=None): + """Send a message for given topic, with optional data, to + subscribed listeners. If topic is not specified, only the + listeners that are interested in all topics will receive message. + The onTopicNeverCreated is an optional callback of your choice that + will be called if the topic given was never created (i.e. it, or + one of its subtopics, was never subscribed to by any listener). + It will be called as onTopicNeverCreated(topic).""" + aTopic = _tupleize(topic) + message = Message(aTopic, data, context=context) + self.__messageCount += 1 + + # send to those who listen to all topics + self.__deliveryCount += \ + self.__topicTree.sendMessage(aTopic, message, onTopicNeverCreated) + + # + # Private methods + # + + def __call__(self): + """Allows for singleton""" + return self + + def __str__(self): + return str(self.__topicTree) + +# Create the Publisher singleton. We prevent users from (inadvertently) +# instantiating more than one object, by requiring a key that is +# accessible only to module. From +# this point forward any calls to Publisher() will invoke the __call__ +# of this instance which just returns itself. +# +# The only flaw with this approach is that you can't derive a new +# class from Publisher without jumping through hoops. If this ever +# becomes an issue then a new Singleton implementaion will need to be +# employed. +_key = _SingletonKey() +Publisher = PublisherClass(_key) + + +#--------------------------------------------------------------------------- + +class Message: + """ + A simple container object for the two components of a message: the + topic and the user data. An instance of Message is given to your + listener when called by Publisher().sendMessage(topic) (if your + listener callback was registered for that topic). + """ + def __init__(self, topic, data, context=None): + self.topic = topic + self.data = data + self.context = context + + Data = property(lambda self: self.data, + lambda self, data: setattr(self, 'data', data)) + Context = property(lambda self: self.context, + lambda self, ctx: setattr(self, 'context', value)) + Type = property(lambda self: self.topic) + + def __str__(self): + return '[Topic: '+`self.topic`+', Data: '+`self.data`+']' + + def GetContext(self): + """Get the context that this message was sent in""" + return self.context + + def GetData(self): + """Return the messages data/value""" + return self.data + + def GetType(self): + """Return the type of message""" + return self.topic + +#--------------------------------------------------------------------------- + + +# +# Code for a simple command-line test +# +def test(): + def done(funcName): + print '----------- Done %s -----------' % funcName + + def testParam(): + def testFunc00(): pass + def testFunc21(a,b,c=1): pass + def testFuncA(*args): pass + def testFuncAK(*args,**kwds): pass + def testFuncK(**kwds): pass + + class Foo: + def testMeth(self,a,b): pass + def __call__(self, a): pass + class Foo2: + def __call__(self, *args): pass + + assert _paramMinCount(testFunc00)==(0,0) + assert _paramMinCount(testFunc21)==(2,1) + assert _paramMinCount(testFuncA) ==(1,0) + assert _paramMinCount(testFuncAK)==(1,0) + assert _paramMinCount(testFuncK) ==(0,0) + foo = Foo() + assert _paramMinCount(Foo.testMeth)==(2,0) + assert _paramMinCount(foo.testMeth)==(2,0) + assert _paramMinCount(foo)==(1,0) + assert _paramMinCount(Foo2())==(1,0) + + done('testParam') + + testParam() + #------------------------ + + _NodeCallback.notified = 0 + def testPreNotifyNode(self, dead): + _NodeCallback.notified += 1 + print 'testPreNotifyNODE heard notification of', `dead` + _NodeCallback.preNotify = testPreNotifyNode + + def testTreeNode(): + + class WS: + def __init__(self, s): + self.s = s + def __call__(self, msg): + print 'WS#', self.s, ' received msg ', msg + def __str__(self): + return self.s + + def testPreNotifyRoot(dead): + print 'testPreNotifyROOT heard notification of', `dead` + + node = _TopicTreeNode((ALL_TOPICS,), WeakRef(testPreNotifyRoot)) + boo, baz, bid = WS('boo'), WS('baz'), WS('bid') + node.addCallable(boo) + node.addCallable(baz) + node.addCallable(boo) + assert node.getCallables() == [boo,baz] + assert node.hasCallable(boo) + + node.removeCallable(bid) # no-op + assert node.hasCallable(baz) + assert node.getCallables() == [boo,baz] + + node.removeCallable(boo) + assert node.getCallables() == [baz] + assert node.hasCallable(baz) + assert not node.hasCallable(boo) + + node.removeCallable(baz) + assert node.getCallables() == [] + assert not node.hasCallable(baz) + + node2 = node.createSubtopic('st1', ('st1',)) + node3 = node.createSubtopic('st2', ('st2',)) + cb1, cb2, cb = WS('st1_cb1'), WS('st1_cb2'), WS('st2_cb') + node2.addCallable(cb1) + node2.addCallable(cb2) + node3.addCallable(cb) + node2.createSubtopic('st3', ('st1','st3')) + node2.createSubtopic('st4', ('st1','st4')) + + print str(node) + assert str(node) == ' (st1: st1_cb1 st1_cb2 (st4: ) (st3: )) (st2: st2_cb )' + + # verify send message, and that a dead listener does not get sent one + delivered = node2.sendMessage('hello') + assert delivered == 2 + del cb1 + delivered = node2.sendMessage('hello') + assert delivered == 1 + assert _NodeCallback.notified == 1 + + done('testTreeNode') + + testTreeNode() + #------------------------ + + def testValidate(): + class Foo: + def __call__(self, a): pass + def fun(self, b): pass + def fun2(self, b=1): pass + def fun3(self, a, b=2): pass + def badFun(self): pass + def badFun2(): pass + def badFun3(self, a, b): pass + + server = Publisher() + foo = Foo() + server.validate(foo) + server.validate(foo.fun) + server.validate(foo.fun2) + server.validate(foo.fun3) + assert not server.isValid(foo.badFun) + assert not server.isValid(foo.badFun2) + assert not server.isValid(foo.badFun3) + + done('testValidate') + + testValidate() + #------------------------ + + class SimpleListener: + def __init__(self, number): + self.number = number + def __call__(self, message = ''): + print 'Callable #%s got the message "%s"' %(self.number, message) + def notify(self, message): + print '%s.notify() got the message "%s"' %(self.number, message) + def __str__(self): + return "SimpleListener_%s" % self.number + + def testSubscribe(): + publisher = Publisher() + + topic1 = 'politics' + topic2 = ('history','middle age') + topic3 = ('politics','UN') + topic4 = ('politics','NATO') + topic5 = ('politics','NATO','US') + + lisnr1 = SimpleListener(1) + lisnr2 = SimpleListener(2) + def func(message, a=1): + print 'Func received message "%s"' % message + lisnr3 = func + lisnr4 = lambda x: 'Lambda received message "%s"' % x + + assert not publisher.isSubscribed(lisnr1) + assert not publisher.isSubscribed(lisnr2) + assert not publisher.isSubscribed(lisnr3) + assert not publisher.isSubscribed(lisnr4) + + publisher.subscribe(lisnr1, topic1) + assert publisher.getAssociatedTopics(lisnr1) == [(topic1,)] + publisher.subscribe(lisnr1, topic2) + publisher.subscribe(lisnr1, topic1) # do it again, should be no-op + assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2] + publisher.subscribe(lisnr2.notify, topic3) + assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3] + assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2] + publisher.subscribe(lisnr3, topic5) + assert publisher.getAssociatedTopics(lisnr3) == [topic5] + assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3] + assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2] + publisher.subscribe(lisnr4) + + print "Publisher tree: ", publisher + assert publisher.isSubscribed(lisnr1) + assert publisher.isSubscribed(lisnr1, topic1) + assert publisher.isSubscribed(lisnr1, topic2) + assert publisher.isSubscribed(lisnr2.notify) + assert publisher.isSubscribed(lisnr3, topic5) + assert publisher.isSubscribed(lisnr4, ALL_TOPICS) + expectTopicTree = 'all: <lambda> (politics: SimpleListener_1 (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: SimpleListener_1 ))' + print "Publisher tree: ", publisher + assert str(publisher) == expectTopicTree + + publisher.unsubscribe(lisnr1, 'booboo') # should do nothing + assert publisher.getAssociatedTopics(lisnr1) == [(topic1,),topic2] + assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3] + assert publisher.getAssociatedTopics(lisnr3) == [topic5] + publisher.unsubscribe(lisnr1, topic1) + assert publisher.getAssociatedTopics(lisnr1) == [topic2] + assert publisher.getAssociatedTopics(lisnr2.notify) == [topic3] + assert publisher.getAssociatedTopics(lisnr3) == [topic5] + publisher.unsubscribe(lisnr1, topic2) + publisher.unsubscribe(lisnr1, topic2) + publisher.unsubscribe(lisnr2.notify, topic3) + publisher.unsubscribe(lisnr3, topic5) + assert publisher.getAssociatedTopics(lisnr1) == [] + assert publisher.getAssociatedTopics(lisnr2.notify) == [] + assert publisher.getAssociatedTopics(lisnr3) == [] + publisher.unsubscribe(lisnr4) + + expectTopicTree = 'all: (politics: (UN: ) (NATO: (US: ))) (history: (middle age: ))' + print "Publisher tree: ", publisher + assert str(publisher) == expectTopicTree + assert publisher.getDeliveryCount() == 0 + assert publisher.getMessageCount() == 0 + + publisher.unsubAll() + assert str(publisher) == 'all: ' + + done('testSubscribe') + + testSubscribe() + #------------------------ + + def testUnsubAll(): + publisher = Publisher() + + topic1 = 'politics' + topic2 = ('history','middle age') + topic3 = ('politics','UN') + topic4 = ('politics','NATO') + topic5 = ('politics','NATO','US') + + lisnr1 = SimpleListener(1) + lisnr2 = SimpleListener(2) + def func(message, a=1): + print 'Func received message "%s"' % message + lisnr3 = func + lisnr4 = lambda x: 'Lambda received message "%s"' % x + + publisher.subscribe(lisnr1, topic1) + publisher.subscribe(lisnr1, topic2) + publisher.subscribe(lisnr2.notify, topic3) + publisher.subscribe(lisnr3, topic2) + publisher.subscribe(lisnr3, topic5) + publisher.subscribe(lisnr4) + + expectTopicTree = 'all: <lambda> (politics: SimpleListener_1 (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: SimpleListener_1 func ))' + print "Publisher tree: ", publisher + assert str(publisher) == expectTopicTree + + publisher.unsubAll(topic1) + assert publisher.getAssociatedTopics(lisnr1) == [topic2] + assert not publisher.isSubscribed(lisnr1, topic1) + + publisher.unsubAll(topic2) + print publisher + assert publisher.getAssociatedTopics(lisnr1) == [] + assert publisher.getAssociatedTopics(lisnr3) == [topic5] + assert not publisher.isSubscribed(lisnr1) + assert publisher.isSubscribed(lisnr3, topic5) + + #print "Publisher tree: ", publisher + expectTopicTree = 'all: <lambda> (politics: (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: ))' + assert str(publisher) == expectTopicTree + publisher.unsubAll(ALL_TOPICS) + #print "Publisher tree: ", publisher + expectTopicTree = 'all: (politics: (UN: SimpleListener_2.notify ) (NATO: (US: func ))) (history: (middle age: ))' + assert str(publisher) == expectTopicTree + + publisher.unsubAll() + done('testUnsubAll') + + testUnsubAll() + #------------------------ + + def testSend(): + publisher = Publisher() + called = [] + + class TestListener: + def __init__(self, num): + self.number = num + def __call__(self, b): + called.append( 'TL%scb' % self.number ) + def notify(self, b): + called.append( 'TL%sm' % self.number ) + def funcListener(b): + called.append('func') + + lisnr1 = TestListener(1) + lisnr2 = TestListener(2) + lisnr3 = funcListener + lisnr4 = lambda x: called.append('lambda') + + topic1 = 'politics' + topic2 = 'history' + topic3 = ('politics','UN') + topic4 = ('politics','NATO','US') + topic5 = ('politics','NATO') + + publisher.subscribe(lisnr1, topic1) + publisher.subscribe(lisnr2, topic2) + publisher.subscribe(lisnr2.notify, topic2) + publisher.subscribe(lisnr3, topic4) + publisher.subscribe(lisnr4) + + print publisher + + # setup ok, now test send/receipt + publisher.sendMessage(topic1) + assert called == ['lambda','TL1cb'] + called = [] + publisher.sendMessage(topic2) + assert called == ['lambda','TL2cb','TL2m'] + called = [] + publisher.sendMessage(topic3) + assert called == ['lambda','TL1cb'] + called = [] + publisher.sendMessage(topic4) + assert called == ['lambda','TL1cb','func'] + called = [] + publisher.sendMessage(topic5) + assert called == ['lambda','TL1cb'] + assert publisher.getDeliveryCount() == 12 + assert publisher.getMessageCount() == 5 + + # test weak referencing works: + _NodeCallback.notified = 0 + del lisnr2 + called = [] + publisher.sendMessage(topic2) + assert called == ['lambda'] + assert _NodeCallback.notified == 2 + + done('testSend') + + testSend() + assert _NodeCallback.notified == 5 + + def testDead(): + # verify if weak references work as expected + print '------ Starting testDead ----------' + node = _TopicTreeNode('t1', None) + lisnr1 = SimpleListener(1) + lisnr2 = SimpleListener(2) + lisnr3 = SimpleListener(3) + lisnr4 = SimpleListener(4) + + node.addCallable(lisnr1) + node.addCallable(lisnr2) + node.addCallable(lisnr3) + node.addCallable(lisnr4) + + print 'Deleting listeners first' + _NodeCallback.notified = 0 + del lisnr1 + del lisnr2 + assert _NodeCallback.notified == 2 + + print 'Deleting node first' + _NodeCallback.notified = 0 + del node + del lisnr3 + del lisnr4 + assert _NodeCallback.notified == 0 + + lisnr1 = SimpleListener(1) + lisnr2 = SimpleListener(2) + lisnr3 = SimpleListener(3) + lisnr4 = SimpleListener(4) + + # try same with root of tree + node = _TopicTreeRoot() + node.addTopic(('',), lisnr1) + node.addTopic(('',), lisnr2) + node.addTopic(('',), lisnr3) + node.addTopic(('',), lisnr4) + # add objects that will die immediately to see if cleanup occurs + # this must be done visually as it is a low-level detail + _NodeCallback.notified = 0 + _TopicTreeRoot.callbackDeadLimit = 3 + node.addTopic(('',), SimpleListener(5)) + node.addTopic(('',), SimpleListener(6)) + node.addTopic(('',), SimpleListener(7)) + print node.numListeners() + assert node.numListeners() == (4, 3) + node.addTopic(('',), SimpleListener(8)) + assert node.numListeners() == (4, 0) + assert _NodeCallback.notified == 4 + + print 'Deleting listeners first' + _NodeCallback.notified = 0 + del lisnr1 + del lisnr2 + assert _NodeCallback.notified == 2 + print 'Deleting node first' + _NodeCallback.notified = 0 + del node + del lisnr3 + del lisnr4 + assert _NodeCallback.notified == 0 + + done('testDead') + + testDead() + + print 'Exiting tests' +#--------------------------------------------------------------------------- + +if __name__ == '__main__': + test() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcprint.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcprint.py new file mode 100644 index 0000000..e477e0d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcprint.py @@ -0,0 +1,614 @@ +#----------------------------------------------------------------------------- +# Name: stcprint.py +# Purpose: wx.StyledTextCtrl printing support +# +# Author: Rob McMullen +# +# Created: 2009 +# RCS-ID: $Id: stcprint.py 67499 2011-04-15 20:33:40Z CJP $ +# Copyright: (c) 2009 Rob McMullen <robm@users.sourceforge.net> +# (c) 2007 Cody Precord <staff@editra.org> +# License: wxWidgets +#----------------------------------------------------------------------------- +"""Printing support for the wx.StyledTextCtrl + +Concrete implementation of the wx.Printout class to generate a print preview +and paper copies of the contents of a wx.StyledTextCtrl. This was written +for U{Peppy<http://peppy.flipturn.org>} but has been designed as a standalone +class with no dependencies on peppy. It can be used for general purpose +printing or print preview of a wx.StyledTextCtrl. See the demo application at +the end of this file for more information. + +I used code from U{Editra<http://www.editra.org>} as a starting point; other +pointers came from the wxPython mailing list, and lots was just pure ol' +trial and error because I couldn't find much specific documentation on the +FormatRange method of the STC. + +NOTE: there are issues with certain scale factors when using print preview on +MSW. Some scale factors seem to work correctly, like 150%, but other smaller +scale factors cause the preview font size to fluctuate. Some zoom levels will +use very small fonts and render all the lines in the top half of the page, +while other zoom levels use an incorrectly large font and render lines off the +bottom of the page. The printed output is unaffected, however, and renders +the correct number of lines. +""" + +import os + +import wx +import wx.stc +_ = wx.GetTranslation + +class STCPrintout(wx.Printout): + """Specific printing support of the wx.StyledTextCtrl for the wxPython + framework + + This class can be used for both printing to a printer and for print preview + functions. Unless otherwise specified, the print is scaled based on the + size of the current font used in the STC so that specifying a larger font + produces a larger font in the printed output (and correspondingly fewer + lines per page). Alternatively, you can eihdec specify the number of + lines per page, or you can specify the print font size in points which + produces a constant number of lines per inch regardless of the paper size. + + Note that line wrapping in the source STC is currently ignored and lines + will be truncated at the right margin instead of wrapping. The STC doesn't + provide a convenient method for determining where line breaks occur within + a wrapped line, so it may be a difficult task to ever implement printing + with line wrapping using the wx.StyledTextCtrl.FormatRange method. + """ + debuglevel = 0 + + def __init__(self, stc, page_setup_data=None, print_mode=None, title=None, + border=False, lines_per_page=None, output_point_size=None, + job_title=None): + """Constructor. + + @param stc: wx.StyledTextCtrl to print + + @kwarg page_setup_data: optional wx.PageSetupDialogData instance that + is used to determine the margins of the page. + + @kwarg print_mode: optional; of the wx.stc.STC_PRINT_* + flags indicating how to render color text. Defaults to + wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG + + @kwarg title: optional text string to use as the title which will be + centered above the first line of text on each page + + @kwarg border: optional flag indicating whether or not to draw a black + border around the text on each page + + @kwarg lines_per_page: optional integer that will force the page to + contain the specified number of lines. Either of C{output_point_size} + and C{lines_per_page} fully specifies the page, so if both are + specified, C{lines_per_page} will be used. + + @kwarg output_point_size: optional integer that will force the output + text to be drawn in the specified point size. (Note that there are + 72 points per inch.) If not specified, the point size of the text in + the STC will be used unless C{lines_per_page} is specified. Either of + C{output_point_size} and C{lines_per_page} fully specifies the page, + so if both are specified, C{lines_per_page} will be used. + """ + if not job_title: + job_title = wx.PrintoutTitleStr + wx.Printout.__init__(self, job_title) + self.stc = stc + if print_mode: + self.print_mode = print_mode + else: + self.print_mode = wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG + if title is not None: + self.title = title + else: + self.title = "" + if page_setup_data is None: + self.top_left_margin = wx.Point(15,15) + self.bottom_right_margin = wx.Point(15,15) + else: + self.top_left_margin = page_setup_data.GetMarginTopLeft() + self.bottom_right_margin = page_setup_data.GetMarginBottomRight() + + try: + value = float(output_point_size) + if value > 0.0: + self.output_point_size = value + except (TypeError, ValueError): + self.output_point_size = None + + try: + value = int(lines_per_page) + if value > 0: + self.user_lines_per_page = value + except (TypeError, ValueError): + self.user_lines_per_page = None + + self.border_around_text = border + + self.setHeaderFont() + + def OnPreparePrinting(self): + """Called once before a print job is started to set up any defaults. + + """ + dc = self.GetDC() + self._calculateScale(dc) + self._calculatePageCount() + + def _calculateScale(self, dc): + """Scale the DC + + This routine scales the DC based on the font size, determines the + number of lines on a page, and saves some useful pixel locations like + the top left corner and the width and height of the drawing area in + logical coordinates. + """ + if self.debuglevel > 0: + print + + dc.SetFont(self.stc.GetFont()) + + # Calculate pixels per inch of the various devices. The dc_ppi will be + # equivalent to the page or screen PPI if the target is the printer or + # a print preview, respectively. + page_ppi_x, page_ppi_y = self.GetPPIPrinter() + screen_ppi_x, screen_ppi_y = self.GetPPIScreen() + dc_ppi_x, dc_ppi_y = dc.GetPPI() + if self.debuglevel > 0: + print("printer ppi: %dx%d" % (page_ppi_x, page_ppi_y)) + print("screen ppi: %dx%d" % (screen_ppi_x, screen_ppi_y)) + print("dc ppi: %dx%d" % (dc_ppi_x, dc_ppi_y)) + + # Calculate paper size. Note that this is the size in pixels of the + # entire paper, which may be larger than the printable range of the + # printer. We need to use the entire paper size because we calculate + # margins ourselves. Note that GetPageSizePixels returns the + # dimensions of the printable area. + px, py, pw, ph = self.GetPaperRectPixels() + page_width_inch = float(pw) / page_ppi_x + page_height_inch = float(ph) / page_ppi_y + if self.debuglevel > 0: + print("page pixels: %dx%d" % (pw, ph)) + print("page size: %fx%f in" % (page_width_inch, page_height_inch)) + + dw, dh = dc.GetSizeTuple() + dc_pixels_per_inch_x = float(dw) / page_width_inch + dc_pixels_per_inch_y = float(dh) / page_height_inch + if self.debuglevel > 0: + print("device pixels: %dx%d" % (dw, dh)) + print("device pixels per inch: %fx%f" % (dc_pixels_per_inch_x, dc_pixels_per_inch_y)) + + # Calculate usable page size + page_height_mm = page_height_inch * 25.4 + margin_mm = self.top_left_margin[1] + self.bottom_right_margin[1] + usable_page_height_mm = page_height_mm - margin_mm + + # Lines per page is then the number of lines (based on the point size + # reported by wx) that will fit into the usable page height + self.lines_pp = self._calculateLinesPerPage(dc, usable_page_height_mm) + + # The final DC scale factor is then the ratio of the total height in + # pixels inside the margins to the number of pixels that it takes to + # represent the number of lines + dc_margin_pixels = float(dc_pixels_per_inch_y) * margin_mm / 25.4 + dc_usable_pixels = dh - dc_margin_pixels + page_to_dc = self._calculateScaleFactor(dc, dc_usable_pixels, self.lines_pp) + + dc.SetUserScale(page_to_dc, page_to_dc) + + if self.debuglevel > 0: + print("Usable page height: %f in" % (usable_page_height_mm / 25.4)) + print("Usable page pixels: %d" % dc_usable_pixels) + print("lines per page: %d" % self.lines_pp) + print("page_to_dc: %f" % page_to_dc) + + self.x1 = dc.DeviceToLogicalXRel(float(self.top_left_margin[0]) / 25.4 * dc_pixels_per_inch_x) + self.y1 = dc.DeviceToLogicalXRel(float(self.top_left_margin[1]) / 25.4 * dc_pixels_per_inch_y) + self.x2 = dc.DeviceToLogicalXRel(dw) - dc.DeviceToLogicalXRel(float(self.bottom_right_margin[0]) / 25.4 * dc_pixels_per_inch_x) + self.y2 = dc.DeviceToLogicalYRel(dh) - dc.DeviceToLogicalXRel(float(self.bottom_right_margin[1]) / 25.4 * dc_pixels_per_inch_y) + page_height = self.y2 - self.y1 + + #self.lines_pp = int(page_height / dc_pixels_per_line) + + if self.debuglevel > 0: + print("page size: %d,%d -> %d,%d, height=%d" % (int(self.x1), int(self.y1), int(self.x2), int(self.y2), page_height)) + + def _calculateLinesPerPage(self, dc, usable_page_height_mm): + """Calculate the number of lines that will fit on the page. + + @param dc: the Device Context + + @param usable_page_height_mm: height in mm of the printable part of the + page (i.e. with the border height removed) + + @returns: the number of lines on the page + """ + if self.user_lines_per_page is not None: + return self.user_lines_per_page + + font = dc.GetFont() + if self.output_point_size is not None: + points_per_line = self.output_point_size + else: + points_per_line = font.GetPointSize() + + # desired lines per mm based on point size. Note: printer points are + # defined as 72 points per inch + lines_per_inch = 72.0 / float(points_per_line) + + if self.debuglevel > 0: + print("font: point size per line=%d" % points_per_line) + print("font: lines per inch=%f" % lines_per_inch) + + # Lines per page is then the number of lines (based on the point size + # reported by wx) that will fit into the usable page height + return float(usable_page_height_mm) / 25.4 * lines_per_inch + + def _calculateScaleFactor(self, dc, dc_usable_pixels, lines_pp): + """Calculate the scale factor for the DC to fit the number of lines + onto the printable area + + @param dc: the Device Context + + @param dc_usable_pixels: the number of pixels that defines usable + height of the printable area + + @param lines_pp: the number of lines to fit into the printable area + + @returns: the scale facter to be used in wx.DC.SetUserScale + """ + # actual line height in pixels according to the DC + dc_pixels_per_line = dc.GetCharHeight() + + # actual line height in pixels according to the STC. This can be + # different from dc_pixels_per_line even though it is the same font. + # Don't know why this is the case; maybe because the STC takes into + # account additional spacing? + stc_pixels_per_line = self.stc.TextHeight(0) + if self.debuglevel > 0: + print("font: dc pixels per line=%d" % dc_pixels_per_line) + print("font: stc pixels per line=%d" % stc_pixels_per_line) + + # Platform dependency alert: I don't know why this works, but through + # experimentation it seems like the scaling factor depends on + # different font heights depending on the platform. + if wx.Platform == "__WXMSW__": + # On windows, the important font height seems to be the number of + # pixels reported by the STC + page_to_dc = float(dc_usable_pixels) / (stc_pixels_per_line * lines_pp) + else: + # Linux and Mac: the DC font height seems to be the correct height + page_to_dc = float(dc_usable_pixels) / (dc_pixels_per_line * lines_pp) + return page_to_dc + + def _calculatePageCount(self, attempt_wrap=False): + """Calculates offsets into the STC for each page + + This pre-calculates the page offsets for each page to support print + preview being able to seek backwards and forwards. + """ + page_offsets = [] + page_line_start = 0 + lines_on_page = 0 + num_lines = self.stc.GetLineCount() + + line = 0 + while line < num_lines: + if attempt_wrap: + wrap_count = self.stc.WrapCount(line) + if wrap_count > 1 and self.debuglevel > 0: + print("found wrapped line %d: %d" % (line, wrap_count)) + else: + wrap_count = 1 + + # If the next line pushes the count over the edge, mark a page and + # start the next page + if lines_on_page + wrap_count > self.lines_pp: + start_pos = self.stc.PositionFromLine(page_line_start) + end_pos = self.stc.GetLineEndPosition(page_line_start + lines_on_page - 1) + if self.debuglevel > 0: + print("Page: line %d - %d" % (page_line_start, page_line_start + lines_on_page)) + page_offsets.append((start_pos, end_pos)) + page_line_start = line + lines_on_page = 0 + lines_on_page += wrap_count + line += 1 + + if lines_on_page > 0: + start_pos = self.stc.PositionFromLine(page_line_start) + end_pos = self.stc.GetLineEndPosition(page_line_start + lines_on_page) + page_offsets.append((start_pos, end_pos)) + + self.page_count = len(page_offsets) + self.page_offsets = page_offsets + if self.debuglevel > 0: + print("page offsets: %s" % self.page_offsets) + + def _getPositionsOfPage(self, page): + """Get the starting and ending positions of a page + + @param page: page number + + @returns: tuple containing the start and end positions that can be + passed to FormatRange to render a page + """ + page -= 1 + start_pos, end_pos = self.page_offsets[page] + return start_pos, end_pos + + def GetPageInfo(self): + """Return the valid page ranges. + + Note that pages are numbered starting from one. + """ + return (1, self.page_count, 1, self.page_count) + + def HasPage(self, page): + """Returns True if the specified page is within the page range + + """ + return page <= self.page_count + + def OnPrintPage(self, page): + """Draws the specified page to the DC + + @param page: page number to render + """ + dc = self.GetDC() + self._calculateScale(dc) + + self._drawPageContents(dc, page) + self._drawPageHeader(dc, page) + self._drawPageBorder(dc) + + return True + + def _drawPageContents(self, dc, page): + """Render the STC window into a DC for printing. + + Force the right margin of the rendered window to be huge so the STC + won't attempt word wrapping. + + @param dc: the device context representing the page + + @param page: page number + """ + start_pos, end_pos = self._getPositionsOfPage(page) + render_rect = wx.Rect(self.x1, self.y1, 32000, self.y2) + page_rect = wx.Rect(self.x1, self.y1, self.x2, self.y2) + + self.stc.SetPrintColourMode(self.print_mode) + edge_mode = self.stc.GetEdgeMode() + self.stc.SetEdgeMode(wx.stc.STC_EDGE_NONE) + end_point = self.stc.FormatRange(True, start_pos, end_pos, dc, dc, + render_rect, page_rect) + self.stc.SetEdgeMode(edge_mode) + + def _drawPageHeader(self, dc, page): + """Draw the page header into the DC for printing + + @param dc: the device context representing the page + + @param page: page number + """ + # Set font for title/page number rendering + dc.SetFont(self.getHeaderFont()) + dc.SetTextForeground ("black") + dum, yoffset = dc.GetTextExtent(".") + yoffset /= 2 + if self.title: + title_w, title_h = dc.GetTextExtent(self.title) + dc.DrawText(self.title, self.x1, self.y1 - title_h - yoffset) + + # Page Number + page_lbl = _("Page: %d") % page + pg_lbl_w, pg_lbl_h = dc.GetTextExtent(page_lbl) + dc.DrawText(page_lbl, self.x2 - pg_lbl_w, self.y1 - pg_lbl_h - yoffset) + + def setHeaderFont(self, point_size=10, family=wx.FONTFAMILY_SWISS, + style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL): + """Set the font to be used as the header font + + @param point_size: point size of the font + + @param family: one of the wx.FONTFAMILY_* values, e.g. + wx.FONTFAMILY_SWISS, wx.FONTFAMILY_ROMAN, etc. + + @param style: one of the wx.FONTSTYLE_* values, e.g. + wxFONTSTYLE_NORMAL, wxFONTSTYLE_ITALIC, etc. + + @param weight: one of the wx.FONTWEIGHT_* values, e.g. + wx.FONTWEIGHT_NORMAL, wx.FONTWEIGHT_LIGHT, etc. + """ + self.header_font_point_size = point_size + self.header_font_family = family + self.header_font_style = style + self.header_font_weight = weight + + def getHeaderFont(self): + """Returns the font to be used to draw the page header text + + @returns: wx.Font instance + """ + point_size = self.header_font_point_size + font = wx.Font(point_size, self.header_font_family, + self.header_font_style, self.header_font_weight) + return font + + def _drawPageBorder(self, dc): + """Draw the page border into the DC for printing + + @param dc: the device context representing the page + """ + if self.border_around_text: + dc.SetPen(wx.BLACK_PEN) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + dc.DrawRectangle(self.x1, self.y1, self.x2 - self.x1 + 1, self.y2 - self.y1 + 1) + + +if __name__ == "__main__": + import sys + import __builtin__ + __builtin__._ = unicode + + # Set up sample print data + top_left_margin = wx.Point(15,15) + bottom_right_margin = wx.Point(15,15) + + def wrap(text, width=80): + """A word-wrap function that preserves existing line breaks + and most spaces in the text. + + Expects that existing line breaks are posix newlines (\n). + + http://code.activestate.com/recipes/148061/ + """ + return reduce(lambda line, word, width=width: '%s%s%s' % + (line, + ' \n'[(len(line)-line.rfind('\n')-1 + + len(word.split('\n',1)[0] + ) >= width)], + word), + text.split(' ') + ) + + class TestSTC(wx.stc.StyledTextCtrl): + def __init__(self, *args, **kwargs): + wx.stc.StyledTextCtrl.__init__(self, *args, **kwargs) + self.SetMarginType(0, wx.stc.STC_MARGIN_NUMBER) + self.SetMarginWidth(0, 32) + + class Frame(wx.Frame): + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + + self.stc = TestSTC(self, -1) + + self.CreateStatusBar() + menubar = wx.MenuBar() + self.SetMenuBar(menubar) # Adding the MenuBar to the Frame content. + menu = wx.Menu() + menubar.Append(menu, "File") + self.menuAdd(menu, "Open", "Open File", self.OnOpenFile) + menu.AppendSeparator() + self.menuAdd(menu, "Print Preview", "Display print preview", self.OnPrintPreview) + self.menuAdd(menu, "Print", "Print to printer or file", self.OnPrint) + menu.AppendSeparator() + self.menuAdd(menu, "Quit", "Exit the pragram", self.OnQuit) + + self.print_data = wx.PrintData() + self.print_data.SetPaperId(wx.PAPER_LETTER) + + + def loadFile(self, filename, word_wrap=False): + fh = open(filename) + text = fh.read() + if word_wrap: + text = wrap(text) + self.stc.SetText(fh.read()) + + def loadSample(self, paragraphs=10, word_wrap=False): + lorem_ipsum = u"""\ +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus mattis +commodo sem. Phasellus scelerisque tellus id lorem. Nulla facilisi. +Suspendisse potenti. Fusce velit odio, scelerisque vel, consequat nec, +dapibus sit amet, tortor. + +Vivamus eu turpis. Nam eget dolor. Integer at elit. Praesent mauris. Nullam non nulla at nulla tincidunt malesuada. Phasellus id ante. Sed mauris. Integer volutpat nisi non diam. + +Etiam elementum. Pellentesque interdum justo eu risus. Cum sociis natoque +penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc +semper. + +In semper enim ut odio. Nulla varius leo commodo elit. Quisque condimentum, nisl eget elementum laoreet, mauris turpis elementum felis, ut accumsan nisl velit et mi. + +And some Russian: \u041f\u0438\u0442\u043e\u043d - \u043b\u0443\u0447\u0448\u0438\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f! + +""" + if word_wrap: + lorem_ipsum = wrap(lorem_ipsum) + self.stc.ClearAll() + for i in range(paragraphs): + self.stc.AppendText(lorem_ipsum) + wx.CallAfter(self.OnPrintPreview, None) + + def menuAdd(self, menu, name, desc, fcn, id=-1, kind=wx.ITEM_NORMAL): + if id == -1: + id = wx.NewId() + a = wx.MenuItem(menu, id, name, desc, kind) + menu.AppendItem(a) + wx.EVT_MENU(self, id, fcn) + menu.SetHelpString(id, desc) + + def OnOpenFile(self, evt): + dlg = wx.FileDialog(self, "Choose a text file", + defaultDir = "", + defaultFile = "", + wildcard = "*") + if dlg.ShowModal() == wx.ID_OK: + print("Opening %s" % dlg.GetPath()) + self.loadFile(dlg.GetPath()) + dlg.Destroy() + + def OnQuit(self, evt): + self.Close(True) + + def getPrintData(self): + return self.print_data + + def OnPrintPreview(self, evt): + wx.CallAfter(self.showPrintPreview) + + def showPrintPreview(self): + printout = STCPrintout(self.stc, title="Testing!!!", border=True, output_point_size=10) + printout2 = STCPrintout(self.stc, title="Testing!!!", border=True, output_point_size=10) + preview = wx.PrintPreview(printout, printout2, self.getPrintData()) + preview.SetZoom(100) + if preview.IsOk(): + pre_frame = wx.PreviewFrame(preview, self, _("Print Preview")) + dsize = wx.GetDisplaySize() + pre_frame.SetInitialSize((self.GetSize()[0], + dsize.GetHeight() - 100)) + pre_frame.Initialize() + pre_frame.Show() + else: + wx.MessageBox(_("Failed to create print preview"), + _("Print Error"), + style=wx.ICON_ERROR|wx.OK) + + def OnPrint(self, evt): + wx.CallAfter(self.showPrint) + + def showPrint(self): + pdd = wx.PrintDialogData(self.getPrintData()) + printer = wx.Printer(pdd) + printout = STCPrintout(self.stc) + result = printer.Print(self.stc, printout) + if result: + data = printer.GetPrintDialogData() + self.print_data = wx.PrintData(data.GetPrintData()) + elif printer.GetLastError() == wx.PRINTER_ERROR: + wx.MessageBox(_("There was an error when printing.\n" + "Check that your printer is properly connected."), + _("Printer Error"), + style=wx.ICON_ERROR|wx.OK) + printout.Destroy() + + app = wx.App(False) + frame = Frame(None, size=(800, -1)) + word_wrap = False + filename = None + if len(sys.argv) > 1: + if not sys.argv[-1].startswith("-"): + filename = sys.argv[-1] + if '-d' in sys.argv: + STCPrintout.debuglevel = 1 + if '-w' in sys.argv: + word_wrap = True + if filename: + frame.loadFile(filename, word_wrap) + else: + frame.loadSample(word_wrap=word_wrap) + frame.Show() + app.MainLoop() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcspellcheck.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcspellcheck.py new file mode 100644 index 0000000..e253714 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/stcspellcheck.py @@ -0,0 +1,815 @@ +#----------------------------------------------------------------------------- +# Name: stcspellcheck.py +# Purpose: Spell checking for the wx.StyledTextControl using pyenchant +# +# Author: Rob McMullen +# +# Created: 2008 +# RCS-ID: $Id: stcspellcheck.py 69791 2011-11-19 22:02:59Z CJP $ +# Copyright: (c) 2008 Rob McMullen +# License: wxWidgets +#----------------------------------------------------------------------------- +# +# Originally based on code from Luke-SDK, which includes the following +# copyright notice: +# +# Copyright (c) 2007 Eur Ing Christopher Thoday, cthoday@mail.berlios.de. +# +# Permission to use, copy, modify and distribute this software and its +# documentation for any purpose and without fee is hereby granted, provided +# that the above copyright notice appear in all copies and that both +# the copyright notice and this permission notice appear in supporting +# documentation. +# +# Christopher Thoday makes no representations about the suitability of this +# software for any purpose. It is provided "as is" without express or implied +# warranty. + +"""Spell checking for the wx.StyledTextControl using pyenchant + +This module was insipred by the spell check function from Christopher Thoday's +U{Luke SDK<http://luke-sdk.berlios.de/>}. + +Spell checking is provided by the pyenchant library, which is an external +dependency not part of wxPython. Packages are available for Mac, Unix, and +windows at U{http://pyenchant.sourceforge.net} + +Currently provides: + - spell checking of entire buffer, currently visible page, or selection region + - user specified indicator number (0 - 2), style, and color + - language can be changed on the fly + - update the spelling as you type + - check the document in either idle time or in a background thread + +@author: Rob McMullen +@version: 1.2 + +Changelog:: + 1.2: + - Rewrote as a standalone class rather than a static mixin + 1.1: + - Added helper function to use idle processing time to check document + - Added word checking function for use in instant spell checking + 1.0: + - First public release +""" + +import os +import locale +import wx +import wx.stc + +# Assume MacPorts install of Enchant +if wx.Platform == '__WXMAC__': + if 'PYENCHANT_LIBRARY_PATH' not in os.environ: + os.environ['PYENCHANT_LIBRARY_PATH'] = '/opt/local/lib/libenchant.dylib' + +try: + import enchant +except ImportError: + # no big deal; support for enchant simply won't be included + pass +except: + # big deal; enchant is there but there's some error that is preventing + # its import + import traceback + traceback.print_exc() + +class STCSpellCheck(object): + """Spell checking for use with wx.StyledTextControl. + + This shows spelling errors using the styling indicators (e.g. the red + squiggly underline) of the styled text control; I find this much more + convenient than a dialog-box that makes you click through each mistake. + + The eventual goal of the module is to provide on-the-fly spell checking + that will display errors as you type, and also will highlight errors + during idle time or in a background thread. + + Spell checking is provided through the pyenchant module. Without + pyenchant, this object won't do anything useful, but it is still safe to + be used. It wraps all calls to pyenchant with try/except blocks to catch + import errors, and any calls to the spell checking functions will return + immediately. + + To use the spelling check, use one of the methods L{checkAll}, + L{checkCurrentPage}, or L{checkSelection}. Clear the spelling + indicators with L{clearAll}. + """ + # Class attributes to act as default values + _spelling_lang = None + _spelling_dict = None + + def __init__(self, stc, *args, **kwargs): + """Mixin must be initialized using this constructor. + + Keyword arguments are also available instead of calling the + convenience functions. For L{setIndicator}, use C{indicator}, + C{indicator_color}, and {indicator_style}; for L{setLanguage}, + use C{language}; and for L{setMinimumWordSize}, use + C{min_word_size}. See the descriptions of those methods for more info. + """ + self.stc = stc + self.setIndicator(kwargs.get('indicator', 2), + kwargs.get('indicator_color', "#FF0000"), + kwargs.get('indicator_style', wx.stc.STC_INDIC_SQUIGGLE)) + self.setMinimumWordSize(kwargs.get('min_word_size', 3)) + if 'language' in kwargs: + # Don't set default language unless explicitly specified -- it + # might have already been set through the class method + self.setDefaultLanguage(kwargs['language']) + if 'check_region' in kwargs: + # optional function to specify if the region should be spell + # checked. Function should return True if the position should + # be spell-checked; False if it doesn't make sense to spell check + # that part of the document + self._spell_check_region = kwargs['check_region'] + else: + self._spell_check_region = lambda s: True + self._spelling_debug = False + + self._spelling_last_idle_line = -1 + self.dirty_range_count_per_idle = 5 + + self._no_update = False + self._last_block = -1 + + self.clearDirtyRanges() + + def setIndicator(self, indicator=None, color=None, style=None): + """Set the indicator styling for misspelled words. + + Set the indicator index to use, its color, and the visual style. + + @param indicator: indicator number (usually 0, 1, or 2, but may be fewer + depending on the number of style bits you've chosen for the stc.) + @param color: string indicating the color of the indicator (e.g. + "#FF0000" for red) + @param style: stc indicator style; one of the wx.stc.STC_INDIC_* + constants (currently wx.stc.STC_INDIC_PLAIN, wx.stc.STC_INDIC_SQUIGGLE, + wx.stc.STC_INDIC_TT, wx.stc.STC_INDIC_DIAGONAL, + wx.stc.STC_INDIC_STRIKE, wx.stc.STC_INDIC_HIDDEN, + wx.stc.STC_INDIC_BOX, wx.stc.STC_INDIC_ROUNDBOX) + """ + indicators = {0: wx.stc.STC_INDIC0_MASK, + 1: wx.stc.STC_INDIC1_MASK, + 2: wx.stc.STC_INDIC2_MASK + } + if indicator is not None: + if indicator not in indicators: + indicator = 0 + # The current view may have fewer than 3 indicators + bitmax = 7 - self.stc.GetStyleBits() + if indicator > bitmax: + indicator = bitmax + self._spelling_indicator = indicator + self._spelling_indicator_mask = indicators[self._spelling_indicator] + + if color is not None: + self._spelling_color = color + self.stc.IndicatorSetForeground(self._spelling_indicator, + self._spelling_color) + + if style is not None: + if style > wx.stc.STC_INDIC_MAX: + style = wx.stc.STC_INDIC_MAX + self._spelling_style = style + self.stc.IndicatorSetStyle(self._spelling_indicator, + self._spelling_style) + + @classmethod + def getAvailableLanguages(cls): + """Return a list of supported languages. + + Pyenchant supplies a list of its supported languages, so this is just + a simple wrapper around its C{list_languages} function. Each item in + the list is a text string indicating the locale name, e.g. en_US, ru, + ru_RU, eo, es_ES, etc. + + @return: a list of text strings indicating the supported languages + """ + try: + return enchant.list_languages() + except NameError: + pass + return [] + + @classmethod + def _getDict(cls, lang): + try: + d = enchant.Dict(lang) + except: + # Catch all exceptions, because if pyenchant isn't available, you + # can't catch the enchant.DictNotFound error. + d = None + return d + + def setCheckRegion(self, func): + """Set region checker callable + @param func: def func(pos): return bool + + """ + self.clearAll() + self._spell_check_region = func + + @classmethod + def setDefaultLanguage(cls, lang): + """Set the default language for spelling check. + + The string should be in language locale format, e.g. en_US, ru, ru_RU, + eo, es_ES, etc. See L{getAvailableLanguages}. + + @param lang: text string indicating the language + """ + cls._spelling_lang = lang + cls._spelling_dict = cls._getDict(lang) + + @classmethod + def getSpellingDictionary(cls): + """Get the currently used spelling dictionary + @return: enchant.Dict instance or None + + """ + return cls._spelling_dict + + def setLanguage(self, lang): + """Set the language for spelling check for this class, if different than + the default. + + The string should be in language locale format, e.g. en_US, ru, ru_RU, + eo, es_ES, etc. See L{getAvailableLanguages}. + + @param lang: text string indicating the language + """ + # Note that this instance variable will shadow the class attribute + self._spelling_lang = lang + self._spelling_dict = self._getDict(lang) + + def hasDictionary(self): + """Returns True if a dictionary is available to spell check the current + language. + """ + return self._spelling_dict is not None + + @classmethod + def isEnchantOk(cls): + """Returns True if enchant is available""" + return 'enchant' in globals() + + @classmethod + def reloadEnchant(cls, libpath=u''): + """Try (re)loading the enchant module. Use to dynamically try to + import enchant incase it could be loaded at the time of the import of + this module. + @keyword libpath: optionally specify path to libenchant + @return: bool + + """ + try: + if libpath and os.path.exists(libpath): + os.environ['PYENCHANT_LIBRARY_PATH'] = libpath + + if cls.isEnchantOk(): + reload(enchant) + else: + mod = __import__('enchant', globals(), locals()) + globals()['enchant'] = mod + except ImportError: + return False + else: + return True + + def getLanguage(self): + """Returns True if a dictionary is available to spell check the current + language. + """ + return self._spelling_lang + + def setMinimumWordSize(self, size): + """Set the minimum word size that will be looked up in the dictionary. + + Words smaller than this size won't be spell checked. + """ + self._spelling_word_size = size + + def clearAll(self): + """Clear the stc of all spelling indicators.""" + self.stc.StartStyling(0, self._spelling_indicator_mask) + self.stc.SetStyling(self.stc.GetLength(), 0) + + def checkRange(self, start, end): + """Perform a spell check over a range of text in the document. + + This is the main spell checking routine -- it loops over the range + of text using the L{findNextWord} method to break the text into + words to check. Misspelled words are highlighted using the current + indicator. + + @param start: starting position + @param end: last position to check + """ + spell = self._spelling_dict + if not spell: + return + + # Remove any old spelling indicators + mask = self._spelling_indicator_mask + count = end - start + if count <= 0: + if self._spelling_debug: + print("No need to check range: start=%d end=%d count=%d" % (start, end, count)) + return + self.stc.StartStyling(start, mask) + self.stc.SetStyling(count, 0) + + text = self.stc.GetTextRange(start, end) # note: returns unicode + unicode_index = 0 + max_index = len(text) + + last_index = 0 # last character in text a valid raw byte position + last_pos = start # raw byte position corresponding to last_index + while unicode_index < max_index: + start_index, end_index = self.findNextWord(text, unicode_index, max_index) + if end_index >= 0: + if end_index - start_index >= self._spelling_word_size: + if self._spelling_debug: + print("checking %s at text[%d:%d]" % (repr(text[start_index:end_index]), start_index, end_index)) + if not spell.check(text[start_index:end_index]): + # Because unicode characters are stored as utf-8 in the + # stc and the positions in the stc correspond to the + # raw bytes, not the number of unicode characters, we + # have to find out the offset to the unicode chars in + # terms of raw bytes. + + # find the number of raw bytes from the last calculated + # styling position to the start of the word + last_pos += len(text[last_index:start_index].encode('utf-8')) + + # find the length of the word in raw bytes + raw_count = len(text[start_index:end_index].encode('utf-8')) + + if self._spell_check_region(last_pos): + if self._spelling_debug: + print("styling text[%d:%d] = (%d,%d) to %d" % (start_index, end_index, last_pos, last_pos + raw_count, mask)) + self.stc.StartStyling(last_pos, mask) + self.stc.SetStyling(raw_count, mask) + elif self._spelling_debug: + print("not in valid spell check region. styling position corresponding to text[%d:%d] = (%d,%d)" % (start_index, end_index, last_pos, last_pos + raw_count)) + last_pos += raw_count + last_index = end_index + unicode_index = end_index + else: + break + + def checkAll(self): + """Perform a spell check on the entire document.""" + return self.checkRange(0, self.stc.GetLength()) + + def checkSelection(self): + """Perform a spell check on the currently selected region.""" + return self.checkRange(self.stc.GetSelectionStart(), self.stc.GetSelectionEnd()) + + def checkLines(self, startline=-1, count=-1): + """Perform a spell check on group of lines. + + Given the starting line, check the spelling on a block of lines. If + the number of lines in the block is not specified, use the number of + currently visibile lines. + + @param startline: current line, or -1 to use the first visible line + @param count: number of lines in the block, or -1 to use the number of + lines visible on screen + """ + if startline < 0: + startline = self.stc.GetFirstVisibleLine() + start = self.stc.PositionFromLine(startline) + if count < 0: + count = self.stc.LinesOnScreen() + endline = startline + count + if endline > self.stc.GetLineCount(): + endline = self.stc.GetLineCount() - 1 + end = self.stc.GetLineEndPosition(endline) + if self._spelling_debug: + print("Checking lines %d-%d, chars %d=%d" % (startline, endline, start, end)) + return self.checkRange(start, end) + + def checkCurrentPage(self): + """Perform a spell check on the currently visible lines.""" + return self.checkLines() + + def findNextWord(self, utext, index, length): + """Find the next valid word to check. + + Designed to be overridden in subclasses, this method takes a starting + position in an array of text and returns a tuple indicating the next + valid word in the string. + + @param utext: array of unicode chars + @param i: starting index within the array to search + @param length: length of the text + @return: tuple indicating the word start and end indexes, or (-1, -1) + indicating that the end of the array was reached and no word was found + """ + while index < length: + if utext[index].isalpha(): + end = index + 1 + while end < length and utext[end].isalpha(): + end += 1 + return (index, end) + index += 1 + return (-1, -1) + + def startIdleProcessing(self): + """Initialize parameters needed for idle block spell checking. + + This must be called before the first call to L{processIdleBlock} + or if you wish to restart the spell checking from the start + of the document. It initializes parameters needed by the + L{processIdleBlock} in order to process the document during idle + time. + """ + self._spelling_last_idle_line = 0 + + def processIdleBlock(self): + """Process a block of lines during idle time. + + This method is designed to be called during idle processing and will + spell check a small number of lines. The next idle processing event + will continue from where the previous call left off, and in this way + over some number of idle events will spell check the entire document. + + Once the entire document is spell checked, a flag is set and + further calls to this method will immediately return. Calling + L{startIdleProcessing} will cause the idle processing to start + checking from the beginning of the document. + """ + self.processDirtyRanges() + if self._spelling_last_idle_line < 0: + return + if self._spelling_debug: + print("Idle processing page starting at line %d" % self._spelling_last_idle_line) + self.checkLines(self._spelling_last_idle_line) + self._spelling_last_idle_line += self.stc.LinesOnScreen() + if self._spelling_last_idle_line > self.stc.GetLineCount(): + self._spelling_last_idle_line = -1 + return False + return True + + def processCurrentlyVisibleBlock(self): + """Alternate method to check lines during idle time. + + This method is designed to be called during idle processing and will + spell check the currently visible block of lines. Once the visible + block has been checked, repeatedly calling this method will have + no effect until the line position changes (or in the less frequent + occurrence when the number of lines on screen changes by resizing + the window). + """ + self.processDirtyRanges() + + self._spelling_last_idle_line = self.stc.GetFirstVisibleLine() + curr_block = self._spelling_last_idle_line + self.stc.LinesOnScreen() + if self._no_update or curr_block == self._last_block: + return + + self.checkLines(self._spelling_last_idle_line) + self._spelling_last_idle_line += self.stc.LinesOnScreen() + self._last_block = self._spelling_last_idle_line + return True + + def getSuggestions(self, word): + """Get suggestion for the correct spelling of a word. + + @param word: word to check + + @return: list of suggestions, or an empty list if any of the following + are true: there are no suggestions, the word is shorter than the + minimum length, or the dictionary can't be found. + """ + spell = self._spelling_dict + if spell and len(word) >= self._spelling_word_size: + words = spell.suggest(word) + if self._spelling_debug: + print("suggestions for %s: %s" % (word, words)) + return words + return [] + + def checkWord(self, pos=None, atend=False): + """Check the word at the current or specified position. + + @param pos: position of a character in the word (or at the start or end + of the word), or None to use the current position + @param atend: True if you know the cursor is at the end of the word + """ + if pos is None: + pos = self.stc.GetCurrentPos() + if atend: + end = pos + else: + end = self.stc.WordEndPosition(pos, True) + start = self.stc.WordStartPosition(pos, True) + if self._spelling_debug: + print("%d-%d: %s" % (start, end, self.stc.GetTextRange(start, end))) + self.checkRange(start, end) + + def addDirtyRange(self, start, end, lines_added=0, deleted=False): + """Add a range of characters to a list of dirty regions that need to be + updated when some idle time is available. + + """ + count = end - start + if deleted: + count = -count + if start == self.current_dirty_end: + self.current_dirty_end = end + elif start >= self.current_dirty_start and start < self.current_dirty_end: + self.current_dirty_end += count + else: + ranges = [] + if self.current_dirty_start >= 0: + ranges.append((self.current_dirty_start, self.current_dirty_end)) + for range_start, range_end in self.dirty_ranges: + if start < range_start: + range_start += count + range_end += count + ranges.append((range_start, range_end)) + self.dirty_ranges = ranges + + self.current_dirty_start = start + self.current_dirty_end = end + + # If there has been a change before the word that used to be under the + # cursor, move the pointer so it matches the text + if start < self.current_word_start: + self.current_word_start += count + self.current_word_end += count + elif start <= self.current_word_end: + self.current_word_end += count + # Prevent nonsensical word end if lots of text have been deleted + if self.current_word_end < self.current_word_start: + #print("word start = %d, word end = %d" % (self.current_word_start, self.current_word_end)) + self.current_word_end = self.current_word_start + + if lines_added > 0: + start = self.current_dirty_start + line = self.stc.LineFromPosition(start) + while True: + line_end = self.stc.GetLineEndPosition(line) + if line_end >= end: + #self.dirty_ranges.append((start, line_end)) + if end > start: + self.current_dirty_start = start + self.current_dirty_end = end + else: + self.current_dirty_start = self.current_dirty_end = -1 + break + self.dirty_ranges.append((start, line_end)) + line += 1 + start = self.stc.PositionFromLine(line) + + if self._spelling_debug: + print("event: %d-%d, current dirty range: %d-%d, older=%s" % (start, end, self.current_dirty_start, self.current_dirty_end, self.dirty_ranges)) + + def clearDirtyRanges(self, ranges=None): + """Throw away all dirty ranges + + """ + self.current_dirty_start = self.current_dirty_end = -1 + self.current_word_start = self.current_word_end = -1 + if ranges is not None: + self.dirty_ranges = ranges + else: + self.dirty_ranges = [] + + def processDirtyRanges(self): + cursor = self.stc.GetCurrentPos() + + # Check that the cursor has moved off the current word and if so check + # its spelling + if self.current_word_start > 0: + if cursor < self.current_word_start or cursor > self.current_word_end: + self.checkRange(self.current_word_start, self.current_word_end) + self.current_word_start = -1 + + # Check spelling around the region currently being typed + if self.current_dirty_start >= 0: + range_start, range_end = self.processDirtyRange(self.current_dirty_start, self.current_dirty_end) + + # If the cursor is in the middle of a word, remove the spelling + # markers + if cursor >= range_start and cursor <= range_end: + word_start = self.stc.WordStartPosition(cursor, True) + word_end = self.stc.WordEndPosition(cursor, True) + mask = self._spelling_indicator_mask + self.stc.StartStyling(word_start, mask) + self.stc.SetStyling(word_end - word_start, 0) + + if word_start != word_end: + self.current_word_start = word_start + self.current_word_end = word_end + else: + self.current_word_start = -1 + self.current_dirty_start = self.current_dirty_end = -1 + + # Process a chunk of dirty ranges + needed = min(len(self.dirty_ranges), self.dirty_range_count_per_idle) + ranges = self.dirty_ranges[0:needed] + self.dirty_ranges = self.dirty_ranges[needed:] + for start, end in ranges: + if self._spelling_debug: + print("processing %d-%d" % (start, end)) + self.processDirtyRange(start, end) + + def processDirtyRange(self, start, end): + range_start = self.stc.WordStartPosition(start, True) + range_end = self.stc.WordEndPosition(end, True) + if self._spelling_debug: + print("processing dirty range %d-%d (modified from %d-%d): %s" % (range_start, range_end, start, end, repr(self.stc.GetTextRange(range_start, range_end)))) + self.checkRange(range_start, range_end) + return range_start, range_end + + +if __name__ == "__main__": + import sys + try: + import enchant + except: + print("pyenchant not available, so spelling correction won't work.") + print("Get pyenchant from http://pyenchant.sourceforge.net") + + class TestSTC(wx.stc.StyledTextCtrl): + def __init__(self, *args, **kwargs): + wx.stc.StyledTextCtrl.__init__(self, *args, **kwargs) + self.spell = STCSpellCheck(self, language="en_US") + self.SetMarginType(0, wx.stc.STC_MARGIN_NUMBER) + self.SetMarginWidth(0, 32) + self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified) + self.Bind(wx.EVT_IDLE, self.OnIdle) + self.modified_count = 0 + self.idle_count = 0 + + def OnModified(self, evt): + # NOTE: on really big insertions, evt.GetText can cause a + # MemoryError on MSW, so I've commented this dprint out. + mod = evt.GetModificationType() + if mod & wx.stc.STC_MOD_INSERTTEXT or mod & wx.stc.STC_MOD_DELETETEXT: + #print("(%s) at %d: text=%s len=%d" % (self.transModType(evt.GetModificationType()),evt.GetPosition(), repr(evt.GetText()), evt.GetLength())) + pos = evt.GetPosition() + last = pos + evt.GetLength() + self.spell.addDirtyRange(pos, last, evt.GetLinesAdded(), mod & wx.stc.STC_MOD_DELETETEXT) + #self.modified_count += 1 + #if self.modified_count > 10: + # wx.CallAfter(self.spell.processDirtyRanges) + # self.modified_count = 0 + evt.Skip() + + def OnIdle(self, evt): + #print("Idle") + self.idle_count += 1 + if self.idle_count > 10: + self.spell.processIdleBlock() + self.idle_count = 0 + + def transModType(self, modType): + st = "" + table = [(wx.stc.STC_MOD_INSERTTEXT, "InsertText"), + (wx.stc.STC_MOD_DELETETEXT, "DeleteText"), + (wx.stc.STC_MOD_CHANGESTYLE, "ChangeStyle"), + (wx.stc.STC_MOD_CHANGEFOLD, "ChangeFold"), + (wx.stc.STC_PERFORMED_USER, "UserFlag"), + (wx.stc.STC_PERFORMED_UNDO, "Undo"), + (wx.stc.STC_PERFORMED_REDO, "Redo"), + (wx.stc.STC_LASTSTEPINUNDOREDO, "Last-Undo/Redo"), + (wx.stc.STC_MOD_CHANGEMARKER, "ChangeMarker"), + (wx.stc.STC_MOD_BEFOREINSERT, "B4-Insert"), + (wx.stc.STC_MOD_BEFOREDELETE, "B4-Delete") + ] + + for flag,text in table: + if flag & modType: + st = st + text + " " + + if not st: + st = 'UNKNOWN' + + return st + + class Frame(wx.Frame): + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + + self.stc = TestSTC(self, -1) + + self.CreateStatusBar() + menubar = wx.MenuBar() + self.SetMenuBar(menubar) # Adding the MenuBar to the Frame content. + menu = wx.Menu() + menubar.Append(menu, "File") + self.menuAdd(menu, "Open", "Open File", self.OnOpenFile) + self.menuAdd(menu, "Quit", "Exit the pragram", self.OnQuit) + menu = wx.Menu() + menubar.Append(menu, "Edit") + self.menuAdd(menu, "Check All", "Spell check the entire document", self.OnCheckAll) + self.menuAdd(menu, "Check Current Page", "Spell check the currently visible page", self.OnCheckPage) + self.menuAdd(menu, "Check Selection", "Spell check the selected region", self.OnCheckSelection) + menu.AppendSeparator() + self.menuAdd(menu, "Clear Spelling", "Remove spelling correction indicators", self.OnClearSpelling) + menu = wx.Menu() + menubar.Append(menu, "Language") + langs = self.stc.spell.getAvailableLanguages() + self.lang_id = {} + for lang in langs: + id = wx.NewId() + self.lang_id[id] = lang + self.menuAdd(menu, lang, "Change dictionary to %s" % lang, self.OnChangeLanguage, id=id) + + + def loadFile(self, filename): + fh = open(filename) + self.stc.SetText(fh.read()) + self.stc.spell.clearDirtyRanges() + self.stc.spell.checkCurrentPage() + + def loadSample(self, paragraphs=10): + lorem_ipsum = u"""\ +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus mattis +commodo sem. Phasellus scelerisque tellus id lorem. Nulla facilisi. +Suspendisse potenti. Fusce velit odio, scelerisque vel, consequat nec, +dapibus sit amet, tortor. Vivamus eu turpis. Nam eget dolor. Integer +at elit. Praesent mauris. Nullam non nulla at nulla tincidunt malesuada. +Phasellus id ante. Sed mauris. Integer volutpat nisi non diam. Etiam +elementum. Pellentesque interdum justo eu risus. Cum sociis natoque +penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc +semper. In semper enim ut odio. Nulla varius leo commodo elit. Quisque +condimentum, nisl eget elementum laoreet, mauris turpis elementum felis, ut +accumsan nisl velit et mi. + +And some Russian: \u041f\u0438\u0442\u043e\u043d - \u043b\u0443\u0447\u0448\u0438\u0439 \u044f\u0437\u044b\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f! + +""" + self.stc.ClearAll() + for i in range(paragraphs): + self.stc.AppendText(lorem_ipsum) + # Call the spell check after the text has had a chance to be + # displayed and the window resized to the correct size. + self.stc.spell.clearDirtyRanges() + wx.CallAfter(self.stc.spell.checkCurrentPage) + + def menuAdd(self, menu, name, desc, fcn, id=-1, kind=wx.ITEM_NORMAL): + if id == -1: + id = wx.NewId() + a = wx.MenuItem(menu, id, name, desc, kind) + menu.AppendItem(a) + wx.EVT_MENU(self, id, fcn) + menu.SetHelpString(id, desc) + + def OnOpenFile(self, evt): + dlg = wx.FileDialog(self, "Choose a text file", + defaultDir = "", + defaultFile = "", + wildcard = "*") + if dlg.ShowModal() == wx.ID_OK: + print("Opening %s" % dlg.GetPath()) + self.loadFile(dlg.GetPath()) + dlg.Destroy() + + def OnQuit(self, evt): + self.Close(True) + + def OnCheckAll(self, evt): + self.stc.spell.checkAll() + + def OnCheckPage(self, evt): + self.stc.spell.checkCurrentPage() + + def OnCheckSelection(self, evt): + self.stc.spell.checkSelection() + + def OnClearSpelling(self, evt): + self.stc.spell.clearAll() + + def OnChangeLanguage(self, evt): + id = evt.GetId() + normalized = locale.normalize(self.lang_id[id]) + try: + locale.setlocale(locale.LC_ALL, normalized) + print("Changing locale %s, dictionary set to %s" % (normalized, self.lang_id[id])) + except locale.Error: + print("Can't set python locale to %s; dictionary set to %s" % (normalized, self.lang_id[id])) + self.stc.spell.setLanguage(self.lang_id[id]) + self.stc.spell.clearAll() + self.stc.spell.checkCurrentPage() + + app = wx.App(False) + frame = Frame(None, size=(600, -1)) + need_sample = True + if len(sys.argv) > 1: + if not sys.argv[-1].startswith("-"): + frame.loadFile(sys.argv[-1]) + need_sample = False + if need_sample: + frame.loadSample() + if '-d' in sys.argv: + frame.stc.spell._spelling_debug = True + frame.Show() + app.MainLoop() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/vertedit.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/vertedit.py new file mode 100644 index 0000000..3b35565 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/extern/vertedit.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python2 +# -*- coding: latin1 -*- +# +# Created in 2008 by Don Quijote +# Licence: wxWindows +# +# Updated 02/09/2011 Cody Precord + +#-----------------------------------------------------------------------------# + +import wx +from wx import stc +from collections import deque +from functools import partial + +#-----------------------------------------------------------------------------# +# Globals +STATE_OFF = 0 +STATE_SELECTION = 1 +STATE_ACTIVE = 2 + +#-----------------------------------------------------------------------------# + +class VertEdit(object): + """ + Used instance variables: + - e STC Editor passed via class constructor + - enabled To deactivate this plugin after been loaded + - state 0: mode off, 1: mode just activated but still in dynamic line selection, 2: mode active, static block of lines + - stack Holds insertions and deletions, to replicate on all lines of the block + - oldCol Used by vertCaret() to remember last column of vertical caret + - markedLines Used by newMarkers() to remember highlighted lines + - orig Holds position of anchor when first switching from state 0 to state 1. + - origCol Holds column of anchor when first switching from state 0 to state 1. + - origLine Holds line of anchor when first switching from state 0 to state 1. + - gotDeletes An action caused STC to try to delete some text while in state 1. + - insCol Remembers column of cursor before STC deleted some text (see gotDeletes) + - delCol2 Remembers last column enclosing text to be deleted + + """ + INS = stc.STC_MOD_INSERTTEXT|stc.STC_PERFORMED_USER + DEL = stc.STC_MOD_DELETETEXT|stc.STC_PERFORMED_USER + BDEL = stc.STC_MOD_BEFOREDELETE|stc.STC_PERFORMED_USER + + def __init__(self, editor, + blockBackColour="light blue", + markerNumber=1): + super(VertEdit, self).__init__() + + # Attributes + self.e = editor + self.marker = markerNumber + self.enabled = False # Disable by default + self.state = STATE_OFF + self.stack = deque() + self.jitter = None + self.SetBlockColor(blockBackColour) + self.modmask = long(self.e.ModEventMask) + + # Event Handlers +# self.e.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) +# self.e.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) + + def enable(self, enable=True): + """Enable the column edit mode""" + if not enable: + self.endMode() + self.enabled = enable + + def disable(self): + """Disable the column edit mode""" + self.endMode() + self.enabled = False + + @property + def Enabled(self): + """Is the column edit mode enabled""" + return self.enabled + + def vertCaret(self, col=None, pos=None): + if col is None: + if pos is None: + pos = self.e.CurrentPos + col = self.e.GetColumn(pos) + + if col != self.oldCol: + self.e.EdgeColumn = col + self.oldCol = col + + def newMarkers(self, linesToMark=frozenset()): + # careful when STC collapses markers due to multiline deletion! + # for line in linesToMark.difference(self.markedLines): + for line in linesToMark: + self.e.MarkerAdd(line, self.marker) + + for line in self.markedLines.difference(linesToMark): + self.e.MarkerDelete(line, self.marker) + + self.markedLines = linesToMark + + def OnKeyDown(self, evt): + if self.Enabled and self.state != STATE_OFF: + k = evt.GetKeyCode() + if k in (wx.WXK_ESCAPE, wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT, + wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT) and evt.Modifiers == 0: + if k == wx.WXK_ESCAPE: + self.endMode() + self.e.GotoPos(self.e.CurrentPos) + return + elif self.state == STATE_SELECTION: + self.e.Anchor = self.e.CurrentPos + evt.Skip() + + def endMode(self): + if self.state != STATE_OFF: + self.e.SetModEventMask(self.modmask) + self.e.HideSelection(False) + self.state = STATE_OFF + self.e.EndUndoAction() + self.e.EdgeColumn, self.e.EdgeMode = self.edge + self.newMarkers() + + def fn_ins(self, col, text, line): + colEnd = self.e.GetColumn(self.e.GetLineEndPosition(line)) + if col > colEnd: + text = u" " * (col - colEnd) + text + col = colEnd + + self.e.CurrentPos = pos = self.e.FindColumn(line, col) + self.e.AddText(text) + return col == self.e.GetColumn(pos) + + def fn_del(self, col1, col2, line): + pos1 = self.e.FindColumn(line, col1) + pos2 = self.e.FindColumn(line, col2) + self.e.CurrentPos = pos1 + + if pos1 == pos2 or col2 != self.e.GetColumn(pos2): + return False + + self.e.SetTargetStart(pos1) + self.e.SetTargetEnd(pos2) + self.e.ReplaceTarget(u'') + return True + + def OnModified(self, evt): + if self.Enabled and self.state > STATE_OFF: + fn = None + if evt.ModificationType & VertEdit.INS == VertEdit.INS: + col = self.insCol or self.e.GetColumn(evt.Position) + fn = partial(self.fn_ins, col, evt.Text) + self.insCol = None + elif evt.ModificationType & VertEdit.DEL == VertEdit.DEL: + if self.state == STATE_ACTIVE: + fn = partial(self.fn_del, self.e.GetColumn(evt.Position), self.delCol2) + elif evt.ModificationType & VertEdit.BDEL == VertEdit.BDEL: + self.delCol2 = self.e.GetColumn(evt.Position + evt.Length) + if self.state == STATE_SELECTION and not self.gotDeletes: + self.gotDeletes = True + self.insCol = self.e.GetColumn(self.e.CurrentPos) + + if fn: + if evt.LinesAdded: + self.endMode() + else: + self.stack.append(fn) + + def SetBlockColor(self, color): + """Set the block background color used during the highlight + @param color: wxColor + + """ + self.e.MarkerDefine(self.marker, + stc.STC_MARK_BACKGROUND, + background=color) + + def startMode(self, singleLine=False): + if self.state == STATE_OFF: + self.e.ModEventMask |= VertEdit.INS|VertEdit.DEL|VertEdit.BDEL + self.e.HideSelection(True) + orig = self.e.Anchor + self.origCol = self.e.GetColumn(orig) + self.origLine = self.e.LineFromPosition(orig) + self.stack.clear() + self.gotDeletes = False + self.e.BeginUndoAction() + + # painting related + self.oldCol = -1 + self.markedLines = frozenset() + self.edge = self.e.EdgeColumn, self.e.EdgeMode + self.e.EdgeMode = stc.STC_EDGE_LINE + + self.state = STATE_SELECTION + self.insCol = None + self.curLine = self.e.LineFromPosition(self.e.CurrentPos) + self.lines = frozenset(range(min(self.origLine, self.curLine), + max(self.origLine, self.curLine) + 1)) + self.jitter = None + + if singleLine: + newA = self.e.PositionFromLine(self.curLine) + if newA == self.e.CurrentPos: + newA = self.e.GetLineEndPosition(self.curLine) + if newA == self.e.CurrentPos: + self.e.CurrentPos -= 1 + newA += 1 + self.e.Anchor = newA + self.jitter = newA + + self.e.SetSelectionMode(stc.STC_SEL_LINES) + + # painting related + self.vertCaret() + self.newMarkers(self.lines) + + def OnUpdateUI(self, evt): + """Handle EVT_UPDATEUI""" + # Check if enabled + if not self.Enabled: + return + + curP = self.e.CurrentPos + if self.state == STATE_OFF: + anchor = self.e.Anchor + selection = anchor != curP + sameCol = selection and self.e.GetColumn(curP) == self.e.GetColumn(anchor) + if sameCol: + self.startMode() + return + + anchor = self.e.Anchor + selection = anchor != curP + sameCol = selection and self.e.GetColumn(curP) == self.origCol + linesOverride = None + if self.state == STATE_SELECTION: + if self.jitter == anchor and selection: + self.jitter = None + self.e.Anchor = anchor = self.e.FindColumn(self.origLine,self.origCol) + selection = anchor != curP + + self.state = STATE_ACTIVE + if self.stack: + self.e.EndUndoAction() + self.e.Undo() + self.e.BeginUndoAction() + linesOverride = self.lines + self.newMarkers(self.lines) + curP = self.e.PositionFromLine(self.curLine) + elif sameCol: + self.startMode() + elif self.gotDeletes or selection: + if not self.gotDeletes: + self.e.Anchor = self.e.FindColumn(self.origLine, self.origCol) + self.endMode() + elif curP == self.e.FindColumn(self.origLine, self.origCol): + self.startMode(True) + + if self.state == STATE_ACTIVE: + curI = self.e.LineFromPosition(curP) + if curP == self.e.GetLineEndPosition(curI): + self.e.GotoPos(curP) + + if curI not in self.lines: + self.endMode() + else: + self.e.HideSelection(False) + curC = self.e.GetColumn(curP) + if self.stack: + self.state *= -1 + lines = linesOverride or self.lines.difference((curI,)) + + cont = True + while(cont and self.stack): + fn = self.stack.popleft() + for line in lines: + if not fn(line): + self.e.EndUndoAction() + self.e.Undo() + self.e.BeginUndoAction() + cont = False + break + + self.stack.clear() + self.e.EndUndoAction() + self.e.BeginUndoAction() + curC = self.e.GetColumn(self.e.CurrentPos) + self.e.GotoPos(self.e.FindColumn(curI, curC)) + self.state *= -1 + + self.vertCaret(col = curC) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/generator.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/generator.py new file mode 100644 index 0000000..70d3215 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/generator.py @@ -0,0 +1,939 @@ +############################################################################### +# Name: generator.py # +# Purpose: Utility classes for creating various formatted plain text # +# from the contents of a EdStc text buffer (i.e HTML, LaTeX, Rtf) # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides various methods and classes for generating code and transforming code +to different formats such as html, latex, rtf with all the styling and formating +intact from how the view is shown in the editor. + +It also provides a plugin interface that allows for plugins that wish to provide +similar services for manipulating and transforming text. + +@summary: Editra's Generator interface and implementations + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: generator.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Imports +import wx +import wx.stc +import time + +# Editra Libraries +import ed_glob +import ed_menu +from ed_style import StyleItem +import util +import plugin +import ebmlib +import eclib + +#--------------------------------------------------------------------------# +# Globals +_ = wx.GetTranslation + +FONT_FALLBACKS = "Trebuchet, Tahoma, sans-serif" + +#--------------------------------------------------------------------------# +# Plugin Interface +class GeneratorI(plugin.Interface): + """Plugins that are to be used for generating code/document need + to implement this interface. + + """ + def Generate(self, stc): + """Generates the code. The txt_ctrl parameter is a reference + to an ED_STC object (see ed_stc.py). The return value of this + function needs to be a 2 item tuple with the first item being + an associated file extension to use for setting highlighting + if available and the second item is the string of the new document. + @param stc: reference to an an stc defined in ed_stc.py + @see: L{ed_stc} + + """ + pass + + def GetId(self): + """Must return the Id used for the generator objects + menu id. This is used to identify which Generator to + call on a menu event. + @return: menu id that identifies the implemented generator + + """ + pass + + def GetMenuEntry(self, menu): + """Returns the MenuItem entry for this generator + @return: wx.MenuItem + + """ + pass + +#-----------------------------------------------------------------------------# + +class Generator(plugin.Plugin): + """Plugin Interface Extension Point for Generator + type plugin objects. Generator objects are used + to generate a document/code from one type to another. + + """ + observers = plugin.ExtensionPoint(GeneratorI) + + def InstallMenu(self, menu): + """Appends the menu of available Generators onto + the given menu. + @param menu: menu to install entries into + + """ + # Fetch all the menu items for each generator object + menu_items = list() + for observer in self.observers: + try: + menu_i = observer.GetMenuEntry(menu) + if menu_i: + menu_items.append((menu_i.GetItemLabel(), menu_i)) + except Exception, msg: + util.Log("[generator][err] %s" % str(msg)) + + # Construct the menu + menu_items.sort() + genmenu = ed_menu.EdMenu() + for item in menu_items: + genmenu.AppendItem(item[1]) + menu.AppendMenu(ed_glob.ID_GENERATOR, _("Generator"), genmenu, + _("Generate Code and Documents")) + + def GenerateText(self, e_id, txt_ctrl): + """Generates the new document text based on the given + generator id and contents of the given ED_STC text control. + @param e_id: event id originating from menu entry + @param txt_ctrl: EditraStc + @return: the generated text + + """ + gentext = None + start = time.time() + # Find the correct generator and run its generate method on the + # given text control. + for observer in self.observers: + if observer.GetId() == e_id: + gentext = observer.Generate(txt_ctrl) + util.Log("[generator][info] Generation time %f" % (time.time() - start)) + return gentext + +#-----------------------------------------------------------------------------# + +class Html(plugin.Plugin): + """Transforms the text from a given Editra stc to a fully + styled html page. Inline CSS is generated and inserted into + the head of the Html to style the text regions by default + unless requested to generate a separate sheet. + + """ + plugin.Implements(GeneratorI) + def __init__(self, mgr): + """Creates the Html object from an Editra stc text control + @param mgr: This generators plugin manager + + """ + plugin.Plugin.__init__(self) + + # Attributes + self._id = ed_glob.ID_HTML_GEN + self.stc = None + self.head = wx.EmptyString + self.css = dict() + self.body = wx.EmptyString + + def __str__(self): + """Returns the string of html + @return: string version of html object + + """ + # Assemble the embedded html + style = "<style type=\"text/css\">\n%s</style>" + css = wx.EmptyString + for key in self.css: + css += str(self.css[key]) + "\n" + css = css % self.stc.GetFontDictionary() + style = style % css + + # Insert the css into the head + head = self.head.replace('</head>', style + "\n</head>") + + # Assemble the body of the html + html = "<html>\n%s\n%s\n</html>" + html = html % (head, self.body) + return html + + def Unicode(self): + """Returns the html as Unicode + @return: Unicode string of html + + """ + return unicode(self.__str__()) + + def Generate(self, stc_ctrl): + """Generates and returns the document + @param stc_ctrl: text control to get text from + + """ + self.stc = stc_ctrl + self.head = self.GenerateHead() + self.body = self.GenerateBody() + return ("html", self.__str__()) + + def GenerateHead(self): + """Generates the html head block + @return: html header information + + """ + return "<head>\n<title>%s</title>\n" \ + "<meta name=\"Generator\" content=\"Editra/%s\">\n" \ + "<meta http-equiv=\"content-type\" content=\"text/html; " \ + "charset=utf-8\">" \ + "\n</head>" % (ebmlib.GetFileName(self.stc.GetFileName()), + ed_glob.VERSION) + + def GenerateBody(self): + """Generates the body of the html from the stc's content. To do + this it does a character by character parse of the stc to determine + style regions and generate css and and styled spans of html in order + to generate an 'exact' html representation of the stc's window. + @return: the body section of the html generated from the text control + + """ + html = list() + parse_pos = 0 + style_start = 0 + style_end = 0 + last_pos = self.stc.GetLineEndPosition(self.stc.GetLineCount()) + 1 + + # Get Document start point info + last_id = self.stc.GetStyleAt(parse_pos) + tag = self.stc.FindTagById(last_id) + if tag != wx.EmptyString: + s_item = StyleItem() + s_item.SetAttrFromStr(self.stc.GetStyleByName(tag)) + self.css[tag] = CssItem(tag.split('_')[0], s_item) + + # Optimizations + stc = self.stc + GetStyleAt = stc.GetStyleAt + + # Build Html + while parse_pos < last_pos: + parse_pos += 1 + curr_id = GetStyleAt(parse_pos) + style_end = parse_pos + # If style region has changed close section + if curr_id == 0 and GetStyleAt(parse_pos + 1) == last_id: + curr_id = last_id + + if curr_id != last_id or parse_pos == last_pos: + tmp = stc.GetTextRange(style_start, style_end) + tmp = self.TransformText(tmp) + if tmp.isspace() or tag in ["default_style", "operator_style"]: + html.append(tmp) + else: + tmp2 = "<span class=\"%s\">%s</span>" + html.append(tmp2 % (tag.split('_')[0], tmp)) + + last_id = curr_id + style_start = style_end + tag = stc.FindTagById(last_id) + if tag not in self.css: + s_item = StyleItem() + s_item.SetAttrFromStr(stc.GetStyleByName(tag)) + self.css[tag] = CssItem(tag.split('_')[0], s_item) + + # Case for unstyled documents + if len(html) == 0: + s_item = StyleItem() + s_item.SetAttrFromStr(stc.GetStyleByName('default_style')) + self.css['default_style'] = CssItem('default', s_item) + html.append(self.TransformText(stc.GetText())) + else: + self.OptimizeCss() + + return "<body class=\"default\">\n<pre>\n%s\n</pre>\n</body>" % \ + "".join(html) + + def GetId(self): + """Returns the menu identifier for the HTML generator + @return: id of this object + + """ + return self._id + + def GetMenuEntry(self, menu): + """Returns the Menu control for the HTML generator + @return: menu entry for this generator + + """ + return wx.MenuItem(menu, self._id, _("Generate %s") % u"HTML", + _("Generate a %s version of the " \ + "current document") % u"HTML") + + def OptimizeCss(self): + """Optimizes the CSS Set + @postcondition: css is optimized to remove any redundant entries + + """ + # Must have the default style defined + if 'default_style' not in self.css: + return + + # Don't style operators. This is to optimize the html size + if 'operator_style' in self.css: + self.css.pop('operator_style') + + # All other css elements will inherit from the default + default = self.css['default_style'] + for key in self.css: + if key == 'default_style': + continue + if default.GetFont() == self.css[key].GetFont(): + self.css[key].SetFont(wx.EmptyString) + if default.GetFontSize() == self.css[key].GetFontSize(): + self.css[key].SetFontSize(wx.EmptyString) + if default.GetBackground() == self.css[key].GetBackground(): + self.css[key].SetBackground(wx.EmptyString) + if default.GetColor() == self.css[key].GetColor(): + self.css[key].SetColor(wx.EmptyString) + for item in default.GetDecorators(): + if item in self.css[key].GetDecorators(): + self.css[key].RemoveDecorator(item) + + def TransformText(self, text): + """Does character substitution on a string and returns + the html equivalent of the given string. + @param text: text to transform + @return: text with all special characters transformed + + """ + text = text.replace('&', "&") # Ampersands + text = text.replace('<', "<") # Less Than Symbols + text = text.replace('>', ">") # Greater Than Symbols + text = text.replace("\"", """) + return text + +#-----------------------------------------------------------------------------# + +class CssItem: + """Converts an Editra StyleItem to a Css item for use in + generating html. + + """ + def __init__(self, class_tag, style_item): + """Initializes a Css object equivalent of an Editra StyleItem + @note: it is left up to the caller to do any string substitution + for font faces and size values as this class will construct the css + item as a mere reformation of StyleItem + @param class_tag: StyleItem tag name + @param style_item: ed_style.StyleItem + @see: L{ed_style} + + """ + + # Attributes + self._tag = class_tag + self._back = style_item.GetBack() + self._fore = style_item.GetFore() + self._font = style_item.GetFace() + self._size = style_item.GetSize() + + # List of additional style specs + self._decor = self.ExtractDecorators() + self._decor.extend(style_item.GetModifierList()) + + def __eq__(self, css2): + """Defines the == operator for the CssItem class + @param css2: CssItem to compare to + @return: whether the two items are equivalent + + """ + return self.__str__() == str(css2) + + def __str__(self): + """Outputs the css item as a formatted css block + @return: CssItem as a string + + """ + # Generate the main style attributes + css = ".%s {\n%s}" + css_body = wx.EmptyString + if self._font != wx.EmptyString: + font = self._font.split(',') + css_body += u"\tfont-family: %s, %s;\n" % (font[0], FONT_FALLBACKS) + if self._size != wx.EmptyString: + size = self._size.split(',') + css_body += u"\tfont-size: %s;\n" % str(size[0]) + if self._fore != wx.EmptyString: + fore = self._fore.split(',') + css_body += u"\tcolor: %s;\n" % fore[0] + if self._back != wx.EmptyString: + back = self._back.split(',') + css_body += u"\tbackground-color: %s;\n" % back[0] + + # Add additional style modifiers + for item in self._decor: + if item == u'bold': + css_body += u"\tfont-weight: %s;\n" % item + elif item == u'italic': + css_body += u"\tfont-style: %s;\n" % item + elif item == u'underline': + css_body += u"\ttext-decoration: %s;\n" % item + else: + pass + + # Format the tag and body into the css def + if css_body != wx.EmptyString: + return css % (self._tag, css_body) + else: + return css_body + + def ExtractDecorators(self): + """Pulls additional style specs from the StyleItem such + as bold, italic, and underline styles. + @return: all decorators in the StyleItem (bold, underline, ect...) + + """ + decor = list() + for val in [ self._back, self._fore, self._font, self._size ]: + tmp = val.split(u',') + if len(tmp) < 2: + continue + else: + decor.append(tmp[1]) + return decor + + def GetBackground(self): + """Returns the Background value + @return: background color attribute + + """ + return self._back + + def GetColor(self): + """Returns the Font/Fore Color + @return: foreground color attribute + + """ + return self._fore + + def GetDecorators(self): + """Returns the list of decorators + @return: list of decorators item uses + + """ + return self._decor + + def GetFont(self): + """Returns the Font Name + @return: font name attribute + + """ + return self._font + + def GetFontSize(self): + """Returns the Font Size + @return: font size attribute + + """ + return self._size + + def RemoveDecorator(self, item): + """Removes a specified decorator from the decorator set + @param item: decorator item to remove + + """ + if item in self._decor: + self._decor.remove(item) + else: + pass + + def SetBackground(self, hex_str): + """Sets the Background Color + @param hex_str: hex color string to set background attribute with + + """ + self._back = hex_str + + def SetColor(self, hex_str): + """Sets the Font/Fore Color + @param hex_str: hex color string to set foreground attribute with + + """ + self._fore = hex_str + + def SetFont(self, font_face): + """Sets the Font Face + @param font_face: font face name to set font attribute with + + """ + self._font = font_face + + def SetFontSize(self, size_str): + """Sets the Font Point Size + @param size_str: point size to use for font in style + + """ + self._size = size_str + +#-----------------------------------------------------------------------------# + +class LaTeX(plugin.Plugin): + """Creates a LaTeX document object from the contents of the + supplied document reference. + @todo: performance improvements and wordwrap in generated document + + """ + plugin.Implements(GeneratorI) + def __init__(self, plgmgr): + """Initializes the LaTeX object + @param plgmgr: pluginmanger for this object + + """ + plugin.Plugin.__init__(self) + + # Attributes + self._stc = None + self._id = ed_glob.ID_TEX_GEN + self._dstyle = StyleItem() + self._cmds = dict() + + def CreateCmdName(self, name): + """Creates and returns a proper cmd name + @param name: name to construct command from + @return: latex formated command string + + """ + name = name.replace('_', '') + tmp = list() + alpha = "ABCDEFGHIJ" + for char in name: + if char.isdigit(): + tmp.append(alpha[int(char)]) + else: + tmp.append(char) + return "".join(tmp) + + def GenDoc(self): + """Generates the document body of the LaTeX document + @returns: the main body of the reference document marked up with latex + + """ + tex = list() + tmp = u'' + start = parse_pos = 0 + last_pos = self._stc.GetLineEndPosition(self._stc.GetLineCount()) + + # Define the default style + self.RegisterStyleCmd('default_style', \ + self._stc.GetItemByName('default_style')) + + # Get Document start point info + last_id = self._stc.GetStyleAt(parse_pos) + tmp = self.TransformText(self._stc.GetTextRange(parse_pos, + parse_pos + 1)) + tag = self._stc.FindTagById(last_id) + if tag != wx.EmptyString: + self.RegisterStyleCmd(tag, self._stc.GetItemByName(tag)) + + # Optimizations + stc = self._stc + GetStyleAt = stc.GetStyleAt + GetTextRange = stc.GetTextRange + TransformText = self.TransformText + + # Build LaTeX + for parse_pos in xrange(last_pos + 1): + curr_id = GetStyleAt(parse_pos) + if parse_pos > 1: + # This is the performance bottleneck, changing the text + # collection to when the style changes is much faster as + # it only needs to be done once per style section instead + # of once per character. Doing that however causes problems + # with the style and resulting document formatting. + tmp = TransformText(GetTextRange((parse_pos - 1), parse_pos)) + + if curr_id == 0 and GetStyleAt(parse_pos + 1) == last_id: + curr_id = last_id + + # If style region has changed close section + if curr_id != last_id or tmp[-1] == "\n": + tmp_tex = TransformText(GetTextRange(start, parse_pos)) +# tmp_tex = u"".join(tmp) + if tag == "operator_style" or \ + (tag == "default_style" and \ + tmp_tex.isspace() and len(tmp_tex) <= 2): + tex.append(tmp_tex) + else: + if "\\\\\n" in tmp_tex: + tmp_tex = tmp_tex.replace("\\\\\n", "") + tmp2 = "\\%s{%s}\\\\\n" + else: + tmp2 = "\\%s{%s}" + + cmd = self.CreateCmdName(tag) + if cmd in [None, wx.EmptyString]: + cmd = "defaultstyle" + tex.append(tmp2 % (cmd, tmp_tex)) + + last_id = curr_id + tag = stc.FindTagById(last_id) + if tag not in [None, wx.EmptyString]: + self.RegisterStyleCmd(tag, stc.GetItemByName(tag)) + tmp = list() + start = parse_pos + + # Case for unstyled documents + if tex == wx.EmptyString: + tex.append(self.TransformText(stc.GetText())) + return "\\begin{document}\n%s\n\\end{document}" % "".join(tex) + + def Generate(self, stc_doc): + """Generates the LaTeX document + @param stc_doc: text control to generate latex from + @return: the reference document marked up in LaTeX. + + """ + self._stc = stc_doc + default_si = self._stc.GetItemByName('default_style') + self._dstyle.SetBack(default_si.GetBack().split(',')[0]) + self._dstyle.SetFore(default_si.GetFore().split(',')[0]) + self._dstyle.SetFace(default_si.GetFace().split(',')[0]) + self._dstyle.SetSize(default_si.GetSize().split(',')[0]) + body = self.GenDoc() + preamble = self.GenPreamble() + return ("tex", u"".join([preamble, body])) + + def GenPreamble(self): + """Generates the Preamble of the document + @return: the LaTeX document preamble + + """ + # Preamble template + pre = ("%% \iffalse meta-comment\n" + "%%\n%% Generated by Editra %s\n" + "%% This is generator is Very Experimental.\n" + "%% The code should compile in most cases but there may\n" + "%% be some display issues when rendered.\n" + "%%\n%%\n\n" + "\\documentclass[11pt, a4paper]{article}\n" + "\\usepackage[a4paper, margin=2cm]{geometry}\n" + "\\usepackage[T1]{fontenc}\n" +# "\\usepackage{ucs}\n" +# "\\usepackage[utf8]{inputenc}\n" + "\\usepackage{color}\n" + "\\usepackage{alltt}\n" + "\\usepackage{times}\n") % ed_glob.VERSION + + # Set the background color + pre += ("\\pagecolor[rgb]{%s}\n" % \ + self.HexToRGB(self._dstyle.GetBack())) + pre += "\\parindent=0in\n\n" + + # Insert all styling commands + pre += "%% Begin Styling Command Definitions" + for cmd in self._cmds: + pre += ("\n" + self._cmds[cmd]) + pre += "\n%% End Styling Command Definitions\n\n" + return pre + + def GetId(self): + """Returns the menu identifier for the LaTeX generator + @return: id of that identifies this generator + + """ + return self._id + + def GetMenuEntry(self, menu): + """Returns the Menu control for the LaTeX generator + @param menu: menu to create MenuItem for + + """ + return wx.MenuItem(menu, self._id, _("Generate %s") % u"LaTeX", + _("Generate an %s version of the " \ + "current document") % u"LaTeX") + + def HexToRGB(self, hex_str): + """Returns a comma separated rgb string representation + of the input hex string. 1.0 = White, 0.0 = Black. + @param hex_str: hex string to convert to latex rgb format + + """ + r_hex = hex_str + if r_hex[0] == u"#": + r_hex = r_hex[1:] + ldiff = 6 - len(r_hex) + r_hex += ldiff * u"0" + # Convert hex values to integer + red = round(float(float(int(r_hex[0:2], 16)) / 255), 2) + green = round(float(float(int(r_hex[2:4], 16)) / 255), 2) + blue = round(float(float(int(r_hex[4:], 16)) / 255), 2) + return "%s,%s,%s" % (str(red), str(green), str(blue)) + + def RegisterStyleCmd(self, cmd_name, s_item): + """Registers and generates a command from the + supplied StyleItem. + @param cmd_name: name of command + @param s_item: style item to create command for + @postcondition: new styling command is created and registered for use + + """ + cmd_name = self.CreateCmdName(cmd_name) + + # If we already made a command for this style return + if cmd_name in self._cmds: + return + + # Templates + uline_tmp = u"\\underline{%s}" + ital_tmp = u"\\emph{%s}" + bold_tmp = u"\\textbf{%s}" + fore_tmp = u"\\textcolor[rgb]{%s}{%s}" + back_tmp = u"\\colorbox[rgb]{%s}{#1}" + cmd_tmp = u"\\newcommand{%s}[1]{%s}" + + # Get Style Attributes + fore = s_item.GetFore() + if fore == wx.EmptyString: + fore = self._dstyle.GetFore() + back = s_item.GetBack() + if back == wx.EmptyString: + back = self._dstyle.GetBack() + face = s_item.GetFace() + if face == wx.EmptyString: + face = self._dstyle.GetFace() + size = s_item.GetSize() + if size == wx.EmptyString: + size = self._dstyle.GetSize() + + back = back_tmp % self.HexToRGB(back.split(u',')[0]) + fore = fore_tmp % (self.HexToRGB(fore.split(u',')[0]), back) + if u"bold" in unicode(s_item): + fore = bold_tmp % fore + if u"underline" in unicode(s_item): + fore = uline_tmp % fore + if u"italic" in unicode(s_item): + fore = ital_tmp % fore + cmd = cmd_tmp % ((u"\\" + cmd_name), u"\\texttt{\\ttfamily{%s}}" % fore) + self._cmds[cmd_name] = cmd + + def TransformText(self, txt): + """Transforms the given text into LaTeX format, by + escaping all special characters and sequences. + @param txt: text to transform + @return: txt with all special characters transformed + + """ + ch_map = { "#" : "\\#", "$" : "\\$", "^" : "\\^", + "%" : "\\%", "&" : "\\&", "_" : "\\_", + "{" : "\\{", "}" : "\\}", "~" : "\\~", + "\\": "$\\backslash$", "\n" : "\\\\\n", + "@" : "$@$", "<" : "$<$", ">" : "$>$", + "-" : "$-$", "|" : "$|$" + } + tmp = list() + for char in txt: + tmp.append(ch_map.get(char, char)) + return u''.join(tmp) + +#-----------------------------------------------------------------------------# + +class Rtf(plugin.Plugin): + """Generates a fully styled RTF document from the given text + controls contents. + @todo: add support for bold/italic/underline and multiple fonts + + """ + plugin.Implements(GeneratorI) + def __init__(self, mgr): + """Initializes and declares the attribute values for + this generator. + @param mgr: plugin manager of this object + + """ + plugin.Plugin.__init__(self) + + # Attributes + self._stc = None + self._id = ed_glob.ID_RTF_GEN + self._colortbl = RtfColorTbl() + + def __str__(self): + """Returns the RTF object as a string + @return: rtf object as a string + + """ + return self._GenRtf() + + #---- Protected Member Functions ----# + def _GenRtf(self): + """Generates the RTF equivalent of the displayed text in the current + stc document window. + @precondition: self._stc must have been set by a call to Generate + @return: generated rtf marked up text + + """ + # Buffer hasn't been set + if self._stc is None: + return u'' + + # Optimizations + stc = self._stc + def_fore = stc.GetDefaultForeColour(as_hex=True) + self._colortbl.AddColor(def_fore) + def_back = stc.GetDefaultBackColour(as_hex=True) + self._colortbl.AddColor(def_back) + last_pos = stc.GetLineEndPosition(stc.GetLineCount()) + parse_pos = 0 + last_id = None + last_fore = None + last_back = None + start = end = 0 + tmp_txt = list() + font_tmp = "\\f0" + fore_tmp = "\\cf%d" + back_tmp = "\\cb%d" + AddColor = self._colortbl.AddColor + GetColorIndex = self._colortbl.GetColorIndex + GetStyleAt = stc.GetStyleAt + + # Parse all characters/style bytes in document + for parse_pos in xrange(last_pos + 1): + sty_id = GetStyleAt(parse_pos) + end = parse_pos + + # If style has changed build the previous section + if sty_id != last_id: + tag = stc.FindTagById(last_id) + s_item = stc.GetItemByName(tag) + AddColor(s_item.GetFore()) + AddColor(s_item.GetBack()) + tplate = font_tmp + fid = GetColorIndex(s_item.GetFore()) + if fid != last_fore: + last_fore = fid + tplate = tplate + (fore_tmp % fid) + bid = GetColorIndex(s_item.GetBack()) + if bid != last_back: + last_back = bid + tplate = tplate + (back_tmp % bid) + tmp_txt.append(tplate + " " + \ + self.TransformText(stc.GetTextRange(start, end))) + start = end + last_id = sty_id + + head = "{\\rtf1\\ansi\\deff0{\\fonttbl{\\f0 %s;}}" % \ + stc.GetDefaultFont().GetFaceName() + return u"%s%s%s}" % (head, self._colortbl, "".join(tmp_txt)) + + #---- End Protected Member Functions ----# + + def Generate(self, stc_doc): + """Implements the GeneratorI's Generator Function by + returning the RTF equivalent of the given stc_doc + @param stc_doc: document to generate text from + @return: document marked up in rtf + + """ + self._stc = stc_doc + return ('rtf', self._GenRtf()) + + def GetId(self): + """Implements the GeneratorI's GetId function by returning + the identifier for this generator. + @return: identifier for this generator + + """ + return self._id + + def GetMenuEntry(self, menu): + """Implements the GeneratorI's GetMenuEntry function by + returning the MenuItem to associate with this object. + @return: menu entry item for this generator + + """ + return wx.MenuItem(menu, self._id, _("Generate %s") % u"RTF", + _("Generate a %s version of the " \ + "current document") % u"RTF") + + def TransformText(self, text): + """Transforms the given text by converting it to RTF format + @param text: text to transform + @return: text with all special characters transformed + """ + chmap = { "\t" : "\\tab ", "{" : "\\{", "}" : "\\}", + "\\" : "\\\\", "\n" : "\\par\n", "\r" : "\\par\n"} + text = text.replace('\r\n', '\n') + tmp = u'' + for char in text: + tmp = tmp + chmap.get(char, char) + return tmp + +#-----------------------------------------------------------------------------# + +class RtfColorTbl: + """A storage class to help with generating the color table for + the Rtf Generator Class. + @see: Rtf + + """ + def __init__(self): + """Initialize the color table + @summary: creates an object for managing an rtf documents color table + + """ + # Attributes + self._index = list() # manages the order of the tables keys + self._tbl = dict() # map of style item color vals to rtf defs + + def __str__(self): + """Returns the string representation of the table + @return: rtf color table object as an rtf formatted string + + """ + rstr = u'' + for item in self._index: + rstr = rstr + self._tbl[item] + return u"{\\colortbl%s}" % rstr + + def AddColor(self, si_color): + """Takes a style item and adds it to the table if + has not already been defined in the table. + @param si_color: hex color string + + """ + if si_color not in self._index: + rgb = eclib.HexToRGB(si_color.split(u',')[0]) + color = "\\red%d\\green%d\\blue%d;" % tuple(rgb) + self._index.append(si_color) + self._tbl[si_color] = color + else: + pass + + def GetColorIndex(self, si_color): + """Gets the index of a particular style items color + definition from the color table. Returns -1 if item is + not found. + @param si_color: style item color to find index in table for + @return: the colors index in the table + + """ + if si_color in self._index: + return self._index.index(si_color) + else: + return -1 diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/iface.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/iface.py new file mode 100644 index 0000000..0e8b59a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/iface.py @@ -0,0 +1,170 @@ +############################################################################### +# Name: iface.py # +# Purpose: Plugin interface definitions # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module contains numerous plugin interfaces and the Extension points that +they extend. Included below is a list of interfaces available in this module. + +Intefaces: + - ShelfI: Interface into the L{Shelf} + - MainWindowI: Interface into L{ed_main.MainWindow} + - AutoCompI: Interface for adding autocompletion helpers + +@summary: Main Plugin interface defintions + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: iface.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Imports +import wx + +# Local Imports +import plugin + +#--------------------------------------------------------------------------# + +class AutoCompI(plugin.Interface): + """The Autocompletion interface. + + """ + def GetCompleter(self, buff): + """Get the completer object implemented by this plugin + @param buff: EditraStc instance + @return: instance of autocomp.BaseCompleter + + """ + raise NotImplementedError + + def GetFileTypeId(self): + """Get the filetype this completer is associated with + @return: int + + """ + return 0 + +#--------------------------------------------------------------------------# + +class MainWindowI(plugin.Interface): + """The MainWindow Interface is intended as a simple general purpose + interface for adding functionality to the main window. It does little + managing of how objects that implement it are handled, most is left up to + the plugin. Some examples of plugins using this interface are the + FileBrowser and Calculator plugins. + + """ + def PlugIt(self, window): + """This method is called once and only once per window when it is + created. It should typically be used to register menu entries, + bind event handlers and other similar actions. + @param window: The parent window of the plugin + @postcondition: The plugins controls are installed in the L{MainWindow} + + """ + raise NotImplementedError + + def GetMenuHandlers(self): + """Get menu event handlers/id pairs. This function should return a + list of tuples containing menu ids and their handlers. The handlers + should be not be a member of this class but a member of the ui component + that they handler acts upon. + @return: list [(ID_FOO, foo.OnFoo), (ID_BAR, bar.OnBar)] + + """ + pass + + def GetUIHandlers(self): + """Get update ui event handlers/id pairs. This function should return a + list of tuples containing object ids and their handlers. The handlers + should be not be a member of this class but a member of the ui component + that they handler acts upon. + @return: list [(ID_FOO, foo.OnFoo), (ID_BAR, bar.OnBar)] + + """ + pass + +#-----------------------------------------------------------------------------# + +class ShelfI(plugin.Interface): + """Interface into the L{Shelf}. All plugins wanting to be + placed on the L{Shelf} should implement this interface. + + """ + def AllowMultiple(self): + """This method is used to check if multiple instances of this + item are allowed to be open at one time. + @return: True/False + + """ + return True + + def CreateItem(self, parent): + """This is them method used to open the item in the L{Shelf} + It should return an object that is a Panel or subclass of a Panel. + @param parent: The would be parent window of this panel + @return: wx.Panel + + """ + raise NotImplementedError + + def GetBitmap(self): + """Get the bitmap to show in the shelf for this item + @return: wx.Bitmap + @note: this method is optional + + """ + return wx.NullBitmap + + def GetId(self): + """Return the id that identifies this item (same as the menuid) + @return: Item ID + + """ + raise NotImplementedError + + def GetMenuEntry(self, menu): + """Returns the menu entry associated with this item + @param menu: The menu this entry will be added to + @return: wx.MenuItem or None if no menu entry is needed + + """ + raise NotImplementedError + + def GetName(self): + """Return the name of this shelf item. This should be the + same as the MenuEntry's label. + @return: name of item + + """ + raise NotImplementedError + + def InstallComponents(self, mainw): + """Called by the Shelf when the plugin is created to allow it + to install any extra components that it may have that fall outside + the normal interface. This method is optional and does not need + to be implemented if it is not needed. + @param mainw: MainWindow Instance + + """ + pass + + def IsStockable(self): + """Return whether this item type is stockable. The shelf saves + what pages it had open the last time the program was run and then + reloads the pages the next time the program starts. If this + item can be reloaded between sessions return True otherwise return + False. + @return: bool + + """ + return True + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/info.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/info.py new file mode 100644 index 0000000..6b4a60d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/info.py @@ -0,0 +1,22 @@ +############################################################################### +# Name: info.py # +# Purpose: Global project information # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +"""Editra Project information module""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: info.py 73347 2013-01-05 19:58:31Z CJP $" +__revision__ = "$Revision: 73347 $" + +#-----------------------------------------------------------------------------# + +AUTHOR = 'Cody Precord' +VERSION = '0.7.20' +PROG_NAME = 'Editra' +HOME_PAGE = "http://editra.org" +I18N_PAGE = "https://translations.launchpad.net/editra/trunk/+pots/editra" +CONTACT_MAIL = "staff@editra.org" diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/perspective.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/perspective.py new file mode 100644 index 0000000..b0bc606 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/perspective.py @@ -0,0 +1,414 @@ +############################################################################### +# Name: perspectives.py # +# Purpose: Editra's view management service # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides a perspective management class for saving and loading custom +perspectives in the MainWindow. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: perspective.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#--------------------------------------------------------------------------# +# Dependencies +import os +import wx +import wx.aui as aui + +# Editra Imports +import util +import ed_menu +import ed_fmgr +from profiler import Profile_Get, Profile_Set + +#--------------------------------------------------------------------------# +# Globals +AUTO_PERSPECTIVE = u'Automatic' +DATA_FILE = u'perspectives' +LAST_KEY = u'**LASTVIEW**' + +# ID's +ID_SAVE_PERSPECTIVE = wx.NewId() +ID_DELETE_PERSPECTIVE = wx.NewId() +ID_AUTO_PERSPECTIVE = wx.NewId() + +# Aliases +_ = wx.GetTranslation +#--------------------------------------------------------------------------# + +class PerspectiveManager(object): + """Creates a perspective manager for the given aui managed window. + It supports saving and loading of on disk perspectives as created by + calling SavePerspective from the AuiManager. Mixin class for a wx.Frame. + + """ + def __init__(self, base): + """Initializes the perspective manager. The auimgr parameter is + a reference to the windows AuiManager instance, base is the base + path to where perspectives should be loaded from and saved to. + @param base: path to configuration cache + + """ + super(PerspectiveManager, self).__init__() + + hint = aui.AUI_MGR_TRANSPARENT_HINT + if wx.Platform == '__WXGTK__': + # Use venetian blinds style as transparent can cause crashes + # on linux when desktop compositing is used. + hint = aui.AUI_MGR_VENETIAN_BLINDS_HINT + + self._mgr = ed_fmgr.EdFrameManager(flags=aui.AUI_MGR_DEFAULT | + aui.AUI_MGR_TRANSPARENT_DRAG | + hint | + aui.AUI_MGR_ALLOW_ACTIVE_PANE) + self._mgr.SetManagedWindow(self) + + # Attributes + self._ids = list() # List of menu ids + self._base = os.path.join(base, DATA_FILE) # Path to config + self._viewset = dict() # Set of Views + self.LoadPerspectives() + self._menu = ed_menu.EdMenu() # Control menu + self._currview = Profile_Get('DEFAULT_VIEW') # Currently used view + + # Setup Menu + self._menu.Append(ID_SAVE_PERSPECTIVE, _("Save Current View"), + _("Save the current window layout")) + self._menu.Append(ID_DELETE_PERSPECTIVE, _("Delete Saved View")) + self._menu.AppendSeparator() + self._menu.Append(ID_AUTO_PERSPECTIVE, _("Automatic"), + _("Automatically save/use window state from last session"), + wx.ITEM_CHECK) + self._menu.AppendSeparator() + for name in self._viewset: + self.AddPerspectiveMenuEntry(name) + + # Restore the managed windows previous position preference if available. + pos = Profile_Get('WPOS', "size_tuple", False) + if Profile_Get('SET_WPOS') and pos: + # Ensure window is on screen + if not self.IsPositionOnScreen(pos): + pos = self.GetPrimaryDisplayOrigin() + self.SetPosition(pos) + + # Event Handlers + self.Bind(wx.EVT_MENU, self.OnPerspectiveMenu) + + #---- Properties ----# + PanelMgr = property(lambda self: self._mgr) + + def AddPerspective(self, name, p_data=None): + """Add a perspective to the view set. If the p_data parameter + is not set then the current view will be added with the given name. + @param name: name for new perspective + @keyword p_data: perspective data from auimgr + @return: bool (True == Added, False == Not Added) + + """ + # Don't allow empty keys or ones that override the automatic + # settings to be added + name = name.strip() + if not len(name) or name == AUTO_PERSPECTIVE: + return False + + domenu = not self.HasPerspective(name) + if p_data is None: + self._viewset[name] = self._mgr.SavePerspective() + else: + self._viewset[name] = p_data + self._currview = name + + if name != AUTO_PERSPECTIVE and domenu: + self.AddPerspectiveMenuEntry(name) + + self.SavePerspectives() + return True + + def AddPerspectiveMenuEntry(self, name): + """Adds an entry to list of perspectives in the menu for this manager. + @param name: name of perspective to add to menu + @return: bool (added or not) + + """ + name = name.strip() + if not len(name) or name == AUTO_PERSPECTIVE: + return False + + per_id = wx.NewId() + self._ids.append(per_id) + self._menu.InsertAlpha(per_id, name, _("Change view to \"%s\"") % name, + kind=wx.ITEM_CHECK, after=ID_AUTO_PERSPECTIVE) + return True + + def GetFrameManager(self): + """Returns the manager for this frame + @return: Reference to the AuiMgr of this window + + """ + return self._mgr + + def GetPerspectiveControls(self): + """Returns the control menu for the manager + @return: menu of this manager + + """ + return self._menu + + def GetPerspective(self): + """Returns the name of the current perspective used + @return: name of currently active perspective + + """ + return self._currview + + def GetPerspectiveData(self, name): + """Returns the given named perspectives data string + @param name: name of perspective to fetch data from + + """ + return self._viewset.get(name, None) + + def GetPersectiveHandlers(self): + """Gets a list of ID to UIHandlers for the perspective Menu + @return: list of [(ID, HandlerFunction)] + + """ + handlers = [(m_id, self.OnUpdatePerspectiveMenu) for m_id in self._ids] + return handlers + [(ID_AUTO_PERSPECTIVE, self.OnUpdatePerspectiveMenu)] + + def GetPerspectiveList(self): + """Returns a list of all the loaded perspectives. The + returned list only provides the names of the perspectives + and not the actual data. + @return: list of all managed perspectives + + """ + return sorted(self._viewset.keys()) + + def GetPrimaryDisplayOrigin(self): + """Get the origin on the primary display to use as a default + window placement position. + @return: position tuple + + """ + # NOTE: don't default to 0,0 otherwise on osx the frame will be + # stuck behind the menubar. + for idx in range(wx.Display.GetCount()): + disp = wx.Display(idx) + if disp.IsPrimary(): + drect = disp.GetClientArea() + return drect.GetPosition() + (5, 5) + else: + return (5, 5) + + def HasPerspective(self, name): + """Returns True if there is a perspective by the given name + being managed by this manager, or False otherwise. + @param name: name of perspective to look for + @return: whether perspective is managed by this manager or not + + """ + return name in self._viewset + + def InitWindowAlpha(self): + """Initialize the windows alpha setting""" + level = max(100, Profile_Get('ALPHA', default=255)) + # Only set the transparency if it is not opaque + if level != 255: + self.SetTransparent(level) + + def IsPositionOnScreen(self, pos): + """Check if the given position is on any of the connected displays + @param pos: Position Tuple + @return: bool + + """ + bOnScreen = False + if len(pos) == 2: + for idx in range(wx.Display.GetCount()): + disp = wx.Display(idx) + drect = disp.GetClientArea() + bOnScreen = drect.Contains(pos) + if bOnScreen: + break + return bOnScreen + + def LoadPerspectives(self): + """Loads the perspectives data into the manager. Returns + the number of perspectives that were successfully loaded. + @return: number of perspectives loaded + + """ + reader = util.GetFileReader(self._base) + if reader == -1: + util.Log("[perspective][err] Failed to get " + + "file reader for %s" % self._base) + return 0 + + try: + for line in reader.readlines(): + label, val = line.split(u"=", 1) + label = label.strip() + if not len(label): + continue + self._viewset[label] = val.strip() + reader.close() + finally: + if LAST_KEY in self._viewset: + self._currview = self._viewset[LAST_KEY] + del self._viewset[LAST_KEY] + return len(self._viewset) + + def OnPerspectiveMenu(self, evt): + """Handles menu events generated by the managers control menu. + @param evt: event that called this handler + + """ + e_id = evt.GetId() + if e_id == ID_SAVE_PERSPECTIVE: + name = wx.GetTextFromUser(_("Perspective Name"), \ + _("Save Perspective")) + if name: + self.AddPerspective(name, p_data=None) + self.SavePerspectives() + Profile_Set('DEFAULT_VIEW', name) + + # It may make sense to update all windows to use this + # perspective at this point but it may be an unexpected + # event to happen when there is many windows open. Will + # leave this to future consideration. + for mainw in wx.GetApp().GetMainWindows(): + mainw.AddPerspective(name, self._viewset[name]) + + elif e_id == ID_DELETE_PERSPECTIVE: + views = [ view for view in self._viewset.keys() + if view != AUTO_PERSPECTIVE ] + name = wx.GetSingleChoice(_("Perspective to Delete"), + _("Delete Perspective"), views) + + if name: + self.RemovePerspective(name) + self.SavePerspectives() + for mainw in wx.GetApp().GetMainWindows(): + mainw.RemovePerspective(name) + else: + pass + + # Update all windows data sets + for mainw in wx.GetApp().GetMainWindows(): + mainw.LoadPerspectives() + + elif e_id in self._ids + [ID_AUTO_PERSPECTIVE]: + if e_id == ID_AUTO_PERSPECTIVE: + Profile_Set('DEFAULT_VIEW', AUTO_PERSPECTIVE) + self.SetAutoPerspective() + else: + self.SetPerspectiveById(e_id) + else: + evt.Skip() + + def OnUpdatePerspectiveMenu(self, evt): + """Update the perspective menu's check mark states + @param evt: UpdateUI event that called this handler + + """ + e_id = evt.GetId() + if e_id in self._ids + [ID_AUTO_PERSPECTIVE]: + evt.Check(self._menu.GetLabel(e_id) == self._currview) + else: + evt.Skip() + + def RemovePerspective(self, name): + """Removes a named perspective from the managed set + @param name: name of perspective to remove/delete + + """ + if name in self._viewset: + del self._viewset[name] + rem_id = self._menu.RemoveItemByName(name) + if rem_id: + self._ids.remove(rem_id) + + def SetAutoPerspective(self): + """Set the current perspective management into automatic mode + @postcondition: window is set into + + """ + self._currview = AUTO_PERSPECTIVE + self.UpdateAutoPerspective() + + def SavePerspectives(self): + """Writes the perspectives out to disk. Returns True if all data was + written and False if there was an error. + @return: whether save was successful + + """ + writer = util.GetFileWriter(self._base) + if writer == -1: + util.Log("[perspective][err] Failed to save %s" % self._base) + return False + + try: + self._viewset[LAST_KEY] = self._currview + for perspect in self._viewset: + writer.write(u"%s=%s\n" % (perspect, self._viewset[perspect])) + del self._viewset[LAST_KEY] + except (IOError, OSError): + util.Log("[perspective][err] Write error: %s" % self._base) + return False + else: + return True + + def SetPerspective(self, name): + """Sets the perspective of the managed window, returns + True on success and False on failure. + @param name: name of perspective to set + @return: whether perspective was set or not + + """ + if name in self._viewset: + self._mgr.LoadPerspective(self._viewset[name]) + self._mgr.Update() + + self._currview = name + self.SavePerspectives() + return True + else: + # Fall back to automatic mode + self.SetAutoPerspective() + return False + + def SetPerspectiveById(self, per_id): + """Sets the perspective using the given control id + @param per_id: id of requested perspective + @return: whether perspective was set or not + + """ + name = None + for pos in range(self._menu.GetMenuItemCount()): + item = self._menu.FindItemByPosition(pos) + if per_id == item.GetId(): + name = item.GetLabel() + break + + if name is not None: + return self.SetPerspective(name) + else: + return False + + def UpdateAutoPerspective(self): + """Update the value of the auto-perspectives current saved state + @postcondition: The perspective data for the Automatic setting is + updated to have data for the current state of the + window. + + """ + self._viewset[AUTO_PERSPECTIVE] = self._mgr.SavePerspective() + self.SavePerspectives() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugdlg.py new file mode 100644 index 0000000..f4a6888 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugdlg.py @@ -0,0 +1,1206 @@ +############################################################################### +# Name: plugdlg.py # +# Purpose: User interface into the PluginManager, also provides interface for # +# downloading and installing plugins. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides a dialog for downloading, installing and configuring plugins or Editra. + +@todo: refactor list population and list item creation + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__cvsid__ = "$Id: plugdlg.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#-----------------------------------------------------------------------------# +# Imports +import os +import sys +import re +import urllib2 +import wx +import wx.lib.delayedresult as delayedresult + +# Local Imports +import ed_glob +import plugin +import ed_event +import ed_msg +import util +import ed_txt +from profiler import Profile_Get, Profile_Set +import ed_basewin +import eclib + +#-----------------------------------------------------------------------------# +# Globals + +CONFIG_PG = 0 +DOWNLOAD_PG = 1 +INSTALL_PG = 2 +PY_VER = str(sys.version_info[0]) + str(sys.version_info[1]) +PLUGIN_REPO = "http://editra.org/plugins.php?list=True&py=" + PY_VER + +# Panel Display Modes +MODE_CONFIG = 0 +MODE_ERROR = 1 + +# Image list indexes +IMG_CONFIG = 0 +IMG_DOWNLOAD = 1 +IMG_INSTALL = 2 +IMG_ERROR = 3 +IMG_PLUGIN = 4 + +_ = wx.GetTranslation + +#-----------------------------------------------------------------------------# + +def MakeThemeTool(tool_id): + """Makes a themed bitmap for the tool book of the plugin dialog. + @param tool_id: An art identifier id + @return: 32x32 bitmap + @todo: why does drawing a bitmap overlay on gtk not draw on transparent area + + """ + osize = Profile_Get('ICON_SZ', default=(24, 24)) + Profile_Set('ICON_SZ', (32, 32)) + base = wx.ArtProvider.GetBitmap(str(tool_id), wx.ART_TOOLBAR) + Profile_Set('ICON_SZ', osize) + if not base.IsOk(): + base = wx.ArtProvider.GetBitmap(wx.ART_WARNING, + wx.ART_TOOLBAR, + size=(32, 32)) + + over = wx.ArtProvider.GetBitmap(str(ed_glob.ID_PLUGMGR), wx.ART_MENU) + if over.IsOk(): + # Draw overlay onto button + mdc = wx.MemoryDC() + mdc.SelectObject(base) + mdc.SetBrush(wx.TRANSPARENT_BRUSH) + mdc.SetPen(wx.TRANSPARENT_PEN) + mdc.DrawBitmap(over, 15, 15, False) + mdc.SelectObject(wx.NullBitmap) + + return base + +#-----------------------------------------------------------------------------# + +class PluginDialog(wx.Frame): + """Defines a Plugin manager Dialog that can be used to download plugins + from a defined repository, offers services to install plugins that + where downloaded with or without the dialog, as well as configure + already installed plugins. It is instanciated as a standalone window + when the show method is called so that if downloads are taking along time + it does not interfere with usage of the editor. + + """ + def __init__(self, parent, id=wx.ID_ANY, title=u'', size=wx.DefaultSize): + super(PluginDialog, self).__init__(parent, title=title, size=size, + style=wx.DEFAULT_FRAME_STYLE) + util.SetWindowIcon(self) + + # Attributes + bstyle = eclib.SEGBOOK_STYLE_NO_DIVIDERS|eclib.SEGBOOK_STYLE_LABELS + self._nb = eclib.SegmentBook(self, style=bstyle) + self._cfg_pg = ConfigPanel(self._nb, style=wx.BORDER_SUNKEN) + self._dl_pg = DownloadPanel(self._nb) + self._inst_pg = InstallPanel(self._nb) + self._imglst = list() + + # Setup + self.__InitImageList() + + self._nb.AddPage(self._cfg_pg, _("Configure"), img_id=IMG_CONFIG) + self._nb.AddPage(self._dl_pg, _("Download"), img_id=IMG_DOWNLOAD) + self._nb.AddPage(self._inst_pg, _("Install"), img_id=IMG_INSTALL) + + # Check for plugins with error conditions and if any are found + # Add the error page. + pmgr = wx.GetApp().GetPluginManager() + if len(pmgr.GetIncompatible()): + self._nb.AddPage(ConfigPanel(self._nb, style=wx.NO_BORDER, + mode=MODE_ERROR), + _("Errors"), img_id=IMG_ERROR) + + # Layout + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self._nb, 1, wx.EXPAND) + self.SetSizer(sizer) + self.SetStatusBar(eclib.ProgressStatusBar(self, style=wx.SB_FLAT)) + self.SetInitialSize(size) + + # Event Handlers + self.Bind(eclib.EVT_SB_PAGE_CHANGING, self.OnPageChanging) + self.Bind(wx.EVT_CLOSE, self.OnClose) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + + # Message Handlers + ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED) + + def OnDestroy(self, evt): + """Cleanup message handlers on delete""" + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.OnThemeChange) + evt.Skip() + + def __InitImageList(self): + """Initialize the segmentbooks image list""" + dorefresh = False + if len(self._imglst): + del self._imglst + self._imglst = list() + dorefresh = True + + self._imglst.append(MakeThemeTool(ed_glob.ID_PREF)) + self._imglst.append(MakeThemeTool(ed_glob.ID_WEB)) + self._imglst.append(MakeThemeTool(ed_glob.ID_PACKAGE)) + bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR, (32, 32)) + self._imglst.append(bmp) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_PREF), + wx.ART_TOOLBAR, (32, 32)) + self._imglst.append(bmp) + self._nb.SetImageList(self._imglst) + self._nb.SetUsePyImageList(True) + + if dorefresh: + self._nb.Refresh() + + def OnClose(self, evt): + """Handles closing the dialog and unregistering it from the mainloop. + @param evt: wx.EVT_CLOSE + + """ + if self._dl_pg.IsDownloading(): + dlg = wx.MessageDialog(self, _("Downloads are incomplete"), + _("Do you wish to exit?"), + style=wx.YES_NO|wx.ICON_EXCLAMATION| \ + wx.CENTER) + result = dlg.ShowModal() + dlg.Destroy() + if result == wx.ID_NO: + return + else: + pass + + if self._cfg_pg.ConfigChanged(): + wx.MessageBox(_("You must restart Editra before your " + "changes will take full affect."), + _("Configuration Changes Made"), + wx.ICON_INFORMATION|wx.OK) + + + wx.GetApp().UnRegisterWindow(repr(self)) + evt.Skip() + + def OnThemeChange(self, msg): + """Update icons on theme change message""" + self.__InitImageList() + + def Show(self, show=True): + """Shows the dialog + @postcondition: Dialog is registered with the main loop and shown + + """ + wx.GetApp().RegisterWindow(repr(self), self, True) + wx.Frame.Show(self, show) + + def Busy(self, busy=True): + """Set the status of the frame to be busy or not + @keyword busy: Start or Stop being busy + + """ + if busy: + self.GetStatusBar().StartBusy() + else: + self.GetStatusBar().StopBusy() + + def OnPageChanging(self, evt): + """Updates pages as they are being changed to. + @param evt: segmentbk.EVT_SB_PAGE_CHANGING + + """ + cur_pg = evt.GetSelection() + self.SetTitle(self.GetTitle().split(" | ")[0] + \ + " | " + self._nb.GetPageText(cur_pg)) + if cur_pg == CONFIG_PG: + self._cfg_pg.PopulateCtrl() + self.SetStatusText(_("Changes will take affect once the" + " program has been restarted"), 0) + elif cur_pg == DOWNLOAD_PG: + self._dl_pg.UpdateList() + elif cur_pg == INSTALL_PG: + pass + else: + page = self._nb.GetPage(cur_pg) + size = page.GetBestSize() + s2 = self.GetSize() + segbar = self._nb.GetSegmentBar() + segsize = segbar.GetBestSize() + self.SetClientSize((s2.GetWidth(), + size.GetHeight() + segsize.GetHeight())) + self.SetStatusText("", 0) + + evt.Skip() + +#-----------------------------------------------------------------------------# + +class ConfigPanel(eclib.ControlBox): + """Creates a panel for configuring plugins.""" + def __init__(self, parent, style=wx.NO_BORDER, mode=MODE_CONFIG): + """Build config panel""" + eclib.ControlBox.__init__(self, parent, style=style) + + # Attrtibutes + self._mode = mode + self._changed = False + self._list = eclib.PanelBox(self) + + # Layout Panel + self.SetWindow(self._list) + + if self._mode == MODE_CONFIG: + self.PopulateCtrl() + else: + self.PopulateErrors() + + # Event Handlers + self.Bind(ed_event.EVT_NOTIFY, self.OnNotify) + + def ConfigChanged(self): + """Did the configuration change? + @return: bool + + """ + return self._changed + + def GetItemIdentifier(self, name): + """Gets the named item and returns its identifier. The + identifier is the combination of the name and version + strings. + @param name: name of item in list + @return: identifier for the named list item + + """ + identifer = None + for item in self._list.GetItems(): + if item.GetPluginName().lower() == name.lower(): + identifer = (name, item.GetVersionString()) + return identifer + + def OnNotify(self, evt): + """Handles the notification events that are + posted from the list control. + @param evt: ed_event.NotificationEvent + + """ + e_id = evt.GetId() + if e_id == ed_glob.ID_PREF: + # TODO: check for an open existing instance of this config objects + # page. + cfg_obj = evt.GetValue() + parent = self.GetParent() # SegmentBook + + bmp = cfg_obj.GetBitmap() + if bmp.IsNull(): + idx = IMG_PLUGIN + else: + imglst = parent.GetImageList() + imglst.append(bmp) + idx = len(imglst) - 1 + + label = cfg_obj.GetLabel() + panel = cfg_obj.GetConfigPanel(parent) + parent.AddPage(panel, label, True, idx) + parent.SetSegmentCanClose(parent.GetPageCount() - 1, True) + else: + pname, enabled = evt.GetValue() + pmgr = wx.GetApp().GetPluginManager() + pmgr.EnablePlugin(pname, enabled) + self._changed = True + + def PopulateCtrl(self): + """Populates the list of plugins and sets the + values of their states. Any successive calls to + this function will clear the list and Repopulate it + with current config values. Returns the number of + items populated to the list + @postcondition: list is populated with all plugins that are + currently loaded and sets the checkmarks accordingly + @return: number of items added to list + + """ + p_mgr = wx.GetApp().GetPluginManager() + if self._list.GetItemCount(): + self._list.DeleteAllItems() + + p_mgr.ReInit() + config = p_mgr.GetConfig() + keys = sorted([ ed_txt.DecodeString(name) + for name in config.keys() ], + key=unicode.lower) + uninstalled = Profile_Get('UNINSTALL_PLUGINS', default=list()) + + with eclib.Freezer(self._list) as _tmp: + for item in keys: + val = config[item] + mod = sys.modules.get(item) + dist = p_mgr.GetPluginDistro(item) + if dist is not None: + item = dist.project_name + version = dist.version + else: + version = str(getattr(mod, '__version__', _("Unknown"))) + + pdata = PluginData() + pdata.SetName(item) + desc = getattr(mod, '__doc__', None) + if not isinstance(desc, basestring): + desc = _("No Description Available") + pdata.SetDescription(desc.strip()) + pdata.SetAuthor(getattr(mod, '__author__', _("Unknown"))) + pdata.SetVersion(version) + pdata.SetDist(dist) + pbi = PBPluginItem(self._list, mod, pdata, None) + + pbi.SetChecked(val) + util.Log("[pluginmgr][info] Adding %s to list" % item) + self._list.AppendItem(pbi) + if pbi.GetInstallPath() in uninstalled: + pbi.Enable(False) + + self._list.SendSizeEvent() + return self._list.GetItemCount() + + def PopulateErrors(self): + """Populates the list of plugins and sets the + values of their states. Any successive calls to + this function will clear the list and Repopulate it + with current config values. Returns the number of + items populated to the list + @postcondition: list is populated with all plugins that are + currently loaded and sets the checkmarks accordingly + @return: number of items added to list + + """ + p_mgr = wx.GetApp().GetPluginManager() + if self._list.GetItemCount(): + self._list.DeleteAllItems() + + p_mgr.ReInit() + errors = p_mgr.GetIncompatible() + keys = sorted([ ed_txt.DecodeString(name) + for name in errors.keys() ], + key=unicode.lower) + bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR, (32, 32)) + msg = _("This plugin requires a newer version of Editra.") + + with eclib.Freezer(self._list) as _tmp: + for item in keys: + val = errors[item] + mod = sys.modules.get(val) + dist = p_mgr.GetPluginDistro(item) + if dist is not None: + item = dist.project_name + version = dist.version + else: + version = unicode(getattr(mod, '__version__', _("Unknown"))) + + pin = PluginData() + pin.SetName(item) + pin.SetAuthor(getattr(mod, '__author__', _("Unknown"))) + pin.SetVersion(version) + pin.SetDist(dist) + pbi = PluginErrorItem(self._list, pin, msg, bmp=bmp) + + self._list.AppendItem(pbi) + + self._list.SendSizeEvent() + return self._list.GetItemCount() + +#-----------------------------------------------------------------------------# + +class DownloadPanel(ed_basewin.EdBaseCtrlBox): + """Creates a panel with controls for downloading plugins.""" + ID_DOWNLOAD = wx.NewId() + EGG_PATTERN = re.compile(r"(?P<name>[^-]+)" + r"( -(?P<ver>[^-]+) (-py(?P<pyver>[^-]+) (-(?P<plat>.+))? )? )?", + re.VERBOSE | re.IGNORECASE + ).match + + def __init__(self, parent): + """Initializes the panel""" + super(DownloadPanel, self).__init__(parent) + + # Attributes + self._p_list = dict() # list of available plugins/meta + self._dl_list = dict() # List of download urls + self._eggcount = 0 # Number of plugins to download + self._eggbasket = dict() # Basket of downloaded eggs + self._list = eclib.PanelBox(self) + + # Layout Panel + cbar = self.CreateControlBar(wx.BOTTOM) + cbar.AddStretchSpacer() + self._downlb = wx.Button(cbar, DownloadPanel.ID_DOWNLOAD, _("Download")) + self._downlb.Disable() + cbar.AddControl(self._downlb, wx.ALIGN_RIGHT) + self.SetWindow(self._list) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(ed_event.EVT_NOTIFY, self.OnNotify) + + def _ResultCatcher(self, delayedResult): + """Catches the results from the download worker threads""" + # Check if result has come after the window is dead + try: + frame = self.GetGrandParent() + except wx.PyDeadObjectError: + return + + self._eggcount = self._eggcount - 1 + try: + result = delayedResult.get() + plug = result[0] + if result[1]: + self._eggbasket[plug] = result[2] + frame.SetStatusText(_("Downloaded") + ": " + plug, 0) + finally: + if not self._eggcount: + frame.SetStatusText(_("Finshed downloading plugins"), 0) + wx.CallAfter(frame.Busy, False) + inst_pg = self.GetParent().GetPage(INSTALL_PG) + for key in self._eggbasket: + inst_pg.AddItemToInstall(key) + self.GetParent().SetSelection(INSTALL_PG) + + def _UpdateCatcher(self, delayedResult): + """Catches the results from the download worker threads""" + try: + frame = self.GetGrandParent() + result = delayedResult.get() + if len(result): + self._p_list = self.FormatPluginList(result) + self.PopulateList() + frame.SetStatusText(_("Select plugins to download"), 0) + except wx.PyDeadObjectError: + return + except Exception, msg: + util.Log("[plugdlg][err] Download failed " + str(msg)) + frame.SetStatusText(_("Unable to retrieve plugin list"), 0) + wx.CallAfter(frame.Busy, False) + + def FormatPluginList(self, data): + """Formats a list of plugin data served by the server into + PluginData objects for usage in the list view. + @return: PluginData of all available plugins + + """ + plugins = data + p_list = dict() + if len(plugins) < 2: + return p_list + + for meta in plugins: + data = meta.split("\n") + + if len(data) < 4: + continue + + tmpdat = PluginData() + set_map = {'author' : tmpdat.SetAuthor, + 'version' : tmpdat.SetVersion, + 'name' : tmpdat.SetName, + 'description' : tmpdat.SetDescription, + 'url' : tmpdat.SetUrl} + + for attr in data: + tmp = attr.split("=") + if len(tmp) != 2: + continue + + funct = set_map.get(tmp[0].lower(), None) + if funct: + funct(ed_txt.DecodeString(tmp[1].strip())) + + if tmpdat.GetName() != u'': + p_list[ed_txt.DecodeString(tmpdat.GetName())] = tmpdat + + # Remove items that have already been installed + config_pg = self.GetParent().GetPage(CONFIG_PG) + to_clean = list() + for pin in p_list: + cfg_id = config_pg.GetItemIdentifier(pin.lower()) + if cfg_id is not None: + try: + cur_id = [int(v) for v in cfg_id[1].split(".")] + dl_id = [int(v) for v in p_list[pin].GetVersion().split(".")] + except: + continue + if cur_id >= dl_id: # Installed version is >= avail dl + to_clean.append(pin) + + for item in to_clean: + del p_list[item] + + return p_list + + def GetDownloadedData(self): + """Returns the dictionary of downloaded data or an + empty dictionary if no data has been downloaded. + @return: set of all successfully downloaded plugins + + """ + return self._eggbasket + + def IsDownloading(self): + """Returns whether the panel has active download + threads or not. + @return: bool + + """ + if self._eggcount: + return True + else: + return False + + def OnButton(self, evt): + """Handles the Button Events. + @param evt: wx.EVT_BUTTON + + """ + e_id = evt.GetId() + if e_id == self.ID_DOWNLOAD: + urls = list() + for item in self._dl_list: + if self._dl_list[item] and item in self._p_list: + urls.append(self._p_list[item].GetUrl()) + self._eggcount = len(urls) + + # Start a separate thread to download each selection + for egg in range(len(urls)): + self.GetGrandParent().SetStatusText(_("Downloading") + "...", 0) + self.GetGrandParent().Busy(True) + delayedresult.startWorker(self._ResultCatcher, _DownloadPlugin, + wargs=(urls[egg]), jobID=egg) + else: + evt.Skip() + + def OnNotify(self, evt): + """Handles the notification events that are posted by the + list control when items are checked. + @param evt: ed_event.NotificationEvent + + """ + pin, enable = evt.GetValue() + self._dl_list[pin] = enable + + if enable: + self._downlb.Enable() + else: + for item in self._dl_list: + if self._dl_list[item]: + self._downlb.Enable() + break + else: + self._downlb.Disable() + + if pin in self._dl_list: + del self._dl_list[pin] + + def PopulateList(self): + """Populates the list control based off data in the plugin data + list. The plugin data list is set as a result of calling UpdateList + it is not recommended to call this directly. + + @return: number of items added to control + + """ + if self._list.GetItemCount(): + self._list.DeleteAllItems() + pins = sorted([ name for name in self._p_list.keys() ], key=unicode.lower) + with eclib.Freezer(self) as _tmp: + for item in pins: + pbi = PBDownloadItem(self._list, self._p_list[item], None) + self._list.AppendItem(pbi) + self._list.SendSizeEvent() + return self._list.GetItemCount() + + def RemoveDownloadedItem(self, item): + """Remove an item from the download cache + @param item: Name of item to remove + + """ + # Removed downloaded data + if item in self._eggbasket: + del self._eggbasket[item] + + # Remove download entry data + match = self.EGG_PATTERN(item) + if match: + plugin_name = match.group('name').lower() + if plugin_name in self._dl_list: + del self._dl_list[plugin_name] + + def UpdateList(self, url=PLUGIN_REPO): + """Update the list of available downloads + @param url: url to fetch update list from + @postcondition: Worker thread is started that will update list when it + finishes. + + """ + if self._list.GetItemCount(): + self._list.DeleteAllItems() + frame = self.GetGrandParent() + frame.SetStatusText(_("Retrieving Plugin List") + "...", 0) + frame.Busy(True) + delayedresult.startWorker(self._UpdateCatcher, _GetPluginListData, + wkwargs={'url' : url}, jobID='update') + +#-----------------------------------------------------------------------------# +# Download utility functions + +# The obtained meta data must be served as a file that is formatted +# as follows. Each meta data item must be on a single line with +# each set of meta data for different plugins separated by three +# hash marks '###'. +def _GetPluginListData(url=PLUGIN_REPO): + """Gets the list of plugins and their related meta data + as a string and returns it. + @return: list of data of available plugins from website + + """ + text = u'' + try: + try: + if Profile_Get('USE_PROXY', default=False): + proxy_set = Profile_Get('PROXY_SETTINGS', + default=dict(uname='', url='', + port='80', passwd='')) + proxy = util.GetProxyOpener(proxy_set) + h_file = proxy.open(url) + else: + h_file = urllib2.urlopen(url) + + text = h_file.read() + h_file.close() + except (IOError, OSError), msg: + util.Log("[plugdlg][err] %s" % str(msg)) + finally: + return text.split("###") + +def _DownloadPlugin(*args): + """Downloads the plugin at the given url. + @note: *args is really a string that has been exploded + @return: name, completed, egg data + @rtype: tuple + + """ + url = "".join(args) + egg = None + try: + try: + if Profile_Get('USE_PROXY', default=False): + proxy_set = Profile_Get('PROXY_SETTINGS', + default=dict(uname='', url='', + port='80', passwd='')) + proxy = util.GetProxyOpener(proxy_set) + h_file = proxy.open(url) + else: + h_file = urllib2.urlopen(url) + + egg = h_file.read() + h_file.close() + except (IOError, OSError), msg: + util.Log("[plugdlg][err] %s" % str(msg)) + finally: + return (url.split("/")[-1], True, egg) + +#-----------------------------------------------------------------------------# + +class InstallPanel(ed_basewin.EdBaseCtrlBox): + """Creates a panel for installing plugins.""" + ID_INSTALL = wx.NewId() + ID_USER = wx.NewId() + ID_SYS = wx.NewId() + ID_REMOVE_ITEM = wx.NewId() + + def __init__(self, parent): + """Initializes the panel""" + super(InstallPanel, self).__init__(parent) + + # Attributes + bbar = self.CreateControlBar(wx.BOTTOM) + toolt = wx.ToolTip(_("To add a new item drag and drop the plugin file " + "into the list.\n\nTo remove an item select it " + "and hit Delete or Backspace.")) + self._install = wx.ListBox(self, wx.ID_ANY, + style=wx.LB_SORT|wx.BORDER_NONE) + self._install.SetToolTip(toolt) + self._install.SetDropTarget(util.DropTargetFT(self._install, + None, self.OnDrop)) + + self._instb = wx.Button(bbar, self.ID_INSTALL, _("Install")) + self._instb.Disable() + self._usercb = wx.CheckBox(bbar, self.ID_USER, _("User Directory")) + self._usercb.SetValue(True) + toolt = wx.ToolTip(_("Install the plugins only for the current user")) + self._usercb.SetToolTip(toolt) + self._syscb = wx.CheckBox(bbar, self.ID_SYS, _("System Directory")) + toolt = wx.ToolTip(_("Install the plugins for all users\n" + " **requires administrative privileges**")) + self._syscb.SetToolTip(toolt) + if not os.access(ed_glob.CONFIG['SYS_PLUGIN_DIR'], os.R_OK | os.W_OK): + self._syscb.Disable() + + # Layout Panel + self.SetWindow(self._install) + bbar.AddControl(self._usercb) + bbar.AddControl(self._syscb) + bbar.AddStretchSpacer() + bbar.AddControl(self._instb, wx.ALIGN_RIGHT) + self.SendSizeEvent() + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_CHECKBOX, self.OnCheckBox) + self._install.Bind(wx.EVT_KEY_UP, self.OnKeyUp) + + def _Install(self): + """Install the plugins in the list. + @postcondition: all plugins listed in the list are installed and loaded + + """ + items = self._install.GetItems() + inst_loc = ed_glob.CONFIG['PLUGIN_DIR'] + if self._syscb.GetValue(): + inst_loc = ed_glob.CONFIG['SYS_PLUGIN_DIR'] + + for item in items: + egg_name = item.split(os.sep)[-1] + if os.path.isabs(item): + try: + reader = file(item, "rb") + egg = reader.read() + reader.close() + except (IOError, SystemError, OSError): + continue + else: + dl_pg = self.GetParent().GetPage(DOWNLOAD_PG) + egg = dl_pg.GetDownloadedData().get(item, None) + if not egg: + continue + + try: + writer = file(inst_loc + egg_name, "wb") + writer.write(egg) + writer.close() + except (IOError, OSError): + continue + else: + # If successfully installed remove from list + ind = self._install.FindString(item) + dl_pg = self.GetParent().GetPage(DOWNLOAD_PG) + if ind != wx.NOT_FOUND: + self._install.Delete(ind) + dl_pg.RemoveDownloadedItem(item) + + if not len(self._install.GetItems()): + # All plugins installed correctly + grand_p = self.GetTopLevelParent() + grand_p.SetStatusText(_("Successfully Installed Plugins"), 0) + # Note: need to do this because SetSelection doesn't fire a + # page change. + wx.GetApp().GetPluginManager().ReInit() + self.GetParent().SetSelection(CONFIG_PG) + self._instb.Disable() + else: + self.GetGrandParent().SetStatusText(_("Error"), 1) + dlg = wx.MessageDialog(self, + _("Failed to install %d plugins") % \ + self._install.GetCount(), + _("Installation Error"), + style = wx.OK | wx.CENTER | wx.ICON_ERROR) + dlg.ShowModal() + dlg.Destroy() + + def AddItemToInstall(self, item): + """Adds an item to the install list, the item + should be a string of the path to the item or + the items name if it is an in memory file from the + download page. + @param item: path or name of plugin item + + """ + if self._install.FindString(item) == wx.NOT_FOUND: + self._instb.Enable() + self._install.Append(item) + else: + pass + + def OnButton(self, evt): + """Handles button events generated by the panel. + @param evt: wx.EVT_BUTTON + + """ + if evt.GetId() == self.ID_INSTALL: + self._Install() + else: + evt.Skip() + + def OnCheckBox(self, evt): + """Handles the checkbox events to make sure that + only one of the two check boxes is checked at a time + @param evt: wx.EVT_CHECKBOX + + """ + e_id = evt.GetId() + val = evt.GetEventObject().GetValue() + u_cb = self.FindWindowById(self.ID_USER) + s_cb = self.FindWindowById(self.ID_SYS) + if e_id == self.ID_USER: + if not s_cb.IsEnabled(): + u_cb.SetValue(True) + else: + s_cb.SetValue(not val) + elif e_id == self.ID_SYS: + u_cb.SetValue(not val) + else: + pass + evt.Skip() + + def OnDrop(self, files): + """Get Drop files and place paths in control + @todo: should also check entry points in addition to filetype + @param files: list of file paths + @postcondition: all non egg files are filtered only placing + the eggs in the list. + """ + # Filter out any files that are not eggs + good = [ fname for fname in files if fname.split(u'.')[-1] == u'egg' ] + for item in good: + if self._install.FindString(item) == wx.NOT_FOUND: + self._install.Append(item) + + if self._install.GetCount(): + self._instb.Enable() + + def OnKeyUp(self, evt): + """Key Event handler. Removes the selected item from + the list control when the delete or backspace kis is pressed. + @param evt: wx.KeyEvent(wx.EVT_KEY_UP) + + """ + if evt.GetKeyCode() in [wx.WXK_DELETE, wx.WXK_BACK]: + item = self._install.GetSelection() + if item != wx.NOT_FOUND: + self._install.Delete(item) + + if not self._install.GetCount(): + self._instb.Disable() + + evt.Skip() + +#-----------------------------------------------------------------------------# + +class PBPluginItem(eclib.PanelBoxItemBase): + """PanelBox Item to display configuration information about a plugin.""" + def __init__(self, parent, mod, pdata, bmp=None, enabled=False): + """Create the PanelBoxItem + @param parent: L{PanelBox} + @param mod: module + @param pdata: PluginData + @keyword bmp: Plugin Icon + @keyword enabled: Plugin is currently enabled (bool) + + """ + super(PBPluginItem, self).__init__(parent) + + # Attributes + self._module = mod + self._pdata = pdata + self._bmp = bmp + self._title = wx.StaticText(self, label=self._pdata.GetName()) + self._version = wx.StaticText(self, label=self._pdata.GetVersion()) + self._desc = wx.StaticText(self, label=self._pdata.GetDescription()) + self._auth = wx.StaticText(self, label=_("Author: %s") % self._pdata.GetAuthor()) + self._enabled = wx.CheckBox(self, label=_("Enable")) + self._enabled.SetValue(enabled) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_DELETE), wx.ART_MENU) + self._uninstall = eclib.PlateButton(self, label=_("Uninstall"), bmp=bmp, + style=eclib.PB_STYLE_NOBG) + self._uninstall.Unbind(wx.EVT_ERASE_BACKGROUND) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_PREF), wx.ART_MENU) + self._config = eclib.PlateButton(self, + label=_("Configure"), bmp=bmp, + style=eclib.PB_STYLE_NOBG) + self._config.Unbind(wx.EVT_ERASE_BACKGROUND) + self._config.Enable(enabled) + + # Setup + if not hasattr(mod, 'GetConfigObject'): + self._config.Hide() + + ipath = self.GetInstallPath() + if ipath: + if not os.access(ipath, os.R_OK|os.W_OK): + self._uninstall.Show(False) + else: + util.Log("[pluginmgr][warn] cant find plugin path for %s" % \ + self._pdata.GetName()) + self._uninstall.Show(False) # Should not happen + + font = self._title.GetFont() + font.SetWeight(wx.FONTWEIGHT_BOLD) + self._title.SetFont(font) + self._version.SetFont(font) + + if wx.Platform == '__WXMAC__': + for ctrl in (self._desc, self._auth, self._enabled, + self._config, self._uninstall): + ctrl.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + + # Layout + self.__DoLayout() + + # Event Handlers + self.Bind(wx.EVT_CHECKBOX, self.OnCheck) + self.Bind(wx.EVT_BUTTON, self.OnConfigButton, self._config) + self.Bind(wx.EVT_BUTTON, self.OnUninstallButton, self._uninstall) + + def __DoLayout(self): + """Layout the panel""" + vsizer = wx.BoxSizer(wx.VERTICAL) + hsizer = wx.BoxSizer(wx.HORIZONTAL) + + # Left side Bitmap and Checkbox + hsizer.Add((5, 5), 0) + if self._bmp is not None: + self._bmp = wx.StaticBitmap(self, bitmap=self._bmp) + hsizer.Add(self._bmp, 0, wx.ALIGN_CENTER_VERTICAL) + + # Central area main content + csizer = wx.BoxSizer(wx.VERTICAL) + tsizer = wx.BoxSizer(wx.HORIZONTAL) + tsizer.AddMany([(self._title, 0), ((20, -1), 1, wx.EXPAND), + (self._version, 0, wx.ALIGN_RIGHT), + ((5, 5), 0)]) + + bsizer = wx.BoxSizer(wx.HORIZONTAL) + bsizer.AddMany([(self._auth, 0), ((5, -1), 1, wx.EXPAND), + (self._enabled, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), + (self._uninstall, 0, wx.ALIGN_CENTER_VERTICAL), + (self._config, 0, wx.ALIGN_CENTER_VERTICAL)]) + csizer.AddMany([(tsizer, 1, wx.EXPAND), ((3, 3), 0), + (self._desc, 0), ((3, 3), 0), + (bsizer, 0, wx.EXPAND)]) + + # Finish Layout + hsizer.AddMany([((5, 5), 0), (csizer, 1, wx.EXPAND), ((5, 5), 0)]) + vsizer.AddMany([((4, 4), 0), (hsizer, 0, wx.EXPAND), ((4, 4), 0)]) + self.SetSizer(vsizer) + self.SetAutoLayout(True) + + def GetInstallPath(self): + """Get the path of the plugin + @return: string + + """ + if self._pdata is not None: + dist = self._pdata.GetDist() + if dist is not None: + return dist.location + return u'' + + def GetPluginName(self): + """Get the name of the plugin + @return: string + + """ + return self._title.GetLabel() + + def GetVersionString(self): + """Get the version of the plugin + @return: string + + """ + return self._version.GetLabel() + + def OnConfigButton(self, evt): + """Handle when the configuration button is hit.""" + if self._module is not None: + cfg_obj = self._module.GetConfigObject() + event = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY, + ed_glob.ID_PREF, cfg_obj) + wx.PostEvent(self.GetParent(), event) + + def OnUninstallButton(self, evt): + """Uninstall the plugin""" + msg = _("Are you sure you want to uninstall %s?\nThis cannot be undone.") + result = wx.MessageBox(msg % self.GetPluginName(), + _("Uninstall Plugin"), + wx.OK|wx.CANCEL|wx.ICON_WARNING) + if result == wx.OK: + self.Enable(False) + self._desc.SetLabel(_("This plugin will be uninstalled on next program launch.")) + self._enabled.SetValue(False) + pname = self._title.GetLabel() + event = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY, self.GetId(), + (pname, False), self) + wx.PostEvent(self.GetParent(), event) + plist = Profile_Get('UNINSTALL_PLUGINS', default=list()) + plist.append(self.GetInstallPath()) + Profile_Set('UNINSTALL_PLUGINS', plist) + else: + return + + def OnCheck(self, evt): + """Notify container of changes to state of plugin""" + enabled = self._enabled.GetValue() + self._config.Enable(enabled) + pname = self._title.GetLabel() + event = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY, self.GetId(), + (pname, enabled), self) + wx.PostEvent(self.GetParent(), event) + + def SetChecked(self, check=True): + """Set the checkbox + @param check: bool + + """ + self._enabled.SetValue(check) + self._config.Enable(check) + +#-----------------------------------------------------------------------------# + +class PBDownloadItem(PBPluginItem): + """PanelBox Item to display download information about a plugin.""" + def __init__(self, parent, pdata, bmp=None): + """Create the PanelBoxItem + @param parent: L{PanelBox} + @param pdata: PluginData + @keyword bmp: Plugin Icon + + """ + super(PBDownloadItem, self).__init__(parent, None, pdata, bmp=bmp) + + # Setup + self._uninstall.Hide() + self._enabled.SetLabel(_("Download")) + self.Layout() + +#-----------------------------------------------------------------------------# + +class PluginErrorItem(eclib.PanelBoxItemBase): + """PanelBox Item to display configuration information about a plugin.""" + def __init__(self, parent, pdata, msg, bmp): + """Create the PanelBoxItem + @param parent: L{PanelBox} + @param pdata: PluginData + @param msg: error msg + @param bmp: Bitmap + + """ + super(PluginErrorItem, self).__init__(parent) + + # Attributes + self._bmp = bmp + self._title = wx.StaticText(self, label=pdata.GetName()) + self._version = wx.StaticText(self, label=pdata.GetVersion()) + self._msg = wx.StaticText(self, label=msg) + self._auth = wx.StaticText(self, label=_("Author: %s") % pdata.GetAuthor()) + + # Setup + font = self._title.GetFont() + font.SetWeight(wx.FONTWEIGHT_BOLD) + self._title.SetFont(font) + self._version.SetFont(font) + + if wx.Platform == '__WXMAC__': + self._msg.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + self._auth.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + + # Layout + self.__DoLayout() + + def __DoLayout(self): + """Layout the panel""" + vsizer = wx.BoxSizer(wx.VERTICAL) + hsizer = wx.BoxSizer(wx.HORIZONTAL) + + # Left side Bitmap and Checkbox + hsizer.Add((5, 5), 0) + if self._bmp is not None: + self._bmp = wx.StaticBitmap(self, bitmap=self._bmp) + hsizer.Add(self._bmp, 0, wx.ALIGN_CENTER_VERTICAL) + + # Central area main content + csizer = wx.BoxSizer(wx.VERTICAL) + tsizer = wx.BoxSizer(wx.HORIZONTAL) + tsizer.AddMany([(self._title, 0), ((20, -1), 1, wx.EXPAND), + (self._version, 0, wx.ALIGN_RIGHT)]) + + bsizer = wx.BoxSizer(wx.HORIZONTAL) + bsizer.AddMany([(self._auth, 0)]) + csizer.AddMany([(tsizer, 1, wx.EXPAND), ((3, 3), 0), + (self._msg, 0), ((3, 3), 0), + (bsizer, 0, wx.EXPAND)]) + + # Finish Layout + hsizer.AddMany([((5, 5), 0), (csizer, 1, wx.EXPAND), ((5, 5), 0)]) + vsizer.AddMany([((4, 4), 0), (hsizer, 0, wx.EXPAND), ((4, 4), 0)]) + self.SetSizer(vsizer) + self.SetAutoLayout(True) + +#-----------------------------------------------------------------------------# + +class PluginData(plugin.PluginData): + """Plugin Metadata storage class used to store data + about plugins and where to download them from + @see: plugin.PluginData + + """ + def __init__(self, name=u'', descript=u'', \ + author=u'', ver=u'', url=u''): + """Extends PluginData to include information about url to get it from. + @keyword name: Plugin name + @keyword descript: Plugin short description + @keyword author: Plugin Author Name + @keyword ver: Plugin Version (Unicode) + @keyword url: url to download plugin from + + """ + super(PluginData, self).__init__(name, descript, author, ver) + + # Attributes + self._url = url + + def GetUrl(self): + """Returns the URL of the plugin + @return: url string of plugins location + + """ + return self._url + + def SetUrl(self, url): + """Sets the url of the plugin. + @param url: fully qualified url string + + """ + if not isinstance(url, basestring): + try: + url = str(url) + except (TypeError, ValueError): + url = u'' + self._url = url + +#-----------------------------------------------------------------------------# + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugin.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugin.py new file mode 100644 index 0000000..de6a669 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/plugin.py @@ -0,0 +1,877 @@ +############################################################################### +# Name: plugin.py # +# Purpose: Plugin system architecture # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### +# +# Some of the code in this document was derived from trac's plugin architecture +# +# Copyright (C) 2003-2006 Edgewall Software +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. The name of the author may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +This module provides the core functionality of the plugin system for Editra. +Its design is influenced by the system used in the web based project management +software Trac (trac.edgewall.org). To create a plugin plugin class must derive +from Plugin and in the class definintion it must state which Interface it +Implements. Interfaces are defined throughout various locations in the core +Editra code. The interface defines the contract that the plugin needs to +conform to. + +Plugins consist of python egg files that can be created with the use of the +setuptools package. + +There are some issues I dont like with how this is currently working that I +hope to find a work around for in later revisions. Namely I dont like the fact +that the plugins are loaded and kept in memory even when they are not activated. +Although the footprint of the non activated plugin class members being held in +memory is not likely to be very large. + +@summary: Plugin interface and mananger implementation + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: plugin.py 71475 2012-05-18 04:22:28Z CJP $" +__revision__ = "$Revision: 71475 $" + +#--------------------------------------------------------------------------# +# Dependancies +import os +import sys +import shutil +import wx + +# Editra Libraries +import ed_glob +from ed_txt import EncodeString +import util +from profiler import CalcVersionValue, Profile_Get, Profile_Set + +# Try to use the system version of pkg_resources if available else fall +# back to the bundled version. Mostly for binary versions of Editra. +try: + import pkg_resources +except ImportError: + try: + from extern import pkg_resources + except ImportError: + pkg_resources = None + +#--------------------------------------------------------------------------# +# Globals +ENTRYPOINT = 'Editra.plugins' +PLUGIN_CONFIG = "plugin.cfg" +_implements = [] + +_ = wx.GetTranslation + +#--------------------------------------------------------------------------# + +class Interface(object): + """Base class for defining interfaces. Interface classes are + used to define the method/contract from which the plugin must + conform to. + + """ + pass + +#-----------------------------------------------------------------------------# + +class ExtensionPoint(property): + """Declares what L{Interface} a plugin is extending""" + def __init__(self, interface): + """Initializes the extension point + @param interface: interface object that the extension point extends + + """ + property.__init__(self, self.Extensions) + self.interface = interface + + def __repr__(self): + """@return: string representation of the object""" + return '<ExtensionPoint %s>' % self.interface.__name__ + + def Extensions(self, component): + """The exensions that extend this extention point + @param component: The component to get the exensions for + @return: a list of plugins that declare to impliment the + given extension point. + + """ + component = wx.GetApp().GetPluginManager() + extensions = PluginMeta._registry.get(self.interface, []) + return filter(None, [component[cls] for cls in extensions]) + +#-----------------------------------------------------------------------------# + +class PluginMeta(type): + """Acts as the registration point for plugin entrypoint objects. + It makes sure that only a single instance of any particular entry + point is active at one time per plugin manager. + + """ + _plugins = list() + _registry = dict() + + def __new__(mcs, name, bases, d): + """Initialize the MetaClass + @param mcs: Class instance + @param name: Name of object + @param bases: Plugin base classes + @param d: Items dictionary + + """ + d['_implements'] = _implements[:] + del _implements[:] + new_obj = type.__new__(mcs, name, bases, d) + if name == 'Plugin': + return new_obj + + init = d.get("__init__") + if not init: + for init in [b.__init__._original for b in new_obj.mro() + if issubclass(b, Plugin) and '__init__' in b.__dict__]: + break + + PluginMeta._plugins.append(new_obj) + for interface in d.get('_implements', []): + PluginMeta._registry.setdefault(interface, []).append(new_obj) + + for base in [base for base in bases if hasattr(base, '_implements')]: + for interface in base._implements: + PluginMeta._registry.setdefault(interface, []).append(new_obj) + return new_obj + +#-----------------------------------------------------------------------------# + +class Plugin(object): + """Base class for all plugin type objects""" + __metaclass__ = PluginMeta + __name__ = 'EdPlugin' + + def __new__(cls, pluginmgr): + """Only one instance of each plugin is allowed to exist + per manager. If an instance of this plugin has already be + initialized, that instance will be returned. If not this will + initialize a new instance of the plugin. + @param cls: Class object + @keyword pluginmgr: Plugin Manager instance + @return: a new class object or an existing instance if one + exists. + + """ + # Case for a pluginmanager being managed by a plugin manager + if issubclass(cls, PluginManager): + self = super(Plugin, cls).__new__(cls) + self.pluginmgr = self + return self + + plugins = pluginmgr.GetPlugins() + self = plugins.get(cls) + + # Check if it is a default plugin + if self is None: + defaults = pluginmgr.GetDefaultPlugins() + self = defaults.get(cls) + + if self is None: + self = super(Plugin, cls).__new__(cls) + self.pluginmgr = pluginmgr + return self + + def GetMinVersion(self): + """Override in subclasses to return the minimum version of Editra that + the plugin is compatible with. By default it will return the current + version of Editra. + @return: version str + + """ + return ed_glob.VERSION + + def InstallHook(self): + """Override in subclasses to allow the plugin to be loaded + dynamically. + @return: None + + """ + pass + + def IsInstalled(self): + """Return whether the plugins L{InstallHook} method has been called + or not already. + @return: bool + + """ + return False + +#-----------------------------------------------------------------------------# + +class PluginConfigObject(object): + """Plugin configuration object. Plugins that wish to provide a + configuration panel should implement a subclass of this object + in their __init__ module. The __init__ module must also have a + function 'GetConfigObject' that returns an instance of this + class. + + """ + def GetConfigPanel(self, parent): + """Get the configuration panel for this plugin + @param parent: parent window for the panel + @return: wxPanel + + """ + raise NotImplementedError + + def GetBitmap(self): + """Get the 32x32 bitmap to show in the config dialog + @return: wx.Bitmap + @note: Optional if not implemented default icon will be used + + """ + return wx.NullBitmap + + def GetLabel(self): + """Get the display label for the configuration + @return: string + + """ + raise NotImplementedError + +#-----------------------------------------------------------------------------# + +class PluginData(object): + """A storage class for representing data about a Plugin + @see: L{Plugin} + + """ + def __init__(self, name=u'', descript=u'', author=u'', ver=u''): + """Create the plugin data object + @keyword name: Name of the plugin + @keyword descript: Short description of plugin + @keyword author: Who made the plugin + @keyword ver: Version of the plugin (Unicode) + + """ + super(PluginData, self).__init__() + + # Attributes + self._name = name + self._description = descript + self._author = author + self._version = ver + + self._enabled = False + self._installed = True + + self._inst = None + self._cls = None + self._distro = None + + @property + def Distribution(self): + """Distrobution object""" + return self.GetDist() + + @property + def Class(self): + """Class Reference""" + return self.GetClass() + + def Enable(self, enable=True): + """Enable the plugin + @param enable: bool + + """ + self._enabled = enabled + + def GetAuthor(self): + """@return: Author of the plugin""" + return self._author + + def GetClass(self): + """@return class object of the plugin""" + return self._cls + + def GetDescription(self): + """@return: Plugins description string""" + return self._description + + def GetDist(self): + """Return the dist object associated with this plugin + @return: Distribution + + """ + return self._distro + + def GetInstance(self): + """Get the plugin instance + @return: Plugin + + """ + return self._inst + + def GetName(self): + """@return: Plugin's name string""" + return self._name + + def GetVersion(self): + """@return: Plugin's version string""" + return self._version + + @property + def Instance(self): + """Plugin Instance""" + return self.GetInstance() + + def IsEnabled(self): + """Is the plugin enabled + @return: bool + + """ + return self._enabled + + @property + def Module(self): + """Plugin Module Reference""" + return getattr(self.GetInstance(), '__module__', None) + + def SetAuthor(self, author): + """Sets the author attribute + @param author: New Authors name string + @postcondition: Author attribute is set to new value + + """ + if not isinstance(author, basestring): + try: + author = str(author) + except (ValueError, TypeError): + author = u'' + self._author = author + + def SetClass(self, cls): + """Set the class used to create this plugins instance + @param cls: class + + """ + self._cls = cls + + def SetDescription(self, descript): + """@return: Plugins description string""" + if not isinstance(descript, basestring): + try: + descript = str(descript) + except (ValueError, TypeError): + descript = u'' + self._description = descript + + def SetDist(self, distro): + """Set the distribution object + @param distro: Distribution + + """ + self._distro = distro + + def SetInstance(self, inst): + """Set the plugin instance + @param inst: Plugin instance + + """ + self._inst = inst + + def SetName(self, name): + """Sets the plugins name string + @param name: String to name plugin with + @postcondition: Plugins name string is set + + """ + if not isinstance(name, basestring): + try: + name = str(name) + except (ValueError, TypeError): + name = u'' + self._name = name + + def SetVersion(self, ver): + """Sets the version attribute of the plugin. + @param ver: Version string + @postcondition: Plugins version attribute is set to new value + + """ + if not isinstance(ver, basestring): + try: + ver = str(ver) + except (ValueError, TypeError): + ver = u'' + self._version = ver + +#-----------------------------------------------------------------------------# + +def Implements(*interfaces): + """Used by L{Plugin}s to declare the interface that they + implment/extend. + @param interfaces: list of interfaces the plugin implements + + """ + _implements.extend(interfaces) + +#--------------------------------------------------------------------------# + +class PluginManager(object): + """The PluginManger keeps track of the active plugins. It + also provides an interface into loading and unloading plugins. + @todo: Allow loaded but inactive plugins to be initiated without + needing to restart the editor. + + """ + def __init__(self): + """Initializes a PluginManager object. + @postcondition: Plugin manager and plugins are initialized + + """ + object.__init__(self) + self.LOG = wx.GetApp().GetLog() + self.RemoveUninstalled() + + self._config = self.LoadPluginConfig() # Enabled/Disabled Plugins + self._pi_path = list(set([ed_glob.CONFIG['PLUGIN_DIR'], + ed_glob.CONFIG['SYS_PLUGIN_DIR']])) + sys.path.extend(self._pi_path) + self._env = self.CreateEnvironment(self._pi_path) + + # TODO: Combine enabled into pdata + self._pdata = dict() # Plugin data + self._defaults = dict() # Default plugins + self._enabled = dict() # Set of enabled plugins + self._loaded = list() # List of + self._obsolete = dict() # Obsolete plugins list + + self.InitPlugins(self._env) + self.RefreshConfig() + + # Enable/Disable plugins based on config data + self.UpdateConfig() + + def __contains__(self, cobj): + """Returns True if a plugin is currently loaded and being + managed by this manager. + @param cobj: object to look for in loaded plugins + + """ + return cobj in [obj.GetClass() for obj in self._pdata] + + def __getitem__(self, cls): + """Gets and returns the instance of given class if it has + already been activated. + @param cls: class object to get from metaregistery + @return: returns either None or the intialiazed class object + + """ + nspace = cls.__module__ + "." + cls.__name__ + if nspace in ed_glob.DEFAULT_PLUGINS: + self._enabled[cls] = True + + if cls not in self._enabled: + self._enabled[cls] = False # If its a new plugin disable by default + + if not self._enabled[cls]: + return None + +# plugin = self._plugins.get(cls) + plugin = None + pdata = self._pdata.get(cls, None) + if pdata is not None: + plugin = pdata.GetInstance() + else: + # Check defaults + plugin = self._defaults.get(cls, None) + + # Plugin not instantiated yet + if plugin is None: + if cls not in PluginMeta._plugins: + self.LOG("[pluginmgr][err] %s Not Registered" % cls.__name__) + try: + plugin = cls(self) + except (AttributeError, TypeError), msg: + self.LOG("[pluginmgr][err] Unable in initialize plugin") + self.LOG("[pluginmgr][err] %s" % str(msg)) + + return plugin + + #---- End Private Members ----# + + #---- Public Class Functions ----# + def AppendPath(self, path): + """Append a path to the environment path for the plugin manager + to look for plugins on. The path is only added to the environment + in order for it to be used you must call RefreshEnvironment afterwards + to re-initialize the running environment. + + @param path: path to append to environment + @return: True if path was successfully added or False otherwise + + """ + if os.path.exists(path): + if path not in self._pi_path: + self._pi_path.append(path) + return True + else: + return False + + def CreateEnvironment(self, path): + """Creates the environment based on the passed + in path list + @param path: path(s) to scan for extension points + @note: pkgutils does not like Unicode! only send encoded strings + + """ + if pkg_resources != None: + path = [ EncodeString(pname, sys.getfilesystemencoding()) + for pname in path ] + + try: + env = pkg_resources.Environment(path) + except UnicodeDecodeError, msg: + self.LOG("[pluginmgr][err] %s" % msg) + else: + self.LOG("[pluginmgr][warn] setuptools is not installed") + env = dict() + return env + + def DisablePlugin(self, plugin): + """Disables a named plugin. Is a convenience function for + EnablePlugin(plugin, False). + + @param plugin: plugin to disable + @precondition: plugin must be managed by this manager instance + @postcondition: plugin is disabled and will not be activated on + next reload. + + """ + self.EnablePlugin(plugin, False) + + def EnablePlugin(self, plugin, enable=True): + """Enables a named plugin. + @param plugin: plugin to enable/disable (case insensitive) + @param enable: should plugin be enabled or disabled + @precondition: plugin must be managed by this manager instance + @postcondition: plugin is added to activate list for activation on + next program start. + + """ + for name in self._config: + if name.lower() == plugin.lower(): + plugin = name + break + + self._config[plugin] = enable + for cls in self._enabled: + if cls.__module__ == plugin: + self._enabled[cls] = enable + + def GetConfig(self): + """Returns a dictionary of plugins and there configuration state. + @return: the mapped set of available plugins (dict) + + """ + self.RefreshConfig() + return self._config + + def GetDefaultPlugins(self): + """Get the loaded default plugins + @return: dict(cls=instance) + + """ + return self._defaults + + def GetEnvironment(self): + """Returns the environment that the plugin manager is currently + running with. + @return: the managers environment + + """ + return self._env + + def GetIncompatible(self): + """Get the list of loaded plugins that are incompatible with the + current running version of Editra. + return: dict(name=module) + + """ + return self._obsolete + + def GetPlugins(self): + """Returns a the dictionary of plugins managed by this manager + @return: all plugins managed by this manger (dict) + + """ + plugins = dict() + for pdata in self._pdata.values(): + plugins[pdata.GetClass()] = pdata.GetInstance() + return plugins + + def GetPluginDistro(self, pname): + """Get the distrobution object for a given plugin name + @param pname: plugin name + @return: Distrobution + + """ + for pdata in self._pdata.values(): + if pname.lower() == pdata.GetName().lower(): + return pdata.GetDist() + else: + return None + + def GetPluginDistros(self): + """Get the plugin distrobution objects + @return: dict(name=Distrobution) + + """ + distros = dict() + for name, pdata in self._pdata: + distros[name] = pdata.GetDist() + return distros + + def InitPlugins(self, env): + """Initializes the plugins that are contained in the given + environment. After calling this the list of available plugins + can be obtained by calling GetPlugins. + @note: plugins must emit the ENTRY_POINT defined in this file in order + to be recognized and initialized. + @postcondition: all plugins in the environment are initialized + + """ + if pkg_resources is None: + return + + pkg_env = env + tmploaded = [ name.lower() for name in self._loaded ] + for name in pkg_env: + self.LOG("[pluginmgr][info] Found plugin: %s" % name) + if name.lower() in tmploaded: + self.LOG("[pluginmgr][info] %s is already loaded" % name) + continue + + egg = pkg_env[name][0] # egg is of type Distribution + egg.activate() + editra_version = CalcVersionValue(ed_glob.VERSION) + for name in egg.get_entry_map(ENTRYPOINT): + try: + # Only load a given entrypoint once + if name not in self._loaded: + entry_point = egg.get_entry_info(ENTRYPOINT, name) + cls = entry_point.load() + self._loaded.append(name) + else: + self.LOG("[pluginmgr][info] Skip reloading: %s" % name) + continue + except Exception, msg: + self.LOG("[pluginmgr][err] Couldn't Load %s: %s" % (name, msg)) + else: + try: + # Only initialize plugins that haven't already been + # initialized + if cls not in self._pdata: + self.LOG("[pluginmgr][info] Creating Instance of %s" % name) + instance = cls(self) + minv = CalcVersionValue(instance.GetMinVersion()) + if minv <= editra_version: + mod = instance.__module__ + desc = getattr(mod, '__doc__', _("No Description Available")) + auth = getattr(mod, '__author__', _("Unknown")) + pdata = PluginData(egg.project_name, + desc.strip(), + auth.strip(), + egg.version) + pdata.SetDist(egg) + pdata.SetInstance(instance) + pdata.SetClass(cls) + self._pdata[cls] = pdata + self.LOG("[pluginmgr][info] Cached Plugin: %s" % egg.project_name) + else: + # Save plugins that are not compatible with + # this version to use for notifications. + self._obsolete[name] = cls.__module__ + else: + self.LOG("[pluginmgr][info] Skip re-init of %s" % cls) + finally: + pass + + # Activate all default plugins + for d_pi in ed_glob.DEFAULT_PLUGINS: + obj = d_pi.split(".") + mod = ".".join(obj[:-1]) + entry = __import__(mod, globals(), globals(), ['__name__']) + if hasattr(entry, obj[-1]) and entry not in self._defaults: + entry = getattr(entry, obj[-1]) + self._defaults[entry] = entry(self) + + return True + + def LoadPluginByName(self, name): + """Loads a named plugin. + @todo: Implement this method + + """ + raise NotImplementedError + + def LoadPluginConfig(self): + """Loads the plugin config file for the current user if + it exists. The configuration file contains which plugins + are active and which ones are not. + @return: configuration dictionary + + """ + config = dict() + reader = util.GetFileReader(os.path.join(ed_glob.CONFIG['CONFIG_DIR'], + PLUGIN_CONFIG)) + if reader == -1: + self.LOG("[pluginmgr][err] Failed to read plugin config file") + return config + + reading = True + for line in reader.readlines(): + data = line.strip() + if len(data) and data[0] == u"#": + continue + + data = data.split(u"=") + if len(data) == 2: + config[data[0].strip()] = data[1].strip().lower() == u"true" + else: + continue + + reader.close() + return config + + def RefreshConfig(self): + """Refreshes the config data comparing the loadable + plugins against the config data and removing any entries + that dont exist in both from the configuration data. + @postcondition: entries that could not be loaded or do not + exist any longer are removed from the config + + """ + plugins = [ plugin.GetInstance().__module__ + for plugin in self._pdata.values() ] + + config = dict() + for item in self._config: + if item in plugins: + config[item] = self._config[item] + self._config = config + + def RefreshEnvironment(self): + """Refreshes the current environment to include any + plugins that may have been added since init. + @postcondition: environment is refreshed + + """ + self._env = self.CreateEnvironment(self._pi_path) + + def ReInit(self): + """Reinitializes the plugin environment and all plugins + in the environment as well as the configuration data. + @postcondition: the manager is reinitialized to reflect + any configuration or environment changes + that may have occured. + + """ + self.RefreshEnvironment() + self.InitPlugins(self.GetEnvironment()) + self.RefreshConfig() + self.UpdateConfig() + + def RemoveUninstalled(self): + """Remove all uninstalled plugins + @todo: need error reporting and handling file permissions + @todo: handle multiple older versions that are installed + @todo: handle when installed in multiple locations + + """ + plist = Profile_Get('UNINSTALL_PLUGINS', default=list()) + for path in list(plist): + try: + if os.path.isdir(path): + shutil.rmtree(path) + else: + os.remove(path) + except OSError: + # TODO: don't delete from list, so it can be kept to report + # removal errors to user. + if not os.path.exists(path): + plist.remove(path) + continue + else: + self.LOG("[pluginmgr][info] Uninstalled: %s" % path) + plist.remove(path) + Profile_Set('UNINSTALL_PLUGINS', plist) + + def UnloadPluginByName(self, name): + """Unloads a named plugin. + @todo: implement this method + + """ + raise NotImplementedError + + def UpdateConfig(self): + """Updates the in memory config data to recognize + any plugins that may have been added or initialzed + by a call to InitPlugins. + @postcondition: plugins are enabled or disabled based + on the configuration data. + + """ + for pdata in self._pdata.values(): + plugin = pdata.GetClass() + if self._config.get(plugin.__module__): + self._enabled[plugin] = True + else: + self._config[plugin.__module__] = False + self._enabled[plugin] = False + + def WritePluginConfig(self): + """Writes out the plugin config. + @postcondition: the configuration data is saved to disk + + """ + writer = util.GetFileWriter(os.path.join(ed_glob.CONFIG['CONFIG_DIR'], + PLUGIN_CONFIG)) + if writer == -1: + self.LOG("[pluginmgr][err] Failed to write plugin config") + return + + writer.write("# Editra %s Plugin Config\n#\n" % ed_glob.VERSION) + for item in self._config: + writer.write("%s=%s\n" % (item, str(self._config[item]))) + writer.write("\n# EOF\n") + writer.close() + return diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/prefdlg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/prefdlg.py new file mode 100644 index 0000000..ac0e6bf --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/prefdlg.py @@ -0,0 +1,2212 @@ +############################################################################### +# Name: prefdlg.py # +# Purpose: UI for configuring User Profile # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +The classes and functions contained in this file are used for creating the +preference dialog that allows for dynamically configuring most of the options +and setting of the program by setting values in the Profile. + +@summary: Editra's Preference Dialog + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: prefdlg.py 72221 2012-07-28 15:28:31Z CJP $" +__revision__ = "$Revision: 72221 $" + +#----------------------------------------------------------------------------# +# Dependencies +import wx +import wx.lib.mixins.listctrl as listmix +import encodings +import os +import sys + +# Editra Libraries +import ed_glob +import profiler +from profiler import Profile_Get, Profile_Set +import ed_i18n +import ed_event +import ed_crypt +import updater +import util +import syntax.syntax as syntax +import ed_msg +import ed_txt +import eclib +import ed_menu +import extern.stcspellcheck as stcspellcheck + +#----------------------------------------------------------------------------# +# Globals +ID_CHECK_UPDATE = wx.NewId() +ID_DOWNLOAD = wx.NewId() +ID_UPDATE_MSG = wx.NewId() + +ID_PREF_BKUP_PATH = wx.NewId() +ID_PREF_BKUP_SUFFIX = wx.NewId() +ID_PREF_BKUP_LBL = wx.NewId() +ID_PREF_AUTO_SPELL = wx.NewId() +ID_PREF_SPELL_DICT = wx.NewId() +ID_PREF_ENCHANT_PATH = wx.NewId() + +_ = wx.GetTranslation +#----------------------------------------------------------------------------# +# Utility + +def MakeThemeTool(tool_id): + """Makes a themed bitmap for the tool book of the pref dialog. + @param tool_id: An art identifier id + @return: 32x32 bitmap + + """ + osize = Profile_Get('ICON_SZ', 'size_tuple', (24, 24)) + Profile_Set('ICON_SZ', (32, 32)) + over = wx.ArtProvider.GetBitmap(str(tool_id), wx.ART_TOOLBAR) + Profile_Set('ICON_SZ', osize) + return over + +#----------------------------------------------------------------------------# + +class PreferencesPanelBase(object): + """Base mixin class for preference panels""" + def __init__(self): + super(PreferencesPanelBase, self).__init__() + + # Attributes + self._layout_done = False + + def DoSelected(self): + """Handle initial selection to create controls""" + if not self._layout_done: + self._layout_done = True + self._DoLayout() + self.SetAutoLayout(True) + +#----------------------------------------------------------------------------# + +class PreferencesDialog(wx.Frame): + """Preference dialog for configuring the editor + @summary: Provides an interface into configuring profile settings + + """ + __name__ = u'PreferencesDialog' + + def __init__(self, parent, id_=wx.ID_ANY, + style=wx.DEFAULT_DIALOG_STYLE | wx.TAB_TRAVERSAL): + """Initializes the preference dialog + @param parent: The parent window of this window + @keyword id_: The id of this window + @keyword style: Window Style bitmask + + """ + super(PreferencesDialog, self).__init__(parent, id_, + _("Preferences - Editra"), + style=style) + util.SetWindowIcon(self) + + # Extra Styles + self.SetTransparent(Profile_Get('ALPHA', default=255)) + + # Attributes + self._accel = wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CLOSE)]) + self.SetAcceleratorTable(self._accel) + self._tbook = PrefTools(self) + sizer = wx.BoxSizer(wx.VERTICAL) + + # Layout + sizer.Add(self._tbook, 1, wx.EXPAND) + self.SetSizer(sizer) + self.SetAutoLayout(True) + self.SetInitialSize() + wx.GetApp().RegisterWindow(repr(self), self, True) + + # Bind Events + self.Bind(wx.EVT_MENU, lambda evt: self.Close(), id=wx.ID_CLOSE) + self.Bind(wx.EVT_CLOSE, self.OnClose) + self.Bind(wx.EVT_SHOW, self.OnShow) + + def OnClose(self, evt): + """Hanles the window closer event + @param evt: Event that called this handler + + """ + # XXX More strange wx is None errors have been reported here + # really need to find the cause of this! + if wx is not None: + wx.GetApp().UnRegisterWindow(repr(self)) + + # Save profile settings + profiler.TheProfile.Write(profiler.Profile_Get('MYPROFILE')) + + evt.Skip() + + def OnShow(self, evt): + """Hanles the window closer event + @param evt: Event that called this handler + + """ + self._tbook.OnPageChanged() + evt.Skip() + +#-----------------------------------------------------------------------------# + +class PrefTools(eclib.SegmentBook): + """Main sections of the configuration pages + @note: implements the top level book control for the prefdlg + + """ + GENERAL_PG = 0 + APPEAR_PG = 1 + DOC_PG = 2 + UPDATE_PG = 3 + ADV_PG = 4 + + def __init__(self, parent): + """Initializes the main book control of the preferences dialog + @summary: Creates the top level notebook control for the prefdlg + a toolbar is used for changing pages. + + """ + super(PrefTools, self).__init__(parent, wx.ID_ANY, + style=eclib.SEGBOOK_STYLE_LABELS|\ + eclib.SEGBOOK_STYLE_NO_DIVIDERS) + + # Attributes + self._imglst = list() + self.__InitImgList() + + self.AddPage(GeneralPanel(self), _("General"), + img_id=self.GENERAL_PG) + self.AddPage(AppearancePanel(self), _("Appearance"), + img_id=self.APPEAR_PG) + self.AddPage(DocumentPanel(self), _("Document"), + img_id=self.DOC_PG) + self.AddPage(NetworkPanel(self), _("Network"), + img_id=self.UPDATE_PG) + self.AddPage(AdvancedPanel(self), _("Advanced"), + img_id=self.ADV_PG) + + # Event Handlers + self.Bind(eclib.EVT_SB_PAGE_CHANGED, self.OnPageChanged) + self.Bind(eclib.EVT_SB_PAGE_CHANGING, self.OnPageChanging) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + + # Message Handlers + ed_msg.Subscribe(self.OnThemeChange, ed_msg.EDMSG_THEME_CHANGED) + + def OnDestroy(self, evt): + """Cleanup message handlers when destroyed""" + if evt.GetId() == self.GetId(): + ed_msg.Unsubscribe(self.OnThemeChange) + evt.Skip() + + def __InitImgList(self): + """Setup the image list for the SegmentBook""" + dorefresh = False + if len(self._imglst): + del self._imglst + self._imglst = list() + dorefresh = True + + self._imglst.append(MakeThemeTool(ed_glob.ID_PREF)) + self._imglst.append(MakeThemeTool(ed_glob.ID_THEME)) + self._imglst.append(MakeThemeTool(ed_glob.ID_DOCPROP)) + self._imglst.append(MakeThemeTool(ed_glob.ID_WEB)) + self._imglst.append(MakeThemeTool(ed_glob.ID_ADVANCED)) + self.SetImageList(self._imglst) + self.SetUsePyImageList(True) + + if dorefresh: + self.Refresh() + + def OnPageChanging(self, evt): + """Handle notebook page change notifications""" + sel = evt.GetSelection() + page = self.GetPage(sel) + if hasattr(page, 'DoSelected'): + page.DoSelected() + evt.Skip() + + def OnPageChanged(self, evt=None): + """Resizes the dialog based on the pages size + @todo: animate the resizing so its smoother + + """ + util.Log("[prefdlg][evt] toolbook page changed") + page = self.GetPage(self.GetSelection()) + page.SetInitialSize() + parent = self.GetParent() + psz = page.GetSize() + width = psz.GetWidth() + + cbar = self.GetControlBar(wx.TOP) + tbsz = cbar.GetBestSize() + if tbsz[0] > width: + width = tbsz[0] + + with eclib.Freezer(page) as _tmp: + parent.SetClientSize((width, psz.GetHeight() + tbsz[1])) + parent.SendSizeEvent() + parent.Layout() + if evt is not None: + evt.Skip() + + def OnThemeChange(self, msg): + """Update icons when the theme changes""" + self.__InitImgList() + +#-----------------------------------------------------------------------------# + +class GeneralPanel(wx.Panel, PreferencesPanelBase): + """Creates a panel with controls for Editra's general settings + @summary: Panel with a number of controls that affect the users + global profile setting for how Editra should operate. + + """ + def __init__(self, parent, style=wx.BORDER_SUNKEN): + """Create the panel + @param parent: Parent window of this panel + @keyword style: Window Style bitmask + + """ + wx.Panel.__init__(self, parent, style=style) + PreferencesPanelBase.__init__(self) + + # Attributes + self.SetToolTipString(_("Changes made in this dialog are saved in your " + "current profile. Some Items such as Language " + "require the program to be restarted before " + "taking effect.")) + + # Layout this page right away + self._DoLayout() + self._layout_done = True + + # Event Handlers + self.Bind(wx.EVT_CHECKBOX, self.OnCheck) + self.Bind(wx.EVT_CHOICE, self.OnChoice) + self.Bind(wx.EVT_COMBOBOX, self.OnChoice) + + def _DoLayout(self): + """Add the controls and do the layout + @note: do not call this after __init__ + + """ + # Startup Section + sizer = wx.BoxSizer(wx.HORIZONTAL) + nbook = wx.Notebook(self) + nbook.AddPage(GeneralStartupPanel(nbook), _("Startup")) + nbook.AddPage(GeneralFilePanel(nbook), _("Files")) + sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)]) + msizer = wx.BoxSizer(wx.VERTICAL) + msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + + def OnCheck(self, evt): + """Handles events from the check boxes + @param evt: event that called this handler + + """ + util.Log("[prefdlg][evt] General Page: Check box clicked") + e_id = evt.GetId() + e_obj = evt.GetEventObject() + val = e_obj.GetValue() + if e_id in (ed_glob.ID_APP_SPLASH, ed_glob.ID_PREF_SPOS, + ed_glob.ID_SESSION, + ed_glob.ID_NEW_WINDOW, ed_glob.ID_PREF_CHKUPDATE, + ed_glob.ID_PREF_WARN_EOL, ed_glob.ID_PREF_AUTO_RELOAD): + Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetValue()) + elif e_id == ed_glob.ID_REPORTER: + Profile_Set(ed_glob.ID_2_PROF[e_id], not e_obj.GetValue()) + elif e_id == ed_glob.ID_PREF_CHKMOD: + Profile_Set(ed_glob.ID_2_PROF[e_id], val) + self.FindWindowById(ed_glob.ID_PREF_AUTO_RELOAD).Enable(val) + elif e_id == ed_glob.ID_PREF_AUTOBKUP: + Profile_Set(ed_glob.ID_2_PROF[e_id], val) + elif e_id == ID_PREF_AUTO_SPELL: + spref = Profile_Get('SPELLCHECK', default=dict()) + spref['auto'] = val + Profile_Set('SPELLCHECK', spref) + else: + pass + evt.Skip() + + @staticmethod + def OnChoice(evt): + """Handles events from the choice controls + @param evt: event that called this handler + @note: Also handles the Language ComboBox + + """ + e_id = evt.GetId() + e_obj = evt.GetEventObject() + if e_id in [ed_glob.ID_PREF_MODE, + ed_glob.ID_PREF_FHIST, + ed_glob.ID_PREF_LANG, + ed_glob.ID_PREF_ENCODING]: + + Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetValue()) + if e_id == ed_glob.ID_PREF_MODE: + val = e_obj.GetValue() + ed_glob.DEBUG = ('DEBUG' in val) + ed_glob.VDEBUG = ('VERBOSE' in val) + elif e_id == ed_glob.ID_PRINT_MODE: + Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetSelection()) + elif e_id == ID_PREF_SPELL_DICT: + ssel = e_obj.GetStringSelection() + sprefs = Profile_Get('SPELLCHECK', default=dict()) + sprefs['dict'] = ssel + Profile_Set('SPELLCHECK', sprefs) + else: + evt.Skip() + +#-----------------------------------------------------------------------------# + +class GeneralStartupPanel(wx.Panel): + """General Startup Settings""" + def __init__(self, parent): + super(GeneralStartupPanel, self).__init__(parent) + + # Attributes + + # Setup + self._DoLayout() + + def _DoLayout(self): + """Do the panels layout""" + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([(wx.StaticText(self, label=_("Editor Mode") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PREF_MODE, + choices=['CODE', 'DEBUG', 'VERBOSE DEBUG'], + default=Profile_Get('MODE')), + 0, wx.ALIGN_CENTER_VERTICAL)]) + + psizer = wx.BoxSizer(wx.HORIZONTAL) + psizer.AddMany([(wx.StaticText(self, label=_("Printer Mode") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PRINT_MODE, + choices=GetPrintModeStrings(), + default=Profile_Get('PRINT_MODE')), + 0, wx.ALIGN_CENTER_VERTICAL)]) + + reporter_cb = wx.CheckBox(self, ed_glob.ID_REPORTER, + _("Disable Error Reporter")) + reporter_cb.SetValue(not Profile_Get('REPORTER')) + sess_cb = wx.CheckBox(self, ed_glob.ID_SESSION, _("Load Last Session")) + sess_cb.SetValue(Profile_Get('SAVE_SESSION', default=False)) + sess_cb.SetToolTipString(_("Load files from last session on startup")) + splash_cb = wx.CheckBox(self, ed_glob.ID_APP_SPLASH, + _("Show Splash Screen")) + splash_cb.SetValue(Profile_Get('APPSPLASH')) + + # Only enable update option if user has access to install directory + isadmin = os.access(ed_glob.CONFIG['INSTALL_DIR'], os.R_OK|os.W_OK) + if isadmin: + chk_update = wx.CheckBox(self, ed_glob.ID_PREF_CHKUPDATE, + _("Check for updates on startup")) + chk_update.SetValue(Profile_Get('CHECKUPDATE')) + + # Locale + lsizer = wx.BoxSizer(wx.HORIZONTAL) + lsizer.AddMany([(wx.StaticText(self, label=_("Language") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ed_i18n.LangListCombo(self, ed_glob.ID_PREF_LANG, + Profile_Get('LANG')), + 0, wx.ALIGN_CENTER_VERTICAL)]) + + # Layout items + sizer = wx.FlexGridSizer(11, 2, 5, 5) + sizer.AddMany([((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, + label=_("Startup Settings") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), (msizer, 0), + ((5, 5),), (psizer, 0), + ((5, 5),), (reporter_cb, 0), + ((5, 5),), (sess_cb, 0), + ((5, 5),), (splash_cb, 0)]) + + if isadmin: + sizer.AddMany([((5, 5),), (chk_update, 0)]) + + sizer.AddMany([((5, 5),), ((5, 5),), + (wx.StaticText(self, label=_("Locale Settings") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), (lsizer, 0), + ((10, 10), 0)]) + + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + +#-----------------------------------------------------------------------------# + +class GeneralFilePanel(wx.Panel): + """Configuration panel for general file settings""" + def __init__(self, parent): + super(GeneralFilePanel, self).__init__(parent) + + # Attributes + self.bsuffix = None + self.bsuffix_lbl = None + + # Setup + self._DoLayout() + + # Event Handlers + self.Bind(wx.EVT_CHECKBOX, + self.OnAutoBkup, + id=ed_glob.ID_PREF_AUTOBKUP) + self.Bind(wx.EVT_CHECKBOX, + self.OnCustomBackupPath, + id=ID_PREF_BKUP_LBL) + self.Bind(wx.EVT_DIRPICKER_CHANGED, + self.OnDirChange, + id=ID_PREF_BKUP_PATH) + self.Bind(wx.EVT_FILEPICKER_CHANGED, + self.OnFileChange, + id=ID_PREF_ENCHANT_PATH) + self.bsuffix.Bind(wx.EVT_KILL_FOCUS, self.OnBackupSuffixLoseFocus) + + def _DoLayout(self): + """Layout the panel""" + # File settings + fhsizer = wx.BoxSizer(wx.HORIZONTAL) + fhsizer.AddMany([(wx.StaticText(self, + label=_("File History Length") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PREF_FHIST, + choices=[str(val) for val in range(1, 10)], + default=Profile_Get('FHIST_LVL', 'str')), + 0, wx.ALIGN_CENTER_VERTICAL)]) + + # Encoding options + d_encoding = Profile_Get('ENCODING', + 'str', + default=ed_txt.DEFAULT_ENCODING) + if d_encoding is None: + d_encoding = 'utf-8' + Profile_Set('ENCODING', d_encoding) + d_encoding = encodings.normalize_encoding(d_encoding) + + enc_ch = ExChoice(self, ed_glob.ID_PREF_ENCODING, + choices=util.GetAllEncodings(), + default=d_encoding) + enc_ch.SetToolTipString(_("Encoding to try when auto detection fails")) + enc_sz = wx.BoxSizer(wx.HORIZONTAL) + enc_sz.AddMany([(wx.StaticText(self, label=_("Preferred Encoding") + u":"), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5),), (enc_ch, 1)]) + + win_cb = wx.CheckBox(self, ed_glob.ID_NEW_WINDOW, + _("Open files in new windows by default")) + win_cb.SetValue(Profile_Get('OPEN_NW')) + pos_cb = wx.CheckBox(self, ed_glob.ID_PREF_SPOS, + _("Remember File Position")) + pos_cb.SetValue(Profile_Get('SAVE_POS')) + chkmod_cb = wx.CheckBox(self, ed_glob.ID_PREF_CHKMOD, + _("Check if on disk file has been " + "modified by others")) + chkmod_val = Profile_Get('CHECKMOD', default=True) + chkmod_cb.SetValue(chkmod_val) + autorl_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTO_RELOAD, + _("Automatically reload files when " + "changes are detected on disk")) + autorl_cb.SetValue(Profile_Get('AUTO_RELOAD', default=False) and chkmod_val) + autorl_cb.Enable(chkmod_val) + eolwarn_cb = wx.CheckBox(self, ed_glob.ID_PREF_WARN_EOL, + _("Warn when mixed eol characters are detected")) + eolwarn_cb.SetValue(Profile_Get('WARN_EOL', default=True)) + + # Layout items + sizer = wx.FlexGridSizer(9, 2, 5, 5) + sizer.AddMany([((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("File Settings") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), (enc_sz, 0), + ((5, 5),), (fhsizer, 0), + ((5, 5),), (win_cb, 0), + ((5, 5),), (pos_cb, 0), + ((5, 5),), (chkmod_cb, 0), + ((5, 5),), (autorl_cb, 0), + ((5, 5),), (eolwarn_cb, 0), + ((5, 5), 0)]) + + # Auto Backup + bksbox = wx.StaticBox(self, label=_("File Backups")) + bksboxsz = wx.StaticBoxSizer(bksbox, wx.VERTICAL) + autobk_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTOBKUP, + _("Automatically Backup Files")) + bAutoBkup = Profile_Get('AUTOBACKUP', default=False) + autobk_cb.SetValue(bAutoBkup) + autobk_cb.SetToolTipString(_("Backup buffer to file periodically")) + bdir = Profile_Get('AUTOBACKUP_PATH', default="") + bkup_path_lbl = wx.CheckBox(self, ID_PREF_BKUP_LBL, + label=_("Backup Path:")) + bkup_path_lbl.SetValue(bool(bdir)) + bkup_path = wx.DirPickerCtrl(self, ID_PREF_BKUP_PATH, + path=bdir, + style=wx.DIRP_CHANGE_DIR|wx.DIRP_USE_TEXTCTRL) + bkup_path.SetToolTipString(_("Used to set a custom backup path. " + "If not specified the backup will be " + "put in the same directory as the file.")) + bkup_path_lbl.Enable(bAutoBkup) + bkup_path.Enable(bAutoBkup) + bkup_p_sizer = wx.BoxSizer(wx.HORIZONTAL) + bkup_p_sizer.AddMany([(bkup_path_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), + (bkup_path, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)]) + suffix = Profile_Get('AUTOBACKUP_SUFFIX', default=".edbkup") + self.bsuffix = wx.TextCtrl(self, ID_PREF_BKUP_SUFFIX, suffix) + self.bsuffix.SetToolTipString(_("Suffix for backup file names")) + self.bsuffix_lbl = wx.StaticText(self, label=_("Backup file suffix:")) + self.bsuffix_lbl.Enable(bAutoBkup) + self.bsuffix.Enable(bAutoBkup) + bkup_s_sizer = wx.BoxSizer(wx.HORIZONTAL) + bkup_s_sizer.AddMany([(self.bsuffix_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), + (self.bsuffix, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)]) + bksboxsz.AddMany([(autobk_cb, 0), + ((5, 5), 0), (bkup_p_sizer, 0, wx.EXPAND), + ((5, 5), 0), (bkup_s_sizer, 0, wx.EXPAND)]) + # End Auto-Backup + + # Spellchecking settings + spell_dicts = stcspellcheck.STCSpellCheck.getAvailableLanguages() + sbox = wx.StaticBox(self, label=_("Spell Checking")) + sboxsz = wx.StaticBoxSizer(sbox, wx.VERTICAL) + sprefs = Profile_Get('SPELLCHECK', default=dict()) + auto_cb = wx.CheckBox(self, id=ID_PREF_AUTO_SPELL, + label=_("Check spelling while typing")) + auto_cb.SetValue(sprefs.get('auto', False)) + dict_ch = wx.Choice(self, id=ID_PREF_SPELL_DICT, choices=spell_dicts) + sdict = sprefs.get('dict', 'en_US') + if sdict in spell_dicts: + dict_ch.SetStringSelection(sdict) + sdh_sz = wx.BoxSizer(wx.HORIZONTAL) + dlbl = wx.StaticText(self, label=_("Dictionary:")) + sdh_sz.AddMany([(dlbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), + (dict_ch, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)]) + sboxsz.AddMany([(auto_cb, 0), ((5, 5), 0), (sdh_sz, 0, wx.EXPAND)]) + + if not stcspellcheck.STCSpellCheck.isEnchantOk(): + for ctrl in (auto_cb, dict_ch, dlbl): + ctrl.Enable(False) + + liblbl = wx.StaticText(self, label=_("Enchant Path:")) + libpath = os.environ.get('PYENCHANT_LIBRARY_PATH', '') + prefpath = sprefs.get('epath', libpath) + if not prefpath: + prefpath = u"" + libpicker = wx.FilePickerCtrl(self, ID_PREF_ENCHANT_PATH, + path=prefpath, + message=_("Path to libenchant")) + libpicker.SetToolTipString(_("Path to libenchant")) + lib_hsz = wx.BoxSizer(wx.HORIZONTAL) + lib_hsz.AddMany([(liblbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), + (libpicker, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)]) + sboxsz.AddMany([((5, 5), 0), (lib_hsz, 0, wx.EXPAND)]) + + vsizer = wx.BoxSizer(wx.VERTICAL) + vsizer.AddMany([(sizer, 1, wx.EXPAND), + ((5, 5), 0), (bksboxsz, 0, wx.EXPAND), + ((5, 5), 0), (sboxsz, 0, wx.EXPAND), + ((10, 10), 0)]) + + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([((10, 10), 0), (vsizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + + def OnAutoBkup(self, evt): + """Enable/Disable the backup path controls + The profile is updated by L{GeneralPanel} so the event must be skipped + + """ + e_obj = evt.GetEventObject() + blbl = self.FindWindowById(ID_PREF_BKUP_LBL) + blbl.Enable(e_obj.Value) + dpick = self.FindWindowById(ID_PREF_BKUP_PATH) + bpath = Profile_Get('AUTOBACKUP_PATH', default="") + dpick.SetPath(bpath) + if not e_obj.Value: + dpick = self.FindWindowById(ID_PREF_BKUP_PATH) + dpick.Enable(False) + self.bsuffix.Enable(e_obj.Value) + self.bsuffix_lbl.Enable(e_obj.Value) + evt.Skip() + + def OnCustomBackupPath(self, evt): + """Enable the use of a custom backup path""" + e_obj = evt.GetEventObject() + event_val = e_obj.GetValue() + dpick = self.FindWindowById(ID_PREF_BKUP_PATH) + if not event_val: + dpick.SetPath(u"") + Profile_Set('AUTOBACKUP_PATH', u"") + dpick.Enable(event_val) + + def OnDirChange(self, evt): + """Update the backup directory path""" + path = evt.GetPath().strip() + bpath = Profile_Get('AUTOBACKUP_PATH', default="") + if bpath != path: + Profile_Set('AUTOBACKUP_PATH', path) + + def OnFileChange(self, evt): + """Update enchant path and attempt to reload enchant if necessary""" + path = evt.GetPath().strip() + sprefs = Profile_Get('SPELLCHECK', default=dict()) + cpath = sprefs.get('epath', u'') + if path != cpath: + try: + ok = stcspellcheck.STCSpellCheck.reloadEnchant(path) + except OSError: + ok = False + + if ok: + # Reload was successful + sprefs['epath'] = path + Profile_Set('SPELLCHECK', sprefs) + else: + wx.MessageBox(_("Failed to load Enchant"), + _("Library Error"), + wx.OK|wx.ICON_ERROR) + + def OnBackupSuffixLoseFocus(self, evt): + """Update the backup file name suffix""" + suffix = self.bsuffix.GetValue().strip() + old_suffix = Profile_Get('AUTOBACKUP_SUFFIX', default='') + if suffix != old_suffix: + Profile_Set('AUTOBACKUP_SUFFIX', suffix) + +#-----------------------------------------------------------------------------# + +class DocumentPanel(wx.Panel, PreferencesPanelBase): + """Creates a panel with controls for Editra's editing settings + @summary: Contains a wx.Notebook that contains a number of pages with + setting controls for how documents are handled by the + ed_stc.EditraStc text control. + + """ + def __init__(self, parent, style=wx.BORDER_SUNKEN): + """Create the panel + @param parent: Parent window of this panel + @keyword style: Window Style bitmask + + """ + wx.Panel.__init__(self, parent, style=style) + PreferencesPanelBase.__init__(self) + + def _DoLayout(self): + """Do the layout of the panel + @note: Do not call this after __init__ + + """ + sizer = wx.BoxSizer(wx.HORIZONTAL) + nbook = wx.Notebook(self) + nbook.AddPage(DocGenPanel(nbook), _("General")) + nbook.AddPage(DocCodePanel(nbook), _("Code")) + nbook.AddPage(DocSyntaxPanel(nbook), _("Syntax Highlighting")) + sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)]) + msizer = wx.BoxSizer(wx.VERTICAL) + msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + + def GetSize(self): + """Get the size of the panel + @return: wx.Size + + """ + sz = wx.Panel.GetSize(self) + return wx.Size(sz[0] + 35, sz[1]) + +class DocGenPanel(wx.Panel): + """Panel used for general document settings in the DocumentPanel's + notebook. + @summary: Panel with controls for setting the general attributes of + how a document is managed. + + """ + ID_FONT_PICKER = wx.NewId() + ID_FONT_PICKER2 = wx.NewId() + + def __init__(self, parent): + """Create the panel + @param parent: Parent window of this panel + + """ + super(DocGenPanel, self).__init__(parent) + + # Layout + self._DoLayout() + self.SetAutoLayout(True) + + # Event Handlers + self.Bind(wx.EVT_CHECKBOX, self.OnUpdateEditor) + self.Bind(wx.EVT_CHOICE, self.OnUpdateEditor) + self.Bind(eclib.EVT_FONT_CHANGED, self.OnFontChange) + + def _DoLayout(self): + """Layout the controls + @note: Do not call this after __init__ + + """ + # Format Section + tabsz = wx.BoxSizer(wx.HORIZONTAL) + tabsz.AddMany([(wx.StaticText(self, label=_("Tab Width") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PREF_TABW, + choices=['2','3','4','5','6','7','8','9','10'], + default=Profile_Get('TABWIDTH', 'str')), 0, + wx.ALIGN_CENTER_VERTICAL)]) + + indentsz = wx.BoxSizer(wx.HORIZONTAL) + indentsz.AddMany([(wx.StaticText(self, label=_("Indent Width") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PREF_INDENTW, + choices=['2','3','4','5','6','7','8','9','10'], + default=Profile_Get('INDENTWIDTH', 'str')), 0, + wx.ALIGN_CENTER_VERTICAL)]) + + at_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTOTRIM, + _("Automatically trim whitespace on save")) + at_cb.SetValue(Profile_Get('AUTO_TRIM_WS', 'bool', False)) + ut_cb = wx.CheckBox(self, ed_glob.ID_PREF_TABS, + _("Use Tabs Instead of Spaces")) + ut_cb.SetValue(Profile_Get('USETABS', 'bool', False)) + bsu_cb = wx.CheckBox(self, ed_glob.ID_PREF_UNINDENT, + _("Backspace Unindents")) + bsu_cb.SetValue(Profile_Get('BSUNINDENT', 'bool', True)) + + eolsz = wx.BoxSizer(wx.HORIZONTAL) + + # NOTE: order must be kept insync with vals in ed_glob, ed_stc + eolmode = ExChoice(self, ed_glob.ID_EOL_MODE, + choices=[_("Old Macintosh (\\r)"), _("Unix (\\n)"), + _("Windows (\\r\\n)")]) + eolmode.SetSelection(Profile_Get('EOL_MODE')) + + eolsz.AddMany([(wx.StaticText(self, + label=_("Default EOL Mode") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (eolmode, 0, wx.ALIGN_CENTER_VERTICAL)]) + + # View Options + aa_cb = wx.CheckBox(self, ed_glob.ID_PREF_AALIAS, _("AntiAliasing")) + aa_cb.SetValue(Profile_Get('AALIASING')) + seol_cb = wx.CheckBox(self, ed_glob.ID_SHOW_EOL, _("Show EOL Markers")) + seol_cb.SetValue(Profile_Get('SHOW_EOL')) + sln_cb = wx.CheckBox(self, ed_glob.ID_SHOW_LN, _("Show Line Numbers")) + sln_cb.SetValue(Profile_Get('SHOW_LN')) + sws_cb = wx.CheckBox(self, ed_glob.ID_SHOW_WS, _("Show Whitespace")) + sws_cb.SetValue(Profile_Get('SHOW_WS')) + ww_cb = wx.CheckBox(self, ed_glob.ID_WORD_WRAP, _("Word Wrap")) + ww_cb.SetValue(Profile_Get('WRAP')) + ww_cb.SetToolTipString(_("Turn off for better performance")) + vs_cb = wx.CheckBox(self, ed_glob.ID_PREF_VIRT_SPACE, + _("View Virtual Space After Last Line")) + vs_cb.SetValue(Profile_Get('VIEWVERTSPACE', default=False)) + vs_cb.SetToolTipString(_("Adds extra scrolling room after last line")) + cursw_sz = wx.BoxSizer(wx.HORIZONTAL) + curlbl = wx.StaticText(self, label=_("Caret Width:")) + curw_ch = ExChoice(self, ed_glob.ID_PREF_CARET_WIDTH, + choices=['1','2','3','4'], + default=Profile_Get('CARETWIDTH', default=1)-1) + cursw_sz.AddMany([(curlbl, 0, wx.ALIGN_CENTER_VERTICAL), + (curw_ch, 0, wx.LEFT, 5)]) + + # Font Options + fnt = Profile_Get('FONT1', 'font', wx.Font(10, wx.FONTFAMILY_MODERN, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL)) + fpick = eclib.PyFontPicker(self, DocGenPanel.ID_FONT_PICKER, fnt) + fpick.SetToolTipString(_("Sets the main/default font of the document")) + fnt = Profile_Get('FONT2', 'font', wx.Font(10, wx.FONTFAMILY_SWISS, + wx.FONTSTYLE_NORMAL, + wx.FONTWEIGHT_NORMAL)) + fpick2 = eclib.PyFontPicker(self, DocGenPanel.ID_FONT_PICKER2, fnt) + fpick2.SetToolTipString(_("Sets a secondary font used for special " + "regions when syntax highlighting is in use")) + + # Layout + sizer = wx.FlexGridSizer(21, 2, 5, 5) + sizer.AddGrowableCol(1, 1) + sizer.AddMany([((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("Format") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), (at_cb, 0), + ((5, 5), 0), (ut_cb, 0), + ((5, 5), 0), (bsu_cb, 0), + ((5, 5), 0), (tabsz, 0), + ((5, 5), 0), (indentsz, 0), + ((5, 5), 0), (eolsz, 0), + ((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("View Options") + u": "), + 0), (aa_cb, 0), + ((5, 5), 0), (seol_cb, 0), + ((5, 5), 0), (sln_cb, 0), + ((5, 5), 0), (sws_cb, 0), + ((5, 5), 0), (ww_cb, 0), + ((5, 5), 0), (vs_cb, 0), + ((5, 5), 0), (cursw_sz, 0), + ((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("Primary Font") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), + (fpick, 1, wx.EXPAND), + (wx.StaticText(self, label=_("Secondary Font") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), + (fpick2, 1, wx.EXPAND), + ((10, 10), 0), ((10, 10), 0)]) + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + + @staticmethod + def OnFontChange(evt): + """Handles L{eclib.EVT_FONT_CHANGED} from the font controls""" + e_id = evt.GetId() + if e_id in [DocGenPanel.ID_FONT_PICKER, DocGenPanel.ID_FONT_PICKER2]: + font = evt.GetValue() + if not isinstance(font, wx.Font) or font.IsNull(): + return + + if e_id == DocGenPanel.ID_FONT_PICKER: + Profile_Set('FONT1', font, 'font') + else: + Profile_Set('FONT2', font, 'font') + + for main in wx.GetApp().GetMainWindows(): + for stc in main.nb.GetTextControls(): + stc.SetStyleFont(font, e_id == DocGenPanel.ID_FONT_PICKER) + stc.UpdateAllStyles() + else: + evt.Skip() + + @staticmethod + def OnUpdateEditor(evt): + """Update any open text controls to reflect the changes made in this + panel from the checkboxes and choice controls. + @param evt: Event that called this handler + + """ + # XXX Why when running on windows this and other imports randomly + # become None. I have been unable to reproduce this behavior myself + # but have received enough error reports about it to believe it. + # If they were actually NoneTypes the dialog would not be able to + # be shown so this is very strange!! + global ed_glob + if ed_glob is None: + import ed_glob + + e_id = evt.Id + if e_id in (ed_glob.ID_PREF_TABS, ed_glob.ID_PREF_TABW, + ed_glob.ID_PREF_UNINDENT, ed_glob.ID_EOL_MODE, + ed_glob.ID_PREF_AALIAS, ed_glob.ID_SHOW_EOL, + ed_glob.ID_SHOW_LN, ed_glob.ID_SHOW_WS, + ed_glob.ID_WORD_WRAP, ed_glob.ID_PREF_AALIAS, + ed_glob.ID_PREF_INDENTW, ed_glob.ID_PREF_AUTOTRIM, + ed_glob.ID_PREF_VIRT_SPACE, ed_glob.ID_PREF_CARET_WIDTH): + + e_value = evt.EventObject.GetValue() + if e_id == ed_glob.ID_EOL_MODE: + e_value = evt.EventObject.GetSelection() + elif e_id == ed_glob.ID_PREF_CARET_WIDTH: + if e_value: + e_value = int(e_value) + else: + e_value = 1 + + Profile_Set(ed_glob.ID_2_PROF[e_id], e_value) + else: + evt.Skip() + +#----------------------------------------------------------------------------# + +class DocCodePanel(wx.Panel): + """Panel used for programming settings + @summary: Houses many of the controls for configuring the editors features + that are related to programming. + + """ + def __init__(self, parent): + """Create the panel + @param parent: Parent window of this panel + + """ + super(DocCodePanel, self).__init__(parent) + + # Layout + self._DoLayout() + self.SetAutoLayout(True) + + # Event Handlers + self.Bind(wx.EVT_CHECKBOX, self.OnCheck) + self.Bind(wx.EVT_CHOICE, self.OnCheck) + self.Bind(wx.EVT_SPINCTRL, self.OnSpin) + + def _DoLayout(self): + """Layout the page + @note: Do not call this after __init__ + + """ + # General Section + dlex_ch = ExChoice(self, ed_glob.ID_PREF_DLEXER, + choices=syntax.GetLexerList(), + default=Profile_Get('DEFAULT_LEX', + default="Plain Text")) + dlex_ch.SetToolTipString(_("Default highlighing for new documents")) + dlex_sz = wx.BoxSizer(wx.HORIZONTAL) + dlex_sz.AddMany([(wx.StaticText(self, label=_("Default Lexer") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((3, 3),), + (dlex_ch, 0, wx.ALIGN_CENTER_VERTICAL)]) + + # Visual Helpers Section + vis_lbl = wx.StaticText(self, label=_("Visual Helpers") + u": ") + br_cb = wx.CheckBox(self, ed_glob.ID_BRACKETHL, + _("Bracket Highlighting")) + br_cb.SetValue(Profile_Get('BRACKETHL')) + fold_cb = wx.CheckBox(self, ed_glob.ID_FOLDING, _("Code Folding")) + fold_cb.SetValue(Profile_Get('CODE_FOLD')) + edge_cb = wx.CheckBox(self, ed_glob.ID_SHOW_EDGE, _("Edge Guide")) + edge_cb.SetValue(Profile_Get('SHOW_EDGE')) + edge_sp = wx.SpinCtrl(self, ed_glob.ID_PREF_EDGE, + Profile_Get('EDGE', 'str'), min=0, max=160) + edge_sp.SetToolTipString(_("Guide Column")) + edge_col = wx.BoxSizer(wx.HORIZONTAL) + edge_col.AddMany([(edge_cb, 0, wx.ALIGN_CENTER_VERTICAL), + ((10, 5), 0), (edge_sp, 0, wx.ALIGN_CENTER_VERTICAL)]) + hlcaret_cb = wx.CheckBox(self, ed_glob.ID_HLCARET_LINE, + _("Highlight Caret Line")) + hlcaret_cb.SetValue(Profile_Get("HLCARETLINE")) + ind_cb = wx.CheckBox(self, ed_glob.ID_INDENT_GUIDES, + _("Indentation Guides")) + ind_cb.SetValue(Profile_Get('GUIDES')) + + # Input Helpers + comp_cb = wx.CheckBox(self, ed_glob.ID_AUTOCOMP, _("Auto-Completion")) + comp_cb.SetValue(Profile_Get('AUTO_COMP')) + compex_cb = wx.CheckBox(self, ed_glob.ID_PREF_AUTOCOMPEX, + _("Extended Auto-Comp")) + compex_cb.SetValue(Profile_Get('AUTO_COMP_EX')) + compex_cb.Enable(comp_cb.GetValue()) + compex_cb.SetToolTipString(_("Warning suggestions will include" + " context insensitive results")) + compex_sz = wx.BoxSizer(wx.HORIZONTAL) + compex_sz.AddMany([((16, -1), 0), (compex_cb, 0)]) + ai_cb = wx.CheckBox(self, ed_glob.ID_AUTOINDENT, _("Auto-Indent")) + ai_cb.SetValue(Profile_Get('AUTO_INDENT')) + vi_cb = wx.CheckBox(self, ed_glob.ID_VI_MODE, _("Enable Vi Emulation")) + vi_cb.SetValue(Profile_Get('VI_EMU')) + vi_ncb = wx.CheckBox(self, ed_glob.ID_VI_NORMAL_DEFAULT, + _("Start in Normal Mode")) + vi_ncb.SetValue(Profile_Get('VI_NORMAL_DEFAULT')) + vi_ncb.Enable(vi_cb.GetValue()) + vi_ncb_sz = wx.BoxSizer(wx.HORIZONTAL) + vi_ncb_sz.AddMany([((16, -1), 0), (vi_ncb, 0)]) + + # Layout the controls + sizer = wx.FlexGridSizer(15, 2, 5, 5) + sizer.AddMany([((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("General") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), (dlex_sz, 0), + ((10, 10), 0), ((10, 10), 0), + (vis_lbl, 0), (br_cb, 0), + ((5, 5), 0), (fold_cb, 0), + ((5, 5), 0), (edge_col, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), (hlcaret_cb, 0), + ((5, 5), 0), (ind_cb, 0), + ((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("Input Helpers") + u": "), + 0), (comp_cb, 0), + ((5, 5), 0), (compex_sz, 0), + ((5, 5), 0), (ai_cb, 0), + ((5, 5), 0), (vi_cb, 0), + ((5, 5), 0), (vi_ncb_sz, 0), + ((10, 10), 0), ((10, 10), 0)]) + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + + def OnCheck(self, evt): + """Handles the events from this panels check boxes + @param evt: wx.CommandEvent + + """ + e_id = evt.GetId() + if e_id in (ed_glob.ID_BRACKETHL, ed_glob.ID_SHOW_EDGE, + ed_glob.ID_INDENT_GUIDES, ed_glob.ID_FOLDING, + ed_glob.ID_AUTOCOMP, ed_glob.ID_AUTOINDENT, + ed_glob.ID_PREF_EDGE, ed_glob.ID_VI_MODE, + ed_glob.ID_VI_NORMAL_DEFAULT, + ed_glob.ID_PREF_DLEXER, ed_glob.ID_HLCARET_LINE, + ed_glob.ID_PREF_AUTOCOMPEX): + + e_val = evt.EventObject.GetValue() + + # Update Profile + Profile_Set(ed_glob.ID_2_PROF[e_id], e_val) + + # Make ui adjustments + meth = None + args = list() + if e_id == ed_glob.ID_SHOW_EDGE: + spin = self.FindWindowById(ed_glob.ID_PREF_EDGE) + if spin is not None: + spin.Enable(e_val) + elif e_id == ed_glob.ID_AUTOCOMP: + cbox = self.FindWindowById(ed_glob.ID_PREF_AUTOCOMPEX) + if cbox is not None: + cbox.Enable(e_val) + elif e_id == ed_glob.ID_VI_MODE: + cbox = self.FindWindowById(ed_glob.ID_VI_NORMAL_DEFAULT) + if cbox is not None: + cbox.Enable(e_val) + else: + evt.Skip() + + @staticmethod + def OnSpin(evt): + """Catch actions from a slider + @param evt: wx.SpinEvent + + """ + e_id = evt.GetId() + if e_id == ed_glob.ID_PREF_EDGE: + val = evt.GetEventObject().GetValue() + Profile_Set(ed_glob.ID_2_PROF[e_id], val) + + for mainw in wx.GetApp().GetMainWindows(): + for stc in mainw.nb.GetTextControls(): + stc.SetEdgeColumn(val) + else: + evt.Skip() + +#----------------------------------------------------------------------------# + +class DocSyntaxPanel(wx.Panel): + """Document syntax config panel + @summary: Manages the configuration of the syntax highlighting + of the documents in the editor. + + """ + def __init__(self, parent): + """Inialize the config panel + @param parent: parent window of this panel + + """ + super(DocSyntaxPanel, self).__init__(parent) + + # Attributes + self._elist = ExtListCtrl(self) + self._elist.SetMinSize((425, 200)) + + # Layout page + self._DoLayout() + self.SetAutoLayout(True) + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_CHECKBOX, self.OnSynChange) + self.Bind(wx.EVT_CHOICE, self.OnSynChange) + + def _DoLayout(self): + """Layout all the controls + @note: Do not call this after __init__ + + """ + sizer = wx.BoxSizer(wx.VERTICAL) + + # Syntax Settings + syn_cb = wx.CheckBox(self, ed_glob.ID_SYNTAX, _("Syntax Highlighting")) + syn_cb.SetValue(Profile_Get('SYNTAX')) + ss_lst = util.GetResourceFiles(u'styles', get_all=True, title=False) + ss_lst = [sheet for sheet in ss_lst if not sheet.startswith('.')] + syntheme = ExChoice(self, ed_glob.ID_PREF_SYNTHEME, + choices=sorted(ss_lst), + default=Profile_Get('SYNTHEME', 'str')) + line = wx.StaticLine(self, size=(-1, 2)) + lsizer = wx.BoxSizer(wx.VERTICAL) + lsizer.Add(line, 0, wx.EXPAND) + lst_lbl = wx.StaticText(self, label=_("Filetype Associations") + u": ") + + # Layout the controls + hsizer = wx.BoxSizer(wx.HORIZONTAL) + hsizer.AddMany([(syn_cb, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 1, wx.EXPAND), + (wx.StaticText(self, label=_("Color Scheme") + u": "), + 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL), + (syntheme, 0, wx.EXPAND), ((5, 5), 0)]) + + sizer.AddMany([((15, 15), 0), (hsizer, 0, wx.EXPAND), + ((5, 5), 0), (lsizer, 0, wx.EXPAND), + ((15, 15), 0), (lst_lbl, 0, wx.ALIGN_LEFT)]) + + hsizer2 = wx.BoxSizer(wx.HORIZONTAL) + hsizer2.AddMany([((5, 5), 0), (self._elist, 1, wx.EXPAND), ((5, 5), 0)]) + + default_btn = wx.Button(self, wx.ID_DEFAULT, _("Revert to Default")) + if wx.Platform == '__WXMAC__': + default_btn.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + sizer.AddMany([((10, 10), 0), (hsizer2, 1, wx.EXPAND), ((15, 15), 0), + (default_btn, 0, wx.ALIGN_LEFT), ((10, 10), 0)]) + + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([((5, 5), 0), (sizer, 1, wx.EXPAND), ((5, 5), 0)]) + self.SetSizer(msizer) + + def OnButton(self, evt): + """Reset button handler + @param evt: Event that called this handler + + """ + if evt.GetId() == wx.ID_DEFAULT: + syntax.ExtensionRegister().LoadDefault() + self._elist.UpdateExtensions() + else: + evt.Skip() + + @staticmethod + def OnSynChange(evt): + """Handles the events from checkbox and choice control for this panel + @param evt: event that called this handler + @postcondition: all text controls are updated to reflect the changes + made in these controls. + + """ + e_id = evt.GetId() + e_obj = evt.GetEventObject() + if e_id in (ed_glob.ID_PREF_SYNTHEME, ed_glob.ID_SYNTAX): + Profile_Set(ed_glob.ID_2_PROF[e_id], e_obj.GetValue()) + else: + evt.Skip() + +#-----------------------------------------------------------------------------# + +class AppearancePanel(wx.Panel, PreferencesPanelBase): + """Creates a panel with controls for Editra's appearance settings + @summary: contains all the controls for configuring the appearance + related settings in Editra. + + """ + def __init__(self, parent, style=wx.BORDER_SUNKEN): + """Create the panel + @param parent: Parent window of this panel + @keyword style: Window Style bitmask + + """ + wx.Panel.__init__(self, parent, style=style) + PreferencesPanelBase.__init__(self) + + # Event Handlers + self.Bind(wx.EVT_CHECKBOX, self.OnCheck) + self.Bind(wx.EVT_CHOICE, self.OnChoice) + self.Bind(wx.EVT_SLIDER, self.OnSetTransparent, \ + id=ed_glob.ID_TRANSPARENCY) + self.Bind(eclib.EVT_FONT_CHANGED, self.OnFontChange) + + def _DoLayout(self): + """Add and layout the widgets + @note: Do not call this after __init__ + + """ + # Icons Section + from ed_theme import BitmapProvider + icons = ['Default'] + icons.extend(BitmapProvider(wx.GetApp().GetPluginManager()).GetThemes()) + iconsz = wx.BoxSizer(wx.HORIZONTAL) + iconsz.AddMany([(wx.StaticText(self, label=_("Icon Theme") + u": "), 0, + wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PREF_ICON, icons, + Profile_Get('ICONS', 'str').title()), 0)]) + tbiconsz = wx.BoxSizer(wx.HORIZONTAL) + tbiconsz.AddMany([(wx.StaticText(self, label=_("Toolbar Icon Size") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PREF_ICONSZ, + ['16', '24', '32'], + str(Profile_Get('ICON_SZ', 'size_tuple')[0])), 0)]) + tabicon_cb = wx.CheckBox(self, ed_glob.ID_PREF_TABICON, + _("Show Icons on Tabs")) + tabicon_cb.SetValue(Profile_Get('TABICONS')) + + # Layout Section + mainw = wx.GetApp().GetActiveWindow() + if mainw is not None: + pchoices = mainw.GetPerspectiveList() + else: + pchoices = list() + perspec_sz = wx.BoxSizer(wx.HORIZONTAL) + perspec_sz.AddMany([(wx.StaticText(self, + label=_("Default Perspective") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5), 0), + (ExChoice(self, ed_glob.ID_PERSPECTIVES, + pchoices, Profile_Get('DEFAULT_VIEW')), 0)]) + ws_cb = wx.CheckBox(self, ed_glob.ID_PREF_WSIZE, \ + _("Remember Window Size on Exit")) + ws_cb.SetValue(Profile_Get('SET_WSIZE')) + wp_cb = wx.CheckBox(self, ed_glob.ID_PREF_WPOS, \ + _("Remember Window Position on Exit")) + wp_cb.SetValue(Profile_Get('SET_WPOS')) + sb_cb = wx.CheckBox(self, ed_glob.ID_SHOW_SB, _("Show Status Bar")) + sb_cb.SetValue(Profile_Get('STATBAR')) + tb_cb = wx.CheckBox(self, ed_glob.ID_VIEW_TOOL, _("Show Toolbar")) + tb_cb.SetValue(Profile_Get('TOOLBAR')) + + # Font + fnt = Profile_Get('FONT3', 'font', wx.NORMAL_FONT) + fpick = eclib.PyFontPicker(self, wx.ID_ANY, fnt) + fpick.SetToolTipString(_("Main display font for various UI components")) + + # Layout + sizer = wx.FlexGridSizer(16, 2, 5, 5) + sizer.AddMany([((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("Icons") + u": "), 0, + wx.ALIGN_CENTER_VERTICAL), (iconsz, 0), + ((5, 5), 0), (tbiconsz, 0), + ((5, 5), 0), (tabicon_cb, 0), + ((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("Layout") + u": "), 0, + wx.ALIGN_CENTER_VERTICAL), + (perspec_sz, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0), (ws_cb, 0), + ((5, 5), 0), (wp_cb, 0), + ((5, 5), 0), (sb_cb, 0), + ((5, 5), 0), (tb_cb, 0), + ((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("Transparency") + u": "), 0), + (wx.Slider(self, ed_glob.ID_TRANSPARENCY, + Profile_Get('ALPHA'), 100, 255, + style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|\ + wx.SL_LABELS), 0, wx.EXPAND), + ((10, 10), 0), ((10, 10), 0), + (wx.StaticText(self, label=_("Display Font") + u": "), + 0, wx.ALIGN_CENTER_VERTICAL), + (fpick, 1, wx.EXPAND), + ((10, 10), 0), ((10, 10), 0), + ]) + + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([((10, 10), 0), (sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + + @staticmethod + def OnCheck(evt): + """Updates profile based on checkbox actions + @param evt: Event that called this handler + + """ + e_id = evt.GetId() + evalue = evt.GetEventObject().GetValue() + if e_id in (ed_glob.ID_PREF_WPOS, ed_glob.ID_PREF_WSIZE): + Profile_Set(ed_glob.ID_2_PROF[e_id], evalue) + elif e_id == ed_glob.ID_PREF_TABICON: + Profile_Set(ed_glob.ID_2_PROF[e_id], evalue) + ed_msg.PostMessage(ed_msg.EDMSG_THEME_NOTEBOOK) + elif e_id in (ed_glob.ID_SHOW_SB, ed_glob.ID_VIEW_TOOL): + Profile_Set(ed_glob.ID_2_PROF[e_id], evalue) + if e_id == ed_glob.ID_SHOW_SB: + fun = 'GetStatusBar' + else: + fun = 'GetToolBar' + + # Update Window(s) + for mainw in wx.GetApp().GetMainWindows(): + getattr(mainw, fun)().Show(evalue) + mainw.SendSizeEvent() + else: + evt.Skip() + + @staticmethod + def OnChoice(evt): + """Handles selection events from the choice controls + @param evt: Event that called this handler + + """ + e_id = evt.GetId() + e_obj = evt.GetEventObject() + val = e_obj.GetValue() + if e_id in [ed_glob.ID_PREF_ICON, ed_glob.ID_PREF_ICONSZ]: + if e_id == ed_glob.ID_PREF_ICONSZ: + val = (int(val), int(val)) + Profile_Set(ed_glob.ID_2_PROF[e_id], val) + wx.GetApp().ReloadArtProvider() + ed_msg.PostMessage(ed_msg.EDMSG_THEME_CHANGED, True) + elif e_id == ed_glob.ID_PERSPECTIVES: + Profile_Set('DEFAULT_VIEW', val) + for main_win in wx.GetApp().GetMainWindows(): + main_win.SetPerspective(Profile_Get('DEFAULT_VIEW')) + else: + evt.Skip() + + @staticmethod + def OnFontChange(evt): + """Send out update messages fo rdisplay font changes""" + font = evt.GetValue() + if isinstance(font, wx.Font) and not font.IsNull(): + Profile_Set('FONT3', font, 'font') + ed_msg.PostMessage(ed_msg.EDMSG_DSP_FONT, font) + + @staticmethod + def OnSetTransparent(evt): + """Sets the transparency of the editor while the slider + is being dragged. + @param evt: Event that called this handler + + """ + if evt.GetId() == ed_glob.ID_TRANSPARENCY: + value = evt.GetEventObject().GetValue() + for window in wx.GetApp().GetOpenWindows().values(): + win = window[0] + if hasattr(win, 'SetTransparent'): + win.SetTransparent(value) + Profile_Set('ALPHA', value) + else: + evt.Skip() + +#-----------------------------------------------------------------------------# + +class NetworkPanel(wx.Panel, PreferencesPanelBase): + """Network related configration options""" + def __init__(self, parent, style=wx.BORDER_SUNKEN): + """Create the panel""" + wx.Panel.__init__(self, parent, style=style) + PreferencesPanelBase.__init__(self) + + def _DoLayout(self): + """Do the layout of the panel + @note: Do not call this after __init__ + + """ + sizer = wx.BoxSizer(wx.HORIZONTAL) + nbook = wx.Notebook(self) + nbook.AddPage(NetConfigPage(nbook), _("Configuration")) + + # Only show update page if user has access to do installs + if os.access(ed_glob.CONFIG['INSTALL_DIR'], os.R_OK|os.W_OK): + nbook.AddPage(UpdatePage(nbook), _("Update")) + + sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)]) + msizer = wx.BoxSizer(wx.VERTICAL) + msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + +#-----------------------------------------------------------------------------# + +ID_USE_PROXY = wx.NewId() +ID_URL = wx.NewId() +ID_PORT = wx.NewId() +ID_USERNAME = wx.NewId() +ID_PASSWORD = wx.NewId() + +class NetConfigPage(wx.Panel): + """Configuration page for network and proxy settings""" + def __init__(self, parent): + super(NetConfigPage, self).__init__(parent) + + # Layout + self._DoLayout() + self.SetAutoLayout(True) + + # Event Handlers + self.Bind(wx.EVT_CHECKBOX, self.OnCheck, id=ID_USE_PROXY) + self.Bind(wx.EVT_BUTTON, self.OnApply, id=wx.ID_APPLY) + + def _DoLayout(self): + """Layout the controls in the panel""" + msizer = wx.BoxSizer(wx.VERTICAL) + + sboxsz = wx.StaticBoxSizer(wx.StaticBox(self, + label=_("Proxy Settings")), wx.VERTICAL) + flexg = wx.FlexGridSizer(4, 2, 10, 5) + flexg.AddGrowableCol(1, 1) + + proxy_val = Profile_Get('PROXY_SETTINGS', default=dict()) + use_proxy = wx.CheckBox(self, ID_USE_PROXY, _("Use Proxy")) + use_proxy.SetValue(Profile_Get('USE_PROXY', 'bool', False)) + sboxsz.AddMany([(use_proxy, 0, wx.ALIGN_LEFT), ((10, 10), 0)]) + + url_sz = wx.BoxSizer(wx.HORIZONTAL) + url_lbl = wx.StaticText(self, label=_("Proxy URL") + u":") + url_txt = wx.TextCtrl(self, ID_URL, proxy_val.get('url', '')) + port_sep = wx.StaticText(self, label=":") + port_txt = wx.TextCtrl(self, ID_PORT, proxy_val.get('port', '')) + port_txt.SetToolTipString(_("Port Number")) + url_sz.AddMany([(url_txt, 1, wx.EXPAND), ((2, 2)), + (port_sep, 0, wx.ALIGN_CENTER_VERTICAL), + ((2, 2)), (port_txt, 0, wx.ALIGN_CENTER_VERTICAL)]) + flexg.AddMany([(url_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + (url_sz, 0, wx.EXPAND)]) + + usr_sz = wx.BoxSizer(wx.HORIZONTAL) + usr_lbl = wx.StaticText(self, label=_("Username") + u":") + usr_txt = wx.TextCtrl(self, ID_USERNAME, proxy_val.get('uname', '')) + usr_sz.Add(usr_txt, 1, wx.EXPAND) + flexg.AddMany([(usr_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + (usr_sz, 0, wx.EXPAND)]) + + pass_sz = wx.BoxSizer(wx.HORIZONTAL) + pass_lbl = wx.StaticText(self, label=_("Password") + u":") + pass_txt = wx.TextCtrl(self, ID_PASSWORD, + ed_crypt.Decrypt(proxy_val.get('passwd', ''), + proxy_val.get('pid', '')), + style=wx.TE_PASSWORD) + pass_sz.Add(pass_txt, 1, wx.EXPAND) + flexg.AddMany([(pass_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + (pass_sz, 0, wx.EXPAND), ((5, 5), 0)]) + + apply_b = wx.Button(self, wx.ID_APPLY) + flexg.Add(apply_b, 0, wx.ALIGN_RIGHT) + + if wx.Platform == '__WXMAC__': + for lbl in (use_proxy, url_txt, port_sep, port_txt, url_lbl, + usr_lbl, usr_txt, pass_lbl, pass_txt, apply_b): + lbl.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + + self.EnableControls(use_proxy.GetValue()) + sboxsz.Add(flexg, 1, wx.EXPAND) + hsizer = wx.BoxSizer(wx.HORIZONTAL) + hsizer.AddMany([((5, 5)), (sboxsz, 1, wx.EXPAND), ((5, 5))]) + msizer.AddMany([((10, 10)), (hsizer, 1, wx.EXPAND), ((10, 10))]) + self.SetSizer(msizer) + + def OnApply(self, evt): + """Apply the changes to the proxy settings + @param evt: wx.EVT_BUTTON + + """ + if evt.GetId() == wx.ID_APPLY: + key_map = { ID_USERNAME : 'uname', ID_URL : 'url', + ID_PORT : 'port', ID_PASSWORD : 'passwd' } + proxy_dict = dict(uname='', passwd='', url='', port='') + for val in (ID_URL, ID_PORT, ID_USERNAME, ID_PASSWORD): + win = self.FindWindowById(val) + if win is not None: + winval = win.GetValue() + if val == ID_PASSWORD: + # This is not the most secure method of saving a + # sensitive data but it is definitely better than plain + # text. ALso as to be able to obtain this info from the + # user profile the intruder would already have had to + # compromise the users system account making anymore + # such security rather moot by this point anyway. + pid = os.urandom(8) + winval = ed_crypt.Encrypt(winval, pid) + proxy_dict['pid'] = pid + proxy_dict[key_map[val]] = winval + + Profile_Set('PROXY_SETTINGS', proxy_dict) + else: + evt.Skip() + + def EnableControls(self, enable=True): + """Enable the controls in the box or disable them + @keyword enable: Enable or Disable + + """ + for child in self.GetChildren(): + if isinstance(child, wx.StaticText) or \ + isinstance(child, wx.TextCtrl) or \ + isinstance(child, wx.Button): + child.Enable(enable) + + def OnCheck(self, evt): + """Enable the use of the proxy settings or not + @param evt: wx.EVT_CHECKBOX + + """ + e_val = evt.GetEventObject().GetValue() + Profile_Set('USE_PROXY', e_val) + self.EnableControls(e_val) + +#-----------------------------------------------------------------------------# + +class UpdatePage(wx.Panel): + """Creates a panel with controls for updating Editra + @summary: Panel with controls to check and download updates for Editra + + """ + def __init__(self, parent): + """Create the panel + @param parent: Parent window of this panel + + """ + super(UpdatePage, self).__init__(parent) + + # Layout + self._DoLayout() + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(ed_event.EVT_UPDATE_TEXT, self.OnUpdateText) + + def _DoLayout(self): + """Do the layout of the panel + @note: Do not call this after __init__ + + """ + # Status text and bar + cur_box = wx.StaticBox(self, label=_("Installed Version")) + cur_sz = wx.StaticBoxSizer(cur_box, wx.HORIZONTAL) + cur_sz.SetMinSize(wx.Size(150, 40)) + cur_ver = wx.StaticText(self, wx.ID_ANY, ed_glob.VERSION) + cur_sz.Add(cur_ver, 0, wx.ALIGN_CENTER_HORIZONTAL) + e_update = updater.UpdateProgress(self, ed_glob.ID_PREF_UPDATE_BAR) + upd_box = wx.StaticBox(self, label=_("Latest Version")) + upd_bsz = wx.StaticBoxSizer(upd_box, wx.HORIZONTAL) + upd_bsz.SetMinSize(wx.Size(150, 40)) + upd_bsz.Add(wx.StaticText(self, ID_UPDATE_MSG, _("Status Unknown")), + 0, wx.ALIGN_CENTER_HORIZONTAL) + upd_bsz.Layout() + + # Layout Controls + statsz = wx.BoxSizer(wx.HORIZONTAL) + statsz.AddMany([((15, 15), 0), (cur_sz, 0), ((20, 10), 1), + (upd_bsz, 0), ((15, 15), 0)]) + + # Control buttons + dl_b = wx.Button(self, ID_DOWNLOAD, _("Download")) + dl_b.Disable() + + bsizer = wx.BoxSizer(wx.HORIZONTAL) + bsizer.AddStretchSpacer() + bsizer.Add(wx.Button(self, ID_CHECK_UPDATE, _("Check")), + 0, wx.ALIGN_LEFT) + bsizer.AddStretchSpacer(2) + bsizer.Add(dl_b, 0, wx.ALIGN_RIGHT) + bsizer.AddStretchSpacer() + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.AddMany([((15, 15), 1), (statsz, 0, wx.EXPAND), ((15, 15), 0), + (e_update, 0, wx.EXPAND), ((15, 15), 0), + (bsizer, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL), + ((15, 15), 1)]) + + msizer = wx.BoxSizer(wx.HORIZONTAL) + msizer.AddMany([((5, 5), 0), (sizer, 1, wx.EXPAND), ((5, 5), 0)]) + self.SetSizer(msizer) + + def OnButton(self, evt): + """Handles events generated by the panels buttons + @param evt: event that called this handler + + """ + e_id = evt.GetId() + e_obj = evt.GetEventObject() + if e_id == ID_CHECK_UPDATE: + util.Log("[prefdlg][evt] Update Page: Check Update Clicked") + e_obj.Disable() + self.FindWindowById(ID_UPDATE_MSG).SetLabel(_("Checking...")) + prog_bar = self.FindWindowById(ed_glob.ID_PREF_UPDATE_BAR) + # Note this function returns right away but its result is + # handled on a separate thread. This window is then notified + # via a custom event being posted by the control. + prog_bar.CheckForUpdates() + elif e_id == ID_DOWNLOAD: + util.Log("[prefdlg][evt] Update Page: Download Updates Clicked") + e_obj.Disable() + self.FindWindowById(ID_CHECK_UPDATE).Disable() + dl_dlg = updater.DownloadDialog(None, ed_glob.ID_DOWNLOAD_DLG, + _("Downloading Update")) + dp_sz = wx.GetDisplaySize() + dl_dlg.SetPosition(((dp_sz[0] - (dl_dlg.GetSize()[0] + 5)), 25)) + dl_dlg.Show() + else: + evt.Skip() + + def OnUpdateText(self, evt): + """Handles text update events""" + util.Log("[prefdlg][evt] Update Page: Updating version status text") + upd = self.FindWindowById(ed_glob.ID_PREF_UPDATE_BAR) + if evt.GetId() == upd.ID_CHECKING: + self.FindWindowById(ID_UPDATE_MSG).SetLabel(upd.GetStatus()) + if upd.GetUpdatesAvailable(): + self.FindWindowById(ID_DOWNLOAD).Enable() + self.FindWindowById(ID_CHECK_UPDATE).Enable() + self.Layout() + + # Trick the notebook into resizing to ensure everything fits + curr_pg = self.GetParent().GetSelection() + nbevt = wx.NotebookEvent(wx.wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED, + 0, curr_pg, curr_pg) + wx.PostEvent(self.GetParent(), nbevt) + gauge = self.FindWindowById(ed_glob.ID_PREF_UPDATE_BAR) + if gauge: + gauge.Stop() + gauge.SetValue(100) + self.Refresh() + +#-----------------------------------------------------------------------------# +# Advanced Page + +class AdvancedPanel(wx.Panel): + """Creates a panel for holding advanced configuration options + @summary: Contains a wx.Notebook that contains a number of pages with + setting controls for configuring the advanced configuration + options. + + """ + def __init__(self, parent, style=wx.BORDER_SUNKEN): + """Create the panel + @param parent: Parent window of this panel + @keyword style: Window Style bitmask + + """ + super(AdvancedPanel, self).__init__(parent, style=style) + + # Layout + self._layout_done = False + + def _DoLayout(self): + """Do the layout of the panel + @note: Do not call this after __init__ + + """ + sizer = wx.BoxSizer(wx.HORIZONTAL) + nbook = wx.Notebook(self) + nbook.AddPage(KeyBindingPanel(nbook), _("Keybindings")) + sizer.AddMany([((10, 10), 0), (nbook, 1, wx.EXPAND), ((10, 10), 0)]) + msizer = wx.BoxSizer(wx.VERTICAL) + msizer.AddMany([(sizer, 1, wx.EXPAND), ((10, 10), 0)]) + self.SetSizer(msizer) + + def DoSelected(self): + """Handle initial selection to create controls""" + if not self._layout_done: + self._layout_done = True + self._DoLayout() + self.SetAutoLayout(True) + +#-----------------------------------------------------------------------------# +# Keybinding Panel + +ID_MENUS = wx.NewId() +ID_MENU_ITEMS = wx.NewId() +ID_MOD1 = wx.NewId() +ID_MOD2 = wx.NewId() +ID_KEYS = wx.NewId() +ID_BINDING = wx.NewId() +KEYS = ['', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '/', ',', + '.', '[', ']', '{', '}', '>', '<', ':', '|', 'Left', 'Right', 'Down', + 'Up', 'Home', 'End', 'Enter', 'Tab', 'Space', '"', "'"] +KEYS.extend(["F" + str(x) for x in range(1, 13)]) # Add function keys + +if wx.Platform == '__WXMSW__': + KEYS.remove('Tab') + +MODIFIERS = ['', 'Alt', 'Shift'] +if wx.Platform == '__WXMAC__': + MODIFIERS.append('Cmd') +else: + MODIFIERS.append('Ctrl') +MODIFIERS.sort() + +class KeyBindingPanel(wx.Panel): + """Keybinding configuration options""" + def __init__(self, parent): + """Create the panel""" + super(KeyBindingPanel, self).__init__(parent) + + # Attributes + self._dirty = False + self.menub = wx.GetApp().GetActiveWindow().GetMenuBar() + self.binder = ed_menu.KeyBinder() + self.menumap = dict() + + # Load the Menu Map + for item in self.menub.GetMenuMap(): + for key, val in item.iteritems(): + if len(val): + if isinstance(val[0], int): + val = val[1:] + self.menumap[key] = sorted(val, key=lambda x: x[1]) + + # Layout + self._DoLayout() + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_CHOICE, self.OnChoice) + self.Bind(wx.EVT_LISTBOX, self.OnListBox) + self.Bind(wx.EVT_UPDATE_UI, + lambda evt: evt.Enable(self.Dirty), + id=wx.ID_APPLY) + + def _DoLayout(self): + """Layout the controls""" + msizer = wx.BoxSizer(wx.VERTICAL) # Main Sizer + spacer = ((5, 5), 0) + + # Key profile section + profsz = wx.BoxSizer(wx.HORIZONTAL) + kprofiles = self.binder.GetKeyProfiles() + # Add an empty selection for the default profile + if len(kprofiles): + kprofiles.insert(0, u'') + cprofile = Profile_Get('KEY_PROFILE', default=None) + profiles = wx.Choice(self, ed_glob.ID_KEY_PROFILES, choices=kprofiles) + profiles.Enable(len(kprofiles)) + if cprofile is None: + profiles.SetStringSelection(u'') + else: + profiles.SetStringSelection(cprofile) + profsz.AddMany([spacer, + (wx.StaticText(self, label=_("Key Profile") + u":"), + 0, wx.ALIGN_CENTER_VERTICAL), spacer, + (profiles, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL), + spacer, (wx.Button(self, wx.ID_NEW, _("New")), 0), + spacer, (wx.Button(self, wx.ID_DELETE, _("Delete")), 0), + spacer]) + + # Left Side Sizer + lvsizer = wx.BoxSizer(wx.VERTICAL) + menus = wx.Choice(self, ID_MENUS, choices=sorted(self.menumap.keys())) + menus.SetSelection(0) + milbls = [ item[1] + for item in self.menumap.get(menus.GetStringSelection()) ] + lvsizer.AddMany([(wx.StaticText(self, label=_("Menu") + u":"), + 0, wx.ALIGN_LEFT), spacer, + (menus, 0, wx.ALIGN_LEFT|wx.EXPAND), spacer, + (wx.ListBox(self, ID_MENU_ITEMS, + choices=sorted(milbls), + style=wx.SIMPLE_BORDER), 1, wx.EXPAND), + spacer]) + + # Right Side Sizer + rvsizer = wx.BoxSizer(wx.VERTICAL) + rvsizer.AddMany([(wx.StaticText(self, label=_("Modifier 1") + u":"), + 0, wx.ALIGN_LEFT), spacer, + (wx.Choice(self, ID_MOD1, choices=MODIFIERS), + 0, wx.ALIGN_LEFT|wx.EXPAND), spacer, + (wx.StaticText(self, label=_("Modifier 2") + u":"), + 0, wx.ALIGN_LEFT), spacer, + (wx.Choice(self, ID_MOD2, choices=[]), + 0, wx.ALIGN_LEFT|wx.EXPAND), spacer, + (wx.StaticText(self, label=_("Key") + u":"), + 0, wx.ALIGN_LEFT), spacer, + (wx.Choice(self, ID_KEYS, choices=KEYS), + 0, wx.ALIGN_LEFT|wx.EXPAND), spacer, + (wx.StaticText(self, label=_("Binding") + u":"), + 0, wx.ALIGN_LEFT), spacer, + (wx.StaticText(self, ID_BINDING, ""), + 0, wx.ALIGN_LEFT), + # Reserve size for widest string + ((self.GetTextExtent('Ctrl+Shift+Right')[0], 1), 0), + ]) + + # Lower Section + lmsizer = wx.BoxSizer(wx.HORIZONTAL) + lmsizer.AddMany([spacer, (lvsizer, 1, wx.EXPAND), ((10, 10), 0), + (rvsizer, 0, wx.EXPAND), spacer]) + + # Main Layout + line_sz = wx.BoxSizer(wx.HORIZONTAL) + line_sz.AddMany([(5, 1), + (wx.StaticLine(self, size=(-1, 1)), 1, wx.EXPAND), + (5, 1)]) + line_sz2 = wx.BoxSizer(wx.HORIZONTAL) + line_sz2.AddMany([(5, 1), + (wx.StaticLine(self, size=(-1, 1)), 1, wx.EXPAND), + (5, 1)]) + bsizer = wx.BoxSizer(wx.HORIZONTAL) + bsizer.AddMany([spacer, (wx.Button(self, wx.ID_REVERT, + _("Revert to Default")), 0, wx.ALIGN_LEFT), + ((-1, 5), 1, wx.EXPAND), + (wx.Button(self, wx.ID_APPLY, _("Apply")), + 0, wx.ALIGN_RIGHT), spacer]) + msizer.AddMany([((10, 10), 0), (profsz, 0, wx.EXPAND), spacer, + (line_sz, 0, wx.EXPAND), spacer, + (lmsizer, 1, wx.EXPAND), ((10, 10), 0), + (line_sz2, 0, wx.EXPAND), spacer, + (bsizer, 0, wx.EXPAND), spacer]) + + # Use the small buttons on mac + if wx.Platform == '__WXMAC__': + for item in (wx.ID_REVERT, wx.ID_APPLY): + self.FindWindowById(item).SetWindowVariant(wx.WINDOW_VARIANT_SMALL) + + self.SetSizer(msizer) + + # Setup control status + self.ClearKeyView() + self.EnableControls(len(profiles.GetStringSelection())) + + def _GetMenuId(self): + """Get the id of the currently selected menu item + @return: int or None + + """ + sel_idx = self.FindWindowById(ID_MENU_ITEMS).GetSelection() + cmenu = self.FindWindowById(ID_MENUS).GetStringSelection() + menu_id = self.menumap.get(cmenu)[sel_idx][0] + return menu_id + + def _UpdateBinding(self): + """Update the current keybinding and its display""" + binding = self.FindWindowById(ID_BINDING) # StaticText + bvalue = self.GetBindingValue() + bstr = u"+".join(bvalue) + if not len(bstr): + bstr = _("None") + binding.SetLabel(bstr) + + def _UpdateKeyDisplay(self, keys): + """Update the controls that show the key binding of the current + menu item. + @param keys: tuple of keys + + """ + mod1 = self.FindWindowById(ID_MOD1) # Choice + mod1.SetItems(MODIFIERS) + mod2 = self.FindWindowById(ID_MOD2) # Choice + mod2.Enable() + key = self.FindWindowById(ID_KEYS) # Choice + + if keys is None: + keys = ('') + + # Change the main meta key for display reasons to keep it from + # being confused with the actual ctrl key since wx translates ctrl + # to apple key (cmd) automatically. + if wx.Platform == '__WXMAC__' and len(keys) and 'Ctrl' in keys: + nkeys = list() + for keystr in keys: + if keystr == 'Ctrl': + nkeys.append('Cmd') + else: + nkeys.append(keystr) + keys = nkeys + + if len(keys) >= 3: + mod1.SetStringSelection(keys[0]) + tmods = list(MODIFIERS) + tmods.remove(keys[0]) + mod2.SetItems(tmods) + mod2.SetStringSelection(keys[1]) + key.SetStringSelection(keys[2]) + elif len(keys) == 2: + mod1.SetStringSelection(keys[0]) + tmods = list(MODIFIERS) + tmods.remove(keys[0]) + mod2.SetItems(tmods) + mod2.SetStringSelection('') + key.SetStringSelection(keys[1]) + elif len(keys) == 1 and keys[0] in KEYS: + self.ClearKeyView() + key.SetStringSelection(keys[0]) + else: + self.ClearKeyView() + + self._UpdateBinding() + + #---- Properties ----# + + Dirty = property(lambda self: self._dirty, + lambda self, bDirty: setattr(self, '_dirty', bDirty)) + + def ClearKeyView(self): + """Clear all selections in the keybinding controls""" + self.FindWindowById(ID_MOD1).SetStringSelection('') + mod2 = self.FindWindowById(ID_MOD2) # Choice + mod2.Clear() + mod2.Disable() + self.FindWindowById(ID_KEYS).SetStringSelection('') + self._UpdateBinding() + + def EnableControls(self, enable=True): + """Enable/Disable the controls for editing the keybinding settings + @keyword enable: enable (True), disable (False) + + """ + for ctrl in (ID_MENUS, ID_MENU_ITEMS, + wx.ID_APPLY, wx.ID_REVERT, wx.ID_DELETE): + self.FindWindowById(ctrl).Enable(enable) + + self.EnableKeyView(enable) + + def EnableKeyView(self, enable=True): + """Enable/Disable the key view/edit controls + @keyword enable: enable (True), disable (False) + + """ + for ctrl in (ID_MOD1, ID_MOD2, ID_KEYS, ID_BINDING): + self.FindWindowById(ctrl).Enable(enable) + + def GetBindingValue(self): + """Get the values of the keybindings selected in the choice controls + @return: list + + """ + rval = list() + for cid in (ID_MOD1, ID_MOD2, ID_KEYS): + val = self.FindWindowById(cid).GetStringSelection() + if len(val): + rval.append(val) + return rval + + def OnButton(self, evt): + """Handle button events + @param evt: wx.CommandEvent + + """ + e_id = evt.GetId() + profiles = self.FindWindowById(ed_glob.ID_KEY_PROFILES) + csel = profiles.GetStringSelection() + if e_id == wx.ID_NEW: + dlg = wx.TextEntryDialog(self, _("New Profile"), + _("Enter the name of the new key profile")) + dlg.ShowModal() + val = dlg.GetValue() + if len(val): + choices = profiles.GetItems() + ['', val] + profiles.SetItems(sorted(list(set(choices)))) + profiles.SetStringSelection(val) + self.menub.NewKeyProfile(val) + profiles.Enable(len(profiles.GetItems())) + self.EnableControls(len(profiles.GetItems())) + elif e_id == wx.ID_DELETE: + val = profiles.GetStringSelection() + if val: + # Remove the selected profile + items = profiles.GetItems() + items.remove(val) + self.menub.DeleteKeyProfile(val) + if len(items) == 1 and items[0] == '': + items = list() + + profiles.SetItems(items) + profiles.Enable(len(items)) + if len(items): + profiles.SetSelection(0) + + self.EnableControls(len(profiles.GetItems())) + csel = profiles.GetStringSelection() + if csel: + Profile_Set('KEY_PROFILE', csel) + else: + Profile_Set('KEY_PROFILE', None) # Use defaults + ed_msg.PostMessage(ed_msg.EDMSG_MENU_LOADPROFILE, + Profile_Get('KEY_PROFILE', default=None)) + elif e_id == wx.ID_REVERT: + # Revert to the original settings + Profile_Set('KEY_PROFILE', None) + ed_msg.PostMessage(ed_msg.EDMSG_MENU_LOADPROFILE, None) + self.menub.SaveKeyProfile() + self.FindWindowById(ed_glob.ID_KEY_PROFILES).SetStringSelection('') + self.EnableControls(False) + elif e_id == wx.ID_APPLY: + # Update the menu(s) to the new settings + profiles = self.FindWindowById(ed_glob.ID_KEY_PROFILES) + csel = profiles.GetStringSelection() + if not len(csel): + csel = None + Profile_Set('KEY_PROFILE', csel) + ed_msg.PostMessage(ed_msg.EDMSG_MENU_REBIND) + self.menub.SaveKeyProfile() + else: + evt.Skip() + + def OnChoice(self, evt): + """Handle selections in the choice controls + @param evt: wx.CommandEvent + + """ + e_id = evt.GetId() + csel = evt.GetEventObject().GetStringSelection() + if e_id == ed_glob.ID_KEY_PROFILES: + if not len(csel): + csel = None + self.binder.LoadKeyProfile(csel) + Profile_Set('KEY_PROFILE', csel) + ed_msg.PostMessage(ed_msg.EDMSG_MENU_REBIND) + self.menub.SaveKeyProfile() + self.EnableControls(csel is not None) + elif e_id == ID_MENUS: + mi_listbx = self.FindWindowById(ID_MENU_ITEMS) + if mi_listbx is not None: + mi_listbx.SetItems([item[1] for item in self.menumap.get(csel)]) + self.ClearKeyView() + elif e_id == ID_MOD1: + mod2 = self.FindWindowById(ID_MOD2) + if not len(csel): + mod2.Clear() + mod2.Disable() + else: + mod2.Enable() + tmods = list(MODIFIERS) + tmods.remove(csel) + mod2.SetItems(tmods) + mod2.SetStringSelection('') + self._UpdateBinding() + self.Dirty = True + elif e_id in [ID_MOD2, ID_KEYS]: + self._UpdateBinding() + self.Dirty = True + else: + evt.Skip() + + # Update the keybinding + if e_id in (ID_MOD1, ID_MOD2, ID_KEYS): + bval = u"+".join(self.GetBindingValue()) + bval = bval.replace('Cmd', 'Ctrl', 1) + self.binder.SetBinding(self._GetMenuId(), bval) + + def OnListBox(self, evt): + """Handle listbox selections and update binding display + @param evt: wx.CommandEvent + + """ + if evt.GetId() == ID_MENU_ITEMS: + sel_idx = evt.GetSelection() + cmenu = self.FindWindowById(ID_MENUS).GetStringSelection() + menu_id = self.menumap.get(cmenu)[sel_idx][0] + keys = self.binder.GetRawBinding(menu_id) + self._UpdateKeyDisplay(keys) + else: + evt.Skip() + +#----------------------------------------------------------------------------# + +class ExtListCtrl(eclib.EEditListCtrl): + """Class to manage the file extension associations + @summary: Creates a list control for showing file type to file extension + associations as well as providing an interface to editing these + associations + + """ + FILE_COL = 0 + EXT_COL = 1 + def __init__(self, parent): + """Initializes the Profile List Control + @param parent: The parent window of this control + + """ + super(ExtListCtrl, self).__init__(parent) + +# listmix.ListCtrlAutoWidthMixin.__init__(self) +# eclib.ListRowHighlighter.__init__(self) + + # Setup + self.InsertColumn(ExtListCtrl.FILE_COL, _("Lexer")) + self.InsertColumn(ExtListCtrl.EXT_COL, \ + _("Extensions (space separated, no dots)")) + self._extreg = syntax.ExtensionRegister() + self._editing = None + self.LoadList() +# listmix.TextEditMixin.__init__(self) + + def CloseEditor(self, evt=None): + """Update list and extension register after edit window + closes. + @keyword evt: Action that triggered this function + + """ + super(ExtListCtrl, self).CloseEditor(evt) + def UpdateRegister(itempos): + """Update the ExtensionRegister + @param itempos: position of the item to base updates on + + """ + vals = self.GetItem(itempos[1], itempos[0]).GetText() + ftype = self.GetItem(itempos[1], ExtListCtrl.FILE_COL).GetText() + self._editing = None + self._extreg.SetAssociation(ftype, vals) + + if self._editing != None: + wx.CallAfter(UpdateRegister, self._editing) + wx.CallAfter(self.UpdateExtensions) + + def LoadList(self): + """Loads the list of filetypes to file extension mappings into the + list control. + @postcondition: The running configuration data that is kept by the + syntax manager that relates to file associations is + loaded into the list control in alphabetical order + + """ + for key in sorted(self._extreg.keys()): + index = self.InsertStringItem(sys.maxint, key) + self.SetStringItem(index, ExtListCtrl.FILE_COL, key) + self.SetStringItem(index, ExtListCtrl.EXT_COL, \ + u' %s' % u' '.join(self._extreg[key])) + + self.SetColumnWidth(ExtListCtrl.FILE_COL, wx.LIST_AUTOSIZE) + self.SetColumnWidth(ExtListCtrl.EXT_COL, wx.LIST_AUTOSIZE) + + def OpenEditor(self, col, row): + """Disable the editor for the first column + @param col: Column to edit + @param row: Row to edit + + """ + if col != self.FILE_COL: + self._editing = (col, row) + super(ExtListCtrl, self).OpenEditor(col, row) + + def UpdateExtensions(self): + """Updates the values in the EXT_COL to reflect changes + in the ExtensionRegister. + @postcondition: Any configuration changes made in the control are + set in the Extension register. + @see: L{syntax.syntax.ExtensionRegister} + + """ + for row in range(self.GetItemCount()): + ftype = self.GetItem(row, ExtListCtrl.FILE_COL).GetText() + self.SetStringItem(row, ExtListCtrl.EXT_COL, \ + u' ' + u' '.join(self._extreg[ftype])) + +#----------------------------------------------------------------------------# + +class ExChoice(wx.Choice): + """Class to extend wx.Choice to have the GetValue + function. This allows the application function to remain + uniform in its value retrieval from all objects. This also extends + wx.Choice to have a default selected value on init. + + """ + def __init__(self, parent, cid=wx.ID_ANY, choices=list(), default=None): + """Constructs a Choice Control + @param parent: The parent window of this control + + """ + if len(choices) and isinstance(choices[0], int): + choices = [ unicode(choice) for choice in choices ] + + super(ExChoice, self).__init__(parent, cid, choices=choices) + + if default != None and isinstance(default, basestring): + self.SetStringSelection(default) + elif default is not None: + self.SetSelection(default) + + def GetValue(self): + """Gets the Selected Value + @return: the value of the currently selected item + @rtype: string + + """ + val = self.GetStringSelection() + if val.isalpha(): + val.lower() + return val + +#-----------------------------------------------------------------------------# +# Utility Functions + +def GetPrintModeStrings(): + """Get the strings for describing the print modes + @note: defined in a function so translations can take place at runtime + @note: Order must be kept in sync with the PRINT_ vals in ed_glob + + """ + return [_('Black/White'), # PRINT_BLACK_WHITE + _('Colour/White'), # PRINT_COLOR_WHITE + _('Colour/Default'), # PRINT_COLOR_DEF + _('Inverse'), # PRINT_INVERSE + _('Normal')] # PRINT_NORMAL diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/profiler.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/profiler.py new file mode 100644 index 0000000..68127e5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/profiler.py @@ -0,0 +1,456 @@ +############################################################################### +# Name: profiler.py # +# Purpose: Editra's user profile services # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This module provides the profile object and support functions for loading and +saving user preferences between sessions. The preferences are saved on disk as +a cPickle, because of this no objects that cannot be resolved in the namespace +of this module prior to starting the mainloop must not be put in the Profile as +it will cause errors on load. Ths means that only builtin python types should +be used and that a translation from that type to the required type should +happen during run time. + +@summary: Editra's user profile management + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: profiler.py 71278 2012-04-25 15:47:19Z CJP $" +__revision__ = "$Revision: 71278 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import sys +import cPickle +import wx + +# Editra Imports +from ed_glob import CONFIG, PROG_NAME, VERSION, PRINT_BLACK_WHITE, EOL_MODE_LF +import util +import dev_tool +import ed_msg + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# +# Globals +_DEFAULTS = { + 'ALPHA' : 255, # Transparency level (0-255) + 'AALIASING' : False, # Use Anti-Aliasing if availble + 'APPSPLASH' : True, # Show splash at startup + 'AUTOBACKUP' : False, # Automatically backup files + 'AUTOBACKUP_PATH' : '', # Backup path + 'AUTOBACKUP_SUFFIX' : '.edbkup', # Backup suffix (e.g. .edbkup, ~) + 'AUTO_COMP' : True, # Use Auto-comp if available + 'AUTO_COMP_EX' : False, # Use extended autocompletion + 'AUTO_INDENT': True, # Use Auto Indent + 'AUTO_TRIM_WS' : False, # Trim whitespace on save + 'AUTO_RELOAD' : False, # Automatically reload files? + 'BRACKETHL' : True, # Use bracket highlighting + 'BSUNINDENT' : True, # Backspace Unindents + 'CARETWIDTH' : 1, # Preferred cursor width + 'CHECKMOD' : True, # Auto check file for file mod + 'CHECKUPDATE': True, # Check for updates on start + 'CODE_FOLD' : True, # Use code folding + 'CTRLBAR' : dict(), # ControlBar layouts + 'DEFAULT_LEX': 'Plain Text', # Default lexer for new documents + 'DEFAULT' : False, # No longer used I believe + 'DEFAULT_VIEW' : 'Automatic', # Default Perspective + 'EDGE' : 80, # Edge guide column + 'ENCODING' : None, # Prefered text encoding + 'EOL_MODE' : EOL_MODE_LF, # EOL mode 1 == LF, 2 == CRLF + 'FHIST' : list(), # List of history files + 'FHIST_LVL' : 9, # Filehistory length (9 is max) + 'FFILTER' : 0, # Last file filter used + 'GUIDES' : False, # Use Indentation guides + 'HLCARETLINE': False, # Highlight Caret Line + 'ICONS' : 'Tango', # Icon Theme + 'ICON_SZ' : (16, 16), # Toolbar Icon Size + 'INDENTWIDTH': 4, # Default indent width + 'ISBINARY' : False, # Is this instance a binary + 'KEY_PROFILE': None, # Keybinding profile + 'LANG' : 'Default', # UI language + 'LASTCHECK' : 0, # Last time update check was done + #'LEXERMENU' : [lang_name,] # Created on an as needed basis + 'MAXIMIZED' : False, # Was window maximized on exit + 'MODE' : 'CODE', # Overall editor mode + 'MYPROFILE' : 'default.ppb', # Path to profile file + 'OPEN_NW' : False, # Open files in new windows + 'PRINT_MODE' : PRINT_BLACK_WHITE,# Printer rendering mode + 'PROXY_SETTINGS' : dict(), # Proxy Server Settings + 'REPORTER' : True, # Error Reporter is Active + 'SAVE_POS' : True, # Remember Carat positions + 'SAVE_SESSION' : False, # Load previous session on startup + 'SEARCH_LOC' : list(), # Recent Search Locations + 'SEARCH_FILTER' : '', # Last used search filter + 'SESSION_KEY' : '', # Ipc Session Server Key + 'SET_WPOS' : True, # Remember window position + 'SET_WSIZE' : True, # Remember mainwindow size on exit + 'SHOW_EDGE' : True, # Show Edge Guide + 'SHOW_EOL' : False, # Show EOL markers + 'SHOW_LN' : True, # Show Line Numbers + 'SHOW_WS' : False, # Show whitespace markers + 'SPELLCHECK' : dict(auto=False, + dict='en_US', + epath=None), # Spell checking preferences + 'STATBAR' : True, # Show Status Bar + 'SYNTAX' : True, # Use Syntax Highlighting + 'SYNTHEME' : 'Default', # Syntax Highlight color scheme + 'TABICONS' : True, # Show Tab Icons + 'TABWIDTH' : 8, # Tab width + 'THEME' : 'DEFAULT', # For future use + 'TOOLBAR' : True, # Show Toolbar + 'USETABS' : False, # Use tabs instead of spaces + 'USE_PROXY' : False, # Use Proxy server settings? + 'VIEWVERTSPACE' : False, # Allow extra virtual space in buffer + 'VI_EMU' : False, # Use Vi emulation mode + 'VI_NORMAL_DEFAULT' : False, # Use Normal mode by default + 'WARN_EOL' : True, # Warn about mixed eol characters + 'WRAP' : False, # Use Wordwrap + 'WSIZE' : (700, 450) # Mainwindow size + #FONT1 created at runtime by ed_styles as primary font + #FONT2 created at runtime by ed_styles as secondary font + #FONT3 Standard Font by UI, added to profile when customized +} + +#--------------------------------------------------------------------------# + +class Profile(dict): + """Class for managing profile data. All data is stored as builtin + python objects (i.e. str, tuple, list, ect...) however on a request + for data the object can be transformed in to a requested type where + applicable. The profile saves itself to disk using the cPickle module + to preserve data types and allow for easy loading. + + """ + _instance = None + _created = False + + def __init__(self): + """Initialize the profile""" + if not self._created: + dict.__init__(self) + else: + pass + + def __new__(cls, *args, **kargs): + """Maintain only a single instance of this object + @return: instance of this class + + """ + if cls._instance is None: + cls._instance = dict.__new__(cls, *args, **kargs) + return cls._instance + + #---- End Private Members ----# + + #---- Begin Public Members ----# + def DeleteItem(self, item): + """Removes an entry from the profile + @param item: items name + + """ + if item in self: + del self[item] + else: + pass + + def Get(self, index, fmt=None, default=None): + """Gets the specified item from the data set + + @param index: index of item to get + @keyword fmt: format the item should be in + @keyword default: Default value to return if index is + not in profile. + + """ + if index in self: + val = self.__getitem__(index) + else: + return default + + if fmt is None: + return val + else: + return _ToObject(index, val, fmt) + + def Load(self, path): + """Load the profiles data set with data from the given file + @param path: path to file to load data from + @note: The files data must have been written with a pickler + + """ + if os.path.exists(path): + try: + fhandle = open(path, 'rb') + val = cPickle.load(fhandle) + fhandle.close() + except (IOError, SystemError, OSError, + cPickle.UnpicklingError, EOFError), msg: + dev_tool.DEBUGP("[profile][err] %s" % str(msg)) + else: + if isinstance(val, dict): + self.update(val) + self.Set('MYPROFILE', path) + dev_tool.DEBUGP("[profile][info] Loaded %s" % path) + else: + dev_tool.DEBUGP("[profile][err] %s does not exist" % path) + dev_tool.DEBUGP("[profile][info] Loading defaults") + self.LoadDefaults() + self.Set('MYPROFILE', path) + return False + + # Update profile to any keys that are missing + for key in _DEFAULTS: + if key not in self: + self.Set(key, _DEFAULTS[key]) + return True + + def LoadDefaults(self): + """Loads the default values into the profile + @return: None + + """ + self.clear() + self.update(_DEFAULTS) + + def Set(self, index, val, fmt=None): + """Set the value of the given index + @param index: Index to set + @param val: Value to set + @keyword fmt: Format to convert to string from + + """ + if fmt is None: + self.__setitem__(index, val) + else: + self.__setitem__(index, _FromObject(val, fmt)) + + # Notify all clients with the configuration change message + ed_msg.PostMessage(ed_msg.EDMSG_PROFILE_CHANGE + (index,), val) + + def Write(self, path): + """Write the dataset of this profile as a pickle + @param path: path to where to write the pickle + @return: True on success / False on failure + + """ + try: + # Only write if given an absolute path + if not os.path.isabs(path): + return False + self.Set('MYPROFILE', path) + fhandle = open(path, 'wb') + cPickle.dump(self.copy(), fhandle, cPickle.HIGHEST_PROTOCOL) + fhandle.close() + UpdateProfileLoader() + except (IOError, cPickle.PickleError), msg: + dev_tool.DEBUGP(u"[profile][err] %s" % msg) + return False + else: + return True + + def Update(self, update=None): + """Update the profile using data from provided dictionary + or the default set if none is given. + @keyword update: dictionary of values to update from or None + @postcondition: All profile values from the update set are set + in this profile. If update is None then the current + set is only updated to include values from the + DEFAULTS that are not currently present. + + """ + if update is None: + for key, val in _DEFAULTS.iteritems(): + if key not in self: + self.Set(key, val) + else: + self.update(update) + + #---- End Public Members ----# + +#-----------------------------------------------------------------------------# +# Singleton reference instance + +TheProfile = Profile() + +#-----------------------------------------------------------------------------# +# Profile convenience functions +Profile_Del = TheProfile.DeleteItem +Profile_Get = TheProfile.Get +Profile_Set = TheProfile.Set + +def _FromObject(val, fmt): + """Convert the given value to a to a profile compatible value + @param val: value to convert + @param fmt: Format to convert to (string) + + """ + if fmt == u'font' and isinstance(val, wx.Font): + return "%s,%s" % (val.GetFaceName(), val.GetPointSize()) + else: + return val + +def _ToObject(index, val, fmt): + """Convert the given value to a different object + @param index: fallback to retrieve item from defaults + @param val: value to convert + @param fmt: Format to convert to + @todo: exception handling, + + """ + tmp = fmt.lower() + if tmp == u'font': + fnt = val.split(',') + rval = wx.FFont(int(fnt[1]), wx.DEFAULT, face=fnt[0]) + elif tmp == u'bool': + if isinstance(val, bool): + rval = val + else: + rval = _DEFAULTS.get(index, False) + elif tmp == u'size_tuple': + if len(val) == 2 and \ + isinstance(val[0], int) and isinstance(val[1], int): + rval = val + else: + rval = _DEFAULTS.get(index, wx.DefaultSize) + elif tmp == u'str': + rval = unicode(val) + elif tmp == u'int': + if isinstance(val, int): + rval = val + elif isinstance(val, basestring) and val.isdigit(): + rval = int(val) + else: + rval = _DEFAULTS.get(index) + else: + return val + return rval + +#---- Begin Function Definitions ----# + +def CalcVersionValue(ver_str="0.0.0"): + """Calculates a version value from the provided dot-formated string + + 1) SPECIFICATION: Version value calculation AA.BBB.CCC + - major values: < 1 (i.e 0.0.85 = 0.850) + - minor values: 1 - 999 (i.e 0.1.85 = 1.850) + - micro values: >= 1000 (i.e 1.1.85 = 1001.850) + + @keyword ver_str: Version string to calculate value of + + """ + ver_str = ''.join([char for char in ver_str + if char.isdigit() or char == '.']) + ver_lvl = ver_str.split(u".") + if len(ver_lvl) < 3: + return 0 + + major = int(ver_lvl[0]) * 1000 + minor = int(ver_lvl[1]) + if len(ver_lvl[2]) <= 2: + ver_lvl[2] += u'0' + micro = float(ver_lvl[2]) / 1000 + return float(major) + float(minor) + micro + +def GetLoader(): + """Finds the loader to use + @return: path to profile loader + @note: path may not exist, only returns the path to where the loader + should be. + + """ + cbase = util.GetUserConfigBase() + loader = os.path.join(cbase, u"profiles", u".loader2") + return loader + +def GetProfileStr(): + """Reads the profile string from the loader and returns it. + The profile string must be the first line in the loader file. + @return: path of profile used in last session + + """ + reader = util.GetFileReader(GetLoader()) + if reader == -1: + # So return the default + return CONFIG['PROFILE_DIR'] + u"default.ppb" + + profile = reader.readline() + profile = profile.strip() + reader.close() + if not os.path.isabs(profile): + profile = CONFIG['PROFILE_DIR'] + profile + return profile + +def ProfileIsCurrent(): + """Checks if profile is compatible with current editor version + and returns a bool stating if it is or not. + @return: whether profile on disk was written with current program version + + """ + if CalcVersionValue(ProfileVersionStr()) >= CalcVersionValue(VERSION): + return True + else: + return False + +def ProfileVersionStr(): + """Checks the Loader for the profile version string and + returns the version string. If there is an error or the + string is not found it returns a zero version string. + @return: the version string value from the profile loader file + + """ + loader = GetLoader() + reader = util.GetFileReader(loader, sys.getfilesystemencoding()) + if reader == -1: + return "0.0.0" + + ret_val = "0.0.0" + count = 0 + while True: + count += 1 + value = reader.readline() + value = value.split() + if len(value) > 0: + if value[0] == u'VERSION': + ret_val = value[1] + break + # Give up after 20 lines if version string not found + if count > 20: + break + reader.close() + + return ret_val + +def UpdateProfileLoader(): + """Updates Loader File + @precondition: MYPROFILE has been set + @postcondition: on disk profile loader is updated + @return: 0 if no error, non zero for error condition + + """ + writer = util.GetFileWriter(GetLoader()) + if writer == -1: + return 1 + + prof_name = Profile_Get('MYPROFILE') + if not prof_name or not os.path.isabs(prof_name): + prof_name = CONFIG['PROFILE_DIR'] + 'default.ppb' + + if not os.path.exists(prof_name): + prof_name = os.path.join(CONFIG['CONFIG_DIR'], + os.path.basename(prof_name)) + Profile_Set('MYPROFILE', prof_name) + + # Use just the relative profile name for local(portable) config paths + prof_name = os.path.basename(prof_name) + + writer.write(prof_name) + writer.write(u"\nVERSION\t" + VERSION) + writer.close() + return 0 diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/style_editor.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/style_editor.py new file mode 100644 index 0000000..deafb20 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/style_editor.py @@ -0,0 +1,919 @@ +############################################################################### +# Name: style_editor.py # +# Purpose: Syntax Highlighting configuration dialog # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008-2011 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides an editor dialog for graphically editing how the text is presented in +the editor when syntax highlighting is turned on. It does this by taking the +data from the controls and formating it into an Editra Style Sheet that the +editor can load to configure the styles of the text. + +@summary: Gui for creating custom Editra Style Sheets + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: style_editor.py 70228 2011-12-31 20:39:16Z CJP $" +__revision__ = "$Revision: 70228 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import glob +import wx + +# Editra Imports +import ed_glob +from profiler import Profile_Get, Profile_Set +import ed_basestc +from ed_style import StyleItem +import util +import syntax.syntax as syntax +import eclib +import ebmlib +import ed_basewin + +# Function Aliases +_ = wx.GetTranslation + +# Global Values +ID_FORE_COLOR = wx.NewId() +ID_BACK_COLOR = wx.NewId() +ID_BOLD = wx.NewId() +ID_ITALIC = wx.NewId() +ID_EOL = wx.NewId() +ID_ULINE = wx.NewId() +ID_FONT = wx.NewId() +ID_FONT_SIZE = wx.NewId() + +SETTINGS_IDS = [ ID_FORE_COLOR, ID_BACK_COLOR, ID_BOLD, ID_ITALIC, + ID_EOL, ID_ULINE, ID_FONT, ID_FONT_SIZE ] + +# Modification Flags +MOD_NONE = 0 +MOD_DOESNT_EXIST = 1 +MOD_CHANGE_PRESENT = 2 + +#--------------------------------------------------------------------------# + +class StyleEditor(ed_basewin.EdBaseDialog): + """This class creates the window that contains the controls + for editing/configuring the syntax highlighting styles it acts + as a graphical way to interact with the L{ed_style.StyleMgr}. + + @see: ed_style.StyleMgr + """ + def __init__(self, parent, id_=wx.ID_ANY, title=_("Style Editor"), + style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER): + super(StyleEditor, self).__init__(parent, id_, title, style=style) + + # Attributes + self.LOG = wx.GetApp().GetLog() + self._panel = StyleEditorBox(self) #TODO + + # Layout + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self._panel, 1, wx.EXPAND) + + # Create Buttons + b_sizer = wx.BoxSizer(wx.HORIZONTAL) + ok_b = wx.Button(self, wx.ID_OK, _("Ok")) + ok_b.SetDefault() + b_sizer.AddMany([(wx.Button(self, wx.ID_CANCEL, _("Cancel")), 0), + ((5, 5), 0), + (wx.Button(self, wx.ID_SAVE, _("Save")), 0), + ((5, 5), 0), (ok_b, 0)]) + sizer.Add(b_sizer, 0, wx.ALIGN_RIGHT | + wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) + + # Finish the Layout + self.SetSizer(sizer) + self.SetInitialSize() + + # Event Handlers + self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL) + self.Bind(wx.EVT_BUTTON, self.OnOk, id=wx.ID_OK) + self.Bind(wx.EVT_BUTTON, self.OnSave, id=wx.ID_SAVE) + self.Bind(wx.EVT_CLOSE, self.OnClose) + + #--- End Init ---# + + def ExportStyleSheet(self): + """Writes the style sheet data out to a style sheet + @return: bool + + """ + saved = self._panel.SaveStyleSheet() + return saved + + def OnCancel(self, evt): + """Catches the cancel button clicks and checks if anything + needs to be done before closing the window. + @param evt: event that called this handler + + """ + self.LOG('[style_editor][evt] Cancel Clicked Closing Window') + evt.Skip() + + def OnClose(self, evt): + """Handles the window closer event + @param evt: event that called this handler + + """ + self.LOG("[style_editor][evt] Dialog closing...") + self.OnOk(evt) + + def OnOk(self, evt): + """Catches the OK button click and checks if any changes need to be + saved before the window closes. + @param evt: event that called this handler + + """ + self.LOG('[style_editor][evt] Ok Clicked Closing Window') + modtype = self._panel.CheckForModifications() + result = wx.ID_NO + msg = None + if modtype == MOD_CHANGE_PRESENT: + msg = _("Some styles have been changed would " + "you like to save before exiting?") + elif modtype == MOD_DOESNT_EXIST: + msg = _("The new style sheet '%s' has not been saved " + "would you like to save before exiting?") % self._panel.StyleTheme + if msg is not None: + dlg = wx.MessageDialog(self, msg, _("Save Styles"), + style=wx.YES_NO | wx.YES_DEFAULT | \ + wx.CANCEL | wx.ICON_INFORMATION) + dlg.CenterOnParent() + result = dlg.ShowModal() + dlg.Destroy() + + if result == wx.ID_NO: + # Get Current Selection to update buffers + sheet = self._panel.StyleTheme + path = self._panel.GetStyleSheetPath(sheet) + if os.path.exists(path): + UpdateBufferStyles(sheet) + evt.Skip() + elif result == wx.ID_CANCEL: + self.LOG('[style_editor][info] canceled closing') + else: + result = self.ExportStyleSheet() + if result != wx.ID_CANCEL: + evt.Skip() + + def OnSave(self, evt): + """Catches save button event + @param evt: event that called this handler + + """ + self.LOG('[style_editor][evt] Export Clicked') + self.ExportStyleSheet() + +#-----------------------------------------------------------------------------# + +class StyleEditorBox(ed_basewin.EdBaseCtrlBox): + """StyleEditor main Panel""" + def __init__(self, parent): + super(StyleEditorBox, self).__init__(parent) + + # Attributes + self._prevTheme = None + ctrlbar = self.CreateControlBar(wx.TOP) + ss_lst = util.GetResourceFiles(u'styles', get_all=True, title=False) + ss_lst = [sheet for sheet in ss_lst if not sheet.startswith('.')] + self._style_ch = wx.Choice(ctrlbar, ed_glob.ID_PREF_SYNTHEME, + choices=sorted(ss_lst)) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_ADD), wx.ART_MENU) + if not bmp.IsOk(): + bmp = None + self._addbtn = eclib.PlateButton(ctrlbar, label=_("New"), + bmp=bmp, style=eclib.PB_STYLE_NOBG) + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_REMOVE), wx.ART_MENU) + if not bmp.IsOk(): + bmp = None + self._delbtn = eclib.PlateButton(ctrlbar, label=_("Remove"), + bmp=bmp, style=eclib.PB_STYLE_NOBG) + + # Setup + ss_lbl = wx.StaticText(ctrlbar, label=_("Style Theme") + u": ") + ctrlbar.AddControl(ss_lbl, wx.ALIGN_LEFT) + self.StyleTheme = Profile_Get('SYNTHEME', 'str') + ctrlbar.AddControl(self._style_ch, wx.ALIGN_LEFT) + ctrlbar.AddControl(self._addbtn, wx.ALIGN_LEFT) + self._addbtn.SetToolTipString(_("Create a new style theme")) + ctrlbar.AddControl(self._delbtn, wx.ALIGN_LEFT) + self._delbtn.SetToolTipString(_("Remove Style")) + self.SetWindow(StyleEditorPanel(self)) + + # Events + self.Bind(wx.EVT_CHOICE, self.OnThemeChoice, self._style_ch) + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_UPDATE_UI, + lambda evt: evt.Enable(not self.IsSystemStyleSheet()), + self._delbtn) + + #--- Properties ----# + def __setStyleTheme(self, theme): + self._prevTheme = theme # Tracking for choice change + self._style_ch.SetStringSelection(theme) + StyleTheme = property(lambda self: self._style_ch.GetStringSelection(), + lambda self, val: self.__setStyleTheme(val)) + SyntaxSheets = property(lambda self: self._style_ch.GetItems(), + lambda self, val: self._style_ch.SetItems(sorted(val))) + + #---- Public Api ----# + def CheckForModifications(self, sheet_name=None): + """Check for any unsaved modifications to the styling information + @return: modification type + + """ + if sheet_name is None: + sheet_name = self.StyleTheme # currently selected + modtype = MOD_NONE + if self.Window.DiffStyles(): + modtype = MOD_CHANGE_PRESENT + elif not self.SheetExistOnDisk(sheet_name): + modtype = MOD_DOESNT_EXIST + return modtype + + def DoChangeStyleSheet(self, sheet_name): + """Change the StyleEditor for the given style sheet""" + if not self.SheetExistOnDisk(sheet_name): + # Changing to a fully transient style sheet that has + # not yet been written to disk. + self.SetDisplayForTransientSheet(sheet_name) + else: + self.Window.ChangeStyleSheet(sheet_name) + self.StyleTheme = sheet_name + + def GetStyleSheetPath(self, sheet, syspath=False): + """Get the on disk path to where the style sheet should + be written to. + @param sheet: sheet name + @keyword syspath: look on the system install path + @return: path to the style sheet + + """ + if syspath: + cfgdir = ed_glob.CONFIG['SYS_STYLES_DIR'] # System Directory + else: + cfgdir = ed_glob.CONFIG['STYLES_DIR'] # User Directory + sheet_path = os.path.join(cfgdir, sheet) + sheet_path = ebmlib.AddFileExtension(sheet_path, '.ess') + return sheet_path + + def IsSystemStyleSheet(self): + """Is the given style sheet a system provided one + @return: bool + + """ + # If it exists in user space it is not a system one + path = self.GetStyleSheetPath(self.StyleTheme) + return not os.path.exists(path) + + def RefreshStyleSheets(self): + """Update the list of style sheets""" + ss_lst = util.GetResourceFiles(u'styles', get_all=True, title=False) + ss_lst = [sname for sname in ss_lst if not sname.startswith('.')] + self.SyntaxSheets = ss_lst + + def SaveStyleSheet(self, sheetname=None): + """Save the changes to the currently selected StyleSheet + @return: bool + + """ + # Ensure user styles directory exists to save style sheet to + if ed_glob.CONFIG['STYLES_DIR'] == ed_glob.CONFIG['SYS_STYLES_DIR']: + path = util.GetUserConfigBase() + user_config = os.path.join(path, 'styles') + if not os.path.exists(user_config): + try: + os.mkdir(user_config) + except (OSError, IOError), msg: + util.Log("[style_editor][err] %s" % msg) + else: + ed_glob.CONFIG['STYLES_DIR'] = user_config + + rval = False + if sheetname is None: + sheetname = self.StyleTheme + sheet_path = self.GetStyleSheetPath(sheetname) + if self.WriteStyleSheet(sheet_path): + # Update Style Sheet Control + self.RefreshStyleSheets() + sheet = u".".join(os.path.basename(sheet_path).split(u'.')[:-1]) + self.StyleTheme = sheet + self.Window.ResetTransientStyleData() + util.Log("[style_editor][info] Successfully exported: %s" % sheet) + + if sheet_path.startswith(ed_glob.CONFIG['STYLES_DIR']) or \ + sheet_path.startswith(ed_glob.CONFIG['SYS_STYLES_DIR']): + # Update editor windows/buffer to use new style sheet + UpdateBufferStyles(sheet) + rval = True + return rval + + def SetDisplayForTransientSheet(self, sheet_name): + """Setup the display and editor data for a transient style sheet""" + self.Window.SetBlankStyle() + themes = self.SyntaxSheets + if sheet_name not in themes: + themes.append(sheet_name) + self.SyntaxSheets = themes + self.StyleTheme = sheet_name + + def SheetExistOnDisk(self, sheet_name): + """Check if the given style sheet exists on disk + @param sheet_name: style sheet name + @return: bool + + """ + path = self.GetStyleSheetPath(sheet_name) # User path + syspath = self.GetStyleSheetPath(sheet_name, True) # System path + exists = os.path.exists(path) or os.path.exists(syspath) + return exists + + def WriteStyleSheet(self, path): + """Write the current style data to the given path + @param path: string + @return: bool + + """ + bOk = True + try: + writer = util.GetFileWriter(path) + writer.write(self.Window.GenerateStyleSheet()) + writer.close() + except (AttributeError, IOError), msg: + util.Log('[style_editor][err] Failed to export style sheet') + util.Log('[style_editor][err] %s' % msg) + bOk = False + return bOk + + #---- Event Handlers ----# + + def OnButton(self, evt): + """Handle the Add/Remove Buttons""" + e_obj = evt.GetEventObject() + if e_obj is self._addbtn: + # TODO: warn about unsaved changes + fname = wx.GetTextFromUser(_("Enter style sheet name"), + _("New Style Sheet"), + parent=self) + if fname: + # Case insensitive check + if fname.lower() in [name.lower() for name in self.SyntaxSheets]: + # Already exists + wx.MessageBox(_("The style %s already exists. Please choose a different name.") % fname, + style=wx.OK|wx.CENTER|wx.ICON_INFORMATION) + else: + # Create it + self.SetDisplayForTransientSheet(fname) + elif e_obj is self._delbtn: + path = self.GetStyleSheetPath(self.StyleTheme) + try: + os.remove(path) + except OSError, msg: + wx.MessageBox(_("Failed to delete style sheet:\nError:\n%s") % msg, + style=wx.OK|wx.CENTER|wx.ICON_ERROR) + else: + self.RefreshStyleSheets() + self.StyleTheme = u"Default" # select the default style + self.DoChangeStyleSheet(self.StyleTheme) + else: + evt.Skip() + + def OnThemeChoice(self, evt): + """Check if current style sheet has been saved when switching sheets""" + oldTheme = self._prevTheme + newTheme = self.StyleTheme # newly selected theme + msg = None + modtype = self.CheckForModifications(self._prevTheme) + if modtype == MOD_CHANGE_PRESENT: + # prompt to save before changing + msg = _("Would you like to save the changes to '%s' before changing themes?\n\n" + "Selecting No will result in all changes being lost.") + msg = msg % oldTheme + elif modtype == MOD_DOESNT_EXIST: + # prompt to save unsaved sheet + msg = _("The new style theme '%s' has not been saved.\n\n" + "Would you like to save it before changing themes?") + msg = msg % oldTheme + + if msg is not None: + dlg = wx.MessageDialog(self, msg, _("Save Styles"), + style=wx.YES_NO | wx.YES_DEFAULT | \ + wx.ICON_INFORMATION) + dlg.CenterOnParent() + result = dlg.ShowModal() + dlg.Destroy() + if result == wx.YES: + # Save the style sheet + self.SaveStyleSheet(oldTheme) + + # Change the style sheet to the newly selected one + self.DoChangeStyleSheet(newTheme) + +#-----------------------------------------------------------------------------# + +class StyleEditorPanel(wx.Panel): + """Main panel for the editor portion of the StyleEditor""" + def __init__(self, parent): + super(StyleEditorPanel, self).__init__(parent) + + # Attributes + self._settings = SettingsPanel(self) + self.preview = PreviewPanel(self) + self.prebuff = self.preview.GetPreviewBuffer() # TEMP HACK + self.styles_orig = DuplicateStyleDict(self.prebuff.GetStyleSet()) + self.styles_new = DuplicateStyleDict(self.styles_orig) + self.prebuff.SetStyles('preview', self.styles_new, True) + self.preview.OpenPreviewFile('cpp') + + # Setup + self.StyleTags = self.styles_orig.keys() + self.__DoLayout() + self.EnableSettings(False) + + # Event Handlers + self.Bind(wx.EVT_LISTBOX, self.OnListBox) + self.Bind(wx.EVT_CHOICE, self.OnChoice) + self.Bind(wx.EVT_CHECKBOX, self.OnCheck) + self.Bind(eclib.EVT_COLORSETTER, self.OnColor) + self.prebuff.Bind(wx.EVT_LEFT_UP, self.OnTextRegion) + self.prebuff.Bind(wx.EVT_KEY_UP, self.OnTextRegion) + + def __DoLayout(self): + """Layout the window""" + vsizer = wx.BoxSizer(wx.VERTICAL) + vsizer.Add(self._settings, 0, wx.EXPAND|wx.ALL, 5) + vsizer.Add(self.preview, 1, wx.EXPAND) + self.SetSizer(vsizer) + + #---- Properties ----# + + StyleTags = property(lambda self: self._settings.TagList.GetItems(), + lambda self, val: self._settings.TagList.SetItems(sorted(val))) + SettingsPanel = property(lambda self: self._settings) + + #---- Public API ----# + + def ChangeStyleSheet(self, sheet_name): + """Change the style sheet that is being edited + @param sheet_name: style sheet name (without extension) + + """ + self.prebuff.UpdateAllStyles(sheet_name) + self.ResetTransientStyleData() + tag = self._settings.TagList.GetStringSelection() + if tag != wx.EmptyString: + self.UpdateSettingsPane(self.styles_new[tag]) + + def DiffStyles(self): + """Checks if the current style set is different from the + original set. Used internally to check if a save prompt needs + to be brought up. Returns True if the style sets are different. + @return: whether style set has been modified or not + @return: bool + + """ + diff = False + for key in self.styles_orig: + if self.styles_orig[key] != self.styles_new[key]: + diff = True + break + return diff + + def EnableSettings(self, enable=True): + """Enables/Disables all settings controls + @keyword enable: whether to enable/disable settings controls + + """ + for child in self.SettingsPanel.GetChildren(): + if not isinstance(child, wx.ListBox): + child.Enable(enable) + + def GenerateStyleSheet(self): + """Generates a style sheet from the dialogs style data + @return: The dictionary of L{StyleItem} in self.styles_new transformed + into a string that is in Editra Style Sheet format. + + """ + sty_sheet = list() + ditem = self.styles_new.get('default_style', StyleItem()) + dvals = ';\n\t\t'.join([item.replace(',', ' ') + for item in ditem.GetAsList() ]) + ';' + sty_sheet.append(''.join(['default_style {\n\t\t', dvals, '\n\n}\n\n'])) + + tags = sorted(self.styles_new.keys()) + for tag in tags: + item = self.styles_new[tag] + if item.IsNull() or tag == 'default_style': + continue + + stage1 = wx.EmptyString + for attr in ('fore', 'back', 'face', 'size'): + ival = item.GetNamedAttr(attr) + if attr in ('fore', 'back'): + ival = ival.upper() + + if ival is None or ival == ditem.GetNamedAttr(attr): + continue + + stage1 = ''.join((stage1, attr, u':', + ival.replace(',', ' '), u';')) + + # Add any modifiers to the modifier tag + modifiers = item.GetModifiers() + if len(modifiers): + stage1 += (u"modifiers:" + modifiers + u";").replace(',', ' ') + + # If the StyleItem had any set attributes add it to the stylesheet + if len(stage1): + sty_sheet.append(tag + u" {\n") + stage2 = u"\t\t" + stage1[0:-1].replace(u";", u";\n\t\t") + u";" + sty_sheet.append(stage2) + sty_sheet.append(u"\n}\n\n") + + return u"".join(sty_sheet) + + def ResetTransientStyleData(self): + """Reset the transient style data to mark the changes as not dirty""" + self.styles_new = DuplicateStyleDict(self.prebuff.GetStyleSet()) + self.styles_orig = DuplicateStyleDict(self.styles_new) + + def SetBlankStyle(self): + """Clear all the transient style data to a blank style set""" + self.styles_orig = self.prebuff.BlankStyleDictionary() + self.styles_new = DuplicateStyleDict(self.styles_orig) + self.prebuff.SetStyles('preview', self.styles_new, nomerge=True) + self.prebuff.UpdateAllStyles('preview') + + # For some reason this causes the text display to refresh + # properly when nothing else would work. + self.OnTextRegion() + + def UpdateSettingsPane(self, syntax_data): + """Updates all the settings controls to hold the + values of the selected tag. + @param syntax_data: syntax data set to configure panel from + + """ + val_str = unicode(syntax_data) + val_map = { ID_FORE_COLOR : syntax_data.GetFore(), + ID_BACK_COLOR : syntax_data.GetBack(), + ID_BOLD : "bold" in val_str, + ID_ITALIC : "italic" in val_str, + ID_EOL : "eol" in val_str, + ID_ULINE : "underline" in val_str, + ID_FONT : syntax_data.GetFace(), + ID_FONT_SIZE : syntax_data.GetSize() + } + + # Fall back to defaults for color values + # that we may not be able to understand + if u"#" not in val_map[ID_FORE_COLOR]: + val_map[ID_FORE_COLOR] = self.prebuff.GetDefaultForeColour(as_hex=True) + if u"#" not in val_map[ID_BACK_COLOR]: + val_map[ID_BACK_COLOR] = self.prebuff.GetDefaultBackColour(as_hex=True) + + for sid in SETTINGS_IDS: + ctrl = self.FindWindowById(sid) + if isinstance(ctrl, wx.CheckBox): + ctrl.SetValue(val_map[sid]) + elif isinstance(ctrl, wx.Choice): + ctrl.SetStringSelection(val_map[sid]) + elif isinstance(ctrl, eclib.ColorSetter): + ctrl.SetLabel(val_map[sid][:7]) + return True + + def UpdateStyleSet(self, id_): + """Updates the value of the style tag to reflect any changes + made in the settings controls. + @param id_: identifier of the style tag in the list + + """ + # Get the tag that has been modified + tag = self._settings.TagList.GetStringSelection() + if not tag: + return False + + # Get the modified value + ctrl = self.FindWindowById(id_) + if isinstance(ctrl, wx.CheckBox): + val = ctrl.GetValue() + elif isinstance(ctrl, wx.Choice): + val = ctrl.GetStringSelection() + elif isinstance(ctrl, eclib.ColorSetter): + val = ctrl.GetLabel() + else: + return False + + # Update the value of the modified tag + val_map = { ID_FONT : u"face", + ID_FONT_SIZE : u"size", + ID_BOLD : u"bold", + ID_EOL : u"eol", + ID_ITALIC : u"italic", + ID_ULINE : u"underline", + ID_FORE_COLOR : u"fore", + ID_BACK_COLOR : u"back" + } + + if id_ in [ ID_FONT, ID_FONT_SIZE, ID_FORE_COLOR, ID_BACK_COLOR ]: + self.styles_new[tag].SetNamedAttr(val_map[id_], val) + elif id_ in [ ID_BOLD, ID_ITALIC, ID_ULINE, ID_EOL ]: + self.styles_new[tag].SetExAttr(val_map[id_], val) + else: + return False + + # Update the Preview Area + self.prebuff.SetStyleTag(tag, self.styles_new[tag]) + self.prebuff.RefreshStyles() + + #---- Event Handlers ----# + + def OnCheck(self, evt): + """Update Model for changes to styling settings""" + e_id = evt.GetId() + if e_id in [ID_BOLD, ID_EOL, ID_ULINE, ID_ITALIC]: + self.UpdateStyleSet(e_id) + else: + evt.Skip() + + def OnChoice(self, evt): + """Update Model for changes to styling settings""" + e_id = evt.GetId() + if e_id in [ID_FONT, ID_FONT_SIZE]: + self.UpdateStyleSet(e_id) + else: + evt.Skip() + + def OnColor(self, evt): + """Handles color selection events + @param evt: event that called this handler + + """ + # Update The Style data for current tag + self.UpdateStyleSet(evt.GetId()) + + def OnListBox(self, evt): + """Catches the selection of a style tag in the listbox + and updates the style window appropriately. + @param evt: event that called this handler + + """ + tag = evt.GetEventObject().GetStringSelection() + if tag != u"" and tag in self.styles_new: + self.UpdateSettingsPane(self.styles_new[tag]) + self.EnableSettings() + else: + self.EnableSettings(False) + + def OnTextRegion(self, evt=None): + """Processes clicks in the preview control and sets the style + selection in the style tags list to the style tag of the area + the cursor has moved into. + @param evt: event that called this handler + + """ + if evt is not None: + evt.Skip() + + style_id = self.prebuff.GetStyleAt(self.prebuff.GetCurrentPos()) + data = self.prebuff.FindTagById(style_id) + if data != wx.EmptyString and data in self.styles_new: + self._settings.TagList.SetStringSelection(data) + if wx.Platform == '__WXGTK__': + self._settings.TagList.SetFirstItemStr(data) + self.UpdateSettingsPane(self.styles_new[data]) + self.EnableSettings() + +#-----------------------------------------------------------------------------# + +class SettingsPanel(wx.Panel): + """Panel holding all settings controls for changing the font, + colors, styles, ect.. in the style set. + + """ + def __init__(self, parent): + """Create the settings panel""" + super(SettingsPanel, self).__init__(parent) + + # Attributes + self._tag_list = wx.ListBox(self, + size=(-1, 150), + style=wx.LB_SINGLE) + + # Layout + self.__DoLayout() + + TagList = property(lambda self: self._tag_list) + + def __DoLayout(self): + """Layout the controls in the panel""" + hsizer = wx.BoxSizer(wx.HORIZONTAL) + + # Setup Left hand side with Style Tag List + ss_v = wx.BoxSizer(wx.VERTICAL) + style_lbl = wx.StaticText(self, label=_("Style Tags") + u": ") + ss_v.AddMany([(style_lbl, 0, wx.ALIGN_LEFT), + (self._tag_list, 1, wx.EXPAND)]) + hsizer.Add(ss_v, 0, wx.EXPAND|wx.ALL, 5) + + # Add divider line + hsizer.Add(wx.StaticLine(self, size=(-1, 2), style=wx.LI_VERTICAL), + 0, wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND|wx.TOP|wx.BOTTOM, 5) + + # Setup the Right side + setting_sizer = wx.BoxSizer(wx.VERTICAL) + setting_top = wx.BoxSizer(wx.HORIZONTAL) + + # Settings top + sbox = wx.StaticBox(self, label=_("Color")) + cbox_sizer = wx.StaticBoxSizer(sbox, wx.VERTICAL) + + # Foreground + fground_sizer = wx.BoxSizer(wx.HORIZONTAL) + fground_lbl = wx.StaticText(self, label=_("Foreground") + u": ") + fground_sel = eclib.ColorSetter(self, ID_FORE_COLOR, wx.BLACK) + fground_sizer.AddMany([((5, 5)), + (fground_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((2, 2), 0), + (fground_sel, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5))]) + cbox_sizer.AddMany([(fground_sizer, 0, wx.ALIGN_LEFT | wx.EXPAND), + ((10, 10))]) + + # Background + bground_sizer = wx.BoxSizer(wx.HORIZONTAL) + bground_lbl = wx.StaticText(self, label=_("Background") + u": ") + bground_sel = eclib.ColorSetter(self, ID_BACK_COLOR, wx.WHITE) + bground_sizer.AddMany([((5, 5)), + (bground_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + ((2, 2), 0), + (bground_sel, 0, wx.ALIGN_CENTER_VERTICAL), + ((5, 5))]) + cbox_sizer.Add(bground_sizer, 0, wx.EXPAND) + setting_top.AddMany([(cbox_sizer, 0, wx.ALIGN_TOP), ((10, 10), 0)]) + + # Attrib Box + attrib_box = wx.StaticBox(self, label=_("Attributes")) + abox_sizer = wx.StaticBoxSizer(attrib_box, wx.VERTICAL) + + # Attributes + bold_cb = wx.CheckBox(self, ID_BOLD, _("bold")) + eol_cb = wx.CheckBox(self, ID_EOL, _("eol")) + ital_cb = wx.CheckBox(self, ID_ITALIC, _("italic")) + uline_cb = wx.CheckBox(self, ID_ULINE, _("underline")) + abox_sizer.AddMany([(bold_cb, 0), + (eol_cb, 0), + (ital_cb, 0), + (uline_cb, 0)]) + setting_top.Add(abox_sizer, 0, wx.ALIGN_TOP) + + # Font + fh_sizer = wx.BoxSizer(wx.HORIZONTAL) + font_box = wx.StaticBox(self, label=_("Font Settings")) + fbox_sizer = wx.StaticBoxSizer(font_box, wx.VERTICAL) + + # Font Face Name + fsizer = wx.BoxSizer(wx.HORIZONTAL) + flbl = wx.StaticText(self, label=_("Font") + u": ") + fontenum = wx.FontEnumerator() + if wx.Platform == '__WXMAC__': + # FixedWidthOnly Asserts on wxMac + fontenum.EnumerateFacenames(fixedWidthOnly=False) + else: + fontenum.EnumerateFacenames(fixedWidthOnly=True) + font_lst = [u"%(primary)s", u"%(secondary)s"] + font_lst.extend(sorted(fontenum.GetFacenames())) + fchoice = wx.Choice(self, ID_FONT, choices=font_lst) + fsizer.AddMany([((5, 5), 0), (flbl, 0, wx.ALIGN_CENTER_VERTICAL), + (fchoice, 0, wx.ALIGN_CENTER_VERTICAL), ((5, 5),0)]) + fbox_sizer.Add(fsizer, 0) + + # Font Size + fsize_sizer = wx.BoxSizer(wx.HORIZONTAL) + fsize_lbl = wx.StaticText(self, label=_("Size") + u": ") + fsizes = [u"%(size)d", u"%(size2)d"] + fsizes.extend([ unicode(x) for x in range(4, 21) ]) + fs_choice = wx.Choice(self, ID_FONT_SIZE, choices=fsizes) + fsize_sizer.AddMany([((5, 5), 0), + (fsize_lbl, 0, wx.ALIGN_CENTER_VERTICAL), + (fs_choice, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL), + ((5, 5), 0)]) + fbox_sizer.AddMany([((5, 5), 0), (fsize_sizer, 0, wx.EXPAND)]) + fh_sizer.AddMany([(fbox_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL), ((10, 10), 0)]) + + # Build Section + setting_sizer.AddMany([(setting_top, 0, wx.ALIGN_CENTER_HORIZONTAL), + ((10, 10), 0), + (fh_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)]) + + # Setup Right hand side with the settings controls + hsizer.AddStretchSpacer() + hsizer.Add(setting_sizer, 0, wx.EXPAND|wx.ALL, 5) + hsizer.AddStretchSpacer() + + self.SetSizer(hsizer) + +#-----------------------------------------------------------------------------# + +class PreviewPanel(ed_basewin.EdBaseCtrlBox): + """Panel to hold the preview window and selector""" + def __init__(self, parent): + super(PreviewPanel, self).__init__(parent) + + # Attributes + self.LOG = wx.GetApp().GetLog() + self.preview = ed_basestc.EditraBaseStc(self, size=(-1, 200), + style=wx.SUNKEN_BORDER) + + # Setup + self.preview.SetEdgeColumn(80) + self.preview.SetEdgeMode(wx.stc.STC_EDGE_LINE) + self.preview.SetCaretLineVisible(True) + self.__DoLayout() + + # Event Handlers + self.Bind(wx.EVT_CHOICE, self.OnChoice) + + def __DoLayout(self): + """Layout the Panel""" + # Create the ControlBar + cbar = self.CreateControlBar(wx.TOP) + + # Setup the ControlBar's controls + lexer_lbl = wx.StaticText(cbar, label=_("Preview File") + u": ") + lexer_lst = wx.Choice(cbar, ed_glob.ID_LEXER, + choices=syntax.GetLexerList()) + lexer_lst.SetToolTip(wx.ToolTip(_("Set the preview file type"))) + lexer_lst.SetStringSelection(u"CPP") + cbar.AddControl(lexer_lbl) + cbar.AddControl(lexer_lst) + + self.SetWindow(self.preview) + + def GetPreviewBuffer(self): + """Get the STC instance""" + return self.preview + + def OnChoice(self, evt): + """Update the preview file""" + if evt.GetId() == ed_glob.ID_LEXER: + e_obj = evt.GetEventObject() + val = e_obj.GetStringSelection() + self.OpenPreviewFile(val) + else: + evt.Skip() + + def OpenPreviewFile(self, file_lbl): + """Opens a file using the names in the Syntax Files choice + control as a search query. + @param file_lbl: name of file to open in test data directory + + """ + fname = file_lbl.replace(u" ", u"_").replace(u"/", u"_").lower() + fname = fname.replace('#', 'sharp') + try: + fname = glob.glob(ed_glob.CONFIG['TEST_DIR'] + fname + ".*")[0] + except IndexError: + self.LOG('[style_editor][err] File %s Does not exist' % fname) + return False + + self.preview.SetFileName(fname) + self.preview.ClearAll() + self.preview.LoadFile(fname) + self.preview.FindLexer() + self.preview.EmptyUndoBuffer() + return True + +#-----------------------------------------------------------------------------# +# Utility functions +def DuplicateStyleDict(style_dict): + """Duplicates the style dictionary to make a true copy of + it, as simply assigning the dictionary to two different variables + only copies a reference leaving both variables pointing to the + same object. + @param style_dict: dictionary of tags->StyleItems + @return: a copy of the given styleitem dictionary + + """ + new_dict = dict() + for tag in style_dict: + new_dict[tag] = style_dict[tag].Clone() + return new_dict + +def UpdateBufferStyles(sheet): + """Update the style used in all buffers + @param sheet: Style sheet to use + + """ + # Only update if the sheet has changed + if sheet is not None: + Profile_Set('SYNTHEME', sheet) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/README b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/README new file mode 100644 index 0000000..828a924 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/README @@ -0,0 +1,99 @@ +Syntax Plugin Specifications: + +Included in this document are the specifications of what is needed to write a +a new module to extend the syntax highlighting support in Editra. + +0: Before you begin + - Editra uses Scintilla for its text control. Since documentation is not + readily available, its suggested that you grab the Scintilla sources and + see what settings are available for each language. + +1: File Specifications + - The plugin file is a python module that provides the editor with the + information that it needs to properly setup the lexer. + +2: What the plugin needs to provide + + CLASS: SyntaxData a subclass instance of syndata.SyntaxDataBase + + METHODS: + - FUNCTION: GetKeywords(self) + DESC: Provides a set of language keywords and their level to set in + the editor. + PARAM: None + RETURN: A list of tuples. + SPECIFICATIONS: + The tuples in the list each contain two items. + -The first item is an integer value specifying the Scintilla + keyword type to set for the Lexer. + -The second is a string of space separated keywords. + EXAMPLE RETURN: [(0, "spam ni"), (1, "monty python")] + + - FUNCTION: GetSyntaxSpec(self) + DESC: This function is called to get the mapping of the stc style attributes + to the Editra Style Sheet tags. + PARAM: None + RETURN: List of tuple string pairs, that pair the STC value to the wanted + style tag. + SPECIFICATIONS: + The values in tuples of the return list must be ordered as follows + - (STC_* value, Editra Style Tag) + EXAMPLE RETURN: [('STC_C_DEFAULT', 'default_style'), + ('STC_C_COMMENT', 'comment_style')] + + - FUNCTION: GetProperties(self) + DESC: This function is called to get any extra lexer properties that the + editor should set for the given language. + PARAM: None + RETURN: List of tuples + SPECIFICATIONS: + The values in the tuples of the return list must be as follows + - ("property", "value") + If there are no needed properties to set the function should + return an empty list. + EXAMPLE RETURN: [("fold", "1"), ("fold.comment", "1")] + + - FUNCTION: GetCommentPattern(self) + DESC: Get the patern of comment meta characters to use for commenting + out code in the given language. + PARAM: None + RETURN: Ordered List of strings + SPECIFICATIONS: + The returned list of strings must be in the order that the characters + are to be added to the document. This only applies to languages that + have multi character sequences required for comments. + EXAMPLE RETURN: + - Bash: [ "#" ] + - C: ["/*", "*/] + + +OPTIONAL EXTENSIONS: + +Optional Features that language extensions can provide. These methods can be +added to a syntax module by using the syndata.SyntaxDataBase.RegisterFeature +method. + +Currently Supported Features: + + - FUNCTION: StyleText(stc, start, end) + DESC: Used for styling the text in a buffer that is using a container + lexer. + PARAM: stc The EditraStyledText control instance to do the styling in + PARAM: start The start position of the styling + PARAM: end The end position to style to + SPECIFICATIONS: Register with the synglob.FEATURE_STYLETEXT id + EXAMPLE: + + - FUNCTION: AutoIndenter(stc, current_pos, indent_char) + DESC: Provide context sensitive auto indentation support + PARAM: stc The buffer to do the indentation in + PARAM: current_pos The current position of the caret in the buffer + PARAM: indent_char Prefered character to use for indentation + ("\t" or " " * tabwidth) + SPECIFICATIONS: Called when the Return key is hit. Note that the new + line character is not sent to the buffer so it needs + to be handled by this method. This method must also + call AddText to add the new whitespace to the buffer. + + Register with the synglob.FEATURE_AUTOINDENT id + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/__init__.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/__init__.py new file mode 100644 index 0000000..a8909fc --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/__init__.py @@ -0,0 +1,26 @@ +############################################################################### +# Name: __init__.py # +# Purpose: initialize the syntax package # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### +"""Syntax data package + +Provides: + - Keyword Data + - Syntax styling definitions + +For all differn't file types and languages supported by Editra + +""" +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: __init__.py 63070 2010-01-05 01:56:27Z CJP $" +__revision__ = "$Revision: 63070 $" + +#-----------------------------------------------------------------------------# +# Setup Namespace + +from synxml import * + +#-----------------------------------------------------------------------------#
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_actionscript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_actionscript.py new file mode 100644 index 0000000..844f391 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_actionscript.py @@ -0,0 +1,86 @@ +############################################################################### +# Name: actionscript.py # +# Purpose: Define ActionScript syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: actionscript.py +AUTHOR: Cody Precord +@summary: Lexer configuration file for ActionScript + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _actionscript.py 70228 2011-12-31 20:39:16Z CJP $" +__revision__ = "$Revision: 70228 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# ActionScript Keywords 0 +AS_KEYWORDS = ("break case catch continue default do each else finally for if " + "in label new return super switch throw while with " + # Attribute Keywords + "dynamic final internal native override private protected " + "public static " + # Definition Keywords + "class const extends function get implements interface " + "namespace package set var " + # Directives + "import include use " + # Primary Expression Keywords + "false null this true " + # Special Types + "void Null *") + +# ActionScript Keywords 1 +# Namespaces and Packages +AS_TYPES = ("AS3 flash_proxy object_proxy flash accessibility display errors " + "events external filters geom media net printing profiler system " + "text ui utils xml ") + +#---- Syntax Style Specs ----# +# Same as cpp + +#---- Extra Properties ----# +# Same as cpp + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """ActionScript SyntaxData""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [(0, AS_KEYWORDS), (1, AS_TYPES)] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _cpp.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [_cpp.FOLD, _cpp.FOLD_PRE] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ada.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ada.py new file mode 100644 index 0000000..099a631 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ada.py @@ -0,0 +1,78 @@ +############################################################################### +# Name: ada.py # +# Purpose: Define Ada syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" + FILE: ada.py + AUTHOR: Cody Precord + @summary: Lexer configuration module for ada + @todo: styles, keywords, testing + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _ada.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +ADA_KEYWORDS = (0, "abort abstract accept access aliased all array at begin " + "body case constant declare delay delta digits do else " + "elsif end entry exception exit for function generic goto " + "if in is limited loop new null of others out package " + "pragma private procedure protected raise range record " + "renames requeue return reverse select separate subtype " + "tagged task terminate then type until use when while with") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_ADA_CHARACTER, 'char_style'), + (stc.STC_ADA_CHARACTEREOL, 'stringeol_style'), + (stc.STC_ADA_COMMENTLINE, 'comment_style'), + (stc.STC_ADA_DEFAULT, 'default_style'), + (stc.STC_ADA_DELIMITER, 'operator_style'), + (stc.STC_ADA_IDENTIFIER, 'default_style'), + (stc.STC_ADA_ILLEGAL, 'error_style'), + (stc.STC_ADA_LABEL, 'keyword2_style'), # Style This + (stc.STC_ADA_NUMBER, 'number_style'), + (stc.STC_ADA_STRING, 'string_style'), + (stc.STC_ADA_STRINGEOL, 'stringeol_style'), + (stc.STC_ADA_WORD, 'keyword_style')] + +#---- Extra Properties ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Ada""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_ADA) + + def GetKeywords(self): + """Returns Specified Keywords List""" + return [ADA_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications""" + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code""" + return [ u'--' ] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_apache.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_apache.py new file mode 100644 index 0000000..4ba7876 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_apache.py @@ -0,0 +1,176 @@ +############################################################################### +# Name: apache.py # +# Purpose: Define Apache syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: apache.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Apache Configuration Files + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _apache.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +DIRECTIVES = (0, 'acceptmutex acceptpathinfo accessconfig accessfilename ' + 'action addalt addaltbyencoding addaltbytype addcharset ' + 'adddefaultcharset adddescription addencoding addhandler ' + 'addicon addiconbyencoding addiconbytype addinputfilter ' + 'addlanguage addmodule addmoduleinfo addoutputfilter ' + 'addoutputfilterbytype addtype agentlog alias aliasmatch all ' + 'allow allowconnect allowencodedslashes allowoverride ' + 'anonymous anonymous_authoritative anonymous_logemail ' + 'anonymous_mustgiveemail anonymous_nouserid ' + 'anonymous_verifyemail assignuserid authauthoritative ' + 'authdbauthoritative authdbgroupfile authdbmauthoritative ' + 'authdbmgroupfile authdbmtype authdbmuserfile authdbuserfile ' + 'authdigestalgorithm authdigestdomain authdigestfile ' + 'authdigestgroupfile authdigestnccheck authdigestnonceformat ' + 'authdigestnoncelifetime authdigestqop authdigestshmemsize ' + 'authgroupfile authldapauthoritative authldapbinddn ' + 'authldapbindpassword authldapcharsetconfig ' + 'authldapcomparednonserver authldapdereferencealiases ' + 'authldapenabled authldapfrontpagehack authldapgroupattribute ' + 'authldapgroupattributeisdn authldapremoteuserisdn ' + 'authldapurl authname authtype authuserfile bindaddress ' + 'browsermatch browsermatchnocase bs2000account bufferedlogs ' + 'cachedefaultexpire cachedirlength cachedirlevels ' + 'cachedisable cacheenable cacheexpirycheck cachefile ' + 'cacheforcecompletion cachegcclean cachegcdaily ' + 'cachegcinterval cachegcmemusage cachegcunused ' + 'cacheignorecachecontrol cacheignoreheaders ' + 'cacheignorenolastmod cachelastmodifiedfactor cachemaxexpire ' + 'cachemaxfilesize cacheminfilesize cachenegotiateddocs ' + 'cacheroot cachesize cachetimemargin cgimapextension ' + 'charsetdefault charsetoptions charsetsourceenc checkspelling ' + 'childperuserid clearmodulelist contentdigest cookiedomain ' + 'cookieexpires cookielog cookiename cookiestyle ' + 'cookietracking coredumpdirectory customlog dav ' + 'davdepthinfinity davlockdb davmintimeout defaulticon ' + 'defaultlanguage defaulttype define deflatebuffersize ' + 'deflatecompressionlevel deflatefilternote deflatememlevel ' + 'deflatewindowsize deny directory directoryindex ' + 'directorymatch directoryslash documentroot dumpioinput ' + 'dumpiooutput enableexceptionhook enablemmap enablesendfile ' + 'errordocument errorlog example expiresactive expiresbytype ' + 'expiresdefault extendedstatus extfilterdefine ' + 'extfilteroptions fancyindexing fileetag files filesmatch ' + 'forcelanguagepriority forcetype forensiclog from group ' + 'header headername hostnamelookups identitycheck ifdefine ' + 'ifmodule imapbase imapdefault imapmenu include indexignore ' + 'indexoptions indexorderdefault isapiappendlogtoerrors ' + 'isapiappendlogtoquery isapicachefile isapifakeasync ' + 'isapilognotsupported isapireadaheadbuffer keepalive ' + 'keepalivetimeout languagepriority ldapcacheentries ' + 'ldapcachettl ldapconnectiontimeout ldapopcacheentries ' + 'ldapopcachettl ldapsharedcachefile ldapsharedcachesize ' + 'ldaptrustedca ldaptrustedcatype limit limitexcept ' + 'limitinternalrecursion limitrequestbody limitrequestfields ' + 'limitrequestfieldsize limitrequestline limitxmlrequestbody ' + 'listen listenbacklog loadfile loadmodule location ' + 'locationmatch lockfile logformat loglevel maxclients ' + 'maxkeepaliverequests maxmemfree maxrequestsperchild ' + 'maxrequestsperthread maxspareservers maxsparethreads ' + 'maxthreads maxthreadsperchild mcachemaxobjectcount ' + 'mcachemaxobjectsize mcachemaxstreamingbuffer ' + 'mcacheminobjectsize mcacheremovalalgorithm mcachesize ' + 'metadir metafiles metasuffix mimemagicfile minspareservers ' + 'minsparethreads mmapfile modmimeusepathinfo multiviewsmatch ' + 'namevirtualhost nocache noproxy numservers nwssltrustedcerts ' + 'nwsslupgradeable options order passenv pidfile port ' + 'protocolecho proxy proxybadheader proxyblock proxydomain ' + 'proxyerroroverride proxyiobuffersize proxymatch ' + 'proxymaxforwards proxypass proxypassreverse ' + 'proxypreservehost proxyreceivebuffersize proxyremote ' + 'proxyremotematch proxyrequests proxytimeout proxyvia qsc ' + 'readmename redirect redirectmatch redirectpermanent ' + 'redirecttemp refererignore refererlog removecharset ' + 'removeencoding removehandler removeinputfilter ' + 'removelanguage removeoutputfilter removetype requestheader ' + 'require resourceconfig rewritebase rewritecond rewriteengine ' + 'rewritelock rewritelog rewriteloglevel rewritemap ' + 'rewriteoptions rewriterule rlimitcpu rlimitmem rlimitnproc ' + 'satisfy scoreboardfile script scriptalias scriptaliasmatch ' + 'scriptinterpretersource scriptlog scriptlogbuffer ' + 'scriptloglength scriptsock securelisten sendbuffersize ' + 'serveradmin serveralias serverlimit servername serverpath ' + 'serverroot serversignature servertokens servertype setenv ' + 'setenvif setenvifnocase sethandler setinputfilter ' + 'setoutputfilter singlelisten ssiendtag ssierrormsg ' + 'ssistarttag ssitimeformat ssiundefinedecho ' + 'sslcacertificatefile sslcacertificatepath ' + 'sslcarevocationfile sslcarevocationpath ' + 'sslcertificatechainfile sslcertificatefile ' + 'sslcertificatekeyfile sslciphersuite sslengine sslmutex ' + 'ssloptions sslpassphrasedialog sslprotocol ' + 'sslproxycacertificatefile sslproxycacertificatepath ' + 'sslproxycarevocationfile sslproxycarevocationpath ' + 'sslproxyciphersuite sslproxyengine ' + 'sslproxymachinecertificatefile ' + 'sslproxymachinecertificatepath sslproxyprotocol ' + 'sslproxyverify sslproxyverifydepth sslrandomseed sslrequire ' + 'sslrequiressl sslsessioncache sslsessioncachetimeout ' + 'sslusername sslverifyclient sslverifydepth startservers ' + 'startthreads suexecusergroup threadlimit threadsperchild ' + 'threadstacksize timeout transferlog typesconfig unsetenv ' + 'usecanonicalname user userdir virtualdocumentroot ' + 'virtualdocumentrootip virtualhost virtualscriptalias ' + 'virtualscriptaliasip win32disableacceptex xbithack') + +PARAMS = (1, 'on off standalone inetd force-response-1.0 downgrade-1.0 ' + 'nokeepalive indexes includes followsymlinks none x-compress ' + 'x-gzip warn') + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_CONF_COMMENT, 'comment_style'), + (stc.STC_CONF_DEFAULT, 'default_style'), + (stc.STC_CONF_DIRECTIVE, 'keyword_style'), + (stc.STC_CONF_EXTENSION, 'pre_style'), + (stc.STC_CONF_IDENTIFIER, 'number_style'), + (stc.STC_CONF_IP, 'number2_style'), + (stc.STC_CONF_NUMBER, 'number_style'), + (stc.STC_CONF_OPERATOR, 'operator_style'), + (stc.STC_CONF_PARAMETER, 'global_style'), + (stc.STC_CONF_STRING, 'string_style')] + +#---- Extra Properties ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Apache Conf files""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CONF) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [DIRECTIVES, PARAMS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm.py new file mode 100644 index 0000000..04a5334 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm.py @@ -0,0 +1,81 @@ +############################################################################### +# Name: asm.py # +# Purpose: Define ASM syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: asm.py +AUTHOR: Cody Precord +@summary: Lexer configuration file GNU Assembly Code +@todo: Complete Keywords/Registers + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _asm.py 70228 2011-12-31 20:39:16Z CJP $" +__revision__ = "$Revision: 70228 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +#-----------------------------------------------------------------------------# + +# GNU Assembly CPU Instructions/Storage Types +ASM_CPU_INST = (0, ".long .ascii .asciz .byte .double .float .hword .int .octa " + ".quad .short .single .space .string .word") + +# GNU FPU Instructions +ASM_MATH_INST = (1, "") + +# GNU Registers +ASM_REGISTER = (2, "") + +# GNU Assembly Directives/Special statements/Macros +ASM_DIRECTIVES = (3, ".include .macro .endm") + +#---- Language Styling Specs ----# +SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'), + (stc.STC_ASM_CHARACTER, 'char_style'), + (stc.STC_ASM_COMMENT, 'comment_style'), + (stc.STC_ASM_COMMENTBLOCK, 'comment_style'), + (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_DIRECTIVE, 'keyword3_style'), + (stc.STC_ASM_DIRECTIVEOPERAND, 'default_style'), + (stc.STC_ASM_EXTINSTRUCTION, 'default_style'), + (stc.STC_ASM_IDENTIFIER, 'default_style'), + (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_NUMBER, 'number_style'), + (stc.STC_ASM_OPERATOR, 'operator_style'), + (stc.STC_ASM_REGISTER, 'keyword2_style'), + (stc.STC_ASM_STRING, 'string_style'), + (stc.STC_ASM_STRINGEOL, 'stringeol_style') ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Assembly files""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + # synglob.ID_LANG_ASM + self.SetLexer(stc.STC_LEX_ASM) + + def GetKeywords(self): + """Returns List of Keyword Specifications """ + return [ASM_CPU_INST, ASM_DIRECTIVES] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u';'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm68k.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm68k.py new file mode 100644 index 0000000..f05a29f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_asm68k.py @@ -0,0 +1,134 @@ +############################################################################### +# Name: asm68k.py # +# Purpose: Define 68k/56k assembly syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: asm68k.py +AUTHOR: Cody Precord +@summary: Lexer configuration file 68k/56k Assembly Code +@todo: more color configuration + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _asm68k.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- 68K Keyword Definitions ----# + +ASM_CPU_INST = (0, "andi and as b beq bg b bl bne bge bpl bchg bclr bfchg " + "bfclr bfexts bfextu bfffo bfins bfset bftst bkpt bra bset " + "bsr btst callm cas2 cas chk2 chk clr cmpa cmpi cmpm cmp " + "dbcc dbcs dbvc dbvs dbeq dbf dbt dbge dbgt dbhi dbmi dble " + "dbls dblt dbne dbpl dbra eori eor exg extb ext illegaljmp " + "jsr lea link ls mm movea movec movem movep moveq moves " + "move nbcd negx neg nop not ori or pack pea reset ro rox rt " + "sbcd seq sne spl swap tas trap tst unlk unpk abcd") + +ASM_MATH_INST = (1, "adda addi addq addx add div mul suba subi subq subx sub " + "tdiv") + +ASM_REGISTER = (2, "a0 a1 a2 a3 a4 a5 a6 a7 d0 d1 d2 d3 d4 d5 d6 d7 pc sr " + "ccr sp usp ssp vbr sfc sfcr dfc dfcr msp isp zpc cacr " + "caar za0 za1 za2 za3 za4 za5 za6 za7 zd0 zd1 zd2 zd3 " + "zd4 zd5 zd6 zd7 crp srp tc ac0 ac1 acusr tt0 tt1 mmusr " + "dtt0 dtt1 itt0 itt1 urp cal val scc crp srp drp tc ac psr " + "pcsr bac0 bac1 bac2 bac3 bac4 bac5 bac6 bac7 bad0 bad1 " + "bad2 bad3 bad4 bad5 bad6 bad7 fp0 fp1 fp2 fp3 fp4 fp5 fp6 " + "fp7 control status iaddr fpcr fpsr fpiar ") + +ASM_DIRECTIVES = (3, "ALIGN CHIP COMLINE COMMON DC DCB DS END EQU FEQU FAIL " + "FOPT IDNT LLEN MASK2 NAME NOOBJ OFFSET OPT ORG PLEN REG " + "RESTORE SAVE SECT SECTION SET SPC TTL XCOM XDEF XREF") + +#---- 56K Keywords ----# + +ASM56K_CPU_INST = (0, "adc addl addr and andi asl asr bchg bclr bra " + "brclr brset bsclr bset bsr bsset btst bcc bcs bec beq " + "bes bge bgt blc ble bls blt bmi bne bnr bpl bnn brkcc " + "brkcs brkec brkeq brkes brkge brkgt brklc brkle brkls " + "brklt brkmi brkne brknr brkpl brknn bscc bscs bsec bseq " + "bses bsge bsgt bslc bsle bsls bslt bsmi bsne bsnr bspl " + "bsnn clb clr cmp cmpm cmpu debug dmac do " + "forever dor enddo eor extract extractu illegal inc " + "insert jclr jmp jsclr jset jsr jsset jcc jcs jec jeq " + "jes jge jgt jlc jle jls jlt jmi jne jnr jpl jnn jscc " + "jscs jsec jseq jses jsge jsgt jslc jsle jsls jslt jsmi " + "jsne jsnr jspl jsnn lra lsl lsr lua mac maci macr macri " + "max maxm merge move movem movec movep mpy mpyi mpyr " + "mpyri nop norm normf not or ori pflush pflushun " + "pfree plock plockr punlock punlockr rep reset rnd rol " + "ror rti rts sbc stop tcc tfr trap trapcc " + "trapcs trapec trapeq trapes trapge trapgt traplc traple " + "trapls traplt trapmi trapne trapnr trappl trapnn tst " + "vsl wait") + +ASM56K_MATH_INST = (1, "abs add dec div neg sub subl subr") + +ASM56K_REGISTERS = (2, "pc mr ccr sr eom com omr sz sc vba la lc sp ssh ssl ss " + "a a2 a1 a0 b b2 b1 b0 x x0 x1 y y0 y1 r0 r1 r2 r3 r4 " + "r5 r6 r7 m0 m1 m2 m3 m4 m5 m6 m7 n0 n1 n2 n3 n4 n5 n6 " + "n7 ") + +ASM56K_DIRECTIVES = (3, "org equ page tabs list nolist if endif else opt title " + "macro endm dup dupa dupc dupf baddr bsb bsc bsm dc " + "dcb ds dsm dsr buffer endbuf section endsec global " + "local xdef xref mode ") + +#---- Language Styling Specs ----# +SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'), + (stc.STC_ASM_CHARACTER, 'char_style'), + (stc.STC_ASM_COMMENT, 'comment_style'), + (stc.STC_ASM_COMMENTBLOCK, 'comment_style'), + (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_DIRECTIVE, 'keyword3_style'), + (stc.STC_ASM_DIRECTIVEOPERAND, 'keyword4_style'), + (stc.STC_ASM_EXTINSTRUCTION, 'funct_style'), + (stc.STC_ASM_IDENTIFIER, 'default_style'), + (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_NUMBER, 'number_style'), + (stc.STC_ASM_OPERATOR, 'operator_style'), + (stc.STC_ASM_REGISTER, 'keyword2_style'), + (stc.STC_ASM_STRING, 'string_style'), + (stc.STC_ASM_STRINGEOL, 'stringeol_style') ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for 68k assembly files""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + # synglob.ID_LANG_68K, synglob.ID_LANG_DSP56K + self.SetLexer(stc.STC_LEX_ASM) + + def GetKeywords(self): + """Returns Specified Keywords List""" + if self.LangId == synglob.ID_LANG_68K: + return [ASM_CPU_INST, ASM_MATH_INST, ASM_REGISTER, ASM_DIRECTIVES] + else: + return [ASM56K_CPU_INST, ASM56K_MATH_INST, + ASM56K_REGISTERS, ASM56K_DIRECTIVES] + + def GetSyntaxSpec(self): + """Syntax Specifications""" + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u';'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_batch.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_batch.py new file mode 100644 index 0000000..6f527ed --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_batch.py @@ -0,0 +1,128 @@ +############################################################################### +# Name: batch.py # +# Purpose: Define DOS Batch syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: batch.py +AUTHOR: Cody Precord +@summary: Lexer configuration file for dos/windows batch scripts. +@todo: incorportate winbat keywords + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _batch.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +DOSBAT_KEYWORDS = (0, "append arp assoc at atmadm attrib bootcfg break cacls " + "call cd chcp chdir chkdsk chkntfs cls cmd color command " + "comp compact control convert copy date debug defrag del " + "delete dir diskcomp diskcopy doskey echo edit edlin " + "else endlocal EQU erase errorlevel exists exit expand " + "fc find findstr for format ftp ftype GEQ goto graftabl " + "GTR help if ipconfig keyb label LEQ loadfix logoff LSS " + "md mkdir mode more move nbtstat NEQ net netsh netstat " + "nlsfunc not nslookup path pathping pause ping popd " + "print prompt pushd rd rem ren rename replace restore " + "rmdir route runas set setlocal setver share shift " + "shutdown sort start subst time title telnet tracetr " + "tree type ver verify vol xcopy ") + +# WinBatch Keywords +WINBAT_KEYWORDS = (0, "if then else endif break end return exit next while for " + "gosub goto switch select to case endselect endwhile " + "endswitch aboveicons acc_attrib acc_chng_nt acc_control " + "acc_create acc_delete acc_full_95 acc_full_nt acc_list " + "acc_pfull_nt acc_pmang_nt acc_print_nt acc_read " + "acc_read_95 acc_read_nt acc_write amc arrange ascending " + "attr_a attr_a attr_ci attr_ci attr_dc attr_dc attr_di " + "attr_di attr_dm attr_dm attr_h attr_h attr_ic attr_ic " + "attr_p attr_p attr_ri attr_ri attr_ro attr_ro attr_sh " + "attr_sh attr_sy attr_sy attr_t attr_t attr_x attr_x " + "avogadro backscan boltzmann cancel capslock check " + "columnscommonformat cr crlf ctrl default default " + "deg2rad descending disable drive electric enable eulers " + "false faraday float8 fwdscan gftsec globalgroup gmtsec " + "goldenratio gravitation hidden icon lbutton lclick " + "ldblclick lf lightmps lightmtps localgroup magfield " + "major mbokcancel mbutton mbyesno mclick mdblclick minor " + "msformat multiple ncsaformat no none none noresize " + "normal notify nowait numlock off on open parsec " + "parseonly pi planckergs planckjoules printer rad2deg " + "rbutton rclick rdblclick regclasses regcurrent " + "regmachine regroot regusers rows save scrolllock server " + "shift single sorted stack string tab tile true uncheck " + "unsorted wait wholesection word1 word2 word4 yes zoomed " + "about abs acos addextender appexist appwaitclose asin " + "askfilename askfiletext askitemlist askline askpassword " + "askyesno atan average beep binaryalloc binarycopy " + "binaryeodget binaryeodset binaryfree binaryhashrec " + "binaryincr binaryincr2 binaryincr4 binaryincrflt " + "binaryindex binaryindexnc binaryoletype binarypeek " + "binarypeek2 binarypeek4 binarypeekflt binarypeekstr " + "binarypoke binarypoke2 binarypoke4 binarypokeflt " + "binarypokestr binaryread binarysort binarystrcnt " + "binarywrite boxbuttondraw boxbuttonkill boxbuttonstat " + "boxbuttonwait boxcaption boxcolor boxdataclear " + "boxdatatag boxdestroy boxdrawcircle boxdrawline " + "boxdrawrect boxdrawtext boxesup boxmapmode boxnew " + "boxopen boxpen boxshut boxtext boxtextcolor boxtextfont " + "boxtitle boxupdates break buttonnames by call callext " + "ceiling char2num clipappend clipget clipput continue " + "cos cosh datetime ddeexecute ddeinitiate ddepoke " + "dderequest ddeterminate ddetimeout debug debugdata " + "decimals delay dialog dialogbox dirattrget dirattrset " + "dirchange direxist") + +#---- Language Styling Specs ----# +SYNTAX_ITEMS = [ (stc.STC_BAT_DEFAULT, "default_style"), + (stc.STC_BAT_COMMAND, "class_style"), + (stc.STC_BAT_COMMENT, "comment_style"), + (stc.STC_BAT_HIDE, "string_style"), + (stc.STC_BAT_IDENTIFIER, "scalar_style"), + (stc.STC_BAT_LABEL, "class_style"), + (stc.STC_BAT_OPERATOR, "operator_style"), + (stc.STC_BAT_WORD, "keyword_style") ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Batch files""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_BATCH) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [DOSBAT_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications""" + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set""" + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'::'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_boo.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_boo.py new file mode 100644 index 0000000..d5ead7f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_boo.py @@ -0,0 +1,78 @@ +############################################################################### +# Name: boo.py # +# Purpose: Define Boo language syntax and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: boo.py +@summary: Defines language and syntax highlighting settings for the Boo + programming language +@todo: support for C style comment regions +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _boo.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _python + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +BOO_KW = (0, "abstract and as AST break callable cast char class constructor " + "continue def destructor do elif else ensure enum event except " + "failure final false for from get given goto if import in " + "interface internal is isa not null of or otherwise override " + "namespace partial pass private protected public raise ref retry " + "return self set static super struct success transient true try " + "typeof unless virtual when while yield") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [x for x in _python.SYNTAX_ITEMS if x[0] != stc.STC_P_DECORATOR] +SYNTAX_ITEMS.append((stc.STC_P_DECORATOR, 'default_style')) + +#---- Extra Properties ----# + +FOLD = ("fold", "1") +TIMMY = ("tab.timmy.whinge.level", "1") # Mark Inconsistent indentation + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Boo + @todo: needs custom highlighting handler + + """ + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_PYTHON) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [BOO_KW] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, TIMMY] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_caml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_caml.py new file mode 100644 index 0000000..dc16ec0 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_caml.py @@ -0,0 +1,95 @@ +############################################################################### +# Name: caml.py # +# Purpose: Define Caml syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: caml.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Caml + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _caml.py 66108 2010-11-10 21:04:54Z CJP $" +__revision__ = "$Revision: 66108 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +# Objective Caml 3 textual keywords +CAML_KW1 = (0, "and as assert asr begin class constraint do done downto else " + "end exception external false for fun function functor if in " + "include inherit initializer land lazy let lor lsl lsr lxor " + "match method mod module mutable new object of open or private " + "rec sig struct then to true try type val virtual when while " + "with") + +# Caml optional keywords +CAML_KW2 = (1, "option Some None ignore ref lnot succ pred parser") + +# Caml type/library keywords +CAML_KW3 = (2, "array bool char float int list string unit") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_CAML_CHAR, 'char_style'), + (stc.STC_CAML_COMMENT, 'comment_style'), + (stc.STC_CAML_COMMENT1, 'comment_style'), + (stc.STC_CAML_COMMENT2, 'comment_style'), + (stc.STC_CAML_COMMENT3, 'comment_style'), + (stc.STC_CAML_DEFAULT, 'default_style'), + (stc.STC_CAML_IDENTIFIER, 'default_style'), + (stc.STC_CAML_KEYWORD, 'keyword_style'), + (stc.STC_CAML_KEYWORD2, 'pre_style'), + (stc.STC_CAML_KEYWORD3, 'keyword2_style'), + (stc.STC_CAML_LINENUM, 'number_style'), + (stc.STC_CAML_NUMBER, 'number_style'), + (stc.STC_CAML_OPERATOR, 'operator_style'), + (stc.STC_CAML_STRING, 'string_style'), + (stc.STC_CAML_TAGNAME, 'directive_style')] #STYLE ME + +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS.append((stc.STC_CAML_WHITE, 'default_style')) #TODO + +#---- Extra Properties ----# +FOLD = ('fold', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Caml""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CAML) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [CAML_KW1, CAML_KW2, CAML_KW3] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'(*', u'*)'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cobra.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cobra.py new file mode 100644 index 0000000..42b7008 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cobra.py @@ -0,0 +1,152 @@ +############################################################################### +# Name: cobra.py # +# Purpose: Define Cobra syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Define support for Cobra programming language. +@summary: Lexer configuration module for Cobra. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _cobra.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +# Indenter keywords +INDENT_KW = (u"body", u"branch", u"class", u"cue", u"def", u"else", u"except", + u"expect", u"finally", u"for", u"if", u"invariant", u"namespace", + u"on" u"post", u"shared", u"success", u"test", u"try", u"while") + +UNINDENT_KW = (u"return", u"raise", u"break", u"continue", u"pass") + +# Cobra Keywords +KEYWORDS = ("abstract adds all and any as assert base be body bool branch " + "break callable catch char class const continue cue decimal def do" + "dynamic each else end ensure enum event every except expect " + "extend extern fake false finally float for from get has if ignore " + "implements implies import in inherits inlined inout int interface " + "internal invariant is listen mixin must namespace new nil " + "nonvirtual not number objc of off old on or out override partial " + "pass passthrough post print private pro protected public raise " + "ref require return same set shared sig stop struct success test " + "this throw to to\\? trace true try uint use using var vari " + "virtual where while yield") +KEYWORDS = (0, KEYWORDS) + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_P_DEFAULT, 'default_style'), + (stc.STC_P_CHARACTER, 'char_style'), + (stc.STC_P_CLASSNAME, 'class_style'), + (stc.STC_P_COMMENTBLOCK, 'comment_style'), + (stc.STC_P_COMMENTLINE, 'comment_style'), + (stc.STC_P_DECORATOR, 'decor_style'), + (stc.STC_P_DEFNAME, 'keyword3_style'), + (stc.STC_P_IDENTIFIER, 'default_style'), + (stc.STC_P_NUMBER, 'number_style'), + (stc.STC_P_OPERATOR, 'operator_style'), + (stc.STC_P_STRING, 'string_style'), + (stc.STC_P_STRINGEOL, 'stringeol_style'), + (stc.STC_P_TRIPLE, 'string_style'), + (stc.STC_P_TRIPLEDOUBLE, 'string_style'), + (stc.STC_P_WORD, 'keyword_style'), + (stc.STC_P_WORD2, 'userkw_style')] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +TIMMY = ("tab.timmy.whinge.level", "1") # Mark Inconsistant indentation + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Cobra""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_PYTHON) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [KEYWORDS, ] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, TIMMY] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#', ] + +#-----------------------------------------------------------------------------# + +def AutoIndenter(estc, pos, ichar): + """Auto indent cobra code. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + + """ + line = estc.GetCurrentLine() + spos = estc.PositionFromLine(line) + text = estc.GetTextRange(spos, pos) + eolch = estc.GetEOLChar() + inspace = text.isspace() + + # Cursor is in the indent area somewhere + if inspace: + estc.AddText(eolch + text) + return + + # Check if the cursor is in column 0 and just return newline. + if not len(text): + estc.AddText(eolch) + return + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + end_spaces = ((indent - (tabw * i_space)) * u" ") + + tokens = filter(None, text.strip().split()) + if tokens and not inspace: + if tokens[-1].endswith(u""): + if tokens[0] in INDENT_KW: + i_space += 1 + elif tokens[0] in UNINDENT_KW: + i_space = max(i_space - 1, 0) + elif tokens[-1].endswith(u"\\"): + i_space += 1 + + rval = eolch + (ichar * i_space) + end_spaces + if inspace and ichar != u"\t": + rpos = indent - (pos - spos) + if rpos < len(rval) and rpos > 0: + rval = rval[:-rpos] + elif rpos >= len(rval): + rval = eolch + + # Put text in the buffer + estc.AddText(rval) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cpp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cpp.py new file mode 100644 index 0000000..5d389b4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_cpp.py @@ -0,0 +1,226 @@ +############################################################################### +# Name: cpp.py # +# Purpose: Define C/CPP/ObjC/Vala syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: cpp.py +@author: Cody Precord +@summary: Lexer configuration file for C/C++/C#/Objective C/Vala/Cilk source files. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _cpp.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +import re + +# Local imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# C Keywords +C_KEYWORDS = ("asm break case const continue default do else for goto return " + "if sizeof static switch typeof while") + +# C Types/Structures/Storage Classes +C_TYPES = ("auto bool char clock_t complex div_t double enum extern float " + "fpos_t inline int int_least8_t int_least16_t int_least32_t " + "int_least64_t int8_t int16_t int32_t int64_t intmax_t intptr_t " + "jmp_buf ldiv_t long mbstate_t ptrdiff_t register sig_atomic_t " + "size_t ssize_t short signed struct typedef union time_t " + "uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t uint8_t " + "uint16_t uint32_t uint64_t uintptr_t uintmax_t unsigned va_list " + "void volatile wchar_t wctrans_t wctype_t wint_t FILE DIR __label__ " + "__complex__ __volatile__ __attribute__") + +# C/CPP Documentation Keywords (includes Doxygen keywords) +DOC_KEYWORDS = (2, "TODO FIXME XXX author brief bug callgraph category class " + "code date def depreciated dir dot dotfile else elseif em " + "endcode enddot endif endverbatim example exception file if " + "ifnot image include link mainpage name namespace page par " + "paragraph param pre post return retval section struct " + "subpage subsection subsubsection test todo typedef union " + "var verbatim version warning $ @ ~ < > # % HACK") + +# CPP Keyword Extensions +CPP_KEYWORDS = ("and and_eq bitand bitor catch class compl const_cast delete " + "dynamic_cast false friend new not not_eq operator or or_eq " + "private protected public reinterpret_cast static_cast this " + "throw try true typeid using xor xor_eq") + +# CPP Type/Structure/Storage Class Extensions +CPP_TYPES = ("bool inline explicit export mutable namespace template typename " + "virtual wchar_t") + +# C# Keywords +CSHARP_KW = ("abstract as base break case catch checked class const continue " + "default delegate do else event explicit extern false finally " + "fixed for foreach goto if implicit in interface internal is lock " + "new null operator out override params readonly ref return sealed " + "sizeof stackalloc static switch this throw true try typeof " + "unchecked unsafe using while") + +# C# Types +CSHARP_TYPES = ("bool byte char decimal double enum float int long " + "namespace object private protected public sbyte short string " + "struct uint ulong ushort virtual void volatile") + +# Objective C +OBJC_KEYWORDS = ("@catch @interface @implementation @end @finally @private " + "@protected @protocol @public @throw @try self super false " + "true") + +OBJC_TYPES = ("id") + +# Vala Keywords +VALA_KEYWORDS = ("abstract as base break case catch checked construct continue " + "default delegate do else event false finally for foreach get " + "goto if implicit interface internal is lock new operator out " + "override params readonly ref return sealed set sizeof " + "stackalloc this throw true try typeof unchecked using while") + +VALA_TYPES = ("bool byte char class const decimal double enum explicit extern " + "fixed float int long namespace private protected public sbyte " + "short static string struct uint ulong unichar unsafe ushort var " + "volatile void virtual") + +# Cilk Keywords +CILK_KEYWORDS = ("abort private shared spawn sync SYNCHED") + +CILK_TYPES = ("cilk inlet") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'stringeol_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, 'number2_style'), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_PRE = ("styling.within.preprocessor", "0") +FOLD_COM = ("fold.comment", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") +ALLOW_DOLLARS = ("lexer.cpp.allow.dollars", "1") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for many C like languages""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List""" + keywords = list() + kw1_str = [C_KEYWORDS] + kw2_str = [C_TYPES] + if self.LangId == synglob.ID_LANG_CPP: + kw1_str.append(CPP_KEYWORDS) + kw2_str.append(CPP_TYPES) + elif self.LangId == synglob.ID_LANG_CSHARP: + kw1_str = [CSHARP_KW] + kw2_str = [CSHARP_TYPES] + elif self.LangId == synglob.ID_LANG_OBJC: + kw1_str.append(OBJC_KEYWORDS) + kw2_str.append(OBJC_TYPES) + elif self.LangId == synglob.ID_LANG_VALA: + kw1_str = [VALA_KEYWORDS] + kw2_str = [VALA_TYPES] + elif self.LangId == synglob.ID_LANG_CILK: + kw1_str.append(CILK_KEYWORDS) + kw2_str.append(CILK_TYPES) + else: + pass + + keywords.append((0, " ".join(kw1_str))) + keywords.append((1, " ".join(kw2_str))) + keywords.append(DOC_KEYWORDS) + return keywords + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set""" + return [FOLD, FOLD_PRE, FOLD_COM] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code + + """ + if self.LangId in [ synglob.ID_LANG_CPP, + synglob.ID_LANG_CSHARP, + synglob.ID_LANG_OBJC, + synglob.ID_LANG_VALA ]: + return [u'//'] + else: + return [u'/*', u'*/'] + +#-----------------------------------------------------------------------------# + +def AutoIndenter(estc, pos, ichar): + """Auto indent cpp code. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + @return: string + + """ + rtxt = u'' + line = estc.GetCurrentLine() + text = estc.GetTextRange(estc.PositionFromLine(line), pos) + eolch = estc.GetEOLChar() + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + ndent = eolch + ichar * i_space + rtxt = ndent + ((indent - (tabw * i_space)) * u' ') + + cdef_pat = re.compile('(public|private|protected)\s*\:') + case_pat = re.compile('(case\s+.+|default)\:') + text = text.strip() + if text.endswith('{') or cdef_pat.match(text) or case_pat.match(text): + rtxt += ichar + + # Put text in the buffer + estc.AddText(rtxt) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_css.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_css.py new file mode 100644 index 0000000..31387df --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_css.py @@ -0,0 +1,223 @@ +############################################################################### +# Name: css.py # +# Purpose: Define CSS syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: css.py +@author: Cody Precord +@summary: Lexer configuration file for Cascading Style Sheets. + + 0. CSS1 Properties + 1. Pseudo-classes + 2. CSS2 Properties + 3. CSS3 Properties + 4. Pseudo-elements + 5. Browser-Specific CSS Properties + 6. Browser-Specific Pseudo-classes + 7. Browser-Specific Pseudo-elements + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _css.py 72399 2012-08-29 19:56:26Z CJP $" +__revision__ = "$Revision: 72399 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# CSS1 Keywords (Identifiers) +CSS1_KEYWORDS = (0, "font-family font-style font-variant font-weight font-size " + "font color background-color background-image " + "background-repeat background-position background " + "word-spacing letter-spacing text-decoration " + "vertical-align text-transform text-align text-indent " + "line-height margin-top margin-right margin-left margin " + "padding-top padding-right padding-bottom padding-left " + "padding border-top-width border-right-width " + "border-bottom-width border-left-width border-width " + "border-color border-style border-top border-right " + "border-bottom border-left border width height float clear " + "display white-space list-style-type list-style-image " + "list-style-position list-style margin-bottom " + "text-decoration min-width min-height " + "background-attachment") + +# CSS Psuedo Classes +CSS_PSUEDO_CLASS = (1, "link active visited indeterminate default " + # CSS 2 + "first-child focus hover lang left right first " + # CSS 3 + "empty enabled disabled checked not root target " + "only-child last-child nth-child nth-last-child " + "first-of-type last-of-type nth-of-type " + "nth-last-of-type only-of-type valid invalid required " + "optional") + +# CSS2 Keywords (Identifiers) +# This is meant for css2 specific keywords, but in order to get a better +# coloring effect this will contain special css properties as well. +CSS2_KEYWORDS = (2, "ActiveBorder ActiveCaption AppWorkspace Background " + "ButtonFace ButtonHighlight ButtonShadow ButtonText " + "CaptionText GrayText Highlight HighlightText " + "InactiveBorder InactiveCaption InactiveCaptionText " + "InfoBackground InfoText Menu MenuText Scrollbar " + "ThreeDDarkShadow ThreeDFace ThreeDHighlight " + "ThreeDLightShadow ThreeDShadow Window WindowFrame " + "WindowText above absolute all always aqua armenian ascent " + "auto avoid azimuth baseline baseline bbox behind below " + "bidi-override black blink block blue bold bolder both " + "bottom capitalize center center centerline child circle " + "clear clip code collapse color compact content continuous " + "crop cross crosshair cursive cursor dashed default " + "descent digits disc dotted double during elevation embed " + "fantasy faster female fixed fixed float fuchsia georgian " + "gray green groove hebrew height help hidden hide higher " + "icon inherit inline inset inside inside invert italic " + "justify landscape larger leftwards level lighter lime " + "lowercase ltr male marks maroon mathline medium menu " + "middle mix monospace move narrower navy non none normal " + "nowrap oblique olive once orphans outset outside overflow " + "overline pointer portrait position pre purple quotes red " + "relative richness ridge rightwards rtl scroll scroll " + "separate show silent silver size slope slower smaller " + "solid square src static stemh stemv stress sub super teal " + "thick thin top topline underline uppercase visibility " + "visible volume wait wider widows width widths yellow " + "z-index outline left") + +# CSS3 Keywords +CSS3_KEYWORDS = (3, "border-radius border-top-left-radius " + "border-top-right-radius border-bottom-left-radius " + "border-bottom-right-radius border-image " + "border-image-outset border-image-repeat " + "border-image-source border-image-slice border-image-width " + "break-after break-before break-inside columns " + "column-count column-fill column-gap column-rule " + "column-rule-color column-rule-style column-rule-width " + "column-span column-width @keframes animation " + "animation-delay animation-direction animation-duration " + "animation-fill-mode animation-iteration-count " + "animation-name animation-play-state " + "animation-timing-function transition transition-delay " + "transition-duration transition-timing-function " + "transition-property backface-visibility perspective " + "perspective-origin transform transform-origin " + "transform-style background-clip background-origin " + "background-size overflow-x overflow-y overflow-style " + "marquee-direction marquee-play-count marquee-speed " + "marquee-style box-shadow box-decoration-break opacity") + +PSEUDO_ELEMENTS = (4, "first-letter first-line before after selection") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_CSS_DEFAULT, 'default_style'), + (stc.STC_CSS_ATTRIBUTE, 'funct_style'), + (stc.STC_CSS_CLASS, 'global_style'), + (stc.STC_CSS_COMMENT, 'comment_style'), + (stc.STC_CSS_DIRECTIVE, 'directive_style'), + (stc.STC_CSS_DOUBLESTRING, 'string_style'), + (stc.STC_CSS_ID, 'scalar_style'), + (stc.STC_CSS_IDENTIFIER, 'keyword_style'), + (stc.STC_CSS_IDENTIFIER2, 'keyword3_style'), + (stc.STC_CSS_IMPORTANT, 'error_style'), + (stc.STC_CSS_OPERATOR, 'operator_style'), + (stc.STC_CSS_PSEUDOCLASS, 'scalar_style'), + (stc.STC_CSS_SINGLESTRING, 'string_style'), + (stc.STC_CSS_TAG, 'keyword_style'), + (stc.STC_CSS_UNKNOWN_IDENTIFIER, 'unknown_style'), + (stc.STC_CSS_UNKNOWN_PSEUDOCLASS, 'unknown_style'), + (stc.STC_CSS_VALUE, 'char_style') ] + +# TODO: add styling and keywords for new style regions in 2.9 +if wx.VERSION >= (2, 9, 0, 0, ''): + # Browser specific identifiers + SYNTAX_ITEMS.append((stc.STC_CSS_EXTENDED_IDENTIFIER, 'default_style')) + SYNTAX_ITEMS.append((stc.STC_CSS_EXTENDED_PSEUDOCLASS, 'default_style')) + SYNTAX_ITEMS.append((stc.STC_CSS_EXTENDED_PSEUDOELEMENT, 'default_style')) + # CSS3 Properties + SYNTAX_ITEMS.append((stc.STC_CSS_IDENTIFIER3, 'keyword2_style')) + # Pseudo elements + SYNTAX_ITEMS.append((stc.STC_CSS_PSEUDOELEMENT, 'default_style')) + +#---- Extra Properties ----# +FOLD = ("fold", "1") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for CSS""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CSS) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + kwlist = [CSS1_KEYWORDS , CSS_PSUEDO_CLASS] + # 2.9 supports CSS3 so for 2.8 just add CSS3 keywords to the css2 list + if wx.VERSION < (2, 9, 0, 0, ''): + css2_kw = (CSS2_KEYWORDS[0], " ".join((CSS2_KEYWORDS[1], CSS3_KEYWORDS[1]))) + kwlist.append(css2_kw) + else: + kwlist.append(CSS2_KEYWORDS) + kwlist.append(CSS3_KEYWORDS) + kwlist.append(PSEUDO_ELEMENTS) + return kwlist + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'/*', u'*/'] + +#-----------------------------------------------------------------------------# + +def AutoIndenter(estc, pos, ichar): + """Auto indent cpp code. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + + """ + rtxt = u'' + line = estc.GetCurrentLine() + text = estc.GetTextRange(estc.PositionFromLine(line), pos) + eolch = estc.GetEOLChar() + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + ndent = eolch + ichar * i_space + rtxt = ndent + ((indent - (tabw * i_space)) * u' ') + + if text.endswith('{'): + rtxt += ichar + + # Put text in the buffer + estc.AddText(rtxt) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_d.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_d.py new file mode 100644 index 0000000..ca394f3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_d.py @@ -0,0 +1,144 @@ +############################################################################### +# Name: d.py # +# Purpose: Define D programming language syntax for highlighting and other # +# features. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: d.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for D programming language +@todo: When 2.9 is out switch to the dedicated D Lexer + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _d.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import synglob +import syndata +from _cpp import AutoIndenter + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +D_KEYWORDS = (0, "abstract alias align asm assert auto body break case cast " + "catch cent class continue debug default delegate delete " + "deprecated do else enum export extern false final finally " + "for foreach foreach_reverse function goto if import in inout " + "interface invariant is lazy mixin module new null out " + "override package pragma private protected public return " + "scope short struct super switch synchronized template this " + "throw true try union unittest version void while with") + +D_TYPES = (1, "bool byte cdouble cfloat char const creal dchar double float " + "idouble ifloat ireal int real long static typeof typedef typeid " + "ubyte ucent uint ulong ushort volatile wchar") + +DOC_KEYWORDS = (2, "TODO FIXME XXX \\author \\brief \\bug \\callgraph " + "\\category \\class \\code \\date \\def \\depreciated \\dir " + "\\dot \\dotfile \\else \\elseif \\em \\endcode \\enddot " + "\\endif \\endverbatim \\example \\exception \\file \\if " + "\\ifnot \\image \\include \\link \\mainpage \\name " + "\\namespace \\page \\par \\paragraph \\param \\return " + "\\retval \\section \\struct \\subpage \\subsection " + "\\subsubsection \\test \\todo \\typedef \\union \\var " + "\\verbatim \\version \\warning \\$ \\@ \\~ \\< \\> \\# \\% " + "HACK ") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS = [ (stc.STC_D_CHARACTER, 'char_style'), + (stc.STC_D_COMMENT, 'comment_style'), + (stc.STC_D_COMMENTDOC, 'comment_style'), + (stc.STC_D_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_D_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_D_COMMENTLINE, 'comment_style'), + (stc.STC_D_COMMENTLINEDOC, 'comment_style'), + (stc.STC_D_COMMENTNESTED, 'comment_style'), + (stc.STC_D_DEFAULT, 'default_style'), + (stc.STC_D_IDENTIFIER, 'default_style'), + (stc.STC_D_NUMBER, 'number_style'), + (stc.STC_D_OPERATOR, 'operator_style'), + (stc.STC_D_STRING, 'string_style'), + (stc.STC_D_STRINGB, 'string_style'), #TODO + (stc.STC_D_STRINGEOL, 'stringeol_style'), + (stc.STC_D_STRINGR, 'string_style'), #TODO + (stc.STC_D_TYPEDEF, 'default_style'), # NEEDS STYLE + (stc.STC_D_WORD, 'keyword_style'), + (stc.STC_D_WORD2, 'keyword2_style'), + (stc.STC_D_WORD3, 'keyword3_style'), + (stc.STC_D_WORD5, 'default_style'), #TODO + (stc.STC_D_WORD6, 'default_style'), #TODO + (stc.STC_D_WORD7, 'default_style')] #TODO +else: + SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'stringeol_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, 'number2_style'), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_PRE = ("styling.within.preprocessor", "0") +FOLD_COM = ("fold.comment", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for D""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + if wx.VERSION >= (2, 9, 0, 0, ''): + self.SetLexer(stc.STC_LEX_D) + else: + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [D_KEYWORDS, D_TYPES, DOC_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_PRE, FOLD_COM] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_diff.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_diff.py new file mode 100644 index 0000000..ac9e2e2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_diff.py @@ -0,0 +1,71 @@ +############################################################################### +# Name: diff.py # +# Purpose: Define Diff/Patch file syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: diff.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Diff/Patch files + +""" + +__author__ = "Cody Precord <cprecord@editra.org" +__svnid__ = "$Id: _diff.py 66108 2010-11-10 21:04:54Z CJP $" +__revision__ = "$Revision: 66108 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +# None +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_DIFF_ADDED, 'global_style'), + (stc.STC_DIFF_COMMAND, 'pre_style'), + (stc.STC_DIFF_COMMENT, 'comment_style'), + (stc.STC_DIFF_DEFAULT, 'default_style'), + (stc.STC_DIFF_DELETED, 'error_style'), + (stc.STC_DIFF_HEADER, 'comment_style'), + (stc.STC_DIFF_POSITION, 'pre_style')] + +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS.append((stc.STC_DIFF_CHANGED, 'default_style')) #TODO + +#---- Extra Properties ----# +FOLD = ('fold', '1') +FOLD_COMPACT = ('fold.compact', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Diff files""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_DIFF) + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_COMPACT] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return ['--- '] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_django.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_django.py new file mode 100644 index 0000000..57ce70f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_django.py @@ -0,0 +1,141 @@ +############################################################################### +# Name: django.py # +# Purpose: Define Django syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: django.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Django Templates. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _django.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +from pygments.token import Token +from pygments.lexers import get_lexer_by_name + +#Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# +# Style Id's + +STC_DJANGO_DEFAULT, \ +STC_DJANGO_COMMENT, \ +STC_DJANGO_NUMBER, \ +STC_DJANGO_STRING, \ +STC_DJANGO_STRINGEOL, \ +STC_DJANGO_SCALAR, \ +STC_DJANGO_OPERATOR, \ +STC_DJANGO_PREPROCESSOR, \ +STC_DJANGO_ATTRIBUTE, \ +STC_DJANGO_TAG, \ +STC_DJANGO_BUILTIN, \ +STC_DJANGO_KEYWORD = range(12) + +#-----------------------------------------------------------------------------# + +# Python Keywords +KEYWORDS = ("true false undefined null in as reversed recursive not and or is " + "if else import with loop block forloop") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (STC_DJANGO_DEFAULT, 'default_style'), + (STC_DJANGO_COMMENT, 'comment_style'), + (STC_DJANGO_NUMBER, 'number_style'), + (STC_DJANGO_STRING, 'string_style'), + (STC_DJANGO_STRINGEOL, 'stringeol_style'), + (STC_DJANGO_SCALAR, 'scalar_style'), + (STC_DJANGO_OPERATOR, 'operator_style'), + (STC_DJANGO_PREPROCESSOR, 'pre_style'), + (STC_DJANGO_ATTRIBUTE, 'keyword2_style'), + (STC_DJANGO_TAG, 'keyword_style'), # Need new tag + (STC_DJANGO_BUILTIN, 'keyword4_style'), + (STC_DJANGO_KEYWORD, 'keyword_style'), ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Django""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CONTAINER) + self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [(1, KEYWORDS)] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u"#",] + +#-----------------------------------------------------------------------------# + +def StyleText(stc, start, end): + """Style the text + @param stc: Styled text control instance + @param start: Start position + @param end: end position + + """ + cpos = 0 + stc.StartStyling(cpos, 0x1f) + lexer = get_lexer_by_name("html+django") + doctxt = stc.GetTextRange(0, end) + wineol = stc.GetEOLChar() == "\r\n" + + # Need to convert to UTF-8 in order to calculate + # correct positions in STC. + try: + doctxt = doctxt.encode('utf-8') + except: + pass + + for token, txt in lexer.get_tokens(doctxt): +# print token, txt + style = TOKEN_MAP.get(token, STC_DJANGO_DEFAULT) + if style == STC_DJANGO_PREPROCESSOR and txt.startswith(u'#'): + style = STC_DJANGO_COMMENT +# elif style == STC_DJANGO_STRING and txt[-1] not in '"\'': +# style = STC_DJANGO_STRINGEOL + + tlen = len(txt) + if wineol and "\n" in txt: + tlen += txt.count("\n") + + if tlen: + stc.SetStyling(tlen, style) + cpos += tlen + stc.StartStyling(cpos, 0x1f) + +#-----------------------------------------------------------------------------# + +TOKEN_MAP = { Token.Literal.String : STC_DJANGO_STRING, + Token.Comment.Preproc : STC_DJANGO_PREPROCESSOR, + Token.Comment : STC_DJANGO_COMMENT, + Token.Name.Builtin : STC_DJANGO_BUILTIN, + Token.Operator : STC_DJANGO_OPERATOR, + Token.Punctuation : STC_DJANGO_OPERATOR, + Token.Number : STC_DJANGO_NUMBER, + Token.Keyword : STC_DJANGO_KEYWORD, + Token.Name.Attribute : STC_DJANGO_ATTRIBUTE, + Token.String.Interpol : STC_DJANGO_SCALAR, + Token.Name.Tag : STC_DJANGO_TAG } +
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_dot.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_dot.py new file mode 100644 index 0000000..aa4e3ba --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_dot.py @@ -0,0 +1,114 @@ +############################################################################### +# Name: dot.py # +# Purpose: Define DOT graph visualization language syntax for highlighting # +# and other features. # +# Author: Rob McMullen <robm@users.sourceforge.net> # +# Copyright: (c) 2007 Rob McMullen <robm@users.sourceforge.net # +# License: wxWindows License # +############################################################################### + +""" +FILE: dot.py +AUTHOR: Rob McMullen +@summary: Lexer configuration module for the DOT graph description language + +""" + +__author__ = "Rob McMullen <robm@users.sourceforge.net>" +__svnid__ = "$Id: _dot.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +DOT_KEYWORDS = (0, "node edge graph digraph subgraph strict") + +DOT_TYPES = (1, +"Damping K URL arrowhead arrowsize arrowtail bb bgcolor center charsetil " +"clusterrank color colorscheme comment compound concentrate constraint " +"decorate defaultdist dim dir diredgeconstraints distortion dpi edgeURL " +"edgehref edgetarget edgetooltip epsilon esep fillcolor fixedsize " +"fontcolor fontname fontnames fontpath fontsize group headURL headclip " +"headhref headlabel headport headtarget headtooltip height href label " +"labelURL labelangle labeldistance labelfloat labelfontcolor " +"labelfontname labelfontsize labelhref labeljust labelloc labeltarget " +"labeltooltip landscape layer layers layersep len levelsgap lhead lp " +"ltail margin maxiter mclimit mindist minlen mode model mosek nodesep " +"nojustify normalize nslimit nslimit1 ordering orientation orientation " +"outputorder overlap pack packmode pad page pagedir pencolor " +"peripheries pin pos quantum rank rankdir ranksep ratio rects regular " +"remincross resolution root rotate samehead sametail samplepoints " +"searchsize sep shape shapefile showboxes sides size skew splines start " +"style stylesheet tailURL tailclip tailhref taillabel tailport " +"tailtarget tailtooltip target tooltip truecolor vertices viewport " +"voro_margin weight width z arrowType clusterMode color colorList " +"dirType escString layerList layerRange lblString outputMode packMode " +"pagedir point pointf pointfList portPos rankType rankdir rect shape " +"splineType startType style viewPort " +) + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'stringeol_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, "number2_style"), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_PRE = ("styling.within.preprocessor", "0") +FOLD_COM = ("fold.comment", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for DOT""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [DOT_KEYWORDS, DOT_TYPES] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_PRE] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_editra_ss.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_editra_ss.py new file mode 100644 index 0000000..39abd74 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_editra_ss.py @@ -0,0 +1,82 @@ +############################################################################### +# Name: editra_ss.py # +# Purpose: Define Editra Style Sheet syntax for highlighting and other # +# features. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: editra_ss.py +AUTHOR: Cody Precord +@summary: Lexer configuration file for Editra Syntax Highlighter Style Sheets. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _editra_ss.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +from _css import AutoIndenter + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Editra Style Sheet Keywords +ESS_KEYWORDS = (0, "fore back face size eol bold italic modifiers") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_CSS_DEFAULT, 'default_style'), + (stc.STC_CSS_CLASS, 'global_style'), + (stc.STC_CSS_COMMENT, 'comment_style'), + (stc.STC_CSS_DIRECTIVE, 'directive_style'), + (stc.STC_CSS_DOUBLESTRING, 'string_style'), + (stc.STC_CSS_ID, 'scalar_style'), + (stc.STC_CSS_IDENTIFIER, 'keyword4_style'), + (stc.STC_CSS_IDENTIFIER2, 'keyword3_style'), + (stc.STC_CSS_IMPORTANT, 'error_style'), + (stc.STC_CSS_OPERATOR, 'operator_style'), + (stc.STC_CSS_PSEUDOCLASS, 'scalar_style'), + (stc.STC_CSS_SINGLESTRING, 'string_style'), + (stc.STC_CSS_TAG, 'keyword_style'), + (stc.STC_CSS_UNKNOWN_IDENTIFIER, 'unknown_style'), + (stc.STC_CSS_UNKNOWN_PSEUDOCLASS, 'unknown_style'), + (stc.STC_CSS_VALUE, 'char_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Editra Style Sheets""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CSS) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [ESS_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'/*', '*/'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_edje.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_edje.py new file mode 100644 index 0000000..6757c73 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_edje.py @@ -0,0 +1,101 @@ +############################################################################### +# Name: edje.py # +# Purpose: Syntax provider module for the Enlightenment Foundation Libraries # +# interface language Edje and Edje Data Collection files. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: edje.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Edje. Edje is a interface definition + language that is part of the Enlightenment Foundation Libraries for + E17. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _edje.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +EDJE_KW = (0, "action after align aspect border clip_to color color2 color3 " + "color_class effect fit font image inherit name normal max min " + "mouse_events offset relative repeat_events signal size smooth " + "source state step target text_class to to_x to_y transition " + "tween type visible") + +EDJE_SEC = (1, "collections description fill group images part parts program " + "programs rel1 rel2 text") + +DOC_KEYWORDS = (2, "TODO FIXME XXX HACK") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'stringeol_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, 'number2_style'), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_PRE = ("styling.within.preprocessor", "0") +FOLD_COM = ("fold.comment", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Edje""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [EDJE_KW, EDJE_SEC] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_PRE] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_eiffel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_eiffel.py new file mode 100644 index 0000000..b58fe63 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_eiffel.py @@ -0,0 +1,81 @@ +############################################################################### +# Name: eiffel.py # +# Purpose: Define Eiffel syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: eiffel.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Eiffel +@todo: look into why io.anything is highlighted as a number + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _eiffel.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +EIFFEL_KW = (0, "alias all and any as bit boolean check class character clone " + "cluster create creation current debug deferred div do double " + "else elseif end ensure equal expanded export external false " + "feature forget from frozen general if implies indexing infix " + "inherit inspect integer invariant is language like local loop " + "mod name nochange none not obsolete old once or platform " + "pointer prefix precursor program real redefine rename require " + "rescue result retry root select separate string strip then " + "true undefine unique until variant void when xor") +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_EIFFEL_CHARACTER, 'char_style'), + (stc.STC_EIFFEL_COMMENTLINE, 'comment_style'), + (stc.STC_EIFFEL_DEFAULT, 'default_style'), + (stc.STC_EIFFEL_IDENTIFIER, 'default_style'), + (stc.STC_EIFFEL_NUMBER, 'number_style'), + (stc.STC_EIFFEL_OPERATOR, 'operator_style'), + (stc.STC_EIFFEL_STRING, 'string_style'), + (stc.STC_EIFFEL_STRINGEOL, 'stringeol_style'), + (stc.STC_EIFFEL_WORD, 'keyword_style')] + +#---- Extra Properties ----# +FOLD = ("fold", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Eiffel""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_EIFFEL) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [EIFFEL_KW] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'--'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_erlang.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_erlang.py new file mode 100644 index 0000000..ed00476 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_erlang.py @@ -0,0 +1,105 @@ +############################################################################### +# Name: erlang.py # +# Purpose: Define Erlang syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: erlang.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for the Erlang Programming Language +@todo: better styling + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _erlang.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +KEYWORDS = (0, "compile define else endif export file ifdef ifndef import " + "include include_lib module record undef author copyright doc " + "after begin case catch cond end fun if let of query receive " + "when define record export import include include_lib else " + "endif undef apply attribute call do in letrec module primop " + "try") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_ERLANG_ATOM, 'default_style'), # need new tag + (stc.STC_ERLANG_CHARACTER, 'char_style'), + (stc.STC_ERLANG_COMMENT, 'comment_style'), + (stc.STC_ERLANG_DEFAULT, 'default_style'), + (stc.STC_ERLANG_FUNCTION_NAME, 'funct_style'), + (stc.STC_ERLANG_KEYWORD, 'keyword_style'), + (stc.STC_ERLANG_MACRO, 'pre_style'), + (stc.STC_ERLANG_NODE_NAME, 'string_style'), # maybe change + (stc.STC_ERLANG_NUMBER, 'number_style'), + (stc.STC_ERLANG_OPERATOR, 'operator_style'), + (stc.STC_ERLANG_RECORD, 'keyword2_style'), + (stc.STC_ERLANG_STRING, 'string_style'), + (stc.STC_ERLANG_UNKNOWN, 'unknown_style'), + (stc.STC_ERLANG_VARIABLE, 'default_style')] # need custom? + +# Version specific +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS.append((stc.STC_ERLANG_ATOM_QUOTED, 'default_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_BIFS, 'default_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_DOC, 'dockey_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_DOC_MACRO, 'dockey_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_FUNCTION, 'comment_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_COMMENT_MODULE, 'comment_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_MACRO_QUOTED, 'default_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_MODULES, 'default_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_MODULES_ATT, 'default_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_NODE_NAME_QUOTED, 'default_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_PREPROC, 'pre_style')) # TODO + SYNTAX_ITEMS.append((stc.STC_ERLANG_RECORD_QUOTED, 'default_style')) # TODO +else: + SYNTAX_ITEMS.append((stc.STC_ERLANG_SEPARATOR, 'default_style')) # need style? + +#---- Extra Properties ----# +FOLD = ('fold', '1') +FOLD_CMT = ('fold.comments', '1') +FOLD_KW = ('fold.keywords', '1') +FOLD_BRACE = ('fold.braces', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Erlang""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_ERLANG) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'%%'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ferite.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ferite.py new file mode 100644 index 0000000..c5fc033 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ferite.py @@ -0,0 +1,68 @@ +############################################################################### +# Name: ferite.py # +# Purpose: Syntax Definitions for the Ferite Scripting Language # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +@summary: Lexer configuration module for Ferite Scripting Language + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _ferite.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +FERITE_KW = (0, "false null self super true abstract alias and arguments " + "attribute_missing break case class closure conformsToProtocol " + "constructor continue default deliver destructor diliver " + "directive do else extends eval final fix for function global " + "handle if iferr implements include instanceof isa " + "method_missing modifies monitor namespace new or private " + "protected protocol public raise recipient rename return " + "static switch uses using while") + +FERITE_TYPES = (1, "boolean string number array object void XML Unix Sys " + "String Stream Serialize RMI Posix Number Network Math " + "FileSystem Console Array Regexp XSLT") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Ferite""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [FERITE_KW, FERITE_TYPES, _cpp.DOC_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _cpp.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [_cpp.FOLD,] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return ['//',] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_flagship.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_flagship.py new file mode 100644 index 0000000..1473944 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_flagship.py @@ -0,0 +1,182 @@ +############################################################################### +# Name: flagship.py # +# Purpose: Define Flagship syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: flagship.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for the Flagship programming language and + other XBase dialects. +@todo: Custom style defs + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _flagship.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +FS_COMMANDS = (0, "? @ accept access all alternate announce ansi any append as " + "assign autolock average begin bell bitmap blank box call " + "cancel case century charset checkbox clear close cls color " + "combobox commit confirm console constant continue copy " + "count create cursor date dbread dbwrite decimals declare " + "default delete deleted delimiters device dir directory " + "display do draw edit else elseif eject end endcase enddo " + "endif endtext epoch erase error escape eval eventmask exact " + "exclusive extended external extra field file filter find " + "fixed font for form format from get gets global " + "global_extern go goto gotop guialign guicolor guicursor " + "guitransl html htmltext if image index input intensity join " + "key keyboard keytransl label lines list listbox local " + "locate margin memory memvar menu message method multibyte " + "multilocks next nfs nfslock nfs_force note on openerror " + "order outmode pack parameters path pixel pop printer " + "private prompt public push pushbutton quit radiobutton " + "radiogroup read recall refresh reindex relation release " + "rename replace report request restore richtext rowadapt " + "rowalign run save say scoreboard scrcompress screen seek " + "select sequence set setenhanced setstandard setunselected " + "skip softseek sort source static store struct structure sum " + "tag tbrowse text to total type typeahead unique unlock " + "update use wait while with wrap xml zap zerobyteout") + +FS_STDLIB = (1, "_displarr _displarrerr _displarrstd _displobj _displobjerr " + "_displobjstd aadd abs achoice aclone acopy adel adir " + "aelemtype aeval afields afill ains alert alias alltrim altd " + "ansi2oem appiomode appmdimode appobject array asc ascan asize " + "asort at atail atanychar autoxlock between bin2i bin2l bin2w " + "binand binlshift binor binrshift binxor bof break browse cdow " + "chr chr2screen cmonth col col2pixel color2rgb colorselect " + "colvisible consoleopen consolesize crc32 ctod curdir date " + "datevalid day dbappend dbclearfilter dbclearindex " + "dbclearrelation dbcloseall dbclosearea dbcommit dbcommitall " + "dbcreate dbcreateindex dbdelete dbedit dbeval dbf dbfilter " + "dbfinfo dbflock dbfused dbgetlocate dbgobottom dbgoto dbgotop " + "dbobject dbrecall dbreindex dbrelation dbrlock dbrlocklist " + "dbrselect dbrunlock dbseek dbselectarea dbsetdriver " + "dbsetfilter dbsetindex dbsetlocate dbsetorder dbsetrelation " + "dbskip dbstruct dbunlock dbunlockall dbusearea default " + "deleted descend devout devoutpict devpos directory diskspace " + "dispbegin dispbox dispcount dispend dispout doserror " + "doserror2str dow drawline dtoc dtos empty eof errorblock " + "errorlevel eval execname execpidnum exp fattrib fclose fcount " + "fcreate ferase ferror ferror2str fieldblock fielddeci " + "fieldget fieldgetarr fieldlen fieldname fieldpos fieldput " + "fieldputarr fieldtype fieldwblock file findexefile fklabel " + "fkmax flagship_dir flock flockf fopen found fread freadstdin " + "freadstr freadtxt frename fs_set fseek fwrite getactive " + "getalign getapplykey getdosetkey getenv getenvarr getfunction " + "getpostvalid getprevalid getreader guidrawline hardcr header " + "hex2num i2bin iif indexcheck indexcount indexdbf indexext " + "indexkey indexnames indexord infobox inkey inkey2read " + "inkey2str inkeytrap instdchar instdstring int int2num isalpha " + "isbegseq iscolor isdbexcl isdbflock isdbmultip isdbmultiple " + "isdbmultipleopen isdbrlock isdigit isfunction isguimode " + "islower isobjclass isobjequiv isobjproperty isprinter isupper " + "l2bin lastkey lastrec left len listbox lock log lower ltrim " + "lupdate macroeval macrosubst max max_col max_row maxcol " + "maxrow mcol mdblck mdiclose mdiopen mdiselect memocode " + "memodecode memoedit memoencode memoline memoread memory " + "memotran memowrit memvarblock mhide min minmax mlcount " + "mlctopos mleftdown mlpos mod month mpostolc mpresent " + "mreststate mrightdown mrow msavestate msetcursor msetpos " + "mshow mstate neterr netname nextkey num2hex num2int objclone " + "oem2ansi onkey ordbagext ordbagname ordcond ordcondset " + "ordcreate orddescend orddestroy ordfor ordisinique ordkey " + "ordkeyadd ordkeycount ordkeydel ordkeygoto ordkeyno ordkeyval " + "ordlistadd ordlistclear ordlistrebui ordname ordnumber " + "ordscope ordsetfocu ordsetrelat ordskipunique os outerr " + "outstd padc padl padr param parameters pcalls pcol pcount " + "pixel2col pixel2row printstatus procfile procline procname " + "procstack proper prow qout qout2 qqout qqout2 rat rddlist " + "rddname rddsetdefault readexit readinsert readkey readkill " + "readmodal readsave readupdated readvar reccount recno recsize " + "replicate restscreen right rlock rlockverify round row " + "row2pixel rowadapt rowvisible rtrim savescreen scrdos2unix " + "screen2chr scroll scrunix2dos seconds secondscpu select " + "serial set setansi setblink setcancel setcol2get setcolor " + "setcolorba setcursor setevent setguicursor setkey setmode " + "setpos setprc setvarempty sleep sleepms soundex space sqrt " + "statbarmsg statusmessage stod str strlen strlen2col " + "strlen2pix strlen2space strpeek strpoke strtran strzero stuff " + "substr tbcolumnnew tbmouse tbrowsearr tbrowsedb tbrowsenew " + "tempfilename time tone transform trim truepath type updated " + "upper used usersactive usersdbf usersmax val valtype version " + "webdate weberrorhandler webgetenvir webgetformdata " + "webhtmlbegin webhtmlend weblogerr webmaildomain weboutdata " + "websendmail word year") + +FS_FUNC = (2, "function procedure return exit") + +FS_CLASS = (3, "class instance export hidden protect prototype") +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_FS_ASM, ''), + (stc.STC_FS_BINNUMBER, 'number_style'), + (stc.STC_FS_COMMENT, 'comment_style'), + (stc.STC_FS_COMMENTDOC, 'dockey_style'), + (stc.STC_FS_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_FS_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_FS_COMMENTLINE, 'comment_style'), + (stc.STC_FS_COMMENTLINEDOC, 'comment_style'), + (stc.STC_FS_CONSTANT, 'default_style'), + (stc.STC_FS_DATE, 'default_style'), + (stc.STC_FS_DEFAULT, 'default_style'), + (stc.STC_FS_ERROR, 'error_style'), + (stc.STC_FS_HEXNUMBER, 'number_style'), + (stc.STC_FS_IDENTIFIER, 'default_style'), + (stc.STC_FS_KEYWORD, 'keyword_style'), + (stc.STC_FS_KEYWORD2, 'keyword2_style'), + (stc.STC_FS_KEYWORD3, 'keyword3_style'), + (stc.STC_FS_KEYWORD4, 'keyword4_style'), + (stc.STC_FS_LABEL, 'default_style'), + (stc.STC_FS_NUMBER, 'number_style'), + (stc.STC_FS_OPERATOR, 'operator_style'), + (stc.STC_FS_PREPROCESSOR, 'pre_style'), + (stc.STC_FS_STRING, 'string_style'), + (stc.STC_FS_STRINGEOL, 'stringeol_style')] + +#---- Extra Properties ----# +FOLD = ('fold', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Flagship""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_FLAGSHIP) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [FS_COMMANDS, FS_STDLIB, FS_FUNC, FS_CLASS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_forth.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_forth.py new file mode 100644 index 0000000..e83b822 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_forth.py @@ -0,0 +1,121 @@ +############################################################################### +# Name: forht.py # +# Purpose: Define Forth syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: _forth.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Forth + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _forth.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# + +# Control Keywords +CONTROL_KW = (0, "again begin case do else endcase endof if loop of " + "repeat then until while [if] [else] [then] ?do") + +# Keywords +KEYWORDS = (1, "dup drop rot swap over @ ! 2@ 2! 2dup 2drop 2swap 2over nip " + "r@ >r r> 2r@ 2>r 2r>; 0= 0<; sp@ sp! w@ w! c@ c! < > = " + "<> 0<> space spaces key? key throw catch abort */ 2* /mod " + "cell+ cells char+ chars move erase dabs title hex decimal " + "hold <# # #s #> sign d. . u. dump (.\") >number ' immediate " + "exit recurse unloop leave here allot , c, w, compile, branch, " + "ret, lit, dlit, ?branch, \", >mark >resolve1 <mark >resolve " + "align aligned user-allot user-here header does> smudge hide " + ":noname last-word ?error error2 find1 sfind set-current " + "get-current definitions get-order forth only set-order also " + "previous voc-name. order latest literal 2literal sliteral " + "cliteral ?literal1 ?sliteral1 hex-literal hex-sliteral " + "?literal2 ?sliteral2 source EndOfChunk CharAddr PeekChar " + "IsDelimiter GetChar OnDelimiter SkipDelimiters OnNotDelimiter " + "SkipWord SkipUpTo ParseWord NextWord parse skip " + "console-handles refill depth ?stack ?comp word interpret bye " + "quit main1 evaluate include-file included >body +word " + "wordlist class! class@ par! par@ id. ?immediate ?voc " + "immediate VOC WordByAddrWl WordByAddr nlist words save options " + "/notransl ansi>oem accept emit cr type ekey? ekey ekey>char " + "externtask erase-imports ModuleName ModuleDirName environment? " + "drop-exc-handler set-exc-handler halt err close-file " + "create-file create-file-shared open-file-shared delete-file " + "file-position file-size open-file read-file reposition-file " + "dos-lines unix-lines read-line write-file resize-file " + "write-line allocate free resize start suspend resume stop " + "pause min max true false asciiz> r/o w/o ;class endwith or and " + "/string search compare export ;module space") + +# Definition Keywords +DEFINITION_KW = (2, "variable create : value constant vm: m: var dvar chars " + "obj constr: destr: class: object: pointer user " + "user-create user-value vect wndproc: vocabulary -- task: " + "cez: module:") + +# Prewords with one argument +PREWORDS1 = (3, "CHAR [CHAR] POSTPONE WITH ['] TO [COMPILE] CHAR ASCII \\'") + +# Prewords with two arguments +PREWORDS2 = (4, "REQUIRE WINAPI:") + +# String definition Keywords +STRING_DEF_KW = (5, "S\" ABORT\" Z\" \" .\" C\"") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_FORTH_DEFAULT, "default_style"), + (stc.STC_FORTH_COMMENT, "comment_style"), + (stc.STC_FORTH_COMMENT_ML, "comment_style"), +# ("STC_FORTH_CONTROL", ""), +# ("STC_FORTH_DEFWORD", ""), +# ("STC_FORTH_IDENTIFIER", ""), + (stc.STC_FORTH_KEYWORD, "keyword_style"), +# ("STC_FORTH_LOCALE", ""), + (stc.STC_FORTH_NUMBER, "number_style"), + (stc.STC_FORTH_PREWORD1, "keyword2_style"), + (stc.STC_FORTH_PREWORD2, "keyword3_style"), + (stc.STC_FORTH_STRING, "string_style")] + + +#---- Extra Properties ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Forth""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_FORTH) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [CONTROL_KW, KEYWORDS, DEFINITION_KW, + PREWORDS1, PREWORDS2, STRING_DEF_KW] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'\\ '] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_fortran.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_fortran.py new file mode 100644 index 0000000..8315cab --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_fortran.py @@ -0,0 +1,197 @@ +############################################################################### +# Name: fortran.py # +# Purpose: Define Fortran 77/95 syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: fortran.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Fortran f77 and f95 +@todo: check keywords more throughly + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _fortran.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +import re + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +# Fortran F77 and F95 keywords +FORT_KEYWORDS = (0, "access action advance allocatable allocate apostrophe " + "assign assignment associate asynchronous backspace bind " + "blank blockdata call case character class close common " + "complex contains continue cycle data deallocate decimal " + "delim default dimension direct do dowhile double " + "doubleprecision else elseif elsewhere encoding end " + "endassociate endblockdata enddo endfile endforall " + "endfunction endif endinterface endmodule endprogram " + "endselect endsubroutine endtype endwhere entry eor " + "equivalence err errmsg exist exit external file flush fmt " + "forall form format formatted function go goto id if " + "implicit in include inout integer inquire intent " + "interface intrinsic iomsg iolength iostat kind len " + "logical module name named namelist nextrec nml none " + "nullify number only open opened operator optional out " + "pad parameter pass pause pending pointer pos position " + "precision print private program protected public quote " + "read readwrite real rec recl recursive result return " + "rewind save select selectcase selecttype sequential sign " + "size stat status stop stream subroutine target then to " + "type unformatted unit use value volatile wait where while " + "write") + +# Fortran Functions +FORT_FUNC = (1, "abs achar acos acosd adjustl adjustr aimag aimax0 aimin0 aint " + "ajmax0 ajmin0 akmax0 akmin0 all allocated alog alog10 amax0 " + "amax1 amin0 amin1 amod anint any asin asind associated atan " + "atan2 atan2d atand bitest bitl bitlr bitrl bjtest bit_size " + "bktest break btest cabs ccos cdabs cdcos cdexp cdlog cdsin " + "cdsqrt ceiling cexp char clog cmplx conjg cos cosd cosh count " + "cpu_time cshift csin csqrt dabs dacos dacosd dasin dasind " + "datan datan2 datan2d datand date date_and_time dble dcmplx " + "dconjg dcos dcosd dcosh dcotan ddim dexp dfloat dflotk dfloti " + "dflotj digits dim dimag dint dlog dlog10 dmax1 dmin1 dmod " + "dnint dot_product dprod dreal dsign dsin dsind dsinh dsqrt " + "dtan dtand dtanh eoshift epsilon errsns exp exponent float " + "floati floatj floatk floor fraction free huge iabs iachar " + "iand ibclr ibits ibset ichar idate idim idint idnint ieor " + "ifix iiabs iiand iibclr iibits iibset iidim iidint iidnnt " + "iieor iifix iint iior iiqint iiqnnt iishft iishftc iisign " + "ilen imax0 imax1 imin0 imin1 imod index inint inot int int1 " + "int2 int4 int8 iqint iqnint ior ishft ishftc isign isnan " + "izext jiand jibclr jibits jibset jidim jidint jidnnt jieor " + "jifix jint jior jiqint jiqnnt jishft jishftc jisign jmax0 " + "jmax1 jmin0 jmin1 jmod jnint jnot jzext kiabs kiand kibclr " + "kibits kibset kidim kidint kidnnt kieor kifix kind kint kior " + "kishft kishftc kisign kmax0 kmax1 kmin0 kmin1 kmod knint knot " + "kzext lbound leadz len len_trim lenlge lge lgt lle llt log " + "log10 logical lshift malloc matmul max max0 max1 maxexponent " + "maxloc maxval merge min min0 min1 minexponent minloc minval " + "mod modulo mvbits nearest nint not nworkers " + "number_of_processors pack popcnt poppar precision present " + "product radix random random_number random_seed range real " + "repeat reshape rrspacing rshift scale scan secnds " + "selected_int_kind selected_real_kind set_exponent shape sign " + "sin sind sinh size sizeof sngl snglq spacing spread sqrt sum " + "system_clock tan tand tanh tiny transfer transpose trim " + "ubound unpack verify") + +# Fortran extended functions +FORT_EXT = (2, "cdabs cdcos cdexp cdlog cdsin cdsqrt cotan cotand dcmplx " + "dconjg dcotan dcotand decode dimag dll_export dll_import " + "doublecomplex dreal dvchk encode find flen flush getarg " + "getcharqq getcl getdat getenv gettim hfix ibchng identifier " + "imag int1 int2 int4 intc intrup invalop iostat_msg isha ishc " + "ishl jfix lacfar locking locnear map nargs nbreak ndperr " + "ndpexc offset ovefl peekcharqq precfill prompt qabs qacos " + "qacosd qasin qasind qatan qatand qatan2 qcmplx qconjg qcos " + "qcosd qcosh qdim qexp qext qextd qfloat qimag qlog qlog10 " + "qmax1 qmin1 qmod qreal qsign qsin qsind qsinh qsqrt qtan qtand " + "qtanh ran rand randu rewrite segment setdat settim system " + "timer undfl unlock union val virtual volatile zabs zcos zexp " + "zlog zsin zsqrt") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_F_COMMENT, 'comment_style'), + (stc.STC_F_CONTINUATION, 'default_style'), # NEED STYLE + (stc.STC_F_DEFAULT, 'default_style'), + (stc.STC_F_IDENTIFIER, 'default_style'), + (stc.STC_F_LABEL, 'number2_style'), # NEED STYLE + (stc.STC_F_NUMBER, 'number_style'), + (stc.STC_F_OPERATOR, 'operator_style'), + (stc.STC_F_OPERATOR2, 'operator_style'), # NEED STYLE + (stc.STC_F_PREPROCESSOR, 'pre_style'), + (stc.STC_F_STRING1, 'string_style'), + (stc.STC_F_STRING2, 'string_style'), + (stc.STC_F_STRINGEOL, 'stringeol_style'), + (stc.STC_F_WORD, 'keyword_style'), + (stc.STC_F_WORD2, 'keyword3_style'), + (stc.STC_F_WORD3, 'funct_style')] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_COMP = ("fold.compact", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Fortran 77/95""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + if self.LangId == synglob.ID_LANG_F77: + self.SetLexer(stc.STC_LEX_F77) + else: + self.SetLexer(stc.STC_LEX_FORTRAN) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [FORT_KEYWORDS, FORT_FUNC , FORT_EXT] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_COMP] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + if self.LangId == synglob.ID_LANG_F77: + return ['*'] + elif self.LangId == synglob.ID_LANG_F95: + return ['!'] + else: + return list() + +#---- End Required Module Functions ----# + +def AutoIndenter(estc, pos, ichar): + """Auto indent cpp code. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + + """ + rtxt = u'' + line = estc.GetCurrentLine() + text = estc.GetTextRange(estc.PositionFromLine(line), pos) + eolch = estc.GetEOLChar() + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + ndent = eolch + ichar * i_space + rtxt = ndent + ((indent - (tabw * i_space)) * u' ') + + blks = '(program|function|subroutine|if|do|while)' + blk_pat = re.compile(blks + '\s*[(a-zA-Z][a-zA-Z0-9]*', re.IGNORECASE) + text = text.strip() + if text.endswith('{') or blk_pat.match(text) or text == 'else': + rtxt += ichar + + # Put text in the buffer + estc.AddText(rtxt) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_glsl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_glsl.py new file mode 100644 index 0000000..aa9a0a3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_glsl.py @@ -0,0 +1,66 @@ +############################################################################### +# Name: glsl.py # +# Purpose: Define C/CPP/ObjC/Vala syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: glsl.py +@author: Cody Precord +@summary: Lexer configuration file for GLSL source files. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id$" +__revision__ = "$Revision$" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +import re + +# Local imports +import synglob +import syndata + +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# C Keywords +GLSL_KEYWORDS = (0, "attribute uniform varying const layout centroid varying flat " + "smooth noperspective patch sample break continue do for while " + "switch case default if else subroutine in out inout true false " + "invariant discard return lowp mediump highp precision") + +# C Types/Structures/Storage Classes +GLSL_TYPES = (1, "mat2 mat3 float double int void bool mat4 dmat2 dmat3 dmat4 mat2x2 " + "mat2x3 mat2x4 dmat2x2 dmat2x3 dmat2x4 mat3x2 mat3x3 mat3x4 dmat3x2 " + "dmat3x3 dmat3x4 mat4x2 mat4x3 mat4x4 dmat4x2 dmat4x3 dmat4x4 vec2 " + "vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 dvec2 dvec3 dvec4 uint " + "uvec2 uvec3 uvec4 sampler1D sampler2D sampler3D samplerCube " + "sampler1DShadow sampler2DShadow samplerCubeShadow sampler1DArray " + "sampler2DArray sampler1DArrayShadow sampler2DArrayShadow isampler1D " + "isampler2D isampler3D isamplerCube isampler1DArray isampler2DArray " + "usampler1D usampler2D usampler3D usamplerCube usampler1DArray " + "usampler2DArray sampler2DRect sampler2DRectShadow isampler2DRect " + "usampler2DRect samplerBuffer isamplerBuffer usamplerBuffer sampler2DMS " + "isampler2DMS usampler2DMS sampler2DMSArray isampler2DMSArray " + "usampler2DMSArray samplerCubeArray samplerCubeArrayShadow " + "isamplerCubeArray usamplerCubeArray struct") + +#------------------------------------------------------------------------------# + +class SyntaxData(_cpp.SyntaxData): + """SyntaxData object for many C like languages""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + def GetKeywords(self): + """Returns Specified Keywords List""" + return [GLSL_KEYWORDS, GLSL_TYPES, _cpp.DOC_KEYWORDS] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_groovy.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_groovy.py new file mode 100644 index 0000000..1ab9cc4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_groovy.py @@ -0,0 +1,117 @@ +############################################################################### +# Name: groovy.py # +# Purpose: Define Groovy syntax for highlighting and other features # +# Author: Omar Gomez <omar.gomez@gmail.com> # +# Copyright: (c) 2009 Omar Gomez <omar.gomez@gmail.com> # +# License: wxWindows License # +############################################################################### + +""" +FILE: groovy.py +AUTHOR: Omar Gomez +@summary: Lexer configuration module for Groovy (based on the Java one). + +""" + +__author__ = "Omar Gomez <omar.gomez@gmail.com>" +__svnid__ = "$Id: _groovy.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +from _cpp import AutoIndenter + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +MAIN_KEYWORDS = (0, +""" +as assert Boolean Byte Character Class Double Float Integer Long Number Object +Short String property void abstract assert boolean break byte case catch char +class const continue default do double else extends false final finally float +for goto if implements import instanceof in int interface long native new null +package private protected public return short static strictfp super switch +synchronized this throw throws transient true try void volatile while def +""" +) + +SECONDARY_KEYWORDS= (1, +""" +abs accept allProperties and any append asImmutable asSynchronized asWritable +center collect compareTo contains count decodeBase64 div dump each eachByte +eachFile eachFileRecurse eachLine eachMatch eachProperty eachPropertyName +eachWithIndex encodeBase64 every execute filterLine find findAll findIndexOf +flatten getErr getIn getOut getText inject inspect intersect intdiv invokeMethod +isCase join leftShift max min minus mod multiply negate newInputStream +newOutputStream newPrintWriter newReader newWriter next or padLeft padRight +plus pop previous print println readBytes readLine readLines reverse +reverseEach rightShift rightShiftUnsigned round size sort splitEachLine step +subMap times toDouble toFloat toInteger tokenize toList toLong toURL +transformChar transformLine upto use waitForOrKill withInputStream +withOutputStream withPrintWriter withReader withStream withStreams withWriter +withWriterAppend write writeLine +""" +) + + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'stringeol_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, 'number2_style'), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_PRE = ("styling.within.preprocessor", "0") +FOLD_COM = ("fold.comment", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Groovy""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [MAIN_KEYWORDS, SECONDARY_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_PRE] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [ u'//' ] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_gui4cli.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_gui4cli.py new file mode 100644 index 0000000..715738f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_gui4cli.py @@ -0,0 +1,148 @@ +############################################################################### +# Name: gui4cli.py # +# Purpose: Syntax configuration for the Gui4Cli programming language # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: gui4cli.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Gui4Cli + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _gui4cli.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +GLOBALS = (0, "3STATE #ANSI #FIXANSI #FIXOEM #FIXSYS #GUI #SEPARATOR #SYS ABRI " + "ACTIVE ALL ALTSTART APPDATA APPWIN ARRANGE ARROW ASCEND AUTO " + "BACK BC BITBUCKET BL BOLD BORDER BOTTOM BR BUFFERS BUSY BUTTON " + "BUTTONS CAPTION CENTER CHAR CHECK CHILD CLEAN CLEAR CLOSED " + "COLOR COMM COMMON.ALTSTART COMMON.DESKTOP COMMON.FAVORITES " + "COMMON.MENU COMMON.PROGRAMS COMMON.STARTUP COOKIES CROSS CURDIR " + "CURRENT CURSOR DATA DATE DAY DECORATIVE DEF1 DEF2 DEF3 DEF4 " + "DESCEND DESKTOP DIALOG DIR DISABLE DISABLED DISK DISKS DLBEGIN " + "DLCOMPLETE DLGFRAME DOUBLE DRAG DROP DROPLIST DTTM EDIT EDITOR " + "EFFECTS ELLIPSE EMBOSS END ENABLE ENDGUI ENGLISH ENTER ERROR " + "EXISTS EXPLORE EXT FAIL FAVORITES FIELDS FILE FILES FIND FIRST " + "FIXED FIXWIDTH FLAT FNUMBER FOCUS FOREGROUND FORMAT FORWARD " + "FREE FRONT FULL FULLPATH GCDIR GCEXE GCNAME GREEK GRID GUIPATH " + "HEAVY HEIGHT HELP HEX HIDDEN HIDE HIST HISTORY HOME HORIZONTAL " + "HOT HOUR IBEAM ICLEFT INDEX INFO INT INVOKE ITALIC ITEM JULIAN " + "JUSTIFY LARGE LAST LB LBLEFT LC LENGTH LIGHT LINE LINES LMB " + "LMDC LOAD LOADED LOWER LT MAX MAXI MAXBOX MAXIMIZE MEDIUM MENU " + "MINBOX MINI MINIMIZE MINUTE MMB MODERN MONTH MOVE MSEC MULTI " + "NAME NAVCOMPLETE NETCACHE NETHOOD NEW NEWMENU NEXT NO NOADJUST " + "NOBORDER NOERROR NOEXT NOFACE NOFILES NOFOCUS NOFOLDERS NONE " + "NOOPEN NOREFRESH NORESET NORMAL NORTH NOSIZE NOVECTOR NOVRT NOW " + "NOWRAP NUMBER OCTAL OFF OK OKCANCEL ON ONECLICK ONELINE OPEN " + "OVERLAP OWNED PARENT PATH PCPATH PERIOD PERSONAL POLYGON PREFS " + "PREV PREVIOUS PRINT PRINTERS PROGRAMS PROP PROPERTY PULSE " + "QUESTION QUOTE RAGGED RAISED RB RC REC RECENT REFRESH REMOVE " + "REMSIZE RENAME REPORT RESIZE RET RETRY RIGHT RMB ROMAN ROOT " + "ROUNDED ROUTINE ROWS RT SAVE SCALABLE SCREEN SCRIPT SCROLL " + "SEARCH SECOND SELECT SELECTED SELSCRIPT SENDTO SENSITIVE " + "SENTENCE SHELL SHOW SILENT SIMPLE SINGLE SIZE SMALL SMOOTH " + "SOLID SORT START STARTGUI STARTUP STAT0 STATIC STATUS STD STOP " + "STRECH STRIKE SUBCHILD SUBSUB SUNK SUNKEN SWISS SYSMENU TAB " + "TABS TC TEMPLATES TEXT THIN TIME TITLE TL TOGGLE TOOL TOP " + "TOPMOST TOTAL TR TRANS TRANSPARENT TTONLY TYPE UNDERLINE " + "UNFORMAT UNJULIAN UNQUOTE UNSELECT UNSELECTED UPPER USER VALID " + "VARIABLE VCENTER VERSION VERTICAL VIEW WAIT WARN WHEEL WIDTH " + "WINEDGE WORD YEAR YES YESNO YESTOALL YNCANCEL") + +EVENTS = (1, "XAREA XBROWSER XBUTTON XCHECKBOX XCOMBO XEDBOX XGROUPBOX XICON " + "XIMAGE XLISTVIEW XMENU XPAN XPROGRESS XRADIO XREBAR XSPLITER " + "XSTATUS XTAB XTEXTBOX XTEXTIN XTOOLBAR XTRACKBAR XTREEVIEW " + "XUPDOWN XAFTER XATTR XBEFORE XENUM XHOTKEY XNOTIFY XONACTIVE " + "XONBROWSER XONCLICK XONCLOSE XONDOUBLECLICK XONDROP XONFAIL " + "XONHELP XONINACTIVE XONKEY XONLMB XONLOAD XONLVCLICK XONLVDIR " + "XONMARK XONMMB XONOPEN XONQUIT XONRELOAD XONRETURN XONRMB " + "XONTEXTIN XONWHEELDOWN XONWHEELUP XPIPE XREQFILE XROUTINE " + "XTBARICON XTIMER XONKEY") + +ATTRIBUTES = (2, "ATTR BACKGROUND BUDDY BUFFERS COLORS COLSAVE DATA DBGSTEP DBGVARS " + "DEBUG DEEPTRANS EDITOR ENDGUI ESCAPE FAIL FILTER FONT FRAME " + "GRID HELP ICON ID IXICON KEY LIKE LOCAL LVCOLUMN MAXDATE " + "MAXSIZE MAXTRANS MCINOTIFY MCISIGNAL MENU MINDATE MINSIZE " + "NEXT OUTPUT PAGE PARENT PATH PREFS RBSTYLE RESIZE SAY SHAPE " + "SHOW STARTGUI STYLE TAB TITLE TRANSLATE VARIABLES") + +CONTROL = (3, "AND ANDIFEXISTS BREAK CALL CASE DOCASE ELSE ELSEIF ELSEIFEXISTS " + "ENDCASE ENDFOR ENDIF ENDWHILE FOR GO GOSUB GOTO IF IFEXISTS " + "LABEL OR ORIFEXISTS QUIT RETURN STOP WHILE") + +COMMANDS = (4, "ADD ADDRESS ADDUNIQUE APPEND APPVAR ASSIGN AUTO BRANCH BROWSER " + "CD CLOSE COMBO COMMAND COPY CREATE CREATELINK CUT CUTVAR DBSUM " + "DCKDEBUG DDEXEC DDPUT DDUSE DEC DEL DELAY DELETE DELVAR EDBOX " + "EMPTYBIN ENUM EXIT EXTRACT FLASH FREEFONT FREEICON GETCLIP " + "GETCOLOR GETFONT GOSUB GUI GUICLOSE GUILOAD GUIOPEN GUIQUIT " + "GUIRENAME GUIWINDOW HTMLHELP IMAGE INC JOINFILE LAUNCH " + "LISTVIEW LOADFONT LOADICON LV LVACTION LVCLIP LVREP LVSEARCH " + "LVSWITCH MAKEDIR MCI MOVE MSGBOX NEWFILE PARSEVAR POPMENU " + "QUICKMENU QUIT RANDOM REGCREATE REGDELETE REGGET REGSET RENAME " + "REPVAR REQFILE RUN SAY SEARCHVAR SEND SET SETATTR SETCLIP " + "SETEVENT SETGADVALUES SETICON SETPOINTER SETVAR SETWINATTR " + "SETWINTITLE SHELL STATUS SYSTEM TERMINATEPROC TEXTFILE " + "TREEVIEW TV UPDATE UPDOWN USE WAIT WINATTR WINDOW") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_GC_ATTRIBUTE, 'keyword3_style'), + (stc.STC_GC_COMMAND, 'keyword2_style'), + (stc.STC_GC_COMMENTBLOCK, 'comment_style'), + (stc.STC_GC_COMMENTLINE, 'comment_style'), + (stc.STC_GC_CONTROL, 'keyword_style'), + (stc.STC_GC_DEFAULT, 'default_style'), + (stc.STC_GC_EVENT, 'keyword4_style'), + (stc.STC_GC_GLOBAL, 'global_style'), + (stc.STC_GC_OPERATOR, 'operator_style'), + (stc.STC_GC_STRING, 'string_style')] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_COMP = ("fold.compact", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Gui4Cli""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_GUI4CLI) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [GLOBALS, EVENTS, ATTRIBUTES, CONTROL, COMMANDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set + @note: gui4cli supports folding but it seems to be partially broken + + """ + return list() #[FOLD, FOLD_COMP] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haskell.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haskell.py new file mode 100644 index 0000000..7ce487a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haskell.py @@ -0,0 +1,84 @@ +############################################################################### +# Name: haskell.py # +# Purpose: Define Haskell syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" + FILE: haskell.py + AUTHOR: Cody Precord + @summary: Lexer configuration module for the Haskell Programming Language + @todo: More custom highlighting + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _haskell.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +HA_KEYWORDS = (0, "as case class data default deriving do forall foreign " + "hiding if import in infix infixl infixr instance else let " + "mdo module newtype of qualified then type where") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_HA_CAPITAL, 'default_style'), + (stc.STC_HA_CHARACTER, 'char_style'), + (stc.STC_HA_CLASS, 'class_style'), + (stc.STC_HA_COMMENTBLOCK, 'comment_style'), + (stc.STC_HA_COMMENTBLOCK2, 'comment_style'), + (stc.STC_HA_COMMENTBLOCK3, 'comment_style'), + (stc.STC_HA_COMMENTLINE, 'comment_style'), + (stc.STC_HA_DATA, 'default_style'), + (stc.STC_HA_DEFAULT, 'default_style'), + (stc.STC_HA_IDENTIFIER, 'default_style'), + (stc.STC_HA_IMPORT, 'default_style'), # possibly use custom style + (stc.STC_HA_INSTANCE, 'default_style'), + (stc.STC_HA_KEYWORD, 'keyword_style'), + (stc.STC_HA_MODULE, 'default_style'), + (stc.STC_HA_NUMBER, 'number_style'), + (stc.STC_HA_OPERATOR, 'operator_style'), + (stc.STC_HA_STRING, 'string_style')] + +#---- Extra Properties ----# +FOLD = ('fold', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Haskell""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_HASKELL) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [HA_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'--'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haxe.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haxe.py new file mode 100644 index 0000000..c9f46a0 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_haxe.py @@ -0,0 +1,65 @@ +############################################################################### +# Name: haxe.py # +# Purpose: Syntax Definitions for haXe web language # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +@summary: Lexer configuration module for haXe web programming language + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _haxe.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +HAXE_KW = (0, "abstract break case catch class const continue trace do else " + "enum extends finally for function goto if implements import in " + "instanceof int interface new package private public return " + "static super switch this throw throws transient try typeof var " + "void volatile while with" ) + +HAXE_TYPES = (1, "Bool Enum false Float Int null String true Void ") + +#---- End Keyword Definitions ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for HaXe""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [HAXE_KW, HAXE_TYPES, _cpp.DOC_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _cpp.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [_cpp.FOLD,] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return ['//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_html.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_html.py new file mode 100644 index 0000000..a4b7399 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_html.py @@ -0,0 +1,297 @@ +############################################################################### +# Name: html.py # +# Purpose: Define HTML syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: html.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for HTML/DHTML/SGML. +@todo: Add Netscape/Microsoft Tag Extenstions (maybe) +@todo: Styleing needs lots of tweaking + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _html.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _javascript +import _vbscript + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# HTML Tags (HTML4) +HTML_TAGS = (0, "address applet area a base basefont big blockquote br caption " + "center cite code dd dfn dir div dl dt font form hr html img " + "input isindex kbd li link map menu meta ol option param pre p " + "samp span select small strike sub sup table td textarea th tr " + "script noscript tt ul var xmp b i u h1 h2 h3 h4 h5 h6 em " + "strong head body title " + # HTML 4.0 Tags + "abbr acronym bdo button col label colgroup del fieldset " + "iframe ins legend object optgroup q s tbody tfoot thead " + # HTML 5 Tags + "article aside audio canvas command datalist details dialog " + "embed figcaption figure footer header hgroup keygen mark " + "meter nav output progress rp rt ruby section source time " + "video " + # Tag Attributes / Arguments + "action align alink alt archive background bgcolor border " + "bordercolor cellpadding cellspacing checked class clear " + "codebase color cols colspan content coords enctype face " + "gutter height hspace id link lowsrc marginheight marginwidth " + "maxlength method name prompt rel rev rows rowspan scrolling " + "selected shape size src start target text type url usemap " + "ismap valign value vlink vspace width wrap href http-equiv " + # HTML 4 Tag Attributes /Arguments + "accept accesskey axis char charoff charset cite classid " + "codetype compact data datetime declare defer dir disabled for " + "frame headers hreflang lang language longdesc multiple nohref " + "nowrap profile readonly rules scheme scope standby style " + "summary tabindex valuetype version " + # HTML 5 Tag Attributes / Arguments + "async autocomplete contenteditable contextmenu date " + "datetime-local draggable email formaction formenctype " + "formmethod formnovalidate formtarget hidden list manifest max " + "media min month novalidate number pattern ping range required " + "reversed role sandbox scoped seamless search sizes spellcheck " + "srcdoc step tel week " + # DHTML Support + "dtml-var dtml-if dtml-unless dtml-in dtml-with dtml-let " + "dtml-call dtml-raise dtml-try dtml-comment dtml-tree") + +#---- Extra defs ----# +# ColdFusion Tags +CF_TAGS = ("cfabort cfapplet cfapplication cfargument cfassociate cfbreak " + "cfcache cfcalendar cfcase cfcatch cfchart cfchartdata " + "cfchartseries cfcol cfcollection cfcomponent cfcontent cfcookie " + "cfdefaultcase cfdirectory cfdocument cfdocumentitem " + "cfdocumentsection cfdump cfelse cfelseif cferror cfexecute cfexit " + "cffile cfflush cfform cfformgroup cfformitem cfftp cffunction " + "cfgrid cfgridcolumn cfgridrow cfgridupdate cfheader cfhtmlhead " + "cfhttp cfhttpparam cfif cfimport cfinclude cfindex cfinput " + "cfinsert cfinvoke cfinvokeargument cfldap cflocation cflock cflog " + "cflogin cfloginuser cflogout cfloop cfmail cfmailparam cfmailpart " + "cfmodule cfNTauthenticate cfobject cfobjectcache cfoutput cfparam " + "cfpop cfprocessingdirective cfprocparam cfprocresult cfproperty " + "cfquery cfqueryparam cfregistry cfreport cfreportparam cfrethrow " + "cfreturn cfsavecontent cfschedule cfscript cfsearch cfselect cfset " + "cfsetting cfsilent cfslider cfstoredproc cfswitch cftable " + "cftextarea cfthrow cftimer cftrace cftransaction cftree cftreeitem " + "cftry cfupdate cfwddx cfxml") + +# JavaScript Keywords (see javascript.py) +JS_KEYWORDS = (1, _javascript.KeywordString(synglob.ID_LANG_JS)) + +# VBScript Keywords (currently unsupported) +VBS_KEYWORDS = (2, _vbscript.VBS_KW) + +# Python Keywords (see python.py) +PY_KEYWORDS = (3, "") + +# PHP Keywords (see php.py) +# This module is loaded for files with a .html/htm extension so it is assumed +# that there is no php in the file. On the other hand the php module loads +# this module so that it can support embedded html. This behavior may be changed +# in the future + +# XML Keywords (see xml.py) +# XML files are handled independantly from html although there is support for +# embedded xml highlighting it is currently not being used. + +# SGML Keywords +SGML_KEYWORDS = (5, "ELEMENT DOCTYPE ATTLIST ENTITY NOTATION") +#SGML_KEYWORDS = (5, "#CURRENT #IMPLIED #REQUIRED ATTLIST CDATA DOCTYPE " +# "ELEMENT ENTITY HTML IDREF INCLUDE IGNORE NMTOKEN NUMBER " +# "RCDATA TEMP") + +# SGML Block Keywords +SGML_BLOCK = (7, "") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_H_DEFAULT, 'default_style'), + (stc.STC_H_ASP, 'array_style'), + (stc.STC_H_ASPAT, 'array_style'), + (stc.STC_H_ATTRIBUTE, 'keyword2_style'), + (stc.STC_H_ATTRIBUTEUNKNOWN, 'error_style'), + (stc.STC_H_CDATA, 'default_style'), # Style ME + (stc.STC_H_COMMENT, 'comment_style'), + (stc.STC_H_DOUBLESTRING, 'string_style'), + (stc.STC_H_ENTITY, 'default_style'), # Style ME + (stc.STC_H_NUMBER, 'number_style'), + (stc.STC_H_OTHER, 'default_style'), # Style ME + (stc.STC_H_QUESTION, 'scalar_style'), + (stc.STC_H_SCRIPT, 'funct_style'), # STYLE ME + (stc.STC_H_SGML_1ST_PARAM, 'keyword2_style'), # STYLE ME + (stc.STC_H_SGML_1ST_PARAM_COMMENT, 'comment_style'), + (stc.STC_H_SGML_BLOCK_DEFAULT, 'default_style'), # STYLE ME + (stc.STC_H_SGML_COMMAND, 'keyword_style'), # STYLE ME + (stc.STC_H_SGML_COMMENT, 'comment_style'), + (stc.STC_H_SGML_DEFAULT, 'array_style'), # STYLE ME + (stc.STC_H_SGML_DOUBLESTRING, 'string_style'), + (stc.STC_H_SGML_ENTITY, 'default_style'), # STYLE ME + (stc.STC_H_SGML_ERROR, 'error_style'), + (stc.STC_H_SGML_SIMPLESTRING, 'string_style'), + (stc.STC_H_SGML_SPECIAL, 'default_style'), # STYLE ME + (stc.STC_H_SINGLESTRING, 'string_style'), + (stc.STC_H_TAG, 'keyword_style'), + (stc.STC_H_TAGEND, 'keyword_style'), + (stc.STC_H_TAGUNKNOWN, 'error_style'), + (stc.STC_H_VALUE, 'number_style'), + (stc.STC_H_XCCOMMENT, 'comment_style'), + (stc.STC_H_XMLEND, 'scalar_style'), + (stc.STC_H_XMLSTART, 'scalar_style'), + + # Embedded JavaScript + (stc.STC_HJ_COMMENT, 'comment_style'), + (stc.STC_HJ_COMMENTDOC, 'comment_style'), + (stc.STC_HJ_COMMENTLINE, 'comment_style'), + (stc.STC_HJ_DEFAULT, 'default_style'), + (stc.STC_HJ_DOUBLESTRING, 'default_style'), # STYLE ME + (stc.STC_HJ_KEYWORD, 'default_style'), # STYLE ME + (stc.STC_HJ_NUMBER, 'default_style'), # STYLE ME + (stc.STC_HJ_REGEX, 'default_style'), # STYLE ME + (stc.STC_HJ_SINGLESTRING, 'default_style'), # STYLE ME + (stc.STC_HJ_START, 'default_style'), # STYLE ME + (stc.STC_HJ_STRINGEOL, 'default_style'), # STYLE ME + (stc.STC_HJ_SYMBOLS, 'default_style'), # STYLE ME + (stc.STC_HJ_WORD, 'default_style'), # STYLE ME + + (stc.STC_HJA_COMMENT, 'comment_style'), + (stc.STC_HJA_COMMENTDOC, 'comment_style'), + (stc.STC_HJA_COMMENTLINE, 'comment_style'), + (stc.STC_HJA_DEFAULT, 'default_style'), + (stc.STC_HJA_DOUBLESTRING, 'default_style'), # STYLE ME + (stc.STC_HJA_KEYWORD, 'default_style'), # STYLE ME + (stc.STC_HJA_NUMBER, 'default_style'), # STYLE ME + (stc.STC_HJA_REGEX, 'default_style'), # STYLE ME # STYLE ME + (stc.STC_HJA_SINGLESTRING, 'default_style'), # STYLE ME + (stc.STC_HJA_START, 'default_style'), # STYLE ME + (stc.STC_HJA_STRINGEOL, 'default_style'), # STYLE ME + (stc.STC_HJA_SYMBOLS, 'default_style'), # STYLE ME + (stc.STC_HJA_WORD, 'default_style'), + + (stc.STC_HBA_DEFAULT, 'operator_style'), # Styles ( ) ? + (stc.STC_HBA_COMMENTLINE, 'comment_style'), + (stc.STC_HBA_IDENTIFIER, 'default_style'), # TODO + (stc.STC_HBA_NUMBER, 'number_style'), + (stc.STC_HBA_START, 'default_style'), # TODO + (stc.STC_HBA_STRING, 'string_style'), + (stc.STC_HBA_STRINGEOL, 'stringeol_style'), + (stc.STC_HBA_WORD, 'keyword_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FLD_HTML = ("fold.html", "1") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Html and related languages""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_HTML) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List""" + if self.LangId == synglob.ID_LANG_COLDFUSION: + return [(HTML_TAGS[0], HTML_TAGS[1] + " " + CF_TAGS), JS_KEYWORDS] + else: + return [HTML_TAGS, JS_KEYWORDS, SGML_KEYWORDS, VBS_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications""" + return SYNTAX_ITEMS + _javascript.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set""" + return [FOLD, FLD_HTML] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code""" + return [u'<!--', u'-->'] + +#-----------------------------------------------------------------------------# + +def AutoIndenter(estc, pos, ichar): + """Auto indent python code. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + + """ + rtxt = u'' + line = estc.GetCurrentLine() + spos = estc.PositionFromLine(line) + text = estc.GetTextRange(spos, pos) + eolch = estc.GetEOLChar() + inspace = text.isspace() + + # Cursor is in the indent area somewhere + if inspace: + estc.AddText(eolch + text) + return + + # Check if the cursor is in column 0 and just return newline. + if not len(text): + estc.AddText(eolch) + return + + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + # Standard indent to match previous line + indent = estc.GetLineIndentation(line) + levels = indent / tabw + end_spaces = ((indent - (tabw * levels)) * u" ") + rtxt = eolch + (ichar * levels) + end_spaces + + # Check if we need some 'special' indentation + tmp = text.rstrip() + if tmp.endswith(u">"): + # At a tag check for if we need extra indentation + tagstart = tmp.rfind(u"<") + if tagstart >= 0: + tagval = tmp[tagstart:] + if not tagval.startswith(u"</") and \ + not tagval.endswith(u"/>") and \ + not tagval.endswith(u"?>"): + # Cursor is after an opening tag so we need to indent more + # First match to the starting tag + levels = (tagstart / tabw) # Add an extra level + end_spaces = ((tagstart - (tabw * levels)) * u" ") + rtxt = eolch + (ichar * (levels+1)) + end_spaces + + # Put text in the buffer + estc.AddText(rtxt) + +#---- Syntax Modules Internal Functions ----# +def KeywordString(option=0): + """Returns the specified Keyword String + @param option: specific subset of keywords to get + + """ + if option == synglob.ID_LANG_SGML: + return SGML_KEYWORDS[1] + else: + return HTML_TAGS[1] + +#---- End Syntax Modules Internal Functions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_inno.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_inno.py new file mode 100644 index 0000000..45d9312 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_inno.py @@ -0,0 +1,176 @@ +############################################################################### +# Name: inno.py # +# Purpose: Syntax configuration module for Inno Setup Scripts # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: inno.py +AUTHOR: Cody Preord +@summary: Lexer configuration module for Inno Setup Scripts + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _inno.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc +import re + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +SECTION_KW = (0, "code components custommessages dirs files icons ini " + "installdelete langoptions languages messages registry run " + "setup types tasks uninstalldelete uninstallrun _istool") + +KEYWORDS = (1, "allowcancelduringinstall allownoicons allowrootdirectory " + "allowuncpath alwaysrestart alwaysshowcomponentslist " + "alwaysshowdironreadypage alwaysshowgrouponreadypage " + "alwaysusepersonalgroup appcomments appcontact appcopyright " + "appenddefaultdirname appenddefaultgroupname appid appmodifypath " + "appmutex appname apppublisher apppublisherurl appreadmefile " + "appsupporturl appupdatesurl appvername appversion " + "architecturesallowed architecturesinstallin64bitmode backcolor " + "backcolor2 backcolordirection backsolid changesassociations " + "changesenvironment compression copyrightfontname " + "copyrightfontsize createappdir createuninstallregkey " + "defaultdirname defaultgroupname defaultuserinfoname " + "defaultuserinfoorg defaultuserinfoserial dialogfontname " + "dialogfontsize direxistswarning disabledirpage " + "disablefinishedpage disableprogramgrouppage disablereadymemo " + "disablereadypage disablestartupprompt diskclustersize " + "diskslicesize diskspanning enablesdirdoesntexistwarning " + "encryption extradiskspacerequired flatcomponentslist " + "infoafterfile infobeforefile internalcompresslevel " + "languagedetectionmethod languagecodepage languageid languagename " + "licensefile mergeduplicatefiles minversion onlybelowversion " + "outputbasefilename outputdir outputmanifestfile password " + "privilegesrequired reservebytes restartifneededbyrun " + "setupiconfile showcomponentsizes showlanguagedialog " + "showtaskstreelines slicesperdisk solidcompression sourcedir " + "timestamprounding timestampsinutc titlefontname titlefontsize " + "touchdate touchtime uninstallable uninstalldisplayicon " + "uninstalldisplayname uninstallfilesdir uninstalllogmode " + "uninstallrestartcomputer updateuninstalllogappname " + "usepreviousappdir usepreviousgroup useprevioussetuptype " + "useprevioustasks useprevioususerinfo userinfopage usesetupldr " + "versioninfocompany versioninfocopyright versioninfodescription " + "versioninfotextversion versioninfoversion welcomefontname " + "welcomefontsize windowshowcaption windowstartmaximized " + "windowresizable windowvisible wizardimagebackcolor " + "wizardimagefile wizardimagestretch wizardsmallimagefile") + +PARAM_KW = (2, "afterinstall attribs beforeinstall check comment components " + "copymode description destdir destname excludes " + "extradiskspacerequired filename flags fontinstall " + "groupdescription hotkey infoafterfile infobeforefile " + "iconfilename iconindex key languages licensefile messagesfile " + "minversion name onlybelowversion parameters permissions root " + "runonceid section source statusmsg string subkey tasks type " + "types valuedata valuename valuetype workingdir") + +PREPROC_KW = (3, "append define dim else emit endif endsub error expr file for " + "if ifdef ifexist ifndef ifnexist include insert pragma sub " + "undef") + +PASCAL_KW = (4, "begin break case const continue do downto else end except " + "finally for function if of procedure repeat then to try until " + "uses var while with") + +USER_DEF = (5, "") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_INNO_COMMENT, 'comment_style'), + (stc.STC_INNO_COMMENT_PASCAL, 'comment_style'), + (stc.STC_INNO_DEFAULT, 'default_style'), + (stc.STC_INNO_IDENTIFIER, 'default_style'), + (stc.STC_INNO_KEYWORD, 'keyword_style'), + (stc.STC_INNO_KEYWORD_PASCAL, 'keyword4_style'), + (stc.STC_INNO_KEYWORD_USER, 'default_style'), + (stc.STC_INNO_PARAMETER, 'keyword2_style'), + (stc.STC_INNO_PREPROC, 'pre_style'), + (stc.STC_INNO_SECTION, 'scalar_style'), + (stc.STC_INNO_STRING_DOUBLE, 'string_style'), + (stc.STC_INNO_STRING_SINGLE, 'char_style')] + +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS.append((stc.STC_INNO_INLINE_EXPANSION, 'default_style')) #TODO +else: + SYNTAX_ITEMS.append((stc.STC_INNO_PREPROC_INLINE, 'pre_style')) + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_COMP = ("fold.compact", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Inno Setup Scripts""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_INNOSETUP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [SECTION_KW, KEYWORDS, PARAM_KW, PREPROC_KW, PASCAL_KW] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + # Note: Inno can also use pascal comments (i.e {}) + return [u';'] + +#-----------------------------------------------------------------------------# + +def AutoIndenter(estc, pos, ichar): + """Auto indent Inno Setup Scripts. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + + """ + rtxt = u'' + line = estc.GetCurrentLine() + text = estc.GetTextRange(estc.PositionFromLine(line), pos) + eolch = estc.GetEOLChar() + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + ndent = eolch + ichar * i_space + rtxt = ndent + ((indent - (tabw * i_space)) * u' ') + + if_pat = re.compile('if\s+.*\sthen') + text = text.strip() + if text == u'begin' or if_pat.match(text): + rtxt += ichar + + # Put text in the buffer + estc.AddText(rtxt) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_issuelist.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_issuelist.py new file mode 100644 index 0000000..bac72c3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_issuelist.py @@ -0,0 +1,127 @@ +############################################################################### +# Name: issuelist.py # +# Purpose: Define IssueList syntax for highlighting and other features # +# Author: Torsten Mohr # +# Copyright: (c) 2008 Cody Precord # +# (c) 2008 Torsten Mohr # +# License: wxWindows License # +############################################################################### + +""" +FILE: issuelist.py +AUTHOR: Cody Precord, Torsten Mohr +@summary: Lexer configuration module for Issue Lists. + +""" + +__author__ = "Cody Precord <cprecord>, Torsten Mohr <none_yet>" +__svnid__ = "$Id: _issuelist.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +#Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# +# Style Id's + +(STC_ISSL_DEFAULT, +STC_ISSL_COMMENT, +STC_ISSL_GREEN, +STC_ISSL_RED, +STC_ISSL_ORANGE, +STC_ISSL_BLUE, +STC_ISSL_PURPLE, +STC_ISSL_PINK) = range(8) + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ + (STC_ISSL_DEFAULT, 'default_style'), + (STC_ISSL_COMMENT, 'comment_style'), + (STC_ISSL_GREEN, 'regex_style'), + (STC_ISSL_RED, 'number_style'), + (STC_ISSL_ORANGE, 'keyword4_style'), + (STC_ISSL_BLUE, 'dockey_style'), + (STC_ISSL_PURPLE, 'scalar2_style'), + (STC_ISSL_PINK, 'char_style'), + ] + +issl_table = ';+-?.#~' + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for IssueLists + This class is primarly intended as an example to creating a custom + lexer + + """ + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CONTAINER) + self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText) + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + +#---- End Required Module Functions ----# + +# ; comment +# + done +# - open +# ? question +# . info +# # strong +# ~ +# * + +def StyleText(stc, start, end): + """Style the text + @param stc: Styled text control instance + @param start: Start position + @param end: end position + + """ + + # First, figure out the line based on the position. + line = stc.LineFromPosition(start) + + # Find the start of the line that's been styled before this one. + while line > 0 and stc.GetLineState(line) == 0: + line -= 1 + + eline = stc.LineFromPosition(end) + + state = stc.GetLineState(line) - 1 + if state < 0: + state = 0 + + for ln in range(line, eline + 1): + text = stc.GetLine(ln).encode('utf-8') + len_text = len(text) + text = text.strip() + + if len(text) == 0: + state = 0 + else: + if len(text) > 0: + ch = text[0] + ix = issl_table.find(ch) + if ix >= 0: + state = ix + 1 + + stc.StartStyling(stc.PositionFromLine(ln), 0xFF) + stc.SetStyling(len_text, state) + + stc.SetLineState(ln, state + 1) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_java.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_java.py new file mode 100644 index 0000000..fd20360 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_java.py @@ -0,0 +1,120 @@ +############################################################################### +# Name: java.py # +# Purpose: Define Java syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: java.py +AUTHOR: Cody Precord +@summary: Lexer configuration file for Java source files. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _java.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +from _cpp import AutoIndenter + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Java Keywords +JAVA_KEYWORDS = (0, "goto if else switch while for " + "do this super new instanceof return " + "throw try catch finally assert synchronize " + "break continue ") + +JAVA_KEYWORDS2 = (1, "import native package synchronized throws " + "extends implements interface class " + "static synchronized transient volatile final " + "serializable public protected private abstract") + +# Java Types/Structures/Storage Classes +JAVA_TYPES = (3, "boolean char byte short int long float double void " + "true false null " + "String Integer Long Float Double Byte Boolean " + "Map HashMap TreeMap CharSequence StringBuilder " + "List ArrayList Set HashSet TreeSet Collection " + "Exception System Runtime Collections Math ") + + +# Documentation Keywords (Doxygen keywords/ect) +DOC_KEYWORDS = (2, "TODO FIXME XXX \\author \\brief \\bug \\callgraph " + "\\category \\class \\code \\date \\def \\depreciated \\dir " + "\\dot \\dotfile \\else \\elseif \\em \\endcode \\enddot " + "\\endif \\endverbatim \\example \\exception \\file \\if " + "\\ifnot \\image \\include \\link \\mainpage \\name " + "\\namespace \\page \\par \\paragraph \\param \\return " + "\\retval \\section \\struct \\subpage \\subsection " + "\\subsubsection \\test \\todo \\typedef \\union \\var " + "\\verbatim \\version \\warning \\$ \\@ \\~ \\< \\> \\# \\% " + "@param @return @throws " + "HACK") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'stringeol_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, 'number2_style'), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_PRE = ("styling.within.preprocessor", "0") +FOLD_COM = ("fold.comment", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Java""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [JAVA_KEYWORDS, JAVA_KEYWORDS2, DOC_KEYWORDS, JAVA_TYPES] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_PRE] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [ u'//' ] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_javascript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_javascript.py new file mode 100644 index 0000000..eb1b770 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_javascript.py @@ -0,0 +1,109 @@ +############################################################################### +# Name: javascript.py # +# Purpose: Define JavaScript syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: javascript.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for JavaScript. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _javascript.py 70228 2011-12-31 20:39:16Z CJP $" +__revision__ = "$Revision: 70228 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# JavaScript Keywords # set to 1 for embeded +JS_KEYWORDS = (0, "abstract break boolean byte case const continue catch " + "class char debugger default delete do double default " + "export false else enum export extend final finally " + "float for function goto if implements import in " + "instanceof int interface long native new null " + "package private protected public return short static " + "synchronized switch super this throw throws transient " + "try true typeof var void volatile with while") + +#---- Syntax Style Spec ----# +SYNTAX_ITEMS = [ (stc.STC_HJ_COMMENT, 'comment_style'), + (stc.STC_HJ_COMMENTDOC, 'dockey_style'), + (stc.STC_HJ_COMMENTLINE, 'comment_style'), + (stc.STC_HJ_DEFAULT, 'default_style'), + (stc.STC_HJ_DOUBLESTRING, 'string_style'), + (stc.STC_HJ_KEYWORD, 'keyword_style'), + (stc.STC_HJ_NUMBER, 'number_style'), + (stc.STC_HJ_REGEX, 'scalar_style'), # STYLE ME + (stc.STC_HJ_SINGLESTRING, 'string_style'), + (stc.STC_HJ_START, 'scalar_style'), + (stc.STC_HJ_STRINGEOL, 'stringeol_style'), + (stc.STC_HJ_SYMBOLS, 'array_style'), + (stc.STC_HJ_WORD, 'class_style'), + (stc.STC_HJA_COMMENT, 'comment_style'), + (stc.STC_HJA_COMMENTDOC, 'dockey_style'), + (stc.STC_HJA_COMMENTLINE, 'comment_style'), + (stc.STC_HJA_DEFAULT, 'default_style'), + (stc.STC_HJA_DOUBLESTRING, 'string_style'), + (stc.STC_HJA_KEYWORD, 'keyword_style'), + (stc.STC_HJA_NUMBER, 'number_style'), + (stc.STC_HJA_REGEX, 'scalar_style'), # STYLE ME + (stc.STC_HJA_SINGLESTRING, 'string_style'), + (stc.STC_HJA_START, 'scalar_style'), + (stc.STC_HJA_STRINGEOL, 'stringeol_style'), + (stc.STC_HJA_SYMBOLS, 'array_style'), + (stc.STC_HJA_WORD, 'class_style') ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for JavaScript""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [JS_KEYWORDS,] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + if self.LangId == synglob.ID_LANG_HTML: + return SYNTAX_ITEMS + else: + return _cpp.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [("fold", "1")] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] + +#---- Syntax Modules Internal Functions ----# +def KeywordString(option=0): + """Returns the specified Keyword String + @keyword option: specific subset of keywords to get + + """ + return JS_KEYWORDS[1] + +#---- End Syntax Modules Internal Functions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_kix.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_kix.py new file mode 100644 index 0000000..8d65a42 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_kix.py @@ -0,0 +1,100 @@ +############################################################################### +# Name: kix.py # +# Purpose: Syntax configuration module for KIXtart scripts # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: kix.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for KIXtart scripts + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _kix.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +COMMANDS = (0, "? and beep big break call cd cls color cookie1 copy debug del " + "dim display do until exit flushkb for each next function " + "endfunction get gets global go gosub goto if else endif md or " + "password play quit rd redim return run select case endselect " + "set setl setm settime shell sleep small use while loop") + +FUNCTIONS = (1, "abs addkey addprinterconnection addprogramgroup " + "addprogramitem asc ascan at backupeventlog box cdbl chr cint " + "cleareventlog close comparefiletimes createobject cstr " + "dectohex delkey delprinterconnection delprogramgroup " + "delprogramitem deltree delvalue dir enumgroup enumipinfo " + "enumkey enumlocalgroup enumvalue execute exist existkey " + "expandenvironmentvars fix formatnumber freefilehandle " + "getdiskspace getfileattr getfilesize getfiletime " + "getfileversion getobject iif ingroup instr instrrev int " + "isdeclared join kbhit keyexist lcase left len loadhive " + "loadkey logevent logoff ltrim memorysize messagebox open " + "readline readprofilestring readtype readvalue redirectoutput " + "right rnd round rtrim savekey sendkeys sendmessage setascii " + "setconsole setdefaultprinter setfileattr setfocus setoption " + "setsystemstate settitle setwallpaper showprogramgroup " + "shutdown sidtoname split srnd substr trim ubound ucase " + "unloadhive val vartype vartypename writeline " + "writeprofilestring writevalue") + +MACROS = (2, "address build color comment cpu crlf csd curdir date day domain " + "dos error fullname homedir homedrive homeshr hostname inwin " + "ipaddress0 ipaddress1 ipaddress2 ipaddress3 kix lanroot ldomain " + "ldrive lm logonmode longhomedir lserver maxpwage mdayno mhz " + "monthno month msecs pid primarygroup priv productsuite " + "producttype pwage ras result rserver scriptdir scriptexe " + "scriptname serror sid site startdir syslang ticks time userid " + "userlang wdayno wksta wuserid ydayno year") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_KIX_COMMENT, 'comment_style'), + (stc.STC_KIX_DEFAULT, 'default_style'), + (stc.STC_KIX_FUNCTIONS, 'funct_style'), + (stc.STC_KIX_IDENTIFIER, 'default_style'), + (stc.STC_KIX_KEYWORD, 'keyword_style'), + (stc.STC_KIX_MACRO, 'pre_style'), + (stc.STC_KIX_NUMBER, 'number_style'), + (stc.STC_KIX_OPERATOR, 'operator_style'), + (stc.STC_KIX_STRING1, 'char_style'), + (stc.STC_KIX_STRING2, 'string_style'), + (stc.STC_KIX_VAR, 'scalar_style')] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Kix""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_KIX) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [COMMANDS, FUNCTIONS, MACROS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u';'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_latex.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_latex.py new file mode 100644 index 0000000..c0bc90d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_latex.py @@ -0,0 +1,95 @@ +############################################################################### +# Name: latex.py # +# Purpose: Define TeX/LateX syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: latex.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Tex/LaTex. +@todo: Fairly poor needs lots of work. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _latex.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Tex Keywords +TEX_KW = (0, "Downarrow backslash lceil rceil Uparrow downarrow lfloor rfloor " + "Updownarrow langle rangle Vert") +# ConTeXt Dutch +DUTCH = (1, "") +# ConTeXt English +ENG = (2, "") +# ConTeXt German +GERMAN = (3, "") +# ConTeXt Czech +CZECH = (4, "") +# ConTeXt Italian +ITALIAN = (5, "") +# ConTeXt Romanian +ROMAINIAN = (6, "") + +# LaTeXt +# There are no keyword settings available for LaTeX + +#---- Syntax Style Specs ----# +# TeX +SYNTAX_ITEMS1 = [(stc.STC_TEX_DEFAULT, 'default_style'), + (stc.STC_TEX_COMMAND, 'keyword_style'), + (stc.STC_TEX_GROUP, 'scalar_style'), + (stc.STC_TEX_SPECIAL, 'operator_style'), + (stc.STC_TEX_SYMBOL, 'number_style'), + (stc.STC_TEX_TEXT, 'default_style') ] + +# LaTeX +SYNTAX_ITEMS2 = [(stc.STC_L_DEFAULT, 'default_style'), + (stc.STC_L_COMMAND, 'pre_style'), + (stc.STC_L_COMMENT, 'comment_style'), + (stc.STC_L_MATH, 'operator_style'), + (stc.STC_L_TAG, 'keyword_style')] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for LaTeX/TeX""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + # TODO: change to LEX_TEX for TeX? + if self.LangId == synglob.ID_LANG_LATEX: + self.SetLexer(stc.STC_LEX_LATEX) + else: + self.SetLexer(stc.STC_LEX_TEX) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [TEX_KW] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + if self.LangId == synglob.ID_LANG_TEX: + return SYNTAX_ITEMS1 + else: + return SYNTAX_ITEMS2 + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'%'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lisp.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lisp.py new file mode 100644 index 0000000..aecaf4c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lisp.py @@ -0,0 +1,405 @@ +############################################################################### +# Name: lisp.py # +# Purpose: Define Lisp syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Author: Jeff # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: lisp.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Lisp Files. +@todo: Add Standard Variables + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _lisp.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# + +# Lisp Functions/Operators +LISP_FUNC = (0, "abort abs access acons acos acosh add-method adjoin " + "adjust-array adjustable-array-p alist allocate-instance " + "alpha-char-p alphanumericp and append apply applyhook apropos " + "apropos-list aref arithmetic-error arithmetic-error-operands " + "arithmetic-error-operation array array-dimension " + "array-dimension-limit array-dimensions array-displacement " + "array-element-type array-has-fill-pointer-p " + "array-in-bounds-p array-rank array-rank-limit " + "array-row-major-index array-total-size " + "array-total-size-limit arrayp ash asin asinh assert assoc " + "assoc-if assoc-if-not atan atanh atom backquote baktrace " + "base-char base-string bignum bignums bit bit-and bit-andc1 " + "bit-andc2 bit-eqv bit-ior bit-nand bit-nor bit-not bit-orc1 " + "bit-orc2 bit-vector bit-vector-p bit-xor block boole boole-1 " + "boole-2 boole-and boole-andc1 boole-andc2 boole-c1 boole-c2 " + "boole-clr boole-eqv boole-ior boole-nand boole-nor boole-orc1 " + "boole-orc2 boole-set boole-xor boolean both-case-p boundp " + "break broadcast-stream broadcast-stream-streams " + "built-in-class butlast byte byte-position byte-size caaaar " + "caaadr caaar caadar caaddr caadr caar cadaar cadadr cadar " + "caddar cadddr caddr cadr call-arguments-limit call-method " + "call-next-method capitalize car case catch ccase cdaaar " + "cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar " + "cdddar cddddr cdddr cddr cdr ceil-error ceil-error-name " + "ceiling cerror change-class char char-bit char-bits " + "char-bits-limit char-code char-code-limit char-control-bit " + "char-downcase char-equal char-font char-font-limit " + "char-greaterp char-hyper-bit char-int char-lessp " + "char-meta-bit char-name char-not-equal char-not-greaterp " + "char-not-lessp char-super-bit char-upcase char/= char<= char= " + "char>= character characterp check-type cirhash cis class " + "class-name class-of clear-input clear-output close code-char " + "coerce commonp compilation-speed compile compile-file " + "compile-file-pathname compiled-function compiled-function-p " + "compiler-let compiler-macro compiler-macro-function " + "complement complex complexp compute-applicable-methods " + "compute-restarts concatenate concatenated-stream " + "concatenated-stream-streams cond condition conjugate cons " + "consp constantly constantp continue control-error copy " + "copy-list copy-pprint-dispatch copy-readtable copy-seq " + "copy-structure copy-symbol copy-tree cos cosh count count-if " + "count-if-not ctypecase debug decf declaim declaration declare " + "decode-float decode-universal-time defclass defconstant " + "defgeneric define-compiler-macro define-condition " + "define-method-combination define-modify-macro " + "define-setf-expander define-setf-method define-symbol-macro " + "defmacro defmethod defpackage defparameter defsetf defstruct " + "deftype defun defvar delete delete-duplicates delete-file " + "delete-if delete-if-not delete-package denominator " + "deposite-field describe describe-object destructuring-bind " + "digit-char digit-char-p directory directory-namestring " + "disassemble division-by-zero do do* do-all-symbols " + "do-external-symbols do-symbols dolist dotimes double-float " + "double-float-epsilon double-float-negative-epsilion dpb " + "dribble dynamic-extent ecase echo-stream " + "echo-stream-input-stream echo-stream-output-stream ed eigth " + "elt encode-universal-time end-of-file endp enough-namestring " + "ensure-directories-exist ensure-generic-function eq eql equal " + "equalp error errset etypecase eval eval-when evalhook evenp " + "every exp export expt extend-char fboundp fceiling " + "fdefinition fflor fifth file-author file-error " + "file-error-pathname file-length file-namestring file-position " + "file-stream file-string-length file-write-date fill " + "fill-pointer find find-all-symbols find-class find-if " + "find-if-not find-method find-package find-restart find-symbol " + "finish-output first fixnum flet float float-digits " + "float-precision float-radix float-sign floating-point-inexact " + "floating-point-invalid-operation floating-point-underflow " + "floatp floor fmakunbound force-output format formatter fourth " + "fresh-line fround ftruncate ftype funcall function " + "function-keywords function-lambda-expression functionp gbitp " + "gcd generic-function gensym gentemp get get-decoded-time " + "get-dispatched-macro-character get-internal-real-time " + "get-internal-run-time get-macro-character " + "get-output-stream-string get-properties get-setf-expansion " + "get-setf-method get-universial-time getf gethash go " + "graphic-char-p handler-bind handler-case hash hash-table " + "hash-table-count hash-table-p hash-table-rehash-size " + "hash-table-rehash-threshold hash-table-size hash-table-test " + "host-namestring identity if if-exists ignorable ignore " + "ignore-errors imagpart import in-package incf " + "initialize-instance inline input-stream-p inspect int-char " + "integer integer-decode-float integer-length integerp " + "interactive-stream-p intern internal-time-units-per-second " + "intersection invalid-method-error invoke-debugger " + "invoke-restart invoke-restart-interactively isqrt keyword " + "keywordp l labels lambda lambda-list-keywords " + "lambda-parameters-limit last lcm ldb ldb-test ldiff " + "least-negative-double-float least-negative-long-float " + "least-negative-normalized-double-float " + "least-negative-normalized-long-float " + "least-negative-normalized-short-font " + "least-negative-normalized-single-font " + "least-negative-short-font least-negative-single-font " + "least-positive-double-float least-positive-long-float " + "least-positive-normalized-double-float " + "least-positive-normalized-long-float " + "least-positive-normalized-short-float " + "least-positive-normalized-single-float " + "least-positive-short-float least-positive-single-float length " + "let let* lisp lisp-implementation-type " + "lisp-implementation-version list list* " + "list-all-packages list-lenght listen listp load " + "load-logical-pathname-translation load-time-value locally " + "log logand logandc1 logandc2 logbitp logcount logeqv " + "logical-pathname logical-pathname-translations logior lognand " + "lognor lognot logorc1 logorc2 logtest logxor long-float " + "long-float-epsilon long-float-negative-epsilon long-site-name " + "loop loop-finish lower-case-p machine-instance machine-type " + "machine-version macro-function macroexpand macroexpand-1 " + "macroexpand-l macrolet make make-array make-broadcast-stream " + "make-char make-concatenated-stream make-condition " + "make-dispatch-macro-character make-echo-stream " + "make-hash-table make-instance make-instances-obsolete " + "make-list make-load-form make-load-form-saving-slots " + "make-method make-package make-pathname make-random-state " + "make-sequence make-string make-string-input-stream " + "make-string-output-stream make-symbol make-synonym-stream " + "make-two-way-stream makunbound map map-into mapc mapcan " + "mapcar mapcon maphash mapl maplist mask-field max member " + "member-if member-if-not merge merge-pathname merge-pathnames " + "method method-combination method-combination-error " + "method-qualifiers min minusp mismatch mod " + "most-negative-double-float most-negative-fixnum " + "most-negative-long-float most-negative-short-float " + "most-negative-single-float most-positive-fixnum " + "most-positive-long-float most-positive-short-float " + "most-positive-single-float muffle-warning " + "multiple-value-bind multiple-value-call multiple-value-limit " + "multiple-value-list multiple-value-prog1 multiple-value-seteq " + "multiple-value-setq name name-char namestring nbutlast nconc " + "next-method-p nil nintersection ninth no-applicable-method " + "no-next-method not notany notevery notinline nreconc nreverse " + "nset-difference nset-exclusive-or nstring nstring-capitalize " + "nstring-downcase nstring-upcase nstubst-if-not nsublis nsubst " + "nsubst-if nth nth-value nthcdr null number numberp numerator " + "nunion oddp open open-stream-p optimize or otherwise " + "output-stream-p package package-error package-error-package " + "package-name package-nicknames package-shadowing-symbols " + "package-use-list package-used-by-list packagep pairlis " + "parse-error parse-integer parse-namestring pathname " + "pathname-device pathname-directory pathname-host " + "pathname-match-p pathname-name pathname-type " + "pathname-version pathnamep peek-char phase pi plist plusp pop " + "position position-if position-if-not pprint pprint-dispatch " + "pprint-exit-if-list-exhausted pprint-fill pprint-indent " + "pprint-linear pprint-logical-block pprint-newline pprint-pop " + "pprint-tab pprint-tabular prin1 prin1-to-string princ " + "princ-to-string print print-not-readable " + "print-not-readable-object print-object probe-file proclaim " + "prog prog* prog1 prog2 progn program-error progv provide " + "psetf psetq push pushnew putprop quote random random-state " + "random-state-p rassoc rassoc-if rassoc-if-not ration rational " + "rationalize rationalp read read-byte read-car-no-hang " + "read-char read-delimited-list read-eval-print " + "read-from-string read-line read-preserving-whitespace " + "read-squence reader-error readtable readtable-case readtablep " + "real realp realpart reduce reinitialize-instance rem remf " + "remhash remove remove-duplicates remove-if " + "remove-if-not remove-method remprop rename-file " + "rename-package replace require rest restart restart-bind " + "restart-case restart-name return return-from revappend " + "reverse room rotatef round row-major-aref rplaca rplacd " + "safety satisfies sbit scale-float schar search second " + "sequence serious-condition set set-char-bit set-difference " + "set-dispatched-macro-character set-exclusive-or " + "set-macro-character set-pprint-dispatch " + "set-syntax-from-char setf setq seventh shadow " + "shadowing-import shared-initialize shiftf short-float " + "short-float-epsilon short-float-negative-epsilon " + "short-site-name signal signed-byte signum simple-array " + "simple-base-string simple-bit-vector- simple-bit-vector-p " + "simple-condition simple-condition-format-arguments " + "simple-condition-format-control simple-error simple-string " + "simple-string-p simple-type-error simple-vector " + "simple-vector-p simple-warning sin single-float " + "single-float-epsilon single-float-negative-epsilon sinh " + "sixth sleep slot-boundp slot-exists-p slot-makunbound " + "slot-missing slot-unbound slot-value software-type " + "software-version some sort space special special-form-p " + "special-operator-p speed sqrt stable-sort standard " + "standard-char standard-char-p standard-class " + "standard-generic-function standard-method standard-object " + "step storage-condition store-value stream stream-element-type " + "stream-error stream-error-stream stream-external-format " + "streamp streamup string string-capitalize string-char " + "string-char-p string-downcase string-equal string-greaterp " + "string-left-trim string-lessp string-not-equal " + "string-not-greaterp string-not-lessp string-right-strim " + "string-right-trim string-stream string-trim string-upcase " + "string/= string< string<= string= string> string>= stringp " + "structure structure-class structure-object style-warning " + "sublim sublis subseq subsetp subst subst-if subst-if-not " + "substitute substitute-if substitute-if-not subtypep svref " + "sxhash symbol symbol-function symbol-macrolet symbol-name " + "symbol-package symbol-plist symbol-value symbolp " + "synonym-stream synonym-stream-symbol sys system t tagbody " + "tailp tan tanh tenth terpri the third throw time trace " + "translate-logical-pathname translate-pathname tree-equal " + "truename truncase truncate two-way-stream " + "two-way-stream-input-stream two-way-stream-output-stream " + "type type-error type-error-datnum type-error-expected-type " + "type-of typecase typep unbound-slot unbound-slot-instance " + "unbound-variable undefined-function unexport unintern union " + "unless unread unread-char unsigned-byte untrace unuse-package " + "unwind-protect update-instance-for-different-class " + "update-instance-for-redefined-class " + "upgraded-array-element-type upgraded-complex-part-type " + "upper-case-p use-package use-value user user-homedir-pathname " + "value value-list values vector vector-pop vector-push " + "vector-push-extend vectorp warn warning when " + "wild-pathname-p with-accessors with-compilation-unit " + "with-condition-restarts with-hash-table-iterator " + "with-input-from-string with-open-file with-open-stream " + "with-output-to-string with-package-iterator " + "with-simple-restart with-slots with-standard-io-syntax write " + "write-byte write-char write-line write-sequence" ) + +SCHEME_KW = (0, "* + - / < <= = => > >= abs acos and angle append apply asin " + "assoc assq assv atan begin boolean? caaaar caaadr caaar " + "caadar caaddr caadr caar cadaar cadadr cadar caddar cadddr " + "caddr cadr call-with-current-continuation " + "call-with-input-file call-with-output-file call-with-values " + "call/cc car case cdaaar cdaadr cdaar cdadar cdaddr cdadr cdar " + "cddaar cddadr cddar cdddar cddddr cdddr cddr cdr ceiling " + "char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? " + "char-ci>=? char-ci>? char-downcase char-lower-case? " + "char-numeric? char-ready? char-upcase char-upper-case? " + "char-whitespace? char<=? char<? char=? char>=? char>? char? " + "close-input-port close-output-port complex? cond cons cos " + "current-input-port current-output-port define define-syntax " + "delay denominator display do dynamic-wind else eof-object? " + "eq? equal? eqv? eval even? exact->inexact exact? exp expt " + "floor for-each force gcd if imag-part inexact->exact inexact? " + "input-port? integer->char integer? interaction-environment " + "lambda lcm length let let* let-syntax letrec letrec-syntax " + "list list->string list->vector list-ref list-tail list? load " + "log magnitude make-polar make-rectangular make-string " + "make-vector map max member memq memv min modulo negative? " + "newline not null-environment null? number->string number? " + "numerator odd? open-input-file open-output-file or " + "output-port? pair? peek-char positive? procedure? quasiquote " + "quote quotient rational? rationalize read read-char " + "real-part real? remainder reverse round " + "scheme-report-environment set! set-car! set-cdr! sin sqrt " + "string string->list string->number string->symbol " + "string-append string-ci<=? string-ci<? string-ci=? " + "string-ci>=? string-ci>? string-copy string-fill! " + "string-length string-ref string-set! string<=? string<? " + "string=? string>=? string>? string? substring symbol->string " + "symbol? syntax-rules transcript-off transcript-on truncate " + "unquote unquote-splicing values vector vector->list " + "vector-fill! vector-length vector-ref vector-set! vector? " + "with-input-from-file with-output-to-file write write-char " + "zero?" ) + +# Lisp Keywords +LISP_KEYWORDS = (1, ":abort :adjustable :append :array :base :case :circle " + ":conc-name :constructor :copier :count :create :default " + ":device :directory :displaced-index-offset :displaced-to " + ":element-type :end :end1 :end2 :error :escape :external " + ":from-end :gensym :host :include :if-does-not-exist " + ":if-exists :index :inherited :internal :initial-contents " + ":initial-element :initial-offset :initial-value :input " + ":io :junk-allowed :key :length :level :name :named " + ":new-version :nicknames :output :ouput=file :overwrite " + ":predicate :preserve-whitespace :pretty :print " + ":print-function :probe :radix :read-only :rehash-size " + ":rehash-threshold :rename :size :rename-and-delete :start " + ":start1 :start2 :stream :supersede :test :test-not :use " + ":verbose :version") + +NEWLISP_FUNC = (0, "! != % & * + - / : < << <= = > >= >> ? @ NaN? abort abs " + "acos acosh add address " "amb and append append-file apply " + "args array array-list array? asin asinh assoc assoc-set " + "atan atan2 atanh atom? base64-dec base64-enc bayes-query " + "bayes-train begin beta betai bind binomial callback case " + "catch ceil change-dir char chop clean close command-event " + "cond cons constant context context? copy-file cos cosh " + "count cpymem crc32 crit-chi2 crit-z current-line curry " + "date date-value debug dec def-new default define " + "define-macro delete delete-file delete-url destroy det " + "device difference directory directory? div do-until " + "do-while doargs dolist dostring dotimes dotree dump dup " + "empty? encrypt ends-with env erf error-event error-number " + "error-text eval eval-string exec exists exit exp expand " + "explode factor fft file-info file? filter find find-all " + "first flat " "float float? floor flt for for-all fork " + "format fv gammai gammaln gcd get-char get-float get-int " + "get-long get-string get-url global global? if if-not ifft " + "import inc index int integer integer? intersect invert irr " + "join lambda? last legal? length let letex letn list list? " + "load local log lookup lower-case macro? main-args make-dir " + "map mat match max member min mod mul multiply name " + "net-accept net-close net-connect net-error net-eval " + "net-listen net-local net-lookup net-peek net-peer net-ping" + "-receive " "net-receive-from net-receive-udp net-select " + "net-send net-send-to net-send-udp net-service net-sessions " + "new nil nil? normal not now nper npv nth nth-set null? " + "number? open or ostype pack parse parse-date peek pipe pmt " + "pop pop-assoc post-url pow pretty-print primitive? print " + "println prob-chi2 prob-z process prompt-event protected? " + "push put-url pv quote quote? rand random randomize " + "read-buffer read-char read-expr read-file read-key " + "read-line real-path ref ref-all ref-set regex regex-comp " + "remove-dir rename-file replace reset rest reverse rotate " + "round save search seed seek select semaphore sequence " + "series set set-assoc set-locale set-nth set-ref " + "set-ref-all setq sgn share signal silent sin sinh sleep " + "slice sort source spawn sqrt starts-with string string? " + "sub swap sym symbol? symbols sync sys-error sys-info tan " + "tanh throw throw-error time time-of-day timer title-case " + "trace trace-highlight transpose trim true true? unicode " + "unify unique unless unpack until upper-case utf8 utf8len " + "uuid wait-pid when while write-buffer write-char " + "write-file write-line xml-error xml-parse xml-type-tags " + "zero? | ~ lambda") + +# Lisp Keywords +NEWLISP_KEYWORDS = (1, "$ $0 $1 $10 $11 $12 $13 $14 $15 $2 $3 $4 $5 $6 $7 $8 " + "$9 $args $idx $main-args MAIN :") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_LISP_DEFAULT, 'default_style'), + (stc.STC_LISP_COMMENT, 'comment_style'), + (stc.STC_LISP_MULTI_COMMENT, 'comment_style'), + (stc.STC_LISP_IDENTIFIER, 'default_style'), + (stc.STC_LISP_KEYWORD, 'keyword_style'), + (stc.STC_LISP_KEYWORD_KW, 'keyword2_style'), + (stc.STC_LISP_NUMBER, 'number_style'), + (stc.STC_LISP_OPERATOR, 'operator_style'), + (stc.STC_LISP_SPECIAL, 'operator_style'), + (stc.STC_LISP_STRING, 'string_style'), + (stc.STC_LISP_STRINGEOL, 'stringeol_style'), + (stc.STC_LISP_SYMBOL, 'scalar_style') ] + +#---- Extra Properties ----# +FOLD = ('fold', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for List/newLisp/Scheme""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_LISP) + + def GetKeywords(self): + """Returns Specified Keywords List """ + if self.LangId == synglob.ID_LANG_LISP: + return [LISP_FUNC, LISP_KEYWORDS] + elif self.LangId == synglob.ID_LANG_SCHEME: + return [SCHEME_KW] + elif self.LangId == synglob.ID_LANG_NEWLISP: + return [NEWLISP_FUNC, NEWLISP_KEYWORDS] + else: + return list() + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u';'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lout.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lout.py new file mode 100644 index 0000000..3bdae63 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lout.py @@ -0,0 +1,116 @@ +############################################################################### +# Name: lout.py # +# Purpose: Define Lout syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: lout.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Lout +@todo: style refinement + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _lout.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +# @ prefixed keywords +LOUT_KW1 = (0, "@OptGall @FontDef @Family @Face @Name @Metrics @ExtraMetrics " + "@Mapping @Recode @Filter @FilterIn @FilterOut @FilterErr @AL " + "@Common @Rump @Meld @Insert @OneOf @Next @Plus @Minus @Wide " + "@High @HShift @VShift @BeginHeaderComponent @Document @TItle " + "@SetHeaderComponent @ClearHeaderComponent @OneCol @OneRow @Doc " + "@HMirror @VMirror @HScale @VScale @HCover @VCover @Scale @Text " + "@KernShrink @HContract @VContract @HLimited @VLimited @HExpand " + "@VExpand @StartHVSpan @StartHSpan @StartVSpan @HSpan @VSpan " + "@PAdjust @HAdjust @VAdjust @Rotate @Background @IncludeGraphic " + "@SysIncludeGraphic @Graphic @LinkSource @LinkDest @URLLink @BI " + "@PlainGraphic @Verbatim @RawVerbatim @Case @Yield @BackEnd @BL " + "@Char @Font @Space @YUnit @ZUnit @Break @Underline @SetColour " + "@SetColor @SetUnderlineColour @SetUnderlineColor @SetTexture " + "@Outline @Language @CurrLang @CurrFamily @CurrFace @CurrYUnit " + "@CurrZUnit @LEnv @@A @@B @@C @@D @@E @LClos @@V @LUse @LEO @PP " + "@Open @Use @NotRevealed @Tagged @Database @SysDatabase @I @B" + "@Include @SysInclude @IncludeGraphicRepeated @InitialFont " + "@SysIncludeGraphicRepeated @PrependGraphic @SysPrependGraphic " + "@Target @Null @PageLabel @Galley @ForceGalley @LInput @Split " + "@Tag @Key @Optimize @Merge @Enclose @Begin @End @Moment @Tab " + "@Second @Minute @Hour @Day @Month @Year @Century @WeekDay " + "@YearDay @DaylightSaving @SetContext @GetContext @Time @List " + "@EndHeaderComponent @Section @BeginSections @EndNote @Abstract " + "@AlphaList @Appendix @Author @Figure @Report @OuterNote " + "@IndentedList @InitialBreak @InitialLanguage InnerNote " + "@Heading @FootNote @Date @LeftList @LeftNote @ListItem " + "@RightDisplay @RightNote @EndSections") + +# Symbols +LOUT_KW2 = (1, "&&& && & ^// ^/ ^|| ^| ^& // / || |") + +# Non @ keywords +LOUT_KW3 = (2, "def langdef force horizontally into extend import export " + "precedence associativity left right body macro named " + "compulsory following preceding foll_or_prec now " + "Base Slope Bold BoldSlope Times Helvetica Courier Palatino " + "adjust breakstyle clines lines linesep hyphen nonhyphen ragged " + ) + +# Document Classes +LOUT_KW4 = (3, "fx vx aformat bformat doc eq graph slides tab text tbl") +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_LOUT_COMMENT, 'comment_style'), + (stc.STC_LOUT_DEFAULT,'default_style'), + (stc.STC_LOUT_IDENTIFIER, 'default_style'), + (stc.STC_LOUT_NUMBER, 'number_style'), + (stc.STC_LOUT_OPERATOR, 'operator_style'), + (stc.STC_LOUT_STRING, 'string_style'), + (stc.STC_LOUT_STRINGEOL, 'stringeol_style'), + (stc.STC_LOUT_WORD, 'scalar_style'), + (stc.STC_LOUT_WORD2, 'keyword2_style'), + (stc.STC_LOUT_WORD3, 'keyword_style'), + (stc.STC_LOUT_WORD4, 'class_style')] + +#---- Extra Properties ----# +FOLD_COMPACT = ("fold.compact", '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for LOUT""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_LOUT) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [LOUT_KW1, LOUT_KW2, LOUT_KW3] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD_COMPACT] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lua.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lua.py new file mode 100644 index 0000000..dc223f5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_lua.py @@ -0,0 +1,131 @@ +############################################################################### +# Name: lua.py # +# Purpose: Define Lua5 syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: lua.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Lua +@todo: This setup for Lua5, maybe add Lua4 support + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _lua.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +# Keywords +LUA_KEYWORDS = (0, "and break do else elseif end false for function if " + "in local nil not or repeat return then true until while") + +# Basic Functions +LUA_FUNCT = (1, "_VERSION assert collectgarbage dofile error gcinfo loadfile " + "loadstring print rawget rawset require tonumber tostring type " + "unpack " + # Lua5 Basic functions + "_G getfenv getmetatable ipairs loadlib next pairs pcall " + "rawequal setfenv setmetatable xpcall \string table math " + "coroutine io os debug \load module select") + +# String, (table) & math functions Lua5 +LUA_STR = (2, "string.byte string.char string.dump string.find string.len " + "string.lower string.rep string.sub string.upper string.format " + "string.gfind string.gsub table.concat table.foreach " + "table.foreachi table.getn table.sort table.insert table.remove " + "table.setn math.abs math.acos math.asin math.atan math.atan2 " + "math.ceil math.cos math.deg math.exp math.floor math.frexp " + "math.ldexp math.log math.log10 math.max math.min math.mod " + "math.pi math.pow math.rad math.random math.randomseed math.sin " + "math.sqrt math.tan string.gmatch string.match string.reverse " + "table.maxn math.cosh math.fmod math.modf math.sinh math.tanh " + "math.huge") + +# (coroutines), I/O & system facilities +LUA_CO = (3, "coroutine.create coroutine.resume coroutine.status coroutine." + "wrap coroutine.yield io.close io.flush io.input io.lines io.open " + "io.output io.read io.tmpfile io.type io.write io.stdin io.stdout " + "io.stderr os.clock os.date os.difftime os.execute os.exit " + "os.getenv os.remove os.rename os.setlocale os.time os.tmpname " + "coroutine.running package.cpath package.loaded package.loadlib " + "package.path package.preload package.seeall io.popen") + +# user1 +LUA_U1 = (4, "") + +# user2 +LUA_U2 = (5, "") + +# user3 +LUA_U3 = (6, "") + +# user4 +LUA_U4 = (7, "") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_LUA_CHARACTER, 'char_style'), + (stc.STC_LUA_COMMENT, 'comment_style'), + (stc.STC_LUA_COMMENTDOC, 'dockey_style'), + (stc.STC_LUA_COMMENTLINE, 'comment_style'), + (stc.STC_LUA_DEFAULT, 'default_style'), + (stc.STC_LUA_IDENTIFIER, 'default_style'), # style maybe + (stc.STC_LUA_LITERALSTRING, 'string_style'), + (stc.STC_LUA_NUMBER, 'number_style'), + (stc.STC_LUA_OPERATOR, 'operator_style'), + (stc.STC_LUA_PREPROCESSOR, 'pre_style'), + (stc.STC_LUA_STRING, 'string_style'), + (stc.STC_LUA_STRINGEOL, 'stringeol_style'), + (stc.STC_LUA_WORD, 'keyword_style'), + (stc.STC_LUA_WORD2, 'keyword3_style'), + (stc.STC_LUA_WORD3, 'funct_style'), + (stc.STC_LUA_WORD4, 'funct_style'), + (stc.STC_LUA_WORD5, 'default_style'), # currently unused + (stc.STC_LUA_WORD6, 'default_style'), # currently unused + (stc.STC_LUA_WORD7, 'default_style'), # currently unused + (stc.STC_LUA_WORD8, 'default_style') # currently unused + ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_COMP = ("fold.compact", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Lua""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_LUA) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [LUA_KEYWORDS, LUA_FUNCT, LUA_STR, LUA_CO] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set""" + return [FOLD, FOLD_COMP] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'--'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_make.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_make.py new file mode 100644 index 0000000..d42c780 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_make.py @@ -0,0 +1,53 @@ +############################################################################### +# Name: make.py # +# Purpose: Define Makefile syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: make.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Makefiles. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _make.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# +# Syntax Style Specs +SYNTAX_ITEMS = [ (stc.STC_MAKE_DEFAULT, 'default_style'), + (stc.STC_MAKE_COMMENT, 'comment_style'), + (stc.STC_MAKE_IDENTIFIER, 'scalar_style'), + (stc.STC_MAKE_IDEOL, 'ideol_style'), + (stc.STC_MAKE_OPERATOR, 'operator_style'), + (stc.STC_MAKE_PREPROCESSOR, 'pre2_style'), + (stc.STC_MAKE_TARGET, 'keyword_style') ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Makefiles""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_MAKEFILE) + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mako.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mako.py new file mode 100644 index 0000000..6edfbe5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mako.py @@ -0,0 +1,134 @@ +############################################################################### +# Name: mako.py # +# Purpose: Define Mako syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: mako.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Mako Templates. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _mako.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +from pygments.token import Token +from pygments.lexers import get_lexer_by_name + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# +# Style Id's + +STC_MAKO_DEFAULT, \ +STC_MAKO_COMMENT, \ +STC_MAKO_NUMBER, \ +STC_MAKO_STRING, \ +STC_MAKO_STRINGEOL, \ +STC_MAKO_SCALAR, \ +STC_MAKO_OPERATOR, \ +STC_MAKO_PREPROCESSOR, \ +STC_MAKO_ATTRIBUTE, \ +STC_MAKO_TAG, \ +STC_MAKO_BUILTIN, \ +STC_MAKO_KEYWORD = range(12) + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Python Keywords +KEYWORDS = "include inherit namespace page" + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (STC_MAKO_DEFAULT, 'default_style'), + (STC_MAKO_COMMENT, 'comment_style'), + (STC_MAKO_NUMBER, 'number_style'), + (STC_MAKO_STRING, 'string_style'), + (STC_MAKO_STRINGEOL, 'stringeol_style'), + (STC_MAKO_SCALAR, 'scalar_style'), + (STC_MAKO_OPERATOR, 'operator_style'), + (STC_MAKO_PREPROCESSOR, 'pre_style'), + (STC_MAKO_ATTRIBUTE, 'keyword2_style'), + (STC_MAKO_TAG, 'keyword_style'), # Need new tag + (STC_MAKO_BUILTIN, 'keyword4_style'), + (STC_MAKO_KEYWORD, 'keyword_style'), ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Mako""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CONTAINER) + self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [(1, KEYWORDS)] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u"#",] + +#-----------------------------------------------------------------------------# + +def StyleText(stc, start, end): + """Style the text + @param stc: Styled text control instance + @param start: Start position + @param end: end position + + """ + cpos = 0 + stc.StartStyling(cpos, 0x1f) + lexer = get_lexer_by_name("html+mako") + doctxt = stc.GetTextRange(0, end) + wineol = stc.GetEOLChar() == "\r\n" + for token, txt in lexer.get_tokens(doctxt): +# print token, txt + style = TOKEN_MAP.get(token, STC_MAKO_DEFAULT) + if style == STC_MAKO_PREPROCESSOR and txt.startswith(u'#'): + style = STC_MAKO_COMMENT +# elif style == STC_MAKO_STRING and txt[-1] not in '"\'': +# style = STC_MAKO_STRINGEOL + + tlen = len(txt) + if wineol and "\n" in txt: + tlen += txt.count("\n") + + if tlen: + stc.SetStyling(tlen, style) + cpos += tlen + stc.StartStyling(cpos, 0x1f) + +#-----------------------------------------------------------------------------# + +TOKEN_MAP = { Token.Literal.String : STC_MAKO_STRING, + Token.Comment.Preproc : STC_MAKO_PREPROCESSOR, + Token.Comment : STC_MAKO_COMMENT, + Token.Name.Builtin : STC_MAKO_BUILTIN, + Token.Operator : STC_MAKO_OPERATOR, + Token.Punctuation : STC_MAKO_OPERATOR, + Token.Number : STC_MAKO_NUMBER, + Token.Keyword : STC_MAKO_KEYWORD, + Token.Name.Attribute : STC_MAKO_ATTRIBUTE, + Token.String.Interpol : STC_MAKO_SCALAR, + Token.Name.Tag : STC_MAKO_TAG } +
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_masm.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_masm.py new file mode 100644 index 0000000..2f2c680 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_masm.py @@ -0,0 +1,196 @@ +############################################################################### +# Name: masm.py # +# Purpose: Define MASM syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: masm.py +AUTHOR: Cody Precord +@summary: Lexer configuration file Microsoft Assembly Code + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _masm.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# + +# MASM CPU Instructions/Operators +MASM_CPU_INST = (0, "aaa aad aam aas adc and arpl bound bsf bsr bswap bt btc " + "btr bts call cdw cdq clc cld cli clts cmc cmp cmps cmpsb " + "cmpsw cmpsd cmpxchng cwd cwde daa das enter in ins insb " + "insw insd int into invd invlpg iret iretd ja jae jb jbe " + "jc jcxz jecxz je jz jg jge jl jle jna jnae jnb jnbe jnc " + "jne jng jnge jnl jnle jno jnp jns jnz jo jp jpe jpo js jz " + "jmp lahf lar lea leave lgdt lidt lgs lss lfs lods lodsb " + "lodsw lodsd loop loope loopz loone loopne retf retn lds " + "les lldt lmsw lock lsl ltr mov movs movsb movsw movsd " + "movsx movzx neg nop not or out outs outsb outsw outsd " + "pop popa popd popf popfd push pusha pushad pushf pushfd " + "rcl rcr rol roro rep repe repz repne repnz ret sahf sal " + "sar shl shr sbb scas scasb scasw scasd seta setae setb " + "setbe setc sete setg setge setl setle setna setnae setnb " + "setnbe setnc setne setng setnge setnl setnle setno setnp " + "setns setnz seto setp setpe setpo ses setz sgdt sidt shld " + "shrd sldt smsw stc std sti stos stosb stosw stosd str " + "test verr verw wait wbinvd xchg xlat xlatb xor add dec " + "idiv imul inc mul sub xadd div " + # MMX/SSE/SSE2 Instructions + "cflush cpuid emms femms cmovo cmovno cmovb cmovc cmovnae " + "cmovae cmovnb cmovnc cmove cmovz cmovne cmovnz cmovbe " + "cmovna cmova cmovnbe cmovs cmovns cmovp cmovpe cmovnp " + "cmovpo cmovl cmovnge cmovge cmovnl cmovle cmovng cmovg " + "cmovnle cmpxchg486 cmpxchg8b loadall loadall286 ibts " + "icebp int1 int3 int01 int03 iretw popaw popfw pushaw " + "pushfw rdmsr rdpmc rdshr rdtsc rsdc rsldt rsm rsts salc " + "smi smint smintold svdc svldt svts syscall sysenter " + "sysexit sysret ud0 ud1 ud2 umov xbts wrmsr wrshr") + +# floating point instructions +MASM_FPU_INST = (1, "f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcom fcomp " + "fcompp fdecstp fdisi fdiv fdivp fdivr fdivrp feni ffree " + "fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit " + "fist fistp fisub fisubr fld fld1 fldcw fldenv fldenvw " + "fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex " + "fndisi fneni fninit fnop fnsave fnsavew fnstcw fnstenv " + "fnstenvw fnstsw fpatan fprem fptan frndint frstor frstorw " + "fsave fsavew fscale fsqrt fst fstcw fstenv fstenvw fstp " + "fstsw fsub fsubp fsubr fsubrp ftst fwait fxam fxch " + "fxtract fyl2x fyl2xp1 fsetpm fcos fldenvd fnsaved " + "fnstenvd fprem1 frstord fsaved fsin fsincos fstenvd fucom " + "fucomp fucompp fcomi fcomip ffreep fcmovb fcmove fcmovbe " + "fcmovu fcmovnb fcmovne fcmovnbe fcmovnu ") + +MASM_REGISTERS = (2, "ah al ax bh bl bp bx ch cl cr0 cr2 cr3 cr4 cs cx dh di " + "dl dr0 dr1 dr2 dr3 dr6 dr7 ds dx eax ebp ebx ecx edi edx " + "es esi esp fs gs si sp ss st tr3 tr4 tr5 tr6 tr7 st0 st1 " + "st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 " + "xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7") + +MASM_DIRECTIVES = (3, ".186 .286 .286c .286p .287 .386 .386c .386p .387 .486 " + ".486p .8086 .8087 .alpha .break .code .const .continue " + ".cref .data .data? .dosseg .else .elseif .endif .endw " + ".err .err1 .err2 .errb .errdef .errdif .errdifi .erre " + ".erridn .erridni .errnb .errndef .errnz .exit .fardata " + ".fardata? .if .lall .lfcond .list .listall .listif " + ".listmacro .listmacroall .model .no87 .nocref .nolist " + ".nolistif .nolistmacro .radix .repeat .sall .seq " + ".sfcond .stack .startup .tfcond .type .until .untilcxz " + ".while .xall .xcref .xlist alias align assume catstr " + "comm comment db dd df dosseg dq dt dup dw echo else " + "elseif elseif1 elseif2 elseifb elseifdef elseifdif " + "elseifdifi elseife elseifidn elseifidni elseifnb " + "elseifndef end endif endm endp ends eq equ even exitm " + "extern externdef extrn for forc ge goto group gt high " + "highword if if1 if2 ifb ifdef ifdif ifdifi ife ifidn " + "ifidni ifnb ifndef include includelib instr invoke irp " + "irpc label le length lengthof local low lowword " + "lroffset lt macro mask mod .msfloat name ne offset " + "opattr option org %out page popcontext proc proto ptr " + "public purge pushcontext record repeat rept seg segment " + "short size sizeof sizestr struc struct substr subtitle " + "subttl textequ this title type typedef union while " + "width") + +MASM_DIREC_OP = (4, "$ ? @b @f addr basic byte c carry? dword far far16 " + "fortran fword near near16 overflow? parity? pascal qword " + "real4 real8 real10 sbyte sdword sign? stdcall sword " + "syscall tbyte vararg word zero? flat near32 far32 abs all " + "assumes at casemap common compact cpu dotname emulator " + "epilogue error export expr16 expr32 farstack flat " + "forceframe huge language large listing ljmp loadds m510 " + "medium memory nearstack nodotname noemulator nokeyword " + "noljmp nom510 none nonunique nooldmacros nooldstructs " + "noreadonly noscoped nosignextend nothing notpublic " + "oldmacros oldstructs os_dos para private prologue radix " + "readonly req scoped setif2 smallstack tiny use16 use32 " + "uses") + +MASM_EXT_INST = (5, "addpd addps addsd addss andpd andps andnpd andnps cmpeqpd " + "cmpltpd cmplepd cmpunordpd cmpnepd cmpnltpd cmpnlepd " + "cmpordpd cmpeqps cmpltps cmpleps cmpunordps cmpneps " + "cmpnltps cmpnleps cmpordps cmpeqsd cmpltsd cmplesd " + "cmpunordsd cmpnesd cmpnltsd cmpnlesd cmpordsd cmpeqss " + "cmpltss cmpless cmpunordss cmpness cmpnltss cmpnless " + "cmpordss comisd comiss cvtdq2pd cvtdq2ps cvtpd2dq " + "cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd " + "cvtps2pi cvtss2sd cvtss2si cvtsd2si cvtsd2ss cvtsi2sd " + "cvtsi2ss cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi " + "cvttsd2si cvttss2si divpd divps divsd divss fxrstor " + "fxsave ldmxscr lfence mfence maskmovdqu maskmovdq maxpd " + "maxps paxsd maxss minpd minps minsd minss movapd movaps " + "movdq2q movdqa movdqu movhlps movhpd movhps movd movq " + "movlhps movlpd movlps movmskpd movmskps movntdq movnti " + "movntpd movntps movntq movq2dq movsd movss movupd movups " + "mulpd mulps mulsd mulss orpd orps packssdw packsswb " + "packuswb paddb paddsb paddw paddsw paddd paddsiw paddq " + "paddusb paddusw pand pandn pause paveb pavgb pavgw " + "pavgusb pdistib pextrw pcmpeqb pcmpeqw pcmpeqd pcmpgtb " + "pcmpgtw pcmpgtd pf2id pf2iw pfacc pfadd pfcmpeq pfcmpge " + "pfcmpgt pfmax pfmin pfmul pmachriw pmaddwd pmagw pmaxsw " + "pmaxub pminsw pminub pmovmskb pmulhrwc pmulhriw " + "pmulhrwa pmulhuw pmulhw pmullw pmuludq pmvzb pmvnzb " + "pmvlzb pmvgezb pfnacc pfpnacc por prefetch prefetchw " + "prefetchnta prefetcht0 prefetcht1 prefetcht2 pfrcp " + "pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd " + "pf2iw pinsrw psadbw pshufd pshufhw pshuflw pshufw psllw " + "pslld psllq pslldq psraw psrad psrlw psrld psrlq psrldq " + "psubb psubw psubd psubq psubsb psubsw psubusb psubusw " + "psubsiw pswapd punpckhbw punpckhwd punpckhdq punpckhqdq " + "punpcklbw punpcklwd punpckldq punpcklqdq pxor rcpps " + "rcpss rsqrtps rsqrtss sfence shufpd shufps sqrtpd sqrtps " + "sqrtsd sqrtss stmxcsr subpd subps subsd subss ucomisd " + "ucomiss unpckhpd unpckhps unpcklpd unpcklps xorpd xorps") + +#---- Language Styling Specs ----# +SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'), + (stc.STC_ASM_CHARACTER, 'char_style'), + (stc.STC_ASM_COMMENT, 'comment_style'), + (stc.STC_ASM_COMMENTBLOCK, 'comment_style'), + (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_DIRECTIVE, 'keyword3_style'), + (stc.STC_ASM_DIRECTIVEOPERAND, 'keyword4_style'), + (stc.STC_ASM_EXTINSTRUCTION, 'funct_style'), + (stc.STC_ASM_IDENTIFIER, 'default_style'), + (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_NUMBER, 'number_style'), + (stc.STC_ASM_OPERATOR, 'operator_style'), + (stc.STC_ASM_REGISTER, 'keyword2_style'), + (stc.STC_ASM_STRING, 'string_style'), + (stc.STC_ASM_STRINGEOL, 'stringeol_style') ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for MASM""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_ASM) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [MASM_CPU_INST, MASM_FPU_INST, MASM_REGISTERS, MASM_DIRECTIVES, + MASM_DIREC_OP, MASM_EXT_INST] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u';'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_matlab.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_matlab.py new file mode 100644 index 0000000..4792aab --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_matlab.py @@ -0,0 +1,91 @@ +############################################################################### +# Name: matlab.py # +# Purpose: Define Matlab and Octave syntax for highlighting and other features# +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: matlab.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Matlab and Octave + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _matlab.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +MATLAB_KW = (0, "break case catch continue else elseif end for function " + "global if otherwise persistent return switch try while") + +OCTAVE_KW = (0, "break case catch continue do else elseif end " + "end_unwind_protect endfor endif endswitch endwhile for " + "function endfunction global if otherwise persistent return " + "switch try until unwind_protect unwind_protect_cleanup while") +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_MATLAB_COMMAND, 'funct_style'), + (stc.STC_MATLAB_COMMENT, 'comment_style'), + (stc.STC_MATLAB_DEFAULT, 'default_style'), + (stc.STC_MATLAB_DOUBLEQUOTESTRING, 'string_style'), + (stc.STC_MATLAB_IDENTIFIER, 'default_style'), + (stc.STC_MATLAB_KEYWORD, 'keyword_style'), + (stc.STC_MATLAB_NUMBER, 'number_style'), + (stc.STC_MATLAB_OPERATOR, 'operator_style'), + (stc.STC_MATLAB_STRING, 'string_style')] + +#---- Extra Properties ----# +FOLD = ('fold', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for MatLab and Octave""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + if self.LangId == synglob.ID_LANG_MATLAB: + self.SetLexer(stc.STC_LEX_MATLAB) + else: + self.SetLexer(stc.STC_LEX_OCTAVE) + + def GetKeywords(self): + """Returns Specified Keywords List """ + if self.LangId == synglob.ID_LANG_MATLAB: + return [MATLAB_KW] + elif self.LangId == synglob.ID_LANG_OCTAVE: + return [OCTAVE_KW] + else: + return list() + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + if self.LangId == synglob.ID_LANG_MATLAB: + return [u'%'] + elif self.LangId == synglob.ID_LANG_OCTAVE: + return [u'#'] + else: + return list() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mssql.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mssql.py new file mode 100644 index 0000000..7f6c036 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_mssql.py @@ -0,0 +1,89 @@ +############################################################################### +# Name: mssql.py # +# Purpose: Define Microsoft SQL syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: mssql.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Microsoft SQL. +@todo: too many to list + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _mssql.py 68355 2011-07-24 20:06:07Z CJP $" +__revision__ = "$Revision: 68355 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Data Types +MSSQL_DAT = (0, "") +# System Tables +MSSQL_SYS = (1, "") +# Global Variables +MSSQL_GLOB = (2, "") +# Functions +MSSQL_FUNC = (3, "") +# System Stored Procedures +MSSQL_SYSP = (4, "") +# Operators +MSSQL_OPS = (5, "") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_MSSQL_DEFAULT, 'default_style'), + (stc.STC_MSSQL_COMMENT, 'comment_style'), + (stc.STC_MSSQL_COLUMN_NAME, 'keyword_style'), + (stc.STC_MSSQL_COLUMN_NAME_2, 'keyword_style'), + (stc.STC_MSSQL_DATATYPE, 'keyword2_style'), + (stc.STC_MSSQL_DEFAULT_PREF_DATATYPE, 'class_style'), + (stc.STC_MSSQL_FUNCTION, 'keyword3_style'), + (stc.STC_MSSQL_GLOBAL_VARIABLE, 'global_style'), + (stc.STC_MSSQL_IDENTIFIER, 'default_style'), + (stc.STC_MSSQL_LINE_COMMENT, 'comment_style'), + (stc.STC_MSSQL_NUMBER, 'number_style'), + (stc.STC_MSSQL_OPERATOR, 'operator_style'), + (stc.STC_MSSQL_STATEMENT, 'keyword_style'), + (stc.STC_MSSQL_STORED_PROCEDURE, 'scalar2_style'), + (stc.STC_MSSQL_STRING, 'string_style'), + (stc.STC_MSSQL_SYSTABLE, 'keyword4_style'), + (stc.STC_MSSQL_VARIABLE, 'scalar_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_COMMENT = ("fold.comment", "1") +FOLD_COMPACT = ("fold.compact", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for MS SQL""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_MSSQL) + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_COMPACT] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'--'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nasm.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nasm.py new file mode 100644 index 0000000..3bb0318 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nasm.py @@ -0,0 +1,138 @@ +############################################################################### +# Name: nasm.py # +# Purpose: Define NASM syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: nasm.py +AUTHOR: Cody Precord +@summary: Lexer configuration file Netwide Assembly Code +@todo: Add mmx, sse, 3dnow, cyrix, amd instruction sets + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _nasm.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# + +# NASM CPU Instructions +NASM_CPU_INST = (0, "cmps movs lcs lods stos xlat aaa aad aam adc and bound " + "bsf bsr bswap bt btc btr bts call cbw cdq clc cld cmc cmp " + "cmpsb cmpsd cmpsw cmpxchg cmpxchg8b cpuid cwd cwde daa " + "das enter int iret iretw jcxz jecxz jmp lahf lds lea " + "leave les lfs lgs lodsb lodsd lodsw loop loope loopne " + "loopnz loopz lss mov movsb movsd movsw movsx movzx neg " + "nop not or popa popad popaw popf popfd popfw push pusha " + "pushd pushaw pushf pushfd pushfw rcl rcr retf ret retn " + "rol ror sahf sal sar sbb scasb scasd scasw shl shld shrd " + "stc std stosb stosd stosw test xchg xlatb xor arpl lar " + "lsl verr verw lldt sldt lgdt sgdt ltr str clts lock wait " + "ins outs in insb insw insd out outsb outsw outsd cli sti " + "lidt sidt hlt invd lmsw prefetcht0 prefetcht1 prefetcht2 " + "prefetchnta rsm sfence smsw sysenter sysexit ud2 wbinvd " + "invlpg int1 int3 rdmsr rdtsc rdpmc wrmsr add dec div idiv " + "imul inc mul sub xaddf2xm1 " + ) + +# NASM FPU Instructions +NASM_FPU_INST = (1, "fchs fclex fcom fcomp fdecstp fdisi feni ffree ficom fild " + "finit fist fld fldcw fldenv fldl2e fldl2e fldl2t fldlg2 " + "fldln2 fldpi fldz fsave fscale fsetpm frndint frstor " + "fscale fsetpm fstcw fstenv fsts fstsw ftst fucom fucomp " + "fxam fxch fxtract fyl2x fyl2xp1"" fabs fadd faddp fbld " + "fcos fdiv fdivr fiadd fidiv fimul fisub fmul fpatan fptan " + "fsin fsincos fsqrt fsub fsubr fsave fbstp") + +# NASM Registers +NASM_REGISTERS = (2, "ah al ax bh bl bp bx ch cl cr0 cr2 cr3 cr4 cs cx dh di " + "dl dr0 dr1 dr2 dr3 dr6 dr7 ds dx eax ebp ebx ecx edi edx " + "es esi esp fs gs si sp ss st tr3 tr4 tr5 tr6 tr7 st0 st1 " + "st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 " + "xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7") + +# NASM Directives +NASM_DIRECTIVES = (3, "DF EXTRN FWORD RESF TBYTE FAR NEAR SHORT BYTE WORD " + "QWORD DQWORD HWORD DHWORD TWORD CDECL FASTCALL NONE " + "PASCAL STDCALL DB DW DD DQ DDQ DT RESB RESW RESD RESQ " + "REST EXTERN GLOBAL COMMON __BITS__ __DATE__ __FILE__ " + "__FORMAT__ __LINE__ __NASM_MAJOR__ __NASM_MINOR__ " + "__NASM_VERSION__ __TIME__ TIMES ALIGN ALIGNB INCBIN " + "EQU NOSPLIT SPLIT ABSOLUTE BITS SECTION SEGMENT DWORD " + "ENDSECTION ENDSEGMENT __SECT__ ENDPROC EPILOGUE LOCALS " + "PROC PROLOGUE USES ENDIF ELSE ELIF ELSIF IF DO ENDFOR " + "ENDWHILE FOR REPEAT UNTIL WHILE EXIT ORG EXPORT GROUP " + "UPPERCASE SEG WRT LIBRARY _GLOBAL_OFFSET_TABLE_ " + "__GLOBAL_OFFSET_TABLE_ ..start ..got ..gotoff ..gotpc " + "..pit ..sym %define %idefine %xdefine %xidefine %undef " + "%assign %iassign %strlen %substr %macro %imacro " + "%endmacro %rotate .nolist %if %elif %else %endif %ifdef " + "%ifndef %elifdef %elifndef %ifmacro %ifnmacro " + "%elifnmacro %ifctk %ifnctk %elifctk %elifnctk %ifidn " + "%ifnidn %elifidn %elifnidn %ifidni %ifnidni %elifidni " + "%elifnidni %ifid %ifnid %elifid %elifnid %ifstr %ifnstr " + "%elifstr %elifnstr %ifnum %ifnnum %elifnum %elifnnum " + "%error %rep %endrep %exitrep %include %push %pop %repl " + "struct endstruc istruc at iend align alignb %arg " + "%stacksize %local %line bits use16 use32 section " + "absolute extern global common cpu org section group " + "import export %elifmacro ") + +NASM_DIREC_OP = (4, "a16 a32 o16 o32 byte word dword nosplit $ $$ seq wrt flat " + "large small .text .data .bss near far %0 %1 %2 %3 %4 %5 " + "%6 %7 %8 %9") + +NASM_EXT_INST = (5, "") + +#---- Language Styling Specs ----# +SYNTAX_ITEMS = [ (stc.STC_ASM_DEFAULT, 'default_style'), + (stc.STC_ASM_CHARACTER, 'char_style'), + (stc.STC_ASM_COMMENT, 'comment_style'), + (stc.STC_ASM_COMMENTBLOCK, 'comment_style'), + (stc.STC_ASM_CPUINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_DIRECTIVE, 'keyword3_style'), + (stc.STC_ASM_DIRECTIVEOPERAND, 'keyword4_style'), + (stc.STC_ASM_EXTINSTRUCTION, 'funct_style'), + (stc.STC_ASM_IDENTIFIER, 'default_style'), + (stc.STC_ASM_MATHINSTRUCTION, 'keyword_style'), + (stc.STC_ASM_NUMBER, 'number_style'), + (stc.STC_ASM_OPERATOR, 'operator_style'), + (stc.STC_ASM_REGISTER, 'keyword2_style'), + (stc.STC_ASM_STRING, 'string_style'), + (stc.STC_ASM_STRINGEOL, 'stringeol_style') ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for NASM""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_ASM) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [NASM_CPU_INST, NASM_FPU_INST, NASM_REGISTERS, + NASM_DIRECTIVES, NASM_DIREC_OP] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u';'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nonmem.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nonmem.py new file mode 100644 index 0000000..23778a9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nonmem.py @@ -0,0 +1,207 @@ +############################################################################### +# Name: nonmem.py # +# Purpose: Define NONMEM syntax for highlighting and other features # +# Author: Robert McLeay <robert\@fearthecow.net> # +# Copyright: (c) 2008 Cody Precord (staff\@editra.org) # +# (c) 2008 Torsten Mohr (none_yet) # +# (c) 2010 Robert McLeay (robert\@fearthecow.net) # +# License: wxWindows License # +############################################################################### + +""" +FILE: nonmem.py +AUTHOR: Cody Precord, Torsten Mohr, Robert McLeay +@summary: Lexer configuration module for NONMEM control streams. + +""" + +__author__ = "Cody Precord <cprecord>, Torsten Mohr <none_yet>" +__svnid__ = "$Id: _nonmem.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +from pygments.lexer import RegexLexer, include, bygroups +from pygments.token import Token, Text, Comment, Operator, \ + Keyword, Name, String, Number, Punctuation + +import re + +#Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# +# Style Id's + +# Style Id's + +STC_NONMEM_DEFAULT, \ +STC_NONMEM_COMMENT, \ +STC_NONMEM_NUMBER, \ +STC_NONMEM_STRING, \ +STC_NONMEM_STRINGEOL, \ +STC_NONMEM_OPERATOR, \ +STC_NONMEM_NAME, \ +STC_NONMEM_ABSTRACTRULE, \ +STC_NONMEM_FEATURE, \ +STC_NONMEM_CROSSREF, \ +STC_NONMEM_PACKAGE, \ +STC_NONMEM_KEYWORD, \ +STC_NONMEM_KEYWORD_PSEUDO = range(13) + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Xtext Keywords +KEYWORDS = ("grammar generate import returns enum terminal hidden with as current") +TERMINALS = ("ID INT STRING") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (STC_NONMEM_DEFAULT, 'default_style'), + (STC_NONMEM_COMMENT, 'comment_style'), + (STC_NONMEM_NUMBER, 'number_style'), + (STC_NONMEM_STRING, 'string_style'), + (STC_NONMEM_STRINGEOL, 'stringeol_style'), + (STC_NONMEM_OPERATOR, 'operator_style'), + (STC_NONMEM_NAME, 'default_style'), + (STC_NONMEM_ABSTRACTRULE, 'keyword3_style'), + (STC_NONMEM_FEATURE, 'default_style'), + (STC_NONMEM_CROSSREF, 'class_style'), + (STC_NONMEM_PACKAGE, 'class_style'), + (STC_NONMEM_KEYWORD, 'keyword_style'), + (STC_NONMEM_KEYWORD_PSEUDO, 'keyword2_style'), ] + +NONMEM_KEYWORDS = ("ADVAN\d+ BLOCK COMP COND CONDITIONAL DEFDOSE DEFOBS " + "DOWHILE ELSE ENDDO ENDIF EXP FILE FIX FIXED ICALL IF " + "IGNORE INTER INTERACTION LOG MATRIX MAX MAXEVAL METHOD " + "NEWIND NOABORT NOAPPEND NOPRINT NOHEADER ONEHEADER PRINT " + "SIG SIGDIGITS SLOW SUBPROBLEMS THEN TOL TRANS1 TRANS2 " + "TRANS3 TRANS4 ONLYSIM ENDIF") +NONMEM_PARAMS = "DADT ERR EPS ETA THETA" +#NONMEM_SPECIAL = "\$COV $DATA $DES $ERROR $EST \$INPUT $MODEL $OMEGA $PRED \\$PK $PROB $PROBLEM $SIGMA $SIM $SUB $TABLE $THETA" + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for IssueLists + This class is primarily intended as an example to creating a custom + lexer. + + """ + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CONTAINER) + self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText) + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + +#---- End Required Module Functions ----# + +def StyleText(_stc, start, end): + """Style the text + @param _stc: Styled text control instance + @param start: Start position + @param end: end position + + """ + for index, token, txt in lexer.get_tokens_unprocessed(_stc.GetTextRange(0, end)): +# print index, token, txt + style = TOKEN_MAP.get(token, STC_NONMEM_DEFAULT) + +# print "Text=%s, len=%s" % (txt, len(txt)) + _stc.StartStyling(index, 0x1f) + tlen = len(txt) + if tlen: + _stc.SetStyling(len(txt), style) + +TOKEN_MAP = { Token.String : STC_NONMEM_STRING, + Token.Comment.Multiline : STC_NONMEM_COMMENT, + Token.Comment.Single : STC_NONMEM_COMMENT, + Token.Operator : STC_NONMEM_OPERATOR, + Token.Punctuation : STC_NONMEM_OPERATOR, + Token.Number.Integer : STC_NONMEM_NUMBER, + Token.Keyword : STC_NONMEM_KEYWORD, + Token.Keyword.Pseudo: STC_NONMEM_KEYWORD_PSEUDO, + Token.Name : STC_NONMEM_NAME, + Token.Name.AbstractRule : STC_NONMEM_ABSTRACTRULE, + Token.Name.Feature : STC_NONMEM_FEATURE, + Token.Name.CrossRef : STC_NONMEM_CROSSREF, + Token.Name.Package : STC_NONMEM_PACKAGE, + Token.Name.Package.EMF : STC_NONMEM_PACKAGE} + + +class NONMEMLexer(RegexLexer): + """ + Nonmem lexer based on statefull RegexLexer from pygments library. + """ + + name = 'NONMEM' + aliases = ['nonmem'] + filenames = ['*.ctl'] + mimetypes = ['text/x-nonmem'] + + flags = re.MULTILINE | re.DOTALL # | re.UNICODE + + #: optional Comment or Whitespace + #_ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+' + + def AltWords(words): + """Makes lexer rule for alternative words from the given words list. + @param words: string consisting of space separated words + @return: string in the form \\bword1\\b|\\bword2\\b|\\bword3\\b... + """ + return "|".join([ "\\b%s\\b" % w for w in words.split()]) + + _ident = r'\^?[a-zA-Z_\$][a-zA-Z0-9_]*' + + tokens = { + 'root': [ + (include('first')), + (_ident + r'(\.' + _ident + r')+', Name.Package), + ('(' + _ident + r')(\s*)(returns)', + bygroups(Name.AbstractRule, Text.Whitespace, Keyword), 'parserrule'), + ('(' + _ident + r')(\s*)(:)', + bygroups(Name.AbstractRule, Text.Whitespace, Punctuation), 'parserrule'), + (_ident, Name), + ], + 'first': [ + (r';[^\n]*$', Comment.Single), + (r'\$[A-Z]+', Name.Package), + (r'[ \t]+', Text.Whitespace), + (r'"(\\\\|\\"|[^"])*"', String), + (r"'(\\\\|\\'|[^'])*'", String), + (r'\*|\?|\+|!|\||=|\?=|\+=|\.\.|->', Operator), + (r'[()\[\]{}:]', Punctuation), + (r'[0-9]+', Number.Integer), + (AltWords(NONMEM_KEYWORDS), Keyword), + (AltWords(NONMEM_PARAMS), Keyword.Pseudo), + # (AltWords(NONMEM_SPECIAL), Name.Package), + ], + 'parserrule': [ + (include('first')), + ('(' + _ident + r'(\.' + _ident + r')?)([ \t]*)(=|\?=|\+=)', + bygroups(Name.Feature, Text.Whitespace, Operator)), + (_ident + r'(\.' + _ident + r')+', Name.Package), + (_ident, Name.CrossRef), + ], + } + +lexer = NONMEMLexer() + +if __name__=='__main__': + import codecs, sys + ftext = codecs.open(sys.argv[1], "r", "utf-8") + text = ftext.read() + ftext.close() + line=1 + for index, token, txt in lexer.get_tokens_unprocessed(text): + if token is Token.EndOfLine: + line += 1 + print line, token, txt diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nsis.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nsis.py new file mode 100644 index 0000000..169bfc9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_nsis.py @@ -0,0 +1,160 @@ +############################################################################### +# Name: nsis.py # +# Purpose: Define NSIS syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: nsis.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Nullsoft Installer Scripts. +@todo: Add User Defined KW + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _nsis.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# NSIS Functions +NSIS_FUNCT = (0, "!addincludedir !addplugindir MakeNSIS Portions Contributors: " + "Abort AddBrandingImage AddSize AutoCloseWindow BGFont " + "BrandingText BringToFront Call CallInstDLL Caption ChangeUI " + "ClearErrors ComponentText GetDLLVersion GetDLLVersionLocal " + "GetFileTime GetFileTimeLocal CopyFiles CRCCheck FileRead " + "CreateFont CreateShortCut SetDatablockOptimize DeleteINISec " + "DeleteINIStr DeleteRegKey DeleteRegValue Delete DetailPrint " + "DirText DirShow DirVar DirVerify GetInstDirError BGGradient" + "AllowRootDirInstall CheckBitmap EnableWindow EnumRegKey " + "EnumRegValue Exch Exec ExecWait ExecShell ExpandEnvStrings " + "FindWindow FindClose FindFirst FindNext File FileBufSize " + "FlushINI ReserveFile FileClose FileErrorText FileOpen IntCmp " + "FileWrite FileReadByte FileWriteByte FileSeek Function Page " + "GetDlgItem GetFullPathName GetTempFileName HideWindow Icon " + "IfErrors IfFileExists IfRebootFlag IfSilent InstallDirRegKey " + "InstallColors InstallDir InstProgressFlags InstType IntOp " + "IntCmpU IntFmt IsWindow Goto LangString LangStringUP Return " + "LicenseForceSelection LicenseLangString LicenseText " + "LoadLanguageFile LogSet LogText MessageBox Nop Name OutFile " + "PageCallbacks PageEx PageExEnd Pop Push Quit ReadINIStr " + "ReadRegDWORD ReadRegStr ReadEnvStr Reboot RegDLL Rename " + "RMDir Section SectionEnd SectionIn SubSection SectionGroup " + "SubSectionEnd SectionGroupEnd SearchPath SectionSetFlags " + "SectionGetFlags SectionSetInstTypes SectionGetInstTypes " + "SectionGetText SectionSetText SectionGetSize SectionSetSize " + "GetCurInstType SetCurInstType InstTypeSetText SetCompress" + "SendMessage SetAutoClose SetCtlColors SetBrandingImage " + "SetCompressor SetCompressorDictSize SetCompressionLevel " + "SetDateSave SetDetailsView SetDetailsPrint SetErrors " + "GetErrorLevel SetFileAttributes SetFont SetOutPath " + "SetPluginUnload SetRebootFlag SetShellVarContext SetSilent " + "ShowInstDetails ShowUninstDetails ShowWindow SilentInstall " + "SilentUnInstall Sleep StrCmp StrCpy StrLen SubCaption " + "UninstallExeName UninstallCaption UninstallIcon UninstPage " + "UninstallText UninstallSubCaption UnRegDLL WindowIcon " + "WriteRegBin WriteRegDWORD WriteRegStr WriteRegExpandStr " + "WriteUninstaller XPStyle !packhdr !system !execute !echo " + "!include !cd !ifdef !ifndef !endif !define !undef !else " + "!warning !error !verbose !macro !macroend !insertmacro " + "!ifmacrondef MiscButtonText DetailsButtonText " + "InstallButtonText SpaceTexts CompletedText InitPluginsDir " + "GetLabelAddress GetCurrentAddress !AddPluginDir LockWindow " + "AllowSkipFiles Var VIAddVersionKey VIProductVersion " + "ShowUnInstDetails WriteIniStr CreateDirectory FunctionEnd " + "IfAbort LicenseData LicenseBkColor InstTypeGetText " + "SetErrorLevel SetOverwrite WriteINIStr !AddIncludeDir " + "!ifmacrodef UninstallButtonText GetFunctionAddress ") + +# NSIS Variables/Constants +NSIS_VAR = (1, "$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $R0 $R1 $R2 $R3 $R4 $R5 $R6 $R7 " + "$R8 $R9 $\t $\" $\' $\` $VARNAME $0, $INSTDIR $OUTDIR $CMDLINE " + "$LANGUAGE $PROGRAMFILES $COMMONFILES $DESKTOP $EXEDIR " + "${NSISDIR} $WINDIR $SYSDIR $TEMP $STARTMENU $SMPROGRAMS " + "$SMSTARTUP $QUICKLAUNCH $DOCUMENTS $SENDTO $RECENT $FAVORITES " + "$MUSIC $PICTURES $VIDEOS $NETHOOD $FONTS $TEMPLATES $APPDATA " + "$PRINTHOOD $INTERNET_CACHE $COOKIES $HISTORY $PROFILE " + "$ADMINTOOLS $RESOURCES $RESOURCES_LOCALIZED $CDBURN_AREA " + "$HWNDPARENT $PLUGINSDIR $$ $\r $\n") + +# NSIS Lables (Attributes) +NSIS_LBL = (2, "ARCHIVE FILE_ATTRIBUTE_ARCHIVE FILE_ATTRIBUTE_HIDDEN LEFT " + "FILE_ATTRIBUTE_NORMAL FILE_ATTRIBUTE_OFFLINE lastused HKCR " + "FILE_ATTRIBUTE_SYSTEM FILE_ATTRIBUTE_TEMPORARY HIDDEN HKCC " + "HKCU HKDD HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG IDYES SYSTEM " + "HKEY_DYN_DATA HKEY_LOCAL_MACHINE MB_ICONQUESTION OFFLINE " + "HKLM HKPD HKU IDABORT IDCANCEL IDIGNORE IDNO IDOK IDRETRY " + "MB_ABORTRETRYIGNORE MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 " + "MB_DEFBUTTON4 MB_ICONEXCLAMATION MB_ICONINFORMATION normal off " + "MB_ICONSTOP MB_OK MB_OKCANCEL MB_RETRYCANCEL MB_RIGHT listonly " + "MB_SETFOREGROUND MB_TOPMOST MB_YESNO MB_YESNOCANCEL NORMAL " + "READONLY SW_SHOWMAXIMIZED SW_SHOWMINIMIZED SW_SHOWNORMAL " + "TEMPORARY auto colored false force hide ifnewer nevershow " + "on show silent silentlog smooth true try lzma zlib bzip2 none " + "textonly both top left bottom right license components " + "instfiles uninstConfirm custom all leave current ifdiff " + "RIGHT CENTER dlg_id ALT CONTROL EXT SHIFT open print manual " + "alwaysoff FILE_ATTRIBUTE_READONLY HKEY_CURRENT_USER directory " + "HKEY_PERFORMANCE_DATA HKEY_USERS ") + +# NSIS User Defined (Not sure need help) +NSIS_DEF = (3, "") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_NSIS_DEFAULT, 'default_style'), + (stc.STC_NSIS_COMMENT, 'comment_style'), + (stc.STC_NSIS_FUNCTION, 'funct_style'), + (stc.STC_NSIS_FUNCTIONDEF, 'keyword_style'), + (stc.STC_NSIS_IFDEFINEDEF, 'pre_style'), + (stc.STC_NSIS_LABEL, 'class_style'), + (stc.STC_NSIS_MACRODEF, 'pre_style'), + (stc.STC_NSIS_NUMBER, 'number_style'), + (stc.STC_NSIS_SECTIONDEF, 'keyword_style'), + (stc.STC_NSIS_STRINGDQ, 'string_style'), + (stc.STC_NSIS_STRINGLQ, 'string_style'), + (stc.STC_NSIS_STRINGRQ, 'string_style'), + (stc.STC_NSIS_STRINGVAR, 'string_style'), + (stc.STC_NSIS_SUBSECTIONDEF, 'keyword_style'), + (stc.STC_NSIS_USERDEFINED, 'pre_style'), + (stc.STC_NSIS_VARIABLE, 'scalar_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for NSIS""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_NSIS) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [NSIS_FUNCT, NSIS_VAR, NSIS_LBL] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u';'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ooc.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ooc.py new file mode 100644 index 0000000..8a6e3f9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ooc.py @@ -0,0 +1,68 @@ +############################################################################### +# Name: ooc.py # +# Purpose: Define OOC Syntax Highlighting Support and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2010 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: ooc.py +@author: Cody Precord +@summary: Lexer configuration file for OOC (Out of Class) + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: $" +__revision__ = "$Revision: $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local imports +import synglob +import syndata +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +KEYWORDS = (0, "class cover interface implement func abstract extends from " + "this super new const final static include import use extern " + "inline proto break continue fallthrough operator if else for " + "while do switch case as in version return true false null " + "default") + +TYPES = (1, "Int Int8 Int16 Int32 Int64 Int80 Int128 UInt UInt8 UInt16 UInt32 " + "UInt64 UInt80 UInt128 Octet Short UShort Long ULong LLong ULLong " + "Float Double LDouble Float32 Float64 Float128 Char UChar WChar " + "String Void Pointer Bool SizeT This") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for many OOC""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + + def GetKeywords(self): + """Returns Specified Keywords List""" + return [KEYWORDS, TYPES, _cpp.DOC_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _cpp.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set""" + return [_cpp.FOLD, _cpp.FOLD_COM] + + def GetCommentPattern(self): + """Return comment pattern for OOC""" + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pascal.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pascal.py new file mode 100644 index 0000000..aee8569 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pascal.py @@ -0,0 +1,124 @@ +############################################################################### +# Name: pascal.py # +# Purpose: Define Pascal syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: pascal.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Pacal. +@todo: Add Support for Turbo Pascal + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _pascal.py 66108 2010-11-10 21:04:54Z CJP $" +__revision__ = "$Revision: 66108 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Pascal Keywords +PAS_KEYWORDS = (0, "and array asm begin case cdecl class const constructor " + "default destructor div do downto else end end. except exit " + "exports external far file finalization finally for " + "function goto if implementation in index inherited " + "initialization inline interface label library message mod " + "near nil not object of on or out overload override packed " + "pascal private procedure program property protected public " + "published raise read record register repeat resourcestring " + "safecall set shl shr stdcall stored string then threadvar " + "to try type unit until uses var virtual while with write " + "xor") + +# Pascal Classwords (Types) +PAS_CLASSWORDS = (1, "array boolean char integer file pointer real set string " + "text variant write read default public protected private " + "property published stored") + +# Pascal Std Functions +PAS_FUNCT = ("pack unpack Dispose New Abs Arctan Cos Exp Ln Sin Sqr Sqrt Eof " + "Eoln Write Writeln Input Output Get Page Put Odd Pred Succ Chr " + "Ord Round Trunc") + +#---- Syntax Style Specs ----# +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS = [ (stc.STC_PAS_ASM, 'default_style'), #TODO + (stc.STC_PAS_CHARACTER, 'char_style'), + (stc.STC_PAS_COMMENT, 'comment_style'), + (stc.STC_PAS_COMMENT2, 'comment_style'), + (stc.STC_PAS_COMMENTLINE, 'comment_style'), + (stc.STC_PAS_DEFAULT, 'default_style'), + (stc.STC_PAS_HEXNUMBER, 'number_style'), #TODO? + (stc.STC_PAS_IDENTIFIER, 'default_style'), + (stc.STC_PAS_NUMBER, 'number_style'), + (stc.STC_PAS_OPERATOR, 'operator_style'), + (stc.STC_PAS_PREPROCESSOR, 'pre_style'), + (stc.STC_PAS_PREPROCESSOR2, 'default_style'), #TODO + (stc.STC_PAS_STRING, 'string_style'), + (stc.STC_PAS_STRINGEOL, 'stringeol_style'), + (stc.STC_PAS_WORD, 'keyword_style'), ] +else: + # Pascal Lexer Uses C values, but need to adjust styles accordingly + SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'stringeol_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, 'number2_style'), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FLD_COMMENT = ("fold.comment", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Pascal""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_PASCAL) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [PAS_KEYWORDS, PAS_CLASSWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FLD_COMMENT] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'{', u'}'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_perl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_perl.py new file mode 100644 index 0000000..d705947 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_perl.py @@ -0,0 +1,147 @@ +############################################################################### +# Name: perl.py # +# Purpose: Define Perl syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: perl.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Perl. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _perl.py 66108 2010-11-10 21:04:54Z CJP $" +__revision__ = "$Revision: 66108 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Perl Keywords +PERL_KW = (0, "if elseif unless else switch eq ne gt lt ge le cmp not and or " + "xor while for foreach do until continue defined undef and or " + "not bless ref BEGIN END my local our goto return last next redo " + "chomp chop chr crypt index lc lcfirst length org pack reverse " + "rindex sprintf substr uc ucfirst pos quotemet split study abs " + "atan2 cos exp hex int log oct rand sin sqrt srand spice unshift " + "shift push pop split join reverse grep map sort unpack each " + "exists keys values tie tied untie carp confess croak dbmclose " + "dbmopen die syscall binmode close closedir eof fileno getc " + "lstat print printf readdir readline readpipe rewinddir select " + "stat tell telldir write fcntl flock ioctl open opendir read " + "seek seekdir sysopen sysread sysseek syswrite truncate pack vec " + "chdir chmod chown chroot glob link mkdir readlink rename rmdir " + "symlink umask ulink utime caller dump eval exit wanarray " + "import alarm exec fork getpgrp getppid getpriority kill pipe " + "setpgrp setpriority sleep system times wait waitpid accept " + "bind connect getpeername getsockname getsockopt listen recv " + "send setsockopt shutdown socket socketpair msgctl msgget msgrcv " + "msgsnd semctl semget semop shmctl shmget shmread shmwrite " + "endhostent endnetent endprooent endservent gethostbyaddr " + "gethostbyname gethostent getnetbyaddr getnetbyname getnetent " + "getprotobyname getprotobynumber getprotoent getervbyname time " + "getservbyport getservent sethostent setnetent setprotoent " + "setservent getpwuid getpwnam getpwent setpwent endpwent " + "getgrgid getlogin getgrnam setgrent endgrent gtime localtime " + "times warn formline reset scalar delete prototype lock new " + "NULL __FILE__ __LINE__ __PACKAGE__ __DATA__ __END__ AUTOLOAD " + "BEGIN CORE DESTROY END EQ GE GT INIT LE LT NE CHECK use sub " + "elsif require getgrent ") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_PL_DEFAULT, 'default_style'), + (stc.STC_PL_ARRAY, 'array_style'), + (stc.STC_PL_BACKTICKS, 'btick_style'), + (stc.STC_PL_CHARACTER, 'char_style'), + (stc.STC_PL_COMMENTLINE, 'comment_style'), + (stc.STC_PL_DATASECTION, 'default_style'), # STYLE ME + (stc.STC_PL_ERROR, 'error_style'), + (stc.STC_PL_HASH, 'global_style'), + (stc.STC_PL_HERE_DELIM, 'here_style'), + (stc.STC_PL_HERE_Q, 'here_style'), + (stc.STC_PL_HERE_QQ, 'here_style'), + (stc.STC_PL_HERE_QX, 'here_style'), + (stc.STC_PL_IDENTIFIER, 'default_style'), + (stc.STC_PL_LONGQUOTE, 'default_style'), # STYLE ME + (stc.STC_PL_NUMBER, 'number_style'), + (stc.STC_PL_OPERATOR, 'operator_style'), + (stc.STC_PL_POD, 'comment_style'), + (stc.STC_PL_PREPROCESSOR, 'pre_style' ), + (stc.STC_PL_PUNCTUATION, 'default_style'), # STYLE ME + (stc.STC_PL_REGEX, 'regex_style'), + (stc.STC_PL_REGSUBST, 'regex_style'), + (stc.STC_PL_SCALAR, 'scalar_style'), + (stc.STC_PL_STRING, 'string_style'), + (stc.STC_PL_STRING_Q, 'string_style'), + (stc.STC_PL_STRING_QQ, 'string_style'), + (stc.STC_PL_STRING_QR, 'string_style'), + (stc.STC_PL_STRING_QW, 'string_style'), + (stc.STC_PL_STRING_QX, 'string_style'), + (stc.STC_PL_SYMBOLTABLE, 'default_style'), # STYLE ME + (stc.STC_PL_WORD, 'keyword_style') ] + +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS.append((stc.STC_PL_FORMAT, 'default_style')) #TODO + SYNTAX_ITEMS.append((stc.STC_PL_FORMAT_IDENT, 'default_style')) #TODO + SYNTAX_ITEMS.append((stc.STC_PL_SUB_PROTOTYPE, 'default_style')) #TODO + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FLD_COMPACT = ("fold.compact", "1") +FLD_COMMENT = ("fold.comment", "1") +FLD_POD = ("fold.perl.pod", "1") +FLD_PKG = ("fold.perl.package", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Perl""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_PERL) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [PERL_KW] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] + +#---- Syntax Modules Internal Functions ----# +def KeywordString(option=0): + """Returns the specified Keyword String + @note: not used by most modules + + """ + if option == synglob.ID_LANG_PERL: + return PERL_KW[1] + else: + return u'' + +#---- End Syntax Modules Internal Functions ----# + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_php.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_php.py new file mode 100644 index 0000000..e81e3eb --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_php.py @@ -0,0 +1,448 @@ +############################################################################### +# Name: php.py # +# Purpose: Define PHP syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: php.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for PHP. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _php.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _html +from _cpp import AutoIndenter + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# PHP Keywords +PHP_KEYWORDS = ("__LINE__ __FILE__ __FUNCTION__ __CLASS__ __METHOD__ declare " + "else enddeclare endswitch elseif endif if switch as do endfor " + "endforeach endwhile for foreach while case default switch " + "break continue var bool boolean int integer real " + "double float string array NULL extends global static " + "new true false function " + "class object self final public private protected try catch " + "throw abstract parent interface implements " + # Language Constructs + "die echo empty exit eval include include_once isset list " + "require require_once return print unset") + +# PHP Standard Functions/Methods +# (roughly based off of PHP Pocket Reference by O'Reilly) +PHP_FUNC = ("__construct __autoload __destruct __get __set __isset __unset " + "__call __sleep __wakeup __toString __set_state __clone " + "apache_child_terminate apache_lookup_uri apache_note " + "apache_request_headers apache_response_headers apache_setenv " + "ascii2ebcdic ebcdic2ascii getallheaders virtual jewishtojd " + "array_change_key_case array_chunk array_count_values " + "array_diff_assoc array_diff array_fill array_filter array_flip " + "array_intersect_assoc array_intersect array_key_exists array_keys " + "array_map array_merge_recursive array_merge array_multisort " + "array_pad array_pop array_push array_rand array_reduce array " + "array_reverse array_search array_shift array_slice array_splice " + "array_sum array_unique array_unshift array_values array_walk " + "arsort asort compact count current each end extract in_array key " + "krsort ksort natcasesort natsort next pos prev range reset " + "rsort shuffle sizeof sort uasort uksort usort aspell_check " + "aspell_new aspell_suggest bcadd bccomp bcdiv bcmod bcmul bcpow " + "bcpowmod bcscale bcsqrt bcsub bzclose bzcompress bzdecompress " + "bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite " + "cal_days_in_month cal_from_jd cal_info cal_to_jd easter_date " + "easter_days frenchtojd gregoriantojd jddayofweek jdmonthname " + "jdtofrench jdtogregorian jdtojewish jdtojulian jdtounix " + "juliantojd unixtojd ccvs_add ccvs_auth ccvs_command ccvs_count " + "ccvs_delete ccvs_done ccvs_init ccvs_lookup ccvs_new ccvs_report " + "ccvs_return ccvs_reverse ccvs_sale ccvs_status ccvs_textvalue " + "ccvs_void call_user_method_array call_user_method class_exists " + "get_class_methods get_class_vars get_class get_declared_classes " + "get_object_vars get_parent_class is_a is_subclass_of com_load " + "com_addref com_get com_invoke com_isenum com_load_typelib " + "com_propget com_propput com_propset com_release com_set " + "cpdf_add_annotation cpdf_add_outline cpdf_arc cpdf_begin_text " + "cpdf_circle cpdf_clip cpdf_close cpdf_closepath_fill_stroke " + "cpdf_closepath_stroke cpdf_closepath cpdf_continue_text " + "cpdf_end_text cpdf_fill_stroke cpdf_fill cpdf_finalize_page " + "cpdf_finalize cpdf_global_set_document_limits cpdf_import_jpeg " + "cpdf_lineto cpdf_moveto cpdf_newpath cpdf_open cpdf_output_buffer " + "cpdf_page_init cpdf_place_inline_image cpdf_rect cpdf_restore " + "cpdf_rlineto cpdf_rmoveto cpdf_rotate_text cpdf_rotate " + "cpdf_save_to_file cpdf_save cpdf_scale cpdf_set_action_url " + "cpdf_set_char_spacing cpdf_set_creator cpdf_set_current_page " + "cpdf_set_font_directories cpdf_set_font_map_file cpdf_set_font " + "cpdf_set_horiz_scaling cpdf_set_keywords cpdf_set_leading " + "cpdf_set_page_animation cpdf_set_subject cpdf_set_text_matrix " + "cpdf_set_text_pos cpdf_set_text_rendering cpdf_set_text_rise " + "cpdf_set_title cpdf_set_viewer_preferences cpdf_set_word_spacing " + "cpdf_setdash cpdf_setflat cpdf_setgray_fill cpdf_setgray_stroke " + "cpdf_setgray cpdf_setlinecap cpdf_setlinejoin cpdf_setlinewidth " + "cpdf_setmiterlimit cpdf_setrgbcolor_fill cpdf_setrgbcolor_stroke " + "cpdf_setrgbcolor cpdf_show_xy cpdf_show cpdf_stringwidth " + "cpdf_text cpdf_translate crack_check crack_closedict cpdf_curveto " + "crack_getlastmessage crack_opendict ctype_alnum ctype_alpha " + "ctype_cntrl ctype_digit ctype_graph ctype_lower ctype_print " + "ctype_punct ctype_space ctype_upper ctype_xdigit curl_close " + "curl_errno curl_error curl_exec curl_getinfo curl_init chgrp " + "curl_version checkdate date getdate gettimeofday gmdate gmmktime " + "gmstrftime localtime microtime mktime strftime strtotime time " + "dba_close dba_delete dba_exists dba_fetch dba_firstkey filetype " + "dba_insert dba_list dba_nextkey dba_open dba_optimize dba_popen " + "dba_replace dba_sync dbase_add_record dbase_close dbase_create " + "dbase_delete_record dbase_get_record_with_names dbase_get_record " + "dbase_numfields dbase_numrecords dbase_open dbase_pack filectime " + "dbase_replace_record dblist dbmclose dbmdelete dbmexists dbmfetch " + "dbmfirstkey dbminsert dbmnextkey dbmopen dbmreplace basename " + "chmod chown clearstatcache copy delete dirname disk_free_space " + "disk_total_space diskfreespace fclose feof fflush fgetc fgetcsv " + "fgets fgetss file_exists file_get_contents file fileatime ftell " + "filegroup fileinode filemtime fileowner fileperms filesize popen " + "flock fnmatch fopen fpassthru fputs fread fscanf fseek fstat stat " + "ftruncate fwrite glob is_dir is_executable is_file is_link " + "is_readable is_uploaded_file is_writable is_writeable link " + "lstat mkdir move_uploaded_file parse_ini_file pathinfo pclose " + "readfile readlink realpath rename rewind rmdir set_file_buffer " + "symlink tempnam tmpfile touch umask unlink ftp_cdup ftp_chdir " + "ftp_close ftp_connect ftp_delete ftp_exec ftp_fget ftp_fput " + "ftp_get_option ftp_get ftp_login ftp_mdtm ftp_mkdir textdomain " + "ftp_nb_fget ftp_nb_fput ftp_nb_get ftp_nb_put ftp_nlist ftp_pasv " + "ftp_put ftp_pwd ftp_quit ftp_rawlist ftp_rename ftp_rmdir checkin " + "ftp_set_option ftp_site ftp_size ftp_ssl_connect ftp_systype " + "call_user_func_array call_user_func create_function func_get_arg " + "func_get_args func_num_args function_exists get_defined_functions " + "register_shutdown_function register_tick_function method_exists " + "unregister_tick_function bind_textdomain_codeset bindtextdomain " + "dcgettext dcngettext dgettext dngettext gettext ngettext " + "gmp_abs gmp_add gmp_and gmp_clrbit gmp_cmp gmp_com gmp_div_q " + "gmp_div_qr gmp_div_r gmp_div gmp_divexact gmp_fact gmp_gcd " + "gmp_hamdist gmp_init gmp_intval gmp_invert gmp_jacobi gmp_gcdext " + "gmp_mod gmp_mul gmp_neg gmp_or gmp_perfect_square gmp_popcount " + "gmp_pow gmp_powm gmp_prob_prime gmp_random gmp_scan0 gmp_scan1 " + "gmp_setbit gmp_sign gmp_sqrt gmp_sqrtrm gmp_strval gmp_sub " + "header headers_sent setcookie hw_api_attribute hwapi_hgcsp " + "hw_api_content hw_api_object key langdepvalue value values insert " + "checkout children mimetype read content copy dbstat dcstat " + "dstofsrcanchors count reason find ftstat hwstat identify info " + "insertanchor insertcollection insertdocument link lock move " + "attreditable count insert remove title value object dstanchors " + "parents description type remove replace setcommitedversion assign " + "srcanchors srcsofdst unlock user userlist iconv_get_encoding " + "iconv_set_encoding iconv ob_iconv_handler exif_imagetype gmp_xor " + "exif_read_data exif_thumbnail gd_info getimagesize cpdf_stroke " + "image_type_to_mime_type image2wbmp imagealphablending imagearc " + "imagechar imagecharup imagecolorallocate imagecolorallocatealpha " + "imagecolorat imagecolorclosest imagecolorclosestalpha curl_setopt " + "imagecolorclosesthwb imagecolordeallocate imagecolorexact " + "imagecolorexactalpha imagecolorresolve imagecolorresolvealpha " + "imagecolorset imagecolorsforindex imagecolorstotal dba_handlers " + "imagecolortransparent imagecopy imagecopymerge imagecopymergegray " + "imagecopyresampled imagecopyresized imagecreate objectbyanchor " + "imagecreatefromgd2part imagecreatefromgd imagecreatefromgif " + "imagecreatefromjpeg imagecreatefrompng imagecreatefromstring " + "imagecreatefromwbmp imagecreatefromxbm imagecreatefromxpm " + "imagecreatetruecolor imagedashedline imagedestroy imageellipse " + "imagefill imagefilledarc imagefilledellipse imagefilledpolygon " + "imagefilledrectangle imagefilltoborder imagefontheight " + "imageftbbox imagefttext imagegammacorrect imagegd2 imagegd " + "imageinterlace imagejpeg imageline imageloadfont imagepalettecopy " + "imagepng imagepolygon imagepsbbox imagepscopyfont imagefontwidth " + "imagepsextendfont imagepsfreefont imagepsloadfont gmp_legendre " + "imagepstext imagerectangle imagerotate imagesetbrush imagegif " + "imagesetstyle imagesetthickness imagesettile imagestring " + "imagestringup imagesx imagesy imagetruecolortopalette " + "imagettftext imagetypes imagewbmp iptcembed iptcparse jpeg2wbmp " + "png2wbmp read_exif_data imap_8bit imap_alerts imap_append " + "imap_binary imap_body imap_bodystruct imap_check imap_base64 " + "imap_close imap_createmailbox imap_delete imap_deletemailbox " + "imap_errors imap_expunge imap_fetch_overview imap_fetchbody " + "imap_fetchheader imap_fetchstructure imap_get_quota imagettfbbox " + "imap_getmailboxes imap_getsubscribed imap_header imap_headerinfo " + "imap_headers imap_last_error imap_list imap_listmailbox " + "imap_listsubscribed imap_lsub imap_mail_compose imap_mail_copy " + "imap_mail_move imap_mail imap_mailboxmsginfo imap_listscan " + "imap_msgno imap_num_msg imap_num_recent imap_open imap_ping " + "imap_renamemailbox imap_reopen imap_rfc822_parse_adrlist linkinfo " + "imap_rfc822_parse_headers imap_rfc822_write_address imap_qprint " + "imap_search imap_set_quota imap_setacl imap_setflag_full " + "imap_status imap_subscribe imap_thread imap_uid imap_undelete " + "imap_unsubscribe imap_utf7_decode imap_utf7_encode imap_utf8 " + "assert_options assert dl extension_loaded get_cfg_var imap_sort " + "get_defined_constants get_extension_funcs get_included_files " + "get_loaded_extensions get_magic_quotes_gpc get_current_user " + "get_required_files getenv getlastmod getmygid getmyinode getmypid " + "getmyuid getopt getrusage ini_alter ini_get_all ini_get " + "ini_set php_ini_scanned_files php_logo_guid php_sapi_name " + "phpcredits phpinfo phpversion putenv set_magic_quotes_runtime " + "set_time_limit version_compare zend_logo_guid zend_version " + "ldap_8859_to_t61 ldap_add ldap_bind ldap_close ldap_compare " + "ldap_connect ldap_count_entries ldap_delete ldap_dn2ufn php_uname " + "ldap_errno ldap_error ldap_explode_dn ldap_first_attribute " + "ldap_first_entry ldap_first_reference ldap_free_result " + "ldap_get_attributes ldap_get_dn ldap_get_entries ldap_get_option " + "ldap_get_values_len ldap_get_values ldap_list ldap_mod_add " + "ldap_mod_del ldap_mod_replace ldap_modify ldap_next_attribute " + "ldap_next_entry ldap_next_reference ldap_parse_reference hypot " + "ldap_parse_result ldap_read ldap_rename ldap_search ldap_err2str " + "ldap_set_option ldap_set_rebind_proc ldap_sort ldap_start_tls " + "ldap_t61_to_8859 ldap_unbind ezmlm_hash mail abs acos acosh asin " + "asinh atan2 atan atanh base_convert bindec ceil cos cosh decbin " + "dechex decoct deg2rad exp expm1 floor fmod getrandmax hexdec " + "is_finite is_infinite is_nan lcg_value log10 log1p log max min " + "mt_getrandmax mt_rand mt_srand octdec pi pow rad2deg rand round " + "sin sinh sqrt srand tan tanh mb_convert_case mb_convert_encoding " + "mb_convert_kana mb_convert_variables mb_decode_mimeheader " + "mb_decode_numericentity mb_detect_encoding mb_detect_order " + "mb_encode_mimeheader mb_encode_numericentity mb_ereg_match " + "mb_ereg_replace mb_ereg_search_getpos mb_ereg_search_getregs " + "mb_ereg_search_init mb_ereg_search_pos mb_ereg_search_regs " + "mb_ereg_search_setpos mb_ereg_search mb_ereg mb_eregi_replace " + "mb_eregi mb_get_info mb_http_input mb_http_output ini_restore " + "mb_internal_encoding mb_language mb_output_handler mb_parse_str " + "mb_preferred_mime_name mb_regex_encoding mb_regex_set_options " + "mb_send_mail mb_split mb_strcut mb_strimwidth mb_strlen mb_strpos " + "mb_strrpos mb_strtolower mb_strtoupper mb_strwidth imagesetpixel " + "mb_substitute_character mb_substr_count mb_substr mcrypt_cbc " + "mcrypt_cfb mcrypt_create_iv mcrypt_decrypt mcrypt_ecb " + "mcrypt_enc_get_algorithms_name mcrypt_enc_get_block_size " + "mcrypt_enc_get_iv_size mcrypt_enc_get_key_size ftp_nb_continue " + "mcrypt_enc_get_modes_name mcrypt_enc_get_supported_key_sizes " + "mcrypt_enc_is_block_algorithm_mode mcrypt_enc_is_block_algorithm " + "mcrypt_enc_is_block_mode mcrypt_enc_self_test mcrypt_encrypt " + "mcrypt_generic_deinit mcrypt_generic_end mcrypt_generic_init " + "mcrypt_generic mcrypt_get_block_size mcrypt_get_cipher_name " + "mcrypt_get_iv_size mcrypt_get_key_size mcrypt_list_algorithms " + "mcrypt_list_modes mcrypt_module_close imap_scanmailbox " + "mcrypt_module_get_algo_key_size imap_get_quotaroot " + "mcrypt_module_is_block_algorithm_mode imap_mime_header_decode " + "mcrypt_module_is_block_mode mcrypt_module_open imagecreatefromgd2 " + "mcrypt_ofb mdecrypt_generic mhash_count mhash_get_block_size " + "mhash_get_hash_name mhash_keygen_s2k mhash mime_content_type " + "connection_aborted connection_status connection_timeout constant " + "defined get_browser highlight_file highlight_string " + "ignore_user_abort pack show_source sleep uniqid unpack usleep " + "msql_affected_rows msql_close msql_connect msql_create_db define " + "msql_data_seek msql_dbname msql_drop_db msql_dropdb msql_error " + "msql_fetch_array msql_fetch_field msql_fetch_object msql_createdb " + "msql_field_seek msql_fieldflags msql_fieldlen msql_fieldname " + "msql_fieldtable msql_fieldtype msql_free_result msql_freeresult " + "msql_list_dbs msql_list_fields msql_list_tables msql_listdbs " + "msql_listfields msql_listtables msql_num_fields msql_num_rows " + "msql_numfields msql_numrows msql_pconnect msql_query msql_regcase " + "msql_result msql_select_db msql_selectdb msql_tablename msql " + "checkdnsrr closelog debugger_off debugger_on gethostbyaddr " + "dns_check_record dns_get_mx dns_get_record fsockopen " + "gethostbyname gethostbynamel getmxrr getprotobyname " + "getservbyname getservbyport ip2long long2ip openlog pfsockopen " + "socket_get_status socket_set_blocking socket_set_timeout syslog " + "ocibindbyname ocicancel OCICollAppend ocicollassign " + "ocicollgetelem ocicollmax ocicollsize ocicolltrim ocicolumnisnull " + "ocicolumnname ocicolumnprecision ocicolumnscale ocicolumnsize " + "ocicolumntype ocicolumntyperaw ocicommit ocidefinebyname ocierror " + "ociexecute ocifetch ocifetchinto ocifetchstatement msql_fetch_row " + "ocifreecursor OCIFreeDesc ocifreestatement ociinternaldebug " + "ocilogoff ocilogon ocinewcollection ocinewcursor ocinewdescriptor " + "ocinlogon ocinumcols ociparse ociplogon ociresult ocirollback " + "ocirowcount ocisavelob ocisavelobfile ociserverversion ociloadlob " + "ocisetprefetch ocistatementtype ociwritelobtofile flush ob_clean " + "ob_end_clean ob_end_flush ob_flush ob_get_contents ob_get_length " + "ob_get_level ob_get_status ob_gzhandler ob_implicit_flush " + "overload pcntl_exec pcntl_fork pcntl_signal pcntl_waitpid " + "pcntl_wexitstatus pcntl_wifexited pcntl_wifsignaled ob_start " + "pcntl_wstopsig pcntl_wtermsig preg_grep preg_match_all preg_match " + "preg_quote preg_replace_callback preg_replace preg_split " + "pdf_add_annotation pdf_add_bookmark pdf_add_launchlink " + "pdf_add_note pdf_add_outline pdf_add_pdflink pdf_add_thumbnail " + "pdf_add_weblink pdf_arc pdf_arcn pdf_attach_file pdf_begin_page " + "pdf_begin_pattern pdf_begin_template pdf_circle pdf_add_locallink " + "pdf_close_pdi_page pdf_close_pdi pdf_close pcntl_wifstopped " + "pdf_closepath_stroke pdf_closepath pdf_concat pdf_continue_text " + "pdf_curveto pdf_delete pdf_end_page pdf_end_pattern " + "pdf_endpath pdf_fill_stroke pdf_fill pdf_findfont pdf_get_buffer " + "pdf_get_font pdf_get_fontname pdf_get_fontsize pdf_open_pdi_page " + "pdf_get_image_width pdf_get_majorversion pdf_get_minorversion " + "pdf_get_parameter pdf_get_pdi_parameter pdf_get_pdi_value " + "pdf_initgraphics pdf_lineto pdf_makespotcolor pdf_moveto pdf_new " + "pdf_open_CCITT pdf_open_file pdf_open_gif pdf_open_image_file " + "pdf_open_image pdf_open_jpeg pdf_open_memory_image " + "pdf_open_pdi pdf_open_png pdf_open_tiff pdf_open pdf_place_image " + "pdf_place_pdi_page pdf_rect pdf_restore pdf_rotate pdf_get_value " + "pdf_set_border_color pdf_set_border_dash pdf_set_border_style " + "pdf_set_char_spacing pdf_set_duration pdf_set_font " + "pdf_set_info_author pdf_set_info_creator pdf_set_info_keywords " + "pdf_set_info_subject pdf_set_info_title pdf_set_info " + "pdf_set_parameter pdf_set_text_matrix pdf_set_text_pos " + "pdf_set_text_rendering pdf_set_text_rise pdf_set_value " + "pdf_set_word_spacing pdf_setcolor pdf_setdash pdf_setflat " + "pdf_setgray_fill pdf_setgray_stroke pdf_setgray pdf_setlinecap " + "pdf_setlinejoin pdf_setlinewidth pdf_setmatrix pdf_setmiterlimit " + "pdf_setpolydash pdf_setrgbcolor_fill pdf_setrgbcolor_stroke " + "pdf_setrgbcolor pdf_show_boxed pdf_show_xy pdf_show pdf_skew " + "pdf_stringwidth pdf_stroke pdf_translate pg_affected_rows " + "pg_cancel_query pg_client_encoding pg_close pg_connect " + "pg_connection_busy pg_connection_reset pg_connection_status " + "pg_copy_from pg_copy_to pg_dbname pg_delete pg_end_copy " + "pg_escape_string pg_fetch_all pg_fetch_array pg_fetch_assoc " + "pg_fetch_object pg_fetch_result pg_fetch_row pg_field_is_null " + "pg_field_name pg_field_num pg_field_prtlen pg_field_size " + "pg_free_result pg_get_notify pg_get_pid pg_get_result pg_host " + "pg_last_error pg_last_notice pg_last_oid pg_lo_close pg_lo_create " + "pg_lo_export pg_lo_import pg_lo_open pg_lo_read_all pg_lo_read " + "pg_lo_seek pg_lo_tell pg_lo_unlink pg_lo_write pg_meta_data " + "pg_num_fields pg_num_rows pg_options pg_pconnect pg_ping pg_port " + "pg_put_line pg_query pg_result_error pg_result_seek pg_field_type " + "pg_select pg_send_query pg_set_client_encoding pg_trace pg_tty " + "pg_unescape_bytea pg_untrace pg_update posix_ctermid posix_getcwd " + "posix_getegid posix_geteuid posix_getgid posix_getgrgid pg_insert " + "posix_getgroups posix_getlogin posix_getpgid posix_getpgrp " + "posix_getppid posix_getpwnam posix_getpwuid posix_getrlimit " + "posix_getuid posix_isatty posix_kill posix_mkfifo posix_setegid " + "posix_seteuid posix_setgid posix_setpgid posix_setsid pdf_setfont " + "posix_times posix_ttyname posix_uname pspell_add_to_personal " + "pspell_add_to_session pspell_check pspell_clear_session " + "pspell_config_create pspell_config_ignore pspell_config_mode " + "pspell_config_personal pspell_config_repl posix_setuid " + "pspell_config_save_repl pspell_new_config pspell_new_personal " + "pspell_new pspell_save_wordlist pspell_store_replacement " + "recode_file recode_string recode ereg_replace ereg eregi_replace " + "split spliti sql_regcase ftok msg_get_queue msg_receive " + "msg_send msg_set_queue msg_stat_queue sem_acquire sem_get " + "sem_remove shm_attach shm_detach shm_get_var shm_put_var " + "shm_remove session_cache_expire session_cache_limiter sem_release " + "session_destroy session_encode session_get_cookie_params eregi " + "session_is_registered session_module_name session_name session_id " + "session_register session_save_path session_set_cookie_params " + "session_set_save_handler session_start session_unregister " + "session_write_close snmp_get_quick_print snmp_set_quick_print " + "snmprealwalk snmpset snmpwalk snmpwalkoid socket_accept snmpget " + "socket_clear_error socket_close socket_connect session_unset " + "socket_create_pair socket_create socket_get_option socket_bind " + "socket_getsockname socket_iovec_add socket_iovec_alloc " + "socket_iovec_delete socket_iovec_fetch socket_iovec_free " + "socket_iovec_set socket_last_error socket_listen socket_read " + "socket_readv socket_recv socket_recvfrom socket_recvmsg " + "socket_send socket_sendmsg socket_sendto socket_set_nonblock " + "socket_set_option socket_shutdown socket_strerror socket_write " + "socket_writev stream_context_create stream_context_get_options " + "stream_context_set_option stream_context_set_params socket_select " + "stream_filter_prepend stream_get_filters stream_get_meta_data " + "stream_get_wrappers stream_register_filter stream_filter_append " + "stream_select stream_set_blocking stream_set_timeout posix_getpid " + "stream_set_write_buffer addcslashes addslashes bin2hex chop chr " + "chunk_split convert_cyr_string count_chars crc32 crypt " + "fprintf get_html_translation_table hebrev hebrevc explode " + "htmlentities htmlspecialchars implode join levenshtein localeconv " + "md5_file md5 metaphone money_format nl_langinfo nl2br pg_convert " + "parse_str printf quoted_printable_decode quotemeta rtrim " + "setlocale sha1_file sha1 similar_text soundex sprintf sscanf ord " + "str_repeat str_replace str_rot13 str_shuffle str_word_count ltrim " + "strchr strcmp strcoll strcspn strip_tags stripcslashes strcasecmp " + "stristr strlen strnatcasecmp strnatcmp strncasecmp strncmp strpos " + "strrchr strrev strrpos strspn strstr strtok strtolower strtoupper " + "substr_count substr_replace substr trim ucfirst ucwords vprintf " + "wordwrap base64_decode base64_encode get_meta_tags parse_url " + "rawurldecode rawurlencode urldecode urlencode doubleval " + "get_defined_vars get_resource_type gettype stripslashes str_pad " + "intval is_array is_bool is_callable is_double is_float is_int " + "is_long is_null is_numeric is_object is_real is_resource floatval " + "is_string print_r serialize settype strval unserialize " + "var_dump var_export utf8_decode utf8_encode xml_error_string " + "xml_get_current_byte_index xml_get_current_column_number " + "xml_get_current_line_number xml_get_error_code is_scalar vsprintf " + "xml_parse xml_parser_create_ns xml_parser_create xml_parser_free " + "xml_parser_get_option xml_parser_set_option number_format " + "xml_set_default_handler xml_set_element_handler is_integer " + "xml_set_end_namespace_decl_handler xml_parse_into_struct strtr " + "xml_set_notation_decl_handler xml_set_object html_entity_decode " + "xml_set_processing_instruction_handler stream_register_wrapper " + "xml_set_unparsed_entity_decl_handler xslt_create xslt_errno " + "xslt_free xslt_output_process xslt_set_base xslt_set_encoding " + "xslt_set_error_handler xslt_set_log xslt_set_sax_handler " + "xslt_set_sax_handlers xslt_set_scheme_handler socket_getpeername " + "zip_close zip_entry_close zip_entry_compressedsize xslt_error " + "zip_entry_compressionmethod zip_entry_filesize zip_entry_name " + "zip_entry_open zip_entry_read zip_open zip_read session_decode " + "get_magic_quotes_runtime xslt_set_scheme_handlers pspell_suggest " + "xml_set_start_namespace_decl_handler import_request_variables " + "xml_set_external_entity_ref_handler socket_create_listen " + "xml_set_character_data_handler session_readonly shm_remove_var " + "msg_remove_queue pspell_config_runtogether posix_getsid " + "posix_getgrnam pg_result_status pg_escape_bytea pdf_set_leading " + "pdf_set_horiz_scaling pdf_save pdf_scale pdf_get_image_height " + "pdf_end_template pdf_closepath_fill_stroke ocicollassignelem " + "pdf_clip pdf_close_image ocifreecollection getprotobynumber " + "mcrypt_module_self_test define_syslog_variables " + "mcrypt_module_get_supported_key_sizes imap_clearflag_full " + "mcrypt_module_is_block_algorithm imagepsencodefont " + "mcrypt_module_get_algo_block_size imagepsslantfont count ") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_HPHP_DEFAULT, 'default_style'), + (stc.STC_HPHP_COMMENT, 'comment_style'), + (stc.STC_HPHP_COMMENTLINE, 'comment_style'), + (stc.STC_HPHP_COMPLEX_VARIABLE, 'pre_style'), #STYLE ME + (stc.STC_HPHP_HSTRING, 'string_style'), + (stc.STC_HPHP_HSTRING_VARIABLE, 'scalar_style'), # STYLE ME + (stc.STC_HPHP_NUMBER, 'number_style'), + (stc.STC_HPHP_OPERATOR, 'operator_style'), + (stc.STC_HPHP_SIMPLESTRING, 'string_style'), + (stc.STC_HPHP_VARIABLE, 'pre2_style'), + (stc.STC_HPHP_WORD, 'keyword_style') ] + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Php""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_HTML) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + # Support Embedded HTML highlighting + html = _html.SyntaxData(synglob.ID_LANG_HTML) + keywords = html.GetKeywords() + keywords.append((4, PHP_KEYWORDS)) + return keywords + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _html.SYNTAX_ITEMS + SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [_html.FOLD, _html.FLD_HTML] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code + @note: assuming pure php code for comment character(s) + + """ + return [u'//'] + +#---- Syntax Modules Internal Functions ----# +def KeywordString(option=0): + """Returns the specified Keyword String + @note: not used by most modules + + """ + return PHP_KEYWORDS + +#---- End Syntax Modules Internal Functions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pike.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pike.py new file mode 100644 index 0000000..f58b4a6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_pike.py @@ -0,0 +1,55 @@ +############################################################################### +# Name: pike.py # +# Purpose: Define highlighting/syntax for Pike programming language # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: pike.py +@summary: Defines syntax and highlighting settings for the Pike programming + language. Pike is very similar in form to C/CPP so the Cpp lexer is + used to provide the highlighting settings. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _pike.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +PIKE_KW = (0, "goto break return continue case default if else switch while " + "foreach do gauge destruct lambda inherit import typeof catch " + "for inline nomask") + +PIKE_TYPE = (1, "private protected public static " + "int string void float mapping array multiset mixed program " + "object function") +#---- End Keyword Definitions ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(_cpp.SyntaxData): + """SyntaxData object for Pike""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [PIKE_KW, PIKE_TYPE, _cpp.DOC_KEYWORDS] + + def GetCommentPattern(self): + """Get the comment pattern""" + return [u"//"] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_postscript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_postscript.py new file mode 100644 index 0000000..58d4cd1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_postscript.py @@ -0,0 +1,170 @@ +############################################################################### +# Name: postscript.py # +# Purpose: Define Postscript syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: postscript.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for PostScript. (case sensitive) +@todo: l3 keywords and ghostscript + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _postscript.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# PS Level 1 Operators +PS_L1 = (0, "$error = == FontDirectory StandardEncoding UserObjects abs add " + "aload anchorsearch and arc arcn arcto array ashow astore atan " + "awidthshow begin bind bitshift bytesavailable cachestatus ceiling " + "charpath clear cleardictstack cleartomark clip clippath closefile " + "closepath concat concatmatrix copy copypage cos count " + "countdictstack countexecstack counttomark currentcmykcolor " + "currentcolorspace currentdash currentdict currentfile currentflat " + "currentfont currentgray currenthsbcolor currentlinecap " + "currentlinejoin currentlinewidth currentmatrix currentmiterlimit " + "currentpagedevice currentpoint currentrgbcolor currentscreen " + "currenttransfer cvi cvlit cvn cvr cvrs cvs cvx def defaultmatrix " + "definefont dict dictstack div dtransform dup echo end eoclip " + "eofill eq erasepage errordict exch exec execstack executeonly " + "executive exit exp false file fill findfont flattenpath floor " + "flush flushfile for forall ge get getinterval grestore " + "grestoreall gsave gt idetmatrix idiv idtransform if ifelse image " + "imagemask index initclip initgraphics initmatrix inustroke " + "invertmatrix itransform known kshow le length lineto ln load log " + "loop lt makefont mark matrix maxlength mod moveto mul ne neg " + "newpath noaccess nor not null nulldevice or pathbbox pathforall " + "pop print prompt pstack put putinterval quit rand rcheck rcurveto " + "read readhexstring readline readonly readstring rectstroke repeat " + "resetfile restore reversepath rlineto rmoveto roll rotate round " + "rrand run save scale scalefont search setblackgeneration " + "setcachedevice setcachelimit setcharwidth setcolorscreen " + "setcolortransfer setdash setflat setfont setgray sethsbcolor " + "setlinecap setlinejoin setlinewidth setmatrix setmiterlimit " + "setpagedevice setrgbcolor setscreen settransfer setvmthreshold " + "show showpage sin sqrt srand stack start status statusdict stop " + "stopped store string stringwidth stroke strokepath sub systemdict " + "token token transform translate true truncate type ueofill " + "undefineresource userdict usertime version vmstatus wcheck where " + "widthshow write writehexstring writestring xcheck xor") + +# PS Level 2 Operators +PS_L2 = (1, "GlobalFontDirectory ISOLatin1Encoding SharedFontDirectory " + "UserObject arct colorimage cshow currentblackgeneration " + "currentcacheparams currentcmykcolor currentcolor " + "currentcolorrendering currentcolorscreen currentcolorspace " + "currentcolortransfer currentdevparams currentglobal currentgstate " + "currenthalftone currentobjectformat currentoverprint " + "currentpacking currentpagedevice currentshared " + "currentstrokeadjust currentsystemparams currentundercolorremoval " + "currentuserparams defineresource defineuserobject deletefile " + "execform execuserobject filenameforall fileposition filter " + "findencoding findresource gcheck globaldict glyphshow gstate " + "ineofill infill instroke inueofill inufill inustroke " + "languagelevel makepattern packedarray printobject product " + "realtime rectclip rectfill rectstroke renamefile resourceforall " + "resourcestatus revision rootfont scheck selectfont serialnumber " + "setbbox setblackgeneration setcachedevice2 setcacheparams " + "setcmykcolor setcolor setcolorrendering setcolorscreen " + "setcolorspace setcolortranfer setdevparams setfileposition " + "setglobal setgstate sethalftone setobjectformat setoverprint " + "setpacking setpagedevice setpattern setshared setstrokeadjust " + "setsystemparams setucacheparams setundercolorremoval " + "setuserparams setvmthreshold shareddict startjob uappend ucache " + "ucachestatus ueofill ufill undef undefinefont undefineresource " + "undefineuserobject upath ustroke ustrokepath vmreclaim " + "writeobject xshow xyshow yshow") + +# PS 3 Operators +PS_L3 = (2, "cliprestore clipsave composefont currentsmoothness " + "findcolorrendering setsmoothness shfill") + +# RIP-specific operators +RIP_OP = (3, ".begintransparencygroup .begintransparencymask .bytestring " + ".charboxpath .currentaccuratecurves .currentblendmode " + ".currentcurvejoin .currentdashadapt .currentdotlength " + ".currentfilladjust2 .currentlimitclamp .currentopacityalpha " + ".currentoverprintmode .currentrasterop .currentshapealpha " + ".currentsourcetransparent .currenttextknockout " + ".currenttexturetransparent .dashpath .dicttomark " + ".discardtransparencygroup .discardtransparencymask " + ".endtransparencygroup .endtransparencymask .execn .filename " + ".filename .fileposition .forceput .forceundef .forgetsave " + ".getbitsrect .getdevice .inittransparencymask .knownget " + ".locksafe .makeoperator .namestring .oserrno .oserrorstring " + ".peekstring .rectappend .runandhide .setaccuratecurves ." + "setblendmode .setcurvejoin .setdashadapt .setdebug " + ".setdefaultmatrix .setdotlength .setfilladjust2 .setlimitclamp " + ".setmaxlength .setopacityalpha .setoverprintmode .setrasterop " + ".setsafe .setshapealpha .setsourcetransparent .settextknockout " + ".settexturetransparent .stringbreak .stringmatch .tempfile " + ".type1decrypt .type1encrypt .type1execchar .unread arccos arcsin " + "copydevice copyscanlines currentdevice finddevice findlibfile " + "findprotodevice flushpage getdeviceprops getenv makeimagedevice " + "makewordimagedevice max min putdeviceprops setdevice") + +# User Defined Operators +USER_DEF = (4, "") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_PS_DEFAULT, 'default_style'), + (stc.STC_PS_BADSTRINGCHAR, 'unknown_style'), + (stc.STC_PS_BASE85STRING, 'string_style'), + (stc.STC_PS_COMMENT, 'comment_style'), + (stc.STC_PS_DSC_COMMENT, 'comment_style'), + (stc.STC_PS_DSC_VALUE, 'comment_style'), # STYLE ME + (stc.STC_PS_HEXSTRING, 'number_style'), + (stc.STC_PS_IMMEVAL, 'comment_style'), # STYLE ME + (stc.STC_PS_KEYWORD, 'class_style'), + (stc.STC_PS_LITERAL, 'scalar2_style'), + (stc.STC_PS_NAME, 'keyword_style'), + (stc.STC_PS_NUMBER, 'number_style'), + (stc.STC_PS_PAREN_ARRAY, 'default_style'), # STYLE ME + (stc.STC_PS_PAREN_DICT, 'default_style'), # STYLE ME + (stc.STC_PS_PAREN_PROC, 'default_style'), # STYLE ME + (stc.STC_PS_TEXT, 'default_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for PostScript""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_PS) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [PS_L1, PS_L2] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'%'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_progress.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_progress.py new file mode 100644 index 0000000..bfbd63f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_progress.py @@ -0,0 +1,262 @@ +############################################################################### +# Name: progress.py # +# Purpose: Define Progress 4gl syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Syntax highlighting definition for Progress 4GL programming language. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _progress.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _sql + +#-----------------------------------------------------------------------------# + +# Reserved Progress 4GL keywords +PROG_KW = (0, "accumulate active-window add alias all alter ambiguous analyze " + "and any apply as ascending assign at attr-space authorization " + "auto-return available background before-hide begins bell " + "between blank break btos by call can-do can-find centered " + "character check chr clear clipboard col colon color column " + "column-label columns compiler connected control count-of " + "cpstream create ctos current current-changed current-language " + "current-window current_date cursor database dataservers " + "dbcodepage dbcollation dbname dbrestrictions dbtaskid dbtype " + "dbversion dde deblank debug-list debugger decimal decimals " + "declare def default default-noxlate default-window define " + "delete delimiter descending dictionary disable disconnect disp " + "display distinct dos down drop editing enable encode entry " + "error-status escape etime except exclusive exclusive-lock " + "exclusive-web-user exists export false fetch field fields " + "file-information fill find find-case-sensitive find-global " + "find-next-occurrence find-prev-occurrence find-select " + "find-wrap-around first first-of focus font form format frame " + "frame-col frame-db frame-down frame-field frame-file " + "frame-index frame-line frame-name frame-row frame-value from " + "from-chars from-pixels gateways get-byte get-codepages " + "get-collations get-key-value getbyte global go-on go-pending " + "grant graphic-edge group having header help hide import in " + "index indicator input input-output insert integer into is " + "is-attr-space join kblabel key-code key-function key-label " + "keycode keyfunction keylabel keys keyword label last last-event " + "last-key last-of lastkey ldbname leave library like " + "line-counter listing locked lookup machine-class map member " + "message message-lines mouse mpe new next next-prompt no " + "no-attr-space no-error no-fill no-help no-hide no-labels " + "no-lock no-map no-message no-pause no-prefetch no-undo " + "no-validate no-wait not null num-aliases num-dbs num-entries " + "of off old on open opsys option or os-append os-command " + "os-copy os-create-dir os-delete os-dir os-drives os-error " + "os-rename os2 os400 output overlay page page-bottom page-number " + "page-top parameter pause pdbname persistent pixels preprocess " + "privileges proc-handle proc-status process program-name " + "Progress prompt prompt-for promsgs propath proversion put " + "put-byte put-key-value putbyte query query-tuning quit r-index " + "rcode-information readkey recid record-length rectangle release " + "reposition retain retry return return-value revert revoke run " + "save schema screen screen-io screen-lines scroll sdbname search " + "seek select self session set setuserid share-lock shared " + "show-stats skip some space status stream stream-io string-xref " + "system-dialog table term terminal text text-cursor " + "text-seg-growth this-procedure time title to today top-only " + "trans transaction trigger triggers trim true underline undo " + "unformatted union unique unix up update use-index use-revvideo " + "use-underline user userid using v6frame value values variable " + "view view-as vms wait-for web-context window window-maximized " + "window-minimized window-normal with work-table workfile write " + "xcode xref yes _cbit _control _list _memory _msg _pcontrol " + "_serial-num _trace " + "repeat transaction for each end finf where if then else skip " + "close" +) + +# Progress 4GL Types +PROG_TYPES = (1, "char character int integer format var variable log logical " + "da date") + +# Progress 4GL Operators +PROG_OP = (7, "absolute accelerator across add-first add-last advise alert-box " + "allow-replication ansi-only anywhere append appl-alert-boxes " + "application as-cursor ask-overwrite attachment auto-end-key " + "auto-endkey auto-go auto-indent auto-resize auto-zap " + "available-formats average avg backwards base-key batch-mode " + "bgcolor binary bind-where block-iteration-display border-bottom " + "border-bottom-chars border-bottom-pixels border-left " + "border-left-chars border-left-pixels border-right " + "border-right-chars border-right-pixels border-top " + "border-top-chars border-top-pixels both bottom box " + "box-selectable browse browse-header buffer buffer-chars " + "buffer-lines button buttons byte cache cache-size can-query " + "can-set cancel-break cancel-button caps careful-paint " + "case-sensitive cdecl character character_length charset checked " + "choose clear-selection close code codepage codepage-convert " + "col-of colon-aligned color-table column-bgcolor column-dcolor " + "column-fgcolor column-font column-label-bgcolor " + "column-label-dcolor column-label-fgcolor column-label-font " + "column-of column-pfcolor column-scrolling combo-box command " + "compile complete connect constrained contents context " + "context-popup control-container control-form convert-to-offset " + "convert count cpcase cpcoll cpinternal cplog cpprint cprcodein " + "cprcodeout cpterm crc-value create-control " + "create-result-list-entry create-test-file current-column " + "current-environment current-iteration current-result-row " + "current-row-modified current-value cursor-char cursor-line " + "cursor-offset data-entry-return data-type date date-format day " + "db-references dcolor dde-error dde-id dde-item dde-name " + "dde-topic debug decimal default-button default-extension " + "defer-lob-fetch define defined delete-char delete-current-row " + "delete-line delete-selected-row delete-selected-rows " + "deselect-focused-row deselect-rows deselect-selected-row " + "design-mode dialog-box dialog-help dir disabled display-message " + "display-type double drag-enabled drop-down drop-down-list dump " + "dynamic echo edge edge-chars edge-pixels editor empty end-key " + "endkey entered eq error error-column error-row event-type " + "events exclusive-id execute exp expand extended extent external " + "extract fetch-selected-row fgcolor file file-name file-offset " + "file-type filename fill-in filled filters first-child " + "first-column first-procedure first-tab-item fixed-only float " + "focused-row font-based-layout font-table force-file foreground " + "forult-row current-row-modified current-value cursor-char " + "cursor-line cursor-offset data-entry-return data-type date " + "date-format day db-references full-width full-width-chars " + "full-width-pixels ge get get-blue-value get-char-property " + "get-double get-dynamic get-file get-float get-green-value " + "get-iteration get-license get-long get-message get-number " + "get-pointer-value get-red-value get-repositioned-row " + "get-selected-widget get-short get-signature get-size get-string " + "get-tab-item get-text-height get-text-height-chars " + "get-text-height-pixels get-text-width get-text-width-chars " + "get-text-width-pixels get-unsigned-short grayed " + "grid-factor-horizontal grid-factor-vertical grid-set grid-snap " + "grid-unit-height grid-unit-height-chars grid-unit-height-pixels " + "grid-unit-width grid-unit-width-chars grid-unit-width-pixels " + "grid-visible gt handle height height-chars height-pixels " + "help-context helpfile-name hidden hint horizontal hwnd image " + "image-down image-insensitive image-size image-size-chars " + "image-size-pixels image-up immediate-display index-hint " + "indexed-reposition information init initial initial-dir " + "initial-filter initiate inner inner-chars inner-lines " + "insert-backtab insert-file insert-row insert-string insert-tab " + "integer internal-entries is-lead-byte is-row-selected " + "is-selected item items-per-row join-by-sqldb keep-frame-z-order " + "keep-messages keep-tab-order key keyword-all label-bgcolor " + "label-dcolor label-fgcolor label-font label-pfcolor labels " + "languages large large-to-small last-child last-tab-item " + "last-procedure lc le leading left left-aligned left-trim length " + "line list-events list-items list-query-attrs list-set-attrs " + "list-widgets load load-control load-icon load-image " + "load-image-down load-image-insensitive load-image-up " + "load-mouse-pointer load-small-icon log logical lookahead lower " + "lt manual-highlight margin-extra margin-height " + "margin-height-chars margin-height-pixels margin-width " + "margin-width-chars margin-width-pixels matches max max-chars " + "max-data-guess max-height max-height-chars max-height-pixels " + "max-rows max-size max-value max-width max-width-chars " + "max-width-pixels maximize maximum memory menu menu-bar " + "menu-item menu-key menu-mouse menubar message-area " + "message-area-font message-line min min-height min-height-chars " + "min-height-pixels min-size min-value min-width min-width-chars " + "min-width-pixels minimum mod modified modulo month " + "mouse-pointer movable move-after-tab-item move-before-tab-item " + "move-column move-to-bottom move-to-eof move-to-top multiple " + "multiple-key multitasking-interval must-exist name native ne " + "new-row next-column next-sibling next-tab-item next-value " + "no-apply no-assign no-bind-where no-box no-column-scrolling " + "no-convert no-current-value no-debug no-drag no-echo " + "no-index-hint no-join-by-sqldb no-lookahead no-row-markers " + "no-scrolling no-separate-connection no-separators no-underline " + "no-word-wrap none num-buttons num-columns num-copies " + "num-formats num-items num-iterations num-lines " + "num-locked-columns num-messages num-results num-selected " + "num-selected-rows num-selected-widgets num-tabs num-to-retain " + "numeric numeric-format octet_length ok ok-cancel " + "on-frame-border ordered-join ordinal orientation os-getenv " + "outer outer-join override owner page-size page-width paged " + "parent partial-key pascal pathname pfcolor pinnable " + "pixels-per-column pixels-per-row popup-menu popup-only position " + "precision preselect prev prev-column prev-sibling prev-tab-item " + "primary printer-control-handle printer-setup private-data " + "profiler Progress-source publish put-double put-float put-long " + "put-short put-string put-unsigned-short query-off-end question " + "radio-buttons radio-set random raw raw-transfer read-file " + "read-only real recursive refresh refreshable replace " + "replace-selection-text replication-create replication-delete " + "replication-write request resizable resize retry-cancel " + "return-inserted return-to-start-dir reverse-from right " + "right-aligned right-trim round row row-markers row-of rowid " + "rule rule-row rule-y save-as save-file screen-value scroll-bars " + "scroll-delta scroll-horiz-value scroll-offset " + "scroll-to-current-row scroll-to-item scroll-to-selected-row " + "scroll-vert-value scrollable scrollbar-horizontal " + "scrollbar-vertical scrolled-row-position scrolling " + "se-check-pools se-enable-off se-enable-on se-num-pools " + "se-use-message section select-focused-row select-next-row " + "select-prev-row select-repositioned-row select-row selectable " + "selected selected-items selection-end selection-list " + "selection-start selection-text send sensitive " + "separate-connection separators set-blue-value set-break " + "set-cell-focus set-contents set-dynamic set-green-value " + "set-leakpoint set-pointer-value set-property set-red-value " + "set-repositioned-row set-selection set-size set-wait-state " + "side-lab side-labe side-label side-label-handle side-labels " + "silent simple single size size-chars size-pixels slider " + "smallint sort source source-procedure sql sqrt start " + "status-area status-area-font status-bar stdcall stenciled stop " + "stopped stored-procedure string sub-average sub-count " + "sub-maximum sub-menu sub-menu-help sub-minimum sub-total " + "subscribe substitute substring subtype sum super " + "suppress-warnings system-alert-boxes system-help tab-position " + "tabbable target target-procedure temp-directory temp-table " + "terminate text-selected three-d through thru tic-marks " + "time-source title-bgcolor title-dcolor title-fgcolor title-font " + "to-rowid toggle-box tool-bar top topic total trailing truncate " + "type unbuffered unique-id unload unsubscribe upper use " + "use-dict-exps use-filename use-text v6display valid-event " + "valid-handle validate validate-condition validate-message " + "variable vertical virtual-height virtual-height-chars " + "use-filename use-text v6display valid-event valid-handle " + "validate validate-condition validate-message variable vertical " + "virtual-height virtual-height-chars widget-pool width " + "width-chars width-pixels window-name window-state window-system " + "word-wrap x-of y-of year yes-no yes-no-cancel _dcm") + + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Progress 4GL""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_SQL) + + def GetKeywords(self): + """Progress 4GL keyword specifications """ + return [PROG_KW, PROG_TYPES, PROG_OP] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _sql.SYNTAX_ITEMS + + def GetProperties(self): + """Language properties for folding ect... """ + return [_sql.FOLD,] + + def GetCommentPattern(self): + """Comment pattern """ + return [u'/*', u'*/'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_props.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_props.py new file mode 100644 index 0000000..4fcf59a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_props.py @@ -0,0 +1,62 @@ +############################################################################### +# Name: props.py # +# Purpose: Define Properties/ini syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: props.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for properties/config files + (ini, cfg, ect..). + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _props.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_PROPS_ASSIGNMENT, 'operator_style'), + (stc.STC_PROPS_COMMENT, 'comment_style'), + (stc.STC_PROPS_DEFAULT, 'default_style'), + (stc.STC_PROPS_DEFVAL, 'string_style'), + (stc.STC_PROPS_KEY, 'scalar_style'), + (stc.STC_PROPS_SECTION, 'keyword_style')] + +#---- Extra Properties ----# +FOLD = ('fold', '1') + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Properties files""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_PROPERTIES) + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return list(u'#') diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_python.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_python.py new file mode 100644 index 0000000..bf7f92e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_python.py @@ -0,0 +1,238 @@ +############################################################################### +# Name: python.py # +# Purpose: Define Python syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: python.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Python. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _python.py 69016 2011-09-06 20:00:06Z CJP $" +__revision__ = "$Revision: 69016 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +import keyword + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Indenter keywords +INDENT_KW = (u"def", u"if", u"elif", u"else", u"for", u"while", + u"class", u"try", u"except", u"finally", u"with") +UNINDENT_KW = (u"return", u"raise", u"break", u"continue", + u"pass", u"exit", u"quit") + +# Python Keywords +KEYWORDS = keyword.kwlist +KEYWORDS.extend(['True', 'False', 'None', 'self']) +PY_KW = (0, u" ".join(KEYWORDS)) + +# Highlighted builtins +try: + import __builtin__ + BUILTINS = dir(__builtin__) +except: + BUILTINS = list() +#BUILTINS.append('self') +BUILTINS = list(set(BUILTINS)) + +PY_BIN = (1, u" ".join(sorted(BUILTINS))) + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_P_DEFAULT, 'default_style'), + (stc.STC_P_CHARACTER, 'char_style'), + (stc.STC_P_CLASSNAME, 'class_style'), + (stc.STC_P_COMMENTBLOCK, 'comment_style'), + (stc.STC_P_COMMENTLINE, 'comment_style'), + (stc.STC_P_DECORATOR, 'decor_style'), + (stc.STC_P_DEFNAME, 'keyword3_style'), + (stc.STC_P_IDENTIFIER, 'default_style'), + (stc.STC_P_NUMBER, 'number_style'), + (stc.STC_P_OPERATOR, 'operator_style'), + (stc.STC_P_STRING, 'string_style'), + (stc.STC_P_STRINGEOL, 'stringeol_style'), + (stc.STC_P_TRIPLE, 'string_style'), + (stc.STC_P_TRIPLEDOUBLE, 'string_style'), + (stc.STC_P_WORD, 'keyword_style'), + (stc.STC_P_WORD2, 'userkw_style')] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_QUOTES = ("fold.quotes.python", "1") +FOLD_COMMENTS = ("fold.comment.python", "1") +TIMMY = ("tab.timmy.whinge.level", "1") # Mark Inconsistent indentation + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Python""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_PYTHON) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [PY_KW, PY_BIN] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, TIMMY, FOLD_QUOTES, FOLD_COMMENTS] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] + +#-----------------------------------------------------------------------------# + +def AutoIndenter(estc, pos, ichar): + """Auto indent python code. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + + """ + line = estc.GetCurrentLine() + spos = estc.PositionFromLine(line) + text = estc.GetTextRange(spos, pos) + eolch = estc.GetEOLChar() + inspace = text.isspace() + + # Cursor is in the indent area somewhere + if inspace: + estc.AddText(eolch + text.replace(eolch, u"")) + return + + # Check if the cursor is in column 0 and just return newline. + if not len(text): + estc.AddText(eolch) + return + + # In case of open bracket: Indent next to open bracket + def BackTrack(tmp_text, tline): + bcount = [ tmp_text.count(brac) for brac in u")}]({[" ] + bRecurse = False + for idx, val in enumerate(bcount[:3]): + if val > bcount[idx+3]: + bRecurse = True + break + if bRecurse: + tline = tline - 1 + if tline < 0: + return tmp_text + spos = estc.PositionFromLine(tline) + tmp_text = estc.GetTextRange(spos, pos) + BackTrack(tmp_text, tline) + return tmp_text + text = BackTrack(text, line) + pos = PosOpenBracket(text) + if pos > -1: + rval = eolch + (pos + 1) * u" " + estc.AddText(rval) + return + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + end_spaces = ((indent - (tabw * i_space)) * u" ") + + tokens = filter(None, text.strip().split()) + if tokens and not inspace: + if tokens[-1].endswith(u":"): + if tokens[0].rstrip(u":") in INDENT_KW: + i_space += 1 + elif tokens[-1].endswith(u"\\"): + i_space += 1 + elif len(tokens[-1]) and tokens[-1][-1] in u"}])": + ptok = tokens[-1][-1] + paren_pos = pos - (len(text) - text.rfind(ptok)) + oparen, cparen = estc.GetBracePair(paren_pos) + if cparen >= 0: # Found matching bracket + line = estc.LineFromPosition(cparen) + indent = estc.GetLineIndentation(line) + i_space = indent / tabw + end_spaces = ((indent - (tabw * i_space)) * u" ") + elif tokens[0] in UNINDENT_KW: + i_space = max(i_space - 1, 0) + + rval = eolch + (ichar * i_space) + end_spaces + if inspace and ichar != u"\t": + rpos = indent - (pos - spos) + if rpos < len(rval) and rpos > 0: + rval = rval[:-rpos] + elif rpos >= len(rval): + rval = eolch + + # Put text in the buffer + estc.AddText(rval) + +#---- End Required Module Functions ----# + +#---- Syntax Modules Internal Functions ----# +def KeywordString(): + """Returns the specified Keyword String + @note: not used by most modules + + """ + return PY_KW[1] + +def PosOpenBracket(text): + """Returns the position of the right most open bracket in text. + Brackets inside strings are ignored. In case of no open bracket + the returned value is -1 + @param text: The line preceding the new line to be indented. + @return res: The position of right most open bracket. + @note: Used by AutoIndenter + + """ + # Store positions of '(', '[','{', ')', ']', '}' + brackets = [[], [], [], [], [], []] + quotes = u"'" + u'"' + in_string = False + for pos, char in enumerate(text): + if in_string: + in_string = not char == quote + else: + if char == u'#': + break + typ = u'([{)]}'.find(char) + if typ > -1: + brackets[typ].append(pos) + else: + typ = quotes.find(char) + if typ > -1: + in_string = True + quote = quotes[typ] + res = -1 + for typ in range(3): + opn, cls = brackets[typ], brackets[typ+3] + nopn, ncls = len(opn), len(cls) + if nopn > ncls: + res = max(res, opn[nopn - ncls - 1]) + return res + +#---- End Syntax Modules Internal Functions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ruby.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ruby.py new file mode 100644 index 0000000..ca99a14 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_ruby.py @@ -0,0 +1,149 @@ +############################################################################### +# Name: ruby.py # +# Purpose: Define Ruby syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: ruby.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Ruby. +@todo: Default Style Refinement. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _ruby.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +import re + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Ruby Keywords +# NOTE: putting words with question marks in them causes an assertion to be +# raised when showing the list in the keyword helper! defined? +RUBY_KW = (0, "__FILE__ and def end in or self unless __LINE__ begin defined " + "ensure module redo super until BEGIN break do false next " + "require rescue then when END case else for nil retry true while " + "alias class elsif if not return undef yieldr puts raise " + "protected private") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_RB_BACKTICKS, 'scalar_style'), + (stc.STC_RB_CHARACTER, 'char_style'), + (stc.STC_RB_CLASSNAME, 'class_style'), + (stc.STC_RB_CLASS_VAR, 'default_style'), # STYLE ME + (stc.STC_RB_COMMENTLINE, 'comment_style'), + (stc.STC_RB_DATASECTION, 'default_style'), # STYLE ME + (stc.STC_RB_DEFAULT, 'default_style'), + (stc.STC_RB_DEFNAME, 'keyword3_style'), # STYLE ME + (stc.STC_RB_ERROR, 'error_style'), + (stc.STC_RB_GLOBAL, 'global_style'), + (stc.STC_RB_HERE_DELIM, 'default_style'), # STYLE ME + (stc.STC_RB_HERE_Q, 'here_style'), + (stc.STC_RB_HERE_QQ, 'here_style'), + (stc.STC_RB_HERE_QX, 'here_style'), + (stc.STC_RB_IDENTIFIER, 'default_style'), + (stc.STC_RB_INSTANCE_VAR, 'scalar2_style'), + (stc.STC_RB_MODULE_NAME, 'global_style'), # STYLE ME + (stc.STC_RB_NUMBER, 'number_style'), + (stc.STC_RB_OPERATOR, 'operator_style'), + (stc.STC_RB_POD, 'default_style'), # STYLE ME + (stc.STC_RB_REGEX, 'regex_style'), # STYLE ME + (stc.STC_RB_STDIN, 'default_style'), # STYLE ME + (stc.STC_RB_STDOUT, 'default_style'), # STYLE ME + (stc.STC_RB_STRING, 'string_style'), + (stc.STC_RB_STRING_Q, 'default_style'), # STYLE ME + (stc.STC_RB_STRING_QQ, 'default_style'), # STYLE ME + (stc.STC_RB_STRING_QR, 'default_style'), # STYLE ME + (stc.STC_RB_STRING_QW, 'default_style'), # STYLE ME + (stc.STC_RB_STRING_QX, 'default_style'), # STYLE ME + (stc.STC_RB_SYMBOL, 'default_style'), # STYLE ME + (stc.STC_RB_UPPER_BOUND, 'default_style'), # STYLE ME + (stc.STC_RB_WORD, 'keyword_style'), + (stc.STC_RB_WORD_DEMOTED, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +TIMMY = ("fold.timmy.whinge.level", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Ruby""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_RUBY) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [RUBY_KW] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, TIMMY] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] + +#-----------------------------------------------------------------------------# + +def AutoIndenter(estc, pos, ichar): + """Auto indent cpp code. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + + """ + rtxt = u'' + line = estc.GetCurrentLine() + text = estc.GetTextRange(estc.PositionFromLine(line), pos) + eolch = estc.GetEOLChar() + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + ndent = eolch + ichar * i_space + rtxt = ndent + ((indent - (tabw * i_space)) * u' ') + + def_pat = re.compile('\s*(class|def)\s+[a-zA-Z_][a-zA-Z0-9_]*') + text = text.strip() + if text.endswith('{') or def_pat.match(text): + rtxt += ichar + + # Put text in the buffer + estc.AddText(rtxt) + +#---- Syntax Modules Internal Functions ----# +def KeywordString(option=0): + """Returns the specified Keyword String + @note: not used by most modules + + """ + return RUBY_KW[1] + +#---- End Syntax Modules Internal Functions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_s.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_s.py new file mode 100644 index 0000000..cb156af --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_s.py @@ -0,0 +1,231 @@ +############################################################################### +# Name: s.py # +# Purpose: Define S and R syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: s.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for the S and R statistical languages + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _s.py 70466 2012-01-26 20:55:16Z CJP $" +__revision__ = "$Revision: 70466 $" + +#-----------------------------------------------------------------------------# +# Imports +from pygments.token import Token +from pygments.lexers import get_lexer_by_name +import wx +import wx.stc as stc + +#Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# +# Style Id's + +STC_S_DEFAULT, \ +STC_S_COMMENT, \ +STC_S_NUMBER, \ +STC_S_STRING, \ +STC_S_STRINGEOL, \ +STC_S_OPERATOR, \ +STC_S_KEYWORD = range(7) + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +KEYWORDS = ("all array break call else exp for function if length library list " + "match max mean min while return try NULL NA TRUE FALSE") + +R_KEYWORDS = "if else repeat while function for in next break TRUE FALSE NULL NA Inf NaN" +R_KEYWORDS2 = ("abbreviate abline abs acf acos acosh addmargins aggregate agrep " + "alarm alias alist all anova any aov aperm append apply approx " + "approxfun apropos ar args arima array arrows asin asinh assign " + "assocplot atan atanh attach attr attributes autoload autoloader " + "ave axis backsolve barplot basename beta bindtextdomain binomial " + "biplot bitmap bmp body box boxplot bquote break browser builtins " + "bxp by bzfile c call cancor capabilities casefold cat category " + "cbind ccf ceiling character charmatch chartr chol choose chull " + "citation class close cm cmdscale codes coef coefficients col " + "colnames colors colorspaces colours comment complex confint " + "conflicts contour contrasts contributors convolve cophenetic " + "coplot cor cos cosh cov covratio cpgram crossprod cummax cummin " + "cumprod cumsum curve cut cutree cycle data dataentry date dbeta " + "dbinom dcauchy dchisq de debug debugger decompose delay deltat " + "demo dendrapply density deparse deriv det detach determinant " + "deviance dexp df dfbeta dfbetas dffits dgamma dgeom dget dhyper " + "diag diff diffinv difftime digamma dim dimnames dir dirname " + "dist dlnorm dlogis dmultinom dnbinom dnorm dotchart double " + "dpois dput drop dsignrank dt dump dunif duplicated dweibull " + "dwilcox eapply ecdf edit effects eigen emacs embed end " + "environment eval evalq example exists exp expression factanal " + "factor factorial family fft fifo file filter find fitted fivenum " + "fix floor flush for force formals format formula forwardsolve " + "fourfoldplot frame frequency ftable function gamma gaussian gc " + "gcinfo gctorture get getenv geterrmessage gettext gettextf getwd " + "gl glm globalenv gray grep grey grid gsub gzcon gzfile hat " + "hatvalues hcl hclust head heatmap help hist history hsv " + "httpclient iconv iconvlist identical identify if ifelse image " + "influence inherits integer integrate interaction interactive " + "intersect invisible isoreg jitter jpeg julian kappa kernapply " + "kernel kmeans knots kronecker ksmooth labels lag lapply layout " + "lbeta lchoose lcm legend length letters levels lfactorial " + "lgamma library licence license line lines list lm load " + "loadhistory loadings local locator loess log logb logical " + "loglin lowess ls lsfit machine mad mahalanobis makepredictcall " + "manova mapply match matlines matplot matpoints matrix max mean " + "median medpolish menu merge message methods mget min missing " + "mode monthplot months mosaicplot mtext mvfft names napredict " + "naprint naresid nargs nchar ncol next nextn ngettext nlevels nlm " + "nls noquote nrow numeric objects offset open optim optimise " + "optimize options order ordered outer pacf page pairlist pairs " + "palette par parse paste pbeta pbinom pbirthday pcauchy pchisq " + "pdf pentagamma person persp pexp pf pgamma pgeom phyper pi pico " + "pictex pie piechart pipe plclust plnorm plogis plot pmatch pmax " + "pmin pnbinom png pnorm points poisson poly polygon polym " + "polyroot postscript power ppoints ppois ppr prcomp predict " + "preplot pretty princomp print prmatrix prod profile profiler " + "proj promax prompt provide psigamma psignrank pt ptukey punif " + "pweibull pwilcox q qbeta qbinom qbirthday qcauchy qchisq qexp qf " + "qgamma qgeom qhyper qlnorm qlogis qnbinom qnorm qpois qqline " + "qqnorm qqplot qr qsignrank qt qtukey quantile quarters quasi " + "quasibinomial quasipoisson quit qunif quote qweibull qwilcox " + "rainbow range rank raw rbeta rbind rbinom rcauchy rchisq " + "readline real recover rect reformulate regexpr relevel remove " + "reorder rep repeat replace replicate replications require " + "reshape resid residuals restart return rev rexp rf rgamma rgb " + "rgeom rhyper rle rlnorm rlogis rm rmultinom rnbinom rnorm round " + "row rownames rowsum rpois rsignrank rstandard rstudent rt rug " + "runif runmed rweibull rwilcox sample sapply save savehistory " + "scale scan screen screeplot sd search searchpaths seek segments " + "seq sequence serialize setdiff setequal setwd shell sign signif " + "sin single sinh sink smooth solve sort source spectrum spline " + "splinefun split sprintf sqrt stack stars start stderr stdin " + "stdout stem step stepfun stl stop stopifnot str strftime " + "strheight stripchart strptime strsplit strtrim structure " + "strwidth strwrap sub subset substitute substr substring sum " + "summary sunflowerplot supsmu svd sweep switch symbols symnum " + "system t table tabulate tail tan tanh tapply tempdir tempfile " + "termplot terms tetragamma text time title toeplitz tolower " + "topenv toupper trace traceback transform trigamma trunc truncate " + "try ts tsdiag tsp typeof unclass undebug union unique uniroot " + "unix unlink unlist unname unserialize unsplit unstack untrace " + "unz update upgrade url var varimax vcov vector version vi " + "vignette warning warnings weekdays weights which while window " + "windows with write wsbrowser xedit xemacs xfig xinch xor xtabs " + "xyinch yinch zapsmall") +R_KEYWORDS3 = ("acme aids aircondit amis aml banking barchart barley beaver " + "bigcity boot brambles breslow bs bwplot calcium cane " + "capability cav censboot channing city claridge cloth cloud " + "coal condense contourplot control corr darwin densityplot " + "dogs dotplot ducks empinf envelope environmental ethanol fir " + "frets gpar grav gravity grob hirose histogram islay knn " + "larrows levelplot llines logit lpoints lsegments lset ltext " + "lvqinit lvqtest manaus melanoma melanoma motor multiedit " + "neuro nitrofen nodal ns nuclear oneway parallel paulsen " + "poisons polar qq qqmath remission rfs saddle salinity shingle " + "simplex singer somgrid splom stripplot survival tau tmd " + "tsboot tuna unit urine viewport wireframe wool xyplot") + +#---- Syntax Style Specs ----# +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS = [ (stc.STC_R_BASEKWORD, 'class_style'), #TODO + (stc.STC_R_COMMENT, 'comment_style'), + (stc.STC_R_DEFAULT, 'default_style'), + (stc.STC_R_IDENTIFIER, 'default_style'), + (stc.STC_R_INFIX, 'default_style'), #TODO + (stc.STC_R_INFIXEOL, 'default_style'), #TODO + (stc.STC_R_KWORD, 'keyword_style'), + (stc.STC_R_NUMBER, 'number_style'), + (stc.STC_R_OPERATOR, 'operator_style'), + (stc.STC_R_OTHERKWORD, 'keyword2_style'), + (stc.STC_R_STRING, 'string_style'), + (stc.STC_R_STRING2, 'char_style')] #TODO +else: + SYNTAX_ITEMS = [ (STC_S_DEFAULT, 'default_style'), + (STC_S_COMMENT, 'comment_style'), + (STC_S_NUMBER, 'number_style'), + (STC_S_STRING, 'string_style'), + (STC_S_STRINGEOL, 'stringeol_style'), + (STC_S_OPERATOR, 'operator_style'), + (STC_S_KEYWORD, 'keyword_style') ] + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for R and S""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + if wx.VERSION >= (2, 9, 0, 0, ''): + self.SetLexer(stc.STC_LEX_R) + else: + self.SetLexer(stc.STC_LEX_CONTAINER) + self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText) + + def GetKeywords(self): + """Returns Specified Keywords List """ + if wx.VERSION >= (2, 9, 0, 0, ''): + return [(0, R_KEYWORDS), (1, R_KEYWORDS2), (2, R_KEYWORDS3)] + else: + return [(1, KEYWORDS)] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u"#",] + +#-----------------------------------------------------------------------------# + +def StyleText(_stc, start, end): + """Style the text + @param _stc: Styled text control instance + @param start: Start position + @param end: end position + @todo: performance improvements + @todo: style errors caused by unicode characters (related to internal utf8) + + """ + cpos = 0 + _stc.StartStyling(cpos, 0x1f) + lexer = get_lexer_by_name("s") + is_wineol = _stc.GetEOLMode() == stc.STC_EOL_CRLF + for token, txt in lexer.get_tokens(_stc.GetTextRange(0, end)): + style = TOKEN_MAP.get(token, STC_S_DEFAULT) + + tlen = len(txt) + + # Account for \r\n end of line characters + if is_wineol and "\n" in txt: + tlen += txt.count("\n") + + if tlen: + _stc.SetStyling(tlen, style) + cpos += tlen + _stc.StartStyling(cpos, 0x1f) + +#-----------------------------------------------------------------------------# + +TOKEN_MAP = { Token.Literal.String : STC_S_STRING, + Token.Comment : STC_S_COMMENT, + Token.Comment.Single : STC_S_COMMENT, + Token.Operator : STC_S_OPERATOR, + Token.Punctuation : STC_S_OPERATOR, + Token.Number : STC_S_NUMBER, + Token.Literal.Number : STC_S_NUMBER, + Token.Keyword : STC_S_KEYWORD, + Token.Keyword.Constant: STC_S_KEYWORD } +
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sh.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sh.py new file mode 100644 index 0000000..78a07dc --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sh.py @@ -0,0 +1,131 @@ +############################################################################### +# Name: sh.py # +# Purpose: Define Bourne/Bash/Csh/Korn Shell syntaxes for highlighting and # +# other features. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: sh.py +AUTHOR: Cody Precord +@summary: Lexer configuration file for Bourne, Bash, Kornshell and + C-Shell scripts. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _sh.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +# Bourne Shell Keywords (bash and kornshell have these too) +COMM_KEYWORDS = ("break eval newgrp return ulimit cd exec pwd shift umask " + "chdir exit read test wait continue kill readonly trap " + "contained elif else then case esac do done for in if fi " + "until while set export unset") + +# Bash/Kornshell extensions (in bash/kornshell but not bourne) +EXT_KEYWORDS = ("function alias fg integer printf times autoload functions " + "jobs r true bg getopts let stop type false hash nohup suspend " + "unalias fc history print time whence typeset while select") + +# Bash Only Keywords +BSH_KEYWORDS = ("bind disown local popd shopt builtin enable logout pushd " + "source dirs help declare") + +# Bash Shell Commands (statements) +BCMD_KEYWORDS = ("chmod chown chroot clear du egrep expr fgrep find gnufind " + "gnugrep grep install less ls mkdir mv reload restart rm " + "rmdir rpm sed su sleep start status sort strip tail touch " + "complete stop echo") + +# Korn Shell Only Keywords +KSH_KEYWORDS = "login newgrp" + +# Korn Shell Commands (statements) +KCMD_KEYWORDS = ("cat chmod chown chroot clear cp du egrep expr fgrep find " + "grep install killall less ls mkdir mv nice printenv rm rmdir " + "sed sort strip stty su tail touch tput") + +# C-Shell Keywords +CSH_KEYWORDS = ("alias cd chdir continue dirs echo break breaksw foreach end " + "eval exec exit glob goto case default history kill login " + "logout nice nohup else endif onintr popd pushd rehash repeat " + "endsw setenv shift source time umask switch unalias unhash " + "unsetenv wait") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_SH_DEFAULT, 'default_style'), + (stc.STC_SH_BACKTICKS, 'scalar_style'), + (stc.STC_SH_CHARACTER, 'char_style'), + (stc.STC_SH_COMMENTLINE, 'comment_style'), + (stc.STC_SH_ERROR, 'error_style'), + (stc.STC_SH_HERE_DELIM, 'here_style'), + (stc.STC_SH_HERE_Q, 'here_style'), + (stc.STC_SH_IDENTIFIER, 'default_style'), + (stc.STC_SH_NUMBER, 'number_style'), + (stc.STC_SH_OPERATOR, 'operator_style'), + (stc.STC_SH_PARAM, 'scalar_style'), + (stc.STC_SH_SCALAR, 'scalar_style'), + (stc.STC_SH_STRING, 'string_style'), + (stc.STC_SH_WORD, 'keyword_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FLD_COMMENT = ("fold.comment", "1") +FLD_COMPACT = ("fold.compact", "0") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for various shell scripting languages""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_BASH) + + def GetKeywords(self): + """Returns Specified Keywords List """ + keywords = list() + keyw_str = [COMM_KEYWORDS] + if self.LangId == synglob.ID_LANG_CSH: + keyw_str.append(CSH_KEYWORDS) + else: + if self.LangId != synglob.ID_LANG_BOURNE: # TODO ?? + keyw_str.append(EXT_KEYWORDS) + + if self.LangId == synglob.ID_LANG_BASH: + keyw_str.append(BSH_KEYWORDS) + keyw_str.append(BCMD_KEYWORDS) + elif self.LangId == synglob.ID_LANG_KSH: + keyw_str.append(KSH_KEYWORDS) + keyw_str.append(KCMD_KEYWORDS) + else: + pass + + keywords.append((0, " ".join(keyw_str))) + return keywords + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FLD_COMMENT, FLD_COMPACT] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_smalltalk.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_smalltalk.py new file mode 100644 index 0000000..1929809 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_smalltalk.py @@ -0,0 +1,91 @@ +############################################################################### +# Name: smalltalk.py # +# Purpose: Define Smalltalk syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: smalltalk.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Smalltalk +@todo: more keywords, styling fixes + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _smalltalk.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +# Special Selectors +ST_KEYWORDS = (0, "ifTrue: ifFalse: whileTrue: whileFalse: ifNil: ifNotNil: " + "whileTrue repeat isNil put to at notNil super self " + "true false new not isNil inspect out nil do add for " + "methods methodsFor instanceVariableNames classVariableNames " + "poolDictionaries subclass") +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_ST_ASSIGN, 'operator_style'), + (stc.STC_ST_BINARY, 'operator_style'), + (stc.STC_ST_BOOL, 'keyword_style'), + (stc.STC_ST_CHARACTER, 'char_style'), + (stc.STC_ST_COMMENT, 'comment_style'), + (stc.STC_ST_DEFAULT, 'default_style'), + (stc.STC_ST_GLOBAL, 'global_style'), + (stc.STC_ST_KWSEND, 'keyword_style'), + (stc.STC_ST_NIL, 'keyword_style'), + (stc.STC_ST_NUMBER, 'number_style'), + (stc.STC_ST_RETURN, 'keyword_style'), + (stc.STC_ST_SELF, 'keyword_style'), + (stc.STC_ST_SPECIAL, 'pre_style'), + (stc.STC_ST_SPEC_SEL, 'keyword_style'), # Words in keyword list + (stc.STC_ST_STRING, 'string_style'), + (stc.STC_ST_SUPER, 'class_style'), + (stc.STC_ST_SYMBOL, 'scalar_style')] + +#---- Extra Properties ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Smalltalk""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_SMALLTALK) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [ST_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'\"', u'\"'] + +#---- Syntax Modules Internal Functions ----# +def KeywordString(): + """Returns the specified Keyword String + @note: not used by most modules + + """ + return ST_KEYWORDS[1] + +#---- End Syntax Modules Internal Functions ----# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sql.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sql.py new file mode 100644 index 0000000..49347bd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_sql.py @@ -0,0 +1,392 @@ +############################################################################### +# Name: sql.py # +# Purpose: Define SQL syntax for highlighting and other features # +# Author: Thomas Keul <tgkeul@web.de> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: sql.py +AUTHOR: Thomas Keul + +SUMMARY: +Lexer configuration module for Oracle 10 PL/SQL (and SQL, sqlplus, pldoc). +This work is based on sql.properties of SciTE 1.74 and other documents +which are linked (these links where current in October 2007) + +The keywords are divided in several sections which unfortunally overlap. +As a fulltime PL/SQL programmer I decided which section I prefer for a +keyword which belongs to multiple sections (like 'in', 'to' or 'else'). +It may be a challange to create an editor which colour the multiple +used keywords depending on their context. +/*+ HINT use same color for PL/SQL and SQL */ +Another thing the SQL-Lexer is not able to handle is a token consisting +of several keywords. Although zone is only part in type definitions as +"timestamp with local time zone" it will be coloured if used as identifier +too. + +If you're unhappy feel free to change it or build a new SQL-Lexer :-) + +The sections I choose + - SQL keywords + - Exception names and transaction control (to hilite in a special color) + - SQL functions + - sqlplus keywords + - PL/SQL keywords + - data types + - standard packages + - pseudo variables and constants + +There are more section than supported by the lexer. Standard packages and +sqlplus keywords share a slot. You may change it. + +In contrast to Gnome gtk-sourceview sql.lang file I did not divide the +function section into subsections like "analytical functions". +For my purpose distinct colours or fonts for different function types don't +help me reading programs. +... and the Scintilla SQL lexer does not support it. + +Some useful internals of the Lexer. +It gets an array with 8 lists of keywords. These lists are defined below. + + - WordList &keywords1 = *keywordlists[0]; : SQL_KW (SQL Keywords) + - WordList &keywords2 = *keywordlists[1]; : SQL_DBO (Data Types) + - WordList &kw_pldoc = *keywordlists[2]; : SQL_PLD (epydoc field tags) + - WordList &kw_sqlplus = *keywordlists[3]; : SQL_PLUS or SQL_PKG + - WordList &kw_user1 = *keywordlists[4]; : SQL_UKW1 (standard functions) + - WordList &kw_user2 = *keywordlists[5]; : SQL_UKW2 (exceptions) + - WordList &kw_user3 = *keywordlists[6]; : SQL_UKW3 (special variables) + - WordList &kw_user4 = *keywordlists[7]; : SQL_UKW4 (PL/SQL Keywords) + +As some keywords are used multiple the colour depends on the process in the +lexer. I prefer the same colour for SQL and PL/SQL Keywords. + +if a token is realized as identifier, the keyword lists are scanned: + 1. keywords1 / SQL_KW + 2. keywords2 / SQL_DBO + 3. kw_sqlplus / SQL_PLUS + 4. kw_user1 / SQL_UKW1 + 5. kw_user2 / SQL_UKW2 + 6. kw_user3 / SQL_UKW3 + 7. kw_user4 / SQL_UKW4 + +What ever comes first wins. For this reason PL/SQL keyword are last in the +list so no prior used keyword must be removed. +Because of the preceeding @ pldoc is processed seperate. + +The Scintilla SQL Lexer 1.75 has a restriction when '#' and '$' are not +identified as valid characters of an (Oracle-)identifier. +wxPython 2.8.7.1 does not use not use lexer version 1.75 yet - so SQL_PKG +wil not work. + +@summary: Lexer configuration module for Oracle 10 PL/SQL + +""" + +__author__ = "Thomas Keul <tgkeul@web.de>" +__svnid__ = "$Id: _sql.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# SQL Keywords (Oracle 11g SQL reserved words) +# (http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/ap_keywd.htm#i690190) +SQL_KW = (0, "access add all alter and any as asc audit between by check " + "cluster column comment compress connect create current default " + "delete desc distinct drop else exclusive exists file for from " + "grant group having identified immediate in increment index " + "initial insert intersect into is like lock maxextents minus mode " + "modify noaudit nocompress not nowait number of offline on online " + "option or order pctfree prior privileges public rename resource " + "revoke row rows select session set share size start successful " + "synonym table to trigger union unique update validate values " + "view whenever where with primary key constraint foreign " + "references restrict no action without schema deferrable not " + "deferrable rule do") +# dropped reserved words from the specification above: +# char date decimal float integer long mlslabel number raw smallint varchar +# varchar2 => SQL_DBO +# level null rowid rownum sysdate uid user => SQL_UKW4 +# then => SQL_UKW3 + +# SQL Data Object (ORACLE 11g predefined SQL and PL/SQL data types) +# (http://download.oracle.com/docs/cd/B28359_01/appdev.111/b31088/exprn_expconcepts.htm#EXPRN007) +SQL_DBO = (1, "anydata anydataset anytype bfile binary_float binary_integer " + "blob boolean char character clob date day dburitype dec decimal " + "double dsinterval_unconstrained float httpuritype int integer " + "interval local long minute mlslabel month national natural " + "naturaln nchar nclob number numeric nvarchar2 ordaudio orddicom " + "orddoc ordimage ordimagesignature ordvideo pls_integer positive " + "positiven precision raw real rowid sdo_geometry sdo_georaster " + "sdo_topo_geometry second second si_averagecolor si_color " + "si_colorhistogram si_featurelist si_positionalcolor " + "si_stillimage si_texture signtype simple_double simple_float " + "simple_integer smallint time timestamp timestamp_unconstrained " + "timestamp_ltz_unconstrained timestamp_tz_unconstrained urowid " + "varchar varchar2 varying xdburitype xmltype year " + "yminterval_unconstrained zone serial") +# Note: some data types consist of more than one word like "interval year to +# month" or "timestamp with local time zone" +# some of these words are preferred in other sections: +# to with => SQL_KW +# cursor => SQL_UKW4 + +# SQL PLDoc Keywords (and epydoc and ... enhance as you like it) +# (http://pldoc.sourceforge.net/docs/Users_Guide/content.html) +SQL_PLD = (2, "TODO author deprecated headcom param return see since throws " + "type ") + +# SQL Plus (I avoid sqlplus, so this section may be outdated) +SQL_PLUS = (3, "acc~ept a~ppend archive attribute bre~ak bti~tle c~hange " + "col~umn comp~ute conn~ect copy def~ine del desc~ribe e~dit " + "exec~ute exit get help ho~st i~nput l~ist log passw~ord pau~se " + "pri~nt pro~mpt quit recover rem~ark repf~ooter reph~eader r~un " + "sav~e set sho~w shutdown spo~ol sta~rt startup store timi~ng " + "undef~ine var~iable whenever oserror whenever sqlerror cl~ear " + "disc~onnect ti~tle ") + +# SQL User Keywords 1 (Oracle 11g SQL Functions) +# (http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions001.htm#i88893) +SQL_UKW1 = (4, "abs acos add_months appendchildxml ascii asciistr asin atan " + "atan2 avg bfilename bin_to_num bitand cardinality cast ceil " + "chartorowid chr cluster_id cluster_probability cluster_set " + "coalesce compose concat convert corr cos cosh count count " + "covar_pop covar_samp cume_dist current_date current_timestamp " + "cv dbtimezone decode decompose deletexml dense_rank depth " + "deref dump empty_blob empty_clob existsnode exp extract " + "extractvalue feature_id feature_set feature_value first " + "first_value floor from_tz greatest group_id grouping " + "grouping_id hextoraw initcap insertchildxml insertxmlbefore " + "instr iteration_number lag last last_day last_value lead least " + "length ln lnnvl localtimestamp log lower lpad ltrim make_ref " + "max median min mod months_between nanvl new_time next_day " + "nls_charset_decl_len nls_charset_id nls_charset_name " + "nls_initcap nls_lower nls_upper nlssort ntile nullif " + "numtodsinterval numtoyminterval nvl nvl2 ora_hash path " + "percent_rank percentile_cont percentile_disc power " + "powermultiset powermultiset_by_cardinality prediction " + "prediction_bounds prediction_cost prediction_details " + "prediction_probability prediction_set presentnnv presentv " + "previous rank ratio_to_report rawtohex rawtonhex ref reftohex " + "regexp_instr regexp_replace regexp_substr remainder " + "round row_number rowidtochar rowidtonchar rpad rtrim " + "scn_to_timestamp sessiontimezone set sign sin sinh soundex " + "sqrt stats_binomial_test stats_crosstab stats_f_test " + "stats_ks_test stats_mode stats_mw_test stats_one_way_anova " + "stats_t_test_ stats_wsr_test stddev stddev_pop stddev_samp " + "substr sum sys_connect_by_path sys_dburigen sys_extract_utc " + "sys_xmlagg sys_xmlgen sysdate systimestamp tan tanh " + "timestamp_to_scn to_binary_double to_binary_float to_char " + "to_clob to_date to_dsinterval to_lob to_multi_byte to_nchar " + "to_nclob to_number to_single_byte to_timestamp to_timestamp_tz " + "to_yminterval translate treat trim trunc tz_offset unistr " + "updatexml upper value var_pop var_samp variance vsize " + "width_bucket xmlagg xmlcast xmlcdata xmlcolattval xmlcomment " + "xmlconcat xmldiff xmlelement xmlexists xmlforest xmlparse " + "xmlpatch xmlpi xmlquery xmlroot xmlsequence xmlserialize " + "xmltable xmltransform") +# replace, collect => SQL_UKW4 + +# SQL User Keywords 2 (Oracle 11g exceptions and transaction control) +SQL_UKW2 = (5, "access_into_null case_not_found collection_is_null " + "cursor_already_open dup_val_on_index invalid_cursor " + "invalid_number login_denied no_data_found not_logged_on " + "program_error rowtype_mismatch self_is_null storage_error " + "subscript_beyond_count subscript_outside_limit " + "sys_invalid_rowid timeout_on_resource too_many_rows " + "value_error zero_divide commit savepoint rollback") + +# SQL User KW3 (Oracle 11g pseudo variables, methods and constants) +SQL_UKW3 = (6, "binary_double_infinity binary_double_max_normal " + "binary_double_max_subnormal binary_double_min_normal " + "binary_double_min_subnormal binary_double_nan " + "binary_float_infinity1 binary_float_max_normal " + "binary_float_max_subnormal binary_float_min_normal " + "binary_float_min_subnormal binary_float_nan1 count currval " + "delete exists extend false first last level limit next nextval " + "null prior rowlabel rownum sql sqlcode sqldata sqlname " + "sqlstate sysdate trim true uid user") + +# SQL User Keywords 4 (Oracle 11g PL/SQL reserved and keywords) +# (http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/reservewords.htm#CHDBBJFE) +SQL_UKW4 = (7, "a add agent aggregate all alter and any array arrow as asc at " + "attribute authid avg begin between bfile_base binary blob_base " + "block body both bound bulk by byte c call calling cascade case " + "char_base charset charsetform charsetid check clob_base close " + "cluster clusters colauth collect columns comment commit " + "committed compiled compress connect constant constructor " + "context continue convert count crash create current cursor " + "customdatum dangling date_base declare default define delete " + "desc deterministic distinct drop duration element else elsif " + "empty end escape except exception exceptions exclusive execute " + "exists exit external fetch final fixed for forall force form " + "from function general goto grant group hash having heap hidden " + "hour identified if immediate in including index indexes " + "indicator indices infinite insert instantiable interface " + "intersect interval into invalidate is isolation java anguage " + "large leading length level library like like2 like4 likec " + "limit limited local lock long loop map max maxlen member merge " + "min minus minute mod mode modify month multiset name nan " + "national native nchar new nocompress nocopy not nowait null " + "number_base object ocicoll ocidate ocidatetime ociduration " + "ociinterval ociloblocator ocinumber ociraw ociref ocirefcursor " + "ocirowid ocistring ocitype of on only opaque open operator " + "option or oracle oradata order organization orlany orlvary " + "others out overlaps overriding package parallel_enable " + "parameter parameters partition pascal pipe pipelined pragma " + "precision prior private procedure public raise range raw read " + "record ref reference relies_on rem remainder rename replace " + "resource result result_cache return returning reverse revoke " + "rollback row sample save savepoint sb1 sb2 sb4 second segment " + "select self separate sequence serializable set share short " + "size size_t some sparse sql sqlcode sqldata sqlname sqlstate " + "standard start static stddev stored string struct style " + "submultiset subpartition substitutable subtype sum synonym " + "tabauth table tdo the then time timestamp timezone_abbr " + "timezone_hour timezone_minute timezone_region to trailing " + "transaction transactional trusted type ub1 ub2 ub4 under union " + "unique unsigned untrusted update use using valist value values " + "variable variance varray varying view views void when where " + "while with work wrapped write year zone") +# char character date day decimal double float int => SQL_CBO + +# SQL PLUS replacement - for people not forced using acient tools +# (needs Scintilla 1.75 SQL Lexer to handle) +SQL_PKG = (3, "apex_custom_auth apex_application apex_item apex_util ctx_adm " + "ctx_cls ctx_ddl ctx_doc ctx_output ctx_query ctx_report " + "ctx_thes ctx_ulexer dbms_addm dbms_advanced_rewrite " + "dbms_advisor dbms_alert dbms_application_info dbms_apply_adm " + "dbms_aq dbms_aqadm dbms_aqelm dbms_aqin dbms_assert " + "dbms_auto_task_admin dbms_aw_stats dbms_capture_adm " + "dbms_cdc_publish dbms_cdc_subscribe dbms_comparison " + "dbms_connection_pool dbms_cq_notification dbms_crypto " + "dbms_csx_admin dbms_cube dbms_cube_advise dbms_data_mining " + "dbms_data_mining_transform dbms_datapump dbms_db_version " + "dbms_ddl dbms_debug dbms_defer dbms_defer_query dbms_defer_sys " + "dbms_describe dbms_dg dbms_dimension " + "dbms_distributed_trust_admin dbms_epg dbms_errlog dbms_expfil " + "dbms_fga dbms_file_group dbms_file_transfer dbms_flashback " + "dbms_frequent_itemset dbms_hm dbms_hprof dbms_hs_parallel " + "dbms_hs_passthrough dbms_iot dbms_java dbms_job dbms_ldap " + "dbms_ldap_utl dbms_libcache dbms_lob dbms_lock dbms_logmnr " + "dbms_logmnr_d dbms_logstdby dbms_metadata dbms_mgd_id_utl " + "dbms_mgwadm dbms_mgwmsg dbms_monitor dbms_network_acl_admin " + "dbms_network_acl_utility dbms_obfuscation_toolkit dbms_odci " + "dbms_offline_og dbms_outln dbms_outln_edit dbms_output " + "dbms_pclxutil dbms_pipe dbms_predictive_analytics " + "dbms_preprocessor dbms_profiler dbms_propagation_adm " + "dbms_random dbms_rectifier_diff dbms_redefinition " + "dbms_refresh dbms_repair dbms_repcat dbms_repcat_admin " + "dbms_repcat_instantiate dbms_repcat_rgt dbms_reputil " + "dbms_resconfig dbms_resource_manager " + "dbms_resource_manager_privs dbms_result_cache dbms_resumable " + "dbms_rlmgr dbms_rls dbms_rowid dbms_rule dbms_rule_adm " + "dbms_scheduler dbms_server_alert dbms_service dbms_session " + "dbms_shared_pool dbms_space dbms_space_admin dbms_spm dbms_sql " + "dbms_sqldiag dbms_sqlpa dbms_sqltune dbms_stat_funcs " + "dbms_stats dbms_storage_map dbms_streams dbms_streams_adm " + "dbms_streams_advisor_adm dbms_streams_auth " + "dbms_streams_messaging dbms_streams_tablespace_adm " + "dbms_tdb dbms_trace dbms_transaction dbms_transform dbms_tts " + "dbms_types dbms_utility dbms_warning dbms_wm " + "dbms_workload_capture dbms_workload_replay " + "dbms_workload_repository dbms_xa dbms_xdb dbms_xdb_admin " + "dbms_xdbresource dbms_xdb_version dbms_xdbt dbms_xdbz " + "dbms_xevent dbms_xmldom dbms_xmlgen dbms_xmlindex " + "dbms_xmlparser dbms_xmlquery dbms_xmlsave dbms_xmlschema " + "dbms_xmlstore dbms_xmltranslations dbms_xplan " + "dbms_xslprocessor debug_extproc htf htp ord_dicom " + "ord_dicom_admin owa_cache owa_cookie owa_custom owa_image " + "owa_opt_lock owa_pattern owa_sec owa_text owa_util sdo_cs " + "sdo_csw_process sdo_gcdr sdo_geom sdo_geor sdo_geor_admin " + "sdo_geor_utl sdo_lrs sdo_migrate sdo_net sdo_net_mem sdo_ols " + "sdo_pc_pkg sdo_sam sdo_tin_pkg sdo_topo sdo_topo_map sdo_tune " + "sdo_util sdo_wfs_lock sdo_wfs_process sem_apis sem_perf " + "utl_coll utl_compress utl_dbws utl_encode utl_file utl_http " + "utl_i18n utl_inaddr utl_lms utl_mail utl_nla utl_raw " + "utl_recomp utl_ref utl_smtp utl_spadv utl_tcp utl_url " + "wpg_docload ") + +#---- Syntax Style Specs ----# +# Scintilla 1.75 SQL Lexer +SYNTAX_ITEMS = [ (stc.STC_SQL_DEFAULT, 'default_style'), # 0 + (stc.STC_SQL_CHARACTER, 'char_style'), # 7 + (stc.STC_SQL_COMMENT, 'comment_style'), # 1 + (stc.STC_SQL_COMMENTDOC, 'comment_style'), # 3 + (stc.STC_SQL_COMMENTDOCKEYWORD, 'dockey_style'), # 17 + (stc.STC_SQL_COMMENTDOCKEYWORDERROR, 'error_style'), # 18 + (stc.STC_SQL_COMMENTLINE, 'comment_style'), # 2 + (stc.STC_SQL_COMMENTLINEDOC, 'comment_style'), # 15 + (stc.STC_SQL_IDENTIFIER, 'default_style'), # 11 + (stc.STC_SQL_NUMBER, 'number_style'), # 4 + (stc.STC_SQL_OPERATOR, 'operator_style'), # 10 + (stc.STC_SQL_QUOTEDIDENTIFIER, 'default_style'), # 23 + (stc.STC_SQL_SQLPLUS, 'scalar_style'), # 8 + #('STC_SQL_SQLPLUS', 'funct_style'), # 8 + (stc.STC_SQL_SQLPLUS_COMMENT, 'comment_style'), # 13 + (stc.STC_SQL_SQLPLUS_PROMPT, 'default_style'), # 9 + (stc.STC_SQL_STRING, 'string_style'), # 6 + (stc.STC_SQL_USER1, 'funct_style'), # 19 + (stc.STC_SQL_USER2, 'directive_style'), # 20 + (stc.STC_SQL_USER3, 'keyword3_style'), # 21 + (stc.STC_SQL_USER4, 'keyword_style'), # 22 + (stc.STC_SQL_WORD, 'keyword_style'), # 5 + (stc.STC_SQL_WORD2, 'keyword2_style') ] # 16 + +#---- Extra Properties ----# +# found in LexSQL.cxx of Scintilla 1.74 +# Folding is rather poor for PL/SQL +FOLD = ("fold", "1") +FOLD_COMMENT = ("fold.comment", "1") +FOLD_COMPACT = ("fold.compact", "0") +FOLD_SQL_ONLY_BEGIN = ("fold.sql.only.begin", "0") + +# Properties which do not match PL/SQL +SQL_BACKSLASH_ESCAPES = ("sql.backslash.escapes", "0") +SQL_BACKTICKS_IDENTIFIER = ("lexer.sql.backticks.identifier", "0") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for PL/SQL""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_SQL) + + def GetKeywords(self): + """ Returns Specified Keywords List """ + common = [ SQL_KW, SQL_DBO, SQL_PLD, SQL_UKW1, SQL_UKW2, SQL_UKW4 ] + if self.LangId == synglob.ID_LANG_SQL: + common.append(SQL_PLUS) + else: + common.extend([SQL_PKG, SQL_UKW3]) + return common + + def GetSyntaxSpec(self): + """ Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """ Returns a list of Extra Properties to set """ + if self.LangId == synglob.ID_LANG_SQL: + return [FOLD] + else: + return [FOLD, FOLD_COMMENT, FOLD_COMPACT, FOLD_SQL_ONLY_BEGIN, + SQL_BACKSLASH_ESCAPES, SQL_BACKTICKS_IDENTIFIER] + + def GetCommentPattern(self): + """ Returns a list of characters used to comment a block of code """ + return [u'--'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_squirrel.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_squirrel.py new file mode 100644 index 0000000..e7a1362 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_squirrel.py @@ -0,0 +1,65 @@ +############################################################################### +# Name: squirrel.py # +# Purpose: Syntax Definitions for Squirrel programming language # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +@summary: Lexer configuration module for Squirrel Programming Language + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _squirrel.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _cpp + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +SQUIRREL_KW = (0, "break case catch class clone continue const default " + "delegate delete do else enum extends for foreach function " + "if in local null resume return switch this throw try typeof " + "while parent yield constructor vargc vargv instanceof true " + "false static") + +SQUIRREL_TYPES = (1, "") + +#---- End Keyword Definitions ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Squirrel""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _cpp.AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [SQUIRREL_KW, SQUIRREL_TYPES, _cpp.DOC_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _cpp.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [_cpp.FOLD,] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return ['//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_stata.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_stata.py new file mode 100644 index 0000000..46649f1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_stata.py @@ -0,0 +1,434 @@ +############################################################################### +# Name: stata.py # +# Purpose: Define Stata syntax for highlighting and other features # +# Author: Jean Eid<jeid@wlu.ca> # +# Note: stata keywords are taken from TextWrangler module for stata # +############################################################################### + +""" +FILE: stata.py +@author: Jean Eid +@summary: Lexer configuration file for STATA source files. + +""" + +__author__ = "Jean Eid <jeid@wlu.ca>" +__svnid__ = "$Id: _stata.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 0$" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local imports +import synglob +import syndata +from _cpp import AutoIndenter + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Documentation Keywords (includes Doxygen keywords) +SECONDARY_KEYWORDS =(1, + """ + __GEEBT __GEERC __GEEUC _3dax0 _3daxmin _3daxout if + _3daxtbl _3ddflts _3dmkdta _3dmnmx _3dproj _3drproj + _3drshow _3dshad _3dsvusr _ac _addl _addop _adjksm + _all _bsqreg _byobs _callerr _cpmatnm _cr1form + _cr1invt _cr1se _cr1t _crc2use _crc4fld _crcacnt + _crcar1 _crcause _crcbcrt _crcbin _crcbygr _crcchi2 + _crcchkt _crcchkw _crcci _crccip _crceprs _crcexn1 + _crcexn2 _crcexn4 _crcexn5 _crcexn6 _crcexn7 _crcexn8 + _crcexn9 _crcexna _crcexnb _crcexnc _crcexnd _crcexne + _crcexnf _crcexnt _crcgldv _crcglil _crcichi _crcird + _crcirr _crcksm _crclf _crcmeq _crcmiss _crcnlou + _crcnms2 _crcnuse _crcor _crcphdr _crcplst _crcra + _crcrd _crcrnfd _crcrr _crcrsfl _crcseq _crcshdr + _crcslbl _crcsrv2 _crcsrvc _crcstep _crcswxx _crct + _crctmge _crcunab _crcunit _crcvarl _crcwsrv _crczsku + _cu_c0 _diparm _evlist _fracchk _fraccox _fracddp + _fracdis _fracdv _fracin _fracmdp _fracord _fracpp + _fracpv _fracrep _fracwgt _fracxo _gcount _gcut _gdiff + _getbv _getrhs _getrres _gfill _ggroup _giqr _gladder + _glmfl _glmilnk _glmmapf _glmmapl _glmresd _glmrpt + _glmwgt _gma _gmad _gmax _gmdmean _gmdmed _gmean + _gmedian _gmin _gmtr _gpctile _grank _grank2 _grfirst + _grlast _grmax _grmean _grmin _grmiss _grmiss2 _grobs + _grsd _grsum _gsd _gsrank _gstd _gsum _gtma _gtrank + _hu _hub _hube _huber _inlist _invlist _isfit _jprfpdt + _jprfpdx _jprfpfp _jprfpgn _jprfpin _jprfplx _jprfpmm + _jprfppp _jprfpre _jprfprp _jprfpse _jprfptp _jprfpxo + _jprglef _jprglfl _jprglil _jprglld _jprglwz _jprxrpa + _kalman1 _ksmwrk _ldrtest _linemax _maked _merge + _mfrmvec _mkvec _mvec _newey _nlout _nobs _opnum + _parsevl _parsewt _partset _pctile _pred_me _pred_se + _predict _qreg _repart _result _rmcoll _robksm _robust + _sfran _subchar _svy _sw_lik _sw_lik2 _sw_ood _ts + _ts_dsmp _ts_flag _ts_gdat _ts_meqn _ts_pars _ts_peri + _tsheadr _ttest _ttest1 _ttest2 _tutends _tx_mtr1 + _tx_mtr2 _tx_mtr3 _tx_mtr4 _tx_mtr5 _tx_rpl _wkapm + _wsrvcrv _xtrenorm + """) + +MAIN_KEYWORDS = (0, + """ + abbrev about abs acprplot add + adjust ado adopath alpha an ano anov anova anovadef + aorder ap app appe appen append arch arch_dr arch_p + areg areg_p args arima arima_dr arima_p as ass asse + asser assert at avplot avplots aw aweight bcskew0 be + bee beep binreg bipp_lf bipr_lf bipr_p biprobit bitest + bitesti bitowt blogit bmemsize boot bootsamp boxcox + boxcox_p bprobit break brier bs bsampl_w bsample + bsqreg bstat bstrap by bys bysort byte c_local canon + canon_p capture cat cc cchart cci cd cell cellsize + centile cf char char chdir checksum chi2 chi2tail ci + cii cksum clear clo clocal clog clog_lf clog_p clogi + clogi_sw clogit clogit_p clogitp clogl_sw cloglog + close cluster cmdlog cnr cnre cnreg cnreg_sw cnsreg + codebook col collaps4 collapse compare compress + compute cond conf confi confir confirm cons const + constr constra constrai constrain constraint contract + copy cor corc corr corr2data corre correl correla + correlat correlate corrgram cou coun count cox cox_p + cox_sw coxbase coxhaz coxvar cp cprplot crc cross cs + cscript csi ct ct_is ctset ctst_5 ctst_st cttost cumsp + cumul cusum d datetof dbeta de debug debugbuf dec deco + decod decode def deff define des desc descr descri + describ describe dfbeta dfuller di dir dis discard + disp disp_res disp_s displ displa display do doe doed + doedi doedit dotplot dprobit drawnorm drop ds dstdize + dwstat dydx dyex dynre dynren e ed edi edit egen + eivreg else emdef en enc enco encod encode end eq + eqlist erase ereg ereg_lf ereg_p ereg_sw err erro + error est esti estim estima estimat estimate estimates + etodow etof etomdy ex exact exec execu execut execute + exi exit expand export eydx eyex F fac fact facto + factor fast fft fillin findit fit float for for5_0 + force form forma format fpredict frac_154 frac_adj + frac_chk frac_cox frac_ddp frac_dis frac_dv frac_in + frac_mun frac_pp frac_pq frac_pv frac_wgt frac_xo + fracgen fracplot fracpoly fracpred freq frequency + Ftail ftodate ftoe ftomdy ftowdate fw fweight g gamma + gamma_lf gamma_p gamma_sw ge gen gene gener genera + generat generate genrank genstd genvmean gettoken gl + gladder glm glm_p glm_sw glmpred glo glob globa global + glogit glogit_p gnbre_lf gnbreg gnbreg_5 gnbreg_p + gomp_lf gompe_sw gomper_p gompertz gph gphdot gphpen + gphprint gprobi_p gprobit gr gr_print gra grap graph + grebar greigen grmeanby group gsort gwood h hadimvo + hareg hausman + he heck_d2 heckma_p heckman heckp_lf heckpr_p heckprob + hel help helpchk hereg hetpr_lf hetpr_p hetprob + hettest hilite hist hlogit hlu hotel hprobit hreg icd9 + icd9p iis impute in index inf infi infil infile + infix inlist inp inpu input ins insh inshe inshee + insheet insp inspe inspec inspect int integ intreg + intrg_ll invchi2 invchi2tail invF invFtail invnchi2 + invnorm invttail ipolate iqreg ir iri istdize ivreg iw + iweight joinby kalarma1 kap kap_3 kapmeier kappa + kapwgt kdensity keep ksm ksmirnov ktau kwallis l la + lab labe label ladder length level leverage lfit + lfit_p li lincom linesize linktest lis list llogi_sw + llogis_p llogist ln lnorm_lf lnorm_sw lnorma_p lnormal + lnskew0 lo loc loca local log logi logis_lf logistic + logit logit_p loglogs logrank logtype loneway long loo + look lookfor looku lookup lower lpredict lroc lrtest + ls lsens lsens_x lstat ltable ltrim lv lvr2plot m ma + mac macr macro man mantel mark markout marksample mat + matcell match matcol matcproc matname matr matri + matrix matrow matsize matstrik max mcc mcci md0_ md1_ + md1debu_ md2_ md2debu_ mdytoe mdytof mean means median + memory memsize meqparse mer merg merge mfx mhodds min + missing mkdir mkmat mkspline ml ml_5 ml_adjs ml_bhhhs + ml_c_d ml_check ml_clear ml_cnt ml_debug ml_defd ml_e0 + ml_e0i ml_e1 ml_e2 ml_ebfg0 ml_ebfr0 ml_ebh0q ml_ebhh0 + ml_ebhr0 ml_ebr0i ml_ecr0i ml_edfp0 ml_edfr0 ml_edr0i + ml_eds ml_eer0i ml_egr0i ml_elf ml_elfi ml_elfs + ml_enr0i ml_enrr0 ml_exde ml_geqnr ml_grad0 ml_graph + ml_hbhhh ml_hd0 ml_init ml_inv ml_log ml_max ml_mlout + ml_model ml_nb0 ml_opt ml_plot ml_query ml_rdgrd + ml_repor ml_s_e ml_searc mleval mlf_ mlmatsum mlog + mlogi mlogit mlogit_p mlopts mlsum mlvecsum mnl0_ mor + more mov move mrdu0_ mvdecode mvencode mvreg n nbreg + nbreg_al nbreg_lf nbreg_sw nchi2 net newey newey_p + news nl nl_p nlexp2 nlexp2a nlexp3 nlgom3 nlgom4 + nlinit nllog3 nllog4 nlogit nlpred no nobreak nod + nodiscrete noe noesample nof nofreq noi nois noisi + noisil noisily nol nolabel nonl nonlinear normden nose + note notes notify now nowght npnchi2 nptrend numlist + obs off old_ver olo olog ologi ologi_sw ologit + ologit_p ologitp on one onew onewa oneway op_colnm + op_comp op_diff op_inv op_str opr opro oprob oprob_sw + oprobi oprobi_p oprobit oprobitp order orthog orthpoly + ou out outf outfi outfil outfile outs outsh outshe + outshee outsheet ovtest pac par pars parse pause pc + pchart pchi pcorr pctile pentium percent pergram + permanent personal pkcollapse pkcross pkequiv + pkexamine pkshape pksumm pl playsnd plo plot plug + plugi plugin pnorm poisgof poiss_lf poiss_sw poisso_p + poisson pop popu popup post postclose postfile pperron + pr prais prais_e prais_p pred predi predic predict + predict preserve printgr priorest pro prob probi + probit probit_p prog progr progra program prove prtest + prtesti push pw pwcorr pwd pweight q qby qchi qnorm + qqplot qreg qreg_c qreg_p qreg_sw qu quadchk quantile + que quer query qui quie quiet quietl quietly range + ranksum rawsum rchart rcof real recast recode reg reg3 + reg3_p regdw regr regre regre_p2 regres regres_p + regress regriv_p remap ren rena renam rename renpfix + repeat replace replay reshape restore ret retu retur + return reverse rm roccomp rocfit rocgold roctab rot + rota rotat rotate round row rreg rreg_p rtrim ru run + runtest rvfplot rvpplot sa safesum sample sampsi sav + save saving say sca scal scala scalar sco scob_lf + scob_p scobi_sw scobit scor score sd sdtest sdtesti se + search separate seperate serrbar set sfrancia sh she + shel shell shewhart showpoint signrank signtest simul + simulinit sktest sleep smcl smooth snapspan so sor + sort spearman speedchk1 speekchk2 spikeplt spline_x + sqreg sret sretu sretur sreturn st st_ct st_hc st_hcd + st_is st_issys st_note st_promo st_set st_show st_smpl + st_subid stack stackdepth stackreset statsby stbase + stci stcox stcox_p stcoxkm stcurv stcurve stdes stem + stereg stfill stgen stinit stir stjoin stmc stmh + stphplot stphtest stptime strate streg streset string + sts stset stsplit stsum sttocc sttoct stvary stweib su + subinstr subinword subpop substr subwin sum summ summa + summar summari summariz summarize sureg survcurv + survsum svmat svy_disp svy_dreg svy_est svy_get + svy_head svy_sub svy_x svydes svyintrg svyivreg svylc + svylog_p svylogit svymean svymlog svyolog svyoprob + svypois svyprobt svyprop svyratio svyreg svyreg_p + svyset svytab svytest svytotal sw swcnreg swcox swereg + swilk swlogis swlogit swologit swoprbt swpois swprobit + swqreg swtobit swweib symmetry symmi symplot syntax + sysdir sysmenu ta tab tab_or tab1 tab2 tabd tabdi + tabdis tabdisp tabi table tabodds tabstat tabu tabul + tabula tabulat tabulate te tempfile tempname tempvar + tes test testnl testparm teststd text timer tis tob + tobi tobit tobit_p tobit_sw token tokeni tokeniz + tokenize touch treatreg trim truncreg tset tsfill + tsreport tsrevar tsset tsunab ttail ttest ttesti + tut_chk tut_wait tutorial ty typ type typeof u unab + unabbrev uniform update upper us use using val values + var variable varlabelpos vce verinst vers versi versio + version vif vwls wdatetof wdctl wdlg wdupdate weib_lf + weib_lf0 weibu_sw weibul_p weibull wh whelp whi whic + which whil while wilc_st wilcoxon win wind windo + window winexec winhelp wmenu wntestb wntestq xchart + xcorr xi xpose xt_iis xt_tis xtabond xtbin_p xtclog + xtcnt_p xtcorr xtdata xtdes xtgee xtgee_p xtgls + xtgls_p xthaus xtile xtint_p xtintreg xtivreg xtlogit + xtnb_fe xtnb_lf xtnbreg xtpcse xtpois xtpred xtprobit + xtps_fe xtps_lf xtps_ren xtrch_p xtrchh xtrefe_p xtreg + xtreg_be xtreg_fe xtreg_ml xtreg_re xtregar xtrere_p + xtsum xttab xttest0 xttobit xttrans xwin xwind xwindo + xwindow zap_s zinb zinb_llf zinb_plf zip zip_llf zip_p + zip_plf zt_ct_5 zt_hc_5 zt_hcd_5 zt_is_5 zt_iss_5 + zt_sho_5 zt_smp_5 ztbase_5 ztcox_5 ztdes_5 ztereg_5 + ztfill_5 ztgen_5 ztir_5 ztjoin_5 zts_5 ztset_5 + ztspli_5 ztsum_5 zttoct_5 ztvary_5 ztweib_5 comma tab + robust mvsktest oglm dlist mahapick viewresults + valuesof textbarplot freduse hcavar distrate zipsave + hutchens svylorenz goprobit regoprob digits cprplot2 + devcon oaxaca supclust convert_top_lines graphbinary + trellis traces wtd glst lxpct_2 clv backrasch mmsrm + diplot kountry gologit2 intcens svygei_svyatk fitint + xtarsim eclpci beamplot samplepps classplot spearman2 + fixsort casefat mehetprob svyselmlog svybsamp2 + moremata checkfor2 dbmscopybatch palette_all ivreset + lookfor_all nmissing isvar descogini akdensity + biplotvlab genscore rrlogit ivvif hnblogit hnbclg + hglogit hgclg hplogit hpclg ztg cdfplot kdens cpoisson + samplesize gnbstrat nbstrat genass outreg2 kapprevi + sampsi_reg lgamma2 glgamma2 ivgauss2 givgauss2 + sampsi_mcc cnbreg xtivreg2 sliceplot cquantile primes + scheme_rbn1mono subsave insob geekel2d censornb + estadd_plus estadd xtregre2 clorenz usmaps2 usswm + tablemat tmap mif2dta surface kdens2 onespell diffpi + plotbeta batplot relrank invcdf jmp jmp2 smithwelch + reswage dfl p2ci heterogi shuffle8 shuffle lincheck + bicdrop1 pre optifact matsort clustsens listmiss bic + hdquantile dirlist variog svypxcon svypxcat seast + xtlsdvc avplots4 eststo vclose gausshermite simirt + cprplots glcurve sscsubmit sdecode harmby ellip + mlboolean splitvallabels circular betacoef bnormpdf + grqreg genhwcci mrtab zandrews cvxhull abar mat2txt + gmlabvpos tableplot sortlistby mgen hlist ppplot rocss + pnrcheck stexpect rbounds regaxis pgmhaz8 meta_lr + mcqscore mvcorr ipf hapblock swblock raschtest + gammasym raschtestv7 vanelteren fs estout1 estout + loevh msp detect disjoint adjacent plotmatrix nnmatch + senspec twoway_estfit mkdat soepren alphawgt center + decompose wgttest cochran examples rollreg clemao_io + heckprob2 gipf metagraph hshaz tslist collapse2 + gen_tail carryforward floattolong doubletofloat + margeff matin4-matout4 perturb coldiag2 sim_arma ndbci + labelmiss mcenter sslope reorder scat3 dummieslab rfl + xtvc metareg rc2 moments sxpose kaputil bystore mice + gzsave witch cureregr hprescott tabout gamet duncan + fview eret2 rc_spline tolerance modeldiag metaparm + profhap nsplit hlm fieller xtfisher matwrite usmaps + ellip6 ellip7 xi3 qhapipf slist nearest fedit extremes + mypkg pairplot cycleplot ciplot selectvars stcompet + full_palette catplot eclplot spellutil metadialog + psmatch2 bygap ingap mylabels metaaggr cleanlog gpfobl + mvprobit eqprhistogram slideplot majority hireg bigtab + vartyp codebook2 dmariano whotdeck crtest + collapseunique stripplot linkplot statsbyfast parplot + mitools groups wclogit xcontract xcollapse metafunnel + corrtab dmerge makematrix cibplot vreverse msplot + nicedates mkcorr nearmrg tabstatmat panelunit + panelauto safedrop gammafit gumbelfit betafit + lookforit savasas usesas etime usagelog tmpdir + confirmdir shortdir lambda survtime xtabond2 + factortest checkvar vtokenize reshape8 pcorr2 tarow + cb2html survwgt svr jonter xsampsi ci2 domdiag + xtpattern nbfit distinct maketex triprobit smileplot + tabmerge avplot3 datesum _gclsort cltest varlab decomp + overlay tab3way tab2way ivreg2 hapipf varlag vececm + isco isko ptrend dpplot cipolate tknz levels reformat + xtab mvsumm fsum stkerhaz explist qlognorm tsspell + gphepssj texteditors alphawgt decompose inccat adjksm + outdat reshape7 qsim allpossible glmcorr gcause + selmlog matsave est2tex log2do2 hansen2 gam ivhettest + newey2 intext matrixof mrdum fastcd ivendog tabcount + tabcond minap qrowname cij ciw textgph latab autolog + histbox kdbox sunflower charlist adoedit lincomest + stylerules strgen wntstmvq grnote xttrans2 inequal7 + tablepc hegy4 regdplot denormix chi2fit bstut aboutreg + _gstd01 cpcorr mktab vecar xdatelist strdate thinplate + gfields takelogs catgraph dsconcat tosql outseries + glcurve7 omninorm summdate sencode rgroup cf3 hlpdir + descsave outmat svytabs mstore savesome stbget spsurv + xtgraph effects stpm madfuller aformat todate _gwtmean + tsgraph soreg fbar metaninf blist johans vecar6 + outtable factmerg factref factext hadrilm levinlin + nharvey ipshin gpreset geneigen dotex outtex sutex + dsearch chiplot idonepsu statsmat ds3 dthaz paran + gprefscode _gsoundex bpass bking labsort intreg2 sq + powercal denton corr_svy log2html dfao xpredict mcl + listtex raschcvt diagt estsave egenmore labutil + concord avplot2 tablecol metabias coldiag fitstat + doubmass cortesti fndmtch2 cusum6 ghistcum findval + centcalc xrigls dfgls charutil icomp enlarge kpss + metatrim ivgmm0 smhsiao matvsort roblpr modlpr recode2 + showgph copydesc shapley rnd himatrix bspline stcascoh + stselpre nct ncf hist3 dolog dologx tscollap bcoeff + grfreq grlogit lrchg lrmatx lrplot lrutil forfile + printgph readlog spaces title dashln lomodrs ctabstat + expandby finddup fitmacro normtest predcalc _grmedf + ranvar matmap svmatf lincom2 csjl shownear fracdiff + genvars calibr fracirf xriml rowranks tgraph ordplot + cpr mlcoint stcmd xttest3 atkplot fsreg ciform rowsort + expgen epsigr dashgph addtxt swboot stak _grprod + sskapp xttest2 trinary ivprob-ivtobit6 torumm split q + linesize keyb expr xtlist xtcount xtcorr2 vce2 summvl + ststrata stcount simul2 regh pcamv pca mvpatt mokken + lrtest2 linest iia hordered htest elogit diag wraplist + qsort precmd modfycmd matfunc listuniq multgof hilite2 + unlabeld to_msp sample2 placevar listby listblck hh + genl for2 dropvars countby bys icslib varcase tsplot + diagtest ssizebi studysi poverty ineq dissim geivars + ineqdec0 ineqdeco ineqfac povdeco sumdist xfrac + dagumfit smfit cpyxplot mkbilogn univstat hotdeck + matodd p_vlists gennorm tab_chi sbplot5 sbplot + mfracpol keyplot taba ds5 tabplot cistat probitiv + tobitiv _gslope sphdist ginidesc inequal2 kernreg1 + kernreg2 outfix outfix2 seg outreg rfregk spautoc + onewplot pwcorrs ltable2 tabhbar hbox tabhplot cihplot + civplot sf36 pwploti partgam cf2 xtile2 ivglog + kwallis2 far5 jb6 gby strparse _gprod mfilegr desmat + areg2 margfx arimafit moreobs tsmktim durbinh bgtest + mnthplot archlm gphudak renames skewplot cnsrsig + recast2 doub2flt feldti tolower lfsum whitetst bpagan + listutil mdensity kdmany stquant byvar cflpois + workdays flower _grpos stcoxgof stcoxplt stpiece + overid overidxt swapval adotype fndmtch svvarlbl + gentrun storecmd sto lrdrop1 lrseq dmexogxt + probexog-tobexog predxcon predxcat mmerge tablab + for211 gmci grand nbinreg spikeplt ocratio biplot + coranal mca heckman2 marker markov pgamma qgamma + somersd pantest2 datmat distan missing quantil2 + distplot tpred contrast cid rglm dtobit2 ljs ewma + barplot genfreq hbar hplot fodstr catdev rmanova + ranova seq intterms lmoments regresby reglike pweibull + wbull qweibull regpred logpred adjmean adjprop spell + switchr trnbin0 mvsamp1i mvsampsi tpvar mvtest addtex + pwcorrw vlist violin eba mstdize orthog stcumh + ccweight psbayes oprobpr cndnmb3 pbeta qbeta vmatch + kr20 sbrowni canon stbtcalc stgtcalc zb_qrm catenate + lprplot nnest longplot parmest qqplot2 jb zip zinb + hetprob unique longch gwhet williams adjust barplot2 + grand2 histplot xcorplot clarify mlogpred nproc + labgraph vallist pexp qexp lms levene centroid medoid + cluster fulltab t2way5 epiconf lstack deaton colelms + confsvy median winsor bys torats venndiag chaos + muxyplot muxplot irrepro triplot tomode circstat tryem + white strip ralloc acplot stack symmetry omodel + allcross dups iia sdtest vplplot summvl labsumm + loopplot elapse istdize blogit2 sparl vallab gologit + mkstrsn poisml trpois0 cenpois sssplot hausman stcstat + forvalues + """ +) + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_C_DEFAULT, 'default_style'), + (stc.STC_C_COMMENT, 'comment_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTDOC, 'comment_style'), + (stc.STC_C_COMMENTDOCKEYWORD, 'dockey_style'), + (stc.STC_C_COMMENTDOCKEYWORDERROR, 'error_style'), + (stc.STC_C_COMMENTLINE, 'comment_style'), + (stc.STC_C_COMMENTLINEDOC, 'comment_style'), + (stc.STC_C_CHARACTER, 'char_style'), + (stc.STC_C_GLOBALCLASS, 'global_style'), + (stc.STC_C_IDENTIFIER, 'default_style'), + (stc.STC_C_NUMBER, 'number_style'), + (stc.STC_C_OPERATOR, 'operator_style'), + (stc.STC_C_PREPROCESSOR, 'pre_style'), + (stc.STC_C_REGEX, 'pre_style'), + (stc.STC_C_STRING, 'string_style'), + (stc.STC_C_STRINGEOL, 'default_style'), + (stc.STC_C_UUID, 'pre_style'), + (stc.STC_C_VERBATIM, 'number2_style'), + (stc.STC_C_WORD, 'keyword_style'), + (stc.STC_C_WORD2, 'keyword2_style') ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_PRE = ("styling.within.preprocessor", "0") +FOLD_COM = ("fold.comment", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") + +#------------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for STATA""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CPP) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [MAIN_KEYWORDS, SECONDARY_KEYWORDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_PRE, FOLD_COM] + + # TODO: this doesnt' look right... + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//', u'/*', u'*/',u'*' ] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_tcl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_tcl.py new file mode 100644 index 0000000..071a15d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_tcl.py @@ -0,0 +1,198 @@ +############################################################################### +# Name: tcl.py # +# Purpose: Define TCL/TK syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: tcl.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for tcl + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _tcl.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +from _cpp import AutoIndenter + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +TCL_KW = (0, "after append array auto_execok auto_import auto_load catch cd " + "auto_load_index auto_qualify beep bgerror binary break case file " + "clock close concat continue dde default echo else elseif eof " + "encoding error eval exec exit expr fblocked fconfigure fcopy " + "fileevent flush for foreach format gets glob global history http " + "if incr info interp join lappend lindex linsert list llength " + "load loadTk lrange lreplace lsearch lset lsort memory msgcat " + "namespace open package pid pkg::create pkg_mkIndex regsub rename " + "Platform-specific proc puts pwd re_syntax read regexp registry " + "resource return scan seek set socket source split string subst " + "switch tclLog tclMacPkgSearch tclPkgSetup tclPkgUnknown tell " + "time trace unknown unset update uplevel upvar variable vwait " + "while") + +TK_KW = (1, "bell bind bindtags bitmap button canvas checkbutton clipboard " + "colors console cursors destroy entry event focus font frame grab " + "grid image Inter-client keysyms label labelframe listbox lower " + "menu menubutton message option options pack panedwindow photo " + "radiobutton raise scale scrollbar selection send spinbox text tk " + "tk_chooseColor tk_chooseDirectory tk_dialog tk_focusNext tkvars " + "tk_messageBox tk_optionMenu tk_popup tk_setPalette tkerror " + "tkwait toplevel winfo wish wm place tk_getOpenFile ") + +ITCL_KW = (2, "@scope body class code common component configbody constructor " + "define destructor hull import inherit itcl itk itk_component " + "itk_initialize itk_interior itk_option iwidgets keep method " + "private protected public typemethod typevariable") + +TK_COMMANDS = (3, "tk_bisque tk_chooseColor tk_dialog tk_focusFollowsMouse " + "tk_focusNext tk_focusPrev tk_getOpenFile tk_getSaveFile " + "tk_messageBox tk_optionMenu tk_popup tk_setPalette " + "tk_textCut tk_textPaste tkButtonAutoInvoke tkButtonDown " + "tkButtonEnter tkButtonInvoke tkButtonLeave tkButtonUp " + "tkCancelRepeat tkCheckRadioDown tkCheckRadioEnter " + "tkCheckRadioInvoke tkColorDialog tkColorDialog_BuildDialog " + "tkColorDialog_CancelCmd tkColorDialog_Config " + "tkColorDialog_CreateSelector tkColorDialog_DrawColorScale " + "tkColorDialog_EnterColorBar tkColorDialog_HandleRGBEntry " + "tkColorDialog_HandleSelEntry tkColorDialog_InitValues " + "tkColorDialog_LeaveColorBar tkColorDialog_MoveSelector " + "tkColorDialog_OkCmd tk_textCopy tkColorDialog_StartMove " + "tkColorDialog_RedrawColorBars tkColorDialog_ResizeColorBars " + "tkColorDialog_RedrawFinalColor tkColorDialog_ReleaseMouse " + "tkColorDialog_RgbToX tkColorDialog_SetRGBValue " + "tkColorDialog_XToRgb tkConsoleAbout tkConsoleBind " + "tkConsoleExit tkConsoleHistory tkConsoleInit tkFocusOK " + "tkConsoleInsert tkConsoleInvoke tkConsoleOutput " + "tkConsolePrompt tkConsoleSource tkDarken tkEntryAutoScan " + "tkEntryBackspace tkEntryButton1 tkEntryClosestGap " + "tkEntryGetSelection tkEntryInsert tkEntryKeySelect " + "tkEntryMouseSelect tkEntryNextWord tkEntryPaste tkFirstMenu " + "tkEntryPreviousWord tkEntrySeeInsert tkEntrySetCursor " + "tkEntryTranspose tkEventMotifBindings tkFDGetFileTypes " + "tkFocusGroup_BindIn tkFocusGroup_BindOut tkFocusGroup_Out" + "tkFocusGroup_Create tkFocusGroup_Destroy tkFocusGroup_In " + "tkGenerateMenuSelect tkIconList tkIconList_Add " + "tkIconList_Arrange tkIconList_AutoScan tkIconList_Btn1 " + "tkIconList_Config tkIconList_Create tkIconList_CtrlBtn1 " + "tkIconList_Curselection tkIconList_DeleteAll " + "tkIconList_Double1 tkIconList_DrawSelection tkIconList_See " + "tkIconList_FocusIn tkIconList_FocusOut tkIconList_Get " + "tkIconList_Goto tkIconList_Index tkIconList_Invoke " + "tkIconList_KeyPress tkIconList_Leave1 tkIconList_LeftRight " + "tkIconList_Motion1 tkIconList_Reset tkIconList_ReturnKey " + "tkIconList_Select tkIconList_Selection tkIconList_ShiftBtn1 " + "tkIconList_UpDown tkListbox tkListboxKeyAccel_Key " + "tkListboxAutoScan tkListboxBeginExtend tkListboxBeginSelect " + "tkListboxBeginToggle tkListboxCancel tkListboxDataExtend " + "tkListboxExtendUpDown tkListboxKeyAccel_Goto tkMbButtonUp " + "tkListboxKeyAccel_Reset tkListboxKeyAccel_Set " + "tkListboxKeyAccel_Unset tkListboxMotion tkListboxSelectAll " + "tkMbEnter tkMbLeave tkMbMotion tkMbPost tkMenuButtonDown " + "tkMenuDownArrow tkMenuDup tkMenuEscape tkMenuFind " + "tkMenuFindName tkMenuFirstEntry tkMenuInvoke tkMenuLeave " + "tkMenuLeftArrow tkMenuMotion tkMenuNextEntry tkMenuNextMenu " + "tkMenuRightArrow tkMenuUnpost tkMenuUpArrow tkMessageBox " + "tkMotifFDialog tkMotifFDialog_ActivateDList tkScaleDrag " + "tkMotifFDialog_ActivateFEnt tkMotifFDialog_ActivateFList " + "tkMotifFDialog_ActivateSEnt tkMotifFDialog_BrowseDList " + "tkMotifFDialog_BrowseFList tkMotifFDialog_BuildUI " + "tkMotifFDialog_CancelCmd tkMotifFDialog_Config " + "tkMotifFDialog_Create tkMotifFDialog_FileTypes " + "tkMotifFDialog_FilterCmd tkMotifFDialog_InterpFilter " + "tkMotifFDialog_LoadFiles tkMotifFDialog_MakeSList " + "tkMotifFDialog_OkCmd tkMotifFDialog_SetFilter " + "tkMotifFDialog_SetListMode tkMotifFDialog_Update " + "tkPostOverPoint tkRecolorTree tkRestoreOldGrab " + "tkSaveGrabInfo tkScaleActivate tkScaleButton2Down " + "tkScaleButtonDown tkScaleControlPress tkScaleEndDrag " + "tkScaleIncrement tkScreenChanged tkScrollButton2Down " + "tkScrollButtonDown tkScrollButtonDrag tkScrollButtonUp " + "tkScrollByPages tkScrollByUnits tkScrollDrag tkTextNextPos " + "tkScrollEndDrag tkScrollSelect tkScrollStartDrag " + "tkScrollTopBottom tkScrollToPos tkTabToWindow tkTearOffMenu " + "tkTextAutoScan tkTextButton1 tkTextClosestGap tkTextInsert " + "tkTextKeyExtend tkTextKeySelect tkTextNextPara " + "tkTextNextWord tkTextPaste tkTextPrevPara tkTextPrevPos " + "tkTextPrevWord tkTextResetAnchor tkTextScrollPages " + "tkTextSelectTo tkTextSetCursor tkTextTranspose " + "tkTextUpDownLine tkTraverseToMenu tkTraverseWithinMenu " + "tkListboxUpDown ") + +EXPAND = (4, "") + +USER1_KW = (5, "") + +USER2_KW = (6, "") + +USER3_KW = (7, "") + +USER4_KW = (8, "") + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_TCL_BLOCK_COMMENT, 'comment_style'), + (stc.STC_TCL_COMMENT, 'comment_style'), + (stc.STC_TCL_COMMENTLINE, 'comment_style'), + (stc.STC_TCL_COMMENT_BOX, 'comment_style'), + (stc.STC_TCL_DEFAULT, 'default_style'), + (stc.STC_TCL_EXPAND, 'default_style'), # STYLE NEEDED + (stc.STC_TCL_IDENTIFIER, 'default_style'), + (stc.STC_TCL_IN_QUOTE, 'string_style'), + (stc.STC_TCL_MODIFIER, 'default_style'), # STYLE NEEDED + (stc.STC_TCL_NUMBER, 'number_style'), + (stc.STC_TCL_OPERATOR, 'operator_style'), + (stc.STC_TCL_SUBSTITUTION, 'scalar_style'), + (stc.STC_TCL_SUB_BRACE, 'string_style'), # STYLE NEEDED + (stc.STC_TCL_WORD, 'keyword_style'), # tcl_kw + (stc.STC_TCL_WORD2, 'keyword2_style'), # tk_kw + (stc.STC_TCL_WORD3, 'keyword3_style'), # itcl_kw + (stc.STC_TCL_WORD4, 'keyword4_style'), # tkCommands + (stc.STC_TCL_WORD5, 'default_style'), + (stc.STC_TCL_WORD6, 'default_style'), + (stc.STC_TCL_WORD7, 'default_style'), + (stc.STC_TCL_WORD8, 'default_style'), + (stc.STC_TCL_WORD_IN_QUOTE, 'default_style')] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_COMMENT = ("fold.comment", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for TCL/Tk""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_TCL) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [TCL_KW, TK_KW, ITCL_KW, TK_COMMANDS] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD, FOLD_COMMENT] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vbscript.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vbscript.py new file mode 100644 index 0000000..a7e17bd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vbscript.py @@ -0,0 +1,95 @@ +############################################################################### +# Name: vbscript.py # +# Purpose: Define VBScript syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: vbscript.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for VBScript. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _vbscript.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +VBS_KW = ("addressof alias and as attribute base begin binary boolean byref " + "byte byval call case cdbl cint clng compare const csng cstr " + "currency date decimal declare defbool defbyte defcur defdate defdbl " + "defdec defint deflng defobj defsng defstr defvar dim do double each " + "else elseif empty end enum eqv erase error event exit explicit " + "false for friend function get global gosub goto if imp implements " + "in input integer is len let lib like load lock long loop lset me " + "mid midb mod new next not nothing null object on option optional " + "or paramarray preserve print private property public raiseevent " + "randomize redim rem resume return rset seek select set single " + "static step stop string sub text then time to true type typeof " + "unload until variant wend while with withevents xor") + +# Syntax specifications +SYNTAX_ITEMS = [ (stc.STC_B_ASM, 'asm_style'), + (stc.STC_B_BINNUMBER, 'default_style'), # STYLE NEEDED + (stc.STC_B_COMMENT, 'comment_style'), + (stc.STC_B_CONSTANT, 'const_style'), + (stc.STC_B_DATE, 'default_style'), # STYLE NEEDED + (stc.STC_B_DEFAULT, 'default_style'), + (stc.STC_B_ERROR, 'error_style'), + (stc.STC_B_HEXNUMBER, 'number_style'), + (stc.STC_B_IDENTIFIER, 'default_style'), + (stc.STC_B_KEYWORD, 'keyword_style'), + (stc.STC_B_KEYWORD2, 'class_style'), # STYLE NEEDED + (stc.STC_B_KEYWORD3, 'funct_style'), # STYLE NEEDED + (stc.STC_B_KEYWORD4, 'scalar_style'), # STYLE NEEDED + (stc.STC_B_LABEL, 'directive_style'), # STYLE NEEDED + (stc.STC_B_NUMBER, 'number_style'), + (stc.STC_B_OPERATOR, 'operator_style'), + (stc.STC_B_PREPROCESSOR, 'pre_style'), + (stc.STC_B_STRING, 'string_style'), + (stc.STC_B_STRINGEOL, 'stringeol_style') + ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for VbScript""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_VBSCRIPT) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [(0, VBS_KW),] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'\''] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_verilog.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_verilog.py new file mode 100644 index 0000000..be8d62d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_verilog.py @@ -0,0 +1,375 @@ +############################################################################### +# Name: verilog.py # +# Purpose: Configuration module for Verilog HDL language # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: verilog.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Verilog Hardware Description Language + and System Verilog programming languages. Much help in creating this + module from Tim Corcoran. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _verilog.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# +#TODO: What to do with preprocessors? +#TODO: What to do with standard methods? + +#---- Keyword Definitions ----# + +#============================================================================== +# IEEE 1364-1995 Verilog +#============================================================================== +# IEEE 1364-1995 Verilog Preprocessors +V_1364_1995_PREPROCESSORS = ( + # 1364-1995 Section 14 + "`celldefine `default_nettype `define `else `endcelldefine `endif `ifdef " + "`include `nounconnected_drive `resetall `timescale `unconnected_drive " + "`undef " + # 1364-1995 Annex G + "`default_decay_time `default_trireg_strength `delay_mode_distributed " + "`delay_mode_path `delay_mode_unit `delay_mode_zero " + #1364-1995 Verilog Preprocessor Commercial Extensions + "`accelerate `autoexpand_vectornets `disable_portfaults `enable_portfaults " + "`endprotect `endprotected `expand_vectornets `noaccelerate " + "`noexpand_vectornets `noremove_gatenames `noremove_netnames " + "`nosuppress_faults `portcoerce `protect `protected " + "`remove_gatenames `remove_netnames `suppress_faults " +) + +# IEEE 1364-1995 Verilog Keywords (NOT USED: attribute endattribute signed unsigned) +V_1364_1995_KEYWORDS = ( + "always assign begin case casex casez deassign default defparam disable " + "edge else end endcase endfunction endmodule endprimitive endspecify " + "endtable endtask for force forever fork function if ifnone initial " + "inout input join macromodule module negedge output parameter posedge " + "primitive release repeat scalared specify specparam strength table task " + "vectored wait while" +) + +# IEEE 1364-1995 Verilog Types (NOT USED: xbuf) +V_1364_1995_TYPES = ( + "and buf bufif0 bufif1 cmos event highz0 highz1 integer large medium nand " + "nmos nor not notif0 notif1 or pmos pull0 pull1 pulldown pullup rcmos real " + "realtime reg rnmos rpmos rtran rtranif0 rtranif1 small strong0 strong1 " + "supply0 supply1 time tran tranif0 tranif1 tri tri0 tri1 triand trior " + "trireg wand weak0 weak1 wire wor xnor xor" +) + +# IEEE 1364-1995 Verilog System Tasks and Functions +V_1364_1995_TASKS = ( + # 1364-1995 Section 14 + "$async$and$array $async$and$plane $async$nand$array $async$nand$plane " + "$async$nor$array $async$nor$plane $async$or$array $async$or$plane " + "$bitstoreal $display $displayb $displayh $displayo $dist_chi_square " + "$dist_erlang $dist_exponential $dist_normal $dist_poisson $dist_t " + "$dist_uniform $dumpall $dumpfile $dumpflush $dumplimit $dumpoff $dumpon " + "$dumpvars $fclose $fdisplay $fdisplayb $fdisplayh $fdisplayo $finish " + "$fmonitor $fmonitorb $fmonitorh $fmonitoro $fopen $fstrobe $fstrobeb " + "$fstrobeh $fstrobeo $fwrite $fwriteb $fwriteh $fwriteo $hold $itor " + "$monitor $monitorb $monitorh $monitoro $monitoroff $monitoron $nochange " + "$period $printtimescale $q_add $q_exam $q_full $q_initialize $q_remove " + "$random $readmemb $readmemh $realtime $realtobits $recovery $rtoi $setup " + "$setuphold $skew $stime $stop $strobe $strobeb $strobeh $strobeo " + "$sync$and$array $sync$and$plane $sync$nand$array $sync$nand$plane " + "$sync$nor$array $sync$nor$plane $sync$or$array $sync$or$plane $time " + "$timeformat $width $write $writeb $writeh $writeo " + # 1364-1995 Annex F + "$countdrivers $getpattern $incsave $input $key $list $log $nokey $nolog " + "$reset $reset_count $reset_value $restart $save $scale $scope $showscopes " + "$showvars $sreadmemb $sreadmemh" +) + +#============================================================================== +# IEEE 1364-2001 Verilog +#============================================================================== +# IEEE 1364-2001 Verilog Preprocessors +V_1364_2001_PREPROCESSORS = ( + "`elsif `ifndef `line" +) + +# IEEE 1364-2001 Verilog Keywords +V_1364_2001_KEYWORDS = ( + "automatic cell config design endconfig endgenerate generate genvar incdir " + "include instance liblist library localparam noshowcancelled " + "pulsestyle_ondetect pulsestyle_onevent showcancelled signed unsigned use" +) + +# IEEE 1364-2001 Verilog Types +V_1364_2001_TYPES = ( + "" +) + +# IEEE 1364-2001 Verilog System Tasks and Functions +V_1364_2001_TASKS = ( + "$dumpports $dumpportsall $dumpportsflush $dumpportslimit $dumpportsoff " + "$dumpportson $ferror $fflush $fgetc $fgets $fread $fscanf $fseek $ftell " + "$rewind $sdf_annotate $sformat $signed $sscanf $swrite $swriteb $swriteh " + "$swriteo $test$plusargs $ungetc $unsigned $value$plusargs" +) + +#============================================================================== +# IEEE 1364-2005 Verilog +#============================================================================== +# IEEE 1364-2005 Verilog Preprocessors +V_1364_2005_PREPROCESSORS = ( + "`pragma" +) + +# IEEE 1364-2005 Verilog Keywords (NONE) +V_1364_2005_KEYWORDS = ( + "" +) + +# IEEE 1364-2005 Verilog Types +V_1364_2005_TYPES = ( + "uwire" +) + +# IEEE 1364-2005 Verilog System Tasks and Functions (NONE) +V_1364_2005_TASKS = ( + "" +) + +#VERILOG_PREPROCESSORS = " ".join([V_1364_1995_PREPROCESSORS, V_1364_2001_PREPROCESSORS, V_1364_2005_PREPROCESSORS]) +#VERILOG_KEYWORDS = " ".join([V_1364_1995_KEYWORDS, V_1364_2001_KEYWORDS, V_1364_2005_KEYWORDS ]) +#VERILOG_TYPES = " ".join([V_1364_1995_TYPES, V_1364_2001_TYPES, V_1364_2005_TYPES ]) +#VERILOG_TASKS = " ".join([V_1364_1995_TASKS, V_1364_2001_TASKS, V_1364_2005_TASKS ]) + +# ---\/----- Overkill maybe? -----\/--- +VERILOG_PREPROCESSORS = " ".join( [V_1364_1995_PREPROCESSORS, + V_1364_2001_PREPROCESSORS, + V_1364_2005_PREPROCESSORS] ).split() +VERILOG_PREPROCESSORS.sort() +VERILOG_PREPROCESSORS = " ".join( VERILOG_PREPROCESSORS ) + +VERILOG_KEYWORDS = " ".join( [V_1364_1995_KEYWORDS, + V_1364_2001_KEYWORDS, + V_1364_2005_KEYWORDS] ).split() +VERILOG_KEYWORDS.sort() +VERILOG_KEYWORDS = " ".join( VERILOG_KEYWORDS ) + +VERILOG_TYPES = " ".join( [V_1364_1995_TYPES, + V_1364_2001_TYPES, + V_1364_2005_TYPES] ).split() +VERILOG_TYPES.sort() +VERILOG_TYPES = " ".join( VERILOG_TYPES ) + +VERILOG_TASKS = " ".join( [V_1364_1995_TASKS, + V_1364_2001_TASKS, + V_1364_2005_TASKS] ).split() +VERILOG_TASKS.sort() +VERILOG_TASKS = " ".join( VERILOG_TASKS ) +# ---/\----- Overkill maybe? -----/\--- + +#---- System Verilog Extensions ----# + +#============================================================================== +# IEEE 1800-2005 SystemVerilog +#============================================================================== +# IEEE 1800-2005 SystemVerilog Preprocessors +SV_1800_2005_PREPROCESSORS = ( + # One of "1800-2009" "1800-2005" "1364-2005" "1364-2001" "1364-2001-noconfig" "1364-1995" + "`begin_keywords `end_keywords" +) + +# IEEE 1800-2005 SystemVerilog Keywords +SV_1800_2005_KEYWORDS = ( + "alias always_comb always_ff always_latch assert assume before bind " + "bins binsof bit break constraint covergroup coverpoint class clocking const" + "context continue cover cross dist do endclass endclocking endgroup endinterface " + "endpackage endprogram endproperty endsequence expect export extends extern " + "final first_match foreach forkjoin iff ignore_bins illegal_bins import " + "inside interface intersect join_any join_none modport new null package " + "priority process program property pure randcase randsequence ref return " + "sequence solve super this throughout timeprecision timeunit type unique " + "wait_order wildcard with within " + "local packed protected static struct tagged typedef union virtual" +) + +# IEEE 1800-2005 SystemVerilog Types +SV_1800_2005_TYPES = ( + "byte chandle enum int logic longint rand randc shortint shortreal std " + "string var void" + # Moved to keywords +# "local packed protected static struct tagged typedef union virtual" +) + +# IEEE 1800-2005 SystemVerilog System Tasks and Functions +SV_1800_2005_TASKS = ( + "$assertkill $assertoff $asserton $bits $countones $coverage_control " + "$coverage_get $coverage_get_max $coverage_merge $coverage_save " + "$dimensions $error $exit $fatal $fell $high $increment $info $isunbounded " + "$isunknown $left $low $onehot $onehot0 $psprintf $right $rose $sampled " + "$size $stable $typename $unpacked_dimensions $warning" +) + +# IEEE 1800-2005 SystemVerilog Standard Methods +SV_1800_2005_METHODS = ( + "and atobin atohex atoi atooct atoreal await back bintoa clear compare data " + "delete empty eq erase erase_range exists find find_first find_first_index " + "find_index find_last find_last_index finish first front get getc hextoa " + "icompare index insert insert_range itoa kill last len max min name neq new " + "next num octtoa or peek pop_back pop_front prev product purge push_back " + "push_front put putc rand_mode realtoa resume reverse rsort self set shuffle " + "size sort start status stop substr sum suspend swap tolower toupper try_get " + "try_peek try_put unique unique_index xor" +) + +#============================================================================== +# IEEE 1800-2009 SystemVerilog +#============================================================================== +SV_1800_2009_PREPROCESSORS = ( + "`__FILE__ `__LINE__ `undefineall" +) + +# IEEE 1800-2009 SystemVerilog Keywords +SV_1800_2009_KEYWORDS = ( + "accept_on checker endchecker eventually global implies let matches nexttime " + "reject_on restrict s_always s_eventually s_nexttime s_until s_until_with " + "sync_accept_on sync_reject_on unique0 until until_with untyped weak " + # 34.4 Protect pragma directives + "protect " + "author author_info begin_protected comment data_block data_decrypt_key " + "data_keyname data_keyowner data_method data_public_key decrypt_license " + "digest_block digest_decrypt_key digest_key_method digest_keyname " + "digest_keyowner digest_method digest_public_key encoding encrypt_agent " + "encrypt_agent_info encrypt_license end_protected key_block key_keyname " + "key_keyowner key_method key_public_key reset runtime_license viewport" +) + +# IEEE 1800-2009 SystemVerilog Types +SV_1800_2009_TYPES = ( + # TODO: Are there new types? + "" +) + +# IEEE 1800-2009 SystemVerilog System Tasks and Functions +SV_1800_2009_TASKS = ( + # Section 20.1 General + "$acos $acosh $asin $asinh $assertfailoff $assertfailon $assertnonvacuouson " + "$assertpassoff $assertpasson $assertvacuousoff $atan $atan2 $atanh " + "$bitstoshortreal $cast $ceil $changed $changed_gclk $changing_gclk $clog2 " + "$cos $cosh $exp $falling_gclk $fell_gclk $floor $future_gclk $get_coverage " + "$hypot $ln $load_coverage_db $log10 $past $past_gclk $pow $rising_gclk " + "$rose_gclk $set_coverage_db_name $sformatf $shortrealtobits $sin $sinh " + "$sqrt $stable_gclk $steady_gclk $system $tan $tanh" +) + +# IEEE 1800-2009 SystemVerilog Standard Methods +SV_1800_2009_METHODS = ( + # TODO: Add new methods + "" +) + +#SYSTEMVERILOG_PREPROCESSORS = " ".join( [VERILOG_PREPROCESSORS, SV_1800_2005_PREPROCESSORS, SV_1800_2009_PREPROCESSORS] ) +#SYSTEMVERILOG_KEYWORDS = " ".join( [VERILOG_KEYWORDS, SV_1800_2005_KEYWORDS, SV_1800_2009_KEYWORDS ] ) +#SYSTEMVERILOG_TYPES = " ".join( [VERILOG_TYPES, SV_1800_2005_TYPES, SV_1800_2009_TYPES ] ) +#SYSTEMVERILOG_TASKS = " ".join( [VERILOG_TASKS, SV_1800_2005_TASKS, SV_1800_2009_TASKS ] ) + +# ---\/----- Overkill maybe? -----\/--- +SYSTEMVERILOG_PREPROCESSORS = " ".join( [VERILOG_PREPROCESSORS, + SV_1800_2005_PREPROCESSORS, + SV_1800_2009_PREPROCESSORS] ).split() +SYSTEMVERILOG_PREPROCESSORS.sort() +SYSTEMVERILOG_PREPROCESSORS = " ".join( SYSTEMVERILOG_PREPROCESSORS ) + +SYSTEMVERILOG_KEYWORDS = " ".join( [VERILOG_KEYWORDS, + SV_1800_2005_KEYWORDS, + SV_1800_2009_KEYWORDS] ).split() +SYSTEMVERILOG_KEYWORDS.sort() +SYSTEMVERILOG_KEYWORDS = " ".join( SYSTEMVERILOG_KEYWORDS ) + +SYSTEMVERILOG_TYPES = " ".join( [VERILOG_TYPES, + SV_1800_2005_TYPES, + SV_1800_2009_TYPES] ).split() +SYSTEMVERILOG_TYPES.sort() +SYSTEMVERILOG_TYPES = " ".join( SYSTEMVERILOG_TYPES ) + +SYSTEMVERILOG_TASKS = " ".join( [VERILOG_TASKS, + SV_1800_2005_TASKS, + SV_1800_2009_TASKS] ).split() +SYSTEMVERILOG_TASKS.sort() +SYSTEMVERILOG_TASKS = " ".join( SYSTEMVERILOG_TASKS ) +# ---/\----- Overkill maybe? -----/\--- + +#---- End System Verilog Extensions ----# + +USER_KW = ( 3, "" ) + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ + (stc.STC_V_COMMENT, 'comment_style' ), + (stc.STC_V_COMMENTLINE, 'comment_style' ), + (stc.STC_V_COMMENTLINEBANG, 'comment_style' ), + (stc.STC_V_DEFAULT, 'default_style' ), + (stc.STC_V_IDENTIFIER, 'default_style' ), + (stc.STC_V_NUMBER, 'number_style' ), + (stc.STC_V_OPERATOR, 'operator_style' ), + (stc.STC_V_PREPROCESSOR, 'pre_style' ), + (stc.STC_V_STRING, 'string_style' ), + (stc.STC_V_STRINGEOL, 'stringeol_style'), + (stc.STC_V_USER, 'default_style' ), + (stc.STC_V_WORD, 'keyword_style' ), + (stc.STC_V_WORD2, 'keyword2_style' ), + (stc.STC_V_WORD3, 'scalar_style' ) +] + +#---- Extra Properties ----# +FOLD = ("fold", "1") +FOLD_CMT = ("fold.comment", "1") +FOLD_PRE = ("fold.preprocessor", "1") +FOLD_COMP = ("fold.compact", "1") +FOLD_ELSE = ("fold.at.else", "0") +FOLD_MOD = ("fold.verilog.flags", "0") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for Verilog and SysVerilog""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_VERILOG) + + def GetKeywords(self): + """Returns Specified Keywords List """ + if self.LangId == synglob.ID_LANG_VERILOG: + return [(0, VERILOG_KEYWORDS), + (1, VERILOG_TYPES), + (2, VERILOG_TASKS)] + else: + return [(0, SYSTEMVERILOG_KEYWORDS), + (1, SYSTEMVERILOG_TYPES), + (2, SYSTEMVERILOG_TASKS)] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'//'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vhdl.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vhdl.py new file mode 100644 index 0000000..9870cdd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_vhdl.py @@ -0,0 +1,130 @@ +############################################################################### +# Name: vhdl.py # +# Purpose: Define VHDL syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: vhdl.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for VHDL. Very High Scale Integrated + Circuit Hardware Description Language +@todo: Maybe add highlighting for values S0S, S1S, ect.. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _vhdl.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# VHDL Keywords +VHDL_KW = (0, "access after alias all assert architecture array attribute for " + "begin block body buffer bus case component configuration inout " + "constant if else disconnect downto elsif end entity exit file " + "function generate generic group guarded impure in inertial is " + "label library linkage literal loop map new next null of on open " + "others out package port postponed procedure process pure range " + "record register reject report return select severity signal use " + "shared subtype then to transport type unaffected units until " + "variable wait when while with note warning error failure true " + "false") + +# VHDL Operators +VHDL_OP = (1, "and nand or nor xor xnor rol ror sla sll sra srl mod rem abs " + "not ") + +# VHDL Attributes +VHDL_AT = (2, "'high 'left 'length 'low 'range 'reverse_range 'right 'foreign " + "'ascending 'behavior 'structure 'simple_name 'instance_name " + "'path_name 'active 'delayed 'event 'last_active 'last_event " + "'last_value 'quiet 'stable 'transaction 'driving 'driving_value " + "'base 'high 'left 'leftof 'low 'pos 'pred 'rightof 'succ 'val " + "'image 'value") + +# Standard Functions +VHDL_STDF = (3, "now readline read writeline write endfile to_stdulogicvector " + "to_bitvector to_stdulogic to_stdlogicvector resolved to_bit " + "to_x01 to_x01z to_UX01 rising_edge falling_edge is_x " + "shift_right rotate_left rotate_right resize to_integer " + "to_unsigned to_signed std_match to_01 shift_left ") + +# Standard Packages +VHDL_STDP = (4, "std ieee work standard textio std_logic_1164 std_logic_arith " + "std_logic_misc std_logic_signed std_logic_textio " + "numeric_bit numeric_std math_complex math_real " + "vital_timing std_logic_unsigned vital_primitives ") + +# Standard Types +VHDL_STDT = (5, "bit bit_vector character boolean integer real time string " + "severity_level positive natural signed unsigned line text " + "std_logic std_logic_vector std_ulogic std_ulogic_vector " + "qsim_state qsim_state_vector qsim_12state qsim_12state_vector " + "qsim_strength mux_bit mux_vector reg_bit reg_vector wor_bit " + "wor_vector") + +# User Words +VHDL_UKW = (6, "") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_VHDL_DEFAULT, 'default_style'), + (stc.STC_VHDL_ATTRIBUTE, 'default_style'), # NEEDS STYLE + (stc.STC_VHDL_COMMENT, 'comment_style'), + (stc.STC_VHDL_COMMENTLINEBANG, 'comment_style'), + (stc.STC_VHDL_IDENTIFIER, 'default_style'), + (stc.STC_VHDL_KEYWORD, 'keyword_style'), + (stc.STC_VHDL_NUMBER, 'default_style'), + (stc.STC_VHDL_OPERATOR, 'operator_style'), + (stc.STC_VHDL_STDFUNCTION, 'funct_style'), + (stc.STC_VHDL_STDOPERATOR, 'operator_style'), + (stc.STC_VHDL_STDPACKAGE, 'pre_style'), + (stc.STC_VHDL_STDTYPE, 'class_style'), + (stc.STC_VHDL_STRING, 'string_style'), + (stc.STC_VHDL_STRINGEOL, 'stringeol_style'), + (stc.STC_VHDL_USERWORD, 'default_style') ] + +#---- Extra Property Specifications ----# +FOLD = ("fold", "1") +FLD_COMMENT = ("fold.comment", "1") +FLD_COMMPACT = ("fold.compact", "1") +FLD_ATELSE = ("fold.at.else", "1") +FLD_ATBEGIN = ("fold.at.Begin", "1") +FLD_ATPAREN = ("fold.at.Parenthese", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for VHDL""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_VHDL) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [VHDL_KW, VHDL_AT, VHDL_STDF, VHDL_STDP, VHDL_STDT] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'--'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_visualbasic.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_visualbasic.py new file mode 100644 index 0000000..4dba95a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_visualbasic.py @@ -0,0 +1,205 @@ +############################################################################### +# Name: visualbasic.py # +# Purpose: Define Visual Basic syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: visualbasic.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for Visual Basic. +@todo: Incomplete requires color/kw tuning + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _visualbasic.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Visual Basic Keywords (Statements) +VB_KW = (0, "AppActivate Base Beep Begin Call Case ChDir ChDrive Const Declare " + "DefByte DefCur DefDate DefDbl DefDec DefInt DefLng DefObj DefSng " + "DefStr Deftype DefVar DeleteSetting Dim Do Else End Enum Erase " + "Event Exit Explicit FileCopy For ForEach Function Get GoSub GoTo " + "If Implements Kill Let LineInput Lock LSet MkDir Name Next " + "On Option Private Property Public Put RaiseEvent Randomize ReDim " + "Rem Reset Resume Return RmDir RSet SavePicture SaveSetting With " + "SendKeys SetAttr Static Sub Then Type Unlock Wend While Width " + "Write Height DefBool OnError ") + +# Visual Basic User Keywords 1 (Functions) +VB_UKW1 = (1, "Abs Array Asc AscB AscW Atn Avg CBool CByte CCur CDate CDbl " + "Choose Chr ChrB ChrW CInt CLng Command Cos Count CreateObject " + "CSng CStr CurDir CVar CVDate CVErr Date DateAdd DateDiff Cdec " + "DatePart DateSerial DateValue Day DDB Dir DoEvents Environ EOF " + "Error Exp FileAttr FileDateTime FileLen Fix Format FreeFile FV " + "GetAllStrings GetAttr GetAutoServerSettings GetObject NPV " + "Hex Hour IIf IMEStatus Input InputB InputBox InStr InstB Int " + "IPmt IsArray IsDate IsEmpty IsError IsMissing IsNull IsNumeric " + "IsObject LBound LCase Left LeftB Len LenB LoadPicture Loc LOF " + "Log LTrim Max Mid MidB Min Minute MIRR Month MsgBox Now NPer " + "Oct Partition Pmt PPmt PV QBColor Rate RGB Right RightB Rnd " + "RTrim Second Seek Sgn Shell Sin SLN Space Spc Sqr StDev StDevP " + "Str StrComp StrConv String Switch Sum SYD Tab Tan Time Timer " + "TimeSerial TimeValue Trim TypeName UBound UCase Val Var VarP " + "VarType Weekday Year GetSetting ") + +# Visual Basic User Keywords 2 (Methods) +VB_UKW2 = (2, "Accept Activate Add AddCustom AddFile AddFromFile AddItem " + "AddFromTemplate AddNew AddToAddInToolbar AddToolboxProgID " + "Append AppendChunk Arrange Assert AsyncRead BatchUpdate " + "BeginTrans Bind Cancel CancelAsyncRead CancelBatch CancelUpdate " + "CanPropertyChange CaptureImage CellText CellValue Circle Clear " + "ClearFields ClearSel ClearSelCols Clone Close Cls ColContaining " + "ColumnSize CommitTrans CompactDatabase Compose Connect Copy " + "CopyQueryDef CreateDatabase CreateDragImage CreateEmbed " + "CreateField CreateGroup CreateIndex CreateLink Customize" + "CreatePreparedStatement CreatePropery CreateQueryCreateQueryDef " + "CreateRelation CreateTableDef CreateUser CreateWorkspace " + "Delete DeleteColumnLabels DeleteColumns DeleteRowLabels Open " + "DeleteRows DoVerb Drag Draw Edit EditCopy EditPaste EndDoc " + "EnsureVisible EstablishConnection Execute ExtractIcon Fetch " + "FetchVerbs Files FillCache Find FindFirst FindItem FindLast " + "FindNext GoForward KillDoc LoadFile MakeCompileFile MoveNext " + "FindPrevious Forward GetBookmark GetChunk GetClipString GetData " + "GetFirstVisible GetFormat GetHeader GetLineFromChar GetNumTicks " + "GetRows GetSelectedPart GetText GetVisibleCount GoBack OLEDrag " + "Hide HitTest HoldFields Idle InitializeLabels InsertRows Item " + "InsertColumnLabels InsertColumns InsertObjDlg InsertRowLabels " + "Layout Line LinkExecute LinkPoke LinkRequest LinkSend Listen " + "LoadResData LoadResPicture LoadResString LogEvent OpenResultset " + "MakeReplica MoreResults Move MoveData MoveFirst MoveLast Point " + "MovePrevious NavigateTo NewPage NewPassword NextRecordset Quit " + "OnAddinsUpdate OnConnection OnDisconnection OnStartupComplete " + "OpenConnection OpenDatabase OpenQueryDef OpenRecordset Reload " + "OpenURL Overlay PaintPicture Paste PastSpecialDlg PeekData Play " + "PopulatePartial PopupMenu Print PrintForm PropertyChanged PSet " + "Raise RandomDataFill RandomFillColumns RandomFillRows Remove " + "rdoCreateEnvironment rdoRegisterDataSource ReadFromFile " + "Rebind ReFill Refresh RefreshLink RegisterDatabase ReadProperty " + "RemoveAddInFromToolbar RemoveItem Render RepairDatabase Reply " + "ReplyAll Requery ResetCustom ResetCustomLabel ResolveName " + "RestoreToolbar Resync Rollback RollbackTrans RowBookmark " + "RowContaining RowTop Save SaveAs SaveFile SaveToFile SelectAll " + "SaveToolbar SaveToOle1File Scale ScaleX ScaleY Scroll Select " + "SelectPart SelPrint Send SendData Set SetAutoServerSettings " + "SetData SetFocus SetOption SetSize SetText SetViewport Show " + "ShowColor ShowFont ShowHelp ShowOpen ShowPrinter ShowSave " + "ShowWhatsThis SignOff SignOn Size Span SplitContaining " + "StartLabelEdit StartLogging Stop Synchronize TextHeight " + "TextWidth ToDefaults TwipsToChartPart TypeByChartType " + "Update UpdateControls UpdateRecord UpdateRow Upto WhatsThisMode " + "WriteProperty ZOrder") + +# Visual Basic User Keywords 3 (Events) +VB_UKW3 = (3, "AccessKeyPress AfterAddFile AfterChangeFileName AfterCloseFile " + "AfterColEdit AfterColUpdate AfterDelete AfterInsert " + "AfterLabelEdit AfterRemoveFile AfterUpdate AfterWriteFile " + "AmbienChanged ApplyChanges Associate AsyncReadComplete " + "AxisActivated AxisLabelActivated AxisLabelSelected Collapse " + "AxisLabelUpdated AxisSelected AxisTitleActivated BeforeColEdit " + "AxisTitleSelected AxisTitleUpdated AxisUpdated BeforeClick " + "BeforeColUpdate BeforeConnect BeforeDelete BeforeInsert " + "BeforeLabelEdit BeforeLoadFile BeforeUpdate ButtonClick " + "ButtonCompleted ButtonGotFocus ButtonLostFocus Change ColResize " + "ChartActivated ChartSelected ChartUpdated Click ColEdit " + "ColumnClick Compare ConfigChageCancelled ConfigChanged " + "ConnectionRequest DataArrival DataChanged DataUpdated DblClick " + "Deactivate DeviceArrival DeviceOtherEvent DeviceQueryRemove " + "DeviceQueryRemoveFailed DeviceRemoveComplete DoGetNewFileName " + "DeviceRemovePending DevModeChange Disconnect DisplayChanged " + "Dissociate Done DonePainting DownClick DragDrop DragOver " + "DropDown EditProperty EnterCell EnterFocus ExitFocus Expand " + "FootnoteActivated FootnoteSelected FootnoteUpdated GotFocus " + "HeadClick InfoMessage Initialize IniProperties ItemActivated " + "ItemAdded ItemCheck ItemClick ItemReloaded ItemRemoved " + "ItemRenamed ItemSeletected KeyDown KeyPress KeyUp LeaveCell " + "LegendActivated LegendSelected LegendUpdated LinkClose " + "LinkError LinkNotify LinkOpen Load LostFocus MouseDown " + "MouseMove MouseUp NodeClick ObjectMove OLECompleteDrag " + "OLEDragDrop OLEDragOver OLEGiveFeedback OLESetData OLEStartDrag " + "OnAddNew OnComm Paint PanelClick PanelDblClick PathChange " + "PatternChange PlotActivated PlotSelected PlotUpdated " + "PointActivated Reposition SelChange StateChanged TitleActivated " + "PointLabelActivated PointLabelSelected PointLabelUpdated " + "PointSelected PointUpdated PowerQuerySuspend PowerResume " + "PowerStatusChanged PowerSuspend QueryChangeConfig QueryComplete " + "QueryCompleted QueryTimeout QueryUnload ReadProperties " + "RequestChangeFileName RequestWriteFile Resize ResultsChanged " + "RowColChange RowCurrencyChange RowResize RowStatusChanged " + "SelectionChanged SendComplete SendProgress SeriesActivated " + "SeriesSelected SeriesUpdated SettingChanged SplitChange Unload " + "StatusUpdate SysColorsChanged Terminate TimeChanged " + "TitleSelected TitleActivated UnboundAddData UnboundDeleteRow " + "UnboundGetRelativeBookmark UnboundReadData UnboundWriteData " + "UpClick Updated Validate ValidationError WillAssociate " + "WillDissociate WillExecute WillUpdateRows WriteProperties " + "WillChangeData") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (stc.STC_B_ASM, 'asm_style'), + (stc.STC_B_BINNUMBER, 'default_style'), # STYLE NEEDED + (stc.STC_B_COMMENT, 'comment_style'), + (stc.STC_B_CONSTANT, 'const_style'), + (stc.STC_B_DATE, 'default_style'), # STYLE NEEDED + (stc.STC_B_DEFAULT, 'default_style'), + (stc.STC_B_ERROR, 'error_style'), + (stc.STC_B_HEXNUMBER, 'number_style'), + (stc.STC_B_IDENTIFIER, 'default_style'), + (stc.STC_B_KEYWORD, 'keyword_style'), + (stc.STC_B_KEYWORD2, 'class_style'), # STYLE NEEDED + (stc.STC_B_KEYWORD3, 'funct_style'), # STYLE NEEDED + (stc.STC_B_KEYWORD4, 'scalar_style'), # STYLE NEEDED + (stc.STC_B_LABEL, 'directive_style'), # STYLE NEEDED + (stc.STC_B_NUMBER, 'number_style'), + (stc.STC_B_OPERATOR, 'operator_style'), + (stc.STC_B_PREPROCESSOR, 'pre_style'), + (stc.STC_B_STRING, 'string_style'), + (stc.STC_B_STRINGEOL, 'stringeol_style') + ] + +#---- Extra Properties ----# +FOLD = ("fold", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for VisualBasic""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_VB) + + def GetKeywords(self): + """Returns Specified Keywords List """ + keywords = list() + tmp = [VB_KW, VB_UKW1, VB_UKW2, VB_UKW3] + for keyw in tmp: + keywords.append((keyw[0], keyw[1].lower())) + return keywords + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'\''] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xml.py new file mode 100644 index 0000000..00e9023 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xml.py @@ -0,0 +1,63 @@ +############################################################################### +# Name: xml.py # +# Purpose: Define XML syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: xml.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for XML Files. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _xml.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc + +# Local Imports +import synglob +import syndata +import _html + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Xml Keywords +XML_KEYWORDS = ("rss atom pubDate channel version title link description " + "language generator item") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for XML""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_XML) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, _html.AutoIndenter) + + def GetKeywords(self): + """Returns Specified Keywords List """ + sgml = _html.KeywordString(synglob.ID_LANG_SGML) + return [(5, XML_KEYWORDS + u" " + sgml)] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return _html.SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [_html.FOLD, _html.FLD_HTML] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'<!--', u'-->'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xtext.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xtext.py new file mode 100644 index 0000000..a9da959 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_xtext.py @@ -0,0 +1,261 @@ +############################################################################### +# Name: xtext.py # +# Purpose: Define xtext syntax for highlighting and other features # +# Author: Igor Dejanovic <igor.dejanovic@gmail.com> # +# Copyright: (c) 2009 Igor Dejanovic <igor.dejanovic@gmail.com> # +# License: wxWindows License # +############################################################################### + +""" +FILE: xtext.py +AUTHOR: Igor Dejanovic +@summary: Lexer module for Xtext language. + For more information see <http://www.eclipse.org/modeling/tmf/> or + <http://www.openarchitectureware.org/>. +""" + +__author__ = "Igor Dejanovic <igor.dejanovic@gmail.com>" +__svnid__ = "$Id: _xtext.py 70229 2012-01-01 01:27:10Z CJP $" +__revision__ = "$Revision: 70229 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx.stc as stc +from pygments.lexer import RegexLexer, include, bygroups +from pygments.token import Token, Text, Comment, Operator, \ + Keyword, Name, String, Number, Punctuation +import re + +# Local Imports +import synglob +import syndata + +#-----------------------------------------------------------------------------# +# Style Id's + +STC_XTEXT_DEFAULT, \ +STC_XTEXT_COMMENT, \ +STC_XTEXT_NUMBER, \ +STC_XTEXT_STRING, \ +STC_XTEXT_STRINGEOL, \ +STC_XTEXT_OPERATOR, \ +STC_XTEXT_NAME, \ +STC_XTEXT_ABSTRACTRULE, \ +STC_XTEXT_FEATURE, \ +STC_XTEXT_CROSSREF, \ +STC_XTEXT_PACKAGE, \ +STC_XTEXT_KEYWORD, \ +STC_XTEXT_KEYWORD_PSEUDO = range(13) + +#-----------------------------------------------------------------------------# + +#---- Keyword Specifications ----# + +# Xtext Keywords +KEYWORDS = ("grammar generate import returns enum terminal hidden with as current") +TERMINALS = ("ID INT STRING") + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [ (STC_XTEXT_DEFAULT, 'default_style'), + (STC_XTEXT_COMMENT, 'comment_style'), + (STC_XTEXT_NUMBER, 'number_style'), + (STC_XTEXT_STRING, 'string_style'), + (STC_XTEXT_STRINGEOL, 'stringeol_style'), + (STC_XTEXT_OPERATOR, 'operator_style'), + (STC_XTEXT_NAME, 'default_style'), + (STC_XTEXT_ABSTRACTRULE, 'keyword3_style'), + (STC_XTEXT_FEATURE, 'default_style'), + (STC_XTEXT_CROSSREF, 'class_style'), + (STC_XTEXT_PACKAGE, 'class_style'), + (STC_XTEXT_KEYWORD, 'keyword_style'), + (STC_XTEXT_KEYWORD_PSEUDO, 'keyword2_style'), ] + + +#-------- Xtext grammar rules --------------- + +#---- Extra Properties ----# + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for XText""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_CONTAINER) + self.RegisterFeature(synglob.FEATURE_AUTOINDENT, AutoIndenter) + self.RegisterFeature(synglob.FEATURE_STYLETEXT, StyleText) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return [(1, KEYWORDS)] + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u"//"] + +#-----------------------------------------------------------------------------# +# Features + +def StyleText(stc, start, end): + """Style the text + @param stc: Styled text control instance + @param start: Start position + @param end: end position + + """ + + for index, token, txt in lexer.get_tokens_unprocessed(stc.GetTextRange(0, end)): +# print index, token, txt + style = TOKEN_MAP.get(token, STC_XTEXT_DEFAULT) + +# print "Text=%s, len=%s" % (txt, len(txt)) + stc.StartStyling(index, 0x1f) + tlen = len(txt) + if tlen: + stc.SetStyling(len(txt), style) + +def AutoIndenter(estc, pos, ichar): + """Auto indent xtext code. + This code is based on python AutoIndenter. + @param estc: EditraStyledTextCtrl + @param pos: current carat position + @param ichar: Indentation character + @return: string + + """ + rtxt = u'' + line = estc.GetCurrentLine() + spos = estc.PositionFromLine(line) + text = estc.GetTextRange(spos, pos) + eolch = estc.GetEOLChar() + inspace = text.isspace() + + # Cursor is in the indent area somewhere or in the column 0. + if inspace or not len(text): + estc.AddText(eolch + text) + return + + text = text.strip() + if text.endswith(";"): + estc.AddText(eolch) + return + + indent = estc.GetLineIndentation(line) + if ichar == u"\t": + tabw = estc.GetTabWidth() + else: + tabw = estc.GetIndent() + + i_space = indent / tabw + end_spaces = ((indent - (tabw * i_space)) * u" ") + + if text.endswith(u":"): + i_space += 1 + + rtxt = eolch + ichar * i_space + end_spaces + + # Put text in the buffer + estc.AddText(rtxt) + +#-----------------------------------------------------------------------------# + +TOKEN_MAP = { Token.String : STC_XTEXT_STRING, + Token.Comment.Multiline : STC_XTEXT_COMMENT, + Token.Comment.Single : STC_XTEXT_COMMENT, + Token.Operator : STC_XTEXT_OPERATOR, + Token.Punctuation : STC_XTEXT_OPERATOR, + Token.Number.Integer : STC_XTEXT_NUMBER, + Token.Keyword : STC_XTEXT_KEYWORD, + Token.Keyword.Pseudo: STC_XTEXT_KEYWORD_PSEUDO, + Token.Name : STC_XTEXT_NAME, + Token.Name.AbstractRule : STC_XTEXT_ABSTRACTRULE, + Token.Name.Feature : STC_XTEXT_FEATURE, + Token.Name.CrossRef : STC_XTEXT_CROSSREF, + Token.Name.Package : STC_XTEXT_PACKAGE, + Token.Name.Package.EMF : STC_XTEXT_PACKAGE} + + +class XTextLexer(RegexLexer): + """ + Xtext lexer based on statefull RegexLexer from pygments library. + """ + + name = 'Xtext' + aliases = ['xtext'] + filenames = ['*.xtxt'] + mimetypes = ['text/x-xtext'] + + flags = re.MULTILINE | re.DOTALL # | re.UNICODE + + #: optional Comment or Whitespace + #_ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+' + + def AltWords(words): + """Makes lexer rule for alternative words from the given words list. + @param words: string consisting of space separated words + @return: string in the form \\bword1\\b|\\bword2\\b|\\bword3\b... + """ + return "|".join([ "\\b%s\\b" % w for w in words.split()]) + + _ident = r'\^?[a-zA-Z_\$][a-zA-Z0-9_]*' + + tokens = { + 'root': [ + (include('first')), + (_ident + r'(\.' + _ident + r')+', Name.Package), + ('(' + _ident + r')(\s*)(returns)', + bygroups(Name.AbstractRule, Text.Whitespace, Keyword), 'parserrule'), + ('(' + _ident + r')(\s*)(:)', + bygroups(Name.AbstractRule, Text.Whitespace, Punctuation), 'parserrule'), + (_ident, Name), + ], + 'first': [ + (r'/\*', Comment.Multiline, 'comment'), + (r'\n', Token.EndOfLine), + (r'//[^\n]*$', Comment.Single), + (r'[ \t]+', Text.Whitespace), + (r'"(\\\\|\\"|[^"])*"', String), + (r"'(\\\\|\\'|[^'])*'", String), + (r'\*|\?|\+|!|\||=|\?=|\+=|\.\.|->', Operator), + (r'[()\[\]{}:]', Punctuation), + (r'[0-9]+', Number.Integer), + (AltWords(KEYWORDS), Keyword), + (AltWords(TERMINALS), Keyword.Pseudo), + (_ident + r'(::' + _ident + r')+', Name.Package.EMF), + ], + 'parserrule': [ + (include('first')), + ('(' + _ident + r'(\.' + _ident + r')?)([ \t]*)(=|\?=|\+=)', + bygroups(Name.Feature, Text.Whitespace, Operator)), + (_ident + r'(\.' + _ident + r')+', Name.Package), + (_ident, Name.CrossRef), + (r';', Punctuation, "#pop"), + ], + 'comment': [ + # Nested and multiline comments + (r'/\*', Comment.Multiline, "#push"), + (r'\*/', Comment.Multiline, "#pop"), + (r'\n', Token.EndOfLine), + (r'[^/*\n]+', Comment.Multiline), + (r'\*|\/', Comment.Multiline), + ], + } + +lexer = XTextLexer() + +if __name__=='__main__': + import codecs, sys + ftext = codecs.open(sys.argv[1], "r", "utf-8") + text = ftext.read() + ftext.close() + line=1 + for index, token, txt in lexer.get_tokens_unprocessed(text): + if token is Token.EndOfLine: + line += 1 + print line, token, txt diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_yaml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_yaml.py new file mode 100644 index 0000000..26407ee --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/_yaml.py @@ -0,0 +1,77 @@ +############################################################################### +# Name: yaml.py # +# Purpose: Define YAML syntax for highlighting and other features # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: yaml.py +AUTHOR: Cody Precord +@summary: Lexer configuration module for YAML +@todo: Maybe new custom style for text regions + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: _yaml.py 68798 2011-08-20 17:17:05Z CJP $" +__revision__ = "$Revision: 68798 $" + +#-----------------------------------------------------------------------------# +# Imports +import wx +import wx.stc as stc + +# Local Imports +import syndata + +#-----------------------------------------------------------------------------# + +#---- Keyword Definitions ----# +YAML_KW = [(0, "true false yes no")] + +#---- End Keyword Definitions ----# + +#---- Syntax Style Specs ----# +SYNTAX_ITEMS = [(stc.STC_YAML_COMMENT, 'comment_style'), + (stc.STC_YAML_DEFAULT, 'default_style'), + (stc.STC_YAML_DOCUMENT, 'scalar_style'), + (stc.STC_YAML_ERROR, 'error_style'), + (stc.STC_YAML_IDENTIFIER, 'keyword2_style'), + (stc.STC_YAML_KEYWORD, 'keyword_style'), + (stc.STC_YAML_NUMBER, 'number_style'), + (stc.STC_YAML_REFERENCE, 'global_style'), + (stc.STC_YAML_TEXT, 'default_style')] # Different style maybe + +if wx.VERSION >= (2, 9, 0, 0, ''): + SYNTAX_ITEMS.append((stc.STC_YAML_OPERATOR, 'operator_style')) + +#---- Extra Properties ----# +FOLD_COMMENT = ("fold.comment.yaml", "1") + +#-----------------------------------------------------------------------------# + +class SyntaxData(syndata.SyntaxDataBase): + """SyntaxData object for YAML""" + def __init__(self, langid): + super(SyntaxData, self).__init__(langid) + + # Setup + self.SetLexer(stc.STC_LEX_YAML) + + def GetKeywords(self): + """Returns Specified Keywords List """ + return YAML_KW + + def GetSyntaxSpec(self): + """Syntax Specifications """ + return SYNTAX_ITEMS + + def GetProperties(self): + """Returns a list of Extra Properties to set """ + return [FOLD_COMMENT] + + def GetCommentPattern(self): + """Returns a list of characters used to comment a block of code """ + return [u'#'] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syndata.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syndata.py new file mode 100644 index 0000000..c2ab987 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syndata.py @@ -0,0 +1,141 @@ + #-*- coding: utf-8 -*- +############################################################################### +# Name: syndata.py # +# Purpose: Syntax Data Base # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" Interface definition for syntax data + +@summary: Editra Syntax Data Interface Definition + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: syndata.py 67392 2011-04-04 21:06:43Z CJP $" +__revision__ = "$Revision: 67392 $" + +__all__ = ['SyntaxDataBase',] + +#-----------------------------------------------------------------------------# +# Imports +import collections +import wx.stc as stc + +# Local Imports +import synglob + +#-----------------------------------------------------------------------------# + +class SyntaxDataBase(object): + """Syntax data container object base class""" + def __init__(self, langid=synglob.ID_LANG_TXT): + object.__init__(self) + + # Attributes + self._langid = langid + self._lexer = stc.STC_LEX_NULL + self._features = dict() + + @property + def CommentPattern(self): + return self.GetCommentPattern() + + @property + def Keywords(self): + return self.GetKeywords() + + @property + def LangId(self): + return self.GetLangId() + + @property + def Lexer(self): + return self.GetLexer() + + @property + def Properties(self): + return self.GetProperties() + + @property + def SyntaxSpec(self): + return self.GetSyntaxSpec() + + #---- Interface Methods ----# + + def GetCommentPattern(self): + """Get the comment pattern + @return: list of strings ['/*', '*/'] + + """ + return list() + + def GetKeywords(self): + """Get the Keyword List(s) + @return: list of tuples [(1, ['kw1', kw2']),] + + """ + return list() + + def GetLangId(self): + """Get the language id + @return: int + + """ + return self._langid + + def GetLexer(self): + """Get the lexer id + @return: wx.stc.STC_LEX_ + + """ + return self._lexer + + def GetProperties(self): + """Get the Properties List + @return: list of tuples [('fold', '1'),] + + """ + return list() + + def GetSyntaxSpec(self): + """Get the the syntax specification list + @return: list of tuples [(int, 'style_tag'),] + @note: required override for subclasses + + """ + raise NotImplementedError + + #---- End Interface Methods ----# + + def GetFeature(self, name): + """Get a registered features callable + @param name: feature name + @return: callable or None + + """ + return self._features.get(name, None) + + def RegisterFeature(self, name, funct): + """Register an extension feature with the factory + @param name: feature name + @param funct: callable + + """ + assert isinstance(funct, collections.Callable), "funct must be callable object" + self._features[name] = funct + + def SetLexer(self, lex): + """Set the lexer object for this data object""" + self._lexer = lex + + def SetLangId(self, lid): + """Set the language identifier + @param lid: int + + """ + self._langid = lid + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synextreg.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synextreg.py new file mode 100644 index 0000000..60b6a34 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synextreg.py @@ -0,0 +1,598 @@ +############################################################################### +# Name: synextreg.py # +# Purpose: IDs and descriptions for supported file types, and also the # +# ExtensionRegister. These items are here in this module inorder to # +# be usable external to Editra and where wx may not be available. # +# # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: synextreg.py +LANGUAGE: Python +@summary: This module defines all supported language/filetype identifiers and + an extension register for mapping file extensions to filetypes. +@see: synglob.py for more details on how this data is used + +@note: Don't use this module directly for internal use only + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: synextreg.py 70228 2011-12-31 20:39:16Z CJP $" +__revision__ = "$Revision: 70228 $" + +#-----------------------------------------------------------------------------# +import os + +#-----------------------------------------------------------------------------# + +def _NewId(): + global _idCounter + _idCounter += 1 + return _idCounter + +_idCounter = 32100 + +#-----------------------------------------------------------------------------# + +#---- Language Identifiers Keys ----# +# Used for specifying what dialect/keyword set to load for a specific lexer + +#---- Use LEX_NULL ----# +ID_LANG_TXT = _NewId() +LANG_TXT = u'Plain Text' + +#---- Use LEX_ADA ----# +ID_LANG_ADA = _NewId() +LANG_ADA = u'Ada' + +#---- Use LEX_ASM ----# +ID_LANG_ASM = _NewId() +LANG_ASM = u'GNU Assembly' +ID_LANG_DSP56K = _NewId() +LANG_DSP56K = u'DSP56K Assembly' +ID_LANG_68K = _NewId() +LANG_68K = u'68k Assembly' +ID_LANG_MASM = _NewId() +LANG_MASM = u'MASM' +ID_LANG_NASM = _NewId() +LANG_NASM = u'Netwide Assembler' + +# Use LEX_BASH +ID_LANG_BOURNE = _NewId() +LANG_BOURNE = u'Bourne Shell Script' +ID_LANG_BASH = _NewId() +LANG_BASH = u'Bash Shell Script' +ID_LANG_CSH = _NewId() +LANG_CSH = u'C-Shell Script' +ID_LANG_KSH = _NewId() +LANG_KSH = u'Korn Shell Script' + +# Use LEX_CAML +ID_LANG_CAML = _NewId() +LANG_CAML = u'Caml' + +# Use LEX_CONF +ID_LANG_APACHE = _NewId() +LANG_APACHE = u'Apache Conf' + +# Use LEX_CPP +ID_LANG_AS = _NewId() +LANG_AS = u'ActionScript' +ID_LANG_C = _NewId() +LANG_C = u'C' +ID_LANG_CILK = _NewId() +LANG_CILK = u'Cilk' +ID_LANG_CPP = _NewId() +LANG_CPP = u'CPP' +ID_LANG_CSHARP = _NewId() +LANG_CSHARP = u'C#' +ID_LANG_D = _NewId() +LANG_D = u'D' +ID_LANG_DOT = _NewId() +LANG_DOT = u'DOT' +ID_LANG_EDJE = _NewId() +LANG_EDJE = u'Edje' +ID_LANG_FERITE = _NewId() +LANG_FERITE = u'Ferite' +ID_LANG_GLSL = _NewId() +LANG_GLSL = u'GLSL' +ID_LANG_HAXE = _NewId() +LANG_HAXE = u'HaXe' +ID_LANG_JAVA = _NewId() +LANG_JAVA = u'Java' +ID_LANG_OBJC = _NewId() +LANG_OBJC = u'Objective C' +ID_LANG_OOC = _NewId() +LANG_OOC = u'OOC' +ID_LANG_PIKE = _NewId() +LANG_PIKE = u'Pike' +ID_LANG_SQUIRREL = _NewId() +LANG_SQUIRREL = u'Squirrel' +ID_LANG_STATA = _NewId() +LANG_STATA = u'Stata' +ID_LANG_VALA = _NewId() +LANG_VALA = u'Vala' + +# Use LEX_CSS +ID_LANG_CSS = _NewId() +LANG_CSS = u'Cascading Style Sheet' +ID_LANG_ESS = _NewId() +LANG_ESS = u'Editra Style Sheet' + +# Use LEX_EIFFEL +ID_LANG_EIFFEL = _NewId() +LANG_EIFFEL = u'Eiffel' + +# Use LEX_ERLANG +ID_LANG_ERLANG = _NewId() +LANG_ERLANG = u'Erlang' + +# Use LEX_FLAGSHIP +ID_LANG_FLAGSHIP = _NewId() +LANG_FLAGSHIP = u'FlagShip' + +# Use LEX_F77 +ID_LANG_F77 = _NewId() +LANG_F77 = u'Fortran 77' + +# Use LEX_FORTH +ID_LANG_FORTH = _NewId() +LANG_FORTH = u"Forth" + +# Use LEX_FORTRAN +ID_LANG_F95 = _NewId() +LANG_F95 = u'Fortran 95' + +# Use LEX_GUI4CLI +ID_LANG_GUI4CLI = _NewId() +LANG_GUI4CLI = u'Gui4Cli' + +# Use LEX_HASKELL +ID_LANG_HASKELL = _NewId() +LANG_HASKELL = u'Haskell' + +# Use LEX_HTML +ID_LANG_COLDFUSION = _NewId() +LANG_COLDFUSION = u'ColdFusion' +ID_LANG_HTML = _NewId() +LANG_HTML = u'HTML' +ID_LANG_JS = _NewId() +LANG_JS = u'JavaScript' +ID_LANG_PHP = _NewId() +LANG_PHP = u'PHP' +ID_LANG_XML = _NewId() +LANG_XML = u'XML' +ID_LANG_SGML = _NewId() + +# Use LEX_INNOSETUP +ID_LANG_INNO = _NewId() +LANG_INNO = u'Inno Setup Script' + +# Use LEX_KIX +ID_LANG_KIX = _NewId() +LANG_KIX = u'Kix' + +# Use LEX_LISP +ID_LANG_LISP = _NewId() +LANG_LISP = u'Lisp' +ID_LANG_SCHEME = _NewId() +LANG_SCHEME = u'Scheme' +ID_LANG_NEWLISP = _NewId() +LANG_NEWLISP = u'newLISP' + +# Use LEX_LOUT +ID_LANG_LOUT = _NewId() +LANG_LOUT = u'Lout' + +# Use LEX_LUA +ID_LANG_LUA = _NewId() +LANG_LUA = u'Lua' + +# Use LEX_MSSQL (Microsoft SQL) +ID_LANG_MSSQL = _NewId() +LANG_MSSQL = u'Microsoft SQL' + +# Use LEX_NONMEM +ID_LANG_NONMEM = _NewId() +LANG_NONMEM = u'NONMEM Control Stream' + +# Use LEX_NSIS +ID_LANG_NSIS = _NewId() +LANG_NSIS = u'Nullsoft Installer Script' + +# Use LEX_PASCAL +ID_LANG_PASCAL = _NewId() +LANG_PASCAL = u'Pascal' + +# Use LEX_PERL +ID_LANG_PERL = _NewId() +LANG_PERL = u'Perl' + +# Use LEX_PS +ID_LANG_PS = _NewId() +LANG_PS = u'Postscript' + +# Use LEX_PYTHON +ID_LANG_BOO = _NewId() +LANG_BOO = u'Boo' +ID_LANG_PYTHON = _NewId() +LANG_PYTHON = u'Python' +ID_LANG_COBRA = _NewId() +LANG_COBRA = u'Cobra' + +# Use LEX_MATLAB +ID_LANG_MATLAB = _NewId() +LANG_MATLAB = u'Matlab' + +# Use LEX_RUBY +ID_LANG_RUBY = _NewId() +LANG_RUBY = u'Ruby' + +# Use LEX_SMALLTALK +ID_LANG_ST = _NewId() +LANG_ST = u'Smalltalk' + +# Use LEX_SQL (PL/SQL, SQL*Plus) +ID_LANG_SQL = _NewId() +LANG_SQL = u'SQL' +ID_LANG_PLSQL = _NewId() +LANG_PLSQL = u'PL/SQL' +ID_LANG_4GL = _NewId() +LANG_4GL = u"Progress 4GL" + +# Use LEX_TCL +ID_LANG_TCL = _NewId() +LANG_TCL = u'Tcl/Tk' + +# Use LEX_TEX +ID_LANG_TEX = _NewId() +LANG_TEX = u'Tex' +ID_LANG_LATEX = _NewId() +LANG_LATEX = u'LaTeX' + +# Use LEX_VB +ID_LANG_VB = _NewId() +LANG_VB = u'Visual Basic' + +# Use LEX_VBSCRIPT +ID_LANG_VBSCRIPT = _NewId() +LANG_VBSCRIPT = u'VBScript' + +# Use LEX_VERILOG +ID_LANG_VERILOG = _NewId() +LANG_VERILOG = u'Verilog' +ID_LANG_SYSVERILOG = _NewId() +LANG_SYSVERILOG = u'System Verilog' + +# Use LEX_VHDL +ID_LANG_VHDL = _NewId() +LANG_VHDL = u'VHDL' + +# Use LEX_OCTAVE +ID_LANG_OCTAVE = _NewId() +LANG_OCTAVE = u'Octave' + +# Use LEX_OTHER (Batch, Diff, Makefile) +ID_LANG_BATCH = _NewId() +LANG_BATCH = u'DOS Batch Script' +ID_LANG_DIFF = _NewId() +LANG_DIFF = u'Diff File' +ID_LANG_MAKE = _NewId() +LANG_MAKE = u'Makefile' +ID_LANG_PROPS = _NewId() +LANG_PROPS = u'Properties' + +# Use LEX_YAML +ID_LANG_YAML = _NewId() +LANG_YAML = u'YAML' + +# Use LEX_CONTAINER +ID_LANG_DJANGO = _NewId() +LANG_DJANGO = u'Django' +ID_LANG_ISSL = _NewId() +LANG_ISSL = u'IssueList' +ID_LANG_MAKO = _NewId() +LANG_MAKO = u'Mako' +ID_LANG_R = _NewId() +LANG_R = u'R' +ID_LANG_S = _NewId() +LANG_S = u'S' +ID_LANG_GROOVY = _NewId() +LANG_GROOVY = u'Groovy' +ID_LANG_XTEXT = _NewId() +LANG_XTEXT = u'Xtext' + +#---- End Language Identifier Keys ----# + +# Default extensions to file type mapping +EXT_MAP = { + '4gl' : LANG_4GL, + '56k' : LANG_DSP56K, + '68k' : LANG_68K, + 'ada adb ads a' : LANG_ADA, + 'conf htaccess' : LANG_APACHE, + 'as asc mx' : LANG_AS, + 'gasm' : LANG_ASM, + 'bsh sh configure' : LANG_BASH, + 'bat cmd' : LANG_BATCH, + 'boo' : LANG_BOO, + 'c h' : LANG_C, + 'ml mli' : LANG_CAML, + 'cilk cilkh' : LANG_CILK, + 'cobra' : LANG_COBRA, + 'cfm cfc cfml dbm' : LANG_COLDFUSION, + 'cc c++ cpp cxx hh h++ hpp hxx' : LANG_CPP, + 'csh' : LANG_CSH, + 'cs' : LANG_CSHARP, + 'css' : LANG_CSS, + 'd' : LANG_D, + 'patch diff' : LANG_DIFF, + 'django' : LANG_DJANGO, + 'dot' : LANG_DOT, + 'edc' : LANG_EDJE, + 'e' : LANG_EIFFEL, + 'erl' : LANG_ERLANG, + 'ess' : LANG_ESS, + 'f for' : LANG_F77, + 'f90 f95 f2k fpp' : LANG_F95, + 'fe' : LANG_FERITE, + 'fth 4th fs seq' : LANG_FORTH, + 'prg' : LANG_FLAGSHIP, + 'frag vert glsl' : LANG_GLSL, + 'gc gui' : LANG_GUI4CLI, + 'hs' : LANG_HASKELL, + 'hx hxml' : LANG_HAXE, + 'htm html shtm shtml xhtml' : LANG_HTML, + 'isl' : LANG_ISSL, + 'iss' : LANG_INNO, + 'java' : LANG_JAVA, + 'js' : LANG_JS, + 'kix' : LANG_KIX, + 'ksh' : LANG_KSH, + 'aux tex sty' : LANG_LATEX, + 'cl lisp' : LANG_LISP, + 'lsp' : LANG_NEWLISP, + 'lt' : LANG_LOUT, + 'lua' : LANG_LUA, + 'mak makefile mk' : LANG_MAKE, + 'mao mako' : LANG_MAKO, + 'asm masm' : LANG_MASM, + 'matlab' : LANG_MATLAB, + 'mssql' : LANG_MSSQL, + 'nasm' : LANG_NASM, + 'ctl nonmem' : LANG_NONMEM, + 'nsi nsh' : LANG_NSIS, + 'mm m' : LANG_OBJC, + 'oct octave' : LANG_OCTAVE, + 'ooc' : LANG_OOC, + 'dfm dpk dpr inc p pas pp' : LANG_PASCAL, + 'cgi pl pm pod' : LANG_PERL, + 'php php3 phtml phtm' : LANG_PHP, + 'pike' : LANG_PIKE, + 'plsql' : LANG_PLSQL, + 'ini inf reg url cfg cnf' : LANG_PROPS, + 'ai ps' : LANG_PS, + 'py pyw python' : LANG_PYTHON, + 'r' : LANG_R, + 'do ado' : LANG_STATA, + 'rake rb rbw rbx gemspec' : LANG_RUBY, + 's' : LANG_S, + 'scm smd ss' : LANG_SCHEME, + 'sql' : LANG_SQL, + 'nut' : LANG_SQUIRREL, + 'st' : LANG_ST, + 'sv svh' : LANG_SYSVERILOG, + 'itcl tcl tk' : LANG_TCL, + 'txt' : LANG_TXT, + 'vala' : LANG_VALA, + 'bas cls frm vb' : LANG_VB, + 'vbs dsm' : LANG_VBSCRIPT, + 'v' : LANG_VERILOG, + 'vh vhdl vhd' : LANG_VHDL, + 'axl dtd plist rdf svg xml xrc xsd xsl xslt xul' : LANG_XML, + 'yaml yml' : LANG_YAML, + 'groovy' : LANG_GROOVY, + 'xtext' : LANG_XTEXT, + } + + +#-----------------------------------------------------------------------------# + +class ExtensionRegister(dict): + """A data storage class for managing mappings of + file types to file extensions. The register is created as a singleton. + + """ + instance = None + config = u'synmap' + def __init__(self): + """Initializes the register""" + if not ExtensionRegister.instance: + self.LoadDefault() + + def __new__(cls, *args, **kargs): + """Maintain only a single instance of this object + @return: instance of this class + + """ + if not cls.instance: + cls.instance = dict.__new__(cls, *args, **kargs) + return cls.instance + + def __missing__(self, key): + """Return the default value if an item is not found + @return: txt extension for plain text + + """ + return u'txt' + + def __setitem__(self, i, y): + """Ensures that only one filetype is associated with an extension + at one time. The behavior is that more recent settings override + and remove associations from older settings. + @param i: key to set + @param y: value to set + @throws: TypeError Only accepts list() objects + + """ + if not isinstance(y, list): + raise TypeError, "Extension Register Expects a List" + for key, val in self.iteritems(): + for item in y: + if item in val: + val.pop(val.index(item)) + y.sort() + dict.__setitem__(self, i, [x.strip() for x in y]) + + def __str__(self): + """Converts the Register to a string that is formatted + for output to a config file. + @return: the register as a string + + """ + keys = self.keys() + keys.sort() + tmp = list() + for key in keys: + tmp.append("%s=%s" % (key, u':'.join(self.__getitem__(key)))) + return os.linesep.join(tmp) + + def Associate(self, ftype, ext): + """Associate a given file type with the given file extension(s). + The ext parameter can be a string of space separated extensions + to allow for multiple associations at once. + @param ftype: file type description string + @param ext: file extension to associate + + """ + assoc = self.get(ftype, None) + exts = ext.strip().split() + if assoc: + for x in exts: + if x not in assoc: + assoc.append(x) + else: + assoc = list(set(exts)) + assoc.sort() + super(ExtensionRegister, self).__setitem__(ftype, assoc) + + def Disassociate(self, ftype, ext): + """Disassociate a file type with a given extension or space + separated list of extensions. + @param ftype: filetype description string + @param ext: extension to disassociate + + """ + to_drop = ext.strip().split() + assoc = self.get(ftype, None) + if assoc: + for item in to_drop: + if item in assoc: + assoc.remove(item) + super(ExtensionRegister, self).__setitem__(ftype, assoc) + else: + pass + + def FileTypeFromExt(self, ext): + """Returns the file type that is associated with + the extension. Matching is done with a case insensitive search. + If no association is found Plain Text + will be returned by default. + @param ext: extension to lookup + + """ + ext = ext.lower() + for key, val in self.iteritems(): + if ext in [ext2.lower() for ext2 in val]: + return key + return LANG_TXT + + def GetAllExtensions(self): + """Returns a sorted list of all extensions registered + @return: list of all registered extensions + + """ + ext = list() + for extension in self.values(): + ext.extend(extension) + ext.sort() + return ext + + def LoadDefault(self): + """Loads the default settings + @postcondition: sets dictionary back to default installation state + + """ + self.clear() + for key in EXT_MAP: + self.__setitem__(EXT_MAP[key], key.split()) + + def LoadFromConfig(self, config): + """Load the extension register with values from a config file + @param config: path to config file to load settings from + + """ + path = os.path.join(config, self.config) + if not os.path.exists(path): + self.LoadDefault() + else: + file_h = file(path, "rb") + lines = file_h.readlines() + file_h.close() + for line in lines: + tmp = line.split(u'=') + if len(tmp) != 2: + continue + ftype = tmp[0].strip() + exts = tmp[1].split(u':') + self.__setitem__(ftype, exts) + + def Remove(self, ftype): + """Remove a filetype from the register + @param ftype: File type description string + @return: bool removed or not + + """ + if ftype in self: + del self[ftype] + return True + return False + + def SetAssociation(self, ftype, ext): + """Like Associate but overrides any current settings instead of + just adding to them. + @param ftype: File type description string + @param ext: space separated list of file extensions to set + + """ + self.__setitem__(ftype, list(set(ext.split()))) + +#-----------------------------------------------------------------------------# + +def GetFileExtensions(): + """Gets a sorted list of all file extensions the editor is configured + to handle. + @return: all registered file extensions + + """ + extreg = ExtensionRegister() + return extreg.GetAllExtensions() + +def RegisterNewLangId(langId, langName): + """Register a new language identifier + @param langId: "ID_LANG_FOO" + @param langName: "Foo" + @return: int + + """ + gdict = globals() + if langId not in gdict: + gdict[langId] = _NewId() + gdict[langId[3:]] = langName + return gdict[langId] + +#-----------------------------------------------------------------------------# diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synglob.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synglob.py new file mode 100644 index 0000000..5b71318 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synglob.py @@ -0,0 +1,170 @@ +############################################################################### +# Name: synglob.py # +# Purpose: Acts as a registration point for all supported languages. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +FILE: synglob.py +AUTHOR: Cody Precord +@summary: Provides configuration and basic API functionality to all the syntax + modules. It also acts as a configuration file for the syntax + management code. When support for a new languages is added it must + have a registration entry in the below L{LANG_MAP} dictionary in + order to be loadable by the syntax module. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: synglob.py 69887 2011-12-01 19:54:13Z CJP $" +__revision__ = "$Revision: 69887 $" + +#-----------------------------------------------------------------------------# +# Dependencies +import wx.stc as stc + +# The language identifiers and the EXT_MAP have been moved out of this +# module in order to be independent of Editra and wx, but they are +# still needed here... +from synextreg import * + +#-----------------------------------------------------------------------------# +# Feature Identifiers +FEATURE_AUTOINDENT = u"AutoIndenter" +FEATURE_STYLETEXT = u"StyleText" + +#-----------------------------------------------------------------------------# + +# Maps file types to syntax definitions +LANG_MAP = {LANG_4GL : (ID_LANG_4GL, '_progress'), + LANG_DSP56K : (ID_LANG_DSP56K, '_asm68k'), + LANG_68K : (ID_LANG_68K, '_asm68k'), + LANG_ADA : (ID_LANG_ADA, '_ada'), + LANG_APACHE : (ID_LANG_APACHE, '_apache'), + LANG_AS : (ID_LANG_AS, '_actionscript'), + LANG_ASM : (ID_LANG_ASM, '_asm'), + LANG_BASH : (ID_LANG_BASH, '_sh'), + LANG_BATCH : (ID_LANG_BATCH, '_batch'), + LANG_BOO : (ID_LANG_BOO, '_boo'), + LANG_C : (ID_LANG_C, '_cpp'), + LANG_CAML : (ID_LANG_CAML, '_caml'), + LANG_CILK : (ID_LANG_CILK, '_cpp'), + LANG_COBRA : (ID_LANG_COBRA, '_cobra'), + LANG_COLDFUSION : (ID_LANG_COLDFUSION, '_html'), + LANG_CPP : (ID_LANG_CPP, '_cpp'), + LANG_CSH : (ID_LANG_CSH, '_sh'), + LANG_CSHARP : (ID_LANG_CSHARP, '_cpp'), + LANG_CSS : (ID_LANG_CSS, '_css'), + LANG_D : (ID_LANG_D, '_d'), + LANG_DIFF : (ID_LANG_DIFF, '_diff'), + LANG_DJANGO : (ID_LANG_DJANGO, '_django'), + LANG_DOT : (ID_LANG_DOT, '_dot'), + LANG_EDJE : (ID_LANG_EDJE, '_edje'), + LANG_EIFFEL : (ID_LANG_EIFFEL, '_eiffel'), + LANG_ERLANG : (ID_LANG_ERLANG, '_erlang'), + LANG_ESS : (ID_LANG_ESS, '_editra_ss'), + LANG_F77 : (ID_LANG_F77, '_fortran'), + LANG_F95 : (ID_LANG_F95, '_fortran'), + LANG_FERITE : (ID_LANG_FERITE, '_ferite'), + LANG_FLAGSHIP: (ID_LANG_FLAGSHIP, '_flagship'), + LANG_FORTH : (ID_LANG_FORTH, '_forth'), + LANG_GLSL : (ID_LANG_GLSL, '_glsl'), + LANG_GUI4CLI : (ID_LANG_GUI4CLI, '_gui4cli'), + LANG_HASKELL : (ID_LANG_HASKELL, '_haskell'), + LANG_HAXE : (ID_LANG_HAXE, '_haxe'), + LANG_HTML : (ID_LANG_HTML, '_html'), + LANG_INNO : (ID_LANG_INNO, '_inno'), + LANG_ISSL : (ID_LANG_ISSL, '_issuelist'), + LANG_JAVA : (ID_LANG_JAVA, '_java'), + LANG_JS : (ID_LANG_JS, '_javascript'), + LANG_KIX : (ID_LANG_KIX, '_kix'), + LANG_KSH : (ID_LANG_KSH, '_sh'), + LANG_LATEX : (ID_LANG_LATEX, '_latex'), + LANG_LISP : (ID_LANG_LISP, '_lisp'), + LANG_LOUT : (ID_LANG_LOUT, '_lout'), + LANG_LUA : (ID_LANG_LUA, '_lua'), + LANG_MAKE : (ID_LANG_MAKE, '_make'), + LANG_MAKO : (ID_LANG_MAKO, '_mako'), + LANG_MASM : (ID_LANG_MASM, '_masm'), + LANG_MATLAB : (ID_LANG_MATLAB, '_matlab'), + LANG_MSSQL : (ID_LANG_MSSQL, '_mssql'), + LANG_NASM : (ID_LANG_NASM, '_nasm'), + LANG_NEWLISP: (ID_LANG_NEWLISP,'_lisp'), + LANG_NONMEM : (ID_LANG_NONMEM, '_nonmem'), + LANG_NSIS : (ID_LANG_NSIS, '_nsis'), + LANG_OBJC : (ID_LANG_OBJC, '_cpp'), + LANG_OCTAVE : (ID_LANG_OCTAVE, '_matlab'), + LANG_OOC : (ID_LANG_OOC, '_ooc'), + LANG_PASCAL : (ID_LANG_PASCAL, '_pascal'), + LANG_PERL : (ID_LANG_PERL, '_perl'), + LANG_PHP : (ID_LANG_PHP, '_php'), + LANG_PIKE : (ID_LANG_PIKE, '_pike'), + LANG_PLSQL : (ID_LANG_PLSQL, '_sql'), + LANG_PROPS : (ID_LANG_PROPS, '_props'), + LANG_PS : (ID_LANG_PS, '_postscript'), + LANG_PYTHON : (ID_LANG_PYTHON, '_python'), + LANG_R : (ID_LANG_R, '_s'), + LANG_RUBY : (ID_LANG_RUBY, '_ruby'), + LANG_S : (ID_LANG_S, '_s'), + LANG_SCHEME : (ID_LANG_SCHEME, '_lisp'), + LANG_SQL : (ID_LANG_SQL, '_sql'), + LANG_SQUIRREL : (ID_LANG_SQUIRREL, '_squirrel'), + LANG_ST : (ID_LANG_ST, '_smalltalk'), + LANG_STATA : (ID_LANG_STATA, '_stata'), + LANG_SYSVERILOG : (ID_LANG_SYSVERILOG, '_verilog'), + LANG_TCL : (ID_LANG_TCL, '_tcl'), + LANG_TXT : (ID_LANG_TXT, None), + LANG_VALA : (ID_LANG_VALA, '_cpp'), + LANG_VB : (ID_LANG_VB, '_visualbasic'), + LANG_VBSCRIPT : (ID_LANG_VBSCRIPT, '_vbscript'), + LANG_VERILOG: (ID_LANG_VERILOG, '_verilog'), + LANG_VHDL : (ID_LANG_VHDL, '_vhdl'), + LANG_XML : (ID_LANG_XML, '_xml'), + LANG_YAML : (ID_LANG_YAML, '_yaml'), + LANG_GROOVY : (ID_LANG_GROOVY, '_groovy'), + LANG_XTEXT : (ID_LANG_XTEXT, '_xtext') + } + + +### TODO: Profiling on the following methods to see if caching is necessary ### + +# Dynamically finds the language description string that matches the given +# language id. +# Used when manually setting lexer from a menu/dialog +def GetDescriptionFromId(lang_id): + """Get the programming languages description string from the given + language id. If no corresponding language is found the plain text + description is returned. + @param lang_id: Language Identifier ID + @note: requires that all languages are defined in ID_LANG_NAME, LANG_NAME + pairs to work properly. + + """ + rval = LANG_TXT + # Guard against async code that may be modifying globals + globs = dict(globals()) + for key, val in globs.iteritems(): + if val == lang_id and key.startswith('ID_LANG'): + rval = globs.get(key[3:], LANG_TXT) + break + return rval + +def GetIdFromDescription(desc): + """Get the language identifier for the given file type string. The search + is case insensitive. + @param desc: unicode (i.e u"Python") + @note: if lookup fails ID_LANG_TXT is returned + + """ + rval = ID_LANG_TXT + desc = desc.lower() + # Guard against async code that may be modifying globals + globs = dict(globals()) + for key, val in globs.iteritems(): + if isinstance(val, unicode): + if val.lower() == desc and key.startswith('LANG_'): + rval = globs.get("ID_" + key, ID_LANG_TXT) + break + return rval diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syntax.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syntax.py new file mode 100644 index 0000000..e913f45 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/syntax.py @@ -0,0 +1,441 @@ +############################################################################### +# Name: syntax.py # +# Purpose: Manage and dynamically load/provide syntax on request from editor. # +# Also manages the mappings of file extensions to lexers. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2007 Cody Precord <staff@editra.org> # +# Licence: wxWindows Licence # +############################################################################### + +""" +FILE: syntax.py +AUTHOR: Cody Precord + +SUMMARY: + +Toolkit for managing the importing of syntax modules and providing the data +to the requesting text control. It is meant to be the main access point to the +resources and api provided by this package. + +DETAIL: + +The main item of this module is the L{SyntaxMgr} it is a singleton object that +manages the dynamic importing of syntax data and configurations for all of the +editors supported languages. It allows only the needed data to be loaded into +memory when requested. The loading is only done once per session and all +subsequent requests share the same object. + +In addition to the L{SyntaxMgr} there are also a number of other utility and +convienience functions in this module for accessing data from other related +objects such as the Extension Register. + +@summary: Main api access point for the syntax package. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: syntax.py 71711 2012-06-09 18:59:03Z CJP $" +__revision__ = "$Revision: 71711 $" + +#-----------------------------------------------------------------------------# +# Dependencies +import wx +import os + +#-----------------------------------------------------------------------------# +# Data Objects / Constants + +# Used to index the tuple returned by getting data from EXT_REG +LANG_ID = 0 +MODULE = 1 + +_ = wx.GetTranslation +#-----------------------------------------------------------------------------# +# Imports +import synglob +import syndata +import synxml + +# Needed by other modules that use this api +from synextreg import ExtensionRegister, GetFileExtensions, RegisterNewLangId + +#-----------------------------------------------------------------------------# + +class SyntaxMgr(object): + """Class Object for managing loaded syntax data. The manager + is only created once as a singleton and shared amongst all + editor windows + + """ + instance = None + first = True + def __init__(self, config=None): + """Initialize a syntax manager. If the optional + value config is set the mapping of extensions to + lexers will be loaded from a config file. + @keyword config: path of config file to load file extension config from + + """ + if SyntaxMgr.first: + object.__init__(self) + SyntaxMgr.first = False + self._extreg = ExtensionRegister() + self._config = config + self._loaded = dict() + + # Syntax mode extensions + self._extensions = dict() # loaded extensions "py" : PythonMode() + + self.InitConfig() + + def __new__(cls, config=None): + """Ensure only a single instance is shared amongst + all objects. + @return: class instance + + """ + if cls.instance is None: + cls.instance = object.__new__(cls) + return cls.instance + + def _ExtToMod(self, ext): + """Gets the name of the module that is is associated + with the given extension or None in the event that there + is no association or that the association is plain text. + @param ext: extension string to lookup module for + + """ + ftype = self._extreg.FileTypeFromExt(ext) + lexdat = synglob.LANG_MAP.get(ftype) + mod = None + if lexdat: + mod = lexdat[MODULE] + return mod + + def GetLangId(self, ext): + """Gets the language Id that is associated with the file + extension. + @param ext: extension to get lang id for + + """ + ftype = self._extreg.FileTypeFromExt(ext) + return synglob.LANG_MAP[ftype][LANG_ID] + + def InitConfig(self): + """Initialize the SyntaxMgr's configuration state""" + if self._config: + self._extreg.LoadFromConfig(self._config) + else: + self._extreg.LoadDefault() + + if self._config: + self.LoadExtensions(self._config) + + def IsModLoaded(self, modname): + """Checks if a module has already been loaded + @param modname: name of module to lookup + + """ + if modname in self._loaded: + return True + else: + return False + + def LoadModule(self, modname): + """Dynamically loads a module by name. The loading is only + done if the modules data set is not already being managed + @param modname: name of syntax module to load + + """ + if modname == None: + return False + if not self.IsModLoaded(modname): + try: + self._loaded[modname] = __import__(modname, globals(), + locals(), ['']) + except ImportError, msg: + return False + return True + + def SaveState(self): + """Saves the current configuration state of the manager to + disk for use in other sessions. + @return: whether save was successful or not + + """ + if not self._config or not os.path.exists(self._config): + return False + path = os.path.join(self._config, self._extreg.config) + try: + file_h = open(path, "wb") + file_h.write(str(self._extreg)) + file_h.close() + except IOError: + return False + return True + + def GetSyntaxData(self, ext): + """Fetches the language data based on a file extension string. The file + extension is used to look up the default lexer actions from the EXT_REG + dictionary. + @see: L{synglob} + @param ext: a string representing the file extension + @return: SyntaxData object + + """ + # The Return Value + lang = self._extreg.FileTypeFromExt(ext) + if lang in self._extensions: + syn_data = self._extensions[lang] + return syn_data + + # Check for extensions that may have been removed + if lang not in synglob.LANG_MAP: + self._extreg.Remove(lang) + + lex_cfg = synglob.LANG_MAP.get(lang, synglob.LANG_MAP[synglob.LANG_TXT]) + + # Check if module is loaded and load if necessary + if not self.LoadModule(lex_cfg[MODULE]): + # Bail out and return a default plaintext config as + # nothing else can be done at this point + return syndata.SyntaxDataBase() + + # This little bit of code fetches the keyword/syntax + # spec set(s) from the specified module + mod = self._loaded[lex_cfg[MODULE]] + syn_data = mod.SyntaxData(lex_cfg[LANG_ID]) + return syn_data + + def LoadExtensions(self, path): + """Load all extensions found at the extension path + @param path: path to look for extension on + + """ + for fname in os.listdir(path): + if fname.endswith(u".edxml"): + fpath = os.path.join(path, fname) + modeh = synxml.LoadHandler(fpath) + + if modeh.IsOk(): + sdata = SynExtensionDelegate(modeh) + self._extensions[sdata.GetXmlObject().GetLanguage()] = sdata + else: + pass + #TODO: report error + + def SetConfigDir(self, path): + """Set the path to locate config information at. The SyntaxMgr will + look for file type associations in a file called synmap and will load + syntax extensions from .edxml files found at this path. + @param path: string + + """ + self._config = path + +#-----------------------------------------------------------------------------# + +class SynExtensionDelegate(syndata.SyntaxDataBase): + """Delegate SyntaxData class for SynXml Extension class instances""" + def __init__(self, xml_obj): + """Initialize the data class + @param xml_obj: SynXml + + """ + langId = _RegisterExtensionHandler(xml_obj) + syndata.SyntaxDataBase.__init__(self, langId) + + # Attributes + self._xml = xml_obj + + # Setup + self.SetLexer(self._xml.GetLexer()) + #TODO: Load and register features specified by the xml object + + #---- Syntax Data Implementation ----# + + def GetCommentPattern(self): + """Get the comment pattern + @return: list of strings ['/*', '*/'] + + """ + return self._xml.GetCommentPattern() + + def GetKeywords(self): + """Get the Keyword List(s) + @return: list of tuples [(1, ['kw1', kw2']),] + + """ + keywords = self._xml.GetKeywords() + rwords = list() + for sid, words in keywords: + rwords.append((sid, u" ".join(words))) + return rwords + + def GetProperties(self): + """Get the Properties List + @return: list of tuples [('fold', '1'),] + + """ + return self._xml.GetProperties() + + def GetSyntaxSpec(self): + """Get the the syntax specification list + @return: list of tuples [(int, 'style_tag'),] + + """ + return self._xml.GetSyntaxSpec() + + #---- End Syntax Data Implementation ----# + + def GetXmlObject(self): + """Get the xml object + @return: EditraXml instance + + """ + return self._xml + +#-----------------------------------------------------------------------------# + +def GenLexerMenu(): + """Generates a menu of available syntax configurations + @return: wx.Menu + + """ + lex_menu = wx.Menu() + f_types = dict() + for key in synglob.LANG_MAP: + f_types[key] = synglob.LANG_MAP[key][LANG_ID] + f_order = list(f_types) + f_order.sort(key=unicode.lower) + + for lang in f_order: + lex_menu.Append(f_types[lang], lang, + _("Switch Lexer to %s") % lang, wx.ITEM_CHECK) + return lex_menu + +def GenFileFilters(): + """Generates a list of file filters + @return: list of all file filters based on extension associations + + """ + extreg = ExtensionRegister() + # Convert extension list into a formatted string + f_dict = dict() + for key, val in extreg.iteritems(): + val.sort() + if key.lower() == 'makefile': + continue + + f_dict[key] = u";*." + u";*.".join(val) + + # Build the final list of properly formatted strings + filters = list() + for key in f_dict: + tmp = u" (%s)|%s|" % (f_dict[key][1:], f_dict[key][1:]) + filters.append(key + tmp) + filters.sort(key=unicode.lower) + filters.insert(0, u"All Files (*)|*|") + filters[-1] = filters[-1][:-1] # IMPORTANT trim last '|' from item in list + return filters + +def GetLexerList(): + """Gets the list of all supported file types + @return: list of strings + + """ + f_types = synglob.LANG_MAP.keys() + f_types.sort(key=unicode.lower) + return f_types + +#---- Syntax id set ----# +SYNTAX_IDS = None + +def SyntaxIds(): + """Gets a list of all Syntax Ids and returns it + @return: list of all syntax language ids + + """ + # Use the cached list if its available + if SYNTAX_IDS is not None: + return SYNTAX_IDS + + syn_ids = list() + for item in dir(synglob): + if item.startswith("ID_LANG"): + syn_ids.append(getattr(synglob, item)) + + return syn_ids + +SYNTAX_IDS = SyntaxIds() + +def SyntaxNames(): + """Gets a list of all Syntax Labels + @return: list of strings + + """ + syn_list = list() + for item in dir(synglob): + if item.startswith("LANG_"): + val = getattr(synglob, item) + if isinstance(val, basestring): + syn_list.append(val) + return syn_list + +#---- End Syntax ids ----# + +def GetExtFromId(ext_id): + """Takes a language ID and fetches an appropriate file extension string + @param ext_id: language id to get extension for + @return: file extension + + """ + extreg = ExtensionRegister() + ftype = synglob.GetDescriptionFromId(ext_id) + rval = u'' + if len(extreg[ftype]): + rval = extreg[ftype][0] + return rval + +def GetIdFromExt(ext): + """Get the language id from the given file extension + @param ext: file extension (no dot) + @return: language identifier id from extension register + + """ + ftype = ExtensionRegister().FileTypeFromExt(ext) + if ftype in synglob.LANG_MAP: + return synglob.LANG_MAP[ftype][LANG_ID] + else: + return synglob.ID_LANG_TXT + +def GetTypeFromExt(ext): + """Get the filetype description string from the given extension. + The return value defaults to synglob.LANG_TXT if nothing is found. + @param ext: file extension string (no dot) + @return: String + + """ + return ExtensionRegister().FileTypeFromExt(ext) + +def _RegisterExtensionHandler(xml_obj): + """Register an ExtensionHandler with this module. + @todo: this is a temporary hack till what to do with the language id's + is decided. + + """ + # Create an ID value for the lang id string + langId = xml_obj.GetLangId() + rid = RegisterNewLangId(langId, xml_obj.GetLanguage()) + setattr(synglob, langId, rid) + setattr(synglob, langId[3:], xml_obj.GetLanguage()) + + # Register file extensions with extension register + ExtensionRegister().Associate(xml_obj.GetLanguage(), + u" ".join(xml_obj.FileExtensions)) + + # Update static syntax id list + if rid not in SYNTAX_IDS: + SYNTAX_IDS.append(rid) + + return rid diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synxml.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synxml.py new file mode 100644 index 0000000..40fe7b5 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/syntax/synxml.py @@ -0,0 +1,823 @@ +# -*- coding: utf-8 -*- +############################################################################### +# Name: synxml.py # +# Purpose: Syntax Mode Xml Interface # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2009 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" Interface for extending language support through the use of xml files + +@summary: EditraXml Implementation + +""" + +xml_spec = """ +<editra version="1"> + <syntax language="Python" lexer="STC_LEX_PYTHON" id="ID_LANG_PYTHON"> + + <associations value="py pyw"/> + + <keywordlist> + <keywords value="0"> + if else elif for while in + </keywords> + <keywords value="1"> + str len setattr getattr + </keywords> + </keywordlist> + + <syntaxspeclist> + <syntaxspec value="STC_P_DEFAULT" tag="default_style"/> + <syntaxspec value="STC_P_WORD" tag="keyword_style"/> + </syntaxspeclist> + + <propertylist> + <property value="fold" enable="1"/> + <property value="tab.timmy.whinge.level" enable="1"/> + </propertylist> + + <commentpattern value="#"/> + + <featurelist> + <feature method="AutoIndenter" source="myextension.py"/> + <!-- <feature method="StyleText" source="myextension.py"/> --> + </featurelist> + + </syntax> + +</editra> + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: synxml.py 68814 2011-08-21 17:10:03Z CJP $" +__revision__ = "$Revision: 68814 $" + +#----------------------------------------------------------------------------# +# Imports +import os +from xml import sax + +# Workaround for building packages when wx is not available +try: + import wx.stc as stc +except ImportError: + pass + +#----------------------------------------------------------------------------# +# Tag Definitions +EXML_START = u"editra" +EXML_SYNTAX = u"syntax" +EXML_KEYWORDLIST = u"keywordlist" +EXML_KEYWORDS = u"keywords" +EXML_SYNSPECLIST = u"syntaxspeclist" +EXML_SYNTAXSPEC = u"syntaxspec" +EXML_PROPERTYLIST = u"propertylist" +EXML_PROPERTY = u"property" +EXML_COMMENTPAT = u"commentpattern" +EXML_FEATURELIST = u"featurelist" +EXML_FEATURE = u"feature" +EXML_ASSOCIATIONS = u"associations" + +# Attributes +EXML_ENABLE = u"enable" +EXML_LANG = u"language" +EXML_LEXER = u"lexer" +EXML_METHOD = u"method" +EXML_SOURCE = u"source" +EXML_TAG = u"tag" +EXML_VALUE = u"value" +EXML_VERSION = u"version" +EXML_NAME = u"name" +EXML_ID = u"id" + +#----------------------------------------------------------------------------# + +class EditraXml(sax.ContentHandler): + """Base class for all Editra syntax xml objects""" + def __init__(self, path=None): + sax.ContentHandler.__init__(self) + + # Attributes + self.name = u'' # Tag name + self.level = 0 # Set the level of the element + self.indent = 3 # Indentation + self.path = path + self._ok = False # Did the object load correctly + + self._context = None # Current parse context + self._reg_handler = dict() # Registered parse handlers + + def __eq__(self, other): + return self.GetXml() == other.GetXml() + + def __str__(self): + return self.GetXml() + + #---- Internal Parser Api ----# + + def startElement(self, name, attrs): + if self._context is not None: + # Delegate to current context + self._context.startElement(name, attrs) + elif name in self._reg_handler: + self._context = self._reg_handler.get(name) + self._context.startElement(name, attrs) + else: + # Unknown tag + # raise? + pass + + def endElement(self, name): + if self._context is not None: + if self._context.Name == name: + self._context = None + else: + # Delegate to registered handler + self._context.endElement(name) + else: + # Unknown tag ending + pass + + def characters(self, chars): + if not chars.isspace(): + if self._context is not None: + self._context.characters(chars) + else: + # No current context or context is self + pass + + def GetXml(self): + """Get the xml representation of this object + @return: string + + """ + ident = self.GetIndentationStr() + xml = ident + self.GetStartTag() + xml += (self.GetSubElements() + os.linesep) + xml += (ident + self.GetEndTag()) + return xml + + def GetSubElements(self): + """Get the sub elements + @return: string + + """ + xml = u'' + for handler in self.GetHandlers(): + handler.SetLevel(self.Level + 1) + xml += (os.linesep + handler.GetXml()) + return xml + + def GetStartTag(self): + """Get the opening tag + @return: string + + """ + return u"<%s>" % self.name + + def GetEndTag(self): + """Get the closing tag + @return: string + + """ + return u"</%s>" % self.name + + def LoadFromDisk(self): + """Load the object from from disk + @precondition: path has been set + @return: bool + @todo: set error state on failed loads + + """ + assert self.path is not None, "Must SetPath before calling Load" + try: + sax.parse(self.path, self) + except (sax.SAXException, OSError, IOError, UnicodeDecodeError): + self._ok = False + return False + else: + self._ok = True + return True + + def LoadFromString(self, txt): + """Load and initialize the object from an xml string + @param txt: string + + """ + sax.parseString(txt, self) + + #---- External Api ----# + + @property + def Context(self): + return self._context + + @property + def Indentation(self): + return self.indent + + @property + def Level(self): + return self.level + + @property + def Name(self): + return self.name + + @property + def Ok(self): + return self.IsOk() + + def GetHandler(self, tag): + """Get the handler associated with the given tag + @param tag: string + @return: EditraXml object or None + + """ + return self._reg_handler.get(tag, None) + + def GetHandlers(self): + """Get all the handlers registered with this element + @return: list of EditraXml objects + + """ + return self._reg_handler.values() + + def GetIndentation(self): + """Get the indentation string + @return: int + + """ + return self.indent + + def GetIndentationStr(self): + """Get the indentation string taking level into consideration + @return: string + + """ + return (self.indent * u" ") * self.level + + def GetLevel(self): + """Get the level of this element + @return: int + + """ + return self.level + + def GetName(self): + """Get the tag name for the handler + @return: string + + """ + return self.name + + def GetPath(self): + """Get the xml files path + @return: string + + """ + return self.path + + def IsOk(self): + """Did the object load from file correctly? + return: bool + + """ + return self._ok + + def RegisterHandler(self, handler): + """Register a handler for a tag. Parsing will be delegated to the + the registered handler until its end tag is encountered. + @param handler: EditraXml instance + + """ + tag = handler.GetName() + assert tag not in self._reg_handler, "%s already registered!" % tag + handler.SetLevel(self.Level + 1) + self._reg_handler[tag] = handler + + def SetIndentation(self, indent): + """Set the indentation level + @param indent: int + + """ + self.indent = indent + + def SetLevel(self, level): + """Set the level of this element + @param level: int + + """ + self.level = level + + def SetName(self, tag): + """Set this handlers tag name used for identifying the open and + end tags. + @param tag: string + + """ + self.name = tag + + def SetPath(self, path): + """Set the path to load this element from + @param path: path + + """ + self.path = path + +#----------------------------------------------------------------------------# + +class SyntaxModeHandler(EditraXml): + """Main Xml interface to extending filetype handling support""" + def __init__(self, path=None): + EditraXml.__init__(self, path) + + # Attributes + self._start = False + self._version = 0 + self.syntax = Syntax() + + # Setup + self.SetName(EXML_START) + self.SetIndentation(3) + self.RegisterHandler(self.syntax) + + def startElement(self, name, attrs): + if self._start: + EditraXml.startElement(self, name, attrs) + elif name == EXML_START: + self._version = int(attrs.get(EXML_VERSION, 0)) + self._start = True + + def endElement(self, name): + if name == EXML_START: + self._start = False + else: + EditraXml.endElement(self, name) + + def GetStartTag(self): + return u"<%s version=\"%s\">" % (self.GetName(), self.Version) + + #---- Get External Api ----# + + # Properties + @property + def CommentPattern(self): + return self.GetCommentPattern() + + @property + def FileExtensions(self): + return self.GetFileExtensions() + + @property + def Keywords(self): + return self.GetKeywords() + + @property + def LangId(self): + return self.GetLangId() + + @property + def Lexer(self): + return self.GetLexer() + + @property + def Properties(self): + return self.GetProperties() + + @property + def SyntaxSpec(self): + return self.GetSyntaxSpec() + + @property + def Version(self): + return self._version + + # Getters + def GetCommentPattern(self): + """Get the comment pattern list + @return: list of strings + + """ + return self.syntax.GetCommentPattern() + + def GetFileExtensions(self): + """Get the list of associated file extensions + @return: list of strings + + """ + return self.syntax.GetFileExtensions() + + def GetKeywords(self): + """Get the keyword list + @return: list of tuples [(idx, ['word', 'word2',]),] + + """ + kwxml = self.syntax.GetKeywordXml() + return kwxml.GetKeywords() + + def GetFeatureFromXml(self, fet): + """Get the callable associated with the given feature + @param fet: string + @return: string + + """ + fetxml = self.syntax.GetFeatureXml() + return fetxml.GetFeature(fet) + + def GetSyntaxSpec(self): + """Get the syntax spec + @return: list of tuples [(style_id, "style_tag")] + + """ + spxml = self.syntax.GetSyntaxSpecXml() + return spxml.GetStyleSpecs() + + def GetLangId(self): + """Get the language id string + @return: str "ID_LANG_" + + """ + return self.syntax.GetLangId() + + def GetLanguage(self): + """Get the language name string + @return: string + + """ + return self.syntax.GetLanguage() + + def GetLexer(self): + """Get the lexer id + @return: wx.stc.STC_LEX_ + + """ + return self.syntax.GetLexer() + + def GetProperties(self): + """Get the property defs + @return: list of tuples [("fold", "1"),] + + """ + propxml = self.syntax.GetPropertiesXml() + return propxml.GetProperties() + +#----------------------------------------------------------------------------# + +class Syntax(EditraXml): + """Syntax definition for initializing a Scintilla Lexer""" + def __init__(self): + EditraXml.__init__(self) + + # Attributes + self.language = u"Plain Text" + self.langid = u"ID_LANG_TXT" + self.lexstr = u"STC_LEX_NULL" + self.lexer = stc.STC_LEX_NULL + self.file_ext = list() + + # Sub Xml Objects + self.keywords = KeywordList() + self.synspec = SyntaxSpecList() + self.props = PropertyList() + self.features = FeatureList() + self.comment = list() + + # Setup + self.SetName(EXML_SYNTAX) + self.RegisterHandler(self.keywords) + self.RegisterHandler(self.synspec) + self.RegisterHandler(self.props) + self.RegisterHandler(self.features) + + def startElement(self, name, attrs): + """Parse the Syntax Xml""" + if name == EXML_COMMENTPAT: + val = attrs.get(EXML_VALUE, '') + tmp = val.split() + # Trailing space may be significant for some comments + if len(tmp) == 1: + comment = [val,] + else: + comment = tmp + self.comment = comment + elif name == EXML_ASSOCIATIONS: + self.file_ext = attrs.get(EXML_VALUE, '').split() + elif name == self.Name: + lang = attrs.get(EXML_LANG, u"Plain Text") + langid = attrs.get(EXML_ID, u"ID_LANG_TXT") + assert langid.startswith(u"ID_LANG_"), "id must start with ID_LANG_" + lexer = attrs.get(EXML_LEXER, 'STC_LEX_NULL') + lexval = getattr(stc, lexer, None) + assert lexval is not None, "Invalid Lexer: %s" % lexer + self.language = lang + self.langid = langid + self.lexstr = lexer + self.lexer = lexval + else: + EditraXml.startElement(self, name, attrs) + + def GetStartTag(self): + """Get the syntax opening tag and attributes""" + return u"<%s %s=\"%s\" %s=\"%s\" %s=\"%s\">" % (self.Name, EXML_LANG, + self.language, EXML_LEXER, + self.lexstr, EXML_ID, + self.langid) + + def GetSubElements(self): + """Get the SubElements xml string + @return: string + + """ + xml = EditraXml.GetSubElements(self) + ident = self.GetIndentationStr() + (self.Indentation * u" ") + xml += os.linesep + cpat = u" ".join(self.GetCommentPattern()) + comment = u"<%s %s=\"%s\"/>" % (EXML_COMMENTPAT, EXML_VALUE, cpat.strip()) + xml += os.linesep + xml += (ident + comment) + xml += os.linesep + fileext = u"<%s %s=\"%s\"/>" % (EXML_ASSOCIATIONS, EXML_VALUE, u" ".join(self.file_ext)) + xml += (ident + fileext) + return xml + + #---- External Api ----# + + def GetCommentPattern(self): + """Get the comment pattern + @return: list of strings ["/*", "*/"] + + """ + return self.comment + + def GetFeatureXml(self): + """Get the FeatureList xml object""" + return self.features + + def GetFileExtensions(self): + """Get the list of associated file extensions""" + return self.file_ext + + def GetKeywordXml(self): + """Get the Keyword Xml object""" + return self.keywords + + def GetLanguage(self): + """Get the language description/name + @return: string + + """ + return self.language + + def GetLangId(self): + """Get the language id + @return: string + + """ + return self.langid + + def GetLexer(self): + """Get the lexer to use for this language + @return: stc.STC_LEX_FOO + + """ + return self.lexer + + def GetSyntaxSpecXml(self): + """Get the Syntax Spec Xml object""" + return self.synspec + + def GetPropertiesXml(self): + """Get the properties xml object""" + return self.props + +#----------------------------------------------------------------------------# + +class KeywordList(EditraXml): + """Container object for all keyword sets""" + def __init__(self): + EditraXml.__init__(self) + + # Attributes + self._current = None + self._keywords = dict() # { index : word_list } + + # Setup + self.SetName(EXML_KEYWORDLIST) + + def startElement(self, name, attrs): + if name == EXML_KEYWORDS: + idx = attrs.get(EXML_VALUE, None) + assert idx is not None, "value attribute not set" + idx = int(idx) + assert idx not in self._keywords, "Duplicate index set %d" % idx + self._keywords[idx] = list() + self._current = self._keywords[idx] + else: + pass + + def endElement(self, name): + if name == EXML_KEYWORDS: + self._current = None + + def characters(self, chars): + chars = chars.strip().split() + if self._current is not None: + if len(chars): + self._current.extend(chars) + + def GetSubElements(self): + """Get the keyword list elements""" + xml = u"" + tag = u"<%s %s=" % (EXML_KEYWORDS, EXML_VALUE) + tag += "\"%s\">" + end = u"</%s>" % EXML_KEYWORDS + ident = self.GetIndentationStr() + (self.Indentation * u" ") + for key in sorted(self._keywords.keys()): + xml += os.linesep + ident + xml += (tag % key) + xml += os.linesep + ident + words = (self.Indentation * u" ") + u" ".join(self._keywords[key]) + xml += words + xml += os.linesep + ident + xml += end + return xml + + #---- External Api ----# + + def GetKeywords(self): + """Get the list of keyword strings + @return: sorted list of tuples [(kw_idx, [word1, word2,])] + + """ + keys = sorted(self._keywords.keys()) + keywords = [ (idx, self._keywords[idx]) for idx in keys ] + keywords.sort(key=lambda x: x[0]) + return keywords + + def GetKeywordList(self, idx): + """Get the list of keywords associated with the given index + @return: list of strings + + """ + return self._keywords.get(idx, None) + +#----------------------------------------------------------------------------# + +class SyntaxSpecList(EditraXml): + """Container element for holding the syntax specification elements""" + def __init__(self): + EditraXml.__init__(self) + + # Attributes + self._specs = list() + + # Setup + self.SetName(EXML_SYNSPECLIST) + + def startElement(self, name, attrs): + """Parse all syntaxspec elements in the list""" + if name == EXML_SYNTAXSPEC: + lid = attrs.get(EXML_VALUE, '') + assert len(lid), "Style Id not specified" + if lid.isdigit(): + style_id = int(lid) + else: + # Scintilla Value + style_id = getattr(stc, lid, None) + assert style_id is not None, "Invalid STC Value: %s" % lid + assert isinstance(style_id, int), "Invalid ID: %s" % lid + + self._specs.append((style_id, attrs.get(EXML_TAG, 'default_style'))) + else: + # Unknown Tag + # Raise? + pass + + def GetSubElements(self): + """Get the xml for all the syntax spec elements""" + xml = u"" + tag = u"<%s %s=" % (EXML_SYNTAXSPEC, EXML_VALUE) + tag += ("\"%s\" " + EXML_TAG + "=\"%s\"/>") + ident = self.GetIndentationStr() + (self.Indentation * u" ") + for spec in self._specs: + xml += os.linesep + ident + xml += (tag % spec) + return xml + + #---- External Api ----# + + def GetStyleSpecs(self): + """Get the list of keyword strings + @return: list of tuples [(style_id, "style_tag"),] + + """ + return self._specs + +#----------------------------------------------------------------------------# + +class PropertyList(EditraXml): + """Container class for the syntax properties""" + def __init__(self): + EditraXml.__init__(self) + + # Attributes + self.properties = list() + + # Setup + self.SetName(EXML_PROPERTYLIST) + + def startElement(self, name, attrs): + if name == EXML_PROPERTY: + prop = attrs.get(EXML_VALUE, '') + if prop: + enable = attrs.get(EXML_ENABLE, '0') + self.properties.append((prop, enable)) + else: + pass + + def GetSubElements(self): + xml = u"" + tag = u"<%s %s=" % (EXML_PROPERTY, EXML_VALUE) + tag += ("\"%s\" " + EXML_ENABLE + "=\"%s\"/>") + ident = self.GetIndentationStr() + (self.Indentation * u" ") + for prop in self.properties: + xml += os.linesep + ident + xml += (tag % prop) + return xml + + #---- External Api ----# + + def GetProperties(self): + """Get the list of properties + @return: list of tuples [("property", "1")] + + """ + return self.properties + +#----------------------------------------------------------------------------# + +class FeatureList(EditraXml): + """Container for all other misc syntax features. + Currently Available Features: + - AutoIndent + - StyleText + + """ + def __init__(self): + EditraXml.__init__(self) + + # Attributes + self._features = dict() + + # Setup + self.SetName(EXML_FEATURELIST) + + def startElement(self, name, attrs): + if name == EXML_FEATURE: + meth = attrs.get(EXML_METHOD, None) + assert meth is not None, "method not defined" + mod = attrs.get(EXML_SOURCE, None) + assert mod is not None, "source not defined" + + self._features[meth] = mod + else: + EditraXml.startElement(self, name, attrs) + + def GetSubElements(self): + xml = u"" + tag = u"<%s %s=" % (EXML_FEATURE, EXML_METHOD) + tag += ("\"%s\" " + EXML_SOURCE + "=\"%s\"/>") + ident = self.GetIndentationStr() + (self.Indentation * u" ") + for feature in self._features.iteritems(): + xml += (os.linesep + ident) + xml += (tag % feature) + return xml + + #---- External Api ----# + + def GetFeature(self, fet): + """Get the callable feature by name + @param fet: string (module name) + + """ + feature = None + src = self._features.get(fet, None) + if src is not None: + feature = src + return feature + +#----------------------------------------------------------------------------# + +def LoadHandler(path): + """Load and initialize a SyntaxModeHandler from an on disk xml config file + @param path: path to an EditraXml file to load a handler from + @return: SyntaxModeHandler instance + + """ + synmode = SyntaxModeHandler(path) + synmode.LoadFromDisk() + return synmode diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/updater.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/updater.py new file mode 100644 index 0000000..f33520d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/updater.py @@ -0,0 +1,718 @@ +############################################################################### +# Name: updater.py # +# Purpose: UI and services for checking update status and downloading updates # +# for Editra. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +Provides controls/services that are used in checking and downloading updates +for the editor if they are available. The main control exported by this module +is the L{UpdateProgress} bar it displays the progress of the network action and +provides a higher level interface into the L{UpdateService}. + +@summary: Utilities and controls for updating Editra +@todo: This module could benefit from a bit of a re-write... + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: updater.py 66703 2011-01-17 23:07:45Z CJP $" +__revision__ = "$Revision: 66703 $" + +#--------------------------------------------------------------------------# +# Dependencies +import os +import sys +import stat +import re +import urllib2 +import threading +import wx +import wx.lib.delayedresult as delayedresult + +# Editra Libraries +import ed_glob +import ed_event +from profiler import CalcVersionValue, Profile_Get +import util +import ebmlib + +#--------------------------------------------------------------------------# +# Globals +RE_VERSION = re.compile('<\s*span id\="VERSION"[^>]*>(.*?)<\s*/span\s*>') +RE_CURL = re.compile('<\s*a id\="CURRENT"\s*href=\"(.*?)\"[^>]*>.*?<\s*/a\s*>') +DL_VERSION = ed_glob.HOME_PAGE + "/version.php" +DL_REQUEST = ed_glob.HOME_PAGE + "/e_update.php?dist=%s" +DL_LIN = 'SRC' # This may need to change in future +DL_MAC = 'Macintosh' +DL_SRC = 'SRC' +DL_WIN = 'Windows' +ISBIN = hasattr(sys, 'frozen') + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# + +class UpdateService(object): + """Defines an updater service object for Editra""" + def __init__(self): + """Initializes the Updater Object""" + super(UpdateService, self).__init__() + self._abort = False + self._progress = (0, 100) + + def __GetUrlHandle(self, url): + """Gets a file handle for the given url. The caller is responsible for + closing the handle. + @requires: network connection + @param url: url to get page from + @return: all text from the given url + + """ + h_file = None + try: + if Profile_Get('USE_PROXY', default=False): + proxy_set = Profile_Get('PROXY_SETTINGS', + default=dict(uname='', url='', + port='80', passwd='')) + + proxy = util.GetProxyOpener(proxy_set) + h_file = proxy.open(url) + else: + h_file = urllib2.urlopen(url) + + finally: + return h_file + + def Abort(self): + """Cancel any pending or in progress actions. + @postcondition: any download actions will be aborted + + """ + self._abort = True + + def GetCurrFileURL(self): + """Returns the url for the current version of the program + for the current operating system, by requesting the data from + project homepage. + @requires: active network connection + @return: url of latest available program version + + """ + if wx.Platform == '__WXGTK__': + dist = DL_LIN + elif wx.Platform == '__WXMAC__' and ISBIN: + dist = DL_MAC + elif wx.Platform == '__WXMSW__' and ISBIN: + dist = DL_WIN + else: + dist = DL_SRC + + url = self.GetPageText(DL_REQUEST % dist) + url = re.findall(RE_CURL, url) + if len(url): + url = url[0] + else: + url = wx.EmptyString + + return url.strip() + + def GetCurrFileName(self): + """Returns the name of the file that is currently available for + download as a string. + @return: name of currently available file without url + + """ + url = self.GetCurrFileURL() + return url.split(u'/')[-1] + + def GetCurrentVersionStr(self): + """Parses the project website front page for the most + recent version of the program. + @requires: network connection + @return: version number of latest available program + + """ + page = self.GetPageText(ed_glob.HOME_PAGE + "/version.php?check=True") + found = re.findall(RE_VERSION, page) + if len(found): + return found[0] # Should be the first/only match found + else: + util.Log("[updater][warn] UpdateService.GetCurrentVersionStr " + "Failed to get version info.") + # TODO: GetTranslation is not threadsafe!!! + return "Unable to retrieve version info" + + def GetFileSize(self, url): + """Gets the size of a file by address + @param url: url to look up file on + @return: size of the file in bytes + + """ + size = 0 + try: + dl_file = self.__GetUrlHandle(url) + info = dl_file.info() + size = int(info['Content-Length']) + dl_file.close() + finally: + return size + + def GetPageText(self, url): + """Gets the text of a url + @requires: network conection + @param url: url to get page from + @return: all text from the given url + + """ + text = u'' + try: + h_file = self.__GetUrlHandle(url) + text = h_file.read() + h_file.close() + finally: + return text + + def GetProgress(self): + """Returns the current progress/total tuple + @return: tuple of progress data + + """ + return self._progress + + def GetUpdateFiles(self, dl_to=wx.GetHomeDir()): + """Gets the requested version of the program from the website + if possible. It will download the current files for the host system to + location (dl_to). On success it returns True, otherwise it returns + false. + @keyword dl_to: where to download the file to + + """ + # Check version to see if update is needed + # Dont allow update if files are current + verpat = re.compile('[0-9]+\.[0-9]+\.[0-9]+') + current = self.GetCurrentVersionStr() + if not re.match(verpat, current): + return False + + if CalcVersionValue(ed_glob.VERSION) < CalcVersionValue(current): + dl_path = self.GetCurrFileURL() + dl_file = dl_path.split('/')[-1] + dl_to = ebmlib.GetUniqueName(dl_to, dl_file) + blk_sz = 4096 + read = 0 + try: + # Download the file in chunks so it can be aborted if need be + # inbetween reads. + webfile = self.__GetUrlHandle(dl_path) + fsize = int(webfile.info()['Content-Length']) + locfile = open(dl_to, 'wb') + while read < fsize and not self._abort: + locfile.write(webfile.read(blk_sz)) + read += blk_sz + self.UpdaterHook(int(read/blk_sz), blk_sz, fsize) + + locfile.close() + webfile.close() + finally: + self._abort = False + if os.path.exists(dl_to) and \ + os.stat(dl_to)[stat.ST_SIZE] == fsize: + return True + else: + return False + else: + return False + + def UpdaterHook(self, count, block_sz, total_sz): + """Updates the progress tuple of (amount_done, total) on + each iterative call during the download. + @param count: number of blocks fetched + @param block_sz: size of download blocks + @param total_sz: total size of file to be downloaded + + """ + done = count * block_sz + if done > total_sz: + done = total_sz + self._progress = (done, total_sz) + +#-----------------------------------------------------------------------------# + +class UpdateThread(threading.Thread): + """Thread for checking for updates""" + def __init__(self, parent, jobId): + """Create the thread object + @param parent: parent window to post event to after completion + @param jobId: job identification id will be set as event id on finish + + """ + super(UpdateThread, self).__init__() + + # Attributes + self.parent = parent + self.id = jobId + + def run(self): + """Run the update check job""" + service = UpdateService() + result = service.GetCurrentVersionStr() + if result.replace('.', '').isdigit(): + isupdate = CalcVersionValue(result) > CalcVersionValue(ed_glob.VERSION) + else: + isupdate = False + + evt = ed_event.NotificationEvent(ed_event.edEVT_NOTIFY, + self.id, (isupdate, result)) + wx.PostEvent(self.parent, evt) + +#-----------------------------------------------------------------------------# + +class UpdateProgress(wx.Gauge, UpdateService): + """Creates a progress bar that is controlled by the UpdateService""" + ID_CHECKING = wx.NewId() + ID_DOWNLOADING = wx.NewId() + ID_TIMER = wx.NewId() + + def __init__(self, parent, id_, range_=100, + style=wx.GA_HORIZONTAL | wx.GA_PROGRESSBAR): + """Initiliazes the bar in a disabled state.""" + wx.Gauge.__init__(self, parent, id_, range_, style=style) + UpdateService.__init__(self) + + #---- Attributes ----# + self.LOG = wx.GetApp().GetLog() + self._checking = False + self._downloading = False + self._dl_result = False + self._mode = 0 + self._status = _("Status Unknown") + self._timer = wx.Timer(self, id=self.ID_TIMER) + + #---- Layout ----# + if wx.Platform == '__WXMAC__': + self.SetWindowVariant(wx.WINDOW_VARIANT_LARGE) + + #---- Bind Events ----# + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(wx.EVT_TIMER, self.OnUpdate, id = self.ID_TIMER) + + # Disable bar till caller is ready to use it + self.Disable() + + def OnDestroy(self, evt): + """Cleans up when the control is destroyed + @postcondition: if timer is running it is stopped before deletion + + """ + if evt.GetId() == self.GetId(): + if self._timer.IsRunning(): + self.LOG("[updater][info]UpdateProgress: __del__, stopped timer") + self._timer.Stop() + evt.Skip() + + def Abort(self): + """Overides the UpdateService abort function + @postcondition: any download actions in the L{UpdateService} are aborted + + """ + self.LOG("[updater][info] UpdateProgress: Download aborted") + UpdateService.Abort(self) + if self._timer.IsRunning(): + self._timer.Stop() + self.SetValue(0) + + def CheckForUpdates(self): + """Checks for updates and activates the bar. In order to keep the + UI from freezing while checking for updates the actual work is carried + out on another thread. When the thread exits it will set the _checking + attribute to false and set the _status attribute (See GetStatus) to the + return value of the check function which is either a version string or + an appropriate error message. + + @see: L{_UpdatesCheckThread} + + """ + # Set bar to Checking mode so it knows to simulate update progress + self._mode = self.ID_CHECKING + self.SetValue(0) + self.Start(10) + self._checking = True + delayedresult.startWorker(self._ResultNotifier, + self._UpdatesCheckThread, + jobID=self.ID_CHECKING) + + def DownloadUpdates(self, dl_loc=wx.EmptyString): + """Downloads available updates and configures the bar. + Returns True if the update was successfull or False if + it was not. The updates will be downloaded to the + specified location or to the Users Desktop or Home + Folder if no location is specified. + @keyword dl_loc: location to download file to + + """ + self.LOG("[updater][info] UpdateProgress: Download Starting...") + if dl_loc == wx.EmptyString: + dl_loc = self.GetDownloadLocation() + self._mode = self.ID_DOWNLOADING + self.SetValue(0) + self.Start(50) #XXX Try this for starters + self._downloading = True # Mark the work status as busy + delayedresult.startWorker(self._ResultNotifier, self._DownloadThread, + wargs=dl_loc, jobID=self.ID_DOWNLOADING) + + def GetDownloadResult(self): + """Returns the status of the last download action. Either + True for success or False for failure. + @return: whether last download was successfull or not + + """ + return self._dl_result + + def GetDownloadLocation(self): + """Returns the path that the file will be downloaded to. + Currently will either return the users Desktop path or the + users home directory in the case that there is no deskop directory + @return: path to download file + + """ + dl_loc = wx.GetHomeDir() + os.sep + if os.path.exists(dl_loc + u"Desktop"): + dl_loc = dl_loc + u"Desktop" + os.sep + return dl_loc + + def GetMode(self): + """Returns the current mode of operation or 0 if the bar + is currently inactive. + @return: mode of operation for the progres bar + + """ + return self._mode + + def GetStatus(self): + """Returns the status attribute string + @return: status set by any update actions + + """ + return self._status + + def GetUpdatesAvailable(self): + """Compares the status against the version of the running + program to see if updates are available. It is expected + that CheckForUpdates has been called prior to calling this + function. Returns True if Available and False otherwise. + @return: whether udpates are available or not + + """ + if self._status[0].isdigit(): + return CalcVersionValue(self._status) > CalcVersionValue(ed_glob.VERSION) + else: + return False + + def IsDownloading(self): + """Returns a bool stating whether there is a download + in progress or not. + @return: whether downloading is active or not + + """ + return self._downloading + + def OnUpdate(self, evt): + """Timer Event Handler Updates the progress bar + on each cycle of the timer + @param evt: event that called this handler + + """ + mode = self.GetMode() + if mode not in (self.ID_CHECKING, self.ID_DOWNLOADING): + return + + progress = self.GetProgress() + prange = self.GetRange() + if mode == self.ID_CHECKING: + # Simulate updates + if progress[0] < prange: + self.UpdaterHook(progress[0] + 1, 1, 90) + progress = self.GetProgress() + if not self._checking and progress[0] >= prange: + self.Stop() + + if mode == self.ID_DOWNLOADING: + if not self._downloading and progress[0] >= prange: + self.Stop() + + # Update Range if need be + if prange != progress[1]: + self.SetRange(progress[1]) + + # Update Progress + if progress[0] < progress[1]: + self.SetValue(progress[0]) + elif progress[0] == progress[1]: + self.Pulse() + else: + pass + + def Start(self, msec=100): + """Starts the progress bar and timer if not already active + @keyword msec: pulse time for clock in milliseconds + + """ + if not self._timer.IsRunning(): + self.LOG('[updater][info] UpdateProgress: Starting Timer') + self.Enable() + self.SetValue(0) + self._timer.Start(msec) + else: + pass + + def Stop(self): + """Stops the progress bar + @postcondition: progress bar is stopped + + """ + if self._timer.IsRunning(): + self.LOG('[updater][info] UpdateProgress: Stopping Clock') + self._timer.Stop() + self._mode = 0 + self.SetValue(self.GetRange()) + else: + pass + self.Enable(False) + + def Pulse(self): + if self._mode == 0: + return + super(UpdateProgress, self).Pulse() + + #--- Protected Member Functions ---# + def _DownloadThread(self, *args): + """Processes the download and checks that the file has been downloaded + properly. Then returns either True if the download was successful or + False if it failed in some way. + @return: success status of download + + """ + dl_ok = self.GetUpdateFiles(u"".join(args)) + return dl_ok + + def _ResultNotifier(self, delayedResult): + """Receives the return from the result of the worker thread and + notifies the interested party with the result. + @param delayedResult: value from worker thread + + """ + jid = delayedResult.getJobID() + try: + self.LOG("[updater][info] UpdateProgress: Worker thread exited. ID = %d" % jid) + self._checking = self._downloading = False # Work has finished + except wx.PyDeadObjectError: + return + + try: + if jid == self.ID_CHECKING: + mevt = ed_event.UpdateTextEvent(ed_event.edEVT_UPDATE_TEXT, \ + self.ID_CHECKING) + wx.PostEvent(self.GetParent(), mevt) + self.SetValue(self.GetRange()) + elif jid == self.ID_DOWNLOADING: + result = delayedResult.get() + self._dl_result = result + else: + pass + except (OSError, IOError, UnicodeDecodeError), msg: + self.LOG("[updater][err] UpdateProgress: Error on thread exit") + self.LOG("[updater][err] UpdateProgress: error = %s" % str(msg)) + + def _UpdatesCheckThread(self): + """Sets internal status value to the return value from calling + GetCurrentVersionStr. This function is called on a separate thread + in the CheckForUpdates function to allow the ui to update properly + while this function waits for the result from the network. Returns + True to the consumer if updates are available and false if they + are not or status is unknown. + @return: whether updates are available or not + + """ + self.LOG("[updater][info] UpdateProgress: Checking for updates") + self._checking = True + ret = self.GetCurrentVersionStr() + self._status = ret + self.LOG("[updater][info] UpdateProgress: Check Finished: result = " + ret) + if ret[0].isdigit() and \ + CalcVersionValue(ret) > CalcVersionValue(ed_glob.VERSION): + ret = True + else: + ret = False + return ret + +#-----------------------------------------------------------------------------# + +class DownloadDialog(wx.Frame): + """Creates a standalone download window + @todo: Status bar is sometimes not wide enough to display all data. + """ + ID_PROGRESS_BAR = wx.NewId() + ID_TIMER = wx.NewId() + SB_DOWNLOADED = 0 + SB_INFO = 1 + + def __init__(self, parent, id_, title, + style=wx.DEFAULT_DIALOG_STYLE | wx.MINIMIZE_BOX): + """Creates a standalone window that is used for downloading + updates for the editor. + @param parent: Parent Window of the dialog + @param title: Title of dialog + + """ + super(DownloadDialog, self).__init__(parent, id_, title, style=style) + util.SetWindowIcon(self) + + #---- Attributes/Objects ----# + self.LOG = wx.GetApp().GetLog() + panel = wx.Panel(self) + self._progress = UpdateProgress(panel, self.ID_PROGRESS_BAR) + fname = self._progress.GetCurrFileName() + floc = self._progress.GetDownloadLocation() + dl_file = wx.StaticText(panel, label=_("Downloading: %s") % fname) + dl_loc = wx.StaticText(panel, wx.ID_ANY, + _("Downloading To: %s") % floc) + self._cancel_bt = wx.Button(panel, wx.ID_CANCEL, _("Cancel")) + self._timer = wx.Timer(self, id=self.ID_TIMER) + self._proghist = list() + + #---- Layout ----# + self.CreateStatusBar(2) + self._sizer = wx.GridBagSizer() + bmp = wx.ArtProvider.GetBitmap(str(ed_glob.ID_WEB), wx.ART_TOOLBAR) + mdc = wx.MemoryDC(bmp) + tmp_bmp = wx.Image(ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.png", + wx.BITMAP_TYPE_PNG) + tmp_bmp.Rescale(20, 20, wx.IMAGE_QUALITY_HIGH) + mdc.DrawBitmap(tmp_bmp.ConvertToBitmap(), 11, 11) + mdc.SelectObject(wx.NullBitmap) + bmp = wx.StaticBitmap(panel, wx.ID_ANY, bmp) + self._sizer.AddMany([(bmp, (1, 1), (3, 2)), + (dl_file, (1, 4), (1, 4)), + (dl_loc, (2, 4), (1, 4)), + ((15, 15), (3, 5), (1, 1))]) + self._sizer.Add(self._progress, (4, 1), (1, 10), wx.EXPAND) + + bsizer = wx.BoxSizer(wx.HORIZONTAL) + bsizer.AddStretchSpacer() + bsizer.Add(self._cancel_bt, 0, wx.ALIGN_CENTER_HORIZONTAL) + bsizer.AddStretchSpacer() + + self._sizer.Add(bsizer, (6, 1), (1, 10), wx.EXPAND) + self._sizer.Add((5, 5), (7, 1)) + self._sizer.Add((5, 5), (7, 11)) + panel.SetSizer(self._sizer) + mwsz = wx.BoxSizer(wx.HORIZONTAL) + mwsz.Add(panel, 1, wx.EXPAND) + self.SetSizer(mwsz) + self.SetInitialSize() + + self.SetStatusWidths([-1, 100]) + self.SetStatusText(_("Downloading") + u"...", self.SB_INFO) + + #---- Bind Events ----# + self.Bind(wx.EVT_BUTTON, self.OnButton) + self.Bind(wx.EVT_CLOSE, self.OnClose) + self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy, self) + self.Bind(wx.EVT_TIMER, self.OnUpdate, id=self.ID_TIMER) + + def OnDestroy(self, evt): + """Cleans up on exit + @postcondition: if timer was running it is stopped + + """ + if evt.GetId() == self.GetId(): + if self._timer.IsRunning(): + self.LOG('[updater][info] DownloadDialog: __del__ Timer Stopped') + self._timer.Stop() + evt.Skip() + + def CalcDownRate(self): + """Calculates and returns the approximate download rate + in Kb/s + @return: current downlaod rate in Kb/s + @rtype: float + + """ + dlist = list() + last = 0 + for item in self._proghist: + val = item - last + dlist.append(val) + last = item + return round((float(sum(dlist) / len(self._proghist)) / 1024), 2) + + def OnButton(self, evt): + """Handles events that are generated when buttons are pushed. + @param evt: event that called this handler + + """ + e_id = evt.GetId() + if e_id == wx.ID_CANCEL: + self.LOG("[updater][evt] DownloadDialog: Cancel pressed") + self._progress.Abort() + self._cancel_bt.Disable() + self.SetStatusText(_("Canceled"), self.SB_INFO) + else: + evt.Skip() + + def OnClose(self, evt): + """Handles the window closer event + @param evt: event that called this handler + + """ + self.LOG("[updater][evt] DownloadDialog: Closing Download Dialog") + self._progress.Abort() + # Wait till thread has halted before exiting + while self._progress.IsDownloading(): + wx.YieldIfNeeded() + wx.GetApp().UnRegisterWindow(repr(self)) + evt.Skip() + + def OnUpdate(self, evt): + """Updates the status text on each pulse from the timer + @param evt: event that called this handler + + """ + e_id = evt.GetId() + if e_id == self.ID_TIMER: + prog = self._progress.GetProgress() + self._proghist.append(prog[0]) + speed = self.CalcDownRate() + if self._progress.IsDownloading(): + self.SetStatusText(_("Rate: %.2f Kb/s") % speed, + self.SB_DOWNLOADED) + else: + self.LOG("[updater][evt] DownloadDialog:: Download finished") + self.SetStatusText(u'', self.SB_DOWNLOADED) + if self._progress.GetDownloadResult(): + self.LOG("[updater][info] DownloadDialog: Download Successful") + self.SetStatusText(_("Finished"), self.SB_INFO) + else: + self.LOG("[updater][info] DownloadDialog: Download Failed") + self.SetStatusText(_("Failed"), self.SB_INFO) + self._progress.Enable() + self._progress.SetValue(self._progress.GetProgress()[0]) + self._timer.Stop() + self._cancel_bt.Disable() + else: + evt.Skip() + + def Show(self): + """Shows the Dialog and starts downloading the updates + @postcondition: window is registered with mainloop and shown on screen + @todo: Allow setting of download location to be set when shown + + """ + # Tell the main loop we are busy + wx.GetApp().RegisterWindow(repr(self), self, True) + self._timer.Start(1000) # One pulse every second + self._progress.DownloadUpdates() + super(DownloadDialog, self).Show() diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/util.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/util.py new file mode 100644 index 0000000..12e000a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/util.py @@ -0,0 +1,791 @@ +############################################################################### +# Name: util.py # +# Purpose: Misc utility functions used through out Editra # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +This file contains various helper functions and utilities that the program uses. + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: util.py 72623 2012-10-06 19:33:06Z CJP $" +__revision__ = "$Revision: 72623 $" + +#--------------------------------------------------------------------------# +# Imports +import os +import sys +import mimetypes +import encodings +import codecs +import urllib2 +import wx + +# Editra Libraries +import ed_glob +import ed_event +import ed_crypt +import dev_tool +import syntax.syntax as syntax +import syntax.synglob as synglob +import ebmlib + +_ = wx.GetTranslation +#--------------------------------------------------------------------------# + +class DropTargetFT(wx.PyDropTarget): + """Drop target capable of accepting dropped files and text + @todo: has some issues with the clipboard on windows under certain + conditions. They are not fatal but need fixing. + + """ + def __init__(self, window, textcallback=None, filecallback=None): + """Initializes the Drop target + @param window: window to receive drop objects + @keyword textcallback: Callback for when text is dropped + @keyword filecallback: Callback for when file(s) are dropped + + """ + super(DropTargetFT, self).__init__() + + # Attributes + self.window = window + self._data = dict(data=None, fdata=None, tdata=None, + tcallb=textcallback, fcallb=filecallback) + self._tmp = None + self._lastp = None + + # Setup + self.InitObjects() + + def CreateDragString(self, txt): + """Creates a bitmap of the text that is being dragged + @todo: possibly set colors to match highlighting of text + @todo: generalize this to be usable by other widgets besides stc + + """ + if not isinstance(self.window, wx.stc.StyledTextCtrl): + return + + stc = self.window + txt = txt.split(stc.GetEOLChar()) + longest = (0, 0) + for line in txt: + ext = stc.GetTextExtent(line) + if ext[0] > longest[0]: + longest = ext + + cords = [ (0, x * longest[1]) for x in range(len(txt)) ] + try: + mdc = wx.MemoryDC(wx.EmptyBitmap(longest[0] + 5, + longest[1] * len(txt), 32)) + mdc.SetBackgroundMode(wx.TRANSPARENT) + mdc.SetTextForeground(stc.GetDefaultForeColour()) + mdc.SetFont(stc.GetDefaultFont()) + mdc.DrawTextList(txt, cords) + self._tmp = wx.DragImage(mdc.GetAsBitmap()) + except wx.PyAssertionError, msg: + Log("[droptargetft][err] %s" % str(msg)) + + def InitObjects(self): + """Initializes the text and file data objects + @postcondition: all data objects are initialized + + """ + self._data['data'] = wx.DataObjectComposite() + self._data['tdata'] = wx.TextDataObject() + self._data['fdata'] = wx.FileDataObject() + self._data['data'].Add(self._data['tdata'], True) + self._data['data'].Add(self._data['fdata'], False) + self.SetDataObject(self._data['data']) + + def OnEnter(self, x_cord, y_cord, drag_result): + """Called when a drag starts + @param x_cord: x cord of enter point + @param y_cord: y cord of enter point + @param drag_result: wxDrag value + @return: result of drop object entering window + + """ + # GetData seems to happen automatically on msw, calling it again + # causes this to fail the first time. + if wx.Platform in ['__WXGTK__', '__WXMSW__']: + return wx.DragCopy + + if wx.Platform == '__WXMAC__': + try: + self.GetData() + except wx.PyAssertionError: + return wx.DragError + + self._lastp = (x_cord, y_cord) + files = self._data['fdata'].GetFilenames() + text = self._data['tdata'].GetText() + if len(files): + self.window.SetCursor(wx.StockCursor(wx.CURSOR_COPY_ARROW)) + else: + self.CreateDragString(text) + return drag_result + + def OnDrop(self, x_cord=0, y_cord=0): + """Gets the drop cords + @keyword x_cord: x cord of drop object + @keyword y_cord: y cord of drop object + @todo: implement snapback when drop is out of range + + """ + self._tmp = None + self._lastp = None + return True + + def OnDragOver(self, x_cord, y_cord, drag_result): + """Called when the cursor is moved during a drag action + @param x_cord: x cord of mouse + @param y_cord: y cord of mouse + @param drag_result: Drag result value + @return: result of drag over + @todo: For some reason the caret position changes which can be seen + by the brackets getting highlighted. However the actual caret + is not moved. + + """ + stc = self.window + if self._tmp is None: + if hasattr(stc, 'DoDragOver'): + val = stc.DoDragOver(x_cord, y_cord, drag_result) + self.ScrollBuffer(stc, x_cord, y_cord) + drag_result = wx.DragCopy + else: + # A drag image was created + if hasattr(stc, 'DoDragOver'): + point = wx.Point(x_cord, y_cord) + self._tmp.BeginDrag(point - self._lastp, stc) + self._tmp.Hide() + stc.DoDragOver(x_cord, y_cord, drag_result) + self._tmp.Move(point) + self._tmp.Show() + self._tmp.RedrawImage(self._lastp, point, True, True) + self._lastp = point + self.ScrollBuffer(stc, x_cord, y_cord) + drag_result = wx.DragCopy + + return drag_result + + def OnData(self, x_cord, y_cord, drag_result): + """Gets and processes the dropped data + @param x_cord: x coordinate + @param y_cord: y coordinate + @param drag_result: wx Drag result value + @postcondition: dropped data is processed + + """ + self.window.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) + if self.window.HasCapture(): + self.window.ReleaseMouse() + + try: + data = self.GetData() + except wx.PyAssertionError: + wx.PostEvent(self.window.GetTopLevelParent(), \ + ed_event.StatusEvent(ed_event.edEVT_STATUS, -1, + _("Unable to accept dropped file " + "or text"))) + data = False + drag_result = wx.DragCancel + + if data: + files = self._data['fdata'].GetFilenames() + text = self._data['tdata'].GetText() + if len(files) > 0 and self._data['fcallb'] is not None: + self._data['fcallb'](files) + elif len(text) > 0: + if self._data['tcallb'] is not None: + self._data['tcallb'](text) + elif hasattr(self.window, 'DoDropText'): + self.window.DoDropText(x_cord, y_cord, text) + self.InitObjects() + return drag_result + + def OnLeave(self): + """Handles the event of when the drag object leaves the window + @postcondition: Cursor is set back to normal state + + """ + self.window.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) + if self.window.HasCapture(): + self.window.ReleaseMouse() + + if self._tmp is not None: + try: + self._tmp.EndDrag() + except wx.PyAssertionError, msg: + Log("[droptargetft][err] %s" % str(msg)) + + @staticmethod + def ScrollBuffer(stc, x_cord, y_cord): + """Scroll the buffer as the dragged text is moved towards the + ends. + @param stc: StyledTextCtrl + @param x_cord: int (x position) + @param y_cord: int (y position) + @note: currently does not work on wxMac + + """ + try: + cline = stc.PositionFromPoint(wx.Point(x_cord, y_cord)) + if cline != wx.stc.STC_INVALID_POSITION: + cline = stc.LineFromPosition(cline) + fline = stc.GetFirstVisibleLine() + lline = stc.GetLastVisibleLine() + if (cline - fline) < 2: + stc.ScrollLines(-1) + elif lline - cline < 2: + stc.ScrollLines(1) + else: + pass + except wx.PyAssertionError, msg: + Log("[droptargetft][err] ScrollBuffer: %s" % msg) + +#---- End FileDropTarget ----# + +class EdClipboard(ebmlib.CycleCache): + """Local clipboard object + @todo: make into a singleton + + """ + def GetNext(self): + """Get the next item in the cache""" + # Initialize the clipboard if it hasn't been loaded yet and + # there is something in the system clipboard + if self.GetCurrentSize() == 0: + txt = GetClipboardText() + if txt is not None: + self.Put(txt) + + return super(EdClipboard, self).GetNext() + + def IsAtIndex(self, txt): + """Is the passed in phrase at the current cycle index in the + cache. Used to check if index should be reset or to continue in + the cycle. + @param txt: selected text + + """ + pre = self.PeekPrev() + next = self.PeekNext() + if txt in (pre, next): + return True + else: + return False + + def Put(self, txt): + """Put some text in the clipboard + @param txt: Text to put in the system clipboard + + """ + pre = self.PeekPrev() + next = self.PeekNext() + if len(txt) and txt not in (pre, next): + self.PutItem(txt) + +#---- Misc Common Function Library ----# +# Used for holding the primary selection on mac/msw +FAKE_CLIPBOARD = None + +def GetClipboardText(primary=False): + """Get the primary selection from the clipboard if there is one + @return: str or None + + """ + if primary and wx.Platform == '__WXGTK__': + wx.TheClipboard.UsePrimarySelection(True) + elif primary: + # Fake the primary selection on mac/msw + global FAKE_CLIPBOARD + return FAKE_CLIPBOARD + else: + pass + + text_obj = wx.TextDataObject() + rtxt = None + + if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open(): + if wx.TheClipboard.GetData(text_obj): + rtxt = text_obj.GetText() + wx.TheClipboard.Close() + + if primary and wx.Platform == '__WXGTK__': + wx.TheClipboard.UsePrimarySelection(False) + return rtxt + +def SetClipboardText(txt, primary=False): + """Copies text to the clipboard + @param txt: text to put in clipboard + @keyword primary: Set txt as primary selection (x11) + + """ + # Check if using primary selection + if primary and wx.Platform == '__WXGTK__': + wx.TheClipboard.UsePrimarySelection(True) + elif primary: + # Fake the primary selection on mac/msw + global FAKE_CLIPBOARD + FAKE_CLIPBOARD = txt + return True + else: + pass + + data_o = wx.TextDataObject() + data_o.SetText(txt) + if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open(): + wx.TheClipboard.SetData(data_o) + wx.TheClipboard.Close() + if primary and wx.Platform == '__WXGTK__': + wx.TheClipboard.UsePrimarySelection(False) + return True + else: + return False + +def FilterFiles(file_list): + """Filters a list of paths and returns a list of paths + that can probably be opened in the editor. + @param file_list: list of files/folders to filter for good files in + + """ + good = list() + checker = ebmlib.FileTypeChecker() + for path in file_list: + if not checker.IsBinary(path): + good.append(path) + return good + +def GetFileType(fname): + """Get what the type of the file is as Editra sees it + in a formatted string. + @param fname: file path + @return: string (formatted/translated filetype) + + """ + if os.path.isdir(fname): + return _("Folder") + + eguess = syntax.GetTypeFromExt(fname.split('.')[-1]) + if eguess == synglob.LANG_TXT and fname.split('.')[-1] == 'txt': + return _("Text Document") + elif eguess == synglob.LANG_TXT: + mtype = mimetypes.guess_type(fname)[0] + if mtype is not None: + return mtype + else: + return _("Unknown") + else: + return _("%s Source File") % eguess + +def GetFileReader(file_name, enc='utf-8'): + """Returns a file stream reader object for reading the + supplied file name. It returns a file reader using the encoding + (enc) which defaults to utf-8. If lookup of the reader fails on + the host system it will return an ascii reader. + If there is an error in creating the file reader the function + will return a negative number. + @param file_name: name of file to get a reader for + @keyword enc: encoding to use for reading the file + @return file reader, or int if error. + + """ + try: + file_h = file(file_name, "rb") + except (IOError, OSError): + dev_tool.DEBUGP("[file_reader] Failed to open file %s" % file_name) + return -1 + + try: + reader = codecs.getreader(enc)(file_h) + except (LookupError, IndexError, ValueError): + dev_tool.DEBUGP('[file_reader] Failed to get %s Reader' % enc) + reader = file_h + return reader + +def GetFileWriter(file_name, enc='utf-8'): + """Returns a file stream writer object for reading the + supplied file name. It returns a file writer in the supplied + encoding if the host system supports it other wise it will return + an ascii reader. The default will try and return a utf-8 reader. + If there is an error in creating the file reader the function + will return a negative number. + @param file_name: path of file to get writer for + @keyword enc: encoding to write text to file with + + """ + try: + file_h = open(file_name, "wb") + except IOError: + dev_tool.DEBUGP("[file_writer][err] Failed to open file %s" % file_name) + return -1 + try: + writer = codecs.getwriter(enc)(file_h) + except (LookupError, IndexError, ValueError): + dev_tool.DEBUGP('[file_writer][err] Failed to get %s Writer' % enc) + writer = file_h + return writer + +# TODO: DEPRECATED - remove once callers migrate to ebmlib +GetFileManagerCmd = ebmlib.GetFileManagerCmd + +def GetUserConfigBase(): + """Get the base user configuration directory path""" + cbase = ed_glob.CONFIG['CONFIG_BASE'] + if cbase is None: + cbase = wx.StandardPaths_Get().GetUserDataDir() + if wx.Platform == '__WXGTK__': + if u'.config' not in cbase and not os.path.exists(cbase): + # If no existing configuration return xdg config path + base, cfgdir = os.path.split(cbase) + tmp_path = os.path.join(base, '.config') + if os.path.exists(tmp_path): + cbase = os.path.join(tmp_path, cfgdir.lstrip(u'.')) + return cbase + os.sep + +def HasConfigDir(loc=u""): + """ Checks if the user has a config directory and returns True + if the config directory exists or False if it does not. + @return: whether config dir in question exists on an expected path + + """ + cbase = GetUserConfigBase() + to_check = os.path.join(cbase, loc) + return os.path.exists(to_check) + +def MakeConfigDir(name): + """Makes a user config directory + @param name: name of config directory to make in user config dir + + """ + cbase = GetUserConfigBase() + try: + os.mkdir(cbase + name) + except (OSError, IOError): + pass + +def RepairConfigState(path): + """Repair the state of profile path, updating and creating it + it does not exist. + @param path: path of profile + + """ + if os.path.isabs(path) and os.path.exists(path): + return path + else: + # Need to fix some stuff up + CreateConfigDir() + import profiler + return profiler.Profile_Get("MYPROFILE") + +def CreateConfigDir(): + """ Creates the user config directory its default sub + directories and any of the default config files. + @postcondition: all default configuration files/folders are created + + """ + #---- Resolve Paths ----# + config_dir = GetUserConfigBase() + profile_dir = os.path.join(config_dir, u"profiles") + dest_file = os.path.join(profile_dir, u"default.ppb") + ext_cfg = [u"cache", u"styles", u"plugins"] + + #---- Create Directories ----# + if not os.path.exists(config_dir): + os.mkdir(config_dir) + + if not os.path.exists(profile_dir): + os.mkdir(profile_dir) + + for cfg in ext_cfg: + if not HasConfigDir(cfg): + MakeConfigDir(cfg) + + import profiler + profiler.TheProfile.LoadDefaults() + profiler.Profile_Set("MYPROFILE", dest_file) + profiler.TheProfile.Write(dest_file) + profiler.UpdateProfileLoader() + +def ResolvConfigDir(config_dir, sys_only=False): + """Checks for a user config directory and if it is not + found it then resolves the absolute path of the executables + directory from the relative execution path. This is then used + to find the location of the specified directory as it relates + to the executable directory, and returns that path as a + string. + @param config_dir: name of config directory to resolve + @keyword sys_only: only get paths of system config directory or user one + @note: This method is probably much more complex than it needs to be but + the code has proven itself. + + """ + # Try to get a User config directory + if not sys_only: + user_config = GetUserConfigBase() + user_config = os.path.join(user_config, config_dir) + + if os.path.exists(user_config): + return user_config + os.sep + + # Check if the system install path has already been resolved once before + if ed_glob.CONFIG['INSTALL_DIR'] != u"": + tmp = os.path.join(ed_glob.CONFIG['INSTALL_DIR'], config_dir) + tmp = os.path.normpath(tmp) + os.sep + if os.path.exists(tmp): + return tmp + else: + del tmp + + # The following lines are used only when Editra is being run as a + # source package. If the found path does not exist then Editra is + # running as as a built package. + if not hasattr(sys, 'frozen'): + path = __file__ + if not ebmlib.IsUnicode(path): + path = path.decode(sys.getfilesystemencoding()) + path = os.sep.join(path.split(os.sep)[:-2]) + path = path + os.sep + config_dir + os.sep + if os.path.exists(path): + if not ebmlib.IsUnicode(path): + path = unicode(path, sys.getfilesystemencoding()) + return path + + # If we get here we need to do some platform dependent lookup + # to find everything. + path = sys.argv[0] + if not ebmlib.IsUnicode(path): + path = unicode(path, sys.getfilesystemencoding()) + + # If it is a link get the real path + if os.path.islink(path): + path = os.path.realpath(path) + + # Tokenize path + pieces = path.split(os.sep) + + if wx.Platform == u'__WXMSW__': + # On Windows the exe is in same dir as config directories + pro_path = os.sep.join(pieces[:-1]) + + if os.path.isabs(pro_path): + pass + elif pro_path == u"": + pro_path = os.getcwd() + pieces = pro_path.split(os.sep) + pro_path = os.sep.join(pieces[:-1]) + else: + pro_path = os.path.abspath(pro_path) + elif wx.Platform == u'__WXMAC__': + # On OS X the config directories are in the applet under Resources + stdpath = wx.StandardPaths_Get() + pro_path = stdpath.GetResourcesDir() + pro_path = os.path.join(pro_path, config_dir) + else: + pro_path = os.sep.join(pieces[:-2]) + if pro_path.startswith(os.sep): + pass + elif pro_path == u"": + pro_path = os.getcwd() + pieces = pro_path.split(os.sep) + if pieces[-1] not in [ed_glob.PROG_NAME.lower(), ed_glob.PROG_NAME]: + pro_path = os.sep.join(pieces[:-1]) + else: + pro_path = os.path.abspath(pro_path) + + if wx.Platform != u'__WXMAC__': + pro_path = pro_path + os.sep + config_dir + os.sep + + path = os.path.normpath(pro_path) + os.sep + + # Make sure path is unicode + if not ebmlib.IsUnicode(path): + path = unicode(path, sys.getdefaultencoding()) + + return path + +def GetResources(resource): + """Returns a list of resource directories from a given toplevel config dir + @param resource: config directory name + @return: list of resource directory that exist under the given resource path + + """ + rec_dir = ResolvConfigDir(resource) + if os.path.exists(rec_dir): + rec_lst = [ rec.title() for rec in os.listdir(rec_dir) + if os.path.isdir(rec_dir + rec) and rec[0] != u"." ] + return rec_lst + else: + return -1 + +def GetResourceFiles(resource, trim=True, get_all=False, + suffix=None, title=True): + """Gets a list of resource files from a directory and trims the + file extentions from the names if trim is set to True (default). + If the get_all parameter is set to True the function will return + a set of unique items by looking up both the user and system level + files and combining them, the default behavior returns the user + level files if they exist or the system level files if the + user ones do not exist. + @param resource: name of config directory to look in (i.e cache) + @keyword trim: trim file extensions or not + @keyword get_all: get a set of both system/user files or just user level + @keyword suffix: Get files that have the specified suffix or all (default) + @keyword title: Titlize the results + + """ + rec_dir = ResolvConfigDir(resource) + if get_all: + rec_dir2 = ResolvConfigDir(resource, True) + rec_list = list() + if not os.path.exists(rec_dir): + return -1 + else: + recs = os.listdir(rec_dir) + if get_all and os.path.exists(rec_dir2): + recs.extend(os.listdir(rec_dir2)) + + for rec in recs: + if os.path.isfile(rec_dir + rec) or \ + (get_all and os.path.isfile(rec_dir2 + rec)): + + # If a suffix was specified only keep files that match + if suffix is not None: + if not rec.endswith(suffix): + continue + + # Trim the last part of an extension if one exists + if trim: + rec = ".".join(rec.split(u".")[:-1]).strip() + + # Make the resource name a title if requested + if title and len(rec): + rec = rec[0].upper() + rec[1:] + + if len(rec): + rec_list.append(rec) + rec_list.sort() + + return list(set(rec_list)) + +def GetAllEncodings(): + """Get all encodings found on the system + @return: list of strings + + """ + elist = encodings.aliases.aliases.values() + elist = list(set(elist)) + elist.sort() + elist = [ enc for enc in elist if not enc.endswith('codec') ] + return elist + +def Log(msg, *args): + """Push the message to the apps log + @param msg: message string to log + @param args: optional positional arguments to use as a printf formatting + to the message. + + """ + try: + wx.GetApp().GetLog()(msg, args) + except: + pass + +def GetProxyOpener(proxy_set): + """Get a urlopener for use with a proxy + @param proxy_set: proxy settings to use + + """ + Log("[util][info] Making proxy opener with %s" % str(proxy_set)) + proxy_info = dict(proxy_set) + auth_str = "%(uname)s:%(passwd)s@%(url)s" + url = proxy_info['url'] + if url.startswith('http://'): + auth_str = "http://" + auth_str + proxy_info['url'] = url.replace('http://', '') + else: + pass + + if len(proxy_info.get('port', '')): + auth_str = auth_str + ":%(port)s" + + proxy_info['passwd'] = ed_crypt.Decrypt(proxy_info['passwd'], + proxy_info['pid']) + Log("[util][info] Formatted proxy request: %s" % \ + (auth_str.replace('%(passwd)s', '****') % proxy_info)) + proxy = urllib2.ProxyHandler({"http" : auth_str % proxy_info}) + opener = urllib2.build_opener(proxy, urllib2.HTTPHandler) + return opener + +#---- GUI helper functions ----# + +def SetWindowIcon(window): + """Sets the given windows icon to be the programs + application icon. + @param window: window to set app icon for + + """ + try: + if wx.Platform == "__WXMSW__": + ed_icon = ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.ico" + window.SetIcon(wx.Icon(ed_icon, wx.BITMAP_TYPE_ICO)) + else: + ed_icon = ed_glob.CONFIG['SYSPIX_DIR'] + u"editra.png" + window.SetIcon(wx.Icon(ed_icon, wx.BITMAP_TYPE_PNG)) + finally: + pass + +#-----------------------------------------------------------------------------# + +class IntValidator(wx.PyValidator): + """A Generic integer validator""" + def __init__(self, min_=0, max_=0): + """Initialize the validator + @keyword min_: min value to accept + @keyword max_: max value to accept + + """ + wx.PyValidator.__init__(self) + self._min = min_ + self._max = max_ + + # Event management + self.Bind(wx.EVT_CHAR, self.OnChar) + + def Clone(self): + """Clones the current validator + @return: clone of this object + + """ + return IntValidator(self._min, self._max) + + def Validate(self, win): + """Validate an window value + @param win: window to validate + + """ + val = win.GetValue() + return val.isdigit() + + def OnChar(self, event): + """Process values as they are entered into the control + @param event: event that called this handler + + """ + key = event.GetKeyCode() + if key < wx.WXK_SPACE or key == wx.WXK_DELETE or \ + key > 255 or chr(key) in '0123456789': + event.Skip() + return + + if not wx.Validator_IsSilent(): + wx.Bell() + + return diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/wxcompat.py b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/wxcompat.py new file mode 100644 index 0000000..70b9e5f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/src/wxcompat.py @@ -0,0 +1,49 @@ +############################################################################### +# Name: wxcompat.py # +# Purpose: Help with compatibility between wx versions. # +# Author: Cody Precord <cprecord@editra.org> # +# Copyright: (c) 2008 Cody Precord <staff@editra.org> # +# License: wxWindows License # +############################################################################### + +""" +@summary: wx Compatibility helper module + +""" + +__author__ = "Cody Precord <cprecord@editra.org>" +__svnid__ = "$Id: wxcompat.py 68998 2011-09-03 22:03:32Z CJP $" +__revision__ = "$Revision: 68998 $" + +#-----------------------------------------------------------------------------# +# Imports +import os +import wx + +#-----------------------------------------------------------------------------# + +if wx.Platform == '__WXMAC__': + # MacThemeColour is defined in wxPython2.9 but does not exist in 2.8 + # This is a 2.8 version of this method. + if not hasattr(wx, 'MacThemeColour'): + def MacThemeColour(theme_id): + """Get a specified Mac theme colour + @param theme_id: Carbon theme id + @return: wx.Colour + + """ + brush = wx.Brush(wx.BLACK) + brush.MacSetTheme(theme_id) + return brush.GetColour() + + wx.MacThemeColour = MacThemeColour + + wx.SystemOptions.SetOptionInt("mac.textcontrol-use-spell-checker", 1) + +elif wx.Platform == '__WXGTK__': + os.environ['LIBOVERLAY_SCROLLBAR'] = '0' + +# GetText is not available in 2.9 but GetItemLabel is not available pre 2.8.6 +if wx.VERSION < (2, 8, 6, 0, ''): + wx.MenuItem.GetItemLabel = wx.MenuItem.GetText + wx.MenuItem.GetItemLabelText = wx.MenuItem.GetLabel diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlackBoard.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlackBoard.ess new file mode 100644 index 0000000..ac3fb28 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlackBoard.ess @@ -0,0 +1,172 @@ +/* File: BlackBoard.ess + * Author: Cody Precord + * License: wxWidgets + */ + +default_style { + fore:#F8F8F8; + back:#0C1021; + face:%(primary)s; + size:%(size)d; +} + +array_style { + fore:#B86214; +} + +brace_bad { + fore:#0000FF; + back:#FFFFFF; + modifiers:bold; +} + +brace_good { + fore:#FF0000; + back:#000000; + modifiers:bold; +} + +btick_style { + fore:#cc33ee; + back:#000000; +} + +calltip { + back:#1c2131; +} + +caret_line { + back:#1a1e2e; +} + +char_style { + fore:#E19618; +} + +class_style { + fore:#FF0404; + modifiers:bold; +} + +class2_style { + fore:#FF0404; +} + +comment_style { + fore:#626262; + modifiers:italic; +} + +decor_style { + fore:#C35E21; + modifiers:italic; +} + +directive_style { + fore:#2DE1CB; +} + +dockey_style { + fore:#39EAE1; +} + +error_style { + fore:#FE5252; +} + +foldmargin_style { + back:#2d3243; +} + +funct_style { + fore:#49DE38; + modifiers:italic; +} + +global_style { + fore:#2F86F0; + modifiers:bold; +} + +here_style { + fore:#41ce77; +} + +keyword_style { + fore:#FBDE2D; +} + +keyword2_style { + fore:#4179C5; + modifiers:bold; +} + +keyword3_style { + fore:#4179C5; + modifiers:bold; +} + +keyword4_style { + fore:#64DA3D; +} + +line_num { + back:#1c2131; +} + +marker_style { + fore:#F8F8F8; +} + +number_style { + fore:#D8FA3C; +} + +number2_style { + fore:#D8Fa3C; +} + +operator_style { + fore:#BBBBBB; +} + +pre_style { + fore:#27E71D; +} + +pre2_style { + fore:#CC33EE; +} + +regex_style { + fore:#22eeff; + modifiers:italic; +} + +scalar_style { + fore:#cc33ee; +} + +scalar2_style { + fore:#cc33ee; + modifiers:bold; +} + +select_style { + back:#142DD6; +} + +string_style { + fore:#61CE3C; +} + +stringeol_style { + fore:#408080; + back:#E0C0E0; + modifiers:eol; +} + +unknown_style { + fore:#F8F8f8; + back:#FF0000; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Blue.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Blue.ess new file mode 100644 index 0000000..034f8c1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Blue.ess @@ -0,0 +1,197 @@ +/* Editra Style Sheet + * Name: Blue + * Author: Cody Precord <cprecord@editra.org> + * License: wxWindows License + */ + +default_style { + fore:#FFEEDD; + back:#000A87; + face:%(primary)s; + size:%(size)d; +} + +array_style { + fore:#CC1313; +} + +brace_bad { + fore:#000A87; + back:#FF0024; +} + +brace_good { + fore:#EEFFDD; + back:#0093FF; +} + +btick_style { + fore:#008AC1; +} + +calltip { + fore:#4D4D4D; + back:#009FFF; +} + +caret_line { + back: #000FD6; +} + +char_style { + fore:#00CDCD; +} + +class_style { + fore:#F33C33; + modifiers: bold; +} + +class2_style { + fore:#F33C33; +} + +comment_style { + fore:#9B9BA7; +} + +ctrl_char { + fore:#000000; +} + +decor_style { + fore:#00A709; + modifiers: italic; +} + +directive_style { + fore:#00FFA2; +} + +dockey_style { + fore:#80007B; +} + +error_style { + fore:#000A87; + back:#FE5252; +} + +foldmargin_style { + fore:#FFEEDD; +} + +funct_style { + fore:#DF5900; + modifiers:italic; +} + +global_style { + fore:#00D00F; + modifiers:bold; +} + +guide_style { + fore: #FFEEDD; +} + +here_style { + fore:#ED0088; + back:#121A97; +} + +ideol_style { + fore:#FFDDEE; + back:#00F8FF; + modifiers:eol; +} + +keyword_style { + fore:#FFCF20; +} + +keyword2_style { + fore:#00F639; + modifiers:bold; +} + +keyword3_style { + fore:#E94F0B; +} + +keyword4_style { + fore:#0062AF; + modifiers:bold; +} + +line_num { + fore:#FFEEDD; + back:#242787; +} + +margin_style { + fore:#000000; + back:#FFFFFF; +} + +marker_style { + fore:#000000; + back:#FFFFFF; +} + +number_style { + fore:#ED0088; +} + +number2_style { + fore:#ED0088; + modifiers:bold; +} + +operator_style { + fore:#FFEEDD; + modifiers:bold; +} + +pre_style { + fore:#EE5507; + modifiers:bold; +} + +pre2_style { + fore:#EE5507; +} + +select_style { + back:#067B40; +} + +string_style { + fore:#00CDCD; +} + +stringeol_style { + fore:#000A87; + back:#00CDCD; + modifiers:bold eol; +} + +regex_style { + fore:#00BFFF; + back:#000A87; + modifiers:italic bold; +} + +scalar_style { + fore:#B037FF; + modifiers:bold; +} + +scalar2_style { + fore:#B037FF; +} + +unknown_style { + fore:#000000; + back:#FF0000; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlueMonday.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlueMonday.ess new file mode 100644 index 0000000..7e1ccba --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/BlueMonday.ess @@ -0,0 +1,184 @@ +/* Editra Style Sheet + * Name: BlueMonday + * Author: Thomas Keul + * License: N/A + */ + +default_style { + fore:#FFFFFF; + back:#233B5A; + face:%(primary)s; + size:%(size)d; +} + +array_style { + fore:#000000; +} + +brace_good { + fore:#000000; +} + +btick_style { + fore:#000000; +} + +calltip { + fore:#000000; + back:#FFFFFF; +} + +caret_line { + back: #3F6BA5; +} + +char_style { + fore:#00B000; +} + +class_style { + fore:#FF8040; +} + +class2_style { + fore:#000000; +} + +comment_style { + fore:#C0C0C0; + back:#1E324D; +} + +ctrl_char { + fore:#000000; +} + +directive_style { + fore:#FF4242; +} + +error_style { + fore:#000000; +} + +foldmargin_style { + fore:#000000; +} + +funct_style { + fore:#FF8000; +} + +global_style { + fore:#000000; +} + +here_style { + fore:#000000; +} + +ideol_style { + fore:#000000; +} + +keyword_style { + fore:#F1B411; +} + +keyword2_style { + fore:#FF8040; +} + +keyword3_style { + fore:#FF8040; +} + +keyword4_style { + fore:#FFFF64; +} + +keyword5_style { + fore:#19C864; +} + +keyword6_style { + fore:#FF8000; +} + +keyword7_style { + fore:#FFFF64; +} + +keyword8_style { + fore:#FFFF64; +} + +line_num { + fore:#000000; + back:#C0C0C0; +} + +margin_style { + back:#000000; +} + +marker_style { + fore:#000000; +} + +number_style { + fore:#00FFFF; +} + +number2_style { + fore:#800000; +} + +operator_style { + fore:#FFFFFF; +} + +pre_style { + fore:#000000; +} + +pre2_style { + fore:#000000; +} + +regex_style { + fore:#000000; +} + +scalar_style { + fore:#FF8000; +} + +scalar2_style { + fore:#000000; +} + +select_style { + back:#8699C4; +} + +string_style { + fore:#00C800; +} + +stringeol_style { + fore:#FF00FF; +} + +unknown_style { + fore:#000000; +} + +brace_bad { + fore:#000000; +} + +dockey_style { + fore:#876D92; + back:#1E324D; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Cream.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Cream.ess new file mode 100644 index 0000000..efde31f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Cream.ess @@ -0,0 +1,209 @@ +/* Editra Style Sheet + * Name: Default + * Author: Cody Precord <cprecord@editra.org> + * License: wxWindows License + */ + +/* Main Style all others inherit from */ +default_style { + fore: #000000; + back: #F6F6F6; + face: %(primary)s; + size: %(size)d; +} + +brace_good { + fore: #FFFFFF; + back: #0000FF; + modifiers: bold; +} + +brace_bad { + back: #FF0000; + modifiers: bold; +} + +calltip { + fore: #404040; + back: #FFFFB8; +} + +caret_line { + back: #D8F8FF; +} + +ctrl_char { + fore: #000000; + back: #F6F6F6; + face: %(primary)s; +} + +line_num { + back: #C0C0C0; + face: %(secondary)s; +} + +array_style { + fore: #EE8B02; + modifiers: bold; + face: %(secondary)s; +} + +btick_style { + fore: #8959F6; + modifiers: bold; + back: #FFFFFF; +} + +char_style { + fore: #FF3AFF; + back: #FFFFFF; +} + +class_style { + fore: #2E8B57; + modifiers: bold; +} + +class2_style { + fore: #2E8B57; + modifiers: bold; + back: #FFFFFF; +} + +comment_style { + fore: #838383; +} + +decor_style { + fore: #BA0EEA; + modifiers: italic; + face: %(secondary)s; +} + +directive_style { + fore: #0000FF; + modifiers: bold; + face: %(secondary)s; +} + +dockey_style { + fore: #0000FF; +} + +error_style { + fore: #DD0101; + modifiers: bold; + face: %(secondary)s; +} + +foldmargin_style { + back: #D1D1D1; +} + +funct_style { + fore: #008B8B; + modifiers:italic; +} + +global_style { + fore: #007F7F; + modifiers:bold; + face: %(secondary)s; +} + +guide_style { + fore: #838383; +} + +here_style { + fore: #CA61CA; + modifiers:bold; + face: %(secondary)s; +} + +ideol_style { + fore: #E0C0E0; + face: %(secondary)s; +} + +keyword_style { + fore: #A52B2B; + modifiers:bold; +} + +keyword2_style { + fore: #2E8B57; + modifiers:bold; +} + +keyword3_style { + fore: #008B8B; + modifiers: bold; +} + +keyword4_style { + fore: #9D2424; +} + +margin_style { + fore: #FFFFFF; + back: #000000; +} + +number_style { + fore: #DD0101; +} + +number2_style { + fore: #DD0101; + modifiers: bold; +} + +operator_style { + face: %(primary)s; + modifiers: bold; +} + +pre_style { + fore: #AB39F2; + modifiers: bold; +} + +pre2_style { + fore: #AB39F2; + modifiers: bold; + back: #FFFFFF; +} + +regex_style { + fore: #008B8B; +} + +scalar_style { + fore: #AB37F2; + modifiers: bold; + face: %(secondary)s; +} + +scalar2_style { + fore: #AB37F2; + face: %(secondary)s; +} + +string_style { + fore: #FF3AFF; + modifiers:bold; +} + +stringeol_style { + back: #EEC0EE; + modifiers:eol bold; + face: %(secondary)s; +} + +unknown_style { + fore: #FFFFFF; + back: #DD0101; + modifiers:bold eol; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Default.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Default.ess new file mode 100644 index 0000000..4c6d571 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Default.ess @@ -0,0 +1,198 @@ +default_style { + fore:#000000; + back:#FFFFFF; + face:%(primary)s; + size:%(size)d; +} + +margin_style { + fore:#FFFFFF; + back:#000000; +} + +number2_style { + fore:#DD0101; + modifiers:bold; +} + +caret_line { + back:#D8F8FF; +} + +comment_style { + fore:#838383; +} + +foldmargin_style { + back:#D1D1D1; +} + +keyword_style { + fore:#A52B2B; + modifiers:bold; +} + +keyword3_style { + fore:#008B8B; + modifiers:bold; +} + +guide_style { + fore:#838383; +} + +edge_style { + fore:#838383; +} + +error_style { + fore:#FE5252; + face:%(secondary)s; + modifiers:bold; +} + +ideol_style { + fore:#E0C0E0; +} + +array_style { + fore:#EE8B02; + modifiers:bold; +} + +global_style { + fore:#007F7F; + modifiers:bold; +} + +line_num { + back:#C0C0C0; +} + +pre2_style { + fore:#AB39F2; + modifiers:bold; +} + +string_style { + fore:#FF3AFF; + modifiers:bold; +} + +class_style { + fore:#2E8B57; + modifiers:bold; +} + +ctrl_char { + back:#FFFFFF; +} + +marker_style { + back:#FFFFFF; +} + +keyword2_style { + fore:#2E8B57; + modifiers:bold; +} + +class2_style { + fore:#2E8B57; + modifiers:bold; +} + +userkw_style { + back:#FFFFFF; +} + +char_style { + fore:#FF3AFF; +} + +keyword4_style { + fore:#9D2424; +} + +unknown_style { + fore:#FFFFFF; + back:#DD0101; + modifiers:bold eol; +} + +btick_style { + fore:#8959F6; + modifiers:bold; +} + +scalar_style { + fore:#AB37F2; + modifiers:bold; +} + +operator_style { + fore:#000000; +} + +here_style { + fore:#CA61CA; + modifiers:bold; +} + +regex_style { + fore:#008B8B; +} + +stringeol_style { + back:#EEC0EE; + modifiers:eol bold; +} + +decor_style { + fore:#BA0EEA; + face:%(secondary)s; + modifiers:italic; +} + +scalar2_style { + fore:#AB37F2; +} + +funct_style { + fore:#008B8B; + modifiers:italic; +} + +brace_good { + fore:#0000FF; + modifiers:bold; +} + +pre_style { + fore:#AB39F2; + modifiers:bold; +} + +directive_style { + fore:#0000FF; + modifiers:bold; +} + +calltip { + fore:#404040; + back:#FFFFB8; +} + +number_style { + fore:#DD0101; +} + +brace_bad { + fore:#FF0000; + modifiers:bold; +} + +dockey_style { + fore:#0000FF; +} + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Dessert.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Dessert.ess new file mode 100644 index 0000000..b8201de --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Dessert.ess @@ -0,0 +1,168 @@ +/* Editra Style Sheet + * Name: Dessert + * Author: Greg Allen <mail@jga23.com> + * License: wxWindows License + */ +default_style { + fore:#CCCCCC; + back:#333333; + face:%(primary)s; + size:%(size)d; +} + +number2_style { + fore:#CCCCCC; +} + +stringeol_style { + fore:#FF0000; +} + +caret_line { + back: #3F3F3F; +} + +comment_style { + fore:#999999; +} + +keyword_style { + fore:#F0E68C; +} + +keyword3_style { + fore:#CD5C5C; +} + +guide_style { + fore:#CCCCCC; +} + +keyword4_style { + fore:#CCCCCC; +} + +ideol_style { + fore:#CCCCCC; +} + +array_style { + fore:#87CEEB; +} + +global_style { + fore:#CCCCCC; +} + +line_num { + fore:#CCCCCC; +} + +pre2_style { + fore:#CCCCCC; +} + +string_style { + fore:#98FB98; +} + +class_style { + fore:#87CEEB; +} + +ctrl_char { + fore:#CCCCCC; +} + +marker_style { + fore:#CCCCCC; +} + +keyword2_style { + fore:#87CEEB; +} + +class2_style { + fore:#CCCCCC; +} + +unknown_style { + fore:#CCCCCC; +} + +calltip { + fore:#CCCCCC; +} + +scalar_style { + fore:#CCCCCC; +} + +char_style { + fore:#98FB98; +} + +here_style { + fore:#CCCCCC; +} + +number_style { + fore:#CCCCCC; +} + +regex_style { + fore:#CCCCCC; +} + +folder_style { + fore:#CCCCCC; +} + +pre_style { + fore:#CCCCCC; +} + +decor_style { + fore:#87CEEB; +} + +scalar2_style { + fore:#CCCCCC; +} + +funct_style { + fore:#CCCCCC; +} + +brace_good { + fore:#CCCCCC; +} + +error_style { + fore:#CD5C5C; +} + +directive_style { + fore:#CCCCCC; +} + +btick_style { + fore:#CCCCCC; +} + +operator_style { + fore:#BDB76B; +} + +margin_style { + fore:#CCCCCC; +} + +brace_bad { + fore:#CCCCCC; +} + +dockey_style { + fore:#CCCCCC; +} + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Guepardo.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Guepardo.ess new file mode 100644 index 0000000..60c0c2c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Guepardo.ess @@ -0,0 +1,109 @@ +/* Guepardo Style Sheet ( Inspired by OSX 10.5 color scheme ) + * Name: Guepardo + * Author: Omar Gomez <omar.gomez@gmail.com> + * License: wxWindows License + */ + +default_style { + fore:#000000; + back:#FCFCFC; + face:%(primary)s; + size:%(size)d; +} + +error_style { + fore:#FFD7D7; +} + +stringeol_style { + fore:#FFFFFF; + back:#4900CC; + face:%(secondary)s; + modifiers:eol bold; +} + +caret_line { + back:#DEEFFF; +} + +comment_style { + fore:#5181AB; + modifiers:italic; +} + +keyword_style { + fore:#0086B5; + modifiers:bold; +} + +keyword3_style { + fore:#d66715; + modifiers:bold; +} + +ideol_style { + fore:#FFFFFF; + back:#4900CC; + face:%(secondary)s; + modifiers:eol bold; +} + +line_num { + fore:#FFFFFF; + back:#5181AB; + face:%(secondary)s; +} + +string_style { + fore:#4900CC; +} + +class_style { + fore:#1CA330; + modifiers:bold; +} + +keyword2_style { + fore:#1ca330; + modifiers:bold; +} + +class2_style { + fore:#0086B5; + modifiers:bold; +} + +number_style { + fore:#5181AB; +} + +pre_style { + fore:#894C24; + modifiers:bold; +} + +decor_style { + fore:#894C24; + modifiers:bold italic; +} + +brace_good { + fore:#FFFFFF; + back:#FF8D03; + modifiers:bold; +} + +char_style { + fore:#4900CC; +} + +brace_bad { + back:#FF0000; + modifiers:bold; +} + +dockey_style { + fore:#0064F3; + modifiers:bold; +} + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Midnight.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Midnight.ess new file mode 100644 index 0000000..b0e9678 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Midnight.ess @@ -0,0 +1,189 @@ +/* Editra Style Sheet + * Name: Midnight + * Author: Cody Precord <cprecord@editra.org> + * License: wxWindows License + */ + +default_style { + fore: #FFFFFF; + back: #000000; + face: %(primary)s; + size: %(size)d; +} + +array_style { + fore: #EE8B02; + modifiers: bold; +} + +brace_good { + fore: #FFFFFF; + back: #0000FF; + modifiers: bold; +} + +brace_bad { + back: #FF0000; + modifiers: bold; +} + +btick_style { + fore: #8959F6; + modifiers: bold; +} + +calltip { + fore: #FFE200; + back: #09026A; +} + +caret_line { + back: #262626; +} + +char_style { + fore: #FF3AFF; +} + +class_style { + fore: #2E8B57; + modifiers: bold; +} + +class2_style { + fore: #2E8B57; + modifiers: bold; +} + +ctrl_char { + fore: #FFFFFF; + back: #000000; + face: %(primary)s; +} + +comment_style { + fore: #0033CC; + face: %(primary)s; +} + +decor_style { + fore: #BA0EEA; + face: %(secondary)s; + modifiers: italic; +} + +directive_style { + fore: #0000FF; + modifiers: bold; +} + +dockey_style { + fore: #00A6FF; +} + +error_style { + fore: #FE5252; +} + +funct_style { + fore: #008B8B; + modifiers: italic; +} + +global_style { + fore: #007F7F; + modifiers: bold; +} + +guide_style { + fore: #F6F6F6; +} + +here_style { + fore: #CA61CA; + modifiers: bold; +} + +ideol_style { + fore: #E0C0E0; +} + +keyword_style { + fore: #A52B2B; + modifiers: bold; +} + +keyword2_style { + fore: #2E8B57; + modifiers: bold; +} + +keyword3_style { + fore: #008B8B; + modifiers: bold; +} + +keyword4_style { + fore: #9D2424; +} + +number_style { + fore: #DD0101; +} + +number2_style { + fore: #DD0101; + modifiers: bold; +} + +operator_style { + fore: #FFFFFF; + modifiers: bold; +} + +pre_style { + fore: #AB39F2; + modifiers: bold; +} + +pre2_style { + fore: #AB39F2; + back: #101010; + modifiers: bold; +} + +regex_style { + fore: #008B8B; + modifiers: bold; +} + +scalar_style { + fore: #AB37F2; + modifiers: bold; +} + +scalar2_style { + fore: #AB37F2; +} + +select_style { + back: #03087D; +} + +string_style { + fore: #FF3AFF; + modifiers: bold; +} + +stringeol_style { + fore: #000000; + back: #EEC0EE; + size: %(size)d; + modifiers: bold eol; +} + +unknown_style { + fore: #FFFFFF; + back: #DD0101; + modifiers: bold eol; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Mocha.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Mocha.ess new file mode 100644 index 0000000..bbdd886 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/styles/Mocha.ess @@ -0,0 +1,210 @@ +/* Mocha.ess + * + */ + +default_style { + fore:#BDAE9D; + back:#2A211C; + face:%(primary)s; + size:%(size)d; +} + +number2_style { + fore:#CCCCCC; + back:#333333; +} + +stringeol_style { + fore:#FF0000; +} + +caret_line { + fore:#CCCCCC; + back:#382C25; +} + +error_style { + fore:#CD5C5C; + back:#333333; +} + +comment_style { + fore:#80756A; + size:%(size)d; + modifiers:italic; +} + +foldmargin_style { + fore:#CCCCCC; + back:#333333; +} + +keyword_style { + fore:#43A8ED; +} + +keyword3_style { + fore:#CD5C5C; + back:#333333; +} + +guide_style { + fore:#665E55; + back:#333333; +} + +keyword4_style { + fore:#CCCCCC; +} + +ideol_style { + fore:#CCCCCC; + back:#333333; +} + +array_style { + fore:#87CEEB; + back:#333333; +} + +global_style { + fore:#CCCCCC; + back:#333333; +} + +line_num { + fore:#80756A; + back:#333333; +} + +pre2_style { + fore:#CCCCCC; + back:#333333; +} + +select_style { + fore:#CCCCCC; + back:#482C25; +} + +string_style { + fore:#049B0A; +} + +class_style { + fore:#87CEEB; + back:#333333; +} + +ctrl_char { + fore:#CCCCCC; + back:#333333; +} + +marker_style { + fore:#CCCCCC; + back:#333333; +} + +keyword2_style { + fore:#327FB3; +} + +class2_style { + fore:#CCCCCC; + back:#333333; +} + +operator_style { + fore:#8C8175; +} + +unknown_style { + fore:#CCCCCC; + back:#333333; +} + +calltip { + fore:#CCCCCC; + back:#333333; +} + +scalar_style { + fore:#CCCCCC; + back:#333333; +} + +char_style { + fore:#98FB98; + back:#333333; +} + +here_style { + fore:#CCCCCC; + back:#333333; +} + +regex_style { + fore:#CCCCCC; + back:#333333; +} + +folder_style { + fore:#CCCCCC; + back:#333333; +} + +decor_style { + fore:#87CEEB; + back:#333333; +} + +scalar2_style { + fore:#CCCCCC; + back:#333333; +} + +funct_style { + fore:#CCCCCC; + back:#333333; +} + +brace_good { + fore:#CCCCCC; + back:#333333; +} + +pre_style { + fore:#AB39F2; + modifiers:bold; +} + +directive_style { + fore:#CCCCCC; + back:#333333; +} + +btick_style { + fore:#CCCCCC; + back:#333333; +} + +number_style { + fore:#44AA43; +} + +margin_style { + fore:#CCCCCC; + back:#333333; +} + +brace_bad { + fore:#CCCCCC; + back:#333333; +} + +dockey_style { + fore:#CCCCCC; + back:#333333; +} + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/68k_assembly.68k b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/68k_assembly.68k new file mode 100644 index 0000000..0a5aaa6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/68k_assembly.68k @@ -0,0 +1,38 @@ +; Syntax Test file for 68k Assembly code +; Some comments about this file +.D0 00000000 +MS 2100 00000002 +MM 2000;DI + LEA.L $002100,A1 + MOVE.L #2,-(A1) + BSR $00002050 + +MM 2050;DI + MOVE.L (A1)+,D1 + MOVE.L (A1),D2 + ADD.L D1,D2 + MOVE.L D2,D0 + RTS + +.D0 00000000 +.D3 00000100 +.D4 00000200 +.D5 00000300 +MM 2000;DI + CMP D3,D4 + BGE $002100 + CMP D3,D5 + BGE $002150 + MOVE.L D3,D0 +. +MM 2100;DI + CMP D4,D5 + BGE $002150 + MOVE.L D4,D0 +. +MM 2150;DI + MOVE.L D5,D0 +. + +.PC 2000 +TR
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/Xtext.xtext b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/Xtext.xtext new file mode 100644 index 0000000..bef01df --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/Xtext.xtext @@ -0,0 +1,43 @@ +/* + Syntax Highlighting test file for Xtext language. +*/ +grammar simpleStateMachine with someOtherGrammar hidden(WS, ML_COMMENT, SL_COMMENT) +import "http://www.eclipse.org/emf/2002/Ecore" as ecore +generate simpleStateMachine "http://www.simplestatemachine.com/simpleStateMachine" + +/* This is multiline comment with + a nested comment. + /* Nested + comment + */ +*/ + +// Terminals +terminal ML_COMMENT : '/*' -> '*/'; +terminal SL_COMMENT : '//' !('\n'|'\r')* ('\r'? '\n')?; + +terminal WS : (' '|'\t'|'\r'|'\n')+; + +// Parser Rules +Machine: + "machine" name=ID ";" + (states+=State)* // testing CrossRef support in codebrowser + (transitions+=Transition)* +; + +State: + "state" name=ID ";" +; + +Transition: + "for" input=STRING oldState=[State] "->" newState=[State] + ("out" output=STRING)? + ";" +; + +// Enumeration +enum EnumerationTest: + first="FIRST"| + second="SECOND" | + third="THIRD" +; diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/actionscript.as b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/actionscript.as new file mode 100644 index 0000000..d21e70d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/actionscript.as @@ -0,0 +1,38 @@ +// ActionScript Syntax Highlighting Test File +// Comments are like this +/** Multi-line comments are like these lines here + * @summary Documentation keywords are like this + */ + +// Hello World ActionScript 2.0 +class com.example.Greeter extends MovieClip +{ + public function Greeter() + { + var txtHello:TextField = this.createTextField("txtHello", 0, 0, 0, 100, 100); + txtHello.text = "Hello World"; + } +} + +// Hellow World ActionScript 3.0 +package com.example +{ + import flash.text.TextField; + import flash.display.Sprite; + + public class Greeter extends Sprite + { + public function Greeter() + { + var txtHello:TextField = new TextField(); + txtHello.text = "Hello World"; + addChild(txtHello); + } + } +} + +// Some Variable Definitions +var item1:String="ABC"; +var item2:Boolean=true; +var item3:Number=12 +var item4:Array=["a","b","c"]; diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ada.adb b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ada.adb new file mode 100644 index 0000000..03731e4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ada.adb @@ -0,0 +1,13 @@ +-- Syntax Highlighting test file for Ada +-- Some Comments about this file +pragma Name (Parameter_List); +with Ada.Text_IO; + +procedure Hello is +begin + Ada.Text_IO.Put_Line("Hello, world!"); + Ada.Text_IO.Put_Line("Unclosed string); +end Hello; + +My_Number := 1; +_Ilegal_Identifier := 'a'; diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/apache_conf.conf b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/apache_conf.conf new file mode 100644 index 0000000..4229d09 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/apache_conf.conf @@ -0,0 +1,31 @@ +## Syntax Highlighting Test File for Apache Configuration Files +## Comment line + +# Directive and Parameter +ServerType standalone + +# Directive and String +ServerRoot "/usr" + +# Directive and Number +Timeout 300 + +# Directive and IP number +Listen 12.34.56.78:80 + +# Directive and Extension +AccessFileName .htaccess + +# Some Extra Examples +DefaultType text/plain +HostnameLookups Off +ErrorLog "/private/var/log/httpd/error_log" +LogLevel warn + +<IfModule mod_setenvif.c> + BrowserMatch "Mozilla/2" nokeepalive + BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + BrowserMatch "RealPlayer 4\.0" force-response-1.0 + BrowserMatch "Java/1\.0" force-response-1.0 + BrowserMatch "JDK/1\.0" force-response-1.0 +</IfModule> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/bash_shell_script.sh b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/bash_shell_script.sh new file mode 100644 index 0000000..a239e93 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/bash_shell_script.sh @@ -0,0 +1,36 @@ +# Syntax Highlighting Test File for Bash +# Comment Line + +# Test Assignment +BLUE="[34;01m" +CYAN="[36;01m" +GREEN="[32;01m" +RED="[31;01m" +YELLOW="[33;01m" +OFF="[0m" + +echo "${YELLOW}**${OFF} Hello World in Yellow ${YELLOW}**${OFF}" +sleep 2 + +# Test Scalar +HELLO=$(Hello) +HELLO2=${Hello} +HELLO3=`Hello` + +# Test Loop/Condition +if [ 'a' == 'a' ]; then + for file in $( ls ); do + echo $file + done +fi + +# Test Function Definition +function quit { + exit +} + +# Here Statement +cat <<EOF +This is a multiline block for testing the +highlighting of a here statement +EOF diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/boo.boo b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/boo.boo new file mode 100644 index 0000000..4c38b0d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/boo.boo @@ -0,0 +1,27 @@ +# Syntax Highlighting Test File for Boo +# Comment line +/* This is also a comment line but highlighting is not +* currently supported by Editra +*/ +// So is this but also not currently supported + +import System +name = Console.ReadLine() +print "Hello, ${name}" + +# Class Def +class TestClass: + public Name as string + public Size as int + +# More complex class def +public abstract class Hello: + abstract def Hello(): + print "HELLO" + +# Function Def +def fib(): + a, b = 0L, 1L + while true: + yield b + a, b = b, a + b diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c-shell_script.csh b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c-shell_script.csh new file mode 100644 index 0000000..a364a41 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c-shell_script.csh @@ -0,0 +1,14 @@ +# Some Comments about this file + +echo "Hello, World!" + +# Look for the file specified as arg 1 and +# say if we find it or not +set f = $1 +foreach d (*) + if (-e $d/$f) then + echo FOUND: $d/$f + exit(0) + endif +end +echo $f not found in subdirectories diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c.c b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c.c new file mode 100644 index 0000000..4360183 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/c.c @@ -0,0 +1,25 @@ +/** Syntax Highlighting Test File for C + * \brief Doxygen tag highlighting + */ + +#include"stdlib.h" + +int main() +{ + int val1 = 10; + int val2 = val1 * 2; + char mychar = 'A'; + + for(;;) + { + val2 = val1 - 1; + if(val <= 0) break; + } + + printf("Hello World, %d + %d = %d", val1, val2, val1 + val2); + printf("An unclosed string and unmatched brace +}/*End Main*/ + +void *test(void) {;} + +/*EOF*/ diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/caml.ml b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/caml.ml new file mode 100644 index 0000000..d4eb218 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/caml.ml @@ -0,0 +1,16 @@ +(* Syntax Highlighting Test File for Caml *) +(* Some Comments about this file *) + +(* Hello World *) +print_endline "Hello world!";; + +(* Calculate Fibbonacci Value of N *) +let rec fib n = + if n < 2 then 1 else fib(n-1) + fib(n-2);; +let main () = + let arg = int_of_string Sys.argv.(1) in + print_int(fib arg); + print_newline(); + exit 0;; +main ();; + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cascading_style_sheet.css b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cascading_style_sheet.css new file mode 100644 index 0000000..54ad496 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cascading_style_sheet.css @@ -0,0 +1,52 @@ +/* Comments About This File */ + +/* Directive */ +@charset "iso-8859-1"; + +/*** Plain tag definition ***/ +a { text-decoration : none; } + +/** Tag:psuedo class def **/ +a:link { color : #456; } + +/** Tag/Attribute def **/ +input[type="submit"] { + border: 2px #369 outset; + background-color: #369; + color: white; +} + +/** Class def **/ +.tiny { + font-family : "Bitstream Vera", "Vera", "Trebuchet MS", sans-serif; + color : #666; + font-size : 10px; + line-height : 10px; +} + +/*** Ids defs ***/ +#docpane { + width: 98%; + padding-top: 10px; + margin: 5px; +} + +/*** uses some css 2 keywords ****/ +form input.objectA { + position: absolute; + text-align: left; + width: 550px; + z-index: 2; +} + +/** Syntax Error/Non WC3 compliant css **/ +a:what { color: red; } + +/** Important **/ +.hide { display: none !important; } + +.hide p { color: blue; } + +.hide .hidedecendant { color: red; } + +.hide #someID { color: yellow; } diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cilk.cilk b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cilk.cilk new file mode 100644 index 0000000..3ca8e60 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cilk.cilk @@ -0,0 +1,15 @@ +// Syntax Highlighting Test file for Cilk +// Comments are like this +/* And This */ + +cilk int fib (int n) { + if (n<2) return (n); + else { + int x,y; + spawn x = fib(n-1); + spawn y = fib(n-2); + sync; + return (x+y); + } +} + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cobra.cobra b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cobra.cobra new file mode 100644 index 0000000..914d593 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cobra.cobra @@ -0,0 +1,25 @@ +# Syntax Highlighting Test File for Cobra +# Comments look like this + +""" +DocString + +""" + +class Hello + + # Class variables + var _name as String + var _verbosity = 1 + + def init(name as String, verbosity as Int) + _name = name + _verbosity = verbosity + + .define('quit', 'built-in:quit') + + def main is shared + print 'Hello, world.' + + def quit + _didQuit = true diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/coldfusion.cfm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/coldfusion.cfm new file mode 100644 index 0000000..1d1ae99 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/coldfusion.cfm @@ -0,0 +1,43 @@ +<!--- Some comments about this file ---> +<!-- Support is still a work in progress --> + +<cfscript> +function helloWorld() { + var greeting = "Hello World!"; + return greeting; +} +</cfscript> + +<cfoutput>#helloWorld()#</cfoutput> + +<cfset Foo1 = "Hello"> +<cfset Foo2 = "Hello World"> + +<cfoutput> +<!--- pound signs output the returned value ---> +<p>The first position of #Foo1# in #Foo2# is #Find(Foo1,Foo2)#</p> +</cfoutput> +<CFSCRIPT> +/** + * Returns a list of all factors for a given + * positive integer. + * + * @param integer Any non negative integer greater + * than or equal to 1. + * @return Returns a comma delimited list + * of values. + * @author Rob Brooks-Bilson (rbils@amkor.com) + * @version 1.1, September 6, 2001 + */ +function factor(integer) +{ + Var i=0; + Var Factors = ""; + for (i=1; i LTE integer/2; i=i+1) { + if (Int(integer/i) EQ integer/i) { + Factors = ListAppend(Factors, i); + } + } + Return ListAppend(Factors, integer); +} +</CFSCRIPT> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cpp.cpp b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cpp.cpp new file mode 100644 index 0000000..9c4af41 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/cpp.cpp @@ -0,0 +1,30 @@ +/** Syntax Highlighting test file for C++ + * \brief Doxygen tag highlighting + */ +#include<iostream> +#include<cstdlib> + +using namespace std; + +int main(void) +{ + cout << "\nHello World" << endl; + cout << "\nUnclosed String << endl; + + // One line comment + int a = 0; + + exit(a); +} + +int add(int x, int y) +{ + return x + y; +} + +void TestClass::Foo(int &nVal) +{ + nVal++; +} + +// EOF diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/csharp.cs b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/csharp.cs new file mode 100644 index 0000000..dc35b7c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/csharp.cs @@ -0,0 +1,30 @@ +// C# Syntax Highlighting Test File +// Comments are like this +/** Multiline comments are like this + * @summary <- Documentation Keyword + * \brief <- Doxygen style keyword + */ + +using System; + +#region Foo +class Foo +{ + void Create() {} +} +#endregion Foo + +// Hello World +class HelloClass +{ + static void Main() + { + System.Console.WriteLine("Hello, world!"); + } + + public static void PrintPlusOne(int x) + { + System.Console.WriteLine(x + 1); + } +} + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/d.d b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/d.d new file mode 100644 index 0000000..11fbac4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/d.d @@ -0,0 +1,59 @@ +// Syntax Highlighting test file for D programming language +// A single line comment +/* A multi-line comment about this file. + * Adopted from http://en.wikipedia.org/wiki/D_%28programming_language%29 + */ + +import std.stdio; +int main(char[][] args) +{ + writefln("Hello World"); + + // Strings are denoted as a dynamic array of chars 'char[]' + // auto type inference and built-in foreach + foreach(argc, argv; args) + { + auto cl = new CmdLin(argc, argv); // OOP is supported + writefln(cl.argnum, cl.suffix, " arg: %s", cl.argv); // user-defined class properties. + + delete cl; // Garbage Collection or explicit memory management - your choice + } + + // Nested structs, classes and functions + struct specs + { + // all vars automatically initialized to 0 at runtime + int count, allocated; + // however you can choose to avoid array initialization + int[10000] bigarray = void; + } + + specs argspecs(char[][] args) + // Optional (built-in) function contracts. + in + { + assert(args.length > 0); // assert built in + } + out(result) + { + assert(result.count == CmdLin.total); + assert(result.allocated > 0); + } + body + { + specs* s = new specs; + // no need for '->' + s.count = args.length; // The 'length' property is number of elements. + s.allocated = typeof(args).sizeof; // built-in properties for native types + foreach(arg; args) + s.allocated += arg.length * typeof(arg[0]).sizeof; + return *s; + } + + // built-in string and common string operations, eg. '~' is concatenate. + char[] argcmsg = "argc = %d"; + char[] allocmsg = "allocated = %d"; + writefln(argcmsg ~ ", " ~ allocmsg, + argspecs(args).count,argspecs(args).allocated); + return 0; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/diff_file.diff b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/diff_file.diff new file mode 100644 index 0000000..660aefe --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/diff_file.diff @@ -0,0 +1,39 @@ +--- Syntax Highlighting Test File for Diff results +--- Comment Lines are like this +--- cpp.cpp 2007-06-26 07:14:22.000000000 -0500 ++++ hello_diff.cpp 2007-08-06 17:01:47.000000000 -0500 +@@ -2,24 +2,29 @@ + * + */ + #include<iostream> +-#include<cstdlib> + + using namespace std; + + int main(void) + { +- cout << "\nHello World" << endl; ++ cout << "\nHello World!" << endl; + cout << "\nUnclosed String << endl; + + // One line comment + int a = 0; +- +- exit(a); ++ cout << add(a, 22) << endl; + } + +-int add(x, y) ++// Add two numbers ++int add(int x, int y) + { + return x + y; + } + ++// Subtract two numbers ++int sub(int x, int y) ++{ ++ return x - y; ++} ++ + // EOF
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/django.django b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/django.django new file mode 100644 index 0000000..203f5a7 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/django.django @@ -0,0 +1,25 @@ +<!-- Syntax Highlighting Test File for Django --> +<!-- Comments are like this --> + +<!-- base.html --> +<html> + <head> + <title>{% block head_title %}mysite.com{% endblock %}</title> + </head> + <body> + </body> +</html> + +<!-- application/model_index.html --> +{% extends "base.html" %} +{% block head_title %}{{ object.title|title }} &ndash; {{ block.super }}{% endblock %} + +<!-- result, when {{ object.title }} was "My test entry" --> +<html> + <head> + <title>My Test Entry &ndash; mysite.com</title> + </head> + <body> + <p class="hello">Hello</p> + </body> +</html> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dos_batch_script.bat b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dos_batch_script.bat new file mode 100644 index 0000000..60768d1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dos_batch_script.bat @@ -0,0 +1,23 @@ +:: Syntax Highlighting Test File for Dos Batch Scripts +:: Comment Line + +:BEGIN +set HELLO="WORLD" +set WORLD="HELLO" +set HELLOWORLD="%WORLD% %HELLO%" + +if "%1" == "/?" goto HELP +if "%1" == "go" goto EXECUTE + +:HELP +echo . +echo Here is test file to show some dos batch highlighting +echo . +goto END + +:EXECUTE +echo . +echo %HELLOWORLD% +echo . + +:END diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dot.dot b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dot.dot new file mode 100644 index 0000000..c1bc0c8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dot.dot @@ -0,0 +1,32 @@ +// Syntax Highlighting Test file for DOT +// Some Comments about this file +// Sample graphviz DOT file from +// http://www.graphviz.org/Gallery/directed/cluster.html + +digraph "Example" { + + subgraph cluster_0 { + style=filled; + color=lightgrey; + node [style=filled,color=white]; + a0 -> a1 -> a2 -> a3; + label = 'process #1'; + } + + subgraph cluster_1 { + node [style=filled]; + b0 -> b1 -> b2 -> b3; + label = "process #2"; + color=blue + } + begin -> a0; + begin -> b0; + a1 -> b3; + b2 -> a3; + a3 -> a0; + a3 -> end; + b3 -> end; + + begin [shape=Mdiamond]; + end [shape=Msquare]; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dsp56k_assembly.56k b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dsp56k_assembly.56k new file mode 100644 index 0000000..9e9274d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/dsp56k_assembly.56k @@ -0,0 +1,31 @@ +;***************************************************************************** +; DSP56K Highlighting Test File +; Comments look like this +;***************************************************************************** + PAGE 110,60,1,1 + TABS 4 +;***************************************************************************** +; DEFINITIONS & POINTERS +;***************************************************************************** +START EQU $000100 ; program start location +SERIAL EQU $2 ; serial number location + +TXD EQU $FFFFBC ; ESSI0 Transmit Data Register 0 +RXD EQU $FFFFB8 ; ESSI0 Receive Data Register +SSISR EQU $FFFFB7 ; ESSI0 Status Register +CRB EQU $FFFFB6 ; ESSI0 Control Register B +CRA EQU $FFFFB5 ; ESSI0 Control Register A +PCRC EQU $FFFFBF ; Port C (ESSI_0) control register +PCTL EQU $FFFFFD ; PLL control register +TXREG EQU $FFFF89 ; external TX register +RXREG EQU $FFFF8A ; external RX register + +PDRB EQU $FFFFC9 ; Port B (HOST) GPIO data +PRRB EQU $FFFFC8 ; Port B (HOST) GPIO direction +PCRB EQU $FFFFC4 ; Port B (HOST) control register + +PCRE EQU $FFFF9F ; Port E (SCI) control register +PRRE EQU $FFFF9E ; Port E (SCI) data direction +PDRE EQU $FFFF9D ; Port E (SCI) data + + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/editra_style_sheet.ess b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/editra_style_sheet.ess new file mode 100644 index 0000000..9412e3f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/editra_style_sheet.ess @@ -0,0 +1,23 @@ +/* Syntax Highlighting Test File for Editra Style Sheets + * Comments are like this + */ + +default_style { + fore: #FFFFFF; + back: #000000; + face: %(mono)s; + size: %(size)d; +} + +keyword_style { + fore: #A52B2B bold; + back: #F6F6F6; + size: %(size)d; +} + +/* Definition with a bad attribute size5 */ +class_style { + fore: #2E8B57 bold; + back: #F6F6F6; + size5: %(size)d; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/edje.edc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/edje.edc new file mode 100644 index 0000000..215d078 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/edje.edc @@ -0,0 +1,70 @@ +// Syntax Highlighting test file for Edje +// Some comments about this file +/******************************************************************** + * Multi line comments are like this. + ********************************************************************/ +#define FRAME LOSSY 60 + +images { + image: "eracnid.png" LOSSY 80; + image: "shadow.png" COMP; + image: "E-wavy_000001.png" FRAME; + image: "E-wavy_000002.png" FRAME; + image: "E-wavy_000003.png" FRAME; +} + +collections { + group { + name: "desktop/background"; + parts { + part { + name: "background_image"; + mouse_events: 0; + description { + state: "default" 0.0; + align: 0.5 0.5; + image { + normal: "eracnid.png"; + } + } + } + part { + name: "logo"; + mouse_events: 0; + description { + aspect: 3.33 3.33; + state: "default" 0.0; + min: 112 148; + max: 200 269; + align: 1.0 1.0; + rel1 { + relative: 0.796 0.355; + offset: 0 0; + to, "background_image"; + } + rel2 { + relative: 0.796 0.355; + offset: 0 0; + to, "background_image"; + } + image { + normal: "E-wavy_000001.png"; + tween: "E-wavy_000002.png"; + tween: "E-wavy_000003.png"; + } + } + } + } + programs { + program { + name: "logo_animate"; + signal: "show"; + source: ""; + action: STATE_SET "default" 0.0; + transition: LINEAR 4.0; + target: "logo"; + after: "logo_animate"; + } + } + } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/eiffel.e b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/eiffel.e new file mode 100644 index 0000000..464cc84 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/eiffel.e @@ -0,0 +1,27 @@ +-- Syntax Highlighting Test File for Eiffel +-- Some Comments about this file + +class + HELLO_WORLD +create + make +feature + make + do + io.put_string ("Hello, world!") + io.put_new_line + io.put_string('Unclosed String + end +end + +-- Run the HelloWorld program + +program hello_prog + +root + HELLO_WORLD: "make" +cluster + "./" +end + include "$EIFFEL_S/library/lib.pdl" +end -- hello_prog diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/erlang.erl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/erlang.erl new file mode 100644 index 0000000..c1f8138 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/erlang.erl @@ -0,0 +1,29 @@ +%% Syntax Highlighting Test file for Erlang +%% Some comments about this file + +%% quicksort:qsort(List) +%% Sort a list of items +-module(quicksort). +-export([qsort/1]). + +qsort([]) -> []; +qsort([Pivot|Rest]) -> + qsort([ X || X <- Rest, X < Pivot]) ++ [Pivot] ++ qsort([ Y || Y <- Rest, Y >= Pivot]). + +%% --------------------------------------------------------------------- %% +%% Sort a list by length +-module(listsort). +-export([by_length/1]). + +by_length(Lists) -> + F = fun(A,B) when is_list(A), is_list(B) -> + length(A) < length(B) + end, + qsort(Lists, F). + + qsort([], _)-> []; + qsort([Pivot|Rest], Smaller) -> + qsort([ X || X <- Rest, Smaller(X,Pivot)], Smaller) + ++ [Pivot] ++ + qsort([ Y ||Y- Rest, not(Smaller(Y, Pivot))], Smaller). + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ferite.fe b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ferite.fe new file mode 100644 index 0000000..010e2af --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ferite.fe @@ -0,0 +1,66 @@ +// Syntax Highlighting Test File for Ferite +// Comments are like this +/** Multiline comments are like this + * @summary Documentation keyword + * \brief Another Doc keyword + */ + +// Hello World +uses "console"; +Console.println( "Hello World" ); +Console.println( "Unclosed String + +// Types +number a; +string b; +array c; + +a = 2; +b = "2"; +c = [ a, b ]; + +// Function +function f( number x ) { + if( x > 1 ) { + return f( x - 1 ) * 2; + } + return 1; +} +Console.println( f(10) ); + +// Class +class A { + string value; + + function constructor() { + .value = "Class.A"; + } + + function f() { + return .value; + } +} + +// Some Namespace defs +namespace A { + function f() { + return "A.f"; + } +} + +namespace modifies A { + function g() { + return "A.g"; + } +} + +// Protocols +protocol C { + function getX(); + function getY(); +} + +class A implements C { + function getX() { return "X"; } + function getY() { return "Y"; } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/flagship.prg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/flagship.prg new file mode 100644 index 0000000..9889c7c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/flagship.prg @@ -0,0 +1,23 @@ +// Syntax Highlighting test file for Flagship/XBase programming languages +// Some comments about this file +/* A multline comment about some stuff in this + * file. + */ + +// Hello World in Clipper +? "Hello World!" + + +USE address ALIAS adr SHARED NEW +SET COLOR TO "W+/B,GR+/R,W/B,W/B,GR+/BG" +cls +@ 1, 0 SAY "Id No. " GET adr->IdNum PICT "999999" VALID IdNum > 0 +@ 3, 0 SAY "Company" GET adr->Company +@ 3,35 SAY "Branch" GET adr->Branch WHEN !empty(adr->Company) +@ 4, 0 SAY "Name " GET adr->Name VALID !empty(adr->Name) +@ 4,35 SAY "First " GET adr->First +@ 6, 0 SAY "Country" GET adr->Country PICTURE "@!" +@ 8, 0 SAY "Zip " GET adr->Zip PICT "@!" VALID !empty(adr->Zip) +@ 9, 0 SAY "City " GET adr->City +@ 10, 0 SAY "Street " GET adr->Street +READ diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/forth.4th b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/forth.4th new file mode 100644 index 0000000..44cade2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/forth.4th @@ -0,0 +1,10 @@ +\ Test file for Forth Syntax +\ Comments are like this +10 constant ten +: .hello ( -- ) + s" Hello World" type [char] ! emit ; +: hello ( flag -- ) + ?dup if .hello then drop ; +hello + + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_77.for b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_77.for new file mode 100644 index 0000000..73181c0 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_77.for @@ -0,0 +1,42 @@ +* Fortran 77 Syntax Test File +* Some Comments about this file + +* Hello World + + PROGRAM HELLOW + PRINT '(A)', 'Hello, world' + STOP + END + +* euclid.f (FORTRAN 77) +* Find greatest common divisor using the Euclidean algorithm + + PROGRAM EUCLID + PRINT *, 'A?' + READ *, NA + IF (NA.LE.0) THEN + PRINT *, 'A must be a positive integer.' + STOP + END IF + PRINT *, 'B?' + READ *, NB + IF (NB.LE.0) THEN + PRINT *, 'B must be a positive integer.' + STOP + END IF + PRINT *, 'The GCD of', NA, ' and', NB, ' is', NGCD(NA, NB), '.' + STOP + END + + FUNCTION NGCD(NA, NB) + IA = NA + IB = NB + 1 IF (IB.NE.0) THEN + ITEMP = IA + IA = IB + IB = MOD(ITEMP, IB) + GOTO 1 + END IF + NGCD = IA + RETURN + END diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_95.f95 b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_95.f95 new file mode 100644 index 0000000..3314b78 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/fortran_95.f95 @@ -0,0 +1,45 @@ +! Fortran 95 Syntax Test File +! Some comments about this file + +! Hello World +program HelloWorld + write (*,*) 'Hello, world!' ! This is an inline comment +end program HelloWorld + +program HelloWorld2 + ihello = 0 + 1 if (ihello.NE.10) ! This line shows the label style + write (*,*) "Hello, World2!" + ihello = ihello + 1 + goto 1 + end if +end program HelloWord2 + +!---------------------------------------------------------- +subroutine Swap_Real(a1, a2) + + implicit none + +! Input/Output + real, intent(inout) :: a1(:), a2(:) + +! Locals + integer :: lb(1), & !Lower bound + ub(1) !Upper bound + integer i + real a + +! Get bounds + lb = lbound(a1) + ub = ubound(a1) + +! Swap + do i = lb(1), ub(1) + a = a1(i) + a1(i) = a2(i) + a2(i) = a + end do + +end subroutine Swap_Real + +!---------------------------------------------------------- diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/glsl.glsl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/glsl.glsl new file mode 100644 index 0000000..a6ef335 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/glsl.glsl @@ -0,0 +1,19 @@ +// Syntax Highlighting Test File for GLSL +// Comment Text + +#define MAX_JOINT_NUM 36 +#define MAX_LIGHT_NUM 8 + +uniform mat4 JointTransform[MAX_JOINT_NUM]; + +void main() +{ + int index; + float dist; + mat4 ModelTransform = gl_ModelViewProjectionMatrix; + index = int(gl_Color.r * 255.99); + mat4 vertTran = JointTransform[index - 1]; + index = int(gl_Color.g * 255.99); + if(index > 0) + vertTran += JointTransform[index - 1]; +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/groovy.groovy b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/groovy.groovy new file mode 100644 index 0000000..256331e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/groovy.groovy @@ -0,0 +1,73 @@ +/** + * Mortgage Calculator + * @author: Jeremy Rayner + * based on algorithms by Jeff Louie, Dr W Carlini and Newton + */ + +println "__..::~~'''~~::..__" +println "Mortgage Calculator" +println "~~~~~~~~~~~~~~~~~~~" +println "Please input 3 of the 4 values in your mortgage calculation" +println "This program will then calculate the value you leave blank" +println "" + +def variables = [ + "Amount of mortgage" : 0.0, + "Annual interest rate (%)" : 0.0, + "Loan duration (months)" : 0.0, + "Monthly payments" : 0.0 +] + +for (entry in variables.entrySet()) { + print("${entry.key}:") + def userInput = System.in.readLine() + if ("" == userInput) { + valueToCalculate = entry.key + } else { + entry.value = userInput.toDouble() + } +} + +println "$valueToCalculate = ${calculateValueOf(valueToCalculate)}" + +def calculateValueOf(valueToCalculate) { + def result = 0 + def principal = variables["Amount of mortgage"] + def interest = variables["Annual interest rate (%)"] / 1200 + def months = variables["Loan duration (months)"] + def payment = variables["Monthly payments"] + + switch (valueToCalculate) { + case "Amount of mortgage": + result = 1 + interest + result = 1/Math.pow(result,months) + result = ((1-result)/interest) * payment + break + case "Loan duration (months)": + result = (1 - (principal * interest / payment)) + result = Math.log(result) + result = - result / Math.log(1 + interest) + break + case "Monthly payments": + result = 1 + interest + result = 1 / Math.pow(result,months) + result = (principal * interest) / (1 - result) + break + case "Annual interest rate (%)": + result = payment / principal + def diff = 100; def accuracy = 0.00001; def maxIterations = 1000 + def index = 0 + while ((diff > accuracy) && (index < maxIterations)) { + def temp = result + def numerator = (principal * temp / payment) + Math.pow((1 + temp), -months) - 1 + def denominator= (principal / payment) - months * Math.pow((1 + temp), (-months - 1)) + result = temp - (numerator / denominator) + diff = result - temp + diff = Math.abs(diff) + index++ + } + result *= 1200 + break + } + return result +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/gui4cli.gui b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/gui4cli.gui new file mode 100644 index 0000000..4634f0a --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/gui4cli.gui @@ -0,0 +1,20 @@ +// Syntax Highlighting test file for Gui4Cli +// Some Comments about this file +// Note lexer only works correctly with CRLF eol chars + +WINDOW 10 10 180 20 'IconBar' + Winattr style clear/topmost/move/remsize/noborder/border/tool + winattr background color 200/200/220 + +// Control +if $test = 0 + cutvar buff cut char $wrapWidth buff2 +else + cutvar buff cut char $test buff2 +endif + +// Event +xOnKey F1 + run :somthing + lv add $somthing + add diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haskell.hs b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haskell.hs new file mode 100644 index 0000000..6004c4c --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haskell.hs @@ -0,0 +1,39 @@ +-- Syntax Highlighting test file for Haskell +-- Some comments about this file + +-- Hello World in Haskell +putStrLn "Hello, Haskell" + +-- Simple do structure +do putStrLn "What is 2 + 2?" + x <- readLn + if x == 4 + then putStrLn "You're right!" + else putStrLn "You're wrong!" + +-- Class def +class Num a where + (+) :: a -> a -> a + negate :: a -> a + +-- Data Declaration +data Set a = NilSet + | ConsSet a (Set a) + +-- Import statement +import somthing + +-- Instance +instance Num Int where + x + y = addInt x y + negate x = negateInt x + +-- Module +module Tree ( Tree(Leaf,Branch), fringe ) where + +data Tree a = Leaf a | Branch (Tree a) (Tree a) + +fringe :: Tree a -> [a] +fringe (Leaf x) = [x] +fringe (Branch left right) = fringe left ++ fringe right + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haxe.hx b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haxe.hx new file mode 100644 index 0000000..5bb56bb --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/haxe.hx @@ -0,0 +1,32 @@ +// Syntax Highlighting Test File for haXe +// Comments are like this +/* Mulitline comments are like + * this block of text + */ + +// Ints / Floats +0; +-1234; +0xFF00; +123.4; + +// Strings +"Hello World"; +"Unclosed String; + +// Constants +true; +false; +null; + +// Class Def +package my.pack; + +class MyClass { + var id : Int; + static var name : String = "MyString"; + function foo() : Void { + } + static function bar( s : String, v : Bool ) : Void { + } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/html.html b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/html.html new file mode 100644 index 0000000..8342f22 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/html.html @@ -0,0 +1,39 @@ +<!-- Syntax Highlighting Test File for Html --> +<%@ LANGUAGE=VBScript %> +<% OPTION EXPLICIT %> +<!-- Embedded ASP --> +<% + Dim sMessage + Dim bIncludeJavaScript + + sMessage = "Hello World" 'This is the message to be displayed + + 'Getting a request value that defines if the javascript part should be included + bIncludeJavaScript = FALSE + If (Request("withJavaScript") = "Y") Then + bIncludeJavaScript = TRUE + End If +%> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> + <head> + <!-- Some Comments about this file --> + <title>Hello World</title> + <link href="hello.css" rel="stylesheet" type="text/css"> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <script language="JavaScript" type="text/JavaScript"> + <!-- Some Embedded JavaScript --!> + <!-- + function MM_swapImgRestore() { //v3.0 + var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc; + } + //--> + </script> + </head> + <body> + <div> + <h1>Hello World HTML</h1> + <p class="bigHello">HELLO HELLO HELLO</p> + </div> + </body> +</html> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/inno_setup_script.iss b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/inno_setup_script.iss new file mode 100644 index 0000000..b986085 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/inno_setup_script.iss @@ -0,0 +1,34 @@ +; Syntax Highlighting Test File for Inno Setup Scripts +; Some comments about this file + +; Preprocessor +#pragma verboselevel 9 +#define Debug + +; Sections +[Setup] +AppName=My Program +AppVerName=My Program version 1.5 +DefaultDirName={code:MyConst}\My Program +DefaultGroupName=My Program +UninstallDisplayIcon={app}\MyProg.exe +InfoBeforeFile=Readme.txt +OutputDir=userdocs:Inno Setup Examples Output + +[Files] +Source: "MyProg.exe"; DestDir: "{app}"; Check: MyProgCheck; BeforeInstall: BeforeMyProgInstall('MyProg.exe'); AfterInstall: AfterMyProgInstall('MyProg.exe') +Source: "MyProg.chm"; DestDir: "{app}"; Check: MyProgCheck; BeforeInstall: BeforeMyProgInstall('MyProg.chm'); AfterInstall: AfterMyProgInstall('MyProg.chm') +Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme + +[Code] +var + MyProgChecked: Boolean; + MyProgCheckResult: Boolean; + FinishedInstall: Boolean; + +function InitializeSetup(): Boolean; +begin + Result := MsgBox('InitializeSetup:' #13#13 'Setup is initializing. Do you really want to start setup?', mbConfirmation, MB_YESNO) = idYes; + if Result = False then + MsgBox('InitializeSetup:' #13#13 'Ok, bye bye.', mbInformation, MB_OK); +end; diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/issuelist.isl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/issuelist.isl new file mode 100644 index 0000000..2300494 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/issuelist.isl @@ -0,0 +1,26 @@ +; Syntax Highlighting Test file for IssueList +; Comments look like this + ++ This item is done +- This is still open +; This is a cancelled item, so it is shown in gray +? This item still needs to be clarified + There are some questions open to solve it. + In detail: + - Is it too expensive ? + + Can it technically be done ? + +- Technically it is quite challenging, + and some details are yet open. + But can be surely solved. + +So there are some more colors: + +# for maybe something important +. Because blue looks cool + +~ This could be used for deep-red items or so + +;;; Local Variables: +;;; mode: outline +;;; End: diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/java.java b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/java.java new file mode 100644 index 0000000..c41ae44 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/java.java @@ -0,0 +1,42 @@ +// Syntax Highlighting Test File For Java +// Comment Line + +/* + * HelloWorld Using Swing + */ +import javax.swing.*; + +public class HelloWorldSwing { + /** + * Create the GUI and show it. For thread safety, + * this method should be invoked from the + * event-dispatching thread. + */ + private static void createAndShowGUI() { + //Create and set up the window. + JFrame frame = new JFrame("HelloWorldSwing"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + //Add the ubiquitous "Hello World" label. + JLabel label = new JLabel("Hello World"); + frame.getContentPane().add(label); + + //Display the window. + frame.pack(); + frame.setVisible(true); + + a = 1000; + // unclosed string + System.out.println("test); + } + + public static void main(String[] args) { + //Schedule a job for the event-dispatching thread: + //creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/javascript.js b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/javascript.js new file mode 100644 index 0000000..5f3707d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/javascript.js @@ -0,0 +1,16 @@ +// Syntax Highlighting Test File for JavaScript +// Some Comments about this file + +function HelloAlert () +{ + alert("Hello World!") +} + +function count(to) +{ + for (i = 0; i <= to; i++) + { + document.write("The number is " + i) + document.write("<br />") + } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/kix.kix b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/kix.kix new file mode 100644 index 0000000..fe3787e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/kix.kix @@ -0,0 +1,27 @@ +; Syntax Highighting test file for KIXtart scripts +; Some comments about this file + +Dim $Type, $S, $J, $R + +If KeyExist("HKCU\Software\Hello") = 1 + $Type = Readtype("HKCU\Software\Hello","World") + $R = ReadValue("HKCU\Software\Hello", "World2") + + Select + Case $Type = "Reg_Multi_SZ" + $S = Split($R,"|") + $J = Join($S," ") + Case $Type = "Reg_SZ" + $J = $R + Case 1 + @Error = 5 + EndSelect + + If $J = "HelloWorld" + ? "We have a match. The string returned was: " $J + Else + ? "No match found. The string returned was: " $J + EndIf +Else + Exit 1 +EndIf diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/korn_shell_script.ksh b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/korn_shell_script.ksh new file mode 100644 index 0000000..4600ee3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/korn_shell_script.ksh @@ -0,0 +1,11 @@ +# Syntax Highlighting Test File for Korn Shell +# Some comments about this file + +export FRIENDS="Jon Kosuke Bill Sandra" +for FRIEND in ${FRIENDS} +do + # each loop say hello + echo "HELLO " $FRIEND +done + +exit 0 diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/latex.tex b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/latex.tex new file mode 100644 index 0000000..6ac3502 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/latex.tex @@ -0,0 +1,10 @@ +% Syntax Highlighting Test File For LaTeX +% Some Comments About This File +\documentclass{article} +\title{Lets Say Hello} +\author{Jane Doe} +\date{April 2007} +\begin{document} + \maketitle + Hello world! +\end{document} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lisp.lisp b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lisp.lisp new file mode 100644 index 0000000..30bc069 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lisp.lisp @@ -0,0 +1,26 @@ +; Syntax Highlighting Test File for Lisp +; Comment Line + +; Lisp funciton and keyword test +(defpackage :mypackage + (:use :common-lisp :cffi)) + +; hello version 1 +(defun hello-word1 () + (print (list 'HELLO 'WORLD))) + +; hello version 2 +(defun hello-world () + (format t "hello world~%")) + +; Lets do some factorials too +(defun factorial (N) + (if (= N 1) + 1 + (* N (factorial (- N 1))))) + +; Fibonacci numbers are fun too +(defun fibonacci (N) + (if (or (zerop N) (= N 1)) + 1 + (+ (fibonacci (- N 1)) (fibonacci (- N 2))))) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lout.lt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lout.lt new file mode 100644 index 0000000..23c299e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lout.lt @@ -0,0 +1,34 @@ + # Lexer Test File for Basser Lout + # http://en.wikipedia.org/wiki/Lout + # Some Comments about this file + + # Use the `doc' document class and its default style. + @SysInclude { doc } + + @Document + @InitialFont { Times Base 10p } + // + + # Beginning of document contents. + @Text @Begin + + # Paragraph with a number of differen't keywords, symbols and strings in it + @PP + Hello Word this is a paragraph. One can easily embed @B { bold } or + @I { italic } text. One can also easily change the style of + text, such as { Helvetica Base } @Font { changing the font + being used } Here is a string @Code "@Font" and a string that + is not closed @Code "@Font. + + @BeginSections + @Section @Title { The First Section } + @Begin + + @PP + This is the content of a section. + + @End @Section + @EndSections + + @End @Text + # End of the document. diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lua.lua b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lua.lua new file mode 100644 index 0000000..8f65a80 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/lua.lua @@ -0,0 +1,38 @@ +-- Lua Syntax Test File +-- Some comments about this file + +-- Hello World Program +print "Hello World" +print "An Open String + +-- Factorial Calculator +function factorial(n) + if n == 0 then + return 1 + end + return n * factorial(n - 1) +end + +-- Fibonacci Numbers +fibs = { 1, 1 } +setmetatable(fibs, { + __index = function(name, n) + name[n] = name[n - 1] + name[n - 2] + return name[n] + end +}) + +-- string buffer implementation +function newbuf () + local buf = { + _buf = {}, + clear = function (self) self._buf = {}; return self end, + content = function (self) return table.concat(self._buf) end, + append = function (self, s) + self._buf[#(self._buf) + 1] = s + return self + end, + set = function (self, s) self._buf = {s}; return self end, + } + return buf +end
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/makefile.mak b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/makefile.mak new file mode 100644 index 0000000..c78e3bb --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/makefile.mak @@ -0,0 +1,20 @@ +# Syntax Highlighting Test File for Makefile +# Some more comments about this file + +# Some Identifiers and Preproccessor stuff +!ifndef DEBUG +CFLAGS=-DDEBUG -g $(CFLAGS) +!else +CFLAGS=-Os $(CFLAGS) +!endif + +# Some Targets +helloworld: helloworld.o + cc -o $@ $< + +helloworld.o: helloworld.c + cc -c -o $@ $< + +.PHONY: clean +clean: + rm -f helloworld helloworld.o *~ core diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/mako.mako b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/mako.mako new file mode 100644 index 0000000..53d7de4 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/mako.mako @@ -0,0 +1,17 @@ +# Syntax Highlighting Test File for Mako Templates +# Comments are like this + +<%def name="label(field, content)"> +<label for="${field}">${content}</label> +</%def> + +<%def name="make_option(opt)"> + <% + import os + from mako.template import Template + + f = open("%s/templates/pages/admin/options/%s" \ + % (c.root, opt)).read() + return Template(f).render() + %> +</%def> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/masm.masm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/masm.masm new file mode 100644 index 0000000..3caed05 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/masm.masm @@ -0,0 +1,20 @@ +; Syntax Highlighting Test File for MASM +; Comment Line's are like this +; Hello world in MASM Assembly +.MODEL tiny +.CODE + ORG 100h +HELLO PROC + MOV AH,09h + LEA DX,msg + INT 21h ;Display Hello World + + MOV AX,4C00h ;Exit to DOS + INT 21h +HELLO ENDP + msg DB 'Hello World$' + END HELLO + + + +
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/matlab.matlab b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/matlab.matlab new file mode 100644 index 0000000..9335c8f --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/matlab.matlab @@ -0,0 +1,54 @@ +% Syntax Highlight Test File for MatLab +% Some comments about this file + +% HelloWorld in MatLab +disp('Hello World'); + +% And now some other randomness to test different color regions +for j=1:4, + j +end + +A = 1; B = []; +if(A|B) disp 'The statement is true', end; + +% Plotting Polynomials +x=[27.7 28 29 30]; +a=[4.1 4.3 4.1]; +b=[0.749 0.503 -0.781]; +c=[0.0 -0.819 -0.470]; +d=[-0.910 0.116 0.157]; + +for i=1:3 + ['p_' num2str(i) '(x) = ' num2str(a(i)) ' + ' ... + num2str(b(i)) ' (x - ' num2str(x(i)) ') + ' ... + num2str(c(i)) ' (x - ' num2str(x(i)) ')^2 + ' ... + num2str(d(i)) ' (x - ' num2str(x(i)) ')^3'] +end; + +%--------------------------------------------------------------------- +function y = nev(xx,n,x,Q) +% NEV Neville's algorithm as a function +% y= nev(xx,n,x,Q) +% +% inputs: +% n = order of interpolation (n+1 = # of points) +% x(1),...,x(n+1) x coords +% Q(1),...,Q(n+1) y coords +% xx=evaluation point for interpolating polynomial p +% +% output: p(xx) +for i = n:-1:1 + for j = 1:i + Q(j) = (xx-x(j))*Q(j+1) - (xx-x(j+n+1-i))*Q(j); + Q(j) = Q(j)/(x(j+n+1-i)-x(j)); + end +end + +y = Q(1); + +%--------------------------------------------------------------------- +function ssum = geom(a,N) + n=0:N; + ssum = sum(a.^n); +end diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/microsoft_sql.sql b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/microsoft_sql.sql new file mode 100644 index 0000000..a9efca9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/microsoft_sql.sql @@ -0,0 +1,149 @@ +-- MS SQL test code for lexer +CREATE TABLE page ( + id INT NOT NULL AUTO_INCREMENT, + pagename VARCHAR(100) NOT NULL, + hits INT NOT NULL DEFAULT 0, + pagedata TEXT NOT NULL DEFAULT '', + cached_html TEXT NOT NULL DEFAULT '', -- added with 1.3.11 + PRIMARY KEY (id), + UNIQUE (pagename) +); + +CREATE TABLE version ( + id INT NOT NULL, + version INT NOT NULL, + mtime INT NOT NULL, + minor_edit TINYINT DEFAULT 0, + content TEXT NOT NULL DEFAULT '', + versiondata TEXT NOT NULL DEFAULT '', + PRIMARY KEY (id,version) +); +CREATE INDEX version_mtime ON version (mtime); + +CREATE TABLE recent ( + id INT NOT NULL, + latestversion INT, + latestmajor INT, + latestminor INT, + PRIMARY KEY (id) +); + +CREATE TABLE nonempty ( + id INT NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE link ( + linkfrom INT NOT NULL, + linkto INT NOT NULL +); +CREATE INDEX linkfrom ON link (linkfrom); +CREATE INDEX linkto ON link (linkto); + +CREATE TABLE session ( + sess_id CHAR(32) NOT NULL DEFAULT '', + sess_data BLOB NOT NULL, + sess_date INT UNSIGNED NOT NULL, + sess_ip CHAR(40) NOT NULL, + PRIMARY KEY (sess_id) +); +CREATE INDEX sessdate_index ON session (sess_date); +CREATE INDEX sessip_index ON session (sess_ip); + +-- Optional DB Auth and Prefs +-- For these tables below the default table prefix must be used +-- in the DBAuthParam SQL statements also. + +CREATE TABLE pref ( + userid CHAR(48) NOT NULL UNIQUE, + prefs TEXT NULL DEFAULT '', + passwd CHAR(48) DEFAULT '', + groupname CHAR(48) DEFAULT 'users', + PRIMARY KEY (userid) +); +-- update to 1.3.12: (see lib/upgrade.php) +-- ALTER TABLE pref ADD passwd CHAR(48) DEFAULT ''; +-- ALTER TABLE pref ADD groupname CHAR(48) DEFAULT 'users'; + +-- better use the extra pref table where such users can be created easily +-- without password. +--CREATE TABLE user ( +-- userid CHAR(48) NOT NULL UNIQUE, +-- passwd CHAR(48) DEFAULT '', +-- prefs TEXT NULL DEFAULT '', +-- groupname CHAR(48) DEFAULT 'users', +-- PRIMARY KEY (userid) +--); + +--CREATE TABLE member ( +-- userid CHAR(48) NOT NULL, +-- groupname CHAR(48) NOT NULL DEFAULT 'users', +-- INDEX (userid), +-- INDEX (groupname) +--); +--CREATE INDEX member_userid ON member (userid); +--CREATE INDEX member_groupname ON member (groupname); + +-- only if you plan to use the wikilens theme +CREATE TABLE rating ( + dimension INT(4) NOT NULL, + raterpage INT(11) NOT NULL, + rateepage INT(11) NOT NULL, + ratingvalue FLOAT NOT NULL, + rateeversion INT(11) NOT NULL, + tstamp TIMESTAMP(14) NOT NULL, + PRIMARY KEY (dimension, raterpage, rateepage) +); +CREATE INDEX rating_dimension ON rating (dimension); +CREATE INDEX rating_raterpage ON rating (raterpage); +CREATE INDEX rating_rateepage ON rating (rateepage); + +-- if ACCESS_LOG_SQL > 0 +-- only if you need fast log-analysis (spam prevention, recent referrers) +-- see http://www.outoforder.cc/projects/apache/mod_log_sql/docs-2.0/#id2756178 +CREATE TABLE accesslog ( + time_stamp INT UNSIGNED, + remote_host VARCHAR(50), + remote_user VARCHAR(50), + request_method VARCHAR(10), + request_line VARCHAR(255), + request_args VARCHAR(255), + request_file VARCHAR(255), + request_uri VARCHAR(255), + request_time CHAR(28), + status SMALLINT UNSIGNED, + bytes_sent SMALLINT UNSIGNED, + referer VARCHAR(255), + agent VARCHAR(255), + request_duration FLOAT +); +CREATE INDEX log_time ON accesslog (time_stamp); +CREATE INDEX log_host ON accesslog (remote_host); +-- create extra indices on demand (usually referer. see plugin/AccessLogSql) + +ALTER TABLE ticket_history ADD FOREIGN KEY (ticket_id) REFERENCES `ticket(id)`; +ALTER TABLE ticket_history_type ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE ticket_history_type ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`; +ALTER TABLE ticket_history_type ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`; +ALTER TABLE article_type ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE article_type ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`; +ALTER TABLE article_type ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`; +ALTER TABLE article_sender_type ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE article_sender_type ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`; +ALTER TABLE article_sender_type ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`; +ALTER TABLE article_flag ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE article ADD FOREIGN KEY (article_sender_type_id) REFERENCES `article_sender_type(id)`; +ALTER TABLE article ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE article ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`; +ALTER TABLE article ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`; +ALTER TABLE article ADD FOREIGN KEY (article_type_id) REFERENCES `article_type(id)`; +ALTER TABLE article ADD FOREIGN KEY (ticket_id) REFERENCES `ticket(id)`; +ALTER TABLE article_plain ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE article_plain ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`; +ALTER TABLE article_plain ADD FOREIGN KEY (article_id) REFERENCES `article(id)`; +ALTER TABLE article_attachment ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE article_attachment ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`; +ALTER TABLE article_attachment ADD FOREIGN KEY (article_id) REFERENCES `article(id)`; +ALTER TABLE standard_response ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`; +ALTER TABLE standard_response ADD FOREIGN KEY (change_by) REFERENCES `system_user(id)`; +ALTER TABLE standard_response ADD FOREIGN KEY (valid_id) REFERENCES `valid(id)`;
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/netwide_assembler.nasm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/netwide_assembler.nasm new file mode 100644 index 0000000..d933dac --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/netwide_assembler.nasm @@ -0,0 +1,24 @@ +; Syntax Highlighting Test File for NASM +; Some Comments about this file +; Hello World in NASM + +section .text + +_start: + push dword len + push dword msg + push dword 1 + mov eax, 0x4 + call _syscall + add esp, 12 + + push dword 0 + mov eax, 0x1 + call _syscall + +_syscall: + int 0x80 + ret + +msg db "Hello World",0xa +len equ $ - msg diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/newlisp.lsp b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/newlisp.lsp new file mode 100644 index 0000000..d3e8032 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/newlisp.lsp @@ -0,0 +1,22 @@ +; Syntax Highlighting Test File for newLISP +; Comments are like this + +(context 'EditraTest) + +(define (hello) + "Says hello." + (println "Hello world")) + +(define (EditraTest:EditraTest substance (times 10)) + (let ((n times)) + (while (> n 0) + (println (format "%d bottles of %s on the wall" n (string substance))) + (dec 'n))) + (println "Time to get to the " substance " store!")) + +(context 'MAIN) + +(dolist (substance '("beer" "apple juice" "spam")) + (EditraTest substance) + (println)) + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nonmem_control_stream.ctl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nonmem_control_stream.ctl new file mode 100644 index 0000000..467f7d9 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nonmem_control_stream.ctl @@ -0,0 +1,21 @@ +$PROB theophylline pharmacodynamics standard control stream +$DATA theopd.dat IGNORE # +$INPUT ID TIME THEO AGE WT GEND RACE DIAG PEFR=DV +$ESTIM PRINT=1 POSTHOC +MSFO=theopd.msf +$COV +$THETA (0,150.,) ;popE0 1 +$THETA (0,200.,) ;popEMAX 2 +$THETA (.001,10,) ;popEC50 3 +$OMEGA 0.5 ;etaE0 1 +$OMEGA 0.5 ;etaEMAX 2 +$OMEGA 0.5 ;etaEC50 3 +$SIGMA 100 ;errSD 1 +$PRED +E0=THETA(1)*EXP(ETA(1)) +EMAX=THETA(2)*EXP(ETA(2)) +EC50=THETA(3)*EXP(ETA(3)) +Y = E0 + EMAX*THEO/(THEO+EC50) + ERR(1) +$TABLE ID TIME THEO AGE WT GEND RACE DIAG +E0 EMAX EC50 Y +NOPRINT ONEHEADER FILE=theopd.fit diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nullsoft_installer_script.nsi b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nullsoft_installer_script.nsi new file mode 100644 index 0000000..694fcb6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/nullsoft_installer_script.nsi @@ -0,0 +1,26 @@ +; Syntax Highlighting Test File for NSIS +; Comments are Like this +# Comments can also be like this + +; Function and String +!define PRODUCT_NAME "HelloWorld" + +; Function and Label +SetCompressor lzma + +; Section Definition +Section "MainSection" SEC01 + SetOutPath "$INSTDIR" + SetOverwrite try + +SectionEnd + +; Section, Function, Variable, String +Section -Post + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" +SectionEnd + +; Function Definition +Function LaunchHello + Exec '"$INSTDIR\hello.exe"' +FunctionEnd diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/objective_c.mm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/objective_c.mm new file mode 100644 index 0000000..a812f29 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/objective_c.mm @@ -0,0 +1,56 @@ +// Syntax Highlighting Test File for Objective C +// Comments are like this +/* Multi line comments are like + * this + */ + +// Hello World +#import <stdio.h> + +int main( int argc, const char *argv[] ) { + printf( "Hello World\n" ); + printf( "Unclosed string ); + return 0; +} + +// Interface +#import <Foundation/NSObject.h> + +@interface Fraction: NSObject { + int numerator; + int denominator; +} + +-(void) print; +-(void) setNumerator: (int) d; +-(void) setDenominator: (int) d; +-(int) numerator; +-(int) denominator; +@end + +// Class implementation +#import "Fraction.h" +#import <stdio.h> + +@implementation Fraction +-(void) print { + printf( "%i/%i", numerator, denominator ); +} + +-(void) setNumerator: (int) n { + numerator = n; +} + +-(void) setDenominator: (int) d { + denominator = d; +} + +-(int) denominator { + return denominator; +} + +-(int) numerator { + return numerator; +} +@end + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/octave.oct b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/octave.oct new file mode 100644 index 0000000..3c02298 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/octave.oct @@ -0,0 +1,15 @@ +# Syntax Highlight Test File for Octave +# Some comments about this file + +# HelloWorld in Octave +printf("Hello World\n") + +a = [ 1, 1, 2; 3, 5, 8; 13, 21, 34 ] + +function s = plus (varargin) + if (nargin==0) + s = 0; + else + s = varargin{1} + plus (varargin{2:nargin}); + endif +endfunction diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ooc.ooc b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ooc.ooc new file mode 100644 index 0000000..a240cd6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ooc.ooc @@ -0,0 +1,38 @@ +// Syntax Highlighting Sample File for OOC +// Comments are like this +import structs/ArrayList + +SPACE := const ' ' + +StringUtilities: class { + split: static func (string: String) -> ArrayList<String> { + tokens := ArrayList<String> new() + + lastIndex := 0 + for(index in 0..string length()) { + if(string[index] == SPACE) { + token := string[lastIndex..index] + + if(!token empty?()) { + tokens add(token) + } + lastIndex = index + 1 + } + } + + rest := string[lastIndex..string length()] + if(!rest empty?()) { + tokens add(rest) + } + + return tokens + } +} + +main: func(arguments: ArrayList<String>) { + for(argument in arguments) { + for(token in StringUtilities split(argument)) { + token println() + } + } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pascal.pas b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pascal.pas new file mode 100644 index 0000000..7133c6d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pascal.pas @@ -0,0 +1,31 @@ +{ Syntax Highlighting Test File for Pascal + Comments are like this + Hello World in Pascal +} +program Hello; + +uses + crt; + +begin + ClrScr; + Write('Hello world'); + Readln; +end. + +program Variables; + +const + pi: Real = 3.14; + +var + Num1, Num2, Ans: Integer; + +begin + Ans := 1 + 1; + Num1 := 5; + Ans := Num1 + 3; + Num2 := 2; + Ans := Num1 - Num2; + Ans := Ans * Num1; +end. diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/perl.pl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/perl.pl new file mode 100644 index 0000000..96c9fcd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/perl.pl @@ -0,0 +1,45 @@ +# Syntax Highlighting test file for Perl +# Some comments about this file + +# Hello world in Perl +print "Hello, world!\n"; + +# Numerous other style region tests + +# Number +$number1 = 42; + +# String Tests +$answer = "The answer is $number1"; # Variable interpolation +$h1 = "Hello World \"Perl\""; # Double quoted string +$h2 = 'Hello World "Perl"'; # Single Quoted String +$h3 = qq(Hello World "Perl"); # qq() instead of quotes +$multilined_string =<<EOF +A multilined string that is terminated with +with the word "EOF" +EOF + +# Array +@greetings = ('Hello', 'Holla', 'Konichiwa'); + +# Hash Table +%translate = ( + Hello => 'Hola', + Bye => 'Adios' +); +print $translate[Hello]; + +=item B<function1> + +This is a POD doc section + +=cut +sub function1 { + my %args = @_; + print "Joe said '$args{Joe}'\n"; +} +function1( Joe => "Hello World" ); + +# Some Regular Expressions +$x =~ m/abc/ +$x =~ s/abc/aBc/; # substitute lowercase b with uppercase B diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/php.php b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/php.php new file mode 100644 index 0000000..2df8144 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/php.php @@ -0,0 +1,69 @@ +<?php + // Syntax Highlighting Test File for PHP + /* Some comments about this file */ + // Comment line + $hello = "HELLO" + $world = "WORLD" + + include_once($hello_root_path . 'hellolib.php'); + + function print_mood() + { + switch($_GET['friendly']) + { + case "yes": + echo "<h1>$hello $world</h1>"; + break; + case "no": + echo "<h1>Bah!!</h1>" + break; + default: + echo "<h1>$hello???</h1>"; + } + } + + /* Class Definition Test */ + class Foo + { + var $myvalue; + + function bar() + { + if (isset($this)) + { + echo '$this is defined ('; + echo get_class($this); + echo ")\n"; + } else { + echo "\$this is not defined.\n"; + } + } + function helloA(param) { + echo "$param"; + } + function printEndTag() { + echo "?>" + } + function printStartTag() { + echo "<?php" + } + + } + + function hello(param) { + echo "$param"; + } +?> + +<html> + <head> + <!-- Some Embedded HTML --> + <title>Hello.php</title> + </head> + <body> + <div> + <p>Today is <?php disp_date() ?> and this website says <?php print_mood() ?></p> + </div> + </body> +</html> + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pike.pike b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pike.pike new file mode 100644 index 0000000..9827b46 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pike.pike @@ -0,0 +1,28 @@ +// Syntax Highlighting test file for Pike +/* Some Comments about this file */ + +// Hello world in Pike +int main() { + write("Hello world!\n"); + return 0; +} + +//! \todo <- Documentation Doxygen Keyword highlighting +mixed something; +something = 5; +something = 2.5; + +string testString; +testString = "a regular string"; +testString = "an open string + +// Print a list of unique characters +string data = "an apple a day"; +array(string) chars = data/""; +mapping(string:int) seen = ([]); + +foreach(chars ;; string char) + seen[char]++; + +write("unique chars are: %s\n", sort(indices(seen))*""); + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pl_sql.plsql b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pl_sql.plsql new file mode 100644 index 0000000..9492221 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/pl_sql.plsql @@ -0,0 +1,94 @@ +/** + * Syntax Highlighting Test File for PLSQL + * This is a package example for syntax colourising of + * Oracle PL/SQL 11g + * It is developed to meet at least my requirements. + * Copyright 2007 Thomas G. Keul + * @author Thomas G. Keul (tgkeul@web.de) + */ + + /** + * Example pldoc header of a procedure. + * + * @param param_1 in parameter + * @param param_2 out parameter + * @param param_3 in out parameter + * @throws no_data_found + */ + procedure my_proc + (param_1 in my_table.the_key%type, + param_2 out my_table%rowtype, + param_3 in out nocopy plsql_table_type); + + /** + * Example pldoc header of a function. + * + * @param param_1 in parameter + * @return true or false + */ + function my_func (param_1 in pls_integer) return boolean; +end example +/ + +create or replace package body example is + + type t_boolean_table is table of boolean index by binary_integer; + subtype t_sample is positive range 1..6; + real_sample constant t_sample := 3; + + cursor get_it (param_1 in varchar2) is + select /*+ a Hint */ + distinct foo + from bar + where the_key = param_1 + and a_column is not null; + + procedure nested_outer (param_1 in number) is + procedure nested_inner is + begin + if a_collection.count > 0 + then + for l in a_collection.first .. a_collection.last + loop + doit; -- just for fun + end loop; + elsif its_a_rainy_day + then help (who => me); + else sigh; + end if; + end nested_inner; + + begin + update a_table + set a_column = 1 + where the_key = 4711 + returning something bulk collect into a_collection; + + << a_label >> + for ex in 1..3 + loop + case ex + when 1 then dbms_output.put_line ('number one'); + when 2 then junk := greatest (ex, nvl(foo, bar)); + when 3 then exit (a_label); + else rollback; + end case; + end loop a_label; + + exception + when no_data_found then null; + when others then raise; + end nested_outer; + +begin + oops := 'no string eol'; +end example; +/ +-- ----------------------------------------------------------- +declare + d date := sysdate; +begin + dbms_output.put_line (to_char (sysdate, 'DD.MM.YYYY')); +end; +-- ----------------------------------------------------------- +exec dbms_job.run(4711); diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/plain_text.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/plain_text.txt new file mode 100644 index 0000000..f92fd39 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/plain_text.txt @@ -0,0 +1,4 @@ +Here is some plain text to test the editor with highlighting in an in active state. This is rather boring isn't it? + +Hello World + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/postscript.ps b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/postscript.ps new file mode 100644 index 0000000..dedf668 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/postscript.ps @@ -0,0 +1,11 @@ +%!PS +% Syntax Highlighting Test File for Postscript +% Comments are like this +% Hello World in Postscript +1.00000 0.99083 scale +/Courier findfont 12 scalefont setfont +0 0 translate +/row 769 def +85 {/col 18 def 6 {col row moveto (Hello World)show /col col 90 add def} +repeat /row row 9 sub def} repeat +showpage save restore diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/progress_4gl.4gl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/progress_4gl.4gl new file mode 100644 index 0000000..7c93df2 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/progress_4gl.4gl @@ -0,0 +1,34 @@ +/* Syntax highlight test file for Progress 4GL */ + +DEFINE TEMP-TABLE tt + FIELDS site like ld_site + FIELDS loc like ld_loc + FIELDS part like ld_part + FIELDS lot like ld_lot + FIELDS ref like ld_ref + FIELDS ldt like ld_date + FIELDS ldst like ld_status + FIELDS qoh like ld_qty_oh + FIELDS coh like ld_cust_consign_qty. + +INPUT FROM "ld-ncstkinconsignloc.d". + REPEAT TRANSACTION. + CREATE tt. + IMPORT tt. +END. + INPUT CLOSE. + +OUTPUT TO "cyc-amt-02.d". +FOR EACH tt: + FINF FIRST pt_mstr WHERE pt_part = part NO-LOCK NO-ERROR. + + FIND FIRST pl_mstr WHERE pl_prod_line = pt_prod_line NO-LOCK NO-ERROR. + FIND FIRST sct_det where sct_sim = "standard" + AND sct_site = "g1" + AND sct_part = part NO-LOCK NO-ERROR. + EXPORT site loc part lot ref + pt_prod_line + pl_inv_acct + pl_inv_cc + qoh sct_cst_tot qoh * sct_cst_tot. +END. diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/properties.ini b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/properties.ini new file mode 100644 index 0000000..02f0099 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/properties.ini @@ -0,0 +1,14 @@ +# Syntax Highlighting Test file for Properties Files +# Some comments about this file + +# Section Def +[greetings] +hello=1 +world=2 + +[food] +cheese=('gouda', 'swiss') +bread=('french', 'italian', 'sliced') +meat=('steak', 'pork') +fish=('salmon', 'tuna') +fruit=('apple', 'orange', 'watermelon') diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/python.python b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/python.python new file mode 100644 index 0000000..3414f2d --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/python.python @@ -0,0 +1,43 @@ +# Syntax Highlight Test File for Python +# Some Comments about this file + +""" +A test file for checking styles for the python highlighter. +This is a docstring + +""" +__author__ = "Cody Precord" + +# Keyword statement +import sys + +# Function Definition +def say_hello(): + """Prints hello world to the console""" + print "Hello World" + print "unclosed string + +# Class Definition +class Greeting: + """A class to represent a greeting""" + def __init__(self, language): + """initializes the greeting""" + self._lang = language + + def __str__(self): + """Returns the string representation of the greeting""" + if self._lang == "English": + return "Hello" + elif self._lang == "Spanish": + return "Holla" + else: + return "Sorry I dont know %s" % self._lang + + # Decorator's (python 2.4+) + @property + def classdocs(self): + return '\n'.join([ x.__doc__ for x in dir(self) if hasattr(x, '__doc__')]) + +if __name__ == '__main__': + say_hello() + print Greeting('English') diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/r.r b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/r.r new file mode 100644 index 0000000..abc6a7e --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/r.r @@ -0,0 +1,28 @@ +# Syntax Highlighting test file for R +# Comments look like this + +options(digits=7) + +## powers +outer(a <- -4:12, -2:7, "^") + +for (n1 in 1:7) + print(zapsmall(polyroot(1:n1), digits = 10)) + +## lowess() {incl. sort, etc}: +options(digits = 5) + +lowess(c(3,2,6,3,8,4))$y # this used to differ on Linux + +y1 <- c(3,1:2,5:2,4,1:3,3) +lowess(y1)$y +lowess(y1, f = .4)$y + +lowess(c(y1,100), f = .4)$y + +## this is the test sample from Cleveland's original lowess.doc: +x <- c(1:5, rep(6,10),8,10,12,14,50) +y <- c(18,2,15,6,10,4,16,11,7,3,14,17,20,12,9,13,1,8,5,19) +lowess(x,y, f = .25, iter = 0, delta = 0)$y +lowess(x,y, f = .25, iter = 0, delta = 3)$y +lowess(x,y, f = .25, iter = 2, delta = 0)$y diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ruby.rb b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ruby.rb new file mode 100644 index 0000000..6e74037 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/ruby.rb @@ -0,0 +1,27 @@ +# Syntax Highlighting Test File for Ruby +# Some Comments about this file +# Hello World in ruby + +# Keyword statement and string +puts 'Hello world' + +# Function Definitions +def hello2(name) + puts "Hello #{name}!" +end + +# Class Definition +class Greeter + def intialize(name = "World") + @name = name + end + def say_hello + puts "Hello #{@name}!" + end + def say_bye + puts "Bye #{@name}, come again." + end +end + +# Keyword and some Numbers +puts 5 ** 2 diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/s.s b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/s.s new file mode 100644 index 0000000..73c7b97 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/s.s @@ -0,0 +1,28 @@ +# Syntax Highlighting test file for S +# Comments look like this + +options(digits=7) + +## powers +outer(a <- -4:12, -2:7, "^") + +for (n1 in 1:7) + print(zapsmall(polyroot(1:n1), digits = 10)) + +## lowess() {incl. sort, etc}: +options(digits = 5) + +lowess(c(3,2,6,3,8,4))$y # this used to differ on Linux + +y1 <- c(3,1:2,5:2,4,1:3,3) +lowess(y1)$y +lowess(y1, f = .4)$y + +lowess(c(y1,100), f = .4)$y + +## this is the test sample from Cleveland's original lowess.doc: +x <- c(1:5, rep(6,10),8,10,12,14,50) +y <- c(18,2,15,6,10,4,16,11,7,3,14,17,20,12,9,13,1,8,5,19) +lowess(x,y, f = .25, iter = 0, delta = 0)$y +lowess(x,y, f = .25, iter = 0, delta = 3)$y +lowess(x,y, f = .25, iter = 2, delta = 0)$y diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/scheme.scm b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/scheme.scm new file mode 100644 index 0000000..2d67cb1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/scheme.scm @@ -0,0 +1,17 @@ +; Syntax Highlighting Test File for Scheme +; Comments are like this + +; Hello World +(define hello-world + (lambda () + (begin + (write 'Hello-World) + (newline) + (hello-world)))) + +; Factorial +(define (fact n) + (if (= n 0) + 1 + (* n (fact (- n 1))))) + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/smalltalk.st b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/smalltalk.st new file mode 100644 index 0000000..e7d57cb --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/smalltalk.st @@ -0,0 +1,41 @@ +" Syntax Highlighting Test File for Smalltalk " +" Comments are like this " +" Hello World in smalltalk " + +" Heres helloworld doesnt get much easier that this " +'Hello World!' + +" Heres a version in a window " +| window | +window := Window new. +window label: 'Hello World'. +window open. + +" Character Definition" +| mychar | +mychar := $A + +" Symbol Definition " +| mySym | +mySym := #foo + +" Symbol Array " +mySym := #(1 2 3 4) + +" Class Def " +Object subclass: #MessagePublisher + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'Smalltalk Examples' + +| rectangles aPoint| +rectangles := OrderedCollection + with: (Rectangle left: 0 right: 10 top: 100 bottom: 200) + with: (Rectangle left: 10 right: 10 top: 110 bottom: 210). +aPoint := Point x: 20 y: 20. +collisions := rectangles select: [:aRect | aRect containsPoint: aPoint]. + +result := a > b + ifTrue:[ 'greater' ] + ifFalse:[ 'less' ] diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/sql.sql b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/sql.sql new file mode 100644 index 0000000..76ff1d8 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/sql.sql @@ -0,0 +1,166 @@ +/****************************************** +* Syntax Highlighting Test File for SQL * +* Multi-Line Comment Block * +* Oracle 9i SQL * +*******************************************/ +--- Single Line Comments are like this + +--- Drop all tables, in case they were previously created --- +DROP TABLE shipment; +DROP TABLE customer; +DROP TABLE truck; +DROP TABLE city; + +--- Create the customer table --- +CREATE TABLE customer +( + CUS_ID Char(4) CONSTRAINT cus_id_pk PRIMARY KEY, + CUS_LNAME Varchar2(20), + CUS_FNAME Varchar2(20), + ANN_REVENUE Number(12,2), + CUS_TYPE Char(1) +); + +--- Create the truck table --- +CREATE TABLE truck +( + TRUCK_ID Char(4) CONSTRAINT truck_id_pk PRIMARY KEY, + DRIVER_NAME Varchar2(40) +); + +--- Create the city table --- +CREATE TABLE city +( + CITY_ID Varchar2(4) CONSTRAINT city_id_pk PRIMARY KEY, + CITY_NAME Varchar2(30), + CITY_STATE Char(2), + POPULATION Number(10) +); + +--- Create the shipment table --- +CREATE TABLE shipment +( + SHIPMENT_ID Char(4) CONSTRAINT ship_id_pk PRIMARY KEY, + CUS_ID Char(4) CONSTRAINT cust_id_fk REFERENCES customer(cus_id), + WEIGHT Number(12,2), + TRUCK_ID Char(4) CONSTRAINT truck_id_fk REFERENCES truck(truck_id), + CITY_ID Varchar2(4) CONSTRAINT city_id_fk REFERENCES city(city_id), + SHIP_DATE DATE +); + +--- Insert records into customer table --- +INSERT INTO customer VALUES + ('C101','Smith','Joe',3000000.3,'P'); +INSERT INTO customer VALUES + ('C102','Sneider','Jenny',7000000.5,'P'); +INSERT INTO customer VALUES + ('C103','Robinson','Dan',1000000.8,'C'); +COMMIT; + +--- Insert records into truck table --- +INSERT INTO truck VALUES + ('T101','Dan Brun'); +INSERT INTO truck VALUES + ('T102','Bob Lee'); +INSERT INTO truck VALUES + ('T104','Jerry Carlson'); +INSERT INTO truck VALUES + ('T103','Frank Hong'); +COMMIT; + +--- Insert records into city table --- +INSERT INTO city VALUES + ('101','Dekalb','IL',50000); +INSERT INTO city VALUES + ('201','Lincoln','NE',160000); +INSERT INTO city VALUES + ('301','Houston','TX',800000); +INSERT INTO city VALUES + ('401','Laredo','TX',260000); +COMMIT; + +--- Insert records into shipment table --- +INSERT INTO shipment VALUES + ('2001','C101',2500.2,'T101','101','12-Apr-2002'); +INSERT INTO shipment VALUES + ('2002','C102',7500.7,'T101','201','20-Apr-2002'); +INSERT INTO shipment VALUES + ('2003','C103',800000.8,'T103','201','25-May-2002'); +INSERT INTO shipment VALUES + ('2004','C102',95.00,'T102','301','02-May-2003'); +INSERT INTO shipment VALUES + ('2005','C101',85.00,'T102','401','02-May-2003'); +COMMIT; + +--- Queries 1 - 10 --- + +--- How many shipments between 1/1/02 & 5/1/03? +--- Version 1 shows all records between the given dates +SELECT * +FROM shipment +WHERE SHIP_DATE >= '01-Jan-2002' +AND SHIP_DATE <= '01-May-2003'; + +--- Version 2 returns simply a count of all the given dates +SELECT COUNT(*) +FROM shipment +WHERE SHIP_DATE >= '01-Jan-2002' +AND SHIP_DATE <= '01-May-2003'; + +--- What is destination city name of shipment id# 2004 +SELECT CITY_NAME +FROM shipment,city +WHERE SHIPMENT_ID = '2004' +AND shipment.CITY_ID = city.CITY_ID; + +--- What are the truck ids of trucks that have carried +--- shipments over 100 lbs? +SELECT DISTINCT TRUCK_ID +FROM shipment +WHERE WEIGHT >= 100; + +--- Give the Names of customers who have sent shipments to cities +--- starting with 'L'? +SELECT CUS_LNAME, CUS_FNAME +FROM customer,shipment,city +WHERE customer.CUS_ID = shipment.CUS_ID +AND shipment.CITY_ID = city.CITY_ID +AND city.CITY_NAME LIKE 'L%'; + +--- What are the names of customers who have sent packages to +--- Lincoln, NE? +SELECT CUS_LNAME, CUS_FNAME +FROM customer,shipment,city +WHERE customer.CUS_ID = shipment.CUS_ID +AND shipment.CITY_ID = city.CITY_ID +AND city.CITY_NAME = 'Lincoln'; + +--- Who are the customers having over 5 million in revenue and +--- have sent less than 100lbs? +SELECT DISTINCT CUS_FNAME, CUS_LNAME +FROM customer, shipment +WHERE customer.ANN_REVENUE > 5000000 +AND shipment.WEIGHT < 100; + +--- For each customer what is the average weight of a package, +--- show name and avg weight? +SELECT CUS_FNAME, CUS_LNAME, AVG(WEIGHT) +FROM customer,shipment +WHERE customer.CUS_ID = shipment.CUS_ID +GROUP BY CUS_FNAME, CUS_LNAME; + +--- For each city with a population over 100,000 what is the +--- minimum weight of a package sent there? +SELECT CITY_NAME, MIN(WEIGHT) +FROM city,shipment +WHERE city.POPULATION >= 100000 +AND city.CITY_ID = shipment.CITY_ID +GROUP BY CITY_NAME; + +--- For each city that has recieved at least 2 packages, what is the +--- average weight of a package sent to that city? +SELECT CITY_NAME, COUNT(SHIPMENT_ID), AVG(WEIGHT) +FROM city,shipment +WHERE shipment.CITY_ID = city.CITY_ID +GROUP BY CITY_NAME +HAVING COUNT(shipment.CITY_ID) >= 2; diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/squirrel.nut b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/squirrel.nut new file mode 100644 index 0000000..2378860 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/squirrel.nut @@ -0,0 +1,40 @@ +// Squirrel Syntax Highlighting Test File +// Comments are like this +/** Multiline comments are like this + * @summary <- Documentation keywords are like this + */ + +// Hello World +print("Hello World") + +// Literals +local a = 123 // Decimal +local b = 0x0012 // Hexadecimal +local c = 075 // Octal +local d = 'w' // Char +local e = "string" // String +local f = "Unclosed string + +// Function Definition +function fib(n) +{ + if (n < 2) return 1 + return fib(n-2) + fib(n-1) +} + +// Class Construct +class Foo { + //constructor + constructor(a) + { + bar = ["bar", 1, 2, 3]; + } + + function PrintBar() + { + foreach(i, val in bar) + { + ::print("idx = " + i + " = " + val + " \n"); + } + } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/stata.do b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/stata.do new file mode 100644 index 0000000..257f1c3 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/stata.do @@ -0,0 +1,14 @@ +/* STATA Test File /* +/* Comments look like this */ + +set mem 100m +use "this\is\where\stata\file\is\file.dta", clear +use "file.dta", clear + + +forvalues i = 1(1)10 { + + keep if auction==`i' + tabstat V1, by(V2) s(mean sd median count) + reg V1 V2 V3,robust + } diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/svg.svg b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/svg.svg new file mode 100644 index 0000000..0b8d0df --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/svg.svg @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Some Comments about this file --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="744.09448" + height="1052.3622" + id="svg2"> + <defs + id="defs4" /> + <g + id="layer1"> + <rect + width="282.85715" + height="260" + x="245.71428" + y="249.50504" + style="fill:#efefef;fill-opacity:1;stroke:#373131;stroke-opacity:1" + id="rect2160" /> + <path + d="M 288.57142 749.50507 A 62.857143 74.285713 0 1 1 162.85714,749.50507 A 62.857143 74.285713 0 1 1 288.57142 749.50507 z" + style="fill:#efefef;fill-opacity:1;stroke:#373131;stroke-opacity:1" + id="path2162" /> + <text + x="91.428574" + y="169.50504" + style="font-size:36px;font-style:normal;font-weight:bold;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + id="text2164" + xml:space="preserve"><tspan + x="91.428574" + y="169.50504" + id="tspan2166">Hello World</tspan></text> + <path + d="M 137.14286,303.79075 L 104.79416,323.98742 L 103.09272,362.08531 L 73.888247,337.56098 L 37.129231,347.71572 L 51.428572,312.36218 L 30.411685,280.54026 L 68.453639,283.2149 L 92.223505,253.39314 L 101.43538,290.39969 L 137.14286,303.79075 z " + style="fill:#efefef;fill-opacity:1;stroke:#373131;stroke-opacity:1" + id="path2168" /> + </g> +</svg> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/system_verilog.sv b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/system_verilog.sv new file mode 100644 index 0000000..ae548bd --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/system_verilog.sv @@ -0,0 +1,139 @@ +// System Verilog Syntax Highlighting Test File +// Comments are like this + +package oop; + +class BaseScoreboard; + string name; + bit[3:0] srce, dest; + int run_for_n_packets; // max number of packets to transmit before giving up on coverage goals + static int pkts_checked = 0; + static int sent_pkt_count = 0; + static int recvd_pkt_count = 0; + Packet refPkts[$]; + + function new(string name = "class", int run_for_n_packets ); + if (TRACE_ON) $display("@%0d: %s.new() started", $time, name); + this.name = name; + this.run_for_n_packets = run_for_n_packets; + endfunction : new + + task report(); + if (TRACE_ON) $display("@%0d: %s.report() started", $time, name); + $display("%0d packets sent, %0d packets sampled, %0d packets checked\n", + sent_pkt_count, recvd_pkt_count, pkts_checked); + endtask : report + +endclass : BaseScoreboard + + +class Scoreboard extends BaseScoreboard; + + covergroup router_cvg; + coverpoint srce; + coverpoint dest; + cross srce, dest; + option.at_least = 1; + option.auto_bin_max = 256; + endgroup + + function new(string name = "class", int run_for_n_packets ); + super.new(name, run_for_n_packets); + router_cvg = new(); + endfunction : new + + task check(Packet pktrecvd); + int index; + int status; + string diff; + Packet pktsent; + if (TRACE_ON) $display("@%0d: %s.check() started", $time, name); + endtask + + +endclass : Scoreboard + +endpackage : oop + +/*****************************************************************************/ + +program test(io_if dutif, input bit clk); + +import oop::*; + +bit[3:0] srce, dest; +reg[7:0] payload[$], pkt2cmp_payload[$]; + +Scoreboard sb; + +initial begin + DONE <= 0; + sb = new("sb", 2500); + pkt2send = new(); + pkt2send.pt_mode = 1; + do begin + fork + begin send(); end + begin recv(); end + join + end + repeat(10) @(posedge clk); +end + +task automatic recv(); + static int pkts_recvd = 0; + int i; + pktrecvd = new($psprintf("Pkt_recvd[%0d]", pkts_recvd++)); + pktrecvd.payload = new[pkt2cmp_payload.size()]; + for (i=0; i<pkt2cmp_payload.size(); i++) + pktrecvd.payload[i] = pkt2cmp_payload[i]; + pktrecvd.dest = dest; +endtask + +task automatic send(); + int i; + payload.delete(); + for (i=0; i<pkt2send.payload.size(); i++) + payload.push_back(pkt2send.payload[i]); + srce = pkt2send.srce; + dest = pkt2send.dest; +endtask + +endprogram + +interface io(input clock, input bit[15:0] din, frame_n); +bit [15:0] passthru; + +sequence s_pass_thru_0 ; + frame_n[ 0] ##1 !frame_n[ 0] ##0 din[ 0] == 0 [*4]; // 0000 +endsequence + +property p_pass_thru_0 ; + @(posedge clk) fr_valid |-> s_pass_thru_0; +endproperty + +assert property (p_pass_thru_0) $info("%m OK"); + else $error("%m Problem"); +endinterface + +sequence s_pass_thru_1 ; + frame_n[ 1] ##1 !frame_n[ 1] ##0 din[ 1] == 0 [*4]; // 0000 +endsequence + +property p_pass_thru_1 ; + @(posedge clk) fr_valid |-> s_pass_thru_1; +endproperty + +assert property (p_pass_thru_1) $info("%m OK"); + else $error("%m Problem"); +endinterface + +module top; +bit clk; +bit[15:0] din; +bit frame_n; + +io IF1 (.clk, .din, .frame_n); +test TB1 (.clk, io_if(IF1) ); + +endmodule diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/tcl_tk.tcl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/tcl_tk.tcl new file mode 100644 index 0000000..1dda0a6 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/tcl_tk.tcl @@ -0,0 +1,60 @@ +# Syntax Highlighting Test File for TCL/TK +# Comments are like this +# Hello World in tcl/tk + +wm title . "Hello world!" + +frame .h -borderwidth 2 +frame .q -borderwidth 2 +button .h.hello -text "Hello world" \ + -command "puts stdout \"Hello world!\"" -cursor gumby +button .q.quit -text "Quit" -command exit -cursor pirate + +pack .h -side left +pack .q -side right +pack .h.hello +pack .q.quit + +# Procedure Definition +proc printArguments args { + foreach arg $args { + puts $arg + } +} + +proc foo::xxxx {} { + set a xxxxxxxxxxxx +} +proc foo_bar {} { + set b xxxxxxx +} + +proc foo::yyyy {} { + set a bbbbbbb +} + +# SNIT +package provide test 1.0 + +snit::widgetadaptor mySnit { + + package require mypack 2.2 + + constructor {args} { + installhull using text -insertwidth 0 + $self configurelist $args + } + + typevariable myList [list] + + typemethod list {} { + return $myList + } + + # Disable the insert and delete methods, to make this readonly. + method insert {args} {} + method delete {args} {} +} + + + diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/unicode_text.txt b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/unicode_text.txt new file mode 100644 index 0000000..c9087db --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/unicode_text.txt @@ -0,0 +1,18 @@ +The next line should show some Japanese characters +こにちは 今晩は + +The next lines should show a bunch of other special characters, the description +of the character is o the left and should be directly followed by the actual +character to the right of the ':'. + +Trademark symbol: ™ +Infinity: ∞ +Bullet: • +Not Equal: ≠ +Yen Symbol: ¥ +Triangle: ∆ +Greater than equal to: ≥ +Less than equal to: ≤ +Checkmark: √ +Pi: π +Copyright: © diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vala.vala b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vala.vala new file mode 100644 index 0000000..cfa7cb0 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vala.vala @@ -0,0 +1,31 @@ +// Syntax Highlighting Test File for Vala +// Comments are like this +/* Multiline comments are like + * this. + */ + +// Hello World in Vala +using GLib; + +//! \summary Documentation keyword +public class Sample : Object { + + // Some Variable definitions + public static const double ASPECT = 8.0/6.0; + static unichar a_char = 'a'; + + public Sample () { + } + + public void run () { + stdout.printf ("Hello World\n"); + stdout.printf ("Unclosed string); + stdout.printf ('a'); // <- Char + } + + static int main (string[] args) { + var sample = new Sample (); + sample.run (); + return 0; + } +} diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vbscript.vbs b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vbscript.vbs new file mode 100644 index 0000000..6edacc1 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vbscript.vbs @@ -0,0 +1,51 @@ +' Syntax Highlighting test file for VBScript +' Comments look like this + +function hello(name) 'comment for function + + on error resume next + + dim x,y + + if name<>"World" then + for x = 1 to 10 + wscript.echo "Hello " & name + next + else + x=0 + do while x<10 + wscript.echo "Hello World" + x=x+1 + loop + end if + + hello=x+y + +end function + +Public Function testPublicFunct() + dim c,d +end Sub + +sub testStub() + dim a,b +end sub + +Public Sub testPublicSub() + dim c,d +end Sub + +'--------------------------- + +on error resume next + +dim didIt +dim userid + +set WshShell = WScript.CreateObject("WScript.Shell") +'Finds the user name from an environment variable +userid=wshshell.expandenvironmentstrings("%username%") + +didIt=hello(userid) + +wscript.exit(0) diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/verilog.v b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/verilog.v new file mode 100644 index 0000000..f905254 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/verilog.v @@ -0,0 +1,33 @@ +// Syntax Highlighting Test file for Verilog +// Some Comments about this file + +module toplevel(clock,reset); + input clock; + input reset; + + reg flop1; + reg flop2; + + always @ (posedge reset or posedge clock) + if (reset) + begin + flop1 <= 0; + flop2 <= 1; + end + else + begin + flop1 <= flop2; + flop2 <= flop1; + end +endmodule + +initial + fork + $write("A"); + $write("B"); + begin + #1; + $write("C"); + end + join +
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vhdl.vhdl b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vhdl.vhdl new file mode 100644 index 0000000..ef2f779 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/vhdl.vhdl @@ -0,0 +1,45 @@ +-- Syntax Highlighting Test File for VHDL +-- Comments are like this +-- Hello World in VHDL + +entity hello_world is +end; + + architecture hello_world of hello_world is + begin + stimulus : process + begin + assert false report "Hello World By Deepak" + severity note; + wait; + end process stimulus; +end hello_world; + +-- A simple counter +library ieee ; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity counter is +port( clk: in std_logic; + reset: in std_logic; + enable: in std_logic; + count: out std_logic_vector(3 downto 0) +); +end counter; + +architecture behav of counter is + signal pre_count: std_logic_vector(3 downto 0); + begin + process(clk, enable, reset) + begin + if reset = '1' then + pre_count <= "0000"; + elsif (clk='1' and clk'event) then + if enable = '1' then + pre_count <= pre_count + "1"; + end if; + end if; + end process; + count <= pre_count; +end behav; diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/visual_basic.vb b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/visual_basic.vb new file mode 100644 index 0000000..c7332be --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/visual_basic.vb @@ -0,0 +1,32 @@ +' Visual Basic Hello World +' Some more comments about this file +VERSION 4.00 +Begin VB.Form Form1 + Caption = "Hello" + ClientHeight = 6030 + ClientLeft = 1095 + ClientTop = 1515 + ClientWidth = 6720 + Height = 6435 + Left = 1035 + LinkTopic = "Form1" + ScaleHeight = 6030 + ScaleWidth = 6720 + Top = 1170 + Width = 6840 + Begin VB.CommandButton Command1 + Caption = "Hello World" + Height = 975 + Left = 2040 + TabIndex = 0 + Top = 2280 + Width = 2535 + End +End +Attribute VB_Name = "Form1" +Attribute VB_Creatable = False +Attribute VB_Exposed = False +Private Sub Command1_Click() +Cls +Print "Hello World" +End Sub
\ No newline at end of file diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/xml.xml b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/xml.xml new file mode 100644 index 0000000..b4d0d52 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/xml.xml @@ -0,0 +1,20 @@ +<!-- Syntax Highlighting Test File for XML --> +<!-- Comments are like this --> +<?xml version="1.0" encoding="utf-8"?> +<rss version="2.0"> + <channel> + <title>Editra.org</title> + <link>http://editra.org/index.php</link> + <description>Editra Text Editor</description> + <language>en-us</language> + <generator>Editra.org</generator> + <item> + <title>Cleanup Round 2</title> + <link>http://editra.org/index.php?artical=helloWorld</link> + <description>Hello XML</description> + <author>admin@editra.org (cody)</author> + <pubDate>Sat, 11 Nov 2006 17:47:39 -0800</pubDate> + <guid isPermaLink="true">http://editra.org/index.php?artical=helloWorld</guid> + </item> + </channel> +</rss> diff --git a/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/yaml.yaml b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/yaml.yaml new file mode 100644 index 0000000..e8c4b84 --- /dev/null +++ b/lib/python2.7/site-packages/wx-3.0-msw/wx/tools/Editra/tests/syntax/yaml.yaml @@ -0,0 +1,25 @@ +# Syntax Highlighting Test file for YAML +# Some Comments about this file + +---!myDocument +logEvent: Hello World +date: 2007-08-06 +customer: + given: Joe + family: Bazooka + +greet: &id001 + location: | + In Front of you + +greeting: + - first: Hello + second: World + + - first: Buy my gum + second: I give you Comics + +specialGreeting: > + This is a text section of a yaml document all + the (xxx:) items are identifiers. +... |