# SchedGui.py - Python extension for perf script, basic GUI code for
#		traces drawing and overview.
#
# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
#
# This software is distributed under the terms of the GNU General
# Public License ("GPL") version 2 as published by the Free Software
# Foundation.


try:
	import wx
except ImportError:
	raise ImportError, "You need to install the wxpython lib for this script"


class RootFrame(wx.Frame):
	Y_OFFSET = 100
	RECT_HEIGHT = 100
	RECT_SPACE = 50
	EVENT_MARKING_WIDTH = 5

	def __init__(self, sched_tracer, title, parent = None, id = -1):
		wx.Frame.__init__(self, parent, id, title)

		(self.screen_width, self.screen_height) = wx.GetDisplaySize()
		self.screen_width -= 10
		self.screen_height -= 10
		self.zoom = 0.5
		self.scroll_scale = 20
		self.sched_tracer = sched_tracer
		self.sched_tracer.set_root_win(self)
		(self.ts_start, self.ts_end) = sched_tracer.interval()
		self.update_width_virtual()
		self.nr_rects = sched_tracer.nr_rectangles() + 1
		self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))

		# whole window panel
		self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))

		# scrollable container
		self.scroll = wx.ScrolledWindow(self.panel)
		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale)
		self.scroll.EnableScrolling(True, True)
		self.scroll.SetFocus()

		# scrollable drawing area
		self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2))
		self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint)
		self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
		self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
		self.scroll.Bind(wx.EVT_PAINT, self.on_paint)
		self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
		self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)

		self.scroll.Fit()
		self.Fit()

		self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING)

		self.txt = None

		self.Show(True)

	def us_to_px(self, val):
		return val / (10 ** 3) * self.zoom

	def px_to_us(self, val):
		return (val / self.zoom) * (10 ** 3)

	def scroll_start(self):
		(x, y) = self.scroll.GetViewStart()
		return (x * self.scroll_scale, y * self.scroll_scale)

	def scroll_start_us(self):
		(x, y) = self.scroll_start()
		return self.px_to_us(x)

	def paint_rectangle_zone(self, nr, color, top_color, start, end):
		offset_px = self.us_to_px(start - self.ts_start)
		width_px = self.us_to_px(end - self.ts_start)

		offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
		width_py = RootFrame.RECT_HEIGHT

		dc = self.dc

		if top_color is not None:
			(r, g, b) = top_color
			top_color = wx.Colour(r, g, b)
			brush = wx.Brush(top_color, wx.SOLID)
			dc.SetBrush(brush)
			dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH)
			width_py -= RootFrame.EVENT_MARKING_WIDTH
			offset_py += RootFrame.EVENT_MARKING_WIDTH

		(r ,g, b) = color
		color = wx.Colour(r, g, b)
		brush = wx.Brush(color, wx.SOLID)
		dc.SetBrush(brush)
		dc.DrawRectangle(offset_px, offset_py, width_px, width_py)

	def update_rectangles(self, dc, start, end):
		start += self.ts_start
		end += self.ts_start
		self.sched_tracer.fill_zone(start, end)

	def on_paint(self, event):
		dc = wx.PaintDC(self.scroll_panel)
		self.dc = dc

		width = min(self.width_virtual, self.screen_width)
		(x, y) = self.scroll_start()
		start = self.px_to_us(x)
		end = self.px_to_us(x + width)
		self.update_rectangles(dc, start, end)

	def rect_from_ypixel(self, y):
		y -= RootFrame.Y_OFFSET
		rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
		height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)

		if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT:
			return -1

		return rect

	def update_summary(self, txt):
		if self.txt:
			self.txt.Destroy()
		self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50))


	def on_mouse_down(self, event):
		(x, y) = event.GetPositionTuple()
		rect = self.rect_from_ypixel(y)
		if rect == -1:
			return

		t = self.px_to_us(x) + self.ts_start

		self.sched_tracer.mouse_down(rect, t)


	def update_width_virtual(self):
		self.width_virtual = self.us_to_px(self.ts_end - self.ts_start)

	def __zoom(self, x):
		self.update_width_virtual()
		(xpos, ypos) = self.scroll.GetViewStart()
		xpos = self.us_to_px(x) / self.scroll_scale
		self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos)
		self.Refresh()

	def zoom_in(self):
		x = self.scroll_start_us()
		self.zoom *= 2
		self.__zoom(x)

	def zoom_out(self):
		x = self.scroll_start_us()
		self.zoom /= 2
		self.__zoom(x)


	def on_key_press(self, event):
		key = event.GetRawKeyCode()
		if key == ord("+"):
			self.zoom_in()
			return
		if key == ord("-"):
			self.zoom_out()
			return

		key = event.GetKeyCode()
		(x, y) = self.scroll.GetViewStart()
		if key == wx.WXK_RIGHT:
			self.scroll.Scroll(x + 1, y)
		elif key == wx.WXK_LEFT:
			self.scroll.Scroll(x - 1, y)
		elif key == wx.WXK_DOWN:
			self.scroll.Scroll(x, y + 1)
		elif key == wx.WXK_UP:
			self.scroll.Scroll(x, y - 1)
