tuikit/application.py
author Radek Brich <radek.brich@devl.cz>
Sat, 05 Jan 2013 16:47:30 +0100
changeset 49 1611c462c3e3
parent 46 2b43a7f38c34
child 52 50a1857557da
permissions -rw-r--r--
Update sdlterm: Optimize commit() - use two cell buffers, redraw only dirty cells, not everything. Fix keypress event, filter mousemove.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     1
# -*- coding: utf-8 -*-
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     2
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     3
import logging
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     4
import time
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     5
import math
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     6
18
e6c3a5ee91aa Eliminate relative imports.
Radek Brich <radek.brich@devl.cz>
parents: 17
diff changeset
     7
from tuikit.container import Container
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     8
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     9
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    10
class TopWindow(Container):
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    11
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    12
    '''Top window of an application. Covers entire screen.'''
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    13
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    14
    def __init__(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    15
        '''Create top window.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    16
        Container.__init__(self)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    17
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    18
        self.top = self
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    19
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    20
        self.timeout = []
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    21
        self.timelast = None
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    22
46
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
    23
    def draw(self, driver, x=0, y=0):
36
caf927c3f10b Update docs.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
    24
        """Draw the top window and its children.
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    25
36
caf927c3f10b Update docs.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
    26
        This is entry point for full screen redraw.
caf927c3f10b Update docs.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
    27
caf927c3f10b Update docs.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
    28
        """
46
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
    29
        driver.erase()
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
    30
        Container.draw(self, driver, x, y)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    31
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    32
    def add_timeout(self, s, func):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    33
        if not len(self.timeout):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    34
            self.timelast = time.time()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    35
        self.timeout += [[s, func]]
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    36
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    37
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    38
    def remove_timeout(self, func):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    39
        for to in self.timeout[:]:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    40
            if to[1] == func:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    41
                self.timeout.remove(to)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    42
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    43
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    44
    def has_timeout(self):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    45
        return len(self.timeout) and True or False
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    46
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    47
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    48
    def nearest_timeout(self):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    49
        return min(self.timeout)[0]
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    50
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    51
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    52
    def process_timeout(self):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    53
        now = time.time()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    54
        lasted = now - self.timelast
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    55
        self.timelast = now
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    56
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    57
        for to in self.timeout[:]:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    58
            newt = to[0] - lasted
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    59
            if newt <= 0.0:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    60
                to[1]()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    61
                self.timeout.remove(to)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    62
            else:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    63
                to[0] = newt
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    64
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    65
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    66
class Application:
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    67
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    68
    '''Application class. Defines main loop.'''
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    69
49
1611c462c3e3 Update sdlterm: Optimize commit() - use two cell buffers, redraw only dirty cells, not everything. Fix keypress event, filter mousemove.
Radek Brich <radek.brich@devl.cz>
parents: 46
diff changeset
    70
    def __init__(self, driver = 'sdl'):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    71
        '''Create application.'''
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    72
23
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
    73
        self.top = TopWindow()
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    74
        '''Top window.'''
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    75
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    76
        self.quit = False
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    77
29
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
    78
        self.driver = self.get_driver_instance(driver)
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
    79
        '''Driver class instance (render + input), e.g. DriverCurses.'''
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    80
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    81
        self.log = logging.getLogger('tuikit')
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    82
        self.log.setLevel(logging.DEBUG)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    83
        handler = logging.FileHandler('./tuikit.log')
15
c55b4749e562 Add Pager.
Radek Brich <radek.brich@devl.cz>
parents: 13
diff changeset
    84
        formatter = logging.Formatter('%(asctime)s %(levelname)-5s %(message)s', '%y-%m-%d %H:%M:%S')
c55b4749e562 Add Pager.
Radek Brich <radek.brich@devl.cz>
parents: 13
diff changeset
    85
        handler.setFormatter(formatter)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    86
        self.log.addHandler(handler)
15
c55b4749e562 Add Pager.
Radek Brich <radek.brich@devl.cz>
parents: 13
diff changeset
    87
        self.log.info('=== start ===')
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    88
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    89
    def start(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    90
        '''Start application. Runs main loop.'''
23
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
    91
        self.driver.start(self.mainloop)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    92
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    93
    def terminate(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    94
        '''Terminate application.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    95
        self.quit = True
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    96
23
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
    97
    def mainloop(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    98
        '''The main loop.'''
7
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
    99
        self.applytheme()
32
088b92ffb119 Clean up, refactoring. Rename EventSource to Emitter, begin merging emit() method with handle().
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
   100
        self.top.size = self.driver.size  # link top widget size to screen size
34
e3beacd5e536 Update event propagation, keypress event, focusing.
Radek Brich <radek.brich@devl.cz>
parents: 32
diff changeset
   101
        self.top.emit('resize')
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   102
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   103
        while True:
23
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   104
            self.top.draw(self.driver)
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   105
            self.driver.commit()
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   106
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   107
            timeout = None
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   108
            if self.top.has_timeout():
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   109
                timeout = int(math.ceil(self.top.nearest_timeout() * 10))
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   110
24
b248ef500557 Add DriverPygame (incomplete). Move unicode graphics constants to UnicodeGraphics class. Move shared parts of drivers to Driver base class.
Radek Brich <radek.brich@devl.cz>
parents: 23
diff changeset
   111
            events = self.driver.getevents(timeout)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   112
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   113
            if self.top.has_timeout():
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   114
                self.top.process_timeout()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   115
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   116
            for event in events:
24
b248ef500557 Add DriverPygame (incomplete). Move unicode graphics constants to UnicodeGraphics class. Move shared parts of drivers to Driver base class.
Radek Brich <radek.brich@devl.cz>
parents: 23
diff changeset
   117
                if event[0] == 'quit':
b248ef500557 Add DriverPygame (incomplete). Move unicode graphics constants to UnicodeGraphics class. Move shared parts of drivers to Driver base class.
Radek Brich <radek.brich@devl.cz>
parents: 23
diff changeset
   118
                    self.quit = True
b248ef500557 Add DriverPygame (incomplete). Move unicode graphics constants to UnicodeGraphics class. Move shared parts of drivers to Driver base class.
Radek Brich <radek.brich@devl.cz>
parents: 23
diff changeset
   119
                else:
b248ef500557 Add DriverPygame (incomplete). Move unicode graphics constants to UnicodeGraphics class. Move shared parts of drivers to Driver base class.
Radek Brich <radek.brich@devl.cz>
parents: 23
diff changeset
   120
                    self.top.emit(event[0], *event[1:])
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   121
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   122
            if self.quit:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   123
                break
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   124
7
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   125
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   126
    def applytheme(self):
23
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   127
        driver = self.driver
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   128
        driver.setcolor('normal',                  'white on black')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   129
        driver.setcolor('strong',                  'white on black, bold')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   130
        driver.setcolor('active',                  'black on cyan')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   131
        driver.setcolor('window:normal',           'white on blue')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   132
        driver.setcolor('window:controls',         'white on blue, bold')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   133
        driver.setcolor('window:controls-active',  'cyan on blue, bold')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   134
        driver.setcolor('button',                  'black on white')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   135
        driver.setcolor('button-active',           'black on cyan')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   136
        driver.setcolor('menu',                    'black on cyan')
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   137
        driver.setcolor('menu-active',             'white on cyan, bold')
30
05500124d7fb Add setup script. Add Checkbox widget + demo. Updates.
Radek Brich <radek.brich@devl.cz>
parents: 29
diff changeset
   138
        driver.setcolor('combo:normal',            'black on green')
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   139
46
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
   140
        driver.setcolor('test-blink',              'cyan on blue, blink')
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
   141
        driver.setcolor('test-bold',               'cyan on blue, bold')
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
   142
        driver.setcolor('test-dim',                'cyan on blue, dim')
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
   143
        driver.setcolor('test-standout',           'cyan on blue, standout')
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
   144
        driver.setcolor('test-underline',          'cyan on blue, underline')
2b43a7f38c34 Minor updates. Replace super() with direct class reference. Add demo_colors.
Radek Brich <radek.brich@devl.cz>
parents: 36
diff changeset
   145
29
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
   146
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
   147
    def get_driver_instance(self, name):
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
   148
        module = __import__('tuikit.driver_' + name, fromlist=['driverclass'])
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
   149
        return module.driverclass()
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
   150