note
	description : "Objects that ..."
	author      : "$Author$"
	date        : "$Date$"
	revision    : "$Revision$"

deferred class
	WSF_WIDGET_COMPOSITE

inherit
	ITERABLE [WSF_WIDGET]

feature {NONE} -- Initialization

	initialize_with_count (n: INTEGER)
		do
			create items.make (n)
		end

feature -- Status

	is_empty: BOOLEAN
		do
			Result := count = 0
		end

	has_item (i: WSF_WIDGET): BOOLEAN
		do
			if has_immediate_item (i) then
				Result := True
			else
				across
					items as c
				loop
					if attached {WSF_WIDGET_COMPOSITE} c.item as comp then
						Result := comp.has_item (i)
					end
				end
			end
		end

	has_immediate_item (i: WSF_WIDGET): BOOLEAN
		do
			Result := items.has (i)
		end

feature -- Access: cursor

	new_cursor: ITERATION_CURSOR [WSF_WIDGET]
			-- Fresh cursor associated with current structure
		do
			Result := items.new_cursor
		end

feature -- Access

	count: INTEGER
		do
			Result := immediate_count
			across
				items as c
			loop
				if attached {WSF_WIDGET_COMPOSITE} c.item as comp then
					Result := Result + comp.count
				end
			end
		end

	immediate_count: INTEGER
		do
			Result := items.count
		end

	items_by_type (a_type: TYPE [detachable ANY]): detachable LIST [WSF_WIDGET]
			-- All WSF_WIDGET items conforming to a_type.
			-- Warning: you should pass {detachable WSF_FORM_SUBMIT_INPUT}  rather than just {WSF_FORM_SUBMIT_INPUT}
		local
			int: INTERNAL
			tid: INTEGER
			t: TYPE [detachable ANY]
		do
			tid := a_type.type_id
			create int
			tid := int.detachable_type (tid)
			if tid > 0 then
				t := int.type_of_type (tid)
				if not a_type.conforms_to (t) then
					t := a_type
				end
			else
				t := a_type
			end
			Result := items_by_type_from (Current, t)
		end

	items_by_css_id (a_id: READABLE_STRING_GENERAL): detachable LIST [WSF_WIDGET]
		do
			Result := items_by_css_id_from (Current, a_id)
		end

	first_item_by_css_id (a_id: READABLE_STRING_GENERAL): detachable WSF_WIDGET
		do
			if attached items_by_css_id_from (Current, a_id) as lst then
				if not lst.is_empty then
					Result := lst.first
				end
			end
		end

feature -- Change

	insert_before (i: WSF_WIDGET; a_item: WSF_WIDGET)
			-- Insert `i' before `a_item'
		require
			has_item (a_item)
		local
			done: BOOLEAN
		do
			if has_immediate_item (a_item) then
				items.start
				items.search (a_item)
				if items.exhausted then
					items.put_front (i)
				else
					items.put_left (i)
				end
			else
				across
					items as c
				until
					done
				loop
					if attached {WSF_WIDGET_COMPOSITE} c.item as comp and then comp.has_item (a_item) then
						comp.insert_before (i, a_item)
						done := True
					end
				end
			end
		end

	insert_after (i: WSF_WIDGET; a_item: WSF_WIDGET)
			-- Insert `i' after `a_item'
		require
			has_item (a_item)
		local
			done: BOOLEAN
		do
			if has_immediate_item (a_item) then
				items.start
				items.search (a_item)
				if items.exhausted then
					items.force (i)
				else
					items.put_right (i)
				end
			else
				across
					items as c
				until
					done
				loop
					if attached {WSF_WIDGET_COMPOSITE} c.item as comp and then comp.has_item (a_item) then
						comp.insert_after (i, a_item)
						done := True
					end
				end
			end
		end

	extend (i: WSF_WIDGET)
		do
			items.force (i)
		end

	prepend (i: WSF_WIDGET)
		do
			items.put_front (i)
		end

	extend_html_text (t: READABLE_STRING_8)
			-- Extend a widget encapsulating html code `t'
		do
			extend (create {WSF_WIDGET_TEXT}.make_with_text (t))
		end

	extend_text (t: READABLE_STRING_8)
		obsolete "Use extend_html_text (..) [2017-05-31]"
		do
			extend_html_text (t)
		end

	extend_raw_text (t: READABLE_STRING_GENERAL)
			-- Extend a widget encapsulating html encoded text `t'
		do
			extend (create {WSF_WIDGET_RAW_TEXT}.make_with_text (t))
		end

feature {NONE} -- Implementation: Items

	items_by_type_from (a_container: ITERABLE [WSF_WIDGET]; a_type: TYPE [detachable ANY]): detachable ARRAYED_LIST [WSF_WIDGET]
		local
			res: detachable ARRAYED_LIST [WSF_WIDGET]
		do
			across
				a_container as i
			loop
				if i.item.generating_type.conforms_to (a_type) then
					if res = Void then
						create res.make (1)
					end
					res.force (i.item)
				elseif attached {ITERABLE [WSF_WIDGET]} i.item as l_cont then
					if attached items_by_type_from (l_cont, a_type) as lst then
						if res = Void then
							res := lst
						else
							res.append (lst)
						end
					end
				end
			end
			Result := res
		end

	items_by_css_id_from (a_container: ITERABLE [WSF_WIDGET]; a_id: READABLE_STRING_GENERAL): detachable ARRAYED_LIST [WSF_WIDGET]
		local
			res: detachable ARRAYED_LIST [WSF_WIDGET]
		do
			across
				a_container as i
			loop
				if
					attached {WSF_WITH_CSS_ID} i.item as l_with_css_id and then
					attached l_with_css_id.css_id as l_css_id and then
					l_css_id.same_string_general (a_id)
				then
					if res = Void then
						create res.make (1)
					end
					res.force (i.item)
				elseif attached {ITERABLE [WSF_WIDGET]} i.item as l_cont then
					if attached items_by_css_id_from (l_cont, a_id) as lst then
						if res = Void then
							res := lst
						else
							res.append (lst)
						end
					end
				end
			end
			Result := res
		end

feature {NONE} -- Implementation

	items: ARRAYED_LIST [WSF_WIDGET]
			-- name => item

invariant
	items /= Void


end
