tuikit/common.py
changeset 62 2f61931520c9
parent 43 369c8ef5070a
child 63 2a0e04091898
--- a/tuikit/common.py	Thu Jan 10 00:03:34 2013 +0100
+++ b/tuikit/common.py	Fri Jan 18 22:36:50 2013 +0100
@@ -3,6 +3,37 @@
 from tuikit.events import Event, Emitter
 
 
+class Select:
+    def __init__(self, selected=None):
+        if not hasattr(self, '_options'):
+            raise TypeError('Cannot instantiate Select class.')
+        self._selected = selected or self._options[0]
+
+    def update(self, selected):
+        if selected not in self._options:
+            raise ValueError('Select: %r not in options %r' % (selected, self._options))
+        self._selected = selected
+
+    def select_next(self):
+        i = self._options.index(self._selected)
+        try:
+            self._selected = self._options[i+1]
+        except IndexError:
+            self._selected = self._options[0]
+
+    @property
+    def selected(self):
+        return self._selected
+
+    def __repr__(self):
+        return self.__class__.__name__ + '(%r)' % self._selected
+
+
+def make_select(*args):
+    name = ''.join([x.capitalize() for x in args]) + 'Select'
+    return type(name, (Select,), {'_options': args})
+
+
 class Coords:
 
     '''2D coordinates.'''
@@ -28,6 +59,19 @@
     def __repr__(self):
         return 'Coords(x={0.x},y={0.y})'.format(self)
 
+    def update(self, x=None, y=None):
+        if isinstance(x, Coords) and y is None:
+            self.x, self.y = x
+        else:
+            if isinstance(x, int):
+                self.x = x
+            elif x is not None:
+                raise ValueError('Coords.update(): first parameter must be int or Coords')
+            if isinstance(y, int):
+                self.y = y
+            elif y is not None:
+                raise ValueError('Coords.update(): second parameter must be int')
+
 
 class Size(Emitter):
 
@@ -78,6 +122,22 @@
     def __repr__(self):
         return 'Size(w={0._w},h={0._h})'.format(self)
 
+    def update(self, w=None, h=None):
+        old_w, old_h = self._w, self._h
+        if isinstance(w, Size) and h is None:
+            self._w, self._h = w
+        else:
+            if isinstance(w, int):
+                self._w = w
+            elif w is not None:
+                raise ValueError('Size.update(): first parameter must be int or Size')
+            if isinstance(h, int):
+                self._h = h
+            elif h is not None:
+                raise ValueError('Size.update(): second parameter must be int')
+        if self._w != old_w or self._h != old_h:
+            self.emit('change')
+
 
 class Rect:
 
@@ -103,11 +163,13 @@
 
     '''
 
-    def __init__(self, l=0, t=0, r=0, b=0):
+    def __init__(self, l=0, t=0, r=0, b=0, full=None):
         self.l = l # left
         self.t = t # top
         self.r = r # right
         self.b = b # bottom
+        if full is not None:
+            self.l = self.t = self.r = self.b = full
 
     def __getitem__(self, key):
         try:
@@ -120,6 +182,16 @@
     def __repr__(self):
         return 'Borders(l={0.l},t={0.t},r={0.r},b={0.b})'.format(self)
 
+    def update(self, *args, **kwargs):
+        if len(args) == 4:
+            self.l, self.t, self.r, self.b = args
+        elif len(args) == 1 and isinstance(args[0], Borders):
+            self.l, self.t, self.r, self.b = args[0]
+        elif len(args):
+            raise ValueError('Borders.update() takes exactly 4 positional arguments.')
+        for arg in kwargs:
+            setattr(self, arg, kwargs[arg])
+
 
 class ClipStack:
 
@@ -176,6 +248,11 @@
     # http://en.wikipedia.org/wiki/List_of_Unicode_characters#Geometric_shapes
     UP_ARROW = '▲' #curses.ACS_UARROW
     DOWN_ARROW = '▼' #curses.ACS_DARROW
+    LEFT_ARROW = '◀'
+    RIGHT_ARROW = '▶'
+    CIRCLE = '●'
+    DIAMOND = '◆'
+    MIDDLE_DOT = '·'
 
     # http://en.wikipedia.org/wiki/Box-drawing_characters
     LIGHT_SHADE = '░' #curses.ACS_BOARD