[Top][All Lists]
[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,
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r9120 - in trunk/gnue-forms/src/uidrivers/curses: . widgets,
johannes <=