#!/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 write_file(self, file_path): x, y, w, h = self.graph.drawing_area.get_allocation() pix_buffer = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, w, h) pix_buffer.get_from_drawable(self.graph.pix_map, self.graph.pix_map.get_colormap(), 0, 0, 0, 0, w, h) pix_buffer.save(file_path, "png") 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()