jaehwan pushed a commit to branch master.
commit d4008a3b97841d28d2f2c20da6289573e20b8c84
Author: Jaehwan Kim <[email protected]>
Date: Wed Apr 10 20:06:41 2013 +0900
Add the API elm_scroller_single_direction_set/get.
This sets how the content is scrolled.
---
ChangeLog | 5 +++
NEWS | 1 +
src/lib/elm_interface_scrollable.c | 65 ++++++++++++++++++----------
src/lib/elm_interface_scrollable.h | 22 +++++-----
src/lib/elm_scroller.c | 42 ++++++++++++++++++
src/lib/elm_scroller.h | 89 ++++++++++++++++++++++++++++----------
6 files changed, 166 insertions(+), 58 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 3a4e4e5..6a8a031 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1237,3 +1237,8 @@
2013-04-10 Jaehwan Kim
* Fix the region_show/region_bring_in don't have a limit at a paging
movement.
+
+2013-04-10 Jaehwan Kim
+
+ * Add the API elm_scroller_single_direction_set/get.
+ This sets how the content is scrolled.
diff --git a/NEWS b/NEWS
index 15890c6..5456b16 100644
--- a/NEWS
+++ b/NEWS
@@ -59,6 +59,7 @@ Additions:
* Add convenient macros - elm_object_translatable_part_text_set(),
elm_object_item_translatable_part_text_set().
* Add the API elm_scroller_page_scroll_limit_set/get.
* Add elm_mapbuf_auto_set/get.
+ * Add the API elm_scroller_single_direction_set/get.
Improvements:
diff --git a/src/lib/elm_interface_scrollable.c
b/src/lib/elm_interface_scrollable.c
index 6698526..0710f27 100644
--- a/src/lib/elm_interface_scrollable.c
+++ b/src/lib/elm_interface_scrollable.c
@@ -2910,7 +2910,6 @@ _elm_scroll_mouse_move_event_cb(void *data,
Elm_Scrollable_Smart_Interface_Data *sid = data;
Evas_Event_Mouse_Move *ev;
Evas_Coord x = 0, y = 0;
- int dodir = 0;
if (!sid->pan_obj) return;
@@ -2977,32 +2976,50 @@ _elm_scroll_mouse_move_event_cb(void *data,
if (x < 0) x = -x;
if (y < 0) y = -y;
- if ((sid->one_direction_at_a_time) &&
- (((sid->down.dir_x) || (sid->down.dir_y))))
+ if (sid->one_direction_at_a_time)
{
- if (x > _elm_config->thumbscroll_threshold)
+ if (!((sid->down.dir_x) || (sid->down.dir_y)) &&
+ (((x * x) + (y * y)) >
+ (_elm_config->thumbscroll_threshold *
+ _elm_config->thumbscroll_threshold)))
{
- if (x > (y * 2))
+ if (sid->one_direction_at_a_time ==
+ ELM_SCROLLER_SINGLE_DIRECTION_SOFT)
{
- sid->down.dir_x = EINA_TRUE;
- sid->down.dir_y = EINA_FALSE;
- dodir++;
+ int dodir = 0;
+ if (x > (y * 2))
+ {
+ sid->down.dir_x = EINA_TRUE;
+ sid->down.dir_y = EINA_FALSE;
+ dodir++;
+ }
+ if (y > (x * 2))
+ {
+ sid->down.dir_x = EINA_FALSE;
+ sid->down.dir_y = EINA_TRUE;
+ dodir++;
+ }
+ if (!dodir)
+ {
+ sid->down.dir_x = EINA_TRUE;
+ sid->down.dir_y = EINA_TRUE;
+ }
}
- }
- if (y > _elm_config->thumbscroll_threshold)
- {
- if (y > (x * 2))
+ else if (sid->one_direction_at_a_time ==
+ ELM_SCROLLER_SINGLE_DIRECTION_HARD)
{
- sid->down.dir_x = EINA_FALSE;
- sid->down.dir_y = EINA_TRUE;
- dodir++;
+ if (x > y)
+ {
+ sid->down.dir_x = EINA_TRUE;
+ sid->down.dir_y = EINA_FALSE;
+ }
+ if (y > x)
+ {
+ sid->down.dir_x = EINA_FALSE;
+ sid->down.dir_y = EINA_TRUE;
+ }
}
}
- if (!dodir)
- {
- sid->down.dir_x = EINA_TRUE;
- sid->down.dir_y = EINA_TRUE;
- }
}
else
{
@@ -3942,7 +3959,8 @@ static void
_elm_scroll_single_direction_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
{
Elm_Scrollable_Smart_Interface_Data *sid = _pd;
- Eina_Bool single_dir = va_arg(*list, int);
+ Elm_Scroller_Single_Direction single_dir =
+ va_arg(*list, Elm_Scroller_Single_Direction);
sid->one_direction_at_a_time = single_dir;
}
@@ -3951,7 +3969,8 @@ static void
_elm_scroll_single_direction_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
{
Elm_Scrollable_Smart_Interface_Data *sid = _pd;
- Eina_Bool *ret = va_arg(*list, Eina_Bool *);
+ Elm_Scroller_Single_Direction *ret =
+ va_arg(*list, Elm_Scroller_Single_Direction *);
*ret = sid->one_direction_at_a_time;
}
@@ -4249,7 +4268,7 @@ _elm_scroll_interface_add(Eo *obj, void *_pd, va_list
*list EINA_UNUSED)
sid->bounce_horiz = EINA_TRUE;
sid->bounce_vert = EINA_TRUE;
- sid->one_direction_at_a_time = EINA_TRUE;
+ sid->one_direction_at_a_time = ELM_SCROLLER_SINGLE_DIRECTION_SOFT;
sid->momentum_animator_disabled = EINA_FALSE;
sid->bounce_animator_disabled = EINA_FALSE;
diff --git a/src/lib/elm_interface_scrollable.h
b/src/lib/elm_interface_scrollable.h
index 30a6621..48d9871 100644
--- a/src/lib/elm_interface_scrollable.h
+++ b/src/lib/elm_interface_scrollable.h
@@ -652,7 +652,7 @@ enum
* @param[out] single_dir
*
*/
-#define elm_scrollable_interface_single_direction_get(single_dir)
ELM_SCROLLABLE_INTERFACE_ID(ELM_SCROLLABLE_INTERFACE_SUB_ID_SINGLE_DIRECTION_GET),
EO_TYPECHECK(Eina_Bool *, single_dir)
+#define elm_scrollable_interface_single_direction_get(single_dir)
ELM_SCROLLABLE_INTERFACE_ID(ELM_SCROLLABLE_INTERFACE_SUB_ID_SINGLE_DIRECTION_GET),
EO_TYPECHECK(Elm_Scroller_Single_Direction *, single_dir)
/**
* @def elm_scrollable_interface_repeat_events_set
@@ -963,18 +963,19 @@ typedef struct _Elm_Scrollable_Smart_Interface_Data
Elm_Scrollable_Smart_Interface_Data;
struct _Elm_Scrollable_Smart_Interface_Data
{
- Evas_Coord x, y, w, h;
- Evas_Coord wx, wy, ww, wh; /**< Last "wanted" geometry */
+ Evas_Coord x, y, w, h;
+ Evas_Coord wx, wy, ww, wh; /**< Last "wanted" geometry */
- Evas_Object *obj;
- Evas_Object *content;
- Evas_Object *pan_obj;
- Evas_Object *edje_obj;
- Evas_Object *event_rect;
+ Evas_Object *obj;
+ Evas_Object *content;
+ Evas_Object *pan_obj;
+ Evas_Object *edje_obj;
+ Evas_Object *event_rect;
- Evas_Object *parent_widget;
+ Evas_Object *parent_widget;
- Elm_Scroller_Policy hbar_flags, vbar_flags;
+ Elm_Scroller_Policy hbar_flags, vbar_flags;
+ Elm_Scroller_Single_Direction one_direction_at_a_time;
struct
{
@@ -1084,7 +1085,6 @@ struct _Elm_Scrollable_Smart_Interface_Data
Eina_Bool momentum_animator_disabled : 1;
Eina_Bool bounce_animator_disabled : 1;
- Eina_Bool one_direction_at_a_time : 1;
Eina_Bool wheel_disabled : 1;
Eina_Bool hbar_visible : 1;
Eina_Bool vbar_visible : 1;
diff --git a/src/lib/elm_scroller.c b/src/lib/elm_scroller.c
index 3f196dd..6d61be2 100644
--- a/src/lib/elm_scroller.c
+++ b/src/lib/elm_scroller.c
@@ -924,6 +924,46 @@ elm_scroller_policy_get(const Evas_Object *obj,
}
EAPI void
+elm_scroller_single_direction_set(Evas_Object *obj,
+ Elm_Scroller_Single_Direction single_dir)
+{
+ ELM_SCROLLABLE_CHECK(obj);
+ eo_do(obj, elm_scrollable_interface_single_direction_set(single_dir));
+}
+
+static void
+_single_direction_set(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
+{
+ Elm_Scroller_Single_Direction single_dir = va_arg(*list,
Elm_Scroller_Single_Direction);
+
+ if (single_dir >= ELM_SCROLLER_SINGLE_DIRECTION_LAST)
+ return;
+
+ eo_do_super(obj, MY_CLASS,
+ elm_scrollable_interface_single_direction_set(single_dir));
+}
+
+EAPI Elm_Scroller_Single_Direction
+elm_scroller_single_direction_get(const Evas_Object *obj)
+{
+ ELM_SCROLLABLE_CHECK(obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE);
+ Elm_Scroller_Single_Direction single_dir;
+
+ eo_do((Eo *) obj,
elm_scrollable_interface_single_direction_get(&single_dir));
+ return single_dir;
+}
+
+static void
+_single_direction_get(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
+{
+ Elm_Scroller_Single_Direction *ret =
+ va_arg(*list, Elm_Scroller_Single_Direction *);
+
+ eo_do_super(obj, MY_CLASS,
+ elm_scrollable_interface_single_direction_get(ret));
+}
+
+EAPI void
elm_scroller_region_get(const Evas_Object *obj,
Evas_Coord *x,
Evas_Coord *y,
@@ -1226,6 +1266,8 @@ _class_constructor(Eo_Class *klass)
EO_OP_FUNC(ELM_OBJ_LAYOUT_ID(ELM_OBJ_LAYOUT_SUB_ID_SIZING_EVAL),
_elm_scroller_smart_sizing_eval),
EO_OP_FUNC(ELM_SCROLLABLE_INTERFACE_ID(ELM_SCROLLABLE_INTERFACE_SUB_ID_POLICY_SET),
_policy_set),
+
EO_OP_FUNC(ELM_SCROLLABLE_INTERFACE_ID(ELM_SCROLLABLE_INTERFACE_SUB_ID_SINGLE_DIRECTION_SET),
_single_direction_set),
+
EO_OP_FUNC(ELM_SCROLLABLE_INTERFACE_ID(ELM_SCROLLABLE_INTERFACE_SUB_ID_SINGLE_DIRECTION_GET),
_single_direction_get),
EO_OP_FUNC(ELM_SCROLLABLE_INTERFACE_ID(ELM_SCROLLABLE_INTERFACE_SUB_ID_PAGE_SIZE_SET),
_page_size_set),
EO_OP_FUNC(ELM_OBJ_SCROLLER_ID(ELM_OBJ_SCROLLER_SUB_ID_CUSTOM_WIDGET_BASE_THEME_SET),
_custom_widget_base_theme_set),
diff --git a/src/lib/elm_scroller.h b/src/lib/elm_scroller.h
index 4d3876d..6d2be42 100644
--- a/src/lib/elm_scroller.h
+++ b/src/lib/elm_scroller.h
@@ -201,6 +201,19 @@ typedef enum
} Elm_Scroller_Policy;
/**
+ * @brief Type that controls how the content is scrolled.
+ *
+ * @see elm_scroller_single_direction_set()
+ */
+typedef enum
+{
+ ELM_SCROLLER_SINGLE_DIRECTION_NONE = 0, /**< Scroll every direction */
+ ELM_SCROLLER_SINGLE_DIRECTION_SOFT, /**< Scroll single direction if the
direction is certain*/
+ ELM_SCROLLER_SINGLE_DIRECTION_HARD, /**< Scroll only single direction */
+ ELM_SCROLLER_SINGLE_DIRECTION_LAST
+} Elm_Scroller_Single_Direction;
+
+/**
* @brief Add a new scroller to the parent
*
* @param parent The parent object
@@ -208,7 +221,7 @@ typedef enum
*
* @ingroup Scroller
*/
-EAPI Evas_Object *elm_scroller_add(Evas_Object *parent);
+EAPI Evas_Object *elm_scroller_add(Evas_Object *parent);
/**
* @brief Make the scroller minimum size limited to the minimum size of the
content
@@ -224,7 +237,7 @@ EAPI Evas_Object
*elm_scroller_add(Evas_Object *parent);
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_content_min_limit(Evas_Object
*obj, Eina_Bool w, Eina_Bool h);
+EAPI void elm_scroller_content_min_limit(Evas_Object
*obj, Eina_Bool w, Eina_Bool h);
/**
* @brief Show a specific virtual region within the scroller content object
@@ -241,7 +254,7 @@ EAPI void
elm_scroller_content_min_limit(Evas_Object *ob
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_region_show(Evas_Object *obj,
Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+EAPI void elm_scroller_region_show(Evas_Object *obj,
Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
/**
* @brief Set the scrollbar visibility policy
@@ -258,7 +271,7 @@ EAPI void
elm_scroller_region_show(Evas_Object *obj, Eva
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_policy_set(Evas_Object *obj,
Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
+EAPI void elm_scroller_policy_set(Evas_Object *obj,
Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
/**
* @brief Gets scrollbar visibility policy
@@ -271,7 +284,35 @@ EAPI void
elm_scroller_policy_set(Evas_Object *obj, Elm_
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_policy_get(const Evas_Object
*obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
+EAPI void elm_scroller_policy_get(const Evas_Object
*obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
+
+/**
+ * @brief Set the type of single direction scroll
+ *
+ * @param obj The scroller object
+ * @param single_dir The type of single direction
+ *
+ * @see elm_scroller_single_direction_get()
+ *
+ * @since 1.8
+ *
+ * @ingroup Scroller
+ */
+EAPI void
elm_scroller_single_direction_set(Evas_Object *obj,
Elm_Scroller_Single_Direction single_dir);
+
+/**
+ * @brief Get the type of single direction scroll
+ *
+ * @param obj The scroller object
+ * @return the type of single direction
+ *
+ * @see elm_scroller_single_direction_get()
+ *
+ * @since 1.8
+ *
+ * @ingroup Scroller
+ */
+EAPI Elm_Scroller_Single_Direction elm_scroller_single_direction_get(const
Evas_Object *obj);
/**
* @brief Get the currently visible content region
@@ -292,7 +333,7 @@ EAPI void
elm_scroller_policy_get(const Evas_Object *obj
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_region_get(const Evas_Object
*obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+EAPI void elm_scroller_region_get(const Evas_Object
*obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
/**
* @brief Get the size of the content object
@@ -305,7 +346,7 @@ EAPI void
elm_scroller_region_get(const Evas_Object *obj
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_child_size_get(const
Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
+EAPI void elm_scroller_child_size_get(const
Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
/**
* @brief Set bouncing behavior
@@ -321,7 +362,7 @@ EAPI void
elm_scroller_child_size_get(const Evas_Object
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_bounce_set(Evas_Object *obj,
Eina_Bool h_bounce, Eina_Bool v_bounce);
+EAPI void elm_scroller_bounce_set(Evas_Object *obj,
Eina_Bool h_bounce, Eina_Bool v_bounce);
/**
* @brief Get the bounce behaviour
@@ -334,7 +375,7 @@ EAPI void
elm_scroller_bounce_set(Evas_Object *obj, Eina
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_bounce_get(const Evas_Object
*obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
+EAPI void elm_scroller_bounce_get(const Evas_Object
*obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
/**
* @brief Set scroll page size relative to viewport size.
@@ -356,7 +397,7 @@ EAPI void
elm_scroller_bounce_get(const Evas_Object *obj
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_relative_set(Evas_Object
*obj, double h_pagerel, double v_pagerel);
+EAPI void elm_scroller_page_relative_set(Evas_Object
*obj, double h_pagerel, double v_pagerel);
/**
* Get a given scroller widget's scrolling page size, relative to
@@ -374,7 +415,7 @@ EAPI void
elm_scroller_page_relative_set(Evas_Object *ob
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_relative_get(const
Evas_Object *obj, double *h_pagerel, double *v_pagerel);
+EAPI void elm_scroller_page_relative_get(const
Evas_Object *obj, double *h_pagerel, double *v_pagerel);
/**
* @brief Set scroll page size.
@@ -391,7 +432,7 @@ EAPI void
elm_scroller_page_relative_get(const Evas_Obje
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_size_set(Evas_Object *obj,
Evas_Coord h_pagesize, Evas_Coord v_pagesize);
+EAPI void elm_scroller_page_size_set(Evas_Object
*obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize);
/**
* @brief Retrieve a scroller widget's current page size.
@@ -407,7 +448,7 @@ EAPI void
elm_scroller_page_size_set(Evas_Object *obj, E
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_size_get(const Evas_Object
*obj, Evas_Coord *h_pagesize, Evas_Coord *v_pagesize);
+EAPI void elm_scroller_page_size_get(const
Evas_Object *obj, Evas_Coord *h_pagesize, Evas_Coord *v_pagesize);
/**
* @brief Set the maxium of the movable page at a flicking.
@@ -424,7 +465,7 @@ EAPI void
elm_scroller_page_size_get(const Evas_Object *
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_scroll_limit_set(const
Evas_Object *obj, Evas_Coord page_limit_h, Evas_Coord page_limit_v);
+EAPI void elm_scroller_page_scroll_limit_set(const
Evas_Object *obj, Evas_Coord page_limit_h, Evas_Coord page_limit_v);
/**
* @brief Get the maxium of the movable page at a flicking.
@@ -439,7 +480,7 @@ EAPI void
elm_scroller_page_scroll_limit_set(const Evas_
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_scroll_limit_get(const
Evas_Object *obj, Evas_Coord *page_limit_h, Evas_Coord *page_limit_v);
+EAPI void elm_scroller_page_scroll_limit_get(const
Evas_Object *obj, Evas_Coord *page_limit_h, Evas_Coord *page_limit_v);
/**
* @brief Get scroll current page number.
@@ -459,7 +500,7 @@ EAPI void
elm_scroller_page_scroll_limit_get(const Evas_
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_current_page_get(const
Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
+EAPI void elm_scroller_current_page_get(const
Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
/**
* @brief Get scroll last page number.
@@ -477,7 +518,7 @@ EAPI void
elm_scroller_current_page_get(const Evas_Objec
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_last_page_get(const Evas_Object
*obj, int *h_pagenumber, int *v_pagenumber);
+EAPI void elm_scroller_last_page_get(const
Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
/**
* Show a specific virtual region within the scroller content object by page
number.
@@ -503,7 +544,7 @@ EAPI void
elm_scroller_last_page_get(const Evas_Object *
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_show(Evas_Object *obj, int
h_pagenumber, int v_pagenumber);
+EAPI void elm_scroller_page_show(Evas_Object *obj,
int h_pagenumber, int v_pagenumber);
/**
* Show a specific virtual region within the scroller content object by page
number.
@@ -529,7 +570,7 @@ EAPI void
elm_scroller_page_show(Evas_Object *obj, int h
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_page_bring_in(Evas_Object *obj,
int h_pagenumber, int v_pagenumber);
+EAPI void elm_scroller_page_bring_in(Evas_Object
*obj, int h_pagenumber, int v_pagenumber);
/**
* @brief Show a specific virtual region within the scroller content object.
@@ -552,7 +593,7 @@ EAPI void
elm_scroller_page_bring_in(Evas_Object *obj, i
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_region_bring_in(Evas_Object
*obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+EAPI void elm_scroller_region_bring_in(Evas_Object
*obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
/**
* @brief Set event propagation on a scroller
@@ -566,7 +607,7 @@ EAPI void
elm_scroller_region_bring_in(Evas_Object *obj,
*
* @ingroup Scroller
*/
-EAPI void
elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation);
+EAPI void
elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation);
/**
* @brief Get event propagation for a scroller
@@ -580,7 +621,7 @@ EAPI void
elm_scroller_propagate_events_set(Evas_Object
*
* @ingroup Scroller
*/
-EAPI Eina_Bool elm_scroller_propagate_events_get(const
Evas_Object *obj);
+EAPI Eina_Bool elm_scroller_propagate_events_get(const
Evas_Object *obj);
/**
* @brief Set scrolling gravity on a scroller
@@ -603,7 +644,7 @@ EAPI Eina_Bool
elm_scroller_propagate_events_get(const Evas_O
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_gravity_set(Evas_Object *obj,
double x, double y);
+EAPI void elm_scroller_gravity_set(Evas_Object *obj,
double x, double y);
/**
* @brief Get scrolling gravity values for a scroller
@@ -618,7 +659,7 @@ EAPI void
elm_scroller_gravity_set(Evas_Object *obj, dou
*
* @ingroup Scroller
*/
-EAPI void elm_scroller_gravity_get(const Evas_Object
*obj, double *x, double *y);
+EAPI void elm_scroller_gravity_get(const Evas_Object
*obj, double *x, double *y);
/**
* @}
--
------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter