#
# Copyright 2009 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#

import wx
from grid_plotter_base import grid_plotter_base
from OpenGL import GL
import common
import numpy

LEGEND_TEXT_FONT_SIZE = 8
LEGEND_BOX_PADDING = 3
MIN_PADDING = 0, 0, 0, 70 #top, right, bottom, left
#constants for the waveform storage
SAMPLES_KEY = 'samples'
COLOR_SPEC_KEY = 'color_spec'
MARKERY_KEY = 'marker'
TRIG_OFF_KEY = 'trig_off'

##################################################
# Bar Plotter for histogram waveforms
##################################################
class bar_plotter(grid_plotter_base):

	def __init__(self, parent):
		"""
		Create a new bar plotter.
		"""
		#init
		grid_plotter_base.__init__(self, parent, MIN_PADDING)
		self._bars = list()
		self._bar_width = .5
		self._color_spec = (0, 0, 0)
		#setup bar cache
		self._bar_cache = self.new_gl_cache(self._draw_bars)
		#setup bar plotter
		self.register_init(self._init_bar_plotter)

	def _init_bar_plotter(self):
		"""
		Run gl initialization tasks.
		"""
		GL.glEnableClientState(GL.GL_VERTEX_ARRAY)

	def _draw_bars(self):
		"""
		Draw the vertical bars.
		"""
		bars = self._bars
		num_bars = len(bars)
		if num_bars == 0: return
		#use scissor to prevent drawing outside grid
		GL.glEnable(GL.GL_SCISSOR_TEST)
		GL.glScissor(
			self.padding_left,
			self.padding_bottom+1,
			self.width-self.padding_left-self.padding_right-1,
			self.height-self.padding_top-self.padding_bottom-1,
		)
		#load the points
		points = list()
		width = self._bar_width/2
		for i, bar in enumerate(bars):
			points.extend([
					(i-width, 0),
					(i+width, 0),
					(i+width, bar),
					(i-width, bar),
				]
			)
		GL.glColor3f(*self._color_spec)
		#matrix transforms
		GL.glPushMatrix()
		GL.glTranslatef(self.padding_left, self.padding_top, 0)
		GL.glScalef(
			(self.width-self.padding_left-self.padding_right),
			(self.height-self.padding_top-self.padding_bottom),
			1,
		)
		GL.glTranslatef(0, 1, 0)
		GL.glScalef(1.0/(num_bars-1), -1.0/(self.y_max-self.y_min), 1)
		GL.glTranslatef(0, -self.y_min, 0)
		#draw the bars
		GL.glVertexPointerf(points)
		GL.glDrawArrays(GL.GL_QUADS, 0, len(points))
		GL.glPopMatrix()
		GL.glDisable(GL.GL_SCISSOR_TEST)

	def _populate_point_label(self, x_val, y_val):
		"""
		Get the text the will populate the point label.
		Give X and Y values for the current point.
		Give values for the channel at the X coordinate.
		@param x_val the current x value
		@param y_val the current y value
		@return a string with newlines
		"""
		if len(self._bars) == 0: return ''
		scalar = float(len(self._bars)-1)/(self.x_max - self.x_min)
		#convert x val to bar #
		bar_index = scalar*(x_val - self.x_min)
		#if abs(bar_index - round(bar_index)) > self._bar_width/2: return ''
		bar_index = int(round(bar_index))
		bar_start = (bar_index - self._bar_width/2)/scalar + self.x_min
		bar_end = (bar_index + self._bar_width/2)/scalar + self.x_min
		bar_value = self._bars[bar_index]
		return '%s to %s\n%s: %s'%(
			common.eng_format(bar_start, self.x_units),
			common.eng_format(bar_end, self.x_units),
			self.y_label, common.eng_format(bar_value, self.y_units),
		)

	def set_bars(self, bars, bar_width, color_spec):
		"""
		Set the bars.
		@param bars a list of bars
		@param bar_width the fractional width of the bar, between 0 and 1
		@param color_spec the color tuple
		"""
		self.lock()
		self._bars = bars
		self._bar_width = float(bar_width)
		self._color_spec = color_spec
		self._bar_cache.changed(True)
		self.unlock()