Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
SchedGui.py
Go to the documentation of this file.
1 # SchedGui.py - Python extension for perf script, basic GUI code for
2 # traces drawing and overview.
3 #
4 # Copyright (C) 2010 by Frederic Weisbecker <[email protected]>
5 #
6 # This software is distributed under the terms of the GNU General
7 # Public License ("GPL") version 2 as published by the Free Software
8 # Foundation.
9 
10 
11 try:
12  import wx
13 except ImportError:
14  raise ImportError, "You need to install the wxpython lib for this script"
15 
16 
17 class RootFrame(wx.Frame):
18  Y_OFFSET = 100
19  RECT_HEIGHT = 100
20  RECT_SPACE = 50
21  EVENT_MARKING_WIDTH = 5
22 
23  def __init__(self, sched_tracer, title, parent = None, id = -1):
24  wx.Frame.__init__(self, parent, id, title)
25 
26  (self.screen_width, self.screen_height) = wx.GetDisplaySize()
27  self.screen_width -= 10
28  self.screen_height -= 10
29  self.zoom = 0.5
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()
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))
37 
38  # whole window panel
39  self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))
40 
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()
46 
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)
55 
56  self.scroll.Fit()
57  self.Fit()
58 
59  self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING)
60 
61  self.txt = None
62 
63  self.Show(True)
64 
65  def us_to_px(self, val):
66  return val / (10 ** 3) * self.zoom
67 
68  def px_to_us(self, val):
69  return (val / self.zoom) * (10 ** 3)
70 
71  def scroll_start(self):
72  (x, y) = self.scroll.GetViewStart()
73  return (x * self.scroll_scale, y * self.scroll_scale)
74 
75  def scroll_start_us(self):
76  (x, y) = self.scroll_start()
77  return self.px_to_us(x)
78 
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)
82 
83  offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
84  width_py = RootFrame.RECT_HEIGHT
85 
86  dc = self.dc
87 
88  if top_color is not None:
89  (r, g, b) = top_color
90  top_color = wx.Colour(r, g, b)
91  brush = wx.Brush(top_color, wx.SOLID)
92  dc.SetBrush(brush)
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
96 
97  (r ,g, b) = color
98  color = wx.Colour(r, g, b)
99  brush = wx.Brush(color, wx.SOLID)
100  dc.SetBrush(brush)
101  dc.DrawRectangle(offset_px, offset_py, width_px, width_py)
102 
103  def update_rectangles(self, dc, start, end):
104  start += self.ts_start
105  end += self.ts_start
106  self.sched_tracer.fill_zone(start, end)
107 
108  def on_paint(self, event):
109  dc = wx.PaintDC(self.scroll_panel)
110  self.dc = dc
111 
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)
117 
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)
122 
123  if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT:
124  return -1
125 
126  return rect
127 
128  def update_summary(self, txt):
129  if self.txt:
130  self.txt.Destroy()
131  self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50))
132 
133 
134  def on_mouse_down(self, event):
135  (x, y) = event.GetPositionTuple()
136  rect = self.rect_from_ypixel(y)
137  if rect == -1:
138  return
139 
140  t = self.px_to_us(x) + self.ts_start
141 
142  self.sched_tracer.mouse_down(rect, t)
143 
144 
146  self.width_virtual = self.us_to_px(self.ts_end - self.ts_start)
147 
148  def __zoom(self, x):
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)
153  self.Refresh()
154 
155  def zoom_in(self):
156  x = self.scroll_start_us()
157  self.zoom *= 2
158  self.__zoom(x)
159 
160  def zoom_out(self):
161  x = self.scroll_start_us()
162  self.zoom /= 2
163  self.__zoom(x)
164 
165 
166  def on_key_press(self, event):
167  key = event.GetRawKeyCode()
168  if key == ord("+"):
169  self.zoom_in()
170  return
171  if key == ord("-"):
172  self.zoom_out()
173  return
174 
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)