Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel <daniel@daniel-EeePC.(none)>2012-02-14 10:14:49 (GMT)
committer Daniel <daniel@daniel-EeePC.(none)>2012-02-14 10:14:49 (GMT)
commit7b223bedbf9c86b55a8ff1d08bda17317c7ebadb (patch)
tree76da3152167450962f639cea643913cd55b2d436
Lybniz Base
-rw-r--r--AUTHORS6
-rw-r--r--COPYING11
-rw-r--r--MANIFEST18
-rw-r--r--activity/activity.info7
-rw-r--r--activity/lybniz.svg108
-rw-r--r--icons/connect-points.svg9
-rw-r--r--icons/custom.svg7
-rw-r--r--icons/decimal.svg7
-rw-r--r--icons/evaluate.svg66
-rw-r--r--icons/graph.svg7
-rw-r--r--icons/radian.svg7
-rwxr-xr-xlybniz.py659
-rwxr-xr-xsetup.py21
13 files changed, 933 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..b60d936
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,6 @@
+Coders:
+Thomas Führinger <ThomasFuhringer@Yahoo.com>
+Sam Tygier <samtygier@yahoo.co.uk>
+
+Sugarization:
+Daniel Francis <santiago.danielfrancis@gmail.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..89a8122
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,11 @@
+Copyright (c) 2005-2006, Thomas Führinger, Sam Tygier
+Copyright (c) 2012, Daniel Francis
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of the Lybniz dev team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..b786aca
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,18 @@
+AUTHORS
+COPYING
+setup.py
+lybniz.py
+activity/activity.info
+activity/lybniz.svg
+icons/graph.svg
+icons/evaluate.svg
+icons/connect-points.svg
+icons/decimal.svg
+icons/radian.svg
+icons/custom.svg
+po/Lybniz.pot
+po/es.po
+po/messages.mo
+po/es.mo
+locale/es/activity.linfo
+locale/es/LC_MESSAGES/org.ceibaljam.Lybniz.mo
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100644
index 0000000..17b8be4
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,7 @@
+[Activity]
+name = Lybniz Graph Plotter
+activity_version = 1
+bundle_id = org.ceibaljam.Lybniz
+exec = sugar-activity lybniz.LybnizActivity -s
+icon = lybniz
+license = BSD
diff --git a/activity/lybniz.svg b/activity/lybniz.svg
new file mode 100644
index 0000000..83d26b7
--- /dev/null
+++ b/activity/lybniz.svg
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="64px"
+ height="64px"
+ id="svg1878"
+ sodipodi:version="0.32"
+ inkscape:version="0.43+0.44pre2"
+ sodipodi:docbase="/home/sam/docs/computer/python/lybniz"
+ sodipodi:docname="rough_icon.svg"
+ inkscape:export-filename="/home/sam/docs/computer/python/lybniz/rough_icon.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs1880" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="8.3516483"
+ inkscape:cx="34.044423"
+ inkscape:cy="30.5"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ gridempspacing="1"
+ inkscape:window-width="1255"
+ inkscape:window-height="713"
+ inkscape:window-x="0"
+ inkscape:window-y="25" />
+ <metadata
+ id="metadata1883">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:red;stroke-width:1.24230552px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 9.8996329,27.121153 C 5.2933829,29.253472 2.6211528,29.378847 2.6211528,29.378847"
+ id="path1884"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 32,1 L 32,63"
+ id="path1886" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 1,31 L 63,31.120983"
+ id="path1888" />
+ <g
+ id="g2792"
+ transform="translate(1.5,1.5)"
+ style="opacity:0.58944164">
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.7;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 32.544423,1 L 32.544423,63"
+ id="path2794" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#303030;stroke-width:1.8;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 1,31.455577 L 63,31.57656"
+ id="path2796" />
+ </g>
+ <path
+ style="fill:#04cf00;fill-opacity:1;stroke:#3a3a3a;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="M 61.310465,46.81222 C 62.503787,43.965805 57.576413,21.813467 47.216741,20.29835 C 36.840587,18.780824 26.283692,37.97802 22.971826,37.97802 C 19.659958,37.97802 19.925701,18.1364 13.309739,17.74019 C 10.932817,17.597843 2.9702694,23.92899 2.9702694,25.588039 C 2.9702694,27.247087 9.605579,28.288946 11.777492,29.376945 C 13.949404,30.464943 16.755689,50.782738 22.834472,50.782738 C 29.033556,50.782738 40.814232,28.06729 45.755979,28.758304 C 50.71231,29.451353 58.79123,49.510214 61.310465,46.81222 z "
+ id="path2832"
+ sodipodi:nodetypes="czzssszzc" />
+ <path
+ id="path2835"
+ d="M 32,0.518797 L 32,62.518797"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path2837"
+ d="M 24.539253,30.968167 L 45.257397,31.003124"
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:3.93633342;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:white;fill-opacity:1;stroke:black;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path2839"
+ sodipodi:cx="11.789474"
+ sodipodi:cy="25.022556"
+ sodipodi:rx="2.0451128"
+ sodipodi:ry="1.3233082"
+ d="M 13.834586 25.022556 A 2.0451128 1.3233082 0 1 1 9.7443607,25.022556 A 2.0451128 1.3233082 0 1 1 13.834586 25.022556 z"
+ transform="translate(0.755639,-1.845865)" />
+ </g>
+</svg>
diff --git a/icons/connect-points.svg b/icons/connect-points.svg
new file mode 100644
index 0000000..796c105
--- /dev/null
+++ b/icons/connect-points.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="40" height="40" xmlns="http://www.w3.org/2000/svg" version="1.1">
+ <circle cx="32" cy="8" r="4" stroke="#FFFFFF" fill="none" />
+ <circle cx="24" cy="16" r="4" stroke="#FFFFFF" fill="none" />
+ <circle cx="16" cy="24" r="4" stroke="#FFFFFF" fill="none" />
+ <circle cx="8" cy="32" r="4" stroke="#FFFFFF" fill="none" />
+ <path d="M 0,39.5 L39.5,0 L40.5,0 L0,40.5" stroke-width="1" stroke="#FFFFFF"/>
+</svg>
diff --git a/icons/custom.svg b/icons/custom.svg
new file mode 100644
index 0000000..3f0c52e
--- /dev/null
+++ b/icons/custom.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="40" height="40" xmlns="http://www.w3.org/2000/svg" version="1.1">
+ <text x="-1" y="27" font-size="15" font-family="Verdana" fill="white">
+ CUST
+ </text>
+</svg>
diff --git a/icons/decimal.svg b/icons/decimal.svg
new file mode 100644
index 0000000..5fe3dc4
--- /dev/null
+++ b/icons/decimal.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="40" height="40" xmlns="http://www.w3.org/2000/svg" version="1.1">
+ <text x="0" y="28" font-size="19" font-family="Verdana" fill="white">
+ DEC
+ </text>
+</svg>
diff --git a/icons/evaluate.svg b/icons/evaluate.svg
new file mode 100644
index 0000000..6bc2c1f
--- /dev/null
+++ b/icons/evaluate.svg
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="75"
+ height="75"
+ id="svg2802"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="execute.svg"
+ version="1.0">
+ <defs
+ id="defs2804" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="9.7466667"
+ inkscape:cx="37.5"
+ inkscape:cy="49.811901"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="714"
+ inkscape:window-x="7"
+ inkscape:window-y="24"
+ width="75px"
+ height="75px"
+ showgrid="true"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata2807">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="opacity:1">
+ <path
+ style="fill:none;stroke:#ffffff;stroke-width:5.10681915;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+ d="m 31.716688,2.8354575 0,8.6349695 c -3.014647,0.680572 -5.837328,1.875822 -8.369517,3.490238 L 17.274839,8.8535558 9.0101836,17.162256 15.085788,23.272647 c -1.604947,2.545966 -2.793417,5.383167 -3.470369,8.414146 l -8.5858011,0 0,11.75279 8.5858011,0 c 0.676833,3.032179 1.864868,5.870593 3.470369,8.417461 l -6.0756044,6.110387 8.2646554,8.308683 6.072332,-6.107089 c 2.532107,1.614293 5.354997,2.809688 8.369517,3.490244 l 0,8.631661 11.685865,0 0,-8.631661 c 3.015099,-0.680702 5.833753,-1.878758 8.366242,-3.493542 l 6.075599,6.110387 8.261382,-8.308683 -6.075605,-6.110387 c 1.605696,-2.547074 2.796806,-5.384971 3.473644,-8.417461 l 8.585806,0 0,-11.75279 -8.589079,0 c -0.676985,-3.031038 -1.865351,-5.868141 -3.470371,-8.414146 l 6.075605,-6.110391 -8.261382,-8.3087002 -6.075599,6.1104032 c -2.532572,-1.614884 -5.351016,-2.812814 -8.366242,-3.493532 l 0,-8.6349695 -11.685865,0 z m 5.842929,18.8321345 c 8.72415,0 15.805094,7.121483 15.805094,15.895595 -8e-6,8.774106 -7.080944,15.895597 -15.805094,15.895597 -8.724144,0 -15.805085,-7.121491 -15.805085,-15.895597 0,-8.774112 7.080941,-15.895595 15.805085,-15.895595 z"
+ id="rect2811"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/icons/graph.svg b/icons/graph.svg
new file mode 100644
index 0000000..619601e
--- /dev/null
+++ b/icons/graph.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="40" height="40" xmlns="http://www.w3.org/2000/svg" version="1.1">
+ <path class="SamplePath" d="M5,20 C5,10 20,10 20,20 S35,30 35,20" style="fill:none; stroke:#FFFFFF; stroke-width:2"/>
+ <rect x="0" y="19.8" width="40" height="0.4" style="fill: #FFFFFF; stroke: none;"/>
+ <rect x="19.8" y="0" width="0.4" height="40" style="fill: #FFFFFF; stroke: none;"/>
+</svg>
diff --git a/icons/radian.svg b/icons/radian.svg
new file mode 100644
index 0000000..ba2a357
--- /dev/null
+++ b/icons/radian.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="40" height="40" xmlns="http://www.w3.org/2000/svg" version="1.1">
+ <text x="0" y="28" font-size="19" font-family="Verdana" fill="white">
+ RAD
+ </text>
+</svg>
diff --git a/lybniz.py b/lybniz.py
new file mode 100755
index 0000000..b37cff8
--- /dev/null
+++ b/lybniz.py
@@ -0,0 +1,659 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+"""
+ Simple Function graph Plotter
+ © Thomas Führinger, Sam Tygier 2005-2007
+ http://lybniz2.sourceforge.net/
+
+ Version 1.3.2
+ Requires PyGtk 2.6
+ Released under the terms of the revised BSD license
+ Modified: 2007-12-14
+
+ Sugarization by Daniel Francis
+"""
+
+from __future__ import division
+import gtk, pango
+import sys
+import math
+from math import *
+from sugar.activity import activity
+from sugar.graphics.toolbarbox import ToolbarBox
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.toggletoolbutton import ToggleToolButton
+from sugar.graphics.radiotoolbutton import RadioToolButton
+from sugar.activity.widgets import StopButton, ActivityToolbarButton, ToolbarButton
+from gettext import gettext as _
+
+connect_points = True
+x_res = 1
+y1 = "sin(x)"
+y2 = ""
+y3 = ""
+x_max = "5.0"
+x_min = "-5.0"
+x_scale = "1.0"
+y_max = "3.0"
+y_min = "-3.0"
+y_scale = "1.0"
+
+enable_profiling = False
+if enable_profiling:
+ from time import time
+
+# create a safe namespace for the eval()s in the graph drawing code
+def sub_dict(somedict, somekeys, default=None):
+ return dict([ (k, somedict.get(k, default)) for k in somekeys ])
+# a list of the functions from math that we want.
+safe_list = ['math','acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh','fac','sinc']
+safe_dict = sub_dict(locals(), safe_list)
+
+#add any needed builtins back in.
+safe_dict['abs'] = abs
+
+def marks(min_val,max_val,minor=1):
+ "yield positions of scale marks between min and max. For making minor marks, set minor to the number of minors you want between majors"
+ try:
+ min_val = float(min_val)
+ max_val = float(max_val)
+ except:
+ print "needs 2 numbers"
+ raise ValueError
+
+ if(min_val >= max_val):
+ print "min bigger or equal to max"
+ raise ValueError
+
+ a = 0.2 # tweakable control for when to switch scales
+ # big a value results in more marks
+
+ a = a + log10(minor)
+
+ width = max_val - min_val
+ log10_range = log10(width)
+
+ interval = 10 ** int(floor(log10_range - a))
+ lower_mark = min_val - fmod(min_val,interval)
+
+ if lower_mark < min_val:
+ lower_mark += interval
+
+ a_mark = lower_mark
+ while a_mark <= max_val:
+ if abs(a_mark) < interval / 2:
+ a_mark = 0
+ yield a_mark
+ a_mark += interval
+
+class GraphClass:
+ def __init__(self, parent):
+ self.parent = parent
+ self.prev_y = [None, None, None]
+ self.selection = [[None, None], [None, None]]
+ self.drawing_area = gtk.DrawingArea()
+ self.drawing_area.set_events(gtk.gdk.EXPOSURE_MASK | gtk.gdk.LEAVE_NOTIFY_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK |gtk.gdk.POINTER_MOTION_HINT_MASK)
+ self.scale_style = "dec"
+ self.drawing_area.connect("expose_event", self.expose_event)
+ self.drawing_area.connect("configure_event", self.configure_event)
+ self.drawing_area.connect("button_press_event", self.button_press_event)
+ self.drawing_area.connect("button_release_event", self.button_release_event)
+ self.drawing_area.connect("motion_notify_event", self.motion_notify_event)
+
+ def button_press_event(self, widget, event):
+ global x_sel, y_sel
+ if event.button == 1:
+ self.selection[0][0], self.selection[0][1] = int(event.x), int(event.y)
+ self.selection[1][0], self.selection[1][1] = None, None
+
+ # End of selection
+ def button_release_event(self, widget, event):
+ if event.button == 1 and event.x != self.selection[0][0] and event.y != self.selection[0][1]:
+ xmi, ymi = min(self.graph_x(self.selection[0][0]), self.graph_x(event.x)), min(self.graph_y(self.selection[0][1]), self.graph_y(event.y))
+ xma, yma = max(self.graph_x(self.selection[0][0]), self.graph_x(event.x)), max(self.graph_y(self.selection[0][1]), self.graph_y(event.y))
+ self.x_min, self.y_min, self.x_max, self.y_max = xmi, ymi, xma, yma
+ self.parent.parameter_entries_repopulate()
+ self.plot()
+ self.selection[1][0] = None
+ self.selection[0][0] = None
+
+ # Draw rectangle during mouse movement
+ def motion_notify_event(self, widget, event):
+ if event.is_hint:
+ x, y, state = event.window.get_pointer()
+ else:
+ x = event.x
+ y = event.y
+ state = event.state
+
+ if state & gtk.gdk.BUTTON1_MASK and self.selection[0][0] is not None:
+ gc = self.drawing_area.get_style().black_gc
+ gc.set_function(gtk.gdk.INVERT)
+ if self.selection[1][0] is not None:
+ x0 = min(self.selection[1][0], self.selection[0][0])
+ y0 = min(self.selection[1][1], self.selection[0][1])
+ w = abs(self.selection[1][0] - self.selection[0][0])
+ h = abs(self.selection[1][1] - self.selection[0][1])
+ self.pix_map.draw_rectangle(gc, False, x0, y0, w, h)
+ x0 = min(self.selection[0][0], int(x))
+ y0 = min(self.selection[0][1], int(y))
+ w = abs(int(x) - self.selection[0][0])
+ h = abs(int(y) - self.selection[0][1])
+ self.pix_map.draw_rectangle(gc, False, x0, y0, w, h)
+ self.selection[1][0], self.selection[1][1] = int(x), int(y)
+ self.draw_drawable()
+
+ def draw_drawable(self):
+ x, y, w, h = self.drawing_area.get_allocation()
+ self.drawing_area.window.draw_drawable(self.drawing_area.get_style().fg_gc[gtk.STATE_NORMAL], self.pix_map, 0, 0, 0, 0, w, h)
+
+ def graph_x(self, x):
+ "Calculate position on graph from point on canvas"
+ return x * (self.x_max - self.x_min) / self.canvas_width + self.x_min
+
+ def graph_y(self, y):
+ return self.y_max - (y * (self.y_max - self.y_min) / self.canvas_height)
+
+ def plot(self):
+ self.pix_map.draw_rectangle(self.drawing_area.get_style().white_gc, True, 0, 0, self.canvas_width, self.canvas_height)
+
+ if (self.scale_style == "cust"):
+
+ #draw cross
+ self.pix_map.draw_lines(self.gc['black'], [(int(round(self.canvas_x(0))),0),(int(round(self.canvas_x(0))),self.canvas_height)])
+ self.pix_map.draw_lines(self.gc['black'], [(0,int(round(self.canvas_y(0)))),(self.canvas_width,int(round(self.canvas_y(0))))])
+ # old style axis marks
+ iv = self.x_scale * self.canvas_width / (self.x_max - self.x_min) # pixel interval between marks
+ os = self.canvas_x(0) % iv # pixel offset of first mark
+ # loop over each mark.
+ for i in xrange(int(self.canvas_width / iv + 1)):
+ #multiples of iv, cause adding of any error in iv, so keep iv as float
+ # use round(), to get to closest pixel, int() to prevent warning
+ self.pix_map.draw_lines(self.gc['black'], [(int(round(os + i * iv)), int(round(self.canvas_y(0) - 5))), (int(round(os + i * iv)), int(round(self.canvas_y(0) + 5)))])
+
+ # and the y-axis
+ iv = self.y_scale * self.canvas_height / (self.y_max - self.y_min)
+ os = self.canvas_y(0) % iv
+ for i in xrange(int(self.canvas_height / iv + 1)):
+ self.pix_map.draw_lines(self.gc['black'], [(int(round(self.canvas_x(0) - 5)), int(round(i * iv + os))), (int(round(self.canvas_x(0) + 5)), int(round(i * iv + os)))])
+
+ else:
+ #new style
+ factor = 1
+ if (self.scale_style == "rad"): factor = pi
+
+ # where to put the numbers
+ numbers_x_pos = -10
+ numbers_y_pos = 10
+
+ # where to center the axis
+ center_x_pix = int(round(self.canvas_x(0)))
+ center_y_pix = int(round(self.canvas_y(0)))
+ if (center_x_pix < 5): center_x_pix = 5
+ if (center_x_pix < 20):numbers_x_pos = 10
+ if (center_y_pix < 5): center_y_pix = 5
+ if (center_x_pix > self.canvas_width - 5): center_x_pix = self.canvas_width - 5
+ if (center_y_pix > self.canvas_height -5): center_y_pix = self.canvas_height - 5;
+ if (center_y_pix > self.canvas_height -20): numbers_y_pos = - 10
+
+ # draw cross
+ self.pix_map.draw_lines(self.gc['black'], [(center_x_pix,0),(center_x_pix,self.canvas_height)])
+ self.pix_map.draw_lines(self.gc['black'], [(0,center_y_pix),(self.canvas_width,center_y_pix)])
+
+ for i in marks(self.x_min / factor, self.x_max / factor):
+ label = '%g' % i
+ if (self.scale_style == "rad"): label += '\xCF\x80'
+ i = i * factor
+
+ self.pix_map.draw_lines(self.gc['black'], [(int(round(self.canvas_x(i))), center_y_pix - 5), (int(round(self.canvas_x(i))), center_y_pix + 5)])
+
+ self.layout.set_text(label)
+ extents = self.layout.get_pixel_extents()[1]
+ if (numbers_y_pos < 0): adjust = extents[3]
+ else: adjust = 0
+ self.pix_map.draw_layout(self.gc['black'],int(round(self.canvas_x(i))), center_y_pix + numbers_y_pos - adjust,self.layout)
+
+ for i in marks(self.y_min,self.y_max):
+ label = '%g' % i
+
+ self.pix_map.draw_lines(self.gc['black'], [(center_x_pix - 5, int(round(self.canvas_y(i)))), (center_x_pix + 5, int(round(self.canvas_y(i))))])
+
+ self.layout.set_text(label)
+ extents = self.layout.get_pixel_extents()[1]
+ if (numbers_x_pos < 0): adjust = extents[2]
+ else: adjust = 0
+ self.pix_map.draw_layout(self.gc['black'],center_x_pix +numbers_x_pos - adjust,int(round(self.canvas_y(i))),self.layout)
+
+ # minor marks
+ for i in marks(self.x_min / factor, self.x_max / factor, minor=10):
+ i = i * factor
+ self.pix_map.draw_lines(self.gc['black'], [(int(round(self.canvas_x(i))), center_y_pix - 2), (int(round(self.canvas_x(i))), center_y_pix +2)])
+
+ for i in marks(self.y_min, self.y_max, minor=10):
+ label = '%g' % i
+ self.pix_map.draw_lines(self.gc['black'], [(center_x_pix - 2, int(round(self.canvas_y(i)))), (center_x_pix +2, int(round(self.canvas_y(i))))])
+
+ plots = []
+ # precompile the functions
+ try:
+ compiled_y1 = compile(y1.replace("^","**"),"",'eval')
+ plots.append((compiled_y1,0,self.gc['blue']))
+ except:
+ compiled_y1 = None
+ try:
+ compiled_y2 = compile(y2.replace("^","**"),"",'eval')
+ plots.append((compiled_y2,1,self.gc['red']))
+ except:
+ compiled_y2 = None
+ try:
+ compiled_y3 = compile(y3.replace("^","**"),"",'eval')
+ plots.append((compiled_y3,2,self.gc['green']))
+ except:
+ compiled_y3 = None
+
+ self.prev_y = [None, None, None]
+
+ if enable_profiling:
+ start_graph = time()
+
+ if len(plots) != 0:
+ for i in xrange(0,self.canvas_width,x_res):
+ x = self.graph_x(i + 1)
+ for e in plots:
+ safe_dict['x']=x
+ try:
+ y = eval(e[0],{"__builtins__":{}},safe_dict)
+ y_c = int(round(self.canvas_y(y)))
+
+ if y_c < 0 or y_c > self.canvas_height:
+ raise ValueError
+
+ if connect_points and self.prev_y[e[1]] is not None:
+ self.pix_map.draw_lines(e[2], [(i, self.prev_y[e[1]]), (i + x_res, y_c)])
+ else:
+ self.pix_map.draw_points(e[2], [(i + x_res, y_c)])
+ self.prev_y[e[1]] = y_c
+ except Exception, exc:
+ print exc
+ #print "Error at %d: %s" % (x, sys.exc_value)
+ self.prev_y[e[1]] = None
+
+ if enable_profiling:
+ print "time to draw graph:", (time() - start_graph) * 1000, "ms"
+
+ self.draw_drawable()
+
+ def configure_event(self, widget, event):
+ x, y, w, h = widget.get_allocation()
+ self.pix_map = gtk.gdk.Pixmap(widget.window, w, h)
+
+ # make colors
+ self.gc = dict()
+ for name, color in (('black',(0,0,0)),('red',(32000,0,0)),('blue',(0,0,32000)),('green',(0,32000,0))):
+ self.gc[name] =self.pix_map.new_gc()
+ self.gc[name].set_rgb_fg_color(gtk.gdk.Color(red=color[0],green=color[1],blue=color[2]))
+ self.layout = pango.Layout(widget.create_pango_context())
+ self.canvas_width = w
+ self.canvas_height = h
+ self.x_max = eval(x_max,{"__builtins__":{}},safe_dict)
+ self.x_min = eval(x_min,{"__builtins__":{}},safe_dict)
+ self.x_scale = eval(x_scale,{"__builtins__":{}},safe_dict)
+ self.y_max = eval(y_max,{"__builtins__":{}},safe_dict)
+ self.y_min = eval(y_min,{"__builtins__":{}},safe_dict)
+ self.y_scale = eval(y_scale,{"__builtins__":{}},safe_dict)
+ self.plot()
+ return True
+
+ def expose_event(self, widget, event):
+ x, y, w, h = event.area
+ widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pix_map, x, y, x, y, w, h)
+ return False
+
+ def canvas_y(self, y):
+ return (self.y_max - y) * self.canvas_height / (self.y_max - self.y_min)
+
+ def canvas_x(self, x):
+ "Calculate position on canvas to point on graph"
+ return (x - self.x_min) * self.canvas_width / (self.x_max - self.x_min)
+
+class LybnizActivity(activity.Activity):
+ def parameter_entries_repopulate(self):
+ # set text in entries for parameters
+ self.y1_entry.set_text(y1)
+ self.y2_entry.set_text(y2)
+ self.y3_entry.set_text(y3)
+ self.x_min_entry.set_text(str(self.graph.x_min))
+ self.x_max_entry.set_text(str(self.graph.x_max))
+ self.x_scale_entry.set_text(str(self.graph.x_scale))
+ self.y_min_entry.set_text(str(self.graph.y_min))
+ self.y_max_entry.set_text(str(self.graph.y_max))
+ self.y_scale_entry.set_text(str(self.graph.y_scale))
+
+ def zoom_in(self, widget, event=None):
+ "Narrow the plotted section by half"
+ center_x = (self.graph.x_min + self.graph.x_max) / 2
+ center_y = (self.graph.y_min + self.graph.y_max) / 2
+ range_x = (self.graph.x_max - self.graph.x_min)
+ range_y = (self.graph.y_max - self.graph.y_min)
+
+ self.graph.x_min = center_x - (range_x / 4)
+ self.graph.x_max = center_x + (range_x / 4)
+ self.graph.y_min = center_y - (range_y / 4)
+ self.graph.y_max = center_y +(range_y / 4)
+
+ self.parameter_entries_repopulate()
+ self.graph.plot()
+
+ def zoom_out(self, widget, event=None):
+ "Double the plotted section"
+ center_x = (self.graph.x_min + self.graph.x_max) / 2
+ center_y = (self.graph.y_min + self.graph.y_max) / 2
+ range_x = (self.graph.x_max - self.graph.x_min)
+ range_y = (self.graph.y_max - self.graph.y_min)
+
+ self.graph.x_min = center_x - (range_x)
+ self.graph.x_max = center_x + (range_x)
+ self.graph.y_min = center_y - (range_y)
+ self.graph.y_max = center_y +(range_y)
+
+ self.parameter_entries_repopulate()
+ self.graph.plot()
+
+ def zoom_reset(self, widget, event=None):
+ "Set the range back to the user's input"
+
+ self.graph.x_min = eval(x_min,{"__builtins__":{}},safe_dict)
+ self.graph.y_min = eval(y_min,{"__builtins__":{}},safe_dict)
+ self.graph.x_max = eval(x_max,{"__builtins__":{}},safe_dict)
+ self.graph.y_max = eval(y_max,{"__builtins__":{}},safe_dict)
+ self.x_min_entry.set_text(self.x_min)
+ self.x_max_entry.set_text(self.x_max)
+ self.x_scale_entry.set_text(self.x_scale)
+ self.y_min_entry.set_text(self.y_min)
+ self.y_max_entry.set_text(self.y_max)
+ self.y_scale_entry.set_text(self.y_scale)
+ self.graph.plot()
+
+ def evaluate(self, widget, event=None):
+ "Evaluate a given x for the three functions"
+
+ def entry_changed(widget):
+ for e in ((y1, dlg_win.y1_entry), (y2, dlg_win.y2_entry), (y3, dlg_win.y3_entry)):
+ try:
+ x = float(dlg_win.x_entry.get_text())
+ safe_dict['x']=x
+ e[1].set_text(str(eval(e[0].replace("^","**"),{"__builtins__":{}},safe_dict)))
+ except:
+ if len(e[0]) > 0:
+ e[1].set_text("Error: %s" % sys.exc_value)
+ else:
+ e[1].set_text("")
+
+ def close(self):
+ dlg_win.destroy()
+
+ dlg_win = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ dlg_win.set_position(gtk.WIN_POS_CENTER)
+ dlg_win.set_title(_("Evaluate"))
+ dlg_win.connect("destroy", close)
+
+ dlg_win.x_entry = gtk.Entry()
+ dlg_win.x_entry.set_editable(True)
+ dlg_win.x_entry.connect("changed", entry_changed)
+ dlg_win.y1_entry = gtk.Entry()
+ dlg_win.y1_entry.set_size_request(200, 24)
+ dlg_win.y1_entry.set_sensitive(False)
+ dlg_win.y2_entry = gtk.Entry()
+ dlg_win.y2_entry.set_size_request(200, 24)
+ dlg_win.y2_entry.set_sensitive(False)
+ dlg_win.y3_entry = gtk.Entry()
+ dlg_win.y3_entry.set_size_request(200, 24)
+ dlg_win.y3_entry.set_sensitive(False)
+
+ table = gtk.Table(2, 5)
+ label = gtk.Label("x = ")
+ label.set_alignment(0, .5)
+ table.attach(label, 0, 1, 0, 1, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ table.attach(dlg_win.x_entry, 1, 2, 0, 1)
+ label = gtk.Label("y1 = ")
+ label.set_alignment(0, .5)
+ label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("blue"))
+ table.attach(label, 0, 1, 1, 2, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ table.attach(dlg_win.y1_entry, 1, 2, 1, 2)
+ label = gtk.Label("y2 = ")
+ label.set_alignment(0, .5)
+ label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("red"))
+ table.attach(label, 0, 1, 2, 3, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ table.attach(dlg_win.y2_entry, 1, 2, 2, 3)
+ label = gtk.Label("y3 = ")
+ label.set_alignment(0, .5)
+ label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("DarkGreen"))
+ table.attach(label, 0, 1, 3, 4, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ table.attach(dlg_win.y3_entry, 1, 2, 3, 4)
+ table.set_border_width(24)
+ dlg_win.add(table)
+ dlg_win.show_all()
+
+ def plot(self, widget, event=None):
+ global x_max, x_min, x_scale, y_max, y_min, y_scale, y1, y2, y3
+ x_max = self.x_max_entry.get_text()
+ x_min = self.x_min_entry.get_text()
+ x_scale = self.x_scale_entry.get_text()
+
+ y_max = self.y_max_entry.get_text()
+ y_min = self.y_min_entry.get_text()
+ y_scale = self.y_scale_entry.get_text()
+
+ self.graph.x_max = eval(x_max,{"__builtins__":{}},safe_dict)
+ self.graph.x_min = eval(x_min,{"__builtins__":{}},safe_dict)
+ self.graph.x_scale = eval(x_scale,{"__builtins__":{}},safe_dict)
+
+ self.graph.y_max = eval(y_max,{"__builtins__":{}},safe_dict)
+ self.graph.y_min = eval(y_min,{"__builtins__":{}},safe_dict)
+ self.graph.y_scale = eval(y_scale,{"__builtins__":{}},safe_dict)
+
+ y1 = self.y1_entry.get_text()
+ y2 = self.y2_entry.get_text()
+ y3 = self.y3_entry.get_text()
+
+ self.graph.plot()
+
+ def toggle_connect(self, widget, event=None):
+ "Toggle between a graph that connects points with lines and one that does not"
+ global connect_points
+ connect_points = not connect_points
+ self.graph.plot()
+
+ def scale_dec(self, widget, event=None):
+ self.graph.scale_style = "dec"
+ self.scale_box.hide()
+ self.plot(None)
+
+
+ def scale_rad(self, widget, event=None):
+ self.graph.scale_style = "rad"
+ self.scale_box.hide()
+ self.plot(None)
+
+ def scale_cust(self, widget, event=None):
+ self.graph.scale_style = "cust"
+ self.scale_box.show()
+ self.plot(None)
+
+ def __init__(self, handle):
+ activity.Activity.__init__(self, handle)
+ self.y1 = y1
+ self.y2 = y2
+ self.y3 = y3
+ self.x_max = x_max
+ self.x_min = x_min
+ self.x_scale = x_scale
+ self.y_max = y_max
+ self.y_min = y_min
+ self.y_scale = y_scale
+ self.toolbar_box = ToolbarBox()
+ self.activity_button = ActivityToolbarButton(self)
+ self.activity_button.page.share.hide()
+ self.toolbar_box.toolbar.insert(self.activity_button, 0)
+ self.activity_button.show()
+ self.graph_item = ToolbarButton()
+ self.graph_item.props.icon_name = 'graph'
+ self.graph_toolbar = gtk.Toolbar()
+ self.graph_item.props.page = self.graph_toolbar
+ self.plot_item = ToolButton('gtk-refresh')
+ self.plot_item.props.tooltip = _("Plot")
+ self.plot_item.connect("clicked", self.plot)
+ self.plot_item.show()
+ self.graph_toolbar.insert(self.plot_item, 0)
+ self.evaluate_item = ToolButton('evaluate')
+ self.evaluate_item.props.tooltip = _('Evaluate')
+ self.evaluate_item.connect("clicked", self.evaluate)
+ self.evaluate_item.show()
+ self.graph_toolbar.insert(self.evaluate_item, -1)
+ separator = gtk.SeparatorToolItem()
+ separator.show()
+ self.graph_toolbar.insert(separator, -1)
+ self.zoom_in_item = ToolButton('zoom-in')
+ self.zoom_in_item.props.tooltip = _('Zoom In')
+ self.zoom_in_item.connect("clicked", self.zoom_in)
+ self.zoom_in_item.show()
+ self.graph_toolbar.insert(self.zoom_in_item, -1)
+ self.zoom_out_item = ToolButton('zoom-out')
+ self.zoom_out_item.props.tooltip = _('Zoom Out')
+ self.zoom_out_item.connect("clicked", self.zoom_out)
+ self.zoom_out_item.show()
+ self.graph_toolbar.insert(self.zoom_out_item, -1)
+ self.zoom_reset_item = ToolButton('zoom-original')
+ self.zoom_reset_item.props.tooltip = _('Zoom Reset')
+ self.zoom_reset_item.connect("clicked", self.zoom_reset)
+ self.zoom_reset_item.show()
+ self.graph_toolbar.insert(self.zoom_reset_item, -1)
+ separator = gtk.SeparatorToolItem()
+ separator.show()
+ self.graph_toolbar.insert(separator, -1)
+ self.connect_points_item = ToggleToolButton('connect-points')
+ self.connect_points_item.set_tooltip(_("Connect Points"))
+ self.connect_points_item.set_active(True)
+ self.connect_points_item.connect("toggled", self.toggle_connect)
+ self.connect_points_item.show()
+ self.graph_toolbar.insert(self.connect_points_item, -1)
+ separator = gtk.SeparatorToolItem()
+ separator.show()
+ self.graph_toolbar.insert(separator, -1)
+ self.decimal_item = RadioToolButton()
+ self.decimal_item.set_named_icon('decimal')
+ self.decimal_item.set_tooltip(_("Decimal Scale Style"))
+ self.decimal_item.connect("toggled", self.scale_dec)
+ self.decimal_item.show()
+ self.graph_toolbar.insert(self.decimal_item, -1)
+ self.radians_item = RadioToolButton()
+ self.radians_item.set_named_icon('radian')
+ self.radians_item.set_tooltip(_("Radians Scale Style"))
+ self.radians_item.set_group(self.decimal_item)
+ self.radians_item.connect("toggled", self.scale_rad)
+ self.radians_item.show()
+ self.graph_toolbar.insert(self.radians_item, -1)
+ self.custom_item = RadioToolButton()
+ self.custom_item.set_named_icon('custom')
+ self.custom_item.set_tooltip(_("Custom Scale Style"))
+ self.custom_item.set_group(self.radians_item)
+ self.custom_item.connect("toggled", self.scale_cust)
+ self.custom_item.show()
+ self.graph_toolbar.insert(self.custom_item, -1)
+ self.graph_toolbar.show()
+ self.graph_item.show()
+ self.toolbar_box.toolbar.insert(self.graph_item, -1)
+ separator = gtk.SeparatorToolItem()
+ separator.set_draw(False)
+ separator.set_expand(True)
+ separator.show()
+ self.toolbar_box.toolbar.insert(separator, -1)
+ self.stop = StopButton(self)
+ self.stop.show()
+ self.toolbar_box.toolbar.insert(self.stop, -1)
+ self.set_toolbar_box(self.toolbar_box)
+ self.toolbar_box.show()
+ self.v_box = gtk.VBox()
+ self.set_canvas(self.v_box)
+ self.parameter_entries = gtk.Table(6, 3)
+ self.y1_entry = gtk.Entry()
+ self.y2_entry = gtk.Entry()
+ self.y3_entry = gtk.Entry()
+ self.x_min_entry = gtk.Entry()
+ self.x_min_entry.set_size_request(90, 24)
+ self.x_min_entry.set_alignment(1)
+ self.x_max_entry = gtk.Entry()
+ self.x_max_entry.set_size_request(90, 24)
+ self.x_max_entry.set_alignment(1)
+ self.x_scale_entry = gtk.Entry()
+ self.x_scale_entry.set_size_request(90, 24)
+ self.x_scale_entry.set_alignment(1)
+ self.y_min_entry = gtk.Entry()
+ self.y_min_entry.set_size_request(90, 24)
+ self.y_min_entry.set_alignment(1)
+ self.y_max_entry = gtk.Entry()
+ self.y_max_entry.set_size_request(90, 24)
+ self.y_max_entry.set_alignment(1)
+ self.y_scale_entry = gtk.Entry()
+ self.y_scale_entry.set_size_request(90, 24)
+ self.y_scale_entry.set_alignment(1)
+ self.y1_entry.set_text(self.y1)
+ self.y2_entry.set_text(self.y2)
+ self.y3_entry.set_text(self.y3)
+ self.x_min_entry.set_text(self.x_min)
+ self.x_max_entry.set_text(self.x_max)
+ self.x_scale_entry.set_text(self.x_scale)
+ self.y_min_entry.set_text(self.y_min)
+ self.y_max_entry.set_text(self.y_max)
+ self.y_scale_entry.set_text(self.y_scale)
+ self.scale_box = gtk.HBox()
+ label = gtk.Label("y1 = ")
+ label.set_alignment(0, .5)
+ label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("blue"))
+ self.parameter_entries.attach(label, 0, 1, 0, 1, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ self.parameter_entries.attach(self.y1_entry, 1, 2, 0, 1)
+ label = gtk.Label(_("X min"))
+ label.set_alignment(1, .5)
+ self.parameter_entries.attach(label, 2, 3, 0, 1, xpadding=5, ypadding=7, xoptions=gtk.FILL)
+ self.parameter_entries.attach(self.x_min_entry, 3, 4, 0, 1, xoptions=gtk.FILL)
+ label = gtk.Label(_("Y min"))
+ label.set_alignment(1, .5)
+ self.parameter_entries.attach(label, 4, 5, 0, 1, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ self.parameter_entries.attach(self.y_min_entry, 5, 6, 0, 1, xpadding=5, xoptions=gtk.FILL)
+ label = gtk.Label("y2 = ")
+ label.set_alignment(0, .5)
+ label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("red"))
+ self.parameter_entries.attach(label, 0, 1, 1, 2, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ self.parameter_entries.attach(self.y2_entry, 1, 2, 1, 2)
+ label = gtk.Label(_("X max"))
+ label.set_alignment(1, .5)
+ self.parameter_entries.attach(label, 2, 3, 1, 2, xpadding=5, ypadding=7, xoptions=gtk.FILL)
+ self.parameter_entries.attach(self.x_max_entry, 3, 4, 1, 2, xoptions=gtk.FILL)
+ label = gtk.Label(_("Y max"))
+ label.set_alignment(1, .5)
+ self.parameter_entries.attach(label, 4, 5, 1, 2, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ self.parameter_entries.attach(self.y_max_entry, 5, 6, 1, 2, xpadding=5, xoptions=gtk.FILL)
+ label = gtk.Label("y3 = ")
+ label.set_alignment(0, .5)
+ label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("DarkGreen"))
+ self.parameter_entries.attach(label, 0, 1, 2, 3, xpadding=5, ypadding=5, xoptions=gtk.FILL)
+ self.parameter_entries.attach(self.y3_entry, 1, 2, 2, 3)
+ label = gtk.Label(_("X scale"))
+ label.set_alignment(0, .5)
+ self.scale_box.add(label)
+ self.scale_box.add(self.x_scale_entry)
+ label = gtk.Label(_("Y scale"))
+ label.set_alignment(0, .5)
+ self.scale_box.add(label)
+ self.scale_box.add(self.y_scale_entry)
+ self.parameter_entries.attach(self.scale_box, 2, 6, 2, 3, xpadding=5, xoptions=gtk.FILL)
+ self.v_box.pack_start(self.parameter_entries, False, True, 4)
+ self.parameter_entries.show_all()
+ self.graph = GraphClass(self)
+ self.v_box.pack_start(self.graph.drawing_area, True, True, 0)
+ self.status_bar = gtk.Statusbar()
+ self.status_bar.ContextId = self.status_bar.get_context_id("Dummy")
+ self.status_bar.show()
+ self.v_box.pack_end(self.status_bar, False, True, 0)
+ self.v_box.show_all()
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..530f97c
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2006, Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from sugar.activity import bundlebuilder
+
+bundlebuilder.start()