Commits

Henning Schröder committed e599cce

simplified colors and chars

Comments (0)

Files changed (1)

+# -*- coding: utf-8 -*-
+import re
 
+COLOR_NAMES = {
+    "black": 0,
+    "red": 1,
+}
 
 
 class Screen(object):
 
-    __slots__ = ("width", "height", "rows", "colors")
+    __slots__ = ("width", "height", "data")
 
-    def __init__(self, width, height):
+    def copy(self):
+        data = []
+        for i, row in enumerate(self.data):
+            data.append(row[:])
+        return self.__class__(self.width, self.height, data)
+
+    def __init__(self, width, height, data=None):
         self.width = width
         self.height = height
-        self.rows = []
-        self.colors = []
-        for row in range(height):
-            self.rows.append(u" " * width)
-            self.colors.append([15] * width)
+        if data is None:
+            data = []
+            for y in xrange(height):
+                data.append([(u" ", None)] * width)
+        self.data = data
 
-    def text(self, x, y, color, value):
-        row = self.rows[y]
-        if x + len(value) > self.width:
-            value = value[:self.width - x - len(value)]
-        self.rows[y] = row[:x] + value + row[x + len(value):]
-        colors = self.colors[y]
-        self.colors[y] = colors[:x] + [color] * len(value) + colors[x + len(value):]
+    def find_color(self, name):
+        return COLOR_NAMES.get(name, 0)
+
+    def text(self, x, y, foreground_color, background_color, chars):
+        if isinstance(foreground_color, basestring):
+            foreground_color = self.find_color(foreground_color)
+        if isinstance(background_color, basestring):
+            background_color = self.find_color(background_color)
+        if isinstance(chars, str):
+            chars = chars.decode("utf-8")
+        chars = list(chars)
+        value_length = len(chars)
+        if x + value_length > self.width:
+            value_length = self.width - x
+            chars = chars[:value_length]
+        colors = [(foreground_color, background_color)] * value_length
+        row = self.data[y]
+        insert = zip(chars, colors)
+        row[x:x+value_length] = insert
+
+    def ctext(self, x, y, foreground_color, background_color, chars):
+        for part in re.split("(\[\[.+?\]\])", chars):
+            if part.startswith("[[") and part.endswith("]]"):
+                color = part[2:-2]
+                if "," in color:
+                    foreground_color, background_color = color.split(",")
+                else:
+                    foreground_color = color
+            else:
+                self.text(x, y, foreground_color, background_color, part)
+                x += len(part)
 
     def dump(self):
         header1 = ""
         header2 = ""
-        for i in range(self.width):
+        for i in xrange(self.width):
             header1 += str(i % 10)
             header2 += (i % 10 and " " or str(i//10))
         print header2
         print header1
-        for i, row in enumerate(self.rows):
+        for i, row in enumerate(self.data):
+            chars, colors = zip(*row)
             print "%.2i" % i,
-            print row.replace(u"\r", u" ").replace(u"\n", u" ").encode("utf-8")
-
-    def copy(self):
-        screen = self.__class__(self.width, self.height)
-        screen.rows = self.rows[::]
-        for i, row in enumerate(screen.rows):
-            screen.rows[i] = row[:]
-        for i, colors in enumerate(screen.colors):
-            screen.colors[i] = colors[:]
-        return screen
+            print "".join(chars).replace(u"\r", u" ").replace(u"\n", u" ").encode("utf-8")
 
     def diff(self, other):
         assert (self.width, self.height) == (other.width, other.height)
         changes = []
-        for i, row in enumerate(self.rows):
-            other_row = other.rows[i]
+        for i, row in enumerate(self.data):
+            other_row = other.data[i]
             if row != other_row:
                 changes.append((i, self.diff_row(row, other_row)))
         return changes
 
     def diff_row(self, row1, row2):
         changes = []
-        for i, col in enumerate(row1):
-            other_col = row2[i]
-            if col != other_col:
-                changes.append(col)
+        changed_offset = -1
+        for col_offset1, col1 in enumerate(row1):
+            col2 = row2[col_offset1]
+            if col1 != col2:
+                (char1, color1) = col1
+                (char2, color2) = col2
+                if changed_offset + 1 == col_offset1 and color1 == color2:
+                    # merge with previous change
+                    changes[-1] = (changes[-1][0] + char1, color1)
+                else:
+                    changes.append(col1)
+                changed_offset = col_offset1
         return changes
 
+    def fill_color(self, x1, y1, x2, y2, foreground_color, background_color):
+        width = x2 - y1
+        for y in xrange(y1, y2 + 1):
+            row = self.data[y]
+            chars, _colors = zip(*row)
+            colors = [(foreground_color, background_color)] * width
+            insert = zip(chars, colors)
+            row[x1:x2] = insert
+
+    def add_shadow(self,  x1, y1, x2, y2):
+        self.fill_color(x2 + 1, y1 + 1, x2 + 1, y1 + 1, "grey", "black")
+        self.fill_color(x1 + 1, y2 + 1, x2, y2 + 1, "grey", "black")
+
+    def rectangle(self, x1, y1, x2, y2, foreground_color, background_color):
+        pass
+
+
 if __name__ == "__main__":
     s1 = Screen(80, 24)
-    s1.text(2, 5, 15, "hello")
+    s1.text(2, 5, 15, 0, "hello")
+    s1.ctext(1,1, 99, 99, "[[blue,yellow]]hello[[red]] this is a test[[black]].")
 
     s2 = s1.copy()
-    s2.text(10, 5, 7, "world")
+    s2.text(2, 5, 15, 0, "H€")
     s2.dump()
 
+    import time
+    start_time = time.time()
     print s2.diff(s1)
+    print time.time() - start_time