diff options
author | Reinier Heeres <reinier@heeres.eu> | 2007-09-10 09:57:56 (GMT) |
---|---|---|
committer | Reinier Heeres <reinier@heeres.eu> | 2007-09-10 09:57:56 (GMT) |
commit | adc9ebd4ac938f16f804943139768b269bf4b497 (patch) | |
tree | 4269b988337ebf0ea06a8a0e740d5ef46bb1b132 | |
parent | b0cca9f16f0a57ea07c8a27f4421311e96b41680 (diff) |
Bugfixes, plot axes labels, MANIFEST update
-rw-r--r-- | MANIFEST | 6 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | calculate.py | 5 | ||||
-rw-r--r-- | eqnparser.py | 30 | ||||
-rw-r--r-- | layout.py | 1 | ||||
-rw-r--r-- | mathlib.py | 12 | ||||
-rw-r--r-- | plotlib.py | 22 | ||||
-rw-r--r-- | toolbars.py | 2 |
8 files changed, 65 insertions, 17 deletions
@@ -1,8 +1,10 @@ calculate.py -layout.py -toolbars.py eqnparser.py +layout.py mathlib.py +plotlib.py +svgimage.py +toolbars.py sharedstate/__init__.py sharedstate/shareddict.py sharedstate/sharedobject.py @@ -1,3 +1,7 @@ +* Plot support, plot(x^3,x=-2..2) +* Fixed toolbar focus bug +* Improved operator parsing ('*' vs '**' and '<' vs '<<') + 7 6 diff --git a/calculate.py b/calculate.py index ff00a1d..24e47de 100644 --- a/calculate.py +++ b/calculate.py @@ -578,7 +578,8 @@ class Calculate(activity.Activity): self.remove_character(1) def keypress_cb(self, widget, event): - if self.label_entry.is_focus(): + if self.label_entry.is_focus() or \ + self.toolbox.get_activity_toolbar().title.is_focus(): return key = gtk.gdk.keyval_name(event.keyval) @@ -676,7 +677,7 @@ class Calculate(activity.Activity): self.text_entry.set_position(pos + len(str)) else: - _logger.error('Calculate.button_pressed(): invalid type') + _logger.error('button_pressed(): invalid type') def receive_message(self, msg, val): if msg == "add_eq": diff --git a/eqnparser.py b/eqnparser.py index 5e9a05c..bcc3f4f 100644 --- a/eqnparser.py +++ b/eqnparser.py @@ -58,6 +58,14 @@ class ParserState: self.char = None return self.char + def prev(self): + self.ofs -= 1 + if self.ofs < self.strlen and self.ofs >= 0: + self.char = self.str[self.ofs] + else: + self.char = None + return self.char + def set_ofs(self, o): self.ofs = o self.char = self.str[o] @@ -163,6 +171,7 @@ class EqnParser: self.register_operator('/', self.OP_DIADIC, 1, lambda x: self.ml.div(x[0], x[1])) self.register_operator('^', self.OP_DIADIC, 2, lambda x: self.ml.pow(x[0], x[1])) + self.register_operator('**', self.OP_DIADIC, 2, lambda x: self.ml.pow(x[0], x[1])) self.register_operator('!', self.OP_POST, 0, lambda x: self.ml.factorial(x[0])) @@ -330,21 +339,28 @@ class EqnParser: def parse_operator(self, ps, left_val): startofs = ps.ofs + op = None while ps.more() and ps.char in self.OP_CHARS: ps.next() - op = self.valid_operator(ps.str[startofs:ps.ofs], left_val) - if op is not None: - _logger.debug('parse_operator(): %d - %d: %s', startofs, ps.ofs, ps.str[startofs:ps.ofs]) - return op - - return self.INVALID_OP + op2 = self.valid_operator(ps.str[startofs:ps.ofs], left_val) + if op2 is not None: + op = op2 + elif op2 is None and op is not None: + ps.prev() + break + + if op is not None: + _logger.debug('parse_operator(): %d - %d: %s', startofs, ps.ofs, ps.str[startofs:ps.ofs]) + return op + else: + return self.INVALID_OP def parse_func_args(self, ps): startofs = ps.ofs args = [] pcount = 1 while ps.more() and pcount > 0: - if ps.char == ',': + if ps.char == ',' and pcount == 1: args.append(ps.str[startofs:ps.ofs]) startofs = ps.ofs + 1 elif ps.char == '(': @@ -144,6 +144,7 @@ class CalcLayout: def show_it(self): self._parent.set_canvas(self.grid) self._parent.show_all() + self.text_entry.grab_focus() def show_history(self, window_list): if self.history is None: @@ -252,6 +252,18 @@ class MathLib: def ceil(self, x): return self.d(math.ceil(x)) + def shift_left(self, x, y): + if self.is_int(x) and self.is_int(y): + return self.d(int(x) << int(y)) + else: + return 0 + + def shift_right(self, x, y): + if self.is_int(x) and self.is_int(y): + return self.d(int(x) >> int(y)) + else: + return 0 + def factorize(self, x): if not self.is_int(x): return 0 @@ -82,6 +82,13 @@ class PlotLib: self.svg_data += '%f,%f ' % (c[0], c[1]) self.svg_data += '" />\n' + def add_text(self, c, text, rotate=0): + c = self.rcoords_to_coords(c) + self.svg_data += '<text x="%f" y="%f"' % (c[0], c[1]) + if rotate != 0: + self.svg_data += ' transform="rotate(%d)"' % (rotate) + self.svg_data += '>%s</text>\n' % (text) + def determine_bounds(self, vals): self.minx = self.miny = 1e99 self.maxx = self.maxy = -1e99 @@ -102,9 +109,6 @@ class PlotLib: def add_curve(self, vals): self.determine_bounds(vals) - self.plot_line((0.08, 0.08), (0.08, 0.92), "black") - self.plot_line((0.08, 0.92), (0.92, 0.92), "black") - c = [] for v in vals: c.append(self.vals_to_rcoords(v)) @@ -112,6 +116,13 @@ class PlotLib: self.plot_polyline(c, "blue") + def draw_axes(self, labelx, labely): + self.plot_line((0.08, 0.92), (0.92, 0.92), "black") + self.add_text((0.50, 0.98), labelx) + + self.plot_line((0.08, 0.08), (0.08, 0.92), "black") + self.add_text((-0.50, 0.065), labely, rotate=-90) + def export_plot(self, fn): f = open(fn, "w") f.write(self.svg_data) @@ -127,12 +138,13 @@ class PlotLib: self.set_size(200, 200) self.create_image() + self.draw_axes(var, eqn) + vals = self.evaluate(eqn, var, range) # print 'vals: %r' % vals self.add_curve(vals) self.finish_image() - self.export_plot("/tmp/calculate_graph.svg") - +# self.export_plot("/tmp/calculate_graph.svg") return self.get_svg() diff --git a/toolbars.py b/toolbars.py index 8b06fae..cc137dd 100644 --- a/toolbars.py +++ b/toolbars.py @@ -164,4 +164,4 @@ class FormatToolbar(gtk.Toolbar): calc.ml.set_angle_type(MathLib.ANGLE_DEG) elif text == 'rad': calc.ml.set_angle_type(MathLib.ANGLE_RAD) - _logger.debug('Angle type: %s', self.calc.ml.angle_scaling) + _logger.debug('Angle type: %s', self.ml.angle_scaling) |