📄 ptrstrip.c
字号:
/*================================================================== * ptrstrip.c - pointer strip 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 "ptrstrip.h"#define XPM_POINTER_WIDTH 11#define XPM_POINTER_HEIGHT 7const char *xpm_pointer[] = { /* yes GIMP rocks (outputs C data XPM!) */ "11 7 3 1", " c None", ". c #FFFFFF", "+ c #000000", "+++++++++++", "+.........+", " +.......+ ", " +.....+ ", " +...+ ", " +.+ ", " + "};#define PTRSTRIP_DEFAULT_SIZEX 50#define PTRSTRIP_DEFAULT_SIZEY XPM_POINTER_HEIGHTenum{ POINTER_CHANGE, POINTER_SELECT, POINTER_UNSELECT, DUMMY_SIGNAL /* used to count signals */};static GtkWidgetClass *parent_class = NULL;static gint ptrstrip_signals[DUMMY_SIGNAL] = { 0 };/* Forward declarations */static void ptrstrip_class_init (PtrStripClass * klass);static void ptrstrip_init (PtrStrip * ptrstrip);static void ptrstrip_destroy (GtkObject * object);static void ptrstrip_size_request (GtkWidget * widget, GtkRequisition * requisition);static void ptrstrip_size_allocate (GtkWidget * widget, GtkAllocation * allocation);static void ptrstrip_realize (GtkWidget * widget);static gint ptrstrip_expose (GtkWidget * widget, GdkEventExpose * event);static void ptrstrip_pointer_changed (PtrStrip * ptrstrip, guint ptrndx);static gint ptrstrip_button_press (GtkWidget * widget, GdkEventButton * event);static gint ptrstrip_button_release (GtkWidget * widget, GdkEventButton * event);static gint ptrstrip_motion_notify (GtkWidget * widget, GdkEventMotion * event);guintptrstrip_get_type (void){ static guint ptrstrip_type = 0; if (!ptrstrip_type) { GtkTypeInfo ptrstrip_info = { "PtrStrip", sizeof (PtrStrip), sizeof (PtrStripClass), (GtkClassInitFunc) ptrstrip_class_init, (GtkObjectInitFunc) ptrstrip_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL, }; ptrstrip_type = gtk_type_unique (gtk_widget_get_type (), &ptrstrip_info); } return ptrstrip_type;}static voidptrstrip_class_init (PtrStripClass * klass){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; parent_class = gtk_type_class (gtk_widget_get_type ()); ptrstrip_signals[POINTER_CHANGE] = gtk_signal_new ("pointer_change", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (PtrStripClass, pointer_change), gtk_marshal_NONE__UINT, GTK_TYPE_NONE, 1, GTK_TYPE_UINT); ptrstrip_signals[POINTER_SELECT] = gtk_signal_new ("pointer_select", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (PtrStripClass, pointer_select), gtk_marshal_NONE__UINT, GTK_TYPE_NONE, 1, GTK_TYPE_UINT); ptrstrip_signals[POINTER_UNSELECT] = gtk_signal_new ("pointer_unselect", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (PtrStripClass, pointer_unselect), gtk_marshal_NONE__UINT, GTK_TYPE_NONE, 1, GTK_TYPE_UINT); gtk_object_class_add_signals (object_class, ptrstrip_signals, DUMMY_SIGNAL); klass->pointer_change = ptrstrip_pointer_changed; klass->pointer_select = NULL; object_class->destroy = ptrstrip_destroy; widget_class->size_request = ptrstrip_size_request; widget_class->size_allocate = ptrstrip_size_allocate; widget_class->realize = ptrstrip_realize; widget_class->expose_event = ptrstrip_expose; widget_class->button_press_event = ptrstrip_button_press; widget_class->button_release_event = ptrstrip_button_release; widget_class->motion_notify_event = ptrstrip_motion_notify;}static voidptrstrip_init (PtrStrip * ptrstrip){ ptrstrip->pointers = NULL; ptrstrip->selpointer = NULL; ptrstrip->pointer_pm = NULL; ptrstrip->pointer_mask = NULL;}GtkWidget *ptrstrip_new (void){ PtrStrip *ptrstrip; ptrstrip = gtk_type_new (ptrstrip_get_type ()); return GTK_WIDGET (ptrstrip);}voidptrstrip_new_pointer (PtrStrip * ptrstrip, gint xpos){ GtkPSPtr *ptr; g_return_if_fail (ptrstrip != NULL); g_return_if_fail (IS_PTRSTRIP (ptrstrip)); ptr = g_new (GtkPSPtr, 1); ptr->xpos = xpos; ptrstrip->pointers = g_list_append (ptrstrip->pointers, ptr); gtk_widget_queue_draw (GTK_WIDGET (ptrstrip));}voidptrstrip_set_pointer (PtrStrip * ptrstrip, guint ptrndx, gint xpos){ GList *p; g_return_if_fail (ptrstrip != NULL); g_return_if_fail (IS_PTRSTRIP (ptrstrip)); if (!(p = g_list_nth (ptrstrip->pointers, ptrndx))) return; ((GtkPSPtr *) (p->data))->xpos = xpos; gtk_signal_emit (GTK_OBJECT (ptrstrip), ptrstrip_signals[POINTER_CHANGE], ptrndx);}static voidptrstrip_destroy (GtkObject * object){ PtrStrip *ptrstrip; GList *p; g_return_if_fail (object != NULL); g_return_if_fail (IS_PTRSTRIP (object)); ptrstrip = PTRSTRIP (object); p = ptrstrip->pointers; while (p) { g_free (p->data); p = g_list_next (p); } g_list_free (ptrstrip->pointers); if (ptrstrip->pointer_pm) gdk_pixmap_unref (ptrstrip->pointer_pm); if (ptrstrip->pointer_mask) gdk_bitmap_unref (ptrstrip->pointer_mask); if (GTK_OBJECT_CLASS (parent_class)->destroy) (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);}static voidptrstrip_size_request (GtkWidget * widget, GtkRequisition * requisition){ requisition->width = PTRSTRIP_DEFAULT_SIZEX; requisition->height = PTRSTRIP_DEFAULT_SIZEY;}static voidptrstrip_size_allocate (GtkWidget * widget, GtkAllocation * allocation){ g_return_if_fail (widget != NULL); g_return_if_fail (IS_PTRSTRIP (widget)); g_return_if_fail (allocation != NULL); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)) gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height);}static voidptrstrip_realize (GtkWidget * widget){ PtrStrip *ptrstrip; GdkWindowAttr attributes; gint attributes_mask; g_return_if_fail (widget != NULL); g_return_if_fail (IS_PTRSTRIP (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); ptrstrip = PTRSTRIP (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 (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (widget->window, widget); widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); ptrstrip->pointer_pm = gdk_pixmap_create_from_xpm_d (widget->window, &ptrstrip->pointer_mask, &widget->style->black, (gchar **) xpm_pointer);}static gintptrstrip_expose (GtkWidget * widget, GdkEventExpose * event){ PtrStrip *ptrstrip; GList *p; gint xpos; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PTRSTRIP (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (event->count > 0) return (FALSE); /* eat up extra expose events */ ptrstrip = PTRSTRIP (widget); gdk_window_clear (widget->window); /* clear the widget's window */ gdk_gc_set_clip_mask (widget->style->black_gc, ptrstrip->pointer_mask); /* draw all the pointers */ p = ptrstrip->pointers; while (p) { xpos = ((GtkPSPtr *) (p->data))->xpos; if (xpos != -1) { /* set the mask clipping origin for destination drawable (window) */ gdk_gc_set_clip_origin (widget->style->black_gc, xpos - (XPM_POINTER_WIDTH >> 1), 0); /* draw the pointer */ gdk_draw_pixmap (widget->window, widget->style->black_gc, ptrstrip->pointer_pm, 0, 0, xpos - (XPM_POINTER_WIDTH >> 1), 0, -1, -1); } p = g_list_next (p); } /* reset clipping mask and origin */ gdk_gc_set_clip_mask (widget->style->black_gc, NULL); gdk_gc_set_clip_origin (widget->style->black_gc, 0, 0); return FALSE;}static voidptrstrip_pointer_changed (PtrStrip * ptrstrip, guint ptrndx){ gtk_widget_queue_draw (GTK_WIDGET (ptrstrip));}static gintptrstrip_button_press (GtkWidget * widget, GdkEventButton * event){ PtrStrip *ptrstrip; GtkPSPtr *ptr; GList *p; gint x, y; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PTRSTRIP (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); ptrstrip = PTRSTRIP (widget); /* make sure its a left button click */ if (event->button != 1) return (FALSE); x = event->x; y = event->y; p = ptrstrip->pointers; while (p) { ptr = (GtkPSPtr *) (p->data); if (ptr->xpos != -1 && x >= (ptr->xpos - (XPM_POINTER_WIDTH >> 1)) && x <= (ptr->xpos + (XPM_POINTER_WIDTH >> 1))) { ptrstrip->selpointer = p; gtk_grab_add (widget); gtk_signal_emit (GTK_OBJECT (ptrstrip), ptrstrip_signals[POINTER_SELECT], g_list_position (ptrstrip->pointers, p)); break; } p = g_list_next (p); } return (FALSE);}static gintptrstrip_button_release (GtkWidget * widget, GdkEventButton * event){ PtrStrip *ptrstrip; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PTRSTRIP (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); ptrstrip = PTRSTRIP (widget); if (event->button == 1 && ptrstrip->selpointer) { gtk_grab_remove (widget); /* no more mouse event grabbing */ gtk_signal_emit (GTK_OBJECT (ptrstrip), ptrstrip_signals[POINTER_UNSELECT], g_list_position (ptrstrip->pointers, ptrstrip->selpointer)); ptrstrip->selpointer = NULL; } return FALSE;}static gintptrstrip_motion_notify (GtkWidget * widget, GdkEventMotion * event){ PtrStrip *ptrstrip; gint x, y; GdkModifierType mods; GtkPSPtr *ptr; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PTRSTRIP (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); ptrstrip = PTRSTRIP (widget); x = event->x; y = event->y; if (event->is_hint || (event->window != widget->window)) gdk_window_get_pointer (widget->window, &x, &y, &mods); if (ptrstrip->selpointer) { ptr = (GtkPSPtr *) (ptrstrip->selpointer->data); /* if mouse x position is out of sample view, clamp it */ x = CLAMP (x, 0, widget->allocation.width - 1); if (x == ptr->xpos) return (FALSE); /* pointer moved from last xpos? */ ptr->xpos = x; gtk_signal_emit (GTK_OBJECT (widget), ptrstrip_signals[POINTER_CHANGE], g_list_position (ptrstrip->pointers, ptrstrip->selpointer)); return (FALSE); } return (FALSE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -