Redraw widgets on request. Add scrollbar demo.
# -*- coding: utf-8 -*-
'''SDL driver.
Requires C++ extension module.
See sdlterm directory.
'''
from tuikit.driver_base import Driver
import logging
import subprocess
import sys
sys.path.insert(0, 'sdlterm/build/lib.linux-x86_64-3.2')
from sdlterm import SDLTerminal
class DriverSDL(Driver):
'''SDL driver class'''
color_map = {
'black' : 0,
'blue' : 1,
'green' : 2,
'cyan' : 3,
'red' : 4,
'magenta' : 5,
'brown' : 6,
'lightgray' : 7,
'gray' : 8,
'lightblue' : 9,
'lightgreen' : 10,
'lightcyan' : 11,
'lightred' : 12,
'lightmagenta' : 13,
'yellow' : 14,
'white' : 15,
}
style_map = {
'bold' : 1 << 24, # bold font
'underline' : 1 << 25, # underline text
'standout' : 1 << 26, # inverse bg/fg
'blink' : 1 << 27, # blinking text
}
def __init__(self):
'''Initialize instance attributes'''
Driver.__init__(self)
self.log = logging.getLogger('tuikit')
self.sdlterm = SDLTerminal()
self.colors = {} # maps names to attributes
self.colorstack = [] # pushcolor/popcolor puts or gets attributes from this
def start(self, mainfunc):
'''Start driver and run mainfunc.'''
self.select_system_font()
self.sdlterm.resize(800, 600)
self.size.w, self.size.h = self.sdlterm.width, self.sdlterm.height
mainfunc()
## input ##
def getevents(self, timeout=None):
'''Process input, return list of events.
timeout -- float, in seconds
'''
if timeout is not None:
timeout = int(timeout*1000)
event = self.sdlterm.wait_event(timeout)
if not event:
return []
if event[0] == 'resize':
self.size.w, self.size.h = self.sdlterm.width, self.sdlterm.height
return [event]
## drawing ##
def erase(self):
'''Clear screen.'''
self.sdlterm.erase()
def putch(self, x, y, c):
'''Output one unicode character to specified coordinates.'''
if not self.clipstack.test(x, y):
return
self.sdlterm.putch(x, y, c)
def commit(self):
'''Commit changes to the screen.'''
self.sdlterm.commit()
## colors ##
def defcolor(self, name, desc):
'''Define color name.'''
parts = desc.split(',')
fgbg = parts[0].split(' on ', 1)
fg = fgbg[0]
bg = fgbg[1:] and fgbg[1] or 'black'
style = parts[1:]
fg = self._color_by_name(fg)
bg = self._color_by_name(bg)
style = self._style_by_names(style)
self.colors[name] = self.sdlterm.prepare_attr(fg, bg, style);
def setcolor(self, name):
"""Set defined color. Previous color is forgotten."""
self.sdlterm.set_attr(self.colors[name])
def pushcolor(self, name):
'''Add color on top of stack and use this color for following output.'''
if len(self.colorprefix):
prefixname = self.colorprefix[-1] + name
if prefixname in self.colors:
name = prefixname
attr = self.colors[name]
self.sdlterm.set_attr(attr)
self.colorstack.append(attr)
def popcolor(self):
'''Remove color from top of stack and use new top color for following output.'''
self.colorstack.pop()
if len(self.colorstack):
attr = self.colorstack[-1]
else:
attr = 7
self.sdlterm.set_attr(attr)
def _color_by_name(self, name):
name = name.lower().strip()
return self.color_map[name]
def _style_by_names(self, names):
style = 0
for name in names:
name = name.lower().strip()
style |= self.style_map[name]
return style
## cursor ##
def showcursor(self, x, y):
'''Set cursor to be shown at x, y coordinates.'''
if not self.clipstack.test(x, y):
return
self.sdlterm.show_cursor(x, y)
def hidecursor(self):
'''Hide cursor.'''
self.sdlterm.hide_cursor()
## private utility ##
def _lookup_system_font(self, family, style):
"""Find system font by family name and style.
style -- font style: 'normal', 'bold'
Returns font file name.
Uses fontconfig, it must be installed in system.
"""
return subprocess.check_output([
'fc-match',
'%s:style=%s:fontformat=truetype:spacing=mono' % (family, style),
'-f%{file}'])
def select_system_font(self, family='monospace'):
"""Search for system fonts by family name and use them.
Example family names:
'monospace' - default monospace system font
'DejaVu Sans Mono'
'Liberation Mono'
"""
fname_regular = self._lookup_system_font(family, 'normal')
fname_bold = self._lookup_system_font(family, 'bold')
self.log.info('DriverSDL: using fonts:\n%s\n%s', fname_regular.decode(), fname_bold.decode())
self.sdlterm.select_font(fname_regular, fname_bold, 12)
driverclass = DriverSDL