# HG changeset patch # User Radek Brich # Date 1409727224 -7200 # Node ID abcadb7e2ef17feed48f77360704f3e3cd095414 # Parent 70c9cfc70cd6fb6e38c88a46f33e7b365a5a197d Use Point for mouse events, add them to Container and Widget. diff -r 70c9cfc70cd6 -r abcadb7e2ef1 demos/04_texteditor.py --- a/demos/04_texteditor.py Mon Sep 01 08:55:40 2014 +0200 +++ b/demos/04_texteditor.py Wed Sep 03 08:53:44 2014 +0200 @@ -8,6 +8,7 @@ class MyApplication(Application): + def __init__(self): Application.__init__(self) #self.top.add_handler('keypress', self.on_top_keypress) diff -r 70c9cfc70cd6 -r abcadb7e2ef1 tuikit/core/container.py --- a/tuikit/core/container.py Mon Sep 01 08:55:40 2014 +0200 +++ b/tuikit/core/container.py Wed Sep 03 08:53:44 2014 +0200 @@ -16,6 +16,7 @@ #: List of child widgets. self.children = [] self.focus_child = None + self.mouse_child = None self.layout = layout_class() def add(self, widget): @@ -67,3 +68,20 @@ def keypress(self, keyname, char, mod=0): if self.focus_child: self.focus_child.keypress(keyname, char, mod) + + def mousedown(self, button, pos): + self.mouse_child = None + for child in reversed(self.children): + if pos in child.boundaries: + child.mousedown(button, pos - child.pos) + self.mouse_child = child + + def mouseup(self, button, pos): + if self.mouse_child: + self.mouse_child.mouseup(button, pos - self.mouse_child.pos) + + def mousemove(self, button, pos, relpos): + if self.mouse_child: + self.mouse_child.mousemove(button, + pos - self.mouse_child.pos, relpos) + diff -r 70c9cfc70cd6 -r abcadb7e2ef1 tuikit/core/coords.py --- a/tuikit/core/coords.py Mon Sep 01 08:55:40 2014 +0200 +++ b/tuikit/core/coords.py Wed Sep 03 08:53:44 2014 +0200 @@ -1,3 +1,4 @@ + class Point: """Point in cartesian space. @@ -11,12 +12,6 @@ self.y = 0 self.update(*args, **kwargs) - def __getitem__(self, key): - return (self.x, self.y)[key] - - def __repr__(self): - return 'Point(x={0.x},y={0.y})'.format(self) - def move(self, relx, rely): self.x += relx self.y += rely @@ -46,6 +41,48 @@ else: raise ValueError('Bad keyword arg: %r' % key) + # sequence interface + + def __len__(self): + return 2 + + def __getitem__(self, key): + return (self.x, self.y)[key] + + # point arithmetics + + def __add__(self, other): + return Point(self.x + other[0], self.y + other[1]) + + def __sub__(self, other): + return Point(self.x - other[0], self.y - other[1]) + + def __eq__(self, other): + """Comparison operator. + + Point can be compared to any sequence of at least two elements: + + >>> p = Point(1, 2) + >>> p == Point(1, 2) + True + >>> p == (1, 2) + True + >>> p == (0, 0) + False + >>> p == None + False + + """ + try: + return self.x == other[0] and self.y == other[1] + except (TypeError, IndexError): + return False + + # string representation + + def __repr__(self): + return 'Point(x={0.x},y={0.y})'.format(self) + class Size: diff -r 70c9cfc70cd6 -r abcadb7e2ef1 tuikit/core/widget.py --- a/tuikit/core/widget.py Mon Sep 01 08:55:40 2014 +0200 +++ b/tuikit/core/widget.py Wed Sep 03 08:53:44 2014 +0200 @@ -70,6 +70,10 @@ def resize(self, w, h): self._size.update(w, h) + @property + def boundaries(self): + return Rect._make(self.pos, self._size) + ## drawing, looks ## def draw(self, buffer): @@ -105,6 +109,18 @@ self._log.debug('keypress(keyname=%r, char=%r, mod=%r)', keyname, char, mod) + def mousedown(self, button, pos): + self._log.debug('mousedown(btn=%r, pos=%r)', + button, pos) + + def mouseup(self, button, pos): + self._log.debug('mouseup(btn=%r, pos=%r)', + button, pos) + + def mousemove(self, button, pos, relpos): + self._log.debug('mousemove(btn=%r, pos=%r, relpos=%r)', + button, pos, relpos) + ## timeouts ## def add_timeout(self, delay, callback, *args): diff -r 70c9cfc70cd6 -r abcadb7e2ef1 tuikit/driver/curses.py --- a/tuikit/driver/curses.py Mon Sep 01 08:55:40 2014 +0200 +++ b/tuikit/driver/curses.py Wed Sep 03 08:53:44 2014 +0200 @@ -3,6 +3,7 @@ import logging from tuikit.driver.driver import Driver +from tuikit.core.coords import Point class CursesDriver(Driver): @@ -87,7 +88,7 @@ self.colorstack = [] # pushcolor/popcolor puts or gets attributes from this self.inputqueue = [] self.mbtnstack = [] - self._mouse_last_pos = (None, None) + self._mouse_last_pos = None # Point self._mouse_last_bstate = None ## initialization, finalization ## @@ -279,15 +280,15 @@ except curses.error: return [] + pos = Point(x, y) out = [] if bstate & curses.REPORT_MOUSE_POSITION: - if self._mouse_last_pos != (x, y): - if self._mouse_last_pos[0] is not None: - relx = x - (self._mouse_last_pos[0] or 0) - rely = y - (self._mouse_last_pos[1] or 0) - out += [('mousemove', 0, x, y, relx, rely)] - self._mouse_last_pos = (x, y) + if self._mouse_last_pos != pos: + if self._mouse_last_pos: + relpos = pos - self._mouse_last_pos + out += [('mousemove', 0, pos, relpos)] + self._mouse_last_pos = pos # we are interested only in changes, not buttons already pressed before event if self._mouse_last_bstate is not None: @@ -299,21 +300,21 @@ self._mouse_last_bstate = bstate if bstate & curses.BUTTON1_PRESSED: - out += [('mousedown', 1, x, y)] + out += [('mousedown', 1, pos)] if bstate & curses.BUTTON2_PRESSED: - out += [('mousedown', 2, x, y)] + out += [('mousedown', 2, pos)] if bstate & curses.BUTTON3_PRESSED: - out += [('mousedown', 3, x, y)] + out += [('mousedown', 3, pos)] if bstate & curses.BUTTON1_RELEASED: - out += [('mouseup', 1, x, y)] + out += [('mouseup', 1, pos)] if bstate & curses.BUTTON2_RELEASED: - out += [('mouseup', 2, x, y)] + out += [('mouseup', 2, pos)] if bstate & curses.BUTTON3_RELEASED: - out += [('mouseup', 3, x, y)] + out += [('mouseup', 3, pos)] # reset last pos when pressed/released if len(out) > 0 and out[-1][0] in ('mousedown', 'mouseup'): - self._mouse_last_pos = (None, None) + self._mouse_last_pos = None return out @@ -394,6 +395,7 @@ t = self._inputqueue_get_wait() x = self._inputqueue_get_wait() - 0x21 y = self._inputqueue_get_wait() - 0x21 + pos = Point(x, y) out = [] @@ -402,25 +404,24 @@ btn = t - 0x1f if not btn in self.mbtnstack: self.mbtnstack.append(btn) - self._mouse_last_pos = (None, None) - out += [('mousedown', btn, x, y)] + self._mouse_last_pos = None + out += [('mousedown', btn, pos)] else: # mouse move - if self._mouse_last_pos != (x, y): - if self._mouse_last_pos[0] is not None: - relx = x - self._mouse_last_pos[0] - rely = y - self._mouse_last_pos[1] - out += [('mousemove', btn, x, y, relx, rely)] - self._mouse_last_pos = (x, y) + if self._mouse_last_pos != pos: + if self._mouse_last_pos: + relpos = pos - self._mouse_last_pos + out += [('mousemove', btn, pos, relpos)] + self._mouse_last_pos = pos elif t == 0x23: # button release btn = self.mbtnstack.pop() self._mouse_last_pos = (None, None) - out += [('mouseup', btn, x, y)] + out += [('mouseup', btn, pos)] elif t in (0x60, 0x61): # wheel up, down btn = 4 + t - 0x60 - out += [('mousewheel', btn, x, y)] + out += [('mousewheel', btn, pos)] else: raise Exception('Unknown mouse event: %x' % t)