import gtkimport gtk.gladeimport weakreffrom cairo import *# TODO Petites constantes pourries (1)HEIGHT=9WIDTH=9SHEIGHT=3SWIDTH=3ZNUMBER=9def rgb_to_hsv(h,s,v): if s == 0.0: return ((v,v,v)); else: i = int(h/60.0) % 6 f = h/60 - i p,q,t = v*(1-s),v*(1-(s*f)),v*(1-s*(1-f)) return([(v,t,p),(q,v,p),(p,v,t),(p,q,v),(t,p,v),(v,p,q)][i])COLOR=[rgb_to_hsv(float(i*360)/ZNUMBER,1.0,1.0) for i in xrange(ZNUMBER)]class SudoGrid: """ Coordonnees des elements d'une grille evoluee (en fonction d'une grille standard) """ def __init__(self): self.grid = [[(c,l) for l in xrange(HEIGHT)] for c in xrange(WIDTH)] self.partitions = [SudoPartition(i) for i in xrange(3)] def apply(gridswap): self.grid[gridswap[0][0],gridswap[0][1]], \ self.grid[gridswap[1][0],gridswap[1][1]] = \ self.grid[gridswap[1][0],gridswap[1][1]], \ self.grid[gridswap[0][0],gridswap[0][1]]class SudoPartition(list): def __init__(self, partitiontype): if partitiontype == 0: self.extend([[(c,l) for l in xrange(HEIGHT)] for c in xrange(WIDTH)]) else: if partitiontype == 1: self.extend([[(c,l) for c in xrange(WIDTH)] for l in xrange(HEIGHT)]) else: self.extend([[(bc+c,bl+l) for c in xrange(SWIDTH) for l in xrange(SHEIGHT)] for bl in xrange(0,HEIGHT,SHEIGHT) for bc in xrange(0,WIDTH,SWIDTH)])"""class SudoGridSwap(list): Liste de couples de coordonnees (permet de stocker des permutations d'elements d'une SudoGrid)"""class SudoGridFace(gtk.DrawingArea): """ Widget GTK ecrit en Cairo pour afficher une SudoGrid """ def __init__(self, sudogrid, partitiontype): self.draw_arrow = False super(SudoGridFace,self).__init__() self.sudogrid = sudogrid() self.ptype = partitiontype self.connect("expose_event",self.expose) self.connect("motion_notify_event", self.motion_notify) self.connect("button_press_event", self.button_press) self.connect("button_release_event", self.button_release) self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK) def launch_draw(self,widget): context = widget.window.cairo_create() rect = self.get_allocation() context.rectangle(0, 0, rect.width, rect.height) context.clip() context.save() context.scale(rect.width, rect.height) self.draw(context) def motion_notify(self,widget,event): if self.draw_arrow: self.arrow_end_x, self.arrow_end_y = event.x, event.y self.launch_draw(widget) def button_press(self,widget,event): self.draw_arrow = True self.arrow_start_x, self.arrow_start_y = event.x, event.y def button_release(self,widget,event): self.draw_arrow = False self.launch_draw(widget) def expose(self, widget, event): self.launch_draw(widget) def draw(self,context): # TODO Petites constantes pourries (2) margin=0.02 line_width=0.005 height = float(HEIGHT) * (1 + 2.0*margin) width = float(WIDTH) * (1 + 2.0*margin) rheight = (1 - 2.0*margin) / float(HEIGHT) rwidth = (1 - 2.0*margin) / float(WIDTH) # Rectangle dans lequel on affiche la SudoGrid context.rectangle(margin, margin, 1.0-2*margin, 1.0-2*margin) context.set_line_width(5*line_width) context.set_source_rgb(0,0,0) context.stroke() context.select_font_face ("Sans", FONT_SLANT_NORMAL) context.set_font_size(0.5/HEIGHT) # On affiche le contenu de chaque case for i,p in enumerate(self.sudogrid.partitions[self.ptype]): for v in p: context.set_source_rgb(COLOR[i][0],COLOR[i][1],COLOR[i][2]) x = v[0] * rwidth + margin y = v[1] * rheight + margin context.rectangle(x,y,rwidth,rheight) context.fill() text = str(v[0]+1)+str(v[1]+1) fxb,fyb,fw,fh,fxa,fya = context.text_extents(text) tx = x + rwidth/2.0 - (fw/2 + fxb) ty = y + rheight/2.0 - (fh/2 + fyb) context.move_to(tx,ty) context.set_source_rgb(0,0,0) context.show_text(text) # Contours des cases context.set_line_width(line_width) context.set_source_rgb(0,0,0) for c in range(1,WIDTH): currentx = c*rwidth + margin context.move_to(currentx, margin) context.line_to(currentx, 1.0-margin) for l in range(1,HEIGHT): currenty = l * rheight + margin context.move_to(margin, currenty) context.line_to(1.0-margin, currenty) context.stroke() if self.draw_arrow == True: context.restore() context.set_source_rgba(1.0,1.0,1.0,0.5) context.set_line_width(8) context.move_to(self.arrow_start_x, self.arrow_start_y) context.line_to(self.arrow_end_x, self.arrow_end_y) context.stroke()def main(): window = gtk.Window() window.set_title("Oops!") window.set_default_size(900,300) table = gtk.Table(1,3) window.add(table) faces = list() sudogrid=SudoGrid() for i in range(0,3): faces.append(SudoGridFace(weakref.ref(sudogrid),i)) table.attach(faces[i],i,i+1,0,1) print(str(i)) window.connect("destroy",gtk.main_quit) window.show_all() gtk.main()if __name__ == "__main__": main()