mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-09 16:25:10 +03:00
Compare commits
219 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9026efeb26 | ||
|
|
2ab023beb0 | ||
|
|
8e471fd720 | ||
|
|
13cbbd8bc1 | ||
|
|
b08ccc9767 | ||
|
|
801a7023a4 | ||
|
|
dd06b554da | ||
|
|
23f0504b30 | ||
|
|
262d172cde | ||
|
|
be81cb7876 | ||
|
|
aaf9bd33cb | ||
|
|
7381e2141f | ||
|
|
3923d941c1 | ||
|
|
d134c33499 | ||
|
|
a2b615d4a7 | ||
|
|
2e1acb7871 | ||
|
|
97a1bf90a4 | ||
|
|
7d3ffbc45a | ||
|
|
93ac6fa88a | ||
|
|
09d19a13b7 | ||
|
|
9eaee8d2c4 | ||
|
|
4da0c342f8 | ||
|
|
70fed22737 | ||
|
|
acb62e347a | ||
|
|
78d06d82d6 | ||
|
|
4777bdd250 | ||
|
|
266e9d92d5 | ||
|
|
54c14d0dc8 | ||
|
|
d59d353c2e | ||
|
|
204da2175b | ||
|
|
152f235ca1 | ||
|
|
d094709dc8 | ||
|
|
97d5792341 | ||
|
|
9429ba7d48 | ||
|
|
af89dd13c1 | ||
|
|
60c6c5b37a | ||
|
|
5ed40cab1d | ||
|
|
1bebfe9cf2 | ||
|
|
e2618c37a2 | ||
|
|
f2ab848c46 | ||
|
|
93b82c0e97 | ||
|
|
4ac5ad06f2 | ||
|
|
a3788038bb | ||
|
|
12af2de99e | ||
|
|
225b722b1b | ||
|
|
1d9c8ca65e | ||
|
|
e51ffe2a1c | ||
|
|
c706a79f74 | ||
|
|
2608061d48 | ||
|
|
df1634de3d | ||
|
|
4aeabea3fe | ||
|
|
eb30f9d5bf | ||
|
|
de718f847c | ||
|
|
8835e20bfc | ||
|
|
92258f3ba3 | ||
|
|
1bda7595dd | ||
|
|
60557fc8c8 | ||
|
|
1a4a7831f6 | ||
|
|
d1415a8c53 | ||
|
|
0d4f33ac6e | ||
|
|
87100bef7b | ||
|
|
958dfa8ae9 | ||
|
|
d3752573e7 | ||
|
|
cfd07cbcc8 | ||
|
|
33e6ce1673 | ||
|
|
00ccda83f9 | ||
|
|
8d66cce6eb | ||
|
|
ba35fb7525 | ||
|
|
4fd2b24b10 | ||
|
|
5f7a33b085 | ||
|
|
65bc5b1f31 | ||
|
|
dd155e9f89 | ||
|
|
5c4ef3b0f5 | ||
|
|
2129a48cc8 | ||
|
|
c0f2784599 | ||
|
|
fee00b2acb | ||
|
|
ae8093313e | ||
|
|
5a4e321f78 | ||
|
|
9d1ed241b9 | ||
|
|
b63cd241d2 | ||
|
|
1e4f2d85a2 | ||
|
|
5cb7be4a64 | ||
|
|
0cd9068c0e | ||
|
|
9d6afe3bde | ||
|
|
52702b5267 | ||
|
|
cd144ff067 | ||
|
|
dd9784b3f2 | ||
|
|
d781b3d4a7 | ||
|
|
790f490674 | ||
|
|
004a5cb765 | ||
|
|
408b2d8376 | ||
|
|
3aa53ff3be | ||
|
|
73b642799d | ||
|
|
b522500379 | ||
|
|
f736ed401f | ||
|
|
c02f824d74 | ||
|
|
6f9a61de56 | ||
|
|
4cebeda37a | ||
|
|
4275005a64 | ||
|
|
5f40ab130e | ||
|
|
7489526eb7 | ||
|
|
e439d91763 | ||
|
|
793969e39b | ||
|
|
9f7ffe8d77 | ||
|
|
eecb867227 | ||
|
|
bff9f135e6 | ||
|
|
03627281d7 | ||
|
|
c83b4093f0 | ||
|
|
7f9f22df3e | ||
|
|
fd48582a9f | ||
|
|
e5761128f9 | ||
|
|
87dd5a9ebb | ||
|
|
11950f8b4d | ||
|
|
f2ddfadc9d | ||
|
|
b1a7983f18 | ||
|
|
b319cb278b | ||
|
|
78e3d781fc | ||
|
|
34834917b0 | ||
|
|
9446c287e9 | ||
|
|
31b0cf396e | ||
|
|
00bb13c230 | ||
|
|
3bf09ee731 | ||
|
|
5b07941c4c | ||
|
|
23c30ec46d | ||
|
|
22c06300f1 | ||
|
|
37cca1b106 | ||
|
|
f0a49c806e | ||
|
|
a1d5f65588 | ||
|
|
b6789e14a4 | ||
|
|
c72ee30a25 | ||
|
|
686d667c4f | ||
|
|
26d603db5d | ||
|
|
409840aef9 | ||
|
|
1f3c264afe | ||
|
|
cd69d9a1a7 | ||
|
|
a000c8fd99 | ||
|
|
84d05603ef | ||
|
|
9d046ecd1d | ||
|
|
030e1809f3 | ||
|
|
5853bd4a96 | ||
|
|
10695ff51b | ||
|
|
f421659fea | ||
|
|
df4f51eff3 | ||
|
|
7e61d6a850 | ||
|
|
0910bd23c4 | ||
|
|
5a29753912 | ||
|
|
a467356437 | ||
|
|
094967f52a | ||
|
|
757b0812ba | ||
|
|
8f4f5d8c92 | ||
|
|
4e266483ba | ||
|
|
7433dc9cf3 | ||
|
|
409a773e36 | ||
|
|
48bdd5c3df | ||
|
|
5796057a75 | ||
|
|
c8248e91ca | ||
|
|
7317ce44e7 | ||
|
|
10e2a5b1eb | ||
|
|
e675d1b7e2 | ||
|
|
499c4dadd5 | ||
|
|
f550f84acd | ||
|
|
8021f1a7fc | ||
|
|
d50fe606ee | ||
|
|
281f014aa0 | ||
|
|
2f6da3e84a | ||
|
|
f9accc2a7a | ||
|
|
fe15078bbd | ||
|
|
27d4b5eba7 | ||
|
|
e378576632 | ||
|
|
74909da110 | ||
|
|
655bf112ac | ||
|
|
5c3638a5a4 | ||
|
|
2459a3654b | ||
|
|
e9a3456cf5 | ||
|
|
2bcdf774ff | ||
|
|
ef01f23384 | ||
|
|
ab7bbb6593 | ||
|
|
f2dad88875 | ||
|
|
c474565ff5 | ||
|
|
fd9dbbd7e6 | ||
|
|
43ab095e0f | ||
|
|
41e2888bf1 | ||
|
|
e7d5e22960 | ||
|
|
3f3884193d | ||
|
|
dfccabc2b9 | ||
|
|
af7c181596 | ||
|
|
8e84112837 | ||
|
|
822cd16daa | ||
|
|
33ea84004d | ||
|
|
8dbbe20840 | ||
|
|
d990ccc4ab | ||
|
|
9f16249898 | ||
|
|
62fc3139cf | ||
|
|
452452dcc9 | ||
|
|
b6fb06bc65 | ||
|
|
aac6bd1b7c | ||
|
|
d260001cbd | ||
|
|
9c470d77cb | ||
|
|
269075657d | ||
|
|
d0029beb22 | ||
|
|
4b4837e3a1 | ||
|
|
d0160b8b6d | ||
|
|
ea351935b2 | ||
|
|
20ccc2951e | ||
|
|
6f9bad1bdf | ||
|
|
39a0d514a8 | ||
|
|
ad82c591cc | ||
|
|
32ceb168d5 | ||
|
|
16146f4c88 | ||
|
|
60febbf3f8 | ||
|
|
4960b30cfb | ||
|
|
56c161fea0 | ||
|
|
27c439d728 | ||
|
|
78d5e03a66 | ||
|
|
f25e647b6a | ||
|
|
e44212fc65 | ||
|
|
a483403774 | ||
|
|
69750dba19 | ||
|
|
af962b99be |
228
.editorconfig
228
.editorconfig
@@ -6,3 +6,231 @@ insert_final_newline = true
|
||||
charset = latin1
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.java]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
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_extends_list = false
|
||||
ij_java_align_multiline_for = true
|
||||
ij_java_align_multiline_method_parentheses = false
|
||||
ij_java_align_multiline_parameters = false
|
||||
ij_java_align_multiline_parameters_in_calls = false
|
||||
ij_java_align_multiline_parenthesized_expression = false
|
||||
ij_java_align_multiline_resources = false
|
||||
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_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 = normal
|
||||
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 = next_line_if_wrapped
|
||||
ij_java_block_comment_at_first_column = true
|
||||
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 = normal
|
||||
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 = next_line
|
||||
ij_java_class_count_to_use_import_on_demand = 99
|
||||
ij_java_class_names_in_javadoc = 1
|
||||
ij_java_do_not_indent_top_level_class_members = false
|
||||
ij_java_do_not_wrap_after_single_annotation = 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 = split_into_lines
|
||||
ij_java_extends_list_wrap = normal
|
||||
ij_java_field_annotation_wrap = split_into_lines
|
||||
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 = java.**,javax.**,*,$*
|
||||
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 = 1
|
||||
ij_java_keep_blank_lines_between_package_declaration_and_header = 1
|
||||
ij_java_keep_blank_lines_in_code = 1
|
||||
ij_java_keep_blank_lines_in_declarations = 1
|
||||
ij_java_keep_control_statement_in_one_line = false
|
||||
ij_java_keep_first_column_comment = false
|
||||
ij_java_keep_indents_on_empty_lines = false
|
||||
ij_java_keep_line_breaks = false
|
||||
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_at_first_column = true
|
||||
ij_java_method_annotation_wrap = split_into_lines
|
||||
ij_java_method_brace_style = next_line_if_wrapped
|
||||
ij_java_method_call_chain_wrap = normal
|
||||
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 = normal
|
||||
ij_java_modifier_list_wrap = false
|
||||
ij_java_names_count_to_use_import_on_demand = 3
|
||||
ij_java_parameter_annotation_wrap = off
|
||||
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_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 = normal
|
||||
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 = true
|
||||
ij_java_space_before_annotation_parameter_list = false
|
||||
ij_java_space_before_array_initializer_left_brace = true
|
||||
ij_java_space_before_catch_keyword = true
|
||||
ij_java_space_before_catch_left_brace = true
|
||||
ij_java_space_before_catch_parentheses = false
|
||||
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_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 = false
|
||||
ij_java_space_before_for_semicolon = false
|
||||
ij_java_space_before_if_left_brace = true
|
||||
ij_java_space_before_if_parentheses = false
|
||||
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 = false
|
||||
ij_java_space_before_synchronized_left_brace = true
|
||||
ij_java_space_before_synchronized_parentheses = false
|
||||
ij_java_space_before_try_left_brace = true
|
||||
ij_java_space_before_try_parentheses = false
|
||||
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 = false
|
||||
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_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 = true
|
||||
ij_java_spaces_within_array_initializer_braces = true
|
||||
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 = true
|
||||
ij_java_spaces_within_for_parentheses = true
|
||||
ij_java_spaces_within_if_parentheses = true
|
||||
ij_java_spaces_within_method_call_parentheses = true
|
||||
ij_java_spaces_within_method_parentheses = true
|
||||
ij_java_spaces_within_parentheses = false
|
||||
ij_java_spaces_within_switch_parentheses = true
|
||||
ij_java_spaces_within_synchronized_parentheses = true
|
||||
ij_java_spaces_within_try_parentheses = true
|
||||
ij_java_spaces_within_while_parentheses = true
|
||||
ij_java_special_else_if_treatment = true
|
||||
ij_java_subclass_name_suffix = Impl
|
||||
ij_java_ternary_operation_signs_on_next_line = true
|
||||
ij_java_ternary_operation_wrap = on_every_item
|
||||
ij_java_test_name_suffix = Test
|
||||
ij_java_throws_keyword_wrap = normal
|
||||
ij_java_throws_list_wrap = normal
|
||||
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
|
||||
|
||||
26
.travis.yml
26
.travis.yml
@@ -19,11 +19,21 @@ before_install:
|
||||
- ./gradlew --version
|
||||
- java -version
|
||||
|
||||
deploy:
|
||||
provider: script
|
||||
script: ./gradlew bintrayUpload
|
||||
skip_cleanup: true # to upload artifacts created during the build
|
||||
on:
|
||||
branch: master
|
||||
jdk: openjdk11
|
||||
tags: true
|
||||
stages:
|
||||
- name: test
|
||||
- name: snapshot
|
||||
if: branch = master AND type IN (push) AND tag IS blank
|
||||
- name: release
|
||||
if: type IN (push) AND tag IS present
|
||||
|
||||
jobs:
|
||||
include:
|
||||
# publish snapshot to oss.jfrog.org
|
||||
- stage: snapshot
|
||||
jdk: openjdk11
|
||||
script: ./gradlew artifactoryPublish
|
||||
|
||||
# release a new stable version to bintray
|
||||
- stage: release
|
||||
jdk: openjdk11
|
||||
script: ./gradlew bintrayUpload -Drelease=true
|
||||
|
||||
194
CHANGELOG.md
194
CHANGELOG.md
@@ -1,6 +1,200 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 0.32
|
||||
|
||||
- ToggleButton: Compute selected background color based on current component
|
||||
background. (issue #32)
|
||||
- IntelliJ Themes: Fixed button and toggle button colors. (issue #86)
|
||||
- Updated IntelliJ Themes in demo to the latest versions.
|
||||
|
||||
|
||||
## 0.31
|
||||
|
||||
- Focus indication border (or background) no longer hidden when temporary
|
||||
loosing focus (e.g. showing a popup menu).
|
||||
- List, Table and Tree: Item selection color of focused components no longer
|
||||
change from blue to gray when temporary loosing focus (e.g. showing a popup
|
||||
menu).
|
||||
|
||||
|
||||
## 0.30
|
||||
|
||||
- Windows: Fixed rendering of Unicode characters. Previously not all Unicode
|
||||
characters were rendered on Windows. (issue #81)
|
||||
|
||||
|
||||
## 0.29
|
||||
|
||||
- Linux: Fixed scaling if `GDK_SCALE` environment variable is set or if running
|
||||
on JetBrains Runtime. (issue #69)
|
||||
- Tree: Fixed repainting wide selection on focus gained/lost.
|
||||
- ComboBox: No longer ignore `JComboBox.prototypeDisplayValue` when computing
|
||||
popup width. (issue #80)
|
||||
- Support changing default font used for all components with automatic scaling
|
||||
UI if using larger font. Use `UIManager.put( "defaultFont", myFont );`
|
||||
- No longer use system property `sun.java2d.uiScale`. (Java 8 only)
|
||||
- Support specifying custom scale factor in system property `flatlaf.uiScale`
|
||||
also for Java 9 and later.
|
||||
- Demo: Support using own FlatLaf themes (`.properties` files) that are located
|
||||
in working directory of Demo application. Shown in the "Themes" list under
|
||||
category "Current Directory".
|
||||
|
||||
|
||||
## 0.28
|
||||
|
||||
- PasswordField: Warn about enabled Caps Lock.
|
||||
- TabbedPane: Support <kbd>Ctrl+TAB</kbd> / <kbd>Ctrl+Shift+TAB</kbd> to switch
|
||||
to next / previous tab.
|
||||
- TextField, FormattedTextField and PasswordField: Support round borders (see UI
|
||||
default value `TextComponent.arc`). (issue #65)
|
||||
- IntelliJ Themes: Added Gradianto themes to demo.
|
||||
- Button, CheckBox and RadioButton: Fixed NPE when button has children. (PR #68)
|
||||
- ScrollBar: Improved colors.
|
||||
- Reviewed (and tested) all key bindings on Windows and macOS. Linux key
|
||||
bindings are equal to Windows key bindings. macOS key bindings are slightly
|
||||
different for platform specific behavior.
|
||||
- UI default values are no longer based on Metal/Aqua UI defaults.
|
||||
|
||||
|
||||
## 0.27
|
||||
|
||||
- Support `JInternalFrame` and `JDesktopPane`. (issues #39 and #11)
|
||||
- Table: Support positioning the column sort arrow in header right, left, top or
|
||||
bottom. (issue #34)
|
||||
- ProgressBar: Fixed visual artifacts in indeterminate mode, on HiDPI screens at
|
||||
125%, 150% and 175% scaling, when the progress moves around.
|
||||
- TabbedPane: New option to allow tab separators to take full height (to enable
|
||||
use `UIManager.put( "TabbedPane.tabSeparatorsFullHeight", true );`). (issue
|
||||
#59, PR #62)
|
||||
- CheckBox and RadioButton: Do not fill background if `contentAreaFilled` is
|
||||
`false`. (issue #58, PR #63)
|
||||
- ToggleButton: Make toggle button square if it has an icon but no text or text
|
||||
is "..." or a single character.
|
||||
- ToolBar: No longer use special rollover border for buttons in toolbar. (issue
|
||||
#36)
|
||||
- ToolBar: Added empty space around buttons in toolbar and toolbar itself (see
|
||||
UI default values `Button.toolbar.spacingInsets` and `ToolBar.borderMargins`).
|
||||
(issue #56)
|
||||
- Fixed "illegal reflective access operation" warning on macOS when using Java
|
||||
12 or later. (issue #60, PR #61)
|
||||
|
||||
|
||||
## 0.26
|
||||
|
||||
- Menus:
|
||||
- Changed menu bar and popup menu background colors (made brighter in light
|
||||
themes and darker in dark themes).
|
||||
- Highlight items in menu bar on mouse hover. (issue #49)
|
||||
- Popup menus now have empty space at the top and bottom.
|
||||
- Menu items now have larger left and right margins.
|
||||
- Made `JMenu`, `JMenuItem`, `JCheckBoxMenuItem` and `JRadioButtonMenuItem`
|
||||
non-opaque.
|
||||
- TextField, FormattedTextField and PasswordField: Select all text when a text
|
||||
field gains focus for the first time and selection was not set explicitly.
|
||||
This can be configured to newer or always select all text on focus gain (see
|
||||
UI default value `TextComponent.selectAllOnFocusPolicy`).
|
||||
- ProgressBar: Made progress bar paint smooth in indeterminate mode.
|
||||
|
||||
|
||||
## 0.25.1
|
||||
|
||||
Re-release of 0.25 because of problems with Maven Central.
|
||||
|
||||
|
||||
## 0.25
|
||||
|
||||
- Hide menu mnemonics by default and show them only when <kbd>Alt</kbd> key is
|
||||
pressed. (issue #43)
|
||||
- Menu: Fixed vertical alignment of sub-menus. (issue #42)
|
||||
- TabbedPane: In scroll-tab-layout, the cropped line is now hidden. (issue #40)
|
||||
- Tree: UI default value `Tree.textBackground` now has a valid color and is no
|
||||
longer `null`.
|
||||
- Tree on macOS: Fixed <kbd>Left</kbd> and <kbd>Right</kbd> keys to collapse or
|
||||
expand nodes.
|
||||
- ComboBox on macOS: Fixed keyboard navigation and show/hide popup.
|
||||
- Button and ToggleButton: Support per component minimum height (set client
|
||||
property `JComponent.minimumHeight` to an integer). (issue #44)
|
||||
- Button and ToggleButton: Do not apply minimum width if button border was
|
||||
changed (is no longer an instance of `FlatButtonBorder`).
|
||||
- ToggleButton: Renamed toggle button type "underline" to "tab" (value of client
|
||||
property `JButton.buttonType` is now `tab`).
|
||||
- ToggleButton: Support per component styling for tab-style toggle buttons with
|
||||
client properties `JToggleButton.tab.underlineHeight` (integer),
|
||||
`JToggleButton.tab.underlineColor` (Color) and
|
||||
`JToggleButton.tab.selectedBackground` (Color). (issue #45)
|
||||
- ToggleButton: No longer use focus width for tab-style toggle buttons to
|
||||
compute component size, which reduces/fixes component size in "Flat IntelliJ"
|
||||
and "Flat Darcula" themes.
|
||||
- TabbedPane: Support per component tab height (set client property
|
||||
`JTabbedPane.tabHeight` to an integer).
|
||||
- ProgressBar: Support square painting (set client property
|
||||
`JProgressBar.square` to `true`) and larger height even if no string is
|
||||
painted (set client property `JProgressBar.largeHeight` to `true`).
|
||||
|
||||
|
||||
## 0.24
|
||||
|
||||
- Support smooth scrolling with touchpads and high precision mouse wheels.
|
||||
(issue #27)
|
||||
- Changed `.properties` file loading order: Now all core `.properties` files are
|
||||
loaded before loading addon `.properties` files. This makes it easier to
|
||||
overwrite core values in addons. Also, addon loading order can be specified.
|
||||
- TableHeader: Paint column borders if renderer has changed, but delegates to
|
||||
the system default renderer (e.g. done in NetBeans).
|
||||
- Label and ToolTip: Fixed font sizes for HTML headings.
|
||||
- Button and ToggleButton: Support square button style (set client property
|
||||
`JButton.buttonType` to `square`).
|
||||
- ToggleButton: Support underline toggle button style (set client property
|
||||
`JButton.buttonType` to `underline`).
|
||||
- Button and TextComponent: Support per component minimum width (set client
|
||||
property `JComponent.minimumWidth` to an integer).
|
||||
- ScrollPane with Table: The border of buttons that are added to one of the four
|
||||
scroll pane corners are now removed if the center component is a table. Also,
|
||||
these corner buttons are made not focusable.
|
||||
- Table: Replaced `Table.showGrid` with `Table.showHorizontalLines` and
|
||||
`Table.showVerticalLines`. (issue #38)
|
||||
- ProgressBar: Now uses blueish color for the progress part in "Flat Dark"
|
||||
theme. In the "Flat Darcula" theme, it remains light gray.
|
||||
- Improved Swing system colors `controlHighlight`, `controlLtHighlight`,
|
||||
`controlShadow` and `controlDkShadow`.
|
||||
|
||||
|
||||
## 0.23.1
|
||||
|
||||
- Tree: Fixed wide selection if scrolled horizontally.
|
||||
- ComboBox: Fixed NPE in Oracle SQL Developer settings.
|
||||
- IntelliJ Themes: Fixed checkbox colors in Material UI Lite dark themes.
|
||||
|
||||
|
||||
## 0.23
|
||||
|
||||
- Updated colors in "Flat Light" and "Flat IntelliJ" themes with colors from
|
||||
"IntelliJ Light Theme", which provides blue coloring that better matches
|
||||
platform colors.
|
||||
- Tree: Support wide selection (enabled by default).
|
||||
- Table: Hide grid and changed intercell spacing to zero.
|
||||
- List, Table and Tree: Added colors for drag-and-drop. Added "enable drag and
|
||||
drop" checkbox to Demo on "Data Components" tab.
|
||||
- List and Tree: Hide cell focus indicator (black rectangle) by default. Can be
|
||||
enabled with `List.showCellFocusIndicator=true` /
|
||||
`Tree.showCellFocusIndicator=true`, but then the cell focus indicator is shown
|
||||
only if more than one item is selected.
|
||||
- Table: Hide cell focus indicator (black rectangle) by default if none of the
|
||||
selected cells is editable. Can be show always with
|
||||
`Table.showCellFocusIndicator=true`.
|
||||
- Support basic color functions in `.properties` files: `rgb(red,green,blue)`,
|
||||
`rgba(red,green,blue,alpha)`, `hsl(hue,saturation,lightness)`,
|
||||
`hsla(hue,saturation,lightness,alpha)`, `lighten(color,amount[,options])` and
|
||||
`darken(color,amount[,options])`.
|
||||
- Replaced prefix `@@` with `$` in `.properties` files.
|
||||
- Fixed link color (in HTML text) and separator color in IntelliJ platform
|
||||
themes.
|
||||
- Use logging instead of printing errors to `System.err`.
|
||||
- Updated IntelliJ Themes in demo to the latest versions.
|
||||
- IntelliJ Themes: Fixed link and separator colors.
|
||||
|
||||
|
||||
## 0.22
|
||||
|
||||
- TextComponent: Support placeholder text that is displayed if text field is
|
||||
|
||||
50
README.md
50
README.md
@@ -45,13 +45,26 @@ build script:
|
||||
|
||||
groupId: com.formdev
|
||||
artifactId: flatlaf
|
||||
version: 0.22
|
||||
version: (see button below)
|
||||
|
||||
Otherwise download `flatlaf-<version>.jar` here:
|
||||
|
||||
[](https://bintray.com/jformdesigner/flatlaf/flatlaf/_latestVersion)
|
||||
|
||||
|
||||
### Snapshots
|
||||
|
||||
FlatLaf snapshot binaries are available in
|
||||
[JFrog Artifactory](https://oss.jfrog.org/artifactory/oss-snapshot-local/com/formdev/).
|
||||
To access the latest snapshot, change the FlatLaf version(s) in the dependencies
|
||||
to `<version>-SNAPSHOT` (e.g. `0.27-SNAPSHOT`) and add the repository
|
||||
`https://oss.jfrog.org/artifactory/oss-snapshot-local` to your build (see
|
||||
[Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html)
|
||||
and
|
||||
[Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository)
|
||||
docs).
|
||||
|
||||
|
||||
Addons
|
||||
------
|
||||
|
||||
@@ -59,6 +72,41 @@ Addons
|
||||
- [JIDE Common Layer](flatlaf-jide-oss)
|
||||
|
||||
|
||||
Projects using FlatLaf
|
||||
----------------------
|
||||
|
||||
- [NetBeans](https://netbeans.apache.org/) 11.3
|
||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
||||
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
||||
- [OWASP Zed Attack Proxy (ZAP)](https://www.zaproxy.org/) (in weekly releases)
|
||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (commercial)
|
||||
- [Total Validator](https://www.totalvalidator.com/) 15 (commercial)
|
||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org)
|
||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5
|
||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
||||
0.13.b024
|
||||
- [Rest Suite](https://github.com/supanadit/restsuite)
|
||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy)
|
||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote)
|
||||
- [mendelson AS2](https://sourceforge.net/projects/mec-as2/),
|
||||
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
||||
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||
[AS4](https://mendelson-e-c.com/as4/) and
|
||||
[OFTP2](https://mendelson-e-c.com/oftp2) (commercial)
|
||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.1.6
|
||||
- [lsfusion platform](https://github.com/lsfusion/platform)
|
||||
- and more...
|
||||
|
||||
|
||||
Buzz
|
||||
----
|
||||
|
||||
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
|
||||
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -14,9 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
version = "0.22"
|
||||
val releaseVersion = "0.32"
|
||||
val developmentVersion = "0.33-SNAPSHOT"
|
||||
|
||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||
|
||||
allprojects {
|
||||
version = rootProject.version
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
@@ -33,3 +38,39 @@ println( "FlatLaf Version: ${version}" )
|
||||
println( "Gradle ${gradle.gradleVersion} at ${gradle.gradleHomeDir}" )
|
||||
println( "Java ${System.getProperty( "java.version" )}" )
|
||||
println()
|
||||
|
||||
|
||||
extra["bintray.user"] = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
|
||||
extra["bintray.key"] = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
|
||||
|
||||
// if true, do not upload to bintray
|
||||
extra["bintray.dryRun"] = false
|
||||
|
||||
// if true, uploaded artifacts are visible to all
|
||||
// if false, only visible to owner when logged into bintray
|
||||
extra["bintray.publish"] = true
|
||||
|
||||
|
||||
allprojects {
|
||||
tasks {
|
||||
withType<JavaCompile>().configureEach {
|
||||
sourceCompatibility = "1.8"
|
||||
targetCompatibility = "1.8"
|
||||
|
||||
options.encoding = "ISO-8859-1"
|
||||
}
|
||||
|
||||
withType<Jar>().configureEach {
|
||||
// manifest for all created JARs
|
||||
manifest.attributes(mapOf(
|
||||
"Implementation-Vendor" to "FormDev Software GmbH",
|
||||
"Implementation-Copyright" to "Copyright (C) ${java.time.LocalDate.now().year} FormDev Software GmbH. All rights reserved.",
|
||||
"Implementation-Version" to project.version))
|
||||
|
||||
// add META-INF/LICENSE to all created JARs
|
||||
from("${rootDir}/LICENSE") {
|
||||
into("META-INF")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -14,12 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
version = rootProject.version
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
id( "com.jfrog.bintray" ) version "1.8.4"
|
||||
id( "com.jfrog.bintray" )
|
||||
id( "com.jfrog.artifactory" )
|
||||
}
|
||||
|
||||
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
@@ -34,11 +33,6 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
tasks {
|
||||
assemble {
|
||||
dependsOn(
|
||||
@@ -53,7 +47,7 @@ tasks {
|
||||
targetCompatibility = "9"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jar {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
|
||||
@@ -68,6 +62,7 @@ tasks {
|
||||
options {
|
||||
this as StandardJavadocDocletOptions
|
||||
tags = listOf( "uiDefault", "clientProperty" )
|
||||
addStringOption( "Xdoclint:all,-missing", "-Xdoclint:all,-missing" )
|
||||
}
|
||||
isFailOnError = false
|
||||
}
|
||||
@@ -106,7 +101,7 @@ publishing {
|
||||
licenses {
|
||||
license {
|
||||
name.set( "The Apache License, Version 2.0" )
|
||||
url.set( "http://www.apache.org/licenses/LICENSE-2.0.txt" )
|
||||
url.set( "https://www.apache.org/licenses/LICENSE-2.0.txt" )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,8 +122,8 @@ publishing {
|
||||
}
|
||||
|
||||
bintray {
|
||||
user = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
|
||||
key = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
|
||||
user = rootProject.extra["bintray.user"] as String?
|
||||
key = rootProject.extra["bintray.key"] as String?
|
||||
|
||||
setPublications( "maven" )
|
||||
|
||||
@@ -142,6 +137,29 @@ bintray {
|
||||
name = project.version.toString()
|
||||
}
|
||||
|
||||
publish = true
|
||||
publish = rootProject.extra["bintray.publish"] as Boolean
|
||||
dryRun = rootProject.extra["bintray.dryRun"] as Boolean
|
||||
}
|
||||
}
|
||||
|
||||
artifactory {
|
||||
setContextUrl( "https://oss.jfrog.org" )
|
||||
|
||||
publish( closureOf<org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig> {
|
||||
repository( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
setProperty( "repoKey", "oss-snapshot-local" )
|
||||
setProperty( "username", rootProject.extra["bintray.user"] as String? )
|
||||
setProperty( "password", rootProject.extra["bintray.key"] as String? )
|
||||
} )
|
||||
|
||||
defaults( delegateClosureOf<groovy.lang.GroovyObject> {
|
||||
invokeMethod( "publications", "maven" )
|
||||
setProperty( "publishArtifacts", true )
|
||||
setProperty( "publishPom", true )
|
||||
} )
|
||||
} )
|
||||
|
||||
resolve( delegateClosureOf<org.jfrog.gradle.plugin.artifactory.dsl.ResolverConfig> {
|
||||
setProperty( "repoKey", "jcenter" )
|
||||
} )
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.Objects;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
@@ -27,14 +28,34 @@ public interface FlatClientProperties
|
||||
/**
|
||||
* Specifies type of a button.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JButton}<br>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong> {@link BUTTON_TYPE_HELP}
|
||||
* <strong>Allowed Values</strong> {@link #BUTTON_TYPE_SQUARE} and {@link #BUTTON_TYPE_HELP}
|
||||
*/
|
||||
String BUTTON_TYPE = "JButton.buttonType";
|
||||
|
||||
/**
|
||||
* Paint the button with square edges.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}
|
||||
*
|
||||
* @see #BUTTON_TYPE
|
||||
*/
|
||||
String BUTTON_TYPE_SQUARE = "square";
|
||||
|
||||
/**
|
||||
* Paint the toggle button in tab style.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JToggleButton}
|
||||
*
|
||||
* @see #BUTTON_TYPE
|
||||
*/
|
||||
String BUTTON_TYPE_TAB = "tab";
|
||||
|
||||
/**
|
||||
* Paint a help button (circle with question mark).
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton}
|
||||
*
|
||||
* @see #BUTTON_TYPE
|
||||
*/
|
||||
@@ -45,7 +66,7 @@ public interface FlatClientProperties
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JCheckBox}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong> {@link SELECTED_STATE_INDETERMINATE}
|
||||
* <strong>Allowed Values</strong> {@link #SELECTED_STATE_INDETERMINATE}
|
||||
*/
|
||||
String SELECTED_STATE = "JButton.selectedState";
|
||||
|
||||
@@ -56,6 +77,38 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String SELECTED_STATE_INDETERMINATE = "indeterminate";
|
||||
|
||||
/**
|
||||
* Specifies minimum width of a component.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JButton}, {@link javax.swing.JToggleButton} and {@link javax.swing.text.JTextComponent}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||
*/
|
||||
String MINIMUM_WIDTH = "JComponent.minimumWidth";
|
||||
|
||||
/**
|
||||
* Specifies minimum height of a component.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||
*/
|
||||
String MINIMUM_HEIGHT = "JComponent.minimumHeight";
|
||||
|
||||
/**
|
||||
* Specifies whether the progress bar has always the larger height even if no string is painted.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JProgressBar}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*/
|
||||
String PROGRESS_BAR_LARGE_HEIGHT = "JProgressBar.largeHeight";
|
||||
|
||||
/**
|
||||
* Specifies whether the progress bar is paint with square edges.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JProgressBar}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*/
|
||||
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
||||
|
||||
/**
|
||||
* Specifies whether the decrease/increase arrow buttons of a scrollbar are shown.
|
||||
* <p>
|
||||
@@ -80,14 +133,80 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TABBED_PANE_HAS_FULL_BORDER = "JTabbedPane.hasFullBorder";
|
||||
|
||||
/**
|
||||
* Specifies the height of a tab.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||
*/
|
||||
String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight";
|
||||
|
||||
/**
|
||||
* Specifies whether all text is selected when the text component gains focus.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong> {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER},
|
||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or
|
||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}
|
||||
*/
|
||||
String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy";
|
||||
|
||||
/**
|
||||
* Never select all text when the text component gains focus.
|
||||
*
|
||||
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
||||
*/
|
||||
String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never";
|
||||
|
||||
/**
|
||||
* Select all text when the text component gains focus for the first time
|
||||
* and selection was not modified (is at end of text).
|
||||
* This is the default.
|
||||
*
|
||||
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
||||
*/
|
||||
String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once";
|
||||
|
||||
/**
|
||||
* Always select all text when the text component gains focus.
|
||||
*
|
||||
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
||||
*/
|
||||
String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always";
|
||||
|
||||
/**
|
||||
* Placeholder text that is only painted if the text field is empty.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} or {@link javax.swing.JComboBox}<br>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses) or {@link javax.swing.JComboBox}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}
|
||||
*/
|
||||
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
|
||||
|
||||
/**
|
||||
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||
*/
|
||||
String TAB_BUTTON_UNDERLINE_HEIGHT = "JToggleButton.tab.underlineHeight";
|
||||
|
||||
/**
|
||||
* Color of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.awt.Color}
|
||||
*/
|
||||
String TAB_BUTTON_UNDERLINE_COLOR = "JToggleButton.tab.underlineColor";
|
||||
|
||||
/**
|
||||
* Background color if selected and toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.awt.Color}
|
||||
*/
|
||||
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
||||
|
||||
/**
|
||||
* Checks whether a client property of a component has the given value.
|
||||
*/
|
||||
@@ -103,4 +222,22 @@ public interface FlatClientProperties
|
||||
Object value = c.getClientProperty( key );
|
||||
return (value instanceof Boolean) ? (boolean) value : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a client property of a component is an integer and returns its value.
|
||||
* If the client property is not set, or not an integer, defaultValue is returned.
|
||||
*/
|
||||
static int clientPropertyInt( JComponent c, String key, int defaultValue ) {
|
||||
Object value = c.getClientProperty( key );
|
||||
return (value instanceof Integer) ? (int) value : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a client property of a component is a color and returns its value.
|
||||
* If the client property is not set, or not a color, defaultValue is returned.
|
||||
*/
|
||||
static Color clientPropertyColor( JComponent c, String key, Color defaultValue ) {
|
||||
Object value = c.getClientProperty( key );
|
||||
return (value instanceof Color) ? (Color) value : defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,19 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.io.InputStream;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIDefaults;
|
||||
|
||||
/**
|
||||
* Addon for FlatLaf UI defaults.
|
||||
*
|
||||
* Allows loading of additional .properties files from addon JARs.
|
||||
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
||||
*
|
||||
* <p>
|
||||
* If you extend this class in a addon JAR, you also have to add a text file named
|
||||
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
||||
* to the addon JAR. The file must contain a single line with the class name.
|
||||
*
|
||||
* <p>
|
||||
* See 'flatlaf-swingx' addon for an example
|
||||
*
|
||||
* @author Karl Tauber
|
||||
@@ -37,6 +39,33 @@ public abstract class FlatDefaultsAddon
|
||||
/**
|
||||
* Finds an addon .properties file for the given LaF class and returns
|
||||
* it as input stream. Or {@code null} if not found.
|
||||
* <p>
|
||||
* This default implementation finds addon .properties file for the given LaF class
|
||||
* in the same package as the subclass.
|
||||
* <p>
|
||||
* Override this method to load addon .properties files from other locations.
|
||||
*/
|
||||
public abstract InputStream getDefaults( Class<?> lafClass );
|
||||
public InputStream getDefaults( Class<?> lafClass ) {
|
||||
Class<?> addonClass = this.getClass();
|
||||
String propertiesName = '/' + addonClass.getPackage().getName().replace( '.', '/' )
|
||||
+ '/' + lafClass.getSimpleName() + ".properties";
|
||||
return addonClass.getResourceAsStream( propertiesName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows modifying UI defaults after loading UI defaults.
|
||||
* The default implementation does nothing.
|
||||
*/
|
||||
public void afterDefaultsLoading( LookAndFeel laf, UIDefaults defaults ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the priority used to sort addon loading.
|
||||
* The order is only important if you want overwrite UI defaults of other addons.
|
||||
* Lower numbers mean higher priority.
|
||||
* Returns 10000 by default.
|
||||
*/
|
||||
public int getPriority() {
|
||||
return 10000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import javax.swing.InputMap;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.UIDefaults.LazyValue;
|
||||
import javax.swing.plaf.InputMapUIResource;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import static javax.swing.text.DefaultEditorKit.*;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class FlatInputMaps
|
||||
{
|
||||
static void initInputMaps( UIDefaults defaults ) {
|
||||
initBasicInputMaps( defaults );
|
||||
initTextComponentInputMaps( defaults );
|
||||
|
||||
if( SystemInfo.IS_MAC )
|
||||
initMacInputMaps( defaults );
|
||||
}
|
||||
|
||||
private static void initBasicInputMaps( UIDefaults defaults ) {
|
||||
defaults.put( "Button.focusInputMap", new UIDefaults.LazyInputMap( new Object[] {
|
||||
"SPACE", "pressed",
|
||||
"released SPACE", "released"
|
||||
} ) );
|
||||
|
||||
modifyInputMap( defaults, "ComboBox.ancestorInputMap",
|
||||
"SPACE", "spacePopup",
|
||||
|
||||
"UP", mac( "selectPrevious2", "selectPrevious" ),
|
||||
"DOWN", mac( "selectNext2", "selectNext" ),
|
||||
"KP_UP", mac( "selectPrevious2", "selectPrevious" ),
|
||||
"KP_DOWN", mac( "selectNext2", "selectNext" ),
|
||||
|
||||
mac( "alt UP", null ), "togglePopup",
|
||||
mac( "alt DOWN", null ), "togglePopup",
|
||||
mac( "alt KP_UP", null ), "togglePopup",
|
||||
mac( "alt KP_DOWN", null ), "togglePopup"
|
||||
);
|
||||
|
||||
if( !SystemInfo.IS_MAC ) {
|
||||
modifyInputMap( defaults, "FileChooser.ancestorInputMap",
|
||||
"F2", "editFileName",
|
||||
"BACK_SPACE", "Go Up"
|
||||
);
|
||||
}
|
||||
|
||||
// join ltr and rtl bindings to fix up/down/etc keys in right-to-left component orientation
|
||||
Object[] bindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings" );
|
||||
Object[] rtlBindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings.RightToLeft" );
|
||||
if( bindings != null && rtlBindings != null ) {
|
||||
Object[] newBindings = new Object[bindings.length + rtlBindings.length];
|
||||
System.arraycopy( bindings, 0, newBindings, 0, bindings.length );
|
||||
System.arraycopy( rtlBindings, 0, newBindings, bindings.length, rtlBindings.length );
|
||||
defaults.put( "PopupMenu.selectedWindowInputMapBindings.RightToLeft", newBindings );
|
||||
}
|
||||
|
||||
modifyInputMap( defaults, "TabbedPane.ancestorInputMap",
|
||||
"ctrl TAB", "navigateNext",
|
||||
"shift ctrl TAB", "navigatePrevious"
|
||||
);
|
||||
|
||||
modifyInputMap( defaults, "Table.ancestorInputMap",
|
||||
// swap to make it consistent with List and Tree
|
||||
"HOME", "selectFirstRow",
|
||||
"END", "selectLastRow",
|
||||
mac( "ctrl HOME", null ), "selectFirstColumn",
|
||||
mac( "ctrl END", null ), "selectLastColumn"
|
||||
);
|
||||
|
||||
if( !SystemInfo.IS_MAC ) {
|
||||
modifyInputMap( defaults, "Tree.focusInputMap",
|
||||
"ADD", "expand",
|
||||
"SUBTRACT", "collapse"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initTextComponentInputMaps( UIDefaults defaults ) {
|
||||
Object[] commonTextComponentBindings = {
|
||||
// move caret one character (without selecting text)
|
||||
"LEFT", backwardAction,
|
||||
"RIGHT", forwardAction,
|
||||
"KP_LEFT", backwardAction,
|
||||
"KP_RIGHT", forwardAction,
|
||||
|
||||
// move caret one character and select text
|
||||
"shift LEFT", selectionBackwardAction,
|
||||
"shift RIGHT", selectionForwardAction,
|
||||
"shift KP_LEFT", selectionBackwardAction,
|
||||
"shift KP_RIGHT", selectionForwardAction,
|
||||
|
||||
// move caret to word (without selecting text)
|
||||
mac( "ctrl LEFT", "alt LEFT" ), previousWordAction,
|
||||
mac( "ctrl RIGHT", "alt RIGHT" ), nextWordAction,
|
||||
mac( "ctrl KP_LEFT", "alt KP_LEFT" ), previousWordAction,
|
||||
mac( "ctrl KP_RIGHT", "alt KP_RIGHT" ), nextWordAction,
|
||||
|
||||
// move caret to word and select text
|
||||
mac( "ctrl shift LEFT", "shift alt LEFT" ), selectionPreviousWordAction,
|
||||
mac( "ctrl shift RIGHT", "shift alt RIGHT" ), selectionNextWordAction,
|
||||
mac( "ctrl shift KP_LEFT", "shift alt KP_LEFT" ), selectionPreviousWordAction,
|
||||
mac( "ctrl shift KP_RIGHT", "shift alt KP_RIGHT" ), selectionNextWordAction,
|
||||
|
||||
// move caret to line begin/end (without selecting text)
|
||||
mac( "HOME", "meta LEFT" ), beginLineAction,
|
||||
mac( "END", "meta RIGHT" ), endLineAction,
|
||||
|
||||
// move caret to line begin/end and select text
|
||||
mac( "shift HOME", "shift meta LEFT" ), selectionBeginLineAction,
|
||||
mac( "shift END", "shift meta RIGHT" ), selectionEndLineAction,
|
||||
|
||||
// select all/none
|
||||
mac( "ctrl A", "meta A" ), selectAllAction,
|
||||
mac( "ctrl BACK_SLASH", "meta BACK_SLASH" ), "unselect", // DefaultEditorKit.unselectAction
|
||||
|
||||
// delete previous/next character
|
||||
"BACK_SPACE", deletePrevCharAction,
|
||||
"shift BACK_SPACE", deletePrevCharAction,
|
||||
"ctrl H", deletePrevCharAction,
|
||||
"DELETE", deleteNextCharAction,
|
||||
|
||||
// delete previous/next word
|
||||
mac( "ctrl BACK_SPACE", "alt BACK_SPACE" ), deletePrevWordAction,
|
||||
mac( "ctrl DELETE", "alt DELETE" ), deleteNextWordAction,
|
||||
|
||||
// clipboard
|
||||
mac( "ctrl X", "meta X" ), cutAction,
|
||||
mac( "ctrl C", "meta C" ), copyAction,
|
||||
mac( "ctrl V", "meta V" ), pasteAction,
|
||||
"CUT", cutAction,
|
||||
"COPY", copyAction,
|
||||
"PASTE", pasteAction,
|
||||
mac( "shift DELETE", null ), cutAction,
|
||||
mac( "control INSERT", null ), copyAction,
|
||||
mac( "shift INSERT", null ), pasteAction,
|
||||
|
||||
// misc
|
||||
"control shift O", "toggle-componentOrientation", // DefaultEditorKit.toggleComponentOrientation
|
||||
};
|
||||
|
||||
Object[] macCommonTextComponentBindings = SystemInfo.IS_MAC ? new Object[] {
|
||||
// move caret one character (without selecting text)
|
||||
"ctrl B", backwardAction,
|
||||
"ctrl F", forwardAction,
|
||||
|
||||
// move caret to document begin/end (without selecting text)
|
||||
"HOME", beginAction,
|
||||
"END", endAction,
|
||||
"meta UP", beginAction,
|
||||
"meta DOWN", endAction,
|
||||
"meta KP_UP", beginAction,
|
||||
"meta KP_DOWN", endAction,
|
||||
"ctrl P", beginAction,
|
||||
"ctrl N", endAction,
|
||||
"ctrl V", endAction,
|
||||
|
||||
// move caret to line begin/end (without selecting text)
|
||||
"meta KP_LEFT", beginLineAction,
|
||||
"meta KP_RIGHT", endLineAction,
|
||||
"ctrl A", beginLineAction,
|
||||
"ctrl E", endLineAction,
|
||||
|
||||
// move caret to document begin/end and select text
|
||||
"shift meta UP", selectionBeginAction,
|
||||
"shift meta DOWN", selectionEndAction,
|
||||
"shift meta KP_UP", selectionBeginAction,
|
||||
"shift meta KP_DOWN", selectionEndAction,
|
||||
"shift HOME", selectionBeginAction,
|
||||
"shift END", selectionEndAction,
|
||||
|
||||
// move caret to line begin/end and select text
|
||||
"shift meta KP_LEFT", selectionBeginLineAction,
|
||||
"shift meta KP_RIGHT", selectionEndLineAction,
|
||||
"shift UP", selectionBeginLineAction,
|
||||
"shift DOWN", selectionEndLineAction,
|
||||
"shift KP_UP", selectionBeginLineAction,
|
||||
"shift KP_DOWN", selectionEndLineAction,
|
||||
|
||||
// delete previous/next word
|
||||
"ctrl W", deletePrevWordAction,
|
||||
"ctrl D", deleteNextCharAction,
|
||||
} : null;
|
||||
|
||||
Object[] singleLineTextComponentBindings = {
|
||||
"ENTER", JTextField.notifyAction,
|
||||
};
|
||||
|
||||
Object[] macSingleLineTextComponentBindings = SystemInfo.IS_MAC ? new Object[] {
|
||||
// move caret to line begin/end (without selecting text)
|
||||
"UP", beginLineAction,
|
||||
"DOWN", endLineAction,
|
||||
"KP_UP", beginLineAction,
|
||||
"KP_DOWN", endLineAction,
|
||||
} : null;
|
||||
|
||||
Object[] formattedTextComponentBindings = {
|
||||
// reset
|
||||
"ESCAPE", "reset-field-edit",
|
||||
|
||||
// increment/decrement
|
||||
"UP", "increment",
|
||||
"DOWN", "decrement",
|
||||
"KP_UP", "increment",
|
||||
"KP_DOWN", "decrement",
|
||||
};
|
||||
|
||||
Object[] passwordTextComponentBindings = {
|
||||
// move caret to line begin/end (without selecting text)
|
||||
mac( "ctrl LEFT", "alt LEFT" ), beginLineAction,
|
||||
mac( "ctrl RIGHT", "alt RIGHT" ), endLineAction,
|
||||
mac( "ctrl KP_LEFT", "alt KP_LEFT" ), beginLineAction,
|
||||
mac( "ctrl KP_RIGHT", "alt KP_RIGHT" ), endLineAction,
|
||||
|
||||
// move caret to line begin/end and select text
|
||||
mac( "ctrl shift LEFT", "shift alt LEFT" ), selectionBeginLineAction,
|
||||
mac( "ctrl shift RIGHT", "shift alt RIGHT" ), selectionEndLineAction,
|
||||
mac( "ctrl shift KP_LEFT", "shift alt KP_LEFT" ), selectionBeginLineAction,
|
||||
mac( "ctrl shift KP_RIGHT", "shift alt KP_RIGHT" ), selectionEndLineAction,
|
||||
|
||||
// delete previous/next word
|
||||
mac( "ctrl BACK_SPACE", "alt BACK_SPACE" ), null,
|
||||
mac( "ctrl DELETE", "alt DELETE" ), null,
|
||||
};
|
||||
|
||||
Object[] multiLineTextComponentBindings = {
|
||||
// move caret one line (without selecting text)
|
||||
"UP", upAction,
|
||||
"DOWN", downAction,
|
||||
"KP_UP", upAction,
|
||||
"KP_DOWN", downAction,
|
||||
|
||||
// move caret one line and select text
|
||||
"shift UP", selectionUpAction,
|
||||
"shift DOWN", selectionDownAction,
|
||||
"shift KP_UP", selectionUpAction,
|
||||
"shift KP_DOWN", selectionDownAction,
|
||||
|
||||
// move caret one page (without selecting text)
|
||||
"PAGE_UP", pageUpAction,
|
||||
"PAGE_DOWN", pageDownAction,
|
||||
|
||||
// move caret one page and select text
|
||||
"shift PAGE_UP", "selection-page-up", // DefaultEditorKit.selectionPageUpAction
|
||||
"shift PAGE_DOWN", "selection-page-down", // DefaultEditorKit.selectionPageDownAction
|
||||
mac( "ctrl shift PAGE_UP", "shift meta PAGE_UP" ), "selection-page-left", // DefaultEditorKit.selectionPageLeftAction
|
||||
mac( "ctrl shift PAGE_DOWN", "shift meta PAGE_DOWN" ), "selection-page-right", // DefaultEditorKit.selectionPageRightAction
|
||||
|
||||
// move caret to document begin/end (without selecting text)
|
||||
mac( "ctrl HOME", "meta UP" ), beginAction,
|
||||
mac( "ctrl END", "meta DOWN" ), endAction,
|
||||
|
||||
// move caret to document begin/end and select text
|
||||
mac( "ctrl shift HOME", "shift meta UP" ), selectionBeginAction,
|
||||
mac( "ctrl shift END", "shift meta DOWN" ), selectionEndAction,
|
||||
|
||||
// misc
|
||||
"ENTER", insertBreakAction,
|
||||
"TAB", insertTabAction,
|
||||
|
||||
// links
|
||||
mac( "ctrl T", "meta T" ), "next-link-action",
|
||||
mac( "ctrl shift T", "shift meta T" ), "previous-link-action",
|
||||
mac( "ctrl SPACE", "meta SPACE" ), "activate-link-action",
|
||||
};
|
||||
|
||||
Object[] macMultiLineTextComponentBindings = SystemInfo.IS_MAC ? new Object[] {
|
||||
// move caret one line (without selecting text)
|
||||
"ctrl N", downAction,
|
||||
"ctrl P", upAction,
|
||||
|
||||
// move caret to beginning/end of paragraph and select text
|
||||
"shift alt UP", selectionBeginParagraphAction,
|
||||
"shift alt DOWN", selectionEndParagraphAction,
|
||||
"shift alt KP_UP", selectionBeginParagraphAction,
|
||||
"shift alt KP_DOWN", selectionEndParagraphAction,
|
||||
|
||||
// move caret one page (without selecting text)
|
||||
"ctrl V", pageDownAction,
|
||||
} : null;
|
||||
|
||||
defaults.put( "TextField.focusInputMap", new LazyInputMapEx(
|
||||
commonTextComponentBindings,
|
||||
macCommonTextComponentBindings,
|
||||
singleLineTextComponentBindings,
|
||||
macSingleLineTextComponentBindings
|
||||
) );
|
||||
defaults.put( "FormattedTextField.focusInputMap", new LazyInputMapEx(
|
||||
commonTextComponentBindings,
|
||||
macCommonTextComponentBindings,
|
||||
singleLineTextComponentBindings,
|
||||
macSingleLineTextComponentBindings,
|
||||
formattedTextComponentBindings
|
||||
) );
|
||||
defaults.put( "PasswordField.focusInputMap", new LazyInputMapEx(
|
||||
commonTextComponentBindings,
|
||||
macCommonTextComponentBindings,
|
||||
singleLineTextComponentBindings,
|
||||
macSingleLineTextComponentBindings,
|
||||
passwordTextComponentBindings
|
||||
) );
|
||||
|
||||
Object multiLineInputMap = new LazyInputMapEx(
|
||||
commonTextComponentBindings,
|
||||
macCommonTextComponentBindings,
|
||||
multiLineTextComponentBindings,
|
||||
macMultiLineTextComponentBindings
|
||||
);
|
||||
defaults.put( "TextArea.focusInputMap", multiLineInputMap );
|
||||
defaults.put( "TextPane.focusInputMap", multiLineInputMap );
|
||||
defaults.put( "EditorPane.focusInputMap", multiLineInputMap );
|
||||
}
|
||||
|
||||
private static void initMacInputMaps( UIDefaults defaults ) {
|
||||
// list
|
||||
modifyInputMap( defaults, "List.focusInputMap",
|
||||
"meta A", "selectAll",
|
||||
"meta C", "copy",
|
||||
"meta V", "paste",
|
||||
"meta X", "cut",
|
||||
|
||||
// let parent scroll pane do the macOS typical scrolling without changing selection
|
||||
"HOME", null,
|
||||
"END", null,
|
||||
"PAGE_UP", null,
|
||||
"PAGE_DOWN", null,
|
||||
|
||||
"ctrl A", null,
|
||||
"ctrl BACK_SLASH", null,
|
||||
"ctrl C", null,
|
||||
"ctrl DOWN", null,
|
||||
"ctrl END", null,
|
||||
"ctrl HOME", null,
|
||||
"ctrl INSERT", null,
|
||||
"ctrl KP_DOWN", null,
|
||||
"ctrl KP_LEFT", null,
|
||||
"ctrl KP_RIGHT", null,
|
||||
"ctrl KP_UP", null,
|
||||
"ctrl LEFT", null,
|
||||
"ctrl PAGE_DOWN", null,
|
||||
"ctrl PAGE_UP", null,
|
||||
"ctrl RIGHT", null,
|
||||
"ctrl SLASH", null,
|
||||
"ctrl SPACE", null,
|
||||
"ctrl UP", null,
|
||||
"ctrl V", null,
|
||||
"ctrl X", null,
|
||||
"SPACE", null,
|
||||
"shift ctrl DOWN", null,
|
||||
"shift ctrl END", null,
|
||||
"shift ctrl HOME", null,
|
||||
"shift ctrl KP_DOWN", null,
|
||||
"shift ctrl KP_LEFT", null,
|
||||
"shift ctrl KP_RIGHT", null,
|
||||
"shift ctrl KP_UP", null,
|
||||
"shift ctrl LEFT", null,
|
||||
"shift ctrl PAGE_DOWN", null,
|
||||
"shift ctrl PAGE_UP", null,
|
||||
"shift ctrl RIGHT", null,
|
||||
"shift ctrl SPACE", null,
|
||||
"shift ctrl UP", null,
|
||||
"shift DELETE", null,
|
||||
"shift INSERT", null,
|
||||
"shift SPACE", null
|
||||
);
|
||||
modifyInputMap( defaults, "List.focusInputMap.RightToLeft",
|
||||
"ctrl KP_LEFT", null,
|
||||
"ctrl KP_RIGHT", null,
|
||||
"ctrl LEFT", null,
|
||||
"ctrl RIGHT", null,
|
||||
"shift ctrl KP_LEFT", null,
|
||||
"shift ctrl KP_RIGHT", null,
|
||||
"shift ctrl LEFT", null,
|
||||
"shift ctrl RIGHT", null
|
||||
);
|
||||
|
||||
// scrollpane
|
||||
modifyInputMap( defaults, "ScrollPane.ancestorInputMap",
|
||||
"END", "scrollEnd",
|
||||
"HOME", "scrollHome",
|
||||
|
||||
"ctrl END", null,
|
||||
"ctrl HOME", null,
|
||||
"ctrl PAGE_DOWN", null,
|
||||
"ctrl PAGE_UP", null
|
||||
);
|
||||
modifyInputMap( defaults, "ScrollPane.ancestorInputMap.RightToLeft",
|
||||
"ctrl PAGE_DOWN", null,
|
||||
"ctrl PAGE_UP", null
|
||||
);
|
||||
|
||||
// tabbedpane
|
||||
modifyInputMap( defaults, "TabbedPane.ancestorInputMap",
|
||||
"ctrl UP", null,
|
||||
"ctrl KP_UP", null
|
||||
);
|
||||
modifyInputMap( defaults, "TabbedPane.focusInputMap",
|
||||
"ctrl DOWN", null,
|
||||
"ctrl KP_DOWN", null
|
||||
);
|
||||
|
||||
// table
|
||||
modifyInputMap( defaults, "Table.ancestorInputMap",
|
||||
"alt TAB", "focusHeader",
|
||||
"shift alt TAB", "focusHeader",
|
||||
"meta A", "selectAll",
|
||||
"meta C", "copy",
|
||||
"meta V", "paste",
|
||||
"meta X", "cut",
|
||||
|
||||
// let parent scroll pane do the macOS typical scrolling without changing selection
|
||||
"HOME", null,
|
||||
"END", null,
|
||||
"PAGE_UP", null,
|
||||
"PAGE_DOWN", null,
|
||||
|
||||
"ctrl A", null,
|
||||
"ctrl BACK_SLASH", null,
|
||||
"ctrl C", null,
|
||||
"ctrl DOWN", null,
|
||||
"ctrl END", null,
|
||||
"ctrl HOME", null,
|
||||
"ctrl INSERT", null,
|
||||
"ctrl KP_DOWN", null,
|
||||
"ctrl KP_LEFT", null,
|
||||
"ctrl KP_RIGHT", null,
|
||||
"ctrl KP_UP", null,
|
||||
"ctrl LEFT", null,
|
||||
"ctrl PAGE_DOWN", null,
|
||||
"ctrl PAGE_UP", null,
|
||||
"ctrl RIGHT", null,
|
||||
"ctrl SLASH", null,
|
||||
"ctrl SPACE", null,
|
||||
"ctrl UP", null,
|
||||
"ctrl V", null,
|
||||
"ctrl X", null,
|
||||
"F2", null,
|
||||
"F8", null,
|
||||
"SPACE", null,
|
||||
"shift ctrl DOWN", null,
|
||||
"shift ctrl END", null,
|
||||
"shift ctrl HOME", null,
|
||||
"shift ctrl KP_DOWN", null,
|
||||
"shift ctrl KP_LEFT", null,
|
||||
"shift ctrl KP_RIGHT", null,
|
||||
"shift ctrl KP_UP", null,
|
||||
"shift ctrl LEFT", null,
|
||||
"shift ctrl PAGE_DOWN", null,
|
||||
"shift ctrl PAGE_UP", null,
|
||||
"shift ctrl RIGHT", null,
|
||||
"shift ctrl SPACE", null,
|
||||
"shift ctrl UP", null,
|
||||
"shift DELETE", null,
|
||||
"shift INSERT", null,
|
||||
"shift SPACE", null
|
||||
);
|
||||
modifyInputMap( defaults, "Table.ancestorInputMap.RightToLeft",
|
||||
"ctrl KP_LEFT", null,
|
||||
"ctrl KP_RIGHT", null,
|
||||
"ctrl LEFT", null,
|
||||
"ctrl RIGHT", null,
|
||||
"shift ctrl KP_LEFT", null,
|
||||
"shift ctrl KP_RIGHT", null,
|
||||
"shift ctrl LEFT", null,
|
||||
"shift ctrl RIGHT", null
|
||||
);
|
||||
|
||||
// tree node expanding/collapsing
|
||||
modifyInputMap( defaults, "Tree.focusInputMap",
|
||||
"LEFT", "selectParent",
|
||||
"RIGHT", "selectChild",
|
||||
"KP_LEFT", "selectParent",
|
||||
"KP_RIGHT", "selectChild",
|
||||
"shift LEFT", "selectParent",
|
||||
"shift RIGHT", "selectChild",
|
||||
"shift KP_LEFT", "selectParent",
|
||||
"shift KP_RIGHT", "selectChild",
|
||||
"alt LEFT", "selectParent",
|
||||
"alt RIGHT", "selectChild",
|
||||
"alt KP_LEFT", "selectParent",
|
||||
"alt KP_RIGHT", "selectChild",
|
||||
|
||||
"meta A", "selectAll",
|
||||
"meta C", "copy",
|
||||
"meta V", "paste",
|
||||
"meta X", "cut",
|
||||
|
||||
// let parent scroll pane do the macOS typical scrolling without changing selection
|
||||
"HOME", null,
|
||||
"END", null,
|
||||
"PAGE_UP", null,
|
||||
"PAGE_DOWN", null,
|
||||
|
||||
"ctrl LEFT", null,
|
||||
"ctrl RIGHT", null,
|
||||
"ctrl KP_LEFT", null,
|
||||
"ctrl KP_RIGHT", null,
|
||||
|
||||
"ctrl A", null,
|
||||
"ctrl BACK_SLASH", null,
|
||||
"ctrl C", null,
|
||||
"ctrl DOWN", null,
|
||||
"ctrl END", null,
|
||||
"ctrl HOME", null,
|
||||
"ctrl INSERT", null,
|
||||
"ctrl KP_DOWN", null,
|
||||
"ctrl KP_UP", null,
|
||||
"ctrl PAGE_DOWN", null,
|
||||
"ctrl PAGE_UP", null,
|
||||
"ctrl SLASH", null,
|
||||
"ctrl SPACE", null,
|
||||
"ctrl UP", null,
|
||||
"ctrl V", null,
|
||||
"ctrl X", null,
|
||||
"F2", null,
|
||||
"SPACE", null,
|
||||
"shift ctrl DOWN", null,
|
||||
"shift ctrl END", null,
|
||||
"shift ctrl HOME", null,
|
||||
"shift ctrl KP_DOWN", null,
|
||||
"shift ctrl KP_UP", null,
|
||||
"shift ctrl PAGE_DOWN", null,
|
||||
"shift ctrl PAGE_UP", null,
|
||||
"shift ctrl SPACE", null,
|
||||
"shift ctrl UP", null,
|
||||
"shift DELETE", null,
|
||||
"shift END", null,
|
||||
"shift HOME", null,
|
||||
"shift INSERT", null,
|
||||
"shift PAGE_DOWN", null,
|
||||
"shift PAGE_UP", null,
|
||||
"shift SPACE", null
|
||||
);
|
||||
defaults.put( "Tree.focusInputMap.RightToLeft", new UIDefaults.LazyInputMap( new Object[] {
|
||||
"LEFT", "selectChild",
|
||||
"RIGHT", "selectParent",
|
||||
"KP_LEFT", "selectChild",
|
||||
"KP_RIGHT", "selectParent",
|
||||
"shift LEFT", "selectChild",
|
||||
"shift RIGHT", "selectParent",
|
||||
"shift KP_LEFT", "selectChild",
|
||||
"shift KP_RIGHT", "selectParent",
|
||||
"alt LEFT", "selectChild",
|
||||
"alt RIGHT", "selectParent",
|
||||
"alt KP_LEFT", "selectChild",
|
||||
"alt KP_RIGHT", "selectParent"
|
||||
} ) );
|
||||
}
|
||||
|
||||
private static void modifyInputMap( UIDefaults defaults, String key, Object... bindings ) {
|
||||
// Note: not using `defaults.get(key)` here because this would resolve the lazy value
|
||||
defaults.put( key, new LazyModifyInputMap( defaults.remove( key ), bindings ) );
|
||||
}
|
||||
|
||||
private static <T> T mac( T value, T macValue ) {
|
||||
return SystemInfo.IS_MAC ? macValue : value;
|
||||
}
|
||||
|
||||
//---- class LazyInputMapEx -----------------------------------------------
|
||||
|
||||
/**
|
||||
* Lazily creates a input map.
|
||||
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
||||
*/
|
||||
private static class LazyInputMapEx
|
||||
implements LazyValue
|
||||
{
|
||||
private final Object[][] bindingsArray;
|
||||
|
||||
LazyInputMapEx( Object[]... bindingsArray ) {
|
||||
this.bindingsArray = bindingsArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createValue( UIDefaults table ) {
|
||||
InputMap inputMap = new InputMapUIResource();
|
||||
for( Object[] bindings : bindingsArray )
|
||||
LookAndFeel.loadKeyBindings( inputMap, bindings );
|
||||
return inputMap;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class LazyModifyInputMap -------------------------------------------
|
||||
|
||||
/**
|
||||
* Takes a (lazy) base input map and lazily applies modifications to it specified in bindings.
|
||||
*/
|
||||
private static class LazyModifyInputMap
|
||||
implements LazyValue
|
||||
{
|
||||
private final Object baseInputMap;
|
||||
private final Object[] bindings;
|
||||
|
||||
LazyModifyInputMap( Object baseInputMap, Object[] bindings ) {
|
||||
this.baseInputMap = baseInputMap;
|
||||
this.bindings = bindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createValue( UIDefaults table ) {
|
||||
// get base input map
|
||||
InputMap inputMap = (baseInputMap instanceof LazyValue)
|
||||
? (InputMap) ((LazyValue)baseInputMap).createValue( table )
|
||||
: (InputMap) baseInputMap;
|
||||
|
||||
// modify input map (replace or remove)
|
||||
for( int i = 0; i < bindings.length; i += 2 ) {
|
||||
KeyStroke keyStroke = KeyStroke.getKeyStroke( (String) bindings[i] );
|
||||
if( bindings[i + 1] != null )
|
||||
inputMap.put( keyStroke, bindings[i + 1] );
|
||||
else
|
||||
inputMap.remove( keyStroke );
|
||||
}
|
||||
|
||||
return inputMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,15 +23,25 @@ import java.awt.EventQueue;
|
||||
import java.awt.Font;
|
||||
import java.awt.KeyEventPostProcessor;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.PopupFactory;
|
||||
@@ -39,10 +49,12 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.UIDefaults.ActiveValue;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
import javax.swing.plaf.FontUIResource;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicLookAndFeel;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
import javax.swing.text.StyleContext;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -55,23 +67,28 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public abstract class FlatLaf
|
||||
extends BasicLookAndFeel
|
||||
{
|
||||
private BasicLookAndFeel base;
|
||||
static final Logger LOG = Logger.getLogger( FlatLaf.class.getName() );
|
||||
private static final String DESKTOPFONTHINTS = "awt.font.desktophints";
|
||||
|
||||
private String desktopPropertyName;
|
||||
private PropertyChangeListener desktopPropertyListener;
|
||||
|
||||
private static boolean aquaLoaded;
|
||||
private static boolean updateUIPending;
|
||||
|
||||
private KeyEventPostProcessor mnemonicListener;
|
||||
private static boolean showMnemonics;
|
||||
private static WeakReference<Window> lastShowMnemonicWindow;
|
||||
|
||||
private Consumer<UIDefaults> postInitialization;
|
||||
|
||||
public static boolean install( LookAndFeel newLookAndFeel ) {
|
||||
try {
|
||||
UIManager.setLookAndFeel( newLookAndFeel );
|
||||
return true;
|
||||
UIManager.setLookAndFeel( newLookAndFeel );
|
||||
return true;
|
||||
} catch( Exception ex ) {
|
||||
System.err.println( "Failed to initialize look and feel " + newLookAndFeel.getClass().getName() );
|
||||
return false;
|
||||
LOG.log( Level.SEVERE, "FlatLaf: Failed to initialize look and feel '" + newLookAndFeel.getClass().getName() + "'.", ex );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,15 +119,11 @@ public abstract class FlatLaf
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
getBase().initialize();
|
||||
if( SystemInfo.IS_MAC )
|
||||
initializeAqua();
|
||||
|
||||
super.initialize();
|
||||
|
||||
// make sure that a plain popup factory is used (otherwise sub-menu rendering
|
||||
// is "jittery" on Mac, where AquaLookAndFeel installs its own popup factory)
|
||||
if( PopupFactory.getSharedInstance().getClass() != PopupFactory.class )
|
||||
PopupFactory.setSharedInstance( new PopupFactory() );
|
||||
|
||||
// add mnemonic listener
|
||||
mnemonicListener = e -> {
|
||||
checkShowMnemonics( e );
|
||||
@@ -131,9 +144,19 @@ public abstract class FlatLaf
|
||||
}
|
||||
if( desktopPropertyName != null ) {
|
||||
desktopPropertyListener = e -> {
|
||||
reSetLookAndFeel();
|
||||
String propertyName = e.getPropertyName();
|
||||
if( desktopPropertyName.equals( propertyName ) )
|
||||
reSetLookAndFeel();
|
||||
else if( DESKTOPFONTHINTS.equals( propertyName ) ) {
|
||||
if( UIManager.getLookAndFeel() instanceof FlatLaf ) {
|
||||
putAATextInfo( UIManager.getLookAndFeelDefaults() );
|
||||
updateUILater();
|
||||
}
|
||||
}
|
||||
};
|
||||
Toolkit.getDefaultToolkit().addPropertyChangeListener( desktopPropertyName, desktopPropertyListener );
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
toolkit.addPropertyChangeListener( desktopPropertyName, desktopPropertyListener );
|
||||
toolkit.addPropertyChangeListener( DESKTOPFONTHINTS, desktopPropertyListener );
|
||||
}
|
||||
|
||||
// Following code should be ideally in initialize(), but needs color from UI defaults.
|
||||
@@ -153,7 +176,9 @@ public abstract class FlatLaf
|
||||
public void uninitialize() {
|
||||
// remove desktop property listener
|
||||
if( desktopPropertyListener != null ) {
|
||||
Toolkit.getDefaultToolkit().removePropertyChangeListener( desktopPropertyName, desktopPropertyListener );
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
toolkit.removePropertyChangeListener( desktopPropertyName, desktopPropertyListener );
|
||||
toolkit.removePropertyChangeListener( DESKTOPFONTHINTS, desktopPropertyListener );
|
||||
desktopPropertyName = null;
|
||||
desktopPropertyListener = null;
|
||||
}
|
||||
@@ -168,73 +193,112 @@ public abstract class FlatLaf
|
||||
new HTMLEditorKit().getStyleSheet().addRule( "a { color: blue; }" );
|
||||
postInitialization = null;
|
||||
|
||||
if( base != null )
|
||||
base.uninitialize();
|
||||
|
||||
super.uninitialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/create base LaF. This is used to grab base UI defaults from different LaFs.
|
||||
* E.g. on Mac from system dependent LaF, otherwise from Metal LaF.
|
||||
* Initialize Aqua LaF on macOS, which is required for using Mac screen menubar.
|
||||
* (at least on Java 8, since 9 it seems to work without it)
|
||||
* <p>
|
||||
* This loads the native library "osxui" and initializes JRSUI.
|
||||
* Because both are not unloaded/uninitialized, Aqua LaF is initialized only once.
|
||||
*/
|
||||
private BasicLookAndFeel getBase() {
|
||||
if( base == null ) {
|
||||
if( SystemInfo.IS_MAC ) {
|
||||
// use Mac Aqua LaF as base
|
||||
try {
|
||||
base = (BasicLookAndFeel) Class.forName( "com.apple.laf.AquaLookAndFeel" ).newInstance();
|
||||
} catch( Exception ex ) {
|
||||
ex.printStackTrace();
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
private void initializeAqua() {
|
||||
if( aquaLoaded )
|
||||
return;
|
||||
|
||||
aquaLoaded = true;
|
||||
|
||||
// create macOS Aqua LaF
|
||||
String aquaLafClassName = "com.apple.laf.AquaLookAndFeel";
|
||||
BasicLookAndFeel aquaLaf;
|
||||
try {
|
||||
if( SystemInfo.IS_JAVA_9_OR_LATER ) {
|
||||
Method m = UIManager.class.getMethod( "createLookAndFeel", String.class );
|
||||
aquaLaf = (BasicLookAndFeel) m.invoke( null, "Mac OS X" );
|
||||
} else
|
||||
base = new MetalLookAndFeel();
|
||||
aquaLaf = (BasicLookAndFeel) Class.forName( aquaLafClassName ).newInstance();
|
||||
} catch( Exception ex ) {
|
||||
LOG.log( Level.SEVERE, "FlatLaf: Failed to initialize Aqua look and feel '" + aquaLafClassName + "'.", ex );
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return base;
|
||||
|
||||
// remember popup factory because aquaLaf.initialize() installs its own
|
||||
// factory, which makes sub-menu rendering "jittery"
|
||||
PopupFactory oldPopupFactory = PopupFactory.getSharedInstance();
|
||||
|
||||
// initialize Aqua LaF
|
||||
aquaLaf.initialize();
|
||||
aquaLaf.uninitialize();
|
||||
|
||||
// restore popup factory
|
||||
PopupFactory.setSharedInstance( oldPopupFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIDefaults getDefaults() {
|
||||
UIDefaults defaults = getBase().getDefaults();
|
||||
UIDefaults defaults = super.getDefaults();
|
||||
|
||||
// add Metal resource bundle, which is required for FlatFileChooserUI
|
||||
defaults.addResourceBundle( "com.sun.swing.internal.plaf.metal.resources.metal" );
|
||||
|
||||
// initialize some defaults (for overriding) that are used in basic UI delegates,
|
||||
// but are not set in MetalLookAndFeel or BasicLookAndFeel
|
||||
Color control = defaults.getColor( "control" );
|
||||
defaults.put( "EditorPane.disabledBackground", control );
|
||||
defaults.put( "EditorPane.inactiveBackground", control );
|
||||
defaults.put( "FormattedTextField.disabledBackground", control );
|
||||
defaults.put( "PasswordField.disabledBackground", control );
|
||||
defaults.put( "TextArea.disabledBackground", control );
|
||||
defaults.put( "TextArea.inactiveBackground", control );
|
||||
defaults.put( "TextField.disabledBackground", control );
|
||||
defaults.put( "TextPane.disabledBackground", control );
|
||||
defaults.put( "TextPane.inactiveBackground", control );
|
||||
|
||||
// initialize some own defaults (for overriding)
|
||||
defaults.put( "Spinner.disabledBackground", control );
|
||||
defaults.put( "Spinner.disabledForeground", control );
|
||||
|
||||
// remember MenuBarUI from Mac Aqua LaF if Mac screen menubar is enabled
|
||||
boolean useScreenMenuBar = SystemInfo.IS_MAC && "true".equals( System.getProperty( "apple.laf.useScreenMenuBar" ) );
|
||||
Object aquaMenuBarUI = useScreenMenuBar ? defaults.get( "MenuBarUI" ) : null;
|
||||
// initialize some defaults (for overriding) that are used in UI delegates,
|
||||
// but are not set in BasicLookAndFeel
|
||||
putDefaults( defaults, defaults.getColor( "control" ),
|
||||
"EditorPane.disabledBackground",
|
||||
"EditorPane.inactiveBackground",
|
||||
"FormattedTextField.disabledBackground",
|
||||
"PasswordField.disabledBackground",
|
||||
"Spinner.disabledBackground",
|
||||
"TextArea.disabledBackground",
|
||||
"TextArea.inactiveBackground",
|
||||
"TextField.disabledBackground",
|
||||
"TextPane.disabledBackground",
|
||||
"TextPane.inactiveBackground" );
|
||||
putDefaults( defaults, defaults.getColor( "textInactiveText" ),
|
||||
"Button.disabledText",
|
||||
"CheckBox.disabledText",
|
||||
"CheckBoxMenuItem.disabledForeground",
|
||||
"Menu.disabledForeground",
|
||||
"MenuItem.disabledForeground",
|
||||
"RadioButton.disabledText",
|
||||
"RadioButtonMenuItem.disabledForeground",
|
||||
"Spinner.disabledForeground",
|
||||
"ToggleButton.disabledText" );
|
||||
putDefaults( defaults, defaults.getColor( "textText" ),
|
||||
"DesktopIcon.foreground" );
|
||||
|
||||
initFonts( defaults );
|
||||
initIconColors( defaults, isDark() );
|
||||
FlatInputMaps.initInputMaps( defaults );
|
||||
|
||||
// get addons and sort them by priority
|
||||
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
|
||||
List<FlatDefaultsAddon> addons = new ArrayList<>();
|
||||
for( FlatDefaultsAddon addon : addonLoader )
|
||||
addons.add( addon );
|
||||
addons.sort( (addon1, addon2) -> addon1.getPriority() - addon2.getPriority() );
|
||||
|
||||
// load defaults from properties
|
||||
List<Class<?>> lafClassesForDefaultsLoading = getLafClassesForDefaultsLoading();
|
||||
if( lafClassesForDefaultsLoading != null )
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, defaults );
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( lafClassesForDefaultsLoading, addons, getAdditionalDefaults(), isDark(), defaults );
|
||||
else
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( getClass(), defaults );
|
||||
UIDefaultsLoader.loadDefaultsFromProperties( getClass(), addons, getAdditionalDefaults(), isDark(), defaults );
|
||||
|
||||
// use Aqua MenuBarUI if Mac screen menubar is enabled
|
||||
if( useScreenMenuBar )
|
||||
defaults.put( "MenuBarUI", aquaMenuBarUI );
|
||||
if( SystemInfo.IS_MAC && Boolean.getBoolean( "apple.laf.useScreenMenuBar" ) )
|
||||
defaults.put( "MenuBarUI", "com.apple.laf.AquaMenuBarUI" );
|
||||
|
||||
// initialize text antialiasing
|
||||
putAATextInfo( defaults );
|
||||
|
||||
// apply additional defaults (e.g. from IntelliJ themes)
|
||||
applyAdditionalDefaults( defaults );
|
||||
|
||||
// allow addons modifying UI defaults
|
||||
for( FlatDefaultsAddon addon : addons )
|
||||
addon.afterDefaultsLoading( this, defaults );
|
||||
|
||||
if( postInitialization != null ) {
|
||||
postInitialization.accept( defaults );
|
||||
@@ -244,7 +308,14 @@ public abstract class FlatLaf
|
||||
return defaults;
|
||||
}
|
||||
|
||||
List<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
void applyAdditionalDefaults( UIDefaults defaults ) {
|
||||
}
|
||||
|
||||
protected List<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Properties getAdditionalDefaults() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -254,17 +325,19 @@ public abstract class FlatLaf
|
||||
if( SystemInfo.IS_WINDOWS ) {
|
||||
Font winFont = (Font) Toolkit.getDefaultToolkit().getDesktopProperty( "win.messagebox.font" );
|
||||
if( winFont != null )
|
||||
uiFont = new FontUIResource( winFont );
|
||||
uiFont = createCompositeFont( winFont.getFamily(), winFont.getStyle(), winFont.getSize() );
|
||||
|
||||
} else if( SystemInfo.IS_MAC ) {
|
||||
Font font = defaults.getFont( "Label.font" );
|
||||
|
||||
String fontName;
|
||||
if( SystemInfo.IS_MAC_OS_10_11_EL_CAPITAN_OR_LATER ) {
|
||||
// use San Francisco Text font
|
||||
font = new FontUIResource( ".SF NS Text", font.getStyle(), font.getSize() );
|
||||
fontName = ".SF NS Text";
|
||||
} else {
|
||||
// default font on older systems (see com.apple.laf.AquaFonts)
|
||||
fontName = "Lucida Grande";
|
||||
}
|
||||
|
||||
uiFont = (font instanceof FontUIResource) ? (FontUIResource) font : new FontUIResource( font );
|
||||
uiFont = createCompositeFont( fontName, Font.PLAIN, 13 );
|
||||
|
||||
} else if( SystemInfo.IS_LINUX ) {
|
||||
Font font = LinuxFontPolicy.getFont();
|
||||
@@ -272,19 +345,34 @@ public abstract class FlatLaf
|
||||
}
|
||||
|
||||
if( uiFont == null )
|
||||
return;
|
||||
uiFont = createCompositeFont( Font.SANS_SERIF, Font.PLAIN, 12 );
|
||||
|
||||
uiFont = UIScale.applyCustomScaleFactor( uiFont );
|
||||
|
||||
// use active value for all fonts to allow changing fonts in all components
|
||||
// (similar as in Nimbus L&F) with:
|
||||
// UIManager.put( "defaultFont", myFont );
|
||||
Object activeFont = new ActiveFont( 1 );
|
||||
|
||||
// override fonts
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && ((String)key).endsWith( ".font" ) )
|
||||
defaults.put( key, uiFont );
|
||||
if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) )
|
||||
defaults.put( key, activeFont );
|
||||
}
|
||||
defaults.put( "MenuItem.acceleratorFont", uiFont );
|
||||
|
||||
// use smaller font for progress bar
|
||||
defaults.put( "ProgressBar.font", UIScale.scaleFont( uiFont, 0.85f ) );
|
||||
defaults.put( "ProgressBar.font", new ActiveFont( 0.85f ) );
|
||||
|
||||
// set default font
|
||||
defaults.put( "defaultFont", uiFont );
|
||||
}
|
||||
|
||||
static FontUIResource createCompositeFont( String family, int style, int size ) {
|
||||
// using StyleContext.getFont() here because it uses
|
||||
// sun.font.FontUtilities.getCompositeFontUIResource()
|
||||
// and creates a composite font that is able to display all Unicode characters
|
||||
Font font = new StyleContext().getFont( family, style, size );
|
||||
return (font instanceof FontUIResource) ? (FontUIResource) font : new FontUIResource( font );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,11 +414,49 @@ public abstract class FlatLaf
|
||||
defaults.put( "Objects.BlackText", new ColorUIResource( 0x231F20 ) );
|
||||
}
|
||||
|
||||
private void putAATextInfo( UIDefaults defaults ) {
|
||||
if( SystemInfo.IS_JAVA_9_OR_LATER ) {
|
||||
Object desktopHints = Toolkit.getDefaultToolkit().getDesktopProperty( DESKTOPFONTHINTS );
|
||||
if( desktopHints instanceof Map ) {
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Map<Object, Object> hints = (Map<Object, Object>) desktopHints;
|
||||
Object aaHint = hints.get( RenderingHints.KEY_TEXT_ANTIALIASING );
|
||||
if( aaHint != null &&
|
||||
aaHint != RenderingHints.VALUE_TEXT_ANTIALIAS_OFF &&
|
||||
aaHint != RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT )
|
||||
{
|
||||
defaults.put( RenderingHints.KEY_TEXT_ANTIALIASING, aaHint );
|
||||
defaults.put( RenderingHints.KEY_TEXT_LCD_CONTRAST,
|
||||
hints.get( RenderingHints.KEY_TEXT_LCD_CONTRAST ) );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Java 8
|
||||
try {
|
||||
Object key = Class.forName( "sun.swing.SwingUtilities2" )
|
||||
.getField( "AA_TEXT_PROPERTY_KEY" )
|
||||
.get( null );
|
||||
Object value = Class.forName( "sun.swing.SwingUtilities2$AATextInfo" )
|
||||
.getMethod( "getAATextInfo", boolean.class )
|
||||
.invoke( null, true );
|
||||
defaults.put( key, value );
|
||||
} catch( Exception ex ) {
|
||||
Logger.getLogger( FlatLaf.class.getName() ).log( Level.SEVERE, null, ex );
|
||||
throw new RuntimeException( ex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putDefaults( UIDefaults defaults, Object value, String... keys ) {
|
||||
for( String key : keys )
|
||||
defaults.put( key, value );
|
||||
}
|
||||
|
||||
private static void reSetLookAndFeel() {
|
||||
EventQueue.invokeLater( () -> {
|
||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||
try {
|
||||
// re-set current LaF
|
||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||
UIManager.setLookAndFeel( lookAndFeel );
|
||||
|
||||
// must fire property change events ourself because old and new LaF are the same
|
||||
@@ -341,13 +467,13 @@ public abstract class FlatLaf
|
||||
// update UI
|
||||
updateUI();
|
||||
} catch( UnsupportedLookAndFeelException ex ) {
|
||||
ex.printStackTrace();
|
||||
LOG.log( Level.SEVERE, "FlatLaf: Failed to reinitialize look and feel '" + lookAndFeel.getClass().getName() + "'.", ex );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update UI of all application windows.
|
||||
* Update UI of all application windows immediately.
|
||||
* Invoke after changing LaF.
|
||||
*/
|
||||
public static void updateUI() {
|
||||
@@ -355,6 +481,25 @@ public abstract class FlatLaf
|
||||
SwingUtilities.updateComponentTreeUI( w );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update UI of all application windows later.
|
||||
*/
|
||||
public static void updateUILater() {
|
||||
synchronized( FlatLaf.class ) {
|
||||
if( updateUIPending )
|
||||
return;
|
||||
|
||||
updateUIPending = true;
|
||||
}
|
||||
|
||||
EventQueue.invokeLater( () -> {
|
||||
updateUI();
|
||||
synchronized( FlatLaf.class ) {
|
||||
updateUIPending = false;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public static boolean isShowMnemonics() {
|
||||
return showMnemonics || !UIManager.getBoolean( "Component.hideMnemonics" );
|
||||
}
|
||||
@@ -364,15 +509,15 @@ public abstract class FlatLaf
|
||||
if( SystemInfo.IS_MAC ) {
|
||||
// Ctrl+Alt keys must be pressed on Mac
|
||||
if( keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_ALT )
|
||||
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED && e.isControlDown() && e.isAltDown() );
|
||||
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED && e.isControlDown() && e.isAltDown(), e.getComponent() );
|
||||
} else {
|
||||
// Alt key must be pressed on Windows and Linux
|
||||
if( keyCode == KeyEvent.VK_ALT )
|
||||
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED );
|
||||
showMnemonics( e.getID() == KeyEvent.KEY_PRESSED, e.getComponent() );
|
||||
}
|
||||
}
|
||||
|
||||
private static void showMnemonics( boolean show ) {
|
||||
private static void showMnemonics( boolean show, Component c ) {
|
||||
if( show == showMnemonics )
|
||||
return;
|
||||
|
||||
@@ -382,22 +527,35 @@ public abstract class FlatLaf
|
||||
if( !UIManager.getBoolean( "Component.hideMnemonics" ) )
|
||||
return;
|
||||
|
||||
// get focus owner
|
||||
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
if( focusOwner == null )
|
||||
return;
|
||||
if( show ) {
|
||||
// get root pane
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||
if( rootPane == null )
|
||||
return;
|
||||
|
||||
// get focused window
|
||||
Window window = SwingUtilities.windowForComponent( focusOwner );
|
||||
if( window == null )
|
||||
return;
|
||||
// get window
|
||||
Window window = SwingUtilities.getWindowAncestor( rootPane );
|
||||
if( window == null )
|
||||
return;
|
||||
|
||||
// repaint components with mnemonics in focused window
|
||||
repaintMnemonics( window );
|
||||
// repaint components with mnemonics in focused window
|
||||
repaintMnemonics( window );
|
||||
|
||||
lastShowMnemonicWindow = new WeakReference<>( window );
|
||||
} else if( lastShowMnemonicWindow != null ) {
|
||||
Window window = lastShowMnemonicWindow.get();
|
||||
if( window != null )
|
||||
repaintMnemonics( window );
|
||||
|
||||
lastShowMnemonicWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void repaintMnemonics( Container container ) {
|
||||
for( Component c : container.getComponents() ) {
|
||||
if( !c.isVisible() )
|
||||
continue;
|
||||
|
||||
if( hasMnemonic( c ) )
|
||||
c.repaint();
|
||||
|
||||
@@ -424,4 +582,42 @@ public abstract class FlatLaf
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//---- class ActiveFont ---------------------------------------------------
|
||||
|
||||
private static class ActiveFont
|
||||
implements ActiveValue
|
||||
{
|
||||
private final float scaleFactor;
|
||||
|
||||
// cache (scaled) font
|
||||
private Font font;
|
||||
private Font lastDefaultFont;
|
||||
|
||||
ActiveFont( float scaleFactor ) {
|
||||
this.scaleFactor = scaleFactor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createValue( UIDefaults table ) {
|
||||
Font defaultFont = UIManager.getFont( "defaultFont" );
|
||||
|
||||
if( lastDefaultFont != defaultFont ) {
|
||||
lastDefaultFont = defaultFont;
|
||||
|
||||
if( scaleFactor != 1 ) {
|
||||
// scale font
|
||||
int newFontSize = Math.round( defaultFont.getSize() * scaleFactor );
|
||||
font = new FontUIResource( defaultFont.deriveFont( (float) newFontSize ) );
|
||||
} else {
|
||||
// make sure that font is a UIResource for LaF switching
|
||||
font = (defaultFont instanceof UIResource)
|
||||
? defaultFont
|
||||
: new FontUIResource( defaultFont );
|
||||
}
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
import com.formdev.flatlaf.json.Json;
|
||||
@@ -72,8 +73,7 @@ public class IntelliJTheme
|
||||
try {
|
||||
return FlatLaf.install( createLaf( in ) );
|
||||
} catch( Exception ex ) {
|
||||
System.err.println( "Failed to load IntelliJ theme" );
|
||||
ex.printStackTrace();
|
||||
FlatLaf.LOG.log( Level.SEVERE, "FlatLaf: Failed to load IntelliJ theme", ex );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,8 @@ public class IntelliJTheme
|
||||
defaults.put( "Button.paintShadow", true );
|
||||
defaults.put( "Button.shadowWidth", dark ? 2 : 1 );
|
||||
|
||||
Map<Object, Object> themeSpecificDefaults = removeThemeSpecificDefaults( defaults );
|
||||
|
||||
loadNamedColors( defaults );
|
||||
|
||||
// convert Json "ui" structure to UI defaults
|
||||
@@ -183,6 +185,37 @@ public class IntelliJTheme
|
||||
if( !uiKeys.contains( "Spinner.background" ) )
|
||||
defaults.put( "Spinner.background", textFieldBackground );
|
||||
}
|
||||
|
||||
// fix ToggleButton
|
||||
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
|
||||
defaults.put( "ToggleButton.startBackground", defaults.get( "Button.startBackground" ) );
|
||||
if( !uiKeys.contains( "ToggleButton.endBackground" ) && !uiKeys.contains( "*.endBackground" ) )
|
||||
defaults.put( "ToggleButton.endBackground", defaults.get( "Button.endBackground" ) );
|
||||
if( !uiKeys.contains( "ToggleButton.foreground" ) && uiKeys.contains( "Button.foreground" ) )
|
||||
defaults.put( "ToggleButton.foreground", defaults.get( "Button.foreground" ) );
|
||||
|
||||
// apply theme specific UI defaults at the end to allow overwriting
|
||||
defaults.putAll( themeSpecificDefaults );
|
||||
}
|
||||
|
||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||
// search for theme specific UI defaults keys
|
||||
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && ((String)key).startsWith( "[" ) )
|
||||
themeSpecificKeys.add( (String) key );
|
||||
}
|
||||
|
||||
// remove theme specific UI defaults and remember only those for current theme
|
||||
Map<Object, Object> themeSpecificDefaults = new HashMap<>();
|
||||
String currentThemePrefix = '[' + name.replace( ' ', '_' ) + ']';
|
||||
for( String key : themeSpecificKeys ) {
|
||||
Object value = defaults.remove( key );
|
||||
if( key.startsWith( currentThemePrefix ) )
|
||||
themeSpecificDefaults.put( key.substring( currentThemePrefix.length() ), value );
|
||||
}
|
||||
|
||||
return themeSpecificDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,7 +278,7 @@ public class IntelliJTheme
|
||||
try {
|
||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr );
|
||||
} catch( RuntimeException ex ) {
|
||||
UIDefaultsLoader.logParseError( key, valueStr, ex );
|
||||
UIDefaultsLoader.logParseError( Level.CONFIG, key, valueStr, ex );
|
||||
return; // ignore invalid value
|
||||
}
|
||||
}
|
||||
@@ -270,7 +303,7 @@ public class IntelliJTheme
|
||||
// (e.g. set ComboBox.buttonEditableBackground to *.background
|
||||
// because it is mapped from ComboBox.ArrowButton.background)
|
||||
String km = uiKeyInverseMapping.getOrDefault( k, (String) k );
|
||||
if( km.endsWith( tail ) && !noWildcardReplace.contains( k ) && !((String)k).startsWith( "CheckBox.icon." ) )
|
||||
if( km.endsWith( tail ) && !((String)k).startsWith( "CheckBox.icon." ) )
|
||||
defaults.put( k, uiValue );
|
||||
}
|
||||
}
|
||||
@@ -355,33 +388,43 @@ public class IntelliJTheme
|
||||
value = "#ffffff";
|
||||
}
|
||||
|
||||
String key2 = checkboxDuplicateColors.get( key );
|
||||
|
||||
if( dark )
|
||||
key = StringUtils.removeTrailing( key, ".Dark" );
|
||||
|
||||
String newKey = checkboxKeyMapping.get( key );
|
||||
if( newKey != null ) {
|
||||
ColorUIResource color = toColor( (String) value );
|
||||
if( color != null )
|
||||
if( color != null ) {
|
||||
defaults.put( newKey, color );
|
||||
|
||||
if( key2 != null ) {
|
||||
// When IDEA replaces colors in SVGs it uses color values and not the keys
|
||||
// from com.intellij.ide.ui.UITheme.colorPalette, but there are some keys that
|
||||
// have same color value:
|
||||
// - Checkbox.Background.Default.Dark has same color as Checkbox.Background.Selected.Dark
|
||||
// - Checkbox.Border.Default.Dark has same color as Checkbox.Border.Selected.Dark
|
||||
// - Checkbox.Focus.Thin.Default.Dark has same color as Checkbox.Focus.Thin.Selected.Dark
|
||||
//
|
||||
// So if only e.g. Checkbox.Background.Default.Dark is specified in .theme.json,
|
||||
// then this color is also used for Checkbox.Background.Selected.Dark.
|
||||
//
|
||||
// If Checkbox.Background.Default.Dark and Checkbox.Background.Selected.Dark
|
||||
// are specified in .theme.json, then the later specified is used for both.
|
||||
if( dark )
|
||||
key2 = StringUtils.removeTrailing( key2, ".Dark" );
|
||||
|
||||
String newKey2 = checkboxKeyMapping.get( key2 );
|
||||
if( newKey2 != null )
|
||||
defaults.put( newKey2, color );
|
||||
}
|
||||
}
|
||||
|
||||
checkboxModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// When IDEA replaces colors in SVGs it uses color values and not the keys
|
||||
// from com.intellij.ide.ui.UITheme.colorPalette, but there are some keys that
|
||||
// have same color value:
|
||||
// - Checkbox.Background.Default.Dark has same color as Checkbox.Background.Selected.Dark
|
||||
// - Checkbox.Border.Default.Dark has same color as Checkbox.Border.Selected.Dark
|
||||
// - Checkbox.Focus.Thin.Default.Dark has same color as Checkbox.Focus.Thin.Selected.Dark
|
||||
//
|
||||
// So if only e.g. Checkbox.Background.Default.Dark is specified in .theme.json,
|
||||
// then this color is also used for Checkbox.Background.Selected.Dark.
|
||||
// Occurs e.g. in "Dark purple" theme.
|
||||
fixCheckBoxColor( defaults, colorPalette, "Checkbox.Background.Default.Dark", "Checkbox.Background.Selected.Dark" );
|
||||
fixCheckBoxColor( defaults, colorPalette, "Checkbox.Border.Default.Dark", "Checkbox.Border.Selected.Dark" );
|
||||
fixCheckBoxColor( defaults, colorPalette, "Checkbox.Focus.Thin.Default.Dark", "Checkbox.Focus.Thin.Selected.Dark" );
|
||||
|
||||
// remove hover and pressed colors
|
||||
if( checkboxModified ) {
|
||||
defaults.remove( "CheckBox.icon.hoverBorderColor" );
|
||||
@@ -391,24 +434,17 @@ public class IntelliJTheme
|
||||
defaults.remove( "CheckBox.icon.selectedHoverBackground" );
|
||||
defaults.remove( "CheckBox.icon.selectedPressedBackground" );
|
||||
}
|
||||
}
|
||||
|
||||
private void fixCheckBoxColor( UIDefaults defaults, Map<String, Object> colorPalette, String key1, String key2 ) {
|
||||
if( colorPalette.containsKey( key1 ) == colorPalette.containsKey( key2 ) )
|
||||
return;
|
||||
|
||||
String newKey1 = checkboxKeyMapping.get( StringUtils.removeTrailing( key1, ".Dark" ) );
|
||||
String newKey2 = checkboxKeyMapping.get( StringUtils.removeTrailing( key2, ".Dark" ) );
|
||||
if( colorPalette.containsKey( key1 ) )
|
||||
defaults.put( newKey2, defaults.get( newKey1 ) );
|
||||
else
|
||||
defaults.put( newKey1, defaults.get( newKey2 ) );
|
||||
// copy values
|
||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() )
|
||||
defaults.put( e.getKey(), defaults.get( e.getValue() ) );
|
||||
}
|
||||
|
||||
private static Map<String, String> uiKeyMapping = new HashMap<>();
|
||||
private static Map<String, String> uiKeyCopying = new HashMap<>();
|
||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static Set<String> noWildcardReplace = new HashSet<>();
|
||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
|
||||
static {
|
||||
// ComboBox
|
||||
@@ -419,6 +455,9 @@ public class IntelliJTheme
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.iconColor", "ComboBox.buttonArrowColor" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.nonEditableBackground", "ComboBox.buttonBackground" );
|
||||
|
||||
// Link
|
||||
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
|
||||
|
||||
// ProgressBar
|
||||
uiKeyMapping.put( "ProgressBar.background", "" ); // ignore
|
||||
uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore
|
||||
@@ -429,12 +468,21 @@ public class IntelliJTheme
|
||||
uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" );
|
||||
uiKeyMapping.put( "ScrollBar.thumbColor", "ScrollBar.thumb" );
|
||||
|
||||
// Separator
|
||||
uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" );
|
||||
|
||||
// Slider
|
||||
uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite)
|
||||
|
||||
for( Map.Entry<String, String> e : uiKeyMapping.entrySet() )
|
||||
uiKeyInverseMapping.put( e.getValue(), e.getKey() );
|
||||
|
||||
uiKeyCopying.put( "ToggleButton.tab.underlineColor", "TabbedPane.underlineColor" );
|
||||
uiKeyCopying.put( "ToggleButton.tab.disabledUnderlineColor", "TabbedPane.disabledUnderlineColor" );
|
||||
uiKeyCopying.put( "ToggleButton.tab.selectedBackground", "TabbedPane.selectedBackground" );
|
||||
uiKeyCopying.put( "ToggleButton.tab.hoverBackground", "TabbedPane.hoverColor" );
|
||||
uiKeyCopying.put( "ToggleButton.tab.focusBackground", "TabbedPane.focusColor" );
|
||||
|
||||
checkboxKeyMapping.put( "Checkbox.Background.Default", "CheckBox.icon.background" );
|
||||
checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" );
|
||||
checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" );
|
||||
@@ -447,15 +495,13 @@ public class IntelliJTheme
|
||||
checkboxKeyMapping.put( "Checkbox.Foreground.Selected", "CheckBox.icon.checkmarkColor" );
|
||||
checkboxKeyMapping.put( "Checkbox.Focus.Thin.Selected", "CheckBox.icon.selectedFocusedBorderColor" );
|
||||
|
||||
// because FlatLaf uses Button.background and Button.borderColor,
|
||||
// but IDEA uses Button.startBackground and Button.startBorderColor,
|
||||
// our default button background and border colors may be replaced by
|
||||
// wildcard *.background and *.borderColor colors
|
||||
noWildcardReplace.add( "Button.background" );
|
||||
noWildcardReplace.add( "Button.borderColor" );
|
||||
noWildcardReplace.add( "Button.default.background" );
|
||||
noWildcardReplace.add( "Button.default.borderColor" );
|
||||
noWildcardReplace.add( "ToggleButton.background" );
|
||||
checkboxDuplicateColors.put( "Checkbox.Background.Default.Dark", "Checkbox.Background.Selected.Dark" );
|
||||
checkboxDuplicateColors.put( "Checkbox.Border.Default.Dark", "Checkbox.Border.Selected.Dark" );
|
||||
checkboxDuplicateColors.put( "Checkbox.Focus.Thin.Default.Dark", "Checkbox.Focus.Thin.Selected.Dark" );
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Map.Entry<String, String>[] entries = checkboxDuplicateColors.entrySet().toArray( new Map.Entry[checkboxDuplicateColors.size()] );
|
||||
for( Map.Entry<String, String> e : entries )
|
||||
checkboxDuplicateColors.put( e.getValue(), e.getKey() );
|
||||
}
|
||||
|
||||
//---- class ThemeLaf -----------------------------------------------------
|
||||
@@ -489,14 +535,12 @@ public class IntelliJTheme
|
||||
}
|
||||
|
||||
@Override
|
||||
public UIDefaults getDefaults() {
|
||||
UIDefaults defaults = super.getDefaults();
|
||||
void applyAdditionalDefaults( UIDefaults defaults ) {
|
||||
theme.applyProperties( defaults );
|
||||
return defaults;
|
||||
}
|
||||
|
||||
@Override
|
||||
ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
lafClasses.add( FlatLaf.class );
|
||||
lafClasses.add( theme.dark ? FlatDarkLaf.class : FlatLightLaf.class );
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Toolkit;
|
||||
import java.io.BufferedReader;
|
||||
@@ -27,9 +28,10 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.swing.text.StyleContext;
|
||||
import java.util.logging.Level;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
@@ -87,9 +89,7 @@ class LinuxFontPolicy
|
||||
}
|
||||
|
||||
private static Font createFont( String family, int style, int size, double dsize ) {
|
||||
// using StyleContext.getFont() here because it uses
|
||||
// sun.font.FontUtilities.getCompositeFontUIResource()
|
||||
Font font = new StyleContext().getFont( family, style, size );
|
||||
Font font = FlatLaf.createCompositeFont( family, style, size );
|
||||
|
||||
// set font size in floating points
|
||||
font = font.deriveFont( style, (float) dsize );
|
||||
@@ -98,6 +98,10 @@ class LinuxFontPolicy
|
||||
}
|
||||
|
||||
private static double getGnomeFontScale() {
|
||||
// do not scale font here if JRE scales
|
||||
if( isSystemScaling() )
|
||||
return 96. / 72.;
|
||||
|
||||
// see class com.sun.java.swing.plaf.gtk.PangoFonts background information
|
||||
|
||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
||||
@@ -161,13 +165,13 @@ class LinuxFontPolicy
|
||||
if( "1".equals( strs.get( 5 ) ) )
|
||||
style |= Font.ITALIC;
|
||||
} catch( RuntimeException ex ) {
|
||||
ex.printStackTrace();
|
||||
FlatLaf.LOG.log( Level.CONFIG, "FlatLaf: Failed to parse 'font=" + generalFont + "'.", ex );
|
||||
}
|
||||
}
|
||||
|
||||
// font dpi
|
||||
int dpi = 96;
|
||||
if( forceFontDPI != null ) {
|
||||
if( forceFontDPI != null && !isSystemScaling() ) {
|
||||
try {
|
||||
dpi = Integer.parseInt( forceFontDPI );
|
||||
if( dpi <= 0 )
|
||||
@@ -175,7 +179,7 @@ class LinuxFontPolicy
|
||||
if( dpi < 50 )
|
||||
dpi = 50;
|
||||
} catch( NumberFormatException ex ) {
|
||||
ex.printStackTrace();
|
||||
FlatLaf.LOG.log( Level.CONFIG, "FlatLaf: Failed to parse 'forceFontDPI=" + forceFontDPI + "'.", ex );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +218,7 @@ class LinuxFontPolicy
|
||||
while( (line = reader.readLine()) != null )
|
||||
lines.add( line );
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace();
|
||||
FlatLaf.LOG.log( Level.CONFIG, "FlatLaf: Failed to read '" + filename + "'.", ex );
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
@@ -246,4 +250,15 @@ class LinuxFontPolicy
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the JRE scales, which is the case if:
|
||||
* - environment variable GDK_SCALE is set and running on Java 9 or later
|
||||
* - running on JetBrains Runtime 11 or later and scaling is enabled in system Settings
|
||||
*/
|
||||
private static boolean isSystemScaling() {
|
||||
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice().getDefaultConfiguration();
|
||||
return UIScale.getSystemScaleFactor( gc ) > 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,10 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UIDefaults.ActiveValue;
|
||||
import javax.swing.UIDefaults.LazyValue;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
@@ -40,6 +41,7 @@ import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.HSLColor;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -60,11 +62,15 @@ class UIDefaultsLoader
|
||||
private static final String TYPE_PREFIX = "{";
|
||||
private static final String TYPE_PREFIX_END = "}";
|
||||
private static final String VARIABLE_PREFIX = "@";
|
||||
@Deprecated
|
||||
private static final String REF_PREFIX = VARIABLE_PREFIX + "@";
|
||||
private static final String PROPERTY_PREFIX = "$";
|
||||
private static final String OPTIONAL_PREFIX = "?";
|
||||
private static final String GLOBAL_PREFIX = "*.";
|
||||
|
||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, UIDefaults defaults ) {
|
||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
{
|
||||
// determine classes in class hierarchy in reverse order
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
for( Class<?> lafClass = lookAndFeelClass;
|
||||
@@ -74,47 +80,69 @@ class UIDefaultsLoader
|
||||
lafClasses.add( 0, lafClass );
|
||||
}
|
||||
|
||||
loadDefaultsFromProperties( lafClasses, defaults );
|
||||
loadDefaultsFromProperties( lafClasses, addons, additionalDefaults, dark, defaults );
|
||||
}
|
||||
|
||||
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, UIDefaults defaults ) {
|
||||
static void loadDefaultsFromProperties( List<Class<?>> lafClasses, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
{
|
||||
try {
|
||||
List<ClassLoader> addonClassLoaders = new ArrayList<>();
|
||||
|
||||
// load properties files
|
||||
// load core properties files
|
||||
Properties properties = new Properties();
|
||||
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
|
||||
for( Class<?> lafClass : lafClasses ) {
|
||||
// load core properties
|
||||
String propertiesName = "/" + lafClass.getName().replace( '.', '/' ) + ".properties";
|
||||
String propertiesName = '/' + lafClass.getName().replace( '.', '/' ) + ".properties";
|
||||
try( InputStream in = lafClass.getResourceAsStream( propertiesName ) ) {
|
||||
if( in != null )
|
||||
properties.load( in );
|
||||
}
|
||||
}
|
||||
|
||||
// load properties from addons
|
||||
for( FlatDefaultsAddon addon : addonLoader ) {
|
||||
// load properties from addons
|
||||
for( FlatDefaultsAddon addon : addons ) {
|
||||
for( Class<?> lafClass : lafClasses ) {
|
||||
try( InputStream in = addon.getDefaults( lafClass ) ) {
|
||||
if( in != null )
|
||||
properties.load( in );
|
||||
}
|
||||
|
||||
ClassLoader addonClassLoader = addon.getClass().getClassLoader();
|
||||
if( !addonClassLoaders.contains( addonClassLoader ) )
|
||||
addonClassLoaders.add( addonClassLoader );
|
||||
}
|
||||
}
|
||||
|
||||
// collect addon class loaders
|
||||
List<ClassLoader> addonClassLoaders = new ArrayList<>();
|
||||
for( FlatDefaultsAddon addon : addons ) {
|
||||
ClassLoader addonClassLoader = addon.getClass().getClassLoader();
|
||||
if( !addonClassLoaders.contains( addonClassLoader ) )
|
||||
addonClassLoaders.add( addonClassLoader );
|
||||
}
|
||||
|
||||
// add additional defaults
|
||||
if( additionalDefaults != null )
|
||||
properties.putAll( additionalDefaults );
|
||||
|
||||
// collect all platform specific keys (but do not modify properties)
|
||||
ArrayList<String> platformSpecificKeys = new ArrayList<>();
|
||||
for( Object key : properties.keySet() ) {
|
||||
if( ((String)key).startsWith( "[" ) )
|
||||
platformSpecificKeys.add( (String) key );
|
||||
for( Object okey : properties.keySet() ) {
|
||||
String key = (String) okey;
|
||||
if( key.startsWith( "[" ) &&
|
||||
(key.startsWith( "[win]" ) ||
|
||||
key.startsWith( "[mac]" ) ||
|
||||
key.startsWith( "[linux]" ) ||
|
||||
key.startsWith( "[light]" ) ||
|
||||
key.startsWith( "[dark]" )) )
|
||||
platformSpecificKeys.add( key );
|
||||
}
|
||||
|
||||
// remove platform specific properties and re-add only properties
|
||||
// for current platform, but with platform prefix removed
|
||||
if( !platformSpecificKeys.isEmpty() ) {
|
||||
// handle light/dark specific properties
|
||||
String lightOrDarkPrefix = dark ? "[dark]" : "[light]";
|
||||
for( String key : platformSpecificKeys ) {
|
||||
if( key.startsWith( lightOrDarkPrefix ) )
|
||||
properties.put( key.substring( lightOrDarkPrefix.length() ), properties.remove( key ) );
|
||||
}
|
||||
|
||||
// handle platform specific properties
|
||||
String platformPrefix =
|
||||
SystemInfo.IS_WINDOWS ? "[win]" :
|
||||
SystemInfo.IS_MAC ? "[mac]" :
|
||||
@@ -141,7 +169,7 @@ class UIDefaultsLoader
|
||||
try {
|
||||
globals.put( key.substring( GLOBAL_PREFIX.length() ), parseValue( key, value, resolver, addonClassLoaders ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
logParseError( key, value, ex );
|
||||
logParseError( Level.SEVERE, key, value, ex );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,25 +194,29 @@ class UIDefaultsLoader
|
||||
try {
|
||||
defaults.put( key, parseValue( key, value, resolver, addonClassLoaders ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
logParseError( key, value, ex );
|
||||
logParseError( Level.SEVERE, key, value, ex );
|
||||
}
|
||||
}
|
||||
} catch( IOException ex ) {
|
||||
ex.printStackTrace();
|
||||
FlatLaf.LOG.log( Level.SEVERE, "FlatLaf: Failed to load properties files.", ex );
|
||||
}
|
||||
}
|
||||
|
||||
static void logParseError( String key, String value, RuntimeException ex ) {
|
||||
System.err.println( "Failed to parse: '" + key + '=' + value + '\'' );
|
||||
System.err.println( " " + ex.getMessage() );
|
||||
static void logParseError( Level level, String key, String value, RuntimeException ex ) {
|
||||
FlatLaf.LOG.log( level, "FlatLaf: Failed to parse: '" + key + '=' + value + '\'', ex );
|
||||
}
|
||||
|
||||
private static String resolveValue( Properties properties, String value ) {
|
||||
if( !value.startsWith( VARIABLE_PREFIX ) )
|
||||
if( value.startsWith( PROPERTY_PREFIX ) )
|
||||
value = value.substring( PROPERTY_PREFIX.length() );
|
||||
else if( !value.startsWith( VARIABLE_PREFIX ) )
|
||||
return value;
|
||||
|
||||
if( value.startsWith( REF_PREFIX ) )
|
||||
// for compatibility
|
||||
if( value.startsWith( REF_PREFIX ) ) {
|
||||
FlatLaf.LOG.log( Level.WARNING, "FlatLaf: Usage of '@@' in .properties files is deprecated. Use '$' instead." );
|
||||
value = value.substring( REF_PREFIX.length() );
|
||||
}
|
||||
|
||||
boolean optional = false;
|
||||
if( value.startsWith( OPTIONAL_PREFIX ) ) {
|
||||
@@ -197,13 +229,14 @@ class UIDefaultsLoader
|
||||
if( optional )
|
||||
return "null";
|
||||
|
||||
throw new IllegalArgumentException( "variable or reference '" + value + "' not found" );
|
||||
throw new IllegalArgumentException( "variable or property '" + value + "' not found" );
|
||||
}
|
||||
|
||||
return resolveValue( properties, newValue );
|
||||
}
|
||||
|
||||
private enum ValueType { UNKNOWN, STRING, INTEGER, BORDER, ICON, INSETS, SIZE, COLOR, SCALEDINTEGER, INSTANCE, CLASS }
|
||||
private enum ValueType { UNKNOWN, STRING, CHARACTER, INTEGER, FLOAT, BORDER, ICON, INSETS, DIMENSION, COLOR,
|
||||
SCALEDINTEGER, SCALEDFLOAT, SCALEDINSETS, SCALEDDIMENSION, INSTANCE, CLASS }
|
||||
|
||||
static Object parseValue( String key, String value ) {
|
||||
return parseValue( key, value, v -> v, Collections.emptyList() );
|
||||
@@ -219,12 +252,24 @@ class UIDefaultsLoader
|
||||
case "true": return true;
|
||||
}
|
||||
|
||||
// check for function "lazy"
|
||||
// Syntax: lazy(uiKey)
|
||||
if( value.startsWith( "lazy(" ) && value.endsWith( ")" ) ) {
|
||||
String uiKey = value.substring( 5, value.length() - 1 ).trim();
|
||||
return (LazyValue) t -> {
|
||||
return lazyUIManagerGet( uiKey );
|
||||
};
|
||||
}
|
||||
|
||||
ValueType valueType = ValueType.UNKNOWN;
|
||||
|
||||
// check whether value type is specified in the value
|
||||
if( value.startsWith( "#" ) )
|
||||
valueType = ValueType.COLOR;
|
||||
else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
else if( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
|
||||
valueType = ValueType.STRING;
|
||||
value = value.substring( 1, value.length() - 1 );
|
||||
} else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
int end = value.indexOf( TYPE_PREFIX_END );
|
||||
if( end != -1 ) {
|
||||
try {
|
||||
@@ -251,9 +296,11 @@ class UIDefaultsLoader
|
||||
key.endsWith( "Margins" ) || key.endsWith( "Insets" ) )
|
||||
valueType = ValueType.INSETS;
|
||||
else if( key.endsWith( "Size" ) )
|
||||
valueType = ValueType.SIZE;
|
||||
valueType = ValueType.DIMENSION;
|
||||
else if( key.endsWith( "Width" ) || key.endsWith( "Height" ) )
|
||||
valueType = ValueType.INTEGER;
|
||||
else if( key.endsWith( "Char" ) )
|
||||
valueType = ValueType.CHARACTER;
|
||||
else if( key.endsWith( "UI" ) )
|
||||
valueType = ValueType.STRING;
|
||||
}
|
||||
@@ -261,19 +308,24 @@ class UIDefaultsLoader
|
||||
// parse value
|
||||
switch( valueType ) {
|
||||
case STRING: return value;
|
||||
case CHARACTER: return parseCharacter( value );
|
||||
case INTEGER: return parseInteger( value, true );
|
||||
case FLOAT: return parseFloat( value, true );
|
||||
case BORDER: return parseBorder( value, resolver, addonClassLoaders );
|
||||
case ICON: return parseInstance( value, addonClassLoaders );
|
||||
case INSETS: return parseInsets( value );
|
||||
case SIZE: return parseSize( value );
|
||||
case COLOR: return parseColorOrFunction( value, true );
|
||||
case DIMENSION: return parseDimension( value );
|
||||
case COLOR: return parseColorOrFunction( value, resolver, true );
|
||||
case SCALEDINTEGER: return parseScaledInteger( value );
|
||||
case SCALEDFLOAT: return parseScaledFloat( value );
|
||||
case SCALEDINSETS: return parseScaledInsets( value );
|
||||
case SCALEDDIMENSION:return parseScaledDimension( value );
|
||||
case INSTANCE: return parseInstance( value, addonClassLoaders );
|
||||
case CLASS: return parseClass( value, addonClassLoaders );
|
||||
case UNKNOWN:
|
||||
default:
|
||||
// colors
|
||||
ColorUIResource color = parseColorOrFunction( value, false );
|
||||
Object color = parseColorOrFunction( value, resolver, false );
|
||||
if( color != null )
|
||||
return color;
|
||||
|
||||
@@ -282,6 +334,11 @@ class UIDefaultsLoader
|
||||
if( integer != null )
|
||||
return integer;
|
||||
|
||||
// float
|
||||
Float f = parseFloat( value, false );
|
||||
if( f != null )
|
||||
return f;
|
||||
|
||||
// string
|
||||
return value;
|
||||
}
|
||||
@@ -289,16 +346,17 @@ class UIDefaultsLoader
|
||||
|
||||
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
||||
if( value.indexOf( ',' ) >= 0 ) {
|
||||
// top,left,bottom,right[,lineColor]
|
||||
List<String> parts = StringUtils.split( value, ',' );
|
||||
// top,left,bottom,right[,lineColor[,lineThickness]]
|
||||
List<String> parts = split( value, ',' );
|
||||
Insets insets = parseInsets( value );
|
||||
ColorUIResource lineColor = (parts.size() == 5)
|
||||
? parseColorOrFunction( resolver.apply( parts.get( 4 ) ), true )
|
||||
ColorUIResource lineColor = (parts.size() >= 5)
|
||||
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true )
|
||||
: null;
|
||||
float lineThickness = (parts.size() >= 6) ? parseFloat( parts.get( 5 ), true ) : 1f;
|
||||
|
||||
return (LazyValue) t -> {
|
||||
return (lineColor != null)
|
||||
? new FlatLineBorder( insets, lineColor )
|
||||
? new FlatLineBorder( insets, lineColor, lineThickness )
|
||||
: new FlatEmptyBorder( insets );
|
||||
};
|
||||
} else
|
||||
@@ -310,7 +368,7 @@ class UIDefaultsLoader
|
||||
try {
|
||||
return findClass( value, addonClassLoaders ).newInstance();
|
||||
} catch( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
|
||||
ex.printStackTrace();
|
||||
FlatLaf.LOG.log( Level.SEVERE, "FlatLaf: Failed to instantiate '" + value + "'.", ex );
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -321,7 +379,7 @@ class UIDefaultsLoader
|
||||
try {
|
||||
return findClass( value, addonClassLoaders );
|
||||
} catch( ClassNotFoundException ex ) {
|
||||
ex.printStackTrace();
|
||||
FlatLaf.LOG.log( Level.SEVERE, "FlatLaf: Failed to find class '" + value + "'.", ex );
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -346,7 +404,7 @@ class UIDefaultsLoader
|
||||
}
|
||||
|
||||
private static Insets parseInsets( String value ) {
|
||||
List<String> numbers = StringUtils.split( value, ',' );
|
||||
List<String> numbers = split( value, ',' );
|
||||
try {
|
||||
return new InsetsUIResource(
|
||||
Integer.parseInt( numbers.get( 0 ) ),
|
||||
@@ -358,8 +416,8 @@ class UIDefaultsLoader
|
||||
}
|
||||
}
|
||||
|
||||
private static Dimension parseSize( String value ) {
|
||||
List<String> numbers = StringUtils.split( value, ',' );
|
||||
private static Dimension parseDimension( String value ) {
|
||||
List<String> numbers = split( value, ',' );
|
||||
try {
|
||||
return new DimensionUIResource(
|
||||
Integer.parseInt( numbers.get( 0 ) ),
|
||||
@@ -369,9 +427,9 @@ class UIDefaultsLoader
|
||||
}
|
||||
}
|
||||
|
||||
private static ColorUIResource parseColorOrFunction( String value, boolean reportError ) {
|
||||
private static Object parseColorOrFunction( String value, Function<String, String> resolver, boolean reportError ) {
|
||||
if( value.endsWith( ")" ) )
|
||||
return parseColorFunctions( value, reportError );
|
||||
return parseColorFunctions( value, resolver, reportError );
|
||||
|
||||
return parseColor( value, reportError );
|
||||
}
|
||||
@@ -439,7 +497,7 @@ class UIDefaultsLoader
|
||||
: (((n >> 8) & 0xffffff) | ((n & 0xff) << 24)); // move alpha from lowest to highest byte
|
||||
}
|
||||
|
||||
private static ColorUIResource parseColorFunctions( String value, boolean reportError ) {
|
||||
private static Object parseColorFunctions( String value, Function<String, String> resolver, boolean reportError ) {
|
||||
int paramsStart = value.indexOf( '(' );
|
||||
if( paramsStart < 0 ) {
|
||||
if( reportError )
|
||||
@@ -448,37 +506,101 @@ class UIDefaultsLoader
|
||||
}
|
||||
|
||||
String function = value.substring( 0, paramsStart ).trim();
|
||||
List<String> params = StringUtils.split( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
|
||||
List<String> params = splitFunctionParams( value.substring( paramsStart + 1, value.length() - 1 ), ',' );
|
||||
if( params.isEmpty() )
|
||||
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
||||
|
||||
switch( function ) {
|
||||
case "lighten": return parseColorLightenOrDarken( true, params, reportError );
|
||||
case "darken": return parseColorLightenOrDarken( false, params, reportError );
|
||||
case "rgb": return parseColorRgbOrRgba( false, params );
|
||||
case "rgba": return parseColorRgbOrRgba( true, params );
|
||||
case "hsl": return parseColorHslOrHsla( false, params );
|
||||
case "hsla": return parseColorHslOrHsla( true, params );
|
||||
case "lighten": return parseColorLightenOrDarken( true, params, resolver, reportError );
|
||||
case "darken": return parseColorLightenOrDarken( false, params, resolver, reportError );
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException( "unknown color function '" + value + "'" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: lighten(amount[,options]) or darken(amount[,options])
|
||||
* - amount: percentage 0-100%
|
||||
* - options: [relative] [autoInverse]
|
||||
* Syntax: rgb(red,green,blue) or rgba(red,green,blue,alpha)
|
||||
* - red: an integer 0-255
|
||||
* - green: an integer 0-255
|
||||
* - blue: an integer 0-255
|
||||
* - alpha: an integer 0-255
|
||||
*/
|
||||
private static ColorUIResource parseColorLightenOrDarken( boolean lighten, List<String> params, boolean reportError ) {
|
||||
int amount = parsePercentage( params.get( 0 ) );
|
||||
private static ColorUIResource parseColorRgbOrRgba( boolean hasAlpha, List<String> params ) {
|
||||
int red = parseInteger( params.get( 0 ), 0, 255 );
|
||||
int green = parseInteger( params.get( 1 ), 0, 255 );
|
||||
int blue = parseInteger( params.get( 2 ), 0, 255 );
|
||||
int alpha = hasAlpha ? parseInteger( params.get( 3 ), 0, 255 ) : 255;
|
||||
|
||||
return hasAlpha
|
||||
? new ColorUIResource( new Color( red, green, blue, alpha ) )
|
||||
: new ColorUIResource( red, green, blue );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: hsl(hue,saturation,lightness) or hsla(hue,saturation,lightness,alpha)
|
||||
* - hue: an integer 0-360 representing degrees
|
||||
* - saturation: a percentage 0-100%
|
||||
* - lightness: a percentage 0-100%
|
||||
* - alpha: a percentage 0-100%
|
||||
*/
|
||||
private static ColorUIResource parseColorHslOrHsla( boolean hasAlpha, List<String> params ) {
|
||||
int hue = parseInteger( params.get( 0 ), 0, 360 );
|
||||
int saturation = parsePercentage( params.get( 1 ) );
|
||||
int lightness = parsePercentage( params.get( 2 ) );
|
||||
int alpha = hasAlpha ? parsePercentage( params.get( 3 ) ) : 100;
|
||||
|
||||
float[] hsl = new float[] { hue, saturation, lightness };
|
||||
return new ColorUIResource( HSLColor.toRGB( hsl, alpha / 100f ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: lighten(color,amount[,options]) or darken(color,amount[,options])
|
||||
* - color: a color (e.g. #f00) or a color function
|
||||
* - amount: percentage 0-100%
|
||||
* - options: [relative] [autoInverse] [lazy] [derived]
|
||||
*/
|
||||
private static Object parseColorLightenOrDarken( boolean lighten, List<String> params,
|
||||
Function<String, String> resolver, boolean reportError )
|
||||
{
|
||||
String colorStr = params.get( 0 );
|
||||
int amount = parsePercentage( params.get( 1 ) );
|
||||
boolean relative = false;
|
||||
boolean autoInverse = false;
|
||||
boolean lazy = false;
|
||||
boolean derived = false;
|
||||
|
||||
if( params.size() >= 2 ) {
|
||||
String options = params.get( 1 );
|
||||
if( params.size() > 2 ) {
|
||||
String options = params.get( 2 );
|
||||
relative = options.contains( "relative" );
|
||||
autoInverse = options.contains( "autoInverse" );
|
||||
lazy = options.contains( "lazy" );
|
||||
derived = options.contains( "derived" );
|
||||
}
|
||||
|
||||
return new DerivedColor( lighten
|
||||
ColorFunctions.ColorFunction function = lighten
|
||||
? new ColorFunctions.Lighten( amount, relative, autoInverse )
|
||||
: new ColorFunctions.Darken( amount, relative, autoInverse ) );
|
||||
: new ColorFunctions.Darken( amount, relative, autoInverse );
|
||||
|
||||
if( derived ) {
|
||||
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
||||
return new DerivedColor( ColorFunctions.applyFunctions( color, function ), function );
|
||||
}
|
||||
|
||||
if( lazy ) {
|
||||
return (LazyValue) t -> {
|
||||
Object color = lazyUIManagerGet( colorStr );
|
||||
return (color instanceof Color)
|
||||
? new ColorUIResource( ColorFunctions.applyFunctions( (Color) color, function ) )
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
ColorUIResource color = (ColorUIResource) parseColorOrFunction( resolver.apply( colorStr ), resolver, reportError );
|
||||
return new ColorUIResource( ColorFunctions.applyFunctions( color, function ) );
|
||||
}
|
||||
|
||||
private static int parsePercentage( String value ) {
|
||||
@@ -497,6 +619,19 @@ class UIDefaultsLoader
|
||||
return val;
|
||||
}
|
||||
|
||||
private static Character parseCharacter( String value ) {
|
||||
if( value.length() != 1 )
|
||||
throw new IllegalArgumentException( "invalid character '" + value + "'" );
|
||||
return value.charAt( 0 );
|
||||
}
|
||||
|
||||
private static Integer parseInteger( String value, int min, int max ) {
|
||||
Integer integer = parseInteger( value, true );
|
||||
if( integer.intValue() < min || integer.intValue() > max )
|
||||
throw new NumberFormatException( "integer '" + value + "' out of range (" + min + '-' + max + ')' );
|
||||
return integer;
|
||||
}
|
||||
|
||||
private static Integer parseInteger( String value, boolean reportError ) {
|
||||
try {
|
||||
return Integer.parseInt( value );
|
||||
@@ -507,10 +642,97 @@ class UIDefaultsLoader
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Float parseFloat( String value, boolean reportError ) {
|
||||
try {
|
||||
return Float.parseFloat( value );
|
||||
} catch( NumberFormatException ex ) {
|
||||
if( reportError )
|
||||
throw new NumberFormatException( "invalid float '" + value + "'" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ActiveValue parseScaledInteger( String value ) {
|
||||
int val = parseInteger( value, true );
|
||||
return (ActiveValue) t -> {
|
||||
return UIScale.scale( val );
|
||||
};
|
||||
}
|
||||
|
||||
private static ActiveValue parseScaledFloat( String value ) {
|
||||
float val = parseFloat( value, true );
|
||||
return (ActiveValue) t -> {
|
||||
return UIScale.scale( val );
|
||||
};
|
||||
}
|
||||
|
||||
private static ActiveValue parseScaledInsets( String value ) {
|
||||
Insets insets = parseInsets( value );
|
||||
return (ActiveValue) t -> {
|
||||
return UIScale.scale( insets );
|
||||
};
|
||||
}
|
||||
|
||||
private static ActiveValue parseScaledDimension( String value ) {
|
||||
Dimension dimension = parseDimension( value );
|
||||
return (ActiveValue) t -> {
|
||||
return UIScale.scale( dimension );
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Split string and trim parts.
|
||||
*/
|
||||
private static List<String> split( String str, char delim ) {
|
||||
List<String> result = StringUtils.split( str, delim );
|
||||
|
||||
// trim strings
|
||||
int size = result.size();
|
||||
for( int i = 0; i < size; i++ )
|
||||
result.set( i, result.get( i ).trim() );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits function parameters and allows using functions as parameters.
|
||||
* In other words: Delimiters surrounded by '(' and ')' are ignored.
|
||||
*/
|
||||
private static List<String> splitFunctionParams( String str, char delim ) {
|
||||
ArrayList<String> strs = new ArrayList<>();
|
||||
int nestLevel = 0;
|
||||
int start = 0;
|
||||
int strlen = str.length();
|
||||
for( int i = 0; i < strlen; i++ ) {
|
||||
char ch = str.charAt( i );
|
||||
if( ch == '(' )
|
||||
nestLevel++;
|
||||
else if( ch == ')' )
|
||||
nestLevel--;
|
||||
else if( nestLevel == 0 && ch == delim ) {
|
||||
strs.add( str.substring( start, i ).trim() );
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
strs.add( str.substring( start ).trim() );
|
||||
|
||||
return strs;
|
||||
}
|
||||
|
||||
/**
|
||||
* For use in LazyValue to get value for given key from UIManager and report error
|
||||
* if not found. If key is prefixed by '?', then no error is reported.
|
||||
*/
|
||||
private static Object lazyUIManagerGet( String uiKey ) {
|
||||
boolean optional = false;
|
||||
if( uiKey.startsWith( OPTIONAL_PREFIX ) ) {
|
||||
uiKey = uiKey.substring( OPTIONAL_PREFIX.length() );
|
||||
optional = true;
|
||||
}
|
||||
|
||||
Object value = UIManager.get( uiKey );
|
||||
if( value == null && !optional )
|
||||
FlatLaf.LOG.log( Level.SEVERE, "FlatLaf: '" + uiKey + "' not found in UI defaults." );
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class FlatAscendingSortIcon
|
||||
g.setColor( sortIconColor );
|
||||
if( chevron ) {
|
||||
// chevron arrow
|
||||
Path2D path = FlatUIUtils.createPath( false, 1,5, 5,1, 9,5 );
|
||||
Path2D path = FlatUIUtils.createPath( false, 1,4, 5,0, 9,4 );
|
||||
g.setStroke( new BasicStroke( 1f ) );
|
||||
g.draw( path );
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "caps lock" icon for {@link javax.swing.JPasswordField}.
|
||||
*
|
||||
* @uiDefault PasswordField.capsLockIconColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatCapsLockIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
public FlatCapsLockIcon() {
|
||||
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||
<rect width="6" height="2" x="5" y="12" fill="#FFF"/>
|
||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
||||
path.append( new Rectangle2D.Float( 5, 12, 6, 2 ), false );
|
||||
path.append( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 11,8, 11,10, 5,10, 5,8 ), false );
|
||||
g.fill( path );
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ public class FlatCheckBoxIcon
|
||||
boolean selected = indeterminate || (c instanceof AbstractButton && ((AbstractButton)c).isSelected());
|
||||
|
||||
// paint focused border
|
||||
if( c.hasFocus() && focusWidth > 0 ) {
|
||||
if( FlatUIUtils.isPermanentFocusOwner( c ) && focusWidth > 0 ) {
|
||||
g2.setColor( focusColor );
|
||||
paintFocusBorder( g2 );
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class FlatDescendingSortIcon
|
||||
g.setColor( sortIconColor );
|
||||
if( chevron ) {
|
||||
// chevron arrow
|
||||
Path2D path = FlatUIUtils.createPath( false, 1,1, 5,5, 9,1 );
|
||||
Path2D path = FlatUIUtils.createPath( false, 1,0, 5,4, 9,0 );
|
||||
g.setStroke( new BasicStroke( 1f ) );
|
||||
g.draw( path );
|
||||
} else {
|
||||
|
||||
@@ -82,7 +82,7 @@ public class FlatHelpButtonIcon
|
||||
*/
|
||||
|
||||
boolean enabled = c.isEnabled();
|
||||
boolean focused = c.hasFocus();
|
||||
boolean focused = FlatUIUtils.isPermanentFocusOwner( c );
|
||||
|
||||
// paint focused border
|
||||
if( focused ) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* Base class for internal frame icons.
|
||||
*
|
||||
* @uiDefault InternalFrame.buttonHoverBackground Color
|
||||
* @uiDefault InternalFrame.buttonPressedBackground Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public abstract class FlatInternalFrameAbstractIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private final Color hoverBackground;
|
||||
private final Color pressedBackground;
|
||||
|
||||
public FlatInternalFrameAbstractIcon() {
|
||||
this( UIManager.getDimension( "InternalFrame.buttonSize" ),
|
||||
UIManager.getColor( "InternalFrame.buttonHoverBackground" ),
|
||||
UIManager.getColor( "InternalFrame.buttonPressedBackground" ) );
|
||||
}
|
||||
|
||||
public FlatInternalFrameAbstractIcon( Dimension size, Color hoverBackground, Color pressedBackground ) {
|
||||
super( size.width, size.height, null );
|
||||
this.hoverBackground = hoverBackground;
|
||||
this.pressedBackground = pressedBackground;
|
||||
}
|
||||
|
||||
protected void paintBackground( Component c, Graphics2D g ) {
|
||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
||||
if( background != null ) {
|
||||
FlatUIUtils.setColor( g, background, c.getBackground() );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
|
||||
/**
|
||||
* "close" icon for {@link javax.swing.JInternalFrame}.
|
||||
*
|
||||
* @uiDefault InternalFrame.buttonHoverBackground Color
|
||||
* @uiDefault InternalFrame.buttonPressedBackground Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatInternalFrameCloseIcon
|
||||
extends FlatInternalFrameAbstractIcon
|
||||
{
|
||||
private final Color hoverForeground = UIManager.getColor( "InternalFrame.closeHoverForeground" );
|
||||
private final Color pressedForeground = UIManager.getColor( "InternalFrame.closePressedForeground" );
|
||||
|
||||
public FlatInternalFrameCloseIcon() {
|
||||
super( UIManager.getDimension( "InternalFrame.buttonSize" ),
|
||||
UIManager.getColor( "InternalFrame.closeHoverBackground" ),
|
||||
UIManager.getColor( "InternalFrame.closePressedBackground" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
paintBackground( c, g );
|
||||
|
||||
g.setColor( FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground ) );
|
||||
|
||||
float mx = width / 2;
|
||||
float my = height / 2;
|
||||
float r = 3.25f;
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
||||
g.setStroke( new BasicStroke( 1f ) );
|
||||
g.draw( path );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
/**
|
||||
* "iconify" icon for {@link javax.swing.JInternalFrame}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatInternalFrameIconifyIcon
|
||||
extends FlatInternalFrameAbstractIcon
|
||||
{
|
||||
public FlatInternalFrameIconifyIcon() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
paintBackground( c, g );
|
||||
|
||||
g.setColor( c.getForeground() );
|
||||
g.fillRect( (width / 2) - 4, height / 2, 8, 1 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "maximize" icon for {@link javax.swing.JInternalFrame}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatInternalFrameMaximizeIcon
|
||||
extends FlatInternalFrameAbstractIcon
|
||||
{
|
||||
public FlatInternalFrameMaximizeIcon() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
paintBackground( c, g );
|
||||
|
||||
g.setColor( c.getForeground() );
|
||||
g.fill( FlatUIUtils.createRectangle( (width / 2) - 4, (height / 2) - 4, 8, 8, 1 ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "minimize" (actually "restore") icon for {@link javax.swing.JInternalFrame}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatInternalFrameMinimizeIcon
|
||||
extends FlatInternalFrameAbstractIcon
|
||||
{
|
||||
public FlatInternalFrameMinimizeIcon() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
paintBackground( c, g );
|
||||
|
||||
g.setColor( c.getForeground() );
|
||||
|
||||
int x = (width / 2) - 4;
|
||||
int y = (height / 2) - 4;
|
||||
Path2D r1 = FlatUIUtils.createRectangle( x + 1, y - 1, 8, 8, 1 );
|
||||
Path2D r2 = FlatUIUtils.createRectangle( x - 1, y + 1, 8, 8, 1 );
|
||||
|
||||
Area area = new Area( r1 );
|
||||
area.subtract( new Area( new Rectangle2D.Float( x - 1, y + 1, 8, 8 ) ) );
|
||||
g.fill( area );
|
||||
|
||||
g.fill( r2 );
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ import javax.swing.text.JTextComponent;
|
||||
* {@link FlatUIUtils#paintParentBackground} to paint the empty space correctly.
|
||||
*
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.innerFocusWidth int
|
||||
* @uiDefault Component.innerFocusWidth int or float
|
||||
* @uiDefault Component.focusColor Color
|
||||
* @uiDefault Component.borderColor Color
|
||||
* @uiDefault Component.disabledBorderColor Color
|
||||
@@ -60,7 +60,7 @@ public class FlatBorder
|
||||
extends BasicBorders.MarginBorder
|
||||
{
|
||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
protected final int innerFocusWidth = UIManager.getInt( "Component.innerFocusWidth" );
|
||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||
protected final Color borderColor = UIManager.getColor( "Component.borderColor" );
|
||||
protected final Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
||||
@@ -73,14 +73,16 @@ public class FlatBorder
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
boolean isCellEditor = isTableCellEditor( c );
|
||||
float focusWidth = isCellEditor ? 0 : getFocusWidth();
|
||||
float focusWidth = isCellEditor ? 0 : getFocusWidth( c );
|
||||
float borderWidth = getBorderWidth( c );
|
||||
float arc = isCellEditor ? 0 : getArc();
|
||||
float arc = isCellEditor ? 0 : getArc( c );
|
||||
|
||||
if( isFocused( c ) ) {
|
||||
float innerFocusWidth = !(c instanceof JScrollPane) ? this.innerFocusWidth : 0;
|
||||
|
||||
g2.setColor( getFocusColor( c ) );
|
||||
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height, focusWidth,
|
||||
getLineWidth() + scale( (float) innerFocusWidth ), arc );
|
||||
getLineWidth( c ) + scale( innerFocusWidth ), arc );
|
||||
}
|
||||
|
||||
g2.setPaint( getBorderColor( c ) );
|
||||
@@ -117,7 +119,7 @@ public class FlatBorder
|
||||
JViewport viewport = ((JScrollPane)c).getViewport();
|
||||
Component view = (viewport != null) ? viewport.getView() : null;
|
||||
if( view != null ) {
|
||||
if( view.hasFocus() )
|
||||
if( FlatUIUtils.isPermanentFocusOwner( view ) )
|
||||
return true;
|
||||
|
||||
if( (view instanceof JTable && ((JTable)view).isEditing()) ||
|
||||
@@ -131,17 +133,17 @@ public class FlatBorder
|
||||
return false;
|
||||
} else if( c instanceof JComboBox && ((JComboBox<?>)c).isEditable() ) {
|
||||
Component editorComponent = ((JComboBox<?>)c).getEditor().getEditorComponent();
|
||||
return (editorComponent != null) ? editorComponent.hasFocus() : false;
|
||||
return (editorComponent != null) ? FlatUIUtils.isPermanentFocusOwner( editorComponent ) : false;
|
||||
} else if( c instanceof JSpinner ) {
|
||||
JComponent editor = ((JSpinner)c).getEditor();
|
||||
if( editor instanceof JSpinner.DefaultEditor ) {
|
||||
JTextField textField = ((JSpinner.DefaultEditor)editor).getTextField();
|
||||
if( textField != null )
|
||||
return textField.hasFocus();
|
||||
return FlatUIUtils.isPermanentFocusOwner( textField );
|
||||
}
|
||||
return false;
|
||||
} else
|
||||
return c.hasFocus();
|
||||
return FlatUIUtils.isPermanentFocusOwner( c );
|
||||
}
|
||||
|
||||
protected boolean isTableCellEditor( Component c ) {
|
||||
@@ -151,7 +153,7 @@ public class FlatBorder
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
boolean isCellEditor = isTableCellEditor( c );
|
||||
float ow = (isCellEditor ? 0 : getFocusWidth()) + getLineWidth();
|
||||
float ow = (isCellEditor ? 0 : getFocusWidth( c )) + getLineWidth( c );
|
||||
|
||||
insets = super.getBorderInsets( c, insets );
|
||||
insets.top = Math.round( scale( (float) insets.top ) + ow );
|
||||
@@ -161,19 +163,19 @@ public class FlatBorder
|
||||
return insets;
|
||||
}
|
||||
|
||||
protected float getFocusWidth() {
|
||||
protected float getFocusWidth( Component c ) {
|
||||
return scale( (float) focusWidth );
|
||||
}
|
||||
|
||||
protected float getLineWidth() {
|
||||
protected float getLineWidth( Component c ) {
|
||||
return scale( 1f );
|
||||
}
|
||||
|
||||
protected float getBorderWidth( Component c ) {
|
||||
return getLineWidth();
|
||||
return getLineWidth( c );
|
||||
}
|
||||
|
||||
protected float getArc() {
|
||||
protected float getArc( Component c ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,10 @@ import java.awt.GradientPaint;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Paint;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Border for {@link javax.swing.JButton}.
|
||||
@@ -43,6 +44,8 @@ import javax.swing.plaf.UIResource;
|
||||
* @uiDefault Button.default.focusedBorderColor Color
|
||||
* @uiDefault Button.default.focusColor Color
|
||||
* @uiDefault Button.default.borderWidth int
|
||||
* @uiDefault Button.toolbar.margin Insets
|
||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||
* @uiDefault Button.arc int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
@@ -61,12 +64,17 @@ public class FlatButtonBorder
|
||||
protected final Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
||||
protected final Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
||||
protected final int defaultBorderWidth = UIManager.getInt( "Button.default.borderWidth" );
|
||||
protected final Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" );
|
||||
protected final Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
||||
protected final int arc = UIManager.getInt( "Button.arc" );
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( FlatButtonUI.isContentAreaFilled( c ) && !FlatButtonUI.isHelpButton( c ) )
|
||||
super.paintBorder( c, g, x, y, width, height );
|
||||
if( FlatButtonUI.isContentAreaFilled( c ) &&
|
||||
!FlatButtonUI.isToolBarButton( c ) &&
|
||||
!FlatButtonUI.isHelpButton( c ) &&
|
||||
!FlatToggleButtonUI.isTabButton( c ) )
|
||||
super.paintBorder( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,22 +103,38 @@ public class FlatButtonBorder
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
insets = super.getBorderInsets( c, insets );
|
||||
if( FlatButtonUI.isToolBarButton( c ) ) {
|
||||
// In toolbars, use button margin only if explicitly set.
|
||||
// Otherwise use toolbar margin specified in UI defaults.
|
||||
Insets margin = (c instanceof AbstractButton)
|
||||
? ((AbstractButton)c).getMargin()
|
||||
: null;
|
||||
|
||||
// use smaller left and right insets for icon-only buttons (so that they are square)
|
||||
if( FlatButtonUI.isIconOnlyButton( c ) && ((JButton)c).getMargin() instanceof UIResource )
|
||||
insets.left = insets.right = Math.min( insets.top, insets.bottom );
|
||||
FlatUIUtils.setInsets( insets, UIScale.scale( FlatUIUtils.addInsets( toolbarSpacingInsets,
|
||||
(margin != null && !(margin instanceof UIResource)) ? margin : toolbarMargin ) ) );
|
||||
} else {
|
||||
insets = super.getBorderInsets( c, insets );
|
||||
|
||||
// use smaller left and right insets for icon-only buttons (so that they are square)
|
||||
if( FlatButtonUI.isIconOnlyButton( c ) && ((AbstractButton)c).getMargin() instanceof UIResource )
|
||||
insets.left = insets.right = Math.min( insets.top, insets.bottom );
|
||||
}
|
||||
|
||||
return insets;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getFocusWidth( Component c ) {
|
||||
return FlatToggleButtonUI.isTabButton( c ) ? 0 : super.getFocusWidth(c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBorderWidth( Component c ) {
|
||||
return FlatButtonUI.isDefaultButton( c ) ? scale( (float) defaultBorderWidth ) : super.getBorderWidth( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getArc() {
|
||||
return scale( (float) arc );
|
||||
protected float getArc( Component c ) {
|
||||
return FlatButtonUI.isSquareButton( c ) ? 0 : scale( (float) arc );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,19 +26,23 @@ import java.awt.FontMetrics;
|
||||
import java.awt.GradientPaint;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicButtonListener;
|
||||
import javax.swing.plaf.basic.BasicButtonUI;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -79,6 +83,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault Button.shadowWidth int default is 2
|
||||
* @uiDefault Button.shadowColor Color optional
|
||||
* @uiDefault Button.default.shadowColor Color optional
|
||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||
* @uiDefault Button.toolbar.hoverBackground Color
|
||||
* @uiDefault Button.toolbar.pressedBackground Color
|
||||
*
|
||||
@@ -111,6 +116,7 @@ public class FlatButtonUI
|
||||
protected Color shadowColor;
|
||||
protected Color defaultShadowColor;
|
||||
|
||||
protected Insets toolbarSpacingInsets;
|
||||
protected Color toolbarHoverBackground;
|
||||
protected Color toolbarPressedBackground;
|
||||
|
||||
@@ -149,6 +155,10 @@ public class FlatButtonUI
|
||||
shadowWidth = FlatUIUtils.getUIInt( "Button.shadowWidth", 2 );
|
||||
shadowColor = UIManager.getColor( "Button.shadowColor" );
|
||||
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
||||
} else {
|
||||
shadowWidth = 0;
|
||||
shadowColor = null;
|
||||
defaultShadowColor = null;
|
||||
}
|
||||
|
||||
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
|
||||
@@ -159,6 +169,7 @@ public class FlatButtonUI
|
||||
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
||||
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
||||
|
||||
toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
||||
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
||||
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
||||
|
||||
@@ -176,7 +187,7 @@ public class FlatButtonUI
|
||||
LookAndFeel.installProperty( b, "opaque", false );
|
||||
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
|
||||
|
||||
MigLayoutVisualPadding.install( b, focusWidth );
|
||||
MigLayoutVisualPadding.install( b, getFocusWidth( b ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -187,6 +198,26 @@ public class FlatButtonUI
|
||||
defaults_initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BasicButtonListener createButtonListener( AbstractButton b ) {
|
||||
return new BasicButtonListener( b ) {
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
FlatButtonUI.this.propertyChange( b, e );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case MINIMUM_WIDTH:
|
||||
case MINIMUM_HEIGHT:
|
||||
b.revalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isContentAreaFilled( Component c ) {
|
||||
return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled();
|
||||
}
|
||||
@@ -196,20 +227,24 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
static boolean isIconOnlyButton( Component c ) {
|
||||
if( !(c instanceof JButton) )
|
||||
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
||||
return false;
|
||||
|
||||
Icon icon = ((JButton)c).getIcon();
|
||||
String text = ((JButton)c).getText();
|
||||
Icon icon = ((AbstractButton)c).getIcon();
|
||||
String text = ((AbstractButton)c).getText();
|
||||
return (icon != null && (text == null || text.isEmpty())) ||
|
||||
(icon == null && text != null && ("...".equals( text ) || text.length() == 1));
|
||||
}
|
||||
|
||||
static boolean isSquareButton( Component c ) {
|
||||
return c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_SQUARE );
|
||||
}
|
||||
|
||||
static boolean isHelpButton( Component c ) {
|
||||
return c instanceof JButton && clientPropertyEquals( (JButton) c, BUTTON_TYPE, BUTTON_TYPE_HELP );
|
||||
}
|
||||
|
||||
static boolean isToolBarButton( JComponent c ) {
|
||||
static boolean isToolBarButton( Component c ) {
|
||||
return c.getParent() instanceof JToolBar;
|
||||
}
|
||||
|
||||
@@ -224,43 +259,64 @@ public class FlatButtonUI
|
||||
return;
|
||||
}
|
||||
|
||||
if( isContentAreaFilled( c ) ) {
|
||||
Color background = getBackground( c );
|
||||
if( background != null ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
Border border = c.getBorder();
|
||||
float focusWidth = (border instanceof FlatBorder) ? scale( (float) this.focusWidth ) : 0;
|
||||
float arc = (border instanceof FlatButtonBorder || isToolBarButton( c )) ? scale( (float) this.arc ) : 0;
|
||||
boolean def = isDefaultButton( c );
|
||||
|
||||
// paint shadow
|
||||
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
||||
if( shadowColor != null && shadowWidth > 0 && focusWidth > 0 && !c.hasFocus() && c.isEnabled() ) {
|
||||
g2.setColor( shadowColor );
|
||||
g2.fill( new RoundRectangle2D.Float( focusWidth, focusWidth + UIScale.scale( (float) shadowWidth ),
|
||||
c.getWidth() - focusWidth * 2, c.getHeight() - focusWidth * 2, arc, arc ) );
|
||||
}
|
||||
|
||||
// paint background
|
||||
Color startBg = def ? defaultBackground : startBackground;
|
||||
Color endBg = def ? defaultEndBackground : endBackground;
|
||||
if( background == startBg && endBg != null && !startBg.equals( endBg ) )
|
||||
g2.setPaint( new GradientPaint( 0, 0, startBg, 0, c.getHeight(), endBg ) );
|
||||
else
|
||||
FlatUIUtils.setColor( g2, background, def ? defaultBackground : c.getBackground() );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
if( isContentAreaFilled( c ) )
|
||||
paintBackground( g, c );
|
||||
|
||||
paint( g, c );
|
||||
}
|
||||
|
||||
protected void paintBackground( Graphics g, JComponent c ) {
|
||||
Color background = getBackground( c );
|
||||
if( background != null ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
Border border = c.getBorder();
|
||||
boolean isToolBarButton = isToolBarButton( c );
|
||||
float focusWidth = (border instanceof FlatBorder && !isToolBarButton) ? scale( (float) getFocusWidth( c ) ) : 0;
|
||||
float arc = ((border instanceof FlatButtonBorder && !isSquareButton( c )) || isToolBarButton)
|
||||
? scale( (float) this.arc ) : 0;
|
||||
boolean def = isDefaultButton( c );
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = c.getWidth();
|
||||
int height = c.getHeight();
|
||||
|
||||
if( isToolBarButton ) {
|
||||
Insets spacing = UIScale.scale( toolbarSpacingInsets );
|
||||
x += spacing.left;
|
||||
y += spacing.top;
|
||||
width -= spacing.left + spacing.right;
|
||||
height -= spacing.top + spacing.bottom;
|
||||
}
|
||||
|
||||
// paint shadow
|
||||
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
||||
if( !isToolBarButton && shadowColor != null && shadowWidth > 0 && focusWidth > 0 &&
|
||||
!FlatUIUtils.isPermanentFocusOwner( c ) && c.isEnabled() )
|
||||
{
|
||||
g2.setColor( shadowColor );
|
||||
g2.fill( new RoundRectangle2D.Float( focusWidth, focusWidth + UIScale.scale( (float) shadowWidth ),
|
||||
width - focusWidth * 2, height - focusWidth * 2, arc, arc ) );
|
||||
}
|
||||
|
||||
// paint background
|
||||
Color startBg = def ? defaultBackground : startBackground;
|
||||
Color endBg = def ? defaultEndBackground : endBackground;
|
||||
if( background == startBg && endBg != null && !startBg.equals( endBg ) )
|
||||
g2.setPaint( new GradientPaint( 0, 0, startBg, 0, height, endBg ) );
|
||||
else
|
||||
FlatUIUtils.setColor( g2, background, def ? defaultBackground : c.getBackground() );
|
||||
|
||||
FlatUIUtils.paintComponentBackground( g2, x, y, width, height, focusWidth, arc );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, AbstractButton b, Rectangle textRect, String text ) {
|
||||
if( isHelpButton( b ) )
|
||||
@@ -328,7 +384,7 @@ public class FlatButtonUI
|
||||
if( hoverColor != null && b != null && b.getModel().isRollover() )
|
||||
return hoverColor;
|
||||
|
||||
if( focusedColor != null && c.hasFocus() )
|
||||
if( focusedColor != null && FlatUIUtils.isPermanentFocusOwner( c ) )
|
||||
return focusedColor;
|
||||
|
||||
return enabledColor;
|
||||
@@ -345,14 +401,23 @@ public class FlatButtonUI
|
||||
return new Dimension( helpButtonIcon.getIconWidth(), helpButtonIcon.getIconHeight() );
|
||||
|
||||
Dimension prefSize = super.getPreferredSize( c );
|
||||
if ( prefSize == null )
|
||||
return null;
|
||||
|
||||
// make button square if it is a icon-only button
|
||||
// or apply minimum width, if not in toolbar and not a icon-only button
|
||||
if( isIconOnlyButton( c ) )
|
||||
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
||||
else if( !isToolBarButton( c ) )
|
||||
prefSize.width = Math.max( prefSize.width, scale( minimumWidth + (focusWidth * 2) ) );
|
||||
else if( !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
|
||||
int focusWidth = getFocusWidth( c );
|
||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) + (focusWidth * 2) ) );
|
||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) + (focusWidth * 2) ) );
|
||||
}
|
||||
|
||||
return prefSize;
|
||||
}
|
||||
|
||||
protected int getFocusWidth( JComponent c ) {
|
||||
return focusWidth;
|
||||
}
|
||||
}
|
||||
|
||||
128
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
Normal file
128
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatCaret.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.text.DefaultCaret;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.JTextComponent;
|
||||
|
||||
/**
|
||||
* Caret that can select all text on focus gained.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
class FlatCaret
|
||||
extends DefaultCaret
|
||||
implements UIResource
|
||||
{
|
||||
private final String selectAllOnFocusPolicy;
|
||||
|
||||
private boolean wasFocused;
|
||||
private boolean wasTemporaryLost;
|
||||
private boolean isMousePressed;
|
||||
|
||||
FlatCaret( String selectAllOnFocusPolicy ) {
|
||||
this.selectAllOnFocusPolicy = selectAllOnFocusPolicy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void install( JTextComponent c ) {
|
||||
super.install( c );
|
||||
|
||||
// the dot and mark are lost when switching LaF
|
||||
// --> move dot to end of text so that all text may be selected when it gains focus
|
||||
Document doc = c.getDocument();
|
||||
if( doc != null && getDot() == 0 && getMark() == 0 ) {
|
||||
int length = doc.getLength();
|
||||
if( length > 0 )
|
||||
setDot( length );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {
|
||||
if( !wasTemporaryLost && !isMousePressed )
|
||||
selectAllOnFocusGained();
|
||||
wasTemporaryLost = false;
|
||||
wasFocused = true;
|
||||
|
||||
super.focusGained( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
wasTemporaryLost = e.isTemporary();
|
||||
super.focusLost( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed( MouseEvent e ) {
|
||||
isMousePressed = true;
|
||||
super.mousePressed( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent e ) {
|
||||
isMousePressed = false;
|
||||
super.mouseReleased( e );
|
||||
}
|
||||
|
||||
private void selectAllOnFocusGained() {
|
||||
JTextComponent c = getComponent();
|
||||
Document doc = c.getDocument();
|
||||
if( doc == null || !c.isEnabled() || !c.isEditable() )
|
||||
return;
|
||||
|
||||
Object selectAllOnFocusPolicy = c.getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
||||
if( selectAllOnFocusPolicy == null )
|
||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
||||
|
||||
if( SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||
return;
|
||||
|
||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
||||
// policy is "once" (or null or unknown)
|
||||
|
||||
// was already focused?
|
||||
if( wasFocused )
|
||||
return;
|
||||
|
||||
// check whether selection was modified before gaining focus
|
||||
int dot = getDot();
|
||||
int mark = getMark();
|
||||
if( dot != mark || dot != doc.getLength() )
|
||||
return;
|
||||
}
|
||||
|
||||
// select all
|
||||
if( c instanceof JFormattedTextField ) {
|
||||
EventQueue.invokeLater( () -> {
|
||||
setDot( 0 );
|
||||
moveDot( doc.getLength() );
|
||||
} );
|
||||
} else {
|
||||
setDot( 0 );
|
||||
moveDot( doc.getLength() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,11 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
||||
|
||||
@@ -74,4 +77,9 @@ public class FlatCheckBoxMenuItemUI
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,9 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicColorChooserUI;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JColorChooser}.
|
||||
@@ -43,21 +40,4 @@ public class FlatColorChooserUI
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatColorChooserUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
if( UIScale.getUserScaleFactor() != 1f ) {
|
||||
// temporary scale swatch sizes
|
||||
Dimension swatchSize = UIManager.getDimension( "ColorChooser.swatchesSwatchSize" );
|
||||
Dimension swatchSize2 = UIManager.getDimension( "ColorChooser.swatchesRecentSwatchSize" );
|
||||
UIManager.put( "ColorChooser.swatchesSwatchSize", UIScale.scale( swatchSize ) );
|
||||
UIManager.put( "ColorChooser.swatchesRecentSwatchSize", UIScale.scale( swatchSize2 ) );
|
||||
|
||||
super.installUI( c );
|
||||
|
||||
UIManager.put( "ColorChooser.swatchesSwatchSize", null );
|
||||
UIManager.put( "ColorChooser.swatchesRecentSwatchSize", null );
|
||||
} else
|
||||
super.installUI( c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.MouseListener;
|
||||
@@ -35,12 +37,16 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.InputMap;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingConstants;
|
||||
@@ -53,6 +59,7 @@ import javax.swing.plaf.basic.BasicComboPopup;
|
||||
import javax.swing.plaf.basic.ComboPopup;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -270,6 +277,19 @@ public class FlatComboBoxUI
|
||||
editor.applyComponentOrientation( comboBox.getComponentOrientation() );
|
||||
|
||||
updateEditorColors();
|
||||
|
||||
// macOS
|
||||
if( SystemInfo.IS_MAC && editor instanceof JTextComponent ) {
|
||||
// delegate actions from editor text field to combobox, which is necessary
|
||||
// because text field on macOS already handle those keys
|
||||
InputMap inputMap = ((JTextComponent)editor).getInputMap();
|
||||
new EditorDelegateAction( inputMap, KeyStroke.getKeyStroke( "UP" ) );
|
||||
new EditorDelegateAction( inputMap, KeyStroke.getKeyStroke( "KP_UP" ) );
|
||||
new EditorDelegateAction( inputMap, KeyStroke.getKeyStroke( "DOWN" ) );
|
||||
new EditorDelegateAction( inputMap, KeyStroke.getKeyStroke( "KP_DOWN" ) );
|
||||
new EditorDelegateAction( inputMap, KeyStroke.getKeyStroke( "HOME" ) );
|
||||
new EditorDelegateAction( inputMap, KeyStroke.getKeyStroke( "END" ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEditorColors() {
|
||||
@@ -348,6 +368,8 @@ public class FlatComboBoxUI
|
||||
public void paintCurrentValue( Graphics g, Rectangle bounds, boolean hasFocus ) {
|
||||
ListCellRenderer<Object> renderer = comboBox.getRenderer();
|
||||
uninstallCellPaddingBorder( renderer );
|
||||
if( renderer == null )
|
||||
renderer = new DefaultListCellRenderer();
|
||||
Component c = renderer.getListCellRendererComponent( listBox, comboBox.getSelectedItem(), -1, false, false );
|
||||
c.setFont( comboBox.getFont() );
|
||||
c.applyComponentOrientation( comboBox.getComponentOrientation() );
|
||||
@@ -438,12 +460,12 @@ public class FlatComboBoxUI
|
||||
//---- class FlatComboPopup -----------------------------------------------
|
||||
|
||||
@SuppressWarnings( { "rawtypes", "unchecked" } )
|
||||
private class FlatComboPopup
|
||||
protected class FlatComboPopup
|
||||
extends BasicComboPopup
|
||||
{
|
||||
private CellPaddingBorder paddingBorder;
|
||||
|
||||
FlatComboPopup( JComboBox combo ) {
|
||||
protected FlatComboPopup( JComboBox combo ) {
|
||||
super( combo );
|
||||
|
||||
// BasicComboPopup listens to JComboBox.componentOrientation and updates
|
||||
@@ -458,13 +480,8 @@ public class FlatComboBoxUI
|
||||
|
||||
@Override
|
||||
protected Rectangle computePopupBounds( int px, int py, int pw, int ph ) {
|
||||
// get maximum display size of all items, ignoring prototype value
|
||||
Object prototype = comboBox.getPrototypeDisplayValue();
|
||||
if( prototype != null )
|
||||
comboBox.setPrototypeDisplayValue( null );
|
||||
// get maximum display size of all items
|
||||
Dimension displaySize = getDisplaySize();
|
||||
if( prototype != null )
|
||||
comboBox.setPrototypeDisplayValue( prototype );
|
||||
|
||||
// make popup wider if necessary
|
||||
if( displaySize.width > pw ) {
|
||||
@@ -520,6 +537,8 @@ public class FlatComboBoxUI
|
||||
CellPaddingBorder.uninstall( renderer );
|
||||
CellPaddingBorder.uninstall( lastRendererComponent );
|
||||
|
||||
if( renderer == null )
|
||||
renderer = new DefaultListCellRenderer();
|
||||
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
|
||||
c.applyComponentOrientation( comboBox.getComponentOrientation() );
|
||||
|
||||
@@ -603,4 +622,31 @@ public class FlatComboBoxUI
|
||||
rendererBorder.paintBorder( c, g, x, y, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class EditorDelegateAction -----------------------------------------
|
||||
|
||||
/**
|
||||
* Delegates actions from editor text field to combobox.
|
||||
*/
|
||||
private class EditorDelegateAction
|
||||
extends AbstractAction
|
||||
{
|
||||
private final KeyStroke keyStroke;
|
||||
|
||||
EditorDelegateAction( InputMap inputMap, KeyStroke keyStroke ) {
|
||||
this.keyStroke = keyStroke;
|
||||
|
||||
// add to input map
|
||||
inputMap.put( keyStroke, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e ) {
|
||||
ActionListener action = comboBox.getActionForKeyStroke( keyStroke );
|
||||
if( action != null ) {
|
||||
action.actionPerformed( new ActionEvent( comboBox, e.getID(),
|
||||
e.getActionCommand(), e.getWhen(), e.getModifiers() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyVetoException;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.JToolTip;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicDesktopIconUI;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame.JDesktopIcon}.
|
||||
*
|
||||
* <!-- BasicDesktopIconUI -->
|
||||
*
|
||||
* @uiDefault DesktopIcon.border Border
|
||||
*
|
||||
* <!-- FlatDesktopIconUI -->
|
||||
*
|
||||
* @uiDefault DesktopIcon.background Color
|
||||
* @uiDefault DesktopIcon.foreground Color
|
||||
* @uiDefault DesktopIcon.iconSize Dimension
|
||||
* @uiDefault DesktopIcon.closeSize Dimension
|
||||
* @uiDefault DesktopIcon.closeIcon Icon
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatDesktopIconUI
|
||||
extends BasicDesktopIconUI
|
||||
{
|
||||
private Dimension iconSize;
|
||||
private Dimension closeSize;
|
||||
|
||||
private JLabel dockIcon;
|
||||
private JButton closeButton;
|
||||
private JToolTip titleTip;
|
||||
private ActionListener closeListener;
|
||||
private MouseInputListener mouseInputListener;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatDesktopIconUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
|
||||
dockIcon = null;
|
||||
closeButton = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installComponents() {
|
||||
dockIcon = new JLabel();
|
||||
dockIcon.setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
closeButton = new JButton();
|
||||
closeButton.setIcon( UIManager.getIcon( "DesktopIcon.closeIcon" ) );
|
||||
closeButton.setFocusable( false );
|
||||
closeButton.setBorder( BorderFactory.createEmptyBorder() );
|
||||
closeButton.setOpaque( true );
|
||||
closeButton.setBackground( FlatUIUtils.nonUIResource( desktopIcon.getBackground() ) );
|
||||
closeButton.setForeground( FlatUIUtils.nonUIResource( desktopIcon.getForeground() ) );
|
||||
closeButton.setVisible( false );
|
||||
|
||||
desktopIcon.setLayout( new FlatDesktopIconLayout() );
|
||||
desktopIcon.add( closeButton );
|
||||
desktopIcon.add( dockIcon );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallComponents() {
|
||||
hideTitleTip();
|
||||
|
||||
desktopIcon.remove( dockIcon );
|
||||
desktopIcon.remove( closeButton );
|
||||
desktopIcon.setLayout( null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
LookAndFeel.installColors( desktopIcon, "DesktopIcon.background", "DesktopIcon.foreground" );
|
||||
|
||||
iconSize = UIManager.getDimension( "DesktopIcon.iconSize" );
|
||||
closeSize = UIManager.getDimension( "DesktopIcon.closeSize" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners() {
|
||||
super.installListeners();
|
||||
|
||||
closeListener = e -> {
|
||||
if( frame.isClosable() )
|
||||
frame.doDefaultCloseAction();
|
||||
};
|
||||
closeButton.addActionListener( closeListener );
|
||||
closeButton.addMouseListener( mouseInputListener );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners() {
|
||||
super.uninstallListeners();
|
||||
|
||||
closeButton.removeActionListener( closeListener );
|
||||
closeButton.removeMouseListener( mouseInputListener );
|
||||
closeListener = null;
|
||||
mouseInputListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MouseInputListener createMouseInputListener() {
|
||||
mouseInputListener = new MouseInputAdapter() {
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent e ) {
|
||||
if( frame.isIcon() && desktopIcon.contains( e.getX(), e.getY() ) ) {
|
||||
hideTitleTip();
|
||||
closeButton.setVisible( false );
|
||||
|
||||
try {
|
||||
frame.setIcon( false );
|
||||
} catch( PropertyVetoException ex ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered( MouseEvent e ) {
|
||||
showTitleTip();
|
||||
if( frame.isClosable() )
|
||||
closeButton.setVisible( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited( MouseEvent e ) {
|
||||
hideTitleTip();
|
||||
closeButton.setVisible( false );
|
||||
}
|
||||
};
|
||||
return mouseInputListener;
|
||||
}
|
||||
|
||||
private void showTitleTip() {
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( desktopIcon );
|
||||
if( rootPane == null )
|
||||
return;
|
||||
|
||||
if( titleTip == null ) {
|
||||
titleTip = new JToolTip();
|
||||
rootPane.getLayeredPane().add( titleTip, JLayeredPane.POPUP_LAYER );
|
||||
}
|
||||
titleTip.setTipText( frame.getTitle() );
|
||||
titleTip.setSize( titleTip.getPreferredSize() );
|
||||
|
||||
int tx = (desktopIcon.getWidth() - titleTip.getWidth()) / 2;
|
||||
int ty = -(titleTip.getHeight() + UIScale.scale( 4 ));
|
||||
Point pt = SwingUtilities.convertPoint( desktopIcon, tx, ty, titleTip.getParent() );
|
||||
if( pt.x + titleTip.getWidth() > rootPane.getWidth() )
|
||||
pt.x = rootPane.getWidth() - titleTip.getWidth();
|
||||
if( pt.x < 0 )
|
||||
pt.x = 0;
|
||||
titleTip.setLocation( pt );
|
||||
titleTip.repaint();
|
||||
}
|
||||
|
||||
private void hideTitleTip() {
|
||||
if( titleTip == null )
|
||||
return;
|
||||
|
||||
titleTip.setVisible( false );
|
||||
titleTip.getParent().remove( titleTip );
|
||||
titleTip = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
return UIScale.scale( iconSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize( JComponent c ) {
|
||||
return getPreferredSize( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMaximumSize( JComponent c ) {
|
||||
return getPreferredSize( c );
|
||||
}
|
||||
|
||||
void updateDockIcon() {
|
||||
// use invoke later to make sure that components are updated when switching LaF
|
||||
EventQueue.invokeLater( () -> {
|
||||
if( dockIcon != null )
|
||||
updateDockIconLater();
|
||||
} );
|
||||
}
|
||||
|
||||
private void updateDockIconLater() {
|
||||
// make sure that frame is not selected
|
||||
if( frame.isSelected() ) {
|
||||
try {
|
||||
frame.setSelected( false );
|
||||
} catch( PropertyVetoException ex ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// paint internal frame to buffered image
|
||||
int frameWidth = Math.max( frame.getWidth(), 1 );
|
||||
int frameHeight = Math.max( frame.getHeight(), 1 );
|
||||
BufferedImage frameImage = new BufferedImage( frameWidth, frameHeight, BufferedImage.TYPE_INT_ARGB );
|
||||
Graphics2D g = frameImage.createGraphics();
|
||||
try {
|
||||
//TODO fix missing internal frame header when switching LaF
|
||||
frame.paint( g );
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
// compute preview size (keep ratio; also works with non-square preview)
|
||||
Insets insets = desktopIcon.getInsets();
|
||||
int previewWidth = UIScale.scale( iconSize.width ) - insets.left - insets.right;
|
||||
int previewHeight = UIScale.scale( iconSize.height ) - insets.top - insets.bottom;
|
||||
float frameRatio = ((float) frameHeight / (float) frameWidth);
|
||||
if( ((float) previewWidth / (float) frameWidth) > ((float) previewHeight / (float) frameHeight) )
|
||||
previewWidth = Math.round( previewHeight / frameRatio );
|
||||
else
|
||||
previewHeight = Math.round( previewWidth * frameRatio );
|
||||
|
||||
// scale preview
|
||||
Image previewImage = frameImage.getScaledInstance( previewWidth, previewHeight, Image.SCALE_SMOOTH );
|
||||
dockIcon.setIcon( new ImageIcon( previewImage ) );
|
||||
}
|
||||
|
||||
//---- class DockIcon -----------------------------------------------------
|
||||
|
||||
private class FlatDesktopIconLayout
|
||||
implements LayoutManager
|
||||
{
|
||||
@Override public void addLayoutComponent( String name, Component comp ) {}
|
||||
@Override public void removeLayoutComponent( Component comp ) {}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize( Container parent ) {
|
||||
return dockIcon.getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension minimumLayoutSize( Container parent ) {
|
||||
return dockIcon.getMinimumSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer( Container parent ) {
|
||||
Insets insets = parent.getInsets();
|
||||
|
||||
// dock icon
|
||||
dockIcon.setBounds( insets.left, insets.top,
|
||||
parent.getWidth() - insets.left - insets.right,
|
||||
parent.getHeight() - insets.top - insets.bottom );
|
||||
|
||||
// close button in upper right corner
|
||||
Dimension cSize = UIScale.scale( closeSize );
|
||||
closeButton.setBounds( parent.getWidth() - cSize.width, 0, cSize.width, cSize.height );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import javax.swing.DefaultDesktopManager;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicDesktopPaneUI;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JDesktopPane}.
|
||||
*
|
||||
* <!-- BasicDesktopPaneUI -->
|
||||
*
|
||||
* @uiDefault Desktop.background Color
|
||||
* @uiDefault Desktop.minOnScreenInsets Insets
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatDesktopPaneUI
|
||||
extends BasicDesktopPaneUI
|
||||
{
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatDesktopPaneUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDesktopManager() {
|
||||
desktopManager = desktop.getDesktopManager();
|
||||
if( desktopManager == null ) {
|
||||
desktopManager = new FlatDesktopManager();
|
||||
desktop.setDesktopManager( desktopManager );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatDesktopManager -------------------------------------------
|
||||
|
||||
private class FlatDesktopManager
|
||||
extends DefaultDesktopManager
|
||||
implements UIResource
|
||||
{
|
||||
@Override
|
||||
public void iconifyFrame( JInternalFrame f ) {
|
||||
super.iconifyFrame( f );
|
||||
|
||||
((FlatDesktopIconUI)f.getDesktopIcon().getUI()).updateDockIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,7 @@ public class FlatEditorPaneUI
|
||||
// and subtract 1px border line width.
|
||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||
// issues. E.g. at scale factor 1.5 the first returns 4, but the second 3.
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
size.width = Math.max( size.width, scale( minimumWidth ) - (scale( 1 ) * 2) );
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -50,9 +50,10 @@ public class FlatEmptyBorder
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
insets.left = scale( left );
|
||||
boolean leftToRight = left == right || c.getComponentOrientation().isLeftToRight();
|
||||
insets.left = scale( leftToRight ? left : right );
|
||||
insets.top = scale( top );
|
||||
insets.right = scale( right );
|
||||
insets.right = scale( leftToRight ? right : left );
|
||||
insets.bottom = scale( bottom );
|
||||
return insets;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,76 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JFileChooser}.
|
||||
*
|
||||
* TODO document used UI defaults of superclass
|
||||
* <!-- BasicFileChooserUI -->
|
||||
*
|
||||
* @uiDefault FileView.directoryIcon Icon
|
||||
* @uiDefault FileView.fileIcon Icon
|
||||
* @uiDefault FileView.computerIcon Icon
|
||||
* @uiDefault FileView.hardDriveIcon Icon
|
||||
* @uiDefault FileView.floppyDriveIcon Icon
|
||||
*
|
||||
* @uiDefault FileChooser.newFolderIcon Icon
|
||||
* @uiDefault FileChooser.upFolderIcon Icon
|
||||
* @uiDefault FileChooser.homeFolderIcon Icon
|
||||
* @uiDefault FileChooser.detailsViewIcon Icon
|
||||
* @uiDefault FileChooser.listViewIcon Icon
|
||||
* @uiDefault FileChooser.viewMenuIcon Icon
|
||||
*
|
||||
* @uiDefault FileChooser.usesSingleFilePane boolean
|
||||
* @uiDefault FileChooser.readOnly boolean if true, "New Folder" is disabled
|
||||
*
|
||||
* @uiDefault FileChooser.newFolderErrorText String
|
||||
* @uiDefault FileChooser.newFolderErrorSeparator String
|
||||
* @uiDefault FileChooser.newFolderParentDoesntExistTitleText String
|
||||
* @uiDefault FileChooser.newFolderParentDoesntExistText String
|
||||
* @uiDefault FileChooser.fileDescriptionText String
|
||||
* @uiDefault FileChooser.directoryDescriptionText String
|
||||
* @uiDefault FileChooser.saveButtonText String
|
||||
* @uiDefault FileChooser.openButtonText String
|
||||
* @uiDefault FileChooser.saveDialogTitleText String
|
||||
* @uiDefault FileChooser.openDialogTitleText String
|
||||
* @uiDefault FileChooser.cancelButtonText String
|
||||
* @uiDefault FileChooser.updateButtonText String
|
||||
* @uiDefault FileChooser.helpButtonText String
|
||||
* @uiDefault FileChooser.directoryOpenButtonText String
|
||||
*
|
||||
* @uiDefault FileChooser.saveButtonMnemonic String
|
||||
* @uiDefault FileChooser.openButtonMnemonic String
|
||||
* @uiDefault FileChooser.cancelButtonMnemonic String
|
||||
* @uiDefault FileChooser.updateButtonMnemonic String
|
||||
* @uiDefault FileChooser.helpButtonMnemonic String
|
||||
* @uiDefault FileChooser.directoryOpenButtonMnemonic String
|
||||
*
|
||||
* @uiDefault FileChooser.saveButtonToolTipText String
|
||||
* @uiDefault FileChooser.openButtonToolTipText String
|
||||
* @uiDefault FileChooser.cancelButtonToolTipText String
|
||||
* @uiDefault FileChooser.updateButtonToolTipText String
|
||||
* @uiDefault FileChooser.helpButtonToolTipText String
|
||||
* @uiDefault FileChooser.directoryOpenButtonToolTipText String
|
||||
*
|
||||
* @uiDefault FileChooser.acceptAllFileFilterText String
|
||||
*
|
||||
* <!-- MetalFileChooserUI -->
|
||||
*
|
||||
* @uiDefault FileChooser.lookInLabelMnemonic String
|
||||
* @uiDefault FileChooser.lookInLabelText String
|
||||
* @uiDefault FileChooser.saveInLabelText String
|
||||
* @uiDefault FileChooser.fileNameLabelMnemonic String
|
||||
* @uiDefault FileChooser.fileNameLabelText String
|
||||
* @uiDefault FileChooser.folderNameLabelMnemonic String
|
||||
* @uiDefault FileChooser.folderNameLabelText String
|
||||
* @uiDefault FileChooser.filesOfTypeLabelMnemonic String
|
||||
* @uiDefault FileChooser.filesOfTypeLabelText String
|
||||
* @uiDefault FileChooser.upFolderToolTipText String
|
||||
* @uiDefault FileChooser.upFolderAccessibleName String
|
||||
* @uiDefault FileChooser.homeFolderToolTipText String
|
||||
* @uiDefault FileChooser.homeFolderAccessibleName String
|
||||
* @uiDefault FileChooser.newFolderToolTipText String
|
||||
* @uiDefault FileChooser.newFolderAccessibleName String
|
||||
* @uiDefault FileChooser.listViewButtonToolTipText String
|
||||
* @uiDefault FileChooser.listViewButtonAccessibleName String
|
||||
* @uiDefault FileChooser.detailsViewButtonToolTipText String
|
||||
* @uiDefault FileChooser.detailsViewButtonAccessibleName String
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@@ -39,10 +39,12 @@ import javax.swing.plaf.ComponentUI;
|
||||
*
|
||||
* <!-- FlatTextFieldUI -->
|
||||
*
|
||||
* @uiDefault TextComponent.arc int
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault FormattedTextField.placeholderForeground Color
|
||||
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.LayoutManager;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF internal frame title bar.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatInternalFrameTitlePane
|
||||
extends BasicInternalFrameTitlePane
|
||||
{
|
||||
private JLabel titleLabel;
|
||||
private JPanel buttonPanel;
|
||||
|
||||
public FlatInternalFrameTitlePane( JInternalFrame f ) {
|
||||
super( f );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
LookAndFeel.installBorder( this, "InternalFrameTitlePane.border" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
return new FlatPropertyChangeHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutManager createLayout() {
|
||||
return new BorderLayout( UIScale.scale( 4 ), 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createButtons() {
|
||||
super.createButtons();
|
||||
|
||||
iconButton.setContentAreaFilled( false );
|
||||
maxButton.setContentAreaFilled( false );
|
||||
closeButton.setContentAreaFilled( false );
|
||||
|
||||
Border emptyBorder = BorderFactory.createEmptyBorder();
|
||||
iconButton.setBorder( emptyBorder );
|
||||
maxButton.setBorder( emptyBorder );
|
||||
closeButton.setBorder( emptyBorder );
|
||||
|
||||
updateButtonsVisibility();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addSubComponents() {
|
||||
titleLabel = new JLabel( frame.getTitle() );
|
||||
titleLabel.setFont( FlatUIUtils.nonUIResource( getFont() ) );
|
||||
titleLabel.setMinimumSize( new Dimension( UIScale.scale( 32 ), 1 ) );
|
||||
updateFrameIcon();
|
||||
updateColors();
|
||||
|
||||
buttonPanel = new JPanel();
|
||||
buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS ) );
|
||||
buttonPanel.setOpaque( false );
|
||||
|
||||
buttonPanel.add( iconButton );
|
||||
buttonPanel.add( maxButton );
|
||||
buttonPanel.add( closeButton );
|
||||
|
||||
add( titleLabel, BorderLayout.CENTER );
|
||||
add( buttonPanel, BorderLayout.LINE_END );
|
||||
}
|
||||
|
||||
private void updateFrameIcon() {
|
||||
Icon frameIcon = frame.getFrameIcon();
|
||||
if( frameIcon == UIManager.getIcon( "InternalFrame.icon" ) )
|
||||
frameIcon = null;
|
||||
titleLabel.setIcon( frameIcon );
|
||||
}
|
||||
|
||||
private void updateColors() {
|
||||
Color background = FlatUIUtils.nonUIResource( frame.isSelected() ? selectedTitleColor : notSelectedTitleColor );
|
||||
Color foreground = FlatUIUtils.nonUIResource( frame.isSelected() ? selectedTextColor : notSelectedTextColor );
|
||||
|
||||
titleLabel.setForeground( foreground );
|
||||
iconButton.setBackground( background );
|
||||
iconButton.setForeground( foreground );
|
||||
maxButton.setBackground( background );
|
||||
maxButton.setForeground( foreground );
|
||||
closeButton.setBackground( background );
|
||||
closeButton.setForeground( foreground );
|
||||
}
|
||||
|
||||
private void updateButtonsVisibility() {
|
||||
iconButton.setVisible( frame.isIconifiable() );
|
||||
maxButton.setVisible( frame.isMaximizable() );
|
||||
closeButton.setVisible( frame.isClosable() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing because FlatLaf internal frames do not have system menus.
|
||||
*/
|
||||
@Override
|
||||
protected void assembleSystemMenu() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing because FlatLaf internal frames do not have system menus.
|
||||
*/
|
||||
@Override
|
||||
protected void showSystemMenu() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent( Graphics g ) {
|
||||
paintTitleBackground( g );
|
||||
}
|
||||
|
||||
//---- class FlatPropertyChangeHandler ------------------------------------
|
||||
|
||||
private class FlatPropertyChangeHandler
|
||||
extends PropertyChangeHandler
|
||||
{
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case JInternalFrame.TITLE_PROPERTY:
|
||||
titleLabel.setText( frame.getTitle() );
|
||||
break;
|
||||
|
||||
case JInternalFrame.FRAME_ICON_PROPERTY:
|
||||
updateFrameIcon();
|
||||
break;
|
||||
|
||||
case JInternalFrame.IS_SELECTED_PROPERTY:
|
||||
updateColors();
|
||||
break;
|
||||
|
||||
case "iconable":
|
||||
case "maximizable":
|
||||
case "closable":
|
||||
updateButtonsVisibility();
|
||||
enableActions();
|
||||
revalidate();
|
||||
repaint();
|
||||
|
||||
// do not invoke super.propertyChange() because this adds/removes the buttons
|
||||
return;
|
||||
|
||||
case "componentOrientation":
|
||||
applyComponentOrientation( frame.getComponentOrientation() );
|
||||
break;
|
||||
}
|
||||
|
||||
super.propertyChange( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JInternalFrame;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}.
|
||||
*
|
||||
* <!-- BasicInternalFrameUI -->
|
||||
*
|
||||
* @uiDefault control Color
|
||||
* @uiDefault InternalFrame.icon Icon
|
||||
* @uiDefault InternalFrame.border Border
|
||||
* @uiDefault InternalFrame.layoutTitlePaneAtOrigin boolean
|
||||
*
|
||||
* <!-- BasicInternalFrameTitlePane -->
|
||||
*
|
||||
* @uiDefault InternalFrame.titleFont Font
|
||||
* @uiDefault InternalFrame.icon Icon
|
||||
* @uiDefault InternalFrame.maximizeIcon Icon
|
||||
* @uiDefault InternalFrame.minimizeIcon Icon
|
||||
* @uiDefault InternalFrame.iconifyIcon Icon
|
||||
* @uiDefault InternalFrame.closeIcon Icon
|
||||
* @uiDefault InternalFrame.activeTitleBackground Color
|
||||
* @uiDefault InternalFrame.activeTitleForeground Color
|
||||
* @uiDefault InternalFrame.inactiveTitleBackground Color
|
||||
* @uiDefault InternalFrame.inactiveTitleForeground Color
|
||||
* @uiDefault InternalFrame.closeButtonToolTip String
|
||||
* @uiDefault InternalFrame.iconButtonToolTip String
|
||||
* @uiDefault InternalFrame.restoreButtonToolTip String
|
||||
* @uiDefault InternalFrame.maxButtonToolTip String
|
||||
* @uiDefault InternalFrameTitlePane.closeButtonText String
|
||||
* @uiDefault InternalFrameTitlePane.minimizeButtonText String
|
||||
* @uiDefault InternalFrameTitlePane.restoreButtonText String
|
||||
* @uiDefault InternalFrameTitlePane.maximizeButtonText String
|
||||
* @uiDefault InternalFrameTitlePane.moveButtonText String
|
||||
* @uiDefault InternalFrameTitlePane.sizeButtonText String
|
||||
* @uiDefault InternalFrameTitlePane.closeButton.mnemonic Integer
|
||||
* @uiDefault InternalFrameTitlePane.minimizeButton.mnemonic Integer
|
||||
* @uiDefault InternalFrameTitlePane.restoreButton.mnemonic Integer
|
||||
* @uiDefault InternalFrameTitlePane.maximizeButton.mnemonic Integer
|
||||
* @uiDefault InternalFrameTitlePane.moveButton.mnemonic Integer
|
||||
* @uiDefault InternalFrameTitlePane.sizeButton.mnemonic Integer
|
||||
*
|
||||
* <!-- FlatInternalFrameUI -->
|
||||
*
|
||||
* @uiDefault InternalFrame.activeBorderColor Color
|
||||
* @uiDefault InternalFrame.inactiveBorderColor Color
|
||||
* @uiDefault InternalFrame.borderLineWidth int
|
||||
* @uiDefault InternalFrame.borderMargins Insets
|
||||
*
|
||||
* <!-- FlatInternalFrameTitlePane -->
|
||||
*
|
||||
* @uiDefault InternalFrameTitlePane.border Border
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatInternalFrameUI
|
||||
extends BasicInternalFrameUI
|
||||
{
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatInternalFrameUI( (JInternalFrame) c );
|
||||
}
|
||||
|
||||
public FlatInternalFrameUI( JInternalFrame b ) {
|
||||
super( b );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
LookAndFeel.installProperty( frame, "opaque", false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createNorthPane( JInternalFrame w ) {
|
||||
return new FlatInternalFrameTitlePane( w );
|
||||
}
|
||||
|
||||
//---- class FlatInternalFrameBorder --------------------------------------
|
||||
|
||||
public static class FlatInternalFrameBorder
|
||||
extends FlatEmptyBorder
|
||||
{
|
||||
private final Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
||||
private final Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
||||
private final int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
||||
|
||||
public FlatInternalFrameBorder() {
|
||||
super( UIManager.getInsets( "InternalFrame.borderMargins" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) {
|
||||
insets.left = scale( Math.min( borderLineWidth, left ) );
|
||||
insets.top = scale( Math.min( borderLineWidth, top ) );
|
||||
insets.right = scale( Math.min( borderLineWidth, right ) );
|
||||
insets.bottom = scale( Math.min( borderLineWidth, bottom ) );
|
||||
return insets;
|
||||
}
|
||||
|
||||
return super.getBorderInsets( c, insets );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
JInternalFrame f = (JInternalFrame) c;
|
||||
|
||||
Insets insets = getBorderInsets( c );
|
||||
float lineWidth = scale( (float) borderLineWidth );
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
g2.setColor( f.isSelected() ? activeBorderColor : inactiveBorderColor );
|
||||
g2.fill( FlatUIUtils.createRectangle(
|
||||
x + insets.left - lineWidth,
|
||||
y + insets.top - lineWidth,
|
||||
width - insets.left - insets.right + (lineWidth * 2),
|
||||
height - insets.top - insets.bottom + (lineWidth * 2),
|
||||
lineWidth ) );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,14 @@ import java.awt.Color;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.plaf.basic.BasicLabelUI;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -77,6 +79,51 @@ public class FlatLabelUI
|
||||
defaults_initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installComponents( JLabel c ) {
|
||||
super.installComponents( c );
|
||||
|
||||
// update HTML renderer if necessary
|
||||
updateHTMLRenderer( c, c.getText(), false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
String name = e.getPropertyName();
|
||||
if( name == "text" || name == "font" || name == "foreground" ) {
|
||||
JLabel label = (JLabel) e.getSource();
|
||||
updateHTMLRenderer( label, label.getText(), true );
|
||||
} else
|
||||
super.propertyChange( e );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether text contains HTML headings and adds a special CSS rule to
|
||||
* re-calculate heading font sizes based on current component font size.
|
||||
*/
|
||||
static void updateHTMLRenderer( JComponent c, String text, boolean always ) {
|
||||
if( BasicHTML.isHTMLString( text ) &&
|
||||
c.getClientProperty( "html.disable" ) != Boolean.TRUE &&
|
||||
text.contains( "<h" ) &&
|
||||
(text.contains( "<h1" ) || text.contains( "<h2" ) || text.contains( "<h3" ) ||
|
||||
text.contains( "<h4" ) || text.contains( "<h5" ) || text.contains( "<h6" )) )
|
||||
{
|
||||
int headIndex = text.indexOf( "<head>" );
|
||||
|
||||
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
|
||||
if( headIndex < 0 )
|
||||
style = "<head>" + style + "</head>";
|
||||
|
||||
int insertIndex = headIndex >= 0 ? (headIndex + "<head>".length()) : "<html>".length();
|
||||
text = text.substring( 0, insertIndex )
|
||||
+ style
|
||||
+ text.substring( insertIndex );
|
||||
} else if( !always )
|
||||
return; // not necessary to invoke BasicHTML.updateRenderer()
|
||||
|
||||
BasicHTML.updateRenderer( c, text );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintEnabledText( JLabel l, Graphics g, String s, int textX, int textY ) {
|
||||
int mnemIndex = FlatLaf.isShowMnemonics() ? l.getDisplayedMnemonicIndex() : -1;
|
||||
|
||||
@@ -26,9 +26,9 @@ import java.awt.Insets;
|
||||
/**
|
||||
* Line border for various components.
|
||||
*
|
||||
* Paints a scaled 1px thick line around the component.
|
||||
* The line thickness is not included in the border insets.
|
||||
* The insets should be at least 1,1,1,1.
|
||||
* Paints a scaled (usually 1px thick) line around the component.
|
||||
* The line thickness is not added to the border insets.
|
||||
* The insets should be at least have line thickness (usually 1,1,1,1).
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -36,10 +36,16 @@ public class FlatLineBorder
|
||||
extends FlatEmptyBorder
|
||||
{
|
||||
private final Color lineColor;
|
||||
private final float lineThickness;
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor ) {
|
||||
this( insets, lineColor, 1f );
|
||||
}
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness ) {
|
||||
super( insets );
|
||||
this.lineColor = lineColor;
|
||||
this.lineThickness = lineThickness;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,7 +54,7 @@ public class FlatLineBorder
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
g2.setColor( lineColor );
|
||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0f, scale( 1f ), 0f );
|
||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, 0f, scale( lineThickness ), 0f );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* Cell border for {@link javax.swing.DefaultListCellRenderer}
|
||||
* (used by {@link javax.swing.JList}).
|
||||
* <p>
|
||||
* Uses separate cell margins from UI defaults to allow easy customizing.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatListCellBorder
|
||||
extends FlatLineBorder
|
||||
{
|
||||
final boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||
|
||||
protected FlatListCellBorder() {
|
||||
super( UIManager.getInsets( "List.cellMargins" ), UIManager.getColor( "List.cellFocusColor" ) );
|
||||
}
|
||||
|
||||
//---- class Default ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Border for unselected cell that uses margins, but does not paint focus indicator border.
|
||||
*/
|
||||
public static class Default
|
||||
extends FlatListCellBorder
|
||||
{
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
// do not paint focus indicator border
|
||||
}
|
||||
}
|
||||
|
||||
//---- class Focused ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Border for focused unselected cell that uses margins and paints focus indicator border.
|
||||
*/
|
||||
public static class Focused
|
||||
extends FlatListCellBorder
|
||||
{
|
||||
}
|
||||
|
||||
//---- class Selected -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* Border for selected cell that uses margins and paints focus indicator border
|
||||
* if enabled (List.showCellFocusIndicator=true) and exactly one item is selected.
|
||||
*/
|
||||
public static class Selected
|
||||
extends FlatListCellBorder
|
||||
{
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( !showCellFocusIndicator )
|
||||
return;
|
||||
|
||||
// paint focus indicator border only if exactly one item is selected
|
||||
JList<?> list = (JList<?>) SwingUtilities.getAncestorOfClass( JList.class, c );
|
||||
if( list != null && list.getMinSelectionIndex() == list.getMaxSelectionIndex() )
|
||||
return;
|
||||
|
||||
super.paintBorder( c, g, x, y, width, height );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,12 @@ import javax.swing.plaf.basic.BasicListUI;
|
||||
* @uiDefault List.selectionInactiveBackground Color
|
||||
* @uiDefault List.selectionInactiveForeground Color
|
||||
*
|
||||
* <!-- FlatListCellBorder -->
|
||||
*
|
||||
* @uiDefault List.cellMargins Insets
|
||||
* @uiDefault List.cellFocusColor Color
|
||||
* @uiDefault List.showCellFocusIndicator boolean
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatListUI
|
||||
@@ -75,7 +81,7 @@ public class FlatListUI
|
||||
selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" );
|
||||
selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" );
|
||||
|
||||
toggleSelectionColors( list.hasFocus() );
|
||||
toggleSelectionColors();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,13 +100,13 @@ public class FlatListUI
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {
|
||||
super.focusGained( e );
|
||||
toggleSelectionColors( true );
|
||||
toggleSelectionColors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
super.focusLost( e );
|
||||
toggleSelectionColors( false );
|
||||
toggleSelectionColors();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -114,8 +120,8 @@ public class FlatListUI
|
||||
* already used in applications. Then either the inactive colors are not used,
|
||||
* or the application has to be changed to extend a FlatLaf renderer.
|
||||
*/
|
||||
private void toggleSelectionColors( boolean focused ) {
|
||||
if( focused ) {
|
||||
private void toggleSelectionColors() {
|
||||
if( FlatUIUtils.isPermanentFocusOwner( list ) ) {
|
||||
if( list.getSelectionBackground() == selectionInactiveBackground )
|
||||
list.setSelectionBackground( selectionBackground );
|
||||
if( list.getSelectionForeground() == selectionInactiveForeground )
|
||||
|
||||
@@ -29,13 +29,26 @@ import javax.swing.plaf.basic.BasicBorders;
|
||||
public class FlatMarginBorder
|
||||
extends BasicBorders.MarginBorder
|
||||
{
|
||||
private final int left, right, top, bottom;
|
||||
|
||||
public FlatMarginBorder() {
|
||||
left = right = top = bottom = 0;
|
||||
}
|
||||
|
||||
public FlatMarginBorder( Insets insets ) {
|
||||
left = insets.left;
|
||||
top = insets.top;
|
||||
right = insets.right;
|
||||
bottom = insets.bottom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
insets = super.getBorderInsets( c, insets );
|
||||
insets.top = scale( insets.top );
|
||||
insets.left = scale( insets.left );
|
||||
insets.bottom = scale( insets.bottom );
|
||||
insets.right = scale( insets.right );
|
||||
insets.top = scale( insets.top + top );
|
||||
insets.left = scale( insets.left + left );
|
||||
insets.bottom = scale( insets.bottom + bottom );
|
||||
insets.right = scale( insets.right + right );
|
||||
return insets;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Component;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* Border for {@link javax.swing.JMenu}, {@link javax.swing.JMenuItem},
|
||||
* {@link javax.swing.JCheckBoxMenuItem} and {@link javax.swing.JRadioButtonMenuItem}.
|
||||
*
|
||||
* @uiDefault MenuBar.itemMargins Insets
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatMenuItemBorder
|
||||
extends FlatMarginBorder
|
||||
{
|
||||
private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" );
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( c.getParent() instanceof JMenuBar ) {
|
||||
insets.top = scale( menuBarItemMargins.top );
|
||||
insets.left = scale( menuBarItemMargins.left );
|
||||
insets.bottom = scale( menuBarItemMargins.bottom + 1 );
|
||||
insets.right = scale( menuBarItemMargins.right );
|
||||
return insets;
|
||||
} else
|
||||
return super.getBorderInsets( c, insets );
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,18 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuItem}.
|
||||
@@ -74,4 +82,26 @@ public class FlatMenuItemUI
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
}
|
||||
|
||||
public static void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect,
|
||||
String text, Color disabledForeground, Color selectionForeground )
|
||||
{
|
||||
FontMetrics fm = menuItem.getFontMetrics( menuItem.getFont() );
|
||||
int mnemonicIndex = FlatLaf.isShowMnemonics() ? menuItem.getDisplayedMnemonicIndex() : -1;
|
||||
|
||||
ButtonModel model = menuItem.getModel();
|
||||
g.setColor( !model.isEnabled()
|
||||
? disabledForeground
|
||||
: (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())
|
||||
? selectionForeground
|
||||
: menuItem.getForeground()) );
|
||||
|
||||
FlatUIUtils.drawStringUnderlineCharAt( menuItem, g, text, mnemonicIndex,
|
||||
textRect.x, textRect.y + fm.getAscent() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,17 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicMenuUI;
|
||||
|
||||
@@ -48,11 +57,17 @@ import javax.swing.plaf.basic.BasicMenuUI;
|
||||
* @uiDefault Menu.useMenuBarBackgroundForTopLevel boolean default is false
|
||||
* @uiDefault MenuBar.background Color used if Menu.useMenuBarBackgroundForTopLevel is true
|
||||
*
|
||||
* <!-- FlatMenuUI -->
|
||||
*
|
||||
* @uiDefault MenuBar.hoverBackground Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatMenuUI
|
||||
extends BasicMenuUI
|
||||
{
|
||||
private Color hoverBackground;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatMenuUI();
|
||||
}
|
||||
@@ -61,10 +76,21 @@ public class FlatMenuUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
menuItem.setRolloverEnabled( true );
|
||||
|
||||
hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
|
||||
|
||||
// scale
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
hoverBackground = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale defaultTextIconGap again if iconTextGap property has changed.
|
||||
*/
|
||||
@@ -77,4 +103,46 @@ public class FlatMenuUI
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MouseInputListener createMouseInputListener( JComponent c ) {
|
||||
return new BasicMenuUI.MouseInputHandler() {
|
||||
@Override
|
||||
public void mouseEntered( MouseEvent e ) {
|
||||
super.mouseEntered( e );
|
||||
rollover( e, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited( MouseEvent e ) {
|
||||
super.mouseExited( e );
|
||||
rollover( e, false );
|
||||
}
|
||||
|
||||
private void rollover( MouseEvent e, boolean rollover ) {
|
||||
JMenu menu = (JMenu) e.getSource();
|
||||
if( menu.isTopLevelMenu() && menu.isRolloverEnabled() ) {
|
||||
menu.getModel().setRollover( rollover );
|
||||
menu.repaint();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g, JMenuItem menuItem, Color bgColor ) {
|
||||
ButtonModel model = menuItem.getModel();
|
||||
if( model.isArmed() || model.isSelected() ) {
|
||||
super.paintBackground( g, menuItem, bgColor );
|
||||
} else if( model.isRollover() && model.isEnabled() && ((JMenu)menuItem).isTopLevelMenu() ) {
|
||||
FlatUIUtils.setColor( g, hoverBackground, menuItem.getBackground() );
|
||||
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
|
||||
} else
|
||||
super.paintBackground( g, menuItem, bgColor );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,20 +35,19 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JOptionPane}.
|
||||
*
|
||||
* <!-- BasicOptionPaneUI -->
|
||||
*
|
||||
* @uiDefault OptionPane.font Font unused
|
||||
* @uiDefault OptionPane.background Color
|
||||
* @uiDefault OptionPane.foreground Color unused
|
||||
* @uiDefault OptionPane.border Border
|
||||
* @uiDefault OptionPane.messageAreaBorder Border
|
||||
* @uiDefault OptionPane.buttonAreaBorder Border
|
||||
* @uiDefault OptionPane.messageForeground Color
|
||||
* @uiDefault OptionPane.messageFont Font
|
||||
* @uiDefault OptionPane.buttonFont Font
|
||||
* @uiDefault OptionPane.messageForeground Color optional; defaults to Label.foreground
|
||||
* @uiDefault OptionPane.messageFont Font optional; defaults to Label.font
|
||||
* @uiDefault OptionPane.buttonFont Font optional; defaults to Button.font
|
||||
*
|
||||
* @uiDefault OptionPane.minimumSize Dimension
|
||||
* @uiDefault OptionPane.maxCharactersPerLine int
|
||||
* @uiDefault OptionPane.iconMessageGap int
|
||||
* @uiDefault OptionPane.messagePadding int
|
||||
* @uiDefault OptionPane.buttonPadding int
|
||||
* @uiDefault OptionPane.buttonMinimumWidth int -1=disabled
|
||||
* @uiDefault OptionPane.sameSizeButtons boolean if true, gives all buttons same size
|
||||
@@ -61,6 +60,25 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault OptionPane.questionIcon Icon
|
||||
* @uiDefault OptionPane.warningIcon Icon
|
||||
*
|
||||
* @uiDefault OptionPane.okButtonText String
|
||||
* @uiDefault OptionPane.okButtonMnemonic String
|
||||
* @uiDefault OptionPane.okIcon Icon
|
||||
* @uiDefault OptionPane.cancelButtonText String
|
||||
* @uiDefault OptionPane.cancelButtonMnemonic String
|
||||
* @uiDefault OptionPane.cancelIcon Icon
|
||||
* @uiDefault OptionPane.yesButtonText String
|
||||
* @uiDefault OptionPane.yesButtonMnemonic String
|
||||
* @uiDefault OptionPane.yesIcon Icon
|
||||
* @uiDefault OptionPane.noButtonText String
|
||||
* @uiDefault OptionPane.noButtonMnemonic String
|
||||
* @uiDefault OptionPane.noIcon Icon
|
||||
*
|
||||
* <!-- FlatOptionPaneUI -->
|
||||
*
|
||||
* @uiDefault OptionPane.iconMessageGap int
|
||||
* @uiDefault OptionPane.messagePadding int
|
||||
* @uiDefault OptionPane.maxCharactersPerLine int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatOptionPaneUI
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicPanelUI;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JPanel}.
|
||||
*
|
||||
* <!-- BasicPanelUI -->
|
||||
*
|
||||
* @uiDefault Panel.font Font unused
|
||||
* @uiDefault Panel.background Color only used if opaque
|
||||
* @uiDefault Panel.foreground Color
|
||||
* @uiDefault Panel.border Border
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatPanelUI
|
||||
extends BasicPanelUI
|
||||
{
|
||||
private static ComponentUI instance;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
if( instance == null )
|
||||
instance = new FlatPanelUI();
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -20,15 +20,21 @@ import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicPasswordFieldUI;
|
||||
import javax.swing.text.Caret;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JPasswordField}.
|
||||
@@ -51,22 +57,28 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
*
|
||||
* <!-- FlatPasswordFieldUI -->
|
||||
*
|
||||
* @uiDefault TextComponent.arc int
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault PasswordField.placeholderForeground Color
|
||||
* @uiDefault PasswordField.capsLockIcon Icon
|
||||
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatPasswordFieldUI
|
||||
extends BasicPasswordFieldUI
|
||||
{
|
||||
protected int arc;
|
||||
protected int focusWidth;
|
||||
protected int minimumWidth;
|
||||
protected boolean isIntelliJTheme;
|
||||
protected Color placeholderForeground;
|
||||
protected Icon capsLockIcon;
|
||||
|
||||
private FocusListener focusListener;
|
||||
private KeyListener capsLockListener;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatPasswordFieldUI();
|
||||
@@ -76,15 +88,13 @@ public class FlatPasswordFieldUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
// use other echoChar on Mac because the default is too large in SF font
|
||||
if( SystemInfo.IS_MAC )
|
||||
LookAndFeel.installProperty( getComponent(), "echoChar", '\u2022' );
|
||||
|
||||
String prefix = getPropertyPrefix();
|
||||
arc = UIManager.getInt( "TextComponent.arc" );
|
||||
focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
|
||||
capsLockIcon = UIManager.getIcon( "PasswordField.capsLockIcon" );
|
||||
|
||||
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
|
||||
|
||||
@@ -96,6 +106,7 @@ public class FlatPasswordFieldUI
|
||||
super.uninstallDefaults();
|
||||
|
||||
placeholderForeground = null;
|
||||
capsLockIcon = null;
|
||||
|
||||
MigLayoutVisualPadding.uninstall( getComponent() );
|
||||
}
|
||||
@@ -105,7 +116,23 @@ public class FlatPasswordFieldUI
|
||||
super.installListeners();
|
||||
|
||||
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
|
||||
capsLockListener = new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed( KeyEvent e ) {
|
||||
repaint( e );
|
||||
}
|
||||
@Override
|
||||
public void keyReleased( KeyEvent e ) {
|
||||
repaint( e );
|
||||
}
|
||||
private void repaint( KeyEvent e ) {
|
||||
if( e.getKeyCode() == KeyEvent.VK_CAPS_LOCK )
|
||||
e.getComponent().repaint();
|
||||
}
|
||||
};
|
||||
|
||||
getComponent().addFocusListener( focusListener );
|
||||
getComponent().addKeyListener( capsLockListener );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,7 +140,14 @@ public class FlatPasswordFieldUI
|
||||
super.uninstallListeners();
|
||||
|
||||
getComponent().removeFocusListener( focusListener );
|
||||
getComponent().removeKeyListener( capsLockListener );
|
||||
focusListener = null;
|
||||
capsLockListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Caret createCaret() {
|
||||
return new FlatCaret( UIManager.getString( "TextComponent.selectAllOnFocusPolicy" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -126,11 +160,23 @@ public class FlatPasswordFieldUI
|
||||
|
||||
@Override
|
||||
protected void paintSafely( Graphics g ) {
|
||||
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth, isIntelliJTheme );
|
||||
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth, arc, isIntelliJTheme );
|
||||
FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
|
||||
paintCapsLock( g );
|
||||
super.paintSafely( g );
|
||||
}
|
||||
|
||||
protected void paintCapsLock( Graphics g ) {
|
||||
JTextComponent c = getComponent();
|
||||
if( !FlatUIUtils.isPermanentFocusOwner( c ) ||
|
||||
!Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK ) )
|
||||
return;
|
||||
|
||||
int y = (c.getHeight() - capsLockIcon.getIconHeight()) / 2;
|
||||
int x = c.getWidth() - capsLockIcon.getIconWidth() - y;
|
||||
capsLockIcon.paintIcon( c, g, x, y );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g ) {
|
||||
// background is painted elsewhere
|
||||
@@ -147,6 +193,7 @@ public class FlatPasswordFieldUI
|
||||
}
|
||||
|
||||
private Dimension applyMinimumWidth( Dimension size, JComponent c ) {
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
|
||||
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
|
||||
return size;
|
||||
|
||||
@@ -16,7 +16,12 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Border for {@link javax.swing.JPopupMenu}.
|
||||
@@ -33,4 +38,18 @@ public class FlatPopupMenuBorder
|
||||
super( UIManager.getInsets( "PopupMenu.borderInsets" ),
|
||||
UIManager.getColor( "PopupMenu.borderColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( c instanceof Container &&
|
||||
((Container)c).getComponentCount() > 0 &&
|
||||
((Container)c).getComponent( 0 ) instanceof JScrollPane )
|
||||
{
|
||||
// e.g. for combobox popups
|
||||
insets.left = insets.top = insets.right = insets.bottom = UIScale.scale( 1 );
|
||||
return insets;
|
||||
}
|
||||
|
||||
return super.getBorderInsets( c, insets );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
@@ -23,6 +24,7 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
@@ -60,6 +62,8 @@ public class FlatProgressBarUI
|
||||
protected Dimension horizontalSize;
|
||||
protected Dimension verticalSize;
|
||||
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatProgressBarUI();
|
||||
}
|
||||
@@ -75,11 +79,35 @@ public class FlatProgressBarUI
|
||||
verticalSize = UIManager.getDimension( "ProgressBar.verticalSize" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners() {
|
||||
super.installListeners();
|
||||
|
||||
propertyChangeListener = e -> {
|
||||
switch( e.getPropertyName() ) {
|
||||
case PROGRESS_BAR_LARGE_HEIGHT:
|
||||
case PROGRESS_BAR_SQUARE:
|
||||
progressBar.revalidate();
|
||||
progressBar.repaint();
|
||||
break;
|
||||
}
|
||||
};
|
||||
progressBar.addPropertyChangeListener( propertyChangeListener );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners() {
|
||||
super.uninstallListeners();
|
||||
|
||||
progressBar.removePropertyChangeListener( propertyChangeListener );
|
||||
propertyChangeListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
Dimension size = super.getPreferredSize( c );
|
||||
|
||||
if( progressBar.isStringPainted() ) {
|
||||
if( progressBar.isStringPainted() || clientPropertyBoolean( c, PROGRESS_BAR_LARGE_HEIGHT, false ) ) {
|
||||
// recalculate progress height/width to make it smaller
|
||||
Insets insets = progressBar.getInsets();
|
||||
FontMetrics fm = progressBar.getFontMetrics( progressBar.getFont() );
|
||||
@@ -122,7 +150,9 @@ public class FlatProgressBarUI
|
||||
return;
|
||||
|
||||
boolean horizontal = (progressBar.getOrientation() == JProgressBar.HORIZONTAL);
|
||||
int arc = Math.min( UIScale.scale( this.arc ), horizontal ? height : width );
|
||||
int arc = clientPropertyBoolean( c, PROGRESS_BAR_SQUARE, false )
|
||||
? 0
|
||||
: Math.min( UIScale.scale( this.arc ), horizontal ? height : width );
|
||||
|
||||
FlatUIUtils.setRenderingHints( (Graphics2D) g );
|
||||
|
||||
@@ -163,4 +193,19 @@ public class FlatProgressBarUI
|
||||
paintString( g, x, y, width, height, amountFull, insets );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAnimationIndex( int newValue ) {
|
||||
super.setAnimationIndex( newValue );
|
||||
|
||||
// On HiDPI screens at 125%, 150% and 175% scaling, it occurs that antialiased painting
|
||||
// may paint one pixel outside of the clipping area. This results in visual artifacts
|
||||
// in indeterminate mode when the progress moves around.
|
||||
// Unfortunately it is not safe to invoke getBox() from here (may throw NPE),
|
||||
// which makes it impractical to get progress box and repaint increased box.
|
||||
// Only solution is to repaint whole progress bar.
|
||||
double systemScaleFactor = UIScale.getSystemScaleFactor( progressBar.getGraphicsConfiguration() );
|
||||
if( (int) systemScaleFactor != systemScaleFactor )
|
||||
progressBar.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;
|
||||
|
||||
@@ -74,4 +77,9 @@ public class FlatRadioButtonMenuItemUI
|
||||
defaultTextIconGap = scale( defaultTextIconGap );
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
|
||||
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,8 @@ public class FlatRadioButtonUI
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
Dimension size = super.getPreferredSize( c );
|
||||
if( size == null )
|
||||
return null;
|
||||
|
||||
// small insets fix
|
||||
int focusWidth = getIconFocusWidth( c );
|
||||
@@ -118,11 +120,13 @@ public class FlatRadioButtonUI
|
||||
|
||||
@Override
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
// fill background even if opaque if
|
||||
// - used as cell renderer (because of selection background)
|
||||
// - if background was explicitly set to a non-UIResource color
|
||||
// fill background even if not opaque if
|
||||
// - contentAreaFilled is true and
|
||||
// - used as cell renderer (because of selection background)
|
||||
// - or if background was explicitly set to a non-UIResource color
|
||||
if( !c.isOpaque() &&
|
||||
(c.getParent() instanceof CellRendererPane || !(c.getBackground() instanceof UIResource)) )
|
||||
((AbstractButton)c).isContentAreaFilled() &&
|
||||
(c.getParent() instanceof CellRendererPane || !(c.getBackground() instanceof UIResource)))
|
||||
{
|
||||
g.setColor( c.getBackground() );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2020 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicRootPaneUI;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JRootPane}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatRootPaneUI
|
||||
extends BasicRootPaneUI
|
||||
{
|
||||
private static ComponentUI instance;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
if( instance == null )
|
||||
instance = new FlatRootPaneUI();
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Component;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
@@ -32,7 +33,7 @@ public class FlatRoundBorder
|
||||
protected final int arc = UIManager.getInt( "Component.arc" );
|
||||
|
||||
@Override
|
||||
protected float getArc() {
|
||||
protected float getArc( Component c ) {
|
||||
return scale( (float) arc );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,11 @@ import java.awt.event.MouseEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Objects;
|
||||
import javax.swing.InputMap;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicScrollBarUI;
|
||||
@@ -127,9 +129,24 @@ public class FlatScrollBarUI
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
|
||||
if( FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS.equals( e.getPropertyName() ) ) {
|
||||
scrollbar.revalidate();
|
||||
scrollbar.repaint();
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS:
|
||||
scrollbar.revalidate();
|
||||
scrollbar.repaint();
|
||||
break;
|
||||
|
||||
case "componentOrientation":
|
||||
// this is missing in BasicScrollBarUI.Handler.propertyChange()
|
||||
InputMap inputMap = (InputMap) UIManager.get( "ScrollBar.ancestorInputMap" );
|
||||
if( !scrollbar.getComponentOrientation().isLeftToRight() ) {
|
||||
InputMap rtlInputMap = (InputMap) UIManager.get( "ScrollBar.ancestorInputMap.RightToLeft" );
|
||||
if( rtlInputMap != null ) {
|
||||
rtlInputMap.setParent( inputMap );
|
||||
inputMap = rtlInputMap;
|
||||
}
|
||||
}
|
||||
SwingUtilities.replaceUIInputMap( scrollbar, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap );
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,22 +14,37 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Smooth scrolling code partly based on code from IntelliJ IDEA Community Edition,
|
||||
* which is licensed under the Apache 2.0 license. Copyright 2000-2016 JetBrains s.r.o.
|
||||
* See: https://github.com/JetBrains/intellij-community/blob/31e1b5a8e43219b9571951bab6457cfb3012e3ef/platform/platform-api/src/com/intellij/ui/components/SmoothScrollPane.java#L141-L185
|
||||
*
|
||||
*/
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.awt.event.ContainerListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.Scrollable;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicScrollPaneUI;
|
||||
@@ -46,6 +61,10 @@ import com.formdev.flatlaf.FlatClientProperties;
|
||||
* @uiDefault ScrollPane.border Border
|
||||
* @uiDefault ScrollPane.viewportBorder Border
|
||||
*
|
||||
* <!-- FlatScrollPaneUI -->
|
||||
*
|
||||
* @uiDefault ScrollPane.smoothScrolling boolean
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatScrollPaneUI
|
||||
@@ -90,6 +109,130 @@ public class FlatScrollPaneUI
|
||||
handler = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MouseWheelListener createMouseWheelListener() {
|
||||
return new BasicScrollPaneUI.MouseWheelHandler() {
|
||||
@Override
|
||||
public void mouseWheelMoved( MouseWheelEvent e ) {
|
||||
// Note: Getting UI value "ScrollPane.smoothScrolling" here to allow
|
||||
// applications to turn smooth scrolling on or off at any time
|
||||
// (e.g. in application options dialog).
|
||||
if( UIManager.getBoolean( "ScrollPane.smoothScrolling" ) &&
|
||||
scrollpane.isWheelScrollingEnabled() &&
|
||||
e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL &&
|
||||
e.getPreciseWheelRotation() != 0 &&
|
||||
e.getPreciseWheelRotation() != e.getWheelRotation() )
|
||||
{
|
||||
mouseWheelMovedSmooth( e );
|
||||
} else
|
||||
super.mouseWheelMoved( e );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static final double EPSILON = 1e-5d;
|
||||
|
||||
private void mouseWheelMovedSmooth( MouseWheelEvent e ) {
|
||||
// return if there is no viewport
|
||||
JViewport viewport = scrollpane.getViewport();
|
||||
if( viewport == null )
|
||||
return;
|
||||
|
||||
// find scrollbar to scroll
|
||||
JScrollBar scrollbar = scrollpane.getVerticalScrollBar();
|
||||
if( scrollbar == null || !scrollbar.isVisible() || e.isShiftDown() ) {
|
||||
scrollbar = scrollpane.getHorizontalScrollBar();
|
||||
if( scrollbar == null || !scrollbar.isVisible() )
|
||||
return;
|
||||
}
|
||||
|
||||
// consume event
|
||||
e.consume();
|
||||
|
||||
// get precise wheel rotation
|
||||
double rotation = e.getPreciseWheelRotation();
|
||||
|
||||
// get unit and block increment
|
||||
int unitIncrement;
|
||||
int blockIncrement;
|
||||
int orientation = scrollbar.getOrientation();
|
||||
Component view = viewport.getView();
|
||||
if( view instanceof Scrollable ) {
|
||||
Scrollable scrollable = (Scrollable) view;
|
||||
|
||||
// Use (0, 0) view position to obtain constant unit increment of first item
|
||||
// (which might otherwise be variable on smaller-than-unit scrolling).
|
||||
Rectangle visibleRect = new Rectangle( viewport.getViewSize() );
|
||||
unitIncrement = scrollable.getScrollableUnitIncrement( visibleRect, orientation, 1 );
|
||||
blockIncrement = scrollable.getScrollableBlockIncrement( visibleRect, orientation, 1 );
|
||||
|
||||
if( unitIncrement > 0 ) {
|
||||
// For the case that the first item (e.g. in a list) is larger
|
||||
// than the other items, get the unit increment of the second item
|
||||
// and use the smaller one.
|
||||
if( orientation == SwingConstants.VERTICAL ) {
|
||||
visibleRect.y += unitIncrement;
|
||||
visibleRect.height -= unitIncrement;
|
||||
} else {
|
||||
visibleRect.x += unitIncrement;
|
||||
visibleRect.width -= unitIncrement;
|
||||
}
|
||||
int unitIncrement2 = scrollable.getScrollableUnitIncrement( visibleRect, orientation, 1 );
|
||||
if( unitIncrement2 > 0 )
|
||||
unitIncrement = Math.min( unitIncrement, unitIncrement2 );
|
||||
}
|
||||
} else {
|
||||
int direction = rotation < 0 ? -1 : 1;
|
||||
unitIncrement = scrollbar.getUnitIncrement( direction );
|
||||
blockIncrement = scrollbar.getBlockIncrement( direction );
|
||||
}
|
||||
|
||||
// limit scroll amount (number of units to scroll) for small viewports
|
||||
// (e.g. vertical scrolling in file chooser)
|
||||
int scrollAmount = e.getScrollAmount();
|
||||
int viewportWH = (orientation == SwingConstants.VERTICAL)
|
||||
? viewport.getHeight()
|
||||
: viewport.getWidth();
|
||||
if( unitIncrement * scrollAmount > viewportWH )
|
||||
scrollAmount = Math.max( viewportWH / unitIncrement, 1 );
|
||||
|
||||
// compute relative delta
|
||||
double delta = rotation * scrollAmount * unitIncrement;
|
||||
boolean adjustDelta = Math.abs( rotation ) < (1.0 + EPSILON);
|
||||
double adjustedDelta = adjustDelta
|
||||
? Math.max( -blockIncrement, Math.min( delta, blockIncrement ) )
|
||||
: delta;
|
||||
|
||||
// compute new value
|
||||
int value = scrollbar.getValue();
|
||||
double minDelta = scrollbar.getMinimum() - value;
|
||||
double maxDelta = scrollbar.getMaximum() - scrollbar.getModel().getExtent() - value;
|
||||
double boundedDelta = Math.max( minDelta, Math.min( adjustedDelta, maxDelta ) );
|
||||
int newValue = value + (int) Math.round( boundedDelta );
|
||||
|
||||
// set new value
|
||||
if( newValue != value )
|
||||
scrollbar.setValue( newValue );
|
||||
|
||||
/*debug
|
||||
System.out.println( String.format( "%4d %9f / %4d %4d / %12f %5s %12f / %4d %4d %4d / %12f %12f %12f / %4d",
|
||||
e.getWheelRotation(),
|
||||
e.getPreciseWheelRotation(),
|
||||
unitIncrement,
|
||||
blockIncrement,
|
||||
delta,
|
||||
adjustDelta,
|
||||
adjustedDelta,
|
||||
value,
|
||||
scrollbar.getMinimum(),
|
||||
scrollbar.getMaximum(),
|
||||
minDelta,
|
||||
maxDelta,
|
||||
boundedDelta,
|
||||
newValue ) );
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
return new BasicScrollPaneUI.PropertyChangeHandler() {
|
||||
@@ -97,17 +240,35 @@ public class FlatScrollPaneUI
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
|
||||
if( FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS.equals( e.getPropertyName() ) ) {
|
||||
JScrollBar vsb = scrollpane.getVerticalScrollBar();
|
||||
JScrollBar hsb = scrollpane.getHorizontalScrollBar();
|
||||
if( vsb != null ) {
|
||||
vsb.revalidate();
|
||||
vsb.repaint();
|
||||
}
|
||||
if( hsb != null ) {
|
||||
hsb.revalidate();
|
||||
hsb.repaint();
|
||||
}
|
||||
switch( e.getPropertyName() ) {
|
||||
case FlatClientProperties.SCROLL_BAR_SHOW_BUTTONS:
|
||||
JScrollBar vsb = scrollpane.getVerticalScrollBar();
|
||||
JScrollBar hsb = scrollpane.getHorizontalScrollBar();
|
||||
if( vsb != null ) {
|
||||
vsb.revalidate();
|
||||
vsb.repaint();
|
||||
}
|
||||
if( hsb != null ) {
|
||||
hsb.revalidate();
|
||||
hsb.repaint();
|
||||
}
|
||||
break;
|
||||
|
||||
case ScrollPaneConstants.LOWER_LEFT_CORNER:
|
||||
case ScrollPaneConstants.LOWER_RIGHT_CORNER:
|
||||
case ScrollPaneConstants.UPPER_LEFT_CORNER:
|
||||
case ScrollPaneConstants.UPPER_RIGHT_CORNER:
|
||||
// remove border from buttons added to corners
|
||||
Object corner = e.getNewValue();
|
||||
if( corner instanceof JButton &&
|
||||
((JButton)corner).getBorder() instanceof FlatButtonBorder &&
|
||||
scrollpane.getViewport() != null &&
|
||||
scrollpane.getViewport().getView() instanceof JTable )
|
||||
{
|
||||
((JButton)corner).setBorder( BorderFactory.createEmptyBorder() );
|
||||
((JButton)corner).setFocusable( false );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -201,7 +201,7 @@ public class FlatSliderUI
|
||||
}
|
||||
|
||||
if( coloredTrack != null ) {
|
||||
FlatUIUtils.setColor( g, slider.hasFocus() ? focusColor : (hover ? hoverColor : thumbColor), thumbColor );
|
||||
FlatUIUtils.setColor( g, FlatUIUtils.isPermanentFocusOwner( slider ) ? focusColor : (hover ? hoverColor : thumbColor), thumbColor );
|
||||
((Graphics2D)g).fill( coloredTrack );
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ public class FlatSliderUI
|
||||
@Override
|
||||
public void paintThumb( Graphics g ) {
|
||||
FlatUIUtils.setColor( g, slider.isEnabled()
|
||||
? (slider.hasFocus() ? focusColor : (hover ? hoverColor : thumbColor))
|
||||
? (FlatUIUtils.isPermanentFocusOwner( slider ) ? focusColor : (hover ? hoverColor : thumbColor))
|
||||
: disabledForeground,
|
||||
thumbColor );
|
||||
|
||||
|
||||
@@ -326,6 +326,7 @@ public class FlatSpinnerUI
|
||||
Dimension editorSize = (editor != null) ? editor.getPreferredSize() : new Dimension( 0, 0 );
|
||||
|
||||
// the arrows width is the same as the inner height so that the arrows area is square
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( spinner, FlatSpinnerUI.this.minimumWidth );
|
||||
int innerHeight = editorSize.height + padding.top + padding.bottom;
|
||||
return new Dimension(
|
||||
Math.max( insets.left + insets.right + editorSize.width + padding.left + padding.right + innerHeight, scale( minimumWidth + (focusWidth * 2) ) ),
|
||||
|
||||
@@ -26,15 +26,21 @@ import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
@@ -46,13 +52,29 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JTabbedPane}.
|
||||
*
|
||||
* @clientProperty JTabbedPane.showTabSeparators boolean
|
||||
* @clientProperty JTabbedPane.hasFullBorder boolean
|
||||
*
|
||||
* @uiDefault Component.arrowType String triangle (default) or chevron
|
||||
* <!-- BasicTabbedPaneUI -->
|
||||
*
|
||||
* @uiDefault TabbedPane.font Font
|
||||
* @uiDefault TabbedPane.background Color
|
||||
* @uiDefault TabbedPane.foreground Color
|
||||
* @uiDefault TabbedPane.shadow Color used for scroll arrows and cropped line
|
||||
* @uiDefault TabbedPane.textIconGap int
|
||||
* @uiDefault TabbedPane.tabInsets Insets
|
||||
* @uiDefault TabbedPane.selectedTabPadInsets Insets
|
||||
* @uiDefault TabbedPane.tabAreaInsets Insets
|
||||
* @uiDefault TabbedPane.tabsOverlapBorder boolean
|
||||
* @uiDefault TabbedPane.tabRunOverlay int
|
||||
* @uiDefault TabbedPane.tabsOpaque boolean
|
||||
* @uiDefault TabbedPane.contentOpaque boolean unused
|
||||
* @uiDefault TabbedPane.opaque boolean
|
||||
* @uiDefault TabbedPane.selectionFollowsFocus boolean default is true
|
||||
*
|
||||
* <!-- FlatTabbedPaneUI -->
|
||||
*
|
||||
* @uiDefault Component.arrowType String triangle (default) or chevron
|
||||
* @uiDefault TabbedPane.disabledForeground Color
|
||||
* @uiDefault TabbedPane.selectedBackground Color optional
|
||||
* @uiDefault TabbedPane.selectedForeground Color
|
||||
@@ -62,13 +84,11 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TabbedPane.focusColor Color
|
||||
* @uiDefault TabbedPane.tabSeparatorColor Color optional; defaults to TabbedPane.contentAreaColor
|
||||
* @uiDefault TabbedPane.contentAreaColor Color
|
||||
* @uiDefault TabbedPane.textIconGap int
|
||||
* @uiDefault TabbedPane.tabInsets Insets
|
||||
* @uiDefault TabbedPane.tabAreaInsets Insets
|
||||
* @uiDefault TabbedPane.tabHeight int
|
||||
* @uiDefault TabbedPane.tabSelectionHeight int
|
||||
* @uiDefault TabbedPane.contentSeparatorHeight int
|
||||
* @uiDefault TabbedPane.showTabSeparators boolean
|
||||
* @uiDefault TabbedPane.tabSeparatorsFullHeight boolean
|
||||
* @uiDefault TabbedPane.hasFullBorder boolean
|
||||
*
|
||||
* @author Karl Tauber
|
||||
@@ -76,6 +96,9 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatTabbedPaneUI
|
||||
extends BasicTabbedPaneUI
|
||||
{
|
||||
private static Set<KeyStroke> focusForwardTraversalKeys;
|
||||
private static Set<KeyStroke> focusBackwardTraversalKeys;
|
||||
|
||||
protected Color disabledForeground;
|
||||
protected Color selectedBackground;
|
||||
protected Color selectedForeground;
|
||||
@@ -90,6 +113,7 @@ public class FlatTabbedPaneUI
|
||||
protected int tabSelectionHeight;
|
||||
protected int contentSeparatorHeight;
|
||||
protected boolean showTabSeparators;
|
||||
protected boolean tabSeparatorsFullHeight;
|
||||
protected boolean hasFullBorder;
|
||||
protected boolean tabsOverlapBorder;
|
||||
|
||||
@@ -115,6 +139,7 @@ public class FlatTabbedPaneUI
|
||||
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
||||
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
||||
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
||||
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
||||
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
||||
tabsOverlapBorder = UIManager.getBoolean( "TabbedPane.tabsOverlapBorder" );
|
||||
|
||||
@@ -126,11 +151,27 @@ public class FlatTabbedPaneUI
|
||||
tabHeight = scale( tabHeight );
|
||||
tabSelectionHeight = scale( tabSelectionHeight );
|
||||
|
||||
// replace focus forward/backward traversal keys with TAB/Shift+TAB because
|
||||
// the default also includes Ctrl+TAB/Ctrl+Shift+TAB, which we need to switch tabs
|
||||
if( focusForwardTraversalKeys == null ) {
|
||||
focusForwardTraversalKeys = Collections.singleton( KeyStroke.getKeyStroke( KeyEvent.VK_TAB, 0 ) );
|
||||
focusBackwardTraversalKeys = Collections.singleton( KeyStroke.getKeyStroke( KeyEvent.VK_TAB, InputEvent.SHIFT_MASK ) );
|
||||
}
|
||||
// Ideally we should use `LookAndFeel.installProperty( tabPane, "focusTraversalKeysForward", keys )` here
|
||||
// instead of `tabPane.setFocusTraversalKeys()`, but WindowsTabbedPaneUI also uses later method
|
||||
// and switching from Windows LaF to FlatLaf would not replace the keys and Ctrl+TAB would not work.
|
||||
tabPane.setFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, focusForwardTraversalKeys );
|
||||
tabPane.setFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, focusBackwardTraversalKeys );
|
||||
|
||||
MigLayoutVisualPadding.install( tabPane, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallDefaults() {
|
||||
// restore focus forward/backward traversal keys
|
||||
tabPane.setFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null );
|
||||
tabPane.setFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null );
|
||||
|
||||
super.uninstallDefaults();
|
||||
|
||||
disabledForeground = null;
|
||||
@@ -156,6 +197,7 @@ public class FlatTabbedPaneUI
|
||||
switch( e.getPropertyName() ) {
|
||||
case TABBED_PANE_SHOW_TAB_SEPARATORS:
|
||||
case TABBED_PANE_HAS_FULL_BORDER:
|
||||
case TABBED_PANE_TAB_HEIGHT:
|
||||
tabPane.revalidate();
|
||||
tabPane.repaint();
|
||||
break;
|
||||
@@ -168,7 +210,7 @@ public class FlatTabbedPaneUI
|
||||
protected JButton createScrollButton( int direction ) {
|
||||
// this method is invoked before installDefaults(), so we can not use color fields here
|
||||
return new FlatArrowButton( direction, UIManager.getString( "Component.arrowType" ),
|
||||
UIManager.getColor( "TabbedPane.shadow" ),
|
||||
UIManager.getColor( "TabbedPane.foreground" ),
|
||||
UIManager.getColor( "TabbedPane.disabledForeground" ), null,
|
||||
UIManager.getColor( "TabbedPane.hoverColor" ) );
|
||||
}
|
||||
@@ -202,6 +244,7 @@ public class FlatTabbedPaneUI
|
||||
|
||||
@Override
|
||||
protected int calculateTabHeight( int tabPlacement, int tabIndex, int fontHeight ) {
|
||||
int tabHeight = clientPropertyInt( tabPane, TABBED_PANE_TAB_HEIGHT, this.tabHeight );
|
||||
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ );
|
||||
}
|
||||
|
||||
@@ -275,7 +318,7 @@ public class FlatTabbedPaneUI
|
||||
boolean enabled = tabPane.isEnabled();
|
||||
g.setColor( enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
|
||||
? hoverColor
|
||||
: (enabled && isSelected && tabPane.hasFocus()
|
||||
: (enabled && isSelected && FlatUIUtils.isPermanentFocusOwner( tabPane )
|
||||
? focusColor
|
||||
: (selectedBackground != null && enabled && isSelected
|
||||
? selectedBackground
|
||||
@@ -292,7 +335,7 @@ public class FlatTabbedPaneUI
|
||||
!isLastInRun( tabIndex ) )
|
||||
{
|
||||
float sepWidth = UIScale.scale( 1f );
|
||||
float offset = UIScale.scale( 5f );
|
||||
float offset = tabSeparatorsFullHeight ? 0 : UIScale.scale( 5f );
|
||||
|
||||
g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor );
|
||||
if( tabPlacement == LEFT || tabPlacement == RIGHT ) {
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* Cell border for {@link javax.swing.table.DefaultTableCellRenderer}
|
||||
* (used by {@link javax.swing.JTable}).
|
||||
* <p>
|
||||
* Uses separate cell margins from UI defaults to allow easy customizing.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatTableCellBorder
|
||||
extends FlatLineBorder
|
||||
{
|
||||
final boolean showCellFocusIndicator = UIManager.getBoolean( "Table.showCellFocusIndicator" );
|
||||
|
||||
protected FlatTableCellBorder() {
|
||||
super( UIManager.getInsets( "Table.cellMargins" ), UIManager.getColor( "Table.cellFocusColor" ) );
|
||||
}
|
||||
|
||||
//---- class Default ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Border for unselected cell that uses margins, but does not paint focus indicator border.
|
||||
*/
|
||||
public static class Default
|
||||
extends FlatTableCellBorder
|
||||
{
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
// do not paint focus indicator border
|
||||
}
|
||||
}
|
||||
|
||||
//---- class Focused ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Border for focused unselected cell that uses margins and paints focus indicator border.
|
||||
*/
|
||||
public static class Focused
|
||||
extends FlatTableCellBorder
|
||||
{
|
||||
}
|
||||
|
||||
//---- class Selected -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* Border for selected cell that uses margins and paints focus indicator border
|
||||
* if enabled (Table.showCellFocusIndicator=true) or at least one selected cell is editable.
|
||||
*/
|
||||
public static class Selected
|
||||
extends FlatTableCellBorder
|
||||
{
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( !showCellFocusIndicator ) {
|
||||
JTable table = (JTable) SwingUtilities.getAncestorOfClass( JTable.class, c );
|
||||
if( table != null && !isSelectionEditable( table ) )
|
||||
return;
|
||||
}
|
||||
|
||||
super.paintBorder( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether at least one selected cell is editable.
|
||||
*/
|
||||
private boolean isSelectionEditable( JTable table ) {
|
||||
if( table.getRowSelectionAllowed() ) {
|
||||
int columnCount = table.getColumnCount();
|
||||
int[] selectedRows = table.getSelectedRows();
|
||||
for( int selectedRow : selectedRows ) {
|
||||
for( int column = 0; column < columnCount; column++ ) {
|
||||
if( table.isCellEditable( selectedRow, column ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( table.getColumnSelectionAllowed() ) {
|
||||
int rowCount = table.getRowCount();
|
||||
int[] selectedColumns = table.getSelectedColumns();
|
||||
for( int selectedColumn : selectedColumns ) {
|
||||
for( int row = 0; row < rowCount; row++ ) {
|
||||
if( table.isCellEditable( row, selectedColumn ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,18 +17,27 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.Objects;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicTableHeaderUI;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -47,6 +56,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TableHeader.separatorColor Color
|
||||
* @uiDefault TableHeader.bottomSeparatorColor Color
|
||||
* @uiDefault TableHeader.height int
|
||||
* @uiDefault TableHeader.sortIconPosition String right (default), left, top or bottom
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -56,6 +66,7 @@ public class FlatTableHeaderUI
|
||||
protected Color separatorColor;
|
||||
protected Color bottomSeparatorColor;
|
||||
protected int height;
|
||||
protected int sortIconPosition;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatTableHeaderUI();
|
||||
@@ -68,12 +79,33 @@ public class FlatTableHeaderUI
|
||||
separatorColor = UIManager.getColor( "TableHeader.separatorColor" );
|
||||
bottomSeparatorColor = UIManager.getColor( "TableHeader.bottomSeparatorColor" );
|
||||
height = UIManager.getInt( "TableHeader.height" );
|
||||
switch( Objects.toString( UIManager.getString( "TableHeader.sortIconPosition" ), "right" ) ) {
|
||||
default:
|
||||
case "right": sortIconPosition = SwingConstants.RIGHT; break;
|
||||
case "left": sortIconPosition = SwingConstants.LEFT; break;
|
||||
case "top": sortIconPosition = SwingConstants.TOP; break;
|
||||
case "bottom": sortIconPosition = SwingConstants.BOTTOM; break;
|
||||
}
|
||||
|
||||
// use own renderer if necessary
|
||||
if( sortIconPosition != SwingConstants.RIGHT ) {
|
||||
TableCellRenderer defaultRenderer = header.getDefaultRenderer();
|
||||
if( defaultRenderer instanceof UIResource )
|
||||
header.setDefaultRenderer( new FlatTableCellHeaderRenderer( defaultRenderer ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
// restore default renderer
|
||||
TableCellRenderer defaultRenderer = header.getDefaultRenderer();
|
||||
if( defaultRenderer instanceof FlatTableCellHeaderRenderer ) {
|
||||
((FlatTableCellHeaderRenderer)defaultRenderer).reset();
|
||||
header.setDefaultRenderer( ((FlatTableCellHeaderRenderer)defaultRenderer).delegate );
|
||||
}
|
||||
|
||||
separatorColor = null;
|
||||
bottomSeparatorColor = null;
|
||||
}
|
||||
@@ -81,10 +113,14 @@ public class FlatTableHeaderUI
|
||||
@Override
|
||||
public void paint( Graphics g, JComponent c ) {
|
||||
// do not paint borders if JTableHeader.setDefaultRenderer() was used
|
||||
String rendererClassName = header.getDefaultRenderer().getClass().getName();
|
||||
boolean paintBorders =
|
||||
rendererClassName.equals( "sun.swing.table.DefaultTableCellHeaderRenderer" ) ||
|
||||
rendererClassName.equals( "sun.swing.FilePane$AlignableTableHeaderRenderer" );
|
||||
TableCellRenderer defaultRenderer = header.getDefaultRenderer();
|
||||
boolean paintBorders = isSystemDefaultRenderer( defaultRenderer );
|
||||
if( !paintBorders && header.getColumnModel().getColumnCount() > 0 ) {
|
||||
// check whether the renderer delegates to the system default renderer
|
||||
Component rendererComponent = defaultRenderer.getTableCellRendererComponent(
|
||||
header.getTable(), "", false, false, -1, 0 );
|
||||
paintBorders = isSystemDefaultRenderer( rendererComponent );
|
||||
}
|
||||
|
||||
if( paintBorders )
|
||||
paintColumnBorders( g, c );
|
||||
@@ -95,6 +131,12 @@ public class FlatTableHeaderUI
|
||||
paintDraggedColumnBorders( g, c );
|
||||
}
|
||||
|
||||
private boolean isSystemDefaultRenderer( Object headerRenderer ) {
|
||||
String rendererClassName = headerRenderer.getClass().getName();
|
||||
return rendererClassName.equals( "sun.swing.table.DefaultTableCellHeaderRenderer" ) ||
|
||||
rendererClassName.equals( "sun.swing.FilePane$AlignableTableHeaderRenderer" );
|
||||
}
|
||||
|
||||
private void paintColumnBorders( Graphics g, JComponent c ) {
|
||||
int width = c.getWidth();
|
||||
int height = c.getHeight();
|
||||
@@ -203,4 +245,83 @@ public class FlatTableHeaderUI
|
||||
parent = parent.getParent();
|
||||
return (parent instanceof JScrollPane) ? (JScrollPane) parent : null;
|
||||
}
|
||||
|
||||
//---- class FlatTableCellHeaderRenderer ----------------------------------
|
||||
|
||||
/**
|
||||
* A delegating header renderer that is only used to paint sort arrows at
|
||||
* top, bottom or left position.
|
||||
*/
|
||||
private class FlatTableCellHeaderRenderer
|
||||
implements TableCellRenderer, Border, UIResource
|
||||
{
|
||||
private final TableCellRenderer delegate;
|
||||
|
||||
private int oldHorizontalTextPosition = -1;
|
||||
private Border origBorder;
|
||||
private Icon sortIcon;
|
||||
|
||||
FlatTableCellHeaderRenderer( TableCellRenderer delegate ) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected,
|
||||
boolean hasFocus, int row, int column )
|
||||
{
|
||||
Component c = delegate.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
|
||||
if( !(c instanceof JLabel) )
|
||||
return c;
|
||||
|
||||
JLabel l = (JLabel) c;
|
||||
|
||||
if( sortIconPosition == SwingConstants.LEFT ) {
|
||||
if( oldHorizontalTextPosition < 0 )
|
||||
oldHorizontalTextPosition = l.getHorizontalTextPosition();
|
||||
l.setHorizontalTextPosition( SwingConstants.RIGHT );
|
||||
} else {
|
||||
// top or bottom
|
||||
sortIcon = l.getIcon();
|
||||
origBorder = l.getBorder();
|
||||
l.setIcon( null );
|
||||
l.setBorder( this );
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if( sortIconPosition == SwingConstants.LEFT && oldHorizontalTextPosition >= 0 ) {
|
||||
Component c = getTableCellRendererComponent( header.getTable(), "", false, false, -1, 0 );
|
||||
if( c instanceof JLabel && ((JLabel)c).getHorizontalTextPosition() == SwingConstants.RIGHT )
|
||||
((JLabel)c).setHorizontalTextPosition( oldHorizontalTextPosition );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( origBorder != null )
|
||||
origBorder.paintBorder( c, g, x, y, width, height );
|
||||
|
||||
if( sortIcon != null ) {
|
||||
int xi = x + ((width - sortIcon.getIconWidth()) / 2);
|
||||
int yi = (sortIconPosition == SwingConstants.TOP)
|
||||
? y + UIScale.scale( 1 )
|
||||
: y + height - sortIcon.getIconHeight()
|
||||
- 1 // for gap
|
||||
- (int) (1 * UIScale.getUserScaleFactor()); // for bottom border
|
||||
sortIcon.paintIcon( c, g, xi, yi );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c ) {
|
||||
return (origBorder != null) ? origBorder.getBorderInsets( c ) : new Insets( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBorderOpaque() {
|
||||
return (origBorder != null) ? origBorder.isBorderOpaque() : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import javax.swing.JComponent;
|
||||
@@ -54,38 +55,83 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatTableUI -->
|
||||
*
|
||||
* @uiDefault Table.rowHeight int
|
||||
* @uiDefault Table.selectionInactiveBackground Color
|
||||
* @uiDefault Table.selectionInactiveForeground Color
|
||||
* @uiDefault Table.rowHeight int
|
||||
* @uiDefault Table.showHorizontalLines boolean
|
||||
* @uiDefault Table.showVerticalLines boolean
|
||||
* @uiDefault Table.intercellSpacing Dimension
|
||||
* @uiDefault Table.selectionInactiveBackground Color
|
||||
* @uiDefault Table.selectionInactiveForeground Color
|
||||
*
|
||||
* <!-- FlatTableCellBorder -->
|
||||
*
|
||||
* @uiDefault Table.cellMargins Insets
|
||||
* @uiDefault Table.cellFocusColor Color
|
||||
* @uiDefault Table.showCellFocusIndicator boolean
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatTableUI
|
||||
extends BasicTableUI
|
||||
{
|
||||
protected boolean showHorizontalLines;
|
||||
protected boolean showVerticalLines;
|
||||
protected Dimension intercellSpacing;
|
||||
|
||||
protected Color selectionBackground;
|
||||
protected Color selectionForeground;
|
||||
protected Color selectionInactiveBackground;
|
||||
protected Color selectionInactiveForeground;
|
||||
|
||||
private boolean oldShowHorizontalLines;
|
||||
private boolean oldShowVerticalLines;
|
||||
private Dimension oldIntercellSpacing;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatTableUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
showHorizontalLines = UIManager.getBoolean( "Table.showHorizontalLines" );
|
||||
showVerticalLines = UIManager.getBoolean( "Table.showVerticalLines" );
|
||||
intercellSpacing = UIManager.getDimension( "Table.intercellSpacing" );
|
||||
|
||||
selectionBackground = UIManager.getColor( "Table.selectionBackground" );
|
||||
selectionForeground = UIManager.getColor( "Table.selectionForeground" );
|
||||
selectionInactiveBackground = UIManager.getColor( "Table.selectionInactiveBackground" );
|
||||
selectionInactiveForeground = UIManager.getColor( "Table.selectionInactiveForeground" );
|
||||
|
||||
toggleSelectionColors( table.hasFocus() );
|
||||
toggleSelectionColors();
|
||||
|
||||
int rowHeight = FlatUIUtils.getUIInt( "Table.rowHeight", 16 );
|
||||
if( rowHeight > 0 )
|
||||
LookAndFeel.installProperty( table, "rowHeight", UIScale.scale( rowHeight ) );
|
||||
|
||||
if( !showHorizontalLines ) {
|
||||
oldShowHorizontalLines = table.getShowHorizontalLines();
|
||||
table.setShowHorizontalLines( false );
|
||||
}
|
||||
if( !showVerticalLines ) {
|
||||
oldShowVerticalLines = table.getShowVerticalLines();
|
||||
table.setShowVerticalLines( false );
|
||||
}
|
||||
|
||||
if( intercellSpacing != null ) {
|
||||
oldIntercellSpacing = table.getIntercellSpacing();
|
||||
table.setIntercellSpacing( intercellSpacing );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,6 +142,16 @@ public class FlatTableUI
|
||||
selectionForeground = null;
|
||||
selectionInactiveBackground = null;
|
||||
selectionInactiveForeground = null;
|
||||
|
||||
// restore old show horizontal/vertical lines (if not modified)
|
||||
if( !showHorizontalLines && oldShowHorizontalLines && !table.getShowHorizontalLines() )
|
||||
table.setShowHorizontalLines( true );
|
||||
if( !showVerticalLines && oldShowVerticalLines && !table.getShowVerticalLines() )
|
||||
table.setShowVerticalLines( true );
|
||||
|
||||
// restore old intercell spacing (if not modified)
|
||||
if( intercellSpacing != null && table.getIntercellSpacing().equals( intercellSpacing ) )
|
||||
table.setIntercellSpacing( oldIntercellSpacing );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,13 +160,13 @@ public class FlatTableUI
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {
|
||||
super.focusGained( e );
|
||||
toggleSelectionColors( true );
|
||||
toggleSelectionColors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
super.focusLost( e );
|
||||
toggleSelectionColors( false );
|
||||
toggleSelectionColors();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -124,8 +180,8 @@ public class FlatTableUI
|
||||
* already used in applications. Then either the inactive colors are not used,
|
||||
* or the application has to be changed to extend a FlatLaf renderer.
|
||||
*/
|
||||
private void toggleSelectionColors( boolean focused ) {
|
||||
if( focused ) {
|
||||
private void toggleSelectionColors() {
|
||||
if( FlatUIUtils.isPermanentFocusOwner( table ) ) {
|
||||
if( table.getSelectionBackground() == selectionInactiveBackground )
|
||||
table.setSelectionBackground( selectionBackground );
|
||||
if( table.getSelectionForeground() == selectionInactiveForeground )
|
||||
|
||||
@@ -117,6 +117,7 @@ public class FlatTextAreaUI
|
||||
// and subtract 1px border line width.
|
||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||
// issues. E.g. at scale factor 1.5 the first returns 4, but the second 3.
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
size.width = Math.max( size.width, scale( minimumWidth ) - (scale( 1 ) * 2) );
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 FormDev Software GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Component;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* Border for various text components (e.g. {@link javax.swing.JTextField}).
|
||||
*
|
||||
* @uiDefault Component.arc int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatTextBorder
|
||||
extends FlatBorder
|
||||
{
|
||||
protected final int arc = UIManager.getInt( "TextComponent.arc" );
|
||||
|
||||
@Override
|
||||
protected float getArc( Component c ) {
|
||||
return scale( (float) arc );
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,11 @@ import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicTextFieldUI;
|
||||
import javax.swing.text.Caret;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
|
||||
@@ -58,16 +60,19 @@ import com.formdev.flatlaf.FlatClientProperties;
|
||||
*
|
||||
* <!-- FlatTextFieldUI -->
|
||||
*
|
||||
* @uiDefault TextComponent.arc int
|
||||
* @uiDefault Component.focusWidth int
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault TextField.placeholderForeground Color
|
||||
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatTextFieldUI
|
||||
extends BasicTextFieldUI
|
||||
{
|
||||
protected int arc;
|
||||
protected int focusWidth;
|
||||
protected int minimumWidth;
|
||||
protected boolean isIntelliJTheme;
|
||||
@@ -84,6 +89,7 @@ public class FlatTextFieldUI
|
||||
super.installDefaults();
|
||||
|
||||
String prefix = getPropertyPrefix();
|
||||
arc = UIManager.getInt( "TextComponent.arc" );
|
||||
focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||
@@ -119,6 +125,11 @@ public class FlatTextFieldUI
|
||||
focusListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Caret createCaret() {
|
||||
return new FlatCaret( UIManager.getString( "TextComponent.selectAllOnFocusPolicy" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
@@ -129,7 +140,7 @@ public class FlatTextFieldUI
|
||||
|
||||
@Override
|
||||
protected void paintSafely( Graphics g ) {
|
||||
paintBackground( g, getComponent(), focusWidth, isIntelliJTheme );
|
||||
paintBackground( g, getComponent(), focusWidth, arc, isIntelliJTheme );
|
||||
paintPlaceholder( g, getComponent(), placeholderForeground );
|
||||
super.paintSafely( g );
|
||||
}
|
||||
@@ -139,13 +150,15 @@ public class FlatTextFieldUI
|
||||
// background is painted elsewhere
|
||||
}
|
||||
|
||||
static void paintBackground( Graphics g, JTextComponent c, int focusWidth, boolean isIntelliJTheme ) {
|
||||
static void paintBackground( Graphics g, JTextComponent c, int focusWidth, int arc, boolean isIntelliJTheme ) {
|
||||
Border border = c.getBorder();
|
||||
|
||||
// do not paint background if:
|
||||
// - not opaque and
|
||||
// - border is not a flat border and
|
||||
// - opaque was explicitly set (to false)
|
||||
// (same behaviour as in AquaTextFieldUI)
|
||||
if( !c.isOpaque() && !(c.getBorder() instanceof FlatBorder) && FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) )
|
||||
if( !c.isOpaque() && !(border instanceof FlatBorder) && FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) )
|
||||
return;
|
||||
|
||||
// fill background if opaque to avoid garbage if user sets opaque to true
|
||||
@@ -157,7 +170,8 @@ public class FlatTextFieldUI
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
float fFocusWidth = (c.getBorder() instanceof FlatBorder) ? scale( (float) focusWidth ) : 0;
|
||||
float fFocusWidth = (border instanceof FlatBorder) ? scale( (float) focusWidth ) : 0;
|
||||
float fArc = (border instanceof FlatTextBorder) ? scale( (float) arc ) : 0;
|
||||
|
||||
Color background = c.getBackground();
|
||||
g2.setColor( !(background instanceof UIResource)
|
||||
@@ -165,7 +179,7 @@ public class FlatTextFieldUI
|
||||
: (isIntelliJTheme && (!c.isEnabled() || !c.isEditable())
|
||||
? FlatUIUtils.getParentBackground( c )
|
||||
: background) );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, 0 );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), fFocusWidth, fArc );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
@@ -217,6 +231,7 @@ public class FlatTextFieldUI
|
||||
(parent != null && parent.getParent() instanceof JSpinner) )
|
||||
return size;
|
||||
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
int focusWidth = (c.getBorder() instanceof FlatBorder) ? this.focusWidth : 0;
|
||||
size.width = Math.max( size.width, scale( minimumWidth + (focusWidth * 2) ) );
|
||||
return size;
|
||||
|
||||
@@ -98,6 +98,7 @@ public class FlatTextPaneUI
|
||||
// and subtract 1px border line width.
|
||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||
// issues. E.g. at scale factor 1.5 the first returns 4, but the second 3.
|
||||
int minimumWidth = FlatUIUtils.minimumWidth( getComponent(), this.minimumWidth );
|
||||
size.width = Math.max( size.width, scale( minimumWidth ) - (scale( 1 ) * 2) );
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.ButtonModel;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JToggleButton}.
|
||||
@@ -55,6 +61,13 @@ import javax.swing.plaf.ComponentUI;
|
||||
* @uiDefault ToggleButton.disabledSelectedBackground Color
|
||||
* @uiDefault ToggleButton.toolbar.selectedBackground Color
|
||||
*
|
||||
* @uiDefault ToggleButton.tab.underlineHeight int
|
||||
* @uiDefault ToggleButton.tab.underlineColor Color
|
||||
* @uiDefault ToggleButton.tab.disabledUnderlineColor Color
|
||||
* @uiDefault ToggleButton.tab.selectedBackground Color optional
|
||||
* @uiDefault ToggleButton.tab.hoverBackground Color
|
||||
* @uiDefault ToggleButton.tab.focusBackground Color
|
||||
*
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -67,6 +80,13 @@ public class FlatToggleButtonUI
|
||||
|
||||
protected Color toolbarSelectedBackground;
|
||||
|
||||
protected int tabUnderlineHeight;
|
||||
protected Color tabUnderlineColor;
|
||||
protected Color tabDisabledUnderlineColor;
|
||||
protected Color tabSelectedBackground;
|
||||
protected Color tabHoverBackground;
|
||||
protected Color tabFocusBackground;
|
||||
|
||||
private boolean defaults_initialized = false;
|
||||
|
||||
private static ComponentUI instance;
|
||||
@@ -93,6 +113,13 @@ public class FlatToggleButtonUI
|
||||
|
||||
toolbarSelectedBackground = UIManager.getColor( "ToggleButton.toolbar.selectedBackground" );
|
||||
|
||||
tabUnderlineHeight = UIManager.getInt( "ToggleButton.tab.underlineHeight" );
|
||||
tabUnderlineColor = UIManager.getColor( "ToggleButton.tab.underlineColor" );
|
||||
tabDisabledUnderlineColor = UIManager.getColor( "ToggleButton.tab.disabledUnderlineColor" );
|
||||
tabSelectedBackground = UIManager.getColor( "ToggleButton.tab.selectedBackground" );
|
||||
tabHoverBackground = UIManager.getColor( "ToggleButton.tab.hoverBackground" );
|
||||
tabFocusBackground = UIManager.getColor( "ToggleButton.tab.focusBackground" );
|
||||
|
||||
defaults_initialized = true;
|
||||
}
|
||||
}
|
||||
@@ -103,6 +130,61 @@ public class FlatToggleButtonUI
|
||||
defaults_initialized = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
||||
super.propertyChange( b, e );
|
||||
|
||||
switch( e.getPropertyName() ) {
|
||||
case BUTTON_TYPE:
|
||||
if( BUTTON_TYPE_TAB.equals( e.getOldValue() ) || BUTTON_TYPE_TAB.equals( e.getNewValue() ) ) {
|
||||
MigLayoutVisualPadding.uninstall( b );
|
||||
MigLayoutVisualPadding.install( b, getFocusWidth( b ) );
|
||||
b.revalidate();
|
||||
}
|
||||
|
||||
b.repaint();
|
||||
break;
|
||||
|
||||
case TAB_BUTTON_UNDERLINE_HEIGHT:
|
||||
case TAB_BUTTON_UNDERLINE_COLOR:
|
||||
case TAB_BUTTON_SELECTED_BACKGROUND:
|
||||
b.repaint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isTabButton( Component c ) {
|
||||
return c instanceof JToggleButton && clientPropertyEquals( (JToggleButton) c, BUTTON_TYPE, BUTTON_TYPE_TAB );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g, JComponent c ) {
|
||||
if( isTabButton( c ) ) {
|
||||
int height = c.getHeight();
|
||||
int width = c.getWidth();
|
||||
boolean selected = ((AbstractButton)c).isSelected();
|
||||
|
||||
// paint background
|
||||
Color background = buttonStateColor( c,
|
||||
selected ? clientPropertyColor( c, TAB_BUTTON_SELECTED_BACKGROUND, tabSelectedBackground ) : null,
|
||||
null, tabFocusBackground, tabHoverBackground, null );
|
||||
if( background != null ) {
|
||||
g.setColor( background );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
}
|
||||
|
||||
// paint underline if selected
|
||||
if( selected ) {
|
||||
int underlineHeight = UIScale.scale( clientPropertyInt( c, TAB_BUTTON_UNDERLINE_HEIGHT, tabUnderlineHeight ) );
|
||||
g.setColor( c.isEnabled()
|
||||
? clientPropertyColor( c, TAB_BUTTON_UNDERLINE_COLOR, tabUnderlineColor )
|
||||
: tabDisabledUnderlineColor );
|
||||
g.fillRect( 0, height - underlineHeight, width, underlineHeight );
|
||||
}
|
||||
} else
|
||||
super.paintBackground( g, c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Color getBackground( JComponent c ) {
|
||||
ButtonModel model = ((AbstractButton)c).getModel();
|
||||
@@ -130,4 +212,9 @@ public class FlatToggleButtonUI
|
||||
|
||||
return super.getForeground( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getFocusWidth( JComponent c ) {
|
||||
return isTabButton( c ) ? 0 : super.getFocusWidth( c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import javax.swing.UIManager;
|
||||
/**
|
||||
* Border for {@link javax.swing.JToolBar}.
|
||||
*
|
||||
* @uiDefault ToolBar.borderMargins Insets
|
||||
* @uiDefault ToolBar.gripColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
@@ -42,6 +43,10 @@ public class FlatToolBarBorder
|
||||
|
||||
protected final Color gripColor = UIManager.getColor( "ToolBar.gripColor" );
|
||||
|
||||
public FlatToolBarBorder() {
|
||||
super( UIManager.getInsets( "ToolBar.borderMargins" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
// paint grip
|
||||
|
||||
@@ -16,18 +16,14 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Component;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.awt.event.ContainerListener;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicToolBarUI;
|
||||
|
||||
/**
|
||||
@@ -45,28 +41,15 @@ import javax.swing.plaf.basic.BasicToolBarUI;
|
||||
* @uiDefault ToolBar.floatingForeground Color
|
||||
* @uiDefault ToolBar.isRollover boolean
|
||||
*
|
||||
* <!-- FlatToolBarUI -->
|
||||
*
|
||||
* @uiDefault ToolBar.buttonMargins Insets
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatToolBarUI
|
||||
extends BasicToolBarUI
|
||||
{
|
||||
private Border rolloverBorder;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatToolBarUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
|
||||
rolloverBorder = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContainerListener createToolBarContListener() {
|
||||
return new ToolBarContListener() {
|
||||
@@ -90,26 +73,15 @@ public class FlatToolBarUI
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Border createRolloverBorder() {
|
||||
return getRolloverBorder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Border createNonRolloverBorder() {
|
||||
return getRolloverBorder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Border getNonRolloverBorder( AbstractButton b ) {
|
||||
return getRolloverBorder();
|
||||
}
|
||||
|
||||
private Border getRolloverBorder() {
|
||||
if( rolloverBorder == null )
|
||||
rolloverBorder = new FlatRolloverMarginBorder();
|
||||
return rolloverBorder;
|
||||
}
|
||||
// disable rollover border
|
||||
@Override protected void setBorderToRollover( Component c ) {}
|
||||
@Override protected void setBorderToNonRollover( Component c ) {}
|
||||
@Override protected void setBorderToNormal( Component c ) {}
|
||||
@Override protected void installRolloverBorders( JComponent c ) {}
|
||||
@Override protected void installNonRolloverBorders( JComponent c ) {}
|
||||
@Override protected void installNormalBorders( JComponent c ) {}
|
||||
@Override protected Border createRolloverBorder() { return null; }
|
||||
@Override protected Border createNonRolloverBorder() { return null; }
|
||||
|
||||
@Override
|
||||
public void setOrientation( int orientation ) {
|
||||
@@ -123,46 +95,4 @@ public class FlatToolBarUI
|
||||
|
||||
super.setOrientation( orientation );
|
||||
}
|
||||
|
||||
//---- class FlatRolloverMarginBorder -------------------------------------
|
||||
|
||||
/**
|
||||
* Uses button margin only if explicitly set.
|
||||
* Otherwise uses insets specified in constructor.
|
||||
*/
|
||||
private static class FlatRolloverMarginBorder
|
||||
extends EmptyBorder
|
||||
{
|
||||
public FlatRolloverMarginBorder() {
|
||||
super( UIManager.getInsets( "ToolBar.buttonMargins" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
Insets margin = (c instanceof AbstractButton)
|
||||
? ((AbstractButton) c).getMargin()
|
||||
: null;
|
||||
|
||||
if( margin == null || margin instanceof UIResource ) {
|
||||
insets.top = top;
|
||||
insets.left = left;
|
||||
insets.bottom = bottom;
|
||||
insets.right = right;
|
||||
} else {
|
||||
// margin explicitly set
|
||||
insets.top = margin.top;
|
||||
insets.left = margin.left;
|
||||
insets.bottom = margin.bottom;
|
||||
insets.right = margin.right;
|
||||
}
|
||||
|
||||
// scale
|
||||
insets.top = scale( insets.top );
|
||||
insets.left = scale( insets.left );
|
||||
insets.bottom = scale( insets.bottom );
|
||||
insets.right = scale( insets.right );
|
||||
|
||||
return insets;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JToolTip;
|
||||
@@ -47,6 +48,8 @@ import com.formdev.flatlaf.util.StringUtils;
|
||||
public class FlatToolTipUI
|
||||
extends BasicToolTipUI
|
||||
{
|
||||
private static PropertyChangeListener sharedPropertyChangedListener;
|
||||
|
||||
private static ComponentUI instance;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
@@ -55,6 +58,38 @@ public class FlatToolTipUI
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
// update HTML renderer if necessary
|
||||
FlatLabelUI.updateHTMLRenderer( c, ((JToolTip)c).getTipText(), false );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners( JComponent c ) {
|
||||
super.installListeners( c );
|
||||
|
||||
if( sharedPropertyChangedListener == null ) {
|
||||
sharedPropertyChangedListener = e -> {
|
||||
String name = e.getPropertyName();
|
||||
if( name == "text" || name == "font" || name == "foreground" ) {
|
||||
JToolTip toolTip = (JToolTip) e.getSource();
|
||||
FlatLabelUI.updateHTMLRenderer( toolTip, toolTip.getTipText(), false );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
c.addPropertyChangeListener( sharedPropertyChangedListener );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uninstallListeners( JComponent c ) {
|
||||
super.uninstallListeners( c );
|
||||
|
||||
c.removePropertyChangeListener( sharedPropertyChangedListener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize( JComponent c ) {
|
||||
if( isMultiLine( c ) ) {
|
||||
|
||||
@@ -21,9 +21,16 @@ import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.JTree.DropLocation;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicTreeUI;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
@@ -33,13 +40,50 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JTree}.
|
||||
*
|
||||
* TODO document used UI defaults of superclass
|
||||
* <!-- BasicTreeUI -->
|
||||
*
|
||||
* @uiDefault Tree.font Font
|
||||
* @uiDefault Tree.background Color
|
||||
* @uiDefault Tree.hash Color
|
||||
* @uiDefault Tree.dropLineColor Color
|
||||
* @uiDefault Tree.expandedIcon Icon
|
||||
* @uiDefault Tree.collapsedIcon Icon
|
||||
* @uiDefault Tree.leftChildIndent int
|
||||
* @uiDefault Tree.rightChildIndent int
|
||||
* @uiDefault Tree.rowHeight int
|
||||
* @uiDefault Tree.scrollsOnExpand boolean
|
||||
* @uiDefault Tree.scrollsHorizontallyAndVertically boolean
|
||||
* @uiDefault Tree.paintLines boolean
|
||||
* @uiDefault Tree.lineTypeDashed boolean
|
||||
* @uiDefault Tree.showsRootHandles boolean
|
||||
* @uiDefault Tree.repaintWholeRow boolean
|
||||
*
|
||||
* <!-- DefaultTreeCellRenderer -->
|
||||
*
|
||||
* @uiDefault Tree.leafIcon Icon
|
||||
* @uiDefault Tree.closedIcon Icon
|
||||
* @uiDefault Tree.openIcon Icon
|
||||
* @uiDefault Tree.textBackground Color
|
||||
* @uiDefault Tree.textForeground Color
|
||||
* @uiDefault Tree.selectionBackground Color
|
||||
* @uiDefault Tree.selectionForeground Color
|
||||
* @uiDefault Tree.selectionBorderColor Color focus indicator border color
|
||||
* @uiDefault Tree.drawsFocusBorderAroundIcon boolean
|
||||
* @uiDefault Tree.drawDashedFocusIndicator boolean
|
||||
* @uiDefault Tree.rendererFillBackground boolean default is true
|
||||
* @uiDefault Tree.rendererMargins Insets
|
||||
* @uiDefault Tree.dropCellBackground Color
|
||||
* @uiDefault Tree.dropCellForeground Color
|
||||
*
|
||||
* <!-- FlatTreeUI -->
|
||||
*
|
||||
* @uiDefault Tree.border Border
|
||||
* @uiDefault Tree.selectionBackground Color
|
||||
* @uiDefault Tree.selectionForeground Color
|
||||
* @uiDefault Tree.selectionInactiveBackground Color
|
||||
* @uiDefault Tree.selectionInactiveForeground Color
|
||||
* @uiDefault Tree.wideSelection boolean
|
||||
* @uiDefault Tree.showCellFocusIndicator boolean
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -50,6 +94,9 @@ public class FlatTreeUI
|
||||
protected Color selectionForeground;
|
||||
protected Color selectionInactiveBackground;
|
||||
protected Color selectionInactiveForeground;
|
||||
protected Color selectionBorderColor;
|
||||
protected boolean wideSelection;
|
||||
protected boolean showCellFocusIndicator;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatTreeUI();
|
||||
@@ -65,6 +112,9 @@ public class FlatTreeUI
|
||||
selectionForeground = UIManager.getColor( "Tree.selectionForeground" );
|
||||
selectionInactiveBackground = UIManager.getColor( "Tree.selectionInactiveBackground" );
|
||||
selectionInactiveForeground = UIManager.getColor( "Tree.selectionInactiveForeground" );
|
||||
selectionBorderColor = UIManager.getColor( "Tree.selectionBorderColor" );
|
||||
wideSelection = UIManager.getBoolean( "Tree.wideSelection" );
|
||||
showCellFocusIndicator = UIManager.getBoolean( "Tree.showCellFocusIndicator" );
|
||||
|
||||
// scale
|
||||
int rowHeight = FlatUIUtils.getUIInt( "Tree.rowHeight", 16 );
|
||||
@@ -84,21 +134,115 @@ public class FlatTreeUI
|
||||
selectionForeground = null;
|
||||
selectionInactiveBackground = null;
|
||||
selectionInactiveForeground = null;
|
||||
selectionBorderColor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MouseListener createMouseListener() {
|
||||
if( !wideSelection )
|
||||
return super.createMouseListener();
|
||||
|
||||
return new BasicTreeUI.MouseHandler() {
|
||||
@Override
|
||||
public void mousePressed( MouseEvent e ) {
|
||||
super.mousePressed( handleWideMouseEvent( e ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent e ) {
|
||||
super.mouseReleased( handleWideMouseEvent( e ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged( MouseEvent e ) {
|
||||
super.mouseDragged( handleWideMouseEvent( e ) );
|
||||
}
|
||||
|
||||
private MouseEvent handleWideMouseEvent( MouseEvent e ) {
|
||||
if( !tree.isEnabled() || !SwingUtilities.isLeftMouseButton( e ) || e.isConsumed() )
|
||||
return e;
|
||||
|
||||
int x = e.getX();
|
||||
int y = e.getY();
|
||||
TreePath path = getClosestPathForLocation( tree, x, y );
|
||||
if( path == null || isLocationInExpandControl( path, x, y ) )
|
||||
return e;
|
||||
|
||||
Rectangle bounds = getPathBounds( tree, path );
|
||||
if( bounds == null || y < bounds.y || y >= (bounds.y + bounds.height) )
|
||||
return e;
|
||||
|
||||
int newX = Math.max( bounds.x, Math.min( x, bounds.x + bounds.width - 1 ) );
|
||||
if( newX == x )
|
||||
return e;
|
||||
|
||||
// clone mouse event, but with new X coordinate
|
||||
return new MouseEvent( e.getComponent(), e.getID(), e.getWhen(),
|
||||
e.getModifiers() | e.getModifiersEx(), newX, e.getY(),
|
||||
e.getClickCount(), e.isPopupTrigger(), e.getButton() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
if( !wideSelection )
|
||||
return super.createPropertyChangeListener();
|
||||
|
||||
return new BasicTreeUI.PropertyChangeHandler() {
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
super.propertyChange( e );
|
||||
|
||||
if( e.getSource() == tree && e.getPropertyName() == "dropLocation" ) {
|
||||
JTree.DropLocation oldValue = (JTree.DropLocation) e.getOldValue();
|
||||
repaintWideDropLocation( oldValue );
|
||||
repaintWideDropLocation( tree.getDropLocation() );
|
||||
}
|
||||
}
|
||||
|
||||
private void repaintWideDropLocation(JTree.DropLocation loc) {
|
||||
if( loc == null || isDropLine( loc ) )
|
||||
return;
|
||||
|
||||
Rectangle r = tree.getPathBounds( loc.getPath() );
|
||||
if( r != null )
|
||||
tree.repaint( 0, r.y, tree.getWidth(), r.height );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as super.paintRow(), but uses inactive selection background/foreground if tree is not focused.
|
||||
* Same as super.paintRow(), but supports wide selection and uses
|
||||
* inactive selection background/foreground if tree is not focused.
|
||||
*/
|
||||
@Override
|
||||
protected void paintRow( Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds, TreePath path, int row,
|
||||
boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf )
|
||||
protected void paintRow( Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds,
|
||||
TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf )
|
||||
{
|
||||
if( editingComponent != null && editingRow == row )
|
||||
return;
|
||||
|
||||
boolean hasFocus = tree.hasFocus();
|
||||
boolean isEditing = (editingComponent != null && editingRow == row);
|
||||
boolean hasFocus = FlatUIUtils.isPermanentFocusOwner( tree );
|
||||
boolean cellHasFocus = hasFocus && (row == getLeadSelectionRow());
|
||||
boolean isSelected = tree.isRowSelected( row );
|
||||
boolean isDropRow = isDropRow( row );
|
||||
|
||||
// wide selection background
|
||||
if( wideSelection && (isSelected || isDropRow) ) {
|
||||
// fill background
|
||||
g.setColor( isDropRow
|
||||
? UIManager.getColor( "Tree.dropCellBackground" )
|
||||
: (hasFocus ? selectionBackground : selectionInactiveBackground) );
|
||||
g.fillRect( 0, bounds.y, tree.getWidth(), bounds.height );
|
||||
|
||||
// paint expand/collapse icon
|
||||
if( shouldPaintExpandControl( path, row, isExpanded, hasBeenExpanded, isLeaf ) ) {
|
||||
paintExpandControl( g, clipBounds, insets, bounds,
|
||||
path, row, isExpanded, hasBeenExpanded, isLeaf );
|
||||
}
|
||||
}
|
||||
|
||||
if( isEditing )
|
||||
return;
|
||||
|
||||
// get renderer component
|
||||
Component rendererComponent = currentCellRenderer.getTreeCellRendererComponent( tree,
|
||||
@@ -106,7 +250,7 @@ public class FlatTreeUI
|
||||
|
||||
// apply inactive selection background/foreground if tree is not focused
|
||||
Color oldBackgroundSelectionColor = null;
|
||||
if( isSelected && !hasFocus ) {
|
||||
if( isSelected && !hasFocus && !isDropRow ) {
|
||||
if( rendererComponent instanceof DefaultTreeCellRenderer ) {
|
||||
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) rendererComponent;
|
||||
if( renderer.getBackgroundSelectionColor() == selectionBackground ) {
|
||||
@@ -122,11 +266,43 @@ public class FlatTreeUI
|
||||
rendererComponent.setForeground( selectionInactiveForeground );
|
||||
}
|
||||
|
||||
// remove focus selection border if exactly one item is selected
|
||||
Color oldBorderSelectionColor = null;
|
||||
if( isSelected && hasFocus &&
|
||||
(!showCellFocusIndicator || tree.getMinSelectionRow() == tree.getMaxSelectionRow()) &&
|
||||
rendererComponent instanceof DefaultTreeCellRenderer )
|
||||
{
|
||||
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) rendererComponent;
|
||||
if( renderer.getBorderSelectionColor() == selectionBorderColor ) {
|
||||
oldBorderSelectionColor = renderer.getBorderSelectionColor();
|
||||
renderer.setBorderSelectionColor( null );
|
||||
}
|
||||
}
|
||||
|
||||
// paint renderer
|
||||
rendererPane.paintComponent( g, rendererComponent, tree, bounds.x, bounds.y, bounds.width, bounds.height, true );
|
||||
|
||||
// restore background selection color
|
||||
// restore background selection color and border selection color
|
||||
if( oldBackgroundSelectionColor != null )
|
||||
((DefaultTreeCellRenderer)rendererComponent).setBackgroundSelectionColor( oldBackgroundSelectionColor );
|
||||
if( oldBorderSelectionColor != null )
|
||||
((DefaultTreeCellRenderer)rendererComponent).setBorderSelectionColor( oldBorderSelectionColor );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether dropping on a row.
|
||||
* See DefaultTreeCellRenderer.getTreeCellRendererComponent().
|
||||
*/
|
||||
private boolean isDropRow( int row ) {
|
||||
JTree.DropLocation dropLocation = tree.getDropLocation();
|
||||
return dropLocation != null &&
|
||||
dropLocation.getChildIndex() == -1 &&
|
||||
tree.getRowForPath( dropLocation.getPath() ) == row;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rectangle getDropLineRect( DropLocation loc ) {
|
||||
Rectangle r = super.getDropLineRect( loc );
|
||||
return wideSelection ? new Rectangle( 0, r.y, tree.getWidth(), r.height ) : r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
@@ -37,7 +39,8 @@ import java.util.function.Consumer;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.JavaCompatibility;
|
||||
@@ -82,6 +85,13 @@ public class FlatUIUtils
|
||||
insets1.right + insets2.right );
|
||||
}
|
||||
|
||||
public static void setInsets( Insets dest, Insets src ) {
|
||||
dest.top = src.top;
|
||||
dest.left = src.left;
|
||||
dest.bottom = src.bottom;
|
||||
dest.right = src.right;
|
||||
}
|
||||
|
||||
public static Color getUIColor( String key, int defaultColorRGB ) {
|
||||
Color color = UIManager.getColor( key );
|
||||
return (color != null) ? color : new Color( defaultColorRGB );
|
||||
@@ -102,14 +112,35 @@ public class FlatUIUtils
|
||||
return (value instanceof Integer) ? (Integer) value : defaultValue;
|
||||
}
|
||||
|
||||
public static float getUIFloat( String key, float defaultValue ) {
|
||||
Object value = UIManager.get( key );
|
||||
return (value instanceof Number) ? ((Number)value).floatValue() : defaultValue;
|
||||
}
|
||||
|
||||
public static Color nonUIResource( Color c ) {
|
||||
return (c instanceof ColorUIResource) ? new Color( c.getRGB(), true ) : c;
|
||||
return (c instanceof UIResource) ? new Color( c.getRGB(), true ) : c;
|
||||
}
|
||||
|
||||
public static Font nonUIResource( Font font ) {
|
||||
return (font instanceof UIResource) ? font.deriveFont( font.getStyle() ) : font;
|
||||
}
|
||||
|
||||
public static int minimumWidth( JComponent c, int minimumWidth ) {
|
||||
return FlatClientProperties.clientPropertyInt( c, FlatClientProperties.MINIMUM_WIDTH, minimumWidth );
|
||||
}
|
||||
|
||||
public static int minimumHeight( JComponent c, int minimumHeight ) {
|
||||
return FlatClientProperties.clientPropertyInt( c, FlatClientProperties.MINIMUM_HEIGHT, minimumHeight );
|
||||
}
|
||||
|
||||
public static boolean isTableCellEditor( Component c ) {
|
||||
return c instanceof JComponent && Boolean.TRUE.equals( ((JComponent)c).getClientProperty( "JComboBox.isTableCellEditor" ) );
|
||||
}
|
||||
|
||||
public static boolean isPermanentFocusOwner( Component c ) {
|
||||
return (KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner() == c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets rendering hints used for painting.
|
||||
*/
|
||||
@@ -141,7 +172,7 @@ public class FlatUIUtils
|
||||
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
||||
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
|
||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
||||
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||
paintComponentOuterBorderImpl( g2d, x2, y2, width2, height2,
|
||||
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
|
||||
@@ -155,13 +186,22 @@ public class FlatUIUtils
|
||||
private static void paintComponentOuterBorderImpl( Graphics2D g, int x, int y, int width, int height,
|
||||
float focusWidth, float lineWidth, float arc )
|
||||
{
|
||||
float outerRadius = (arc > 0) ? arc + focusWidth - UIScale.scale( 2f ) : focusWidth;
|
||||
float ow = focusWidth + lineWidth;
|
||||
float innerRadius = outerRadius - ow;
|
||||
float outerArc = arc + (focusWidth * 2);
|
||||
float innerArc = arc - (lineWidth * 2);
|
||||
|
||||
// reduce outer arc slightly for small arcs to make the curve slightly wider
|
||||
if( arc > 0 && arc < UIScale.scale( 10 ) )
|
||||
outerArc -= UIScale.scale( 2f );
|
||||
|
||||
if( outerArc < 0 )
|
||||
outerArc = 0;
|
||||
if( innerArc < 0 )
|
||||
innerArc = 0;
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( createRoundRectanglePath( x, y, width, height, outerRadius, outerRadius, outerRadius, outerRadius ), false );
|
||||
path.append( createRoundRectanglePath( x + ow, y + ow, width - (ow * 2), height - (ow * 2), innerRadius, innerRadius, innerRadius, innerRadius ), false );
|
||||
path.append( new RoundRectangle2D.Float( x, y, width, height, outerArc, outerArc ), false );
|
||||
path.append( new RoundRectangle2D.Float( x + ow, y + ow, width - (ow * 2), height - (ow * 2), innerArc, innerArc ), false );
|
||||
g.fill( path );
|
||||
}
|
||||
|
||||
@@ -181,7 +221,7 @@ public class FlatUIUtils
|
||||
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
||||
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
|
||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
||||
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||
paintComponentBorderImpl( g2d, x2, y2, width2, height2,
|
||||
(float) (focusWidth * scaleFactor), (float) (lineWidth * scaleFactor), (float) (arc * scaleFactor) );
|
||||
@@ -195,7 +235,12 @@ public class FlatUIUtils
|
||||
private static void paintComponentBorderImpl( Graphics2D g, int x, int y, int width, int height,
|
||||
float focusWidth, float lineWidth, float arc )
|
||||
{
|
||||
float arc2 = arc > lineWidth ? arc - lineWidth : 0f;
|
||||
float arc2 = arc - (lineWidth * 2);
|
||||
|
||||
if( arc < 0 )
|
||||
arc = 0;
|
||||
if( arc2 < 0 )
|
||||
arc2 = 0;
|
||||
|
||||
RoundRectangle2D.Float r1 = new RoundRectangle2D.Float(
|
||||
x + focusWidth, y + focusWidth,
|
||||
@@ -226,7 +271,7 @@ public class FlatUIUtils
|
||||
double systemScaleFactor = UIScale.getSystemScaleFactor( g );
|
||||
if( systemScaleFactor != 1 && systemScaleFactor != 2 ) {
|
||||
// paint at scale 1x to avoid clipping on right and bottom edges at 125%, 150% or 175%
|
||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height, systemScaleFactor,
|
||||
HiDPIUtils.paintAtScale1x( g, x, y, width, height,
|
||||
(g2d, x2, y2, width2, height2, scaleFactor) -> {
|
||||
paintComponentBackgroundImpl( g2d, x2, y2, width2, height2,
|
||||
(float) (focusWidth * scaleFactor), (float) (arc * scaleFactor) );
|
||||
@@ -240,6 +285,9 @@ public class FlatUIUtils
|
||||
private static void paintComponentBackgroundImpl( Graphics2D g, int x, int y, int width, int height,
|
||||
float focusWidth, float arc )
|
||||
{
|
||||
if( arc < 0 )
|
||||
arc = 0;
|
||||
|
||||
g.fill( new RoundRectangle2D.Float(
|
||||
x + focusWidth, y + focusWidth,
|
||||
width - focusWidth * 2, height - focusWidth * 2, arc, arc ) );
|
||||
@@ -278,6 +326,17 @@ public class FlatUIUtils
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a not-filled rectangle shape with the given line width.
|
||||
*/
|
||||
public static Path2D createRectangle( float x, float y, float width, float height, float lineWidth ) {
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Rectangle2D.Float( x, y, width, height ), false );
|
||||
path.append( new Rectangle2D.Float( x + lineWidth, y + lineWidth,
|
||||
width - (lineWidth * 2), height - (lineWidth * 2) ), false );
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.awt.Color;
|
||||
*/
|
||||
public class ColorFunctions
|
||||
{
|
||||
public static Color applyFunctions( Color color, ColorFunction[] functions ) {
|
||||
public static Color applyFunctions( Color color, ColorFunction... functions ) {
|
||||
float[] hsl = HSLColor.fromRGB( color );
|
||||
float alpha = color.getAlpha() / 255f;
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ public class DerivedColor
|
||||
{
|
||||
private final ColorFunction[] functions;
|
||||
|
||||
public DerivedColor( ColorFunction... functions ) {
|
||||
super( Color.red );
|
||||
public DerivedColor( Color defaultColor, ColorFunction... functions ) {
|
||||
super( (defaultColor != null) ? defaultColor : Color.red );
|
||||
this.functions = functions;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,10 +34,6 @@ public class HiDPIUtils
|
||||
paintAtScale1x( g, 0, 0, c.getWidth(), c.getHeight(), painter );
|
||||
}
|
||||
|
||||
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height, Painter painter ) {
|
||||
paintAtScale1x( g, x, y, width, height, UIScale.getSystemScaleFactor( g ), painter );
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint at system scale factor 1x to avoid rounding issues at 125%, 150% and 175% scaling.
|
||||
* <p>
|
||||
@@ -46,38 +42,29 @@ public class HiDPIUtils
|
||||
* <p>
|
||||
* Uses the same scaling calculation as the JRE uses.
|
||||
*/
|
||||
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height,
|
||||
double scaleFactor, Painter painter )
|
||||
{
|
||||
if( scaleFactor == 1 ) {
|
||||
public static void paintAtScale1x( Graphics2D g, int x, int y, int width, int height, Painter painter ) {
|
||||
// save original transform
|
||||
AffineTransform transform = g.getTransform();
|
||||
|
||||
// check whether scaled
|
||||
if( transform.getScaleX() == 1 && transform.getScaleY() == 1 ) {
|
||||
painter.paint( g, x, y, width, height, 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
// save original transform
|
||||
AffineTransform transform = g.getTransform();
|
||||
|
||||
// scale rectangle
|
||||
Rectangle2D.Double scaledRect = scale( transform, x, y, width, height );
|
||||
|
||||
try {
|
||||
// unscale to factor 1.0
|
||||
double scale = 1.0 / scaleFactor;
|
||||
g.scale( scale, scale );
|
||||
|
||||
// compute origin delta x/y
|
||||
double dx = Math.floor( scaledRect.x ) - transform.getTranslateX();
|
||||
double dy = Math.floor( scaledRect.y ) - transform.getTranslateY();
|
||||
|
||||
// move origin to make sure that origin x/y are at whole numbers
|
||||
if( dx != 0 || dy != 0 )
|
||||
g.translate( dx, dy );
|
||||
// unscale to factor 1.0 and move origin (to whole numbers)
|
||||
g.setTransform( new AffineTransform( 1, 0, 0, 1,
|
||||
Math.floor( scaledRect.x ), Math.floor( scaledRect.y ) ) );
|
||||
|
||||
int swidth = (int) scaledRect.width;
|
||||
int sheight = (int) scaledRect.height;
|
||||
|
||||
// paint
|
||||
painter.paint( g, 0, 0, swidth, sheight, scaleFactor );
|
||||
painter.paint( g, 0, 0, swidth, sheight, transform.getScaleX() );
|
||||
} finally {
|
||||
// restore original transform
|
||||
g.setTransform( transform );
|
||||
|
||||
@@ -20,7 +20,10 @@ import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JComponent;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
|
||||
/**
|
||||
* Provides Java version compatibility methods.
|
||||
@@ -52,7 +55,7 @@ public class JavaCompatibility
|
||||
? new Class[] { JComponent.class, Graphics2D.class, String.class, int.class, float.class, float.class }
|
||||
: new Class[] { JComponent.class, Graphics.class, String.class, int.class, int.class, int.class } );
|
||||
} catch( Exception ex ) {
|
||||
ex.printStackTrace();
|
||||
Logger.getLogger( FlatLaf.class.getName() ).log( Level.SEVERE, null, ex );
|
||||
throw new RuntimeException( ex );
|
||||
}
|
||||
}
|
||||
@@ -64,7 +67,7 @@ public class JavaCompatibility
|
||||
else
|
||||
drawStringUnderlineCharAtMethod.invoke( null, c, g, text, underlinedIndex, x, y );
|
||||
} catch( IllegalAccessException | IllegalArgumentException | InvocationTargetException ex ) {
|
||||
ex.printStackTrace();
|
||||
Logger.getLogger( FlatLaf.class.getName() ).log( Level.SEVERE, null, ex );
|
||||
throw new RuntimeException( ex );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Insets;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.lang.reflect.Method;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
@@ -48,12 +49,15 @@ import javax.swing.plaf.UIResource;
|
||||
*
|
||||
* 2) user scaling mode
|
||||
*
|
||||
* This mode is mainly for Java 8 compatibility, but is also used on Linux.
|
||||
* This mode is mainly for Java 8 compatibility, but is also used on Linux
|
||||
* or if the default font is changed.
|
||||
* The user scale factor is computed based on the used font.
|
||||
* The JRE does not scale anything.
|
||||
* So we have to invoke {@link #scale(float)} where necessary.
|
||||
* There is only one user scale factor for all displays.
|
||||
* The user scale factor may change if the active LaF or "Label.font" has changed.
|
||||
* The user scale factor may change if the active LaF, "defaultFont" or "Label.font" has changed.
|
||||
* If system scaling mode is available the user scale factor is usually 1,
|
||||
* but may be larger on Linux or if the default font is changed.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -61,6 +65,20 @@ public class UIScale
|
||||
{
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static PropertyChangeSupport changeSupport;
|
||||
|
||||
public static void addPropertyChangeListener( PropertyChangeListener listener ) {
|
||||
if( changeSupport == null )
|
||||
changeSupport = new PropertyChangeSupport( UIScale.class );
|
||||
changeSupport.addPropertyChangeListener( listener );
|
||||
}
|
||||
|
||||
public static void removePropertyChangeListener( PropertyChangeListener listener ) {
|
||||
if( changeSupport == null )
|
||||
return;
|
||||
changeSupport.removePropertyChangeListener( listener );
|
||||
}
|
||||
|
||||
//---- system scaling (Java 9) --------------------------------------------
|
||||
|
||||
private static Boolean jreHiDPI;
|
||||
@@ -97,7 +115,7 @@ public class UIScale
|
||||
}
|
||||
|
||||
public static double getSystemScaleFactor( GraphicsConfiguration gc ) {
|
||||
return isSystemScalingEnabled() ? gc.getDefaultTransform().getScaleX() : 1;
|
||||
return (isSystemScalingEnabled() && gc != null) ? gc.getDefaultTransform().getScaleX() : 1;
|
||||
}
|
||||
|
||||
//---- user scaling (Java 8) ----------------------------------------------
|
||||
@@ -110,27 +128,33 @@ public class UIScale
|
||||
return;
|
||||
initialized = true;
|
||||
|
||||
if( isUserScalingEnabled() ) {
|
||||
// listener to update scale factor if LaF changed or if Label.font changed
|
||||
// (e.g. option "Override default fonts" in IntelliJ IDEA)
|
||||
PropertyChangeListener listener = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
String propName = e.getPropertyName();
|
||||
if( "lookAndFeel".equals( propName ) ) {
|
||||
if( !isUserScalingEnabled() )
|
||||
return;
|
||||
|
||||
// listener to update scale factor if LaF changed, "defaultFont" or "Label.font" changed
|
||||
PropertyChangeListener listener = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case "lookAndFeel":
|
||||
// it is not necessary (and possible) to remove listener of old LaF defaults
|
||||
if( e.getNewValue() instanceof LookAndFeel )
|
||||
UIManager.getLookAndFeelDefaults().addPropertyChangeListener( this );
|
||||
updateScaleFactor();
|
||||
} else if( "Label.font".equals( propName ) )
|
||||
updateScaleFactor();
|
||||
}
|
||||
};
|
||||
UIManager.addPropertyChangeListener( listener );
|
||||
UIManager.getLookAndFeelDefaults().addPropertyChangeListener( listener );
|
||||
break;
|
||||
|
||||
updateScaleFactor();
|
||||
}
|
||||
case "defaultFont":
|
||||
case "Label.font":
|
||||
updateScaleFactor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
UIManager.addPropertyChangeListener( listener );
|
||||
UIManager.getDefaults().addPropertyChangeListener( listener );
|
||||
UIManager.getLookAndFeelDefaults().addPropertyChangeListener( listener );
|
||||
|
||||
updateScaleFactor();
|
||||
}
|
||||
|
||||
private static void updateScaleFactor() {
|
||||
@@ -141,7 +165,9 @@ public class UIScale
|
||||
// because even if we are on a HiDPI display it is not sure
|
||||
// that a larger font size is set by the current LaF
|
||||
// (e.g. can avoid large icons with small text)
|
||||
Font font = UIManager.getFont( "Label.font" );
|
||||
Font font = UIManager.getFont( "defaultFont" );
|
||||
if( font == null )
|
||||
font = UIManager.getFont( "Label.font" );
|
||||
|
||||
setUserScaleFactor( computeScaleFactor( font ) );
|
||||
}
|
||||
@@ -156,6 +182,9 @@ public class UIScale
|
||||
// Tahoma 11 is used at 100%
|
||||
if( "Tahoma".equals( font.getFamily() ) )
|
||||
fontSizeDivider = 11f;
|
||||
} else if( SystemInfo.IS_MAC ) {
|
||||
// default font size on macOS is 13
|
||||
fontSizeDivider = 13f;
|
||||
} else if( SystemInfo.IS_LINUX ) {
|
||||
// default font size for Unity and Gnome is 15 and for KDE it is 13
|
||||
fontSizeDivider = SystemInfo.IS_KDE ? 13f : 15f;
|
||||
@@ -165,26 +194,17 @@ public class UIScale
|
||||
}
|
||||
|
||||
private static boolean isUserScalingEnabled() {
|
||||
if( isSystemScalingEnabled() && !SystemInfo.IS_LINUX )
|
||||
return false; // disable user scaling if JRE scales
|
||||
|
||||
// same as in IntelliJ IDEA
|
||||
String hidpi = System.getProperty( "hidpi" );
|
||||
return (hidpi != null) ? Boolean.parseBoolean( hidpi ) : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a custom scale factor given in system properties "flatlaf.uiScale"
|
||||
* or "sun.java2d.uiScale" to the given font.
|
||||
* Applies a custom scale factor given in system property "flatlaf.uiScale"
|
||||
* to the given font.
|
||||
*/
|
||||
public static FontUIResource applyCustomScaleFactor( FontUIResource font ) {
|
||||
if( UIScale.isSystemScalingEnabled() )
|
||||
return font;
|
||||
|
||||
String uiScale = System.getProperty( "flatlaf.uiScale" );
|
||||
if( uiScale == null )
|
||||
uiScale = System.getProperty( "sun.java2d.uiScale" );
|
||||
|
||||
float scaleFactor = parseScaleFactor( uiScale );
|
||||
if( scaleFactor <= 0 )
|
||||
return font;
|
||||
@@ -194,15 +214,7 @@ public class UIScale
|
||||
return font;
|
||||
|
||||
int newFontSize = Math.round( (font.getSize() / fontScaleFactor) * scaleFactor );
|
||||
return new FontUIResource( font.getFamily(), font.getStyle(), newFontSize );
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the given font.
|
||||
*/
|
||||
public static FontUIResource scaleFont( FontUIResource font, float scaleFactor ) {
|
||||
int newFontSize = Math.round( font.getSize() * scaleFactor );
|
||||
return new FontUIResource( font.getFamily(), font.getStyle(), newFontSize );
|
||||
return new FontUIResource( font.deriveFont( (float) newFontSize ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,10 +254,14 @@ public class UIScale
|
||||
else // round scale factor to 1/4
|
||||
scaleFactor = Math.round( scaleFactor * 4f ) / 4f;
|
||||
|
||||
float oldScaleFactor = UIScale.scaleFactor;
|
||||
UIScale.scaleFactor = scaleFactor;
|
||||
|
||||
if( DEBUG )
|
||||
System.out.println( "HiDPI scale factor " + scaleFactor );
|
||||
|
||||
if( changeSupport != null )
|
||||
changeSupport.firePropertyChange( "userScaleFactor", oldScaleFactor, scaleFactor );
|
||||
}
|
||||
|
||||
public static float scale( float value ) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
module com.formdev.flatlaf {
|
||||
requires java.desktop;
|
||||
requires java.logging;
|
||||
|
||||
exports com.formdev.flatlaf;
|
||||
exports com.formdev.flatlaf.icons;
|
||||
|
||||
@@ -30,6 +30,12 @@ Component.innerFocusWidth=0
|
||||
Component.arrowType=triangle
|
||||
|
||||
|
||||
#---- ProgressBar ----
|
||||
|
||||
ProgressBar.foreground=#a0a0a0
|
||||
ProgressBar.selectionForeground=@background
|
||||
|
||||
|
||||
#---- RadioButton ----
|
||||
|
||||
RadioButton.icon.centerDiameter=5
|
||||
|
||||
@@ -28,12 +28,15 @@
|
||||
@selectionInactiveForeground=@foreground
|
||||
@disabledText=#777777
|
||||
@textComponentBackground=#45494A
|
||||
@menuBackground=darken(@background,5%)
|
||||
@cellFocusColor=#000000
|
||||
@icon=#adadad
|
||||
|
||||
# Button
|
||||
@buttonHoverBackground=lighten(3%,autoInverse)
|
||||
@buttonPressedBackground=lighten(6%,autoInverse)
|
||||
# Drop (use lazy colors for IntelliJ platform themes, which usually do not specify these colors)
|
||||
@dropCellBackground=darken(List.selectionBackground,10%,lazy)
|
||||
@dropCellForeground=lazy(List.selectionForeground)
|
||||
@dropLineColor=lighten(List.selectionBackground,10%,lazy)
|
||||
@dropLineShortColor=lighten(List.selectionBackground,30%,lazy)
|
||||
|
||||
|
||||
#---- globals ----
|
||||
@@ -58,35 +61,34 @@
|
||||
|
||||
activeCaption=#434E60
|
||||
inactiveCaption=#393C3D
|
||||
controlHighlight=#616669
|
||||
controlLtHighlight=#303234
|
||||
controlShadow=#afb3b5
|
||||
controlDkShadow=#d7d9da
|
||||
controlHighlight=darken($controlShadow,20%)
|
||||
controlLtHighlight=darken($controlShadow,25%)
|
||||
controlDkShadow=lighten($controlShadow,10%)
|
||||
|
||||
|
||||
#---- Button ----
|
||||
|
||||
Button.background=#4c5052
|
||||
Button.hoverBackground=@buttonHoverBackground
|
||||
Button.pressedBackground=@buttonPressedBackground
|
||||
Button.hoverBackground=lighten($Button.background,3%,derived autoInverse)
|
||||
Button.pressedBackground=lighten($Button.background,6%,derived autoInverse)
|
||||
|
||||
Button.borderColor=#5e6060
|
||||
Button.disabledBorderColor=#5e6060
|
||||
Button.focusedBorderColor=#466d94
|
||||
Button.hoverBorderColor=@@Button.focusedBorderColor
|
||||
Button.hoverBorderColor=$Button.focusedBorderColor
|
||||
|
||||
Button.default.background=#365880
|
||||
Button.default.foreground=#bbbbbb
|
||||
Button.default.hoverBackground=@buttonHoverBackground
|
||||
Button.default.pressedBackground=@buttonPressedBackground
|
||||
Button.default.hoverBackground=lighten($Button.default.background,3%,derived autoInverse)
|
||||
Button.default.pressedBackground=lighten($Button.default.background,6%,derived autoInverse)
|
||||
Button.default.borderColor=#4c708c
|
||||
Button.default.hoverBorderColor=#537699
|
||||
Button.default.focusedBorderColor=#537699
|
||||
Button.default.focusColor=#43688c
|
||||
Button.default.boldText=true
|
||||
|
||||
Button.toolbar.hoverBackground=#4c5052
|
||||
Button.toolbar.pressedBackground=#555a5d
|
||||
Button.toolbar.hoverBackground=lighten($Button.background,1%,derived autoInverse)
|
||||
Button.toolbar.pressedBackground=lighten($Button.background,4%,derived autoInverse)
|
||||
|
||||
|
||||
#---- CheckBox ----
|
||||
@@ -95,12 +97,12 @@ CheckBox.icon.borderColor=#6B6B6B
|
||||
CheckBox.icon.disabledBorderColor=#545556
|
||||
CheckBox.icon.selectedBorderColor=#6B6B6B
|
||||
CheckBox.icon.focusedBorderColor=#466D94
|
||||
CheckBox.icon.hoverBorderColor=@@CheckBox.icon.focusedBorderColor
|
||||
CheckBox.icon.hoverBorderColor=$CheckBox.icon.focusedBorderColor
|
||||
CheckBox.icon.selectedFocusedBorderColor=#466D94
|
||||
CheckBox.icon.background=#43494A
|
||||
CheckBox.icon.disabledBackground=@background
|
||||
CheckBox.icon.hoverBackground=@buttonHoverBackground
|
||||
CheckBox.icon.pressedBackground=@buttonPressedBackground
|
||||
CheckBox.icon.hoverBackground=lighten($CheckBox.icon.background,3%,derived autoInverse)
|
||||
CheckBox.icon.pressedBackground=lighten($CheckBox.icon.background,6%,derived autoInverse)
|
||||
CheckBox.icon.selectedBackground=#43494A
|
||||
CheckBox.icon.checkmarkColor=#A7A7A7
|
||||
CheckBox.icon.disabledCheckmarkColor=#606060
|
||||
@@ -125,6 +127,34 @@ Component.focusColor=#3d6185
|
||||
Component.linkColor=#589df6
|
||||
|
||||
|
||||
#---- Desktop ----
|
||||
|
||||
Desktop.background=#3E434C
|
||||
|
||||
|
||||
#---- DesktopIcon ----
|
||||
|
||||
DesktopIcon.background=lighten($Desktop.background,10%)
|
||||
|
||||
|
||||
#---- InternalFrame ----
|
||||
|
||||
InternalFrame.activeTitleBackground=darken(@background,10%)
|
||||
InternalFrame.activeTitleForeground=@foreground
|
||||
InternalFrame.inactiveTitleBackground=darken(@background,5%)
|
||||
InternalFrame.inactiveTitleForeground=@disabledText
|
||||
|
||||
InternalFrame.activeBorderColor=lighten($Component.borderColor,10%)
|
||||
InternalFrame.inactiveBorderColor=$Component.borderColor
|
||||
|
||||
InternalFrame.buttonHoverBackground=lighten($InternalFrame.activeTitleBackground,10%,derived autoInverse)
|
||||
InternalFrame.buttonPressedBackground=lighten($InternalFrame.activeTitleBackground,20%,derived autoInverse)
|
||||
InternalFrame.closeHoverBackground=lazy(Actions.Red)
|
||||
InternalFrame.closePressedBackground=darken(Actions.Red,10%,lazy)
|
||||
InternalFrame.closeHoverForeground=#fff
|
||||
InternalFrame.closePressedForeground=#fff
|
||||
|
||||
|
||||
#---- List ----
|
||||
|
||||
List.background=@textComponentBackground
|
||||
@@ -139,6 +169,7 @@ Menu.icon.disabledArrowColor=#606060
|
||||
#---- MenuBar ----
|
||||
|
||||
MenuBar.borderColor=#515151
|
||||
MenuBar.hoverBackground=lighten($MenuBar.background,10%)
|
||||
|
||||
|
||||
#---- MenuItemCheckBox ----
|
||||
@@ -147,25 +178,30 @@ MenuItemCheckBox.icon.checkmarkColor=#A7A7A7
|
||||
MenuItemCheckBox.icon.disabledCheckmarkColor=#606060
|
||||
|
||||
|
||||
#---- PasswordField ----
|
||||
|
||||
PasswordField.capsLockIconColor=#ffffff64
|
||||
|
||||
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.borderColor=#515151
|
||||
PopupMenu.borderColor=#5e5e5e
|
||||
|
||||
|
||||
#---- ProgressBar ----
|
||||
|
||||
ProgressBar.background=#555555
|
||||
ProgressBar.foreground=#a0a0a0
|
||||
ProgressBar.selectionForeground=@background
|
||||
ProgressBar.foreground=#4A88C7
|
||||
ProgressBar.selectionForeground=@foreground
|
||||
ProgressBar.selectionBackground=@foreground
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
|
||||
ScrollBar.track=#3F4244
|
||||
ScrollBar.thumb=#5B5E5F
|
||||
ScrollBar.hoverTrackColor=#434647
|
||||
ScrollBar.hoverThumbColor=#666868
|
||||
ScrollBar.thumb=lighten($ScrollBar.track,10%)
|
||||
ScrollBar.hoverTrackColor=lighten($ScrollBar.track,4%)
|
||||
ScrollBar.hoverThumbColor=lighten($ScrollBar.thumb,10%)
|
||||
|
||||
|
||||
#---- Separator ----
|
||||
@@ -178,7 +214,7 @@ Separator.foreground=#515151
|
||||
Slider.trackColor=#646464
|
||||
Slider.thumbColor=#A6A6A6
|
||||
Slider.tickColor=#888888
|
||||
Slider.hoverColor=darken(15%,autoInverse)
|
||||
Slider.hoverColor=darken($Slider.thumbColor,15%,derived autoInverse)
|
||||
Slider.disabledForeground=#4c5052
|
||||
|
||||
|
||||
@@ -190,7 +226,7 @@ SplitPaneDivider.oneTouchHoverArrowColor=#7A7D81
|
||||
|
||||
#---- TabbedPane ----
|
||||
|
||||
TabbedPane.disabledForeground=#777777
|
||||
TabbedPane.disabledForeground=@disabledText
|
||||
TabbedPane.underlineColor=#4A88C7
|
||||
TabbedPane.disabledUnderlineColor=#7a7a7a
|
||||
TabbedPane.hoverColor=#2e3133
|
||||
@@ -201,23 +237,23 @@ TabbedPane.contentAreaColor=#323232
|
||||
#---- Table ----
|
||||
|
||||
Table.background=@textComponentBackground
|
||||
Table.gridColor=#4F5152
|
||||
Table.gridColor=lighten($Table.background,3%)
|
||||
|
||||
|
||||
#---- TableHeader ----
|
||||
|
||||
TableHeader.background=#45494A
|
||||
TableHeader.separatorColor=#585858
|
||||
TableHeader.bottomSeparatorColor=#585858
|
||||
TableHeader.background=@textComponentBackground
|
||||
TableHeader.separatorColor=lighten($TableHeader.background,10%)
|
||||
TableHeader.bottomSeparatorColor=$TableHeader.separatorColor
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.selectedBackground=#64696C
|
||||
ToggleButton.selectedBackground=lighten($ToggleButton.background,10%,derived autoInverse)
|
||||
ToggleButton.selectedForeground=@foreground
|
||||
ToggleButton.disabledSelectedBackground=#525658
|
||||
ToggleButton.disabledSelectedBackground=lighten($ToggleButton.background,3%,derived autoInverse)
|
||||
|
||||
ToggleButton.toolbar.selectedBackground=#5c6164
|
||||
ToggleButton.toolbar.selectedBackground=lighten($ToggleButton.background,7%,derived autoInverse)
|
||||
|
||||
|
||||
#---- ToolTip ----
|
||||
|
||||
@@ -22,21 +22,22 @@
|
||||
|
||||
Button.focusedBackground=null
|
||||
|
||||
Button.default.background=#4A86C7
|
||||
Button.default.foreground=#f0f0f0
|
||||
Button.default.background=#4D8AC9
|
||||
Button.default.foreground=#FFFFFF
|
||||
Button.default.focusedBackground=null
|
||||
Button.default.borderColor=#3167ad
|
||||
Button.default.hoverBorderColor=#a8cef6
|
||||
Button.default.focusedBorderColor=#a8cef6
|
||||
Button.default.borderColor=#3D75B2
|
||||
Button.default.hoverBorderColor=#A9C9F5
|
||||
Button.default.focusedBorderColor=#A9C9F5
|
||||
Button.default.focusColor=#97c3f3
|
||||
Button.default.boldText=true
|
||||
Button.default.borderWidth=1
|
||||
|
||||
|
||||
#---- CheckBox ----
|
||||
|
||||
CheckBox.icon.selectedBorderColor=#4982CC
|
||||
CheckBox.icon.selectedBorderColor=#4B97D9
|
||||
CheckBox.icon.selectedFocusedBorderColor=#ACCFF7
|
||||
CheckBox.icon.selectedBackground=#4D89C9
|
||||
CheckBox.icon.selectedBackground=#4F9EE3
|
||||
CheckBox.icon.checkmarkColor=#FFFFFF
|
||||
|
||||
CheckBox.icon.selectedHoverBackground=#5E94CE
|
||||
|
||||
@@ -21,21 +21,26 @@ CheckBoxUI=com.formdev.flatlaf.ui.FlatCheckBoxUI
|
||||
CheckBoxMenuItemUI=com.formdev.flatlaf.ui.FlatCheckBoxMenuItemUI
|
||||
ColorChooserUI=com.formdev.flatlaf.ui.FlatColorChooserUI
|
||||
ComboBoxUI=com.formdev.flatlaf.ui.FlatComboBoxUI
|
||||
DesktopIconUI=com.formdev.flatlaf.ui.FlatDesktopIconUI
|
||||
DesktopPaneUI=com.formdev.flatlaf.ui.FlatDesktopPaneUI
|
||||
EditorPaneUI=com.formdev.flatlaf.ui.FlatEditorPaneUI
|
||||
FileChooserUI=com.formdev.flatlaf.ui.FlatFileChooserUI
|
||||
FormattedTextFieldUI=com.formdev.flatlaf.ui.FlatFormattedTextFieldUI
|
||||
InternalFrameUI=com.formdev.flatlaf.ui.FlatInternalFrameUI
|
||||
LabelUI=com.formdev.flatlaf.ui.FlatLabelUI
|
||||
ListUI=com.formdev.flatlaf.ui.FlatListUI
|
||||
MenuUI=com.formdev.flatlaf.ui.FlatMenuUI
|
||||
MenuBarUI=com.formdev.flatlaf.ui.FlatMenuBarUI
|
||||
MenuItemUI=com.formdev.flatlaf.ui.FlatMenuItemUI
|
||||
OptionPaneUI=com.formdev.flatlaf.ui.FlatOptionPaneUI
|
||||
PanelUI=com.formdev.flatlaf.ui.FlatPanelUI
|
||||
PasswordFieldUI=com.formdev.flatlaf.ui.FlatPasswordFieldUI
|
||||
PopupMenuUI=com.formdev.flatlaf.ui.FlatPopupMenuUI
|
||||
PopupMenuSeparatorUI=com.formdev.flatlaf.ui.FlatPopupMenuSeparatorUI
|
||||
ProgressBarUI=com.formdev.flatlaf.ui.FlatProgressBarUI
|
||||
RadioButtonUI=com.formdev.flatlaf.ui.FlatRadioButtonUI
|
||||
RadioButtonMenuItemUI=com.formdev.flatlaf.ui.FlatRadioButtonMenuItemUI
|
||||
RootPaneUI=com.formdev.flatlaf.ui.FlatRootPaneUI
|
||||
ScrollBarUI=com.formdev.flatlaf.ui.FlatScrollBarUI
|
||||
ScrollPaneUI=com.formdev.flatlaf.ui.FlatScrollPaneUI
|
||||
SeparatorUI=com.formdev.flatlaf.ui.FlatSeparatorUI
|
||||
@@ -59,15 +64,16 @@ ViewportUI=com.formdev.flatlaf.ui.FlatViewportUI
|
||||
#---- variables ----
|
||||
|
||||
@textComponentMargin=2,6,2,6
|
||||
@menuItemMargin=2,8,2,8
|
||||
|
||||
|
||||
#---- system colors ----
|
||||
|
||||
desktop=@textComponentBackground
|
||||
activeCaptionText=@foreground
|
||||
activeCaptionBorder=@@activeCaption
|
||||
activeCaptionBorder=$activeCaption
|
||||
inactiveCaptionText=@foreground
|
||||
inactiveCaptionBorder=@@inactiveCaption
|
||||
inactiveCaptionBorder=$inactiveCaption
|
||||
window=@background
|
||||
windowBorder=@foreground
|
||||
windowText=@foreground
|
||||
@@ -80,11 +86,44 @@ textHighlightText=@selectionForeground
|
||||
textInactiveText=@disabledText
|
||||
control=@background
|
||||
controlText=@foreground
|
||||
scrollbar=@@ScrollBar.track
|
||||
info=@@ToolTip.background
|
||||
controlShadow=$Component.borderColor
|
||||
scrollbar=$ScrollBar.track
|
||||
info=$ToolTip.background
|
||||
infoText=@foreground
|
||||
|
||||
|
||||
#---- unused colors ----
|
||||
|
||||
# Colors that are defined in BasicLookAndFeel but are not used in FlatLaf.
|
||||
# Keep them for compatibility (if used in 3rd party app) and give them useful values.
|
||||
|
||||
*.shadow=$controlShadow
|
||||
*.darkShadow=$controlDkShadow
|
||||
*.light=$controlHighlight
|
||||
*.highlight=$controlLtHighlight
|
||||
|
||||
ComboBox.buttonShadow=$controlShadow
|
||||
ComboBox.buttonDarkShadow=$controlDkShadow
|
||||
ComboBox.buttonHighlight=$controlLtHighlight
|
||||
|
||||
InternalFrame.borderColor=$control
|
||||
InternalFrame.borderShadow=$controlShadow
|
||||
InternalFrame.borderDarkShadow=$controlDkShadow
|
||||
InternalFrame.borderHighlight=$controlLtHighlight
|
||||
InternalFrame.borderLight=$controlHighlight
|
||||
|
||||
Label.disabledShadow=$controlShadow
|
||||
|
||||
ScrollBar.trackHighlight=$controlDkShadow
|
||||
ScrollBar.thumbHighlight=$controlLtHighlight
|
||||
ScrollBar.thumbDarkShadow=$controlDkShadow
|
||||
ScrollBar.thumbShadow=$controlShadow
|
||||
|
||||
Slider.focus=$controlDkShadow
|
||||
|
||||
TabbedPane.focus=$controlText
|
||||
|
||||
|
||||
#---- Button ----
|
||||
|
||||
Button.border=com.formdev.flatlaf.ui.FlatButtonBorder
|
||||
@@ -98,6 +137,9 @@ Button.defaultButtonFollowsFocus=false
|
||||
|
||||
Button.default.borderWidth=1
|
||||
|
||||
Button.toolbar.margin=3,3,3,3
|
||||
Button.toolbar.spacingInsets=1,2,1,2
|
||||
|
||||
|
||||
#---- Caret ----
|
||||
|
||||
@@ -116,34 +158,47 @@ CheckBox.rollover=true
|
||||
|
||||
#---- CheckBoxMenuItem ----
|
||||
|
||||
CheckBoxMenuItem.border=com.formdev.flatlaf.ui.FlatMarginBorder
|
||||
CheckBoxMenuItem.border=com.formdev.flatlaf.ui.FlatMenuItemBorder
|
||||
CheckBoxMenuItem.checkIcon=com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon
|
||||
CheckBoxMenuItem.arrowIcon=com.formdev.flatlaf.icons.FlatMenuItemArrowIcon
|
||||
CheckBoxMenuItem.margin=2,2,2,2
|
||||
CheckBoxMenuItem.margin=@menuItemMargin
|
||||
CheckBoxMenuItem.opaque=false
|
||||
CheckBoxMenuItem.borderPainted=true
|
||||
CheckBoxMenuItem.background=@menuBackground
|
||||
|
||||
|
||||
#---- ColorChooser ----
|
||||
|
||||
ColorChooser.swatchesSwatchSize=16,16
|
||||
ColorChooser.swatchesRecentSwatchSize=16,16
|
||||
ColorChooser.swatchesSwatchSize={scaledDimension}16,16
|
||||
ColorChooser.swatchesRecentSwatchSize={scaledDimension}16,16
|
||||
ColorChooser.swatchesDefaultRecentColor=$control
|
||||
|
||||
|
||||
#---- ComboBox ----
|
||||
|
||||
ComboBox.border=com.formdev.flatlaf.ui.FlatRoundBorder
|
||||
ComboBox.padding=2,6,2,6
|
||||
[mac]ComboBox.showPopupOnNavigation=true
|
||||
|
||||
|
||||
#---- Component ----
|
||||
|
||||
Component.focusWidth=0
|
||||
Component.innerFocusWidth=0
|
||||
Component.innerFocusWidth={float}0.5
|
||||
Component.arc=5
|
||||
Component.minimumWidth=64
|
||||
Component.arrowType=chevron
|
||||
Component.hideMnemonics=true
|
||||
|
||||
|
||||
#---- DesktopIcon ----
|
||||
|
||||
DesktopIcon.border=4,4,4,4
|
||||
DesktopIcon.iconSize=64,64
|
||||
DesktopIcon.closeSize=20,20
|
||||
DesktopIcon.closeIcon=com.formdev.flatlaf.icons.FlatInternalFrameCloseIcon
|
||||
|
||||
|
||||
#---- EditorPane ----
|
||||
|
||||
EditorPane.border=com.formdev.flatlaf.ui.FlatMarginBorder
|
||||
@@ -158,6 +213,7 @@ FileChooser.upFolderIcon=com.formdev.flatlaf.icons.FlatFileChooserUpFolderIcon
|
||||
FileChooser.homeFolderIcon=com.formdev.flatlaf.icons.FlatFileChooserHomeFolderIcon
|
||||
FileChooser.detailsViewIcon=com.formdev.flatlaf.icons.FlatFileChooserDetailsViewIcon
|
||||
FileChooser.listViewIcon=com.formdev.flatlaf.icons.FlatFileChooserListViewIcon
|
||||
FileChooser.usesSingleFilePane=true
|
||||
|
||||
|
||||
#---- FileView ----
|
||||
@@ -171,7 +227,7 @@ FileView.floppyDriveIcon=com.formdev.flatlaf.icons.FlatFileViewFloppyDriveIcon
|
||||
|
||||
#---- FormattedTextField ----
|
||||
|
||||
FormattedTextField.border=com.formdev.flatlaf.ui.FlatBorder
|
||||
FormattedTextField.border=com.formdev.flatlaf.ui.FlatTextBorder
|
||||
FormattedTextField.margin=@textComponentMargin
|
||||
FormattedTextField.background=@textComponentBackground
|
||||
FormattedTextField.placeholderForeground=@disabledText
|
||||
@@ -180,46 +236,83 @@ FormattedTextField.placeholderForeground=@disabledText
|
||||
#---- HelpButton ----
|
||||
|
||||
HelpButton.icon=com.formdev.flatlaf.icons.FlatHelpButtonIcon
|
||||
HelpButton.borderColor=@@CheckBox.icon.borderColor
|
||||
HelpButton.disabledBorderColor=@@CheckBox.icon.disabledBorderColor
|
||||
HelpButton.focusedBorderColor=@@CheckBox.icon.focusedBorderColor
|
||||
HelpButton.hoverBorderColor=@@?CheckBox.icon.hoverBorderColor
|
||||
HelpButton.background=@@CheckBox.icon.background
|
||||
HelpButton.disabledBackground=@@CheckBox.icon.disabledBackground
|
||||
HelpButton.focusedBackground=@@?CheckBox.icon.focusedBackground
|
||||
HelpButton.hoverBackground=@@?CheckBox.icon.hoverBackground
|
||||
HelpButton.pressedBackground=@@?CheckBox.icon.pressedBackground
|
||||
HelpButton.questionMarkColor=@@CheckBox.icon.checkmarkColor
|
||||
HelpButton.disabledQuestionMarkColor=@@CheckBox.icon.disabledCheckmarkColor
|
||||
HelpButton.borderColor=$CheckBox.icon.borderColor
|
||||
HelpButton.disabledBorderColor=$CheckBox.icon.disabledBorderColor
|
||||
HelpButton.focusedBorderColor=$CheckBox.icon.focusedBorderColor
|
||||
HelpButton.hoverBorderColor=$?CheckBox.icon.hoverBorderColor
|
||||
HelpButton.background=$CheckBox.icon.background
|
||||
HelpButton.disabledBackground=$CheckBox.icon.disabledBackground
|
||||
HelpButton.focusedBackground=$?CheckBox.icon.focusedBackground
|
||||
HelpButton.hoverBackground=$?CheckBox.icon.hoverBackground
|
||||
HelpButton.pressedBackground=$?CheckBox.icon.pressedBackground
|
||||
HelpButton.questionMarkColor=$CheckBox.icon.checkmarkColor
|
||||
HelpButton.disabledQuestionMarkColor=$CheckBox.icon.disabledCheckmarkColor
|
||||
|
||||
|
||||
#---- InternalFrame ----
|
||||
|
||||
InternalFrame.border=com.formdev.flatlaf.ui.FlatInternalFrameUI$FlatInternalFrameBorder
|
||||
InternalFrame.borderLineWidth=1
|
||||
InternalFrame.borderMargins=6,6,6,6
|
||||
InternalFrame.buttonSize=24,24
|
||||
InternalFrame.closeIcon=com.formdev.flatlaf.icons.FlatInternalFrameCloseIcon
|
||||
InternalFrame.iconifyIcon=com.formdev.flatlaf.icons.FlatInternalFrameIconifyIcon
|
||||
InternalFrame.maximizeIcon=com.formdev.flatlaf.icons.FlatInternalFrameMaximizeIcon
|
||||
InternalFrame.minimizeIcon=com.formdev.flatlaf.icons.FlatInternalFrameMinimizeIcon
|
||||
InternalFrame.windowBindings=null
|
||||
|
||||
|
||||
#---- InternalFrameTitlePane ----
|
||||
|
||||
InternalFrameTitlePane.border=0,8,0,0
|
||||
|
||||
|
||||
#---- List ----
|
||||
|
||||
List.border=1,0,1,0
|
||||
List.cellNoFocusBorder=1,6,1,6
|
||||
List.focusCellHighlightBorder=1,6,1,6,@cellFocusColor
|
||||
List.focusSelectedCellHighlightBorder=1,6,1,6,@cellFocusColor
|
||||
List.border=0,0,0,0
|
||||
List.cellMargins=1,6,1,6
|
||||
List.cellFocusColor=@cellFocusColor
|
||||
List.cellNoFocusBorder=com.formdev.flatlaf.ui.FlatListCellBorder$Default
|
||||
List.focusCellHighlightBorder=com.formdev.flatlaf.ui.FlatListCellBorder$Focused
|
||||
List.focusSelectedCellHighlightBorder=com.formdev.flatlaf.ui.FlatListCellBorder$Selected
|
||||
List.selectionInactiveBackground=@selectionInactiveBackground
|
||||
List.selectionInactiveForeground=@selectionInactiveForeground
|
||||
List.dropCellBackground=@dropCellBackground
|
||||
List.dropCellForeground=@dropCellForeground
|
||||
List.dropLineColor=@dropLineColor
|
||||
|
||||
|
||||
#---- Menu ----
|
||||
|
||||
Menu.border=com.formdev.flatlaf.ui.FlatMarginBorder
|
||||
Menu.border=com.formdev.flatlaf.ui.FlatMenuItemBorder
|
||||
Menu.arrowIcon=com.formdev.flatlaf.icons.FlatMenuArrowIcon
|
||||
Menu.margin=2,2,2,2
|
||||
Menu.checkIcon=null
|
||||
Menu.margin=@menuItemMargin
|
||||
Menu.submenuPopupOffsetX={scaledInteger}-4
|
||||
Menu.submenuPopupOffsetY={scaledInteger}-4
|
||||
Menu.opaque=false
|
||||
Menu.borderPainted=true
|
||||
Menu.background=@menuBackground
|
||||
|
||||
|
||||
#---- MenuBar ----
|
||||
|
||||
MenuBar.border=com.formdev.flatlaf.ui.FlatMenuBarBorder
|
||||
MenuBar.background=@menuBackground
|
||||
MenuBar.itemMargins=3,3,3,3
|
||||
|
||||
|
||||
#---- MenuItem ----
|
||||
|
||||
MenuItem.border=com.formdev.flatlaf.ui.FlatMarginBorder
|
||||
MenuItem.border=com.formdev.flatlaf.ui.FlatMenuItemBorder
|
||||
MenuItem.arrowIcon=com.formdev.flatlaf.icons.FlatMenuItemArrowIcon
|
||||
MenuItem.margin=2,2,2,2
|
||||
MenuItem.checkIcon=null
|
||||
MenuItem.margin=@menuItemMargin
|
||||
MenuItem.opaque=false
|
||||
MenuItem.borderPainted=true
|
||||
MenuItem.background=@menuBackground
|
||||
MenuItem.acceleratorDelimiter=-
|
||||
[mac]MenuItem.acceleratorDelimiter=
|
||||
|
||||
|
||||
#---- OptionPane ----
|
||||
@@ -247,16 +340,19 @@ OptionPane.warningIcon=com.formdev.flatlaf.icons.FlatOptionPaneWarningIcon
|
||||
|
||||
#---- PasswordField ----
|
||||
|
||||
PasswordField.border=com.formdev.flatlaf.ui.FlatBorder
|
||||
PasswordField.border=com.formdev.flatlaf.ui.FlatTextBorder
|
||||
PasswordField.margin=@textComponentMargin
|
||||
PasswordField.background=@textComponentBackground
|
||||
PasswordField.placeholderForeground=@disabledText
|
||||
PasswordField.echoChar=\u2022
|
||||
PasswordField.capsLockIcon=com.formdev.flatlaf.icons.FlatCapsLockIcon
|
||||
|
||||
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.border=com.formdev.flatlaf.ui.FlatPopupMenuBorder
|
||||
PopupMenu.borderInsets=1,1,1,1
|
||||
PopupMenu.borderInsets=4,1,4,1
|
||||
PopupMenu.background=@menuBackground
|
||||
|
||||
|
||||
#---- PopupMenuSeparator ----
|
||||
@@ -272,6 +368,8 @@ ProgressBar.border=com.formdev.flatlaf.ui.FlatEmptyBorder
|
||||
ProgressBar.arc=4
|
||||
ProgressBar.horizontalSize=146,4
|
||||
ProgressBar.verticalSize=4,146
|
||||
ProgressBar.cycleTime=4000
|
||||
ProgressBar.repaintInterval=15
|
||||
|
||||
|
||||
#---- RadioButton ----
|
||||
@@ -286,10 +384,13 @@ RadioButton.rollover=true
|
||||
|
||||
#---- RadioButtonMenuItem ----
|
||||
|
||||
RadioButtonMenuItem.border=com.formdev.flatlaf.ui.FlatMarginBorder
|
||||
RadioButtonMenuItem.border=com.formdev.flatlaf.ui.FlatMenuItemBorder
|
||||
RadioButtonMenuItem.checkIcon=com.formdev.flatlaf.icons.FlatRadioButtonMenuItemIcon
|
||||
RadioButtonMenuItem.arrowIcon=com.formdev.flatlaf.icons.FlatMenuItemArrowIcon
|
||||
RadioButtonMenuItem.margin=2,2,2,2
|
||||
RadioButtonMenuItem.margin=@menuItemMargin
|
||||
RadioButtonMenuItem.opaque=false
|
||||
RadioButtonMenuItem.borderPainted=true
|
||||
RadioButtonMenuItem.background=@menuBackground
|
||||
|
||||
|
||||
#---- ScrollBar ----
|
||||
@@ -297,15 +398,17 @@ RadioButtonMenuItem.margin=2,2,2,2
|
||||
ScrollBar.width=10
|
||||
ScrollBar.showButtons=false
|
||||
ScrollBar.squareButtons=false
|
||||
ScrollBar.buttonArrowColor=@@ComboBox.buttonArrowColor
|
||||
ScrollBar.buttonDisabledArrowColor=@@ComboBox.buttonDisabledArrowColor
|
||||
ScrollBar.buttonArrowColor=$ComboBox.buttonArrowColor
|
||||
ScrollBar.buttonDisabledArrowColor=$ComboBox.buttonDisabledArrowColor
|
||||
ScrollBar.allowsAbsolutePositioning=true
|
||||
|
||||
|
||||
#---- ScrollPane ----
|
||||
|
||||
ScrollPane.border=com.formdev.flatlaf.ui.FlatBorder
|
||||
ScrollPane.background=@@ScrollBar.track
|
||||
ScrollPane.background=$ScrollBar.track
|
||||
ScrollPane.fillUpperCorner=true
|
||||
ScrollPane.smoothScrolling=true
|
||||
|
||||
|
||||
#---- Separator ----
|
||||
@@ -326,10 +429,10 @@ Slider.thumbWidth=11
|
||||
|
||||
Spinner.border=com.formdev.flatlaf.ui.FlatRoundBorder
|
||||
Spinner.background=@textComponentBackground
|
||||
Spinner.buttonBackground=@@ComboBox.buttonEditableBackground
|
||||
Spinner.buttonArrowColor=@@ComboBox.buttonArrowColor
|
||||
Spinner.buttonDisabledArrowColor=@@ComboBox.buttonDisabledArrowColor
|
||||
Spinner.buttonHoverArrowColor=@@ComboBox.buttonHoverArrowColor
|
||||
Spinner.buttonBackground=$ComboBox.buttonEditableBackground
|
||||
Spinner.buttonArrowColor=$ComboBox.buttonArrowColor
|
||||
Spinner.buttonDisabledArrowColor=$ComboBox.buttonDisabledArrowColor
|
||||
Spinner.buttonHoverArrowColor=$ComboBox.buttonHoverArrowColor
|
||||
Spinner.padding=@textComponentMargin
|
||||
Spinner.editorBorderPainted=false
|
||||
|
||||
@@ -344,7 +447,7 @@ SplitPane.oneTouchButtonSize={scaledInteger}6
|
||||
SplitPane.oneTouchButtonOffset={scaledInteger}2
|
||||
|
||||
SplitPaneDivider.border=null
|
||||
SplitPaneDivider.oneTouchArrowColor=@@ComboBox.buttonArrowColor
|
||||
SplitPaneDivider.oneTouchArrowColor=$ComboBox.buttonArrowColor
|
||||
|
||||
|
||||
#---- TabbedPane ----
|
||||
@@ -358,26 +461,40 @@ TabbedPane.tabAreaInsets=0,0,0,0
|
||||
TabbedPane.selectedTabPadInsets=0,0,0,0
|
||||
TabbedPane.tabRunOverlay=0
|
||||
TabbedPane.tabsOverlapBorder=true
|
||||
TabbedPane.shadow=@@ComboBox.buttonArrowColor
|
||||
TabbedPane.shadow=@background
|
||||
TabbedPane.contentBorderInsets=null
|
||||
|
||||
|
||||
#---- Table ----
|
||||
|
||||
Table.rowHeight=20
|
||||
Table.showHorizontalLines=false
|
||||
Table.showVerticalLines=false
|
||||
Table.intercellSpacing={dimension}0,0
|
||||
Table.scrollPaneBorder=com.formdev.flatlaf.ui.FlatBorder
|
||||
Table.ascendingSortIcon=com.formdev.flatlaf.icons.FlatAscendingSortIcon
|
||||
Table.descendingSortIcon=com.formdev.flatlaf.icons.FlatDescendingSortIcon
|
||||
Table.sortIconColor=@icon
|
||||
Table.cellNoFocusBorder=2,3,2,3
|
||||
Table.focusSelectedCellHighlightBorder=2,3,2,3,@cellFocusColor
|
||||
Table.cellMargins=2,3,2,3
|
||||
Table.cellFocusColor=@cellFocusColor
|
||||
Table.cellNoFocusBorder=com.formdev.flatlaf.ui.FlatTableCellBorder$Default
|
||||
Table.focusCellHighlightBorder=com.formdev.flatlaf.ui.FlatTableCellBorder$Focused
|
||||
Table.focusSelectedCellHighlightBorder=com.formdev.flatlaf.ui.FlatTableCellBorder$Selected
|
||||
Table.focusCellBackground=@textComponentBackground
|
||||
Table.focusCellForeground=@foreground
|
||||
Table.selectionInactiveBackground=@selectionInactiveBackground
|
||||
Table.selectionInactiveForeground=@selectionInactiveForeground
|
||||
Table.dropCellBackground=@dropCellBackground
|
||||
Table.dropCellForeground=@dropCellForeground
|
||||
Table.dropLineColor=@dropLineColor
|
||||
Table.dropLineShortColor=@dropLineShortColor
|
||||
|
||||
|
||||
#---- TableHeader ----
|
||||
|
||||
TableHeader.height=25
|
||||
TableHeader.cellBorder=2,3,2,3
|
||||
TableHeader.focusCellBackground=$TableHeader.background
|
||||
|
||||
|
||||
#---- TextArea ----
|
||||
@@ -387,9 +504,16 @@ TextArea.margin=@textComponentMargin
|
||||
TextArea.background=@textComponentBackground
|
||||
|
||||
|
||||
#---- TextComponent ----
|
||||
|
||||
# allowed values: "never", "once" (default) or "always"
|
||||
TextComponent.selectAllOnFocusPolicy=once
|
||||
TextComponent.arc=0
|
||||
|
||||
|
||||
#---- TextField ----
|
||||
|
||||
TextField.border=com.formdev.flatlaf.ui.FlatBorder
|
||||
TextField.border=com.formdev.flatlaf.ui.FlatTextBorder
|
||||
TextField.margin=@textComponentMargin
|
||||
TextField.background=@textComponentBackground
|
||||
TextField.placeholderForeground=@disabledText
|
||||
@@ -405,7 +529,7 @@ TextPane.background=@textComponentBackground
|
||||
#---- TitledBorder ----
|
||||
|
||||
TitledBorder.titleColor=@foreground
|
||||
TitledBorder.border=1,1,1,1,@@Separator.foreground
|
||||
TitledBorder.border=1,1,1,1,$Separator.foreground
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
@@ -415,32 +539,49 @@ ToggleButton.margin=2,14,2,14
|
||||
ToggleButton.iconTextGap=4
|
||||
ToggleButton.rollover=true
|
||||
|
||||
ToggleButton.background=@@Button.background
|
||||
ToggleButton.pressedBackground=@@Button.pressedBackground
|
||||
ToggleButton.background=$Button.background
|
||||
ToggleButton.pressedBackground=$Button.pressedBackground
|
||||
|
||||
ToggleButton.toolbar.hoverBackground=@@Button.toolbar.hoverBackground
|
||||
ToggleButton.toolbar.pressedBackground=@@Button.toolbar.pressedBackground
|
||||
ToggleButton.toolbar.hoverBackground=$Button.toolbar.hoverBackground
|
||||
ToggleButton.toolbar.pressedBackground=$Button.toolbar.pressedBackground
|
||||
|
||||
# button type "tab"
|
||||
ToggleButton.tab.underlineHeight=2
|
||||
ToggleButton.tab.underlineColor=$TabbedPane.underlineColor
|
||||
ToggleButton.tab.disabledUnderlineColor=$TabbedPane.disabledUnderlineColor
|
||||
ToggleButton.tab.selectedBackground=$?TabbedPane.selectedBackground
|
||||
ToggleButton.tab.hoverBackground=$TabbedPane.hoverColor
|
||||
ToggleButton.tab.focusBackground=$TabbedPane.focusColor
|
||||
|
||||
|
||||
#---- ToolBar ----
|
||||
|
||||
ToolBar.border=com.formdev.flatlaf.ui.FlatToolBarBorder
|
||||
ToolBar.borderMargins=2,2,2,2
|
||||
ToolBar.isRollover=true
|
||||
ToolBar.buttonMargins=3,3,3,3
|
||||
ToolBar.gripColor=@icon
|
||||
ToolBar.dockingBackground=@background
|
||||
ToolBar.dockingForeground=@foreground
|
||||
ToolBar.floatingBackground=@background
|
||||
ToolBar.floatingForeground=@disabledText
|
||||
|
||||
ToolBar.separatorSize=null
|
||||
ToolBar.separatorWidth=7
|
||||
ToolBar.separatorColor=@@Separator.foreground
|
||||
ToolBar.separatorColor=$Separator.foreground
|
||||
|
||||
ToolBar.spacingBorder=$Button.toolbar.spacingInsets
|
||||
|
||||
|
||||
#---- ToolTipManager ----
|
||||
|
||||
ToolTipManager.enableToolTipMode=activeApplication
|
||||
|
||||
|
||||
#---- ToolTip ----
|
||||
|
||||
ToolTip.border=4,6,4,6,@@Component.borderColor
|
||||
ToolTip.border=4,6,4,6,$Component.borderColor
|
||||
ToolTip.borderInactive=null
|
||||
ToolTip.backgroundInactive=@@ToolTip.background
|
||||
ToolTip.backgroundInactive=$ToolTip.background
|
||||
ToolTip.foregroundInactive=@disabledText
|
||||
|
||||
|
||||
@@ -449,9 +590,15 @@ ToolTip.foregroundInactive=@disabledText
|
||||
Tree.border=1,1,1,1
|
||||
Tree.selectionInactiveBackground=@selectionInactiveBackground
|
||||
Tree.selectionInactiveForeground=@selectionInactiveForeground
|
||||
Tree.textBackground=null
|
||||
Tree.textBackground=$Tree.background
|
||||
Tree.selectionBorderColor=@cellFocusColor
|
||||
Tree.dropCellBackground=@dropCellBackground
|
||||
Tree.dropCellForeground=@dropCellForeground
|
||||
Tree.dropLineColor=@dropLineColor
|
||||
Tree.rendererFillBackground=false
|
||||
Tree.rendererMargins=1,2,1,2
|
||||
Tree.wideSelection=true
|
||||
Tree.repaintWholeRow=true
|
||||
Tree.paintLines=false
|
||||
Tree.leftChildIndent=7
|
||||
Tree.rightChildIndent=11
|
||||
|
||||
@@ -22,18 +22,21 @@
|
||||
|
||||
@background=#f2f2f2
|
||||
@foreground=#000000
|
||||
@selectionBackground=#4A6EB7
|
||||
@selectionBackground=#2675BF
|
||||
@selectionForeground=#ffffff
|
||||
@selectionInactiveBackground=#d4d4d4
|
||||
@selectionInactiveForeground=@foreground
|
||||
@disabledText=#999999
|
||||
@disabledText=#8C8C8C
|
||||
@textComponentBackground=#ffffff
|
||||
@menuBackground=#fff
|
||||
@cellFocusColor=#000000
|
||||
@icon=#afafaf
|
||||
|
||||
# Button
|
||||
@buttonHoverBackground=darken(3%,autoInverse)
|
||||
@buttonPressedBackground=darken(10%,autoInverse)
|
||||
# Drop (use lazy colors for IntelliJ platform themes, which usually do not specify these colors)
|
||||
@dropCellBackground=lighten(List.selectionBackground,10%,lazy)
|
||||
@dropCellForeground=lazy(List.selectionForeground)
|
||||
@dropLineColor=lighten(List.selectionBackground,20%,lazy)
|
||||
@dropLineShortColor=darken(List.selectionBackground,20%,lazy)
|
||||
|
||||
|
||||
#---- globals ----
|
||||
@@ -44,7 +47,7 @@
|
||||
*.textForeground=@foreground
|
||||
*.caretForeground=@foreground
|
||||
*.inactiveBackground=@background
|
||||
*.inactiveForeground=#777777
|
||||
*.inactiveForeground=@disabledText
|
||||
*.selectionBackground=@selectionBackground
|
||||
*.selectionForeground=@selectionForeground
|
||||
*.disabledBackground=@background
|
||||
@@ -60,51 +63,50 @@ activeCaption=#99b4d1
|
||||
inactiveCaption=#bfcddb
|
||||
controlHighlight=#e3e3e3
|
||||
controlLtHighlight=#fff
|
||||
controlShadow=#a0a0a0
|
||||
controlDkShadow=#696969
|
||||
controlDkShadow=darken($controlShadow,15%)
|
||||
|
||||
|
||||
#---- Button ----
|
||||
|
||||
Button.background=#ffffff
|
||||
Button.focusedBackground=#e3f1fa
|
||||
Button.hoverBackground=@buttonHoverBackground
|
||||
Button.pressedBackground=@buttonPressedBackground
|
||||
Button.hoverBackground=darken($Button.background,3%,derived autoInverse)
|
||||
Button.pressedBackground=darken($Button.background,10%,derived autoInverse)
|
||||
|
||||
Button.borderColor=#bfbfbf
|
||||
Button.disabledBorderColor=#cfcfcf
|
||||
Button.focusedBorderColor=#87afda
|
||||
Button.hoverBorderColor=@@Button.focusedBorderColor
|
||||
Button.borderColor=$Component.borderColor
|
||||
Button.disabledBorderColor=$Component.disabledBorderColor
|
||||
Button.focusedBorderColor=$Component.focusedBorderColor
|
||||
Button.hoverBorderColor=$Button.focusedBorderColor
|
||||
|
||||
Button.default.background=@@Button.background
|
||||
Button.default.background=$Button.background
|
||||
Button.default.foreground=@foreground
|
||||
Button.default.focusedBackground=@@Button.focusedBackground
|
||||
Button.default.hoverBackground=@buttonHoverBackground
|
||||
Button.default.pressedBackground=@buttonPressedBackground
|
||||
Button.default.borderColor=#4D89C9
|
||||
Button.default.hoverBorderColor=@@Button.hoverBorderColor
|
||||
Button.default.focusedBorderColor=@@Button.focusedBorderColor
|
||||
Button.default.focusColor=@@Component.focusColor
|
||||
Button.default.focusedBackground=$Button.focusedBackground
|
||||
Button.default.hoverBackground=$Button.hoverBackground
|
||||
Button.default.pressedBackground=$Button.pressedBackground
|
||||
Button.default.borderColor=#4F9EE3
|
||||
Button.default.hoverBorderColor=$Button.hoverBorderColor
|
||||
Button.default.focusedBorderColor=$Button.focusedBorderColor
|
||||
Button.default.focusColor=$Component.focusColor
|
||||
Button.default.borderWidth=2
|
||||
|
||||
Button.toolbar.hoverBackground=#dfdfdf
|
||||
Button.toolbar.pressedBackground=#d8d8d8
|
||||
Button.toolbar.hoverBackground=darken($Button.background,12%,derived autoInverse)
|
||||
Button.toolbar.pressedBackground=darken($Button.background,15%,derived autoInverse)
|
||||
|
||||
|
||||
#---- CheckBox ----
|
||||
|
||||
CheckBox.icon.borderColor=#878787
|
||||
CheckBox.icon.borderColor=#b0b0b0
|
||||
CheckBox.icon.disabledBorderColor=#BDBDBD
|
||||
CheckBox.icon.selectedBorderColor=#878787
|
||||
CheckBox.icon.selectedBorderColor=$CheckBox.icon.borderColor
|
||||
CheckBox.icon.focusedBorderColor=#7B9FC7
|
||||
CheckBox.icon.hoverBorderColor=@@CheckBox.icon.focusedBorderColor
|
||||
CheckBox.icon.hoverBorderColor=$CheckBox.icon.focusedBorderColor
|
||||
CheckBox.icon.background=#FFFFFF
|
||||
CheckBox.icon.disabledBackground=@background
|
||||
CheckBox.icon.focusedBackground=@@Button.focusedBackground
|
||||
CheckBox.icon.hoverBackground=@buttonHoverBackground
|
||||
CheckBox.icon.pressedBackground=@buttonPressedBackground
|
||||
CheckBox.icon.focusedBackground=$Button.focusedBackground
|
||||
CheckBox.icon.hoverBackground=$Button.hoverBackground
|
||||
CheckBox.icon.pressedBackground=$Button.pressedBackground
|
||||
CheckBox.icon.selectedBackground=#FFFFFF
|
||||
CheckBox.icon.checkmarkColor=#4D89C9
|
||||
CheckBox.icon.checkmarkColor=#4F9EE3
|
||||
CheckBox.icon.disabledCheckmarkColor=#ABABAB
|
||||
|
||||
|
||||
@@ -124,12 +126,40 @@ Component.borderColor=#c4c4c4
|
||||
Component.disabledBorderColor=#cfcfcf
|
||||
Component.focusedBorderColor=#87afda
|
||||
Component.focusColor=#97c3f3
|
||||
Component.linkColor=#4a78c2
|
||||
Component.linkColor=#2470B3
|
||||
|
||||
|
||||
#---- Desktop ----
|
||||
|
||||
Desktop.background=#E6EBF0
|
||||
|
||||
|
||||
#---- DesktopIcon ----
|
||||
|
||||
DesktopIcon.background=darken($Desktop.background,10%)
|
||||
|
||||
|
||||
#---- HelpButton ----
|
||||
|
||||
HelpButton.questionMarkColor=#4D89C9
|
||||
HelpButton.questionMarkColor=#4F9EE3
|
||||
|
||||
|
||||
#---- InternalFrame ----
|
||||
|
||||
InternalFrame.activeTitleBackground=#fff
|
||||
InternalFrame.activeTitleForeground=@foreground
|
||||
InternalFrame.inactiveTitleBackground=#fafafa
|
||||
InternalFrame.inactiveTitleForeground=@disabledText
|
||||
|
||||
InternalFrame.activeBorderColor=darken($Component.borderColor,20%)
|
||||
InternalFrame.inactiveBorderColor=$Component.borderColor
|
||||
|
||||
InternalFrame.buttonHoverBackground=darken($InternalFrame.activeTitleBackground,10%,derived autoInverse)
|
||||
InternalFrame.buttonPressedBackground=darken($InternalFrame.activeTitleBackground,20%,derived autoInverse)
|
||||
InternalFrame.closeHoverBackground=lazy(Actions.Red)
|
||||
InternalFrame.closePressedBackground=darken(Actions.Red,10%,lazy)
|
||||
InternalFrame.closeHoverForeground=#fff
|
||||
InternalFrame.closePressedForeground=#fff
|
||||
|
||||
|
||||
#---- List ----
|
||||
@@ -146,23 +176,29 @@ Menu.icon.disabledArrowColor=#ABABAB
|
||||
#---- MenuBar ----
|
||||
|
||||
MenuBar.borderColor=#cdcdcd
|
||||
MenuBar.hoverBackground=darken($MenuBar.background,10%)
|
||||
|
||||
|
||||
#---- MenuItemCheckBox ----
|
||||
|
||||
MenuItemCheckBox.icon.checkmarkColor=#4D89C9
|
||||
MenuItemCheckBox.icon.checkmarkColor=#4F9EE3
|
||||
MenuItemCheckBox.icon.disabledCheckmarkColor=#ABABAB
|
||||
|
||||
|
||||
#---- PasswordField ----
|
||||
|
||||
PasswordField.capsLockIconColor=#00000064
|
||||
|
||||
|
||||
#---- PopupMenu ----
|
||||
|
||||
PopupMenu.borderColor=#cdcdcd
|
||||
PopupMenu.borderColor=#adadad
|
||||
|
||||
|
||||
#---- ProgressBar ----
|
||||
|
||||
ProgressBar.background=#c4c4c4
|
||||
ProgressBar.foreground=#808080
|
||||
ProgressBar.background=#D1D1D1
|
||||
ProgressBar.foreground=#1E82E6
|
||||
ProgressBar.selectionForeground=@textComponentBackground
|
||||
ProgressBar.selectionBackground=@foreground
|
||||
|
||||
@@ -170,14 +206,14 @@ ProgressBar.selectionBackground=@foreground
|
||||
#---- ScrollBar ----
|
||||
|
||||
ScrollBar.track=#F5F5F5
|
||||
ScrollBar.thumb=#DBDBDB
|
||||
ScrollBar.hoverTrackColor=#e6e6e6
|
||||
ScrollBar.hoverThumbColor=#c6c6c6
|
||||
ScrollBar.thumb=darken($ScrollBar.track,10%)
|
||||
ScrollBar.hoverTrackColor=darken($ScrollBar.track,3%)
|
||||
ScrollBar.hoverThumbColor=darken($ScrollBar.thumb,10%)
|
||||
|
||||
|
||||
#---- Separator ----
|
||||
|
||||
Separator.foreground=#cdcdcd
|
||||
Separator.foreground=#d1d1d1
|
||||
|
||||
|
||||
#---- Slider ----
|
||||
@@ -185,7 +221,7 @@ Separator.foreground=#cdcdcd
|
||||
Slider.trackColor=#c4c4c4
|
||||
Slider.thumbColor=#6e6e6e
|
||||
Slider.tickColor=#888888
|
||||
Slider.hoverColor=lighten(15%,autoInverse)
|
||||
Slider.hoverColor=lighten($Slider.thumbColor,15%,derived autoInverse)
|
||||
Slider.disabledForeground=#c0c0c0
|
||||
|
||||
|
||||
@@ -197,7 +233,7 @@ SplitPaneDivider.oneTouchHoverArrowColor=#333333
|
||||
|
||||
#---- TabbedPane ----
|
||||
|
||||
TabbedPane.disabledForeground=#999999
|
||||
TabbedPane.disabledForeground=@disabledText
|
||||
TabbedPane.underlineColor=#4083C9
|
||||
TabbedPane.disabledUnderlineColor=#ababab
|
||||
TabbedPane.hoverColor=#d9d9d9
|
||||
@@ -208,23 +244,23 @@ TabbedPane.contentAreaColor=#bfbfbf
|
||||
#---- Table ----
|
||||
|
||||
Table.background=@textComponentBackground
|
||||
Table.gridColor=#F7F7F7
|
||||
Table.gridColor=darken($Table.background,3%)
|
||||
|
||||
|
||||
#---- TableHeader ----
|
||||
|
||||
TableHeader.background=#ffffff
|
||||
TableHeader.separatorColor=#e5e5e5
|
||||
TableHeader.bottomSeparatorColor=#e5e5e5
|
||||
TableHeader.background=@textComponentBackground
|
||||
TableHeader.separatorColor=darken($TableHeader.background,10%)
|
||||
TableHeader.bottomSeparatorColor=$TableHeader.separatorColor
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.selectedBackground=#cfcfcf
|
||||
ToggleButton.selectedBackground=darken($ToggleButton.background,20%,derived autoInverse)
|
||||
ToggleButton.selectedForeground=@foreground
|
||||
ToggleButton.disabledSelectedBackground=#dfdfdf
|
||||
ToggleButton.disabledSelectedBackground=darken($ToggleButton.background,13%,derived autoInverse)
|
||||
|
||||
ToggleButton.toolbar.selectedBackground=#cfcfcf
|
||||
ToggleButton.toolbar.selectedBackground=$ToggleButton.selectedBackground
|
||||
|
||||
|
||||
#---- ToolTip ----
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
|
||||
#---- Button ----
|
||||
|
||||
Button.startBackground=$Button.background
|
||||
Button.endBackground=$Button.background
|
||||
Button.startBorderColor=$Button.borderColor
|
||||
Button.endBorderColor=$Button.borderColor
|
||||
|
||||
Button.default.startBackground=$Button.default.background
|
||||
Button.default.endBackground=$Button.default.background
|
||||
Button.default.startBorderColor=$Button.default.borderColor
|
||||
Button.default.endBorderColor=$Button.default.borderColor
|
||||
|
||||
Button.hoverBorderColor=null
|
||||
Button.default.hoverBorderColor=null
|
||||
|
||||
@@ -23,3 +33,32 @@ Button.default.hoverBorderColor=null
|
||||
#---- HelpButton ----
|
||||
|
||||
HelpButton.hoverBorderColor=null
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.startBackground=$ToggleButton.background
|
||||
ToggleButton.endBackground=$ToggleButton.background
|
||||
[dark]ToggleButton.selectedBackground=lighten($ToggleButton.background,15%,derived autoInverse)
|
||||
[dark]ToggleButton.disabledSelectedBackground=lighten($ToggleButton.background,5%,derived autoInverse)
|
||||
|
||||
|
||||
#---- theme specific ----
|
||||
|
||||
[Gruvbox_Dark_Hard]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Hard]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[Gruvbox_Dark_Medium]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Medium]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[Gruvbox_Dark_Soft]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground=$ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground=$ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[High_contrast]ToggleButton.selectedBackground=#fff
|
||||
[High_contrast]ToggleButton.selectedForeground=#000
|
||||
[High_contrast]ToggleButton.disabledSelectedBackground=#444
|
||||
[High_contrast]ToggleButton.toolbar.selectedBackground=#fff
|
||||
|
||||
7
flatlaf-core/svg/CapsLockIcon.svg
Normal file
7
flatlaf-core/svg/CapsLockIcon.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||
<rect width="6" height="2" x="5" y="12" fill="#FFF"/>
|
||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 326 B |
Binary file not shown.
13
flatlaf-demo/DemoLaf.properties
Normal file
13
flatlaf-demo/DemoLaf.properties
Normal file
@@ -0,0 +1,13 @@
|
||||
# This file demonstrates using a FlatLaf theme file in the FlatLaf Demo application.
|
||||
# Must be in the working directory of the Demo application.
|
||||
# Shown in the "Themes" list under category "Current Directory".
|
||||
#
|
||||
# Modifications to this file are automatically loaded by the FlatLaf Demo application
|
||||
# when the Demo window is activated.
|
||||
|
||||
|
||||
# base theme (light, dark, intellij or darcula)
|
||||
@baseTheme=light
|
||||
|
||||
# add you theme defaults here
|
||||
@background=#ccc
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -14,29 +14,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
version = rootProject.version
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
id( "com.jfrog.bintray" ) version "1.8.4"
|
||||
id( "com.jfrog.bintray" )
|
||||
|
||||
// Although artifactory plugin is not used in this subproject, the plugin is required
|
||||
// because otherwise gradle fails with following error:
|
||||
// Caused by: org.codehaus.groovy.runtime.typehandling.GroovyCastException:
|
||||
// Cannot cast object 'task ':bintrayUpload''
|
||||
// with class 'com.jfrog.bintray.gradle.tasks.BintrayUploadTask_Decorated'
|
||||
// to class 'com.jfrog.bintray.gradle.tasks.BintrayUploadTask'
|
||||
id( "com.jfrog.artifactory" )
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation( project( ":flatlaf-core" ) )
|
||||
implementation( project( ":flatlaf-extras" ) )
|
||||
implementation( project( ":flatlaf-intellij-themes" ) )
|
||||
implementation( "com.miglayout:miglayout-swing:5.2" )
|
||||
implementation( "com.jgoodies:jgoodies-forms:1.9.0" )
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
tasks {
|
||||
jar {
|
||||
dependsOn( ":flatlaf-core:jar" )
|
||||
dependsOn( ":flatlaf-extras:jar" )
|
||||
dependsOn( ":flatlaf-intellij-themes:jar" )
|
||||
|
||||
manifest {
|
||||
attributes( "Main-Class" to "com.formdev.flatlaf.demo.FlatLafDemo" )
|
||||
@@ -46,14 +49,18 @@ tasks {
|
||||
|
||||
// include all dependencies in jar
|
||||
from( {
|
||||
configurations.runtimeClasspath.get().filter { it.name.endsWith( "jar" ) }.map { zipTree( it ) }
|
||||
configurations.runtimeClasspath.get()
|
||||
.filter { it.name.endsWith( "jar" ) }
|
||||
.map { zipTree( it ).matching {
|
||||
exclude( "META-INF/LICENSE" )
|
||||
} }
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
bintray {
|
||||
user = System.getenv( "BINTRAY_USER" ) ?: System.getProperty( "bintray.user" )
|
||||
key = System.getenv( "BINTRAY_KEY" ) ?: System.getProperty( "bintray.key" )
|
||||
user = rootProject.extra["bintray.user"] as String?
|
||||
key = rootProject.extra["bintray.key"] as String?
|
||||
|
||||
setConfigurations( "archives" )
|
||||
|
||||
@@ -67,6 +74,7 @@ bintray {
|
||||
name = project.version.toString()
|
||||
}
|
||||
|
||||
publish = true
|
||||
publish = rootProject.extra["bintray.publish"] as Boolean
|
||||
dryRun = rootProject.extra["bintray.dryRun"] as Boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.demo;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.DefaultEditorKit;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -37,6 +38,8 @@ class BasicComponentsPanel
|
||||
JLabel buttonLabel = new JLabel();
|
||||
JButton button1 = new JButton();
|
||||
JButton button2 = new JButton();
|
||||
JButton button5 = new JButton();
|
||||
JButton button6 = new JButton();
|
||||
JButton button3 = new JButton();
|
||||
JButton button4 = new JButton();
|
||||
JButton button13 = new JButton();
|
||||
@@ -111,6 +114,10 @@ class BasicComponentsPanel
|
||||
JScrollPane scrollPane12 = new JScrollPane();
|
||||
JTextPane textPane4 = new JTextPane();
|
||||
JTextPane textPane5 = new JTextPane();
|
||||
JPopupMenu popupMenu1 = new JPopupMenu();
|
||||
JMenuItem cutMenuItem = new JMenuItem();
|
||||
JMenuItem copyMenuItem = new JMenuItem();
|
||||
JMenuItem pasteMenuItem = new JMenuItem();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
@@ -166,10 +173,21 @@ class BasicComponentsPanel
|
||||
button2.setEnabled(false);
|
||||
add(button2, "cell 2 1");
|
||||
|
||||
//---- button5 ----
|
||||
button5.setText("square");
|
||||
button5.putClientProperty("JButton.buttonType", "square");
|
||||
add(button5, "cell 3 1");
|
||||
|
||||
//---- button6 ----
|
||||
button6.setText("square");
|
||||
button6.setEnabled(false);
|
||||
button6.putClientProperty("JButton.buttonType", "square");
|
||||
add(button6, "cell 4 1");
|
||||
|
||||
//---- button3 ----
|
||||
button3.setText("Help");
|
||||
button3.putClientProperty("JButton.buttonType", "help");
|
||||
add(button3, "cell 3 1");
|
||||
add(button3, "cell 4 1");
|
||||
|
||||
//---- button4 ----
|
||||
button4.setText("Help");
|
||||
@@ -247,6 +265,8 @@ class BasicComponentsPanel
|
||||
|
||||
//---- comboBoxLabel ----
|
||||
comboBoxLabel.setText("JComboBox:");
|
||||
comboBoxLabel.setDisplayedMnemonic('C');
|
||||
comboBoxLabel.setLabelFor(comboBox1);
|
||||
add(comboBoxLabel, "cell 0 4");
|
||||
|
||||
//---- comboBox1 ----
|
||||
@@ -290,17 +310,18 @@ class BasicComponentsPanel
|
||||
add(comboBox4, "cell 4 4,growx");
|
||||
|
||||
//---- comboBox5 ----
|
||||
comboBox5.setPrototypeDisplayValue("12345");
|
||||
comboBox5.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||
"wide popup if text is longer",
|
||||
"aa",
|
||||
"bbb",
|
||||
"cccc"
|
||||
}));
|
||||
add(comboBox5, "cell 5 4,growx");
|
||||
add(comboBox5, "cell 5 4,growx,wmax 100");
|
||||
|
||||
//---- spinnerLabel ----
|
||||
spinnerLabel.setText("JSpinner:");
|
||||
spinnerLabel.setLabelFor(spinner1);
|
||||
spinnerLabel.setDisplayedMnemonic('S');
|
||||
add(spinnerLabel, "cell 0 5");
|
||||
add(spinner1, "cell 1 5,growx");
|
||||
|
||||
@@ -315,10 +336,13 @@ class BasicComponentsPanel
|
||||
|
||||
//---- textFieldLabel ----
|
||||
textFieldLabel.setText("JTextField:");
|
||||
textFieldLabel.setDisplayedMnemonic('T');
|
||||
textFieldLabel.setLabelFor(textField1);
|
||||
add(textFieldLabel, "cell 0 6");
|
||||
|
||||
//---- textField1 ----
|
||||
textField1.setText("editable");
|
||||
textField1.setComponentPopupMenu(popupMenu1);
|
||||
add(textField1, "cell 1 6,growx");
|
||||
|
||||
//---- textField2 ----
|
||||
@@ -343,10 +367,13 @@ class BasicComponentsPanel
|
||||
|
||||
//---- formattedTextFieldLabel ----
|
||||
formattedTextFieldLabel.setText("JFormattedTextField:");
|
||||
formattedTextFieldLabel.setLabelFor(formattedTextField1);
|
||||
formattedTextFieldLabel.setDisplayedMnemonic('O');
|
||||
add(formattedTextFieldLabel, "cell 0 7");
|
||||
|
||||
//---- formattedTextField1 ----
|
||||
formattedTextField1.setText("editable");
|
||||
formattedTextField1.setComponentPopupMenu(popupMenu1);
|
||||
add(formattedTextField1, "cell 1 7,growx");
|
||||
|
||||
//---- formattedTextField2 ----
|
||||
@@ -569,7 +596,27 @@ class BasicComponentsPanel
|
||||
//---- textPane5 ----
|
||||
textPane5.setText("no scroll pane");
|
||||
add(textPane5, "cell 5 11,growx");
|
||||
|
||||
//======== popupMenu1 ========
|
||||
{
|
||||
|
||||
//---- cutMenuItem ----
|
||||
cutMenuItem.setText("Cut");
|
||||
popupMenu1.add(cutMenuItem);
|
||||
|
||||
//---- copyMenuItem ----
|
||||
copyMenuItem.setText("Copy");
|
||||
popupMenu1.add(copyMenuItem);
|
||||
|
||||
//---- pasteMenuItem ----
|
||||
pasteMenuItem.setText("Paste");
|
||||
popupMenu1.add(pasteMenuItem);
|
||||
}
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
|
||||
cutMenuItem.addActionListener( new DefaultEditorKit.CutAction() );
|
||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "13.0.1" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -54,12 +54,27 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "button5"
|
||||
"text": "square"
|
||||
"$client.JButton.buttonType": "square"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "button6"
|
||||
"text": "square"
|
||||
"enabled": false
|
||||
"$client.JButton.buttonType": "square"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "button3"
|
||||
"text": "Help"
|
||||
"$client.JButton.buttonType": "help"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 1"
|
||||
"value": "cell 4 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JButton" ) {
|
||||
name: "button4"
|
||||
@@ -168,6 +183,8 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "comboBoxLabel"
|
||||
"text": "JComboBox:"
|
||||
"displayedMnemonic": 67
|
||||
"labelFor": new FormReference( "comboBox1" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 4"
|
||||
} )
|
||||
@@ -225,7 +242,6 @@ new FormModel {
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||
name: "comboBox5"
|
||||
"prototypeDisplayValue": "12345"
|
||||
"model": new javax.swing.DefaultComboBoxModel {
|
||||
selectedItem: "wide popup if text is longer"
|
||||
addElement( "wide popup if text is longer" )
|
||||
@@ -234,11 +250,13 @@ new FormModel {
|
||||
addElement( "cccc" )
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 4,growx"
|
||||
"value": "cell 5 4,growx,wmax 100"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "spinnerLabel"
|
||||
"text": "JSpinner:"
|
||||
"labelFor": new FormReference( "spinner1" )
|
||||
"displayedMnemonic": 83
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 5"
|
||||
} )
|
||||
@@ -266,12 +284,15 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "textFieldLabel"
|
||||
"text": "JTextField:"
|
||||
"displayedMnemonic": 84
|
||||
"labelFor": new FormReference( "textField1" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "textField1"
|
||||
"text": "editable"
|
||||
"componentPopupMenu": &FormReference0 new FormReference( "popupMenu1" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 6,growx"
|
||||
} )
|
||||
@@ -306,12 +327,15 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "formattedTextFieldLabel"
|
||||
"text": "JFormattedTextField:"
|
||||
"labelFor": new FormReference( "formattedTextField1" )
|
||||
"displayedMnemonic": 79
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 7"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JFormattedTextField" ) {
|
||||
name: "formattedTextField1"
|
||||
"text": "editable"
|
||||
"componentPopupMenu": #FormReference0
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 7,growx"
|
||||
} )
|
||||
@@ -570,7 +594,25 @@ new FormModel {
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 790, 715 )
|
||||
"size": new java.awt.Dimension( 790, 440 )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
|
||||
name: "popupMenu1"
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "cutMenuItem"
|
||||
"text": "Cut"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "copyMenuItem"
|
||||
"text": "Copy"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "pasteMenuItem"
|
||||
"text": "Paste"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 500 )
|
||||
"size": new java.awt.Dimension( 91, 87 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,11 @@ class ControlBar
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
UIScale.addPropertyChangeListener( e -> {
|
||||
// update info label because user scale factor may change
|
||||
updateInfoLabel();
|
||||
} );
|
||||
}
|
||||
|
||||
void initialize( JFrame frame, JTabbedPane tabbedPane ) {
|
||||
|
||||
@@ -16,8 +16,12 @@
|
||||
|
||||
package com.formdev.flatlaf.demo;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.*;
|
||||
import javax.swing.tree.*;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -30,22 +34,58 @@ class DataComponentsPanel
|
||||
initComponents();
|
||||
}
|
||||
|
||||
private void dndChanged() {
|
||||
boolean dnd = dndCheckBox.isSelected();
|
||||
list1.setDragEnabled( dnd );
|
||||
list2.setDragEnabled( dnd );
|
||||
tree1.setDragEnabled( dnd );
|
||||
tree2.setDragEnabled( dnd );
|
||||
table1.setDragEnabled( dnd );
|
||||
|
||||
DropMode dropMode = dnd ? DropMode.ON_OR_INSERT : DropMode.USE_SELECTION;
|
||||
list1.setDropMode( dropMode );
|
||||
tree1.setDropMode( dropMode );
|
||||
table1.setDropMode( dropMode );
|
||||
|
||||
String key = "FlatLaf.oldTransferHandler";
|
||||
if( dnd ) {
|
||||
list1.putClientProperty( key, list1.getTransferHandler() );
|
||||
list1.setTransferHandler( new DummyTransferHandler() );
|
||||
|
||||
tree1.putClientProperty( key, tree1.getTransferHandler() );
|
||||
tree1.setTransferHandler( new DummyTransferHandler() );
|
||||
|
||||
table1.putClientProperty( key, table1.getTransferHandler() );
|
||||
table1.setTransferHandler( new DummyTransferHandler() );
|
||||
} else {
|
||||
list1.setTransferHandler( (TransferHandler) list1.getClientProperty( key ) );
|
||||
tree1.setTransferHandler( (TransferHandler) tree1.getClientProperty( key ) );
|
||||
table1.setTransferHandler( (TransferHandler) table1.getClientProperty( key ) );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JLabel listLabel = new JLabel();
|
||||
JScrollPane scrollPane1 = new JScrollPane();
|
||||
JList<String> list1 = new JList<>();
|
||||
list1 = new JList<>();
|
||||
JScrollPane scrollPane2 = new JScrollPane();
|
||||
JList<String> list2 = new JList<>();
|
||||
list2 = new JList<>();
|
||||
JLabel treeLabel = new JLabel();
|
||||
JScrollPane scrollPane3 = new JScrollPane();
|
||||
JTree tree1 = new JTree();
|
||||
tree1 = new JTree();
|
||||
JScrollPane scrollPane4 = new JScrollPane();
|
||||
JTree tree2 = new JTree();
|
||||
tree2 = new JTree();
|
||||
JLabel tableLabel = new JLabel();
|
||||
JScrollPane scrollPane5 = new JScrollPane();
|
||||
JTable table1 = new JTable();
|
||||
table1 = new JTable();
|
||||
dndCheckBox = new JCheckBox();
|
||||
JPopupMenu popupMenu2 = new JPopupMenu();
|
||||
JMenuItem menuItem3 = new JMenuItem();
|
||||
JMenuItem menuItem4 = new JMenuItem();
|
||||
JMenuItem menuItem5 = new JMenuItem();
|
||||
JMenuItem menuItem6 = new JMenuItem();
|
||||
|
||||
//======== this ========
|
||||
setLayout(new MigLayout(
|
||||
@@ -57,7 +97,8 @@ class DataComponentsPanel
|
||||
// rows
|
||||
"[]" +
|
||||
"[::200]" +
|
||||
"[::150]"));
|
||||
"[::150]" +
|
||||
"[]"));
|
||||
|
||||
//---- listLabel ----
|
||||
listLabel.setText("JList:");
|
||||
@@ -65,36 +106,57 @@ class DataComponentsPanel
|
||||
|
||||
//======== scrollPane1 ========
|
||||
{
|
||||
scrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
|
||||
scrollPane1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
|
||||
//---- list1 ----
|
||||
list1.setModel(new AbstractListModel<String>() {
|
||||
String[] values = {
|
||||
"abc",
|
||||
"de",
|
||||
"f"
|
||||
"item 1",
|
||||
"item 2",
|
||||
"item 3",
|
||||
"item 4",
|
||||
"item 5",
|
||||
"item 6",
|
||||
"item 7",
|
||||
"item 8",
|
||||
"item 9",
|
||||
"item 10",
|
||||
"item 11",
|
||||
"item 12",
|
||||
"item 13",
|
||||
"item 14",
|
||||
"item 15"
|
||||
};
|
||||
@Override
|
||||
public int getSize() { return values.length; }
|
||||
@Override
|
||||
public String getElementAt(int i) { return values[i]; }
|
||||
});
|
||||
list1.setComponentPopupMenu(popupMenu2);
|
||||
scrollPane1.setViewportView(list1);
|
||||
}
|
||||
add(scrollPane1, "cell 1 0,growx");
|
||||
|
||||
//======== scrollPane2 ========
|
||||
{
|
||||
scrollPane2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
|
||||
scrollPane2.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
|
||||
//---- list2 ----
|
||||
list2.setModel(new AbstractListModel<String>() {
|
||||
String[] values = {
|
||||
"abc",
|
||||
"de",
|
||||
"f"
|
||||
"item 1",
|
||||
"item 2",
|
||||
"item 3",
|
||||
"item 4",
|
||||
"item 5",
|
||||
"item 6",
|
||||
"item 7",
|
||||
"item 8",
|
||||
"item 9",
|
||||
"item 10",
|
||||
"item 11",
|
||||
"item 12",
|
||||
"item 13",
|
||||
"item 14",
|
||||
"item 15"
|
||||
};
|
||||
@Override
|
||||
public int getSize() { return values.length; }
|
||||
@@ -115,6 +177,34 @@ class DataComponentsPanel
|
||||
|
||||
//---- tree1 ----
|
||||
tree1.setShowsRootHandles(true);
|
||||
tree1.setEditable(true);
|
||||
tree1.setModel(new DefaultTreeModel(
|
||||
new DefaultMutableTreeNode("JTree") {
|
||||
{
|
||||
DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("colors");
|
||||
node1.add(new DefaultMutableTreeNode("blue"));
|
||||
node1.add(new DefaultMutableTreeNode("violet"));
|
||||
node1.add(new DefaultMutableTreeNode("red"));
|
||||
node1.add(new DefaultMutableTreeNode("yellow"));
|
||||
add(node1);
|
||||
node1 = new DefaultMutableTreeNode("sports");
|
||||
node1.add(new DefaultMutableTreeNode("basketball"));
|
||||
node1.add(new DefaultMutableTreeNode("soccer"));
|
||||
node1.add(new DefaultMutableTreeNode("football"));
|
||||
node1.add(new DefaultMutableTreeNode("hockey"));
|
||||
add(node1);
|
||||
node1 = new DefaultMutableTreeNode("food");
|
||||
node1.add(new DefaultMutableTreeNode("hot dogs"));
|
||||
DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("pizza");
|
||||
node2.add(new DefaultMutableTreeNode("pizza aglio e olio"));
|
||||
node2.add(new DefaultMutableTreeNode("pizza margherita bianca"));
|
||||
node1.add(node2);
|
||||
node1.add(new DefaultMutableTreeNode("ravioli"));
|
||||
node1.add(new DefaultMutableTreeNode("bananas"));
|
||||
add(node1);
|
||||
}
|
||||
}));
|
||||
tree1.setComponentPopupMenu(popupMenu2);
|
||||
scrollPane3.setViewportView(tree1);
|
||||
}
|
||||
add(scrollPane3, "cell 1 1,growx");
|
||||
@@ -138,8 +228,18 @@ class DataComponentsPanel
|
||||
//---- table1 ----
|
||||
table1.setModel(new DefaultTableModel(
|
||||
new Object[][] {
|
||||
{"Item 1a", "Item 2a", "January", "July", 123, null},
|
||||
{"Item 1b", "Item 2b", "February", "August", 456, true},
|
||||
{"item 1", "item 1b", "January", "July", 123, null},
|
||||
{"item 2", "item 2b", "February", "August", 456, true},
|
||||
{"item 3", null, "March", null, null, null},
|
||||
{"item 4", null, "April", null, null, null},
|
||||
{"item 5", null, "May", null, null, null},
|
||||
{"item 6", null, "June", null, null, null},
|
||||
{"item 7", null, "July", null, null, null},
|
||||
{"item 8", null, "August", null, null, null},
|
||||
{"item 9", null, "September", null, null, null},
|
||||
{"item 10", null, "October", null, null, null},
|
||||
{"item 11", null, "November", null, null, null},
|
||||
{"item 12", null, "December", null, null, null},
|
||||
},
|
||||
new String[] {
|
||||
"Not editable", "Text", "Combo", "Combo Editable", "Integer", "Boolean"
|
||||
@@ -194,14 +294,85 @@ class DataComponentsPanel
|
||||
}))));
|
||||
}
|
||||
table1.setAutoCreateRowSorter(true);
|
||||
table1.setComponentPopupMenu(popupMenu2);
|
||||
scrollPane5.setViewportView(table1);
|
||||
}
|
||||
add(scrollPane5, "cell 1 2 2 1,growx,width 300");
|
||||
|
||||
//---- dndCheckBox ----
|
||||
dndCheckBox.setText("enable drag and drop");
|
||||
dndCheckBox.setMnemonic('D');
|
||||
dndCheckBox.addActionListener(e -> dndChanged());
|
||||
add(dndCheckBox, "cell 0 3 3 1");
|
||||
|
||||
//======== popupMenu2 ========
|
||||
{
|
||||
|
||||
//---- menuItem3 ----
|
||||
menuItem3.setText("Some Action");
|
||||
popupMenu2.add(menuItem3);
|
||||
|
||||
//---- menuItem4 ----
|
||||
menuItem4.setText("More Action");
|
||||
popupMenu2.add(menuItem4);
|
||||
popupMenu2.addSeparator();
|
||||
|
||||
//---- menuItem5 ----
|
||||
menuItem5.setText("No Action");
|
||||
popupMenu2.add(menuItem5);
|
||||
|
||||
//---- menuItem6 ----
|
||||
menuItem6.setText("Noop Action");
|
||||
popupMenu2.add(menuItem6);
|
||||
}
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
|
||||
((JComboBox)((DefaultCellEditor)table1.getColumnModel().getColumn( 3 ).getCellEditor()).getComponent()).setEditable( true );
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JList<String> list1;
|
||||
private JList<String> list2;
|
||||
private JTree tree1;
|
||||
private JTree tree2;
|
||||
private JTable table1;
|
||||
private JCheckBox dndCheckBox;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
//---- class DummyTransferHandler -----------------------------------------
|
||||
|
||||
private static class DummyTransferHandler
|
||||
extends TransferHandler
|
||||
{
|
||||
@Override
|
||||
protected Transferable createTransferable( JComponent c ) {
|
||||
if( c instanceof JList && ((JList<?>)c).isSelectionEmpty() )
|
||||
return null;
|
||||
if( c instanceof JTree && ((JTree)c).isSelectionEmpty() )
|
||||
return null;
|
||||
if( c instanceof JTable && ((JTable)c).getSelectionModel().isSelectionEmpty() )
|
||||
return null;
|
||||
|
||||
return new StringSelection( "dummy" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSourceActions( JComponent c ) {
|
||||
return COPY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canImport( TransferSupport support ) {
|
||||
return support.isDataFlavorSupported( DataFlavor.stringFlavor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean importData( TransferSupport support ) {
|
||||
String message = String.valueOf( support.getDropLocation() );
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
JOptionPane.showMessageDialog( null, message, "Drop", JOptionPane.PLAIN_MESSAGE );
|
||||
} );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.2" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -9,7 +9,7 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "hidemode 3"
|
||||
"$columnConstraints": "[][200][200]"
|
||||
"$rowConstraints": "[][::200][::150]"
|
||||
"$rowConstraints": "[][::200][::150][]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
@@ -20,17 +20,29 @@ new FormModel {
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "scrollPane1"
|
||||
"verticalScrollBarPolicy": 21
|
||||
"horizontalScrollBarPolicy": 31
|
||||
add( new FormComponent( "javax.swing.JList" ) {
|
||||
name: "list1"
|
||||
"model": &DefaultListModel0 new javax.swing.DefaultListModel {
|
||||
addElement( "abc" )
|
||||
addElement( "de" )
|
||||
addElement( "f" )
|
||||
"model": new javax.swing.DefaultListModel {
|
||||
addElement( "item 1" )
|
||||
addElement( "item 2" )
|
||||
addElement( "item 3" )
|
||||
addElement( "item 4" )
|
||||
addElement( "item 5" )
|
||||
addElement( "item 6" )
|
||||
addElement( "item 7" )
|
||||
addElement( "item 8" )
|
||||
addElement( "item 9" )
|
||||
addElement( "item 10" )
|
||||
addElement( "item 11" )
|
||||
addElement( "item 12" )
|
||||
addElement( "item 13" )
|
||||
addElement( "item 14" )
|
||||
addElement( "item 15" )
|
||||
}
|
||||
"componentPopupMenu": new FormReference( "popupMenu2" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.typeParameters": "String"
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -38,14 +50,29 @@ new FormModel {
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "scrollPane2"
|
||||
"verticalScrollBarPolicy": 21
|
||||
"horizontalScrollBarPolicy": 31
|
||||
add( new FormComponent( "javax.swing.JList" ) {
|
||||
name: "list2"
|
||||
"model": #DefaultListModel0
|
||||
"model": new javax.swing.DefaultListModel {
|
||||
addElement( "item 1" )
|
||||
addElement( "item 2" )
|
||||
addElement( "item 3" )
|
||||
addElement( "item 4" )
|
||||
addElement( "item 5" )
|
||||
addElement( "item 6" )
|
||||
addElement( "item 7" )
|
||||
addElement( "item 8" )
|
||||
addElement( "item 9" )
|
||||
addElement( "item 10" )
|
||||
addElement( "item 11" )
|
||||
addElement( "item 12" )
|
||||
addElement( "item 13" )
|
||||
addElement( "item 14" )
|
||||
addElement( "item 15" )
|
||||
}
|
||||
"enabled": false
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.typeParameters": "String"
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -62,6 +89,65 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JTree" ) {
|
||||
name: "tree1"
|
||||
"showsRootHandles": true
|
||||
"editable": true
|
||||
"model": new javax.swing.tree.DefaultTreeModel( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "JTree"
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "colors"
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "blue"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "violet"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "red"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "yellow"
|
||||
} )
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "sports"
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "basketball"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "soccer"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "football"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "hockey"
|
||||
} )
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "food"
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "hot dogs"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "pizza"
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "pizza aglio e olio"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "pizza margherita bianca"
|
||||
} )
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "ravioli"
|
||||
} )
|
||||
add( new javax.swing.tree.DefaultMutableTreeNode {
|
||||
userObject: "bananas"
|
||||
} )
|
||||
} )
|
||||
} )
|
||||
"componentPopupMenu": new FormReference( "popupMenu2" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1,growx"
|
||||
@@ -71,6 +157,9 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JTree" ) {
|
||||
name: "tree2"
|
||||
"enabled": false
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1,growx"
|
||||
@@ -87,21 +176,101 @@ new FormModel {
|
||||
name: "table1"
|
||||
"model": new com.jformdesigner.model.SwingTableModel( new java.util.Vector {
|
||||
add( new java.util.Vector {
|
||||
add( "Item 1a" )
|
||||
add( "Item 2a" )
|
||||
add( "item 1" )
|
||||
add( "item 1b" )
|
||||
add( "January" )
|
||||
add( "July" )
|
||||
add( 123 )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "Item 1b" )
|
||||
add( "Item 2b" )
|
||||
add( "item 2" )
|
||||
add( "item 2b" )
|
||||
add( "February" )
|
||||
add( "August" )
|
||||
add( 456 )
|
||||
add( true )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 3" )
|
||||
add( null )
|
||||
add( "March" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 4" )
|
||||
add( null )
|
||||
add( "April" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 5" )
|
||||
add( null )
|
||||
add( "May" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 6" )
|
||||
add( null )
|
||||
add( "June" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 7" )
|
||||
add( null )
|
||||
add( "July" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 8" )
|
||||
add( null )
|
||||
add( "August" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 9" )
|
||||
add( null )
|
||||
add( "September" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 10" )
|
||||
add( null )
|
||||
add( "October" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 11" )
|
||||
add( null )
|
||||
add( "November" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
add( new java.util.Vector {
|
||||
add( "item 12" )
|
||||
add( null )
|
||||
add( "December" )
|
||||
add( null )
|
||||
add( null )
|
||||
add( null )
|
||||
} )
|
||||
}, new java.util.Vector {
|
||||
add( "Not editable" )
|
||||
add( "Text" )
|
||||
@@ -132,13 +301,52 @@ new FormModel {
|
||||
add( null )
|
||||
} )
|
||||
"autoCreateRowSorter": true
|
||||
"componentPopupMenu": new FormReference( "popupMenu2" )
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2 2 1,growx,width 300"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "dndCheckBox"
|
||||
"text": "enable drag and drop"
|
||||
"mnemonic": 68
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "dndChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3 3 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 790, 715 )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
|
||||
name: "popupMenu2"
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "menuItem3"
|
||||
"text": "Some Action"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "menuItem4"
|
||||
"text": "More Action"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||
name: "separator1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "menuItem5"
|
||||
"text": "No Action"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "menuItem6"
|
||||
"text": "Noop Action"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 740 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.formdev.flatlaf.demo;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.DefaultEditorKit;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.demo.intellijthemes.*;
|
||||
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
||||
import net.miginfocom.swing.*;
|
||||
@@ -51,6 +53,53 @@ class DemoFrame
|
||||
DemoPrefs.getState().putInt( FlatLafDemo.KEY_TAB, tabbedPane.getSelectedIndex() );
|
||||
}
|
||||
|
||||
private void menuItemActionPerformed( ActionEvent e ) {
|
||||
SwingUtilities.invokeLater( () -> {
|
||||
JOptionPane.showMessageDialog( this, e.getActionCommand(), "Menu Item", JOptionPane.PLAIN_MESSAGE );
|
||||
} );
|
||||
}
|
||||
|
||||
private void fontFamilyChanged( ActionEvent e ) {
|
||||
String fontFamily = e.getActionCommand();
|
||||
|
||||
Font font = UIManager.getFont( "defaultFont" );
|
||||
Font newFont = new Font( fontFamily, font.getStyle(), font.getSize() );
|
||||
UIManager.put( "defaultFont", newFont );
|
||||
|
||||
FlatLaf.updateUI();
|
||||
}
|
||||
|
||||
private void fontSizeChanged( ActionEvent e ) {
|
||||
String fontSizeStr = e.getActionCommand();
|
||||
|
||||
Font font = UIManager.getFont( "defaultFont" );
|
||||
Font newFont = font.deriveFont( (float) Integer.parseInt( fontSizeStr ) );
|
||||
UIManager.put( "defaultFont", newFont );
|
||||
|
||||
FlatLaf.updateUI();
|
||||
}
|
||||
|
||||
private void restoreFont() {
|
||||
UIManager.put( "defaultFont", null );
|
||||
FlatLaf.updateUI();
|
||||
}
|
||||
|
||||
private void incrFont() {
|
||||
Font font = UIManager.getFont( "defaultFont" );
|
||||
Font newFont = font.deriveFont( (float) (font.getSize() + 1) );
|
||||
UIManager.put( "defaultFont", newFont );
|
||||
|
||||
FlatLaf.updateUI();
|
||||
}
|
||||
|
||||
private void decrFont() {
|
||||
Font font = UIManager.getFont( "defaultFont" );
|
||||
Font newFont = font.deriveFont( (float) Math.max( font.getSize() - 1, 8 ) );
|
||||
UIManager.put( "defaultFont", newFont );
|
||||
|
||||
FlatLaf.updateUI();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||
JMenuBar menuBar1 = new JMenuBar();
|
||||
@@ -68,9 +117,21 @@ class DemoFrame
|
||||
JMenuItem deleteMenuItem = new JMenuItem();
|
||||
JMenu viewMenu = new JMenu();
|
||||
JCheckBoxMenuItem checkBoxMenuItem1 = new JCheckBoxMenuItem();
|
||||
JMenu menu1 = new JMenu();
|
||||
JMenu subViewsMenu = new JMenu();
|
||||
JMenu subSubViewsMenu = new JMenu();
|
||||
JMenuItem errorLogViewMenuItem = new JMenuItem();
|
||||
JMenuItem searchViewMenuItem = new JMenuItem();
|
||||
JMenuItem projectViewMenuItem = new JMenuItem();
|
||||
JMenuItem structureViewMenuItem = new JMenuItem();
|
||||
JMenuItem propertiesViewMenuItem = new JMenuItem();
|
||||
JRadioButtonMenuItem radioButtonMenuItem1 = new JRadioButtonMenuItem();
|
||||
JRadioButtonMenuItem radioButtonMenuItem2 = new JRadioButtonMenuItem();
|
||||
JRadioButtonMenuItem radioButtonMenuItem3 = new JRadioButtonMenuItem();
|
||||
fontMenu = new JMenu();
|
||||
JMenuItem restoreFontMenuItem = new JMenuItem();
|
||||
JMenuItem incrFontMenuItem = new JMenuItem();
|
||||
JMenuItem decrFontMenuItem = new JMenuItem();
|
||||
JMenu helpMenu = new JMenu();
|
||||
JMenuItem aboutMenuItem = new JMenuItem();
|
||||
JToolBar toolBar1 = new JToolBar();
|
||||
@@ -103,27 +164,35 @@ class DemoFrame
|
||||
//======== fileMenu ========
|
||||
{
|
||||
fileMenu.setText("File");
|
||||
fileMenu.setMnemonic('F');
|
||||
|
||||
//---- newMenuItem ----
|
||||
newMenuItem.setText("New");
|
||||
newMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
newMenuItem.setMnemonic('N');
|
||||
newMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
fileMenu.add(newMenuItem);
|
||||
|
||||
//---- openMenuItem ----
|
||||
openMenuItem.setText("Open");
|
||||
openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
openMenuItem.setMnemonic('O');
|
||||
openMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
fileMenu.add(openMenuItem);
|
||||
fileMenu.addSeparator();
|
||||
|
||||
//---- closeMenuItem ----
|
||||
closeMenuItem.setText("Close");
|
||||
closeMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
closeMenuItem.setMnemonic('C');
|
||||
closeMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
fileMenu.add(closeMenuItem);
|
||||
fileMenu.addSeparator();
|
||||
|
||||
//---- exitMenuItem ----
|
||||
exitMenuItem.setText("Exit");
|
||||
exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
exitMenuItem.setMnemonic('X');
|
||||
exitMenuItem.addActionListener(e -> exitActionPerformed());
|
||||
fileMenu.add(exitMenuItem);
|
||||
}
|
||||
@@ -132,37 +201,47 @@ class DemoFrame
|
||||
//======== editMenu ========
|
||||
{
|
||||
editMenu.setText("Edit");
|
||||
editMenu.setMnemonic('E');
|
||||
|
||||
//---- undoMenuItem ----
|
||||
undoMenuItem.setText("Undo");
|
||||
undoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
undoMenuItem.setMnemonic('U');
|
||||
undoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
editMenu.add(undoMenuItem);
|
||||
|
||||
//---- redoMenuItem ----
|
||||
redoMenuItem.setText("Redo");
|
||||
redoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
redoMenuItem.setMnemonic('R');
|
||||
redoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
editMenu.add(redoMenuItem);
|
||||
editMenu.addSeparator();
|
||||
|
||||
//---- cutMenuItem ----
|
||||
cutMenuItem.setText("Cut");
|
||||
cutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
cutMenuItem.setMnemonic('C');
|
||||
editMenu.add(cutMenuItem);
|
||||
|
||||
//---- copyMenuItem ----
|
||||
copyMenuItem.setText("Copy");
|
||||
copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
copyMenuItem.setMnemonic('O');
|
||||
editMenu.add(copyMenuItem);
|
||||
|
||||
//---- pasteMenuItem ----
|
||||
pasteMenuItem.setText("Paste");
|
||||
pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||
pasteMenuItem.setMnemonic('P');
|
||||
editMenu.add(pasteMenuItem);
|
||||
editMenu.addSeparator();
|
||||
|
||||
//---- deleteMenuItem ----
|
||||
deleteMenuItem.setText("Delete");
|
||||
deleteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
|
||||
deleteMenuItem.setMnemonic('D');
|
||||
deleteMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
editMenu.add(deleteMenuItem);
|
||||
}
|
||||
menuBar1.add(editMenu);
|
||||
@@ -170,34 +249,120 @@ class DemoFrame
|
||||
//======== viewMenu ========
|
||||
{
|
||||
viewMenu.setText("View");
|
||||
viewMenu.setMnemonic('V');
|
||||
|
||||
//---- checkBoxMenuItem1 ----
|
||||
checkBoxMenuItem1.setText("Show Toolbar");
|
||||
checkBoxMenuItem1.setSelected(true);
|
||||
checkBoxMenuItem1.setMnemonic('T');
|
||||
checkBoxMenuItem1.addActionListener(e -> menuItemActionPerformed(e));
|
||||
viewMenu.add(checkBoxMenuItem1);
|
||||
|
||||
//======== menu1 ========
|
||||
{
|
||||
menu1.setText("Show View");
|
||||
menu1.setMnemonic('V');
|
||||
|
||||
//======== subViewsMenu ========
|
||||
{
|
||||
subViewsMenu.setText("Sub Views");
|
||||
subViewsMenu.setMnemonic('S');
|
||||
|
||||
//======== subSubViewsMenu ========
|
||||
{
|
||||
subSubViewsMenu.setText("Sub sub Views");
|
||||
subSubViewsMenu.setMnemonic('U');
|
||||
|
||||
//---- errorLogViewMenuItem ----
|
||||
errorLogViewMenuItem.setText("Error Log");
|
||||
errorLogViewMenuItem.setMnemonic('E');
|
||||
errorLogViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
subSubViewsMenu.add(errorLogViewMenuItem);
|
||||
}
|
||||
subViewsMenu.add(subSubViewsMenu);
|
||||
|
||||
//---- searchViewMenuItem ----
|
||||
searchViewMenuItem.setText("Search");
|
||||
searchViewMenuItem.setMnemonic('S');
|
||||
searchViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
subViewsMenu.add(searchViewMenuItem);
|
||||
}
|
||||
menu1.add(subViewsMenu);
|
||||
|
||||
//---- projectViewMenuItem ----
|
||||
projectViewMenuItem.setText("Project");
|
||||
projectViewMenuItem.setMnemonic('P');
|
||||
projectViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
menu1.add(projectViewMenuItem);
|
||||
|
||||
//---- structureViewMenuItem ----
|
||||
structureViewMenuItem.setText("Structure");
|
||||
structureViewMenuItem.setMnemonic('T');
|
||||
structureViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
menu1.add(structureViewMenuItem);
|
||||
|
||||
//---- propertiesViewMenuItem ----
|
||||
propertiesViewMenuItem.setText("Properties");
|
||||
propertiesViewMenuItem.setMnemonic('O');
|
||||
propertiesViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
|
||||
menu1.add(propertiesViewMenuItem);
|
||||
}
|
||||
viewMenu.add(menu1);
|
||||
viewMenu.addSeparator();
|
||||
|
||||
//---- radioButtonMenuItem1 ----
|
||||
radioButtonMenuItem1.setText("Details");
|
||||
radioButtonMenuItem1.setSelected(true);
|
||||
radioButtonMenuItem1.setMnemonic('D');
|
||||
radioButtonMenuItem1.addActionListener(e -> menuItemActionPerformed(e));
|
||||
viewMenu.add(radioButtonMenuItem1);
|
||||
|
||||
//---- radioButtonMenuItem2 ----
|
||||
radioButtonMenuItem2.setText("Small Icons");
|
||||
radioButtonMenuItem2.setMnemonic('S');
|
||||
radioButtonMenuItem2.addActionListener(e -> menuItemActionPerformed(e));
|
||||
viewMenu.add(radioButtonMenuItem2);
|
||||
|
||||
//---- radioButtonMenuItem3 ----
|
||||
radioButtonMenuItem3.setText("Large Icons");
|
||||
radioButtonMenuItem3.setMnemonic('L');
|
||||
radioButtonMenuItem3.addActionListener(e -> menuItemActionPerformed(e));
|
||||
viewMenu.add(radioButtonMenuItem3);
|
||||
}
|
||||
menuBar1.add(viewMenu);
|
||||
|
||||
//======== fontMenu ========
|
||||
{
|
||||
fontMenu.setText("Font");
|
||||
|
||||
//---- restoreFontMenuItem ----
|
||||
restoreFontMenuItem.setText("Restore Font");
|
||||
restoreFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_0, KeyEvent.CTRL_MASK));
|
||||
restoreFontMenuItem.addActionListener(e -> restoreFont());
|
||||
fontMenu.add(restoreFontMenuItem);
|
||||
|
||||
//---- incrFontMenuItem ----
|
||||
incrFontMenuItem.setText("Increase Font Size");
|
||||
incrFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, KeyEvent.CTRL_MASK));
|
||||
incrFontMenuItem.addActionListener(e -> incrFont());
|
||||
fontMenu.add(incrFontMenuItem);
|
||||
|
||||
//---- decrFontMenuItem ----
|
||||
decrFontMenuItem.setText("Decrease Font Size");
|
||||
decrFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, KeyEvent.CTRL_MASK));
|
||||
decrFontMenuItem.addActionListener(e -> decrFont());
|
||||
fontMenu.add(decrFontMenuItem);
|
||||
}
|
||||
menuBar1.add(fontMenu);
|
||||
|
||||
//======== helpMenu ========
|
||||
{
|
||||
helpMenu.setText("Help");
|
||||
helpMenu.setMnemonic('H');
|
||||
|
||||
//---- aboutMenuItem ----
|
||||
aboutMenuItem.setText("About");
|
||||
aboutMenuItem.setMnemonic('A');
|
||||
aboutMenuItem.addActionListener(e -> aboutActionPerformed());
|
||||
helpMenu.add(aboutMenuItem);
|
||||
}
|
||||
@@ -288,9 +453,34 @@ class DemoFrame
|
||||
pasteButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/menu-paste.svg" ) );
|
||||
refreshButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/refresh.svg" ) );
|
||||
showToggleButton.setIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/show.svg" ) );
|
||||
|
||||
cutMenuItem.addActionListener( new DefaultEditorKit.CutAction() );
|
||||
copyMenuItem.addActionListener( new DefaultEditorKit.CopyAction() );
|
||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||
|
||||
// add font families
|
||||
fontMenu.addSeparator();
|
||||
String[] fontFamilies = { "Arial", "Comic Sans MS", "Courier New", "Dialog",
|
||||
"Monospaced", "SansSerif", "Serif", "Tahoma", "Verdana" };
|
||||
for( String fontFamily : fontFamilies ) {
|
||||
JMenuItem fontItem = new JMenuItem( fontFamily );
|
||||
fontItem.addActionListener( this::fontFamilyChanged );
|
||||
fontMenu.add( fontItem );
|
||||
}
|
||||
|
||||
// add font sizes
|
||||
fontMenu.addSeparator();
|
||||
int[] fontSizes = { 8, 10, 12, 14, 16, 18, 20, 24, 28 };
|
||||
for( int fontSize : fontSizes ) {
|
||||
String fontSizeStr = Integer.toString( fontSize );
|
||||
JMenuItem fontItem = new JMenuItem( fontSizeStr );
|
||||
fontItem.addActionListener( this::fontSizeChanged );
|
||||
fontMenu.add( fontItem );
|
||||
}
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JMenu fontMenu;
|
||||
private JTabbedPane tabbedPane;
|
||||
private ControlBar controlBar;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.2" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -117,15 +117,20 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "fileMenu"
|
||||
"text": "File"
|
||||
"mnemonic": 70
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "newMenuItem"
|
||||
"text": "New"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 78, 4226, false )
|
||||
"mnemonic": 78
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "openMenuItem"
|
||||
"text": "Open"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 79, 4226, false )
|
||||
"mnemonic": 79
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||
name: "separator2"
|
||||
@@ -134,6 +139,8 @@ new FormModel {
|
||||
name: "closeMenuItem"
|
||||
"text": "Close"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 87, 4226, false )
|
||||
"mnemonic": 67
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||
name: "separator1"
|
||||
@@ -142,21 +149,27 @@ new FormModel {
|
||||
name: "exitMenuItem"
|
||||
"text": "Exit"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 81, 4226, false )
|
||||
"mnemonic": 88
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "exitActionPerformed", false ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "editMenu"
|
||||
"text": "Edit"
|
||||
"mnemonic": 69
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "undoMenuItem"
|
||||
"text": "Undo"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 90, 4226, false )
|
||||
"mnemonic": 85
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "redoMenuItem"
|
||||
"text": "Redo"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 89, 4226, false )
|
||||
"mnemonic": 82
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||
name: "separator4"
|
||||
@@ -165,16 +178,19 @@ new FormModel {
|
||||
name: "cutMenuItem"
|
||||
"text": "Cut"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 88, 4226, false )
|
||||
"mnemonic": 67
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "copyMenuItem"
|
||||
"text": "Copy"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 67, 4226, false )
|
||||
"mnemonic": 79
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "pasteMenuItem"
|
||||
"text": "Paste"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 86, 4226, false )
|
||||
"mnemonic": 80
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||
name: "separator3"
|
||||
@@ -183,15 +199,65 @@ new FormModel {
|
||||
name: "deleteMenuItem"
|
||||
"text": "Delete"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 127, 0, false )
|
||||
"mnemonic": 68
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "viewMenu"
|
||||
"text": "View"
|
||||
"mnemonic": 86
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "checkBoxMenuItem1"
|
||||
"text": "Show Toolbar"
|
||||
"selected": true
|
||||
"mnemonic": 84
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "menu1"
|
||||
"text": "Show View"
|
||||
"mnemonic": 86
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "subViewsMenu"
|
||||
"text": "Sub Views"
|
||||
"mnemonic": 83
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "subSubViewsMenu"
|
||||
"text": "Sub sub Views"
|
||||
"mnemonic": 85
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "errorLogViewMenuItem"
|
||||
"text": "Error Log"
|
||||
"mnemonic": 69
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "searchViewMenuItem"
|
||||
"text": "Search"
|
||||
"mnemonic": 83
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "projectViewMenuItem"
|
||||
"text": "Project"
|
||||
"mnemonic": 80
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "structureViewMenuItem"
|
||||
"text": "Structure"
|
||||
"mnemonic": 84
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "propertiesViewMenuItem"
|
||||
"text": "Properties"
|
||||
"mnemonic": 79
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||
name: "separator8"
|
||||
@@ -201,24 +267,57 @@ new FormModel {
|
||||
"text": "Details"
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"mnemonic": 68
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JRadioButtonMenuItem" ) {
|
||||
name: "radioButtonMenuItem2"
|
||||
"text": "Small Icons"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"mnemonic": 83
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JRadioButtonMenuItem" ) {
|
||||
name: "radioButtonMenuItem3"
|
||||
"text": "Large Icons"
|
||||
"$buttonGroup": new FormReference( "buttonGroup1" )
|
||||
"mnemonic": 76
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemActionPerformed", true ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "fontMenu"
|
||||
"text": "Font"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "restoreFontMenuItem"
|
||||
"text": "Restore Font"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 48, 130, false )
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "restoreFont", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "incrFontMenuItem"
|
||||
"text": "Increase Font Size"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 521, 130, false )
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "incrFont", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "decrFontMenuItem"
|
||||
"text": "Decrease Font Size"
|
||||
"accelerator": static javax.swing.KeyStroke getKeyStroke( 45, 130, false )
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "decrFont", false ) )
|
||||
} )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||
name: "helpMenu"
|
||||
"text": "Help"
|
||||
"mnemonic": 72
|
||||
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||
name: "aboutMenuItem"
|
||||
"text": "About"
|
||||
"mnemonic": 65
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "aboutActionPerformed", false ) )
|
||||
} )
|
||||
} )
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.demo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.prefs.Preferences;
|
||||
import javax.swing.UIManager;
|
||||
@@ -23,6 +24,8 @@ import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
import com.formdev.flatlaf.IntelliJTheme;
|
||||
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel;
|
||||
import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel.PropertiesLaf;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
@@ -30,12 +33,12 @@ import com.formdev.flatlaf.demo.intellijthemes.IJThemesPanel;
|
||||
public class DemoPrefs
|
||||
{
|
||||
public static final String KEY_LAF = "laf";
|
||||
public static final String KEY_LAF_INTELLIJ_THEME = "lafIntelliJTheme";
|
||||
public static final String KEY_LAF_THEME = "lafTheme";
|
||||
|
||||
public static final String RESOURCE_PREFIX = "res:";
|
||||
public static final String FILE_PREFIX = "file:";
|
||||
|
||||
public static final String INTELLIJ_THEME_UI_KEY = "__FlatLaf.demo.intelliJTheme";
|
||||
public static final String THEME_UI_KEY = "__FlatLaf.demo.theme";
|
||||
|
||||
private static Preferences state;
|
||||
|
||||
@@ -55,16 +58,27 @@ public class DemoPrefs
|
||||
else {
|
||||
String lafClassName = state.get( KEY_LAF, FlatLightLaf.class.getName() );
|
||||
if( IntelliJTheme.ThemeLaf.class.getName().equals( lafClassName ) ) {
|
||||
String intelliJTheme = state.get( KEY_LAF_INTELLIJ_THEME, "" );
|
||||
if( intelliJTheme.startsWith( RESOURCE_PREFIX ) )
|
||||
IntelliJTheme.install( IJThemesPanel.class.getResourceAsStream( intelliJTheme.substring( RESOURCE_PREFIX.length() ) ) );
|
||||
else if( intelliJTheme.startsWith( FILE_PREFIX ) )
|
||||
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( intelliJTheme.substring( FILE_PREFIX.length() ) ) ) );
|
||||
String theme = state.get( KEY_LAF_THEME, "" );
|
||||
if( theme.startsWith( RESOURCE_PREFIX ) )
|
||||
IntelliJTheme.install( IJThemesPanel.class.getResourceAsStream( IJThemesPanel.THEMES_PACKAGE + theme.substring( RESOURCE_PREFIX.length() ) ) );
|
||||
else if( theme.startsWith( FILE_PREFIX ) )
|
||||
FlatLaf.install( IntelliJTheme.createLaf( new FileInputStream( theme.substring( FILE_PREFIX.length() ) ) ) );
|
||||
else
|
||||
FlatLightLaf.install();
|
||||
|
||||
if( !intelliJTheme.isEmpty() )
|
||||
UIManager.getLookAndFeelDefaults().put( INTELLIJ_THEME_UI_KEY, intelliJTheme );
|
||||
if( !theme.isEmpty() )
|
||||
UIManager.getLookAndFeelDefaults().put( THEME_UI_KEY, theme );
|
||||
} else if( IJThemesPanel.PropertiesLaf.class.getName().equals( lafClassName ) ) {
|
||||
String theme = state.get( KEY_LAF_THEME, "" );
|
||||
if( theme.startsWith( FILE_PREFIX ) ) {
|
||||
File themeFile = new File( theme.substring( FILE_PREFIX.length() ) );
|
||||
String themeName = StringUtils.removeTrailing( themeFile.getName(), ".properties" );
|
||||
FlatLaf.install( new PropertiesLaf( themeName, themeFile ) );
|
||||
} else
|
||||
FlatLightLaf.install();
|
||||
|
||||
if( !theme.isEmpty() )
|
||||
UIManager.getLookAndFeelDefaults().put( THEME_UI_KEY, theme );
|
||||
} else
|
||||
UIManager.setLookAndFeel( lafClassName );
|
||||
}
|
||||
|
||||
@@ -69,7 +69,14 @@ class MoreComponentsPanel
|
||||
JToggleButton toggleButton7 = new JToggleButton();
|
||||
JLabel scrollBarLabel = new JLabel();
|
||||
JScrollBar scrollBar1 = new JScrollBar();
|
||||
JLabel label4 = new JLabel();
|
||||
JScrollBar scrollBar4 = new JScrollBar();
|
||||
JPanel panel3 = new JPanel();
|
||||
JLabel label3 = new JLabel();
|
||||
JScrollPane scrollPane15 = new JScrollPane();
|
||||
JEditorPane editorPane6 = new JEditorPane();
|
||||
JScrollPane scrollPane16 = new JScrollPane();
|
||||
JTextPane textPane6 = new JTextPane();
|
||||
JScrollBar scrollBar5 = new JScrollBar();
|
||||
JScrollBar scrollBar6 = new JScrollBar();
|
||||
JLabel separatorLabel = new JLabel();
|
||||
@@ -211,11 +218,53 @@ class MoreComponentsPanel
|
||||
scrollBar1.setOrientation(Adjustable.HORIZONTAL);
|
||||
add(scrollBar1, "cell 1 1,growx");
|
||||
|
||||
//---- label4 ----
|
||||
label4.setText("HTML:");
|
||||
add(label4, "cell 5 1");
|
||||
|
||||
//---- scrollBar4 ----
|
||||
scrollBar4.setOrientation(Adjustable.HORIZONTAL);
|
||||
scrollBar4.setEnabled(false);
|
||||
add(scrollBar4, "cell 1 2,growx");
|
||||
|
||||
//======== panel3 ========
|
||||
{
|
||||
panel3.setOpaque(false);
|
||||
panel3.setLayout(new MigLayout(
|
||||
"ltr,insets 0,hidemode 3",
|
||||
// columns
|
||||
"[]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]"));
|
||||
|
||||
//---- label3 ----
|
||||
label3.setText("<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u> with <a href=\"#\">link</a></html>");
|
||||
panel3.add(label3, "cell 0 0");
|
||||
|
||||
//======== scrollPane15 ========
|
||||
{
|
||||
|
||||
//---- editorPane6 ----
|
||||
editorPane6.setContentType("text/html");
|
||||
editorPane6.setText("JEditorPane HTML<br>Sample <b>content</b><br> <u>text</u> with <a href=\"#\">link</a>");
|
||||
scrollPane15.setViewportView(editorPane6);
|
||||
}
|
||||
panel3.add(scrollPane15, "cell 0 1,grow");
|
||||
|
||||
//======== scrollPane16 ========
|
||||
{
|
||||
|
||||
//---- textPane6 ----
|
||||
textPane6.setContentType("text/html");
|
||||
textPane6.setText("JTextPane HTML<br>Sample <b>content</b><br> <u>text</u> with <a href=\"#\">link</a>");
|
||||
scrollPane16.setViewportView(textPane6);
|
||||
}
|
||||
panel3.add(scrollPane16, "cell 0 2,grow");
|
||||
}
|
||||
add(panel3, "cell 5 2 1 9,aligny top,growy 0");
|
||||
|
||||
//---- scrollBar5 ----
|
||||
scrollBar5.setOrientation(Adjustable.HORIZONTAL);
|
||||
scrollBar5.putClientProperty("JScrollBar.showButtons", true);
|
||||
|
||||
@@ -140,6 +140,12 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label4"
|
||||
"text": "HTML:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JScrollBar" ) {
|
||||
name: "scrollBar4"
|
||||
"orientation": 0
|
||||
@@ -147,6 +153,42 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 2,growx"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$columnConstraints": "[]"
|
||||
"$rowConstraints": "[][][]"
|
||||
"$layoutConstraints": "ltr,insets 0,hidemode 3"
|
||||
} ) {
|
||||
name: "panel3"
|
||||
"opaque": false
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "label3"
|
||||
"text": "<html>JLabel HTML<br>Sample <b>content</b><br> <u>text</u> with <a href=\"#\">link</a></html>"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 0"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "scrollPane15"
|
||||
add( new FormComponent( "javax.swing.JEditorPane" ) {
|
||||
name: "editorPane6"
|
||||
"contentType": "text/html"
|
||||
"text": "JEditorPane HTML<br>Sample <b>content</b><br> <u>text</u> with <a href=\"#\">link</a>"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 1,grow"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||
name: "scrollPane16"
|
||||
add( new FormComponent( "javax.swing.JTextPane" ) {
|
||||
name: "textPane6"
|
||||
"contentType": "text/html"
|
||||
"text": "JTextPane HTML<br>Sample <b>content</b><br> <u>text</u> with <a href=\"#\">link</a>"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2,grow"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 5 2 1 9,aligny top,growy 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JScrollBar" ) {
|
||||
name: "scrollBar5"
|
||||
"orientation": 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.2" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -243,7 +243,7 @@ new FormModel {
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 790, 840 )
|
||||
"size": new java.awt.Dimension( 840, 900 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user