summaryrefslogtreecommitdiff
path: root/gr-wxgui/src/python/plotter/plotter_base.py
diff options
context:
space:
mode:
Diffstat (limited to 'gr-wxgui/src/python/plotter/plotter_base.py')
-rw-r--r--gr-wxgui/src/python/plotter/plotter_base.py214
1 files changed, 214 insertions, 0 deletions
diff --git a/gr-wxgui/src/python/plotter/plotter_base.py b/gr-wxgui/src/python/plotter/plotter_base.py
new file mode 100644
index 000000000..6d9463458
--- /dev/null
+++ b/gr-wxgui/src/python/plotter/plotter_base.py
@@ -0,0 +1,214 @@
+#
+# Copyright 2008, 2009, 2010 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
+import wx.glcanvas
+from OpenGL import GL
+import common
+
+BACKGROUND_COLOR_SPEC = (1, 0.976, 1, 1) #creamy white
+
+##################################################
+# GL caching interface
+##################################################
+class gl_cache(object):
+ """
+ Cache a set of gl drawing routines in a compiled list.
+ """
+
+ def __init__(self, draw):
+ """
+ Create a new cache.
+ @param draw a function to draw gl stuff
+ """
+ self.changed(True)
+ self._draw = draw
+
+ def init(self):
+ """
+ To be called when gl initializes.
+ Create a new compiled list.
+ """
+ self._grid_compiled_list_id = GL.glGenLists(1)
+
+ def draw(self):
+ """
+ Draw the gl stuff using a compiled list.
+ If changed, reload the compiled list.
+ """
+ if self.changed():
+ GL.glNewList(self._grid_compiled_list_id, GL.GL_COMPILE)
+ self._draw()
+ GL.glEndList()
+ self.changed(False)
+ #draw the grid
+ GL.glCallList(self._grid_compiled_list_id)
+
+ def changed(self, state=None):
+ """
+ Set the changed flag if state is not None.
+ Otherwise return the changed flag.
+ """
+ if state is None: return self._changed
+ self._changed = state
+
+##################################################
+# OpenGL WX Plotter Canvas
+##################################################
+class plotter_base(wx.glcanvas.GLCanvas, common.mutex):
+ """
+ Plotter base class for all plot types.
+ """
+
+ def __init__(self, parent):
+ """
+ Create a new plotter base.
+ Initialize the GLCanvas with double buffering.
+ Initialize various plotter flags.
+ Bind the paint and size events.
+ @param parent the parent widgit
+ """
+ attribList = (wx.glcanvas.WX_GL_DOUBLEBUFFER, wx.glcanvas.WX_GL_RGBA)
+ wx.glcanvas.GLCanvas.__init__(self, parent, wx.ID_ANY, attribList); # Specifically use the CTOR which does NOT create an implicit GL context
+ self._gl_ctx = wx.glcanvas.GLContext(self) # Create the explicit GL context
+ self.use_persistence=False
+ self.persist_alpha=2.0/15
+ self.clear_accum=True
+ self._gl_init_flag = False
+ self._resized_flag = True
+ self._init_fcns = list()
+ self._draw_fcns = list()
+ self._gl_caches = list()
+ self.Bind(wx.EVT_PAINT, self._on_paint)
+ self.Bind(wx.EVT_SIZE, self._on_size)
+ self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
+
+ def set_use_persistence(self,enable):
+ self.use_persistence=enable
+ self.clear_accum=True
+
+ def set_persist_alpha(self,analog_alpha):
+ self.persist_alpha=analog_alpha
+
+ def new_gl_cache(self, draw_fcn, draw_pri=50):
+ """
+ Create a new gl cache.
+ Register its draw and init function.
+ @return the new cache object
+ """
+ cache = gl_cache(draw_fcn)
+ self.register_init(cache.init)
+ self.register_draw(cache.draw, draw_pri)
+ self._gl_caches.append(cache)
+ return cache
+
+ def register_init(self, init_fcn):
+ self._init_fcns.append(init_fcn)
+
+ def register_draw(self, draw_fcn, draw_pri=50):
+ """
+ Register a draw function with a layer priority.
+ Large pri values are drawn last.
+ Small pri values are drawn first.
+ """
+ for i in range(len(self._draw_fcns)):
+ if draw_pri < self._draw_fcns[i][0]:
+ self._draw_fcns.insert(i, (draw_pri, draw_fcn))
+ return
+ self._draw_fcns.append((draw_pri, draw_fcn))
+
+ def _on_size(self, event):
+ """
+ Flag the resize event.
+ The paint event will handle the actual resizing.
+ """
+ self.lock()
+ self._resized_flag = True
+ self.clear_accum=True
+ self.unlock()
+
+ def _on_paint(self, event):
+ """
+ Respond to paint events.
+ Initialize GL if this is the first paint event.
+ Resize the view port if the width or height changed.
+ Redraw the screen, calling the draw functions.
+ """
+ if not self.IsShownOnScreen(): # Cannot realise a GL context on OS X if window is not yet shown
+ return
+ # create device context (needed on Windows, noop on X)
+ dc = None
+ if event.GetEventObject(): # Only create DC if paint triggered by WM message (for OS X)
+ dc = wx.PaintDC(self)
+ self.lock()
+ self.SetCurrent(self._gl_ctx) # Real the explicit GL context
+
+ # check if gl was initialized
+ if not self._gl_init_flag:
+ GL.glClearColor(*BACKGROUND_COLOR_SPEC)
+ for fcn in self._init_fcns: fcn()
+ self._gl_init_flag = True
+
+ # check for a change in window size
+ if self._resized_flag:
+ self.width, self.height = self.GetSize()
+ GL.glMatrixMode(GL.GL_PROJECTION)
+ GL.glLoadIdentity()
+ GL.glOrtho(0, self.width, self.height, 0, 1, 0)
+ GL.glMatrixMode(GL.GL_MODELVIEW)
+ GL.glLoadIdentity()
+ GL.glViewport(0, 0, self.width, self.height)
+ for cache in self._gl_caches: cache.changed(True)
+ self._resized_flag = False
+
+ # clear buffer if needed
+ if self.clear_accum or not self.use_persistence:
+ GL.glClear(GL.GL_COLOR_BUFFER_BIT)
+ self.clear_accum=False
+
+ # apply fading
+ if self.use_persistence:
+ GL.glEnable(GL.GL_BLEND)
+ GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
+
+ GL.glBegin(GL.GL_QUADS)
+ GL.glColor4f(1,1,1,self.persist_alpha)
+ GL.glVertex2f(0, self.height)
+ GL.glVertex2f(self.width, self.height)
+ GL.glVertex2f(self.width, 0)
+ GL.glVertex2f(0, 0)
+ GL.glEnd()
+
+ GL.glDisable(GL.GL_BLEND)
+
+ # draw functions
+ for fcn in self._draw_fcns: fcn[1]()
+
+ # show result
+ self.SwapBuffers()
+ self.unlock()
+
+ def update(self):
+ """
+ Force a paint event.
+ """
+ if not self._gl_init_flag: return
+ wx.PostEvent(self, wx.PaintEvent())