Update TableView: cursor movement.
authorRadek Brich <radek.brich@devl.cz>
Sun, 09 Oct 2011 11:17:42 +0200
changeset 22 6ca8b2d221c3
parent 21 8553a6bd2d82
child 23 4e72fd2a0e14
Update TableView: cursor movement.
demo_tableview.py
tuikit/tableview.py
--- a/demo_tableview.py	Sat Oct 08 17:16:07 2011 +0200
+++ b/demo_tableview.py	Sun Oct 09 11:17:42 2011 +0200
@@ -16,7 +16,7 @@
 
         data = []
         for y in range(100):
-            row = [str(y)]
+            row = [str(y+1)]
             for x in range(10):
                 row.append('r{}:c{}'.format(y, x))
             data.append(row)
--- a/tuikit/tableview.py	Sat Oct 08 17:16:07 2011 +0200
+++ b/tuikit/tableview.py	Sun Oct 09 11:17:42 2011 +0200
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import math
+import logging
 
 from tuikit.widget import EventSource, Widget
 from tuikit.common import Coords
@@ -28,15 +29,18 @@
     
     '''Columns description.'''
     
-    def __init__(self, title='', expand=True, sizereq=1,
-        header=False, readonly=False, maxlength=None):
+    def __init__(self, title='', header=False, expand=True, sizereq=1,
+        readonly=False, maxlength=None):
         '''Create column with default values.'''
         
         self.title = title
-        '''Column title'''
+        '''Title is displayed in heading before first row.'''
+
+        self.header = header
+        '''Header column is highlighted, values in this column cannot be edited.'''
         
         self.expand = expand
-        '''Use free space?'''
+        '''If true, this column will autoresize to consume any free space.'''
         
         self.sizereq = sizereq
         '''Size request. Meaning depends on value of expand:
@@ -46,14 +50,14 @@
         
         '''
         
-        self.size = 0
+        self.size = None
         '''Computed size of column.'''
         
-        self.header = header
-        '''Is this header column? (bold, readonly)'''
+        self.index = None
+        '''Computed index.'''
         
         self.readonly = readonly
-        '''Allow edit?'''
+        '''If not readonly, values in this column can be changed by user.'''
         
         self.maxlength = maxlength
         '''Maximum length of value (for EditField).'''
@@ -69,11 +73,17 @@
         
         self.columns = []
         self.spacing = 1
+        self.rowcount = 0
+        self.headsize = 1
         
         self.offset = Coords()
+        self.acell = Coords()
+        '''Active cell (cursor).'''
         
         self.connect('draw', self.on_draw)
         self.connect('keypress', self.on_keypress)
+        
+        self.addevents('scroll', 'areasize')
     
     def getmodel(self):
         return self._model
@@ -120,6 +130,13 @@
                 if remaining_space > 0.99:
                     remaining_space -= 1.
                     col.size += 1
+        
+        # compute indexes
+        idx = 0
+        for col in self.columns:
+            if not col.header:
+                col.index = idx
+                idx += 1
     
     def draw_head(self, screen, x, y):
         screen.pushcolor('strong')
@@ -128,33 +145,96 @@
             x += col.size + self.spacing
         screen.popcolor()
     
-    def draw_row(self, screen, x, y, row):
+    def draw_row(self, screen, x, y, row, highlight):
         for col, data in zip(self.columns, row):
             if col.header:
                 screen.pushcolor('strong')
+            elif col.index in highlight:
+                screen.pushcolor('active')
+            else:
+                screen.pushcolor('normal')
             screen.puts(x, y, data[:col.size])
-            if col.header:
-                screen.popcolor()
+            screen.popcolor()
             x += col.size + self.spacing
     
     def on_draw(self, screen, x, y):
         screen.pushcolor('normal') 
-        head_size = 1
-        numrows = min(self.model.getcount() - self.offset.y, self.size.h - head_size)
+        self.rowcount = self.model.getcount()
+        numrows = min(self.rowcount - self.offset.y, self.size.h - self.headsize)
         rows = self.model.getrows(self.offset.y, self.offset.y + numrows)
         self.compute_column_sizes()
         self.draw_head(screen, x, y)
-        y += head_size
+        y += self.headsize
         for row in rows:
-            self.draw_row(screen, x, y, row)
+            highlight = []
+            if self.offset.y + rows.index(row) == self.acell.y:
+                highlight.append(self.acell.x)
+            self.draw_row(screen, x, y, row, highlight)
             y += 1
         screen.popcolor()        
 
     def on_keypress(self, keyname, char):
         if keyname:
-            if keyname == 'up':    self.move_up()
+            if keyname == 'up':  self.move_up()
             if keyname == 'down':  self.move_down()
             if keyname == 'left':  self.move_left()
-            if keyname == 'right': self.move_right()
+            if keyname == 'right':  self.move_right()
+            if keyname == 'pageup':  self.move_pageup()
+            if keyname == 'pagedown':  self.move_pagedown()
         self.redraw()
 
+    def set_yofs(self, yofs):
+        if yofs > self.rowcount - (self.height - self.headsize):
+            yofs = self.rowcount - (self.height - self.headsize)
+        if yofs < 0:
+            yofs = 0
+        self.offset.y = yofs
+        self.handle('scroll')
+    
+    def move_up(self):
+        if self.acell.y > 0:
+            self.acell.y -= 1
+            if self.acell.y < self.offset.y:
+                self.set_yofs(self.acell.y)
+            return True
+        return False
+    
+    def move_down(self):
+        log=logging.getLogger('tuikit')
+        log.debug('height %d', self.height)
+        if self.acell.y < self.rowcount - 1:
+            self.acell.y += 1
+            if self.acell.y > self.offset.y + (self.height - self.headsize - 1):
+                self.set_yofs(self.acell.y - (self.height - self.headsize - 1))
+            return True
+        return False
+
+    def move_pageup(self):
+        if self.acell.y >= self.height - self.headsize - 1:
+            self.acell.y -= self.height - self.headsize - 1
+            self.set_yofs(self.offset.y - (self.height - self.headsize - 1))
+        else:
+            self.acell.y = 0
+            self.set_yofs(0)
+
+
+    def move_pagedown(self):
+        if self.acell.y <= self.rowcount - (self.height - self.headsize - 1):
+            self.acell.y += self.height - self.headsize - 1
+            self.set_yofs(self.offset.y + (self.height - self.headsize - 1))
+        else:
+            self.acell.y = self.rowcount - 1
+            self.set_yofs(self.acell.y)
+
+    def move_left(self):
+        if self.acell.x > 0:
+            self.acell.x -= 1
+            return True
+        return False
+
+    def move_right(self):
+        if self.acell.x < len([col for col in self.columns if not col.header]) - 1:
+            self.acell.x += 1
+            return True
+        return False
+