2005-06-22 18:20:32 +00:00
|
|
|
/*
|
2007-06-24 12:56:20 -05:00
|
|
|
* mooaccelbutton.c
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
2010-11-07 01:20:45 -08:00
|
|
|
* Copyright (C) 2004-2010 by Yevgen Muntyan <emuntyan@sourceforge.net>
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
2008-09-05 17:20:50 -05:00
|
|
|
* This file is part of medit. medit 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 2.1 of the License,
|
|
|
|
* or (at your option) any later version.
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
2008-09-05 17:20:50 -05:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with medit. If not, see <http://www.gnu.org/licenses/>.
|
2005-06-22 18:20:32 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "mooutils/mooaccelbutton.h"
|
2008-02-18 19:42:41 -06:00
|
|
|
#include "marshals.h"
|
2006-04-20 23:44:50 -05:00
|
|
|
#include "mooutils/moodialogs.h"
|
2006-08-03 02:29:39 -05:00
|
|
|
#include "mooutils/mooi18n.h"
|
2010-12-17 00:46:14 -08:00
|
|
|
#include "mooutils/mooaccelbutton-gxml.h"
|
2009-04-19 02:33:05 -07:00
|
|
|
#include <gtk/gtk.h>
|
2005-06-22 18:20:32 +00:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
PROP_0,
|
|
|
|
PROP_ACCEL,
|
|
|
|
PROP_TITLE
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ACCEL_SET,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = {0};
|
|
|
|
|
|
|
|
|
2006-12-31 04:53:45 -06:00
|
|
|
static void moo_accel_button_finalize (GObject *object);
|
|
|
|
static void moo_accel_button_set_property (GObject *object,
|
|
|
|
guint param_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec);
|
|
|
|
static void moo_accel_button_get_property (GObject *object,
|
|
|
|
guint param_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2006-12-31 04:53:45 -06:00
|
|
|
static void moo_accel_button_clicked (GtkButton *button);
|
|
|
|
|
|
|
|
static const char *_moo_accel_button_get_title (MooAccelButton *button);
|
|
|
|
static void _moo_accel_button_set_title (MooAccelButton *button,
|
|
|
|
const char *title);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
G_DEFINE_TYPE (MooAccelButton, _moo_accel_button, GTK_TYPE_BUTTON)
|
2005-06-22 18:20:32 +00:00
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
static void
|
|
|
|
_moo_accel_button_class_init (MooAccelButtonClass *klass)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
gobject_class->get_property = moo_accel_button_get_property;
|
|
|
|
gobject_class->set_property = moo_accel_button_set_property;
|
|
|
|
gobject_class->finalize = moo_accel_button_finalize;
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
GTK_BUTTON_CLASS (klass)->clicked = moo_accel_button_clicked;
|
|
|
|
|
2005-06-22 18:20:32 +00:00
|
|
|
klass->accel_set = NULL;
|
|
|
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
PROP_ACCEL,
|
|
|
|
g_param_spec_string (
|
|
|
|
"accel",
|
|
|
|
"accel",
|
|
|
|
"accel",
|
|
|
|
NULL,
|
2010-08-12 18:17:00 -07:00
|
|
|
(GParamFlags) G_PARAM_READWRITE));
|
2005-06-22 18:20:32 +00:00
|
|
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
PROP_TITLE,
|
|
|
|
g_param_spec_string (
|
|
|
|
"title",
|
|
|
|
"title",
|
|
|
|
"title",
|
|
|
|
"Choose shortcut",
|
2010-08-12 18:17:00 -07:00
|
|
|
(GParamFlags) G_PARAM_READWRITE));
|
2005-06-22 18:20:32 +00:00
|
|
|
|
|
|
|
signals[ACCEL_SET] = g_signal_new ("accel-set",
|
|
|
|
G_TYPE_FROM_CLASS (gobject_class),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
G_STRUCT_OFFSET (MooAccelButtonClass, accel_set),
|
|
|
|
NULL, NULL,
|
|
|
|
_moo_marshal_VOID__STRING,
|
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
G_TYPE_STRING);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
static void
|
|
|
|
_moo_accel_button_init (MooAccelButton *button)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
button->accel = NULL;
|
|
|
|
button->title = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
static void
|
|
|
|
moo_accel_button_finalize (GObject *object)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
MooAccelButton *button = MOO_ACCEL_BUTTON (object);
|
|
|
|
g_free (button->title);
|
|
|
|
button->title = NULL;
|
|
|
|
g_free (button->accel);
|
|
|
|
button->accel = NULL;
|
2006-08-15 02:09:09 -05:00
|
|
|
G_OBJECT_CLASS (_moo_accel_button_parent_class)->finalize (object);
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
static void
|
|
|
|
moo_accel_button_set_property (GObject *object,
|
|
|
|
guint param_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
MooAccelButton *button = MOO_ACCEL_BUTTON (object);
|
|
|
|
|
|
|
|
switch (param_id)
|
|
|
|
{
|
|
|
|
case PROP_TITLE:
|
2006-08-15 02:09:09 -05:00
|
|
|
_moo_accel_button_set_title (button, g_value_get_string (value));
|
2005-06-22 18:20:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_ACCEL:
|
2006-08-15 02:09:09 -05:00
|
|
|
_moo_accel_button_set_accel (button, g_value_get_string (value));
|
2005-06-22 18:20:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
static void
|
|
|
|
moo_accel_button_get_property (GObject *object,
|
|
|
|
guint param_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
MooAccelButton *button = MOO_ACCEL_BUTTON (object);
|
|
|
|
|
|
|
|
switch (param_id)
|
|
|
|
{
|
|
|
|
case PROP_TITLE:
|
2006-08-15 02:09:09 -05:00
|
|
|
g_value_set_string (value, _moo_accel_button_get_title (button));
|
2005-06-22 18:20:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_ACCEL:
|
2006-08-15 02:09:09 -05:00
|
|
|
g_value_set_string (value, _moo_accel_button_get_accel (button));
|
2005-06-22 18:20:32 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-31 04:53:45 -06:00
|
|
|
static const char *
|
2006-08-15 02:09:09 -05:00
|
|
|
_moo_accel_button_get_title (MooAccelButton *button)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (MOO_IS_ACCEL_BUTTON (button), NULL);
|
|
|
|
return button->title;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-31 04:53:45 -06:00
|
|
|
static void
|
2006-08-15 02:09:09 -05:00
|
|
|
_moo_accel_button_set_title (MooAccelButton *button,
|
|
|
|
const char *title)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
g_return_if_fail (MOO_IS_ACCEL_BUTTON (button));
|
|
|
|
g_free (button->title);
|
|
|
|
button->title = g_strdup (title);
|
|
|
|
g_object_notify (G_OBJECT (button), "title");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
const char *
|
|
|
|
_moo_accel_button_get_accel (MooAccelButton *button)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (MOO_IS_ACCEL_BUTTON (button), NULL);
|
|
|
|
return button->accel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
gboolean
|
|
|
|
_moo_accel_button_set_accel (MooAccelButton *button,
|
|
|
|
const char *accel)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2006-08-15 02:09:09 -05:00
|
|
|
guint accel_key = 0;
|
2010-08-12 18:17:00 -07:00
|
|
|
GdkModifierType accel_mods = (GdkModifierType) 0;
|
2005-06-22 18:20:32 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (MOO_IS_ACCEL_BUTTON (button), FALSE);
|
|
|
|
|
|
|
|
if (accel && accel[0])
|
|
|
|
{
|
|
|
|
gtk_accelerator_parse (accel, &accel_key, &accel_mods);
|
2006-08-15 02:09:09 -05:00
|
|
|
|
2008-05-05 10:25:47 -05:00
|
|
|
if (!accel_key || accel_key == GDK_VoidSymbol)
|
2005-06-22 18:20:32 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (button->accel);
|
2006-08-15 02:09:09 -05:00
|
|
|
|
|
|
|
if (accel_key || accel_mods)
|
|
|
|
{
|
2005-06-22 18:20:32 +00:00
|
|
|
char *label = gtk_accelerator_get_label (accel_key, accel_mods);
|
|
|
|
button->accel = gtk_accelerator_name (accel_key, accel_mods);
|
|
|
|
gtk_button_set_label (GTK_BUTTON (button), label);
|
|
|
|
g_free (label);
|
|
|
|
}
|
2006-08-15 02:09:09 -05:00
|
|
|
else
|
|
|
|
{
|
2005-06-22 18:20:32 +00:00
|
|
|
button->accel = g_strdup ("");
|
|
|
|
gtk_button_set_label (GTK_BUTTON (button), "");
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (button), "accel");
|
|
|
|
g_signal_emit (button, signals[ACCEL_SET], 0, button->accel);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2010-08-12 18:17:00 -07:00
|
|
|
GdkModifierType mods;
|
2005-06-22 18:20:32 +00:00
|
|
|
guint key;
|
|
|
|
GtkLabel *label;
|
2007-09-12 13:39:53 -05:00
|
|
|
GtkDialog *dialog;
|
|
|
|
guint commit_timeout;
|
2005-06-22 18:20:32 +00:00
|
|
|
} Stuff;
|
|
|
|
|
|
|
|
|
2007-09-12 13:39:53 -05:00
|
|
|
static gboolean
|
|
|
|
commit_timeout (Stuff *s)
|
|
|
|
{
|
|
|
|
s->commit_timeout = 0;
|
|
|
|
gtk_dialog_response (s->dialog, GTK_RESPONSE_OK);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_commit_timeout (Stuff *s)
|
|
|
|
{
|
|
|
|
if (s->commit_timeout)
|
|
|
|
g_source_remove (s->commit_timeout);
|
|
|
|
s->commit_timeout = g_timeout_add (500, (GSourceFunc) commit_timeout, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
remove_commit_timeout (Stuff *s)
|
|
|
|
{
|
|
|
|
if (s->commit_timeout)
|
|
|
|
g_source_remove (s->commit_timeout);
|
|
|
|
s->commit_timeout = 0;
|
|
|
|
}
|
|
|
|
|
2006-08-15 02:09:09 -05:00
|
|
|
static gboolean
|
2006-11-07 06:05:12 -06:00
|
|
|
key_event (GtkWidget *widget,
|
2006-08-15 02:09:09 -05:00
|
|
|
GdkEventKey *event,
|
|
|
|
Stuff *s)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2006-11-07 06:05:12 -06:00
|
|
|
GdkKeymap *keymap;
|
|
|
|
guint keyval;
|
|
|
|
GdkModifierType consumed_modifiers;
|
2010-08-12 18:17:00 -07:00
|
|
|
int mods;
|
2006-11-07 06:05:12 -06:00
|
|
|
|
|
|
|
keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
|
|
|
|
gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode,
|
2010-08-12 18:17:00 -07:00
|
|
|
(GdkModifierType) event->state, event->group,
|
2006-11-07 06:05:12 -06:00
|
|
|
NULL, NULL, NULL, &consumed_modifiers);
|
|
|
|
|
|
|
|
keyval = gdk_keyval_to_lower (event->keyval);
|
|
|
|
mods = event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_modifiers;
|
|
|
|
|
|
|
|
if (keyval != event->keyval)
|
|
|
|
mods |= GDK_SHIFT_MASK;
|
|
|
|
|
2010-08-12 18:17:00 -07:00
|
|
|
if (gtk_accelerator_valid (keyval, (GdkModifierType) mods))
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2010-08-12 18:17:00 -07:00
|
|
|
char *label = gtk_accelerator_get_label (keyval, (GdkModifierType) mods);
|
2005-06-22 18:20:32 +00:00
|
|
|
gtk_label_set_text (s->label, label);
|
|
|
|
g_free (label);
|
2006-11-07 06:05:12 -06:00
|
|
|
s->key = keyval;
|
2010-08-12 18:17:00 -07:00
|
|
|
s->mods = (GdkModifierType) mods;
|
2007-09-12 13:39:53 -05:00
|
|
|
add_commit_timeout (s);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
remove_commit_timeout (s);
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-03 02:29:39 -05:00
|
|
|
static void
|
2006-08-15 02:09:09 -05:00
|
|
|
moo_accel_button_clicked (GtkButton *gtkbutton)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2006-08-15 02:09:09 -05:00
|
|
|
MooAccelButton *button = MOO_ACCEL_BUTTON (gtkbutton);
|
2008-08-24 04:06:24 -05:00
|
|
|
AccelDialogXml *xml;
|
|
|
|
GtkWidget *dialog;
|
2007-09-12 13:39:53 -05:00
|
|
|
GtkWidget *parent;
|
2010-08-12 18:17:00 -07:00
|
|
|
Stuff s = { (GdkModifierType) 0, 0, NULL, NULL, 0 };
|
2005-06-22 18:20:32 +00:00
|
|
|
int response;
|
|
|
|
|
2008-08-24 04:06:24 -05:00
|
|
|
xml = accel_dialog_xml_new ();
|
|
|
|
dialog = GTK_WIDGET (xml->AccelDialog);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-09-12 13:39:53 -05:00
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (gtkbutton));
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW (dialog),
|
|
|
|
GTK_IS_WINDOW (parent) ? GTK_WINDOW (parent) : NULL);
|
|
|
|
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
|
|
|
|
|
2005-06-22 18:20:32 +00:00
|
|
|
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
if (button->title)
|
|
|
|
gtk_window_set_title (GTK_WINDOW (dialog), button->title);
|
2006-04-20 23:44:50 -05:00
|
|
|
|
2008-08-24 04:06:24 -05:00
|
|
|
gtk_button_set_use_underline (GTK_BUTTON (xml->ok), FALSE);
|
|
|
|
gtk_button_set_use_underline (GTK_BUTTON (xml->cancel), FALSE);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-08-24 04:06:24 -05:00
|
|
|
s.label = xml->label;
|
2007-09-12 13:39:53 -05:00
|
|
|
s.dialog = GTK_DIALOG (dialog);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-08-24 04:06:24 -05:00
|
|
|
g_signal_connect (xml->eventbox, "key-press-event", G_CALLBACK (key_event), &s);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
|
|
|
response = gtk_dialog_run (GTK_DIALOG (dialog));
|
2007-09-12 13:39:53 -05:00
|
|
|
remove_commit_timeout (&s);
|
2005-09-10 16:02:38 +00:00
|
|
|
|
2005-06-22 18:20:32 +00:00
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
|
2005-09-10 16:02:38 +00:00
|
|
|
if (response == GTK_RESPONSE_OK)
|
|
|
|
{
|
|
|
|
if (s.key || s.mods)
|
|
|
|
{
|
2005-06-22 18:20:32 +00:00
|
|
|
char *accel = gtk_accelerator_name (s.key, s.mods);
|
2006-08-15 02:09:09 -05:00
|
|
|
_moo_accel_button_set_accel (button, accel);
|
2005-06-22 18:20:32 +00:00
|
|
|
g_free (accel);
|
|
|
|
}
|
|
|
|
else
|
2005-09-10 16:02:38 +00:00
|
|
|
{
|
2006-08-15 02:09:09 -05:00
|
|
|
_moo_accel_button_set_accel (button, "");
|
2005-09-10 16:02:38 +00:00
|
|
|
}
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
}
|