Add TableView plus demo.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/demo_tableview.py Sat Oct 08 17:16:07 2011 +0200
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import locale
+locale.setlocale(locale.LC_ALL, '')
+
+from tuikit import Application
+from tuikit.layout import VerticalLayout
+from tuikit.tableview import TableView, TableModel
+
+
+class MyApplication(Application):
+ def __init__(self):
+ Application.__init__(self)
+ self.top.connect('keypress', self.globalkeypress)
+
+ data = []
+ for y in range(100):
+ row = [str(y)]
+ for x in range(10):
+ row.append('r{}:c{}'.format(y, x))
+ data.append(row)
+ model = TableModel(data)
+
+ view = TableView(model)
+ view.addcolumn(header=True, expand=False, sizereq=5)
+ for x in range(10):
+ view.addcolumn(title='head'+str(x))
+
+ self.top.add(view, expand=True, fill=True)
+
+ vert = VerticalLayout()
+ self.top.layout(vert)
+
+ def globalkeypress(self, keyname, char):
+ if keyname == 'escape':
+ self.terminate()
+
+
+if __name__ == '__main__':
+ app = MyApplication()
+ app.start()
+
--- a/docs/index.rst Fri Oct 07 12:36:14 2011 +0200
+++ b/docs/index.rst Sat Oct 08 17:16:07 2011 +0200
@@ -17,6 +17,7 @@
focus
redraw
colors
+ tableview
.. inheritance-diagram:: tuikit.application
tuikit.eventsource
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/tableview.rst Sat Oct 08 17:16:07 2011 +0200
@@ -0,0 +1,11 @@
+TableView
+=========
+
+.. toctree::
+ :maxdepth: 3
+ :titlesonly:
+
+.. automodule:: tuikit.tableview
+ :members:
+ :show-inheritance:
+
--- a/tuikit/__init__.py Fri Oct 07 12:36:14 2011 +0200
+++ b/tuikit/__init__.py Sat Oct 08 17:16:07 2011 +0200
@@ -13,6 +13,7 @@
from tuikit.menubar import MenuBar
from tuikit.pager import Pager
from tuikit.scrollbar import VScrollbar
+from tuikit.tableview import TableModel, TableView
from tuikit.textedit import TextEdit
from tuikit.treeview import TreeNode, TreeModel, TreeView
from tuikit.widget import Widget
--- a/tuikit/application.py Fri Oct 07 12:36:14 2011 +0200
+++ b/tuikit/application.py Sat Oct 08 17:16:07 2011 +0200
@@ -137,6 +137,7 @@
def applytheme(self):
screen = self.screen
screen.setcolor('normal', 'white on black')
+ screen.setcolor('strong', 'white on black, bold')
screen.setcolor('active', 'black on cyan')
screen.setcolor('window:normal', 'white on blue')
screen.setcolor('window:controls', 'white on blue, bold')
--- a/tuikit/backend_curses.py Fri Oct 07 12:36:14 2011 +0200
+++ b/tuikit/backend_curses.py Sat Oct 08 17:16:07 2011 +0200
@@ -513,7 +513,7 @@
return [('keypress', 'Unknown', None)]
if keyname == 'mouse':
- return self.process_xterm_mouse()
+ return self.process_xterm_mouse()
return [('keypress', keyname, None)]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tuikit/tableview.py Sat Oct 08 17:16:07 2011 +0200
@@ -0,0 +1,160 @@
+# -*- coding: utf-8 -*-
+
+import math
+
+from tuikit.widget import EventSource, Widget
+from tuikit.common import Coords
+
+
+class TableModel(EventSource):
+ def __init__(self, list_of_lists):
+ EventSource.__init__(self)
+ self.addevents('change')
+ self.data = list_of_lists
+
+ def getcount(self):
+ '''Get number of rows.'''
+ return len(self.data)
+
+ def getrows(self, begin, end):
+ '''Get rows from begin to end, including begin, excluding end.'''
+ return self.data[begin:end]
+
+ def update(self, row, col, val):
+ self.data[row][col] = val
+
+
+class Column:
+
+ '''Columns description.'''
+
+ def __init__(self, title='', expand=True, sizereq=1,
+ header=False, readonly=False, maxlength=None):
+ '''Create column with default values.'''
+
+ self.title = title
+ '''Column title'''
+
+ self.expand = expand
+ '''Use free space?'''
+
+ self.sizereq = sizereq
+ '''Size request. Meaning depends on value of expand:
+
+ When false, sizereq is number of characters.
+ When true, sizereq is relative size ratio.
+
+ '''
+
+ self.size = 0
+ '''Computed size of column.'''
+
+ self.header = header
+ '''Is this header column? (bold, readonly)'''
+
+ self.readonly = readonly
+ '''Allow edit?'''
+
+ self.maxlength = maxlength
+ '''Maximum length of value (for EditField).'''
+
+
+class TableView(Widget):
+ def __init__(self, model=None, width=20, height=20):
+ Widget.__init__(self, width, height)
+
+ # model
+ self._model = None
+ self.setmodel(model)
+
+ self.columns = []
+ self.spacing = 1
+
+ self.offset = Coords()
+
+ self.connect('draw', self.on_draw)
+ self.connect('keypress', self.on_keypress)
+
+ def getmodel(self):
+ return self._model
+
+ def setmodel(self, value):
+ if self._model:
+ self._model.disconnect('change', self.redraw)
+ self._model = value
+ if self._model:
+ self._model.connect('change', self.redraw)
+
+ model = property(getmodel, setmodel)
+
+ def addcolumn(self, *args, **kwargs):
+ for col in args:
+ self.columns.append(col)
+ if len(args) == 0:
+ col = Column(**kwargs)
+ self.columns.append(col)
+
+ def compute_column_sizes(self):
+ total_space = self.size.w - self.spacing * len(self.columns)
+ no_expand_cols = [col for col in self.columns if not col.expand]
+ no_expand_size = sum([col.sizereq for col in no_expand_cols])
+ expand_cols = [col for col in self.columns if col.expand]
+ expand_num = len(expand_cols)
+ expand_size = total_space - no_expand_size
+
+ # compute size of cols without expand
+ for col in no_expand_cols:
+ col.size = col.sizereq
+
+ # compute size of cols with expand
+ if no_expand_size > total_space + expand_num:
+ for col in expand_cols:
+ col.size = 1
+ else:
+ total_req = sum([col.sizereq for col in expand_cols])
+ remaining_space = 0.
+ for col in expand_cols:
+ frac, intp = math.modf(expand_size * col.sizereq / total_req)
+ col.size = int(intp)
+ remaining_space += frac
+ if remaining_space > 0.99:
+ remaining_space -= 1.
+ col.size += 1
+
+ def draw_head(self, screen, x, y):
+ screen.pushcolor('strong')
+ for col in self.columns:
+ screen.puts(x, y, col.title[:col.size])
+ x += col.size + self.spacing
+ screen.popcolor()
+
+ def draw_row(self, screen, x, y, row):
+ for col, data in zip(self.columns, row):
+ if col.header:
+ screen.pushcolor('strong')
+ screen.puts(x, y, data[:col.size])
+ if col.header:
+ 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)
+ rows = self.model.getrows(self.offset.y, self.offset.y + numrows)
+ self.compute_column_sizes()
+ self.draw_head(screen, x, y)
+ y += head_size
+ for row in rows:
+ self.draw_row(screen, x, y, row)
+ y += 1
+ screen.popcolor()
+
+ def on_keypress(self, keyname, char):
+ if keyname:
+ if keyname == 'up': self.move_up()
+ if keyname == 'down': self.move_down()
+ if keyname == 'left': self.move_left()
+ if keyname == 'right': self.move_right()
+ self.redraw()
+