| Index: third_party/twisted_8_1/twisted/conch/insults/window.py
|
| diff --git a/third_party/twisted_8_1/twisted/conch/insults/window.py b/third_party/twisted_8_1/twisted/conch/insults/window.py
|
| deleted file mode 100644
|
| index 51487f80d93ece6677621456a87c61e1b5d67d02..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/conch/insults/window.py
|
| +++ /dev/null
|
| @@ -1,864 +0,0 @@
|
| -# -*- test-case-name: twisted.conch.test.test_window -*-
|
| -
|
| -"""
|
| -Simple insults-based widget library
|
| -
|
| -@author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>}
|
| -"""
|
| -
|
| -import array
|
| -
|
| -from twisted.conch.insults import insults, helper
|
| -from twisted.python import text as tptext
|
| -
|
| -class YieldFocus(Exception):
|
| - """Input focus manipulation exception
|
| - """
|
| -
|
| -class BoundedTerminalWrapper(object):
|
| - def __init__(self, terminal, width, height, xoff, yoff):
|
| - self.width = width
|
| - self.height = height
|
| - self.xoff = xoff
|
| - self.yoff = yoff
|
| - self.terminal = terminal
|
| - self.cursorForward = terminal.cursorForward
|
| - self.selectCharacterSet = terminal.selectCharacterSet
|
| - self.selectGraphicRendition = terminal.selectGraphicRendition
|
| - self.saveCursor = terminal.saveCursor
|
| - self.restoreCursor = terminal.restoreCursor
|
| -
|
| - def cursorPosition(self, x, y):
|
| - return self.terminal.cursorPosition(
|
| - self.xoff + min(self.width, x),
|
| - self.yoff + min(self.height, y)
|
| - )
|
| -
|
| - def cursorHome(self):
|
| - return self.terminal.cursorPosition(
|
| - self.xoff, self.yoff)
|
| -
|
| - def write(self, bytes):
|
| - return self.terminal.write(bytes)
|
| -
|
| -class Widget(object):
|
| - focused = False
|
| - parent = None
|
| - dirty = False
|
| - width = height = None
|
| -
|
| - def repaint(self):
|
| - if not self.dirty:
|
| - self.dirty = True
|
| - if self.parent is not None and not self.parent.dirty:
|
| - self.parent.repaint()
|
| -
|
| - def filthy(self):
|
| - self.dirty = True
|
| -
|
| - def redraw(self, width, height, terminal):
|
| - self.filthy()
|
| - self.draw(width, height, terminal)
|
| -
|
| - def draw(self, width, height, terminal):
|
| - if width != self.width or height != self.height or self.dirty:
|
| - self.width = width
|
| - self.height = height
|
| - self.dirty = False
|
| - self.render(width, height, terminal)
|
| -
|
| - def render(self, width, height, terminal):
|
| - pass
|
| -
|
| - def sizeHint(self):
|
| - return None
|
| -
|
| - def keystrokeReceived(self, keyID, modifier):
|
| - if keyID == '\t':
|
| - self.tabReceived(modifier)
|
| - elif keyID == '\x7f':
|
| - self.backspaceReceived()
|
| - elif keyID in insults.FUNCTION_KEYS:
|
| - self.functionKeyReceived(keyID, modifier)
|
| - else:
|
| - self.characterReceived(keyID, modifier)
|
| -
|
| - def tabReceived(self, modifier):
|
| - # XXX TODO - Handle shift+tab
|
| - raise YieldFocus()
|
| -
|
| - def focusReceived(self):
|
| - """Called when focus is being given to this widget.
|
| -
|
| - May raise YieldFocus is this widget does not want focus.
|
| - """
|
| - self.focused = True
|
| - self.repaint()
|
| -
|
| - def focusLost(self):
|
| - self.focused = False
|
| - self.repaint()
|
| -
|
| - def backspaceReceived(self):
|
| - pass
|
| -
|
| - def functionKeyReceived(self, keyID, modifier):
|
| - func = getattr(self, 'func_' + keyID.name, None)
|
| - if func is not None:
|
| - func(modifier)
|
| -
|
| - def characterReceived(self, keyID, modifier):
|
| - pass
|
| -
|
| -class ContainerWidget(Widget):
|
| - """
|
| - @ivar focusedChild: The contained widget which currently has
|
| - focus, or None.
|
| - """
|
| - focusedChild = None
|
| - focused = False
|
| -
|
| - def __init__(self):
|
| - Widget.__init__(self)
|
| - self.children = []
|
| -
|
| - def addChild(self, child):
|
| - assert child.parent is None
|
| - child.parent = self
|
| - self.children.append(child)
|
| - if self.focusedChild is None and self.focused:
|
| - try:
|
| - child.focusReceived()
|
| - except YieldFocus:
|
| - pass
|
| - else:
|
| - self.focusedChild = child
|
| - self.repaint()
|
| -
|
| - def remChild(self, child):
|
| - assert child.parent is self
|
| - child.parent = None
|
| - self.children.remove(child)
|
| - self.repaint()
|
| -
|
| - def filthy(self):
|
| - for ch in self.children:
|
| - ch.filthy()
|
| - Widget.filthy(self)
|
| -
|
| - def render(self, width, height, terminal):
|
| - for ch in self.children:
|
| - ch.draw(width, height, terminal)
|
| -
|
| - def changeFocus(self):
|
| - self.repaint()
|
| -
|
| - if self.focusedChild is not None:
|
| - self.focusedChild.focusLost()
|
| - focusedChild = self.focusedChild
|
| - self.focusedChild = None
|
| - try:
|
| - curFocus = self.children.index(focusedChild) + 1
|
| - except ValueError:
|
| - raise YieldFocus()
|
| - else:
|
| - curFocus = 0
|
| - while curFocus < len(self.children):
|
| - try:
|
| - self.children[curFocus].focusReceived()
|
| - except YieldFocus:
|
| - curFocus += 1
|
| - else:
|
| - self.focusedChild = self.children[curFocus]
|
| - return
|
| - # None of our children wanted focus
|
| - raise YieldFocus()
|
| -
|
| -
|
| - def focusReceived(self):
|
| - self.changeFocus()
|
| - self.focused = True
|
| -
|
| -
|
| - def keystrokeReceived(self, keyID, modifier):
|
| - if self.focusedChild is not None:
|
| - try:
|
| - self.focusedChild.keystrokeReceived(keyID, modifier)
|
| - except YieldFocus:
|
| - self.changeFocus()
|
| - self.repaint()
|
| - else:
|
| - Widget.keystrokeReceived(self, keyID, modifier)
|
| -
|
| -
|
| -class TopWindow(ContainerWidget):
|
| - """
|
| - A top-level container object which provides focus wrap-around and paint
|
| - scheduling.
|
| -
|
| - @ivar painter: A no-argument callable which will be invoked when this
|
| - widget needs to be redrawn.
|
| -
|
| - @ivar scheduler: A one-argument callable which will be invoked with a
|
| - no-argument callable and should arrange for it to invoked at some point in
|
| - the near future. The no-argument callable will cause this widget and all
|
| - its children to be redrawn. It is typically beneficial for the no-argument
|
| - callable to be invoked at the end of handling for whatever event is
|
| - currently active; for example, it might make sense to call it at the end of
|
| - L{twisted.conch.insults.insults.ITerminalProtocol.keystrokeReceived}.
|
| - Note, however, that since calls to this may also be made in response to no
|
| - apparent event, arrangements should be made for the function to be called
|
| - even if an event handler such as C{keystrokeReceived} is not on the call
|
| - stack (eg, using C{reactor.callLater} with a short timeout).
|
| - """
|
| - focused = True
|
| -
|
| - def __init__(self, painter, scheduler):
|
| - ContainerWidget.__init__(self)
|
| - self.painter = painter
|
| - self.scheduler = scheduler
|
| -
|
| - _paintCall = None
|
| - def repaint(self):
|
| - if self._paintCall is None:
|
| - self._paintCall = object()
|
| - self.scheduler(self._paint)
|
| - ContainerWidget.repaint(self)
|
| -
|
| - def _paint(self):
|
| - self._paintCall = None
|
| - self.painter()
|
| -
|
| - def changeFocus(self):
|
| - try:
|
| - ContainerWidget.changeFocus(self)
|
| - except YieldFocus:
|
| - try:
|
| - ContainerWidget.changeFocus(self)
|
| - except YieldFocus:
|
| - pass
|
| -
|
| - def keystrokeReceived(self, keyID, modifier):
|
| - try:
|
| - ContainerWidget.keystrokeReceived(self, keyID, modifier)
|
| - except YieldFocus:
|
| - self.changeFocus()
|
| -
|
| -
|
| -class AbsoluteBox(ContainerWidget):
|
| - def moveChild(self, child, x, y):
|
| - for n in range(len(self.children)):
|
| - if self.children[n][0] is child:
|
| - self.children[n] = (child, x, y)
|
| - break
|
| - else:
|
| - raise ValueError("No such child", child)
|
| -
|
| - def render(self, width, height, terminal):
|
| - for (ch, x, y) in self.children:
|
| - wrap = BoundedTerminalWrapper(terminal, width - x, height - y, x, y)
|
| - ch.draw(width, height, wrap)
|
| -
|
| -
|
| -class _Box(ContainerWidget):
|
| - TOP, CENTER, BOTTOM = range(3)
|
| -
|
| - def __init__(self, gravity=CENTER):
|
| - ContainerWidget.__init__(self)
|
| - self.gravity = gravity
|
| -
|
| - def sizeHint(self):
|
| - height = 0
|
| - width = 0
|
| - for ch in self.children:
|
| - hint = ch.sizeHint()
|
| - if hint is None:
|
| - hint = (None, None)
|
| -
|
| - if self.variableDimension == 0:
|
| - if hint[0] is None:
|
| - width = None
|
| - elif width is not None:
|
| - width += hint[0]
|
| - if hint[1] is None:
|
| - height = None
|
| - elif height is not None:
|
| - height = max(height, hint[1])
|
| - else:
|
| - if hint[0] is None:
|
| - width = None
|
| - elif width is not None:
|
| - width = max(width, hint[0])
|
| - if hint[1] is None:
|
| - height = None
|
| - elif height is not None:
|
| - height += hint[1]
|
| -
|
| - return width, height
|
| -
|
| -
|
| - def render(self, width, height, terminal):
|
| - if not self.children:
|
| - return
|
| -
|
| - greedy = 0
|
| - wants = []
|
| - for ch in self.children:
|
| - hint = ch.sizeHint()
|
| - if hint is None:
|
| - hint = (None, None)
|
| - if hint[self.variableDimension] is None:
|
| - greedy += 1
|
| - wants.append(hint[self.variableDimension])
|
| -
|
| - length = (width, height)[self.variableDimension]
|
| - totalWant = sum([w for w in wants if w is not None])
|
| - if greedy:
|
| - leftForGreedy = int((length - totalWant) / greedy)
|
| -
|
| - widthOffset = heightOffset = 0
|
| -
|
| - for want, ch in zip(wants, self.children):
|
| - if want is None:
|
| - want = leftForGreedy
|
| -
|
| - subWidth, subHeight = width, height
|
| - if self.variableDimension == 0:
|
| - subWidth = want
|
| - else:
|
| - subHeight = want
|
| -
|
| - wrap = BoundedTerminalWrapper(
|
| - terminal,
|
| - subWidth,
|
| - subHeight,
|
| - widthOffset,
|
| - heightOffset,
|
| - )
|
| - ch.draw(subWidth, subHeight, wrap)
|
| - if self.variableDimension == 0:
|
| - widthOffset += want
|
| - else:
|
| - heightOffset += want
|
| -
|
| -
|
| -class HBox(_Box):
|
| - variableDimension = 0
|
| -
|
| -class VBox(_Box):
|
| - variableDimension = 1
|
| -
|
| -
|
| -class Packer(ContainerWidget):
|
| - def render(self, width, height, terminal):
|
| - if not self.children:
|
| - return
|
| -
|
| - root = int(len(self.children) ** 0.5 + 0.5)
|
| - boxes = [VBox() for n in range(root)]
|
| - for n, ch in enumerate(self.children):
|
| - boxes[n % len(boxes)].addChild(ch)
|
| - h = HBox()
|
| - map(h.addChild, boxes)
|
| - h.render(width, height, terminal)
|
| -
|
| -
|
| -class Canvas(Widget):
|
| - focused = False
|
| -
|
| - contents = None
|
| -
|
| - def __init__(self):
|
| - Widget.__init__(self)
|
| - self.resize(1, 1)
|
| -
|
| - def resize(self, width, height):
|
| - contents = array.array('c', ' ' * width * height)
|
| - if self.contents is not None:
|
| - for x in range(min(width, self._width)):
|
| - for y in range(min(height, self._height)):
|
| - contents[width * y + x] = self[x, y]
|
| - self.contents = contents
|
| - self._width = width
|
| - self._height = height
|
| - if self.x >= width:
|
| - self.x = width - 1
|
| - if self.y >= height:
|
| - self.y = height - 1
|
| -
|
| - def __getitem__(self, (x, y)):
|
| - return self.contents[(self._width * y) + x]
|
| -
|
| - def __setitem__(self, (x, y), value):
|
| - self.contents[(self._width * y) + x] = value
|
| -
|
| - def clear(self):
|
| - self.contents = array.array('c', ' ' * len(self.contents))
|
| -
|
| - def render(self, width, height, terminal):
|
| - if not width or not height:
|
| - return
|
| -
|
| - if width != self._width or height != self._height:
|
| - self.resize(width, height)
|
| - for i in range(height):
|
| - terminal.cursorPosition(0, i)
|
| - terminal.write(''.join(self.contents[self._width * i:self._width * i + self._width])[:width])
|
| -
|
| -
|
| -def horizontalLine(terminal, y, left, right):
|
| - terminal.selectCharacterSet(insults.CS_DRAWING, insults.G0)
|
| - terminal.cursorPosition(left, y)
|
| - terminal.write(chr(0161) * (right - left))
|
| - terminal.selectCharacterSet(insults.CS_US, insults.G0)
|
| -
|
| -def verticalLine(terminal, x, top, bottom):
|
| - terminal.selectCharacterSet(insults.CS_DRAWING, insults.G0)
|
| - for n in xrange(top, bottom):
|
| - terminal.cursorPosition(x, n)
|
| - terminal.write(chr(0170))
|
| - terminal.selectCharacterSet(insults.CS_US, insults.G0)
|
| -
|
| -
|
| -def rectangle(terminal, (top, left), (width, height)):
|
| - terminal.selectCharacterSet(insults.CS_DRAWING, insults.G0)
|
| -
|
| - terminal.cursorPosition(top, left)
|
| - terminal.write(chr(0154))
|
| - terminal.write(chr(0161) * (width - 2))
|
| - terminal.write(chr(0153))
|
| - for n in range(height - 2):
|
| - terminal.cursorPosition(left, top + n + 1)
|
| - terminal.write(chr(0170))
|
| - terminal.cursorForward(width - 2)
|
| - terminal.write(chr(0170))
|
| - terminal.cursorPosition(0, top + height - 1)
|
| - terminal.write(chr(0155))
|
| - terminal.write(chr(0161) * (width - 2))
|
| - terminal.write(chr(0152))
|
| -
|
| - terminal.selectCharacterSet(insults.CS_US, insults.G0)
|
| -
|
| -class Border(Widget):
|
| - def __init__(self, containee):
|
| - Widget.__init__(self)
|
| - self.containee = containee
|
| - self.containee.parent = self
|
| -
|
| - def focusReceived(self):
|
| - return self.containee.focusReceived()
|
| -
|
| - def focusLost(self):
|
| - return self.containee.focusLost()
|
| -
|
| - def keystrokeReceived(self, keyID, modifier):
|
| - return self.containee.keystrokeReceived(keyID, modifier)
|
| -
|
| - def sizeHint(self):
|
| - hint = self.containee.sizeHint()
|
| - if hint is None:
|
| - hint = (None, None)
|
| - if hint[0] is None:
|
| - x = None
|
| - else:
|
| - x = hint[0] + 2
|
| - if hint[1] is None:
|
| - y = None
|
| - else:
|
| - y = hint[1] + 2
|
| - return x, y
|
| -
|
| - def filthy(self):
|
| - self.containee.filthy()
|
| - Widget.filthy(self)
|
| -
|
| - def render(self, width, height, terminal):
|
| - if self.containee.focused:
|
| - terminal.write('\x1b[31m')
|
| - rectangle(terminal, (0, 0), (width, height))
|
| - terminal.write('\x1b[0m')
|
| - wrap = BoundedTerminalWrapper(terminal, width - 2, height - 2, 1, 1)
|
| - self.containee.draw(width - 2, height - 2, wrap)
|
| -
|
| -
|
| -class Button(Widget):
|
| - def __init__(self, label, onPress):
|
| - Widget.__init__(self)
|
| - self.label = label
|
| - self.onPress = onPress
|
| -
|
| - def sizeHint(self):
|
| - return len(self.label), 1
|
| -
|
| - def characterReceived(self, keyID, modifier):
|
| - if keyID == '\r':
|
| - self.onPress()
|
| -
|
| - def render(self, width, height, terminal):
|
| - terminal.cursorPosition(0, 0)
|
| - if self.focused:
|
| - terminal.write('\x1b[1m' + self.label + '\x1b[0m')
|
| - else:
|
| - terminal.write(self.label)
|
| -
|
| -class TextInput(Widget):
|
| - def __init__(self, maxwidth, onSubmit):
|
| - Widget.__init__(self)
|
| - self.onSubmit = onSubmit
|
| - self.maxwidth = maxwidth
|
| - self.buffer = ''
|
| - self.cursor = 0
|
| -
|
| - def setText(self, text):
|
| - self.buffer = text[:self.maxwidth]
|
| - self.cursor = len(self.buffer)
|
| - self.repaint()
|
| -
|
| - def func_LEFT_ARROW(self, modifier):
|
| - if self.cursor > 0:
|
| - self.cursor -= 1
|
| - self.repaint()
|
| -
|
| - def func_RIGHT_ARROW(self, modifier):
|
| - if self.cursor < len(self.buffer):
|
| - self.cursor += 1
|
| - self.repaint()
|
| -
|
| - def backspaceReceived(self):
|
| - if self.cursor > 0:
|
| - self.buffer = self.buffer[:self.cursor - 1] + self.buffer[self.cursor:]
|
| - self.cursor -= 1
|
| - self.repaint()
|
| -
|
| - def characterReceived(self, keyID, modifier):
|
| - if keyID == '\r':
|
| - self.onSubmit(self.buffer)
|
| - else:
|
| - if len(self.buffer) < self.maxwidth:
|
| - self.buffer = self.buffer[:self.cursor] + keyID + self.buffer[self.cursor:]
|
| - self.cursor += 1
|
| - self.repaint()
|
| -
|
| - def sizeHint(self):
|
| - return self.maxwidth + 1, 1
|
| -
|
| - def render(self, width, height, terminal):
|
| - currentText = self._renderText()
|
| - terminal.cursorPosition(0, 0)
|
| - if self.focused:
|
| - terminal.write(currentText[:self.cursor])
|
| - cursor(terminal, currentText[self.cursor:self.cursor+1] or ' ')
|
| - terminal.write(currentText[self.cursor+1:])
|
| - terminal.write(' ' * (self.maxwidth - len(currentText) + 1))
|
| - else:
|
| - more = self.maxwidth - len(currentText)
|
| - terminal.write(currentText + '_' * more)
|
| -
|
| - def _renderText(self):
|
| - return self.buffer
|
| -
|
| -class PasswordInput(TextInput):
|
| - def _renderText(self):
|
| - return '*' * len(self.buffer)
|
| -
|
| -class TextOutput(Widget):
|
| - text = ''
|
| -
|
| - def __init__(self, size=None):
|
| - Widget.__init__(self)
|
| - self.size = size
|
| -
|
| - def sizeHint(self):
|
| - return self.size
|
| -
|
| - def render(self, width, height, terminal):
|
| - terminal.cursorPosition(0, 0)
|
| - text = self.text[:width]
|
| - terminal.write(text + ' ' * (width - len(text)))
|
| -
|
| - def setText(self, text):
|
| - self.text = text
|
| - self.repaint()
|
| -
|
| - def focusReceived(self):
|
| - raise YieldFocus()
|
| -
|
| -class TextOutputArea(TextOutput):
|
| - WRAP, TRUNCATE = range(2)
|
| -
|
| - def __init__(self, size=None, longLines=WRAP):
|
| - TextOutput.__init__(self, size)
|
| - self.longLines = longLines
|
| -
|
| - def render(self, width, height, terminal):
|
| - n = 0
|
| - inputLines = self.text.splitlines()
|
| - outputLines = []
|
| - while inputLines:
|
| - if self.longLines == self.WRAP:
|
| - wrappedLines = tptext.greedyWrap(inputLines.pop(0), width)
|
| - outputLines.extend(wrappedLines or [''])
|
| - else:
|
| - outputLines.append(inputLines.pop(0)[:width])
|
| - if len(outputLines) >= height:
|
| - break
|
| - for n, L in enumerate(outputLines[:height]):
|
| - terminal.cursorPosition(0, n)
|
| - terminal.write(L)
|
| -
|
| -class Viewport(Widget):
|
| - _xOffset = 0
|
| - _yOffset = 0
|
| -
|
| - def xOffset():
|
| - def get(self):
|
| - return self._xOffset
|
| - def set(self, value):
|
| - if self._xOffset != value:
|
| - self._xOffset = value
|
| - self.repaint()
|
| - return get, set
|
| - xOffset = property(*xOffset())
|
| -
|
| - def yOffset():
|
| - def get(self):
|
| - return self._yOffset
|
| - def set(self, value):
|
| - if self._yOffset != value:
|
| - self._yOffset = value
|
| - self.repaint()
|
| - return get, set
|
| - yOffset = property(*yOffset())
|
| -
|
| - _width = 160
|
| - _height = 24
|
| -
|
| - def __init__(self, containee):
|
| - Widget.__init__(self)
|
| - self.containee = containee
|
| - self.containee.parent = self
|
| -
|
| - self._buf = helper.TerminalBuffer()
|
| - self._buf.width = self._width
|
| - self._buf.height = self._height
|
| - self._buf.connectionMade()
|
| -
|
| - def filthy(self):
|
| - self.containee.filthy()
|
| - Widget.filthy(self)
|
| -
|
| - def render(self, width, height, terminal):
|
| - self.containee.draw(self._width, self._height, self._buf)
|
| -
|
| - # XXX /Lame/
|
| - for y, line in enumerate(self._buf.lines[self._yOffset:self._yOffset + height]):
|
| - terminal.cursorPosition(0, y)
|
| - n = 0
|
| - for n, (ch, attr) in enumerate(line[self._xOffset:self._xOffset + width]):
|
| - if ch is self._buf.void:
|
| - ch = ' '
|
| - terminal.write(ch)
|
| - if n < width:
|
| - terminal.write(' ' * (width - n - 1))
|
| -
|
| -
|
| -class _Scrollbar(Widget):
|
| - def __init__(self, onScroll):
|
| - Widget.__init__(self)
|
| - self.onScroll = onScroll
|
| - self.percent = 0.0
|
| -
|
| - def smaller(self):
|
| - self.percent = min(1.0, max(0.0, self.onScroll(-1)))
|
| - self.repaint()
|
| -
|
| - def bigger(self):
|
| - self.percent = min(1.0, max(0.0, self.onScroll(+1)))
|
| - self.repaint()
|
| -
|
| -
|
| -class HorizontalScrollbar(_Scrollbar):
|
| - def sizeHint(self):
|
| - return (None, 1)
|
| -
|
| - def func_LEFT_ARROW(self, modifier):
|
| - self.smaller()
|
| -
|
| - def func_RIGHT_ARROW(self, modifier):
|
| - self.bigger()
|
| -
|
| - _left = u'\N{BLACK LEFT-POINTING TRIANGLE}'
|
| - _right = u'\N{BLACK RIGHT-POINTING TRIANGLE}'
|
| - _bar = u'\N{LIGHT SHADE}'
|
| - _slider = u'\N{DARK SHADE}'
|
| - def render(self, width, height, terminal):
|
| - terminal.cursorPosition(0, 0)
|
| - n = width - 3
|
| - before = int(n * self.percent)
|
| - after = n - before
|
| - me = self._left + (self._bar * before) + self._slider + (self._bar * after) + self._right
|
| - terminal.write(me.encode('utf-8'))
|
| -
|
| -
|
| -class VerticalScrollbar(_Scrollbar):
|
| - def sizeHint(self):
|
| - return (1, None)
|
| -
|
| - def func_UP_ARROW(self, modifier):
|
| - self.smaller()
|
| -
|
| - def func_DOWN_ARROW(self, modifier):
|
| - self.bigger()
|
| -
|
| - _up = u'\N{BLACK UP-POINTING TRIANGLE}'
|
| - _down = u'\N{BLACK DOWN-POINTING TRIANGLE}'
|
| - _bar = u'\N{LIGHT SHADE}'
|
| - _slider = u'\N{DARK SHADE}'
|
| - def render(self, width, height, terminal):
|
| - terminal.cursorPosition(0, 0)
|
| - knob = int(self.percent * (height - 2))
|
| - terminal.write(self._up.encode('utf-8'))
|
| - for i in xrange(1, height - 1):
|
| - terminal.cursorPosition(0, i)
|
| - if i != (knob + 1):
|
| - terminal.write(self._bar.encode('utf-8'))
|
| - else:
|
| - terminal.write(self._slider.encode('utf-8'))
|
| - terminal.cursorPosition(0, height - 1)
|
| - terminal.write(self._down.encode('utf-8'))
|
| -
|
| -
|
| -class ScrolledArea(Widget):
|
| - def __init__(self, containee):
|
| - Widget.__init__(self, containee)
|
| - self._viewport = Viewport(containee)
|
| - self._horiz = HorizontalScrollbar(self._horizScroll)
|
| - self._vert = VerticalScrollbar(self._vertScroll)
|
| -
|
| - for w in self._viewport, self._horiz, self._vert:
|
| - w.parent = self
|
| -
|
| - def _horizScroll(self, n):
|
| - self._viewport.xOffset += n
|
| - self._viewport.xOffset = max(0, self._viewport.xOffset)
|
| - return self._viewport.xOffset / 25.0
|
| -
|
| - def _vertScroll(self, n):
|
| - self._viewport.yOffset += n
|
| - self._viewport.yOffset = max(0, self._viewport.yOffset)
|
| - return self._viewport.yOffset / 25.0
|
| -
|
| - def func_UP_ARROW(self, modifier):
|
| - self._vert.smaller()
|
| -
|
| - def func_DOWN_ARROW(self, modifier):
|
| - self._vert.bigger()
|
| -
|
| - def func_LEFT_ARROW(self, modifier):
|
| - self._horiz.smaller()
|
| -
|
| - def func_RIGHT_ARROW(self, modifier):
|
| - self._horiz.bigger()
|
| -
|
| - def filthy(self):
|
| - self._viewport.filthy()
|
| - self._horiz.filthy()
|
| - self._vert.filthy()
|
| - Widget.filthy(self)
|
| -
|
| - def render(self, width, height, terminal):
|
| - wrapper = BoundedTerminalWrapper(terminal, width - 2, height - 2, 1, 1)
|
| - self._viewport.draw(width - 2, height - 2, wrapper)
|
| - if self.focused:
|
| - terminal.write('\x1b[31m')
|
| - horizontalLine(terminal, 0, 1, width - 1)
|
| - verticalLine(terminal, 0, 1, height - 1)
|
| - self._vert.draw(1, height - 1, BoundedTerminalWrapper(terminal, 1, height - 1, width - 1, 0))
|
| - self._horiz.draw(width, 1, BoundedTerminalWrapper(terminal, width, 1, 0, height - 1))
|
| - terminal.write('\x1b[0m')
|
| -
|
| -def cursor(terminal, ch):
|
| - terminal.saveCursor()
|
| - terminal.selectGraphicRendition(str(insults.REVERSE_VIDEO))
|
| - terminal.write(ch)
|
| - terminal.restoreCursor()
|
| - terminal.cursorForward()
|
| -
|
| -class Selection(Widget):
|
| - # Index into the sequence
|
| - focusedIndex = 0
|
| -
|
| - # Offset into the displayed subset of the sequence
|
| - renderOffset = 0
|
| -
|
| - def __init__(self, sequence, onSelect, minVisible=None):
|
| - Widget.__init__(self)
|
| - self.sequence = sequence
|
| - self.onSelect = onSelect
|
| - self.minVisible = minVisible
|
| - if minVisible is not None:
|
| - self._width = max(map(len, self.sequence))
|
| -
|
| - def sizeHint(self):
|
| - if self.minVisible is not None:
|
| - return self._width, self.minVisible
|
| -
|
| - def func_UP_ARROW(self, modifier):
|
| - if self.focusedIndex > 0:
|
| - self.focusedIndex -= 1
|
| - if self.renderOffset > 0:
|
| - self.renderOffset -= 1
|
| - self.repaint()
|
| -
|
| - def func_PGUP(self, modifier):
|
| - if self.renderOffset != 0:
|
| - self.focusedIndex -= self.renderOffset
|
| - self.renderOffset = 0
|
| - else:
|
| - self.focusedIndex = max(0, self.focusedIndex - self.height)
|
| - self.repaint()
|
| -
|
| - def func_DOWN_ARROW(self, modifier):
|
| - if self.focusedIndex < len(self.sequence) - 1:
|
| - self.focusedIndex += 1
|
| - if self.renderOffset < self.height - 1:
|
| - self.renderOffset += 1
|
| - self.repaint()
|
| -
|
| -
|
| - def func_PGDN(self, modifier):
|
| - if self.renderOffset != self.height - 1:
|
| - change = self.height - self.renderOffset - 1
|
| - if change + self.focusedIndex >= len(self.sequence):
|
| - change = len(self.sequence) - self.focusedIndex - 1
|
| - self.focusedIndex += change
|
| - self.renderOffset = self.height - 1
|
| - else:
|
| - self.focusedIndex = min(len(self.sequence) - 1, self.focusedIndex + self.height)
|
| - self.repaint()
|
| -
|
| - def characterReceived(self, keyID, modifier):
|
| - if keyID == '\r':
|
| - self.onSelect(self.sequence[self.focusedIndex])
|
| -
|
| - def render(self, width, height, terminal):
|
| - self.height = height
|
| - start = self.focusedIndex - self.renderOffset
|
| - if start > len(self.sequence) - height:
|
| - start = max(0, len(self.sequence) - height)
|
| -
|
| - elements = self.sequence[start:start+height]
|
| -
|
| - for n, ele in enumerate(elements):
|
| - terminal.cursorPosition(0, n)
|
| - if n == self.renderOffset:
|
| - terminal.saveCursor()
|
| - if self.focused:
|
| - modes = str(insults.REVERSE_VIDEO), str(insults.BOLD)
|
| - else:
|
| - modes = str(insults.REVERSE_VIDEO),
|
| - terminal.selectGraphicRendition(*modes)
|
| - text = ele[:width]
|
| - terminal.write(text + (' ' * (width - len(text))))
|
| - if n == self.renderOffset:
|
| - terminal.restoreCursor()
|
|
|