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;
+ }
}