#! /usr/bin/env python
class ArrayItem: def __init__(self, array, index, value): self.array = array self.index = index self.value = value x1, y1, x2, y2 = self.position() self.item = Rectangle(array.canvas, x1, y1, x2, y2, fill='red', outline='black', width=1) self.item.bind('<Button-1>', self.mouse_down) self.item.bind('<Button1-Motion>', self.mouse_move) self.item.bind('<ButtonRelease-1>', self.mouse_up) def delete(self): item = self.item self.array = None self.item = None item.delete() def mouse_down(self, event): self.lastx = event.x self.lasty = event.y self.origx = event.x self.origy = event.y self.item.tkraise() def mouse_move(self, event): self.item.move(event.x - self.lastx, event.y - self.lasty) self.lastx = event.x self.lasty = event.y def mouse_up(self, event): i = self.nearestindex(event.x) if i >= self.array.getsize(): i = self.array.getsize() - 1 if i < 0: i = 0 other = self.array.items[i] here = self.index self.array.items[here], self.array.items[i] = other, self self.index = i x1, y1, x2, y2 = self.position() self.item.coords(((x1, y1), (x2, y2))) other.setindex(here) def setindex(self, index): nsteps = steps(self.index, index) if not nsteps: return if self.array.speed == "fastest": nsteps = 0 oldpts = self.position() self.index = index newpts = self.position() trajectory = interpolate(oldpts, newpts, nsteps) self.item.tkraise() for pts in trajectory: self.item.coords((pts[:2], pts[2:])) self.array.wait(50) def swapwith(self, other): nsteps = steps(self.index, other.index) if not nsteps: return if self.array.speed == "fastest": nsteps = 0 myoldpts = self.position() otheroldpts = other.position() self.index, other.index = other.index, self.index mynewpts = self.position() othernewpts = other.position() myfill = self.item['fill'] otherfill = other.item['fill'] self.item.config(fill='green') other.item.config(fill='yellow') self.array.master.update() if self.array.speed == "single-step": self.item.coords((mynewpts[:2], mynewpts[2:])) other.item.coords((othernewpts[:2], othernewpts[2:])) self.array.master.update() self.item.config(fill=myfill) other.item.config(fill=otherfill) self.array.wait(0) return mytrajectory = interpolate(myoldpts, mynewpts, nsteps) othertrajectory = interpolate(otheroldpts, othernewpts, nsteps) if self.value > other.value: self.item.tkraise() other.item.tkraise() else: other.item.tkraise() self.item.tkraise() try: for i in range(len(mytrajectory)): mypts = mytrajectory[i] otherpts = othertrajectory[i] self.item.coords((mypts[:2], mypts[2:])) other.item.coords((otherpts[:2], otherpts[2:])) self.array.wait(50) finally: mypts = mytrajectory[-1] otherpts = othertrajectory[-1] self.item.coords((mypts[:2], mypts[2:])) other.item.coords((otherpts[:2], otherpts[2:])) self.item.config(fill=myfill) other.item.config(fill=otherfill) def compareto(self, other): myfill = self.item['fill'] otherfill = other.item['fill'] outcome = cmp(self.value, other.value) if outcome < 0: myflash = 'white' otherflash = 'black' elif outcome > 0: myflash = 'black' otherflash = 'white' else: myflash = otherflash = 'grey' try: self.item.config(fill=myflash) other.item.config(fill=otherflash) self.array.wait(500) finally: self.item.config(fill=myfill) other.item.config(fill=otherfill) return outcome def position(self): x1 = (self.index+1)*XGRID - WIDTH/2 x2 = x1+WIDTH y2 = (self.array.maxvalue+1)*YGRID y1 = y2 - (self.value)*YGRID return x1, y1, x2, y2 def nearestindex(self, x): return int(round(float(x)/XGRID)) - 1