keyspan.c

来自「A GTK sound font editor. Sound font file」· C语言 代码 · 共 468 行

C
468
字号
/*================================================================== * keyspan.c - Keyspan widget * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * This program 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 2 * of the License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include <stdio.h>#include <gtk/gtkmain.h>#include <gtk/gtksignal.h>#include "keyspan.h"/* Forward declarations */static void keyspan_class_init (KeySpanClass * klass);static void keyspan_init (KeySpan * keyspan);static void keyspan_destroy (GtkObject * object);static void keyspan_realize (GtkWidget * widget);static void keyspan_size_request (GtkWidget * widget,  GtkRequisition * requisition);static void keyspan_size_allocate (GtkWidget * widget,  GtkAllocation * allocation);static gint keyspan_expose (GtkWidget * widget, GdkEventExpose * event);static gint keyspan_button_press (GtkWidget * widget, GdkEventButton * event);static gint keyspan_button_release (GtkWidget * widget,  GdkEventButton * event);static gint keyspan_motion_notify (GtkWidget * widget,  GdkEventMotion * event);static void keyspan_update_mouse (KeySpan * keyspan, gint x);/* Local data */static struct{				/* key pixel offsets for one octave */  guint8 selx;			/* pixel offset to first pixel of select range */  guint8 dispx;			/* pixel offset to first pixel of key */  gboolean white;		/* TRUE if key is white, FALSE if black */}keyinfo[12] = { {6, 2, TRUE}, {11, 7, FALSE}, {15, 11, TRUE}, {20, 16, FALSE},  {26, 20, TRUE}, {33, 29, TRUE}, {38, 34, FALSE}, {42, 38, TRUE},  {47, 43, FALSE}, {51, 47, TRUE}, {56, 52, FALSE}, {62, 56, TRUE}};enum{  SPAN_CHANGE,			/* span change signal */  SPAN_LAST			/* place holder for last enum */};static gint keyspan_signals[SPAN_LAST] = { 0 };static GtkWidgetClass *parent_class = NULL;guintkeyspan_get_type (void){  static guint keyspan_type = 0;  if (!keyspan_type)    {      GtkTypeInfo keyspan_info = {	"KeySpan",	sizeof (KeySpan),	sizeof (KeySpanClass),	(GtkClassInitFunc) keyspan_class_init,	(GtkObjectInitFunc) keyspan_init,	(GtkArgSetFunc) NULL,	(GtkArgGetFunc) NULL,      };      keyspan_type = gtk_type_unique (gtk_widget_get_type (), &keyspan_info);    }  return keyspan_type;}static voidkeyspan_class_init (KeySpanClass * class){  GtkObjectClass *object_class;  GtkWidgetClass *widget_class;  object_class = (GtkObjectClass *) class;  widget_class = (GtkWidgetClass *) class;  parent_class = gtk_type_class (gtk_widget_get_type ());  keyspan_signals[SPAN_CHANGE] = gtk_signal_new ("span_change",    GTK_RUN_FIRST, object_class->type,    GTK_SIGNAL_OFFSET (KeySpanClass, span_change),    gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0);  gtk_object_class_add_signals (object_class, keyspan_signals, SPAN_LAST);  class->span_change = NULL;  object_class->destroy = keyspan_destroy;  widget_class->realize = keyspan_realize;  widget_class->expose_event = keyspan_expose;  widget_class->size_request = keyspan_size_request;  widget_class->size_allocate = keyspan_size_allocate;  widget_class->button_press_event = keyspan_button_press;  widget_class->button_release_event = keyspan_button_release;  widget_class->motion_notify_event = keyspan_motion_notify;}static voidkeyspan_init (KeySpan * keyspan){  keyspan->lokey = 0;  keyspan->hikey = 0;  keyspan->selected = 0;  keyspan->mode = KEYSPAN_KEYMODE;}GtkWidget *keyspan_new (void){  KeySpan *keyspan;  keyspan = gtk_type_new (keyspan_get_type ());  return GTK_WIDGET (keyspan);}voidkeyspan_set_span (KeySpan * keyspan, guint8 lokey, guint8 hikey){  g_return_if_fail (keyspan != NULL);  g_return_if_fail (IS_KEYSPAN (keyspan));  keyspan->lokey = lokey;  keyspan->hikey = hikey;  gtk_widget_draw (GTK_WIDGET (keyspan), NULL);}voidkeyspan_set_mode (KeySpan * keyspan, gint mode){  g_return_if_fail (keyspan != NULL);  g_return_if_fail (IS_KEYSPAN (keyspan));  g_return_if_fail (mode == KEYSPAN_KEYMODE || mode == KEYSPAN_VELMODE);  keyspan->mode = mode;}static voidkeyspan_destroy (GtkObject * object){  KeySpan *keyspan;  g_return_if_fail (object != NULL);  g_return_if_fail (IS_KEYSPAN (object));  keyspan = KEYSPAN (object);  if (GTK_OBJECT_CLASS (parent_class)->destroy)    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);}static voidkeyspan_realize (GtkWidget * widget){  KeySpan *keyspan;  GdkWindowAttr attributes;  gint attributes_mask;  g_return_if_fail (widget != NULL);  g_return_if_fail (IS_KEYSPAN (widget));  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);  keyspan = KEYSPAN (widget);  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.window_type = GDK_WINDOW_CHILD;  attributes.event_mask = gtk_widget_get_events (widget) |    GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |    GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |    GDK_POINTER_MOTION_HINT_MASK;  attributes.visual = gtk_widget_get_visual (widget);  attributes.colormap = gtk_widget_get_colormap (widget);  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;  widget->window = gdk_window_new (widget->parent->window, &attributes,    attributes_mask);  gdk_window_set_user_data (widget->window, widget);  widget->style = gtk_style_attach (widget->style, widget->window);  gdk_window_set_background (widget->window,    &widget->style->bg[GTK_STATE_NORMAL]);}static voidkeyspan_size_request (GtkWidget * widget, GtkRequisition * requisition){  requisition->width = KEYSPAN_DEFAULT_SIZEX;  requisition->height = KEYSPAN_DEFAULT_SIZEY;}static voidkeyspan_size_allocate (GtkWidget * widget, GtkAllocation * allocation){  KeySpan *keyspan;  g_return_if_fail (widget != NULL);  g_return_if_fail (IS_KEYSPAN (widget));  g_return_if_fail (allocation != NULL);  widget->allocation = *allocation;  keyspan = KEYSPAN (widget);  if (GTK_WIDGET_REALIZED (widget))    {      gdk_window_move_resize (widget->window, allocation->x, allocation->y,	allocation->width, allocation->height);    }}static gintkeyspan_expose (GtkWidget * widget, GdkEventExpose * event){  KeySpan *keyspan;  gint lox, hix;  GdkGC *fg_gc, *bg_gc;  g_return_val_if_fail (widget != NULL, FALSE);  g_return_val_if_fail (IS_KEYSPAN (widget), FALSE);  g_return_val_if_fail (event != NULL, FALSE);  if (event->count > 0)    return FALSE;  keyspan = KEYSPAN (widget);  fg_gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];  bg_gc = widget->style->bg_gc[GTK_WIDGET_STATE (widget)];  gdk_draw_rectangle (widget->window, bg_gc, TRUE, 0, 0,    widget->allocation.width, widget->allocation.height);  if (keyspan->mode == KEYSPAN_KEYMODE)    lox = keyspan->lokey / 12 * 63 + keyinfo[keyspan->lokey % 12].dispx;  else    lox = keyspan->lokey * (KEYSPAN_DEFAULT_SIZEX - 8) / 127 + 2;  if (keyspan->hikey > keyspan->lokey)    {      if (keyspan->mode == KEYSPAN_KEYMODE)	hix = keyspan->hikey / 12 * 63 + keyinfo[keyspan->hikey % 12].dispx;      else	hix = keyspan->hikey * (KEYSPAN_DEFAULT_SIZEX - 8) / 127 + 2;      gdk_draw_line (widget->window, fg_gc, lox + 5, 7, hix - 1, 7);      gdk_draw_rectangle (widget->window, fg_gc, TRUE, hix, 2, 5, 12);      if (keyinfo[keyspan->hikey % 12].white	|| keyspan->mode == KEYSPAN_VELMODE)	gdk_draw_rectangle (widget->window, bg_gc, TRUE, hix + 1, 3, 3, 10);    }  gdk_draw_rectangle (widget->window, fg_gc, TRUE, lox, 2, 5, 12);  if (keyinfo[keyspan->lokey % 12].white || keyspan->mode == KEYSPAN_VELMODE)    gdk_draw_rectangle (widget->window, bg_gc, TRUE, lox + 1, 3, 3, 10);  return FALSE;}static gintkeyspan_button_press (GtkWidget * widget, GdkEventButton * event){  KeySpan *keyspan;  gint x, y, xval;  g_return_val_if_fail (widget != NULL, FALSE);  g_return_val_if_fail (IS_KEYSPAN (widget), FALSE);  g_return_val_if_fail (event != NULL, FALSE);  keyspan = KEYSPAN (widget);  if (keyspan->selected != 0)    return (FALSE);		/* A button is already active */  if (event->button == 2)    {				/* middle mouse button maximizes span */      keyspan->lokey = 0;      keyspan->hikey = 127;      gtk_widget_draw (GTK_WIDGET (keyspan), NULL);      gtk_signal_emit (GTK_OBJECT (keyspan), keyspan_signals[SPAN_CHANGE]);      return (FALSE);    }  if (event->button != 1)    return (FALSE);  x = CLAMP (event->x, 0, 675);  y = event->y;  /* select keyspan if it hasn't been already */  if (GTK_WIDGET_STATE (GTK_WIDGET (keyspan)) != GTK_STATE_SELECTED)    gtk_widget_set_state (GTK_WIDGET (keyspan), GTK_STATE_SELECTED);  if (y >= 2 && y <= 13)    {      if (keyspan->mode == KEYSPAN_KEYMODE)	xval = keyspan->lokey / 12 * 63 + keyinfo[keyspan->lokey % 12].dispx;      else	xval = keyspan->lokey * (KEYSPAN_DEFAULT_SIZEX - 8) / 127 + 2;      if ((x >= xval) && (x < xval + 5))	keyspan->selected = 1;      else	{	  if (keyspan->mode == KEYSPAN_KEYMODE)	    xval =	      keyspan->hikey / 12 * 63 + keyinfo[keyspan->hikey % 12].dispx;	  else	    xval = keyspan->hikey * (KEYSPAN_DEFAULT_SIZEX - 8) / 127 + 2;	  if ((x >= xval) && (x < xval + 5))	    keyspan->selected = 2;	}    }  if (keyspan->selected)    gtk_grab_add (widget);  return (FALSE);}static gintkeyspan_button_release (GtkWidget * widget, GdkEventButton * event){  KeySpan *keyspan;  g_return_val_if_fail (widget != NULL, FALSE);  g_return_val_if_fail (IS_KEYSPAN (widget), FALSE);  g_return_val_if_fail (event != NULL, FALSE);  keyspan = KEYSPAN (widget);  if (event->button == 1)    {      gtk_grab_remove (widget);      keyspan->selected = 0;      gtk_signal_emit (GTK_OBJECT (keyspan), keyspan_signals[SPAN_CHANGE]);    }  return FALSE;}static gintkeyspan_motion_notify (GtkWidget * widget, GdkEventMotion * event){  KeySpan *keyspan;  GdkModifierType mods;  gint x, y;  g_return_val_if_fail (widget != NULL, FALSE);  g_return_val_if_fail (IS_KEYSPAN (widget), FALSE);  g_return_val_if_fail (event != NULL, FALSE);  keyspan = KEYSPAN (widget);  if (keyspan->selected)    {      x = event->x;      y = event->y;      if (event->is_hint || (event->window != widget->window))	gdk_window_get_pointer (widget->window, &x, &y, &mods);      if (mods & GDK_BUTTON1_MASK)	keyspan_update_mouse (keyspan, x);    }  return FALSE;}static voidkeyspan_update_mouse (KeySpan * keyspan, gint x){  gint i;  gint xval;  guint8 keynum;  g_return_if_fail (keyspan != NULL);  g_return_if_fail (IS_KEYSPAN (keyspan));  if (keyspan->selected == 0)    return;  if (x > 672)    x = 672;  else if (x < 0)    x = 0;  if (keyspan->mode == KEYSPAN_KEYMODE)    {      xval = x % 63;		/* pixel offset into keyboard octave */      for (i = 0; i < 12; i++)	{			/* loop through key selection offsets */	  if (xval <= keyinfo[i].selx)	    {			/* is offset within key selection area? */	      keynum = x / 63 * 12 + i;	/* calc key number */	      break;	    }	}    }  else    keynum = x * 127 / 672;  if (keyspan->selected == 1)    {				/* lokey? */      if (keynum == keyspan->lokey)	return;      if (keynum <= keyspan->hikey)	{			/* Is lokey selected keynum <= hikey? */	  keyspan->lokey = keynum;	}      else	{			/* lokey > hikey so swap selection */	  keyspan->lokey = keyspan->hikey;	  keyspan->hikey = keynum;	  keyspan->selected = 2;	}    }  else    {      if (keynum == keyspan->hikey)	return;      if (keynum >= keyspan->lokey)	{			/* Is hikey selected keynum >= hikey? */	  keyspan->hikey = keynum;	}      else	{			/* hikey < lokey so swap selection */	  keyspan->hikey = keyspan->lokey;	  keyspan->lokey = keynum;	  keyspan->selected = 1;	}    }  gtk_widget_draw (GTK_WIDGET (keyspan), NULL);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?