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