-
Notifications
You must be signed in to change notification settings - Fork 45
/
kiva_explorer.py
128 lines (101 loc) · 3.5 KB
/
kiva_explorer.py
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
125
126
127
128
"""
Kiva Explorer
=============
Interactive editor for exploring Kiva drawing commands.
"""
import time
from traits.api import Any, Code, Float, Instance, Property, Str
from traitsui.api import HSplit, ModelView, UItem, VGroup, View
from enable.api import Component, ComponentEditor
default_script = """# Write your code here.
# The graphics context is available as gc.
from math import pi
from kiva import constants
from kiva.fonttools import Font
with gc:
gc.set_fill_color((1.0, 1.0, 0.0, 1.0))
gc.arc(200, 200, 100, 0, 2*pi)
gc.fill_path()
with gc:
gc.set_font(Font('Times New Roman', size=24))
gc.translate_ctm(200, 200)
for i in range(0, 12):
gc.set_fill_color((i/12.0, 0.0, 1.0-(i/12.0), 0.75))
gc.rotate_ctm(2*pi/12.0)
gc.show_text_at_point("Hello World", 20, 0)
gc.set_stroke_color((0.0, 0.0, 1.0, 1.0))
gc.set_line_width(7)
gc.set_line_join(constants.JOIN_ROUND)
gc.set_line_cap(constants.CAP_ROUND)
gc.rect(100, 400, 50, 50)
gc.stroke_path()
"""
class ScriptedComponent(Component):
""" An Enable component that draws its mainlayer from a script """
#: kiva drawing code for mainlayer
draw_script = Code(default_script)
#: any errors which occur
error = Str
#: how long did the last draw take
last_draw_time = Float(0.0)
fps_display = Property(Str, depends_on='last_draw_time')
#: compiled code
_draw_code = Any
def _draw_mainlayer(self, gc, view_bounds=None, mode="default"):
""" Try running the compiled code with the graphics context as `gc` """
with gc:
try:
self.error = ''
start_time = time.time()
exec(self._draw_code, {}, {'gc': gc})
self.last_draw_time = time.time() - start_time
except Exception as exc:
self.error = str(exc)
def _compile_script(self):
""" Try compiling the script to bytecode """
try:
self.error = ''
return compile(self.draw_script, "<script>", "exec")
except SyntaxError as exc:
self.error = str(exc)
return None
def _draw_script_changed(self):
code = self._compile_script()
if code is not None:
self._draw_code = code
self.request_redraw()
def __draw_code_default(self):
code = self._compile_script()
if code is None:
code = compile("", "<script>", "exec")
return code
def _get_fps_display(self):
if self.last_draw_time == 0.0:
return ""
draw_time_ms = self.last_draw_time * 1000.0
draw_fps = 1000.0 / draw_time_ms
return "{:.2f}ms ({:.2f} fps)".format(draw_time_ms, draw_fps)
class ScriptedComponentView(ModelView):
""" ModelView of a ScriptedComponent displaying the script and image """
#: the component we are editing
model = Instance(ScriptedComponent, ())
view = View(
HSplit(
VGroup(
UItem('model.draw_script'),
UItem(
'model.error',
visible_when="model.error != ''",
style='readonly',
height=100)
),
VGroup(
UItem('model', editor=ComponentEditor()),
UItem('model.fps_display', height=20)
),
),
resizable=True
)
if __name__ == '__main__':
view = ScriptedComponentView()
view.configure_traits()