fixed some bugs
[public/library.git] / form.py
1 import curses
2
3 class formWindow:
4     mx = my = 0
5     hl = 0
6     bt = -1
7     cursor = 0
8     textStart = 0
9     left = 0
10     top = 2
11     row = 2
12     caption = "Form"
13     blabel = "Done"
14     labels = ["label1"]
15     entries = []
16
17     commands = [('pU', 'top'),('pD', 'bottom'),('Es', 'cancel')]
18
19     def clear(self):
20         self.w.erase()
21         self.w.refresh()
22
23     def __init__(self,window,helpbar,book={}):
24         self.w = window
25         self.w.resize(len(self.labels)+6,50)
26         self.hb = helpbar
27         self.updateEntries(book)
28         self.updateGeometry()
29
30     def updateGeometry(self):
31         (self.my, self.mx) = self.w.getmaxyx()
32         self.left=0
33         for l in self.labels:
34             self.left = max(len(l),self.left)
35         self.left += 4
36         self.width = self.mx-self.left-2
37         self.top = 2
38         # next, the buttons
39         self.bcol = [self.mx-len(self.blabel)-14, self.mx-len(self.blabel)-4]
40         self.bwidth = [8,len(self.blabel)+2]
41
42     def updateEntries(self,book):
43         self.entries=[]
44         for l in self.labels:
45             if l.lower() in book:
46                 self.entries.append(str(book[l.lower()]))
47             else:
48                 self.entries.append("")
49
50     def refresh(self):
51         self.hb.commands = self.commands
52         self.hb.refresh()
53         self.updateGeometry()
54         self.w.box()
55         self.w.addstr(0,(self.mx-len(self.caption))/2,self.caption)
56         r=self.top
57         for l in self.labels:
58             c = self.left-len(l)-2
59             self.w.addstr(r,c,l+":")
60             self.drawRow(r-self.top)
61             r+=1
62         self.w.addstr(r+1,self.bcol[0], "<cancel>  <"+self.blabel+">")
63         self.w.refresh()
64
65     def drawRow(self,row):
66         r = self.top + row
67         self.w.addnstr(r,self.left, self.entries[row]+" "*self.width, self.width)
68
69     def highlight(self):
70         if self.bt == -1:
71             self.w.chgat(self.row, self.left, self.width, curses.A_UNDERLINE)
72             self.mvCursor(0)
73             curses.curs_set(1)
74         else:
75             self.w.chgat(self.row, self.bcol[self.bt], self.bwidth[self.bt], curses.A_REVERSE)
76             curses.curs_set(0)
77
78     def unHighlight(self):
79         self.w.chgat(self.row,1,self.mx-2,curses.A_NORMAL)
80
81     def mvHighlight(self,delta):
82         self.unHighlight()
83         new = self.hl+delta
84         new = max(new,0)
85         new = min(new,len(self.labels))   # the extra is for the buttons
86         self.hl = new
87         self.row = self.hl + self.top
88         if new == len(self.labels):
89             self.bt =1
90             self.bt = min(self.bt,1)
91             self.row+=1
92         else:
93             self.mvCursor(+len(self.entries[self.hl]))
94             self.bt=-1
95         self.highlight()
96
97     def mvCursor(self,delta):
98         n = self.cursor + delta
99         n = max(n,0)
100         n = min(n,len(self.entries[self.hl]))
101         self.cursor = n
102         col = self.left + self.cursor - self.textStart
103         if col >= self.left and col < self.left+self.width:
104             self.w.move(self.row,col)
105
106     def insert(self,ch):
107         c = self.cursor
108         self.entries[self.hl]=self.entries[self.hl][:c] +ch+  self.entries[self.hl][c:]
109         self.drawRow(self.hl)
110         self.mvCursor(+1)
111         self.highlight()
112
113     def backspace(self):
114         if self.cursor>0:
115             self.entries[self.hl]=self.entries[self.hl][:self.cursor-1] + self.entries[self.hl][self.cursor:]
116             self.drawRow(self.hl)
117             self.mvCursor(-1)
118             self.highlight()
119
120     def delete(self):
121         c = self.cursor
122         self.entries[self.hl]=self.entries[self.hl][:c] + self.entries[self.hl][c+1:]
123         self.drawRow(self.hl)
124         self.highlight()
125
126     def returnValues(self):
127         book = {}
128         for k,v in zip(self.labels, self.entries):
129             if v!="" and k.lower()!="publish date":
130                 book[k.lower()]=v
131         return book
132
133     def eventLoop(self):
134         self.w.keypad(1)
135         self.refresh()
136         self.mvCursor(+len(self.entries[self.hl]))
137         self.highlight()
138
139         ch = self.w.getch()
140         while ch != 27:
141             self.handleInput(ch)
142             if ch==10 or ch==curses.KEY_ENTER:
143                 if self.bt==0:
144                     return {}
145                 elif self.bt==1:
146                     return self.returnValues()
147                 self.mvHighlight(+1)
148             self.w.refresh()
149             ch = self.w.getch()
150         curses.curs_set(0)
151         return {}
152
153
154     def handleInput(self,ch):
155         if ch==curses.KEY_UP:
156             self.mvHighlight(-1)
157         elif ch==curses.KEY_PPAGE:
158             self.mvHighlight(-len(self.labels))
159         elif ch==curses.KEY_DOWN:
160             self.mvHighlight(+1)
161         elif ch==curses.KEY_NPAGE:
162             self.mvHighlight(+len(self.labels))
163
164         elif ch==curses.KEY_LEFT:
165             if self.bt==-1:
166                 self.mvCursor(-1)
167             else:
168                 self.unHighlight()
169                 self.bt=0
170                 self.highlight()
171         elif ch==curses.KEY_HOME:
172             if self.bt==-1:
173                 self.mvCursor(-len(self.entries[self.hl]))
174         elif ch==curses.KEY_RIGHT:
175             if self.bt==-1:
176                 self.mvCursor(+1)
177             else:
178                 self.unHighlight()
179                 self.bt=1
180                 self.highlight()
181         elif ch==curses.KEY_END:
182             if self.bt==-1:
183                 self.mvCursor(+len(self.entries[self.hl]))
184
185         elif ch>=32 and ch<=126:
186             if self.bt==-1:
187                 self.insert(curses.keyname(ch))
188         elif ch==curses.KEY_BACKSPACE:
189             if self.bt==-1:
190                 self.backspace()
191         elif ch==curses.KEY_DC:
192             if self.bt==-1:
193                 self.delete()
194         
195         
196
197 class bookForm(formWindow):
198     caption = "Add a Book"
199     blabel = "Add"
200     labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
201               "Publisher", "Publish Date", "Publish Year", "Publish Month", "Publish location",
202               "Pages", "Pagination", "Weight"]
203     
204
205     # redefineable functions lookup is called when 'enter' is pressed on ISBN
206     # and returns the looked-up book. Default returns nothing
207     def lookup_isbn(self,isbn):
208         return {'isbn':isbn}
209     
210     def lookup_lccn(self,lccn):
211         return {'lccn':lccn}
212
213     def returnBook(self):
214         return self.returnValues()
215
216     def handleInput(self,ch):
217         if ch==10 or ch==curses.KEY_ENTER:
218             if self.hl==0:          # lookup by isbn
219                 book = self.lookup_isbn(self.entries[0])
220                 if book != {}:
221                     self.updateEntries(book)
222                 self.refresh()
223                 self.mvHighlight(+7)
224             if self.hl==1:          # lookup by lccn
225                 book = self.lookup_lccn(self.entries[1])
226                 if book != {}:
227                     self.updateEntries(book)
228                 self.refresh()
229                 self.mvHighlight(+6)
230         else:
231             formWindow.handleInput(self,ch)
232
233 class categoryForm(formWindow):
234     caption = "Add a Category"
235     blabel = "Add"
236     labels = ["Category"]
237
238     def returnValues(self):
239         return self.entries