e_fm custom and regular mode icon selection
authorYossi Kantor <yossi.kantor@samsung.com>
Tue, 17 Sep 2013 06:58:05 +0000 (08:58 +0200)
committerMike Blumenkrantz <m.blumenkran@samsung.com>
Mon, 30 Sep 2013 13:54:49 +0000 (14:54 +0100)
src/bin/e_fm.c

index 2a2c2db1228cd697acd7413a8759fff8f3c5da44..cf9cac625c16f2b1dd1e2e921bd2189ea0d1cd7e 100644 (file)
@@ -88,6 +88,7 @@ struct _E_Fm2_Smart_Data
    } new_file;
 
    E_Fm2_Icon      *last_selected;
+   E_Fm2_Icon      *range_selected;
    Eina_List       *selected_icons;
    Eina_List       *icons_place;
    Eina_List       *queue;
@@ -310,6 +311,7 @@ static void          _e_fm2_icon_sel_prev(Evas_Object *obj, Eina_Bool add);
 static void          _e_fm2_icon_sel_next(Evas_Object *obj, Eina_Bool add);
 static void          _e_fm2_icon_sel_down(Evas_Object *obj, Eina_Bool add);
 static void          _e_fm2_icon_sel_up(Evas_Object *obj, Eina_Bool add);
+static void          _e_fm2_icon_range_select(E_Fm2_Icon *ic);
 
 static void          _e_fm2_typebuf_show(Evas_Object *obj);
 static void          _e_fm2_typebuf_hide(Evas_Object *obj);
@@ -5034,6 +5036,7 @@ _e_fm2_icon_select(E_Fm2_Icon *ic)
    prev = eina_list_last_data_get(ic->sd->selected_icons);
    if (prev) prev->last_selected = EINA_FALSE;
    ic->selected = EINA_TRUE;
+   ic->sd->range_selected = NULL;
    ic->sd->last_selected = ic;
    ic->sd->selected_icons = eina_list_append(ic->sd->selected_icons, ic);
    ic->last_selected = EINA_TRUE;
@@ -5061,6 +5064,7 @@ _e_fm2_icon_deselect(E_Fm2_Icon *ic)
    if (!ic->selected) return;
    ic->selected = EINA_FALSE;
    ic->last_selected = EINA_FALSE;
+   ic->sd->range_selected = NULL;
    if (ic->sd->last_selected == ic) ic->sd->last_selected = NULL;
    ic->sd->selected_icons = eina_list_remove(ic->sd->selected_icons, ic);
    ic->selected_time = 0.0;
@@ -5414,10 +5418,10 @@ _e_fm2_icon_next_find(Evas_Object *obj, int next, int (*match_func)(E_Fm2_Icon *
 {
    E_Fm2_Smart_Data *sd;
    Eina_List *l;
-   E_Fm2_Icon *ic, *ic_next;
+   E_Fm2_Icon *ic, *ic_next, *ic_vert, *ic_horz;
    char view_mode;
    int x = 0, y = 0, custom = 0;
-   int dist, min = 65535;
+   int dist = 0, min_horz = 65535, min_vert = 65535;
 
    sd = evas_object_smart_data_get(obj);
    if (!sd) return NULL;
@@ -5428,106 +5432,64 @@ _e_fm2_icon_next_find(Evas_Object *obj, int next, int (*match_func)(E_Fm2_Icon *
        (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
        (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
      custom = 1;
-
+     
+   l = eina_list_data_find_list(sd->icons, (sd->range_selected) ?
+                                     sd->range_selected :
+                                     sd->last_selected);
+                                     
+   if (!l) return eina_list_data_get(sd->icons);
+   
+   if (!next) return eina_list_data_get(l);
+   
    ic_next = NULL;
-   /* find selected item / current position */
-   EINA_LIST_FOREACH(sd->icons, l, ic)
-     {
-        if (ic->selected)
-          {
-             if (!custom && !match_func)
-               {
-                  ic_next = ic;
-               }
-             else
-               {
-                  x = ic->x;
-                  y = ic->y;
-               }
-             break;
-          }
-     }
-   if (next && (custom || match_func))
-     {
-        /* find next item in custom grid, or list/grid when match
-           func is given */
-        if (next == 1)
-          {
-             EINA_LIST_FOREACH(sd->icons, l, ic)
-               {
-                  if ((ic->x > x) &&
-                      (custom ? (ic->y >= y) : (ic->y == y)) &&
-                      (!match_func || match_func(ic, data)))
-                    {
-                       dist = 2 * (ic->y - y) + (ic->x - x);
-                       if (dist < min)
-                         {
-                            min = dist;
-                            ic_next = ic;
-                         }
-                    }
-               }
-             /* no next item was found in row go down and begin */
-             if (!ic_next)
-               {
-                  EINA_LIST_FOREACH(sd->icons, l, ic)
-                    {
-                       if ((ic->y > y) && (!match_func || match_func(ic, data)))
-                         {
-                            dist = 2 * (abs(ic->y - y)) + ic->x;
-                            if (dist < min)
-                              {
-                                 min = dist;
-                                 ic_next = ic;
-                              }
-                         }
-                    }
-               }
-          }
-        /* find previous item */
-        else if (next == -1)
+   ic_vert = NULL;
+   ic_horz = NULL;
+   
+   if (custom || match_func)
+     {
+        ic = eina_list_data_get(l);
+        x = ic->x;
+        y = ic->y;
+     
+        EINA_LIST_FOREACH(sd->icons, l, ic)
           {
-             EINA_LIST_FOREACH(sd->icons, l, ic)
+             if (match_func && !match_func(ic, data)) continue;
+             
+             int dx = (ic->x - x);
+             int dy = (ic->y - y);
+             int sgnx = (dx) ? dx / abs(dx) : 0;
+             int sgny = (dy) ? dy / abs(dy) : 0;
+             
+             if ((next == sgnx) && (abs(dx) >= abs(dy)) && ((sgny*sgnx) >= 0))
                {
-                  if ((ic->x < x) &&
-                      (custom ? (ic->y <= y) : (ic->y == y)) &&
-                      (!match_func || match_func(ic, data)))
+                  dist = abs(dy) + abs(dx);
+                  if (dist < min_horz)
                     {
-                       dist = 2 * (y - ic->y) + (x - ic->x);
-                       if (dist < min)
-                         {
-                            min = dist;
-                            ic_next = ic;
-                         }
+                       min_horz = dist;
+                       ic_horz = ic;
                     }
                }
-             /* no prev item was found in row go to end and up */
-             if (!ic_next)
+             
+             if (!ic_horz && (next == sgny))
                {
-                  EINA_LIST_FOREACH(sd->icons, l, ic)
+                  dist = abs(dy) + ic->x * next;
+                  if (dist < min_vert)
                     {
-                       if ((ic->y < y) && (!match_func || match_func(ic, data)))
-                         {
-                            dist = 2 * (abs(ic->y - y)) - ic->x;
-                            if (dist < min)
-                              {
-                                 min = dist;
-                                 ic_next = ic;
-                              }
-                         }
-                    }
+                       min_vert = dist;
+                       ic_vert = ic;
+                    } 
                }
           }
+        ic_next = (ic_horz) ? ic_horz : ic_vert;
      }
-   /* not custom, items are arranged in list order */
-   else if (ic_next)
+   else
      {
         if (next == 1)
           {
              if (!eina_list_next(l)) return NULL;
              ic_next = eina_list_data_get(eina_list_next(l));
           }
-        if (next == -1)
+        else if (next == -1)
           {
              if (!eina_list_prev(l)) return NULL;
              ic_next = eina_list_data_get(eina_list_prev(l));
@@ -5544,16 +5506,19 @@ _e_fm2_icon_sel_prev(Evas_Object *obj, Eina_Bool add)
 
    ic_prev = _e_fm2_icon_next_find(obj, -1, NULL, NULL);
 
-   if (!ic_prev)
+   if (!ic_prev) return;
+
+   if ((!add) || ic_prev->sd->config->selection.single)
      {
-        /* FIXME this is not the bottomright item for custom grid */
-        _e_fm2_icon_sel_last(obj, add);
-        return;
+        _e_fm2_icon_desel_any(obj);
+        _e_fm2_icon_select(ic_prev);
      }
-   if ((!add) || ic_prev->sd->config->selection.single)
-     _e_fm2_icon_desel_any(obj);
-   _e_fm2_icon_select(ic_prev);
-   evas_object_smart_callback_call(obj, "selection_change", NULL); /*XXX sd->obj*/
+   else
+     {
+        _e_fm2_icon_range_select(ic_prev);
+     }
+   
+   evas_object_smart_callback_call(obj, "selection_change", NULL);
    _e_fm2_icon_make_visible(ic_prev);
 }
 
@@ -5563,15 +5528,18 @@ _e_fm2_icon_sel_next(Evas_Object *obj, Eina_Bool add)
    E_Fm2_Icon *ic_next;
 
    ic_next = _e_fm2_icon_next_find(obj, 1, NULL, NULL);
-   if (!ic_next)
+   
+   if (!ic_next) return;
+
+   if ((!add) || ic_next->sd->config->selection.single)
      {
-        /* FIXME this is not the topleft item for custom grid */
-        _e_fm2_icon_sel_first(obj, add);
-        return;
+        _e_fm2_icon_desel_any(obj);
+        _e_fm2_icon_select(ic_next);
+     }
+   else
+     {
+        _e_fm2_icon_range_select(ic_next);
      }
-   if ((!add) || ic_next->sd->config->selection.single)
-     _e_fm2_icon_desel_any(obj);
-   _e_fm2_icon_select(ic_next);
    evas_object_smart_callback_call(obj, "selection_change", NULL);
    _e_fm2_icon_make_visible(ic_next);
 }
@@ -5581,72 +5549,41 @@ _e_fm2_icon_sel_down(Evas_Object *obj, Eina_Bool add)
 {
    E_Fm2_Smart_Data *sd;
    Eina_List *l;
-   E_Fm2_Icon *ic, *ic_down;
-   int found, x = -1, y = -1, custom = 0;
+   E_Fm2_Icon *ic, *ic2, *ic_down;
    int dist, min = 65535;
-   char view_mode;
 
    sd = evas_object_smart_data_get(obj);
    if (!sd) return;
    if (!sd->icons) return;
 
-   view_mode = _e_fm2_view_mode_get(sd);
-   if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
-       (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
-       (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
-     custom = 1;
+   ic = (sd->range_selected) ? sd->range_selected : sd->last_selected;
+   if (!ic) ic = eina_list_data_get(sd->icons);
 
-   ic_down = NULL;
-   found = 0;
+   ic_down = ic;
 
-   EINA_LIST_FOREACH(sd->icons, l, ic)
+   EINA_LIST_FOREACH(sd->icons, l, ic2)
      {
-        if (!found)
+        if (ic2->y > ic->y)
           {
-             if (ic->selected)
-               {
-                  found = 1;
-                  x = ic->x;
-                  y = ic->y;
-                  if (custom) break;
-               }
-          }
-        else if (ic->y > y)
-          {
-             dist = (abs(ic->x - x)) + (ic->y - y) * 2;
+             dist = (abs(ic2->x - ic->x)) + (ic2->y - ic->y) * 2;
              if (dist < min)
                {
                   min = dist;
-                  ic_down = ic;
+                  ic_down = ic2;
                }
-             else break;
           }
      }
 
-   if (custom)
+   if ((!add) || ic_down->sd->config->selection.single)
      {
-        EINA_LIST_FOREACH(sd->icons, l, ic)
-          {
-             if (ic->y > y)
-               {
-                  dist = (abs(ic->x - x)) + (ic->y - y) * 2;
-                  if (dist < min)
-                    {
-                       min = dist;
-                       ic_down = ic;
-                    }
-               }
-          }
+        _e_fm2_icon_desel_any(obj);
+        _e_fm2_icon_select(ic_down);
      }
-
-   if (!ic_down)
+   else
      {
-        if (!custom) _e_fm2_icon_sel_next(obj, add);
-        return;
+        _e_fm2_icon_range_select(ic_down);
      }
-   if ((!add) || ic_down->sd->config->selection.single)
-     _e_fm2_icon_desel_any(obj);
-   _e_fm2_icon_select(ic_down);
+
    evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
    _e_fm2_icon_make_visible(ic_down);
 }
@@ -5656,74 +5593,89 @@ _e_fm2_icon_sel_up(Evas_Object *obj, Eina_Bool add)
 {
    E_Fm2_Smart_Data *sd;
    Eina_List *l;
-   E_Fm2_Icon *ic, *ic_up;
-   int found = 0, x = 0, y = 0, custom = 0;
+   E_Fm2_Icon *ic, *ic2, *ic_down;
    int dist, min = 65535;
-   char view_mode;
 
    sd = evas_object_smart_data_get(obj);
    if (!sd) return;
    if (!sd->icons) return;
 
-   view_mode = _e_fm2_view_mode_get(sd);
-
-   if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
-       (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
-       (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
-     custom = 1;
+   ic = (sd->range_selected) ? sd->range_selected : sd->last_selected;
+   if (!ic) ic = eina_list_data_get(sd->icons);
 
-   ic_up = NULL;
+   ic_down = ic;
 
-   EINA_LIST_REVERSE_FOREACH(sd->icons, l, ic)
+   EINA_LIST_FOREACH(sd->icons, l, ic2)
      {
-        if (!found)
+        if (ic2->y < ic->y)
           {
-             if (ic->selected)
-               {
-                  found = 1;
-                  x = ic->x;
-                  y = ic->y;
-                  if (custom) break;
-               }
-          }
-        else if (ic->y < y)
-          {
-             dist = (abs(ic->x - x)) + (y - ic->y) * 2;
+             dist = (abs(ic2->x - ic->x)) + (ic->y - ic2->y) * 2;
              if (dist < min)
                {
                   min = dist;
-                  ic_up = ic;
+                  ic_down = ic2;
                }
-             else break;
           }
      }
 
-   if (custom && found)
+   if ((!add) || ic_down->sd->config->selection.single)
      {
-        EINA_LIST_FOREACH(sd->icons, l, ic)
+        _e_fm2_icon_desel_any(obj);
+        _e_fm2_icon_select(ic_down);
+     }
+   else
+     {
+        _e_fm2_icon_range_select(ic_down);
+     }
+
+   evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
+   _e_fm2_icon_make_visible(ic_down);
+}
+
+static void
+_e_fm2_icon_range_select(E_Fm2_Icon *ic)
+{
+   const Eina_List *l;
+   E_Fm2_Icon *ic2;
+   
+   char view_mode = _e_fm2_view_mode_get(ic->sd);
+   E_Fm2_Icon *last = ic->sd->last_selected;
+   
+   _e_fm2_icon_desel_any(ic->sd->obj);
+   
+   if ((!last) || (last == ic))
+     {
+        last = ic;
+     }
+   else if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
+            (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
+            (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
+     {
+        int topx = (ic->x <= last->x) ? ic->x : last->x;
+        int boundx = (ic->x < last->x) ? (last->x + last->w) : (ic->x + ic->w);
+        int topy = (ic->y <= last->y) ? ic->y : last->y;
+        int boundy = (ic->y < last->y) ? (last->y + last->h) : (ic->y + ic->h);
+         
+        EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
           {
-             if (!ic->selected && ic->y < y)
-               {
-                  dist = (abs(ic->x - x)) + (y - ic->y) * 2;
-                  if (dist < min)
-                    {
-                       min = dist;
-                       ic_up = ic;
-                    }
-               }
+             if ((ic2 != last) && 
+                 (ic2->x >= topx) && (ic2->x < boundx) &&
+                 (ic2->y >= topy) && (ic2->y < boundy))
+               _e_fm2_icon_select(ic2);
           }
      }
-
-   if (!ic_up)
+   else
      {
-        if (!custom) _e_fm2_icon_sel_prev(obj, add);
-        return;
+        int trig = 2;
+        EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
+          {
+             if ((ic2 == last) || (ic2 == ic)) trig--;
+             if ((trig < 2) && (ic2 != last)) _e_fm2_icon_select(ic2);
+             if (!trig) break;
+          }
      }
-   if ((!add) || ic_up->sd->config->selection.single)
-     _e_fm2_icon_desel_any(obj);
-   _e_fm2_icon_select(ic_up);
-   evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
-   _e_fm2_icon_make_visible(ic_up);
+   _e_fm2_icon_select(last);
+   ic->sd->range_selected = ic;
 }
 
 /* FIXME: prototype */
@@ -7240,39 +7192,7 @@ _e_fm2_mouse_1_handler(E_Fm2_Icon *ic, int up, void *evas_event)
 
    if (range_sel)
      {
-        const Eina_List *l, *l2;
-        E_Fm2_Icon *ic2;
-        Eina_Bool seen = 0;
-        /* find last selected - if any, and select all icons between */
-        EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
-          {
-             if (ic2 == ic) seen = 1;
-             if (ic2->last_selected)
-               {
-                  ic2->last_selected = 0;
-                  if (seen)
-                    {
-                       for (l2 = l, ic2 = l2->data; l2; l2 = l2->prev, ic2 = l2->data)
-                         {
-                            if (ic == ic2) break;
-                            if (!ic2->selected) sel_change = 1;
-                            _e_fm2_icon_select(ic2);
-                            ic2->last_selected = 0;
-                         }
-                    }
-                  else
-                    {
-                       EINA_LIST_FOREACH(l, l2, ic2)
-                         {
-                            if (ic == ic2) break;
-                            if (!ic2->selected) sel_change = 1;
-                            _e_fm2_icon_select(ic2);
-                            ic2->last_selected = 0;
-                         }
-                    }
-                  break;
-               }
-          }
+        if (!up) _e_fm2_icon_range_select(ic);
      }
    else if ((!multi_sel) && ((up) || ((!up) && (!ic->selected))))
      {