#!/usr/bin/env python """ Copyright 2009 Adam Schreiber 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 3 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, see . """ import gtk import math class DrawShapesArea(gtk.DrawingArea): def __init__(self): gtk.DrawingArea.__init__(self) self.connect_after("expose_event", self.expose) self.ones = 0 self.tens = 0 self.hundreds = 0 self.thousands = 0 self.tenthousands = 0 self.hundredthousands = 0 def expose(self, widget, event): self.context = widget.window.cairo_create() # set a clip region for the expose event self.context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) self.context.clip() self.draw(self.context) return False def draw (self, context): rect = self.get_allocation() context.set_source_rgba(0.0, 0.0, 0.0, 1.0) context.move_to (rect.width/6, 0) context.line_to (rect.width/6, rect.height) context.move_to (2*rect.width/6, 0) context.line_to (2*rect.width/6, rect.height) context.move_to (3*rect.width/6, 0) context.line_to (3*rect.width/6, rect.height) context.move_to (4*rect.width/6, 0) context.line_to (4*rect.width/6, rect.height) context.move_to (5*rect.width/6, 0) context.line_to (5*rect.width/6, rect.height) context.stroke() for m in range (0,5): for n in range (0,2): if (((5-m) + ((n+1)%2)*5) <= self.ones): opacity = 1 else: opacity = 0.25 self.drawBar (context, 5*rect.width/6 + n*rect.width/12, m*rect.height/6 + (rect.height - 5*rect.height/6)/2, rect.width/12, rect.height/6, opacity) for m in range (0,5): for n in range (0,2): if (((5-m) + ((n+1)%2)*5) <= self.tens): opacity = 1 else: opacity = 0.25 self.drawCircle (context, 4*rect.width/6 + n*rect.width/12, m*rect.height/6 + (rect.height - 5*rect.height/6)/2, rect.width/12, rect.height/6, opacity) for m in range (0,5): for n in range (0,2): if (((5-m) + ((n+1)%2)*5) <= self.hundreds): opacity = 1 else: opacity = 0.25 self.drawTriangle (context, 3*rect.width/6 + n*rect.width/12, m*rect.height/6 + (rect.height - 5*rect.height/6)/2, rect.width/12, rect.height/6, opacity) for m in range (0,5): for n in range (0,2): if (((5-m) + ((n+1)%2)*5) <= self.thousands): opacity = 1 else: opacity = 0.25 self.drawSquare (context, + 2*rect.width/6 + n*rect.width/12, m*rect.height/6 + (rect.height - 5*rect.height/6)/2, rect.width/12, rect.height/6, opacity) for m in range (0,5): for n in range (0,2): if (((5-m) + ((n+1)%2)*5) <= self.tenthousands): opacity = 1 else: opacity = 0.25 self.drawPentagon (context, + 1*rect.width/6 + n*rect.width/12, m*rect.height/6 + (rect.height - 5*rect.height/6)/2, rect.width/12, rect.height/6, opacity) for m in range (0,5): for n in range (0,2): if (((5-m) + ((n+1)%2)*5) <= self.hundredthousands): opacity = 1 else: opacity = 0.25 self.drawHexagon (context, + 0*rect.width/6 + n*rect.width/12, m*rect.height/6 + (rect.height - 5*rect.height/6)/2, rect.width/12, rect.height/6, opacity) def set_count (self, count): val = int(count) self.hundredthousands = int(math.floor(val/math.pow(10,5))) self.tenthousands = int(math.floor(math.fmod(val,math.pow(10,5))/math.pow(10,4))) self.thousands = int(math.floor(math.fmod(val,math.pow(10,4))/math.pow(10,3))) self.hundreds = int(math.floor(math.fmod(val,math.pow(10,3))/math.pow(10,2))) self.tens = int(math.floor(math.fmod(val,math.pow(10,2))/math.pow(10,1))) self.ones = int(math.floor(math.fmod(val,math.pow(10,1)))) self.queue_draw () def get_count (): return (self.hundredthousands * 10**5 + self.tenthousands * 10**4 + self.thousands * 10**3 + self.hundreds * 10**2 + self.tens * 10 + self.ones) def drawBar (self, context, x, y, width, height, opacity): context.rectangle(gtk.gdk.Rectangle(x + width/3, y+height/6, width/3, height*2/3)) context.set_source_rgba(0.933, 0.510, 0.933, opacity) context.fill_preserve() context.set_source_rgba(0.933, 0.510, 0.933, 1.0) context.stroke() def drawCircle (self, context, x, y, width, height, opacity): x = x + width / 2 y = y + height / 2 radius = min(width / 2, height / 2) - 5 context.arc(x, y, radius, 0, 2 * math.pi) context.set_source_rgba(0, 0, 1, opacity) context.fill_preserve() context.set_source_rgb(0, 0, 1) context.stroke() def drawTriangle (self, context, x, y, width, height, opacity): x = x + width / 2 y = y + height / 2 radius = min(width / 2, height / 2) - 5 context.move_to (x, y - radius) context.line_to (x+radius*math.cos(-30.0/180.0*math.pi), y - radius*math.sin(-30.0/180.0*math.pi)) context.line_to (x-radius*math.cos(-30.0/180.0*math.pi), y - radius*math.sin(-30.0/180.0*math.pi)) context.line_to (x, y - radius) context.set_source_rgba(0.0, 1.0, 0.0, opacity) context.fill_preserve() context.set_source_rgba(0.0, 1.0, 0.0, 1.0) context.stroke() def drawSquare (self, context, x, y, width, height, opacity): x = x + width / 2 y = y + height / 2 radius = min(width / 2, height / 2) - 5 context.rectangle (gtk.gdk.Rectangle (int(x-.5*radius*math.sqrt(2.0)), int(y-.5*radius*math.sqrt(2.0)), int(radius*math.sqrt(2.0)), int(radius*math.sqrt(2.0)))) context.set_source_rgba(1.0, 1.0, 0.0, opacity) context.fill_preserve() context.set_source_rgba(1.0, 1.0, 0.0, 1.0) context.stroke() def drawPentagon (self, context, x, y, width, height, opacity): x = x + width / 2 y = y + height / 2 radius = min(width / 2, height / 2) - 5 context.move_to (x, y - radius) context.line_to (x+radius*math.cos(13.0/180.0*math.pi), y - radius*math.sin(13.0/180.0*math.pi)) context.line_to (x+radius*math.cos(54.0/180.0*math.pi), y + radius*math.sin(54.0/180.0*math.pi)) context.line_to (x-radius*math.cos(54.0/180.0*math.pi), y + radius*math.sin(54.0/180.0*math.pi)) context.line_to (x-radius*math.cos(13.0/180.0*math.pi), y - radius*math.sin(13.0/180.0*math.pi)) context.line_to (x, y - radius) context.set_source_rgba(1.0, 0.647, 0.0, opacity) context.fill_preserve() context.set_source_rgba(1.0, 0.647, 0.0, 1.0) context.stroke() def drawHexagon (self, context, x, y, width, height, opacity): x = x + width / 2 y = y + height / 2 radius = min(width / 2, height / 2) - 5 context.move_to (x+radius*math.cos(60.0/180.0*math.pi), y - radius*math.sin(60.0/180.0*math.pi)) context.line_to (x+radius, y) context.line_to (x+radius*math.cos(60.0/180.0*math.pi), y + radius*math.sin(60.0/180.0*math.pi)) context.line_to (x-radius*math.cos(60.0/180.0*math.pi), y + radius*math.sin(60.0/180.0*math.pi)) context.line_to (x-radius, y) context.line_to (x - radius*math.cos(60.0/180.0*math.pi), y - radius*math.sin(60.0/180.0*math.pi)) context.line_to (x+radius*math.cos(60.0/180.0*math.pi), y - radius*math.sin(60.0/180.0*math.pi)) context.set_source_rgba(1.0, 0.0, 0.0, opacity) context.fill_preserve() context.set_source_rgba(1.0, 0.0, 0.0, 1.0) context.stroke() def main(): window = gtk.Window(gtk.WINDOW_TOPLEVEL) window.connect("delete_event", delete_event) window.connect("destroy", gtk.main_quit) window.set_border_width(10) window.set_default_size(640, 480) window.set_title("Deka") vbox = gtk.VBox (False, 10) window.add(vbox) # Scrollbar Value Label hbox = gtk.HBox() spinbut = gtk.SpinButton() spinbut.set_range(0,999999) spinbut.set_increments(1,100) spinbut.set_numeric(True) hbox.pack_start(spinbut, True, False) vbox.pack_start(hbox, False) # Scrollbar hscrollbar = gtk.HScrollbar() hscrollbar.set_range(0,999999) hscrollbar.set_increments(1,100) vbox.pack_start(hscrollbar, False) # Equivalent Label equivlab = gtk.Label("0 * 100000 + 0 * 10000 + 0 * 1000 + 0 * 100 + 0 * 10 + 0 * 1 = 0") vbox.pack_start(equivlab, False) # Power of 10 Equivalent Label powequivlab = gtk.Label("0 * 105 + 0 * 104 + 0 * 103 + 0 * 102 + 0 * 101 + 0 * 100 = 0") powequivlab.set_use_markup(True) vbox.pack_start(powequivlab, False) # Start Figure Box drawshapesarea = DrawShapesArea() vbox.add(drawshapesarea) spinbut.connect("value-changed", scrollbar_changed, [spinbut, hscrollbar, equivlab, powequivlab, drawshapesarea]) hscrollbar.connect("value-changed", scrollbar_changed, [spinbut, hscrollbar, equivlab, powequivlab, drawshapesarea]) window.show_all() gtk.main() def scrollbar_changed(range, data=None): spinbut = data[0] hscrollbar = data[1] equivlab = data[2] powequivlab = data[3] drawshapesarea = data[4] val = round(range.get_value()) if abs(val) < abs(1e-2): val = 0 val = int(val) val5 = int(math.floor(val/math.pow(10,5))) val4 = int(math.floor(math.fmod(val,math.pow(10,5))/math.pow(10,4))) val3 = int(math.floor(math.fmod(val,math.pow(10,4))/math.pow(10,3))) val2 = int(math.floor(math.fmod(val,math.pow(10,3))/math.pow(10,2))) val1 = int(math.floor(math.fmod(val,math.pow(10,2))/math.pow(10,1))) val0 = int(math.floor(math.fmod(val,math.pow(10,1)))) spinbut.set_value(int(val)) hscrollbar.set_value(int(val)) equivlab.set_text("{0} * 100000 + {1} * 10000 + {2} * 1000 + {3} * 100 + {4} * 10 + {5} * 1 = {6}".format(val5, val4, val3, val2, val1, val0, val)) powequivlab.set_markup("{0} * 105 + {1} * 104 + {2} * 103 + {3} * 102 + {4} * 101 + {5} * 100 = {6}".format(val5, val4, val3, val2, val1, val0, val)) drawshapesarea.set_count (val) def delete_event(widget, event, data=None): return False if __name__ == "__main__": main()