Ver Mensaje Individual
  #6 (permalink)  
Antiguo 09/12/2002, 15:07
Avatar de epplestun
epplestun
 
Fecha de Ingreso: octubre-2001
Mensajes: 1.621
Antigüedad: 23 años, 6 meses
Puntos: 5
Código:
/*
 * Archivo: GtkGraph.c
 * Autor: IvanRodriguez
 *
 * Widget de grafica gtk sencillo
 */
 
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include "gtkgraph.h"

static GtkWidgetClass *parent_class = NULL;

/*
 * Declaraciones anticipadas
 */
static void gtk_graph_class_init (GtkGraphClass *class);
static void gtk_graph_init (GtkGraph *graph);
static void gtk_graph_realize (GtkWidget *widget);
static void gtk_graph_draw (GtkWidget *widget, GdkRectangle *area);
static void gtk_graph_size_request (GtkWidget *widget, GtkRequisition *req);
static gint gtk_graph_expose (GtkWidget *widget, GdkEventExpose *event);
static void gtk_graph_destroy (GtkObject *object);

/*
 * gtk_grapth_get_type
 *
 * Clase interna. Utilizada para definir la clase GtkGraph ante GTK+
 */
guint gtk_graph_get_type (void)
{
	static guint graph_type = 0;
	
		/* Si no esta creada todavia */
		if(!graph_type)
		{
			/* Crear un objeto graph_info */
			GtkTypeInfo graph_info = 
			{
				"GtkGraph",
				sizeof (GtkGraph),
				sizeof (GtkGraphClass),
				(GtkClassInitFunc) gtk_graph_class_init,
				(GtkObjectInitFunc) gtk_graph_init,
				(GtkArgSetFunc) NULL,
				(GtkArgGetFunc) NULL,
			};
			
			/* Informar a GTK+ de su existencia · Obtener identificador univoco */
			graph_type = gtk_type_unique (gtk_widget_get_type(), &graph_info);
		}
		return graph_type;
}
/*
 * gtk_graph_class_init
 *
 * Sustituir todos los metodos de la clase que sea necesario
 * para que la clase de la grafica se comporte adecuadamene.
 * Aqui se sustituyen las funciones que hacen que se realize
 * el dibujo.
 *
 * class - Clase de definicion del objeto
 */
static void gtk_graph_class_init (GtkGraphClass *class)
{
	GtkObjectClass *object_class;
	GtkWidgetClass *widget_class;
	
	/* Obtener la clase del widget */
	object_class = (GtkObjectClass *) class;
	widget_class = (GtkWidgetClass *) class;
	parent_class = gtk_type_class (gtk_widget_get_type());
	
	/* Sustituir destruccion del objeto */
	object_class->destroy = gtk_graph_destroy;
	
	/* sustituir destruccion del objeto */
	widget_class->realize = gtk_graph_realize;
	widget_class->draw = gtk_graph_draw;
	widget_class->size_request = gtk_graph_size_request;
	widget_class->expose_event = gtk_graph_expose;
}

/*
 * gtk_graph_init
 *
 * se invoca cada vez que se crea un nuevo elemento de grafica.
 * Inicializa los campos de nuestra estructura.
 */
static void gtk_graph_init (GtkGraph *graph)
{
	GtkWidget *widget;
	
	widget = (GtkWidget *) graph;
	
	/* Valores iniciales */
	graph->values = NULL;
	graph->num_values = 0;
}

/*
 * gtk_graph_new
 *
 * Crea un nuevo elemento GtkGraph
 */
GtkWidget* gtk_graph_new (void)
{
	return gtk_type_new (gtk_graph_get_type());
}

/*
 * gtk_graph_realize
 *
 * Asociar el widget con una ventana X Window.
 *
 */
static void gtk_graph_realize (GtkWidget *widget)
{
	GtkGraph *darea;
	GdkWindowAttr attributes;
	gint attributes_mask;
	
	/* Comprobar errores */
	g_return_if_fail (widget != NULL);
	g_return_if_fail (GTK_IS_GRAPH (widget));
	
	darea = GTK_GRAPH (widget);
	GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
	
	/* Atributos para crear la ventana */
	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;
	
	/* Estamos pasando valores x, y, visual y colormap */
	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
	
	/* Crear la ventana */
	widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
	gdk_window_set_user_data (widget->window, darea);
	
	widget->style = gtk_style_attach (widget->style, widget->window);
	gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}

/*
 * gtk_graph_size
 *
 * Metodo personalizado para establecer el tamañano de la grafica
 */
void gtk_graph_size (GtkGraph *graph, int size)
{
	g_return_if_fail (graph != NULL);
	g_return_if_fail (GTK_IS_GRAPH (graph));
	
	graph->num_values = size;
	graph->values = g_realloc (graph->values, sizeof (gint) *size);
}

/*
 * gtk_graph_set_value
 *
 * Metodo personalizado para establecer el tamaño
 */
void gtk_graph_set_value (GtkGraph *graph, int index, int value)
{
	g_return_if_fail (graph != NULL);
	g_return_if_fail (GTK_IS_GRAPH (graph));
	g_return_if_fail (index < graph->num_values && index >=0);
	
	graph->values[index] = value;
}

/*
 * gtk_graph_draw
 *
 * Dibujar el widget, basandose en el numero de valores graficos del grafico de barras
 */
static void gtk_graph_draw (GtkWidget *widget, GdkRectangle *area)
{
	GtkGraph *graph;
	int width;
	int height;
	int column_width;
	int max = 0;
	int i;
	int bar_height;
	
	/* Comprobar existencia de problemas obvios */
	g_return_if_fail (widget != NULL);
	g_return_if_fail (GTK_IS_GRAPH (widget));
	
	/* Asegurarse de que es un widget dibujable */
	if (GTK_WIDGET_DRAWABLE (widget))
	{
		graph = GTK_GRAPH (widget);
		if (graph->num_values == 0)
		{
			return;
		}
		
		/* Obtener altura y anchura */
		width = widget->allocation.width -1;
		height = widget->allocation.height -1;
		
		/* Calcular anchura de las columnas */
		column_width = width / graph->num_values;
		
		/* Encontrar valor maximo */
		for (i = 0; i < graph->num_values; i++)
		{
			if (max < graph->values[i])
			{
				max = graph->values[i];
			}
		}
		
		for (i = 0; i < graph->num_values; i++)
		{
			bar_height = (graph->values[i] * height) / max;
			
			gdk_draw_rectangle (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], TRUE, (i * column_width), height - bar_height, (column_width-2), bar_height);
		}
	}
}

/*
 * gtk_graph_size_request
 *
 * ¿de que tamaño debe ser el widget?
 * Puede modificarse
 */
static void gtk_graph_size_request (GtkWidget *widget, GtkRequisition *req)
{
	req->width = 100;
	req->height = 100;
}

/*
 * gtk_graph_expose
 *
 * El widget de grafica ha quedado expuesto y debe redibujarse
 */
static gint gtk_graph_expose (GtkWidget *widget, GdkEventExpose *event)
{
	GtkGraph *graph;
	
	/* Realizar comprobacion de errores */
	g_return_val_if_fail (widget != NULL, FALSE);
	g_return_val_if_fail (GTK_IS_GRAPH (widget), FALSE);
	g_return_val_if_fail (event != NULL, FALSE);
	
	if (event->count > 0)
	{
		return (FALSE);
	}
	
	/* Obtener el widget de grafica */
	graph = GTK_GRAPH (widget);
	
	/* Borrar la ventana */
	gdk_window_clear_area (widget->window, 0, 0, widget->allocation.width, widget->allocation.height);
	
	/* Dibujar la grafica */
	gtk_graph_draw (widget, NULL);
	
	return(FALSE);
}

/*
 * gtk_graph_destroy
 *
 * Destruir el widget y liberar la memoria asiganada.
 * Despues, invocar funcion de destruccion del padre,
 * para asegurarse de que libera la memoria asignada
 * por este.
 */
static void gtk_graph_destroy (GtkObject *object)
{
	GtkGraph *graph;
	
	/* Comprobar tipo */
	g_return_if_fail (object != NULL);
	g_return_if_fail (GTK_IS_GRAPH (object));
	
	/* Convertir en objeto de grafica */
	graph = GTK_GRAPH (object);
	
	/* Liberar memoria */
	g_free (graph->values);
	
	/* Invocar destruccion del padre */
	GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
__________________
Usuario registrado de Linux #288725