Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamie Boisture <jboisture@nevada.gctaa.net>2009-06-08 15:41:44 (GMT)
committer Jamie Boisture <jboisture@nevada.gctaa.net>2009-06-08 15:41:44 (GMT)
commit493b2c5dba1e3bda872e836f89dbd05cfe0539d8 (patch)
treeffa2002b1e4499b7982109b779aaa38c1fba3b60
This is the initial commit to the Logic Circuits Activity
-rwxr-xr-xLogicCircuitsActivity.py804
-rwxr-xr-xLogicCircuitsActivity.pycbin0 -> 30485 bytes
-rwxr-xr-xLogicCircuitsActivity.py~813
-rwxr-xr-xMANIFEST~11
-rwxr-xr-xactivity/.logic-circuits.sugar.svg.swpbin0 -> 12288 bytes
-rwxr-xr-xactivity/.logic-circuits.svg.swobin0 -> 12288 bytes
-rwxr-xr-xactivity/.logic-circuits.svg.swpbin0 -> 12288 bytes
-rwxr-xr-xactivity/activity.info8
-rwxr-xr-xactivity/activity.info~8
-rwxr-xr-xactivity/logic-circuits.sugar.svg9
-rwxr-xr-xactivity/logic-circuits.svg9
-rwxr-xr-xactivity/logic-circuits.svg~9
-rwxr-xr-xdata/AND.svg29
-rwxr-xr-xdata/NOT.svg30
-rwxr-xr-xdata/OR.svg32
-rwxr-xr-xdata/XOR.svg33
-rwxr-xr-xdata/greenlight.svg47
-rwxr-xr-xdata/redlight.svg47
-rwxr-xr-xmanifest11
-rwxr-xr-xsaves/save1.lc5
-rwxr-xr-xsaves/save2.lc5
-rwxr-xr-xsaves/save3.lc5
-rwxr-xr-xsaves/save4.lc5
-rwxr-xr-xsaves/save5.lc5
-rwxr-xr-xsaves/save6.lc5
-rwxr-xr-xsaves/save7.lc5
-rwxr-xr-xsaves/save8.lc5
-rwxr-xr-xsaves/save9.lc5
-rwxr-xr-xsetup.py4
29 files changed, 1949 insertions, 0 deletions
diff --git a/LogicCircuitsActivity.py b/LogicCircuitsActivity.py
new file mode 100755
index 0000000..93c2a11
--- /dev/null
+++ b/LogicCircuitsActivity.py
@@ -0,0 +1,804 @@
+#!/usr/bin/env python
+
+# example helloworld.py
+from sugar.activity import activity
+import pygtk
+pygtk.require('2.0')
+import gtk
+import os
+import time
+import rsvg
+import cairo
+
+class LogicCircuitsActivity(activity.Activity):
+
+ def __init__(self,handle):
+ activity.Activity.__init__(self,handle)
+ self.set_title('Logic Circuits Activity')
+ #begin the program
+ self.build_GUI()
+
+
+ self.graphics = graphicsDriver()
+ self.mouse_move = 0
+ self.clicked = 0
+ self.buffer = gtk.gdk.Pixmap(self.draw_area.window, 3*self.X/4, self.Y)
+ self.gc = gtk.gdk.GC(self.buffer)
+ gtk.main()
+
+ def delete_event(self, widget, event, data=None):
+ print "delete event occurred"
+ return False
+
+ def destroy(self, widget, data=None):
+ print "destroy signal occurred"
+ gtk.main_quit()
+
+ def set_placement(self, widget, data=None):
+ self.LightButton.set_relief(gtk.RELIEF_NORMAL)
+ self.AndButton.set_relief(gtk.RELIEF_NORMAL)
+ self.NotButton.set_relief(gtk.RELIEF_NORMAL)
+ self.OrButton.set_relief(gtk.RELIEF_NORMAL)
+ self.XorButton.set_relief(gtk.RELIEF_NORMAL)
+ widget.set_relief(gtk.RELIEF_NONE)
+ self.graphics.changeDrawingType(widget.get_label())
+
+ def set_connection(self, widget, data=None):
+ self.input_button.set_relief(gtk.RELIEF_NORMAL)
+ self.output_button.set_relief(gtk.RELIEF_NORMAL)
+ widget.set_relief(gtk.RELIEF_NONE)
+ self.graphics.changeConnectionType(widget.get_label())
+
+
+ def expose(self, widget, event):
+ self.update()
+
+
+ def update(self,pos=(0,0)):
+ #update the screen
+ self.context = self.buffer.cairo_create()
+ self.context.rectangle(0, 0,
+ *self.draw_area.window.get_size())
+ self.context.clip()
+ self.context.set_source_rgb(1, 1, 1)
+ self.context.rectangle(0, 0, *self.draw_area.window.get_size())
+ self.context.fill()
+ self.context.set_source_rgb(0, 0, 0)
+ self.graphics.update(self.context,pos)
+ self.draw_area.window.draw_drawable(self.gc,self.buffer,0,0,0,0,-1,-1,)
+
+
+ def build_GUI(self):
+ #build the GUI
+ size= self.get_frame_dimensions()
+ self.X = self.window.get_screen().get_width()
+ self.Y = self.window.get_screen().get_height()
+ global X,Y
+ X = self.X
+ Y = self.Y
+
+ self.table = gtk.Table(4,3,False)
+ self.table.show()
+
+ self.draw_area = gtk.DrawingArea()
+ self.v = gtk.VPaned()
+ self.table.attach(self.v,0,3,0,3)
+ self.v.show()
+ self.v.add1(self.draw_area)
+ self.draw_area.set_size_request(3*self.X/4, self.Y)
+ self.draw_area.show()
+ self.draw_area.set_events(gtk.gdk.POINTER_MOTION_MASK |
+ gtk.gdk.BUTTON_PRESS_MASK |
+ gtk.gdk.KEY_PRESS_MASK |
+ gtk.gdk.BUTTON_RELEASE_MASK |
+ gtk.gdk.POINTER_MOTION_HINT_MASK )
+ self.draw_area.connect("motion_notify_event", self.mouse_move)
+ self.draw_area.connect('button-press-event', self.mouse_press)
+ self.draw_area.connect('button-release-event', self.mouse_release)
+ self.draw_area.connect("expose_event", self.expose)
+ self.filechooser = gtk.FileChooserWidget(gtk.FILE_CHOOSER_ACTION_OPEN)
+ self.v.add2(self.filechooser)
+ self.filechooser.set_size_request(3*self.X/4, self.Y)
+ self.filechooser.connect("file-activated",self.fileChoosen)
+ self.filechooser.set_current_folder("saves")
+ self.filter = gtk.FileFilter()
+ self.filter.set_name("txt files")
+ self.filter.add_pattern("*.lc")
+
+ self.filechooser.add_filter(self.filter)
+
+
+
+
+ self.Frame1 = gtk.Frame("Select an Object to Place")
+ self.table.attach(self.Frame1,3,4,0,1)
+ self.Frame1.set_size_request(self.X/4,self.Y/2)
+ self.Frame1.show()
+
+ self.Frame2 = gtk.Frame("Select a Connection Type")
+ self.table.attach(self.Frame2,3,4,1,2)
+ self.Frame2.set_size_request(self.X/4,self.Y/4)
+ self.Frame2.show()
+
+ self.Frame3 = gtk.Frame("Save and Load")
+ self.table.attach(self.Frame3,3,4,2,3)
+ self.Frame3.set_size_request(self.X/4,self.Y/4)
+ self.Frame3.show()
+
+ self.save_table = gtk.Table(2, 3, False)
+ self.Frame3.add(self.save_table)
+ self.save_table.show()
+
+ self.filename = gtk.Label("File Name:")
+ self.save_table.attach(self.filename,0,1,0,1)
+ self.filename.show()
+
+ self.file_text = gtk.Entry(15)
+ self.save_table.attach(self.file_text,1,2,0,1)
+ self.file_text.show()
+
+ self.SaveButton = gtk.Button(stock = gtk.STOCK_SAVE)
+ self.save_table.attach(self.SaveButton,0,2,1,2)
+ self.SaveButton.show()
+ self.SaveButton.connect("clicked", self.saveFile, None)
+
+ self.OpenButton = gtk.Button(stock = gtk.STOCK_OPEN)
+ self.save_table.attach(self.OpenButton,0,2,2,3)
+
+ self.OpenButton.show()
+ self.OpenButton.connect("clicked", self.loadFile, None)
+
+ and_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/AND.svg").get_pixbuf())
+ not_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/NOT.svg").get_pixbuf())
+ or_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/OR.svg").get_pixbuf())
+ xor_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/XOR.svg").get_pixbuf())
+ light_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/redlight.svg").get_pixbuf())
+
+ self.object_table = gtk.Table(1, 6, False)
+ self.Frame1.add(self.object_table)
+ self.object_table.show()
+
+ self.LightButton = gtk.Button("Light")
+ self.AndButton = gtk.Button("And")
+ self.NotButton = gtk.Button("Not")
+ self.OrButton = gtk.Button("Or")
+ self.XorButton = gtk.Button("Xor")
+
+ self.LightButton.connect("clicked", self.set_placement, None)
+ self.AndButton.connect("clicked", self.set_placement, None)
+ self.NotButton.connect("clicked", self.set_placement, None)
+ self.OrButton.connect("clicked", self.set_placement, None)
+ self.XorButton.connect("clicked", self.set_placement, None)
+
+ self.LightButton.set_relief(gtk.RELIEF_NONE)
+
+ self.AndButton.set_image(and_image)
+ self.NotButton.set_image(not_image)
+ self.OrButton.set_image(or_image)
+ self.XorButton.set_image(xor_image)
+ self.LightButton.set_image(light_image)
+
+
+
+ self.object_table.attach(self.LightButton,0,1,1,2)
+ self.object_table.attach(self.AndButton,0,1,2,3)
+ self.object_table.attach(self.NotButton,0,1,3,4)
+ self.object_table.attach(self.OrButton,0,1,4,5)
+ self.object_table.attach(self.XorButton,0,1,5,6)
+
+ self.LightButton.show()
+ self.AndButton.show()
+ self.NotButton.show()
+ self.OrButton.show()
+ self.XorButton.show()
+
+ self.connection_table = gtk.Table(1,2,False)
+ self.Frame2.add(self.connection_table)
+ self.connection_table.show()
+ self.input_button = gtk.Button("Input")
+ self.output_button = gtk.Button("Output")
+ self.input_button.connect("clicked", self.set_connection, None)
+ self.output_button.connect("clicked", self.set_connection, None)
+ self.connection_table.attach(self.input_button,0,1,0,1)
+ self.connection_table.attach(self.output_button,0,1,1,2)
+ self.input_button.set_relief(gtk.RELIEF_NONE)
+ self.input_button.show()
+ self.output_button.show()
+ self.set_canvas(self.table)
+ self.show()
+
+ def mouse_press(self, widget, event):
+ if self.clicked + .1 < time.time():
+ if event.button == 1: self.graphics.button1((event.x,event.y))
+ if event.button == 2: self.graphics.button2((event.x,event.y))
+ if event.button == 3: self.graphics.button3((event.x,event.y))
+ self.update((event.x,event.y))
+ self.clicked=time.time()
+
+
+ def mouse_release(self, widget, event):
+ if event.button == 1:
+ if self.graphics.pressed != None:
+ self.graphics.pressed.clicked = False
+ self.graphics.pressed = None
+
+ def mouse_move(self, widget, event):
+ if self.mouse_move == 1:
+ if self.graphics.pressed != None:
+ self.graphics.pressed.move((event.x,event.y))
+ self.update((event.x,event.y))
+ self.mouse_move = 0
+ self.mouse_move += 1
+ self.mousePositions = (event.x,event.y)
+
+ def saveFile(self, widget, event):
+ text = self.file_text.get_text()
+ save(text)
+
+ def loadFile(self, widget, event):
+ self.draw_area.hide()
+ self.filechooser.show()
+
+ def fileChoosen(self, widget):
+ filename = widget.get_filename()
+ load(filename)
+ self.draw_area.show()
+ self.filechooser.hide()
+
+
+
+
+
+class Light:
+
+ def __init__(self, position):
+ self.color = "red"
+ self.svg = rsvg.Handle("data/" +self.color+"light.svg")
+ self.pos = position
+ self.mousePos = (0,0)
+ self.clicked = False
+
+ def change_color(self):
+ if self.color == "red":
+ self.color = "green"
+ elif self.color == "green":
+ self.color = "red"
+ self.update_image()
+ calculate()
+
+
+ def set_color(self, color):
+ if color == "red":
+ self.color = "red"
+ elif color == "green":
+ self.color = "green"
+
+ def is_clicked(self, pos):
+ self.mousePos = pos
+ self.clicked = True
+
+ def get(self):
+ if self.color == "red":
+ return 0
+ return 1
+
+ def move(self, pos):
+ x = pos[0]-self.pos[0]
+ y = pos[1]-self.pos[1]
+ if int(x + self.pos[0]) in range(0,3*X/4): x = x + self.pos[0]
+ else: x = self.pos[0]
+ if int(y + self.pos[1]) in range(0,Y): y = y + self.pos[1]
+ else: y = self.pos[1]
+ self.pos = (x,y)
+ #self.mousePos = pos
+ for i in connections: i.update()
+
+
+ def update_image(self):
+ self.svg = rsvg.Handle("data/" +self.color+"light.svg")
+
+ def draw(self, context):
+ context.translate(self.pos[0]-self.svg.props.width/2, self.pos[1]-self.svg.props.height/2)
+ self.svg.render_cairo(context)
+ context.translate(-1*(self.pos[0]-self.svg.props.width/2), -1*(self.pos[1]-self.svg.props.height/2))
+
+
+
+class Circuit:
+
+ def __init__(self, pos, max_inputs, text,input_pos, output_pos):
+ self.input_positions = input_pos
+ self.output_positions = output_pos
+ self.svg = rsvg.Handle("data/" +text+".svg")
+ self.text = text
+ self.pos = pos
+ self.inputs = []
+ self.outputs = []
+ self.max_inputs = max_inputs
+ self.clicked = False
+ self.mousePos = (0,0)
+
+ def add_input(self, input_object):
+ if len(self.inputs) > 0 and self.inputs[0].pos[1] > input_object.pos[1]:
+ self.inputs = [input_object,self.inputs[0]]
+ else: self.inputs.append(input_object)
+
+ def is_clicked(self, pos):
+ self.mousePos = pos
+ self.clicked = True
+
+ def add_output(self, output_object):
+ self.outputs.append(output_object)
+ if output_object in pressing_lights:
+ non_pressing_lights.append(output_object)
+ pressing_lights.remove(output_object)
+
+ def draw(self, context):
+ i = 0
+ context.translate(self.pos[0]-self.svg.props.width/2, self.pos[1]-self.svg.props.height/2)
+ self.svg.render_cairo(context)
+ context.translate(-1*(self.pos[0]-self.svg.props.width/2), -1*(self.pos[1]-self.svg.props.height/2))
+ context.set_source_rgb(1,0,0)
+ while i < len(self.inputs):
+ context.move_to(self.pos[0]+self.input_positions[i][0],self.pos[1]+self.input_positions[i][1])
+ context.line_to(*self.inputs[i].pos)
+ context.stroke()
+ i += 1
+ context.set_source_rgb(0,0,1)
+ for i in self.outputs:
+ context.move_to(self.pos[0]+self.output_positions[0],self.pos[1]+self.output_positions[1])
+ context.line_to(*i.pos)
+ context.stroke()
+
+ def move(self, pos):
+ x = pos[0]-self.mousePos[0]
+ y = pos[1]-self.mousePos[1]
+ mpx = pos[0]
+ mpy = pos[1]
+ if int(x + self.pos[0]) in range(0,3*X/4): x = x + self.pos[0]
+ else:
+ x = self.pos[0]
+ mpx = self.mousePos[0]
+ if int(y + self.pos[1]) in range(0,Y): y = y + self.pos[1]
+ else:
+ y = self.pos[1]
+ mpy = self.mousePos[1]
+ self.pos = (x,y)
+ self.mousePos = (mpx,mpy)
+ for i in connections: i.update()
+
+ def calculate(self):
+ pass
+
+
+class Not(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 1, "NOT",[(-45,0)],(45,0))
+ self.name = "not"
+
+ def calculate(self):
+ if not self.inputs[0].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+
+class And(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 2, "AND", [(-45,-10),(-45,10)],(45,0))
+ self.name = "and"
+
+ def calculate(self):
+ if self.inputs[0].get() and self.inputs[1].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+
+class Or(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 2, "OR", [(-45,-10),(-45,10)],(45,0))
+ self.name = "or"
+
+ def calculate(self):
+ if self.inputs[0].get() or self.inputs[1].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+
+class Xor(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 2, "XOR", [(-45,-10),(-45,10)],(45,0))
+ self.name = "xor"
+
+ def calculate(self):
+ if not self.inputs[0].get() == self.inputs[1].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+class connection:
+ def __init__(self, circuit, light):
+ self.light = light
+ self.circuit = circuit
+ x1 = light.pos[0]
+ y1 = light.pos[1]
+ if self.light in self.circuit.inputs:
+ i = self.circuit.inputs.index(self.light)
+ x2 = self.circuit.pos[0]+self.circuit.input_positions[i][0]
+ y2 = self.circuit.pos[1]+self.circuit.input_positions[i][1]
+ else:
+ x2 = self.circuit.pos[0]+self.circuit.output_positions[0]
+ y2 = self.circuit.pos[1]+self.circuit.output_positions[1]
+ if x1-x2 == 0:
+ self.slope = 0
+ elif x1<x2:
+ self.range = (x1,x2)
+ self.slope = 1.0*(y1-y2)/(x1-x2)
+ elif x1>x2:
+ self.range = (x2,x1)
+ self.slope = 1.0*(y2-y1)/(x2-x1)
+ self.intercept = y1 - self.slope*x1
+ calculate()
+
+ def update(self):
+ x1 = self.light.pos[0]
+ y1 = self.light.pos[1]
+ if self.light in self.circuit.inputs:
+ i = self.circuit.inputs.index(self.light)
+ x2 = self.circuit.pos[0]+self.circuit.input_positions[i][0]
+ y2 = self.circuit.pos[1]+self.circuit.input_positions[i][1]
+ else:
+ x2 = self.circuit.pos[0]+self.circuit.output_positions[0]
+ y2 = self.circuit.pos[1]+self.circuit.output_positions[1]
+ if x1-x2 == 0:
+ self.slope = 0
+ elif x1<x2:
+ self.range = (x1,x2)
+ self.slope = 1.0*(y1-y2)/(x1-x2)
+ elif x1>x2:
+ self.range = (x2,x1)
+ self.slope = 1.0*(y2-y1)/(x2-x1)
+ self.intercept = y1 - self.slope*x1
+
+
+ def in_range(self,x):
+ if x > self.range[0] and x < self.range[1]:
+ return True
+ return False
+
+ def get_error(self, (x, y)):
+ return self.intercept + self.slope*x - y
+
+ def destroy(self):
+ if self.light in self.circuit.inputs:
+ del self.circuit.inputs[self.circuit.inputs.index(self.light)]
+ elif self.light in self.circuit.outputs:
+ del self.circuit.outputs[self.circuit.outputs.index(self.light)]
+ del connections[connections.index(self)]
+
+
+
+def add_circuit(pos, string):
+ if string.lower() == "not":
+ circuits.append(Not(pos))
+ if string.lower() == "or":
+ circuits.append(Or(pos))
+ if string.lower() == "and":
+ circuits.append(And(pos))
+ if string.lower() == "xor":
+ circuits.append(Xor(pos))
+
+
+
+def is_over(pos, item):
+ if item.pos[0]-item.svg.props.width/2 < pos[0] < item.pos[0]+item.svg.props.width/2 and \
+ item.pos[1]-item.svg.props.height/2 < pos[1] < item.pos[1]+item.svg.props.height/2:
+ return True
+ return False
+
+def connect(light, circuit):
+ if input_or_output == "Output":
+ if not circuit.outputs and light not in circuit.inputs:
+ connected = False
+ for i in circuits:
+ if light in i.outputs: connected = True
+ if not connected:
+ circuit.add_output(light)
+ connections.append(connection(circuit,light))
+ elif input_or_output == "Input":
+ if len(circuit.inputs) != circuit.max_inputs \
+ and light not in circuit.inputs and light not in circuit.outputs:
+ circuit.add_input(light)
+ connections.append(connection(circuit,light))
+
+
+def calculate():
+ for item in xrange(55):
+ for i in circuits:
+ if i.outputs and len(i.inputs) == i.max_inputs:
+ i.calculate()
+ for i in circuits:
+ for item in i.outputs:
+ item.update_image()
+
+
+class graphicsDriver:
+ def __init__(self, input_size=(900,900)):
+ global pressing_lights, non_pressing_lights, clock, size
+ global circuits, drawing, font, input_or_output, connections
+ size = input_size
+ connections = []
+ pressing_lights = []
+ non_pressing_lights = []
+ pos = 10
+ circuits = []
+ drawing = "Light"
+ self.selected = None
+ input_or_output = "Input"
+ self.pressed = None
+
+ def changeDrawingType(self, text):
+ global drawing
+ drawing = text
+
+ def changeConnectionType(self, text):
+ global input_or_output
+ input_or_output = text
+
+
+ def button1(self,pos):
+ clicked = []
+ for i in pressing_lights:
+ if is_over(pos, i):
+ i.change_color()
+ clicked.append(i)
+
+ for i in non_pressing_lights:
+ if is_over(pos, i):
+ clicked.append(i)
+
+ moused_over = False
+ for i in circuits:
+ if is_over(pos,i):
+ clicked.append(i)
+ if len(clicked) > 0:
+ clicked[-1].is_clicked(pos)
+ self.pressed = clicked[-1]
+ over = False
+ for i in circuits:
+ if is_over(pos,i):
+ over = True
+ for i in pressing_lights:
+ if is_over(pos,i):
+ over = True
+ for i in non_pressing_lights:
+ if is_over(pos,i):
+ over = True
+ if drawing.lower() in ("or", "and", "not", "xor"):
+ if not over:
+ add_circuit(pos, drawing)
+ if "light" in drawing.lower():
+ if not over:
+ pressing_lights.append(Light(pos))
+
+
+ def button2(self,pos):
+ deleted = False
+ for i in non_pressing_lights:
+ if is_over(pos, i):
+ del non_pressing_lights[non_pressing_lights.index(i)]
+ if self.selected == i:
+ self.selected = None
+ for item in circuits:
+ if i in item.inputs:
+ del item.inputs[item.inputs.index(i)]
+ deleted = True
+ if i in item.outputs:
+ del item.outputs[item.outputs.index(i)]
+ deleted = True
+ for i in pressing_lights:
+ if is_over(pos, i):
+ del pressing_lights[pressing_lights.index(i)]
+ if self.selected == i:
+ self.selected = None
+ for item in circuits:
+ if i in item.inputs:
+ del item.inputs[item.inputs.index(i)]
+ deleted = True
+ if i in item.outputs:
+ del item.outputs[item.outputs.index(i)]
+ deleted = True
+ for i in circuits:
+ if is_over(pos, i):
+ circuits.remove(i)
+ deleted = True
+ if self.selected == i:
+ self.selected = None
+ if not deleted:
+ connects = []
+ for i in connections:
+ if i.in_range(pos[0]):
+ connects.append(i)
+ if len(connects) > 0:
+ closest = connects[0]
+ for i in connects:
+ if abs(i.get_error(pos)) < abs(closest.get_error(pos)):
+ closest = i
+ distance = closest.get_error(pos)
+ if abs(distance) < 12:
+ closest.destroy()
+
+ def button3(self, pos):
+ over = False
+ for i in pressing_lights:
+ if is_over(pos, i):
+ if self.selected and self.selected in circuits:
+ connect(i, self.selected)
+ self.selected = None
+ elif self.selected == i:
+ self.selected = None
+ elif not self.selected:
+ self.selected = i
+ over = True
+ for i in non_pressing_lights:
+ if is_over(pos, i):
+ if self.selected and self.selected in circuits:
+ connect(i, self.selected)
+ self.selected = None
+ elif self.selected == i:
+ self.selected = None
+ elif not self.selected:
+ self.selected = i
+ over = True
+ for i in circuits:
+ if is_over(pos, i):
+ if self.selected in non_pressing_lights or \
+ self.selected in pressing_lights and self.selected:
+ connect(self.selected, i)
+ self.selected = None
+ elif self.selected == i:
+ self.selected = None
+ elif not self.selected:
+ self.selected = i
+ over = True
+ if not over: self.selected = None
+
+
+
+ def update(self, context,pos):
+ if self.selected:
+ context.set_source_rgb(1, 1, 0)
+ context.rectangle(self.selected.pos[0]-self.selected.svg.props.width/2-2, self.selected.pos[1]-self.selected.svg.props.height/2-2,
+ self.selected.svg.props.width+4,self.selected.svg.props.height+4)
+ context.fill()
+ for i in circuits:
+ i.draw(context)
+ for i in pressing_lights:
+ i.draw(context)
+ for i in non_pressing_lights:
+ i.draw(context)
+ context.set_font_size(20)
+ moused_over = False
+ context.set_source_rgb(0,0,0)
+ for i in circuits:
+ if is_over(pos,i) and not moused_over:
+ context.move_to(pos[0]+10,pos[1]-10)
+ context.show_text(i.name)
+ moused_over=True
+
+
+
+
+
+
+def save(name):
+ if name == "":
+ files = []
+ for i in os.listdir(os.path.join("saves", "")):
+ if ".lc" in i:
+ item = i.split(".lc")[0]
+ if "save" in item:
+ item = item.split("save")[1]
+ files.append(int(item))
+ try:
+ name = "save" + str(max(files) + 1)
+ except:
+ name = "save1"
+ open_file = open(os.path.join("saves", name + ".lc"), "w")
+ list1 = {}
+ for i in pressing_lights:
+ list1[i.pos[0]] = i.pos[1]
+ list2 = {}
+ for i in non_pressing_lights:
+ list2[i.pos[0]] = i.pos[1]
+ circuit_list = ""
+ for i in circuits:
+ circuit_list += str(i.pos[0]) + ":" + str(i.pos[1])
+ circuit_list += ":" + i.name
+ circuit_list += ","
+ input_connect = ""
+ for i in circuits:
+ for item in i.inputs:
+ input_connect += str(item.pos[0]) + ":" + \
+ str(item.pos[1])
+ input_connect += ";"
+ input_connect += str(i.pos[0])+":"+str(i.pos[1])
+ input_connect += ","
+ output_connect = ""
+ for i in circuits:
+ for item in i.outputs:
+ output_connect += str(item.pos[0]) + ":" + \
+ str(item.pos[1])
+ output_connect += ";"
+ output_connect += str(i.pos[0])+":"+str(i.pos[1])
+ output_connect += ","
+ open_file.write(str(list1) + "\n")
+ open_file.write(str(list2) + "\n")
+ open_file.write(circuit_list + "\n")
+ open_file.write(input_connect + "\n")
+ open_file.write(str(output_connect) + "\n")
+
+
+def load(name):
+ global circuits, pressing_lights, non_pressing_lights, input_or_output
+ try:
+ open_file = open(os.path.join(name), "r").readlines()
+ except:
+ return
+ circuits = []
+ pressing_lights = []
+ non_pressing_lights = []
+ for i in open_file[0][1:-2].split(","):
+ if i:
+ pressing_lights.append(Light((float(i.split(":")[0].strip()),
+ float(i.split(":")[1].strip()))))
+ for i in open_file[1][1:-2].split(","):
+ if i:
+ non_pressing_lights.append(Light((float(i.split(":")[0].strip()),
+ float(i.split(":")[1].strip()))))
+ for i in open_file[2].strip().split(","):
+ if i:
+ add_circuit((float(i.split(":")[0]), float(i.split(":")[1])),
+ i.split(":")[2])
+ input_or_output = "Input"
+ for l in open_file[3].split(","):
+ i = l.strip()
+ if i:
+ for item in pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in non_pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in circuits:
+ if item.pos == (float(i.split(";")[1].split(":")[0]),
+ float(i.split(";")[1].split(":")[1])):
+ circuit = item
+ connect(light, circuit)
+ input_or_output = "Output"
+ for l in open_file[4].split(","):
+ i = l.strip()
+ if i:
+ for item in pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in non_pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in circuits:
+ if item.pos == (float(i.split(";")[1].split(":")[0]),
+ float(i.split(";")[1].split(":")[1])):
+ circuit = item
+ connect(light, circuit)
+ input_or_output = "Input"
+
diff --git a/LogicCircuitsActivity.pyc b/LogicCircuitsActivity.pyc
new file mode 100755
index 0000000..56cfca3
--- /dev/null
+++ b/LogicCircuitsActivity.pyc
Binary files differ
diff --git a/LogicCircuitsActivity.py~ b/LogicCircuitsActivity.py~
new file mode 100755
index 0000000..b8c2d91
--- /dev/null
+++ b/LogicCircuitsActivity.py~
@@ -0,0 +1,813 @@
+#!/usr/bin/env python
+
+# example helloworld.py
+from sugar.activity import activity
+import pygtk
+pygtk.require('2.0')
+import gtk
+import os
+import time
+import rsvg
+import cairo
+X = 1200
+Y = 900
+
+class LogicCircuitsActivity(activity.Activity):
+
+ def __init__(self,handle):
+ activity.Activity.__init__(self,handle)
+ self.set_title('Logic Circuits Activity')
+ #begin the program
+ self.build_GUI()
+
+
+ self.graphics = graphicsDriver()
+ self.mouse_move = 0
+ self.clicked = 0
+ self.buffer = gtk.gdk.Pixmap(self.draw_area.window, 900, 900)
+ self.gc = gtk.gdk.GC(self.buffer)
+ gtk.main()
+
+ def delete_event(self, widget, event, data=None):
+ print "delete event occurred"
+ return False
+
+ def destroy(self, widget, data=None):
+ print "destroy signal occurred"
+ gtk.main_quit()
+
+ def set_placement(self, widget, data=None):
+ self.InputLightButton.set_relief(gtk.RELIEF_NORMAL)
+ self.OutputLightButton.set_relief(gtk.RELIEF_NORMAL)
+ self.AndButton.set_relief(gtk.RELIEF_NORMAL)
+ self.NotButton.set_relief(gtk.RELIEF_NORMAL)
+ self.OrButton.set_relief(gtk.RELIEF_NORMAL)
+ self.XorButton.set_relief(gtk.RELIEF_NORMAL)
+ widget.set_relief(gtk.RELIEF_NONE)
+ self.graphics.changeDrawingType(widget.get_label())
+
+ def set_connection(self, widget, data=None):
+ self.input_button.set_relief(gtk.RELIEF_NORMAL)
+ self.output_button.set_relief(gtk.RELIEF_NORMAL)
+ widget.set_relief(gtk.RELIEF_NONE)
+ self.graphics.changeConnectionType(widget.get_label())
+
+
+ def expose(self, widget, event):
+ self.update()
+
+
+ def update(self,pos=(0,0)):
+ #update the screen
+ self.context = self.buffer.cairo_create()
+ self.context.rectangle(0, 0,
+ *self.draw_area.window.get_size())
+ self.context.clip()
+ self.context.set_source_rgb(1, 1, 1)
+ self.context.rectangle(0, 0, *self.draw_area.window.get_size())
+ self.context.fill()
+ self.context.set_source_rgb(0, 0, 0)
+ self.graphics.update(self.context,pos)
+ self.draw_area.window.draw_drawable(self.gc,self.buffer,0,0,0,0,-1,-1,)
+
+
+ def build_GUI(self):
+ #build the GUI
+ self.hpaned = gtk.HPaned()
+
+ self.draw_area = gtk.DrawingArea()
+ self.v = gtk.VPaned()
+ self.hpaned.add1(self.v)
+ self.v.show()
+ self.v2 = gtk.VPaned()
+ self.v.add1(self.draw_area)
+ self.draw_area.set_size_request(3*X/4, Y)
+ self.draw_area.show()
+ self.draw_area.set_events(gtk.gdk.POINTER_MOTION_MASK |
+ gtk.gdk.BUTTON_PRESS_MASK |
+ gtk.gdk.KEY_PRESS_MASK |
+ gtk.gdk.BUTTON_RELEASE_MASK |
+ gtk.gdk.POINTER_MOTION_HINT_MASK )
+ self.draw_area.connect("motion_notify_event", self.mouse_move)
+ self.draw_area.connect('button-press-event', self.mouse_press)
+ self.draw_area.connect('button-release-event', self.mouse_release)
+ self.draw_area.connect("expose_event", self.expose)
+ self.filechooser = gtk.FileChooserWidget(gtk.FILE_CHOOSER_ACTION_OPEN)
+ self.v.add2(self.filechooser)
+ self.filechooser.set_size_request(3*X/4, Y)
+ self.filechooser.connect("file-activated",self.fileChoosen)
+ self.filechooser.set_current_folder("saves")
+ self.filter = gtk.FileFilter()
+ self.filter.set_name("txt files")
+ self.filter.add_pattern("*.lc")
+
+ self.filechooser.add_filter(self.filter)
+
+
+
+ self.vpaned = gtk.VPaned()
+ self.hpaned.add2(self.vpaned)
+ self.vpaned.show()
+
+ self.Frame1 = gtk.Frame("Select an Object to Place")
+ self.vpaned.add1(self.Frame1)
+ self.Frame1.show()
+
+ self.Frame2 = gtk.Frame("Select a Connection Type")
+ self.vpaned2 = gtk.VPaned()
+ self.vpaned.add2(self.vpaned2)
+ self.vpaned2.show()
+ self.vpaned2.add1(self.Frame2)
+ self.Frame2.show()
+
+ self.Frame3 = gtk.Frame("Save and Load")
+ self.vpaned2.add2(self.Frame3)
+ self.Frame3.show()
+
+ self.save_table = gtk.Table(2, 3, False)
+ self.Frame3.add(self.save_table)
+ self.save_table.show()
+
+ self.filename = gtk.Label("File Name:")
+ self.save_table.attach(self.filename,0,1,0,1)
+ self.filename.show()
+
+ self.file_text = gtk.Entry(15)
+ self.save_table.attach(self.file_text,1,2,0,1)
+ self.file_text.show()
+
+ self.SaveButton = gtk.Button(stock = gtk.STOCK_SAVE)
+ self.save_table.attach(self.SaveButton,0,2,1,2)
+ self.SaveButton.show()
+ self.SaveButton.connect("clicked", self.saveFile, None)
+
+ self.OpenButton = gtk.Button(stock = gtk.STOCK_OPEN)
+ self.save_table.attach(self.OpenButton,0,2,2,3)
+ self.OpenButton.show()
+ self.OpenButton.connect("clicked", self.loadFile, None)
+
+ and_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/AND.svg").get_pixbuf())
+ not_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/NOT.svg").get_pixbuf())
+ or_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/OR.svg").get_pixbuf())
+ xor_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/XOR.svg").get_pixbuf())
+ inputlight_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/redlight.svg").get_pixbuf())
+ outputlight_image = gtk.image_new_from_pixbuf(rsvg.Handle("data/redlight.svg").get_pixbuf())
+
+ self.object_table = gtk.Table(1, 6, False)
+ self.Frame1.add(self.object_table)
+ self.object_table.show()
+ self.object_table.set_size_request(X/4,2*Y/4)
+
+ self.InputLightButton = gtk.Button("Input Light")
+ self.OutputLightButton = gtk.Button("Output Light")
+ self.AndButton = gtk.Button("And")
+ self.NotButton = gtk.Button("Not")
+ self.OrButton = gtk.Button("Or")
+ self.XorButton = gtk.Button("Xor")
+
+ self.InputLightButton.connect("clicked", self.set_placement, None)
+ self.OutputLightButton.connect("clicked", self.set_placement, None)
+ self.AndButton.connect("clicked", self.set_placement, None)
+ self.NotButton.connect("clicked", self.set_placement, None)
+ self.OrButton.connect("clicked", self.set_placement, None)
+ self.XorButton.connect("clicked", self.set_placement, None)
+
+ self.InputLightButton.set_relief(gtk.RELIEF_NONE)
+
+ self.AndButton.set_image(and_image)
+ self.NotButton.set_image(not_image)
+ self.OrButton.set_image(or_image)
+ self.XorButton.set_image(xor_image)
+ self.InputLightButton.set_image(inputlight_image)
+ self.OutputLightButton.set_image(outputlight_image)
+
+
+
+ self.object_table.attach(self.InputLightButton,0,1,0,1)
+ self.object_table.attach(self.OutputLightButton,0,1,1,2)
+ self.object_table.attach(self.AndButton,0,1,2,3)
+ self.object_table.attach(self.NotButton,0,1,3,4)
+ self.object_table.attach(self.OrButton,0,1,4,5)
+ self.object_table.attach(self.XorButton,0,1,5,6)
+
+ self.InputLightButton.show()
+ self.OutputLightButton.show()
+ self.AndButton.show()
+ self.NotButton.show()
+ self.OrButton.show()
+ self.XorButton.show()
+
+ self.connection_table = gtk.Table(1,2,False)
+ self.Frame2.add(self.connection_table)
+ self.connection_table.show()
+ self.connection_table.set_size_request(X/4,Y/4)
+ self.input_button = gtk.Button("Input")
+ self.output_button = gtk.Button("Output")
+ self.input_button.connect("clicked", self.set_connection, None)
+ self.output_button.connect("clicked", self.set_connection, None)
+ self.connection_table.attach(self.input_button,0,1,0,1)
+ self.connection_table.attach(self.output_button,0,1,1,2)
+ self.input_button.set_relief(gtk.RELIEF_NONE)
+ self.input_button.show()
+ self.output_button.show()
+ self.set_canvas(self.hpaned)
+ self.show_all()
+
+ def mouse_press(self, widget, event):
+ if self.clicked + .1 < time.time():
+ if event.button == 1: self.graphics.button1((event.x,event.y))
+ if event.button == 2: self.graphics.button2((event.x,event.y))
+ if event.button == 3: self.graphics.button3((event.x,event.y))
+ self.update((event.x,event.y))
+ self.clicked=time.time()
+
+
+ def mouse_release(self, widget, event):
+ if event.button == 1:
+ if self.graphics.pressed != None:
+ self.graphics.pressed.clicked = False
+ self.graphics.pressed = None
+
+ def mouse_move(self, widget, event):
+ if self.mouse_move == 3:
+ if self.graphics.pressed != None:
+ self.graphics.pressed.move((event.x,event.y))
+ self.update((event.x,event.y))
+ self.mouse_move = 0
+ self.mouse_move += 1
+ self.mousePositions = (event.x,event.y)
+
+ def saveFile(self, widget, event):
+ text = self.file_text.get_text()
+ save(text)
+
+ def loadFile(self, widget, event):
+ self.draw_area.hide()
+ self.filechooser.show()
+
+ def fileChoosen(self, widget):
+ filename = widget.get_filename()
+ load(filename)
+ self.draw_area.show()
+ self.filechooser.hide()
+
+
+
+
+
+class Light:
+
+ def __init__(self, position):
+ self.color = "red"
+ self.svg = rsvg.Handle("data/" +self.color+"light.svg")
+ self.pos = position
+ self.mousePos = (0,0)
+ self.clicked = False
+
+ def change_color(self):
+ if self.color == "red":
+ self.color = "green"
+ elif self.color == "green":
+ self.color = "red"
+ self.update_image()
+ calculate()
+
+
+ def set_color(self, color):
+ if color == "red":
+ self.color = "red"
+ elif color == "green":
+ self.color = "green"
+
+ def is_clicked(self, pos):
+ self.mousePos = pos
+ self.clicked = True
+
+ def get(self):
+ if self.color == "red":
+ return 0
+ return 1
+
+ def move(self, pos):
+ x = pos[0]-self.pos[0]
+ y = pos[1]-self.pos[1]
+ if int(x + self.pos[0]) in range(0,900): x = x + self.pos[0]
+ else: x = self.pos[0]
+ if int(y + self.pos[1]) in range(0,900): y = y + self.pos[1]
+ else: y = self.pos[1]
+ self.pos = (x,y)
+ #self.mousePos = pos
+ for i in connections: i.update()
+
+
+ def update_image(self):
+ self.svg = rsvg.Handle("data/" +self.color+"light.svg")
+
+ def draw(self, context):
+ context.translate(self.pos[0]-self.svg.props.width/2, self.pos[1]-self.svg.props.height/2)
+ self.svg.render_cairo(context)
+ context.translate(-1*(self.pos[0]-self.svg.props.width/2), -1*(self.pos[1]-self.svg.props.height/2))
+
+
+
+class Circuit:
+
+ def __init__(self, pos, max_inputs, text,input_pos, output_pos):
+ self.input_positions = input_pos
+ self.output_positions = output_pos
+ self.svg = rsvg.Handle("data/" +text+".svg")
+ self.text = text
+ self.pos = pos
+ self.inputs = []
+ self.outputs = []
+ self.max_inputs = max_inputs
+ self.clicked = False
+ self.mousePos = (0,0)
+
+ def add_input(self, input_object):
+ if len(self.inputs) > 0 and self.inputs[0].pos[1] > input_object.pos[1]:
+ self.inputs = [input_object,self.inputs[0]]
+ else: self.inputs.append(input_object)
+
+ def is_clicked(self, pos):
+ self.mousePos = pos
+ self.clicked = True
+
+ def add_output(self, output_object):
+ self.outputs.append(output_object)
+
+
+ def draw(self, context):
+ i = 0
+ context.translate(self.pos[0]-self.svg.props.width/2, self.pos[1]-self.svg.props.height/2)
+ self.svg.render_cairo(context)
+ context.translate(-1*(self.pos[0]-self.svg.props.width/2), -1*(self.pos[1]-self.svg.props.height/2))
+ context.set_source_rgb(1,0,0)
+ while i < len(self.inputs):
+ context.move_to(self.pos[0]+self.input_positions[i][0],self.pos[1]+self.input_positions[i][1])
+ context.line_to(*self.inputs[i].pos)
+ context.stroke()
+ i += 1
+ context.set_source_rgb(0,0,1)
+ for i in self.outputs:
+ context.move_to(self.pos[0]+self.output_positions[0],self.pos[1]+self.output_positions[1])
+ context.line_to(*i.pos)
+ context.stroke()
+
+ def move(self, pos):
+ x = pos[0]-self.mousePos[0]
+ y = pos[1]-self.mousePos[1]
+ mpx = pos[0]
+ mpy = pos[1]
+ if int(x + self.pos[0]) in range(0,900): x = x + self.pos[0]
+ else:
+ x = self.pos[0]
+ mpx = self.mousePos[0]
+ if int(y + self.pos[1]) in range(0,900): y = y + self.pos[1]
+ else:
+ y = self.pos[1]
+ mpy = self.mousePos[1]
+ self.pos = (x,y)
+ self.mousePos = (mpx,mpy)
+ for i in connections: i.update()
+
+ def calculate(self):
+ pass
+
+
+class Not(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 1, "NOT",[(-45,0)],(45,0))
+ self.name = "not"
+
+ def calculate(self):
+ if not self.inputs[0].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+
+class And(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 2, "AND", [(-45,-10),(-45,10)],(45,0))
+ self.name = "and"
+
+ def calculate(self):
+ if self.inputs[0].get() and self.inputs[1].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+
+class Or(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 2, "OR", [(-45,-10),(-45,10)],(45,0))
+ self.name = "or"
+
+ def calculate(self):
+ if self.inputs[0].get() or self.inputs[1].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+
+class Xor(Circuit):
+
+ def __init__(self, pos):
+ Circuit.__init__(self, pos, 2, "XOR", [(-45,-10),(-45,10)],(45,0))
+ self.name = "xor"
+
+ def calculate(self):
+ if not self.inputs[0].get() == self.inputs[1].get():
+ self.outputs[0].set_color("green")
+ else:
+ self.outputs[0].set_color("red")
+
+class connection:
+ def __init__(self, circuit, light):
+ self.light = light
+ self.circuit = circuit
+ x1 = light.pos[0]
+ y1 = light.pos[1]
+ if self.light in self.circuit.inputs:
+ i = self.circuit.inputs.index(self.light)
+ x2 = self.circuit.pos[0]+self.circuit.input_positions[i][0]
+ y2 = self.circuit.pos[1]+self.circuit.input_positions[i][1]
+ else:
+ x2 = self.circuit.pos[0]+self.circuit.output_positions[0]
+ y2 = self.circuit.pos[1]+self.circuit.output_positions[1]
+ if x1-x2 == 0:
+ self.slope = 0
+ elif x1<x2:
+ self.range = (x1,x2)
+ self.slope = 1.0*(y1-y2)/(x1-x2)
+ elif x1>x2:
+ self.range = (x2,x1)
+ self.slope = 1.0*(y2-y1)/(x2-x1)
+ self.intercept = y1 - self.slope*x1
+ calculate()
+
+ def update(self):
+ x1 = self.light.pos[0]
+ y1 = self.light.pos[1]
+ if self.light in self.circuit.inputs:
+ i = self.circuit.inputs.index(self.light)
+ x2 = self.circuit.pos[0]+self.circuit.input_positions[i][0]
+ y2 = self.circuit.pos[1]+self.circuit.input_positions[i][1]
+ else:
+ x2 = self.circuit.pos[0]+self.circuit.output_positions[0]
+ y2 = self.circuit.pos[1]+self.circuit.output_positions[1]
+ if x1-x2 == 0:
+ self.slope = 0
+ elif x1<x2:
+ self.range = (x1,x2)
+ self.slope = 1.0*(y1-y2)/(x1-x2)
+ elif x1>x2:
+ self.range = (x2,x1)
+ self.slope = 1.0*(y2-y1)/(x2-x1)
+ self.intercept = y1 - self.slope*x1
+
+
+ def in_range(self,x):
+ if x > self.range[0] and x < self.range[1]:
+ return True
+ return False
+
+ def get_error(self, (x, y)):
+ return self.intercept + self.slope*x - y
+
+ def destroy(self):
+ if self.light in self.circuit.inputs:
+ del self.circuit.inputs[self.circuit.inputs.index(self.light)]
+ elif self.light in self.circuit.outputs:
+ del self.circuit.outputs[self.circuit.outputs.index(self.light)]
+ del connections[connections.index(self)]
+
+
+
+def add_circuit(pos, string):
+ if string.lower() == "not":
+ circuits.append(Not(pos))
+ if string.lower() == "or":
+ circuits.append(Or(pos))
+ if string.lower() == "and":
+ circuits.append(And(pos))
+ if string.lower() == "xor":
+ circuits.append(Xor(pos))
+
+
+
+def is_over(pos, item):
+ if item.pos[0]-item.svg.props.width/2 < pos[0] < item.pos[0]+item.svg.props.width/2 and \
+ item.pos[1]-item.svg.props.height/2 < pos[1] < item.pos[1]+item.svg.props.height/2:
+ return True
+ return False
+
+def connect(light, circuit):
+ if input_or_output == "Output":
+ if not circuit.outputs and light not in circuit.inputs:
+ connected = False
+ for i in circuits:
+ if light in i.outputs: connected = True
+ if not connected:
+ circuit.add_output(light)
+ connections.append(connection(circuit,light))
+ elif input_or_output == "Input":
+ if len(circuit.inputs) != circuit.max_inputs \
+ and light not in circuit.inputs and light not in circuit.outputs:
+ circuit.add_input(light)
+ connections.append(connection(circuit,light))
+
+
+def calculate():
+ for item in xrange(55):
+ for i in circuits:
+ if i.outputs and len(i.inputs) == i.max_inputs:
+ i.calculate()
+ for i in circuits:
+ for item in i.outputs:
+ item.update_image()
+
+
+class graphicsDriver:
+ def __init__(self, input_size=(900,900)):
+ global pressing_lights, non_pressing_lights, clock, size
+ global circuits, drawing, font, input_or_output, connections
+ size = input_size
+ connections = []
+ pressing_lights = []
+ non_pressing_lights = []
+ pos = 10
+ circuits = []
+ drawing = "Input Light"
+ self.selected = None
+ input_or_output = "Input"
+ self.pressed = None
+
+ def changeDrawingType(self, text):
+ global drawing
+ drawing = text
+
+ def changeConnectionType(self, text):
+ global input_or_output
+ input_or_output = text
+
+
+ def button1(self,pos):
+ clicked = []
+ for i in pressing_lights:
+ if is_over(pos, i):
+ i.change_color()
+ clicked.append(i)
+
+ for i in non_pressing_lights:
+ if is_over(pos, i):
+ clicked.append(i)
+
+ moused_over = False
+ for i in circuits:
+ if is_over(pos,i):
+ clicked.append(i)
+ if len(clicked) > 0:
+ clicked[-1].is_clicked(pos)
+ self.pressed = clicked[-1]
+ over = False
+ for i in circuits:
+ if is_over(pos,i):
+ over = True
+ for i in pressing_lights:
+ if is_over(pos,i):
+ over = True
+ for i in non_pressing_lights:
+ if is_over(pos,i):
+ over = True
+ if drawing.lower() in ("or", "and", "not", "xor"):
+ temp = Not(pos)
+ if not over:
+ add_circuit(temp.pos, drawing)
+ if "light" in drawing.lower():
+ temp = Light(pos)
+ if not over:
+ if "input" in drawing.lower():
+ pressing_lights.append(temp)
+ elif "output" in drawing.lower():
+ non_pressing_lights.append(temp)
+
+
+ def button2(self,pos):
+ deleted = False
+ for i in non_pressing_lights:
+ if is_over(pos, i):
+ del non_pressing_lights[non_pressing_lights.index(i)]
+ if self.selected == i:
+ self.selected = None
+ for item in circuits:
+ if i in item.inputs:
+ del item.inputs[item.inputs.index(i)]
+ deleted = True
+ if i in item.outputs:
+ del item.outputs[item.outputs.index(i)]
+ deleted = True
+ for i in pressing_lights:
+ if is_over(pos, i):
+ del pressing_lights[pressing_lights.index(i)]
+ if self.selected == i:
+ self.selected = None
+ for item in circuits:
+ if i in item.inputs:
+ del item.inputs[item.inputs.index(i)]
+ deleted = True
+ if i in item.outputs:
+ del item.outputs[item.outputs.index(i)]
+ deleted = True
+ for i in circuits:
+ if is_over(pos, i):
+ circuits.remove(i)
+ deleted = True
+ if self.selected == i:
+ self.selected = None
+ if not deleted:
+ connects = []
+ for i in connections:
+ if i.in_range(pos[0]):
+ connects.append(i)
+ if len(connects) > 0:
+ closest = connects[0]
+ for i in connects:
+ if abs(i.get_error(pos)) < abs(closest.get_error(pos)):
+ closest = i
+ distance = closest.get_error(pos)
+ if abs(distance) < 12:
+ closest.destroy()
+
+ def button3(self, pos):
+ over = False
+ for i in pressing_lights:
+ if is_over(pos, i):
+ if self.selected and self.selected in circuits:
+ connect(i, self.selected)
+ self.selected = None
+ elif self.selected == i:
+ self.selected = None
+ elif not self.selected:
+ self.selected = i
+ over = True
+ for i in non_pressing_lights:
+ if is_over(pos, i):
+ if self.selected and self.selected in circuits:
+ connect(i, self.selected)
+ self.selected = None
+ elif self.selected == i:
+ self.selected = None
+ elif not self.selected:
+ self.selected = i
+ over = True
+ for i in circuits:
+ if is_over(pos, i):
+ if self.selected in non_pressing_lights or \
+ self.selected in pressing_lights and self.selected:
+ connect(self.selected, i)
+ self.selected = None
+ elif self.selected == i:
+ self.selected = None
+ elif not self.selected:
+ self.selected = i
+ over = True
+ if not over: self.selected = None
+
+
+
+ def update(self, context,pos):
+ if self.selected:
+ context.set_source_rgb(1, 1, 0)
+ context.rectangle(self.selected.pos[0]-self.selected.svg.props.width/2-2, self.selected.pos[1]-self.selected.svg.props.height/2-2,
+ self.selected.svg.props.width+4,self.selected.svg.props.height+4)
+ context.fill()
+ for i in circuits:
+ i.draw(context)
+ for i in pressing_lights:
+ i.draw(context)
+ for i in non_pressing_lights:
+ i.draw(context)
+ context.set_font_size(20)
+ moused_over = False
+ context.set_source_rgb(0,0,0)
+ for i in circuits:
+ if is_over(pos,i) and not moused_over:
+ context.move_to(pos[0]+10,pos[1]-10)
+ context.show_text(i.name)
+ moused_over=True
+
+
+
+
+
+
+def save(name):
+ if name == "":
+ files = []
+ for i in os.listdir(os.path.join("saves", "")):
+ if ".lc" in i:
+ item = i.split(".lc")[0]
+ if "save" in item:
+ item = item.split("save")[1]
+ files.append(int(item))
+ try:
+ name = "save" + str(max(files) + 1)
+ except:
+ name = "save1"
+ open_file = open(os.path.join("saves", name + ".lc"), "w")
+ list1 = {}
+ for i in pressing_lights:
+ list1[i.pos[0]] = i.pos[1]
+ list2 = {}
+ for i in non_pressing_lights:
+ list2[i.pos[0]] = i.pos[1]
+ circuit_list = ""
+ for i in circuits:
+ circuit_list += str(i.pos[0]) + ":" + str(i.pos[1])
+ circuit_list += ":" + i.name
+ circuit_list += ","
+ input_connect = ""
+ for i in circuits:
+ for item in i.inputs:
+ input_connect += str(item.pos[0]) + ":" + \
+ str(item.pos[1])
+ input_connect += ";"
+ input_connect += str(i.pos[0])+":"+str(i.pos[1])
+ input_connect += ","
+ output_connect = ""
+ for i in circuits:
+ for item in i.outputs:
+ output_connect += str(item.pos[0]) + ":" + \
+ str(item.pos[1])
+ output_connect += ";"
+ output_connect += str(i.pos[0])+":"+str(i.pos[1])
+ output_connect += ","
+ open_file.write(str(list1) + "\n")
+ open_file.write(str(list2) + "\n")
+ open_file.write(circuit_list + "\n")
+ open_file.write(input_connect + "\n")
+ open_file.write(str(output_connect) + "\n")
+
+
+def load(name):
+ global circuits, pressing_lights, non_pressing_lights, input_or_output
+ try:
+ open_file = open(os.path.join(name), "r").readlines()
+ except:
+ return
+ circuits = []
+ pressing_lights = []
+ non_pressing_lights = []
+ for i in open_file[0][1:-2].split(","):
+ if i:
+ pressing_lights.append(Light((float(i.split(":")[0].strip()),
+ float(i.split(":")[1].strip()))))
+ for i in open_file[1][1:-2].split(","):
+ if i:
+ non_pressing_lights.append(Light((float(i.split(":")[0].strip()),
+ float(i.split(":")[1].strip()))))
+ for i in open_file[2].strip().split(","):
+ if i:
+ add_circuit((float(i.split(":")[0]), float(i.split(":")[1])),
+ i.split(":")[2])
+ input_or_output = "Input"
+ for l in open_file[3].split(","):
+ i = l.strip()
+ if i:
+ for item in pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in non_pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in circuits:
+ if item.pos == (float(i.split(";")[1].split(":")[0]),
+ float(i.split(";")[1].split(":")[1])):
+ circuit = item
+ connect(light, circuit)
+ input_or_output = "Output"
+ for l in open_file[4].split(","):
+ i = l.strip()
+ if i:
+ for item in pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in non_pressing_lights:
+ if item.pos == (float(i.split(";")[0].split(":")[0]),
+ float(i.split(";")[0].split(":")[1])):
+ light = item
+ for item in circuits:
+ if item.pos == (float(i.split(";")[1].split(":")[0]),
+ float(i.split(";")[1].split(":")[1])):
+ circuit = item
+ connect(light, circuit)
+ input_or_output = "Input"
+
diff --git a/MANIFEST~ b/MANIFEST~
new file mode 100755
index 0000000..9e5525d
--- /dev/null
+++ b/MANIFEST~
@@ -0,0 +1,11 @@
+GrapherActivity.py
+LogicCircuits.py
+saves/
+data/AND.svg
+data/greenlight.svg
+data/NOT.svg
+data/OR.svg
+data/redlight.svg
+data/XOR.svg
+activity/activity-grapher.svg
+activity/activity.info
diff --git a/activity/.logic-circuits.sugar.svg.swp b/activity/.logic-circuits.sugar.svg.swp
new file mode 100755
index 0000000..dbf37ed
--- /dev/null
+++ b/activity/.logic-circuits.sugar.svg.swp
Binary files differ
diff --git a/activity/.logic-circuits.svg.swo b/activity/.logic-circuits.svg.swo
new file mode 100755
index 0000000..fa518ea
--- /dev/null
+++ b/activity/.logic-circuits.svg.swo
Binary files differ
diff --git a/activity/.logic-circuits.svg.swp b/activity/.logic-circuits.svg.swp
new file mode 100755
index 0000000..506b4f5
--- /dev/null
+++ b/activity/.logic-circuits.svg.swp
Binary files differ
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100755
index 0000000..bc9e775
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,8 @@
+[Activity]
+name = Logic-Circuits
+bundle_id = org.laptop.LogicCircuitsActivity
+class = LogicCircuitsActivity.LogicCircuitsActivity
+icon = logic-circuits
+activity_version = 1
+host_version = 1
+show_launcher = yes
diff --git a/activity/activity.info~ b/activity/activity.info~
new file mode 100755
index 0000000..0933c99
--- /dev/null
+++ b/activity/activity.info~
@@ -0,0 +1,8 @@
+[Activity]
+name = Grapher-sugarized
+bundle_id = org.laptop.GrapherActivity-sugarized
+class = GrapherActivity-sugarized.GrapherActivity
+icon = activity-grapher
+activity_version = 1
+host_version = 1
+show_launcher = yes
diff --git a/activity/logic-circuits.sugar.svg b/activity/logic-circuits.sugar.svg
new file mode 100755
index 0000000..4098131
--- /dev/null
+++ b/activity/logic-circuits.sugar.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" ?><!-- Created with Inkscape (http://www.inkscape.org/) --><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#666666">
+ <!ENTITY fill_color "#ffffff">
+]><svg height="90" id="svg" style="" version="1.0" width="90" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
+ <path d="M 80,25 C 100,25 105,25 105,25" id="path3059" style="fill:&stroke_color;;stroke:&fill_color;;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 41,15 L 15,15" id="path3061" style="fill:&stroke_color;;stroke;;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 42,35 L 15,35" id="path3944" style="fill:&stroke_color;;stroke;;stroke-width:16;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 40,5 L 40,6.4285714 L 40,43.571429 L 40,45 L 41.428571,45 L 60.47619,45 C 71.744098,45 80.47619,35.999955 80.47619,25 C 80.47619,14.000045 71.744099,5.0000002 60.47619,5 C 60.47619,5 60.47619,5 41.428571,5 L 40,5 z M 42.857143,7.8571429 C 50.834264,7.8571429 55.918368,7.8571429 58.095238,7.8571429 C 59.285714,7.8571429 59.880952,7.8571429 60.178571,7.8571429 C 60.327381,7.8571429 60.409227,7.8571429 60.446429,7.8571429 C 60.465029,7.8571429 60.471543,7.8571429 60.47619,7.8571429 C 70.236853,7.857143 77.142857,15.497098 77.142857,25 C 77.142857,34.502902 69.760662,42.142857 60,42.142857 L 42.857143,42.142857 L 42.857143,7.8571429 z" id="path2884" style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:16;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" transform="translate(-15, 20)"/>
+</svg>
diff --git a/activity/logic-circuits.svg b/activity/logic-circuits.svg
new file mode 100755
index 0000000..b14eac2
--- /dev/null
+++ b/activity/logic-circuits.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" ?><!-- Created with Inkscape (http://www.inkscape.org/) --><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#666666">
+ <!ENTITY fill_color "#ffffff">
+]><svg height="90" id="svg" style="" version="1.0" width="90" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
+ <path d="M 80,25 C 100,25 105,25 105,25" id="path3059" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 41,15 L 15,15" id="path3061" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 42,35 L 15,35" id="path3944" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 40,5 L 40,6.4285714 L 40,43.571429 L 40,45 L 41.428571,45 L 60.47619,45 C 71.744098,45 80.47619,35.999955 80.47619,25 C 80.47619,14.000045 71.744099,5.0000002 60.47619,5 C 60.47619,5 60.47619,5 41.428571,5 L 40,5 z M 42.857143,7.8571429 C 50.834264,7.8571429 55.918368,7.8571429 58.095238,7.8571429 C 59.285714,7.8571429 59.880952,7.8571429 60.178571,7.8571429 C 60.327381,7.8571429 60.409227,7.8571429 60.446429,7.8571429 C 60.465029,7.8571429 60.471543,7.8571429 60.47619,7.8571429 C 70.236853,7.857143 77.142857,15.497098 77.142857,25 C 77.142857,34.502902 69.760662,42.142857 60,42.142857 L 42.857143,42.142857 L 42.857143,7.8571429 z" id="path2884" style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" transform="translate(-15, 20)"/>
+</svg>
diff --git a/activity/logic-circuits.svg~ b/activity/logic-circuits.svg~
new file mode 100755
index 0000000..743e68f
--- /dev/null
+++ b/activity/logic-circuits.svg~
@@ -0,0 +1,9 @@
+<?xml version="1.0" ?><!-- Created with Inkscape (http://www.inkscape.org/) --><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#666666">
+ <!ENTITY fill_color "#ffffff">
+]><svg height="90" id="svg" style="" version="1.0" width="90" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
+ <path d="M 80,25 C 100,25 105,25 105,25" id="path3059" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 41,15 L 15,15" id="path3061" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 42,35 L 15,35" id="path3944" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" transform="translate(-15, 20)"/>
+ <path d="M 40,5 L 40,6.4285714 L 40,43.571429 L 40,45 L 41.428571,45 L 60.47619,45 C 71.744098,45 80.47619,35.999955 80.47619,25 C 80.47619,14.000045 71.744099,5.0000002 60.47619,5 C 60.47619,5 60.47619,5 41.428571,5 L 40,5 z M 42.857143,7.8571429 C 50.834264,7.8571429 55.918368,7.8571429 58.095238,7.8571429 C 59.285714,7.8571429 59.880952,7.8571429 60.178571,7.8571429 C 60.327381,7.8571429 60.409227,7.8571429 60.446429,7.8571429 C 60.465029,7.8571429 60.471543,7.8571429 60.47619,7.8571429 C 70.236853,7.857143 77.142857,15.497098 77.142857,25 C 77.142857,34.502902 69.760662,42.142857 60,42.142857 L 42.857143,42.142857 L 42.857143,7.8571429 z" id="path2884" style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" transform="translate(-15, 20)"/>
+</svg>
diff --git a/data/AND.svg b/data/AND.svg
new file mode 100755
index 0000000..9e3967d
--- /dev/null
+++ b/data/AND.svg
@@ -0,0 +1,29 @@
+<?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="100" height="50" id="svg2" sodipodi:version="0.32" inkscape:version="0.46" version="1.0" sodipodi:docname="AND ANSI.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs id="defs4">
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 15 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="50 : 15 : 1" inkscape:persp3d-origin="25 : 10 : 1" id="perspective2714"/>
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="1 : 0.5 : 1" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" id="perspective2806"/>
+ <inkscape:perspective id="perspective2819" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective2777" inkscape:persp3d-origin="75 : 40 : 1" inkscape:vp_z="150 : 60 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 60 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective3275" inkscape:persp3d-origin="50 : 33.333333 : 1" inkscape:vp_z="100 : 50 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 50 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective5533" inkscape:persp3d-origin="32 : 21.333333 : 1" inkscape:vp_z="64 : 32 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 32 : 1" sodipodi:type="inkscape:persp3d"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="8" inkscape:cx="56.698348" inkscape:cy="25.326899" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:grid-points="true" gridtolerance="10000" inkscape:window-width="1399" inkscape:window-height="874" inkscape:window-x="33" inkscape:window-y="0" inkscape:snap-bbox="true">
+ <inkscape:grid id="GridFromPre046Settings" type="xygrid" originx="0px" originy="0px" spacingx="1px" spacingy="1px" color="#0000ff" empcolor="#0000ff" opacity="0.2" empopacity="0.4" empspacing="5" visible="true" enabled="true"/>
+ </sodipodi:namedview>
+ <metadata id="metadata7">
+ <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">
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="m 70,25 c 20,0 25,0 25,0" id="path3059" sodipodi:nodetypes="cc"/>
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 31,15 5,15" id="path3061"/>
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 32,35 5,35" id="path3944"/>
+ <path style="overflow: visible; marker: none; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; text-indent: 0pt; text-align: start; text-decoration: none; line-height: normal; letter-spacing: normal; word-spacing: normal; text-transform: none; direction: ltr; text-anchor: start; fill: rgb(0, 0, 0); fill-opacity: 1; stroke: none; stroke-width: 3; visibility: visible; display: inline; font-family: Bitstream Vera Sans;" d="M 30,5 L 30,6.4285714 L 30,43.571429 L 30,45 L 31.428571,45 L 50.47619,45 C 61.744098,45 70.47619,35.999955 70.47619,25 C 70.47619,14.000045 61.744099,5.0000002 50.47619,5 C 50.47619,5 50.47619,5 31.428571,5 L 30,5 z M 32.857143,7.8571429 C 40.834264,7.8571429 45.918368,7.8571429 48.095238,7.8571429 C 49.285714,7.8571429 49.880952,7.8571429 50.178571,7.8571429 C 50.327381,7.8571429 50.409227,7.8571429 50.446429,7.8571429 C 50.465029,7.8571429 50.471543,7.8571429 50.47619,7.8571429 C 60.236853,7.857143 67.142857,15.497098 67.142857,25 C 67.142857,34.502902 59.760662,42.142857 50,42.142857 L 32.857143,42.142857 L 32.857143,7.8571429 z" id="path2884" sodipodi:nodetypes="ccccccsccccsssssccc"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/data/NOT.svg b/data/NOT.svg
new file mode 100755
index 0000000..f11beae
--- /dev/null
+++ b/data/NOT.svg
@@ -0,0 +1,30 @@
+<?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="100" height="50" id="svg2" sodipodi:version="0.32" inkscape:version="0.46" version="1.0" sodipodi:docname="NOT ANSI.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs id="defs4">
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 15 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="50 : 15 : 1" inkscape:persp3d-origin="25 : 10 : 1" id="perspective2714"/>
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="1 : 0.5 : 1" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" id="perspective2806"/>
+ <inkscape:perspective id="perspective2819" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective2777" inkscape:persp3d-origin="75 : 40 : 1" inkscape:vp_z="150 : 60 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 60 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective3275" inkscape:persp3d-origin="50 : 33.333333 : 1" inkscape:vp_z="100 : 50 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 50 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective5533" inkscape:persp3d-origin="32 : 21.333333 : 1" inkscape:vp_z="64 : 32 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 32 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective2557" inkscape:persp3d-origin="25 : 16.666667 : 1" inkscape:vp_z="50 : 25 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 25 : 1" sodipodi:type="inkscape:persp3d"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="8" inkscape:cx="84.685352" inkscape:cy="15.288628" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:grid-points="true" gridtolerance="10000" inkscape:window-width="1399" inkscape:window-height="874" inkscape:window-x="33" inkscape:window-y="0" inkscape:snap-bbox="true">
+ <inkscape:grid id="GridFromPre046Settings" type="xygrid" originx="0px" originy="0px" spacingx="1px" spacingy="1px" color="#0000ff" empcolor="#0000ff" opacity="0.2" empopacity="0.4" empspacing="5" visible="true" enabled="true"/>
+ </sodipodi:namedview>
+ <metadata id="metadata7">
+ <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">
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 79.15691,25 L 95,25" id="path3059" sodipodi:nodetypes="cc"/>
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 29.043478,25 L 5.0434781,25" id="path3061"/>
+ <path style="overflow: visible; marker: none; fill: rgb(0, 0, 0); fill-opacity: 1; stroke: none; stroke-width: 3; stroke-linejoin: miter; stroke-opacity: 1; visibility: visible; display: inline;" d="M 28.96875,2.59375 L 28.96875,5 L 28.96875,45 L 28.96875,47.40625 L 31.125,46.34375 L 72.15625,26.34375 L 72.15625,23.65625 L 31.125,3.65625 L 28.96875,2.59375 z M 31.96875,7.40625 L 68.09375,25 L 31.96875,42.59375 L 31.96875,7.40625 z" id="path2638" sodipodi:nodetypes="ccccccccccccc"/>
+ <path sodipodi:type="arc" style="overflow: visible; marker: none; fill: none; fill-opacity: 1; stroke: rgb(0, 0, 0); stroke-width: 3; stroke-linejoin: miter; stroke-opacity: 1; visibility: visible; display: inline;" id="path2671" sodipodi:cx="76" sodipodi:cy="25" sodipodi:rx="4" sodipodi:ry="4" d="M 80,25 A 4,4 0 1 1 72,25 A 4,4 0 1 1 80,25 z" transform="translate(-1)"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/data/OR.svg b/data/OR.svg
new file mode 100755
index 0000000..829310a
--- /dev/null
+++ b/data/OR.svg
@@ -0,0 +1,32 @@
+<?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="100" height="50" id="svg2" sodipodi:version="0.32" inkscape:version="0.46" version="1.0" sodipodi:docname="OR ANSI.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs id="defs4">
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 15 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="50 : 15 : 1" inkscape:persp3d-origin="25 : 10 : 1" id="perspective2714"/>
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="1 : 0.5 : 1" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" id="perspective2806"/>
+ <inkscape:perspective id="perspective2819" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective2777" inkscape:persp3d-origin="75 : 40 : 1" inkscape:vp_z="150 : 60 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 60 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective3275" inkscape:persp3d-origin="50 : 33.333333 : 1" inkscape:vp_z="100 : 50 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 50 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective5533" inkscape:persp3d-origin="32 : 21.333333 : 1" inkscape:vp_z="64 : 32 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 32 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective2557" inkscape:persp3d-origin="25 : 16.666667 : 1" inkscape:vp_z="50 : 25 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 25 : 1" sodipodi:type="inkscape:persp3d"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="4" inkscape:cx="113.00039" inkscape:cy="12.893731" inkscape:document-units="px" inkscape:current-layer="g2560" showgrid="false" inkscape:grid-bbox="true" inkscape:grid-points="true" gridtolerance="10000" inkscape:window-width="1399" inkscape:window-height="874" inkscape:window-x="37" inkscape:window-y="-4" inkscape:snap-bbox="true">
+ <inkscape:grid id="GridFromPre046Settings" type="xygrid" originx="0px" originy="0px" spacingx="1px" spacingy="1px" color="#0000ff" empcolor="#0000ff" opacity="0.2" empopacity="0.4" empspacing="5" visible="true" enabled="true"/>
+ </sodipodi:namedview>
+ <metadata id="metadata7">
+ <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">
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="m 70,25 c 20,0 25,0 25,0" id="path3059" sodipodi:nodetypes="cc"/>
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 31,15 5,15" id="path3061"/>
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 32,35 5,35" id="path3944"/>
+ <g id="g2560" inkscape:label="Layer 1" transform="translate(26.5, -39.5)">
+ <path style="fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: evenodd; stroke: none; stroke-width: 3; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M -2.40625,44.5 L -0.40625,46.9375 C -0.40625,46.9375 5.25,53.937549 5.25,64.5 C 5.25,75.062451 -0.40625,82.0625 -0.40625,82.0625 L -2.40625,84.5 L 0.75,84.5 L 14.75,84.5 C 17.158076,84.500001 22.439699,84.524514 28.375,82.09375 C 34.310301,79.662986 40.911536,74.750484 46.0625,65.21875 L 44.75,64.5 L 46.0625,63.78125 C 35.759387,44.71559 19.506574,44.5 14.75,44.5 L 0.75,44.5 L -2.40625,44.5 z M 3.46875,47.5 L 14.75,47.5 C 19.434173,47.5 33.03685,47.369793 42.71875,64.5 C 37.951964,72.929075 32.197469,77.18391 27,79.3125 C 21.639339,81.507924 17.158075,81.500001 14.75,81.5 L 3.5,81.5 C 5.3735884,78.391566 8.25,72.45065 8.25,64.5 C 8.25,56.526646 5.3414686,50.599815 3.46875,47.5 z" id="path4973" sodipodi:nodetypes="ccsccccscccccccccsccsc"/>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/data/XOR.svg b/data/XOR.svg
new file mode 100755
index 0000000..b07a88b
--- /dev/null
+++ b/data/XOR.svg
@@ -0,0 +1,33 @@
+<?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="100" height="50" id="svg2" sodipodi:version="0.32" inkscape:version="0.46" version="1.0" sodipodi:docname="XOR ANSI.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs id="defs4">
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 15 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="50 : 15 : 1" inkscape:persp3d-origin="25 : 10 : 1" id="perspective2714"/>
+ <inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="1 : 0.5 : 1" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" id="perspective2806"/>
+ <inkscape:perspective id="perspective2819" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:vp_z="744.09448 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective2777" inkscape:persp3d-origin="75 : 40 : 1" inkscape:vp_z="150 : 60 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 60 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective3275" inkscape:persp3d-origin="50 : 33.333333 : 1" inkscape:vp_z="100 : 50 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 50 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective5533" inkscape:persp3d-origin="32 : 21.333333 : 1" inkscape:vp_z="64 : 32 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 32 : 1" sodipodi:type="inkscape:persp3d"/>
+ <inkscape:perspective id="perspective2557" inkscape:persp3d-origin="25 : 16.666667 : 1" inkscape:vp_z="50 : 25 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 25 : 1" sodipodi:type="inkscape:persp3d"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="5.6568542" inkscape:cx="25.938116" inkscape:cy="17.23005" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:grid-points="true" gridtolerance="10000" inkscape:window-width="1399" inkscape:window-height="874" inkscape:window-x="33" inkscape:window-y="0" inkscape:snap-bbox="true">
+ <inkscape:grid id="GridFromPre046Settings" type="xygrid" originx="0px" originy="0px" spacingx="1px" spacingy="1px" color="#0000ff" empcolor="#0000ff" opacity="0.2" empopacity="0.4" empspacing="5" visible="true" enabled="true"/>
+ </sodipodi:namedview>
+ <metadata id="metadata7">
+ <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">
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="m 70,25 c 20,0 25,0 25,0" id="path3059" sodipodi:nodetypes="cc"/>
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 30.385717,15 L 4.9999998,15" id="path3061"/>
+ <path style="fill: none; stroke: rgb(0, 0, 0); stroke-width: 2; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M 31.362091,35 L 4.9999998,35" id="path3944"/>
+ <g id="g2560" inkscape:label="Layer 1" transform="translate(26.5, -39.5)">
+ <path id="path3516" style="fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: evenodd; stroke: none; stroke-width: 3; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M -2.25,81.500005 C -3.847374,84.144405 -4.5,84.500005 -4.5,84.500005 L -8.15625,84.500005 L -6.15625,82.062505 C -6.15625,82.062505 -0.5,75.062451 -0.5,64.5 C -0.5,53.937549 -6.15625,46.9375 -6.15625,46.9375 L -8.15625,44.5 L -4.5,44.5 C -3.71875,45.4375 -3.078125,46.15625 -2.28125,47.5 C -0.408531,50.599815 2.5,56.526646 2.5,64.5 C 2.5,72.45065 -0.396697,78.379425 -2.25,81.500005 z" sodipodi:nodetypes="ccccsccccsc"/>
+ <path style="fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: evenodd; stroke: none; stroke-width: 3; stroke-linecap: butt; stroke-linejoin: miter; stroke-opacity: 1;" d="M -2.40625,44.5 L -0.40625,46.9375 C -0.40625,46.9375 5.25,53.937549 5.25,64.5 C 5.25,75.062451 -0.40625,82.0625 -0.40625,82.0625 L -2.40625,84.5 L 0.75,84.5 L 14.75,84.5 C 17.158076,84.500001 22.439699,84.524514 28.375,82.09375 C 34.310301,79.662986 40.911536,74.750484 46.0625,65.21875 L 44.75,64.5 L 46.0625,63.78125 C 35.759387,44.71559 19.506574,44.5 14.75,44.5 L 0.75,44.5 L -2.40625,44.5 z M 3.46875,47.5 L 14.75,47.5 C 19.434173,47.5 33.03685,47.369793 42.71875,64.5 C 37.951964,72.929075 32.197469,77.18391 27,79.3125 C 21.639339,81.507924 17.158075,81.500001 14.75,81.5 L 3.5,81.5 C 5.3735884,78.391566 8.25,72.45065 8.25,64.5 C 8.25,56.526646 5.3414686,50.599815 3.46875,47.5 z" id="path4973" sodipodi:nodetypes="ccsccccscccccccccsccsc"/>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/data/greenlight.svg b/data/greenlight.svg
new file mode 100755
index 0000000..5477eb9
--- /dev/null
+++ b/data/greenlight.svg
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="20px"
+ height="20px"
+ viewBox="0 0 20 20"
+ id="svg3231">
+ <defs
+ id="defs2485">
+ <linearGradient
+ id="linearGradient3261">
+ <stop
+ id="stop3263"
+ style="stop-color:#a5ff28;stop-opacity:0.62068963"
+ offset="0" />
+ <stop
+ id="stop3265"
+ style="stop-color:#28c228;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="4"
+ cy="0"
+ r="9"
+ fx="0"
+ fy="0"
+ id="radialGradient3271"
+ xlink:href="#linearGradient3261"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <circle
+ cx="10"
+ cy="10"
+ r="9"
+ style="fill:#FFF;" />
+ <circle
+ cx="0"
+ cy="0"
+ r="9"
+ transform="translate(10,10)"
+ id="circle2482"
+ style="fill:url(#radialGradient3271);fill-opacity:1;fill-rule:evenodd" />
+</svg>
diff --git a/data/redlight.svg b/data/redlight.svg
new file mode 100755
index 0000000..af2bdd2
--- /dev/null
+++ b/data/redlight.svg
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.0"
+ width="20px"
+ height="20px"
+ viewBox="0 0 20 20"
+ id="svg3231">
+ <defs
+ id="defs2485">
+ <linearGradient
+ id="linearGradient3261">
+ <stop
+ id="stop3263"
+ style="stop-color:#ff3b3b;stop-opacity:0.20689656"
+ offset="0" />
+ <stop
+ id="stop3265"
+ style="stop-color:#de2828;stop-opacity:1"
+ offset="1" />
+ </linearGradient>
+ <radialGradient
+ cx="4"
+ cy="0"
+ r="9"
+ fx="0"
+ fy="0"
+ id="radialGradient3271"
+ xlink:href="#linearGradient3261"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <circle
+ cx="10"
+ cy="10"
+ r="9"
+ style="fill:#FFF;" />
+ <circle
+ cx="0"
+ cy="0"
+ r="9"
+ transform="translate(10, 10)"
+ id="circle2482"
+ style="fill:url(#radialGradient3271);fill-opacity:1;fill-rule:evenodd" />
+</svg>
diff --git a/manifest b/manifest
new file mode 100755
index 0000000..9e5525d
--- /dev/null
+++ b/manifest
@@ -0,0 +1,11 @@
+GrapherActivity.py
+LogicCircuits.py
+saves/
+data/AND.svg
+data/greenlight.svg
+data/NOT.svg
+data/OR.svg
+data/redlight.svg
+data/XOR.svg
+activity/activity-grapher.svg
+activity/activity.info
diff --git a/saves/save1.lc b/saves/save1.lc
new file mode 100755
index 0000000..c532f28
--- /dev/null
+++ b/saves/save1.lc
@@ -0,0 +1,5 @@
+{372.0: 312.0, 365.0: 170.0, 366.0: 357.0, 367.0: 245.0}
+{587.0: 205.0}
+485.0:211.0:and,469.0:321.0:xor,
+365.0:170.0;485.0:211.0,367.0:245.0;485.0:211.0,372.0:312.0;469.0:321.0,366.0:357.0;469.0:321.0,
+587.0:205.0;485.0:211.0,
diff --git a/saves/save2.lc b/saves/save2.lc
new file mode 100755
index 0000000..c532f28
--- /dev/null
+++ b/saves/save2.lc
@@ -0,0 +1,5 @@
+{372.0: 312.0, 365.0: 170.0, 366.0: 357.0, 367.0: 245.0}
+{587.0: 205.0}
+485.0:211.0:and,469.0:321.0:xor,
+365.0:170.0;485.0:211.0,367.0:245.0;485.0:211.0,372.0:312.0;469.0:321.0,366.0:357.0;469.0:321.0,
+587.0:205.0;485.0:211.0,
diff --git a/saves/save3.lc b/saves/save3.lc
new file mode 100755
index 0000000..eec9e44
--- /dev/null
+++ b/saves/save3.lc
@@ -0,0 +1,5 @@
+{320.0: 144.0, 321.0: 169.0, 164.0: 488.0, 612.0: 100.0, 521.0: 475.0, 618.0: 169.0, 620.0: 211.0, 621.0: 236.0, 49.0: 72.0, 53.0: 100.0, 56.0: 150.0, 57.0: 179.0, 58.0: 239.0, 314.0: 57.0, 319.0: 82.0}
+{774.0: 84.0, 198.0: 228.0, 201.0: 84.0, 778.0: 161.0, 683.0: 482.0, 467.0: 158.0, 468.0: 224.0, 214.0: 166.0, 475.0: 75.0, 298.0: 483.0}
+120.0:86.0:and,139.0:165.0:xor,134.0:228.0:or,390.0:77.0:and,391.0:156.0:or,396.0:224.0:xor,707.0:226.0:xor,707.0:163.0:or,706.0:90.0:and,238.0:485.0:not,600.0:482.0:not,
+49.0:72.0;120.0:86.0,53.0:100.0;120.0:86.0,56.0:150.0;139.0:165.0,57.0:179.0;139.0:165.0,58.0:217.0;134.0:228.0,58.0:239.0;134.0:228.0,314.0:57.0;390.0:77.0,319.0:82.0;390.0:77.0,320.0:144.0;391.0:156.0,321.0:169.0;391.0:156.0,321.0:211.0;396.0:224.0,319.0:236.0;396.0:224.0,620.0:211.0;707.0:226.0,621.0:236.0;707.0:226.0,621.0:145.0;707.0:163.0,618.0:169.0;707.0:163.0,618.0:77.0;706.0:90.0,612.0:100.0;706.0:90.0,164.0:488.0;238.0:485.0,521.0:475.0;600.0:482.0,
+201.0:84.0;120.0:86.0,214.0:166.0;139.0:165.0,198.0:228.0;134.0:228.0,475.0:75.0;390.0:77.0,467.0:158.0;391.0:156.0,468.0:224.0;396.0:224.0,774.0:224.0;707.0:226.0,778.0:161.0;707.0:163.0,774.0:84.0;706.0:90.0,298.0:483.0;238.0:485.0,683.0:482.0;600.0:482.0,
diff --git a/saves/save4.lc b/saves/save4.lc
new file mode 100755
index 0000000..f144492
--- /dev/null
+++ b/saves/save4.lc
@@ -0,0 +1,5 @@
+{320.0: 144.0, 321.0: 237.0, 164.0: 488.0, 613.0: 137.0, 521.0: 475.0, 618.0: 169.0, 620.0: 211.0, 621.0: 236.0, 49.0: 72.0, 318.0: 211.0, 53.0: 211.0, 57.0: 178.0, 56.0: 150.0, 612.0: 100.0, 58.0: 239.0, 314.0: 57.0, 608.0: 71.0, 319.0: 82.0}
+{774.0: 84.0, 198.0: 228.0, 201.0: 84.0, 778.0: 161.0, 683.0: 482.0, 782.0: 224.0, 467.0: 158.0, 468.0: 224.0, 214.0: 166.0, 475.0: 75.0, 298.0: 483.0}
+120.0:86.0:and,139.0:165.0:xor,134.0:228.0:or,390.0:77.0:and,391.0:156.0:or,396.0:224.0:xor,707.0:226.0:xor,707.0:163.0:or,706.0:90.0:and,238.0:485.0:not,600.0:482.0:not,
+49.0:72.0;120.0:86.0,53.0:100.0;120.0:86.0,56.0:150.0;139.0:165.0,57.0:178.0;139.0:165.0,53.0:211.0;134.0:228.0,58.0:239.0;134.0:228.0,314.0:57.0;390.0:77.0,319.0:82.0;390.0:77.0,320.0:144.0;391.0:156.0,321.0:169.0;391.0:156.0,318.0:211.0;396.0:224.0,321.0:237.0;396.0:224.0,620.0:211.0;707.0:226.0,621.0:236.0;707.0:226.0,613.0:137.0;707.0:163.0,618.0:169.0;707.0:163.0,608.0:71.0;706.0:90.0,612.0:100.0;706.0:90.0,164.0:488.0;238.0:485.0,521.0:475.0;600.0:482.0,
+201.0:84.0;120.0:86.0,214.0:166.0;139.0:165.0,198.0:228.0;134.0:228.0,475.0:75.0;390.0:77.0,467.0:158.0;391.0:156.0,468.0:224.0;396.0:224.0,782.0:224.0;707.0:226.0,778.0:161.0;707.0:163.0,774.0:84.0;706.0:90.0,298.0:483.0;238.0:485.0,683.0:482.0;600.0:482.0,
diff --git a/saves/save5.lc b/saves/save5.lc
new file mode 100755
index 0000000..65657a4
--- /dev/null
+++ b/saves/save5.lc
@@ -0,0 +1,5 @@
+{320.0: 144.0, 321.0: 237.0, 164.0: 488.0, 613.0: 137.0, 521.0: 475.0, 618.0: 169.0, 620.0: 211.0, 621.0: 236.0, 49.0: 72.0, 53.0: 211.0, 612.0: 100.0, 608.0: 71.0, 56.0: 150.0, 57.0: 178.0, 58.0: 239.0, 314.0: 57.0, 318.0: 211.0, 319.0: 82.0}
+{774.0: 84.0, 198.0: 228.0, 201.0: 84.0, 778.0: 161.0, 683.0: 482.0, 782.0: 224.0, 467.0: 158.0, 468.0: 224.0, 214.0: 166.0, 475.0: 75.0, 298.0: 483.0}
+120.0:86.0:and,139.0:165.0:xor,134.0:228.0:or,390.0:77.0:and,391.0:156.0:or,396.0:224.0:xor,707.0:226.0:xor,707.0:163.0:or,706.0:90.0:and,238.0:485.0:not,600.0:482.0:not,
+49.0:72.0;120.0:86.0,56.0:150.0;139.0:165.0,57.0:178.0;139.0:165.0,53.0:211.0;134.0:228.0,58.0:239.0;134.0:228.0,314.0:57.0;390.0:77.0,319.0:82.0;390.0:77.0,320.0:144.0;391.0:156.0,318.0:211.0;396.0:224.0,321.0:237.0;396.0:224.0,620.0:211.0;707.0:226.0,621.0:236.0;707.0:226.0,613.0:137.0;707.0:163.0,618.0:169.0;707.0:163.0,608.0:71.0;706.0:90.0,612.0:100.0;706.0:90.0,164.0:488.0;238.0:485.0,521.0:475.0;600.0:482.0,
+201.0:84.0;120.0:86.0,214.0:166.0;139.0:165.0,198.0:228.0;134.0:228.0,475.0:75.0;390.0:77.0,467.0:158.0;391.0:156.0,468.0:224.0;396.0:224.0,782.0:224.0;707.0:226.0,778.0:161.0;707.0:163.0,774.0:84.0;706.0:90.0,298.0:483.0;238.0:485.0,683.0:482.0;600.0:482.0,
diff --git a/saves/save6.lc b/saves/save6.lc
new file mode 100755
index 0000000..f026c8d
--- /dev/null
+++ b/saves/save6.lc
@@ -0,0 +1,5 @@
+{320.0: 144.0, 321.0: 237.0, 164.0: 488.0, 613.0: 137.0, 521.0: 475.0, 618.0: 169.0, 620.0: 211.0, 621.0: 236.0, 49.0: 97.0, 318.0: 164.0, 53.0: 211.0, 57.0: 178.0, 56.0: 150.0, 612.0: 100.0, 58.0: 239.0, 314.0: 57.0, 608.0: 71.0, 319.0: 82.0}
+{774.0: 84.0, 198.0: 228.0, 201.0: 84.0, 778.0: 161.0, 683.0: 482.0, 782.0: 224.0, 467.0: 158.0, 468.0: 224.0, 214.0: 166.0, 475.0: 75.0, 298.0: 483.0}
+120.0:86.0:and,139.0:165.0:xor,134.0:228.0:or,390.0:77.0:and,391.0:156.0:or,396.0:224.0:xor,707.0:226.0:xor,707.0:163.0:or,706.0:90.0:and,238.0:485.0:not,600.0:482.0:not,
+49.0:72.0;120.0:86.0,49.0:97.0;120.0:86.0,56.0:150.0;139.0:165.0,57.0:178.0;139.0:165.0,53.0:211.0;134.0:228.0,58.0:239.0;134.0:228.0,314.0:57.0;390.0:77.0,319.0:82.0;390.0:77.0,320.0:144.0;391.0:156.0,318.0:164.0;391.0:156.0,318.0:211.0;396.0:224.0,321.0:237.0;396.0:224.0,620.0:211.0;707.0:226.0,621.0:236.0;707.0:226.0,613.0:137.0;707.0:163.0,618.0:169.0;707.0:163.0,608.0:71.0;706.0:90.0,612.0:100.0;706.0:90.0,164.0:488.0;238.0:485.0,521.0:475.0;600.0:482.0,
+201.0:84.0;120.0:86.0,214.0:166.0;139.0:165.0,198.0:228.0;134.0:228.0,475.0:75.0;390.0:77.0,467.0:158.0;391.0:156.0,468.0:224.0;396.0:224.0,782.0:224.0;707.0:226.0,778.0:161.0;707.0:163.0,774.0:84.0;706.0:90.0,298.0:483.0;238.0:485.0,683.0:482.0;600.0:482.0,
diff --git a/saves/save7.lc b/saves/save7.lc
new file mode 100755
index 0000000..3561aa7
--- /dev/null
+++ b/saves/save7.lc
@@ -0,0 +1,5 @@
+{320.0: 144.0, 321.0: 237.0, 164.0: 488.0, 613.0: 137.0, 521.0: 475.0, 618.0: 169.0, 620.0: 211.0, 621.0: 236.0, 49.0: 97.0, 53.0: 211.0, 612.0: 100.0, 608.0: 71.0, 56.0: 150.0, 57.0: 178.0, 58.0: 239.0, 314.0: 57.0, 318.0: 164.0, 319.0: 82.0}
+{774.0: 84.0, 198.0: 228.0, 201.0: 84.0, 778.0: 161.0, 683.0: 482.0, 782.0: 224.0, 467.0: 158.0, 468.0: 224.0, 214.0: 166.0, 475.0: 75.0, 298.0: 483.0}
+120.0:86.0:and,139.0:165.0:xor,134.0:228.0:or,390.0:77.0:and,391.0:156.0:or,396.0:224.0:xor,707.0:226.0:xor,707.0:163.0:or,706.0:90.0:and,238.0:485.0:not,600.0:482.0:not,
+
+
diff --git a/saves/save8.lc b/saves/save8.lc
new file mode 100755
index 0000000..acbc961
--- /dev/null
+++ b/saves/save8.lc
@@ -0,0 +1,5 @@
+{128.0: 493.0, 261.0: 339.0, 390.0: 525.0, 7.0: 314.0, 393.0: 564.0, 11.0: 261.0, 534.0: 429.0, 535.0: 473.0, 177.0: 153.0, 183.0: 93.0, 696.0: 624.0, 710.0: 659.0, 119.0: 527.0, 722.0: 135.0, 212.0: 579.0, 726.0: 170.0, 220.0: 626.0, 734.0: 369.0, 225.0: 228.0, 370.0: 297.0, 759.0: 406.0, 255.0: 370.0}
+{521.0: 277.0, 369.0: 244.0}
+448.0:273.0:and,297.0:233.0:not,215.0:511.0:and,511.0:553.0:and,650.0:449.0:and,844.0:385.0:and,781.0:639.0:and,354.0:357.0:and,326.0:608.0:and,87.0:282.0:and,284.0:137.0:and,802.0:157.0:and,
+369.0:244.0;448.0:273.0,370.0:297.0;448.0:273.0,225.0:228.0;297.0:233.0,128.0:493.0;215.0:511.0,119.0:527.0;215.0:511.0,390.0:525.0;511.0:553.0,393.0:564.0;511.0:553.0,534.0:429.0;650.0:449.0,535.0:473.0;650.0:449.0,734.0:369.0;844.0:385.0,759.0:406.0;844.0:385.0,696.0:624.0;781.0:639.0,710.0:659.0;781.0:639.0,261.0:339.0;354.0:357.0,255.0:370.0;354.0:357.0,212.0:579.0;326.0:608.0,220.0:626.0;326.0:608.0,11.0:261.0;87.0:282.0,7.0:314.0;87.0:282.0,183.0:93.0;284.0:137.0,177.0:153.0;284.0:137.0,722.0:135.0;802.0:157.0,726.0:170.0;802.0:157.0,
+521.0:277.0;448.0:273.0,369.0:244.0;297.0:233.0,
diff --git a/saves/save9.lc b/saves/save9.lc
new file mode 100755
index 0000000..6e6aed5
--- /dev/null
+++ b/saves/save9.lc
@@ -0,0 +1,5 @@
+{128.0: 493.0, 261.0: 339.0, 390.0: 525.0, 7.0: 314.0, 393.0: 564.0, 11.0: 261.0, 534.0: 429.0, 535.0: 473.0, 177.0: 153.0, 183.0: 93.0, 696.0: 624.0, 710.0: 659.0, 119.0: 527.0, 722.0: 135.0, 212.0: 579.0, 726.0: 170.0, 220.0: 626.0, 734.0: 369.0, 225.0: 228.0, 370.0: 297.0, 759.0: 406.0, 255.0: 370.0}
+{449.0: 353.0, 771.0: 444.0, 401.0: 610.0, 521.0: 277.0, 856.0: 641.0, 369.0: 244.0, 931.0: 393.0, 597.0: 554.0, 278.0: 511.0, 888.0: 151.0, 153.0: 286.0, 350.0: 144.0}
+448.0:273.0:and,297.0:233.0:not,215.0:511.0:and,511.0:553.0:and,650.0:449.0:and,844.0:385.0:and,781.0:639.0:and,354.0:357.0:and,326.0:608.0:and,87.0:282.0:and,284.0:137.0:and,802.0:157.0:and,
+369.0:244.0;448.0:273.0,370.0:297.0;448.0:273.0,225.0:228.0;297.0:233.0,128.0:493.0;215.0:511.0,119.0:527.0;215.0:511.0,390.0:525.0;511.0:553.0,393.0:564.0;511.0:553.0,534.0:429.0;650.0:449.0,535.0:473.0;650.0:449.0,734.0:369.0;844.0:385.0,759.0:406.0;844.0:385.0,696.0:624.0;781.0:639.0,710.0:659.0;781.0:639.0,261.0:339.0;354.0:357.0,255.0:370.0;354.0:357.0,212.0:579.0;326.0:608.0,220.0:626.0;326.0:608.0,11.0:261.0;87.0:282.0,7.0:314.0;87.0:282.0,183.0:93.0;284.0:137.0,177.0:153.0;284.0:137.0,722.0:135.0;802.0:157.0,726.0:170.0;802.0:157.0,
+521.0:277.0;448.0:273.0,369.0:244.0;297.0:233.0,278.0:511.0;215.0:511.0,597.0:554.0;511.0:553.0,771.0:444.0;650.0:449.0,931.0:393.0;844.0:385.0,856.0:641.0;781.0:639.0,449.0:353.0;354.0:357.0,401.0:610.0;326.0:608.0,153.0:286.0;87.0:282.0,350.0:144.0;284.0:137.0,888.0:151.0;802.0:157.0,
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..6ed89aa
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+bundlebuilder.start()
+