diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..fe4b6e5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,329 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = false +max_line_length = 140 +tab_width = 2 +ij_continuation_indent_size = 2 + +ij_any_else_on_new_line = true +ij_any_catch_on_new_line = true +ij_any_finally_on_new_line = true +ij_any_block_comment_at_first_column = false +ij_any_line_comment_at_first_column = false +ij_javascript_force_semicolon_style = true +ij_javascript_use_semicolon_after_statement = false +# ij_formatter_off_tag = @formatter:off +# ij_formatter_on_tag = @formatter:on +# ij_formatter_tags_enabled = true +# ij_smart_tabs = false +# ij_visual_guides = +# ij_wrap_on_typing = false + +[*.java] +# ij_java_align_consecutive_assignments = false +# ij_java_align_consecutive_variable_declarations = false +# ij_java_align_group_field_declarations = false +# ij_java_align_multiline_annotation_parameters = false +# ij_java_align_multiline_array_initializer_expression = false +# ij_java_align_multiline_assignment = false +# ij_java_align_multiline_binary_operation = false +# ij_java_align_multiline_chained_methods = false +# ij_java_align_multiline_deconstruction_list_components = true +# ij_java_align_multiline_extends_list = false +# ij_java_align_multiline_for = true +# ij_java_align_multiline_method_parentheses = false +# ij_java_align_multiline_parameters = true +# ij_java_align_multiline_parameters_in_calls = false +# ij_java_align_multiline_parenthesized_expression = false +# ij_java_align_multiline_records = true +# ij_java_align_multiline_resources = true +# ij_java_align_multiline_ternary_operation = false +# ij_java_align_multiline_text_blocks = false +# ij_java_align_multiline_throws_list = false +# ij_java_align_subsequent_simple_methods = false +# ij_java_align_throws_keyword = false +# ij_java_align_types_in_multi_catch = true +# ij_java_annotation_parameter_wrap = off +# ij_java_array_initializer_new_line_after_left_brace = false +# ij_java_array_initializer_right_brace_on_new_line = false +# ij_java_array_initializer_wrap = off +# ij_java_assert_statement_colon_on_next_line = false +# ij_java_assert_statement_wrap = off +# ij_java_assignment_wrap = off +# ij_java_binary_operation_sign_on_next_line = false +# ij_java_binary_operation_wrap = off +# ij_java_blank_lines_after_anonymous_class_header = 0 +# ij_java_blank_lines_after_class_header = 0 +# ij_java_blank_lines_after_imports = 1 +# ij_java_blank_lines_after_package = 1 +# ij_java_blank_lines_around_class = 1 +# ij_java_blank_lines_around_field = 0 +# ij_java_blank_lines_around_field_in_interface = 0 +# ij_java_blank_lines_around_initializer = 1 +# ij_java_blank_lines_around_method = 1 +# ij_java_blank_lines_around_method_in_interface = 1 +# ij_java_blank_lines_before_class_end = 0 +# ij_java_blank_lines_before_imports = 1 +# ij_java_blank_lines_before_method_body = 0 +# ij_java_blank_lines_before_package = 0 +# ij_java_block_brace_style = end_of_line +# ij_java_block_comment_add_space = false +# ij_java_block_comment_at_first_column = true +# ij_java_builder_methods = +# ij_java_call_parameters_new_line_after_left_paren = false +# ij_java_call_parameters_right_paren_on_new_line = false +# ij_java_call_parameters_wrap = off +# ij_java_case_statement_on_separate_line = true +# ij_java_catch_on_new_line = false +# ij_java_class_annotation_wrap = split_into_lines +# ij_java_class_brace_style = end_of_line +# ij_java_class_count_to_use_import_on_demand = 5 +# ij_java_class_names_in_javadoc = 1 +# ij_java_deconstruction_list_wrap = normal +# ij_java_do_not_indent_top_level_class_members = false +# ij_java_do_not_wrap_after_single_annotation = false +# ij_java_do_not_wrap_after_single_annotation_in_parameter = false +# ij_java_do_while_brace_force = never +# ij_java_doc_add_blank_line_after_description = true +# ij_java_doc_add_blank_line_after_param_comments = false +# ij_java_doc_add_blank_line_after_return = false +# ij_java_doc_add_p_tag_on_empty_lines = true +# ij_java_doc_align_exception_comments = true +# ij_java_doc_align_param_comments = true +# ij_java_doc_do_not_wrap_if_one_line = false +# ij_java_doc_enable_formatting = true +# ij_java_doc_enable_leading_asterisks = true +# ij_java_doc_indent_on_continuation = false +# ij_java_doc_keep_empty_lines = true +# ij_java_doc_keep_empty_parameter_tag = true +# ij_java_doc_keep_empty_return_tag = true +# ij_java_doc_keep_empty_throws_tag = true +# ij_java_doc_keep_invalid_tags = true +# ij_java_doc_param_description_on_new_line = false +# ij_java_doc_preserve_line_breaks = false +# ij_java_doc_use_throws_not_exception_tag = true +# ij_java_else_on_new_line = false +# ij_java_enum_constants_wrap = off +# ij_java_extends_keyword_wrap = off +# ij_java_extends_list_wrap = off +# ij_java_field_annotation_wrap = split_into_lines +# ij_java_field_name_prefix = +# ij_java_field_name_suffix = +# ij_java_finally_on_new_line = false +# ij_java_for_brace_force = never +# ij_java_for_statement_new_line_after_left_paren = false +# ij_java_for_statement_right_paren_on_new_line = false +# ij_java_for_statement_wrap = off +# ij_java_generate_final_locals = false +# ij_java_generate_final_parameters = false +# ij_java_if_brace_force = never +# ij_java_imports_layout = *,|,javax.**,java.**,|,$* +# ij_java_indent_case_from_switch = true +# ij_java_insert_inner_class_imports = false +# ij_java_insert_override_annotation = true +# ij_java_keep_blank_lines_before_right_brace = 2 +# ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +# ij_java_keep_blank_lines_in_code = 2 +# ij_java_keep_blank_lines_in_declarations = 2 +# ij_java_keep_builder_methods_indents = false +# ij_java_keep_control_statement_in_one_line = true +# ij_java_keep_first_column_comment = true +# ij_java_keep_indents_on_empty_lines = false +# ij_java_keep_line_breaks = true +# ij_java_keep_multiple_expressions_in_one_line = false +# ij_java_keep_simple_blocks_in_one_line = false +# ij_java_keep_simple_classes_in_one_line = false +# ij_java_keep_simple_lambdas_in_one_line = false +# ij_java_keep_simple_methods_in_one_line = false +# ij_java_label_indent_absolute = false +# ij_java_label_indent_size = 0 +# ij_java_lambda_brace_style = end_of_line +# ij_java_layout_static_imports_separately = true +# ij_java_line_comment_add_space = false +# ij_java_line_comment_add_space_on_reformat = false +# ij_java_line_comment_at_first_column = true +# ij_java_local_variable_name_prefix = +# ij_java_local_variable_name_suffix = +# ij_java_method_annotation_wrap = split_into_lines +# ij_java_method_brace_style = end_of_line +# ij_java_method_call_chain_wrap = off +# ij_java_method_parameters_new_line_after_left_paren = false +# ij_java_method_parameters_right_paren_on_new_line = false +# ij_java_method_parameters_wrap = off +# ij_java_modifier_list_wrap = false +# ij_java_multi_catch_types_wrap = normal +# ij_java_names_count_to_use_import_on_demand = 3 +# ij_java_new_line_after_lparen_in_annotation = false +# ij_java_new_line_after_lparen_in_deconstruction_pattern = true +# ij_java_new_line_after_lparen_in_record_header = false +# ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.* +# ij_java_parameter_annotation_wrap = off +# ij_java_parameter_name_prefix = +# ij_java_parameter_name_suffix = +# ij_java_parentheses_expression_new_line_after_left_paren = false +# ij_java_parentheses_expression_right_paren_on_new_line = false +# ij_java_place_assignment_sign_on_next_line = false +# ij_java_prefer_longer_names = true +# ij_java_prefer_parameters_wrap = false +# ij_java_record_components_wrap = normal +# ij_java_repeat_annotations = +# ij_java_repeat_synchronized = true +# ij_java_replace_instanceof_and_cast = false +# ij_java_replace_null_check = true +# ij_java_replace_sum_lambda_with_method_ref = true +# ij_java_resource_list_new_line_after_left_paren = false +# ij_java_resource_list_right_paren_on_new_line = false +# ij_java_resource_list_wrap = off +# ij_java_rparen_on_new_line_in_annotation = false +# ij_java_rparen_on_new_line_in_deconstruction_pattern = true +# ij_java_rparen_on_new_line_in_record_header = false +# ij_java_space_after_closing_angle_bracket_in_type_argument = false +# ij_java_space_after_colon = true +# ij_java_space_after_comma = true +# ij_java_space_after_comma_in_type_arguments = true +# ij_java_space_after_for_semicolon = true +# ij_java_space_after_quest = true +# ij_java_space_after_type_cast = true +# ij_java_space_before_annotation_array_initializer_left_brace = false +# ij_java_space_before_annotation_parameter_list = false +# ij_java_space_before_array_initializer_left_brace = false +# ij_java_space_before_catch_keyword = true +# ij_java_space_before_catch_left_brace = true +# ij_java_space_before_catch_parentheses = true +# ij_java_space_before_class_left_brace = true +# ij_java_space_before_colon = true +# ij_java_space_before_colon_in_foreach = true +# ij_java_space_before_comma = false +# ij_java_space_before_deconstruction_list = false +# ij_java_space_before_do_left_brace = true +# ij_java_space_before_else_keyword = true +# ij_java_space_before_else_left_brace = true +# ij_java_space_before_finally_keyword = true +# ij_java_space_before_finally_left_brace = true +# ij_java_space_before_for_left_brace = true +# ij_java_space_before_for_parentheses = true +# ij_java_space_before_for_semicolon = false +# ij_java_space_before_if_left_brace = true +# ij_java_space_before_if_parentheses = true +# ij_java_space_before_method_call_parentheses = false +# ij_java_space_before_method_left_brace = true +# ij_java_space_before_method_parentheses = false +# ij_java_space_before_opening_angle_bracket_in_type_parameter = false +# ij_java_space_before_quest = true +# ij_java_space_before_switch_left_brace = true +# ij_java_space_before_switch_parentheses = true +# ij_java_space_before_synchronized_left_brace = true +# ij_java_space_before_synchronized_parentheses = true +# ij_java_space_before_try_left_brace = true +# ij_java_space_before_try_parentheses = true +# ij_java_space_before_type_parameter_list = false +# ij_java_space_before_while_keyword = true +# ij_java_space_before_while_left_brace = true +# ij_java_space_before_while_parentheses = true +# ij_java_space_inside_one_line_enum_braces = false +# ij_java_space_within_empty_array_initializer_braces = false +# ij_java_space_within_empty_method_call_parentheses = false +# ij_java_space_within_empty_method_parentheses = false +# ij_java_spaces_around_additive_operators = true +# ij_java_spaces_around_annotation_eq = true +# ij_java_spaces_around_assignment_operators = true +# ij_java_spaces_around_bitwise_operators = true +# ij_java_spaces_around_equality_operators = true +# ij_java_spaces_around_lambda_arrow = true +# ij_java_spaces_around_logical_operators = true +# ij_java_spaces_around_method_ref_dbl_colon = false +# ij_java_spaces_around_multiplicative_operators = true +# ij_java_spaces_around_relational_operators = true +# ij_java_spaces_around_shift_operators = true +# ij_java_spaces_around_type_bounds_in_type_parameters = true +# ij_java_spaces_around_unary_operator = false +# ij_java_spaces_within_angle_brackets = false +# ij_java_spaces_within_annotation_parentheses = false +# ij_java_spaces_within_array_initializer_braces = false +# ij_java_spaces_within_braces = false +# ij_java_spaces_within_brackets = false +# ij_java_spaces_within_cast_parentheses = false +# ij_java_spaces_within_catch_parentheses = false +# ij_java_spaces_within_deconstruction_list = false +# ij_java_spaces_within_for_parentheses = false +# ij_java_spaces_within_if_parentheses = false +# ij_java_spaces_within_method_call_parentheses = false +# ij_java_spaces_within_method_parentheses = false +# ij_java_spaces_within_parentheses = false +# ij_java_spaces_within_record_header = false +# ij_java_spaces_within_switch_parentheses = false +# ij_java_spaces_within_synchronized_parentheses = false +# ij_java_spaces_within_try_parentheses = false +# ij_java_spaces_within_while_parentheses = false +# ij_java_special_else_if_treatment = true +# ij_java_static_field_name_prefix = +# ij_java_static_field_name_suffix = +# ij_java_subclass_name_prefix = +# ij_java_subclass_name_suffix = Impl +# ij_java_ternary_operation_signs_on_next_line = false +# ij_java_ternary_operation_wrap = off +# ij_java_test_name_prefix = +# ij_java_test_name_suffix = Test +# ij_java_throws_keyword_wrap = off +# ij_java_throws_list_wrap = off +# ij_java_use_external_annotations = false +# ij_java_use_fq_class_names = false +# ij_java_use_relative_indents = false +# ij_java_use_single_class_imports = true +# ij_java_variable_annotation_wrap = off +# ij_java_visibility = public +# ij_java_while_brace_force = never +# ij_java_while_on_new_line = false +# ij_java_wrap_comments = false +# ij_java_wrap_first_method_in_call_chain = false +# ij_java_wrap_long_lines = false + +[.editorconfig] +# ij_editorconfig_align_group_field_declarations = false +# ij_editorconfig_space_after_colon = false +# ij_editorconfig_space_after_comma = true +# ij_editorconfig_space_before_colon = false +# ij_editorconfig_space_before_comma = false +# ij_editorconfig_spaces_around_assignment_operators = true + +[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.jspx,*.pom,*.rng,*.tagx,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] +# ij_xml_align_attributes = true +# ij_xml_align_text = false +# ij_xml_attribute_wrap = normal +# ij_xml_block_comment_add_space = false +# ij_xml_block_comment_at_first_column = true +# ij_xml_keep_blank_lines = 2 +# ij_xml_keep_indents_on_empty_lines = false +# ij_xml_keep_line_breaks = true +# ij_xml_keep_line_breaks_in_text = true +# ij_xml_keep_whitespaces = false +# ij_xml_keep_whitespaces_around_cdata = preserve +# ij_xml_keep_whitespaces_inside_cdata = false +# ij_xml_line_comment_at_first_column = true +# ij_xml_space_after_tag_name = false +# ij_xml_space_around_equals_in_attribute = false +# ij_xml_space_inside_empty_tag = false +# ij_xml_text_wrap = normal + +[{*.markdown,*.md}] +# ij_markdown_force_one_space_after_blockquote_symbol = true +# ij_markdown_force_one_space_after_header_symbol = true +# ij_markdown_force_one_space_after_list_bullet = true +# ij_markdown_force_one_space_between_words = true +# ij_markdown_format_tables = true +# ij_markdown_insert_quote_arrows_on_wrap = true +# ij_markdown_keep_indents_on_empty_lines = false +# ij_markdown_keep_line_breaks_inside_text_blocks = true +# ij_markdown_max_lines_around_block_elements = 1 +# ij_markdown_max_lines_around_header = 1 +# ij_markdown_max_lines_between_paragraphs = 1 +# ij_markdown_min_lines_around_block_elements = 1 +# ij_markdown_min_lines_around_header = 1 +# ij_markdown_min_lines_between_paragraphs = 1 +# ij_markdown_wrap_text_if_long = true +# ij_markdown_wrap_text_inside_blockquotes = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85d1f12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +### Java template +# Compiled class file +*.class +target/* + +# Log file +*.log + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +# IntelliJ project files +.idea +*.iml +out +gen \ No newline at end of file diff --git a/pom.xml b/pom.xml index c39e89b..6afd73e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,8 @@ UTF-8 UTF-8 - 21 - 21 + 17 + 17 1.4.7 7.0.3 @@ -32,6 +32,8 @@ 2.0.32 6.4.4 1.5.4 + 1.0-alpha3 + 1.2.11 @@ -127,7 +129,19 @@ jfreechart ${jfreechart.version} - + + + org.apache.commons + commons-imaging + ${imaging.version} + + + + xmlwise + xmlwise + ${xmlwise.version} + + diff --git a/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.java b/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.java index 4cb70e0..e085c50 100644 --- a/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.java +++ b/src/main/java/com/luoboduner/moo/info/ui/form/ProcessesForm.java @@ -8,19 +8,28 @@ import com.intellij.uiDesigner.core.Spacer; import com.luoboduner.moo.info.App; import com.luoboduner.moo.info.ui.UiConsts; import lombok.Getter; +import org.apache.commons.imaging.formats.icns.IcnsImageParser; +import org.apache.commons.lang3.SystemUtils; +import org.jetbrains.annotations.NotNull; import oshi.PlatformEnum; import oshi.SystemInfo; import oshi.software.os.OSProcess; import oshi.software.os.OperatingSystem; import oshi.util.FormatUtil; +import xmlwise.Plist; +import javax.swing.Timer; import javax.swing.*; +import javax.swing.filechooser.FileSystemView; import javax.swing.table.*; import java.awt.*; -import java.util.ArrayList; -import java.util.HashMap; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.List; -import java.util.Map; +import java.util.*; /** * ProcessesForm @@ -30,176 +39,287 @@ import java.util.Map; */ @Getter public class ProcessesForm { - private static final String[] COLUMNS = {"PID", "PPID", "Threads", "% CPU", "Cumulative", "VSZ", "RSS", "% Memory", - "Process Name"}; - private static final double[] COLUMN_WIDTH_PERCENT = {0.07, 0.07, 0.07, 0.07, 0.09, 0.1, 0.1, 0.08, 0.35}; + private static final String[] COLUMNS = {"Icon", "PID", "PPID", "Threads", "% CPU", "Cumulative", "VSZ", "RSS", "% Memory", + "Process Name"}; + private static final double[] COLUMN_WIDTH_PERCENT = {0.01, 0.07, 0.07, 0.07, 0.07, 0.09, 0.1, 0.1, 0.08, 0.35}; - private transient static Map priorSnapshotMap = new HashMap<>(); + private final static Map priorSnapshotMap = new HashMap<>(); - private static final Log logger = LogFactory.get(); + private final static HashMap iconCacheMap = new HashMap<>(); - private static ProcessesForm processesForm; - private JPanel mainPanel; - private JTable processTable; - private JRadioButton cpuButton; - private JRadioButton cumulativeCpuButton; - private JRadioButton memButton; - private JRadioButton perProc; - private JRadioButton perSystem; + private static final Log logger = LogFactory.get(); - public static ProcessesForm getInstance() { - if (processesForm == null) { - processesForm = new ProcessesForm(); - } - return processesForm; - } + private static ProcessesForm processesForm; + private JPanel mainPanel; + private JTable processTable; + private JRadioButton cpuButton; + private JRadioButton cumulativeCpuButton; + private JRadioButton memButton; + private JRadioButton perProc; + private JRadioButton perSystem; - public static void init() { - processesForm = getInstance(); + public static ProcessesForm getInstance() { + if (processesForm == null) { + processesForm = new ProcessesForm(); + } + return processesForm; + } - initUi(); - initInfo(); - } + public static void init() { + processesForm = getInstance(); - private static void initUi() { - resetCpuPercentButtonGroup(); - resetSortByButtonGroup(); + initUi(); + initInfo(); + } - processesForm = getInstance(); - if (SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) { - processesForm.perSystem.setSelected(true); - } else { - processesForm.perProc.setSelected(true); - } - processesForm.cpuButton.setSelected(true); + private static void initUi() { + resetCpuPercentButtonGroup(); + resetSortByButtonGroup(); - processesForm.perProc.addActionListener(e -> { - resetCpuPercentButtonGroup(); - processesForm.perProc.setSelected(true); - }); - processesForm.perSystem.addActionListener(e -> { - resetCpuPercentButtonGroup(); - processesForm.perSystem.setSelected(true); - }); + processesForm = getInstance(); + if (SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) { + processesForm.perSystem.setSelected(true); + } else { + processesForm.perProc.setSelected(true); + } + processesForm.cpuButton.setSelected(true); - processesForm.cpuButton.addActionListener(e -> { - resetSortByButtonGroup(); - processesForm.cpuButton.setSelected(true); - }); - processesForm.cumulativeCpuButton.addActionListener(e -> { - resetSortByButtonGroup(); - processesForm.cumulativeCpuButton.setSelected(true); - }); - processesForm.memButton.addActionListener(e -> { - resetSortByButtonGroup(); - processesForm.memButton.setSelected(true); - }); - } + processesForm.perProc.addActionListener(e -> { + resetCpuPercentButtonGroup(); + processesForm.perProc.setSelected(true); + }); + processesForm.perSystem.addActionListener(e -> { + resetCpuPercentButtonGroup(); + processesForm.perSystem.setSelected(true); + }); - /** - * Codes are copied from oshi and have some modifications. - */ - private static void initInfo() { - OperatingSystem os = App.si.getOperatingSystem(); - TableModel model = new DefaultTableModel(parseProcesses(os.getProcesses(null, null, 0), App.si), COLUMNS); - JTable procTable = getInstance().getProcessTable(); - procTable.setModel(model); - resizeColumns(procTable.getColumnModel()); - procTable.setShowGrid(true); + processesForm.cpuButton.addActionListener(e -> { + resetSortByButtonGroup(); + processesForm.cpuButton.setSelected(true); + }); + processesForm.cumulativeCpuButton.addActionListener(e -> { + resetSortByButtonGroup(); + processesForm.cumulativeCpuButton.setSelected(true); + }); + processesForm.memButton.addActionListener(e -> { + resetSortByButtonGroup(); + processesForm.memButton.setSelected(true); + }); + } - DefaultTableCellRenderer hr = (DefaultTableCellRenderer) procTable.getTableHeader() - .getDefaultRenderer(); - // The name of header column turn to left - hr.setHorizontalAlignment(DefaultTableCellRenderer.LEFT); + /** + * Codes are copied from oshi and have some modifications. + */ + private static void initInfo() { + OperatingSystem os = App.si.getOperatingSystem(); + TableModel model = new DefaultTableModel(parseProcesses(os.getProcesses(null, null, 0), App.si), COLUMNS) { + @Override + public Class getColumnClass(int column) { + if (column == 0) { - Timer timer = new Timer(UiConsts.REFRESH_SLOW, e -> { - DefaultTableModel tableModel = (DefaultTableModel) procTable.getModel(); - Object[][] newData = parseProcesses(os.getProcesses(null, null, 0), App.si); - int rowCount = tableModel.getRowCount(); - for (int row = 0; row < newData.length; row++) { - if (row < rowCount) { - // Overwrite row - for (int col = 0; col < newData[row].length; col++) { - tableModel.setValueAt(newData[row][col], row, col); - } - } else { - // Add row - tableModel.addRow(newData[row]); - } - } - // Delete any extra rows - for (int row = rowCount - 1; row >= newData.length; row--) { - tableModel.removeRow(row); - } - }); - timer.start(); - } + return ImageIcon.class; + } + return Object.class; + } + }; + JTable procTable = getInstance().getProcessTable(); + procTable.setModel(model); + resizeColumns(procTable.getColumnModel()); + procTable.getColumnModel().getColumn(0).setMaxWidth(32); + procTable.getColumnModel().getColumn(0).setMinWidth(32); + procTable.setShowGrid(true); - /** - * Codes are copied from oshi and have some modifications. - * - * @param list - * @param si - * @return - */ - private static Object[][] parseProcesses(List list, SystemInfo si) { - processesForm = getInstance(); - long totalMem = si.getHardware().getMemory().getTotal(); - int cpuCount = si.getHardware().getProcessor().getLogicalProcessorCount(); - // Build a map with a value for each process to control the sort - Map processSortValueMap = new HashMap<>(); - for (OSProcess p : list) { - int pid = p.getProcessID(); - // Ignore the Idle process on Windows - if (pid > 0 || !SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) { - // Set up for appropriate sort - if (processesForm.cpuButton.isSelected()) { - processSortValueMap.put(p, p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid))); - } else if (processesForm.cumulativeCpuButton.isSelected()) { - processSortValueMap.put(p, p.getProcessCpuLoadCumulative()); - } else { - processSortValueMap.put(p, (double) p.getResidentSetSize()); - } - } - } - // Now sort the list by the values - List> procList = new ArrayList<>(processSortValueMap.entrySet()); - procList.sort(Map.Entry.comparingByValue()); - // Insert into array in reverse order (lowest sort value last) - int i = procList.size(); - Object[][] procArr = new Object[i][COLUMNS.length]; - // These are in descending CPU order - for (Map.Entry e : procList) { - OSProcess p = e.getKey(); - // Matches order of COLUMNS field - i--; - int pid = p.getProcessID(); - procArr[i][0] = pid; - procArr[i][1] = p.getParentProcessID(); - procArr[i][2] = p.getThreadCount(); - if (processesForm.perProc.isSelected()) { - procArr[i][3] = String.format("%.1f", - 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid)) / cpuCount); - procArr[i][4] = String.format("%.1f", 100d * p.getProcessCpuLoadCumulative() / cpuCount); - } else { - procArr[i][3] = String.format("%.1f", - 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid))); - procArr[i][4] = String.format("%.1f", 100d * p.getProcessCpuLoadCumulative()); - } - procArr[i][5] = FormatUtil.formatBytes(p.getVirtualSize()); - procArr[i][6] = FormatUtil.formatBytes(p.getResidentSetSize()); - procArr[i][7] = String.format("%.1f", 100d * p.getResidentSetSize() / totalMem); - procArr[i][8] = p.getName(); - } - // Re-populate snapshot map - priorSnapshotMap.clear(); - for (OSProcess p : list) { - priorSnapshotMap.put(p.getProcessID(), p); - } - return procArr; - } + DefaultTableCellRenderer hr = (DefaultTableCellRenderer) procTable.getTableHeader() + .getDefaultRenderer(); + // The name of header column turn to left + hr.setHorizontalAlignment(DefaultTableCellRenderer.LEFT); - /** + Timer timer = new Timer(UiConsts.REFRESH_SLOW, e -> { + DefaultTableModel tableModel = (DefaultTableModel) procTable.getModel(); + Object[][] newData = parseProcesses(os.getProcesses(null, null, 0), App.si); + int rowCount = tableModel.getRowCount(); + for (int row = 0; row < newData.length; row++) { + if (row < rowCount) { + // Overwrite row + for (int col = 0; col < newData[row].length; col++) { + tableModel.setValueAt(newData[row][col], row, col); + } + } else { + // Add row + tableModel.addRow(newData[row]); + } + } + // Delete any extra rows + for (int row = rowCount - 1; row >= newData.length; row--) { + tableModel.removeRow(row); + } + }); + timer.start(); + } + + /** + * Codes are copied from oshi and have some modifications. + * + * @param list + * @param si + * @return + */ + private static Object[][] parseProcesses(List list, SystemInfo si) { + processesForm = getInstance(); + long totalMem = si.getHardware().getMemory().getTotal(); + int cpuCount = si.getHardware().getProcessor().getLogicalProcessorCount(); + // Build a map with a value for each process to control the sort + Map processSortValueMap = new HashMap<>(); + for (OSProcess p : list) { + int pid = p.getProcessID(); + // Ignore the Idle process on Windows + if (pid > 0 || !SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) { + // Set up for appropriate sort + if (processesForm.cpuButton.isSelected()) { + processSortValueMap.put(p, p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid))); + } else if (processesForm.cumulativeCpuButton.isSelected()) { + processSortValueMap.put(p, p.getProcessCpuLoadCumulative()); + } else { + processSortValueMap.put(p, (double) p.getResidentSetSize()); + } + } + } + // Now sort the list by the values + List> procList = new ArrayList<>(processSortValueMap.entrySet()); + procList.sort(Map.Entry.comparingByValue()); + // Insert into array in reverse order (lowest sort value last) + int i = procList.size(); + Object[][] procArr = new Object[i][COLUMNS.length]; + // These are in descending CPU order + for (Map.Entry e : procList) { + OSProcess p = e.getKey(); + // Matches order of COLUMNS field + i--; + int pid = p.getProcessID(); + procArr[i][0] = getProcessIcon(p.getPath()); + procArr[i][1] = pid; + procArr[i][2] = p.getParentProcessID(); + procArr[i][3] = p.getThreadCount(); + if (processesForm.perProc.isSelected()) { + procArr[i][4] = String.format("%.1f", + 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid)) / cpuCount); + procArr[i][5] = String.format("%.1f", 100d * p.getProcessCpuLoadCumulative() / cpuCount); + } else { + procArr[i][4] = String.format("%.1f", + 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid))); + procArr[i][5] = String.format("%.1f", 100d * p.getProcessCpuLoadCumulative()); + } + procArr[i][6] = FormatUtil.formatBytes(p.getVirtualSize()); + procArr[i][7] = FormatUtil.formatBytes(p.getResidentSetSize()); + procArr[i][8] = String.format("%.1f", 100d * p.getResidentSetSize() / totalMem); + procArr[i][9] = p.getName(); + } + // Re-populate snapshot map + priorSnapshotMap.clear(); + for (OSProcess p : list) { + priorSnapshotMap.put(p.getProcessID(), p); + } + return procArr; + } + + /** + * Retrieves the executable's associated icon if available, or returns null. + * + * @param fullProcessPathName The full path of the executable process. + * @return The associated icon, or null if not found. + */ + private static Icon getProcessIcon(String fullProcessPathName) { + if (iconCacheMap.containsKey(fullProcessPathName)) { + return iconCacheMap.get(fullProcessPathName); + } + + File file = new File(fullProcessPathName); + if (!file.exists()) { + // Alternatively, provide a default icon or return nul + return UIManager.getIcon("FileView.fileIcon"); + } + + try { + if (SystemUtils.IS_OS_WINDOWS) { + Icon icon = FileSystemView.getFileSystemView().getSystemIcon(file); + iconCacheMap.put(fullProcessPathName, icon); + return icon; + } + + if (SystemUtils.IS_OS_LINUX) { + // investigate why getPath or getCommandLine is "" on kali + } + + // macOS-specific icon retrieval + // maybe find a simpler solution + // Todo : fix various icons like VLC ... + if (SystemUtils.IS_OS_MAC && fullProcessPathName.contains("MacOS")) { + String iconPathSplit = fullProcessPathName.split("MacOS")[0]; + String plistFilePath = iconPathSplit + "Info.plist"; + + File pListFile = getFileWithSpaceUri(plistFilePath); + if (pListFile.exists()) { + Map properties = Plist.load(plistFilePath); + String cFBundleIconFile = (String) properties.get("CFBundleIconFile"); + String iconFilePath = iconPathSplit + "Resources/" + cFBundleIconFile; + + // Ensure file path ends with ".icns" + if (!iconFilePath.endsWith(".icns")) { + iconFilePath += ".icns"; + } + + File iconFile = getFileWithSpaceUri(iconFilePath); + if (iconFile.canRead()) { + List iconImages = new IcnsImageParser().getAllBufferedImages(iconFile); + Optional resultImage = iconImages + .stream().parallel() + .filter(num -> num.getRaster().getHeight() == 32).findAny(); + + if (resultImage.isPresent()) { + BufferedImage bufferedImageR = resizeImage(resultImage.get(), 26, 26); + Icon icon = new ImageIcon(bufferedImageR); + iconCacheMap.put(fullProcessPathName, icon); + return icon; + } + + } + } + } + } catch (Exception e) { + } + return UIManager.getIcon("FileView.fileIcon"); + } + + @NotNull + /** + * Workaround to open folders files with spaces + * @param filePath + * @return file + */ + private static File getFileWithSpaceUri(String filePath) throws URISyntaxException { + URI outputURI = new URI(("file:///" + filePath.replaceAll(" ", "%20"))); + File outputFile = new File(outputURI); + return outputFile; + } + + /** + * ResizeImage BufferedImage to given targetWidth targetHeight preserve transparency + * + * @param originalImage + * @param targetWidth + * @param targetHeight + * @return resizeImage + */ + public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException { + BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB_PRE); + Graphics2D graphics2D = resizedImage.createGraphics(); + graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); + graphics2D.dispose(); + return resizedImage; + } + + + /** * Codes are copied from oshi and have some modifications. * * @param tableColumnModel @@ -230,60 +350,60 @@ public class ProcessesForm { processesForm.perSystem.setSelected(false); } - { + { // GUI initializer generated by IntelliJ IDEA GUI Designer // >>> IMPORTANT!! <<< // DO NOT EDIT OR ADD ANY CODE HERE! - $$$setupUI$$$(); - } + $$$setupUI$$$(); + } - /** - * Method generated by IntelliJ IDEA GUI Designer - * >>> IMPORTANT!! <<< - * DO NOT edit this method OR call it in your code! - * - * @noinspection ALL - */ - private void $$$setupUI$$$() { - mainPanel = new JPanel(); - mainPanel.setLayout(new GridLayoutManager(2, 1, new Insets(20, 20, 20, 20), -1, -1)); - final JScrollPane scrollPane1 = new JScrollPane(); - mainPanel.add(scrollPane1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - processTable = new JTable(); - scrollPane1.setViewportView(processTable); - final JPanel panel1 = new JPanel(); - panel1.setLayout(new GridLayoutManager(1, 8, new Insets(0, 0, 10, 0), -1, -1)); - mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); - final JLabel label1 = new JLabel(); - label1.setText("Sort by: "); - panel1.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final Spacer spacer1 = new Spacer(); - panel1.add(spacer1, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); - final JLabel label2 = new JLabel(); - label2.setText("CPU %: "); - panel1.add(label2, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - cpuButton = new JRadioButton(); - cpuButton.setText("CPU %"); - panel1.add(cpuButton, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - cumulativeCpuButton = new JRadioButton(); - cumulativeCpuButton.setText("Cumulative CPU"); - panel1.add(cumulativeCpuButton, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - memButton = new JRadioButton(); - memButton.setText("Memory %"); - panel1.add(memButton, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - perProc = new JRadioButton(); - perProc.setText("of one Processor"); - panel1.add(perProc, new GridConstraints(0, 6, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - perSystem = new JRadioButton(); - perSystem.setText("of System"); - panel1.add(perSystem, new GridConstraints(0, 7, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - } + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(2, 1, new Insets(20, 20, 20, 20), -1, -1)); + final JScrollPane scrollPane1 = new JScrollPane(); + mainPanel.add(scrollPane1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + processTable = new JTable(); + scrollPane1.setViewportView(processTable); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 8, new Insets(0, 0, 10, 0), -1, -1)); + mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label1 = new JLabel(); + label1.setText("Sort by: "); + panel1.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JLabel label2 = new JLabel(); + label2.setText("CPU %: "); + panel1.add(label2, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + cpuButton = new JRadioButton(); + cpuButton.setText("CPU %"); + panel1.add(cpuButton, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + cumulativeCpuButton = new JRadioButton(); + cumulativeCpuButton.setText("Cumulative CPU"); + panel1.add(cumulativeCpuButton, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + memButton = new JRadioButton(); + memButton.setText("Memory %"); + panel1.add(memButton, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + perProc = new JRadioButton(); + perProc.setText("of one Processor"); + panel1.add(perProc, new GridConstraints(0, 6, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + perSystem = new JRadioButton(); + perSystem.setText("of System"); + panel1.add(perSystem, new GridConstraints(0, 7, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + } - /** - * @noinspection ALL - */ - public JComponent $$$getRootComponent$$$() { - return mainPanel; - } + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } }