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 + -
显示快捷键?