note description: "[ Box containing the list of available iron package, with name, location, repository and available extra informations. It also provides control on iron package such as - install - remove - update It indicates if there are any name conflicts, remember that order of repositories matters. ]" date: "$Date$" revision: "$Revision$" class IRON_PACKAGE_COLLECTION_BOX inherit CONF_GUI_INTERFACE_CONSTANTS SHARED_BENCH_NAMES create make convert widget: {EV_WIDGET} feature {NONE} -- Initialization make (a_iron_service: ES_IRON_SERVICE) do iron_service := a_iron_service create box build_interface (box) end build_interface (b: EV_VERTICAL_BOX) local g: like packages_grid lst: like repositories_grid hsp: EV_VERTICAL_SPLIT_AREA vb: EV_VERTICAL_BOX; hb: EV_HORIZONTAL_BOX but: EV_BUTTON l_filter: like filter_text do -- Create attached attributes. create info_widget.make (iron_service) create packages_grid create update_button create on_iron_package_selected_actions create on_iron_packages_changed_actions -- Repositories create hb hb.set_padding (layout_constants.small_padding_size) hb.set_border_width (layout_constants.small_border_size) b.extend (hb) b.disable_item_expand (hb) hb.extend (create {EV_LABEL}.make_with_text (conf_interface_names.iron_box_repositories_label)) hb.disable_item_expand (hb.last) hb.extend (create {EV_CELL}) create lst b.extend (lst) repositories_grid := lst lst.set_column_count_to (1) lst.enable_single_row_selection lst.set_row_count_to (0) b.disable_item_expand (lst) lst.hide_header -- toolbar/filter/.. create hb hb.set_padding (layout_constants.small_padding_size) hb.set_border_width (layout_constants.small_border_size) b.extend (hb) b.disable_item_expand (hb) hb.extend (create {EV_LABEL}.make_with_text (conf_interface_names.iron_box_packages_label)) hb.disable_item_expand (hb.last) hb.extend (create {EV_CELL}) hb.extend (create {EV_LABEL}.make_with_text (Names.l_filter)) hb.disable_item_expand (hb.last) create l_filter filter_text := l_filter hb.extend (l_filter) l_filter.change_actions.extend (agent request_update_filter) create but but.select_actions.extend (agent l_filter.remove_text) but.set_pixmap (conf_pixmaps.general_remove_icon) but.set_tooltip (names.b_reset) hb.extend (but) hb.disable_item_expand (but) -- Split area create hsp b.extend (hsp) -- First part of the split area g := packages_grid create vb vb.set_border_width (3) vb.extend (g) hsp.set_first (vb) g.set_column_count_to (4) g.column (1).set_title (conf_interface_names.iron_box_package_label) g.column (2).set_title (conf_interface_names.iron_box_installation_label) g.column (3).set_title (conf_interface_names.iron_box_location_label) g.column (4).set_title (conf_interface_names.iron_box_information_label) g.enable_single_row_selection g.row_select_actions.extend (agent on_single_row_selected) g.row_deselect_actions.extend (agent on_single_row_deselected) g.set_row_count_to (1) g.set_item (1, 1, create {EV_GRID_LABEL_ITEM}.make_with_text (conf_interface_names.iron_box_package_waiting_for_data_message)) -- Second part of the split area. create vb create hb hb.set_padding (layout_constants.small_padding_size) hb.set_border_width (layout_constants.small_border_size) vb.extend (hb) vb.disable_item_expand (hb) hb.extend (create {EV_LABEL}.make_with_text (conf_interface_names.iron_box_package_status_label)) hb.disable_item_expand (hb.last) hb.extend (create {EV_CELL}) but := update_button but.set_text (conf_interface_names.iron_box_update_label) layout_constants.set_default_size_for_button (but) but.select_actions.extend (agent update_iron) hb.extend (but) -- create info_widget.make (iron_service) info_widget.on_install_actions.extend (agent install_selected_package) info_widget.on_uninstall_actions.extend (agent remove_selected_package) vb.extend (info_widget.widget) hsp.set_second (vb) -- Set the second part of the split area. hsp.disable_item_expand (vb) hsp.set_split_position (hsp.height - vb.minimum_height) b.focus_in_actions.extend_kamikaze (agent populate) end iron_service: ES_IRON_SERVICE feature -- Callback package_from_row (a_row: EV_GRID_ROW): detachable IRON_PACKAGE do if attached {IRON_PACKAGE} a_row.data as p then Result := p end end on_single_row_deselected (a_row: EV_GRID_ROW) do on_iron_package_selected (Void) end on_single_row_selected (a_row: EV_GRID_ROW) do on_iron_package_selected (package_from_row (a_row)) end on_iron_package_selected (p: detachable IRON_PACKAGE) do info_widget.set_package (p) on_iron_package_selected_actions.call ([p]) end on_iron_package_selected_actions: ACTION_SEQUENCE [TUPLE [package: detachable IRON_PACKAGE]] -- Actions to be triggered when a package is selected. on_iron_packages_changed_actions: ACTION_SEQUENCE [TUPLE [package: detachable IRON_PACKAGE]] -- Actions to be triggered when there is a change in iron data, -- if `package' is attached, the change is related to that package. --| trigger: when a package is installed, or removed, and when update is executed. feature {NONE} -- Update filter update_filter_timeout: detachable EV_TIMEOUT request_update_filter local l_update_filter_timeout: like update_filter_timeout do cancel_delayed_update_filter l_update_filter_timeout := update_filter_timeout if l_update_filter_timeout = Void then create l_update_filter_timeout update_filter_timeout := l_update_filter_timeout l_update_filter_timeout.actions.extend_kamikaze (agent delayed_update_filter) end l_update_filter_timeout.set_interval (700) end cancel_delayed_update_filter do if attached update_filter_timeout as l_update_filter_timeout then l_update_filter_timeout.destroy update_filter_timeout := Void end end delayed_update_filter do cancel_delayed_update_filter update_filter end update_filter local l_style: EV_POINTER_STYLE do l_style := widget.pointer_style widget.set_pointer_style ((create {EV_STOCK_PIXMAPS}).busy_cursor) update widget.set_pointer_style (l_style) end filter_string: detachable STRING_32 do Result := filter_text.text if Result /= Void then Result.left_adjust Result.right_adjust if Result.is_empty then Result := Void end end if Result /= Void then if Result.item (1) /= '*' then Result.prepend_character ('*') end if Result.item (Result.count) /= '*' then Result.append_character ('*') end end end filter_matcher: detachable KMP_WILD do -- And filter if pattern specified if attached filter_string as l_filter then create Result.make_empty Result.set_pattern (l_filter) Result.disable_case_sensitive end end feature -- Basic operations is_populated: BOOLEAN reload do is_populated := False populate end update do reload end populate local api: IRON_INSTALLATION_API i: INTEGER l_package: IRON_PACKAGE l_names: STRING_TABLE [IRON_PACKAGE] g: like packages_grid repos: like repositories_grid l_row: EV_GRID_ROW do if is_populated then -- Already populated. else repos := repositories_grid repos.clear api := iron_service.installation_api if attached api.repositories as l_repositories then repos.set_row_count_to (l_repositories.count) i := 0 across api.repositories as ic loop i := i + 1 repos.set_item (1, i, create {EV_GRID_LABEL_ITEM}.make_with_text (ic.location_string)) end end repos.set_minimum_height (i.min (5).max (1) * repos.row_height) g := packages_grid g.clear if attached scored_available_packages as l_packages then g.set_row_count_to (g.row_count + l_packages.count) create l_names.make_caseless (l_packages.count) i := 0 across l_packages as ic loop l_package := ic.value i := i + 1 l_row := g.row (i) l_row.set_data (l_package) if attached l_names.item (l_package.identifier) as l_conflicting_package then build_row (l_row, l_conflicting_package) -- Conflicting else l_names.put (l_package, l_package.identifier) build_row (l_row, Void) end if ic.score_is_zero then l_row.hide else l_row.show end end end if g.column_count >= 2 then g.column (2).resize_to_content if g.column_count >= 3 then g.column (3).resize_to_content end end is_populated := True end end scored_available_packages: LIST [SCORED_VALUE [IRON_PACKAGE]] local lst: LIST [IRON_PACKAGE] prov: ES_LIBRARY_IRON_PACKAGE_PROVIDER do create prov.make (iron_service) lst := iron_service.installation_api.available_packages if attached filter_string as f then Result := prov.scorer.sorted_scored_list (f, lst, True) else create {ARRAYED_LIST [SCORED_VALUE [IRON_PACKAGE]]} Result.make (lst.count) across lst as ic loop Result.force (create {SCORED_VALUE [IRON_PACKAGE]}.make (ic, 1.0)) end end end clear_row (a_row: EV_GRID_ROW) require a_row_exists: not a_row.is_destroyed do a_row.clear end refresh_row_associated_with_package (p: IRON_PACKAGE) local i,n: INTEGER g: like packages_grid l_api: IRON_INSTALLATION_API do l_api := iron_service.installation_api from g := packages_grid i := 1 n := g.row_count until i > n loop if attached package_from_row (g.row (i)) as l_package and then p.is_same_package (l_package) then clear_row (g.row (i)) build_row (g.row (i), l_api.conflicting_available_package (l_package)) end i := i + 1 end end build_row (a_row: EV_GRID_ROW; in_conflict_with: detachable IRON_PACKAGE) require a_row_exists: not a_row.is_destroyed coherent_data: attached {IRON_PACKAGE} a_row.data local api: IRON_INSTALLATION_API glab: EV_GRID_LABEL_ITEM s,t: STRING_32 i: INTEGER is_installed: BOOLEAN do api := iron_service.installation_api i := a_row.index if attached {IRON_PACKAGE} a_row.data as l_package then clear_row (a_row) -- Package identifier create glab.make_with_text (l_package.identifier) a_row.set_item (1, glab) a_row.set_data (l_package) is_installed := api.is_package_installed (l_package) if attached l_package.description as desc and then not desc.is_empty then glab.set_tooltip (desc) end -- Installation info if is_installed then if attached api.package_installation_path (l_package) as p then create glab.make_with_text ({STRING_32} "Installed in " + p.name) else create glab end if in_conflict_with /= Void then glab.set_pixmap (conf_pixmaps.general_warning_icon) else glab.set_pixmap (conf_pixmaps.general_tick_icon) end else if in_conflict_with /= Void then create glab.make_with_text (conf_interface_names.iron_box_conflicting_with_package_message (in_conflict_with.location.string)) glab.set_pixmap (conf_pixmaps.general_warning_icon) else create glab.make_with_text (conf_interface_names.iron_box_how_to_install_selected_package_message) glab.set_pixmap (conf_pixmaps.general_add_icon) end end glab.set_data (l_package) a_row.set_item (2, glab) -- Location create glab.make_with_text (l_package.location.string) a_row.set_item (3, glab) -- Information create s.make_empty if attached l_package.tags as l_tags and then not l_tags.is_empty then s.append ("tags:") create t.make_empty across l_tags as tags_ic loop if not t.is_empty then t.append_character (',') end t.append (tags_ic) end s.append (t) s.append_character (' ') end if s.is_empty then create glab else create glab.make_with_text (s) end a_row.set_item (4, glab) else clear_row (a_row) a_row.set_item (1, create {EV_GRID_LABEL_ITEM}.make_with_text (conf_interface_names.iron_box_missing_package_error_message)) end end feature -- Iron package management install_package (p: IRON_PACKAGE; cb: detachable PROCEDURE [TUPLE [succeed: BOOLEAN]]) do iron_service.install_package (p, cb) end uninstall_package (p: IRON_PACKAGE; cb: detachable PROCEDURE [TUPLE [succeed: BOOLEAN]]) do iron_service.uninstall_package (p, cb) end feature -- Actions selected_package: detachable IRON_PACKAGE do if attached packages_grid.selected_rows as lst then if lst.count = 1 then Result := package_from_row (lst.first) end end end install_selected_package (p: IRON_PACKAGE) do install_package (p, agent (ia_p: IRON_PACKAGE; ia_succeed: BOOLEAN) do iron_service.installation_api.refresh_installed_packages refresh_row_associated_with_package (ia_p) on_iron_packages_changed_actions.call ([ia_p]) end(p, ?) ) end remove_selected_package (p: IRON_PACKAGE) do uninstall_package (p, agent (ia_p: IRON_PACKAGE; ia_succeed: BOOLEAN) do iron_service.installation_api.refresh_installed_packages refresh_row_associated_with_package (ia_p) on_iron_packages_changed_actions.call ([ia_p]) end(p, ?) ) end update_iron -- Install iron package `a_package' and call associated callback `cb'. do iron_service.update_iron ( agent (ia_succeed: BOOLEAN) do iron_service.installation_api.refresh if ia_succeed then reload end on_iron_packages_changed_actions.call ([Void]) end ) end feature -- Access parent_window_of (w: EV_WIDGET): detachable EV_WINDOW -- Parent for all dialogs shown. do if attached w.parent as p then if attached {EV_WINDOW} p as win then Result := win else Result := parent_window_of (p) end end end feature -- Access widget: EV_WIDGET do Result := box end filter_text: EV_TEXT_FIELD update_button: EV_BUTTON feature -- Widgets box: EV_VERTICAL_BOX packages_grid: ES_GRID repositories_grid: ES_GRID info_widget: IRON_PACKAGE_WIDGET feature -- Events hide do widget.hide end show do widget.show end set_focus do if packages_grid.is_show_requested then packages_grid.set_focus end end note copyright: "Copyright (c) 1984-2021, Eiffel Software" license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)" licensing_options: "http://www.eiffel.com/licensing" copying: "[ This file is part of Eiffel Software's Eiffel Development Environment. Eiffel Software's Eiffel Development Environment is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License (available at the URL listed under "license" above). Eiffel Software's Eiffel Development Environment is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eiffel Software's Eiffel Development Environment; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ]" 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