Author: johannes Date: 2005-04-28 10:14:58 -0500 (Thu, 28 Apr 2005) New Revision: 7500
Added: trunk/gnue-forms/src/uidrivers/curses/dialogs.py Modified: trunk/gnue-forms/src/uidrivers/curses/UIdriver.py trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py Log: Added lookup dialog to dropdowns (currently using Ctrl-W) Modified: trunk/gnue-forms/src/uidrivers/curses/UIdriver.py =================================================================== --- trunk/gnue-forms/src/uidrivers/curses/UIdriver.py 2005-04-28 11:17:58 UTC (rev 7499) +++ trunk/gnue-forms/src/uidrivers/curses/UIdriver.py 2005-04-28 15:14:58 UTC (rev 7500) @@ -29,6 +29,7 @@ from gnue.common.datasources import GLoginHandler from gnue.forms.GFKeyMapper import vk, KeyMapper from gnue.forms.uidrivers._base.UIdriver import GFUserInterfaceBase +from gnue.forms.uidrivers.curses import dialogs # ============================================================================= # User interface object @@ -76,9 +77,15 @@ self.attr ['warnmsg'] = curses.color_pair (9) + curses.A_BOLD self.attr ['errormsg'] = curses.color_pair (9) + curses.A_BOLD \ + curses.A_BLINK + self.attr ['window 1'] = curses.color_pair (5) self.__currentForm = None + # TODO: Add a concept of 'lookups' to the GF* layer (like canCOMMIT, ...) + # Meanwhile we're using Ctrl-W (hardcoded) + self.lookupKey = 23 + + # --------------------------------------------------------------------------- # Initialize user interface # --------------------------------------------------------------------------- @@ -301,7 +308,36 @@ gDebug (2, "Detail : %s" % detail) self.showMessage (message, kind = 'Error') + # --------------------------------------------------------------------------- + # Select one of the given options + # --------------------------------------------------------------------------- + + def getOption (self, title, options): + """ + Create a dialog box for selecting one of the given options + @param title: title for the dialog box + @param options: dictionary to select a value from + + @return: the selected option (dict-value) or None if cancelled + """ + + if self.__currentForm: + (left, top, right, bottom) = self.__currentForm.getCanvas () + else: + (right, bottom) = self.__screen.getmaxyx () + left = top = 0 + + dialog = dialogs.OptionsDialog (title, options, self.attr, self.lookupKey, + left, top, right, bottom) + try: + return dialog.run () + + finally: + self.__screen.refresh () + + + # --------------------------------------------------------------------------- # Ask for login info # --------------------------------------------------------------------------- Added: trunk/gnue-forms/src/uidrivers/curses/dialogs.py =================================================================== --- trunk/gnue-forms/src/uidrivers/curses/dialogs.py 2005-04-28 11:17:58 UTC (rev 7499) +++ trunk/gnue-forms/src/uidrivers/curses/dialogs.py 2005-04-28 15:14:58 UTC (rev 7500) @@ -0,0 +1,192 @@ +# Short line describing the purpose of this file +# +# Copyright 2001-2005 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 + +# ============================================================================= +# Dialog box for selection an option from a given options dictionary +# ============================================================================= + +class OptionsDialog: + + # --------------------------------------------------------------------------- + # Constructor + # --------------------------------------------------------------------------- + + def __init__ (self, title, options, attrs, quit = None, left = 0, top = 0, + right = 80, bottom = 24): + + curses.noecho () + curses.cbreak () + + try: + self.__oldcursor = curses.curs_set (0) + except: + self.__oldcursor = 1 + + self.__data = ["%s" % item for item in options.values ()] + self.__data.sort () + + maxString = max ([len (item) for item in self.__data]) + + width = min (right - left, max ((maxString + 4), len (title) + 4)) + height = min (bottom - top, len (options) + 4) + left = max (left, (right - left - width) / 2) + top = max (top, (bottom - top - height) / 2) + + width = min (left + width, right) - left + height = min (top + height, bottom) - top + + self.__window = curses.newwin (height, width, top, left) + self.__window.keypad (1) + self.__window.box () + + self.__normal = attrs.get ('window 1', attrs ['background']) + self.__reverse = attrs ['focusentry'] + self.__quit = quit + + + self.__dwidth = width - 4 + self.__window.bkgd (' ', self.__normal) + self.__window.addstr (1, 2, title.center (self.__dwidth)) + self.__window.hline (2, 1, curses.ACS_HLINE, width - 2) + + self.__offset = 0 + self.__index = 0 + self.__pIndex = 1 + self.__page = height - 4 + + self.__refresh () + + + # --------------------------------------------------------------------------- + # Start the selection + # --------------------------------------------------------------------------- + + def run (self): + """ + Start the selection dialog. + + @return: selected item or None if canceled + """ + + self.__window.refresh () + + try: + while 1: + key = self.__window.getch () + + if key == 27 or key == self.__quit: + return None + + elif key == curses.KEY_UP: + self.__move (-1) + + elif key == curses.KEY_DOWN: + self.__move (+1) + + elif key == 10: + return self.__data [self.__index] + + finally: + try: + curses.curs_set (self.__oldcursor) + except: + pass + + + # --------------------------------------------------------------------------- + # Move the selection in a given direction + # --------------------------------------------------------------------------- + + def __move (self, direction): + + self.__pIndex += direction + self.__index += direction + + if self.__pIndex > self.__page: + if self.__index < len (self.__data): + self.__offset += direction + + elif self.__pIndex < 1: + self.__offset = max (0, self.__offset - 1) + + # Make sure to stay in bounds + self.__index = max (0, self.__index) + self.__index = min (len (self.__data) - 1, self.__index) + + self.__pIndex = max (1, self.__pIndex) + self.__pIndex = min (self.__page, self.__pIndex) + + self.__refresh () + + + # --------------------------------------------------------------------------- + # Refresh the dialog's window + # --------------------------------------------------------------------------- + + def __refresh (self): + + lines = self.__data [self.__offset:self.__offset + self.__page] + for (line, value) in enumerate (lines): + text = " %s " % value.ljust (self.__dwidth) [:self.__dwidth] + if line == self.__pIndex - 1: + attr = self.__reverse + else: + attr = self.__normal + + self.__window.addnstr (3 + line, 1, text, self.__dwidth + 2, attr) + + self.__window.move (3 + self.__pIndex - 1, 1) + + +# ============================================================================= +# Module self test +# ============================================================================= + +if __name__ == '__main__': + curses.initscr () + curses.raw () + curses.start_color () + + curses.init_pair (3, curses.COLOR_BLACK, curses.COLOR_CYAN) + curses.init_pair (4, curses.COLOR_BLUE, curses.COLOR_WHITE) + curses.init_pair (5, curses.COLOR_WHITE, curses.COLOR_RED) + + attrs = {'background': curses.color_pair (4), + 'focusentry': curses.color_pair (5), + 'window 1': curses.color_pair (3)} + + opts = {'foo': 'Foobar', 'baz': 'Barbaz and the Gang!', + 2: 'something', 3: 'quite', 4: 'interesting stuff', 5: 'hey ho', + 7: 'number 7'} + + opts = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8, 9:9, 10:10, 11:11, 12:12, + 13:13, 14:14, 15:15, 16:16, 17:17, 18:18, 19:19, 20:20} + d = OptionsDialog ('Foos', opts, attrs, quit = 23, top = 2, bottom = 22) + r = d.run () + + + curses.endwin () + + print "RESULT:", r Property changes on: trunk/gnue-forms/src/uidrivers/curses/dialogs.py ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py =================================================================== --- trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py 2005-04-28 11:17:58 UTC (rev 7499) +++ trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py 2005-04-28 15:14:58 UTC (rev 7500) @@ -50,6 +50,9 @@ self.__selection = {} self.__enabled = {} + if self.__style in ['dropdown', 'listbox']: + self.__allowedValues = event.object._field._allowedValues + if self.__style == 'checkbox': self._setCursor (1, 0) @@ -164,6 +167,21 @@ self._setText (index, text, attr, self.__selection [index]) + + # --------------------------------------------------------------------------- + # handle keypress + # --------------------------------------------------------------------------- + + def _keypress (self, key): + + if self.__style == 'dropdown' and key == chr (self._uiDriver.lookupKey): + res = self._uiDriver.getOption (u_("Select option"), self.__allowedValues) + if res is not None: + self._request ('REPLACEVALUE', text = res) + else: + UIHelper._keypress (self, key) + + # ============================================================================= # Configuration data # ============================================================================= _______________________________________________ Commit-gnue mailing list Commit-gnue@gnu.org http://lists.gnu.org/mailman/listinfo/commit-gnue