ANY CONTAINER LAYOUT NONE WIDGET
class interface CONTAINER
   -- A CONTAINER is designed to contain many widgets (called children).
   -- Children are arranged in the container using some LAYOUT, and painted.
   -- The CONTAINER may be seen as a shell: if the container is not
   -- shrinkable, it will not shrink any of it's children. If the
   -- container is shrinkable, it may shrink children that are shrinkable
   -- but never shrink not shrinkable children (it's like a shell again).
   --
   -- The LAYOUT is an algorithm attached to the container. It has to
   -- decide size and position for children.
   --

creation
   default_create
      -- Default creation method. It is used when no creation
      -- method is specified if allowed. Note it may be renamed.

   make_layout (p: CONTAINER; lo: LAYOUT)
      require
         p /= Void;
         lo /= Void;
         lo.container = Void
      ensure
         parent = p;
         layout = lo

feature(s) from STATE
   state: INTEGER
      -- use values from STATE_CONSTANTS

   is_state_normal: BOOLEAN

   is_state_active: BOOLEAN

   is_state_prelight: BOOLEAN

   is_state_selected: BOOLEAN

   is_state_insensitive: BOOLEAN

feature(s) from WIDGET
   parent: CONTAINER

   pos_x: INTEGER

   pos_y: INTEGER

   x_shrink_allowed: BOOLEAN

   x_expand_allowed: BOOLEAN

   y_shrink_allowed: BOOLEAN

   y_expand_allowed: BOOLEAN

   min_width: INTEGER

   min_height: INTEGER

   std_width: INTEGER

   std_height: INTEGER

   width: INTEGER

   height: INTEGER

   valid_width (w: INTEGER): BOOLEAN

   valid_height (h: INTEGER): BOOLEAN

   area: RECT

   root_area: RECT

   set_x_shrink (b: BOOLEAN)

   set_x_expand (b: BOOLEAN)

   set_y_shrink (b: BOOLEAN)

   set_y_expand (b: BOOLEAN)

   set_shrink (b: BOOLEAN)
      -- change both x and y shrink state

   set_expand (b: BOOLEAN)
      -- change both x and y expand state

feature(s) from WIDGET
   set_parent (p: CONTAINER)
      require
         p = Void implies parent /= Void;
         p /= Void implies parent = Void;
         p /= Void implies p.has_child(Current)
      ensure
         parent = p

feature(s) from DRAWABLE
   clear_without_expose
      -- clear the all the drawable area.
      -- WARNING: don't redraw the content (no expose event)

feature(s) from DRAWABLE
   drawing_widget: POINTER
      -- Because Windows can not paint on widgets like windows or bitmaps,
      -- it needs another object (Device Context) attached to the widget.
      -- For X11, it is the same value as widget.

feature(s) from HASHABLE
   hash_code: INTEGER
      -- The hash-code value of Current.
      ensure
         good_hash_value: Result >= 0

feature(s) from SENSITIVE
   widget: POINTER
      -- widget identifier from the native graphic API.

feature(s) from CONTAINER
   layout: LAYOUT

   child: FAST_ARRAY[WIDGET]
      -- feature ANY for require validity

   layout_update_paused: BOOLEAN
      --TODO: suppress. Handle this with mapped

   set_layout (l: LAYOUT)
      -- Change the layout for the container (layout choose children
      -- position and size). The layout has to be free (not used
      -- by another container).
      require
         l /= Void;
         l.container = Void
      ensure
         layout = l;
         layout.container = Current;
         not layout_update_paused implies layout_ready

   layout_pause
      --TODO: remove when mapped ready
      require
         not layout_update_paused
      ensure
         layout_update_paused

   layout_continue
      --TODO: remove when mapped ready
      require
         layout_update_paused
      ensure
         layout_ready;
         not layout_update_paused

   child_attach (w: WIDGET)
      -- Add widget w in this container.
      require
         layout /= Void;
         w /= Void;
         w.parent = Void;
         not has_child(w)
      ensure
         w.parent = Current;
         has_child(w);
         last_child = w;
         not layout_update_paused implies layout_ready or not done

   child_detach (w: WIDGET)
      -- Remove widget w from this container.
      require
         w /= Void;
         has_child(w)
      ensure
         child.count = old child.count - 1;
         not has_child(w);
         w.parent = Void;
         not layout_update_paused implies layout_ready

   has_child (w: WIDGET): BOOLEAN

   last_child: WIDGET
      require
         not is_empty

   is_empty: BOOLEAN

   clear_area (x, y, w, h: INTEGER)
      -- clear area and emit expose event (contents will be drawn)
      -- x and y are relative to current object
      require
         w > 0;
         h > 0;
         area.include(x,y);
         area.include(x + w - 1,y + h - 1)

   refresh
      -- clear and update entire object (sub_window(s) are not updated).

   clear
      -- clear and update entire object (sub_window(s) are not updated).

   as_x_root (x: INTEGER): INTEGER
      require
         x >= pos_x;
         x < pos_x + width

   as_y_root (y: INTEGER): INTEGER
      require
         y >= pos_y;
         y < pos_y + height

feature(s) from CONTAINER
   done: BOOLEAN
      --TODO: suppress. Handle this with mapped

   child_requisition_changed
      require
         layout /= Void
      ensure
         not layout_update_paused implies layout_ready or not done

feature(s) from CONTAINER
   layout_ready: BOOLEAN


invariant

    child /= Void;

    width >= min_width or computing_size;

    height >= min_height or computing_size;

    std_width > 0;

    std_height > 0;

    (not x_shrink_allowed implies width >= std_width) or computing_size;

    (not x_expand_allowed implies width <= std_width) or computing_size;

    (not y_shrink_allowed implies height >= std_height) or computing_size;

    (not y_expand_allowed implies height <= std_height) or computing_size;

end of CONTAINER