note description: "EiffelVision vertical box. Puts child widgets in a column. Cocoa implementation." author: "Daniel Furrer " keywords: "container, box, vertical" date: "$Date$" revision: "$Revision$" class EV_VERTICAL_BOX_IMP inherit EV_VERTICAL_BOX_I undefine propagate_foreground_color, propagate_background_color redefine interface end EV_BOX_IMP redefine interface end create make feature -- Access children_height: INTEGER -- Sum of the width of all the children. feature -- Basic operation ev_apply_new_size (a_x_position, a_y_position, a_width, a_height: INTEGER; repaint: BOOLEAN) do ev_move_and_resize (a_x_position, a_y_position, a_width, a_height, repaint) set_children_height (a_height, False) end -- TODO?: abstract to box to avoid duplicated code set_children_height (a_height: INTEGER; originator: BOOLEAN) -- Move and resize the children to have them adapted to the -- current height. local litem: EV_WIDGET_IMP rate, total_rest, y: INTEGER children_size, item_height: INTEGER item_width: INTEGER cur: CURSOR int1, int2: INTEGER do if childvisible_nb /= 0 then cur := ev_children.cursor item_width := client_width children_size := a_height - 2 * border_width - total_spacing -- Homogeneous state : only the visible children are -- important. if is_homogeneous then rate := children_size // childvisible_nb total_rest := children_size \\ childvisible_nb from y := border_width ev_children.start until ev_children.after loop litem := ev_children.item if litem.is_show_requested then item_height := rate + rest (total_rest) total_rest := (total_rest - 1).max (0) if originator then litem.ev_move_and_resize (border_width, y, item_width, item_height, True) else litem.ev_apply_new_size (border_width, y, item_width, item_height, True) end y := y + padding + item_height end ev_children.forth end -- Non homogeneous state : we have to be carefull to the non -- expanded children too. else int1 := children_size - children_height int2 := childexpand_nb.max (1) -- It is possible that int1 < 0. -- This occurs when `Current' has a minimum width and -- the children are larger. Because of the minimum -- width, `Current' does not expand. if int1 >= 0 then rate := int1 // int2 total_rest := int1 \\ int2 else rate := 0 total_rest := 0 end -- Then, we ask the children to move and resize. -- Be carefull to the expanded child. from y := border_width ev_children.start until ev_children.after or not ev_children.valid_index (ev_children.index) loop litem := ev_children.item if litem.is_show_requested then if litem.is_expandable then item_height := litem.minimum_height + rate + rest (total_rest) if total_rest > 0 then total_rest := total_rest - 1 elseif total_rest < 0 then total_rest := total_rest + 1 end else item_height := litem.minimum_height end if originator then litem.ev_move_and_resize (border_width, y, item_width, item_height, True) else litem.ev_apply_new_size (border_width, y, item_width, item_height, True) end y := y + padding + item_height end ev_children.forth end -- loop. end -- is_homogeneous. if ev_children.valid_cursor (cur) then ev_children.go_to (cur) end end end feature {NONE} -- Implementation for automatic size compute compute_minimum_height -- Recompute the minimum_height of `Current'. local litem: EV_WIDGET_IMP cur: CURSOR value, nb_visi: INTEGER do childvisible_nb := 0 if not ev_children.is_empty then cur := ev_children.cursor if is_homogeneous then from ev_children.start until ev_children.after loop litem := ev_children.item if litem.is_show_requested then nb_visi := nb_visi + 1 value := value.max (litem.minimum_height) end ev_children.forth end childvisible_nb := nb_visi compute_childexpand_nb internal_set_minimum_height (value * nb_visi + total_spacing + 2 * border_width) else from ev_children.start until ev_children.after loop litem := ev_children.item if litem.is_show_requested then nb_visi := nb_visi + 1 value := value + litem.minimum_height end ev_children.forth end children_height := value childvisible_nb := nb_visi compute_childexpand_nb internal_set_minimum_height (value + total_spacing + 2 * border_width) end if ev_children.valid_cursor (cur) then ev_children.go_to (cur) end else children_height := 0 internal_set_minimum_height (2 * border_width) end end compute_minimum_width -- Recompute the minimum_width of `Current'. local litem: EV_WIDGET_IMP cur: CURSOR value, nb_visi: INTEGER do childvisible_nb := 0 -- TODO: is this check really needed before the loop?? if not ev_children.is_empty then from cur := ev_children.cursor ev_children.start until ev_children.after loop litem := ev_children.item if litem.is_show_requested then nb_visi := nb_visi + 1 value := value.max (litem.minimum_width) end ev_children.forth end if ev_children.valid_cursor (cur) then ev_children.go_to (cur) end childvisible_nb := nb_visi compute_childexpand_nb end internal_set_minimum_width (value + 2 * border_width) end compute_minimum_size -- Recompute both the minimum_width and the minimum_height of -- `Current'. local litem: EV_WIDGET_IMP cur: CURSOR hvalue, wvalue, nb_visi: INTEGER do childvisible_nb := 0 if not ev_children.is_empty then cur := ev_children.cursor if is_homogeneous then from ev_children.start until ev_children.after loop litem := ev_children.item if litem.is_show_requested then nb_visi := nb_visi + 1 wvalue := wvalue.max (litem.minimum_width) hvalue := hvalue.max (litem.minimum_height) end ev_children.forth end childvisible_nb := nb_visi compute_childexpand_nb internal_set_minimum_size (wvalue + 2 * border_width, hvalue * nb_visi + total_spacing + 2 * border_width) else from ev_children.start until ev_children.after loop litem := ev_children.item if litem.is_show_requested then nb_visi := nb_visi + 1 wvalue := wvalue.max (litem.minimum_width) hvalue := hvalue + litem.minimum_height end ev_children.forth end children_height := hvalue childvisible_nb := nb_visi compute_childexpand_nb internal_set_minimum_size (wvalue + 2 * border_width, hvalue + total_spacing + 2 * border_width) end if ev_children.valid_cursor (cur) then ev_children.go_to (cur) end else children_height := 0 internal_set_minimum_size (2 * border_width, 2 * border_width) end end feature {EV_ANY, EV_ANY_I} -- Implementation interface: detachable EV_VERTICAL_BOX note option: stable attribute end; note copyright: "Copyright (c) 1984-2019, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class EV_VERTICAL_BOX_IMP