DriverSDL: mousewheel, key repeation.
authorRadek Brich <radek.brich@devl.cz>
Mon, 07 Jan 2013 00:23:45 +0100
changeset 55 1ab0edd5d784
parent 54 86b84535726e
child 56 282a07d20680
DriverSDL: mousewheel, key repeation.
demo_input.py
docs/driver.rst
docs/index.rst
sdlterm/cython/sdlterm.pyx
sdlterm/src/sdlterm.cc
tuikit/events.py
--- a/demo_input.py	Sun Jan 06 23:03:24 2013 +0100
+++ b/demo_input.py	Mon Jan 07 00:23:45 2013 +0100
@@ -4,24 +4,29 @@
 import locale
 locale.setlocale(locale.LC_ALL, '')
 
-from tuikit import *
+from tuikit import Application, TextEdit
 
 
 class MyApplication(Application):
     def __init__(self):
         Application.__init__(self)
-        self.top.add_handler('keypress', self.on_top_keypress)
 
         self.text = ''
-        textedit = TextEdit(100, 40, self.text)
-        self.top.add(textedit)
-        textedit.x = 2
-        self.textedit = textedit
+        self.textedit = TextEdit(100, 40, self.text)
+        self.top.add(self.textedit)
+        self.textedit.x = 2
 
-    def on_top_keypress(self, ev):
-        if ev.char == 'q':
+        editbox = self.textedit.editbox
+        editbox.add_handler('keypress', self.on_any_input)
+        editbox.add_handler('mousedown', self.on_any_input)
+        editbox.add_handler('mouseup', self.on_any_input)
+        editbox.add_handler('mousewheel', self.on_any_input)
+        editbox.add_handler('mousemove', self.on_any_input)
+
+    def on_any_input(self, ev):
+        if ev.event_name == 'keypress' and ev.char == 'q':
             self.terminate()
-        self.text += 'keyname: %(keyname)s  char: %(char)s\n' % ev
+        self.text += ''.join((ev.event_name.ljust(10), ' : ', repr(ev), '\n'))
         self.textedit.settext(self.text)
         self.textedit.scrolltoend()
         return True
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/driver.rst	Mon Jan 07 00:23:45 2013 +0100
@@ -0,0 +1,46 @@
+Driver
+======
+
+Tuikit driver is the lowest part of the kit - it actually draws characters on screen,
+receives user events and forwards them to widgets.
+
+Any dirty details of actual graphical toolkit should be hidden by this driver.
+Though it's not hardware driver, nowhere near that. Tuikit driver is expected to use
+pretty high-level libraries, it's low-level only in Tuikit perpective.
+
+Currently there are three drivers: Dummy, Curses, SDL
+
+
+Dummy driver
+------------
+
+This driver shows and documents complete interface required from any driver.
+
+It does not draw anything and immediately emits keypress event for 'q' char and 'escape' key,
+which should exit application.
+
+All methods of dummy driver just report they where being called - into log file.
+
+
+Curses driver
+-------------
+
+Default driver for Text User Interface in any terminal supporting required features.
+Uses curses module from Python.
+
+
+SDL driver
+----------
+
+Creates graphical window and draws characters here. This has less limits than curses,
+we can use any colors, fonts and possibly even draw images.
+
+Though by default, it just emulates terminal with curses.
+
+SDL application is more portable than curses one, which means that Tuikit application
+using SDL driver may work in non-unix OS like Windows (does not currently,
+due to unconditional use of fontconfig).
+
+SDL driver requires sdlterm module for Python, which must be compiled from C++.
+See sdlterm directory in Tuikit distribution.
+
--- a/docs/index.rst	Sun Jan 06 23:03:24 2013 +0100
+++ b/docs/index.rst	Mon Jan 07 00:23:45 2013 +0100
@@ -16,6 +16,7 @@
    events
    redraw
    colors
+   driver
 
 .. inheritance-diagram:: tuikit.application
                          tuikit.events
--- a/sdlterm/cython/sdlterm.pyx	Sun Jan 06 23:03:24 2013 +0100
+++ b/sdlterm/cython/sdlterm.pyx	Mon Jan 07 00:23:45 2013 +0100
@@ -94,6 +94,8 @@
             return ('mousedown', event.mouse.x, event.mouse.y, event.mouse.button)
         if event.type == event.MOUSEUP:
             return ('mouseup', event.mouse.x, event.mouse.y, event.mouse.button)
+        if event.type == event.MOUSEWHEEL:
+            return ('mousewheel', event.mouse.x, event.mouse.y, event.mouse.button)
         if event.type == event.KEYPRESS:
             keyname = event.key.keyname
             if keyname:
--- a/sdlterm/src/sdlterm.cc	Sun Jan 06 23:03:24 2013 +0100
+++ b/sdlterm/src/sdlterm.cc	Mon Jan 07 00:23:45 2013 +0100
@@ -307,7 +307,8 @@
 
 
 Terminal::Terminal()
- : _screen(), _attr(7), _cursor_visible(false), _mousemove_last_x(-1)
+ : _screen(), _attr(7), _cursor_x(0), _cursor_y(0), _cursor_visible(false),
+   _mousemove_last_x(-1), _mousemove_last_y(-1)
 {
     if (SDL_Init(SDL_INIT_VIDEO) == -1)
     {
@@ -315,6 +316,7 @@
         throw std::exception();
     }
     SDL_EnableUNICODE(1);
+    SDL_EnableKeyRepeat(250, SDL_DEFAULT_REPEAT_INTERVAL);
     SDL_WM_SetCaption("terminal", NULL);
 }
 
@@ -387,6 +389,12 @@
                 event.mouse.x = sdl_event.button.x / _screen.get_cell_width();
                 event.mouse.y = sdl_event.button.y / _screen.get_cell_height();
                 event.mouse.button = sdl_event.button.button;
+                if (sdl_event.button.button == SDL_BUTTON_WHEELUP || sdl_event.button.button == SDL_BUTTON_WHEELDOWN)
+                {
+                    if (sdl_event.type == SDL_MOUSEBUTTONUP)
+                        break; // do not report button-up events for mouse wheel
+                    event.type = Event::MOUSEWHEEL;
+                }
                 _mousemove_last_x = -1;
                 return;
 
--- a/tuikit/events.py	Sun Jan 06 23:03:24 2013 +0100
+++ b/tuikit/events.py	Mon Jan 07 00:23:45 2013 +0100
@@ -14,6 +14,7 @@
 
 class Event:
     def __init__(self):
+        self.event_name = None
         self.originator = None
 
     def __getitem__(self, key):
@@ -62,6 +63,7 @@
         self.wy = y
         self.px = 0  # parent coordinates
         self.py = 0
+        #: Mouse button: left=1, middle=2, right=3, wheelup=4 wheeldown=5
         self.button = button
 
     def childevent(self, child):
@@ -194,6 +196,7 @@
             event = self._event_class[event_name](*args, **kwargs)
         # set originator to instance on which emit() was called
         event.originator = self
+        event.event_name = event_name
         # call handlers from first to last, stop if satisfied
         for handler in self._event_handlers[event_name]:
             handled = handler(event)