more objectifying add/update book form
[public/library.git] / bookForm.py
1 import curses
2
3
4
5
6
7 class bookForm:
8     mx = my = 0
9     hl = 0
10     bt = -1
11     cursor = 0
12     left = 0
13     top = 2
14     row = 2
15     caption = "Add a Book"
16     blabel = "Add"
17     labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
18               "Publisher", "Publish Date", "Publish Year", "Publish Month", "Publish location",
19               "Pages", "Pagination", "Weight"]
20     entries = []
21
22     def __init__(self,window,book={}):
23         self.w = window
24         self.w.resize(len(self.labels)+6,50)
25         self.updateEntries(book)
26         self.updateGeometry()
27
28     def updateGeometry(self):
29         (self.my, self.mx) = self.w.getmaxyx()
30         for l in self.labels:
31             self.left = max(len(l),self.left)
32         self.left += 2
33         self.width = self.mx-self.left-2
34         self.top = 2
35         # next, the buttons
36         self.bcol = [self.mx-len(self.blabel)-14, self.mx-len(self.blabel)-4]
37         self.bwidth = [8,len(self.blabel)+2]
38
39     def updateEntries(self,book):
40         self.entries=[]
41         for l in self.labels:
42             if l.lower() in book:
43                 self.entries.append(book[l.lower()])
44             else:
45                 self.entries.append("")
46
47     def refresh(self):
48         self.updateGeometry()
49         self.w.box()
50         self.w.addstr(0,(self.mx-len(self.caption))/2,self.caption)
51         r=self.top
52         for l,v in zip(self.labels,self.entries):
53             c = self.left-len(l)-2
54             self.w.addstr(r,c,l+":")
55             self.w.addnstr(r,self.left,v,self.width)
56             r+=1
57         self.w.addstr(r+1,self.bcol[0], "<cancel>  <"+self.blabel+">")
58         self.w.refresh()
59
60     def highlight(self):
61         if self.bt == -1:
62             self.w.chgat(self.row, self.left, self.width, curses.A_UNDERLINE)
63             self.cursor = len(self.entries[self.hl])
64             self.w.move(self.row, self.left+self.cursor)
65             curses.curs_set(1)
66         else:
67             self.w.chgat(self.row, self.bcol[self.bt], self.bwidth[self.bt], curses.A_REVERSE)
68             curses.curs_set(0)
69
70     def unHighlight(self):
71         self.w.chgat(self.row,1,self.mx-2,curses.A_NORMAL)
72
73     def mvHighlight(self,delta):
74         self.unHighlight()
75         new = self.hl+delta
76         new = max(new,0)
77         new = min(new,len(self.labels))   # the extra is for the buttons
78         self.hl = new
79         self.row = self.hl + self.top
80         if new == len(self.labels):
81             self.bt+=1
82             self.bt = min(self.bt,1)
83             self.row+=1
84         else:
85             self.bt=-1
86         self.highlight()
87
88     def eventLoop(self):
89         self.w.keypad(1)
90         self.refresh()
91         self.highlight()
92
93         ch = self.w.getch()
94         while ch != 27:
95             if ch==curses.KEY_UP:
96                 self.mvHighlight(-1)
97             elif ch==curses.KEY_PPAGE:
98                 self.mvHighlight(-len(self.labels))
99             elif ch==curses.KEY_DOWN:
100                 self.mvHighlight(+1)
101             elif ch==curses.KEY_NPAGE:
102                 self.mvHighlight(+len(self.labels))
103             self.w.refresh()
104             ch = self.w.getch()
105         
106
107
108 def test(stdscr):
109     w = curses.newwin(10,10,10,10)
110     bf = bookForm(w)
111     bf.eventLoop()
112
113 curses.wrapper(test)
114
115 # items is a list of (label, value) pairs
116 def redrawForm(w, caption, items, buttonlabel, m):
117     (y,x)=w.getmaxyx()
118     w.border()
119     curses.curs_set(1)
120     w.addstr(1,1,caption)
121     r=3
122     for l,v in items:
123         c = m-len(l)-2
124         w.addstr(r,c,l+":")
125         w.addstr(r,m,v)
126         r+=2
127     w.addstr(r,x-len(buttonlabel)-len("<cancel>")-6, "<cancel>  <"+buttonlabel+">")
128     w.refresh()
129
130 def lists_to_dict(l1, l2):
131     book = {}
132     for k,v in zip(l1,l2):
133         if v!="" and k.lower()!="publish date":
134             book[k.lower()]=v
135     return book
136
137
138 #the final form for book data entry - takes caption and book info.
139 def bookForm(caption, book, buttonlabel):
140     labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
141               "Publisher", "Publish Date", "Publish Year", "Publish Month", "Publish location",
142               "Pages", "Pagination", "Weight"]
143     entries = []
144     m = 0
145
146     w=curses.newwin(34,70,1,10)
147     (y,x)=w.getmaxyx()
148     w.keypad(1)
149     redrawForm(w,caption,zip(labels,entries),buttonlabel,m)
150     bcol = [x-len(buttonlabel)-len("<cancel>")-6, x-len(buttonlabel)-4]
151     bwidth = [8,len(buttonlabel)+2]
152     
153     highlight=0
154     b = -1
155     r=3
156     w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
157     w.move(r,m+len(entries[highlight]))
158     cursor = len(entries[highlight])
159     ch = w.getch()
160     while (1==1):
161         if ch==27: #escape key
162             curses.curs_set(0)
163             w.clear()
164             w.refresh()
165             return {}
166         if ch==curses.KEY_UP:
167             if highlight == len(labels):
168                 w.chgat(r,bcol[b],bwidth[b],curses.A_NORMAL)
169                 highlight = len(labels)-1
170                 b = -1
171                 r=3+2*highlight
172                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
173                 cursor = len(entries[highlight])
174                 w.move(r,m+cursor)
175                 curses.curs_set(1)
176             elif highlight!=0:
177                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
178                 highlight -= 1
179                 r=3+2*highlight
180                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
181                 cursor = len(entries[highlight])
182                 w.move(r,m+cursor)
183         elif ch==curses.KEY_PPAGE:
184             w.chgat(r,m,x-m-2,curses.A_NORMAL)
185             highlight=0
186             b=-1
187             r=3+2*highlight
188             w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
189             cursor = len(entries[highlight])
190             w.move(r,m+cursor)
191             curses.curs_set(1)
192         elif ch==curses.KEY_DOWN:
193             if highlight >= len(labels) -1:
194                 highlight = len(labels)
195                 b += 1
196                 b = min(b,1)
197                 curses.curs_set(0)
198                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
199                 r = y-3
200                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
201             else:
202                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
203                 highlight += 1
204                 r=3+2*highlight
205                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
206                 cursor = len(entries[highlight])
207                 w.move(r,m+cursor)
208         elif ch==curses.KEY_NPAGE:
209             if highlight!=len(labels):
210                 highlight = len(labels)
211                 b += 1
212                 b = min(b,1)
213                 curses.curs_set(0)
214                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
215                 r = y-3
216                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
217         elif ch==curses.KEY_LEFT:
218             if highlight == len(labels):
219                 w.chgat(r,bcol[b],bwidth[b],curses.A_NORMAL)
220                 b=0
221                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
222             else:
223                 if cursor>0:
224                     cursor-=1
225                     w.move(r,m+cursor)
226         elif ch==curses.KEY_RIGHT:
227             if highlight == len(labels):
228                 w.chgat(r,bcol[b],bwidth[b],curses.A_NORMAL)
229                 b=1
230                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
231             else:
232                 if cursor < len(entries[highlight]):
233                     cursor+=1
234                     w.move(r,m+cursor)
235         elif ch>31 and ch<127:
236             if highlight != len(labels):
237                 entries[highlight]=entries[highlight][:cursor] + curses.keyname(ch) + entries[highlight][cursor:]
238                 cursor+=1
239                 w.addnstr(r,m, entries[highlight]+(" "*40), x-m-2)
240                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
241                 w.move(r,m+cursor)
242         elif ch==curses.KEY_BACKSPACE:
243             if highlight != len(labels) and cursor!=0:
244                 cursor-=1
245                 entries[highlight]=entries[highlight][:cursor] + entries[highlight][cursor+1:]
246                 w.addnstr(r,m, entries[highlight]+(" "*40), x-m-2)
247                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
248                 w.move(r,m+cursor)
249         elif ch==curses.KEY_DC:
250             if highlight != len(labels):
251                 entries[highlight]=entries[highlight][:cursor] + entries[highlight][cursor+1:]
252                 w.addnstr(r,m, entries[highlight]+(" "*40), x-m-2)
253                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
254                 w.move(r,m+cursor)
255         elif ch==curses.KEY_HOME:
256             if highlight != len(labels):
257                 cursor=0
258                 w.move(r,m+cursor)
259         elif ch==curses.KEY_END:
260             if highlight != len(labels):
261                 cursor=len(entries[highlight])
262                 w.move(r,m+cursor)
263         elif ch==10:
264             if b != -1:
265                 if b == 0:
266                     w.clear()
267                     w.refresh()
268                     return {}
269                 elif b == 1:
270                     w.clear()
271                     w.refresh()
272                     return lists_to_dict(labels,entries)
273             elif highlight == len(labels)-1:
274                 highlight = len(labels)
275                 b=0
276                 curses.curs_set(0)
277                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
278                 r = y-3
279                 w.chgat(r,bcol[b],bwidth[b],curses.A_REVERSE)
280             else:
281                 w.chgat(r,m,x-m-2,curses.A_NORMAL)
282                 highlight += 1
283                 r=3+2*highlight
284                 w.chgat(r,m,x-m-2,curses.A_UNDERLINE)
285                 cursor = len(entries[highlight])
286                 w.move(r,m+cursor)
287
288
289         w.refresh()
290         ch = w.getch()
291
292     curses.curs_set(0)
293     w.clear()
294     w.refresh()
295     return {}