Mercurial > audlegacy
annotate src/audacious/widgets/audacious_pbutton.c @ 2831:251fe210b6fd trunk
[svn] - free images
| author | desowin |
|---|---|
| date | Mon, 11 Jun 2007 12:53:55 -0700 |
| parents | 4eda78b785ed |
| children | 1e97a0a228b7 |
| rev | line source |
|---|---|
| 2822 | 1 /* |
| 2 * Audacious - a cross-platform multimedia player | |
| 3 * Copyright (c) 2007 Audacious development team. | |
| 4 * | |
| 5 * This program is free software; you can redistribute it and/or modify | |
| 6 * it under the terms of the GNU General Public License as published by | |
| 7 * the Free Software Foundation; either version 2 of the License, or | |
| 8 * (at your option) any later version. | |
| 9 * | |
| 10 * This program is distributed in the hope that it will be useful, | |
| 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 * GNU General Public License for more details. | |
| 14 * | |
| 15 * You should have received a copy of the GNU General Public License | |
| 16 * along with this program; if not, write to the Free Software | |
| 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 18 */ | |
| 19 | |
| 20 #include "widgetcore.h" | |
| 21 #include "audacious_pbutton.h" | |
| 2827 | 22 #include "../util.h" |
| 2822 | 23 |
| 24 #include <gtk/gtkmain.h> | |
| 25 #include <gtk/gtkmarshal.h> | |
| 26 #include <gtk/gtkimage.h> | |
| 27 | |
| 28 #define AUDACIOUS_PBUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), AUDACIOUS_TYPE_PBUTTON, AudaciousPButtonPrivate)) | |
| 29 typedef struct _AudaciousPButtonPrivate AudaciousPButtonPrivate; | |
| 30 | |
| 31 struct _AudaciousPButtonPrivate { | |
| 32 //Skinned part | |
| 33 GtkWidget *image; | |
| 34 GdkGC *gc; | |
| 35 gint w; | |
| 36 gint h; | |
| 37 SkinPixmapId skin_index1; | |
| 38 SkinPixmapId skin_index2; | |
| 39 GtkWidget *fixed; | |
| 2827 | 40 gboolean double_size; |
| 2822 | 41 }; |
| 42 | |
| 43 | |
| 44 static GtkBinClass *parent_class = NULL; | |
| 45 static void audacious_pbutton_class_init(AudaciousPButtonClass *klass); | |
| 46 static void audacious_pbutton_init(AudaciousPButton *button); | |
| 47 static GObject* audacious_pbutton_constructor(GType type, guint n_construct_properties, GObjectConstructParam *construct_params); | |
| 48 static void audacious_pbutton_destroy(GtkObject *object); | |
| 49 static void audacious_pbutton_realize(GtkWidget *widget); | |
| 50 static void audacious_pbutton_unrealize(GtkWidget *widget); | |
| 51 static void audacious_pbutton_map(GtkWidget *widget); | |
| 52 static void audacious_pbutton_unmap(GtkWidget *widget); | |
| 53 static gint audacious_pbutton_expose(GtkWidget *widget,GdkEventExpose *event); | |
| 54 | |
| 55 static void audacious_pbutton_size_allocate(GtkWidget *widget, GtkAllocation *allocation); | |
| 56 static void audacious_pbutton_update_state(AudaciousPButton *button); | |
| 57 | |
| 58 static guint button_signals[LAST_SIGNAL] = { 0 }; | |
| 59 static gint audacious_pbutton_button_press(GtkWidget *widget, GdkEventButton *event); | |
| 60 static gint audacious_pbutton_button_release(GtkWidget *widget, GdkEventButton *event); | |
| 61 static void button_pressed(AudaciousPButton *button); | |
| 62 static void button_released(AudaciousPButton *button); | |
| 63 static void audacious_pbutton_add(GtkContainer *container, GtkWidget *widget); | |
| 2827 | 64 static void audacious_pbutton_toggle_doublesize(AudaciousPButton *button); |
| 2822 | 65 |
| 66 static gint audacious_pbutton_enter_notify(GtkWidget *widget, GdkEventCrossing *event); | |
| 67 static gint audacious_pbutton_leave_notify(GtkWidget *widget, GdkEventCrossing *event); | |
| 68 static void audacious_pbutton_paint(AudaciousPButton *button); | |
| 69 | |
| 70 GType audacious_pbutton_get_type (void) { | |
| 71 static GType button_type = 0; | |
| 72 | |
| 73 if (!button_type) { | |
| 74 static const GTypeInfo button_info = { | |
| 75 sizeof (AudaciousPButtonClass), | |
| 76 NULL, /* base_init */ | |
| 77 NULL, /* base_finalize */ | |
| 78 (GClassInitFunc) audacious_pbutton_class_init, | |
| 79 NULL, /* class_finalize */ | |
| 80 NULL, /* class_data */ | |
| 81 sizeof (AudaciousPButton), | |
| 82 16, /* n_preallocs */ | |
| 83 (GInstanceInitFunc) audacious_pbutton_init, | |
| 84 }; | |
| 85 | |
| 86 button_type = g_type_register_static (GTK_TYPE_BIN, "AudaciousPButton", &button_info, 0); | |
| 87 } | |
| 88 return button_type; | |
| 89 } | |
| 90 | |
| 91 static void audacious_pbutton_class_init (AudaciousPButtonClass *klass) { | |
| 92 GObjectClass *gobject_class; | |
| 93 GtkObjectClass *object_class; | |
| 94 GtkWidgetClass *widget_class; | |
| 95 GtkContainerClass *container_class; | |
| 96 | |
| 97 gobject_class = G_OBJECT_CLASS(klass); | |
| 98 object_class = (GtkObjectClass*)klass; | |
| 99 widget_class = (GtkWidgetClass*)klass; | |
| 100 container_class = (GtkContainerClass*)klass; | |
| 101 | |
| 102 parent_class = g_type_class_peek_parent(klass); | |
| 103 gobject_class->constructor = audacious_pbutton_constructor; | |
| 104 object_class->destroy = audacious_pbutton_destroy; | |
| 105 | |
| 106 widget_class->realize = audacious_pbutton_realize; | |
| 107 widget_class->unrealize = audacious_pbutton_unrealize; | |
| 108 widget_class->map = audacious_pbutton_map; | |
| 109 widget_class->unmap = audacious_pbutton_unmap; | |
| 110 widget_class->size_allocate = audacious_pbutton_size_allocate; | |
| 111 widget_class->expose_event = audacious_pbutton_expose; | |
| 112 widget_class->button_press_event = audacious_pbutton_button_press; | |
| 113 widget_class->button_release_event = audacious_pbutton_button_release; | |
| 114 widget_class->enter_notify_event = audacious_pbutton_enter_notify; | |
| 115 widget_class->leave_notify_event = audacious_pbutton_leave_notify; | |
| 116 | |
| 117 container_class->add = audacious_pbutton_add; | |
| 118 | |
| 119 klass->pressed = button_pressed; | |
| 120 klass->released = button_released; | |
| 121 klass->clicked = NULL; | |
| 2827 | 122 klass->doubled = audacious_pbutton_toggle_doublesize; |
|
2829
4eda78b785ed
[svn] - draw_main_window redraws custom gtk widgets
desowin
parents:
2828
diff
changeset
|
123 klass->redraw = audacious_pbutton_paint; |
| 2822 | 124 |
| 125 button_signals[PRESSED] = | |
| 126 g_signal_new ("pressed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, | |
| 127 G_STRUCT_OFFSET (AudaciousPButtonClass, pressed), NULL, NULL, | |
| 128 gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); | |
| 129 | |
| 130 button_signals[RELEASED] = | |
| 131 g_signal_new ("released", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, | |
| 132 G_STRUCT_OFFSET (AudaciousPButtonClass, released), NULL, NULL, | |
| 133 gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); | |
| 134 | |
| 135 button_signals[CLICKED] = | |
| 136 g_signal_new ("clicked", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, | |
| 137 G_STRUCT_OFFSET (AudaciousPButtonClass, clicked), NULL, NULL, | |
| 138 gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); | |
| 139 | |
| 140 button_signals[DOUBLED] = | |
| 2827 | 141 g_signal_new ("toggle-double-size", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, |
| 2822 | 142 G_STRUCT_OFFSET (AudaciousPButtonClass, doubled), NULL, NULL, |
| 143 gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); | |
| 144 | |
|
2829
4eda78b785ed
[svn] - draw_main_window redraws custom gtk widgets
desowin
parents:
2828
diff
changeset
|
145 button_signals[REDRAW] = |
|
4eda78b785ed
[svn] - draw_main_window redraws custom gtk widgets
desowin
parents:
2828
diff
changeset
|
146 g_signal_new ("redraw", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, |
|
4eda78b785ed
[svn] - draw_main_window redraws custom gtk widgets
desowin
parents:
2828
diff
changeset
|
147 G_STRUCT_OFFSET (AudaciousPButtonClass, redraw), NULL, NULL, |
|
4eda78b785ed
[svn] - draw_main_window redraws custom gtk widgets
desowin
parents:
2828
diff
changeset
|
148 gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); |
|
4eda78b785ed
[svn] - draw_main_window redraws custom gtk widgets
desowin
parents:
2828
diff
changeset
|
149 |
| 2822 | 150 g_type_class_add_private (gobject_class, sizeof (AudaciousPButtonPrivate)); |
| 151 } | |
| 152 | |
| 153 static void audacious_pbutton_init (AudaciousPButton *button) { | |
| 154 AudaciousPButtonPrivate *priv = AUDACIOUS_PBUTTON_GET_PRIVATE (button); | |
| 155 priv->image = gtk_image_new(); | |
| 156 g_object_set (priv->image, "visible", TRUE, NULL); | |
| 157 gtk_container_add(GTK_CONTAINER(GTK_WIDGET(button)), priv->image); | |
| 158 | |
| 159 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS); | |
| 160 GTK_WIDGET_SET_FLAGS (button, GTK_NO_WINDOW); | |
| 161 } | |
| 162 | |
| 163 static void audacious_pbutton_destroy (GtkObject *object) { | |
| 164 (*GTK_OBJECT_CLASS (parent_class)->destroy) (object); | |
| 165 } | |
| 166 | |
| 167 static GObject* audacious_pbutton_constructor(GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { | |
| 168 GObject *object = (*G_OBJECT_CLASS (parent_class)->constructor)(type, n_construct_properties, construct_params); | |
| 169 | |
| 170 return object; | |
| 171 } | |
| 172 | |
| 173 static void audacious_pbutton_realize (GtkWidget *widget) { | |
| 174 AudaciousPButton *button = AUDACIOUS_PBUTTON (widget); | |
| 175 GdkWindowAttr attrib; | |
| 176 | |
| 177 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); | |
| 178 | |
| 179 attrib.window_type = GDK_WINDOW_CHILD; | |
| 180 attrib.x = widget->allocation.x; | |
| 181 attrib.y = widget->allocation.y; | |
| 182 attrib.width = widget->allocation.width; | |
| 183 attrib.height = widget->allocation.height; | |
| 184 attrib.wclass = GDK_INPUT_ONLY; | |
| 185 attrib.event_mask = gtk_widget_get_events (widget); | |
| 186 attrib.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); | |
| 187 | |
| 188 widget->window = gtk_widget_get_parent_window(widget); | |
| 189 g_object_ref(widget->window); | |
| 190 | |
| 191 button->event_window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrib, GDK_WA_X | GDK_WA_Y); | |
| 192 gdk_window_set_user_data (button->event_window, button); | |
| 193 } | |
| 194 | |
| 195 static void audacious_pbutton_unrealize(GtkWidget *widget) { | |
| 196 AudaciousPButton *button = AUDACIOUS_PBUTTON (widget); | |
| 197 | |
| 198 if (button->event_window) { | |
| 199 gdk_window_set_user_data (button->event_window, NULL); | |
| 200 gdk_window_destroy (button->event_window); | |
| 201 button->event_window = NULL; | |
| 202 } | |
| 203 | |
| 204 GTK_WIDGET_CLASS (parent_class)->unrealize (widget); | |
| 205 } | |
| 206 | |
| 207 static void audacious_pbutton_map(GtkWidget *widget) { | |
| 208 AudaciousPButton *button = AUDACIOUS_PBUTTON (widget); | |
| 209 g_return_if_fail (AUDACIOUS_IS_PBUTTON (widget)); | |
| 210 GTK_WIDGET_CLASS (parent_class)->map(widget); | |
| 211 gdk_window_show (button->event_window); | |
| 212 } | |
| 213 | |
| 214 static void audacious_pbutton_unmap (GtkWidget *widget) { | |
| 215 AudaciousPButton *button = AUDACIOUS_PBUTTON (widget); | |
| 216 g_return_if_fail (AUDACIOUS_IS_PBUTTON(widget)); | |
| 217 | |
| 218 if (button->event_window) | |
| 219 gdk_window_hide (button->event_window); | |
| 220 | |
| 221 GTK_WIDGET_CLASS (parent_class)->unmap (widget); | |
| 222 } | |
| 223 | |
| 224 static gboolean audacious_pbutton_expose(GtkWidget *widget, GdkEventExpose *event) { | |
| 225 if (GTK_WIDGET_DRAWABLE (widget)) | |
| 226 (*GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); | |
| 227 | |
| 228 return FALSE; | |
| 229 } | |
| 230 | |
| 231 GtkWidget* audacious_pbutton_new () { | |
| 232 return g_object_new (AUDACIOUS_TYPE_PBUTTON, NULL); | |
| 233 } | |
| 234 | |
| 235 void audacious_pbutton_setup(GtkWidget *button, GtkWidget *fixed, GdkPixmap *parent, GdkGC *gc, gint x, gint y, gint w, gint h, gint nx, gint ny, gint px, gint py, SkinPixmapId si) { | |
| 236 | |
| 237 AudaciousPButton *pbutton = AUDACIOUS_PBUTTON(button); | |
| 238 AudaciousPButtonPrivate *priv = AUDACIOUS_PBUTTON_GET_PRIVATE(pbutton); | |
| 239 priv->gc = gc; | |
| 240 priv->w = w; | |
| 241 priv->h = h; | |
| 242 pbutton->x = x; | |
| 243 pbutton->y = y; | |
| 244 pbutton->nx = nx; | |
| 245 pbutton->ny = ny; | |
| 246 pbutton->px = px; | |
| 247 pbutton->py = py; | |
| 248 priv->skin_index1 = si; | |
| 249 priv->skin_index2 = si; | |
| 250 priv->fixed = fixed; | |
| 2827 | 251 priv->double_size = FALSE; |
| 2822 | 252 |
| 253 gtk_widget_set_size_request(button, priv->w, priv->h); | |
| 254 gtk_fixed_put(GTK_FIXED(priv->fixed),GTK_WIDGET(button), pbutton->x, pbutton->y); | |
| 255 } | |
| 256 | |
| 257 static void audacious_pbutton_size_allocate(GtkWidget *widget, GtkAllocation *allocation) { | |
| 258 AudaciousPButton *button = AUDACIOUS_PBUTTON (widget); | |
| 259 GtkAllocation child_alloc; | |
| 260 | |
| 261 widget->allocation = *allocation; | |
| 262 if (GTK_BIN (button)->child) { //image should fill whole widget | |
| 263 child_alloc.x = widget->allocation.x; | |
| 264 child_alloc.y = widget->allocation.y; | |
| 265 child_alloc.width = MAX (1, widget->allocation.width); | |
| 266 child_alloc.height = MAX (1, widget->allocation.height); | |
| 267 | |
| 268 gtk_widget_size_allocate (GTK_BIN (button)->child, &child_alloc); | |
| 269 } | |
| 2828 | 270 |
| 271 if (GDK_IS_WINDOW(button->event_window)) | |
| 272 gdk_window_move_resize (button->event_window, widget->allocation.x, widget->allocation.y, | |
| 273 widget->allocation.width, widget->allocation.height); | |
| 2822 | 274 } |
| 275 | |
| 276 static void button_pressed(AudaciousPButton *button) { | |
| 277 button->button_down = TRUE; | |
| 278 audacious_pbutton_update_state(button); | |
| 279 } | |
| 280 | |
| 281 static void button_released(AudaciousPButton *button) { | |
| 282 button->button_down = FALSE; | |
| 283 if(button->hover) audacious_pbutton_clicked(button); | |
| 284 audacious_pbutton_update_state(button); | |
| 285 } | |
| 286 | |
| 287 static void audacious_pbutton_update_state(AudaciousPButton *button) { | |
| 288 _audacious_pbutton_set_pressed(button, button->button_down); | |
| 289 } | |
| 290 | |
| 291 void _audacious_pbutton_set_pressed (AudaciousPButton *button, gboolean pressed) { | |
| 292 if (pressed != button->pressed) { | |
| 293 button->pressed = pressed; | |
| 294 audacious_pbutton_paint(button); | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 static gboolean audacious_pbutton_button_press(GtkWidget *widget, GdkEventButton *event) { | |
| 299 AudaciousPButton *button; | |
| 300 | |
| 301 if (event->type == GDK_BUTTON_PRESS) { | |
| 302 button = AUDACIOUS_PBUTTON(widget); | |
| 303 | |
| 304 if (event->button == 1) | |
| 305 audacious_pbutton_pressed (button); | |
| 306 } | |
| 307 | |
| 308 return TRUE; | |
| 309 } | |
| 310 | |
| 311 static gboolean audacious_pbutton_button_release(GtkWidget *widget, GdkEventButton *event) { | |
| 312 AudaciousPButton *button; | |
| 313 if (event->button == 1) { | |
| 314 button = AUDACIOUS_PBUTTON(widget); | |
| 315 audacious_pbutton_released(button); | |
| 316 } | |
| 317 | |
| 318 return TRUE; | |
| 319 } | |
| 320 | |
| 321 void audacious_pbutton_pressed(AudaciousPButton *button) { | |
| 322 g_return_if_fail(AUDACIOUS_IS_PBUTTON(button)); | |
| 323 g_signal_emit(button, button_signals[PRESSED], 0); | |
| 324 } | |
| 325 | |
| 326 void audacious_pbutton_released(AudaciousPButton *button) { | |
| 327 g_return_if_fail(AUDACIOUS_IS_PBUTTON(button)); | |
| 328 g_signal_emit(button, button_signals[RELEASED], 0); | |
| 329 } | |
| 330 | |
| 331 void audacious_pbutton_clicked(AudaciousPButton *button) { | |
| 332 g_return_if_fail(AUDACIOUS_IS_PBUTTON(button)); | |
| 333 g_signal_emit(button, button_signals[CLICKED], 0); | |
| 334 } | |
| 335 | |
| 336 static gboolean audacious_pbutton_enter_notify(GtkWidget *widget, GdkEventCrossing *event) { | |
| 337 AudaciousPButton *button; | |
| 338 | |
| 339 button = AUDACIOUS_PBUTTON(widget); | |
| 340 button->hover = TRUE; | |
| 341 if(button->button_down) _audacious_pbutton_set_pressed(button, TRUE); | |
| 342 | |
| 343 return FALSE; | |
| 344 } | |
| 345 | |
| 346 static gboolean audacious_pbutton_leave_notify(GtkWidget *widget, GdkEventCrossing *event) { | |
| 347 AudaciousPButton *button; | |
| 348 | |
| 349 button = AUDACIOUS_PBUTTON (widget); | |
| 350 button->hover = FALSE; | |
| 351 if(button->button_down) _audacious_pbutton_set_pressed(button, FALSE); | |
| 352 | |
| 353 return FALSE; | |
| 354 } | |
| 355 | |
| 356 static void audacious_pbutton_add(GtkContainer *container, GtkWidget *widget) { | |
| 357 GTK_CONTAINER_CLASS (parent_class)->add(container, widget); | |
| 358 } | |
| 359 | |
| 2827 | 360 static void audacious_pbutton_toggle_doublesize(AudaciousPButton *button) { |
| 361 GtkWidget *widget = GTK_WIDGET (button); | |
| 362 AudaciousPButtonPrivate *priv = AUDACIOUS_PBUTTON_GET_PRIVATE (button); | |
| 363 priv->double_size = !priv->double_size; | |
| 364 | |
| 365 gtk_widget_set_size_request(widget, priv->w*(1+priv->double_size), priv->h*(1+priv->double_size)); | |
| 366 gtk_widget_set_uposition(widget, button->x*(1+priv->double_size), button->y*(1+priv->double_size)); | |
| 367 | |
| 368 audacious_pbutton_paint(button); | |
| 2822 | 369 } |
| 370 | |
| 371 static void audacious_pbutton_paint(AudaciousPButton *button) { | |
| 372 GtkWidget *widget = GTK_WIDGET (button); | |
| 373 AudaciousPButtonPrivate *priv = AUDACIOUS_PBUTTON_GET_PRIVATE (button); | |
| 374 | |
| 375 GdkPixmap *obj; | |
| 376 obj = gdk_pixmap_new(NULL, priv->w, priv->h, gdk_rgb_get_visual()->depth); | |
| 377 skin_draw_pixmap(bmp_active_skin, obj, priv->gc, priv->skin_index2, | |
| 378 button->pressed ? button->px : button->nx, | |
| 379 button->pressed ? button->py : button->ny, | |
| 380 0, 0, priv->w, priv->h); | |
| 2827 | 381 if(priv->double_size) { |
| 382 GdkImage *img, *img2x; | |
| 383 img = gdk_drawable_get_image(obj, 0, 0, priv->w, priv->h); | |
| 384 img2x = create_dblsize_image(img); | |
| 385 gtk_image_set(GTK_IMAGE(priv->image), img2x, NULL); | |
| 2831 | 386 g_object_unref(img2x); |
| 387 g_object_unref(img); | |
| 2827 | 388 } else |
| 389 gtk_image_set_from_pixmap(GTK_IMAGE(priv->image), obj, NULL); | |
| 2831 | 390 g_object_unref(obj); |
| 2822 | 391 gtk_widget_queue_resize(widget); |
| 392 } |
