From 94c66c0a34b3dea0a6e37711d2d5694eca018ab6 Mon Sep 17 00:00:00 2001 From: Andrea Gavana Date: Tue, 3 Apr 2012 18:41:48 +0000 Subject: [PATCH] Phoenix updates: 1) Keep the sidebar always visible; 2) Put the search stuff on the scrolling header; 3) Implement accordion-style JavaScrip stuff to show/hide user-contributed samples; 4) Minor clean-ups. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@71087 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/sphinx/_downloads/GridBagSizer.1.py | 46 ++++++ docs/sphinx/_downloads/GridBagSizer.2.py | 43 +++++ docs/sphinx/_static/css/phoenix.css | 38 ++++- .../_static/images/sphinxdocs/arrows.png | Bin 0 -> 1171 bytes .../_static/javascript/jquery.collapse.js | 151 ++++++++++++++++++ .../_static/javascript/jquery.cookie.js | 96 +++++++++++ docs/sphinx/_static/javascript/sidebar.js | 6 +- docs/sphinx/_templates/layout.html | 51 +++++- docs/sphinx/availability.py | 3 + docs/sphinx/conf.py | 6 +- docs/sphinx/phoenix_theme/theme.conf | 38 +++++ etg/_core.py | 41 +++-- etgtools/sphinx_generator.py | 72 +++++++-- sphinxtools/constants.py | 2 +- sphinxtools/postprocess.py | 43 ++++- sphinxtools/utilities.py | 53 +++++- 16 files changed, 636 insertions(+), 53 deletions(-) create mode 100644 docs/sphinx/_downloads/GridBagSizer.1.py create mode 100644 docs/sphinx/_downloads/GridBagSizer.2.py create mode 100644 docs/sphinx/_static/images/sphinxdocs/arrows.png create mode 100644 docs/sphinx/_static/javascript/jquery.collapse.js create mode 100644 docs/sphinx/_static/javascript/jquery.cookie.js create mode 100644 docs/sphinx/phoenix_theme/theme.conf diff --git a/docs/sphinx/_downloads/GridBagSizer.1.py b/docs/sphinx/_downloads/GridBagSizer.1.py new file mode 100644 index 00000000..3fb4e7ae --- /dev/null +++ b/docs/sphinx/_downloads/GridBagSizer.1.py @@ -0,0 +1,46 @@ +##Chris Barker +#!/usr/bin/env python + +""" +A simple test of the GridBagSizer + +http://wiki.wxpython.org/index.cgi/WriteItYourself + +""" + +import wx + +class MyFrame(wx.Frame): + def __init__(self, parent, ID, title): + wx.Frame.__init__(self, parent, ID, title, wx.DefaultPosition) + + Buttons = [] + for i in range(6): + Buttons.append(wx.Button(self,-1, "Button %i"%(i))) + + sizer = wx.GridBagSizer(9, 9) + sizer.Add(Buttons[0], (0, 0), wx.DefaultSpan, wx.ALL, 5) + sizer.Add(Buttons[1], (1, 1), (1,7), wx.EXPAND) + sizer.Add(Buttons[2], (6, 6), (3,3), wx.EXPAND) + sizer.Add(Buttons[3], (3, 0), (1,1), wx.ALIGN_CENTER) + sizer.Add(Buttons[4], (4, 0), (1,1), wx.ALIGN_LEFT) + sizer.Add(Buttons[5], (5, 0), (1,1), wx.ALIGN_RIGHT) + + sizer.AddGrowableRow(6) + sizer.AddGrowableCol(6) + + self.SetSizerAndFit(sizer) + self.Centre() + + +class MyApp(wx.App): + def OnInit(self): + frame = MyFrame(None, -1, "wx.gridbagsizer.py") + frame.Show(True) + self.SetTopWindow(frame) + return True + +if __name__ == "__main__": + app = MyApp(0) + app.MainLoop() + diff --git a/docs/sphinx/_downloads/GridBagSizer.2.py b/docs/sphinx/_downloads/GridBagSizer.2.py new file mode 100644 index 00000000..6442a0cc --- /dev/null +++ b/docs/sphinx/_downloads/GridBagSizer.2.py @@ -0,0 +1,43 @@ +##Chris Barker +#!/usr/bin/env python + +import wx + +class TestFrame(wx.Frame): + def __init__(self, *args, **kwargs): + wx.Frame.__init__(self, *args, **kwargs) + + t = wx.TextCtrl(self) + + b1 = wx.Button(self, label="Button1") + b2 = wx.Button(self, label="Button2") + + exitBut = wx.Button(self, label="Exit") + exitBut.Bind(wx.EVT_BUTTON, self.OnCloseWindow) + + sizer = wx.GridBagSizer(10, 10) + sizer.Add(t, (0,0), span=(2,1), flag=wx.ALIGN_CENTER_VERTICAL ) + sizer.Add(b1, (0,1), span=(2,1), flag=wx.ALIGN_CENTER) + sizer.Add(b2, (0,2), flag=wx.ALIGN_CENTER) + + sizer.Add(exitBut, (1,3)) + + self.SetSizerAndFit(sizer) + + wx.EVT_CLOSE(self, self.OnCloseWindow) + + def OnCloseWindow(self, event): + self.Destroy() + +class App(wx.App): + def OnInit(self): + frame = TestFrame(None, title="GridBagSizer Test") + self.SetTopWindow(frame) + frame.Show(True) + return True + +if __name__ == "__main__": + app = App(0) + app.MainLoop() + + diff --git a/docs/sphinx/_static/css/phoenix.css b/docs/sphinx/_static/css/phoenix.css index 9ae04ea7..f4229543 100644 --- a/docs/sphinx/_static/css/phoenix.css +++ b/docs/sphinx/_static/css/phoenix.css @@ -88,22 +88,30 @@ div.body h4 { */ body { - background-color: rgb(100,135,220); + background-color: rgb(230,230,230); } div.document { background-color: rgb(230,230,230); position: relative; + margin-left: 240px; z-index: 0; top: 30px; } div.sphinxsidebar { - background-color: rgb(230,230,230); - z-index: 1; - left: 0; - top: 30px; - bottom: 0; + background-color: rgb(230,230,230); + margin-left: 0; + float: none; + position: fixed; + overflow: auto; + width: 240px; + max-width: 240px; + height: auto; + z-index: 1; + left: 0; + top: 33px; + bottom: 0; } div.related { @@ -195,6 +203,16 @@ div.sphinxsidebar ul.want-points { text-align:center; } +div.bodywrapper { + margin: 0; +} + +div.headerfix :target { + /* compensate fixed header in link anchors */ + padding-top: {{ 30 }}; + margin-top: -{{ 30 }}; +} + /** * Extra admonitions */ @@ -637,4 +655,10 @@ tt { background-color: #EAEAF8; padding: 0 1px 0 1px; font-size: 0.95em; -} \ No newline at end of file +} + +.codeexpander p {padding-left: 25px; cursor:pointer; background: url("../images/sphinxdocs/arrows.png") no-repeat 0 -33px; text-decoration:none;} +.codeexpander p {border-bottom:1px solid #ccc; padding-bottom:4px;} +.codeexpander p a {text-decoration:none;} +.codeexpander p.myactive {background-position: 0 5px;} +.myactive {background-color: rgb(230, 230, 230); background-position: 0 5px;} \ No newline at end of file diff --git a/docs/sphinx/_static/images/sphinxdocs/arrows.png b/docs/sphinx/_static/images/sphinxdocs/arrows.png new file mode 100644 index 0000000000000000000000000000000000000000..e1e9c9a529207f00c1888c38176e04d0d9556ec7 GIT binary patch literal 1171 zcmeAS@N?(olHy`uVBq!ia0vp^fDSr z1<%~X^wgl##FWaylc_cg49rTIArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XP}#GU}m6TW~gUq zY+`P1uA^XNU}&IkV5Dzoq-$tyWo%?+V4wg6Nh+i#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yc06!V;*iRM zRQ;gT;{4L0WMIUlDTAykuyQU+O)SYT3dzsUfrVl~Mt(_taYlZDf^)E`f^TASW*&$S zR`2U;<(XGpl9-pA>gi&u1T;Y}Gc(1?$kE8e$jsEx!qn8#(9p%r!pXwL)ydM?+}zO2 z#Kp)2rq?AuximL5uLPzy1)Yv_@3^u<6<~Wu0oD~h-yCgP0;Jei*bKuMMISpPG5v6lxM#VHNa{sW6 zvqV>S5&wy$leaM~^=7{tR2;JT0cTLr8q*z3ww2Rny}425d}Z6(_s$tE^(z!OCxMYr z=F0iu;#W3G$K^csnVWO)-1fX6ndg73RMownTWVU|wp#CZQ1f=>{16$(xn((r-KQUUe%tc1 gq{o+sb*vH$4|5OS{Q6qcA5=_uy85}Sb4q9e0GX|mivR!s literal 0 HcmV?d00001 diff --git a/docs/sphinx/_static/javascript/jquery.collapse.js b/docs/sphinx/_static/javascript/jquery.collapse.js new file mode 100644 index 00000000..c0776d12 --- /dev/null +++ b/docs/sphinx/_static/javascript/jquery.collapse.js @@ -0,0 +1,151 @@ +/*! + * Collapse plugin for jQuery + * http://github.com/danielstocks/jQuery-Collapse/ + * + * @author Daniel Stocks (http://webcloud.se) + * @version 0.9.1 + * @updated 17-AUG-2010 + * + * Copyright 2010, Daniel Stocks + * Released under the MIT, BSD, and GPL Licenses. + */ + +(function($) { + + // Use a cookie counter to allow multiple instances of the plugin + var cookieCounter = 0; + + $.fn.extend({ + collapse: function(options) { + + var defaults = { + head : "h3", + group : "div, ul", + cookieName : "collapse", + // Default function for showing content + show: function() { + this.show(); + }, + // Default function for hiding content + hide: function() { + this.hide(); + } + }; + var op = $.extend(defaults, options); + + // Default CSS classes + var active = "myactive", + inactive = "myinactive"; + + return this.each(function() { + + // Increment coookie counter to ensure cookie name integrity + cookieCounter++; + var obj = $(this), + // Find all headers and wrap them in for accessibility. + sections = obj.find(op.head).wrapInner(''), + l = sections.length, + cookie = op.cookieName + "_" + cookieCounter; + // Locate all panels directly following a header + var panel = obj.find(op.head).map(function() { + var head = $(this) + if(!head.hasClass(active)) { + return head.next(op.group).hide()[0]; + } + return head.next(op.group)[0]; + }); + + // Bind event for showing content + obj.bind("show", function(e, bypass) { + var obj = $(e.target); + // ARIA attribute + obj.attr('aria-hidden', false) + .prev() + .removeClass(inactive) + .addClass(active); + // Bypass method for instant display + if(bypass) { + obj.show(); + } else { + op.show.call(obj); + } + }); + + // Bind event for hiding content + obj.bind("hide", function(e, bypass) { + var obj = $(e.target); + obj.attr('aria-hidden', true) + .prev() + .removeClass(active) + .addClass(inactive); + if(bypass) { + obj.hide(); + } else { + op.hide.call(obj); + } + }); + + // Look for existing cookies + if(cookieSupport) { + for (var c=0;c<=l;c++) { + var val = $.cookie(cookie + c); + // Show content if associating cookie is found + if ( val == c + "open" ) { + panel.eq(c).trigger('show', [true]); + // Hide content + } else if ( val == c + "closed") { + panel.eq(c).trigger('hide', [true]); + } + } + } + + // Delegate click event to show/hide content. + obj.bind("click", function(e) { + var t = $(e.target); + // Check if header was clicked + if(!t.is(op.head)) { + // What about link inside header. + if ( t.parent().is(op.head) ) { + t = t.parent(); + } else { + return; + } + e.preventDefault(); + } + // Figure out what position the clicked header has. + var num = sections.index(t), + cookieName = cookie + num, + cookieVal = num, + content = t.next(op.group); + // If content is already active, hide it. + if(t.hasClass(active)) { + content.trigger('hide'); + cookieVal += 'closed'; + if(cookieSupport) { + $.cookie(cookieName, cookieVal, { path: '/', expires: 10 }); + } + return; + } + // Otherwise show it. + content.trigger('show'); + cookieVal += 'open'; + if(cookieSupport) { + $.cookie(cookieName, cookieVal, { path: '/', expires: 10 }); + } + }); + }); + } + }); + + // Make sure can we eat cookies without getting into trouble. + var cookieSupport = (function() { + try { + $.cookie('x', 'x', { path: '/', expires: 10 }); + $.cookie('x', null); + } + catch(e) { + return false; + } + return true; + })(); +})(jQuery); \ No newline at end of file diff --git a/docs/sphinx/_static/javascript/jquery.cookie.js b/docs/sphinx/_static/javascript/jquery.cookie.js new file mode 100644 index 00000000..6df1faca --- /dev/null +++ b/docs/sphinx/_static/javascript/jquery.cookie.js @@ -0,0 +1,96 @@ +/** + * Cookie plugin + * + * Copyright (c) 2006 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +/** + * Create a cookie with the given name and value and other optional parameters. + * + * @example $.cookie('the_cookie', 'the_value'); + * @desc Set the value of a cookie. + * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); + * @desc Create a cookie with all available options. + * @example $.cookie('the_cookie', 'the_value'); + * @desc Create a session cookie. + * @example $.cookie('the_cookie', null); + * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain + * used when the cookie was set. + * + * @param String name The name of the cookie. + * @param String value The value of the cookie. + * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. + * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. + * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. + * If set to null or omitted, the cookie will be a session cookie and will not be retained + * when the the browser exits. + * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). + * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). + * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will + * require a secure protocol (like HTTPS). + * @type undefined + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ + +/** + * Get the value of a cookie with the given name. + * + * @example $.cookie('the_cookie'); + * @desc Get the value of a cookie. + * + * @param String name The name of the cookie. + * @return The value of the cookie. + * @type String + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ +jQuery.cookie = function(name, value, options) { + if (typeof value != 'undefined') { // name and value given, set cookie + options = options || {}; + if (value === null) { + value = ''; + options.expires = -1; + } + var expires = ''; + if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { + var date; + if (typeof options.expires == 'number') { + date = new Date(); + date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); + } else { + date = options.expires; + } + expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE + } + // CAUTION: Needed to parenthesize options.path and options.domain + // in the following expressions, otherwise they evaluate to undefined + // in the packed version for some reason... + var path = options.path ? '; path=' + (options.path) : ''; + var domain = options.domain ? '; domain=' + (options.domain) : ''; + var secure = options.secure ? '; secure' : ''; + document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); + } else { // only name given, get cookie + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } +}; \ No newline at end of file diff --git a/docs/sphinx/_static/javascript/sidebar.js b/docs/sphinx/_static/javascript/sidebar.js index 057f741f..e618a4b1 100644 --- a/docs/sphinx/_static/javascript/sidebar.js +++ b/docs/sphinx/_static/javascript/sidebar.js @@ -29,7 +29,7 @@ $(function() { var sidebarbutton = $('
'); var sbw_width = sidebar.width(); var sbb_width = 9; - var dark_color = $('div.related').css('background-color'); + var dark_color = 'darkgrey'; var light_color = sidebarwrapper.css('color'); var opacity_factor = $.browser.msie ? 1 : 0.75; var collapsed = sidebarwrapper.is(':not(:visible)'); @@ -97,8 +97,8 @@ $(function() { 'color': light_color, 'font-size': 14, 'text-align': 'center', - 'border-left': '1px solid ' + dark_color, - 'border-right': '1px solid ' + dark_color, + 'border-left': '1px solid ' + 'white', + 'border-right': '1px solid ' + 'white', 'padding': '1px 0', 'margin': '0', 'width': sbb_width - 2, diff --git a/docs/sphinx/_templates/layout.html b/docs/sphinx/_templates/layout.html index 7e14c013..ff3e4e0d 100644 --- a/docs/sphinx/_templates/layout.html +++ b/docs/sphinx/_templates/layout.html @@ -1,11 +1,30 @@ - {% extends "!layout.html" %} {%- block relbaritems %}
  • {{ title }}
  • {% endblock %} -{% block sidebar1 %}{{ sidebar() }}{% endblock %} +{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) + and (sidebars != []) and (pagename != 'index') %} + +{% macro phoenixsidebar() %} + {%- if render_sidebar %}{{ sidebar() }}{%- endif %} +{% endmacro %} + +{% macro sidebarcss() %} + {%- if not render_sidebar %} + + {%- endif %} +{% endmacro %} + +{% block extrahead %}{{ sidebarcss() }}{% endblock %} + +{% block sidebar1 %}{{ phoenixsidebar() }}{% endblock %} +{% block sidebar2 %}{% endblock %} + +{% block relbar2 %}{% endblock %} {% block rootrellink %} @@ -15,10 +34,38 @@
  • Gallery
  • Documentation »
  • +{%- if pagename != 'search' %} + + +{%- endif %} {% endblock %} +{% block document %} +
    +
    + {% block body %} {% endblock %} + {%- if theme_disqus_comments|tobool %} +
    + + + {%- endif %} +
    +
    +{%- endblock %} + {% block header %}
    Phoenix Logo
    {% endblock %} + +set script_files = script_files + ['_static/sidebar.js'] +set script_files = script_files + ['_static/header.js'] diff --git a/docs/sphinx/availability.py b/docs/sphinx/availability.py index 681d430a..ecdb54b9 100644 --- a/docs/sphinx/availability.py +++ b/docs/sphinx/availability.py @@ -178,6 +178,9 @@ def depart_availability_node(self, node): def setup(app): app.add_javascript('javascript/header.js') + app.add_javascript('javascript/sidebar.js') + app.add_javascript('javascript/jquery.collapse.js') + app.add_javascript('javascript/jquery.cookie.js') app.add_config_value('availability_include_availabilities', False, False) diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index 32edb530..2342b746 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -100,15 +100,15 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'default' +html_theme = 'phoenix_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -html_theme_options = {'collapsiblesidebar': 'true'} +html_theme_options = dict() # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +html_theme_path = ['.'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". diff --git a/docs/sphinx/phoenix_theme/theme.conf b/docs/sphinx/phoenix_theme/theme.conf new file mode 100644 index 00000000..6ae2b098 --- /dev/null +++ b/docs/sphinx/phoenix_theme/theme.conf @@ -0,0 +1,38 @@ +[theme] + +inherit = basic +stylesheet = phoenix.css +pygments_style = sphinx + +[options] + +disqus_comments = false +google_analytics = false + +rightsidebar = false +collapsiblesidebar = true +headerheight = 30px + +externalrefs = false + +footerbgcolor = #11303d +footertextcolor = #ffffff +sidebarbgcolor = #1c4e63 +sidebarbtncolor = #3c6e83 +sidebartextcolor = #ffffff +sidebarlinkcolor = #98dbcc +relbarbgcolor = #133f52 +relbartextcolor = #ffffff +relbarlinkcolor = #ffffff +bgcolor = #ffffff +textcolor = #000000 +headbgcolor = #f2f2f2 +headtextcolor = #20435c +headlinkcolor = #c60f0f +linkcolor = #355f7c +visitedlinkcolor = #355f7c +codebgcolor = #eeffcc +codetextcolor = #333333 + +bodyfont = sans-serif +headfont = 'Trebuchet MS', Verdana, Arial, Helvetica, sans-serif \ No newline at end of file diff --git a/etg/_core.py b/etg/_core.py index 0648f15b..cf4f4682 100644 --- a/etg/_core.py +++ b/etg/_core.py @@ -229,7 +229,7 @@ def run(): method calls from non-GUI threads. Any extra positional or keyword args are passed on to the callable when it is called. - :param callableObj: the callable object + :param PyObject callableObj: the callable object :param args: arguments to be passed to the callable object :param kw: keywords to be passed to the callable object @@ -256,29 +256,36 @@ def run(): module.addPyClass('CallLater', ['object'], doc="""\ - A convenience class for `wx.Timer`, that calls the given callable + A convenience class for :class:`Timer`, that calls the given callable object once after the given amount of milliseconds, passing any positional or keyword args. The return value of the callable is - availbale after it has been run with the `GetResult` method. + availbale after it has been run with the :meth:`~CallLater.GetResult` method. If you don't need to get the return value or restart the timer then there is no need to hold a reference to this object. It will hold a reference to itself while the timer is running (the timer - has a reference to self.Notify) but the cycle will be broken when - the timer completes, automatically cleaning up the wx.CallLater + has a reference to :meth:`~CallLater.Notify`) but the cycle will be broken when + the timer completes, automatically cleaning up the :class:`CallLater` object. - - :param int millis: number of milli seconds - :param callableObj: the callable object - :param args: arguments to be passed to the callable object - :param kw: keywords to be passed to the callable object - - ::seealso: + + .. seealso:: :func:`CallAfter` """, items = [ PyFunctionDef('__init__', '(self, millis, callableObj, *args, **kwargs)', + doc="""\ + A convenience class for :class:`Timer`, that calls the given callable + object once after the given amount of milliseconds, passing any + positional or keyword args. The return value of the callable is + availbale after it has been run with the :meth:`~CallLater.GetResult` method. + + :param int millis: number of milli seconds + :param PyObject callableObj: the callable object + :param args: arguments to be passed to the callable object + :param kw: keywords to be passed to the callable object + """, + body="""\ assert callable(callableObj), "callableObj is not callable" self.millis = millis @@ -333,7 +340,7 @@ def run(): PyFunctionDef('SetArgs', '(self, *args, **kwargs)', doc="""\ (Re)set the args passed to the callable object. This is - useful in conjunction with Restart if you want to schedule a + useful in conjunction with :meth:`Restart` if you want to schedule a new call to the same callable object but with different parameters. @@ -347,14 +354,18 @@ def run(): PyFunctionDef('HasRun', '(self)', 'return self.hasRun', doc="""\ - :rtype: boolean + Returns whether or not the callable has run. + + :rtype: bool """), PyFunctionDef('GetResult', '(self)', 'return self.result', doc="""\ - :rtype: result from callable + Returns the value of the callable. + :rtype: a Python object + :return: result from callable """), PyFunctionDef('Notify', '(self)', diff --git a/etgtools/sphinx_generator.py b/etgtools/sphinx_generator.py index 1f814883..393a198d 100644 --- a/etgtools/sphinx_generator.py +++ b/etgtools/sphinx_generator.py @@ -21,6 +21,7 @@ import operator import shutil import textwrap import glob +import cPickle from StringIO import StringIO @@ -515,7 +516,7 @@ class ParameterList(Node): for pdef in xml_item.items: - if pdef.out: + if pdef.out or pdef.ignored: continue name = pdef.name @@ -609,9 +610,15 @@ class ParameterList(Node): ' ==> Function/Method signature from `extractors`: %s\n' \ ' ==> Parameter list from wxWidgets XML items: %s\n\n' \ 'This may be a documentation bug in wxWidgets or a side-effect of removing the `wx` prefix from signatures.\n\n' + + theargs = [] for arg in arguments: + myarg = arg.split('=')[0].strip() + if myarg: + theargs.append(myarg) + if '*' in arg or ')' in arg: continue @@ -624,6 +631,17 @@ class ParameterList(Node): class_name = Wx2Sphinx(xml_item.className)[1] + '.' print message % (class_name + name, arg, signature, py_parameters) + +## for param in py_parameters: +## if param not in theargs: +## class_name = '' +## if hasattr(xml_item, 'className') and xml_item.className is not None: +## class_name = Wx2Sphinx(xml_item.className)[1] + '.' +## +## print '\n ||| %s;%s;%s |||\n'%(class_name[0:-1], signature, param) +## fid = open('mismatched.txt', 'a') +## fid.write('%s;%s;%s\n'%(class_name[0:-1], signature, param)) +## fid.close() # ----------------------------------------------------------------------- @@ -689,7 +707,7 @@ class Parameter(Node): self.pdef = pdef self.name = pdef.name - self.type = PythonizeType(pdef.type) + self.type = PythonizeType(pdef.type) # ----------------------------------------------------------------------- # @@ -2787,6 +2805,9 @@ class SphinxGenerator(generators.DocsGeneratorBase): function.overloads = [] function.pyArgsString = function.argsString + + self.UnIndent(function) + # docstring docstring = XMLDocString(function) docstring.kind = 'function' @@ -2806,7 +2827,28 @@ class SphinxGenerator(generators.DocsGeneratorBase): docstring.Dump() - + + def UnIndent(self, item): + + if not item.briefDoc: + return + + newdocs = '' + for line in item.briefDoc.splitlines(): + if line.strip(): + stripped = len(line) - len(line.lstrip()) + break + + newdocs = '' + for line in item.briefDoc.splitlines(): + if line.strip(): + line = line[stripped:] + + newdocs += line + '\n' + + item.briefDoc = newdocs + + # ----------------------------------------------------------------------- def generatePyClass(self, klass): @@ -2843,6 +2885,8 @@ class SphinxGenerator(generators.DocsGeneratorBase): init_method = class_items.pop(init_position) class_items.insert(0, init_method) + self.UnIndent(klass) + docstring = XMLDocString(klass) docstring.kind = 'class' @@ -2853,17 +2897,16 @@ class SphinxGenerator(generators.DocsGeneratorBase): docstring.Dump() # these are the only kinds of items allowed to be items in a PyClass - dispatch = { - extractors.PyFunctionDef : self.generateMethod, - extractors.PyPropertyDef : self.generatePyProperty, - extractors.PyCodeDef : self.generatePyCode, - extractors.PyClassDef : self.generatePyClass, - } + dispatch = [(extractors.PyFunctionDef, self.generateMethod), + (extractors.PyPropertyDef, self.generatePyProperty), + (extractors.PyCodeDef, self.generatePyCode), + (extractors.PyClassDef, self.generatePyClass)] - for item in class_items: - item.klass = klass - f = dispatch[item.__class__] - f(item) + for kind, function in dispatch: + for item in class_items: + if kind == item.__class__: + item.klass = klass + function(item) # ----------------------------------------------------------------------- @@ -2979,6 +3022,9 @@ class SphinxGenerator(generators.DocsGeneratorBase): ## if name.startswith("__") and "__init__" not in name: ## return + if isinstance(method, extractors.PyFunctionDef): + self.UnIndent(method) + class_name = RemoveWxPrefix(self.current_class.name) or self.current_class.pyName # docstring diff --git a/sphinxtools/constants.py b/sphinxtools/constants.py index 015b37ff..33980b31 100644 --- a/sphinxtools/constants.py +++ b/sphinxtools/constants.py @@ -144,7 +144,7 @@ HTML_REPLACE = ['module', 'function', 'method', 'class', 'classmethod', 'staticm # The SVN revision of wxWidgets/Phoenix used to build the Sphinx docs. # There must be a more intelligent way to get this information automatically. -SVN_REVISION = '71066' +SVN_REVISION = '71086' # Today's date representation for the Sphinx HTML docs TODAY = datetime.date.today().strftime('%d %B %Y') diff --git a/sphinxtools/postprocess.py b/sphinxtools/postprocess.py index b0d3f2d4..c4a96e7a 100644 --- a/sphinxtools/postprocess.py +++ b/sphinxtools/postprocess.py @@ -150,14 +150,17 @@ def BuildEnumsAndMethods(sphinxDir): text = text.replace('`String`&', 'string') text = text.replace('See also\n', '.. seealso:: ') + # Avoid Sphinx warnings on wx.TreeCtrl text = text.replace('**( `', '** ( `') # Replace EmptyString stuff text = text.replace('EmptyString', "''") - # Replace ArrayString stuff... - text = text.replace('ArrayString()', '[]') - text = text.replace('ArrayString', 'list of strings') + # Replace ArrayXXX stuff... + + for cpp in ['ArrayString()', 'ArrayInt()', 'ArrayDouble()']: + text = text.replace(cpp, '[]') + if text != orig_text: fid = open(input, 'wt') fid.write(text) @@ -504,6 +507,36 @@ def ClassToFile(line): return line +# ----------------------------------------------------------------------- # + +def AddJavaScript(text): + + jsCode = """\ + + """ + + index = text.rfind('') + newtext = text[0:index] + jsCode + text[index:] + + return newtext + + # ----------------------------------------------------------------------- # def PostProcess(folder): @@ -581,12 +614,14 @@ def PostProcess(folder): elif stripline == '
    ' and not properties_done: line = '

    PropertiesΒΆ

    ' + '\n' + line properties_done = True - + newtext += line + '\n' for old, new in enum_dict.items(): newtext = newtext.replace(old, new) + newtext = AddJavaScript(newtext) + if orig_text != newtext: fid = open(files, "wt") fid.write(newtext) diff --git a/sphinxtools/utilities.py b/sphinxtools/utilities.py index 89772810..01893ae8 100644 --- a/sphinxtools/utilities.py +++ b/sphinxtools/utilities.py @@ -226,24 +226,48 @@ def PythonizeType(ptype): :rtype: `string` """ - ptype = Wx2Sphinx(ReplaceCppItems(ptype))[1] + if 'size_t' in ptype: + ptype = 'int' + elif 'wx.' in ptype: + ptype = ptype[3:] + else: + ptype = Wx2Sphinx(ReplaceCppItems(ptype))[1] + ptype = ptype.replace('::', '.').replace('*&', '') ptype = ptype.replace('int const', 'int') ptype = ptype.replace('Uint32', 'int').replace('**', '').replace('Int32', 'int') ptype = ptype.replace('FILE', 'file') + ptype = ptype.replace('boolean', 'bool') for item in ['unsignedchar', 'unsignedint', 'unsignedlong', 'unsigned']: ptype = ptype.replace(item, 'int') - ptype = ptype.strip() + ptype = ptype.strip() ptype = RemoveWxPrefix(ptype) - if ptype.lower() == 'double': + if '. wx' in ptype: + ptype = ptype.replace('. wx', '.') + + plower = ptype.lower() + + if plower == 'double': ptype = 'float' - if ptype.lower() in ['string', 'char']: + if plower in ['string', 'char']: ptype = 'string' + if plower in ['coord', 'byte', 'fileoffset', 'short', 'time_t', 'intptr', 'uintptr', 'windowid']: + ptype = 'int' + + if plower in ['longlong']: + ptype = 'long' + + cpp = ['ArrayString', 'ArrayInt', 'ArrayDouble'] + python = ['list of strings', 'list of integers', 'list of floats'] + + for c, p in zip(cpp, python): + ptype = ptype.replace(c, p) + if 'Image.' in ptype: ptype = ptype.split('.')[-1] @@ -590,6 +614,22 @@ def Wx2Sphinx(name): # ----------------------------------------------------------------------- # +RAW_1 = """ + +%s.. raw:: html + +%s
    + +""" + +RAW_2 = """ + +%s.. raw:: html + +%s
    + +""" + def FormatContributedSnippets(kind, contrib_snippets): spacer = '' @@ -608,12 +648,15 @@ def FormatContributedSnippets(kind, contrib_snippets): lines = fid.readlines() fid.close() user = lines[0].replace('##', '').strip() + onlyfile = os.path.split(snippet)[1] - text += '\n' + spacer + 'Example %d (%s)::\n\n'%(indx+1, user) + text += RAW_1%(spacer, spacer) + text += '\n' + spacer + 'Example %d - %s (:download:`download <_downloads/%s>`)::\n\n'%(indx+1, user, onlyfile) for line in lines[1:]: text += 4*' '+ spacer + line text += '\n' + text += RAW_2%(spacer, spacer) return text