[shpy-commit] r2869 - in shpy/trunk/dist/shpy: . net

hpk@codespeak.net hpk@codespeak.net
Tue, 20 Jan 2004 22:48:12 +0100 (MET)


Author: hpk
Date: Tue Jan 20 22:48:11 2004
New Revision: 2869

Modified:
   shpy/trunk/dist/shpy/net/shared.py
   shpy/trunk/dist/shpy/ui_pygame.py
Log:
- hi michael :-) 

- we now draw a list of cells 

- a cell now contains a list of structures (each representing a line) 
  so that lines can be updated and propagated independently, and so that we
  can use a reference to the "current" line of each cursor
  instead of an index into some list. 

- the screen is drawn starting from the *last line* that is visible 
  and then up backwards from there. 

- the screen doesn't yet scroll automatically to follow the cursor



Modified: shpy/trunk/dist/shpy/net/shared.py
==============================================================================
--- shpy/trunk/dist/shpy/net/shared.py	(original)
+++ shpy/trunk/dist/shpy/net/shared.py	Tue Jan 20 22:48:11 2004
@@ -17,10 +17,27 @@
     def __init__(self, **attributes):
         self.__dict__.update(attributes)
 
+
+def structurelist(*args):
+    l = []
+    for arg in args:
+        l.append(Structure(content=arg))
+    return l
+
 root = Structure()
 
-root.cells = Structure()
-cell = Structure(lines=open('/etc/passwd', 'r').read().split('\n'))
-root.cells.list = [cell]
+root.cells = Structure(list = [
+        Structure(lines = structurelist(
+        'def f():',
+        '   for i in range(10):',
+        '       print i * 42',
+        '       break',
+        )),
+        Structure(lines = structurelist(
+        'def f():',
+        '   print 42',
+        )),
+    ]
+)
 
 root.users = Structure()

Modified: shpy/trunk/dist/shpy/ui_pygame.py
==============================================================================
--- shpy/trunk/dist/shpy/ui_pygame.py	(original)
+++ shpy/trunk/dist/shpy/ui_pygame.py	Tue Jan 20 22:48:11 2004
@@ -39,131 +39,198 @@
         self.servergateway = shpy.net.register.ServerGateway(hostport, ns)
         pygame.init()
         pygame.key.set_repeat(500,30)
-        pygame.display.set_mode(RESOLUTION, RESIZABLE)
+        self.screen = pygame.display.set_mode(RESOLUTION, RESIZABLE)
         self.font = pygame.font.Font(FONT, HEIGHT)
         self.fontheight = self.font.size('X')[1]
         self.root = self.servergateway.registerclient()
+        self.changed = {}
         username = info.getusername()
         try:
             self.cursor = getattr(self.root.users, username)
         except AttributeError:
-            self.cursor = Structure(x=0, y=0, color=info.getcolor())
+            self.cursor = Structure(x=0, color=info.getcolor())
             setattr(self.root.users, username, self.cursor)
-            self.notifychanges(self.cursor, self.root.users)
-        print self.root.users.__dict__
-        self.cell = self.root.cells.list[0]
-        self.vscroll = 0
+        #print self.root.users.__dict__
+        self.celllist = self.root.cells.list
+        if not hasattr(self.cursor, 'cell') or self.cursor.cell not in self.celllist:
+            self.cursor.cell = self.celllist[-1]
+        if not hasattr(self.cursor, 'line') or self.cursor.line not in self.cursor.cell.lines:
+            self.cursor.line = self.cursor.cell.lines[-1]
+        self.lastline_cell = self.cursor.cell
+        self.lastline = self.lastline_cell.lines[-1]
+        self.changed[self.cursor] = 1
+        self.changed[self.root.users] = 1
 
     def repaint(self):
-        screen = pygame.display.get_surface()
-        screen.fill((255,255,255))
-        self.drawcell(screen, self.cell)
+        self.screen.fill((255,255,255))
+        self.bring_lastline_in_view_of_cursor()
+        self.line2ypos = {}
+        
+        index = self.lastline_cell.lines.index(self.lastline)
+        lines = self.lastline_cell.lines[:index+1]
+        ypos = self.drawlinesbackwards(lines)
+        if ypos > 0:
+            index = self.celllist.index(self.lastline_cell)
+            remainingcells = self.celllist[:index]
+            while remainingcells and ypos > 0:
+                cell = remainingcells.pop()
+                ypos = self.drawspacing(ypos)
+                ypos = self.drawlinesbackwards(cell.lines, ypos)
+        self.drawcursors()
         pygame.display.flip()
 
-    def drawcell(self, screen, cell):
-        self.scroll_cursor_into_view(screen)
-        start = -self.vscroll//self.fontheight
-        stop = (-self.vscroll + screen.get_size()[1])//self.fontheight + 1
-        ypos = self.vscroll + start*self.fontheight
-        for line in cell.lines[start:stop]:
-            lineimage = self.font.render(line or ' ', 1, (0,0,0))
-            screen.blit(lineimage, (0, ypos))
-            ypos += self.fontheight
-        self.drawcursors(screen, cell)
-
-    def char_pos(self, cell, x, y):
-        line = cell.lines[y]
-        return (self.font.size(line[:x])[0],
-                y*self.fontheight + self.vscroll)
-
-    def char_rect(self, cell, x, y):
-        c = cell.lines[y][x:x+1]
-        if not c:
-            c = ' '
-        return Rect(self.char_pos(x, y), self.font.size(c))
-
-    def scroll_cursor_into_view(self, screen):
-        ypos = self.vscroll + self.cursor.y * self.fontheight
-        if ypos < 0:
-            screen.fill((255, 255, 255))
-            self.vscroll -= ypos
-        elif ypos + self.fontheight > screen.get_size()[1]:
-            screen.fill((255, 255, 255))
-            self.vscroll -= ypos + self.fontheight - screen.get_size()[1]
-
-    def drawcursors(self, screen, cell):
+    def drawcursors(self):
         for cursor in self.root.users.__dict__.values():
             x = cursor.x
-            y = cursor.y
-            if y >= len(cell.lines):
-                y = len(cell.lines)-1
-            char = cell.lines[y][x:x+1]
+            line = cursor.line
+            try:
+                ypos = self.line2ypos[line]
+            except KeyError:
+                continue
+            char = line.content[x:x+1]
             if not char:
                 char = ' '
             charimage = self.font.render(char, 1, (255,255,255), cursor.color)
-            screen.blit(charimage, self.char_pos(cell, x, y))
+            startoflineimagesize = self.font.size(line.content[:x])
+            self.screen.blit(charimage, (startoflineimagesize[0], ypos))
+
+    def drawspacing(self, ypos):
+        self.screen.fill((160, 160, 160), Rect(0, ypos-2, 100, 1))
+        return ypos - 3
+    
+    def drawlinesbackwards(self, lines, ypos = None):
+        if ypos is None:
+            ypos = self.screen.get_size()[1]
+        l = lines[:]
+        while l and ypos > 0:
+            line = l.pop()
+            lineimage = self.font.render(line.content or ' ', 1, (0,0,0))
+            ypos -= self.fontheight
+            self.screen.blit(lineimage, (0, ypos))
+            self.line2ypos[line] = ypos
+        return ypos
+                
+    def bring_lastline_in_view_of_cursor(self):
+        pass
+    
+##    def drawcell(self, screen, cell):
+##        self.scroll_cursor_into_view(screen)
+##        start = -self.vscroll//self.fontheight
+##        stop = (-self.vscroll + screen.get_size()[1])//self.fontheight + 1
+##        ypos = self.vscroll + start*self.fontheight
+##        for line in cell.lines[start:stop]:
+##            lineimage = self.font.render(line or ' ', 1, (0,0,0))
+##            screen.blit(lineimage, (0, ypos))
+##            ypos += self.fontheight
+##        self.drawcursors(screen, cell)
+
+##    def char_pos(self, cell, x, y):
+##        line = cell.lines[y]
+##        return (self.font.size(line[:x])[0],
+##                y*self.fontheight + self.vscroll)
+
+##    def char_rect(self, cell, x, y):
+##        c = cell.lines[y][x:x+1]
+##        if not c:
+##            c = ' '
+##        return Rect(self.char_pos(x, y), self.font.size(c))
+
+##    def scroll_cursor_into_view(self, screen):
+##        ypos = self.vscroll + self.cursor.y * self.fontheight
+##        if ypos < 0:
+##            self.vscroll -= ypos
+##        elif ypos + self.fontheight > screen.get_size()[1]:
+##            self.vscroll -= ypos + self.fontheight - screen.get_size()[1]
+
+##    def drawcursors(self, screen, cell):
+##        for cursor in self.root.users.__dict__.values():
+##            x = cursor.x
+##            y = cursor.y
+##            if y >= len(cell.lines):
+##                y = len(cell.lines)-1
+##            char = cell.lines[y][x:x+1]
+##            if not char:
+##                char = ' '
+##            charimage = self.font.render(char, 1, (255,255,255), cursor.color)
+##            screen.blit(charimage, self.char_pos(cell, x, y))
 
     def PRINTABLE_KEY(self, event):
         assert event.unicode
         x = self.cursor.x
-        y = self.cursor.y
-        line = self.cell.lines[y]
-        line = line[:x] + event.unicode + line[x:]
-        self.cell.lines[y] = line
+        line = self.cursor.line
+        line.content = line.content[:x] + event.unicode + line.content[x:]
         self.cursor.x += len(event.unicode)
-        self.changed[self.cell] = 1
+        self.changed[line] = 1
 
     def CTRL_K_a(self, event):
         self.cursor.x = 0
 
     def CTRL_K_e(self, event):
-        self.cursor.x = len(self.cell.lines[self.cursor.y])
+        self.cursor.x = len(self.cursor.line.content)
         
     def K_UP(self, event):
-        if self.cursor.y > 0:
-            self.cursor.y -= 1
-
+        index = self.cursor.cell.lines.index(self.cursor.line)
+        if index > 0:
+            self.cursor.line = self.cursor.cell.lines[index-1]
+        else:
+            # XXX this changes if we have output cells ...
+            index = self.celllist.index(self.cursor.cell)
+            if index > 0:
+                self.cursor.cell = self.celllist[index-1]
+                self.cursor.line = self.cursor.cell.lines[-1]
+                
     def K_DOWN(self, event):
-        if self.cursor.y < len(self.cell.lines)-1:
-            self.cursor.y += 1
+        index = self.cursor.cell.lines.index(self.cursor.line)
+        if index + 1 < len(self.cursor.cell.lines):
+            self.cursor.line = self.cursor.cell.lines[index+1]
+        else:
+            # XXX this changes if we have output cells ...
+            index = self.celllist.index(self.cursor.cell)
+            if index + 1 < len(self.celllist):
+                self.cursor.cell = self.celllist[index+1]
+                self.cursor.line = self.cursor.cell.lines[0]
 
     def K_LEFT(self, event):
         if self.cursor.x > 0:
             self.cursor.x -= 1
 
     def K_RIGHT(self, event):
-        line = self.cell.lines[self.cursor.y]
-        if self.cursor.x < len(line):
+        if self.cursor.x < len(self.cursor.line.content):
             self.cursor.x += 1
 
     def K_BACKSPACE(self, event):
         x = self.cursor.x
-        y = self.cursor.y
+        line = self.cursor.line
         if x > 0:
-            line = self.cell.lines[y]
-            line = line[:x-1] + line[x:]
-            self.cell.lines[y] = line
+            line.content = line.content[:x-1] + line.content[x:]
+            self.changed[line] = 1
             self.cursor.x -= 1
-        elif y > 0:
-            line = self.cell.lines[y]
-            prevline = self.cell.lines[y-1]
-            self.cell.lines[y-1:y+1] = [prevline + line]
-            self.cursor.y -= 1
-            self.cursor.x = len(prevline)
-        self.changed[self.cell] = 1
+        else:
+            index = self.cursor.cell.lines.index(line)
+            if index > 0:
+                prevline = self.cursor.cell.lines[index-1]
+                prevline.content += line.content
+                del self.cursor.cell.lines[index]
+                self.changed[prevline] = 1
+                self.changed[self.cursor.cell] = 1
+                self.cursor.line = prevline
+                self.cursor.x = len(prevline.content)
 
     def K_RETURN(self, event):
         x = self.cursor.x
-        y = self.cursor.y
-        line = self.cell.lines[y]
-        self.cell.lines[y:y+1] = [line[:x], line[x:]]
+        line = self.cursor.line
+        newline = Structure(content=line.content[x:])
+        line.content = line.content[:x]
+        index = self.cursor.cell.lines.index(line)
+        self.cursor.cell.lines.insert(index+1, newline)
+        self.cursor.line = newline
         self.cursor.x = 0
-        self.cursor.y += 1
-        self.changed[self.cell] = 1
+        self.changed[self.cursor.cell] = 1
+        self.changed[line] = 1
+        self.changed[newline] = 1
 
     def run(self):
         self.invalid = True
-        self.changed = {}
         while 1:
             if self.changed:
                 self.notifychanges(*self.changed.keys())
@@ -190,7 +257,7 @@
             if event.type == QUIT:
                 break
             if event.type == VIDEORESIZE:
-                pygame.display.set_mode(event.size, RESIZABLE)
+                self.screen = pygame.display.set_mode(event.size, RESIZABLE)
                 self.invalid = True
 
     def close(self):