#! /usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------------------------------------------------------------
# Name: graph.py
# Purpose:
#
# Author: Jeremy Arendt
#
# Created: 2004/28/01
# RCS-ID: $Id: graph.py,v 1.1 2005/06/09 16:37:52 Inigo Exp $
# Copyright: (c) 2002
# Licence: See G3.LICENCE.TXT
#-----------------------------------------------------------------------------
import wx
import random
from traceback import print_exc
from btconfig import BTConfig
class GraphRecord:
def __init__(self, gp_linecolor1 = wx.Color(255,0,0),
gp_linecolor2 = wx.Color(0,0,255),
max_x = 100,
max_y = 100,
avg=1):
self.linepen1 = wx.Pen(gp_linecolor1, 1, wx.SOLID)
self.linepen2 = wx.Pen(gp_linecolor2, 1, wx.SOLID)
self.avg_over = avg
self.max_x = max_x+1 # max relative y
self.max_y = max_y+1 # max relative x
self.value = 0
self.cur_x = 0
self.cur_y = 0
self.avg_y = []
self.screen_x = 0
self.screen_y = 0
self.graph_area = [(0,0),(0,0)] #to be recived OnSize
self.line_data = [0] * (self.max_x)
self.line = [wx.Point(0,0)] * (self.max_x)
def SetYMax(self, y, size=False):
self.max_y = max(1, y)
if size:
self.OnSize(self.graph_area)
def OnSize(self, graph_area):
self.graph_area = graph_area
#resize graph
ga = self.graph_area
delta_x = float(ga[1][0] - ga[0][0]) / self.max_x
delta_y = float(ga[1][1] - ga[0][1]) / self.max_y
x = 0
for y in self.line_data:
self.screen_x = int(ga[0][0] + x*delta_x)
self.screen_y = int(ga[1][1] - y*delta_y)
if self.screen_y < ga[0][1]:
self.screen_y = ga[0][1]
if self.screen_y < ga[0][1]:
self.screen_y = ga[1][1]
self.line[x] = wx.Point( self.screen_x, self.screen_y )
x += 1
def ChangeColor(self, color1, color2):
self.linepen1 = wx.Pen(color1, 1, wx.SOLID)
self.linepen2 = wx.Pen(color2, 1, wx.SOLID)
def AddValue(self, value):
self.cur_y = value
self.cur_x += 1
ga = self.graph_area
if self.cur_x >= self.max_x:
self.cur_x = 1
self.line_data[0] = self.line_data[self.max_x-1]
self.line[0] = wx.Point( ga[0][0], self.line[self.max_x-1].y )
delta_x = float(ga[1][0] - ga[0][0]) / self.max_x
delta_y = float(ga[1][1] - ga[0][1]) / self.max_y
x = self.cur_x
y = self.cur_y
# avg y
if self.avg_over > 1:
if len(self.avg_y) > self.avg_over:
self.avg_y.pop(0)
self.avg_y.append(y)
sum = 0
for v in self.avg_y:
sum += v
y = sum / self.avg_over
self.screen_x = int(ga[0][0] + x*delta_x)
self.screen_y = int(ga[1][1] - y*delta_y)
if self.screen_y < ga[0][1]:
self.screen_y = ga[0][1]
if self.screen_y < ga[0][1]:
self.screen_y = ga[1][1]
self.line_data[x] = int(y)
self.line[x] = wx.Point( self.screen_x, self.screen_y )
class Graph(wx.Panel):
def __init__(self, parent, btconfig, margin=15, xaxis_text = "x", yaxis_text = "y", size=wx.DefaultSize):
wx.Panel.__init__(self, parent, -1, size=size, style = wx.NO_FULL_REPAINT_ON_RESIZE)
self.xaxis_text = [xaxis_text, 8, wx.SWISS, wx.NORMAL, wx.NORMAL]
self.yaxis_text = [yaxis_text, 8, wx.SWISS, wx.NORMAL, wx.NORMAL]
self.btconfig = btconfig
self.client_size = size
self.graph_area = [(margin,margin), (self.client_size[0]-margin,self.client_size[1]-margin)]
self.margin = margin
self.records = []
self.InitBuffer()
wx.EVT_SIZE(self, self.OnSize)
wx.EVT_PAINT(self, self.OnPaint)
#wx.EVT_ERASE_BACKGROUND(self, self.DummyFunc)
def DummyFunc(self,event):
pass
def UpdateGraph(self):
if not self.IsShown():
return
self.InitBuffer()
def GetGraphArea(self):
return self.graph_area
def AddRecord(self, record):
record.OnSize(self.graph_area)
self.records.append(record)
def RemoveRecord(self, record):
try:
self.records.remove(record)
return True
except:
return False
def InitBuffer(self):
size = self.GetClientSize()
self.buffer = wx.EmptyBitmap(size.width, size.height)
dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
self.DrawGraph(dc)
def OnSize(self, event=None):
if not self.IsShown() and event:
return
self.client_size = self.GetClientSize()
self.graph_area = [(self.margin,self.margin-10), (self.client_size[0]-self.margin,self.client_size[1]-self.margin)]
for record in self.records:
record.OnSize(self.graph_area)
self.InitBuffer()
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self, self.buffer)
def DrawGraph(self, dc):
gp_bgcolor = self.btconfig.GetColor('gp_bgcolor')
gp_linecolor1 = self.btconfig.GetColor('gp_linecolor1')
gp_grapharea_b = self.btconfig.GetColor('gp_grapharea_b')
gp_grapharea_f = self.btconfig.GetColor('gp_grapharea_f')
gp_hbars = self.btconfig.GetColor('gp_hbars')
#setbrushes
hbars = wx.Pen(gp_hbars, 1, wx.DOT)
no_pen = wx.Pen(gp_bgcolor, 0, wx.SOLID)
no_brush = wx.Brush(gp_bgcolor, wx.TRANSPARENT)
bgbrush = wx.Brush(gp_bgcolor, wx.SOLID)
grapharea = wx.Brush(gp_grapharea_b, wx.SOLID)
grapharea_pen = wx.Pen(gp_grapharea_f, 2, wx.SOLID)
grapharea_pen.SetCap(wx.CAP_BUTT)
# some tmp locals
if len(self.records) > 0:
progress_line = True
else:
progress_line = False
xaxis_text = self.xaxis_text
yaxis_text = self.yaxis_text
ga = self.graph_area
dc.SetBackground(bgbrush)
dc.Clear()
#start drawing
dc.BeginDrawing()
#draw graph area rect
dc.SetPen(no_pen)
dc.SetBrush(grapharea)
dc.DrawRectangle(ga[0][0], ga[0][1], ga[1][0]-ga[0][0], ga[1][1]-ga[0][1])
#draw h_bars
dc.SetPen(hbars)
h = ga[1][1] - ga[0][1]
h_delta = float(h) / 10
for i in range(1, 10):
y = ga[0][1] + int(h_delta*i)
dc.DrawLine(ga[0][0]+2, y, ga[1][0]-1, y)
# draw graph line (s)
for record in self.records:
dc.SetPen(record.linepen1)
dc.DrawLines( record.line[:record.cur_x+1] )
dc.SetPen(record.linepen2)
dc.DrawLines( record.line[record.cur_x+1:] )
# draw progress indicator line
if progress_line:
x = self.records[0].screen_x
dc.SetPen(hbars)
dc.DrawLine(x, ga[0][1], x, ga[1][1])
# draw bounding box around graph area
dc.SetPen(grapharea_pen)
dc.SetBrush(no_brush)
dc.DrawRectangle(ga[0][0], ga[0][1], ga[1][0]-ga[0][0], (ga[1][1]-ga[0][1])+1)
# draw text
dc.SetFont(wx.Font(xaxis_text[1], wx.SWISS, wx.NORMAL, wx.NORMAL))
dc.SetTextForeground(gp_grapharea_f)
tsize = dc.GetTextExtent(xaxis_text[0])
center = ((ga[1][0]-ga[0][0])/ 2) + ga[0][0]
dc.DrawText(xaxis_text[0], int(center - tsize[0]/2), ( ga[1][1] + 0))
tsize = dc.GetTextExtent(yaxis_text[0])
h1 = ga[0][1]
h2 = (ga[1][1] - ga[0][1]) / 2
h3 = tsize[0]/2
center = int( h1 + h2 + h3 )
dc.SetFont(wx.Font(yaxis_text[1], wx.SWISS, wx.NORMAL, wx.NORMAL))
dc.DrawRotatedText(yaxis_text[0], 2, center, 90)
dc.EndDrawing()
#---------------------------------------------------------------------------
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, '')
p = Graph(frame, BTConfig())
p.Show(True)
frame.Show(True)
app.MainLoop()
|