Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
authorRadek Brich <radek.brich@devl.cz>
Wed, 30 Jan 2013 00:38:48 +0100
changeset 71 cfd3445107b4
parent 70 db2eab0beb45
child 72 6e0656600754
Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
demo_anchorlayout.py
sdlterm/cython/sdlterm.pyx
sdlterm/src/sdlterm.cc
sdlterm/src/sdlterm.h
tuikit/driver_curses.py
tuikit/events.py
tuikit/layout.py
tuikit/window.py
--- a/demo_anchorlayout.py	Sun Jan 27 23:51:59 2013 +0100
+++ b/demo_anchorlayout.py	Wed Jan 30 00:38:48 2013 +0100
@@ -41,6 +41,11 @@
         label_margin.add_handler('draw', self.on_label_margin_draw)
         win.add(label_margin, halign='center', margin=Borders(t=6))
 
+        label_size = Label(str(self.win.sizereq))
+        label_size.name = 'label_size'
+        label_size.add_handler('draw', self.on_label_size_draw)
+        win.add(label_size, halign='center', margin=Borders(t=8))
+
     def on_button_align_click(self, ev):
         align_type = ev.originator.label.split(':', 1)[0]
         align = self.win.hints[align_type]
@@ -52,6 +57,9 @@
     def on_label_margin_draw(self, ev):
         ev.originator.label = str(self.win.hints['margin'])
 
+    def on_label_size_draw(self, ev):
+        ev.originator.label = str(self.win.sizereq)
+
     def on_top_keypress(self, ev):
         if ev.keyname == 'escape':
             self.terminate()
--- a/sdlterm/cython/sdlterm.pyx	Sun Jan 27 23:51:59 2013 +0100
+++ b/sdlterm/cython/sdlterm.pyx	Wed Jan 30 00:38:48 2013 +0100
@@ -17,6 +17,7 @@
 
     cdef struct Event_mouse:
         int x, y
+        int relx, rely
         int button
 
     cdef struct Event:
@@ -92,13 +93,13 @@
             return None
         event = self.event
         if event.type == event.MOUSEMOVE:
-            return ('mousemove', event.mouse.x, event.mouse.y)
+            return ('mousemove', 0, event.mouse.x, event.mouse.y, event.mouse.relx, event.mouse.rely)
         if event.type == event.MOUSEDOWN:
-            return ('mousedown', event.mouse.x, event.mouse.y, event.mouse.button)
+            return ('mousedown', event.mouse.button, event.mouse.x, event.mouse.y)
         if event.type == event.MOUSEUP:
-            return ('mouseup', event.mouse.x, event.mouse.y, event.mouse.button)
+            return ('mouseup', event.mouse.button, event.mouse.x, event.mouse.y)
         if event.type == event.MOUSEWHEEL:
-            return ('mousewheel', event.mouse.x, event.mouse.y, event.mouse.button)
+            return ('mousewheel', event.mouse.button, event.mouse.x, event.mouse.y)
         if event.type == event.KEYPRESS:
             keyname = event.key.keyname
             if keyname:
--- a/sdlterm/src/sdlterm.cc	Sun Jan 27 23:51:59 2013 +0100
+++ b/sdlterm/src/sdlterm.cc	Wed Jan 30 00:38:48 2013 +0100
@@ -462,9 +462,14 @@
                 if (_mousemove_last_x != event.mouse.x ||
                     _mousemove_last_y != event.mouse.y)
                 {
+                    if (_mousemove_last_x != -1)
+                    {
+                        event.mouse.relx = event.mouse.x - _mousemove_last_x;
+                        event.mouse.rely = event.mouse.y - _mousemove_last_y;
+                        event_ready = true;
+                    }
                     _mousemove_last_x = event.mouse.x;
                     _mousemove_last_y = event.mouse.y;
-                    event_ready = true;
                     break;
                 }
                 break; // continue loop when mouse position did not change
--- a/sdlterm/src/sdlterm.h	Sun Jan 27 23:51:59 2013 +0100
+++ b/sdlterm/src/sdlterm.h	Wed Jan 30 00:38:48 2013 +0100
@@ -191,6 +191,7 @@
         struct
         {
             int x, y;
+            int relx, rely;
             int button;
         } mouse;
     };
--- a/tuikit/driver_curses.py	Sun Jan 27 23:51:59 2013 +0100
+++ b/tuikit/driver_curses.py	Wed Jan 30 00:38:48 2013 +0100
@@ -318,8 +318,11 @@
 
         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)
-                out += [('mousemove', x, y)]
 
         # we are interested only in changes, not buttons already pressed before event
         if self._mouse_last_bstate is not None:
@@ -331,17 +334,17 @@
             self._mouse_last_bstate = bstate
 
         if bstate & curses.BUTTON1_PRESSED:
-            out += [('mousedown', x, y, 1)]
+            out += [('mousedown', 1, x, y)]
         if bstate & curses.BUTTON2_PRESSED:
-            out += [('mousedown', x, y, 2)]
+            out += [('mousedown', 2, x, y)]
         if bstate & curses.BUTTON3_PRESSED:
-            out += [('mousedown', x, y, 3)]
+            out += [('mousedown', 3, x, y)]
         if bstate & curses.BUTTON1_RELEASED:
-            out += [('mouseup', x, y, 1)]
+            out += [('mouseup', 1, x, y)]
         if bstate & curses.BUTTON2_RELEASED:
-            out += [('mouseup', x, y, 2)]
+            out += [('mouseup', 2, x, y)]
         if bstate & curses.BUTTON3_RELEASED:
-            out += [('mouseup', x, y, 3)]
+            out += [('mouseup', 3, x, y)]
 
         # reset last pos when pressed/released
         if len(out) > 0 and out[-1][0] in ('mousedown', 'mouseup'):
@@ -432,26 +435,30 @@
 
         out = []
 
-        if t in (0x20, 0x21, 0x22): # button press
+        if t in (0x20, 0x21, 0x22):
+            # button press
             btn = t - 0x1f
             if not btn in self.mbtnstack:
                 self.mbtnstack.append(btn)
                 self._mouse_last_pos = (None, None)
-                out += [('mousedown', x, y, btn)]
+                out += [('mousedown', btn, x, y)]
             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)
-                    out += [('mousemove', x, y, btn)]
-
-        elif t == 0x23: # button release
+        elif t == 0x23:
+            # button release
             btn = self.mbtnstack.pop()
             self._mouse_last_pos = (None, None)
-            out += [('mouseup', x, y, btn)]
-
-        elif t in (0x60, 0x61): # wheel up, down
+            out += [('mouseup', btn, x, y)]
+        elif t in (0x60, 0x61):
+            # wheel up, down
             btn = 4 + t - 0x60
-            out += [('mousewheel', x, y, btn)]
-
+            out += [('mousewheel', btn, x, y)]
         else:
             raise Exception('Unknown mouse event: %x' % t)
 
--- a/tuikit/events.py	Sun Jan 27 23:51:59 2013 +0100
+++ b/tuikit/events.py	Wed Jan 30 00:38:48 2013 +0100
@@ -65,19 +65,25 @@
 
 
 class MouseEvent(Event):
-    def __init__(self, x=0, y=0, button=0):
+    def __init__(self, button=0, x=0, y=0, relx=0, rely=0):
         Event.__init__(self)
-        self.x = x   # global coordinates
+        # global coordinates
+        self.x = x
         self.y = y
-        self.wx = x  # local widget coordinates
+        # local widget coordinates
+        self.wx = x
         self.wy = y
-        self.px = 0  # parent coordinates
+        # parent coordinates
+        self.px = 0
         self.py = 0
+        # relative change of coordinates (mousemove)
+        self.relx = relx
+        self.rely = rely
         #: Mouse button: left=1, middle=2, right=3, wheelup=4, wheeldown=5
         self.button = button
 
     def make_child_event(self, container, child):
-        ev = MouseEvent(self.x, self.y, self.button)
+        ev = MouseEvent(self.button, self.x, self.y, self.relx, self.rely)
         ev.originator = self.originator
         ev.event_name = self.event_name
         # original local coordinates are new parent coordinates
@@ -89,7 +95,7 @@
         return ev
 
     def __repr__(self):
-        return 'MouseEvent(x={0.x},y={0.y},button={0.button})'.format(self)
+        return 'MouseEvent(button={0.button},x={0.x},y={0.y},relx={0.relx},rely={0.rely})'.format(self)
 
 
 class GenericEvent(Event):
--- a/tuikit/layout.py	Sun Jan 27 23:51:59 2013 +0100
+++ b/tuikit/layout.py	Wed Jan 30 00:38:48 2013 +0100
@@ -82,32 +82,38 @@
             child._pos.update(x=x, y=y)
             child._size.update(w=w, h=h)
 
-    def move_child(self, child, x, y):
+    def move_child(self, child, x=None, y=None):
+        """Move child inside container by adjusting its margin.
+
+        Operation is supported only for one-side anchors:
+            left, right, top, bottom
+        No move on axis where align is set to
+            center, fill
+
+        """
         if not child in self.children:
             raise ValueError('AnchorLayout.move(): Cannot move foreign child.')
         margin = child.hints['margin']
-        ha = child.hints['halign'].selected
-        va = child.hints['valign'].selected
-        ofsx = x - child.x
-        ofsy = y - child.y
-        if ha == 'left':
-            margin.l += ofsx
-            newx = margin.l
-        elif ha == 'right':
-            margin.r -= ofsx
-            newx = self.width - margin.r - child.sizereq.w
-        else:
-            # do not move when halign is center,fill
-            newx = child.x
-        if va == 'top':
-            margin.t += ofsy
-            newy = margin.t
-        elif va == 'bottom':
-            margin.b -= ofsy
-            newy = self.height - margin.b - child.sizereq.h
-        else:
-            # do not move when valign is center,fill
-            newy = child.y
+        newx = None
+        if x is not None:
+            ha = child.hints['halign'].selected
+            ofsx = x - child.x
+            if ha == 'left':
+                margin.l += ofsx
+                newx = margin.l
+            elif ha == 'right':
+                margin.r -= ofsx
+                newx = self.width - margin.r - child.sizereq.w
+        newy = None
+        if y is not None:
+            va = child.hints['valign'].selected
+            ofsy = y - child.y
+            if va == 'top':
+                margin.t += ofsy
+                newy = margin.t
+            elif va == 'bottom':
+                margin.b -= ofsy
+                newy = self.height - margin.b - child.sizereq.h
         child._pos.update(x=newx, y=newy)
 
 
--- a/tuikit/window.py	Sun Jan 27 23:51:59 2013 +0100
+++ b/tuikit/window.py	Wed Jan 30 00:38:48 2013 +0100
@@ -86,46 +86,35 @@
 
 
     def after_mousedown(self, ev):
-        self.dragstart = (ev.wx, ev.wy)
         if self.resizable and ev.wx >= self.width - 1 and ev.wy >= self.height - 1:
             self._resizing = True
         elif self.movable:
             self._moving = True
-        self.origsize = (self.width, self.height)
-
         self.redraw(True)
 
-
     def after_mouseup(self, ev):
-        if self._resizing:
-            self.resize(self.origsize[0] + ev.wx - self.dragstart[0],
-                        self.origsize[1] + ev.wy - self.dragstart[1])
-            self._resizing = False
-        elif self._moving:
-            self.move(ev.px - self.dragstart[0],
-                      ev.py - self.dragstart[1])
-            self._moving = False
+        self._resize_or_move(ev)
+        self._resizing = False
+        self._moving = False
+        self.redraw(True)
 
+    def after_mousemove(self, ev):
+        self._resize_or_move(ev)
         self.redraw(True)
 
-
-    def after_mousemove(self, ev):
-        if ev.px == self.x + self.dragstart[0] \
-        and ev.py == self.y + self.dragstart[1]:
-            return
-
-        #if x > self.parent.width-self.width:
-        #    return
-
+    def _resize_or_move(self, ev):
         if self._resizing:
-            self.resize(self.origsize[0] + ev.wx - self.dragstart[0],
-                        self.origsize[1] + ev.wy - self.dragstart[1])
+            self.resize(self.sizereq.w + ev.relx,
+                        self.sizereq.h + ev.rely)
+            # AnchorLayout, right/bottom align
+            # also move the window so that it visualy stays in place
+            if 'halign' in self.hints and self.hints['halign'].selected == 'right':
+                self.move(x = self.x + ev.relx)
+            if 'valign' in self.hints and self.hints['valign'].selected == 'bottom':
+                self.move(y = self.y + ev.rely)
         elif self._moving:
-            self.move(ev.px - self.dragstart[0],
-                      ev.py - self.dragstart[1])
-
-        self.redraw(True)
-
+            self.move(self.x + ev.relx,
+                      self.y + ev.rely)
 
     def on_closebtn_click(self, ev):
         self.hide()