Logo Search packages:      
Sourcecode: baycomusb version File versions  Download package

signalhist.c

/* 
 * Signal History Widget
 * Copyright (C) 2000 Thomas Sailer <sailer@ife.ee.ethz.ch>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "signalhist.h"
#include <gtk/gtkgc.h>
#include <gtk/gtkmain.h>
#include <math.h>

#include <stdio.h>
#include <string.h>

/* --------------------------------------------------------------------- */

#define PRIO G_PRIORITY_LOW

static void signalhistory_class_init(SignalhistoryClass *klass);
static void signalhistory_init(Signalhistory *signalhistory);
static void signalhistory_finalize(GtkObject *object);
static gint signalhistory_expose(GtkWidget *widget, GdkEventExpose *event);
static void signalhistory_realize(GtkWidget *widget);
static void signalhistory_unrealize(GtkWidget *widget);
static void signalhistory_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
static void signalhistory_send_configure (Signalhistory *signalhistory);
static gint idle_callback(gpointer data);

static GtkWidgetClass *parent_class = NULL;
static SignalhistoryClass *signalhistory_class = NULL;


guint signalhistory_get_type(void)
{
      static guint signalhistory_type = 0;

      if (!signalhistory_type)
      {
            static const GtkTypeInfo signalhistory_info =
            {
                  "Signalhistory",
                  sizeof(Signalhistory),
                  sizeof(SignalhistoryClass),
                  (GtkClassInitFunc)signalhistory_class_init,
                  (GtkObjectInitFunc)signalhistory_init,
                  /* reserved_1 */ NULL,
                  /* reserved_2 */ NULL,
                  (GtkClassInitFunc)NULL,
            };
            signalhistory_type = gtk_type_unique(gtk_widget_get_type(), &signalhistory_info);
      }
      return signalhistory_type;
}

static void signalhistory_class_init(SignalhistoryClass *klass)
{
      GtkObjectClass *object_class;
      GtkWidgetClass *widget_class;

      object_class = (GtkObjectClass*)klass;
      widget_class = (GtkWidgetClass*)klass;

      parent_class = gtk_type_class(gtk_widget_get_type());
      signalhistory_class = klass;

      object_class->finalize = signalhistory_finalize;
      widget_class->expose_event = signalhistory_expose;
      widget_class->realize = signalhistory_realize;
      widget_class->unrealize = signalhistory_unrealize;
      widget_class->size_allocate = signalhistory_size_allocate;
}

static void signalhistory_init(Signalhistory *signalhistory)
{
      signalhistory->idlefunc = 0;
      /* initialize the colors */
      signalhistory->col0.red = 39322;
      signalhistory->col0.green = 60948;
      signalhistory->col0.blue = 39322;
      signalhistory->col1.red = 3277;
      signalhistory->col1.green = 60948;
      signalhistory->col1.blue = 0;
      signalhistory->col2.red = 65535;
      signalhistory->col2.green = 15073;
      signalhistory->col2.blue = 0;
      signalhistory->col0_gc = signalhistory->col1_gc = signalhistory->col2_gc = NULL;
      signalhistory->pixmap = NULL;
      /* initialize the data */
      memset(&signalhistory->data, 0, sizeof(signalhistory->data));
      signalhistory->ptr = 0;
}

static void signalhistory_realize(GtkWidget *widget)
{
      Signalhistory *signalhistory;
      GdkWindowAttr attributes;
      gint attributes_mask;
      GdkGCValues gc_values;

      g_return_if_fail(widget != NULL);
      g_return_if_fail(IS_SIGNALHISTORY(widget));

      signalhistory = SIGNALHISTORY(widget);
      GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);

      attributes.window_type = GDK_WINDOW_CHILD;
      attributes.x = widget->allocation.x;
      attributes.y = widget->allocation.y;
      attributes.width = widget->allocation.width;
      attributes.height = widget->allocation.height;
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.visual = gtk_widget_get_visual(widget);
      attributes.colormap = gtk_widget_get_colormap(widget);
      attributes.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;

      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

      widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributes_mask);
      gdk_window_set_user_data(widget->window, signalhistory);

      widget->style = gtk_style_attach(widget->style, widget->window);
      gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);

      /* gc's if necessary */
      if (!gdk_color_alloc(widget->style->colormap, &signalhistory->col0))
            g_warning("unable to allocate color: ( %d %d %d )", signalhistory->col0.red, signalhistory->col0.green, signalhistory->col0.blue);
      gc_values.foreground = signalhistory->col0;
      signalhistory->col0_gc = gtk_gc_get(widget->style->depth, widget->style->colormap, &gc_values, GDK_GC_FOREGROUND);
      if (!gdk_color_alloc(widget->style->colormap, &signalhistory->col1))
            g_warning("unable to allocate color: ( %d %d %d )", signalhistory->col1.red, signalhistory->col1.green, signalhistory->col1.blue);
      gc_values.foreground = signalhistory->col1;
      signalhistory->col1_gc = gtk_gc_get(widget->style->depth, widget->style->colormap, &gc_values, GDK_GC_FOREGROUND);
      if (!gdk_color_alloc(widget->style->colormap, &signalhistory->col2))
            g_warning("unable to allocate color: ( %d %d %d )", signalhistory->col2.red, signalhistory->col2.green, signalhistory->col2.blue);
      gc_values.foreground = signalhistory->col2;
      signalhistory->col2_gc = gtk_gc_get(widget->style->depth, widget->style->colormap, &gc_values, GDK_GC_FOREGROUND);
      /* create backing store */
      signalhistory->pixmap = gdk_pixmap_new(widget->window, SIGNALHISTORY_WIDTH, SIGNALHISTORY_HEIGHT, -1);

      signalhistory_send_configure(SIGNALHISTORY(widget));
}

static void signalhistory_unrealize(GtkWidget *widget)
{
      Signalhistory *signalhistory;

      g_return_if_fail(widget != NULL);
      g_return_if_fail(IS_SIGNALHISTORY(widget));

      signalhistory = SIGNALHISTORY(widget);
      if (signalhistory->idlefunc)
            gtk_idle_remove(signalhistory->idlefunc);
      if (signalhistory->col0_gc)
            gtk_gc_release(signalhistory->col0_gc);
      if (signalhistory->col1_gc)
            gtk_gc_release(signalhistory->col1_gc);
      if (signalhistory->col2_gc)
            gtk_gc_release(signalhistory->col2_gc);
      signalhistory->col0_gc = signalhistory->col1_gc = signalhistory->col2_gc = NULL;
      if (signalhistory->pixmap)
                  gdk_pixmap_unref(signalhistory->pixmap);
      signalhistory->pixmap = NULL;
      if (GTK_WIDGET_CLASS(parent_class)->unrealize)
            (*GTK_WIDGET_CLASS(parent_class)->unrealize)(widget);
}

static void signalhistory_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
{
      g_return_if_fail(widget != NULL);
      g_return_if_fail(IS_SIGNALHISTORY(widget));
      g_return_if_fail(allocation != NULL);
      
      widget->allocation = *allocation;
      widget->allocation.width = SIGNALHISTORY_WIDTH;
      widget->allocation.height = SIGNALHISTORY_HEIGHT;

      if (GTK_WIDGET_REALIZED(widget)) {
            gdk_window_move_resize (widget->window,
                              allocation->x, allocation->y,
                              allocation->width, allocation->height);
            signalhistory_send_configure(SIGNALHISTORY(widget));
      }
}

static void signalhistory_send_configure(Signalhistory *signalhistory)
{
      GtkWidget *widget;
      GdkEventConfigure event;

      widget = GTK_WIDGET(signalhistory);

      event.type = GDK_CONFIGURE;
      event.window = widget->window;
      event.send_event = TRUE;
      event.x = widget->allocation.x;
      event.y = widget->allocation.y;
      event.width = widget->allocation.width;
      event.height = widget->allocation.height;
  
      gtk_widget_event(widget, (GdkEvent*)&event);
}


GtkWidget* signalhistory_new(gchar *name, gchar *string1, gchar *string2, gint int1, gint int2)
{
      Signalhistory *signalhistory;
      
      signalhistory = gtk_type_new(signalhistory_get_type());
      memset(&signalhistory->data, 0, sizeof(signalhistory->data));
      signalhistory->ptr = 0;
      return GTK_WIDGET(signalhistory);
}

static void signalhistory_finalize(GtkObject *object)
{
      g_return_if_fail(object != NULL);
      g_return_if_fail(IS_SIGNALHISTORY(object));
      (*GTK_OBJECT_CLASS(parent_class)->finalize)(object);
}

static gint signalhistory_expose(GtkWidget *widget, GdkEventExpose *event)
{
      Signalhistory *signalhistory;

      g_return_val_if_fail(widget != NULL, FALSE);
      g_return_val_if_fail(IS_SIGNALHISTORY(widget), FALSE);
      g_return_val_if_fail (event != NULL, FALSE);
      if (GTK_WIDGET_DRAWABLE(widget)) {
            signalhistory = SIGNALHISTORY(widget);
            if (!signalhistory->idlefunc)
                  signalhistory->idlefunc = gtk_idle_add_priority(PRIO, idle_callback, signalhistory);
      }
      return FALSE;
}

static void draw(Signalhistory *signalhistory)
{
      guint i, j, ptr;
      GdkPoint pt[SIGNALHISTORY_WIDTH+1];
      GtkWidget *widget;
      unsigned char col;

      widget = GTK_WIDGET(signalhistory);
      g_return_if_fail(GTK_WIDGET_DRAWABLE(widget));
      g_return_if_fail(signalhistory->pixmap);
      /* clear window */
      gdk_draw_rectangle(signalhistory->pixmap, widget->style->base_gc[widget->state],
                     TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
      /* draw data points */
      ptr = signalhistory->ptr;
      for (i = 0; i < SIGNALHISTORY_WIDTH; ) {
            col = signalhistory->data[ptr].col;
            for (j = 0; i < SIGNALHISTORY_WIDTH;) {
                  pt[j].x = i;
                  pt[j].y = ((255-signalhistory->data[ptr].sample)*SIGNALHISTORY_HEIGHT) >> 8;
                  j++;
                  if (col != signalhistory->data[ptr].col)
                        break;
                  i++;
                  ptr = (ptr + 1) % SIGNALHISTORY_WIDTH;
            }
            gdk_draw_lines(signalhistory->pixmap, (col == 0) ? signalhistory->col0_gc : ((col == 1) ? signalhistory->col1_gc : signalhistory->col2_gc), pt, j);
      }
      /* draw to screen */
      gdk_draw_pixmap(widget->window, widget->style->base_gc[widget->state], signalhistory->pixmap, 
                  0, 0, 0, 0, widget->allocation.width, widget->allocation.height);
}

static gint idle_callback(gpointer data)
{
      g_return_val_if_fail(data != NULL, FALSE);
      g_return_val_if_fail(IS_SIGNALHISTORY(data), FALSE);
      SIGNALHISTORY(data)->idlefunc = 0;
      if (!GTK_WIDGET_DRAWABLE(GTK_WIDGET(data)))
            return FALSE;
      draw(SIGNALHISTORY(data));
      return FALSE;  /* don't call this callback again */
}

void signalhistory_newdata(Signalhistory *signalhistory, unsigned char sample, unsigned char col)
{
      g_return_if_fail(signalhistory != NULL);
      g_return_if_fail(IS_SIGNALHISTORY(signalhistory));
      signalhistory->data[signalhistory->ptr].sample = sample;
      signalhistory->data[signalhistory->ptr].col = col;
      signalhistory->ptr = (signalhistory->ptr + 1) % SIGNALHISTORY_WIDTH;
      if (GTK_WIDGET_DRAWABLE(GTK_WIDGET(signalhistory))) {
            if (!signalhistory->idlefunc)
                  signalhistory->idlefunc = gtk_idle_add_priority(PRIO, idle_callback, signalhistory);
      }
}

Generated by  Doxygen 1.6.0   Back to index