mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
Compare commits
661 Commits
animated-b
...
3.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
6b880af447 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -20,7 +20,9 @@
|
||||
*.gif binary
|
||||
*.jar binary
|
||||
*.lib binary
|
||||
*.otf binary
|
||||
*.png binary
|
||||
*.sketch binary
|
||||
*.so binary
|
||||
*.ttf binary
|
||||
*.zip binary
|
||||
|
||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
custom: https://www.formdev.com/flatlaf/sponsor/
|
||||
104
.github/workflows/ci.yml
vendored
104
.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
|
||||
|
||||
@@ -8,9 +9,14 @@ on:
|
||||
- '*'
|
||||
tags:
|
||||
- '[0-9]*'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '.*'
|
||||
- '**/.settings/**'
|
||||
- 'flatlaf-core/svg/**'
|
||||
- 'flatlaf-testing/dumps/**'
|
||||
- 'flatlaf-testing/misc/**'
|
||||
- 'images/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -19,51 +25,47 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
# test against
|
||||
# - Java 1.8 (minimum requirement)
|
||||
# - Java 9 (first version with JPMS)
|
||||
# - Java 8 (minimum requirement)
|
||||
# - Java LTS versions (11, 17, ...)
|
||||
# - lastest Java version(s)
|
||||
# - latest Java version(s)
|
||||
java:
|
||||
- 1.8
|
||||
- 9
|
||||
- 8
|
||||
- 11 # LTS
|
||||
- 14
|
||||
- 15
|
||||
- 17 # LTS
|
||||
- 21 # LTS
|
||||
toolchain: [""]
|
||||
include:
|
||||
- java: 21
|
||||
toolchain: 22 # latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
if: matrix.java == '1.8'
|
||||
- uses: gradle/wrapper-validation-action@v2
|
||||
if: matrix.java == '8'
|
||||
|
||||
- name: Setup Java ${{ matrix.java }}
|
||||
uses: actions/setup-java@v1
|
||||
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: Cache Gradle wrapper
|
||||
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: Check with Error Prone
|
||||
if: matrix.java == '11'
|
||||
run: ./gradlew errorprone clean -Dtoolchain=${{ matrix.toolchain }}
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
run: ./gradlew build -Dtoolchain=${{ matrix.toolchain }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
if: matrix.java == '11'
|
||||
with:
|
||||
name: FlatLaf-build-artifacts
|
||||
path: |
|
||||
flatlaf-*/build/libs
|
||||
flatlaf-*/flatlaf-*/build/libs
|
||||
!**/*-javadoc.jar
|
||||
!**/*-sources.jar
|
||||
|
||||
@@ -73,32 +75,21 @@ jobs:
|
||||
needs: build
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
github.ref == 'refs/heads/main' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )) &&
|
||||
github.repository == 'JFormDesigner/FlatLaf'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
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
|
||||
distribution: temurin # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Publish snapshot to oss.sonatype.org
|
||||
run: ./gradlew publish :flatlaf-theme-editor:build -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||
run: ./gradlew publish :flatlaf-theme-editor:build -PskipFonts -Dorg.gradle.internal.publish.checksums.insecure=true -Dorg.gradle.parallel=false
|
||||
env:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
@@ -124,28 +115,17 @@ jobs:
|
||||
github.repository == 'JFormDesigner/FlatLaf'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
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
|
||||
distribution: temurin # pre-installed on ubuntu-latest
|
||||
cache: gradle
|
||||
|
||||
- name: Release a new stable version to Maven Central
|
||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -Drelease=true
|
||||
run: ./gradlew publish :flatlaf-demo:build :flatlaf-theme-editor:build -PskipFonts -Prelease -Dorg.gradle.parallel=false
|
||||
env:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
|
||||
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 oss.sonatype.org
|
||||
run: ./gradlew :flatlaf-fonts-${{ matrix.font }}:publish -Dorg.gradle.internal.publish.checksums.insecure=true
|
||||
env:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_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:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
|
||||
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
|
||||
if: startsWith( github.ref, format( 'refs/tags/fonts/{0}-', matrix.font ) )
|
||||
63
.github/workflows/natives.yml
vendored
63
.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
|
||||
|
||||
@@ -9,50 +10,44 @@ on:
|
||||
tags:
|
||||
- '[0-9]*'
|
||||
paths:
|
||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
paths:
|
||||
- 'flatlaf-natives/flatlaf-natives-windows/**'
|
||||
- 'flatlaf-natives/**'
|
||||
- '.github/workflows/natives.yml'
|
||||
- 'gradle/wrapper/gradle-wrapper.properties'
|
||||
- '!**.md'
|
||||
- '!**/.settings/**'
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
runs-on: windows-latest
|
||||
Natives:
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- windows
|
||||
- macos
|
||||
- ubuntu
|
||||
|
||||
runs-on: ${{ matrix.os }}-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: gradle/wrapper-validation-action@v2
|
||||
|
||||
- name: Setup Java 1.8
|
||||
uses: actions/setup-java@v1
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Cache Gradle wrapper
|
||||
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
|
||||
java-version: 11
|
||||
distribution: temurin
|
||||
cache: 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
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: FlatLaf-natives-windows-build-artifacts
|
||||
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
||||
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 oss.sonatype.org
|
||||
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:
|
||||
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
|
||||
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,5 +9,7 @@ out/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.xcuserstate
|
||||
*.xcworkspacedata
|
||||
.vs/
|
||||
.vscode/
|
||||
|
||||
724
CHANGELOG.md
724
CHANGELOG.md
@@ -1,7 +1,672 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 2.0-SNAPSHOT
|
||||
## 3.5
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Table: Support rounded selection. (PR #856)
|
||||
- Button and ToggleButton: Added border colors for pressed and selected states.
|
||||
(issue #848)
|
||||
- Label: Support painting background with rounded corners. (issue #842)
|
||||
- Popup: Fixed flicker of popups (e.g. tooltips) while they are moving (e.g.
|
||||
following mouse pointer). (issues #832 and #672)
|
||||
- FileChooser: Wrap shortcuts in scroll pane. (issue #828)
|
||||
- Theme Editor: On macOS, use larger window title bar. (PR #779)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- FlatLaf window decorations: Window top border on Windows 10 in "full window
|
||||
content" mode was not fully repainted when activating or deactivating window.
|
||||
(issue #809)
|
||||
- Button and ToggleButton: UI properties `[Toggle]Button.selectedForeground` and
|
||||
`[Toggle]Button.pressedForeground` did not work for HTML text. (issue #848)
|
||||
- HTML: Fixed font sizes for HTML tags `<h1>`...`<h6>`, `<code>`, `<kbd>`,
|
||||
`<big>`, `<small>` and `<samp>` in HTML text for components Button, CheckBox,
|
||||
RadioButton, MenuItem (and subclasses), JideLabel, JideButton, JXBusyLabel and
|
||||
JXHyperlink. Also fixed for Label and ToolTip if using Java 11+.
|
||||
- ScrollPane: Fixed/improved border painting at 125% - 175% scaling to avoid
|
||||
different border thicknesses. (issue #743)
|
||||
- Table: Fixed painting of alternating rows below table if auto-resize mode is
|
||||
`JTable.AUTO_RESIZE_OFF` and table width is smaller than scroll pane (was not
|
||||
updated when table width changed and was painted on wrong side in
|
||||
right-to-left component orientation).
|
||||
- Theme Editor: Fixed occasional empty window on startup on macOS.
|
||||
- FlatLaf window decorations: Fixed black line sometimes painted on top of
|
||||
(native) window border on Windows 11. (issue #852)
|
||||
- HiDPI: Fixed incomplete component paintings at 125% or 175% scaling on Windows
|
||||
where sometimes a 1px wide area at the right or bottom component edge is not
|
||||
repainted. E.g. ScrollPane focus indicator border. (issues #860 and #582)
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- ProgressBar: Log warning (including stack trace) when uninstalling
|
||||
indeterminate progress bar UI or using `JProgressBar.setIndeterminate(false)`
|
||||
not on AWT thread, because this may throw NPE in `FlatProgressBarUI.paint()`.
|
||||
(issues #841 and #830)
|
||||
- Panel: Rounded background of panel with rounded corners is now painted even if
|
||||
panel is not opaque. (issue #840)
|
||||
|
||||
|
||||
## 3.4.1
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- SplitPane: Update divider when client property `JSplitPane.expandableSide`
|
||||
changed.
|
||||
- TabbedPane: Fixed swapped back and forward scroll buttons when using
|
||||
`TabbedPane.scrollButtonsPlacement = trailing` (regression in FlatLaf 3.3).
|
||||
- Fixed missing window top border on Windows 10 in "full window content" mode.
|
||||
(issue #809)
|
||||
- Extras:
|
||||
- `FlatSVGIcon` color filters now support linear gradients. (PR #817)
|
||||
- `FlatSVGIcon`: Use log level `CONFIG` instead of `SEVERE` and allow
|
||||
disabling logging. (issue #823)
|
||||
- Added support for `JSplitPane.expandableSide` client property to
|
||||
`FlatSplitPane`.
|
||||
- Native libraries: Added API version check to test whether native library
|
||||
matches the JAR (bad builds could e.g. ship a newer JAR with an older
|
||||
incompatible native library) and to test whether native methods can be invoked
|
||||
(some security software allows loading native library but blocks method
|
||||
invocation).
|
||||
- macOS: Fixed crash when running in WebSwing. (issue #826; regression in 3.4)
|
||||
- macOS: Disabled rounded popup border (see PR #772) on macOS 14.4+ because it
|
||||
may freeze the application and crash the macOS WindowServer process (reports
|
||||
vary from Finder restarts to OS restarts). This is a temporary change until a
|
||||
solution is found. See NetBeans issues
|
||||
[apache/netbeans#7560](https://github.com/apache/netbeans/issues/7560#issuecomment-2226439215)
|
||||
and
|
||||
[apache/netbeans#6647](https://github.com/apache/netbeans/issues/6647#issuecomment-2070124442).
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- File names of custom properties files for nested Laf classes now must include
|
||||
name of enclosing class name. E.g. nested Laf class `IntelliJTheme.ThemeLaf`
|
||||
used `ThemeLaf.properties` in previous versions, but now needs to be named
|
||||
`IntelliJTheme$ThemeLaf.properties`.
|
||||
|
||||
|
||||
## 3.4
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- FlatLaf window decorations (Windows 10/11 and Linux): Support "full window
|
||||
content" mode, which allows you to extend the content into the window title
|
||||
bar. (PR #801)
|
||||
- macOS: Support larger window title bar close/minimize/zoom buttons spacing in
|
||||
[full window content](https://www.formdev.com/flatlaf/macos/#full_window_content)
|
||||
mode and introduced "buttons placeholder". (PR #779)
|
||||
- Native libraries:
|
||||
- System property `flatlaf.nativeLibraryPath` now supports loading native
|
||||
libraries named the same as on Maven central.
|
||||
- Published `flatlaf-<version>-no-natives.jar` to Maven Central. This JAR is
|
||||
equal to `flatlaf-<version>.jar`, except that it does not contain the
|
||||
FlatLaf native libraries. The Maven "classifier" to use this JAR is
|
||||
`no-natives`. You need to distribute the FlatLaf native libraries with your
|
||||
application.
|
||||
See https://www.formdev.com/flatlaf/native-libraries/ for more details.
|
||||
- Improved log messages for loading fails.
|
||||
- Fonts: Updated **Inter** to
|
||||
[v4.0](https://github.com/rsms/inter/releases/tag/v4.0).
|
||||
- Table: Select all text in cell editor when starting editing using `F2` key on
|
||||
Windows or Linux. (issue #652)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- macOS: Setting window background (of undecorated window) to translucent color
|
||||
(alpha < 255) did not show the window translucent. (issue #705)
|
||||
- JIDE CommandMenuBar: Fixed `ClassCastException` when JIDE command bar displays
|
||||
`JideMenu` in popup. (PR #794)
|
||||
|
||||
|
||||
## 3.3
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- macOS (10.14+): Popups (`JPopupMenu`, `JComboBox`, `JToolTip`, etc.) now use
|
||||
native macOS rounded borders. (PR #772; issue #715)
|
||||
- Native libraries: Added `libflatlaf-macos-arm64.dylib` and
|
||||
`libflatlaf-macos-x86_64.dylib`. See also
|
||||
https://www.formdev.com/flatlaf/native-libraries/.
|
||||
- ScrollPane: Support rounded border. (PR #713)
|
||||
- SplitPane: Support divider hover and pressed background colors. (PR #788)
|
||||
- TabbedPane: Support vertical tabs. (PR #758, issue #633)
|
||||
- TabbedPane: Paint rounded tab area background for rounded cards. (issue #717)
|
||||
- ToolBar: Added styling properties `separatorWidth` and `separatorColor`.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Button and ToggleButton: Selected buttons did not use explicitly set
|
||||
foreground color. (issue #756)
|
||||
- FileChooser: Catch NPE in Java 21 when getting icon for `.exe` files that use
|
||||
default Windows exe icon. (see
|
||||
[JDK-8320692](https://bugs.openjdk.org/browse/JDK-8320692))
|
||||
- OptionPane: Fixed styling custom panel background in `JOptionPane`. (issue
|
||||
#761)
|
||||
- ScrollPane: Styling ScrollPane border properties did not work if view
|
||||
component is a Table.
|
||||
- Table:
|
||||
- Switching theme looses table grid and intercell spacing. (issues #733 and
|
||||
#750)
|
||||
- Fixed background of `boolean` columns when using alternating row colors.
|
||||
(issue #780)
|
||||
- Fixed border arc of components in complex table cell editors. (issue #786)
|
||||
- TableHeader:
|
||||
- No longer temporary replace header cell renderer while painting. This avoids
|
||||
a `StackOverflowError` in case that custom renderer does this too. (see
|
||||
[NetBeans issue #6835](https://github.com/apache/netbeans/issues/6835)) This
|
||||
also improves compatibility with custom table header implementations.
|
||||
- Header cell renderer background/foreground colors were not restored after
|
||||
hover if renderer uses `null` for background/foreground. (PR #790)
|
||||
- TabbedPane:
|
||||
- Avoid unnecessary repainting whole tabbed pane content area when layouting
|
||||
leading/trailing components.
|
||||
- Avoid unnecessary repainting of selected tab on temporary changes.
|
||||
- Fixed "endless" layouting and repainting when using nested tabbed panes (top
|
||||
and bottom tab placement) and RSyntaxTextArea (with enabled line-wrapping)
|
||||
as tab content. (see
|
||||
[jadx issue #2030](https://github.com/skylot/jadx/issues/2030))
|
||||
- Fixed broken rendering after resizing window to minimum size and then
|
||||
increasing size again. (issue #767)
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- Removed support for JetBrains custom decorations, which required
|
||||
[JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/wiki) (JBR)
|
||||
8 or 11. It did not work for JBR 17. System property
|
||||
`flatlaf.useJetBrainsCustomDecorations` is now ignored. **Note**: FlatLaf
|
||||
window decorations continue to work with JBR.
|
||||
|
||||
|
||||
## 3.2.5
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Popup: Fixed NPE if popup invoker is `null` on Windows 10. (issue #753;
|
||||
regression in 3.2.1 in fix for #626)
|
||||
|
||||
|
||||
## 3.2.4
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Popup: Fixed NPE if popup invoker is `null` on Linux with Wayland and Java 21.
|
||||
(issue #752; regression in 3.2.3)
|
||||
|
||||
|
||||
## 3.2.3
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Popup: Popups that request focus were not shown on Linux with Wayland and Java 21.
|
||||
(issue #752)
|
||||
|
||||
|
||||
## 3.2.2
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Button: Fixed painting icon and text at wrong location when using HTML text,
|
||||
left/right vertical alignment and running in Java 19+. (issue #746)
|
||||
- CheckBox and RadioButton: Fixed cut off right side when border is removed and
|
||||
horizontal alignment is set to `right`. (issue #734)
|
||||
- TabbedPane: Fixed NPE when using focusable component as tab component and
|
||||
switching theme. (issue #745)
|
||||
|
||||
|
||||
## 3.2.1
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Fixed memory leak in
|
||||
`MultiResolutionImageSupport.create(int,Dimension[],Function<Dimension,Image>)`,
|
||||
which caches images created by the producer function. Used by
|
||||
`FlatSVGIcon.getImage()` and `FlatSVGUtils.createWindowIconImages()`. If you
|
||||
use one of these methods, it is **strongly recommended** to upgrade to this
|
||||
version, because if the returned image is larger and painted very often it may
|
||||
result in an out-of-memory situation. (issue #726)
|
||||
- FileChooser: Fixed occasional NPE in `FlatShortcutsPanel` on Windows. (issue
|
||||
#718)
|
||||
- TextField: Fixed placeholder text painting, which did not respect horizontal
|
||||
alignment property of `JTextField`. (issue #721)
|
||||
- Popup: Fixed drop shadow if popup overlaps a heavyweight component. (Windows
|
||||
10 only; issue #626)
|
||||
|
||||
|
||||
## 3.2
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- TabbedPane: Support rounded underline selection and rounded card tabs. (PR
|
||||
#703)
|
||||
- FlatLaf window decorations:
|
||||
- Support for Windows on ARM 64-bit. (issue #443, PR #707)
|
||||
- Support toolbox-style "small" window title bar. (issue #659, PR #702)
|
||||
- Extras: Class `FlatSVGIcon` now uses [JSVG](https://github.com/weisJ/jsvg)
|
||||
library (instead of svgSalamander) for rendering. JSVG provides improved SVG
|
||||
rendering and uses less memory compared to svgSalamander. (PR #684)
|
||||
- ComboBox: Improved location of selected item in popup if list is large and
|
||||
scrollable.
|
||||
- FileChooser: Show localized text for all locales supported by Java's Metal
|
||||
look and feel. (issue #680)
|
||||
- Added system property `flatlaf.useNativeLibrary` to allow disabling loading of
|
||||
FlatLaf native library. (issue #674)
|
||||
- IntelliJ Themes:
|
||||
- Reduced memory footprint by releasing Json data and ignoring IntelliJ UI
|
||||
properties that are not used in FlatLaf.
|
||||
- Updated "Hiberbee Dark" and "Gradianto" themes.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Styling: Fixed scaling of some styling properties (`rowHeight` for Table and
|
||||
Tree; `iconTextGap` for Button, CheckBox and RadioButton). (issue #682)
|
||||
- Fixed `IllegalComponentStateException` when invoker is not showing in
|
||||
`SubMenuUsabilityHelper`. (issue #692)
|
||||
- macOS themes: Changing `@accentColor` variable in FlatLaf properties files did
|
||||
not change all accent related colors for all components.
|
||||
- IntelliJ Themes:
|
||||
- "Light Owl" theme: Fixed wrong (unreadable) text color in selected menu
|
||||
items, selected text in text components, and selection in ComboBox popup
|
||||
list. (issue #687)
|
||||
- "Gradianto Midnight Blue" theme: Fixed color of ScrollBar track, which was
|
||||
not visible. (issue #686)
|
||||
- "Monocai" theme: Fixed unreadable text color of default buttons. (issue
|
||||
#693)
|
||||
- "Vuesion" theme: Fixed foreground colors of disabled text.
|
||||
- "Material UI Lite" themes: Fixed non-editable ComboBox button background.
|
||||
- CheckBox and RadioButton: Fixed unselected icon colors for themes "Atom One
|
||||
Light", "Cyan Light", "GitHub", "Light Owl", "Material Lighter" and
|
||||
"Solarized Light".
|
||||
- TabbedPane: Fixed focused tab background color for themes "Arc *", "Material
|
||||
Design Dark", "Monocai", "One Dark", "Spacegray" and "Xcode-Dark". (issue
|
||||
#697)
|
||||
- TextComponents, ComboBox and Spinner: Fixed background colors of enabled
|
||||
text components, to distinguish from disabled, for themes "Carbon", "Cobalt
|
||||
2", "Gradianto *", "Gruvbox *", "Monocai", "Spacegray", "Vuesion",
|
||||
"Xcode-Dark", "GitHub", and "Light Owl". (issue #528)
|
||||
- Fixed wrong disabled text colors in "Dark Flat", "Hiberbee Dark", "Light
|
||||
Flat", "Nord", "Solarized Dark" and "Solarized Light" themes.
|
||||
- Fixed colors for selection background/foreground, Separator, Slider track
|
||||
and ProgressBar background in various themes.
|
||||
- Native Windows libraries: Fixed crash when running in Java 8 and newer Java
|
||||
version is installed in `PATH` environment variable and using class
|
||||
`SystemInfo` before AWT initialization. (issue #673)
|
||||
- ComboBox: Fixed search in item list for text with spaces. (issue #691)
|
||||
- FormattedTextField: On Linux, fixed `IllegalArgumentException: Invalid
|
||||
location` if `JFormattedTextField.setDocument()` is invoked in a focus gained
|
||||
listener on that formatted text field. (issue #698)
|
||||
- PopupMenu: Make sure that popup menu does not overlap any operating system
|
||||
task bar. (issue #701)
|
||||
- FileChooser: Use system icons on Windows with Java 17.0.3 (and later) 32-bit.
|
||||
Only Java 17 - 17.0.2 32-bit do not use system icons because of a bug in Java
|
||||
32-bit that crashes the application. (PR #709)
|
||||
- FileChooser: Fixed crash on Windows with Java 17 to 17.0.2 32-bit. Java 17
|
||||
64-bit is not affected. (regression since FlatLaf 2.3; PR #522, see also issue
|
||||
#403)
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- Extras: Class `FlatSVGIcon` now uses [JSVG](https://github.com/weisJ/jsvg)
|
||||
library for SVG rendering. You need to replace svgSalamander with JSVG in your
|
||||
build scripts and distribute `jsvg.jar` with your application. Also replace
|
||||
`com.kitfox.svg` with `com.github.weisj.jsvg` in `module-info.java` files.
|
||||
- IntelliJ Themes: Removed all "Contrast" themes from "Material UI Lite".
|
||||
|
||||
|
||||
## 3.1.1
|
||||
|
||||
- IntelliJ Themes:
|
||||
- Fixed too large menu item paddings and too large table/tree row heights (all
|
||||
"Material Theme UI Lite" themes; issue #667; regression in FlatLaf 3.1).
|
||||
- Fixed too large tree row height in "Carbon", "Dark Purple", "Gray",
|
||||
"Material Design Dark", "Monokai Pro", "One Dark" and "Spacegray" themes.
|
||||
- Native libraries: Fixed `IllegalArgumentException: URI scheme is not "file"`
|
||||
when using FlatLaf in WebStart. (issue #668; regression in FlatLaf 3.1)
|
||||
|
||||
|
||||
## 3.1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Windows 11: Popups (`JPopupMenu`, `JComboBox`, `JToolTip`, etc.) now use
|
||||
native Windows 11 rounded borders and drop shadows. (PR #643)
|
||||
- Fonts:
|
||||
- Added **Roboto Mono** (https://fonts.google.com/specimen/Roboto+Mono). (PR
|
||||
#639, issue #638)
|
||||
- Updated **JetBrains Mono** to
|
||||
[v2.304](https://github.com/JetBrains/JetBrainsMono/releases/tag/v2.304).
|
||||
- Theme Editor: Support macOS light and dark themes.
|
||||
- TabbedPane: Support hover and focused tab foreground colors. (issue #627)
|
||||
- TabbedPane: `tabbedPane.getBackgroundAt(tabIndex)` now has higher priority
|
||||
than `TabbedPane.focusColor` and `TabbedPane.selectedBackground`. If
|
||||
`tabbedPane.setBackgroundAt(tabIndex)` is used to set a color for a single
|
||||
tab, then this color is now used even if the tab is focused or selected.
|
||||
- TableHeader: Support column hover and pressed background and foreground
|
||||
colors. (issue #636)
|
||||
- Native libraries: Made it easier to distribute FlatLaf native libraries
|
||||
(Windows `.dll` and Linux `.so`) to avoid problems on operating systems with
|
||||
enabled execution restrictions.
|
||||
See https://www.formdev.com/flatlaf/native-libraries/ for more details. (issue #624)
|
||||
- Published native libraries to Maven Central for easy using them as
|
||||
dependencies in Gradle and Maven.
|
||||
- If available, native libraries are now loaded from same location as
|
||||
`flatlaf.jar`, otherwise they are extract from `flatlaf.jar` to temporary
|
||||
folder and loaded from there.
|
||||
- Windows DLLs are now digitally signed with FormDev Software GmbH
|
||||
certificate.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- FlatLaf window decorations:
|
||||
- Fixed inconsistent size of glass pane depending on whether FlatLaf window
|
||||
decorations are used (e.g. Windows 10/11) or not (e.g. macOS). Now the glass
|
||||
pane no longer overlaps the FlatLaf window title bar. (issue #630)
|
||||
- Linux: Fixed broken window resizing on multi-screen setups. (issue #632)
|
||||
- Linux: Fixed behavior of maximize/restore button when tiling window to left
|
||||
or right half of screen. (issue #647)
|
||||
- IntelliJ Themes:
|
||||
- Fixed default button hover background in "Solarized Light" theme. (issue
|
||||
#628)
|
||||
- Avoid that accent color affect some colors in some IntelliJ themes. (issue
|
||||
#625)
|
||||
- Updated "Hiberbee Dark" and "Material Theme UI Lite" themes.
|
||||
- Styling: Fixed resolving of UI variables in styles that use other variables.
|
||||
- MenuItem: Fixed horizontal alignment of icons. (issue #631)
|
||||
- Table: Fixed potential performance issue with paint cell focus indicator
|
||||
border. (issue #654)
|
||||
- Tree: Fixed missing custom closed/opened/leaf icons of a custom
|
||||
`DefaultTreeCellRenderer`. (issue #653; regression since implementing PR #609
|
||||
in FlatLaf 3.0)
|
||||
- Tree: Fixed truncated node text and too small painted non-wide node background
|
||||
if custom cell renderer sets icon, but not disabled icon, and tree is
|
||||
disabled. (issue #640)
|
||||
- Fixed `HiDPIUtils.paintAtScale1x()`, which painted at wrong location if
|
||||
graphics is rotated, is scaled and `x` or `y` parameters are not zero. (issue
|
||||
#646)
|
||||
|
||||
|
||||
## 3.0
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- **macOS light and dark themes**: The two new themes `FlatMacLightLaf` and
|
||||
`FlatMacDarkLaf` use macOS colors and look similar to native macOS controls.
|
||||
(PRs #533, #612 and #607)
|
||||
- **Fonts**: Packaged some fonts into JARs and provide an easy way to use them
|
||||
with FlatLaf. (PRs #545, #614 and #615) At the moment there are three fonts:
|
||||
- **Inter** (https://rsms.me/inter/) - a typeface carefully crafted & designed
|
||||
for computer screens
|
||||
- **Roboto** (https://fonts.google.com/specimen/Roboto) - default font on
|
||||
Android and recommended for Material Design
|
||||
- **JetBrains Mono** (https://www.jetbrains.com/mono) - a monospaced typeface
|
||||
- **Rounded selection**: Optionally use rounded selection in:
|
||||
- Menus (PR #536)
|
||||
- ComboBox (PR #548)
|
||||
- List (PR #547)
|
||||
- Tree (PR #546)
|
||||
- Tree: Hide default closed/opened/leaf icons by default. Set UI value
|
||||
`Tree.showDefaultIcons` to `true` to show them.
|
||||
- ToolBar: Hover effect for button groups. (PR #534)
|
||||
- Icons: New modern **rounded outlined icons** for `JFileChooser`,
|
||||
`JOptionPane`, `JPasswordField` and `JTree`. (PR #577)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- FileChooser: Fixed layout of (optional) accessory component and fixed too
|
||||
large right margin. (issue #604; regression since implementing PR #522 in
|
||||
FlatLaf 2.3)
|
||||
- Tree:
|
||||
- Fixed missing tree lines (if enabled) for wide-selected rows. (issue #598)
|
||||
- Fixed scaling of tree lines and fixed alignment to expand/collapse arrows.
|
||||
- Removed support for dashed tree lines. `Tree.lineTypeDashed` is now ignored.
|
||||
- SwingX: Fonts in `JXHeader`, `JXMonthView`, `JXTaskPane` and `JXTitledPanel`
|
||||
were not updated when changing default font.
|
||||
|
||||
|
||||
## 2.6
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- If value of system property `flatlaf.nativeLibraryPath` is `system`, then
|
||||
`System.loadLibrary(String)` is used to load the native library.
|
||||
- TabbedPane: Switch and close tabs on left mouse click only. (PR #595)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox and Spinner: Fixed missing arrow buttons if preferred height is zero.
|
||||
Minimum width of arrow buttons is 3/4 of default width.
|
||||
- MenuBar: Fixed NPE in `FlatMenuItemRenderer.getTopLevelFont()` if menu item
|
||||
does not have a parent. (issue #600; regression since implementing #589 in
|
||||
FlatLaf 2.5)
|
||||
- ScrollBar: Show "pressed" feedback on track/thumb only for left mouse button.
|
||||
If absolute positioning is enabled (the default), then also for middle mouse
|
||||
button.
|
||||
- Arrow buttons in ComboBox, Spinner, ScrollBar and TabbedPane: Show "pressed"
|
||||
feedback only for left mouse button.
|
||||
- ScaledImageIcon: Do not throw exceptions if image was has invalid size (e.g.
|
||||
not found). Instead, paint a red rectangle (similar to `FlatSVGIcon`).
|
||||
- Fixed NPE in `FlatUIUtils.isCellEditor()`. (issue #601)
|
||||
|
||||
|
||||
## 2.5
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Linux: Use X11 window manager events to move window and to show window menu
|
||||
(right-click on window title bar), if custom window decorations are enabled.
|
||||
This gives FlatLaf windows a more "native" feeling. (issue #482)
|
||||
- MenuBar: Support different menu selection style UI defaults for `MenuBar` and
|
||||
`MenuItem`. (issue #587)
|
||||
- MenuBar: Top level menus now use `MenuBar.font` instead of `Menu.font`. (issue
|
||||
#589)
|
||||
- PasswordField: Reveal button is now hidden (and turned off) if password field
|
||||
is disabled. (issue #501)
|
||||
- TabbedPane: New option to disable tab run rotation in wrap layout. Set UI
|
||||
value `TabbedPane.rotateTabRuns` to `false`. (issue #574)
|
||||
- Window decorations:
|
||||
- Added client property to mark components in embedded menu bar as "caption"
|
||||
(allow moving window). (issue #569)
|
||||
- Option to show window icon only in frames, but not in dialogs. Set UI value
|
||||
`TitlePane.showIconInDialogs` to `false`. (issue #589)
|
||||
- Added UI value `TitlePane.font` to customize window title font. (issue #589)
|
||||
- Added system property `flatlaf.updateUIOnSystemFontChange` to allow disabling
|
||||
automatic UI update when system font changes. (issue #580)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Fixed missing UI value `MenuItem.acceleratorDelimiter` on macOS. (was `null`,
|
||||
is now an empty string)
|
||||
- Fixed possible exception in `FlatUIUtils.resetRenderingHints()`. (issue #575)
|
||||
- Fixed AWT components on macOS, which use Swing components internally. (issue
|
||||
#583)
|
||||
- SwingX: Fixed missing highlighting of "today" in `JXMonthView` and
|
||||
`JXDatePicker`.
|
||||
|
||||
|
||||
## 2.4
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Native window decorations (Windows 10/11 only):
|
||||
- There is now a small area at top of the embedded menu bar to resize the
|
||||
window.
|
||||
- Improved window title bar layout for small window widths:
|
||||
- Width of iconify/maximize/close buttons is reduced (if necessary) to give
|
||||
more space to embedded menu bar and title.
|
||||
- Window title now has a minimum width to always allow moving window
|
||||
(click-and-drag on window title). Instead, embedded menu bar is made
|
||||
smaller.
|
||||
- Option to show window icon beside window title, if menu bar is embedded or
|
||||
title is centered. Set UI value `TitlePane.showIconBesideTitle` to `true`.
|
||||
- No longer reduce height of window title bar if it has an embedded menu bar
|
||||
and is maximized.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox: Fixed vertical alignment of text in popup list with text in combo
|
||||
box in IntelliJ/Darcula themes.
|
||||
- Menus: Fixed application freeze under very special conditions (invoking
|
||||
`FlatLaf.initialize()` twice in NetBeans GUI builder) and using menu that has
|
||||
submenus. See
|
||||
[NetBeans issue #4231](https://github.com/apache/netbeans/issues/4231#issuecomment-1179611682)
|
||||
for details.
|
||||
- MenuItem: Fixed sometimes wrapped HTML text on HiDPI screens on Windows.
|
||||
- TableHeader: Fixed exception when changing table structure (e.g. removing
|
||||
column) from a table header popup menu action. (issue #532)
|
||||
- `HiDPIUtils.paintAtScale1x()` now supports rotated graphics. (issue #557)
|
||||
- Typography: No longer use `Consolas` or `Courier New` as monospaced font on
|
||||
Windows because they have bad vertically placement.
|
||||
- Native window decorations (Windows 10/11 only):
|
||||
- Do not center window title if embedded menu bar is empty or has no menus at
|
||||
left side, but some components at right side. (issue #558)
|
||||
- Do not use window decorations if system property `sun.java2d.opengl` is
|
||||
`true` on Windows 10. (issue #540)
|
||||
- Fixed missing top window border in dark themes if window drop shadows are
|
||||
disabled in system settings. (issue #554; Windows 10 only)
|
||||
- Right-to-left component orientation of title bar was lost when switching
|
||||
theme.
|
||||
|
||||
|
||||
## 2.3
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- FileChooser: Added (optional) shortcuts panel. On Windows it contains "Recent
|
||||
Items", "Desktop", "Documents", "This PC" and "Network". On macOS and Linux it
|
||||
is empty/hidden. (issue #100)
|
||||
- Button and ToggleButton: Added missing foreground colors for hover, pressed,
|
||||
focused and selected states. (issue #535)
|
||||
- Table: Optionally paint alternating rows below table if table is smaller than
|
||||
scroll pane. Set UI value `Table.paintOutsideAlternateRows` to `true`.
|
||||
Requires that `Table.alternateRowColor` is set to a color. (issue #504)
|
||||
- ToggleButton: Made the underline placement of tab-style toggle buttons
|
||||
configurable. (PR #530; issue #529)
|
||||
- Added spanish translation. (PR #525)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- IntelliJ Themes: Fixed `TitledBorder` text color in "Monokai Pro" theme.
|
||||
(issue #524)
|
||||
|
||||
|
||||
## 2.2
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- SplitPane: Allow limiting one-touch expanding to a single side (set client
|
||||
property `JSplitPane.expandableSide` to `"left"` or `"right"`). (issue #355)
|
||||
- TabbedPane: Selected tab underline color now changes depending on whether the
|
||||
focus is within the tab content. (issue #398)
|
||||
- IntelliJ Themes:
|
||||
- Added "Monokai Pro" and "Xcode-Dark" themes.
|
||||
- TabbedPane now use different background color for selected tabs in all "Arc"
|
||||
themes, in "Hiberbee Dark" and in all "Material UI Lite" themes.
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Native window decorations (Windows 10/11 only): Fixed wrong window title
|
||||
character encoding used in Windows taskbar. (issue #502)
|
||||
- Button: Fixed icon layout and preferred width of default buttons that use bold
|
||||
font. (issue #506)
|
||||
- FileChooser: Enabled full row selection for details view to fix alternate row
|
||||
coloring. (issue #512)
|
||||
- SplitPane: Fixed `StackOverflowError` caused by layout loop that may occur
|
||||
under special circumstances. (issue #513)
|
||||
- Table: Slightly changed grid colors to make grid better recognizable. (issue
|
||||
#514)
|
||||
- ToolBar: Fixed endless loop in focus navigation that may occur under special
|
||||
circumstances. (issue #505)
|
||||
- IntelliJ Themes: `Component.accentColor` UI property now has useful theme
|
||||
specific values. (issue #507)
|
||||
|
||||
|
||||
## 2.1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- Menus: Improved usability of submenus. (PR #490; issue #247)
|
||||
- Menus: Scroll large menus using mouse wheel or up/down arrows. (issue #225)
|
||||
- Linux: Support using custom window decorations. Enable with
|
||||
`JFrame.setDefaultLookAndFeelDecorated(true)` and
|
||||
`JDialog.setDefaultLookAndFeelDecorated(true)` before creating a window.
|
||||
(issue #482)
|
||||
- ScrollBar: Added UI value `ScrollBar.minimumButtonSize` to specify minimum
|
||||
scroll arrow button size (if shown). (issue #493)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- PasswordField: Fixed reveal button appearance in IntelliJ themes. (issue #494)
|
||||
- ScrollBar: Center and scale arrows in scroll up/down buttons (if shown).
|
||||
(issue #493)
|
||||
- TextArea, TextPane and EditorPane: No longer select all text when component is
|
||||
focused for the first time. (issue #498; regression in FlatLaf 2.0)
|
||||
- TabbedPane: Disable all items in "Show Hidden Tabs" popup menu if tabbed pane
|
||||
is disabled.
|
||||
|
||||
#### Incompatibilities
|
||||
|
||||
- Method `FlatUIUtils.paintArrow()` (and class `FlatArrowButton`) now paints
|
||||
arrows one pixel smaller than before. To fix this, increase parameter
|
||||
`arrowSize` by one.
|
||||
|
||||
|
||||
## 2.0.2
|
||||
|
||||
- Native window decorations (Windows 10/11 only): Fixed rendering artifacts on
|
||||
HiDPI screens when dragging window partly offscreen and back into screen
|
||||
bounds. (issue #477)
|
||||
- Repaint component when setting client property `JComponent.outline` (issue
|
||||
#480).
|
||||
- macOS: Fixed NPE when using some icons in main menu items. (issue #483)
|
||||
|
||||
|
||||
## 2.0.1
|
||||
|
||||
- Fixed memory leak in Panel, Separator and ToolBarSeparator. (issue #471;
|
||||
regression in FlatLaf 2.0)
|
||||
- ToolTip: Fixed wrong tooltip location if component overrides
|
||||
`JComponent.getToolTipLocation()` and wants place tooltip under mouse
|
||||
location. (issue #468)
|
||||
- Extras: Added copy constructor to `FlatSVGIcon`. (issue #465)
|
||||
- Moved `module-info.class` from `META-INF\versions\9\` to root folder of JARs.
|
||||
(issue #466)
|
||||
|
||||
|
||||
## 2.0
|
||||
|
||||
- Added system property `flatlaf.nativeLibraryPath` to load native libraries
|
||||
from a directory. (PR #453)
|
||||
- Fixed "endless recursion in font" exception in
|
||||
`FlatLaf$ActiveFont.createValue()` if `UIManager.getFont()` is invoked from
|
||||
multiple threads. (issue #456)
|
||||
- PasswordField: Preserve reveal button state when switching theme. (PR #442;
|
||||
issue #173)
|
||||
- PasswordField: Reveal button did not show password if
|
||||
`JPasswordField.setEchoChar()` was invoked from application. (PR #442; issue
|
||||
#173)
|
||||
- Slider: Fixed/improved focused indicator color when changing accent color. (PR
|
||||
#375)
|
||||
- TextField:
|
||||
- Improved hover/pressed/selected colors of leading/trailing buttons (e.g.
|
||||
"reveal" button in password field). (issue #452)
|
||||
- Clear button no longer paints over round border. (issue #451)
|
||||
- Extras: Fixed concurrent loading of SVG icons on multiple threads. (issue
|
||||
#459)
|
||||
- Use FlatLaf native window decorations by default when running in
|
||||
[JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime/wiki)
|
||||
(instead of using JetBrains custom decorations). System variable
|
||||
`flatlaf.useJetBrainsCustomDecorations` is now `false` by default (was `true`
|
||||
in FlatLaf 1.x). (issue #454)
|
||||
- Native window decorations:
|
||||
- Fixed blurry iconify/maximize/close button hover rectangles at 125%, 150% or
|
||||
175% scaling. (issue #431)
|
||||
- Updated maximize and restore icons for Windows 11 style. (requires Java
|
||||
8u321, 11.0.14, 17.0.2 or 18+)
|
||||
- Updated hover and pressed colors of iconify/maximize/close buttons for
|
||||
Windows 11 style.
|
||||
|
||||
|
||||
## 2.0-rc1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
@@ -24,13 +689,22 @@ FlatLaf Change Log
|
||||
- Possibility to hide window title bar icon (for single window set client
|
||||
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
|
||||
value `TitlePane.showIcon` to `false`).
|
||||
- OptionPane: Hide window title bar icon by default. Can be be made visibly by
|
||||
- OptionPane: Hide window title bar icon by default. Can be made visibly by
|
||||
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
|
||||
- No longer show the Java "duke/cup" icon if no window icon image is set.
|
||||
(issue #416)
|
||||
- TextField, FormattedTextField and PasswordField: Support leading and trailing
|
||||
icons (set client property `JTextField.leadingIcon` or
|
||||
`JTextField.trailingIcon` to an `Icon`). (PR #378; issue #368)
|
||||
- TextField, FormattedTextField and PasswordField:
|
||||
- Support leading and trailing icons (set client property
|
||||
`JTextField.leadingIcon` or `JTextField.trailingIcon` to a
|
||||
`javax.swing.Icon`). (PR #378; issue #368)
|
||||
- Support leading and trailing components (set client property
|
||||
`JTextField.leadingComponent` or `JTextField.trailingComponent` to a
|
||||
`java.awt.Component`). (PR #386)
|
||||
- Support "clear" (or "cancel") button to empty text field. Only shown if text
|
||||
field is not empty, editable and enabled. (set client property
|
||||
`JTextField.showClearButton` to `true`). (PR #442)
|
||||
- PasswordField: Support reveal (or "eye") button to show password. (see UI
|
||||
value `PasswordField.showRevealButton`) (PR #442; issue #173)
|
||||
- TextComponents: Double/triple-click-and-drag now extends selection by whole
|
||||
words/lines.
|
||||
- Theming improvements: Reworks core themes to make it easier to create new
|
||||
@@ -61,6 +735,10 @@ FlatLaf Change Log
|
||||
- Slider: Support specifying width of thumb border (see UI value
|
||||
`Slider.thumbBorderWidth`).
|
||||
- TabbedPane: Optionally paint selected tab as card. (PR #343)
|
||||
- MenuItem:
|
||||
- Paint the selected icon when the item is selected. (PR #415)
|
||||
- Vertically align text if icons have different widths. (issue #437)
|
||||
- Panel: Support painting background with rounded corners. (issue #367)
|
||||
- Added more color functions to class `ColorFunctions` for easy use in
|
||||
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
||||
`tint()`, `shade()` and `luma()`.
|
||||
@@ -73,6 +751,40 @@ FlatLaf Change Log
|
||||
- `FlatSVGIcon`: Support loading SVG from `URL` (for JPMS), `URI`, `File` or
|
||||
`InputStream`. (issues #419 and #325)
|
||||
- `FlatSVGUtils`: Support loading SVG from `URL` (for JPMS). (issue #325)
|
||||
- SwingX:
|
||||
- New "column control" icon for `JXTable` that scales and uses antialiasing.
|
||||
(issue #434)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Native window decorations: Fixed `UnsatisfiedLinkError` on Windows 11 for ARM
|
||||
processors. (issue #443)
|
||||
- MenuBar: Do not fill background if non-opaque and having custom background
|
||||
color. (issue #409)
|
||||
- InternalFrame: Fill background to avoid that parent may shine through internal
|
||||
frame if it contains non-opaque components. (better fix for issue #274)
|
||||
- SwingX: Fixed `NullPointerException` in `FlatCaret` when using
|
||||
`org.jdesktop.swingx.prompt.PromptSupport.setPrompt()` on a text field and
|
||||
then switching theme.
|
||||
|
||||
|
||||
## 1.6.5
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Linux: Fixed font problems when running on Oracle Java (OpenJDK is not
|
||||
affected):
|
||||
- oversized text if system font is "Inter" (issue #427)
|
||||
- missing text if system font is "Cantarell" (on Fedora)
|
||||
- MenuItem: Changed accelerator delimiter from `-` to `+`. (Windows and Linux).
|
||||
- ComboBox: Fixed occasional `StackOverflowError` when modifying combo box not
|
||||
on AWT thread. (issue #432)
|
||||
- macOS: Fixed `NullPointerException` when using AWT component
|
||||
`java.awt.Choice`. (issue #439)
|
||||
- Native window decorations: Do not exit application with `UnsatisfiedLinkError`
|
||||
in case that FlatLaf DLL cannot be executed because of restrictions on
|
||||
temporary directory. Instead, continue with default window decorations. (issue
|
||||
#436)
|
||||
|
||||
|
||||
## 1.6.4
|
||||
@@ -178,7 +890,7 @@ FlatLaf Change Log
|
||||
- Native window decorations (Windows 10 only):
|
||||
- Fixed occasional application crash in `flatlaf-windows.dll`. (issue #357)
|
||||
- When window is initially shown, fill background with window background color
|
||||
(instead of white), which avoids flickering in dark themes. (issue 339)
|
||||
(instead of white), which avoids flickering in dark themes. (issue #339)
|
||||
- When resizing a window at the right/bottom edge, then first fill the new
|
||||
space with the window background color (instead of black) before the layout
|
||||
is updated.
|
||||
|
||||
294
README.md
294
README.md
@@ -6,14 +6,19 @@ Swing desktop applications.
|
||||
|
||||
It looks almost flat (no shadows or gradients), clean, simple and elegant.
|
||||
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
|
||||
IntelliJ IDEA 2019.2+ and uses almost the same colors and icons.
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

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

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

|
||||
|
||||
|
||||
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>
|
||||
|
||||
[Become a Sponsor](https://www.formdev.com/flatlaf/sponsor/)
|
||||
|
||||
Demo
|
||||
----
|
||||
|
||||
@@ -46,10 +62,15 @@ build script:
|
||||
artifactId: flatlaf
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
@@ -74,6 +95,8 @@ Addons
|
||||
- [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
|
||||
@@ -99,14 +122,26 @@ For more information and documentation visit
|
||||
- [Customizing](https://www.formdev.com/flatlaf/customizing/)
|
||||
- [How to Customize](https://www.formdev.com/flatlaf/how-to-customize/)
|
||||
- [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/)
|
||||
- [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
|
||||
----
|
||||
|
||||
- [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 announcement on Reddit](https://www.reddit.com/r/java/comments/dl0hu3/flatlaf_flat_look_and_feel/)
|
||||
|
||||
@@ -114,89 +149,196 @@ Buzz
|
||||
Applications using FlatLaf
|
||||
--------------------------
|
||||
|
||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
||||
and much more
|
||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
||||
- [KeyStore Explorer](https://keystore-explorer.org/) 5.4.3
|
||||
- 
|
||||
### Featured
|
||||
|
||||
-  [JFormDesigner](https://www.formdev.com/)
|
||||
(**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)
|
||||
9.0 (**commercial**) - the powerful multi-platform Java installer builder
|
||||
-  [DbVisualizer](https://www.dbvis.com/) 12.0
|
||||
(**commercial**) - the powerful multi-platform Java installer builder
|
||||
-  [DbVisualizer](https://www.dbvis.com/)
|
||||
(**commercial**) - the universal database tool for developers, analysts and
|
||||
DBAs
|
||||
-  [MagicPlot](https://magicplot.com/) 3.0
|
||||
(**commercial**) - Software for nonlinear fitting, plotting and data analysis
|
||||
- 
|
||||
[Thermo-Calc](https://thermocalc.com/products/thermo-calc/) 2021a
|
||||
(**commercial**) - Thermodynamics and Properties Software
|
||||
- [OWASP ZAP](https://www.zaproxy.org/) 2.10 - the worlds most widely used web
|
||||
app scanner
|
||||
-  [Apache NetBeans](https://netbeans.apache.org/) - IDE
|
||||
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
|
||||
|
||||
### 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)
|
||||
2020.11.2 (**commercial**) - the leading software for web security testing
|
||||
(**commercial**) - the leading software for web security testing
|
||||
- 
|
||||
[BurpCustomizer](https://github.com/CoreyD97/BurpCustomizer) - adds more
|
||||
[Ghidra](https://github.com/NationalSecurityAgency/ghidra) - a software
|
||||
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
|
||||
- [JOSM](https://josm.openstreetmap.de/) - an extensible editor for
|
||||
[OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf JOSM plugin)
|
||||
- [jAlbum](https://jalbum.net/) 21 (**commercial**) - creates photo album
|
||||
websites
|
||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
||||
checks your website
|
||||
- [j-lawyer](https://github.com/jlawyerorg/j-lawyer-org) - Kanzleisoftware
|
||||
- [MegaMek](https://github.com/MegaMek/megamek) v0.47.4 and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) v0.47.5 - a turn-based sci-fi board
|
||||
game
|
||||
- [GUIslice Builder](https://github.com/ImpulseAdventure/GUIslice-Builder)
|
||||
0.13.b024 - GUI builder for
|
||||
[GUIslice](https://github.com/ImpulseAdventure/GUIslice), a lightweight GUI
|
||||
framework for embedded displays
|
||||
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
||||
gamepad mapping software
|
||||
- [SpringRemote](https://github.com/HaleyWang/SpringRemote) - remote Linux SSH
|
||||
connections manager
|
||||
- [jEnTunnel](https://github.com/ggrandes/jentunnel) - manage SSH Tunnels made
|
||||
easy
|
||||
- [Total Validator](https://www.totalvalidator.com/) (**commercial**) - checks
|
||||
your website
|
||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||
encryption
|
||||
|
||||
### Software Development
|
||||
|
||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib)
|
||||
- [KeyStore Explorer](https://keystore-explorer.org/)
|
||||
- 
|
||||
[muCommander](https://github.com/mucommander/mucommander) - lightweight
|
||||
cross-platform file manager
|
||||
-  [Guiffy](https://www.guiffy.com/) (**commercial**) -
|
||||
advanced cross-platform Diff/Merge
|
||||
-  [HashGarten](https://github.com/jonelo/HashGarten) -
|
||||
cross-platform Swing GUI for Jacksum
|
||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
||||
IDE for Pseudo-Assembler
|
||||
- [Linotte](https://github.com/cpc6128/LangageLinotte) - French programming
|
||||
language created to learn programming
|
||||
- [lsfusion platform](https://github.com/lsfusion/platform) - information
|
||||
systems development platform
|
||||
|
||||
### 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
|
||||
- [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
|
||||
- [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
|
||||
|
||||
### Modelling
|
||||
|
||||
-  [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
|
||||
|
||||
### 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
|
||||
|
||||
- 
|
||||
[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/),
|
||||
[AS4](https://sourceforge.net/projects/mendelson-as4/) and
|
||||
[OFTP2](https://sourceforge.net/projects/mendelson-oftp2/) (open-source) and
|
||||
[mendelson AS2](https://mendelson-e-c.com/as2/),
|
||||
[AS4](https://mendelson-e-c.com/as4/) and
|
||||
[OFTP2](https://mendelson-e-c.com/oftp2) (**commercial**)
|
||||
-  [IGMAS+](https://www.gfz-potsdam.de/igmas) -
|
||||
Interactive Gravity and Magnetic Application System
|
||||
- [MeteoInfo](https://github.com/meteoinfo/MeteoInfo) 2.2 - GIS and scientific
|
||||
computation environment for meteorological community
|
||||
- [lsfusion platform](https://github.com/lsfusion/platform) 4 - information
|
||||
systems development platform
|
||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||
encryption
|
||||
- [Jes - Die Java-E<>R](https://www.jes-eur.de)
|
||||
- [Mapton](https://mapton.org/) 2.0
|
||||
([source code](https://github.com/trixon/mapton)) - some kind of map
|
||||
application (based on NetBeans platform)
|
||||
- [Pseudo Assembler IDE](https://github.com/tomasz-herman/PseudoAssemblerIDE) -
|
||||
IDE for Pseudo-Assembler
|
||||
- [Linotte](https://github.com/cpc6128/LangageLinotte) 3.1 - French programming
|
||||
language created to learn programming
|
||||
- [MEKA](https://github.com/Waikato/meka) 1.9.3 - multi-label classifiers and
|
||||
evaluation procedures using the Weka machine learning framework
|
||||
- [Shutter Encoder](https://www.shutterencoder.com/) 14.2
|
||||
([source code](https://github.com/paulpacifico/shutter-encoder)) -
|
||||
professional video converter and compression tool (screenshots show **old**
|
||||
look)
|
||||
- [Sound Analysis](https://github.com/tomasz-herman/SoundAnalysis) - analyze
|
||||
sound files in time or frequency domain
|
||||
- [RemoteLight](https://github.com/Drumber/RemoteLight) - multifunctional LED
|
||||
control software
|
||||
- [ThunderFocus](https://github.com/marcocipriani01/ThunderFocus) -
|
||||
Arduino-based telescope focuser
|
||||
- [Novel-Grabber](https://github.com/Flameish/Novel-Grabber) - download novels
|
||||
from any webnovel and lightnovel site
|
||||
- [lectureStudio](https://www.lecturestudio.org/) 4.3.1060 - digitize your
|
||||
lectures with ease
|
||||
|
||||
### Messaging
|
||||
|
||||
-  [Spark](https://github.com/igniterealtime/Spark) -
|
||||
cross-platform IM client optimized for businesses and organizations
|
||||
-  [Chatty](https://github.com/chatty/chatty) - Twitch
|
||||
Chat Client
|
||||
|
||||
### Gaming
|
||||
|
||||
-  
|
||||
[BGBlitz](https://www.bgblitz.com/) (**commercial**) - professional Backgammon
|
||||
-  [MCreator](https://github.com/MCreator/MCreator) -
|
||||
software used to make Minecraft Java Edition mods, Minecraft Bedrock Edition Add-Ons,
|
||||
and data packs without programming knowledge
|
||||
-  [MapTool](https://github.com/RPTools/maptool) - virtual
|
||||
Tabletop for playing role-playing games
|
||||
- [MegaMek](https://github.com/MegaMek/megamek),
|
||||
[MegaMekLab](https://github.com/MegaMek/megameklab) and
|
||||
[MekHQ](https://github.com/MegaMek/mekhq) - a sci-fi tabletop BattleTech
|
||||
simulator suite handling battles, unit building, and campaigns
|
||||
- [ControllerBuddy](https://github.com/bwRavencl/ControllerBuddy) - advanced
|
||||
gamepad mapping software
|
||||
|
||||
### Utilities
|
||||
|
||||
- [MooInfo](https://github.com/rememberber/MooInfo) - visual implementation of
|
||||
OSHI, to view information about the system and hardware
|
||||
- 
|
||||
[Linux Task Manager (LTM)](https://github.com/ajee10x/LTM-LinuxTaskManager) -
|
||||
GUI for monitoring and managing various aspects of a Linux system
|
||||
- [Rest Suite](https://github.com/supanadit/restsuite) - Rest API testing
|
||||
- [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
|
||||
and fastboot commands easier to use
|
||||
- and more...
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- [MEKA](https://github.com/Waikato/meka) - multi-label classifiers and
|
||||
evaluation procedures using the Weka machine learning framework
|
||||
|
||||
@@ -14,10 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "1.6.4"
|
||||
val developmentVersion = "2.0-SNAPSHOT"
|
||||
import net.ltgt.gradle.errorprone.errorprone
|
||||
|
||||
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 {
|
||||
version = rootProject.version
|
||||
@@ -37,9 +42,16 @@ println( "----------------------------------------------------------------------
|
||||
println( "FlatLaf Version: ${version}" )
|
||||
println( "Gradle ${gradle.gradleVersion} at ${gradle.gradleHomeDir}" )
|
||||
println( "Java ${System.getProperty( "java.version" )}" )
|
||||
val toolchainJavaVersion = System.getProperty( "toolchain" )
|
||||
if( !toolchainJavaVersion.isNullOrEmpty() )
|
||||
println( "Java toolchain ${toolchainJavaVersion}" )
|
||||
println()
|
||||
|
||||
|
||||
plugins {
|
||||
alias( libs.plugins.errorprone ) apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
tasks {
|
||||
withType<JavaCompile>().configureEach {
|
||||
@@ -78,4 +90,56 @@ allprojects {
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ReorderJarEntries
|
||||
// 1st pass: copy .properties files
|
||||
copyFiles( zipOutStream, jarFile, name -> name.endsWith( ".properties" ) );
|
||||
|
||||
// 2st pass: copy other files
|
||||
// 2nd pass: copy other files
|
||||
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 {
|
||||
add( "java9Compile", sourceSets.main.get().output )
|
||||
add( "java9Implementation", sourceSets.main.get().output )
|
||||
}
|
||||
|
||||
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 {
|
||||
manifest.attributes( "Multi-Release" to "true" )
|
||||
|
||||
into( "META-INF/versions/9" ) {
|
||||
from( sourceSets["module-info"].output ) {
|
||||
include( "module-info.class" )
|
||||
}
|
||||
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 {
|
||||
var artifactId: String? = null
|
||||
var name: String? = null
|
||||
var description: String? = null
|
||||
var nativeArtifacts: List<NativeArtifact>? = null
|
||||
}
|
||||
|
||||
val extension = project.extensions.create<PublishExtension>( "flatlafPublish" )
|
||||
@@ -41,34 +44,43 @@ publishing {
|
||||
|
||||
pom {
|
||||
afterEvaluate {
|
||||
this@pom.name.set( extension.name )
|
||||
this@pom.description.set( extension.description )
|
||||
this@pom.name = extension.name
|
||||
this@pom.description = extension.description
|
||||
}
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
||||
url = "https://github.com/JFormDesigner/FlatLaf"
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name.set( "The Apache License, Version 2.0" )
|
||||
url.set( "https://www.apache.org/licenses/LICENSE-2.0.txt" )
|
||||
name = "The Apache License, Version 2.0"
|
||||
url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
name.set( "Karl Tauber" )
|
||||
organization.set( "FormDev Software GmbH" )
|
||||
organizationUrl.set( "https://www.formdev.com/" )
|
||||
name = "Karl Tauber"
|
||||
organization = "FormDev Software GmbH"
|
||||
organizationUrl = "https://www.formdev.com/"
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
connection.set( "scm:git:git://github.com/JFormDesigner/FlatLaf.git" )
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf" )
|
||||
connection = "scm:git:git://github.com/JFormDesigner/FlatLaf.git"
|
||||
url = "https://github.com/JFormDesigner/FlatLaf"
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system.set( "GitHub" )
|
||||
url.set( "https://github.com/JFormDesigner/FlatLaf/issues" )
|
||||
system = "GitHub"
|
||||
url = "https://github.com/JFormDesigner/FlatLaf/issues"
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
extension.nativeArtifacts?.forEach {
|
||||
artifact( artifacts.add( "archives", file( it.fileName ) ) {
|
||||
classifier = it.classifier
|
||||
type = it.type
|
||||
} )
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +92,7 @@ publishing {
|
||||
|
||||
val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||
val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
url = uri( if( java.lang.Boolean.getBoolean( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||
url = uri( if( rootProject.hasProperty( "release" ) ) releasesRepoUrl else snapshotsRepoUrl )
|
||||
|
||||
credentials {
|
||||
// get from gradle.properties
|
||||
@@ -108,5 +120,13 @@ signing {
|
||||
|
||||
// disable signing of snapshots
|
||||
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 )
|
||||
}
|
||||
}
|
||||
2151
compare1.txt
2151
compare1.txt
File diff suppressed because it is too large
Load Diff
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
|
||||
@@ -14,8 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Flatlaf_publish_gradle.NativeArtifact
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`flatlaf-toolchain`
|
||||
`flatlaf-module-info`
|
||||
`flatlaf-java9`
|
||||
`flatlaf-publish`
|
||||
@@ -24,12 +27,11 @@ plugins {
|
||||
val sigtest = configurations.create( "sigtest" )
|
||||
|
||||
dependencies {
|
||||
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
|
||||
testImplementation( "org.junit.jupiter:junit-jupiter-params" )
|
||||
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
|
||||
testImplementation( libs.junit )
|
||||
testRuntimeOnly( libs.junit.launcher )
|
||||
|
||||
// https://github.com/jtulach/netbeans-apitest
|
||||
sigtest( "org.netbeans.tools:sigtest-maven-plugin:1.4" )
|
||||
sigtest( libs.sigtest )
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -40,16 +42,11 @@ java {
|
||||
tasks {
|
||||
compileJava {
|
||||
// generate JNI headers
|
||||
options.headerOutputDirectory.set( buildDir.resolve( "generated/jni-headers" ) )
|
||||
}
|
||||
|
||||
processResources {
|
||||
// build native libraries
|
||||
dependsOn( ":flatlaf-natives-windows:assemble" )
|
||||
options.headerOutputDirectory = layout.buildDirectory.dir( "generated/jni-headers" )
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
archiveBaseName = "flatlaf"
|
||||
|
||||
doLast {
|
||||
ReorderJarEntries.reorderJarEntries( outputs.files.singleFile );
|
||||
@@ -57,11 +54,32 @@ tasks {
|
||||
}
|
||||
|
||||
named<Jar>( "sourcesJar" ) {
|
||||
archiveBaseName.set( "flatlaf" )
|
||||
archiveBaseName = "flatlaf"
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -71,6 +89,9 @@ tasks {
|
||||
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" ) {
|
||||
@@ -88,7 +109,7 @@ tasks {
|
||||
"action" to "generate",
|
||||
"fileName" to "${project.name}-sigtest.txt",
|
||||
"classpath" to jar.get().outputs.files.asPath,
|
||||
"packages" to "com.formdev.flatlaf,com.formdev.flatlaf.util",
|
||||
"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" )
|
||||
@@ -124,4 +145,16 @@ flatlafPublish {
|
||||
artifactId = "flatlaf"
|
||||
name = "FlatLaf"
|
||||
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" ),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#Signature file v4.1
|
||||
#Version 1.6
|
||||
#Version 3.5
|
||||
|
||||
CLSS public abstract interface com.formdev.flatlaf.FlatClientProperties
|
||||
fld public final static java.lang.String BUTTON_TYPE = "JButton.buttonType"
|
||||
@@ -11,6 +11,14 @@ fld public final static java.lang.String BUTTON_TYPE_TAB = "tab"
|
||||
fld public final static java.lang.String BUTTON_TYPE_TOOLBAR_BUTTON = "toolBarButton"
|
||||
fld public final static java.lang.String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner"
|
||||
fld public final static java.lang.String COMPONENT_ROUND_RECT = "JComponent.roundRect"
|
||||
fld public final static java.lang.String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption"
|
||||
fld public final static java.lang.String FULL_WINDOW_CONTENT = "FlatLaf.fullWindowContent"
|
||||
fld public final static java.lang.String FULL_WINDOW_CONTENT_BUTTONS_BOUNDS = "FlatLaf.fullWindowContent.buttonsBounds"
|
||||
fld public final static java.lang.String FULL_WINDOW_CONTENT_BUTTONS_PLACEHOLDER = "FlatLaf.fullWindowContent.buttonsPlaceholder"
|
||||
fld public final static java.lang.String GLASS_PANE_FULL_HEIGHT = "JRootPane.glassPaneFullHeight"
|
||||
fld public final static java.lang.String MACOS_WINDOW_BUTTONS_SPACING = "FlatLaf.macOS.windowButtonsSpacing"
|
||||
fld public final static java.lang.String MACOS_WINDOW_BUTTONS_SPACING_LARGE = "large"
|
||||
fld public final static java.lang.String MACOS_WINDOW_BUTTONS_SPACING_MEDIUM = "medium"
|
||||
fld public final static java.lang.String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded"
|
||||
fld public final static java.lang.String MINIMUM_HEIGHT = "JComponent.minimumHeight"
|
||||
fld public final static java.lang.String MINIMUM_WIDTH = "JComponent.minimumWidth"
|
||||
@@ -18,8 +26,10 @@ fld public final static java.lang.String OUTLINE = "JComponent.outline"
|
||||
fld public final static java.lang.String OUTLINE_ERROR = "error"
|
||||
fld public final static java.lang.String OUTLINE_WARNING = "warning"
|
||||
fld public final static java.lang.String PLACEHOLDER_TEXT = "JTextField.placeholderText"
|
||||
fld public final static java.lang.String POPUP_BORDER_CORNER_RADIUS = "Popup.borderCornerRadius"
|
||||
fld public final static java.lang.String POPUP_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted"
|
||||
fld public final static java.lang.String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight"
|
||||
fld public final static java.lang.String POPUP_ROUNDED_BORDER_WIDTH = "Popup.roundedBorderWidth"
|
||||
fld public final static java.lang.String PROGRESS_BAR_LARGE_HEIGHT = "JProgressBar.largeHeight"
|
||||
fld public final static java.lang.String PROGRESS_BAR_SQUARE = "JProgressBar.square"
|
||||
fld public final static java.lang.String SCROLL_BAR_SHOW_BUTTONS = "JScrollBar.showButtons"
|
||||
@@ -30,7 +40,12 @@ fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY = "JTextFiel
|
||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ALWAYS = "always"
|
||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_NEVER = "never"
|
||||
fld public final static java.lang.String SELECT_ALL_ON_FOCUS_POLICY_ONCE = "once"
|
||||
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE = "JSplitPane.expandableSide"
|
||||
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_LEFT = "left"
|
||||
fld public final static java.lang.String SPLIT_PANE_EXPANDABLE_SIDE_RIGHT = "right"
|
||||
fld public final static java.lang.String SQUARE_SIZE = "JButton.squareSize"
|
||||
fld public final static java.lang.String STYLE = "FlatLaf.style"
|
||||
fld public final static java.lang.String STYLE_CLASS = "FlatLaf.styleClass"
|
||||
fld public final static java.lang.String TABBED_PANE_ALIGN_CENTER = "center"
|
||||
fld public final static java.lang.String TABBED_PANE_ALIGN_FILL = "fill"
|
||||
fld public final static java.lang.String TABBED_PANE_ALIGN_LEADING = "leading"
|
||||
@@ -59,6 +74,14 @@ fld public final static java.lang.String TABBED_PANE_TAB_CLOSE_TOOLTIPTEXT = "JT
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_ICON_PLACEMENT = "JTabbedPane.tabIconPlacement"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_INSETS = "JTabbedPane.tabInsets"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION = "JTabbedPane.tabRotation"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_AUTO = "auto"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_LEFT = "left"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_NONE = "none"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_ROTATION_RIGHT = "right"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_TYPE_CARD = "card"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE = "JTabbedPane.tabWidthMode"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_COMPACT = "compact"
|
||||
fld public final static java.lang.String TABBED_PANE_TAB_WIDTH_MODE_EQUAL = "equal"
|
||||
@@ -67,12 +90,27 @@ fld public final static java.lang.String TABBED_PANE_TRAILING_COMPONENT = "JTabb
|
||||
fld public final static java.lang.String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground"
|
||||
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_COLOR = "JToggleButton.tab.underlineColor"
|
||||
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_HEIGHT = "JToggleButton.tab.underlineHeight"
|
||||
fld public final static java.lang.String TAB_BUTTON_UNDERLINE_PLACEMENT = "JToggleButton.tab.underlinePlacement"
|
||||
fld public final static java.lang.String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback"
|
||||
fld public final static java.lang.String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent"
|
||||
fld public final static java.lang.String TEXT_FIELD_LEADING_ICON = "JTextField.leadingIcon"
|
||||
fld public final static java.lang.String TEXT_FIELD_PADDING = "JTextField.padding"
|
||||
fld public final static java.lang.String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton"
|
||||
fld public final static java.lang.String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent"
|
||||
fld public final static java.lang.String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon"
|
||||
fld public final static java.lang.String TITLE_BAR_BACKGROUND = "JRootPane.titleBarBackground"
|
||||
fld public final static java.lang.String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground"
|
||||
fld public final static java.lang.String TITLE_BAR_SHOW_CLOSE = "JRootPane.titleBarShowClose"
|
||||
fld public final static java.lang.String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon"
|
||||
fld public final static java.lang.String TITLE_BAR_SHOW_ICONIFFY = "JRootPane.titleBarShowIconify"
|
||||
fld public final static java.lang.String TITLE_BAR_SHOW_MAXIMIZE = "JRootPane.titleBarShowMaximize"
|
||||
fld public final static java.lang.String TITLE_BAR_SHOW_TITLE = "JRootPane.titleBarShowTitle"
|
||||
fld public final static java.lang.String TREE_PAINT_SELECTION = "JTree.paintSelection"
|
||||
fld public final static java.lang.String TREE_WIDE_SELECTION = "JTree.wideSelection"
|
||||
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations"
|
||||
fld public final static java.lang.String WINDOW_STYLE = "Window.style"
|
||||
fld public final static java.lang.String WINDOW_STYLE_SMALL = "small"
|
||||
meth public static <%0 extends java.lang.Object> {%%0} clientProperty(javax.swing.JComponent,java.lang.String,{%%0},java.lang.Class<{%%0}>)
|
||||
meth public static boolean clientPropertyBoolean(javax.swing.JComponent,java.lang.String,boolean)
|
||||
meth public static boolean clientPropertyEquals(javax.swing.JComponent,java.lang.String,java.lang.Object)
|
||||
meth public static int clientPropertyInt(javax.swing.JComponent,java.lang.String,int)
|
||||
@@ -165,8 +203,10 @@ meth public boolean isSupportedLookAndFeel()
|
||||
meth public final boolean equals(java.lang.Object)
|
||||
meth public final int hashCode()
|
||||
meth public java.lang.String getID()
|
||||
meth public java.util.Map<java.lang.String,java.lang.String> getExtraDefaults()
|
||||
meth public javax.swing.Icon getDisabledIcon(javax.swing.JComponent,javax.swing.Icon)
|
||||
meth public javax.swing.UIDefaults getDefaults()
|
||||
meth public static <%0 extends java.lang.Object> {%%0} getStyleableValue(javax.swing.JComponent,java.lang.String)
|
||||
meth public static boolean install(javax.swing.LookAndFeel)
|
||||
anno 0 java.lang.Deprecated()
|
||||
meth public static boolean isLafDark()
|
||||
@@ -174,6 +214,14 @@ meth public static boolean isShowMnemonics()
|
||||
meth public static boolean isUseNativeWindowDecorations()
|
||||
meth public static boolean setup(javax.swing.LookAndFeel)
|
||||
meth public static boolean supportsNativeWindowDecorations()
|
||||
meth public static java.lang.Object parseDefaultsValue(java.lang.String,java.lang.String,java.lang.Class<?>)
|
||||
meth public static java.lang.String getPreferredFontFamily()
|
||||
meth public static java.lang.String getPreferredLightFontFamily()
|
||||
meth public static java.lang.String getPreferredMonospacedFontFamily()
|
||||
meth public static java.lang.String getPreferredSemiboldFontFamily()
|
||||
meth public static java.util.Map<java.lang.String,java.lang.Class<?>> getStyleableInfos(javax.swing.JComponent)
|
||||
meth public static java.util.Map<java.lang.String,java.lang.String> getGlobalExtraDefaults()
|
||||
meth public static java.util.function.Function<java.lang.String,java.awt.Color> getSystemColorGetter()
|
||||
meth public static javax.swing.UIDefaults$ActiveValue createActiveFontValue(float)
|
||||
meth public static void hideMnemonics()
|
||||
meth public static void initIconColors(javax.swing.UIDefaults,boolean)
|
||||
@@ -181,22 +229,31 @@ meth public static void installLafInfo(java.lang.String,java.lang.Class<? extend
|
||||
meth public static void registerCustomDefaultsSource(java.io.File)
|
||||
meth public static void registerCustomDefaultsSource(java.lang.String)
|
||||
meth public static void registerCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
||||
meth public static void registerCustomDefaultsSource(java.net.URL)
|
||||
meth public static void repaintAllFramesAndDialogs()
|
||||
meth public static void revalidateAndRepaintAllFramesAndDialogs()
|
||||
meth public static void runWithUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>,java.lang.Runnable)
|
||||
meth public static void setGlobalExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
||||
meth public static void setPreferredFontFamily(java.lang.String)
|
||||
meth public static void setPreferredLightFontFamily(java.lang.String)
|
||||
meth public static void setPreferredMonospacedFontFamily(java.lang.String)
|
||||
meth public static void setPreferredSemiboldFontFamily(java.lang.String)
|
||||
meth public static void setSystemColorGetter(java.util.function.Function<java.lang.String,java.awt.Color>)
|
||||
meth public static void setUseNativeWindowDecorations(boolean)
|
||||
meth public static void showMnemonics(java.awt.Component)
|
||||
meth public static void unregisterCustomDefaultsSource(java.io.File)
|
||||
meth public static void unregisterCustomDefaultsSource(java.lang.String)
|
||||
meth public static void unregisterCustomDefaultsSource(java.lang.String,java.lang.ClassLoader)
|
||||
meth public static void unregisterCustomDefaultsSource(java.net.URL)
|
||||
meth public static void updateUI()
|
||||
meth public static void updateUILater()
|
||||
meth public void initialize()
|
||||
meth public void registerUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||
meth public void setExtraDefaults(java.util.Map<java.lang.String,java.lang.String>)
|
||||
meth public void uninitialize()
|
||||
meth public void unregisterUIDefaultsGetter(java.util.function.Function<java.lang.Object,java.lang.Object>)
|
||||
supr javax.swing.plaf.basic.BasicLookAndFeel
|
||||
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,mnemonicHandler,oldPopupFactory,postInitialization,uiDefaultsGetters,updateUIPending
|
||||
hfds DESKTOPFONTHINTS,aquaLoaded,customDefaultsSources,desktopPropertyListener,desktopPropertyName,desktopPropertyName2,extraDefaults,globalExtraDefaults,mnemonicHandler,oldPopupFactory,postInitialization,preferredFontFamily,preferredLightFontFamily,preferredMonospacedFontFamily,preferredSemiboldFontFamily,subMenuUsabilityHelperInstalled,systemColorGetter,uiDefaultsGetters,updateUIPending
|
||||
hcls ActiveFont,FlatUIDefaults,ImageIconUIResource
|
||||
|
||||
CLSS public abstract interface static com.formdev.flatlaf.FlatLaf$DisabledIconProvider
|
||||
@@ -231,10 +288,14 @@ hfds baseTheme,dark,name,properties
|
||||
CLSS public abstract interface com.formdev.flatlaf.FlatSystemProperties
|
||||
fld public final static java.lang.String ANIMATION = "flatlaf.animation"
|
||||
fld public final static java.lang.String MENUBAR_EMBEDDED = "flatlaf.menuBarEmbedded"
|
||||
fld public final static java.lang.String NATIVE_LIBRARY_PATH = "flatlaf.nativeLibraryPath"
|
||||
fld public final static java.lang.String UI_SCALE = "flatlaf.uiScale"
|
||||
fld public final static java.lang.String UI_SCALE_ALLOW_SCALE_DOWN = "flatlaf.uiScale.allowScaleDown"
|
||||
fld public final static java.lang.String UI_SCALE_ENABLED = "flatlaf.uiScale.enabled"
|
||||
fld public final static java.lang.String UPDATE_UI_ON_SYSTEM_FONT_CHANGE = "flatlaf.updateUIOnSystemFontChange"
|
||||
fld public final static java.lang.String USE_JETBRAINS_CUSTOM_DECORATIONS = "flatlaf.useJetBrainsCustomDecorations"
|
||||
anno 0 java.lang.Deprecated()
|
||||
fld public final static java.lang.String USE_NATIVE_LIBRARY = "flatlaf.useNativeLibrary"
|
||||
fld public final static java.lang.String USE_TEXT_Y_CORRECTION = "flatlaf.useTextYCorrection"
|
||||
fld public final static java.lang.String USE_UBUNTU_FONT = "flatlaf.useUbuntuFont"
|
||||
fld public final static java.lang.String USE_WINDOW_DECORATIONS = "flatlaf.useWindowDecorations"
|
||||
@@ -253,7 +314,7 @@ meth public static boolean setup(java.io.InputStream)
|
||||
meth public static com.formdev.flatlaf.FlatLaf createLaf(com.formdev.flatlaf.IntelliJTheme)
|
||||
meth public static com.formdev.flatlaf.FlatLaf createLaf(java.io.InputStream) throws java.io.IOException
|
||||
supr java.lang.Object
|
||||
hfds checkboxDuplicateColors,checkboxKeyMapping,colors,icons,isMaterialUILite,namedColors,ui,uiKeyCopying,uiKeyInverseMapping,uiKeyMapping
|
||||
hfds checkboxDuplicateColors,checkboxKeyMapping,colors,icons,isMaterialUILite,namedColors,ui,uiKeyCopying,uiKeyDoNotOverride,uiKeyExcludes,uiKeyInverseMapping,uiKeyMapping
|
||||
|
||||
CLSS public static com.formdev.flatlaf.IntelliJTheme$ThemeLaf
|
||||
outer com.formdev.flatlaf.IntelliJTheme
|
||||
@@ -266,6 +327,26 @@ meth public java.lang.String getName()
|
||||
supr com.formdev.flatlaf.FlatLaf
|
||||
hfds theme
|
||||
|
||||
CLSS public com.formdev.flatlaf.themes.FlatMacDarkLaf
|
||||
cons public init()
|
||||
fld public final static java.lang.String NAME = "FlatLaf macOS Dark"
|
||||
meth public boolean isDark()
|
||||
meth public java.lang.String getDescription()
|
||||
meth public java.lang.String getName()
|
||||
meth public static boolean setup()
|
||||
meth public static void installLafInfo()
|
||||
supr com.formdev.flatlaf.FlatDarkLaf
|
||||
|
||||
CLSS public com.formdev.flatlaf.themes.FlatMacLightLaf
|
||||
cons public init()
|
||||
fld public final static java.lang.String NAME = "FlatLaf macOS Light"
|
||||
meth public boolean isDark()
|
||||
meth public java.lang.String getDescription()
|
||||
meth public java.lang.String getName()
|
||||
meth public static boolean setup()
|
||||
meth public static void installLafInfo()
|
||||
supr com.formdev.flatlaf.FlatLightLaf
|
||||
|
||||
CLSS public abstract interface com.formdev.flatlaf.util.AnimatedIcon
|
||||
innr public static AnimationSupport
|
||||
intf javax.swing.Icon
|
||||
@@ -330,7 +411,16 @@ innr public static HSLIncreaseDecrease
|
||||
innr public static Mix
|
||||
meth public !varargs static java.awt.Color applyFunctions(java.awt.Color,com.formdev.flatlaf.util.ColorFunctions$ColorFunction[])
|
||||
meth public static float clamp(float)
|
||||
meth public static float luma(java.awt.Color)
|
||||
meth public static java.awt.Color darken(java.awt.Color,float)
|
||||
meth public static java.awt.Color desaturate(java.awt.Color,float)
|
||||
meth public static java.awt.Color fade(java.awt.Color,float)
|
||||
meth public static java.awt.Color lighten(java.awt.Color,float)
|
||||
meth public static java.awt.Color mix(java.awt.Color,java.awt.Color,float)
|
||||
meth public static java.awt.Color saturate(java.awt.Color,float)
|
||||
meth public static java.awt.Color shade(java.awt.Color,float)
|
||||
meth public static java.awt.Color spin(java.awt.Color,float)
|
||||
meth public static java.awt.Color tint(java.awt.Color,float)
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public abstract interface static com.formdev.flatlaf.util.ColorFunctions$ColorFunction
|
||||
@@ -400,6 +490,17 @@ meth public java.lang.String toString()
|
||||
supr javax.swing.plaf.ColorUIResource
|
||||
hfds baseOfDefaultColorRGB,functions,hasBaseOfDefaultColor
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.FontUtils
|
||||
cons public init()
|
||||
meth public static boolean installFont(java.net.URL)
|
||||
meth public static java.awt.Font getCompositeFont(java.lang.String,int,int)
|
||||
meth public static java.awt.Font[] getAllFonts()
|
||||
meth public static java.lang.String[] getAvailableFontFamilyNames()
|
||||
meth public static void loadFontFamily(java.lang.String)
|
||||
meth public static void registerFontFamilyLoader(java.lang.String,java.lang.Runnable)
|
||||
supr java.lang.Object
|
||||
hfds loadersMap
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.Graphics2DProxy
|
||||
cons public init(java.awt.Graphics2D)
|
||||
meth public boolean drawImage(java.awt.Image,int,int,int,int,int,int,int,int,java.awt.Color,java.awt.image.ImageObserver)
|
||||
@@ -528,15 +629,32 @@ hfds alpha,hsl,rgb
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.HiDPIUtils
|
||||
cons public init()
|
||||
innr public abstract interface static DirtyRegionCallback
|
||||
innr public abstract interface static Painter
|
||||
innr public static HiDPIRepaintManager
|
||||
meth public static float computeTextYCorrection(java.awt.Graphics2D)
|
||||
meth public static java.awt.Graphics2D createGraphicsTextYCorrection(java.awt.Graphics2D)
|
||||
meth public static void addDirtyRegion(javax.swing.JComponent,int,int,int,int,com.formdev.flatlaf.util.HiDPIUtils$DirtyRegionCallback)
|
||||
meth public static void drawStringUnderlineCharAtWithYCorrection(javax.swing.JComponent,java.awt.Graphics2D,java.lang.String,int,int,int)
|
||||
meth public static void drawStringWithYCorrection(javax.swing.JComponent,java.awt.Graphics2D,java.lang.String,int,int)
|
||||
meth public static void installHiDPIRepaintManager()
|
||||
meth public static void paintAtScale1x(java.awt.Graphics2D,int,int,int,int,com.formdev.flatlaf.util.HiDPIUtils$Painter)
|
||||
meth public static void paintAtScale1x(java.awt.Graphics2D,javax.swing.JComponent,com.formdev.flatlaf.util.HiDPIUtils$Painter)
|
||||
meth public static void repaint(java.awt.Component)
|
||||
meth public static void repaint(java.awt.Component,int,int,int,int)
|
||||
meth public static void repaint(java.awt.Component,java.awt.Rectangle)
|
||||
supr java.lang.Object
|
||||
hfds useTextYCorrection
|
||||
hfds CORRECTION_INTER,CORRECTION_OPEN_SANS,CORRECTION_SEGOE_UI,CORRECTION_TAHOMA,SCALE_FACTORS,useDebugScaleFactor,useTextYCorrection
|
||||
|
||||
CLSS public abstract interface static com.formdev.flatlaf.util.HiDPIUtils$DirtyRegionCallback
|
||||
outer com.formdev.flatlaf.util.HiDPIUtils
|
||||
meth public abstract void addDirtyRegion(javax.swing.JComponent,int,int,int,int)
|
||||
|
||||
CLSS public static com.formdev.flatlaf.util.HiDPIUtils$HiDPIRepaintManager
|
||||
outer com.formdev.flatlaf.util.HiDPIUtils
|
||||
cons public init()
|
||||
meth public void addDirtyRegion(javax.swing.JComponent,int,int,int,int)
|
||||
supr javax.swing.RepaintManager
|
||||
|
||||
CLSS public abstract interface static com.formdev.flatlaf.util.HiDPIUtils$Painter
|
||||
outer com.formdev.flatlaf.util.HiDPIUtils
|
||||
@@ -566,6 +684,8 @@ meth public static java.util.List<java.awt.Image> getResolutionVariants(java.awt
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.NativeLibrary
|
||||
cons public init(java.io.File,boolean)
|
||||
cons public init(java.lang.String,boolean)
|
||||
cons public init(java.lang.String,java.lang.ClassLoader,boolean)
|
||||
meth public boolean isLoaded()
|
||||
supr java.lang.Object
|
||||
@@ -589,23 +709,59 @@ meth public void paintIcon(java.awt.Component,java.awt.Graphics,int,int)
|
||||
supr java.lang.Object
|
||||
hfds iconHeight,iconWidth,imageIcon,lastImage,lastSystemScaleFactor,lastUserScaleFactor
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.SoftCache<%0 extends java.lang.Object, %1 extends java.lang.Object>
|
||||
cons public init()
|
||||
cons public init(int)
|
||||
intf java.util.Map<{com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1}>
|
||||
meth public boolean containsKey(java.lang.Object)
|
||||
meth public boolean containsValue(java.lang.Object)
|
||||
meth public boolean isEmpty()
|
||||
meth public int size()
|
||||
meth public java.util.Collection<{com.formdev.flatlaf.util.SoftCache%1}> values()
|
||||
meth public java.util.Set<java.util.Map$Entry<{com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1}>> entrySet()
|
||||
meth public java.util.Set<{com.formdev.flatlaf.util.SoftCache%0}> keySet()
|
||||
meth public void clear()
|
||||
meth public void forEach(java.util.function.BiConsumer<? super {com.formdev.flatlaf.util.SoftCache%0},? super {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||
meth public void putAll(java.util.Map<? extends {com.formdev.flatlaf.util.SoftCache%0},? extends {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||
meth public void replaceAll(java.util.function.BiFunction<? super {com.formdev.flatlaf.util.SoftCache%0},? super {com.formdev.flatlaf.util.SoftCache%1},? extends {com.formdev.flatlaf.util.SoftCache%1}>)
|
||||
meth public {com.formdev.flatlaf.util.SoftCache%1} get(java.lang.Object)
|
||||
meth public {com.formdev.flatlaf.util.SoftCache%1} put({com.formdev.flatlaf.util.SoftCache%0},{com.formdev.flatlaf.util.SoftCache%1})
|
||||
meth public {com.formdev.flatlaf.util.SoftCache%1} remove(java.lang.Object)
|
||||
supr java.lang.Object
|
||||
hfds map,queue
|
||||
hcls CacheReference
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.StringUtils
|
||||
cons public init()
|
||||
meth public static boolean isEmpty(java.lang.String)
|
||||
meth public static boolean isTrimmedEmpty(java.lang.String)
|
||||
meth public static java.lang.String removeLeading(java.lang.String,java.lang.String)
|
||||
meth public static java.lang.String removeTrailing(java.lang.String,java.lang.String)
|
||||
meth public static java.lang.String substringTrimmed(java.lang.String,int)
|
||||
meth public static java.lang.String substringTrimmed(java.lang.String,int,int)
|
||||
meth public static java.util.List<java.lang.String> split(java.lang.String,char)
|
||||
meth public static java.util.List<java.lang.String> split(java.lang.String,char,boolean,boolean)
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.SwingUtils
|
||||
cons public init()
|
||||
meth public static <%0 extends java.awt.Component> {%%0} getComponentByName(java.awt.Container,java.lang.String)
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public com.formdev.flatlaf.util.SystemInfo
|
||||
cons public init()
|
||||
fld public final static boolean isAARCH64
|
||||
fld public final static boolean isJava_11_orLater
|
||||
fld public final static boolean isJava_12_orLater
|
||||
fld public final static boolean isJava_15_orLater
|
||||
fld public final static boolean isJava_17_orLater
|
||||
fld public final static boolean isJava_18_orLater
|
||||
fld public final static boolean isJava_9_orLater
|
||||
fld public final static boolean isJetBrainsJVM
|
||||
fld public final static boolean isJetBrainsJVM_11_orLater
|
||||
fld public final static boolean isKDE
|
||||
fld public final static boolean isLinux
|
||||
fld public final static boolean isMacFullWindowContentSupported
|
||||
fld public final static boolean isMacOS
|
||||
fld public final static boolean isMacOS_10_11_ElCapitan_orLater
|
||||
fld public final static boolean isMacOS_10_14_Mojave_orLater
|
||||
@@ -615,6 +771,8 @@ fld public final static boolean isWebswing
|
||||
fld public final static boolean isWinPE
|
||||
fld public final static boolean isWindows
|
||||
fld public final static boolean isWindows_10_orLater
|
||||
fld public final static boolean isWindows_11_orLater
|
||||
fld public final static boolean isX86
|
||||
fld public final static boolean isX86_64
|
||||
fld public final static long javaVersion
|
||||
fld public final static long osVersion
|
||||
@@ -627,6 +785,7 @@ cons public init()
|
||||
meth public static boolean isSystemScalingEnabled()
|
||||
meth public static double getSystemScaleFactor(java.awt.Graphics2D)
|
||||
meth public static double getSystemScaleFactor(java.awt.GraphicsConfiguration)
|
||||
meth public static float computeFontScaleFactor(java.awt.Font)
|
||||
meth public static float getUserScaleFactor()
|
||||
meth public static float scale(float)
|
||||
meth public static float unscale(float)
|
||||
@@ -933,6 +1092,34 @@ CLSS public abstract interface !annotation java.lang.annotation.Target
|
||||
intf java.lang.annotation.Annotation
|
||||
meth public abstract java.lang.annotation.ElementType[] value()
|
||||
|
||||
CLSS public abstract interface java.util.Map<%0 extends java.lang.Object, %1 extends java.lang.Object>
|
||||
innr public abstract interface static Entry
|
||||
meth public abstract boolean containsKey(java.lang.Object)
|
||||
meth public abstract boolean containsValue(java.lang.Object)
|
||||
meth public abstract boolean equals(java.lang.Object)
|
||||
meth public abstract boolean isEmpty()
|
||||
meth public abstract int hashCode()
|
||||
meth public abstract int size()
|
||||
meth public abstract java.util.Collection<{java.util.Map%1}> values()
|
||||
meth public abstract java.util.Set<java.util.Map$Entry<{java.util.Map%0},{java.util.Map%1}>> entrySet()
|
||||
meth public abstract java.util.Set<{java.util.Map%0}> keySet()
|
||||
meth public abstract void clear()
|
||||
meth public abstract void putAll(java.util.Map<? extends {java.util.Map%0},? extends {java.util.Map%1}>)
|
||||
meth public abstract {java.util.Map%1} get(java.lang.Object)
|
||||
meth public abstract {java.util.Map%1} put({java.util.Map%0},{java.util.Map%1})
|
||||
meth public abstract {java.util.Map%1} remove(java.lang.Object)
|
||||
meth public boolean remove(java.lang.Object,java.lang.Object)
|
||||
meth public boolean replace({java.util.Map%0},{java.util.Map%1},{java.util.Map%1})
|
||||
meth public void forEach(java.util.function.BiConsumer<? super {java.util.Map%0},? super {java.util.Map%1}>)
|
||||
meth public void replaceAll(java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} compute({java.util.Map%0},java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} computeIfAbsent({java.util.Map%0},java.util.function.Function<? super {java.util.Map%0},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} computeIfPresent({java.util.Map%0},java.util.function.BiFunction<? super {java.util.Map%0},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} getOrDefault(java.lang.Object,{java.util.Map%1})
|
||||
meth public {java.util.Map%1} merge({java.util.Map%0},{java.util.Map%1},java.util.function.BiFunction<? super {java.util.Map%1},? super {java.util.Map%1},? extends {java.util.Map%1}>)
|
||||
meth public {java.util.Map%1} putIfAbsent({java.util.Map%0},{java.util.Map%1})
|
||||
meth public {java.util.Map%1} replace({java.util.Map%0},{java.util.Map%1})
|
||||
|
||||
CLSS public abstract interface javax.swing.Icon
|
||||
meth public abstract int getIconHeight()
|
||||
meth public abstract int getIconWidth()
|
||||
@@ -967,6 +1154,31 @@ meth public void provideErrorFeedback(java.awt.Component)
|
||||
meth public void uninitialize()
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public javax.swing.RepaintManager
|
||||
cons public init()
|
||||
meth public boolean isCompletelyDirty(javax.swing.JComponent)
|
||||
meth public boolean isDoubleBufferingEnabled()
|
||||
meth public java.awt.Dimension getDoubleBufferMaximumSize()
|
||||
meth public java.awt.Image getOffscreenBuffer(java.awt.Component,int,int)
|
||||
meth public java.awt.Image getVolatileOffscreenBuffer(java.awt.Component,int,int)
|
||||
meth public java.awt.Rectangle getDirtyRegion(javax.swing.JComponent)
|
||||
meth public java.lang.String toString()
|
||||
meth public static javax.swing.RepaintManager currentManager(java.awt.Component)
|
||||
meth public static javax.swing.RepaintManager currentManager(javax.swing.JComponent)
|
||||
meth public static void setCurrentManager(javax.swing.RepaintManager)
|
||||
meth public void addDirtyRegion(java.applet.Applet,int,int,int,int)
|
||||
meth public void addDirtyRegion(java.awt.Window,int,int,int,int)
|
||||
meth public void addDirtyRegion(javax.swing.JComponent,int,int,int,int)
|
||||
meth public void addInvalidComponent(javax.swing.JComponent)
|
||||
meth public void markCompletelyClean(javax.swing.JComponent)
|
||||
meth public void markCompletelyDirty(javax.swing.JComponent)
|
||||
meth public void paintDirtyRegions()
|
||||
meth public void removeInvalidComponent(javax.swing.JComponent)
|
||||
meth public void setDoubleBufferMaximumSize(java.awt.Dimension)
|
||||
meth public void setDoubleBufferingEnabled(boolean)
|
||||
meth public void validateInvalidComponents()
|
||||
supr java.lang.Object
|
||||
|
||||
CLSS public abstract javax.swing.border.AbstractBorder
|
||||
cons public init()
|
||||
intf java.io.Serializable
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.IllegalComponentStateException;
|
||||
import java.awt.Window;
|
||||
import java.util.Objects;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingConstants;
|
||||
@@ -31,7 +33,7 @@ public interface FlatClientProperties
|
||||
//---- JButton ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies type of a button.
|
||||
* Specifies type of button.
|
||||
* <p>
|
||||
* <strong>Components</strong> {@link javax.swing.JButton} and {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
@@ -100,6 +102,17 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
@@ -116,13 +129,6 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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 ---------------------------------------------------------
|
||||
|
||||
@@ -253,8 +259,157 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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 --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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
|
||||
* or if the component is the owner of another component that is shown in a popup.
|
||||
@@ -273,6 +428,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String POPUP_FORCE_HEAVY_WEIGHT = "Popup.forceHeavyWeight";
|
||||
|
||||
|
||||
//---- JProgressBar -------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -291,6 +447,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
||||
|
||||
|
||||
//---- JRootPane ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -331,9 +488,49 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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>
|
||||
* <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).
|
||||
* (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.
|
||||
@@ -349,6 +546,62 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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>
|
||||
* <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>
|
||||
* <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>
|
||||
* <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>
|
||||
* <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).
|
||||
* <p>
|
||||
@@ -373,6 +626,48 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TITLE_BAR_FOREGROUND = "JRootPane.titleBarForeground";
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* <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 -------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -391,6 +686,42 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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 --------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -656,7 +987,7 @@ public interface FlatClientProperties
|
||||
* <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#LEADING} (default)
|
||||
* {@link SwingConstants#LEADING} (default),
|
||||
* {@link SwingConstants#TRAILING},
|
||||
* {@link SwingConstants#CENTER},
|
||||
* {@link #TABBED_PANE_ALIGN_LEADING} (default),
|
||||
@@ -760,12 +1091,65 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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.
|
||||
* <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>
|
||||
* 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.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
@@ -776,9 +1160,9 @@ public interface FlatClientProperties
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
||||
* <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>
|
||||
* 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).
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
@@ -786,6 +1170,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
||||
|
||||
|
||||
//---- JTextField ---------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -863,10 +1248,118 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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 ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* <strong>Component</strong> {@link javax.swing.JToggleButton}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Integer}
|
||||
@@ -889,6 +1382,7 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
||||
|
||||
|
||||
//---- JTree --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -908,6 +1402,45 @@ public interface FlatClientProperties
|
||||
*/
|
||||
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 -----------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,8 @@ public class FlatDarculaLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatDarculaLaf() );
|
||||
|
||||
@@ -33,6 +33,8 @@ public class FlatDarkLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatDarkLaf() );
|
||||
|
||||
@@ -26,7 +26,7 @@ import javax.swing.UIDefaults;
|
||||
* Allows loading of additional .properties files from addon JARs.
|
||||
* {@link java.util.ServiceLoader} is used to load extensions of this class from addon JARs.
|
||||
* <p>
|
||||
* If you extend this class in a addon JAR, you also have to add a text file named
|
||||
* 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}
|
||||
* to the addon JAR. The file must contain a single line with the class name.
|
||||
* <p>
|
||||
@@ -48,7 +48,7 @@ public abstract class FlatDefaultsAddon
|
||||
public InputStream getDefaults( Class<?> lafClass ) {
|
||||
Class<?> addonClass = this.getClass();
|
||||
String propertiesName = '/' + addonClass.getPackage().getName().replace( '.', '/' )
|
||||
+ '/' + lafClass.getSimpleName() + ".properties";
|
||||
+ '/' + UIDefaultsLoader.simpleClassName( lafClass ) + ".properties";
|
||||
return addonClass.getResourceAsStream( propertiesName );
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public abstract class FlatDefaultsAddon
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Returns 10000 by default.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf;
|
||||
/**
|
||||
* Default color palette for action icons and object icons.
|
||||
* <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 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.
|
||||
@@ -35,7 +35,7 @@ package com.formdev.flatlaf;
|
||||
* <p>
|
||||
* 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>
|
||||
* Instead use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||
* Instead, use {@code UIManager.getColor( FlatIconColors.ACTIONS_GREY.key )}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
|
||||
@@ -50,7 +50,8 @@ class FlatInputMaps
|
||||
}
|
||||
|
||||
modifyInputMap( defaults, "ComboBox.ancestorInputMap",
|
||||
"SPACE", "spacePopup",
|
||||
// Space key still shows popup, but from FlatComboBoxUI.FlatKeySelectionManager
|
||||
// "SPACE", "spacePopup",
|
||||
|
||||
"UP", mac( "selectPrevious2", "selectPrevious" ),
|
||||
"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[] rtlBindings = (Object[]) defaults.get( "PopupMenu.selectedWindowInputMapBindings.RightToLeft" );
|
||||
if( bindings != null && rtlBindings != null ) {
|
||||
@@ -596,7 +597,7 @@ class FlatInputMaps
|
||||
//---- class LazyInputMapEx -----------------------------------------------
|
||||
|
||||
/**
|
||||
* Lazily creates a input map.
|
||||
* Lazily creates an input map.
|
||||
* Similar to {@link UIDefaults.LazyInputMap}, but can use multiple bindings arrays.
|
||||
*/
|
||||
private static class LazyInputMapEx
|
||||
|
||||
@@ -34,6 +34,8 @@ public class FlatIntelliJLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatIntelliJLaf() );
|
||||
|
||||
@@ -52,6 +52,7 @@ import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.RootPaneContainer;
|
||||
@@ -62,16 +63,21 @@ import javax.swing.UIDefaults.LazyValue;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.FontUIResource;
|
||||
import javax.swing.plaf.IconUIResource;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicLookAndFeel;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
import javax.swing.text.StyleContext;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
|
||||
import com.formdev.flatlaf.ui.FlatPopupFactory;
|
||||
import com.formdev.flatlaf.ui.FlatRootPaneUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.ui.JavaCompatibility2;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.FontUtils;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
@@ -92,6 +98,7 @@ public abstract class FlatLaf
|
||||
private static List<Object> customDefaultsSources;
|
||||
private static Map<String, String> globalExtraDefaults;
|
||||
private Map<String, String> extraDefaults;
|
||||
private static Function<String, Color> systemColorGetter;
|
||||
|
||||
private String desktopPropertyName;
|
||||
private String desktopPropertyName2;
|
||||
@@ -102,13 +109,21 @@ public abstract class FlatLaf
|
||||
|
||||
private PopupFactory oldPopupFactory;
|
||||
private MnemonicHandler mnemonicHandler;
|
||||
private boolean subMenuUsabilityHelperInstalled;
|
||||
|
||||
private Consumer<UIDefaults> postInitialization;
|
||||
private List<Function<Object, Object>> uiDefaultsGetters;
|
||||
|
||||
private static String preferredFontFamily;
|
||||
private static String preferredLightFontFamily;
|
||||
private static String preferredSemiboldFontFamily;
|
||||
private static String preferredMonospacedFontFamily;
|
||||
|
||||
/**
|
||||
* Sets the application look and feel to the given LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup( LookAndFeel newLookAndFeel ) {
|
||||
try {
|
||||
@@ -165,18 +180,13 @@ public abstract class FlatLaf
|
||||
* Returns whether FlatLaf supports custom window decorations.
|
||||
* This depends on the operating system and on the used Java runtime.
|
||||
* <p>
|
||||
* This method returns {@code true} on Windows 10 (see exception below), {@code false} otherwise.
|
||||
* This method returns {@code true} on Windows 10/11 (see exception below)
|
||||
* and on Linux, otherwise returns {@code false}.
|
||||
* <p>
|
||||
* Returns also {@code false} on Windows 10 if:
|
||||
* <ul>
|
||||
* <li>FlatLaf native window border support is available (requires Windows 10)</li>
|
||||
* <li>running in
|
||||
* <a href="https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime">JetBrains Runtime 11 (or later)</a>
|
||||
* (<a href="https://github.com/JetBrains/JetBrainsRuntime">source code on github</a>)
|
||||
* and JBR supports custom window decorations
|
||||
* </li>
|
||||
* </ul>
|
||||
* In this cases, custom decorations are enabled by the root pane.
|
||||
* Returns also {@code false} on Windows 10/11 if
|
||||
* FlatLaf native window border support is available (requires Windows 10/11).
|
||||
* <p>
|
||||
* In these cases, custom decorations are enabled by the root pane.
|
||||
* Usage of {@link JFrame#setDefaultLookAndFeelDecorated(boolean)} or
|
||||
* {@link JDialog#setDefaultLookAndFeelDecorated(boolean)} is not necessary.
|
||||
*/
|
||||
@@ -189,7 +199,7 @@ public abstract class FlatLaf
|
||||
FlatNativeWindowBorder.isSupported() )
|
||||
return false;
|
||||
|
||||
return SystemInfo.isWindows_10_orLater;
|
||||
return SystemInfo.isWindows_10_orLater || SystemInfo.isLinux;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -229,6 +239,15 @@ public abstract class FlatLaf
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
// do not initialize if this is not the current look and feel
|
||||
// This is only necessary for special Laf usage. E.g. in GUI builders,
|
||||
// which may use multiple Lafs and may invoke this method directly.
|
||||
// This avoids that listeners and factories are installed multiple times.
|
||||
// In case of the NetBeans GUI builder, which does not invoke uninitialize(),
|
||||
// this also avoids that listeners stay registered in the system.
|
||||
if( UIManager.getLookAndFeel() != this )
|
||||
return;
|
||||
|
||||
if( SystemInfo.isMacOS )
|
||||
initializeAqua();
|
||||
|
||||
@@ -242,6 +261,9 @@ public abstract class FlatLaf
|
||||
mnemonicHandler = new MnemonicHandler();
|
||||
mnemonicHandler.install();
|
||||
|
||||
// install submenu usability helper
|
||||
subMenuUsabilityHelperInstalled = SubMenuUsabilityHelper.install();
|
||||
|
||||
// listen to desktop property changes to update UI if system font or scaling changes
|
||||
if( SystemInfo.isWindows ) {
|
||||
// Windows 10 allows increasing font size independent of scaling:
|
||||
@@ -259,6 +281,9 @@ public abstract class FlatLaf
|
||||
}
|
||||
if( desktopPropertyName != null ) {
|
||||
desktopPropertyListener = e -> {
|
||||
if( !FlatSystemProperties.getBoolean( FlatSystemProperties.UPDATE_UI_ON_SYSTEM_FONT_CHANGE, true ) )
|
||||
return;
|
||||
|
||||
String propertyName = e.getPropertyName();
|
||||
if( desktopPropertyName.equals( propertyName ) || propertyName.equals( desktopPropertyName2 ) )
|
||||
reSetLookAndFeel();
|
||||
@@ -297,6 +322,10 @@ public abstract class FlatLaf
|
||||
|
||||
@Override
|
||||
public void uninitialize() {
|
||||
// do not uninitialize if this is not the current look and feel
|
||||
if( UIManager.getLookAndFeel() != this )
|
||||
return;
|
||||
|
||||
// remove desktop property listener
|
||||
if( desktopPropertyListener != null ) {
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
@@ -321,6 +350,12 @@ public abstract class FlatLaf
|
||||
mnemonicHandler = null;
|
||||
}
|
||||
|
||||
// uninstall submenu usability helper
|
||||
if( subMenuUsabilityHelperInstalled ) {
|
||||
SubMenuUsabilityHelper.uninstall();
|
||||
subMenuUsabilityHelperInstalled = false;
|
||||
}
|
||||
|
||||
// restore default link color
|
||||
new HTMLEditorKit().getStyleSheet().addRule( "a, address { color: blue; }" );
|
||||
postInitialization = null;
|
||||
@@ -349,7 +384,7 @@ public abstract class FlatLaf
|
||||
Method m = UIManager.class.getMethod( "createLookAndFeel", String.class );
|
||||
aquaLaf = (BasicLookAndFeel) m.invoke( null, "Mac OS X" );
|
||||
} else
|
||||
aquaLaf = (BasicLookAndFeel) Class.forName( aquaLafClassName ).getDeclaredConstructor().newInstance();
|
||||
aquaLaf = Class.forName( aquaLafClassName ).asSubclass( BasicLookAndFeel.class ).getDeclaredConstructor().newInstance();
|
||||
} catch( Exception ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to initialize Aqua look and feel '" + aquaLafClassName + "'.", ex );
|
||||
throw new IllegalStateException();
|
||||
@@ -501,7 +536,7 @@ public abstract class FlatLaf
|
||||
// which can happen in applications that use some plugin system
|
||||
// and load FlatLaf in a plugin that uses its own classloader.
|
||||
// (e.g. Apache NetBeans)
|
||||
if( defaults.get( "FileChooser.fileNameHeaderText" ) != null )
|
||||
if( defaults.get( "TabbedPane.moreTabsButtonToolTipText" ) != null )
|
||||
return;
|
||||
|
||||
// load FlatLaf resource bundle and add content to defaults
|
||||
@@ -539,13 +574,17 @@ public abstract class FlatLaf
|
||||
Object activeFont = new ActiveFont( null, null, -1, 0, 0, 0, 0 );
|
||||
|
||||
// override fonts
|
||||
List<String> fontKeys = new ArrayList<>( 50 );
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) )
|
||||
defaults.put( key, activeFont );
|
||||
fontKeys.add( (String) key );
|
||||
}
|
||||
for( String key : fontKeys )
|
||||
defaults.put( key, activeFont );
|
||||
|
||||
// add fonts that are not set in BasicLookAndFeel
|
||||
defaults.put( "RootPane.font", activeFont );
|
||||
defaults.put( "TitlePane.font", activeFont );
|
||||
}
|
||||
|
||||
private void initDefaultFont( UIDefaults defaults ) {
|
||||
@@ -594,6 +633,13 @@ public abstract class FlatLaf
|
||||
if( uiFont == null )
|
||||
uiFont = createCompositeFont( Font.SANS_SERIF, Font.PLAIN, 12 );
|
||||
|
||||
// use preferred font family (if specified)
|
||||
if( preferredFontFamily != null ) {
|
||||
FontUIResource preferredFont = createCompositeFont( preferredFontFamily, uiFont.getStyle(), uiFont.getSize() );
|
||||
if( !ActiveFont.isFallbackFont( preferredFont ) || ActiveFont.isDialogFamily( preferredFontFamily ) )
|
||||
uiFont = preferredFont;
|
||||
}
|
||||
|
||||
// get/remove "defaultFont" from defaults if set in properties files
|
||||
// (use remove() to avoid that ActiveFont.createValue() gets invoked)
|
||||
Object defaultFont = defaults.remove( "defaultFont" );
|
||||
@@ -604,7 +650,7 @@ public abstract class FlatLaf
|
||||
uiFont = ((ActiveFont)defaultFont).derive( baseFont, fontSize -> {
|
||||
return Math.round( fontSize * UIScale.computeFontScaleFactor( baseFont ) );
|
||||
} );
|
||||
};
|
||||
}
|
||||
|
||||
// increase font size if system property "flatlaf.uiScale" is set
|
||||
uiFont = UIScale.applyCustomScaleFactor( uiFont );
|
||||
@@ -614,6 +660,9 @@ public abstract class FlatLaf
|
||||
}
|
||||
|
||||
static FontUIResource createCompositeFont( String family, int style, int size ) {
|
||||
// load lazy font family
|
||||
FontUtils.loadFontFamily( family );
|
||||
|
||||
// using StyleContext.getFont() here because it uses
|
||||
// sun.font.FontUtilities.getCompositeFontUIResource()
|
||||
// and creates a composite font that is able to display all Unicode characters
|
||||
@@ -759,7 +808,7 @@ public abstract class FlatLaf
|
||||
* Invoke this method before setting the look and feel.
|
||||
* <p>
|
||||
* If using Java modules, the package must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #registerCustomDefaultsSource(URL)}.
|
||||
* Otherwise, use {@link #registerCustomDefaultsSource(URL)}.
|
||||
*
|
||||
* @param packageName a package name (e.g. "com.myapp.resources")
|
||||
*/
|
||||
@@ -861,14 +910,14 @@ public abstract class FlatLaf
|
||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||
* <p>
|
||||
* The global extra defaults are useful for smaller additional defaults that may change.
|
||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
||||
* Otherwise, FlatLaf properties files should be used.
|
||||
* See {@link #registerCustomDefaultsSource(String)}.
|
||||
* <p>
|
||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||
* <p>
|
||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
||||
* Sample that setups "FlatLaf Light" theme with white background color:
|
||||
* <pre>{@code
|
||||
* FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
||||
* FlatLaf.setGlobalExtraDefaults( Collections.singletonMap( "@background", "#fff" ) );
|
||||
* FlatLightLaf.setup();
|
||||
* }</pre>
|
||||
*
|
||||
@@ -893,15 +942,15 @@ public abstract class FlatLaf
|
||||
* E.g. using {@link UIManager#setLookAndFeel(LookAndFeel)} or {@link #setup(LookAndFeel)}.
|
||||
* <p>
|
||||
* The extra defaults are useful for smaller additional defaults that may change.
|
||||
* E.g. accent color. Otherwise FlatLaf properties files should be used.
|
||||
* Otherwise, FlatLaf properties files should be used.
|
||||
* See {@link #registerCustomDefaultsSource(String)}.
|
||||
* <p>
|
||||
* The keys and values are strings in same format as in FlatLaf properties files.
|
||||
* <p>
|
||||
* Sample that setups "FlatLaf Light" theme with red accent color:
|
||||
* Sample that setups "FlatLaf Light" theme with white background color:
|
||||
* <pre>{@code
|
||||
* FlatLaf laf = new FlatLightLaf();
|
||||
* laf.setExtraDefaults( Collections.singletonMap( "@accentColor", "#f00" ) );
|
||||
* laf.setExtraDefaults( Collections.singletonMap( "@background", "#fff" ) );
|
||||
* FlatLaf.setup( laf );
|
||||
* }</pre>
|
||||
*
|
||||
@@ -943,6 +992,36 @@ public abstract class FlatLaf
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the system color getter function, or {@code null}.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static Function<String, Color> getSystemColorGetter() {
|
||||
return systemColorGetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a system color getter function that is invoked when function
|
||||
* {@code systemColor()} is used in FlatLaf properties files.
|
||||
* <p>
|
||||
* The name of the system color is passed as parameter to the function.
|
||||
* The function should return {@code null} for unknown system colors.
|
||||
* <p>
|
||||
* Can be used to change the accent color:
|
||||
* <pre>{@code
|
||||
* FlatLaf.setSystemColorGetter( name -> {
|
||||
* return name.equals( "accent" ) ? Color.red : null;
|
||||
* } );
|
||||
* FlatLightLaf.setup();
|
||||
* }</pre>
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static void setSystemColorGetter( Function<String, Color> systemColorGetter ) {
|
||||
FlatLaf.systemColorGetter = systemColorGetter;
|
||||
}
|
||||
|
||||
private static void reSetLookAndFeel() {
|
||||
EventQueue.invokeLater( () -> {
|
||||
LookAndFeel lookAndFeel = UIManager.getLookAndFeel();
|
||||
@@ -950,7 +1029,7 @@ public abstract class FlatLaf
|
||||
// re-set current LaF
|
||||
UIManager.setLookAndFeel( lookAndFeel );
|
||||
|
||||
// must fire property change events ourself because old and new LaF are the same
|
||||
// must fire property change events ourselves because old and new LaF are the same
|
||||
PropertyChangeEvent e = new PropertyChangeEvent( UIManager.class, "lookAndFeel", lookAndFeel, lookAndFeel );
|
||||
for( PropertyChangeListener l : UIManager.getPropertyChangeListeners() )
|
||||
l.propertyChange( e );
|
||||
@@ -994,7 +1073,7 @@ public abstract class FlatLaf
|
||||
/**
|
||||
* Returns whether native window decorations are supported on current platform.
|
||||
* <p>
|
||||
* This requires Windows 10, but may be disabled if running in special environments
|
||||
* This requires Windows 10/11, but may be disabled if running in special environments
|
||||
* (JetBrains Projector, Webswing or WinPE) or if loading native library fails.
|
||||
* If system property {@link FlatSystemProperties#USE_WINDOW_DECORATIONS} is set to
|
||||
* {@code false}, then this method also returns {@code false}.
|
||||
@@ -1036,12 +1115,23 @@ public abstract class FlatLaf
|
||||
|
||||
/**
|
||||
* Revalidate and repaint all displayable frames and dialogs.
|
||||
* <p>
|
||||
* Useful to update UI after changing {@code TitlePane.menuBarEmbedded}.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static void revalidateAndRepaintAllFramesAndDialogs() {
|
||||
for( Window w : Window.getWindows() ) {
|
||||
if( isDisplayableFrameOrDialog( w ) ) {
|
||||
// revalidate menu bar
|
||||
JMenuBar menuBar = (w instanceof JFrame)
|
||||
? ((JFrame)w).getJMenuBar()
|
||||
: (w instanceof JDialog
|
||||
? ((JDialog)w).getJMenuBar()
|
||||
: null);
|
||||
if( menuBar != null )
|
||||
menuBar.revalidate();
|
||||
|
||||
w.revalidate();
|
||||
w.repaint();
|
||||
}
|
||||
@@ -1050,6 +1140,9 @@ public abstract class FlatLaf
|
||||
|
||||
/**
|
||||
* Repaint all displayable frames and dialogs.
|
||||
* <p>
|
||||
* Useful to update UI after changing {@code TitlePane.unifiedBackground},
|
||||
* {@code MenuItem.selectionType} or {@code Component.hideMnemonics}.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
@@ -1186,28 +1279,150 @@ public abstract class FlatLaf
|
||||
*/
|
||||
public static final Object NULL_VALUE = new Object();
|
||||
|
||||
/**
|
||||
* Returns information about styleable values of a component.
|
||||
* <p>
|
||||
* This is equivalent to: {@code ((StyleableUI)c.getUI()).getStyleableInfos(c)}
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public static Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
ComponentUI ui = JavaCompatibility2.getUI( c );
|
||||
return (ui instanceof StyleableUI) ? ((StyleableUI)ui).getStyleableInfos( c ) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (styled) value for the given key from the given component.
|
||||
* <p>
|
||||
* This is equivalent to: {@code ((StyleableUI)c.getUI()).getStyleableValue(c, key)}
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public static <T> T getStyleableValue( JComponent c, String key ) {
|
||||
ComponentUI ui = JavaCompatibility2.getUI( c );
|
||||
return (ui instanceof StyleableUI) ? (T) ((StyleableUI)ui).getStyleableValue( c, key ) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred font family to be used for (nearly) all fonts; or {@code null}.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static String getPreferredFontFamily() {
|
||||
return preferredFontFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preferred font family to be used for (nearly) all fonts.
|
||||
* <p>
|
||||
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||
* the application look and feel.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static void setPreferredFontFamily( String preferredFontFamily ) {
|
||||
FlatLaf.preferredFontFamily = preferredFontFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred font family to be used for "light" fonts; or {@code null}.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static String getPreferredLightFontFamily() {
|
||||
return preferredLightFontFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preferred font family to be used for "light" fonts.
|
||||
* <p>
|
||||
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||
* the application look and feel.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static void setPreferredLightFontFamily( String preferredLightFontFamily ) {
|
||||
FlatLaf.preferredLightFontFamily = preferredLightFontFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred font family to be used for "semibold" fonts; or {@code null}.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static String getPreferredSemiboldFontFamily() {
|
||||
return preferredSemiboldFontFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preferred font family to be used for "semibold" fonts.
|
||||
* <p>
|
||||
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||
* the application look and feel.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static void setPreferredSemiboldFontFamily( String preferredSemiboldFontFamily ) {
|
||||
FlatLaf.preferredSemiboldFontFamily = preferredSemiboldFontFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred font family to be used for monospaced fonts; or {@code null}.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static String getPreferredMonospacedFontFamily() {
|
||||
return preferredMonospacedFontFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preferred font family to be used for monospaced fonts.
|
||||
* <p>
|
||||
* <strong>Note</strong>: This must be invoked <strong>before</strong> setting
|
||||
* the application look and feel.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static void setPreferredMonospacedFontFamily( String preferredMonospacedFontFamily ) {
|
||||
FlatLaf.preferredMonospacedFontFamily = preferredMonospacedFontFamily;
|
||||
}
|
||||
|
||||
//---- class FlatUIDefaults -----------------------------------------------
|
||||
|
||||
private class FlatUIDefaults
|
||||
extends UIDefaults
|
||||
{
|
||||
private UIDefaults metalDefaults;
|
||||
|
||||
FlatUIDefaults( int initialCapacity, float loadFactor ) {
|
||||
super( initialCapacity, loadFactor );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get( Object key ) {
|
||||
Object value = getValue( key );
|
||||
return (value != null) ? (value != NULL_VALUE ? value : null) : super.get( key );
|
||||
return get( key, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get( Object key, Locale l ) {
|
||||
Object value = getValue( key );
|
||||
return (value != null) ? (value != NULL_VALUE ? value : null) : super.get( key, l );
|
||||
Object value = getFromUIDefaultsGetters( key );
|
||||
if( value != null )
|
||||
return (value != NULL_VALUE) ? value : null;
|
||||
|
||||
value = super.get( key, l );
|
||||
if( value != null )
|
||||
return value;
|
||||
|
||||
// get file chooser texts from Metal
|
||||
return (key instanceof String && ((String)key).startsWith( "FileChooser." ))
|
||||
? getFromMetal( (String) key, l )
|
||||
: null;
|
||||
}
|
||||
|
||||
private Object getValue( Object key ) {
|
||||
private Object getFromUIDefaultsGetters( Object key ) {
|
||||
// use local variable for getters to avoid potential multi-threading issues
|
||||
List<Function<Object, Object>> uiDefaultsGetters = FlatLaf.this.uiDefaultsGetters;
|
||||
if( uiDefaultsGetters == null )
|
||||
return null;
|
||||
|
||||
@@ -1219,6 +1434,22 @@ public abstract class FlatLaf
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private synchronized Object getFromMetal( String key, Locale l ) {
|
||||
if( metalDefaults == null ) {
|
||||
metalDefaults = new MetalLookAndFeel() {
|
||||
// avoid unnecessary initialization
|
||||
@Override protected void initClassDefaults( UIDefaults table ) {}
|
||||
@Override protected void initSystemColorDefaults( UIDefaults table ) {}
|
||||
}.getDefaults();
|
||||
|
||||
// empty not needed defaults (to save memory) because we're only interested
|
||||
// in resource bundle strings, which are stored in another internal map
|
||||
metalDefaults.clear();
|
||||
}
|
||||
|
||||
return metalDefaults.get( key, l );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class ActiveFont ---------------------------------------------------
|
||||
@@ -1261,8 +1492,9 @@ public abstract class FlatLaf
|
||||
this.scaleSize = scaleSize;
|
||||
}
|
||||
|
||||
// using synchronized to avoid exception if invoked at the same time on multiple threads
|
||||
@Override
|
||||
public Object createValue( UIDefaults table ) {
|
||||
public synchronized Object createValue( UIDefaults table ) {
|
||||
if( inCreateValue )
|
||||
throw new IllegalStateException( "FlatLaf: endless recursion in font" );
|
||||
|
||||
@@ -1300,7 +1532,7 @@ public abstract class FlatLaf
|
||||
int newStyle = (style != -1)
|
||||
? style
|
||||
: (styleChange != 0)
|
||||
? baseStyle & ~((styleChange >> 16) & 0xffff) | (styleChange & 0xffff)
|
||||
? (baseStyle & ~((styleChange >> 16) & 0xffff)) | (styleChange & 0xffff)
|
||||
: baseStyle;
|
||||
|
||||
// new size
|
||||
@@ -1316,17 +1548,34 @@ public abstract class FlatLaf
|
||||
|
||||
// create font for family
|
||||
if( families != null && !families.isEmpty() ) {
|
||||
String preferredFamily = preferredFamily( families );
|
||||
if( preferredFamily != null ) {
|
||||
Font font = createCompositeFont( preferredFamily, newStyle, newSize );
|
||||
if( !isFallbackFont( font ) || isDialogFamily( preferredFamily ) )
|
||||
return toUIResource( font );
|
||||
}
|
||||
|
||||
for( String family : families ) {
|
||||
Font font = createCompositeFont( family, newStyle, newSize );
|
||||
if( !isFallbackFont( font ) || family.equalsIgnoreCase( Font.DIALOG ) )
|
||||
if( !isFallbackFont( font ) || isDialogFamily( family ) )
|
||||
return toUIResource( font );
|
||||
}
|
||||
}
|
||||
|
||||
// derive font
|
||||
if( newStyle != baseStyle || newSize != baseSize )
|
||||
if( newStyle != baseStyle || newSize != baseSize ) {
|
||||
// hack for font "Ubuntu Medium" on Linux, which curiously belongs
|
||||
// to family "Ubuntu Light" and using deriveFont() would create a light font
|
||||
if( "Ubuntu Medium".equalsIgnoreCase( baseFont.getName() ) &&
|
||||
"Ubuntu Light".equalsIgnoreCase( baseFont.getFamily() ) )
|
||||
{
|
||||
Font font = createCompositeFont( "Ubuntu Medium", newStyle, newSize );
|
||||
if( !isFallbackFont( font ) )
|
||||
return toUIResource( font );
|
||||
}
|
||||
|
||||
return toUIResource( baseFont.deriveFont( newStyle, newSize ) );
|
||||
else
|
||||
} else
|
||||
return toUIResource( baseFont );
|
||||
}
|
||||
|
||||
@@ -1337,9 +1586,26 @@ public abstract class FlatLaf
|
||||
: new FontUIResource( font );
|
||||
}
|
||||
|
||||
private boolean isFallbackFont( Font font ) {
|
||||
private static boolean isFallbackFont( Font font ) {
|
||||
return Font.DIALOG.equalsIgnoreCase( font.getFamily() );
|
||||
}
|
||||
|
||||
private static boolean isDialogFamily( String family ) {
|
||||
return family.equalsIgnoreCase( Font.DIALOG );
|
||||
}
|
||||
|
||||
private static String preferredFamily( List<String> families ) {
|
||||
for( String family : families ) {
|
||||
family = family.toLowerCase( Locale.ENGLISH );
|
||||
if( family.endsWith( " light" ) || family.endsWith( "-thin" ) )
|
||||
return preferredLightFontFamily;
|
||||
if( family.endsWith( " semibold" ) || family.endsWith( "-medium" ) )
|
||||
return preferredSemiboldFontFamily;
|
||||
if( family.equals( "monospaced" ) )
|
||||
return preferredMonospacedFontFamily;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//---- class ImageIconUIResource ------------------------------------------
|
||||
|
||||
@@ -33,6 +33,8 @@ public class FlatLightLaf
|
||||
/**
|
||||
* Sets the application look and feel to this LaF
|
||||
* using {@link UIManager#setLookAndFeel(javax.swing.LookAndFeel)}.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup() {
|
||||
return setup( new FlatLightLaf() );
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -96,7 +97,7 @@ public class FlatPropertiesLaf
|
||||
protected ArrayList<Class<?>> getLafClassesForDefaultsLoading() {
|
||||
ArrayList<Class<?>> lafClasses = new ArrayList<>();
|
||||
lafClasses.add( FlatLaf.class );
|
||||
switch( baseTheme.toLowerCase() ) {
|
||||
switch( baseTheme.toLowerCase( Locale.ENGLISH ) ) {
|
||||
default:
|
||||
case "light":
|
||||
lafClasses.add( FlatLightLaf.class );
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -34,7 +35,7 @@ public interface FlatSystemProperties
|
||||
* To replace the Java 9+ system scale factor, use system property "sun.java2d.uiScale",
|
||||
* which has the same syntax as this one.
|
||||
* <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>
|
||||
* <strong>Allowed Values</strong> e.g. {@code 1.5}, {@code 1.5x}, {@code 150%} or {@code 144dpi} (96dpi is 100%)<br>
|
||||
*/
|
||||
@@ -81,7 +82,7 @@ public interface FlatSystemProperties
|
||||
* {@link FlatClientProperties#USE_WINDOW_DECORATIONS} and
|
||||
* UI default {@code TitlePane.useWindowDecorations}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> none
|
||||
@@ -92,17 +93,20 @@ public interface FlatSystemProperties
|
||||
* Specifies whether JetBrains Runtime custom window decorations should be used
|
||||
* when creating {@code JFrame} or {@code JDialog}.
|
||||
* 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).
|
||||
* <p>
|
||||
* Setting this to {@code false} disables using JetBrains Runtime custom window decorations.
|
||||
* Then FlatLaf native window decorations are used.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <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";
|
||||
|
||||
/**
|
||||
@@ -116,7 +120,7 @@ public interface FlatSystemProperties
|
||||
* {@link FlatClientProperties#MENU_BAR_EMBEDDED} and
|
||||
* UI default {@code TitlePane.menuBarEmbedded}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* (requires Window 10/11)
|
||||
* <p>
|
||||
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||
* <strong>Default</strong> none
|
||||
@@ -139,6 +143,67 @@ public interface FlatSystemProperties
|
||||
*/
|
||||
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";
|
||||
|
||||
/**
|
||||
* Checks whether a system property is set and returns {@code true} if its value
|
||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||
|
||||
@@ -23,13 +23,17 @@ import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import javax.swing.UIDefaults;
|
||||
import javax.swing.plaf.ColorUIResource;
|
||||
import com.formdev.flatlaf.json.Json;
|
||||
@@ -37,6 +41,7 @@ import com.formdev.flatlaf.json.ParseException;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
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.
|
||||
@@ -60,9 +65,9 @@ public class IntelliJTheme
|
||||
|
||||
private final boolean isMaterialUILite;
|
||||
|
||||
private final Map<String, String> colors;
|
||||
private final Map<String, Object> ui;
|
||||
private final Map<String, Object> icons;
|
||||
private Map<String, String> colors;
|
||||
private Map<String, Object> ui;
|
||||
private Map<String, Object> icons;
|
||||
|
||||
private Map<String, ColorUIResource> namedColors = Collections.emptyMap();
|
||||
|
||||
@@ -72,6 +77,8 @@ public class IntelliJTheme
|
||||
*
|
||||
* The input stream is automatically closed.
|
||||
* Using a buffered input stream is not necessary.
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
public static boolean setup( InputStream in ) {
|
||||
try {
|
||||
@@ -162,8 +169,11 @@ public class IntelliJTheme
|
||||
applyCheckBoxColors( defaults );
|
||||
|
||||
// copy values
|
||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() )
|
||||
defaults.put( e.getKey(), defaults.get( e.getValue() ) );
|
||||
for( Map.Entry<String, String> e : uiKeyCopying.entrySet() ) {
|
||||
Object value = defaults.get( e.getValue() );
|
||||
if( value != null )
|
||||
defaults.put( e.getKey(), value );
|
||||
}
|
||||
|
||||
// IDEA does not paint button background if disabled, but FlatLaf does
|
||||
Object panelBackground = defaults.get( "Panel.background" );
|
||||
@@ -175,7 +185,7 @@ public class IntelliJTheme
|
||||
defaults.put( "Button.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
defaults.put( "HelpButton.hoverBorderColor", defaults.get( "Button.focusedBorderColor" ) );
|
||||
|
||||
// IDEA uses a SVG icon for the help button, but paints the background with Button.startBackground and Button.endBackground
|
||||
// IDEA uses an 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 )
|
||||
@@ -190,8 +200,9 @@ public class IntelliJTheme
|
||||
defaults.put( "HelpButton.focusedBackground", defaults.get( "Button.focusedBackground" ) );
|
||||
|
||||
// IDEA uses TextField.background for editable ComboBox and Spinner
|
||||
defaults.put( "ComboBox.editableBackground", defaults.get( "TextField.background" ) );
|
||||
defaults.put( "Spinner.background", defaults.get( "TextField.background" ) );
|
||||
Object textFieldBackground = get( defaults, themeSpecificDefaults, "TextField.background" );
|
||||
defaults.put( "ComboBox.editableBackground", textFieldBackground );
|
||||
defaults.put( "Spinner.background", textFieldBackground );
|
||||
|
||||
// Spinner arrow button always has same colors as ComboBox arrow button
|
||||
defaults.put( "Spinner.buttonBackground", defaults.get( "ComboBox.buttonEditableBackground" ) );
|
||||
@@ -199,22 +210,41 @@ public class IntelliJTheme
|
||||
defaults.put( "Spinner.buttonDisabledArrowColor", defaults.get( "ComboBox.buttonDisabledArrowColor" ) );
|
||||
|
||||
// some themes specify colors for TextField.background, but forget to specify it for other components
|
||||
// (probably because those components are not used in IntelliJ)
|
||||
if( uiKeys.contains( "TextField.background" ) ) {
|
||||
Object textFieldBackground = defaults.get( "TextField.background" );
|
||||
if( !uiKeys.contains( "FormattedTextField.background" ) )
|
||||
defaults.put( "FormattedTextField.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "PasswordField.background" ) )
|
||||
defaults.put( "PasswordField.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "EditorPane.background" ) )
|
||||
defaults.put( "EditorPane.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "TextArea.background" ) )
|
||||
defaults.put( "TextArea.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "TextPane.background" ) )
|
||||
defaults.put( "TextPane.background", textFieldBackground );
|
||||
if( !uiKeys.contains( "Spinner.background" ) )
|
||||
defaults.put( "Spinner.background", textFieldBackground );
|
||||
}
|
||||
// (probably because those components are not used in IntelliJ IDEA)
|
||||
putAll( defaults, textFieldBackground,
|
||||
"EditorPane.background",
|
||||
"FormattedTextField.background",
|
||||
"PasswordField.background",
|
||||
"TextArea.background",
|
||||
"TextPane.background"
|
||||
);
|
||||
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionBackground" ),
|
||||
"EditorPane.selectionBackground",
|
||||
"FormattedTextField.selectionBackground",
|
||||
"PasswordField.selectionBackground",
|
||||
"TextArea.selectionBackground",
|
||||
"TextPane.selectionBackground"
|
||||
);
|
||||
putAll( defaults, get( defaults, themeSpecificDefaults, "TextField.selectionForeground" ),
|
||||
"EditorPane.selectionForeground",
|
||||
"FormattedTextField.selectionForeground",
|
||||
"PasswordField.selectionForeground",
|
||||
"TextArea.selectionForeground",
|
||||
"TextPane.selectionForeground"
|
||||
);
|
||||
|
||||
// fix disabled and not-editable backgrounds for text components, combobox and spinner
|
||||
// (IntelliJ IDEA does not use those colors; instead it used background color of parent)
|
||||
putAll( defaults, panelBackground,
|
||||
"ComboBox.disabledBackground",
|
||||
"EditorPane.disabledBackground", "EditorPane.inactiveBackground",
|
||||
"FormattedTextField.disabledBackground", "FormattedTextField.inactiveBackground",
|
||||
"PasswordField.disabledBackground", "PasswordField.inactiveBackground",
|
||||
"Spinner.disabledBackground",
|
||||
"TextArea.disabledBackground", "TextArea.inactiveBackground",
|
||||
"TextField.disabledBackground", "TextField.inactiveBackground",
|
||||
"TextPane.disabledBackground", "TextPane.inactiveBackground"
|
||||
);
|
||||
|
||||
// fix ToggleButton
|
||||
if( !uiKeys.contains( "ToggleButton.startBackground" ) && !uiKeys.contains( "*.startBackground" ) )
|
||||
@@ -241,8 +271,61 @@ public class IntelliJTheme
|
||||
if( rowHeight > 22 )
|
||||
defaults.put( "Tree.rowHeight", 22 );
|
||||
|
||||
// get (and remove) theme specific wildcard replacements, which override all other defaults that end with same suffix
|
||||
HashMap<String, Object> wildcards = new HashMap<>();
|
||||
Iterator<Entry<Object, Object>> it = themeSpecificDefaults.entrySet().iterator();
|
||||
while( it.hasNext() ) {
|
||||
Entry<Object, Object> e = it.next();
|
||||
String key = (String) e.getKey();
|
||||
if( key.startsWith( "*." ) ) {
|
||||
wildcards.put( key.substring( "*.".length() ), e.getValue() );
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// override UI defaults with theme specific wildcard replacements
|
||||
if( !wildcards.isEmpty() ) {
|
||||
for( Object key : defaults.keySet().toArray() ) {
|
||||
int dot;
|
||||
if( !(key instanceof String) ||
|
||||
(dot = ((String)key).lastIndexOf( '.' )) < 0 )
|
||||
continue;
|
||||
|
||||
String wildcardKey = ((String)key).substring( dot + 1 );
|
||||
Object wildcardValue = wildcards.get( wildcardKey );
|
||||
if( wildcardValue != null )
|
||||
defaults.put( key, wildcardValue );
|
||||
}
|
||||
}
|
||||
|
||||
// apply theme specific UI defaults at the end to allow overwriting
|
||||
defaults.putAll( themeSpecificDefaults );
|
||||
for( Map.Entry<Object, Object> e : themeSpecificDefaults.entrySet() ) {
|
||||
Object key = e.getKey();
|
||||
Object value = e.getValue();
|
||||
|
||||
// append styles to existing styles
|
||||
if( key instanceof String && ((String)key).startsWith( "[style]" ) ) {
|
||||
Object oldValue = defaults.get( key );
|
||||
if( oldValue != null )
|
||||
value = oldValue + "; " + value;
|
||||
}
|
||||
|
||||
defaults.put( key, value );
|
||||
}
|
||||
|
||||
// let Java release memory
|
||||
colors = null;
|
||||
ui = null;
|
||||
icons = null;
|
||||
}
|
||||
|
||||
private Object get( UIDefaults defaults, Map<Object, Object> themeSpecificDefaults, String key ) {
|
||||
return themeSpecificDefaults.getOrDefault( key, defaults.get( key ) );
|
||||
}
|
||||
|
||||
private void putAll( UIDefaults defaults, Object value, String... keys ) {
|
||||
for( String key : keys )
|
||||
defaults.put( key, value );
|
||||
}
|
||||
|
||||
private Map<Object, Object> removeThemeSpecificDefaults( UIDefaults defaults ) {
|
||||
@@ -284,7 +367,7 @@ public class IntelliJTheme
|
||||
|
||||
for( Map.Entry<String, String> e : colors.entrySet() ) {
|
||||
String value = e.getValue();
|
||||
ColorUIResource color = UIDefaultsLoader.parseColor( value );
|
||||
ColorUIResource color = parseColor( value );
|
||||
if( color != null ) {
|
||||
String key = e.getKey();
|
||||
namedColors.put( key, color );
|
||||
@@ -299,23 +382,47 @@ public class IntelliJTheme
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private void apply( String key, Object value, UIDefaults defaults, ArrayList<Object> defaultsKeysCache, Set<String> uiKeys ) {
|
||||
if( value instanceof Map ) {
|
||||
for( Map.Entry<String, Object> e : ((Map<String, Object>)value).entrySet() )
|
||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
||||
Map<String, Object> map = (Map<String, Object>)value;
|
||||
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 ), defaults, defaultsKeysCache, uiKeys );
|
||||
else if( map.containsKey( "os.default" ) )
|
||||
apply( key, map.get( "os.default" ), defaults, defaultsKeysCache, uiKeys );
|
||||
} else {
|
||||
for( Map.Entry<String, Object> e : map.entrySet() )
|
||||
apply( key + '.' + e.getKey(), e.getValue(), defaults, defaultsKeysCache, uiKeys );
|
||||
}
|
||||
} else {
|
||||
if( "".equals( value ) )
|
||||
return; // ignore empty value
|
||||
|
||||
uiKeys.add( key );
|
||||
|
||||
// fix ComboBox size and Spinner border in all Material UI Lite themes
|
||||
if( isMaterialUILite && (key.equals( "ComboBox.padding" ) || key.equals( "Spinner.border" )) )
|
||||
return; // ignore
|
||||
// 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
|
||||
|
||||
// map keys
|
||||
key = uiKeyMapping.getOrDefault( key, key );
|
||||
if( key.isEmpty() )
|
||||
return; // ignore key
|
||||
|
||||
// exclude properties
|
||||
int dot = key.indexOf( '.' );
|
||||
if( dot > 0 && uiKeyExcludes.contains( key.substring( 0, dot + 1 ) ) )
|
||||
return;
|
||||
|
||||
if( uiKeyDoNotOverride.contains( key ) && uiKeys.contains( key ) )
|
||||
return;
|
||||
|
||||
uiKeys.add( key );
|
||||
|
||||
String valueStr = value.toString();
|
||||
|
||||
// map named colors
|
||||
@@ -361,7 +468,8 @@ public class IntelliJTheme
|
||||
// replace all values in UI defaults that match the wildcard key
|
||||
for( Object k : defaultsKeysCache ) {
|
||||
if( k.equals( "Desktop.background" ) ||
|
||||
k.equals( "DesktopIcon.background" ) )
|
||||
k.equals( "DesktopIcon.background" ) ||
|
||||
k.equals( "TabbedPane.focusColor" ) )
|
||||
continue;
|
||||
|
||||
if( k instanceof String ) {
|
||||
@@ -419,12 +527,20 @@ public class IntelliJTheme
|
||||
ColorUIResource color = namedColors.get( value );
|
||||
|
||||
// parse color
|
||||
return (color != null) ? color : UIDefaultsLoader.parseColor( value );
|
||||
return (color != null) ? color : parseColor( value );
|
||||
}
|
||||
|
||||
private ColorUIResource parseColor( String value ) {
|
||||
try {
|
||||
return UIDefaultsLoader.parseColor( value );
|
||||
} catch( IllegalArgumentException ex ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private void applyCheckBoxColors( UIDefaults defaults ) {
|
||||
@@ -444,18 +560,6 @@ public class IntelliJTheme
|
||||
if( !key.startsWith( "Checkbox." ) || !(value instanceof String) )
|
||||
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 )
|
||||
key = StringUtils.removeTrailing( key, ".Dark" );
|
||||
|
||||
@@ -469,6 +573,7 @@ public class IntelliJTheme
|
||||
if( color != null ) {
|
||||
defaults.put( newKey, color );
|
||||
|
||||
String key2 = checkboxDuplicateColors.get( key + ".Dark");
|
||||
if( key2 != null ) {
|
||||
// When IDEA replaces colors in SVGs it uses color values and not the keys
|
||||
// from com.intellij.ide.ui.UITheme.colorPalette, but there are some keys that
|
||||
@@ -511,7 +616,7 @@ public class IntelliJTheme
|
||||
// radioFocused.svg and radioSelectedFocused.svg
|
||||
// use opacity=".65" for the border
|
||||
// --> add alpha to focused border colors
|
||||
String[] focusedBorderColorKeys = new String[] {
|
||||
String[] focusedBorderColorKeys = {
|
||||
"CheckBox.icon.focusedBorderColor",
|
||||
"CheckBox.icon.focusedSelectedBorderColor",
|
||||
"CheckBox.icon[filled].focusedBorderColor",
|
||||
@@ -533,17 +638,59 @@ public class IntelliJTheme
|
||||
defaults.put( destKey, defaults.get( srcKey ) );
|
||||
}
|
||||
|
||||
private static final Set<String> uiKeyExcludes;
|
||||
private static final Set<String> uiKeyDoNotOverride;
|
||||
/** 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). */
|
||||
private static Map<String, String> uiKeyCopying = new HashMap<>();
|
||||
private static Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
private static final Map<String, String> uiKeyCopying = new LinkedHashMap<>();
|
||||
private static final Map<String, String> uiKeyInverseMapping = new HashMap<>();
|
||||
private static final Map<String, String> checkboxKeyMapping = new HashMap<>();
|
||||
private static final Map<String, String> checkboxDuplicateColors = new HashMap<>();
|
||||
|
||||
static {
|
||||
// IntelliJ UI properties that are not used in FlatLaf
|
||||
uiKeyExcludes = new HashSet<>( Arrays.asList(
|
||||
"ActionButton.", "ActionToolbar.", "ActionsList.", "AppInspector.", "AssignedMnemonic.", "Autocomplete.",
|
||||
"AvailableMnemonic.",
|
||||
"BigSpinner.", "Bookmark.", "BookmarkIcon.", "BookmarkMnemonicAssigned.", "BookmarkMnemonicAvailable.",
|
||||
"BookmarkMnemonicCurrent.", "BookmarkMnemonicIcon.", "Borders.", "Breakpoint.",
|
||||
"Canvas.", "CodeWithMe.", "ComboBoxButton.", "CompletionPopup.", "ComplexPopup.", "Content.",
|
||||
"CurrentMnemonic.", "Counter.",
|
||||
"Debugger.", "DebuggerPopup.", "DebuggerTabs.", "DefaultTabs.", "Dialog.", "DialogWrapper.", "DragAndDrop.",
|
||||
"Editor.", "EditorGroupsTabs.", "EditorTabs.",
|
||||
"FileColor.", "FlameGraph.", "Focus.",
|
||||
"Git.", "Github.", "GotItTooltip.", "Group.", "Gutter.", "GutterTooltip.",
|
||||
"HeaderColor.", "HelpTooltip.", "Hg.",
|
||||
"IconBadge.", "InformationHint.", "InplaceRefactoringPopup.",
|
||||
"Lesson.", "Link.", "LiveIndicator.",
|
||||
"MainMenu.", "MainToolbar.", "MemoryIndicator.", "MlModelBinding.", "MnemonicIcon.",
|
||||
"NavBar.", "NewClass.", "NewPSD.", "Notification.", "Notifications.", "NotificationsToolwindow.",
|
||||
"OnePixelDivider.", "OptionButton.", "Outline.",
|
||||
"ParameterInfo.", "Plugins.", "ProgressIcon.", "PsiViewer.",
|
||||
"ReviewList.", "RunWidget.",
|
||||
"ScreenView.", "SearchEverywhere.", "SearchFieldWithExtension.", "SearchMatch.", "SearchOption.",
|
||||
"SearchResults.", "SegmentedButton.", "Settings.", "SidePanel.", "Space.", "SpeedSearch.", "StateWidget.",
|
||||
"StatusBar.",
|
||||
"Tag.", "TipOfTheDay.", "ToolbarComboWidget.", "ToolWindow.",
|
||||
"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."
|
||||
) );
|
||||
|
||||
uiKeyDoNotOverride = new HashSet<>( Arrays.asList(
|
||||
"TabbedPane.selectedForeground"
|
||||
) );
|
||||
|
||||
// ComboBox
|
||||
uiKeyMapping.put( "ComboBox.background", "" ); // ignore
|
||||
uiKeyMapping.put( "ComboBox.buttonBackground", "" ); // ignore
|
||||
uiKeyMapping.put( "ComboBox.nonEditableBackground", "ComboBox.background" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.background", "ComboBox.buttonEditableBackground" );
|
||||
uiKeyMapping.put( "ComboBox.ArrowButton.disabledIconColor", "ComboBox.buttonDisabledArrowColor" );
|
||||
@@ -600,6 +747,11 @@ public class IntelliJTheme
|
||||
uiKeyCopying.put( "Spinner.buttonSeparatorColor", "Component.borderColor" );
|
||||
uiKeyCopying.put( "Spinner.buttonDisabledSeparatorColor", "Component.disabledBorderColor" );
|
||||
|
||||
// TabbedPane
|
||||
uiKeyMapping.put( "DefaultTabs.underlinedTabBackground", "TabbedPane.selectedBackground" );
|
||||
uiKeyMapping.put( "DefaultTabs.underlinedTabForeground", "TabbedPane.selectedForeground" );
|
||||
uiKeyMapping.put( "DefaultTabs.inactiveUnderlineColor", "TabbedPane.inactiveUnderlineColor" );
|
||||
|
||||
// TitlePane
|
||||
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
||||
uiKeyMapping.put( "TitlePane.infoForeground", "TitlePane.foreground" );
|
||||
|
||||
@@ -17,18 +17,22 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Toolkit;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.swing.text.StyleContext;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
@@ -67,7 +71,7 @@ class LinuxFontPolicy
|
||||
if( word.endsWith( "," ) )
|
||||
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" ) )
|
||||
style |= Font.ITALIC;
|
||||
else if( lword.equals( "bold" ) )
|
||||
@@ -103,7 +107,7 @@ class LinuxFontPolicy
|
||||
size = 1;
|
||||
|
||||
// handle logical font names
|
||||
String logicalFamily = mapFcName( family.toLowerCase() );
|
||||
String logicalFamily = mapFcName( family.toLowerCase( Locale.ENGLISH ) );
|
||||
if( logicalFamily != null )
|
||||
family = logicalFamily;
|
||||
|
||||
@@ -121,17 +125,28 @@ class LinuxFontPolicy
|
||||
for(;;) {
|
||||
Font font = createFont( family, style, size, dsize );
|
||||
|
||||
// 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( family ) )
|
||||
return font;
|
||||
|
||||
// if the font family does not match any font on the system, "Dialog" family is returned
|
||||
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 createFont( Font.DIALOG, style, size, dsize );
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
// find last word in family
|
||||
int index = family.lastIndexOf( ' ' );
|
||||
if( index < 0 )
|
||||
return createFont( "Dialog", style, size, dsize );
|
||||
return createFont( Font.DIALOG, style, size, dsize );
|
||||
|
||||
// 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" ) )
|
||||
style |= Font.BOLD;
|
||||
|
||||
@@ -158,7 +173,7 @@ class LinuxFontPolicy
|
||||
|
||||
Object value = Toolkit.getDefaultToolkit().getDesktopProperty( "gnome.Xft/DPI" );
|
||||
if( value instanceof Integer ) {
|
||||
int dpi = ((Integer)value).intValue() / 1024;
|
||||
int dpi = (Integer) value / 1024;
|
||||
if( dpi == -1 )
|
||||
dpi = 96;
|
||||
if( dpi < 50 )
|
||||
@@ -185,10 +200,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
|
||||
* (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.
|
||||
*
|
||||
* The "display scale factor" (kdeglobals: [KScreen] > ScaleFactor) is not used
|
||||
@@ -245,6 +260,7 @@ class LinuxFontPolicy
|
||||
return createFont( family, style, size, dsize );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "MixedMutabilityReturnType" ) // Error Prone
|
||||
private static List<String> readConfig( String filename ) {
|
||||
File userHome = new File( System.getProperty( "user.home" ) );
|
||||
|
||||
@@ -265,8 +281,10 @@ class LinuxFontPolicy
|
||||
|
||||
// read config file
|
||||
ArrayList<String> lines = new ArrayList<>( 200 );
|
||||
try( BufferedReader reader = new BufferedReader( new FileReader( file ) ) ) {
|
||||
String line = null;
|
||||
try( BufferedReader reader = new BufferedReader( new InputStreamReader(
|
||||
new FileInputStream( file ), StandardCharsets.US_ASCII ) ) )
|
||||
{
|
||||
String line;
|
||||
while( (line = reader.readLine()) != null )
|
||||
lines.add( line );
|
||||
} catch( IOException ex ) {
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
|
||||
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( !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 = new SubMenuEventQueue();
|
||||
|
||||
// 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 );
|
||||
|
||||
Toolkit.getDefaultToolkit().getSystemEventQueue().push( this );
|
||||
}
|
||||
|
||||
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
@@ -23,13 +23,13 @@ import java.awt.Graphics2D;
|
||||
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.
|
||||
* <p>
|
||||
* Subclasses do not need to scale icon painting.
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
|
||||
@@ -51,7 +51,7 @@ public class FlatAscendingSortIcon
|
||||
boolean chevron = this.chevron;
|
||||
Color sortIconColor = this.sortIconColor;
|
||||
|
||||
// Because this icons are always shared for all table headers,
|
||||
// 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 ) {
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
@@ -36,6 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatCapsLockIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatCapsLockIcon() {
|
||||
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
|
||||
}
|
||||
@@ -49,22 +54,36 @@ public class FlatCapsLockIcon
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
switch( key ) {
|
||||
case "capsLockIconColor": return color;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="16" height="16" fill="#6E6E6E" rx="3"/>
|
||||
<rect width="6" height="2" x="5" y="11.5" fill="#FFF"/>
|
||||
<path fill="#FFF" d="M2,8 L8,2 L14,8 L11,8 L11,10 L5,10 L5,8 L2,8 Z"/>
|
||||
<rect width="5" height="2" x="5.5" y="11.5" stroke="#FFF" stroke-linejoin="round"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
|
||||
path.append( new Rectangle2D.Float( 5, 11.5f, 6, 2 ), false );
|
||||
path.append( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 11,8, 11,10, 5,10, 5,8 ), false );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
BasicStroke stroke = new BasicStroke( 1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND );
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +172,11 @@ public class FlatCheckBoxIcon
|
||||
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 ) {
|
||||
boolean indeterminate = isIndeterminate( c );
|
||||
@@ -237,7 +242,7 @@ public class FlatCheckBoxIcon
|
||||
}
|
||||
|
||||
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.lineTo( 6.6f, 10f );
|
||||
path.lineTo( 11.25f, 3.5f );
|
||||
|
||||
@@ -59,6 +59,11 @@ public class FlatCheckBoxMenuItemIcon
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||
boolean selected = (c instanceof AbstractButton) && ((AbstractButton)c).isSelected();
|
||||
@@ -71,7 +76,7 @@ public class FlatCheckBoxMenuItemIcon
|
||||
}
|
||||
|
||||
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.lineTo( 6.6f, 10f );
|
||||
path.lineTo( 11.25f, 3.5f );
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.AbstractButton;
|
||||
@@ -47,8 +46,16 @@ public class FlatClearIcon
|
||||
@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 */
|
||||
@@ -61,9 +68,14 @@ public class FlatClearIcon
|
||||
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( c instanceof AbstractButton ) {
|
||||
if( !ignoreButtonState && c instanceof AbstractButton ) {
|
||||
ButtonModel model = ((AbstractButton)c).getModel();
|
||||
if( model.isPressed() || model.isRollover() ) {
|
||||
/*
|
||||
@@ -90,9 +102,11 @@ public class FlatClearIcon
|
||||
|
||||
// paint cross
|
||||
g.setColor( clearIconColor );
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Line2D.Float( 5,5, 11,11 ), false );
|
||||
path.append( new Line2D.Float( 5,11, 11,5 ), false );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,21 +39,25 @@ public class FlatFileChooserDetailsViewIcon
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="2" height="2" x="2" y="3" fill="#6E6E6E"/>
|
||||
<rect width="2" height="2" x="2" y="7" fill="#6E6E6E"/>
|
||||
<rect width="2" height="2" x="2" y="11" fill="#6E6E6E"/>
|
||||
<rect width="8" height="2" x="6" y="3" fill="#6E6E6E"/>
|
||||
<rect width="8" height="2" x="6" y="7" fill="#6E6E6E"/>
|
||||
<rect width="8" height="2" x="6" y="11" fill="#6E6E6E"/>
|
||||
<rect width="2" height="1" x="2" y="3" fill="#6E6E6E" rx=".5"/>
|
||||
<rect width="2" height="1" x="2" y="6" fill="#6E6E6E" rx=".5"/>
|
||||
<rect width="2" height="1" x="2" y="9" fill="#6E6E6E" rx=".5"/>
|
||||
<rect width="2" height="1" x="2" y="12" fill="#6E6E6E" rx=".5"/>
|
||||
<rect width="8" height="1" x="6" y="3" fill="#6E6E6E" rx=".5"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.fillRect( 2, 3, 2, 2 );
|
||||
g.fillRect( 2, 7, 2, 2 );
|
||||
g.fillRect( 2, 11, 2, 2 );
|
||||
g.fillRect( 6, 3, 8, 2 );
|
||||
g.fillRect( 6, 7, 8, 2 );
|
||||
g.fillRect( 6, 11, 8, 2 );
|
||||
g.fillRoundRect( 2, 3, 2, 1, 1, 1 );
|
||||
g.fillRoundRect( 2, 6, 2, 1, 1, 1 );
|
||||
g.fillRoundRect( 2, 9, 2, 1, 1, 1 );
|
||||
g.fillRoundRect( 2, 12, 2, 1, 1, 1 );
|
||||
g.fillRoundRect( 6, 3, 8, 1, 1, 1 );
|
||||
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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
@@ -39,10 +41,22 @@ public class FlatFileChooserHomeFolderIcon
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<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>
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
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">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="4" height="4" x="3" y="3" fill="#6E6E6E"/>
|
||||
<rect width="4" height="4" x="3" y="9" fill="#6E6E6E"/>
|
||||
<rect width="4" height="4" x="9" y="9" fill="#6E6E6E"/>
|
||||
<rect width="4" height="4" x="9" 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="2.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||
<rect width="4" height="4" x="9.5" y="9.5" stroke="#6E6E6E" rx="1.5"/>
|
||||
<rect width="4" height="4" x="9.5" y="2.5" stroke="#6E6E6E" rx="1.5"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.fillRect( 3, 3, 4, 4 );
|
||||
g.fillRect( 3, 9, 4, 4 );
|
||||
g.fillRect( 9, 9, 4, 4 );
|
||||
g.fillRect( 9, 3, 4, 4 );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||
|
||||
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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Line2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "new folder" icon for {@link javax.swing.JFileChooser}.
|
||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatFileChooserNewFolderIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private final Color greenColor = UIManager.getColor( "Actions.Green" );
|
||||
|
||||
public FlatFileChooserNewFolderIcon() {
|
||||
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">
|
||||
<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 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"/>
|
||||
<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"/>
|
||||
<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>
|
||||
</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.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.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( 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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Line2D;
|
||||
import javax.swing.UIManager;
|
||||
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">
|
||||
<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 fill="#389FD6" d="M12,4 L12,8 L10,8 L10,4 L8,4 L11,1 L14,4 L12,4 Z"/>
|
||||
<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"/>
|
||||
<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>
|
||||
</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.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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
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">
|
||||
<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="12" height="2" x="2" y="12" fill="#6E6E6E"/>
|
||||
<rect width="11" height="7" x="2.5" y="3.5" stroke="#6E6E6E" rx="1"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Rectangle2D.Float( 2, 3, 12, 8 ), false );
|
||||
path.append( new Rectangle2D.Float( 4, 5, 8, 4 ), false );
|
||||
g.fill( path );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||
|
||||
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.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
@@ -31,6 +33,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatFileViewDirectoryIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatFileViewDirectoryIcon() {
|
||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||
}
|
||||
@@ -39,10 +43,32 @@ public class FlatFileViewDirectoryIcon
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<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>
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatFileViewFileIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatFileViewFileIcon() {
|
||||
super( 16, 16, UIManager.getColor( "Objects.Grey" ) );
|
||||
}
|
||||
@@ -39,14 +44,33 @@ public class FlatFileViewFileIcon
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
||||
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||
<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"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.RenderingHints;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
@@ -40,18 +41,22 @@ public class FlatFileViewFloppyDriveIcon
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<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"/>
|
||||
<rect width="4" height="2" x="6" y="12" fill="#6E6E6E"/>
|
||||
<g fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||
<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"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( FlatUIUtils.createPath( 11,14, 11,11, 5,11, 5,14, 2,14, 2,2, 14,2, 14,14, 11,14 ), false );
|
||||
path.append( FlatUIUtils.createPath( 4,4, 4,8, 12,8, 12,4, 4,4 ), false );
|
||||
g.fill( path );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||
|
||||
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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
@@ -40,14 +42,19 @@ public class FlatFileViewHardDriveIcon
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
/*
|
||||
<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>
|
||||
*/
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Rectangle2D.Float( 2, 6, 12, 4 ), false );
|
||||
path.append( new Rectangle2D.Float( 12, 8, 1, 1 ), false );
|
||||
path.append( new Rectangle2D.Float( 10, 8, 1, 1 ), false );
|
||||
g.fill( path );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||
|
||||
g.draw( new RoundRectangle2D.Float( 2.5f, 5.5f, 11, 5, 2, 2 ) );
|
||||
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,9 +17,11 @@
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import static com.formdev.flatlaf.util.UIScale.*;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.Map;
|
||||
@@ -84,6 +86,11 @@ public class FlatHelpButtonIcon
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||
/*
|
||||
@@ -91,13 +98,14 @@ public class FlatHelpButtonIcon
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<circle cx="11" cy="11" r="10.5" fill="#6E6E6E"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
boolean enabled = c.isEnabled();
|
||||
boolean focused = FlatUIUtils.isPermanentFocusOwner( c );
|
||||
boolean enabled = c == null || c.isEnabled();
|
||||
boolean focused = c != null && FlatUIUtils.isPermanentFocusOwner( c );
|
||||
|
||||
float xy = 0.5f;
|
||||
float wh = iconSize() - 1;
|
||||
@@ -142,22 +150,19 @@ public class FlatHelpButtonIcon
|
||||
g2.fill( new Ellipse2D.Float( xy, xy, wh, wh ) );
|
||||
|
||||
// paint question mark
|
||||
Path2D q = new Path2D.Float();
|
||||
q.moveTo( 11, 5 );
|
||||
q.curveTo( 8.8,5, 7,6.8, 7,9 );
|
||||
q.lineTo( 9, 9 );
|
||||
q.curveTo( 9,7.9, 9.9,7, 11,7 );
|
||||
q.curveTo( 12.1,7, 13,7.9, 13,9 );
|
||||
q.curveTo( 13,11, 10,10.75, 10,14 );
|
||||
q.lineTo( 12, 14 );
|
||||
q.curveTo( 12,11.75, 15,11.5, 15,9 );
|
||||
q.curveTo( 15,6.8, 13.2,5, 11,5 );
|
||||
q.closePath();
|
||||
Path2D q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||
q.moveTo( 8,8.5 );
|
||||
q.curveTo( 8.25,7, 9.66585007,6, 11,6 );
|
||||
q.curveTo( 12.5,6, 14,7, 14,8.5 );
|
||||
q.curveTo( 14,10.5, 11,11, 11,13 );
|
||||
|
||||
g2.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
g2.setStroke( new BasicStroke( 2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
|
||||
|
||||
g2.translate( focusWidth, focusWidth );
|
||||
g2.setColor( enabled ? questionMarkColor : disabledQuestionMarkColor );
|
||||
g2.fill( q );
|
||||
g2.fillRect( 10, 15, 2, 2 );
|
||||
g2.draw( q );
|
||||
g2.fill( new Ellipse2D.Float( 9.8f, 14.8f, 2.4f, 2.4f ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
@@ -54,13 +53,15 @@ public class FlatInternalFrameCloseIcon
|
||||
|
||||
g.setColor( FlatButtonUI.buttonStateColor( c, c.getForeground(), null, null, hoverForeground, pressedForeground ) );
|
||||
|
||||
float mx = width / 2;
|
||||
float my = height / 2;
|
||||
float mx = width / 2f;
|
||||
float my = height / 2f;
|
||||
float r = 3.25f;
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||
path.moveTo( mx - r, my - r );
|
||||
path.lineTo( mx + r, my + r );
|
||||
path.moveTo( mx - r, my + r );
|
||||
path.lineTo( mx + r, my - r );
|
||||
g.setStroke( new BasicStroke( 1f ) );
|
||||
g.draw( path );
|
||||
}
|
||||
|
||||
@@ -61,9 +61,14 @@ public class FlatMenuArrowIcon
|
||||
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( !c.getComponentOrientation().isLeftToRight() )
|
||||
if( c != null && !c.getComponentOrientation().isLeftToRight() )
|
||||
g.rotate( Math.toRadians( 180 ), width / 2., height / 2. );
|
||||
|
||||
g.setColor( getArrowColor( c ) );
|
||||
@@ -82,7 +87,7 @@ public class FlatMenuArrowIcon
|
||||
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
|
||||
return selectionForeground;
|
||||
|
||||
return c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||
return c == null || c.isEnabled() ? arrowColor : disabledArrowColor;
|
||||
}
|
||||
|
||||
protected boolean isUnderlineSelection() {
|
||||
|
||||
@@ -21,14 +21,16 @@ import java.awt.Graphics;
|
||||
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
|
||||
*/
|
||||
public class FlatMenuItemArrowIcon
|
||||
extends FlatMenuArrowIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
public FlatMenuItemArrowIcon() {
|
||||
super( 6, 10, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
|
||||
/**
|
||||
* "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">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<circle cx="16" cy="16" r="14" fill="#DB5860"/>
|
||||
<rect width="4" height="11" x="14" y="7" fill="#FFF"/>
|
||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
||||
<rect width="4" height="12" x="14" y="7" fill="#FFF" rx="2"/>
|
||||
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneErrorIcon
|
||||
@Override
|
||||
protected Shape createInside() {
|
||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 11 ), false );
|
||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
||||
inside.append( new RoundRectangle2D.Float( 14, 7, 4, 12, 4, 4 ), false );
|
||||
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||
return inside;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.formdev.flatlaf.icons;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
|
||||
/**
|
||||
* "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">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||
<rect width="4" height="11" x="14" y="14" fill="#FFF"/>
|
||||
<rect width="4" height="4" x="14" y="7" fill="#FFF"/>
|
||||
<rect width="4" height="12" x="14" y="13" fill="#FFF" rx="2"/>
|
||||
<circle cx="16" cy="9" r="2" fill="#FFF"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
@@ -54,8 +54,8 @@ public class FlatOptionPaneInformationIcon
|
||||
@Override
|
||||
protected Shape createInside() {
|
||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
inside.append( new Rectangle2D.Float( 14, 14, 4, 11 ), false );
|
||||
inside.append( new Rectangle2D.Float( 14, 7, 4, 4 ), false );
|
||||
inside.append( new RoundRectangle2D.Float( 14, 13, 4, 12, 4, 4 ), false );
|
||||
inside.append( new Ellipse2D.Float( 14, 7, 4, 4 ), false );
|
||||
return inside;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* "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">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<circle cx="16" cy="16" r="14" fill="#389FD6"/>
|
||||
<rect width="4" height="4" x="14" y="22" 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"/>
|
||||
<circle cx="16" cy="24" r="1.7" fill="#FFF"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
@@ -53,21 +53,17 @@ public class FlatOptionPaneQuestionIcon
|
||||
|
||||
@Override
|
||||
protected Shape createInside() {
|
||||
Path2D q = new Path2D.Float();
|
||||
q.moveTo( 14, 20 );
|
||||
q.lineTo( 18, 20 );
|
||||
q.curveTo( 18, 16, 23, 16, 23, 12 );
|
||||
q.curveTo( 23, 8, 20, 6, 16, 6 );
|
||||
q.curveTo( 12, 6, 9, 8, 9, 12 );
|
||||
q.curveTo( 9, 12, 13, 12, 13, 12 );
|
||||
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 q = new Path2D.Float( Path2D.WIND_NON_ZERO, 10 );
|
||||
q.moveTo( 11.5,11.75 );
|
||||
q.curveTo( 11.75,9.5, 13.75,8, 16,8 );
|
||||
q.curveTo( 18.25,8, 20.5,9.5, 20.5,11.75 );
|
||||
q.curveTo( 20.5,14.75, 16,15.5, 16,19 );
|
||||
|
||||
BasicStroke stroke = new BasicStroke( 3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER );
|
||||
|
||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
inside.append( new Rectangle2D.Float( 14, 22, 4, 4 ), false );
|
||||
inside.append( q, false );
|
||||
inside.append( new Ellipse2D.Float( 14.3f, 22.3f, 3.4f, 3.4f ), false );
|
||||
inside.append( stroke.createStrokedShape( q ), false );
|
||||
return inside;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
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">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<polygon fill="#EDA200" points="16 2 31 28 1 28"/>
|
||||
<rect width="4" height="8" x="14" y="10" fill="#FFF"/>
|
||||
<rect width="4" height="4" x="14" y="21" fill="#FFF"/>
|
||||
<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="11" x="14" y="8" fill="#FFF" rx="2"/>
|
||||
<circle cx="16" cy="23" r="2" fill="#FFF"/>
|
||||
</g>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected Shape createOutside() {
|
||||
return FlatUIUtils.createPath( 16,2, 31,28, 1,28 );
|
||||
return FlatUIUtils.createRoundTrianglePath( 16,0, 32,28, 0,28, 4 );
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Shape createInside() {
|
||||
Path2D inside = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
inside.append( new Rectangle2D.Float( 14, 10, 4, 8 ), false );
|
||||
inside.append( new Rectangle2D.Float( 14, 21, 4, 4 ), false );
|
||||
inside.append( new RoundRectangle2D.Float( 14, 8, 4, 11, 4, 4 ), false );
|
||||
inside.append( new Ellipse2D.Float( 14, 21, 4, 4 ), false );
|
||||
return inside;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -45,8 +45,17 @@ public class FlatSearchIcon
|
||||
@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 */
|
||||
@@ -59,6 +68,11 @@ public class FlatSearchIcon
|
||||
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 ) {
|
||||
/*
|
||||
@@ -70,13 +84,17 @@ public class FlatSearchIcon
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.setColor( FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
||||
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||
g.setColor( ignoreButtonState
|
||||
? searchIconColor
|
||||
: FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
||||
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||
|
||||
// paint magnifier
|
||||
Area 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 ) ) );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ public class FlatSearchWithHistoryIcon
|
||||
extends FlatSearchIcon
|
||||
{
|
||||
public FlatSearchWithHistoryIcon() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public FlatSearchWithHistoryIcon( boolean ignoreButtonState ) {
|
||||
super( ignoreButtonState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.Map;
|
||||
import javax.swing.UIManager;
|
||||
@@ -76,6 +75,11 @@ public class FlatTabbedPaneCloseIcon
|
||||
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 ) {
|
||||
// paint background
|
||||
@@ -86,18 +90,20 @@ public class FlatTabbedPaneCloseIcon
|
||||
closeSize.width, closeSize.height, closeArc, closeArc );
|
||||
}
|
||||
|
||||
// set cross color
|
||||
// set color of cross
|
||||
Color fg = FlatButtonUI.buttonStateColor( c, closeForeground, null, null, closeHoverForeground, closePressedForeground );
|
||||
g.setColor( FlatUIUtils.deriveColor( fg, c.getForeground() ) );
|
||||
|
||||
float mx = width / 2;
|
||||
float my = height / 2;
|
||||
float mx = width / 2f;
|
||||
float my = height / 2f;
|
||||
float r = ((bg != null) ? closeCrossFilledSize : closeCrossPlainSize) / 2;
|
||||
|
||||
// paint cross
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
||||
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||
path.moveTo( mx - r, my - r );
|
||||
path.lineTo( mx + r, my + r );
|
||||
path.moveTo( mx - r, my + r );
|
||||
path.lineTo( mx + r, my - r );
|
||||
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
||||
g.draw( path );
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@ package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
/**
|
||||
* "closed" icon for {@link javax.swing.JTree} used by {@link javax.swing.tree.DefaultTreeCellRenderer}.
|
||||
@@ -31,6 +32,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatTreeClosedIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatTreeClosedIcon() {
|
||||
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) );
|
||||
}
|
||||
@@ -41,10 +44,14 @@ public class FlatTreeClosedIcon
|
||||
|
||||
/*
|
||||
<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>
|
||||
*/
|
||||
|
||||
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,9 +16,11 @@
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -39,6 +41,7 @@ public class FlatTreeCollapsedIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private final boolean chevron;
|
||||
private Path2D path;
|
||||
|
||||
public FlatTreeCollapsedIcon() {
|
||||
this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
|
||||
@@ -59,10 +62,15 @@ public class FlatTreeCollapsedIcon
|
||||
|
||||
if( chevron ) {
|
||||
// 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 {
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +84,7 @@ public class FlatTreeCollapsedIcon
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this icons are always shared for all trees,
|
||||
* 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 ) {
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
|
||||
package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
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}.
|
||||
@@ -42,13 +46,22 @@ public class FlatTreeLeafIcon
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<polygon fill="#6E6E6E" points="8 6 8 1 13 1 13 15 3 15 3 6"/>
|
||||
<polygon fill="#6E6E6E" points="3 5 7 5 7 1"/>
|
||||
<rect width="11" height="13" x="2.5" y="1.5" stroke="#6E6E6E" rx="1.5"/>
|
||||
<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>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.fill( FlatUIUtils.createPath( 8,6, 8,1, 13,1, 13,15, 3,15, 3,6 ) );
|
||||
g.fill( FlatUIUtils.createPath( 3,5, 7,5, 7,1 ) );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
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;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
|
||||
@@ -31,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
public class FlatTreeOpenIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private Path2D path;
|
||||
|
||||
public FlatTreeOpenIcon() {
|
||||
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) );
|
||||
}
|
||||
@@ -41,14 +46,38 @@ public class FlatTreeOpenIcon
|
||||
|
||||
/*
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<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>
|
||||
<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"/>
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.fill( FlatUIUtils.createPath( 1,2, 6,2, 8,4, 14,4, 14,6, 3.5,6, 1,11 ) );
|
||||
g.fill( FlatUIUtils.createPath( 4,7, 16,7, 13,13, 1,13 ) );
|
||||
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.UIManager;
|
||||
import java.awt.RenderingHints;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
@@ -29,6 +29,7 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
* Base class for window icons.
|
||||
*
|
||||
* @uiDefault TitlePane.buttonSize Dimension
|
||||
* @uiDefault TitlePane.buttonSymbolHeight int
|
||||
* @uiDefault TitlePane.buttonHoverBackground Color
|
||||
* @uiDefault TitlePane.buttonPressedBackground Color
|
||||
*
|
||||
@@ -37,17 +38,22 @@ import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
public abstract class FlatWindowAbstractIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
private final int symbolHeight;
|
||||
private final Color hoverBackground;
|
||||
private final Color pressedBackground;
|
||||
|
||||
public FlatWindowAbstractIcon() {
|
||||
this( UIManager.getDimension( "TitlePane.buttonSize" ),
|
||||
UIManager.getColor( "TitlePane.buttonHoverBackground" ),
|
||||
UIManager.getColor( "TitlePane.buttonPressedBackground" ) );
|
||||
/** @since 3.2 */
|
||||
protected FlatWindowAbstractIcon( String windowStyle ) {
|
||||
this( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonHoverBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.buttonPressedBackground", windowStyle ) );
|
||||
}
|
||||
|
||||
public FlatWindowAbstractIcon( Dimension size, Color hoverBackground, Color pressedBackground ) {
|
||||
/** @since 3.2 */
|
||||
protected FlatWindowAbstractIcon( Dimension size, int symbolHeight, Color hoverBackground, Color pressedBackground ) {
|
||||
super( size.width, size.height, null );
|
||||
this.symbolHeight = symbolHeight;
|
||||
this.hoverBackground = hoverBackground;
|
||||
this.pressedBackground = pressedBackground;
|
||||
}
|
||||
@@ -65,12 +71,23 @@ public abstract class FlatWindowAbstractIcon
|
||||
protected void paintBackground( Component c, Graphics2D g ) {
|
||||
Color background = FlatButtonUI.buttonStateColor( c, null, null, null, hoverBackground, pressedBackground );
|
||||
if( background != null ) {
|
||||
// disable antialiasing for background rectangle painting to avoid blurry edges when scaled (e.g. at 125% or 175%)
|
||||
Object oldHint = g.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
|
||||
|
||||
g.setColor( FlatUIUtils.deriveColor( background, c.getBackground() ) );
|
||||
g.fillRect( 0, 0, width, height );
|
||||
|
||||
g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, oldHint );
|
||||
}
|
||||
}
|
||||
|
||||
protected Color getForeground( Component c ) {
|
||||
return c.getForeground();
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
protected int getSymbolHeight() {
|
||||
return symbolHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import javax.swing.UIManager;
|
||||
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "close" icon for windows (frames and dialogs).
|
||||
@@ -38,27 +38,38 @@ import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||
public class FlatWindowCloseIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
private final Color hoverForeground = UIManager.getColor( "TitlePane.closeHoverForeground" );
|
||||
private final Color pressedForeground = UIManager.getColor( "TitlePane.closePressedForeground" );
|
||||
private final Color hoverForeground;
|
||||
private final Color pressedForeground;
|
||||
|
||||
public FlatWindowCloseIcon() {
|
||||
super( UIManager.getDimension( "TitlePane.buttonSize" ),
|
||||
UIManager.getColor( "TitlePane.closeHoverBackground" ),
|
||||
UIManager.getColor( "TitlePane.closePressedBackground" ) );
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowCloseIcon( String windowStyle ) {
|
||||
super( FlatUIUtils.getSubUIDimension( "TitlePane.buttonSize", windowStyle ),
|
||||
FlatUIUtils.getSubUIInt( "TitlePane.buttonSymbolHeight", windowStyle, 10 ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closeHoverBackground", windowStyle ),
|
||||
FlatUIUtils.getSubUIColor( "TitlePane.closePressedBackground", windowStyle ) );
|
||||
|
||||
hoverForeground = FlatUIUtils.getSubUIColor( "TitlePane.closeHoverForeground", windowStyle );
|
||||
pressedForeground = FlatUIUtils.getSubUIColor( "TitlePane.closePressedForeground", windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int ix2 = ix + iwh - 1;
|
||||
int iy2 = iy + iwh - 1;
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Line2D.Float( ix, iy, ix2, iy2 ), false );
|
||||
path.append( new Line2D.Float( ix, iy2, ix2, iy ), false );
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD, 4 );
|
||||
path.moveTo( ix, iy );
|
||||
path.lineTo( ix2, iy2 );
|
||||
path.moveTo( ix, iy2 );
|
||||
path.lineTo( ix2, iy );
|
||||
g.setStroke( new BasicStroke( thickness ) );
|
||||
g.draw( path );
|
||||
}
|
||||
|
||||
@@ -27,11 +27,17 @@ public class FlatWindowIconifyIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
public FlatWindowIconifyIcon() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowIconifyIcon( String windowStyle ) {
|
||||
super( windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iw = (int) (10 * scaleFactor);
|
||||
int iw = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ih = (int) scaleFactor;
|
||||
int ix = x + ((width - iw) / 2);
|
||||
int iy = y + ((height - ih) / 2);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.icons;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "maximize" icon for windows (frames and dialogs).
|
||||
@@ -28,15 +29,24 @@ public class FlatWindowMaximizeIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
public FlatWindowMaximizeIcon() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowMaximizeIcon( String windowStyle ) {
|
||||
super( windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
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.Rectangle2D;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
/**
|
||||
* "restore" icon for windows (frames and dialogs).
|
||||
@@ -31,25 +32,46 @@ public class FlatWindowRestoreIcon
|
||||
extends FlatWindowAbstractIcon
|
||||
{
|
||||
public FlatWindowRestoreIcon() {
|
||||
this( null );
|
||||
}
|
||||
|
||||
/** @since 3.2 */
|
||||
public FlatWindowRestoreIcon( String windowStyle ) {
|
||||
super( windowStyle );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIconAt1x( Graphics2D g, int x, int y, int width, int height, double scaleFactor ) {
|
||||
int iwh = (int) (10 * scaleFactor);
|
||||
int iwh = (int) (getSymbolHeight() * scaleFactor);
|
||||
int ix = x + ((width - iwh) / 2);
|
||||
int iy = y + ((height - iwh) / 2);
|
||||
int thickness = (int) scaleFactor;
|
||||
float thickness = SystemInfo.isWindows_11_orLater ? (float) scaleFactor : (int) scaleFactor;
|
||||
int arc = Math.max( (int) (1.5 * scaleFactor), 2 );
|
||||
int arcOuter = (int) (arc + (1.5 * scaleFactor));
|
||||
|
||||
int rwh = (int) (8 * scaleFactor);
|
||||
int rwh = (int) ((getSymbolHeight() - 2) * scaleFactor);
|
||||
int ro2 = iwh - rwh;
|
||||
|
||||
Path2D r1 = FlatUIUtils.createRectangle( ix + ro2, iy, rwh, rwh, thickness );
|
||||
Path2D r2 = FlatUIUtils.createRectangle( ix, iy + ro2, rwh, rwh, thickness );
|
||||
// upper-right rectangle
|
||||
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.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 );
|
||||
|
||||
// paint lower-left rectangle
|
||||
g.fill( r2 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,9 +502,9 @@ class JsonParser {
|
||||
}
|
||||
|
||||
private boolean isHexDigit() {
|
||||
return current >= '0' && current <= '9'
|
||||
|| current >= 'a' && current <= 'f'
|
||||
|| current >= 'A' && current <= 'F';
|
||||
return (current >= '0' && current <= '9')
|
||||
|| (current >= 'a' && current <= 'f')
|
||||
|| (current >= 'A' && current <= 'F');
|
||||
}
|
||||
|
||||
private boolean isEndOfText() {
|
||||
|
||||
@@ -69,7 +69,7 @@ public class Location {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
if (!(obj instanceof Location)) {
|
||||
return false;
|
||||
}
|
||||
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.
|
||||
* Otherwise the compiler outputs a warning because this package is opend in module-info.java.
|
||||
* Also when using --patch-module (e.g. from an IDE), an error would occur for empty packages.
|
||||
* 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.
|
||||
*
|
||||
* @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.MouseEvent;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicArrowButton;
|
||||
|
||||
@@ -37,7 +38,7 @@ public class FlatArrowButton
|
||||
extends BasicArrowButton
|
||||
implements UIResource
|
||||
{
|
||||
public static final int DEFAULT_ARROW_WIDTH = 8;
|
||||
public static final int DEFAULT_ARROW_WIDTH = 9;
|
||||
|
||||
protected boolean chevron;
|
||||
protected Color foreground;
|
||||
@@ -48,8 +49,10 @@ public class FlatArrowButton
|
||||
protected Color pressedBackground;
|
||||
|
||||
private int arrowWidth = DEFAULT_ARROW_WIDTH;
|
||||
private float arrowThickness = 1;
|
||||
private float xOffset = 0;
|
||||
private float yOffset = 0;
|
||||
private boolean roundBorderAutoXOffset = true;
|
||||
|
||||
private boolean hover;
|
||||
private boolean pressed;
|
||||
@@ -82,14 +85,18 @@ public class FlatArrowButton
|
||||
|
||||
@Override
|
||||
public void mousePressed( MouseEvent e ) {
|
||||
pressed = true;
|
||||
repaint();
|
||||
if( SwingUtilities.isLeftMouseButton( e ) ) {
|
||||
pressed = true;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent e ) {
|
||||
pressed = false;
|
||||
repaint();
|
||||
if( SwingUtilities.isLeftMouseButton( e ) ) {
|
||||
pressed = false;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
@@ -116,6 +123,16 @@ public class FlatArrowButton
|
||||
this.arrowWidth = arrowWidth;
|
||||
}
|
||||
|
||||
/** @since 3 */
|
||||
public float getArrowThickness() {
|
||||
return arrowThickness;
|
||||
}
|
||||
|
||||
/** @since 3 */
|
||||
public void setArrowThickness( float arrowThickness ) {
|
||||
this.arrowThickness = arrowThickness;
|
||||
}
|
||||
|
||||
protected boolean isHover() {
|
||||
return hover;
|
||||
}
|
||||
@@ -140,6 +157,16 @@ public class FlatArrowButton
|
||||
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 ) {
|
||||
return background;
|
||||
}
|
||||
@@ -203,14 +230,17 @@ public class FlatArrowButton
|
||||
}
|
||||
|
||||
protected void paintArrow( Graphics2D g ) {
|
||||
boolean vert = (direction == NORTH || direction == SOUTH);
|
||||
int x = 0;
|
||||
|
||||
// move arrow for round borders
|
||||
Container parent = getParent();
|
||||
if( vert && parent instanceof JComponent && FlatUIUtils.hasRoundBorder( (JComponent) parent ) )
|
||||
x -= scale( parent.getComponentOrientation().isLeftToRight() ? 1 : -1 );
|
||||
if( isRoundBorderAutoXOffset() ) {
|
||||
Container parent = getParent();
|
||||
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() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JViewport;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicBorders;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
@@ -101,6 +100,12 @@ public class FlatBorder
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
@@ -130,7 +135,7 @@ public class FlatBorder
|
||||
Paint borderColor = (outlineColor != null) ? outlineColor : getBorderColor( c );
|
||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||
focusWidth, 1, focusInnerWidth, borderWidth, arc,
|
||||
focusColor, borderColor, null );
|
||||
focusColor, borderColor, null, c instanceof JScrollPane );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
@@ -189,8 +194,7 @@ public class FlatBorder
|
||||
protected boolean isEnabled( Component c ) {
|
||||
if( c instanceof JScrollPane ) {
|
||||
// check whether view component is disabled
|
||||
JViewport viewport = ((JScrollPane)c).getViewport();
|
||||
Component view = (viewport != null) ? viewport.getView() : null;
|
||||
Component view = FlatScrollPaneUI.getView( (JScrollPane) c );
|
||||
if( view != null && !isEnabled( view ) )
|
||||
return false;
|
||||
}
|
||||
@@ -273,7 +277,7 @@ public class FlatBorder
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (unscaled) arc diameter of the border.
|
||||
* Returns the (unscaled) arc diameter of the border corners.
|
||||
*/
|
||||
protected int getArc( Component c ) {
|
||||
return 0;
|
||||
|
||||
@@ -42,6 +42,13 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault Button.disabledBorderColor Color
|
||||
* @uiDefault Button.focusedBorderColor Color
|
||||
* @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
|
||||
@@ -49,6 +56,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault Button.default.endBorderColor Color optional; if set, a gradient paint is used
|
||||
* @uiDefault Button.default.focusedBorderColor Color
|
||||
* @uiDefault Button.default.focusColor Color
|
||||
* @uiDefault Button.default.pressedBorderColor Color optional
|
||||
* @uiDefault Button.default.hoverBorderColor Color optional
|
||||
*
|
||||
* @uiDefault Button.toolbar.focusWidth int or float optional; default is 1.5
|
||||
@@ -65,6 +73,13 @@ public class FlatButtonBorder
|
||||
|
||||
protected Color endBorderColor = UIManager.getColor( "Button.endBorderColor" );
|
||||
@Styleable protected Color hoverBorderColor = UIManager.getColor( "Button.hoverBorderColor" );
|
||||
/** @since 3.5 */ @Styleable protected Color pressedBorderColor = UIManager.getColor( "Button.pressedBorderColor" );
|
||||
|
||||
/** @since 3.5 */ @Styleable protected Color selectedBorderColor = UIManager.getColor( "Button.selectedBorderColor" );
|
||||
/** @since 3.5 */ @Styleable protected Color disabledSelectedBorderColor = UIManager.getColor( "Button.disabledSelectedBorderColor" );
|
||||
/** @since 3.5 */ @Styleable protected Color focusedSelectedBorderColor = UIManager.getColor( "Button.focusedSelectedBorderColor" );
|
||||
/** @since 3.5 */ @Styleable protected Color hoverSelectedBorderColor = UIManager.getColor( "Button.hoverSelectedBorderColor" );
|
||||
/** @since 3.5 */ @Styleable protected Color pressedSelectedBorderColor = UIManager.getColor( "Button.pressedSelectedBorderColor" );
|
||||
|
||||
@Styleable(dot=true) protected float defaultBorderWidth = FlatUIUtils.getUIFloat( "Button.default.borderWidth", 1 );
|
||||
@Styleable(dot=true) protected Color defaultBorderColor = FlatUIUtils.getUIColor( "Button.default.startBorderColor", "Button.default.borderColor" );
|
||||
@@ -72,6 +87,7 @@ public class FlatButtonBorder
|
||||
@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" );
|
||||
@@ -139,12 +155,13 @@ public class FlatButtonBorder
|
||||
@Override
|
||||
protected Paint getBorderColor( Component c ) {
|
||||
boolean def = FlatButtonUI.isDefaultButton( c );
|
||||
boolean selected = (c instanceof AbstractButton && ((AbstractButton)c).isSelected());
|
||||
Paint color = FlatButtonUI.buttonStateColor( c,
|
||||
def ? defaultBorderColor : borderColor,
|
||||
disabledBorderColor,
|
||||
def ? defaultFocusedBorderColor : focusedBorderColor,
|
||||
def ? defaultHoverBorderColor : hoverBorderColor,
|
||||
null );
|
||||
def ? defaultBorderColor : ((selected && selectedBorderColor != null) ? selectedBorderColor : borderColor),
|
||||
(selected && disabledSelectedBorderColor != null) ? disabledSelectedBorderColor : disabledBorderColor,
|
||||
def ? defaultFocusedBorderColor : ((selected && focusedSelectedBorderColor != null) ? focusedSelectedBorderColor : focusedBorderColor),
|
||||
def ? defaultHoverBorderColor : ((selected && hoverSelectedBorderColor != null) ? hoverSelectedBorderColor : hoverBorderColor),
|
||||
def ? defaultPressedBorderColor : ((selected && pressedSelectedBorderColor != null) ? pressedSelectedBorderColor : pressedBorderColor) );
|
||||
|
||||
// change to gradient paint if start/end colors are specified
|
||||
Color startBg = def ? defaultBorderColor : borderColor;
|
||||
@@ -159,7 +176,7 @@ public class FlatButtonBorder
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( FlatButtonUI.isToolBarButton( c ) ) {
|
||||
// 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)
|
||||
? ((AbstractButton)c).getMargin()
|
||||
: null;
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
@@ -28,6 +29,7 @@ import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Map;
|
||||
@@ -38,20 +40,29 @@ import javax.swing.ButtonModel;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.plaf.ButtonUI;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.ToolBarUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicButtonListener;
|
||||
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.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;
|
||||
|
||||
@@ -74,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.endBackground Color optional; if set, a gradient paint is used
|
||||
* @uiDefault Button.focusedBackground Color optional
|
||||
* @uiDefault Button.focusedForeground Color optional
|
||||
* @uiDefault Button.hoverBackground Color optional
|
||||
* @uiDefault Button.hoverForeground Color optional
|
||||
* @uiDefault Button.pressedBackground Color optional
|
||||
* @uiDefault Button.pressedForeground Color optional
|
||||
* @uiDefault Button.selectedBackground Color
|
||||
* @uiDefault Button.selectedForeground Color
|
||||
* @uiDefault Button.disabledBackground Color optional
|
||||
* @uiDefault Button.disabledText Color
|
||||
* @uiDefault Button.disabledSelectedBackground Color
|
||||
* @uiDefault Button.disabledSelectedForeground Color optional
|
||||
* @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.endBackground Color optional; if set, a gradient paint is used
|
||||
* @uiDefault Button.default.foreground Color
|
||||
* @uiDefault Button.default.focusedBackground Color optional
|
||||
* @uiDefault Button.default.focusedForeground Color optional
|
||||
* @uiDefault Button.default.hoverBackground Color optional
|
||||
* @uiDefault Button.default.hoverForeground Color optional
|
||||
* @uiDefault Button.default.pressedBackground Color optional
|
||||
* @uiDefault Button.default.pressedForeground Color optional
|
||||
* @uiDefault Button.default.boldText boolean
|
||||
* @uiDefault Button.paintShadow boolean default is false
|
||||
* @uiDefault Button.shadowWidth int default is 2
|
||||
@@ -95,8 +113,13 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault Button.default.shadowColor Color optional
|
||||
* @uiDefault Button.toolbar.spacingInsets Insets
|
||||
* @uiDefault Button.toolbar.hoverBackground Color
|
||||
* @uiDefault Button.toolbar.hoverForeground Color optional
|
||||
* @uiDefault Button.toolbar.pressedBackground Color
|
||||
* @uiDefault Button.toolbar.pressedForeground Color optional
|
||||
* @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
|
||||
*/
|
||||
@@ -113,20 +136,27 @@ public class FlatButtonUI
|
||||
protected Color startBackground;
|
||||
protected Color endBackground;
|
||||
@Styleable protected Color focusedBackground;
|
||||
/** @since 2.3 */ @Styleable protected Color focusedForeground;
|
||||
@Styleable protected Color hoverBackground;
|
||||
/** @since 2.3 */ @Styleable protected Color hoverForeground;
|
||||
@Styleable protected Color pressedBackground;
|
||||
/** @since 2.3 */ @Styleable protected Color pressedForeground;
|
||||
@Styleable protected Color selectedBackground;
|
||||
@Styleable protected Color selectedForeground;
|
||||
@Styleable protected Color disabledBackground;
|
||||
@Styleable protected Color disabledText;
|
||||
@Styleable protected Color disabledSelectedBackground;
|
||||
/** @since 2.3 */ @Styleable protected Color disabledSelectedForeground;
|
||||
|
||||
@Styleable(dot=true) protected Color defaultBackground;
|
||||
protected Color defaultEndBackground;
|
||||
@Styleable(dot=true) protected Color defaultForeground;
|
||||
@Styleable(dot=true) protected Color defaultFocusedBackground;
|
||||
/** @since 2.3 */ @Styleable(dot=true) protected Color defaultFocusedForeground;
|
||||
@Styleable(dot=true) protected Color defaultHoverBackground;
|
||||
/** @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;
|
||||
|
||||
@Styleable protected boolean paintShadow;
|
||||
@@ -135,8 +165,13 @@ public class FlatButtonUI
|
||||
@Styleable(dot=true) protected Color defaultShadowColor;
|
||||
|
||||
@Styleable(dot=true) protected Color toolbarHoverBackground;
|
||||
/** @since 2.3 */ @Styleable(dot=true) protected Color toolbarHoverForeground;
|
||||
@Styleable(dot=true) protected Color toolbarPressedBackground;
|
||||
/** @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;
|
||||
@@ -153,7 +188,7 @@ public class FlatButtonUI
|
||||
private AtomicBoolean borderShared;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return FlatUIUtils.canUseSharedUI( c )
|
||||
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||
? FlatUIUtils.createSharedUI( FlatButtonUI.class, () -> new FlatButtonUI( true ) )
|
||||
: new FlatButtonUI( false );
|
||||
}
|
||||
@@ -165,6 +200,13 @@ public class FlatButtonUI
|
||||
|
||||
@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 );
|
||||
@@ -186,20 +228,27 @@ public class FlatButtonUI
|
||||
startBackground = UIManager.getColor( prefix + "startBackground" );
|
||||
endBackground = UIManager.getColor( prefix + "endBackground" );
|
||||
focusedBackground = UIManager.getColor( prefix + "focusedBackground" );
|
||||
focusedForeground = UIManager.getColor( prefix + "focusedForeground" );
|
||||
hoverBackground = UIManager.getColor( prefix + "hoverBackground" );
|
||||
hoverForeground = UIManager.getColor( prefix + "hoverForeground" );
|
||||
pressedBackground = UIManager.getColor( prefix + "pressedBackground" );
|
||||
pressedForeground = UIManager.getColor( prefix + "pressedForeground" );
|
||||
selectedBackground = UIManager.getColor( prefix + "selectedBackground" );
|
||||
selectedForeground = UIManager.getColor( prefix + "selectedForeground" );
|
||||
disabledBackground = UIManager.getColor( prefix + "disabledBackground" );
|
||||
disabledText = UIManager.getColor( prefix + "disabledText" );
|
||||
disabledSelectedBackground = UIManager.getColor( prefix + "disabledSelectedBackground" );
|
||||
disabledSelectedForeground = UIManager.getColor( prefix + "disabledSelectedForeground" );
|
||||
|
||||
defaultBackground = FlatUIUtils.getUIColor( "Button.default.startBackground", "Button.default.background" );
|
||||
defaultEndBackground = UIManager.getColor( "Button.default.endBackground" );
|
||||
defaultForeground = UIManager.getColor( "Button.default.foreground" );
|
||||
defaultFocusedBackground = UIManager.getColor( "Button.default.focusedBackground" );
|
||||
defaultFocusedForeground = UIManager.getColor( "Button.default.focusedForeground" );
|
||||
defaultHoverBackground = UIManager.getColor( "Button.default.hoverBackground" );
|
||||
defaultHoverForeground = UIManager.getColor( "Button.default.hoverForeground" );
|
||||
defaultPressedBackground = UIManager.getColor( "Button.default.pressedBackground" );
|
||||
defaultPressedForeground = UIManager.getColor( "Button.default.pressedForeground" );
|
||||
defaultBoldText = UIManager.getBoolean( "Button.default.boldText" );
|
||||
|
||||
paintShadow = UIManager.getBoolean( "Button.paintShadow" );
|
||||
@@ -208,8 +257,13 @@ public class FlatButtonUI
|
||||
defaultShadowColor = UIManager.getColor( "Button.default.shadowColor" );
|
||||
|
||||
toolbarHoverBackground = UIManager.getColor( prefix + "toolbar.hoverBackground" );
|
||||
toolbarHoverForeground = UIManager.getColor( prefix + "toolbar.hoverForeground" );
|
||||
toolbarPressedBackground = UIManager.getColor( prefix + "toolbar.pressedBackground" );
|
||||
toolbarPressedForeground = UIManager.getColor( prefix + "toolbar.pressedForeground" );
|
||||
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" );
|
||||
defaultMargin = UIManager.getInsets( prefix + "margin" );
|
||||
@@ -248,6 +302,10 @@ public class FlatButtonUI
|
||||
|
||||
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case BasicHTML.propertyKey:
|
||||
FlatHTML.updateRendererCSSFontBaseSize( b );
|
||||
break;
|
||||
|
||||
case SQUARE_SIZE:
|
||||
case MINIMUM_WIDTH:
|
||||
case MINIMUM_HEIGHT:
|
||||
@@ -256,19 +314,23 @@ public class FlatButtonUI
|
||||
|
||||
case BUTTON_TYPE:
|
||||
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 applyStyle() from installUI()
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
b.updateUI();
|
||||
} else
|
||||
installStyle( b );
|
||||
b.revalidate();
|
||||
b.repaint();
|
||||
HiDPIUtils.repaint( b );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -308,6 +370,9 @@ public class FlatButtonUI
|
||||
return ((FlatHelpButtonIcon)helpButtonIcon).applyStyleProperty( key, value );
|
||||
}
|
||||
|
||||
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 );
|
||||
@@ -322,6 +387,18 @@ public class FlatButtonUI
|
||||
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 ) {
|
||||
return !(c instanceof AbstractButton) || ((AbstractButton)c).isContentAreaFilled();
|
||||
}
|
||||
@@ -336,7 +413,7 @@ public class FlatButtonUI
|
||||
|
||||
/**
|
||||
* 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 ) {
|
||||
if( !(c instanceof JButton) && !(c instanceof JToggleButton) )
|
||||
@@ -420,11 +497,21 @@ public class FlatButtonUI
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
boolean isToolBarButton = isToolBarButton( c );
|
||||
float focusWidth = isToolBarButton ? 0 : FlatUIUtils.getBorderFocusWidth( 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 y = 0;
|
||||
@@ -437,8 +524,15 @@ public class FlatButtonUI
|
||||
y += spacing.top;
|
||||
width -= spacing.left + spacing.right;
|
||||
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
|
||||
Color shadowColor = def ? defaultShadowColor : this.shadowColor;
|
||||
if( paintShadow &&
|
||||
@@ -465,9 +559,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
|
||||
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
|
||||
@@ -503,11 +657,14 @@ public class FlatButtonUI
|
||||
|
||||
// selected state
|
||||
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
|
||||
return buttonStateColor( c,
|
||||
toolBarButton ? toolbarSelectedBackground : selectedBackground,
|
||||
toolBarButton ? toolbarSelectedBackground : disabledSelectedBackground,
|
||||
toolBarButton
|
||||
? (toolbarDisabledSelectedBackground != null ? toolbarDisabledSelectedBackground : toolbarSelectedBackground)
|
||||
: disabledSelectedBackground,
|
||||
null,
|
||||
null,
|
||||
toolBarButton ? toolbarPressedBackground : pressedBackground );
|
||||
@@ -534,6 +691,9 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
protected Color getBackgroundBase( JComponent c, boolean def ) {
|
||||
if( FlatUIUtils.isAWTPeer( c ) )
|
||||
return background;
|
||||
|
||||
// use component background if explicitly set
|
||||
Color bg = c.getBackground();
|
||||
if( isCustomBackground( bg ) )
|
||||
@@ -549,6 +709,9 @@ public class FlatButtonUI
|
||||
public static Color buttonStateColor( Component c, Color enabledColor, Color disabledColor,
|
||||
Color focusedColor, Color hoverColor, Color pressedColor )
|
||||
{
|
||||
if( c == null )
|
||||
return enabledColor;
|
||||
|
||||
if( !c.isEnabled() )
|
||||
return disabledColor;
|
||||
|
||||
@@ -569,18 +732,49 @@ public class FlatButtonUI
|
||||
}
|
||||
|
||||
protected Color getForeground( JComponent c ) {
|
||||
if( !c.isEnabled() )
|
||||
return disabledText;
|
||||
Color fg = c.getForeground();
|
||||
boolean toolBarButton = isToolBarButton( c ) || isBorderlessButton( c );
|
||||
|
||||
if( ((AbstractButton)c).isSelected() && !(isToolBarButton( c ) || isBorderlessButton( c )) )
|
||||
return selectedForeground;
|
||||
// selected state
|
||||
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 );
|
||||
}
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
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
|
||||
Color fg = c.getForeground();
|
||||
if( isCustomForeground( fg ) )
|
||||
return fg;
|
||||
|
||||
boolean def = isDefaultButton( c );
|
||||
return def ? defaultForeground : fg;
|
||||
}
|
||||
|
||||
@@ -597,6 +791,9 @@ public class FlatButtonUI
|
||||
if( prefSize == null )
|
||||
return null;
|
||||
|
||||
// increase width when using bold font for default button
|
||||
prefSize.width += defaultBoldPlainWidthDiff( c );
|
||||
|
||||
// make square or apply minimum width/height
|
||||
boolean isIconOnlyOrSingleCharacter = isIconOnlyOrSingleCharacterButton( c );
|
||||
if( clientPropertyBoolean( c, SQUARE_SIZE, squareSize ) ) {
|
||||
@@ -617,11 +814,89 @@ public class FlatButtonUI
|
||||
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 -------------------------------------------
|
||||
|
||||
protected class FlatButtonListener
|
||||
@@ -639,5 +914,32 @@ public class FlatButtonUI
|
||||
super.propertyChange( 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,11 +96,14 @@ public class FlatCaret
|
||||
|
||||
// if text component is focused, then caret and selection are visible,
|
||||
// but when switching theme, the component does not yet have
|
||||
// an highlighter and the selection is not painted
|
||||
// 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 );
|
||||
@@ -233,7 +236,7 @@ public class FlatCaret
|
||||
if( selectAllOnFocusPolicy == null )
|
||||
selectAllOnFocusPolicy = this.selectAllOnFocusPolicy;
|
||||
|
||||
if( SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||
if( selectAllOnFocusPolicy == null || SELECT_ALL_ON_FOCUS_POLICY_NEVER.equals( selectAllOnFocusPolicy ) )
|
||||
return;
|
||||
|
||||
if( !SELECT_ALL_ON_FOCUS_POLICY_ALWAYS.equals( selectAllOnFocusPolicy ) ) {
|
||||
@@ -253,7 +256,14 @@ public class FlatCaret
|
||||
// select all
|
||||
if( c instanceof JFormattedTextField ) {
|
||||
EventQueue.invokeLater( () -> {
|
||||
select( 0, doc.getLength() );
|
||||
// Warning: do not use variables from outside of this runnable
|
||||
// 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 {
|
||||
select( 0, doc.getLength() );
|
||||
|
||||
@@ -16,18 +16,21 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Map;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
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.ui.FlatStylingSupport.UnknownStyleException;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
|
||||
/**
|
||||
@@ -58,9 +61,15 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
*
|
||||
* @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
|
||||
extends BasicCheckBoxMenuItemUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, StyleableLookupProvider
|
||||
{
|
||||
private FlatMenuItemRenderer renderer;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
@@ -89,17 +98,28 @@ public class FlatCheckBoxMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installComponents( JMenuItem menuItem ) {
|
||||
super.installComponents( menuItem );
|
||||
|
||||
// update HTML renderer if necessary
|
||||
FlatHTML.updateRendererCSSFontBaseSize( menuItem );
|
||||
}
|
||||
|
||||
protected FlatMenuItemRenderer createRenderer() {
|
||||
return new FlatMenuItemRenderer( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
|
||||
return FlatStylingSupport.createPropertyChangeListener( c, this::installStyle, super.createPropertyChangeListener( c ) );
|
||||
return FlatHTML.createPropertyChangeListener(
|
||||
FlatStylingSupport.createPropertyChangeListener( c, this::installStyle,
|
||||
super.createPropertyChangeListener( c ) ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -118,29 +138,27 @@ public class FlatCheckBoxMenuItemUI
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( String key, Object value ) {
|
||||
try {
|
||||
return renderer.applyStyleProperty( key, value );
|
||||
} catch ( UnknownStyleException ex ) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
Object oldValue;
|
||||
switch( key ) {
|
||||
// BasicMenuItemUI
|
||||
case "selectionBackground": oldValue = selectionBackground; selectionBackground = (Color) value; return oldValue;
|
||||
case "selectionForeground": oldValue = selectionForeground; selectionForeground = (Color) value; return oldValue;
|
||||
case "disabledForeground": oldValue = disabledForeground; disabledForeground = (Color) value; return oldValue;
|
||||
case "acceleratorForeground": oldValue = acceleratorForeground; acceleratorForeground = (Color) value; return oldValue;
|
||||
case "acceleratorSelectionForeground": oldValue = acceleratorSelectionForeground; acceleratorSelectionForeground = (Color) value; return oldValue;
|
||||
}
|
||||
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, menuItem, key, value );
|
||||
return FlatMenuItemUI.applyStyleProperty( menuItem, this, renderer, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
return FlatMenuItemUI.getStyleableInfos( renderer );
|
||||
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
|
||||
|
||||
@@ -43,7 +43,7 @@ public class FlatCheckBoxUI
|
||||
extends FlatRadioButtonUI
|
||||
{
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return FlatUIUtils.canUseSharedUI( c )
|
||||
return FlatUIUtils.canUseSharedUI( c ) && !FlatUIUtils.needsLightAWTPeer( c )
|
||||
? FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, () -> new FlatCheckBoxUI( true ) )
|
||||
: new FlatCheckBoxUI( false );
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.awt.Component;
|
||||
import java.awt.ComponentOrientation;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
@@ -42,15 +43,18 @@ import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.CellRendererPane;
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.InputMap;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComboBox.KeySelectionManager;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
@@ -69,8 +73,12 @@ import javax.swing.plaf.basic.BasicComboBoxUI;
|
||||
import javax.swing.plaf.basic.BasicComboPopup;
|
||||
import javax.swing.plaf.basic.ComboPopup;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
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.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
|
||||
@@ -86,20 +94,24 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
* @uiDefault ComboBox.padding Insets
|
||||
* @uiDefault ComboBox.squareButton boolean default is true
|
||||
*
|
||||
* <!-- BasicComboPopup -->
|
||||
*
|
||||
* @uiDefault ComboBox.selectionBackground Color
|
||||
* @uiDefault ComboBox.selectionForeground Color
|
||||
*
|
||||
* <!-- FlatComboBoxUI -->
|
||||
*
|
||||
* @uiDefault ComboBox.minimumWidth int
|
||||
* @uiDefault ComboBox.editorColumns int
|
||||
* @uiDefault ComboBox.maximumRowCount int
|
||||
* @uiDefault ComboBox.buttonStyle String auto (default), button or none
|
||||
* @uiDefault ComboBox.buttonStyle String auto (default), button, mac or none
|
||||
* @uiDefault Component.arrowType String chevron (default) or triangle
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault ComboBox.editableBackground Color optional; defaults to ComboBox.background
|
||||
* @uiDefault ComboBox.focusedBackground Color optional
|
||||
* @uiDefault ComboBox.disabledBackground Color
|
||||
* @uiDefault ComboBox.disabledForeground Color
|
||||
* @uiDefault ComboBox.buttonBackground Color
|
||||
* @uiDefault ComboBox.buttonEditableBackground Color
|
||||
* @uiDefault ComboBox.buttonBackground Color optional
|
||||
* @uiDefault ComboBox.buttonEditableBackground Color optional
|
||||
* @uiDefault ComboBox.buttonFocusedBackground Color optional; defaults to ComboBox.focusedBackground
|
||||
* @uiDefault ComboBox.buttonSeparatorWidth int or float optional; defaults to Component.borderWidth
|
||||
* @uiDefault ComboBox.buttonSeparatorColor Color optional
|
||||
@@ -109,19 +121,24 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
* @uiDefault ComboBox.buttonHoverArrowColor Color
|
||||
* @uiDefault ComboBox.buttonPressedArrowColor Color
|
||||
* @uiDefault ComboBox.popupBackground Color optional
|
||||
* @uiDefault ComboBox.popupInsets Insets
|
||||
* @uiDefault ComboBox.selectionInsets Insets
|
||||
* @uiDefault ComboBox.selectionArc int
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@StyleableField( cls=BasicComboBoxUI.class, key="padding" )
|
||||
|
||||
public class FlatComboBoxUI
|
||||
extends BasicComboBoxUI
|
||||
implements StyleableUI
|
||||
implements StyleableUI, StyleableLookupProvider
|
||||
{
|
||||
@Styleable protected int minimumWidth;
|
||||
@Styleable protected int editorColumns;
|
||||
@Styleable protected String buttonStyle;
|
||||
@Styleable protected String arrowType;
|
||||
protected boolean isIntelliJTheme;
|
||||
|
||||
private Color background;
|
||||
@Styleable protected Color editableBackground;
|
||||
@Styleable protected Color focusedBackground;
|
||||
@Styleable protected Color disabledBackground;
|
||||
@@ -139,6 +156,9 @@ public class FlatComboBoxUI
|
||||
@Styleable protected Color buttonPressedArrowColor;
|
||||
|
||||
@Styleable protected Color popupBackground;
|
||||
/** @since 3 */ @Styleable protected Insets popupInsets;
|
||||
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||
/** @since 3 */ @Styleable protected int selectionArc;
|
||||
|
||||
private MouseListener hoverListener;
|
||||
protected boolean hover;
|
||||
@@ -155,8 +175,18 @@ public class FlatComboBoxUI
|
||||
|
||||
@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 );
|
||||
|
||||
// install key selection manager that shows popup when Space key is pressed
|
||||
comboBox.setKeySelectionManager( new FlatKeySelectionManager( comboBox.getKeySelectionManager() ) );
|
||||
|
||||
installStyle();
|
||||
}
|
||||
|
||||
@@ -191,7 +221,7 @@ public class FlatComboBoxUI
|
||||
|
||||
private void repaintArrowButton() {
|
||||
if( arrowButton != null && !comboBox.isEditable() )
|
||||
arrowButton.repaint();
|
||||
HiDPIUtils.repaint( arrowButton );
|
||||
}
|
||||
};
|
||||
comboBox.addMouseListener( hoverListener );
|
||||
@@ -215,8 +245,8 @@ public class FlatComboBoxUI
|
||||
editorColumns = UIManager.getInt( "ComboBox.editorColumns" );
|
||||
buttonStyle = UIManager.getString( "ComboBox.buttonStyle" );
|
||||
arrowType = UIManager.getString( "Component.arrowType" );
|
||||
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
|
||||
|
||||
background = UIManager.getColor( "ComboBox.background" );
|
||||
editableBackground = UIManager.getColor( "ComboBox.editableBackground" );
|
||||
focusedBackground = UIManager.getColor( "ComboBox.focusedBackground" );
|
||||
disabledBackground = UIManager.getColor( "ComboBox.disabledBackground" );
|
||||
@@ -234,6 +264,9 @@ public class FlatComboBoxUI
|
||||
buttonPressedArrowColor = UIManager.getColor( "ComboBox.buttonPressedArrowColor" );
|
||||
|
||||
popupBackground = UIManager.getColor( "ComboBox.popupBackground" );
|
||||
popupInsets = UIManager.getInsets( "ComboBox.popupInsets" );
|
||||
selectionInsets = UIManager.getInsets( "ComboBox.selectionInsets" );
|
||||
selectionArc = UIManager.getInt( "ComboBox.selectionArc" );
|
||||
|
||||
// set maximumRowCount
|
||||
int maximumRowCount = UIManager.getInt( "ComboBox.maximumRowCount" );
|
||||
@@ -249,6 +282,7 @@ public class FlatComboBoxUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
background = null;
|
||||
editableBackground = null;
|
||||
focusedBackground = null;
|
||||
disabledBackground = null;
|
||||
@@ -281,15 +315,21 @@ public class FlatComboBoxUI
|
||||
public void layoutContainer( Container parent ) {
|
||||
super.layoutContainer( parent );
|
||||
|
||||
if( arrowButton != null ) {
|
||||
// on macOS, a Swing combo box is used for AWT component java.awt.Choice
|
||||
// and the font may be (temporary) null
|
||||
|
||||
if( arrowButton != null && comboBox.getFont() != null ) {
|
||||
// limit button width to height of a raw combobox (without insets)
|
||||
FontMetrics fm = comboBox.getFontMetrics( comboBox.getFont() );
|
||||
int maxButtonWidth = fm.getHeight() + scale( padding.top ) + scale( padding.bottom );
|
||||
int minButtonWidth = (maxButtonWidth * 3) / 4;
|
||||
|
||||
// make button square (except if width is limited)
|
||||
Insets insets = getInsets();
|
||||
int buttonWidth = Math.min( parent.getPreferredSize().height - insets.top - insets.bottom, maxButtonWidth );
|
||||
int buttonWidth = Math.min( Math.max( parent.getHeight() - insets.top - insets.bottom, minButtonWidth ), maxButtonWidth );
|
||||
|
||||
if( buttonWidth != arrowButton.getWidth() ) {
|
||||
// set width of arrow button to preferred height of combobox
|
||||
// set width of arrow button
|
||||
int xOffset = comboBox.getComponentOrientation().isLeftToRight()
|
||||
? arrowButton.getWidth() - buttonWidth
|
||||
: 0;
|
||||
@@ -312,15 +352,15 @@ public class FlatComboBoxUI
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {
|
||||
super.focusGained( e );
|
||||
if( comboBox != null && comboBox.isEditable() )
|
||||
comboBox.repaint();
|
||||
if( comboBox != null )
|
||||
HiDPIUtils.repaint( comboBox );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
super.focusLost( e );
|
||||
if( comboBox != null && comboBox.isEditable() )
|
||||
comboBox.repaint();
|
||||
if( comboBox != null )
|
||||
HiDPIUtils.repaint( comboBox );
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -347,11 +387,12 @@ public class FlatComboBoxUI
|
||||
switch( propertyName ) {
|
||||
case PLACEHOLDER_TEXT:
|
||||
if( editor != null )
|
||||
editor.repaint();
|
||||
HiDPIUtils.repaint( editor );
|
||||
break;
|
||||
|
||||
case COMPONENT_ROUND_RECT:
|
||||
comboBox.repaint();
|
||||
case OUTLINE:
|
||||
HiDPIUtils.repaint( comboBox );
|
||||
break;
|
||||
|
||||
case MINIMUM_WIDTH:
|
||||
@@ -362,7 +403,7 @@ public class FlatComboBoxUI
|
||||
case STYLE_CLASS:
|
||||
installStyle();
|
||||
comboBox.revalidate();
|
||||
comboBox.repaint();
|
||||
HiDPIUtils.repaint( comboBox );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -482,13 +523,6 @@ public class FlatComboBoxUI
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( String key, Object value ) {
|
||||
// BasicComboBoxUI
|
||||
if( key.equals( "padding" ) ) {
|
||||
Object oldValue = padding;
|
||||
padding = (Insets) value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
if( borderShared == null )
|
||||
borderShared = new AtomicBoolean( true );
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrBorder( this, key, value, comboBox, borderShared );
|
||||
@@ -497,11 +531,21 @@ public class FlatComboBoxUI
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
Map<String, Class<?>> infos = new FlatStylingSupport.StyleableInfosMap<>();
|
||||
infos.put( "padding", Insets.class );
|
||||
FlatStylingSupport.collectAnnotatedStyleableInfos( this, infos );
|
||||
FlatStylingSupport.collectStyleableInfos( comboBox.getBorder(), infos );
|
||||
return infos;
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, comboBox.getBorder() );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, comboBox.getBorder(), 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
|
||||
@@ -529,7 +573,9 @@ public class FlatComboBoxUI
|
||||
int height = c.getHeight();
|
||||
int arrowX = arrowButton.getX();
|
||||
int arrowWidth = arrowButton.getWidth();
|
||||
boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) && !"none".equals( buttonStyle );
|
||||
boolean paintButton = (comboBox.isEditable() || "button".equals( buttonStyle )) &&
|
||||
!"none".equals( buttonStyle ) &&
|
||||
!isMacStyle();
|
||||
boolean enabled = comboBox.isEnabled();
|
||||
boolean isLeftToRight = comboBox.getComponentOrientation().isLeftToRight();
|
||||
|
||||
@@ -540,24 +586,35 @@ public class FlatComboBoxUI
|
||||
|
||||
// paint arrow button background
|
||||
if( enabled && !isCellRenderer ) {
|
||||
g2.setColor( paintButton
|
||||
Color buttonColor = paintButton
|
||||
? buttonEditableBackground
|
||||
: (buttonFocusedBackground != null || focusedBackground != null) && isPermanentFocusOwner( comboBox )
|
||||
? (buttonFocusedBackground != null ? buttonFocusedBackground : focusedBackground)
|
||||
: buttonBackground );
|
||||
Shape oldClip = g2.getClip();
|
||||
if( isLeftToRight )
|
||||
g2.clipRect( arrowX, 0, width - arrowX, height );
|
||||
else
|
||||
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
|
||||
g2.setClip( oldClip );
|
||||
: buttonBackground;
|
||||
if( buttonColor != null ) {
|
||||
g2.setColor( buttonColor );
|
||||
if( isMacStyle() ) {
|
||||
Insets insets = comboBox.getInsets();
|
||||
int gap = scale( 2 );
|
||||
FlatUIUtils.paintComponentBackground( g2, arrowX + gap, insets.top + gap,
|
||||
arrowWidth - (gap * 2), height - insets.top - insets.bottom - (gap * 2),
|
||||
0, arc - focusWidth );
|
||||
} else {
|
||||
Shape oldClip = g2.getClip();
|
||||
if( isLeftToRight )
|
||||
g2.clipRect( arrowX, 0, width - arrowX, height );
|
||||
else
|
||||
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
|
||||
g2.setClip( oldClip );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// paint vertical line between value and arrow button
|
||||
if( paintButton ) {
|
||||
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
|
||||
if( separatorColor != null ) {
|
||||
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
|
||||
g2.setColor( separatorColor );
|
||||
float lw = scale( buttonSeparatorWidth );
|
||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
||||
@@ -596,7 +653,7 @@ public class FlatComboBoxUI
|
||||
|
||||
boolean shouldValidate = (c instanceof JPanel);
|
||||
|
||||
paddingBorder.install( c );
|
||||
paddingBorder.install( c, 0 );
|
||||
currentValuePane.paintComponent( g, c, comboBox, bounds.x, bounds.y, bounds.width, bounds.height, shouldValidate );
|
||||
paddingBorder.uninstall();
|
||||
|
||||
@@ -611,6 +668,9 @@ public class FlatComboBoxUI
|
||||
|
||||
protected Color getBackground( boolean enabled ) {
|
||||
if( enabled ) {
|
||||
if( FlatUIUtils.isAWTPeer( comboBox ) )
|
||||
return background;
|
||||
|
||||
Color background = comboBox.getBackground();
|
||||
|
||||
// always use explicitly set color
|
||||
@@ -623,7 +683,7 @@ public class FlatComboBoxUI
|
||||
|
||||
return (editableBackground != null && comboBox.isEditable()) ? editableBackground : background;
|
||||
} else
|
||||
return isIntelliJTheme ? FlatUIUtils.getParentBackground( comboBox ) : disabledBackground;
|
||||
return disabledBackground;
|
||||
}
|
||||
|
||||
protected Color getForeground( boolean enabled ) {
|
||||
@@ -670,7 +730,7 @@ public class FlatComboBoxUI
|
||||
|
||||
@Override
|
||||
protected Dimension getSizeForComponent( Component comp ) {
|
||||
paddingBorder.install( comp );
|
||||
paddingBorder.install( comp, 0 );
|
||||
Dimension size = super.getSizeForComponent( comp );
|
||||
paddingBorder.uninstall();
|
||||
return size;
|
||||
@@ -686,6 +746,10 @@ public class FlatComboBoxUI
|
||||
return parentParent != null && !comboBox.getBackground().equals( parentParent.getBackground() );
|
||||
}
|
||||
|
||||
private boolean isMacStyle() {
|
||||
return "mac".equals( buttonStyle );
|
||||
}
|
||||
|
||||
/** @since 1.3 */
|
||||
public static boolean isPermanentFocusOwner( JComboBox<?> comboBox ) {
|
||||
if( comboBox.isEditable() ) {
|
||||
@@ -693,7 +757,7 @@ public class FlatComboBoxUI
|
||||
return true;
|
||||
|
||||
Component editorComponent = comboBox.getEditor().getEditorComponent();
|
||||
return (editorComponent != null) ? FlatUIUtils.isPermanentFocusOwner( editorComponent ) : false;
|
||||
return editorComponent != null && FlatUIUtils.isPermanentFocusOwner( editorComponent );
|
||||
} else
|
||||
return FlatUIUtils.isPermanentFocusOwner( comboBox );
|
||||
}
|
||||
@@ -720,6 +784,21 @@ public class FlatComboBoxUI
|
||||
buttonHoverArrowColor, null, buttonPressedArrowColor, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArrowWidth() {
|
||||
return isMacStyle() ? (getWidth() % 2 == 0 ? 6 : 7) : super.getArrowWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getArrowThickness() {
|
||||
return isMacStyle() ? 1.5f : super.getArrowThickness();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRoundBorderAutoXOffset() {
|
||||
return isMacStyle() ? false : super.isRoundBorderAutoXOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isHover() {
|
||||
return super.isHover() || (!comboBox.isEditable() ? hover : false);
|
||||
@@ -737,6 +816,20 @@ public class FlatComboBoxUI
|
||||
|
||||
return super.getArrowColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintArrow( Graphics2D g ) {
|
||||
if( isMacStyle() && !comboBox.isEditable() ) {
|
||||
// for style "mac", paint up and down arrows if combobox is not editable
|
||||
int height = getHeight();
|
||||
int h = Math.round( height / 2f );
|
||||
FlatUIUtils.paintArrow( g, 0, 0, getWidth(), h, SwingConstants.NORTH, chevron,
|
||||
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() + 1.25f );
|
||||
FlatUIUtils.paintArrow( g, 0, height - h, getWidth(), h, SwingConstants.SOUTH, chevron,
|
||||
getArrowWidth(), getArrowThickness(), getXOffset(), getYOffset() - 1.25f );
|
||||
} else
|
||||
super.paintArrow( g );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatComboPopup -----------------------------------------------
|
||||
@@ -771,12 +864,19 @@ public class FlatComboBoxUI
|
||||
}
|
||||
}
|
||||
|
||||
// for style "mac", add width of "checked item" icon
|
||||
boolean isPopupOverComboBox = isPopupOverComboBox();
|
||||
int selectedIndex = -1;
|
||||
if( isPopupOverComboBox && (selectedIndex = comboBox.getSelectedIndex()) >= 0 )
|
||||
displayWidth += MacCheckedItemIcon.INSTANCE.getIconWidth() + scale( CellPaddingBorder.MAC_STYLE_GAP );
|
||||
|
||||
// add width of vertical scroll bar
|
||||
JScrollBar verticalScrollBar = scroller.getVerticalScrollBar();
|
||||
if( verticalScrollBar != null )
|
||||
displayWidth += verticalScrollBar.getPreferredSize().width;
|
||||
|
||||
// make popup wider if necessary
|
||||
int pw0 = pw;
|
||||
if( displayWidth > pw ) {
|
||||
// limit popup width to screen width
|
||||
GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
|
||||
@@ -796,6 +896,30 @@ public class FlatComboBoxUI
|
||||
px -= diff;
|
||||
}
|
||||
|
||||
// for style "mac", place popup over combobox
|
||||
Rectangle cellBounds;
|
||||
if( isPopupOverComboBox && selectedIndex >= 0 &&
|
||||
(cellBounds = list.getCellBounds( 0, 0 )) != null )
|
||||
{
|
||||
Insets comboBoxInsets = comboBox.getInsets();
|
||||
Insets listInsets = list.getInsets();
|
||||
Insets popupInsets = getInsets();
|
||||
|
||||
// position popup so that selected item is at same Y position as combobox
|
||||
py -= (cellBounds.height * (selectedIndex + 1)) + comboBoxInsets.top + listInsets.top + popupInsets.top;
|
||||
|
||||
// position popup slightly to the left so that a small part of the right side of the combobox stays visible
|
||||
int offset = Math.min( pw - pw0, MacCheckedItemIcon.INSTANCE.getIconWidth() ) + scale( 4 );
|
||||
if( comboBox.getComponentOrientation().isLeftToRight() )
|
||||
px -= offset + comboBoxInsets.right + listInsets.right;
|
||||
else
|
||||
px += offset + comboBoxInsets.left + listInsets.left;
|
||||
|
||||
// not invoking super.computePopupBounds() here to let
|
||||
// JPopupMenu.adjustPopupLocationToFitScreen() fix the location if necessary
|
||||
return new Rectangle( px, py, pw, ph );
|
||||
}
|
||||
|
||||
return super.computePopupBounds( px, py, pw, ph );
|
||||
}
|
||||
|
||||
@@ -803,17 +927,15 @@ public class FlatComboBoxUI
|
||||
protected void configurePopup() {
|
||||
super.configurePopup();
|
||||
|
||||
// make opaque to avoid that background shines thru border (e.g. at 150% scaling)
|
||||
// make opaque to avoid that background shines through border (e.g. at 150% scaling)
|
||||
setOpaque( true );
|
||||
|
||||
// set popup border
|
||||
// use non-UIResource to avoid that it is overwritten when making
|
||||
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||
Border border = UIManager.getBorder( "PopupMenu.border" );
|
||||
if( border != null )
|
||||
setBorder( border );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureList() {
|
||||
super.configureList();
|
||||
setBorder( FlatUIUtils.nonUIResource( border ) );
|
||||
|
||||
list.setCellRenderer( new PopupListCellRenderer() );
|
||||
updateStyle();
|
||||
@@ -821,7 +943,21 @@ public class FlatComboBoxUI
|
||||
|
||||
void updateStyle() {
|
||||
if( popupBackground != null )
|
||||
list.setBackground( popupBackground );
|
||||
list.setBackground( popupBackground );
|
||||
|
||||
// set popup background because it may shine through when scaled (e.g. at 150%)
|
||||
// use non-UIResource to avoid that it is overwritten when making
|
||||
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||
setBackground( FlatUIUtils.nonUIResource( list.getBackground() ) );
|
||||
|
||||
scroller.setViewportBorder( (popupInsets != null) ? new FlatEmptyBorder( popupInsets ) : null );
|
||||
scroller.setOpaque( false );
|
||||
|
||||
if( list.getUI() instanceof FlatListUI ) {
|
||||
FlatListUI ui = (FlatListUI) list.getUI();
|
||||
ui.selectionInsets = selectionInsets;
|
||||
ui.selectionArc = selectionArc;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -854,6 +990,29 @@ public class FlatComboBoxUI
|
||||
}
|
||||
}
|
||||
|
||||
// improve location of selected item in popup if list is large and scrollable
|
||||
if( list.getHeight() == 0 ) {
|
||||
// If popup is shown for the first time (or after a laf switch) and is scrollable,
|
||||
// then BasicComboPopup scrolls the selected item to the top of the visible area.
|
||||
// But for usability it would be better to have selected item somewhere
|
||||
// in the middle of the visible area so that the user can see items above
|
||||
// the selected item, which are usually more "important".
|
||||
|
||||
int selectedIndex = list.getSelectedIndex();
|
||||
if( selectedIndex >= 1 ) {
|
||||
int maximumRowCount = comboBox.getMaximumRowCount();
|
||||
if( selectedIndex < maximumRowCount ) {
|
||||
// selected item is in the first visible items --> scroll to top
|
||||
list.scrollRectToVisible( new Rectangle() );
|
||||
} else {
|
||||
// scroll the selected item to the middle of the visible area
|
||||
int firstVisibleIndex = Math.max( selectedIndex - (maximumRowCount / 2), 0 );
|
||||
if( firstVisibleIndex > 0 )
|
||||
list.ensureIndexIsVisible( firstVisibleIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.show( invoker, x, y );
|
||||
}
|
||||
|
||||
@@ -863,6 +1022,15 @@ public class FlatComboBoxUI
|
||||
paddingBorder.uninstall();
|
||||
}
|
||||
|
||||
private boolean isPopupOverComboBox() {
|
||||
return isMacStyle() &&
|
||||
!comboBox.isEditable() &&
|
||||
comboBox.getItemCount() > 0 &&
|
||||
comboBox.getItemCount() <= comboBox.getMaximumRowCount() &&
|
||||
// for compatibility with Aqua Laf
|
||||
!clientPropertyBoolean( comboBox, "JComboBox.isPopDown", false );
|
||||
}
|
||||
|
||||
//---- class PopupListCellRenderer -----
|
||||
|
||||
private class PopupListCellRenderer
|
||||
@@ -880,7 +1048,14 @@ public class FlatComboBoxUI
|
||||
Component c = renderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
|
||||
c.applyComponentOrientation( comboBox.getComponentOrientation() );
|
||||
|
||||
paddingBorder.install( c );
|
||||
// style "mac"
|
||||
if( isPopupOverComboBox() && c instanceof JComponent ) {
|
||||
int selectedIndex = comboBox.getSelectedIndex();
|
||||
((JComponent)c).putClientProperty( CellPaddingBorder.KEY_MAC_STYLE_HINT,
|
||||
(selectedIndex >= 0) ? (index == selectedIndex) : null );
|
||||
}
|
||||
|
||||
paddingBorder.install( c, Math.round( FlatUIUtils.getBorderFocusWidth( comboBox ) ) );
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -896,22 +1071,33 @@ public class FlatComboBoxUI
|
||||
* which vertically aligns text in popup list with text in combobox.
|
||||
* <p>
|
||||
* The renderer border is painted on the outer side of this border.
|
||||
* <p>
|
||||
* For button style "mac", also used to increase insets on left side for
|
||||
* "checked item" icon and to paint "checked item" icon for selected combobox item.
|
||||
*/
|
||||
private static class CellPaddingBorder
|
||||
extends AbstractBorder
|
||||
{
|
||||
static final String KEY_MAC_STYLE_HINT = "FlatLaf.internal.FlatComboBoxUI.macStyleHint";
|
||||
static final int MAC_STYLE_GAP = 4;
|
||||
|
||||
private Insets padding;
|
||||
private JComponent rendererComponent;
|
||||
private Border rendererBorder;
|
||||
private int focusWidth;
|
||||
|
||||
CellPaddingBorder( Insets padding ) {
|
||||
this.padding = padding;
|
||||
}
|
||||
|
||||
void install( Component c ) {
|
||||
// using synchronized to avoid problems with code that modifies combo box
|
||||
// (model, selection, etc.) not on AWT thread (which should be not done)
|
||||
synchronized void install( Component c, int focusWidth ) {
|
||||
if( !(c instanceof JComponent) )
|
||||
return;
|
||||
|
||||
this.focusWidth = focusWidth;
|
||||
|
||||
JComponent jc = (JComponent) c;
|
||||
Border oldBorder = jc.getBorder();
|
||||
if( oldBorder == this )
|
||||
@@ -940,10 +1126,12 @@ public class FlatComboBoxUI
|
||||
* there is no single place to uninstall it.
|
||||
* This is the reason why this method is called from various places.
|
||||
*/
|
||||
void uninstall() {
|
||||
synchronized void uninstall() {
|
||||
if( rendererComponent == null )
|
||||
return;
|
||||
|
||||
rendererComponent.putClientProperty( KEY_MAC_STYLE_HINT, null );
|
||||
|
||||
if( rendererComponent.getBorder() == this )
|
||||
rendererComponent.setBorder( rendererBorder );
|
||||
rendererComponent = null;
|
||||
@@ -951,9 +1139,9 @@ public class FlatComboBoxUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
synchronized public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
Insets padding = scale( this.padding );
|
||||
if( rendererBorder != null ) {
|
||||
if( rendererBorder != null && !(rendererBorder instanceof CellPaddingBorder) ) {
|
||||
Insets insideInsets = rendererBorder.getBorderInsets( c );
|
||||
insets.top = Math.max( padding.top, insideInsets.top );
|
||||
insets.left = Math.max( padding.left, insideInsets.left );
|
||||
@@ -965,6 +1153,24 @@ public class FlatComboBoxUI
|
||||
insets.bottom = padding.bottom;
|
||||
insets.right = padding.right;
|
||||
}
|
||||
|
||||
// if used in popup list, add focus width for exact vertical alignment
|
||||
// of text in popup list with text in combobox
|
||||
insets.left += focusWidth;
|
||||
insets.right += focusWidth;
|
||||
|
||||
// style "mac"
|
||||
if( c instanceof JComponent ) {
|
||||
Boolean macStyleHint = clientPropertyBooleanStrict( (JComponent) c, KEY_MAC_STYLE_HINT, null );
|
||||
if( macStyleHint != null ) {
|
||||
int indent = MacCheckedItemIcon.INSTANCE.getIconWidth() + scale( MAC_STYLE_GAP );
|
||||
if( c.getComponentOrientation().isLeftToRight() )
|
||||
insets.left += indent;
|
||||
else
|
||||
insets.right += indent;
|
||||
}
|
||||
}
|
||||
|
||||
return insets;
|
||||
}
|
||||
|
||||
@@ -972,6 +1178,35 @@ public class FlatComboBoxUI
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( rendererBorder != null )
|
||||
rendererBorder.paintBorder( c, g, x, y, width, height );
|
||||
|
||||
// style "mac"
|
||||
if( c instanceof JComponent ) {
|
||||
Boolean macStyleHint = clientPropertyBooleanStrict( (JComponent) c, KEY_MAC_STYLE_HINT, null );
|
||||
if( macStyleHint == Boolean.TRUE ) {
|
||||
// paint "checked item" icon
|
||||
int ix = c.getComponentOrientation().isLeftToRight()
|
||||
? x + scale( padding.left )
|
||||
: x + width - scale( padding.right ) - MacCheckedItemIcon.INSTANCE.getIconWidth();
|
||||
MacCheckedItemIcon.INSTANCE.paintIcon( c, g, ix, y + ((height - MacCheckedItemIcon.INSTANCE.getIconHeight()) / 2) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---- class MacCheckedItemIcon -------------------------------------------
|
||||
|
||||
/**
|
||||
* Use for style "mac" to mark checked item.
|
||||
*/
|
||||
private static class MacCheckedItemIcon
|
||||
extends FlatCheckBoxMenuItemIcon
|
||||
{
|
||||
static MacCheckedItemIcon INSTANCE = new MacCheckedItemIcon();
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g2 ) {
|
||||
g2.setColor( c.getForeground() );
|
||||
paintCheckmark( g2 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1001,4 +1236,46 @@ public class FlatComboBoxUI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatKeySelectionManager --------------------------------------
|
||||
|
||||
/**
|
||||
* Key selection manager that delegates to the default manager.
|
||||
* Shows the popup if Space key is pressed and "typed characters" buffer is empty.
|
||||
* If items contain spaces (e.g. "a b") it is still possible to select them
|
||||
* by pressing keys 'a', 'Space' and 'b'.
|
||||
*/
|
||||
private class FlatKeySelectionManager
|
||||
implements JComboBox.KeySelectionManager, UIResource
|
||||
{
|
||||
private final KeySelectionManager delegate;
|
||||
private final long timeFactor;
|
||||
private long lastTime;
|
||||
|
||||
FlatKeySelectionManager( JComboBox.KeySelectionManager delegate ) {
|
||||
this.delegate = delegate;
|
||||
|
||||
Long value = (Long) UIManager.get( "ComboBox.timeFactor" );
|
||||
timeFactor = (value != null) ? value : 1000;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "rawtypes" )
|
||||
@Override
|
||||
public int selectionForKey( char aKey, ComboBoxModel aModel ) {
|
||||
long time = EventQueue.getMostRecentEventTime();
|
||||
long oldLastTime = lastTime;
|
||||
lastTime = time;
|
||||
|
||||
// SPACE key shows popup if not yet visible
|
||||
if( aKey == ' ' &&
|
||||
time - oldLastTime >= timeFactor &&
|
||||
!comboBox.isPopupVisible() )
|
||||
{
|
||||
comboBox.setPopupVisible( true );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return delegate.selectionForKey( aKey, aModel );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,12 @@ public class FlatDropShadowBorder
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( shadowSize <= 0 )
|
||||
|
||||
@@ -44,8 +44,8 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
* <!-- BasicEditorPaneUI -->
|
||||
*
|
||||
* @uiDefault EditorPane.font Font
|
||||
* @uiDefault EditorPane.background Color also used if not editable
|
||||
* @uiDefault EditorPane.foreground Color
|
||||
* @uiDefault EditorPane.background Color
|
||||
* @uiDefault EditorPane.foreground Color also used if not editable
|
||||
* @uiDefault EditorPane.caretForeground Color
|
||||
* @uiDefault EditorPane.selectionBackground Color
|
||||
* @uiDefault EditorPane.selectionForeground Color
|
||||
@@ -59,7 +59,6 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
* <!-- FlatEditorPaneUI -->
|
||||
*
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault EditorPane.focusedBackground Color optional
|
||||
*
|
||||
* @author Karl Tauber
|
||||
@@ -69,7 +68,6 @@ public class FlatEditorPaneUI
|
||||
implements StyleableUI
|
||||
{
|
||||
@Styleable protected int minimumWidth;
|
||||
protected boolean isIntelliJTheme;
|
||||
private Color background;
|
||||
@Styleable protected Color disabledBackground;
|
||||
@Styleable protected Color inactiveBackground;
|
||||
@@ -101,7 +99,6 @@ public class FlatEditorPaneUI
|
||||
|
||||
String prefix = getPropertyPrefix();
|
||||
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" );
|
||||
@@ -174,7 +171,7 @@ public class FlatEditorPaneUI
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
installStyle.run();
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
HiDPIUtils.repaint( c );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -209,6 +206,12 @@ public class FlatEditorPaneUI
|
||||
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,
|
||||
@@ -246,11 +249,11 @@ public class FlatEditorPaneUI
|
||||
|
||||
@Override
|
||||
protected void paintBackground( Graphics g ) {
|
||||
paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
|
||||
paintBackground( g, getComponent(), focusedBackground );
|
||||
}
|
||||
|
||||
static void paintBackground( Graphics g, JTextComponent c, boolean isIntelliJTheme, Color focusedBackground ) {
|
||||
g.setColor( FlatTextFieldUI.getBackground( c, isIntelliJTheme, focusedBackground ) );
|
||||
static void paintBackground( Graphics g, JTextComponent c, Color focusedBackground ) {
|
||||
g.setColor( FlatTextFieldUI.getBackground( c, focusedBackground ) );
|
||||
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class FlatEmptyBorder
|
||||
protected static Insets scaleInsets( Component c, Insets insets,
|
||||
int top, int left, int bottom, int right )
|
||||
{
|
||||
boolean leftToRight = left == right || c.getComponentOrientation().isLeftToRight();
|
||||
boolean leftToRight = left == right || c == null || c.getComponentOrientation().isLeftToRight();
|
||||
insets.left = scale( leftToRight ? left : right );
|
||||
insets.top = scale( top );
|
||||
insets.right = scale( leftToRight ? right : left );
|
||||
@@ -76,4 +76,9 @@ public class FlatEmptyBorder
|
||||
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.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
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.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Function;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
@@ -34,12 +47,18 @@ import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.Scrollable;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
import javax.swing.filechooser.FileView;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.metal.MetalFileChooserUI;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
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.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -133,12 +152,22 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault FileChooser.listViewActionLabelText 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
|
||||
*/
|
||||
public class FlatFileChooserUI
|
||||
extends MetalFileChooserUI
|
||||
{
|
||||
private final FlatFileView fileView = new FlatFileView();
|
||||
private FlatShortcutsPanel shortcutsPanel;
|
||||
private JScrollPane shortcutsScrollPane;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatFileChooserUI( (JFileChooser) c );
|
||||
@@ -153,6 +182,29 @@ public class FlatFileChooserUI
|
||||
super.installComponents( 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 ) {
|
||||
@@ -192,6 +244,27 @@ public class FlatFileChooserUI
|
||||
} catch( ArrayIndexOutOfBoundsException ex ) {
|
||||
// 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
|
||||
@@ -250,9 +323,19 @@ public class FlatFileChooserUI
|
||||
return p;
|
||||
}
|
||||
|
||||
/** @since 2.3 */
|
||||
protected FlatShortcutsPanel createShortcutsPanel( JFileChooser fc ) {
|
||||
return new FlatShortcutsPanel( fc );
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
@@ -273,9 +356,12 @@ public class FlatFileChooserUI
|
||||
fileView.clearIconCache();
|
||||
}
|
||||
|
||||
private boolean doNotUseSystemIcons() {
|
||||
private static boolean doNotUseSystemIcons() {
|
||||
// Java 17 32bit craches on Windows when using system icons
|
||||
return SystemInfo.isWindows && SystemInfo.isJava_17_orLater && !SystemInfo.isX86_64;
|
||||
// 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 -------------------------------------------------
|
||||
@@ -292,7 +378,11 @@ public class FlatFileChooserUI
|
||||
|
||||
// get system icon
|
||||
if( f != null ) {
|
||||
icon = getFileChooser().getFileSystemView().getSystemIcon( f );
|
||||
try {
|
||||
icon = getFileChooser().getFileSystemView().getSystemIcon( f );
|
||||
} catch( NullPointerException ex ) {
|
||||
// Java 21 may throw a NPE for exe files that use default Windows exe icon
|
||||
}
|
||||
|
||||
if( icon != null ) {
|
||||
if( icon instanceof ImageIcon )
|
||||
@@ -313,4 +403,267 @@ public class FlatFileChooserUI
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
//---- 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buttonGroup.clearSelection();
|
||||
}
|
||||
|
||||
//---- interface PropertyChangeListener ----
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
switch( e.getPropertyName() ) {
|
||||
case JFileChooser.DIRECTORY_CHANGED_PROPERTY:
|
||||
directoryChanged( fc.getCurrentDirectory() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//---- 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import javax.swing.plaf.ComponentUI;
|
||||
* <!-- FlatTextFieldUI -->
|
||||
*
|
||||
* @uiDefault Component.minimumWidth int
|
||||
* @uiDefault Component.isIntelliJTheme boolean
|
||||
* @uiDefault FormattedTextField.placeholderForeground Color
|
||||
* @uiDefault FormattedTextField.focusedBackground Color optional
|
||||
* @uiDefault FormattedTextField.iconTextGap int optional, default is 4
|
||||
|
||||
164
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
164
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatHTML.java
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
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.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?retiredLocale=de#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();
|
||||
int fontBaseSize = c.getFont().getSize();
|
||||
if( styleSheet.getPointSize( 7 ) != 36f ||
|
||||
styleSheet.getPointSize( 4 ) == fontBaseSize )
|
||||
return;
|
||||
|
||||
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
||||
styleSheet.addRule( "BASE_SIZE " + fontBaseSize );
|
||||
clearViewCaches( view );
|
||||
|
||||
// dumpViews( view, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() ) )
|
||||
FlatHTML.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.print( view.getClass().isAnonymousClass() ? view.getClass().getName() : view.getClass().getSimpleName() );
|
||||
if( view instanceof LabelView ) {
|
||||
LabelView lview = ((LabelView)view);
|
||||
Font font = lview.getFont();
|
||||
Color foreground = lview.getForeground();
|
||||
System.out.printf( " %2d-%-2d %-14s %d #%06x",
|
||||
lview.getStartOffset(), lview.getEndOffset() - 1,
|
||||
font.getName(), font.getSize(),
|
||||
foreground.getRGB() & 0xffffff );
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
int viewCount = view.getViewCount();
|
||||
for( int i = 0; i < viewCount; i++ ) {
|
||||
View child = view.getView( i );
|
||||
dumpViews( child, indent + 1 );
|
||||
}
|
||||
}
|
||||
debug*/
|
||||
}
|
||||
@@ -213,6 +213,13 @@ public class FlatInternalFrameTitlePane
|
||||
case "componentOrientation":
|
||||
applyComponentOrientation( frame.getComponentOrientation() );
|
||||
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 );
|
||||
|
||||
@@ -179,6 +179,32 @@ public class FlatInternalFrameUI
|
||||
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 --------------------------------------
|
||||
|
||||
public static class FlatInternalFrameBorder
|
||||
@@ -233,6 +259,23 @@ public class FlatInternalFrameUI
|
||||
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
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) {
|
||||
|
||||
@@ -22,10 +22,7 @@ import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
@@ -63,6 +60,9 @@ public class FlatLabelUI
|
||||
{
|
||||
@Styleable protected Color disabledForeground;
|
||||
|
||||
// only used via styling (not in UI defaults)
|
||||
/** @since 3.5 */ @Styleable protected int arc = -1;
|
||||
|
||||
private final boolean shared;
|
||||
private boolean defaults_initialized = false;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
@@ -109,27 +109,26 @@ public class FlatLabelUI
|
||||
super.installComponents( c );
|
||||
|
||||
// update HTML renderer if necessary
|
||||
updateHTMLRenderer( c, c.getText(), false );
|
||||
FlatHTML.updateRendererCSSFontBaseSize( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
String name = e.getPropertyName();
|
||||
if( name == "text" || name == "font" || name == "foreground" ) {
|
||||
JLabel label = (JLabel) e.getSource();
|
||||
updateHTMLRenderer( label, label.getText(), true );
|
||||
} else if( name.equals( FlatClientProperties.STYLE ) || name.equals( FlatClientProperties.STYLE_CLASS ) ) {
|
||||
if( name.equals( FlatClientProperties.STYLE ) || name.equals( FlatClientProperties.STYLE_CLASS ) ) {
|
||||
JLabel label = (JLabel) e.getSource();
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( label ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes applyStyle() from installUI()
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
label.updateUI();
|
||||
} else
|
||||
installStyle( label );
|
||||
label.revalidate();
|
||||
label.repaint();
|
||||
} else
|
||||
super.propertyChange( e );
|
||||
HiDPIUtils.repaint( label );
|
||||
}
|
||||
|
||||
super.propertyChange( e );
|
||||
FlatHTML.propertyChange( e );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -158,83 +157,16 @@ public class FlatLabelUI
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether text contains HTML tags that use "absolute-size" keywords
|
||||
* (e.g. "x-large") for font-size in default style sheet
|
||||
* (see javax/swing/text/html/default.css).
|
||||
* If yes, adds a special CSS rule (BASE_SIZE) to the HTML text, which
|
||||
* re-calculates font sizes based on current component font size.
|
||||
*/
|
||||
static void updateHTMLRenderer( JComponent c, String text, boolean always ) {
|
||||
if( BasicHTML.isHTMLString( text ) &&
|
||||
c.getClientProperty( "html.disable" ) != Boolean.TRUE &&
|
||||
needsFontBaseSize( text ) )
|
||||
{
|
||||
// BASE_SIZE rule is parsed in javax.swing.text.html.StyleSheet.addRule()
|
||||
String style = "<style>BASE_SIZE " + c.getFont().getSize() + "</style>";
|
||||
|
||||
String lowerText = text.toLowerCase();
|
||||
int headIndex;
|
||||
int styleIndex;
|
||||
|
||||
int insertIndex;
|
||||
if( (headIndex = lowerText.indexOf( "<head>" )) >= 0 ) {
|
||||
// there is a <head> tag --> insert after <head> tag
|
||||
insertIndex = headIndex + "<head>".length();
|
||||
} else if( (styleIndex = lowerText.indexOf( "<style>" )) >= 0 ) {
|
||||
// there is a <style> tag --> insert before <style> tag
|
||||
insertIndex = styleIndex;
|
||||
} else {
|
||||
// no <head> or <style> tag --> insert <head> tag after <html> tag
|
||||
style = "<head>" + style + "</head>";
|
||||
insertIndex = "<html>".length();
|
||||
}
|
||||
|
||||
text = text.substring( 0, insertIndex )
|
||||
+ style
|
||||
+ text.substring( insertIndex );
|
||||
} else if( !always )
|
||||
return; // not necessary to invoke BasicHTML.updateRenderer()
|
||||
|
||||
BasicHTML.updateRenderer( c, text );
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
private static Set<String> tagsUseFontSizeSet;
|
||||
|
||||
private static boolean needsFontBaseSize( String text ) {
|
||||
if( tagsUseFontSizeSet == null ) {
|
||||
// tags that use font-size in javax/swing/text/html/default.css
|
||||
tagsUseFontSizeSet = new HashSet<>( Arrays.asList(
|
||||
"h1", "h2", "h3", "h4", "h5", "h6", "code", "kbd", "big", "small", "samp" ) );
|
||||
}
|
||||
|
||||
// search for tags in HTML text
|
||||
int textLength = text.length();
|
||||
for( int i = 6; i < textLength - 1; i++ ) {
|
||||
if( text.charAt( i ) == '<' ) {
|
||||
switch( text.charAt( i + 1 ) ) {
|
||||
// first letters of tags in tagsUseFontSizeSet
|
||||
case 'b': case 'B':
|
||||
case 'c': case 'C':
|
||||
case 'h': case 'H':
|
||||
case 'k': case 'K':
|
||||
case 's': case 'S':
|
||||
int tagBegin = i + 1;
|
||||
for( i += 2; i < textLength; i++ ) {
|
||||
if( !Character.isLetterOrDigit( text.charAt( i ) ) ) {
|
||||
String tag = text.substring( tagBegin, i ).toLowerCase();
|
||||
if( tagsUseFontSizeSet.contains( tag ) )
|
||||
return true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
FlatPanelUI.fillRoundedBackground( g, c, arc );
|
||||
paint( g, c );
|
||||
}
|
||||
|
||||
static Graphics createGraphicsHTMLTextYCorrection( Graphics g, JComponent c ) {
|
||||
|
||||
@@ -22,13 +22,21 @@ import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
|
||||
/**
|
||||
* Line border for various components.
|
||||
*
|
||||
* <p>
|
||||
* Paints a scaled (usually 1px thick) line around the component.
|
||||
* The line thickness is not added to the border insets.
|
||||
* The insets should be at least have line thickness (usually 1,1,1,1).
|
||||
* <p>
|
||||
* For {@link javax.swing.JPanel} and {@link javax.swing.JLabel}, this border
|
||||
* can be used paint rounded background (if line color is {@code null}) or
|
||||
* paint rounded line border with rounded background.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
@@ -37,32 +45,76 @@ public class FlatLineBorder
|
||||
{
|
||||
private final Color lineColor;
|
||||
private final float lineThickness;
|
||||
/** @since 2 */ private final int arc;
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor ) {
|
||||
this( insets, lineColor, 1f );
|
||||
this( insets, lineColor, 1f, -1 );
|
||||
}
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness ) {
|
||||
/** @since 2 */
|
||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness, int arc ) {
|
||||
super( insets );
|
||||
this.lineColor = lineColor;
|
||||
this.lineThickness = lineThickness;
|
||||
this.arc = arc;
|
||||
}
|
||||
|
||||
/** @since 3.5 */
|
||||
public FlatLineBorder( Insets insets, int arc ) {
|
||||
this( insets, null, 0, arc );
|
||||
}
|
||||
|
||||
public Color getLineColor() {
|
||||
return lineColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (unscaled) line thickness used to paint the border.
|
||||
* The line thickness does not affect the border insets.
|
||||
*/
|
||||
public float getLineThickness() {
|
||||
return lineThickness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (unscaled) arc diameter of the border corners.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public int getArc() {
|
||||
return arc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( c instanceof JComponent && ((JComponent)c).getClientProperty( FlatPopupFactory.KEY_POPUP_USES_NATIVE_BORDER ) != null )
|
||||
return;
|
||||
|
||||
Color lineColor = getLineColor();
|
||||
float lineThickness = getLineThickness();
|
||||
if( lineColor == null || lineThickness <= 0 )
|
||||
return;
|
||||
|
||||
int arc = getArc();
|
||||
if( arc < 0 ) {
|
||||
// get arc from label or panel
|
||||
ComponentUI ui = (c instanceof JLabel)
|
||||
? ((JLabel)c).getUI()
|
||||
: (c instanceof JPanel ? ((JPanel)c).getUI() : null);
|
||||
if( ui instanceof FlatLabelUI )
|
||||
arc = ((FlatLabelUI)ui).arc;
|
||||
else if( ui instanceof FlatPanelUI )
|
||||
arc = ((FlatPanelUI)ui).arc;
|
||||
|
||||
if( arc < 0 )
|
||||
arc = 0;
|
||||
}
|
||||
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||
0, 0, 0, scale( getLineThickness() ), 0, null, getLineColor(), null );
|
||||
0, 0, 0, scale( lineThickness ), scale( arc ), null, lineColor, null );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import javax.swing.plaf.ListUI;
|
||||
public class FlatListCellBorder
|
||||
extends FlatLineBorder
|
||||
{
|
||||
protected boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||
/** @since 2 */ protected boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||
|
||||
private Component c;
|
||||
|
||||
@@ -72,7 +72,7 @@ public class FlatListCellBorder
|
||||
}
|
||||
|
||||
/**
|
||||
* Because this borders are always shared for all lists,
|
||||
* Because this border is always shared for all lists,
|
||||
* get border specific style from FlatListUI.
|
||||
*/
|
||||
static <T> T getStyleFromListUI( Component c, Function<FlatListUI, T> f ) {
|
||||
@@ -113,7 +113,7 @@ public class FlatListCellBorder
|
||||
|
||||
/**
|
||||
* Border for selected cell that uses margins and paints focus indicator border
|
||||
* if enabled (List.showCellFocusIndicator=true) and exactly one item is selected.
|
||||
* if enabled (List.showCellFocusIndicator=true) and multiple items are selected.
|
||||
*/
|
||||
public static class Selected
|
||||
extends FlatListCellBorder
|
||||
@@ -125,7 +125,7 @@ public class FlatListCellBorder
|
||||
if( !showCellFocusIndicator )
|
||||
return;
|
||||
|
||||
// paint focus indicator border only if exactly one item is selected
|
||||
// paint focus indicator border only if multiple items are selected
|
||||
JList<?> list = (JList<?>) SwingUtilities.getAncestorOfClass( JList.class, c );
|
||||
if( list != null && list.getMinSelectionIndex() == list.getMaxSelectionIndex() )
|
||||
return;
|
||||
|
||||
@@ -17,20 +17,35 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||
import javax.swing.plaf.basic.BasicListUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||
import com.formdev.flatlaf.util.HiDPIUtils;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JList}.
|
||||
@@ -59,6 +74,8 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
*
|
||||
* @uiDefault List.selectionInactiveBackground Color
|
||||
* @uiDefault List.selectionInactiveForeground Color
|
||||
* @uiDefault List.selectionInsets Insets
|
||||
* @uiDefault List.selectionArc int
|
||||
*
|
||||
* <!-- FlatListCellBorder -->
|
||||
*
|
||||
@@ -76,11 +93,13 @@ public class FlatListUI
|
||||
@Styleable protected Color selectionForeground;
|
||||
@Styleable protected Color selectionInactiveBackground;
|
||||
@Styleable protected Color selectionInactiveForeground;
|
||||
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||
/** @since 3 */ @Styleable protected int selectionArc;
|
||||
|
||||
// for FlatListCellBorder
|
||||
@Styleable protected Insets cellMargins;
|
||||
@Styleable protected Color cellFocusColor;
|
||||
@Styleable protected boolean showCellFocusIndicator;
|
||||
/** @since 2 */ @Styleable protected Insets cellMargins;
|
||||
/** @since 2 */ @Styleable protected Color cellFocusColor;
|
||||
/** @since 2 */ @Styleable protected Boolean showCellFocusIndicator;
|
||||
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
@@ -90,6 +109,13 @@ public class FlatListUI
|
||||
|
||||
@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();
|
||||
@@ -103,6 +129,8 @@ public class FlatListUI
|
||||
selectionForeground = UIManager.getColor( "List.selectionForeground" );
|
||||
selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" );
|
||||
selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" );
|
||||
selectionInsets = UIManager.getInsets( "List.selectionInsets" );
|
||||
selectionArc = UIManager.getInt( "List.selectionArc" );
|
||||
|
||||
toggleSelectionColors();
|
||||
}
|
||||
@@ -155,12 +183,35 @@ public class FlatListUI
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
installStyle();
|
||||
list.revalidate();
|
||||
list.repaint();
|
||||
HiDPIUtils.repaint( list );
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListSelectionListener createListSelectionListener() {
|
||||
ListSelectionListener superListener = super.createListSelectionListener();
|
||||
return e -> {
|
||||
superListener.valueChanged( e );
|
||||
|
||||
// for united rounded selection, repaint parts of the rows/columns that adjoin to the changed rows/columns
|
||||
if( useUnitedRoundedSelection( true, true ) &&
|
||||
!list.isSelectionEmpty() &&
|
||||
(list.getMaxSelectionIndex() - list.getMinSelectionIndex()) >= 1 )
|
||||
{
|
||||
int size = list.getModel().getSize();
|
||||
int firstIndex = Math.min( Math.max( e.getFirstIndex(), 0 ), size - 1 );
|
||||
int lastIndex = Math.min( Math.max( e.getLastIndex(), 0 ), size - 1 );
|
||||
Rectangle r = getCellBounds( list, firstIndex, lastIndex );
|
||||
if( r != null ) {
|
||||
int arc = (int) Math.ceil( UIScale.scale( selectionArc / 2f ) );
|
||||
HiDPIUtils.repaint( list, r.x - arc, r.y - arc, r.width + (arc * 2), r.height + (arc * 2) );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle() {
|
||||
try {
|
||||
@@ -209,10 +260,16 @@ public class FlatListUI
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle selection colors from focused to inactive and vice versa.
|
||||
*
|
||||
* This is not a optimal solution but much easier than rewriting the whole paint methods.
|
||||
* This is not an optimal solution but much easier than rewriting the whole paint methods.
|
||||
*
|
||||
* Using a LaF specific renderer was avoided because often a custom renderer is
|
||||
* already used in applications. Then either the inactive colors are not used,
|
||||
@@ -234,4 +291,173 @@ public class FlatListUI
|
||||
list.setSelectionForeground( selectionInactiveForeground );
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( "rawtypes" )
|
||||
@Override
|
||||
protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRenderer cellRenderer,
|
||||
ListModel dataModel, ListSelectionModel selModel, int leadIndex )
|
||||
{
|
||||
boolean isSelected = selModel.isSelectedIndex( row );
|
||||
|
||||
// get renderer component
|
||||
@SuppressWarnings( "unchecked" )
|
||||
Component rendererComponent = cellRenderer.getListCellRendererComponent( list,
|
||||
dataModel.getElementAt( row ), row, isSelected,
|
||||
FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) );
|
||||
|
||||
//
|
||||
boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) );
|
||||
int cx, cw;
|
||||
if( isFileList ) {
|
||||
// see BasicListUI.paintCell()
|
||||
cw = Math.min( rowBounds.width, rendererComponent.getPreferredSize().width + 4 );
|
||||
cx = list.getComponentOrientation().isLeftToRight()
|
||||
? rowBounds.x
|
||||
: rowBounds.x + (rowBounds.width - cw);
|
||||
} else {
|
||||
cx = rowBounds.x;
|
||||
cw = rowBounds.width;
|
||||
}
|
||||
|
||||
// rounded selection or selection insets
|
||||
if( isSelected &&
|
||||
!isFileList && // rounded selection is not supported for file list
|
||||
(rendererComponent instanceof DefaultListCellRenderer ||
|
||||
rendererComponent instanceof BasicComboBoxRenderer) &&
|
||||
(selectionArc > 0 ||
|
||||
(selectionInsets != null && !FlatUIUtils.isInsetsEmpty( selectionInsets ))) )
|
||||
{
|
||||
// Because selection painting is done in the cell renderer, it would be
|
||||
// necessary to require a FlatLaf specific renderer to implement rounded selection.
|
||||
// Using a LaF specific renderer was avoided because often a custom renderer is
|
||||
// already used in applications. Then either the rounded selection is not used,
|
||||
// or the application has to be changed to extend a FlatLaf renderer.
|
||||
//
|
||||
// To solve this, a graphics proxy is used that paints rounded selection
|
||||
// if row is selected and the renderer wants to fill the background.
|
||||
class RoundedSelectionGraphics extends Graphics2DProxy {
|
||||
// used to avoid endless loop in case that paintCellSelection() invokes
|
||||
// g.fillRect() with full bounds (selectionInsets is 0,0,0,0)
|
||||
private boolean inPaintSelection;
|
||||
|
||||
RoundedSelectionGraphics( Graphics delegate ) {
|
||||
super( (Graphics2D) delegate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create() {
|
||||
return new RoundedSelectionGraphics( super.create() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics create( int x, int y, int width, int height ) {
|
||||
return new RoundedSelectionGraphics( super.create( x, y, width, height ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect( int x, int y, int width, int height ) {
|
||||
if( !inPaintSelection &&
|
||||
x == 0 && y == 0 && width == rowBounds.width && height == rowBounds.height &&
|
||||
this.getColor() == rendererComponent.getBackground() )
|
||||
{
|
||||
inPaintSelection = true;
|
||||
paintCellSelection( this, row, x, y, width, height );
|
||||
inPaintSelection = false;
|
||||
} else
|
||||
super.fillRect( x, y, width, height );
|
||||
}
|
||||
}
|
||||
g = new RoundedSelectionGraphics( g );
|
||||
}
|
||||
|
||||
// paint renderer
|
||||
rendererPane.paintComponent( g, rendererComponent, list, cx, rowBounds.y, cw, rowBounds.height, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints (rounded) cell selection.
|
||||
* Supports {@link #selectionArc} and {@link #selectionInsets}.
|
||||
* <p>
|
||||
* <b>Note:</b> This method is only invoked if either selection arc
|
||||
* is greater than zero or if selection insets are not empty.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
protected void paintCellSelection( Graphics g, int row, int x, int y, int width, int height ) {
|
||||
float arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight;
|
||||
arcTopLeft = arcTopRight = arcBottomLeft = arcBottomRight = UIScale.scale( selectionArc / 2f );
|
||||
|
||||
if( list.getLayoutOrientation() == JList.VERTICAL ) {
|
||||
// layout orientation: VERTICAL
|
||||
if( useUnitedRoundedSelection( true, false ) ) {
|
||||
if( row > 0 && list.isSelectedIndex( row - 1 ) )
|
||||
arcTopLeft = arcTopRight = 0;
|
||||
if( row < list.getModel().getSize() - 1 && list.isSelectedIndex( row + 1 ) )
|
||||
arcBottomLeft = arcBottomRight = 0;
|
||||
}
|
||||
} else {
|
||||
// layout orientation: VERTICAL_WRAP or HORIZONTAL_WRAP
|
||||
Rectangle r = null;
|
||||
if( useUnitedRoundedSelection( true, false ) ) {
|
||||
// vertical: check whether cells above or below are selected
|
||||
r = getCellBounds( list, row, row );
|
||||
|
||||
int topIndex = locationToIndex( list, new Point( r.x, r.y - 1 ) );
|
||||
int bottomIndex = locationToIndex( list, new Point( r.x, r.y + r.height ) );
|
||||
|
||||
if( topIndex >= 0 && topIndex != row && list.isSelectedIndex( topIndex ) )
|
||||
arcTopLeft = arcTopRight = 0;
|
||||
if( bottomIndex >= 0 && bottomIndex != row && list.isSelectedIndex( bottomIndex ) )
|
||||
arcBottomLeft = arcBottomRight = 0;
|
||||
}
|
||||
|
||||
if( useUnitedRoundedSelection( false, true ) ) {
|
||||
// horizontal: check whether cells left or right are selected
|
||||
if( r == null )
|
||||
r = getCellBounds( list, row, row );
|
||||
|
||||
int leftIndex = locationToIndex( list, new Point( r.x - 1, r.y ) );
|
||||
int rightIndex = locationToIndex( list, new Point( r.x + r.width, r.y ) );
|
||||
|
||||
// special handling for the case that last column contains fewer cells than the other columns
|
||||
boolean ltr = list.getComponentOrientation().isLeftToRight();
|
||||
if( !ltr && leftIndex >= 0 && leftIndex != row && leftIndex == locationToIndex( list, new Point( r.x - 1, r.y - 1 ) ) )
|
||||
leftIndex = -1;
|
||||
if( ltr && rightIndex >= 0 && rightIndex != row && rightIndex == locationToIndex( list, new Point( r.x + r.width, r.y - 1 ) ) )
|
||||
rightIndex = -1;
|
||||
|
||||
if( leftIndex >= 0 && leftIndex != row && list.isSelectedIndex( leftIndex ) )
|
||||
arcTopLeft = arcBottomLeft = 0;
|
||||
if( rightIndex >= 0 && rightIndex != row && list.isSelectedIndex( rightIndex ) )
|
||||
arcTopRight = arcBottomRight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
FlatUIUtils.paintSelection( (Graphics2D) g, x, y, width, height,
|
||||
UIScale.scale( selectionInsets ), arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight, 0 );
|
||||
}
|
||||
|
||||
private boolean useUnitedRoundedSelection( boolean vertical, boolean horizontal ) {
|
||||
return selectionArc > 0 &&
|
||||
(selectionInsets == null ||
|
||||
(vertical && selectionInsets.top == 0 && selectionInsets.bottom == 0) ||
|
||||
(horizontal && selectionInsets.left == 0 && selectionInsets.right == 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints a cell selection at the given coordinates.
|
||||
* The selection color must be set on the graphics context.
|
||||
* <p>
|
||||
* This method is intended for use in custom cell renderers
|
||||
* to support {@link #selectionArc} and {@link #selectionInsets}.
|
||||
*
|
||||
* @since 3
|
||||
*/
|
||||
public static void paintCellSelection( JList<?> list, Graphics g, int row, int x, int y, int width, int height ) {
|
||||
if( !(list.getUI() instanceof FlatListUI) )
|
||||
return;
|
||||
|
||||
FlatListUI ui = (FlatListUI) list.getUI();
|
||||
ui.paintCellSelection( g, row, x, y, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,12 @@ public class FlatMenuBarBorder
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( !showBottomSeparator( c ) )
|
||||
|
||||
@@ -18,15 +18,17 @@ package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
@@ -36,15 +38,16 @@ import javax.swing.MenuElement;
|
||||
import javax.swing.MenuSelectionManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.ActionMapUIResource;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicMenuBarUI;
|
||||
import javax.swing.plaf.basic.DefaultMenuLayout;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuBar}.
|
||||
@@ -70,7 +73,12 @@ public class FlatMenuBarUI
|
||||
/** @since 2 */ @Styleable protected Insets itemMargins;
|
||||
|
||||
// used in FlatMenuUI
|
||||
/** @since 3 */ @Styleable protected Insets selectionInsets;
|
||||
/** @since 3 */ @Styleable protected Insets selectionEmbeddedInsets;
|
||||
/** @since 3 */ @Styleable protected int selectionArc = -1;
|
||||
/** @since 2 */ @Styleable protected Color hoverBackground;
|
||||
/** @since 2.5 */ @Styleable protected Color selectionBackground;
|
||||
/** @since 2.5 */ @Styleable protected Color selectionForeground;
|
||||
/** @since 2 */ @Styleable protected Color underlineSelectionBackground;
|
||||
/** @since 2 */ @Styleable protected Color underlineSelectionColor;
|
||||
/** @since 2 */ @Styleable protected int underlineSelectionHeight = -1;
|
||||
@@ -100,6 +108,10 @@ public class FlatMenuBarUI
|
||||
super.installDefaults();
|
||||
|
||||
LookAndFeel.installProperty( menuBar, "opaque", false );
|
||||
|
||||
LayoutManager layout = menuBar.getLayout();
|
||||
if( layout == null || layout instanceof UIResource )
|
||||
menuBar.setLayout( new FlatMenuBarLayout( menuBar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,12 +142,10 @@ public class FlatMenuBarUI
|
||||
protected void installKeyboardActions() {
|
||||
super.installKeyboardActions();
|
||||
|
||||
// get shared action map, used for all menu bars
|
||||
ActionMap map = SwingUtilities.getUIActionMap( menuBar );
|
||||
if( map == null ) {
|
||||
map = new ActionMapUIResource();
|
||||
SwingUtilities.replaceUIActionMap( menuBar, map );
|
||||
}
|
||||
map.put( "takeFocus", new TakeFocus() );
|
||||
if( map != null && !(map.get( "takeFocus" ) instanceof TakeFocusAction) )
|
||||
map.put( "takeFocus", new TakeFocusAction( "takeFocus" ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -165,6 +175,12 @@ public class FlatMenuBarUI
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, menuBar.getBorder() );
|
||||
}
|
||||
|
||||
/** @since 2.5 */
|
||||
@Override
|
||||
public Object getStyleableValue( JComponent c, String key ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableValue( this, menuBar.getBorder(), key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
// paint background
|
||||
@@ -180,11 +196,15 @@ public class FlatMenuBarUI
|
||||
protected Color getBackground( JComponent c ) {
|
||||
Color background = c.getBackground();
|
||||
|
||||
// paint background if opaque or if having custom background color
|
||||
if( c.isOpaque() || !(background instanceof UIResource) )
|
||||
// paint background if opaque
|
||||
if( c.isOpaque() )
|
||||
return background;
|
||||
|
||||
// paint background if menu bar is not the "main" menu bar
|
||||
// do not paint background if non-opaque and having custom background color
|
||||
if( !(background instanceof UIResource) )
|
||||
return null;
|
||||
|
||||
// paint background if menu bar is not the "main" menu bar (e.g. in internal frame)
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||
if( rootPane == null || !(rootPane.getParent() instanceof Window) || rootPane.getJMenuBar() != c )
|
||||
return background;
|
||||
@@ -206,7 +226,7 @@ public class FlatMenuBarUI
|
||||
// check whether:
|
||||
// - TitlePane.unifiedBackground is true and
|
||||
// - menu bar is the "main" menu bar and
|
||||
// - window has custom decorations enabled
|
||||
// - window root pane has custom decoration style
|
||||
|
||||
JRootPane rootPane;
|
||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||
@@ -214,19 +234,147 @@ public class FlatMenuBarUI
|
||||
(rootPane = SwingUtilities.getRootPane( c )) != null &&
|
||||
rootPane.getParent() instanceof Window &&
|
||||
rootPane.getJMenuBar() == c &&
|
||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() );
|
||||
rootPane.getWindowDecorationStyle() != JRootPane.NONE;
|
||||
}
|
||||
|
||||
//---- class TakeFocus ----------------------------------------------------
|
||||
//---- class FlatMenuBarLayout --------------------------------------------
|
||||
|
||||
/**
|
||||
* @since 2.4
|
||||
*/
|
||||
protected static class FlatMenuBarLayout
|
||||
extends DefaultMenuLayout
|
||||
{
|
||||
public FlatMenuBarLayout( Container target ) {
|
||||
super( target, BoxLayout.LINE_AXIS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer( Container target ) {
|
||||
super.layoutContainer( target );
|
||||
|
||||
|
||||
// The only purpose of the code below is to make sure that a horizontal glue,
|
||||
// which can be used to move window and displays the window title in embedded menu bar,
|
||||
// is always visible within the menu bar bounds and has a minimum width.
|
||||
// If this is not the case, the horizontal glue is made larger and
|
||||
// components that are on the left side of the glue are made smaller.
|
||||
|
||||
|
||||
// get root pane and check whether this menu bar is the root pane menu bar
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( target );
|
||||
if( rootPane == null || rootPane.getJMenuBar() != target )
|
||||
return;
|
||||
|
||||
// get title pane and check whether menu bar is embedded
|
||||
FlatTitlePane titlePane = FlatRootPaneUI.getTitlePane( rootPane );
|
||||
if( titlePane == null || !titlePane.isMenuBarEmbedded() )
|
||||
return;
|
||||
|
||||
// check whether there is a horizontal glue (used for window title in embedded menu bar)
|
||||
// and check minimum width of horizontal glue
|
||||
Component horizontalGlue = titlePane.findHorizontalGlue( (JMenuBar) target );
|
||||
int minTitleWidth = UIScale.scale( titlePane.titleMinimumWidth );
|
||||
if( horizontalGlue != null && horizontalGlue.getWidth() < minTitleWidth ) {
|
||||
// get index of glue component
|
||||
int glueIndex = -1;
|
||||
Component[] components = target.getComponents();
|
||||
for( int i = components.length - 1; i >= 0; i-- ) {
|
||||
if( components[i] == horizontalGlue ) {
|
||||
glueIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( glueIndex < 0 )
|
||||
return; // should never happen
|
||||
|
||||
if( target.getComponentOrientation().isLeftToRight() ) {
|
||||
// left-to-right
|
||||
|
||||
// make horizontal glue wider (minimum title width)
|
||||
int offset = minTitleWidth - horizontalGlue.getWidth();
|
||||
horizontalGlue.setSize( minTitleWidth, horizontalGlue.getHeight() );
|
||||
|
||||
// check whether glue is fully visible
|
||||
int minGlueX = target.getWidth() - target.getInsets().right - minTitleWidth;
|
||||
if( minGlueX < horizontalGlue.getX() ) {
|
||||
// move glue to the left to make it fully visible
|
||||
offset -= (horizontalGlue.getX() - minGlueX);
|
||||
horizontalGlue.setLocation( minGlueX, horizontalGlue.getY() );
|
||||
|
||||
// shrink and move components that are on the left side of the glue
|
||||
for( int i = glueIndex - 1; i >= 0; i-- ) {
|
||||
Component c = components[i];
|
||||
if( c.getX() > minGlueX ) {
|
||||
// move component and set width to zero
|
||||
c.setBounds( minGlueX, c.getY(), 0, c.getHeight() );
|
||||
} else {
|
||||
// reduce size of component
|
||||
c.setSize( minGlueX - c.getX(), c.getHeight() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move components that are on the right side of the glue
|
||||
for( int i = glueIndex + 1; i < components.length; i++ ) {
|
||||
Component c = components[i];
|
||||
c.setLocation( c.getX() + offset, c.getY() );
|
||||
}
|
||||
} else {
|
||||
// right-to-left
|
||||
|
||||
// make horizontal glue wider (minimum title width)
|
||||
int offset = minTitleWidth - horizontalGlue.getWidth();
|
||||
horizontalGlue.setBounds( horizontalGlue.getX() - offset, horizontalGlue.getY(),
|
||||
minTitleWidth, horizontalGlue.getHeight() );
|
||||
|
||||
// check whether glue is fully visible
|
||||
int minGlueX = target.getInsets().left;
|
||||
if( minGlueX > horizontalGlue.getX() ) {
|
||||
// move glue to the right to make it fully visible
|
||||
offset -= (horizontalGlue.getX() - minGlueX);
|
||||
horizontalGlue.setLocation( minGlueX, horizontalGlue.getY() );
|
||||
|
||||
// shrink and move components that are on the right side of the glue
|
||||
int x = horizontalGlue.getX() + horizontalGlue.getWidth();
|
||||
for( int i = glueIndex - 1; i >= 0; i-- ) {
|
||||
Component c = components[i];
|
||||
if( c.getX() + c.getWidth() < x ) {
|
||||
// move component and set width to zero
|
||||
c.setBounds( x, c.getY(), 0, c.getHeight() );
|
||||
} else {
|
||||
// move component and reduce size
|
||||
c.setBounds( x, c.getY(), c.getWidth() - (x - c.getX()), c.getHeight() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move components that are on the left side of the glue
|
||||
for( int i = glueIndex + 1; i < components.length; i++ ) {
|
||||
Component c = components[i];
|
||||
c.setLocation( c.getX() - offset, c.getY() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---- class TakeFocusAction ----------------------------------------------
|
||||
|
||||
/**
|
||||
* Activates the menu bar and shows mnemonics.
|
||||
* On Windows, the popup of the first menu is not shown.
|
||||
* On other platforms, the popup of the first menu is shown.
|
||||
*/
|
||||
private static class TakeFocus
|
||||
extends AbstractAction
|
||||
private static class TakeFocusAction
|
||||
extends FlatUIAction
|
||||
{
|
||||
TakeFocusAction( String name ) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed( ActionEvent e ) {
|
||||
JMenuBar menuBar = (JMenuBar) e.getSource();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user