element, tag would be "div".
+ data is a dictionary containing attributes of the tag. For
+ example: htmlobj("div", {"width":120, "id":"div10}) creates:
+
+ style is a dictionary of css style attributes to be applied. For
+ example: htmlobj("div", {}, {"float":"left","width":"200"})
+ creates:
+ To access the HTML representation of an instance, call str() or the
+ built-in html() method.
+ """
+ def __init__(self,tag,data={},style={}):
+ self.tag = tag
+ self.data = data
+ self.style = style
+ self.contents = []
+ def __str__(self):
+ retval = "<"+self.tag
+ for i in self.data:
+ retval+=" "+i+"="+str(self.data[i])
+ if self.style:
+ retval+=" style='"
+ for i in self.style:
+ retval+=i+":"+str(self.style[i])+";"
+ retval+="'"
+ retval+=">"+"".join((str(i) for i in self.contents))+""+self.tag+">\n"
+ return retval
+ def add(self, item):
+ self.contents.append(item)
+ def html(self):
+ return str(self)
+
+class Window:
+ def __init__(self, title=""):
+ __windowlist__.append(self)
+ if SYSTEM=="gtk":
+ self.window = gtk.Window()
+ self.vbox = gtk.VBox()
+ self.window.add(self.vbox)
+ self.window.show_all()
+ self.window.connect("destroy",self.destroy)
+ elif SYSTEM=="osx":
+ self.window = OSXWindow(width=1024,height=500)
+ #components = [i._int() for i in args]
+ #self.vbox = GUI.Column(components, equalize="w", expand=0)
+ #self.window.place(self.vbox, left = 0, top = 0, right = 0, bottom = 0, sticky = 'nsew')
+ self.window.show()
+ elif SYSTEM=="html":
+ self.window = htmlobj("div")
+
+ def add(self, obj,expand=False):
+ objint = obj._int() #Internal representation
+ if SYSTEM=="gtk":
+ self.vbox.pack_start(objint, expand, True, 0)
+ self.window.show_all()
+ elif SYSTEM=="osx":
+ self.window.place(objint, left=0, top=0, right=0, bottom=0, sticky="nsew")
+ elif SYSTEM=="html":
+ objint.data["width"] = "100%"
+ objint.data["height"] = "100%"
+ self.window.add(objint)
+ def destroy(self,data=None):
+ __windowlist__.remove(self)
+ if __windowlist__==[]:
+ if SYSTEM=="gtk":
+ gtk.main_quit()
+ elif SYSTEM=="osx":
+ pass
+ def maximize(self):
+ if SYSTEM=="gtk":
+ self.window.maximize()
+ def set_title(self, title):
+ if SYSTEM=="gtk":
+ self.window.set_title(title)
+ elif SYSTEM=="osx":
+ self.window.title = title
+ elif SYSTEM=="html":
+ jscommunicate("document.title = "+title)
+
+# Widget meta-class - to prevent code duplication
+# I don't seem to have any code in here. :(
+class Widget(object):
+ def __init__(self):
+ pass
+
+class Menu(Widget):
+ def __init__(self, top, menuitems):
+ if SYSTEM=="gtk":
+ if top:
+ self.mb = gtk.MenuBar()
+ else:
+ self.mb = gtk.Menu()
+ def build_menu(j, parent):
+ for i in j:
+ if type(i)==type(""):
+ #lambda is an anonymous function name, I'll use 'kappa' for an anonymous variable
+ kappa = gtk.MenuItem(i)
+ elif type(i)==type([]):
+ kappa = gtk.MenuItem(i[0])
+ kappabeta = gtk.Menu() #Same idea. Kappa is the menu item, kappabeta is the menu.
+ build_menu(i[1:],kappabeta)
+ kappa.set_submenu(kappabeta)
+ parent.append(kappa)
+ build_menu(menuitems,self.mb)
+ elif SYSTEM=="android":
+ for i in menuitems:
+ if i[0]=="File":
+ droid.addOptionsMenuItem(i[0], "javaevent", "pass")
+ elif i[0]=="Edit":
+ droid.addOptionsMenuItem(i[0], "javaevent", "quit()")
+ elif i[0]=="Help":
+ droid.addOptionsMenuItem(i[0], "pythonevent", "pass")
+ else:
+ droid.addOptionsMenuItem(i[0], "pythonevent", "quit()")
+ elif SYSTEM=="osx":
+ if top:
+ global menus
+ self.mb = GUI.MenuList()
+ tool_menu = GUI.Menu("Tools", [("Execute", "test_cmd")])
+ menus = basic_menus(exclude = print_cmds)
+ menus.append(tool_menu)
+ elif SYSTEM=="html":
+ pass
+ # I need to figure out how the menus work here.
+ def _int(self): # Returns internal GUI-specific item
+ return self.mb
+
+#def menufuncs(menu,j):
+def menufuncs(j):
+ if SYSTEM=="gtk":
+ def connect_menu(j,parent):
+ def dummifunc():
+ pass
+ agr = gtk.AccelGroup()
+ menu._int().get_toplevel().add_accel_group(agr)
+ for i in xrange(len(j)):
+ if type(j[i])==type(dummifunc):
+ parent.get_children()[i].connect("activate",j[i])
+ elif type(j[i])==type(()):
+ parent.get_children()[i].connect("activate",j[i][0])
+ key, mod = gtk.accelerator_parse(j[i][1])
+ parent.get_children()[i].add_accelerator("activate", agr, key, mod, gtk.ACCEL_VISIBLE)
+ elif type(j[i])==type([]):
+ connect_menu(j[i],parent.get_children()[i].get_submenu())
+ connect_menu(j,menu._int())
+ elif SYSTEM=="osx":
+ global menus
+ global app
+ def test():
+ print 95
+ for i in j:
+ if not i[0] in ["File", "Edit", "Help"]:
+ '''for n in i:
+ if type(n) == type(()):
+ print n[1].__name__
+ if n[1].__name__=="run_file":
+ app.run_file = test'''
+ [setattr(app,k[1].__name__, k[1]) for k in i if type(k)==type(())]
+ menu = GUI.Menu(i[0],[(k[0],k[1].__name__) for k in i if type(k)==type(())])
+ #menu = GUI.Menu("Test", [("Run", 'run_file')])
+ menus.append(menu)
+
+class VBox(Widget):
+ def __init__(self,width=False,height=False,*args):
+ if SYSTEM=="gtk":
+ self.vbox=gtk.VBox()
+ if width and height:
+ self.vbox.set_size_request(width,height)
+ [self.add(*i) for i in args]
+ elif SYSTEM=="osx":
+ seq = [i[0] for i in args] # TODO: load elements on load please
+ self.vbox=GUI.Column(seq)
+ elif SYSTEM=="html":
+ self.vbox = htmlobj("table")
+ def _int(self): # Returns internal GUI-specific item
+ return self.vbox
+ def add(self,obj,expand=False,fill=True):
+ objint = obj._int()
+ if SYSTEM=="gtk":
+ self.vbox.pack_start(objint,expand,fill,0)
+ self.vbox.show_all()
+ elif SYSTEM=="osx":
+ self.vbox.add(objint)
+ elif SYSTEM=="html":
+ if expand:
+ objint.data["height"]="100%"
+ tr = htmlobj("tr")
+ td = htmlobj("td")
+ td.add(objint)
+ tr.add(td)
+ self.vbox.add(tr)
+
+class HBox(Widget):
+ def __init__(self,width=False,height=False,*args):
+ if SYSTEM=="gtk":
+ self.hbox=gtk.HBox()
+ if width and height:
+ self.hbox.set_size_request(width,height)
+ [self.add(*i) for i in args]
+ elif SYSTEM=="osx":
+ seq = [i[0] for i in args] # TODO: load elements on load please
+ self.hbox=GUI.Row(seq)
+ elif SYSTEM=="html":
+ self.hbox = htmlobj("table")
+ self.tr = htmlobj("tr")
+ self.hbox.add(self.tr)
+ def _int(self): # Returns internal GUI-specific item
+ return self.hbox
+ def add(self,obj,expand=False,fill=False):
+ objint = obj._int()
+ if SYSTEM=="gtk":
+ self.hbox.pack_start(objint,expand,fill,0)
+ self.hbox.show_all()
+ elif SYSTEM=="html":
+ if expand:
+ objint.data["width"]="100%"
+ td = htmlobj("td")
+ td.add(objint)
+ self.tr.add(td)
+
+class Grid(Widget):
+ def __init__(self,*args):
+ if SYSTEM=="osx":
+ self.buttons = args
+ self.grid = GUI.Grid([[j._int() for j in i] for i in args],row_spacing=2,column_spacing=2,
+ align="c",equalize="wh")
+ elif SYSTEM=="html":
+ self.buttons = args
+ self.grid = htmlobj("table")
+ for i in args:
+ tr = htmlobj("tr")
+ self.grid.add(tr)
+ for j in i:
+ td = htmlobj("td")
+ td.add(j._int())
+ tr.add(td)
+ def _int(self):
+ return self.grid
+class Button(Widget):
+ def __init__(self,text=""):
+ if SYSTEM=="gtk":
+ self.button=gtk.Button()
+ self.button.connect("clicked", self._onPress)
+ elif SYSTEM=="osx":
+ self.button = GUI.Button(title=text)
+ self.button.action = (self._onPress, self.button)
+ elif SYSTEM=="html":
+ global ids
+ while True:
+ tid = id(self)
+ if not tid in ids:
+ ids[tid]=self
+ self.tid = tid
+ break
+ #self.button = htmlobj("button",{"onmousedown":"pythoncommu\
+#nicate('ids["+self.tid+"]._onPress('+event.pageX+','+event.pageY+')')"})
+ self.button = htmlobj("button",{"onmousedown":"pythoncommun\
+icate('ids["+str(self.tid)+"]._onPress(ids["+str(self.tid)+"])')"})
+ def _int(self):
+ return self.button
+ def set_image(self, img):
+ if SYSTEM=="gtk":
+ image=gtk.Image()
+ image.set_from_file(img)
+ self.button.add(image)
+ elif SYSTEM=="osx":
+ self.button.title = img.split("/")[-1].split(".")[0]
+ def set_content(self, content):
+ if SYSTEM=="gtk":
+ self.button.add(content._int())
+ elif SYSTEM=="html":
+ self.button.add(content._int())
+ def _onPress(self, widget):
+ self.onPress(self)
+ def onPress(self, self1):
+ pass
+
+class ButtonBox(Widget):
+ # This class appears to be platform-independent. Nice!
+ def __init__(self,rows,columns):
+ self.buttons=[]
+ self.hboxes=[]
+ self.vbox=VBox()
+ for i in range(rows):
+ self.hboxes.append(HBox())
+ self.vbox.add(self.hboxes[-1])
+ self.buttons.append([])
+ for j in range(columns):
+ self.buttons[-1].append(Button())
+ self.hboxes[-1].add(self.buttons[-1][-1])
+ def _int(self):
+ return self.vbox._int()
+ def add(self, obj):
+ self.vbox.add(obj)
+
+class ScrolledWindow(Widget):
+ #sch controls the horizontal scrollbar, scv controls the vertical one
+ def __init__(self,sch=True,scv=True):
+ if SYSTEM=="gtk":
+ self.sw = gtk.ScrolledWindow()
+ self.sw.set_policy(gtk.POLICY_ALWAYS if sch else gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS if scv else gtk.POLICY_AUTOMATIC)
+ def _int(self):
+ return self.sw
+ def add(self,obj):
+ objint = obj._int()
+ self.sw.add_with_viewport(objint)
+
+class Frame(Widget):
+ # PyGUI, HTML only right now
+ def __init__(self):
+ if SYSTEM=="osx":
+ self.frame = GUI.Frame()
+ elif SYSTEM=="html":
+ self.frame = htmlobj("div")
+ def _int(self):
+ return self.frame
+ def layout_self(self, *args):
+ if SYSTEM=="osx":
+ for i in args:
+ self.frame.place(i[0]._int(),left=i[1],right=i[2],top=i[3],bottom=i[4],sticky=i[5], scrolling=i[6])
+ elif SYSTEM=="html":
+ for i in args:
+ i[0]._int().style["position"]="absolute"
+ if i[1]:
+ i[0]._int().style["left"]=i[1]
+ if i[2]:
+ i[0]._int().style["right"]=i[2]
+ if i[3]:
+ i[0]._int().style["top"]=i[3]
+ if i[4]:
+ i[0]._int().style["bottom"]=i[4]
+ if "h" in i[6]:
+ i[0]._int().style["overflow-x"]="scroll"
+ else:
+ i[0]._int().style["overflow-x"]="hidden"
+ if "v" in i[6]:
+ i[0]._int().style["overflow-y"]="scroll"
+ else:
+ i[0]._int().style["overflow-y"]="hidden"
+ self.frame.add(i[0]._int())
+class Canvas(Widget):
+ def __init__(self,width=False,height=False):
+ self.objs=[]
+ if SYSTEM=="gtk":
+ self.canvas = gtk.DrawingArea()
+ self.canvas.add_events(gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.KEY_PRESS_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+ if width and height:
+ self.canvas.set_size_request(width,height)
+ def onMouseDown(canvas, event):
+ for i in self.objs:
+ i._onMouseDown(event.x, event.y)
+ self.expose_event(self.canvas, "expose-event", self.objs)
+ def onMouseUp(canvas, event):
+ for i in self.objs:
+ i._onMouseUp(event.x, event.y)
+ self.expose_event(self.canvas, "expose-event", self.objs)
+ def onMouseMove(canvas, event):
+ for i in self.objs:
+ i._onMouseMove(event.x, event.y)
+ self.expose_event(self.canvas, "expose-event", self.objs)
+ self.canvas.connect("expose-event", self.expose_event, self.objs)
+ self.canvas.connect("button-press-event", onMouseDown)
+ self.canvas.connect("button-release-event", onMouseUp)
+ self.canvas.connect("motion_notify_event", onMouseMove)
+ elif SYSTEM=="osx":
+ class OSXCanvas (ScrollableView):
+ def draw(self, canvas, update_rect):
+ canvas.erase_rect(update_rect)
+ for i in self.objs:
+ i.draw(canvas)
+
+ def mouse_down(self, event):
+ x, y = event.position
+ for i in self.objs:
+ i._onMouseDown(x, y)
+ self.invalidate_rect([0,0,self.extent[0],self.extent[1]])
+
+ def mouse_drag(self, event):
+ x, y = event.position
+ for i in self.objs:
+ i._onMouseDrag(x, y)
+ self.invalidate_rect([0,0,self.extent[0],self.extent[1]])
+
+ def mouse_move(self, event):
+ x, y = event.position
+ for i in self.objs:
+ i._onMouseMove(x, y)
+ self.invalidate_rect([0,0,self.extent[0],self.extent[1]])
+
+ def mouse_up(self, event):
+ x, y = event.position
+ for i in self.objs:
+ i._onMouseUp(x, y)
+ self.invalidate_rect([0,0,self.extent[0],self.extent[1]])
+
+ self.canvas = OSXCanvas(extent = (width, height), scrolling = 'hv')
+ self.canvas.objs = self.objs
+ elif SYSTEM=="html":
+ global ids
+ while True:
+ tid = id(self)
+ ids[tid]=self
+ self.tid = tid
+ break
+ self.canvas = htmlobj("canvas",{"id":"canvas"+str(self.tid)})
+ jsdefine("drawcanvas","(tid)",'''
+ var canvas = document.getElementById("canvas"+tid.toString());
+ var ctx = canvas.getContext("2d")
+ ctx.clearRect(0, 0, canvas.width, canvas.height)
+ for (i in cchildren[tid]) {
+ i.draw(ctx);
+ }''')
+ jscommunicate("cchildren["+str(self.tid)+"]="+str(self.objs))
+ def _int(self):
+ return self.canvas
+ def expose_event(self, canvas, event, objs):
+ x,y,w,h = canvas.allocation
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w,h)
+ cr = cairo.Context(surface)
+ cra = canvas.window.cairo_create()
+ cr.set_source_rgb(0.5, 0.5, 0.5)
+ cr.paint()
+ for i in objs:
+ i.draw(cr)
+ cra.set_source_surface(surface)
+ cra.paint()
+ def draw(self):
+ if SYSTEM=="gtk":
+ self.expose_event(self.canvas, "draw_event", self.objs)
+ elif SYSTEM in ["osx", "android"]:
+ self.canvas.invalidate_rect((0,0,self.canvas.extent[0],self.canvas.extent[1]))
+ elif SYSTEM=="html":
+ jscommunicate("drawcanvas("+self.tid+")")
+ def add(self, obj, x, y):
+ obj.x = x
+ obj.y = y
+ self.objs.append(obj)
+ jscommunicate("cchildren["+str(self.tid)+"]="+str(self.objs))
+ def delete(self, obj):
+ self.objs.remove(obj)
+ del obj
+ self.draw()
+ jscommunicate("cchildren["+str(self.tid)+"]="+str(self.objs))
+
+class TextView(Widget):
+ def __init__(self,editable=True,width=False,height=False):
+ if SYSTEM=="gtk":
+ self.sw=ScrolledWindow()
+ self.box=gtk.TextView()
+ if width and height:
+ self.sw._int().set_size_request(width,height)
+ self.box.set_cursor_visible(editable)
+ self.sw._int().add_with_viewport(self.box)
+ #self.sw._int().set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ def scroll(self,widget):
+ self.scroll_to_mark(self.get_buffer().get_insert(), 0)
+ self.box.connect("key-press-event",scroll)
+ elif SYSTEM=="osx":
+ self.box = GUI.TextEditor(scrolling="hv")
+ elif SYSTEM=="html":
+ self.box = htmlobj("textarea")
+ def _int(self):
+ if SYSTEM=="gtk":
+ return self.sw._int()
+ elif SYSTEM=="osx":
+ return self.box
+ elif SYSTEM=="html":
+ return self.box
+
+class Image(object):
+ def __init__(self,image,x=0,y=0,animated=False,canvas=None,htiles=1,vtiles=1):
+ self.x = x
+ self.y = y
+ self.minx = x
+ self.miny = y
+ self.rotation = 0
+ self.xscale = 1
+ self.yscale = 1
+ self.filled = True
+ self.linecolor = None
+ self.fillcolor = None
+ self.name = image
+ if animated:
+ self.animated = True
+ self.htiles = htiles
+ self.vtiles = vtiles
+ self.pointer = 0
+ self.canvas = canvas
+ def animate(self):
+ self.pointer = (self.pointer+1)%(htiles*vtiles)
+ if SYSTEM in ["gtk", "osx"]:
+ self.canvas._int().invalidate_rect([self.x, self.y, self.x+self.image.bounds[2]/self.htiles, self.y+self.image.bounds[3]/self.vtiles])
+ else:
+ jscommunicate("drawcanvas("+str(self.canvas.tid)+")")
+ r = misc_funcs.RepeatTimer(0.1, animate, args=[self])
+ r.daemon = True
+ r.start()
+ else:
+ self.animated = False
+ if SYSTEM=="osx":
+ self.image = GUI.Image(file = image)
+ if self.animated:
+ self.maxx = self.x+self.image.bounds[2]/self.htiles
+ self.maxy = self.y+self.image.bounds[3]/self.vtiles
+ else:
+ self.maxx = self.x+self.image.bounds[2]
+ self.maxy = self.y+self.image.bounds[3]
+ elif SYSTEM=="html":
+ self.image = htmlobj("img", {"src":image})
+ #TODO: ##### FIGURE OUT WIDTH, HEIGHT #####
+ if self.animated:
+ self.maxx = self.x#+self.image.width[2]/self.htiles
+ self.maxy = self.y#+self.image.height[3]/self.vtiles
+ else:
+ self.maxx = self.x#+self.image.width[2]
+ self.maxy = self.y#+self.image.height[3]
+ def _int(self):
+ return self.image
+ def draw(self, cr=None, parent=None, rect=None):
+ if SYSTEM=="android":
+ pass
+ elif SYSTEM=="osx":
+ cr.gsave()
+ if sep=="\\":
+ # Very ugly hack for Windows. :(
+ # Windows doesn't respect coordinate transformations
+ # with respect to translation, so we have to do this
+ # bit ourselves.
+
+ # Rotation in radians
+ radrot = parent.group.rotation*math.pi/180
+ # Coordinate transform: multiplication by a rotation matrix
+ cr.translate(self.x*math.cos(radrot)-self.y*math.sin(radrot), self.x*math.sin(radrot)+self.y*math.cos(radrot))
+ else:
+ cr.translate(self.x,self.y)
+ cr.rotate(self.rotation)
+ cr.scale(self.xscale*1.0, self.yscale*1.0)
+ if self.animated:
+ src_rect = self.image.bounds
+ # (i%4)%6, i/4
+ src_rect = [(src_rect[2]/self.htiles)*(self.pointer%self.htiles),
+ (src_rect[3]/self.vtiles)*(self.pointer/self.htiles),
+ (src_rect[2]/self.htiles)*(self.pointer%self.htiles+1),
+ (src_rect[3]/self.vtiles)*(self.pointer/self.htiles+1)]
+ #src_rect = [16*self.pointer,0,16+16*self.pointer,32]
+ #print [self.x, self.y, self.x+self.image.bounds[2]/self.htiles, self.y+self.image.bounds[3]/self.vtiles]
+ dst_rect = [0, 0, self.image.bounds[2]/self.htiles, self.image.bounds[3]/self.vtiles]
+ self.image.draw(cr, src_rect, dst_rect)
+ else:
+ src_rect = self.image.bounds
+ dst_rect = src_rect
+ self.image.draw(cr, src_rect, dst_rect)
+ cr.grestore()
+ elif SYSTEM=="html":
+ cr.save()
+ pass
+
+class Shape (object):
+ def __init__(self,x=0,y=0,rotation=0,fillcolor=None,linecolor=None):
+ global SITER
+ self.x=x
+ self.y=y
+ self.rotation=rotation
+ self.xscale = 1
+ self.yscale = 1
+ self.linecolor = linecolor if linecolor else LINECOLOR
+ self.fillcolor = fillcolor if fillcolor else FILLCOLOR
+ self.shapedata=[]
+ self.filled=False
+ self.type="Shape"
+ ####################-----TEMPORARY-----#########################
+ self.name = "s"+str(int(random.random()*10000))+str(SITER)
+ SITER+=1
+ ################################################################
+ def draw(self,cr=None,parent=None,rect=None):
+ if SYSTEM=="gtk":
+ cr.save()
+ cr.translate(self.x,self.y)
+ cr.rotate(self.rotation*math.pi/180)
+ cr.scale(self.xscale*1.0, self.yscale*1.0)
+ cr.set_source(self.linecolor.cairo)
+ for i in self.shapedata:
+ if i[0]=="M":
+ cr.move_to(i[1],i[2])
+ elif i[0]=="L":
+ cr.line_to(i[1],i[2])
+ elif i[0]=="C":
+ cr.curve_to(i[1],i[2],i[3],i[4],i[5],i[6])
+ if self.filled:
+ cr.stroke_preserve()
+ cr.set_source(self.fillcolor.cairo)
+ cr.fill()
+ else:
+ cr.stroke()
+ cr.restore()
+ elif SYSTEM=="android":
+ global tb
+ tb+="cr.save()\n"
+ tb+="cr.translate("+str(self.x)+","+str(self.y)+")\n"
+ tb+="cr.rotate("+str(self.rotation*math.pi/180)+")\n"
+ tb+="cr.scale("+str(self.xscale)+"*1.0, "+str(self.yscale)+"*1.0)\n"
+ if type(self.fill)==type([]):
+ tb+="cr.fillStyle = \""+rgb2hex(self.fill[0],self.fill[1],self.fill[2])+"\"\n"
+ for i in self.shapedata:
+ if i[0]=="M":
+ tb+="cr.moveTo("+str(i[1])+","+str(i[2])+")\n"
+ elif i[0]=="L":
+ tb+="cr.lineTo("+str(i[1])+","+str(i[2])+")\n"
+ elif i[0]=="C":
+ tb+="cr.bezierCurveTo("+str(i[1])+","+str(i[2])+","+str(i[3])+","+str(i[4])+","+str(i[5])+","+str(i[6])+")\n"
+ if self.filled:
+ tb+="cr.stroke()\n"
+ tb+="cr.fill()\n"
+ else:
+ tb+="cr.stroke()\n"
+ tb+="cr.restore()\n"
+ elif SYSTEM=="osx":
+ cr.gsave()
+ if sep=="\\":
+ # Very ugly hack for Windows. :(
+ # Windows doesn't respect coordinate transformations
+ # with respect to translation, so we have to do this
+ # bit ourselves.
+
+ # Rotation in radians
+ radrot = parent.group.rotation*math.pi/180
+ # Coordinate transform: multiplication by a rotation matrix
+ cr.translate(self.x*math.cos(radrot)-self.y*math.sin(radrot), self.x*math.sin(radrot)+self.y*math.cos(radrot))
+ else:
+ cr.translate(self.x,self.y)
+ cr.rotate(self.rotation)
+ cr.scale(self.xscale*1.0, self.yscale*1.0)
+ cr.newpath()
+ cr.pencolor = self.linecolor.pygui
+ cr.fillcolor = self.fillcolor.pygui
+ for i in self.shapedata:
+ if i[0]=="M":
+ point = (i[1], i[2])
+ cr.moveto(point[0],point[1])
+ elif i[0]=="L":
+ point = (i[1], i[2])
+ cr.lineto(point[0],point[1])
+ elif i[0]=="C":
+ pointa = (i[1], i[2])
+ pointb = (i[3], i[4])
+ pointc = (i[5], i[6])
+ ### Mac OSX needs custom PyGUI for this to work ###
+ cr.curveto((pointa[0],pointa[1]),(pointb[0],pointb[1]),(pointc[0],pointc[1]))
+ if self.filled:
+ cr.closepath()
+ cr.fill_stroke()
+ else:
+ cr.stroke()
+ cr.grestore()
+ elif SYSTEM=="html":
+ tb = ""
+ tb+="cr.save()\n"
+ tb+="cr.translate("+str(self.x)+","+str(self.y)+")\n"
+ tb+="cr.rotate("+str(self.rotation*math.pi/180)+")\n"
+ tb+="cr.scale("+str(self.xscale)+"*1.0, "+str(self.yscale)+"*1.0)\n"
+ if type(self.fill)==type([]):
+ tb+="cr.fillStyle = \""+rgb2hex(self.fill[0],self.fill[1],self.fill[2])+"\"\n"
+ for i in self.shapedata:
+ if i[0]=="M":
+ tb+="cr.moveTo("+str(i[1])+","+str(i[2])+")\n"
+ elif i[0]=="L":
+ tb+="cr.lineTo("+str(i[1])+","+str(i[2])+")\n"
+ elif i[0]=="C":
+ tb+="cr.bezierCurveTo("+str(i[1])+","+str(i[2])+","+str(i[3])+","+str(i[4])+","+str(i[5])+","+str(i[6])+")\n"
+ if self.filled:
+ tb+="cr.stroke()\n"
+ tb+="cr.fill()\n"
+ else:
+ tb+="cr.stroke()\n"
+ tb+="cr.restore()\n"
+ jscommunicate(tb)
+ def line(self,x,y,x1=False,y1=False):
+ pass
+ def curve(self,x,y,x1,y1,x2=False,y2=False):
+ pass
+ def edit(self, arguments):
+ pass #no idea how this will work yet
+ def move(self, x, y):
+ pass
+ def scale(self, width, height):
+ try:
+ xfactor = width/self.maxx
+ yfactor = height/maxy
+ def scale_section(section):
+ try:
+ if section[0] in ["M", "L"]:
+ section[1]*=xfactor
+ section[2]*=yfactor
+ elif section[0]=="C":
+ section[1]*=xfactor
+ section[2]*=yfactor
+ section[3]*=xfactor
+ section[4]*=yfactor
+ section[5]*=xfactor
+ section[6]*=yfactor
+ except ZeroDivisionError:
+ print "Divided by zero while scaling a tiny segment. Continuing happily."
+ result = [scale_section(i) for i in self.shapedata]
+ except ZeroDivisionError:
+ print "Divided by zero! Universe collapsing."
+ def hitTest(self,x,y):
+ hits = False
+ # points "a" and "b" forms the anchored segment.
+ # point "c" is the evaluated point
+ def IsOnLeft(a, b, c):
+ return Area2(a, b, c) > 0
+ def IsOnRight(a, b, c):
+ return Area2(a, b, c) < 0
+ def IsCollinear(a, b, c):
+ return Area2(a, b, c) == 0
+ # calculates the triangle's size (formed by the "anchor" segment and additional point)
+ def Area2(a, b, c):
+ return (b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1])
+ def intersects(a,b,c,d):
+ return not (IsOnLeft(a,b,c) != IsOnRight(a,b,d))
+ def ccw(a,b,c):
+ return (c[1]-a[1])*(b[0]-a[0]) > (b[1]-a[1])*(c[0]-a[0])
+ def intersect(a,b,c,d):
+ return ccw(a,c,d) != ccw(b,c,d) and ccw(a,b,c) != ccw(a,b,d)
+ for i in xrange(len(self.shapedata)):
+ hits = hits != intersect(self.shapedata[i-1][1:3],self.shapedata[i][1:3],[x,y],[x,sys.maxint])
+ return hits
+ def localtransform(self, x, y, parent):
+ x,y = parent.localtransform(x,y)
+ nx = x*math.cos(-self.rotation)-y*math.sin(-self.rotation)+self.x
+ ny = x*math.sin(-self.rotation)+y*math.cos(-self.rotation)+self.y
+ return nx, ny
+ def revlocaltransform(self, x, y, parent):
+ x,y = parent.revlocaltransform(x,y)
+ radrot = self.rotation*math.pi/180
+ nx = x*math.cos(radrot)-y*math.sin(radrot)+self.x
+ ny = x*math.sin(radrot)+y*math.cos(radrot)+self.y
+ return nx, ny
+ def getminx(self):
+ return min([i[1] for i in self.shapedata])
+ def getminy(self):
+ return min([i[2] for i in self.shapedata])
+ def getmaxx(self):
+ return max([i[1] for i in self.shapedata])
+ def getmaxy(self):
+ return max([i[2] for i in self.shapedata])
+ def onMouseDown(self, self1, x, y):
+ pass
+ def onMouseDrag(self, self1, x, y):
+ pass
+ def onMouseUp(self, self1, x, y):
+ pass
+ def onMouseMove(self, self1, x, y):
+ pass
+ minx = property(getminx)
+ miny = property(getminy)
+ maxx = property(getmaxx)
+ maxy = property(getmaxy)
+class Layer:
+ def setscale(self, scal):
+ self.xscale = scal
+ self.yscale = scal
+ def getminx(self):
+ return min([i.minx for i in self.currentFrame()])
+ def getminy(self):
+ return min([i.miny for i in self.currentFrame()])
+ def getmaxx(self):
+ return max([i.maxx for i in self.currentFrame()])
+ def getmaxy(self):
+ return max([i.maxy for i in self.currentFrame()])
+ def onMouseDown(self, self1, x, y):
+ pass
+ def onMouseDrag(self, self1, x, y):
+ pass
+ def onMouseUp(self, self1, x, y):
+ pass
+ def onMouseMove(self, self1, x, y):
+ pass
+ minx = property(getminx)
+ miny = property(getminy)
+ maxx = property(getmaxx)
+ maxy = property(getmaxy)
+ scale = property(fset = setscale)
+ class frame:
+ class framewrapper (object):
+ #Wraps object per-frame. Allows for changes in position, rotation, scale.
+ def __init__(self, obj, x, y, rot, scalex, scaley):
+ self.obj = obj
+ self.x = obj.x = x
+ self.y = obj.y = y
+ self.rot = obj.rot = rot
+ self.scalex = obj.scalex = scalex
+ self.scaley = obj.scaley = scaley
+ self.level = False # don't try to descend into a framewrapper
+ self.type = obj.__class__.__name__
+ self.filled = obj.filled
+ self.linecolor = obj.linecolor
+ self.fillcolor = obj.fillcolor
+ self.name = obj.name
+ def draw(self,cr,transform):
+ pass
+ self.update()
+ self.obj.draw(cr,transform)
+ def update(self):
+ self.obj.x = self.x
+ self.obj.y = self.y
+ self.obj.rot = self.rot
+ self.obj.scalex = self.scalex
+ self.obj.scaley = self.scaley
+ self.obj.filled = self.filled
+ self.obj.linecolor = self.linecolor
+ self.obj.fillcolor = self.fillcolor
+ def _onMouseDown(self, x, y):
+ self.obj.onMouseDown(self,x, y)
+ def _onMouseUp(self, x, y):
+ self.obj.onMouseUp(self,x, y)
+ def _onMouseMove(self, x, y):
+ self.obj.onMouseMove(self, x, y)
+ def _onMouseDrag(self, x, y):
+ self.obj.onMouseDrag(self, x, y)
+ def getminx(self):
+ return self.obj.minx+self.x
+ def getminy(self):
+ return self.obj.miny+self.y
+ def getmaxx(self):
+ return self.obj.maxx
+ def getmaxy(self):
+ return self.obj.maxy
+ minx = property(getminx)
+ miny = property(getminy)
+ maxx = property(getmaxx)
+ maxy = property(getmaxy)
+ def hitTest(self, x, y):
+ x,y = self.transformcoords(x,y)
+ return self.obj.hitTest(x, y)
+ def transformcoords(self,x,y):
+ x = x-self.x
+ y = y-self.y
+ return x,y
+ def __init__(self,duplicate=None):
+ self.objs = []
+ self.currentselect=None
+ self.type="Group"
+ def add(self, obj, x, y, rot=0, scalex=0, scaley=0):
+ self.objs.append(self.framewrapper(obj, x, y, rot, scalex, scaley))
+ def play(self, group, cr, currentselect,transform,rect):
+ if SYSTEM=="gtk":
+ cr.save()
+ cr.translate(group.x,group.y)
+ cr.rotate(group.rotation*math.pi/180)
+ cr.scale(group.xscale,group.yscale)
+ result = [obj.draw(cr) for obj in self.objs if ((obj.minx>=rect[0] and obj.miny>=rect[1]) or (obj.maxx<=rect[2] and obj.maxy<=rect[3]))]
+ if currentselect:
+ cr.set_source_rgb(0,0,1)
+ cr.rectangle(currentselect.minx-1,currentselect.miny-1,currentselect.maxx+2,currentselect.maxy+2)
+ cr.stroke()
+ cr.restore()
+ elif SYSTEM=="android":
+ global tb
+ tb+="cr.save()\n"
+ tb+="cr.translate("+str(group.x)+","+str(group.y)+")\n"
+ tb+="cr.rotate("+str(group.rotation*math.pi/180)+")\n"
+ result = [obj.draw(cr) for obj in self.objs]
+ if currentselect:
+ tb+="cr.strokeSyle = \"#0000FF\"\n"
+ tb+="cr.rect("+str(currentselect.minx-1)+","+str(currentselect.miny-1)+","+str(currentselect.maxx+2)+","+str(currentselect.maxy+2)+")\n"
+ tb+="cr.stroke()\n"
+ tb+="cr.restore()\n"
+ elif SYSTEM=="osx":
+ pass
+ self.group = group
+ cr.gsave()
+ cr.rotate(group.rotation)
+ cr.translate(group.x,group.y)
+ cr.scale(group.xscale,group.yscale)
+ def dodraw(obj, cr):
+ obj.draw(cr, self)
+ result = [dodraw(obj, cr) for obj in self.objs]
+ if currentselect:
+ cr.gsave()
+ cr.newpath()
+ cr.pencolor = Colors.rgb(0,0,1)
+ cr.rect([currentselect.minx-1,currentselect.miny-1,
+ currentselect.maxx+currentselect.x+2,
+ currentselect.maxy+currentselect.y+2])
+ cr.stroke()
+ cr.grestore()
+ cr.grestore()
+ elif SYSTEM=="html":
+ tb = ""
+ tb+="cr.save()\n"
+ tb+="cr.translate("+str(group.x)+","+str(group.y)+")\n"
+ tb+="cr.rotate("+str(group.rotation*math.pi/180)+")\n"
+ def dodraw(obj, cr):
+ obj.draw(cr, self)
+ result = [dodraw(obj, cr) for obj in self.objs]
+ if currentselect:
+ tb+="cr.strokeSyle = \"#0000FF\"\n"
+ tb+="cr.rect("+str(currentselect.minx-1)+","+str(currentselect.miny-1)+","+str(currentselect.maxx+2)+","+str(currentselect.maxy+2)+")\n"
+ tb+="cr.stroke()\n"
+ tb+="cr.restore()\n"
+ jscommunicate(tb)
+ def localtransform(self,x,y):
+ radrot = self.group.rotation*math.pi/180.0
+ nx = x*math.cos(-radrot)-y*math.sin(-radrot)-self.group.x
+ ny = x*math.sin(-radrot)+y*math.cos(-radrot)-self.group.y
+ return nx, ny
+ def revlocaltransform(self,x,y):
+ radrot = self.group.rotation*math.pi/180.0
+ nx = x*math.cos(radrot)-y*math.sin(radrot)-self.group.x
+ ny = x*math.sin(radrot)+y*math.cos(radrot)-self.group.y
+ return nx, ny
+ def print_sc(self):
+ retval = ""
+ for i in self.objs:
+ retval = retval+".put "+i.name+" x="+str(i.x)+" y="+str(i.y)+"\n"
+ return retval
+ def __init__(self, *args):
+ # init is system-independent, oh joy
+ self.x=0
+ self.y=0
+ self.rotation=0
+ self.xscale = 1.0
+ self.yscale = 1.0
+ self.objs=[]
+ self.currentframe=0
+ self.activeframe=0 # Frame selected - not necessarily the frame displayed
+ self.frames=[self.frame()]
+ self.level = False
+ self.clicked = False
+ self.hidden = False
+ self.currentselect = None
+ def parse_obj(obj):
+ self.objs.append(obj)
+ obj.x=obj.x-self.x
+ obj.y=obj.y-self.y
+ [parse_obj(obj) for obj in args]
+ def draw(self,cr=None,transform=None,rect=None):
+ if SYSTEM=="android":
+ global tb
+ rc = False
+ if cr:
+ rc = True
+ cr = None
+ self.frames[self.currentframe].play(self,cr, self.currentselect, transform,rect)
+ if SYSTEM=="android":
+ if rc:
+ droid.eventPost("javaevent", tb)
+ tb = ""
+ def add(self,*args):
+ # system-independent
+ def parse_obj(obj):
+ obj.x=obj.x-self.x
+ obj.y=obj.y-self.y
+ self.frames[self.currentframe].add(obj, obj.x, obj.y, obj.rotation,0,0)
+ self.objs.append(obj)
+ [parse_obj(obj) for obj in args]
+ def add_frame(self,populate):
+ if self.activeframe>len(self.frames):
+ lastframe = len(self.frames)
+ for i in xrange(self.activeframe-len(self.frames)):
+ self.frames.append(None)
+ if self.frames[self.activeframe]==None:
+ self.frames[self.activeframe]=self.frame()
+ for i in xrange(self.activeframe-1,-1,-1):
+ if self.frames[i]:
+ lastframe = i
+ break
+ else:
+ lastframe = self.activeframe
+ else:
+ lastframe = self.activeframe
+ self.activeframe+=1
+ self.frames.insert(self.activeframe,self.frame())
+ for i in self.frames[lastframe].objs:
+ i.update()
+ self.frames[self.activeframe].add(i.obj, i.x, i.y, i.rot)
+ self.currentframe = self.activeframe
+ def descendItem(self):
+ if self.currentselect.__class__.__name__=="Group" and self.level==True:
+ return self.frames[self.currentframe].currentselect.descendItem()
+ else:
+ return self
+ def currentFrame(self):
+ return self.frames[self.currentframe].objs
+ def _onMouseDown(self, x, y):
+ if self.level:
+ if self.currentselect and self.currentselect.level:
+ self.currentselect._onMouseDown(self.currentselect, x, y)
+ else:
+ if MODE in [" ", "s", "b"]:
+ for i in reversed(self.currentFrame()):
+ test = False
+ if i.hitTest(x, y):
+ if MODE in [" ", "s"]:
+ self.currentselect = i
+ i._onMouseDown(x, y)
+ test=True
+ break
+ if not test:
+ self.currentselect = None
+ else:
+ self.onMouseDown(self, x, y)
+ else:
+ self.onMouseDown(self, x, y)
+ def onMouseDown(self, self1, x, y):
+ pass
+ def _onMouseUp(self,x,y):
+ if self.level and MODE in [" ", "s"]:
+ if self.currentselect:
+ self.currentselect._onMouseUp(x, y)
+ else:
+ self.onMouseUp(self, x, y)
+ def onMouseUp(self, self1, x, y):
+ pass
+ def _onMouseMove(self,x,y):
+ if self.level and MODE in [" ", "s"]:
+ if self.currentselect:
+ self.currentselect._onMouseMove(x, y)
+ else:
+ self.onMouseMove(self, x, y)
+ def onMouseMove(self, self1, x, y):
+ pass
+ def _onMouseDrag(self, x, y):
+ if self.level and MODE in [" ", "s"]:
+ if self.currentselect:
+ self.currentselect._onMouseDrag(x, y)
+ else:
+ self.onMouseDrag(self, x, y)
+ def onMouseDrag(self, self1, x, y):
+ pass
+ def print_sc(self,defs=True,frams=True):
+ retval = ""
+ if defs:
+ for i in self.objs:
+ if i.type=="Group":
+ retval+=".sprite "+i.name+"\n"+i.print_sc
+ elif i.type=="Shape":
+ retval+=".outline "+i.name+"outline:\n"
+ retval+=" ".join([" ".join([str(x) for x in a]) for a in i.shapedata])+"\n.end\n"
+ if i.filled:
+ retval+=".filled "+i.name+" outline="+i.name+"outline fill="+i.fillcolor.rgb+" color="+i.linecolor.rgb+"\n"
+ else:
+ retval+=".filled "+i.name+" outline="+i.name+"outline fill=#00000000 color="+i.linecolor.rgb+"\n"
+ if frams:
+ for i in self.frames:
+ retval+=".frame "+str(self.frames.index(i)+1)+"\n"+i.print_sc()
+ return retval
+
+
+class Group (object):
+ def setscale(self, scal):
+ self.xscale = scal
+ self.yscale = scal
+ def getal(self):
+ return self.layers[self._al]
+ def setal(self,al):
+ self._al = al
+ def getlevel(self):
+ return self.activelayer.level
+ def setlevel(self,lev):
+ self.activelayer.level = lev
+ def getminx(self):
+ return min([i.minx for i in self.layers])
+ def getminy(self):
+ return min([i.miny for i in self.layers])
+ def getmaxx(self):
+ return max([i.maxx for i in self.layers])
+ def getmaxy(self):
+ return max([i.maxy for i in self.layers])
+ def onMouseDown(self, self1, x, y):
+ pass
+ def onMouseDrag(self, self1, x, y):
+ pass
+ def onMouseUp(self, self1, x, y):
+ pass
+ def onMouseMove(self, self1, x, y):
+ pass
+ minx = property(getminx)
+ miny = property(getminy)
+ maxx = property(getmaxx)
+ maxy = property(getmaxy)
+ activelayer = property(getal,setal)
+ level = property(getlevel, setlevel)
+ scale = property(fset = setscale)
+ def __init__(self, *args, **kwargs):
+ self.layers = [Layer(*args)]
+ self._al = 0
+ self.clicked = False
+ self.x = 0
+ self.y = 0
+ self.rotation = 0
+ self.xscale = 1
+ self.yscale = 1
+ print kwargs
+ if "onload" in kwargs:
+ kwargs["onload"](self)
+ def draw(self,cr=None,transform=None,rect=None):
+ for i in self.layers:
+ if not i.hidden:
+ i.x = self.x
+ i.y = self.y
+ i.rotation = self.rotation
+ i.xscale = self.xscale
+ i.yscale = self.yscale
+ i.draw(cr,rect=rect)
+ def add(self, *args):
+ self.activelayer.add(*args)
+ def add_frame(self, populate):
+ self.activelayer.add_frame(populate)
+ def add_layer(self, index):
+ self.layers.insert(index+1,Layer())
+ self.activelayer = index+1
+ self.activelayer.level = True
+ def delete_layer(self, index):
+ del self.layers[index]
+ while self._al>=0:
+ try:
+ dum = self.activelayer
+ break
+ except IndexError:
+ self._al-=1
+ if self._al<0:
+ self.add_layer(-1)
+ def descendItem(self):
+ if self.activelayer.currentselect.__class__.__name__=="Group" and self.level==True:
+ return self.frames[self.currentframe].currentselect.descendItem()
+ else:
+ return self
+ self.activelayer.descendItem()
+ def currentFrame(self):
+ return self.activelayer.currentFrame()
+ def localtransform(self,x,y):
+ radrot = self.rotation*math.pi/180.0
+ nx = x*math.cos(-radrot)-y*math.sin(-radrot)-self.x
+ ny = x*math.sin(-radrot)+y*math.cos(-radrot)-self.y
+ return nx, ny
+ def onLoad(self, self1):
+ pass
+ def _onMouseDown(self, x, y):
+ x, y = self.localtransform(x, y)
+ if self.level:
+ if self.activelayer.currentselect and self.activelayer.currentselect.level:
+ self.activelayer.currentselect._onMouseDown(self.activelayer.currentselect, x, y)
+ else:
+ if MODE in [" ", "s", "b"]:
+ for i in reversed(self.currentFrame()):
+ test = False
+ if i.hitTest(x, y):
+ if MODE in [" ", "s"]:
+ self.activelayer.currentselect = i
+ test=True
+ i._onMouseDown(x, y)
+ break
+ if not test:
+ self.activelayer.currentselect = None
+ else:
+ self.onMouseDown(self, x, y)
+ else:
+ self.onMouseDown(self, x, y)
+ def onMouseDown(self, self1, x, y):
+ pass
+ def _onMouseUp(self,x,y):
+ x, y = self.localtransform(x, y)
+ if self.activelayer.level and MODE in [" ", "s"]:
+ if self.activelayer.currentselect:
+ self.activelayer.currentselect._onMouseUp(x, y)
+ else:
+ self.onMouseUp(self, x, y)
+ def onMouseUp(self, self1, x, y):
+ pass
+ def _onMouseMove(self,x,y):
+ x, y = self.localtransform(x, y)
+ if self.activelayer.level and MODE in [" ", "s"]:
+ if self.activelayer.currentselect:
+ self.activelayer.currentselect._onMouseMove(x, y)
+ else:
+ self.onMouseMove(self, x, y)
+ def onMouseMove(self, self1, x, y):
+ pass
+ def _onMouseDrag(self, x, y):
+ x, y = self.localtransform(x, y)
+ if self.activelayer.level and MODE in [" ", "s"]:
+ if self.activelayer.currentselect:
+ self.activelayer.currentselect._onMouseDrag(x, y)
+ else:
+ self.onMouseDrag(self, x, y)
+ def onMouseDrag(self, self1, x, y):
+ pass
+ def maxframe(self):
+ frame = 0
+ for i in self.layers:
+ frame = max(frame, len(i.frames))
+ return frame
+ def print_sc(self):
+ retval = ""
+ for i in self.layers:
+ retval+=i.print_sc(True, False)
+ for i in xrange(self.maxframe()):
+ retval+=".frame "+str(i+1)+"\n"
+ for j in self.layers:
+ if j.frames[i]:
+ retval+=j.frames[i].print_sc()
+ return retval
+
+
+def alert(text,critical=False):
+ if SYSTEM=="gtk":
+ #Launches an alert window with a given text.
+ #If critical is True, closing the alert terminates SWIFT.
+ def abutton_press_event(widget, event):
+ #Close when "Ok" is pressed
+ alert.destroy()
+ def on_destroy(event):
+ if critical:
+ #if this is a critical alert, such as when another instrance of SWIFT is already running
+ gtk.main_quit()
+ alert = gtk.Window(type=gtk.WINDOW_TOPLEVEL) # make a new window for the alert
+ alert.set_position(gtk.WIN_POS_CENTER) # put it in the center of the screen
+ alert.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) # tell the WM that it is a dialog
+ alert.set_destroy_with_parent(True) # if someone closes SWIFT, we want the alert to close too
+ alert.set_modal(True) # alert should block input to SWIFT until acknowledged
+ alert.set_title("Alert") # call it "Alert"
+ alert.set_size_request(250, 100) # make it 250x100
+ avbox = vbox = gtk.VBox(False, 0) # create a vertical box container
+ alert.add(avbox) # add said container to the alert
+ alabel=gtk.Label(text) # make a label to hold the text
+ alabel.set_size_request(240,-1) # make it slightly narrower than the parent window
+ alabel.set_line_wrap(True) # we want the text to word wrap
+ alabel.set_justify(gtk.JUSTIFY_CENTER) # center the text
+ avbox.pack_start(alabel, False, True, 0) # put it at the start of the vbox
+ alabel.show() # make it visible
+ abutton = gtk.Button("OK") # new button with text "OK"
+ abutton.set_use_stock(True) # it is a stock button provided by GTK
+ abutton.set_size_request(50, -1) # we don't want it as wide as the whole alert
+ abutton.set_events(gtk.gdk.ALL_EVENTS_MASK); # capture clicks, keyboard, anything
+ abutton.connect("button_press_event", abutton_press_event) # but only listen to the clicks
+ alert.connect("destroy", on_destroy) # close alert when alert is closed
+ abutton.show() # make button visible
+ ahbox = gtk.HBox(False, 10) # make a new hbox
+ ahbox.pack_start(abutton, True, False, 0) # put the button in it, but don't make it expand
+ avbox.pack_start(ahbox, True, False, 0) # put the hbox in the vbox
+ ahbox.show() # make it visible
+ avbox.show() # make the vbox visible
+ alert.show() # make the alert itself visible
+ elif SYSTEM=="html":
+ jscommunicate("alert("+text+")")
+ if critical:
+ # reloading the page is equivalent to force-quitting, right?
+ jscommunicate("window.location.reload()")
+
+class OverlayWindow:
+ if SYSTEM=="gtk":
+ def expose (widget, event, startime=time.time()):
+ cr = widget.window.cairo_create()
+ # Sets the operator to clear which deletes everything below where an object is drawn
+ cr.set_operator(cairo.OPERATOR_CLEAR)
+ # Makes the mask fill the entire window
+ cr.rectangle(0.0, 0.0, *widget.get_size())
+ # Deletes everything in the window (since the compositing operator is clear and mask fills the entire window
+ cr.fill()
+ # Set the compositing operator back to the default
+ cr.set_operator(cairo.OPERATOR_OVER)
+
+ widget.present()
+
+ # Clear background to transparent black
+ cr.set_source_rgba(0.0,0.0,0.0,2.0-(time.time()-startime))
+ cr.paint()
+ image = "media/logo-transparent.png"
+ surface = cairo.ImageSurface.create_from_png(image)
+ pat = cairo.SurfacePattern(surface)
+ cr.set_source(pat)
+ cr.paint_with_alpha(2.0-(time.time()-startime))
+ #return True
+
+
+ win = gtk.Window()
+ win.set_decorated(False)
+ win.set_modal(True)
+
+ # Makes the window paintable, so we can draw directly on it
+ win.set_app_paintable(True)
+ win.set_size_request(512, 512)
+ win.set_position(gtk.WIN_POS_CENTER)
+
+ # This sets the windows colormap, so it supports transparency.
+ # This will only work if the wm support alpha channel
+ screen = win.get_screen()
+ rgba = screen.get_rgba_colormap()
+ win.set_colormap(rgba)
+ win.connect('expose-event', expose)
+ win.show()
+ win.present()
+ gobject.timeout_add(50, expose, win, 'fade-event', time.time())
+ gobject.timeout_add(2000, win.destroy)
+
+class ColorSelectionWindow:
+ def __init__(self,var,dispgrp, dcanv):
+ if SYSTEM=="gtk":
+ win = gtk.Window()
+ win.set_size_request(320,208)
+ win.set_decorated(False)
+ darea = gtk.DrawingArea()
+ darea.set_size_request(320,208)
+ win.add(darea)
+ win.show_all()
+ win.add_events(gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.LEAVE_NOTIFY_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.KEY_PRESS_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+ def expose_event(widget, event):
+ x,y,w,h = widget.allocation
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w,h)
+ cr = cairo.Context(surface)
+ cra = widget.window.cairo_create()
+ cr.set_source_rgb(0.5, 0.5, 0.5)
+ cr.paint()
+ for i in xrange(21):
+ for j in xrange(len(colors.colorArray(i))):
+ cr.rectangle(i*16,j*16,15,15)
+ r,g,b = colors.colorArray(i)[j]
+ cr.set_source_rgb(r,g,b)
+ cr.fill()
+ cra.set_source_surface(surface)
+ cra.paint()
+ def close(widget, event, dispshape, dcanv):
+ global LINECOLOR,FILLCOLOR
+ if var=="line":
+ LINECOLOR = Color(colors.colorArray(int(event.x)/16)[int(event.y)/16])
+ elif var=="fill":
+ FILLCOLOR = Color(colors.colorArray(int(event.x)/16)[int(event.y)/16])
+ dispgrp.frames[0].objs[2].fillcolor = LINECOLOR if var=="line" else FILLCOLOR
+ dcanv.draw()
+ widget.destroy()
+ darea.connect("expose-event",expose_event)
+ win.connect("button-press-event", close, dispgrp, dcanv)
+ win.set_modal(True)
+ win.present()
+
+def main():
+ #Executes the main loop for whatever GUI is running
+ if SYSTEM=="gtk":
+ gtk.main()
+ elif SYSTEM=="osx":
+ global app
+ app.menus = menus
+ app.run()
+ elif SYSTEM=="html":
+ print __windowlist__[0].window
+ pass
+
+def quit():
+ #Self-descriptive
+ if SYSTEM=="gtk":
+ gtk.main_quit()
+ elif SYSTEM=="android":
+ sys.exit(0)
+
+def jscommunicate(string):
+ pass
+def jsdefine(func, args, body):
+ global jsdefs, jsfunctions
+ if not func in jsdefs:
+ jsfunctions = jsfunctions+"function "+func+args+" {\n"+body+"\n};\n"
+ jsdefs.append(func)