Enlightenment CVS committal

Author  : pfritz
Project : e17
Module  : libs/ewl

Dir     : e17/libs/ewl/src/lib


Modified Files:
        ewl_paned.c 


Log Message:
- fix the grabber reset issue

===================================================================
RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_paned.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -3 -r1.41 -r1.42
--- ewl_paned.c 14 Jan 2007 23:11:03 -0000      1.41
+++ ewl_paned.c 19 Jan 2007 21:13:05 -0000      1.42
@@ -32,10 +32,8 @@
 
 static void ewl_paned_grabbers_update(Ewl_Paned *p);
 static void ewl_paned_layout_setup(void);
-static int ewl_paned_widgets_resize(Ecore_List *list, int space);
-static int ewl_paned_widgets_place(Ecore_List *from, Ecore_List *to,
-                       Ewl_Paned_Layout *layout, int (*size)(Ewl_Object *o), 
-                       int other);
+static Ewl_Widget *ewl_paned_grabber_next(Ewl_Paned *p);
+static int ewl_paned_widgets_place(Ewl_Paned *p, Ewl_Paned_Layout *layout);
 
 /**
  * @return Returns NULL on failure, or a pointer to a new paned widget on 
success.
@@ -142,8 +140,7 @@
  * @param p: The paned to set the orientation on
  * @param o: The Ewl_Orientation to set
  * @return Returns no value.
- * @brief Set the orientation of the paned widget
- */
+ * @brief Set the orientation of the paned */
 void
 ewl_paned_orientation_set(Ewl_Paned *p, Ewl_Orientation o)
 {
@@ -235,6 +232,7 @@
 void
 ewl_paned_cb_child_remove(Ewl_Container *c, Ewl_Widget *w, int idx)
 {
+       Ewl_Paned *p;
        Ewl_Widget *o;
 
        DENTER_FUNCTION(DLEVEL_STABLE);
@@ -243,6 +241,7 @@
        DCHECK_TYPE("c", c, EWL_CONTAINER_TYPE);
        DCHECK_TYPE("w", w, EWL_WIDGET_TYPE);
 
+       p = EWL_PANED(c);
        /* skip grabbers */
        if (ewl_widget_type_is(w, EWL_PANED_GRABBER_TYPE))
                DRETURN(DLEVEL_STABLE);
@@ -250,6 +249,9 @@
        /* our grabber is always to our left, since we were just removed
         * from idx that means it's at idx - 1 */
        o = ewl_container_child_internal_get(c, idx - 1);
+       if (p->last_grab == o)
+               p->last_grab = NULL;
+
        ewl_widget_destroy(o);
 
        /* if this is on the new pane list, remove it */
@@ -346,10 +348,9 @@
        Ewl_Paned *p;
        Ewl_Container *c;
        Ewl_Widget *child;
-       Ecore_List *unsized, *sized;
-       int grabber_size = 0, needed_pane_size = 0, min_pane_size = 0;
-       int tot_paned_size = 0, cur_pane_size = 0;
-       int available_size, pos = 0, other_size, main_dir, other_dir;
+       int last_size, pos_diff, available, pane_num;
+       int tot_paned_size, other_size, main_dir, other_dir;
+       int grabber_size = 0, cur_pos;
 
        DENTER_FUNCTION(DLEVEL_STABLE);
        DCHECK_PARAM_PTR("w", w);
@@ -358,9 +359,14 @@
        p = EWL_PANED(w);
        c = EWL_CONTAINER(p);
 
-       unsized = ecore_list_new();
-       sized = ecore_list_new();
-
+       /*
+        * Before we start with the code, here is a little overview what
+        * the function actually do. The main thing to understand is
+        * that we first only place the grabber and ignore more or less
+        * the pane widgets. Every resizing is done through the grabber
+        * positions. When we this have done the pane widgets will be
+        * placed between the grabber
+        */     
        if (ewl_paned_orientation_get(p) == EWL_ORIENTATION_HORIZONTAL)
        {
                layout = horizontal_layout;
@@ -378,141 +384,161 @@
                other_dir = CURRENT_X(w);
        }
 
-       /* get a list of panes and grabbers that will be shown and the sizes
-        * we have to work with */
-       ecore_dlist_goto_first(c->children);
-       while ((child = ecore_dlist_next(c->children)))
-       {
-               if (!VISIBLE(child)) continue;
+       last_size = p->last_size;
+       p->last_size = tot_paned_size;
+       pos_diff = p->last_pos - main_dir;
+       p->last_pos = main_dir;
 
-               /* if the widget is a grabber. remove space from total and 
-                * sum up needed/current space for panes */
-               if (ewl_widget_type_is(child, EWL_PANED_GRABBER_TYPE))
+       if (ecore_dlist_is_empty(c->children))
+               DRETURN(DLEVEL_STABLE);
+       /* if there are new widgets we have to place them first else
+        * we need to move the grabber to the new position. this is important
+        * because the grabber are also the size setter for the pane
+        * widget between them */
+       if (!ecore_list_is_empty(p->new_panes)) {
+               last_size = ewl_paned_widgets_place(p, layout);
+       }
+       else 
+       {
+               /* move the grabber to the new position */              
+               ecore_dlist_goto_first(c->children);
+               while ((child = ewl_paned_grabber_next(p)))
                {
+                       int pos;
+
                        /* get the grabber size if needed */
                        if (!grabber_size)
                                grabber_size = 
                                        layout->current_size(EWL_OBJECT(child));
 
-                       tot_paned_size -= grabber_size;
+                       /* move the grabber to the new position */
+                       pos = layout->current_position(EWL_OBJECT(child));
+                       pos -= pos_diff;
+                       layout->position_request(EWL_OBJECT(child), pos);
+                       /* the 'other' position is for all grabber the same
+                        * so no need to fetch it from some where */
+                       layout->stable_position_request(EWL_OBJECT(child),
+                                                               other_dir);
+                       layout->stable_request(EWL_OBJECT(child), other_size);
                }
-               else
-               {
-                       /* if the child is on the new panes list it still
-                        * needs to be placed, so take it's size into
-                        * account */
-                       if (ecore_list_goto(p->new_panes, child) == child)
-                       {
-                               needed_pane_size += 
-                                       
layout->preferred_size(EWL_OBJECT(child));
-                               min_pane_size +=
-                                       layout->minimum_size(EWL_OBJECT(child));
-
-                               /* remove the child from the new panes list
-                                * and set it to the list of widgets to be
-                                * sized */
-                               ecore_list_remove(p->new_panes);
-                               ecore_list_append(unsized, child);
+       }
+       /* We now resize the pane areas so that they fit into the new size
+        * therefor we have to first calculate, how many space is available
+        * for giving or taking it from the panes */
+       available = tot_paned_size - last_size;
+
+       while (available != 0)
+       {
+               int old_pos, give;
+
+               cur_pos = old_pos = main_dir;
+               /* we need to now the number of panes = the number of children
+                * divided by two, because we don't count the grabber and 
+                * minus one because we cannot change the size of the 
+                * last pane directly*/ 
+               pane_num = ecore_list_nodes(c->children)/2 - 1;
+               /* if we have no panes we don't need to calc their place */
+               if (pane_num < 1)
+                       break;  
+
+               /* give can also be negative, so see it as a can take or give */
+               give = available / pane_num;
+               /* to prevent rounding errors */
+               if (give == 0) {
+                       give = (available > 0) ? 1 : -1;
+                       if (!p->last_grab) {
+                               ecore_dlist_goto_first(c->children);
                        }
                        else
-                       {
-                               cur_pane_size += 
-                                       layout->current_size(EWL_OBJECT(child));
-                               ecore_list_append(sized, child);
-                       }
+                               ecore_dlist_goto(c->children, p->last_grab);
                }
-       }
-
-       available_size = tot_paned_size - cur_pane_size;
+               else
+                       ecore_list_goto_first(c->children);
 
-       /* the paned has gotten smaller, we need to reclaim space from the
-        * currently sized widgets */
-       if (available_size < 0)
-               available_size += ewl_paned_widgets_resize(sized, 
available_size);
-
-       /* available space is less then our needed space, we need to resize
-        * the other widgets until we have at least min_pane_size available */
-       if (available_size < min_pane_size)
-               available_size += ewl_paned_widgets_resize(sized, 
-                                       min_pane_size - available_size);
+               while ((child = ecore_list_next(c->children)))
+               {
+                       Ewl_Widget *grab;
+                       int min, new_size, grab_pos;
+                       if (!VISIBLE(child) 
+                               || ewl_widget_type_is(child,
+                                               EWL_PANED_GRABBER_TYPE))
+                               continue;
+
+                       min = layout->minimum_size(EWL_OBJECT(child));
+                       grab = ewl_paned_grabber_next(p);
+
+                       if (!grab) {
+                               new_size = p->last_size - 
+                                               (cur_pos - p->last_pos);
+                               if (new_size < min) {
+                                       available -= min - new_size;
+                               }
+                               available -= give;
 
-       /* we have the minimum space, but not our preferred space. Give each
-        * unsized widget their minimum size .
-        */
-       if ((min_pane_size <= available_size) 
-                       && (available_size < needed_pane_size))
-               available_size -= ewl_paned_widgets_place(unsized, sized,
-                                               layout,
-                                               layout->minimum_size,
-                                               other_size);
-       /* give each widget their preferred size */
-       else
-               available_size -= ewl_paned_widgets_place(unsized, sized,
-                                               layout, layout->preferred_size, 
-                                               other_size);
-
-       /* now that the widgets have all been sized we need to distrubute
-        * any extra space available */
-       if (available_size > 0)
-       {
-               int give = 0;
-               int nodes = 0;
+                               if (available == 0)
+                                       p->last_grab = NULL;
+                               break;
+                       }
+                       
+                       grab_pos = layout->current_position(EWL_OBJECT(grab));
 
-               nodes = ecore_list_nodes(sized);
-               while((available_size > 0) && (nodes > 0))
-               {
-                       give = floor(available_size / nodes);
-                       ecore_list_goto_first(sized);
-                       while ((child = ecore_list_current(sized)))
+                       if (grab_pos - old_pos + give < min) 
                        {
-                               int size, new_size;
-
-                               size = layout->current_size(EWL_OBJECT(child));
-                               layout->variable_request(EWL_OBJECT(child), 
size + give);
-                               new_size = 
layout->current_size(EWL_OBJECT(child));
-
-                               if ((new_size - size) > 0)
-                               {
-                                       available_size -= (new_size - size);
-                                       ecore_list_next(sized);
-                               }
-                               else
-                                       ecore_list_remove(sized);
+                               new_size = min;
+                               pane_num--;
                        }
-                       nodes = ecore_list_nodes(sized);
+                       else
+                               new_size = grab_pos - old_pos + give;
+                       
+                       available -= new_size - (grab_pos - old_pos);
+
+                       /* if there is no space to distribute left
+                        * we can stop in resizing the panes, but we
+                        * still have to place them on there new
+                        * places */
+                       if (available == 0 && give != 0) {
+                               give = 0;
+                               p->last_grab = grab;
+                       }
+                       
+                       cur_pos += new_size;
+                       layout->position_request(EWL_OBJECT(grab), cur_pos);
+                       cur_pos += grabber_size;
+                       old_pos = grab_pos + grabber_size;
                }
        }
 
        /* now that all of the space is filled we can go and layout all of
         * the available widgets */
-       pos = main_dir;
+       cur_pos = main_dir;
        ecore_dlist_goto_first(c->children);
        while ((child = ecore_dlist_next(c->children)))
        {
-               int ow, oh;
+               Ewl_Widget *grab;
+               int size;
 
-               if (VISIBLE(child))
-               {
-                       ewl_object_current_size_get(EWL_OBJECT(child), &ow, 
&oh);
+               if (!VISIBLE(child))
+                       continue;
 
-                       if (ewl_paned_orientation_get(p) ==
-                                       EWL_ORIENTATION_HORIZONTAL)
-                       {
-                               ewl_object_place(EWL_OBJECT(child), pos, 
other_dir, 
-                                                                       ow, 
other_size);
-                               pos += ow;
-                       }
-                       else
-                       {
-                               ewl_object_place(EWL_OBJECT(child), other_dir, 
pos, 
-                                                                       
other_size, oh);
-                               pos += oh;
-                       }
+               /* first calculate the size */ 
+               grab = ewl_paned_grabber_next(p);
+               if (grab) {
+                       size = layout->current_position(EWL_OBJECT(grab))
+                               - cur_pos;
                }
-       }
+               else
+                       /* this is actually the current size */
+                       size = p->last_size - (cur_pos - p->last_pos); 
 
-       ecore_list_destroy(sized);
-       ecore_list_destroy(unsized);
+               if (ewl_paned_orientation_get(p) == EWL_ORIENTATION_HORIZONTAL)
+                       ewl_object_place(EWL_OBJECT(child), cur_pos, other_dir, 
+                                                       size, other_size);
+               else
+                       ewl_object_place(EWL_OBJECT(child), other_dir, cur_pos, 
+                                                       other_size, size);
+
+               cur_pos += size + grabber_size;
+       }
 
        DLEAVE_FUNCTION(DLEVEL_STABLE);
 }
@@ -758,10 +784,10 @@
        Ewl_Widget *child;
        Ewl_Container *c;
        Ewl_Paned *p;
-       Ewl_Widget *left_pane = NULL, *right_pane = NULL;
+       Ewl_Widget *prev_pane = NULL, *next_pane = NULL;
 
        int paned_pos, paned_size;
-       int left_grabber_pos, right_grabber_pos;
+       int prev_grabber_pos, next_grabber_pos;
        int grabber_pos, grabber_size;
        int mouse_pos, mouse_vec, mouse_offset;
        int grabber_pos_new;
@@ -795,7 +821,7 @@
        grabber_size = layout->current_size(EWL_OBJECT(w));
 
        /* 
-        * this is the vector pointing from the left edge of the grabber
+        * this is the vector pointing from the left/top edge of the grabber
         * to the mouse position, so is it neagtive the grabber will
         * be moved to the left side and is it positiv to the right
         */
@@ -803,7 +829,7 @@
        if (mouse_vec == 0)
                DRETURN(DLEVEL_STABLE);
 
-       /* find the left grabber that is blocking us */
+       /* find the previous grabber that is blocking us */
        ecore_dlist_goto(c->children, w);
 
        /* move past the selected grabber */
@@ -818,18 +844,18 @@
                        break;
                }
                else
-                       left_pane = child;
+                       prev_pane = child;
        }
 
-       /* if we didn't find a left grabber set the paned position instead */
+       /* if we didn't find a privous grabber set the paned position instead */
        if (stop_grabber)
-               left_grabber_pos = 
+               prev_grabber_pos = 
                        layout->current_position(EWL_OBJECT(stop_grabber))
                        + grabber_size;
        else
-               left_grabber_pos = paned_pos;
+               prev_grabber_pos = paned_pos;
 
-       /* and now find the right pane */
+       /* and now find the right/bottom pane */
        ecore_dlist_goto(c->children, w);
        stop_grabber = NULL;
 
@@ -844,15 +870,15 @@
                        break;
                }
                else
-                       right_pane = child;
+                       next_pane = child;
        }
        
-       /* if we didn't find a left grabber set the paned position instead */
+       /* if we didn't find a prevous grabber set the paned position instead */
        if (stop_grabber)
-               right_grabber_pos = 
+               next_grabber_pos = 
                        layout->current_position(EWL_OBJECT(stop_grabber));
        else
-               right_grabber_pos = paned_pos + paned_size;
+               next_grabber_pos = paned_pos + paned_size;
 
        /*
         * now we have collected enought data to place the grabber
@@ -861,20 +887,20 @@
        /* we don't want to shrink the panes more that it is allowed */
        if (mouse_vec < 0) {
                /* the left side get shrinked */
-               int pane_min = layout->minimum_size(EWL_OBJECT(left_pane));
-               if (grabber_pos + mouse_vec - left_grabber_pos < pane_min)
-                       grabber_pos_new = left_grabber_pos + pane_min;
+               int pane_min = layout->minimum_size(EWL_OBJECT(prev_pane));
+               if (grabber_pos + mouse_vec - prev_grabber_pos < pane_min)
+                       grabber_pos_new = prev_grabber_pos + pane_min;
                else
                        /* note that mouse_vec is here negative! */
                        grabber_pos_new = grabber_pos + mouse_vec;
        }
        else {
-               /* the right side get shrinked */
-               int pane_min = layout->minimum_size(EWL_OBJECT(right_pane));
-               if (right_grabber_pos - (grabber_pos + mouse_vec + grabber_size)
+               /* the right/bottom side get shrinked */
+               int pane_min = layout->minimum_size(EWL_OBJECT(next_pane));
+               if (next_grabber_pos - (grabber_pos + mouse_vec + grabber_size)
                                < pane_min)
                        grabber_pos_new = 
-                               right_grabber_pos - pane_min - grabber_size;
+                               next_grabber_pos - pane_min - grabber_size;
                else
                        grabber_pos_new = grabber_pos + mouse_vec;
        }
@@ -883,37 +909,37 @@
         * finally we can place the stuff 
         */
        if (ewl_paned_orientation_get(p) == EWL_ORIENTATION_HORIZONTAL) {
-               ewl_object_place(EWL_OBJECT(left_pane), left_grabber_pos,
+               ewl_object_place(EWL_OBJECT(prev_pane), prev_grabber_pos,
                                        CURRENT_Y(p),
-                                       grabber_pos_new - left_grabber_pos,
+                                       grabber_pos_new - prev_grabber_pos,
                                        CURRENT_H(p));
                ewl_object_place(EWL_OBJECT(w), grabber_pos_new,
                                        CURRENT_Y(p),
                                        grabber_size,
                                        CURRENT_H(p));
-               ewl_object_place(EWL_OBJECT(right_pane), 
+               ewl_object_place(EWL_OBJECT(next_pane), 
                                        grabber_pos_new + grabber_size,
                                        CURRENT_Y(p),
-                                       right_grabber_pos - grabber_pos_new
+                                       next_grabber_pos - grabber_pos_new
                                        - grabber_size,
                                        CURRENT_H(p));
        }
        else {
-               ewl_object_place(EWL_OBJECT(left_pane), 
+               ewl_object_place(EWL_OBJECT(prev_pane), 
                                        CURRENT_X(p),
-                                       left_grabber_pos,
+                                       prev_grabber_pos,
                                        CURRENT_W(p),
-                                       grabber_pos_new - left_grabber_pos);
+                                       grabber_pos_new - prev_grabber_pos);
                ewl_object_place(EWL_OBJECT(w), 
                                        CURRENT_X(p),
                                        grabber_pos_new,
                                        CURRENT_W(p),
                                        grabber_size);
-               ewl_object_place(EWL_OBJECT(right_pane), 
+               ewl_object_place(EWL_OBJECT(next_pane), 
                                        CURRENT_X(p),
                                        grabber_pos_new + grabber_size,
                                        CURRENT_W(p),
-                                       right_grabber_pos - grabber_pos_new
+                                       next_grabber_pos - grabber_pos_new
                                        - grabber_size);
        }
 
@@ -958,80 +984,93 @@
 
        DLEAVE_FUNCTION(DLEVEL_STABLE);
 }
-
+               
 static int
-ewl_paned_widgets_resize(Ecore_List *list, int space)
+ewl_paned_widgets_place(Ewl_Paned *p, Ewl_Paned_Layout *layout)
 {
-       int take, nodes = 0, moved = 0;
-       Ecore_List *tmp;
        Ewl_Widget *child;
+       Ewl_Container *c;
+       int cur_pos, main_pos;
+       int other_pos, other_size;
+       int grabber_size = 0;
 
        DENTER_FUNCTION(DLEVEL_STABLE);
-       DCHECK_PARAM_PTR_RET("list", list, 0);
+       DCHECK_PARAM_PTR_RET("p", p, 0);
+       DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, 0);
+       DCHECK_PARAM_PTR_RET("layout", layout, 0);
 
-       /* make a temporary list */
-       tmp = ecore_list_new();
-       ecore_list_goto_first(list);
-       while ((child = ecore_list_next(list)))
-               ecore_list_append(tmp, child);
-
-       space = abs(space);
-       nodes = ecore_list_nodes(tmp);
-       while ((space > 0) && (nodes > 0))
+       c = EWL_CONTAINER(p);
+
+       if (p->orientation == EWL_ORIENTATION_HORIZONTAL)
+       {
+               main_pos = CURRENT_X(p);
+               other_pos = CURRENT_Y(p);
+               other_size = CURRENT_H(p);
+       }
+       else
        {
-               take = floor(space / nodes);
+               main_pos = CURRENT_Y(p);
+               other_pos = CURRENT_X(p);
+               other_size = CURRENT_W(p);
+       }
 
-               ecore_list_goto_first(tmp);
-               while ((child = ecore_list_current(tmp)))
-               {
-                       int size, new_size;
+       cur_pos = main_pos;
+       ecore_dlist_goto_first(c->children);
+       while ((child = ecore_dlist_next(c->children)))
+       {
+               Ewl_Widget *grab;
+               int min;
 
-                       size = layout->current_size(EWL_OBJECT(child));
-                       layout->variable_request(EWL_OBJECT(child), size - 
take);
-                       new_size = layout->current_size(EWL_OBJECT(child));
+               if (!VISIBLE(child)) continue;
 
-                       if ((size - new_size) > 0)
-                       {
-                               int dist;
-                               dist = size - new_size;
-                               moved += dist;
-                               space -= dist;
-                               ecore_list_next(tmp);
-                       }
-                       else
-                               ecore_list_remove(tmp);
+               min = layout->minimum_size(EWL_OBJECT(child));
+               
+               grab = ewl_paned_grabber_next(p);
+
+               if (!grab) 
+               {
+                       cur_pos += min;
+                       break;
                }
-               nodes = ecore_list_nodes(tmp);
+               
+               if (!grabber_size)
+                       grabber_size = 
+                               layout->minimum_size(EWL_OBJECT(grab));
+
+               cur_pos += min;
+               layout->variable_request(EWL_OBJECT(grab), grabber_size);
+               layout->stable_request(EWL_OBJECT(grab), other_size);
+               layout->position_request(EWL_OBJECT(grab), cur_pos);
+               layout->stable_position_request(EWL_OBJECT(grab), other_pos);
+
+               cur_pos += grabber_size;
        }
-       ecore_list_destroy(tmp);
 
-       DRETURN_INT(moved, DLEVEL_STABLE);
+       ecore_dlist_clear(p->new_panes);
+
+       DRETURN_INT(cur_pos - main_pos, DLEVEL_STABLE);
 }
-               
-static int
-ewl_paned_widgets_place(Ecore_List *from, Ecore_List *to,
-                       Ewl_Paned_Layout *layout,
-                       int (*size)(Ewl_Object *o), int other)
+
+static Ewl_Widget *
+ewl_paned_grabber_next(Ewl_Paned *p)
 {
+       Ewl_Container *c;
        Ewl_Widget *child;
-       int current, ret = 0;
 
        DENTER_FUNCTION(DLEVEL_STABLE);
-       DCHECK_PARAM_PTR_RET("from", from, 0);
-       DCHECK_PARAM_PTR_RET("to", to, 0);
-       DCHECK_PARAM_PTR_RET("size", size, 0);
+       DCHECK_PARAM_PTR_RET("p", p, 0);
+       DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, 0);
 
-       while ((child = ecore_list_remove_first(from)))
-       {
-               current = size(EWL_OBJECT(child));
-               layout->variable_request(EWL_OBJECT(child), current);
-               layout->stable_request(EWL_OBJECT(child), other);
+       c = EWL_CONTAINER(p);
 
-               ret += current;
-               ecore_list_append(to, child);
+       while ((child = ecore_dlist_next(c->children))) 
+       {
+               if (VISIBLE(child) && ewl_widget_type_is(child, 
+                                               EWL_PANED_GRABBER_TYPE))
+                       break;
        }
 
-       DRETURN_INT(ret, DLEVEL_STABLE);
+       DRETURN_INT(child, DLEVEL_STABLE);
 }
 
 static void



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to