Logo Search packages:      
Sourcecode: kazehakase version File versions

prefs_gesture.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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, 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.
 */

#include "prefs_gesture.h"

#include <ctype.h>
#include <glib/gi18n.h>
#include "kazehakase.h"
#include "kz-window.h"
#include "kz-gesture.h"
#include "kz-input-event-box.h"

#define DATA_KEY "KzPrefsGesture::info"

enum
{
      TERMINATOR = -1,
      COLUMN_ACTION,
      COLUMN_GESTURE,
      N_COLUMNS
};


typedef struct _KzPrefsGesture
{
      GtkWidget    *main_vbox;
      GtkWidget    *use_gesture_check;

      GtkWidget    *treeview;
      GtkTreeStore *treestore;

      GtkWidget    *edit_area;
      GtkWidget    *up, *down, *left, *right, *bs;
      GtkWidget    *entry;

      KzGesture    *gesture;
} KzPrefsGesture;


static GtkWidget *prefs_gesture_create   (void);
static void       prefs_gesture_response (GtkWidget *widget,
                                gint       response);

static KzPrefsWinPageEntry prefs_entry =
{
      path:            N_("/Gesture"),
      priority_hint:   0,
      ui_level:        ~KZ_UI_LEVEL_BEGINNER,
      create:          prefs_gesture_create,
      response:        prefs_gesture_response,
};


static void
prefs_gesture_destroy (gpointer data)
{
      KzPrefsGesture *self = data;
      
      if (self->treestore)
      {
            g_object_unref(self->treestore);
            self->treestore = NULL;
      }

      g_free(self);
}


static gboolean
valid_char (gint c)
{
      gint valid[] = {
            'U', 'D', 'L', 'R',
      };
      gint src;
      guint i;

      src = toupper(c);

      for (i = 0; i < G_N_ELEMENTS(valid); i++)
      {
            if (valid[i] == toupper(c))
                  return TRUE;
      }

      return FALSE;
}


static gint
get_last_char (KzPrefsGesture *self)
{
      const gchar *text = gtk_entry_get_text(GTK_ENTRY(self->entry));
      gsize len;
      gint i;

      g_return_val_if_fail(text, 0);

      len = strlen(text);
      if (len <= 0) return 0;

      /* FIXME!: validate the character? */
      for (i = len - 1; len > 0 && i >= 0; i--)
            if (!isspace(text[i])) return text[i];

      return 0;
}


static void
reduce_motion_str (gchar *str)
{
      gint i, len;

      g_return_if_fail(str);

      len = strlen(str);

      for (i = 0; i < len; i++)
      {
            if (!valid_char(str[i]))
            {
                  memmove(str + i, str + i + 1, (len - i + 1));
                  len--;
                  i--;
            }
      }
}


static void
append_motion (KzPrefsGesture *self, gint motion)
{
      const gchar *text = gtk_entry_get_text(GTK_ENTRY(self->entry));
      gchar *newstr;
      gsize size, len;
      gint c = 0, i;

      g_return_if_fail(text);

      len = strlen(text);
      size = strlen(text) + 2;

      for (i = len - 1; len > 0 && i >= 0; i--)
      {
            if (!isspace(text[i]))
            {
                  c = text[i];
                  break;
            }
      }

      if (g_ascii_toupper(c) == motion)
            return;

      newstr = g_alloca(size);
      g_return_if_fail(newstr);

      memcpy(newstr, text, size - 2);
      newstr[size - 2] = motion;
      newstr[size - 1] = '\0';

      gtk_entry_set_text(GTK_ENTRY(self->entry), newstr);
}


static void
remove_last_motion (KzPrefsGesture *self)
{
      const gchar *text = gtk_entry_get_text(GTK_ENTRY(self->entry));
      gchar *newstr;
      gsize size, len;
      gint i;

      g_return_if_fail(text);

      len = strlen(text);
      for (i = len - 1; len > 0 && i >= 0; i--)
            if (!isspace(text[i])) break;

      if (i > 0)
            size = i + 1;
      else
            size = 1;

      newstr = g_alloca(size);
      g_return_if_fail(newstr);

      memcpy(newstr, text, size - 1);
      newstr[size - 1] = '\0';

      gtk_entry_set_text(GTK_ENTRY(self->entry), newstr);
}


static void
reset_gesture_items (KzPrefsGesture *self)
{
      GtkWidget *top;
      KzWindow *kz;
      GList *list, *node;
      GtkActionGroup *actions;

      g_return_if_fail(self);

      top = gtk_widget_get_toplevel(self->main_vbox);
      if (!GTK_IS_WINDOW(top)) return;

      kz = KZ_WINDOW(gtk_window_get_transient_for(GTK_WINDOW(top)));
      if (!KZ_IS_WINDOW(kz)) return;

      /* clear */
      gtk_tree_store_clear(self->treestore);

      /* set new list */
      actions = kz->actions;
      list = gtk_action_group_list_actions(actions);

      for (node = list; node; node = g_list_next(node))
      {
            GtkAction *action = node->data;
            const gchar *name = gtk_action_get_name(action);
            gchar *gesture;
            GtkTreeIter iter;

            gesture = KZ_CONF_GET_STR("Gesture", name);
            if (gesture)
                  reduce_motion_str(gesture);

            gtk_tree_store_append(self->treestore, &iter, NULL);
            gtk_tree_store_set(self->treestore, &iter,
                           COLUMN_ACTION,  name,
                           COLUMN_GESTURE, gesture,
                           TERMINATOR);

            g_free(gesture);
      }

      g_list_free(list);
}


static void
cb_realize (GtkWidget *widget, KzPrefsGesture *self)
{
      reset_gesture_items(self);
      g_signal_handlers_disconnect_by_func(widget,
                                   G_CALLBACK(cb_realize), self);
}


static void
cb_selection_changed (GtkTreeSelection *selection, KzPrefsGesture *self)
{
      GtkTreeModel *model;
      GtkTreeIter iter;
      gchar *gesture = NULL;

      g_return_if_fail(self);

      if (!gtk_tree_selection_get_selected(selection, &model, &iter))
      {
            gtk_widget_set_sensitive(self->edit_area, FALSE);
            gtk_entry_set_text(GTK_ENTRY(self->entry), "");
            return;
      }

      gtk_widget_set_sensitive(self->edit_area, TRUE);

      gtk_tree_model_get(model, &iter,
                     COLUMN_GESTURE, &gesture,
                     TERMINATOR);
      if (!gesture)
            gesture = g_strdup("");

      gtk_entry_set_text(GTK_ENTRY(self->entry), gesture);

      g_free(gesture);
}


static void
set_sensitive_edit_buttons (KzPrefsGesture *self)
{
      const gchar *text = gtk_entry_get_text(GTK_ENTRY(self->entry));
      gsize len;
      gint c = 0;

      g_return_if_fail(text);

      gtk_widget_set_sensitive(self->up,    TRUE);
      gtk_widget_set_sensitive(self->down,  TRUE);
      gtk_widget_set_sensitive(self->left,  TRUE);
      gtk_widget_set_sensitive(self->right, TRUE);
      gtk_widget_set_sensitive(self->bs,    TRUE);

      len = strlen(text);
      if (len <= 0)
      {
            gtk_widget_set_sensitive(self->bs, FALSE);
            return;
      }

      c = get_last_char(self);

      switch (c)
      {
      case 'U':
            gtk_widget_set_sensitive(self->up, FALSE);
            break;
      case 'D':
            gtk_widget_set_sensitive(self->down, FALSE);
            break;
      case 'L':
            gtk_widget_set_sensitive(self->left, FALSE);
            break;
      case 'R':
            gtk_widget_set_sensitive(self->right, FALSE);
            break;
      default:
            break;
      }
}


static void
cb_up_clicked (GtkButton *button, KzPrefsGesture *self)
{
      append_motion(self, 'U');
}


static void
cb_down_clicked (GtkButton *button, KzPrefsGesture *self)
{
      append_motion(self, 'D');
}


static void
cb_left_clicked (GtkButton *button, KzPrefsGesture *self)
{
      append_motion(self, 'L');
}


static void
cb_right_clicked (GtkButton *button, KzPrefsGesture *self)
{
      append_motion(self, 'R');
}


static void
cb_bs_clicked (GtkButton *button, KzPrefsGesture *self)
{
      remove_last_motion(self);
}


static gboolean
cb_motion_notify (GtkWidget *widget,
              GdkEventMotion *event,
              KzPrefsGesture *self)
{
      gint x, y;

      g_return_val_if_fail(self, FALSE);

      gtk_widget_get_pointer (GTK_WIDGET(widget), &x, &y);

      if (kz_gesture_is_started(self->gesture))
      {
            kz_gesture_update_position(self->gesture, x, y);
      }

      return FALSE;
}


static gboolean
cb_button_release (GtkWidget *widget,
               GdkEventButton *event,
               KzPrefsGesture *self)
{
        if (gdk_pointer_is_grabbed ())
        {
                gdk_pointer_ungrab (gtk_get_current_event_time ());
        }
      g_signal_handlers_disconnect_by_func(widget,
                                   G_CALLBACK(cb_button_release),
                                   self);
      g_signal_handlers_disconnect_by_func(widget,
                                   G_CALLBACK(cb_motion_notify),
                                   self);

      g_object_unref(self->gesture);
      self->gesture = NULL;

      return FALSE;
}


static void
cb_gesture_stack_motion (KzGesture *gesture, KzGestureMotion motion,
                   KzPrefsGesture *self)
{
      gchar buf[256];

      kz_gesture_create_gesture_string(gesture, buf, G_N_ELEMENTS(buf));

      gtk_entry_set_text(GTK_ENTRY(self->entry), buf);
}


static gboolean
cb_button_press (GtkButton *button, GdkEventButton *event,
             KzPrefsGesture *self)
{
      if (event->button == 3)
      {
            static GdkCursor *cursor;
            GtkWidget *top = gtk_widget_get_toplevel(GTK_WIDGET(button));
            gint x, y;

            gtk_widget_get_pointer (GTK_WIDGET(top), &x, &y);

            self->gesture = kz_gesture_new();
            g_signal_connect(self->gesture, "stack_motion",
                         G_CALLBACK(cb_gesture_stack_motion), self);
            kz_gesture_start(self->gesture, 0, x, y);

            if (!cursor) cursor = gdk_cursor_new (GDK_HAND1);
            gdk_pointer_grab (top->window,
                          FALSE,
                          GDK_POINTER_MOTION_MASK |
                          GDK_BUTTON_RELEASE_MASK |
                          GDK_BUTTON_PRESS_MASK,
                          NULL, cursor, gtk_get_current_event_time ());
            g_signal_connect(top, "button-release-event",
                         G_CALLBACK(cb_button_release), self);
            g_signal_connect(top, "motion-notify-event",
                         G_CALLBACK(cb_motion_notify), self);

            return TRUE;
      }
      return FALSE;
}


static void
cb_insert_text (GtkEditable *editable,
            const gchar *text,
            gint length,
            gint *position,
            KzPrefsGesture *self)
{
      int i, j = 0, last = 0;
      gchar *result = g_alloca(sizeof(gchar) * length + 1);

      result[0] = '\0';

      last = get_last_char(self);

      for (i = 0; i < length; i++)
      {
            gint c = toupper(text[i]);

            if (valid_char(c) && (!last || last != c))
            {
                  result[j++] = c;
                  last = c;
            }
      }

      result[j] = '\0';
      length = j;

      if (length > 0)
      {
            g_signal_handlers_block_by_func(editable, 
                                    G_CALLBACK(cb_insert_text),
                                    self);
            gtk_editable_insert_text(editable, result, length, position);
            g_signal_handlers_unblock_by_func(editable, 
                                      G_CALLBACK(cb_insert_text),
                                      self);
      }

      g_signal_stop_emission_by_name (editable, "insert_text"); 
}


static void
cb_entry_changed (GtkEntry *entry, KzPrefsGesture *self)
{
      g_return_if_fail(self);

      set_sensitive_edit_buttons(self);
}


static void
cb_use_gesture_toggled(GtkToggleButton *button, KzPrefsGesture *self)
{
      gtk_widget_set_sensitive(self->treeview,
                         gtk_toggle_button_get_active(button));
      gtk_widget_set_sensitive(self->edit_area,
                         gtk_toggle_button_get_active(button));
}

typedef struct _CheckDupl
{
      KzPrefsGesture *self;
      const gchar *action;
      const gchar *gesture;
      gboolean valid;
} CheckDupl;


static void
cb_response (GtkDialog *dialog, gint response, CheckDupl *dupl)
{
      if (response == GTK_RESPONSE_NO)
            dupl->valid = FALSE;
}


static gboolean
check_dupl_func (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
             gpointer data)
{
      CheckDupl *dupl = data;

      gchar *action = NULL, *gesture = NULL;

      gtk_tree_model_get(model, iter,
                     COLUMN_ACTION,  &action,
                     COLUMN_GESTURE, &gesture,
                     TERMINATOR);

      if (action && dupl->action && strcmp(action, dupl->action) &&
          gesture && *gesture && dupl->gesture && !strcmp(gesture, dupl->gesture))
      {
            GtkWidget *top = gtk_widget_get_toplevel(dupl->self->main_vbox);
            GtkWidget *dialog;

            dialog = gtk_message_dialog_new
                        (GTK_WINDOW(top),
                         GTK_DIALOG_DESTROY_WITH_PARENT,
                         GTK_MESSAGE_QUESTION,
                         GTK_BUTTONS_YES_NO,
                         _("Specified gesture is duplicated with \"%s\" action. "
                           "Replace?"), action);
            g_signal_connect(dialog, "response",
                         G_CALLBACK(cb_response), dupl);
            gtk_dialog_run(GTK_DIALOG(dialog));
            gtk_widget_destroy(dialog);

            if (dupl->valid)
                  gtk_tree_store_set(GTK_TREE_STORE(model), iter,
                                 COLUMN_GESTURE, "",
                                 TERMINATOR);
            else
                  return TRUE;
      }

      g_free(gesture);
      g_free(action);

      return FALSE;
}


static void
cb_apply_button_clicked (GtkButton *button, KzPrefsGesture *self)
{
      const gchar *str = gtk_entry_get_text(GTK_ENTRY(self->entry));
      const gchar *action;
      gchar *old_gesture = NULL, *new_gesture = g_strdup(str);
      GtkTreeSelection *selection;
      GtkTreeModel *model;
      GtkTreeIter iter;
      CheckDupl dupl;

      g_return_if_fail(self);

      reduce_motion_str(new_gesture);

      selection= gtk_tree_view_get_selection(GTK_TREE_VIEW(self->treeview));
      if (!gtk_tree_selection_get_selected(selection, &model, &iter)) return;

      gtk_tree_model_get(model, &iter,
                     COLUMN_ACTION,  &action,
                     COLUMN_GESTURE, &old_gesture,
                     TERMINATOR);

      if (old_gesture)
      {
            reduce_motion_str(old_gesture);
            if (!strcmp(old_gesture, new_gesture))
                  goto ERROR;
      }

      dupl.self    = self;
      dupl.action  = action;
      dupl.gesture = new_gesture;
      dupl.valid   = TRUE;

      gtk_tree_model_foreach(model, check_dupl_func, &dupl);

      if (dupl.valid)
            gtk_tree_store_set(self->treestore, &iter,
                           COLUMN_GESTURE, new_gesture,
                           TERMINATOR);

ERROR:
      g_free(old_gesture);
      g_free(new_gesture);
}


static void
cb_clear_button_clicked (GtkButton *button, KzPrefsGesture *self)
{
      g_return_if_fail(self);

      gtk_entry_set_text(GTK_ENTRY(self->entry), "");
}


static GtkWidget *
prefs_gesture_create (void)
{
      KzPrefsGesture *self = g_new0(KzPrefsGesture, 1);
      GtkWidget *main_vbox, *swin;
      GtkWidget *label, *check, *frame, *frame_vbox;
      GtkTreeModel *model;
      GtkTreeView *treeview;
      GtkTreeSortable *sortable;
      GtkTreeViewColumn *col;
      GtkCellRenderer *renderer;
      GtkWidget *table, *hbox, *vbox, *button, *arrow, *entry, *ebox;
      gboolean use_gesture = TRUE;

      self->gesture = NULL;


      main_vbox = gtk_vbox_new(FALSE, 0);
      self->main_vbox = main_vbox;
      g_object_set_data_full(G_OBJECT(main_vbox), DATA_KEY,
                         self, (GDestroyNotify) prefs_gesture_destroy);
      g_signal_connect(main_vbox, "realize",
                   G_CALLBACK(cb_realize), self);

      label = kz_prefs_ui_utils_create_title(_("Gesture"));
      gtk_box_pack_start(GTK_BOX(main_vbox), label,
                     FALSE, FALSE, 0);
      gtk_widget_show(label);

      KZ_CONF_GET("Gesture", "use_gesture", use_gesture, BOOL);
      self->use_gesture_check = check =
            gtk_check_button_new_with_label(_("Use gestures"));
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check),
                             TRUE);
      g_signal_connect(check, "toggled",
                   G_CALLBACK(cb_use_gesture_toggled), self);
      frame = gtk_frame_new("");
      gtk_frame_set_label_widget(GTK_FRAME(frame), check);
      gtk_frame_set_label_align(GTK_FRAME(frame), 0.03, 0.5);
      gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
      gtk_box_pack_start(GTK_BOX(main_vbox), frame, TRUE, TRUE, 2);
      gtk_widget_show(frame);
      gtk_widget_show(check);

      frame_vbox = gtk_vbox_new(FALSE, 0);
      gtk_container_set_border_width(GTK_CONTAINER(frame_vbox), 4);
      gtk_container_add(GTK_CONTAINER(frame), frame_vbox);
      gtk_widget_show(frame_vbox);

      /*
       *  Tree view
       */
      self->treestore = gtk_tree_store_new(3,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING,
                                   G_TYPE_STRING);
      model = GTK_TREE_MODEL(self->treestore);
      sortable = GTK_TREE_SORTABLE(self->treestore);
      gtk_tree_sortable_set_sort_column_id(sortable, 0, GTK_SORT_ASCENDING);
      reset_gesture_items (self);


      swin = gtk_scrolled_window_new(NULL, NULL);
      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin),
                               GTK_POLICY_AUTOMATIC,
                               GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swin),
                                  GTK_SHADOW_IN);
      gtk_container_set_border_width(GTK_CONTAINER(swin), 5);
      gtk_box_pack_start(GTK_BOX(frame_vbox), swin, TRUE, TRUE, 0);
      gtk_widget_show(swin);

      self->treeview = gtk_tree_view_new_with_model(model);
      treeview = GTK_TREE_VIEW(self->treeview);
      gtk_tree_view_set_rules_hint(treeview, TRUE);
      gtk_tree_selection_set_mode(gtk_tree_view_get_selection(treeview),
                            GTK_SELECTION_BROWSE);
      g_signal_connect(gtk_tree_view_get_selection(treeview), "changed",
                   G_CALLBACK(cb_selection_changed), self);

      renderer = gtk_cell_renderer_text_new();
      g_object_set(G_OBJECT(renderer), "xalign", 0.0, NULL);
      gtk_tree_view_insert_column_with_attributes(treeview, -1,
                                        _("Action"), renderer,
                                        "text", COLUMN_ACTION,
                                        NULL);
      col = gtk_tree_view_get_column(treeview, 0);
      gtk_tree_view_column_set_sort_column_id(col, 0);
      gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
      gtk_tree_view_column_set_fixed_width (col, 200);
      gtk_tree_view_column_set_resizable(col, TRUE);

      renderer = gtk_cell_renderer_text_new();
      g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
      gtk_tree_view_insert_column_with_attributes(treeview, -1,
                                        _("Gesture"), renderer,
                                        "text", COLUMN_GESTURE,
                                        NULL);
      col = gtk_tree_view_get_column(treeview, 1);
      gtk_tree_view_column_set_sort_column_id(col, 1);
      gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
      gtk_tree_view_column_set_resizable(col, TRUE);

      gtk_container_add(GTK_CONTAINER(swin), self->treeview);
      gtk_widget_show(self->treeview);


      /*
       *  Edit area
       */
      hbox = gtk_hbox_new(FALSE, 0);
      self->edit_area = hbox;
      gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
      gtk_box_pack_start(GTK_BOX(frame_vbox), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);

      ebox = kz_input_event_box_new();
      gtk_box_pack_start(GTK_BOX(hbox), ebox, FALSE, FALSE, 2);
      g_signal_connect(ebox, "button-press-event",
                   G_CALLBACK(cb_button_press), self);
      gtk_widget_show(ebox);

      table = gtk_table_new(3, 3, TRUE);
      gtk_container_add(GTK_CONTAINER(ebox), table);
      gtk_widget_show(table);

      /* up button */
      button = gtk_button_new();
      self->up = button;
      arrow = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_table_attach(GTK_TABLE(table), button,
                   1, 2, 0, 1,
                   GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
                   2, 2);
      g_signal_connect(button, "clicked",
                   G_CALLBACK(cb_up_clicked), self);
      g_signal_connect(button, "button-press-event",
                   G_CALLBACK(cb_button_press), self);
      gtk_widget_show(button);

      /* left button */
      button = gtk_button_new();
      self->left = button;
      arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_table_attach(GTK_TABLE(table), button,
                   0, 1, 1, 2,
                   GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
                   2, 2);
      g_signal_connect(button, "clicked",
                   G_CALLBACK(cb_left_clicked), self);
      g_signal_connect(button, "button-press-event",
                   G_CALLBACK(cb_button_press), self);
      gtk_widget_show(button);

      /* back space button */
      button = gtk_button_new();
      self->bs = button;
      label = gtk_label_new_with_mnemonic("_BS");
      gtk_label_set_mnemonic_widget(GTK_LABEL(label), button);
      gtk_container_add(GTK_CONTAINER(button), label);
      gtk_widget_show(label);
      gtk_table_attach(GTK_TABLE(table), button,
                   1, 2, 1, 2,
                   GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
                   2, 2);
      g_signal_connect(button, "clicked",
                   G_CALLBACK(cb_bs_clicked), self);
      g_signal_connect(button, "button-press-event",
                   G_CALLBACK(cb_button_press), self);
      gtk_widget_show(button);

      /* right button */
      button = gtk_button_new();
      self->right = button;
      arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_table_attach(GTK_TABLE(table), button,
                   2, 3, 1, 2,
                   GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
                   2, 2);
      g_signal_connect(button, "clicked",
                   G_CALLBACK(cb_right_clicked), self);
      g_signal_connect(button, "button-press-event",
                   G_CALLBACK(cb_button_press), self);
      gtk_widget_show(button);

      /* down button */
      button = gtk_button_new();
      self->down = button;
      arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_table_attach(GTK_TABLE(table), button,
                   1, 2, 2, 3,
                   GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
                   2, 2);
      g_signal_connect(button, "clicked",
                   G_CALLBACK(cb_down_clicked), self);
      g_signal_connect(button, "button-press-event",
                   G_CALLBACK(cb_button_press), self);
      gtk_widget_show(button);

      /* right side of edit area */
      vbox = gtk_vbox_new(FALSE, 0);
      gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 2);
      gtk_widget_show(vbox);

      /* description */
      label = gtk_label_new(_("Press right mouse button on edit button "
                        "to start to caputure gesture sequence."));
      gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
      gtk_box_pack_start(GTK_BOX(vbox), label,
                     FALSE, FALSE, 5);
      gtk_widget_show(label);

      /* button box */
      hbox = gtk_hbutton_box_new();
      gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
      gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
      gtk_widget_show(hbox);

      button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
      gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 2);
      g_signal_connect(button, "clicked",
                   G_CALLBACK(cb_apply_button_clicked), self);
      gtk_widget_show(button);

      button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
      gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 2);
      g_signal_connect(button, "clicked",
                   G_CALLBACK(cb_clear_button_clicked), self);
      gtk_widget_show(button);

      /* entry */
      entry = gtk_entry_new();
      self->entry = entry;
      gtk_box_pack_end(GTK_BOX(vbox), entry, FALSE, FALSE, 2);
      g_signal_connect(entry, "insert-text",
                   G_CALLBACK(cb_insert_text), self);
      g_signal_connect(entry, "changed",
                   G_CALLBACK(cb_entry_changed), self);
      gtk_widget_show(entry);

      gtk_widget_set_sensitive(self->edit_area, FALSE);

      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check),
                             use_gesture);
      return main_vbox;
}


static gboolean
apply_config_func (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
               gpointer data)
{
      gchar *action = NULL, *gesture = NULL, *old_gesture;

      gtk_tree_model_get(model, iter,
                     COLUMN_ACTION,  &action,
                     COLUMN_GESTURE, &gesture,
                     TERMINATOR);

      old_gesture = KZ_CONF_GET_STR("Gesture", action);

      /* didn't change gestures */
      if ((!old_gesture || !*old_gesture) && (!gesture || !*gesture))
            goto ERROR;
      if (old_gesture && *old_gesture && !strcmp(gesture, old_gesture))
            goto ERROR;

      /* apply */
      if (!gesture)
            gesture = g_strdup("");
      KZ_CONF_SET_STR("Gesture", action, gesture);

ERROR:
      g_free(action);
      g_free(gesture);
      g_free(old_gesture);

      return FALSE;
}


static void
prefs_gesture_response (GtkWidget *widget, gint response)
{
      gboolean use_gesture = TRUE;
      KzPrefsGesture *self = g_object_get_data(G_OBJECT(widget), DATA_KEY);

      g_return_if_fail(self);

      switch (response) {
      case GTK_RESPONSE_ACCEPT:
      case GTK_RESPONSE_APPLY:
            gtk_tree_model_foreach(GTK_TREE_MODEL(self->treestore),
                               apply_config_func, self);

            use_gesture = gtk_toggle_button_get_active
                        (GTK_TOGGLE_BUTTON(self->use_gesture_check));
            KZ_CONF_SET("Gesture", "use_gesture", use_gesture, BOOL);
            
            break;
      case GTK_RESPONSE_REJECT:
            break;
      case KZ_RESPONSE_UI_LEVEL_MEDIUM:
            break;
      case KZ_RESPONSE_UI_LEVEL_EXPERT:
            break;
      case KZ_RESPONSE_UI_LEVEL_CUSTOM:
            break;
      default:
            break;
      }
}


KzPrefsWinPageEntry *
prefs_gesture_get_entry (gint idx)
{
      if (idx == 0)
            return &prefs_entry;
      else
            return NULL;
}

Generated by  Doxygen 1.6.0   Back to index