changeset 707:6b8fa2248ee1 pyntnclick

Hack'ish filechooser widget
author Neil Muller <neil@dip.sun.ac.za>
date Sat, 04 Aug 2012 22:30:15 +0200
parents 909cd470674c
children 9b6d68ba627e
files pyntnclick/widgets/filechooser.py
diffstat 1 files changed, 141 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyntnclick/widgets/filechooser.py	Sat Aug 04 22:30:15 2012 +0200
@@ -0,0 +1,141 @@
+# Display a paged lsit of files and directories
+# Allow moving up and down directory trees
+
+import os
+
+from pyntnclick.widgets.base import Box
+from pyntnclick.widgets.text import TextButton, LabelWidget
+
+
+class FileChooser(Box):
+
+    def __init__(self, rect, gd, curdir, page_length=12, padding=2):
+        super(FileChooser, self).__init__(rect, gd)
+        self.page_length = page_length
+        self.page = 0
+        self.curdir = os.path.realpath(os.path.normpath(curdir))
+        self.selected = None
+        self.padding = padding
+        self.dirs = []
+        self.files = []
+        self.modal = True
+        self.prev_but = None
+        self.next_but = None
+        self.get_lists()
+        self.fill_page()
+
+    def get_lists(self):
+        self.dirs = []
+        self.files = []
+        for entry in sorted(os.listdir(self.curdir)):
+            path = os.path.join(self.curdir, entry)
+            if os.path.isdir(path):
+                self.dirs.append(entry)
+            else:
+                self.files.append(entry)
+
+    def _dir_button(self, entry):
+        widget = TextButton((0, 0), self.gd, entry + '/',
+                fontname=self.gd.constants.bold_font,
+                fontsize=10)
+        widget.add_callback('clicked', self.change_dir, entry)
+        return widget
+
+    def _file_button(self, entry):
+        if entry == self.selected:
+            # highlight
+            widget = TextButton((0, 0), self.gd, entry,
+                    fontsize=10, border=2, border_color='yellow')
+        else:
+            widget = TextButton((0, 0), self.gd, entry, fontsize=10)
+        self.add_callback('clicked', self.change_selection, entry)
+        return widget
+
+    def fill_page(self):
+        for widget in self.children[:]:
+            self.remove(widget)
+        start_page = self.page * self.page_length
+        end_page = start_page + self.page_length
+        entries = self.dirs + self.files
+        top = self.rect.top + self.padding
+        left = self.rect.left + self.padding
+        # Add current directory at the top
+        widget = LabelWidget((0, 0), self.gd, self.curdir[-30:], color='black')
+        widget.rect.topleft = (left, top)
+        self.add(widget)
+        upbut = TextButton((left + self.padding + widget.rect.width, top),
+                self.gd, u'\N{LEFTWARDS ARROW WITH HOOK}Back one level')
+        upbut.add_callback('clicked', self.change_dir, os.pardir)
+        self.add(upbut)
+        top += max(widget.rect.height, upbut.rect.height) + 4 * self.padding
+        page_top = top
+        page_left = left
+        for entry in entries[start_page:end_page]:
+            if entry in self.dirs:
+                widget = self._dir_button(entry)
+            else:
+                widget = self._file_button(entry)
+            widget.rect.topleft = (left, top)
+            self.add(widget)
+            top += widget.rect.height + self.padding
+            page_left = max(page_left, left + widget.rect.width)
+        # Add page list buttons
+        if not self.prev_but:
+            self.prev_but = TextButton((0, 0), self.gd, u'\N{UPWARDS ARROW}')
+            self.prev_but.add_callback('clicked', self.change_page, -1)
+        self.prev_but.rect.topleft = (page_left, page_top)
+        if not self.next_but:
+            self.next_but = TextButton((0, 0), self.gd, u'\N{DOWNWARDS ARROW}')
+            self.next_but.add_callback('clicked', self.change_page, -1)
+        page_top = max(top - self.next_but.rect.height,
+                self.prev_but.rect.bottom + self.padding)
+        self.next_but.rect.topleft = (page_left, page_top)
+        if self.page > 0:
+            self.prev_but.enable()
+        else:
+            self.prev_but.disable()
+        if end_page < len(entries):
+            self.next_but.enable()
+        else:
+            self.next_but.disable()
+        self.add(self.next_but)
+        self.add(self.prev_but)
+        # Add OK and Cancel buttons
+        ok_but = TextButton((left, top), self.gd, 'OK')
+        ok_but.add_callback('clicked', self.ok)
+        self.add(ok_but)
+        cancel_but = TextButton(
+                (left + ok_but.rect.width + 4 * self.padding, top),
+                self.gd, 'Cancel')
+        cancel_but.add_callback('clicked', self.cancel)
+        self.add(cancel_but)
+
+    def change_page(self, ev, widget, change):
+        self.page += change
+        self.fill_page()
+        return True
+
+    def change_dir(self, ev, widget, newdir):
+        """Change directory and refresh the widget."""
+        self.curdir = os.path.normpath(os.path.join(self.curdir, newdir))
+        self.page = 0
+        self.selected = None
+        self.get_lists()
+        self.fill_page()
+
+    def change_selection(self, ev, widget, entry):
+        """Update selection"""
+        self.selected = entry
+
+    def cancel(self, ev, widget):
+        if hasattr(self.parent, 'paused'):
+            self.parent.paused = False
+        self.parent.remove(self)
+        self.selected = None
+        return True
+
+    def ok(self, ev, widget):
+        if hasattr(self.parent, 'paused'):
+            self.parent.paused = False
+        self.parent.remove(self)
+        return True