1 # SchedGui.py - Python extension for perf script, basic GUI code for
2 # traces drawing and overview.
4 # Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
6 # This software is distributed under the terms of the GNU General
7 # Public License ("GPL") version 2 as published by the Free Software
14 raise ImportError("You need to install the wxpython lib for this script")
17 class RootFrame(wx
.Frame
):
21 EVENT_MARKING_WIDTH
= 5
23 def __init__(self
, sched_tracer
, title
, parent
= None, id = -1):
24 wx
.Frame
.__init
__(self
, parent
, id, title
)
26 (self
.screen_width
, self
.screen_height
) = wx
.GetDisplaySize()
27 self
.screen_width
-= 10
28 self
.screen_height
-= 10
30 self
.scroll_scale
= 20
31 self
.sched_tracer
= sched_tracer
32 self
.sched_tracer
.set_root_win(self
)
33 (self
.ts_start
, self
.ts_end
) = sched_tracer
.interval()
34 self
.update_width_virtual()
35 self
.nr_rects
= sched_tracer
.nr_rectangles() + 1
36 self
.height_virtual
= RootFrame
.Y_OFFSET
+ (self
.nr_rects
* (RootFrame
.RECT_HEIGHT
+ RootFrame
.RECT_SPACE
))
39 self
.panel
= wx
.Panel(self
, size
=(self
.screen_width
, self
.screen_height
))
41 # scrollable container
42 self
.scroll
= wx
.ScrolledWindow(self
.panel
)
43 self
.scroll
.SetScrollbars(self
.scroll_scale
, self
.scroll_scale
, self
.width_virtual
/ self
.scroll_scale
, self
.height_virtual
/ self
.scroll_scale
)
44 self
.scroll
.EnableScrolling(True, True)
45 self
.scroll
.SetFocus()
47 # scrollable drawing area
48 self
.scroll_panel
= wx
.Panel(self
.scroll
, size
=(self
.screen_width
- 15, self
.screen_height
/ 2))
49 self
.scroll_panel
.Bind(wx
.EVT_PAINT
, self
.on_paint
)
50 self
.scroll_panel
.Bind(wx
.EVT_KEY_DOWN
, self
.on_key_press
)
51 self
.scroll_panel
.Bind(wx
.EVT_LEFT_DOWN
, self
.on_mouse_down
)
52 self
.scroll
.Bind(wx
.EVT_PAINT
, self
.on_paint
)
53 self
.scroll
.Bind(wx
.EVT_KEY_DOWN
, self
.on_key_press
)
54 self
.scroll
.Bind(wx
.EVT_LEFT_DOWN
, self
.on_mouse_down
)
59 self
.scroll_panel
.SetDimensions(-1, -1, self
.width_virtual
, self
.height_virtual
, wx
.SIZE_USE_EXISTING
)
65 def us_to_px(self
, val
):
66 return val
/ (10 ** 3) * self
.zoom
68 def px_to_us(self
, val
):
69 return (val
/ self
.zoom
) * (10 ** 3)
71 def scroll_start(self
):
72 (x
, y
) = self
.scroll
.GetViewStart()
73 return (x
* self
.scroll_scale
, y
* self
.scroll_scale
)
75 def scroll_start_us(self
):
76 (x
, y
) = self
.scroll_start()
77 return self
.px_to_us(x
)
79 def paint_rectangle_zone(self
, nr
, color
, top_color
, start
, end
):
80 offset_px
= self
.us_to_px(start
- self
.ts_start
)
81 width_px
= self
.us_to_px(end
- self
.ts_start
)
83 offset_py
= RootFrame
.Y_OFFSET
+ (nr
* (RootFrame
.RECT_HEIGHT
+ RootFrame
.RECT_SPACE
))
84 width_py
= RootFrame
.RECT_HEIGHT
88 if top_color
is not None:
90 top_color
= wx
.Colour(r
, g
, b
)
91 brush
= wx
.Brush(top_color
, wx
.SOLID
)
93 dc
.DrawRectangle(offset_px
, offset_py
, width_px
, RootFrame
.EVENT_MARKING_WIDTH
)
94 width_py
-= RootFrame
.EVENT_MARKING_WIDTH
95 offset_py
+= RootFrame
.EVENT_MARKING_WIDTH
98 color
= wx
.Colour(r
, g
, b
)
99 brush
= wx
.Brush(color
, wx
.SOLID
)
101 dc
.DrawRectangle(offset_px
, offset_py
, width_px
, width_py
)
103 def update_rectangles(self
, dc
, start
, end
):
104 start
+= self
.ts_start
106 self
.sched_tracer
.fill_zone(start
, end
)
108 def on_paint(self
, event
):
109 dc
= wx
.PaintDC(self
.scroll_panel
)
112 width
= min(self
.width_virtual
, self
.screen_width
)
113 (x
, y
) = self
.scroll_start()
114 start
= self
.px_to_us(x
)
115 end
= self
.px_to_us(x
+ width
)
116 self
.update_rectangles(dc
, start
, end
)
118 def rect_from_ypixel(self
, y
):
119 y
-= RootFrame
.Y_OFFSET
120 rect
= y
/ (RootFrame
.RECT_HEIGHT
+ RootFrame
.RECT_SPACE
)
121 height
= y
% (RootFrame
.RECT_HEIGHT
+ RootFrame
.RECT_SPACE
)
123 if rect
< 0 or rect
> self
.nr_rects
- 1 or height
> RootFrame
.RECT_HEIGHT
:
128 def update_summary(self
, txt
):
131 self
.txt
= wx
.StaticText(self
.panel
, -1, txt
, (0, (self
.screen_height
/ 2) + 50))
134 def on_mouse_down(self
, event
):
135 (x
, y
) = event
.GetPositionTuple()
136 rect
= self
.rect_from_ypixel(y
)
140 t
= self
.px_to_us(x
) + self
.ts_start
142 self
.sched_tracer
.mouse_down(rect
, t
)
145 def update_width_virtual(self
):
146 self
.width_virtual
= self
.us_to_px(self
.ts_end
- self
.ts_start
)
149 self
.update_width_virtual()
150 (xpos
, ypos
) = self
.scroll
.GetViewStart()
151 xpos
= self
.us_to_px(x
) / self
.scroll_scale
152 self
.scroll
.SetScrollbars(self
.scroll_scale
, self
.scroll_scale
, self
.width_virtual
/ self
.scroll_scale
, self
.height_virtual
/ self
.scroll_scale
, xpos
, ypos
)
156 x
= self
.scroll_start_us()
161 x
= self
.scroll_start_us()
166 def on_key_press(self
, event
):
167 key
= event
.GetRawKeyCode()
175 key
= event
.GetKeyCode()
176 (x
, y
) = self
.scroll
.GetViewStart()
177 if key
== wx
.WXK_RIGHT
:
178 self
.scroll
.Scroll(x
+ 1, y
)
179 elif key
== wx
.WXK_LEFT
:
180 self
.scroll
.Scroll(x
- 1, y
)
181 elif key
== wx
.WXK_DOWN
:
182 self
.scroll
.Scroll(x
, y
+ 1)
183 elif key
== wx
.WXK_UP
:
184 self
.scroll
.Scroll(x
, y
- 1)