Text entry allows wider strings, and fixed code
authorJohn Ladan <jladan@uwaterloo.ca>
Fri, 25 Oct 2013 19:33:49 +0000 (15:33 -0400)
committerJohn Ladan <jladan@uwaterloo.ca>
Fri, 25 Oct 2013 19:33:49 +0000 (15:33 -0400)
browser.py
gui.py
librarian.py

index 2db9e49..8251157 100644 (file)
@@ -1,7 +1,7 @@
 import sys
 import curses
 import db_layer as db
-from form import bookForm,categoryForm
+from gui import BookForm,CategoryForm
 
 class browserWindow:
     hl=0
@@ -259,11 +259,11 @@ class trashBrowser(browserWindow):
     def viewSelection(self,book):
         bookid = book['id']
         w=curses.newwin(1,1,20,20)
-        bf = bookForm(w,self.hb,book)
+        bf = BookForm(w,self.hb,book)
         self.centreChild(w)
         bf.caption='Viewing Book '+str(bookid)
         bf.blabel='done'
-        bf.eventLoop()
+        bf.event_loop()
         bf.clear()
 
     def restoreSelected(self):
@@ -325,11 +325,11 @@ class bookBrowser(browserWindow):
         bookid = book['id']
         
         w=curses.newwin(1,1)
-        bf=bookForm(w,self.hb,book)
+        bf=BookForm(w,self.hb,book)
         self.centreChild(w)
         bf.caption='Update Book '+str(bookid)
         bf.blabel='update'
-        newbook = bf.eventLoop()
+        newbook = bf.event_loop()
         if len(newbook)!=0:
             db.updateBook(newbook,bookid)
         bf.clear()
@@ -337,11 +337,11 @@ class bookBrowser(browserWindow):
     def viewSelection(self,book):
         bookid = book['id']
         w=curses.newwin(1,1,20,20)
-        bf = bookForm(w,self.hb,book)
+        bf = BookForm(w,self.hb,book)
         self.centreChild(w)
         bf.caption='Viewing Book '+str(bookid)
         bf.blabel='done'
-        bf.eventLoop()
+        bf.event_loop()
         bf.clear()
 
     def categorizeSelection(self,book):
@@ -407,9 +407,9 @@ class categoryBrowser(browserWindow):
 
     def addCategory(self):
         w = curses.newwin(1,1,10,10)
-        cf = categoryForm(w,self.hb)
+        cf = CategoryForm(w,self.hb)
         self.centreChild(w)
-        cats = cf.eventLoop()
+        cats = cf.event_loop()
         for c in cats:
             db.addCategory(c)
         cf.clear()
@@ -481,9 +481,9 @@ class categorySelector(browserWindow):
 
     def addCategory(self):
         w = curses.newwin(1,1,10,10)
-        cf = categoryForm(w,self.hb)
+        cf = CategoryForm(w,self.hb)
         self.centreChild(w)
-        cats = cf.eventLoop()
+        cats = cf.event_loop()
         for c in cats:
             db.addCategory(c)
         cf.clear()
diff --git a/gui.py b/gui.py
index 0e35764..4be00a6 100644 (file)
--- a/gui.py
+++ b/gui.py
 import curses
 import sys
 
-class textEntry:
+
+class TextEntry:
+
+    """A part of a window that handles text entry.
+    Properties:
+        value holds the string that was entered
+    
+    Public Methods:
+        set_geom(row,column,width)  Sets the geometry in the window
+        set_value(string)           Set the value and redraw
+        gain_focus()                Gives it focus, moving cursor and changing the drawing
+        lose_focus()                Takes focus, moving cursor to start, changing drawing
+        handle_input(ch)            Pass this the ncurses key, and it manages input
+        redraw()                    Redraw the text entry (should never need to do this
+        """
+
+    # Public
+    value = ""  # Use the set_value function to set, but retrieve with value
+
+    # Should be Private
     cursor = 0
     start = 0
     focus = False
     x = 0
     y = 0
     width = 10
-    value = ""
 
     def __init__(self, parent_window, value=""):
         self.w = parent_window
         self.value = value
 
-    def setGeom(self,y,x,width):
+    def set_geom(self,y,x,width):
         self.x = x
         self.y = y
         self.width = width
 
-    def redraw(self):
-        self.w.addnstr(self.y,self.x, self.value[self.start:]+" "*self.width, self.width)
-        if self.focus:
-            self.w.chgat(self.y, self.x, self.width, curses.A_UNDERLINE)
-            curses.curs_set(1)
+    def set_value(self,v):
+        self.value=v
+        self.cursor=len(v)
+        self.redraw()
 
-    def gainFocus(self):
-        sys.stderr.write('I have focus!\n')
+    def gain_focus(self):
+        #sys.stderr.write('I have focus!\n')
         self.focus = True
-        self.mvCursor(+len(self.value))
+        self._mv_cursor(+len(self.value))
         self.start = max(0,self.cursor-self.width) 
         self.redraw()
 
-    def loseFocus(self):
+    def lose_focus(self):
         self.focus = False
         self.cursor = 0
         self.start = 0
         self.redraw()
     
-    def mvCursor(self,delta):
-        n = self.cursor + delta
-        # make sure new position is legal
-        n = max(n,0)
-        n = min(n,len(self.value))
-        self.cursor = n
+    def handle_input(self,ch):
+        if ch==curses.KEY_LEFT:
+            self._mv_cursor(-1)
+        elif ch==curses.KEY_HOME:
+            self._set_cursor(0)
+        elif ch==curses.KEY_RIGHT:
+            self._mv_cursor(+1)
+        elif ch==curses.KEY_END:
+            self._set_cursor(len(self.value))
+        elif ch>=32 and ch<=126:
+            self._insert(curses.keyname(ch).decode('utf-8'))
+        elif ch==curses.KEY_BACKSPACE:
+            self._backspace()
+        elif ch==curses.KEY_DC:
+            self._delete()
+
+    def redraw(self):
+        self.w.addnstr(self.y,self.x, self.value[self.start:]+" "*self.width, self.width)
+        if self.focus:
+            self.w.chgat(self.y, self.x, self.width, curses.A_UNDERLINE)
+            curses.curs_set(1)
+
+    # Private functions
+    def _mv_cursor(self,delta):
+        self._set_cursor(self.cursor + delta)
+    
+    def _set_cursor(self, new_c):
+        self.cursor = max(0, min(len(self.value), new_c))
         self.start = max(0,self.cursor-self.width+1) 
         self.redraw()
+        # Place the drawn cursor in the correct spot
         col = self.x + self.cursor - self.start
         self.w.move(self.y,col)
 
-    def insert(self,ch):
+    def _insert(self,ch):
         c = self.cursor
         self.value = self.value[:c] +ch+  self.value[c:]
-        self.mvCursor(+1)
+        self._mv_cursor(+1)
 
-    def backspace(self):
+    def _backspace(self):
         if self.cursor>0:
             c = self.cursor
             self.value=self.value[:c-1] + self.value[c:]
-            self.mvCursor(-1)
+            self._mv_cursor(-1)
 
-    def delete(self):
+    def _delete(self):
         c = self.cursor
         self.value = self.value[:c] + self.value[c+1:]
-        self.mvCursor(0)
+        self._mv_cursor(0)
 
-    def handle_input(self,ch):
-        if ch==curses.KEY_LEFT:
-            self.mvCursor(-1)
-        elif ch==curses.KEY_HOME:
-            self.mvCursor(-len(self.value))
-        elif ch==curses.KEY_RIGHT:
-            self.mvCursor(+1)
-        elif ch==curses.KEY_END:
-            self.mvCursor(+len(self.value))
 
-        elif ch>=32 and ch<=126:
-            self.insert(curses.keyname(ch))
-        elif ch==curses.KEY_BACKSPACE:
-            self.backspace()
-        elif ch==curses.KEY_DC:
-            self.delete()
 
+class FormWindow:
 
+    """General class for a Form Window.
+    
+    To use, make the window for it, call the constructor, then call event_loop.
+    """
 
-class formWindow:
+    # Private variables
     mx = my = 0
     hl = 0
     bt = -1
@@ -94,27 +124,51 @@ class formWindow:
     caption = "Form"
     blabel = "Done"
     labels = ["label1"]
-    entries=[]
 
     commands = [('pU', 'top'),('pD', 'bottom'),('Es', 'cancel')]
 
-    def clear(self):
-        self.w.erase()
-        self.w.refresh()
 
+    # Public functions
     def __init__(self,window,helpbar,book={}):
         self.w = window
         self.w.resize(len(self.labels)+6,50)
         self.hb = helpbar
-        self.makeEntries()
-        self.updateGeometry()
-        self.updateEntries(book)
+        self._make_entries()
+        self._update_geometry()
+        self._set_entries(book)
 
-    def makeEntries(self):
+    def clear(self):
+        self.w.erase()
+        self.w.refresh()
+
+    def event_loop(self):
+        self.w.keypad(1)
+        self.refresh()
+        self.hl=0;
+        self.entries[self.hl].gain_focus()
+
+        ch = self.w.getch()
+        while ch != 27:
+            #sys.stderr.write(curses.keyname(ch).decode('utf-8'))
+            self.handle_input(ch)
+            if ch==10 or ch==curses.KEY_ENTER:
+                if self.bt==0:
+                    return {}
+                elif self.bt==1:
+                    return self.return_values()
+                else:
+                    self._mv_focus(+1)
+            self.w.refresh()
+            ch = self.w.getch()
+        curses.curs_set(0)
+        return {}
+
+    def _make_entries(self):
+        self.entries = []
         for e in range(len(self.labels)):
-            self.entries.append(textEntry(self.w))
+            self.entries.append(TextEntry(self.w))
 
-    def updateGeometry(self):
+    def _update_geometry(self):
         (self.my, self.mx) = self.w.getmaxyx()
         self.left=0
         for l in self.labels:
@@ -123,21 +177,21 @@ class formWindow:
         width = self.mx-self.left-2
         self.top = 2
         for r in range(len(self.entries)):
-            self.entries[r].setGeom(r+self.top, self.left, width)
+            self.entries[r].set_geom(r+self.top, self.left, width)
         # next, the buttons
         self.brow = self.top+len(self.labels)+1
         self.bcol = [self.mx-len(self.blabel)-14, self.mx-len(self.blabel)-4]
         self.bwidth = [8,len(self.blabel)+2]
 
-    def updateEntries(self,book):
+    def _set_entries(self,book):
         e = 0
         for l in self.labels:
-            sys.stderr.write('updating label: '+l+'\n')
+            #sys.stderr.write('updating label: '+l+'\n')
             if l.lower() in book:
-                sys.stderr.write('   '+l+' found\n')
+                #sys.stderr.write('   '+l+' found\n')
                 self.entries[e].value = str(book[l.lower()])
             else:
-                sys.stderr.write('   '+l+' notfound\n')
+                #sys.stderr.write('   '+l+' notfound\n')
                 self.entries[e].value = ""
             e += 1 
 
@@ -156,89 +210,67 @@ class formWindow:
     def refresh(self):
         self.hb.commands = self.commands
         self.hb.refresh()
-        self.updateGeometry()
+        self._update_geometry()
         self.redraw()
 
-    def highlightButton(self):
+    def _highlight_button(self):
         self.w.chgat(self.brow, self.bcol[self.bt], self.bwidth[self.bt], curses.A_REVERSE)
         curses.curs_set(0)
 
-    def unHighlightButton(self):
+    def _unhighlight_button(self):
         self.w.chgat(self.brow,1,self.mx-2,curses.A_NORMAL)
 
-    def mvFocus(self,delta):
+    def _mv_focus(self,delta):
         if self.bt==-1:
-            self.entries[self.hl].loseFocus()
+            self.entries[self.hl].lose_focus()
         else:
-            self.unHighlightButton()
+            self._unhighlight_button()
         new = self.hl+delta
-        new = max(new,0)
-        new = min(new,len(self.labels))   # the extra is for the buttons
+        new = max(0, min(len(self.labels), new))   # the extra is for the buttons
         self.hl = new
         if new == len(self.labels):
             self.bt = 1
             self.bt = min(self.bt,1)
-            self.highlightButton()
+            self._highlight_button()
         else:
             self.bt=-1
-            self.entries[self.hl].gainFocus()
+            self.entries[self.hl].gain_focus()
 
 
-    def returnValues(self):
+    def _return_values(self):
         book = {}
         for k,e in zip(self.labels, self.entries):
             if v!="" and k.lower()!="publish date":
                 book[k.lower()]=e.value
         return book
 
-    def eventLoop(self):
-        self.w.keypad(1)
-        self.refresh()
-        self.hl=0;
-        self.entries[self.hl].gainFocus()
-
-        ch = self.w.getch()
-        while ch != 27:
-            self.handleInput(ch)
-            if ch==10 or ch==curses.KEY_ENTER:
-                if self.bt==0:
-                    return {}
-                elif self.bt==1:
-                    return self.returnValues()
-                else:
-                    self.mvFocus(+1)
-            self.w.refresh()
-            ch = self.w.getch()
-        curses.curs_set(0)
-        return {}
-
 
-    def handleInput(self,ch):
+    def handle_input(self,ch):
         if ch==curses.KEY_UP:
-            self.mvFocus(-1)
+            self._mv_focus(-1)
         elif ch==curses.KEY_PPAGE:
-            self.mvFocus(-len(self.labels))
+            self._mv_focus(-len(self.labels))
         elif ch==curses.KEY_DOWN:
-            self.mvFocus(+1)
+            self._mv_focus(+1)
         elif ch==curses.KEY_NPAGE:
-            self.mvFocus(+len(self.labels))
+            self._mv_focus(+len(self.labels))
         elif ch==curses.KEY_LEFT:
             if self.bt==-1:
                 self.entries[self.hl].handle_input(ch)
             else:
-                self.unHighlightButton()
+                self._unhighlight_button()
                 self.bt=0
-                self.highlightButton()
+                self._highlight_button()
         elif ch==curses.KEY_HOME:
             if self.bt==-1:
-                self.mvCursor(-len(self.entries[self.hl]))
+                self._mv_cursor(-len(self.entries[self.hl]))
         elif ch==curses.KEY_RIGHT:
             if self.bt==-1:
                 self.entries[self.hl].handle_input(ch)
             else:
-                self.unHighlightButton()
+                self._unhighlight_button()
                 self.bt=1
-                self.highlightButton()
+                self._highlight_button()
         else:
             if self.bt==-1:
                 self.entries[self.hl].handle_input(ch)
@@ -246,7 +278,7 @@ class formWindow:
         
         
 
-class bookForm(formWindow):
+class BookForm(FormWindow):
     caption = "Add a Book"
     blabel = "Add"
     labels = ["ISBN", "LCCN", "Title", "Subtitle", "Authors", "Edition",
@@ -262,31 +294,31 @@ class bookForm(formWindow):
     def lookup_lccn(self,lccn):
         return {'lccn':lccn}
 
-    def returnBook(self):
-        return self.returnValues()
+    def return_book(self):
+        return self.return_values()
 
-    def handleInput(self,ch):
+    def handle_input(self,ch):
         if ch==10 or ch==curses.KEY_ENTER:
             if self.hl==0:          # lookup by isbn
                 book = self.lookup_isbn(self.entries[0].value)
                 if book != {}:
-                    sys.stderr.write('updating entries\n')
-                    self.updateEntries(book)
+                    #sys.stderr.write('updating entries\n')
+                    self._set_entries(book)
                 self.refresh()
-                self.mvFocus(+7)
+                self._mv_focus(+7)
             if self.hl==1:          # lookup by lccn
                 book = self.lookup_lccn(self.entries[1].value)
                 if book != {}:
-                    self.updateEntries(book)
+                    self._set_entries(book)
                 self.refresh()
-                self.mvFocus(+6)
+                self._mv_focus(+6)
         else:
-            formWindow.handleInput(self,ch)
+            FormWindow.handle_input(self,ch)
 
-class categoryForm(formWindow):
+class CategoryForm(FormWindow):
     caption = "Add a Category"
     blabel = "Add"
     labels = ["Category"]
 
-    def returnValues(self):
+    def return_values(self):
         return self.entries
index 4677065..c4dc884 100755 (executable)
@@ -3,7 +3,7 @@
 import curses
 import db_layer as db
 import browser
-import form as form
+import gui as form
 import help_bar as helpBar
 
 import book_data
@@ -82,14 +82,14 @@ def redrawMenu(w,items,highlight):
 def addForm():
     w=curses.newwin(1,1)
     (my,mx)=stdscr.getmaxyx()
-    bf = form.bookForm(w,hb)
+    bf = form.BookForm(w,hb)
     (r,c)=w.getmaxyx()
     w.mvwin((my-r)//2,(mx-c)//2)
     bf.lookup_isbn=book_data.openLibrary_isbn
     bf.lookup_lccn=book_data.openLibrary_lccn
     bf.caption='Add a Book'
     bf.blabel = 'Add'
-    book = bf.eventLoop()
+    book = bf.event_loop()
     bf.clear()
     if len(book)!=0:
         db.addBook(book)