diff options
| author | MenTaLguY <mental@rydia.net> | 2006-01-16 02:36:01 +0000 |
|---|---|---|
| committer | mental <mental@users.sourceforge.net> | 2006-01-16 02:36:01 +0000 |
| commit | 179fa413b047bede6e32109e2ce82437c5fb8d34 (patch) | |
| tree | a5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/shortcuts.cpp | |
| download | inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip | |
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/shortcuts.cpp')
| -rw-r--r-- | src/shortcuts.cpp | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp new file mode 100644 index 000000000..047928071 --- /dev/null +++ b/src/shortcuts.cpp @@ -0,0 +1,195 @@ +#define __SP_SHORTCUTS_C__ + +/** \file + * Keyboard shortcut processing. + */ +/* + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * MenTaLguY <mental@rydia.net> + * bulia byak <buliabyak@users.sf.net> + * Peter Moulder <pmoulder@mail.csse.monash.edu.au> + * + * Copyright (C) 2005 Monash University + * Copyright (C) 2005 MenTaLguY <mental@rydia.net> + * + * You may redistribute and/or modify this file 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gdk/gdkkeys.h> +#include <gdk/gdkkeysyms.h> + +#include "helper/action.h" +#include "shortcuts.h" +#include "verbs.h" +#include "xml/node-iterators.h" +#include "xml/repr.h" + +using namespace Inkscape; + +static void sp_shortcut_set(unsigned int const shortcut, Inkscape::Verb *const verb, bool const is_primary); + +static void set_shortcuts_xml(XML::Document const *doc); + +/* Returns true if action was performed */ + +bool +sp_shortcut_invoke(unsigned int shortcut, Inkscape::UI::View::View *view) +{ + Inkscape::Verb *verb = sp_shortcut_get_verb(shortcut); + if (verb) { + SPAction *action = verb->get_action(view); + if (action) { + sp_action_perform(action, NULL); + return true; + } + } + return false; +} + +static GHashTable *verbs = NULL; +static GHashTable *primary_shortcuts = NULL; + +extern char const shortcuts_default_xml[]; + +static void +sp_shortcut_init() +{ + verbs = g_hash_table_new(NULL, NULL); + primary_shortcuts = g_hash_table_new(NULL, NULL); + + XML::Document *shortcuts=sp_repr_read_mem(shortcuts_default_xml, strlen(shortcuts_default_xml), NULL); + if (shortcuts) { + set_shortcuts_xml(shortcuts); + GC::release(shortcuts); + } else { + g_error("Unable to parse default shortcuts"); + } +} + +static void set_shortcuts_xml(XML::Document const *doc) { + XML::Node const *root=doc->root(); + g_return_if_fail(!strcmp(root->name(), "keybindings")); + XML::NodeConstSiblingIterator iter=root->firstChild(); + for ( ; iter ; ++iter ) { + bool is_primary; + + if (!strcmp(iter->name(), "primary")) { + is_primary = true; + } else if (!strcmp(iter->name(), "secondary")) { + is_primary = false; + } else { + g_warning("Unknown key binding type %s", iter->name()); + continue; + } + + gchar const *verb_name=iter->attribute("verb"); + if (!verb_name) { + g_warning("Missing verb name for shortcut"); + continue; + } + + gchar const *keyval_name=iter->attribute("keyval"); + if (!keyval_name) { + g_warning("Missing keyval for %s", verb_name); + continue; + } + guint keyval=gdk_keyval_from_name(keyval_name); + if (keyval == GDK_VoidSymbol) { + g_warning("Unknown keyval %s for %s", keyval_name, verb_name); + continue; + } + + guint modifiers=0; + + gchar const *modifiers_string=iter->attribute("modifiers"); + if (modifiers_string) { + gchar const *iter=modifiers_string; + while (*iter) { + size_t length=strcspn(iter, ","); + gchar *mod=g_strndup(iter, length); + if (!strcmp(mod, "control")) { + modifiers |= SP_SHORTCUT_CONTROL_MASK; + } else if (!strcmp(mod, "shift")) { + modifiers |= SP_SHORTCUT_SHIFT_MASK; + } else if (!strcmp(mod, "alt")) { + modifiers |= SP_SHORTCUT_ALT_MASK; + } else { + g_warning("Unknown modifier %s for %s", mod, verb_name); + } + g_free(mod); + iter += length; + if (*iter) iter++; + } + } + + sp_shortcut_set(keyval | modifiers, + Inkscape::Verb::getbyid(verb_name), + is_primary); + } +} + +/** + * Adds a keyboard shortcut for the given verb. + * (Removes any existing binding for the given shortcut, including appropriately + * adjusting sp_shortcut_get_primary if necessary.) + * + * \param is_primary True iff this is the shortcut to be written in menu items or buttons. + * + * \post sp_shortcut_get_verb(shortcut) == verb. + * \post !is_primary or sp_shortcut_get_primary(verb) == shortcut. + */ +static void +sp_shortcut_set(unsigned int const shortcut, Inkscape::Verb *const verb, bool const is_primary) +{ + if (!verbs) sp_shortcut_init(); + + Inkscape::Verb *old_verb = (Inkscape::Verb *)(g_hash_table_lookup(verbs, GINT_TO_POINTER(shortcut))); + g_hash_table_insert(verbs, GINT_TO_POINTER(shortcut), (gpointer)(verb)); + + /* Maintain the invariant that sp_shortcut_get_primary(v) returns either 0 or a valid shortcut for v. */ + if (old_verb && old_verb != verb) { + unsigned int const old_primary = (unsigned int)GPOINTER_TO_INT(g_hash_table_lookup(primary_shortcuts, (gpointer)old_verb)); + + if (old_primary == shortcut) { + g_hash_table_insert(primary_shortcuts, (gpointer)old_verb, GINT_TO_POINTER(0)); + } + } + + if (is_primary) { + g_hash_table_insert(primary_shortcuts, (gpointer)(verb), GINT_TO_POINTER(shortcut)); + } +} + +Inkscape::Verb * +sp_shortcut_get_verb(unsigned int shortcut) +{ + if (!verbs) sp_shortcut_init(); + return (Inkscape::Verb *)(g_hash_table_lookup(verbs, GINT_TO_POINTER(shortcut))); +} + +unsigned int +sp_shortcut_get_primary(Inkscape::Verb *verb) +{ + if (!primary_shortcuts) sp_shortcut_init(); + return (unsigned int)GPOINTER_TO_INT(g_hash_table_lookup(primary_shortcuts, + (gpointer)(verb))); +} + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : |
