mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
Compare commits
1218 Commits
1.2
...
ddc8d6e29c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddc8d6e29c | ||
|
|
119b4a922d | ||
|
|
5e4f00f0c8 | ||
|
|
15cbf28a0d | ||
|
|
f8e53c9064 | ||
|
|
b3c9638e47 | ||
|
|
d079741f94 | ||
|
|
c051ad5f72 | ||
|
|
1ed7aeaa45 | ||
|
|
2ac7234c32 | ||
|
|
6f63982054 | ||
|
|
d388158de7 | ||
|
|
e7a766bf8f | ||
|
|
97988e90b4 | ||
|
|
f71dbb2647 | ||
|
|
04ad21b5b6 | ||
|
|
ff722c0b34 | ||
|
|
34b19f00e4 | ||
|
|
286ce15146 | ||
|
|
abfaf86cd5 | ||
|
|
bc4c7b25d3 | ||
|
|
0863e289a1 | ||
|
|
4945378dd3 | ||
|
|
b178450e81 | ||
|
|
e3ffdd3b7c | ||
|
|
5326971287 | ||
|
|
cd34c08dc9 | ||
|
|
edee73e0ea | ||
|
|
54a53fb527 | ||
|
|
62b96fbccd | ||
|
|
42cbb0666d | ||
|
|
1465fbaabc | ||
|
|
5575854e68 | ||
|
|
640f2ba9a2 | ||
|
|
b221fd1894 | ||
|
|
b64ab09b88 | ||
|
|
2870ee5c51 | ||
|
|
23f8ce867b | ||
|
|
835a1f155b | ||
|
|
3925f198d9 | ||
|
|
d8e59f2cf3 | ||
|
|
666b99971d | ||
|
|
0ba7798cbd | ||
|
|
c486f695f2 | ||
|
|
0bc2513c46 | ||
|
|
bc3504378b | ||
|
|
94fc75dc78 | ||
|
|
681c0cd4fe | ||
|
|
f7495a0a5b | ||
|
|
dd44d3ed2d | ||
|
|
86a4d0ab12 | ||
|
|
b43c3a9e00 | ||
|
|
babc8aa55d | ||
|
|
5dc88a6210 | ||
|
|
d612b9f4b8 | ||
|
|
9b1ae5c74a | ||
|
|
143f96360b | ||
|
|
f5e6b90e02 | ||
|
|
f36886aeb3 | ||
|
|
d26eb2674f | ||
|
|
68b8769d0d | ||
|
|
7f37e884d3 | ||
|
|
a4dc1b4151 | ||
|
|
022a67929a | ||
|
|
f7c867fb97 | ||
|
|
f0685d179e | ||
|
|
c8eaf5f587 | ||
|
|
ed69049c08 | ||
|
|
ae4037ee82 | ||
|
|
411a2f6d29 | ||
|
|
f24b3a6022 | ||
|
|
ebacad2d04 | ||
|
|
76f436726f | ||
|
|
6c8f813e53 | ||
|
|
5f6cc719ad | ||
|
|
00858002de | ||
|
|
072cc3c488 | ||
|
|
1f594b2ba8 | ||
|
|
c32c00a5eb | ||
|
|
3a8a55a545 | ||
|
|
6c49b8bc4d | ||
|
|
cca9707f6b | ||
|
|
f30dd876e4 | ||
|
|
c6872d48b3 | ||
|
|
5e78b21df7 | ||
|
|
2ef87dc789 | ||
|
|
28904c34cc | ||
|
|
91f19bf94c | ||
|
|
0ea188f8db | ||
|
|
6c77b81277 | ||
|
|
ddee4ef526 | ||
|
|
f11f68282b | ||
|
|
ac0cceb09b | ||
|
|
a238fd4505 | ||
|
|
8dc6242889 | ||
|
|
d17fffb82a | ||
|
|
0ad3180b10 | ||
|
|
80ba75fdeb | ||
|
|
7027821c00 | ||
|
|
a3a49cef73 | ||
|
|
abf77d5399 | ||
|
|
6404b8de2a | ||
|
|
19055d5a18 | ||
|
|
c12adf12e7 | ||
|
|
b9c68fbe77 | ||
|
|
7bdfd49921 | ||
|
|
58fa2a5085 | ||
|
|
a400799db5 | ||
|
|
2a8e487c1f | ||
|
|
145631fd43 | ||
|
|
6a774d8c70 | ||
|
|
bfd746f981 | ||
|
|
3af54b7215 | ||
|
|
3ba9fc6c1c | ||
|
|
0a9ecd66a9 | ||
|
|
6991d6729e | ||
|
|
304cb0d57b | ||
|
|
41332de275 | ||
|
|
ef61ae504b | ||
|
|
f96baf1bc2 | ||
|
|
1462636e97 | ||
|
|
7e59a7f4af | ||
|
|
e9a21848bc | ||
|
|
1dcb251ecb | ||
|
|
3f33543cee | ||
|
|
84bd2088f2 | ||
|
|
4f4a3132c5 | ||
|
|
e064c934cb | ||
|
|
16fc3cabf2 | ||
|
|
7e002ff6c2 | ||
|
|
323c0c62c3 | ||
|
|
ff5bd301cc | ||
|
|
c37712b0f0 | ||
|
|
ee9e238592 | ||
|
|
da5d6fa157 | ||
|
|
d471f08b15 | ||
|
|
b97424f767 | ||
|
|
a20cfa6db3 | ||
|
|
6ac6698ecf | ||
|
|
8004d2761a | ||
|
|
25c2bbc851 | ||
|
|
33e37a7167 | ||
|
|
c29a276188 | ||
|
|
d1694aa8bd | ||
|
|
570cf6fc51 | ||
|
|
8eab86e489 | ||
|
|
566568f61a | ||
|
|
56a73a4d17 | ||
|
|
656d25b75e | ||
|
|
dcdc80ade3 | ||
|
|
09f2d65d5e | ||
|
|
b304d46f7e | ||
|
|
3391f971ec | ||
|
|
778fed27a5 | ||
|
|
1755dbc877 | ||
|
|
4e6f538519 | ||
|
|
a6ecb0ef85 | ||
|
|
438ec6ac5c | ||
|
|
8089e66642 | ||
|
|
d27e0561f2 | ||
|
|
97b21bfa8b | ||
|
|
ec4343ed30 | ||
|
|
948decb3b5 | ||
|
|
d510fee7f6 | ||
|
|
70b7a3d662 | ||
|
|
b142a6f31e | ||
|
|
14705a9b30 | ||
|
|
32b0f1ba10 | ||
|
|
cbffdf4900 | ||
|
|
1238da5e54 | ||
|
|
cba203be09 | ||
|
|
d89c6156b9 | ||
|
|
e06475b3b7 | ||
|
|
5ff99bd45e | ||
|
|
127dd6ac41 | ||
|
|
9e05384513 | ||
|
|
9ffda72ae3 | ||
|
|
72a4c00e72 | ||
|
|
c95e95ef67 | ||
|
|
0c0d4bffbf | ||
|
|
2a494b1d60 | ||
|
|
1463723e52 | ||
|
|
9ade48d078 | ||
|
|
7ba8274fd4 | ||
|
|
238443074c | ||
|
|
0decbec595 | ||
|
|
0eb77c7f72 | ||
|
|
f05df0db0a | ||
|
|
13fbaf1f74 | ||
|
|
969d2642de | ||
|
|
17ce6d39b4 | ||
|
|
261d2b1fe8 | ||
|
|
a54aeb3838 | ||
|
|
cc4f9a9db5 | ||
|
|
a311bac89b | ||
|
|
029f273dd9 | ||
|
|
bbbdd7e4d3 | ||
|
|
3f3ef6b24f | ||
|
|
8c3dfd4a36 | ||
|
|
af57599df9 | ||
|
|
bde25f6ac8 | ||
|
|
c989b97ffa | ||
|
|
5f5c225300 | ||
|
|
36e4071b7f | ||
|
|
1068884bce | ||
|
|
32d102dbc9 | ||
|
|
4e1f092b98 | ||
|
|
bd60a18ff4 | ||
|
|
3b3d7d76eb | ||
|
|
ec76448e9f | ||
|
|
872c84974c | ||
|
|
5dd2008969 | ||
|
|
55ddac2bc7 | ||
|
|
a62dd22f83 | ||
|
|
a503879858 | ||
|
|
14f19dd735 | ||
|
|
9a727f68ce | ||
|
|
d26819d268 | ||
|
|
44752cc9aa | ||
|
|
11e0757387 | ||
|
|
1f1ebc3c44 | ||
|
|
4be97b6ea6 | ||
|
|
3facca5499 | ||
|
|
bfbd25012a | ||
|
|
063fff2ab4 | ||
|
|
fbdc8d5b99 | ||
|
|
625c0a3321 | ||
|
|
2972300112 | ||
|
|
a8e71895ee | ||
|
|
d7a76081e3 | ||
|
|
fd925a6718 | ||
|
|
4fc890a77c | ||
|
|
b804463b73 | ||
|
|
8f161b4b5a | ||
|
|
c6338169f3 | ||
|
|
6cea24ed9e | ||
|
|
3d8eb9eb66 | ||
|
|
a84aceb1ba | ||
|
|
8adb7e3021 | ||
|
|
bc0d5dc9b5 | ||
|
|
1d935d6659 | ||
|
|
445466acd0 | ||
|
|
30af74f806 | ||
|
|
16ddd100d3 | ||
|
|
c946ec170d | ||
|
|
ca514dd76e | ||
|
|
cf44a5c50b | ||
|
|
91b8c02c7f | ||
|
|
ca3b2b4b07 | ||
|
|
722dde63df | ||
|
|
c85baf4dc6 | ||
|
|
96b7770ab2 | ||
|
|
0c00117820 | ||
|
|
3465fa68b4 | ||
|
|
28278a75a7 | ||
|
|
f68a871dd6 | ||
|
|
93d424cfe1 | ||
|
|
a1adde0888 | ||
|
|
13528b49cb | ||
|
|
f3be3f2d1c | ||
|
|
241fe855cc | ||
|
|
ea2447dcb7 | ||
|
|
f40baed65e | ||
|
|
eed11d211b | ||
|
|
19f27a8d56 | ||
|
|
cf3fa17666 | ||
|
|
6fdc56f2d3 | ||
|
|
9f17a5b26d | ||
|
|
fa53e90847 | ||
|
|
50c630f403 | ||
|
|
5630c161ea | ||
|
|
7d16ff9e79 | ||
|
|
a9ea9daec3 | ||
|
|
45bdd40dce | ||
|
|
a2bca88eec | ||
|
|
c0dd02ee13 | ||
|
|
97495a6093 | ||
|
|
4ad45088c4 | ||
|
|
d6d1d4b1b7 | ||
|
|
6e453c170f | ||
|
|
beb2deee52 | ||
|
|
9c69043b2c | ||
|
|
4df34b3f9d | ||
|
|
ee01756188 | ||
|
|
0386aaa18b | ||
|
|
92c4230cde | ||
|
|
26165999e0 | ||
|
|
38b2641078 | ||
|
|
4e19169312 | ||
|
|
46de81c1c9 | ||
|
|
9bf4da7acf | ||
|
|
6f32236fb7 | ||
|
|
c25d857e78 | ||
|
|
8cc2925fd0 | ||
|
|
2b87d3c4db | ||
|
|
7f6f366744 | ||
|
|
b1fdbde5cd | ||
|
|
417f0f5f1c | ||
|
|
ec7673790c | ||
|
|
7d0bdf3b9e | ||
|
|
2ef5270095 | ||
|
|
61ba011c3b | ||
|
|
8d8b9f3e98 | ||
|
|
69899ec29f | ||
|
|
5063621c95 | ||
|
|
030177f739 | ||
|
|
808f5a6381 | ||
|
|
9602b191a9 | ||
|
|
34bd2d781c | ||
|
|
cf364c1264 | ||
|
|
a997820bb6 | ||
|
|
b8fabd59c0 | ||
|
|
97d290795e | ||
|
|
2a237ff5fc | ||
|
|
13a418f74e | ||
|
|
5c56dbfed6 | ||
|
|
0d2f37e1da | ||
|
|
0494c2161c | ||
|
|
635a620439 | ||
|
|
0a7c76ec72 | ||
|
|
9ad8fb38e8 | ||
|
|
1dbe968952 | ||
|
|
460b6492cb | ||
|
|
67b0faa9ae | ||
|
|
5553425a1a | ||
|
|
8ff516e43a | ||
|
|
b6207bafde | ||
|
|
b9f43fd560 | ||
|
|
c617d9f569 | ||
|
|
9efb9761c6 | ||
|
|
03f9115fbf | ||
|
|
a2859cedb5 | ||
|
|
0c604b1023 | ||
|
|
cdee0594f8 | ||
|
|
808833d749 | ||
|
|
581c64b601 | ||
|
|
40418607e5 | ||
|
|
5436ea88d8 | ||
|
|
7bec5ec6dc | ||
|
|
c953ff84d0 | ||
|
|
96cd207df3 | ||
|
|
7a75f62a6a | ||
|
|
61e5fe58c2 | ||
|
|
1a3baba702 | ||
|
|
58dc14bb46 | ||
|
|
a5b7e04943 | ||
|
|
22f2aa5475 | ||
|
|
d4e9cb12be | ||
|
|
75da361480 | ||
|
|
7488bcb7b0 | ||
|
|
1b1a9be107 | ||
|
|
db2f94aa53 | ||
|
|
810146b993 | ||
|
|
93091662ab | ||
|
|
d349227fbf | ||
|
|
c9423e3aa8 | ||
|
|
b9737ca4f1 | ||
|
|
4b4990635d | ||
|
|
afaa2c8c78 | ||
|
|
f506ef0d4f | ||
|
|
d30fe66cac | ||
|
|
270e998e86 | ||
|
|
c395386c05 | ||
|
|
4f1207b0db | ||
|
|
dc3878e290 | ||
|
|
be2876149d | ||
|
|
52bae9dfb0 | ||
|
|
bb636bac3f | ||
|
|
502b18fa86 | ||
|
|
e0a5450264 | ||
|
|
5ffb23c37f | ||
|
|
b75f22b7bd | ||
|
|
35fa3197c8 | ||
|
|
f03725ae36 | ||
|
|
2b640e2129 | ||
|
|
2a983f5c03 | ||
|
|
cacc5daa14 | ||
|
|
593502287d | ||
|
|
7a9bdf9be0 | ||
|
|
170c22c5ed | ||
|
|
7e8fa58bd7 | ||
|
|
046200625c | ||
|
|
710ed55152 | ||
|
|
ce527329a6 | ||
|
|
b455dd41ab | ||
|
|
b47ed94f40 | ||
|
|
f1351a2093 | ||
|
|
c1c5e81df0 | ||
|
|
8e3c8ba6c5 | ||
|
|
dfe4404a17 | ||
|
|
b3fb63c9f5 | ||
|
|
9db3dfff26 | ||
|
|
3c9051e7de | ||
|
|
798a6d061c | ||
|
|
19afbe99d9 | ||
|
|
4715d8d16c | ||
|
|
193da2bc4d | ||
|
|
799f8efe22 | ||
|
|
f6062e1ec4 | ||
|
|
c790778a46 | ||
|
|
4344f1b3a0 | ||
|
|
d520b30500 | ||
|
|
11c02e5f50 | ||
|
|
aa4c6ee9da | ||
|
|
98f8557392 | ||
|
|
6f6a860887 | ||
|
|
38695e9e16 | ||
|
|
242c478cb3 | ||
|
|
f003e835bd | ||
|
|
267defb321 | ||
|
|
4392c7627b | ||
|
|
fde65b2730 | ||
|
|
e908362f0a | ||
|
|
a40b837634 | ||
|
|
b391465fbf | ||
|
|
bad0428f5b | ||
|
|
97018df2f9 | ||
|
|
9d84501bc8 | ||
|
|
e9fb2b3fdc | ||
|
|
f60250fd8a | ||
|
|
5fc3cae28a | ||
|
|
e7935be85b | ||
|
|
89363b2ea1 | ||
|
|
e84390ee46 | ||
|
|
65a0f467ae | ||
|
|
4afb150106 | ||
|
|
0f6702217e | ||
|
|
13a0097858 | ||
|
|
01c830ad92 | ||
|
|
dce4f4623c | ||
|
|
d530624362 | ||
|
|
2e878b62d1 | ||
|
|
d27a246dfe | ||
|
|
778def118a | ||
|
|
bc5587477b | ||
|
|
03a775cd31 | ||
|
|
875083a924 | ||
|
|
f6fc925c9e | ||
|
|
74e1972781 | ||
|
|
2f5c54bb49 | ||
|
|
465798ee3d | ||
|
|
425f3acced | ||
|
|
546382e471 | ||
|
|
7e91d78633 | ||
|
|
136e1e4e30 | ||
|
|
f5f6850172 | ||
|
|
28cdde3f17 | ||
|
|
29b801e13d | ||
|
|
1435469ee5 | ||
|
|
4a0bd2c09f | ||
|
|
f8d67f863f | ||
|
|
0291dd5416 | ||
|
|
9014435d4d | ||
|
|
07ad467c73 | ||
|
|
35e23574cf | ||
|
|
9b62b8395f | ||
|
|
45e7022deb | ||
|
|
32dce16363 | ||
|
|
e34b5eafe1 | ||
|
|
4e1e749094 | ||
|
|
ede9293377 | ||
|
|
9101324a1f | ||
|
|
4b844353ee | ||
|
|
2134c19c58 | ||
|
|
c974784ebb | ||
|
|
5eb6961023 | ||
|
|
07cbd8b97b | ||
|
|
09c7f15364 | ||
|
|
b879b393ad | ||
|
|
e4503c2a54 | ||
|
|
7e2d02b997 | ||
|
|
d286550572 | ||
|
|
4e44e25d30 | ||
|
|
9fef2f9d05 | ||
|
|
04f1f5921d | ||
|
|
f9ecffb850 | ||
|
|
c9b5274ccf | ||
|
|
d209d47b9e | ||
|
|
21baaf810c | ||
|
|
95b4366270 | ||
|
|
c3adadfe2f | ||
|
|
adf7753617 | ||
|
|
d491847754 | ||
|
|
6afc747790 | ||
|
|
ff46935448 | ||
|
|
78c2f98f1f | ||
|
|
91be9aa2fe | ||
|
|
13e5da584f | ||
|
|
1762e0b7a6 | ||
|
|
05240abfe0 | ||
|
|
b515e8be04 | ||
|
|
24bc7fb0b5 | ||
|
|
0d2e1e6d18 | ||
|
|
f23c523baf | ||
|
|
76fee29f5b | ||
|
|
ec77746a43 | ||
|
|
92cd6f8f34 | ||
|
|
e7d2b5cbb6 | ||
|
|
4d175da3a0 | ||
|
|
5f047ddda9 | ||
|
|
ccca6fe88e | ||
|
|
a1f18e1ec9 | ||
|
|
afdaf7a0a5 | ||
|
|
62f0ef19f4 | ||
|
|
b736502c27 | ||
|
|
2be2dae3d6 | ||
|
|
aefe104ca4 | ||
|
|
3e6bce9cec | ||
|
|
a6394cac38 | ||
|
|
1e09ddfc93 | ||
|
|
664f5c98e9 | ||
|
|
c7bfd2ea82 | ||
|
|
9ce7ddd088 | ||
|
|
cca8d427d2 | ||
|
|
aa9263a2e7 | ||
|
|
5eaebde437 | ||
|
|
7f15f557a5 | ||
|
|
b459715cb5 | ||
|
|
bfede219d0 | ||
|
|
ef21efecf5 | ||
|
|
2bfbc9dc12 | ||
|
|
c3a1b45546 | ||
|
|
b72508f920 | ||
|
|
22bb80218d | ||
|
|
873a7e8572 | ||
|
|
0c5016fe89 | ||
|
|
607b084697 | ||
|
|
9d8ffec276 | ||
|
|
15f08e9b7c | ||
|
|
08aa6b1894 | ||
|
|
06b02c4f7c | ||
|
|
b56acd271f | ||
|
|
b24e2db59e | ||
|
|
f215356629 | ||
|
|
069a7c809c | ||
|
|
883b4d735a | ||
|
|
9f39b269bb | ||
|
|
36c405c708 | ||
|
|
bc7c68ebe4 | ||
|
|
6c502ad4c5 | ||
|
|
100aa0b621 | ||
|
|
8e42b19934 | ||
|
|
1a456d5d68 | ||
|
|
e83c26a76a | ||
|
|
6e7c2a616b | ||
|
|
0699454df8 | ||
|
|
92c110548a | ||
|
|
ca88023560 | ||
|
|
12fc2299ec | ||
|
|
2089c77b84 | ||
|
|
4f5a3e8d8b | ||
|
|
95522846ac | ||
|
|
614ac956de | ||
|
|
c228362c01 | ||
|
|
f6c5db07f2 | ||
|
|
78e7839213 | ||
|
|
f7be12df67 | ||
|
|
a1d1e221ae | ||
|
|
0a4dc54fb9 | ||
|
|
b8c7801365 | ||
|
|
a7099c039f | ||
|
|
a4d2d347e3 | ||
|
|
829c537fd3 | ||
|
|
28437f99cf | ||
|
|
c1402d85e1 | ||
|
|
32e071ab89 | ||
|
|
01125e030e | ||
|
|
b43278439a | ||
|
|
7a445aabd7 | ||
|
|
86a4f306c6 | ||
|
|
0e523f1193 | ||
|
|
9041a16b22 | ||
|
|
596ff3382d | ||
|
|
cbd80252ed | ||
|
|
bcd7a7e3dd | ||
|
|
9c98f1a553 | ||
|
|
c3d214aa23 | ||
|
|
d301f6e104 | ||
|
|
eb9fa585f7 | ||
|
|
16c6ffb032 | ||
|
|
7858e42e37 | ||
|
|
30132aa6b0 | ||
|
|
bf4d4cc2c5 | ||
|
|
9f0554c883 | ||
|
|
218ea6ce47 | ||
|
|
0baae7da8b | ||
|
|
fb4576fc1b | ||
|
|
16f3f9e6ff | ||
|
|
fee7cf6265 | ||
|
|
2dd75c4a64 | ||
|
|
d2f46cd0b5 | ||
|
|
10914083e6 | ||
|
|
5d167da55e | ||
|
|
b381e20e57 | ||
|
|
380dae1017 | ||
|
|
fb15cdc546 | ||
|
|
a525fe29db | ||
|
|
475cc9a9a5 | ||
|
|
264d6fbd6d | ||
|
|
2826cf379b | ||
|
|
d28745df29 | ||
|
|
94f9e4a1be | ||
|
|
ec547e1d65 | ||
|
|
61d4eb649b | ||
|
|
52ad15e375 | ||
|
|
ff00a6c0f0 | ||
|
|
9b1ebd658d | ||
|
|
f842530537 | ||
|
|
63077bbb19 | ||
|
|
4dad337377 | ||
|
|
10a965d765 | ||
|
|
3e9c9c9066 | ||
|
|
8b5a738e65 | ||
|
|
2c041dce3a | ||
|
|
ef151c68f4 | ||
|
|
52feaac92a | ||
|
|
cddbb3d7d4 | ||
|
|
42764550e6 | ||
|
|
6ee737b314 | ||
|
|
f460ef7685 | ||
|
|
9977bcb468 | ||
|
|
7437d984c7 | ||
|
|
5cd0b2403c | ||
|
|
a372da22f3 | ||
|
|
8b10d3ba5a | ||
|
|
a8b15c6a12 | ||
|
|
23bac7e5fd | ||
|
|
b82ee2ef61 | ||
|
|
b7761f4b71 | ||
|
|
f9a4f9771c | ||
|
|
d2acb2c98a | ||
|
|
bf0685cee2 | ||
|
|
d60bd5df14 | ||
|
|
73b6ca3762 | ||
|
|
8262793751 | ||
|
|
5ec7848fb0 | ||
|
|
450fc123ff | ||
|
|
3802c64be3 | ||
|
|
7bf1b26812 | ||
|
|
6c18431a30 | ||
|
|
a49d20249f | ||
|
|
ad384acd57 | ||
|
|
69851b7f3a | ||
|
|
92b53bf0df | ||
|
|
93e0496fd2 | ||
|
|
5151951f46 | ||
|
|
58dbccec2d | ||
|
|
90de14d013 | ||
|
|
f1792e46c6 | ||
|
|
84e9c36280 | ||
|
|
2ef6a2c3c9 | ||
|
|
5f961618bf | ||
|
|
37c375e2fa | ||
|
|
1758c175ed | ||
|
|
96f2a02cfa | ||
|
|
96d4bda6c8 | ||
|
|
02cf6050a1 | ||
|
|
38cf32a2e9 | ||
|
|
2ae7589d14 | ||
|
|
bcb2e1f0a1 | ||
|
|
14932d3f07 | ||
|
|
c3b9dc397d | ||
|
|
58b653f55d | ||
|
|
1dcdc42dde | ||
|
|
58a0a16985 | ||
|
|
a117243f14 | ||
|
|
22411060be | ||
|
|
045263ae58 | ||
|
|
024b6daaf6 | ||
|
|
bd5512c121 | ||
|
|
9afce83a02 | ||
|
|
07a8bd9486 | ||
|
|
bcdc0a8fce | ||
|
|
b295809432 | ||
|
|
52763ab932 | ||
|
|
99666265c9 | ||
|
|
af3e280d74 | ||
|
|
b57e4c0565 | ||
|
|
aca9931560 | ||
|
|
d09e166e4a | ||
|
|
68a7a60ff2 | ||
|
|
f21261914b | ||
|
|
7b11339fdc | ||
|
|
081fd43d98 | ||
|
|
ef2eedfc7c | ||
|
|
0dba9265be | ||
|
|
301aae9b8e | ||
|
|
c63f4e9662 | ||
|
|
47508dc6ac | ||
|
|
3a8879608a | ||
|
|
b221889549 | ||
|
|
c00d99b85f | ||
|
|
0bf87b753d | ||
|
|
53f2730064 | ||
|
|
d487c3b005 | ||
|
|
fef6ae7ff7 | ||
|
|
f6b42754de | ||
|
|
2ae9bb381d | ||
|
|
53bde84710 | ||
|
|
d006ac27ff | ||
|
|
c478d28b71 | ||
|
|
99f7b9ad84 | ||
|
|
ab58101ce3 | ||
|
|
d8f3682dc0 | ||
|
|
1fec7ba553 | ||
|
|
418f55f34e | ||
|
|
05d795b2ae | ||
|
|
a365b750d9 | ||
|
|
0aecfb565f | ||
|
|
0cf4edd9e5 | ||
|
|
dd7b7c6aef | ||
|
|
0bd677c46b | ||
|
|
1a131d5206 | ||
|
|
016e515ae2 | ||
|
|
456ceb3c58 | ||
|
|
2169be1b45 | ||
|
|
49eb0b0201 | ||
|
|
2e222bcdea | ||
|
|
c7fa475128 | ||
|
|
4174b065f3 | ||
|
|
df6256d989 | ||
|
|
c27db56321 | ||
|
|
97bed8554a | ||
|
|
751c0e16e9 | ||
|
|
936de60700 | ||
|
|
f6b64d48ec | ||
|
|
b043da7d4c | ||
|
|
7e47cc2443 | ||
|
|
b8b45f9442 | ||
|
|
66337f9af6 | ||
|
|
54646706a0 | ||
|
|
e8ee037d09 | ||
|
|
6d705e568a | ||
|
|
e768791eba | ||
|
|
2aff7c97f9 | ||
|
|
ca6fc7773e | ||
|
|
a1395a5490 | ||
|
|
61dd4d71d6 | ||
|
|
6beda53238 | ||
|
|
941441d7e1 | ||
|
|
d10ea41b47 | ||
|
|
9458870f70 | ||
|
|
095794bbd1 | ||
|
|
c7fc0aa936 | ||
|
|
a8d98ced61 | ||
|
|
831b3d851a | ||
|
|
8c891c7016 | ||
|
|
5c4706cbc9 | ||
|
|
db66a6c4f0 | ||
|
|
0517e4fc02 | ||
|
|
dd7fa4a87d | ||
|
|
e5956900ea | ||
|
|
3755593c14 | ||
|
|
8ddd3b6d68 | ||
|
|
840083940d | ||
|
|
0cdfd29ecf | ||
|
|
bb32c727b6 | ||
|
|
f978c04750 | ||
|
|
b6a504e121 | ||
|
|
5fae367fab | ||
|
|
6e807f44b2 | ||
|
|
53ebed7f89 | ||
|
|
1c10c41808 | ||
|
|
01170b669b | ||
|
|
b56215e5e3 | ||
|
|
221e801561 | ||
|
|
90edbe23d7 | ||
|
|
5b16a814c8 | ||
|
|
ef01721464 | ||
|
|
efd8cf8236 | ||
|
|
8dbfc6d5d6 | ||
|
|
ef343397d4 | ||
|
|
cae02d31db | ||
|
|
96c78cbc16 | ||
|
|
f8c769644d | ||
|
|
0bd1e413b0 | ||
|
|
07c9ad484a | ||
|
|
5fd5b1206e | ||
|
|
8e107647bd | ||
|
|
12b7389376 | ||
|
|
45332c8126 | ||
|
|
02a9d4e31d | ||
|
|
a4377e81cb | ||
|
|
8d2ed3faf6 | ||
|
|
e7dacb8fef | ||
|
|
60e2ffac5f | ||
|
|
73c37b2018 | ||
|
|
1b3cc223da | ||
|
|
51be7ad832 | ||
|
|
f93d035e4e | ||
|
|
a3885d7a48 | ||
|
|
bbf2331766 | ||
|
|
2164bd363b | ||
|
|
6205e18c45 | ||
|
|
959b3e46fa | ||
|
|
09d8d09aad | ||
|
|
70336e31c7 | ||
|
|
600e0f3d67 | ||
|
|
023e356057 | ||
|
|
27786ec00a | ||
|
|
e52e72c5a8 | ||
|
|
802dd08ce7 | ||
|
|
568ec5a1a2 | ||
|
|
035d196392 | ||
|
|
dd3ffc64b9 | ||
|
|
c9a38f0a13 | ||
|
|
78461a9d5a | ||
|
|
79b8fb910a | ||
|
|
405e3df1f0 | ||
|
|
f7126d154f | ||
|
|
d8df8c9631 | ||
|
|
37b35f9063 | ||
|
|
f61a7288eb | ||
|
|
47a1122f04 | ||
|
|
e1bfabbce5 | ||
|
|
9708fec0e0 | ||
|
|
7f4efaf0a3 | ||
|
|
269eb0ba29 | ||
|
|
428c6b7813 | ||
|
|
db2452a4ec | ||
|
|
7dac3825d7 | ||
|
|
7c99872278 | ||
|
|
64c7318cfc | ||
|
|
a9d6483829 | ||
|
|
13a6b92e47 | ||
|
|
9ba008002b | ||
|
|
8914cf78a1 | ||
|
|
d360375b4f | ||
|
|
1caab194af | ||
|
|
31754eba5d | ||
|
|
3cfa16b8b7 | ||
|
|
f80d2bacf4 | ||
|
|
5df3717d94 | ||
|
|
68897f04a2 | ||
|
|
4cb6aeae36 | ||
|
|
0a765a35bf | ||
|
|
6c0b122fbc | ||
|
|
4da2bd90cb | ||
|
|
f0275192c6 | ||
|
|
df905a1d73 | ||
|
|
ad8ad06f44 | ||
|
|
d6b9e2df62 | ||
|
|
5c9b36556f | ||
|
|
80a8348a99 | ||
|
|
005c9f471e | ||
|
|
b40532a830 | ||
|
|
fc7a4408e9 | ||
|
|
93b5f0081d | ||
|
|
ce049ea3ee | ||
|
|
fcc39b2db5 | ||
|
|
cb70fb4e82 | ||
|
|
2593a43d72 | ||
|
|
e44ff5b72a | ||
|
|
22cb1b50a6 | ||
|
|
a42c413705 | ||
|
|
d59d38dc7c | ||
|
|
77582be7fd | ||
|
|
0cb50355b7 | ||
|
|
a2d66e91ff | ||
|
|
ccdb981917 | ||
|
|
d80b581ace | ||
|
|
53efb6711d | ||
|
|
1de6e875f9 | ||
|
|
95a15c3cf8 | ||
|
|
ab320684f5 | ||
|
|
a284b69a1e | ||
|
|
b590f41254 | ||
|
|
a97076ead5 | ||
|
|
0b6df8be1c | ||
|
|
150bab0b57 | ||
|
|
d3355eda65 | ||
|
|
fbf10e553d | ||
|
|
fb37be5734 | ||
|
|
54e6cefa67 | ||
|
|
33b25c1129 | ||
|
|
44d8545c09 | ||
|
|
7a2808243c | ||
|
|
1be84de26b | ||
|
|
78e37f7ab4 | ||
|
|
e49459fd8b | ||
|
|
52f6e7fc32 | ||
|
|
c8ea61dc79 | ||
|
|
16a769ea61 | ||
|
|
6b880af447 | ||
|
|
475781db91 | ||
|
|
4dae082cd5 | ||
|
|
57405b2f56 | ||
|
|
88576f68fd | ||
|
|
aa4e013097 | ||
|
|
d67cfc911b | ||
|
|
00a3ad738f | ||
|
|
1d39d34d7c | ||
|
|
5f6013edd4 | ||
|
|
3e198ecd28 | ||
|
|
d48b98f582 | ||
|
|
9b839231f7 | ||
|
|
dd80614465 | ||
|
|
8c2be1b406 | ||
|
|
8152b7dad6 | ||
|
|
fb4fe175d9 | ||
|
|
5e03eb9b51 | ||
|
|
ef25575f85 | ||
|
|
b77b338c7a | ||
|
|
0e4fe4e9bb | ||
|
|
f742f83834 | ||
|
|
e6e4e53a73 | ||
|
|
7c594ba7a9 | ||
|
|
0156a9a9d5 | ||
|
|
3facbc0900 | ||
|
|
78cef1b3c7 | ||
|
|
d907c469ed | ||
|
|
cc238d3e34 | ||
|
|
0f9b38895e | ||
|
|
8fa1eae352 | ||
|
|
e13fb25f14 | ||
|
|
e36f942129 | ||
|
|
d34619824c | ||
|
|
80297f113f | ||
|
|
80f51bfe1e | ||
|
|
f8b9f4c1fa | ||
|
|
587f431ef4 | ||
|
|
65a4f66d2c | ||
|
|
a253b6c0cf | ||
|
|
efcbc1fbdb | ||
|
|
e560f9cbd6 | ||
|
|
80235d53f4 | ||
|
|
892b9a732e | ||
|
|
d8a0a015e4 | ||
|
|
e60e3b9fae | ||
|
|
6715f01b8c | ||
|
|
465af9bc41 | ||
|
|
d10bcfc72f | ||
|
|
942e5b9cd1 | ||
|
|
51a90d32f8 | ||
|
|
ac46632e73 | ||
|
|
1192bef1ae | ||
|
|
b9ec382589 | ||
|
|
5ecf19ef4f | ||
|
|
9636809b4d | ||
|
|
ba1c1ed952 | ||
|
|
7452390614 | ||
|
|
69042e42b7 | ||
|
|
1e93deab2a | ||
|
|
16ea809bb3 | ||
|
|
78aa4343b7 | ||
|
|
6815109e15 | ||
|
|
e34fbcec58 | ||
|
|
bb2a21270b | ||
|
|
49b9ec9025 | ||
|
|
a2e896e102 | ||
|
|
2e1ef647a9 | ||
|
|
f0c314df80 | ||
|
|
4db39828ef | ||
|
|
b2d40825ac | ||
|
|
6df5d3334e | ||
|
|
0e982df90c | ||
|
|
3834d93c9d | ||
|
|
16920a5b82 | ||
|
|
d66e35fdde | ||
|
|
d93dde0a03 | ||
|
|
2d232124dd | ||
|
|
ac6702fcf7 | ||
|
|
c4b016c9c8 | ||
|
|
6baa583a28 | ||
|
|
82df2ecfa9 | ||
|
|
06b3de720a | ||
|
|
b0edd5659f | ||
|
|
bb5c2eea10 | ||
|
|
e31e4dfe3a | ||
|
|
caf2cd8487 | ||
|
|
15c6f11a5e | ||
|
|
a4ea88f4be | ||
|
|
36d5747fbf | ||
|
|
3d8c535ffa | ||
|
|
1c067d0284 | ||
|
|
b6be0462a5 | ||
|
|
cce91ea16d | ||
|
|
d756041b06 | ||
|
|
2d0eb0a05b | ||
|
|
02f3239669 | ||
|
|
14a9240c45 | ||
|
|
c659638fb4 | ||
|
|
fd15b63044 | ||
|
|
263e6c34b5 | ||
|
|
eb62a3dc17 | ||
|
|
161ee090a8 | ||
|
|
560ec437b9 | ||
|
|
ccd0597b35 | ||
|
|
c5c0a3768a | ||
|
|
5aa2d24d58 | ||
|
|
ae28c595f9 | ||
|
|
1d08ddda60 | ||
|
|
578379fd00 | ||
|
|
7c9f550d4c | ||
|
|
84d4510d70 | ||
|
|
fa194ec258 | ||
|
|
fd56de403d | ||
|
|
85fde46504 | ||
|
|
b283178979 | ||
|
|
e0dddfceba | ||
|
|
bddef38a7c | ||
|
|
b5f2f77944 | ||
|
|
fca0718ed0 | ||
|
|
0d44ade6ea | ||
|
|
08ca2aa266 | ||
|
|
fe15758e59 | ||
|
|
674efae184 | ||
|
|
4a65bc88d5 | ||
|
|
a8f3d59729 | ||
|
|
6018f83a22 | ||
|
|
0b6247851b | ||
|
|
8640dee053 | ||
|
|
824db2e3bd | ||
|
|
c2c79c4676 | ||
|
|
4795fe5687 | ||
|
|
d508f339c1 | ||
|
|
c7054537e7 | ||
|
|
b98b904023 | ||
|
|
253df9325d | ||
|
|
78a9cc1d0c | ||
|
|
b25fcc3381 | ||
|
|
a2c0df5891 | ||
|
|
dc33c26960 | ||
|
|
51d7bc2c37 | ||
|
|
cdbdccf1ad | ||
|
|
397c369114 | ||
|
|
6f9bbb184a | ||
|
|
b12c818862 | ||
|
|
9118dcf925 | ||
|
|
d333d0c9e4 | ||
|
|
7f9cf6f45c | ||
|
|
9b465cb550 | ||
|
|
9144b7206e | ||
|
|
dd14843f2e | ||
|
|
09a18b2305 | ||
|
|
31f2feee2e | ||
|
|
218bb62bfd | ||
|
|
694c2ad767 | ||
|
|
97943fcd38 | ||
|
|
77f33467d2 | ||
|
|
651454170d | ||
|
|
7ca48bd136 | ||
|
|
968e508bb5 | ||
|
|
a6d318a197 | ||
|
|
cd20f4086b | ||
|
|
ebd5905947 | ||
|
|
817a3c62bb | ||
|
|
f8f58400fe | ||
|
|
ef06840649 | ||
|
|
b17c14d62e | ||
|
|
19dba94064 | ||
|
|
601e24f9e7 | ||
|
|
c7f323ee13 | ||
|
|
e4522f3af4 | ||
|
|
79af461a5b | ||
|
|
2e8e07faf6 | ||
|
|
ecdb000818 | ||
|
|
999fd0d4da | ||
|
|
705dd9558f | ||
|
|
97ca866ffa | ||
|
|
543b977db7 | ||
|
|
ebb8a6d025 | ||
|
|
506543281e | ||
|
|
60322be22a | ||
|
|
e1f30f24a8 | ||
|
|
1759f6b25c | ||
|
|
6578f25cc9 | ||
|
|
8c26e0323f | ||
|
|
a5575894ab | ||
|
|
357823a027 | ||
|
|
a6d3f6b3eb | ||
|
|
ae4c69e75c | ||
|
|
31cadc532b | ||
|
|
6e8443473b | ||
|
|
cca4ab3cd8 | ||
|
|
dab0ee3306 | ||
|
|
c6d1ed91a7 | ||
|
|
a613a244f4 | ||
|
|
268fe15004 | ||
|
|
7bc9be686f | ||
|
|
751919ec5a | ||
|
|
da913b426e | ||
|
|
d8ef99cd8f | ||
|
|
d08a6d7dd3 | ||
|
|
896e9bca8e | ||
|
|
1df9597bb1 | ||
|
|
eaf55f2099 | ||
|
|
5018a1f9eb | ||
|
|
71ba8f55a7 | ||
|
|
b65db707ed | ||
|
|
ed62266a43 | ||
|
|
49913b7dad | ||
|
|
3eeeb9e00b | ||
|
|
bfb1642284 | ||
|
|
0544a605c3 | ||
|
|
3f5acda132 | ||
|
|
02b1ba2926 | ||
|
|
7f7f9e3c7c | ||
|
|
6fcee03752 | ||
|
|
5782ceeb5d | ||
|
|
f752db5892 | ||
|
|
bce58bc97b | ||
|
|
d373687bc4 | ||
|
|
e5e510c825 | ||
|
|
29064ec72f | ||
|
|
953eee1dc8 | ||
|
|
75f76f4875 | ||
|
|
ecfbe68c33 | ||
|
|
7f02eb9cf0 | ||
|
|
4ab90065dc | ||
|
|
d3e39a1359 | ||
|
|
60e5861de4 | ||
|
|
ca7f5045ae | ||
|
|
299bd67151 | ||
|
|
4d4bb3fd7f | ||
|
|
7fd64a1b73 | ||
|
|
e3e8765b91 | ||
|
|
b0997fb5d2 | ||
|
|
435cf05f9f | ||
|
|
37dab9fb22 | ||
|
|
943dfe0619 | ||
|
|
be7114d3e6 | ||
|
|
fb44c8fbe4 | ||
|
|
94375b7d36 | ||
|
|
8b585deb78 | ||
|
|
4d8b544aed | ||
|
|
548d651d29 | ||
|
|
0b342acec9 | ||
|
|
cc6d3c1b1a | ||
|
|
74a748d92e | ||
|
|
1de81d0af5 | ||
|
|
ff9ef21f67 | ||
|
|
266a546478 | ||
|
|
87407ca832 | ||
|
|
90282d4436 | ||
|
|
abbe6d6c1f | ||
|
|
a28f701e6f | ||
|
|
4cdc995a7f | ||
|
|
713a01bfa9 | ||
|
|
ac291b688d | ||
|
|
84f7e244f2 | ||
|
|
4a8207f367 | ||
|
|
9cfd4d27e9 | ||
|
|
1b23cfd747 | ||
|
|
c708205593 | ||
|
|
a22c6c8013 | ||
|
|
b576f473e5 | ||
|
|
0b127caa83 | ||
|
|
5801bf3bdf | ||
|
|
4507ce359d | ||
|
|
3e14f28dc2 | ||
|
|
a9dcf09d13 | ||
|
|
c8998c2bcf | ||
|
|
10bf1295bc | ||
|
|
1e869973d4 | ||
|
|
731c8962c9 | ||
|
|
294b8bb789 | ||
|
|
4f9b819f48 | ||
|
|
5318d5fa8e | ||
|
|
98b156bdde | ||
|
|
511dd02107 | ||
|
|
f1f7a2e7b6 | ||
|
|
d557cf5427 | ||
|
|
2b1c55ee67 | ||
|
|
925ddaa63a | ||
|
|
2b60b18d47 | ||
|
|
d502406fa2 | ||
|
|
afdbf711f7 | ||
|
|
39d2941099 | ||
|
|
b4f7b1d71d | ||
|
|
69061cd41c | ||
|
|
8ba7f7f961 | ||
|
|
5e5aa17e14 | ||
|
|
551f5fc929 | ||
|
|
4e7b0d11d0 | ||
|
|
06bc53692a | ||
|
|
007ee38cb4 | ||
|
|
2a732306a1 | ||
|
|
82192bef91 | ||
|
|
0c51dfe19c | ||
|
|
24a9fa1ccc | ||
|
|
14b06507cb | ||
|
|
b46233087b | ||
|
|
28fb2e2a08 | ||
|
|
943e211cf1 | ||
|
|
ad0a13004e | ||
|
|
04bb6a5275 | ||
|
|
d3c917eac1 | ||
|
|
4c13271a5b | ||
|
|
20027c2db7 | ||
|
|
6affc70a66 | ||
|
|
ab4c9bdeda | ||
|
|
b4a9c9b7f5 | ||
|
|
5e20d50abf | ||
|
|
53abbbbe56 | ||
|
|
1938cb586d | ||
|
|
50490ece84 | ||
|
|
f291cc2bd3 | ||
|
|
2542c8bd53 | ||
|
|
b457fd634e | ||
|
|
041fd0e0cd | ||
|
|
a983edde1e | ||
|
|
7eb642dd13 | ||
|
|
e0bc93371e | ||
|
|
db56486506 | ||
|
|
c99be13697 | ||
|
|
0830c78728 | ||
|
|
edade93054 | ||
|
|
8a72b30cbc | ||
|
|
ed9cb0f918 | ||
|
|
7e0915cb9c | ||
|
|
a51294d570 | ||
|
|
d962f218a1 | ||
|
|
7b248427f0 | ||
|
|
b99fb8b11f | ||
|
|
26250e790f | ||
|
|
b26dbe81f4 | ||
|
|
903212345b |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -20,7 +20,9 @@
|
|||||||
*.gif binary
|
*.gif binary
|
||||||
*.jar binary
|
*.jar binary
|
||||||
*.lib binary
|
*.lib binary
|
||||||
|
*.otf binary
|
||||||
*.png binary
|
*.png binary
|
||||||
*.sketch binary
|
*.sketch binary
|
||||||
*.so binary
|
*.so binary
|
||||||
|
*.ttf binary
|
||||||
*.zip binary
|
*.zip binary
|
||||||
|
|||||||
8
.gitbugtraq
Normal file
8
.gitbugtraq
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# links issue numbers in git commit messages to issue tracker
|
||||||
|
# https://github.com/mstrap/bugtraq
|
||||||
|
# for SmartGit - https://www.syntevo.com/smartgit/
|
||||||
|
|
||||||
|
[bugtraq]
|
||||||
|
url = "https://github.com/JFormDesigner/FlatLaf/issues/%BUGID%"
|
||||||
|
loglinkregex = "#[0-9]{1,5}"
|
||||||
|
logregex = "[0-9]{1,5}"
|
||||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
custom: https://www.formdev.com/flatlaf/sponsor/
|
||||||
170
.github/workflows/ci.yml
vendored
170
.github/workflows/ci.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
# https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
@@ -8,145 +9,140 @@ on:
|
|||||||
- '*'
|
- '*'
|
||||||
tags:
|
tags:
|
||||||
- '[0-9]*'
|
- '[0-9]*'
|
||||||
pull_request:
|
paths-ignore:
|
||||||
branches:
|
- '**.md'
|
||||||
- '*'
|
- '.*'
|
||||||
|
- '**/.settings/**'
|
||||||
|
- 'flatlaf-core/svg/**'
|
||||||
|
- 'flatlaf-testing/dumps/**'
|
||||||
|
- 'flatlaf-testing/misc/**'
|
||||||
|
- 'images/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
name: build (11)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
# test against
|
|
||||||
# - Java 1.8 (minimum requirement)
|
|
||||||
# - Java 9 (first version with JPMS)
|
|
||||||
# - Java LTS versions (11, 17, ...)
|
|
||||||
# - lastest Java version(s)
|
|
||||||
java:
|
|
||||||
- 1.8
|
|
||||||
- 9
|
|
||||||
- 11 # LTS
|
|
||||||
- 14
|
|
||||||
- 15
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/actions/wrapper-validation@v4
|
||||||
|
|
||||||
- name: Setup Java ${{ matrix.java }}
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: ${{ matrix.java }}
|
java-version: 11
|
||||||
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
- name: Cache Gradle wrapper
|
- name: Check with Error Prone
|
||||||
uses: actions/cache@v1
|
run: ./gradlew errorprone clean
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
if: matrix.java == '11'
|
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-build-artifacts
|
name: FlatLaf-build-artifacts
|
||||||
path: |
|
path: |
|
||||||
flatlaf-*/build/libs
|
flatlaf-*/build/libs
|
||||||
|
flatlaf-*/flatlaf-*/build/libs
|
||||||
!**/*-javadoc.jar
|
!**/*-javadoc.jar
|
||||||
!**/*-sources.jar
|
!**/*-sources.jar
|
||||||
|
|
||||||
|
|
||||||
snapshot:
|
build-on:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
|
if: github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
# test against
|
||||||
|
# - Java 8 (minimum requirement)
|
||||||
|
# - Java LTS versions (11, 17, ...)
|
||||||
|
# - latest Java version(s)
|
||||||
|
java:
|
||||||
|
- 8
|
||||||
|
- 17 # LTS
|
||||||
|
- 21 # LTS
|
||||||
|
toolchain: [""]
|
||||||
|
include:
|
||||||
|
- java: 21
|
||||||
|
toolchain: 25 # LTS
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Java ${{ matrix.java }}
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.java }}
|
||||||
|
distribution: temurin # Java 8, 11, 17 and 21 are pre-installed on ubuntu-latest
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
|
||||||
|
|
||||||
|
|
||||||
|
snapshot:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build-on
|
||||||
if: |
|
if: |
|
||||||
github.event_name == 'push' &&
|
github.event_name == 'push' &&
|
||||||
github.ref == 'refs/heads/main' &&
|
(github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )) &&
|
||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
- name: Cache Gradle wrapper
|
- name: Publish snapshot to Sonatype Central
|
||||||
uses: actions/cache@v1
|
run: ./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Publish snapshot to oss.sonatype.org
|
|
||||||
run: ./gradlew publish -Dorg.gradle.internal.publish.checksums.insecure=true
|
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build-on
|
||||||
if: |
|
if: |
|
||||||
github.event_name == 'push' &&
|
github.event_name == 'push' &&
|
||||||
startsWith( github.ref, 'refs/tags/' ) &&
|
startsWith( github.ref, 'refs/tags/' ) &&
|
||||||
github.repository == 'JFormDesigner/FlatLaf'
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/caches
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Release a new stable version to Maven Central
|
- name: Release a new stable version to Maven Central
|
||||||
run: ./gradlew publish :flatlaf-demo:build -Drelease=true
|
run: ./gradlew publishToSonatype closeSonatypeStagingRepository :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
|
||||||
env:
|
env:
|
||||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||||
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
||||||
|
|
||||||
- name: Upload demo
|
- name: Install lftp
|
||||||
uses: sebastianpopp/ftp-action@releases/v2
|
run: sudo apt-get -y install lftp
|
||||||
with:
|
|
||||||
host: ${{ secrets.FTP_SERVER }}
|
- name: Upload demo and theme editor
|
||||||
user: ${{ secrets.FTP_USERNAME }}
|
run: >
|
||||||
password: ${{ secrets.FTP_PASSWORD }}
|
lftp -c "set ftp:ssl-force true;
|
||||||
forceSsl: true
|
open -u ${{ secrets.FTP_USERNAME }},${{ secrets.FTP_PASSWORD }} ${{ secrets.FTP_SERVER }};
|
||||||
localDir: "flatlaf-demo/build/libs"
|
mput flatlaf-demo/build/libs/flatlaf-demo-*.jar;
|
||||||
remoteDir: "."
|
mput flatlaf-theme-editor/build/libs/flatlaf-theme-editor-*.jar"
|
||||||
options: "--only-newer --no-recursion --verbose=1"
|
|
||||||
|
|||||||
62
.github/workflows/fonts.yml
vendored
Normal file
62
.github/workflows/fonts.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
|
name: Fonts
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
tags:
|
||||||
|
- 'fonts/*-[0-9]*'
|
||||||
|
paths:
|
||||||
|
- 'flatlaf-fonts/**'
|
||||||
|
- '.github/workflows/fonts.yml'
|
||||||
|
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||||
|
- '!**.md'
|
||||||
|
- '!**/.settings/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Fonts:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
font:
|
||||||
|
- inter
|
||||||
|
- jetbrains-mono
|
||||||
|
- roboto
|
||||||
|
- roboto-mono
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: |
|
||||||
|
github.event_name == 'push' &&
|
||||||
|
github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Java 11
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: 11
|
||||||
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
|
- name: Build with Gradle
|
||||||
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build
|
||||||
|
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) ) != true
|
||||||
|
|
||||||
|
- name: Publish snapshot to Sonatype Central
|
||||||
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:publish -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||||
|
env:
|
||||||
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
|
if: github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )
|
||||||
|
|
||||||
|
- name: Release a new stable version to Maven Central
|
||||||
|
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:build :flatlaf-fonts-${{ matrix.font }}:publish -Prelease
|
||||||
|
env:
|
||||||
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
|
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||||
|
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
||||||
|
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) )
|
||||||
72
.github/workflows/natives.yml
vendored
72
.github/workflows/natives.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
# https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
name: Native Libraries
|
name: Native Libraries
|
||||||
|
|
||||||
@@ -9,50 +10,53 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- '[0-9]*'
|
- '[0-9]*'
|
||||||
paths:
|
paths:
|
||||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
- 'flatlaf-natives/**'
|
||||||
- '.github/workflows/natives.yml'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- '*'
|
|
||||||
paths:
|
|
||||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
|
||||||
- '.github/workflows/natives.yml'
|
- '.github/workflows/natives.yml'
|
||||||
|
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||||
|
- '!**.md'
|
||||||
|
- '!**/.settings/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Windows:
|
Natives:
|
||||||
runs-on: windows-latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- windows-latest
|
||||||
|
- macos-latest
|
||||||
|
- ubuntu-latest
|
||||||
|
- ubuntu-24.04-arm
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/actions/wrapper-validation@v4
|
||||||
|
|
||||||
- name: Setup Java 1.8
|
- name: install libxt-dev
|
||||||
uses: actions/setup-java@v1
|
if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm'
|
||||||
|
run: sudo apt install libxt-dev
|
||||||
|
|
||||||
|
- name: install g++-aarch64-linux-gnu
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
run: sudo apt install g++-aarch64-linux-gnu
|
||||||
|
|
||||||
|
- name: Setup Java 11
|
||||||
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 1.8
|
java-version: 11
|
||||||
|
distribution: temurin
|
||||||
- name: Cache Gradle wrapper
|
cache: gradle
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.gradle/wrapper
|
|
||||||
key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
|
|
||||||
|
|
||||||
- name: Cache Gradle cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
!~/.gradle/caches/modules-2/modules-2.lock
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew :flatlaf-natives-windows:build
|
# --no-daemon is necessary on Windows otherwise caching Gradle would fail with:
|
||||||
|
# tar.exe: Couldn't open ~/.gradle/caches/modules-2/modules-2.lock: Permission denied
|
||||||
|
run: ./gradlew build-natives --no-daemon
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-natives-windows-build-artifacts
|
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
||||||
path: |
|
path: |
|
||||||
flatlaf-natives/flatlaf-natives-windows/build
|
flatlaf-core/src/main/resources/com/formdev/flatlaf/natives
|
||||||
|
flatlaf-natives/flatlaf-natives-*/build
|
||||||
|
|||||||
37
.github/workflows/pr-snapshots.yml
vendored
Normal file
37
.github/workflows/pr-snapshots.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
|
||||||
|
|
||||||
|
name: PR Snapshots
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
- '.*'
|
||||||
|
- '**/.settings/**'
|
||||||
|
- 'flatlaf-core/svg/**'
|
||||||
|
- 'flatlaf-testing/dumps/**'
|
||||||
|
- 'flatlaf-testing/misc/**'
|
||||||
|
- 'images/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
snapshot:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.repository == 'JFormDesigner/FlatLaf'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Java 11
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: 11
|
||||||
|
distribution: temurin # pre-installed on ubuntu-latest
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
|
- name: Publish PR snapshot to Sonatype Central
|
||||||
|
run: >
|
||||||
|
./gradlew publish -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||||
|
-Pgithub.event.pull_request.number=${{ github.event.pull_request.number }}
|
||||||
|
env:
|
||||||
|
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
|
||||||
|
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,9 +5,12 @@ build/
|
|||||||
.project
|
.project
|
||||||
.settings/
|
.settings/
|
||||||
.idea/
|
.idea/
|
||||||
|
.consulo/
|
||||||
out/
|
out/
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
|
*.xcuserstate
|
||||||
|
*.xcworkspacedata
|
||||||
.vs/
|
.vs/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
1214
CHANGELOG.md
1214
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
362
README.md
362
README.md
@@ -6,14 +6,19 @@ Swing desktop applications.
|
|||||||
|
|
||||||
It looks almost flat (no shadows or gradients), clean, simple and elegant.
|
It looks almost flat (no shadows or gradients), clean, simple and elegant.
|
||||||
FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes,
|
FlatLaf comes with **Light**, **Dark**, **IntelliJ** and **Darcula** themes,
|
||||||
scales on **HiDPI** displays and runs on Java 8 or newer.
|
scales on **HiDPI** displays and runs on Java 8 or newer (LTS and latest).
|
||||||
|
|
||||||
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
The look is heavily inspired by **Darcula** and **IntelliJ** themes from
|
||||||
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
macOS Themes
|
||||||
|
------------
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
IntelliJ Platform Themes
|
IntelliJ Platform Themes
|
||||||
@@ -25,6 +30,27 @@ FlatLaf can use 3rd party themes created for IntelliJ Platform (see
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
Sponsors
|
||||||
|
--------
|
||||||
|
|
||||||
|
### Current Sponsors
|
||||||
|
|
||||||
|
<a href="https://www.soptim.de/"><img src="https://www.formdev.com/flatlaf/sponsor/soptim.svg" width="200" alt="SOPTIM" title="SOPTIM - your expert in software solutions for the energy industry"></a>
|
||||||
|
|
||||||
|
<a href="https://exocharts.com/"><img src="https://www.formdev.com/flatlaf/sponsor/Exocharts.png" width="200" alt="Exocharts" title="Exocharts - Professional Grade OrderFlow"></a>
|
||||||
|
|
||||||
|
<!-- [](https://www.formdev.com/flatlaf/sponsor/) -->
|
||||||
|
|
||||||
|
[Become a Sponsor](https://www.formdev.com/flatlaf/sponsor/)
|
||||||
|
|
||||||
|
### Previous Sponsors
|
||||||
|
|
||||||
|
<a href="https://www.ej-technologies.com/"><img src="https://www.formdev.com/flatlaf/sponsor/ej-technologies.png" width="200" alt="ej-technologies" title="ej-technologies - Java APM, Java Profiler, Java Installer Builder"></a>
|
||||||
|
|
||||||
|
<a href="https://www.dbvis.com/"><img src="https://www.formdev.com/flatlaf/sponsor/dbvisualizer.svg" width="200" alt="DbVisualizer" title="DbVisualizer - SQL Client and Editor"></a>
|
||||||
|
|
||||||
|
<a href="https://www.dscsag.com/"><img src="https://www.formdev.com/flatlaf/sponsor/DSC.png" height="48" alt="DSC Software AG" title="DSC Software AG - Your Companion for Integrative PLM"></a>
|
||||||
|
|
||||||
Demo
|
Demo
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -46,18 +72,23 @@ build script:
|
|||||||
artifactId: flatlaf
|
artifactId: flatlaf
|
||||||
version: (see button below)
|
version: (see button below)
|
||||||
|
|
||||||
Otherwise download `flatlaf-<version>.jar` here:
|
Otherwise, download `flatlaf-<version>.jar` here:
|
||||||
|
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.formdev/flatlaf)
|
[](https://central.sonatype.com/artifact/com.formdev/flatlaf)
|
||||||
|
|
||||||
|
See also
|
||||||
|
[Native Libraries distribution](https://www.formdev.com/flatlaf/native-libraries/)
|
||||||
|
for instructions on how to redistribute FlatLaf native libraries with your
|
||||||
|
application.
|
||||||
|
|
||||||
|
|
||||||
### Snapshots
|
### Snapshots
|
||||||
|
|
||||||
FlatLaf snapshot binaries are available on
|
FlatLaf snapshot binaries are available on
|
||||||
[Sonatype OSSRH](https://oss.sonatype.org/content/repositories/snapshots/com/formdev/flatlaf/).
|
[Sonatype Central](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/com/formdev/flatlaf/).
|
||||||
To access the latest snapshot, change the FlatLaf version in your dependencies
|
To access the latest snapshot, change the FlatLaf version in your dependencies
|
||||||
to `<version>-SNAPSHOT` (e.g. `0.27-SNAPSHOT`) and add the repository
|
to `<version>-SNAPSHOT` (e.g. `3.7-SNAPSHOT`) and add the repository
|
||||||
`https://oss.sonatype.org/content/repositories/snapshots/` to your build (see
|
`https://central.sonatype.com/repository/maven-snapshots/` to your build (see
|
||||||
[Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html)
|
[Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html)
|
||||||
and
|
and
|
||||||
[Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository)
|
[Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository)
|
||||||
@@ -67,20 +98,25 @@ docs).
|
|||||||
Addons
|
Addons
|
||||||
------
|
------
|
||||||
|
|
||||||
- [IntelliJ Themes Pack](flatlaf-intellij-themes)
|
- [IntelliJ Themes Pack](flatlaf-intellij-themes) - bundles many popular
|
||||||
- [Extras](flatlaf-extras)
|
open-source 3rd party themes
|
||||||
- [SwingX](flatlaf-swingx)
|
- [Extras](flatlaf-extras) - SVG icon, tri-state check box, UI inspectors, and
|
||||||
- [JIDE Common Layer](flatlaf-jide-oss)
|
more
|
||||||
|
- [SwingX](flatlaf-swingx) - support for SwingX components
|
||||||
|
- [JIDE Common Layer](flatlaf-jide-oss) - support for JIDE Common Layer
|
||||||
|
components
|
||||||
|
- [Fonts](flatlaf-fonts) - some font families bundled in easy-to-use and
|
||||||
|
redistributable JARs
|
||||||
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
To enable FlatLaf, add following code to your main method before you create any
|
To use FlatLaf, add following code to your main method before you create any
|
||||||
Swing component:
|
Swing component:
|
||||||
|
|
||||||
~~~java
|
~~~java
|
||||||
FlatLightLaf.install();
|
FlatLightLaf.setup();
|
||||||
|
|
||||||
// create UI here...
|
// create UI here...
|
||||||
~~~
|
~~~
|
||||||
@@ -96,14 +132,26 @@ For more information and documentation visit
|
|||||||
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
||||||
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
||||||
- [Properties Files](https://www.formdev.com/flatlaf/properties-files/)
|
- [Properties Files](https://www.formdev.com/flatlaf/properties-files/)
|
||||||
|
- [Components UI Properties](https://www.formdev.com/flatlaf/components/)
|
||||||
|
- [Typography](https://www.formdev.com/flatlaf/typography/)
|
||||||
- [Client Properties](https://www.formdev.com/flatlaf/client-properties/)
|
- [Client Properties](https://www.formdev.com/flatlaf/client-properties/)
|
||||||
- [System Properties](https://www.formdev.com/flatlaf/system-properties/)
|
- [System Properties](https://www.formdev.com/flatlaf/system-properties/)
|
||||||
|
|
||||||
|
|
||||||
|
Theme Editor
|
||||||
|
------------
|
||||||
|
|
||||||
|
The Theme Editor that supports editing FlatLaf theme properties files. See
|
||||||
|
[Theme Editor documentation](https://www.formdev.com/flatlaf/theme-editor/) for
|
||||||
|
details and downloads.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
Buzz
|
Buzz
|
||||||
----
|
----
|
||||||
|
|
||||||
- [What others say about FlatLaf on Twitter](https://twitter.com/search?f=live&q=flatlaf)
|
- [FlatLaf 3.1 (and 3.0) announcement on Reddit](https://www.reddit.com/r/java/comments/12xgrsu/flatlaf_31_and_30_swing_look_and_feel/)
|
||||||
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
|
- [FlatLaf 1.0 announcement on Reddit](https://www.reddit.com/r/java/comments/lsbcwe/flatlaf_10_swing_look_and_feel/)
|
||||||
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
- [FlatLaf announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
||||||
|
|
||||||
@@ -111,89 +159,231 @@ Buzz
|
|||||||
Applications using FlatLaf
|
Applications using FlatLaf
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
### Featured
|
||||||
and much more
|
|
||||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
-  [JFormDesigner](https://www.formdev.com/)
|
||||||
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
(**commercial**) - Java/Swing GUI Designer (from the FlatLaf creators)
|
||||||
- 
|
- 
|
||||||
|
[JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html)
|
||||||
|
(**commercial**) - the award-winning all-in-one Java profiler
|
||||||
|
- 
|
||||||
[install4j](https://www.ej-technologies.com/products/install4j/overview.html)
|
[install4j](https://www.ej-technologies.com/products/install4j/overview.html)
|
||||||
9.0 (**commercial**) - the powerful multi-platform Java installer builder
|
(**commercial**) - the powerful multi-platform Java installer builder
|
||||||
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
-  [DbVisualizer](https://www.dbvis.com/)
|
||||||
(**commercial**) - the universal database tool for developers, analysts and
|
(**commercial**) - the universal database tool for developers, analysts and
|
||||||
DBAs
|
DBAs
|
||||||
-  [MagicPlot](https://magicplot.com/) 3.0
|
-  [Apache NetBeans](https://netbeans.apache.org/) - IDE
|
||||||
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
for Java, PHP, HTML and much more
|
||||||
|
- 
|
||||||
|
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) (**commercial**) -
|
||||||
|
Thermodynamics and Properties Software
|
||||||
|
|
||||||
|
### Data
|
||||||
|
|
||||||
|
-  [Ultorg](https://www.ultorg.com/) (**commercial**) - a
|
||||||
|
visual query system for relational databases
|
||||||
|
- [Jailer](https://github.com/Wisser/Jailer) - database subsetting and
|
||||||
|
relational data browsing tool
|
||||||
|
-  [MagicPlot](https://magicplot.com/) (**commercial**) -
|
||||||
|
Software for nonlinear fitting, plotting and data analysis
|
||||||
|
- [Constellation](https://www.constellation-app.com/) - Data Visualization and
|
||||||
|
Analytics (based on NetBeans platform)
|
||||||
|
- [Kafka Visualizer](https://github.com/kumait/kafkavisualizer) - Kafka GUI
|
||||||
|
client
|
||||||
- 
|
- 
|
||||||
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
[RedisFront](https://github.com/dromara/RedisFront/blob/master/README_EN.md) -
|
||||||
(**commercial**) - Thermodynamics and Properties Software
|
Cross-platform redis GUI
|
||||||
- [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds most widely used web
|
|
||||||
app scanner
|
|
||||||
- 
|
- 
|
||||||
|
[Zettelkasten](https://github.com/Zettelkasten-Team/Zettelkasten) - knowledge
|
||||||
|
management tool
|
||||||
|
-  [QStudio](https://www.timestored.com/qstudio/) - free
|
||||||
|
SQL editor
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
-  [ZAP](https://www.zaproxy.org/) - the world's most
|
||||||
|
widely used web app scanner
|
||||||
|
- 
|
||||||
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
[Burp Suite Professional and Community Edition](https://portswigger.net/burp/pro)
|
||||||
2020.11.2 (**commercial**) - the leading software for web security testing
|
(**commercial**) - the leading software for web security testing
|
||||||
- 
|
- [Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software
|
||||||
[BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
reverse engineering (SRE) framework
|
||||||
|
- [jadx](https://github.com/skylot/jadx) - Dex to Java decompiler
|
||||||
|
- [BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
||||||
FlatLaf themes to Burp Suite
|
FlatLaf themes to Burp Suite
|
||||||
- [JOSM](https://josm.openstreetmap.de/) - an extensible editor for
|
- [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks
|
||||||
[OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf JOSM plugin)
|
your website
|
||||||
- [jAlbum](https://jalbum.net/) 21 (**commercial**) - creates photo album
|
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||||
websites
|
encryption
|
||||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
|
||||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
### Software Development
|
||||||
checks your website
|
|
||||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib)
|
||||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
- [KeyStore Explorer](https://keystore-explorer.org/)
|
||||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5 - a turn-based sci-fi board
|
- [muCommander](https://github.com/mucommander/mucommander) - lightweight
|
||||||
game
|
cross-platform file manager
|
||||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
- [Guiffy](https://www.guiffy.com/) (**commercial**) - advanced cross-platform
|
||||||
0.13.b024 - GUI builder for
|
Diff/Merge
|
||||||
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
- [HashGarten](https://github.com/jonelo/HashGarten) - cross-platform Swing GUI
|
||||||
framework for embedded displays
|
for Jacksum
|
||||||
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
||||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
IDE for Pseudo-Assembler
|
||||||
gamepad mapping software
|
- [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming
|
||||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
language created to learn programming
|
||||||
connections manager
|
- [lsfusion platform](https://github.com/lsfusion/platform) - information
|
||||||
- [jEnTunnel](https://github.com/ggrandes/jentunnel) - manage SSH Tunnels made
|
systems development platform
|
||||||
easy
|
-  [Consulo](https://github.com/consulo/consulo) - open
|
||||||
|
source cross-platform multi-language IDE (Java, .NET, JS, etc)
|
||||||
|
- [Convertigo](https://github.com/convertigo/convertigo) - low code & no code
|
||||||
|
mobile & web platform
|
||||||
|
-  [EduMIPS64](https://github.com/EduMIPS64/edumips64) -
|
||||||
|
visual MIPS64 CPU simulator
|
||||||
|
-  [Launch4j](https://launch4j.sourceforge.net/) -
|
||||||
|
cross-platform Java executable wrapper
|
||||||
|
|
||||||
|
### Electrical
|
||||||
|
|
||||||
|
- [Antares](https://www.antarescircuit.io/) - a free, powerful platform for
|
||||||
|
designing, simulating and explaining digital circuits
|
||||||
|
- [Logisim-evolution](https://github.com/logisim-evolution/logisim-evolution) -
|
||||||
|
Digital logic design tool and simulator
|
||||||
|
-  [OpenPnP](https://github.com/openpnp/openpnp) - SMT
|
||||||
|
Pick and Place Hardware and Software
|
||||||
|
- 
|
||||||
|
[TrainControl](https://github.com/bob123456678/TrainControl) - control Marklin
|
||||||
|
/ Trix / DCC digital model train layout
|
||||||
|
- [Makelangelo Software](https://github.com/MarginallyClever/Makelangelo-software) -
|
||||||
|
for plotters, especially the wall-hanging polargraph
|
||||||
|
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder) - GUI
|
||||||
|
builder for [GUIslice](https://github.com/ImpulseAdventure/GUIslice), a
|
||||||
|
lightweight GUI framework for embedded displays
|
||||||
|
- [ThunderFocus](https://github.com/marcocipriani01/ThunderFocus) -
|
||||||
|
Arduino-based telescope focuser
|
||||||
|
- [RemoteLight](https://github.com/Drumber/RemoteLight) - multifunctional LED
|
||||||
|
control software
|
||||||
|
|
||||||
|
### Media
|
||||||
|
|
||||||
|
-  [jAlbum](https://jalbum.net/) (**commercial**) -
|
||||||
|
creates photo album websites
|
||||||
|
- [MediathekView](https://mediathekview.de/) - search in media libraries of
|
||||||
|
various German broadcasters
|
||||||
|
-  [Pixelitor](https://github.com/lbalazscs/Pixelitor) -
|
||||||
|
image editor
|
||||||
|
- [Cinecred](https://loadingbyte.com/cinecred/) - create beautiful film credit
|
||||||
|
sequences
|
||||||
|
- [tinyMediaManager](https://www.tinymediamanager.org/) (**commercial**) - a
|
||||||
|
media management tool
|
||||||
|
- [Weasis](https://nroduit.github.io/) - medical DICOM viewer used in healthcare
|
||||||
|
by hospitals, health networks, etc
|
||||||
|
- [Shutter Encoder](https://www.shutterencoder.com/)
|
||||||
|
([source code](https://github.com/paulpacifico/shutter-encoder)) -
|
||||||
|
professional video converter and compression tool
|
||||||
|
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis) - analyze
|
||||||
|
sound files in time or frequency domain
|
||||||
|
- [Novel-Grabber](https://github.com/Flameish/Novel-Grabber) - download novels
|
||||||
|
from any webnovel and lightnovel site
|
||||||
|
- [lectureStudio](https://www.lecturestudio.org/) - digitize your lectures with
|
||||||
|
ease
|
||||||
|
-  [Nortantis](https://jandjheydorn.com/nortantis) -
|
||||||
|
fantasy map generator and editor
|
||||||
|
|
||||||
|
### Modelling / Planning
|
||||||
|
|
||||||
|
-  [OpenRocket](https://github.com/openrocket/openrocket) -
|
||||||
|
model-rocketry aerodynamics and trajectory simulation software
|
||||||
|
- 
|
||||||
|
[Warteschlangensimulator](https://github.com/A-Herzog/Warteschlangensimulator) -
|
||||||
|
discrete-event stochastic simulator
|
||||||
|
-  [Gephi](https://github.com/gephi/gephi) - the Open
|
||||||
|
Graph Viz Platform
|
||||||
|
- [Astah](https://astah.net/) (**commercial**) - create UML, ER Diagram,
|
||||||
|
Flowchart, Data Flow Diagram, Requirement Diagram, SysML diagrams and more
|
||||||
|
- [IGMAS+](https://www.gfz-potsdam.de/igmas) - Interactive Gravity and Magnetic
|
||||||
|
Application System
|
||||||
|
-  [StarPlan](https://www.progotec.de/) (**commercial**) -
|
||||||
|
die Stundenplan Software für Bildungseinrichtungen
|
||||||
|
-  [SSPlot](https://github.com/babaissarkar/ssplot) -
|
||||||
|
plotting utility for plotting CSV data
|
||||||
|
|
||||||
|
### Documents
|
||||||
|
|
||||||
|
- [Big Faceless (BFO) PDF Viewer](https://bfo.com/) (**commercial**) - Swing PDF
|
||||||
|
Viewer
|
||||||
|
- [PDF Studio](https://www.qoppa.com/pdfstudio/) (**commercial**) - create,
|
||||||
|
review and edit PDF documents
|
||||||
|
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) (**commercial**)
|
||||||
|
|
||||||
|
### Geo
|
||||||
|
|
||||||
|
-  [JOSM](https://josm.openstreetmap.de/) - an extensible
|
||||||
|
editor for [OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf
|
||||||
|
JOSM plugin)
|
||||||
|
- [Mapton](https://mapton.org/)
|
||||||
|
([source code](https://github.com/trixon/mapton)) - some kind of map
|
||||||
|
application (based on NetBeans platform)
|
||||||
|
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) - GIS and scientific
|
||||||
|
computation environment for meteorological community
|
||||||
|
|
||||||
|
### Business / Legal
|
||||||
|
|
||||||
|
-  
|
||||||
|
[Lisheane ERP](https://www.lisheane.ch/) (**commercial**) - backoffice
|
||||||
|
applikation
|
||||||
|
- 
|
||||||
|
[j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||||
|
-  [Jeyla Studio](https://www.jeylastudio.com/) -
|
||||||
|
Salon Software
|
||||||
|
- [Fanurio](https://www.fanuriotimetracking.com/) (**commercial**) - time
|
||||||
|
tracking and billing for freelancers and teams
|
||||||
|
- [Jes](https://www.jes-eur.de) - Die Java-EÜR
|
||||||
- [mendelson AS2](https://sourceforge.net/projects/mec-as2/),
|
- [mendelson AS2](https://sourceforge.net/projects/mec-as2/),
|
||||||
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
||||||
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
||||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||||
[AS4](https://mendelson-e-c.com/as4/) and
|
[AS4](https://mendelson-e-c.com/as4/) and
|
||||||
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
||||||
-  [IGMAS+](https://www.gfz-potsdam.de/igmas) -
|
|
||||||
Interactive Gravity and Magnetic Application System
|
### Messaging
|
||||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
|
||||||
computation environment for meteorological community
|
- [Spark](https://github.com/igniterealtime/Spark) - cross-platform IM client
|
||||||
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
optimized for businesses and organizations
|
||||||
systems development platform
|
- [Chatty](https://github.com/chatty/chatty) - Twitch Chat Client
|
||||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
|
||||||
encryption
|
### Gaming
|
||||||
- [Jes - Die Java-E<>R](https://www.jes-eur.de)
|
|
||||||
- [Mapton](https://mapton.org/) 2.0
|
-  [BGBlitz](https://www.bgblitz.com/)
|
||||||
([source code](https://github.com/trixon/mapton)) - some kind of map
|
(**commercial**) - professional Backgammon
|
||||||
application (based on NetBeans platform)
|
-  [josé](https://peteschaefer.github.io/jose/) - a
|
||||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
graphical chess tool
|
||||||
IDE for Pseudo-Assembler
|
-  [MCreator](https://github.com/MCreator/MCreator) - make
|
||||||
- [Linotte](https://github.com/cpc6128/LangageLinotte) 3.1 - French programming
|
Minecraft Java Edition mods, Minecraft Bedrock Edition Add-Ons, and data packs
|
||||||
language created to learn programming
|
- [MapTool](https://github.com/RPTools/maptool) - virtual Tabletop for playing
|
||||||
- [MEKA](https://github.com/Waikato/meka) 1.9.3 - multi-label classifiers and
|
role-playing games
|
||||||
evaluation procedures using the Weka machine learning framework
|
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||||
- [Shutter Encoder](https://www.shutterencoder.com/) 14.2
|
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||||
([source code](https://github.com/paulpacifico/shutter-encoder)) -
|
[MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech
|
||||||
professional video converter and compression tool (screenshots show **old**
|
simulator suite handling battles, unit building, and campaigns
|
||||||
look)
|
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
||||||
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis) - analyze
|
gamepad mapping software
|
||||||
sound files in time or frequency domain
|
|
||||||
- [RemoteLight](https://github.com/Drumber/RemoteLight) - multifunctional LED
|
### Utilities
|
||||||
control software
|
|
||||||
- [ThunderFocus](https://github.com/marcocipriani01/ThunderFocus) -
|
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
||||||
Arduino-based telescope focuser
|
OSHI, to view information about the system and hardware
|
||||||
- [Novel-Grabber](https://github.com/Flameish/Novel-Grabber) - download novels
|
- [Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) -
|
||||||
from any webnovel and lightnovel site
|
GUI for monitoring and managing various aspects of a Linux system
|
||||||
- [lectureStudio](https://www.lecturestudio.org/) 4.3.1060 - digitize your
|
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
||||||
lectures with ease
|
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
||||||
|
connections manager
|
||||||
|
- [jEnTunnel](https://github.com/ggrandes/jentunnel) - manage SSH Tunnels made
|
||||||
|
easy
|
||||||
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
|
- [Android Tool](https://github.com/fast-geek/Android-Tool) - makes popular adb
|
||||||
and fastboot commands easier to use
|
and fastboot commands easier to use
|
||||||
- and more...
|
-  [Termora](https://github.com/TermoraDev/termora) -
|
||||||
|
Terminal emulator and SSH client
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
|
||||||
|
- [MEKA](https://github.com/Waikato/meka) - multi-label classifiers and
|
||||||
|
evaluation procedures using the Weka machine learning framework
|
||||||
|
|||||||
@@ -14,10 +14,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val releaseVersion = "1.2"
|
import net.ltgt.gradle.errorprone.errorprone
|
||||||
val developmentVersion = "1.3-SNAPSHOT"
|
|
||||||
|
group = "com.formdev"
|
||||||
|
version = property( if( hasProperty( "release" ) ) "flatlaf.releaseVersion" else "flatlaf.developmentVersion" ) as String
|
||||||
|
|
||||||
|
// for PR snapshots change version to 'PR-<pr_number>-SNAPSHOT'
|
||||||
|
val pullRequestNumber = findProperty( "github.event.pull_request.number" )
|
||||||
|
if( pullRequestNumber != null )
|
||||||
|
version = "PR-${pullRequestNumber}-SNAPSHOT"
|
||||||
|
|
||||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
@@ -37,9 +43,17 @@ println( "----------------------------------------------------------------------
|
|||||||
println( "FlatLaf Version: ${version}" )
|
println( "FlatLaf Version: ${version}" )
|
||||||
println( "Gradle ${gradle.gradleVersion} at ${gradle.gradleHomeDir}" )
|
println( "Gradle ${gradle.gradleVersion} at ${gradle.gradleHomeDir}" )
|
||||||
println( "Java ${System.getProperty( "java.version" )}" )
|
println( "Java ${System.getProperty( "java.version" )}" )
|
||||||
|
val toolchainJavaVersion = System.getProperty( "toolchain" )
|
||||||
|
if( !toolchainJavaVersion.isNullOrEmpty() )
|
||||||
|
println( "Java toolchain ${toolchainJavaVersion}" )
|
||||||
println()
|
println()
|
||||||
|
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias( libs.plugins.gradle.nexus.publish.plugin )
|
||||||
|
alias( libs.plugins.errorprone ) apply false
|
||||||
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
tasks {
|
tasks {
|
||||||
withType<JavaCompile>().configureEach {
|
withType<JavaCompile>().configureEach {
|
||||||
@@ -78,4 +92,73 @@ allprojects {
|
|||||||
isFailOnError = false
|
isFailOnError = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---- Error Prone ----
|
||||||
|
|
||||||
|
tasks.register( "errorprone" ) {
|
||||||
|
group = "verification"
|
||||||
|
tasks.withType<JavaCompile>().forEach {
|
||||||
|
dependsOn( it )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val useErrorProne = gradle.startParameter.taskNames.contains( "errorprone" )
|
||||||
|
if( useErrorProne ) {
|
||||||
|
plugins.withType<JavaPlugin> {
|
||||||
|
apply( plugin = libs.plugins.errorprone.get().pluginId )
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
"errorprone"( libs.errorprone )
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<JavaCompile>().configureEach {
|
||||||
|
options.compilerArgs.add( "-Werror" )
|
||||||
|
options.errorprone {
|
||||||
|
disable(
|
||||||
|
"ReferenceEquality", // reports usage of '==' for objects
|
||||||
|
"StringSplitter", // reports String.split()
|
||||||
|
"JavaTimeDefaultTimeZone", // reports Year.now()
|
||||||
|
"MissingSummary", // reports `/** @since 2 */`
|
||||||
|
"InvalidBlockTag", // reports @uiDefault in javadoc
|
||||||
|
"AlreadyChecked", // reports false positives
|
||||||
|
"InlineMeSuggester", // suggests using Error Prone annotations for deprecated methods
|
||||||
|
"TypeParameterUnusedInFormals",
|
||||||
|
"UnsynchronizedOverridesSynchronized",
|
||||||
|
"NonApiType", // reports ArrayList/HashSet in parameter or return type
|
||||||
|
)
|
||||||
|
when( project.name ) {
|
||||||
|
"flatlaf-intellij-themes" -> disable(
|
||||||
|
"MutablePublicArray", // reports FlatAllIJThemes.INFOS
|
||||||
|
)
|
||||||
|
"flatlaf-theme-editor" -> disable(
|
||||||
|
"CatchAndPrintStackTrace",
|
||||||
|
)
|
||||||
|
"flatlaf-testing" -> disable(
|
||||||
|
"CatchAndPrintStackTrace",
|
||||||
|
"JdkObsolete", // reports Hashtable used for JSlider.setLabelTable()
|
||||||
|
"JavaUtilDate", // reports usage of class Date
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nexusPublishing {
|
||||||
|
repositories {
|
||||||
|
sonatype {
|
||||||
|
// see https://central.sonatype.org/publish/publish-portal-ossrh-staging-api/
|
||||||
|
nexusUrl = uri( "https://ossrh-staging-api.central.sonatype.com/service/local/" )
|
||||||
|
snapshotRepositoryUrl = uri( "https://central.sonatype.com/repository/maven-snapshots/" )
|
||||||
|
|
||||||
|
// get from gradle.properties
|
||||||
|
val sonatypeUsername: String? by project
|
||||||
|
val sonatypePassword: String? by project
|
||||||
|
|
||||||
|
username = System.getenv( "SONATYPE_USERNAME" ) ?: sonatypeUsername
|
||||||
|
password = System.getenv( "SONATYPE_PASSWORD" ) ?: sonatypePassword
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class ReorderJarEntries
|
|||||||
// 1st pass: copy .properties files
|
// 1st pass: copy .properties files
|
||||||
copyFiles( zipOutStream, jarFile, name -> name.endsWith( ".properties" ) );
|
copyFiles( zipOutStream, jarFile, name -> name.endsWith( ".properties" ) );
|
||||||
|
|
||||||
// 2st pass: copy other files
|
// 2nd pass: copy other files
|
||||||
copyFiles( zipOutStream, jarFile, name -> !name.endsWith( ".properties" ) );
|
copyFiles( zipOutStream, jarFile, name -> !name.endsWith( ".properties" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
46
buildSrc/src/main/kotlin/flatlaf-cpp-library.gradle.kts
Normal file
46
buildSrc/src/main/kotlin/flatlaf-cpp-library.gradle.kts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
`cpp-library`
|
||||||
|
}
|
||||||
|
|
||||||
|
library {
|
||||||
|
// disable debuggable for release builds to make shared libraries smaller
|
||||||
|
binaries.configureEach( CppSharedLibrary::class ) {
|
||||||
|
with( compileTask.get() ) {
|
||||||
|
if( name.contains( "Release" ) )
|
||||||
|
isDebuggable = false
|
||||||
|
}
|
||||||
|
with( linkTask.get() ) {
|
||||||
|
if( name.contains( "Release" ) )
|
||||||
|
debuggable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
withType<CppCompile>().configureEach {
|
||||||
|
doFirst {
|
||||||
|
println( "Used Tool Chain:" )
|
||||||
|
println( " - ${toolChain.get()}" )
|
||||||
|
println( "Available Tool Chains:" )
|
||||||
|
toolChains.forEach {
|
||||||
|
println( " - $it" )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
add( "java9Compile", sourceSets.main.get().output )
|
add( "java9Implementation", sourceSets.main.get().output )
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|||||||
36
buildSrc/src/main/kotlin/flatlaf-jni-headers.gradle.kts
Normal file
36
buildSrc/src/main/kotlin/flatlaf-jni-headers.gradle.kts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
open class JniHeadersExtension {
|
||||||
|
var headers: List<String> = emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
val extension = project.extensions.create<JniHeadersExtension>( "flatlafJniHeaders" )
|
||||||
|
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
register<Copy>( "jni-headers" ) {
|
||||||
|
// depend on :flatlaf-core:compileJava because it generates the JNI headers
|
||||||
|
dependsOn( ":flatlaf-core:compileJava" )
|
||||||
|
|
||||||
|
from( project( ":flatlaf-core" ).layout.buildDirectory.dir( "generated/jni-headers" ) )
|
||||||
|
into( "src/main/headers" )
|
||||||
|
include( extension.headers )
|
||||||
|
filter<org.apache.tools.ant.filters.FixCrLfFilter>(
|
||||||
|
"eol" to org.apache.tools.ant.filters.FixCrLfFilter.CrLf.newInstance( "lf" )
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,12 +61,8 @@ if( JavaVersion.current() >= JavaVersion.VERSION_1_9 ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest.attributes( "Multi-Release" to "true" )
|
from( sourceSets["module-info"].output ) {
|
||||||
|
include( "module-info.class" )
|
||||||
into( "META-INF/versions/9" ) {
|
|
||||||
from( sourceSets["module-info"].output ) {
|
|
||||||
include( "module-info.class" )
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
open class NativeArtifact( val fileName: String, val classifier: String, val type: String ) {}
|
||||||
|
|
||||||
open class PublishExtension {
|
open class PublishExtension {
|
||||||
var artifactId: String? = null
|
var artifactId: String? = null
|
||||||
var name: String? = null
|
var name: String? = null
|
||||||
var description: String? = null
|
var description: String? = null
|
||||||
|
var nativeArtifacts: List<NativeArtifact>? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
||||||
@@ -41,57 +44,68 @@ publishing {
|
|||||||
|
|
||||||
pom {
|
pom {
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
this@pom.name.set( extension.name )
|
this@pom.name = extension.name
|
||||||
this@pom.description.set( extension.description )
|
this@pom.description = extension.description
|
||||||
}
|
}
|
||||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
url = "https://github.com/JFormDesigner/FlatLaf"
|
||||||
|
|
||||||
licenses {
|
licenses {
|
||||||
license {
|
license {
|
||||||
name.set( "The Apache License, Version 2.0" )
|
name = "The Apache License, Version 2.0"
|
||||||
url.set( "https://www.apache.org/licenses/LICENSE-2.0.txt" )
|
url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
developers {
|
developers {
|
||||||
developer {
|
developer {
|
||||||
name.set( "Karl Tauber" )
|
name = "Karl Tauber"
|
||||||
organization.set( "FormDev Software GmbH" )
|
organization = "FormDev Software GmbH"
|
||||||
organizationUrl.set( "https://www.formdev.com/" )
|
organizationUrl = "https://www.formdev.com/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scm {
|
scm {
|
||||||
connection.set( "scm:git:git://github.com/JFormDesigner/FlatLaf.git" )
|
connection = "scm:git:git://github.com/JFormDesigner/FlatLaf.git"
|
||||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
url = "https://github.com/JFormDesigner/FlatLaf"
|
||||||
}
|
}
|
||||||
|
|
||||||
issueManagement {
|
issueManagement {
|
||||||
system.set( "GitHub" )
|
system = "GitHub"
|
||||||
url.set( "https://github.com/JFormDesigner/FlatLaf/issues" )
|
url = "https://github.com/JFormDesigner/FlatLaf/issues"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
extension.nativeArtifacts?.forEach {
|
||||||
|
artifact( artifacts.add( "archives", file( it.fileName ) ) {
|
||||||
|
classifier = it.classifier
|
||||||
|
type = it.type
|
||||||
|
} )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
name = "OSSRH"
|
name = "MavenCentral"
|
||||||
|
|
||||||
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
val releasesRepoUrl = "https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"
|
||||||
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
val snapshotsRepoUrl = "https://central.sonatype.com/repository/maven-snapshots/"
|
||||||
url = uri( if( java.lang.Boolean.getBoolean( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||||
|
|
||||||
credentials {
|
credentials {
|
||||||
// get from gradle.properties
|
// get from gradle.properties
|
||||||
val ossrhUsername: String? by project
|
val sonatypeUsername: String? by project
|
||||||
val ossrhPassword: String? by project
|
val sonatypePassword: String? by project
|
||||||
|
|
||||||
username = System.getenv( "OSSRH_USERNAME" ) ?: ossrhUsername
|
username = System.getenv( "SONATYPE_USERNAME" ) ?: sonatypeUsername
|
||||||
password = System.getenv( "OSSRH_PASSWORD" ) ?: ossrhPassword
|
password = System.getenv( "SONATYPE_PASSWORD" ) ?: sonatypePassword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
signing {
|
signing {
|
||||||
@@ -108,5 +122,13 @@ signing {
|
|||||||
|
|
||||||
// disable signing of snapshots
|
// disable signing of snapshots
|
||||||
tasks.withType<Sign>().configureEach {
|
tasks.withType<Sign>().configureEach {
|
||||||
onlyIf { java.lang.Boolean.getBoolean( "release" ) }
|
onlyIf { rootProject.hasProperty( "release" ) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether parallel build is enabled
|
||||||
|
tasks.withType<AbstractPublishToMaven>().configureEach {
|
||||||
|
doFirst {
|
||||||
|
if( System.getProperty( "org.gradle.parallel" ) == "true" )
|
||||||
|
throw RuntimeException( "Publishing does not work correctly with enabled parallel build. Disable parallel build with VM option '-Dorg.gradle.parallel=false'." )
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
buildSrc/src/main/kotlin/flatlaf-toolchain.gradle.kts
Normal file
26
buildSrc/src/main/kotlin/flatlaf-toolchain.gradle.kts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
java
|
||||||
|
}
|
||||||
|
|
||||||
|
val toolchainJavaVersion = System.getProperty( "toolchain" )
|
||||||
|
if( !toolchainJavaVersion.isNullOrEmpty() ) {
|
||||||
|
java.toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of( toolchainJavaVersion )
|
||||||
|
}
|
||||||
|
}
|
||||||
2
flatlaf-core/.settings/org.eclipse.core.resources.prefs
Normal file
2
flatlaf-core/.settings/org.eclipse.core.resources.prefs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding/<project>=ISO-8859-1
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
|
||||||
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
|
||||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||||
|
|||||||
@@ -14,13 +14,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import Flatlaf_publish_gradle.NativeArtifact
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
|
`flatlaf-toolchain`
|
||||||
`flatlaf-module-info`
|
`flatlaf-module-info`
|
||||||
`flatlaf-java9`
|
`flatlaf-java9`
|
||||||
`flatlaf-publish`
|
`flatlaf-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sigtest = configurations.create( "sigtest" )
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation( libs.junit )
|
||||||
|
testRuntimeOnly( libs.junit.launcher )
|
||||||
|
|
||||||
|
// https://github.com/jtulach/netbeans-apitest
|
||||||
|
sigtest( libs.sigtest )
|
||||||
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
@@ -29,16 +42,11 @@ java {
|
|||||||
tasks {
|
tasks {
|
||||||
compileJava {
|
compileJava {
|
||||||
// generate JNI headers
|
// generate JNI headers
|
||||||
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
options.headerOutputDirectory = layout.buildDirectory.dir( "generated/jni-headers" )
|
||||||
}
|
|
||||||
|
|
||||||
processResources {
|
|
||||||
// build native libraries
|
|
||||||
dependsOn( ":flatlaf-natives-windows:assemble" )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
archiveBaseName.set( "flatlaf" )
|
archiveBaseName = "flatlaf"
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
ReorderJarEntries.reorderJarEntries( outputs.files.singleFile );
|
ReorderJarEntries.reorderJarEntries( outputs.files.singleFile );
|
||||||
@@ -46,11 +54,90 @@ tasks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
named<Jar>( "sourcesJar" ) {
|
named<Jar>( "sourcesJar" ) {
|
||||||
archiveBaseName.set( "flatlaf" )
|
archiveBaseName = "flatlaf"
|
||||||
}
|
}
|
||||||
|
|
||||||
named<Jar>( "javadocJar" ) {
|
named<Jar>( "javadocJar" ) {
|
||||||
archiveBaseName.set( "flatlaf" )
|
archiveBaseName = "flatlaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
register<Zip>( "jarNoNatives" ) {
|
||||||
|
group = "build"
|
||||||
|
dependsOn( "jar" )
|
||||||
|
|
||||||
|
archiveBaseName = "flatlaf"
|
||||||
|
archiveClassifier = "no-natives"
|
||||||
|
archiveExtension = "jar"
|
||||||
|
destinationDirectory = layout.buildDirectory.dir( "libs" )
|
||||||
|
|
||||||
|
from( zipTree( jar.get().archiveFile.get().asFile ) )
|
||||||
|
exclude( "com/formdev/flatlaf/natives/**" )
|
||||||
|
}
|
||||||
|
|
||||||
|
withType<AbstractPublishToMaven>().configureEach {
|
||||||
|
dependsOn( "jarNoNatives" )
|
||||||
|
}
|
||||||
|
|
||||||
|
withType<Sign>().configureEach {
|
||||||
|
dependsOn( "jarNoNatives" )
|
||||||
|
}
|
||||||
|
|
||||||
|
check {
|
||||||
|
dependsOn( "sigtestCheck" )
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||||
|
|
||||||
|
if( JavaVersion.current() >= JavaVersion.VERSION_1_9 )
|
||||||
|
jvmArgs( listOf( "--add-opens", "java.desktop/javax.swing.plaf.basic=ALL-UNNAMED" ) )
|
||||||
|
}
|
||||||
|
|
||||||
|
register( "sigtestGenerate" ) {
|
||||||
|
group = "verification"
|
||||||
|
dependsOn( "jar" )
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
ant.withGroovyBuilder {
|
||||||
|
"taskdef"(
|
||||||
|
"name" to "sigtest",
|
||||||
|
"classname" to "org.netbeans.apitest.Sigtest",
|
||||||
|
"classpath" to sigtest.asPath )
|
||||||
|
|
||||||
|
"sigtest"(
|
||||||
|
"action" to "generate",
|
||||||
|
"fileName" to "${project.name}-sigtest.txt",
|
||||||
|
"classpath" to jar.get().outputs.files.asPath,
|
||||||
|
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.themes,com.formdev.flatlaf.util",
|
||||||
|
"version" to version,
|
||||||
|
"release" to "1.8", // Java version
|
||||||
|
"failonerror" to "true" )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register( "sigtestCheck" ) {
|
||||||
|
group = "verification"
|
||||||
|
dependsOn( "jar" )
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
ant.withGroovyBuilder {
|
||||||
|
"taskdef"(
|
||||||
|
"name" to "sigtest",
|
||||||
|
"classname" to "org.netbeans.apitest.Sigtest",
|
||||||
|
"classpath" to sigtest.asPath )
|
||||||
|
|
||||||
|
"sigtest"(
|
||||||
|
"action" to "check",
|
||||||
|
"fileName" to "${project.name}-sigtest.txt",
|
||||||
|
"classpath" to jar.get().outputs.files.asPath,
|
||||||
|
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.util",
|
||||||
|
"version" to version,
|
||||||
|
"release" to "1.8", // Java version
|
||||||
|
"failonerror" to "true" )
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,4 +145,17 @@ flatlafPublish {
|
|||||||
artifactId = "flatlaf"
|
artifactId = "flatlaf"
|
||||||
name = "FlatLaf"
|
name = "FlatLaf"
|
||||||
description = "Flat Look and Feel"
|
description = "Flat Look and Feel"
|
||||||
|
|
||||||
|
val natives = "src/main/resources/com/formdev/flatlaf/natives"
|
||||||
|
nativeArtifacts = listOf(
|
||||||
|
NativeArtifact( tasks.getByName( "jarNoNatives" ).outputs.files.asPath, "no-natives", "jar" ),
|
||||||
|
|
||||||
|
NativeArtifact( "${natives}/flatlaf-windows-x86.dll", "windows-x86", "dll" ),
|
||||||
|
NativeArtifact( "${natives}/flatlaf-windows-x86_64.dll", "windows-x86_64", "dll" ),
|
||||||
|
NativeArtifact( "${natives}/flatlaf-windows-arm64.dll", "windows-arm64", "dll" ),
|
||||||
|
NativeArtifact( "${natives}/libflatlaf-macos-arm64.dylib", "macos-arm64", "dylib" ),
|
||||||
|
NativeArtifact( "${natives}/libflatlaf-macos-x86_64.dylib", "macos-x86_64", "dylib" ),
|
||||||
|
NativeArtifact( "${natives}/libflatlaf-linux-x86_64.so", "linux-x86_64", "so" ),
|
||||||
|
NativeArtifact( "${natives}/libflatlaf-linux-arm64.so", "linux-arm64", "so" ),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
1264
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
1264
flatlaf-core/flatlaf-core-sigtest.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,12 @@
|
|||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.IllegalComponentStateException;
|
||||||
|
import java.awt.Window;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JFormattedTextField;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,7 +35,7 @@ public interface FlatClientProperties
|
|||||||
//---- JButton ------------------------------------------------------------
|
//---- JButton ------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies type of a button.
|
* Specifies type of button.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
@@ -100,6 +104,17 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String BUTTON_TYPE_BORDERLESS = "borderless";
|
String BUTTON_TYPE_BORDERLESS = "borderless";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the button preferred size will be made square (quadratically).
|
||||||
|
* <p>
|
||||||
|
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*/
|
||||||
|
String SQUARE_SIZE = "JButton.squareSize";
|
||||||
|
|
||||||
|
|
||||||
|
//---- JCheckBox ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies selected state of a checkbox.
|
* Specifies selected state of a checkbox.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -116,16 +131,60 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SELECTED_STATE_INDETERMINATE = "indeterminate";
|
String SELECTED_STATE_INDETERMINATE = "indeterminate";
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies whether the button preferred size will be made square (quadratically).
|
|
||||||
* <p>
|
|
||||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
|
||||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
|
||||||
*/
|
|
||||||
String SQUARE_SIZE = "JButton.squareSize";
|
|
||||||
|
|
||||||
//---- JComponent ---------------------------------------------------------
|
//---- JComponent ---------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the style of a component as String in CSS syntax ("key1: value1; key2: value2; ...")
|
||||||
|
* or as {@link java.util.Map}<String, Object> with binary values.
|
||||||
|
* <p>
|
||||||
|
* The keys are the same as used in UI defaults, but without component type prefix.
|
||||||
|
* E.g. for UI default {@code Slider.thumbSize} use key {@code thumbSize}.
|
||||||
|
* <p>
|
||||||
|
* The syntax of the CSS values is the same as used in FlatLaf properties files
|
||||||
|
* (<a href="https://www.formdev.com/flatlaf/properties-files/">https://www.formdev.com/flatlaf/properties-files/</a>),
|
||||||
|
* but some features are not supported (e.g. variables).
|
||||||
|
* When using a map, the values are not parsed from a string. They must be binary.
|
||||||
|
* <p>
|
||||||
|
* <strong>Components</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String} or {@link java.util.Map}<String, Object><br>
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String STYLE = "FlatLaf.style";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the style class(es) of a component as String (single class or multiple classes separated by space characters)
|
||||||
|
* or as {@code String[]} or {@link java.util.List}<String> (multiple classes).
|
||||||
|
* <p>
|
||||||
|
* The style rules must be defined in UI defaults either as strings (in CSS syntax)
|
||||||
|
* or as {@link java.util.Map}<String, Object> (with binary values).
|
||||||
|
* The key must be in syntax: {@code [style]type.styleClass}, where the type is optional.
|
||||||
|
* E.g. in FlatLaf properties file:
|
||||||
|
* <pre>{@code
|
||||||
|
* [style]Button.primary = borderColor: #08f; background: #08f; foreground: #fff
|
||||||
|
* [style].secondary = borderColor: #0f8; background: #0f8
|
||||||
|
* }</pre>
|
||||||
|
* or in Java code:
|
||||||
|
* <pre>{@code
|
||||||
|
* UIManager.put( "[style]Button.primary", "borderColor: #08f; background: #08f; foreground: #fff" );
|
||||||
|
* UIManager.put( "[style].secondary", "borderColor: #0f8; background: #0f8" );
|
||||||
|
* }</pre>
|
||||||
|
* The rule "Button.primary" can be applied to buttons only.
|
||||||
|
* The rule ".secondary" can be applied to any component.
|
||||||
|
* <p>
|
||||||
|
* To have similar behavior as in CSS, first the rule without type is applied,
|
||||||
|
* then the rule with type.
|
||||||
|
* E.g. setting style class to "foo" on a {@code JButton} uses rules
|
||||||
|
* from UI default keys "[style].foo" and "[style]Button.foo".
|
||||||
|
* <p>
|
||||||
|
* <strong>Components</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}, {@code String[]} or {@link java.util.List}<String><br>
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String STYLE_CLASS = "FlatLaf.styleClass";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies minimum width of a component.
|
* Specifies minimum width of a component.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -163,6 +222,7 @@ public interface FlatClientProperties
|
|||||||
* <strong>Allowed Values</strong>
|
* <strong>Allowed Values</strong>
|
||||||
* {@link #OUTLINE_ERROR},
|
* {@link #OUTLINE_ERROR},
|
||||||
* {@link #OUTLINE_WARNING},
|
* {@link #OUTLINE_WARNING},
|
||||||
|
* {@link #OUTLINE_SUCCESS},
|
||||||
* any color (type {@link java.awt.Color}) or
|
* any color (type {@link java.awt.Color}) or
|
||||||
* an array of two colors (type {@link java.awt.Color}[2]) where the first color
|
* an array of two colors (type {@link java.awt.Color}[2]) where the first color
|
||||||
* is for focused state and the second for unfocused state
|
* is for focused state and the second for unfocused state
|
||||||
@@ -183,6 +243,14 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String OUTLINE_WARNING = "warning";
|
String OUTLINE_WARNING = "warning";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paint the component border in another color (usually greenish) to indicate a success.
|
||||||
|
*
|
||||||
|
* @see #OUTLINE
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
String OUTLINE_SUCCESS = "success";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a callback that is invoked to check whether a component is permanent focus owner.
|
* Specifies a callback that is invoked to check whether a component is permanent focus owner.
|
||||||
* Used to paint focus indicators.
|
* Used to paint focus indicators.
|
||||||
@@ -202,8 +270,157 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";
|
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether a component shown in a window title bar area should behave as caption
|
||||||
|
* (left-click allows moving window, right-click shows window system menu).
|
||||||
|
* The caption component does not receive mouse pressed/released/clicked/dragged events,
|
||||||
|
* but it gets mouse entered/exited/moved events.
|
||||||
|
* <p>
|
||||||
|
* Since 3.4, this client property also supports using a function that can check
|
||||||
|
* whether a given location in the component should behave as caption.
|
||||||
|
* Useful for components that do not use mouse input on whole component bounds.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* myComponent.putClientProperty( "JComponent.titleBarCaption",
|
||||||
|
* (Function<Point, Boolean>) pt -> {
|
||||||
|
* // parameter pt contains mouse location (in myComponent coordinates)
|
||||||
|
* // return true if the component is not interested in mouse input at the given location
|
||||||
|
* // return false if the component wants process mouse input at the given location
|
||||||
|
* // return null if the component children should be checked
|
||||||
|
* return ...; // check here
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* <b>Warning</b>:
|
||||||
|
* <ul>
|
||||||
|
* <li>This function is invoked often when mouse is moved over window title bar area
|
||||||
|
* and should therefore return quickly.
|
||||||
|
* <li>This function is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread)
|
||||||
|
* while processing Windows messages.
|
||||||
|
* It <b>must not</b> change any component property or layout because this could cause a dead lock.
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean} or {@link java.util.function.Function}<Point, Boolean>
|
||||||
|
*
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";
|
||||||
|
|
||||||
|
|
||||||
|
//---- Panel --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the panel as placeholder for the iconfify/maximize/close buttons
|
||||||
|
* in fullWindowContent mode. See {@link #FULL_WINDOW_CONTENT}.
|
||||||
|
* <p>
|
||||||
|
* If fullWindowContent mode is enabled, the preferred size of the panel is equal
|
||||||
|
* to the size of the iconfify/maximize/close buttons. Otherwise is is {@code 0,0}.
|
||||||
|
* <p>
|
||||||
|
* You're responsible to layout that panel at the top-left or top-right corner,
|
||||||
|
* depending on platform, where the iconfify/maximize/close buttons are located.
|
||||||
|
* <p>
|
||||||
|
* Syntax of the value string is: {@code "win|mac [horizontal|vertical] [zeroInFullScreen] [leftToRight|rightToLeft]"}.
|
||||||
|
* <p>
|
||||||
|
* The string must start with {@code "win"} (for Windows or Linux) or
|
||||||
|
* with {@code "mac"} (for macOS) and specifies the platform where the placeholder
|
||||||
|
* should be used. On macOS, you need the placeholder in the top-left corner,
|
||||||
|
* but on Windows/Linux you need it in the top-right corner. So if your application supports
|
||||||
|
* fullWindowContent mode on both platforms, you can add two placeholders to your layout
|
||||||
|
* and FlatLaf automatically uses only one of them. The other gets size {@code 0,0}.
|
||||||
|
* <p>
|
||||||
|
* Optionally, you can append following options to the value string (separated by space characters):
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code "horizontal"} - preferred height is zero
|
||||||
|
* <li>{@code "vertical"} - preferred width is zero
|
||||||
|
* <li>{@code "zeroInFullScreen"} - in full-screen mode on macOS, preferred size is {@code 0,0}
|
||||||
|
* <li>{@code "leftToRight"} - in right-to-left component orientation, preferred size is {@code 0,0}
|
||||||
|
* <li>{@code "rightToLeft"} - in left-to-right component orientation, preferred size is {@code 0,0}
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* Example for adding placeholder to top-left corner on macOS:
|
||||||
|
* <pre>{@code
|
||||||
|
* JPanel placeholder = new JPanel();
|
||||||
|
* placeholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac" );
|
||||||
|
*
|
||||||
|
* JToolBar toolBar = new JToolBar();
|
||||||
|
* // add tool bar items
|
||||||
|
*
|
||||||
|
* JPanel toolBarPanel = new JPanel( new BorderLayout() );
|
||||||
|
* toolBarPanel.add( placeholder, BorderLayout.WEST );
|
||||||
|
* toolBarPanel.add( toolBar, BorderLayout.CENTER );
|
||||||
|
*
|
||||||
|
* frame.getContentPane().add( toolBarPanel, BorderLayout.NORTH );
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* Or add placeholder as first item to the tool bar:
|
||||||
|
* <pre>{@code
|
||||||
|
* JPanel placeholder = new JPanel();
|
||||||
|
* placeholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac" );
|
||||||
|
*
|
||||||
|
* JToolBar toolBar = new JToolBar();
|
||||||
|
* toolBar.add( placeholder );
|
||||||
|
* // add tool bar items
|
||||||
|
*
|
||||||
|
* frame.getContentPane().add( toolBar, BorderLayout.NORTH );
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* If a tabbed pane is located at the top, you can add the placeholder
|
||||||
|
* as leading component to that tabbed pane:
|
||||||
|
* <pre>{@code
|
||||||
|
* JPanel placeholder = new JPanel();
|
||||||
|
* placeholder.putClientProperty( FlatClientProperties.FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER, "mac" );
|
||||||
|
*
|
||||||
|
* tabbedPane.putClientProperty( FlatClientProperties.TABBED_PANE_LEADING_COMPONENT, placeholder );
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JPanel}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}
|
||||||
|
*
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
String FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER = "FlatLaf.fullWindowContent.buttonsPlaceholder";
|
||||||
|
|
||||||
|
|
||||||
//---- Popup --------------------------------------------------------------
|
//---- Popup --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the popup border corner radius if the component is shown in a popup
|
||||||
|
* or if the component is the owner of another component that is shown in a popup.
|
||||||
|
* <p>
|
||||||
|
* Note that this is not available on all platforms since it requires special support.
|
||||||
|
* Supported platforms:
|
||||||
|
* <ul>
|
||||||
|
* <li><strong>Windows 11</strong>: Only two corner radiuses are supported
|
||||||
|
* by the OS: {@code DWMWCP_ROUND} is 8px and {@code DWMWCP_ROUNDSMALL} is 4px.
|
||||||
|
* If this value is {@code 1 - 4}, then {@code DWMWCP_ROUNDSMALL} is used.
|
||||||
|
* If it is {@code >= 5}, then {@code DWMWCP_ROUND} is used.
|
||||||
|
* <li><strong>macOS</strong> (10.14 and later): Any corner radius is supported.
|
||||||
|
* </ul>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Integer}<br>
|
||||||
|
*
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the popup rounded border width if the component is shown in a popup
|
||||||
|
* or if the component is the owner of another component that is shown in a popup.
|
||||||
|
* <p>
|
||||||
|
* Only used if popup uses rounded border.
|
||||||
|
* <p>
|
||||||
|
* Note that this is not available on all platforms since it requires special support.
|
||||||
|
* Supported platforms:
|
||||||
|
* <ul>
|
||||||
|
* <li><strong>macOS</strong> (10.14 and later)
|
||||||
|
* </ul>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.Float}<br>
|
||||||
|
*
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String POPUP_ROUNDED_BORDER_WIDTH = "Popup.roundedBorderWidth";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
||||||
* or if the component is the owner of another component that is shown in a popup.
|
* or if the component is the owner of another component that is shown in a popup.
|
||||||
@@ -222,6 +439,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight";
|
String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight";
|
||||||
|
|
||||||
|
|
||||||
//---- JProgressBar -------------------------------------------------------
|
//---- JProgressBar -------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,6 +458,7 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
||||||
|
|
||||||
|
|
||||||
//---- JRootPane ----------------------------------------------------------
|
//---- JRootPane ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -253,7 +472,7 @@ public interface FlatClientProperties
|
|||||||
* {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority
|
* {@link FlatSystemProperties#USE_WINDOW_DECORATIONS}, but higher priority
|
||||||
* than UI default {@code TitlePane.useWindowDecorations}.
|
* than UI default {@code TitlePane.useWindowDecorations}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Windows 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
@@ -273,17 +492,141 @@ public interface FlatClientProperties
|
|||||||
* {@link FlatSystemProperties#MENUBAR_EMBEDDED}, but higher priority
|
* {@link FlatSystemProperties#MENUBAR_EMBEDDED}, but higher priority
|
||||||
* than UI default {@code TitlePane.menuBarEmbedded}.
|
* than UI default {@code TitlePane.menuBarEmbedded}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Windows 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
*/
|
*/
|
||||||
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the content pane (and the glass pane) should be extended
|
||||||
|
* into the window title bar area
|
||||||
|
* (requires enabled window decorations). Default is {@code false}.
|
||||||
|
* <p>
|
||||||
|
* On macOS, use client property {@code apple.awt.fullWindowContent}
|
||||||
|
* (see <a href="https://www.formdev.com/flatlaf/macos/#full_window_content">macOS Full window content</a>).
|
||||||
|
* <p>
|
||||||
|
* Setting this enables/disables full window content
|
||||||
|
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* If {@code true}, the content pane (and the glass pane) is extended into
|
||||||
|
* the title bar area. The window icon and title are hidden.
|
||||||
|
* Only the iconfify/maximize/close buttons stay visible in the upper right corner
|
||||||
|
* (and overlap the content pane).
|
||||||
|
* <p>
|
||||||
|
* The user can left-click-and-drag on the title bar area to move the window,
|
||||||
|
* except when clicking on a component that processes mouse events (e.g. buttons or menus).
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
String FULL_WINDOW_CONTENT = "FlatLaf.fullWindowContent";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the current bounds of the iconfify/maximize/close buttons
|
||||||
|
* (in root pane coordinates) if fullWindowContent mode is enabled.
|
||||||
|
* Otherwise its value is {@code null}.
|
||||||
|
* <p>
|
||||||
|
* <b>Note</b>: Do not set this client property. It is set by FlatLaf.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.awt.Rectangle}
|
||||||
|
*
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
String FULL_WINDOW_CONTENT_BUTTONS_BOUNDS = "FlatLaf.fullWindowContent.buttonsBounds";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the window icon should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is UI property {@code TitlePane.showIcon}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the windows icon
|
||||||
|
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* This client property has higher priority than UI default {@code TitlePane.showIcon}.
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the window title should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the windows title
|
||||||
|
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the "iconify" button should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the "iconify" button
|
||||||
|
* for the {@code JFrame} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_ICONIFFY = "JRootPane.titleBarShowIconify";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the "maximize/restore" button should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the "maximize/restore" button
|
||||||
|
* for the {@code JFrame} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the "close" button should be shown in the window title bar
|
||||||
|
* (requires enabled window decorations). Default is {@code true}.
|
||||||
|
* <p>
|
||||||
|
* Setting this shows/hides the "close" button
|
||||||
|
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_SHOW_CLOSE = "JRootPane.titleBarShowClose";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Background color of window title bar (requires enabled window decorations).
|
* Background color of window title bar (requires enabled window decorations).
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Windows 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
* <strong>Value type</strong> {@link java.awt.Color}
|
* <strong>Value type</strong> {@link java.awt.Color}
|
||||||
@@ -295,7 +638,7 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Foreground color of window title bar (requires enabled window decorations).
|
* Foreground color of window title bar (requires enabled window decorations).
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Windows 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
* <strong>Value type</strong> {@link java.awt.Color}
|
* <strong>Value type</strong> {@link java.awt.Color}
|
||||||
@@ -304,6 +647,62 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
|
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the preferred height of title bar (requires enabled window decorations).
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||||
|
*
|
||||||
|
* @since 3.5.2
|
||||||
|
*/
|
||||||
|
String TITLE_BAR_HEIGHT = "JRootPane.titleBarHeight";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether the glass pane should have full height and overlap the title bar,
|
||||||
|
* if FlatLaf window decorations are enabled. Default is {@code false}.
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 10/11)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the style of the window title bar.
|
||||||
|
* Besides the default title bar style, you can use a Utility-style title bar,
|
||||||
|
* which is smaller than the default title bar.
|
||||||
|
* <p>
|
||||||
|
* On Windows 10/11, this requires FlatLaf window decorations.
|
||||||
|
* On macOS, Java supports this out of the box.
|
||||||
|
* <p>
|
||||||
|
* Note that this client property must be set before the window becomes displayable.
|
||||||
|
* Otherwise, an {@link IllegalComponentStateException} is thrown.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #WINDOW_STYLE_SMALL}
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
String WINDOW_STYLE = "Window.style";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The window has Utility-style title bar, which is smaller than default title bar.
|
||||||
|
* <p>
|
||||||
|
* This is the same as using {@link Window#setType}( {@link Window.Type#UTILITY} ).
|
||||||
|
*
|
||||||
|
* @see #WINDOW_STYLE
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
String WINDOW_STYLE_SMALL = "small";
|
||||||
|
|
||||||
|
|
||||||
//---- JScrollBar / JScrollPane -------------------------------------------
|
//---- JScrollBar / JScrollPane -------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -322,8 +721,73 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
||||||
|
|
||||||
|
|
||||||
|
//---- JSplitPane ---------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies what side of the spilt pane is allowed to expand
|
||||||
|
* via one-touch expanding arrow buttons.
|
||||||
|
* Requires that one-touch expanding is enabled with
|
||||||
|
* {@link javax.swing.JSplitPane#setOneTouchExpandable(boolean)}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JSplitPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_LEFT} or
|
||||||
|
* {@link #SPLIT_PANE_EXPANDABLE_SIDE_RIGHT}
|
||||||
|
*
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow expanding only left/top side of the split pane.
|
||||||
|
*
|
||||||
|
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow expanding only right/bottom side of the split pane.
|
||||||
|
*
|
||||||
|
* @see #SPLIT_PANE_EXPANDABLE_SIDE
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right";
|
||||||
|
|
||||||
|
|
||||||
//---- JTabbedPane --------------------------------------------------------
|
//---- JTabbedPane --------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies type of the selected tab.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #TABBED_PANE_TAB_TYPE_UNDERLINED} or
|
||||||
|
* {@link #TABBED_PANE_TAB_TYPE_CARD}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paint the selected tab underlined.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_TYPE
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paint the selected tab as card.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_TYPE
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_TYPE_CARD = "card";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether separators are shown between tabs.
|
* Specifies whether separators are shown between tabs.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -558,7 +1022,7 @@ public interface FlatClientProperties
|
|||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.String}<br>
|
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.String}<br>
|
||||||
* <strong>Allowed Values</strong>
|
* <strong>Allowed Values</strong>
|
||||||
* {@link SwingConstants#LEADING} (default)
|
* {@link SwingConstants#LEADING} (default),
|
||||||
* {@link SwingConstants#TRAILING},
|
* {@link SwingConstants#TRAILING},
|
||||||
* {@link SwingConstants#CENTER},
|
* {@link SwingConstants#CENTER},
|
||||||
* {@link #TABBED_PANE_ALIGN_LEADING} (default),
|
* {@link #TABBED_PANE_ALIGN_LEADING} (default),
|
||||||
@@ -662,12 +1126,65 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement";
|
String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the rotation of the tabs (title, icon, etc.).
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Integer} or {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link SwingConstants#LEFT},
|
||||||
|
* {@link SwingConstants#RIGHT},
|
||||||
|
* {@link #TABBED_PANE_TAB_ROTATION_NONE} (default),
|
||||||
|
* {@link #TABBED_PANE_TAB_ROTATION_AUTO},
|
||||||
|
* {@link #TABBED_PANE_TAB_ROTATION_LEFT} or
|
||||||
|
* {@link #TABBED_PANE_TAB_ROTATION_RIGHT}
|
||||||
|
*
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_ROTATION = "JTabbedPane.tabRotation";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tabs are not rotated.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_ROTATION
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_ROTATION_NONE = "none";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tabs are rotated depending on tab placement.
|
||||||
|
* <p>
|
||||||
|
* For top and bottom tab placement, the tabs are not rotated.<br>
|
||||||
|
* For left tab placement, the tabs are rotated counter-clockwise.<br>
|
||||||
|
* For right tab placement, the tabs are rotated clockwise.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_ROTATION
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_ROTATION_AUTO = "auto";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tabs are rotated counter-clockwise.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_ROTATION
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_ROTATION_LEFT = "left";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tabs are rotated clockwise.
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_ROTATION
|
||||||
|
* @since 3.3
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_ROTATION_RIGHT = "right";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the leading edge of the tabs area.
|
* Specifies a component that will be placed at the leading edge of the tabs area.
|
||||||
* <p>
|
* <p>
|
||||||
* For top and bottom tab placement, the layed out component size will be
|
* For top and bottom tab placement, the laid out component size will be
|
||||||
* the preferred component width and the tab area height.<br>
|
* the preferred component width and the tab area height.<br>
|
||||||
* For left and right tab placement, the layed out component size will be
|
* For left and right tab placement, the laid out component size will be
|
||||||
* the tab area width and the preferred component height.
|
* the tab area width and the preferred component height.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
@@ -678,9 +1195,9 @@ public interface FlatClientProperties
|
|||||||
/**
|
/**
|
||||||
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
||||||
* <p>
|
* <p>
|
||||||
* For top and bottom tab placement, the layed out component size will be
|
* For top and bottom tab placement, the laid out component size will be
|
||||||
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
||||||
* For left and right tab placement, the layed out component size will be
|
* For left and right tab placement, the laid out component size will be
|
||||||
* the tab area width and the available vertical space (minimum is preferred component height).
|
* the tab area width and the available vertical space (minimum is preferred component height).
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||||
@@ -688,17 +1205,21 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
||||||
|
|
||||||
|
|
||||||
//---- JTextField ---------------------------------------------------------
|
//---- JTextField ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether all text is selected when the text component gains focus.
|
* Specifies whether all text is selected when the text component gains focus.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
* <strong>Components</strong> {@link javax.swing.text.JTextComponent} (and subclasses),
|
||||||
|
* {@link javax.swing.JComboBox} (since 3.6) and {@link javax.swing.JSpinner} (since 3.6)<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
* <strong>Allowed Values</strong>
|
* <strong>Allowed Values</strong>
|
||||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER},
|
* {@link #SELECT_ALL_ON_FOCUS_POLICY_NEVER},
|
||||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or
|
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ONCE} (default) or
|
||||||
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}
|
* {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}
|
||||||
|
*
|
||||||
|
* @see #SELECT_ALL_ON_MOUSE_CLICK
|
||||||
*/
|
*/
|
||||||
String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy";
|
String SELECT_ALL_ON_FOCUS_POLICY = "JTextField.selectAllOnFocusPolicy";
|
||||||
|
|
||||||
@@ -713,6 +1234,12 @@ public interface FlatClientProperties
|
|||||||
* Select all text when the text component gains focus for the first time
|
* Select all text when the text component gains focus for the first time
|
||||||
* and selection was not modified (is at end of text).
|
* and selection was not modified (is at end of text).
|
||||||
* This is the default.
|
* This is the default.
|
||||||
|
* <p>
|
||||||
|
* <b>Limitations:</b>
|
||||||
|
* For {@link JFormattedTextField} and {@link JSpinner} this behaves
|
||||||
|
* as {@link #SELECT_ALL_ON_FOCUS_POLICY_ALWAYS}.
|
||||||
|
* This is because of special behavior of {@link JFormattedTextField}
|
||||||
|
* that did not allow implementation of {@code "once"}.
|
||||||
*
|
*
|
||||||
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
||||||
*/
|
*/
|
||||||
@@ -725,6 +1252,19 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always";
|
String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether all text is selected when when clicking with the mouse
|
||||||
|
* into the text field (and if "select all on focus" policy is enabled).
|
||||||
|
* <p>
|
||||||
|
* <strong>Components</strong> {@link javax.swing.text.JTextComponent} (and subclasses),
|
||||||
|
* {@link javax.swing.JComboBox} and {@link javax.swing.JSpinner}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @see #SELECT_ALL_ON_FOCUS_POLICY
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
String SELECT_ALL_ON_MOUSE_CLICK = "JTextField.selectAllOnMouseClick";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Placeholder text that is only painted if the text field is empty.
|
* Placeholder text that is only painted if the text field is empty.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -733,10 +1273,150 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
|
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the padding of the text.
|
||||||
|
* This changes the location and size of the text view within the component bounds,
|
||||||
|
* but does not affect the size of the component.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link java.awt.Insets}
|
||||||
|
*
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_PADDING = "JTextField.padding";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an icon that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.Icon}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_LEADING_ICON = "JTextField.leadingIcon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an icon that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.Icon}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the leading edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* The component will be positioned inside and aligned to the visible text field border.
|
||||||
|
* There is no gap between the visible border and the component.
|
||||||
|
* The laid out component size will be the preferred component width
|
||||||
|
* and the inner text field height.
|
||||||
|
* <p>
|
||||||
|
* The component should be not opaque because the text field border is painted
|
||||||
|
* slightly inside the usually visible border in some cases.
|
||||||
|
* E.g. when focused (in some themes) or when an outline color is specified
|
||||||
|
* (see {@link #OUTLINE}).
|
||||||
|
* <p>
|
||||||
|
* The component is prepared in the following way:
|
||||||
|
* <ul>
|
||||||
|
* <li>Component client property {@link #STYLE_CLASS} is set to {@code inTextField}.
|
||||||
|
* <li>If component is a button or toggle button, client property {@link #BUTTON_TYPE}
|
||||||
|
* is set to {@link #BUTTON_TYPE_TOOLBAR_BUTTON}
|
||||||
|
* and button cursor is set to default cursor (if not set).
|
||||||
|
* <li>If component is a toolbar, client property {@link #STYLE_CLASS}
|
||||||
|
* is set to {@code inTextField} on all toolbar children
|
||||||
|
* and toolbar cursor is set to default cursor (if not set).
|
||||||
|
* </ul>
|
||||||
|
* Because text fields use the text cursor by default and the cursor is inherited by child components,
|
||||||
|
* it may be necessary to explicitly set component cursor if you e.g. need the default arrow cursor.
|
||||||
|
* E.g. {@code comp.setCursor( Cursor.getDefaultCursor() )}.
|
||||||
|
* <p>
|
||||||
|
* Styling is used to modify insets/margins and appearance of buttons and toolbars
|
||||||
|
* so that they fit nicely into the text field and do not increase text field height.
|
||||||
|
* See styles {@code [style]Button.inTextField} and {@code [style]ToolBar.inTextField}
|
||||||
|
* in {@code Flat[Light|Dark]Laf.properties}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||||
|
* <p>
|
||||||
|
* See {@link #TEXT_FIELD_LEADING_COMPONENT} for details.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether a "clear" (or "cancel") button is shown on the trailing side
|
||||||
|
* if the text field is not empty, editable and enabled. Default is {@code false}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the callback that is invoked when a "clear" (or "cancel") button is clicked.
|
||||||
|
* If a callback is specified than it is responsible for clearing the text field.
|
||||||
|
* Without callback, the text field clears itself.
|
||||||
|
* <p>
|
||||||
|
* Either use a {@link java.lang.Runnable}:
|
||||||
|
* <pre>{@code
|
||||||
|
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||||
|
* (Runnable) () -> {
|
||||||
|
* // clear field here or cancel search
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* Or use a {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||||
|
* that receives the text field as parameter:
|
||||||
|
* <pre>{@code
|
||||||
|
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||||
|
* (Consumer<JTextComponent>) textField -> {
|
||||||
|
* // clear field here or cancel search
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Runnable}
|
||||||
|
* or {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||||
|
*
|
||||||
|
* @see #TEXT_FIELD_SHOW_CLEAR_BUTTON
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback";
|
||||||
|
|
||||||
|
|
||||||
//---- JToggleButton ------------------------------------------------------
|
//---- JToggleButton ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
* Placement 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}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link SwingConstants#BOTTOM} (default),
|
||||||
|
* {@link SwingConstants#TOP},
|
||||||
|
* {@link SwingConstants#LEFT} or
|
||||||
|
* {@link SwingConstants#RIGHT}
|
||||||
|
*
|
||||||
|
* @since 2.3
|
||||||
|
*/
|
||||||
|
String TAB_BUTTON_UNDERLINE_PLACEMENT = "JToggleButton.tab.underlinePlacement";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thickness of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Integer}
|
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||||
@@ -759,16 +1439,27 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
||||||
|
|
||||||
|
|
||||||
//---- JTree --------------------------------------------------------------
|
//---- JTree --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override if a tree shows a wide selection. Default is {@code true}.
|
* Specifies whether tree shows a wide selection. Default is {@code true}.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JTree}<br>
|
* <strong>Component</strong> {@link javax.swing.JTree}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
*/
|
*/
|
||||||
String TREE_WIDE_SELECTION = "JTree.wideSelection";
|
String TREE_WIDE_SELECTION = "JTree.wideSelection";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether tree uses a wide cell renderer. Default is {@code false}.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTree}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @since 3.6
|
||||||
|
*/
|
||||||
|
String TREE_WIDE_CELL_RENDERER = "JTree.wideCellRenderer";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether tree item selection is painted. Default is {@code true}.
|
* Specifies whether tree item selection is painted. Default is {@code true}.
|
||||||
* If set to {@code false}, then the tree cell renderer is responsible for painting selection.
|
* If set to {@code false}, then the tree cell renderer is responsible for painting selection.
|
||||||
@@ -778,6 +1469,45 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
String TREE_PAINT_SELECTION = "JTree.paintSelection";
|
||||||
|
|
||||||
|
|
||||||
|
//---- macOS --------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the spacing around the macOS window close/minimize/zoom buttons.
|
||||||
|
* Useful if <a href="https://www.formdev.com/flatlaf/macos/#full_window_content">full window content</a>
|
||||||
|
* is enabled.
|
||||||
|
* <p>
|
||||||
|
* (requires macOS 10.14+ for "medium" spacing and macOS 11+ for "large" spacing, requires Java 17+)
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||||
|
* <strong>Allowed Values</strong>
|
||||||
|
* {@link #MACOS_WINDOW_BUTTONS_SPACING_MEDIUM} or
|
||||||
|
* {@link #MACOS_WINDOW_BUTTONS_SPACING_LARGE} (requires macOS 11+)
|
||||||
|
*
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
String MACOS_WINDOW_BUTTONS_SPACING = "FlatLaf.macOS.windowButtonsSpacing";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add medium spacing around the macOS window close/minimize/zoom buttons.
|
||||||
|
*
|
||||||
|
* @see #MACOS_WINDOW_BUTTONS_SPACING
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
String MACOS_WINDOW_BUTTONS_SPACING_MEDIUM = "medium";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add large spacing around the macOS window close/minimize/zoom buttons.
|
||||||
|
* <p>
|
||||||
|
* (requires macOS 11+; "medium" is used on older systems)
|
||||||
|
*
|
||||||
|
* @see #MACOS_WINDOW_BUTTONS_SPACING
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
String MACOS_WINDOW_BUTTONS_SPACING_LARGE = "large";
|
||||||
|
|
||||||
|
|
||||||
//---- helper methods -----------------------------------------------------
|
//---- helper methods -----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -801,8 +1531,7 @@ public interface FlatClientProperties
|
|||||||
* If the client property is not set, or not a {@link Boolean}, defaultValue is returned.
|
* If the client property is not set, or not a {@link Boolean}, defaultValue is returned.
|
||||||
*/
|
*/
|
||||||
static Boolean clientPropertyBooleanStrict( JComponent c, String key, Boolean defaultValue ) {
|
static Boolean clientPropertyBooleanStrict( JComponent c, String key, Boolean defaultValue ) {
|
||||||
Object value = c.getClientProperty( key );
|
return clientProperty( c, key, defaultValue, Boolean.class );
|
||||||
return (value instanceof Boolean) ? (Boolean) value : defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -819,7 +1548,18 @@ public interface FlatClientProperties
|
|||||||
* If the client property is not set, or not a color, defaultValue is returned.
|
* If the client property is not set, or not a color, defaultValue is returned.
|
||||||
*/
|
*/
|
||||||
static Color clientPropertyColor( JComponent c, String key, Color defaultValue ) {
|
static Color clientPropertyColor( JComponent c, String key, Color defaultValue ) {
|
||||||
|
return clientProperty( c, key, defaultValue, Color.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the specified client property if it is an instance of
|
||||||
|
* the specified type. Otherwise, defaultValue is returned.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
static <T> T clientProperty( JComponent c, String key, T defaultValue, Class<T> type ) {
|
||||||
Object value = c.getClientProperty( key );
|
Object value = c.getClientProperty( key );
|
||||||
return (value instanceof Color) ? (Color) value : defaultValue;
|
return type.isInstance( value ) ? (T) value : defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public class FlatDarculaLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatDarculaLaf() );
|
return setup( new FlatDarculaLaf() );
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public class FlatDarkLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatDarkLaf() );
|
return setup( new FlatDarkLaf() );
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import javax.swing.UIDefaults;
|
|||||||
* Allows loading of additional .properties files from addon JARs.
|
* Allows loading of additional .properties files from addon JARs.
|
||||||
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
||||||
* <p>
|
* <p>
|
||||||
* If you extend this class in a addon JAR, you also have to add a text file named
|
* If you extend this class in an addon JAR, you also have to add a text file named
|
||||||
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
* {@code META-INF/services/com.formdev.flatlaf.FlatDefaultsAddon}
|
||||||
* to the addon JAR. The file must contain a single line with the class name.
|
* to the addon JAR. The file must contain a single line with the class name.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -48,7 +48,7 @@ public abstract class FlatDefaultsAddon
|
|||||||
public InputStream getDefaults( Class<?> lafClass ) {
|
public InputStream getDefaults( Class<?> lafClass ) {
|
||||||
Class<?> addonClass = this.getClass();
|
Class<?> addonClass = this.getClass();
|
||||||
String propertiesName = '/' + addonClass.getPackage().getName().replace( '.', '/' )
|
String propertiesName = '/' + addonClass.getPackage().getName().replace( '.', '/' )
|
||||||
+ '/' + lafClass.getSimpleName() + ".properties";
|
+ '/' + UIDefaultsLoader.simpleClassName( lafClass ) + ".properties";
|
||||||
return addonClass.getResourceAsStream( propertiesName );
|
return addonClass.getResourceAsStream( propertiesName );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ public abstract class FlatDefaultsAddon
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the priority used to sort addon loading.
|
* Returns the priority used to sort addon loading.
|
||||||
* The order is only important if you want overwrite UI defaults of other addons.
|
* The order is only important if you want to overwrite UI defaults of other addons.
|
||||||
* Lower numbers mean higher priority.
|
* Lower numbers mean higher priority.
|
||||||
* Returns 10000 by default.
|
* Returns 10000 by default.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf;
|
|||||||
/**
|
/**
|
||||||
* Default color palette for action icons and object icons.
|
* Default color palette for action icons and object icons.
|
||||||
* <p>
|
* <p>
|
||||||
* The idea is to use only this well defined set of colors in SVG icons and
|
* The idea is to use only this well-defined set of colors in SVG icons, and
|
||||||
* then they are replaced at runtime to dark variants or to other theme colors.
|
* then they are replaced at runtime to dark variants or to other theme colors.
|
||||||
* Then a single SVG icon (light variant) can be used for dark themes too.
|
* Then a single SVG icon (light variant) can be used for dark themes too.
|
||||||
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
* IntelliJ Platform uses this mechanism to allow themes to change IntelliJ Platform icons.
|
||||||
@@ -35,7 +35,7 @@ package com.formdev.flatlaf;
|
|||||||
* <p>
|
* <p>
|
||||||
* You may use these colors also in your application (outside of SVG icons), but do
|
* You may use these colors also in your application (outside of SVG icons), but do
|
||||||
* not use the RGB values defined in this enum.<br>
|
* not use the RGB values defined in this enum.<br>
|
||||||
* Instead use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
* Instead, use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ class FlatInputMaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
modifyInputMap( defaults, "ComboBox.ancestorInputMap",
|
modifyInputMap( defaults, "ComboBox.ancestorInputMap",
|
||||||
"SPACE", "spacePopup",
|
// Space key still shows popup, but from FlatComboBoxUI.FlatKeySelectionManager
|
||||||
|
// "SPACE", "spacePopup",
|
||||||
|
|
||||||
"UP", mac( "selectPrevious2", "selectPrevious" ),
|
"UP", mac( "selectPrevious2", "selectPrevious" ),
|
||||||
"DOWN", mac( "selectNext2", "selectNext" ),
|
"DOWN", mac( "selectNext2", "selectNext" ),
|
||||||
@@ -70,7 +71,7 @@ class FlatInputMaps
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// join ltr and rtl bindings to fix up/down/etc keys in right-to-left component orientation
|
// 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[] bindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings" );
|
||||||
Object[] rtlBindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings.RightToLeft" );
|
Object[] rtlBindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings.RightToLeft" );
|
||||||
if( bindings != null && rtlBindings != null ) {
|
if( bindings != null && rtlBindings != null ) {
|
||||||
@@ -596,7 +597,7 @@ class FlatInputMaps
|
|||||||
//---- class LazyInputMapEx -----------------------------------------------
|
//---- class LazyInputMapEx -----------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazily creates a input map.
|
* Lazily creates an input map.
|
||||||
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
||||||
*/
|
*/
|
||||||
private static class LazyInputMapEx
|
private static class LazyInputMapEx
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public class FlatIntelliJLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatIntelliJLaf() );
|
return setup( new FlatIntelliJLaf() );
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,8 @@ public class FlatLightLaf
|
|||||||
/**
|
/**
|
||||||
* Sets the application look and feel to this LaF
|
* Sets the application look and feel to this LaF
|
||||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup() {
|
public static boolean setup() {
|
||||||
return setup( new FlatLightLaf() );
|
return setup( new FlatLightLaf() );
|
||||||
|
|||||||
@@ -20,15 +20,21 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
|
||||||
|
import com.formdev.flatlaf.themes.FlatMacLightLaf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Flat LaF that is able to load UI defaults from properties passed to the constructor.
|
* A Flat LaF that is able to load UI defaults from properties passed to the constructor.
|
||||||
* <p>
|
* <p>
|
||||||
* Specify the base theme in the properties with {@code @baseTheme=<baseTheme>}.
|
* Specify the base theme in the properties with {@code @baseTheme=<baseTheme>}.
|
||||||
* Allowed values for {@code <baseTheme>} are {@code light} (the default), {@code dark},
|
* Allowed values for {@code <baseTheme>} are {@code light} (the default), {@code dark},
|
||||||
* {@code intellij} or {@code darcula}.
|
* {@code intellij}, {@code darcula}, {@code maclight} or {@code macdark}.
|
||||||
* <p>
|
* <p>
|
||||||
* The properties are applied after loading the base theme and may overwrite base properties.
|
* The properties are applied after loading the base theme and may overwrite base properties.
|
||||||
* All features of FlatLaf properties files are available.
|
* All features of FlatLaf properties files are available.
|
||||||
@@ -59,8 +65,8 @@ public class FlatPropertiesLaf
|
|||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
try( InputStream in2 = in ) {
|
try( Reader reader = new InputStreamReader( in, StandardCharsets.UTF_8 )) {
|
||||||
properties.load( in2 );
|
properties.load( reader );
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
@@ -70,7 +76,8 @@ public class FlatPropertiesLaf
|
|||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
|
|
||||||
baseTheme = properties.getProperty( "@baseTheme", "light" );
|
baseTheme = properties.getProperty( "@baseTheme", "light" );
|
||||||
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme );
|
dark = "dark".equalsIgnoreCase( baseTheme ) || "darcula".equalsIgnoreCase( baseTheme ) ||
|
||||||
|
"macdark".equalsIgnoreCase( baseTheme );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -96,7 +103,7 @@ public class FlatPropertiesLaf
|
|||||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||||
lafClasses.add( FlatLaf.class );
|
lafClasses.add( FlatLaf.class );
|
||||||
switch( baseTheme.toLowerCase() ) {
|
switch( baseTheme.toLowerCase( Locale.ENGLISH ) ) {
|
||||||
default:
|
default:
|
||||||
case "light":
|
case "light":
|
||||||
lafClasses.add( FlatLightLaf.class );
|
lafClasses.add( FlatLightLaf.class );
|
||||||
@@ -115,6 +122,16 @@ public class FlatPropertiesLaf
|
|||||||
lafClasses.add( FlatDarkLaf.class );
|
lafClasses.add( FlatDarkLaf.class );
|
||||||
lafClasses.add( FlatDarculaLaf.class );
|
lafClasses.add( FlatDarculaLaf.class );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "maclight":
|
||||||
|
lafClasses.add( FlatLightLaf.class );
|
||||||
|
lafClasses.add( FlatMacLightLaf.class );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "macdark":
|
||||||
|
lafClasses.add( FlatDarkLaf.class );
|
||||||
|
lafClasses.add( FlatMacDarkLaf.class );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return lafClasses;
|
return lafClasses;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +36,7 @@ public interface FlatSystemProperties
|
|||||||
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
||||||
* which has the same syntax as this one.
|
* which has the same syntax as this one.
|
||||||
* <p>
|
* <p>
|
||||||
* Since FlatLaf 1.1.2: Scale factors less then 100% are allowed.
|
* Since FlatLaf 1.1.2: Scale factors less than 100% are allowed.
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
||||||
*/
|
*/
|
||||||
@@ -81,7 +83,7 @@ public interface FlatSystemProperties
|
|||||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||||
* UI default {@code TitlePane.useWindowDecorations}.
|
* UI default {@code TitlePane.useWindowDecorations}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Windows 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> none
|
* <strong>Default</strong> none
|
||||||
@@ -92,17 +94,20 @@ public interface FlatSystemProperties
|
|||||||
* Specifies whether JetBrains Runtime custom window decorations should be used
|
* Specifies whether JetBrains Runtime custom window decorations should be used
|
||||||
* when creating {@code JFrame} or {@code JDialog}.
|
* when creating {@code JFrame} or {@code JDialog}.
|
||||||
* Requires that the application runs in a
|
* Requires that the application runs in a
|
||||||
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime</a>
|
* <a href="https://github.com/JetBrains/JetBrainsRuntime/wiki">JetBrains Runtime</a>
|
||||||
* (based on OpenJDK).
|
* (based on OpenJDK).
|
||||||
* <p>
|
* <p>
|
||||||
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
||||||
* Then FlatLaf native window decorations are used.
|
* Then FlatLaf native window decorations are used.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Windows 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> {@code true}
|
* <strong>Default</strong> {@code false} (since v2; was {@code true} in v1)
|
||||||
|
*
|
||||||
|
* @deprecated No longer used since FlatLaf 3.3. Retained for API compatibility.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,7 +121,7 @@ public interface FlatSystemProperties
|
|||||||
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
||||||
* UI default {@code TitlePane.menuBarEmbedded}.
|
* UI default {@code TitlePane.menuBarEmbedded}.
|
||||||
* <p>
|
* <p>
|
||||||
* (requires Window 10)
|
* (requires Windows 10/11)
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
* <strong>Default</strong> none
|
* <strong>Default</strong> none
|
||||||
@@ -131,6 +136,37 @@ public interface FlatSystemProperties
|
|||||||
*/
|
*/
|
||||||
String ANIMATION = "flatlaf.animation";
|
String ANIMATION = "flatlaf.animation";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether native rounded popup borders should be used (if supported by operating system).
|
||||||
|
* <p>
|
||||||
|
* (requires Windows 11 or macOS)
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}; except in FlatLaf 3.5.x on macOS 14.4+ where it was {@code false}
|
||||||
|
*
|
||||||
|
* @since 3.5.2
|
||||||
|
*/
|
||||||
|
String USE_ROUNDED_POPUP_BORDER = "flatlaf.useRoundedPopupBorder";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Species whether popup windows may be reused without (temporary) hiding them.
|
||||||
|
* E.g. if "moving" a tooltip to follow the mouse pointer, normally it is necessary
|
||||||
|
* to hide the tooltip and show it again at the new location, which causes some
|
||||||
|
* flicker with heavy-weight popup windows that FlatLaf uses on all platforms.
|
||||||
|
* <p>
|
||||||
|
* If {@code true}, hiding popup window is deferred for an event cycle,
|
||||||
|
* which allows reusing still visible popup window and avoids flicker when "moving" the popup.
|
||||||
|
* <p>
|
||||||
|
* Note that {@link JPopupMenu} popup windows (menus and combobox lists) are newer reused.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
String REUSE_VISIBLE_POPUP_WINDOW = "flatlaf.reuseVisiblePopupWindow";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens.
|
* Specifies whether vertical text position is corrected when UI is scaled on HiDPI screens.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -139,6 +175,77 @@ public interface FlatSystemProperties
|
|||||||
*/
|
*/
|
||||||
String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection";
|
String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether FlatLaf updates the UI when the system font changes.
|
||||||
|
* If {@code true}, {@link SwingUtilities#updateComponentTreeUI(java.awt.Component)}
|
||||||
|
* gets invoked for all windows if the system font has changed.
|
||||||
|
* This is the similar to when switching to another look and feel (theme).
|
||||||
|
* Applications that do not work correctly when switching look and feel,
|
||||||
|
* should disable this option to avoid corrupted UI.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
|
* @since 2.5
|
||||||
|
*/
|
||||||
|
String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether FlatLaf native library should be used.
|
||||||
|
* <p>
|
||||||
|
* Setting this to {@code false} disables loading native library,
|
||||||
|
* which also disables some features that depend on the native library.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a directory in which the FlatLaf native libraries are searched for.
|
||||||
|
* The path can be absolute or relative to current application working directory.
|
||||||
|
* This can be used to avoid extraction of the native libraries to the temporary directory at runtime.
|
||||||
|
* <p>
|
||||||
|
* If the value is {@code "system"} (supported since FlatLaf 2.6),
|
||||||
|
* then {@link System#loadLibrary(String)} is used to load the native library.
|
||||||
|
* This searches for the native library in classloader of caller
|
||||||
|
* (using {@link ClassLoader#findLibrary(String)}) and in paths specified
|
||||||
|
* in system properties {@code sun.boot.library.path} and {@code java.library.path}.
|
||||||
|
* <p>
|
||||||
|
* If the native library can not be loaded from the given path (or via {@link System#loadLibrary(String)}),
|
||||||
|
* then the embedded native library is extracted to the temporary directory and loaded from there.
|
||||||
|
* <p>
|
||||||
|
* The file names of the native libraries must be either:
|
||||||
|
* <ul>
|
||||||
|
* <li>the same as in flatlaf.jar in package 'com/formdev/flatlaf/natives' (required for "system") or
|
||||||
|
* <li>when downloaded from Maven central then as described here:
|
||||||
|
* <a href="https://www.formdev.com/flatlaf/native-libraries/">https://www.formdev.com/flatlaf/native-libraries/</a>
|
||||||
|
* (requires FlatLaf 3.4)
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* <strong>Note</strong>: Since FlatLaf 3.1 it is recommended to download the
|
||||||
|
* FlatLaf native libraries from Maven central and distribute them with your
|
||||||
|
* application in the same directory as flatlaf.jar.
|
||||||
|
* Then it is <strong>not necessary</strong> to set this system property.
|
||||||
|
* See <a href="https://www.formdev.com/flatlaf/native-libraries/">https://www.formdev.com/flatlaf/native-libraries/</a>
|
||||||
|
* for details.
|
||||||
|
*
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether safe triangle is used to improve usability of submenus.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
|
* @since 3.5.1
|
||||||
|
*/
|
||||||
|
String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a system property is set and returns {@code true} if its value
|
* Checks whether a system property is set and returns {@code true} if its value
|
||||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||||
|
|||||||
@@ -16,27 +16,27 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.swing.UIDefaults;
|
|
||||||
import javax.swing.plaf.ColorUIResource;
|
|
||||||
import com.formdev.flatlaf.json.Json;
|
import com.formdev.flatlaf.json.Json;
|
||||||
import com.formdev.flatlaf.json.ParseException;
|
import com.formdev.flatlaf.json.ParseException;
|
||||||
import com.formdev.flatlaf.util.ColorFunctions;
|
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class supports loading IntelliJ .theme.json files and using them as a Laf.
|
* This class supports loading IntelliJ .theme.json files and using them as a Laf.
|
||||||
@@ -58,13 +58,11 @@ public class IntelliJTheme
|
|||||||
public final boolean dark;
|
public final boolean dark;
|
||||||
public final String author;
|
public final String author;
|
||||||
|
|
||||||
private final boolean isMaterialUILite;
|
private Map<String, String> jsonColors;
|
||||||
|
private Map<String, Object> jsonUI;
|
||||||
|
private Map<String, Object> jsonIcons;
|
||||||
|
|
||||||
private final Map<String, String> colors;
|
private Map<String, String> namedColors = Collections.emptyMap();
|
||||||
private final Map<String, Object> ui;
|
|
||||||
private final Map<String, Object> icons;
|
|
||||||
|
|
||||||
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a IntelliJ .theme.json file from the given input stream,
|
* Loads a IntelliJ .theme.json file from the given input stream,
|
||||||
@@ -72,12 +70,14 @@ public class IntelliJTheme
|
|||||||
*
|
*
|
||||||
* The input stream is automatically closed.
|
* The input stream is automatically closed.
|
||||||
* Using a buffered input stream is not necessary.
|
* Using a buffered input stream is not necessary.
|
||||||
|
*
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public static boolean setup( InputStream in ) {
|
public static boolean setup( InputStream in ) {
|
||||||
try {
|
try {
|
||||||
return FlatLaf.setup( createLaf( in ) );
|
return FlatLaf.setup( createLaf( in ) );
|
||||||
} catch( Exception ex ) {
|
} catch( Exception ex ) {
|
||||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load IntelliJ theme", ex );
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load IntelliJ theme", ex );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,164 +131,252 @@ public class IntelliJTheme
|
|||||||
dark = Boolean.parseBoolean( (String) json.get( "dark" ) );
|
dark = Boolean.parseBoolean( (String) json.get( "dark" ) );
|
||||||
author = (String) json.get( "author" );
|
author = (String) json.get( "author" );
|
||||||
|
|
||||||
isMaterialUILite = author.equals( "Mallowigi" );
|
jsonColors = (Map<String, String>) json.get( "colors" );
|
||||||
|
jsonUI = (Map<String, Object>) json.get( "ui" );
|
||||||
colors = (Map<String, String>) json.get( "colors" );
|
jsonIcons = (Map<String, Object>) json.get( "icons" );
|
||||||
ui = (Map<String, Object>) json.get( "ui" );
|
|
||||||
icons = (Map<String, Object>) json.get( "icons" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyProperties( UIDefaults defaults ) {
|
private void applyProperties( Properties properties ) {
|
||||||
if( ui == null )
|
if( jsonUI == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
defaults.put( "Component.isIntelliJTheme", true );
|
put( properties, "Component.isIntelliJTheme", "true" );
|
||||||
|
|
||||||
// enable button shadows
|
// enable button shadows
|
||||||
defaults.put( "Button.paintShadow", true );
|
put( properties, "Button.paintShadow", "true" );
|
||||||
defaults.put( "Button.shadowWidth", dark ? 2 : 1 );
|
put( properties, "Button.shadowWidth", dark ? "2" : "1" );
|
||||||
|
|
||||||
Map<Object, Object> themeSpecificDefaults = removeThemeSpecificDefaults( defaults );
|
Map<String, String> themeSpecificProps = removeThemeSpecificProps( properties );
|
||||||
|
Set<String> jsonUIKeys = new HashSet<>();
|
||||||
|
|
||||||
loadNamedColors( defaults );
|
// Json node "colors"
|
||||||
|
loadNamedColors( properties, jsonUIKeys );
|
||||||
|
|
||||||
// convert Json "ui" structure to UI defaults
|
// convert Json "ui" structure to UI properties
|
||||||
ArrayList<Object> defaultsKeysCache = new ArrayList<>();
|
for( Map.Entry<String, Object> e : jsonUI.entrySet() )
|
||||||
Set<String> uiKeys = new HashSet<>();
|
apply( e.getKey(), e.getValue(), properties, jsonUIKeys );
|
||||||
for( Map.Entry<String, Object> e : ui.entrySet() )
|
|
||||||
apply( e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
|
||||||
|
|
||||||
applyColorPalette( defaults );
|
// set FlatLaf variables
|
||||||
applyCheckBoxColors( defaults );
|
copyIfSetInJson( properties, jsonUIKeys, "@background", "Panel.background", "*.background" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@foreground", "CheckBox.foreground", "*.foreground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@accentBaseColor",
|
||||||
|
"ColorPalette.accent", // Material UI Lite, Hiberbee
|
||||||
|
"ColorPalette.accentColor", // Dracula, One Dark
|
||||||
|
"ProgressBar.foreground",
|
||||||
|
"*.selectionBackground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@accentUnderlineColor", "*.underlineColor", "TabbedPane.underlineColor" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionBackground", "*.selectionBackground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionForeground", "*.selectionForeground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveBackground", "*.selectionInactiveBackground" );
|
||||||
|
copyIfSetInJson( properties, jsonUIKeys, "@selectionInactiveForeground", "*.selectionInactiveForeground" );
|
||||||
|
|
||||||
|
// Json node "icons/ColorPalette"
|
||||||
|
applyIconsColorPalette( properties );
|
||||||
|
|
||||||
|
// apply "CheckBox.icon." colors
|
||||||
|
applyCheckBoxColors( properties );
|
||||||
|
|
||||||
// copy values
|
// copy values
|
||||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() )
|
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
|
||||||
defaults.put( e.getKey(), defaults.get( e.getValue() ) );
|
Object value = properties.get( e.getValue() );
|
||||||
|
if( value != null )
|
||||||
|
put( properties, e.getKey(), value );
|
||||||
|
}
|
||||||
|
|
||||||
// IDEA does not paint button background if disabled, but FlatLaf does
|
// IDEA does not paint button background if disabled, but FlatLaf does
|
||||||
Object panelBackground = defaults.get( "Panel.background" );
|
put( properties, "Button.disabledBackground", "@disabledBackground" );
|
||||||
defaults.put( "Button.disabledBackground", panelBackground );
|
put( properties, "ToggleButton.disabledBackground", "@disabledBackground" );
|
||||||
defaults.put( "ToggleButton.disabledBackground", panelBackground );
|
|
||||||
|
|
||||||
// fix Button borders
|
// fix Button
|
||||||
copyIfNotSet( defaults, "Button.focusedBorderColor", "Component.focusedBorderColor", uiKeys );
|
fixStartEnd( properties, jsonUIKeys, "Button.startBackground", "Button.endBackground", "Button.background" );
|
||||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
fixStartEnd( properties, jsonUIKeys, "Button.startBorderColor", "Button.endBorderColor", "Button.borderColor" );
|
||||||
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
fixStartEnd( properties, jsonUIKeys, "Button.default.startBackground", "Button.default.endBackground", "Button.default.background" );
|
||||||
|
fixStartEnd( properties, jsonUIKeys, "Button.default.startBorderColor", "Button.default.endBorderColor", "Button.default.borderColor" );
|
||||||
// IDEA uses a SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
|
||||||
Object helpButtonBackground = defaults.get( "Button.startBackground" );
|
|
||||||
Object helpButtonBorderColor = defaults.get( "Button.startBorderColor" );
|
|
||||||
if( helpButtonBackground == null )
|
|
||||||
helpButtonBackground = defaults.get( "Button.background" );
|
|
||||||
if( helpButtonBorderColor == null )
|
|
||||||
helpButtonBorderColor = defaults.get( "Button.borderColor" );
|
|
||||||
defaults.put( "HelpButton.background", helpButtonBackground );
|
|
||||||
defaults.put( "HelpButton.borderColor", helpButtonBorderColor );
|
|
||||||
defaults.put( "HelpButton.disabledBackground", panelBackground );
|
|
||||||
defaults.put( "HelpButton.disabledBorderColor", defaults.get( "Button.disabledBorderColor" ) );
|
|
||||||
defaults.put( "HelpButton.focusedBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
|
||||||
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
|
|
||||||
|
|
||||||
// IDEA uses TextField.background for editable ComboBox and Spinner
|
// IDEA uses TextField.background for editable ComboBox and Spinner
|
||||||
defaults.put( "ComboBox.editableBackground", defaults.get( "TextField.background" ) );
|
Object textFieldBackground = get( properties, themeSpecificProps, "TextField.background" );
|
||||||
defaults.put( "Spinner.background", defaults.get( "TextField.background" ) );
|
put( properties, "ComboBox.editableBackground", textFieldBackground );
|
||||||
|
put( properties, "Spinner.background", textFieldBackground );
|
||||||
// Spinner arrow button always has same colors as ComboBox arrow button
|
|
||||||
defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) );
|
|
||||||
defaults.put( "Spinner.buttonArrowColor", defaults.get( "ComboBox.buttonArrowColor" ) );
|
|
||||||
defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) );
|
|
||||||
|
|
||||||
// some themes specify colors for TextField.background, but forget to specify it for other components
|
// some themes specify colors for TextField.background, but forget to specify it for other components
|
||||||
// (probably because those components are not used in IntelliJ)
|
// (probably because those components are not used in IntelliJ IDEA)
|
||||||
if( uiKeys.contains( "TextField.background" ) ) {
|
putAll( properties, textFieldBackground,
|
||||||
Object textFieldBackground = defaults.get( "TextField.background" );
|
"EditorPane.background",
|
||||||
if( !uiKeys.contains( "FormattedTextField.background" ) )
|
"FormattedTextField.background",
|
||||||
defaults.put( "FormattedTextField.background", textFieldBackground );
|
"PasswordField.background",
|
||||||
if( !uiKeys.contains( "PasswordField.background" ) )
|
"TextArea.background",
|
||||||
defaults.put( "PasswordField.background", textFieldBackground );
|
"TextPane.background"
|
||||||
if( !uiKeys.contains( "EditorPane.background" ) )
|
);
|
||||||
defaults.put( "EditorPane.background", textFieldBackground );
|
putAll( properties, get( properties, themeSpecificProps, "TextField.selectionBackground" ),
|
||||||
if( !uiKeys.contains( "TextArea.background" ) )
|
"EditorPane.selectionBackground",
|
||||||
defaults.put( "TextArea.background", textFieldBackground );
|
"FormattedTextField.selectionBackground",
|
||||||
if( !uiKeys.contains( "TextPane.background" ) )
|
"PasswordField.selectionBackground",
|
||||||
defaults.put( "TextPane.background", textFieldBackground );
|
"TextArea.selectionBackground",
|
||||||
if( !uiKeys.contains( "Spinner.background" ) )
|
"TextPane.selectionBackground"
|
||||||
defaults.put( "Spinner.background", textFieldBackground );
|
);
|
||||||
}
|
putAll( properties, get( properties, themeSpecificProps, "TextField.selectionForeground" ),
|
||||||
|
"EditorPane.selectionForeground",
|
||||||
|
"FormattedTextField.selectionForeground",
|
||||||
|
"PasswordField.selectionForeground",
|
||||||
|
"TextArea.selectionForeground",
|
||||||
|
"TextPane.selectionForeground"
|
||||||
|
);
|
||||||
|
|
||||||
// fix ToggleButton
|
// fix disabled and not-editable backgrounds for text components, combobox and spinner
|
||||||
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
|
// (IntelliJ IDEA does not use those colors; instead it used background color of parent)
|
||||||
defaults.put( "ToggleButton.startBackground", defaults.get( "Button.startBackground" ) );
|
putAll( properties, "@disabledBackground",
|
||||||
if( !uiKeys.contains( "ToggleButton.endBackground" ) && !uiKeys.contains( "*.endBackground" ) )
|
"ComboBox.disabledBackground",
|
||||||
defaults.put( "ToggleButton.endBackground", defaults.get( "Button.endBackground" ) );
|
"EditorPane.disabledBackground", "EditorPane.inactiveBackground",
|
||||||
if( !uiKeys.contains( "ToggleButton.foreground" ) && uiKeys.contains( "Button.foreground" ) )
|
"FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground",
|
||||||
defaults.put( "ToggleButton.foreground", defaults.get( "Button.foreground" ) );
|
"PasswordField.disabledBackground", "PasswordField.inactiveBackground",
|
||||||
|
"Spinner.disabledBackground",
|
||||||
|
"TextArea.disabledBackground", "TextArea.inactiveBackground",
|
||||||
|
"TextField.disabledBackground", "TextField.inactiveBackground",
|
||||||
|
"TextPane.disabledBackground", "TextPane.inactiveBackground"
|
||||||
|
);
|
||||||
|
|
||||||
// fix DesktopPane background (use Panel.background and make it 5% darker/lighter)
|
// fix DesktopPane background (use Panel.background and make it 5% darker/lighter)
|
||||||
Color desktopBackgroundBase = defaults.getColor( "Panel.background" );
|
put( properties, "Desktop.background", dark ? "lighten($Panel.background,5%)" : "darken($Panel.background,5%)" );
|
||||||
Color desktopBackground = ColorFunctions.applyFunctions( desktopBackgroundBase,
|
|
||||||
new ColorFunctions.HSLIncreaseDecrease( 2, dark, 5, false, true ) );
|
|
||||||
defaults.put( "Desktop.background", new ColorUIResource( desktopBackground ) );
|
|
||||||
|
|
||||||
// fix List and Table background colors in Material UI Lite themes
|
|
||||||
if( isMaterialUILite ) {
|
|
||||||
defaults.put( "List.background", defaults.get( "Tree.background" ) );
|
|
||||||
defaults.put( "Table.background", defaults.get( "Tree.background" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// limit tree row height
|
// limit tree row height
|
||||||
int rowHeight = defaults.getInt( "Tree.rowHeight" );
|
String rowHeightStr = (String) properties.get( "Tree.rowHeight" );
|
||||||
|
int rowHeight = (rowHeightStr != null) ? Integer.parseInt( rowHeightStr ) : 0;
|
||||||
if( rowHeight > 22 )
|
if( rowHeight > 22 )
|
||||||
defaults.put( "Tree.rowHeight", 22 );
|
put( properties, "Tree.rowHeight", "22" );
|
||||||
|
|
||||||
// apply theme specific UI defaults at the end to allow overwriting
|
// get (and remove) theme specific wildcard replacements, which override all other properties that end with same suffix
|
||||||
defaults.putAll( themeSpecificDefaults );
|
HashMap<String, String> wildcardProps = new HashMap<>();
|
||||||
|
Iterator<Map.Entry<String, String>> it = themeSpecificProps.entrySet().iterator();
|
||||||
|
while( it.hasNext() ) {
|
||||||
|
Map.Entry<String, String> e = it.next();
|
||||||
|
String key = e.getKey();
|
||||||
|
if( key.startsWith( "*." ) ) {
|
||||||
|
wildcardProps.put( key, e.getValue() );
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// override properties with theme specific wildcard replacements
|
||||||
|
if( !wildcardProps.isEmpty() ) {
|
||||||
|
for( Map.Entry<String, String> e : wildcardProps.entrySet() )
|
||||||
|
applyWildcard( properties, e.getKey(), e.getValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply theme specific properties at the end to allow overwriting
|
||||||
|
for( Map.Entry<String, String> e : themeSpecificProps.entrySet() ) {
|
||||||
|
String key = e.getKey();
|
||||||
|
String value = e.getValue();
|
||||||
|
|
||||||
|
// append styles to existing styles
|
||||||
|
if( key.startsWith( "[style]" ) ) {
|
||||||
|
String oldValue = (String) properties.get( key );
|
||||||
|
if( oldValue != null )
|
||||||
|
value = oldValue + "; " + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
put( properties, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// let Java release memory
|
||||||
|
jsonColors = null;
|
||||||
|
jsonUI = null;
|
||||||
|
jsonIcons = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
private String get( Properties properties, Map<String, String> themeSpecificProps, String key ) {
|
||||||
// search for theme specific UI defaults keys
|
return themeSpecificProps.getOrDefault( key, (String) properties.get( key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void put( Properties properties, Object key, Object value ) {
|
||||||
|
if( value != null )
|
||||||
|
properties.put( key, value );
|
||||||
|
else
|
||||||
|
properties.remove( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void putAll( Properties properties, Object value, String... keys ) {
|
||||||
|
for( String key : keys )
|
||||||
|
put( properties, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyIfSetInJson( Properties properties, Set<String> jsonUIKeys, String destKey, String... srcKeys ) {
|
||||||
|
for( String srcKey : srcKeys ) {
|
||||||
|
if( jsonUIKeys.contains( srcKey ) ) {
|
||||||
|
Object value = properties.get( srcKey );
|
||||||
|
if( value != null ) {
|
||||||
|
put( properties, destKey, value );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fixStartEnd( Properties properties, Set<String> jsonUIKeys, String startKey, String endKey, String key ) {
|
||||||
|
if( jsonUIKeys.contains( startKey ) && jsonUIKeys.contains( endKey ) )
|
||||||
|
put( properties, key, "$" + startKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> removeThemeSpecificProps( Properties properties ) {
|
||||||
|
// search for theme specific properties keys
|
||||||
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
ArrayList<String> themeSpecificKeys = new ArrayList<>();
|
||||||
for( Object key : defaults.keySet() ) {
|
for( Object key : properties.keySet() ) {
|
||||||
if( key instanceof String && ((String)key).startsWith( "[" ) )
|
if( ((String)key).startsWith( "{" ) )
|
||||||
themeSpecificKeys.add( (String) key );
|
themeSpecificKeys.add( (String) key );
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove theme specific UI defaults and remember only those for current theme
|
// special prefixes (priority from highest to lowest)
|
||||||
Map<Object, Object> themeSpecificDefaults = new HashMap<>();
|
String currentThemePrefix = '{' + name.replace( ' ', '_' ) + '}';
|
||||||
String currentThemePrefix = '[' + name.replace( ' ', '_' ) + ']';
|
String currentThemeAndAuthorPrefix = '{' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + '}';
|
||||||
String currentThemeAndAuthorPrefix = '[' + name.replace( ' ', '_' ) + "---" + author.replace( ' ', '_' ) + ']';
|
String currentAuthorPrefix = "{author-" + author.replace( ' ', '_' ) + '}';
|
||||||
String currentAuthorPrefix = "[author-" + author.replace( ' ', '_' ) + ']';
|
String lightOrDarkPrefix = dark ? "{*-dark}" : "{*-light}";
|
||||||
String allThemesPrefix = "[*]";
|
String allThemesPrefix = "{*}";
|
||||||
String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, allThemesPrefix };
|
String[] prefixes = { currentThemePrefix, currentThemeAndAuthorPrefix, currentAuthorPrefix, lightOrDarkPrefix, allThemesPrefix };
|
||||||
|
|
||||||
|
// collect values for special prefixes in its own maps
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
Map<String, String>[] maps = new Map[prefixes.length];
|
||||||
|
for( int i = 0; i < maps.length; i++ )
|
||||||
|
maps[i] = new HashMap<>();
|
||||||
|
|
||||||
|
// remove theme specific properties and remember only those for current theme
|
||||||
for( String key : themeSpecificKeys ) {
|
for( String key : themeSpecificKeys ) {
|
||||||
Object value = defaults.remove( key );
|
String value = (String) properties.remove( key );
|
||||||
for( String prefix : prefixes ) {
|
for( int i = 0; i < prefixes.length; i++ ) {
|
||||||
|
String prefix = prefixes[i];
|
||||||
if( key.startsWith( prefix ) ) {
|
if( key.startsWith( prefix ) ) {
|
||||||
themeSpecificDefaults.put( key.substring( prefix.length() ), value );
|
maps[i].put( key.substring( prefix.length() ), value );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return themeSpecificDefaults;
|
// copy values into single map (from lowest to highest priority)
|
||||||
|
Map<String, String> themeSpecificProps = new HashMap<>();
|
||||||
|
for( int i = maps.length - 1; i >= 0; i-- )
|
||||||
|
themeSpecificProps.putAll( maps[i] );
|
||||||
|
return themeSpecificProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#defining-named-colors
|
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#defining-named-colors
|
||||||
*/
|
*/
|
||||||
private void loadNamedColors( UIDefaults defaults ) {
|
private void loadNamedColors( Properties properties, Set<String> jsonUIKeys ) {
|
||||||
if( colors == null )
|
if( jsonColors == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
namedColors = new HashMap<>();
|
namedColors = new HashMap<>();
|
||||||
|
|
||||||
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
for( Map.Entry<String, String> e : jsonColors.entrySet() ) {
|
||||||
String value = e.getValue();
|
String value = e.getValue();
|
||||||
ColorUIResource color = UIDefaultsLoader.parseColor( value );
|
if( canParseColor( value ) ) {
|
||||||
if( color != null ) {
|
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
namedColors.put( key, color );
|
namedColors.put( key, value );
|
||||||
defaults.put( "ColorPalette." + key, color );
|
|
||||||
|
String uiKey = "ColorPalette." + key;
|
||||||
|
put( properties, uiKey, value );
|
||||||
|
|
||||||
|
// this is only necessary for copyIfSetInJson() (used for accent color)
|
||||||
|
jsonUIKeys.add( uiKey );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,18 +385,36 @@ public class IntelliJTheme
|
|||||||
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#custom-ui-control-colors
|
* http://www.jetbrains.org/intellij/sdk/docs/reference_guide/ui_themes/themes_customize.html#custom-ui-control-colors
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
private void apply( String key, Object value, Properties properties, Set<String> jsonUIKeys ) {
|
||||||
if( value instanceof Map ) {
|
if( value instanceof Map ) {
|
||||||
for( Map.Entry<String, Object> e : ((Map<String, Object>)value).entrySet() )
|
Map<String, Object> map = (Map<String, Object>)value;
|
||||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
if( map.containsKey( "os.default" ) || map.containsKey( "os.windows" ) || map.containsKey( "os.mac" ) || map.containsKey( "os.linux" ) ) {
|
||||||
|
String osKey = SystemInfo.isWindows ? "os.windows"
|
||||||
|
: SystemInfo.isMacOS ? "os.mac"
|
||||||
|
: SystemInfo.isLinux ? "os.linux" : null;
|
||||||
|
if( osKey != null && map.containsKey( osKey ) )
|
||||||
|
apply( key, map.get( osKey ), properties, jsonUIKeys );
|
||||||
|
else if( map.containsKey( "os.default" ) )
|
||||||
|
apply( key, map.get( "os.default" ), properties, jsonUIKeys );
|
||||||
|
} else {
|
||||||
|
for( Map.Entry<String, Object> e : map.entrySet() )
|
||||||
|
apply( key + '.' + e.getKey(), e.getValue(), properties, jsonUIKeys );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if( "".equals( value ) )
|
if( "".equals( value ) )
|
||||||
return; // ignore empty value
|
return; // ignore empty value
|
||||||
|
|
||||||
uiKeys.add( key );
|
// ignore some properties that affect sizes
|
||||||
|
if( key.endsWith( ".border" ) ||
|
||||||
|
key.endsWith( ".rowHeight" ) ||
|
||||||
|
key.equals( "ComboBox.padding" ) ||
|
||||||
|
key.equals( "Spinner.padding" ) ||
|
||||||
|
key.equals( "Tree.leftChildIndent" ) ||
|
||||||
|
key.equals( "Tree.rightChildIndent" ) )
|
||||||
|
return; // ignore
|
||||||
|
|
||||||
// fix ComboBox size and Spinner border in all Material UI Lite themes
|
// ignore icons
|
||||||
if( isMaterialUILite && (key.equals( "ComboBox.padding" ) || key.equals( "Spinner.border" )) )
|
if( key.endsWith( "Icon" ) )
|
||||||
return; // ignore
|
return; // ignore
|
||||||
|
|
||||||
// map keys
|
// map keys
|
||||||
@@ -316,10 +422,31 @@ public class IntelliJTheme
|
|||||||
if( key.isEmpty() )
|
if( key.isEmpty() )
|
||||||
return; // ignore key
|
return; // ignore key
|
||||||
|
|
||||||
String valueStr = value.toString();
|
// exclude properties (1st level)
|
||||||
|
int dot = key.indexOf( '.' );
|
||||||
|
if( dot > 0 && uiKeyExcludesStartsWith.contains( key.substring( 0, dot + 1 ) ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// exclude properties (2st level)
|
||||||
|
int dot2 = (dot > 0) ? key.indexOf( '.', dot + 1 ) : -1;
|
||||||
|
if( dot2 > 0 && uiKeyExcludesStartsWith.contains( key.substring( 0, dot2 + 1 ) ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// exclude properties (contains)
|
||||||
|
for( String s : uiKeyExcludesContains ) {
|
||||||
|
if( key.contains( s ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uiKeyDoNotOverride.contains( key ) && jsonUIKeys.contains( key ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
jsonUIKeys.add( key );
|
||||||
|
|
||||||
|
String valueStr = value.toString().trim();
|
||||||
|
|
||||||
// map named colors
|
// map named colors
|
||||||
Object uiValue = namedColors.get( valueStr );
|
String uiValue = namedColors.get( valueStr );
|
||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
if( uiValue == null ) {
|
if( uiValue == null ) {
|
||||||
@@ -338,46 +465,64 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
try {
|
try {
|
||||||
uiValue = UIDefaultsLoader.parseValue( key, valueStr );
|
UIDefaultsLoader.parseValue( key, valueStr, null );
|
||||||
|
uiValue = valueStr;
|
||||||
} catch( RuntimeException ex ) {
|
} catch( RuntimeException ex ) {
|
||||||
UIDefaultsLoader.logParseError( key, valueStr, ex, false );
|
UIDefaultsLoader.logParseError( key, valueStr, ex, true );
|
||||||
return; // ignore invalid value
|
return; // ignore invalid value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( key.startsWith( "*." ) ) {
|
// wildcards
|
||||||
// wildcard
|
if( applyWildcard( properties, key, uiValue ) )
|
||||||
String tail = key.substring( 1 );
|
return;
|
||||||
|
|
||||||
// because we can not iterate over the UI defaults keys while
|
put( properties, key, uiValue );
|
||||||
// modifying UI defaults in the same loop, we have to copy the keys
|
|
||||||
if( defaultsKeysCache.size() != defaults.size() ) {
|
|
||||||
defaultsKeysCache.clear();
|
|
||||||
Enumeration<Object> e = defaults.keys();
|
|
||||||
while( e.hasMoreElements() )
|
|
||||||
defaultsKeysCache.add( e.nextElement() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace all values in UI defaults that match the wildcard key
|
|
||||||
for( Object k : defaultsKeysCache ) {
|
|
||||||
if( k.equals( "Desktop.background" ) ||
|
|
||||||
k.equals( "DesktopIcon.background" ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( k instanceof String ) {
|
|
||||||
// support replacing of mapped keys
|
|
||||||
// (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 ) && !((String)k).startsWith( "CheckBox.icon." ) )
|
|
||||||
defaults.put( k, uiValue );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
defaults.put( key, uiValue );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean applyWildcard( Properties properties, String key, String value ) {
|
||||||
|
if( !key.startsWith( "*." ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
String tail = key.substring( 1 );
|
||||||
|
|
||||||
|
// because we can not iterate over the properties keys while
|
||||||
|
// modifying properties in the same loop, we have to copy the keys
|
||||||
|
String[] keys = properties.keySet().toArray( new String[properties.size()] );
|
||||||
|
|
||||||
|
// replace all values in properties that match the wildcard key
|
||||||
|
for( String k : keys ) {
|
||||||
|
if( k.startsWith( "*" ) ||
|
||||||
|
k.startsWith( "@" ) ||
|
||||||
|
k.startsWith( "HelpButton." ) ||
|
||||||
|
k.startsWith( "JX" ) ||
|
||||||
|
k.startsWith( "Jide" ) ||
|
||||||
|
k.startsWith( "ProgressBar.selection" ) ||
|
||||||
|
k.startsWith( "TitlePane." ) ||
|
||||||
|
k.startsWith( "ToggleButton.tab." ) ||
|
||||||
|
k.equals( "Desktop.background" ) ||
|
||||||
|
k.equals( "DesktopIcon.background" ) ||
|
||||||
|
k.equals( "TabbedPane.focusColor" ) ||
|
||||||
|
k.endsWith( ".hoverBackground" ) ||
|
||||||
|
k.endsWith( ".pressedBackground" ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// support replacing of mapped keys
|
||||||
|
// (e.g. set ComboBox.buttonEditableBackground to *.background
|
||||||
|
// because it is mapped from ComboBox.ArrowButton.background)
|
||||||
|
String km = uiKeyInverseMapping.getOrDefault( k, k );
|
||||||
|
if( km.endsWith( tail ) && !k.startsWith( "CheckBox.icon." ) )
|
||||||
|
put( properties, k, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: also add wildcards to properties and let UIDefaultsLoader
|
||||||
|
// process it on BasicLookAndFeel UI defaults
|
||||||
|
put( properties, key, value );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private String fixColorIfValid( String newColorStr, String colorStr ) {
|
private String fixColorIfValid( String newColorStr, String colorStr ) {
|
||||||
try {
|
try {
|
||||||
// check whether it is valid
|
// check whether it is valid
|
||||||
@@ -389,11 +534,11 @@ public class IntelliJTheme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyColorPalette( UIDefaults defaults ) {
|
private void applyIconsColorPalette( Properties properties ) {
|
||||||
if( icons == null )
|
if( jsonIcons == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object palette = icons.get( "ColorPalette" );
|
Object palette = jsonIcons.get( "ColorPalette" );
|
||||||
if( !(palette instanceof Map) )
|
if( !(palette instanceof Map) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -402,36 +547,48 @@ public class IntelliJTheme
|
|||||||
for( Map.Entry<String, Object> e : colorPalette.entrySet() ) {
|
for( Map.Entry<String, Object> e : colorPalette.entrySet() ) {
|
||||||
String key = e.getKey();
|
String key = e.getKey();
|
||||||
Object value = e.getValue();
|
Object value = e.getValue();
|
||||||
if( key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
if( key.startsWith( "Checkbox." ) || key.startsWith( "#" ) || !(value instanceof String) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( dark )
|
if( dark )
|
||||||
key = StringUtils.removeTrailing( key, ".Dark" );
|
key = StringUtils.removeTrailing( key, ".Dark" );
|
||||||
|
|
||||||
ColorUIResource color = toColor( (String) value );
|
String color = toColor( (String) value );
|
||||||
if( color != null )
|
if( color != null )
|
||||||
defaults.put( key, color );
|
put( properties, key, color );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ColorUIResource toColor( String value ) {
|
private String toColor( String value ) {
|
||||||
|
if( value.startsWith( "##" ) )
|
||||||
|
value = fixColorIfValid( value.substring( 1 ), value );
|
||||||
|
|
||||||
// map named colors
|
// map named colors
|
||||||
ColorUIResource color = namedColors.get( value );
|
String color = namedColors.get( value );
|
||||||
|
|
||||||
// parse color
|
// parse color
|
||||||
return (color != null) ? color : UIDefaultsLoader.parseColor( value );
|
return (color != null) ? color : (canParseColor( value ) ? value : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canParseColor( String value ) {
|
||||||
|
try {
|
||||||
|
return UIDefaultsLoader.parseColor( value ) != null;
|
||||||
|
} catch( IllegalArgumentException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to parse color: '" + value + '\'', ex );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
* Because IDEA uses SVGs for check boxes and radio buttons, the colors for
|
||||||
* this two components are specified in "icons > ColorPalette".
|
* these two components are specified in "icons > ColorPalette".
|
||||||
* FlatLaf uses vector icons and expects colors for the two components in UI defaults.
|
* FlatLaf uses vector icons and expects colors for the two components in properties.
|
||||||
*/
|
*/
|
||||||
private void applyCheckBoxColors( UIDefaults defaults ) {
|
private void applyCheckBoxColors( Properties properties ) {
|
||||||
if( icons == null )
|
if( jsonIcons == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object palette = icons.get( "ColorPalette" );
|
Object palette = jsonIcons.get( "ColorPalette" );
|
||||||
if( !(palette instanceof Map) )
|
if( !(palette instanceof Map) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -444,18 +601,6 @@ public class IntelliJTheme
|
|||||||
if( !key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
if( !key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( key.equals( "Checkbox.Background.Default" ) ||
|
|
||||||
key.equals( "Checkbox.Foreground.Selected" ) )
|
|
||||||
{
|
|
||||||
// This two keys do not work correctly in IDEA because they
|
|
||||||
// map SVG color "#ffffff" to another color, but checkBox.svg and
|
|
||||||
// radio.svg (in package com.intellij.ide.ui.laf.icons.intellij)
|
|
||||||
// use "#fff". So use white to get same appearance as in IDEA.
|
|
||||||
value = "#ffffff";
|
|
||||||
}
|
|
||||||
|
|
||||||
String key2 = checkboxDuplicateColors.get( key );
|
|
||||||
|
|
||||||
if( dark )
|
if( dark )
|
||||||
key = StringUtils.removeTrailing( key, ".Dark" );
|
key = StringUtils.removeTrailing( key, ".Dark" );
|
||||||
|
|
||||||
@@ -465,10 +610,11 @@ public class IntelliJTheme
|
|||||||
if( !dark && newKey.startsWith( checkBoxIconPrefix ) )
|
if( !dark && newKey.startsWith( checkBoxIconPrefix ) )
|
||||||
newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) );
|
newKey = "CheckBox.icon[filled].".concat( newKey.substring( checkBoxIconPrefix.length() ) );
|
||||||
|
|
||||||
ColorUIResource color = toColor( (String) value );
|
String color = toColor( (String) value );
|
||||||
if( color != null ) {
|
if( color != null ) {
|
||||||
defaults.put( newKey, color );
|
put( properties, newKey, color );
|
||||||
|
|
||||||
|
String key2 = checkboxDuplicateColors.get( key + ".Dark");
|
||||||
if( key2 != null ) {
|
if( key2 != null ) {
|
||||||
// When IDEA replaces colors in SVGs it uses color values and not the keys
|
// 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
|
// from com.intellij.ide.ui.UITheme.colorPalette, but there are some keys that
|
||||||
@@ -487,7 +633,7 @@ public class IntelliJTheme
|
|||||||
|
|
||||||
String newKey2 = checkboxKeyMapping.get( key2 );
|
String newKey2 = checkboxKeyMapping.get( key2 );
|
||||||
if( newKey2 != null )
|
if( newKey2 != null )
|
||||||
defaults.put( newKey2, color );
|
put( properties, newKey2, color );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,52 +644,102 @@ public class IntelliJTheme
|
|||||||
// update hover, pressed and focused colors
|
// update hover, pressed and focused colors
|
||||||
if( checkboxModified ) {
|
if( checkboxModified ) {
|
||||||
// for non-filled checkbox/radiobutton used in dark themes
|
// for non-filled checkbox/radiobutton used in dark themes
|
||||||
defaults.remove( "CheckBox.icon.focusWidth" );
|
properties.remove( "CheckBox.icon.focusWidth" );
|
||||||
defaults.put( "CheckBox.icon.hoverBorderColor", defaults.get( "CheckBox.icon.focusedBorderColor" ) );
|
put( properties, "CheckBox.icon.hoverBorderColor", properties.get( "CheckBox.icon.focusedBorderColor" ) );
|
||||||
|
|
||||||
// for filled checkbox/radiobutton used in light themes
|
// for filled checkbox/radiobutton used in light themes
|
||||||
defaults.remove( "CheckBox.icon[filled].focusWidth" );
|
properties.remove( "CheckBox.icon[filled].focusWidth" );
|
||||||
defaults.put( "CheckBox.icon[filled].hoverBorderColor", defaults.get( "CheckBox.icon[filled].focusedBorderColor" ) );
|
put( properties, "CheckBox.icon[filled].hoverBorderColor", properties.get( "CheckBox.icon[filled].focusedBorderColor" ) );
|
||||||
defaults.put( "CheckBox.icon[filled].selectedFocusedBackground", defaults.get( "CheckBox.icon[filled].selectedBackground" ) );
|
put( properties, "CheckBox.icon[filled].focusedSelectedBackground", properties.get( "CheckBox.icon[filled].selectedBackground" ) );
|
||||||
|
|
||||||
if( dark ) {
|
if( dark ) {
|
||||||
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
|
// IDEA Darcula checkBoxFocused.svg, checkBoxSelectedFocused.svg,
|
||||||
// radioFocused.svg and radioSelectedFocused.svg
|
// radioFocused.svg and radioSelectedFocused.svg
|
||||||
// use opacity=".65" for the border
|
// use opacity=".65" for the border
|
||||||
// --> add alpha to focused border colors
|
// --> add alpha to focused border colors
|
||||||
String[] focusedBorderColorKeys = new String[] {
|
String[] focusedBorderColorKeys = {
|
||||||
"CheckBox.icon.focusedBorderColor",
|
"CheckBox.icon.focusedBorderColor",
|
||||||
"CheckBox.icon.selectedFocusedBorderColor",
|
"CheckBox.icon.focusedSelectedBorderColor",
|
||||||
"CheckBox.icon[filled].focusedBorderColor",
|
"CheckBox.icon[filled].focusedBorderColor",
|
||||||
"CheckBox.icon[filled].selectedFocusedBorderColor",
|
"CheckBox.icon[filled].focusedSelectedBorderColor",
|
||||||
};
|
};
|
||||||
for( String key : focusedBorderColorKeys ) {
|
for( String key : focusedBorderColorKeys ) {
|
||||||
Color color = defaults.getColor( key );
|
Object color = properties.get( key );
|
||||||
if( color != null ) {
|
if( color != null )
|
||||||
defaults.put( key, new ColorUIResource( new Color(
|
put( properties, key, "fade(" + color + ", 65%)" );
|
||||||
(color.getRGB() & 0xffffff) | 0xa6000000, true ) ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyIfNotSet( UIDefaults defaults, String destKey, String srcKey, Set<String> uiKeys ) {
|
private static final Set<String> uiKeyExcludesStartsWith;
|
||||||
if( !uiKeys.contains( destKey ) )
|
private static final String[] uiKeyExcludesContains;
|
||||||
defaults.put( destKey, defaults.get( srcKey ) );
|
private static final Set<String> uiKeyDoNotOverride;
|
||||||
}
|
|
||||||
|
|
||||||
/** Rename UI default keys (key --> value). */
|
/** Rename UI default keys (key --> value). */
|
||||||
private static Map<String, String> uiKeyMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyMapping = new HashMap<>();
|
||||||
/** Copy UI default keys (value --> key). */
|
/** Copy UI default keys (value --> key). */
|
||||||
private static Map<String, String> uiKeyCopying = new HashMap<>();
|
private static final Map<String, String> uiKeyCopying = new LinkedHashMap<>();
|
||||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
// IntelliJ UI properties that are not used in FlatLaf
|
||||||
|
uiKeyExcludesStartsWith = new HashSet<>( Arrays.asList(
|
||||||
|
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
|
||||||
|
"AvailableMnemonic.",
|
||||||
|
"Badge.", "Banner.", "BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
||||||
|
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
|
||||||
|
"Canvas.", "CellEditor.", "Code.", "CodeWithMe.", "ColumnControlButton.", "CombinedDiff.", "ComboBoxButton.",
|
||||||
|
"CompilationCharts.", "CompletionPopup.", "ComplexPopup.", "Content.", "ContextHelp.", "CurrentMnemonic.", "Counter.",
|
||||||
|
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.",
|
||||||
|
"DisclosureButton.", "DragAndDrop.",
|
||||||
|
"Editor.", "EditorGroupsTabs.", "EditorTabs.",
|
||||||
|
"FileColor.", "FindPopup.", "FlameGraph.", "Focus.",
|
||||||
|
"Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.",
|
||||||
|
"HeaderColor.", "HelpTooltip.", "Hg.",
|
||||||
|
"IconBadge.", "InformationHint.", "InlineBanner.", "InplaceRefactoringPopup.",
|
||||||
|
"Lesson.", "LineProfiler.", "Link.", "LiveIndicator.",
|
||||||
|
"MainMenu.", "MainToolbar.", "MainWindow.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
||||||
|
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
|
||||||
|
"OnePixelDivider.", "OptionButton.", "Outline.",
|
||||||
|
"ParameterInfo.", "PresentationAssistant.", "Plugins.", "Profiler.", "ProgressIcon.", "PsiViewer.",
|
||||||
|
"Resizable.", "Review.", "ReviewList.", "RunToolbar.", "RunWidget.",
|
||||||
|
"ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.",
|
||||||
|
"SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.",
|
||||||
|
"StatusBar.", "StripeToolbar.",
|
||||||
|
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.", "TrialWidget.",
|
||||||
|
"UIDesigner.", "UnattendedHostStatus.",
|
||||||
|
"ValidationTooltip.", "VersionControl.",
|
||||||
|
"WelcomeScreen.",
|
||||||
|
|
||||||
|
// lower case
|
||||||
|
"darcula.", "dropArea.", "icons.", "intellijlaf.", "macOSWindow.", "material.", "tooltips.",
|
||||||
|
|
||||||
|
// possible typos in .theme.json files
|
||||||
|
"Checkbox.", "Toolbar.", "Tooltip.", "UiDesigner.", "link."
|
||||||
|
) );
|
||||||
|
uiKeyExcludesContains = new String[] {
|
||||||
|
".darcula."
|
||||||
|
};
|
||||||
|
|
||||||
|
uiKeyDoNotOverride = new HashSet<>( Arrays.asList(
|
||||||
|
"TabbedPane.selectedForeground"
|
||||||
|
) );
|
||||||
|
|
||||||
|
// "*."
|
||||||
|
uiKeyMapping.put( "*.fontFace", "" ); // ignore (used in OnePauintxi themes)
|
||||||
|
uiKeyMapping.put( "*.fontSize", "" ); // ignore (used in OnePauintxi themes)
|
||||||
|
|
||||||
|
// Button
|
||||||
|
uiKeyMapping.put( "Button.minimumSize", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
|
// CheckBox.iconSize
|
||||||
|
uiKeyMapping.put( "CheckBox.iconSize", "" ); // ignore (used in Rider themes)
|
||||||
|
|
||||||
// ComboBox
|
// ComboBox
|
||||||
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
||||||
|
uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore
|
||||||
uiKeyMapping.put( "ComboBox.nonEditableBackground", "ComboBox.background" );
|
uiKeyMapping.put( "ComboBox.nonEditableBackground", "ComboBox.background" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.background", "ComboBox.buttonEditableBackground" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.background", "ComboBox.buttonEditableBackground" );
|
||||||
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
||||||
@@ -555,6 +751,11 @@ public class IntelliJTheme
|
|||||||
uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" );
|
uiKeyMapping.put( "Component.errorFocusColor", "Component.error.focusedBorderColor" );
|
||||||
uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" );
|
uiKeyMapping.put( "Component.inactiveWarningFocusColor", "Component.warning.borderColor" );
|
||||||
uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" );
|
uiKeyMapping.put( "Component.warningFocusColor", "Component.warning.focusedBorderColor" );
|
||||||
|
uiKeyMapping.put( "Component.inactiveSuccessFocusColor", "Component.success.borderColor" );
|
||||||
|
uiKeyMapping.put( "Component.successFocusColor", "Component.success.focusedBorderColor" );
|
||||||
|
|
||||||
|
// Label
|
||||||
|
uiKeyMapping.put( "Label.disabledForegroundColor", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
// Link
|
// Link
|
||||||
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
|
uiKeyMapping.put( "Link.activeForeground", "Component.linkColor" );
|
||||||
@@ -562,10 +763,7 @@ public class IntelliJTheme
|
|||||||
// Menu
|
// Menu
|
||||||
uiKeyMapping.put( "Menu.border", "Menu.margin" );
|
uiKeyMapping.put( "Menu.border", "Menu.margin" );
|
||||||
uiKeyMapping.put( "MenuItem.border", "MenuItem.margin" );
|
uiKeyMapping.put( "MenuItem.border", "MenuItem.margin" );
|
||||||
uiKeyCopying.put( "CheckBoxMenuItem.margin", "MenuItem.margin" );
|
|
||||||
uiKeyCopying.put( "RadioButtonMenuItem.margin", "MenuItem.margin" );
|
|
||||||
uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" );
|
uiKeyMapping.put( "PopupMenu.border", "PopupMenu.borderInsets" );
|
||||||
uiKeyCopying.put( "MenuItem.underlineSelectionColor", "TabbedPane.underlineColor" );
|
|
||||||
|
|
||||||
// IDEA uses List.selectionBackground also for menu selection
|
// IDEA uses List.selectionBackground also for menu selection
|
||||||
uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" );
|
uiKeyCopying.put( "Menu.selectionBackground", "List.selectionBackground" );
|
||||||
@@ -573,13 +771,14 @@ public class IntelliJTheme
|
|||||||
uiKeyCopying.put( "CheckBoxMenuItem.selectionBackground", "List.selectionBackground" );
|
uiKeyCopying.put( "CheckBoxMenuItem.selectionBackground", "List.selectionBackground" );
|
||||||
uiKeyCopying.put( "RadioButtonMenuItem.selectionBackground", "List.selectionBackground" );
|
uiKeyCopying.put( "RadioButtonMenuItem.selectionBackground", "List.selectionBackground" );
|
||||||
|
|
||||||
// ProgressBar
|
// ProgressBar: IDEA uses ProgressBar.trackColor and ProgressBar.progressColor
|
||||||
uiKeyMapping.put( "ProgressBar.background", "" ); // ignore
|
uiKeyMapping.put( "ProgressBar.background", "" ); // ignore
|
||||||
uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore
|
uiKeyMapping.put( "ProgressBar.foreground", "" ); // ignore
|
||||||
uiKeyMapping.put( "ProgressBar.trackColor", "ProgressBar.background" );
|
uiKeyMapping.put( "ProgressBar.trackColor", "ProgressBar.background" );
|
||||||
uiKeyMapping.put( "ProgressBar.progressColor", "ProgressBar.foreground" );
|
uiKeyMapping.put( "ProgressBar.progressColor", "ProgressBar.foreground" );
|
||||||
uiKeyCopying.put( "ProgressBar.selectionForeground", "ProgressBar.background" );
|
|
||||||
uiKeyCopying.put( "ProgressBar.selectionBackground", "ProgressBar.foreground" );
|
// RadioButton
|
||||||
|
uiKeyMapping.put( "RadioButton.iconSize", "" ); // ignore (used in Rider themes)
|
||||||
|
|
||||||
// ScrollBar
|
// ScrollBar
|
||||||
uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" );
|
uiKeyMapping.put( "ScrollBar.trackColor", "ScrollBar.track" );
|
||||||
@@ -589,25 +788,30 @@ public class IntelliJTheme
|
|||||||
uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" );
|
uiKeyMapping.put( "Separator.separatorColor", "Separator.foreground" );
|
||||||
|
|
||||||
// Slider
|
// Slider
|
||||||
|
uiKeyMapping.put( "Slider.buttonColor", "Slider.thumbColor" );
|
||||||
|
uiKeyMapping.put( "Slider.buttonBorderColor", "" ); // ignore
|
||||||
|
uiKeyMapping.put( "Slider.thumb", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
uiKeyMapping.put( "Slider.track", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
uiKeyMapping.put( "Slider.trackDisabled", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite)
|
uiKeyMapping.put( "Slider.trackWidth", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
uiKeyCopying.put( "Slider.trackValueColor", "ProgressBar.foreground" );
|
|
||||||
uiKeyCopying.put( "Slider.thumbColor", "ProgressBar.foreground" );
|
// TabbedPane
|
||||||
uiKeyCopying.put( "Slider.trackColor", "ProgressBar.background" );
|
uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" );
|
||||||
|
uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" );
|
||||||
|
uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" );
|
||||||
|
uiKeyMapping.put( "TabbedPane.tabAreaInsets", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
|
// TableHeader
|
||||||
|
uiKeyMapping.put( "TableHeader.cellBorder", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
uiKeyMapping.put( "TableHeader.height", "" ); // ignore (used in Material Theme UI Lite)
|
||||||
|
|
||||||
// TitlePane
|
// TitlePane
|
||||||
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
|
||||||
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
||||||
uiKeyMapping.put( "TitlePane.inactiveInfoForeground", "TitlePane.inactiveForeground" );
|
uiKeyMapping.put( "TitlePane.inactiveInfoForeground", "TitlePane.inactiveForeground" );
|
||||||
|
|
||||||
for( Map.Entry<String, String> e : uiKeyMapping.entrySet() )
|
for( Map.Entry<String, String> e : uiKeyMapping.entrySet() )
|
||||||
uiKeyInverseMapping.put( e.getValue(), e.getKey() );
|
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.Default", "CheckBox.icon.background" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" );
|
checkboxKeyMapping.put( "Checkbox.Background.Disabled", "CheckBox.icon.disabledBackground" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" );
|
checkboxKeyMapping.put( "Checkbox.Border.Default", "CheckBox.icon.borderColor" );
|
||||||
@@ -618,7 +822,7 @@ public class IntelliJTheme
|
|||||||
checkboxKeyMapping.put( "Checkbox.Background.Selected", "CheckBox.icon.selectedBackground" );
|
checkboxKeyMapping.put( "Checkbox.Background.Selected", "CheckBox.icon.selectedBackground" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Border.Selected", "CheckBox.icon.selectedBorderColor" );
|
checkboxKeyMapping.put( "Checkbox.Border.Selected", "CheckBox.icon.selectedBorderColor" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Foreground.Selected", "CheckBox.icon.checkmarkColor" );
|
checkboxKeyMapping.put( "Checkbox.Foreground.Selected", "CheckBox.icon.checkmarkColor" );
|
||||||
checkboxKeyMapping.put( "Checkbox.Focus.Thin.Selected", "CheckBox.icon.selectedFocusedBorderColor" );
|
checkboxKeyMapping.put( "Checkbox.Focus.Thin.Selected", "CheckBox.icon.focusedSelectedBorderColor" );
|
||||||
|
|
||||||
checkboxDuplicateColors.put( "Checkbox.Background.Default.Dark", "Checkbox.Background.Selected.Dark" );
|
checkboxDuplicateColors.put( "Checkbox.Background.Default.Dark", "Checkbox.Background.Selected.Dark" );
|
||||||
checkboxDuplicateColors.put( "Checkbox.Border.Default.Dark", "Checkbox.Border.Selected.Dark" );
|
checkboxDuplicateColors.put( "Checkbox.Border.Default.Dark", "Checkbox.Border.Selected.Dark" );
|
||||||
@@ -660,17 +864,15 @@ public class IntelliJTheme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void applyAdditionalDefaults( UIDefaults defaults ) {
|
void applyAdditionalProperties( Properties properties ) {
|
||||||
theme.applyProperties( defaults );
|
theme.applyProperties( properties );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
ArrayList<Class<?>> lafClasses = UIDefaultsLoader.getLafClassesForDefaultsLoading( getClass() );
|
||||||
lafClasses.add( FlatLaf.class );
|
lafClasses.add( 1, theme.dark ? FlatDarkLaf.class : FlatLightLaf.class );
|
||||||
lafClasses.add( theme.dark ? FlatDarkLaf.class : FlatLightLaf.class );
|
lafClasses.add( 2, theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
|
||||||
lafClasses.add( theme.dark ? FlatDarculaLaf.class : FlatIntelliJLaf.class );
|
|
||||||
lafClasses.add( ThemeLaf.class );
|
|
||||||
return lafClasses;
|
return lafClasses;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,22 @@
|
|||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
import java.awt.GraphicsConfiguration;
|
import java.awt.GraphicsConfiguration;
|
||||||
import java.awt.GraphicsEnvironment;
|
import java.awt.GraphicsEnvironment;
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import javax.swing.text.StyleContext;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
@@ -67,7 +71,7 @@ class LinuxFontPolicy
|
|||||||
if( word.endsWith( "," ) )
|
if( word.endsWith( "," ) )
|
||||||
word = word.substring( 0, word.length() - 1 ).trim();
|
word = word.substring( 0, word.length() - 1 ).trim();
|
||||||
|
|
||||||
String lword = word.toLowerCase();
|
String lword = word.toLowerCase( Locale.ENGLISH );
|
||||||
if( lword.equals( "italic" ) || lword.equals( "oblique" ) )
|
if( lword.equals( "italic" ) || lword.equals( "oblique" ) )
|
||||||
style |= Font.ITALIC;
|
style |= Font.ITALIC;
|
||||||
else if( lword.equals( "bold" ) )
|
else if( lword.equals( "bold" ) )
|
||||||
@@ -103,11 +107,11 @@ class LinuxFontPolicy
|
|||||||
size = 1;
|
size = 1;
|
||||||
|
|
||||||
// handle logical font names
|
// handle logical font names
|
||||||
String logicalFamily = mapFcName( family.toLowerCase() );
|
String logicalFamily = mapFcName( family.toLowerCase( Locale.ENGLISH ) );
|
||||||
if( logicalFamily != null )
|
if( logicalFamily != null )
|
||||||
family = logicalFamily;
|
family = logicalFamily;
|
||||||
|
|
||||||
return createFontEx( family, style, size, dsize );
|
return createFontEx( family, style, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,21 +121,32 @@ class LinuxFontPolicy
|
|||||||
* E.g. family 'URW Bookman Light' is not found, but 'URW Bookman' is found.
|
* E.g. family 'URW Bookman Light' is not found, but 'URW Bookman' is found.
|
||||||
* If still not found, then font of family 'Dialog' is returned.
|
* If still not found, then font of family 'Dialog' is returned.
|
||||||
*/
|
*/
|
||||||
private static Font createFontEx( String family, int style, int size, double dsize ) {
|
private static Font createFontEx( String family, int style, int size ) {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
Font font = createFont( family, style, size, dsize );
|
Font font = FlatLaf.createCompositeFont( family, style, size );
|
||||||
|
|
||||||
|
if( Font.DIALOG.equals( family ) )
|
||||||
|
return font;
|
||||||
|
|
||||||
// if the font family does not match any font on the system, "Dialog" family is returned
|
// if the font family does not match any font on the system, "Dialog" family is returned
|
||||||
if( !"Dialog".equals( font.getFamily() ) || "Dialog".equals( family ) )
|
if( !Font.DIALOG.equals( font.getFamily() ) ) {
|
||||||
|
// check for font problems
|
||||||
|
// - font height much larger than expected (e.g. font Inter; Oracle Java 8)
|
||||||
|
// - character width is zero (e.g. font Cantarell; Fedora; Oracle Java 8)
|
||||||
|
FontMetrics fm = StyleContext.getDefaultStyleContext().getFontMetrics( font );
|
||||||
|
if( fm.getHeight() > size * 2 || fm.stringWidth( "a" ) == 0 )
|
||||||
|
return FlatLaf.createCompositeFont( Font.DIALOG, style, size );
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
// find last word in family
|
// find last word in family
|
||||||
int index = family.lastIndexOf( ' ' );
|
int index = family.lastIndexOf( ' ' );
|
||||||
if( index < 0 )
|
if( index < 0 )
|
||||||
return createFont( "Dialog", style, size, dsize );;
|
return FlatLaf.createCompositeFont( Font.DIALOG, style, size );
|
||||||
|
|
||||||
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
||||||
String lastWord = family.substring( index + 1 ).toLowerCase();
|
String lastWord = family.substring( index + 1 ).toLowerCase( Locale.ENGLISH );
|
||||||
if( lastWord.contains( "bold" ) || lastWord.contains( "heavy" ) || lastWord.contains( "black" ) )
|
if( lastWord.contains( "bold" ) || lastWord.contains( "heavy" ) || lastWord.contains( "black" ) )
|
||||||
style |= Font.BOLD;
|
style |= Font.BOLD;
|
||||||
|
|
||||||
@@ -140,15 +155,6 @@ class LinuxFontPolicy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Font createFont( String family, int style, int size, double dsize ) {
|
|
||||||
Font font = FlatLaf.createCompositeFont( family, style, size );
|
|
||||||
|
|
||||||
// set font size in floating points
|
|
||||||
font = font.deriveFont( style, (float) dsize );
|
|
||||||
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double getGnomeFontScale() {
|
private static double getGnomeFontScale() {
|
||||||
// do not scale font here if JRE scales
|
// do not scale font here if JRE scales
|
||||||
if( isSystemScaling() )
|
if( isSystemScaling() )
|
||||||
@@ -158,7 +164,7 @@ class LinuxFontPolicy
|
|||||||
|
|
||||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
||||||
if( value instanceof Integer ) {
|
if( value instanceof Integer ) {
|
||||||
int dpi = ((Integer)value).intValue() / 1024;
|
int dpi = (Integer) value / 1024;
|
||||||
if( dpi == -1 )
|
if( dpi == -1 )
|
||||||
dpi = 96;
|
dpi = 96;
|
||||||
if( dpi < 50 )
|
if( dpi < 50 )
|
||||||
@@ -185,10 +191,10 @@ class LinuxFontPolicy
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default font for KDE for KDE configuration files.
|
* Gets the default font for KDE from KDE configuration files.
|
||||||
*
|
*
|
||||||
* The Swing fonts are not updated when the user changes system font size
|
* The Swing fonts are not updated when the user changes system font size
|
||||||
* (System Settings > Fonts > Force Font DPI). A application restart is necessary.
|
* (System Settings > Fonts > Force Font DPI). An application restart is necessary.
|
||||||
* This is the same behavior as in native KDE applications.
|
* This is the same behavior as in native KDE applications.
|
||||||
*
|
*
|
||||||
* The "display scale factor" (kdeglobals: [KScreen] > ScaleFactor) is not used
|
* The "display scale factor" (kdeglobals: [KScreen] > ScaleFactor) is not used
|
||||||
@@ -242,9 +248,10 @@ class LinuxFontPolicy
|
|||||||
if( size < 1 )
|
if( size < 1 )
|
||||||
size = 1;
|
size = 1;
|
||||||
|
|
||||||
return createFont( family, style, size, dsize );
|
return FlatLaf.createCompositeFont( family, style, size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "MixedMutabilityReturnType" ) // Error Prone
|
||||||
private static List<String> readConfig( String filename ) {
|
private static List<String> readConfig( String filename ) {
|
||||||
File userHome = new File( System.getProperty( "user.home" ) );
|
File userHome = new File( System.getProperty( "user.home" ) );
|
||||||
|
|
||||||
@@ -265,8 +272,10 @@ class LinuxFontPolicy
|
|||||||
|
|
||||||
// read config file
|
// read config file
|
||||||
ArrayList<String> lines = new ArrayList<>( 200 );
|
ArrayList<String> lines = new ArrayList<>( 200 );
|
||||||
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
try( BufferedReader reader = new BufferedReader( new InputStreamReader(
|
||||||
String line = null;
|
new FileInputStream( file ), StandardCharsets.US_ASCII ) ) )
|
||||||
|
{
|
||||||
|
String line;
|
||||||
while( (line = reader.readLine()) != null )
|
while( (line = reader.readLine()) != null )
|
||||||
lines.add( line );
|
lines.add( line );
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
@@ -309,6 +318,9 @@ class LinuxFontPolicy
|
|||||||
* - running on JetBrains Runtime 11 or later and scaling is enabled in system Settings
|
* - running on JetBrains Runtime 11 or later and scaling is enabled in system Settings
|
||||||
*/
|
*/
|
||||||
private static boolean isSystemScaling() {
|
private static boolean isSystemScaling() {
|
||||||
|
if( GraphicsEnvironment.isHeadless() )
|
||||||
|
return true;
|
||||||
|
|
||||||
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||||
.getDefaultScreenDevice().getDefaultConfiguration();
|
.getDefaultScreenDevice().getDefaultConfiguration();
|
||||||
return UIScale.getSystemScaleFactor( gc ) > 1;
|
return UIScale.getSystemScaleFactor( gc ) > 1;
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 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 java.awt.Component;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.awt.event.ComponentListener;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.MenuElement;
|
||||||
|
import javax.swing.MenuSelectionManager;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels (hides) popup menus on Linux.
|
||||||
|
* <p>
|
||||||
|
* On Linux, popups are not hidden under following conditions, which results in
|
||||||
|
* misplaced popups:
|
||||||
|
* <ul>
|
||||||
|
* <li>window moved or resized
|
||||||
|
* <li>window maximized or restored
|
||||||
|
* <li>window iconified
|
||||||
|
* <li>window deactivated (e.g. activated other application)
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* On Windows and macOS, popups are automatically hidden.
|
||||||
|
* <p>
|
||||||
|
* The implementation is similar to what's done in
|
||||||
|
* {@code javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber},
|
||||||
|
* but only hides popup in some conditions.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
class LinuxPopupMenuCanceler
|
||||||
|
extends WindowAdapter
|
||||||
|
implements ChangeListener, ComponentListener
|
||||||
|
{
|
||||||
|
private MenuElement[] lastPathSelectedPath;
|
||||||
|
private Window window;
|
||||||
|
|
||||||
|
LinuxPopupMenuCanceler() {
|
||||||
|
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
|
||||||
|
msm.addChangeListener( this );
|
||||||
|
|
||||||
|
lastPathSelectedPath = msm.getSelectedPath();
|
||||||
|
if( lastPathSelectedPath.length > 0 )
|
||||||
|
addWindowListeners( lastPathSelectedPath[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstall() {
|
||||||
|
MenuSelectionManager.defaultManager().removeChangeListener( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addWindowListeners( MenuElement selected ) {
|
||||||
|
removeWindowListeners();
|
||||||
|
|
||||||
|
// see BasicPopupMenuUI.MouseGrabber.grabWindow()
|
||||||
|
Component invoker = selected.getComponent();
|
||||||
|
if( invoker instanceof JPopupMenu )
|
||||||
|
invoker = ((JPopupMenu)invoker).getInvoker();
|
||||||
|
window = (invoker instanceof Window)
|
||||||
|
? (Window) invoker
|
||||||
|
: SwingUtilities.windowForComponent( invoker );
|
||||||
|
|
||||||
|
if( window != null ) {
|
||||||
|
window.addWindowListener( this );
|
||||||
|
window.addComponentListener( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeWindowListeners() {
|
||||||
|
if( window != null ) {
|
||||||
|
window.removeWindowListener( this );
|
||||||
|
window.removeComponentListener( this );
|
||||||
|
window = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelPopupMenu() {
|
||||||
|
try {
|
||||||
|
MenuSelectionManager msm = MenuSelectionManager.defaultManager();
|
||||||
|
MenuElement[] selectedPath = msm.getSelectedPath();
|
||||||
|
for( MenuElement e : selectedPath ) {
|
||||||
|
if( e instanceof JPopupMenu )
|
||||||
|
((JPopupMenu)e).putClientProperty( "JPopupMenu.firePopupMenuCanceled", true );
|
||||||
|
}
|
||||||
|
msm.clearSelectedPath();
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
removeWindowListeners();
|
||||||
|
throw ex;
|
||||||
|
} catch( Error ex ) {
|
||||||
|
removeWindowListeners();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- ChangeListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged( ChangeEvent e ) {
|
||||||
|
MenuElement[] selectedPath = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||||
|
|
||||||
|
if( selectedPath.length == 0 )
|
||||||
|
removeWindowListeners();
|
||||||
|
else if( lastPathSelectedPath.length == 0 )
|
||||||
|
addWindowListeners( selectedPath[0] );
|
||||||
|
|
||||||
|
lastPathSelectedPath = selectedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- WindowListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void windowIconified( WindowEvent e ) {
|
||||||
|
cancelPopupMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void windowDeactivated( WindowEvent e ) {
|
||||||
|
cancelPopupMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void windowClosing( WindowEvent e ) {
|
||||||
|
cancelPopupMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- ComponentListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentResized( ComponentEvent e ) {
|
||||||
|
cancelPopupMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentMoved( ComponentEvent e ) {
|
||||||
|
cancelPopupMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentShown( ComponentEvent e ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentHidden( ComponentEvent e ) {
|
||||||
|
cancelPopupMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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 java.awt.AWTEvent;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.MouseInfo;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.PointerInfo;
|
||||||
|
import java.awt.Polygon;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLayeredPane;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
import javax.swing.MenuElement;
|
||||||
|
import javax.swing.MenuSelectionManager;
|
||||||
|
import javax.swing.RootPaneContainer;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Improves usability of submenus by using a
|
||||||
|
* <a href="https://height.app/blog/guide-to-build-context-menus#safe-triangle">safe triangle</a>
|
||||||
|
* to avoid that the submenu closes while the user moves the mouse to it.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
class SubMenuUsabilityHelper
|
||||||
|
implements ChangeListener
|
||||||
|
{
|
||||||
|
private static final String KEY_USE_SAFE_TRIANGLE = "Menu.useSafeTriangle";
|
||||||
|
private static final String KEY_SHOW_SAFE_TRIANGLE = "FlatLaf.debug.menu.showSafeTriangle";
|
||||||
|
|
||||||
|
// Using a static field to ensure that there is only one instance in the system.
|
||||||
|
// Multiple instances would freeze the application.
|
||||||
|
// https://github.com/apache/netbeans/issues/4231#issuecomment-1179616607
|
||||||
|
private static SubMenuUsabilityHelper instance;
|
||||||
|
|
||||||
|
private boolean eventQueuePushNotSupported;
|
||||||
|
private SubMenuEventQueue subMenuEventQueue;
|
||||||
|
private SafeTrianglePainter safeTrianglePainter;
|
||||||
|
private boolean changePending;
|
||||||
|
|
||||||
|
// mouse location in screen coordinates
|
||||||
|
private int mouseX;
|
||||||
|
private int mouseY;
|
||||||
|
|
||||||
|
// target popup bounds in screen coordinates
|
||||||
|
private int targetX;
|
||||||
|
private int targetTopY;
|
||||||
|
private int targetBottomY;
|
||||||
|
|
||||||
|
private Rectangle invokerBounds;
|
||||||
|
|
||||||
|
static synchronized boolean install() {
|
||||||
|
if( instance != null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.USE_SUB_MENU_SAFE_TRIANGLE, true ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
instance = new SubMenuUsabilityHelper();
|
||||||
|
MenuSelectionManager.defaultManager().addChangeListener( instance );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static synchronized void uninstall() {
|
||||||
|
if( instance == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
MenuSelectionManager.defaultManager().removeChangeListener( instance );
|
||||||
|
instance.uninstallEventQueue();
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged( ChangeEvent e ) {
|
||||||
|
if( eventQueuePushNotSupported || !FlatUIUtils.getUIBoolean( KEY_USE_SAFE_TRIANGLE, true ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// handle menu selection change later, but only once in case of temporary changes
|
||||||
|
// e.g. moving mouse from one menu item to another one, fires two events:
|
||||||
|
// 1. old menu item is removed from menu selection
|
||||||
|
// 2. new menu item is added to menu selection
|
||||||
|
synchronized( this ) {
|
||||||
|
if( changePending )
|
||||||
|
return;
|
||||||
|
changePending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
synchronized( this ) {
|
||||||
|
changePending = false;
|
||||||
|
}
|
||||||
|
menuSelectionChanged();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void menuSelectionChanged() {
|
||||||
|
MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||||
|
|
||||||
|
/*debug
|
||||||
|
System.out.println( "--- " + path.length );
|
||||||
|
for( int i = 0; i < path.length; i++ )
|
||||||
|
System.out.println( " " + i + ": " + path[i].getClass().getName() );
|
||||||
|
debug*/
|
||||||
|
|
||||||
|
// find submenu in menu selection
|
||||||
|
int subMenuIndex = findSubMenu( path );
|
||||||
|
|
||||||
|
// uninstall if there is no submenu in selection
|
||||||
|
if( subMenuIndex < 0 || subMenuIndex != path.length - 1 ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get current mouse location
|
||||||
|
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
|
||||||
|
Point mouseLocation = (pointerInfo != null) ? pointerInfo.getLocation() : new Point();
|
||||||
|
mouseX = mouseLocation.x;
|
||||||
|
mouseY = mouseLocation.y;
|
||||||
|
|
||||||
|
// check whether popup is showing, which is e.g. not the case if it is empty
|
||||||
|
JPopupMenu popup = (JPopupMenu) path[subMenuIndex];
|
||||||
|
if( !popup.isShowing() ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get invoker screen bounds
|
||||||
|
Component invoker = popup.getInvoker();
|
||||||
|
invokerBounds = (invoker != null && invoker.isShowing())
|
||||||
|
? new Rectangle( invoker.getLocationOnScreen(), invoker.getSize() )
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// check whether mouse location is within invoker
|
||||||
|
if( invokerBounds != null && !invokerBounds.contains( mouseX, mouseY ) ) {
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute top/bottom target locations
|
||||||
|
Point popupLocation = popup.getLocationOnScreen();
|
||||||
|
Dimension popupSize = popup.getSize();
|
||||||
|
targetX = (mouseX < popupLocation.x + (popupSize.width / 2))
|
||||||
|
? popupLocation.x
|
||||||
|
: popupLocation.x + popupSize.width;
|
||||||
|
targetTopY = popupLocation.y;
|
||||||
|
targetBottomY = popupLocation.y + popupSize.height;
|
||||||
|
|
||||||
|
// install own event queue to suppress mouse events when mouse is moved within safe triangle
|
||||||
|
if( subMenuEventQueue == null ) {
|
||||||
|
SubMenuEventQueue queue = new SubMenuEventQueue();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||||
|
toolkit.getSystemEventQueue().push( queue );
|
||||||
|
|
||||||
|
// check whether push() worked
|
||||||
|
// (e.g. SWTSwing uses own event queue that does not support push())
|
||||||
|
if( toolkit.getSystemEventQueue() != queue ) {
|
||||||
|
eventQueuePushNotSupported = true;
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", null );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subMenuEventQueue = queue;
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
// catch runtime exception from EventQueue.push()
|
||||||
|
eventQueuePushNotSupported = true;
|
||||||
|
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to push submenu event queue. Disabling submenu safe triangle.", ex );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create safe triangle painter
|
||||||
|
if( safeTrianglePainter == null && UIManager.getBoolean( KEY_SHOW_SAFE_TRIANGLE ) )
|
||||||
|
safeTrianglePainter = new SafeTrianglePainter( popup );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uninstallEventQueue() {
|
||||||
|
if( subMenuEventQueue != null ) {
|
||||||
|
subMenuEventQueue.uninstall();
|
||||||
|
subMenuEventQueue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( safeTrianglePainter != null ) {
|
||||||
|
safeTrianglePainter.uninstall();
|
||||||
|
safeTrianglePainter = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findSubMenu( MenuElement[] path ) {
|
||||||
|
for( int i = path.length - 1; i >= 1; i-- ) {
|
||||||
|
if( path[i] instanceof JPopupMenu &&
|
||||||
|
path[i - 1] instanceof JMenu &&
|
||||||
|
!((JMenu)path[i - 1]).isTopLevelMenu() )
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Polygon createSafeTriangle() {
|
||||||
|
return new Polygon(
|
||||||
|
new int[] { mouseX, targetX, targetX },
|
||||||
|
new int[] { mouseY, targetTopY, targetBottomY },
|
||||||
|
3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class SubMenuEventQueue --------------------------------------------
|
||||||
|
|
||||||
|
private class SubMenuEventQueue
|
||||||
|
extends EventQueue
|
||||||
|
{
|
||||||
|
private Timer mouseUpdateTimer;
|
||||||
|
private Timer timeoutTimer;
|
||||||
|
|
||||||
|
private int newMouseX;
|
||||||
|
private int newMouseY;
|
||||||
|
private AWTEvent lastMouseEvent;
|
||||||
|
|
||||||
|
SubMenuEventQueue() {
|
||||||
|
// timer used to slightly delay update of mouse location used for safe triangle
|
||||||
|
mouseUpdateTimer = new Timer( 50, e -> {
|
||||||
|
mouseX = newMouseX;
|
||||||
|
mouseY = newMouseY;
|
||||||
|
|
||||||
|
if( safeTrianglePainter != null )
|
||||||
|
safeTrianglePainter.repaint();
|
||||||
|
} );
|
||||||
|
mouseUpdateTimer.setRepeats( false );
|
||||||
|
|
||||||
|
// timer used to timeout safe triangle when mouse stops moving
|
||||||
|
timeoutTimer = new Timer( 200, e -> {
|
||||||
|
if( invokerBounds != null && !invokerBounds.contains( newMouseX, newMouseY ) ) {
|
||||||
|
// post last mouse event, which selects menu item at mouse location
|
||||||
|
if( lastMouseEvent != null ) {
|
||||||
|
postEvent( lastMouseEvent );
|
||||||
|
lastMouseEvent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstallEventQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
timeoutTimer.setRepeats( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstall() {
|
||||||
|
mouseUpdateTimer.stop();
|
||||||
|
mouseUpdateTimer = null;
|
||||||
|
|
||||||
|
timeoutTimer.stop();
|
||||||
|
timeoutTimer = null;
|
||||||
|
|
||||||
|
lastMouseEvent = null;
|
||||||
|
|
||||||
|
super.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispatchEvent( AWTEvent e ) {
|
||||||
|
int id = e.getID();
|
||||||
|
|
||||||
|
if( e instanceof MouseEvent &&
|
||||||
|
(id == MouseEvent.MOUSE_MOVED || id == MouseEvent.MOUSE_DRAGGED) )
|
||||||
|
{
|
||||||
|
newMouseX = ((MouseEvent)e).getXOnScreen();
|
||||||
|
newMouseY = ((MouseEvent)e).getYOnScreen();
|
||||||
|
|
||||||
|
if( safeTrianglePainter != null )
|
||||||
|
safeTrianglePainter.repaint();
|
||||||
|
|
||||||
|
mouseUpdateTimer.stop();
|
||||||
|
timeoutTimer.stop();
|
||||||
|
|
||||||
|
// check whether mouse moved within safe triangle
|
||||||
|
if( createSafeTriangle().contains( newMouseX, newMouseY ) ) {
|
||||||
|
// update mouse location delayed (this changes the safe triangle)
|
||||||
|
mouseUpdateTimer.start();
|
||||||
|
|
||||||
|
timeoutTimer.start();
|
||||||
|
|
||||||
|
// remember last mouse event, which will be posted if the mouse stops moving
|
||||||
|
lastMouseEvent = e;
|
||||||
|
|
||||||
|
// ignore mouse event
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update mouse location immediately (this changes the safe triangle)
|
||||||
|
mouseX = newMouseX;
|
||||||
|
mouseY = newMouseY;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.dispatchEvent( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class SafeTrianglePainter ------------------------------------------
|
||||||
|
|
||||||
|
private class SafeTrianglePainter
|
||||||
|
extends JComponent
|
||||||
|
{
|
||||||
|
SafeTrianglePainter( JPopupMenu popup ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( popup.getInvoker() );
|
||||||
|
if( window instanceof RootPaneContainer ) {
|
||||||
|
JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
|
||||||
|
setSize( layeredPane.getSize() );
|
||||||
|
layeredPane.add( this, Integer.valueOf( JLayeredPane.POPUP_LAYER + 1 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstall() {
|
||||||
|
Container parent = getParent();
|
||||||
|
if( parent != null ) {
|
||||||
|
parent.remove( this );
|
||||||
|
parent.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent( Graphics g ) {
|
||||||
|
Point locationOnScreen = getLocationOnScreen();
|
||||||
|
g.translate( -locationOnScreen.x, -locationOnScreen.y );
|
||||||
|
|
||||||
|
g.setColor( Color.red );
|
||||||
|
((Graphics2D)g).draw( createSafeTriangle() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@ public abstract class FlatAbstractIcon
|
|||||||
{
|
{
|
||||||
protected final int width;
|
protected final int width;
|
||||||
protected final int height;
|
protected final int height;
|
||||||
protected final Color color;
|
protected Color color;
|
||||||
|
|
||||||
public FlatAbstractIcon( int width, int height, Color color ) {
|
public FlatAbstractIcon( int width, int height, Color color ) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@@ -57,6 +57,8 @@ public abstract class FlatAbstractIcon
|
|||||||
// g2.setColor( Color.blue );
|
// g2.setColor( Color.blue );
|
||||||
// g2.drawRect( x, y, getIconWidth() - 1, getIconHeight() - 1 );
|
// g2.drawRect( x, y, getIconWidth() - 1, getIconHeight() - 1 );
|
||||||
|
|
||||||
|
paintBackground( c, g2, x, y );
|
||||||
|
|
||||||
g2.translate( x, y );
|
g2.translate( x, y );
|
||||||
UIScale.scaleGraphics( g2 );
|
UIScale.scaleGraphics( g2 );
|
||||||
|
|
||||||
@@ -69,7 +71,11 @@ public abstract class FlatAbstractIcon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void paintIcon( Component c, Graphics2D g2 );
|
/** @since 3.5.2 */
|
||||||
|
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void paintIcon( Component c, Graphics2D g );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIconWidth() {
|
public int getIconWidth() {
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ import java.awt.Graphics2D;
|
|||||||
import com.formdev.flatlaf.util.AnimatedIcon;
|
import com.formdev.flatlaf.util.AnimatedIcon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for animated icons that scales width and height, creates and initializes
|
* Base class for animated icons that scale width and height, creates and initializes
|
||||||
* a scaled graphics context for icon painting.
|
* a scaled graphics context for icon painting.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses do not need to scale icon painting.
|
* Subclasses do not need to scale icon painting.
|
||||||
* <p>
|
* <p>
|
||||||
* This class does not store any state information (needed for animation) in its instance.
|
* This class does not store any state information (needed for animation) in its instance.
|
||||||
* Instead a client property is set on the painted component.
|
* Instead, a client property is set on the painted component.
|
||||||
* This makes it possible to use a share icon instance for multiple components.
|
* This makes it possible to use a share icon instance for multiple components.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.TableHeaderUI;
|
||||||
|
import javax.swing.table.JTableHeader;
|
||||||
|
import com.formdev.flatlaf.ui.FlatTableHeaderUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,8 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatAscendingSortIcon
|
public class FlatAscendingSortIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
protected boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
||||||
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
protected Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
||||||
|
|
||||||
public FlatAscendingSortIcon() {
|
public FlatAscendingSortIcon() {
|
||||||
super( 10, 5, null );
|
super( 10, 5, null );
|
||||||
@@ -44,7 +48,28 @@ public class FlatAscendingSortIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
boolean chevron = this.chevron;
|
||||||
|
Color sortIconColor = this.sortIconColor;
|
||||||
|
|
||||||
|
// Because this icon is always shared for all table headers,
|
||||||
|
// get icon specific style from FlatTableHeaderUI.
|
||||||
|
JTableHeader tableHeader = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
|
||||||
|
if( tableHeader != null ) {
|
||||||
|
TableHeaderUI ui = tableHeader.getUI();
|
||||||
|
if( ui instanceof FlatTableHeaderUI ) {
|
||||||
|
FlatTableHeaderUI fui = (FlatTableHeaderUI) ui;
|
||||||
|
if( fui.arrowType != null )
|
||||||
|
chevron = FlatUIUtils.isChevron( fui.arrowType );
|
||||||
|
if( fui.sortIconColor != null )
|
||||||
|
sortIconColor = fui.sortIconColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g.setColor( sortIconColor );
|
g.setColor( sortIconColor );
|
||||||
|
paintArrow( c, g, chevron );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
Path2D path = FlatUIUtils.createPath( false, 1,4, 5,0, 9,4 );
|
Path2D path = FlatUIUtils.createPath( false, 1,4, 5,0, 9,4 );
|
||||||
|
|||||||
@@ -16,12 +16,17 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Area;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,26 +39,51 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatCapsLockIcon
|
public class FlatCapsLockIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatCapsLockIcon() {
|
public FlatCapsLockIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
Object oldValue;
|
||||||
|
switch( key ) {
|
||||||
|
case "capsLockIconColor": oldValue = color; color = (Color) value; return oldValue;
|
||||||
|
default: throw new UnknownStyleException( key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
switch( key ) {
|
||||||
|
case "capsLockIconColor": return color;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||||
<rect width="6" height="2" x="5" y="12" fill="#FFF"/>
|
<rect width="5" height="2" x="5.5" y="11.5" stroke="#FFF" stroke-linejoin="round"/>
|
||||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
<path stroke="#FFF" stroke-linejoin="round" d="M2.5,7.5 L8,2 L13.5,7.5 L10.5,7.5 L10.5,9.5 L5.5,9.5 L5.5,7.5 L2.5,7.5 Z"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
BasicStroke stroke = new BasicStroke( 1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND );
|
||||||
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 );
|
if( path == null ) {
|
||||||
|
path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
||||||
|
path.append( new Area( stroke.createStrokedShape( new Rectangle2D.Float( 5.5f, 11.5f, 5, 2 ) ) ), false );
|
||||||
|
path.append( new Area( stroke.createStrokedShape( FlatUIUtils.createPath(
|
||||||
|
2.5,7.5, 8,2, 13.5,7.5, 10.5,7.5, 10.5,9.5, 5.5,9.5, 5.5,7.5, 2.5,7.5 ) ) ), false );
|
||||||
|
}
|
||||||
g.fill( path );
|
g.fill( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,89 +17,156 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
|
import static com.formdev.flatlaf.ui.FlatUIUtils.stateColor;
|
||||||
import java.awt.BasicStroke;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon for {@link javax.swing.JCheckBox}.
|
* Icon for {@link javax.swing.JCheckBox}.
|
||||||
*
|
* <p>
|
||||||
* Note: If Component.focusWidth is greater than zero, then the outline focus border
|
* <strong>Note</strong>:
|
||||||
|
* If Component.focusWidth is greater than zero, then the outer focus border
|
||||||
* is painted outside of the icon bounds. Make sure that the checkbox
|
* is painted outside of the icon bounds. Make sure that the checkbox
|
||||||
* has margins, which are equal or greater than focusWidth.
|
* has margins, which are equal or greater than focusWidth.
|
||||||
*
|
*
|
||||||
* @uiDefault CheckBox.icon.style String optional; "outline"/null (default) or "filled"
|
* @uiDefault CheckBox.icon.style String optional; "outlined"/null (default) or "filled"
|
||||||
* @uiDefault Component.focusWidth int
|
* @uiDefault Component.focusWidth int
|
||||||
|
* @uiDefault Component.borderWidth int
|
||||||
* @uiDefault Component.focusColor Color
|
* @uiDefault Component.focusColor Color
|
||||||
* @uiDefault CheckBox.icon.focusWidth int optional; defaults to Component.focusWidth
|
* @uiDefault CheckBox.icon.focusWidth int or float optional; defaults to Component.focusWidth
|
||||||
|
* @uiDefault CheckBox.icon.borderWidth int or float optional; defaults to Component.borderWidth
|
||||||
|
* @uiDefault CheckBox.icon.selectedBorderWidth int or float optional; defaults to CheckBox.icon.borderWidth
|
||||||
|
* @uiDefault CheckBox.icon.disabledSelectedBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth
|
||||||
|
* @uiDefault CheckBox.icon.indeterminateBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth
|
||||||
|
* @uiDefault CheckBox.icon.disabledIndeterminateBorderWidth int or float optional; defaults to CheckBox.icon.disabledSelectedBorderWidth
|
||||||
|
* @uiDefault CheckBox.arc int
|
||||||
|
*
|
||||||
* @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor
|
* @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor
|
||||||
* @uiDefault CheckBox.icon.borderColor Color
|
* @uiDefault CheckBox.icon.borderColor Color
|
||||||
* @uiDefault CheckBox.icon.background Color
|
* @uiDefault CheckBox.icon.background Color
|
||||||
* @uiDefault CheckBox.icon.selectedBorderColor Color
|
* @uiDefault CheckBox.icon.selectedBorderColor Color
|
||||||
* @uiDefault CheckBox.icon.selectedBackground Color
|
* @uiDefault CheckBox.icon.selectedBackground Color
|
||||||
* @uiDefault CheckBox.icon.checkmarkColor Color
|
* @uiDefault CheckBox.icon.checkmarkColor Color
|
||||||
* @uiDefault CheckBox.icon.disabledBorderColor Color
|
* @uiDefault CheckBox.icon.indeterminateBorderColor Color optional; defaults to CheckBox.icon.selectedBorderColor
|
||||||
* @uiDefault CheckBox.icon.disabledBackground Color
|
* @uiDefault CheckBox.icon.indeterminateBackground Color optional; defaults to CheckBox.icon.selectedBackground
|
||||||
* @uiDefault CheckBox.icon.disabledCheckmarkColor Color
|
* @uiDefault CheckBox.icon.indeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
|
||||||
* @uiDefault CheckBox.icon.focusedBorderColor Color optional
|
*
|
||||||
* @uiDefault CheckBox.icon.focusedBackground Color optional
|
* @uiDefault CheckBox.icon.disabledBorderColor Color
|
||||||
* @uiDefault CheckBox.icon.selectedFocusedBorderColor Color optional; CheckBox.icon.focusedBorderColor is used if not specified
|
* @uiDefault CheckBox.icon.disabledBackground Color
|
||||||
* @uiDefault CheckBox.icon.selectedFocusedBackground Color optional; CheckBox.icon.focusedBackground is used if not specified
|
* @uiDefault CheckBox.icon.disabledSelectedBorderColor Color optional; defaults to CheckBox.icon.disabledBorderColor
|
||||||
* @uiDefault CheckBox.icon.selectedFocusedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified
|
* @uiDefault CheckBox.icon.disabledSelectedBackground Color optional; defaults to CheckBox.icon.disabledBackground
|
||||||
* @uiDefault CheckBox.icon.hoverBorderColor Color optional
|
* @uiDefault CheckBox.icon.disabledCheckmarkColor Color
|
||||||
* @uiDefault CheckBox.icon.hoverBackground Color optional
|
* @uiDefault CheckBox.icon.disabledIndeterminateBorderColor Color optional; defaults to CheckBox.icon.disabledSelectedBorderColor
|
||||||
* @uiDefault CheckBox.icon.selectedHoverBackground Color optional; CheckBox.icon.hoverBackground is used if not specified
|
* @uiDefault CheckBox.icon.disabledIndeterminateBackground Color optional; defaults to CheckBox.icon.disabledSelectedBackground
|
||||||
* @uiDefault CheckBox.icon.pressedBackground Color optional
|
* @uiDefault CheckBox.icon.disabledIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.disabledCheckmarkColor
|
||||||
* @uiDefault CheckBox.icon.selectedPressedBackground Color optional; CheckBox.icon.pressedBackground is used if not specified
|
*
|
||||||
* @uiDefault CheckBox.arc int
|
* @uiDefault CheckBox.icon.focusedBorderColor Color optional
|
||||||
|
* @uiDefault CheckBox.icon.focusedBackground Color optional
|
||||||
|
* @uiDefault CheckBox.icon.focusedSelectedBorderColor Color optional; defaults to CheckBox.icon.focusedBorderColor
|
||||||
|
* @uiDefault CheckBox.icon.focusedSelectedBackground Color optional; defaults to CheckBox.icon.focusedBackground
|
||||||
|
* @uiDefault CheckBox.icon.focusedCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
|
||||||
|
* @uiDefault CheckBox.icon.focusedIndeterminateBorderColor Color optional; defaults to CheckBox.icon.focusedSelectedBorderColor
|
||||||
|
* @uiDefault CheckBox.icon.focusedIndeterminateBackground Color optional; defaults to CheckBox.icon.focusedSelectedBackground
|
||||||
|
* @uiDefault CheckBox.icon.focusedIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.focusedCheckmarkColor
|
||||||
|
*
|
||||||
|
* @uiDefault CheckBox.icon.hoverBorderColor Color optional
|
||||||
|
* @uiDefault CheckBox.icon.hoverBackground Color optional
|
||||||
|
* @uiDefault CheckBox.icon.hoverSelectedBorderColor Color optional; defaults to CheckBox.icon.hoverBorderColor
|
||||||
|
* @uiDefault CheckBox.icon.hoverSelectedBackground Color optional; defaults to CheckBox.icon.hoverBackground
|
||||||
|
* @uiDefault CheckBox.icon.hoverCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
|
||||||
|
* @uiDefault CheckBox.icon.hoverIndeterminateBorderColor Color optional; defaults to CheckBox.icon.hoverSelectedBorderColor
|
||||||
|
* @uiDefault CheckBox.icon.hoverIndeterminateBackground Color optional; defaults to CheckBox.icon.hoverSelectedBackground
|
||||||
|
* @uiDefault CheckBox.icon.hoverIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.hoverCheckmarkColor
|
||||||
|
*
|
||||||
|
* @uiDefault CheckBox.icon.pressedBorderColor Color optional
|
||||||
|
* @uiDefault CheckBox.icon.pressedBackground Color optional
|
||||||
|
* @uiDefault CheckBox.icon.pressedSelectedBorderColor Color optional; defaults to CheckBox.icon.pressedBorderColor
|
||||||
|
* @uiDefault CheckBox.icon.pressedSelectedBackground Color optional; defaults to CheckBox.icon.pressedBackground
|
||||||
|
* @uiDefault CheckBox.icon.pressedCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor
|
||||||
|
* @uiDefault CheckBox.icon.pressedIndeterminateBorderColor Color optional; defaults to CheckBox.icon.pressedSelectedBorderColor
|
||||||
|
* @uiDefault CheckBox.icon.pressedIndeterminateBackground Color optional; defaults to CheckBox.icon.pressedSelectedBackground
|
||||||
|
* @uiDefault CheckBox.icon.pressedIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.pressedCheckmarkColor
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatCheckBoxIcon
|
public class FlatCheckBoxIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final String style = UIManager.getString( "CheckBox.icon.style" );
|
protected final String style = UIManager.getString( getPropertyPrefix() + "icon.style" );
|
||||||
public final int focusWidth = getUIInt( "CheckBox.icon.focusWidth",
|
@Styleable protected float focusWidth = getUIFloat( "CheckBox.icon.focusWidth", UIManager.getInt( "Component.focusWidth" ), style );
|
||||||
UIManager.getInt( "Component.focusWidth" ), style );
|
@Styleable protected Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusColor", UIManager.getColor( "Component.focusColor" ) );
|
||||||
protected final Color focusColor = FlatUIUtils.getUIColor( "CheckBox.icon.focusColor",
|
/** @since 2 */ @Styleable protected float borderWidth = getUIFloat( "CheckBox.icon.borderWidth", FlatUIUtils.getUIFloat( "Component.borderWidth", 1 ), style );
|
||||||
UIManager.getColor( "Component.focusColor" ) );
|
/** @since 2 */ @Styleable protected float selectedBorderWidth = getUIFloat( "CheckBox.icon.selectedBorderWidth", Float.MIN_VALUE, style );
|
||||||
protected final int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
|
/** @since 2 */ @Styleable protected float disabledSelectedBorderWidth = getUIFloat( "CheckBox.icon.disabledSelectedBorderWidth", Float.MIN_VALUE, style );
|
||||||
|
/** @since 3.6 */ @Styleable protected float indeterminateBorderWidth = getUIFloat( "CheckBox.icon.indeterminateBorderWidth", Float.MIN_VALUE, style );
|
||||||
|
/** @since 3.6 */ @Styleable protected float disabledIndeterminateBorderWidth = getUIFloat( "CheckBox.icon.disabledIndeterminateBorderWidth", Float.MIN_VALUE, style );
|
||||||
|
@Styleable protected int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 );
|
||||||
|
|
||||||
// enabled
|
// enabled
|
||||||
protected final Color borderColor = getUIColor( "CheckBox.icon.borderColor", style );
|
@Styleable protected Color borderColor = getUIColor( "CheckBox.icon.borderColor", style );
|
||||||
protected final Color background = getUIColor( "CheckBox.icon.background", style );
|
@Styleable protected Color background = getUIColor( "CheckBox.icon.background", style );
|
||||||
protected final Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style );
|
@Styleable protected Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style );
|
||||||
protected final Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style );
|
@Styleable protected Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style );
|
||||||
protected final Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style );
|
@Styleable protected Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color indeterminateBorderColor = getUIColor( "CheckBox.icon.indeterminateBorderColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color indeterminateBackground = getUIColor( "CheckBox.icon.indeterminateBackground", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color indeterminateCheckmarkColor = getUIColor( "CheckBox.icon.indeterminateCheckmarkColor", style );
|
||||||
|
|
||||||
// disabled
|
// disabled
|
||||||
protected final Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style );
|
@Styleable protected Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style );
|
||||||
protected final Color disabledBackground = getUIColor( "CheckBox.icon.disabledBackground", style );
|
@Styleable protected Color disabledBackground = getUIColor( "CheckBox.icon.disabledBackground", style );
|
||||||
protected final Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style );
|
/** @since 2 */ @Styleable protected Color disabledSelectedBorderColor = getUIColor( "CheckBox.icon.disabledSelectedBorderColor", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color disabledSelectedBackground = getUIColor( "CheckBox.icon.disabledSelectedBackground", style );
|
||||||
|
@Styleable protected Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color disabledIndeterminateBorderColor = getUIColor( "CheckBox.icon.disabledIndeterminateBorderColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color disabledIndeterminateBackground = getUIColor( "CheckBox.icon.disabledIndeterminateBackground", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color disabledIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.disabledIndeterminateCheckmarkColor", style );
|
||||||
|
|
||||||
// focused
|
// focused
|
||||||
protected final Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style );
|
@Styleable protected Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style );
|
||||||
protected final Color focusedBackground = getUIColor( "CheckBox.icon.focusedBackground", style );
|
@Styleable protected Color focusedBackground = getUIColor( "CheckBox.icon.focusedBackground", style );
|
||||||
protected final Color selectedFocusedBorderColor = getUIColor( "CheckBox.icon.selectedFocusedBorderColor", style );
|
/** @since 2 */ @Styleable protected Color focusedSelectedBorderColor = getUIColor( "CheckBox.icon.focusedSelectedBorderColor", style );
|
||||||
protected final Color selectedFocusedBackground = getUIColor( "CheckBox.icon.selectedFocusedBackground", style );
|
/** @since 2 */ @Styleable protected Color focusedSelectedBackground = getUIColor( "CheckBox.icon.focusedSelectedBackground", style );
|
||||||
protected final Color selectedFocusedCheckmarkColor = getUIColor( "CheckBox.icon.selectedFocusedCheckmarkColor", style );
|
/** @since 2 */ @Styleable protected Color focusedCheckmarkColor = getUIColor( "CheckBox.icon.focusedCheckmarkColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color focusedIndeterminateBorderColor = getUIColor( "CheckBox.icon.focusedIndeterminateBorderColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color focusedIndeterminateBackground = getUIColor( "CheckBox.icon.focusedIndeterminateBackground", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color focusedIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.focusedIndeterminateCheckmarkColor", style );
|
||||||
|
|
||||||
// hover
|
// hover
|
||||||
protected final Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style );
|
@Styleable protected Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style );
|
||||||
protected final Color hoverBackground = getUIColor( "CheckBox.icon.hoverBackground", style );
|
@Styleable protected Color hoverBackground = getUIColor( "CheckBox.icon.hoverBackground", style );
|
||||||
protected final Color selectedHoverBackground = getUIColor( "CheckBox.icon.selectedHoverBackground", style );
|
/** @since 2 */ @Styleable protected Color hoverSelectedBorderColor = getUIColor( "CheckBox.icon.hoverSelectedBorderColor", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color hoverSelectedBackground = getUIColor( "CheckBox.icon.hoverSelectedBackground", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color hoverCheckmarkColor = getUIColor( "CheckBox.icon.hoverCheckmarkColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color hoverIndeterminateBorderColor = getUIColor( "CheckBox.icon.hoverIndeterminateBorderColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color hoverIndeterminateBackground = getUIColor( "CheckBox.icon.hoverIndeterminateBackground", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color hoverIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.hoverIndeterminateCheckmarkColor", style );
|
||||||
|
|
||||||
// pressed
|
// pressed
|
||||||
protected final Color pressedBackground = getUIColor( "CheckBox.icon.pressedBackground", style );
|
/** @since 2 */ @Styleable protected Color pressedBorderColor = getUIColor( "CheckBox.icon.pressedBorderColor", style );
|
||||||
protected final Color selectedPressedBackground = getUIColor( "CheckBox.icon.selectedPressedBackground", style );
|
@Styleable protected Color pressedBackground = getUIColor( "CheckBox.icon.pressedBackground", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color pressedSelectedBorderColor = getUIColor( "CheckBox.icon.pressedSelectedBorderColor", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color pressedSelectedBackground = getUIColor( "CheckBox.icon.pressedSelectedBackground", style );
|
||||||
|
/** @since 2 */ @Styleable protected Color pressedCheckmarkColor = getUIColor( "CheckBox.icon.pressedCheckmarkColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color pressedIndeterminateBorderColor = getUIColor( "CheckBox.icon.pressedIndeterminateBorderColor", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color pressedIndeterminateBackground = getUIColor( "CheckBox.icon.pressedIndeterminateBackground", style );
|
||||||
|
/** @since 3.6 */ @Styleable protected Color pressedIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.pressedIndeterminateCheckmarkColor", style );
|
||||||
|
|
||||||
|
protected String getPropertyPrefix() {
|
||||||
|
return "CheckBox.";
|
||||||
|
}
|
||||||
|
|
||||||
protected static Color getUIColor( String key, String style ) {
|
protected static Color getUIColor( String key, String style ) {
|
||||||
if( style != null ) {
|
if( style != null ) {
|
||||||
@@ -110,13 +177,14 @@ public class FlatCheckBoxIcon
|
|||||||
return UIManager.getColor( key );
|
return UIManager.getColor( key );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int getUIInt( String key, int defaultValue, String style ) {
|
/** @since 2 */
|
||||||
|
protected static float getUIFloat( String key, float defaultValue, String style ) {
|
||||||
if( style != null ) {
|
if( style != null ) {
|
||||||
Object value = UIManager.get( styleKey( key, style ) );
|
float value = FlatUIUtils.getUIFloat( styleKey( key, style ), Float.MIN_VALUE );
|
||||||
if( value instanceof Integer )
|
if( value != Float.MIN_VALUE )
|
||||||
return (Integer) value;
|
return value;
|
||||||
}
|
}
|
||||||
return FlatUIUtils.getUIInt( key, defaultValue );
|
return FlatUIUtils.getUIFloat( key, defaultValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String styleKey( String key, String style ) {
|
private static String styleKey( String key, String style ) {
|
||||||
@@ -129,11 +197,37 @@ public class FlatCheckBoxIcon
|
|||||||
super( ICON_SIZE, ICON_SIZE, null );
|
super( ICON_SIZE, ICON_SIZE, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
boolean indeterminate = isIndeterminate( c );
|
boolean indeterminate = isIndeterminate( c );
|
||||||
boolean selected = indeterminate || isSelected( c );
|
boolean selected = indeterminate || isSelected( c );
|
||||||
boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c );
|
boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c );
|
||||||
|
float bw = Float.MIN_VALUE;
|
||||||
|
if( !c.isEnabled() ) {
|
||||||
|
bw = (indeterminate && disabledIndeterminateBorderWidth != Float.MIN_VALUE)
|
||||||
|
? disabledIndeterminateBorderWidth
|
||||||
|
: (selected ? disabledSelectedBorderWidth : selectedBorderWidth);
|
||||||
|
}
|
||||||
|
if( bw == Float.MIN_VALUE ) {
|
||||||
|
bw = (indeterminate && indeterminateBorderWidth != Float.MIN_VALUE)
|
||||||
|
? indeterminateBorderWidth
|
||||||
|
: ((selected && selectedBorderWidth != Float.MIN_VALUE) ? selectedBorderWidth : borderWidth);
|
||||||
|
}
|
||||||
|
|
||||||
// paint focused border
|
// paint focused border
|
||||||
if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) {
|
if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) {
|
||||||
@@ -142,23 +236,23 @@ public class FlatCheckBoxIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// paint border
|
// paint border
|
||||||
g.setColor( getBorderColor( c, selected ) );
|
g.setColor( getBorderColor( c, selected, indeterminate ) );
|
||||||
paintBorder( c, g );
|
paintBorder( c, g, bw );
|
||||||
|
|
||||||
// paint background
|
// paint background
|
||||||
Color bg = FlatUIUtils.deriveColor( getBackground( c, selected ),
|
Color baseBg = stateColor( indeterminate, indeterminateBackground, selected, selectedBackground, background );
|
||||||
selected ? selectedBackground : background );
|
Color bg = FlatUIUtils.deriveColor( getBackground( c, selected, indeterminate ), baseBg );
|
||||||
if( bg.getAlpha() < 255 ) {
|
if( bg.getAlpha() < 255 ) {
|
||||||
// fill background with default color before filling with non-opaque background
|
// fill background with default color before filling with non-opaque background
|
||||||
g.setColor( selected ? selectedBackground : background );
|
g.setColor( baseBg );
|
||||||
paintBackground( c, g );
|
paintBackground( c, g, bw );
|
||||||
}
|
}
|
||||||
g.setColor( bg );
|
g.setColor( bg );
|
||||||
paintBackground( c, g );
|
paintBackground( c, g, bw );
|
||||||
|
|
||||||
// paint checkmark
|
// paint checkmark
|
||||||
if( selected || indeterminate ) {
|
if( selected ) {
|
||||||
g.setColor( getCheckmarkColor( c, selected, isFocused ) );
|
g.setColor( getCheckmarkColor( c, indeterminate ) );
|
||||||
if( indeterminate )
|
if( indeterminate )
|
||||||
paintIndeterminate( c, g );
|
paintIndeterminate( c, g );
|
||||||
else
|
else
|
||||||
@@ -167,24 +261,29 @@ public class FlatCheckBoxIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
||||||
// the outline focus border is painted outside of the icon
|
// the outer focus border is painted outside of the icon
|
||||||
int wh = ICON_SIZE - 1 + (focusWidth * 2);
|
float wh = ICON_SIZE - 1 + (focusWidth * 2);
|
||||||
int arcwh = arc + (focusWidth * 2);
|
float arcwh = arc + (focusWidth * 2);
|
||||||
g.fillRoundRect( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh );
|
g.fill( new RoundRectangle2D.Float( -focusWidth + 1, -focusWidth, wh, wh, arcwh, arcwh ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintBorder( Component c, Graphics2D g ) {
|
protected void paintBorder( Component c, Graphics2D g, float borderWidth ) {
|
||||||
|
if( borderWidth == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
int arcwh = arc;
|
int arcwh = arc;
|
||||||
g.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
|
g.fillRoundRect( 1, 0, 14, 14, arcwh, arcwh );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintBackground( Component c, Graphics2D g ) {
|
protected void paintBackground( Component c, Graphics2D g, float borderWidth ) {
|
||||||
int arcwh = arc - 1;
|
float xy = borderWidth;
|
||||||
g.fillRoundRect( 2, 1, 12, 12, arcwh, arcwh );
|
float wh = 14 - (borderWidth * 2);
|
||||||
|
float arcwh = arc - borderWidth;
|
||||||
|
g.fill( new RoundRectangle2D.Float( 1 + xy, xy, wh, wh, arcwh, arcwh ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void paintCheckmark( Component c, Graphics2D g ) {
|
protected void paintCheckmark( Component c, Graphics2D g ) {
|
||||||
Path2D.Float path = new Path2D.Float();
|
Path2D.Float path = new Path2D.Float( Path2D.WIND_NON_ZERO, 3 );
|
||||||
path.moveTo( 4.5f, 7.5f );
|
path.moveTo( 4.5f, 7.5f );
|
||||||
path.lineTo( 6.6f, 10f );
|
path.lineTo( 6.6f, 10f );
|
||||||
path.lineTo( 11.25f, 3.5f );
|
path.lineTo( 11.25f, 3.5f );
|
||||||
@@ -205,33 +304,42 @@ public class FlatCheckBoxIcon
|
|||||||
return c instanceof AbstractButton && ((AbstractButton)c).isSelected();
|
return c instanceof AbstractButton && ((AbstractButton)c).isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public float getFocusWidth() {
|
||||||
|
return focusWidth;
|
||||||
|
}
|
||||||
|
|
||||||
protected Color getFocusColor( Component c ) {
|
protected Color getFocusColor( Component c ) {
|
||||||
return focusColor;
|
return focusColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getBorderColor( Component c, boolean selected ) {
|
/** @since 3.6 */
|
||||||
|
protected Color getBorderColor( Component c, boolean selected, boolean indeterminate ) {
|
||||||
return FlatButtonUI.buttonStateColor( c,
|
return FlatButtonUI.buttonStateColor( c,
|
||||||
selected ? selectedBorderColor : borderColor,
|
stateColor( indeterminate, indeterminateBorderColor, selected, selectedBorderColor, borderColor ),
|
||||||
disabledBorderColor,
|
stateColor( indeterminate, disabledIndeterminateBorderColor, selected, disabledSelectedBorderColor, disabledBorderColor ),
|
||||||
selected && selectedFocusedBorderColor != null ? selectedFocusedBorderColor : focusedBorderColor,
|
stateColor( indeterminate, focusedIndeterminateBorderColor, selected, focusedSelectedBorderColor, focusedBorderColor ),
|
||||||
hoverBorderColor,
|
stateColor( indeterminate, hoverIndeterminateBorderColor, selected, hoverSelectedBorderColor, hoverBorderColor ),
|
||||||
null );
|
stateColor( indeterminate, pressedIndeterminateBorderColor, selected, pressedSelectedBorderColor, pressedBorderColor ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getBackground( Component c, boolean selected ) {
|
/** @since 3.6 */
|
||||||
|
protected Color getBackground( Component c, boolean selected, boolean indeterminate ) {
|
||||||
return FlatButtonUI.buttonStateColor( c,
|
return FlatButtonUI.buttonStateColor( c,
|
||||||
selected ? selectedBackground : background,
|
stateColor( indeterminate, indeterminateBackground, selected, selectedBackground, background ),
|
||||||
disabledBackground,
|
stateColor( indeterminate, disabledIndeterminateBackground, selected, disabledSelectedBackground, disabledBackground ),
|
||||||
(selected && selectedFocusedBackground != null) ? selectedFocusedBackground : focusedBackground,
|
stateColor( indeterminate, focusedIndeterminateBackground, selected, focusedSelectedBackground, focusedBackground ),
|
||||||
(selected && selectedHoverBackground != null) ? selectedHoverBackground : hoverBackground,
|
stateColor( indeterminate, hoverIndeterminateBackground, selected, hoverSelectedBackground, hoverBackground ),
|
||||||
(selected && selectedPressedBackground != null) ? selectedPressedBackground : pressedBackground );
|
stateColor( indeterminate, pressedIndeterminateBackground, selected, pressedSelectedBackground, pressedBackground ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getCheckmarkColor( Component c, boolean selected, boolean isFocused ) {
|
/** @since 3.6 */
|
||||||
return c.isEnabled()
|
protected Color getCheckmarkColor( Component c, boolean indeterminate ) {
|
||||||
? ((selected && isFocused && selectedFocusedCheckmarkColor != null)
|
return FlatButtonUI.buttonStateColor( c,
|
||||||
? selectedFocusedCheckmarkColor
|
stateColor( indeterminate, indeterminateCheckmarkColor, checkmarkColor ),
|
||||||
: checkmarkColor)
|
stateColor( indeterminate, disabledIndeterminateCheckmarkColor, disabledCheckmarkColor ),
|
||||||
: disabledCheckmarkColor;
|
stateColor( indeterminate, focusedIndeterminateCheckmarkColor, focusedCheckmarkColor ),
|
||||||
|
stateColor( indeterminate, hoverIndeterminateCheckmarkColor, hoverCheckmarkColor ),
|
||||||
|
stateColor( indeterminate, pressedIndeterminateCheckmarkColor, pressedCheckmarkColor ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,15 +21,18 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon for {@link javax.swing.JCheckBoxMenuItem}.
|
* Icon for {@link javax.swing.JCheckBoxMenuItem}.
|
||||||
*
|
*
|
||||||
* @uiDefault MenuItemCheckBox.icon.checkmarkColor Color
|
* @uiDefault CheckBoxMenuItem.icon.checkmarkColor Color
|
||||||
* @uiDefault MenuItemCheckBox.icon.disabledCheckmarkColor Color
|
* @uiDefault CheckBoxMenuItem.icon.disabledCheckmarkColor Color
|
||||||
* @uiDefault MenuItem.selectionForeground Color
|
* @uiDefault MenuItem.selectionForeground Color
|
||||||
* @uiDefault MenuItem.selectionType String
|
* @uiDefault MenuItem.selectionType String
|
||||||
*
|
*
|
||||||
@@ -38,14 +41,29 @@ import javax.swing.UIManager;
|
|||||||
public class FlatCheckBoxMenuItemIcon
|
public class FlatCheckBoxMenuItemIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final Color checkmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.checkmarkColor" );
|
@Styleable protected Color checkmarkColor = UIManager.getColor( "CheckBoxMenuItem.icon.checkmarkColor" );
|
||||||
protected final Color disabledCheckmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.disabledCheckmarkColor" );
|
@Styleable protected Color disabledCheckmarkColor = UIManager.getColor( "CheckBoxMenuItem.icon.disabledCheckmarkColor" );
|
||||||
protected final Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );
|
@Styleable protected Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );
|
||||||
|
|
||||||
public FlatCheckBoxMenuItemIcon() {
|
public FlatCheckBoxMenuItemIcon() {
|
||||||
super( 15, 15, null );
|
super( 15, 15, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||||
boolean selected = (c instanceof AbstractButton) && ((AbstractButton)c).isSelected();
|
boolean selected = (c instanceof AbstractButton) && ((AbstractButton)c).isSelected();
|
||||||
@@ -58,7 +76,7 @@ public class FlatCheckBoxMenuItemIcon
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintCheckmark( Graphics2D g2 ) {
|
protected void paintCheckmark( Graphics2D g2 ) {
|
||||||
Path2D.Float path = new Path2D.Float();
|
Path2D.Float path = new Path2D.Float( Path2D.WIND_NON_ZERO, 3 );
|
||||||
path.moveTo( 4.5f, 7.5f );
|
path.moveTo( 4.5f, 7.5f );
|
||||||
path.lineTo( 6.6f, 10f );
|
path.lineTo( 6.6f, 10f );
|
||||||
path.lineTo( 11.25f, 3.5f );
|
path.lineTo( 11.25f, 3.5f );
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.ButtonModel;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "clear" icon for search fields.
|
||||||
|
*
|
||||||
|
* @uiDefault SearchField.clearIconColor Color
|
||||||
|
* @uiDefault SearchField.clearIconHoverColor Color
|
||||||
|
* @uiDefault SearchField.clearIconPressedColor Color
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public class FlatClearIcon
|
||||||
|
extends FlatAbstractIcon
|
||||||
|
{
|
||||||
|
@Styleable protected Color clearIconColor = UIManager.getColor( "SearchField.clearIconColor" );
|
||||||
|
@Styleable protected Color clearIconHoverColor = UIManager.getColor( "SearchField.clearIconHoverColor" );
|
||||||
|
@Styleable protected Color clearIconPressedColor = UIManager.getColor( "SearchField.clearIconPressedColor" );
|
||||||
|
|
||||||
|
private final boolean ignoreButtonState;
|
||||||
|
|
||||||
|
public FlatClearIcon() {
|
||||||
|
this( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public FlatClearIcon( boolean ignoreButtonState ) {
|
||||||
|
super( 16, 16, null );
|
||||||
|
this.ignoreButtonState = ignoreButtonState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
if( !ignoreButtonState && c instanceof AbstractButton ) {
|
||||||
|
ButtonModel model = ((AbstractButton)c).getModel();
|
||||||
|
if( model.isPressed() || model.isRollover() ) {
|
||||||
|
/*
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
|
<path fill="#7F8B91" fill-opacity=".5" fill-rule="evenodd" d="M8,1.75 C11.4517797,1.75 14.25,4.54822031 14.25,8 C14.25,11.4517797 11.4517797,14.25 8,14.25 C4.54822031,14.25 1.75,11.4517797 1.75,8 C1.75,4.54822031 4.54822031,1.75 8,1.75 Z M10.5,4.5 L8,7 L5.5,4.5 L4.5,5.5 L7,8 L4.5,10.5 L5.5,11.5 L8,9 L10.5,11.5 L11.5,10.5 L9,8 L11.5,5.5 L10.5,4.5 Z"/>
|
||||||
|
</svg>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// paint filled circle with cross
|
||||||
|
g.setColor( model.isPressed() ? clearIconPressedColor : clearIconHoverColor );
|
||||||
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path.append( new Ellipse2D.Float( 1.75f, 1.75f, 12.5f, 12.5f ), false );
|
||||||
|
path.append( FlatUIUtils.createPath( 4.5,5.5, 5.5,4.5, 8,7, 10.5,4.5, 11.5,5.5, 9,8, 11.5,10.5, 10.5,11.5, 8,9, 5.5,11.5, 4.5,10.5, 7,8 ), false );
|
||||||
|
g.fill( path );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
|
<path fill="none" stroke="#7F8B91" stroke-linecap="square" stroke-opacity=".5" d="M5,5 L11,11 M5,11 L11,5"/>
|
||||||
|
</svg>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// paint cross
|
||||||
|
g.setColor( clearIconColor );
|
||||||
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
|
path.moveTo( 5, 5 );
|
||||||
|
path.lineTo( 11, 11 );
|
||||||
|
path.moveTo( 5, 11 );
|
||||||
|
path.lineTo( 11, 5 );
|
||||||
|
g.draw( path );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,11 +17,9 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,18 +31,14 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatDescendingSortIcon
|
public class FlatDescendingSortIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAscendingSortIcon
|
||||||
{
|
{
|
||||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
|
||||||
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
|
|
||||||
|
|
||||||
public FlatDescendingSortIcon() {
|
public FlatDescendingSortIcon() {
|
||||||
super( 10, 5, null );
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
|
||||||
g.setColor( sortIconColor );
|
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
Path2D path = FlatUIUtils.createPath( false, 1,0, 5,4, 9,0 );
|
Path2D path = FlatUIUtils.createPath( false, 1,0, 5,4, 9,0 );
|
||||||
|
|||||||
@@ -39,21 +39,25 @@ public class FlatFileChooserDetailsViewIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="2" height="2" x="2" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="7" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="2" height="2" x="2" y="11" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="3" fill="#6E6E6E"/>
|
<rect width="2" height="1" x="2" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="7" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="3" fill="#6E6E6E" rx=".5"/>
|
||||||
<rect width="8" height="2" x="6" y="11" fill="#6E6E6E"/>
|
<rect width="8" height="1" x="6" y="6" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="9" fill="#6E6E6E" rx=".5"/>
|
||||||
|
<rect width="8" height="1" x="6" y="12" fill="#6E6E6E" rx=".5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fillRect( 2, 3, 2, 2 );
|
g.fillRoundRect( 2, 3, 2, 1, 1, 1 );
|
||||||
g.fillRect( 2, 7, 2, 2 );
|
g.fillRoundRect( 2, 6, 2, 1, 1, 1 );
|
||||||
g.fillRect( 2, 11, 2, 2 );
|
g.fillRoundRect( 2, 9, 2, 1, 1, 1 );
|
||||||
g.fillRect( 6, 3, 8, 2 );
|
g.fillRoundRect( 2, 12, 2, 1, 1, 1 );
|
||||||
g.fillRect( 6, 7, 8, 2 );
|
g.fillRoundRect( 6, 3, 8, 1, 1, 1 );
|
||||||
g.fillRect( 6, 11, 8, 2 );
|
g.fillRoundRect( 6, 6, 8, 1, 1, 1 );
|
||||||
|
g.fillRoundRect( 6, 9, 8, 1, 1, 1 );
|
||||||
|
g.fillRoundRect( 6, 12, 8, 1, 1, 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -39,10 +41,22 @@ public class FlatFileChooserHomeFolderIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="2 8 8 2 14 8 12 8 12 13 9 13 9 10 7 10 7 13 4 13 4 8"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linejoin="round" points="6.5 13 6.5 9.5 9.5 9.5 9.5 13"/>
|
||||||
|
<path stroke="#6E6E6E" d="M3.5,6.5 L3.5,12.5 C3.5,13.0522847 3.94771525,13.5 4.5,13.5 L11.5,13.5 C12.0522847,13.5 12.5,13.0522847 12.5,12.5 L12.5,6.5 L12.5,6.5"/>
|
||||||
|
<polyline stroke="#6E6E6E" stroke-linecap="round" stroke-linejoin="round" points="1.5 8.5 8 2 14.5 8.5"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 12,8, 12,13, 9,13, 9,10, 7,10, 7,13, 4,13, 4,8 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 6.5,13, 6.5,9.5, 9.5,9.5, 9.5,13 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 3.5,6.5,
|
||||||
|
3.5,12.5, FlatUIUtils.QUAD_TO, 3.5,13.5, 4.5,13.5,
|
||||||
|
11.5,13.5, FlatUIUtils.QUAD_TO, 12.5,13.5, 12.5,12.5,
|
||||||
|
12.5,6.5 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 1.5,8.5, 8,2, 14.5,8.5 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,17 +42,20 @@ public class FlatFileChooserListViewIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<rect width="4" height="4" x="3" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="3" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="2.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="9" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<rect width="4" height="4" x="9" y="3" fill="#6E6E6E"/>
|
<rect width="4" height="4" x="9.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fillRect( 3, 3, 4, 4 );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fillRect( 3, 9, 4, 4 );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
g.fillRect( 9, 9, 4, 4 );
|
|
||||||
g.fillRect( 9, 3, 4, 4 );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 2.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 2.5f, 9.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 9.5f, 9.5f, 4, 4, 2, 2 ) );
|
||||||
|
g.draw( new RoundRectangle2D.Float( 9.5f, 2.5f, 4, 4, 2, 2 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,13 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "new folder" icon for {@link javax.swing.JFileChooser}.
|
* "new folder" icon for {@link javax.swing.JFileChooser}.
|
||||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileChooserNewFolderIcon
|
public class FlatFileChooserNewFolderIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private final Color greenColor = UIManager.getColor( "Actions.Green" );
|
||||||
|
|
||||||
public FlatFileChooserNewFolderIcon() {
|
public FlatFileChooserNewFolderIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Actions.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Actions.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -40,13 +45,20 @@ public class FlatFileChooserNewFolderIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 14 5 14 8 11 8 11 10 9 10 9 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#59A869" d="M14,11 L16,11 L16,13 L14,13 L14,15 L12,15 L12,13 L10,13 L10,11 L12,11 L12,9 L14,9 L14,11 Z"/>
|
<line x1="5.5" x2="10.5" y1="9" y2="9" stroke="#59A869" stroke-linecap="round"/>
|
||||||
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#59A869" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,3, 5.5,3, 7,5, 14,5, 14,8, 11,8, 11,10, 9,10, 9,13, 2,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 14,11, 16,11, 16,13, 14,13, 14,15, 12,15, 12,13, 10,13, 10,11, 12,11, 12,9, 14,9, 14,11 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatFileViewDirectoryIcon.createFolderPath() );
|
||||||
|
|
||||||
|
g.setColor( greenColor );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 9, 10.5f, 9 ) );
|
||||||
|
g.draw( new Line2D.Float( 8, 6.5f, 8, 11.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -44,15 +47,20 @@ public class FlatFileChooserUpFolderIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="2 3 5.5 3 7 5 9 5 9 9 13 9 13 5 14 5 14 13 2 13"/>
|
<path stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
<path fill="#389FD6" d="M12,4 L12,8 L10,8 L10,4 L8,4 L11,1 L14,4 L12,4 Z"/>
|
<line x1="8" x2="8" y1="6.5" y2="11.5" stroke="#389FD6" stroke-linecap="round"/>
|
||||||
|
<polyline stroke="#389FD6" stroke-linecap="round" stroke-linejoin="round" points="5.5 9 8 6.5 10.5 9"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 2,3, 5.5,3, 7,5, 9,5, 9,9, 13,9, 13,5, 14,5, 14,13, 2,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( FlatFileViewDirectoryIcon.createFolderPath() );
|
||||||
|
|
||||||
g.setColor( blueColor );
|
g.setColor( blueColor );
|
||||||
g.fill( FlatUIUtils.createPath( 12,4, 12,8, 10,8, 10,4, 8,4, 11,1, 14,4, 12,4 ) );
|
g.draw( new Line2D.Float( 8, 6.5f, 8, 11.5f ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 5.5,9, 8,6.5, 10.5,9 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,17 +43,18 @@ public class FlatFileViewComputerIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<path fill="#6E6E6E" d="M2,3 L14,3 L14,11 L2,11 L2,3 Z M4,5 L4,9 L12,9 L12,5 L4,5 Z"/>
|
<rect width="11" height="7" x="2.5" y="3.5" stroke="#6E6E6E" rx="1"/>
|
||||||
<rect width="12" height="2" x="2" y="12" fill="#6E6E6E"/>
|
<line x1="8" x2="8" y1="11" y2="12" stroke="#6E6E6E"/>
|
||||||
|
<line x1="4.5" x2="11.5" y1="12.5" y2="12.5" stroke="#6E6E6E" stroke-linecap="round"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new Rectangle2D.Float( 2, 3, 12, 8 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( new Rectangle2D.Float( 4, 5, 8, 4 ), false );
|
|
||||||
g.fill( path );
|
|
||||||
|
|
||||||
g.fillRect( 2, 12, 12, 2 );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 3.5f, 11, 7, 2, 2 ) );
|
||||||
|
g.drawLine( 8, 11, 8, 12 );
|
||||||
|
g.draw( new Line2D.Float( 4.5f, 12.5f, 11.5f, 12.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,6 +33,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileViewDirectoryIcon
|
public class FlatFileViewDirectoryIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatFileViewDirectoryIcon() {
|
public FlatFileViewDirectoryIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -39,10 +43,32 @@ public class FlatFileViewDirectoryIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="1 2 6 2 8 4 15 4 15 13 1 13"/>
|
<path fill="none" stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 15,4, 15,13, 1,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
if( path == null )
|
||||||
|
path = createFolderPath();
|
||||||
|
g.draw( path );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Path2D createFolderPath() {
|
||||||
|
double arc = 1.5;
|
||||||
|
double arc2 = 0.5;
|
||||||
|
return FlatUIUtils.createPath(
|
||||||
|
// bottom-right
|
||||||
|
14.5,13.5-arc, FlatUIUtils.QUAD_TO, 14.5,13.5, 14.5-arc,13.5,
|
||||||
|
// bottom-left
|
||||||
|
1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc,
|
||||||
|
// top-left
|
||||||
|
1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5,
|
||||||
|
// top-mid-left
|
||||||
|
6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2,
|
||||||
|
// top-mid-right
|
||||||
|
8.5,4.5,
|
||||||
|
// top-right
|
||||||
|
14.5-arc,4.5, FlatUIUtils.QUAD_TO, 14.5,4.5, 14.5,4.5+arc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatFileViewFileIcon
|
public class FlatFileViewFileIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatFileViewFileIcon() {
|
public FlatFileViewFileIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||||
}
|
}
|
||||||
@@ -39,14 +44,33 @@ public class FlatFileViewFileIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
<path stroke="#6E6E6E" d="M4,1.5 L8.8,1.5 L8.8,1.5 L13.5,6.2 L13.5,13 C13.5,13.8284271 12.8284271,14.5 12,14.5 L4,14.5 C3.17157288,14.5 2.5,13.8284271 2.5,13 L2.5,3 C2.5,2.17157288 3.17157288,1.5 4,1.5 Z"/>
|
||||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
<path stroke="#6E6E6E" d="M8.5,2 L8.5,5 C8.5,5.82842712 9.17157288,6.5 10,6.5 L13,6.5 L13,6.5"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
if( path == null ) {
|
||||||
|
double arc = 1.5;
|
||||||
|
path = FlatUIUtils.createPath( false,
|
||||||
|
// top-left
|
||||||
|
2.5,1.5+arc, FlatUIUtils.QUAD_TO, 2.5,1.5, 2.5+arc,1.5,
|
||||||
|
// top-right
|
||||||
|
8.8,1.5, 13.5,6.2,
|
||||||
|
// bottom-right
|
||||||
|
13.5,14.5-arc, FlatUIUtils.QUAD_TO, 13.5,14.5, 13.5-arc,14.5,
|
||||||
|
// bottom-left
|
||||||
|
2.5+arc,14.5, FlatUIUtils.QUAD_TO, 2.5,14.5, 2.5,14.5-arc,
|
||||||
|
FlatUIUtils.CLOSE_PATH,
|
||||||
|
|
||||||
|
FlatUIUtils.MOVE_TO, 8.5,2,
|
||||||
|
8.5,6.5-arc, FlatUIUtils.QUAD_TO, 8.5,6.5, 8.5+arc,6.5,
|
||||||
|
13,6.5 );
|
||||||
|
}
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -40,18 +41,22 @@ public class FlatFileViewFloppyDriveIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||||
<path fill="#6E6E6E" d="M11,14 L11,11 L5,11 L5,14 L2,14 L2,2 L14,2 L14,14 L11,14 Z M4,4 L4,8 L12,8 L12,4 L4,4 Z"/>
|
<path stroke="#6E6E6E" d="M3.5,2.5 L11.5,2.5 L11.5,2.5 L13.5,4.5 L13.5,12.5 C13.5,13.0522847 13.0522847,13.5 12.5,13.5 L3.5,13.5 C2.94771525,13.5 2.5,13.0522847 2.5,12.5 L2.5,3.5 C2.5,2.94771525 2.94771525,2.5 3.5,2.5 Z"/>
|
||||||
<rect width="4" height="2" x="6" y="12" fill="#6E6E6E"/>
|
<polyline stroke="#6E6E6E" points="4.5 13 4.5 9.5 11.5 9.5 11.5 13"/>
|
||||||
|
<polyline stroke="#6E6E6E" points="5.5 3 5.5 5.5 10.5 5.5 10.5 3"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( FlatUIUtils.createPath( 11,14, 11,11, 5,11, 5,14, 2,14, 2,2, 14,2, 14,14, 11,14 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( FlatUIUtils.createPath( 4,4, 4,8, 12,8, 12,4, 4,4 ), false );
|
|
||||||
g.fill( path );
|
|
||||||
|
|
||||||
g.fillRect( 6, 12, 4, 2 );
|
g.draw( FlatUIUtils.createPath( 3.5,2.5, 11.5,2.5, 11.5,2.5, 13.5,4.5,
|
||||||
|
13.5,12.5, FlatUIUtils.QUAD_TO, 13.5,13.5, 12.5,13.5,
|
||||||
|
3.5,13.5, FlatUIUtils.QUAD_TO, 2.5,13.5, 2.5,12.5,
|
||||||
|
2.5,3.5, FlatUIUtils.QUAD_TO, 2.5,2.5, 3.5,2.5 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 4.5,13, 4.5,9.5, 11.5,9.5, 11.5,13 ) );
|
||||||
|
g.draw( FlatUIUtils.createPath( false, 5.5,3, 5.5,5.5, 10.5,5.5, 10.5,3 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,14 +42,19 @@ public class FlatFileViewHardDriveIcon
|
|||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<path fill="#6E6E6E" fill-rule="evenodd" d="M2,6 L14,6 L14,10 L2,10 L2,6 Z M12,8 L12,9 L13,9 L13,8 L12,8 Z M10,8 L10,9 L11,9 L11,8 L10,8 Z"/>
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<rect width="11" height="5" x="2.5" y="5.5" stroke="#6E6E6E" rx="1"/>
|
||||||
|
<circle cx="11.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
<circle cx="9.5" cy="8.5" r="1" fill="#6E6E6E"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
path.append( new Rectangle2D.Float( 2, 6, 12, 4 ), false );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
path.append( new Rectangle2D.Float( 12, 8, 1, 1 ), false );
|
|
||||||
path.append( new Rectangle2D.Float( 10, 8, 1, 1 ), false );
|
g.draw( new RoundRectangle2D.Float( 2.5f, 5.5f, 11, 5, 2, 2 ) );
|
||||||
g.fill( path );
|
g.fill( new Ellipse2D.Float( 10.8f, 7.8f, 1.4f, 1.4f ) );
|
||||||
|
g.fill( new Ellipse2D.Float( 8.8f, 7.8f, 1.4f, 1.4f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,18 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import static com.formdev.flatlaf.util.UIScale.*;
|
import static com.formdev.flatlaf.util.UIScale.*;
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,29 +55,42 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatHelpButtonIcon
|
public class FlatHelpButtonIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
@Styleable protected int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
@Styleable protected Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "HelpButton.innerFocusWidth", FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 ) );
|
@Styleable protected float innerFocusWidth = FlatUIUtils.getUIFloat( "HelpButton.innerFocusWidth", FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 ) );
|
||||||
protected final int borderWidth = FlatUIUtils.getUIInt( "HelpButton.borderWidth", 1 );
|
@Styleable protected int borderWidth = FlatUIUtils.getUIInt( "HelpButton.borderWidth", 1 );
|
||||||
|
|
||||||
protected final Color borderColor = UIManager.getColor( "HelpButton.borderColor" );
|
@Styleable protected Color borderColor = UIManager.getColor( "HelpButton.borderColor" );
|
||||||
protected final Color disabledBorderColor = UIManager.getColor( "HelpButton.disabledBorderColor" );
|
@Styleable protected Color disabledBorderColor = UIManager.getColor( "HelpButton.disabledBorderColor" );
|
||||||
protected final Color focusedBorderColor = UIManager.getColor( "HelpButton.focusedBorderColor" );
|
@Styleable protected Color focusedBorderColor = UIManager.getColor( "HelpButton.focusedBorderColor" );
|
||||||
protected final Color hoverBorderColor = UIManager.getColor( "HelpButton.hoverBorderColor" );
|
@Styleable protected Color hoverBorderColor = UIManager.getColor( "HelpButton.hoverBorderColor" );
|
||||||
protected final Color background = UIManager.getColor( "HelpButton.background" );
|
@Styleable protected Color background = UIManager.getColor( "HelpButton.background" );
|
||||||
protected final Color disabledBackground = UIManager.getColor( "HelpButton.disabledBackground" );
|
@Styleable protected Color disabledBackground = UIManager.getColor( "HelpButton.disabledBackground" );
|
||||||
protected final Color focusedBackground = UIManager.getColor( "HelpButton.focusedBackground" );
|
@Styleable protected Color focusedBackground = UIManager.getColor( "HelpButton.focusedBackground" );
|
||||||
protected final Color hoverBackground = UIManager.getColor( "HelpButton.hoverBackground" );
|
@Styleable protected Color hoverBackground = UIManager.getColor( "HelpButton.hoverBackground" );
|
||||||
protected final Color pressedBackground = UIManager.getColor( "HelpButton.pressedBackground" );
|
@Styleable protected Color pressedBackground = UIManager.getColor( "HelpButton.pressedBackground" );
|
||||||
protected final Color questionMarkColor = UIManager.getColor( "HelpButton.questionMarkColor" );
|
@Styleable protected Color questionMarkColor = UIManager.getColor( "HelpButton.questionMarkColor" );
|
||||||
protected final Color disabledQuestionMarkColor = UIManager.getColor( "HelpButton.disabledQuestionMarkColor" );
|
@Styleable protected Color disabledQuestionMarkColor = UIManager.getColor( "HelpButton.disabledQuestionMarkColor" );
|
||||||
|
|
||||||
protected final int iconSize = 22 + (focusWidth * 2);
|
|
||||||
|
|
||||||
public FlatHelpButtonIcon() {
|
public FlatHelpButtonIcon() {
|
||||||
super( 0, 0, null );
|
super( 0, 0, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||||
/*
|
/*
|
||||||
@@ -80,16 +98,17 @@ public class FlatHelpButtonIcon
|
|||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
||||||
<circle cx="11" cy="11" r="9.5" fill="#FFF"/>
|
<circle cx="11" cy="11" r="9.5" fill="#FFF"/>
|
||||||
<path fill="#6E6E6E" d="M10,17 L12,17 L12,15 L10,15 L10,17 Z M11,5 C8.8,5 7,6.8 7,9 L9,9 C9,7.9 9.9,7 11,7 C12.1,7 13,7.9 13,9 C13,11 10,10.75 10,14 L12,14 C12,11.75 15,11.5 15,9 C15,6.8 13.2,5 11,5 Z"/>
|
<path stroke="#6E6E6E" stroke-linecap="round" stroke-width="2" d="M8,8.5 C8.25,7 9.66585007,6 11,6 C12.5,6 14,7 14,8.5 C14,10.5 11,11 11,13"/>
|
||||||
|
<circle cx="11" cy="16" r="1.2" fill="#6E6E6E"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
boolean enabled = c.isEnabled();
|
boolean enabled = c == null || c.isEnabled();
|
||||||
boolean focused = FlatUIUtils.isPermanentFocusOwner( c );
|
boolean focused = c != null && FlatUIUtils.isPermanentFocusOwner( c );
|
||||||
|
|
||||||
float xy = 0.5f;
|
float xy = 0.5f;
|
||||||
float wh = iconSize - 1;
|
float wh = iconSize() - 1;
|
||||||
|
|
||||||
// paint outer focus border
|
// paint outer focus border
|
||||||
if( focused && FlatButtonUI.isFocusPainted( c ) ) {
|
if( focused && FlatButtonUI.isFocusPainted( c ) ) {
|
||||||
@@ -131,31 +150,32 @@ public class FlatHelpButtonIcon
|
|||||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||||
|
|
||||||
// paint question mark
|
// paint question mark
|
||||||
Path2D q = new Path2D.Float();
|
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||||
q.moveTo( 11, 5 );
|
q.moveTo( 8,8.5 );
|
||||||
q.curveTo( 8.8,5, 7,6.8, 7,9 );
|
q.curveTo( 8.25,7, 9.66585007,6, 11,6 );
|
||||||
q.lineTo( 9, 9 );
|
q.curveTo( 12.5,6, 14,7, 14,8.5 );
|
||||||
q.curveTo( 9,7.9, 9.9,7, 11,7 );
|
q.curveTo( 14,10.5, 11,11, 11,13 );
|
||||||
q.curveTo( 12.1,7, 13,7.9, 13,9 );
|
|
||||||
q.curveTo( 13,11, 10,10.75, 10,14 );
|
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
q.lineTo( 12, 14 );
|
g2.setStroke( new BasicStroke( 2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
q.curveTo( 12,11.75, 15,11.5, 15,9 );
|
|
||||||
q.curveTo( 15,6.8, 13.2,5, 11,5 );
|
|
||||||
q.closePath();
|
|
||||||
|
|
||||||
g2.translate( focusWidth, focusWidth );
|
g2.translate( focusWidth, focusWidth );
|
||||||
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
||||||
g2.fill( q );
|
g2.draw( q );
|
||||||
g2.fillRect( 10, 15, 2, 2 );
|
g2.fill( new Ellipse2D.Float( 9.8f, 14.8f, 2.4f, 2.4f ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIconWidth() {
|
public int getIconWidth() {
|
||||||
return scale( iconSize );
|
return scale( iconSize() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIconHeight() {
|
public int getIconHeight() {
|
||||||
return scale( iconSize );
|
return scale( iconSize() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private int iconSize() {
|
||||||
|
return 22 + (focusWidth * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import java.awt.BasicStroke;
|
|||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
@@ -54,13 +53,15 @@ public class FlatInternalFrameCloseIcon
|
|||||||
|
|
||||||
g.setColor( FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground ) );
|
g.setColor( FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground ) );
|
||||||
|
|
||||||
float mx = width / 2;
|
float mx = width / 2f;
|
||||||
float my = height / 2;
|
float my = height / 2f;
|
||||||
float r = 3.25f;
|
float r = 3.25f;
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
path.moveTo( mx - r, my - r );
|
||||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
path.lineTo( mx + r, my + r );
|
||||||
|
path.moveTo( mx - r, my + r );
|
||||||
|
path.lineTo( mx + r, my - r );
|
||||||
g.setStroke( new BasicStroke( 1f ) );
|
g.setStroke( new BasicStroke( 1f ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,12 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "arrow" icon for {@link javax.swing.JMenu}.
|
* "arrow" icon for {@link javax.swing.JMenu}.
|
||||||
@@ -39,22 +42,37 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatMenuArrowIcon
|
public class FlatMenuArrowIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
|
@Styleable protected String arrowType = UIManager.getString( "Component.arrowType" );
|
||||||
protected final Color arrowColor = UIManager.getColor( "Menu.icon.arrowColor" );
|
@Styleable protected Color arrowColor = UIManager.getColor( "Menu.icon.arrowColor" );
|
||||||
protected final Color disabledArrowColor = UIManager.getColor( "Menu.icon.disabledArrowColor" );
|
@Styleable protected Color disabledArrowColor = UIManager.getColor( "Menu.icon.disabledArrowColor" );
|
||||||
protected final Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
|
@Styleable protected Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
|
||||||
|
|
||||||
public FlatMenuArrowIcon() {
|
public FlatMenuArrowIcon() {
|
||||||
super( 6, 10, null );
|
super( 6, 10, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
if( !c.getComponentOrientation().isLeftToRight() )
|
if( c != null && !c.getComponentOrientation().isLeftToRight() )
|
||||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||||
|
|
||||||
g.setColor( getArrowColor( c ) );
|
g.setColor( getArrowColor( c ) );
|
||||||
if( chevron ) {
|
if( FlatUIUtils.isChevron( arrowType ) ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
Path2D path = FlatUIUtils.createPath( false, 1,1, 5,5, 1,9 );
|
Path2D path = FlatUIUtils.createPath( false, 1,1, 5,5, 1,9 );
|
||||||
g.setStroke( new BasicStroke( 1f ) );
|
g.setStroke( new BasicStroke( 1f ) );
|
||||||
@@ -69,7 +87,7 @@ public class FlatMenuArrowIcon
|
|||||||
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
||||||
return selectionForeground;
|
return selectionForeground;
|
||||||
|
|
||||||
return c.isEnabled() ? arrowColor : disabledArrowColor;
|
return c == null || c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isUnderlineSelection() {
|
protected boolean isUnderlineSelection() {
|
||||||
|
|||||||
@@ -21,14 +21,16 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "arrow" icon for {@link javax.swing.JMenuItem}.
|
* "arrow" icon for {@link javax.swing.JMenuItem}, {@link javax.swing.JCheckBoxMenuItem}
|
||||||
|
* and {@link javax.swing.JRadioButtonMenuItem}.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatMenuItemArrowIcon
|
public class FlatMenuItemArrowIcon
|
||||||
extends FlatMenuArrowIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatMenuItemArrowIcon() {
|
public FlatMenuItemArrowIcon() {
|
||||||
|
super( 6, 10, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Error" icon for {@link javax.swing.JOptionPane}.
|
* "Error" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneErrorIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#DB5860"/>
|
<circle cx="16" cy="16" r="14" fill="#DB5860"/>
|
||||||
<rect width="4" height="11" x="14" y="7" fill="#FFF"/>
|
<rect width="4" height="12" x="14" y="7" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneErrorIcon
|
|||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 11 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 7, 4, 12, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Information" icon for {@link javax.swing.JOptionPane}.
|
* "Information" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneInformationIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||||
<rect width="4" height="11" x="14" y="14" fill="#FFF"/>
|
<rect width="4" height="12" x="14" y="13" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="7" fill="#FFF"/>
|
<circle cx="16" cy="9" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneInformationIcon
|
|||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 14, 4, 11 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 13, 4, 12, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 7, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Question" icon for {@link javax.swing.JOptionPane}.
|
* "Question" icon for {@link javax.swing.JOptionPane}.
|
||||||
@@ -40,8 +40,8 @@ public class FlatOptionPaneQuestionIcon
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||||
<rect width="4" height="4" x="14" y="22" fill="#FFF"/>
|
<circle cx="16" cy="24" r="1.7" fill="#FFF"/>
|
||||||
<path fill="#FFF" d="M14,20 C14,20 18,20 18,20 C18,16 23,16 23,12 C23,8 20,6 16,6 C12,6 9,8 9,12 C9,12 13,12 13,12 C13,10 14,9 16,9 C18,9 19,10 19,12 C19,15 14,15 14,20 Z"/>
|
<path stroke="#FFF" stroke-linecap="round" stroke-width="3" d="M11.5,11.75 C11.75,9.5 13.75,8 16,8 C18.25,8 20.5,9.5 20.5,11.75 C20.5,14.75 16,15.5 16,19"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
@@ -53,21 +53,17 @@ public class FlatOptionPaneQuestionIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D q = new Path2D.Float();
|
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||||
q.moveTo( 14, 20 );
|
q.moveTo( 11.5,11.75 );
|
||||||
q.lineTo( 18, 20 );
|
q.curveTo( 11.75,9.5, 13.75,8, 16,8 );
|
||||||
q.curveTo( 18, 16, 23, 16, 23, 12 );
|
q.curveTo( 18.25,8, 20.5,9.5, 20.5,11.75 );
|
||||||
q.curveTo( 23, 8, 20, 6, 16, 6 );
|
q.curveTo( 20.5,14.75, 16,15.5, 16,19 );
|
||||||
q.curveTo( 12, 6, 9, 8, 9, 12 );
|
|
||||||
q.curveTo( 9, 12, 13, 12, 13, 12 );
|
BasicStroke stroke = new BasicStroke( 3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER );
|
||||||
q.curveTo( 13, 10, 14, 9, 16, 9 );
|
|
||||||
q.curveTo( 18, 9, 19, 10, 19, 12 );
|
|
||||||
q.curveTo( 19, 15, 14, 15, 14, 20 );
|
|
||||||
q.closePath();
|
|
||||||
|
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 22, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14.3f, 22.3f, 3.4f, 3.4f ), false );
|
||||||
inside.append( q, false );
|
inside.append( stroke.createStrokedShape( q ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,23 +40,24 @@ public class FlatOptionPaneWarningIcon
|
|||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#EDA200" points="16 2 31 28 1 28"/>
|
<path fill="#EDA200" d="M17.7364863,3.038851 L30.2901269,25.0077221 C30.8381469,25.966757 30.5049534,27.1884663 29.5459185,27.7364863 C29.2437231,27.9091694 28.9016945,28 28.5536406,28 L3.44635936,28 C2.34178986,28 1.44635936,27.1045695 1.44635936,26 C1.44635936,25.6519461 1.53718999,25.3099175 1.70987307,25.0077221 L14.2635137,3.038851 C14.8115337,2.0798161 16.033243,1.74662265 16.9922779,2.29464259 C17.3023404,2.47182119 17.5593077,2.72878844 17.7364863,3.038851 Z"/>
|
||||||
<rect width="4" height="8" x="14" y="10" fill="#FFF"/>
|
<rect width="4" height="11" x="14" y="8" fill="#FFF" rx="2"/>
|
||||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createOutside() {
|
protected Shape createOutside() {
|
||||||
return FlatUIUtils.createPath( 16,2, 31,28, 1,28 );
|
return FlatUIUtils.createRoundTrianglePath( 16,0, 32,28, 0,28, 4 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Shape createInside() {
|
protected Shape createInside() {
|
||||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
inside.append( new Rectangle2D.Float( 14, 10, 4, 8 ), false );
|
inside.append( new RoundRectangle2D.Float( 14, 8, 4, 11, 4, 4 ), false );
|
||||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,38 +19,51 @@ package com.formdev.flatlaf.icons;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icon for {@link javax.swing.JRadioButton}.
|
* Icon for {@link javax.swing.JRadioButton}.
|
||||||
*
|
* <p>
|
||||||
* Note: If Component.focusWidth is greater than zero, then the outline focus border
|
* <strong>Note</strong>:
|
||||||
|
* If Component.focusWidth is greater than zero, then the outer focus border
|
||||||
* is painted outside of the icon bounds. Make sure that the radiobutton
|
* is painted outside of the icon bounds. Make sure that the radiobutton
|
||||||
* has margins, which are equal or greater than focusWidth.
|
* has margins, which are equal or greater than focusWidth.
|
||||||
*
|
*
|
||||||
* @uiDefault RadioButton.icon.centerDiameter int
|
* @uiDefault RadioButton.icon.style String optional; "outlined"/null (default) or "filled"
|
||||||
|
* @uiDefault RadioButton.icon.centerDiameter int or float
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatRadioButtonIcon
|
public class FlatRadioButtonIcon
|
||||||
extends FlatCheckBoxIcon
|
extends FlatCheckBoxIcon
|
||||||
{
|
{
|
||||||
protected final int centerDiameter = getUIInt( "RadioButton.icon.centerDiameter", 8, style );
|
@Styleable protected float centerDiameter = getUIFloat( "RadioButton.icon.centerDiameter", 8, style );
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
protected String getPropertyPrefix() {
|
||||||
// the outline focus border is painted outside of the icon
|
return "RadioButton.";
|
||||||
int wh = ICON_SIZE + (focusWidth * 2);
|
|
||||||
g.fillOval( -focusWidth, -focusWidth, wh, wh );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBorder( Component c, Graphics2D g ) {
|
protected void paintFocusBorder( Component c, Graphics2D g ) {
|
||||||
|
// the outer focus border is painted outside of the icon
|
||||||
|
float wh = ICON_SIZE + (focusWidth * 2);
|
||||||
|
g.fill( new Ellipse2D.Float( -focusWidth, -focusWidth, wh, wh ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintBorder( Component c, Graphics2D g, float borderWidth ) {
|
||||||
|
if( borderWidth == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
g.fillOval( 0, 0, 15, 15 );
|
g.fillOval( 0, 0, 15, 15 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Component c, Graphics2D g ) {
|
protected void paintBackground( Component c, Graphics2D g, float borderWidth ) {
|
||||||
g.fillOval( 1, 1, 13, 13 );
|
float xy = borderWidth;
|
||||||
|
float wh = 15 - (borderWidth * 2);
|
||||||
|
g.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.Area;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "eye" icon for {@link javax.swing.JPasswordField}.
|
||||||
|
*
|
||||||
|
* @uiDefault PasswordField.revealIconColor Color
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 2
|
||||||
|
*/
|
||||||
|
public class FlatRevealIcon
|
||||||
|
extends FlatAbstractIcon
|
||||||
|
{
|
||||||
|
public FlatRevealIcon() {
|
||||||
|
super( 16, 16, UIManager.getColor( "PasswordField.revealIconColor" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path.append( new Ellipse2D.Float( 5.15f, 6.15f, 5.7f, 5.7f ), false );
|
||||||
|
path.append( new Ellipse2D.Float( 6, 7, 4, 4 ), false );
|
||||||
|
g.fill( path );
|
||||||
|
|
||||||
|
Path2D path2 = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path2.append( new Ellipse2D.Float( 2.15f, 4.15f, 11.7f, 11.7f ), false );
|
||||||
|
path2.append( new Ellipse2D.Float( 3, 5, 10, 10 ), false );
|
||||||
|
Area area = new Area( path2 );
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( 0, 9.5f, 16, 16 ) ) );
|
||||||
|
g.fill( area );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Area;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "search" icon for search fields.
|
||||||
|
*
|
||||||
|
* @uiDefault SearchField.searchIconColor Color
|
||||||
|
* @uiDefault SearchField.searchIconHoverColor Color
|
||||||
|
* @uiDefault SearchField.searchIconPressedColor Color
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public class FlatSearchIcon
|
||||||
|
extends FlatAbstractIcon
|
||||||
|
{
|
||||||
|
@Styleable protected Color searchIconColor = UIManager.getColor( "SearchField.searchIconColor" );
|
||||||
|
@Styleable protected Color searchIconHoverColor = UIManager.getColor( "SearchField.searchIconHoverColor" );
|
||||||
|
@Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
|
||||||
|
|
||||||
|
private final boolean ignoreButtonState;
|
||||||
|
private Area area;
|
||||||
|
|
||||||
|
public FlatSearchIcon() {
|
||||||
|
this( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public FlatSearchIcon( boolean ignoreButtonState ) {
|
||||||
|
super( 16, 16, null );
|
||||||
|
this.ignoreButtonState = ignoreButtonState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@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-opacity=".9" fill-rule="evenodd">
|
||||||
|
<polygon fill="#7F8B91" points="10.813 9.75 14 12.938 12.938 14 9.75 10.813"/>
|
||||||
|
<path fill="#7F8B91" d="M7,2 C9.76142375,2 12,4.23857625 12,7 C12,9.76142375 9.76142375,12 7,12 C4.23857625,12 2,9.76142375 2,7 C2,4.23857625 4.23857625,2 7,2 Z M7,3 C4.790861,3 3,4.790861 3,7 C3,9.209139 4.790861,11 7,11 C9.209139,11 11,9.209139 11,7 C11,4.790861 9.209139,3 7,3 Z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
*/
|
||||||
|
|
||||||
|
g.setColor( ignoreButtonState
|
||||||
|
? searchIconColor
|
||||||
|
: FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
||||||
|
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||||
|
|
||||||
|
// paint magnifier
|
||||||
|
if( area == null ) {
|
||||||
|
area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
|
||||||
|
area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) );
|
||||||
|
area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) );
|
||||||
|
}
|
||||||
|
g.fill( area );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 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 com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "search with history" icon for search fields.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 1.5
|
||||||
|
*/
|
||||||
|
public class FlatSearchWithHistoryIcon
|
||||||
|
extends FlatSearchIcon
|
||||||
|
{
|
||||||
|
public FlatSearchWithHistoryIcon() {
|
||||||
|
this( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public FlatSearchWithHistoryIcon( boolean ignoreButtonState ) {
|
||||||
|
super( ignoreButtonState );
|
||||||
|
}
|
||||||
|
|
||||||
|
@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-opacity=".9" fill-rule="evenodd">
|
||||||
|
<polygon fill="#7F8B91" points="8.813 9.75 12 12.938 10.938 14 7.75 10.813"/>
|
||||||
|
<path fill="#7F8B91" d="M5,2 C7.76142375,2 10,4.23857625 10,7 C10,9.76142375 7.76142375,12 5,12 C2.23857625,12 0,9.76142375 0,7 C0,4.23857625 2.23857625,2 5,2 Z M5,3 C2.790861,3 1,4.790861 1,7 C1,9.209139 2.790861,11 5,11 C7.209139,11 9,9.209139 9,7 C9,4.790861 7.209139,3 5,3 Z"/>
|
||||||
|
<polygon fill="#7F8B91" points="11 7 16 7 13.5 10"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// paint magnifier
|
||||||
|
g.translate( -2, 0 );
|
||||||
|
super.paintIcon( c, g );
|
||||||
|
g.translate( 2, 0 );
|
||||||
|
|
||||||
|
// paint history arrow
|
||||||
|
g.fill( FlatUIUtils.createPath( 11,7, 16,7, 13.5,10 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,10 +21,12 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,44 +49,61 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTabbedPaneCloseIcon
|
public class FlatTabbedPaneCloseIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
protected final Dimension size = UIManager.getDimension( "TabbedPane.closeSize" );
|
@Styleable protected Dimension closeSize = UIManager.getDimension( "TabbedPane.closeSize" );
|
||||||
protected final int arc = UIManager.getInt( "TabbedPane.closeArc" );
|
@Styleable protected int closeArc = UIManager.getInt( "TabbedPane.closeArc" );
|
||||||
protected final float crossPlainSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossPlainSize", 7.5f );
|
@Styleable protected float closeCrossPlainSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossPlainSize", 7.5f );
|
||||||
protected final float crossFilledSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossFilledSize", crossPlainSize );
|
@Styleable protected float closeCrossFilledSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossFilledSize", closeCrossPlainSize );
|
||||||
protected final float closeCrossLineWidth = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossLineWidth", 1f );
|
@Styleable protected float closeCrossLineWidth = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossLineWidth", 1f );
|
||||||
protected final Color background = UIManager.getColor( "TabbedPane.closeBackground" );
|
@Styleable protected Color closeBackground = UIManager.getColor( "TabbedPane.closeBackground" );
|
||||||
protected final Color foreground = UIManager.getColor( "TabbedPane.closeForeground" );
|
@Styleable protected Color closeForeground = UIManager.getColor( "TabbedPane.closeForeground" );
|
||||||
protected final Color hoverBackground = UIManager.getColor( "TabbedPane.closeHoverBackground" );
|
@Styleable protected Color closeHoverBackground = UIManager.getColor( "TabbedPane.closeHoverBackground" );
|
||||||
protected final Color hoverForeground = UIManager.getColor( "TabbedPane.closeHoverForeground" );
|
@Styleable protected Color closeHoverForeground = UIManager.getColor( "TabbedPane.closeHoverForeground" );
|
||||||
protected final Color pressedBackground = UIManager.getColor( "TabbedPane.closePressedBackground" );
|
@Styleable protected Color closePressedBackground = UIManager.getColor( "TabbedPane.closePressedBackground" );
|
||||||
protected final Color pressedForeground = UIManager.getColor( "TabbedPane.closePressedForeground" );
|
@Styleable protected Color closePressedForeground = UIManager.getColor( "TabbedPane.closePressedForeground" );
|
||||||
|
|
||||||
public FlatTabbedPaneCloseIcon() {
|
public FlatTabbedPaneCloseIcon() {
|
||||||
super( 16, 16, null );
|
super( 16, 16, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
// paint background
|
// paint background
|
||||||
Color bg = FlatButtonUI.buttonStateColor( c, background, null, null, hoverBackground, pressedBackground );
|
Color bg = FlatButtonUI.buttonStateColor( c, closeBackground, null, null, closeHoverBackground, closePressedBackground );
|
||||||
if( bg != null ) {
|
if( bg != null ) {
|
||||||
g.setColor( FlatUIUtils.deriveColor( bg, c.getBackground() ) );
|
g.setColor( FlatUIUtils.deriveColor( bg, c.getBackground() ) );
|
||||||
g.fillRoundRect( (width - size.width) / 2, (height - size.height) / 2,
|
g.fillRoundRect( (width - closeSize.width) / 2, (height - closeSize.height) / 2,
|
||||||
size.width, size.height, arc, arc );
|
closeSize.width, closeSize.height, closeArc, closeArc );
|
||||||
}
|
}
|
||||||
|
|
||||||
// set cross color
|
// set color of cross
|
||||||
Color fg = FlatButtonUI.buttonStateColor( c, foreground, null, null, hoverForeground, pressedForeground );
|
Color fg = FlatButtonUI.buttonStateColor( c, closeForeground, null, null, closeHoverForeground, closePressedForeground );
|
||||||
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
||||||
|
|
||||||
float mx = width / 2;
|
float mx = width / 2f;
|
||||||
float my = height / 2;
|
float my = height / 2f;
|
||||||
float r = ((bg != null) ? crossFilledSize : crossPlainSize) / 2;
|
float r = ((bg != null) ? closeCrossFilledSize : closeCrossPlainSize) / 2;
|
||||||
|
|
||||||
// paint cross
|
// paint cross
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
path.moveTo( mx - r, my - r );
|
||||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
path.lineTo( mx + r, my + r );
|
||||||
|
path.moveTo( mx - r, my + r );
|
||||||
|
path.lineTo( mx + r, my - r );
|
||||||
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "closed" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
* "closed" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
||||||
@@ -31,18 +32,26 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTreeClosedIcon
|
public class FlatTreeClosedIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeClosedIcon() {
|
public FlatTreeClosedIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconClosedColor );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<polygon fill="#6E6E6E" fill-rule="evenodd" points="1 2 6 2 8 4 15 4 15 13 1 13"/>
|
<path fill="none" stroke="#6E6E6E" d="M13,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L13,4.5 C13.8284271,4.5 14.5,5.17157288 14.5,6 L14.5,12 C14.5,12.8284271 13.8284271,13.5 13,13.5 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 15,4, 15,13, 1,13 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
|
|
||||||
|
if( path == null )
|
||||||
|
path = FlatFileViewDirectoryIcon.createFolderPath();
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,17 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import javax.swing.JTree;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.plaf.TreeUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatTreeUI;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,6 +41,7 @@ public class FlatTreeCollapsedIcon
|
|||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
private final boolean chevron;
|
private final boolean chevron;
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeCollapsedIcon() {
|
public FlatTreeCollapsedIcon() {
|
||||||
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
||||||
@@ -46,19 +54,54 @@ public class FlatTreeCollapsedIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
setStyleColorFromTreeUI( c, g );
|
||||||
rotate( c, g );
|
rotate( c, g );
|
||||||
|
|
||||||
|
String arrowType = getStyleFromTreeUI( c, ui -> ui.iconArrowType );
|
||||||
|
boolean chevron = (arrowType != null) ? FlatUIUtils.isChevron( arrowType ) : this.chevron;
|
||||||
|
|
||||||
if( chevron ) {
|
if( chevron ) {
|
||||||
// chevron arrow
|
// chevron arrow
|
||||||
g.fill( FlatUIUtils.createPath( 3,1, 3,2.5, 6,5.5, 3,8.5, 3,10, 4.5,10, 9,5.5, 4.5,1 ) );
|
g.setStroke( new BasicStroke( 1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER ) );
|
||||||
|
if( path == null )
|
||||||
|
path = FlatUIUtils.createPath( false, 3.5,1.5, 7.5,5.5, 3.5,9.5 );
|
||||||
|
g.draw( path );
|
||||||
} else {
|
} else {
|
||||||
// triangle arrow
|
// triangle arrow
|
||||||
g.fill( FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 ) );
|
if( path == null )
|
||||||
|
path = FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 );
|
||||||
|
g.fill( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setStyleColorFromTreeUI( Component c, Graphics2D g ) {
|
||||||
|
setStyleColorFromTreeUI( c, g, ui -> ui.iconCollapsedColor );
|
||||||
|
}
|
||||||
|
|
||||||
void rotate( Component c, Graphics2D g ) {
|
void rotate( Component c, Graphics2D g ) {
|
||||||
if( !c.getComponentOrientation().isLeftToRight() )
|
if( !c.getComponentOrientation().isLeftToRight() )
|
||||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because this icon is always shared for all trees,
|
||||||
|
* get icon specific style from FlatTreeUI.
|
||||||
|
*/
|
||||||
|
static <T> T getStyleFromTreeUI( Component c, Function<FlatTreeUI, T> f ) {
|
||||||
|
JTree tree = (c instanceof JTree)
|
||||||
|
? (JTree) c
|
||||||
|
: (JTree) SwingUtilities.getAncestorOfClass( JTree.class, c );
|
||||||
|
if( tree != null ) {
|
||||||
|
TreeUI ui = tree.getUI();
|
||||||
|
if( ui instanceof FlatTreeUI )
|
||||||
|
return f.apply( (FlatTreeUI) ui );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setStyleColorFromTreeUI( Component c, Graphics2D g, Function<FlatTreeUI, Color> f ) {
|
||||||
|
Color color = getStyleFromTreeUI( c, f );
|
||||||
|
if( color != null )
|
||||||
|
g.setColor( color );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ public class FlatTreeExpandedIcon
|
|||||||
super( UIManager.getColor( "Tree.icon.expandedColor" ) );
|
super( UIManager.getColor( "Tree.icon.expandedColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void setStyleColorFromTreeUI( Component c, Graphics2D g ) {
|
||||||
|
setStyleColorFromTreeUI( c, g, ui -> ui.iconExpandedColor );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void rotate( Component c, Graphics2D g ) {
|
void rotate( Component c, Graphics2D g ) {
|
||||||
g.rotate( Math.toRadians( 90 ), width / 2., height / 2. );
|
g.rotate( Math.toRadians( 90 ), width / 2., height / 2. );
|
||||||
|
|||||||
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "leaf" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
* "leaf" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
||||||
@@ -37,16 +41,27 @@ public class FlatTreeLeafIcon
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconLeafColor );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
<rect width="11" height="13" x="2.5" y="1.5" stroke="#6E6E6E" rx="1.5"/>
|
||||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
<line x1="5.5" x2="10.5" y1="5.5" y2="5.5" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
|
<line x1="5.5" x2="10.5" y1="8" y2="8" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
|
<line x1="5.5" x2="10.5" y1="10.5" y2="10.5" stroke="#6E6E6E" stroke-linecap="round" stroke-opacity=".6"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||||
|
|
||||||
|
g.draw( new RoundRectangle2D.Float( 2.5f, 1.5f, 11, 13, 3, 3 ) );
|
||||||
|
|
||||||
|
g.setColor( ColorFunctions.fade( g.getColor(), 0.6f ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 5.5f, 10.5f, 5.5f ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 8, 10.5f, 8 ) );
|
||||||
|
g.draw( new Line2D.Float( 5.5f, 10.5f, 10.5f, 10.5f ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
@@ -31,22 +34,50 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
|||||||
public class FlatTreeOpenIcon
|
public class FlatTreeOpenIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
|
private Path2D path;
|
||||||
|
|
||||||
public FlatTreeOpenIcon() {
|
public FlatTreeOpenIcon() {
|
||||||
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
FlatTreeCollapsedIcon.setStyleColorFromTreeUI( c, g, ui -> ui.iconOpenColor );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
<g fill="none" fill-rule="evenodd">
|
<path fill="none" stroke="#6E6E6E" d="M2,13.5 L4.11538462,8.42307692 C4.34828895,7.86410651 4.89444872,7.5 5.5,7.5 L14.75,7.5 C15.0261424,7.5 15.25,7.72385763 15.25,8 C15.25,8.06601301 15.2369281,8.13137261 15.2115385,8.19230769 L13.3846154,12.5769231 C13.151711,13.1358935 12.6055513,13.5 12,13.5 L3,13.5 C2.17157288,13.5 1.5,12.8284271 1.5,12 L1.5,4 C1.5,3.17157288 2.17157288,2.5 3,2.5 L6.29289322,2.5 C6.42550146,2.5 6.55267842,2.55267842 6.64644661,2.64644661 L8.5,4.5 L8.5,4.5 L12,4.5 C12.8284271,4.5 13.5,5.17157288 13.5,6 L13.5,6.5 L13.5,6.5"/>
|
||||||
<polygon fill="#6E6E6E" points="1 2 6 2 8 4 14 4 14 6 3.5 6 1 11"/>
|
|
||||||
<polygon fill="#6E6E6E" points="4 7 16 7 13 13 1 13"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 14,4, 14,6, 3.5,6, 1,11 ) );
|
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||||
g.fill( FlatUIUtils.createPath( 4,7, 16,7, 13,13, 1,13 ) );
|
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER ) );
|
||||||
|
|
||||||
|
if( path == null ) {
|
||||||
|
double arc = 1.5;
|
||||||
|
double arc2 = 0.5;
|
||||||
|
path = FlatUIUtils.createPath( false,
|
||||||
|
// bottom-left of opened part
|
||||||
|
2,13.5,
|
||||||
|
// top-left of opened part
|
||||||
|
FlatUIUtils.ROUNDED, 4.5,7.5, arc,
|
||||||
|
// top-right of opened part
|
||||||
|
FlatUIUtils.ROUNDED, 15.5,7.5, arc2,
|
||||||
|
|
||||||
|
// bottom-right
|
||||||
|
FlatUIUtils.ROUNDED, 13,13.5, arc,
|
||||||
|
// bottom-left
|
||||||
|
1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc,
|
||||||
|
// top-left
|
||||||
|
1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5,
|
||||||
|
// top-mid-left
|
||||||
|
6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2,
|
||||||
|
// top-mid-right
|
||||||
|
8.5,4.5,
|
||||||
|
// top-right
|
||||||
|
13.5-arc,4.5, FlatUIUtils.QUAD_TO, 13.5,4.5, 13.5,4.5+arc,
|
||||||
|
13.5,6.5 );
|
||||||
|
}
|
||||||
|
g.draw( path );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,59 +18,141 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import javax.swing.UIManager;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Window;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatTitlePane;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for window icons.
|
* Base class for window icons.
|
||||||
*
|
*
|
||||||
* @uiDefault TitlePane.buttonSize Dimension
|
* @uiDefault TitlePane.buttonSize Dimension
|
||||||
* @uiDefault TitlePane.buttonHoverBackground Color
|
* @uiDefault TitlePane.buttonInsets Insets optional
|
||||||
* @uiDefault TitlePane.buttonPressedBackground Color
|
* @uiDefault TitlePane.buttonArc int optional
|
||||||
|
* @uiDefault TitlePane.buttonSymbolHeight int
|
||||||
|
* @uiDefault TitlePane.buttonBackground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonForeground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonInactiveBackground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonInactiveForeground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonHoverBackground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonHoverForeground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonPressedBackground Color optional
|
||||||
|
* @uiDefault TitlePane.buttonPressedForeground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public abstract class FlatWindowAbstractIcon
|
public abstract class FlatWindowAbstractIcon
|
||||||
extends FlatAbstractIcon
|
extends FlatAbstractIcon
|
||||||
{
|
{
|
||||||
private final Color hoverBackground;
|
/** @since 3.6 */ protected final Insets insets;
|
||||||
private final Color pressedBackground;
|
/** @since 3.6 */ protected final int arc;
|
||||||
|
/** @since 3.6 */ protected final int symbolHeight;
|
||||||
|
|
||||||
public FlatWindowAbstractIcon() {
|
/** @since 3.6 */ protected final Color background;
|
||||||
this( UIManager.getDimension( "TitlePane.buttonSize" ),
|
/** @since 3.6 */ protected final Color foreground;
|
||||||
UIManager.getColor( "TitlePane.buttonHoverBackground" ),
|
/** @since 3.6 */ protected final Color inactiveBackground;
|
||||||
UIManager.getColor( "TitlePane.buttonPressedBackground" ) );
|
/** @since 3.6 */ protected final Color inactiveForeground;
|
||||||
|
protected final Color hoverBackground;
|
||||||
|
/** @since 3.6 */ protected final Color hoverForeground;
|
||||||
|
protected final Color pressedBackground;
|
||||||
|
/** @since 3.6 */ protected final Color pressedForeground;
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
protected FlatWindowAbstractIcon( String windowStyle ) {
|
||||||
|
this( windowStyle, null, null, null, null, null, null, null, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlatWindowAbstractIcon( Dimension size, Color hoverBackground, Color pressedBackground ) {
|
/** @since 3.6 */
|
||||||
|
protected FlatWindowAbstractIcon( String windowStyle,
|
||||||
|
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
|
||||||
|
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
|
||||||
|
{
|
||||||
|
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIInsets( "TitlePane.buttonInsets", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIInt( "TitlePane.buttonArc", windowStyle, 0 ),
|
||||||
|
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||||
|
(background != null) ? background : FlatUIUtils.getSubUIColor( "TitlePane.buttonBackground", windowStyle ),
|
||||||
|
(foreground != null) ? foreground : FlatUIUtils.getSubUIColor( "TitlePane.buttonForeground", windowStyle ),
|
||||||
|
(inactiveBackground != null) ? inactiveBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveBackground", windowStyle ),
|
||||||
|
(inactiveForeground != null) ? inactiveForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonInactiveForeground", windowStyle ),
|
||||||
|
(hoverBackground != null) ? hoverBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
||||||
|
(hoverForeground != null) ? hoverForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverForeground", windowStyle ),
|
||||||
|
(pressedBackground != null) ? pressedBackground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ),
|
||||||
|
(pressedForeground != null) ? pressedForeground : FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedForeground", windowStyle ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.6 */
|
||||||
|
protected FlatWindowAbstractIcon( Dimension size, Insets insets, int arc, int symbolHeight,
|
||||||
|
Color background, Color foreground, Color inactiveBackground, Color inactiveForeground,
|
||||||
|
Color hoverBackground, Color hoverForeground, Color pressedBackground, Color pressedForeground )
|
||||||
|
{
|
||||||
super( size.width, size.height, null );
|
super( size.width, size.height, null );
|
||||||
|
this.insets = (insets != null) ? insets : new Insets( 0, 0, 0, 0 );
|
||||||
|
this.arc = arc;
|
||||||
|
this.symbolHeight = symbolHeight;
|
||||||
|
|
||||||
|
this.background = background;
|
||||||
|
this.foreground = foreground;
|
||||||
|
this.inactiveBackground = inactiveBackground;
|
||||||
|
this.inactiveForeground = inactiveForeground;
|
||||||
this.hoverBackground = hoverBackground;
|
this.hoverBackground = hoverBackground;
|
||||||
|
this.hoverForeground = hoverForeground;
|
||||||
this.pressedBackground = pressedBackground;
|
this.pressedBackground = pressedBackground;
|
||||||
|
this.pressedForeground = pressedForeground;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIcon( Component c, Graphics2D g ) {
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
paintBackground( c, g );
|
|
||||||
|
|
||||||
g.setColor( getForeground( c ) );
|
g.setColor( getForeground( c ) );
|
||||||
HiDPIUtils.paintAtScale1x( g, 0, 0, width, height, this::paintIconAt1x );
|
HiDPIUtils.paintAtScale1x( g, 0, 0, width, height, this::paintIconAt1x );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
protected abstract void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor );
|
||||||
|
|
||||||
protected void paintBackground( Component c, Graphics2D g ) {
|
/** @since 3.5.2 */
|
||||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
@Override
|
||||||
|
protected void paintBackground( Component c, Graphics2D g, int x, int y ) {
|
||||||
|
Color bg = null;
|
||||||
|
if( background != null || inactiveBackground != null ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( c );
|
||||||
|
bg = (window == null || window.isActive()) ? background : inactiveBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color background = FlatButtonUI.buttonStateColor( c, bg, null, null, hoverBackground, pressedBackground );
|
||||||
if( background != null ) {
|
if( background != null ) {
|
||||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
Insets insets = UIScale.scale( this.insets );
|
||||||
g.fillRect( 0, 0, width, height );
|
float arc = UIScale.scale( (float) this.arc );
|
||||||
|
|
||||||
|
// derive color from title pane background
|
||||||
|
if( background instanceof DerivedColor ) {
|
||||||
|
Container titlePane = SwingUtilities.getAncestorOfClass( FlatTitlePane.class, c );
|
||||||
|
Component baseComp = (titlePane != null) ? titlePane : c;
|
||||||
|
background = FlatUIUtils.deriveColor( background, baseComp.getBackground() );
|
||||||
|
}
|
||||||
|
|
||||||
|
g.setColor( background );
|
||||||
|
FlatUIUtils.paintComponentBackground( g, insets.left, insets.top,
|
||||||
|
c.getWidth() - insets.left - insets.right,
|
||||||
|
c.getHeight() - insets.top - insets.bottom,
|
||||||
|
0, arc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( Component c ) {
|
protected Color getForeground( Component c ) {
|
||||||
return c.getForeground();
|
Color fg = null;
|
||||||
|
if( foreground != null || inactiveForeground != null ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( c );
|
||||||
|
fg = (window == null || window.isActive()) ? foreground : inactiveForeground;
|
||||||
|
}
|
||||||
|
return FlatButtonUI.buttonStateColor( c, (fg != null) ? fg : c.getForeground(),
|
||||||
|
null, null, hoverForeground, pressedForeground );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,54 +17,61 @@
|
|||||||
package com.formdev.flatlaf.icons;
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
import java.awt.BasicStroke;
|
import java.awt.BasicStroke;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import javax.swing.UIManager;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "close" icon for windows (frames and dialogs).
|
* "close" icon for windows (frames and dialogs).
|
||||||
*
|
*
|
||||||
* @uiDefault TitlePane.closeHoverBackground Color
|
* @uiDefault TitlePane.closeBackground Color optional
|
||||||
* @uiDefault TitlePane.closePressedBackground Color
|
* @uiDefault TitlePane.closeForeground Color optional
|
||||||
* @uiDefault TitlePane.closeHoverForeground Color
|
* @uiDefault TitlePane.closeInactiveBackground Color optional
|
||||||
* @uiDefault TitlePane.closePressedForeground Color
|
* @uiDefault TitlePane.closeInactiveForeground Color optional
|
||||||
|
* @uiDefault TitlePane.closeHoverBackground Color optional
|
||||||
|
* @uiDefault TitlePane.closeHoverForeground Color optional
|
||||||
|
* @uiDefault TitlePane.closePressedBackground Color optional
|
||||||
|
* @uiDefault TitlePane.closePressedForeground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatWindowCloseIcon
|
public class FlatWindowCloseIcon
|
||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
private final Color hoverForeground = UIManager.getColor( "TitlePane.closeHoverForeground" );
|
|
||||||
private final Color pressedForeground = UIManager.getColor( "TitlePane.closePressedForeground" );
|
|
||||||
|
|
||||||
public FlatWindowCloseIcon() {
|
public FlatWindowCloseIcon() {
|
||||||
super( UIManager.getDimension( "TitlePane.buttonSize" ),
|
this( null );
|
||||||
UIManager.getColor( "TitlePane.closeHoverBackground" ),
|
}
|
||||||
UIManager.getColor( "TitlePane.closePressedBackground" ) );
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowCloseIcon( String windowStyle ) {
|
||||||
|
super( windowStyle,
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeForeground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeInactiveForeground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ),
|
||||||
|
FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (symbolHeight * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int ix2 = ix + iwh - 1;
|
int ix2 = ix + iwh - 1;
|
||||||
int iy2 = iy + iwh - 1;
|
int iy2 = iy + iwh - 1;
|
||||||
int thickness = (int) scaleFactor;
|
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||||
|
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
|
||||||
|
|
||||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||||
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
path.moveTo( ix, iy );
|
||||||
path.append( new Line2D.Float( ix, iy2, ix2, iy ), false );
|
path.lineTo( ix2, iy2 );
|
||||||
|
path.moveTo( ix, iy2 );
|
||||||
|
path.lineTo( ix2, iy );
|
||||||
g.setStroke( new BasicStroke( thickness ) );
|
g.setStroke( new BasicStroke( thickness ) );
|
||||||
g.draw( path );
|
g.draw( path );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Color getForeground( Component c ) {
|
|
||||||
return FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,12 +27,18 @@ public class FlatWindowIconifyIcon
|
|||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatWindowIconifyIcon() {
|
public FlatWindowIconifyIcon() {
|
||||||
|
this( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowIconifyIcon( String windowStyle ) {
|
||||||
|
super( windowStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iw = (int) (10 * scaleFactor);
|
int iw = (int) (symbolHeight * scaleFactor);
|
||||||
int ih = (int) scaleFactor;
|
int ih = Math.max( (int) scaleFactor, 1 );
|
||||||
int ix = x + ((width - iw) / 2);
|
int ix = x + ((width - iw) / 2);
|
||||||
int iy = y + ((height - ih) / 2);
|
int iy = y + ((height - ih) / 2);
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.icons;
|
|||||||
|
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "maximize" icon for windows (frames and dialogs).
|
* "maximize" icon for windows (frames and dialogs).
|
||||||
@@ -28,15 +29,25 @@ public class FlatWindowMaximizeIcon
|
|||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatWindowMaximizeIcon() {
|
public FlatWindowMaximizeIcon() {
|
||||||
|
this( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowMaximizeIcon( String windowStyle ) {
|
||||||
|
super( windowStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (symbolHeight * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int thickness = (int) scaleFactor;
|
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||||
|
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
|
||||||
|
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||||
|
|
||||||
g.fill( FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
g.fill( SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix, iy, iwh, iwh, thickness, arc, arc, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix, iy, iwh, iwh, thickness ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.awt.geom.Area;
|
|||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "restore" icon for windows (frames and dialogs).
|
* "restore" icon for windows (frames and dialogs).
|
||||||
@@ -31,25 +32,47 @@ public class FlatWindowRestoreIcon
|
|||||||
extends FlatWindowAbstractIcon
|
extends FlatWindowAbstractIcon
|
||||||
{
|
{
|
||||||
public FlatWindowRestoreIcon() {
|
public FlatWindowRestoreIcon() {
|
||||||
|
this( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.2 */
|
||||||
|
public FlatWindowRestoreIcon( String windowStyle ) {
|
||||||
|
super( windowStyle );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||||
int iwh = (int) (10 * scaleFactor);
|
int iwh = (int) (symbolHeight * scaleFactor);
|
||||||
int ix = x + ((width - iwh) / 2);
|
int ix = x + ((width - iwh) / 2);
|
||||||
int iy = y + ((height - iwh) / 2);
|
int iy = y + ((height - iwh) / 2);
|
||||||
int thickness = (int) scaleFactor;
|
boolean isWindows10 = SystemInfo.isWindows_10_orLater && !SystemInfo.isWindows_11_orLater;
|
||||||
|
float thickness = Math.max( isWindows10 ? (int) scaleFactor : (float) scaleFactor, 1 );
|
||||||
|
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||||
|
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
||||||
|
|
||||||
int rwh = (int) (8 * scaleFactor);
|
int rwh = (int) ((symbolHeight - 2) * scaleFactor);
|
||||||
int ro2 = iwh - rwh;
|
int ro2 = iwh - rwh;
|
||||||
|
|
||||||
Path2D r1 = FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
// upper-right rectangle
|
||||||
Path2D r2 = FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
Path2D r1 = SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix + ro2, iy, rwh, rwh, thickness, arc, arcOuter, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||||
|
|
||||||
|
// lower-left rectangle
|
||||||
|
Path2D r2 = SystemInfo.isWindows_11_orLater
|
||||||
|
? FlatUIUtils.createRoundRectangle( ix, iy + ro2, rwh, rwh, thickness, arc, arc, arc, arc )
|
||||||
|
: FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||||
|
|
||||||
|
// paint upper-right rectangle
|
||||||
Area area = new Area( r1 );
|
Area area = new Area( r1 );
|
||||||
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
if( SystemInfo.isWindows_11_orLater ) {
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( ix, (float) (iy + scaleFactor), rwh, rwh ) ) );
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( (float) (ix + scaleFactor), iy + ro2, rwh, rwh ) ) );
|
||||||
|
} else
|
||||||
|
area.subtract( new Area( new Rectangle2D.Float( ix, iy + ro2, rwh, rwh ) ) );
|
||||||
g.fill( area );
|
g.fill( area );
|
||||||
|
|
||||||
|
// paint lower-left rectangle
|
||||||
g.fill( r2 );
|
g.fill( r2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -502,9 +502,9 @@ class JsonParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHexDigit() {
|
private boolean isHexDigit() {
|
||||||
return current >= '0' && current <= '9'
|
return (current >= '0' && current <= '9')
|
||||||
|| current >= 'a' && current <= 'f'
|
|| (current >= 'a' && current <= 'f')
|
||||||
|| current >= 'A' && current <= 'F';
|
|| (current >= 'A' && current <= 'F');
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEndOfText() {
|
private boolean isEndOfText() {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class Location {
|
|||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (getClass() != obj.getClass()) {
|
if (!(obj instanceof Location)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Location other = (Location)obj;
|
Location other = (Location)obj;
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package com.formdev.flatlaf.resources;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
* The only purpose of this file is to add a .class file to this package to make it non-empty.
|
||||||
* Otherwise the compiler outputs a warning because this package is opend in module-info.java.
|
* Otherwise, the compiler outputs a warning because this package is opened in module-info.java.
|
||||||
* Also when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
* Also, when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.themes;
|
||||||
|
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.FlatDarkLaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Flat LaF that imitates macOS dark look.
|
||||||
|
* <p>
|
||||||
|
* The UI defaults are loaded from {@code FlatMacDarkLaf.properties},
|
||||||
|
* {@code FlatDarkLaf.properties} and {@code FlatLaf.properties}.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public class FlatMacDarkLaf
|
||||||
|
extends FlatDarkLaf
|
||||||
|
{
|
||||||
|
public static final String NAME = "FlatLaf macOS Dark";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the application look and feel to this LaF
|
||||||
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*/
|
||||||
|
public static boolean setup() {
|
||||||
|
return setup( new FlatMacDarkLaf() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds this look and feel to the set of available look and feels.
|
||||||
|
* <p>
|
||||||
|
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||||
|
* to query available LaFs and display them to the user in a combobox.
|
||||||
|
*/
|
||||||
|
public static void installLafInfo() {
|
||||||
|
installLafInfo( NAME, FlatMacDarkLaf.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "FlatLaf macOS Dark Look and Feel";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDark() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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.themes;
|
||||||
|
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Flat LaF that imitates macOS light look.
|
||||||
|
* <p>
|
||||||
|
* The UI defaults are loaded from {@code FlatMacLightLaf.properties},
|
||||||
|
* {@code FlatLightLaf.properties} and {@code FlatLaf.properties}.
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3
|
||||||
|
*/
|
||||||
|
public class FlatMacLightLaf
|
||||||
|
extends FlatLightLaf
|
||||||
|
{
|
||||||
|
public static final String NAME = "FlatLaf macOS Light";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the application look and feel to this LaF
|
||||||
|
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||||
|
*/
|
||||||
|
public static boolean setup() {
|
||||||
|
return setup( new FlatMacLightLaf() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds this look and feel to the set of available look and feels.
|
||||||
|
* <p>
|
||||||
|
* Useful if your application uses {@link UIManager#getInstalledLookAndFeels()}
|
||||||
|
* to query available LaFs and display them to the user in a combobox.
|
||||||
|
*/
|
||||||
|
public static void installLafInfo() {
|
||||||
|
installLafInfo( NAME, FlatMacLightLaf.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "FlatLaf macOS Light Look and Feel";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDark() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicArrowButton;
|
import javax.swing.plaf.basic.BasicArrowButton;
|
||||||
|
|
||||||
@@ -37,19 +38,21 @@ public class FlatArrowButton
|
|||||||
extends BasicArrowButton
|
extends BasicArrowButton
|
||||||
implements UIResource
|
implements UIResource
|
||||||
{
|
{
|
||||||
public static final int DEFAULT_ARROW_WIDTH = 8;
|
public static final int DEFAULT_ARROW_WIDTH = 9;
|
||||||
|
|
||||||
protected final boolean chevron;
|
protected boolean chevron;
|
||||||
protected final Color foreground;
|
protected Color foreground;
|
||||||
protected final Color disabledForeground;
|
protected Color disabledForeground;
|
||||||
protected final Color hoverForeground;
|
protected Color hoverForeground;
|
||||||
protected final Color hoverBackground;
|
protected Color hoverBackground;
|
||||||
protected final Color pressedForeground;
|
protected Color pressedForeground;
|
||||||
protected final Color pressedBackground;
|
protected Color pressedBackground;
|
||||||
|
|
||||||
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
||||||
private int xOffset = 0;
|
private float arrowThickness = 1;
|
||||||
private int yOffset = 0;
|
private float xOffset = 0;
|
||||||
|
private float yOffset = 0;
|
||||||
|
private boolean roundBorderAutoXOffset = true;
|
||||||
|
|
||||||
private boolean hover;
|
private boolean hover;
|
||||||
private boolean pressed;
|
private boolean pressed;
|
||||||
@@ -58,14 +61,8 @@ public class FlatArrowButton
|
|||||||
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
||||||
{
|
{
|
||||||
super( direction, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE );
|
super( direction, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE );
|
||||||
|
updateStyle( type, foreground, disabledForeground, hoverForeground, hoverBackground,
|
||||||
this.chevron = FlatUIUtils.isChevron( type );
|
pressedForeground, pressedBackground );
|
||||||
this.foreground = foreground;
|
|
||||||
this.disabledForeground = disabledForeground;
|
|
||||||
this.hoverForeground = hoverForeground;
|
|
||||||
this.hoverBackground = hoverBackground;
|
|
||||||
this.pressedForeground = pressedForeground;
|
|
||||||
this.pressedBackground = pressedBackground;
|
|
||||||
|
|
||||||
setOpaque( false );
|
setOpaque( false );
|
||||||
setBorder( null );
|
setBorder( null );
|
||||||
@@ -88,19 +85,36 @@ public class FlatArrowButton
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mousePressed( MouseEvent e ) {
|
public void mousePressed( MouseEvent e ) {
|
||||||
pressed = true;
|
if( SwingUtilities.isLeftMouseButton( e ) ) {
|
||||||
repaint();
|
pressed = true;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased( MouseEvent e ) {
|
public void mouseReleased( MouseEvent e ) {
|
||||||
pressed = false;
|
if( SwingUtilities.isLeftMouseButton( e ) ) {
|
||||||
repaint();
|
pressed = false;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public void updateStyle( String type, Color foreground, Color disabledForeground,
|
||||||
|
Color hoverForeground, Color hoverBackground, Color pressedForeground, Color pressedBackground )
|
||||||
|
{
|
||||||
|
this.chevron = FlatUIUtils.isChevron( type );
|
||||||
|
this.foreground = foreground;
|
||||||
|
this.disabledForeground = disabledForeground;
|
||||||
|
this.hoverForeground = hoverForeground;
|
||||||
|
this.hoverBackground = hoverBackground;
|
||||||
|
this.pressedForeground = pressedForeground;
|
||||||
|
this.pressedBackground = pressedBackground;
|
||||||
|
}
|
||||||
|
|
||||||
public int getArrowWidth() {
|
public int getArrowWidth() {
|
||||||
return arrowWidth;
|
return arrowWidth;
|
||||||
}
|
}
|
||||||
@@ -109,6 +123,16 @@ public class FlatArrowButton
|
|||||||
this.arrowWidth = arrowWidth;
|
this.arrowWidth = arrowWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public float getArrowThickness() {
|
||||||
|
return arrowThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public void setArrowThickness( float arrowThickness ) {
|
||||||
|
this.arrowThickness = arrowThickness;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isHover() {
|
protected boolean isHover() {
|
||||||
return hover;
|
return hover;
|
||||||
}
|
}
|
||||||
@@ -117,22 +141,32 @@ public class FlatArrowButton
|
|||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getXOffset() {
|
public float getXOffset() {
|
||||||
return xOffset;
|
return xOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setXOffset( int xOffset ) {
|
public void setXOffset( float xOffset ) {
|
||||||
this.xOffset = xOffset;
|
this.xOffset = xOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYOffset() {
|
public float getYOffset() {
|
||||||
return yOffset;
|
return yOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setYOffset( int yOffset ) {
|
public void setYOffset( float yOffset ) {
|
||||||
this.yOffset = yOffset;
|
this.yOffset = yOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public boolean isRoundBorderAutoXOffset() {
|
||||||
|
return roundBorderAutoXOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3 */
|
||||||
|
public void setRoundBorderAutoXOffset( boolean roundBorderAutoXOffset ) {
|
||||||
|
this.roundBorderAutoXOffset = roundBorderAutoXOffset;
|
||||||
|
}
|
||||||
|
|
||||||
protected Color deriveBackground( Color background ) {
|
protected Color deriveBackground( Color background ) {
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
@@ -196,14 +230,17 @@ public class FlatArrowButton
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void paintArrow( Graphics2D g ) {
|
protected void paintArrow( Graphics2D g ) {
|
||||||
boolean vert = (direction == NORTH || direction == SOUTH);
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
// move arrow for round borders
|
// move arrow for round borders
|
||||||
Container parent = getParent();
|
if( isRoundBorderAutoXOffset() ) {
|
||||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
Container parent = getParent();
|
||||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
boolean vert = (direction == NORTH || direction == SOUTH);
|
||||||
|
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||||
|
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||||
|
}
|
||||||
|
|
||||||
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron, arrowWidth, xOffset, yOffset );
|
FlatUIUtils.paintArrow( g, x, 0, getWidth(), getHeight(), getDirection(), chevron,
|
||||||
|
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,34 +22,34 @@ import java.awt.Component;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.KeyboardFocusManager;
|
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSpinner;
|
import javax.swing.JSpinner;
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.JTextField;
|
|
||||||
import javax.swing.JTree;
|
|
||||||
import javax.swing.JViewport;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.basic.BasicBorders;
|
import javax.swing.plaf.basic.BasicBorders;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||||
import com.formdev.flatlaf.util.DerivedColor;
|
import com.formdev.flatlaf.util.DerivedColor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for various components (e.g. {@link javax.swing.JTextField}).
|
* Border for various components (e.g. {@link javax.swing.JTextField}).
|
||||||
*
|
* <p>
|
||||||
* There is empty space around the component border, if Component.focusWidth is greater than zero,
|
* There is empty space around the component border, if Component.focusWidth is greater than zero,
|
||||||
* which is used to paint outer focus border.
|
* which is used to paint outer focus border.
|
||||||
*
|
* <p>
|
||||||
* Because there is empty space (if outer focus border is not painted),
|
* Because there is empty space (if outer focus border is not painted),
|
||||||
* UI delegates that use this border (or subclasses) must invoke
|
* UI delegates that use this border (or subclasses) must invoke
|
||||||
* {@link FlatUIUtils#paintParentBackground} to paint the empty space correctly.
|
* {@link FlatUIUtils#paintParentBackground} to fill the empty space correctly.
|
||||||
*
|
*
|
||||||
* @uiDefault Component.focusWidth int
|
* @uiDefault Component.focusWidth int
|
||||||
* @uiDefault Component.innerFocusWidth int or float
|
* @uiDefault Component.innerFocusWidth int or float
|
||||||
|
* @uiDefault Component.innerOutlineWidth int or float
|
||||||
|
* @uiDefault Component.borderWidth int or float
|
||||||
|
*
|
||||||
* @uiDefault Component.focusColor Color
|
* @uiDefault Component.focusColor Color
|
||||||
* @uiDefault Component.borderColor Color
|
* @uiDefault Component.borderColor Color
|
||||||
* @uiDefault Component.disabledBorderColor Color
|
* @uiDefault Component.disabledBorderColor Color
|
||||||
@@ -59,26 +59,56 @@ import com.formdev.flatlaf.util.DerivedColor;
|
|||||||
* @uiDefault Component.error.focusedBorderColor Color
|
* @uiDefault Component.error.focusedBorderColor Color
|
||||||
* @uiDefault Component.warning.borderColor Color
|
* @uiDefault Component.warning.borderColor Color
|
||||||
* @uiDefault Component.warning.focusedBorderColor Color
|
* @uiDefault Component.warning.focusedBorderColor Color
|
||||||
|
* @uiDefault Component.success.borderColor Color
|
||||||
|
* @uiDefault Component.success.focusedBorderColor Color
|
||||||
* @uiDefault Component.custom.borderColor Color
|
* @uiDefault Component.custom.borderColor Color
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatBorder
|
public class FlatBorder
|
||||||
extends BasicBorders.MarginBorder
|
extends BasicBorders.MarginBorder
|
||||||
|
implements StyleableBorder
|
||||||
{
|
{
|
||||||
protected final int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
@Styleable protected int focusWidth = UIManager.getInt( "Component.focusWidth" );
|
||||||
protected final float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
@Styleable protected float innerFocusWidth = FlatUIUtils.getUIFloat( "Component.innerFocusWidth", 0 );
|
||||||
protected final float innerOutlineWidth = FlatUIUtils.getUIFloat( "Component.innerOutlineWidth", 0 );
|
@Styleable protected float innerOutlineWidth = FlatUIUtils.getUIFloat( "Component.innerOutlineWidth", 0 );
|
||||||
protected final Color focusColor = UIManager.getColor( "Component.focusColor" );
|
/** @since 2 */ @Styleable protected float borderWidth = FlatUIUtils.getUIFloat( "Component.borderWidth", 1 );
|
||||||
protected final Color borderColor = UIManager.getColor( "Component.borderColor" );
|
|
||||||
protected final Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
|
||||||
protected final Color focusedBorderColor = UIManager.getColor( "Component.focusedBorderColor" );
|
|
||||||
|
|
||||||
protected final Color errorBorderColor = UIManager.getColor( "Component.error.borderColor" );
|
@Styleable protected Color focusColor = UIManager.getColor( "Component.focusColor" );
|
||||||
protected final Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
@Styleable protected Color borderColor = UIManager.getColor( "Component.borderColor" );
|
||||||
protected final Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
@Styleable protected Color disabledBorderColor = UIManager.getColor( "Component.disabledBorderColor" );
|
||||||
protected final Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
@Styleable protected Color focusedBorderColor = UIManager.getColor( "Component.focusedBorderColor" );
|
||||||
protected final Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
|
||||||
|
@Styleable(dot=true) protected Color errorBorderColor = UIManager.getColor( "Component.error.borderColor" );
|
||||||
|
@Styleable(dot=true) protected Color errorFocusedBorderColor = UIManager.getColor( "Component.error.focusedBorderColor" );
|
||||||
|
@Styleable(dot=true) protected Color warningBorderColor = UIManager.getColor( "Component.warning.borderColor" );
|
||||||
|
@Styleable(dot=true) protected Color warningFocusedBorderColor = UIManager.getColor( "Component.warning.focusedBorderColor" );
|
||||||
|
/** @since 3.6 */ @Styleable(dot=true) protected Color successBorderColor = UIManager.getColor( "Component.success.borderColor" );
|
||||||
|
/** @since 3.6 */ @Styleable(dot=true) protected Color successFocusedBorderColor = UIManager.getColor( "Component.success.focusedBorderColor" );
|
||||||
|
@Styleable(dot=true) protected Color customBorderColor = UIManager.getColor( "Component.custom.borderColor" );
|
||||||
|
|
||||||
|
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||||
|
/** @since 2 */ @Styleable protected String outline;
|
||||||
|
/** @since 2 */ @Styleable protected Color outlineColor;
|
||||||
|
/** @since 2 */ @Styleable protected Color outlineFocusedColor;
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
@@ -87,9 +117,11 @@ public class FlatBorder
|
|||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
float focusWidth = scale( (float) getFocusWidth( c ) );
|
float focusWidth = scale( (float) getFocusWidth( c ) );
|
||||||
float borderWidth = scale( (float) getBorderWidth( c ) );
|
float focusInnerWidth = 0;
|
||||||
|
float borderWidth = scale( getBorderWidth( c ) );
|
||||||
float arc = scale( (float) getArc( c ) );
|
float arc = scale( (float) getArc( c ) );
|
||||||
Color outlineColor = getOutlineColor( c );
|
Color outlineColor = getOutlineColor( c );
|
||||||
|
Color focusColor = null;
|
||||||
|
|
||||||
// paint outer border
|
// paint outer border
|
||||||
if( outlineColor != null || isFocused( c ) ) {
|
if( outlineColor != null || isFocused( c ) ) {
|
||||||
@@ -98,15 +130,16 @@ public class FlatBorder
|
|||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
if( focusWidth > 0 || innerWidth > 0 ) {
|
if( focusWidth > 0 || innerWidth > 0 ) {
|
||||||
g2.setColor( (outlineColor != null) ? outlineColor : getFocusColor( c ) );
|
focusColor = (outlineColor != null) ? outlineColor : getFocusColor( c );
|
||||||
FlatUIUtils.paintComponentOuterBorder( g2, x, y, width, height,
|
focusInnerWidth = borderWidth + scale( innerWidth );
|
||||||
focusWidth, borderWidth + scale( innerWidth ), arc );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// paint border
|
// paint border
|
||||||
g2.setPaint( (outlineColor != null) ? outlineColor : getBorderColor( c ) );
|
Paint borderColor = (outlineColor != null) ? outlineColor : getBorderColor( c );
|
||||||
FlatUIUtils.paintComponentBorder( g2, x, y, width, height, focusWidth, borderWidth, arc );
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||||
|
focusWidth, 1, focusInnerWidth, borderWidth, arc,
|
||||||
|
focusColor, borderColor, null, c instanceof JScrollPane );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
@@ -121,6 +154,17 @@ public class FlatBorder
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
Object outline = ((JComponent)c).getClientProperty( FlatClientProperties.OUTLINE );
|
Object outline = ((JComponent)c).getClientProperty( FlatClientProperties.OUTLINE );
|
||||||
|
if( outline == null )
|
||||||
|
outline = this.outline;
|
||||||
|
if( outline == null ) {
|
||||||
|
if( outlineColor != null && outlineFocusedColor != null )
|
||||||
|
outline = new Color[] { outlineFocusedColor, outlineColor };
|
||||||
|
else if( outlineColor != null )
|
||||||
|
outline = outlineColor;
|
||||||
|
else if( outlineFocusedColor != null )
|
||||||
|
outline = outlineFocusedColor;
|
||||||
|
}
|
||||||
|
|
||||||
if( outline instanceof String ) {
|
if( outline instanceof String ) {
|
||||||
switch( (String) outline ) {
|
switch( (String) outline ) {
|
||||||
case FlatClientProperties.OUTLINE_ERROR:
|
case FlatClientProperties.OUTLINE_ERROR:
|
||||||
@@ -128,6 +172,9 @@ public class FlatBorder
|
|||||||
|
|
||||||
case FlatClientProperties.OUTLINE_WARNING:
|
case FlatClientProperties.OUTLINE_WARNING:
|
||||||
return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor;
|
return isFocused( c ) ? warningFocusedBorderColor : warningBorderColor;
|
||||||
|
|
||||||
|
case FlatClientProperties.OUTLINE_SUCCESS:
|
||||||
|
return isFocused( c ) ? successFocusedBorderColor : successBorderColor;
|
||||||
}
|
}
|
||||||
} else if( outline instanceof Color ) {
|
} else if( outline instanceof Color ) {
|
||||||
Color color = (Color) outline;
|
Color color = (Color) outline;
|
||||||
@@ -154,8 +201,7 @@ public class FlatBorder
|
|||||||
protected boolean isEnabled( Component c ) {
|
protected boolean isEnabled( Component c ) {
|
||||||
if( c instanceof JScrollPane ) {
|
if( c instanceof JScrollPane ) {
|
||||||
// check whether view component is disabled
|
// check whether view component is disabled
|
||||||
JViewport viewport = ((JScrollPane)c).getViewport();
|
Component view = FlatScrollPaneUI.getView( (JScrollPane) c );
|
||||||
Component view = (viewport != null) ? viewport.getView() : null;
|
|
||||||
if( view != null && !isEnabled( view ) )
|
if( view != null && !isEnabled( view ) )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -164,37 +210,13 @@ public class FlatBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isFocused( Component c ) {
|
protected boolean isFocused( Component c ) {
|
||||||
if( c instanceof JScrollPane ) {
|
if( c instanceof JScrollPane )
|
||||||
JViewport viewport = ((JScrollPane)c).getViewport();
|
return FlatScrollPaneUI.isPermanentFocusOwner( (JScrollPane) c );
|
||||||
Component view = (viewport != null) ? viewport.getView() : null;
|
else if( c instanceof JComboBox )
|
||||||
if( view != null ) {
|
return FlatComboBoxUI.isPermanentFocusOwner( (JComboBox<?>) c );
|
||||||
if( FlatUIUtils.isPermanentFocusOwner( view ) )
|
else if( c instanceof JSpinner )
|
||||||
return true;
|
return FlatSpinnerUI.isPermanentFocusOwner( (JSpinner) c );
|
||||||
|
else
|
||||||
if( (view instanceof JTable && ((JTable)view).isEditing()) ||
|
|
||||||
(view instanceof JTree && ((JTree)view).isEditing()) )
|
|
||||||
{
|
|
||||||
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
|
||||||
if( focusOwner != null )
|
|
||||||
return SwingUtilities.isDescendingFrom( focusOwner, view );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else if( c instanceof JComboBox && ((JComboBox<?>)c).isEditable() ) {
|
|
||||||
Component editorComponent = ((JComboBox<?>)c).getEditor().getEditorComponent();
|
|
||||||
return (editorComponent != null) ? FlatUIUtils.isPermanentFocusOwner( editorComponent ) : false;
|
|
||||||
} else if( c instanceof JSpinner ) {
|
|
||||||
if( FlatUIUtils.isPermanentFocusOwner( c ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
JComponent editor = ((JSpinner)c).getEditor();
|
|
||||||
if( editor instanceof JSpinner.DefaultEditor ) {
|
|
||||||
JTextField textField = ((JSpinner.DefaultEditor)editor).getTextField();
|
|
||||||
if( textField != null )
|
|
||||||
return FlatUIUtils.isPermanentFocusOwner( textField );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
return FlatUIUtils.isPermanentFocusOwner( c );
|
return FlatUIUtils.isPermanentFocusOwner( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,13 +227,14 @@ public class FlatBorder
|
|||||||
@Override
|
@Override
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
float focusWidth = scale( (float) getFocusWidth( c ) );
|
float focusWidth = scale( (float) getFocusWidth( c ) );
|
||||||
float ow = focusWidth + scale( (float) getLineWidth( c ) );
|
int ow = Math.round( focusWidth + scale( (float) getLineWidth( c ) ) );
|
||||||
|
|
||||||
insets = super.getBorderInsets( c, insets );
|
insets = super.getBorderInsets( c, insets );
|
||||||
insets.top = Math.round( scale( (float) insets.top ) + ow );
|
|
||||||
insets.left = Math.round( scale( (float) insets.left ) + ow );
|
insets.top = scale( insets.top ) + ow;
|
||||||
insets.bottom = Math.round( scale( (float) insets.bottom ) + ow );
|
insets.left = scale( insets.left ) + ow;
|
||||||
insets.right = Math.round( scale( (float) insets.right ) + ow );
|
insets.bottom = scale( insets.bottom ) + ow;
|
||||||
|
insets.right = scale( insets.right ) + ow;
|
||||||
|
|
||||||
if( isCellEditor( c ) ) {
|
if( isCellEditor( c ) ) {
|
||||||
// remove top and bottom insets if used as cell editor
|
// remove top and bottom insets if used as cell editor
|
||||||
@@ -256,12 +279,12 @@ public class FlatBorder
|
|||||||
* Returns the (unscaled) line thickness used to paint the border.
|
* Returns the (unscaled) line thickness used to paint the border.
|
||||||
* This may be different to {@link #getLineWidth}.
|
* This may be different to {@link #getLineWidth}.
|
||||||
*/
|
*/
|
||||||
protected int getBorderWidth( Component c ) {
|
protected float getBorderWidth( Component c ) {
|
||||||
return getLineWidth( c );
|
return borderWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the (unscaled) arc diameter of the border.
|
* Returns the (unscaled) arc diameter of the border corners.
|
||||||
*/
|
*/
|
||||||
protected int getArc( Component c ) {
|
protected int getArc( Component c ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -20,56 +20,88 @@ import java.awt.Color;
|
|||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.GradientPaint;
|
import java.awt.GradientPaint;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Border for {@link javax.swing.JButton}.
|
* Border for {@link javax.swing.JButton}.
|
||||||
*
|
*
|
||||||
|
* @uiDefault Button.arc int
|
||||||
|
* @uiDefault Button.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth
|
||||||
|
* @uiDefault Button.borderWidth int or float optional; defaults to Component.borderWidth
|
||||||
|
*
|
||||||
* @uiDefault Button.borderColor Color
|
* @uiDefault Button.borderColor Color
|
||||||
* @uiDefault Button.startBorderColor Color optional; if set, a gradient paint is used and Button.borderColor is ignored
|
* @uiDefault Button.startBorderColor Color optional; if set, a gradient paint is used and Button.borderColor is ignored
|
||||||
* @uiDefault Button.endBorderColor Color optional; if set, a gradient paint is used
|
* @uiDefault Button.endBorderColor Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.disabledBorderColor Color
|
* @uiDefault Button.disabledBorderColor Color
|
||||||
* @uiDefault Button.focusedBorderColor Color
|
* @uiDefault Button.focusedBorderColor Color
|
||||||
* @uiDefault Button.hoverBorderColor Color optional
|
* @uiDefault Button.hoverBorderColor Color optional
|
||||||
|
* @uiDefault Button.pressedBorderColor Color optional
|
||||||
|
*
|
||||||
|
* @uiDefault Button.selectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.disabledSelectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.focusedSelectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.hoverSelectedBorderColor Color optional
|
||||||
|
* @uiDefault Button.pressedSelectedBorderColor Color optional
|
||||||
|
*
|
||||||
|
* @uiDefault Button.default.borderWidth int or float
|
||||||
* @uiDefault Button.default.borderColor Color
|
* @uiDefault Button.default.borderColor Color
|
||||||
* @uiDefault Button.default.startBorderColor Color optional; if set, a gradient paint is used and Button.default.borderColor is ignored
|
* @uiDefault Button.default.startBorderColor Color optional; if set, a gradient paint is used and Button.default.borderColor is ignored
|
||||||
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.default.hoverBorderColor Color optional
|
|
||||||
* @uiDefault Button.default.focusedBorderColor Color
|
* @uiDefault Button.default.focusedBorderColor Color
|
||||||
* @uiDefault Button.default.focusColor Color
|
* @uiDefault Button.default.focusColor Color
|
||||||
* @uiDefault Button.borderWidth int
|
* @uiDefault Button.default.pressedBorderColor Color optional
|
||||||
* @uiDefault Button.default.borderWidth int
|
* @uiDefault Button.default.hoverBorderColor Color optional
|
||||||
* @uiDefault Button.innerFocusWidth int or float optional; defaults to Component.innerFocusWidth
|
*
|
||||||
|
* @uiDefault Button.toolbar.focusWidth int or float optional; default is 1.5
|
||||||
|
* @uiDefault Button.toolbar.focusColor Color optional; defaults to Component.focusColor
|
||||||
* @uiDefault Button.toolbar.margin Insets
|
* @uiDefault Button.toolbar.margin Insets
|
||||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||||
* @uiDefault Button.arc int
|
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatButtonBorder
|
public class FlatButtonBorder
|
||||||
extends FlatBorder
|
extends FlatBorder
|
||||||
{
|
{
|
||||||
protected final Color borderColor = FlatUIUtils.getUIColor( "Button.startBorderColor", "Button.borderColor" );
|
@Styleable protected int arc = UIManager.getInt( "Button.arc" );
|
||||||
protected final Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
|
||||||
protected final Color disabledBorderColor = UIManager.getColor( "Button.disabledBorderColor" );
|
protected Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
||||||
protected final Color focusedBorderColor = UIManager.getColor( "Button.focusedBorderColor" );
|
@Styleable protected Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
||||||
protected final Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
/** @since 3.5 */ @Styleable protected Color pressedBorderColor = UIManager.getColor( "Button.pressedBorderColor" );
|
||||||
protected final Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
|
||||||
protected final Color defaultEndBorderColor = UIManager.getColor( "Button.default.endBorderColor" );
|
/** @since 3.5 */ @Styleable protected Color selectedBorderColor = UIManager.getColor( "Button.selectedBorderColor" );
|
||||||
protected final Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
/** @since 3.5 */ @Styleable protected Color disabledSelectedBorderColor = UIManager.getColor( "Button.disabledSelectedBorderColor" );
|
||||||
protected final Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
/** @since 3.5 */ @Styleable protected Color focusedSelectedBorderColor = UIManager.getColor( "Button.focusedSelectedBorderColor" );
|
||||||
protected final Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
/** @since 3.5 */ @Styleable protected Color hoverSelectedBorderColor = UIManager.getColor( "Button.hoverSelectedBorderColor" );
|
||||||
protected final int borderWidth = UIManager.getInt( "Button.borderWidth" );
|
/** @since 3.5 */ @Styleable protected Color pressedSelectedBorderColor = UIManager.getColor( "Button.pressedSelectedBorderColor" );
|
||||||
protected final int defaultBorderWidth = UIManager.getInt( "Button.default.borderWidth" );
|
|
||||||
protected final float buttonInnerFocusWidth = FlatUIUtils.getUIFloat( "Button.innerFocusWidth", innerFocusWidth );
|
@Styleable(dot=true) protected float defaultBorderWidth = FlatUIUtils.getUIFloat( "Button.default.borderWidth", 1 );
|
||||||
protected final Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" );
|
@Styleable(dot=true) protected Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
||||||
protected final Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
protected Color defaultEndBorderColor = UIManager.getColor( "Button.default.endBorderColor" );
|
||||||
protected final int arc = UIManager.getInt( "Button.arc" );
|
@Styleable(dot=true) protected Color defaultFocusedBorderColor = UIManager.getColor( "Button.default.focusedBorderColor" );
|
||||||
|
@Styleable(dot=true) protected Color defaultFocusColor = UIManager.getColor( "Button.default.focusColor" );
|
||||||
|
@Styleable(dot=true) protected Color defaultHoverBorderColor = UIManager.getColor( "Button.default.hoverBorderColor" );
|
||||||
|
/** @since 3.5 */ @Styleable(dot=true) protected Color defaultPressedBorderColor = UIManager.getColor( "Button.default.pressedBorderColor" );
|
||||||
|
|
||||||
|
/** @since 1.4 */ @Styleable(dot=true) protected float toolbarFocusWidth = FlatUIUtils.getUIFloat( "Button.toolbar.focusWidth", 1.5f );
|
||||||
|
/** @since 1.4 */ @Styleable(dot=true) protected Color toolbarFocusColor = UIManager.getColor( "Button.toolbar.focusColor" );
|
||||||
|
@Styleable(dot=true) protected Insets toolbarMargin = UIManager.getInsets( "Button.toolbar.margin" );
|
||||||
|
@Styleable(dot=true) protected Insets toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
||||||
|
|
||||||
|
public FlatButtonBorder() {
|
||||||
|
innerFocusWidth = FlatUIUtils.getUIFloat( "Button.innerFocusWidth", innerFocusWidth );
|
||||||
|
borderWidth = FlatUIUtils.getUIFloat( "Button.borderWidth", borderWidth );
|
||||||
|
|
||||||
|
borderColor = FlatUIUtils.getUIColor( "Button.startBorderColor", "Button.borderColor" );
|
||||||
|
disabledBorderColor = UIManager.getColor( "Button.disabledBorderColor" );
|
||||||
|
focusedBorderColor = UIManager.getColor( "Button.focusedBorderColor" );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
@@ -79,11 +111,40 @@ public class FlatButtonBorder
|
|||||||
!FlatButtonUI.isHelpButton( c ) &&
|
!FlatButtonUI.isHelpButton( c ) &&
|
||||||
!FlatToggleButtonUI.isTabButton( c ) )
|
!FlatToggleButtonUI.isTabButton( c ) )
|
||||||
super.paintBorder( c, g, x, y, width, height );
|
super.paintBorder( c, g, x, y, width, height );
|
||||||
|
else if( FlatButtonUI.isToolBarButton( c ) && isFocused( c ) )
|
||||||
|
paintToolBarFocus( c, g, x, y, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 1.4 */
|
||||||
|
protected void paintToolBarFocus( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
|
try {
|
||||||
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
|
float focusWidth = UIScale.scale( toolbarFocusWidth );
|
||||||
|
float arc = UIScale.scale( (float) getArc( c ) );
|
||||||
|
Color outlineColor = getOutlineColor( c );
|
||||||
|
|
||||||
|
Insets spacing = UIScale.scale( toolbarSpacingInsets );
|
||||||
|
x += spacing.left;
|
||||||
|
y += spacing.top;
|
||||||
|
width -= spacing.left + spacing.right;
|
||||||
|
height -= spacing.top + spacing.bottom;
|
||||||
|
|
||||||
|
Color color = (outlineColor != null) ? outlineColor : getFocusColor( c );
|
||||||
|
// not using focus border painting of paintOutlinedComponent() here
|
||||||
|
// because its round edges look too "thick"
|
||||||
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height, 0, 0, 0, focusWidth, arc, null, color, null );
|
||||||
|
} finally {
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Color getFocusColor( Component c ) {
|
protected Color getFocusColor( Component c ) {
|
||||||
return FlatButtonUI.isDefaultButton( c ) ? defaultFocusColor : super.getFocusColor( c );
|
return (toolbarFocusColor != null && FlatButtonUI.isToolBarButton( c ))
|
||||||
|
? toolbarFocusColor
|
||||||
|
: (FlatButtonUI.isDefaultButton( c ) ? defaultFocusColor : super.getFocusColor( c ));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -94,12 +155,13 @@ public class FlatButtonBorder
|
|||||||
@Override
|
@Override
|
||||||
protected Paint getBorderColor( Component c ) {
|
protected Paint getBorderColor( Component c ) {
|
||||||
boolean def = FlatButtonUI.isDefaultButton( c );
|
boolean def = FlatButtonUI.isDefaultButton( c );
|
||||||
|
boolean selected = (c instanceof AbstractButton && ((AbstractButton)c).isSelected());
|
||||||
Paint color = FlatButtonUI.buttonStateColor( c,
|
Paint color = FlatButtonUI.buttonStateColor( c,
|
||||||
def ? defaultBorderColor : borderColor,
|
def ? defaultBorderColor : ((selected && selectedBorderColor != null) ? selectedBorderColor : borderColor),
|
||||||
disabledBorderColor,
|
(selected && disabledSelectedBorderColor != null) ? disabledSelectedBorderColor : disabledBorderColor,
|
||||||
def ? defaultFocusedBorderColor : focusedBorderColor,
|
def ? defaultFocusedBorderColor : ((selected && focusedSelectedBorderColor != null) ? focusedSelectedBorderColor : focusedBorderColor),
|
||||||
def ? defaultHoverBorderColor : hoverBorderColor,
|
def ? defaultHoverBorderColor : ((selected && hoverSelectedBorderColor != null) ? hoverSelectedBorderColor : hoverBorderColor),
|
||||||
null );
|
def ? defaultPressedBorderColor : ((selected && pressedSelectedBorderColor != null) ? pressedSelectedBorderColor : pressedBorderColor) );
|
||||||
|
|
||||||
// change to gradient paint if start/end colors are specified
|
// change to gradient paint if start/end colors are specified
|
||||||
Color startBg = def ? defaultBorderColor : borderColor;
|
Color startBg = def ? defaultBorderColor : borderColor;
|
||||||
@@ -114,7 +176,7 @@ public class FlatButtonBorder
|
|||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
if( FlatButtonUI.isToolBarButton( c ) ) {
|
if( FlatButtonUI.isToolBarButton( c ) ) {
|
||||||
// In toolbars, use button margin only if explicitly set.
|
// In toolbars, use button margin only if explicitly set.
|
||||||
// Otherwise use toolbar margin specified in UI defaults.
|
// Otherwise, use toolbar margin specified in UI defaults.
|
||||||
Insets margin = (c instanceof AbstractButton)
|
Insets margin = (c instanceof AbstractButton)
|
||||||
? ((AbstractButton)c).getMargin()
|
? ((AbstractButton)c).getMargin()
|
||||||
: null;
|
: null;
|
||||||
@@ -138,12 +200,7 @@ public class FlatButtonBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getInnerFocusWidth( Component c ) {
|
protected float getBorderWidth( Component c ) {
|
||||||
return buttonInnerFocusWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getBorderWidth( Component c ) {
|
|
||||||
return FlatButtonUI.isDefaultButton( c ) ? defaultBorderWidth : borderWidth;
|
return FlatButtonUI.isDefaultButton( c ) ? defaultBorderWidth : borderWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
|||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.FontMetrics;
|
import java.awt.FontMetrics;
|
||||||
@@ -28,22 +29,41 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.geom.RoundRectangle2D;
|
import java.awt.geom.RoundRectangle2D;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.ButtonModel;
|
import javax.swing.ButtonModel;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JTextField;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.plaf.ButtonUI;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
|
import javax.swing.plaf.ToolBarUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicButtonListener;
|
import javax.swing.plaf.basic.BasicButtonListener;
|
||||||
import javax.swing.plaf.basic.BasicButtonUI;
|
import javax.swing.plaf.basic.BasicButtonUI;
|
||||||
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
|
import javax.swing.text.View;
|
||||||
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.icons.FlatHelpButtonIcon;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
|
||||||
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,20 +85,27 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
* @uiDefault Button.startBackground Color optional; if set, a gradient paint is used and Button.background is ignored
|
||||||
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
|
* @uiDefault Button.endBackground Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.focusedBackground Color optional
|
* @uiDefault Button.focusedBackground Color optional
|
||||||
|
* @uiDefault Button.focusedForeground Color optional
|
||||||
* @uiDefault Button.hoverBackground Color optional
|
* @uiDefault Button.hoverBackground Color optional
|
||||||
|
* @uiDefault Button.hoverForeground Color optional
|
||||||
* @uiDefault Button.pressedBackground Color optional
|
* @uiDefault Button.pressedBackground Color optional
|
||||||
|
* @uiDefault Button.pressedForeground Color optional
|
||||||
* @uiDefault Button.selectedBackground Color
|
* @uiDefault Button.selectedBackground Color
|
||||||
* @uiDefault Button.selectedForeground Color
|
* @uiDefault Button.selectedForeground Color
|
||||||
* @uiDefault Button.disabledBackground Color optional
|
* @uiDefault Button.disabledBackground Color optional
|
||||||
* @uiDefault Button.disabledText Color
|
* @uiDefault Button.disabledText Color
|
||||||
* @uiDefault Button.disabledSelectedBackground Color
|
* @uiDefault Button.disabledSelectedBackground Color
|
||||||
|
* @uiDefault Button.disabledSelectedForeground Color optional
|
||||||
* @uiDefault Button.default.background Color
|
* @uiDefault Button.default.background Color
|
||||||
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
|
* @uiDefault Button.default.startBackground Color optional; if set, a gradient paint is used and Button.default.background is ignored
|
||||||
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
|
* @uiDefault Button.default.endBackground Color optional; if set, a gradient paint is used
|
||||||
* @uiDefault Button.default.foreground Color
|
* @uiDefault Button.default.foreground Color
|
||||||
* @uiDefault Button.default.focusedBackground Color optional
|
* @uiDefault Button.default.focusedBackground Color optional
|
||||||
|
* @uiDefault Button.default.focusedForeground Color optional
|
||||||
* @uiDefault Button.default.hoverBackground Color optional
|
* @uiDefault Button.default.hoverBackground Color optional
|
||||||
|
* @uiDefault Button.default.hoverForeground Color optional
|
||||||
* @uiDefault Button.default.pressedBackground Color optional
|
* @uiDefault Button.default.pressedBackground Color optional
|
||||||
|
* @uiDefault Button.default.pressedForeground Color optional
|
||||||
* @uiDefault Button.default.boldText boolean
|
* @uiDefault Button.default.boldText boolean
|
||||||
* @uiDefault Button.paintShadow boolean default is false
|
* @uiDefault Button.paintShadow boolean default is false
|
||||||
* @uiDefault Button.shadowWidth int default is 2
|
* @uiDefault Button.shadowWidth int default is 2
|
||||||
@@ -86,15 +113,21 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault Button.default.shadowColor Color optional
|
* @uiDefault Button.default.shadowColor Color optional
|
||||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||||
* @uiDefault Button.toolbar.hoverBackground Color
|
* @uiDefault Button.toolbar.hoverBackground Color
|
||||||
|
* @uiDefault Button.toolbar.hoverForeground Color optional
|
||||||
* @uiDefault Button.toolbar.pressedBackground Color
|
* @uiDefault Button.toolbar.pressedBackground Color
|
||||||
|
* @uiDefault Button.toolbar.pressedForeground Color optional
|
||||||
* @uiDefault Button.toolbar.selectedBackground Color
|
* @uiDefault Button.toolbar.selectedBackground Color
|
||||||
|
* @uiDefault Button.toolbar.selectedForeground Color optional
|
||||||
|
* @uiDefault Button.toolbar.disabledSelectedBackground Color optional
|
||||||
|
* @uiDefault Button.toolbar.disabledSelectedForeground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatButtonUI
|
public class FlatButtonUI
|
||||||
extends BasicButtonUI
|
extends BasicButtonUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected int iconTextGap;
|
protected int iconTextGap;
|
||||||
|
|
||||||
protected Color background;
|
protected Color background;
|
||||||
@@ -102,38 +135,81 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
protected Color startBackground;
|
protected Color startBackground;
|
||||||
protected Color endBackground;
|
protected Color endBackground;
|
||||||
protected Color focusedBackground;
|
@Styleable protected Color focusedBackground;
|
||||||
protected Color hoverBackground;
|
/** @since 2.3 */ @Styleable protected Color focusedForeground;
|
||||||
protected Color pressedBackground;
|
@Styleable protected Color hoverBackground;
|
||||||
protected Color selectedBackground;
|
/** @since 2.3 */ @Styleable protected Color hoverForeground;
|
||||||
protected Color selectedForeground;
|
@Styleable protected Color pressedBackground;
|
||||||
protected Color disabledBackground;
|
/** @since 2.3 */ @Styleable protected Color pressedForeground;
|
||||||
protected Color disabledText;
|
@Styleable protected Color selectedBackground;
|
||||||
protected Color disabledSelectedBackground;
|
@Styleable protected Color selectedForeground;
|
||||||
|
@Styleable protected Color disabledBackground;
|
||||||
|
@Styleable protected Color disabledText;
|
||||||
|
@Styleable protected Color disabledSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable protected Color disabledSelectedForeground;
|
||||||
|
|
||||||
protected Color defaultBackground;
|
@Styleable(dot=true) protected Color defaultBackground;
|
||||||
protected Color defaultEndBackground;
|
protected Color defaultEndBackground;
|
||||||
protected Color defaultForeground;
|
@Styleable(dot=true) protected Color defaultForeground;
|
||||||
protected Color defaultFocusedBackground;
|
@Styleable(dot=true) protected Color defaultFocusedBackground;
|
||||||
protected Color defaultHoverBackground;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultFocusedForeground;
|
||||||
protected Color defaultPressedBackground;
|
@Styleable(dot=true) protected Color defaultHoverBackground;
|
||||||
protected boolean defaultBoldText;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultHoverForeground;
|
||||||
|
@Styleable(dot=true) protected Color defaultPressedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultPressedForeground;
|
||||||
|
@Styleable(dot=true) protected boolean defaultBoldText;
|
||||||
|
|
||||||
protected int shadowWidth;
|
@Styleable protected boolean paintShadow;
|
||||||
protected Color shadowColor;
|
@Styleable protected int shadowWidth;
|
||||||
protected Color defaultShadowColor;
|
@Styleable protected Color shadowColor;
|
||||||
|
@Styleable(dot=true) protected Color defaultShadowColor;
|
||||||
|
|
||||||
protected Insets toolbarSpacingInsets;
|
@Styleable(dot=true) protected Color toolbarHoverBackground;
|
||||||
protected Color toolbarHoverBackground;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarHoverForeground;
|
||||||
protected Color toolbarPressedBackground;
|
@Styleable(dot=true) protected Color toolbarPressedBackground;
|
||||||
protected Color toolbarSelectedBackground;
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarPressedForeground;
|
||||||
|
@Styleable(dot=true) protected Color toolbarSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarSelectedForeground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedBackground;
|
||||||
|
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarDisabledSelectedForeground;
|
||||||
|
|
||||||
|
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||||
|
/** @since 2 */ @Styleable protected String buttonType;
|
||||||
|
/** @since 2 */ @Styleable protected boolean squareSize;
|
||||||
|
/** @since 2 */ @Styleable protected int minimumHeight;
|
||||||
|
|
||||||
private Icon helpButtonIcon;
|
private Icon helpButtonIcon;
|
||||||
|
private Insets defaultMargin;
|
||||||
|
|
||||||
|
private final boolean shared;
|
||||||
|
private boolean helpButtonIconShared = true;
|
||||||
private boolean defaults_initialized = false;
|
private boolean defaults_initialized = false;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
private AtomicBoolean borderShared;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return FlatUIUtils.createSharedUI( FlatButtonUI.class, FlatButtonUI::new );
|
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||||
|
? FlatUIUtils.createSharedUI( FlatButtonUI.class, () -> new FlatButtonUI( true ) )
|
||||||
|
: new FlatButtonUI( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected FlatButtonUI( boolean shared ) {
|
||||||
|
this.shared = shared;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
if( FlatUIUtils.needsLightAWTPeer( c ) )
|
||||||
|
FlatUIUtils.runWithLightAWTPeerUIDefaults( () -> installUIImpl( c ) );
|
||||||
|
else
|
||||||
|
installUIImpl( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installUIImpl( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle( (AbstractButton) c );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -152,39 +228,47 @@ public class FlatButtonUI
|
|||||||
startBackground = UIManager.getColor( prefix + "startBackground" );
|
startBackground = UIManager.getColor( prefix + "startBackground" );
|
||||||
endBackground = UIManager.getColor( prefix + "endBackground" );
|
endBackground = UIManager.getColor( prefix + "endBackground" );
|
||||||
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
|
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
|
||||||
|
focusedForeground = UIManager.getColor( prefix + "focusedForeground" );
|
||||||
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
|
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
|
||||||
|
hoverForeground = UIManager.getColor( prefix + "hoverForeground" );
|
||||||
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
|
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
|
||||||
|
pressedForeground = UIManager.getColor( prefix + "pressedForeground" );
|
||||||
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
|
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
|
||||||
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
|
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
|
||||||
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
|
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
|
||||||
disabledText = UIManager.getColor( prefix + "disabledText" );
|
disabledText = UIManager.getColor( prefix + "disabledText" );
|
||||||
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
|
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
|
||||||
|
disabledSelectedForeground = UIManager.getColor( prefix + "disabledSelectedForeground" );
|
||||||
if( UIManager.getBoolean( "Button.paintShadow" ) ) {
|
|
||||||
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" );
|
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
|
||||||
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
|
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
|
||||||
defaultForeground = UIManager.getColor( "Button.default.foreground" );
|
defaultForeground = UIManager.getColor( "Button.default.foreground" );
|
||||||
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
|
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
|
||||||
|
defaultFocusedForeground = UIManager.getColor( "Button.default.focusedForeground" );
|
||||||
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
|
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
|
||||||
|
defaultHoverForeground = UIManager.getColor( "Button.default.hoverForeground" );
|
||||||
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
||||||
|
defaultPressedForeground = UIManager.getColor( "Button.default.pressedForeground" );
|
||||||
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
||||||
|
|
||||||
toolbarSpacingInsets = UIManager.getInsets( "Button.toolbar.spacingInsets" );
|
paintShadow = UIManager.getBoolean( "Button.paintShadow" );
|
||||||
|
shadowWidth = FlatUIUtils.getUIInt( "Button.shadowWidth", 2 );
|
||||||
|
shadowColor = UIManager.getColor( "Button.shadowColor" );
|
||||||
|
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
||||||
|
|
||||||
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
||||||
|
toolbarHoverForeground = UIManager.getColor( prefix + "toolbar.hoverForeground" );
|
||||||
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
||||||
|
toolbarPressedForeground = UIManager.getColor( prefix + "toolbar.pressedForeground" );
|
||||||
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
|
toolbarSelectedBackground = UIManager.getColor( prefix + "toolbar.selectedBackground" );
|
||||||
|
toolbarSelectedForeground = UIManager.getColor( prefix + "toolbar.selectedForeground" );
|
||||||
|
toolbarDisabledSelectedBackground = UIManager.getColor( prefix + "toolbar.disabledSelectedBackground" );
|
||||||
|
toolbarDisabledSelectedForeground = UIManager.getColor( prefix + "toolbar.disabledSelectedForeground" );
|
||||||
|
|
||||||
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
|
helpButtonIcon = UIManager.getIcon( "HelpButton.icon" );
|
||||||
|
defaultMargin = UIManager.getInsets( prefix + "margin" );
|
||||||
|
|
||||||
|
helpButtonIconShared = true;
|
||||||
defaults_initialized = true;
|
defaults_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,18 +280,32 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
LookAndFeel.installProperty( b, "opaque", false );
|
LookAndFeel.installProperty( b, "opaque", false );
|
||||||
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
|
LookAndFeel.installProperty( b, "iconTextGap", scale( iconTextGap ) );
|
||||||
|
|
||||||
MigLayoutVisualPadding.install( b );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void uninstallDefaults( AbstractButton b ) {
|
protected void uninstallDefaults( AbstractButton b ) {
|
||||||
super.uninstallDefaults( b );
|
super.uninstallDefaults( b );
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( b );
|
oldStyleValues = null;
|
||||||
|
borderShared = null;
|
||||||
|
|
||||||
defaults_initialized = false;
|
defaults_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installListeners( AbstractButton b ) {
|
||||||
|
super.installListeners( b );
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.install( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void uninstallListeners( AbstractButton b ) {
|
||||||
|
super.uninstallListeners( b );
|
||||||
|
|
||||||
|
MigLayoutVisualPadding.uninstall( b );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BasicButtonListener createButtonListener( AbstractButton b ) {
|
protected BasicButtonListener createButtonListener( AbstractButton b ) {
|
||||||
return new FlatButtonListener( b );
|
return new FlatButtonListener( b );
|
||||||
@@ -215,6 +313,10 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
|
case BasicHTML.propertyKey:
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( b );
|
||||||
|
break;
|
||||||
|
|
||||||
case SQUARE_SIZE:
|
case SQUARE_SIZE:
|
||||||
case MINIMUM_WIDTH:
|
case MINIMUM_WIDTH:
|
||||||
case MINIMUM_HEIGHT:
|
case MINIMUM_HEIGHT:
|
||||||
@@ -223,11 +325,97 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
case BUTTON_TYPE:
|
case BUTTON_TYPE:
|
||||||
b.revalidate();
|
b.revalidate();
|
||||||
b.repaint();
|
HiDPIUtils.repaint( b );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OUTLINE:
|
||||||
|
HiDPIUtils.repaint( b );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STYLE:
|
||||||
|
case STYLE_CLASS:
|
||||||
|
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
||||||
|
// unshare component UI if necessary
|
||||||
|
// updateUI() invokes installStyle() from installUI()
|
||||||
|
b.updateUI();
|
||||||
|
} else
|
||||||
|
installStyle( b );
|
||||||
|
b.revalidate();
|
||||||
|
HiDPIUtils.repaint( b );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle( AbstractButton b ) {
|
||||||
|
try {
|
||||||
|
applyStyle( b, FlatStylingSupport.getResolvedStyle( b, getStyleType() ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
String getStyleType() {
|
||||||
|
return "Button";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( AbstractButton b, Object style ) {
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style,
|
||||||
|
(key, value) -> applyStyleProperty( b, key, value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( AbstractButton b, String key, Object value ) {
|
||||||
|
if( key.startsWith( "help." ) ) {
|
||||||
|
if( !(helpButtonIcon instanceof FlatHelpButtonIcon) )
|
||||||
|
return new UnknownStyleException( key );
|
||||||
|
|
||||||
|
if( helpButtonIconShared ) {
|
||||||
|
helpButtonIcon = FlatStylingSupport.cloneIcon( helpButtonIcon );
|
||||||
|
helpButtonIconShared = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = key.substring( "help.".length() );
|
||||||
|
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// update internal values; otherwise isCustomBackground() and isCustomForeground() would return wrong results
|
||||||
|
switch( key ) {
|
||||||
|
case "background": background = (Color) value; break;
|
||||||
|
case "foreground": foreground = (Color) value; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( "iconTextGap".equals( key ) && value instanceof Integer )
|
||||||
|
value = UIScale.scale( (Integer) value );
|
||||||
|
|
||||||
|
if( borderShared == null )
|
||||||
|
borderShared = new AtomicBoolean( true );
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, b, borderShared );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
Map<String, Class<?>> infos = FlatStylingSupport.getAnnotatedStyleableInfos( this, c.getBorder() );
|
||||||
|
if( helpButtonIcon instanceof FlatHelpButtonIcon )
|
||||||
|
FlatStylingSupport.putAllPrefixKey( infos, "help.", ((FlatHelpButtonIcon)helpButtonIcon).getStyleableInfos() );
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
if( key.startsWith( "help." ) ) {
|
||||||
|
return (helpButtonIcon instanceof FlatHelpButtonIcon)
|
||||||
|
? ((FlatHelpButtonIcon)helpButtonIcon).getStyleableValue( key.substring( "help.".length() ) )
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, c.getBorder(), key );
|
||||||
|
}
|
||||||
|
|
||||||
static boolean isContentAreaFilled( Component c ) {
|
static boolean isContentAreaFilled( Component c ) {
|
||||||
return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled();
|
return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled();
|
||||||
}
|
}
|
||||||
@@ -242,7 +430,7 @@ public class FlatButtonUI
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the button has an icon but no text,
|
* Returns true if the button has an icon but no text,
|
||||||
* or it it does not have an icon and the text is either "..." or one character.
|
* or it does not have an icon and the text is either "..." or one character.
|
||||||
*/
|
*/
|
||||||
static boolean isIconOnlyOrSingleCharacterButton( Component c ) {
|
static boolean isIconOnlyOrSingleCharacterButton( Component c ) {
|
||||||
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
||||||
@@ -265,11 +453,11 @@ public class FlatButtonUI
|
|||||||
if( !(c instanceof AbstractButton) )
|
if( !(c instanceof AbstractButton) )
|
||||||
return TYPE_OTHER;
|
return TYPE_OTHER;
|
||||||
|
|
||||||
Object value = ((AbstractButton)c).getClientProperty( BUTTON_TYPE );
|
String value = getButtonTypeStr( (AbstractButton) c );
|
||||||
if( !(value instanceof String) )
|
if( value == null )
|
||||||
return TYPE_OTHER;
|
return TYPE_OTHER;
|
||||||
|
|
||||||
switch( (String) value ) {
|
switch( value ) {
|
||||||
case BUTTON_TYPE_SQUARE: return TYPE_SQUARE;
|
case BUTTON_TYPE_SQUARE: return TYPE_SQUARE;
|
||||||
case BUTTON_TYPE_ROUND_RECT: return TYPE_ROUND_RECT;
|
case BUTTON_TYPE_ROUND_RECT: return TYPE_ROUND_RECT;
|
||||||
default: return TYPE_OTHER;
|
default: return TYPE_OTHER;
|
||||||
@@ -277,16 +465,27 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
static boolean isHelpButton( Component c ) {
|
static boolean isHelpButton( Component c ) {
|
||||||
return c instanceof JButton && clientPropertyEquals( (JButton) c, BUTTON_TYPE, BUTTON_TYPE_HELP );
|
return c instanceof JButton && BUTTON_TYPE_HELP.equals( getButtonTypeStr( (JButton) c ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isToolBarButton( Component c ) {
|
static boolean isToolBarButton( Component c ) {
|
||||||
return c.getParent() instanceof JToolBar ||
|
return c.getParent() instanceof JToolBar ||
|
||||||
(c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON ));
|
(c instanceof AbstractButton && BUTTON_TYPE_TOOLBAR_BUTTON.equals( getButtonTypeStr( (AbstractButton) c ) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isBorderlessButton( Component c ) {
|
static boolean isBorderlessButton( Component c ) {
|
||||||
return c instanceof AbstractButton && clientPropertyEquals( (AbstractButton) c, BUTTON_TYPE, BUTTON_TYPE_BORDERLESS );
|
return c instanceof AbstractButton && BUTTON_TYPE_BORDERLESS.equals( getButtonTypeStr( (AbstractButton) c ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getButtonTypeStr( AbstractButton c ) {
|
||||||
|
// get from client property
|
||||||
|
Object value = c.getClientProperty( BUTTON_TYPE );
|
||||||
|
if( value instanceof String )
|
||||||
|
return (String) value;
|
||||||
|
|
||||||
|
// get from styling property
|
||||||
|
ButtonUI ui = c.getUI();
|
||||||
|
return (ui instanceof FlatButtonUI) ? ((FlatButtonUI)ui).buttonType : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -315,28 +514,46 @@ public class FlatButtonUI
|
|||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
|
|
||||||
|
boolean def = isDefaultButton( c );
|
||||||
boolean isToolBarButton = isToolBarButton( c );
|
boolean isToolBarButton = isToolBarButton( c );
|
||||||
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( c );
|
||||||
float arc = FlatUIUtils.getBorderArc( c );
|
float arc = FlatUIUtils.getBorderArc( c );
|
||||||
|
float textFieldArc = 0;
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
// if toolbar button is in leading/trailing component of a text field,
|
||||||
|
// increase toolbar button arc to match text field arc (if necessary)
|
||||||
|
if( isToolBarButton &&
|
||||||
|
FlatClientProperties.clientProperty( c, STYLE_CLASS, "", String.class ).contains( "inTextField" ) )
|
||||||
|
{
|
||||||
|
JTextField textField = (JTextField) SwingUtilities.getAncestorOfClass( JTextField.class, c );
|
||||||
|
if( textField != null )
|
||||||
|
textFieldArc = FlatUIUtils.getBorderArc( textField );
|
||||||
|
}
|
||||||
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
int width = c.getWidth();
|
int width = c.getWidth();
|
||||||
int height = c.getHeight();
|
int height = c.getHeight();
|
||||||
|
|
||||||
if( isToolBarButton ) {
|
if( isToolBarButton && c.getBorder() instanceof FlatButtonBorder ) {
|
||||||
Insets spacing = UIScale.scale( toolbarSpacingInsets );
|
Insets spacing = UIScale.scale( ((FlatButtonBorder)c.getBorder()).toolbarSpacingInsets );
|
||||||
x += spacing.left;
|
x += spacing.left;
|
||||||
y += spacing.top;
|
y += spacing.top;
|
||||||
width -= spacing.left + spacing.right;
|
width -= spacing.left + spacing.right;
|
||||||
height -= spacing.top + spacing.bottom;
|
height -= spacing.top + spacing.bottom;
|
||||||
|
|
||||||
|
// reduce text field arc
|
||||||
|
textFieldArc -= spacing.top + spacing.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increase toolbar button arc to match text field arc (if necessary)
|
||||||
|
if( arc < textFieldArc )
|
||||||
|
arc = textFieldArc;
|
||||||
|
|
||||||
// paint shadow
|
// paint shadow
|
||||||
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
||||||
if( shadowColor != null && shadowWidth > 0 && focusWidth > 0 && c.isEnabled() &&
|
if( paintShadow &&
|
||||||
|
shadowColor != null && shadowWidth > 0 && focusWidth > 0 && c.isEnabled() &&
|
||||||
!isToolBarButton && !isBorderlessButton( c ) &&
|
!isToolBarButton && !isBorderlessButton( c ) &&
|
||||||
!(isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c )) )
|
!(isFocusPainted( c ) && FlatUIUtils.isPermanentFocusOwner( c )) )
|
||||||
{
|
{
|
||||||
@@ -359,9 +576,69 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to BasicButtonUI.paint(), but does not use zero insets for HTML text,
|
||||||
|
* which is done in BasicButtonUI.layout() since Java 19.
|
||||||
|
* See https://github.com/openjdk/jdk/pull/8407
|
||||||
|
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void paint( Graphics g, JComponent c ) {
|
public void paint( Graphics g, JComponent c ) {
|
||||||
super.paint( FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c ), c );
|
g = FlatLabelUI.createGraphicsHTMLTextYCorrection( g, c );
|
||||||
|
|
||||||
|
AbstractButton b = (AbstractButton) c;
|
||||||
|
|
||||||
|
// layout
|
||||||
|
String clippedText = layout( b, b.getFontMetrics( b.getFont() ), b.getWidth(), b.getHeight() );
|
||||||
|
|
||||||
|
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
||||||
|
clearTextShiftOffset();
|
||||||
|
|
||||||
|
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
||||||
|
ButtonModel model = b.getModel();
|
||||||
|
if( model.isArmed() && model.isPressed() )
|
||||||
|
paintButtonPressed( g, b );
|
||||||
|
|
||||||
|
// paint icon
|
||||||
|
if( b.getIcon() != null )
|
||||||
|
paintIcon( g, b, iconR );
|
||||||
|
|
||||||
|
// paint text
|
||||||
|
if( clippedText != null && !clippedText.isEmpty() ) {
|
||||||
|
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view != null ) {
|
||||||
|
// update foreground color in HTML view, which is necessary
|
||||||
|
// for selected and pressed states
|
||||||
|
// (only for enabled buttons, because UIManager.getColor("textInactiveText")
|
||||||
|
// is used for disabled components; see: javax.swing.text.GlyphView.paint())
|
||||||
|
if( b.isEnabled() )
|
||||||
|
FlatHTML.updateRendererCSSForeground( view, getForeground( b ) );
|
||||||
|
|
||||||
|
view.paint( g, textR ); // HTML text
|
||||||
|
} else
|
||||||
|
paintText( g, b, textR, clippedText );
|
||||||
|
}
|
||||||
|
|
||||||
|
// not used in FlatLaf, but invoked for compatibility with BasicButtonUI.paint()
|
||||||
|
if( b.isFocusPainted() && b.hasFocus() )
|
||||||
|
paintFocus( g, b, viewR, textR, iconR );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Graphics g, JComponent c, Rectangle iconRect ) {
|
||||||
|
// correct icon location when using bold font for default button
|
||||||
|
int xOffset = defaultBoldPlainWidthDiff( c ) / 2;
|
||||||
|
if( xOffset > 0 ) {
|
||||||
|
boolean ltr = c.getComponentOrientation().isLeftToRight();
|
||||||
|
switch( ((AbstractButton)c).getHorizontalTextPosition() ) {
|
||||||
|
case SwingConstants.RIGHT: iconRect.x -= xOffset; break;
|
||||||
|
case SwingConstants.LEFT: iconRect.x += xOffset; break;
|
||||||
|
case SwingConstants.TRAILING: iconRect.x -= ltr ? xOffset : -xOffset; break;
|
||||||
|
case SwingConstants.LEADING: iconRect.x += ltr ? xOffset : -xOffset; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.paintIcon( g, c, iconRect );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -393,15 +670,19 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Color getBackground( JComponent c ) {
|
protected Color getBackground( JComponent c ) {
|
||||||
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
boolean def = isDefaultButton( c );
|
||||||
|
boolean toolBarButton = !def && (isToolBarButton( c ) || isBorderlessButton( c ));
|
||||||
|
|
||||||
// selected state
|
// selected state
|
||||||
if( ((AbstractButton)c).isSelected() ) {
|
if( ((AbstractButton)c).isSelected() ) {
|
||||||
// in toolbar use same background colors for disabled and enabled because
|
// in toolbar, if toolbarDisabledSelectedBackground is null,
|
||||||
|
// use same background colors for disabled and enabled because
|
||||||
// we assume that toolbar icon is shown disabled
|
// we assume that toolbar icon is shown disabled
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
||||||
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
|
toolBarButton
|
||||||
|
? (toolbarDisabledSelectedBackground != null ? toolbarDisabledSelectedBackground : toolbarSelectedBackground)
|
||||||
|
: disabledSelectedBackground,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
||||||
@@ -418,7 +699,6 @@ public class FlatButtonUI
|
|||||||
toolbarPressedBackground );
|
toolbarPressedBackground );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
|
||||||
return buttonStateColor( c,
|
return buttonStateColor( c,
|
||||||
getBackgroundBase( c, def ),
|
getBackgroundBase( c, def ),
|
||||||
disabledBackground,
|
disabledBackground,
|
||||||
@@ -428,6 +708,9 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Color getBackgroundBase( JComponent c, boolean def ) {
|
protected Color getBackgroundBase( JComponent c, boolean def ) {
|
||||||
|
if( FlatUIUtils.isAWTPeer( c ) )
|
||||||
|
return background;
|
||||||
|
|
||||||
// use component background if explicitly set
|
// use component background if explicitly set
|
||||||
Color bg = c.getBackground();
|
Color bg = c.getBackground();
|
||||||
if( isCustomBackground( bg ) )
|
if( isCustomBackground( bg ) )
|
||||||
@@ -443,6 +726,9 @@ public class FlatButtonUI
|
|||||||
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
||||||
Color focusedColor, Color hoverColor, Color pressedColor )
|
Color focusedColor, Color hoverColor, Color pressedColor )
|
||||||
{
|
{
|
||||||
|
if( c == null )
|
||||||
|
return enabledColor;
|
||||||
|
|
||||||
if( !c.isEnabled() )
|
if( !c.isEnabled() )
|
||||||
return disabledColor;
|
return disabledColor;
|
||||||
|
|
||||||
@@ -463,18 +749,49 @@ public class FlatButtonUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Color getForeground( JComponent c ) {
|
protected Color getForeground( JComponent c ) {
|
||||||
if( !c.isEnabled() )
|
Color fg = c.getForeground();
|
||||||
return disabledText;
|
boolean def = isDefaultButton( c );
|
||||||
|
boolean toolBarButton = !def && (isToolBarButton( c ) || isBorderlessButton( c ));
|
||||||
|
|
||||||
if( ((AbstractButton)c).isSelected() && !(isToolBarButton( c ) || isBorderlessButton( c )) )
|
// selected state
|
||||||
return selectedForeground;
|
if( ((AbstractButton)c).isSelected() ) {
|
||||||
|
return buttonStateColor( c,
|
||||||
|
toolBarButton
|
||||||
|
? (toolbarSelectedForeground != null ? toolbarSelectedForeground : fg)
|
||||||
|
: (isCustomForeground( fg ) ? fg : selectedForeground),
|
||||||
|
toolBarButton
|
||||||
|
? (toolbarDisabledSelectedForeground != null ? toolbarDisabledSelectedForeground : disabledText)
|
||||||
|
: (disabledSelectedForeground != null ? disabledSelectedForeground : disabledText),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
toolBarButton ? toolbarPressedForeground : pressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
// toolbar button
|
||||||
|
if( toolBarButton ) {
|
||||||
|
return buttonStateColor( c,
|
||||||
|
fg,
|
||||||
|
disabledText,
|
||||||
|
null,
|
||||||
|
toolbarHoverForeground,
|
||||||
|
toolbarPressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
return buttonStateColor( c,
|
||||||
|
getForegroundBase( c, def ),
|
||||||
|
disabledText,
|
||||||
|
isCustomForeground( fg ) ? null : (def ? defaultFocusedForeground : focusedForeground),
|
||||||
|
def ? defaultHoverForeground : hoverForeground,
|
||||||
|
def ? defaultPressedForeground : pressedForeground );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
protected Color getForegroundBase( JComponent c, boolean def ) {
|
||||||
// use component foreground if explicitly set
|
// use component foreground if explicitly set
|
||||||
Color fg = c.getForeground();
|
Color fg = c.getForeground();
|
||||||
if( isCustomForeground( fg ) )
|
if( isCustomForeground( fg ) )
|
||||||
return fg;
|
return fg;
|
||||||
|
|
||||||
boolean def = isDefaultButton( c );
|
|
||||||
return def ? defaultForeground : fg;
|
return def ? defaultForeground : fg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,24 +808,112 @@ public class FlatButtonUI
|
|||||||
if( prefSize == null )
|
if( prefSize == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// increase width when using bold font for default button
|
||||||
|
prefSize.width += defaultBoldPlainWidthDiff( c );
|
||||||
|
|
||||||
// make square or apply minimum width/height
|
// make square or apply minimum width/height
|
||||||
boolean isIconOnlyOrSingleCharacter = isIconOnlyOrSingleCharacterButton( c );
|
boolean isIconOnlyOrSingleCharacter = isIconOnlyOrSingleCharacterButton( c );
|
||||||
if( clientPropertyBoolean( c, SQUARE_SIZE, false ) ) {
|
if( clientPropertyBoolean( c, SQUARE_SIZE, squareSize ) ) {
|
||||||
// make button square (increase width or height so that they are equal)
|
// make button square (increase width or height so that they are equal)
|
||||||
prefSize.width = prefSize.height = Math.max( prefSize.width, prefSize.height );
|
prefSize.width = prefSize.height = Math.max( prefSize.width, prefSize.height );
|
||||||
} else if( isIconOnlyOrSingleCharacter && ((AbstractButton)c).getIcon() == null ) {
|
} else if( isIconOnlyOrSingleCharacter && ((AbstractButton)c).getIcon() == null ) {
|
||||||
// make single-character-no-icon button square (increase width)
|
// make single-character-no-icon button square (increase width)
|
||||||
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
prefSize.width = Math.max( prefSize.width, prefSize.height );
|
||||||
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) && c.getBorder() instanceof FlatButtonBorder ) {
|
} else if( !isIconOnlyOrSingleCharacter && !isToolBarButton( c ) &&
|
||||||
|
c.getBorder() instanceof FlatButtonBorder && hasDefaultMargins( c ) )
|
||||||
|
{
|
||||||
// apply minimum width/height
|
// apply minimum width/height
|
||||||
float focusWidth = FlatUIUtils.getBorderFocusWidth( c );
|
int fw = Math.round( FlatUIUtils.getBorderFocusWidth( c ) * 2 );
|
||||||
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + Math.round( focusWidth * 2 ) );
|
prefSize.width = Math.max( prefSize.width, scale( FlatUIUtils.minimumWidth( c, minimumWidth ) ) + fw );
|
||||||
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, 0 ) ) + Math.round( focusWidth * 2 ) );
|
prefSize.height = Math.max( prefSize.height, scale( FlatUIUtils.minimumHeight( c, minimumHeight ) ) + fw );
|
||||||
}
|
}
|
||||||
|
|
||||||
return prefSize;
|
return prefSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int defaultBoldPlainWidthDiff( JComponent c ) {
|
||||||
|
if( defaultBoldText && isDefaultButton( c ) && c.getFont() instanceof UIResource ) {
|
||||||
|
String text = ((AbstractButton)c).getText();
|
||||||
|
if( text == null || text.isEmpty() )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Font font = c.getFont();
|
||||||
|
Font boldFont = font.deriveFont( Font.BOLD );
|
||||||
|
int boldWidth = c.getFontMetrics( boldFont ).stringWidth( text );
|
||||||
|
int plainWidth = c.getFontMetrics( font ).stringWidth( text );
|
||||||
|
if( boldWidth > plainWidth )
|
||||||
|
return boldWidth - plainWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasDefaultMargins( JComponent c ) {
|
||||||
|
Insets margin = ((AbstractButton)c).getMargin();
|
||||||
|
return margin instanceof UIResource && Objects.equals( margin, defaultMargin );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBaseline( JComponent c, int width, int height ) {
|
||||||
|
return getBaselineImpl( c, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to BasicButtonUI.getBaseline(), but does not use zero insets for HTML text,
|
||||||
|
* which is done in BasicButtonUI.layout() since Java 19.
|
||||||
|
* See https://github.com/openjdk/jdk/pull/8407
|
||||||
|
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
||||||
|
*/
|
||||||
|
static int getBaselineImpl( JComponent c, int width, int height ) {
|
||||||
|
if( width < 0 || height < 0 )
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
|
||||||
|
AbstractButton b = (AbstractButton) c;
|
||||||
|
String text = b.getText();
|
||||||
|
if( text == null || text.isEmpty() )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
FontMetrics fm = b.getFontMetrics( b.getFont() );
|
||||||
|
layout( b, fm, width, height );
|
||||||
|
|
||||||
|
View view = (View) b.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view != null ) {
|
||||||
|
// HTML text
|
||||||
|
int baseline = BasicHTML.getHTMLBaseline( view, textR.width, textR.height );
|
||||||
|
return (baseline >= 0) ? textR.y + baseline : baseline;
|
||||||
|
} else
|
||||||
|
return textR.y + fm.getAscent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to BasicButtonUI.layout(), but does not use zero insets for HTML text,
|
||||||
|
* which is done in BasicButtonUI.layout() since Java 19.
|
||||||
|
* See https://github.com/openjdk/jdk/pull/8407
|
||||||
|
* and https://github.com/openjdk/jdk/pull/8407#issuecomment-1761583430
|
||||||
|
*/
|
||||||
|
private static String layout( AbstractButton b, FontMetrics fm, int width, int height ) {
|
||||||
|
// compute view rectangle
|
||||||
|
Insets insets = b.getInsets();
|
||||||
|
viewR.setBounds( insets.left, insets.top,
|
||||||
|
width - insets.left - insets.right,
|
||||||
|
height - insets.top - insets.bottom );
|
||||||
|
|
||||||
|
// reset rectangles
|
||||||
|
textR.setBounds( 0, 0, 0, 0 );
|
||||||
|
iconR.setBounds( 0, 0, 0, 0 );
|
||||||
|
|
||||||
|
String text = b.getText();
|
||||||
|
return SwingUtilities.layoutCompoundLabel( b, fm, text, b.getIcon(),
|
||||||
|
b.getVerticalAlignment(), b.getHorizontalAlignment(),
|
||||||
|
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
|
||||||
|
viewR, iconR, textR,
|
||||||
|
(text != null) ? b.getIconTextGap() : 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Rectangle viewR = new Rectangle();
|
||||||
|
private static Rectangle textR = new Rectangle();
|
||||||
|
private static Rectangle iconR = new Rectangle();
|
||||||
|
|
||||||
//---- class FlatButtonListener -------------------------------------------
|
//---- class FlatButtonListener -------------------------------------------
|
||||||
|
|
||||||
protected class FlatButtonListener
|
protected class FlatButtonListener
|
||||||
@@ -526,5 +931,32 @@ public class FlatButtonUI
|
|||||||
super.propertyChange( e );
|
super.propertyChange( e );
|
||||||
FlatButtonUI.this.propertyChange( b, e );
|
FlatButtonUI.this.propertyChange( b, e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateChanged( ChangeEvent e ) {
|
||||||
|
HiDPIUtils.repaint( b );
|
||||||
|
|
||||||
|
// if button is in toolbar, repaint button groups
|
||||||
|
AbstractButton b = (AbstractButton) e.getSource();
|
||||||
|
Container parent = b.getParent();
|
||||||
|
if( parent instanceof JToolBar ) {
|
||||||
|
JToolBar toolBar = (JToolBar) parent;
|
||||||
|
ToolBarUI ui = toolBar.getUI();
|
||||||
|
if( ui instanceof FlatToolBarUI )
|
||||||
|
((FlatToolBarUI)ui).repaintButtonGroup( b );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusGained( FocusEvent e ) {
|
||||||
|
super.focusGained( e );
|
||||||
|
HiDPIUtils.repaint( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusLost( FocusEvent e ) {
|
||||||
|
super.focusLost( e );
|
||||||
|
HiDPIUtils.repaint( b );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,17 +17,32 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
|
import java.awt.Container;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.ActionMap;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JFormattedTextField;
|
import javax.swing.JFormattedTextField;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.text.DefaultCaret;
|
import javax.swing.text.DefaultCaret;
|
||||||
|
import javax.swing.text.DefaultEditorKit;
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import javax.swing.text.Position;
|
||||||
|
import javax.swing.text.Utilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caret that can select all text on focus gained.
|
* Caret that can select all text on focus gained.
|
||||||
|
* Also fixes Swing's double-click-and-drag behavior so that dragging after
|
||||||
|
* a double-click extends selection by whole words.
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
@@ -35,12 +50,22 @@ public class FlatCaret
|
|||||||
extends DefaultCaret
|
extends DefaultCaret
|
||||||
implements UIResource
|
implements UIResource
|
||||||
{
|
{
|
||||||
|
private static final String KEY_CARET_INFO = "FlatLaf.internal.caretInfo";
|
||||||
|
|
||||||
|
// selectAllOnFocusPolicy
|
||||||
|
private static final int NEVER = 0, ONCE = 1, ALWAYS = 2;
|
||||||
|
|
||||||
private final String selectAllOnFocusPolicy;
|
private final String selectAllOnFocusPolicy;
|
||||||
private final boolean selectAllOnMouseClick;
|
private final boolean selectAllOnMouseClick;
|
||||||
|
|
||||||
|
private boolean inInstall;
|
||||||
private boolean wasFocused;
|
private boolean wasFocused;
|
||||||
private boolean wasTemporaryLost;
|
private boolean wasFocusTemporaryLost;
|
||||||
private boolean isMousePressed;
|
private boolean isMousePressed;
|
||||||
|
private boolean isWordSelection;
|
||||||
|
private boolean isLineSelection;
|
||||||
|
private int dragSelectionStart;
|
||||||
|
private int dragSelectionEnd;
|
||||||
|
|
||||||
public FlatCaret( String selectAllOnFocusPolicy, boolean selectAllOnMouseClick ) {
|
public FlatCaret( String selectAllOnFocusPolicy, boolean selectAllOnMouseClick ) {
|
||||||
this.selectAllOnFocusPolicy = selectAllOnFocusPolicy;
|
this.selectAllOnFocusPolicy = selectAllOnFocusPolicy;
|
||||||
@@ -49,23 +74,113 @@ public class FlatCaret
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void install( JTextComponent c ) {
|
public void install( JTextComponent c ) {
|
||||||
super.install( c );
|
// get caret info if switched theme
|
||||||
|
long[] ci = (long[]) c.getClientProperty( KEY_CARET_INFO );
|
||||||
|
if( ci != null ) {
|
||||||
|
c.putClientProperty( KEY_CARET_INFO, null );
|
||||||
|
|
||||||
// the dot and mark are lost when switching LaF
|
// if caret info is too old assume that switched from FlatLaf
|
||||||
// --> move dot to end of text so that all text may be selected when it gains focus
|
// to another Laf and back to FlatLaf
|
||||||
Document doc = c.getDocument();
|
if( System.currentTimeMillis() - 500 > ci[3] )
|
||||||
if( doc != null && getDot() == 0 && getMark() == 0 ) {
|
ci = null;
|
||||||
int length = doc.getLength();
|
}
|
||||||
if( length > 0 )
|
if( ci != null ) {
|
||||||
setDot( length );
|
// when switching theme, it is necessary to set blink rate before
|
||||||
|
// invoking super.install() otherwise the caret does not blink
|
||||||
|
setBlinkRate( (int) ci[2] );
|
||||||
|
}
|
||||||
|
|
||||||
|
inInstall = true;
|
||||||
|
try {
|
||||||
|
super.install( c );
|
||||||
|
} finally {
|
||||||
|
inInstall = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ci != null ) {
|
||||||
|
// restore selection
|
||||||
|
select( (int) ci[1], (int) ci[0] );
|
||||||
|
|
||||||
|
if( ci[4] != 0 )
|
||||||
|
wasFocused = true;
|
||||||
|
|
||||||
|
// if text component is focused, then caret and selection are visible,
|
||||||
|
// but when switching theme, the component does not yet have
|
||||||
|
// a highlighter and the selection is not painted
|
||||||
|
// --> make selection temporary invisible later, then the caret
|
||||||
|
// adds selection highlights to the text component highlighter
|
||||||
|
if( isSelectionVisible() ) {
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
if( getComponent() == null )
|
||||||
|
return; // was deinstalled
|
||||||
|
|
||||||
|
if( isSelectionVisible() ) {
|
||||||
|
setSelectionVisible( false );
|
||||||
|
setSelectionVisible( true );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deinstall( JTextComponent c ) {
|
||||||
|
// remember dot and mark (the selection) when switching theme
|
||||||
|
c.putClientProperty( KEY_CARET_INFO, new long[] {
|
||||||
|
getDot(),
|
||||||
|
getMark(),
|
||||||
|
getBlinkRate(),
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
wasFocused ? 1 : 0,
|
||||||
|
} );
|
||||||
|
|
||||||
|
super.deinstall( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void adjustVisibility( Rectangle nloc ) {
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
if( c != null && c.getUI() instanceof FlatTextFieldUI ) {
|
||||||
|
// need to fix x location because JTextField.scrollRectToVisible() uses insets.left
|
||||||
|
// (as BasicTextUI.getVisibleEditorRect() does),
|
||||||
|
// but FlatTextFieldUI.getVisibleEditorRect() may add some padding
|
||||||
|
Rectangle r = ((FlatTextFieldUI)c.getUI()).getVisibleEditorRect();
|
||||||
|
if( r != null )
|
||||||
|
nloc.x -= r.x - c.getInsets().left;
|
||||||
|
}
|
||||||
|
super.adjustVisibility( nloc );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDot( int dot ) {
|
||||||
|
super.setDot( dot );
|
||||||
|
|
||||||
|
// mark as focused if invoked from JTextComponent.setCaretPosition()
|
||||||
|
// to disable SELECT_ALL_ON_FOCUS_POLICY_ONCE if application explicitly changes selection
|
||||||
|
if( !wasFocused &&
|
||||||
|
getSelectAllOnFocusPolicy() == ONCE &&
|
||||||
|
StackUtils.wasInvokedFrom( JTextComponent.class.getName(), "setCaretPosition", 6 ) )
|
||||||
|
wasFocused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveDot( int dot ) {
|
||||||
|
super.moveDot( dot );
|
||||||
|
|
||||||
|
// mark as focused if invoked from JTextComponent.moveCaretPosition()
|
||||||
|
// to disable SELECT_ALL_ON_FOCUS_POLICY_ONCE if application explicitly changes selection
|
||||||
|
if( !wasFocused &&
|
||||||
|
getSelectAllOnFocusPolicy() == ONCE &&
|
||||||
|
StackUtils.wasInvokedFrom( JTextComponent.class.getName(), "moveCaretPosition", 6 ) )
|
||||||
|
wasFocused = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusGained( FocusEvent e ) {
|
public void focusGained( FocusEvent e ) {
|
||||||
if( !wasTemporaryLost && (!isMousePressed || selectAllOnMouseClick) )
|
if( !inInstall && !wasFocusTemporaryLost && (!isMousePressed || isSelectAllOnMouseClick()) )
|
||||||
selectAllOnFocusGained();
|
selectAllOnFocusGained();
|
||||||
wasTemporaryLost = false;
|
|
||||||
|
wasFocusTemporaryLost = false;
|
||||||
wasFocused = true;
|
wasFocused = true;
|
||||||
|
|
||||||
super.focusGained( e );
|
super.focusGained( e );
|
||||||
@@ -73,7 +188,7 @@ public class FlatCaret
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusLost( FocusEvent e ) {
|
public void focusLost( FocusEvent e ) {
|
||||||
wasTemporaryLost = e.isTemporary();
|
wasFocusTemporaryLost = e.isTemporary();
|
||||||
super.focusLost( e );
|
super.focusLost( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,50 +196,161 @@ public class FlatCaret
|
|||||||
public void mousePressed( MouseEvent e ) {
|
public void mousePressed( MouseEvent e ) {
|
||||||
isMousePressed = true;
|
isMousePressed = true;
|
||||||
super.mousePressed( e );
|
super.mousePressed( e );
|
||||||
|
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
|
||||||
|
// left double-click starts word selection
|
||||||
|
isWordSelection = e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton( e ) && !e.isConsumed();
|
||||||
|
|
||||||
|
// left triple-click starts line selection
|
||||||
|
isLineSelection = e.getClickCount() == 3 && SwingUtilities.isLeftMouseButton( e ) && (!e.isConsumed() || c.getDragEnabled());
|
||||||
|
|
||||||
|
// select line
|
||||||
|
// (this is also done in DefaultCaret.mouseClicked(), but this event is
|
||||||
|
// sent when the mouse is released, which is too late for triple-click-and-drag)
|
||||||
|
if( isLineSelection ) {
|
||||||
|
ActionMap actionMap = c.getActionMap();
|
||||||
|
Action selectLineAction = (actionMap != null)
|
||||||
|
? actionMap.get( DefaultEditorKit.selectLineAction )
|
||||||
|
: null;
|
||||||
|
if( selectLineAction != null ) {
|
||||||
|
selectLineAction.actionPerformed( new ActionEvent( c,
|
||||||
|
ActionEvent.ACTION_PERFORMED, null, e.getWhen(), e.getModifiers() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember selection where word/line selection starts to keep it always selected while dragging
|
||||||
|
if( isWordSelection || isLineSelection ) {
|
||||||
|
int mark = getMark();
|
||||||
|
int dot = getDot();
|
||||||
|
dragSelectionStart = Math.min( dot, mark );
|
||||||
|
dragSelectionEnd = Math.max( dot, mark );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseReleased( MouseEvent e ) {
|
public void mouseReleased( MouseEvent e ) {
|
||||||
isMousePressed = false;
|
isMousePressed = false;
|
||||||
|
isWordSelection = false;
|
||||||
|
isLineSelection = false;
|
||||||
super.mouseReleased( e );
|
super.mouseReleased( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDragged( MouseEvent e ) {
|
||||||
|
if( (isWordSelection || isLineSelection) &&
|
||||||
|
!e.isConsumed() && SwingUtilities.isLeftMouseButton( e ) )
|
||||||
|
{
|
||||||
|
// fix Swing's double/triple-click-and-drag behavior so that dragging after
|
||||||
|
// a double/triple-click extends selection by whole words/lines
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
int pos = c.viewToModel( e.getPoint() );
|
||||||
|
if( pos < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( pos > dragSelectionEnd )
|
||||||
|
select( dragSelectionStart, isWordSelection ? Utilities.getWordEnd( c, pos ) : Utilities.getRowEnd( c, pos ) );
|
||||||
|
else if( pos < dragSelectionStart )
|
||||||
|
select( dragSelectionEnd, isWordSelection ? Utilities.getWordStart( c, pos ) : Utilities.getRowStart( c, pos ) );
|
||||||
|
else
|
||||||
|
select( dragSelectionStart, dragSelectionEnd );
|
||||||
|
} catch( BadLocationException ex ) {
|
||||||
|
UIManager.getLookAndFeel().provideErrorFeedback( c );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
super.mouseDragged( e );
|
||||||
|
}
|
||||||
|
|
||||||
protected void selectAllOnFocusGained() {
|
protected void selectAllOnFocusGained() {
|
||||||
JTextComponent c = getComponent();
|
JTextComponent c = getComponent();
|
||||||
Document doc = c.getDocument();
|
Document doc = c.getDocument();
|
||||||
if( doc == null || !c.isEnabled() || !c.isEditable() )
|
if( doc == null || !c.isEnabled() || !c.isEditable() || FlatUIUtils.isCellEditor( c ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object selectAllOnFocusPolicy = c.getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
int selectAllOnFocusPolicy = getSelectAllOnFocusPolicy();
|
||||||
if( selectAllOnFocusPolicy == null )
|
if( selectAllOnFocusPolicy == NEVER )
|
||||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
|
||||||
|
|
||||||
if( SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
if( selectAllOnFocusPolicy == ONCE && !isMousePressed ) {
|
||||||
// policy is "once" (or null or unknown)
|
|
||||||
|
|
||||||
// was already focused?
|
// was already focused?
|
||||||
if( wasFocused )
|
if( wasFocused && !(c instanceof JFormattedTextField) )
|
||||||
return;
|
|
||||||
|
|
||||||
// check whether selection was modified before gaining focus
|
|
||||||
int dot = getDot();
|
|
||||||
int mark = getMark();
|
|
||||||
if( dot != mark || dot != doc.getLength() )
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// select all
|
// select all
|
||||||
if( c instanceof JFormattedTextField ) {
|
if( c instanceof JFormattedTextField ) {
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
setDot( 0 );
|
// Warning: do not use variables from outside of this runnable
|
||||||
moveDot( doc.getLength() );
|
// because they may be out-of-date when this runnable is executed
|
||||||
|
|
||||||
|
JTextComponent c2 = getComponent();
|
||||||
|
if( c2 == null )
|
||||||
|
return; // was deinstalled
|
||||||
|
|
||||||
|
select( 0, c2.getDocument().getLength() );
|
||||||
} );
|
} );
|
||||||
} else {
|
} else
|
||||||
setDot( 0 );
|
select( 0, doc.getLength() );
|
||||||
moveDot( doc.getLength() );
|
}
|
||||||
|
|
||||||
|
private void select( int mark, int dot ) {
|
||||||
|
if( mark != getMark() )
|
||||||
|
setDot( mark, Position.Bias.Forward );
|
||||||
|
if( dot != getDot() )
|
||||||
|
moveDot( dot, Position.Bias.Forward );
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSelectAllOnFocusPolicy() {
|
||||||
|
Object value = getClientProperty( SELECT_ALL_ON_FOCUS_POLICY );
|
||||||
|
// Note: using String.valueOf() because selectAllOnFocusPolicy may be null
|
||||||
|
switch( String.valueOf( value instanceof String ? value : selectAllOnFocusPolicy ) ) {
|
||||||
|
default:
|
||||||
|
case SELECT_ALL_ON_FOCUS_POLICY_NEVER: return NEVER;
|
||||||
|
case SELECT_ALL_ON_FOCUS_POLICY_ONCE: return ONCE;
|
||||||
|
case SELECT_ALL_ON_FOCUS_POLICY_ALWAYS: return ALWAYS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSelectAllOnMouseClick() {
|
||||||
|
Object value = getClientProperty( SELECT_ALL_ON_MOUSE_CLICK );
|
||||||
|
return (value instanceof Boolean) ? (boolean) value : selectAllOnMouseClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getClientProperty( String key ) {
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
if( c == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Object value = c.getClientProperty( key );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
|
||||||
|
Container parent = c.getParent();
|
||||||
|
if( parent instanceof JComboBox )
|
||||||
|
return ((JComboBox<?>)parent).getClientProperty( key );
|
||||||
|
if( parent instanceof JSpinner.DefaultEditor ) {
|
||||||
|
parent = parent.getParent();
|
||||||
|
if( parent instanceof JSpinner )
|
||||||
|
return ((JSpinner)parent).getClientProperty( key );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 1.4 */
|
||||||
|
public void scrollCaretToVisible() {
|
||||||
|
JTextComponent c = getComponent();
|
||||||
|
if( c == null || c.getUI() == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Rectangle loc = c.getUI().modelToView( c, getDot(), getDotBias() );
|
||||||
|
if( loc != null ) {
|
||||||
|
adjustVisibility( loc );
|
||||||
|
damage( loc );
|
||||||
|
}
|
||||||
|
} catch( BadLocationException ex ) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,20 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
||||||
|
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableField;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableLookupProvider;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JCheckBoxMenuItem}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JCheckBoxMenuItem}.
|
||||||
@@ -52,15 +61,30 @@ import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
|
|||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionBackground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="selectionForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="disabledForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorForeground" )
|
||||||
|
@StyleableField( cls=BasicMenuItemUI.class, key="acceleratorSelectionForeground" )
|
||||||
|
|
||||||
public class FlatCheckBoxMenuItemUI
|
public class FlatCheckBoxMenuItemUI
|
||||||
extends BasicCheckBoxMenuItemUI
|
extends BasicCheckBoxMenuItemUI
|
||||||
|
implements StyleableUI, StyleableLookupProvider
|
||||||
{
|
{
|
||||||
private FlatMenuItemRenderer renderer;
|
private FlatMenuItemRenderer renderer;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatCheckBoxMenuItemUI();
|
return new FlatCheckBoxMenuItemUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
@@ -74,13 +98,69 @@ public class FlatCheckBoxMenuItemUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||||
renderer = null;
|
renderer = null;
|
||||||
|
oldStyleValues = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installComponents( JMenuItem menuItem ) {
|
||||||
|
super.installComponents( menuItem );
|
||||||
|
|
||||||
|
// update HTML renderer if necessary
|
||||||
|
FlatHTML.updateRendererCSSFontBaseSize( menuItem );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FlatMenuItemRenderer createRenderer() {
|
protected FlatMenuItemRenderer createRenderer() {
|
||||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||||
|
return FlatHTML.createPropertyChangeListener(
|
||||||
|
FlatStylingSupport.createPropertyChangeListener( c, this::installStyle,
|
||||||
|
super.createPropertyChangeListener( c ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( menuItem, "CheckBoxMenuItem" ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( Object style ) {
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatMenuItemUI.getStyleableInfos( this, renderer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatMenuItemUI.getStyleableValue( this, renderer, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public MethodHandles.Lookup getLookupForStyling() {
|
||||||
|
// MethodHandles.lookup() is caller sensitive and must be invoked in this class,
|
||||||
|
// otherwise it is not possible to access protected fields in JRE superclass
|
||||||
|
return MethodHandles.lookup();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
protected Dimension getPreferredMenuItemSize( JComponent c, Icon checkIcon, Icon arrowIcon, int defaultTextIconGap ) {
|
||||||
return renderer.getPreferredMenuItemSize();
|
return renderer.getPreferredMenuItemSize();
|
||||||
|
|||||||
@@ -43,11 +43,24 @@ public class FlatCheckBoxUI
|
|||||||
extends FlatRadioButtonUI
|
extends FlatRadioButtonUI
|
||||||
{
|
{
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, FlatCheckBoxUI::new );
|
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||||
|
? FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, () -> new FlatCheckBoxUI( true ) )
|
||||||
|
: new FlatCheckBoxUI( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected FlatCheckBoxUI( boolean shared ) {
|
||||||
|
super( shared );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPropertyPrefix() {
|
public String getPropertyPrefix() {
|
||||||
return "CheckBox.";
|
return "CheckBox.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
String getStyleType() {
|
||||||
|
return "CheckBox";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,9 @@ import java.awt.Image;
|
|||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.RadialGradientPaint;
|
import java.awt.RadialGradientPaint;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -40,14 +43,17 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatDropShadowBorder
|
public class FlatDropShadowBorder
|
||||||
extends FlatEmptyBorder
|
extends FlatEmptyBorder
|
||||||
|
implements StyleableBorder
|
||||||
{
|
{
|
||||||
private final Color shadowColor;
|
@Styleable protected Color shadowColor;
|
||||||
private final Insets shadowInsets;
|
@Styleable protected Insets shadowInsets;
|
||||||
private final float shadowOpacity;
|
@Styleable protected float shadowOpacity;
|
||||||
|
|
||||||
private final int shadowSize;
|
private int shadowSize;
|
||||||
private Image shadowImage;
|
private Image shadowImage;
|
||||||
private Color lastShadowColor;
|
private Color lastShadowColor;
|
||||||
|
private float lastShadowOpacity;
|
||||||
|
private int lastShadowSize;
|
||||||
private double lastSystemScaleFactor;
|
private double lastSystemScaleFactor;
|
||||||
private float lastUserScaleFactor;
|
private float lastUserScaleFactor;
|
||||||
|
|
||||||
@@ -64,17 +70,49 @@ public class FlatDropShadowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FlatDropShadowBorder( Color shadowColor, Insets shadowInsets, float shadowOpacity ) {
|
public FlatDropShadowBorder( Color shadowColor, Insets shadowInsets, float shadowOpacity ) {
|
||||||
super( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ),
|
super( nonNegativeInsets( shadowInsets ) );
|
||||||
Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) );
|
|
||||||
this.shadowColor = shadowColor;
|
this.shadowColor = shadowColor;
|
||||||
this.shadowInsets = shadowInsets;
|
this.shadowInsets = shadowInsets;
|
||||||
this.shadowOpacity = shadowOpacity;
|
this.shadowOpacity = Math.min( Math.max( shadowOpacity, 0f ), 1f );
|
||||||
|
|
||||||
shadowSize = Math.max(
|
shadowSize = maxInset( shadowInsets );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Insets nonNegativeInsets( Insets shadowInsets ) {
|
||||||
|
return new Insets( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ),
|
||||||
|
Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private int maxInset( Insets shadowInsets ) {
|
||||||
|
return Math.max(
|
||||||
Math.max( shadowInsets.left, shadowInsets.right ),
|
Math.max( shadowInsets.left, shadowInsets.right ),
|
||||||
Math.max( shadowInsets.top, shadowInsets.bottom ) );
|
Math.max( shadowInsets.top, shadowInsets.bottom ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
Object oldValue = FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
if( key.equals( "shadowInsets" ) ) {
|
||||||
|
applyStyleProperty( nonNegativeInsets( shadowInsets ) );
|
||||||
|
shadowSize = maxInset( shadowInsets );
|
||||||
|
}
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
if( shadowSize <= 0 )
|
if( shadowSize <= 0 )
|
||||||
@@ -91,12 +129,16 @@ public class FlatDropShadowBorder
|
|||||||
float userScaleFactor = UIScale.getUserScaleFactor();
|
float userScaleFactor = UIScale.getUserScaleFactor();
|
||||||
if( shadowImage == null ||
|
if( shadowImage == null ||
|
||||||
!shadowColor.equals( lastShadowColor ) ||
|
!shadowColor.equals( lastShadowColor ) ||
|
||||||
|
lastShadowOpacity != shadowOpacity ||
|
||||||
|
lastShadowSize != shadowSize ||
|
||||||
lastSystemScaleFactor != scaleFactor ||
|
lastSystemScaleFactor != scaleFactor ||
|
||||||
lastUserScaleFactor != userScaleFactor )
|
lastUserScaleFactor != userScaleFactor )
|
||||||
{
|
{
|
||||||
shadowImage = createShadowImage( shadowColor, shadowSize, shadowOpacity,
|
shadowImage = createShadowImage( shadowColor, shadowSize, shadowOpacity,
|
||||||
(float) (scaleFactor * userScaleFactor) );
|
(float) (scaleFactor * userScaleFactor) );
|
||||||
lastShadowColor = shadowColor;
|
lastShadowColor = shadowColor;
|
||||||
|
lastShadowOpacity = shadowOpacity;
|
||||||
|
lastShadowSize = shadowSize;
|
||||||
lastSystemScaleFactor = scaleFactor;
|
lastSystemScaleFactor = scaleFactor;
|
||||||
lastUserScaleFactor = userScaleFactor;
|
lastUserScaleFactor = userScaleFactor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,19 +17,26 @@
|
|||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.event.FocusListener;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JEditorPane;
|
import javax.swing.JEditorPane;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
|
||||||
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
import javax.swing.plaf.basic.BasicEditorPaneUI;
|
||||||
|
import javax.swing.text.Caret;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JEditorPane}.
|
||||||
@@ -37,8 +44,8 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
|||||||
* <!-- BasicEditorPaneUI -->
|
* <!-- BasicEditorPaneUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault EditorPane.font Font
|
* @uiDefault EditorPane.font Font
|
||||||
* @uiDefault EditorPane.background Color also used if not editable
|
* @uiDefault EditorPane.background Color
|
||||||
* @uiDefault EditorPane.foreground Color
|
* @uiDefault EditorPane.foreground Color also used if not editable
|
||||||
* @uiDefault EditorPane.caretForeground Color
|
* @uiDefault EditorPane.caretForeground Color
|
||||||
* @uiDefault EditorPane.selectionBackground Color
|
* @uiDefault EditorPane.selectionBackground Color
|
||||||
* @uiDefault EditorPane.selectionForeground Color
|
* @uiDefault EditorPane.selectionForeground Color
|
||||||
@@ -52,28 +59,52 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
|||||||
* <!-- FlatEditorPaneUI -->
|
* <!-- FlatEditorPaneUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
* @uiDefault EditorPane.focusedBackground Color optional
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatEditorPaneUI
|
public class FlatEditorPaneUI
|
||||||
extends BasicEditorPaneUI
|
extends BasicEditorPaneUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
protected int minimumWidth;
|
@Styleable protected int minimumWidth;
|
||||||
protected boolean isIntelliJTheme;
|
private Color background;
|
||||||
|
@Styleable protected Color disabledBackground;
|
||||||
|
@Styleable protected Color inactiveBackground;
|
||||||
|
@Styleable protected Color focusedBackground;
|
||||||
|
|
||||||
|
private Color oldDisabledBackground;
|
||||||
|
private Color oldInactiveBackground;
|
||||||
|
|
||||||
|
private Insets defaultMargin;
|
||||||
|
|
||||||
private Object oldHonorDisplayProperties;
|
private Object oldHonorDisplayProperties;
|
||||||
|
private FocusListener focusListener;
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatEditorPaneUI();
|
return new FlatEditorPaneUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
installStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|
||||||
|
String prefix = getPropertyPrefix();
|
||||||
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
|
||||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
background = UIManager.getColor( prefix + ".background" );
|
||||||
|
disabledBackground = UIManager.getColor( prefix + ".disabledBackground" );
|
||||||
|
inactiveBackground = UIManager.getColor( prefix + ".inactiveBackground" );
|
||||||
|
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
|
||||||
|
|
||||||
|
defaultMargin = UIManager.getInsets( prefix + ".margin" );
|
||||||
|
|
||||||
// use component font and foreground for HTML text
|
// use component font and foreground for HTML text
|
||||||
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
|
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
|
||||||
@@ -84,34 +115,124 @@ public class FlatEditorPaneUI
|
|||||||
protected void uninstallDefaults() {
|
protected void uninstallDefaults() {
|
||||||
super.uninstallDefaults();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
|
background = null;
|
||||||
|
disabledBackground = null;
|
||||||
|
inactiveBackground = null;
|
||||||
|
focusedBackground = null;
|
||||||
|
|
||||||
|
oldDisabledBackground = null;
|
||||||
|
oldInactiveBackground = null;
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
|
|
||||||
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
|
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void propertyChange( PropertyChangeEvent e ) {
|
protected void installListeners() {
|
||||||
super.propertyChange( e );
|
super.installListeners();
|
||||||
propertyChange( getComponent(), e );
|
|
||||||
|
// necessary to update focus background
|
||||||
|
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), c -> focusedBackground != null );
|
||||||
|
getComponent().addFocusListener( focusListener );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void propertyChange( JTextComponent c, PropertyChangeEvent e ) {
|
@Override
|
||||||
|
protected void uninstallListeners() {
|
||||||
|
super.uninstallListeners();
|
||||||
|
|
||||||
|
getComponent().removeFocusListener( focusListener );
|
||||||
|
focusListener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Caret createCaret() {
|
||||||
|
return new FlatCaret( null, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
// invoke updateBackground() before super.propertyChange()
|
||||||
|
String propertyName = e.getPropertyName();
|
||||||
|
if( "editable".equals( propertyName ) || "enabled".equals( propertyName ) )
|
||||||
|
updateBackground();
|
||||||
|
|
||||||
|
super.propertyChange( e );
|
||||||
|
propertyChange( getComponent(), e, this::installStyle );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void propertyChange( JTextComponent c, PropertyChangeEvent e, Runnable installStyle ) {
|
||||||
switch( e.getPropertyName() ) {
|
switch( e.getPropertyName() ) {
|
||||||
case FlatClientProperties.MINIMUM_WIDTH:
|
case FlatClientProperties.MINIMUM_WIDTH:
|
||||||
c.revalidate();
|
c.revalidate();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FlatClientProperties.STYLE:
|
||||||
|
case FlatClientProperties.STYLE_CLASS:
|
||||||
|
installStyle.run();
|
||||||
|
c.revalidate();
|
||||||
|
HiDPIUtils.repaint( c );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( getComponent(), "EditorPane" ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( Object style ) {
|
||||||
|
oldDisabledBackground = disabledBackground;
|
||||||
|
oldInactiveBackground = inactiveBackground;
|
||||||
|
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
|
||||||
|
updateBackground();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, getComponent(), key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBackground() {
|
||||||
|
FlatTextFieldUI.updateBackground( getComponent(), background,
|
||||||
|
disabledBackground, inactiveBackground,
|
||||||
|
oldDisabledBackground, oldInactiveBackground );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize( JComponent c ) {
|
public Dimension getPreferredSize( JComponent c ) {
|
||||||
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth );
|
return applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth, defaultMargin );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getMinimumSize( JComponent c ) {
|
public Dimension getMinimumSize( JComponent c ) {
|
||||||
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth );
|
return applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth, defaultMargin );
|
||||||
}
|
}
|
||||||
|
|
||||||
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth ) {
|
static Dimension applyMinimumWidth( JComponent c, Dimension size, int minimumWidth, Insets defaultMargin ) {
|
||||||
|
// do not apply minimum width if JTextComponent.margin is set
|
||||||
|
if( !FlatTextFieldUI.hasDefaultMargins( c, defaultMargin ) )
|
||||||
|
return size;
|
||||||
|
|
||||||
// Assume that text area is in a scroll pane (that displays the border)
|
// Assume that text area is in a scroll pane (that displays the border)
|
||||||
// and subtract 1px border line width.
|
// and subtract 1px border line width.
|
||||||
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
// Using "(scale( 1 ) * 2)" instead of "scale( 2 )" to deal with rounding
|
||||||
@@ -128,14 +249,11 @@ public class FlatEditorPaneUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void paintBackground( Graphics g ) {
|
protected void paintBackground( Graphics g ) {
|
||||||
JTextComponent c = getComponent();
|
paintBackground( g, getComponent(), focusedBackground );
|
||||||
|
}
|
||||||
|
|
||||||
// for compatibility with IntelliJ themes
|
static void paintBackground( Graphics g, JTextComponent c, Color focusedBackground ) {
|
||||||
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) && (c.getBackground() instanceof UIResource) ) {
|
g.setColor( FlatTextFieldUI.getBackground( c, focusedBackground ) );
|
||||||
FlatUIUtils.paintParentBackground( g, c );
|
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.paintBackground( g );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,13 @@ public class FlatEmptyBorder
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
boolean leftToRight = left == right || c.getComponentOrientation().isLeftToRight();
|
return scaleInsets( c, insets, top, left, bottom, right );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Insets scaleInsets( Component c, Insets insets,
|
||||||
|
int top, int left, int bottom, int right )
|
||||||
|
{
|
||||||
|
boolean leftToRight = left == right || c == null || c.getComponentOrientation().isLeftToRight();
|
||||||
insets.left = scale( leftToRight ? left : right );
|
insets.left = scale( leftToRight ? left : right );
|
||||||
insets.top = scale( top );
|
insets.top = scale( top );
|
||||||
insets.right = scale( leftToRight ? right : left );
|
insets.right = scale( leftToRight ? right : left );
|
||||||
@@ -61,4 +67,18 @@ public class FlatEmptyBorder
|
|||||||
public Insets getUnscaledBorderInsets() {
|
public Insets getUnscaledBorderInsets() {
|
||||||
return super.getBorderInsets();
|
return super.getBorderInsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object applyStyleProperty( Insets insets ) {
|
||||||
|
Insets oldInsets = getUnscaledBorderInsets();
|
||||||
|
top = insets.top;
|
||||||
|
left = insets.left;
|
||||||
|
bottom = insets.bottom;
|
||||||
|
right = insets.right;
|
||||||
|
return oldInsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
public Insets getStyleableValue() {
|
||||||
|
return new Insets( top, left, bottom, right );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,24 @@ package com.formdev.flatlaf.ui;
|
|||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Image;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
@@ -34,12 +47,18 @@ import javax.swing.JPanel;
|
|||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.JToolBar;
|
||||||
|
import javax.swing.Scrollable;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.filechooser.FileSystemView;
|
||||||
import javax.swing.filechooser.FileView;
|
import javax.swing.filechooser.FileView;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.metal.MetalFileChooserUI;
|
import javax.swing.plaf.metal.MetalFileChooserUI;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.icons.FlatFileViewDirectoryIcon;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
@@ -133,12 +152,22 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault FileChooser.listViewActionLabelText String
|
* @uiDefault FileChooser.listViewActionLabelText String
|
||||||
* @uiDefault FileChooser.detailsViewActionLabelText String
|
* @uiDefault FileChooser.detailsViewActionLabelText String
|
||||||
*
|
*
|
||||||
|
* <!-- FlatFileChooserUI -->
|
||||||
|
*
|
||||||
|
* @uiDefault FileChooser.shortcuts.buttonSize Dimension optional; default is 84,64
|
||||||
|
* @uiDefault FileChooser.shortcuts.iconSize Dimension optional; default is 32,32
|
||||||
|
* @uiDefault FileChooser.shortcuts.filesFunction Function<File[], File[]>
|
||||||
|
* @uiDefault FileChooser.shortcuts.displayNameFunction Function<File, String>
|
||||||
|
* @uiDefault FileChooser.shortcuts.iconFunction Function<File, Icon>
|
||||||
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
public class FlatFileChooserUI
|
public class FlatFileChooserUI
|
||||||
extends MetalFileChooserUI
|
extends MetalFileChooserUI
|
||||||
{
|
{
|
||||||
private final FlatFileView fileView = new FlatFileView();
|
private final FlatFileView fileView = new FlatFileView();
|
||||||
|
private FlatShortcutsPanel shortcutsPanel;
|
||||||
|
private JScrollPane shortcutsScrollPane;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatFileChooserUI( (JFileChooser) c );
|
return new FlatFileChooserUI( (JFileChooser) c );
|
||||||
@@ -153,6 +182,29 @@ public class FlatFileChooserUI
|
|||||||
super.installComponents( fc );
|
super.installComponents( fc );
|
||||||
|
|
||||||
patchUI( fc );
|
patchUI( fc );
|
||||||
|
|
||||||
|
if( !UIManager.getBoolean( "FileChooser.noPlacesBar" ) ) { // same as in Windows L&F
|
||||||
|
FlatShortcutsPanel panel = createShortcutsPanel( fc );
|
||||||
|
if( panel.getComponentCount() > 0 ) {
|
||||||
|
shortcutsPanel = panel;
|
||||||
|
shortcutsScrollPane = new JScrollPane( shortcutsPanel,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
|
||||||
|
shortcutsScrollPane.setBorder( BorderFactory.createEmptyBorder() );
|
||||||
|
fc.add( shortcutsScrollPane, BorderLayout.LINE_START );
|
||||||
|
fc.addPropertyChangeListener( shortcutsPanel );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uninstallComponents( JFileChooser fc ) {
|
||||||
|
super.uninstallComponents( fc );
|
||||||
|
|
||||||
|
if( shortcutsPanel != null ) {
|
||||||
|
fc.removePropertyChangeListener( shortcutsPanel );
|
||||||
|
shortcutsPanel = null;
|
||||||
|
shortcutsScrollPane = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void patchUI( JFileChooser fc ) {
|
private void patchUI( JFileChooser fc ) {
|
||||||
@@ -192,6 +244,27 @@ public class FlatFileChooserUI
|
|||||||
} catch( ArrayIndexOutOfBoundsException ex ) {
|
} catch( ArrayIndexOutOfBoundsException ex ) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// put north, center and south components into a new panel so that
|
||||||
|
// the shortcuts panel (at west) gets full height
|
||||||
|
LayoutManager layout = fc.getLayout();
|
||||||
|
if( layout instanceof BorderLayout ) {
|
||||||
|
BorderLayout borderLayout = (BorderLayout) layout;
|
||||||
|
borderLayout.setHgap( 8 );
|
||||||
|
|
||||||
|
Component north = borderLayout.getLayoutComponent( BorderLayout.NORTH );
|
||||||
|
Component lineEnd = borderLayout.getLayoutComponent( BorderLayout.LINE_END );
|
||||||
|
Component center = borderLayout.getLayoutComponent( BorderLayout.CENTER );
|
||||||
|
Component south = borderLayout.getLayoutComponent( BorderLayout.SOUTH );
|
||||||
|
if( north != null && lineEnd != null && center != null && south != null ) {
|
||||||
|
JPanel p = new JPanel( new BorderLayout( 0, 11 ) );
|
||||||
|
p.add( north, BorderLayout.NORTH );
|
||||||
|
p.add( lineEnd, BorderLayout.LINE_END );
|
||||||
|
p.add( center, BorderLayout.CENTER );
|
||||||
|
p.add( south, BorderLayout.SOUTH );
|
||||||
|
fc.add( p, BorderLayout.CENTER );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -250,9 +323,19 @@ public class FlatFileChooserUI
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
protected FlatShortcutsPanel createShortcutsPanel( JFileChooser fc ) {
|
||||||
|
return new FlatShortcutsPanel( fc );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dimension getPreferredSize( JComponent c ) {
|
public Dimension getPreferredSize( JComponent c ) {
|
||||||
return UIScale.scale( super.getPreferredSize( c ) );
|
Dimension prefSize = super.getPreferredSize( c );
|
||||||
|
Dimension minSize = getMinimumSize( c );
|
||||||
|
int shortcutsPanelWidth = (shortcutsScrollPane != null) ? shortcutsScrollPane.getPreferredSize().width : 0;
|
||||||
|
return new Dimension(
|
||||||
|
Math.max( prefSize.width, minSize.width + shortcutsPanelWidth ),
|
||||||
|
Math.max( prefSize.height, minSize.height ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -262,12 +345,23 @@ public class FlatFileChooserUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileView getFileView( JFileChooser fc ) {
|
public FileView getFileView( JFileChooser fc ) {
|
||||||
return fileView;
|
return doNotUseSystemIcons() ? super.getFileView( fc ) : fileView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearIconCache() {
|
public void clearIconCache() {
|
||||||
fileView.clearIconCache();
|
if( doNotUseSystemIcons() )
|
||||||
|
super.clearIconCache();
|
||||||
|
else
|
||||||
|
fileView.clearIconCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean doNotUseSystemIcons() {
|
||||||
|
// Java 17 32bit craches on Windows when using system icons
|
||||||
|
// fixed in Java 18+, fix backported in Java 17.0.3+ (see https://bugs.openjdk.java.net/browse/JDK-8277299)
|
||||||
|
return SystemInfo.isWindows &&
|
||||||
|
SystemInfo.isX86 &&
|
||||||
|
(SystemInfo.isJava_17_orLater && SystemInfo.javaVersion < SystemInfo.toVersion( 17, 0, 3, 0 ));
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatFileView -------------------------------------------------
|
//---- class FlatFileView -------------------------------------------------
|
||||||
@@ -282,27 +376,331 @@ public class FlatFileChooserUI
|
|||||||
if( icon != null )
|
if( icon != null )
|
||||||
return icon;
|
return icon;
|
||||||
|
|
||||||
// get system icon
|
// new proxy icon
|
||||||
if( f != null ) {
|
//
|
||||||
icon = getFileChooser().getFileSystemView().getSystemIcon( f );
|
// Note: Since this is a super light weight icon object, we do not add it
|
||||||
|
// to the icon cache here. This keeps cache small in case of large directories
|
||||||
|
// with thousands of files when icons of all files are only needed to compute
|
||||||
|
// the layout of list/table, but never painted because located outside of visible area.
|
||||||
|
// When an icon needs to be painted, the proxy adds it to the icon cache
|
||||||
|
// and loads the real icon.
|
||||||
|
return new FlatFileViewIcon( f );
|
||||||
|
}
|
||||||
|
|
||||||
if( icon != null ) {
|
//---- class FlatFileViewIcon -----------------------------------------
|
||||||
if( icon instanceof ImageIcon )
|
|
||||||
icon = new ScaledImageIcon( (ImageIcon) icon );
|
/**
|
||||||
cacheIcon( f, icon );
|
* A proxy icon that has a fixed (scaled) width/height (16x16) and
|
||||||
|
* gets/loads the real (system) icon only for painting.
|
||||||
|
* Avoids unnecessary getting/loading system icons.
|
||||||
|
*/
|
||||||
|
private class FlatFileViewIcon
|
||||||
|
implements Icon
|
||||||
|
{
|
||||||
|
private final File f;
|
||||||
|
private Icon realIcon;
|
||||||
|
|
||||||
|
FlatFileViewIcon( File f ) {
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconWidth() {
|
||||||
|
return UIScale.scale( 16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconHeight() {
|
||||||
|
return UIScale.scale( 16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||||
|
// get icon on demand
|
||||||
|
if( realIcon == null ) {
|
||||||
|
// get system icon
|
||||||
|
try {
|
||||||
|
if( f != null )
|
||||||
|
realIcon = getFileChooser().getFileSystemView().getSystemIcon( f );
|
||||||
|
} catch( NullPointerException ex ) {
|
||||||
|
// Java 21 may throw a NPE for exe files that use default Windows exe icon
|
||||||
|
}
|
||||||
|
|
||||||
|
// get default icon
|
||||||
|
if( realIcon == null )
|
||||||
|
realIcon = FlatFileView.super.getIcon( f );
|
||||||
|
|
||||||
|
if( realIcon instanceof ImageIcon )
|
||||||
|
realIcon = new ScaledImageIcon( (ImageIcon) realIcon );
|
||||||
|
|
||||||
|
cacheIcon( f, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
realIcon.paintIcon( c, g, x, y );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class FlatShortcutsPanel -------------------------------------------
|
||||||
|
|
||||||
|
/** @since 2.3 */
|
||||||
|
public static class FlatShortcutsPanel
|
||||||
|
extends JToolBar
|
||||||
|
implements PropertyChangeListener, Scrollable
|
||||||
|
{
|
||||||
|
private final JFileChooser fc;
|
||||||
|
|
||||||
|
private final Dimension buttonSize;
|
||||||
|
private final Dimension iconSize;
|
||||||
|
private final Function<File[], File[]> filesFunction;
|
||||||
|
private final Function<File, String> displayNameFunction;
|
||||||
|
private final Function<File, Icon> iconFunction;
|
||||||
|
|
||||||
|
protected final File[] files;
|
||||||
|
protected final JToggleButton[] buttons;
|
||||||
|
protected final ButtonGroup buttonGroup = new ButtonGroup();
|
||||||
|
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
public FlatShortcutsPanel( JFileChooser fc ) {
|
||||||
|
super( JToolBar.VERTICAL );
|
||||||
|
this.fc = fc;
|
||||||
|
setFloatable( false );
|
||||||
|
putClientProperty( FlatClientProperties.STYLE, "hoverButtonGroupBackground: null" );
|
||||||
|
|
||||||
|
buttonSize = UIScale.scale( getUIDimension( "FileChooser.shortcuts.buttonSize", 84, 64 ) );
|
||||||
|
iconSize = getUIDimension( "FileChooser.shortcuts.iconSize", 32, 32 );
|
||||||
|
|
||||||
|
filesFunction = (Function<File[], File[]>) UIManager.get( "FileChooser.shortcuts.filesFunction" );
|
||||||
|
displayNameFunction = (Function<File, String>) UIManager.get( "FileChooser.shortcuts.displayNameFunction" );
|
||||||
|
iconFunction = (Function<File, Icon>) UIManager.get( "FileChooser.shortcuts.iconFunction" );
|
||||||
|
|
||||||
|
FileSystemView fsv = fc.getFileSystemView();
|
||||||
|
File[] files = JavaCompatibility2.getChooserShortcutPanelFiles( fsv );
|
||||||
|
if( filesFunction != null )
|
||||||
|
files = filesFunction.apply( files );
|
||||||
|
|
||||||
|
// create toolbar buttons
|
||||||
|
ArrayList<File> filesList = new ArrayList<>();
|
||||||
|
ArrayList<JToggleButton> buttonsList = new ArrayList<>();
|
||||||
|
for( File file : files ) {
|
||||||
|
if( file == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// wrap drive path
|
||||||
|
if( fsv.isFileSystemRoot( file ) )
|
||||||
|
file = fsv.createFileObject( file.getAbsolutePath() );
|
||||||
|
|
||||||
|
String name = getDisplayName( fsv, file );
|
||||||
|
Icon icon = getIcon( fsv, file );
|
||||||
|
if( name == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// remove path from name
|
||||||
|
int lastSepIndex = name.lastIndexOf( File.separatorChar );
|
||||||
|
if( lastSepIndex >= 0 && lastSepIndex < name.length() - 1 )
|
||||||
|
name = name.substring( lastSepIndex + 1 );
|
||||||
|
|
||||||
|
// scale icon (if necessary)
|
||||||
|
if( icon instanceof ImageIcon )
|
||||||
|
icon = new ScaledImageIcon( (ImageIcon) icon, iconSize.width, iconSize.height );
|
||||||
|
else if( icon != null )
|
||||||
|
icon = new ShortcutIcon( icon, iconSize.width, iconSize.height );
|
||||||
|
|
||||||
|
// create button
|
||||||
|
JToggleButton button = createButton( name, icon, file.toString() );
|
||||||
|
File f = file;
|
||||||
|
button.addActionListener( e -> {
|
||||||
|
fc.setCurrentDirectory( f );
|
||||||
|
} );
|
||||||
|
|
||||||
|
add( button );
|
||||||
|
buttonGroup.add( button );
|
||||||
|
|
||||||
|
filesList.add( file );
|
||||||
|
buttonsList.add( button );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.files = filesList.toArray( new File[filesList.size()] );
|
||||||
|
this.buttons = buttonsList.toArray( new JToggleButton[buttonsList.size()] );
|
||||||
|
|
||||||
|
directoryChanged( fc.getCurrentDirectory() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dimension getUIDimension( String key, int defaultWidth, int defaultHeight ) {
|
||||||
|
Dimension size = UIManager.getDimension( key );
|
||||||
|
if( size == null )
|
||||||
|
size = new Dimension( defaultWidth, defaultHeight );
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.5 */
|
||||||
|
protected JToggleButton createButton( String name, Icon icon, String toolTip ) {
|
||||||
|
JToggleButton button = new JToggleButton( name, icon );
|
||||||
|
button.setToolTipText( toolTip );
|
||||||
|
button.setVerticalTextPosition( SwingConstants.BOTTOM );
|
||||||
|
button.setHorizontalTextPosition( SwingConstants.CENTER );
|
||||||
|
button.setAlignmentX( Component.CENTER_ALIGNMENT );
|
||||||
|
button.setIconTextGap( 0 );
|
||||||
|
button.setPreferredSize( buttonSize );
|
||||||
|
button.setMaximumSize( buttonSize );
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDisplayName( FileSystemView fsv, File file ) {
|
||||||
|
if( displayNameFunction != null ) {
|
||||||
|
String name = displayNameFunction.apply( file );
|
||||||
|
if( name != null )
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fsv.getSystemDisplayName( file );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Icon getIcon( FileSystemView fsv, File file ) {
|
||||||
|
if( iconFunction != null ) {
|
||||||
|
Icon icon = iconFunction.apply( file );
|
||||||
|
if( icon != null )
|
||||||
return icon;
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( doNotUseSystemIcons() )
|
||||||
|
return new FlatFileViewDirectoryIcon();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Java 17+ supports getting larger system icons
|
||||||
|
try {
|
||||||
|
if( SystemInfo.isJava_17_orLater ) {
|
||||||
|
Method m = fsv.getClass().getMethod( "getSystemIcon", File.class, int.class, int.class );
|
||||||
|
return (Icon) m.invoke( fsv, file, iconSize.width, iconSize.height );
|
||||||
|
} else if( iconSize.width > 16 || iconSize.height > 16 ) {
|
||||||
|
Class<?> cls = Class.forName( "sun.awt.shell.ShellFolder" );
|
||||||
|
if( cls.isInstance( file ) ) {
|
||||||
|
Method m = file.getClass().getMethod( "getIcon", boolean.class );
|
||||||
|
m.setAccessible( true );
|
||||||
|
Image image = (Image) m.invoke( file, true );
|
||||||
|
if( image != null )
|
||||||
|
return new ImageIcon( image );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch( Exception ex ) {
|
||||||
|
// do not log InaccessibleObjectException because access
|
||||||
|
// may be denied via VM option '--illegal-access=deny' (default in Java 16)
|
||||||
|
// (not catching InaccessibleObjectException here because it is new in Java 9, but FlatLaf also runs on Java 8)
|
||||||
|
if( !"java.lang.reflect.InaccessibleObjectException".equals( ex.getClass().getName() ) )
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
|
||||||
|
// get system icon in default size 16x16
|
||||||
|
return fsv.getSystemIcon( file );
|
||||||
|
} catch( NullPointerException ex ) {
|
||||||
|
// Java 21 may throw a NPE for exe files that use default Windows exe icon
|
||||||
|
return new FlatFileViewDirectoryIcon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void directoryChanged( File file ) {
|
||||||
|
if( file != null ) {
|
||||||
|
String absolutePath = file.getAbsolutePath();
|
||||||
|
for( int i = 0; i < files.length; i++ ) {
|
||||||
|
// also compare path because otherwise selecting "Documents"
|
||||||
|
// in "Look in" combobox would not select "Documents" shortcut item
|
||||||
|
if( files[i].equals( file ) || files[i].getAbsolutePath().equals( absolutePath ) ) {
|
||||||
|
buttons[i].setSelected( true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get default icon
|
buttonGroup.clearSelection();
|
||||||
icon = super.getIcon( f );
|
}
|
||||||
|
|
||||||
if( icon instanceof ImageIcon ) {
|
//---- interface PropertyChangeListener ----
|
||||||
icon = new ScaledImageIcon( (ImageIcon) icon );
|
|
||||||
cacheIcon( f, icon );
|
@Override
|
||||||
|
public void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
switch( e.getPropertyName() ) {
|
||||||
|
case JFileChooser.DIRECTORY_CHANGED_PROPERTY:
|
||||||
|
directoryChanged( fc.getCurrentDirectory() );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return icon;
|
//---- interface Scrollable ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dimension getPreferredScrollableViewportSize() {
|
||||||
|
if( getComponentCount() > 0 ) {
|
||||||
|
Insets insets = getInsets();
|
||||||
|
int height = (getComponent( 0 ).getPreferredSize().height * 5) + insets.top + insets.bottom;
|
||||||
|
return new Dimension( getPreferredSize().width, height );
|
||||||
|
}
|
||||||
|
return getPreferredSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getScrollableUnitIncrement( Rectangle visibleRect, int orientation, int direction ) {
|
||||||
|
if( orientation == SwingConstants.VERTICAL && getComponentCount() > 0 )
|
||||||
|
return getComponent( 0 ).getPreferredSize().height;
|
||||||
|
|
||||||
|
return getScrollableBlockIncrement( visibleRect, orientation, direction ) / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getScrollableBlockIncrement( Rectangle visibleRect, int orientation, int direction ) {
|
||||||
|
return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getScrollableTracksViewportWidth() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getScrollableTracksViewportHeight() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class ShortcutIcon -------------------------------------------------
|
||||||
|
|
||||||
|
private static class ShortcutIcon
|
||||||
|
implements Icon
|
||||||
|
{
|
||||||
|
private final Icon icon;
|
||||||
|
private final int iconWidth;
|
||||||
|
private final int iconHeight;
|
||||||
|
|
||||||
|
ShortcutIcon( Icon icon, int iconWidth, int iconHeight ) {
|
||||||
|
this.icon = icon;
|
||||||
|
this.iconWidth = iconWidth;
|
||||||
|
this.iconHeight = iconHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintIcon( Component c, Graphics g, int x, int y ) {
|
||||||
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
|
try {
|
||||||
|
// set rendering hint for the case that the icon is a bitmap (not used for vector icons)
|
||||||
|
g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC );
|
||||||
|
|
||||||
|
double scale = (double) getIconWidth() / (double) icon.getIconWidth();
|
||||||
|
g2.translate( x, y );
|
||||||
|
g2.scale( scale, scale );
|
||||||
|
|
||||||
|
icon.paintIcon( c, g2, 0, 0 );
|
||||||
|
} finally {
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconWidth() {
|
||||||
|
return UIScale.scale( iconWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIconHeight() {
|
||||||
|
return UIScale.scale( iconHeight );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,11 +39,10 @@ import javax.swing.plaf.ComponentUI;
|
|||||||
*
|
*
|
||||||
* <!-- FlatTextFieldUI -->
|
* <!-- FlatTextFieldUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault TextComponent.arc int
|
|
||||||
* @uiDefault Component.focusWidth int
|
|
||||||
* @uiDefault Component.minimumWidth int
|
* @uiDefault Component.minimumWidth int
|
||||||
* @uiDefault Component.isIntelliJTheme boolean
|
|
||||||
* @uiDefault FormattedTextField.placeholderForeground Color
|
* @uiDefault FormattedTextField.placeholderForeground Color
|
||||||
|
* @uiDefault FormattedTextField.focusedBackground Color optional
|
||||||
|
* @uiDefault FormattedTextField.iconTextGap int optional, default is 4
|
||||||
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
|
||||||
* @uiDefault TextComponent.selectAllOnMouseClick boolean
|
* @uiDefault TextComponent.selectAllOnMouseClick boolean
|
||||||
*
|
*
|
||||||
@@ -60,4 +59,10 @@ public class FlatFormattedTextFieldUI
|
|||||||
protected String getPropertyPrefix() {
|
protected String getPropertyPrefix() {
|
||||||
return "FormattedTextField";
|
return "FormattedTextField";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
String getStyleType() {
|
||||||
|
return "FormattedTextField";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
290
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
290
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 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.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JToolTip;
|
||||||
|
import javax.swing.plaf.basic.BasicHTML;
|
||||||
|
import javax.swing.text.AttributeSet;
|
||||||
|
import javax.swing.text.Document;
|
||||||
|
import javax.swing.text.LabelView;
|
||||||
|
import javax.swing.text.Style;
|
||||||
|
import javax.swing.text.StyleConstants;
|
||||||
|
import javax.swing.text.View;
|
||||||
|
import javax.swing.text.html.CSS;
|
||||||
|
import javax.swing.text.html.HTMLDocument;
|
||||||
|
import javax.swing.text.html.StyleSheet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public class FlatHTML
|
||||||
|
{
|
||||||
|
private FlatHTML() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds CSS rule BASE_SIZE to the style sheet of the HTML view,
|
||||||
|
* which re-calculates font sizes based on current component font size.
|
||||||
|
* This is necessary for "absolute-size" keywords (e.g. "x-large")
|
||||||
|
* for "font-size" attributes in default style sheet (see javax/swing/text/html/default.css).
|
||||||
|
* See also <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-size#values">CSS font-size</a>.
|
||||||
|
* <p>
|
||||||
|
* This method should be invoked after {@link BasicHTML#updateRenderer(JComponent, String)}.
|
||||||
|
*/
|
||||||
|
public static void updateRendererCSSFontBaseSize( JComponent c ) {
|
||||||
|
View view = (View) c.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// dumpViews( view, 0 );
|
||||||
|
|
||||||
|
Document doc = view.getDocument();
|
||||||
|
if( !(doc instanceof HTMLDocument) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// add BASE_SIZE rule if necessary
|
||||||
|
// - if point size at index 7 is not 36, then probably HTML text contains BASE_SIZE rule
|
||||||
|
// - if point size at index 4 is equal to given font size, then it is not necessary to add BASE_SIZE rule
|
||||||
|
StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet();
|
||||||
|
/*debug
|
||||||
|
for( int i = 1; i <= 7; i++ )
|
||||||
|
System.out.println( i+": "+ styleSheet.getPointSize( i ) );
|
||||||
|
debug*/
|
||||||
|
Font font = c.getFont();
|
||||||
|
if( styleSheet.getPointSize( 7 ) != 36f ||
|
||||||
|
font == null || styleSheet.getPointSize( 4 ) == font.getSize() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// check whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
|
||||||
|
if( !usesAbsoluteSizeKeywordForFontSize( view ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get HTML text from component
|
||||||
|
String text;
|
||||||
|
if( c instanceof JLabel )
|
||||||
|
text = ((JLabel)c).getText();
|
||||||
|
else if( c instanceof AbstractButton )
|
||||||
|
text = ((AbstractButton)c).getText();
|
||||||
|
else if( c instanceof JToolTip )
|
||||||
|
text = ((JToolTip)c).getTipText();
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
if( text == null || !BasicHTML.isHTMLString( text ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
||||||
|
String style = "<style>BASE_SIZE " + font.getSize() + "</style>";
|
||||||
|
String openTag = "";
|
||||||
|
String closeTag = "";
|
||||||
|
|
||||||
|
int headIndex;
|
||||||
|
int styleIndex;
|
||||||
|
|
||||||
|
int insertIndex;
|
||||||
|
if( (headIndex = indexOfTag( text, "head", true )) >= 0 ) {
|
||||||
|
// there is a <head> tag --> insert after <head> tag
|
||||||
|
insertIndex = headIndex;
|
||||||
|
} else if( (styleIndex = indexOfTag( text, "style", false )) >= 0 ) {
|
||||||
|
// there is a <style> tag --> insert before <style> tag
|
||||||
|
insertIndex = styleIndex;
|
||||||
|
} else {
|
||||||
|
// no <head> or <style> tag --> insert <head> tag after <html> tag
|
||||||
|
insertIndex = "<html>".length();
|
||||||
|
openTag = "<head>";
|
||||||
|
closeTag = "</head>";
|
||||||
|
}
|
||||||
|
|
||||||
|
String newText = text.substring( 0, insertIndex )
|
||||||
|
+ openTag + style + closeTag
|
||||||
|
+ text.substring( insertIndex );
|
||||||
|
|
||||||
|
BasicHTML.updateRenderer( c, newText );
|
||||||
|
|
||||||
|
// for unit tests
|
||||||
|
if( testUpdateRenderer != null )
|
||||||
|
testUpdateRenderer.accept( c, newText );
|
||||||
|
}
|
||||||
|
|
||||||
|
// for unit tests
|
||||||
|
static BiConsumer<JComponent, String> testUpdateRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns start or end index of a HTML tag.
|
||||||
|
* Checks only for leading '<' character and (case-ignore) tag name.
|
||||||
|
*/
|
||||||
|
private static int indexOfTag( String html, String tag, boolean endIndex ) {
|
||||||
|
int tagLength = tag.length();
|
||||||
|
int maxLength = html.length() - tagLength - 2;
|
||||||
|
char lastTagChar = tag.charAt( tagLength - 1 );
|
||||||
|
|
||||||
|
for( int i = "<html>".length(); i < maxLength; i++ ) {
|
||||||
|
// check for leading '<' and last tag name character
|
||||||
|
if( html.charAt( i ) == '<' && Character.toLowerCase( html.charAt( i + tagLength ) ) == lastTagChar ) {
|
||||||
|
// compare tag characters from last to first
|
||||||
|
for( int j = tagLength - 2; j >= 0; j-- ) {
|
||||||
|
if( Character.toLowerCase( html.charAt( i + 1 + j ) ) != tag.charAt( j ) )
|
||||||
|
break; // not equal
|
||||||
|
|
||||||
|
if( j == 0 ) {
|
||||||
|
// tag found
|
||||||
|
return endIndex ? html.indexOf( '>', i + tagLength ) + 1 : i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Set<String> absoluteSizeKeywordsSet = new HashSet<>( Arrays.asList(
|
||||||
|
"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large" ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether view uses "absolute-size" keywords (e.g. "x-large") for font-size
|
||||||
|
* (see javax/swing/text/html/default.css).
|
||||||
|
*/
|
||||||
|
private static boolean usesAbsoluteSizeKeywordForFontSize( View view ) {
|
||||||
|
AttributeSet attributes = view.getAttributes();
|
||||||
|
if( attributes != null ) {
|
||||||
|
Object fontSize = attributes.getAttribute( CSS.Attribute.FONT_SIZE );
|
||||||
|
if( fontSize != null ) {
|
||||||
|
if( absoluteSizeKeywordsSet.contains( fontSize.toString() ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int viewCount = view.getViewCount();
|
||||||
|
for( int i = 0; i < viewCount; i++ ) {
|
||||||
|
if( usesAbsoluteSizeKeywordForFontSize( view.getView( i ) ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates foreground in style sheet of the HTML view.
|
||||||
|
* Adds "body { color: #<foreground-hex>; }"
|
||||||
|
*/
|
||||||
|
public static void updateRendererCSSForeground( View view, Color foreground ) {
|
||||||
|
Document doc = view.getDocument();
|
||||||
|
if( !(doc instanceof HTMLDocument) || foreground == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// add foreground rule if necessary
|
||||||
|
// - use tag 'body' because BasicHTML.createHTMLView() also uses this tag
|
||||||
|
// to set font and color styles to component font/color
|
||||||
|
// see: SwingUtilities2.displayPropertiesToCSS()
|
||||||
|
// - this color is not used if component is disabled;
|
||||||
|
// JTextComponent.getDisabledTextColor() is used for disabled text components;
|
||||||
|
// UIManager.getColor("textInactiveText") is used for other disabled components
|
||||||
|
// see: javax.swing.text.GlyphView.paint()
|
||||||
|
Style bodyStyle = ((HTMLDocument)doc).getStyle( "body" );
|
||||||
|
if( bodyStyle == null ) {
|
||||||
|
StyleSheet styleSheet = ((HTMLDocument)doc).getStyleSheet();
|
||||||
|
styleSheet.addRule( String.format( "body { color: #%06x; }", foreground.getRGB() & 0xffffff ) );
|
||||||
|
clearViewCaches( view );
|
||||||
|
} else if( !foreground.equals( bodyStyle.getAttribute( StyleConstants.Foreground ) ) ) {
|
||||||
|
bodyStyle.addAttribute( StyleConstants.Foreground, foreground );
|
||||||
|
clearViewCaches( view );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears cached values in view so that CSS changes take effect.
|
||||||
|
*/
|
||||||
|
private static void clearViewCaches( View view ) {
|
||||||
|
if( view instanceof LabelView )
|
||||||
|
((LabelView)view).changedUpdate( null, null, null );
|
||||||
|
|
||||||
|
int viewCount = view.getViewCount();
|
||||||
|
for( int i = 0; i < viewCount; i++ )
|
||||||
|
clearViewCaches( view.getView( i ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PropertyChangeListener createPropertyChangeListener( PropertyChangeListener superListener ) {
|
||||||
|
return e -> {
|
||||||
|
if( superListener != null )
|
||||||
|
superListener.propertyChange( e );
|
||||||
|
propertyChange( e );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes {@link #updateRendererCSSFontBaseSize(JComponent)}
|
||||||
|
* for {@link BasicHTML#propertyKey} property change events,
|
||||||
|
* which are fired when {@link BasicHTML#updateRenderer(JComponent, String)}
|
||||||
|
* updates the HTML view.
|
||||||
|
*/
|
||||||
|
public static void propertyChange( PropertyChangeEvent e ) {
|
||||||
|
if( BasicHTML.propertyKey.equals( e.getPropertyName() ) && e.getNewValue() instanceof View )
|
||||||
|
updateRendererCSSFontBaseSize( (JComponent) e.getSource() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*debug
|
||||||
|
public static void dumpView( JComponent c ) {
|
||||||
|
View view = (View) c.getClientProperty( BasicHTML.propertyKey );
|
||||||
|
if( view != null )
|
||||||
|
dumpViews( view, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dumpViews( View view, int indent ) {
|
||||||
|
for( int i = 0; i < indent; i++ )
|
||||||
|
System.out.print( " " );
|
||||||
|
|
||||||
|
System.out.printf( "%s @%-8x %3d,%2d",
|
||||||
|
view.getClass().isAnonymousClass() ? view.getClass().getName() : view.getClass().getSimpleName(),
|
||||||
|
System.identityHashCode( view ),
|
||||||
|
(int) view.getPreferredSpan( View.X_AXIS ),
|
||||||
|
(int) view.getPreferredSpan( View.Y_AXIS ) );
|
||||||
|
|
||||||
|
AttributeSet attrs = view.getAttributes();
|
||||||
|
if( attrs != null ) {
|
||||||
|
Object fontSize = attrs.getAttribute( CSS.Attribute.FONT_SIZE );
|
||||||
|
System.out.printf( " %-8s", fontSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( view instanceof javax.swing.text.GlyphView ) {
|
||||||
|
javax.swing.text.GlyphView gview = ((javax.swing.text.GlyphView)view);
|
||||||
|
java.awt.Font font = gview.getFont();
|
||||||
|
System.out.printf( " %3d-%-3d %s %2d (@%x) #%06x '%s'",
|
||||||
|
gview.getStartOffset(), gview.getEndOffset() - 1,
|
||||||
|
font.getName(), font.getSize(), System.identityHashCode( font ),
|
||||||
|
gview.getForeground().getRGB() & 0xffffff,
|
||||||
|
gview.getText( gview.getStartOffset(), gview.getEndOffset() ) );
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
int viewCount = view.getViewCount();
|
||||||
|
for( int i = 0; i < viewCount; i++ ) {
|
||||||
|
View child = view.getView( i );
|
||||||
|
dumpViews( child, indent + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug*/
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.LayoutManager;
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
@@ -146,6 +147,19 @@ public class FlatInternalFrameTitlePane
|
|||||||
closeButton.setVisible( frame.isClosable() );
|
closeButton.setVisible( frame.isClosable() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle getFrameIconBounds() {
|
||||||
|
Icon icon = titleLabel.getIcon();
|
||||||
|
if( icon == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int iconWidth = icon.getIconWidth();
|
||||||
|
int iconHeight = icon.getIconHeight();
|
||||||
|
boolean leftToRight = titleLabel.getComponentOrientation().isLeftToRight();
|
||||||
|
int x = titleLabel.getX() + (leftToRight ? 0 : (titleLabel.getWidth() - iconWidth));
|
||||||
|
int y = titleLabel.getY() + ((titleLabel.getHeight() - iconHeight) / 2);
|
||||||
|
return new Rectangle( x, y, iconWidth, iconHeight );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does nothing because FlatLaf internal frames do not have system menus.
|
* Does nothing because FlatLaf internal frames do not have system menus.
|
||||||
*/
|
*/
|
||||||
@@ -199,6 +213,13 @@ public class FlatInternalFrameTitlePane
|
|||||||
case "componentOrientation":
|
case "componentOrientation":
|
||||||
applyComponentOrientation( frame.getComponentOrientation() );
|
applyComponentOrientation( frame.getComponentOrientation() );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "opaque":
|
||||||
|
// Do not invoke super.propertyChange() here because it always
|
||||||
|
// invokes repaint(), which would cause endless repainting.
|
||||||
|
// The opaque flag is temporary changed in FlatUIUtils.hasOpaqueBeenExplicitlySet(),
|
||||||
|
// invoked from FlatInternalFrameUI.update().
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.propertyChange( e );
|
super.propertyChange( e );
|
||||||
|
|||||||
@@ -22,12 +22,22 @@ import java.awt.Component;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JInternalFrame;
|
import javax.swing.JInternalFrame;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.event.MouseInputAdapter;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
import javax.swing.plaf.basic.BasicInternalFrameUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableBorder;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}.
|
||||||
@@ -83,9 +93,13 @@ import javax.swing.plaf.basic.BasicInternalFrameUI;
|
|||||||
*/
|
*/
|
||||||
public class FlatInternalFrameUI
|
public class FlatInternalFrameUI
|
||||||
extends BasicInternalFrameUI
|
extends BasicInternalFrameUI
|
||||||
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
protected FlatWindowResizer windowResizer;
|
protected FlatWindowResizer windowResizer;
|
||||||
|
|
||||||
|
private Map<String, Object> oldStyleValues;
|
||||||
|
private AtomicBoolean borderShared;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatInternalFrameUI( (JInternalFrame) c );
|
return new FlatInternalFrameUI( (JInternalFrame) c );
|
||||||
}
|
}
|
||||||
@@ -101,6 +115,8 @@ public class FlatInternalFrameUI
|
|||||||
LookAndFeel.installProperty( frame, "opaque", false );
|
LookAndFeel.installProperty( frame, "opaque", false );
|
||||||
|
|
||||||
windowResizer = createWindowResizer();
|
windowResizer = createWindowResizer();
|
||||||
|
|
||||||
|
installStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -111,6 +127,9 @@ public class FlatInternalFrameUI
|
|||||||
windowResizer.uninstall();
|
windowResizer.uninstall();
|
||||||
windowResizer = null;
|
windowResizer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldStyleValues = null;
|
||||||
|
borderShared = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -122,15 +141,80 @@ public class FlatInternalFrameUI
|
|||||||
return new FlatWindowResizer.InternalFrameResizer( frame, this::getDesktopManager );
|
return new FlatWindowResizer.InternalFrameResizer( frame, this::getDesktopManager );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MouseInputAdapter createBorderListener( JInternalFrame w ) {
|
||||||
|
return new FlatBorderListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PropertyChangeListener createPropertyChangeListener() {
|
||||||
|
return FlatStylingSupport.createPropertyChangeListener( frame, this::installStyle,
|
||||||
|
super.createPropertyChangeListener() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void installStyle() {
|
||||||
|
try {
|
||||||
|
applyStyle( FlatStylingSupport.getResolvedStyle( frame, "InternalFrame" ) );
|
||||||
|
} catch( RuntimeException ex ) {
|
||||||
|
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected void applyStyle( Object style ) {
|
||||||
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
protected Object applyStyleProperty( String key, Object value ) {
|
||||||
|
if( borderShared == null )
|
||||||
|
borderShared = new AtomicBoolean( true );
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, frame, borderShared );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this, frame.getBorder() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( JComponent c, String key ) {
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, frame.getBorder(), key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( Graphics g, JComponent c ) {
|
||||||
|
// The internal frame actually should be opaque and fill its background,
|
||||||
|
// but it must be non-opaque to allow translucent resize handles (outside of visual bounds).
|
||||||
|
// To avoid that parent may shine through internal frame (e.g. if menu bar is non-opaque),
|
||||||
|
// fill background excluding insets (translucent resize handles),
|
||||||
|
// but only if opaque was not set explicitly by application to false.
|
||||||
|
// If applications has set internal frame opacity to false, do not fill background (for compatibility).
|
||||||
|
if( !c.isOpaque() && !FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) ) {
|
||||||
|
Insets insets = c.getInsets();
|
||||||
|
|
||||||
|
g.setColor( c.getBackground() );
|
||||||
|
g.fillRect( insets.left, insets.top,
|
||||||
|
c.getWidth() - insets.left - insets.right,
|
||||||
|
c.getHeight() - insets.top - insets.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
|
super.update( g, c );
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatInternalFrameBorder --------------------------------------
|
//---- class FlatInternalFrameBorder --------------------------------------
|
||||||
|
|
||||||
public static class FlatInternalFrameBorder
|
public static class FlatInternalFrameBorder
|
||||||
extends FlatEmptyBorder
|
extends FlatEmptyBorder
|
||||||
|
implements StyleableBorder
|
||||||
{
|
{
|
||||||
private final Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
@Styleable protected Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" );
|
||||||
private final Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
@Styleable protected Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" );
|
||||||
private final int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
@Styleable protected int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 );
|
||||||
private final boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" );
|
@Styleable protected boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" );
|
||||||
|
|
||||||
private final FlatDropShadowBorder activeDropShadowBorder = new FlatDropShadowBorder(
|
private final FlatDropShadowBorder activeDropShadowBorder = new FlatDropShadowBorder(
|
||||||
UIManager.getColor( "InternalFrame.activeDropShadowColor" ),
|
UIManager.getColor( "InternalFrame.activeDropShadowColor" ),
|
||||||
@@ -145,6 +229,53 @@ public class FlatInternalFrameUI
|
|||||||
super( UIManager.getInsets( "InternalFrame.borderMargins" ) );
|
super( UIManager.getInsets( "InternalFrame.borderMargins" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object applyStyleProperty( String key, Object value ) {
|
||||||
|
switch( key ) {
|
||||||
|
case "borderMargins": return applyStyleProperty( (Insets) value );
|
||||||
|
|
||||||
|
case "activeDropShadowColor": return activeDropShadowBorder.applyStyleProperty( "shadowColor", value );
|
||||||
|
case "activeDropShadowInsets": return activeDropShadowBorder.applyStyleProperty( "shadowInsets", value );
|
||||||
|
case "activeDropShadowOpacity": return activeDropShadowBorder.applyStyleProperty( "shadowOpacity", value );
|
||||||
|
case "inactiveDropShadowColor": return inactiveDropShadowBorder.applyStyleProperty( "shadowColor", value );
|
||||||
|
case "inactiveDropShadowInsets": return inactiveDropShadowBorder.applyStyleProperty( "shadowInsets", value );
|
||||||
|
case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.applyStyleProperty( "shadowOpacity", value );
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.applyToAnnotatedObject( this, key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Class<?>> getStyleableInfos() {
|
||||||
|
Map<String, Class<?>> infos = new FlatStylingSupport.StyleableInfosMap<>();
|
||||||
|
FlatStylingSupport.collectAnnotatedStyleableInfos( this, infos );
|
||||||
|
infos.put( "borderMargins", Insets.class );
|
||||||
|
infos.put( "activeDropShadowColor", Color.class );
|
||||||
|
infos.put( "activeDropShadowInsets", Insets.class );
|
||||||
|
infos.put( "activeDropShadowOpacity", float.class );
|
||||||
|
infos.put( "inactiveDropShadowColor", Color.class );
|
||||||
|
infos.put( "inactiveDropShadowInsets", Insets.class );
|
||||||
|
infos.put( "inactiveDropShadowOpacity", float.class );
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.5 */
|
||||||
|
@Override
|
||||||
|
public Object getStyleableValue( String key ) {
|
||||||
|
switch( key ) {
|
||||||
|
case "borderMargins": return getStyleableValue();
|
||||||
|
|
||||||
|
case "activeDropShadowColor": return activeDropShadowBorder.getStyleableValue( "shadowColor" );
|
||||||
|
case "activeDropShadowInsets": return activeDropShadowBorder.getStyleableValue( "shadowInsets" );
|
||||||
|
case "activeDropShadowOpacity": return activeDropShadowBorder.getStyleableValue( "shadowOpacity" );
|
||||||
|
case "inactiveDropShadowColor": return inactiveDropShadowBorder.getStyleableValue( "shadowColor" );
|
||||||
|
case "inactiveDropShadowInsets": return inactiveDropShadowBorder.getStyleableValue( "shadowInsets" );
|
||||||
|
case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.getStyleableValue( "shadowOpacity" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||||
if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) {
|
if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) {
|
||||||
@@ -195,4 +326,27 @@ public class FlatInternalFrameUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class FlatBorderListener -------------------------------------------
|
||||||
|
|
||||||
|
/** @since 1.6 */
|
||||||
|
protected class FlatBorderListener
|
||||||
|
extends BorderListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void mouseClicked( MouseEvent e ) {
|
||||||
|
if( e.getClickCount() == 2 && !frame.isIcon() &&
|
||||||
|
e.getSource() instanceof FlatInternalFrameTitlePane )
|
||||||
|
{
|
||||||
|
Rectangle iconBounds = ((FlatInternalFrameTitlePane)e.getSource()).getFrameIconBounds();
|
||||||
|
if( iconBounds != null && iconBounds.contains( e.getX(), e.getY() ) ) {
|
||||||
|
if( frame.isClosable() )
|
||||||
|
frame.doDefaultCloseAction();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.mouseClicked( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user