Split the Drawing class out into a separate module
No point having multiple implementations of what a drawing is. Let's have it in one module.
This commit is contained in:
parent
3d516530c6
commit
80d214c78f
71
tuhi/base.py
71
tuhi/base.py
|
@ -12,14 +12,13 @@
|
|||
#
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
from gi.repository import GObject
|
||||
|
||||
from tuhi.dbusserver import TuhiDBusServer
|
||||
from tuhi.ble import BlueZDeviceManager
|
||||
from tuhi.wacom import WacomDevice, Stroke
|
||||
from tuhi.wacom import WacomDevice
|
||||
from tuhi.config import TuhiConfig
|
||||
|
||||
logging.basicConfig(format='%(levelname)s: %(name)s: %(message)s',
|
||||
|
@ -29,47 +28,6 @@ logger = logging.getLogger('tuhi')
|
|||
WACOM_COMPANY_ID = 0x4755
|
||||
|
||||
|
||||
class TuhiDrawing(object):
|
||||
class Stroke(object):
|
||||
def __init__(self):
|
||||
self.points = []
|
||||
|
||||
def to_dict(self):
|
||||
d = {}
|
||||
d['points'] = [p.to_dict() for p in self.points]
|
||||
return d
|
||||
|
||||
class Point(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def to_dict(self):
|
||||
d = {}
|
||||
for key in ['toffset', 'position', 'pressure']:
|
||||
val = getattr(self, key, None)
|
||||
if val is not None:
|
||||
d[key] = val
|
||||
return d
|
||||
|
||||
def __init__(self, name, dimensions, timestamp):
|
||||
self.name = name
|
||||
self.dimensions = dimensions
|
||||
self.timestamp = timestamp
|
||||
self.strokes = []
|
||||
|
||||
def json(self):
|
||||
JSON_FILE_FORMAT_VERSION = 1
|
||||
|
||||
json_data = {
|
||||
'version': JSON_FILE_FORMAT_VERSION,
|
||||
'devicename': self.name,
|
||||
'dimensions': list(self.dimensions),
|
||||
'timestamp': self.timestamp,
|
||||
'strokes': [s.to_dict() for s in self.strokes]
|
||||
}
|
||||
return json.dumps(json_data)
|
||||
|
||||
|
||||
class TuhiDevice(GObject.Object):
|
||||
"""
|
||||
Glue object to combine the backend bluez DBus object (that talks to the
|
||||
|
@ -156,32 +114,7 @@ class TuhiDevice(GObject.Object):
|
|||
|
||||
def _on_drawing_received(self, device, drawing):
|
||||
logger.debug('Drawing received')
|
||||
d = TuhiDrawing(device.name, (0, 0), drawing.timestamp)
|
||||
for s in drawing:
|
||||
stroke = TuhiDrawing.Stroke()
|
||||
lastx, lasty, lastp = None, None, None
|
||||
for type, x, y, p in s.points:
|
||||
if x is not None:
|
||||
if type == Stroke.RELATIVE:
|
||||
x += lastx
|
||||
lastx = x
|
||||
if y is not None:
|
||||
if type == Stroke.RELATIVE:
|
||||
y += lasty
|
||||
lasty = y
|
||||
if p is not None:
|
||||
if type == Stroke.RELATIVE:
|
||||
p += lastp
|
||||
lastp = p
|
||||
|
||||
lastx, lasty, lastp = x, y, p
|
||||
point = TuhiDrawing.Point()
|
||||
point.position = (lastx, lasty)
|
||||
point.pressure = lastp
|
||||
stroke.points.append(point)
|
||||
d.strokes.append(stroke)
|
||||
|
||||
self._tuhi_dbus_device.add_drawing(d)
|
||||
self._tuhi_dbus_device.add_drawing(drawing)
|
||||
|
||||
def _on_fetching_finished(self, device, exception, bluez_device):
|
||||
bluez_device.disconnect_device()
|
||||
|
|
|
@ -294,7 +294,7 @@ class TuhiDBusDevice(_TuhiDBus):
|
|||
except IndexError:
|
||||
return ''
|
||||
else:
|
||||
return drawing.json()
|
||||
return drawing.to_json()
|
||||
|
||||
def add_drawing(self, drawing):
|
||||
self.drawings.append(drawing)
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
from gi.repository import GObject
|
||||
import json
|
||||
|
||||
|
||||
class Point(GObject.Object):
|
||||
def __init__(self, stroke):
|
||||
GObject.Object.__init__(self)
|
||||
self.stroke = stroke
|
||||
self.position = None
|
||||
self.pressure = None
|
||||
|
||||
def to_dict(self):
|
||||
d = {}
|
||||
for key in ['position', 'pressure']:
|
||||
val = getattr(self, key, None)
|
||||
if val is not None:
|
||||
d[key] = val
|
||||
return d
|
||||
|
||||
|
||||
class Stroke(GObject.Object):
|
||||
def __init__(self, drawing):
|
||||
GObject.Object.__init__(self)
|
||||
self.drawing = drawing
|
||||
self.points = []
|
||||
self._position = (0, 0)
|
||||
self._pressure = 0
|
||||
|
||||
def new_rel(self, position=None, pressure=None):
|
||||
p = Point(self)
|
||||
if position is not None:
|
||||
x, y = self._position
|
||||
self._position = (x + position[0], y + position[1])
|
||||
p.position = self._position
|
||||
if pressure is not None:
|
||||
self._pressure += pressure
|
||||
p.pressure = self._pressure
|
||||
|
||||
self.points.append(p)
|
||||
|
||||
def new_abs(self, position=None, pressure=None):
|
||||
p = Point(self)
|
||||
if position is not None:
|
||||
self._position = position
|
||||
p.position = position
|
||||
if pressure is not None:
|
||||
self._pressure = pressure
|
||||
p.pressure = pressure
|
||||
|
||||
self.points.append(p)
|
||||
|
||||
def to_dict(self):
|
||||
d = {}
|
||||
d['points'] = [p.to_dict() for p in self.points]
|
||||
return d
|
||||
|
||||
|
||||
class Drawing(GObject.Object):
|
||||
"""
|
||||
Abstracts a drawing. The drawing is composed Strokes, each of which has
|
||||
Points.
|
||||
"""
|
||||
def __init__(self, name, dimensions, timestamp):
|
||||
GObject.Object.__init__(self)
|
||||
self.name = name
|
||||
self.dimensions = dimensions
|
||||
self.timestamp = timestamp # unix seconds
|
||||
self.strokes = []
|
||||
self._current_stroke = -1
|
||||
|
||||
# The way we're building drawings, we don't need to change the current
|
||||
# stroke at runtime, so this is read-ony
|
||||
@property
|
||||
def current_stroke(self):
|
||||
return self.strokes[self._current_stroke]
|
||||
|
||||
def new_stroke(self):
|
||||
"""
|
||||
Create a new stroke and make it the current stroke
|
||||
"""
|
||||
l = Stroke(self)
|
||||
self.strokes.append(l)
|
||||
self._current_stroke += 1
|
||||
return l
|
||||
|
||||
def to_json(self):
|
||||
JSON_FILE_FORMAT_VERSION = 1
|
||||
|
||||
json_data = {
|
||||
'version': JSON_FILE_FORMAT_VERSION,
|
||||
'devicename': self.name,
|
||||
'dimensions': list(self.dimensions),
|
||||
'timestamp': self.timestamp,
|
||||
'strokes': [s.to_dict() for s in self.strokes]
|
||||
}
|
||||
return json.dumps(json_data)
|
|
@ -19,6 +19,7 @@ import time
|
|||
import uuid
|
||||
import errno
|
||||
from gi.repository import GObject
|
||||
from .drawing import Drawing
|
||||
|
||||
logger = logging.getLogger('tuhi.wacom')
|
||||
|
||||
|
@ -65,27 +66,6 @@ class NordicData(list):
|
|||
self.length = bs[1]
|
||||
|
||||
|
||||
class Stroke(object):
|
||||
RELATIVE = 1
|
||||
ABSOLUTE = 2
|
||||
|
||||
def __init__(self):
|
||||
self.points = []
|
||||
|
||||
def add_pos(self, x, y, p=None):
|
||||
self.points.append((Stroke.ABSOLUTE, x, y, p))
|
||||
|
||||
def add_rel(self, x, y, p=None):
|
||||
self.points.append((Stroke.RELATIVE, x, y, p))
|
||||
|
||||
|
||||
class Drawing(list):
|
||||
def __init__(self, size, timestamp):
|
||||
super().__init__()
|
||||
self.timestamp = timestamp
|
||||
self.size = size
|
||||
|
||||
|
||||
class WacomException(Exception):
|
||||
errno = errno.ENOSYS
|
||||
|
||||
|
@ -491,15 +471,14 @@ class WacomDevice(GObject.Object):
|
|||
bitmask, opcode, raw_args, args, offset = self.next_pen_data(data, offset)
|
||||
if opcode == 0x3800:
|
||||
logger.info(f'beginning of sequence')
|
||||
drawing = Drawing((self.width, self.height), timestamp)
|
||||
drawing = Drawing(self.name, (self.width, self.height), timestamp)
|
||||
drawings.append(drawing)
|
||||
continue
|
||||
elif opcode == 0xeeff:
|
||||
# some sort of headers
|
||||
time_offset = int.from_bytes(raw_args[4:], byteorder='little')
|
||||
logger.info(f'time offset since boot: {time_offset * 0.005} secs')
|
||||
stroke = Stroke()
|
||||
drawing.append(stroke)
|
||||
stroke = drawing.new_stroke()
|
||||
continue
|
||||
if bytes(args) == b'\xff\xff\xff\xff\xff\xff\xff\xff':
|
||||
logger.info(f'end of sequence')
|
||||
|
@ -510,8 +489,7 @@ class WacomDevice(GObject.Object):
|
|||
continue
|
||||
|
||||
if stroke is None:
|
||||
stroke = Stroke()
|
||||
drawing.append(stroke)
|
||||
stroke = drawing.new_stroke()
|
||||
|
||||
x, dx, xrel = self.get_coordinate(bitmask, 0, args, x, dx)
|
||||
y, dy, yrel = self.get_coordinate(bitmask, 1, args, y, dy)
|
||||
|
@ -526,9 +504,9 @@ class WacomDevice(GObject.Object):
|
|||
if bitmask & 0b00111100 == 0:
|
||||
continue
|
||||
if xrel or yrel or prel:
|
||||
stroke.add_rel(dx, dy, dp)
|
||||
stroke.new_rel((dx, dy), dp)
|
||||
else:
|
||||
stroke.add_pos(x, y, p)
|
||||
stroke.new_abs((x, y), p)
|
||||
|
||||
return drawings
|
||||
|
||||
|
|
Loading…
Reference in New Issue