1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124 | import re
from copy import copy
from .lazy import LazyValue
class SizeValue:
parser = re.compile(
r"^(?P<min_size>\d+)$|^(?P<ratio>\d+)%$|^(?P<fill_1>fill)$|^fill[(](?P<fill>\d+)[)]+$"
) # noqa
def __init__(self, min_size=0, ratio=None, fill=0, lazy_value=None):
self.min_size = min_size
self.ratio = ratio
self.fill = fill
self.lazy_value = lazy_value
@classmethod
def parse(cls, obj):
if isinstance(obj, int) or isinstance(obj, float):
return SizeValue(min_size=obj)
if isinstance(obj, LazyValue):
return SizeValue(lazy_value=obj)
if not isinstance(obj, str) or not str:
raise Exception("{!r} cannot be used as as size value", obj)
m = cls.parser.match(obj)
if m is None:
raise Exception("Invalid format of size string")
m = m.groupdict()
if m["min_size"] is not None:
return SizeValue(min_size=float(m["min_size"]))
if m["ratio"] is not None:
ratio = float(m["ratio"]) / 100
return SizeValue(ratio=ratio)
if m["fill_1"] is not None:
return SizeValue(fill=1)
if m["fill"] is not None:
return SizeValue(fill=int(m["fill"]))
raise Exception("Invalid string as size value")
def ensure(self, size):
if size <= self.min_size:
return self
s = copy(self)
s.min_size = size
return s
def compute(self, full_size, fill_unit):
if self.lazy_value:
return self.lazy_value.eval()
if self.fill:
if fill_unit is None:
return full_size
else:
return fill_unit * self.fill
if self.ratio:
return max(full_size * self.ratio, self.min_size)
return self.min_size
def __repr__(self):
return "<SizeValue min_size={} ratio={} fill={} lazy_value={}>".format(
self.min_size, self.ratio, self.fill, self.lazy_value is not None
)
class PosValue:
parser = re.compile(r"^(?P<fix_pos>^\d+$)|^(?P<ratio>^\d+)%$|^\[(?P<align>\d+)%\]$")
def __init__(self, fix_pos=None, ratio=None, align=None, lazy_value=None):
self.fix_pos = fix_pos
self.ratio = ratio
self.align = align
self.lazy_value = lazy_value
@classmethod
def parse(cls, obj):
if obj is None:
return PosValue()
if isinstance(obj, int) or isinstance(obj, float):
return PosValue(fix_pos=obj)
if isinstance(obj, LazyValue):
return PosValue(lazy_value=obj)
if not isinstance(obj, str) or not str:
raise Exception("{!r} cannot be used as as size value", obj)
m = cls.parser.match(obj)
if m is None:
raise Exception("Invalid format of position string")
m = m.groupdict()
if m["fix_pos"] is not None:
return PosValue(fix_pos=float(m["fix_pos"]))
if m["ratio"] is not None:
ratio = float(m["ratio"]) / 100
return PosValue(ratio=ratio)
if m["align"] is not None:
align = float(m["align"]) / 100
return PosValue(align=align)
raise Exception("Invalid string as position request")
def compute(self, origin, full_size, self_size):
if self.lazy_value:
return self.lazy_value.eval()
if self.ratio is not None:
return origin + full_size * self.ratio
if self.align is not None:
return origin + (full_size - self_size) * self.align
if self.fix_pos is not None:
return origin + self.fix_pos
raise Exception("Invalid pos")
|