Enlightenment CVS committal Author : pfritz Project : e17 Module : libs/ewl
Dir : e17/libs/ewl/src/lib Modified Files: ewl_paned.c ewl_paned.h Log Message: add ewl_paned_initial_size_set(), note that this value isn't accounted for the preferred size calculation yet =================================================================== RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_paned.c,v retrieving revision 1.56 retrieving revision 1.57 diff -u -3 -r1.56 -r1.57 --- ewl_paned.c 2 Nov 2007 01:28:30 -0000 1.56 +++ ewl_paned.c 4 Nov 2007 23:13:07 -0000 1.57 @@ -7,8 +7,10 @@ typedef struct { - int size; Ewl_Widget *pane; + Ewl_Paned_Size_Info *info; + int size; + unsigned char fixed:1; } Ewl_Paned_Pane_Info; /** @@ -42,7 +44,19 @@ static void ewl_paned_grabbers_update(Ewl_Paned *p); static void ewl_paned_layout_setup(void); -static int ewl_paned_widgets_place(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, Ewl_Paned_Layout *layout); +static int ewl_paned_pane_info_setup(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + Ewl_Paned_Layout *layout, int *resizable); + +static int ewl_paned_pane_info_collect(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + Ewl_Paned_Layout *layout, int *resizable, int grabber_size); +static void ewl_paned_pane_info_layout(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + Ewl_Paned_Layout *layout, int available, + int resizable); + +static void ewl_paned_widgets_place(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + int grabber_size); + +static int ewl_paned_grapper_size_get(Ewl_Paned *p); /** * @return Returns NULL on failure, or a pointer to a new paned widget on success. @@ -133,6 +147,8 @@ ewl_callback_append(w, EWL_CALLBACK_CONFIGURE, ewl_paned_cb_configure, NULL); + ewl_callback_append(w, EWL_CALLBACK_DESTROY, + ewl_paned_cb_destroy, NULL); ewl_object_fill_policy_set(EWL_OBJECT(w), EWL_FLAG_FILL_FILL); ewl_object_alignment_set(EWL_OBJECT(w), EWL_FLAG_ALIGN_LEFT | @@ -190,6 +206,51 @@ } /** + * @param p: The paned to work with + * @param child: The child widget to set the initial size + * @param size: the size to set + * @return Returns no value. + * @brief Set the initial size of a pane in px + */ +void +ewl_paned_initial_size_set(Ewl_Paned *p, Ewl_Widget *child, int size) +{ + Ewl_Paned_Size_Info *info; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("p", p); + DCHECK_TYPE("p", p, EWL_PANED_TYPE); + + info = ewl_paned_size_info_add(p, child); + info->initial_size = size; + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/** + * @param p: The paned to work with + * @param child: The child widget to get the initial size + * @return Returns the initial size that is set to the given widget. If there + * isn't any size set, it'll return 0. + * @brief Get the initial size of a pane in px + */ +int +ewl_paned_initial_size_get(Ewl_Paned *p, Ewl_Widget *child) +{ + Ewl_Paned_Size_Info *info; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("p", p, 0); + DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, 0); + + info = ewl_paned_size_info_get(p, child); + if (!info) + DRETURN_INT(0, DLEVEL_STABLE); + + DRETURN_INT(info->initial_size, DLEVEL_STABLE); +} + +/** * @internal * @param c: The container to work with * @param w: The widget to work with @@ -253,10 +314,12 @@ /* 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_pane == o) + ewl_widget_destroy(o); + + if (p->last_pane == w) p->last_pane = NULL; - ewl_widget_destroy(o); + ewl_paned_size_info_del(p, w); ewl_paned_grabbers_update(EWL_PANED(c)); DLEAVE_FUNCTION(DLEVEL_STABLE); @@ -348,12 +411,10 @@ { Ewl_Paned *p; Ewl_Container *c; - Ewl_Widget *child = NULL; Ewl_Paned_Pane_Info *panes; - int available = 0, pane_num; - int main_pos, main_size, cur_pos, cur_size; - int grabber_size = 0, resizable, i; - const int *xx, *yy, *ww, *hh; + int available, pane_num; + int main_size, main_pos; + int grabber_size, resizable = 0; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); @@ -367,20 +428,12 @@ layout = horizontal_layout; main_size = CURRENT_W(w); main_pos = CURRENT_X(w); - xx = &cur_pos; - yy = &CURRENT_Y(w); - ww = &cur_size; - hh = &CURRENT_H(w); } else { layout = vertical_layout; main_size = CURRENT_H(w); main_pos = CURRENT_Y(w); - xx = &CURRENT_X(w); - yy = &cur_pos; - ww = &CURRENT_W(w); - hh = &cur_size; } if (ecore_dlist_empty_is(c->children)) @@ -390,76 +443,226 @@ pane_num = (ewl_container_child_count_visible_get(c) + 1)/2; panes = alloca(sizeof(Ewl_Paned_Pane_Info) * pane_num); + grabber_size = ewl_paned_grapper_size_get(p); + /* if there are new widgets we place them first */ - if (p->new_panes) { - available = ewl_paned_widgets_place(p, panes, layout); - p->new_panes = 0; - } - else - { - /* We haven't moved the widgets yet. Let us now get their - * previous position so we can determine the size of the - * space they had */ - int prev_pos = p->last_pos; - i = 0; + if (p->new_panes) + available = ewl_paned_pane_info_setup(p, panes, layout, + &resizable); + else + available = ewl_paned_pane_info_collect(p, panes, layout, + &resizable, grabber_size); + + + available = main_size - grabber_size * (pane_num - 1) - available; + + ewl_paned_pane_info_layout(p, panes, layout, available, resizable); + /* now that all of the space is filled we can go and layout all of + * the available widgets */ + ewl_paned_widgets_place(p, panes, grabber_size); + + p->last_size = main_size; + p->last_pos = main_pos; + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/** + * @internal + * @param w: The widget to work with + * @param ev: UNUSED + * @param data: UNUSED + * @return Returns no value + * @brief The destroy callback + */ +void +ewl_paned_cb_destroy(Ewl_Widget *w, void *ev __UNUSED__, + void *data __UNUSED__) +{ + Ewl_Paned *p; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("w", w); + DCHECK_TYPE("w", w, EWL_PANED_TYPE); + + p = EWL_PANED(w); + IF_FREE(p->info); + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +/* Look at all of the grabbers and show/hide them as needed */ +static void +ewl_paned_grabbers_update(Ewl_Paned *p) +{ + Ewl_Widget *child, *g = NULL; + Ewl_Container *c; + int left = 0; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("p", p); + DCHECK_TYPE("p", p, EWL_PANED_TYPE); + + if (p->updating_grabbers) + DRETURN(DLEVEL_STABLE); - /* get size infos of the children */ - ecore_dlist_first_goto(c->children); - while ((child = ecore_dlist_next(c->children))) + p->updating_grabbers = 1; + + c = EWL_CONTAINER(p); + ecore_dlist_first_goto(c->children); + while ((child = ecore_dlist_next(c->children))) + { + /* internal means grabber */ + if (EWL_PANED_GRABBER_IS(child)) + { + /* if there is a widget to the left we store the + * grabber */ + if (left) g = child; + ewl_widget_hide(child); + } + else if (VISIBLE(child)) { - int pos; + left = 1; - if (!VISIBLE(child)) - continue; - if (!EWL_PANED_GRABBER_IS(child)) + /* if we have a grabber to the left of us we need to + * show it as that means there is a widget to the + * left of us */ + if (g) { - panes[i].pane = child; - continue; + ewl_widget_show(g); + g = NULL; } - /* get the grabber size if needed */ - if (!grabber_size) - grabber_size = - layout->current_size(EWL_OBJECT(child)); - - pos = layout->current_position(EWL_OBJECT(child)); - panes[i].size = pos - prev_pos; - available += panes[i].size; - prev_pos = pos + grabber_size; - i++; } - /* only the last position is not set because we have no grabber - * at the end */ - panes[i].size = p->last_size - (prev_pos - p->last_pos); - available += panes[i].size; } - if (!grabber_size) + p->updating_grabbers = 0; + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +static int +ewl_paned_pane_info_setup(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + Ewl_Paned_Layout *layout, int *resizable) +{ + Ewl_Widget *child; + Ewl_Container *c; + int available = 0; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("p", p, 0); + DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, 0); + DCHECK_PARAM_PTR_RET("layout", layout, 0); + + c = EWL_CONTAINER(p); + + ecore_dlist_first_goto(c->children); + while ((child = ecore_dlist_next(c->children))) { - ecore_list_first_goto(c->children); - while ((child = ecore_list_next(c->children))) + if (!VISIBLE(child) || EWL_PANED_GRABBER_IS(child)) + continue; + + panes->info = ewl_paned_size_info_get(p, child); + panes->pane = child; + + if (!panes->info) { - if (!VISIBLE(child) || !EWL_PANED_GRABBER_IS(child)) - continue; - grabber_size = layout->current_size(EWL_OBJECT(child)); - break; + panes->size = layout->minimum_size(EWL_OBJECT(child)); + (*resizable)++; + panes->fixed = FALSE; } + else + { + panes->size = panes->info->initial_size; + panes->fixed = TRUE; + } + + available += panes->size; + panes++; } + + p->new_panes = FALSE; + + DRETURN_INT(available, DLEVEL_STABLE); +} + +static int +ewl_paned_pane_info_collect(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + Ewl_Paned_Layout *layout, int *resizable, int grabber_size) +{ + Ewl_Container *c; + Ewl_Widget *child; + int prev_pos; + int i = 0; + int available = 0; - available = main_size - grabber_size * (pane_num - 1) - available; - resizable = pane_num; + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("p", p, 0); + DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, 0); + + prev_pos = p->last_pos; + c = EWL_CONTAINER(p); + + /* We haven't moved the widgets yet. Let us now get their + * previous position so we can determine the size of the + * space they had */ + ecore_dlist_first_goto(c->children); + while ((child = ecore_dlist_next(c->children))) + { + int pos; + + if (!VISIBLE(child)) + continue; + if (!EWL_PANED_GRABBER_IS(child)) + { + panes[i].pane = child; + panes[i].info = ewl_paned_size_info_get(p, child); + continue; + } + + panes[i].fixed = FALSE; + pos = layout->current_position(EWL_OBJECT(child)); + panes[i].size = pos - prev_pos; + available += panes[i].size; + prev_pos = pos + grabber_size; + i++; + } + /* only the last position is not set because we have no grabber + * at the end */ + panes[i].fixed = FALSE; + panes[i].size = p->last_size - (prev_pos - p->last_pos); + available += panes[i].size; + + *resizable = i + 1; + + DRETURN_INT(available, DLEVEL_STABLE); +} + +static void +ewl_paned_pane_info_layout(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + Ewl_Paned_Layout *layout, int available, + int resizable) +{ + int pane_num = + (ewl_container_child_count_visible_get(EWL_CONTAINER(p)) + 1)/2; + int cur_res = resizable; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("p", p); + DCHECK_TYPE("p", p, EWL_PANED_TYPE); while (available != 0) { int give; + int i; /* if we have no panes we don't need to calc their place */ - if (resizable < 1) + if (cur_res < 1) break; /* give can also be negative, so see it as a can take or give */ - give = available / resizable; + give = available / cur_res; /* reset the resizable pane_num now */ - resizable = pane_num; + cur_res = resizable; i = 0; /* to prevent rounding errors */ if (give == 0) { @@ -482,12 +685,15 @@ { int min; + if (panes[i].fixed) + continue; + min = layout->minimum_size(EWL_OBJECT(panes[i].pane)); if (min > panes[i].size + give) { available -= panes[i].size - min; panes[i].size = min; - resizable--; + cur_res--; } else { available -= give; @@ -502,11 +708,41 @@ } } } + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} - /* now that all of the space is filled we can go and layout all of - * the available widgets */ - cur_pos = main_pos; - i = 0; +static void +ewl_paned_widgets_place(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, + int grabber_size) +{ + Ewl_Container *c; + Ewl_Widget *child; + int cur_pos, cur_size; + const int *x, *y, *w, *h; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("p", p); + DCHECK_TYPE("p", p, EWL_PANED_TYPE); + + c = EWL_CONTAINER(p); + + if (ewl_paned_orientation_get(p) == EWL_ORIENTATION_HORIZONTAL) + { + cur_pos = CURRENT_X(p); + x = &cur_pos; + y = &CURRENT_Y(p); + w = &cur_size; + h = &CURRENT_H(p); + } + else + { + cur_pos = CURRENT_Y(p); + x = &CURRENT_X(p); + y = &cur_pos; + w = &CURRENT_W(p); + h = &cur_size; + } ecore_dlist_first_goto(c->children); while ((child = ecore_dlist_next(c->children))) @@ -517,64 +753,128 @@ if (EWL_PANED_GRABBER_IS(child)) cur_size = grabber_size; else - cur_size = panes[i++].size; + cur_size = (panes++)->size; - ewl_object_place(EWL_OBJECT(child), *xx, *yy, *ww, *hh); + ewl_object_place(EWL_OBJECT(child), *x, *y, *w, *h); cur_pos += cur_size; } - p->last_size = main_size; - p->last_pos = main_pos; - DLEAVE_FUNCTION(DLEVEL_STABLE); } -/* Look at all of the grabbers and show/hide them as needed */ -static void -ewl_paned_grabbers_update(Ewl_Paned *p) +static int +ewl_paned_grapper_size_get(Ewl_Paned *p) { - Ewl_Widget *child, *g = NULL; Ewl_Container *c; - int left = 0; + Ewl_Widget *child; + c = EWL_CONTAINER(p); + DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR("p", p); - DCHECK_TYPE("p", p, EWL_PANED_TYPE); + DCHECK_PARAM_PTR_RET("p", p, 0); + DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, 0); - if (p->updating_grabbers) - DRETURN(DLEVEL_STABLE); + ecore_list_first_goto(c->children); + while ((child = ecore_list_next(c->children))) + { + if (!VISIBLE(child) || !EWL_PANED_GRABBER_IS(child)) + continue; + + DRETURN_INT(layout->current_size(EWL_OBJECT(child)), + DLEVEL_STABLE); + } - p->updating_grabbers = 1; + DRETURN_INT(0, DLEVEL_STABLE); +} - c = EWL_CONTAINER(p); - ecore_dlist_first_goto(c->children); - while ((child = ecore_dlist_next(c->children))) - { - /* internal means grabber */ - if (EWL_PANED_GRABBER_IS(child)) - { - /* if there is a widget to the left we store the - * grabber */ - if (left) g = child; - ewl_widget_hide(child); - } - else if (VISIBLE(child)) - { - left = 1; - /* if we have a grabber to the left of us we need to - * show it as that means there is a widget to the - * left of us */ - if (g) - { - ewl_widget_show(g); - g = NULL; - } - } +/* + * Ewl_Paned_Size_Info stuff + */ +Ewl_Paned_Size_Info * +ewl_paned_size_info_add(Ewl_Paned *p, Ewl_Widget *w) +{ + Ewl_Paned_Size_Info *info; + int i; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("p", p, NULL); + DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, NULL); + + + /* if we already have a info item for this widget we don't need + * to create one */ + info = ewl_paned_size_info_get(p, w); + if (info) + DRETURN_PTR(info, DLEVEL_STABLE); + + /* ok we don't have found one first we have to resize our array */ + p->info = realloc(p->info, (p->info_size + 1) + * sizeof(Ewl_Paned_Size_Info)); + /* now we need to find the position for the new info item */ + for (i = 0; i < p->info_size; i++) + { + if (p->info[i].child > w) + break; } + /* move the rest so we can insert it */ + memmove(p->info + i + 1, p->info + i, + sizeof(Ewl_Paned_Size_Info) * (p->info_size - i)); + memset(p->info + i, 0, sizeof(Ewl_Paned_Size_Info)); + p->info[i].child = w; + p->info_size++; - p->updating_grabbers = 0; + DRETURN_PTR(p->info + i, DLEVEL_STABLE); +} + +static int +ewl_paned_size_info_compare(const void *key1, const void *key2) +{ + const Ewl_Paned_Size_Info *info1, *info2; + + DENTER_FUNCTION(DLEVEL_STABLE); + + info1 = key1; + info2 = key2; + + DRETURN_INT(ecore_direct_compare(info1->child, info2->child), + DLEVEL_STABLE); +} + +Ewl_Paned_Size_Info * +ewl_paned_size_info_get(Ewl_Paned *p, Ewl_Widget *w) +{ + Ewl_Paned_Size_Info info; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("p", p, NULL); + DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, NULL); + + memset(&info, 0, sizeof(Ewl_Paned_Size_Info)); + info.child = w; + + DRETURN_PTR(bsearch(&info, p->info, p->info_size, + sizeof(Ewl_Paned_Size_Info), + ewl_paned_size_info_compare), DLEVEL_STABLE); +} + +void +ewl_paned_size_info_del(Ewl_Paned *p, Ewl_Widget *w) +{ + Ewl_Paned_Size_Info *info; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("p", p); + DCHECK_TYPE("p", p, EWL_PANED_TYPE); + + info = ewl_paned_size_info_get(p, w); + if (!info) + DRETURN(DLEVEL_STABLE); + + memmove(info, info + 1, (p->info_size - (info - p->info) + 1) + * sizeof(Ewl_Paned_Size_Info)); + p->info = realloc(p->info, --p->info_size); DLEAVE_FUNCTION(DLEVEL_STABLE); } @@ -969,38 +1269,6 @@ vertical_layout->stable_position_request = ewl_object_x_request; DLEAVE_FUNCTION(DLEVEL_STABLE); -} - -static int -ewl_paned_widgets_place(Ewl_Paned *p, Ewl_Paned_Pane_Info *panes, - Ewl_Paned_Layout *layout) -{ - Ewl_Widget *child; - Ewl_Container *c; - int available = 0; - - DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR_RET("p", p, 0); - DCHECK_TYPE_RET("p", p, EWL_PANED_TYPE, 0); - DCHECK_PARAM_PTR_RET("layout", layout, 0); - - c = EWL_CONTAINER(p); - - ecore_dlist_first_goto(c->children); - while ((child = ecore_dlist_next(c->children))) - { - if (!VISIBLE(child) || EWL_PANED_GRABBER_IS(child)) - continue; - - panes->size = layout->minimum_size(EWL_OBJECT(child)); - panes->pane = child; - available += panes->size; - panes++; - } - - p->new_panes = FALSE; - - DRETURN_INT(available, DLEVEL_STABLE); } static void =================================================================== RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_paned.h,v retrieving revision 1.31 retrieving revision 1.32 diff -u -3 -r1.31 -r1.32 --- ewl_paned.h 2 Nov 2007 01:28:30 -0000 1.31 +++ ewl_paned.h 4 Nov 2007 23:13:07 -0000 1.32 @@ -24,6 +24,20 @@ */ /** + * The Ewl_Paned_Size_Info structure + */ +typedef struct Ewl_Paned_Size_Info Ewl_Paned_Size_Info; + +/** + * @brief Holds some information about the children. It is only used internally. + */ +struct Ewl_Paned_Size_Info +{ + Ewl_Widget *child; + int initial_size; +}; + +/** * @def EWL_PANED_TYPE * The type name for the Ewl_Paned widget */ @@ -57,6 +71,8 @@ int last_pos; /**< the last position */ int last_size; /**< the last size */ Ewl_Widget *last_pane; /**< a pointer to the last resized pane */ + Ewl_Paned_Size_Info *info; /**< The extra infos for the children */ + int info_size; /**< The size of the info array */ unsigned short updating_grabbers:1; /**< are we updating the grabbers */ unsigned short new_panes:1; /**< are there new visible panes */ }; @@ -68,10 +84,17 @@ void ewl_paned_orientation_set(Ewl_Paned *p, Ewl_Orientation o); Ewl_Orientation ewl_paned_orientation_get(Ewl_Paned *p); +void ewl_paned_initial_size_set(Ewl_Paned *p, Ewl_Widget *child, + int size); +int ewl_paned_initial_size_get(Ewl_Paned *p, Ewl_Widget *child); /* * Internal functions. Override at your risk. */ +Ewl_Paned_Size_Info *ewl_paned_size_info_add(Ewl_Paned *p, Ewl_Widget *w); +Ewl_Paned_Size_Info *ewl_paned_size_info_get(Ewl_Paned *p, Ewl_Widget *w); +void ewl_paned_size_info_del(Ewl_Paned *p, Ewl_Widget *w); + void ewl_paned_cb_child_add(Ewl_Container *c, Ewl_Widget *w); void ewl_paned_cb_child_remove(Ewl_Container *c, Ewl_Widget *w, int idx); void ewl_paned_cb_child_show(Ewl_Container *c, Ewl_Widget *w); ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs