brian's button autorepeat core code.
authorCarsten Haitzler <raster@rasterman.com>
Sun, 24 Jan 2010 01:53:37 +0000 (01:53 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Sun, 24 Jan 2010 01:53:37 +0000 (01:53 +0000)
SVN revision: 45504

data/themes/default.edc
src/bin/test_button.c
src/lib/elm_button.c

index 1efb6b8..a7b8c29 100644 (file)
@@ -737,6 +737,11 @@ collections {
            name:   "button_click";
            signal: "mouse,down,1";
            source: "over2";
+           action: SIGNAL_EMIT "elm,action,press" "";
+           after: "button_click_anim";
+        }
+        program {
+           name:   "button_click_anim";
            action: STATE_SET "clicked" 0.0;
            target: "button_image";
         }
@@ -744,6 +749,11 @@ collections {
            name:   "button_unclick";
            signal: "mouse,up,1";
            source: "over2";
+           action: SIGNAL_EMIT "elm,action,unpress" "";
+           after: "button_unclick_anim";
+        }
+        program {
+           name:   "button_unclick_anim";
            action: STATE_SET "default" 0.0;
            target: "button_image";
         }
index 489bebb..f154e77 100644 (file)
@@ -1,5 +1,17 @@
 #include <Elementary.h>
 #ifndef ELM_LIB_QUICKLAUNCH
+static void
+_bt_repeated(void *data, Evas_Object *obj, void *event_info)
+{
+       static int count;
+       char buf[16];
+
+       snprintf(buf, sizeof(buf), "count=%d", count++);
+       if (count >= 10000)
+               count = 0;
+       elm_button_label_set(obj, buf);
+}
+
 void
 test_button(void *data, Evas_Object *obj, void *event_info)
 {
@@ -68,6 +80,10 @@ test_button(void *data, Evas_Object *obj, void *event_info)
    bt = elm_button_add(win);
    elm_button_label_set(bt, "Label Only");
    elm_box_pack_end(bx, bt);
+   evas_object_smart_callback_add(bt, "repeated", _bt_repeated, NULL);
+   elm_button_autorepeat_set(bt, 1);
+   elm_button_autorepeat_initital_timeout_set(bt, 2.0);
+   elm_button_autorepeat_gap_timeout_set(bt, 0.5);
    evas_object_show(bt);
 
    ic = elm_icon_add(win);
index 1e6443f..ab87d14 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ *
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
 #include <Elementary.h>
 #include "elm_priv.h"
 
@@ -14,6 +18,12 @@ struct _Widget_Data
 {
    Evas_Object *btn, *icon;
    const char *label;
+
+   Eina_Bool autorepeat;
+   Eina_Bool repeating;
+   double ar_threshold;
+   double ar_interval;
+   Ecore_Timer *timer;
 };
 
 static void _del_hook(Evas_Object *obj);
@@ -23,6 +33,8 @@ static void _sizing_eval(Evas_Object *obj);
 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
 static void _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_pressed(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_unpressed(void *data, Evas_Object *obj, const char *emission, const char *source);
 static void _on_focus_hook(void *data, Evas_Object *obj);
 
 static void
@@ -124,6 +136,61 @@ _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *
    Widget_Data *wd = elm_widget_data_get(data);
    if (!wd) return;
    evas_object_smart_callback_call(data, "clicked", NULL);
+   _signal_unpressed(data, obj, emission, source); /* safe guard when the theme does not emit the 'unpress' signal */
+}
+
+static int
+_autorepeat_send(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+
+   evas_object_smart_callback_call(data, "repeated", NULL);
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static int
+_autorepeat_initial_send(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+
+   _autorepeat_send(data);
+   wd->timer = ecore_timer_add(wd->ar_interval, _autorepeat_send, data);
+   wd->repeating = 1;
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_signal_pressed(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+
+   if (wd->autorepeat)
+     {
+       if (wd->ar_threshold <= 0.0)
+         _autorepeat_initial_send(data); /* call immediately */
+       else
+         wd->timer = ecore_timer_add(wd->ar_threshold, _autorepeat_initial_send, data);
+     }
+}
+
+static void
+_signal_unpressed(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   evas_object_smart_callback_call(data, "unpressed", NULL);
+
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+   wd->repeating = 0;
 }
 
 /**
@@ -156,6 +223,10 @@ elm_button_add(Evas_Object *parent)
    _elm_theme_set(wd->btn, "button", "base", "default");
    edje_object_signal_callback_add(wd->btn, "elm,action,click", "",
                                    _signal_clicked, obj);
+   edje_object_signal_callback_add(wd->btn, "elm,action,press", "",
+                                   _signal_pressed, obj);
+   edje_object_signal_callback_add(wd->btn, "elm,action,unpress", "",
+                                   _signal_unpressed, obj);
    elm_widget_resize_object_set(obj, wd->btn);
 
    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
@@ -256,3 +327,81 @@ elm_button_style_set(Evas_Object *obj, const char *style)
 {
    elm_widget_style_set(obj, style);
 }
+
+/**
+ * Turn on/off the autorepeat event generated when the user keeps pressing on the button
+ *
+ * @param obj The button object
+ * @param on  A bool to turn on/off the event
+ *
+ * @ingroup Button
+ */
+EAPI void
+elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->timer) {
+          ecore_timer_del(wd->timer);
+          wd->timer = NULL;
+   }
+   wd->autorepeat = on;
+}
+
+/**
+ * Set the initial timeout before the autorepeat event is generated
+ *
+ * @param obj The button object
+ * @param t   Timeout
+ *
+ * @ingroup Button
+ */
+EAPI void
+elm_button_autorepeat_initital_timeout_set(Evas_Object *obj, double t)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->ar_threshold == t)
+     return;
+
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+
+   wd->ar_threshold = t;
+}
+
+/**
+ * Set the interval between each generated autorepeat event
+ *
+ * @param obj The button object
+ * @param t   Interval
+ *
+ * @ingroup Button
+ */
+EAPI void         
+elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->ar_interval == t)
+     return;
+
+   if (wd->timer)
+     {
+       ecore_timer_del(wd->timer);
+       wd->timer = NULL;
+     }
+
+   wd->ar_interval = t;
+   if (wd->repeating)
+     {
+       wd->timer = ecore_timer_add(t, _autorepeat_send, obj);
+     }
+}
+