PIKApp/libpikawidgets/pikabutton.c

174 lines
4.7 KiB
C

/* LIBPIKA - The PIKA Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* pikabutton.c
* Copyright (C) 2000-2008 Michael Natterer <mitch@gimp.org>
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "pikawidgetstypes.h"
#include "pikabutton.h"
/**
* SECTION: pikabutton
* @title: PikaButton
* @short_description: A #GtkButton with a little extra functionality.
*
* #PikaButton adds an extra signal to the #GtkButton widget that
* allows the callback to distinguish a normal click from a click that
* was performed with modifier keys pressed.
**/
enum
{
EXTENDED_CLICKED,
LAST_SIGNAL
};
struct _PikaButtonPrivate
{
GdkModifierType press_state;
};
#define GET_PRIVATE(obj) (((PikaButton *) (obj))->priv)
static gboolean pika_button_button_press (GtkWidget *widget,
GdkEventButton *event);
static void pika_button_clicked (GtkButton *button);
G_DEFINE_TYPE_WITH_PRIVATE (PikaButton, pika_button, GTK_TYPE_BUTTON)
#define parent_class pika_button_parent_class
static guint button_signals[LAST_SIGNAL] = { 0 };
static void
pika_button_class_init (PikaButtonClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
/**
* PikaButton::extended-clicked:
* @pikabutton: the object that received the signal.
* @arg1: the state of modifier keys when the button was clicked
*
* This signal is emitted when the button is clicked with a modifier
* key pressed.
**/
button_signals[EXTENDED_CLICKED] =
g_signal_new ("extended-clicked",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (PikaButtonClass, extended_clicked),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
GDK_TYPE_MODIFIER_TYPE);
widget_class->button_press_event = pika_button_button_press;
button_class->clicked = pika_button_clicked;
}
static void
pika_button_init (PikaButton *button)
{
button->priv = pika_button_get_instance_private (button);
}
/**
* pika_button_new:
*
* Creates a new #PikaButton widget.
*
* Returns: A pointer to the new #PikaButton widget.
**/
GtkWidget *
pika_button_new (void)
{
return g_object_new (PIKA_TYPE_BUTTON, NULL);
}
/**
* pika_button_extended_clicked:
* @button: a #PikaButton.
* @modifier_state: a state as found in #GdkEventButton->state,
* e.g. #GDK_SHIFT_MASK.
*
* Emits the button's "extended_clicked" signal.
**/
void
pika_button_extended_clicked (PikaButton *button,
GdkModifierType modifier_state)
{
g_return_if_fail (PIKA_IS_BUTTON (button));
g_signal_emit (button, button_signals[EXTENDED_CLICKED], 0, modifier_state);
}
static gboolean
pika_button_button_press (GtkWidget *widget,
GdkEventButton *bevent)
{
PikaButtonPrivate *private = GET_PRIVATE (widget);
if (bevent->button == 1)
{
private->press_state = bevent->state;
}
else
{
private->press_state = 0;
}
return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, bevent);
}
static void
pika_button_clicked (GtkButton *button)
{
PikaButtonPrivate *private = GET_PRIVATE (button);
if (private->press_state &
(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK |
gtk_widget_get_modifier_mask (GTK_WIDGET (button),
GDK_MODIFIER_INTENT_PRIMARY_ACCELERATOR) |
gtk_widget_get_modifier_mask (GTK_WIDGET (button),
GDK_MODIFIER_INTENT_EXTEND_SELECTION) |
gtk_widget_get_modifier_mask (GTK_WIDGET (button),
GDK_MODIFIER_INTENT_MODIFY_SELECTION)))
{
g_signal_stop_emission_by_name (button, "clicked");
pika_button_extended_clicked (PIKA_BUTTON (button), private->press_state);
}
else if (GTK_BUTTON_CLASS (parent_class)->clicked)
{
GTK_BUTTON_CLASS (parent_class)->clicked (button);
}
}