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

class
	EV_TITLED_WINDOW_IMP

inherit
	EV_TITLED_WINDOW_I
		undefine
			propagate_foreground_color,
			propagate_background_color,
			lock_update,
			unlock_update
		redefine
			interface
		end

	EV_WINDOW_IMP
		rename
			maximize as wel_maximize,
			minimize as wel_minimize
		redefine
			destroy,
			old_make,
			default_style,
			on_show,
			on_size,
			title,
			set_title,
			interface,
			class_name,
			is_displayed,
			execute_resize_actions,
			has_title_bar,
			make,
			title_name
		end

	EV_ID_IMP

create
	make

feature -- Initialization

	old_make (an_interface: attached like interface)
			-- Create `Current' with interface `an_interface'.
		do
			assign_interface (an_interface)
		end

	make
			-- Create and initialize `Current'
		do
			internal_class_name := new_class_name
			create internal_icon_name.make_empty
			Precursor
		end

	title_name: STRING
			-- Title name used for registration.
		do
			Result := "EV_TITLED_WINDOW"
		end

feature -- Access

	title: STRING_32
			-- Application name to be displayed by
			-- the window manager.
		do
			if attached internal_title as l_internal_title then
				Result := l_internal_title.twin
			else
				create Result.make_empty
			end
		end

	internal_title: detachable STRING_32
			-- Our internal represention of the application
			-- name to be displayed by the window manager.

	icon_name: STRING_32
			-- Short form of application name to be
			-- displayed by the window manager when
			-- application is iconified.
		do
			if internal_icon_name /= Void then
				Result := internal_icon_name.twin
			else
				create Result.make_empty
			end
		end

	icon_pixmap: EV_PIXMAP
			-- Bitmap that could be used by the window manager
			-- as the application's icon.
		local
			ev_pixmap_imp: detachable EV_PIXMAP_IMP
		do
			if attached current_icon_pixmap as l_current_icon_pixmap then
				create Result
				ev_pixmap_imp ?= Result.implementation
				check ev_pixmap_imp /= Void then end
				ev_pixmap_imp.set_with_resource (l_current_icon_pixmap)
			else
					-- Icon is not valid, return the default icon.
				Result := default_pixmaps.Default_window_icon
			end
		end

feature -- Status report

	is_minimized: BOOLEAN
			-- Is `Current' minimized (iconic state)?
		do
			Result := flag_set (style, Ws_minimize)
		end

	is_maximized: BOOLEAN
			-- Is `Current' maximized (take the all screen).
		do
			Result := flag_set (style, Ws_maximize)
		end

	is_displayed: BOOLEAN
			-- Is `Current' visible on screen?
			-- `Result' is False if `is_minimized'.
		do
			Result := Precursor {EV_WINDOW_IMP} and not is_minimized
		end

	has_title_bar: BOOLEAN
			-- Does current have a title bar?
		do
				-- Not a constant because some descendants do not have a title bar.
			Result := True
		end

feature -- Status setting

	raise
			-- Raise `Current'. ie: put the window on the front
			-- of the screen.
		local
			l_bool: BOOLEAN
		do
			if not is_show_requested then
				show
			end
			if is_minimized then
				restore
			end
			l_bool := {WEL_API}.set_foreground_window (wel_item)
		end

	lower
			-- Lower `Current'. ie: put the window on the back
			-- of the screen.
		do
			set_z_order (hwnd_bottom)
		end

	destroy
			-- Destroy `Current', but set the parent sensitive
			-- in case it was set insensitive by the child.
		do
			Precursor {EV_WINDOW_IMP}

				-- Destroy the icon
			if attached current_icon_pixmap as l_current_icon_pixmap then
				l_current_icon_pixmap.decrement_reference
				current_icon_pixmap := Void
			end
		end

	minimize
			-- Minimize `Current'
		do
			wel_minimize
		end

	maximize
			-- Maximize `Current'.
			-- If the window is not shown, it gives it the screen
			-- size, but do not call the precursor otherwise, it
			-- shows the window.
		do
			wel_maximize
		end

feature -- Element change

	set_title (txt: READABLE_STRING_GENERAL)
			-- Make `txt' the title of `Current'.
		do
			internal_title := txt.as_string_32.twin
			if not is_minimized then
				set_text (txt)
			end
		end

	set_icon_name (txt: READABLE_STRING_GENERAL)
			-- Make `txt' the new icon name.
		do
			internal_icon_name := txt.as_string_32.twin
			if is_minimized then
				set_text (txt)
			end
		end

	set_icon_pixmap (a_pixmap: EV_PIXMAP)
			-- Make `pixmap' the new icon pixmap.
		local
			icon: detachable WEL_ICON
			built_icon: detachable WEL_ICON
			pixmap_imp: detachable EV_PIXMAP_IMP_STATE
			previous_icon_pixmap: detachable WEL_ICON
		do
			pixmap_imp ?= a_pixmap.implementation
			check pixmap_imp /= Void then end
			icon := pixmap_imp.icon
			if icon = Void then
				pixmap_imp ?= a_pixmap.implementation
				check pixmap_imp /= Void then end
				built_icon := pixmap_imp.build_icon
				built_icon.enable_reference_tracking
				icon := built_icon
			end
			check icon /= Void then end

				-- Remember the icon

			previous_icon_pixmap := current_icon_pixmap
			current_icon_pixmap := icon
			icon.increment_reference

			set_icon (icon, icon)

				-- Destroy the old icon
			if previous_icon_pixmap /= Void then
				previous_icon_pixmap.decrement_reference
				previous_icon_pixmap := Void
			end

				-- Forget the icon we have just built.
			if built_icon /= Void then
				built_icon.decrement_reference
				built_icon := Void
			end
			pixmap_imp.gdi_compact
		end

feature -- Standard window class values

	class_name: STRING_32
			-- Window class name to create.
		do
			Result := internal_class_name
		end

feature {EV_ANY_I} -- Implementation

	current_icon_pixmap: detachable WEL_ICON
			-- Current icon set. Void if none
			-- Should not be destroyed until the window is destroyed

	internal_class_name: STRING_32
			-- Window class name.

	new_class_name: STRING_32
			-- Standard application icon used to create the
			-- window class.
			-- Can be redefined to return a user-defined icon.
		do
			make_id
			Result := {STRING_32} "EV_TITLED_WINDOW_IMP"
		end

	internal_icon_name: STRING_32
			-- Name given by the user. internal representation.

feature {NONE} -- WEL Implementation

	default_style: INTEGER
			-- default style of `Current'.
			-- Set with the option `Ws_clipchildren' to avoid flashing.
		do
			Result := Ws_overlapped + Ws_dlgframe + Ws_thickframe
					+ Ws_clipchildren + Ws_clipsiblings
					+ Ws_minimizebox + Ws_maximizebox
					+ Ws_border + Ws_sysmenu
		end

	on_show
			-- When `Current' receives the on_show message,
			-- it resizes to the size of the child and sends
			-- a message to the child.
		local
			l_rect: WEL_RECT
		do
				-- We check if there is a menu
			if has_menu then
				draw_menu
			end

				-- Different behaviors if the window was maximized or not.
			if is_maximized then
				wel_maximize
			elseif is_minimized then
				wel_minimize
			else
					-- Position window if needed.
				if child_cell.is_positioned then
					wel_move (child_cell.x, child_cell.y)
				end
				if item_imp = Void or else child_cell.is_size_specified then
					wel_resize (
						width.min (maximum_width),
						height.min (maximum_height))
				elseif attached item_imp as l_item_imp then

						-- When there is an item that is bigger than minimum_size
						-- we try to stretch window as much as we can (ie not bigger
						-- than the maximum size).
					l_rect := extra_minimum_rect
					wel_resize (
						(l_item_imp.width + l_rect.width).min (maximum_width),
						(l_item_imp.height + l_rect.height).min (maximum_height))
				end
			end
		end

	on_size (size_type, a_width, a_height: INTEGER)
			-- Called when `Current' is resized.
			-- Resize the child if it exists.
		do
			if size_type = Wel_window_constants.Size_minimized then
				if icon_name.is_empty then
					set_text (internal_title)
				else
					set_text (icon_name)
				end
				if minimize_actions_internal /= Void then
					minimize_actions_internal.call (Void)
				end
			elseif size_type = Wel_window_constants.Size_maximized then
				if maximize_actions_internal /= Void then
					maximize_actions_internal.call (Void)
				end
					-- We must now override restore_actions if we are changing state
					-- from minimimzed to maximized. This is not considered a restore.
				if fire_restore_actions = True then
					fire_restore_actions := False
				end
			elseif size_type = Wel_window_constants.Size_restored then
				set_text (internal_title)
			end
			Precursor {EV_WINDOW_IMP} (size_type, a_width, a_height)

				 -- We now set our internal flag, as it must be set after we
				 -- call `execute_resize_actions'.

			if size_type = Wel_window_constants.Size_minimized or
			size_type = Wel_window_constants.Size_maximized then
					-- If we are now maximized or minimized then we
					-- must assign True to `fire_restore_actions', so that
					-- the next time we resize, we know to fire them.
				fire_restore_actions := True
			end
		end

	execute_resize_actions (a_width, a_height: INTEGER)
			-- execute `resize_actions_internal' if not Void.
		do
			trigger_resize_actions (a_width, a_height)
				-- We must only fire restore actions if
				-- `fire_restore_actions'.
			if fire_restore_actions then
				if restore_actions_internal /= Void then
					restore_actions.call (Void)
				end
				fire_restore_actions := False
			end
		end

	fire_restore_actions: BOOLEAN
		-- If `True' then restore_actions must be fired.
		-- We have to have this flag, as Windows does not provide a message
		-- which distinguishes between a normal resize or a restore.

	copy_box_attributes (original_box, new_box: EV_VERTICAL_BOX)
			-- Copy all widgets from `original_box' to `new_box'
			-- and set attributes.
		require
			original_box_not_void: original_box /= Void
			new_box_not_void: new_box /= Void
			new_box_empty: new_box.is_empty
		local
			current_widget: EV_WIDGET
			l_or_imp, l_ub_imp: detachable EV_VERTICAL_BOX_IMP
		do
			fixme (once "[We should copy all attributes and action sequences.]")
			l_ub_imp ?= new_box.implementation
			check l_ub_imp /= Void then end
			if l_ub_imp.wel_item /= default_pointer then
				from
					l_or_imp ?= original_box.implementation
					check l_or_imp /= Void then end
						-- We remove `original_box' from Current as otherwise we would
						-- be violating the `parent_contains_current' invariant.
					l_or_imp.set_parent_imp (Void)
					original_box.start
				until
					original_box.is_empty
				loop
					current_widget := original_box.item
					original_box.remove
					new_box.extend (current_widget)
				end
				new_box.set_padding (original_box.padding)
				new_box.set_border_width (original_box.border_width)
				check
					ub_imp_not_void: l_ub_imp /= Void then
				end
				l_ub_imp.on_parented
				l_ub_imp.wel_set_parent (Current)
				l_ub_imp.set_top_level_window_imp (Current)
			end
		ensure
			old_and_new_counts_consistent: old original_box.count = new_box.count
			original_box_empty: original_box.is_empty
		end

feature {EV_ANY, EV_ANY_I} -- Implementation

	interface: detachable EV_TITLED_WINDOW note option: stable attribute end

feature {NONE} -- Constants

	Wel_icon_constants: WEL_ICON_CONSTANTS
			-- Icon constants (Icon_Big & Icon_small)
		once
			create Result
		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_TITLED_WINDOW_IMP