tuikit/application.py
author Radek Brich <radek.brich@devl.cz>
Sat, 08 Oct 2011 17:16:07 +0200
changeset 21 8553a6bd2d82
parent 18 e6c3a5ee91aa
child 23 4e72fd2a0e14
permissions -rw-r--r--
Add TableView plus demo.
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 curses.wrapper
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     4
import logging
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     5
import time
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     6
import math
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     7
18
e6c3a5ee91aa Eliminate relative imports.
Radek Brich <radek.brich@devl.cz>
parents: 17
diff changeset
     8
from tuikit.container import Container
e6c3a5ee91aa Eliminate relative imports.
Radek Brich <radek.brich@devl.cz>
parents: 17
diff changeset
     9
from tuikit.backend_curses import BackendCurses
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    10
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    11
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    12
class TopWindow(Container):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    13
    
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    14
    '''Top window of an application. Covers entire screen.'''
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    15
    
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    16
    def __init__(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    17
        '''Create top window.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    18
        Container.__init__(self)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    19
1
69318aba22bf Menu development. New focus. Easier imports from tuikit package.
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    20
        self.focuswidget = None
69318aba22bf Menu development. New focus. Easier imports from tuikit package.
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    21
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    22
        self.top = self
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    23
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    24
        self.timeout = []
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    25
        self.timelast = None
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    26
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    27
        self.connect('draw', self.on_draw)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    28
9
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
    29
1
69318aba22bf Menu development. New focus. Easier imports from tuikit package.
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    30
    def keypress(self, keyname, char):
9
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
    31
        if self.handle('keypress', keyname, char):
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
    32
            return
1
69318aba22bf Menu development. New focus. Easier imports from tuikit package.
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    33
        if self.focuswidget and self.focuswidget != self:
69318aba22bf Menu development. New focus. Easier imports from tuikit package.
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    34
            self.focuswidget.emit('keypress', keyname, char)
69318aba22bf Menu development. New focus. Easier imports from tuikit package.
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    35
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    36
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    37
    def on_draw(self, screen, x, y):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    38
        screen.erase()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    39
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    40
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    41
    def add_timeout(self, s, func):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    42
        if not len(self.timeout):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    43
            self.timelast = time.time()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    44
        self.timeout += [[s, func]]
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    45
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    46
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    47
    def remove_timeout(self, func):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    48
        for to in self.timeout[:]:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    49
            if to[1] == func:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    50
                self.timeout.remove(to)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    51
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    52
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    53
    def has_timeout(self):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    54
        return len(self.timeout) and True or False
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    55
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    56
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    57
    def nearest_timeout(self):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    58
        return min(self.timeout)[0]
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    59
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    60
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    61
    def process_timeout(self):
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    62
        now = time.time()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    63
        lasted = now - self.timelast
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    64
        self.timelast = now
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    65
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    66
        for to in self.timeout[:]:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    67
            newt = to[0] - lasted
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    68
            if newt <= 0.0:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    69
                to[1]()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    70
                self.timeout.remove(to)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    71
            else:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    72
                to[0] = newt
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    73
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    74
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    75
class Application:
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    76
    
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    77
    '''Application class. Defines main loop.'''
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    78
       
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    79
    def __init__(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    80
        '''Create application.'''
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    81
        
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    82
        '''Top window.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    83
        self.top = TopWindow()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    84
        self.quit = False
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    85
        
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    86
        '''Renderer class, i.e. BackendCurses.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    87
        self.screen = None
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    88
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    89
        self.log = logging.getLogger('tuikit')
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    90
        self.log.setLevel(logging.DEBUG)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    91
        handler = logging.FileHandler('./tuikit.log')
15
c55b4749e562 Add Pager.
Radek Brich <radek.brich@devl.cz>
parents: 13
diff changeset
    92
        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
    93
        handler.setFormatter(formatter)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    94
        self.log.addHandler(handler)
15
c55b4749e562 Add Pager.
Radek Brich <radek.brich@devl.cz>
parents: 13
diff changeset
    95
        self.log.info('=== start ===')
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    96
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    97
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    98
    def start(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    99
        '''Start application. Runs main loop.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   100
        curses.wrapper(self.mainloop)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   101
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   102
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   103
    def terminate(self):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   104
        '''Terminate application.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   105
        self.quit = True
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   106
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   107
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   108
    def mainloop(self, screen):
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   109
        '''The main loop.'''
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   110
        self.screen = BackendCurses(screen)
7
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   111
        self.applytheme()
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   112
        self.top.width, self.top.height = self.screen.width, self.screen.height
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   113
        self.top.emit('resize')
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   114
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   115
        while True:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   116
            self.top.draw(self.screen)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   117
            self.screen.commit()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   118
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   119
            timeout = None
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   120
            if self.top.has_timeout():
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   121
                timeout = int(math.ceil(self.top.nearest_timeout() * 10))
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   122
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   123
            events = self.screen.process_input(timeout)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   124
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   125
            if self.top.has_timeout():
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   126
                self.top.process_timeout()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   127
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   128
            for event in events:
17
5be7cc43402e Handle curses resize event.
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
   129
                if event[0] == 'resize':
5be7cc43402e Handle curses resize event.
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
   130
                    self.top.width, self.top.height = self.screen.width, self.screen.height
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   131
                self.top.emit(event[0], *event[1:])
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   132
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   133
            if self.quit:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   134
                break
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   135
7
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   136
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   137
    def applytheme(self):
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   138
        screen = self.screen
9
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   139
        screen.setcolor('normal',                  'white on black')
21
8553a6bd2d82 Add TableView plus demo.
Radek Brich <radek.brich@devl.cz>
parents: 18
diff changeset
   140
        screen.setcolor('strong',                  'white on black, bold')
11
762513aacc87 TreeView: Add cursor, node collapse, reworked draw.
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   141
        screen.setcolor('active',                  'black on cyan')
9
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   142
        screen.setcolor('window:normal',           'white on blue')
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   143
        screen.setcolor('window:controls',         'white on blue, bold')
7175ed629a76 Added ComboBox, HorizontalLayout, TreeNode, TreeModel, TreeView. Widget is now descendant of EventSource. Improved color management (color prefixes).
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   144
        screen.setcolor('window:controls-active',  'cyan on blue, bold')
7
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   145
        screen.setcolor('button',                  'black on white')
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   146
        screen.setcolor('button-active',           'black on cyan')
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   147
        screen.setcolor('menu',                    'black on cyan')
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 1
diff changeset
   148
        screen.setcolor('menu-active',             'white on cyan, bold')
13
19ebde2fd594 Add more generated documentation.
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   149