commit-gnue
[Top][All Lists]
Advanced

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

[gnue] r9120 - in trunk/gnue-forms/src/uidrivers/curses: . widgets


From: johannes
Subject: [gnue] r9120 - in trunk/gnue-forms/src/uidrivers/curses: . widgets
Date: Thu, 7 Dec 2006 03:38:13 -0600 (CST)

Author: johannes
Date: 2006-12-07 03:38:12 -0600 (Thu, 07 Dec 2006)
New Revision: 9120

Added:
   trunk/gnue-forms/src/uidrivers/curses/widgets/hbox.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/vbox.py
Modified:
   trunk/gnue-forms/src/uidrivers/curses/UIdriver.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/_base.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/box.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/button.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/form.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/label.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/page.py
   trunk/gnue-forms/src/uidrivers/curses/widgets/scrollbar.py
Log:
Aproaching managed layout


Modified: trunk/gnue-forms/src/uidrivers/curses/UIdriver.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/UIdriver.py   2006-12-07 07:58:07 UTC 
(rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/UIdriver.py   2006-12-07 09:38:12 UTC 
(rev 9120)
@@ -55,6 +55,7 @@
         self.__screen = curses.initscr()
         atexit.register(curses.endwin)
         curses.raw()
+        curses.noecho()
         curses.start_color()
 
         # Define colors
@@ -108,7 +109,9 @@
         self.__exiting = False
 
         KeyMapper.setUIKeyMap(self._keymap)
-        KeyMapper.loadUserKeyMap({'JUMPPROMPT': 'Ctrl-r'})
+        KeyMapper.loadUserKeyMap({'JUMPPROMPT': 'Ctrl-r',
+                                  'NEXTPAGE': 'PAGEDOWN',
+                                  'PREVPAGE': 'PAGEUP'})
 
         # Find out all functions mapped to function keys
                                         # Both hold [eventname, enabled] pairs:
@@ -135,6 +138,8 @@
 
     def _activateForm(self, form, modal):
 
+        assert gDebug(2, "ACTIVATING FORM")
+        form.set_size_and_fit()
         self.__current_form = form
 
     # -------------------------------------------------------------------------

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/_base.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/_base.py      2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/_base.py      2006-12-07 
09:38:12 UTC (rev 9120)
@@ -25,34 +25,59 @@
 
 from gnue.forms.uidrivers._base.widgets._base import UIWidget
 
+__all__ = ['UIHelper']
+
 # =============================================================================
 # Widget helper class
 # =============================================================================
 
-class UIHelper (UIWidget):
+class UIHelper(UIWidget):
+    """
+    The base class for all user interface widgets in the curses driver.
+    All UI widgets have a top/left coordinate as well as a width and height.
+    """
 
     # -------------------------------------------------------------------------
-    # Initialize
+    # Create a widget
     # -------------------------------------------------------------------------
 
-    def __init__ (self, event):
+    def _create_widget_(self, event, spacer):
+        """
+        Initialize the coordinates of a widget.  These coordinates will be set
+        later using set_size_and_fit().
+        """
 
-        UIWidget.__init__ (self, event)
+        self.top = 0
+        self.left = 0
+        self.width = 0
+        self.height = 0
 
-        # should go in base uidriver
-        self._parent = event.parent
-        self._x = self._gfObject ['Char:x']
-        self._y = self._gfObject ['Char:y']
+        self._parent = event.container
 
+
     # -------------------------------------------------------------------------
-    # Initialize widget
+    # Virtual methods
     # -------------------------------------------------------------------------
 
-    def _create_widget_(self, event, spacer):
+    def _container_is_ready_(self):
+        """
+        Descendants implement this method to determine wether their container
+        is ready for output or not.
+        """
+        parent = self.getParent()
+        if parent:
+            result = parent.ready()
+        else:
+            result = False
+        return result
 
-        # should go in base uidriver
-        self._init (spacer)
+    # -------------------------------------------------------------------------
 
+    def ready(self):
+        """ Returns wether the container is ready for output or not """
+        return self._container_is_ready_()
+
+    
     # -------------------------------------------------------------------------
     # Focus handling
     # -------------------------------------------------------------------------
@@ -74,17 +99,51 @@
 
         self._lose_focus(index)
 
+
     # -------------------------------------------------------------------------
     # Set text for widget
     # -------------------------------------------------------------------------
 
     def _set_text(self, index, text, attr, selection = None):
 
-        if selection:
-            (s1, s2) = selection
-            self._parent.write(self._x, self._y + index, text[:s1], attr)
-            self._parent.write(self._x + s1, self._y + index, text[s1:s2],
-                                attr + curses.A_STANDOUT)
-            self._parent.write(self._x + s2, self._y + index, text[s2:], attr)
+        if self.getParent().ready():
+            line = self.top + index * (self._gfObject._gap + 1)
+
+            if selection:
+                (s1, s2) = selection
+                self._parent.write(self.left, line, text[:s1], attr)
+                self._parent.write(self.left + s1, line, text[s1:s2],
+                                    attr + curses.A_STANDOUT)
+                self._parent.write(self.left + s2, line, text[s2:], attr)
+            else:
+                self._parent.write(self.left, line, text, attr)
+
+
+    # -------------------------------------------------------------------------
+    # Get the minimum size of a widget
+    # -------------------------------------------------------------------------
+
+    def get_size_hints(self):
+        """
+        Returns the minimal space needed by a widget as well as it's proportion
+        within it's container and the size of it's label (if any).  For a
+        positioned layout this is always the width and height specified in the
+        GFD file.  Descendants will likely override this method.
+
+        @returns: tuple (min-width, min-height, label-width, proportion)
+        """
+
+        if not self.managed:
+            return (self.chr_w, self.chr_h, 0, 0)
         else:
-            self._parent.write(self._x, self._y + index, text, attr)
+            return (20, 1, 0, 0)
+
+    # -------------------------------------------------------------------------
+    # Set the size for a widget and it's children
+    # -------------------------------------------------------------------------
+
+    def set_size_and_fit(self, width, height):
+        """
+        """
+        self.width = width
+        self.height = height

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/box.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/box.py        2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/box.py        2006-12-07 
09:38:12 UTC (rev 9120)
@@ -33,28 +33,37 @@
 
 class UIBox(UIHelper):
 
-    def _init(self, index):
+    # -------------------------------------------------------------------------
+    # Define the bounding box and draw it
+    # -------------------------------------------------------------------------
 
+    def set_size_and_fit(self, width, height):
+
+        self.width = width
+        self.height = height
+
         attr = self._uiDriver.attr['background']
 
-        w = self._gfObject['Char:width']
-        h = self._gfObject['Char:height']
+        for pos in range(self.left+1, self.left+self.width-1):
+            self._parent.putchar(pos, self.top, curses.ACS_HLINE, attr)
+            self._parent.putchar(pos, self.top+self.height-1, curses.ACS_HLINE,
+                    attr)
 
-        for pos in range(self._x+1, self._x+w-1):
-            self._parent.putchar(pos, self._y    , curses.ACS_HLINE, attr)
-            self._parent.putchar(pos, self._y+h-1, curses.ACS_HLINE, attr)
+        for line in range(self.top+1, self.top+self.height-1):
+            self._parent.putchar(self.left, line, curses.ACS_VLINE, attr)
+            self._parent.putchar(self.left+self.width-1, line,
+                    curses.ACS_VLINE, attr)
 
-        for line in range(self._y+1, self._y+h-1):
-            self._parent.putchar(self._x    , line, curses.ACS_VLINE, attr)
-            self._parent.putchar(self._x+w-1, line, curses.ACS_VLINE, attr)
+        self._parent.putchar(self.left, self.top, curses.ACS_ULCORNER, attr)
+        self._parent.putchar(self.left+self.width-1, self.top,
+                curses.ACS_URCORNER, attr)
+        self._parent.putchar(self.left, self.top+self.height-1,
+                curses.ACS_LLCORNER, attr)
+        self._parent.putchar(self.left+self.width-1, self.top+self.height-1,
+                curses.ACS_LRCORNER, attr)
 
-        self._parent.putchar(self._x, self._y, curses.ACS_ULCORNER, attr)
-        self._parent.putchar(self._x+w-1, self._y, curses.ACS_URCORNER, attr)
-        self._parent.putchar(self._x, self._y+h-1, curses.ACS_LLCORNER, attr)
-        self._parent.putchar(self._x+w-1, self._y+h-1, curses.ACS_LRCORNER,
-                attr)
+        self._parent.write(self.left+2, self.top, self._gfObject.label, attr)
 
-        self._parent.write(self._x+2, self._y, self._gfObject.label, attr)
 
 # =============================================================================
 # Configuration data

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/button.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/button.py     2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/button.py     2006-12-07 
09:38:12 UTC (rev 9120)
@@ -31,7 +31,7 @@
 # Button class
 # =============================================================================
 
-class UIButton (UIHelper):
+class UIButton(UIHelper):
 
     # -------------------------------------------------------------------------
     # Initialization
@@ -41,24 +41,16 @@
 
         UIHelper.__init__(self, event)
 
-        # Determine button text
-        maxlen = event.object['Char:width'] - 2
-        label = event.object.label[:maxlen]                # cut if too long
-        label = ' ' * ((maxlen - len(label)) / 2) + label  # expand if too 
short
-        label = label + ' ' * (maxlen - len(label))
-
-        self.__text = '[' + label + ']'
-
         self.__enabled = {}
 
     # -------------------------------------------------------------------------
     # Initialization per row
     # -------------------------------------------------------------------------
 
-    def _init(self, index):
+    def _create_widget_(self, event, spacer):
 
-        self.__enabled[index] = True
-        self.__repaint(index, False)
+        UIHelper._create_widget_(self, event, spacer)
+        self.__enabled[spacer] = True
 
     # -------------------------------------------------------------------------
     # Enable/disable this button
@@ -113,7 +105,26 @@
         else:
             UIHelper._keypress(self, key)
 
+    def get_size_hints(self):
 
+        return (self.min_width or 20, 1, 0, 0)
+
+    def set_size_and_fit(self, width, height):
+
+        self.width = width
+        self.height = height
+        # Determine button text
+        maxlen = width - 2
+        label = self._gfObject.label[:maxlen]              # cut if too long
+        label = ' ' * ((maxlen - len(label)) / 2) + label  # expand if too 
short
+        label = label + ' ' * (maxlen - len(label))
+
+        self.__text = '[' + label + ']'
+
+        for index in range(len(self.widgets)):
+            self.__repaint(index, False)
+
+
 # =============================================================================
 # Configuration data
 # =============================================================================

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py      2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/entry.py      2006-12-07 
09:38:12 UTC (rev 9120)
@@ -39,23 +39,14 @@
 
         UIHelper.__init__(self, event)
 
-        self.__style = event.object.style
-        if self.__style in ['default', 'password', 'label', 'dropdown',
-                'listbox', 'multiline']:
-            self.__length = event.object['Char:width']
-        else:
-            self.__length = None
-
-        self.__height    = event.object['Char:height']
-        self.__value     = {}
-        self.__offset    = {}
+        self.__style = self._gfObject.style
+        self.__value = {}
+        self.__offset = {}
         self.__selection = {}
-        self.__enabled   = {}
-        self.__voffset   = {}
+        self.__enabled = {}
+        self.__voffset = {}
 
-        self.__isMultiline = (self.__style in ['default', 'password'] and \
-                              self.__height > 1) or self.__style == 'multiline'
-
+        self.__isMultiline = (self.__style == 'multiline')
         self.__focusIndex = None
 
         self.__cursor = (0, 0)
@@ -73,16 +64,21 @@
     # Initialization per row
     # -------------------------------------------------------------------------
 
-    def _init(self, index):
+    def _create_widget_(self, event, spacer):
 
-        self.__value[index] = None
-        self.__selection[index] = None
-        self.__enabled[index] = True
-        self.__offset[index]  = 0
-        self.__voffset[index] = 0
-        self.__index[index]   = 0
-        self.__pindex[index]  = 1
+        UIHelper._create_widget_(self, event, spacer)
+        gDebug(2, "Creating widget: %s[%s]" % (self._gfObject.name, spacer))
+        
+        self.__value[spacer] = None
+        self.__selection[spacer] = None
+        self.__enabled[spacer] = True
+        self.__offset[spacer]  = 0
+        self.__voffset[spacer] = 0
+        self.__index[spacer]   = 0
+        self.__pindex[spacer]  = 1
+        gLeave(2)
 
+
     # -------------------------------------------------------------------------
     # Enable/disable this entry
     # -------------------------------------------------------------------------
@@ -114,9 +110,9 @@
             self.__oldCursor = curses.curs_set(0)
 
         self.__updateCursorPosition()
-
         self.__repaint(index)
 
+
     # -------------------------------------------------------------------------
     # Focus has changed away from this entry
     # -------------------------------------------------------------------------
@@ -143,7 +139,7 @@
                 self.__pindex[index] = 1
                 self.__offset[index] = self.__index[index]
 
-        self.__value[index]   = value
+        self.__value[index] = value
         self.__repaint(index)
 
     # -------------------------------------------------------------------------
@@ -160,6 +156,9 @@
 
     def _ui_set_cursor_position_(self, index, position):
 
+        if not self.ready():
+            return
+
         old_selection = self.__selection[index]
         self.__selection[index] = None
         need_repaint = old_selection is not None
@@ -180,9 +179,9 @@
                 self.__setCursor(0, 0)
                 return
 
-            # Grab the text portion, which is everything up to position. If 
the last
-            # character is a newline, we can remove this, since it would 
result in a
-            # wrong vertical offset
+            # Grab the text portion, which is everything up to position. If the
+            # last character is a newline, we can remove this, since it would
+            # result in a wrong vertical offset
             value = self.__value[index][:position+1]
             vcorr = [0, 1][value[-1] == '\n']
 
@@ -200,12 +199,12 @@
                 cpVertical  = 1
                 need_repaint = True
 
-            elif cpVertical >= self.__height:
+            elif cpVertical >= self.height:
                 # the position is not visible right now, so we need to scroll
                 # down (which means changing the voffset).
                 self.__voffset[index] = value.count('\n') - \
-                        self.__height + 1 - vcorr
-                cpVertical  = self.__height            # Pos. are Zero-based
+                        self.height + 1 - vcorr
+                cpVertical  = self.height            # Pos. are Zero-based
                 need_repaint = True
 
             # Now, after having a valid row, we need to determine the 
horizontal
@@ -219,17 +218,17 @@
                 cpHorizontal = 0
                 need_repaint  = True
 
-            elif cpHorizontal > self.__length:
-                self.__offset[index] = len(currentLine) - self.__length
-                cpHorizontal = self.__length
+            elif cpHorizontal > self.width:
+                self.__offset[index] = len(currentLine) - self.width
+                cpHorizontal = self.width
                 need_repaint  = True
 
             if need_repaint:
                 self.__repaint(index)
 
-            cpHorizontal = min(cpHorizontal, self.__length)
+            cpHorizontal = min(cpHorizontal, self.width)
             cpHorizontal = max(cpHorizontal, 0)
-            cpVertical   = min(cpVertical, self.__height - 1)
+            cpVertical   = min(cpVertical, self.height - 1)
             cpVertical   = max(cpVertical, 0)
 
             assert gDebug(2, "H/V: %s/%s - Offsets %s/%s" % (cpHorizontal,
@@ -239,11 +238,11 @@
 
 
         else:
-            if self.__length:
+            if self.__style != ['checkbox']:
                 npos = position - self.__offset[index]
-                if npos > self.__length:
-                    self.__offset[index] = position - self.__length
-                    npos = self.__length
+                if npos > self.width:
+                    self.__offset[index] = position - self.width
+                    npos = self.width
                     self.__repaint(index)
                     need_repaint = False
 
@@ -303,33 +302,36 @@
 
     def __repaint(self, index):
 
+        if not self.ready():
+            return
+
         if self.__style == 'listbox':
             # First draw the visible items of the listbox
             offset = self.__offset[index]
-            lines  = self.__choices[offset:offset + self.__height]
+            lines  = self.__choices[offset:offset + self.height]
 
             for (line, value) in enumerate(lines):
-                text = value.ljust(self.__length)[:self.__length]
+                text = value.ljust(self.width)[:self.width]
                 attr = self.__getAttr(index)
 
                 # Note: this is not safe if there's a gap !
                 self._set_text(index+line, text, attr, self.__selection[index])
 
-            self._parent.move(self._x, self._y + self.__pindex[index] - 1)
+            self._parent.move(self.left, self.top + self.__pindex[index] - 1)
 
         elif self.__isMultiline:
             # Create all visible, empty lines
-            gDebug(2, "LEN: %s, H: %s" % (self.__length, self.__height))
-            data    = [''.ljust(self.__length)] * self.__height
+            gDebug(2, "LEN: %s, H: %s" % (self.width, self.height))
+            data    = [''.ljust(self.width)] * self.height
             hOffset = self.__offset[index]
             vOffset = self.__voffset[index]
 
             # Overwrite these empty lines with the data as stated by v/h-Offset
             if self.__value[index]:
-                add = 
self.__value[index].splitlines()[vOffset:vOffset+self.__height]
+                add = 
self.__value[index].splitlines()[vOffset:vOffset+self.height]
                 for (ix, text) in enumerate(add):
-                    text = text[hOffset:hOffset + self.__length]
-                    data[ix] = text.ljust(self.__length)[:self.__length]
+                    text = text[hOffset:hOffset + self.width]
+                    data[ix] = text.ljust(self.width)[:self.width]
 
             attr = self.__getAttr(index)
 
@@ -344,13 +346,13 @@
 
             if self.__style in['default', 'label', 'dropdown']:
                 text = value or ''
-                text = text[offset:offset + self.__length]
-                text += ' ' * (self.__length - len(text))
+                text = text[offset:offset + self.width]
+                text += ' ' * (self.width - len(text))
 
             elif self.__style == 'password':
                 text = '*' * len(value or '')
-                text = text[offset:offset + self.__length]
-                text += ' ' * (self.__length - len(text))
+                text = text[offset:offset + self.width]
+                text += ' ' * (self.width - len(text))
 
             elif self.__style == 'checkbox':
                 if self.__value[index] is None:
@@ -425,7 +427,7 @@
         self.__pindex[index] += direction
         self.__index[index] += direction
 
-        if self.__pindex[index] > self.__height:
+        if self.__pindex[index] > self.height:
             if self.__index[index] < len(self.__choices):
                 self.__offset[index] += direction
 
@@ -436,10 +438,11 @@
         self.__index[index] = min(len(self.__choices) - 1, self.__index[index])
 
         self.__pindex[index] = max(1, self.__pindex[index])
-        self.__pindex[index] = min(self.__pindex[index], self.__height)
+        self.__pindex[index] = min(self.__pindex[index], self.height)
 
         self.__value[index] = self.__choices[self.__index[index]]
-        self._request('REPLACEVALUE', text = 
self.__choices[self.__index[index]])
+        self._request('REPLACEVALUE', text =
+                self.__choices[self.__index[index]])
 
     # -------------------------------------------------------------------------
     # Set cursor position for widget
@@ -458,8 +461,31 @@
 
         if self.__focusIndex is not None:
             (x, y) = self.__cursor
-            self._parent.move(self._x + x, self._y + self.__focusIndex + y)
+            self._parent.move(self.left + x, self.top + self.__focusIndex + y)
 
+    def set_size_and_fit(self, width, height):
+
+        self.width = width
+        self.height = height
+
+        for index in range(len(self.widgets)):
+            self.__repaint(index)
+
+    # -------------------------------------------------------------------------
+    # Get the size hints for an entry
+    # -------------------------------------------------------------------------
+
+    def get_size_hints(self):
+
+        label = ''
+        if self.__style != 'checkbox':
+            label = getattr(self._gfObject, 'label', '')
+
+        result = (self.min_width or 20, self.min_height or 1, len(label),
+                self.stretch)
+        gLeave(2, result)
+        return result
+
 # =============================================================================
 # Configuration data
 # =============================================================================

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/form.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/form.py       2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/form.py       2006-12-07 
09:38:12 UTC (rev 9120)
@@ -25,8 +25,7 @@
 
 from gnue.forms.input.GFKeyMapper import KeyMapper
 
-from gnue.forms.uidrivers._base import UIdriver as BaseDriver
-from gnue.forms.uidrivers._base.widgets._base import UIWidget
+from gnue.forms.uidrivers.curses.widgets._base import UIHelper
 
 __all__ = ['UIForm']
 
@@ -34,7 +33,7 @@
 # Form class
 # =============================================================================
 
-class UIForm(UIWidget):
+class UIForm(UIHelper):
 
     # -------------------------------------------------------------------------
     # Initialization
@@ -42,7 +41,8 @@
 
     def __init__(self, event):
 
-        UIWidget.__init__(self, event)
+        gDebug(2, "Base is %s" % UIHelper)
+        UIHelper.__init__(self, event)
 
         self.__pages = []
         self.__currentPage = None
@@ -51,29 +51,42 @@
         self.__tip = ''
         self.__status = ''
         self.__insert = ''
-        self.__curRec = 0
-        self.__maxRec = 0
-        self.__curPage = 0
-        self.__maxPage = 0
+        self.__cur_rec = 0
+        self.__max_rec = 0
+        self.__cur_page = 0
+        self.__max_page = 0
 
+
     # -------------------------------------------------------------------------
     # Initialize form
     # -------------------------------------------------------------------------
 
-    def create_widget(self, event, spacer):
+    def _create_widget_(self, event, spacer):
 
-        (x, y) = event.interface.screen_size()
-        self.__window = curses.newpad(y, x)
-        self.__window.keypad(1)
+        gDebug(2, "creating form widget: %s" % self.managed)
+        self.__window = None
+        self._container = self
 
-        self._ui_set_title_(event.object.title)
 
     # -------------------------------------------------------------------------
+    # Virtual methods
+    # -------------------------------------------------------------------------
+
+    def _container_is_ready_(self):
+
+        gEnter(2)
+        return self.__window is not None
+
+
+    # -------------------------------------------------------------------------
     # Set form title
     # -------------------------------------------------------------------------
 
     def _ui_set_title_(self, title):
 
+        if not self.__window:
+            return
+
         (y, x) = self.__window.getmaxyx()
 
         text = ' ' * ((x - len(title)) / 2) + title
@@ -102,18 +115,18 @@
 
     # -------------------------------------------------------------------------
 
-    def _ui_update_status_(self, tip, status, insert, curRec, maxRec, curPage,
-                       maxPage):
+    def _ui_update_status_(self, tip, status, insert, cur_rec, max_rec,
+            cur_page, max_page):
 
         # Gets called with incomplete parameters, so we always have to remember
         # the old values for missing parameters
         if tip     is not None: self.__tip     = tip
         if status  is not None: self.__status  = status
         if insert  is not None: self.__insert  = insert
-        if curRec  is not None: self.__curRec  = curRec
-        if maxRec  is not None: self.__maxRec  = maxRec
-        if curPage is not None: self.__curPage = curPage
-        if maxPage is not None: self.__maxPage = maxPage
+        if cur_rec  is not None: self.__cur_rec  = cur_rec
+        if max_rec  is not None: self.__max_rec  = max_rec
+        if cur_page is not None: self.__cur_page = cur_page
+        if max_page is not None: self.__max_page = max_page
 
         self.__update_status_bar()
 
@@ -137,9 +150,13 @@
 
     def status_message(self, message):
 
+        if not self.ready():
+            return
+
+        gDebug(2, "StatusMessage: %s" % message)
         if message:
             (y, x) = self.__window.getmaxyx()
-            self.__window.bkgdset(' ', self._uiDriver.attr ['status'])
+            self.__window.bkgdset(' ', self._uiDriver.attr['status'])
             self.__window.addstr(y - 2, 0, o(message))
             self.__window.clrtoeol()
             self.__window.refresh(y - 2, 0, y - 2, 0, y - 2, x)
@@ -178,8 +195,14 @@
 
     def get_canvas(self):
 
-        (y, x) = self.__window.getmaxyx()
-        return (0, 2, x, y - 2)
+        gEnter(2)
+        if self.ready():
+            gDebug(2, "Ready for action!")
+            (y, x) = self.__window.getmaxyx()
+            return (0, 2, x, y - 2)
+        else:
+            gDebug(2, "not ready yet")
+            return None
 
     # -------------------------------------------------------------------------
     # Update page list
@@ -187,6 +210,9 @@
 
     def __update_page_list(self):
 
+        if not self.ready():
+            return
+
         self.__window.bkgdset(' ', self._uiDriver.attr ['page'])
         self.__window.move(1, 0)
 
@@ -198,7 +224,6 @@
                                       self._uiDriver.attr ['currentpage'])
             else:
                 self.__window.addstr('[' + o(caption) + ']')
-            # self.__window.addstr (' ')
 
         self.__window.clrtoeol()
 
@@ -211,13 +236,16 @@
 
     def __update_status_bar(self):
 
+        if not self.ready():
+            return
+
         (y, x) = self.__window.getmaxyx()
         self.__window.bkgdset(' ', self._uiDriver.attr ['status'])
 
         tip = ('%-' + str(x - 25) + 's') % self.__tip
 
-        recstr = '%d/%d' % (self.__curRec, self.__maxRec)
-        pagestr = '%d/%d' % (self.__curPage, self.__maxPage)
+        recstr = '%d/%d' % (self.__cur_rec, self.__max_rec)
+        pagestr = '%d/%d' % (self.__cur_page, self.__max_page)
 
         self.__window.addstr(y - 2, 0,      '%s'   % o(tip))
         self.__window.addstr(y - 2, x - 24, '%-4s' % o(self.__status))
@@ -230,7 +258,7 @@
         self.__window.addch(y - 2, x - 16, curses.ACS_VLINE)
         self.__window.addch(y - 2, x -  6, curses.ACS_VLINE)
 
-        self.__window.bkgdset(' ', self._uiDriver.attr ['fkeys'])
+        self.__window.bkgdset(' ', self._uiDriver.attr['fkeys'])
 
         self.__window.addstr(y-1, 0, o(self._uiDriver.getFunctionKeyLine()))
         self.__window.clrtoeol()
@@ -245,7 +273,34 @@
 
         pass
 
+    # -------------------------------------------------------------------------
+    # Create the window and fit all widgets into the available space
+    # -------------------------------------------------------------------------
 
+    def set_size_and_fit(self):
+        """
+        Create the window for the form and 
+        """
+
+        gEnter(2)
+
+        (x, y) = self._uiDriver.screen_size()
+        self.__window = curses.newpad(y, x)
+        self.__window.keypad(1)
+        self._ui_set_title_(self._gfObject.title)
+
+        # The children of a form are pages which can have all the available
+        # space
+        for child in self._children:
+            child.set_size_and_fit(x, y)
+
+        gDebug(2, "creating windows for form-widget")
+
+        self.__update_page_list()
+        self.__update_status_bar()
+
+
+
 # =============================================================================
 # Configuration data
 # =============================================================================

Added: trunk/gnue-forms/src/uidrivers/curses/widgets/hbox.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/hbox.py       2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/hbox.py       2006-12-07 
09:38:12 UTC (rev 9120)
@@ -0,0 +1,166 @@
+# GNU Enterprise Forms - Curses UI Driver - VBox Widget
+#
+# Copyright 2000-2006 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 _base import UIHelper
+
+__all__ = ['UIHBox']
+
+# =============================================================================
+# VBox class
+# =============================================================================
+
+class UIHBox(UIHelper):
+
+    def _create_widget_(self, event, spacer):
+
+        UIHelper._create_widget_(self, event, spacer)
+        self._parent = event.container
+        self._container = self._parent
+
+
+    def set_size_and_fit(self, width, height):
+
+        right, bottom = self.left + width - 1, self.top + height - 1
+        gDebug(2, "Size for hbox: %s/%s %s/%s %s/%s" % (width, height,
+            self.left,
+            self.top, right, bottom))
+
+        attr = self._uiDriver.attr['background']
+
+        if self._gfObject.label:
+            for pos in range(self.left+1, right):
+                self._parent.putchar(pos, self.top, curses.ACS_HLINE, attr)
+                self._parent.putchar(pos, bottom, curses.ACS_HLINE, attr)
+
+            for line in range(self.top+1, bottom):
+                self._parent.putchar(self.left, line, curses.ACS_VLINE, attr)
+                self._parent.putchar(right, line, curses.ACS_VLINE, attr)
+
+            self._parent.putchar(self.left, self.top, curses.ACS_ULCORNER, 
attr)
+            self._parent.putchar(right, self.top, curses.ACS_URCORNER, attr)
+            self._parent.putchar(self.left, bottom, curses.ACS_LLCORNER, attr)
+            self._parent.putchar(right, bottom, curses.ACS_LRCORNER, attr)
+
+            self._parent.write(self.left+2, self.top, self._gfObject.label,
+                    attr)
+            # If there is a border around the box, all children have less space
+            # available
+            width -= 2
+            height -= 2
+
+        hints = {}
+        for (index, child) in enumerate(self._children):
+            hints[index] = child.get_size_hints()
+
+        # Total of the stretching (proportion)
+        sum_sx = float(sum([i[3] for i in hints.values()]))
+
+        # Reorder the list of size-hints starting with the highest
+        # stretching factor
+        needed = 0
+        ordered = []
+        for key, (minw, minh, label, propx) in hints.items():
+            ordered.append((propx, key))
+            needed += minw
+        ordered.sort()
+        ordered.reverse()
+
+        # Now let's have a look how much space is left if all children have
+        # used up their minimum width
+        available = width - needed
+
+        gDebug(2, "Ordered: w=%s n=%s a=%s o=%s" % (width, needed, available, 
ordered))
+
+        # First assign the minimum space required to each child
+        sizes = {}
+        for (propx, index) in ordered:
+            child = self._children[index]
+
+            (minw, minh, label, propx) = hints[index]
+
+            current_w = max(minw, label)
+            current_h = minh
+
+            if propx and available:
+                add = int(available / sum_sx * propx)
+                current_w += add
+                available -= add
+                gDebug(2, "Adding %s to %s" % (add, child._gfObject.name))
+            else:
+                gDebug(2, "Propx: %s, av: %s" % (propx, available))
+
+            sizes[index] = (current_w, current_h)
+
+        last_x = self.left + 1
+        for (index, child) in enumerate(self._children):
+            cwidth, cheight = sizes[index]
+            child.left = last_x
+            child.top = self.top + 2
+            last_x += cwidth
+
+            gDebug(2, "Child %s: %x/%s" % (child._gfObject.name, child.left,
+                child.top))
+            # If there's a label, add it to the parent's window
+            if hints[index][2]:
+                attr = self._uiDriver.attr['background']
+                self._parent.write(child.left, child.top-1,
+                        child._gfObject.label, attr)
+            child.set_size_and_fit(cwidth, cheight)
+
+
+
+    # -------------------------------------------------------------------------
+    # Get the size hints for the vbox
+    # -------------------------------------------------------------------------
+
+    def get_size_hints(self):
+
+        hints = []
+        for child in self._children:
+            hints.append(child.get_size_hints())
+
+        if hints:
+            minw = max([i[0] for i in hints]) + 3
+            minh = sum([i[1] for i in hints]) + 2
+            prop = sum([i[3] for i in hints])
+        else:
+            minw = minh = 2 
+            prop = 0
+
+        gDebug(2, "min: %s %s %s %s" % (minw, minh, 1, prop))
+
+        return (minw, minh, 1, prop)
+
+
+
+# =============================================================================
+# Configuration data
+# =============================================================================
+
+configuration = {
+  'baseClass'  : UIHBox,
+  'provides'   : 'GFHBox',
+  'container'  : 0,
+}

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/label.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/label.py      2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/label.py      2006-12-07 
09:38:12 UTC (rev 9120)
@@ -31,9 +31,14 @@
 
 class UILabel(UIHelper):
 
-    def _init(self, index):
+    def _create_widget_(self, event, spacer):
 
-        self._set_text(index, self._gfObject.text,
+        UIHelper._create_widget_(self, event, spacer)
+
+    def set_size_and_fit(self, width, height):
+
+        for index in range(len(self.widgets)):
+            self._set_text(index, self._gfObject.text,
                 self._uiDriver.attr['background'])
 
 # =============================================================================

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/page.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/page.py       2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/page.py       2006-12-07 
09:38:12 UTC (rev 9120)
@@ -23,14 +23,14 @@
 
 import curses
 
-from gnue.forms.uidrivers._base.widgets._base import UIWidget
 from gnue.common.apps import i18n
+from _base import UIHelper
 
 # =============================================================================
 # Page class
 # =============================================================================
 
-class UIPage (UIWidget):
+class UIPage(UIHelper):
 
     # -------------------------------------------------------------------------
     # Initialize page
@@ -41,37 +41,136 @@
         caption = getattr(self._gfObject, 'caption', None) or \
                 self._gfObject.name
 
+        self.__window = None
+        self.__cursor = (0, 0)
+        self._container = self
+
+        self._parent = event.container
         event.parent.add_page(self, caption)
 
-        (self.__x1, self.__y1, self.__x2, self.__y2) = 
event.parent.get_canvas()
 
-        self.__window = curses.newpad(self.__y2 - self.__y1, self.__x2 -
-                self.__x1)
+    # -------------------------------------------------------------------------
+    # Virtual methods
+    # -------------------------------------------------------------------------
+
+    def _container_is_ready_(self):
+
+        return self.__window is not None
+
+
+    # -------------------------------------------------------------------------
+    # Set the page sizes and fit their children
+    # -------------------------------------------------------------------------
+
+    def set_size_and_fit(self, width, height):
+
+        gDebug(2, "Parent: %s" % self._parent._gfObject.name)
+        (self.left, self.top, self.right, self.bottom) = \
+                self._parent.get_canvas()
+
+        width, height = self.right - self.left, self.bottom - self.top
+
+        gDebug(2, "Size of Page: %s/%s at %s/%s %s/%s" % \
+                (width, height, self.left, self.top, self.right, self.bottom))
+
+        self.__window = curses.newpad(height, width)
         self.__window.keypad(1)
         self.__window.bkgd(' ', self._uiDriver.attr['background'])
-        self.__cursor = (0, 0)
 
+        if not self.managed:
+            for child in self._children:
+                child.left = child.chr_x
+                child.top = child.chr_y
+
+                child.set_size_and_fit(child.chr_w, child.chr_h)
+        else:
+            # Note: a page is an implicit vbox, so all it's childrens are lined
+            # up vertically
+
+            hints = {}
+            for (index, child) in enumerate(self._children):
+                hints[index] = child.get_size_hints()
+
+            # Total of the stretching (proportion)
+            sum_sy = float(sum([i[3] for i in hints.values()]))
+
+            # Reorder the list of size-hints starting with the highest
+            # stretching factor (vertical)
+            needed = 0
+            ordered = []
+            for key, (minw, minh, label, stretch) in hints.items():
+                ordered.append((stretch, key))
+                needed += minh
+            ordered.sort()
+            ordered.reverse()
+
+            # Now let's have a look how much space is left if all children have
+            # used up their minimum height
+            available = height - needed
+
+            gDebug(2, "Ordered: %s/%s: %s" % (needed, available, ordered))
+
+            # First assign the minimum space required to each child
+            sizes = {}
+            for (propy, index) in ordered:
+                child = self._children[index]
+
+                (minw, minh, label, propy) = hints[index]
+
+                # A page is like a vbox, so all children can use all the
+                # horizontal space 
+                current_w = width
+                current_h = minh
+
+                if propy and available:
+                    add = int(available / sum_sy * propy)
+                    current_h += add
+                    available -= add
+
+                sizes[index] = (current_w, current_h)
+
+            last_y = 0
+            for (index, child) in enumerate(self._children):
+                cwidth, cheight = sizes[index]
+                child.left = 0
+                child.top = last_y
+                last_y += cheight
+
+                gDebug(2, "Child %s: %x/%s" % (child._gfObject.name, 
child.left,
+                    child.top))
+                child.set_size_and_fit(cwidth, cheight)
+
+
     # -------------------------------------------------------------------------
     # Write a text to a given position
     # -------------------------------------------------------------------------
 
-    def write (self, x, y, text, attribute):
+    def write(self, x, y, text, attribute):
 
-        self.__window.addstr (y, x, o(text), attribute)
+        if self.ready():
+            try:
+                self.__window.addstr(y, x, o(text), attribute)
+            except curses.error:
+                pass
 
+
     # -------------------------------------------------------------------------
     # Write a special character to a given position
     # -------------------------------------------------------------------------
 
     def putchar (self, x, y, char, attribute):
 
-        self.__window.addch (y, x, char, attribute)
+        if self.ready():
+            try:
+                self.__window.addch (y, x, char, attribute)
+            except curses.error:
+                pass
 
     # -------------------------------------------------------------------------
     # Move the cursor to a given position
     # -------------------------------------------------------------------------
 
-    def move (self, x, y):
+    def move(self, x, y):
 
         self.__cursor = (x, y)
 
@@ -79,10 +178,13 @@
     # Update screen and wait for user input
     # -------------------------------------------------------------------------
 
-    def wait (self):
+    def wait(self):
 
-        self.__window.move (self.__cursor [1], self.__cursor [0])
-        self.__window.refresh (0, 0, self.__y1, self.__x1, self.__y2, 
self.__x2)
+        self.__window.move(self.__cursor[1], self.__cursor[0])
+        gDebug(2, "Refresh of page: %s/%s %s/%s" % (self.top, self.left,
+            self.bottom, self.right))
+        self.__window.refresh(0, 0, self.top, self.left, self.bottom,
+                self.right)
         return self.__get_key()
 
     # -------------------------------------------------------------------------
@@ -129,6 +231,7 @@
         return unicode("".join([chr(i) for i in result]), i18n.encoding)
 
 
+
 # =============================================================================
 # Configuration data
 # =============================================================================
@@ -137,4 +240,4 @@
   'baseClass'  : UIPage,
   'provides'   : 'GFPage',
   'container'  : 1,
-  }
+}

Modified: trunk/gnue-forms/src/uidrivers/curses/widgets/scrollbar.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/scrollbar.py  2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/scrollbar.py  2006-12-07 
09:38:12 UTC (rev 9120)
@@ -29,7 +29,7 @@
 
 class UIScrollBar (UIHelper):
 
-  def _init (self, index):
+  def _create_widget_(self, event, spacer):
     pass
 
   def _ui_adjust_scrollbar_(self, position, size, count):

Added: trunk/gnue-forms/src/uidrivers/curses/widgets/vbox.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/curses/widgets/vbox.py       2006-12-07 
07:58:07 UTC (rev 9119)
+++ trunk/gnue-forms/src/uidrivers/curses/widgets/vbox.py       2006-12-07 
09:38:12 UTC (rev 9120)
@@ -0,0 +1,167 @@
+# GNU Enterprise Forms - Curses UI Driver - VBox Widget
+#
+# Copyright 2000-2006 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 _base import UIHelper
+
+__all__ = ['UIVBox']
+
+# =============================================================================
+# VBox class
+# =============================================================================
+
+class UIVBox(UIHelper):
+
+    def _create_widget_(self, event, spacer):
+
+        UIHelper._create_widget_(self, event, spacer)
+        self._parent = event.container
+        self._container = self._parent
+
+
+    def set_size_and_fit(self, width, height):
+
+        right, bottom = self.left + width - 1, self.top + height - 1
+        gDebug(2, "Size for vbox: %s/%s %s/%s %s/%s" % (width, height,
+            self.left,
+            self.top, right, bottom))
+
+        attr = self._uiDriver.attr['background']
+
+        if self._gfObject.label:
+            for pos in range(self.left+1, right):
+                self._parent.putchar(pos, self.top, curses.ACS_HLINE, attr)
+                self._parent.putchar(pos, bottom, curses.ACS_HLINE, attr)
+
+            for line in range(self.top+1, bottom):
+                self._parent.putchar(self.left, line, curses.ACS_VLINE, attr)
+                self._parent.putchar(right, line, curses.ACS_VLINE, attr)
+
+            self._parent.putchar(self.left, self.top, curses.ACS_ULCORNER, 
attr)
+            self._parent.putchar(right, self.top, curses.ACS_URCORNER, attr)
+            self._parent.putchar(self.left, bottom, curses.ACS_LLCORNER, attr)
+            self._parent.putchar(right, bottom, curses.ACS_LRCORNER, attr)
+
+            self._parent.write(self.left+2, self.top, self._gfObject.label,
+                    attr)
+            # If there is a border around the box, all children have less space
+            # available
+            width -= 2
+            height -= 2
+
+        hints = {}
+        for (index, child) in enumerate(self._children):
+            hints[index] = child.get_size_hints()
+
+        # Total of the stretching (proportion)
+        sum_sy = float(sum([i[3] for i in hints.values()]))
+
+        # The widest label
+        widest_label = max([i[2] for i in hints.values()])
+
+        # Reorder the list of size-hints starting with the highest
+        # stretching factor (vertical)
+        needed = 0
+        ordered = []
+        for key, (minw, minh, label, propy) in hints.items():
+            ordered.append((propy, key))
+            needed += minh
+        ordered.sort()
+        ordered.reverse()
+
+        # Now let's have a look how much space is left if all children have
+        # used up their minimum height
+        available = height - needed
+
+        gDebug(2, "Ordered: %s/%s: %s" % (needed, available, ordered))
+
+        # First assign the minimum space required to each child
+        sizes = {}
+        for (propy, index) in ordered:
+            child = self._children[index]
+
+            (minw, minh, label, propy) = hints[index]
+
+            current_w = width - widest_label - 2
+            current_h = minh
+
+            if propy and available:
+                add = int(available / sum_sy * propy)
+                current_h += add
+                available -= add
+                gDebug(2, "Adding %s to %s" % (add, child._gfObject.name))
+
+            sizes[index] = (current_w, current_h)
+
+        last_y = self.top + 1
+        for (index, child) in enumerate(self._children):
+            cwidth, cheight = sizes[index]
+            child.left = self.left + widest_label + 2
+            child.top = last_y
+            last_y += cheight
+
+            gDebug(2, "Child %s: %x/%s" % (child._gfObject.name, child.left,
+                child.top))
+            # If there's a label, add it to the parent's window
+            if hints[index][2]:
+                attr = self._uiDriver.attr['background']
+                self._parent.write(self.left + 1, child.top,
+                        child._gfObject.label, attr)
+            child.set_size_and_fit(cwidth, cheight)
+
+
+
+    # -------------------------------------------------------------------------
+    # Get the size hints for the vbox
+    # -------------------------------------------------------------------------
+
+    def get_size_hints(self):
+
+        hints = []
+        for child in self._children:
+            hints.append(child.get_size_hints())
+
+        if hints:
+            widest_label = max([i[2] for i in hints])
+            minw = widest_label + max([i[0] for i in hints]) + 3
+            minh = sum([i[1] for i in hints]) + 2
+            prop = sum([i[3] for i in hints])
+        else:
+            minw = minh = 2 
+            prop = 0
+
+        gDebug(2, "min: %s %s %s %s" % (minw, minh, 1, prop))
+
+        return (minw, minh, 1, prop)
+
+
+# =============================================================================
+# Configuration data
+# =============================================================================
+
+configuration = {
+  'baseClass'  : UIVBox,
+  'provides'   : 'GFVBox',
+  'container'  : 0,
+}





reply via email to

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