Commits

anatoly techtonik committed 339021c

FilePanel: Added scrolling.

Comments (0)

Files changed (1)

     # a list of unique directory entries, one entry is always active
     # [ ] background color (pyglet bug)
     # [x] up/down arrows move cursor
+    # [x] scrolling
     def __init__(self, width, height):
         self.height = height
         self.width = width
+        # offset of starting visible element from the items list
+        self.offset = 0
+        # [ ] resize - correct offset when window height shrinked
         
         # every item is (filename, label)
         self.items = []
-        self.current_index = 0
-        
+        self.item_idx = 0
+
+    def _is_item_visible(self, idx):
+        """True if item with given idx is visible in panel"""
+        return (idx >= self.offset and idx < self.offset + self.height)
+
     def add_entry(self, name):
         label = pyglet.text.Label(name, font_name=font_family, anchor_y='top')
-        label.y = (self.height - len(self.items)) * font_height
-        if len(self.items) == self.current_index:
-            label.color = palette.active
-            label.background_color = palette.background_active
+        idx = len(self.items)  # index that will be assigned to the new entry
         self.items.append((name, label))
+        if self._is_item_visible(idx):
+            self._refresh_label_positions(idx)
+            if idx == self.item_idx:
+                self._color_entry(idx, palette.active,
+                                       palette.background_active)
         
     def _color_entry(self, idx, foreground, background=None):
         self.items[idx][1].color = foreground
         self.items[idx][1].background_color = background
         
+    def _refresh_label_positions(self, idx=None):
+        """Change position of visible label on the canvas. If idx is not None,
+           refresh coordinate for label with given idx.
+        """
+        if idx is not None:
+            if idx not in range(self.offset, self.height):
+                return
+            position = idx - self.offset 
+            self.items[idx][1].y = (self.height - position) * font_height
+        else:
+            items = self.items[self.offset:self.offset+self.height]
+            for position,item in enumerate(items):
+                item[1].y = (self.height - position) * font_height
+        
     def up(self):
         """Move cursor up"""
-        if self.current_index != 0:
-            self._color_entry(self.current_index, palette.foreground,
-                                                  palette.background)
-            self.current_index -= 1
-            self._color_entry(self.current_index, palette.active,
-                                                  palette.background_active)
+        if self.item_idx == 0:
+            # stop if first element of list is reached
+            return
+    
+        # repaint old/new active items labels
+        self._color_entry(self.item_idx, palette.foreground,
+                                         palette.background)
+        self.item_idx -= 1
+        self._color_entry(self.item_idx, palette.active,
+                                         palette.background_active)
+        if self.item_idx < self.offset:
+            self.offset -= 1
+            self._refresh_label_positions()
 
     def down(self):
         """Move cursor down"""
-        if self.current_index < len(filepanel.items)-1:
-            self._color_entry(self.current_index, palette.foreground,
-                                                  palette.background)
-            self.current_index += 1
-            self._color_entry(self.current_index, palette.active,
-                                                  palette.background_active)
+        if self.item_idx == len(filepanel.items)-1:
+            # stop if last element of list is reached
+            return
+
+        # repaint old/new active items labels                
+        self._color_entry(self.item_idx, palette.foreground,
+                                         palette.background)
+        self.item_idx += 1
+        self._color_entry(self.item_idx, palette.active,
+                                         palette.background_active)
+
+        if self.item_idx - self.offset == self.height:
+            self.offset += 1
+            self._refresh_label_positions()
 
 filepanel = FilePanel(80, 25)
 
     
     # draw panel
     for idx, (name, label) in enumerate(filepanel.items):
-        label.draw()
+        if idx >= filepanel.offset and idx < filepanel.offset + filepanel.height:
+            label.draw()
 
 @window.event
 def on_text_motion(motion):