note
	description: "Eiffel Vision menu item. Mswindows implementation."
	legal: "See notice at end of class."
	status: "See notice at end of class."
	date: "$Date$"
	revision: "$Revision$"

class
	EV_MENU_ITEM_IMP

inherit
	EV_MENU_ITEM_I
		redefine
			interface,
			parent
		end

	EV_ITEM_IMP
		undefine
			parent
		redefine
			interface,
			set_capture,
			release_capture,
			set_heavy_capture,
			release_heavy_capture,
			remove_pixmap,
			set_pixmap,
			top_level_window_imp
		end

	EV_TEXTABLE_IMP
		redefine
			interface,
			set_text,
			text
		end

	EV_ID_IMP

	WEL_WINDOWS_ROUTINES
		export
			{NONE} all
		end

	WEL_CONSTANTS
		export
			{NONE} all
		end

	WEL_SHARED_FONTS
		export
			{NONE} all
		end

	WEL_SYSTEM_COLORS
		export
			{NONE} all
		end

	WEL_WINDOWS_VERSION
		export
			{NONE} all
		end

	WEL_SYSTEM_PARAMETERS_INFO
		export
			{NONE} all
		end

	DISPOSABLE
		export
			{NONE} all
		end

create
	make

feature -- Initialization

	old_make (an_interface: attached like interface)
			-- Create the menu item.
		do
			assign_interface (an_interface)
		end

	make
			-- Initialize `is_sensitive' True.
		do
			make_id
			is_sensitive := True
			set_is_initialized (True)
			set_text ("")
		end

feature -- Access

	text: STRING_32
			-- Text displayed in label.
		do
			Result := wel_text
		end

	object_id: INTEGER
			-- Run-time object Id of `Current'.
		do
			if internal_object_id = 0 then
				internal_object_id := eif_object_id (Current)
			end
			Result := internal_object_id
		end

feature -- Element change

	set_text (a_text: READABLE_STRING_GENERAL)
			-- Assign `a_text' to `text'.
		do
			wel_set_text (a_text)
		end

feature -- Status report

	is_sensitive: BOOLEAN
			-- Can this item be clicked on?
			--| is not a function because we do not want to block the
			-- user from setting the sensitive state while unparented.

feature -- Status setting

	enable_sensitive
   			-- Set current item sensitive.
		do
			is_sensitive := True
			if has_parent and then attached parent_imp as l_parent_imp then
				l_parent_imp.enable_item (id)
			end
   		end

	disable_sensitive
   			-- Set current item insensitive.
		do
			is_sensitive := False
			if has_parent and then attached parent_imp as l_parent_imp then
				l_parent_imp.disable_item (id)
			end
   		end

feature -- Element change

	set_parent_imp (a_parent_imp: like parent_imp)
			-- Make `a_parent_imp' the parent of `Current'.
		do
			parent_imp := a_parent_imp
		end

feature -- Measurement

	x_position: INTEGER
			-- Horizontal offset relative to parent `x_position' in pixels.
		do
			if attached {EV_MENU_BAR_IMP} parent_imp as l_menu_bar then
				Result := screen_x - l_menu_bar.screen_x
			elseif attached {EV_MENU_IMP} parent_imp as l_menu then
				Result := screen_x - l_menu.screen_x
			else
				check parent_either_menu_bar_or_menu: False end
			end
		end

	y_position: INTEGER
			-- Vertical offset relative to parent `y_position' in pixels.
		do
			if attached {EV_MENU_BAR_IMP} parent_imp as a_menu_bar then
				Result := screen_y - a_menu_bar.screen_y
			elseif attached {EV_MENU_IMP} parent_imp as a_menu then
				Result := screen_y - a_menu.screen_y
			else
				check either_menu_bar_or_manu: False end
			end
		end

	screen_x: INTEGER
			-- Horizontal offset relative to screen.
		do
			load_bounds_rect
			Result := bounds_rect.left
		end

	screen_y: INTEGER
			-- Vertical offset relative to screen.
		do
			load_bounds_rect
			Result := bounds_rect.top
		end

	width: INTEGER
			-- Horizontal size in pixels.
		do
			load_bounds_rect
			Result := bounds_rect.right - bounds_rect.left
		end

	height: INTEGER
			-- Vertical size in pixels.
		do
			load_bounds_rect
			Result := bounds_rect.bottom - bounds_rect.top
		end

	minimum_width: INTEGER
			-- Minimum horizontal size in pixels.
		do
				-- If this is called an invariant violation is triggered in WEL_DC
				-- It looks like the call to "load_bounds_rect" and then to "GetMenuItemRect" has some side-effects
				-- juliant, 16. Nov. 2006
			--Result := width
		end

	minimum_height: INTEGER
			-- Minimum vertical size in pixels.
		do
				-- If this is called an invariant violation is triggered in WEL_DC
				-- It looks like the call to "load_bounds_rect" and then to "GetMenuItemRect" has some side-effects
				-- juliant, 16. Nov. 2006
			--Result := height
		end

feature {NONE} -- Implementation

	wel_text: STRING_32
			-- Caption of the menu item.
			--| For the specification given in the note of EV_MENU_ITEM,
			--| we do not have to take any special action.
			--| Does not return internal toolkit string because it is possible
			--| to set the string without parent.
		do
			if attached real_text as l_real_text then
				Result := l_real_text.twin
			else
				create Result.make_empty
			end
		end

	real_text: detachable STRING_32

	wel_set_text (a_text: READABLE_STRING_GENERAL)
			-- Set `text' to `a_txt'. See `wel_text'.
		do
			if a_text /= Void then
				if a_text.is_string_32 then
					real_text := a_text.as_string_32.twin
				else
					real_text := a_text.as_string_32
				end
			end

				-- Force the menu bar to be recomputed.
			if attached parent_imp as l_parent_imp then
				l_parent_imp.rebuild_control
			end
		end

	text_length: INTEGER
			-- Length of text'.
		do
			if attached real_text as l_real_text then
				Result := l_real_text.count
			end
		end

	parent_imp: detachable EV_MENU_ITEM_LIST_IMP
			-- The menu or menu-bar this item is in.

	parent: detachable EV_MENU_ITEM_LIST
			-- Item list containing `Current'.
		do
			if
				attached parent_imp as l_parent_imp and then
				attached {EV_MENU_ITEM_LIST} l_parent_imp.interface as l_interface
			then
				Result := l_interface
			end
		end

	has_parent: BOOLEAN
			-- Is this menu item in a menu?
		do
			Result := attached parent_imp as l_parent_imp and then l_parent_imp.item_exists (id)
		end

	remove_pixmap
			-- Remove pixmap from `Current'.
		do
			if private_pixmap /= Void then
				private_pixmap := Void
				if attached parent_imp as l_parent_imp then
					l_parent_imp.internal_replace (Current, l_parent_imp.index_of (interface, 1))

						-- Force the menu bar to be recomputed.
					l_parent_imp.rebuild_control
				end
			end
		end

	set_pixmap (a_pixmap: EV_PIXMAP)
			-- Assign `a_pixmap' to `pixmap'.
		do
			Precursor (a_pixmap)
			if attached parent_imp as l_parent_imp then
				l_parent_imp.internal_replace (Current, l_parent_imp.index_of (interface, 1))

						-- Force the menu bar to be recomputed.
				l_parent_imp.rebuild_control
			end
		end

	internal_object_id: INTEGER
			-- Runtime Eiffel Object Id. Zero if no call to `eif_object_id'
			-- has been made so far.
			-- This is used for drawing owner-draw menu items

	dispose
			-- Destroy the inner structure of `Current'.
			--
			-- This function should be called by the GC when the
			-- object is collected or by the user if `Current' is
			-- no more usefull.
		do
			if internal_object_id /= 0 then
				eif_object_id_free (internal_object_id)
				internal_object_id := 0
			end
		end

feature {EV_MENU_ITEM_IMP} -- Implementation

	top_level_window_imp: detachable EV_WINDOW_IMP
			-- Window containing `Current' in parenting hierarchy.
		do
			if attached parent_imp as l_parent_imp then
				if attached {EV_MENU_IMP} l_parent_imp as l_menu then
					Result := l_menu.top_level_window_imp
				elseif attached {EV_MENU_BAR_IMP} l_parent_imp as l_menu_bar then
					Result := l_menu_bar.top_level_window_imp
				else
					check
						parent_was_menu_or_bar: False then
					end
				end
			end
		end

feature {EV_MENU_IMP} -- WEL Implementation

	plain_text: STRING_32
			-- Plain text of menu item (equal "N&ew" when full_text = "N&ew%TCtrl+B")
		do
			Result := internal_plain_text (True)
		ensure
			Result_not_void: Result /= Void
		end

	plain_text_without_ampersands: STRING_32
			-- Plain text of menu item (equal "New" when full_text = "N&ew%TCtrl+B")
			-- Ampersands are removed.
		do
			Result := internal_plain_text (False)
		ensure
			Result_not_void: Result /= Void
		end

	accelerator_text: STRING_32
			-- Accelerator text of menu item (equal "Ctrl+B" when full text = "New%TCtrl+B")
		local
			tab_index: INTEGER
		do
			if text /= Void then
				tab_index := text.index_of ('%T', 1)
				if tab_index = 0 then
						-- No accelerator
					create Result.make_empty
				else
					Result := text.substring (tab_index + 1, text.count)
				end
			else
				create Result.make_empty
			end
		ensure
			Result_not_void: Result /= Void
		end

feature {NONE} -- WEL Implementation

	internal_plain_text (keep_ampersands: BOOLEAN): STRING_32
			-- Plain text of menu item (equal "New" when full_text = "New%TCtrl+B")
			-- Set `keep_ampersands' to True to keep the ampersands.
		local
			tab_index: INTEGER
		do
			if text /= Void then
				Result := text.twin
				tab_index := Result.index_of ('%T', 1)
				if tab_index /= 0 then
					Result := Result.substring (1, tab_index - 1)
				end
				if not keep_ampersands then
					Result := remove_ampersands (Result)
				end
			else
				create Result.make_empty
			end
		ensure
			Result_not_void: Result /= Void
		end

feature {EV_MENU_CONTAINER_IMP, EV_MENU_IMP} -- WEL Implementation

	set_accelerator_text_position (a_value: INTEGER)
			-- Set the `accelerator_text_position' to `a_value'.
		require
			valid_value: a_value >= 0
		do
			accelerator_text_position := a_value
		ensure
			value_set: accelerator_text_position = a_value
		end

	set_plain_text_position (a_value: INTEGER)
			-- Set the `plain_text_position' to `a_value'.
		require
			valid_value: a_value >= 0
		do
			plain_text_position := a_value
		ensure
			value_set: plain_text_position = a_value
		end

	desired_height: INTEGER
			-- Desired height for this menu item
		local
			pixmap_height: INTEGER
			text_height: INTEGER
		do
			if attached real_text as l_real_text then
				text_height := menu_font.string_height (l_real_text) + 4
				if attached pixmap_imp as l_pixmap_imp then
					pixmap_height := l_pixmap_imp.height + 4 -- We add + 4 for drawing the edge when the item is selected
					Result := text_height.max (pixmap_height)
				else
					Result := text_height
				end
			end
		end

	on_measure_item (measure_item_struct: WEL_MEASURE_ITEM_STRUCT)
			-- Process `Wm_measureitem' message.
		do
			if attached {EV_MENU_IMP} parent_imp as par_imp then
				par_imp.on_measure_menu_item (measure_item_struct)
			else
				on_measure_menu_bar_item (measure_item_struct)
			end
		end

	on_draw_item (draw_item_struct: WEL_DRAW_ITEM_STRUCT)
			-- Process `Wm_drawitem' message.
		do
			if attached {EV_MENU_IMP} parent_imp as par_imp then
				on_draw_menu_item (draw_item_struct)
			else
				on_draw_menu_bar_item (draw_item_struct)
			end
		end

feature {NONE} -- WEL Implementation

	accelerator_text_position: INTEGER
			-- Position in pixels where the accelerator starts being written.

	plain_text_position: INTEGER
			-- Position in pixels where the plain text starts being written.

	erase_background (a_dc: WEL_DC; a_rect: WEL_RECT; a_background_color: WEL_COLOR_REF)
			-- Erase the background for the rectangle `a_rect' using the
			-- Device context `a_dc'. If `hilited_state' is set, use the
			-- background color corresponding to the hilited state.
		local
			a_background_brush: WEL_BRUSH
		do
			create a_background_brush.make_solid (a_background_color)
			a_dc.fill_rect (a_rect, a_background_brush)
			a_background_brush.delete
		end

	on_measure_menu_bar_item (measure_item_struct: WEL_MEASURE_ITEM_STRUCT)
			-- Get the measure for an item within a menu bar
		local
			accel_text: STRING_32
			plain_text_width: INTEGER
			accel_text_width: INTEGER
			pixmap_width: INTEGER
		do
			plain_text_width := menu_font.string_width (plain_text_without_ampersands)
			accel_text := accelerator_text
			if not accel_text.is_empty then
				accel_text_width := menu_font.string_width (" "+accel_text)
			end
			if attached pixmap_imp as l_pixmap_imp then
				pixmap_width := l_pixmap_imp.width + Menu_bar_item_pixmap_text_space
			end

				-- Compute the result
			measure_item_struct.set_item_width (pixmap_width + plain_text_width + accel_text_width)
			measure_item_struct.set_item_height (desired_height)

				-- Update the tabultation margins
			set_accelerator_text_position (0)
			set_plain_text_position (pixmap_width + plain_text_width + accel_text_width)
		end

	on_draw_menu_item (draw_item_struct: WEL_DRAW_ITEM_STRUCT)
			-- Process `Wm_drawitem' message for classic menu item
			-- (i.e. not menu item in the menu bar).
		local
			draw_dc: WEL_CLIENT_DC
			draw_item_struct_rect: WEL_RECT
			draw_flags: INTEGER
			foreground_color, background_color: WEL_COLOR_REF
			left_pos, top_pos, bottom_pos, right_pos: INTEGER
			text_top_pos: INTEGER
			selected_state, disabled_state: BOOLEAN
			rect: WEL_RECT
			right_plain_text_pos: INTEGER
			space_width: INTEGER
		do
			draw_dc := draw_item_struct.dc
			draw_item_struct_rect := draw_item_struct.rect_item
			left_pos := draw_item_struct_rect.left
			right_pos := draw_item_struct_rect.right
			top_pos := draw_item_struct_rect.top
			bottom_pos := draw_item_struct_rect.bottom
			selected_state := (draw_item_struct.item_state & Wel_ownerdraw_constants.Ods_selected /= 0)
			disabled_state := (draw_item_struct.item_state & Wel_ownerdraw_constants.Ods_disabled /= 0)

				-- Draw the left part (pixmap, check mark)
			on_draw_menu_item_left_part (draw_item_struct)

				-- Draw the text part
			if attached real_text as l_real_text then
					-- Select the right colors
				if selected_state then
					background_color := system_color_highlight
					if disabled_state then
						foreground_color := system_color_btnshadow
						if foreground_color.same_color (background_color) then
							foreground_color := system_color_btnhighlight
						end
					else
						foreground_color := system_color_highlighttext
					end
				else
					background_color := system_color_menu
					foreground_color := system_color_menutext
				end

					-- Erase the text area
				create rect.make (left_pos + plain_text_position, top_pos, right_pos, bottom_pos)
				erase_background (draw_dc, rect, background_color)

					-- Set the font properties
				draw_dc.select_font (menu_font)
				draw_dc.set_background_transparent
				draw_dc.set_background_color (background_color)

					-- Compute where to put texts
				text_top_pos := top_pos + ((draw_item_struct_rect.height - menu_font.string_height (l_real_text)) // 2)

					-- Compute the drawing flags
				draw_flags := Wel_drawing_constants.Dt_left
				if draw_item_struct.item_state & Wel_ownerdraw_constants.Ods_noaccel /= 0 then
					draw_flags := draw_flags | Wel_drawing_constants.Dt_hideprefix
				end

					-- Default spacing between text and accelerator, and the right border.
					-- We use the letter `o' so that the spacing is proportional to the chosen font.
					-- See `{EV_MENU_IMP}.on_measure_menu_item'.
				space_width := menu_font.string_width ("o")
					-- Compute the right offset of the end of the plain text
				if accelerator_text_position = 0 then
					right_plain_text_pos := right_pos - space_width
				else
					right_plain_text_pos := left_pos + accelerator_text_position - space_width
				end

					-- Draw the text
				if disabled_state and not selected_state then
							-- Draw highlighted text if needed
					if system_color_menu.same_color (system_color_btnface) then
						draw_dc.set_text_color (system_color_btnhighlight)

						rect.set_rect (1 + left_pos + plain_text_position, 1 + text_top_pos, right_plain_text_pos, bottom_pos)
						draw_dc.draw_text (plain_text, rect, draw_flags)

						rect.set_rect (1 + left_pos + accelerator_text_position, 1 + text_top_pos, right_pos, bottom_pos)
						draw_dc.draw_text (accelerator_text, rect, Wel_drawing_constants.Dt_left | Wel_drawing_constants.Dt_expandtabs)
					end

						-- Draw dark text
					draw_dc.set_text_color (system_color_btnshadow)
					rect.set_rect (left_pos + plain_text_position, text_top_pos, right_plain_text_pos, bottom_pos)
					draw_dc.draw_text (plain_text, rect, draw_flags)

					if not accelerator_text.is_empty then
						rect.set_rect (left_pos + accelerator_text_position, text_top_pos, right_pos, bottom_pos)
						draw_dc.draw_text (accelerator_text, rect, Wel_drawing_constants.Dt_left | Wel_drawing_constants.Dt_expandtabs)
					end
				else
					draw_dc.set_background_color (background_color)
					draw_dc.set_text_color (foreground_color)

					rect.set_rect (left_pos + plain_text_position, text_top_pos, right_plain_text_pos, bottom_pos)
					draw_dc.draw_text (plain_text, rect, draw_flags)

					if not accelerator_text.is_empty then
						rect.set_rect (left_pos + accelerator_text_position, text_top_pos, right_pos, bottom_pos)
						draw_dc.draw_text (accelerator_text, rect, Wel_drawing_constants.Dt_left | Wel_drawing_constants.Dt_expandtabs)
					end
				end
				draw_dc.unselect_font
			end
		end

	on_draw_menu_item_left_part (draw_item_struct: WEL_DRAW_ITEM_STRUCT)
			-- Process `Wm_drawitem' message, for the left part.
			-- In the left part, one draw the pixmap, check state..
			-- or nothing.
		local
			draw_dc: WEL_CLIENT_DC
			draw_item_struct_rect: WEL_RECT
			draw_item_state: INTEGER
			wel_icon: WEL_ICON
			icon_top_position: INTEGER
			left_pos, top_pos, bottom_pos: INTEGER
			background_color: WEL_COLOR_REF
			selected_state, disabled_state: BOOLEAN
			draw_flags: INTEGER
			rect: WEL_RECT
			l_bitmap: WEL_BITMAP
		do
			draw_dc := draw_item_struct.dc
			draw_item_struct_rect := draw_item_struct.rect_item
			draw_item_state := draw_item_struct.item_state
			left_pos := draw_item_struct_rect.left
			top_pos := draw_item_struct_rect.top
			bottom_pos := draw_item_struct_rect.bottom
			selected_state := (draw_item_state & Wel_ownerdraw_constants.Ods_selected /= 0)
			disabled_state := (draw_item_state & Wel_ownerdraw_constants.Ods_disabled /= 0)

					-- First erase the background
			create rect.make (0, 0, 0, 0)
			if disabled_state and pixmap_imp /= Void and not selected_state then
				background_color := system_color_menu
			else
				background_color := system_color_highlight
			end
			if selected_state then

				rect.set_rect (left_pos, top_pos, left_pos + plain_text_position - 2, bottom_pos)
				erase_background (draw_dc, rect, background_color)
				rect.set_rect (left_pos + plain_text_position - 2, top_pos, left_pos + plain_text_position, bottom_pos)
				erase_background (draw_dc, rect, system_color_highlight)
			else
				rect.set_rect (left_pos, top_pos, left_pos + plain_text_position, bottom_pos)
				erase_background (draw_dc, rect, system_color_menu)
			end

					-- Draw the pixmap if needed
			if attached pixmap_imp as l_pixmap_imp then
				if disabled_state then
					draw_flags := Wel_drawing_constants.Dss_disabled
				else
					draw_flags := Wel_drawing_constants.Dss_normal
				end
				icon_top_position := top_pos + (draw_item_struct_rect.height - l_pixmap_imp.height - 2) // 2
				left_pos := left_pos + 1

				wel_icon := extract_icon (l_pixmap_imp)
				if disabled_state and then attached disabled_image as l_disabled_image then
					l_bitmap := l_pixmap_imp.get_bitmap
					l_disabled_image.draw_grayscale_bitmap_or_icon_with_memory_buffer (l_bitmap, wel_icon, draw_dc, left_pos, icon_top_position, background_color, l_pixmap_imp.has_mask)
					l_bitmap.decrement_reference
				else
					draw_dc.draw_state_icon (Void, wel_icon, left_pos, icon_top_position, draw_flags)
				end
				wel_icon.decrement_reference

			end
		end

	on_draw_menu_bar_item (draw_item_struct: WEL_DRAW_ITEM_STRUCT)
			-- Process `Wm_drawitem' message.
		local
			draw_dc: WEL_CLIENT_DC
			draw_item_struct_rect: WEL_RECT
			draw_flags: INTEGER
			draw_item_state: INTEGER
			rect: WEL_RECT
			left_pos, top_pos, bottom_pos, right_pos: INTEGER
			text_top_pos: INTEGER
			selected_state, disabled_state: BOOLEAN
			wel_icon: WEL_ICON
			icon_top_position: INTEGER
			text_color, background_color: WEL_COLOR_REF
			desired_width: INTEGER
			left_pos_start: INTEGER
			drawn_text: STRING_32
			flat_menu_enabled: BOOLEAN
			l_bitmap: WEL_BITMAP
		do
			draw_dc := draw_item_struct.dc
			draw_item_struct_rect := draw_item_struct.rect_item
			draw_item_state := draw_item_struct.item_state
			left_pos := draw_item_struct_rect.left
			right_pos := draw_item_struct_rect.right
			top_pos := draw_item_struct_rect.top
			bottom_pos := draw_item_struct_rect.bottom
			selected_state := (draw_item_state & Wel_ownerdraw_constants.Ods_selected /= 0)
			disabled_state := (draw_item_state & Wel_ownerdraw_constants.Ods_disabled /= 0)
			desired_width := plain_text_position -- We have used this variable to store the desired width in `on_measure_menu_bar_item'.
			left_pos_start := (right_pos - left_pos - desired_width) // 2
			flat_menu_enabled := has_flat_menu

				-- First erase the background
			if flat_menu_enabled then
				if selected_state then
					background_color := system_color_menuhilight
					text_color := system_color_highlighttext
				else
					background_color := system_color_menubar
					text_color := system_color_menutext
				end
			else
				background_color := system_color_menu
				text_color := system_color_menutext
			end
			erase_background (draw_dc, draw_item_struct_rect, background_color)

					-- Draw a border around the item for top menu when menus are not flat.
			if not (flat_menu_enabled) then
				if selected_state then
					draw_dc.draw_edge (draw_item_struct_rect, Wel_drawing_constants.Bdr_sunkenouter, Wel_drawing_constants.Bf_rect)
				elseif draw_item_state & Wel_ownerdraw_constants.Ods_hotlight /= 0 then
					draw_dc.draw_edge (draw_item_struct_rect, Wel_drawing_constants.Bdr_raisedinner, Wel_drawing_constants.Bf_rect)
				end
			end

					-- Draw the pixmap if needed
			if attached pixmap_imp as l_pixmap_imp then
				if disabled_state then
					draw_flags := Wel_drawing_constants.Dss_disabled
				else
					draw_flags := Wel_drawing_constants.Dss_normal
				end
				icon_top_position := top_pos + (draw_item_struct_rect.height - l_pixmap_imp.height) // 2

				wel_icon := extract_icon (l_pixmap_imp)
				if disabled_state and then attached disabled_image as l_disabled_image then
					l_bitmap := l_pixmap_imp.get_bitmap
					l_disabled_image.draw_grayscale_bitmap_or_icon_with_memory_buffer (l_bitmap, wel_icon, draw_dc, left_pos, icon_top_position, background_color, l_pixmap_imp.has_mask)
					l_bitmap.decrement_reference
				else
					draw_dc.draw_state_icon (Void, wel_icon, left_pos + left_pos_start, icon_top_position, draw_flags)
				end
				wel_icon.decrement_reference
				left_pos_start := left_pos_start + l_pixmap_imp.width + Menu_bar_item_pixmap_text_space
			end

				-- Draw the text part
			if attached real_text as l_real_text then
					-- Set the font properties
				draw_dc.select_font (menu_font)
				draw_dc.set_background_color (background_color)
				draw_dc.set_text_color (text_color)

					-- Compute where to put texts
				text_top_pos := top_pos + ((draw_item_struct_rect.height - menu_font.string_height (l_real_text)) // 2)
				create rect.make (left_pos + left_pos_start, text_top_pos, right_pos, bottom_pos)

					-- Compute the drawing flags
				draw_flags := Wel_drawing_constants.Dt_expandtabs | Wel_drawing_constants.Dt_left
				if draw_item_state & Wel_ownerdraw_constants.Ods_noaccel /= 0 then
					draw_flags := draw_flags | Wel_drawing_constants.Dt_hideprefix
				end

					-- Draw the text
				drawn_text := plain_text.twin
				drawn_text.append_character (' ')
				drawn_text.append (accelerator_text)
				if disabled_state then
					draw_dc.draw_disabled_text (drawn_text, rect, draw_flags)
				else
					draw_dc.draw_text (drawn_text, rect, draw_flags)
				end
				draw_dc.unselect_font
			end
		end

	disabled_image: detachable WEL_GDIP_GRAYSCALE_IMAGE_DRAWER
			-- Grayscale image drawer.
			-- Void if Gdi+ not installed.
		local
			l_gdip_starter: WEL_GDIP_STARTER
		once
			create l_gdip_starter
			if l_gdip_starter.is_gdi_plus_installed then
				create Result
			end
		end

feature {EV_ANY_I} -- Pick and Drop

	set_capture
			-- Grab user input.
			-- Works only on current windows thread.
		do
			--| To be implemented.
			--| This may work without redefinition.
			--| These have been left as re-defined to make sure it is not
			--| overlooked in the future.
			check
				To_be_implemented: False
			end
		end

	release_capture
			-- Release user input.
			-- Works only on current windows thread.
		do
			--| To be implemented.
			--| This may work without redefinition.
			--| These have been left as re-defined to make sure it is not
			--| overlooked in the future.
			check
				To_be_implemented: False
			end
		end

	set_heavy_capture
			-- Grab user input.
			-- Works on all windows threads.
		do
			--| To be implemented.
			--| This may work without redefinition.
			--| These have been left as re-defined to make sure it is not
			--| overlooked in the future.
			check
				To_be_implemented: False
			end
		end

	release_heavy_capture
			-- Release user input
			-- Works on all windows threads.
		do
			--| To be implemented.
			--| This may work without redefinition.
			--| These have been left as re-defined to make sure it is not
			--| overlooked in the future.
			check
				To_be_implemented: False
			end
		end

feature {NONE} -- Contract Support

	parent_is_sensitive: BOOLEAN
			-- is parent of `Current' sensitive?
		do
			if attached parent_imp as l_parent_imp then
				Result := l_parent_imp.is_sensitive
			end
		end

feature {EV_ANY_I} -- Implementation

	on_activate
			-- `Current' has been clicked on.
		do
			if select_actions_internal /= Void then
				select_actions_internal.call (Void)
			end
		end

feature {EV_ANY, EV_ANY_I} -- Implementation

	interface: detachable EV_MENU_ITEM note option: stable attribute end

feature {NONE} -- Implementation

	remove_ampersands (a_string: STRING_32): STRING_32
			-- Remove all single ampersands in `a_string'.
			-- Double ampersands are replaced by a single ampersand.
		local
			prv_index: INTEGER
			amp_index: INTEGER
		do
			create Result.make (a_string.count)
			from
				prv_index := 1
				amp_index := a_string.index_of ('&', prv_index)
			until
				amp_index = 0
			loop
				Result.append (a_string.substring (prv_index, amp_index - 1))
				prv_index := amp_index + 1
					-- We search at `prv_index + 1' so that double ampersands are indeed
					-- replaced by a single ampersand.
				amp_index := a_string.index_of ('&', prv_index + 1)
			end
			Result.append (a_string.substring (prv_index, a_string.count))
		end

	extract_icon (a_pixmap_imp_state: EV_PIXMAP_IMP_STATE): WEL_ICON
			-- Extract the icon from `pixmap_imp'.
		local
			l_result: detachable WEL_ICON
		do
			if attached {EV_PIXMAP_IMP} a_pixmap_imp_state as pix_imp then
				l_result := pix_imp.icon
			end
			if l_result /= Void then
				l_result.increment_reference
			else
				l_result := a_pixmap_imp_state.build_icon
				l_result.enable_reference_tracking
			end
			Result := l_result
		end

	bounds_rect: WEL_RECT
			-- Rect struct which holds boundary information
			-- This struct is shared.
		once
			create Result.make (0, 0, 0, 0)
		ensure
			result_not_void: Result /= Void
		end

	load_bounds_rect
			-- Load bounds rect.
		do
			if attached parent_imp as l_parent_imp then
				if {WEL_API}.get_menu_item_rect (Default_pointer, l_parent_imp.wel_item, l_parent_imp.index_of (interface, 1)-1, bounds_rect.item) = 0 then
					bounds_rect.set_rect (0, 0, 0, 0)
				end
			else
				bounds_rect.set_rect (0, 0, 0, 0)
			end
		end

feature {NONE} -- Constants

	Menu_bar_item_pixmap_text_space: INTEGER = 4;
			-- Space between the text and the pixmap in a menu bar item

note
	copyright:	"Copyright (c) 1984-2018, 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