commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r9378 - trunk/gnue-forms/src/uidrivers/curses/widgets


From: johannes
Subject: [gnue] r9378 - trunk/gnue-forms/src/uidrivers/curses/widgets
Date: Tue, 13 Feb 2007 10:02:15 -0600 (CST)

Author: johannes
Date: 2007-02-13 10:02:14 -0600 (Tue, 13 Feb 2007)
New Revision: 9378

Added:
   trunk/gnue-forms/src/uidrivers/curses/widgets/menu.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/menuitem.py
Modified:
   trunk/gnue-forms/src/uidrivers/curses/widgets/form.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/page.py
Log:
Startet menu support for curses


Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/form.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/form.py       2007-02-13 
08:20:06 UTC (rev 9377)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/form.py       2007-02-13 
16:02:14 UTC (rev 9378)
@@ -45,6 +45,8 @@
 
         self.__pages = []
         self.__currentPage = None
+        self.__main_menu = None
+        self.__close_in_progress = False
 
         # Status bar values
         self.__tip = ''
@@ -74,7 +76,15 @@
 
         return self.__window is not None
 
+    # -------------------------------------------------------------------------
+    # Register an UIMenu instance as main menu
+    # -------------------------------------------------------------------------
 
+    def register_main_menu(self, menu):
+
+        self.__main_menu = menu
+
+
     # -------------------------------------------------------------------------
     # Set form title
     # -------------------------------------------------------------------------
@@ -184,8 +194,19 @@
     # -------------------------------------------------------------------------
 
     def wait(self):
-        return self.__currentPage.wait()
 
+        result = None
+        while result is None:
+            result = self.__currentPage.wait()
+            if result == curses.KEY_F10 and self.__main_menu is not None:
+                self.__main_menu.show(self.__currentPage)
+                result = None
+
+            if self.__close_in_progress:
+                break
+
+        return result
+
     # -------------------------------------------------------------------------
     # Get free area in the window
     # -------------------------------------------------------------------------
@@ -270,7 +291,7 @@
 
     def _ui_close_(self):
 
-        pass
+        self.__close_in_progress = True
 
     # -------------------------------------------------------------------------
     # Create the window and fit all widgets into the available space

Added: trunk/gnue-forms/src/uidrivers/curses/widgets/menu.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/menu.py       2007-02-13 
08:20:06 UTC (rev 9377)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/menu.py       2007-02-13 
16:02:14 UTC (rev 9378)
@@ -0,0 +1,351 @@
+# GNU Enterprise Forms - Curses UI Driver - Menu Widget
+#
+# Copyright 2001-2007 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+import curses
+
+from gnue.forms.uidrivers.curses.widgets._base import UIHelper
+
+
+# =============================================================================
+# Wrap an UI layer around a wxMenu widget
+# =============================================================================
+
+class UIMenu(UIHelper):
+    """
+    Implements a menu object.
+    """
+
+    enough_space = True
+
+    # -------------------------------------------------------------------------
+    # Create a menu widget
+    # -------------------------------------------------------------------------
+
+    def _create_widget_(self, event, spacer):
+        """
+        Creates a new Menu widget.
+        """
+
+        if self._gfObject.name == '__main_menu__' \
+                and not self._form._features['GUI:MENUBAR:SUPPRESS']:
+            # Menu bar of the form
+            self._uiForm.register_main_menu(self)
+        else:
+            # Submenu or popup menu
+            if isinstance (event.container, UIMenu):
+                event.container.add_subitem(self)
+
+        self._container = self
+        self.__menu_items = []
+
+        return None
+
+
+    # -------------------------------------------------------------------------
+    # Add a sub item to the menu
+    # -------------------------------------------------------------------------
+
+    def add_subitem(self, item):
+
+        self.__menu_items.append(item)
+
+
+    # -------------------------------------------------------------------------
+    # Show this menu
+    # -------------------------------------------------------------------------
+
+    def show(self, page, offsx=0, offsy=0, run=True):
+
+        self.__page = page
+        self.__pattern = self.__get_pattern()
+        self.__sep_len = len(self.__pattern % {'text': '-', 'hotk': '-'})
+        self.__separator = curses.ACS_HLINE
+
+        self.__data = []
+        for item in self.__menu_items:
+            if item._gfObject.label:
+                add = self.__pattern % {'text': item._gfObject.label,
+                                 'hotk': getattr(item._gfObject, 'hotkey', '')}
+                self.__data.append(' %s ' % add)
+            else:
+                self.__data.append(self.__separator)
+
+        # Figure out where to position the menu
+        ca_left, ca_top, ca_right, ca_bottom = self._uiForm.get_canvas()
+        if not offsx:
+            offsx = ca_left
+        if not offsy:
+            offsy = ca_top
+
+        maxy, maxx = ca_bottom, ca_right
+        if offsx + self.__sep_len + 4 < maxx:
+            self.left = offsx
+
+        elif offsx - self.__sep_len - 4 > 0:
+            self.left = offsx - self.__sep_len - 4
+
+        else:
+            self.left = 0
+
+        if offsy + len(self.__data) + 2 < maxy:
+            self.top = offsy
+
+        elif offsy - len(self.__data) - 2 > 0:
+            self.top = offsy - len(self.__data) - 2
+        else:
+            self.top = 0
+
+        self.width = min((self.__sep_len + 4), maxx - self.left)
+        self.height = min(len(self.__data) + 2, maxy - self.top)
+
+        self.offset = 0
+        self.selected = 0
+        self.display = 0
+
+        self.__draw_menu(run)
+
+        if run:
+            result = self.run()
+        else:
+            result = False
+
+        return result
+
+
+    # -------------------------------------------------------------------------
+
+    def __get_pattern(self):
+
+        ca_left, ca_top, ca_right, ca_bottom = self._uiForm.get_canvas()
+        # Take away the decoration of the menu
+        av_width = ca_right - ca_left - 4
+
+        text = []
+        hotk = []
+
+        for item in self.__menu_items:
+            add = item._gfObject.label or ''
+            text.append(add)
+            hotk.append(getattr(item._gfObject, 'hotkey', '') or '')
+
+        max_text = max([len(i) for i in text])
+        max_hotk = max([len(i) for i in hotk])
+
+        # Get the best width for this menu
+        best = max_text
+        if max_hotk:
+            best += 3 + max_hotk
+            patt = "%%(text)-%ds%%(hotk)%ds" % (max_text, max_hotk + 3)
+        else:
+            patt = "%%(text)-%ds" % max_text
+
+        if best <= av_width:
+            result = patt
+
+        # Does it help to reduce the gap between text and hotkey
+        elif max_hotk and best <= av_width - 2:
+            result = "%%(text)-%ds%%(hotk)%ds" % (max_text, max_hotk + 1)
+
+        # And if we use the text only 
+        elif max_text <= av_width:
+            result = "%%(text)-%ds" % max_text
+
+        else:
+            result = "%%(text)-%ds" % av_width
+
+        return result
+
+
+    # -------------------------------------------------------------------------
+    # Draw the menu
+    # -------------------------------------------------------------------------
+
+    def __draw_menu(self, highlight):
+
+        self.__window = curses.newwin(self.height, self.width, self.top,
+                self.left)
+        self.__window.keypad(1)
+        self.__window.box()
+
+        self.__normal = self._uiDriver.attr['window 1']
+        self.__reverse = self._uiDriver.attr['focusentry']
+
+        count = self.height - 2
+        data = self.__data[self.offset:self.offset+count]
+        if len(data) < count:
+            data.extend([''] * (count - len(data)))
+
+        for row, value in enumerate(data):
+            if isinstance(value, basestring):
+                text = value.ljust(self.width - 2)[:self.width - 2]
+                attr = self.__normal
+                if highlight and row == self.display:
+                    attr = self.__reverse
+                self.__window.addstr(1 + row, 1, o(text), attr)
+            else:
+                self.__window.hline(1 + row, 2, curses.ACS_HLINE, self.width-4)
+
+        self.__window.refresh()
+
+
+    # -------------------------------------------------------------------------
+    # Start an input loop for the menu
+    # -------------------------------------------------------------------------
+
+    def run(self):
+
+        old = curses.curs_set(0)
+        previous = None
+
+        try:
+            while True:
+                result = True
+                if isinstance(self.__menu_items[self.selected], UIMenu):
+                    previous = self.__menu_items[self.selected]
+                    self.__step_down(previous, False)
+
+                key = self.__window.getch()
+                current = self.__menu_items[self.selected]
+
+                if key == 27:
+                    break
+
+                if key in [curses.KEY_UP, curses.KEY_DOWN]:
+                    if previous is not None:
+                        self.__update_to_current()
+
+                    self.__move([1, -1][key == curses.KEY_UP])
+                    key = None
+
+                elif key in [curses.KEY_RIGHT, curses.KEY_ENTER, 10]:
+
+                    if isinstance(current, UIMenu):
+                        quit = self.__step_down(current, True)
+                        if quit:
+                            break
+
+                    elif key != curses.KEY_RIGHT:
+                        current._gfObject._event_fire()
+                        break
+
+                elif key == curses.KEY_LEFT:
+                    result = False
+                    break
+
+                self.__draw_menu(True)
+
+        finally:
+            curses.curs_set(old)
+            return result
+
+
+
+    # -------------------------------------------------------------------------
+    # Repaint all parent menus
+    # -------------------------------------------------------------------------
+
+    def __update_to_current(self):
+
+        self.__page.repaint(False)
+
+        level = self
+        while isinstance(level, UIMenu):
+            level.repaint()
+            level = level.getParent()
+
+        curses.doupdate()
+
+
+    # -------------------------------------------------------------------------
+    # Show and optionally run a submenu
+    # -------------------------------------------------------------------------
+
+    def __step_down(self, destination, run):
+
+        offsx = self.left + self.width - 1
+        offsy = self.top + self.selected + 1 
+        return destination.show(self.__page, offsx, offsy, run)
+
+
+    # -------------------------------------------------------------------------
+    # Move the selected item
+    # -------------------------------------------------------------------------
+
+    def __move(self, direction):
+
+        movement = self.__get_next(direction)
+        self.display += movement
+        self.selected += movement
+
+        if self.display >= self.height - 2:
+            if self.selected < len(self.__data):
+                self.offset += movement
+
+        elif self.display < 0:
+            self.offset = max(0, self.offset - 1)
+
+        self.selected = max(0, self.selected)
+        self.selected = min(len(self.__data) - 1, self.selected)
+
+        self.display = max(0, self.display)
+        self.display = min(self.display, self.height-3)
+
+
+    # -------------------------------------------------------------------------
+    # Get the next usable menu-item (skipping separators)
+    # -------------------------------------------------------------------------
+
+    def __get_next(self, direction):
+
+        if direction > 0:
+            next = self.__data[self.selected+1:]
+        else:
+            next = self.__data[:self.selected]
+            next.reverse()
+
+        for add, item in enumerate(next):
+            if item != self.__separator:
+                res = direction * (add + 1)
+                return res
+
+        return 0
+
+
+    # -------------------------------------------------------------------------
+    # Repaint the menu
+    # -------------------------------------------------------------------------
+
+    def repaint(self):
+
+        self.__draw_menu(False)
+
+
+# =============================================================================
+# Configuration data
+# =============================================================================
+
+configuration = {
+  'baseClass': UIMenu,
+  'provides' : 'GFMenu',
+  'container': 1,
+}


Property changes on: trunk/gnue-forms/src/uidrivers/curses/widgets/menu.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/gnue-forms/src/uidrivers/curses/widgets/menuitem.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/menuitem.py   2007-02-13 
08:20:06 UTC (rev 9377)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/menuitem.py   2007-02-13 
16:02:14 UTC (rev 9378)
@@ -0,0 +1,99 @@
+# GNU Enterprise Forms - Curses UI Driver - MenuItem Widget
+#
+# Copyright 2001-2007 Free Software Foundation
+#
+# This file is part of GNU Enterprise
+#
+# GNU Enterprise is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2, or (at your option) any later version.
+#
+# GNU Enterprise is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with program; see the file COPYING. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place
+# - Suite 330, Boston, MA 02111-1307, USA.
+#
+# $Id$
+
+from gnue.forms.uidrivers.curses.widgets._base import UIHelper
+
+
+# =============================================================================
+# Wrap an UI layer around a wxMenu widget
+# =============================================================================
+
+class UIMenuItem(UIHelper):
+    """
+    Implements a menu item object.
+    """
+
+    # -------------------------------------------------------------------------
+    # Create a menu item widget
+    # -------------------------------------------------------------------------
+
+    def _create_widget_(self, event, spacer):
+        """
+        Creates a new MenuItem widget.
+        """
+
+        # These are the relevant parameters
+        label = self._gfObject.label
+        description = self._gfObject.description
+        hotkey = self._gfObject.hotkey
+        check = (self._gfObject.action_off is not None)
+
+        if label is not None:
+            if hotkey is not None:
+                text = label + u"\t" + hotkey
+            else:
+                text = label
+
+        event.container.add_subitem(self)
+
+        return None
+
+
+    # -------------------------------------------------------------------------
+    # Check/uncheck menu item
+    # -------------------------------------------------------------------------
+
+    def _ui_switch_on_(self):
+        # TODO: need implementation
+        return
+
+    # -------------------------------------------------------------------------
+
+    def _ui_switch_off_(self):
+        # TODO: need implementation
+        return
+
+    # -------------------------------------------------------------------------
+    # Enable/disable menu item
+    # -------------------------------------------------------------------------
+
+    def _ui_enable_(self):
+        # TODO: need implementation
+        return
+
+    # -------------------------------------------------------------------------
+
+    def _ui_disable_(self):
+        # TODO: need implmementation
+        return
+
+
+# =============================================================================
+# Configuration data
+# =============================================================================
+
+configuration = {
+  'baseClass': UIMenuItem,
+  'provides' : 'GFMenuItem',
+  'container': False
+}


Property changes on: trunk/gnue-forms/src/uidrivers/curses/widgets/menuitem.py
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/page.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/page.py       2007-02-13 
08:20:06 UTC (rev 9377)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/page.py       2007-02-13 
16:02:14 UTC (rev 9378)
@@ -160,8 +160,27 @@
 
         return self.__get_key()
 
+
     # -------------------------------------------------------------------------
+    # Repaint this page
+    # -------------------------------------------------------------------------
 
+    def repaint(self, immediate=True):
+
+        try:
+            if immediate:
+                self.__window.refresh(0, 0, self.top, self.left, self.bottom,
+                    self.right)
+            else:
+                self.__window.noutrefresh(0, 0, self.top, self.left,
+                        self.bottom, self.right)
+
+        except curses.error:
+            pass
+
+
+    # -------------------------------------------------------------------------
+
     def __get_next_key(self):
 
         # In nodelay mode the result of getch() is -1 if there is no input.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]