--- /dev/null
+#!/usr/bin/env python
+
+import pygtk
+import gtk
+import os
+
+def page_cmp(a,b):
+ if a < b:
+ return -1
+ if a > b:
+ return 1
+ return 0
+
+def inc_name(a):
+ l = len(a)
+ while l > 0 and a[l-1] >= '0' and a[l-1] <= '9':
+ l -= 1
+ # a[l:] is the last number
+ if l == len(a):
+ # there is no number
+ return a + ".1"
+ num = 0 + int(a[l:])
+ return a[0:l] + ("%d" % (num+1))
+
+class ScribblePad:
+
+ def __init__(self):
+ window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ window.connect("destroy", self.close_application)
+ window.set_title("ScribblePad")
+ #window.set_size_request(480,640)
+
+ vb = gtk.VBox()
+ window.add(vb)
+ vb.show()
+
+ bar = gtk.HBox()
+ vb.add(bar)
+ bar.show()
+
+ page = gtk.DrawingArea()
+ page.set_size_request(480,540)
+ vb.add(page)
+ page.show()
+
+ # Now the widgets:
+ # < > R u r A D C name
+ #back = gtk.Button(stock = gtk.STOCK_GO_BACK) ; back.show()
+ #fore = gtk.Button(stock = gtk.STOCK_GO_FORWARD) ; fore.show()
+ #red = gtk.ToggleButton("red"); red.show()
+ #undo = gtk.Button(stock = gtk.STOCK_UNDO) ; undo.show()
+ #redo = gtk.Button(stock = gtk.STOCK_REDO) ; redo.show()
+ #add = gtk.Button(stock = gtk.STOCK_ADD) ; add.show()
+ #delete = gtk.Button(stock = gtk.STOCK_REMOVE) ; delete.show()
+ #clear = gtk.Button(stock = gtk.STOCK_CLEAR) ; clear.show()
+ #name = gtk.Label("1.2.3.4.5") ; name.show()
+
+ back = gtk.Button("<") ; back.show()
+ fore = gtk.Button(">") ; fore.show()
+ red = gtk.ToggleButton("red"); red.show()
+ undo = gtk.Button("u") ; undo.show()
+ redo = gtk.Button("r") ; redo.show()
+ add = gtk.Button("+") ; add.show()
+ delete = gtk.Button("-") ; delete.show()
+ clear = gtk.Button("C") ; clear.show()
+ name = gtk.Label("1.2.3.4.5") ; name.show()
+
+ bar.add(back)
+ bar.add(fore)
+ bar.add(red)
+ bar.add(undo)
+ bar.add(redo)
+ bar.add(add)
+ bar.add(delete)
+ bar.add(clear)
+ bar.add(name)
+
+ back.connect("clicked", self.back)
+ fore.connect("clicked", self.fore)
+ red.connect("toggled", self.colour_change)
+ undo.connect("clicked", self.undo)
+ redo.connect("clicked", self.redo)
+ add.connect("clicked", self.add)
+ delete.connect("clicked", self.delete)
+ clear.connect("clicked", self.clear)
+ self.name = name
+ self.page = page
+ self.line = None
+ self.lines = []
+ self.hist = [] # undo history
+
+
+ page.connect("button_press_event", self.press)
+ page.connect("button_release_event", self.release)
+ page.connect("motion_notify_event", self.motion)
+ page.connect("expose-event", self.refresh)
+ page.set_events(gtk.gdk.EXPOSURE_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK
+ | gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK)
+
+ window.show()
+ colourmap = page.get_colormap()
+ black = gtk.gdk.color_parse("black")
+ red = gtk.gdk.color_parse("red")
+ self.colour_black = page.window.new_gc()
+ self.colour_black.line_width = 2
+ self.colour_black.set_foreground(colourmap.alloc_color(black))
+
+ self.colour_red = page.window.new_gc()
+ self.colour_red.line_width = 2
+ self.colour_red.set_foreground(colourmap.alloc_color(red))
+
+ self.colour = self.colour_black
+ self.colourname = "black"
+ self.bg = page.get_style().bg_gc[gtk.STATE_NORMAL]
+
+ self.page_dir = os.environ['HOME'] + '/Pages'
+ self.load_pages()
+
+ window.show()
+
+ def close_application(self, widget):
+ self.save_page()
+ gtk.main_quit()
+
+ def load_pages(self):
+ try:
+ os.mkdir(self.page_dir)
+ except:
+ pass
+ self.names = os.listdir(self.page_dir)
+ if len(self.names) == 0:
+ self.names.append("1")
+ self.names.sort(page_cmp)
+ self.pages = {}
+ self.pagenum = 0
+ self.load_page()
+ return
+
+ def press(self, c, ev):
+ # Start a new line
+
+ self.line = [ self.colourname, [int(ev.x), int(ev.y)] ]
+ return
+ def release(self, c, ev):
+ #FIXME ignore line if only one dot.
+ if self.line:
+ self.lines.append(self.line)
+ self.line = None
+ return
+ def motion(self, c, ev):
+ if self.line:
+ if ev.is_hint:
+ x, y, state = ev.window.get_pointer()
+ else:
+ x = ev.x
+ y = ev.y
+ x = int(x)
+ y = int(y)
+ prev = self.line[-1]
+ c.window.draw_line(self.colour, prev[0],prev[1],x,y)
+ self.line.append([x,y])
+ return
+
+ def refresh(self, area, ev):
+ self.redraw()
+ def redraw(self):
+ self.name.set_text(self.names[self.pagenum])
+ self.page.window.draw_rectangle(self.bg, True, 0, 0,
+ 480,640)
+ for l in self.lines:
+ if l[0] == "red":
+ col = self.colour_red
+ else:
+ col = self.colour_black
+ st = l[1]
+ for p in l[2:]:
+ self.page.window.draw_line(col, st[0], st[1],
+ p[0],p[1])
+ st = p
+ return
+
+ def back(self,b):
+ self.save_page()
+ if self.pagenum <= 0:
+ return
+ self.pagenum -= 1
+ self.load_page()
+ self.redraw()
+ return
+ def fore(self,b):
+ if self.pagenum >= len(self.names)-1:
+ return self.add(b)
+ self.save_page()
+ self.pagenum += 1
+ self.load_page()
+ self.redraw()
+
+ return
+ def colour_change(self,t):
+ if t.get_active():
+ self.colour = self.colour_red
+ self.colourname = "red"
+ else:
+ self.colour = self.colour_black
+ self.colourname = "black"
+ return
+ def undo(self,b):
+ if len(self.lines) == 0:
+ return
+ self.hist.append(self.lines.pop())
+ self.redraw()
+ return
+ def redo(self,b):
+ if len(self.hist) == 0:
+ return
+ self.lines.append(self.hist.pop())
+ self.redraw()
+ return
+ def add(self,b):
+ # New name is either
+ # - take last number and increment it
+ # - add .1
+ if len(self.lines) == 0:
+ # don't add after a blank page
+ return
+ self.save_page()
+ newname = self.names[self.pagenum]
+ while newname in self.pages:
+ new2 = inc_name(newname)
+ if new2 not in self.pages:
+ newname = new2
+ elif (newname + ".1") not in self.pages:
+ newname = newname + ".1"
+ else:
+ newname = newname + ".0.1"
+
+ self.names = self.names[0:self.pagenum+1] + [ newname ] + \
+ self.names[self.pagenum+1:]
+ self.pagenum += 1;
+ self.lines = []
+ self.redraw()
+ return
+ def delete(self,b):
+ if len(self.names) <= 1:
+ return
+ if len(self.lines) > 0:
+ return
+ self.save_page()
+ nm = self.names[self.pagenum]
+ if nm in self.pages:
+ del self.pages[nm]
+ self.names = self.names[0:self.pagenum] + self.names[self.pagenum+1:]
+ if self.pagenum >= len(self.names):
+ self.pagenum -= 1
+ self.load_page()
+ self.redraw()
+
+ return
+ def clear(self,b):
+ while len(self.lines) > 0:
+ self.hist.append(self.lines.pop())
+ self.redraw()
+ return
+
+ def parseline(self, l):
+ # string in "", or num,num. ':' separates words
+ words = l.strip().split(':')
+ line = []
+ for w in words:
+ if w[0] == '"':
+ w = w[1:-1]
+ elif w.find(',') >= 0:
+ n = w.find(',')
+ x = int(w[:n])
+ y = int(w[n+1:])
+ w = [x,y]
+ line.append(w)
+ return line
+
+ def load_page(self):
+ nm = self.names[self.pagenum]
+ if nm in self.pages:
+ if self.names[self.pagenum] in self.pages:
+ self.lines = self.pages[self.names[self.pagenum]]
+ return
+ self.lines = [];
+ try:
+ f = open(self.page_dir + "/" + self.names[self.pagenum], "r")
+ except:
+ f = None
+ if f:
+ l = f.readline()
+ while len(l) > 0:
+ self.lines.append(self.parseline(l))
+ l = f.readline()
+ f.close()
+ return
+
+ def save_page(self):
+ self.pages[self.names[self.pagenum]] = self.lines
+ fn = self.page_dir + "/" + self.names[self.pagenum]
+ if len(self.lines) == 0:
+ try:
+ os.unlink(fn)
+ except:
+ pass
+ return
+ f = open(fn, "w")
+ for l in self.lines:
+ start = True
+ if not l:
+ continue
+ for w in l:
+ if not start:
+ f.write(":")
+ start = False
+ if isinstance(w, str):
+ f.write('"%s"' % w)
+ elif isinstance(w, list):
+ f.write("%d,%d" %( w[0],w[1]))
+ f.write("\n")
+ f.close()
+
+def main():
+ gtk.main()
+ return 0
+if __name__ == "__main__":
+ ScribblePad()
+ main()
+