1765532c8SArnaldo Carvalho de Melo# SchedGui.py - Python extension for perf script, basic GUI code for
2df92b408SFrederic Weisbecker#		traces drawing and overview.
3df92b408SFrederic Weisbecker#
4df92b408SFrederic Weisbecker# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
5df92b408SFrederic Weisbecker#
6df92b408SFrederic Weisbecker# This software is distributed under the terms of the GNU General
7df92b408SFrederic Weisbecker# Public License ("GPL") version 2 as published by the Free Software
8df92b408SFrederic Weisbecker# Foundation.
9df92b408SFrederic Weisbecker
10df92b408SFrederic Weisbecker
11df92b408SFrederic Weisbeckertry:
12df92b408SFrederic Weisbecker	import wx
13df92b408SFrederic Weisbeckerexcept ImportError:
142ab89262SJeremy Cline	raise ImportError("You need to install the wxpython lib for this script")
15df92b408SFrederic Weisbecker
16df92b408SFrederic Weisbecker
17df92b408SFrederic Weisbeckerclass RootFrame(wx.Frame):
18df92b408SFrederic Weisbecker	Y_OFFSET = 100
19df92b408SFrederic Weisbecker	RECT_HEIGHT = 100
20df92b408SFrederic Weisbecker	RECT_SPACE = 50
21df92b408SFrederic Weisbecker	EVENT_MARKING_WIDTH = 5
22df92b408SFrederic Weisbecker
23df92b408SFrederic Weisbecker	def __init__(self, sched_tracer, title, parent = None, id = -1):
24df92b408SFrederic Weisbecker		wx.Frame.__init__(self, parent, id, title)
25df92b408SFrederic Weisbecker
26df92b408SFrederic Weisbecker		(self.screen_width, self.screen_height) = wx.GetDisplaySize()
27df92b408SFrederic Weisbecker		self.screen_width -= 10
28df92b408SFrederic Weisbecker		self.screen_height -= 10
29df92b408SFrederic Weisbecker		self.zoom = 0.5
30df92b408SFrederic Weisbecker		self.scroll_scale = 20
31df92b408SFrederic Weisbecker		self.sched_tracer = sched_tracer
32df92b408SFrederic Weisbecker		self.sched_tracer.set_root_win(self)
33df92b408SFrederic Weisbecker		(self.ts_start, self.ts_end) = sched_tracer.interval()
34df92b408SFrederic Weisbecker		self.update_width_virtual()
35df92b408SFrederic Weisbecker		self.nr_rects = sched_tracer.nr_rectangles() + 1
36df92b408SFrederic Weisbecker		self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
37df92b408SFrederic Weisbecker
38df92b408SFrederic Weisbecker		# whole window panel
39df92b408SFrederic Weisbecker		self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))
40df92b408SFrederic Weisbecker
41df92b408SFrederic Weisbecker		# scrollable container
42df92b408SFrederic Weisbecker		self.scroll = wx.ScrolledWindow(self.panel)
43df92b408SFrederic Weisbecker		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale)
44df92b408SFrederic Weisbecker		self.scroll.EnableScrolling(True, True)
45df92b408SFrederic Weisbecker		self.scroll.SetFocus()
46df92b408SFrederic Weisbecker
47df92b408SFrederic Weisbecker		# scrollable drawing area
48df92b408SFrederic Weisbecker		self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2))
49df92b408SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint)
50df92b408SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
51df92b408SFrederic Weisbecker		self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
52df92b408SFrederic Weisbecker		self.scroll.Bind(wx.EVT_PAINT, self.on_paint)
53df92b408SFrederic Weisbecker		self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
54df92b408SFrederic Weisbecker		self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
55df92b408SFrederic Weisbecker
56df92b408SFrederic Weisbecker		self.scroll.Fit()
57df92b408SFrederic Weisbecker		self.Fit()
58df92b408SFrederic Weisbecker
59df92b408SFrederic Weisbecker		self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING)
60df92b408SFrederic Weisbecker
61df92b408SFrederic Weisbecker		self.txt = None
62df92b408SFrederic Weisbecker
63df92b408SFrederic Weisbecker		self.Show(True)
64df92b408SFrederic Weisbecker
65df92b408SFrederic Weisbecker	def us_to_px(self, val):
66df92b408SFrederic Weisbecker		return val / (10 ** 3) * self.zoom
67df92b408SFrederic Weisbecker
68df92b408SFrederic Weisbecker	def px_to_us(self, val):
69df92b408SFrederic Weisbecker		return (val / self.zoom) * (10 ** 3)
70df92b408SFrederic Weisbecker
71df92b408SFrederic Weisbecker	def scroll_start(self):
72df92b408SFrederic Weisbecker		(x, y) = self.scroll.GetViewStart()
73df92b408SFrederic Weisbecker		return (x * self.scroll_scale, y * self.scroll_scale)
74df92b408SFrederic Weisbecker
75df92b408SFrederic Weisbecker	def scroll_start_us(self):
76df92b408SFrederic Weisbecker		(x, y) = self.scroll_start()
77df92b408SFrederic Weisbecker		return self.px_to_us(x)
78df92b408SFrederic Weisbecker
79df92b408SFrederic Weisbecker	def paint_rectangle_zone(self, nr, color, top_color, start, end):
80df92b408SFrederic Weisbecker		offset_px = self.us_to_px(start - self.ts_start)
81df92b408SFrederic Weisbecker		width_px = self.us_to_px(end - self.ts_start)
82df92b408SFrederic Weisbecker
83df92b408SFrederic Weisbecker		offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
84df92b408SFrederic Weisbecker		width_py = RootFrame.RECT_HEIGHT
85df92b408SFrederic Weisbecker
86df92b408SFrederic Weisbecker		dc = self.dc
87df92b408SFrederic Weisbecker
88df92b408SFrederic Weisbecker		if top_color is not None:
89df92b408SFrederic Weisbecker			(r, g, b) = top_color
90df92b408SFrederic Weisbecker			top_color = wx.Colour(r, g, b)
91df92b408SFrederic Weisbecker			brush = wx.Brush(top_color, wx.SOLID)
92df92b408SFrederic Weisbecker			dc.SetBrush(brush)
93df92b408SFrederic Weisbecker			dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH)
94df92b408SFrederic Weisbecker			width_py -= RootFrame.EVENT_MARKING_WIDTH
95df92b408SFrederic Weisbecker			offset_py += RootFrame.EVENT_MARKING_WIDTH
96df92b408SFrederic Weisbecker
97df92b408SFrederic Weisbecker		(r ,g, b) = color
98df92b408SFrederic Weisbecker		color = wx.Colour(r, g, b)
99df92b408SFrederic Weisbecker		brush = wx.Brush(color, wx.SOLID)
100df92b408SFrederic Weisbecker		dc.SetBrush(brush)
101df92b408SFrederic Weisbecker		dc.DrawRectangle(offset_px, offset_py, width_px, width_py)
102df92b408SFrederic Weisbecker
103df92b408SFrederic Weisbecker	def update_rectangles(self, dc, start, end):
104df92b408SFrederic Weisbecker		start += self.ts_start
105df92b408SFrederic Weisbecker		end += self.ts_start
106df92b408SFrederic Weisbecker		self.sched_tracer.fill_zone(start, end)
107df92b408SFrederic Weisbecker
108df92b408SFrederic Weisbecker	def on_paint(self, event):
109df92b408SFrederic Weisbecker		dc = wx.PaintDC(self.scroll_panel)
110df92b408SFrederic Weisbecker		self.dc = dc
111df92b408SFrederic Weisbecker
112df92b408SFrederic Weisbecker		width = min(self.width_virtual, self.screen_width)
113df92b408SFrederic Weisbecker		(x, y) = self.scroll_start()
114df92b408SFrederic Weisbecker		start = self.px_to_us(x)
115df92b408SFrederic Weisbecker		end = self.px_to_us(x + width)
116df92b408SFrederic Weisbecker		self.update_rectangles(dc, start, end)
117df92b408SFrederic Weisbecker
118df92b408SFrederic Weisbecker	def rect_from_ypixel(self, y):
119df92b408SFrederic Weisbecker		y -= RootFrame.Y_OFFSET
120df92b408SFrederic Weisbecker		rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
121df92b408SFrederic Weisbecker		height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
122df92b408SFrederic Weisbecker
123df92b408SFrederic Weisbecker		if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT:
124df92b408SFrederic Weisbecker			return -1
125df92b408SFrederic Weisbecker
126df92b408SFrederic Weisbecker		return rect
127df92b408SFrederic Weisbecker
128df92b408SFrederic Weisbecker	def update_summary(self, txt):
129df92b408SFrederic Weisbecker		if self.txt:
130df92b408SFrederic Weisbecker			self.txt.Destroy()
131df92b408SFrederic Weisbecker		self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50))
132df92b408SFrederic Weisbecker
133df92b408SFrederic Weisbecker
134df92b408SFrederic Weisbecker	def on_mouse_down(self, event):
135df92b408SFrederic Weisbecker		(x, y) = event.GetPositionTuple()
136df92b408SFrederic Weisbecker		rect = self.rect_from_ypixel(y)
137df92b408SFrederic Weisbecker		if rect == -1:
138df92b408SFrederic Weisbecker			return
139df92b408SFrederic Weisbecker
140df92b408SFrederic Weisbecker		t = self.px_to_us(x) + self.ts_start
141df92b408SFrederic Weisbecker
142df92b408SFrederic Weisbecker		self.sched_tracer.mouse_down(rect, t)
143df92b408SFrederic Weisbecker
144df92b408SFrederic Weisbecker
145df92b408SFrederic Weisbecker	def update_width_virtual(self):
146df92b408SFrederic Weisbecker		self.width_virtual = self.us_to_px(self.ts_end - self.ts_start)
147df92b408SFrederic Weisbecker
148df92b408SFrederic Weisbecker	def __zoom(self, x):
149df92b408SFrederic Weisbecker		self.update_width_virtual()
150df92b408SFrederic Weisbecker		(xpos, ypos) = self.scroll.GetViewStart()
151df92b408SFrederic Weisbecker		xpos = self.us_to_px(x) / self.scroll_scale
152df92b408SFrederic Weisbecker		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos)
153df92b408SFrederic Weisbecker		self.Refresh()
154df92b408SFrederic Weisbecker
155df92b408SFrederic Weisbecker	def zoom_in(self):
156df92b408SFrederic Weisbecker		x = self.scroll_start_us()
157df92b408SFrederic Weisbecker		self.zoom *= 2
158df92b408SFrederic Weisbecker		self.__zoom(x)
159df92b408SFrederic Weisbecker
160df92b408SFrederic Weisbecker	def zoom_out(self):
161df92b408SFrederic Weisbecker		x = self.scroll_start_us()
162df92b408SFrederic Weisbecker		self.zoom /= 2
163df92b408SFrederic Weisbecker		self.__zoom(x)
164df92b408SFrederic Weisbecker
165df92b408SFrederic Weisbecker
166df92b408SFrederic Weisbecker	def on_key_press(self, event):
167df92b408SFrederic Weisbecker		key = event.GetRawKeyCode()
168df92b408SFrederic Weisbecker		if key == ord("+"):
169df92b408SFrederic Weisbecker			self.zoom_in()
170df92b408SFrederic Weisbecker			return
171df92b408SFrederic Weisbecker		if key == ord("-"):
172df92b408SFrederic Weisbecker			self.zoom_out()
173df92b408SFrederic Weisbecker			return
174df92b408SFrederic Weisbecker
175df92b408SFrederic Weisbecker		key = event.GetKeyCode()
176df92b408SFrederic Weisbecker		(x, y) = self.scroll.GetViewStart()
177df92b408SFrederic Weisbecker		if key == wx.WXK_RIGHT:
178df92b408SFrederic Weisbecker			self.scroll.Scroll(x + 1, y)
179df92b408SFrederic Weisbecker		elif key == wx.WXK_LEFT:
180df92b408SFrederic Weisbecker			self.scroll.Scroll(x - 1, y)
181df92b408SFrederic Weisbecker		elif key == wx.WXK_DOWN:
182df92b408SFrederic Weisbecker			self.scroll.Scroll(x, y + 1)
183df92b408SFrederic Weisbecker		elif key == wx.WXK_UP:
184df92b408SFrederic Weisbecker			self.scroll.Scroll(x, y - 1)
185