note
	description: "Summary description for {CTR_LOGS_TOOL}."
	author: ""
	date: "$Date$"
	revision: "$Revision$"

class
	CTR_INFO_TOOL

inherit
	CTR_TOOL
		redefine
			focus_widget
		end

	EV_SHARED_APPLICATION

	CTR_SHARED_GUI_PREFERENCES

create
	make

feature {NONE} -- Initialization

	build_interface (a_container: EV_CONTAINER)
		local
			g: like grid
			c: like sd_content
			mtb: SD_TOOL_BAR
			tbbut: SD_TOOL_BAR_BUTTON
		do
			create g
			grid := g
			a_container.extend (g)
			c := sd_content

			g.enable_multiple_row_selection
			g.set_column_count_to (2)
			g.disable_row_height_fixed
			g.enable_tree
			g.hide_tree_node_connectors
			g.hide_header
			g.key_release_actions.extend (agent on_key_released)

			c.set_short_title ("Info ...")
			c.set_long_title ("Info")
			create mtb.make
			create tbbut.make
			tbbut.set_pixmap (icons.new_diff_small_toolbar_button_icon)
			tbbut.select_actions.extend (agent show_info_diff)
			mtb.extend (tbbut)

			create tbbut.make
			tbbut.set_pixmap (icons.new_text_small_toolbar_button_standard_icon ("Open Data Folder"))
			tbbut.select_actions.extend (agent open_data_folder)
			mtb.extend (tbbut)

			mtb.compute_minimum_size
			c.set_mini_toolbar (mtb)

			if attached preferences as prefs then
				changes_expanded := prefs.info_tool_changes_expanded_pref.value
			end
		end

feature -- Access

	current_log: detachable REPOSITORY_LOG

	current_repository: detachable REPOSITORY_DATA

	grid: ES_GRID

	focus_widget: detachable EV_WIDGET
			-- Real widget to focus, when `set_focus' is called
		do
			Result := grid
		end


feature -- Actions

	on_key_released	(k: EV_KEY)
		local
			s: detachable STRING_32
		do
			inspect k.code
			when {EV_KEY_CONSTANTS}.key_C, {EV_KEY_CONSTANTS}.key_INSERT then
				if
					ev_application.ctrl_pressed and
					not ev_application.alt_pressed and
					not ev_application.shift_pressed
				then
					create s.make_empty
					if
						attached grid.selected_rows as l_rows and then
						not l_rows.is_empty
					then
						create s.make_empty
						from
							l_rows.start
						until
							l_rows.after
						loop
							s.append_string (grid_row_to_string (l_rows.item))
							l_rows.forth
							if not l_rows.off then
								s.append_character ('%N')
							end
						end
					end
					ev_application.clipboard.set_text (s)
				end
			else
				-- default
			end
		end

	grid_row_to_string (a_row: EV_GRID_ROW): STRING_32
			-- Row's text to string
		local
			i,n: INTEGER
		do
			create Result.make_empty
			n := a_row.count
			if n > 0 then
				from
					i := 1
				until
					i > n
				loop
					if attached a_row.item (i) as l_item then
						if attached {EV_GRID_LABEL_ITEM} l_item as l_lab then
							Result.append_string (l_lab.text)
						else
						end
					end
					i := i + 1
					if i <= n then
						Result.append_character ('%T')
					end

				end
			end
		end

feature -- Element change

	update
		local
			g: like grid
			l_row, l_subrow: detachable EV_GRID_ROW
			glab: EV_GRID_LABEL_ITEM
			mlab: CTR_INFO_MESSAGE_GRID_ITEM
			grtxt: EV_GRID_RICH_LABEL_ITEM
--			gcb: EV_GRID_CHECKABLE_LABEL_ITEM
--			gtxt: EV_GRID_TEXT_ITEM
			md: like smart_log_message
			repo: REPOSITORY_DATA
			cst_info_title_col: INTEGER
			cst_info_value_col: INTEGER
			n: INTEGER
		do
			g := grid
			g.wipe_out
			g.row_expand_actions.wipe_out
			g.resize_actions.wipe_out
			cst_info_title_col := 2
			cst_info_value_col := 1

			if attached {REPOSITORY_SVN_LOG} current_log as rsvnlog then
				cst_info_title_col := 2
				cst_info_value_col := 1 -- 2

				g.insert_new_row (g.row_count + 1)
				l_row := g.row (g.row_count)
--				l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Info"))
				create grtxt--.make_with_text ("revision " + rsvnlog.id + " by " + rsvnlog.author + " (" + rsvnlog.date + ")")
				grtxt.add_formatted_text ("revision ", Void, Void)
				grtxt.add_formatted_text (rsvnlog.id, info_highlight_fgcolor, font_bold)
				grtxt.add_formatted_text (" by ", Void, Void)
				grtxt.add_formatted_text (rsvnlog.author, info_highlight_fgcolor, font_bold)
				grtxt.add_formatted_text (" (" + rsvnlog.date + ")", Void, font_comment)
				l_row.set_item (cst_info_value_col, grtxt)

				g.insert_new_row (g.row_count + 1)
				l_row := g.row (g.row_count)
--				create glab.make_with_text ("Message")
--				glab.align_text_top
--				l_row.set_item (cst_info_title_col, glab)
				repo := rsvnlog.parent
				md  := smart_log_message (rsvnlog, repo.tokens_keys)
				create mlab.make_with_text (md.message)
				mlab.set_foreground_color (info_highlight_fgcolor)
				mlab.set_font (message_font)
				mlab.align_text_top
				mlab.set_top_border (3)
				mlab.set_bottom_border (5)
				l_row.set_item (cst_info_value_col, mlab)

				if attached mlab.font as ft then
					l_row.set_height (ft.string_size (mlab.text).height + mlab.bottom_border + mlab.top_border)
				end

				if attached repo.tokens as l_tokens and then l_tokens.count > 0 then
					across l_tokens as tok loop
						if attached md.matches.item (tok.item.key) as lst then
							n := n + lst.count
						end
					end
					if n > 0 then
						if n > 1 then
							g.insert_new_row (g.row_count + 1)
							l_row := g.row (g.row_count)
							l_row.set_item (1, create {EV_GRID_LABEL_ITEM}.make_with_text (n.out + " references"))
						else
							l_row := Void
						end

						across
							l_tokens as tok
						loop
							if attached md.matches.item (tok.item.key) as lst then
								from
									lst.start
								until
									lst.after
								loop
									if attached repo.token_url (tok.key, lst.item) as l_url then
										if l_row /= Void then
											g.insert_new_row_parented (g.row_count + 1, l_row)
										else
											g.insert_new_row (g.row_count + 1)
										end
										l_subrow := g.row (g.row_count)
--										l_subrow.set_item (cst_info_title_col, create {EV_GRID_ITEM})
										create glab.make_with_text (tok.item.key + " #" + lst.item + ": " + l_url)
										glab.set_data (l_url)
										glab.pointer_double_press_actions.force_extend (agent open_url (l_url))
										l_subrow.set_item (cst_info_value_col, glab)
									end
									lst.forth
								end
								if l_row /= Void and then l_row.is_expandable then
									l_row.expand
								end
							end
						end
					end
				end

				if attached rsvnlog.svn_revision.paths as l_changes and then l_changes.count > 0 then
--					g.insert_new_row (g.row_count + 1)
					l_row := Void
					if l_changes.count > 1 then
						g.insert_new_row (g.row_count + 1)
						l_row := g.row (g.row_count)

						l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_changes.count.out + " nodes changed"))
						l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (rsvnlog.svn_revision.common_parent_path + " (..)"))
						l_row.expand_actions.extend (agent set_changes_expanded (True))
						l_row.collapse_actions.extend (agent set_changes_expanded (False))
					end

					across
						l_changes as l_paths
					loop
						if l_row /= Void then
							g.insert_new_row_parented (g.row_count + 1, l_row)
						else
							g.insert_new_row (g.row_count + 1)
						end

						l_subrow := g.row (g.row_count)
						l_subrow.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_paths.item.action))
						create glab.make_with_text (l_paths.item.path)
						l_subrow.set_item (cst_info_value_col, glab)
						glab.pointer_double_press_actions.force_extend (agent show_info ("service.diff.text", l_paths.item.path))
					end
					if l_row /= Void and then l_row.is_expandable and changes_expanded then
						l_row.expand
					end
				end


--				g.insert_new_row (g.row_count + 1)
				g.insert_new_row (g.row_count + 1)
				l_row := g.row (g.row_count)
--				l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Diff"))

				if rsvnlog.has_diff then
					create glab.make_with_text ("Double click to SHOW diff")
					glab.pointer_double_press_actions.force_extend (agent show_info_diff) --popup_diff (rsvnlog))
					l_row.set_item (cst_info_value_col, glab)
				else
					create glab.make_with_text ("Double click to GET diff")
					glab.pointer_double_press_actions.force_extend (agent show_info_diff)
					l_row.set_item (cst_info_value_col, glab)
				end

				if attached rsvnlog.parent.repository_option ("service.diff.web") then
					g.insert_new_row (g.row_count + 1)
					l_row := g.row (g.row_count)
					create glab.make_with_text ("Double click to view changes online")
					glab.pointer_double_press_actions.force_extend (agent show_info ("service.diff.web", Void))
					l_row.set_item (cst_info_value_col, glab)
				end

				request_update_grid_layout (cst_info_title_col, cst_info_value_col)
			elseif attached {REPOSITORY_SVN_DATA} current_repository as rsvnrepo then
				cst_info_title_col := 1
				cst_info_value_col := 2

				if attached rsvnrepo.info as rinfo then
					g.insert_new_row (g.row_count + 1)
					l_row := g.row (g.row_count)
					l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Revision"))
					l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (rinfo.revision.out))

					g.insert_new_row (g.row_count + 1)
					l_row := g.row (g.row_count)
					l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Localisation"))
					l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (rinfo.localisation))

					if attached rinfo.last_changed_rev as l_rev then
						g.insert_new_row (g.row_count + 1)
						l_row := g.row (g.row_count)
						l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Last rev"))
						l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_rev.out))
					end
					if attached rinfo.last_changed_author as l_author then
						g.insert_new_row (g.row_count + 1)
						l_row := g.row (g.row_count)
						l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Last author"))
						l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_author))
					end
					if attached rinfo.last_changed_date as l_date then
						g.insert_new_row (g.row_count + 1)
						l_row := g.row (g.row_count)
						l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Last Date"))
						l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_date))
					end

					if attached rinfo.repository_root as l_root then
						g.insert_new_row (g.row_count + 1)
						l_row := g.row (g.row_count)
						l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Repo Root"))
						l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_root))
					end

					if attached rinfo.repository_uuid as l_uuid then
						g.insert_new_row (g.row_count + 1)
						l_row := g.row (g.row_count)
						l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Repo UUID"))
						l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_uuid))
					end

					if attached rinfo.url as l_url then
						g.insert_new_row (g.row_count + 1)
						l_row := g.row (g.row_count)
						l_row.set_item (cst_info_title_col, create {EV_GRID_LABEL_ITEM}.make_with_text ("Url"))
						l_row.set_item (cst_info_value_col, create {EV_GRID_LABEL_ITEM}.make_with_text (l_url))
					end

					request_update_grid_layout (cst_info_title_col, cst_info_value_col)
				end
			end
			g.row_expand_actions.force_extend (agent request_update_grid_layout (cst_info_title_col,cst_info_value_col))
			g.resize_actions.force_extend (agent request_update_grid_layout (cst_info_title_col,cst_info_value_col))
		end

	request_update_grid_layout (cst_info_title_col, cst_info_value_col: INTEGER)
		do
			ev_application.add_idle_action_kamikaze (agent update_grid_layout (cst_info_title_col, cst_info_value_col))
		end

	update_grid_layout (cst_info_title_col, cst_info_value_col: INTEGER)
		local
			g: like grid
			ww, w1, w2: INTEGER
			col: EV_GRID_COLUMN
			r,c,n: INTEGER
		do
			g := grid
				-- Update layout columns
			ww := g.viewable_width
			if g.column_count >= cst_info_title_col then
				col := g.column (cst_info_title_col)
				w1 := col.required_width_of_item_span (1, g.row_count) + 5
			end
			if g.column_count >= cst_info_value_col then
				col := g.column (cst_info_value_col)
				w2 := col.required_width_of_item_span (1, g.row_count) + 5
			end
			w2 := w2.max (ww - w1)
			if g.column_count >= cst_info_title_col then
				g.column (cst_info_title_col).set_width (w1)
			end
			if g.column_count >= cst_info_value_col then
				g.column (cst_info_value_col).set_width (w2)
			end
			from
				r := 1
			until
				r > g.row_count
			loop
				from
					c := 1
					n := g.row (r).count
				until
					c > n
				loop
					if attached {CTR_INFO_MESSAGE_GRID_ITEM} g.item (c, r) as m then
						m.update
						g.row (r).set_height (m.required_height_after_update)
					end
					c := c + 1
				end
				r := r + 1
			end
		end

	update_current_log (v: like current_log)
		do
			current_repository := Void
			current_log := v
			update
		end

	update_current_repository (v: like current_repository)
		do
			current_log := Void
			current_repository := v
			update
		end

feature {NONE} -- Smart log message

	smart_token_handler: detachable CTR_SMART_TOKEN_HANDLER
			-- Smart token handler

	smart_log_message (a_log: REPOSITORY_LOG; a_patterns: detachable ARRAY [detachable STRING]): like {CTR_SMART_TOKEN_HANDLER}.smart_log_message
		local
			h: like smart_token_handler
		do
			h := smart_token_handler
			if h = Void then
				create h
				smart_token_handler := h
			end
			Result := h.smart_log_message (a_log, a_patterns)
		end

feature {NONE} -- Implementation

	open_url (a_url: STRING)
		local
			e: CTR_EXTERNAL_TOOLS
		do
			create e
			e.open_url (a_url)
		end

	open_data_folder
		local
			exec: EXECUTION_ENVIRONMENT
			s: detachable STRING
			rep: like current_repository
		do
			if attached current_repository as r then
				rep := r
			elseif attached current_log as l_log then
				rep := l_log.parent
			end
			if
				rep /= Void and then
				attached {REPOSITORY_FILE_STORAGE} rep.storage as fs
			then
				s := fs.data_folder_name
			end
			if s /= Void then
				create exec
				if attached exec.get ("COMSPEC") as l_comspec then
					s := l_comspec + " /C start " + s
				else
					s := "explorer " + s
				end
				exec.launch (s)
			end
		end

--	popup_diff (a_log: REPOSITORY_LOG)
--		do
--			if attached ctr_window as w then
--				w.popup_diff (a_log)
--			end
--		end

	show_info_diff
		do
			show_info ("service.diff.file", Void)
			if attached ctr_window as w then
				if attached current_log as l_log then
					w.show_log_diff (l_log)
				end
			end
		end

	show_info (a_service: STRING; a_path: detachable STRING)
		do
			if attached ctr_window as w then
				if attached current_log as l_log then
					w.show_log (a_service, l_log, a_path)
				end
			end
		end

	changes_expanded: BOOLEAN

	set_changes_expanded (b: BOOLEAN)
		do
			changes_expanded := b
			if attached preferences as prefs then
				prefs.info_tool_changes_expanded_pref.set_value (b)
			end
		end

end